mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-24 10:40:46 +00:00
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:
parent
bbcf6d6353
commit
f6065e227a
5 changed files with 316 additions and 255 deletions
|
@ -795,9 +795,11 @@ do
|
|||
-- Callback function chaining control 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 = 0x08000000 -- Should only be used for gameevent
|
||||
our_SFLAG.chain_beg = 0x20000000
|
||||
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
|
||||
-- external for Lunatic.
|
||||
|
@ -853,7 +855,8 @@ actor = setmtonce({}, defs_c.GenStructMetatable("actor", "MAXSPRITES", actor_sta
|
|||
-- Some bitwise NOTs of various actor flag masks.
|
||||
local BNOT = {
|
||||
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[]")
|
||||
|
@ -1617,6 +1620,15 @@ local function chain_func3(func1, func2)
|
|||
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?
|
||||
local g_firstRun = (ffiC.g_elCONSize == 0)
|
||||
|
||||
|
@ -1624,10 +1636,17 @@ local g_firstRun = (ffiC.g_elCONSize == 0)
|
|||
local actor_funcs = {}
|
||||
|
||||
local gameactor_internal = gameactor_internal -- included in lunatic.c
|
||||
-- gameactor(tilenum [, flags [, strength [, act [, mov [, movflags]]]]], actor_func)
|
||||
local function our_gameactor(tilenum, ...)
|
||||
-- gameactor{tilenum [, flags [, strength [, action [, move [, movflags]]]]], func}
|
||||
-- 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")
|
||||
|
||||
if (type(args)~="table") then
|
||||
error("invalid gameactor call: must be passed a table")
|
||||
end
|
||||
|
||||
local tilenum = args[1]
|
||||
if (type(tilenum) ~= "number") then
|
||||
error("invalid argument #1 to gameactor: must be a number", 2)
|
||||
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)
|
||||
end
|
||||
|
||||
local args = {...}
|
||||
-- Number of varargs; args may have nil's in the middle!
|
||||
local numargs = select('#', ...)
|
||||
|
||||
if (numargs == 0) then
|
||||
error("invalid call to gameactor: must have at least two arguments (tilenum, func)", 2)
|
||||
local lastargi = ourmaxn(args)
|
||||
local func = args[lastargi]
|
||||
if (type(func) ~= "function") then
|
||||
func = args.func
|
||||
lastargi = 1/0
|
||||
end
|
||||
if (numargs >= 7) then -- sic, because tilenum isn't counted!
|
||||
error("invalid call to gameactor: must have at most 7 arguments", 2)
|
||||
end
|
||||
if (type(args[numargs]) ~= "function") then
|
||||
error("invalid last argument to gameactor: must be a function", 2)
|
||||
if (type(func) ~= "function") then
|
||||
error("invalid gameactor call: must provide a function with last numeric arg or .func", 2)
|
||||
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
|
||||
error("invalid 'flags' argument to gameactor: must be a number", 2)
|
||||
error("invalid 'flags' argument (#2) to gameactor: must be a number", 2)
|
||||
end
|
||||
|
||||
local AF = actor.FLAGS
|
||||
local chainflags = bit.band(flags, AF._CHAIN_MASK)
|
||||
flags = bit.band(flags, BNOT.CHAIN_MASK)
|
||||
local chainflags = bit.band(flags, AF._CHAIN_MASK_ACTOR)
|
||||
flags = bit.band(flags, BNOT.CHAIN_MASK_ACTOR)
|
||||
|
||||
-- Default chaining behavior: don't, replace the old actor instead, but
|
||||
-- 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)
|
||||
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)
|
||||
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 (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
|
||||
|
||||
-- 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 (type(act)=="string") then
|
||||
act = AC[act]
|
||||
end
|
||||
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
|
||||
|
||||
-- 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 (type(mov)=="string") then
|
||||
mov = MV[mov]
|
||||
end
|
||||
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
|
||||
|
||||
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 (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
|
||||
|
||||
|
@ -1726,7 +1741,6 @@ local function our_gameactor(tilenum, ...)
|
|||
tile.flags = (chainflags==AF.replace_hard) and flags or bit.bor(tile.flags, flags)
|
||||
end
|
||||
|
||||
local func = args[numargs]
|
||||
local newfunc = replacep and func
|
||||
or (chainflags==AF.chain_beg) and chain_func3(func, actor_funcs[tilenum])
|
||||
or (chainflags==AF.chain_end) and chain_func3(actor_funcs[tilenum], func)
|
||||
|
@ -1740,10 +1754,16 @@ end
|
|||
local event_funcs = {}
|
||||
|
||||
local gameevent_internal = gameevent_internal -- included in lunatic.c
|
||||
-- gameevent(<event idx or string> [, flags], <event function>)
|
||||
local function our_gameevent(event, flags, func)
|
||||
-- gameevent{<event idx or string> [, flags], <event function>}
|
||||
local function our_gameevent(args)
|
||||
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 (event:sub(1,6) ~= "EVENT_") then
|
||||
event = "EVENT_"..event
|
||||
|
@ -1763,27 +1783,28 @@ local function our_gameevent(event, flags, func)
|
|||
|
||||
local AF = actor.FLAGS
|
||||
|
||||
-- Event chaining: in Lunatic, chaining at the *end* is the default.
|
||||
if (func==nil) then
|
||||
func = flags
|
||||
flags = AF.chain_end
|
||||
else
|
||||
if (type(flags) ~= "number") then
|
||||
error("invalid 'flags' argument to gameevent: must be a number", 2)
|
||||
-- Kind of CODEDUP from our_gameactor.
|
||||
local lastargi = ourmaxn(args)
|
||||
local func = args[lastargi]
|
||||
if (type(func) ~= "function") then
|
||||
func = args.func
|
||||
lastargi = 1/0
|
||||
end
|
||||
if (bit.band(flags, BNOT.CHAIN_MASK) ~= 0) then
|
||||
if (type(func) ~= "function") then
|
||||
error("invalid gameevent call: must provide a function with last numeric arg or .func", 2)
|
||||
end
|
||||
|
||||
-- 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
|
||||
if (flags == 0) then
|
||||
flags = AF.chain_end
|
||||
end
|
||||
end
|
||||
|
||||
if (type(func) ~= "function") then
|
||||
error("invalid last argument to gameevent: must be a function", 2)
|
||||
end
|
||||
|
||||
local newfunc = replacep and func
|
||||
local newfunc = (flags==AF.replace) and func
|
||||
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 assert(false)
|
||||
|
|
|
@ -418,9 +418,9 @@ function on.actor_end(pos, usertype, tsamm, codetab)
|
|||
str = str .. movflags..","
|
||||
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())
|
||||
add_code_and_end(codetab, "end)")
|
||||
add_code_and_end(codetab, "end}")
|
||||
|
||||
if (g_code.actor[tilenum] ~= nil) then
|
||||
pwarnprintf(pos, "redefined actor %d", tilenum)
|
||||
|
@ -476,22 +476,22 @@ end
|
|||
function on.event_end(pos, eventidx, codetab)
|
||||
assert(type(codetab)=="table")
|
||||
-- 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(codetab)
|
||||
addcode("end)")
|
||||
addcode("end}")
|
||||
|
||||
g_code.event[eventidx] = codetab
|
||||
end
|
||||
|
||||
function on.eventloadactor_end(pos, tilenum, codetab)
|
||||
-- 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())
|
||||
addcodef("if (%s==%d) then", SPS".picnum", tilenum)
|
||||
addcode(codetab)
|
||||
addcode("end")
|
||||
addcode("end)")
|
||||
addcode("end}")
|
||||
|
||||
if (g_code.loadactor[tilenum] ~= nil and g_warn["chained-loadactor"]) then
|
||||
-- NOTE: C-CON redefines loadactor code if encountered multiple times.
|
||||
|
|
|
@ -178,7 +178,7 @@ checkfail('local i = actor[0].t_data[15]', "has no member named 't_data'")
|
|||
-- no pointer arithmetic!
|
||||
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")
|
||||
-- the cdata returned by player[] can't be made into a pointer!
|
||||
|
@ -195,17 +195,20 @@ player[0].curr_weapon = 1
|
|||
|
||||
printf('ceilingbunch of sector 0: %d', sector[0].ceilingbunch)
|
||||
|
||||
gameevent(gv.EVENT_JUMP,
|
||||
gameevent{gv.EVENT_JUMP,
|
||||
function(actori, playeri, dist)
|
||||
printf("jump i=%d p=%d d=%d", actori, playeri, dist)
|
||||
error("greetings from EVENT_JUMP")
|
||||
end
|
||||
)
|
||||
}
|
||||
|
||||
gameevent
|
||||
{
|
||||
"PROCESSINPUT",
|
||||
|
||||
gameevent("PROCESSINPUT",
|
||||
-- Input test.
|
||||
-- NOTE: I don't think that exposing g_player[].sync (aka "input") is a good idea...
|
||||
function(actori, playeri, dist)
|
||||
func = function(actori, playeri, dist)
|
||||
local IB = player._INPUT_BITS
|
||||
local input = player[playeri]._input
|
||||
if (bit.band(input.bits, IB.JUMP) ~= 0) then
|
||||
|
@ -216,10 +219,15 @@ gameevent("PROCESSINPUT",
|
|||
input.bits = bit.bor(input.bits, IB.JETPACK)
|
||||
end
|
||||
end
|
||||
)
|
||||
}
|
||||
|
||||
-- test event chaining
|
||||
gameevent("JUMP", actor.FLAGS.chain_beg,
|
||||
gameevent
|
||||
{
|
||||
"JUMP",
|
||||
|
||||
flags = actor.FLAGS.chain_beg,
|
||||
|
||||
function(actori, playeri, dist)
|
||||
local ps = player[playeri]
|
||||
print("\n--- I'm first!")
|
||||
|
@ -237,9 +245,12 @@ gameevent("JUMP", actor.FLAGS.chain_beg,
|
|||
ps._pals[2] = 20
|
||||
ps._pals.f = 30
|
||||
end
|
||||
)
|
||||
}
|
||||
|
||||
gameevent
|
||||
{
|
||||
gv.EVENT_ENTERLEVEL,
|
||||
|
||||
gameevent(gv.EVENT_ENTERLEVEL,
|
||||
function()
|
||||
if (gv._DEBUG_LUNATIC) then
|
||||
DBG_.testmembread()
|
||||
|
@ -327,33 +338,40 @@ gameevent(gv.EVENT_ENTERLEVEL,
|
|||
checkfail("gameevent('GAME', function() print('qwe') end)",
|
||||
"must be called from top level")
|
||||
end
|
||||
)
|
||||
}
|
||||
|
||||
local geom = require "geom"
|
||||
|
||||
gameevent("LOADACTOR", function(i)
|
||||
gameevent{"LOADACTOR", function(i)
|
||||
local spr = sprite[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
|
||||
spr.hitag = 0
|
||||
end
|
||||
end)
|
||||
end}
|
||||
|
||||
gameactor(930, nil, 1, function(i) -- "police line" ribbon
|
||||
gameactor
|
||||
{
|
||||
-- "police line" ribbon
|
||||
930, nil, 1,
|
||||
|
||||
func = function(i)
|
||||
local spr = sprite[i]
|
||||
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)
|
||||
end
|
||||
}
|
||||
|
||||
local stat = require("stat")
|
||||
local hs = stat.new()
|
||||
|
||||
local con = require("con")
|
||||
local AC, MV = con.AC, con.MV
|
||||
|
||||
con.action("TROOPSTAND",0,1,5,1,1)
|
||||
con.action("TROOPFLINTCH", 50, 1, 1, 1, 6)
|
||||
con.move("SHRUNKVELS", 32)
|
||||
|
@ -366,12 +384,18 @@ con.ai("AITEMP", "TROOPFLINTCH", "SHRUNKVELS", 0)
|
|||
|
||||
local TROOPSTRENGTH = 30
|
||||
|
||||
local D = require("CON.DEFS")
|
||||
local AF = actor.FLAGS
|
||||
local CS = sprite.CSTAT
|
||||
|
||||
-- Also test actor code chaining: strength is doubled.
|
||||
gameactor(1680, AF.chain_end+AF.enemy, 2*TROOPSTRENGTH, "TROOPSTAND", -- LIZTROOP
|
||||
function(i, playeri, dist)
|
||||
gameactor
|
||||
{
|
||||
D.LIZTROOP, AF.chain_end+AF.enemy, 2*TROOPSTRENGTH,
|
||||
|
||||
action = "TROOPSTAND",
|
||||
|
||||
func = function(i, playeri, dist)
|
||||
spriteext[i]:make_animated()
|
||||
|
||||
sprite[i].pal = math.random(32)
|
||||
|
@ -408,9 +432,12 @@ gameactor(1680, AF.chain_end+AF.enemy, 2*TROOPSTRENGTH, "TROOPSTAND", -- LIZTROO
|
|||
end
|
||||
end
|
||||
end
|
||||
)
|
||||
}
|
||||
|
||||
gameevent
|
||||
{
|
||||
"DISPLAYROOMS",
|
||||
|
||||
gameevent("DISPLAYROOMS",
|
||||
function()
|
||||
local cam = gv.cam
|
||||
cam.pos.z = cam.pos.z + 64*16*math.sin(gv.totalclock/30)
|
||||
|
@ -425,9 +452,13 @@ gameevent("DISPLAYROOMS",
|
|||
end
|
||||
end
|
||||
end
|
||||
)
|
||||
}
|
||||
|
||||
gameevent("DISPLAYREST", function()
|
||||
gameevent
|
||||
{
|
||||
"DISPLAYREST",
|
||||
|
||||
function()
|
||||
for i=0,10 do
|
||||
for j=1,100 do
|
||||
-- XXX: This is slower in the Polymodes than with classic!
|
||||
|
@ -445,17 +476,25 @@ gameevent("DISPLAYREST", function()
|
|||
show2dsector:set0(i)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
}
|
||||
|
||||
-- APLAYER
|
||||
gameactor(1405, actor.FLAGS.chain_beg, function(aci, pli)
|
||||
gameactor
|
||||
{
|
||||
D.APLAYER, actor.FLAGS.chain_beg,
|
||||
|
||||
function(aci, pli)
|
||||
if (con._squished(aci, pli)) then
|
||||
printf("Squished LunaCON test")
|
||||
end
|
||||
end)
|
||||
end
|
||||
}
|
||||
|
||||
|
||||
gameevent("ANIMATESPRITES",
|
||||
gameevent
|
||||
{
|
||||
"ANIMATESPRITES",
|
||||
|
||||
function(aci)
|
||||
local tspr = atsprite[aci]
|
||||
if (tspr:getspr().picnum==1680) then
|
||||
|
@ -466,7 +505,8 @@ function(aci)
|
|||
tspr2.cstatbits:set(CS.TRANS_BITMASK)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
}
|
||||
|
||||
printf("EVENT_INIT = %d", gv.EVENT_INIT) -- tests default defines
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ require "end_gamevars"
|
|||
local tag = tag
|
||||
|
||||
|
||||
gameevent("JUMP", actor.FLAGS.chain_beg,
|
||||
gameevent{"JUMP", actor.FLAGS.chain_beg,
|
||||
function(aci, pli)
|
||||
local ps = player[pli]
|
||||
|
||||
|
@ -74,4 +74,4 @@ function(aci, pli)
|
|||
end
|
||||
|
||||
insp = not insp
|
||||
end)
|
||||
end}
|
||||
|
|
|
@ -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)
|
||||
end
|
||||
|
||||
gameevent(gv.EVENT_DISPLAYREST, rotatesprite_test)
|
||||
gameevent{gv.EVENT_DISPLAYREST, rotatesprite_test}
|
||||
|
||||
|
||||
module(...) --====================
|
||||
|
|
Loading…
Reference in a new issue