Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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,8 @@ 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. Can remember the cancelled task for resumption.
virtual void cancelAllTasks() = 0; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it
virtual void resumePreviousTask() = 0; ///< resume the previous task if there was one

// 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 +210,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 +240,8 @@ 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 resumePreviousTask() override; ///< resume the previous task if there was one

// 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 Expand Up @@ -278,6 +277,10 @@ class DozerAIUpdate : public AIUpdateInterface, public DozerAIInterface
virtual void privateRepair( Object *obj, CommandSourceType cmdSource ) override; ///< repair the target
virtual void privateResumeConstruction( Object *obj, CommandSourceType cmdSource ) override; ///< resume construction on obj

virtual void setPreviousTask(DozerTask task); ///< set the previous task
virtual void resumePreviousTask(); ///< resume the previous task if there was one
virtual void clearPreviousTask(); ///< clear the previous task

struct DozerTaskInfo
{
DozerTaskInfo()
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,8 @@ 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. Can remember the cancelled task for resumption.
virtual void cancelAllTasks() override; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it
virtual void resumePreviousTask() override; ///< resume the previous task if there was one

// 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 Expand Up @@ -264,6 +264,10 @@ class WorkerAIUpdate : public AIUpdateInterface, public DozerAIInterface, public
virtual void privateDock( Object *obj, CommandSourceType cmdSource ) override;
virtual void privateIdle(CommandSourceType cmdSource) override; ///< Enter idle state.

virtual void setPreviousTask(DozerTask task); ///< set the previous task
virtual void resumePreviousTask(); ///< resume the previous task if there was one
virtual void clearPreviousTask(); ///< clear the previous task

private:

void createMachines(); ///< create our behavior machines we need
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,8 @@ 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. Can remember the cancelled task for resumption.
virtual void cancelAllTasks() = 0; ///< cancel all tasks from the queue, if it's the current task the dozer will stop working on it
virtual void resumePreviousTask() = 0; ///< resume the previous task if there was one

// 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 +210,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 +240,8 @@ 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 resumePreviousTask() override; ///< resume the previous task if there was one

// 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 Expand Up @@ -278,6 +277,10 @@ class DozerAIUpdate : public AIUpdateInterface, public DozerAIInterface
virtual void privateRepair( Object *obj, CommandSourceType cmdSource ) override; ///< repair the target
virtual void privateResumeConstruction( Object *obj, CommandSourceType cmdSource ) override; ///< resume construction on obj

virtual void setPreviousTask(DozerTask task); ///< set the previous task
virtual void resumePreviousTask(); ///< resume the previous task if there was one
virtual void clearPreviousTask(); ///< clear the previous task

struct DozerTaskInfo
{
DozerTaskInfo()
Expand Down
Loading
Loading