Lunatic t.: {read,save}gamevar, fix break in nested while, fix rotatesprite16.

git-svn-id: https://svn.eduke32.com/eduke32@3533 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2013-02-28 17:30:15 +00:00
parent fe4090b9fd
commit 8955316bba
5 changed files with 102 additions and 13 deletions

View file

@ -276,6 +276,13 @@ function rotatesprite(x, y, zoom, ang, tilenum, shade, pal, orientation,
check_tile_idx(tilenum)
orientation = bit.band(orientation, 2047) -- ROTATESPRITE_MAX-1
-- XXX: This is the same as the check in gameexec.c, but ideally we'd want
-- rotatesprite to accept all coordinates and simply draw nothing if they
-- denote an area beyond the screen.
if (not (x >= -320 and x < 640) or not (y >= -200 and y < 400)) then
error(format("invalid coordinates (%.03f, %.03f)", x, y), 2)
end
-- TODO: check that it works correctly with all coordinates, also if one
-- border is outside the screen etc...
ffiC.rotatesprite(65536*x, 65536*y, zoom, ang, tilenum, shade, pal, bit.bor(2,orientation),
@ -1578,6 +1585,34 @@ function _setgamepalette(pli, basepal)
ffiC.P_SetGamePalette(player[pli], basepal)
end
-- Gamevar persistence in the configuration file
function _savegamevar(name, val)
if (ffiC.ud.config.scripthandle < 0) then
return
end
assert(type(name)=="string")
assert(type(val)=="number")
ffiC.SCRIPT_PutNumber(ffiC.ud.config.scripthandle, "Gamevars", name,
val, 0, 0);
end
function _readgamevar(name)
if (ffiC.ud.config.scripthandle < 0) then
return
end
assert(type(name)=="string")
local v = ffi.new("int32_t [1]")
ffiC.SCRIPT_GetNumber(ffiC.ud.config.scripthandle, "Gamevars", name, v);
-- NOTE: doesn't examine SCRIPT_GetNumber() return value and returns 0 if
-- there was no such gamevar saved, like C-CON.
return v[0]
end
--- Game arrays ---

View file

@ -595,6 +595,10 @@ void C_DefineLevelName(int32_t vol, int32_t lev, const char *fn,
void C_DefineProjectile(int32_t j, int32_t what, int32_t val);
void C_DefineGameFuncName(int32_t idx, const char *name);
int32_t C_SetDefName(const char *name);
int32_t SCRIPT_GetNumber(int32_t scripthandle, const char *sectionname, const char *entryname, int32_t *number);
void SCRIPT_PutNumber(int32_t scripthandle, const char *sectionname, const char *entryname, int32_t number,
int32_t hexadecimal, int32_t defaultvalue);
]]

View file

@ -94,6 +94,9 @@ C_DefineProjectile;
C_DefineGameFuncName;
C_SetDefName;
SCRIPT_GetNumber;
SCRIPT_PutNumber;
actor;
g_camera;
ud;

View file

@ -28,8 +28,12 @@ local unpack = unpack
local read_into_string = read_into_string
local ffi, ffiC
if (string.dump) then
bit = require("bit")
if (string.dump) then -- running stand-alone
local ljp = pcall(function() require("ffi") end)
-- "lbit" is the same module as LuaJIT's "bit" (LuaBitOp:
-- http://bitop.luajit.org/), but under a different name for (IMO) less
-- confusion. Useful for running with Rio Lua for cross-checking.
bit = ljp and require("bit") or require("lbit")
require("strict")
else
bit = require("bit")
@ -948,7 +952,7 @@ function Cmd.gamearray(identifier, initsize)
return
end
if (initsize >= 0x7fffffff+0ULL) then
if (not (initsize >= 0 and initsize < 0x7fffffff)) then
errprintf("invalid initial size %d for gamearray `%s'", initsize, identifier)
return
end
@ -1587,7 +1591,35 @@ local handle =
end,
rotatesprite16 = function(...)
return format("_con.rotatesprite(%s,%s/65536,%s/65536,%s,%s,%s,%s,%s,%s,%s,%s,%s)", ...)
return format("_con.rotatesprite(%s/65536,%s/65536,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)", ...)
end,
-- readgamevar or savegamevar
RSgamevar = function(identifier, dosave)
-- check identifier for sanity
if (not identifier:match("^[A-Za-z][A-Za-z0-9_]*$")) then
errprintf("%s: invalid identifier name `%s' for config file persistence",
g_lastkw)
return "_BADRSGV()"
end
local gv = g_gamevar[identifier]
if (gv and bit.band(gv.flags, GVFLAG.PERX_MASK)==GVFLAG.PERACTOR) then
-- Per-player are kind of global without multiplayer anyway. TODO_MP
errprintf("can only %s global or per-player gamevars", g_lastkw,
dosave and "save" or "read")
return "_BADRSGV()"
end
-- NOTE: more strict than C-CON: we require the gamevar being writable
-- even if we're saving it.
local code = lookup.gamevar(identifier, nil, true)
if (dosave) then
return format("_con._savegamevar(%q,%s)", identifier, code)
else
return format("%s=_con._readgamevar(%q)", code, identifier)
end
end,
state = function(statename)
@ -1618,7 +1650,7 @@ local Cinner = {
["break"] = cmd()
/ function()
return g_isWhile[#g_isWhile]
and format("goto l%d", g_whilenum)
and format("goto l%d", #g_isWhile)
or "do return end"
end,
["return"] = cmd() -- NLCF
@ -1976,10 +2008,10 @@ local Cinner = {
/ handle.dynNYI,
savemapstate = cmd()
/ handle.dynNYI,
savegamevar = cmd(R)
/ handle.dynNYI,
readgamevar = cmd(W)
/ handle.dynNYI,
savegamevar = cmd(I)
/ function(id) return handle.RSgamevar(id, true) end,
readgamevar = cmd(I)
/ function(id) return handle.RSgamevar(id, false) end,
savenn = cmd(D)
/ handle.dynNYI,
save = cmd(D)
@ -2621,10 +2653,9 @@ function on.while_begin(v1, v2)
end
function on.while_end()
local whilenum = #g_isWhile
table.remove(g_isWhile)
local code=format("::l%d:: end", g_whilenum)
g_whilenum = g_whilenum+1
return code
return format("::l%d:: end", whilenum)
end
function on.switch_begin()
@ -2838,7 +2869,6 @@ function on.parse_begin()
g_iflevel = 0
g_ifelselevel = 0
g_isWhile = {}
g_whilenum = 0
g_have_file[g_filename] = true
-- set up new state

View file

@ -107,4 +107,21 @@ onevent EVENT_ENTERLEVEL
userquote 30
endswitch
*/
// nested whilevar*n
setvar j -1
setvar k -1
whilevarn j 0
{
whilevarn k 0
{
setvar k 0
break
setvar k 1
}
setvar j 0
break
setvar j -1
}
endevent