mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-11-10 23:02:03 +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?
|
||||
error(true)
|
||||
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,
|
||||
|
||||
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.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)
|
||||
p.rotscrnang = n
|
||||
p.look_ang = n
|
||||
|
@ -890,7 +893,7 @@ local function readintostr(fn)
|
|||
error("INTERNAL ERROR: kfilelength() returned negative length", ERRLEV)
|
||||
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)
|
||||
|
||||
ffiC.kclose(fd); fd=-1
|
||||
|
@ -905,9 +908,10 @@ end
|
|||
-- The "require" function accessible to Lunatic code.
|
||||
-- Base modules in allowed_modules are wrapped so that they cannot be
|
||||
-- modified, user modules are searched in the EDuke32 search
|
||||
-- path. Also, our require never messes with the global environment,
|
||||
-- it only returns the module.
|
||||
local function our_require(modname)
|
||||
-- path. Also, our require
|
||||
-- * never messes with the global environment, it only returns the module.
|
||||
-- * allows passing varargs beyond the name to the module.
|
||||
local function our_require(modname, ...)
|
||||
check_valid_modname(modname, 2)
|
||||
|
||||
-- see whether it's a base module name first
|
||||
|
@ -937,7 +941,7 @@ local function our_require(modname)
|
|||
table.insert(modname_stack, modname)
|
||||
|
||||
-- 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)
|
||||
|
||||
|
@ -959,9 +963,6 @@ local function our_require(modname)
|
|||
end
|
||||
|
||||
|
||||
-- _G tweaks -- pull in only 'safe' stuff
|
||||
local G_ = {} -- our soon-to-be global environment
|
||||
|
||||
local module_mt = {
|
||||
__index = function (_, n)
|
||||
error("attempt to read undeclared variable '"..n.."'", 2)
|
||||
|
@ -1000,6 +1001,10 @@ local function our_error(errmsg, level)
|
|||
error(errmsg, 2)
|
||||
end
|
||||
|
||||
|
||||
-- _G tweaks -- pull in only 'safe' stuff
|
||||
local G_ = {} -- our soon-to-be global environment
|
||||
|
||||
G_.assert = assert
|
||||
G_.error = our_error
|
||||
G_.ipairs = ipairs
|
||||
|
@ -1154,6 +1159,9 @@ do
|
|||
end
|
||||
|
||||
concode = lunacon.compile(confn)
|
||||
if (concode == nil) then
|
||||
error("Failure compiling CON code, exiting.", 0)
|
||||
end
|
||||
end
|
||||
|
||||
-- change the environment of this chunk to the table G_
|
||||
|
|
|
@ -96,15 +96,18 @@ local g_iflevel = 0
|
|||
local g_ifelselevel = 0
|
||||
|
||||
---=== Code generation ===---
|
||||
local GVFLAG = { PERPLAYER=1, PERACTOR=2, PERX_MASK=3, }
|
||||
|
||||
-- CON --> mangled Lua function name, also existence check:
|
||||
local g_funcname = {}
|
||||
-- [identifier] = { name=<mangled name>, flags=<gamevar flags> }
|
||||
local g_gamevar = {}
|
||||
|
||||
local g_have_file = {} -- [filename]=true
|
||||
local g_curcode = nil -- a table of string pieces or other "gencode" tables
|
||||
|
||||
local g_actor_code = {} -- [actornum]=gencode_table
|
||||
local g_event_code = {} -- [eventnum]=gencode_table
|
||||
local g_loadactor_code = {} -- [actornum]=gencode_table
|
||||
-- [{actor, event, actor}num]=gencode_table
|
||||
local g_code = { actor={}, event={}, loadactor={} }
|
||||
|
||||
|
||||
local function getlinecol(pos) end -- fwd-decl
|
||||
|
@ -119,10 +122,11 @@ end
|
|||
|
||||
local function reset_codegen()
|
||||
g_funcname = {}
|
||||
g_gamevar = {}
|
||||
|
||||
g_have_file = {}
|
||||
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_numerrors = 0
|
||||
|
@ -163,7 +167,7 @@ local function on_actor_end(usertype, tsamm, codetab)
|
|||
addcodef("gameactor(%d,%sfunction(_aci, _pli, _dist)", tilenum, str)
|
||||
add_code_and_end(codetab, "end)")
|
||||
|
||||
g_actor_code[tilenum] = codetab
|
||||
g_code.actor[tilenum] = codetab
|
||||
end
|
||||
|
||||
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)
|
||||
add_code_and_end(codetab, "end)")
|
||||
|
||||
g_event_code[eventidx] = codetab
|
||||
g_code.event[eventidx] = codetab
|
||||
end
|
||||
|
||||
----------
|
||||
|
@ -318,6 +322,10 @@ local function do_define_label(identifier, num)
|
|||
end
|
||||
end
|
||||
else
|
||||
if (g_gamevar[identifier]) then
|
||||
warnprintf("symbol `%s' already used for game variable", identifier)
|
||||
end
|
||||
|
||||
-- New definition of a label
|
||||
g_labeldef[identifier] = num
|
||||
g_labeltype[identifier] = LABEL.NUMBER
|
||||
|
@ -646,6 +654,73 @@ local function cmd_music(volnum, ...)
|
|||
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 ====----
|
||||
|
||||
---- basic ones
|
||||
|
@ -665,12 +740,10 @@ local alpha = Range("AZ", "az") -- locale?
|
|||
local alphanum = alpha + Range("09")
|
||||
--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_number = POS() * lpeg.C(
|
||||
t_maybe_minus * ((Pat("0x") + "0X") * Range("09", "af", "AF")^1 * Pat("h")^-1
|
||||
+ Range("09")^1)
|
||||
) / parse_number
|
||||
local t_number = Var("t_number")
|
||||
-- Valid identifier names are disjunct from keywords!
|
||||
-- XXX: CON is more permissive with identifier name characters:
|
||||
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:
|
||||
local t_arrayexp = Var("t_arrayexp")
|
||||
|
||||
-- defines and constants can take the place of vars that are only read:
|
||||
-- NOTE: when one of t_identifier+t_define matches, we don't actually know
|
||||
-- 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
|
||||
local t_rvar = Var("t_rvar")
|
||||
local t_wvar = Var("t_wvar")
|
||||
|
||||
|
||||
---- helper patterns / pattern constructing functions
|
||||
|
@ -784,7 +853,7 @@ local Co = {
|
|||
spriteflags = cmd(D,D), -- also see inner
|
||||
|
||||
--- 4. Game Variables / Arrays
|
||||
gamevar = cmd(I,D,D),
|
||||
gamevar = cmd(I,D,D) / cmd_gamevar,
|
||||
gamearray = cmd(I,D),
|
||||
|
||||
--- 5. Top level commands that are also run-time commands
|
||||
|
@ -1096,7 +1165,7 @@ local Ci = {
|
|||
pkick = cmd()
|
||||
/ format("_con._pkick(%s,%s)", PLS"", ACS""),
|
||||
pstomp = cmd()
|
||||
/ PLS":pstomp(_aci)",
|
||||
/ PLS":stomp(_aci)",
|
||||
resetactioncount = cmd()
|
||||
/ ACS":reset_acount()",
|
||||
resetcount = cmd()
|
||||
|
@ -1668,6 +1737,11 @@ local Grammar = Pat{
|
|||
-- NOTE: NW demo (NWSNOW.CON) contains a Ctrl-Z char (decimal 26)
|
||||
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,
|
||||
-- NOTE: -conl.keyword alone would be wrong, e.g. "state breakobject":
|
||||
-- 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_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 =
|
||||
POS()*t_identifier / function(...) return lookup_composite(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")
|
||||
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 ===---
|
||||
|
||||
|
@ -1790,17 +1881,10 @@ function parse(contents) -- local
|
|||
local lastkw, lastkwpos, numerrors = g_lastkw, g_lastkwpos, g_numerrors
|
||||
local newlineidxs = g_newlineidxs
|
||||
|
||||
g_iflevel = 0
|
||||
g_ifelselevel = 0
|
||||
g_have_file[g_filename] = true
|
||||
on_parse_begin()
|
||||
|
||||
-- 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_recurslevel = g_recurslevel+1
|
||||
|
||||
addcodef("-- BEGIN %s", g_filename)
|
||||
|
||||
local idx = lpeg.match(Grammar, contents)
|
||||
|
|
Loading…
Reference in a new issue