LunaCON: real user per-player vars.

The previous behavior was to translate them as global gamevars, since LunaCON
currently has no support for multiplayer. However, then some errors would be
missed where such gamevars are accessed in no-player context
(e.g. EVENT_ENTERLEVEL).
On by default, disabled with -fno-playervar.

git-svn-id: https://svn.eduke32.com/eduke32@3842 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2013-06-01 20:09:41 +00:00
parent 358c7eb28b
commit e0433e66fb
2 changed files with 60 additions and 16 deletions

View file

@ -1845,6 +1845,11 @@ local function serialize_array(ar, strtab, maxnum)
return table.concat(strtab) return table.concat(strtab)
end end
local function our_get_require()
return OUR_REQUIRE_STRING
end
--- Game arrays --- --- Game arrays ---
local function moddir_filename(cstr_fn) local function moddir_filename(cstr_fn)
@ -2006,10 +2011,7 @@ local gamearray_methods = {
--- Serialization --- --- Serialization ---
_get_require = our_get_require,
_get_require = function(gar)
return OUR_REQUIRE_STRING
end,
_serialize = function(gar) _serialize = function(gar)
local strtab = { OUR_NAME.."._gamearray(", tostring(gar._size), ",{" } local strtab = { OUR_NAME.."._gamearray(", tostring(gar._size), ",{" }
@ -2069,7 +2071,7 @@ function killit()
end end
-- Per-actor variable. --== Per-actor variable ==--
local actorvar_methods = { local actorvar_methods = {
--- Internal routines --- --- Internal routines ---
@ -2089,10 +2091,7 @@ local actorvar_methods = {
--- Serialization --- --- Serialization ---
_get_require = our_get_require,
_get_require = function(acv)
return OUR_REQUIRE_STRING
end,
_serialize = function(acv) _serialize = function(acv)
local strtab = { OUR_NAME..".actorvar(", tostring(acv._defval), ",{" } local strtab = { OUR_NAME..".actorvar(", tostring(acv._defval), ",{" }
@ -2129,3 +2128,41 @@ function actorvar(initval, values)
g_actorvar[acv] = true g_actorvar[acv] = true
return set_values_from_table(acv, values) return set_values_from_table(acv, values)
end 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",
}
-- <initval>: default value for per-player variable.
-- <values>: optional, a table of <playeridx>=value
function playervar(initval, values)
local plv = setmetatable({ _defval=initval }, playervar_mt)
return set_values_from_table(plv, values)
end

View file

@ -113,7 +113,9 @@ local g_warn = { ["not-redefined"]=true, ["bad-identifier"]=false,
-- Code generation and output options. -- Code generation and output options.
local g_cgopt = { ["no"]=false, ["debug-lineinfo"]=false, ["gendir"]=nil, 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 local function csapp() return g_cgopt["cache-sap"] end
-- Stack with *true* on top if the innermost block is a "whilevar*n". -- 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 NODEFAULT = 0x00000400, -- don't reset on actor spawn
NORESET = 0x00020000, -- don't reset when restoring map state 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 -- 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 g_gamevar[identifier] = gv
-- TODO: Write gamevar system on the Lunatic side and hook it up. -- 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 if (bit.band(flags, GVFLAG.PERX_MASK)==GVFLAG.PERACTOR) then
addcodef("%s=_con.actorvar(%d)", gv.name, initval) 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 else
addcodef("%s=%d", gv.name, initval) addcodef("%s=%d", gv.name, initval)
end end
@ -1239,6 +1244,10 @@ function lookup.gamearray(identifier)
return ga.name return ga.name
end end
local function thisactor_to_pli(var)
return (var=="_aci") and "_pli" or var
end
-- <aorpvar>: code for actor or player index -- <aorpvar>: code for actor or player index
function lookup.gamevar(identifier, aorpvar, writable) function lookup.gamevar(identifier, aorpvar, writable)
local gv = g_gamevar[identifier] local gv = g_gamevar[identifier]
@ -1255,6 +1264,8 @@ function lookup.gamevar(identifier, aorpvar, writable)
if (bit.band(gv.flags, GVFLAG.PERACTOR)~=0) then if (bit.band(gv.flags, GVFLAG.PERACTOR)~=0) then
return format("%s[%s]", gv.name, aorpvar) 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 else
return gv.name return gv.name
end end
@ -1510,10 +1521,6 @@ local getperxvarcmd = -- get<actor/player>var[<idx>].<varname> <<var>>
local setperxvarcmd = -- set<actor/player>var[<idx>].<<varname>> <var> local setperxvarcmd = -- set<actor/player>var[<idx>].<<varname>> <var>
arraypat * singlememberpat * sp1 * tok.rvar 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. -- Function generating code for a struct read/write access.
local function StructAccess(Structname, writep, index, membertab) local function StructAccess(Structname, writep, index, membertab)
assert(type(membertab)=="table") assert(type(membertab)=="table")