Lunatic: revamp sector changing/updating functions of sprites.

git-svn-id: https://svn.eduke32.com/eduke32@3953 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2013-07-13 21:04:57 +00:00
parent b9dfcc902d
commit d7ad2c36d4
5 changed files with 108 additions and 19 deletions

View file

@ -1456,6 +1456,21 @@ function _movesprite(spritenum, x, y, z, cliptype)
return ffiC.A_MoveSprite(spritenum, vel, cliptype) return ffiC.A_MoveSprite(spritenum, vel, cliptype)
end 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) -- NOTE: returns two args (in C version, hit sprite is a pointer input arg)
local function A_CheckHitSprite(spr, angadd) local function A_CheckHitSprite(spr, angadd)
local zoff = (spr:isenemy() and 42*256) or (ispic(spr.picnum, "APLAYER") and 39*256) or 0 local zoff = (spr:isenemy() and 42*256) or (ispic(spr.picnum, "APLAYER") and 39*256) or 0

View file

@ -665,6 +665,10 @@ end
local tspritetype_mt = deep_copy(spritetype_mt) 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 function get_sprite_idx(spr)
local i = ffi.cast(spritetype_ptr_ct, spr)-ffi.cast(spritetype_ptr_ct, ffiC.sprite) local i = ffi.cast(spritetype_ptr_ct, spr)-ffi.cast(spritetype_ptr_ct, ffiC.sprite)
assert(not (i >= ffiC.MAXSPRITES+0ULL)) assert(not (i >= ffiC.MAXSPRITES+0ULL))
@ -674,36 +678,65 @@ end
---=== Methods that are specific to sprites ===--- ---=== Methods that are specific to sprites ===---
local l_updatesector -- fwd-decl 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 <newsect> is taken to mean "set the sprite's sector number to <newsect>";
-- 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 spr.x, spr.y, spr.z = pos.x, pos.y, pos.z
local newsect = l_updatesector(spr, spr.sectnum) if (newsect ~= nil) then
spr:changesect(newsect)
if (newsect >= 0 and spr.sectnum ~= newsect) then
ffiC.changespritesect(get_sprite_idx(spr), newsect)
end end
return spr
end
-- spr:changesect(newsect)
-- changes the sector number of <spr> in an 'unforgiving' fashion (<newsect> 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 <spr>'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 return newsect
end end
---=== Methods that are specific to tsprites ===--- ---=== Methods that are specific to tsprites ===---
function tspritetype_mt.__index.set_sectnum(tspr, sectnum) -- This ought to be called 'set_sectnum', but 'changesect' is for consistency
check_sector_idx(sectnum) -- with the sprite method.
ffi.cast(spritetype_ptr_ct, tspr).sectnum = sectnum 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 end
-- TODO: flags (the same as sprite.UPDATE_FLAGS + "provide own sectnum", function tspritetype_mt.__index.setpos(tspr, pos, newsect)
-- e.g. for example because it's already there from "hitscan").
function tspritetype_mt.__index.setpos(tspr, pos)
tspr.x, tspr.y, tspr.z = pos.x, pos.y, pos.z tspr.x, tspr.y, tspr.z = pos.x, pos.y, pos.z
local newsect = l_updatesector(tspr, tspr.sectnum) if (newsect ~= nil) then
if (newsect >= 0 and tspr.sectnum ~= newsect) then
tspr:set_sectnum(newsect) tspr:set_sectnum(newsect)
end 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 return newsect
end end
@ -816,6 +849,7 @@ static_members.sector.NEARTAG_FLAGS = conststruct
static_members.sector.UPDATE_FLAGS = conststruct static_members.sector.UPDATE_FLAGS = conststruct
{ {
BREADTH = 1, BREADTH = 1,
Z = 2,
} }
static_members.wall.CSTAT = conststruct static_members.wall.CSTAT = conststruct
@ -874,6 +908,12 @@ function static_members.wall.dragto(wallnum, pos)
ffiC.dragpoint(wallnum, pos.x, pos.y, 0) ffiC.dragpoint(wallnum, pos.x, pos.y, 0)
end end
-- Functions changing the sector/status number of a sprite, without asking.
-- Changes sector number of sprite with index <spritenum> to <sectnum>,
-- unconditionally and "unforgiving" (oob <sectnum> gives error).
-- <noerr> is for CON compatibility and prevents error on *sprite not in the
-- game world* if true.
function static_members.sprite.changesect(spritenum, sectnum, noerr) function static_members.sprite.changesect(spritenum, sectnum, noerr)
check_sprite_idx(spritenum) check_sprite_idx(spritenum)
check_sector_idx(sectnum) check_sector_idx(sectnum)
@ -882,6 +922,8 @@ function static_members.sprite.changesect(spritenum, sectnum, noerr)
end end
end end
l_changesect = static_members.sprite.changesect
function static_members.sprite.changestat(spritenum, statnum, noerr) function static_members.sprite.changestat(spritenum, statnum, noerr)
-- TODO: see gameexec.c's CON_CHANGESPRITESTAT. -- TODO: see gameexec.c's CON_CHANGESPRITESTAT.
check_sprite_idx(spritenum) check_sprite_idx(spritenum)
@ -893,6 +935,18 @@ function static_members.sprite.changestat(spritenum, statnum, noerr)
end end
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) function GenStructMetatable(Structname, Boundname, StaticMembersTab)
StaticMembersTab = StaticMembersTab or static_members[Structname] StaticMembersTab = StaticMembersTab or static_members[Structname]
@ -1118,6 +1172,10 @@ function updatesector(pos, sectnum, flags)
ffiC.updatesector(pos.x, pos.y, us_retsect) ffiC.updatesector(pos.x, pos.y, us_retsect)
elseif (flags==USF.BREADTH) then elseif (flags==USF.BREADTH) then
ffiC.updatesectorbreadth(pos.x, pos.y, us_retsect) 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 else
error("invalid argument #3 (flags)", 2) error("invalid argument #3 (flags)", 2)
end end

View file

@ -301,6 +301,7 @@ local function new_initial_codetab()
"local _div, _mod, _mulTR, _mulWR = _con._div, _con._mod, _con._mulTR, _con._mulWR", "local _div, _mod, _mulTR, _mulWR = _con._div, _con._mod, _con._mulTR, _con._mulWR",
"local _band, _bor, _bxor = _bit.band, _bit.bor, _bit.bxor", "local _band, _bor, _bxor = _bit.band, _bit.bor, _bit.bxor",
"local _lsh, _rsh, _arsh = _bit.lshift, _bit.rshift, _bit.arshift", "local _lsh, _rsh, _arsh = _bit.lshift, _bit.rshift, _bit.arshift",
"local _setsprite = _con._setsprite",
-- * CON "states" (subroutines) and -- * CON "states" (subroutines) and
-- * Switch function table, indexed by global switch sequence number: -- * Switch function table, indexed by global switch sequence number:
@ -2689,7 +2690,7 @@ local Cinner = {
ssp = cmd(R,R) ssp = cmd(R,R)
/ handle.NYI, / handle.NYI,
setsprite = cmd(R,R,R,R) 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) updatesector = cmd(R,R,W)
/ format("%%3=updatesector(_IV(1,%%1,%%2,0),%s)", SPS".sectnum"), / format("%%3=updatesector(_IV(1,%%1,%%2,0),%s)", SPS".sectnum"),
updatesectorz = cmd(R,R,R,W) updatesectorz = cmd(R,R,R,W)

View file

@ -371,6 +371,8 @@ gameevent{"LOADACTOR", function(i)
if (i==614 and spr.picnum==930) then if (i==614 and spr.picnum==930) then
-- "police line" ribbon in E1L1 -- "police line" ribbon in E1L1
-- clear the hitag so that it doesn't spawn as FALLER from premap -- 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 spr.hitag = 0
end end
end} end}
@ -386,7 +388,7 @@ gameactor
local d = 20 local d = 20
-- NOTE: __add metamethod is called because of the RHS: -- NOTE: __add metamethod is called because of the RHS:
local v = spr + xmath.vec3(r(-d,d), r(-d,d)) local v = spr + xmath.vec3(r(-d,d), r(-d,d))
spr:setpos(v) spr:setpos(v):updatesect()
-- Test vec3 constructor with cdata. -- Test vec3 constructor with cdata.
local tempvec = xmath.vec3(player[0].pos) local tempvec = xmath.vec3(player[0].pos)
@ -486,8 +488,7 @@ gameactor
if (aimtspr) then if (aimtspr) then
aimtspr.pal = 2 aimtspr.pal = 2
aimtspr:set_picnum(555) aimtspr:set_picnum(555)
aimtspr:setpos(hit.pos) aimtspr:setpos(hit.pos, hit.sect)
aimtspr:set_sectnum(hit.sect)
end end
end end
end, end,
@ -550,6 +551,7 @@ gameevent
-- in such a sector or an adjoining one.) -- in such a sector or an adjoining one.)
-- XXX: We need a better place to do this, maybe an event in -- XXX: We need a better place to do this, maybe an event in
-- G_DisplayRest() where show2dsector[] is tweaked? -- G_DisplayRest() where show2dsector[] is tweaked?
-- NOT YET OFFICIAL API.
local show2dsector = sector.showbitmap local show2dsector = sector.showbitmap
for i=0,gv.numsectors-1 do for i=0,gv.numsectors-1 do
if (sector[i].floorpicnum==815) then if (sector[i].floorpicnum==815) then

View file

@ -53,12 +53,12 @@ gameactor
func = function(aci) func = function(aci)
-- NOTE: this is prettier than calling it 'a', even if 'act' is used to -- NOTE: this is prettier than calling it 'a', even if 'act' is used to
-- denote an action in other places: -- denote an action in other places:
local spr = sprite[aci]
local act = actor[aci] local act = actor[aci]
if (act:has_action(0)) then if (act:has_action(0)) then
act:set_action(1) -- TODO: actor constructors, i.e. 'init' callbacks 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 decasec = math.floor((gv.gametic - nukeswStart[spr.owner])/(GTICSPERSEC*10))
local pal = COLOR[decasec+1] local pal = COLOR[decasec+1]
@ -74,6 +74,19 @@ gameactor
if (act:checkbump()) then if (act:checkbump()) then
con.killit() con.killit()
end 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 end
} }