diff --git a/polymer/eduke32/source/lunatic/con_lang.lua b/polymer/eduke32/source/lunatic/con_lang.lua index 22795e7d7..c245b8307 100644 --- a/polymer/eduke32/source/lunatic/con_lang.lua +++ b/polymer/eduke32/source/lunatic/con_lang.lua @@ -20,6 +20,8 @@ MAXSKILLS = 7 MAXEVENTS = 95 -- KEEPINSYNC with EVENT_* list MAXSOUNDS = 4096 +MAXSESSIONVARS = 8 -- KEEPINSYNC lunatic_game.c + -- KEEPINSYNC quotes.h -- For Lunatic, MAXQUOTES is OBITQUOTEINDEX because starting from that index diff --git a/polymer/eduke32/source/lunatic/defs.ilua b/polymer/eduke32/source/lunatic/defs.ilua index 855ff913e..29867e173 100644 --- a/polymer/eduke32/source/lunatic/defs.ilua +++ b/polymer/eduke32/source/lunatic/defs.ilua @@ -575,6 +575,7 @@ typedef struct { ]]) bcarray.new("weapondata_t", ffiC.MAX_WEAPONS, "weapon", "weapondata_x_MAX_WEAPONS", WEAPON_NAMES) +bcarray.new("int32_t", con_lang.MAXSESSIONVARS, "sessionvar", "int32_x_MAXSESSIONVARS") -- EXTERNALLY EXPOSED GAME VARIABLES ffi.cdef[[ @@ -604,6 +605,7 @@ int32_t g_elCallDepth; int32_t block_deletesprite; const char **g_elModules; char g_modDir[]; +int32_x_MAXSESSIONVARS g_elSessionVar; actor_t actor[MAXSPRITES]; camera_t g_camera; user_defs ud; @@ -2344,10 +2346,12 @@ end local varnameMap = { gametic = "g_moveThingsCount", RETURN = "g_RETURN", + _sessionVar = "g_elSessionVar", } gv_access.gametic = true gv_access.RETURN = true +gv_access._sessionVar = true local tmpmt = { __index = function(_, key) diff --git a/polymer/eduke32/source/lunatic/dynsymlist b/polymer/eduke32/source/lunatic/dynsymlist index 92b081862..4cac45fcf 100644 --- a/polymer/eduke32/source/lunatic/dynsymlist +++ b/polymer/eduke32/source/lunatic/dynsymlist @@ -107,6 +107,7 @@ block_deletesprite; g_RETURN; g_elModules; g_modDir; +g_elSessionVar; MapInfo; EpisodeNames; diff --git a/polymer/eduke32/source/lunatic/lunacon.lua b/polymer/eduke32/source/lunatic/lunacon.lua index 1928332bc..a43e2b9fd 100644 --- a/polymer/eduke32/source/lunatic/lunacon.lua +++ b/polymer/eduke32/source/lunatic/lunacon.lua @@ -254,6 +254,8 @@ local g_funcname = {} local g_switchCode = nil -- Global number of switch statements: local g_switchCount = 0 +-- Number of session gamevars: +local g_numSessionVars = 0 -- [identifier] = { name=, flags= } local g_gamevar = {} -- [identifier] = { name=, size= } @@ -451,6 +453,7 @@ local function reset_codegen() g_funcname = {} g_switchCode = nil g_switchCount = 0 + g_numSessionVars = 0 g_gamevar = new_initial_gvartab() g_gamearray = { -- SYSTEM_GAMEARRAY @@ -1387,23 +1390,42 @@ function Cmd.gamevar(identifier, initval, flags) return end - local GVFLAG_NYI = GVFLAG.NODEFAULT + GVFLAG.NORESET - if (bit.band(flags, GVFLAG_NYI) ~= 0) then - warnprintf("gamevar \"%s\" flag(s) %d: not yet implemented", - identifier, bit.band(flags, GVFLAG_NYI)) + if (bit.band(flags, GVFLAG.NORESET) ~= 0) then + warnprintf("gamevar \"%s\" flag NORESET (131072): not yet implemented", + identifier) end - if (flags==GVFLAG.PERPLAYER+GVFLAG.PERACTOR) then + local perPlayer = (bit.band(flags, GVFLAG.PERPLAYER) ~= 0) + local perActor = (bit.band(flags, GVFLAG.PERACTOR) ~= 0) + + if (perPlayer and perActor) then errprintf("invalid gamevar flags: must be either PERPLAYER or PERACTOR, not both") return end local ogv = g_gamevar[identifier] + local isSessionVar = (bit.band(flags, GVFLAG.NODEFAULT) ~= 0) + + if (isSessionVar and (perPlayer or perActor)) then + if (ogv == nil) then -- warn only once per gamevar + warnprintf("per-%s for session gamevars: not yet implemented (made into %s)", + perPlayer and "player" or "actor", + perPlayer and "global" or "plain") + end + + if (perActor) then + flags = bit.band(flags, bit.bnot(GVFLAG.NODEFAULT)) + isSessionVar = false + elseif (perPlayer) then + flags = bit.band(flags, bit.bnot(GVFLAG.PERPLAYER)) + perPlayer = false + end + end if (ogv ~= nil) then local oflags = ogv.flags if (oflags ~= flags) then - if (bit.band(oflags, GVFLAG.SYSTEM) ~= 0) then + if (bit.band(oflags, GVFLAG.SYSTEM) ~= 0 and not isSessionVar) then -- Attempt to override a system gamevar. See if it's read-only... if (bit.band(oflags, GVFLAG.READONLY) ~= 0) then errprintf("attempt to override read-only system gamevar `%s'", identifier) @@ -1450,14 +1472,28 @@ function Cmd.gamevar(identifier, initval, flags) warnprintf("symbol `%s' already used for a defined %s", identifier, LABEL[ltype]) end + if (isSessionVar) then + if (g_numSessionVars == conl.MAXSESSIONVARS) then + errprintf("Declared too many session gamevars (flag 1024), can have at most %d.", + conl.MAXSESSIONVARS) + return + end + + -- Declare new session gamevar. + g_gamevar[identifier] = { name=format("_gv._sessionVar[%d]", g_numSessionVars), + flags=flags } + g_numSessionVars = g_numSessionVars+1 + return + end + local gv = { name=mangle_name(identifier, "V"), flags=flags } g_gamevar[identifier] = gv addcode("if _S then") - if (bit.band(flags, GVFLAG.PERX_MASK)==GVFLAG.PERACTOR) then + if (perActor) then addcodef("%s=_con.actorvar(%d)", gv.name, initval) - elseif (bit.band(flags, GVFLAG.PERX_MASK)==GVFLAG.PERPLAYER and g_cgopt["playervar"]) then + elseif (perPlayer and g_cgopt["playervar"]) then gv.flags = bit.bor(gv.flags, GVFLAG.CON_PERPLAYER) addcodef("%s=_con.playervar(%d)", gv.name, initval) else diff --git a/polymer/eduke32/source/lunatic/lunatic_game.c b/polymer/eduke32/source/lunatic/lunatic_game.c index f28755fe7..01bde260c 100644 --- a/polymer/eduke32/source/lunatic/lunatic_game.c +++ b/polymer/eduke32/source/lunatic/lunatic_game.c @@ -31,6 +31,9 @@ uint8_t g_elEvents[MAXEVENTS]; // same thing for actors: el_actor_t g_elActors[MAXTILES]; +// Session variable. Never restored except by 'readgamevar'. +int32_t g_elSessionVar[8]; // MAXSESSIONVARS, KEEPINSYNC con_lang.lua + // Set to 1 on error in event. int32_t g_elEventError; diff --git a/polymer/eduke32/source/lunatic/test/mapstate.con b/polymer/eduke32/source/lunatic/test/mapstate.con index feb31e0e0..06e904bea 100644 --- a/polymer/eduke32/source/lunatic/test/mapstate.con +++ b/polymer/eduke32/source/lunatic/test/mapstate.con @@ -151,3 +151,12 @@ endevent onevent EVENT_ENTERLEVEL loadmapstate endevent + + +onevent EVENT_USEJETPACK + savegamevar numwarpsD +endevent + +onevent EVENT_USENIGHTVISION + readgamevar numwarpsD +endevent