From a1276041339a87164cf84aaf31049ea256be1770 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Wed, 22 Oct 2025 22:53:05 +1100 Subject: [PATCH 01/16] refactor: Split historic damage calculation into separate method --- .../GameEngine/Include/GameLogic/Weapon.h | 1 + .../Source/GameLogic/Object/Weapon.cpp | 24 ++++++++++++------- .../GameEngine/Include/GameLogic/Weapon.h | 1 + .../Source/GameLogic/Object/Weapon.cpp | 24 ++++++++++++------- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/Weapon.h b/Generals/Code/GameEngine/Include/GameLogic/Weapon.h index dda3d86b33..73ba5a6500 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Weapon.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Weapon.h @@ -460,6 +460,7 @@ class WeaponTemplate : public MemoryPoolObject // actually deal out the damage. void dealDamageInternal(ObjectID sourceID, ObjectID victimID, const Coord3D *pos, const WeaponBonus& bonus, Bool isProjectileDetonation) const; void trimOldHistoricDamage() const; + void processHistoricDamage(const Object* source, const Coord3D* pos) const; private: diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index 2eedfb79bb..6dc9292e72 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1121,16 +1121,8 @@ static Bool is2DDistSquaredLessThan(const Coord3D& a, const Coord3D& b, Real dis } //------------------------------------------------------------------------------------------------- -void WeaponTemplate::dealDamageInternal(ObjectID sourceID, ObjectID victimID, const Coord3D *pos, const WeaponBonus& bonus, Bool isProjectileDetonation) const +void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* pos) const { - if (sourceID == 0) // must have a source - return; - - if (victimID == 0 && pos == NULL) // must have some sort of destination - return; - - Object *source = TheGameLogic->findObjectByID(sourceID); // might be null... - // /** @todo We need to rewrite the historic stuff ... if you fire 5 missiles, and the 5th, // one creates a firestorm ... and then half a second later another volley of 5 missiles @@ -1176,6 +1168,20 @@ void WeaponTemplate::dealDamageInternal(ObjectID sourceID, ObjectID victimID, co } } +} + +//------------------------------------------------------------------------------------------------- +void WeaponTemplate::dealDamageInternal(ObjectID sourceID, ObjectID victimID, const Coord3D *pos, const WeaponBonus& bonus, Bool isProjectileDetonation) const +{ + if (sourceID == 0) // must have a source + return; + + if (victimID == 0 && pos == NULL) // must have some sort of destination + return; + + Object *source = TheGameLogic->findObjectByID(sourceID); // might be null... + + processHistoricDamage(source, pos); //DEBUG_LOG(("WeaponTemplate::dealDamageInternal: dealing damage %s at frame %d",m_name.str(),TheGameLogic->getFrame())); diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h index 3435cb95e1..a4707cef10 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h @@ -480,6 +480,7 @@ class WeaponTemplate : public MemoryPoolObject // actually deal out the damage. void dealDamageInternal(ObjectID sourceID, ObjectID victimID, const Coord3D *pos, const WeaponBonus& bonus, Bool isProjectileDetonation) const; void trimOldHistoricDamage() const; + void processHistoricDamage(const Object* source, const Coord3D* pos) const; private: diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index 7bdb420798..ddb67647b5 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1199,16 +1199,8 @@ static Bool is2DDistSquaredLessThan(const Coord3D& a, const Coord3D& b, Real dis } //------------------------------------------------------------------------------------------------- -void WeaponTemplate::dealDamageInternal(ObjectID sourceID, ObjectID victimID, const Coord3D *pos, const WeaponBonus& bonus, Bool isProjectileDetonation) const +void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* pos) const { - if (sourceID == 0) // must have a source - return; - - if (victimID == 0 && pos == NULL) // must have some sort of destination - return; - - Object *source = TheGameLogic->findObjectByID(sourceID); // might be null... - // /** @todo We need to rewrite the historic stuff ... if you fire 5 missiles, and the 5th, // one creates a firestorm ... and then half a second later another volley of 5 missiles @@ -1254,6 +1246,20 @@ void WeaponTemplate::dealDamageInternal(ObjectID sourceID, ObjectID victimID, co } } +} + +//------------------------------------------------------------------------------------------------- +void WeaponTemplate::dealDamageInternal(ObjectID sourceID, ObjectID victimID, const Coord3D *pos, const WeaponBonus& bonus, Bool isProjectileDetonation) const +{ + if (sourceID == 0) // must have a source + return; + + if (victimID == 0 && pos == NULL) // must have some sort of destination + return; + + Object *source = TheGameLogic->findObjectByID(sourceID); // might be null... + + processHistoricDamage(source, pos); //DEBUG_LOG(("WeaponTemplate::dealDamageInternal: dealing damage %s at frame %d",m_name.str(),TheGameLogic->getFrame())); From bc50362da58ba1e66e3831346bc1565bf7bbe044 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Wed, 22 Oct 2025 22:59:10 +1100 Subject: [PATCH 02/16] perf: Only trim old historic damage for historic weapons --- Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp | 4 ++-- GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index 6dc9292e72..1954c55857 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1130,10 +1130,10 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* // firestorms (CBD) */ // - trimOldHistoricDamage(); - if( m_historicBonusCount > 0 && m_historicBonusWeapon != this ) { + trimOldHistoricDamage(); + Real radSqr = m_historicBonusRadius * m_historicBonusRadius; Int count = 0; UnsignedInt frameNow = TheGameLogic->getFrame(); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index ddb67647b5..9607fa9a02 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1208,10 +1208,10 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* // firestorms (CBD) */ // - trimOldHistoricDamage(); - if( m_historicBonusCount > 0 && m_historicBonusWeapon != this ) { + trimOldHistoricDamage(); + Real radSqr = m_historicBonusRadius * m_historicBonusRadius; Int count = 0; UnsignedInt frameNow = TheGameLogic->getFrame(); From 74ea02410f337517d98a04a5d0338ad18cef6e5f Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Wed, 22 Oct 2025 23:09:10 +1100 Subject: [PATCH 03/16] bugfix: Triggered historic damage no longer resets all instances for the same weapon template --- .../GameEngine/Include/GameLogic/Weapon.h | 2 + .../Source/GameLogic/Object/Weapon.cpp | 50 +++++++++++++++++++ .../GameEngine/Include/GameLogic/Weapon.h | 2 + .../Source/GameLogic/Object/Weapon.cpp | 50 +++++++++++++++++++ 4 files changed, 104 insertions(+) diff --git a/Generals/Code/GameEngine/Include/GameLogic/Weapon.h b/Generals/Code/GameEngine/Include/GameLogic/Weapon.h index 73ba5a6500..93318dd93c 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Weapon.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Weapon.h @@ -320,10 +320,12 @@ struct HistoricWeaponDamageInfo // The time and location this weapon was fired UnsignedInt frame; Coord3D location; + Bool triggered; HistoricWeaponDamageInfo(UnsignedInt f, const Coord3D& l) : frame(f), location(l) { + triggered = false; } }; diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index 1954c55857..a2ce9f9d33 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1093,6 +1093,7 @@ UnsignedInt WeaponTemplate::fireWeaponTemplate } //------------------------------------------------------------------------------------------------- +#if RETAIL_COMPATIBLE_CRC void WeaponTemplate::trimOldHistoricDamage() const { UnsignedInt expirationDate = TheGameLogic->getFrame() - TheGlobalData->m_historicDamageLimit; @@ -1112,6 +1113,21 @@ void WeaponTemplate::trimOldHistoricDamage() const } } } +#else +void WeaponTemplate::trimOldHistoricDamage() const +{ + HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); + + while (it != m_historicDamage.end()) + { + UnsignedInt expirationDate = it->frame + m_historicBonusTime; + if (TheGameLogic->getFrame() > expirationDate || it->triggered) + it = m_historicDamage.erase(it); + else + ++it; + } +} +#endif //------------------------------------------------------------------------------------------------- static Bool is2DDistSquaredLessThan(const Coord3D& a, const Coord3D& b, Real distSqr) @@ -1121,6 +1137,7 @@ static Bool is2DDistSquaredLessThan(const Coord3D& a, const Coord3D& b, Real dis } //------------------------------------------------------------------------------------------------- +#if RETAIL_COMPATIBLE_CRC void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* pos) const { // @@ -1169,6 +1186,39 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* } } +#else +void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* pos) const +{ + if (m_historicBonusCount > 0 && m_historicBonusWeapon != this) + { + trimOldHistoricDamage(); + + Real radSqr = m_historicBonusRadius * m_historicBonusRadius; + Int count = 0; + for (HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); it != m_historicDamage.end(); ++it) + { + if (is2DDistSquaredLessThan(*pos, it->location, radSqr)) + { + // This one is close enough in time and distance, so count it. This is tracked by template since it applies + // across units, so don't try to clear historicDamage on success in here. + (*it).triggered = true; + ++count; + } + } + + if (count >= m_historicBonusCount - 1) // minus 1 since we include ourselves implicitly + TheWeaponStore->createAndFireTempWeapon(m_historicBonusWeapon, source, pos); + else + { + for (HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); it != m_historicDamage.end(); ++it) + (*it).triggered = false; + + // add AFTER checking for historic stuff + m_historicDamage.push_back(HistoricWeaponDamageInfo(TheGameLogic->getFrame(), *pos)); + } + } +} +#endif //------------------------------------------------------------------------------------------------- void WeaponTemplate::dealDamageInternal(ObjectID sourceID, ObjectID victimID, const Coord3D *pos, const WeaponBonus& bonus, Bool isProjectileDetonation) const diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h index a4707cef10..0d22562a01 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h @@ -331,10 +331,12 @@ struct HistoricWeaponDamageInfo // The time and location this weapon was fired UnsignedInt frame; Coord3D location; + Bool triggered; HistoricWeaponDamageInfo(UnsignedInt f, const Coord3D& l) : frame(f), location(l) { + triggered = false; } }; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index 9607fa9a02..51dcc32179 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1171,6 +1171,7 @@ UnsignedInt WeaponTemplate::fireWeaponTemplate } //------------------------------------------------------------------------------------------------- +#if RETAIL_COMPATIBLE_CRC void WeaponTemplate::trimOldHistoricDamage() const { UnsignedInt expirationDate = TheGameLogic->getFrame() - TheGlobalData->m_historicDamageLimit; @@ -1190,6 +1191,21 @@ void WeaponTemplate::trimOldHistoricDamage() const } } } +#else +void WeaponTemplate::trimOldHistoricDamage() const +{ + HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); + + while (it != m_historicDamage.end()) + { + UnsignedInt expirationDate = it->frame + m_historicBonusTime; + if (TheGameLogic->getFrame() > expirationDate || it->triggered) + it = m_historicDamage.erase(it); + else + ++it; + } +} +#endif //------------------------------------------------------------------------------------------------- static Bool is2DDistSquaredLessThan(const Coord3D& a, const Coord3D& b, Real distSqr) @@ -1199,6 +1215,7 @@ static Bool is2DDistSquaredLessThan(const Coord3D& a, const Coord3D& b, Real dis } //------------------------------------------------------------------------------------------------- +#if RETAIL_COMPATIBLE_CRC void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* pos) const { // @@ -1247,6 +1264,39 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* } } +#else +void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* pos) const +{ + if (m_historicBonusCount > 0 && m_historicBonusWeapon != this) + { + trimOldHistoricDamage(); + + Real radSqr = m_historicBonusRadius * m_historicBonusRadius; + Int count = 0; + for (HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); it != m_historicDamage.end(); ++it) + { + if (is2DDistSquaredLessThan(*pos, it->location, radSqr)) + { + // This one is close enough in time and distance, so count it. This is tracked by template since it applies + // across units, so don't try to clear historicDamage on success in here. + (*it).triggered = true; + ++count; + } + } + + if (count >= m_historicBonusCount - 1) // minus 1 since we include ourselves implicitly + TheWeaponStore->createAndFireTempWeapon(m_historicBonusWeapon, source, pos); + else + { + for (HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); it != m_historicDamage.end(); ++it) + (*it).triggered = false; + + // add AFTER checking for historic stuff + m_historicDamage.push_back(HistoricWeaponDamageInfo(TheGameLogic->getFrame(), *pos)); + } + } +} +#endif //------------------------------------------------------------------------------------------------- void WeaponTemplate::dealDamageInternal(ObjectID sourceID, ObjectID victimID, const Coord3D *pos, const WeaponBonus& bonus, Bool isProjectileDetonation) const From 33ebfadf45c760214dd4343462aa47c46b798547 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Sun, 26 Oct 2025 16:17:57 +1100 Subject: [PATCH 04/16] refactor: Minor optimisation --- .../Source/GameLogic/Object/Weapon.cpp | 19 ++++++++++--------- .../Source/GameLogic/Object/Weapon.cpp | 19 ++++++++++--------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index a2ce9f9d33..8884c5fe32 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1203,19 +1203,20 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* // across units, so don't try to clear historicDamage on success in here. (*it).triggered = true; ++count; + + if (count >= m_historicBonusCount - 1) // minus 1 since we include ourselves implicitly + { + TheWeaponStore->createAndFireTempWeapon(m_historicBonusWeapon, source, pos); + return; + } } } - if (count >= m_historicBonusCount - 1) // minus 1 since we include ourselves implicitly - TheWeaponStore->createAndFireTempWeapon(m_historicBonusWeapon, source, pos); - else - { - for (HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); it != m_historicDamage.end(); ++it) - (*it).triggered = false; + for (HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); it != m_historicDamage.end(); ++it) + (*it).triggered = false; - // add AFTER checking for historic stuff - m_historicDamage.push_back(HistoricWeaponDamageInfo(TheGameLogic->getFrame(), *pos)); - } + // add AFTER checking for historic stuff + m_historicDamage.push_back(HistoricWeaponDamageInfo(TheGameLogic->getFrame(), *pos)); } } #endif diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index 51dcc32179..e890679454 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1281,19 +1281,20 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* // across units, so don't try to clear historicDamage on success in here. (*it).triggered = true; ++count; + + if (count >= m_historicBonusCount - 1) // minus 1 since we include ourselves implicitly + { + TheWeaponStore->createAndFireTempWeapon(m_historicBonusWeapon, source, pos); + return; + } } } - if (count >= m_historicBonusCount - 1) // minus 1 since we include ourselves implicitly - TheWeaponStore->createAndFireTempWeapon(m_historicBonusWeapon, source, pos); - else - { - for (HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); it != m_historicDamage.end(); ++it) - (*it).triggered = false; + for (HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); it != m_historicDamage.end(); ++it) + (*it).triggered = false; - // add AFTER checking for historic stuff - m_historicDamage.push_back(HistoricWeaponDamageInfo(TheGameLogic->getFrame(), *pos)); - } + // add AFTER checking for historic stuff + m_historicDamage.push_back(HistoricWeaponDamageInfo(TheGameLogic->getFrame(), *pos)); } } #endif From 5ad4ea0316c4254c09fc24ecc0d7b7e211a6e369 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Sun, 26 Oct 2025 16:19:05 +1100 Subject: [PATCH 05/16] refactor: Standardise struct initialisation --- Generals/Code/GameEngine/Include/GameLogic/Weapon.h | 3 +-- GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/Weapon.h b/Generals/Code/GameEngine/Include/GameLogic/Weapon.h index 93318dd93c..8903222e18 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Weapon.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Weapon.h @@ -323,9 +323,8 @@ struct HistoricWeaponDamageInfo Bool triggered; HistoricWeaponDamageInfo(UnsignedInt f, const Coord3D& l) : - frame(f), location(l) + frame(f), location(l), triggered(false) { - triggered = false; } }; diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h index 0d22562a01..cf4dd3c47d 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h @@ -334,9 +334,8 @@ struct HistoricWeaponDamageInfo Bool triggered; HistoricWeaponDamageInfo(UnsignedInt f, const Coord3D& l) : - frame(f), location(l) + frame(f), location(l), triggered(false) { - triggered = false; } }; From 5fe0be7e1b04d618865024b843817fe927c18a76 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Sun, 26 Oct 2025 16:20:10 +1100 Subject: [PATCH 06/16] refactor: Clearer naming --- Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp | 4 ++-- GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index 8884c5fe32..2b05d8fb54 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1120,8 +1120,8 @@ void WeaponTemplate::trimOldHistoricDamage() const while (it != m_historicDamage.end()) { - UnsignedInt expirationDate = it->frame + m_historicBonusTime; - if (TheGameLogic->getFrame() > expirationDate || it->triggered) + UnsignedInt expirationFrame = it->frame + m_historicBonusTime; + if (TheGameLogic->getFrame() > expirationFrame || it->triggered) it = m_historicDamage.erase(it); else ++it; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index e890679454..9fc9e723f7 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1198,8 +1198,8 @@ void WeaponTemplate::trimOldHistoricDamage() const while (it != m_historicDamage.end()) { - UnsignedInt expirationDate = it->frame + m_historicBonusTime; - if (TheGameLogic->getFrame() > expirationDate || it->triggered) + UnsignedInt expirationFrame = it->frame + m_historicBonusTime; + if (TheGameLogic->getFrame() > expirationFrame || it->triggered) it = m_historicDamage.erase(it); else ++it; From e41a7b22608f57f77b484d0cdf4f83bc4d1a388b Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Mon, 27 Oct 2025 18:31:11 +1100 Subject: [PATCH 07/16] refactor: Reduce calculations and assignments in the trim loop --- .../Code/GameEngine/Source/GameLogic/Object/Weapon.cpp | 9 +++++++-- .../Code/GameEngine/Source/GameLogic/Object/Weapon.cpp | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index 2b05d8fb54..35db4522da 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1116,12 +1116,17 @@ void WeaponTemplate::trimOldHistoricDamage() const #else void WeaponTemplate::trimOldHistoricDamage() const { + if (m_historicDamage.empty()) + return; + + const UnsignedInt currentFrame = TheGameLogic->getFrame(); + const UnsignedInt expirationFrame = currentFrame - m_historicBonusTime; + HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); while (it != m_historicDamage.end()) { - UnsignedInt expirationFrame = it->frame + m_historicBonusTime; - if (TheGameLogic->getFrame() > expirationFrame || it->triggered) + if (it->frame <= expirationFrame || it->triggered) it = m_historicDamage.erase(it); else ++it; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index 9fc9e723f7..a0ac995f55 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1194,12 +1194,17 @@ void WeaponTemplate::trimOldHistoricDamage() const #else void WeaponTemplate::trimOldHistoricDamage() const { + if (m_historicDamage.empty()) + return; + + const UnsignedInt currentFrame = TheGameLogic->getFrame(); + const UnsignedInt expirationFrame = currentFrame - m_historicBonusTime; + HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); while (it != m_historicDamage.end()) { - UnsignedInt expirationFrame = it->frame + m_historicBonusTime; - if (TheGameLogic->getFrame() > expirationFrame || it->triggered) + if (it->frame <= expirationFrame || it->triggered) it = m_historicDamage.erase(it); else ++it; From 0582d006908079353515e45241d02b943592b551 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Mon, 27 Oct 2025 18:36:48 +1100 Subject: [PATCH 08/16] refactor: Only process historic damage if enough instances exist to meet the bonus count requirement --- .../Source/GameLogic/Object/Weapon.cpp | 35 +++++++++++-------- .../Source/GameLogic/Object/Weapon.cpp | 35 +++++++++++-------- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index 35db4522da..d74342bb34 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1198,27 +1198,32 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* { trimOldHistoricDamage(); - Real radSqr = m_historicBonusRadius * m_historicBonusRadius; - Int count = 0; - for (HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); it != m_historicDamage.end(); ++it) + const Int requiredCount = m_historicBonusCount - 1; // minus 1 since we include ourselves implicitly + if (m_historicDamage.size() >= requiredCount) { - if (is2DDistSquaredLessThan(*pos, it->location, radSqr)) - { - // This one is close enough in time and distance, so count it. This is tracked by template since it applies - // across units, so don't try to clear historicDamage on success in here. - (*it).triggered = true; - ++count; + const Real radSqr = m_historicBonusRadius * m_historicBonusRadius; + Int count = 0; - if (count >= m_historicBonusCount - 1) // minus 1 since we include ourselves implicitly + for (HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); it != m_historicDamage.end(); ++it) + { + if (is2DDistSquaredLessThan(*pos, it->location, radSqr)) { - TheWeaponStore->createAndFireTempWeapon(m_historicBonusWeapon, source, pos); - return; + // This one is close enough in time and distance, so count it. This is tracked by template since it applies + // across units, so don't try to clear historicDamage on success in here. + (*it).triggered = true; + ++count; + + if (count >= requiredCount) + { + TheWeaponStore->createAndFireTempWeapon(m_historicBonusWeapon, source, pos); + return; + } } } - } - for (HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); it != m_historicDamage.end(); ++it) - (*it).triggered = false; + for (HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); it != m_historicDamage.end(); ++it) + (*it).triggered = false; + } // add AFTER checking for historic stuff m_historicDamage.push_back(HistoricWeaponDamageInfo(TheGameLogic->getFrame(), *pos)); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index a0ac995f55..6abecf246b 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1276,27 +1276,32 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* { trimOldHistoricDamage(); - Real radSqr = m_historicBonusRadius * m_historicBonusRadius; - Int count = 0; - for (HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); it != m_historicDamage.end(); ++it) + const Int requiredCount = m_historicBonusCount - 1; // minus 1 since we include ourselves implicitly + if (m_historicDamage.size() >= requiredCount) { - if (is2DDistSquaredLessThan(*pos, it->location, radSqr)) - { - // This one is close enough in time and distance, so count it. This is tracked by template since it applies - // across units, so don't try to clear historicDamage on success in here. - (*it).triggered = true; - ++count; + const Real radSqr = m_historicBonusRadius * m_historicBonusRadius; + Int count = 0; - if (count >= m_historicBonusCount - 1) // minus 1 since we include ourselves implicitly + for (HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); it != m_historicDamage.end(); ++it) + { + if (is2DDistSquaredLessThan(*pos, it->location, radSqr)) { - TheWeaponStore->createAndFireTempWeapon(m_historicBonusWeapon, source, pos); - return; + // This one is close enough in time and distance, so count it. This is tracked by template since it applies + // across units, so don't try to clear historicDamage on success in here. + (*it).triggered = true; + ++count; + + if (count >= requiredCount) + { + TheWeaponStore->createAndFireTempWeapon(m_historicBonusWeapon, source, pos); + return; + } } } - } - for (HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); it != m_historicDamage.end(); ++it) - (*it).triggered = false; + for (HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); it != m_historicDamage.end(); ++it) + (*it).triggered = false; + } // add AFTER checking for historic stuff m_historicDamage.push_back(HistoricWeaponDamageInfo(TheGameLogic->getFrame(), *pos)); From 5fef7b397201f04bb8f08267732d599f46ad19fa Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Mon, 27 Oct 2025 21:26:09 +1100 Subject: [PATCH 09/16] refactor: Split trim logic --- .../GameEngine/Include/GameLogic/Weapon.h | 1 + .../Source/GameLogic/Object/Weapon.cpp | 19 +++++++++++++++++-- .../GameEngine/Include/GameLogic/Weapon.h | 1 + .../Source/GameLogic/Object/Weapon.cpp | 19 +++++++++++++++++-- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/Weapon.h b/Generals/Code/GameEngine/Include/GameLogic/Weapon.h index 8903222e18..4df63e338b 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Weapon.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Weapon.h @@ -461,6 +461,7 @@ class WeaponTemplate : public MemoryPoolObject // actually deal out the damage. void dealDamageInternal(ObjectID sourceID, ObjectID victimID, const Coord3D *pos, const WeaponBonus& bonus, Bool isProjectileDetonation) const; void trimOldHistoricDamage() const; + void trimTriggeredHistoricDamage() const; void processHistoricDamage(const Object* source, const Coord3D* pos) const; private: diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index d74342bb34..435e5037ee 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1126,14 +1126,28 @@ void WeaponTemplate::trimOldHistoricDamage() const while (it != m_historicDamage.end()) { - if (it->frame <= expirationFrame || it->triggered) + if (it->frame <= expirationFrame) it = m_historicDamage.erase(it); else - ++it; + break; } } #endif +//------------------------------------------------------------------------------------------------- +void WeaponTemplate::trimTriggeredHistoricDamage() const +{ + HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); + + while (it != m_historicDamage.end()) + { + if (it->triggered) + it = m_historicDamage.erase(it); + else + ++it; + } +} + //------------------------------------------------------------------------------------------------- static Bool is2DDistSquaredLessThan(const Coord3D& a, const Coord3D& b, Real distSqr) { @@ -1216,6 +1230,7 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* if (count >= requiredCount) { TheWeaponStore->createAndFireTempWeapon(m_historicBonusWeapon, source, pos); + trimTriggeredHistoricDamage(); return; } } diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h index cf4dd3c47d..ac404cd362 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h @@ -481,6 +481,7 @@ class WeaponTemplate : public MemoryPoolObject // actually deal out the damage. void dealDamageInternal(ObjectID sourceID, ObjectID victimID, const Coord3D *pos, const WeaponBonus& bonus, Bool isProjectileDetonation) const; void trimOldHistoricDamage() const; + void trimTriggeredHistoricDamage() const; void processHistoricDamage(const Object* source, const Coord3D* pos) const; private: diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index 6abecf246b..ae57dc720c 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1204,14 +1204,28 @@ void WeaponTemplate::trimOldHistoricDamage() const while (it != m_historicDamage.end()) { - if (it->frame <= expirationFrame || it->triggered) + if (it->frame <= expirationFrame) it = m_historicDamage.erase(it); else - ++it; + break; } } #endif +//------------------------------------------------------------------------------------------------- +void WeaponTemplate::trimTriggeredHistoricDamage() const +{ + HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); + + while (it != m_historicDamage.end()) + { + if (it->triggered) + it = m_historicDamage.erase(it); + else + ++it; + } +} + //------------------------------------------------------------------------------------------------- static Bool is2DDistSquaredLessThan(const Coord3D& a, const Coord3D& b, Real distSqr) { @@ -1294,6 +1308,7 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* if (count >= requiredCount) { TheWeaponStore->createAndFireTempWeapon(m_historicBonusWeapon, source, pos); + trimTriggeredHistoricDamage(); return; } } From d8473802ad95e2f3a0dc3dad52d46fba15ec2b6d Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Mon, 27 Oct 2025 22:42:40 +1100 Subject: [PATCH 10/16] refactor: Implement cleaner historic damage trimming --- .../Code/GameEngine/Include/GameLogic/Weapon.h | 5 +++-- .../GameEngine/Source/GameLogic/Object/Weapon.cpp | 14 +++++++++----- .../Code/GameEngine/Include/GameLogic/Weapon.h | 5 +++-- .../GameEngine/Source/GameLogic/Object/Weapon.cpp | 14 +++++++++----- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/Weapon.h b/Generals/Code/GameEngine/Include/GameLogic/Weapon.h index 4df63e338b..55c11a738c 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Weapon.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Weapon.h @@ -320,10 +320,10 @@ struct HistoricWeaponDamageInfo // The time and location this weapon was fired UnsignedInt frame; Coord3D location; - Bool triggered; + Int triggerIndex; HistoricWeaponDamageInfo(UnsignedInt f, const Coord3D& l) : - frame(f), location(l), triggered(false) + frame(f), location(l), triggerIndex(0) { } }; @@ -539,6 +539,7 @@ class WeaponTemplate : public MemoryPoolObject Real m_infantryInaccuracyDist; ///< When this weapon is used against infantry, it can randomly miss by as much as this distance. UnsignedInt m_suspendFXDelay; ///< The fx can be suspended for any delay, in frames, then they will execute as normal mutable HistoricWeaponDamageList m_historicDamage; + mutable UnsignedInt m_historicDamageInstanceCount; }; // --------------------------------------------------------- diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index 435e5037ee..2c81a9af20 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -309,6 +309,8 @@ WeaponTemplate::WeaponTemplate() : m_nextTemplate(NULL) m_continueAttackRange = 0.0f; m_infantryInaccuracyDist = 0.0f; m_suspendFXDelay = 0; + + m_historicDamageInstanceCount = 0; } //------------------------------------------------------------------------------------------------- @@ -1117,7 +1119,10 @@ void WeaponTemplate::trimOldHistoricDamage() const void WeaponTemplate::trimOldHistoricDamage() const { if (m_historicDamage.empty()) + { + m_historicDamageInstanceCount = 0; return; + } const UnsignedInt currentFrame = TheGameLogic->getFrame(); const UnsignedInt expirationFrame = currentFrame - m_historicBonusTime; @@ -1141,7 +1146,7 @@ void WeaponTemplate::trimTriggeredHistoricDamage() const while (it != m_historicDamage.end()) { - if (it->triggered) + if (it->triggerIndex == m_historicDamageInstanceCount) it = m_historicDamage.erase(it); else ++it; @@ -1212,6 +1217,8 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* { trimOldHistoricDamage(); + ++m_historicDamageInstanceCount; + const Int requiredCount = m_historicBonusCount - 1; // minus 1 since we include ourselves implicitly if (m_historicDamage.size() >= requiredCount) { @@ -1224,7 +1231,7 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* { // This one is close enough in time and distance, so count it. This is tracked by template since it applies // across units, so don't try to clear historicDamage on success in here. - (*it).triggered = true; + (*it).triggerIndex = m_historicDamageInstanceCount; ++count; if (count >= requiredCount) @@ -1235,9 +1242,6 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* } } } - - for (HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); it != m_historicDamage.end(); ++it) - (*it).triggered = false; } // add AFTER checking for historic stuff diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h index ac404cd362..f6e7024d89 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h @@ -331,10 +331,10 @@ struct HistoricWeaponDamageInfo // The time and location this weapon was fired UnsignedInt frame; Coord3D location; - Bool triggered; + Int triggerIndex; HistoricWeaponDamageInfo(UnsignedInt f, const Coord3D& l) : - frame(f), location(l), triggered(false) + frame(f), location(l), triggerIndex(0) { } }; @@ -567,6 +567,7 @@ class WeaponTemplate : public MemoryPoolObject Bool m_dieOnDetonate; mutable HistoricWeaponDamageList m_historicDamage; + mutable UnsignedInt m_historicDamageInstanceCount; }; // --------------------------------------------------------- diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index ae57dc720c..bb2b823dd3 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -322,6 +322,8 @@ WeaponTemplate::WeaponTemplate() : m_nextTemplate(NULL) m_damageStatusType = OBJECT_STATUS_NONE; m_suspendFXDelay = 0; m_dieOnDetonate = FALSE; + + m_historicDamageInstanceCount = 0; } //------------------------------------------------------------------------------------------------- @@ -1195,7 +1197,10 @@ void WeaponTemplate::trimOldHistoricDamage() const void WeaponTemplate::trimOldHistoricDamage() const { if (m_historicDamage.empty()) + { + m_historicDamageInstanceCount = 0; return; + } const UnsignedInt currentFrame = TheGameLogic->getFrame(); const UnsignedInt expirationFrame = currentFrame - m_historicBonusTime; @@ -1219,7 +1224,7 @@ void WeaponTemplate::trimTriggeredHistoricDamage() const while (it != m_historicDamage.end()) { - if (it->triggered) + if (it->triggerIndex == m_historicDamageInstanceCount) it = m_historicDamage.erase(it); else ++it; @@ -1290,6 +1295,8 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* { trimOldHistoricDamage(); + ++m_historicDamageInstanceCount; + const Int requiredCount = m_historicBonusCount - 1; // minus 1 since we include ourselves implicitly if (m_historicDamage.size() >= requiredCount) { @@ -1302,7 +1309,7 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* { // This one is close enough in time and distance, so count it. This is tracked by template since it applies // across units, so don't try to clear historicDamage on success in here. - (*it).triggered = true; + (*it).triggerIndex = m_historicDamageInstanceCount; ++count; if (count >= requiredCount) @@ -1313,9 +1320,6 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* } } } - - for (HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); it != m_historicDamage.end(); ++it) - (*it).triggered = false; } // add AFTER checking for historic stuff From ee185a958798187ce50aeee495a2482602c4ff0c Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Tue, 28 Oct 2025 10:40:49 +1100 Subject: [PATCH 11/16] refactor: More concise count logic --- Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp | 3 +-- GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index 2c81a9af20..d6467a8f19 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1232,9 +1232,8 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* // This one is close enough in time and distance, so count it. This is tracked by template since it applies // across units, so don't try to clear historicDamage on success in here. (*it).triggerIndex = m_historicDamageInstanceCount; - ++count; - if (count >= requiredCount) + if (++count == requiredCount) { TheWeaponStore->createAndFireTempWeapon(m_historicBonusWeapon, source, pos); trimTriggeredHistoricDamage(); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index bb2b823dd3..d33396a993 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1310,9 +1310,8 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* // This one is close enough in time and distance, so count it. This is tracked by template since it applies // across units, so don't try to clear historicDamage on success in here. (*it).triggerIndex = m_historicDamageInstanceCount; - ++count; - if (count >= requiredCount) + if (++count == requiredCount) { TheWeaponStore->createAndFireTempWeapon(m_historicBonusWeapon, source, pos); trimTriggeredHistoricDamage(); From e32aba78461a1736969f4ab92d7d79c5129456ce Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Tue, 28 Oct 2025 10:42:02 +1100 Subject: [PATCH 12/16] refactor: Standardise pointer access syntax --- Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp | 2 +- GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index d6467a8f19..ed94c1d2af 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1231,7 +1231,7 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* { // This one is close enough in time and distance, so count it. This is tracked by template since it applies // across units, so don't try to clear historicDamage on success in here. - (*it).triggerIndex = m_historicDamageInstanceCount; + it->triggerIndex = m_historicDamageInstanceCount; if (++count == requiredCount) { diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index d33396a993..f3fa1ef367 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1309,7 +1309,7 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* { // This one is close enough in time and distance, so count it. This is tracked by template since it applies // across units, so don't try to clear historicDamage on success in here. - (*it).triggerIndex = m_historicDamageInstanceCount; + it->triggerIndex = m_historicDamageInstanceCount; if (++count == requiredCount) { From 0e3f291e0d69da8355ba3b19606cdb25d2fcf9c0 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Tue, 28 Oct 2025 10:42:45 +1100 Subject: [PATCH 13/16] refactor: Let unsigned int overflow --- Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp | 3 --- GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp | 3 --- 2 files changed, 6 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index ed94c1d2af..a8afdbff6c 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1119,10 +1119,7 @@ void WeaponTemplate::trimOldHistoricDamage() const void WeaponTemplate::trimOldHistoricDamage() const { if (m_historicDamage.empty()) - { - m_historicDamageInstanceCount = 0; return; - } const UnsignedInt currentFrame = TheGameLogic->getFrame(); const UnsignedInt expirationFrame = currentFrame - m_historicBonusTime; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index f3fa1ef367..c586b1c34a 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -1197,10 +1197,7 @@ void WeaponTemplate::trimOldHistoricDamage() const void WeaponTemplate::trimOldHistoricDamage() const { if (m_historicDamage.empty()) - { - m_historicDamageInstanceCount = 0; return; - } const UnsignedInt currentFrame = TheGameLogic->getFrame(); const UnsignedInt expirationFrame = currentFrame - m_historicBonusTime; From 276a6ccca5125cf2b7a5a2a5102a0a68ba23e9aa Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Tue, 28 Oct 2025 10:45:49 +1100 Subject: [PATCH 14/16] refactor: Adjust naming --- Generals/Code/GameEngine/Include/GameLogic/Weapon.h | 6 +++--- .../Code/GameEngine/Source/GameLogic/Object/Weapon.cpp | 8 ++++---- GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h | 6 +++--- .../Code/GameEngine/Source/GameLogic/Object/Weapon.cpp | 8 ++++---- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/Weapon.h b/Generals/Code/GameEngine/Include/GameLogic/Weapon.h index 55c11a738c..bfbe44c401 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Weapon.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Weapon.h @@ -320,10 +320,10 @@ struct HistoricWeaponDamageInfo // The time and location this weapon was fired UnsignedInt frame; Coord3D location; - Int triggerIndex; + Int triggerId; HistoricWeaponDamageInfo(UnsignedInt f, const Coord3D& l) : - frame(f), location(l), triggerIndex(0) + frame(f), location(l), triggerId(0) { } }; @@ -539,7 +539,7 @@ class WeaponTemplate : public MemoryPoolObject Real m_infantryInaccuracyDist; ///< When this weapon is used against infantry, it can randomly miss by as much as this distance. UnsignedInt m_suspendFXDelay; ///< The fx can be suspended for any delay, in frames, then they will execute as normal mutable HistoricWeaponDamageList m_historicDamage; - mutable UnsignedInt m_historicDamageInstanceCount; + mutable UnsignedInt m_historicDamageTriggerId; }; // --------------------------------------------------------- diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index a8afdbff6c..31b4d3e069 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -310,7 +310,7 @@ WeaponTemplate::WeaponTemplate() : m_nextTemplate(NULL) m_infantryInaccuracyDist = 0.0f; m_suspendFXDelay = 0; - m_historicDamageInstanceCount = 0; + m_historicDamageTriggerId = 0; } //------------------------------------------------------------------------------------------------- @@ -1143,7 +1143,7 @@ void WeaponTemplate::trimTriggeredHistoricDamage() const while (it != m_historicDamage.end()) { - if (it->triggerIndex == m_historicDamageInstanceCount) + if (it->triggerId == m_historicDamageTriggerId) it = m_historicDamage.erase(it); else ++it; @@ -1214,7 +1214,7 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* { trimOldHistoricDamage(); - ++m_historicDamageInstanceCount; + ++m_historicDamageTriggerId; const Int requiredCount = m_historicBonusCount - 1; // minus 1 since we include ourselves implicitly if (m_historicDamage.size() >= requiredCount) @@ -1228,7 +1228,7 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* { // This one is close enough in time and distance, so count it. This is tracked by template since it applies // across units, so don't try to clear historicDamage on success in here. - it->triggerIndex = m_historicDamageInstanceCount; + it->triggerId = m_historicDamageTriggerId; if (++count == requiredCount) { diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h index f6e7024d89..7863bfe96f 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h @@ -331,10 +331,10 @@ struct HistoricWeaponDamageInfo // The time and location this weapon was fired UnsignedInt frame; Coord3D location; - Int triggerIndex; + Int triggerId; HistoricWeaponDamageInfo(UnsignedInt f, const Coord3D& l) : - frame(f), location(l), triggerIndex(0) + frame(f), location(l), triggerId(0) { } }; @@ -567,7 +567,7 @@ class WeaponTemplate : public MemoryPoolObject Bool m_dieOnDetonate; mutable HistoricWeaponDamageList m_historicDamage; - mutable UnsignedInt m_historicDamageInstanceCount; + mutable UnsignedInt m_historicDamageTriggerId; }; // --------------------------------------------------------- diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index c586b1c34a..767bc392c1 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -323,7 +323,7 @@ WeaponTemplate::WeaponTemplate() : m_nextTemplate(NULL) m_suspendFXDelay = 0; m_dieOnDetonate = FALSE; - m_historicDamageInstanceCount = 0; + m_historicDamageTriggerId = 0; } //------------------------------------------------------------------------------------------------- @@ -1221,7 +1221,7 @@ void WeaponTemplate::trimTriggeredHistoricDamage() const while (it != m_historicDamage.end()) { - if (it->triggerIndex == m_historicDamageInstanceCount) + if (it->triggerId == m_historicDamageTriggerId) it = m_historicDamage.erase(it); else ++it; @@ -1292,7 +1292,7 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* { trimOldHistoricDamage(); - ++m_historicDamageInstanceCount; + ++m_historicDamageTriggerId; const Int requiredCount = m_historicBonusCount - 1; // minus 1 since we include ourselves implicitly if (m_historicDamage.size() >= requiredCount) @@ -1306,7 +1306,7 @@ void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* { // This one is close enough in time and distance, so count it. This is tracked by template since it applies // across units, so don't try to clear historicDamage on success in here. - it->triggerIndex = m_historicDamageInstanceCount; + it->triggerId = m_historicDamageTriggerId; if (++count == requiredCount) { From 250293aa056a3365b78ba92a833f481b24a98466 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Tue, 28 Oct 2025 10:46:41 +1100 Subject: [PATCH 15/16] refactor: Make trigger id unsigned --- Generals/Code/GameEngine/Include/GameLogic/Weapon.h | 2 +- GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/Weapon.h b/Generals/Code/GameEngine/Include/GameLogic/Weapon.h index bfbe44c401..2b4bca529d 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Weapon.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Weapon.h @@ -320,7 +320,7 @@ struct HistoricWeaponDamageInfo // The time and location this weapon was fired UnsignedInt frame; Coord3D location; - Int triggerId; + UnsignedInt triggerId; HistoricWeaponDamageInfo(UnsignedInt f, const Coord3D& l) : frame(f), location(l), triggerId(0) diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h index 7863bfe96f..a5d9bc2f8f 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h @@ -331,7 +331,7 @@ struct HistoricWeaponDamageInfo // The time and location this weapon was fired UnsignedInt frame; Coord3D location; - Int triggerId; + UnsignedInt triggerId; HistoricWeaponDamageInfo(UnsignedInt f, const Coord3D& l) : frame(f), location(l), triggerId(0) From a21d9e6766a5a07effeca7c059dfc06800a2da7e Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Tue, 28 Oct 2025 10:48:08 +1100 Subject: [PATCH 16/16] docs: Add comments --- Generals/Code/GameEngine/Include/GameLogic/Weapon.h | 2 +- GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/Weapon.h b/Generals/Code/GameEngine/Include/GameLogic/Weapon.h index 2b4bca529d..63998be2c4 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Weapon.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Weapon.h @@ -320,7 +320,7 @@ struct HistoricWeaponDamageInfo // The time and location this weapon was fired UnsignedInt frame; Coord3D location; - UnsignedInt triggerId; + UnsignedInt triggerId; ///< Unique Id assigned to any grouped damage instances HistoricWeaponDamageInfo(UnsignedInt f, const Coord3D& l) : frame(f), location(l), triggerId(0) diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h index a5d9bc2f8f..0166ecaca0 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h @@ -331,7 +331,7 @@ struct HistoricWeaponDamageInfo // The time and location this weapon was fired UnsignedInt frame; Coord3D location; - UnsignedInt triggerId; + UnsignedInt triggerId; ///< Unique Id assigned to any grouped damage instances HistoricWeaponDamageInfo(UnsignedInt f, const Coord3D& l) : frame(f), location(l), triggerId(0)