From 0bb4e0b0fa2dc84bfb0e2126b33bfc4120e7d796 Mon Sep 17 00:00:00 2001 From: --get Date: Mon, 14 Aug 2023 03:50:45 -0400 Subject: [PATCH 1/3] ACS: Better thing counting - ThingCount has an extra argument for sector tag. - CountEnemies and CountPushables have an extra argument for thing tag. - Sector tag 0 for CountEnemies and CountPushables now redirects to activator sector. --- src/acs/call-funcs.cpp | 119 +++++++++++++++++++++++++++++----------- src/acs/environment.cpp | 1 + 2 files changed, 88 insertions(+), 32 deletions(-) diff --git a/src/acs/call-funcs.cpp b/src/acs/call-funcs.cpp index 6987f65c9..e23c29e74 100644 --- a/src/acs/call-funcs.cpp +++ b/src/acs/call-funcs.cpp @@ -364,7 +364,7 @@ static bool ACS_ActivatorIsLocal(ACSVM::Thread *thread) } /*-------------------------------------------------- - static UINT32 ACS_SectorThingCounter(sector_t *sec, bool (*filter)(mobj_t *)) + static UINT32 ACS_SectorThingCounter(sector_t *sec, mtag_t thingTag, bool (*filter)(mobj_t *)) Helper function for CallFunc_CountEnemies and CallFunc_CountPushables. Counts a number @@ -372,13 +372,14 @@ static bool ACS_ActivatorIsLocal(ACSVM::Thread *thread) Input Arguments:- sec: The sector to search in. + thingTag: Thing tag to filter for. 0 allows any. filter: Filter function, total count is increased when this function returns true. Return:- Numbers of things matching the filter found. --------------------------------------------------*/ -static UINT32 ACS_SectorThingCounter(sector_t *sec, bool (*filter)(mobj_t *)) +static UINT32 ACS_SectorThingCounter(sector_t *sec, mtag_t thingTag, bool (*filter)(mobj_t *)) { msecnode_t *node = sec->touching_thinglist; // things touching this sector UINT32 count = 0; @@ -387,6 +388,11 @@ static UINT32 ACS_SectorThingCounter(sector_t *sec, bool (*filter)(mobj_t *)) { mobj_t *mo = node->m_thing; + if (thingTag != 0 && mo->tid != thingTag) + { + continue; + } + if (mo->z > sec->ceilingheight || mo->z + mo->height < sec->floorheight) { @@ -405,53 +411,76 @@ static UINT32 ACS_SectorThingCounter(sector_t *sec, bool (*filter)(mobj_t *)) } /*-------------------------------------------------- - static UINT32 ACS_SectorTagThingCounter(mtag_t tag, bool (*filter)(mobj_t *)) + static UINT32 ACS_SectorTagThingCounter(mtag_t sectorTag, sector_t *activator, mtag_t thingTag, bool (*filter)(mobj_t *)) Helper function for CallFunc_CountEnemies and CallFunc_CountPushables. Counts a number of things in the tagged sectors. Input Arguments:- - tag: The sector tag to search in. + sectorTag: The sector tag to search in. + activator: The activator sector to fall back on when sectorTag is 0. + thingTag: Thing tag to filter for. 0 allows any. filter: Filter function, total count is increased when this function returns true. Return:- Numbers of things matching the filter found. --------------------------------------------------*/ -static UINT32 ACS_SectorTagThingCounter(mtag_t tag, bool (*filter)(mobj_t *)) +static UINT32 ACS_SectorIterateThingCounter(sector_t *sec, mtag_t thingTag, bool (*filter)(mobj_t *)) { - INT32 secnum = -1; UINT32 count = 0; + boolean FOFsector = false; size_t i; - TAG_ITER_SECTORS(tag, secnum) + if (sec == nullptr) { - sector_t *sec = §ors[secnum]; - boolean FOFsector = false; + return 0; + } - // Check the lines of this sector, to see if it is a FOF control sector. - for (i = 0; i < sec->linecount; i++) + // Check the lines of this sector, to see if it is a FOF control sector. + for (i = 0; i < sec->linecount; i++) + { + INT32 targetsecnum = -1; + + if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300) { - INT32 targetsecnum = -1; - - if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300) - { - continue; - } - - FOFsector = true; - - TAG_ITER_SECTORS(sec->lines[i]->args[0], targetsecnum) - { - sector_t *targetsec = §ors[targetsecnum]; - count += ACS_SectorThingCounter(targetsec, filter); - } + continue; } - if (FOFsector == false) + FOFsector = true; + + TAG_ITER_SECTORS(sec->lines[i]->args[0], targetsecnum) { - count += ACS_SectorThingCounter(sec, filter); + sector_t *targetsec = §ors[targetsecnum]; + count += ACS_SectorThingCounter(targetsec, thingTag, filter); + } + } + + if (FOFsector == false) + { + count += ACS_SectorThingCounter(sec, thingTag, filter); + } + + return count; +} + +static UINT32 ACS_SectorTagThingCounter(mtag_t sectorTag, sector_t *activator, mtag_t thingTag, bool (*filter)(mobj_t *)) +{ + UINT32 count = 0; + + if (sectorTag == 0) + { + count += ACS_SectorIterateThingCounter(activator, thingTag, filter); + } + else + { + INT32 secnum = -1; + + TAG_ITER_SECTORS(sectorTag, secnum) + { + sector_t *sec = §ors[secnum]; + count += ACS_SectorIterateThingCounter(sec, thingTag, filter); } } @@ -485,6 +514,12 @@ bool CallFunc_Random(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word no type means indescriminate against type, no tid means search thru all thinkers. --------------------------------------------------*/ +static mobjtype_t filter_for_mobjtype = MT_NULL; // annoying but I don't wanna mess with other code +bool ACS_ThingTypeFilter(mobj_t *mo) +{ + return (ACS_CountThing(mo, filter_for_mobjtype)); +} + bool CallFunc_ThingCount(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) { ACSVM::MapScope *map = NULL; @@ -494,11 +529,10 @@ bool CallFunc_ThingCount(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM:: mobjtype_t type = MT_NULL; mtag_t tid = 0; + mtag_t sectorTag = 0; size_t count = 0; - (void)argC; - map = thread->scopeMap; str = map->getString(argV[0]); @@ -524,8 +558,21 @@ bool CallFunc_ThingCount(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM:: tid = argV[1]; - if (tid != 0) + if (argC > 2) { + sectorTag = argV[2]; + } + + if (sectorTag != 0) + { + // Search through sectors. + filter_for_mobjtype = type; + count = ACS_SectorTagThingCounter(sectorTag, nullptr, tid, ACS_ThingTypeFilter); + filter_for_mobjtype = MT_NULL; + } + else if (tid != 0) + { + // Search through tag lists. mobj_t *mobj = nullptr; while ((mobj = P_FindMobjFromTID(tid, mobj, nullptr)) != nullptr) @@ -1300,13 +1347,17 @@ bool ACS_EnemyFilter(mobj_t *mo) bool CallFunc_CountEnemies(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) { + auto info = &static_cast(thread)->info; + mtag_t tag = 0; + mtag_t tid = 0; UINT32 count = 0; (void)argC; tag = argV[0]; - count = ACS_SectorTagThingCounter(tag, ACS_EnemyFilter); + tid = argV[1]; + count = ACS_SectorTagThingCounter(tag, info->sector, tid, ACS_EnemyFilter); thread->dataStk.push(count); return false; @@ -1325,13 +1376,17 @@ bool ACS_PushableFilter(mobj_t *mo) bool CallFunc_CountPushables(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) { + auto info = &static_cast(thread)->info; + mtag_t tag = 0; + mtag_t tid = 0; UINT32 count = 0; (void)argC; tag = argV[0]; - count = ACS_SectorTagThingCounter(tag, ACS_PushableFilter); + tid = argV[1]; + count = ACS_SectorTagThingCounter(tag, info->sector, tid, ACS_PushableFilter); thread->dataStk.push(count); return false; diff --git a/src/acs/environment.cpp b/src/acs/environment.cpp index 0843773f8..c07a4e5ec 100644 --- a/src/acs/environment.cpp +++ b/src/acs/environment.cpp @@ -160,6 +160,7 @@ Environment::Environment() addFuncDataACS0( 309, addCallFunc(CallFunc_EncoreMode)); addFuncDataACS0( 310, addCallFunc(CallFunc_BreakTheCapsules)); addFuncDataACS0( 311, addCallFunc(CallFunc_TimeAttack)); + addFuncDataACS0( 312, addCallFunc(CallFunc_ThingCount)); addFuncDataACS0( 500, addCallFunc(CallFunc_CameraWait)); addFuncDataACS0( 501, addCallFunc(CallFunc_PodiumPosition)); From ae7325cbc3dc0e1ea412b9f2a6b6638b42469b6a Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 14 Aug 2023 04:06:11 -0400 Subject: [PATCH 2/3] Add PlayerNumber and ActivatorTID from ZDoom --- src/acs/call-funcs.cpp | 47 +++++++++++++++++++++++++++++++++++++++++ src/acs/call-funcs.hpp | 2 ++ src/acs/environment.cpp | 3 +++ 3 files changed, 52 insertions(+) diff --git a/src/acs/call-funcs.cpp b/src/acs/call-funcs.cpp index e23c29e74..a241ab370 100644 --- a/src/acs/call-funcs.cpp +++ b/src/acs/call-funcs.cpp @@ -1236,6 +1236,53 @@ bool CallFunc_PlayerScore(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM: return false; } +/*-------------------------------------------------- + bool CallFunc_PlayerNumber(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) + + Returns the activating player's ID. +--------------------------------------------------*/ +bool CallFunc_PlayerNumber(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) +{ + auto info = &static_cast(thread)->info; + INT16 playerID = -1; + + (void)argV; + (void)argC; + + if ((info != NULL) + && (info->mo != NULL && P_MobjWasRemoved(info->mo) == false) + && (info->mo->player != NULL)) + { + playerID = (info->mo->player - players); + } + + thread->dataStk.push(playerID); + return false; +} + +/*-------------------------------------------------- + bool CallFunc_ActivatorTID(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) + + Returns the activating object's TID. +--------------------------------------------------*/ +bool CallFunc_ActivatorTID(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) +{ + auto info = &static_cast(thread)->info; + INT16 tid = 0; + + (void)argV; + (void)argC; + + if ((info != NULL) + && (info->mo != NULL && P_MobjWasRemoved(info->mo) == false)) + { + tid = info->mo->tid; + } + + thread->dataStk.push(tid); + return false; +} + /*-------------------------------------------------- bool CallFunc_EndLog(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) diff --git a/src/acs/call-funcs.hpp b/src/acs/call-funcs.hpp index 9bc46d0ef..bb9aa23b5 100644 --- a/src/acs/call-funcs.hpp +++ b/src/acs/call-funcs.hpp @@ -60,6 +60,8 @@ bool CallFunc_EndPrintBold(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM bool CallFunc_PlayerTeam(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_PlayerRings(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_PlayerScore(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); +bool CallFunc_PlayerNumber(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); +bool CallFunc_ActivatorTID(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_EndLog(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_strcmp(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); diff --git a/src/acs/environment.cpp b/src/acs/environment.cpp index c07a4e5ec..78ffa2256 100644 --- a/src/acs/environment.cpp +++ b/src/acs/environment.cpp @@ -108,6 +108,9 @@ Environment::Environment() // 225 to 243: Implemented by ACSVM + addCodeDataACS0(247, {"", 0, addCallFunc(CallFunc_PlayerNumber)}); + addCodeDataACS0(248, {"", 0, addCallFunc(CallFunc_ActivatorTID)}); + // 253: Implemented by ACSVM // 256 to 257: Implemented by ACSVM From eff895178bf6899b171379ae6cb4e140bb02c569 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 14 Aug 2023 18:11:33 -0700 Subject: [PATCH 3/3] ACS_SectorThingCounter: fix infinite loop in touching iterator --- src/acs/call-funcs.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/acs/call-funcs.cpp b/src/acs/call-funcs.cpp index a241ab370..747d74144 100644 --- a/src/acs/call-funcs.cpp +++ b/src/acs/call-funcs.cpp @@ -381,10 +381,9 @@ static bool ACS_ActivatorIsLocal(ACSVM::Thread *thread) --------------------------------------------------*/ static UINT32 ACS_SectorThingCounter(sector_t *sec, mtag_t thingTag, bool (*filter)(mobj_t *)) { - msecnode_t *node = sec->touching_thinglist; // things touching this sector UINT32 count = 0; - while (node) + for (msecnode_t *node = sec->touching_thinglist; node; node = node->m_thinglist_next) // things touching this sector { mobj_t *mo = node->m_thing; @@ -403,8 +402,6 @@ static UINT32 ACS_SectorThingCounter(sector_t *sec, mtag_t thingTag, bool (*filt { count++; } - - node = node->m_thinglist_next; } return count;