Lunatic: implement a couple more 1.5 commands.

git-svn-id: https://svn.eduke32.com/eduke32@2869 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2012-08-08 19:32:35 +00:00
parent 8fa80701bb
commit 7f4eb4f5c3
4 changed files with 165 additions and 21 deletions

View file

@ -946,6 +946,7 @@ skip_check:
#ifdef LUNATIC
set_action_members(vm.g_i);
#endif
// NOTE: "if (g_t[5])" added in r1155. It used to be a pointer though.
if (vm.g_t[5])
{
vm.g_t[1] = *(script + vm.g_t[5] + 1); // move

View file

@ -12,26 +12,34 @@ local type = type
module(...)
local lastid = { action=0, move=0 }
local lastid = { action=0, move=0, ai=0 }
local def = { action={}, move={}, ai={} }
local function forbidden() error("newindex forbidden", 2) end
local ac, mv = {}, {}
AC = setmetatable({}, { __index=ac, __newindex=forbidden })
MV = setmetatable({}, { __index=mv, __newindex=forbidden })
AC = setmetatable({}, { __index=def.action, __newindex=forbidden })
MV = setmetatable({}, { __index=def.move, __newindex=forbidden })
AI = setmetatable({}, { __index=def.ai, __newindex=forbidden })
local function check_name(name, what, errlev)
if (type(name)~="string" or #name > 63) then
error("bad argument #1 to "..what..": must be a string of length <= 63", errlev+1)
end
end
local function action_or_move(what, numargs, tab, name, ...)
assert(lastid[what] > -(2^31))
if (type(name)~="string" or #name > 63) then
error("bad argument #1 to "..what..": must be a string of length <= 63", 3)
end
check_name(name, what, 3)
local args = {...}
assert(#args <= numargs)
for i=1,#args do
local n = args[i]
assert(type(n)=="number" and (n >= -32768 and n <= 32767))
if (type(n)~="number" or not (n >= -32768 and n <= 32767)) then
error("bad argument #".. i+1 .." to "..what..
": must be numbers in [-32768..32767]", 3)
end
end
-- missing fields are initialized to 0 by ffi.new
@ -46,9 +54,47 @@ local function action_or_move(what, numargs, tab, name, ...)
end
function action(name, ...)
action_or_move("action", 5, ac, name, ...)
action_or_move("action", 5, def.action, name, ...)
end
function move(name, ...)
action_or_move("move", 2, mv, name, ...)
action_or_move("move", 2, def.move, name, ...)
end
local function get_action_or_move(what, val, argi)
if (val == nil) then
return {} -- will init the struct to all zeros
elseif (type(val)=="string") then
local am = def[what][val]
if (am==nil) then
error("no "..what.." '"..val.."' defined", 3)
end
return am
elseif (ffi.istype("con_"..what.."_t", val)) then
return val
end
-- TODO: literal number actions/moves?
error("bad argument #"..argi.." to ai: must be string or "..what)
end
function ai(name, action, move, flags)
assert(lastid.ai > -(2^31))
check_name(name, "ai", 2)
lastid.ai = lastid.ai-1
local act = get_action_or_move("action", action, 2)
local mov = get_action_or_move("move", move, 3)
if (flags~=nil) then
if (type(flags)~="number" or not (flags>=0 and flags<=32767)) then
error("bad argument #4 to ai: must be a number in [0..32767]", 2)
end
else
flags = 0
end
def.ai[name] = ffi.new("const con_ai_t", lastid.ai, act, mov, flags)
end

View file

@ -67,7 +67,7 @@ typedef struct {
typedef struct {
vec3_t pos;
int16_t hitsprite, hitwall, hitsect;
int16_t sprite, wall, sect;
} hitdata_t;
typedef struct {
@ -247,6 +247,13 @@ struct move {
typedef struct { int32_t id; struct move mv; } con_move_t;
typedef struct { int32_t id; struct action ac; } con_action_t;
typedef struct {
int32_t id;
con_action_t act;
con_move_t mov;
int32_t movflags;
} con_ai_t;
// TODO: still need to make some fields read-only
// NOTE: must not expose arrays in structs!!!
typedef struct
@ -255,9 +262,9 @@ typedef struct
..repeat_n_elts("int32_t", "_t", 10)..
[[
// const int32_t t_data[10]; // 56b sometimes used to hold offsets to con code
struct move mv;
struct action ac;
const int16_t padding_;
const struct move mv;
const struct action ac;
const int16_t _padding;
int16_t picnum,ang,extra,owner; //8b
int16_t movflag,tempang,timetosleep; //6b
@ -562,7 +569,7 @@ string.dump = nil
-- sanity-check struct type sizes
for i=0,6 do
assert(ffi.sizeof(ffi.typeof(ffi.string(ffiC.g_sizes_of_what[i])))
assert(ffi.sizeof(ffi.string(ffiC.g_sizes_of_what[i]))
== ffiC.g_sizes_of[i])
end
@ -575,30 +582,117 @@ local con = require("con")
-- All-zero action and move
local nullac, nullmv = ffi.new("const struct action"), ffi.new("const struct move")
local function check_literal_am(am)
if (type(am) ~= "number") then
error("bad argument: expected number", 3)
end
if (not (am >= 0 and am <= 32767)) then
error("bad argument: expected number in [0 .. 32767]", 3)
end
end
local actor_mt = {
__index = {
-- action
set_action = function(a, act)
a = ffi.cast("actor_u_t *", a)
if (ffi.istype("con_action_t", act)) then
a.t_data[4] = act.id
a.ac = act.ac
else
assert(type(act)=="number" and act >= 0 and act <= 32767)
check_literal_am(act)
a.t_data[4] = act
a.ac = nullac
end
a.t_data[2] = 0
a.t_data[3] = 0
end,
set_move = function(a, mv)
has_action = function(a, act)
a = ffi.cast("actor_u_t *", a)
if (ffi.istype("con_action_t", act)) then
return (a.t_data[4]==act.id)
else
check_literal_am(act)
return (a.t_data[4]==act)
end
end,
-- count
set_count = function(a)
ffi.cast("actor_u_t *", a).t_data[0] = 0
end,
get_count = function(a)
return ffi.cast("actor_u_t *", a).t_data[0]
end,
-- action count
reset_acount = function(a)
ffi.cast("actor_u_t *", a).t_data[2] = 0
end,
get_acount = function(a)
return ffi.cast("actor_u_t *", a).t_data[2]
end,
-- move
set_move = function(a, mov, movflags)
a = ffi.cast("actor_u_t *", a)
if (ffi.istype("con_move_t", mov)) then
a.t_data[4] = mov.id
a.t_data[1] = mov.id
a.mv = mov.mv
else
assert(type(mov)=="number" and mov >= 0 and mov <= 32767)
a.t_data[4] = mov
check_literal_am(mov)
a.t_data[1] = mov
a.mv = nullmv
end
a.t_data[0] = 0
local i = a-ffi.cast("actor_u_t *", ffiC.actor[0])
ffiC.sprite[i].hitag = movflags or 0
-- TODO: random angle moveflag
end,
has_move = function(a, mov)
a = ffi.cast("actor_u_t *", a)
if (ffi.istype("con_move_t", mov)) then
return (a.t_data[1]==mov.id)
else
check_literal_am(mov)
return (a.t_data[1]==mov)
end
end,
-- ai
set_ai = function(a, ai)
local oa = a
a = ffi.cast("actor_u_t *", a)
-- TODO: literal number AIs?
assert(ffi.istype("con_ai_t", ai))
-- NOTE: compare with gameexec.c
a.t_data[5] = ai.id
oa:set_action(ai.act)
oa:set_move(ai.mov, ai.movflags)
a.t_data[0] = 0
end,
has_ai = function(a, ai)
a = ffi.cast("actor_u_t *", a)
if (ffi.istype("con_ai_t", ai)) then
return (a.t_data[5]==ai.id)
else
check_literal_am(ai)
return (a.t_data[5]==ai)
end
end,
},
}

View file

@ -233,8 +233,10 @@ local stat = require("stat")
local hs = stat.new()
local con = require("con")
local AC = con.AC
local AC, MV = con.AC, con.MV
con.action("TROOPFLINTCH", 50, 1, 1, 1, 6)
con.move("SHRUNKVELS", 32)
con.ai("AITEMP", "TROOPFLINTCH", MV.SHRUNKVELS, 0) -- TODO: test
gameactor(1680, -- LIZTROOP
function(i, playeri, dist)
@ -257,6 +259,7 @@ gameactor(1680, -- LIZTROOP
if (dist < 4096) then
-- Duke Vader / Anakin Nukewalker?
actor[i]:set_action(AC.TROOPFLINTCH)
actor[i]:set_move(MV.SHRUNKVELS)
end
end
)