Lunatic: more complete gameactor(), misc. translator tweaks.

git-svn-id: https://svn.eduke32.com/eduke32@3315 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2012-12-23 19:24:16 +00:00
parent 48c47af5dc
commit 4ea9f799b1
8 changed files with 147 additions and 32 deletions

View file

@ -82,6 +82,9 @@ struct action {
struct move {
int16_t hvel, vvel;
};
typedef struct { int32_t id; struct move mv; } con_move_t;
typedef struct { int32_t id; struct action ac; } con_action_t;
#endif
typedef struct {

View file

@ -4016,6 +4016,20 @@ int32_t A_InsertSprite(int32_t whatsect,int32_t s_x,int32_t s_y,int32_t s_z,int3
#endif
s->hitag = *(g_tile[s_pn].execPtr+3);
}
#ifdef LUNATIC
else if (El_HaveActor(s_pn))
{
// ^^^ C-CON takes precedence for now.
const el_actor_t *a = &g_elActors[s_pn];
s->extra = a->strength;
s->hitag = a->movflags;
T5 = a->act.id;
T2 = a->mov.id;
Bmemcpy(&actor[i].ac, &a->act.ac, sizeof(struct action));
Bmemcpy(&actor[i].mv, &a->mov.mv, sizeof(struct move));
}
#endif
if (show2dsector[SECT>>3]&(1<<(SECT&7))) show2dsprite[i>>3] |= (1<<(i&7));
else show2dsprite[i>>3] &= ~(1<<(i&7));

View file

@ -25,7 +25,11 @@ module(...)
local lastid = { action=0, move=0, ai=0 }
local def = { action={}, move={}, ai={} }
local def = {
action = {NO=ffi.new("con_action_t")},
move = {NO=ffi.new("con_move_t")},
ai = {NO=ffi.new("con_ai_t")},
}
local function forbidden() error("newindex forbidden", 2) end

View file

@ -985,9 +985,57 @@ G_._VERSION = _VERSION
G_._G = G_
local gameactor_internal = gameactor_internal -- included in lunatic.c
-- gameactor(tilenum [, strength [, act [, mov [, movflags]]]], actor_func)
local function our_gameactor(tilenum, ...)
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)
end
if (#args == 0) then
error("invalid call to gameactor: must have at least two arguments (tilenum, func)", 2)
end
if (type(args[#args]) ~= "function") then
error("invalid last argument to gameactor: must be a function", 2)
end
local strength = (#args >= 2) and args[1] 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"
if (type(act)=="string") then
act = AC[act]
end
if (not ffi.istype(con_action_ct, act)) then
error("invalid 'act' argument to gameactor: must be a string or action", 2)
end
-- TODO: literal number move other than 0?
local mov = (#args >= 4) and args[3] or "NO"
if (type(mov)=="string") then
mov = MV[mov]
end
if (not ffi.istype(con_move_ct, mov)) then
error("invalid 'mov' argument to gameactor: must be a string or move", 2)
end
local movflags = (#args >= 5) and args[4] 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])
end
--- non-default data and functions
G_.gameevent = gameevent -- included in lunatic.c
G_.gameactor = gameactor -- included in lunatic.c
G_.gameactor = our_gameactor
G_.player = player -- from above

View file

@ -17,6 +17,7 @@ local pairs = pairs
local pcall = pcall
local print = print
local tonumber = tonumber
local tostring = tostring
local type = type
if (string.dump) then
@ -24,7 +25,7 @@ if (string.dump) then
end
module(...)
module("lunacon")
-- I think that the "too many pending calls/choices" is unavoidable in general.
@ -107,11 +108,26 @@ local function addcodef(fmt, ...)
end
local function on_actor_end(usertype, tsamm, codetab)
-- TODO: strength, action, move, moveflags
local tilenum = tsamm[1]
-- usertype is non-nil only for 'useractor'
addcodef("gameactor(%d, function(_aci, _pli, _dist)", tilenum)
local str = ""
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
tsamm[i] = "'NO'"
end
str = str .. tostring(tsamm[i])..","
end
if (#tsamm==5) then
local flags = 0
for i=5,#tsamm do
flags = bit.bor(flags, tsamm[i])
end
str = str .. flags..","
end
-- TODO: usertype (is non-nil only for 'useractor')
addcodef("gameactor(%d,%sfunction(_aci, _pli, _dist)", tilenum, str)
assert(type(codetab)=="table")
g_actor_code[tilenum] = codetab
@ -121,7 +137,7 @@ end
local function on_state_end(statename, codetab)
-- TODO: mangle names, make them accessible from other translation units
addcodef("local function %s()", statename)
addcodef("local function %s(_aci, _pli, _dist)", statename)
assert(type(codetab)=="table")
addcode(codetab)
addcode("end")
@ -732,7 +748,7 @@ local Ci = {
/ "_con.longjmp()", -- TODO: test with code from Wiki "return" entry
state = cmd(I)
/ "%1()", -- TODO: mangle names
/ "%1(_aci, _pli, _dist)", -- TODO: mangle names
--- 1. get*, set*
getactor = getstructcmd,
@ -930,7 +946,8 @@ local Ci = {
insertspriteq = cmd(),
killit = cmd() -- NLCF
/ "_con.killit()",
mikesnd = cmd(),
mikesnd = cmd()
/ "", -- TODO
nullop = cmd()
/ "", -- NOTE: really generate no code
pkick = cmd()
@ -1095,9 +1112,9 @@ local Cif = {
ifrnd = cmd(D)
/ "_con.rnd(%1)",
ifpdistl = cmd(D)
/ "_dist<%1", -- TODO: maybe set actor[].timetosleep afterwards
/ "_dist<%1", -- TODO: conditionally set actor[].timetosleep afterwards
ifpdistg = cmd(D)
/ "_dist>%1", -- TODO: maybe set actor[].timetosleep afterwards
/ "_dist>%1", -- TODO: conditionally set actor[].timetosleep afterwards
ifactioncount = cmd(D)
/ ACS":get_acount()==%1",
ifcount = cmd(D)
@ -1160,11 +1177,12 @@ local Cif = {
ifoutside = cmd()
/ format("_bit.band(sector[%s].ceilingstat,1)~=0", SPS".sectnum"),
ifonwater = cmd()
/ format("sectnum[%s].lotag==1 and _math.abs(%s-sector[%s].floorz)<32*256",
/ format("sector[%s].lotag==1 and _math.abs(%s-sector[%s].floorz)<32*256",
SPS".sectnum", SPS".z", SPS".sectnum"),
ifnotmoving = cmd()
/ "_bit.band(actor[_aci].movflag,49152)>16384",
ifnosounds = cmd(),
ifnosounds = cmd()
/ "false",
ifmultiplayer = cmd()
/ "false", -- TODO?
ifinwater = cmd()
@ -1182,7 +1200,7 @@ local Cif = {
ifclient = cmd(),
ifcanshoottarget = cmd()
/ "_con._canshoottarget(_dist,_aci)",
ifcanseetarget = cmd() -- TODO: maybe set timetosleep afterwards
ifcanseetarget = cmd() -- TODO: conditionally set timetosleep afterwards
/ format("_con._canseetarget(%s,%s)", SPS"", PLS""),
ifcansee = cmd() * #sp1
/ format("_con._cansee(_aci,%s)", PLS""),
@ -1576,7 +1594,10 @@ end
---=== EXPORTED FUNCTIONS ===---
local function new_initial_perfile_codetab()
return { "local _con=require'con'; local _bit=require'bit'" }
return {
"local _con, _bit, _math = require'con', require'bit', require'math';",
"local sector, sprite, actor, player = sector, sprite, actor, player;"
}
end
function parse(contents) -- local
@ -1713,7 +1734,7 @@ if (string.dump) then
end
--[[
local file = require("io").stdout
local file = require("io").stderr
for filename,codetab in pairs(g_file_code) do
file:write(format("-- GENERATED CODE for \"%s\":\n", filename))
file:write(table.concat(flatten_codetab(codetab), "\n"))
@ -1721,7 +1742,4 @@ if (string.dump) then
end
--]]
end
else
--- embedded
return { parse=parse }
end

View file

@ -19,7 +19,7 @@ L_State g_ElState;
uint8_t g_elEvents[MAXEVENTS];
// same thing for actors:
uint8_t g_elActors[MAXTILES];
el_actor_t g_elActors[MAXTILES];
// for timing events and actors
uint32_t g_eventCalls[MAXEVENTS], g_actorCalls[MAXTILES];
@ -116,7 +116,7 @@ static void El_StateSetup(lua_State *L)
lua_pushcfunction(L, SetEvent_luacf);
lua_setglobal(L, "gameevent");
lua_pushcfunction(L, SetActor_luacf);
lua_setglobal(L, "gameactor");
lua_setglobal(L, "gameactor_internal");
Bassert(lua_gettop(L)==0);
}
@ -152,19 +152,35 @@ static int32_t SetEvent_luacf(lua_State *L)
return 0;
}
// gameactor(<actortile>, lua_function)
// gameactor(actortile, strength, act, mov, movflags, lua_function)
static int32_t SetActor_luacf(lua_State *L)
{
int32_t actortile;
int32_t actortile, strength, movflags;
const con_action_t *act;
const con_move_t *mov;
if (lua_gettop(L) != 2)
luaL_error(L, "gameactor: must pass exactly two arguments");
el_actor_t *a;
Bassert(lua_gettop(L) == 6);
actortile = luaL_checkint(L, 1);
Bassert((unsigned)actortile < MAXTILES);
luaL_argcheck(L, (unsigned)actortile < MAXTILES, 1, "must be an tile number (0 .. MAXTILES-1)");
L_CheckAndRegisterFunction(L, &g_elActors[actortile]);
g_elActors[actortile] = 1;
strength = luaL_checkint(L, 2);
movflags = luaL_checkint(L, 5);
act = lua_topointer(L, 3);
mov = lua_topointer(L, 4);
a = &g_elActors[actortile];
L_CheckAndRegisterFunction(L, a);
a->haveit = 1;
a->strength = strength;
a->movflags = movflags;
Bmemcpy(&a->act, act, sizeof(con_action_t));
Bmemcpy(&a->mov, mov, sizeof(con_move_t));
return 0;
}

View file

@ -9,9 +9,18 @@
extern L_State g_ElState;
// actor initialization data
typedef struct
{
con_move_t mov;
int16_t movflags;
int16_t strength;
con_action_t act;
uint8_t haveit; // shouldn't be used directly
} el_actor_t;
extern uint8_t g_elEvents[MAXEVENTS]; // shouldn't be used directly
extern uint8_t g_elActors[MAXTILES]; // shouldn't be used directly
extern el_actor_t g_elActors[MAXTILES];
extern uint32_t g_eventCalls[MAXEVENTS], g_actorCalls[MAXTILES];
extern double g_eventTotalMs[MAXEVENTS], g_actorTotalMs[MAXTILES];
@ -26,6 +35,6 @@ int32_t El_CallEvent(L_State *estate, int32_t eventidx, int32_t iActor, int32_t
int32_t El_CallActor(L_State *estate, int32_t actortile, int32_t iActor, int32_t iPlayer, int32_t lDist);
static inline int32_t El_HaveEvent(int32_t eventidx) { return g_elEvents[eventidx]!=0; }
static inline int32_t El_HaveActor(int32_t actortile) { return g_elActors[actortile]!=0; }
static inline int32_t El_HaveActor(int32_t actortile) { return g_elActors[actortile].haveit!=0; }
#endif

View file

@ -176,7 +176,7 @@ checkfail('local i = actor[0].t_data[15]', "has no member named 't_data'")
-- no pointer arithmetic!
checkfail('local spr = sprite[0]; local x=spr+1', "attempt to perform arithmetic on")
checkfail('gameactor(1680, 0)', "bad argument #3 to 'gameactor' (function expected, got number)")
checkfail('gameactor(1680, 0)', "invalid last argument to gameactor: must be a function")
checkfail("do local bt=require'bittest'; bt.QWE=1; end", "modifying module table forbidden")
-- the cdata returned by player[] can't be made into a pointer!
@ -236,6 +236,7 @@ local hs = stat.new()
local con = require("con")
local AC, MV = con.AC, con.MV
con.action("TROOPSTAND",0,1,5,1,1)
con.action("TROOPFLINTCH", 50, 1, 1, 1, 6)
con.move("SHRUNKVELS", 32)
con.ai("AITEMP", AC.TROOPFLINTCH, MV.SHRUNKVELS, 0) -- TODO: test
@ -245,7 +246,9 @@ con.ai("AITEMP", AC.TROOPFLINTCH, MV.SHRUNKVELS, 0) -- TODO: test
-- Or will we allow only one definition per label ever?
con.ai("AITEMP", "TROOPFLINTCH", "SHRUNKVELS", 0)
gameactor(1680, -- LIZTROOP
local TROOPSTRENGTH = 30
gameactor(1680, TROOPSTRENGTH, "TROOPSTAND", -- LIZTROOP
function(i, playeri, dist)
sprite[i].pal = math.random(32)
-- sprite[i].ang = bit.band(sprite[i].ang-20, 2047)