Lunatic translator: sprite list commands, findnear*, protect player[].ftq.

git-svn-id: https://svn.eduke32.com/eduke32@3498 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2013-02-18 16:07:32 +00:00
parent 719efefbf0
commit 2d61216758
8 changed files with 164 additions and 92 deletions

View file

@ -1,6 +1,7 @@
-- Bound-checking functions for engine and game "things". -- Bound-checking functions for engine and game "things".
local ffiC = require("ffi").C local ffiC = require("ffi").C
local con_lang = require("con_lang")
local bcheck = {} local bcheck = {}
@ -71,5 +72,15 @@ function bcheck.level_idx(level)
end end
end end
function bcheck.quote_idx(qnum)
if (qnum >= con_lang.MAXQUOTES+0ULL) then
error("invalid quote number "..qnum, 3)
end
if (ffiC.ScriptQuotes[qnum] == nil) then
error("null quote "..qnum, 3)
end
end
return bcheck return bcheck

View file

@ -516,9 +516,9 @@ local PlayerLabels = {
airleft = PL".airleft", airleft = PL".airleft",
fta = PL".fta", fta = PL".fta",
ftq = PL".ftq", ftq = { PL".ftq", PL":set_ftq(%%s)" },
access_wallnum = PL".access_wallnum", access_wallnum = { PL".access_wallnum" },
access_spritenum = PL".access_spritenum", access_spritenum = { PL".access_spritenum" },
got_access = PL".got_access", got_access = PL".got_access",
weapon_ang = PL".weapon_ang", weapon_ang = PL".weapon_ang",

View file

@ -329,6 +329,10 @@ end
--- player/actor/sprite searching functions --- --- player/actor/sprite searching functions ---
local xmath = require("xmath")
local abs = math.abs
local dist, ldist = xmath.dist, xmath.ldist
local function A_FP_ManhattanDist(ps, spr) local function A_FP_ManhattanDist(ps, spr)
return (ps.pos - spr^(28*256)):blen1() return (ps.pos - spr^(28*256)):blen1()
end end
@ -339,6 +343,48 @@ function _findplayer(ps, spritenum)
return 0, A_FP_ManhattanDist(ps, sprite[spritenum]) return 0, A_FP_ManhattanDist(ps, sprite[spritenum])
end end
local FN_STATNUMS = {
[false] = { con_lang.STAT.STAT_ACTOR },
[true] = {},
}
-- TODO: Python-like range() and xrange()?
for i=0,ffiC.MAXSTATUS-1 do
FN_STATNUMS[true][i+1] = ffiC.MAXSTATUS-1-i
end
local FN_DISTFUNC = {
d2 = function(s1, s2, d)
return (xmath.ldist(s1, s2) < d)
end,
d3 = function(s1, s2, d)
return (xmath.dist(s1, s2) < d)
end,
z = function(s1, s2, d, zd)
return (xmath.ldist(s1, s2) < d and abs(s1.z-s2.z) < zd)
end,
}
function _findnear(spritenum, allspritesp, distkind, picnum, maxdist, maxzdist)
local statnums = FN_STATNUMS[allspritesp]
local distfunc = FN_DISTFUNC[distkind]
local spr = sprite[spritenum]
for st=1,#statnums do
for i in spritesofstat(st) do
if (i ~= spritenum and sprite[i].picnum==picnum) then
if (distfunc(spr, sprite[i], maxdist, maxzdist)) then
return i
end
end
end
end
return -1
end
---=== Weapon stuff ===--- ---=== Weapon stuff ===---
@ -374,31 +420,21 @@ end
local MAXQUOTES = con_lang.MAXQUOTES local MAXQUOTES = con_lang.MAXQUOTES
local function check_quote_idx(qnum)
if (qnum >= MAXQUOTES+0ULL) then
error("invalid quote number "..qnum, 3)
end
if (ffiC.ScriptQuotes[qnum] == nil) then
error("null quote "..qnum, 3)
end
end
function _definequote(qnum, quotestr) function _definequote(qnum, quotestr)
check_quote_idx(qnum) bcheck.quote_idx(qnum)
assert(type(quotestr)=="string") assert(type(quotestr)=="string")
ffiC.C_DefineQuote(qnum, quotestr) ffiC.C_DefineQuote(qnum, quotestr)
return (#quotestr >= con_lang.MAXQUOTELEN) return (#quotestr >= con_lang.MAXQUOTELEN)
end end
function _quote(pli, qnum) function _quote(pli, qnum)
check_quote_idx(qnum) bcheck.quote_idx(qnum)
check_player_idx(pli) check_player_idx(pli)
ffiC.P_DoQuote(qnum+MAXQUOTES, ffiC.g_player[pli].ps) ffiC.P_DoQuote(qnum+MAXQUOTES, ffiC.g_player[pli].ps)
end end
function _echo(qnum) function _echo(qnum)
check_quote_idx(qnum) bcheck.quote_idx(qnum)
-- XXX: ugly round-trip -- XXX: ugly round-trip
print(ffi.string(ffiC.ScriptQuotes[qnum])) print(ffi.string(ffiC.ScriptQuotes[qnum]))
end end
@ -771,14 +807,12 @@ function _awayfromwall(spr, d)
return true return true
end end
local xmath = require("xmath")
local function cossinb(bang) local function cossinb(bang)
return xmath.cosb(bang), xmath.sinb(bang) return xmath.cosb(bang), xmath.sinb(bang)
end end
local function manhatdist(v1, v2) local function manhatdist(v1, v2)
return math.abs(v1.x-v2.x) + math.abs(v1.y-v2.y) return abs(v1.x-v2.x) + abs(v1.y-v2.y)
end end
-- "otherspr" is either player or holoduke sprite -- "otherspr" is either player or holoduke sprite
@ -950,8 +984,8 @@ function _angdiffabs(a1, a2)
a1 = bit.band(a1, 2047) a1 = bit.band(a1, 2047)
a2 = bit.band(a2, 2047) a2 = bit.band(a2, 2047)
-- a1 and a2 are in [0, 2047] -- a1 and a2 are in [0, 2047]
if (math.abs(a2-a1) < 1024) then if (abs(a2-a1) < 1024) then
return math.abs(a2-a1) return abs(a2-a1)
end end
-- |a2-a1| >= 1024 -- |a2-a1| >= 1024
if (a2 > 1024) then a2=a2-2048 end if (a2 > 1024) then a2=a2-2048 end
@ -961,7 +995,7 @@ function _angdiffabs(a1, a2)
end end
function _angdiffabs(a1, a2) function _angdiffabs(a1, a2)
return math.abs(_angdiff(a1, a2)) return abs(_angdiff(a1, a2))
end end
function _angtotarget(aci) function _angtotarget(aci)

View file

@ -199,7 +199,8 @@ __attribute__((packed)) struct {
int16_t horiz, horizoff, ohoriz, ohorizoff; int16_t horiz, horizoff, ohoriz, ohorizoff;
const int16_t newowner; const int16_t newowner;
int16_t jumping_counter, airleft; int16_t jumping_counter, airleft;
int16_t fta, ftq, access_wallnum, access_spritenum; int16_t fta;
const int16_t ftq, access_wallnum, access_spritenum;
int16_t got_access, weapon_ang, visibility; int16_t got_access, weapon_ang, visibility;
int16_t somethingonplayer, on_crane; int16_t somethingonplayer, on_crane;
const int16_t i; const int16_t i;
@ -911,6 +912,11 @@ local player_mt = {
p.inv_amount[inv] = amount p.inv_amount[inv] = amount
end, end,
set_ftq = function(p, ftq)
bcheck.quote_idx(ftq)
ffi.cast(player_ptr_ct, p).ftq = ftq
end,
set_customexitsound = function(p, soundnum) set_customexitsound = function(p, soundnum)
if (soundnum >= con_lang.MAXSOUNDS+0ULL) then if (soundnum >= con_lang.MAXSOUNDS+0ULL) then
error("Invalid sound number "..soundnum, 2) error("Invalid sound number "..soundnum, 2)
@ -1047,6 +1053,15 @@ function gv_access._currentMenu()
return ffiC.g_currentMenu return ffiC.g_currentMenu
end end
function gv_access._set_guniqhudid(id)
local MAXUNIQHUDID = 256 -- KEEPINSYNC build.h
if (id >= MAXUNIQHUDID+0ULL) then
error("invalid unique HUD ID "..id)
end
ffiC.guniqhudid = id
end
-- TODO: make return 1-based index
function gv_access.currentEpisode() function gv_access.currentEpisode()
return ffiC.ud.volume_number return ffiC.ud.volume_number
end end

View file

@ -228,6 +228,7 @@ const int32_t windowx1, windowy1, windowx2, windowy2;
decl[[ decl[[
int32_t yxaspect, viewingrange; int32_t yxaspect, viewingrange;
int32_t spritesortcnt; int32_t spritesortcnt;
int32_t guniqhudid;
const int32_t rendmode; const int32_t rendmode;
const int16_t headspritesect[MAXSECTORS+1], headspritestat[MAXSTATUS+1]; const int16_t headspritesect[MAXSECTORS+1], headspritestat[MAXSTATUS+1];
const int16_t prevspritesect[MAXSPRITES], prevspritestat[MAXSPRITES]; const int16_t prevspritesect[MAXSPRITES], prevspritestat[MAXSPRITES];
@ -511,6 +512,24 @@ end
---- indirect C array access ---- ---- indirect C array access ----
-- create a safe indirection for an ffi.C array
function creategtab(ctab, maxidx, name)
local tab = {}
local tmpmt = {
__index = function(tab, key)
if (key>=0 and key < maxidx) then
return ctab[key]
end
error('out-of-bounds '..name..' read access', 2)
end,
__newindex = function()
error('cannot write directly to '..name, 2)
end,
}
return setmtonce(tab, tmpmt)
end
-- Construct const struct from table -- Construct const struct from table
function conststruct(tab) function conststruct(tab)
local strtab = { "const struct { int32_t " } local strtab = { "const struct { int32_t " }
@ -554,6 +573,15 @@ static_members.sprite.CSTAT = conststruct
TRANSLUCENT_BOTH_BITS = 512+2, TRANSLUCENT_BOTH_BITS = 512+2,
} }
local sms = static_members.sprite
sms._headspritesect = creategtab(ffiC.headspritesect, ffiC.MAXSECTORS, 'headspritesect[]')
-- NOTE: don't allow freelist access
sms._headspritestat = creategtab(ffiC.headspritestat, ffiC.MAXSTATUS, 'headspritestat[]')
sms._nextspritesect = creategtab(ffiC.nextspritesect, ffiC.MAXSPRITES, 'nextspritesect[]')
sms._nextspritestat = creategtab(ffiC.nextspritestat, ffiC.MAXSPRITES, 'nextspritestat[]')
sms._prevspritesect = creategtab(ffiC.prevspritesect, ffiC.MAXSPRITES, 'prevspritesect[]')
sms._prevspritestat = creategtab(ffiC.prevspritestat, ffiC.MAXSPRITES, 'prevspritestat[]')
function static_members.sprite.changesect(spritenum, sectnum) function static_members.sprite.changesect(spritenum, sectnum)
check_sprite_idx(spritenum) check_sprite_idx(spritenum)
check_sector_idx(sectnum) check_sector_idx(sectnum)
@ -611,24 +639,6 @@ local atsprite_mt = {
__newindex = function() error('cannot write directly to atsprite[]', 2) end, __newindex = function() error('cannot write directly to atsprite[]', 2) end,
} }
-- create a safe indirection for an ffi.C array
function creategtab(ctab, maxidx, name)
local tab = {}
local tmpmt = {
__index = function(tab, key)
if (key>=0 and key < maxidx) then
return ctab[key]
end
error('out-of-bounds '..name..' read access', 2)
end,
__newindex = function()
error('cannot write directly to '..name, 2)
end,
}
return setmtonce(tab, tmpmt)
end
local vars_to_ignore = {} local vars_to_ignore = {}
for varname,_ in pairs(getfenv(1)) do for varname,_ in pairs(getfenv(1)) do
@ -646,14 +656,6 @@ sprite = setmtonce({}, sprite_mt)
spriteext = creategtab(ffiC.spriteext, ffiC.MAXSPRITES, 'spriteext[]') spriteext = creategtab(ffiC.spriteext, ffiC.MAXSPRITES, 'spriteext[]')
atsprite = setmtonce({}, atsprite_mt) atsprite = setmtonce({}, atsprite_mt)
headspritesect = creategtab(ffiC.headspritesect, ffiC.MAXSECTORS, 'headspritesect[]')
-- TODO: allow sprite freelist access via the status list for CON compatibility?
headspritestat = creategtab(ffiC.headspritestat, ffiC.MAXSTATUS, 'headspritestat[]')
nextspritesect = creategtab(ffiC.nextspritesect, ffiC.MAXSPRITES, 'nextspritesect[]')
nextspritestat = creategtab(ffiC.nextspritestat, ffiC.MAXSPRITES, 'nextspritestat[]')
prevspritesect = creategtab(ffiC.prevspritesect, ffiC.MAXSPRITES, 'prevspritesect[]')
prevspritestat = creategtab(ffiC.prevspritestat, ffiC.MAXSPRITES, 'prevspritestat[]')
local function iter_wallsofsec(endwall, w) local function iter_wallsofsec(endwall, w)
w = w+1 w = w+1
if (w < endwall) then if (w < endwall) then

View file

@ -29,8 +29,6 @@ local ffi, ffiC
if (string.dump) then if (string.dump) then
bit = require("bit") bit = require("bit")
-- For Rio Lua:
-- bit = { bor=function() return 0 end }
require("strict") require("strict")
else else
bit = require("bit") bit = require("bit")
@ -1492,12 +1490,14 @@ local Cinner = {
/ handle.NYI, -- will never be / handle.NYI, -- will never be
cmenu = cmd(R) cmenu = cmd(R)
/ handle.NYI, / handle.NYI,
checkavailweapon = cmd(R), checkavailweapon = cmd(R) -- THISACTOR
checkavailinven = cmd(R), / handle.NYI,
guniqhudid = cmd(R), checkavailinven = cmd(R) -- THISACTOR
/ handle.NYI,
guniqhudid = cmd(R)
/ "_gv._set_guniqhudid(%1)",
savegamevar = cmd(R), savegamevar = cmd(R),
readgamevar = cmd(R), readgamevar = cmd(R),
userquote = cmd(R),
echo = cmd(R) echo = cmd(R)
/ "_con._echo(%1)", / "_con._echo(%1)",
activatecheat = cmd(R) activatecheat = cmd(R)
@ -1579,8 +1579,6 @@ local Cinner = {
/ "_con._spawnmany(_aci,1233,%1)", -- TODO: dyntile / "_con._spawnmany(_aci,1233,%1)", -- TODO: dyntile
paper = cmd(D) paper = cmd(D)
/ "_con._spawnmany(_aci,4460,%1)", -- TODO: dyntile / "_con._spawnmany(_aci,4460,%1)", -- TODO: dyntile
quote = cmd(D)
/ "_con._quote(_pli,%1)",
savenn = cmd(D), savenn = cmd(D),
save = cmd(D), save = cmd(D),
sleeptime = cmd(D) sleeptime = cmd(D)
@ -1630,7 +1628,7 @@ local Cinner = {
tip = cmd() tip = cmd()
/ PLS".tipincs=26", / PLS".tipincs=26",
tossweapon = cmd() tossweapon = cmd()
/ "", -- TODO / "", -- TODO_MP
wackplayer = cmd() wackplayer = cmd()
/ PLS":wack()", / PLS":wack()",
@ -1638,19 +1636,31 @@ local Cinner = {
findplayer = cmd(W) findplayer = cmd(W)
/ CSV".RETURN,%1=_con._findplayer(_pli,_aci)", -- player index, distance / CSV".RETURN,%1=_con._findplayer(_pli,_aci)", -- player index, distance
findotherplayer = cmd(W) findotherplayer = cmd(W)
/ CSV".RETURN,%1=0,0x7fffffff", -- TODO: MP case / CSV".RETURN,%1=0,0x7fffffff", -- TODO_MP
findnearspritezvar = cmd(D,R,R,W), findnearspritezvar = cmd(D,R,R,W)
findnearspritez = cmd(D,D,D,W), / "%4=_con._findnear(_aci,true,'z',%1,%2,%3)",
findnearsprite3dvar = cmd(D,R,W), findnearspritez = cmd(D,D,D,W)
findnearsprite3d = cmd(D,D,W), / "%4=_con._findnear(_aci,true,'z',%1,%2,%3)",
findnearspritevar = cmd(D,R,W), findnearsprite3dvar = cmd(D,R,W)
findnearsprite = cmd(D,D,W), / "%3=_con._findnear(_aci,true,'d3',%1,%2)",
findnearactorzvar = cmd(D,R,R,W), findnearsprite3d = cmd(D,D,W)
findnearactorz = cmd(D,D,D,W), / "%3=_con._findnear(_aci,true,'d3',%1,%2)",
findnearactor3dvar = cmd(D,R,W), findnearspritevar = cmd(D,R,W)
findnearactor3d = cmd(D,D,W), / "%3=_con._findnear(_aci,true,'d2',%1,%2)",
findnearactorvar = cmd(D,R,W), findnearsprite = cmd(D,D,W)
findnearactor = cmd(D,D,W), / "%3=_con._findnear(_aci,true,'d2',%1,%2)",
findnearactorzvar = cmd(D,R,R,W)
/ "%4=_con._findnear(_aci,false,'z',%1,%2,%3)",
findnearactorz = cmd(D,D,D,W)
/ "%4=_con._findnear(_aci,false,'z',%1,%2,%3)",
findnearactor3dvar = cmd(D,R,W)
/ "%3=_con._findnear(_aci,false,'d3',%1,%2)",
findnearactor3d = cmd(D,D,W)
/ "%3=_con._findnear(_aci,false,'d3',%1,%2)",
findnearactorvar = cmd(D,R,W)
/ "%3=_con._findnear(_aci,false,'d2',%1,%2)",
findnearactor = cmd(D,D,W)
/ "%3=_con._findnear(_aci,false,'d2',%1,%2)",
-- quotes -- quotes
qsprintf = sp1 * tok.rvar * sp1 * tok.rvar * (sp1 * tok.rvar)^-32, qsprintf = sp1 * tok.rvar * sp1 * tok.rvar * (sp1 * tok.rvar)^-32,
@ -1660,6 +1670,11 @@ local Cinner = {
qstrlen = cmd(R,R), qstrlen = cmd(R,R),
qstrncat = cmd(R,R), qstrncat = cmd(R,R),
qsubstr = cmd(R,R), qsubstr = cmd(R,R),
quote = cmd(D)
/ "_con._quote(_pli,%1)",
userquote = cmd(R),
getkeyname = cmd(R,R,R),
getpname = cmd(R,R),
-- array stuff -- array stuff
copy = sp1 * tok.identifier * arraypat * sp1 * tok.identifier * arraypat * sp1 * tok.rvar, copy = sp1 * tok.identifier * arraypat * sp1 * tok.identifier * arraypat * sp1 * tok.rvar,
@ -1751,12 +1766,18 @@ local Cinner = {
loadmapstate = cmd(), loadmapstate = cmd(),
savemapstate = cmd(), savemapstate = cmd(),
headspritesect = cmd(W,R), headspritesect = cmd(W,R)
headspritestat = cmd(W,R), / "%1=sprite._headspritesect[%2]",
nextspritesect = cmd(W,R), headspritestat = cmd(W,R)
nextspritestat = cmd(W,R), / "%1=sprite._headspritestat[%2]",
prevspritesect = cmd(W,R), nextspritesect = cmd(W,R)
prevspritestat = cmd(W,R), / "%1=sprite._nextspritesect[%2]",
nextspritestat = cmd(W,R)
/ "%1=sprite._nextspritestat[%2]",
prevspritesect = cmd(W,R)
/ "%1=sprite._prevspritesect[%2]",
prevspritestat = cmd(W,R)
/ "%1=sprite._prevspritestat[%2]",
redefinequote = sp1 * tok.define * newline_term_string redefinequote = sp1 * tok.define * newline_term_string
/ function(qnum, qstr) return format("_con._definequote(%d,%q)", qnum, stripws(qstr)) end, / function(qnum, qstr) return format("_con._definequote(%d,%q)", qnum, stripws(qstr)) end,
@ -1821,8 +1842,6 @@ local Cinner = {
/ "%4=sector[%1]:floorzat(%2,%3)", / "%4=sector[%1]:floorzat(%2,%3)",
getcurraddress = cmd(W) getcurraddress = cmd(W)
/ handle.NYI, -- will never be / handle.NYI, -- will never be
getkeyname = cmd(R,R,R),
getpname = cmd(R,R),
getticks = cmd(W) getticks = cmd(W)
/ "%1=_gv.getticks()", / "%1=_gv.getticks()",
gettimedate = cmd(W,W,W,W,W,W,W,W) gettimedate = cmd(W,W,W,W,W,W,W,W)
@ -1868,7 +1887,7 @@ local Cif = {
ifspritepal = cmd(D) ifspritepal = cmd(D)
/ SPS".pal==%1", / SPS".pal==%1",
ifgotweaponce = cmd(D) ifgotweaponce = cmd(D)
/ "false", -- TODO? (multiplayer only) / "false", -- TODO_MP
ifangdiffl = cmd(D) ifangdiffl = cmd(D)
/ format("_con._angdiffabs(%s,%s)<=%%1", PLS".ang", SPS".ang"), / format("_con._angdiffabs(%s,%s)<=%%1", PLS".ang", SPS".ang"),
ifsound = cmd(D) ifsound = cmd(D)
@ -1931,7 +1950,7 @@ local Cif = {
ifnosounds = cmd() ifnosounds = cmd()
/ "not _con._ianysound()", / "not _con._ianysound()",
ifmultiplayer = cmd() ifmultiplayer = cmd()
/ "false", -- TODO? / "false", -- TODO_MP
ifinwater = cmd() ifinwater = cmd()
/ format("sector[%s].lotag==2", SPS".sectnum"), / format("sector[%s].lotag==2", SPS".sectnum"),
ifinspace = cmd() ifinspace = cmd()

View file

@ -136,10 +136,10 @@ checkfail('gv.QWE = 4', "write access forbidden")
checkfail('sector[4] = sector[6]', "cannot write directly to sector[]") checkfail('sector[4] = sector[6]', "cannot write directly to sector[]")
-- that would be horrible... -- that would be horrible...
checkfail('nextspritesect[4] = -666', "cannot write directly to nextspritesect[]") checkfail('sprite._nextspritesect[4] = -666', "cannot write directly to nextspritesect[]")
-- we're indexing a plain array! -- we're indexing a plain array!
checkfail('print(nextspritesect[4].whatfield)', "attempt to index a number value") checkfail('print(sprite._nextspritesect[4].whatfield)', "attempt to index a number value")
-- creating new keys forbidden... handled by LuaJit -- creating new keys forbidden... handled by LuaJit
checkfail('wall[4].QWE = 123', "has no member named 'QWE'") checkfail('wall[4].QWE = 123', "has no member named 'QWE'")

View file

@ -2032,12 +2032,6 @@ static int32_t P_DisplayTip(int32_t gs,int32_t snum)
p = P_GetHudPal(ps); p = P_GetHudPal(ps);
/* if(ps->access_spritenum >= 0)
p = sprite[ps->access_spritenum].pal;
else
p = wall[ps->access_wallnum].pal;
*/
tipy = tip_y[ps->tipincs]>>1; tipy = tip_y[ps->tipincs]>>1;
G_DrawTileScaled(170+(g_player[snum].sync->avel>>4)-(ps->look_ang>>1), G_DrawTileScaled(170+(g_player[snum].sync->avel>>4)-(ps->look_ang>>1),
@ -2069,9 +2063,6 @@ static int32_t P_DisplayAccess(int32_t gs,int32_t snum)
if (ps->access_spritenum >= 0) if (ps->access_spritenum >= 0)
p = sprite[ps->access_spritenum].pal; p = sprite[ps->access_spritenum].pal;
// else
// p = wall[ps->access_wallnum].pal;
if ((ps->access_incs-3) > 0 && (ps->access_incs-3)>>3) if ((ps->access_incs-3) > 0 && (ps->access_incs-3)>>3)
{ {
guniqhudid = 200; guniqhudid = 200;