From d7ad2c36d4d813f916dbde49efedf390d4390393 Mon Sep 17 00:00:00 2001 From: helixhorned Date: Sat, 13 Jul 2013 21:04:57 +0000 Subject: [PATCH] Lunatic: revamp sector changing/updating functions of sprites. git-svn-id: https://svn.eduke32.com/eduke32@3953 1a8010ca-5511-0410-912e-c29ae57300e0 --- polymer/eduke32/source/lunatic/control.lua | 15 ++++ .../eduke32/source/lunatic/defs_common.lua | 86 ++++++++++++++++--- polymer/eduke32/source/lunatic/lunacon.lua | 3 +- polymer/eduke32/source/lunatic/test.elua | 8 +- .../source/lunatic/test/helixspawner.lua | 15 +++- 5 files changed, 108 insertions(+), 19 deletions(-) diff --git a/polymer/eduke32/source/lunatic/control.lua b/polymer/eduke32/source/lunatic/control.lua index 54f17c7ee..460c2b907 100644 --- a/polymer/eduke32/source/lunatic/control.lua +++ b/polymer/eduke32/source/lunatic/control.lua @@ -1456,6 +1456,21 @@ function _movesprite(spritenum, x, y, z, cliptype) return ffiC.A_MoveSprite(spritenum, vel, cliptype) end +-- CON's 'setsprite' function on top of the Lunatic-provided ones. +-- (Lunatic's sprite setting functions have slightly different semantics.) +local updatesect = sprite.updatesect +function _setsprite(i, pos) + check_sprite_idx(i) + local spr = ffiC.sprite[i] + + -- First, unconditionally set the sprite's position. + spr:setpos(pos) + + -- Next, update the sector number, but if updatesector() returns -1, don't + -- change it. (This is exactly what sprite.updatesect() provides.) + updatesect(i) +end + -- NOTE: returns two args (in C version, hit sprite is a pointer input arg) local function A_CheckHitSprite(spr, angadd) local zoff = (spr:isenemy() and 42*256) or (ispic(spr.picnum, "APLAYER") and 39*256) or 0 diff --git a/polymer/eduke32/source/lunatic/defs_common.lua b/polymer/eduke32/source/lunatic/defs_common.lua index 64fed5c51..3d187ed00 100644 --- a/polymer/eduke32/source/lunatic/defs_common.lua +++ b/polymer/eduke32/source/lunatic/defs_common.lua @@ -665,6 +665,10 @@ end local tspritetype_mt = deep_copy(spritetype_mt) +-- Get the sprite index of a sprite reference. +-- This is relatively slow if the code doesn't get compiled, see related +-- discussion here: +-- http://www.freelists.org/post/luajit/FFI-versus-Lua-C-API-in-purely-interpreted-mode local function get_sprite_idx(spr) local i = ffi.cast(spritetype_ptr_ct, spr)-ffi.cast(spritetype_ptr_ct, ffiC.sprite) assert(not (i >= ffiC.MAXSPRITES+0ULL)) @@ -674,36 +678,65 @@ end ---=== Methods that are specific to sprites ===--- local l_updatesector -- fwd-decl +local l_changesect -- fwd-decl -function spritetype_mt.__index.setpos(spr, pos) -- setsprite() clone +-- The 'setpos' method is available for sprite and tsprite objects. +-- spr:setpos(pos [, newsect]), +-- where is taken to mean "set the sprite's sector number to "; +-- don't run update/search routines or anything like this. +function spritetype_mt.__index.setpos(spr, pos, newsect) spr.x, spr.y, spr.z = pos.x, pos.y, pos.z - local newsect = l_updatesector(spr, spr.sectnum) - - if (newsect >= 0 and spr.sectnum ~= newsect) then - ffiC.changespritesect(get_sprite_idx(spr), newsect) + if (newsect ~= nil) then + spr:changesect(newsect) end + return spr +end +-- spr:changesect(newsect) +-- changes the sector number of in an 'unforgiving' fashion ( of +-- -1 is error) +function spritetype_mt.__index.changesect(spr, newsect) + if (newsect ~= spr.sectnum) then + l_changesect(get_sprite_idx(spr), newsect) + end +end + +-- spr:updatesect(flags) +-- updates 's sectnum; if no matching sector is found, no-op +-- returns the updated sector number +function spritetype_mt.__index.updatesect(spr, flags) + local newsect = l_updatesector(spr, spr.sectnum, flags) + if (newsect ~= -1) then + spr:changesect(newsect) + end return newsect end ---=== Methods that are specific to tsprites ===--- -function tspritetype_mt.__index.set_sectnum(tspr, sectnum) - check_sector_idx(sectnum) - ffi.cast(spritetype_ptr_ct, tspr).sectnum = sectnum +-- This ought to be called 'set_sectnum', but 'changesect' is for consistency +-- with the sprite method. +function tspritetype_mt.__index.changesect(tspr, sectnum) + if (tspr.sectnum ~= sectnum) then + check_sector_idx(sectnum) + ffi.cast(spritetype_ptr_ct, tspr).sectnum = sectnum + end end --- TODO: flags (the same as sprite.UPDATE_FLAGS + "provide own sectnum", --- e.g. for example because it's already there from "hitscan"). -function tspritetype_mt.__index.setpos(tspr, pos) +function tspritetype_mt.__index.setpos(tspr, pos, newsect) tspr.x, tspr.y, tspr.z = pos.x, pos.y, pos.z - local newsect = l_updatesector(tspr, tspr.sectnum) - - if (newsect >= 0 and tspr.sectnum ~= newsect) then + if (newsect ~= nil) then tspr:set_sectnum(newsect) end + return tspr +end +function tspritetype_mt.__index.updatesect(tspr, flags) + local newsect = l_updatesector(tspr, tspr.sectnum, flags) + if (newsect ~= -1 and newsect ~= tspr.sectnum) then + tspr:set_sectnum(newsect) + end return newsect end @@ -816,6 +849,7 @@ static_members.sector.NEARTAG_FLAGS = conststruct static_members.sector.UPDATE_FLAGS = conststruct { BREADTH = 1, + Z = 2, } static_members.wall.CSTAT = conststruct @@ -874,6 +908,12 @@ function static_members.wall.dragto(wallnum, pos) ffiC.dragpoint(wallnum, pos.x, pos.y, 0) end +-- Functions changing the sector/status number of a sprite, without asking. + +-- Changes sector number of sprite with index to , +-- unconditionally and "unforgiving" (oob gives error). +-- is for CON compatibility and prevents error on *sprite not in the +-- game world* if true. function static_members.sprite.changesect(spritenum, sectnum, noerr) check_sprite_idx(spritenum) check_sector_idx(sectnum) @@ -882,6 +922,8 @@ function static_members.sprite.changesect(spritenum, sectnum, noerr) end end +l_changesect = static_members.sprite.changesect + function static_members.sprite.changestat(spritenum, statnum, noerr) -- TODO: see gameexec.c's CON_CHANGESPRITESTAT. check_sprite_idx(spritenum) @@ -893,6 +935,18 @@ function static_members.sprite.changestat(spritenum, statnum, noerr) end end +-- Update a sprite's sector number from its current position and sector number. +function static_members.sprite.updatesect(spritenum, flags) + check_sprite_idx(spritenum) + local spr = ffiC.sprite[spritenum] + + local newsect = l_updatesector(spr, spr.sectnum, flags) + if (newsect ~= -1 and newsect ~= spr.sectnum) then + l_changesect(spritenum, newsect) + end + return newsect +end + function GenStructMetatable(Structname, Boundname, StaticMembersTab) StaticMembersTab = StaticMembersTab or static_members[Structname] @@ -1118,6 +1172,10 @@ function updatesector(pos, sectnum, flags) ffiC.updatesector(pos.x, pos.y, us_retsect) elseif (flags==USF.BREADTH) then ffiC.updatesectorbreadth(pos.x, pos.y, us_retsect) + elseif (flags==USF.Z) then + -- Same as updatesectorz, but useful if we are called from + -- e.g. sprite.updatesect(). + ffiC.updatesectorz(pos.x, pos.y, pos.z, us_retsect) else error("invalid argument #3 (flags)", 2) end diff --git a/polymer/eduke32/source/lunatic/lunacon.lua b/polymer/eduke32/source/lunatic/lunacon.lua index 6e6a88015..a1469adec 100644 --- a/polymer/eduke32/source/lunatic/lunacon.lua +++ b/polymer/eduke32/source/lunatic/lunacon.lua @@ -301,6 +301,7 @@ local function new_initial_codetab() "local _div, _mod, _mulTR, _mulWR = _con._div, _con._mod, _con._mulTR, _con._mulWR", "local _band, _bor, _bxor = _bit.band, _bit.bor, _bit.bxor", "local _lsh, _rsh, _arsh = _bit.lshift, _bit.rshift, _bit.arshift", + "local _setsprite = _con._setsprite", -- * CON "states" (subroutines) and -- * Switch function table, indexed by global switch sequence number: @@ -2689,7 +2690,7 @@ local Cinner = { ssp = cmd(R,R) / handle.NYI, setsprite = cmd(R,R,R,R) - / "sprite[%1]:setpos(_IV(1,%2,%3,%4))", + / "_setsprite(%1,_IV(1,%2,%3,%4))", updatesector = cmd(R,R,W) / format("%%3=updatesector(_IV(1,%%1,%%2,0),%s)", SPS".sectnum"), updatesectorz = cmd(R,R,R,W) diff --git a/polymer/eduke32/source/lunatic/test.elua b/polymer/eduke32/source/lunatic/test.elua index 256f8da3c..8a55b25e9 100644 --- a/polymer/eduke32/source/lunatic/test.elua +++ b/polymer/eduke32/source/lunatic/test.elua @@ -371,6 +371,8 @@ gameevent{"LOADACTOR", function(i) if (i==614 and spr.picnum==930) then -- "police line" ribbon in E1L1 -- clear the hitag so that it doesn't spawn as FALLER from premap + -- Rather a HACK: relies on an implementation detail (A_Spawn() + -- "hard-wired" code). spr.hitag = 0 end end} @@ -386,7 +388,7 @@ gameactor local d = 20 -- NOTE: __add metamethod is called because of the RHS: local v = spr + xmath.vec3(r(-d,d), r(-d,d)) - spr:setpos(v) + spr:setpos(v):updatesect() -- Test vec3 constructor with cdata. local tempvec = xmath.vec3(player[0].pos) @@ -486,8 +488,7 @@ gameactor if (aimtspr) then aimtspr.pal = 2 aimtspr:set_picnum(555) - aimtspr:setpos(hit.pos) - aimtspr:set_sectnum(hit.sect) + aimtspr:setpos(hit.pos, hit.sect) end end end, @@ -550,6 +551,7 @@ gameevent -- in such a sector or an adjoining one.) -- XXX: We need a better place to do this, maybe an event in -- G_DisplayRest() where show2dsector[] is tweaked? + -- NOT YET OFFICIAL API. local show2dsector = sector.showbitmap for i=0,gv.numsectors-1 do if (sector[i].floorpicnum==815) then diff --git a/polymer/eduke32/source/lunatic/test/helixspawner.lua b/polymer/eduke32/source/lunatic/test/helixspawner.lua index 8ec62f616..a9a1e2817 100644 --- a/polymer/eduke32/source/lunatic/test/helixspawner.lua +++ b/polymer/eduke32/source/lunatic/test/helixspawner.lua @@ -53,12 +53,12 @@ gameactor func = function(aci) -- NOTE: this is prettier than calling it 'a', even if 'act' is used to -- denote an action in other places: + local spr = sprite[aci] local act = actor[aci] if (act:has_action(0)) then act:set_action(1) -- TODO: actor constructors, i.e. 'init' callbacks - local spr = sprite[aci] local decasec = math.floor((gv.gametic - nukeswStart[spr.owner])/(GTICSPERSEC*10)) local pal = COLOR[decasec+1] @@ -74,6 +74,19 @@ gameactor if (act:checkbump()) then con.killit() end + + -- Test spr:changesect() vs. sprite.changesect() + local sectnum = spr.sectnum + + for i=0,gv.numsectors-1 do + if (spr.pal ~= 2 and spr.pal ~= 7) then + sprite.changesect(aci, i) -- noticeably faster... + else + spr:changesect(i) -- ...than this + end + end + + sprite.changesect(aci, sectnum) end }