diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 51751f996..7ce40beb0 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -109,6 +109,7 @@ enum mobj_e { mobj_stringargs, mobj_reappear, mobj_punt_ref, + mobj_owner, }; static const char *const mobj_opt[] = { @@ -198,6 +199,7 @@ static const char *const mobj_opt[] = { "stringargs", "reappear", "punt_ref", + "owner", NULL}; #define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field]) @@ -508,6 +510,14 @@ static int mobj_get(lua_State *L) } LUA_PushUserdata(L, mo->punt_ref, META_MOBJ); break; + case mobj_owner: + if (mo->owner && P_MobjWasRemoved(mo->owner)) + { // don't put invalid mobj back into Lua. + P_SetTarget(&mo->owner, NULL); + return 0; + } + LUA_PushUserdata(L, mo->owner, META_MOBJ); + break; default: // extra custom variables in Lua memory lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); @@ -910,6 +920,15 @@ static int mobj_set(lua_State *L) P_SetTarget(&mo->punt_ref, punt_ref); } break; + case mobj_owner: + if (lua_isnil(L, 3)) + P_SetTarget(&mo->owner, NULL); + else + { + mobj_t *owner = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + P_SetTarget(&mo->owner, owner); + } + break; default: lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); diff --git a/src/p_mobj.c b/src/p_mobj.c index 3f4ec495a..8673f7181 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10252,6 +10252,8 @@ void P_MobjThinker(mobj_t *mobj) P_SetTarget(&mobj->itnext, NULL); if (mobj->punt_ref && P_MobjWasRemoved(mobj->punt_ref)) P_SetTarget(&mobj->punt_ref, NULL); + if (mobj->owner && P_MobjWasRemoved(mobj->owner)) + P_SetTarget(&mobj->owner, NULL); if (mobj->flags & MF_NOTHINK) return; @@ -11807,6 +11809,7 @@ void P_RemoveMobj(mobj_t *mobj) P_SetTarget(&mobj->itnext, NULL); P_SetTarget(&mobj->punt_ref, NULL); + P_SetTarget(&mobj->owner, NULL); P_RemoveThingTID(mobj); P_DeleteMobjStringArgs(mobj); diff --git a/src/p_mobj.h b/src/p_mobj.h index 1fbb676bf..2570acda9 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -445,6 +445,8 @@ struct mobj_t // If punt_ref, set punt_ref->reappear, treat as if this->reappear mobj_t *punt_ref; + mobj_t *owner; + // WARNING: New fields must be added separately to savegame and Lua. }; diff --git a/src/p_saveg.c b/src/p_saveg.c index ef09120d7..67a28de32 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2676,6 +2676,7 @@ typedef enum MD3_LIGHTLEVEL = 1, MD3_REAPPEAR = 1<<1, MD3_PUNT_REF = 1<<2, + MD3_OWNER = 1<<3, } mobj_diff3_t; typedef enum @@ -3000,6 +3001,8 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 diff3 |= MD3_REAPPEAR; if (mobj->punt_ref) diff3 |= MD3_PUNT_REF; + if (mobj->owner) + diff3 |= MD3_OWNER; if (diff3 != 0) diff2 |= MD2_MORE; @@ -3288,6 +3291,10 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 { WRITEUINT32(save->p, mobj->punt_ref->mobjnum); } + if (diff3 & MD3_OWNER) + { + WRITEUINT32(save->p, mobj->owner->mobjnum); + } WRITEUINT32(save->p, mobj->mobjnum); } @@ -4542,6 +4549,10 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) { mobj->punt_ref = (mobj_t *)(size_t)READUINT32(save->p); } + if (diff3 & MD3_OWNER) + { + mobj->owner = (mobj_t *)(size_t)READUINT32(save->p); + } // set sprev, snext, bprev, bnext, subsector P_SetThingPosition(mobj); @@ -5589,6 +5600,13 @@ static void P_RelinkPointers(void) if (!P_SetTarget(&mobj->punt_ref, P_FindNewPosition(temp))) CONS_Debug(DBG_GAMELOGIC, "punt_ref not found on %d\n", mobj->type); } + if (mobj->owner) + { + temp = (UINT32)(size_t)mobj->owner; + mobj->owner = NULL; + if (!P_SetTarget(&mobj->owner, P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "owner not found on %d\n", mobj->type); + } } for (i = 0; i < MAXPLAYERS; i++)