diff --git a/polymer/eduke32/source/game.c b/polymer/eduke32/source/game.c index e20032a79..f1ef8921b 100644 --- a/polymer/eduke32/source/game.c +++ b/polymer/eduke32/source/game.c @@ -9999,11 +9999,11 @@ bool fatInit (uint32_t cacheSize, bool setAsDefaultDevice); #ifdef LUNATIC const char *g_sizes_of_what[] = { - "sectortype", "walltype", "spritetype", + "sectortype", "walltype", "spritetype", "spriteext_t", "actor_t", "DukePlayer_t", "playerdata_t", "user_defs", "tiledata_t" }; int32_t g_sizes_of[] = { - sizeof(sectortype), sizeof(walltype), sizeof(spritetype), + sizeof(sectortype), sizeof(walltype), sizeof(spritetype), sizeof(spriteext_t), sizeof(actor_t), sizeof(DukePlayer_t), sizeof(playerdata_t), sizeof(user_defs), sizeof(tiledata_t) }; #endif diff --git a/polymer/eduke32/source/lunatic/defs.ilua b/polymer/eduke32/source/lunatic/defs.ilua index 39790dacd..5c027185f 100644 --- a/polymer/eduke32/source/lunatic/defs.ilua +++ b/polymer/eduke32/source/lunatic/defs.ilua @@ -560,7 +560,7 @@ string.dump = nil -- sanity-check struct type sizes local good = true -for i=0,7 do +for i=0,8 do local what = ffi.string(ffiC.g_sizes_of_what[i]) local fsz = ffi.sizeof(what) local csz = ffiC.g_sizes_of[i] @@ -599,10 +599,12 @@ local con = require("control") local MV, AC, AI = con.MV, con.AC, con.AI -- Add game-side metamethods to "spritetype" and register it with "metatype" -defs_c.spritetype_mt.__index.isenemy = function(s) - return con.isenemytile(s.picnum) -end -ffi.metatype("spritetype", defs_c.spritetype_mt) +local spr_mt_index_add = { + isenemy = function(s) + return con.isenemytile(s.picnum) + end, +} +defs_c.finish_spritetype(spr_mt_index_add) -- All-zero action and move local nullac, nullmv = ffi.new("const struct action"), ffi.new("const struct move") diff --git a/polymer/eduke32/source/lunatic/defs_common.lua b/polymer/eduke32/source/lunatic/defs_common.lua index fc19a7938..917da4cdd 100644 --- a/polymer/eduke32/source/lunatic/defs_common.lua +++ b/polymer/eduke32/source/lunatic/defs_common.lua @@ -18,6 +18,7 @@ local pairs = pairs local require = require local setmetatable = setmetatable local tostring = tostring +local type = type local decl = decl local getfenv = getfenv @@ -100,6 +101,7 @@ ffi.cdef([[ typedef $ sectortype; typedef $ walltype; typedef $ spritetype; +typedef $ tspritetype; typedef struct { const uint32_t mdanimtims; @@ -110,8 +112,10 @@ typedef struct { uint8_t xpanning, ypanning; const uint8_t filler; float alpha; - const int32_t _do_not_use1; - const int32_t _do_not_use2; + union { + const intptr_t _tspr; + struct { const int32_t _dummy0, _dummy1; }; + }; } spriteext_t; typedef struct { @@ -123,7 +127,11 @@ typedef struct { int16_t sprite, wall, sect; } hitdata_t; #pragma pack(pop) -]], ffi.typeof(SECTOR_STRUCT), ffi.typeof(WALL_STRUCT), ffi.typeof(SPRITE_STRUCT)) +]], +ffi.typeof(SECTOR_STRUCT), ffi.typeof(WALL_STRUCT), +ffi.typeof(SPRITE_STRUCT), ffi.typeof(SPRITE_STRUCT)) +-- NOTE: spritetype and tspritetype are different types with the same layout. +-- (XXX: is there a better way?) -- Define the "palette_t" type, which for us has .{r,g,b} fields and a -- bound-checking array of length 3 overlaid. @@ -154,6 +162,7 @@ if (ffiC.engine_main_arrays_are_static ~= 0) then sectortype sector[]; walltype wall[]; spritetype sprite[]; + tspritetype tsprite[]; spriteext_t spriteext[]; ]] else @@ -161,6 +170,7 @@ else sectortype *sector; walltype *wall; spritetype *sprite; + tspritetype *tsprite; spriteext_t *spriteext; ]] end @@ -191,6 +201,7 @@ ffi.cdef[[ enum { MAXSTATUS = 1024, MAXTILES = 30720, + MAXSPRITESONSCREEN = 4096, MAXBUNCHES = 256, CEILING = 0, @@ -211,6 +222,7 @@ const int32_t windowx1, windowy1, windowx2, windowy2; ]] decl[[ +int32_t spritesortcnt; const int32_t rendmode; const int16_t headspritesect[MAXSECTORS+1], headspritestat[MAXSTATUS+1]; const int16_t prevspritesect[MAXSPRITES], prevspritestat[MAXSPRITES]; @@ -257,6 +269,7 @@ int32_t __fastcall getangle(int32_t xvect, int32_t yvect); local bcheck = require("bcheck") local check_sector_idx = bcheck.sector_idx +local check_sprite_idx = bcheck.sprite_idx local check_tile_idx = bcheck.tile_idx local ivec3_ @@ -368,9 +381,19 @@ local walltype_mt = { } ffi.metatype("walltype", walltype_mt) +local spriteext_mt = { + __index = { + -- Enable EVENT_ANIMATESPRITES for this sprite. + make_animated = function(sx) + sx.flags = bit.bor(sx.flags, 16) + end, + }, +} +ffi.metatype("spriteext_t", spriteext_mt) + local spritetype_ptr_ct = ffi.typeof("$ *", ffi.typeof(strip_const(SPRITE_STRUCT))) -spritetype_mt = { +local spritetype_mt = { __pow = function(s, zofs) return ivec3_(s.x, s.y, s.z-zofs) end, @@ -387,8 +410,46 @@ spritetype_mt = { end, }, } --- The user of this module can insert additional "spritetype" metamethods and --- register them with "ffi.metatype". + +local function deep_copy(tab) + local ntab = {} + for key, val in pairs(tab) do + if (type(val)=="table") then + ntab[key] = deep_copy(val) + else + assert(type(val)=="function") + ntab[key] = val + end + end + return ntab +end + +local tspritetype_mt = deep_copy(spritetype_mt) + +-- Methods that are specific to tsprites +-- XXX: doesn't work with LuaJIT git f772bed34b39448e3a9ab8d07f6d5c0c26300e1b +function tspritetype_mt.__index.dup(tspr) + if (ffiC.spritesortcnt >= ffiC.MAXSPRITESONSCREEN+0ULL) then + return nil + end + + local newtspr = ffi.tsprite[ffiC.spritesortcnt] + ffi.copy(newtspr, tspr, ffi.sizeof(tspr)) + ffiC.spritesortcnt = ffiC.spritesortcnt+1 + + return newtspr +end + +-- The user of this module can insert additional "spritetype" index +-- methods and register them with "ffi.metatype". +function finish_spritetype(mt_index) + for name, func in pairs(mt_index) do + spritetype_mt.__index[name] = func + tspritetype_mt.__index[name] = func + end + ffi.metatype("spritetype", spritetype_mt) + ffi.metatype("tspritetype", tspritetype_mt) +end ---=== Restricted access to C variables from Lunatic ===--- @@ -406,7 +467,7 @@ local sector_mt = { error('out-of-bounds sector[] read access', 2) end, - __newindex = function(tab, key, val) error('cannot write directly to sector[] struct', 2) end, + __newindex = function() error('cannot write directly to sector[]', 2) end, } local wall_mt = { @@ -415,7 +476,23 @@ local wall_mt = { error('out-of-bounds wall[] read access', 2) end, - __newindex = function(tab, key, val) error('cannot write directly to wall[] struct', 2) end, + __newindex = function() error('cannot write directly to wall[]', 2) end, +} + +local atsprite_mt = { + __index = function(tab, idx) + check_sprite_idx(idx) + + local tspr = ffi.cast(spritetype_ptr_ct, ffiC.spriteext[idx]._tspr) + if (tspr == nil) then + error("tsprite of actor "..idx.." unavailable", 2) + end + + -- Return a reference to a tsprite[] element. + return tspr[0] + end, + + __newindex = function() error('cannot write directly to atsprite[]', 2) end, } -- create a safe indirection for an ffi.C array @@ -428,7 +505,7 @@ function creategtab(ctab, maxidx, name) end error('out-of-bounds '..name..' read access', 2) end, - __newindex = function(tab, key, val) + __newindex = function() error('cannot write directly to '..name, 2) end, } @@ -449,8 +526,9 @@ end sector = setmtonce({}, sector_mt) wall = setmtonce({}, wall_mt) -sprite = creategtab(ffiC.sprite, ffiC.MAXSPRITES, 'sprite[] struct') -spriteext = creategtab(ffiC.spriteext, ffiC.MAXSPRITES, 'spriteext[] struct') +sprite = creategtab(ffiC.sprite, ffiC.MAXSPRITES, 'sprite[]') +spriteext = creategtab(ffiC.spriteext, ffiC.MAXSPRITES, 'spriteext[]') +atsprite = setmtonce({}, atsprite_mt) headspritesect = creategtab(ffiC.headspritesect, ffiC.MAXSECTORS, 'headspritesect[]') -- TODO: allow sprite freelist access via the status list for CON compatibility? diff --git a/polymer/eduke32/source/lunatic/defs_m32.ilua b/polymer/eduke32/source/lunatic/defs_m32.ilua index f21976f42..093f203ec 100644 --- a/polymer/eduke32/source/lunatic/defs_m32.ilua +++ b/polymer/eduke32/source/lunatic/defs_m32.ilua @@ -7,7 +7,7 @@ local ffiC = ffi.C --== First, load the definitions common to the game's and editor's Lua interface. decl = ffi.cdef local defs_c = require("defs_common") -ffi.metatype("spritetype", defs_c.spritetype_mt) +defs_c.finish_spritetype({}) defs_c.create_globals(_G) diff --git a/polymer/eduke32/source/lunatic/dynsymlist b/polymer/eduke32/source/lunatic/dynsymlist index c0949469c..705fe4bc2 100644 --- a/polymer/eduke32/source/lunatic/dynsymlist +++ b/polymer/eduke32/source/lunatic/dynsymlist @@ -5,11 +5,13 @@ engine_v8; sector; wall; sprite; +tsprite; spriteext; numsectors; numwalls; numyaxbunches; +spritesortcnt; rendmode; totalclock; diff --git a/polymer/eduke32/source/lunatic/dynsymlist_m32 b/polymer/eduke32/source/lunatic/dynsymlist_m32 index 32b70a0fa..e203f7704 100644 --- a/polymer/eduke32/source/lunatic/dynsymlist_m32 +++ b/polymer/eduke32/source/lunatic/dynsymlist_m32 @@ -5,11 +5,13 @@ engine_v8; sector; wall; sprite; +tsprite; spriteext; numsectors; numwalls; numyaxbunches; +spritesortcnt; rendmode; totalclock; diff --git a/polymer/eduke32/source/lunatic/lunacon.lua b/polymer/eduke32/source/lunatic/lunacon.lua index e044734b5..248b01f45 100644 --- a/polymer/eduke32/source/lunatic/lunacon.lua +++ b/polymer/eduke32/source/lunatic/lunacon.lua @@ -1274,10 +1274,10 @@ local Cinner = { getactor = GetStructCmd(Access.xsprite), getplayer = GetStructCmd(Access.player), - getinput = getstructcmd, - getprojectile = getstructcmd, - getthisprojectile = getstructcmd, - gettspr = getstructcmd, + getinput = getstructcmd / handle.NYI, + getprojectile = getstructcmd / handle.NYI, + getthisprojectile = getstructcmd / handle.NYI, + gettspr = getstructcmd / handle.NYI, -- NOTE: {get,set}userdef is the only struct that can be accessed without -- an "array part", e.g. H266MOD has "setuserdef .weaponswitch 0" (space -- between keyword and "." is mandatory). @@ -1286,21 +1286,21 @@ local Cinner = { -- arrays, I highly doubt that they worked (much less were safe) in CON. -- We disallow them unless CONs in the wild crop up that actually used -- these. - getuserdef = (arraypat + sp1)/{} * singlememberpat * sp1 * tok.wvar, + getuserdef = (arraypat + sp1)/{} * singlememberpat * sp1 * tok.wvar / handle.NYI, - getactorvar = getperxvarcmd, - getplayervar = getperxvarcmd, + getactorvar = getperxvarcmd / handle.NYI, + getplayervar = getperxvarcmd / handle.NYI, setsector = SetStructCmd(Access.sector), setwall = SetStructCmd(Access.wall), setactor = SetStructCmd(Access.xsprite), setplayer = SetStructCmd(Access.player), - setinput = setstructcmd, - setprojectile = setstructcmd, - setthisprojectile = setstructcmd, - settspr = setstructcmd, - setuserdef = (arraypat + sp1)/{} * singlememberpat * sp1 * tok.rvar, + setinput = setstructcmd / handle.NYI, + setprojectile = setstructcmd / handle.NYI, + setthisprojectile = setstructcmd / handle.NYI, + settspr = setstructcmd / handle.NYI, + setuserdef = (arraypat + sp1)/{} * singlememberpat * sp1 * tok.rvar / handle.NYI, setactorvar = setperxvarcmd, setplayervar = setperxvarcmd, diff --git a/polymer/eduke32/source/lunatic/test.elua b/polymer/eduke32/source/lunatic/test.elua index 84cdd52bc..82be81334 100644 --- a/polymer/eduke32/source/lunatic/test.elua +++ b/polymer/eduke32/source/lunatic/test.elua @@ -133,7 +133,7 @@ checkfail('gv.numsectors = 4', "write access forbidden") checkfail('gv.QWE = 4', "write access forbidden") -- direct sector write access forbidden -checkfail('sector[4] = sector[6]', "cannot write directly to sector[] struct") +checkfail('sector[4] = sector[6]', "cannot write directly to sector[]") -- that would be horrible... checkfail('nextspritesect[4] = -666', "cannot write directly to nextspritesect[]") @@ -285,6 +285,8 @@ local TROOPSTRENGTH = 30 gameactor(1680, TROOPSTRENGTH, "TROOPSTAND", -- LIZTROOP function(i, playeri, dist) + spriteext[i]:make_animated() + sprite[i].pal = math.random(32) -- sprite[i].ang = bit.band(sprite[i].ang-20, 2047) @@ -320,6 +322,18 @@ gameevent("DISPLAYROOMS", end ) +gameevent("ANIMATESPRITES", +function(aci) + local tspr = atsprite[aci] + if (tspr.picnum==1680) then +--[[ + local tspr2 = tspr:dup() + tspr2.x = tspr2.x + 512*math.cos(gv.totalclock/120) + tspr2.y = tspr2.y + 512*math.sin(gv.totalclock/120) +--]] + end +end) + printf("EVENT_INIT = %d", gv.EVENT_INIT) -- tests default defines local bittest = require "bittest" diff --git a/polymer/eduke32/source/player.h b/polymer/eduke32/source/player.h index 79ecd3a5f..3b409f0a4 100644 --- a/polymer/eduke32/source/player.h +++ b/polymer/eduke32/source/player.h @@ -40,17 +40,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define PIPEBOMB_TIMER 0x00000002 enum dukeinv_t { - GET_STEROIDS, + GET_STEROIDS, // 0 GET_SHIELD, GET_SCUBA, GET_HOLODUKE, GET_JETPACK, - GET_DUMMY1, + GET_DUMMY1, // 5 GET_ACCESS, GET_HEATS, GET_DUMMY2, GET_FIRSTAID, - GET_BOOTS, + GET_BOOTS, // 10 GET_MAX };