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.
This commit is contained in:
Sally Coolatta 2023-01-01 16:55:39 -05:00
parent a602530811
commit 345e7f83b0
8 changed files with 154 additions and 19 deletions

View file

@ -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");

View file

@ -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
{

View file

@ -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 *>(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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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.

View file

@ -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

View file

@ -7474,6 +7474,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
R_InitializeLevelInterpolators();
P_InitThinkers();
P_InitTIDHash();
R_InitMobjInterpolators();
P_InitCachedActions();