2008-09-15 01:07:45 -05:00
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
# include "cbase.h"
# include "ai_behavior_functank.h"
# include "ai_navigator.h"
# include "ai_memory.h"
# include "ai_senses.h"
// memdbgon must be the last include file in a .cpp file!!!
# include "tier0/memdbgon.h"
// How long to fire a func tank before running schedule selection again.
# define FUNCTANK_FIRE_TIME 5.0f
BEGIN_DATADESC ( CAI_FuncTankBehavior )
DEFINE_FIELD ( m_hFuncTank , FIELD_EHANDLE ) ,
DEFINE_FIELD ( m_bMounted , FIELD_BOOLEAN ) ,
DEFINE_FIELD ( m_flBusyTime , FIELD_TIME ) ,
DEFINE_FIELD ( m_bSpottedPlayerOutOfCover , FIELD_BOOLEAN ) ,
END_DATADESC ( ) ;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//--k---------------------------------------------------------------------------
CAI_FuncTankBehavior : : CAI_FuncTankBehavior ( )
{
m_hFuncTank = NULL ;
m_bMounted = false ;
m_flBusyTime = 0.0f ;
m_bSpottedPlayerOutOfCover = false ;
}
//-----------------------------------------------------------------------------
// Purpose: Deconstructor
//-----------------------------------------------------------------------------
CAI_FuncTankBehavior : : ~ CAI_FuncTankBehavior ( )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CAI_FuncTankBehavior : : CanSelectSchedule ( )
{
// If we don't have a func_tank do not bother with conditions, schedules, etc.
if ( ! m_hFuncTank )
return false ;
// Are you alive, in a script?
if ( ! GetOuter ( ) - > IsInterruptable ( ) )
return false ;
// Commander is giving you orders?
if ( GetOuter ( ) - > HasCondition ( COND_RECEIVED_ORDERS ) )
return false ;
return true ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAI_FuncTankBehavior : : BeginScheduleSelection ( )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAI_FuncTankBehavior : : EndScheduleSelection ( )
{
if ( m_bMounted )
{
Dismount ( ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAI_FuncTankBehavior : : PrescheduleThink ( )
{
BaseClass : : PrescheduleThink ( ) ;
if ( ! HasCondition ( COND_SEE_PLAYER ) )
{
m_bSpottedPlayerOutOfCover = false ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CAI_FuncTankBehavior : : SelectSchedule ( )
{
// This shouldn't get called with an m_hFuncTank, see CanSelectSchedule.
Assert ( m_hFuncTank ) ;
// If we've been told to dismount, or we are out of ammo - dismount.
if ( HasCondition ( COND_FUNCTANK_DISMOUNT ) | | m_hFuncTank - > GetAmmoCount ( ) = = 0 )
{
if ( m_bMounted )
{
Dismount ( ) ;
}
return BaseClass : : SelectSchedule ( ) ;
}
// If we are not mounted to a func_tank look for one.
if ( ! IsMounted ( ) )
{
return SCHED_MOVE_TO_FUNCTANK ;
}
// If we have an enemy, it's in the viewcone & we have LOS to it
if ( GetEnemy ( ) )
{
// Tell the func tank whenever we see the player for the first time since not seeing him for a while
if ( HasCondition ( COND_NEW_ENEMY ) & & GetEnemy ( ) - > IsPlayer ( ) & & ! m_bSpottedPlayerOutOfCover )
{
m_bSpottedPlayerOutOfCover = true ;
m_hFuncTank - > NPC_JustSawPlayer ( GetEnemy ( ) ) ;
}
// Fire at the enemy.
return SCHED_FIRE_FUNCTANK ;
}
else
{
// Scan for enemies.
return SCHED_SCAN_WITH_FUNCTANK ;
}
return SCHED_IDLE_STAND ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : activity -
// Output : Activity
//-----------------------------------------------------------------------------
Activity CAI_FuncTankBehavior : : NPC_TranslateActivity ( Activity activity )
{
// If I'm on the gun, I play the idle manned gun animation
if ( m_bMounted )
return ACT_IDLE_MANNEDGUN ;
return BaseClass : : NPC_TranslateActivity ( activity ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAI_FuncTankBehavior : : Dismount ( void )
{
SetBusy ( gpGlobals - > curtime + AI_FUNCTANK_BEHAVIOR_BUSYTIME ) ;
Assert ( m_hFuncTank ) ;
if ( m_hFuncTank )
{
GetOuter ( ) - > SpeakSentence ( FUNCTANK_SENTENCE_DISMOUNTING ) ;
Assert ( m_hFuncTank - > IsMarkedForDeletion ( ) | | m_hFuncTank - > GetController ( ) = = GetOuter ( ) ) ;
m_hFuncTank - > NPC_SetInRoute ( false ) ;
if ( m_hFuncTank - > GetController ( ) = = GetOuter ( ) )
m_hFuncTank - > StopControl ( ) ;
SetFuncTank ( NULL ) ;
}
GetOuter ( ) - > SetDesiredWeaponState ( DESIREDWEAPONSTATE_UNHOLSTERED ) ;
m_bMounted = false ;
// Set this condition to force breakout of any func_tank behavior schedules
SetCondition ( COND_FUNCTANK_DISMOUNT ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
int CAI_FuncTankBehavior : : OnTakeDamage_Alive ( const CTakeDamageInfo & info )
{
int iResult = BaseClass : : OnTakeDamage_Alive ( info ) ;
if ( ! iResult )
return 0 ;
// If we've been hit by the player, and the player's not targetable
// by our func_tank, get off the tank.
CBaseEntity * pAttacker = info . GetAttacker ( ) ;
bool bValidDismountAttacker = ( pAttacker & & pAttacker - > IsPlayer ( ) ) ;
# ifdef HL2_EPISODIC
bValidDismountAttacker = true ;
# endif
if ( m_hFuncTank & & bValidDismountAttacker = = true )
{
if ( ! m_hFuncTank - > IsEntityInViewCone ( pAttacker ) )
{
SetCondition ( COND_FUNCTANK_DISMOUNT ) ;
}
}
return iResult ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAI_FuncTankBehavior : : StartTask ( const Task_t * pTask )
{
switch ( pTask - > iTask )
{
case TASK_FUNCTANK_ANNOUNCE_SCAN :
{
if ( random - > RandomInt ( 0 , 3 ) = = 0 )
{
GetOuter ( ) - > SpeakSentence ( FUNCTANK_SENTENCE_SCAN_FOR_ENEMIES ) ;
}
TaskComplete ( ) ;
}
break ;
case TASK_GET_PATH_TO_FUNCTANK :
{
if ( ! m_hFuncTank )
{
TaskFail ( FAIL_NO_TARGET ) ;
return ;
}
Vector vecManPos ;
m_hFuncTank - > NPC_FindManPoint ( vecManPos ) ;
AI_NavGoal_t goal ( vecManPos ) ;
goal . pTarget = m_hFuncTank ;
if ( GetNavigator ( ) - > SetGoal ( goal ) )
{
GetNavigator ( ) - > SetArrivalDirection ( m_hFuncTank - > GetAbsAngles ( ) ) ;
TaskComplete ( ) ;
}
else
{
TaskFail ( " NO PATH " ) ;
// Don't try and use me again for a while
SetBusy ( gpGlobals - > curtime + AI_FUNCTANK_BEHAVIOR_BUSYTIME ) ;
}
break ;
}
case TASK_FACE_FUNCTANK :
{
if ( ! m_hFuncTank )
{
TaskFail ( FAIL_NO_TARGET ) ;
return ;
}
// Ensure we've reached the func_tank
Vector vecManPos ;
m_hFuncTank - > NPC_FindManPoint ( vecManPos ) ;
// More leniency in Z.
Vector vecDelta = ( vecManPos - GetAbsOrigin ( ) ) ;
if ( fabs ( vecDelta . x ) > 16 | | fabs ( vecDelta . y ) > 16 | | fabs ( vecDelta . z ) > 48 )
{
TaskFail ( " Not correctly on func_tank man point " ) ;
m_hFuncTank - > NPC_InterruptRoute ( ) ;
return ;
}
GetMotor ( ) - > SetIdealYawToTarget ( m_hFuncTank - > GetAbsOrigin ( ) ) ;
GetOuter ( ) - > SetTurnActivity ( ) ;
break ;
}
case TASK_HOLSTER_WEAPON :
{
if ( ! m_hFuncTank )
{
TaskFail ( FAIL_NO_TARGET ) ;
return ;
}
if ( GetOuter ( ) - > IsWeaponHolstered ( ) | | ! GetOuter ( ) - > CanHolsterWeapon ( ) )
{
GetOuter ( ) - > SpeakSentence ( FUNCTANK_SENTENCE_JUST_MOUNTED ) ;
// We are at the correct position and facing for the func_tank, mount it.
m_hFuncTank - > StartControl ( GetOuter ( ) ) ;
GetOuter ( ) - > ClearEnemyMemory ( ) ;
m_bMounted = true ;
TaskComplete ( ) ;
GetOuter ( ) - > SetIdealActivity ( ACT_IDLE_MANNEDGUN ) ;
}
else
{
GetOuter ( ) - > SetDesiredWeaponState ( DESIREDWEAPONSTATE_HOLSTERED ) ;
}
break ;
}
case TASK_FIRE_FUNCTANK :
{
if ( ! m_hFuncTank )
{
TaskFail ( FAIL_NO_TARGET ) ;
return ;
}
GetOuter ( ) - > m_flWaitFinished = gpGlobals - > curtime + FUNCTANK_FIRE_TIME ;
break ;
}
case TASK_SCAN_LEFT_FUNCTANK :
{
if ( ! m_hFuncTank )
{
TaskFail ( FAIL_NO_TARGET ) ;
return ;
}
GetMotor ( ) - > SetIdealYawToTarget ( m_hFuncTank - > GetAbsOrigin ( ) ) ;
float flCenterYaw = m_hFuncTank - > YawCenterWorld ( ) ;
float flYawRange = m_hFuncTank - > YawRange ( ) ;
float flScanAmount = random - > RandomFloat ( 0 , flYawRange ) ;
QAngle vecTargetAngles ( 0 , UTIL_AngleMod ( flCenterYaw + flScanAmount ) , 0 ) ;
/*
float flCenterPitch = m_hFuncTank - > YawCenterWorld ( ) ;
float flPitchRange = m_hFuncTank - > PitchRange ( ) ;
float flPitch = random - > RandomFloat ( - flPitchRange , flPitchRange ) ;
QAngle vecTargetAngles ( flCenterPitch + flPitch , UTIL_AngleMod ( flCenterYaw + flScanAmount ) , 0 ) ;
*/
Vector vecTargetForward ;
AngleVectors ( vecTargetAngles , & vecTargetForward ) ;
Vector vecTarget = GetOuter ( ) - > EyePosition ( ) + ( vecTargetForward * 256 ) ;
GetOuter ( ) - > AddLookTarget ( vecTarget , 1.0 , 2.0 , 0.2 ) ;
m_hFuncTank - > NPC_SetIdleAngle ( vecTarget ) ;
break ;
}
case TASK_SCAN_RIGHT_FUNCTANK :
{
if ( ! m_hFuncTank )
{
TaskFail ( FAIL_NO_TARGET ) ;
return ;
}
GetMotor ( ) - > SetIdealYawToTarget ( m_hFuncTank - > GetAbsOrigin ( ) ) ;
float flCenterYaw = m_hFuncTank - > YawCenterWorld ( ) ;
float flYawRange = m_hFuncTank - > YawRange ( ) ;
float flScanAmount = random - > RandomFloat ( 0 , flYawRange ) ;
QAngle vecTargetAngles ( 0 , UTIL_AngleMod ( flCenterYaw - flScanAmount ) , 0 ) ;
/*
float flCenterPitch = m_hFuncTank - > YawCenterWorld ( ) ;
float flPitchRange = m_hFuncTank - > PitchRange ( ) ;
float flPitch = random - > RandomFloat ( - flPitchRange , flPitchRange ) ;
QAngle vecTargetAngles ( flCenterPitch + flPitch , UTIL_AngleMod ( flCenterYaw - flScanAmount ) , 0 ) ;
*/
Vector vecTargetForward ;
AngleVectors ( vecTargetAngles , & vecTargetForward ) ;
Vector vecTarget = GetOuter ( ) - > EyePosition ( ) + ( vecTargetForward * 256 ) ;
GetOuter ( ) - > AddLookTarget ( vecTarget , 1.0 , 2.0 , 0.2 ) ;
m_hFuncTank - > NPC_SetIdleAngle ( vecTarget ) ;
break ;
}
case TASK_FORGET_ABOUT_FUNCTANK :
{
if ( ! m_hFuncTank )
{
TaskFail ( FAIL_NO_TARGET ) ;
return ;
}
break ;
}
default :
{
BaseClass : : StartTask ( pTask ) ;
break ;
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAI_FuncTankBehavior : : RunTask ( const Task_t * pTask )
{
switch ( pTask - > iTask )
{
case TASK_FACE_FUNCTANK :
{
Assert ( m_hFuncTank ) ;
GetMotor ( ) - > UpdateYaw ( ) ;
if ( GetOuter ( ) - > FacingIdeal ( ) )
{
TaskComplete ( ) ;
}
break ;
}
case TASK_HOLSTER_WEAPON :
{
Assert ( m_hFuncTank ) ;
if ( GetOuter ( ) - > IsWeaponHolstered ( ) )
{
GetOuter ( ) - > SpeakSentence ( FUNCTANK_SENTENCE_JUST_MOUNTED ) ;
// We are at the correct position and facing for the func_tank, mount it.
m_hFuncTank - > StartControl ( GetOuter ( ) ) ;
GetOuter ( ) - > ClearEnemyMemory ( ) ;
m_bMounted = true ;
TaskComplete ( ) ;
GetOuter ( ) - > SetIdealActivity ( ACT_IDLE_MANNEDGUN ) ;
}
break ;
}
case TASK_FIRE_FUNCTANK :
{
Assert ( m_hFuncTank ) ;
if ( GetOuter ( ) - > m_flWaitFinished < gpGlobals - > curtime )
{
TaskComplete ( ) ;
}
if ( m_hFuncTank - > NPC_HasEnemy ( ) )
{
GetOuter ( ) - > SetLastAttackTime ( gpGlobals - > curtime ) ;
m_hFuncTank - > NPC_Fire ( ) ;
// The NPC may have decided to stop using the func_tank, because it's out of ammo.
if ( ! m_hFuncTank )
{
TaskComplete ( ) ;
break ;
}
}
else
{
TaskComplete ( ) ;
}
Assert ( m_hFuncTank ) ;
if ( m_hFuncTank - > GetAmmoCount ( ) = = 0 )
{
TaskComplete ( ) ;
}
break ;
}
case TASK_SCAN_LEFT_FUNCTANK :
case TASK_SCAN_RIGHT_FUNCTANK :
{
GetMotor ( ) - > UpdateYaw ( ) ;
if ( GetOuter ( ) - > FacingIdeal ( ) )
{
TaskComplete ( ) ;
}
break ;
}
case TASK_FORGET_ABOUT_FUNCTANK :
{
m_hFuncTank - > NPC_InterruptRoute ( ) ;
SetBusy ( gpGlobals - > curtime + AI_FUNCTANK_BEHAVIOR_BUSYTIME ) ;
TaskComplete ( ) ;
break ;
}
default :
{
BaseClass : : RunTask ( pTask ) ;
break ;
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAI_FuncTankBehavior : : Event_Killed ( const CTakeDamageInfo & info )
{
if ( m_hFuncTank )
{
Dismount ( ) ;
}
Assert ( ! m_hFuncTank ) ;
BaseClass : : Event_Killed ( info ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAI_FuncTankBehavior : : UpdateOnRemove ( void )
{
if ( m_hFuncTank )
{
Dismount ( ) ;
}
BaseClass : : UpdateOnRemove ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAI_FuncTankBehavior : : SetFuncTank ( CHandle < CFuncTank > hFuncTank )
{
if ( m_hFuncTank & & ! hFuncTank )
{
SetBusy ( gpGlobals - > curtime + AI_FUNCTANK_BEHAVIOR_BUSYTIME ) ;
SetCondition ( COND_FUNCTANK_DISMOUNT ) ;
}
m_hFuncTank = hFuncTank ;
GetOuter ( ) - > ClearSchedule ( " Setting a new func_tank " ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAI_FuncTankBehavior : : AimGun ( void )
{
if ( m_bMounted & & m_hFuncTank )
{
Vector vecForward ;
AngleVectors ( m_hFuncTank - > GetAbsAngles ( ) , & vecForward ) ;
GetOuter ( ) - > SetAim ( vecForward ) ;
return ;
}
BaseClass : : AimGun ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAI_FuncTankBehavior : : GatherConditions ( )
{
BaseClass : : GatherConditions ( ) ;
// Since we can't pathfind, if we can't see the enemy, he's eluded us
// So we deliberately ignore unreachability
if ( GetEnemy ( ) & & ! HasCondition ( COND_SEE_ENEMY ) )
{
if ( gpGlobals - > curtime - GetOuter ( ) - > GetEnemyLastTimeSeen ( ) > = 3.0f )
{
GetOuter ( ) - > MarkEnemyAsEluded ( ) ;
}
}
if ( ! m_hFuncTank )
{
m_bMounted = false ;
GetOuter ( ) - > SetDesiredWeaponState ( DESIREDWEAPONSTATE_UNHOLSTERED ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CBaseEntity * CAI_FuncTankBehavior : : BestEnemy ( void )
{
// Only use this BestEnemy call when we are on the manned gun.
if ( ! m_hFuncTank | | ! IsMounted ( ) )
return BaseClass : : BestEnemy ( ) ;
CBaseEntity * pBestEnemy = NULL ;
int iBestDistSq = MAX_COORD_RANGE * MAX_COORD_RANGE ; // so first visible entity will become the closest.
int iBestPriority = - 1000 ;
bool bBestUnreachable = false ; // Forces initial check
bool bBestSeen = false ;
bool bUnreachable = false ;
int iDistSq ;
AIEnemiesIter_t iter ;
// Get the current npc for checking from.
CAI_BaseNPC * pNPC = GetOuter ( ) ;
if ( ! pNPC )
return NULL ;
for ( AI_EnemyInfo_t * pEMemory = GetEnemies ( ) - > GetFirst ( & iter ) ; pEMemory ! = NULL ; pEMemory = GetEnemies ( ) - > GetNext ( & iter ) )
{
CBaseEntity * pEnemy = pEMemory - > hEnemy ;
if ( ! pEnemy | | ! pEnemy - > IsAlive ( ) )
continue ;
// UNDONE: Move relationship checks into IsValidEnemy?
if ( ( pEnemy - > GetFlags ( ) & FL_NOTARGET ) | |
( pNPC - > IRelationType ( pEnemy ) ! = D_HT & & pNPC - > IRelationType ( pEnemy ) ! = D_FR ) | |
! IsValidEnemy ( pEnemy ) )
continue ;
if ( pEMemory - > timeLastSeen < pNPC - > GetAcceptableTimeSeenEnemy ( ) )
continue ;
if ( pEMemory - > timeValidEnemy > gpGlobals - > curtime )
continue ;
// Skip enemies that have eluded me to prevent infinite loops
if ( GetEnemies ( ) - > HasEludedMe ( pEnemy ) )
continue ;
// Establish the reachability of this enemy
bUnreachable = pNPC - > IsUnreachable ( pEnemy ) ;
// Check view cone of the view tank here.
bUnreachable = ! m_hFuncTank - > IsEntityInViewCone ( pEnemy ) ;
if ( ! bUnreachable )
{
// It's in the viewcone. Now make sure we have LOS to it.
bUnreachable = ! m_hFuncTank - > HasLOSTo ( pEnemy ) ;
}
// If best is reachable and current is unreachable, skip the unreachable enemy regardless of priority
if ( ! bBestUnreachable & & bUnreachable )
continue ;
// If best is unreachable and current is reachable, always pick the current regardless of priority
if ( bBestUnreachable & & ! bUnreachable )
{
bBestSeen = ( pNPC - > GetSenses ( ) - > DidSeeEntity ( pEnemy ) | | pNPC - > FVisible ( pEnemy ) ) ; // @TODO (toml 04-02-03): Need to optimize CanSeeEntity() so multiple calls in frame do not recalculate, rather cache
iBestPriority = pNPC - > IRelationPriority ( pEnemy ) ;
2008-09-15 02:50:57 -05:00
iBestDistSq = ( int ) ( pEnemy - > GetAbsOrigin ( ) - GetAbsOrigin ( ) ) . LengthSqr ( ) ;
2008-09-15 01:07:45 -05:00
pBestEnemy = pEnemy ;
bBestUnreachable = bUnreachable ;
}
// If both are unreachable or both are reachable, chose enemy based on priority and distance
else if ( pNPC - > IRelationPriority ( pEnemy ) > iBestPriority )
{
// this entity is disliked MORE than the entity that we
// currently think is the best visible enemy. No need to do
// a distance check, just get mad at this one for now.
iBestPriority = pNPC - > IRelationPriority ( pEnemy ) ;
2008-09-15 02:50:57 -05:00
iBestDistSq = ( int ) ( pEnemy - > GetAbsOrigin ( ) - GetAbsOrigin ( ) ) . LengthSqr ( ) ;
2008-09-15 01:07:45 -05:00
pBestEnemy = pEnemy ;
bBestUnreachable = bUnreachable ;
}
else if ( pNPC - > IRelationPriority ( pEnemy ) = = iBestPriority )
{
// this entity is disliked just as much as the entity that
// we currently think is the best visible enemy, so we only
// get mad at it if it is closer.
2008-09-15 02:50:57 -05:00
iDistSq = ( int ) ( pEnemy - > GetAbsOrigin ( ) - GetAbsOrigin ( ) ) . LengthSqr ( ) ;
2008-09-15 01:07:45 -05:00
bool bCloser = ( iDistSq < iBestDistSq ) ;
if ( bCloser | | ! bBestSeen )
{
// @TODO (toml 04-02-03): Need to optimize FVisible() so multiple calls in frame do not recalculate, rather cache
bool fSeen = ( pNPC - > GetSenses ( ) - > DidSeeEntity ( pEnemy ) | | pNPC - > FVisible ( pEnemy ) ) ;
if ( ( bCloser & & ( fSeen | | ! bBestSeen ) ) | | ( ! bCloser & & ! bBestSeen & & fSeen ) )
{
bBestSeen = fSeen ;
iBestDistSq = iDistSq ;
iBestPriority = pNPC - > IRelationPriority ( pEnemy ) ;
pBestEnemy = pEnemy ;
bBestUnreachable = bUnreachable ;
}
}
}
}
return pBestEnemy ;
}
//=============================================================================
//
// Custom AI schedule data
//
AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER ( CAI_FuncTankBehavior )
DECLARE_TASK ( TASK_GET_PATH_TO_FUNCTANK )
DECLARE_TASK ( TASK_FACE_FUNCTANK )
DECLARE_TASK ( TASK_HOLSTER_WEAPON )
DECLARE_TASK ( TASK_FIRE_FUNCTANK )
DECLARE_TASK ( TASK_SCAN_LEFT_FUNCTANK )
DECLARE_TASK ( TASK_SCAN_RIGHT_FUNCTANK )
DECLARE_TASK ( TASK_FORGET_ABOUT_FUNCTANK )
DECLARE_TASK ( TASK_FUNCTANK_ANNOUNCE_SCAN )
DECLARE_CONDITION ( COND_FUNCTANK_DISMOUNT )
//=========================================================
//=========================================================
DEFINE_SCHEDULE
(
SCHED_MOVE_TO_FUNCTANK ,
" Tasks "
" TASK_SET_FAIL_SCHEDULE SCHEDULE: SCHED_FAIL_MOVE_TO_FUNCTANK "
" TASK_GET_PATH_TO_FUNCTANK 0 "
" TASK_SPEAK_SENTENCE 1000 " // FUNCTANK_SENTENCE_MOVE_TO_MOUNT
" TASK_RUN_PATH 0 "
" TASK_WAIT_FOR_MOVEMENT 0 "
" TASK_STOP_MOVING 0 "
" TASK_FACE_FUNCTANK 0 "
" TASK_HOLSTER_WEAPON 0 "
" "
" Interrupts "
" COND_FUNCTANK_DISMOUNT "
)
//=========================================================
//=========================================================
DEFINE_SCHEDULE
(
SCHED_FIRE_FUNCTANK ,
" Tasks "
" TASK_ANNOUNCE_ATTACK 1 " // 1 = primary attack
" TASK_FIRE_FUNCTANK 0 "
" "
" Interrupts "
" COND_NEW_ENEMY "
" COND_ENEMY_DEAD "
" COND_LOST_ENEMY "
" COND_ENEMY_OCCLUDED "
" COND_WEAPON_BLOCKED_BY_FRIEND "
" COND_WEAPON_SIGHT_OCCLUDED "
" COND_FUNCTANK_DISMOUNT "
)
DEFINE_SCHEDULE
(
SCHED_SCAN_WITH_FUNCTANK ,
" Tasks "
" TASK_FUNCTANK_ANNOUNCE_SCAN 0 "
" TASK_STOP_MOVING 0 "
" TASK_WAIT 4 "
" TASK_SCAN_LEFT_FUNCTANK 0 "
" TASK_WAIT 4 "
" TASK_SCAN_RIGHT_FUNCTANK 0 "
" "
" Interrupts "
" COND_NEW_ENEMY "
" COND_PROVOKED "
" COND_FUNCTANK_DISMOUNT "
)
DEFINE_SCHEDULE
(
SCHED_FAIL_MOVE_TO_FUNCTANK ,
" Tasks "
" TASK_FORGET_ABOUT_FUNCTANK 0 "
" "
" Interrupts "
)
AI_END_CUSTOM_SCHEDULE_PROVIDER ( )