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 37e33d4a96e..3c83b3d66e9 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -1975,6 +1975,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 79eb4aef39e..558d6351660 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2049,17 +2049,35 @@ 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 */ //------------------------------------------------------------------------------------------------- void DozerAIUpdate::resumePreviousTask() { - if (m_previousTask != DOZER_TASK_INVALID) + if (m_previousTask == DOZER_TASK_INVALID) + return; + + if (m_previousTask == DOZER_TASK_BUILD) { - newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); - m_previousTask = DOZER_TASK_INVALID; - m_previousTaskInfo = DozerTaskInfo(); + Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); + if (target && !target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) + newTask(m_previousTask, target); } + + m_previousTask = DOZER_TASK_INVALID; + m_previousTaskInfo = DozerTaskInfo(); } //------------------------------------------------------------------------------------------------- @@ -2143,9 +2161,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 d8610312c94..d29c252fab4 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -704,17 +704,35 @@ 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 */ //------------------------------------------------------------------------------------------------- void WorkerAIUpdate::resumePreviousTask() { - if (m_previousTask != DOZER_TASK_INVALID) + if (m_previousTask == DOZER_TASK_INVALID) + return; + + if (m_previousTask == DOZER_TASK_BUILD) { - newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); - m_previousTask = DOZER_TASK_INVALID; - m_previousTaskInfo = DozerTaskInfo(); + Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); + if (target && !target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) + newTask(m_previousTask, target); } + + m_previousTask = DOZER_TASK_INVALID; + m_previousTaskInfo = DozerTaskInfo(); } //------------------------------------------------------------------------------------------------- @@ -798,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 377a82f8832..6be6a55ba4b 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -2186,6 +2186,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 c4a0e29a919..85789c3a90b 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2054,17 +2054,35 @@ 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 */ //------------------------------------------------------------------------------------------------- void DozerAIUpdate::resumePreviousTask() { - if (m_previousTask != DOZER_TASK_INVALID) + if (m_previousTask == DOZER_TASK_INVALID) + return; + + if (m_previousTask == DOZER_TASK_BUILD) { - newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); - m_previousTask = DOZER_TASK_INVALID; - m_previousTaskInfo = DozerTaskInfo(); + Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); + if (target && !target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) + newTask(m_previousTask, target); } + + m_previousTask = DOZER_TASK_INVALID; + m_previousTaskInfo = DozerTaskInfo(); } //------------------------------------------------------------------------------------------------- @@ -2148,9 +2166,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 173f2e095af..3858580875f 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -704,17 +704,35 @@ 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 */ //------------------------------------------------------------------------------------------------- void WorkerAIUpdate::resumePreviousTask() { - if (m_previousTask != DOZER_TASK_INVALID) + if (m_previousTask == DOZER_TASK_INVALID) + return; + + if (m_previousTask == DOZER_TASK_BUILD) { - newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); - m_previousTask = DOZER_TASK_INVALID; - m_previousTaskInfo = DozerTaskInfo(); + Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID); + if (target && !target->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) + newTask(m_previousTask, target); } + + m_previousTask = DOZER_TASK_INVALID; + m_previousTaskInfo = DozerTaskInfo(); } //------------------------------------------------------------------------------------------------- @@ -798,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;