mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-25 11:10:47 +00:00
Lunatic: event chaining.
git-svn-id: https://svn.eduke32.com/eduke32@3320 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
41bfa1b841
commit
fa2ac57674
7 changed files with 106 additions and 15 deletions
|
@ -17,6 +17,7 @@ MAXLEVELS = 64
|
||||||
|
|
||||||
MAXSKILLS = 7
|
MAXSKILLS = 7
|
||||||
|
|
||||||
|
MAXEVENTS = 95 -- KEEPINSYNC with EVENT_* list
|
||||||
MAXSOUNDS = 4096
|
MAXSOUNDS = 4096
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,6 @@ local tostring = tostring
|
||||||
local type = type
|
local type = type
|
||||||
|
|
||||||
|
|
||||||
--== First, load the definitions common to the game's and editor's Lua interface.
|
|
||||||
|
|
||||||
-- The "gv" global will provide access to C global *scalars* and safe functions.
|
-- The "gv" global will provide access to C global *scalars* and safe functions.
|
||||||
-- XXX: still exposes C library functions etc. contained in ffi.C, problem?
|
-- XXX: still exposes C library functions etc. contained in ffi.C, problem?
|
||||||
local gv_ = {
|
local gv_ = {
|
||||||
|
@ -53,7 +51,7 @@ function decl(str)
|
||||||
ffi.cdef(str)
|
ffi.cdef(str)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- load the common definitions!
|
-- Load the definitions common to the game's and editor's Lua interface.
|
||||||
local defs_c = require("defs_common")
|
local defs_c = require("defs_common")
|
||||||
local cansee = defs_c.cansee
|
local cansee = defs_c.cansee
|
||||||
local strip_const = defs_c.strip_const
|
local strip_const = defs_c.strip_const
|
||||||
|
@ -449,6 +447,7 @@ typedef struct {
|
||||||
decl[[
|
decl[[
|
||||||
const char *g_sizes_of_what[];
|
const char *g_sizes_of_what[];
|
||||||
int32_t g_sizes_of[];
|
int32_t g_sizes_of[];
|
||||||
|
int32_t g_elCallDepth;
|
||||||
actor_t actor[MAXSPRITES];
|
actor_t actor[MAXSPRITES];
|
||||||
user_defs ud;
|
user_defs ud;
|
||||||
playerdata_t g_player[MAXPLAYERS];
|
playerdata_t g_player[MAXPLAYERS];
|
||||||
|
@ -990,6 +989,10 @@ G_._G = G_
|
||||||
local gameactor_internal = gameactor_internal -- included in lunatic.c
|
local gameactor_internal = gameactor_internal -- included in lunatic.c
|
||||||
-- gameactor(tilenum [, strength [, act [, mov [, movflags]]]], actor_func)
|
-- gameactor(tilenum [, strength [, act [, mov [, movflags]]]], actor_func)
|
||||||
local function our_gameactor(tilenum, ...)
|
local function our_gameactor(tilenum, ...)
|
||||||
|
if (ffiC.g_elCallDepth > 0) then
|
||||||
|
error("Invalid use of gameactor: must be called from top level", 2)
|
||||||
|
end
|
||||||
|
|
||||||
local args = {...}
|
local args = {...}
|
||||||
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)
|
||||||
|
@ -1000,6 +1003,9 @@ local function our_gameactor(tilenum, ...)
|
||||||
if (#args == 0) then
|
if (#args == 0) then
|
||||||
error("invalid call to gameactor: must have at least two arguments (tilenum, func)", 2)
|
error("invalid call to gameactor: must have at least two arguments (tilenum, func)", 2)
|
||||||
end
|
end
|
||||||
|
if (#args > 6) then
|
||||||
|
error("invalid call to gameactor: must have at most six arguments", 2)
|
||||||
|
end
|
||||||
if (type(args[#args]) ~= "function") then
|
if (type(args[#args]) ~= "function") then
|
||||||
error("invalid last argument to gameactor: must be a function", 2)
|
error("invalid last argument to gameactor: must be a function", 2)
|
||||||
end
|
end
|
||||||
|
@ -1035,8 +1041,52 @@ local function our_gameactor(tilenum, ...)
|
||||||
gameactor_internal(tilenum, strength, act, mov, movflags, args[#args])
|
gameactor_internal(tilenum, strength, act, mov, movflags, args[#args])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Event functions, saved for event chaining
|
||||||
|
local event_funcs = {}
|
||||||
|
|
||||||
|
local gameevent_internal = gameevent_internal -- included in lunatic.c
|
||||||
|
-- gameevent(<event idx or string>, <event function>)
|
||||||
|
local function our_gameevent(event, func)
|
||||||
|
if (ffiC.g_elCallDepth > 0) then
|
||||||
|
error("Invalid use of gameevent: must be called from top level", 2)
|
||||||
|
end
|
||||||
|
if (type(event) == "string") then
|
||||||
|
if (event:sub(1,6) ~= "EVENT_") then
|
||||||
|
event = "EVENT_"..event
|
||||||
|
end
|
||||||
|
local eventidx = con_lang.labels[3][event] -- 3: event list
|
||||||
|
if (eventidx == nil) then
|
||||||
|
errorf(2, "gameevent: invalid event label %q", event)
|
||||||
|
end
|
||||||
|
event = eventidx
|
||||||
|
end
|
||||||
|
if (type(event) ~= "number") then
|
||||||
|
error("invalid argument #1 to gameevent: must be a number", 2)
|
||||||
|
end
|
||||||
|
if (event >= con_lang.MAXEVENTS+0ULL) then
|
||||||
|
error("invalid argument #1 to gameevent: must be an event number (0 .. MAXEVENTS-1)", 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
if (type(func) ~= "function") then
|
||||||
|
error("invalid argument #2 to gameevent: must be a function", 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
local newfunc = func
|
||||||
|
local oldfunc = event_funcs[event]
|
||||||
|
-- event chaining: events defined later come first
|
||||||
|
if (oldfunc ~= nil) then
|
||||||
|
newfunc = function(aci, pli, dist)
|
||||||
|
func(aci, pli, dist)
|
||||||
|
oldfunc(aci, pli, dist)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
gameevent_internal(event, newfunc)
|
||||||
|
event_funcs[event] = newfunc
|
||||||
|
end
|
||||||
|
|
||||||
--- non-default data and functions
|
--- non-default data and functions
|
||||||
G_.gameevent = gameevent -- included in lunatic.c
|
G_.gameevent = our_gameevent
|
||||||
G_.gameactor = our_gameactor
|
G_.gameactor = our_gameactor
|
||||||
G_.player = player -- from above
|
G_.player = player -- from above
|
||||||
|
|
||||||
|
@ -1052,8 +1102,6 @@ local lunacon = require("lunacon")
|
||||||
setfenv(1, G_)
|
setfenv(1, G_)
|
||||||
|
|
||||||
-- Print keys and values of a table.
|
-- Print keys and values of a table.
|
||||||
-- REMEMBER special position of 'tostring' (it's looked up and used as a global
|
|
||||||
-- from 'print')
|
|
||||||
local function printkv(label, table)
|
local function printkv(label, table)
|
||||||
print("========== Keys and values of "..label.." ("..tostring(table)..")")
|
print("========== Keys and values of "..label.." ("..tostring(table)..")")
|
||||||
for k,v in pairs(table) do
|
for k,v in pairs(table) do
|
||||||
|
|
|
@ -12,12 +12,14 @@ local string = require("string")
|
||||||
local error = error
|
local error = error
|
||||||
local pairs = pairs
|
local pairs = pairs
|
||||||
local setmetatable = setmetatable
|
local setmetatable = setmetatable
|
||||||
|
local tostring = tostring
|
||||||
|
|
||||||
local decl = decl
|
local decl = decl
|
||||||
local getfenv = getfenv
|
local getfenv = getfenv
|
||||||
|
|
||||||
decl "void OSD_Printf(const char *fmt, ...);"
|
decl "void OSD_Printf(const char *fmt, ...);"
|
||||||
print = function(str)
|
print = function(str)
|
||||||
|
-- our "print" doesn't use the global "tostring", but the initial one
|
||||||
str = tostring(str)
|
str = tostring(str)
|
||||||
if (type(str) ~= "string") then
|
if (type(str) ~= "string") then
|
||||||
error("invalid argument to print: must be convertible to a string")
|
error("invalid argument to print: must be convertible to a string")
|
||||||
|
|
|
@ -50,6 +50,7 @@ OSD_Printf;
|
||||||
|
|
||||||
g_sizes_of_what;
|
g_sizes_of_what;
|
||||||
g_sizes_of;
|
g_sizes_of;
|
||||||
|
g_elCallDepth;
|
||||||
|
|
||||||
kopen4loadfrommod;
|
kopen4loadfrommod;
|
||||||
kfilelength;
|
kfilelength;
|
||||||
|
|
|
@ -23,6 +23,8 @@ uint8_t g_elEvents[MAXEVENTS];
|
||||||
// same thing for actors:
|
// same thing for actors:
|
||||||
el_actor_t g_elActors[MAXTILES];
|
el_actor_t g_elActors[MAXTILES];
|
||||||
|
|
||||||
|
int32_t g_elCallDepth = 0;
|
||||||
|
|
||||||
// for timing events and actors
|
// for timing events and actors
|
||||||
uint32_t g_eventCalls[MAXEVENTS], g_actorCalls[MAXTILES];
|
uint32_t g_eventCalls[MAXEVENTS], g_actorCalls[MAXTILES];
|
||||||
double g_eventTotalMs[MAXEVENTS], g_actorTotalMs[MAXTILES];
|
double g_eventTotalMs[MAXEVENTS], g_actorTotalMs[MAXTILES];
|
||||||
|
@ -104,7 +106,7 @@ void El_PrintTimes(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
////////// ERROR REPORTING //////////
|
////////// ERROR REPORTING //////////
|
||||||
#define EL_MAXERRORS 2
|
#define EL_MAXERRORS 20
|
||||||
static int32_t el_numErrors=0, el_tooMuchErrors;
|
static int32_t el_numErrors=0, el_tooMuchErrors;
|
||||||
static char *el_errorMsgs[EL_MAXERRORS];
|
static char *el_errorMsgs[EL_MAXERRORS];
|
||||||
|
|
||||||
|
@ -202,7 +204,7 @@ static void El_StateSetup(lua_State *L)
|
||||||
|
|
||||||
// create misc. global functions in the Lua state
|
// create misc. global functions in the Lua state
|
||||||
lua_pushcfunction(L, SetEvent_luacf);
|
lua_pushcfunction(L, SetEvent_luacf);
|
||||||
lua_setglobal(L, "gameevent");
|
lua_setglobal(L, "gameevent_internal");
|
||||||
lua_pushcfunction(L, SetActor_luacf);
|
lua_pushcfunction(L, SetActor_luacf);
|
||||||
lua_setglobal(L, "gameactor_internal");
|
lua_setglobal(L, "gameactor_internal");
|
||||||
|
|
||||||
|
@ -230,12 +232,10 @@ static int32_t SetEvent_luacf(lua_State *L)
|
||||||
{
|
{
|
||||||
int32_t eventidx;
|
int32_t eventidx;
|
||||||
|
|
||||||
if (lua_gettop(L) != 2)
|
Bassert(lua_gettop(L) == 2);
|
||||||
luaL_error(L, "gameevent: must pass exactly two arguments");
|
|
||||||
|
|
||||||
eventidx = luaL_checkint(L, 1);
|
eventidx = luaL_checkint(L, 1);
|
||||||
|
Bassert((unsigned)eventidx < MAXEVENTS);
|
||||||
|
|
||||||
luaL_argcheck(L, (unsigned)eventidx < MAXEVENTS, 1, "must be an event number (0 .. MAXEVENTS-1)");
|
|
||||||
L_CheckAndRegisterFunction(L, &g_elEvents[eventidx]);
|
L_CheckAndRegisterFunction(L, &g_elEvents[eventidx]);
|
||||||
g_elEvents[eventidx] = 1;
|
g_elEvents[eventidx] = 1;
|
||||||
|
|
||||||
|
@ -308,8 +308,11 @@ int32_t El_CallEvent(L_State *estate, int32_t eventidx, int32_t iActor, int32_t
|
||||||
// make a global?
|
// make a global?
|
||||||
|
|
||||||
lua_State *const L = estate->L;
|
lua_State *const L = estate->L;
|
||||||
|
int32_t i;
|
||||||
|
|
||||||
int32_t i = call_regd_function3(L, &g_elEvents[eventidx], iActor, iPlayer, lDist);
|
g_elCallDepth++;
|
||||||
|
i = call_regd_function3(L, &g_elEvents[eventidx], iActor, iPlayer, lDist);
|
||||||
|
g_elCallDepth--;
|
||||||
|
|
||||||
if (i == LUA_ERRRUN)
|
if (i == LUA_ERRRUN)
|
||||||
{
|
{
|
||||||
|
@ -337,8 +340,11 @@ int32_t El_CallEvent(L_State *estate, int32_t eventidx, int32_t iActor, int32_t
|
||||||
int32_t El_CallActor(L_State *estate, int32_t actortile, int32_t iActor, int32_t iPlayer, int32_t lDist)
|
int32_t El_CallActor(L_State *estate, int32_t actortile, int32_t iActor, int32_t iPlayer, int32_t lDist)
|
||||||
{
|
{
|
||||||
lua_State *const L = estate->L;
|
lua_State *const L = estate->L;
|
||||||
|
int32_t i;
|
||||||
|
|
||||||
int32_t i = call_regd_function3(L, &g_elActors[actortile], iActor, iPlayer, lDist);
|
g_elCallDepth++;
|
||||||
|
i = call_regd_function3(L, &g_elActors[actortile], iActor, iPlayer, lDist);
|
||||||
|
g_elCallDepth--;
|
||||||
|
|
||||||
if (i == LUA_ERRRUN)
|
if (i == LUA_ERRRUN)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,6 +7,9 @@ local string = require("string")
|
||||||
local bit = require("bit")
|
local bit = require("bit")
|
||||||
local math = require("math")
|
local math = require("math")
|
||||||
|
|
||||||
|
local pcall = pcall
|
||||||
|
local DBG_ = DBG_
|
||||||
|
|
||||||
print('---=== ELua Test script ===---')
|
print('---=== ELua Test script ===---')
|
||||||
|
|
||||||
local function printf(fmt, ...)
|
local function printf(fmt, ...)
|
||||||
|
@ -183,7 +186,7 @@ checkfail("do local bt=require'bittest'; bt.QWE=1; end", "modifying module table
|
||||||
-- the cdata returned by player[] can't be made into a pointer!
|
-- the cdata returned by player[] can't be made into a pointer!
|
||||||
checkfail("do local pl=player[0]; i=pl[1]; end")
|
checkfail("do local pl=player[0]; i=pl[1]; end")
|
||||||
checkfail("do local ud=gv.ud.camera; end", "dummy variable: read access forbidden") -- test for proper decl()
|
checkfail("do local ud=gv.ud.camera; end", "dummy variable: read access forbidden") -- test for proper decl()
|
||||||
checkfail("sprite[0]:set_picnum(-10)", "attempt to set invalid picnums")
|
checkfail("sprite[0]:set_picnum(-10)", "attempt to set invalid picnum")
|
||||||
|
|
||||||
printf('ceilingbunch of sector 0: %d', getbunch(0, gv.CEILING))
|
printf('ceilingbunch of sector 0: %d', getbunch(0, gv.CEILING))
|
||||||
|
|
||||||
|
@ -194,6 +197,13 @@ gameevent(gv.EVENT_JUMP,
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|
||||||
|
-- test event chaining
|
||||||
|
gameevent("JUMP",
|
||||||
|
function(actori, playeri, dist)
|
||||||
|
print("I'm first!")
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
gameevent(gv.EVENT_ENTERLEVEL,
|
gameevent(gv.EVENT_ENTERLEVEL,
|
||||||
function()
|
function()
|
||||||
-- NOTE: times are for helixhorned (Core2Duo 3GHz)
|
-- NOTE: times are for helixhorned (Core2Duo 3GHz)
|
||||||
|
@ -230,6 +240,9 @@ gameevent(gv.EVENT_ENTERLEVEL,
|
||||||
|
|
||||||
printf("sqrt(0xffffffff) = %f(ksqrt) %f(math.sqrt)",
|
printf("sqrt(0xffffffff) = %f(ksqrt) %f(math.sqrt)",
|
||||||
gv.ksqrt(0xffffffff), math.sqrt(0xffffffff))
|
gv.ksqrt(0xffffffff), math.sqrt(0xffffffff))
|
||||||
|
|
||||||
|
checkfail("gameevent('GAME', function() print('qwe') end)",
|
||||||
|
"must be called from top level")
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
20
polymer/eduke32/source/lunatic/test/event_chaining.con
Normal file
20
polymer/eduke32/source/lunatic/test/event_chaining.con
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
definequote 125 FIRST
|
||||||
|
definequote 126 SECOND
|
||||||
|
definequote 127 THIRD
|
||||||
|
|
||||||
|
onevent EVENT_INIT
|
||||||
|
echo 125
|
||||||
|
endevent
|
||||||
|
|
||||||
|
onevent EVENT_INIT
|
||||||
|
echo 126
|
||||||
|
endevent
|
||||||
|
|
||||||
|
onevent EVENT_INIT
|
||||||
|
echo 127
|
||||||
|
endevent
|
||||||
|
|
||||||
|
// output:
|
||||||
|
// THIRD
|
||||||
|
// SECOND
|
||||||
|
// FIRST
|
Loading…
Reference in a new issue