diff --git a/polymer/eduke32/source/lunatic/control.lua b/polymer/eduke32/source/lunatic/control.lua index 4ffe8dcdc..51c190d73 100644 --- a/polymer/eduke32/source/lunatic/control.lua +++ b/polymer/eduke32/source/lunatic/control.lua @@ -1845,6 +1845,11 @@ local function serialize_array(ar, strtab, maxnum) return table.concat(strtab) end +local function our_get_require() + return OUR_REQUIRE_STRING +end + + --- Game arrays --- local function moddir_filename(cstr_fn) @@ -2006,10 +2011,7 @@ local gamearray_methods = { --- Serialization --- - - _get_require = function(gar) - return OUR_REQUIRE_STRING - end, + _get_require = our_get_require, _serialize = function(gar) local strtab = { OUR_NAME.."._gamearray(", tostring(gar._size), ",{" } @@ -2069,7 +2071,7 @@ function killit() end --- Per-actor variable. +--== Per-actor variable ==-- local actorvar_methods = { --- Internal routines --- @@ -2089,10 +2091,7 @@ local actorvar_methods = { --- Serialization --- - - _get_require = function(acv) - return OUR_REQUIRE_STRING - end, + _get_require = our_get_require, _serialize = function(acv) local strtab = { OUR_NAME..".actorvar(", tostring(acv._defval), ",{" } @@ -2129,3 +2128,41 @@ function actorvar(initval, values) g_actorvar[acv] = true return set_values_from_table(acv, values) end + + +--== Per-player variable (kind of CODEDUP) ==-- +local playervar_methods = { + --- Serialization --- + _get_require = our_get_require, + + _serialize = function(plv) + local strtab = { OUR_NAME..".playervar(", tostring(plv._defval), ",{" } + return serialize_array(plv, strtab, ffiC.MAXSPRITES) + end, +} + +-- XXX: How about types other than numbers? +local playervar_mt = { + __index = function(plv, idx) + if (type(idx)=="number") then + check_player_idx(idx) + return plv._defval + else + return playervar_methods[idx] + end + end, + + __newindex = function(plv, idx, val) + check_player_idx(idx) + rawset(plv, idx, val) + end, + + __metatable = "serializeable", +} + +-- : default value for per-player variable. +-- : optional, a table of =value +function playervar(initval, values) + local plv = setmetatable({ _defval=initval }, playervar_mt) + return set_values_from_table(plv, values) +end diff --git a/polymer/eduke32/source/lunatic/lunacon.lua b/polymer/eduke32/source/lunatic/lunacon.lua index a7675bf1e..fdc3012e2 100644 --- a/polymer/eduke32/source/lunatic/lunacon.lua +++ b/polymer/eduke32/source/lunatic/lunacon.lua @@ -113,7 +113,9 @@ local g_warn = { ["not-redefined"]=true, ["bad-identifier"]=false, -- Code generation and output options. local g_cgopt = { ["no"]=false, ["debug-lineinfo"]=false, ["gendir"]=nil, - ["cache-sap"]=false, ["error-nostate"]=true, } + ["cache-sap"]=false, ["error-nostate"]=true, + ["playervar"]=true, } + local function csapp() return g_cgopt["cache-sap"] end -- Stack with *true* on top if the innermost block is a "whilevar*n". @@ -130,6 +132,8 @@ local GVFLAG = { NODEFAULT = 0x00000400, -- don't reset on actor spawn NORESET = 0x00020000, -- don't reset when restoring map state + + CON_PERPLAYER = 0x40000000, -- LunaCON internal } -- NOTE: This differs from enum GamevarFlags_t's GAMEVAR_USER_MASK @@ -1214,10 +1218,11 @@ function Cmd.gamevar(identifier, initval, flags) g_gamevar[identifier] = gv -- TODO: Write gamevar system on the Lunatic side and hook it up. - -- TODO: per-player gamevars. Currently, no error on using per-player var - -- in no-player context! if (bit.band(flags, GVFLAG.PERX_MASK)==GVFLAG.PERACTOR) then addcodef("%s=_con.actorvar(%d)", gv.name, initval) + elseif (bit.band(flags, GVFLAG.PERX_MASK)==GVFLAG.PERPLAYER and g_cgopt["playervar"]) then + gv.flags = bit.bor(gv.flags, GVFLAG.CON_PERPLAYER) + addcodef("%s=_con.playervar(%d)", gv.name, initval) else addcodef("%s=%d", gv.name, initval) end @@ -1239,6 +1244,10 @@ function lookup.gamearray(identifier) return ga.name end +local function thisactor_to_pli(var) + return (var=="_aci") and "_pli" or var +end + -- : code for actor or player index function lookup.gamevar(identifier, aorpvar, writable) local gv = g_gamevar[identifier] @@ -1255,6 +1264,8 @@ function lookup.gamevar(identifier, aorpvar, writable) if (bit.band(gv.flags, GVFLAG.PERACTOR)~=0) then return format("%s[%s]", gv.name, aorpvar) + elseif (bit.band(gv.flags, GVFLAG.CON_PERPLAYER)~=0 and g_cgopt["playervar"]) then + return format("%s[%s]", gv.name, thisactor_to_pli(aorpvar)) else return gv.name end @@ -1510,10 +1521,6 @@ local getperxvarcmd = -- getvar[]. <> local setperxvarcmd = -- setvar[].<> arraypat * singlememberpat * sp1 * tok.rvar -local function thisactor_to_pli(var) - return (var=="_aci") and "_pli" or var -end - -- Function generating code for a struct read/write access. local function StructAccess(Structname, writep, index, membertab) assert(type(membertab)=="table")