Skip to content
Merged
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
16 changes: 11 additions & 5 deletions GeneralsMD/Code/GameEngine/Include/GameLogic/Module/AIUpdate.h
Original file line number Diff line number Diff line change
Expand Up @@ -314,11 +314,11 @@ class AIUpdateInterface : public UpdateModule, public AICommandInterface

virtual AIUpdateInterface* getAIUpdateInterface() { return this; }

// Disabled conditions to process (AI will still process held status)
//virtual DisabledMaskType getDisabledTypesToProcess() const { return MAKE_DISABLED_MASK( DISABLED_HELD ); }

// We need to process all disabled types to allow Locomotor working while disabled
virtual DisabledMaskType getDisabledTypesToProcess() const { return DISABLEDMASK_ALL; }
// Disabled conditions to process. By default the AI only processes HELD (so a disabled
// unit's AI fully freezes, as it always did). We additionally process all disabled types
// only when the current locomotor must keep working while disabled, so it can maintain
// position. (Implemented in the .cpp because it needs the full Locomotor definition.)
virtual DisabledMaskType getDisabledTypesToProcess() const;

// Some very specific, complex behaviors are used by more than one AIUpdate. Here are their interfaces.
virtual DozerAIInterface* getDozerAIInterface() {return nullptr;}
Expand Down Expand Up @@ -649,6 +649,12 @@ class AIUpdateInterface : public UpdateModule, public AICommandInterface
virtual UpdateSleepTime doLocomotor(); // virtual so subclasses can override
virtual void chooseGoodLocomotorFromCurrentSet();

// True when a disable type should suspend AI logic. We still run while disabled
// (DISABLEDMASK_ALL) so the locomotor can maintain position, but all other AI logic
// (state machine, attacking, pathfinding, economy) must be frozen. HELD never suspends,
// and death is handled separately by the normal update path.
Bool isAiSuspendedByDisable() const;

void setLastCommandSource(CommandSourceType source);

// subclasses may want to override this, to use a subclass of AIStateMachine.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1154,6 +1154,16 @@ UpdateSleepTime AIUpdateInterface::update( void )

m_isInUpdate = TRUE;

// While disabled (other than HELD/dead), suspend all AI logic and only let the locomotor
// run, so locos flagged LocomotorWorksWhenDisabled can maintain position. This restores the
// pre-DISABLEDMASK_ALL behavior where a disabled AI module's update() was not called at all.
if (isAiSuspendedByDisable())
{
doLocomotor(); // self-gates: does nothing unless the loco works while disabled / maintains position
m_isInUpdate = FALSE;
return UPDATE_SLEEP_NONE; // poll each frame so we resume full AI when the disable clears
}

m_completedWaypoint = nullptr; // Reset so state machine update can set it if we just completed the path.

// assume we can sleep forever, unless the state machine (or turret, etc) demand otherwise
Expand Down Expand Up @@ -2263,6 +2273,30 @@ Bool AIUpdateInterface::isValidLocomotorPosition(const Coord3D* pos) const
return TheAI->pathfinder()->validMovementPosition( getObject()->getCrusherLevel()>0, getObject()->getLayer(), m_locomotorSet, getObject()->getRequiredBridgeHeight(), pos );
}

//-------------------------------------------------------------------------------------------------
DisabledMaskType AIUpdateInterface::getDisabledTypesToProcess() const
{
// Only keep ticking while disabled if the current locomotor must keep working while
// disabled (e.g. to maintain position). Otherwise process HELD only, so the AI fully
// freezes when disabled - matching the original behavior. Note that when no locomotor is
// chosen (buildings and other units that never move) we also freeze; the rare mobile unit
// flagged LocomotorWorksWhenDisabled will have already selected a locomotor before it can
// be disabled in flight.
if (m_curLocomotor != NULL && m_curLocomotor->getLocomotorWorksWhenDisabled())
return DISABLEDMASK_ALL;

return MAKE_DISABLED_MASK( DISABLED_HELD );
}

//-------------------------------------------------------------------------------------------------
Bool AIUpdateInterface::isAiSuspendedByDisable() const
{
const Object* obj = getObject();
return obj->isDisabled()
&& !obj->isDisabledByType(DISABLED_HELD)
&& !obj->isEffectivelyDead();
}

//-------------------------------------------------------------------------------------------------
DECLARE_PERF_TIMER(doLocomotor)
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ UpdateSleepTime AssaultTransportAIUpdate::update( void )
//return UPDATE_SLEEP_FOREVER;
}

// Suspend assault coordination while disabled; only the locomotor runs.
if (isAiSuspendedByDisable())
return AIUpdateInterface::update();

//First removing dead members or members that have been ordered to do something outside of this AI.
if( m_currentMembers )
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ CarrierDroneAIUpdate::~CarrierDroneAIUpdate(void)
//-------------------------------------------------------------------------------------------------
UpdateSleepTime CarrierDroneAIUpdate::update()
{
// Suspend carrier-drone AI while disabled; only the locomotor runs.
if (isAiSuspendedByDisable())
return AIUpdateInterface::update();

Object* obj = getObject();
const CarrierDroneAIUpdateModuleData* data = getCarrierDroneAIUpdateModuleData();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,11 @@ Bool DeliverPayloadAIUpdate::isAllowedToRespondToAiCommands(const AICommandParms
//-------------------------------------------------------------------------------------------------
UpdateSleepTime DeliverPayloadAIUpdate::update( void )
{
// While disabled (e.g. DelayDeliveryFrames hold), suspend delivery logic so the
// approach/deliver state machine does not advance while we are frozen in place.
if (isAiSuspendedByDisable())
return AIUpdateInterface::update();

m_deliveryDecal.update();

if(!(isAiInDeadState()) && m_deliverPayloadStateMachine)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ void DeployStyleAIUpdate::aiDoCommand( const AICommandParms* parms )
//-------------------------------------------------------------------------------------------------
UpdateSleepTime DeployStyleAIUpdate::update( void )
{
// Suspend deploy/undeploy timers while disabled; only the locomotor runs.
if (isAiSuspendedByDisable())
return AIUpdateInterface::update();

// have to call our parent's isIdle, because we override it to never return true
// when we have a pending command...
Object *self = getObject();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1561,6 +1561,9 @@ void DozerAIUpdate::removeBridgeScaffolding( Object *bridgeTower )
//-------------------------------------------------------------------------------------------------
UpdateSleepTime DozerAIUpdate::update( void )
{
// Suspend dozer tasks (build/repair) while disabled; only the locomotor runs.
if (isAiSuspendedByDisable())
return AIUpdateInterface::update();

//
// NOTE: Any changes to DozerAIUpdate::* you probably want to reflect and copy into
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,10 @@ void DroneCarrierAIUpdate::aiDoCommand(const AICommandParms* parms)

UpdateSleepTime DroneCarrierAIUpdate::update()
{
// Suspend drone-carrier management while disabled; only the locomotor runs.
if (isAiSuspendedByDisable())
return AIUpdateInterface::update();

if (!getObject()->isEffectivelyDead()) {
const DroneCarrierAIUpdateModuleData* data = getDroneCarrierAIUpdateModuleData();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ Bool HackInternetAIUpdate::isHackingPackingOrUnpacking() const
//-------------------------------------------------------------------------------------------------
UpdateSleepTime HackInternetAIUpdate::update( void )
{
// Suspend hacking (and pending-command handling) while disabled; only the locomotor runs.
if (isAiSuspendedByDisable())
return AIUpdateInterface::update();

// have to call our parent's isIdle, because we override it to never return true
// when we have a pending command...
if( AIUpdateInterface::isIdle() )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2433,6 +2433,10 @@ void JetAIUpdate::getProducerLocation()
//-------------------------------------------------------------------------------------------------
UpdateSleepTime JetAIUpdate::update()
{
// Suspend jet AI (taxi/takeoff/landing/ammo logic) while disabled; only the locomotor runs.
if (isAiSuspendedByDisable())
return AIUpdateInterface::update();

const JetAIUpdateModuleData* d = getJetAIUpdateModuleData();

getProducerLocation();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ void POWTruckAIUpdate::aiDoCommand( const AICommandParms *parms )
//-------------------------------------------------------------------------------------------------
UpdateSleepTime POWTruckAIUpdate::update( void )
{
// Suspend POW collection tasks while disabled; only the locomotor runs.
if (isAiSuspendedByDisable())
return AIUpdateInterface::update();

// we are ultra accurate
if( getCurLocomotor() )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,10 @@ UpdateSleepTime RailedTransportAIUpdate::update( void )
{
Object *us = getObject();

// Suspend railed-transport pathing while disabled; only the locomotor runs.
if (isAiSuspendedByDisable())
return AIUpdateInterface::update();

// load the waypoint data if not loaded
if( m_waypointDataLoaded == FALSE )
loadWaypointData();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ SupplyTruckAIUpdate::~SupplyTruckAIUpdate( void )
//-------------------------------------------------------------------------------------------------
UpdateSleepTime SupplyTruckAIUpdate::update( void )
{
// Suspend supply ferrying while disabled (e.g. EMP/hacked); only the locomotor runs.
if (isAiSuspendedByDisable())
return AIUpdateInterface::update();

StateReturnType stRet = m_supplyTruckStateMachine->updateStateMachine();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ WanderAIUpdate::~WanderAIUpdate( void )
//-------------------------------------------------------------------------------------------------
UpdateSleepTime WanderAIUpdate::update( void )
{
// Suspend wandering while disabled; only the locomotor runs.
if (isAiSuspendedByDisable())
return AIUpdateInterface::update();

// If I'm standing still, move somewhere
if (isIdle())
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,9 @@ Real WorkerAIUpdate::getWarehouseScanDistance() const
//-------------------------------------------------------------------------------------------------
UpdateSleepTime WorkerAIUpdate::update( void )
{
// Suspend worker tasks (build/repair/supply) while disabled; only the locomotor runs.
if (isAiSuspendedByDisable())
return AIUpdateInterface::update();

//
// NOTE: Any changes to DozerAIUpdate::* you probably want to reflect and copy into
Expand Down
Loading