From 68743fffde63dd694d5786b29ebb3744371315ac Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Mon, 15 Jun 2026 01:07:30 +1000 Subject: [PATCH 01/18] bugfix: Fix issue where builders could resume completed tasks after being disabled --- .../GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp | 6 ++++++ .../GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp | 6 ++++++ .../GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp | 6 ++++++ .../GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp | 6 ++++++ 4 files changed, 24 insertions(+) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index c5a3eb001f2..ca21a01ec5b 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2015,7 +2015,13 @@ void DozerAIUpdate::newTask( DozerTask task, Object *target ) // multiple dozers/workers to double up on construction efforts // if( task == DOZER_TASK_BUILD ) + { + // TheSuperHackers @bugfix Stubbjax 15/06/2026 Ignore the build task if the building is already complete. + if (target->getConstructionPercent() == CONSTRUCTION_COMPLETE) + return; + target->setBuilder( me ); + } m_dockPoint[ task ][ DOZER_DOCK_POINT_START ].valid = TRUE; m_dockPoint[ task ][ DOZER_DOCK_POINT_START ].location = position; 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..49f75ce29c1 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -644,7 +644,13 @@ void WorkerAIUpdate::newTask( DozerTask task, Object* target ) // multiple dozers/workers to double up on construction efforts // if( task == DOZER_TASK_BUILD ) + { + // TheSuperHackers @bugfix Stubbjax 15/06/2026 Ignore the build task if the building is already complete. + if (target->getConstructionPercent() == CONSTRUCTION_COMPLETE) + return; + target->setBuilder( me ); + } m_dockPoint[ task ][ DOZER_DOCK_POINT_START ].valid = TRUE; m_dockPoint[ task ][ DOZER_DOCK_POINT_START ].location = position; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index 2ccaaa00d38..e5443a2a2d1 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2020,7 +2020,13 @@ void DozerAIUpdate::newTask( DozerTask task, Object *target ) // multiple dozers/workers to double up on construction efforts // if( task == DOZER_TASK_BUILD ) + { + // TheSuperHackers @bugfix Stubbjax 15/06/2026 Ignore the build task if the building is already complete. + if (target->getConstructionPercent() == CONSTRUCTION_COMPLETE) + return; + target->setBuilder( me ); + } m_dockPoint[ task ][ DOZER_DOCK_POINT_START ].valid = TRUE; m_dockPoint[ task ][ DOZER_DOCK_POINT_START ].location = position; 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..5f62781b4ab 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -644,7 +644,13 @@ void WorkerAIUpdate::newTask( DozerTask task, Object* target ) // multiple dozers/workers to double up on construction efforts // if( task == DOZER_TASK_BUILD ) + { + // TheSuperHackers @bugfix Stubbjax 15/06/2026 Ignore the build task if the building is already complete. + if (target->getConstructionPercent() == CONSTRUCTION_COMPLETE) + return; + target->setBuilder( me ); + } m_dockPoint[ task ][ DOZER_DOCK_POINT_START ].valid = TRUE; m_dockPoint[ task ][ DOZER_DOCK_POINT_START ].location = position; From 8b4cd2e35a186e7a3ff8492f65d2984863a62230 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Mon, 15 Jun 2026 01:58:44 +1000 Subject: [PATCH 02/18] bugfix: Only save the previous task for resumption when explicitly disabled --- .../Include/GameLogic/Module/DozerAIUpdate.h | 2 ++ .../Include/GameLogic/Module/WorkerAIUpdate.h | 1 + .../GameEngine/Source/GameLogic/Object/Object.cpp | 4 ++++ .../Object/Update/AIUpdate/DozerAIUpdate.cpp | 15 ++++++++++++--- .../Object/Update/AIUpdate/WorkerAIUpdate.cpp | 15 ++++++++++++--- .../Include/GameLogic/Module/DozerAIUpdate.h | 2 ++ .../Include/GameLogic/Module/WorkerAIUpdate.h | 1 + .../GameEngine/Source/GameLogic/Object/Object.cpp | 4 ++++ .../Object/Update/AIUpdate/DozerAIUpdate.cpp | 15 ++++++++++++--- .../Object/Update/AIUpdate/WorkerAIUpdate.cpp | 15 ++++++++++++--- 10 files changed, 62 insertions(+), 12 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h index 16681f0864b..458db09b7b8 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h @@ -141,6 +141,7 @@ class DozerAIInterface virtual void newTask( DozerTask task, Object *target ) = 0; ///< set a desire to do the requrested task virtual void cancelTask( DozerTask task ) = 0; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it virtual void cancelAllTasks() = 0; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it + virtual void setPreviousTask(DozerTask task) = 0; ///< set the previous task virtual void resumePreviousTask() = 0; ///< resume the previous task if there was one // internal methods to manage behavior from within the dozer state machine @@ -242,6 +243,7 @@ class DozerAIUpdate : public AIUpdateInterface, public DozerAIInterface virtual void newTask( DozerTask task, Object *target ) override; ///< set a desire to do the requrested task virtual void cancelTask( DozerTask task ) override; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it virtual void cancelAllTasks() override; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it + virtual void setPreviousTask(DozerTask task) override; ///< set the previous task virtual void resumePreviousTask() override; ///< resume the previous task if there was one // internal methods to manage behavior from within the dozer state machine diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h index 9b15198c754..edb142c3449 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h @@ -156,6 +156,7 @@ class WorkerAIUpdate : public AIUpdateInterface, public DozerAIInterface, public virtual void newTask( DozerTask task, Object* target ) override; ///< set a desire to do the requrested task virtual void cancelTask( DozerTask task ) override; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it virtual void cancelAllTasks() override; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it + virtual void setPreviousTask(DozerTask task) override; ///< set the previous task virtual void resumePreviousTask() override; ///< resume the previous task if there was one // internal methods to manage behavior from within the dozer state machine diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp index d5748b002e4..9b7de7ffa53 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -1985,6 +1985,10 @@ void Object::setDisabledUntil( DisabledType type, UnsignedInt frame ) sound.setPosition( getPosition() ); TheAudio->addAudioEvent( &sound ); } + + DozerAIInterface* dozerAI = getAI() ? getAI()->getDozerAIInterface() : nullptr; + if (dozerAI) + dozerAI->setPreviousTask(dozerAI->getCurrentTask()); } } diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index ca21a01ec5b..34d58e379b7 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2070,6 +2070,18 @@ void DozerAIUpdate::cancelAllTasks() m_dozerMachine->resetToDefaultState(); } +//------------------------------------------------------------------------------------------------- +/** Set the previous task so that we may return to it if we become temporarily incapacitated */ +//------------------------------------------------------------------------------------------------- +void DozerAIUpdate::setPreviousTask(DozerTask task) +{ + if (task == DOZER_TASK_INVALID) + return; + + m_previousTask = task; + m_previousTaskInfo = m_task[task]; +} + //------------------------------------------------------------------------------------------------- /** Attempt to resume the previous task */ //------------------------------------------------------------------------------------------------- @@ -2164,9 +2176,6 @@ void DozerAIUpdate::internalCancelTask( DozerTask task ) // call the single method that gets called for completing and canceling tasks internalTaskCompleteOrCancelled( task ); - m_previousTask = task; - m_previousTaskInfo = m_task[task]; - // remove the info for this task m_task[ task ].m_targetObjectID = INVALID_ID; m_task[ task ].m_taskOrderFrame = 0; 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 49f75ce29c1..f50148491b9 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -710,6 +710,18 @@ void WorkerAIUpdate::cancelAllTasks() m_dozerMachine->resetToDefaultState(); } +//------------------------------------------------------------------------------------------------- +/** Set the previous task so that we may return to it if we become temporarily incapacitated */ +//------------------------------------------------------------------------------------------------- +void WorkerAIUpdate::setPreviousTask(DozerTask task) +{ + if (task == DOZER_TASK_INVALID) + return; + + m_previousTask = task; + m_previousTaskInfo = m_task[task]; +} + //------------------------------------------------------------------------------------------------- /** Attempt to resume the previous task */ //------------------------------------------------------------------------------------------------- @@ -804,9 +816,6 @@ void WorkerAIUpdate::internalCancelTask( DozerTask task ) // call the single method that gets called for completing and canceling tasks internalTaskCompleteOrCancelled( task ); - m_previousTask = task; - m_previousTaskInfo = m_task[task]; - // remove the info for this task m_task[ task ].m_targetObjectID = INVALID_ID; m_task[ task ].m_taskOrderFrame = 0; diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h index 150e893762d..022023705e2 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h @@ -141,6 +141,7 @@ class DozerAIInterface virtual void newTask( DozerTask task, Object *target ) = 0; ///< set a desire to do the requested task virtual void cancelTask( DozerTask task ) = 0; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it virtual void cancelAllTasks() = 0; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it + virtual void setPreviousTask(DozerTask task) = 0; ///< set the previous task virtual void resumePreviousTask() = 0; ///< resume the previous task if there was one // internal methods to manage behavior from within the dozer state machine @@ -242,6 +243,7 @@ class DozerAIUpdate : public AIUpdateInterface, public DozerAIInterface virtual void newTask( DozerTask task, Object *target ) override; ///< set a desire to do the requested task virtual void cancelTask( DozerTask task ) override; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it virtual void cancelAllTasks() override; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it + virtual void setPreviousTask(DozerTask task) override; ///< set the previous task virtual void resumePreviousTask() override; ///< resume the previous task if there was one // internal methods to manage behavior from within the dozer state machine diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h index 5d0faa343f6..b76d04eec14 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h @@ -159,6 +159,7 @@ class WorkerAIUpdate : public AIUpdateInterface, public DozerAIInterface, public virtual void newTask( DozerTask task, Object* target ) override; ///< set a desire to do the requested task virtual void cancelTask( DozerTask task ) override; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it virtual void cancelAllTasks() override; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it + virtual void setPreviousTask(DozerTask task) override; ///< set the previous task virtual void resumePreviousTask() override; ///< resume the previous task if there was one // internal methods to manage behavior from within the dozer state machine diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 629cf11f4fe..a1378a485d1 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -2196,6 +2196,10 @@ void Object::setDisabledUntil( DisabledType type, UnsignedInt frame ) sound.setPosition( getPosition() ); TheAudio->addAudioEvent( &sound ); } + + DozerAIInterface* dozerAI = getAI() ? getAI()->getDozerAIInterface() : nullptr; + if (dozerAI) + dozerAI->setPreviousTask(dozerAI->getCurrentTask()); } } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index e5443a2a2d1..5a1a46a97af 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2075,6 +2075,18 @@ void DozerAIUpdate::cancelAllTasks() m_dozerMachine->resetToDefaultState(); } +//------------------------------------------------------------------------------------------------- +/** Set the previous task so that we may return to it if we become temporarily incapacitated */ +//------------------------------------------------------------------------------------------------- +void DozerAIUpdate::setPreviousTask(DozerTask task) +{ + if (task == DOZER_TASK_INVALID) + return; + + m_previousTask = task; + m_previousTaskInfo = m_task[task]; +} + //------------------------------------------------------------------------------------------------- /** Attempt to resume the previous task */ //------------------------------------------------------------------------------------------------- @@ -2169,9 +2181,6 @@ void DozerAIUpdate::internalCancelTask( DozerTask task ) // call the single method that gets called for completing and canceling tasks internalTaskCompleteOrCancelled( task ); - m_previousTask = task; - m_previousTaskInfo = m_task[task]; - // remove the info for this task m_task[ task ].m_targetObjectID = INVALID_ID; m_task[ task ].m_taskOrderFrame = 0; 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 5f62781b4ab..e1b458c660c 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -710,6 +710,18 @@ void WorkerAIUpdate::cancelAllTasks() m_dozerMachine->resetToDefaultState(); } +//------------------------------------------------------------------------------------------------- +/** Set the previous task so that we may return to it if we become temporarily incapacitated */ +//------------------------------------------------------------------------------------------------- +void WorkerAIUpdate::setPreviousTask(DozerTask task) +{ + if (task == DOZER_TASK_INVALID) + return; + + m_previousTask = task; + m_previousTaskInfo = m_task[task]; +} + //------------------------------------------------------------------------------------------------- /** Attempt to resume the previous task */ //------------------------------------------------------------------------------------------------- @@ -804,9 +816,6 @@ void WorkerAIUpdate::internalCancelTask( DozerTask task ) // call the single method that gets called for completing and canceling tasks internalTaskCompleteOrCancelled( task ); - m_previousTask = task; - m_previousTaskInfo = m_task[task]; - // remove the info for this task m_task[ task ].m_targetObjectID = INVALID_ID; m_task[ task ].m_taskOrderFrame = 0; From 0c66471f112c151b4280ae67ad2472c40b2664c0 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Mon, 15 Jun 2026 02:07:26 +1000 Subject: [PATCH 03/18] refactor: Move fix to the task resumption method --- .../Object/Update/AIUpdate/DozerAIUpdate.cpp | 16 +++++++++------- .../Object/Update/AIUpdate/WorkerAIUpdate.cpp | 16 +++++++++------- .../Object/Update/AIUpdate/DozerAIUpdate.cpp | 16 +++++++++------- .../Object/Update/AIUpdate/WorkerAIUpdate.cpp | 16 +++++++++------- 4 files changed, 36 insertions(+), 28 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index 34d58e379b7..a7780bd3c38 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2015,13 +2015,7 @@ void DozerAIUpdate::newTask( DozerTask task, Object *target ) // multiple dozers/workers to double up on construction efforts // if( task == DOZER_TASK_BUILD ) - { - // TheSuperHackers @bugfix Stubbjax 15/06/2026 Ignore the build task if the building is already complete. - if (target->getConstructionPercent() == CONSTRUCTION_COMPLETE) - return; - target->setBuilder( me ); - } m_dockPoint[ task ][ DOZER_DOCK_POINT_START ].valid = TRUE; m_dockPoint[ task ][ DOZER_DOCK_POINT_START ].location = position; @@ -2087,8 +2081,16 @@ void DozerAIUpdate::setPreviousTask(DozerTask task) //------------------------------------------------------------------------------------------------- void DozerAIUpdate::resumePreviousTask() { - if (m_previousTask != DOZER_TASK_INVALID) + if (m_previousTask == DOZER_TASK_INVALID) + return; + + // TheSuperHackers @bugfix Stubbjax 15/06/2026 Ignore the build task if the building is already complete. + if (m_previousTask == DOZER_TASK_BUILD) { + Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); + if (target && target->getConstructionPercent() == CONSTRUCTION_COMPLETE) + return; + newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); m_previousTask = DOZER_TASK_INVALID; m_previousTaskInfo = DozerTaskInfo(); 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 f50148491b9..abe17abc859 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -644,13 +644,7 @@ void WorkerAIUpdate::newTask( DozerTask task, Object* target ) // multiple dozers/workers to double up on construction efforts // if( task == DOZER_TASK_BUILD ) - { - // TheSuperHackers @bugfix Stubbjax 15/06/2026 Ignore the build task if the building is already complete. - if (target->getConstructionPercent() == CONSTRUCTION_COMPLETE) - return; - target->setBuilder( me ); - } m_dockPoint[ task ][ DOZER_DOCK_POINT_START ].valid = TRUE; m_dockPoint[ task ][ DOZER_DOCK_POINT_START ].location = position; @@ -727,8 +721,16 @@ void WorkerAIUpdate::setPreviousTask(DozerTask task) //------------------------------------------------------------------------------------------------- void WorkerAIUpdate::resumePreviousTask() { - if (m_previousTask != DOZER_TASK_INVALID) + if (m_previousTask == DOZER_TASK_INVALID) + return; + + // TheSuperHackers @bugfix Stubbjax 15/06/2026 Ignore the build task if the building is already complete. + if (m_previousTask == DOZER_TASK_BUILD) { + Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); + if (target && target->getConstructionPercent() == CONSTRUCTION_COMPLETE) + return; + newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); m_previousTask = DOZER_TASK_INVALID; m_previousTaskInfo = DozerTaskInfo(); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index 5a1a46a97af..5dc953b98dd 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2020,13 +2020,7 @@ void DozerAIUpdate::newTask( DozerTask task, Object *target ) // multiple dozers/workers to double up on construction efforts // if( task == DOZER_TASK_BUILD ) - { - // TheSuperHackers @bugfix Stubbjax 15/06/2026 Ignore the build task if the building is already complete. - if (target->getConstructionPercent() == CONSTRUCTION_COMPLETE) - return; - target->setBuilder( me ); - } m_dockPoint[ task ][ DOZER_DOCK_POINT_START ].valid = TRUE; m_dockPoint[ task ][ DOZER_DOCK_POINT_START ].location = position; @@ -2092,8 +2086,16 @@ void DozerAIUpdate::setPreviousTask(DozerTask task) //------------------------------------------------------------------------------------------------- void DozerAIUpdate::resumePreviousTask() { - if (m_previousTask != DOZER_TASK_INVALID) + if (m_previousTask == DOZER_TASK_INVALID) + return; + + // TheSuperHackers @bugfix Stubbjax 15/06/2026 Ignore the build task if the building is already complete. + if (m_previousTask == DOZER_TASK_BUILD) { + Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); + if (target && target->getConstructionPercent() == CONSTRUCTION_COMPLETE) + return; + newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); m_previousTask = DOZER_TASK_INVALID; m_previousTaskInfo = DozerTaskInfo(); 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 e1b458c660c..c34e8c480d5 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -644,13 +644,7 @@ void WorkerAIUpdate::newTask( DozerTask task, Object* target ) // multiple dozers/workers to double up on construction efforts // if( task == DOZER_TASK_BUILD ) - { - // TheSuperHackers @bugfix Stubbjax 15/06/2026 Ignore the build task if the building is already complete. - if (target->getConstructionPercent() == CONSTRUCTION_COMPLETE) - return; - target->setBuilder( me ); - } m_dockPoint[ task ][ DOZER_DOCK_POINT_START ].valid = TRUE; m_dockPoint[ task ][ DOZER_DOCK_POINT_START ].location = position; @@ -727,8 +721,16 @@ void WorkerAIUpdate::setPreviousTask(DozerTask task) //------------------------------------------------------------------------------------------------- void WorkerAIUpdate::resumePreviousTask() { - if (m_previousTask != DOZER_TASK_INVALID) + if (m_previousTask == DOZER_TASK_INVALID) + return; + + // TheSuperHackers @bugfix Stubbjax 15/06/2026 Ignore the build task if the building is already complete. + if (m_previousTask == DOZER_TASK_BUILD) { + Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); + if (target && target->getConstructionPercent() == CONSTRUCTION_COMPLETE) + return; + newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); m_previousTask = DOZER_TASK_INVALID; m_previousTaskInfo = DozerTaskInfo(); From 6cf851a96556936a42df1f8a503abe8a3c58368b Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Mon, 15 Jun 2026 02:34:21 +1000 Subject: [PATCH 04/18] docs: Remove superfluous comments --- .../Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp | 1 - .../Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp | 1 - .../Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp | 1 - .../Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp | 1 - 4 files changed, 4 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index a7780bd3c38..011007d20e4 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2084,7 +2084,6 @@ void DozerAIUpdate::resumePreviousTask() if (m_previousTask == DOZER_TASK_INVALID) return; - // TheSuperHackers @bugfix Stubbjax 15/06/2026 Ignore the build task if the building is already complete. if (m_previousTask == DOZER_TASK_BUILD) { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); 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 abe17abc859..ab36f864e9f 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -724,7 +724,6 @@ void WorkerAIUpdate::resumePreviousTask() if (m_previousTask == DOZER_TASK_INVALID) return; - // TheSuperHackers @bugfix Stubbjax 15/06/2026 Ignore the build task if the building is already complete. if (m_previousTask == DOZER_TASK_BUILD) { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index 5dc953b98dd..5125de5a4f8 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2089,7 +2089,6 @@ void DozerAIUpdate::resumePreviousTask() if (m_previousTask == DOZER_TASK_INVALID) return; - // TheSuperHackers @bugfix Stubbjax 15/06/2026 Ignore the build task if the building is already complete. if (m_previousTask == DOZER_TASK_BUILD) { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); 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 c34e8c480d5..68969e75897 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -724,7 +724,6 @@ void WorkerAIUpdate::resumePreviousTask() if (m_previousTask == DOZER_TASK_INVALID) return; - // TheSuperHackers @bugfix Stubbjax 15/06/2026 Ignore the build task if the building is already complete. if (m_previousTask == DOZER_TASK_BUILD) { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); From dc11862e6ee863fc14869cdda261d14426d05e79 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Mon, 15 Jun 2026 02:36:47 +1000 Subject: [PATCH 05/18] refactor: Check construction status bit instead of construction percent --- .../Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp | 2 +- .../Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp | 2 +- .../Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp | 2 +- .../Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index 011007d20e4..7bbc31c47ae 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2087,7 +2087,7 @@ void DozerAIUpdate::resumePreviousTask() if (m_previousTask == DOZER_TASK_BUILD) { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); - if (target && target->getConstructionPercent() == CONSTRUCTION_COMPLETE) + if (target && !target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) return; newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); 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 ab36f864e9f..62e77128a12 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -727,7 +727,7 @@ void WorkerAIUpdate::resumePreviousTask() if (m_previousTask == DOZER_TASK_BUILD) { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); - if (target && target->getConstructionPercent() == CONSTRUCTION_COMPLETE) + if (target && !target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) return; newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index 5125de5a4f8..e569b53584c 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2092,7 +2092,7 @@ void DozerAIUpdate::resumePreviousTask() if (m_previousTask == DOZER_TASK_BUILD) { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); - if (target && target->getConstructionPercent() == CONSTRUCTION_COMPLETE) + if (target && !target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) return; newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); 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 68969e75897..c1f92cf8419 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -727,7 +727,7 @@ void WorkerAIUpdate::resumePreviousTask() if (m_previousTask == DOZER_TASK_BUILD) { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); - if (target && target->getConstructionPercent() == CONSTRUCTION_COMPLETE) + if (target && !target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) return; newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); From 122edf070c33f4ed58112b64b0b5461127234332 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Mon, 15 Jun 2026 02:38:12 +1000 Subject: [PATCH 06/18] tweak: Still clear previous task if the resumed build fails --- .../Object/Update/AIUpdate/DozerAIUpdate.cpp | 11 +++++------ .../Object/Update/AIUpdate/WorkerAIUpdate.cpp | 11 +++++------ .../Object/Update/AIUpdate/DozerAIUpdate.cpp | 11 +++++------ .../Object/Update/AIUpdate/WorkerAIUpdate.cpp | 11 +++++------ 4 files changed, 20 insertions(+), 24 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index 7bbc31c47ae..a8b6716a7e5 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2087,13 +2087,12 @@ void DozerAIUpdate::resumePreviousTask() if (m_previousTask == DOZER_TASK_BUILD) { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); - if (target && !target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) - return; - - newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); - m_previousTask = DOZER_TASK_INVALID; - m_previousTaskInfo = DozerTaskInfo(); + if (!target || target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) + newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); } + + m_previousTask = DOZER_TASK_INVALID; + m_previousTaskInfo = DozerTaskInfo(); } //------------------------------------------------------------------------------------------------- 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 62e77128a12..a9dc0ad627b 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -727,13 +727,12 @@ void WorkerAIUpdate::resumePreviousTask() if (m_previousTask == DOZER_TASK_BUILD) { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); - if (target && !target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) - return; - - newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); - m_previousTask = DOZER_TASK_INVALID; - m_previousTaskInfo = DozerTaskInfo(); + if (!target || target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) + newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); } + + m_previousTask = DOZER_TASK_INVALID; + m_previousTaskInfo = DozerTaskInfo(); } //------------------------------------------------------------------------------------------------- diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index e569b53584c..277f0517f96 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2092,13 +2092,12 @@ void DozerAIUpdate::resumePreviousTask() if (m_previousTask == DOZER_TASK_BUILD) { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); - if (target && !target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) - return; - - newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); - m_previousTask = DOZER_TASK_INVALID; - m_previousTaskInfo = DozerTaskInfo(); + if (!target || target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) + newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); } + + m_previousTask = DOZER_TASK_INVALID; + m_previousTaskInfo = DozerTaskInfo(); } //------------------------------------------------------------------------------------------------- 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 c1f92cf8419..bc47e363f30 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -727,13 +727,12 @@ void WorkerAIUpdate::resumePreviousTask() if (m_previousTask == DOZER_TASK_BUILD) { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); - if (target && !target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) - return; - - newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); - m_previousTask = DOZER_TASK_INVALID; - m_previousTaskInfo = DozerTaskInfo(); + if (!target || target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) + newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); } + + m_previousTask = DOZER_TASK_INVALID; + m_previousTaskInfo = DozerTaskInfo(); } //------------------------------------------------------------------------------------------------- From 04e0119835119955a5cf3c675fb0ffced81a2fcb Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Mon, 15 Jun 2026 02:53:21 +1000 Subject: [PATCH 07/18] refactor: Optimise target acquisition --- .../Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp | 2 +- .../Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp | 2 +- .../Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp | 2 +- .../Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index a8b6716a7e5..416cae0f77d 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2088,7 +2088,7 @@ void DozerAIUpdate::resumePreviousTask() { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); if (!target || target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) - newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); + newTask(m_previousTask, target); } m_previousTask = DOZER_TASK_INVALID; 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 a9dc0ad627b..bd7147c607f 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -728,7 +728,7 @@ void WorkerAIUpdate::resumePreviousTask() { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); if (!target || target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) - newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); + newTask(m_previousTask, target); } m_previousTask = DOZER_TASK_INVALID; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index 277f0517f96..19756d4bdc5 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2093,7 +2093,7 @@ void DozerAIUpdate::resumePreviousTask() { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); if (!target || target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) - newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); + newTask(m_previousTask, target); } m_previousTask = DOZER_TASK_INVALID; 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 bc47e363f30..a37e806c172 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -728,7 +728,7 @@ void WorkerAIUpdate::resumePreviousTask() { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); if (!target || target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) - newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); + newTask(m_previousTask, target); } m_previousTask = DOZER_TASK_INVALID; From cbb639aa82dbbd82f116a1c68cddc3612108daaa Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Mon, 15 Jun 2026 02:54:52 +1000 Subject: [PATCH 08/18] fix: Reverse condition --- .../Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp | 2 +- .../Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp | 2 +- .../Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp | 2 +- .../Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index 416cae0f77d..0f3db93ccbb 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2087,7 +2087,7 @@ void DozerAIUpdate::resumePreviousTask() if (m_previousTask == DOZER_TASK_BUILD) { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); - if (!target || target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) + if (target && target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) newTask(m_previousTask, target); } 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 bd7147c607f..18c4d6bf4b6 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -727,7 +727,7 @@ void WorkerAIUpdate::resumePreviousTask() if (m_previousTask == DOZER_TASK_BUILD) { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); - if (!target || target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) + if (target && target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) newTask(m_previousTask, target); } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index 19756d4bdc5..db3cbe9fd99 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2092,7 +2092,7 @@ void DozerAIUpdate::resumePreviousTask() if (m_previousTask == DOZER_TASK_BUILD) { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); - if (!target || target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) + if (target && target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) newTask(m_previousTask, target); } 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 a37e806c172..f49f3ed0c90 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -727,7 +727,7 @@ void WorkerAIUpdate::resumePreviousTask() if (m_previousTask == DOZER_TASK_BUILD) { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); - if (!target || target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) + if (target && target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) newTask(m_previousTask, target); } From 2145c6a30abce8e7a9c265e6f4a05ac1f70d5492 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Mon, 24 Aug 2026 01:19:57 +1000 Subject: [PATCH 09/18] bugfix: Apply correct version condition --- .../Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp | 2 +- .../Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp | 2 +- .../Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp | 2 +- .../Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index 0f3db93ccbb..438fc3746e4 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2526,7 +2526,7 @@ void DozerAIUpdate::xfer( Xfer *xfer ) xfer->xferSnapshot(m_dozerMachine); xfer->xferUser(&m_currentTask, sizeof(m_currentTask)); - if (currentVersion >= 2) + if (version >= 2) { xfer->xferUser(&m_previousTask, sizeof(m_previousTask)); xfer->xferUser(&m_previousTaskInfo, sizeof(m_previousTaskInfo)); 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 18c4d6bf4b6..c81f7715548 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -1478,7 +1478,7 @@ void WorkerAIUpdate::xfer( Xfer *xfer ) xfer->xferSnapshot(m_dozerMachine); xfer->xferUser(&m_currentTask, sizeof(m_currentTask)); - if (currentVersion >= 2) + if (version >= 2) { xfer->xferUser(&m_previousTask, sizeof(m_previousTask)); xfer->xferUser(&m_previousTaskInfo, sizeof(m_previousTaskInfo)); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index db3cbe9fd99..4bcc1ec6ec7 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2538,7 +2538,7 @@ void DozerAIUpdate::xfer( Xfer *xfer ) xfer->xferSnapshot(m_dozerMachine); xfer->xferUser(&m_currentTask, sizeof(m_currentTask)); - if (currentVersion >= 2) + if (version >= 2) { xfer->xferUser(&m_previousTask, sizeof(m_previousTask)); xfer->xferUser(&m_previousTaskInfo, sizeof(m_previousTaskInfo)); 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 f49f3ed0c90..cae8d525f11 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -1488,7 +1488,7 @@ void WorkerAIUpdate::xfer( Xfer *xfer ) xfer->xferSnapshot(m_dozerMachine); xfer->xferUser(&m_currentTask, sizeof(m_currentTask)); - if (currentVersion >= 2) + if (version >= 2) { xfer->xferUser(&m_previousTask, sizeof(m_previousTask)); xfer->xferUser(&m_previousTaskInfo, sizeof(m_previousTaskInfo)); From cb687409d0c41b6045d02eb2f2d5400fa07fe26e Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Mon, 24 Aug 2026 01:27:26 +1000 Subject: [PATCH 10/18] tweak: Support resumption of repair tasks --- .../GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp | 6 ++++++ .../GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp | 6 ++++++ .../GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp | 6 ++++++ .../GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp | 6 ++++++ 4 files changed, 24 insertions(+) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index 438fc3746e4..8190ed95ef6 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2090,6 +2090,12 @@ void DozerAIUpdate::resumePreviousTask() if (target && target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) newTask(m_previousTask, target); } + else if (m_previousTask == DOZER_TASK_REPAIR) + { + Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); + if (target) + newTask(m_previousTask, target); + } m_previousTask = DOZER_TASK_INVALID; m_previousTaskInfo = DozerTaskInfo(); 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 c81f7715548..2f6fe5112eb 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -730,6 +730,12 @@ void WorkerAIUpdate::resumePreviousTask() if (target && target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) newTask(m_previousTask, target); } + else if (m_previousTask == DOZER_TASK_REPAIR) + { + Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); + if (target) + newTask(m_previousTask, target); + } m_previousTask = DOZER_TASK_INVALID; m_previousTaskInfo = DozerTaskInfo(); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index 4bcc1ec6ec7..98c926e3da9 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2095,6 +2095,12 @@ void DozerAIUpdate::resumePreviousTask() if (target && target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) newTask(m_previousTask, target); } + else if (m_previousTask == DOZER_TASK_REPAIR) + { + Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); + if (target) + newTask(m_previousTask, target); + } m_previousTask = DOZER_TASK_INVALID; m_previousTaskInfo = DozerTaskInfo(); 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 cae8d525f11..0235bc28e53 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -730,6 +730,12 @@ void WorkerAIUpdate::resumePreviousTask() if (target && target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) newTask(m_previousTask, target); } + else if (m_previousTask == DOZER_TASK_REPAIR) + { + Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); + if (target) + newTask(m_previousTask, target); + } m_previousTask = DOZER_TASK_INVALID; m_previousTaskInfo = DozerTaskInfo(); From 506f141f6b00fed01314d37a92b46c2d7f5bbd65 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Mon, 24 Aug 2026 01:32:20 +1000 Subject: [PATCH 11/18] refactor: Streamline previous task assignment --- .../Source/GameLogic/Object/Object.cpp | 4 ---- .../Source/GameLogic/Object/Object.cpp | 16 ++++++++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 9b7de7ffa53..d5748b002e4 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -1985,10 +1985,6 @@ void Object::setDisabledUntil( DisabledType type, UnsignedInt frame ) sound.setPosition( getPosition() ); TheAudio->addAudioEvent( &sound ); } - - DozerAIInterface* dozerAI = getAI() ? getAI()->getDozerAIInterface() : nullptr; - if (dozerAI) - dozerAI->setPreviousTask(dozerAI->getCurrentTask()); } } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp index a1378a485d1..bd782500ac5 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -2196,10 +2196,6 @@ void Object::setDisabledUntil( DisabledType type, UnsignedInt frame ) sound.setPosition( getPosition() ); TheAudio->addAudioEvent( &sound ); } - - DozerAIInterface* dozerAI = getAI() ? getAI()->getDozerAIInterface() : nullptr; - if (dozerAI) - dozerAI->setPreviousTask(dozerAI->getCurrentTask()); } } @@ -3919,7 +3915,19 @@ void Object::onDisabledEdge(Bool becomingDisabled) { // Have to say goodbye to the thing we might be building or repairing so someone else can do it. if (dozerAI->getCurrentTask() != DOZER_TASK_INVALID) + { + // TheSuperHackers @info We want to explicitly define what types to resume from as some types + // are undesirable (e.g. DISABLED_HELD via entering/exiting a container). + Bool attemptToResumeTask = isDisabledByType(DISABLED_EMP) || + isDisabledByType(DISABLED_HACKED) || + isDisabledByType(DISABLED_SUBDUED) || + isDisabledByType(DISABLED_UNDERPOWERED); + + if (attemptToResumeTask) + dozerAI->setPreviousTask(dozerAI->getCurrentTask()); + dozerAI->cancelTask(dozerAI->getCurrentTask()); + } } else { From 5f41b3b2ab8eb9b00f7fa0366204ac9e9d1d052e Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Tue, 1 Sep 2026 20:01:12 +1000 Subject: [PATCH 12/18] refactor: Push down onDisabledEdge behaviour to DozerAIUpdate and WorkerAIUpdate --- .../Code/GameEngine/Include/Common/Module.h | 1 + .../Include/GameLogic/Module/DozerAIUpdate.h | 1 + .../Include/GameLogic/Module/WorkerAIUpdate.h | 1 + .../Source/GameLogic/Object/Object.cpp | 4 +++ .../Object/Update/AIUpdate/DozerAIUpdate.cpp | 29 ++++++++++++++++++ .../Object/Update/AIUpdate/WorkerAIUpdate.cpp | 29 ++++++++++++++++++ .../Include/GameLogic/Module/DozerAIUpdate.h | 1 + .../Include/GameLogic/Module/WorkerAIUpdate.h | 1 + .../Source/GameLogic/Object/Object.cpp | 30 ------------------- .../Object/Update/AIUpdate/DozerAIUpdate.cpp | 29 ++++++++++++++++++ .../Object/Update/AIUpdate/WorkerAIUpdate.cpp | 29 ++++++++++++++++++ 11 files changed, 125 insertions(+), 30 deletions(-) diff --git a/Generals/Code/GameEngine/Include/Common/Module.h b/Generals/Code/GameEngine/Include/Common/Module.h index ca254e755f0..084a44f82cf 100644 --- a/Generals/Code/GameEngine/Include/Common/Module.h +++ b/Generals/Code/GameEngine/Include/Common/Module.h @@ -248,6 +248,7 @@ class ObjectModule : public Module // virtual destructor prototype defined by MemoryPoolObject virtual void onCapture( Player *oldOwner, Player *newOwner ) { } + virtual void onDisabledEdge( Bool nowDisabled ) { } protected: diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h index 458db09b7b8..6cedd61dbac 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h @@ -212,6 +212,7 @@ class DozerAIUpdate : public AIUpdateInterface, public DozerAIInterface virtual const DozerAIInterface* getDozerAIInterface() const override {return this;} virtual void onDelete() override; + virtual void onDisabledEdge(Bool nowDisabled) override; // // module data methods ... this is LAME, multiple inheritance off an interface with replicated diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h index edb142c3449..5d3595a39de 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h @@ -132,6 +132,7 @@ class WorkerAIUpdate : public AIUpdateInterface, public DozerAIInterface, public // Dozer side virtual void onDelete() override; + virtual void onDisabledEdge(Bool nowDisabled) override; virtual Real getRepairHealthPerSecond() const override; ///< get health to repair per second virtual Real getBoredTime() const override; ///< how long till we're bored diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp index d5748b002e4..4e37a99ec2e 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -3415,6 +3415,10 @@ void Object::friend_adjustPowerForPlayer( Bool incoming ) //------------------------------------------------------------------------------------------------- void Object::onDisabledEdge(Bool becomingDisabled) { + // rip through the behavior modules and call the onDisabledEdge for any modules that care + for( BehaviorModule **module = m_behaviors; *module; ++module ) + (*module)->onDisabledEdge( becomingDisabled ); + Player* controller = getControllingPlayer(); // can be called during game teardown, thus controller can be null if (controller) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index 8190ed95ef6..fb53cc78a5e 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2318,6 +2318,35 @@ void DozerAIUpdate::onDelete() } } +void DozerAIUpdate::onDisabledEdge(Bool nowDisabled) +{ + if (nowDisabled) + { + // Have to say goodbye to the thing we might be building or repairing so someone else can do it. + if (getCurrentTask() != DOZER_TASK_INVALID) + { + // TheSuperHackers @info We want to explicitly define what types to resume from as some types + // are undesirable (e.g. DISABLED_HELD via entering/exiting a container). + Bool attemptToResumeTask = getObject()->isDisabledByType(DISABLED_EMP) || + getObject()->isDisabledByType(DISABLED_HACKED) || + getObject()->isDisabledByType(DISABLED_SUBDUED) || + getObject()->isDisabledByType(DISABLED_UNDERPOWERED); + + if (attemptToResumeTask) + setPreviousTask(getCurrentTask()); + + cancelTask(getCurrentTask()); + } + } + else + { +#if !RETAIL_COMPATIBLE_CRC + // TheSuperHackers @bugfix Stubbjax 17/11/2025 Resume previous task when re-enabled. + resumePreviousTask(); +#endif + } +} + //------------------------------------------------------------------------------------------------- /** Get the most recently issued task */ //------------------------------------------------------------------------------------------------- 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 2f6fe5112eb..6fc4df40ebb 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -946,6 +946,35 @@ void WorkerAIUpdate::onDelete() } } +void WorkerAIUpdate::onDisabledEdge(Bool nowDisabled) +{ + if (nowDisabled) + { + // Have to say goodbye to the thing we might be building or repairing so someone else can do it. + if (getCurrentTask() != DOZER_TASK_INVALID) + { + // TheSuperHackers @info We want to explicitly define what types to resume from as some types + // are undesirable (e.g. DISABLED_HELD via entering/exiting a container). + Bool attemptToResumeTask = getObject()->isDisabledByType(DISABLED_EMP) || + getObject()->isDisabledByType(DISABLED_HACKED) || + getObject()->isDisabledByType(DISABLED_SUBDUED) || + getObject()->isDisabledByType(DISABLED_UNDERPOWERED); + + if (attemptToResumeTask) + setPreviousTask(getCurrentTask()); + + cancelTask(getCurrentTask()); + } + } + else + { +#if !RETAIL_COMPATIBLE_CRC + // TheSuperHackers @bugfix Stubbjax 17/11/2025 Resume previous task when re-enabled. + resumePreviousTask(); +#endif + } +} + //------------------------------------------------------------------------------------------------- /** Get the most recently issued task */ //------------------------------------------------------------------------------------------------- diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h index 022023705e2..477a390cfc0 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h @@ -212,6 +212,7 @@ class DozerAIUpdate : public AIUpdateInterface, public DozerAIInterface virtual const DozerAIInterface* getDozerAIInterface() const override {return this;} virtual void onDelete() override; + virtual void onDisabledEdge(Bool nowDisabled) override; // // module data methods ... this is LAME, multiple inheritance off an interface with replicated diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h index b76d04eec14..c8eda0266cd 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h @@ -135,6 +135,7 @@ class WorkerAIUpdate : public AIUpdateInterface, public DozerAIInterface, public // Dozer side virtual void onDelete() override; + virtual void onDisabledEdge(Bool nowDisabled) override; virtual Real getRepairHealthPerSecond() const override; ///< get health to repair per second virtual Real getBoredTime() const override; ///< how long till we're bored diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp index bd782500ac5..ba7b7264b77 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -3908,36 +3908,6 @@ void Object::onDisabledEdge(Bool becomingDisabled) for( BehaviorModule **module = m_behaviors; *module; ++module ) (*module)->onDisabledEdge( becomingDisabled ); - DozerAIInterface *dozerAI = getAI() ? getAI()->getDozerAIInterface() : nullptr; - if (dozerAI) - { - if (becomingDisabled) - { - // Have to say goodbye to the thing we might be building or repairing so someone else can do it. - if (dozerAI->getCurrentTask() != DOZER_TASK_INVALID) - { - // TheSuperHackers @info We want to explicitly define what types to resume from as some types - // are undesirable (e.g. DISABLED_HELD via entering/exiting a container). - Bool attemptToResumeTask = isDisabledByType(DISABLED_EMP) || - isDisabledByType(DISABLED_HACKED) || - isDisabledByType(DISABLED_SUBDUED) || - isDisabledByType(DISABLED_UNDERPOWERED); - - if (attemptToResumeTask) - dozerAI->setPreviousTask(dozerAI->getCurrentTask()); - - dozerAI->cancelTask(dozerAI->getCurrentTask()); - } - } - else - { -#if !RETAIL_COMPATIBLE_CRC - // TheSuperHackers @bugfix Stubbjax 17/11/2025 Resume previous task when re-enabled. - dozerAI->resumePreviousTask(); -#endif - } - } - Player* controller = getControllingPlayer(); // can be called during game teardown, thus controller can be null if (controller) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index 98c926e3da9..3cd3d136687 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2323,6 +2323,35 @@ void DozerAIUpdate::onDelete() } } +void DozerAIUpdate::onDisabledEdge(Bool nowDisabled) +{ + if (nowDisabled) + { + // Have to say goodbye to the thing we might be building or repairing so someone else can do it. + if (getCurrentTask() != DOZER_TASK_INVALID) + { + // TheSuperHackers @info We want to explicitly define what types to resume from as some types + // are undesirable (e.g. DISABLED_HELD via entering/exiting a container). + Bool attemptToResumeTask = getObject()->isDisabledByType(DISABLED_EMP) || + getObject()->isDisabledByType(DISABLED_HACKED) || + getObject()->isDisabledByType(DISABLED_SUBDUED) || + getObject()->isDisabledByType(DISABLED_UNDERPOWERED); + + if (attemptToResumeTask) + setPreviousTask(getCurrentTask()); + + cancelTask(getCurrentTask()); + } + } + else + { +#if !RETAIL_COMPATIBLE_CRC + // TheSuperHackers @bugfix Stubbjax 17/11/2025 Resume previous task when re-enabled. + resumePreviousTask(); +#endif + } +} + //------------------------------------------------------------------------------------------------- /** Get the most recently issued task */ //------------------------------------------------------------------------------------------------- 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 0235bc28e53..82b880c8b11 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -946,6 +946,35 @@ void WorkerAIUpdate::onDelete() } } +void WorkerAIUpdate::onDisabledEdge(Bool nowDisabled) +{ + if (nowDisabled) + { + // Have to say goodbye to the thing we might be building or repairing so someone else can do it. + if (getCurrentTask() != DOZER_TASK_INVALID) + { + // TheSuperHackers @info We want to explicitly define what types to resume from as some types + // are undesirable (e.g. DISABLED_HELD via entering/exiting a container). + Bool attemptToResumeTask = getObject()->isDisabledByType(DISABLED_EMP) || + getObject()->isDisabledByType(DISABLED_HACKED) || + getObject()->isDisabledByType(DISABLED_SUBDUED) || + getObject()->isDisabledByType(DISABLED_UNDERPOWERED); + + if (attemptToResumeTask) + setPreviousTask(getCurrentTask()); + + cancelTask(getCurrentTask()); + } + } + else + { +#if !RETAIL_COMPATIBLE_CRC + // TheSuperHackers @bugfix Stubbjax 17/11/2025 Resume previous task when re-enabled. + resumePreviousTask(); +#endif + } +} + //------------------------------------------------------------------------------------------------- /** Get the most recently issued task */ //------------------------------------------------------------------------------------------------- From 155c6d45550f8cb45fffcd73d4f943624d80ca44 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Tue, 1 Sep 2026 21:29:04 +1000 Subject: [PATCH 13/18] refactor: Remember task as part of cancellation --- .../Include/GameLogic/Module/DozerAIUpdate.h | 4 ++-- .../Include/GameLogic/Module/WorkerAIUpdate.h | 2 +- .../Object/Update/AIUpdate/DozerAIUpdate.cpp | 11 +++++------ .../Object/Update/AIUpdate/WorkerAIUpdate.cpp | 11 +++++------ .../Include/GameLogic/Module/DozerAIUpdate.h | 4 ++-- .../Include/GameLogic/Module/WorkerAIUpdate.h | 2 +- .../Object/Update/AIUpdate/DozerAIUpdate.cpp | 11 +++++------ .../Object/Update/AIUpdate/WorkerAIUpdate.cpp | 11 +++++------ 8 files changed, 26 insertions(+), 30 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h index 6cedd61dbac..65471b28833 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h @@ -139,7 +139,7 @@ class DozerAIInterface // task actions virtual void newTask( DozerTask task, Object *target ) = 0; ///< set a desire to do the requrested task - virtual void cancelTask( DozerTask task ) = 0; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it + virtual void cancelTask( DozerTask task, Bool rememberTask = false ) = 0; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it virtual void cancelAllTasks() = 0; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it virtual void setPreviousTask(DozerTask task) = 0; ///< set the previous task virtual void resumePreviousTask() = 0; ///< resume the previous task if there was one @@ -242,7 +242,7 @@ class DozerAIUpdate : public AIUpdateInterface, public DozerAIInterface // task actions virtual void newTask( DozerTask task, Object *target ) override; ///< set a desire to do the requrested task - virtual void cancelTask( DozerTask task ) override; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it + virtual void cancelTask( DozerTask task, Bool rememberTask = false ) override; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it virtual void cancelAllTasks() override; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it virtual void setPreviousTask(DozerTask task) override; ///< set the previous task virtual void resumePreviousTask() override; ///< resume the previous task if there was one diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h index 5d3595a39de..0bba9759efe 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h @@ -155,7 +155,7 @@ class WorkerAIUpdate : public AIUpdateInterface, public DozerAIInterface, public // task actions virtual void newTask( DozerTask task, Object* target ) override; ///< set a desire to do the requrested task - virtual void cancelTask( DozerTask task ) override; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it + virtual void cancelTask( DozerTask task, Bool rememberTask = false ) override; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it virtual void cancelAllTasks() override; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it virtual void setPreviousTask(DozerTask task) override; ///< set the previous task virtual void resumePreviousTask() override; ///< resume the previous task if there was one diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index fb53cc78a5e..a6420e27d3c 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2045,8 +2045,10 @@ void DozerAIUpdate::newTask( DozerTask task, Object *target ) * re-evaluate what it wants to do if it was working on the task being * cancelled */ //------------------------------------------------------------------------------------------------- -void DozerAIUpdate::cancelTask( DozerTask task ) +void DozerAIUpdate::cancelTask( DozerTask task, Bool rememberTask ) { + if (rememberTask) + setPreviousTask(task); // clear the order internalCancelTask( task ); @@ -2327,15 +2329,12 @@ void DozerAIUpdate::onDisabledEdge(Bool nowDisabled) { // TheSuperHackers @info We want to explicitly define what types to resume from as some types // are undesirable (e.g. DISABLED_HELD via entering/exiting a container). - Bool attemptToResumeTask = getObject()->isDisabledByType(DISABLED_EMP) || + Bool rememberTask = getObject()->isDisabledByType(DISABLED_EMP) || getObject()->isDisabledByType(DISABLED_HACKED) || getObject()->isDisabledByType(DISABLED_SUBDUED) || getObject()->isDisabledByType(DISABLED_UNDERPOWERED); - if (attemptToResumeTask) - setPreviousTask(getCurrentTask()); - - cancelTask(getCurrentTask()); + cancelTask(getCurrentTask(), rememberTask); } } else 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 6fc4df40ebb..95834b86784 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -685,8 +685,10 @@ void WorkerAIUpdate::newTask( DozerTask task, Object* target ) * re-evaluate what it wants to do if it was working on the task being * cancelled */ //------------------------------------------------------------------------------------------------- -void WorkerAIUpdate::cancelTask( DozerTask task ) +void WorkerAIUpdate::cancelTask( DozerTask task, Bool rememberTask ) { + if (rememberTask) + setPreviousTask(task); // clear the order internalCancelTask( task ); @@ -955,15 +957,12 @@ void WorkerAIUpdate::onDisabledEdge(Bool nowDisabled) { // TheSuperHackers @info We want to explicitly define what types to resume from as some types // are undesirable (e.g. DISABLED_HELD via entering/exiting a container). - Bool attemptToResumeTask = getObject()->isDisabledByType(DISABLED_EMP) || + Bool rememberTask = getObject()->isDisabledByType(DISABLED_EMP) || getObject()->isDisabledByType(DISABLED_HACKED) || getObject()->isDisabledByType(DISABLED_SUBDUED) || getObject()->isDisabledByType(DISABLED_UNDERPOWERED); - if (attemptToResumeTask) - setPreviousTask(getCurrentTask()); - - cancelTask(getCurrentTask()); + cancelTask(getCurrentTask(), rememberTask); } } else diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h index 477a390cfc0..a81013b10d6 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h @@ -139,7 +139,7 @@ class DozerAIInterface // task actions virtual void newTask( DozerTask task, Object *target ) = 0; ///< set a desire to do the requested task - virtual void cancelTask( DozerTask task ) = 0; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it + virtual void cancelTask( DozerTask task, Bool rememberTask = false ) = 0; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it virtual void cancelAllTasks() = 0; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it virtual void setPreviousTask(DozerTask task) = 0; ///< set the previous task virtual void resumePreviousTask() = 0; ///< resume the previous task if there was one @@ -242,7 +242,7 @@ class DozerAIUpdate : public AIUpdateInterface, public DozerAIInterface // task actions virtual void newTask( DozerTask task, Object *target ) override; ///< set a desire to do the requested task - virtual void cancelTask( DozerTask task ) override; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it + virtual void cancelTask( DozerTask task, Bool rememberTask = false ) override; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it virtual void cancelAllTasks() override; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it virtual void setPreviousTask(DozerTask task) override; ///< set the previous task virtual void resumePreviousTask() override; ///< resume the previous task if there was one diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h index c8eda0266cd..179688b32e7 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h @@ -158,7 +158,7 @@ class WorkerAIUpdate : public AIUpdateInterface, public DozerAIInterface, public // task actions virtual void newTask( DozerTask task, Object* target ) override; ///< set a desire to do the requested task - virtual void cancelTask( DozerTask task ) override; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it + virtual void cancelTask( DozerTask task, Bool rememberTask = false ) override; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it virtual void cancelAllTasks() override; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it virtual void setPreviousTask(DozerTask task) override; ///< set the previous task virtual void resumePreviousTask() override; ///< resume the previous task if there was one diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index 3cd3d136687..9c93eacc913 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2050,8 +2050,10 @@ void DozerAIUpdate::newTask( DozerTask task, Object *target ) * re-evaluate what it wants to do if it was working on the task being * cancelled */ //------------------------------------------------------------------------------------------------- -void DozerAIUpdate::cancelTask( DozerTask task ) +void DozerAIUpdate::cancelTask( DozerTask task, Bool rememberTask ) { + if (rememberTask) + setPreviousTask(task); // clear the order internalCancelTask( task ); @@ -2332,15 +2334,12 @@ void DozerAIUpdate::onDisabledEdge(Bool nowDisabled) { // TheSuperHackers @info We want to explicitly define what types to resume from as some types // are undesirable (e.g. DISABLED_HELD via entering/exiting a container). - Bool attemptToResumeTask = getObject()->isDisabledByType(DISABLED_EMP) || + Bool rememberTask = getObject()->isDisabledByType(DISABLED_EMP) || getObject()->isDisabledByType(DISABLED_HACKED) || getObject()->isDisabledByType(DISABLED_SUBDUED) || getObject()->isDisabledByType(DISABLED_UNDERPOWERED); - if (attemptToResumeTask) - setPreviousTask(getCurrentTask()); - - cancelTask(getCurrentTask()); + cancelTask(getCurrentTask(), rememberTask); } } else 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 82b880c8b11..7cbbe7270ab 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -685,8 +685,10 @@ void WorkerAIUpdate::newTask( DozerTask task, Object* target ) * re-evaluate what it wants to do if it was working on the task being * cancelled */ //------------------------------------------------------------------------------------------------- -void WorkerAIUpdate::cancelTask( DozerTask task ) +void WorkerAIUpdate::cancelTask( DozerTask task, Bool rememberTask ) { + if (rememberTask) + setPreviousTask(task); // clear the order internalCancelTask( task ); @@ -955,15 +957,12 @@ void WorkerAIUpdate::onDisabledEdge(Bool nowDisabled) { // TheSuperHackers @info We want to explicitly define what types to resume from as some types // are undesirable (e.g. DISABLED_HELD via entering/exiting a container). - Bool attemptToResumeTask = getObject()->isDisabledByType(DISABLED_EMP) || + Bool rememberTask = getObject()->isDisabledByType(DISABLED_EMP) || getObject()->isDisabledByType(DISABLED_HACKED) || getObject()->isDisabledByType(DISABLED_SUBDUED) || getObject()->isDisabledByType(DISABLED_UNDERPOWERED); - if (attemptToResumeTask) - setPreviousTask(getCurrentTask()); - - cancelTask(getCurrentTask()); + cancelTask(getCurrentTask(), rememberTask); } } else From 3886b385258e4058b59c0b45a499bafdf3196090 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Tue, 1 Sep 2026 22:09:18 +1000 Subject: [PATCH 14/18] refactor: Consolidate previous task clearing logic --- .../Include/GameLogic/Module/DozerAIUpdate.h | 2 ++ .../Include/GameLogic/Module/WorkerAIUpdate.h | 1 + .../Object/Update/AIUpdate/DozerAIUpdate.cpp | 8 ++++++-- .../Object/Update/AIUpdate/WorkerAIUpdate.cpp | 8 ++++++-- .../Include/GameLogic/Module/DozerAIUpdate.h | 2 ++ .../Include/GameLogic/Module/WorkerAIUpdate.h | 1 + .../Object/Update/AIUpdate/DozerAIUpdate.cpp | 12 ++++++++---- .../Object/Update/AIUpdate/WorkerAIUpdate.cpp | 8 ++++++-- 8 files changed, 32 insertions(+), 10 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h index 65471b28833..e5fd19087d5 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h @@ -143,6 +143,7 @@ class DozerAIInterface virtual void cancelAllTasks() = 0; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it virtual void setPreviousTask(DozerTask task) = 0; ///< set the previous task virtual void resumePreviousTask() = 0; ///< resume the previous task if there was one + virtual void clearPreviousTask() = 0; ///< clear the previous task // internal methods to manage behavior from within the dozer state machine virtual void internalTaskComplete( DozerTask task ) = 0; ///< set a dozer task as successfully completed @@ -246,6 +247,7 @@ class DozerAIUpdate : public AIUpdateInterface, public DozerAIInterface virtual void cancelAllTasks() override; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it virtual void setPreviousTask(DozerTask task) override; ///< set the previous task virtual void resumePreviousTask() override; ///< resume the previous task if there was one + virtual void clearPreviousTask() override; ///< clear the previous task // internal methods to manage behavior from within the dozer state machine virtual void internalTaskComplete( DozerTask task ) override; ///< set a dozer task as successfully completed diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h index 0bba9759efe..e84c9ae1f46 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h @@ -159,6 +159,7 @@ class WorkerAIUpdate : public AIUpdateInterface, public DozerAIInterface, public virtual void cancelAllTasks() override; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it virtual void setPreviousTask(DozerTask task) override; ///< set the previous task virtual void resumePreviousTask() override; ///< resume the previous task if there was one + virtual void clearPreviousTask() override; ///< clear the previous task // internal methods to manage behavior from within the dozer state machine virtual void internalTaskComplete( DozerTask task ) override; ///< set a dozer task as successfully completed diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index a6420e27d3c..39e12846ba7 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2099,6 +2099,11 @@ void DozerAIUpdate::resumePreviousTask() newTask(m_previousTask, target); } + clearPreviousTask(); +} + +void DozerAIUpdate::clearPreviousTask() +{ m_previousTask = DOZER_TASK_INVALID; m_previousTaskInfo = DozerTaskInfo(); } @@ -2159,8 +2164,7 @@ void DozerAIUpdate::internalTaskComplete( DozerTask task ) m_task[ task ].m_targetObjectID = INVALID_ID; m_task[ task ].m_taskOrderFrame = 0; - m_previousTask = DOZER_TASK_INVALID; - m_previousTaskInfo = DozerTaskInfo(); + clearPreviousTask(); // remove dock point info for this task for( Int i = 0; i < DOZER_NUM_DOCK_POINTS; i++ ) 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 95834b86784..943b7eadf48 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -739,6 +739,11 @@ void WorkerAIUpdate::resumePreviousTask() newTask(m_previousTask, target); } + clearPreviousTask(); +} + +void WorkerAIUpdate::clearPreviousTask() +{ m_previousTask = DOZER_TASK_INVALID; m_previousTaskInfo = DozerTaskInfo(); } @@ -799,8 +804,7 @@ void WorkerAIUpdate::internalTaskComplete( DozerTask task ) m_task[ task ].m_targetObjectID = INVALID_ID; m_task[ task ].m_taskOrderFrame = 0; - m_previousTask = DOZER_TASK_INVALID; - m_previousTaskInfo = DozerTaskInfo(); + clearPreviousTask(); // remove dock point info for this task for( Int i = 0; i < DOZER_NUM_DOCK_POINTS; i++ ) diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h index a81013b10d6..7fe3d392509 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h @@ -143,6 +143,7 @@ class DozerAIInterface virtual void cancelAllTasks() = 0; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it virtual void setPreviousTask(DozerTask task) = 0; ///< set the previous task virtual void resumePreviousTask() = 0; ///< resume the previous task if there was one + virtual void clearPreviousTask() = 0; ///< clear the previous task // internal methods to manage behavior from within the dozer state machine virtual void internalTaskComplete( DozerTask task ) = 0; ///< set a dozer task as successfully completed @@ -246,6 +247,7 @@ class DozerAIUpdate : public AIUpdateInterface, public DozerAIInterface virtual void cancelAllTasks() override; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it virtual void setPreviousTask(DozerTask task) override; ///< set the previous task virtual void resumePreviousTask() override; ///< resume the previous task if there was one + virtual void clearPreviousTask() override; ///< clear the previous task // internal methods to manage behavior from within the dozer state machine virtual void internalTaskComplete( DozerTask task ) override; ///< set a dozer task as successfully completed diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h index 179688b32e7..6e5c5a79be9 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h @@ -162,6 +162,7 @@ class WorkerAIUpdate : public AIUpdateInterface, public DozerAIInterface, public virtual void cancelAllTasks() override; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it virtual void setPreviousTask(DozerTask task) override; ///< set the previous task virtual void resumePreviousTask() override; ///< resume the previous task if there was one + virtual void clearPreviousTask() override; ///< clear the previous task // internal methods to manage behavior from within the dozer state machine virtual void internalTaskComplete( DozerTask task ) override; ///< set a dozer task as successfully completed diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index 9c93eacc913..7c3eb41e115 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2104,8 +2104,13 @@ void DozerAIUpdate::resumePreviousTask() newTask(m_previousTask, target); } - m_previousTask = DOZER_TASK_INVALID; - m_previousTaskInfo = DozerTaskInfo(); + clearPreviousTask(); +} + +void DozerAIUpdate::clearPreviousTask() +{ + m_previousTask = DOZER_TASK_INVALID; + m_previousTaskInfo = DozerTaskInfo(); } //------------------------------------------------------------------------------------------------- @@ -2164,8 +2169,7 @@ void DozerAIUpdate::internalTaskComplete( DozerTask task ) m_task[ task ].m_targetObjectID = INVALID_ID; m_task[ task ].m_taskOrderFrame = 0; - m_previousTask = DOZER_TASK_INVALID; - m_previousTaskInfo = DozerTaskInfo(); + clearPreviousTask(); // remove dock point info for this task for( Int i = 0; i < DOZER_NUM_DOCK_POINTS; i++ ) 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 7cbbe7270ab..7711f44ee34 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -739,6 +739,11 @@ void WorkerAIUpdate::resumePreviousTask() newTask(m_previousTask, target); } + clearPreviousTask(); +} + +void WorkerAIUpdate::clearPreviousTask() +{ m_previousTask = DOZER_TASK_INVALID; m_previousTaskInfo = DozerTaskInfo(); } @@ -799,8 +804,7 @@ void WorkerAIUpdate::internalTaskComplete( DozerTask task ) m_task[ task ].m_targetObjectID = INVALID_ID; m_task[ task ].m_taskOrderFrame = 0; - m_previousTask = DOZER_TASK_INVALID; - m_previousTaskInfo = DozerTaskInfo(); + clearPreviousTask(); // remove dock point info for this task for( Int i = 0; i < DOZER_NUM_DOCK_POINTS; i++ ) From 6bc5daccb212a411046f6ea7005a98243b9b8aae Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Wed, 2 Sep 2026 00:53:02 +1000 Subject: [PATCH 15/18] bugfix: Also resume FORTIFY tasks --- .../Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp | 2 +- .../Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp | 2 +- .../Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp | 2 +- .../Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index 39e12846ba7..fa06088bb65 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2092,7 +2092,7 @@ void DozerAIUpdate::resumePreviousTask() if (target && target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) newTask(m_previousTask, target); } - else if (m_previousTask == DOZER_TASK_REPAIR) + else if (m_previousTask == DOZER_TASK_REPAIR || m_previousTask == DOZER_TASK_FORTIFY) { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); if (target) 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 943b7eadf48..8ac45310c1f 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -732,7 +732,7 @@ void WorkerAIUpdate::resumePreviousTask() if (target && target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) newTask(m_previousTask, target); } - else if (m_previousTask == DOZER_TASK_REPAIR) + else if (m_previousTask == DOZER_TASK_REPAIR || m_previousTask == DOZER_TASK_FORTIFY) { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); if (target) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index 7c3eb41e115..27cb231a22d 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2097,7 +2097,7 @@ void DozerAIUpdate::resumePreviousTask() if (target && target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) newTask(m_previousTask, target); } - else if (m_previousTask == DOZER_TASK_REPAIR) + else if (m_previousTask == DOZER_TASK_REPAIR || m_previousTask == DOZER_TASK_FORTIFY) { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); if (target) 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 7711f44ee34..39ff4435ffd 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -732,7 +732,7 @@ void WorkerAIUpdate::resumePreviousTask() if (target && target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) newTask(m_previousTask, target); } - else if (m_previousTask == DOZER_TASK_REPAIR) + else if (m_previousTask == DOZER_TASK_REPAIR || m_previousTask == DOZER_TASK_FORTIFY) { Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); if (target) From 3c36a85026e73b8ab78ecdbf7bdd0e43415c03c0 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Wed, 2 Sep 2026 01:04:16 +1000 Subject: [PATCH 16/18] bugfix: Cancelling all tasks now clears the previous task --- .../Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp | 2 ++ .../Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp | 2 ++ .../Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp | 2 ++ .../Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp | 2 ++ 4 files changed, 8 insertions(+) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index fa06088bb65..c60801ae013 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2063,6 +2063,8 @@ void DozerAIUpdate::cancelAllTasks() for (UnsignedInt task = DOZER_TASK_FIRST; task < DOZER_NUM_TASKS; ++task) internalCancelTask((DozerTask)task); + clearPreviousTask(); + m_dozerMachine->resetToDefaultState(); } 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 8ac45310c1f..dcfa81a50c4 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -703,6 +703,8 @@ void WorkerAIUpdate::cancelAllTasks() for (UnsignedInt task = DOZER_TASK_FIRST; task < DOZER_NUM_TASKS; ++task) internalCancelTask((DozerTask)task); + clearPreviousTask(); + m_dozerMachine->resetToDefaultState(); } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp index 27cb231a22d..1b01957d1de 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2068,6 +2068,8 @@ void DozerAIUpdate::cancelAllTasks() for (UnsignedInt task = DOZER_TASK_FIRST; task < DOZER_NUM_TASKS; ++task) internalCancelTask((DozerTask)task); + clearPreviousTask(); + m_dozerMachine->resetToDefaultState(); } 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 39ff4435ffd..47a17d182bc 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -703,6 +703,8 @@ void WorkerAIUpdate::cancelAllTasks() for (UnsignedInt task = DOZER_TASK_FIRST; task < DOZER_NUM_TASKS; ++task) internalCancelTask((DozerTask)task); + clearPreviousTask(); + m_dozerMachine->resetToDefaultState(); } From a87efc3259719c2d9580fadd97ff390f0fb654e0 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Thu, 3 Sep 2026 23:59:08 +1000 Subject: [PATCH 17/18] docs: Explain new method argument --- .../Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h | 2 +- .../Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h | 2 +- .../Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h | 2 +- .../Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h index e5fd19087d5..4df7198e3b6 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h @@ -139,7 +139,7 @@ class DozerAIInterface // task actions virtual void newTask( DozerTask task, Object *target ) = 0; ///< set a desire to do the requrested task - virtual void cancelTask( DozerTask task, Bool rememberTask = false ) = 0; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it + virtual void cancelTask( DozerTask task, Bool rememberTask = false ) = 0; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it. Can remember the cancelled task for resumption. virtual void cancelAllTasks() = 0; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it virtual void setPreviousTask(DozerTask task) = 0; ///< set the previous task virtual void resumePreviousTask() = 0; ///< resume the previous task if there was one diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h index e84c9ae1f46..836896178bf 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h @@ -155,7 +155,7 @@ class WorkerAIUpdate : public AIUpdateInterface, public DozerAIInterface, public // task actions virtual void newTask( DozerTask task, Object* target ) override; ///< set a desire to do the requrested task - virtual void cancelTask( DozerTask task, Bool rememberTask = false ) override; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it + virtual void cancelTask( DozerTask task, Bool rememberTask = false ) override; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it. Can remember the cancelled task for resumption. virtual void cancelAllTasks() override; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it virtual void setPreviousTask(DozerTask task) override; ///< set the previous task virtual void resumePreviousTask() override; ///< resume the previous task if there was one diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h index 7fe3d392509..4d1349e87b1 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h @@ -139,7 +139,7 @@ class DozerAIInterface // task actions virtual void newTask( DozerTask task, Object *target ) = 0; ///< set a desire to do the requested task - virtual void cancelTask( DozerTask task, Bool rememberTask = false ) = 0; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it + virtual void cancelTask( DozerTask task, Bool rememberTask = false ) = 0; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it. Can remember the cancelled task for resumption. virtual void cancelAllTasks() = 0; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it virtual void setPreviousTask(DozerTask task) = 0; ///< set the previous task virtual void resumePreviousTask() = 0; ///< resume the previous task if there was one diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h index 6e5c5a79be9..d639c595368 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h @@ -158,7 +158,7 @@ class WorkerAIUpdate : public AIUpdateInterface, public DozerAIInterface, public // task actions virtual void newTask( DozerTask task, Object* target ) override; ///< set a desire to do the requested task - virtual void cancelTask( DozerTask task, Bool rememberTask = false ) override; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it + virtual void cancelTask( DozerTask task, Bool rememberTask = false ) override; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it. Can remember the cancelled task for resumption. virtual void cancelAllTasks() override; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it virtual void setPreviousTask(DozerTask task) override; ///< set the previous task virtual void resumePreviousTask() override; ///< resume the previous task if there was one From 47ccf551d18365e42ef72012ea492e2a95320ff0 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Fri, 4 Sep 2026 01:19:09 +1000 Subject: [PATCH 18/18] chore: Move previous-task methods from the interface to the implementers --- .../Include/GameLogic/Module/DozerAIUpdate.h | 10 ++++------ .../Include/GameLogic/Module/WorkerAIUpdate.h | 7 ++++--- .../Include/GameLogic/Module/DozerAIUpdate.h | 10 ++++------ .../Include/GameLogic/Module/WorkerAIUpdate.h | 7 ++++--- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h index 4df7198e3b6..b8a8dca3ead 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h @@ -141,9 +141,6 @@ class DozerAIInterface virtual void newTask( DozerTask task, Object *target ) = 0; ///< set a desire to do the requrested task virtual void cancelTask( DozerTask task, Bool rememberTask = false ) = 0; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it. Can remember the cancelled task for resumption. virtual void cancelAllTasks() = 0; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it - virtual void setPreviousTask(DozerTask task) = 0; ///< set the previous task - virtual void resumePreviousTask() = 0; ///< resume the previous task if there was one - virtual void clearPreviousTask() = 0; ///< clear the previous task // internal methods to manage behavior from within the dozer state machine virtual void internalTaskComplete( DozerTask task ) = 0; ///< set a dozer task as successfully completed @@ -245,9 +242,6 @@ class DozerAIUpdate : public AIUpdateInterface, public DozerAIInterface virtual void newTask( DozerTask task, Object *target ) override; ///< set a desire to do the requrested task virtual void cancelTask( DozerTask task, Bool rememberTask = false ) override; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it virtual void cancelAllTasks() override; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it - virtual void setPreviousTask(DozerTask task) override; ///< set the previous task - virtual void resumePreviousTask() override; ///< resume the previous task if there was one - virtual void clearPreviousTask() override; ///< clear the previous task // internal methods to manage behavior from within the dozer state machine virtual void internalTaskComplete( DozerTask task ) override; ///< set a dozer task as successfully completed @@ -283,6 +277,10 @@ class DozerAIUpdate : public AIUpdateInterface, public DozerAIInterface virtual void privateRepair( Object *obj, CommandSourceType cmdSource ) override; ///< repair the target virtual void privateResumeConstruction( Object *obj, CommandSourceType cmdSource ) override; ///< resume construction on obj + virtual void setPreviousTask(DozerTask task); ///< set the previous task + virtual void resumePreviousTask(); ///< resume the previous task if there was one + virtual void clearPreviousTask(); ///< clear the previous task + struct DozerTaskInfo { DozerTaskInfo() diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h index 836896178bf..54eb5917c25 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h @@ -157,9 +157,6 @@ class WorkerAIUpdate : public AIUpdateInterface, public DozerAIInterface, public virtual void newTask( DozerTask task, Object* target ) override; ///< set a desire to do the requrested task virtual void cancelTask( DozerTask task, Bool rememberTask = false ) override; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it. Can remember the cancelled task for resumption. virtual void cancelAllTasks() override; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it - virtual void setPreviousTask(DozerTask task) override; ///< set the previous task - virtual void resumePreviousTask() override; ///< resume the previous task if there was one - virtual void clearPreviousTask() override; ///< clear the previous task // internal methods to manage behavior from within the dozer state machine virtual void internalTaskComplete( DozerTask task ) override; ///< set a dozer task as successfully completed @@ -267,6 +264,10 @@ class WorkerAIUpdate : public AIUpdateInterface, public DozerAIInterface, public virtual void privateDock( Object *obj, CommandSourceType cmdSource ) override; virtual void privateIdle(CommandSourceType cmdSource) override; ///< Enter idle state. + virtual void setPreviousTask(DozerTask task); ///< set the previous task + virtual void resumePreviousTask(); ///< resume the previous task if there was one + virtual void clearPreviousTask(); ///< clear the previous task + private: void createMachines(); ///< create our behavior machines we need diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h index 4d1349e87b1..d7113be4a1d 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h @@ -141,9 +141,6 @@ class DozerAIInterface virtual void newTask( DozerTask task, Object *target ) = 0; ///< set a desire to do the requested task virtual void cancelTask( DozerTask task, Bool rememberTask = false ) = 0; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it. Can remember the cancelled task for resumption. virtual void cancelAllTasks() = 0; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it - virtual void setPreviousTask(DozerTask task) = 0; ///< set the previous task - virtual void resumePreviousTask() = 0; ///< resume the previous task if there was one - virtual void clearPreviousTask() = 0; ///< clear the previous task // internal methods to manage behavior from within the dozer state machine virtual void internalTaskComplete( DozerTask task ) = 0; ///< set a dozer task as successfully completed @@ -245,9 +242,6 @@ class DozerAIUpdate : public AIUpdateInterface, public DozerAIInterface virtual void newTask( DozerTask task, Object *target ) override; ///< set a desire to do the requested task virtual void cancelTask( DozerTask task, Bool rememberTask = false ) override; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it virtual void cancelAllTasks() override; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it - virtual void setPreviousTask(DozerTask task) override; ///< set the previous task - virtual void resumePreviousTask() override; ///< resume the previous task if there was one - virtual void clearPreviousTask() override; ///< clear the previous task // internal methods to manage behavior from within the dozer state machine virtual void internalTaskComplete( DozerTask task ) override; ///< set a dozer task as successfully completed @@ -283,6 +277,10 @@ class DozerAIUpdate : public AIUpdateInterface, public DozerAIInterface virtual void privateRepair( Object *obj, CommandSourceType cmdSource ) override; ///< repair the target virtual void privateResumeConstruction( Object *obj, CommandSourceType cmdSource ) override; ///< resume construction on obj + virtual void setPreviousTask(DozerTask task); ///< set the previous task + virtual void resumePreviousTask(); ///< resume the previous task if there was one + virtual void clearPreviousTask(); ///< clear the previous task + struct DozerTaskInfo { DozerTaskInfo() diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h index d639c595368..7b9deabdc08 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h @@ -160,9 +160,6 @@ class WorkerAIUpdate : public AIUpdateInterface, public DozerAIInterface, public virtual void newTask( DozerTask task, Object* target ) override; ///< set a desire to do the requested task virtual void cancelTask( DozerTask task, Bool rememberTask = false ) override; ///< cancel this task from the queue, if it's the current task the dozer will stop working on it. Can remember the cancelled task for resumption. virtual void cancelAllTasks() override; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it - virtual void setPreviousTask(DozerTask task) override; ///< set the previous task - virtual void resumePreviousTask() override; ///< resume the previous task if there was one - virtual void clearPreviousTask() override; ///< clear the previous task // internal methods to manage behavior from within the dozer state machine virtual void internalTaskComplete( DozerTask task ) override; ///< set a dozer task as successfully completed @@ -273,6 +270,10 @@ class WorkerAIUpdate : public AIUpdateInterface, public DozerAIInterface, public virtual void privateDock( Object *obj, CommandSourceType cmdSource ) override; virtual void privateIdle(CommandSourceType cmdSource) override; ///< Enter idle state. + virtual void setPreviousTask(DozerTask task); ///< set the previous task + virtual void resumePreviousTask(); ///< resume the previous task if there was one + virtual void clearPreviousTask(); ///< clear the previous task + private: void createMachines(); ///< create our behavior machines we need