diff --git a/src/p_local.h b/src/p_local.h index d0805b6ad220f10f4c5426686fabff0f602f4a11..11bfa5aedafb6bc95abb7d7e118590ebd5500384 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -597,8 +597,9 @@ fixed_t P_GetMobjZMovement(mobj_t *mo); boolean P_MobjCanChangeFlip(mobj_t *mobj); void P_InitTIDHash(void); -void P_SetThingTID(mobj_t *mo, mtag_t tid); +void P_AddThingTID(mobj_t *mo); void P_RemoveThingTID(mobj_t *mo); +void P_SetThingTID(mobj_t *mo, mtag_t tid); mobj_t *P_FindMobjFromTID(mtag_t tid, mobj_t *i, mobj_t *activator); void P_DeleteMobjStringArgs(mobj_t *mobj); diff --git a/src/p_mobj.c b/src/p_mobj.c index 17283f951f5399321c4f31763b2cbd8a103a0d5e..e6effb1fc6a0a54329f7a7d47b93ba270eca4864 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11465,6 +11465,9 @@ void P_RemoveMobj(mobj_t *mobj) mobj->health = 0; // Just because + // unlink from tid chains + P_RemoveThingTID(mobj); + // unlink from sector and block lists P_UnsetThingPosition(mobj); if (sector_list) @@ -11518,7 +11521,6 @@ void P_RemoveMobj(mobj_t *mobj) P_SetTarget(&mobj->punt_ref, NULL); P_SetTarget(&mobj->owner, NULL); - P_RemoveThingTID(mobj); P_DeleteMobjStringArgs(mobj); R_RemoveMobjInterpolator(mobj); @@ -11582,9 +11584,9 @@ void P_FreePrecipMobj(precipmobj_t *mobj) // Clearing out stuff for savegames void P_RemoveSavegameMobj(mobj_t *mobj) { - // unlink from sector and block lists if (((thinker_t *)mobj)->function.acp1 == (actionf_p1)P_NullPrecipThinker) { + // unlink from sector and block lists P_UnsetPrecipThingPosition((precipmobj_t *)mobj); if (precipsector_list) @@ -11595,6 +11597,9 @@ void P_RemoveSavegameMobj(mobj_t *mobj) } else { + // unlink from tid chains + P_RemoveThingTID(mobj); + // unlink from sector and block lists P_UnsetThingPosition(mobj); @@ -11604,12 +11609,13 @@ void P_RemoveSavegameMobj(mobj_t *mobj) P_DelSeclist(sector_list); sector_list = NULL; } + + P_DeleteMobjStringArgs(mobj); } // stop any playing sound S_StopSound(mobj); - P_DeleteMobjStringArgs(mobj); R_RemoveMobjInterpolator(mobj); // free block @@ -13976,8 +13982,6 @@ void P_CopyMapThingSpecialFieldsToMobj(const mapthing_t *mthing, mobj_t *mobj) { size_t arg = SIZE_MAX; - P_SetThingTID(mobj, mthing->tid); - mobj->special = mthing->special; for (arg = 0; arg < NUM_MAPTHING_ARGS; arg++) @@ -14048,6 +14052,9 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y, mobj->spritexscale = mthing->spritexscale; mobj->spriteyscale = mthing->spriteyscale; + mobj->tid = mthing->tid; + P_AddThingTID(mobj); + P_CopyMapThingSpecialFieldsToMobj(mthing, mobj); if (!P_SetupSpawnedMapThing(mthing, mobj)) @@ -15028,27 +15035,25 @@ void P_InitTIDHash(void) } // -// P_SetThingTID +// P_AddThingTID // Adds a mobj to the hash array // -void P_SetThingTID(mobj_t *mo, mtag_t tid) +void P_AddThingTID(mobj_t *mo) { - INT32 key = 0; + I_Assert(!P_MobjWasRemoved(mo)); - if (tid == 0) + if (mo->tid <= 0) { - if (mo->tid != 0) - { - P_RemoveThingTID(mo); - } - + // 0 is no TID, and negative + // values are reserved. + mo->tid = 0; + mo->tid_next = NULL; + mo->tid_prev = NULL; return; } - mo->tid = tid; - // Insert at the head of this chain - key = tid % TID_HASH_CHAINS; + INT32 key = mo->tid % TID_HASH_CHAINS; mo->tid_next = TID_Hash[key]; mo->tid_prev = &TID_Hash[key]; @@ -15076,30 +15081,70 @@ void P_RemoveThingTID(mobj_t *mo) { mo->tid_next->tid_prev = mo->tid_prev; } + + mo->tid_prev = NULL; + mo->tid_next = NULL; } // Remove TID. mo->tid = 0; } +// +// P_SetThingTID +// Changes a mobj's TID +// +void P_SetThingTID(mobj_t *mo, mtag_t tid) +{ + P_RemoveThingTID(mo); + + if (P_MobjWasRemoved(mo)) + { + // Do not assign if it is going to be removed. + return; + } + + mo->tid = tid; + P_AddThingTID(mo); +} + // // P_FindMobjFromTID // Mobj tag search function. // mobj_t *P_FindMobjFromTID(mtag_t tid, mobj_t *i, mobj_t *activator) { - if (tid == 0) + if (tid <= 0) { - // 0 grabs the activator, if applicable, - // for some ACS functions. + if (tid == 0) + { + // 0 grabs the activator, if applicable, + // for some ACS functions. + + if (i != NULL) + { + // Don't do more than once. + return NULL; + } - if (i != NULL) + return activator; + } + else if (tid >= -MAXPLAYERS) { - // Don't do more than once. + // -1 to -MAXPLAYERS returns an arbritrary player's object. + INT32 playerID = -tid - 1; + player_t *player = &players[ playerID ]; + + if (playeringame[playerID] == true && player->spectator == false) + { + return player->mo; + } + return NULL; } - return activator; + // Invalid input, return NULL. + return NULL; } i = (i != NULL) ? i->tid_next : TID_Hash[tid % TID_HASH_CHAINS]; diff --git a/src/p_saveg.c b/src/p_saveg.c index a75274b0560ed54fdf9078ee71692866f8eae776..721285c9a51441353cb947a551a3774b74717499 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -4663,10 +4663,7 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) if (diff2 & MD2_RENDERFLAGS) mobj->renderflags = READUINT32(save->p); if (diff2 & MD2_TID) - { - INT16 tid = READINT16(save->p); - P_SetThingTID(mobj, tid); - } + mobj->tid = READINT16(save->p); if (diff2 & MD2_SPRITESCALE) { mobj->spritexscale = READFIXED(save->p); @@ -4788,6 +4785,9 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) mobj->owner = (mobj_t *)(size_t)READUINT32(save->p); } + // link tid set earlier + P_AddThingTID(mobj); + // set sprev, snext, bprev, bnext, subsector P_SetThingPosition(mobj);