Lunatic: actor usertypes from CON, set SFLAGs as 2nd gameactor() arg in Lua.

In passing, fix a couple of omissions: gameactor() being passed nil's in the
middle, more than one moveflag to CON *actor.

git-svn-id: https://svn.eduke32.com/eduke32@3597 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2013-03-24 18:53:28 +00:00
parent 290eb3a962
commit efbc4cec90
7 changed files with 168 additions and 73 deletions

View file

@ -8149,10 +8149,7 @@ void A_PlayAlertSound(int32_t i)
int32_t A_CheckEnemyTile(int32_t pn)
{
if (g_tile[pn].flags & SPRITE_HARDCODED_BADGUY)
return 1;
return A_CheckSpriteTileFlags(pn, SPRITE_BADGUY);
return ((g_tile[pn].flags & (SPRITE_HARDCODED_BADGUY|SPRITE_BADGUY)) != 0);
}
int32_t A_CheckSwitchTile(int32_t i)

View file

@ -4,6 +4,7 @@ local lpeg = require("lpeg")
local pairs = pairs
local print = print
local setmetatable = setmetatable
local type = type
@ -197,26 +198,28 @@ EVENT = {
EVENT_CHANGEMENU = 94,
}
local SFLAG = {
-- NOTE: negated values are not exported to the ffi.C namespace or CON.
-- See TWEAK_SFLAG below.
SFLAG = {
SFLAG_SHADOW = 0x00000001,
SFLAG_NVG = 0x00000002,
SFLAG_NOSHADE = 0x00000004,
-- SFLAG_PROJECTILE = 0x00000008,
-- SFLAG_DECAL = 0x00000010,
SFLAG_PROJECTILE = -0x00000008,
SFLAG_DECAL = -0x00000010,
SFLAG_BADGUY = 0x00000020,
SFLAG_NOPAL = 0x00000040,
SFLAG_NOEVENTS = 0x00000080, -- NAME
SFLAG_NOEVENTS = 0x00000080, -- NAME
SFLAG_NOLIGHT = 0x00000100,
SFLAG_USEACTIVATOR = 0x00000200,
-- SFLAG_NULL = 0x00000400,
SFLAG_NULL = -0x00000400,
SFLAG_NOCLIP = 0x00000800,
-- SFLAG_NOFLOORSHADOW = 0x00001000,
SFLAG_NOFLOORSHADOW = -0x00001000,
SFLAG_SMOOTHMOVE = 0x00002000,
SFLAG_NOTELEPORT = 0x00004000,
-- SFLAG_BADGUYSTAYPUT = 0x00008000,
-- SFLAG_CACHE = 0x00010000,
-- SFLAG_ROTFIXED = 0x00020000,
-- SPRITE_HARDCODED_BADGUY= 0x00040000,
SFLAG_BADGUYSTAYPUT = -0x00008000,
SFLAG_CACHE = -0x00010000,
SFLAG_ROTFIXED = -0x00020000,
SFLAG_HARDCODED_BADGUY = -0x00040000,
}
STAT = {
@ -297,6 +300,14 @@ local GAMEFUNC = {
GAMEFUNC_DPAD_AIMING = 55,
}
local function shallow_copy(tab)
local t = {}
for k,v in pairs(tab) do
t[k] = v
end
return t
end
-- KEEPINSYNC with gamedef.c:C_AddDefaultDefinitions() and the respective
-- defines. These are exported to the ffi.C namespace and as literal defines
-- in lunacon.lua.
@ -305,11 +316,19 @@ labels =
STR,
PROJ,
EVENT,
SFLAG,
setmetatable(shallow_copy(SFLAG), { __metatable="noffiC" }),
STAT,
GAMEFUNC,
}
-- TWEAK_SFLAG
for name, flag in pairs(SFLAG) do
if (flag < 0) then
SFLAG[name] = -flag
labels[4][name] = nil
end
end
-- KEEPINSYNC player.h
wdata_members =
{

View file

@ -273,11 +273,10 @@ function _shoot(i, tilenum, zvel)
return CF.A_ShootWithZvel(i, tilenum, zvel)
end
local BADGUY_MASK = bit.bor(con_lang.SFLAG.SFLAG_HARDCODED_BADGUY, con_lang.SFLAG.SFLAG_BADGUY)
function isenemytile(tilenum)
if (bit.band(ffiC.g_tile[tilenum].flags, 0x00040000)~=0) then
return true
end
return (bit.band(ffiC.g_tile[tilenum].flags, ffiC.SFLAG_BADGUY)~=0)
return (bit.band(ffiC.g_tile[tilenum].flags, BADGUY_MASK)~=0)
end
function rotatesprite(x, y, zoom, ang, tilenum, shade, pal, orientation,

View file

@ -12,11 +12,13 @@ local math = math
local assert = assert
local error = error
local getmetatable = getmetatable
local ipairs = ipairs
local loadstring = loadstring
local pairs = pairs
local rawget = rawget
local rawset = rawset
local select = select
local setmetatable = setmetatable
local setfenv = setfenv
local tonumber = tonumber
@ -683,23 +685,50 @@ player_static_members.INPUT_BITS = defs_c.conststruct
player_static_members.INPUT_EXT_BITS = defs_c.conststruct
{
INPUT_MOVE_FORWARD = 1,
INPUT_MOVE_BACKWARD = 2,
INPUT_STRAFE_LEFT = 4,
INPUT_STRAFE_RIGHT = 8,
INPUT_TURN_LEFT = 16,
INPUT_TURN_RIGHT = 32,
MOVE_FORWARD = 1,
MOVE_BACKWARD = 2,
STRAFE_LEFT = 4,
STRAFE_RIGHT = 8,
TURN_LEFT = 16,
TURN_RIGHT = 32,
}
-- Actor flags
local actor_static_members = {}
do
local our_SFLAG = {}
local ext_SFLAG = con_lang.labels[4] -- external actor flags only
local USER_MASK = 0
for name, flag in pairs(ext_SFLAG) do
our_SFLAG[name:sub(7)] = flag -- strip "SFLAG_"
USER_MASK = bit.bor(USER_MASK, flag)
end
-- Add a couple of convenience defines.
our_SFLAG.enemy = con_lang.SFLAG.SFLAG_BADGUY
our_SFLAG.enemystayput = con_lang.SFLAG.SFLAG_BADGUY + con_lang.SFLAG.SFLAG_BADGUYSTAYPUT
our_SFLAG.rotfixed = con_lang.SFLAG.SFLAG_ROTFIXED
-- XXX: CON doesn't export BADGUYSTAYPUT or ROTFIXED SFLAGs, but they are considered
-- external for Lunatic.
our_SFLAG.USER_MASK = bit.bor(USER_MASK, our_SFLAG.enemystayput, our_SFLAG.rotfixed)
actor_static_members.FLAGS = defs_c.conststruct(our_SFLAG)
end
local tile_static_members = {}
tile_static_members.sizx = defs_c.creategtab(ffiC.tilesizx, ffiC.MAXTILES, "tilesizx[]")
tile_static_members.sizy = defs_c.creategtab(ffiC.tilesizy, ffiC.MAXTILES, "tilesizy[]")
do
tile_static_members.sizx = defs_c.creategtab(ffiC.tilesizx, ffiC.MAXTILES, "tilesizx[]")
tile_static_members.sizy = defs_c.creategtab(ffiC.tilesizy, ffiC.MAXTILES, "tilesizy[]")
end
-- XXX: error message will say "g_player_ps"
player = setmtonce({}, defs_c.GenStructMetatable("g_player_ps", "playerswhenstarted", player_static_members))
-- needed by "control"
actor = defs_c.creategtab(ffiC.actor, ffiC.MAXSPRITES, "actor[]")
actor = setmtonce({}, defs_c.GenStructMetatable("actor", "MAXSPRITES", actor_static_members))
local BNOT_SFLAG_USER_MASK = bit.bnot(actor.FLAGS.USER_MASK)
local projectile = defs_c.creategtab(ffiC.ProjectileData, ffiC.MAXTILES, "projectile[]")
local g_tile = setmtonce({}, defs_c.GenStructMetatable("g_tile", "MAXTILES", tile_static_members))
@ -1172,14 +1201,15 @@ end
-- Declare all con_lang.labels constants in the global FFI namespace.
for i=1,#con_lang.labels do
local strbuf = {"enum {"}
if (getmetatable(con_lang.labels[i]) ~= "noffiC") then
local strbuf = {"enum {"}
for label, val in pairs(con_lang.labels[i]) do
strbuf[#strbuf+1] = string.format("%s = %d,", label, val)
end
strbuf[#strbuf+1] = "};"
for label, val in pairs(con_lang.labels[i]) do
strbuf[#strbuf+1] = string.format("%s = %d,", label, val)
ffi.cdef(table.concat(strbuf))
end
strbuf[#strbuf+1] = "};"
ffi.cdef(table.concat(strbuf))
end
@ -1201,16 +1231,20 @@ local allowed_modules = {
con = con,
}
for modname, themodule in pairs(allowed_modules) do
local mt = {
__index = themodule,
__newindex = function(tab,idx,val)
error("modifying base module table forbidden", 2)
end,
}
-- Protect base modules.
do
local function basemodule_newindex()
error("modifying base module table forbidden", 2)
end
-- Comment out to make base modules not protected:
allowed_modules[modname] = setmtonce({}, mt)
for modname, themodule in pairs(allowed_modules) do
local mt = {
__index = themodule,
__newindex = basemodule_newindex,
}
allowed_modules[modname] = setmtonce({}, mt)
end
end
local function check_valid_modname(modname, errlev)
@ -1396,34 +1430,49 @@ G_._VERSION = _VERSION
G_._G = G_
local gameactor_internal = gameactor_internal -- included in lunatic.c
-- gameactor(tilenum [, strength [, act [, mov [, movflags]]]], actor_func)
-- gameactor(tilenum [, flags [, strength [, act [, mov [, movflags]]]]], actor_func)
local function our_gameactor(tilenum, ...)
bcheck.top_level("gameactor")
local args = {...}
if (type(tilenum) ~= "number") then
error("invalid argument #1 to gameactor: must be a number", 2)
end
if (tilenum >= ffiC.MAXTILES+0ULL) then
error("invalid argument #1 to gameactor: must be a tile number (0 .. MAXTILES-1)", 2)
error("invalid argument #1 to gameactor: must be a tile number [0..gv.MAXTILES-1]", 2)
end
if (#args == 0) then
local args = {...}
-- Number of varargs; args may have nil's in the middle!
local numargs = select('#', ...)
if (numargs == 0) then
error("invalid call to gameactor: must have at least two arguments (tilenum, func)", 2)
end
if (#args > 5) then
error("invalid call to gameactor: must have at most six arguments", 2)
if (numargs >= 7) then -- sic, because tilenum isn't counted!
error("invalid call to gameactor: must have at most 7 arguments", 2)
end
if (type(args[#args]) ~= "function") then
if (type(args[numargs]) ~= "function") then
error("invalid last argument to gameactor: must be a function", 2)
end
local strength = (#args >= 2) and args[1] or 0
local flags = (numargs > 1) and args[1] or 0
if (type(flags) ~= "number") then
error("invalid 'flags' argument to gameactor: must be a number", 2)
end
local flags_rbits = bit.band(flags, BNOT_SFLAG_USER_MASK)
if (flags_rbits ~= 0) then
error("invalid 'flags' argument to gameactor: must not set reserved bits (0x"
..(bit.tohex(flags_rbits))..")", 2)
end
local strength = (numargs > 2) and args[2] or 0
if (type(strength) ~= "number") then
error("invalid 'strength' argument to gameactor: must be a number", 2)
end
-- TODO: literal number action other than 0?
local act = (#args >= 3) and args[2] or "NO"
local act = (numargs > 3) and args[3] or "NO"
if (type(act)=="string") then
act = AC[act]
end
@ -1432,7 +1481,7 @@ local function our_gameactor(tilenum, ...)
end
-- TODO: literal number move other than 0?
local mov = (#args >= 4) and args[3] or "NO"
local mov = (numargs > 4) and args[4] or "NO"
if (type(mov)=="string") then
mov = MV[mov]
end
@ -1440,12 +1489,17 @@ local function our_gameactor(tilenum, ...)
error("invalid 'mov' argument to gameactor: must be a string or move", 2)
end
local movflags = (#args >= 5) and args[4] or 0
local movflags = (numargs > 5) and args[5] or 0
if (type(movflags) ~= "number") then
error("invalid 'movflags' argument to gameactor: must be a number", 2)
end
gameactor_internal(tilenum, strength, act, mov, movflags, args[#args])
-- All good, set the tile bits and register the actor!
local tile = ffiC.g_tile[tilenum]
tile.flags = bit.bor(tile.flags, flags)
gameactor_internal(tilenum, strength, act, mov, movflags, args[numargs])
end
-- Event functions, saved for event chaining
@ -1565,9 +1619,8 @@ end
-- error(..., 2) is to blame the caller and get its line numbers
gv = gv_
local tmpmt = {
__index = function(gv, key)
__index = function(_, key)
if (gv_access[key] == nil) then
return ffiC[key]
end
@ -1578,7 +1631,7 @@ local tmpmt = {
error("access forbidden", 2)
end,
__newindex = function(gv, key, val)
__newindex = function(_, key, val)
if (gv_access[key] == nil) then
-- Read-only vars handled by LuaJIT.
ffiC[key] = val
@ -1587,7 +1640,7 @@ local tmpmt = {
end
end,
}
setmtonce(gv, tmpmt)
gv = setmtonce(gv_, tmpmt)
-- This will create 'sprite', 'wall', etc. HERE, i.e. in the environment of this chunk
defs_c.create_globals(_G)

View file

@ -341,10 +341,32 @@ local function warnprintf() end -- fwd-decl
local on = {}
-- Map from CON actor usertype to SFLAGs.
local MAP_ACTOR_FLAGS = {
[0] = 0,
[1] = conl.SFLAG.SFLAG_BADGUY,
[2] = conl.SFLAG.SFLAG_BADGUY + conl.SFLAG.SFLAG_BADGUYSTAYPUT,
[3] = conl.SFLAG.SFLAG_BADGUY + conl.SFLAG.SFLAG_BADGUYSTAYPUT,
}
for i=4,7 do
MAP_ACTOR_FLAGS[i] = MAP_ACTOR_FLAGS[i-4] + conl.SFLAG.SFLAG_ROTFIXED
end
function on.actor_end(usertype, tsamm, codetab)
local tilenum = tsamm[1]
local flags = 0
local str = ""
if (usertype ~= nil) then -- useractor
if (not (bit.band(usertype, bit.bnot(7)) == 0)) then
-- XXX: position will be that of last command in actor code
errprintf("invalid usertype: must be bitwise OR of 1, 2 and/or 4")
else
flags = MAP_ACTOR_FLAGS[usertype]
end
end
local str = flags..","
for i=2,math.min(#tsamm,4) do
if ((i==3 or i==4) and tsamm[i]=="0") then
-- HACK, gameactor() currently doesn't support literals for actions
@ -353,12 +375,11 @@ function on.actor_end(usertype, tsamm, codetab)
end
str = str .. tostring(tsamm[i])..","
end
if (#tsamm==5) then
local flags = bit.bor(unpack(tsamm, 5))
str = str .. flags..","
if (#tsamm >= 5) then
local movflags = bit.bor(unpack(tsamm, 5))
str = str .. movflags..","
end
-- TODO: usertype (is non-nil only for 'useractor')
addcodef("gameactor(%d,%sfunction(_aci, _pli, _dist)", tilenum, str)
addcode(get_cache_sap_code())
add_code_and_end(codetab, "end)")
@ -2355,7 +2376,6 @@ local Cif = {
/ format("_con._angdiffabs(%s,%s)<=%%1", PLS".ang", SPS".ang"),
ifsound = cmd(D)
/ "_con._soundplaying(_aci,%1)",
-- vvv TODO: this is not correct for GET_ACCESS or GET_SHIELD.
ifpinventory = cmd(D,D)
/ format("_con._checkpinventory(%s,%%1,%%2,_aci)", PLS""),

View file

@ -110,9 +110,6 @@ local unsafe = pcall(function() string.UNSAFE=true; end)
-- direct gv array access forbidden
checkfail('gv.sprite[0].yrepeat = 100', "access forbidden")
-- indexing struct array with non-numeric type
checkfail('local i = sprite["qwe"]') -- this will produce an error inside the sprite metatable
checkfail('print(sprite[100000].ceilingpal)', "out-of-bounds sprite[] read access")
checkfail('print(gv.sprite[0])', "access forbidden")
@ -129,7 +126,7 @@ checkfail('sector[-1].ceilingpal = 4', "out-of-bounds sector[] read access")
checkfail('sector[0].wallnum = 0', "attempt to write to constant location") -- this comes from LJ/FFI
-- gv.numsectors is read-only
checkfail('gv.numsectors = 4', "write access forbidden")
checkfail('gv.numsectors = 4', "attempt to write to constant location")
-- cannot create new fields in 'gv'
checkfail('gv.QWE = 4', "write access forbidden")
@ -153,7 +150,7 @@ checkfail('wall[4].QWE = 123', "has no member named 'QWE'")
checkfail("new_global = 345", "attempt to write to undeclared variable 'new_global'")
-- can't redefine constants in 'gv'
checkfail('gv.CEILING = 3', "write access forbidden")
checkfail('gv.CEILING = 3', "attempt to write to constant location")
-- string.dump is unavailable
checkfail('local s=require[[string]]; local tmp=s.dump(gameevent)',
@ -174,7 +171,7 @@ checkfail('gv.luaJIT_setmode(nil, 0, 0)', "missing declaration for symbol 'luaJI
checkfail('gv.luaJIT_BC_con_lang', "attempt to call a nil value")
checkfail('gv.yax_getbunch(0,0)', "access forbidden")
checkfail('gv.gethitickms = nil', "write access forbidden")
checkfail('gv.gethitickms = nil', "attempt to write to constant location")
-- actor[].t_data[] is not accessible for now
checkfail('local i = actor[0].t_data[15]', "has no member named 't_data'")
@ -191,6 +188,7 @@ checkfail("do local ud=gv.ud.camerasprite; end", "access forbidden") -- test fo
checkfail("sprite[0]:set_picnum(-10)", "invalid tile number")
checkfail("gv.g_sizes_of=nil; print(gv.g_sizes_of[0])", "write access forbidden")
checkfail("gv.cam.sect=-1", "invalid sector number")
checkfail("local flag=gv.SFLAG_NULL", "missing declaration")
printf('ceilingbunch of sector 0: %d', getbunch(0, gv.CEILING))
@ -339,7 +337,7 @@ gameevent("LOADACTOR", function(i)
end
end)
gameactor(930, 1, function(i) -- "police line" ribbon
gameactor(930, nil, 1, function(i) -- "police line" ribbon
local spr = sprite[i]
local r = math.random
local d = 20
@ -365,7 +363,9 @@ con.ai("AITEMP", "TROOPFLINTCH", "SHRUNKVELS", 0)
local TROOPSTRENGTH = 30
gameactor(1680, TROOPSTRENGTH, "TROOPSTAND", -- LIZTROOP
local AF = actor.FLAGS
gameactor(1680, AF.enemy, TROOPSTRENGTH, "TROOPSTAND", -- LIZTROOP
function(i, playeri, dist)
spriteext[i]:make_animated()

View file

@ -20,3 +20,10 @@ useractor 4 58 1 NO NO 0
state killme
enda
// Test useractor type "enemy"
define CYCLOIDHEAD 490
// Will have a flat-sprite-on-floor shadow and be an autoaim target.
useractor 1 CYCLOIDHEAD 10
state killme
enda