mirror of
https://github.com/ZDoom/raze-gles.git
synced 2025-01-11 18:50:46 +00:00
Lunatic: begin changing ones...
git-svn-id: https://svn.eduke32.com/eduke32@3390 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
7d2dd223bb
commit
8e5d5f9b89
3 changed files with 162 additions and 38 deletions
|
@ -1020,3 +1020,35 @@ function killit()
|
||||||
-- TODO: guard against deletion of player sprite?
|
-- TODO: guard against deletion of player sprite?
|
||||||
error(true)
|
error(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Per-actor variable
|
||||||
|
-- TODO: serialization
|
||||||
|
local peractorvar_mt = {
|
||||||
|
__index = function(acv, idx)
|
||||||
|
check_sprite_idx(idx)
|
||||||
|
return acv._defval
|
||||||
|
end,
|
||||||
|
|
||||||
|
__newindex = function(acv, idx, val)
|
||||||
|
check_sprite_idx(idx)
|
||||||
|
acv[idx] = val
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Calling a per-actor variable causes its cleanup:
|
||||||
|
-- * All values for sprite not in the game world are cleared.
|
||||||
|
-- * All values equal to the default one are cleared.
|
||||||
|
__call = function(acv)
|
||||||
|
for i=0,ffiC.MAXSPRITES-1 do
|
||||||
|
if (ffiC.sprite[i].statnum == ffiC.MAXSTATUS or acv[i]==acv._defval) then
|
||||||
|
acv[i] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
__metatable = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
function peractorvar(initval)
|
||||||
|
return setmetatable({ _defval=initval }, peractorvar_mt)
|
||||||
|
end
|
||||||
|
|
|
@ -784,11 +784,14 @@ local player_mt = {
|
||||||
|
|
||||||
addinventory = con._addinventory,
|
addinventory = con._addinventory,
|
||||||
|
|
||||||
pstomp = con._pstomp,
|
stomp = con._pstomp,
|
||||||
|
|
||||||
wack = function(p)
|
-- XXX: is the correct spelling "whack"?
|
||||||
|
wack = function(p, no_return_to_center)
|
||||||
p.horiz = p.horiz + 64
|
p.horiz = p.horiz + 64
|
||||||
p.return_to_center = 9
|
if (not no_return_to_center) then
|
||||||
|
p.return_to_center = 9
|
||||||
|
end
|
||||||
local n = bit.arshift(128-bit.band(ffiC.krand(),255), 1)
|
local n = bit.arshift(128-bit.band(ffiC.krand(),255), 1)
|
||||||
p.rotscrnang = n
|
p.rotscrnang = n
|
||||||
p.look_ang = n
|
p.look_ang = n
|
||||||
|
@ -890,7 +893,7 @@ local function readintostr(fn)
|
||||||
error("INTERNAL ERROR: kfilelength() returned negative length", ERRLEV)
|
error("INTERNAL ERROR: kfilelength() returned negative length", ERRLEV)
|
||||||
end
|
end
|
||||||
|
|
||||||
local str = ffi.new("char [?]", sz) -- XXX: what does it do on out of mem?
|
local str = ffi.new("char [?]", sz)
|
||||||
local readlen = ffiC.kread(fd, str, sz)
|
local readlen = ffiC.kread(fd, str, sz)
|
||||||
|
|
||||||
ffiC.kclose(fd); fd=-1
|
ffiC.kclose(fd); fd=-1
|
||||||
|
@ -905,9 +908,10 @@ end
|
||||||
-- The "require" function accessible to Lunatic code.
|
-- The "require" function accessible to Lunatic code.
|
||||||
-- Base modules in allowed_modules are wrapped so that they cannot be
|
-- Base modules in allowed_modules are wrapped so that they cannot be
|
||||||
-- modified, user modules are searched in the EDuke32 search
|
-- modified, user modules are searched in the EDuke32 search
|
||||||
-- path. Also, our require never messes with the global environment,
|
-- path. Also, our require
|
||||||
-- it only returns the module.
|
-- * never messes with the global environment, it only returns the module.
|
||||||
local function our_require(modname)
|
-- * allows passing varargs beyond the name to the module.
|
||||||
|
local function our_require(modname, ...)
|
||||||
check_valid_modname(modname, 2)
|
check_valid_modname(modname, 2)
|
||||||
|
|
||||||
-- see whether it's a base module name first
|
-- see whether it's a base module name first
|
||||||
|
@ -937,7 +941,7 @@ local function our_require(modname)
|
||||||
table.insert(modname_stack, modname)
|
table.insert(modname_stack, modname)
|
||||||
|
|
||||||
-- Run the module code!
|
-- Run the module code!
|
||||||
modfunc(modname) -- TODO: call protected and report errors here later
|
modfunc(modname, ...) -- TODO: call protected and report errors here later
|
||||||
|
|
||||||
table.remove(modname_stack)
|
table.remove(modname_stack)
|
||||||
|
|
||||||
|
@ -959,9 +963,6 @@ local function our_require(modname)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- _G tweaks -- pull in only 'safe' stuff
|
|
||||||
local G_ = {} -- our soon-to-be global environment
|
|
||||||
|
|
||||||
local module_mt = {
|
local module_mt = {
|
||||||
__index = function (_, n)
|
__index = function (_, n)
|
||||||
error("attempt to read undeclared variable '"..n.."'", 2)
|
error("attempt to read undeclared variable '"..n.."'", 2)
|
||||||
|
@ -1000,6 +1001,10 @@ local function our_error(errmsg, level)
|
||||||
error(errmsg, 2)
|
error(errmsg, 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- _G tweaks -- pull in only 'safe' stuff
|
||||||
|
local G_ = {} -- our soon-to-be global environment
|
||||||
|
|
||||||
G_.assert = assert
|
G_.assert = assert
|
||||||
G_.error = our_error
|
G_.error = our_error
|
||||||
G_.ipairs = ipairs
|
G_.ipairs = ipairs
|
||||||
|
@ -1154,6 +1159,9 @@ do
|
||||||
end
|
end
|
||||||
|
|
||||||
concode = lunacon.compile(confn)
|
concode = lunacon.compile(confn)
|
||||||
|
if (concode == nil) then
|
||||||
|
error("Failure compiling CON code, exiting.", 0)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- change the environment of this chunk to the table G_
|
-- change the environment of this chunk to the table G_
|
||||||
|
|
|
@ -96,15 +96,18 @@ local g_iflevel = 0
|
||||||
local g_ifelselevel = 0
|
local g_ifelselevel = 0
|
||||||
|
|
||||||
---=== Code generation ===---
|
---=== Code generation ===---
|
||||||
|
local GVFLAG = { PERPLAYER=1, PERACTOR=2, PERX_MASK=3, }
|
||||||
|
|
||||||
-- CON --> mangled Lua function name, also existence check:
|
-- CON --> mangled Lua function name, also existence check:
|
||||||
local g_funcname = {}
|
local g_funcname = {}
|
||||||
|
-- [identifier] = { name=<mangled name>, flags=<gamevar flags> }
|
||||||
|
local g_gamevar = {}
|
||||||
|
|
||||||
local g_have_file = {} -- [filename]=true
|
local g_have_file = {} -- [filename]=true
|
||||||
local g_curcode = nil -- a table of string pieces or other "gencode" tables
|
local g_curcode = nil -- a table of string pieces or other "gencode" tables
|
||||||
|
|
||||||
local g_actor_code = {} -- [actornum]=gencode_table
|
-- [{actor, event, actor}num]=gencode_table
|
||||||
local g_event_code = {} -- [eventnum]=gencode_table
|
local g_code = { actor={}, event={}, loadactor={} }
|
||||||
local g_loadactor_code = {} -- [actornum]=gencode_table
|
|
||||||
|
|
||||||
|
|
||||||
local function getlinecol(pos) end -- fwd-decl
|
local function getlinecol(pos) end -- fwd-decl
|
||||||
|
@ -119,10 +122,11 @@ end
|
||||||
|
|
||||||
local function reset_codegen()
|
local function reset_codegen()
|
||||||
g_funcname = {}
|
g_funcname = {}
|
||||||
|
g_gamevar = {}
|
||||||
|
|
||||||
g_have_file = {}
|
g_have_file = {}
|
||||||
g_curcode = new_initial_codetab()
|
g_curcode = new_initial_codetab()
|
||||||
g_actor_code, g_event_code, g_loadactor_code = {}, {}, {}
|
g_code.actor, g_code.event, g_code.loadactor = {}, {}, {}
|
||||||
|
|
||||||
g_recurslevel = -1
|
g_recurslevel = -1
|
||||||
g_numerrors = 0
|
g_numerrors = 0
|
||||||
|
@ -163,7 +167,7 @@ local function on_actor_end(usertype, tsamm, codetab)
|
||||||
addcodef("gameactor(%d,%sfunction(_aci, _pli, _dist)", tilenum, str)
|
addcodef("gameactor(%d,%sfunction(_aci, _pli, _dist)", tilenum, str)
|
||||||
add_code_and_end(codetab, "end)")
|
add_code_and_end(codetab, "end)")
|
||||||
|
|
||||||
g_actor_code[tilenum] = codetab
|
g_code.actor[tilenum] = codetab
|
||||||
end
|
end
|
||||||
|
|
||||||
local BAD_ID_CHARS0 = "_/\\*?" -- allowed 1st identifier chars
|
local BAD_ID_CHARS0 = "_/\\*?" -- allowed 1st identifier chars
|
||||||
|
@ -193,7 +197,7 @@ local function on_event_end(eventidx, codetab)
|
||||||
addcodef("gameevent(%d, function (_aci, _pli, _dist)", eventidx)
|
addcodef("gameevent(%d, function (_aci, _pli, _dist)", eventidx)
|
||||||
add_code_and_end(codetab, "end)")
|
add_code_and_end(codetab, "end)")
|
||||||
|
|
||||||
g_event_code[eventidx] = codetab
|
g_code.event[eventidx] = codetab
|
||||||
end
|
end
|
||||||
|
|
||||||
----------
|
----------
|
||||||
|
@ -318,6 +322,10 @@ local function do_define_label(identifier, num)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
if (g_gamevar[identifier]) then
|
||||||
|
warnprintf("symbol `%s' already used for game variable", identifier)
|
||||||
|
end
|
||||||
|
|
||||||
-- New definition of a label
|
-- New definition of a label
|
||||||
g_labeldef[identifier] = num
|
g_labeldef[identifier] = num
|
||||||
g_labeltype[identifier] = LABEL.NUMBER
|
g_labeltype[identifier] = LABEL.NUMBER
|
||||||
|
@ -646,6 +654,73 @@ local function cmd_music(volnum, ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- GAMEVARS / GAMEARRAYS
|
||||||
|
|
||||||
|
local function cmd_gamevar(identifier, initval, flags)
|
||||||
|
local invalid_code = "local _INVALIDGV"
|
||||||
|
|
||||||
|
if (bit.band(flags, bit.bnot(GVFLAG.PERX_MASK)) ~= 0) then
|
||||||
|
-- TODO: a couple of the presumably safe ones
|
||||||
|
errprintf("gamevar flags other than PERPLAYER or PERACTOR: NYI or forbidden")
|
||||||
|
return invalid_code
|
||||||
|
end
|
||||||
|
|
||||||
|
if (flags==GVFLAG.PERPLAYER+GVFLAG.PERACTOR) then
|
||||||
|
errprintf("invalid gamevar flags: must be either PERPLAYER or PERACTOR, not both")
|
||||||
|
return invalid_code
|
||||||
|
end
|
||||||
|
|
||||||
|
local ogv = g_gamevar[identifier]
|
||||||
|
|
||||||
|
if (ogv ~= nil) then
|
||||||
|
if (ogv.flags ~= flags) then
|
||||||
|
errprintf("duplicate gamevar definition `%s' has different flags", identifier)
|
||||||
|
return invalid_code
|
||||||
|
else
|
||||||
|
warnprintf("duplicate gamevar definition `%s' ignored", identifier)
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local ltype = g_labeltype[identifier]
|
||||||
|
if (ltype ~= nil) then
|
||||||
|
warnprintf("symbol `%s' already used for a defined %s", identifier, LABEL[ltype])
|
||||||
|
end
|
||||||
|
|
||||||
|
local gv = { name=mangle_name(identifier, "V"), flags=flags }
|
||||||
|
g_gamevar[identifier] = gv
|
||||||
|
|
||||||
|
-- TODO: Write gamevar system on the Lunatic side and hook it up.
|
||||||
|
-- TODO: per-player gamevars
|
||||||
|
if (flags==GVFLAG.PERACTOR) then
|
||||||
|
return format("local %s=_con.peractorvar(%d)", gv.name, initval)
|
||||||
|
else
|
||||||
|
return format("local %s=%d", gv.name, initval)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function lookup_gamevar(identifier)
|
||||||
|
local gv = g_gamevar[identifier]
|
||||||
|
|
||||||
|
if (gv == nil) then
|
||||||
|
errprintf("symbol `%s' is not a game variable", identifier)
|
||||||
|
return "_INVALIDGV"
|
||||||
|
end
|
||||||
|
|
||||||
|
if (gv.flags==GVFLAG.PERACTOR) then
|
||||||
|
return format("%s[_aci]", gv.name)
|
||||||
|
else
|
||||||
|
return gv.name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function maybe_gamevar_Cmt(subj, pos, identifier)
|
||||||
|
if (g_gamevar[identifier]) then
|
||||||
|
return true, lookup_gamevar(identifier)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
----==== patterns ====----
|
----==== patterns ====----
|
||||||
|
|
||||||
---- basic ones
|
---- basic ones
|
||||||
|
@ -665,12 +740,10 @@ local alpha = Range("AZ", "az") -- locale?
|
||||||
local alphanum = alpha + Range("09")
|
local alphanum = alpha + Range("09")
|
||||||
--local alnumtok = alphanum + Set("{}/\\*-_.") -- see isaltok() in gamedef.c
|
--local alnumtok = alphanum + Set("{}/\\*-_.") -- see isaltok() in gamedef.c
|
||||||
|
|
||||||
--- basic lexical elements ("tokens")
|
--- Basic lexical elements ("tokens"). See the final grammar ("Grammar") for
|
||||||
|
--- their definitions.
|
||||||
local t_maybe_minus = (Pat("-") * sp0)^-1;
|
local t_maybe_minus = (Pat("-") * sp0)^-1;
|
||||||
local t_number = POS() * lpeg.C(
|
local t_number = Var("t_number")
|
||||||
t_maybe_minus * ((Pat("0x") + "0X") * Range("09", "af", "AF")^1 * Pat("h")^-1
|
|
||||||
+ Range("09")^1)
|
|
||||||
) / parse_number
|
|
||||||
-- Valid identifier names are disjunct from keywords!
|
-- Valid identifier names are disjunct from keywords!
|
||||||
-- XXX: CON is more permissive with identifier name characters:
|
-- XXX: CON is more permissive with identifier name characters:
|
||||||
local t_identifier = Var("t_identifier")
|
local t_identifier = Var("t_identifier")
|
||||||
|
@ -687,12 +760,8 @@ local t_newline_term_str = match_until(anychar, newline)
|
||||||
-- new-style inline arrays and structures:
|
-- new-style inline arrays and structures:
|
||||||
local t_arrayexp = Var("t_arrayexp")
|
local t_arrayexp = Var("t_arrayexp")
|
||||||
|
|
||||||
-- defines and constants can take the place of vars that are only read:
|
local t_rvar = Var("t_rvar")
|
||||||
-- NOTE: when one of t_identifier+t_define matches, we don't actually know
|
local t_wvar = Var("t_wvar")
|
||||||
-- whether it's the right one yet, since their syntax overlaps.
|
|
||||||
local t_rvar = t_arrayexp + t_identifier + t_define
|
|
||||||
-- not so with written-to vars:
|
|
||||||
local t_wvar = t_arrayexp + t_identifier
|
|
||||||
|
|
||||||
|
|
||||||
---- helper patterns / pattern constructing functions
|
---- helper patterns / pattern constructing functions
|
||||||
|
@ -784,7 +853,7 @@ local Co = {
|
||||||
spriteflags = cmd(D,D), -- also see inner
|
spriteflags = cmd(D,D), -- also see inner
|
||||||
|
|
||||||
--- 4. Game Variables / Arrays
|
--- 4. Game Variables / Arrays
|
||||||
gamevar = cmd(I,D,D),
|
gamevar = cmd(I,D,D) / cmd_gamevar,
|
||||||
gamearray = cmd(I,D),
|
gamearray = cmd(I,D),
|
||||||
|
|
||||||
--- 5. Top level commands that are also run-time commands
|
--- 5. Top level commands that are also run-time commands
|
||||||
|
@ -1096,7 +1165,7 @@ local Ci = {
|
||||||
pkick = cmd()
|
pkick = cmd()
|
||||||
/ format("_con._pkick(%s,%s)", PLS"", ACS""),
|
/ format("_con._pkick(%s,%s)", PLS"", ACS""),
|
||||||
pstomp = cmd()
|
pstomp = cmd()
|
||||||
/ PLS":pstomp(_aci)",
|
/ PLS":stomp(_aci)",
|
||||||
resetactioncount = cmd()
|
resetactioncount = cmd()
|
||||||
/ ACS":reset_acount()",
|
/ ACS":reset_acount()",
|
||||||
resetcount = cmd()
|
resetcount = cmd()
|
||||||
|
@ -1668,6 +1737,11 @@ local Grammar = Pat{
|
||||||
-- NOTE: NW demo (NWSNOW.CON) contains a Ctrl-Z char (decimal 26)
|
-- NOTE: NW demo (NWSNOW.CON) contains a Ctrl-Z char (decimal 26)
|
||||||
whitespace = Set(" \t\r\26") + newline + Set("(),;") + comment + linecomment,
|
whitespace = Set(" \t\r\26") + newline + Set("(),;") + comment + linecomment,
|
||||||
|
|
||||||
|
t_number = POS() * lpeg.C(
|
||||||
|
t_maybe_minus * ((Pat("0x") + "0X") * Range("09", "af", "AF")^1 * Pat("h")^-1
|
||||||
|
+ Range("09")^1)
|
||||||
|
) / parse_number,
|
||||||
|
|
||||||
t_identifier_all = t_broken_identifier + t_good_identifier,
|
t_identifier_all = t_broken_identifier + t_good_identifier,
|
||||||
-- NOTE: -conl.keyword alone would be wrong, e.g. "state breakobject":
|
-- NOTE: -conl.keyword alone would be wrong, e.g. "state breakobject":
|
||||||
-- NOTE 2: The + "[" is so that stuff like
|
-- NOTE 2: The + "[" is so that stuff like
|
||||||
|
@ -1680,6 +1754,12 @@ local Grammar = Pat{
|
||||||
t_identifier = -NotKeyw(conl.keyword * (sp1 + "[")) * lpeg.C(t_identifier_all),
|
t_identifier = -NotKeyw(conl.keyword * (sp1 + "[")) * lpeg.C(t_identifier_all),
|
||||||
t_define = (POS() * lpeg.C(t_maybe_minus) * t_identifier / lookup_defined_label) + t_number,
|
t_define = (POS() * lpeg.C(t_maybe_minus) * t_identifier / lookup_defined_label) + t_number,
|
||||||
|
|
||||||
|
-- Defines and constants can take the place of vars that are only read.
|
||||||
|
-- XXX: now, when t_rvar fails, the t_define failure message is printed.
|
||||||
|
t_rvar = t_arrayexp + lpeg.Cmt(t_identifier, maybe_gamevar_Cmt) + t_define,
|
||||||
|
-- not so with written-to vars:
|
||||||
|
t_wvar = t_arrayexp + (t_identifier/lookup_gamevar),
|
||||||
|
|
||||||
t_move =
|
t_move =
|
||||||
POS()*t_identifier / function(...) return lookup_composite(LABEL.MOVE, ...) end +
|
POS()*t_identifier / function(...) return lookup_composite(LABEL.MOVE, ...) end +
|
||||||
POS()*t_number / function(...) return check_composite_literal(LABEL.MOVE, ...) end,
|
POS()*t_number / function(...) return check_composite_literal(LABEL.MOVE, ...) end,
|
||||||
|
@ -1780,6 +1860,17 @@ local function get_code_string(codetab)
|
||||||
return table.concat(flatten_codetab(g_curcode), "\n")
|
return table.concat(flatten_codetab(g_curcode), "\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function on_parse_begin()
|
||||||
|
g_iflevel = 0
|
||||||
|
g_ifelselevel = 0
|
||||||
|
g_have_file[g_filename] = true
|
||||||
|
|
||||||
|
-- set up new state
|
||||||
|
-- TODO: pack into one "parser state" table?
|
||||||
|
g_lastkw, g_lastkwpos, g_numerrors = nil, nil, 0
|
||||||
|
g_recurslevel = g_recurslevel+1
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
---=== EXPORTED FUNCTIONS ===---
|
---=== EXPORTED FUNCTIONS ===---
|
||||||
|
|
||||||
|
@ -1790,17 +1881,10 @@ function parse(contents) -- local
|
||||||
local lastkw, lastkwpos, numerrors = g_lastkw, g_lastkwpos, g_numerrors
|
local lastkw, lastkwpos, numerrors = g_lastkw, g_lastkwpos, g_numerrors
|
||||||
local newlineidxs = g_newlineidxs
|
local newlineidxs = g_newlineidxs
|
||||||
|
|
||||||
g_iflevel = 0
|
on_parse_begin()
|
||||||
g_ifelselevel = 0
|
|
||||||
g_have_file[g_filename] = true
|
|
||||||
|
|
||||||
-- set up new state
|
|
||||||
-- TODO: pack into one "parser state" table?
|
|
||||||
g_lastkw, g_lastkwpos, g_numerrors = nil, nil, 0
|
|
||||||
g_newlineidxs = setup_newlineidxs(contents)
|
g_newlineidxs = setup_newlineidxs(contents)
|
||||||
|
|
||||||
g_recurslevel = g_recurslevel+1
|
|
||||||
|
|
||||||
addcodef("-- BEGIN %s", g_filename)
|
addcodef("-- BEGIN %s", g_filename)
|
||||||
|
|
||||||
local idx = lpeg.match(Grammar, contents)
|
local idx = lpeg.match(Grammar, contents)
|
||||||
|
|
Loading…
Reference in a new issue