Lunatic: make gameactor and gameevent be "table-called" functions.

git-svn-id: https://svn.eduke32.com/eduke32@3873 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2013-06-12 17:49:53 +00:00
parent bbcf6d6353
commit f6065e227a
5 changed files with 316 additions and 255 deletions

View file

@ -795,9 +795,11 @@ do
-- Callback function chaining control flags. -- Callback function chaining control flags.
our_SFLAG.replace_hard = 0x08000000 -- Replace actor code and flags our_SFLAG.replace_hard = 0x08000000 -- Replace actor code and flags
our_SFLAG.replace_soft = 0x10000000 -- Replace actor code, bitwise OR flags our_SFLAG.replace_soft = 0x10000000 -- Replace actor code, bitwise OR flags
our_SFLAG.replace = 0x08000000 -- Should only be used for gameevent
our_SFLAG.chain_beg = 0x20000000 our_SFLAG.chain_beg = 0x20000000
our_SFLAG.chain_end = 0x40000000 our_SFLAG.chain_end = 0x40000000
our_SFLAG._CHAIN_MASK = 0x78000000 our_SFLAG._CHAIN_MASK_ACTOR = 0x78000000
our_SFLAG._CHAIN_MASK_EVENT = 0x68000000
-- XXX: CON doesn't export BADGUYSTAYPUT or ROTFIXED SFLAGs, but they are considered -- XXX: CON doesn't export BADGUYSTAYPUT or ROTFIXED SFLAGs, but they are considered
-- external for Lunatic. -- external for Lunatic.
@ -853,7 +855,8 @@ actor = setmtonce({}, defs_c.GenStructMetatable("actor", "MAXSPRITES", actor_sta
-- Some bitwise NOTs of various actor flag masks. -- Some bitwise NOTs of various actor flag masks.
local BNOT = { local BNOT = {
USER_MASK = bit.bnot(actor.FLAGS.USER_MASK), USER_MASK = bit.bnot(actor.FLAGS.USER_MASK),
CHAIN_MASK = bit.bnot(actor.FLAGS._CHAIN_MASK), CHAIN_MASK_ACTOR = bit.bnot(actor.FLAGS._CHAIN_MASK_ACTOR),
CHAIN_MASK_EVENT = bit.bnot(actor.FLAGS._CHAIN_MASK_EVENT),
} }
local projectile = defs_c.creategtab(ffiC.ProjectileData, ffiC.MAXTILES, "projectile[]") local projectile = defs_c.creategtab(ffiC.ProjectileData, ffiC.MAXTILES, "projectile[]")
@ -1617,6 +1620,15 @@ local function chain_func3(func1, func2)
end end
end end
-- Determines the last numeric index of a table using *ipairs*.
local function ourmaxn(tab)
local maxi = 0
for i in ipairs(tab) do
maxi = math.max(i, maxi)
end
return maxi
end
-- Running for the very first time? -- Running for the very first time?
local g_firstRun = (ffiC.g_elCONSize == 0) local g_firstRun = (ffiC.g_elCONSize == 0)
@ -1624,10 +1636,17 @@ local g_firstRun = (ffiC.g_elCONSize == 0)
local actor_funcs = {} local actor_funcs = {}
local gameactor_internal = gameactor_internal -- included in lunatic.c local gameactor_internal = gameactor_internal -- included in lunatic.c
-- gameactor(tilenum [, flags [, strength [, act [, mov [, movflags]]]]], actor_func) -- gameactor{tilenum [, flags [, strength [, action [, move [, movflags]]]]], func}
local function our_gameactor(tilenum, ...) -- Every arg may be positional OR key=val (with the name indicated above as key),
-- but not both.
local function our_gameactor(args)
bcheck.top_level("gameactor") bcheck.top_level("gameactor")
if (type(args)~="table") then
error("invalid gameactor call: must be passed a table")
end
local tilenum = args[1]
if (type(tilenum) ~= "number") then if (type(tilenum) ~= "number") then
error("invalid argument #1 to gameactor: must be a number", 2) error("invalid argument #1 to gameactor: must be a number", 2)
end end
@ -1635,28 +1654,24 @@ local function our_gameactor(tilenum, ...)
error("invalid argument #1 to gameactor: must be a tile number [0..gv.MAXTILES-1]", 2) error("invalid argument #1 to gameactor: must be a tile number [0..gv.MAXTILES-1]", 2)
end end
local args = {...} local lastargi = ourmaxn(args)
-- Number of varargs; args may have nil's in the middle! local func = args[lastargi]
local numargs = select('#', ...) if (type(func) ~= "function") then
func = args.func
if (numargs == 0) then lastargi = 1/0
error("invalid call to gameactor: must have at least two arguments (tilenum, func)", 2)
end end
if (numargs >= 7) then -- sic, because tilenum isn't counted! if (type(func) ~= "function") then
error("invalid call to gameactor: must have at most 7 arguments", 2) error("invalid gameactor call: must provide a function with last numeric arg or .func", 2)
end
if (type(args[numargs]) ~= "function") then
error("invalid last argument to gameactor: must be a function", 2)
end end
local flags = (numargs > 1) and args[1] or 0 local flags = (lastargi > 2 and args[2]) or args.flags or 0
if (type(flags) ~= "number") then if (type(flags) ~= "number") then
error("invalid 'flags' argument to gameactor: must be a number", 2) error("invalid 'flags' argument (#2) to gameactor: must be a number", 2)
end end
local AF = actor.FLAGS local AF = actor.FLAGS
local chainflags = bit.band(flags, AF._CHAIN_MASK) local chainflags = bit.band(flags, AF._CHAIN_MASK_ACTOR)
flags = bit.band(flags, BNOT.CHAIN_MASK) flags = bit.band(flags, BNOT.CHAIN_MASK_ACTOR)
-- Default chaining behavior: don't, replace the old actor instead, but -- Default chaining behavior: don't, replace the old actor instead, but
-- unlike CON, also replace its flags. (CON ORs them instead.) -- unlike CON, also replace its flags. (CON ORs them instead.)
@ -1673,43 +1688,43 @@ local function our_gameactor(tilenum, ...)
local flags_rbits = bit.band(flags, BNOT.USER_MASK) local flags_rbits = bit.band(flags, BNOT.USER_MASK)
if (flags_rbits ~= 0) then if (flags_rbits ~= 0) then
error("invalid 'flags' argument to gameactor: must not set reserved bits (0x" error("invalid 'flags' argument (#2) to gameactor: must not set reserved bits (0x"
..(bit.tohex(flags_rbits))..")", 2) ..(bit.tohex(flags_rbits))..")", 2)
end end
local strength = (numargs > 2) and args[2] or (replacep and 0 or nil) local strength = ((lastargi > 3 and args[3]) or args.strength) or (replacep and 0 or nil)
if (replacep or strength~=nil) then if (replacep or strength~=nil) then
if (type(strength) ~= "number") then if (type(strength) ~= "number") then
error("invalid 'strength' argument to gameactor: must be a number", 2) error("invalid 'strength' argument (#3) to gameactor: must be a number", 2)
end end
end end
-- TODO: literal number action other than 0? -- TODO: literal number action other than 0?
local act = (numargs > 3) and args[3] or (replacep and "NO" or nil) local act = ((lastargi > 4 and args[4]) or args.action) or (replacep and "NO" or nil)
if (replacep or act ~= nil) then if (replacep or act ~= nil) then
if (type(act)=="string") then if (type(act)=="string") then
act = AC[act] act = AC[act]
end end
if (not ffi.istype(con_action_ct, act)) then if (not ffi.istype(con_action_ct, act)) then
error("invalid 'act' argument to gameactor: must be a string or action", 2) error("invalid 'action' argument (#4) to gameactor: must be a string or action", 2)
end end
end end
-- TODO: literal number move other than 0? -- TODO: literal number move other than 0?
local mov = (numargs > 4) and args[4] or (replacep and "NO" or nil) local mov = ((lastargi > 5 and args[5]) or args.move) or (replacep and "NO" or nil)
if (replacep or mov ~= nil) then if (replacep or mov ~= nil) then
if (type(mov)=="string") then if (type(mov)=="string") then
mov = MV[mov] mov = MV[mov]
end end
if (not ffi.istype(con_move_ct, mov)) then if (not ffi.istype(con_move_ct, mov)) then
error("invalid 'mov' argument to gameactor: must be a string or move", 2) error("invalid 'move' argument (#5) to gameactor: must be a string or move", 2)
end end
end end
local movflags = (numargs > 5) and args[5] or (replacep and 0 or nil) local movflags = ((lastargi > 6 and args[6]) or args.movflags) or (replacep and 0 or nil)
if (replacep or movflags ~= nil) then if (replacep or movflags ~= nil) then
if (type(movflags) ~= "number") then if (type(movflags) ~= "number") then
error("invalid 'movflags' argument to gameactor: must be a number", 2) error("invalid 'movflags' argument (#6) to gameactor: must be a number", 2)
end end
end end
@ -1726,7 +1741,6 @@ local function our_gameactor(tilenum, ...)
tile.flags = (chainflags==AF.replace_hard) and flags or bit.bor(tile.flags, flags) tile.flags = (chainflags==AF.replace_hard) and flags or bit.bor(tile.flags, flags)
end end
local func = args[numargs]
local newfunc = replacep and func local newfunc = replacep and func
or (chainflags==AF.chain_beg) and chain_func3(func, actor_funcs[tilenum]) or (chainflags==AF.chain_beg) and chain_func3(func, actor_funcs[tilenum])
or (chainflags==AF.chain_end) and chain_func3(actor_funcs[tilenum], func) or (chainflags==AF.chain_end) and chain_func3(actor_funcs[tilenum], func)
@ -1740,10 +1754,16 @@ end
local event_funcs = {} local event_funcs = {}
local gameevent_internal = gameevent_internal -- included in lunatic.c local gameevent_internal = gameevent_internal -- included in lunatic.c
-- gameevent(<event idx or string> [, flags], <event function>) -- gameevent{<event idx or string> [, flags], <event function>}
local function our_gameevent(event, flags, func) local function our_gameevent(args)
bcheck.top_level("gameevent") bcheck.top_level("gameevent")
if (type(args)~="table") then
error("invalid gameevent call: must be passed a table")
end
local event = args[1]
if (type(event) == "string") then if (type(event) == "string") then
if (event:sub(1,6) ~= "EVENT_") then if (event:sub(1,6) ~= "EVENT_") then
event = "EVENT_"..event event = "EVENT_"..event
@ -1763,27 +1783,28 @@ local function our_gameevent(event, flags, func)
local AF = actor.FLAGS local AF = actor.FLAGS
-- Event chaining: in Lunatic, chaining at the *end* is the default. -- Kind of CODEDUP from our_gameactor.
if (func==nil) then local lastargi = ourmaxn(args)
func = flags local func = args[lastargi]
flags = AF.chain_end
else
if (type(flags) ~= "number") then
error("invalid 'flags' argument to gameevent: must be a number", 2)
end
if (bit.band(flags, BNOT.CHAIN_MASK) ~= 0) then
error("invalid 'flags' argument to gameevent: must not set reserved bits", 2)
end
if (flags == 0) then
flags = AF.chain_end
end
end
if (type(func) ~= "function") then if (type(func) ~= "function") then
error("invalid last argument to gameevent: must be a function", 2) func = args.func
lastargi = 1/0
end
if (type(func) ~= "function") then
error("invalid gameevent call: must provide a function with last numeric arg or .func", 2)
end end
local newfunc = replacep and func -- Event chaining: in Lunatic, chaining at the *end* is the default.
local flags = (lastargi > 2 and args[2]) or args.flags or AF.chain_end
if (type(flags) ~= "number") then
error("invalid 'flags' argument (#2) to gameevent: must be a number", 2)
end
if (bit.band(flags, BNOT.CHAIN_MASK_EVENT) ~= 0) then
error("invalid 'flags' argument to gameevent: must not set reserved bits", 2)
end
local newfunc = (flags==AF.replace) and func
or (flags==AF.chain_beg) and chain_func3(func, event_funcs[event]) or (flags==AF.chain_beg) and chain_func3(func, event_funcs[event])
or (flags==AF.chain_end) and chain_func3(event_funcs[event], func) or (flags==AF.chain_end) and chain_func3(event_funcs[event], func)
or assert(false) or assert(false)

View file

@ -418,9 +418,9 @@ function on.actor_end(pos, usertype, tsamm, codetab)
str = str .. movflags.."," str = str .. movflags..","
end end
paddcodef(pos, "gameactor(%d,%sfunction(_aci, _pli, _dist)", tilenum, str) paddcodef(pos, "gameactor{%d,%sfunction(_aci, _pli, _dist)", tilenum, str)
addcode(get_cache_sap_code()) addcode(get_cache_sap_code())
add_code_and_end(codetab, "end)") add_code_and_end(codetab, "end}")
if (g_code.actor[tilenum] ~= nil) then if (g_code.actor[tilenum] ~= nil) then
pwarnprintf(pos, "redefined actor %d", tilenum) pwarnprintf(pos, "redefined actor %d", tilenum)
@ -476,22 +476,22 @@ end
function on.event_end(pos, eventidx, codetab) function on.event_end(pos, eventidx, codetab)
assert(type(codetab)=="table") assert(type(codetab)=="table")
-- 0x20000000: actor.FLAGS.chain_beg -- 0x20000000: actor.FLAGS.chain_beg
paddcodef(pos, "gameevent(%d,0x20000000,function (_aci, _pli, _dist)", eventidx) paddcodef(pos, "gameevent{%d,0x20000000,function (_aci, _pli, _dist)", eventidx)
addcode(get_cache_sap_code()) addcode(get_cache_sap_code())
addcode(codetab) addcode(codetab)
addcode("end)") addcode("end}")
g_code.event[eventidx] = codetab g_code.event[eventidx] = codetab
end end
function on.eventloadactor_end(pos, tilenum, codetab) function on.eventloadactor_end(pos, tilenum, codetab)
-- Translate eventloadactor into a chained EVENT_LOADACTOR block -- Translate eventloadactor into a chained EVENT_LOADACTOR block
paddcodef(pos, "gameevent('LOADACTOR', function (_aci, _pli, _dist)") paddcodef(pos, "gameevent{'LOADACTOR', function (_aci, _pli, _dist)")
addcode(get_cache_sap_code()) addcode(get_cache_sap_code())
addcodef("if (%s==%d) then", SPS".picnum", tilenum) addcodef("if (%s==%d) then", SPS".picnum", tilenum)
addcode(codetab) addcode(codetab)
addcode("end") addcode("end")
addcode("end)") addcode("end}")
if (g_code.loadactor[tilenum] ~= nil and g_warn["chained-loadactor"]) then if (g_code.loadactor[tilenum] ~= nil and g_warn["chained-loadactor"]) then
-- NOTE: C-CON redefines loadactor code if encountered multiple times. -- NOTE: C-CON redefines loadactor code if encountered multiple times.

View file

@ -178,7 +178,7 @@ checkfail('local i = actor[0].t_data[15]', "has no member named 't_data'")
-- no pointer arithmetic! -- no pointer arithmetic!
checkfail('local spr = sprite[0]; local x=spr+1', "attempt to perform arithmetic on") checkfail('local spr = sprite[0]; local x=spr+1', "attempt to perform arithmetic on")
checkfail('gameactor(1680, 0)', "invalid last argument to gameactor: must be a function") checkfail('gameactor{1680, 0}', "must provide a function with last numeric arg or .func")
checkfail("do local bt=require'test.test_bitar'; bt.QWE=1; end", "modifying module table forbidden") checkfail("do local bt=require'test.test_bitar'; bt.QWE=1; end", "modifying module table forbidden")
-- the cdata returned by player[] can't be made into a pointer! -- the cdata returned by player[] can't be made into a pointer!
@ -195,165 +195,183 @@ player[0].curr_weapon = 1
printf('ceilingbunch of sector 0: %d', sector[0].ceilingbunch) printf('ceilingbunch of sector 0: %d', sector[0].ceilingbunch)
gameevent(gv.EVENT_JUMP, gameevent{gv.EVENT_JUMP,
function(actori, playeri, dist) function(actori, playeri, dist)
printf("jump i=%d p=%d d=%d", actori, playeri, dist) printf("jump i=%d p=%d d=%d", actori, playeri, dist)
error("greetings from EVENT_JUMP") error("greetings from EVENT_JUMP")
end end
) }
gameevent("PROCESSINPUT", gameevent
-- Input test. {
-- NOTE: I don't think that exposing g_player[].sync (aka "input") is a good idea... "PROCESSINPUT",
function(actori, playeri, dist)
local IB = player._INPUT_BITS -- Input test.
local input = player[playeri]._input -- NOTE: I don't think that exposing g_player[].sync (aka "input") is a good idea...
if (bit.band(input.bits, IB.JUMP) ~= 0) then func = function(actori, playeri, dist)
print("JUMPED") local IB = player._INPUT_BITS
-- ... because for example this doesn't work local input = player[playeri]._input
-- (P_HandleSharedKeys, where the JETPACK bit is tested, runs if (bit.band(input.bits, IB.JUMP) ~= 0) then
-- before P_ProcessInput): print("JUMPED")
input.bits = bit.bor(input.bits, IB.JETPACK) -- ... because for example this doesn't work
end -- (P_HandleSharedKeys, where the JETPACK bit is tested, runs
end -- before P_ProcessInput):
) input.bits = bit.bor(input.bits, IB.JETPACK)
end
end
}
-- test event chaining -- test event chaining
gameevent("JUMP", actor.FLAGS.chain_beg, gameevent
function(actori, playeri, dist) {
local ps = player[playeri] "JUMP",
print("\n--- I'm first!")
-- DBG_.oom()
ps.weapon.PISTOL.shoots = 2605 -- RPG
ps.weapon[gv.PISTOL_WEAPON].firesound = 351 -- thunder
-- XXX: provide either named constants or methods? flags = actor.FLAGS.chain_beg,
ps.pipebombControl = 2
ps.tripbombControl = 2
-- Test of INTERNAL member _pals. function(actori, playeri, dist)
-- NOTE: setting colors partially is bad! E.g. after an item is local ps = player[playeri]
-- picked up, col[0] and col[1] remain and tint everything greenish. print("\n--- I'm first!")
ps._pals[2] = 20 -- DBG_.oom()
ps._pals.f = 30 ps.weapon.PISTOL.shoots = 2605 -- RPG
end ps.weapon[gv.PISTOL_WEAPON].firesound = 351 -- thunder
)
gameevent(gv.EVENT_ENTERLEVEL, -- XXX: provide either named constants or methods?
function() ps.pipebombControl = 2
if (gv._DEBUG_LUNATIC) then ps.tripbombControl = 2
DBG_.testmembread()
end
-- NOTE: times are for helixhorned (Core2Duo 3GHz) -- Test of INTERNAL member _pals.
local i -- NOTE: setting colors partially is bad! E.g. after an item is
local N = 1e6 -- picked up, col[0] and col[1] remain and tint everything greenish.
local t = gv.gethitickms() ps._pals[2] = 20
ps._pals.f = 30
end
}
for i=3,N do gameevent
gv.gethitickms() {
end gv.EVENT_ENTERLEVEL,
t = gv.gethitickms()-t function()
if (gv._DEBUG_LUNATIC) then
DBG_.testmembread()
end
-- x86_64: 35ns/call, x86: 280 ns/call -- NOTE: times are for helixhorned (Core2Duo 3GHz)
-- Windows 32-bit: about 1 us/call? local i
printf("%d gethitickms() calls took %.03f ms (%.03f us/call)", local N = 1e6
N, t, (t*1000)/N) local t = gv.gethitickms()
local sum=0 for i=3,N do
t = gv.gethitickms() gv.gethitickms()
for i=1,N do sum = sum+gv.ksqrt(i) end end
t = gv.gethitickms()-t
-- x86_64: 14ns/call
printf("%d ksqrt() calls took %.03f ms (%.03f us/call) [sum=%f]",
N, t, (t*1000)/N, sum)
sum=0 t = gv.gethitickms()-t
t = gv.gethitickms()
for i=1,N do sum = sum+math.sqrt(i) end
t = gv.gethitickms()-t
-- x86_64: 7ns/call
printf("%d math.sqrt() calls took %.03f ms (%.03f us/call) [sum=%f]",
N, t, (t*1000)/N, sum)
printf("sqrt(0xffffffff) = %f(ksqrt) %f(math.sqrt)", -- x86_64: 35ns/call, x86: 280 ns/call
gv.ksqrt(0xffffffff), math.sqrt(0xffffffff)) -- Windows 32-bit: about 1 us/call?
printf("%d gethitickms() calls took %.03f ms (%.03f us/call)",
N, t, (t*1000)/N)
local pl = player[0] local sum=0
-- MAX < current is "allowed" t = gv.gethitickms()
pl.max_ammo_amount[gv.RPG_WEAPON] = 17 for i=1,N do sum = sum+gv.ksqrt(i) end
pl:give_weapon(gv.RPG_WEAPON) t = gv.gethitickms()-t
pl.ammo_amount[gv.RPG_WEAPON] = 54 -- x86_64: 14ns/call
printf("%d ksqrt() calls took %.03f ms (%.03f us/call) [sum=%f]",
N, t, (t*1000)/N, sum)
pl:give_weapon(gv.SHRINKER_WEAPON) sum=0
-- This looks much prettier: t = gv.gethitickms()
pl.ammo_amount.SHRINKER = 2 for i=1,N do sum = sum+math.sqrt(i) end
t = gv.gethitickms()-t
-- x86_64: 7ns/call
printf("%d math.sqrt() calls took %.03f ms (%.03f us/call) [sum=%f]",
N, t, (t*1000)/N, sum)
-- MORTER2 from test/weaponvars.con printf("sqrt(0xffffffff) = %f(ksqrt) %f(math.sqrt)",
player[0].weapon.SHOTGUN.shoots = 1653 gv.ksqrt(0xffffffff), math.sqrt(0xffffffff))
local proj = projectile[1653]
proj.drop = 0
proj:set_trail(2329) -- SMALLSMOKE
t = gv.gethitickms() local pl = player[0]
local N=1 -- MAX < current is "allowed"
for n=1,N do pl.max_ammo_amount[gv.RPG_WEAPON] = 17
for i=0,gv.MAXSPRITES-1 do pl:give_weapon(gv.RPG_WEAPON)
sprite[i].filler = 1 pl.ammo_amount[gv.RPG_WEAPON] = 54
end
for i=gv.MAXSPRITES-1,0,-1 do
sprite[i].shade = 1
end
for i=0,gv.MAXSPRITES-1 do
sprite[i].xoffset = 0
end
for i=gv.MAXSPRITES-1,0,-1 do
sprite[i].yoffset = 1
end
end
t = gv.gethitickms()-t
printf("%d x four 0..MAXSPRITES-1 iterations took %.03f us per outer iteration", N, (1000*t)/N)
-- Results on x86:
-- N=1: 480-1000 us (too large variance)
-- N=10: 190-210 us * 10 = 1.9-2.1 ms
-- N=100: about 160 us * 100 = about 16 ms
-- Make the DUKECAR in E1L1 into a zombie actor (temporarily) pl:give_weapon(gv.SHRINKER_WEAPON)
if (sprite[24].picnum==2491) then -- This looks much prettier:
sprite.changestat(24, actor.STAT.ZOMBIEACTOR) pl.ammo_amount.SHRINKER = 2
end
checkfail("gameevent('GAME', function() print('qwe') end)", -- MORTER2 from test/weaponvars.con
"must be called from top level") player[0].weapon.SHOTGUN.shoots = 1653
end local proj = projectile[1653]
) proj.drop = 0
proj:set_trail(2329) -- SMALLSMOKE
t = gv.gethitickms()
local N=1
for n=1,N do
for i=0,gv.MAXSPRITES-1 do
sprite[i].filler = 1
end
for i=gv.MAXSPRITES-1,0,-1 do
sprite[i].shade = 1
end
for i=0,gv.MAXSPRITES-1 do
sprite[i].xoffset = 0
end
for i=gv.MAXSPRITES-1,0,-1 do
sprite[i].yoffset = 1
end
end
t = gv.gethitickms()-t
printf("%d x four 0..MAXSPRITES-1 iterations took %.03f us per outer iteration", N, (1000*t)/N)
-- Results on x86:
-- N=1: 480-1000 us (too large variance)
-- N=10: 190-210 us * 10 = 1.9-2.1 ms
-- N=100: about 160 us * 100 = about 16 ms
-- Make the DUKECAR in E1L1 into a zombie actor (temporarily)
if (sprite[24].picnum==2491) then
sprite.changestat(24, actor.STAT.ZOMBIEACTOR)
end
checkfail("gameevent('GAME', function() print('qwe') end)",
"must be called from top level")
end
}
local geom = require "geom" local geom = require "geom"
gameevent("LOADACTOR", function(i) gameevent{"LOADACTOR", function(i)
local spr = sprite[i] local spr = sprite[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
spr.hitag = 0 spr.hitag = 0
end end
end) end}
gameactor(930, nil, 1, function(i) -- "police line" ribbon gameactor
local spr = sprite[i] {
local r = math.random -- "police line" ribbon
local d = 20 930, nil, 1,
-- NOTE: __add metamethod is called because of the RHS:
local v = spr + geom.vec3(r(-d,d), r(-d,d)) func = function(i)
spr:setpos(v) local spr = sprite[i]
end) local r = math.random
local d = 20
-- NOTE: __add metamethod is called because of the RHS:
local v = spr + geom.vec3(r(-d,d), r(-d,d))
spr:setpos(v)
end
}
local stat = require("stat") local stat = require("stat")
local hs = stat.new() local hs = stat.new()
local con = require("con") local con = require("con")
local AC, MV = con.AC, con.MV local AC, MV = con.AC, con.MV
con.action("TROOPSTAND",0,1,5,1,1) con.action("TROOPSTAND",0,1,5,1,1)
con.action("TROOPFLINTCH", 50, 1, 1, 1, 6) con.action("TROOPFLINTCH", 50, 1, 1, 1, 6)
con.move("SHRUNKVELS", 32) con.move("SHRUNKVELS", 32)
@ -366,107 +384,129 @@ con.ai("AITEMP", "TROOPFLINTCH", "SHRUNKVELS", 0)
local TROOPSTRENGTH = 30 local TROOPSTRENGTH = 30
local D = require("CON.DEFS")
local AF = actor.FLAGS local AF = actor.FLAGS
local CS = sprite.CSTAT local CS = sprite.CSTAT
-- Also test actor code chaining: strength is doubled. -- Also test actor code chaining: strength is doubled.
gameactor(1680, AF.chain_end+AF.enemy, 2*TROOPSTRENGTH, "TROOPSTAND", -- LIZTROOP gameactor
function(i, playeri, dist) {
spriteext[i]:make_animated() D.LIZTROOP, AF.chain_end+AF.enemy, 2*TROOPSTRENGTH,
sprite[i].pal = math.random(32) action = "TROOPSTAND",
-- sprite[i].ang = bit.band(sprite[i].ang-20, 2047)
local spr = sprite[i] func = function(i, playeri, dist)
spriteext[i]:make_animated()
local t = gv.gethitickms() sprite[i].pal = math.random(32)
local hit = hitscan(spr, spr.sectnum, 10, 10, 0, gv.CLIPMASK0) -- sprite[i].ang = bit.band(sprite[i].ang-20, 2047)
hs:add(1000*(gv.gethitickms()-t)) local spr = sprite[i]
if (hs.n == 300) then local t = gv.gethitickms()
printf("hitscan: %s", hs:getstatstr()) local hit = hitscan(spr, spr.sectnum, 10, 10, 0, gv.CLIPMASK0)
hs:reset()
error("greetings from LIZTROOP actor")
end
local actr = actor[i] hs:add(1000*(gv.gethitickms()-t))
if (actr:get_count() % 30 == 0) then
spr.cstatbits:flip(CS.YFLIP)
end
-- Test of bitint's ":test()" for actor[].flags. if (hs.n == 300) then
actr.flagsbits:test(AF.NVG) printf("hitscan: %s", hs:getstatstr())
hs:reset()
error("greetings from LIZTROOP actor")
end
if (dist < 4096) then local actr = actor[i]
-- Duke Vader / Anakin Nukewalker? if (actr:get_count() % 30 == 0) then
actor[i]:set_action("TROOPFLINTCH") spr.cstatbits:flip(CS.YFLIP)
actor[i]:set_move("SHRUNKVELS") end
if (dist < 1024) then -- Test of bitint's ":test()" for actor[].flags.
con.killit() actr.flagsbits:test(AF.NVG)
end
end
end
)
gameevent("DISPLAYROOMS", if (dist < 4096) then
function() -- Duke Vader / Anakin Nukewalker?
local cam = gv.cam actor[i]:set_action("TROOPFLINTCH")
cam.pos.z = cam.pos.z + 64*16*math.sin(gv.totalclock/30) actor[i]:set_move("SHRUNKVELS")
local ps = player[0] if (dist < 1024) then
if (ps.cursectnum >= 0) then con.killit()
local hit = sector[ps.cursectnum]:zrangeat(cam.pos) end
if (gv.totalclock%200==0) then
printf("hit %s %d at z=%d, %s %d at z=%d",
hit.c.spritep and "sprite" or "sector", hit.c.num, hit.c.z,
hit.f.spritep and "sprite" or "sector", hit.f.num, hit.f.z)
end
end
end
)
gameevent("DISPLAYREST", function()
for i=0,10 do
for j=1,100 do
-- XXX: This is slower in the Polymodes than with classic!
-- con._gametext(2822, j, i, 12, 0, 0, 16, 0,0,gv.xdim,gv.ydim,8192)
end end
end end
}
-- Clear showing every sector with the pavement floor tile. (Unless we're gameevent
-- in such a sector or an adjoining one.) {
-- XXX: We need a better place to do this, maybe an event in "DISPLAYROOMS",
-- G_DisplayRest() where show2dsector[] is tweaked?
local show2dsector = sector.showbitmap function()
for i=0,gv.numsectors-1 do local cam = gv.cam
if (sector[i].floorpicnum==815) then cam.pos.z = cam.pos.z + 64*16*math.sin(gv.totalclock/30)
show2dsector:set0(i)
local ps = player[0]
if (ps.cursectnum >= 0) then
local hit = sector[ps.cursectnum]:zrangeat(cam.pos)
if (gv.totalclock%200==0) then
printf("hit %s %d at z=%d, %s %d at z=%d",
hit.c.spritep and "sprite" or "sector", hit.c.num, hit.c.z,
hit.f.spritep and "sprite" or "sector", hit.f.num, hit.f.z)
end
end end
end end
end) }
-- APLAYER gameevent
gameactor(1405, actor.FLAGS.chain_beg, function(aci, pli) {
if (con._squished(aci, pli)) then "DISPLAYREST",
printf("Squished LunaCON test")
end
end)
function()
for i=0,10 do
for j=1,100 do
-- XXX: This is slower in the Polymodes than with classic!
-- con._gametext(2822, j, i, 12, 0, 0, 16, 0,0,gv.xdim,gv.ydim,8192)
end
end
gameevent("ANIMATESPRITES", -- Clear showing every sector with the pavement floor tile. (Unless we're
function(aci) -- in such a sector or an adjoining one.)
local tspr = atsprite[aci] -- XXX: We need a better place to do this, maybe an event in
if (tspr:getspr().picnum==1680) then -- G_DisplayRest() where show2dsector[] is tweaked?
local tspr2 = tspr:dup() local show2dsector = sector.showbitmap
if (tspr2) then for i=0,gv.numsectors-1 do
tspr2.x = tspr2.x + 512*math.cos(gv.totalclock/60) if (sector[i].floorpicnum==815) then
tspr2.y = tspr2.y + 512*math.sin(gv.totalclock/60) show2dsector:set0(i)
tspr2.cstatbits:set(CS.TRANS_BITMASK) end
end end
end end
end) }
gameactor
{
D.APLAYER, actor.FLAGS.chain_beg,
function(aci, pli)
if (con._squished(aci, pli)) then
printf("Squished LunaCON test")
end
end
}
gameevent
{
"ANIMATESPRITES",
function(aci)
local tspr = atsprite[aci]
if (tspr:getspr().picnum==1680) then
local tspr2 = tspr:dup()
if (tspr2) then
tspr2.x = tspr2.x + 512*math.cos(gv.totalclock/60)
tspr2.y = tspr2.y + 512*math.sin(gv.totalclock/60)
tspr2.cstatbits:set(CS.TRANS_BITMASK)
end
end
end
}
printf("EVENT_INIT = %d", gv.EVENT_INIT) -- tests default defines printf("EVENT_INIT = %d", gv.EVENT_INIT) -- tests default defines

View file

@ -36,7 +36,7 @@ require "end_gamevars"
local tag = tag local tag = tag
gameevent("JUMP", actor.FLAGS.chain_beg, gameevent{"JUMP", actor.FLAGS.chain_beg,
function(aci, pli) function(aci, pli)
local ps = player[pli] local ps = player[pli]
@ -74,4 +74,4 @@ function(aci, pli)
end end
insp = not insp insp = not insp
end) end}

View file

@ -47,7 +47,7 @@ local function rotatesprite_test()
rs(30,170, 32768, 2047*((gv.totalclock/240)%1), 142, 0,0,8+1024,0, 0,0,gv.xdim-1,gv.ydim-1) rs(30,170, 32768, 2047*((gv.totalclock/240)%1), 142, 0,0,8+1024,0, 0,0,gv.xdim-1,gv.ydim-1)
end end
gameevent(gv.EVENT_DISPLAYREST, rotatesprite_test) gameevent{gv.EVENT_DISPLAYREST, rotatesprite_test}
module(...) --==================== module(...) --====================