From 68743fffde63dd694d5786b29ebb3744371315ac Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Mon, 15 Jun 2026 01:07:30 +1000 Subject: [PATCH 01/17] 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/17] 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/17] 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/17] 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/17] 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/17] 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/17] 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/17] 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/17] 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/17] 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/17] 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/17] 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/17] 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/17] 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/17] 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/17] 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 558b3cf0e03985511e9cf67b576c207dc2f73773 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Thu, 3 Sep 2026 23:59:08 +1000 Subject: [PATCH 17/17] 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..708b45c99d2 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 (e.g. after the unit is disabled). 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..28030ce6ccc 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 (e.g. after the unit is disabled). 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..5be4b3e46ea 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 (e.g. after the unit is disabled). 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..27fb7e53428 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 (e.g. after the unit is disabled). 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