Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Generals/Code/GameEngine/Include/Common/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,11 @@ 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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The EA comment can be expanded that if rememberTask is set that it will resume the task when enabled again.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it need to be virtual function? If it is only called internally in the implementation, then it can be implementation local. Same for the other Task functions here.


// internal methods to manage behavior from within the dozer state machine
virtual void internalTaskComplete( DozerTask task ) = 0; ///< set a dozer task as successfully completed
Expand Down Expand Up @@ -211,6 +213,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
Expand Down Expand Up @@ -240,9 +243,11 @@ 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
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -154,9 +155,11 @@ 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
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
Expand Down
4 changes: 4 additions & 0 deletions Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Comment thread
xezon marked this conversation as resolved.

// clear the order
internalCancelTask( task );
Expand All @@ -2061,20 +2063,51 @@ void DozerAIUpdate::cancelAllTasks()
for (UnsignedInt task = DOZER_TASK_FIRST; task < DOZER_NUM_TASKS; ++task)
internalCancelTask((DozerTask)task);

clearPreviousTask();

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);
}
else if (m_previousTask == DOZER_TASK_REPAIR || m_previousTask == DOZER_TASK_FORTIFY)
{
Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID);
if (target)
newTask(m_previousTask, target);
}

clearPreviousTask();
}

void DozerAIUpdate::clearPreviousTask()
{
m_previousTask = DOZER_TASK_INVALID;
m_previousTaskInfo = DozerTaskInfo();
}

//-------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -2133,8 +2166,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++ )
Expand All @@ -2158,9 +2190,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;
Expand Down Expand Up @@ -2297,6 +2326,32 @@ 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 rememberTask = getObject()->isDisabledByType(DISABLED_EMP) ||
getObject()->isDisabledByType(DISABLED_HACKED) ||
getObject()->isDisabledByType(DISABLED_SUBDUED) ||
getObject()->isDisabledByType(DISABLED_UNDERPOWERED);

cancelTask(getCurrentTask(), rememberTask);
}
}
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 */
//-------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -2511,7 +2566,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));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand All @@ -701,20 +703,51 @@ void WorkerAIUpdate::cancelAllTasks()
for (UnsignedInt task = DOZER_TASK_FIRST; task < DOZER_NUM_TASKS; ++task)
internalCancelTask((DozerTask)task);

clearPreviousTask();

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);
}
else if (m_previousTask == DOZER_TASK_REPAIR || m_previousTask == DOZER_TASK_FORTIFY)
{
Object* target = TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID);
if (target)
newTask(m_previousTask, target);
}

clearPreviousTask();
}

void WorkerAIUpdate::clearPreviousTask()
{
m_previousTask = DOZER_TASK_INVALID;
m_previousTaskInfo = DozerTaskInfo();
}

//-------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -773,8 +806,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++ )
Expand All @@ -798,9 +830,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;
Expand Down Expand Up @@ -925,6 +954,32 @@ 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 rememberTask = getObject()->isDisabledByType(DISABLED_EMP) ||
getObject()->isDisabledByType(DISABLED_HACKED) ||
getObject()->isDisabledByType(DISABLED_SUBDUED) ||
getObject()->isDisabledByType(DISABLED_UNDERPOWERED);

cancelTask(getCurrentTask(), rememberTask);
}
}
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 */
//-------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -1463,7 +1518,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));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,11 @@ 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
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
Expand Down Expand Up @@ -211,6 +213,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
Expand Down Expand Up @@ -240,9 +243,11 @@ 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
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -157,9 +158,11 @@ 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
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
Expand Down
Loading
Loading