From 4ea9f799b1cff984a74e3e93e3df6ff3ed3aa239 Mon Sep 17 00:00:00 2001 From: helixhorned Date: Sun, 23 Dec 2012 19:24:16 +0000 Subject: [PATCH] Lunatic: more complete gameactor(), misc. translator tweaks. git-svn-id: https://svn.eduke32.com/eduke32@3315 1a8010ca-5511-0410-912e-c29ae57300e0 --- polymer/eduke32/source/actors.h | 3 ++ polymer/eduke32/source/game.c | 14 +++++ polymer/eduke32/source/lunatic/control.lua | 6 ++- polymer/eduke32/source/lunatic/defs.ilua | 50 +++++++++++++++++- polymer/eduke32/source/lunatic/lunacon.lua | 52 +++++++++++++------ polymer/eduke32/source/lunatic/lunatic_game.c | 34 ++++++++---- polymer/eduke32/source/lunatic/lunatic_game.h | 13 ++++- polymer/eduke32/source/lunatic/test.elua | 7 ++- 8 files changed, 147 insertions(+), 32 deletions(-) diff --git a/polymer/eduke32/source/actors.h b/polymer/eduke32/source/actors.h index 8cc396518..1956a6ef4 100644 --- a/polymer/eduke32/source/actors.h +++ b/polymer/eduke32/source/actors.h @@ -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 { diff --git a/polymer/eduke32/source/game.c b/polymer/eduke32/source/game.c index e67b9c786..2923d8f33 100644 --- a/polymer/eduke32/source/game.c +++ b/polymer/eduke32/source/game.c @@ -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)); diff --git a/polymer/eduke32/source/lunatic/control.lua b/polymer/eduke32/source/lunatic/control.lua index 8fb1ef015..c6d2451ca 100644 --- a/polymer/eduke32/source/lunatic/control.lua +++ b/polymer/eduke32/source/lunatic/control.lua @@ -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 diff --git a/polymer/eduke32/source/lunatic/defs.ilua b/polymer/eduke32/source/lunatic/defs.ilua index a4bda3568..c32044a30 100644 --- a/polymer/eduke32/source/lunatic/defs.ilua +++ b/polymer/eduke32/source/lunatic/defs.ilua @@ -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 diff --git a/polymer/eduke32/source/lunatic/lunacon.lua b/polymer/eduke32/source/lunatic/lunacon.lua index 9b9e89e52..f8677595c 100644 --- a/polymer/eduke32/source/lunatic/lunacon.lua +++ b/polymer/eduke32/source/lunatic/lunacon.lua @@ -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 diff --git a/polymer/eduke32/source/lunatic/lunatic_game.c b/polymer/eduke32/source/lunatic/lunatic_game.c index 5ce791ea4..d5c19a271 100644 --- a/polymer/eduke32/source/lunatic/lunatic_game.c +++ b/polymer/eduke32/source/lunatic/lunatic_game.c @@ -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(, 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; } diff --git a/polymer/eduke32/source/lunatic/lunatic_game.h b/polymer/eduke32/source/lunatic/lunatic_game.h index deecdd5e6..97496328b 100644 --- a/polymer/eduke32/source/lunatic/lunatic_game.h +++ b/polymer/eduke32/source/lunatic/lunatic_game.h @@ -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 diff --git a/polymer/eduke32/source/lunatic/test.elua b/polymer/eduke32/source/lunatic/test.elua index 764a1316a..3f354fee7 100644 --- a/polymer/eduke32/source/lunatic/test.elua +++ b/polymer/eduke32/source/lunatic/test.elua @@ -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)