From e1060abeb7461b4c2f611e40b9e590cbcccb6879 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Tue, 1 Jul 2025 11:34:30 +1000 Subject: [PATCH 1/2] bugfix: Fix cases where supply units return to collect supplies after receiving player-issued commands --- .../Include/GameLogic/Module/SupplyTruckAIUpdate.h | 1 + .../Object/Update/AIUpdate/ChinookAIUpdate.cpp | 1 + .../Object/Update/AIUpdate/SupplyTruckAIUpdate.cpp | 10 ++++++++++ .../Object/Update/AIUpdate/WorkerAIUpdate.cpp | 5 +++++ .../Include/GameLogic/Module/SupplyTruckAIUpdate.h | 1 + .../Object/Update/AIUpdate/ChinookAIUpdate.cpp | 1 + .../Object/Update/AIUpdate/SupplyTruckAIUpdate.cpp | 10 ++++++++++ .../Object/Update/AIUpdate/WorkerAIUpdate.cpp | 5 +++++ 8 files changed, 34 insertions(+) diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/SupplyTruckAIUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/SupplyTruckAIUpdate.h index 1a8ebf6591b..5d3903d8ac2 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/SupplyTruckAIUpdate.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/SupplyTruckAIUpdate.h @@ -214,6 +214,7 @@ class SupplyTruckAIUpdate : public AIUpdateInterface, public SupplyTruckAIInterf virtual UnsignedInt getActionDelayForDock( Object *dock ) override; virtual UpdateSleepTime update() override; + virtual void aiDoCommand(const AICommandParms* parms) override; protected: diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp index bf77558102c..d302080e306 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp @@ -235,6 +235,7 @@ class ChinookTakeoffOrLandingState : public State { // A chinook given transport duty loses his supplies. while( ai->loseOneBox() ); + ai->setForceWantingState(FALSE); } // kill any drift... diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/SupplyTruckAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/SupplyTruckAIUpdate.cpp index 9d544810cfa..5c4fba4ee69 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/SupplyTruckAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/SupplyTruckAIUpdate.cpp @@ -238,6 +238,16 @@ Real SupplyTruckAIUpdate::getWarehouseScanDistance() const return getSupplyTruckAIUpdateModuleData()->m_warehouseScanDistance; } +void SupplyTruckAIUpdate::aiDoCommand(const AICommandParms* parms) +{ + if (parms->m_cmdSource == CMD_FROM_PLAYER) + { + setForceWantingState(FALSE); + } + + AIUpdateInterface::aiDoCommand(parms); +} + // ------------------------------------------------------------------------------------------------ /** CRC */ // ------------------------------------------------------------------------------------------------ diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp index c6798af48f3..9d04a28f997 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -396,6 +396,7 @@ Object *WorkerAIUpdate::construct( const ThingTemplate *what, // leave the supply truck state and now behave like a dozer. exitingSupplyTruckState(); + setForceWantingState(FALSE); // take the required money away from the player if( isRebuild == FALSE ) @@ -673,6 +674,7 @@ void WorkerAIUpdate::newTask( DozerTask task, Object* target ) getObject()->getAIUpdateInterface()->aiIdle(CMD_FROM_AI); } m_workerMachine->setState( AS_DOZER ); + setForceWantingState(FALSE); // To clarify, I leave supply truck mode when I notice I am doing something not supply // truck related. When given a construct command, I wait to do anything until I notice // I'm not busy. Both states are being polite, so I must force the switch. @@ -1037,7 +1039,10 @@ void WorkerAIUpdate::aiDoCommand(const AICommandParms* parms) // when a player issues commands, this will cause the dozer to re-evaluate what it's doing if( parms->m_cmdSource == CMD_FROM_PLAYER ) + { m_dozerMachine->resetToDefaultState(); + setForceWantingState(FALSE); + } break; } diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/SupplyTruckAIUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/SupplyTruckAIUpdate.h index 10b178c045d..9aa545c5de4 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/SupplyTruckAIUpdate.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/SupplyTruckAIUpdate.h @@ -219,6 +219,7 @@ class SupplyTruckAIUpdate : public AIUpdateInterface, public SupplyTruckAIInterf virtual Int getUpgradedSupplyBoost() const override { return 0; } virtual UpdateSleepTime update() override; + virtual void aiDoCommand(const AICommandParms* parms) override; protected: diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp index 917ba12853a..f98437cd25c 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp @@ -234,6 +234,7 @@ class ChinookTakeoffOrLandingState : public State { // A chinook given transport duty loses his supplies. while( ai->loseOneBox() ); + ai->setForceWantingState(FALSE); } // kill any drift... diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/SupplyTruckAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/SupplyTruckAIUpdate.cpp index 5e966094ef7..f67a8e66500 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/SupplyTruckAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/SupplyTruckAIUpdate.cpp @@ -244,6 +244,16 @@ Real SupplyTruckAIUpdate::getWarehouseScanDistance() const return getSupplyTruckAIUpdateModuleData()->m_warehouseScanDistance; } +void SupplyTruckAIUpdate::aiDoCommand(const AICommandParms* parms) +{ + if (parms->m_cmdSource == CMD_FROM_PLAYER) + { + setForceWantingState(FALSE); + } + + AIUpdateInterface::aiDoCommand(parms); +} + // ------------------------------------------------------------------------------------------------ /** CRC */ // ------------------------------------------------------------------------------------------------ diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp index ba7313535c5..0051cd1144c 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -396,6 +396,7 @@ Object *WorkerAIUpdate::construct( const ThingTemplate *what, // leave the supply truck state and now behave like a dozer. exitingSupplyTruckState(); + setForceWantingState(FALSE); // take the required money away from the player if( isRebuild == FALSE ) @@ -673,6 +674,7 @@ void WorkerAIUpdate::newTask( DozerTask task, Object* target ) getObject()->getAIUpdateInterface()->aiIdle(CMD_FROM_AI); } m_workerMachine->setState( AS_DOZER ); + setForceWantingState(FALSE); // To clarify, I leave supply truck mode when I notice I am doing something not supply // truck related. When given a construct command, I wait to do anything until I notice // I'm not busy. Both states are being polite, so I must force the switch. @@ -1037,7 +1039,10 @@ void WorkerAIUpdate::aiDoCommand(const AICommandParms* parms) // when a player issues commands, this will cause the dozer to re-evaluate what it's doing if( parms->m_cmdSource == CMD_FROM_PLAYER ) + { m_dozerMachine->resetToDefaultState(); + setForceWantingState(FALSE); + } break; } From 7436d0ee2208b1ca0e43fd9b07d5d8b4eb8cf78e Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Wed, 19 Aug 2026 14:54:05 +1000 Subject: [PATCH 2/2] tweak: Apply retail-compatible branching --- .../GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp | 2 ++ .../Object/Update/AIUpdate/SupplyTruckAIUpdate.cpp | 2 ++ .../GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp | 6 ++++++ .../GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp | 2 ++ .../Object/Update/AIUpdate/SupplyTruckAIUpdate.cpp | 2 ++ .../GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp | 6 ++++++ 6 files changed, 20 insertions(+) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp index d302080e306..de3fa8dc5a1 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp @@ -235,7 +235,9 @@ class ChinookTakeoffOrLandingState : public State { // A chinook given transport duty loses his supplies. while( ai->loseOneBox() ); +#if !RETAIL_COMPATIBLE_CRC ai->setForceWantingState(FALSE); +#endif } // kill any drift... diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/SupplyTruckAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/SupplyTruckAIUpdate.cpp index 5c4fba4ee69..5c773f45fae 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/SupplyTruckAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/SupplyTruckAIUpdate.cpp @@ -240,10 +240,12 @@ Real SupplyTruckAIUpdate::getWarehouseScanDistance() const void SupplyTruckAIUpdate::aiDoCommand(const AICommandParms* parms) { +#if !RETAIL_COMPATIBLE_CRC if (parms->m_cmdSource == CMD_FROM_PLAYER) { setForceWantingState(FALSE); } +#endif AIUpdateInterface::aiDoCommand(parms); } diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp index 9d04a28f997..4b4445d715a 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -396,7 +396,9 @@ Object *WorkerAIUpdate::construct( const ThingTemplate *what, // leave the supply truck state and now behave like a dozer. exitingSupplyTruckState(); +#if !RETAIL_COMPATIBLE_CRC setForceWantingState(FALSE); +#endif // take the required money away from the player if( isRebuild == FALSE ) @@ -674,7 +676,9 @@ void WorkerAIUpdate::newTask( DozerTask task, Object* target ) getObject()->getAIUpdateInterface()->aiIdle(CMD_FROM_AI); } m_workerMachine->setState( AS_DOZER ); +#if !RETAIL_COMPATIBLE_CRC setForceWantingState(FALSE); +#endif // To clarify, I leave supply truck mode when I notice I am doing something not supply // truck related. When given a construct command, I wait to do anything until I notice // I'm not busy. Both states are being polite, so I must force the switch. @@ -1041,7 +1045,9 @@ void WorkerAIUpdate::aiDoCommand(const AICommandParms* parms) if( parms->m_cmdSource == CMD_FROM_PLAYER ) { m_dozerMachine->resetToDefaultState(); +#if !RETAIL_COMPATIBLE_CRC setForceWantingState(FALSE); +#endif } break; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp index f98437cd25c..9a168dfa54b 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp @@ -234,7 +234,9 @@ class ChinookTakeoffOrLandingState : public State { // A chinook given transport duty loses his supplies. while( ai->loseOneBox() ); +#if !RETAIL_COMPATIBLE_CRC ai->setForceWantingState(FALSE); +#endif } // kill any drift... diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/SupplyTruckAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/SupplyTruckAIUpdate.cpp index f67a8e66500..9c1d3a8ec04 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/SupplyTruckAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/SupplyTruckAIUpdate.cpp @@ -246,10 +246,12 @@ Real SupplyTruckAIUpdate::getWarehouseScanDistance() const void SupplyTruckAIUpdate::aiDoCommand(const AICommandParms* parms) { +#if !RETAIL_COMPATIBLE_CRC if (parms->m_cmdSource == CMD_FROM_PLAYER) { setForceWantingState(FALSE); } +#endif AIUpdateInterface::aiDoCommand(parms); } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp index 0051cd1144c..16f64fd5edf 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -396,7 +396,9 @@ Object *WorkerAIUpdate::construct( const ThingTemplate *what, // leave the supply truck state and now behave like a dozer. exitingSupplyTruckState(); +#if !RETAIL_COMPATIBLE_CRC setForceWantingState(FALSE); +#endif // take the required money away from the player if( isRebuild == FALSE ) @@ -674,7 +676,9 @@ void WorkerAIUpdate::newTask( DozerTask task, Object* target ) getObject()->getAIUpdateInterface()->aiIdle(CMD_FROM_AI); } m_workerMachine->setState( AS_DOZER ); +#if !RETAIL_COMPATIBLE_CRC setForceWantingState(FALSE); +#endif // To clarify, I leave supply truck mode when I notice I am doing something not supply // truck related. When given a construct command, I wait to do anything until I notice // I'm not busy. Both states are being polite, so I must force the switch. @@ -1041,7 +1045,9 @@ void WorkerAIUpdate::aiDoCommand(const AICommandParms* parms) if( parms->m_cmdSource == CMD_FROM_PLAYER ) { m_dozerMachine->resetToDefaultState(); +#if !RETAIL_COMPATIBLE_CRC setForceWantingState(FALSE); +#endif } break;