From 345e7f83b0fa7ee4d8963f6ccdc839d4a99c78f1 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 1 Jan 2023 16:55:39 -0500 Subject: [PATCH] Copy first mapthing tag to their mobjs Allows the ThingCount and ThingSound ACS functions to fully work now, and adds significantly more possibilities for scripting later. --- .../conf/udb/Includes/RingRacers_common.cfg | 5 + .../conf/udb/Includes/RingRacers_linedefs.cfg | 7 ++ src/acs/call-funcs.cpp | 34 +++--- src/p_local.h | 5 + src/p_mobj.c | 109 ++++++++++++++++++ src/p_mobj.h | 4 + src/p_saveg.c | 8 +- src/p_setup.c | 1 + 8 files changed, 154 insertions(+), 19 deletions(-) diff --git a/extras/conf/udb/Includes/RingRacers_common.cfg b/extras/conf/udb/Includes/RingRacers_common.cfg index 2be3d9af4..975919739 100644 --- a/extras/conf/udb/Includes/RingRacers_common.cfg +++ b/extras/conf/udb/Includes/RingRacers_common.cfg @@ -130,6 +130,11 @@ mapformat_udmf include("RingRacers_misc.cfg", "linedefflags_udmf"); } + linedefactivations + { + include("RingRacers_misc.cfg", "linedefactivations_udmf"); + } + linedefflagstranslation { include("RingRacers_misc.cfg", "linedefflagstranslation"); diff --git a/extras/conf/udb/Includes/RingRacers_linedefs.cfg b/extras/conf/udb/Includes/RingRacers_linedefs.cfg index 7f6bf5459..7164261a2 100644 --- a/extras/conf/udb/Includes/RingRacers_linedefs.cfg +++ b/extras/conf/udb/Includes/RingRacers_linedefs.cfg @@ -1,5 +1,7 @@ udmf { + requiresactivation = false; + misc { title = "Miscellaneous"; @@ -1556,6 +1558,7 @@ udmf linedefexecsector { title = "Linedef Executor (sector)"; + requiresactivation = true; 400 { @@ -1894,6 +1897,7 @@ udmf linedefexecplane { title = "Linedef Executor (plane movement)"; + requiresactivation = true; 403 { @@ -2031,6 +2035,7 @@ udmf linedefexecplayer { title = "Linedef Executor (player/object)"; + requiresactivation = true; 412 { @@ -2357,6 +2362,7 @@ udmf linedefexecmisc { title = "Linedef Executor (misc.)"; + requiresactivation = true; 413 { @@ -3014,6 +3020,7 @@ udmf linedefexecpoly { title = "Linedef Executor (polyobject)"; + requiresactivation = true; 480 { diff --git a/src/acs/call-funcs.cpp b/src/acs/call-funcs.cpp index 85e9ee99f..f5498894c 100644 --- a/src/acs/call-funcs.cpp +++ b/src/acs/call-funcs.cpp @@ -368,18 +368,21 @@ bool CallFunc_ThingCount(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM:: if (tid != 0) { - // TODO: Even in SRB2 next's UDMF, tag lists - // still aren't attached to mobj_t, only - // mapthing_t. Fix this. - CONS_Alert(CONS_WARNING, - "ThingCount TID field not implemented -- waiting for mobj tags.\n" - ); + mobj_t *mobj = nullptr; + + while ((mobj = P_FindMobjFromTID(tid, mobj, nullptr)) != nullptr) + { + if (ACS_CountThing(mobj, type) == true) + { + ++count; + } + } } else { // Search thinkers instead of tag lists. - thinker_t *th = NULL; - mobj_t *mobj = NULL; + thinker_t *th = nullptr; + mobj_t *mobj = nullptr; for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { @@ -862,6 +865,8 @@ bool CallFunc_SetLineSpecial(ACSVM::Thread *thread, const ACSVM::Word *argV, ACS --------------------------------------------------*/ bool CallFunc_ThingSound(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) { + auto info = &static_cast(thread)->info; + ACSVM::MapScope *map = nullptr; ACSVM::String *str = nullptr; @@ -872,6 +877,8 @@ bool CallFunc_ThingSound(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM:: sfxenum_t sfxId = sfx_None; INT32 vol = 0; + mobj_t *mobj = nullptr; + (void)argC; tag = argV[0]; @@ -901,19 +908,10 @@ bool CallFunc_ThingSound(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM:: vol = argV[2]; -#if 0 - TAG_ITER_MOBJS(tag, mobj) + while ((mobj = P_FindMobjFromTID(tag, mobj, info->mo)) != nullptr) { S_StartSoundAtVolume(mobj, sfxId, vol); } -#else - CONS_Alert(CONS_WARNING, - "ThingSound not implemented -- waiting for mobj tags.\n" - ); - - (void)tag; - (void)vol; -#endif return false; } diff --git a/src/p_local.h b/src/p_local.h index 06adebf6b..ac91cbd84 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -582,6 +582,11 @@ fixed_t P_GetMobjFeet(const mobj_t *); fixed_t P_GetMobjGround(const mobj_t *); fixed_t P_GetMobjZMovement(mobj_t *mo); +void P_InitTIDHash(void); +void P_SetThingTID(mobj_t *mo, mtag_t tid); +void P_RemoveThingTID(mobj_t *mo); +mobj_t *P_FindMobjFromTID(mtag_t tid, mobj_t *i, mobj_t *activator); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/p_mobj.c b/src/p_mobj.c index 0ad0a8478..895c337c2 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11085,6 +11085,7 @@ void P_RemoveMobj(mobj_t *mobj) memset((UINT8 *)mobj + sizeof(thinker_t), 0xff, sizeof(mobj_t) - sizeof(thinker_t)); #endif + P_RemoveThingTID(mobj); R_RemoveMobjInterpolator(mobj); // free block @@ -13270,6 +13271,8 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y, mobj->pitch = FixedAngle(mthing->pitch << FRACBITS); mobj->roll = FixedAngle(mthing->roll << FRACBITS); + P_SetThingTID(mobj, Tag_FGet(&mthing->tags)); + mthing->mobj = mobj; // Generic reverse gravity for individual objects flag. @@ -14141,3 +14144,109 @@ fixed_t P_GetMobjZMovement(mobj_t *mo) return P_ReturnThrustY(mo, slope->zangle, P_ReturnThrustX(mo, angDiff, speed)); } + +// +// Thing IDs / tags +// +// TODO: Replace this system with taglist_t instead. +// The issue is that those require a static numbered ID +// to determine which struct it belongs to, which mobjs +// don't really have. +// + +#define TID_HASH_CHAINS (131) +static mobj_t *TID_Hash[TID_HASH_CHAINS]; + +// +// P_InitTIDHash +// Initializes mobj tag hash array +// +void P_InitTIDHash(void) +{ + memset(TID_Hash, 0, TID_HASH_CHAINS * sizeof(mobj_t *)); +} + +// +// P_SetThingTID +// Adds a mobj to the hash array +// +void P_SetThingTID(mobj_t *mo, mtag_t tid) +{ + INT32 key = 0; + + if (tid == 0) + { + if (mo->tid != 0) + { + P_RemoveThingTID(mo); + } + + return; + } + + mo->tid = tid; + + // Insert at the head of this chain + key = tid % TID_HASH_CHAINS; + + mo->tid_next = TID_Hash[key]; + mo->tid_prev = &TID_Hash[key]; + TID_Hash[key] = mo; + + // Connect to any existing things in chain + if (mo->tid_next != NULL) + { + mo->tid_next->tid_prev = &(mo->tid_next); + } +} + +// +// P_RemoveThingTID +// Removes a mobj from the hash array +// +void P_RemoveThingTID(mobj_t *mo) +{ + if (mo->tid != 0 && mo->tid_prev != NULL) + { + // Fix the gap this would leave. + *(mo->tid_prev) = mo->tid_next; + + if (mo->tid_next != NULL) + { + mo->tid_next->tid_prev = mo->tid_prev; + } + } + + // Remove TID. + mo->tid = 0; +} + +// +// P_FindMobjFromTID +// Mobj tag search function. +// +mobj_t *P_FindMobjFromTID(mtag_t tid, mobj_t *i, mobj_t *activator) +{ + if (tid == 0) + { + // 0 grabs the activator, if applicable, + // for some ACS functions. + + if (i != NULL) + { + // Don't do more than once. + return NULL; + } + + return activator; + } + + i = (i != NULL) ? i->tid_next : TID_Hash[tid % TID_HASH_CHAINS]; + + while (i != NULL && i->tid != tid) + { + i = i->tid_next; + } + + return i; +} diff --git a/src/p_mobj.h b/src/p_mobj.h index e73e834da..323bcc4ae 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -338,6 +338,10 @@ struct mobj_t UINT32 flags2; // MF2_ flags UINT16 eflags; // extra flags + mtag_t tid; + mobj_t *tid_next; + mobj_t **tid_prev; // killough 8/11/98: change to ptr-to-ptr + void *skin; // overrides 'sprite' when non-NULL (for player bodies to 'remember' the skin) // Player and mobj sprites in multiplayer modes are modified // using an internal color lookup table for re-indexing. diff --git a/src/p_saveg.c b/src/p_saveg.c index b4bd2da71..aa22e6732 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1856,7 +1856,7 @@ typedef enum MD2_ROLLANGLE = 1<<14, MD2_SHADOWSCALE = 1<<15, MD2_RENDERFLAGS = 1<<16, - // 1<<17 was taken out, maybe reuse later + MD2_TID = 1<<17, MD2_SPRITEXSCALE = 1<<18, MD2_SPRITEYSCALE = 1<<19, MD2_SPRITEXOFFSET = 1<<20, @@ -2084,6 +2084,8 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 diff2 |= MD2_SHADOWSCALE; if (mobj->renderflags) diff2 |= MD2_RENDERFLAGS; + if (mobj->tid != 0) + diff2 |= MD2_TID; if (mobj->spritexscale != FRACUNIT) diff2 |= MD2_SPRITEXSCALE; if (mobj->spriteyscale != FRACUNIT) @@ -2285,6 +2287,8 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 WRITEUINT32(save->p, rf); } + if (diff2 & MD2_TID) + WRITEINT16(save->p, mobj->tid); if (diff2 & MD2_SPRITEXSCALE) WRITEFIXED(save->p, mobj->spritexscale); if (diff2 & MD2_SPRITEYSCALE) @@ -3406,6 +3410,8 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) } if (diff2 & MD2_RENDERFLAGS) mobj->renderflags = READUINT32(save->p); + if (diff2 & MD2_TID) + P_SetThingTID(mobj, READINT16(save->p)); if (diff2 & MD2_SPRITEXSCALE) mobj->spritexscale = READFIXED(save->p); else diff --git a/src/p_setup.c b/src/p_setup.c index af2b2e901..f1408e1fe 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -7474,6 +7474,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) R_InitializeLevelInterpolators(); P_InitThinkers(); + P_InitTIDHash(); R_InitMobjInterpolators(); P_InitCachedActions();