diff --git a/Generals/Code/GameEngine/Include/Common/Player.h b/Generals/Code/GameEngine/Include/Common/Player.h index cf37308e70..07bf31aff0 100644 --- a/Generals/Code/GameEngine/Include/Common/Player.h +++ b/Generals/Code/GameEngine/Include/Common/Player.h @@ -345,7 +345,7 @@ class Player : public Snapshot //it's possible for multiple strategy centers to have the same plan, so we need //to keep track of that like radar. Keep in mind multiple strategy centers with //same plan do not stack, but different strategy centers with different plans do. - void changeBattlePlan( BattlePlanStatus plan, Int delta, BattlePlanBonusesData *bonus ); + void changeBattlePlan( BattlePlanStatus plan, Int delta, const BattlePlanBonusesData *bonus ); Int getNumBattlePlansActive() const { return m_bombardBattlePlans + m_holdTheLineBattlePlans + m_searchAndDestroyBattlePlans; } Int getBattlePlansActiveSpecific( BattlePlanStatus plan ) const; void applyBattlePlanBonusesForObject( Object *obj ) const; //New object or converted object gaining our current battle plan bonuses. diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/BattlePlanUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/BattlePlanUpdate.h index ae93f31951..17fbd91029 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/BattlePlanUpdate.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/BattlePlanUpdate.h @@ -162,6 +162,7 @@ class BattlePlanUpdate : public UpdateModule, public SpecialPowerUpdateInterface virtual void onObjectCreated() override; virtual void onDelete() override; virtual UpdateSleepTime update() override; + virtual void onCapture(Player* oldOwner, Player* newOwner) override; virtual CommandOption getCommandOption() const override; protected: diff --git a/Generals/Code/GameEngine/Source/Common/RTS/Player.cpp b/Generals/Code/GameEngine/Source/Common/RTS/Player.cpp index 25596036b7..6240cca19d 100644 --- a/Generals/Code/GameEngine/Source/Common/RTS/Player.cpp +++ b/Generals/Code/GameEngine/Source/Common/RTS/Player.cpp @@ -2921,8 +2921,7 @@ Bool Player::doesObjectQualifyForBattlePlan( Object *obj ) const } //------------------------------------------------------------------------------------------------- -// note, bonus is an in-out parm. -void Player::changeBattlePlan( BattlePlanStatus plan, Int delta, BattlePlanBonusesData *bonus ) +void Player::changeBattlePlan( BattlePlanStatus plan, Int delta, const BattlePlanBonusesData *bonus ) { DUMPBATTLEPLANBONUSES(bonus, this, nullptr); Bool addBonus = false; @@ -2976,22 +2975,24 @@ void Player::changeBattlePlan( BattlePlanStatus plan, Int delta, BattlePlanBonus else if( removeBonus ) { //First, inverse the bonuses - bonus->m_armorScalar = 1.0f / __max( bonus->m_armorScalar, 0.01f ); - bonus->m_sightRangeScalar = 1.0f / __max( bonus->m_sightRangeScalar, 0.01f ); - if( bonus->m_bombardment > 0 ) + BattlePlanBonusesData invertedBonus = *bonus; + + invertedBonus.m_armorScalar = 1.0f / __max(bonus->m_armorScalar, 0.01f); + invertedBonus.m_sightRangeScalar = 1.0f / __max(bonus->m_sightRangeScalar, 0.01f); + if (invertedBonus.m_bombardment > 0) { - bonus->m_bombardment = -1; + invertedBonus.m_bombardment = -1; } - if( bonus->m_holdTheLine > 0 ) + if (invertedBonus.m_holdTheLine > 0) { - bonus->m_holdTheLine = -1; + invertedBonus.m_holdTheLine = -1; } - if( bonus->m_searchAndDestroy > 0 ) + if (invertedBonus.m_searchAndDestroy > 0) { - bonus->m_searchAndDestroy = -1; + invertedBonus.m_searchAndDestroy = -1; } - applyBattlePlanBonusesForPlayerObjects( bonus ); + applyBattlePlanBonusesForPlayerObjects(&invertedBonus); } } diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/BattlePlanUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/BattlePlanUpdate.cpp index 40b091ec4e..64da934984 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/BattlePlanUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/BattlePlanUpdate.cpp @@ -247,6 +247,16 @@ void BattlePlanUpdate::onObjectCreated() enableTurret( false ); } +//------------------------------------------------------------------------------------------------- +void BattlePlanUpdate::onCapture(Player* oldOwner, Player* newOwner) +{ +#if !RETAIL_COMPATIBLE_CRC + // TheSuperHackers @bugfix Stubbjax 04/11/2025 Transfer battle plan bonuses on capture. + oldOwner->changeBattlePlan(m_planAffectingArmy, -1, m_bonuses); + newOwner->changeBattlePlan(m_planAffectingArmy, 1, m_bonuses); +#endif +} + //------------------------------------------------------------------------------------------------- Bool BattlePlanUpdate::initiateIntentToDoSpecialPower(const SpecialPowerTemplate *specialPowerTemplate, const Object *targetObj, const Coord3D *targetPos, const Waypoint *way, UnsignedInt commandOptions ) { diff --git a/GeneralsMD/Code/GameEngine/Include/Common/Player.h b/GeneralsMD/Code/GameEngine/Include/Common/Player.h index 582f97d2db..e30dcf5953 100644 --- a/GeneralsMD/Code/GameEngine/Include/Common/Player.h +++ b/GeneralsMD/Code/GameEngine/Include/Common/Player.h @@ -369,7 +369,7 @@ class Player : public Snapshot //it's possible for multiple strategy centers to have the same plan, so we need //to keep track of that like radar. Keep in mind multiple strategy centers with //same plan do not stack, but different strategy centers with different plans do. - void changeBattlePlan( BattlePlanStatus plan, Int delta, BattlePlanBonusesData *bonus ); + void changeBattlePlan( BattlePlanStatus plan, Int delta, const BattlePlanBonusesData *bonus ); Int getNumBattlePlansActive() const { return m_bombardBattlePlans + m_holdTheLineBattlePlans + m_searchAndDestroyBattlePlans; } Int getBattlePlansActiveSpecific( BattlePlanStatus plan ) const; void applyBattlePlanBonusesForObject( Object *obj ) const; //New object or converted object gaining our current battle plan bonuses. diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/BattlePlanUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/BattlePlanUpdate.h index 2d16d1c481..3e9e438a9b 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/BattlePlanUpdate.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/BattlePlanUpdate.h @@ -162,6 +162,7 @@ class BattlePlanUpdate : public SpecialPowerUpdateModule virtual void onObjectCreated() override; virtual void onDelete() override; virtual UpdateSleepTime update() override; + virtual void onCapture(Player* oldOwner, Player* newOwner) override; virtual CommandOption getCommandOption() const override; protected: diff --git a/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp b/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp index 5c4009fd42..2a5171bbcf 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp @@ -3414,8 +3414,7 @@ Bool Player::doesObjectQualifyForBattlePlan( Object *obj ) const } //------------------------------------------------------------------------------------------------- -// note, bonus is an in-out parm. -void Player::changeBattlePlan( BattlePlanStatus plan, Int delta, BattlePlanBonusesData *bonus ) +void Player::changeBattlePlan( BattlePlanStatus plan, Int delta, const BattlePlanBonusesData *bonus ) { DUMPBATTLEPLANBONUSES(bonus, this, nullptr); Bool addBonus = false; @@ -3469,22 +3468,24 @@ void Player::changeBattlePlan( BattlePlanStatus plan, Int delta, BattlePlanBonus else if( removeBonus ) { //First, inverse the bonuses - bonus->m_armorScalar = 1.0f / __max( bonus->m_armorScalar, 0.01f ); - bonus->m_sightRangeScalar = 1.0f / __max( bonus->m_sightRangeScalar, 0.01f ); - if( bonus->m_bombardment > 0 ) + BattlePlanBonusesData invertedBonus = *bonus; + + invertedBonus.m_armorScalar = 1.0f / __max(bonus->m_armorScalar, 0.01f); + invertedBonus.m_sightRangeScalar = 1.0f / __max(bonus->m_sightRangeScalar, 0.01f); + if (invertedBonus.m_bombardment > 0) { - bonus->m_bombardment = -1; + invertedBonus.m_bombardment = -1; } - if( bonus->m_holdTheLine > 0 ) + if (invertedBonus.m_holdTheLine > 0) { - bonus->m_holdTheLine = -1; + invertedBonus.m_holdTheLine = -1; } - if( bonus->m_searchAndDestroy > 0 ) + if (invertedBonus.m_searchAndDestroy > 0) { - bonus->m_searchAndDestroy = -1; + invertedBonus.m_searchAndDestroy = -1; } - applyBattlePlanBonusesForPlayerObjects( bonus ); + applyBattlePlanBonusesForPlayerObjects(&invertedBonus); } } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/BattlePlanUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/BattlePlanUpdate.cpp index 8a23e0f968..d4d0cead9d 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/BattlePlanUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/BattlePlanUpdate.cpp @@ -247,6 +247,16 @@ void BattlePlanUpdate::onObjectCreated() enableTurret( false ); } +//------------------------------------------------------------------------------------------------- +void BattlePlanUpdate::onCapture(Player* oldOwner, Player* newOwner) +{ +#if !RETAIL_COMPATIBLE_CRC + // TheSuperHackers @bugfix Stubbjax 04/11/2025 Transfer battle plan bonuses on capture. + oldOwner->changeBattlePlan(m_planAffectingArmy, -1, m_bonuses); + newOwner->changeBattlePlan(m_planAffectingArmy, 1, m_bonuses); +#endif +} + //------------------------------------------------------------------------------------------------- Bool BattlePlanUpdate::initiateIntentToDoSpecialPower(const SpecialPowerTemplate *specialPowerTemplate, const Object *targetObj, const Coord3D *targetPos, const Waypoint *way, UnsignedInt commandOptions ) {