LunaCON: implement NODEFAULT per-actor gamevars in the C-CON fashion.

For glocal gamevars, the LunaCON semantics (session gamevar) are kept.
For per-actor ones, this now prevents resetting a gamevar's value to
default on spawn or loadactor. BUILD_LUNATIC.

git-svn-id: https://svn.eduke32.com/eduke32@5194 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2015-05-16 14:27:03 +00:00
parent c3b3b376fa
commit ef25eb6329
2 changed files with 27 additions and 18 deletions

View file

@ -234,7 +234,7 @@ local function check_allnumbers(...)
end end
-- Table of all per-actor gamevars active in the system. -- Table of all non-NODEFAULT per-actor gamevars active in the system.
-- [<actorvar reference>] = true -- [<actorvar reference>] = true
local g_actorvar = setmetatable({}, { __mode="k" }) local g_actorvar = setmetatable({}, { __mode="k" })
@ -2060,12 +2060,12 @@ local function serialize_value(strtab, i, v)
end end
-- Common serialization function for gamearray and actorvar. -- Common serialization function for gamearray and actorvar.
local function serialize_array(ar, strtab, maxnum) local function serialize_array(ar, strtab, maxnum, suffix)
for i=0,maxnum-1 do for i=0,maxnum-1 do
serialize_value(strtab, i, rawget(ar, i)) serialize_value(strtab, i, rawget(ar, i))
end end
strtab[#strtab+1] = "})" strtab[#strtab+1] = "}"..(suffix or "")..")"
return table.concat(strtab) return table.concat(strtab)
end end
@ -2316,11 +2316,13 @@ end
local actorvar_methods = { local actorvar_methods = {
--- Internal routines --- --- Internal routines ---
-- * All values for sprites not in the game world are cleared. -- * All values for sprites not in the game world are cleared (non-NODEFAULT only).
-- * All values equal to the default one are cleared. -- * All values equal to the default one are cleared.
_cleanup = function(acv) _cleanup = function(acv)
for i=0,ffiC.MAXSPRITES-1 do for i=0,ffiC.MAXSPRITES-1 do
if (ffiC.sprite[i].statnum == ffiC.MAXSTATUS or rawget(acv, i)==acv._defval) then -- NOTE: NODEFAULT per-actor gamevars are used in a non-actor fashion
if ((not acv:_is_nodefault() and ffiC.sprite[i].statnum == ffiC.MAXSTATUS)
or rawget(acv, i)==acv._defval) then
acv:_clear(i) acv:_clear(i)
end end
end end
@ -2330,6 +2332,10 @@ local actorvar_methods = {
rawset(acv, i, nil) rawset(acv, i, nil)
end, end,
_is_nodefault = function(acv, i)
return rawget(acv, '_nodefault')
end,
--- Serialization --- --- Serialization ---
_get_require = our_get_require, _get_require = our_get_require,
@ -2339,7 +2345,8 @@ local actorvar_methods = {
-- A_ResetVars() and related functions above.) -- A_ResetVars() and related functions above.)
acv:_cleanup() acv:_cleanup()
local strtab = { "_av(", tostring(acv._defval), ",{" } local strtab = { "_av(", tostring(acv._defval), ",{" }
return serialize_array(acv, strtab, ffiC.MAXSPRITES) return serialize_array(acv, strtab, ffiC.MAXSPRITES,
acv:_is_nodefault() and ",true")
end, end,
} }
@ -2364,10 +2371,12 @@ local actorvar_mt = {
-- <initval>: default value for per-actor variable. -- <initval>: default value for per-actor variable.
-- <values>: optional, a table of <spritenum>=value -- <values>: optional, a table of <spritenum>=value
function actorvar(initval, values) function actorvar(initval, values, nodefault)
check_perxval_type(initval) check_perxval_type(initval)
local acv = setmetatable({ _defval=initval }, actorvar_mt) local acv = setmetatable({ _defval=initval, _nodefault=nodefault }, actorvar_mt)
g_actorvar[acv] = true if (not nodefault) then
g_actorvar[acv] = true
end
return set_values_from_table(acv, values) return set_values_from_table(acv, values)
end end

View file

@ -1595,20 +1595,20 @@ function Cmd.gamevar(identifier, initval, flags)
local isSessionVar = (bit.band(flags, GVFLAG.NODEFAULT) ~= 0) local isSessionVar = (bit.band(flags, GVFLAG.NODEFAULT) ~= 0)
local storeWithSavegames = (bit.band(flags, GVFLAG.NORESET) == 0) local storeWithSavegames = (bit.band(flags, GVFLAG.NORESET) == 0)
if (isSessionVar and (perPlayer or perActor)) then local actorVarSuffix = ""
if (ogv == nil) then -- warn only once per gamevar
warnprintf("per-%s session gamevar `%s': NYI, made %s",
perPlayer and "player" or "actor",
identifier,
perPlayer and "global" or "non-session")
end
if (isSessionVar and (perPlayer or perActor)) then
if (perActor) then if (perActor) then
flags = bit.band(flags, bit.bnot(GVFLAG.NODEFAULT)) actorVarSuffix = ",nil,true"
-- flags = bit.band(flags, bit.bnot(GVFLAG.NODEFAULT))
isSessionVar = false isSessionVar = false
elseif (perPlayer) then elseif (perPlayer) then
flags = bit.band(flags, bit.bnot(GVFLAG.PERPLAYER)) flags = bit.band(flags, bit.bnot(GVFLAG.PERPLAYER))
perPlayer = false perPlayer = false
if (ogv == nil) then -- warn only once per gamevar
warnprintf("per-player session gamevar `%s': NYI, made global", identifier)
end
end end
end end
@ -1694,7 +1694,7 @@ function Cmd.gamevar(identifier, initval, flags)
end end
if (perActor) then if (perActor) then
addcodef("%s=_con.actorvar(%d)", gv.name, initval) addcodef("%s=_con.actorvar(%d%s)", gv.name, initval, actorVarSuffix)
elseif (perPlayer and g_cgopt["playervar"]) then elseif (perPlayer and g_cgopt["playervar"]) then
gv.flags = bit.bor(gv.flags, GVFLAG.CON_PERPLAYER) gv.flags = bit.bor(gv.flags, GVFLAG.CON_PERPLAYER)
addcodef("%s=_con.playervar(%d)", gv.name, initval) addcodef("%s=_con.playervar(%d)", gv.name, initval)