diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h index 1488eecb0d..b41311bd72 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h @@ -140,6 +140,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 resumePreviousTask(void) = 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 @@ -239,6 +240,7 @@ class DozerAIUpdate : public AIUpdateInterface, public DozerAIInterface // task actions virtual void newTask( DozerTask task, Object *target ); ///< set a desire to do the requrested task virtual void cancelTask( DozerTask task ); ///< cancel this task from the queue, if it's the current task the dozer will stop working on it + virtual void resumePreviousTask(void); ///< resume the previous task if there was one // internal methods to manage behavior from within the dozer state machine virtual void internalTaskComplete( DozerTask task ); ///< set a dozer task as successfully completed @@ -282,6 +284,8 @@ class DozerAIUpdate : public AIUpdateInterface, public DozerAIInterface DozerPrimaryStateMachine *m_dozerMachine; ///< the custom state machine for Dozer behavior DozerTask m_currentTask; ///< current task the dozer is attending to (if any) + DozerTask m_previousTask; ///< previous task the dozer was attending to (if any) + DozerTaskInfo m_previousTaskInfo; ///< info on the previous task the dozer was attending to (if any) AudioEventRTS m_buildingSound; ///< sound is pulled from the object we are building! Bool m_isRebuild; ///< is this a rebuild of a previous building? diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h index a124c77aff..cc8726d970 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h @@ -155,6 +155,7 @@ class WorkerAIUpdate : public AIUpdateInterface, public DozerAIInterface, public // task actions virtual void newTask( DozerTask task, Object* target ); ///< set a desire to do the requrested task virtual void cancelTask( DozerTask task ); ///< cancel this task from the queue, if it's the current task the dozer will stop working on it + virtual void resumePreviousTask(void); ///< resume the previous task if there was one // internal methods to manage behavior from within the dozer state machine virtual void internalTaskComplete( DozerTask task ); ///< set a dozer task as successfully completed @@ -218,6 +219,8 @@ class WorkerAIUpdate : public AIUpdateInterface, public DozerAIInterface, public DozerTask m_currentTask; ///< current task the dozer is attending to (if any) + DozerTask m_previousTask; ///< previous task the dozer was attending to (if any) + DozerTaskInfo m_previousTaskInfo; ///< info on the previous task the dozer was attending to (if any) // // the following info array can be used if we want to have more complicated approaches 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 d5371bd9a3..64e3c5b2bf 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2037,6 +2037,15 @@ void DozerAIUpdate::cancelTask( DozerTask task ) } +//------------------------------------------------------------------------------------------------- +/** Attempt to resume the previous task */ +//------------------------------------------------------------------------------------------------- +void DozerAIUpdate::resumePreviousTask(void) +{ + if (m_previousTask != DOZER_TASK_INVALID) + newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); +} + //------------------------------------------------------------------------------------------------- /** Is there a given task waiting to be done */ //------------------------------------------------------------------------------------------------- @@ -2115,6 +2124,9 @@ 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; @@ -2438,7 +2450,11 @@ void DozerAIUpdate::crc( Xfer *xfer ) void DozerAIUpdate::xfer( Xfer *xfer ) { // version - XferVersion currentVersion = 1; +#if RETAIL_COMPATIBLE_XFER_SAVE + XferVersion currentVersion = 1; +#else + XferVersion currentVersion = 2; +#endif XferVersion version = currentVersion; xfer->xferVersion( &version, currentVersion ); @@ -2459,6 +2475,12 @@ void DozerAIUpdate::xfer( Xfer *xfer ) xfer->xferSnapshot(m_dozerMachine); xfer->xferUser(&m_currentTask, sizeof(m_currentTask)); + if (currentVersion >= 2) + { + xfer->xferUser(&m_previousTask, sizeof(m_previousTask)); + xfer->xferUser(&m_previousTaskInfo, sizeof(m_previousTaskInfo)); + } + Int dockPoints = DOZER_NUM_DOCK_POINTS; xfer->xferInt(&dockPoints); if (dockPoints!=DOZER_NUM_DOCK_POINTS) { 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 7b2dfd9eec..c6d723dfa8 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -695,6 +695,15 @@ void WorkerAIUpdate::cancelTask( DozerTask task ) } +//------------------------------------------------------------------------------------------------- +/** Attempt to resume the previous task */ +//------------------------------------------------------------------------------------------------- +void WorkerAIUpdate::resumePreviousTask(void) +{ + if (m_previousTask != DOZER_TASK_INVALID) + newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); +} + //------------------------------------------------------------------------------------------------- /** Is there a given task waiting to be done */ //------------------------------------------------------------------------------------------------- @@ -773,6 +782,9 @@ 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; @@ -1405,7 +1417,11 @@ void WorkerAIUpdate::crc( Xfer *xfer ) // ------------------------------------------------------------------------------------------------ void WorkerAIUpdate::xfer( Xfer *xfer ) { - XferVersion currentVersion = 1; +#if RETAIL_COMPATIBLE_XFER_SAVE + XferVersion currentVersion = 1; +#else + XferVersion currentVersion = 2; +#endif XferVersion version = currentVersion; xfer->xferVersion( &version, currentVersion ); @@ -1429,6 +1445,12 @@ void WorkerAIUpdate::xfer( Xfer *xfer ) xfer->xferSnapshot(m_dozerMachine); xfer->xferUser(&m_currentTask, sizeof(m_currentTask)); + if (currentVersion >= 2) + { + xfer->xferUser(&m_previousTask, sizeof(m_previousTask)); + xfer->xferUser(&m_previousTaskInfo, sizeof(m_previousTaskInfo)); + } + Int dockPoints = DOZER_NUM_DOCK_POINTS; xfer->xferInt(&dockPoints); if (dockPoints!=DOZER_NUM_DOCK_POINTS) { diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h index 2d5d4bd399..bb3c891930 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DozerAIUpdate.h @@ -140,6 +140,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 resumePreviousTask(void) = 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 @@ -239,6 +240,7 @@ class DozerAIUpdate : public AIUpdateInterface, public DozerAIInterface // task actions virtual void newTask( DozerTask task, Object *target ); ///< set a desire to do the requrested task virtual void cancelTask( DozerTask task ); ///< cancel this task from the queue, if it's the current task the dozer will stop working on it + virtual void resumePreviousTask(void); ///< resume the previous task if there was one // internal methods to manage behavior from within the dozer state machine virtual void internalTaskComplete( DozerTask task ); ///< set a dozer task as successfully completed @@ -282,6 +284,8 @@ class DozerAIUpdate : public AIUpdateInterface, public DozerAIInterface DozerPrimaryStateMachine *m_dozerMachine; ///< the custom state machine for Dozer behavior DozerTask m_currentTask; ///< current task the dozer is attending to (if any) + DozerTask m_previousTask; ///< previous task the dozer was attending to (if any) + DozerTaskInfo m_previousTaskInfo; ///< info on the previous task the dozer was attending to (if any) AudioEventRTS m_buildingSound; ///< sound is pulled from the object we are building! Bool m_isRebuild; ///< is this a rebuild of a previous building? diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h index afc308ccf6..099638a89e 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/WorkerAIUpdate.h @@ -158,6 +158,7 @@ class WorkerAIUpdate : public AIUpdateInterface, public DozerAIInterface, public // task actions virtual void newTask( DozerTask task, Object* target ); ///< set a desire to do the requrested task virtual void cancelTask( DozerTask task ); ///< cancel this task from the queue, if it's the current task the dozer will stop working on it + virtual void resumePreviousTask(void); ///< resume the previous task if there was one // internal methods to manage behavior from within the dozer state machine virtual void internalTaskComplete( DozerTask task ); ///< set a dozer task as successfully completed @@ -223,6 +224,8 @@ class WorkerAIUpdate : public AIUpdateInterface, public DozerAIInterface, public DozerTask m_currentTask; ///< current task the dozer is attending to (if any) + DozerTask m_previousTask; ///< previous task the dozer was attending to (if any) + DozerTaskInfo m_previousTaskInfo; ///< info on the previous task the dozer was attending to (if any) // // the following info array can be used if we want to have more complicated approaches diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp index df4f4c66a2..fede2ffa04 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -3809,11 +3809,20 @@ void Object::onDisabledEdge(Bool becomingDisabled) (*module)->onDisabledEdge( becomingDisabled ); DozerAIInterface *dozerAI = getAI() ? getAI()->getDozerAIInterface() : NULL; - if( becomingDisabled && dozerAI ) + if (dozerAI) { - // 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 ) - dozerAI->cancelTask( dozerAI->getCurrentTask() ); + 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) + dozerAI->cancelTask(dozerAI->getCurrentTask()); + } + else + { +#if !RETAIL_COMPATIBLE_CRC + dozerAI->resumePreviousTask(); +#endif + } } Player* controller = getControllingPlayer(); 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 ea9d64c9a2..f9a0be58b4 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DozerAIUpdate.cpp @@ -2042,6 +2042,15 @@ void DozerAIUpdate::cancelTask( DozerTask task ) } +//------------------------------------------------------------------------------------------------- +/** Attempt to resume the previous task */ +//------------------------------------------------------------------------------------------------- +void DozerAIUpdate::resumePreviousTask(void) +{ + if (m_previousTask != DOZER_TASK_INVALID) + newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); +} + //------------------------------------------------------------------------------------------------- /** Is there a given task waiting to be done */ //------------------------------------------------------------------------------------------------- @@ -2120,6 +2129,9 @@ 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; @@ -2450,7 +2462,11 @@ void DozerAIUpdate::crc( Xfer *xfer ) void DozerAIUpdate::xfer( Xfer *xfer ) { // version - XferVersion currentVersion = 1; +#if RETAIL_COMPATIBLE_XFER_SAVE + XferVersion currentVersion = 1; +#else + XferVersion currentVersion = 2; +#endif XferVersion version = currentVersion; xfer->xferVersion( &version, currentVersion ); @@ -2471,6 +2487,12 @@ void DozerAIUpdate::xfer( Xfer *xfer ) xfer->xferSnapshot(m_dozerMachine); xfer->xferUser(&m_currentTask, sizeof(m_currentTask)); + if (currentVersion >= 2) + { + xfer->xferUser(&m_previousTask, sizeof(m_previousTask)); + xfer->xferUser(&m_previousTaskInfo, sizeof(m_previousTaskInfo)); + } + Int dockPoints = DOZER_NUM_DOCK_POINTS; xfer->xferInt(&dockPoints); if (dockPoints!=DOZER_NUM_DOCK_POINTS) { 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 a3bdd0628a..13ca49327c 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/WorkerAIUpdate.cpp @@ -695,6 +695,15 @@ void WorkerAIUpdate::cancelTask( DozerTask task ) } +//------------------------------------------------------------------------------------------------- +/** Attempt to resume the previous task */ +//------------------------------------------------------------------------------------------------- +void WorkerAIUpdate::resumePreviousTask(void) +{ + if (m_previousTask != DOZER_TASK_INVALID) + newTask(m_previousTask, TheGameLogic->findObjectByID(m_previousTaskInfo.m_targetObjectID)); +} + //------------------------------------------------------------------------------------------------- /** Is there a given task waiting to be done */ //------------------------------------------------------------------------------------------------- @@ -773,6 +782,9 @@ 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; @@ -1415,7 +1427,11 @@ void WorkerAIUpdate::crc( Xfer *xfer ) // ------------------------------------------------------------------------------------------------ void WorkerAIUpdate::xfer( Xfer *xfer ) { - XferVersion currentVersion = 1; +#if RETAIL_COMPATIBLE_XFER_SAVE + XferVersion currentVersion = 1; +#else + XferVersion currentVersion = 2; +#endif XferVersion version = currentVersion; xfer->xferVersion( &version, currentVersion ); @@ -1439,6 +1455,12 @@ void WorkerAIUpdate::xfer( Xfer *xfer ) xfer->xferSnapshot(m_dozerMachine); xfer->xferUser(&m_currentTask, sizeof(m_currentTask)); + if (currentVersion >= 2) + { + xfer->xferUser(&m_previousTask, sizeof(m_previousTask)); + xfer->xferUser(&m_previousTaskInfo, sizeof(m_previousTaskInfo)); + } + Int dockPoints = DOZER_NUM_DOCK_POINTS; xfer->xferInt(&dockPoints); if (dockPoints!=DOZER_NUM_DOCK_POINTS) {