mirror of
https://github.com/nillerusr/source-engine.git
synced 2025-02-07 12:44:28 +00:00
549 lines
13 KiB
C++
549 lines
13 KiB
C++
![]() |
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
|||
|
//
|
|||
|
// Purpose:
|
|||
|
//
|
|||
|
//=============================================================================//
|
|||
|
|
|||
|
#include "cbase.h"
|
|||
|
#include "beam_shared.h"
|
|||
|
#include "ai_motor.h"
|
|||
|
#include "asw_ai_behavior_shield.h"
|
|||
|
#include "ai_hint.h"
|
|||
|
#include "ai_navigator.h"
|
|||
|
#include "ai_memory.h"
|
|||
|
#include "asw_alien.h"
|
|||
|
#include "movevars_shared.h"
|
|||
|
#include "asw_marine.h"
|
|||
|
#include "asw_player.h"
|
|||
|
#include "asw_director.h"
|
|||
|
|
|||
|
// memdbgon must be the last include file in a .cpp file!!!
|
|||
|
#include "tier0/memdbgon.h"
|
|||
|
|
|||
|
|
|||
|
BEGIN_DATADESC( CAI_ASW_ShieldBehavior )
|
|||
|
END_DATADESC();
|
|||
|
|
|||
|
LINK_BEHAVIOR_TO_CLASSNAME( CAI_ASW_ShieldBehavior );
|
|||
|
|
|||
|
|
|||
|
//#define DRAW_DEBUG 1
|
|||
|
|
|||
|
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
// Purpose: constructor
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
CAI_ASW_ShieldBehavior::CAI_ASW_ShieldBehavior( )
|
|||
|
{
|
|||
|
m_flDistance = 200.0f;
|
|||
|
m_flMaxFrozenTime = 3.0f;
|
|||
|
m_flSFrozenDownTime = 3.0f;
|
|||
|
m_flFrozenTimeReductionMultiplier = 10.0f;
|
|||
|
m_flFrozenTimeExpansionMultiplier = 50.0f;
|
|||
|
m_FrozenParm = UTL_INVAL_SYMBOL;
|
|||
|
m_bShieldLowering = false;
|
|||
|
m_bBeganFrozen = false;
|
|||
|
m_flStartFrozenTime = -1.0f;
|
|||
|
m_flEndFrozenTime = -1.0f;
|
|||
|
m_flStartDownTime = -1.0f;
|
|||
|
m_bReachedFrozenLimit = false;
|
|||
|
m_TurningGesture = ACT_INVALID;
|
|||
|
m_Freezer = NULL;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
// Purpose: function to set up parameters
|
|||
|
// Input : szKeyName - the name of the key
|
|||
|
// szValue - the value to be set
|
|||
|
// Output : returns true of we handled this key
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
bool CAI_ASW_ShieldBehavior::KeyValue( const char *szKeyName, const char *szValue )
|
|||
|
{
|
|||
|
if ( V_stricmp( szKeyName, "distance") == 0 )
|
|||
|
{
|
|||
|
m_flDistance = atof( szValue );
|
|||
|
return true;
|
|||
|
}
|
|||
|
else if ( V_stricmp( szKeyName, "max_frozen_time") == 0 )
|
|||
|
{
|
|||
|
m_flMaxFrozenTime = atof( szValue );
|
|||
|
return true;
|
|||
|
}
|
|||
|
else if ( V_stricmp( szKeyName, "frozen_down_time") == 0 )
|
|||
|
{
|
|||
|
m_flSFrozenDownTime = atof( szValue );
|
|||
|
return true;
|
|||
|
}
|
|||
|
else if ( V_stricmp( szKeyName, "frozen_param" ) == 0 )
|
|||
|
{
|
|||
|
m_FrozenParm = GetSymbol( szValue );
|
|||
|
return true;
|
|||
|
}
|
|||
|
else if ( V_stricmp( szKeyName, "frozen_time_reduction_multiplier" ) == 0 )
|
|||
|
{
|
|||
|
m_flFrozenTimeReductionMultiplier = atof( szValue );
|
|||
|
return true;
|
|||
|
}
|
|||
|
else if ( V_stricmp( szKeyName, "frozen_time_expansion_multiplier" ) == 0 )
|
|||
|
{
|
|||
|
m_flFrozenTimeExpansionMultiplier = atof( szValue );
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
return BaseClass::KeyValue( szKeyName, szValue );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
// Purpose: precaches any additional assets this behavior needs
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
void CAI_ASW_ShieldBehavior::Precache( void )
|
|||
|
{
|
|||
|
BaseClass::Precache();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
// Purpose:
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
void CAI_ASW_ShieldBehavior::Init( )
|
|||
|
{
|
|||
|
CASW_Alien *pNPC = static_cast< CASW_Alien * >( GetOuter() );
|
|||
|
if ( !pNPC )
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
pNPC->meleeAttack2.Init( 0.0f, m_flDistance, COMBAT_COND_NO_FACING_CHECK, true );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
// Purpose: determines if we can use this behavior currently
|
|||
|
// Output : returns true if this behavior is able to run
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
bool CAI_ASW_ShieldBehavior::CanSelectSchedule()
|
|||
|
{
|
|||
|
if ( m_bShieldLowering )
|
|||
|
{
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
if ( !GetOuter()->IsInterruptable() )
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
if ( !HasCondition( COND_CAN_MELEE_ATTACK2 ) )
|
|||
|
{
|
|||
|
if ( GetBehaviorParam( m_StatusParm ) == 0 )
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return BaseClass::CanSelectSchedule();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
// Purpose: sets / clears conditions for when the behavior is active. this is
|
|||
|
// generally a larger set of conditions to interrupt any tasks.
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
void CAI_ASW_ShieldBehavior::GatherConditions( )
|
|||
|
{
|
|||
|
BaseClass::GatherConditions();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
// Purpose: sets / clears conditions for when the behavior is not active. this is
|
|||
|
// mainly to have a smaller set of conditions to wake up the behavior.
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
void CAI_ASW_ShieldBehavior::GatherConditionsNotActive( )
|
|||
|
{
|
|||
|
BaseClass::GatherConditionsNotActive();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void CAI_ASW_ShieldBehavior::BeginScheduleSelection( )
|
|||
|
{
|
|||
|
m_TurningGesture = ACT_INVALID;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void CAI_ASW_ShieldBehavior::EndScheduleSelection( )
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
// Purpose: general purpose routine to collect conditions used both during active
|
|||
|
// and non-active states of the behavior.
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
void CAI_ASW_ShieldBehavior::GatherCommonConditions( )
|
|||
|
{
|
|||
|
BaseClass::GatherCommonConditions();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
// Purpose: routine called to start when a task initially starts
|
|||
|
// Input : pTask - the task structure
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
void CAI_ASW_ShieldBehavior::StartTask( const Task_t *pTask )
|
|||
|
{
|
|||
|
switch( pTask->iTask )
|
|||
|
{
|
|||
|
case TASK_SHIELD_RAISE:
|
|||
|
GetOuter()->SetIdealActivity( ACT_SHIELD_UP );
|
|||
|
break;
|
|||
|
|
|||
|
case TASK_SHIELD_LOWER:
|
|||
|
GetOuter()->SetIdealActivity( ACT_SHIELD_DOWN );
|
|||
|
break;
|
|||
|
|
|||
|
case TASK_SHIELD_MAINTAIN:
|
|||
|
m_TurningGesture = ACT_INVALID;
|
|||
|
|
|||
|
if ( m_flEndFrozenTime < gpGlobals->curtime )
|
|||
|
{
|
|||
|
CBaseEntity *pTarget = GetEnemy();
|
|||
|
|
|||
|
if ( pTarget )
|
|||
|
{
|
|||
|
float flIdealYaw = UTIL_VecToYaw( pTarget->GetAbsOrigin() - GetLocalOrigin() );
|
|||
|
float flYawDiff = UTIL_AngleMod( GetLocalAngles().y - flIdealYaw );
|
|||
|
if ( flYawDiff > 180.0f && flYawDiff < 330.0f )
|
|||
|
{
|
|||
|
m_TurningGesture = ACT_GESTURE_TURN_LEFT45;
|
|||
|
GetOuter()->RestartGesture( m_TurningGesture );
|
|||
|
GetOuter()->SetIdealActivity( ACT_SHIELD_UP_IDLE );
|
|||
|
}
|
|||
|
else if ( flYawDiff <= 180.0f && flYawDiff > 30.0f )
|
|||
|
{
|
|||
|
m_TurningGesture = ACT_GESTURE_TURN_RIGHT45;
|
|||
|
GetOuter()->RestartGesture( m_TurningGesture );
|
|||
|
GetOuter()->SetIdealActivity( ACT_SHIELD_UP_IDLE );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( m_TurningGesture == ACT_INVALID )
|
|||
|
{
|
|||
|
if ( m_flEndFrozenTime > gpGlobals->curtime )
|
|||
|
{
|
|||
|
if ( m_bBeganFrozen == false )
|
|||
|
{
|
|||
|
m_bBeganFrozen = true;
|
|||
|
GetOuter()->SetIdealActivity( ACT_CROUCHING_SHIELD_UP );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
GetOuter()->SetIdealActivity( ACT_CROUCHING_SHIELD_UP_IDLE );
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
GetOuter()->SetIdealActivity( ACT_SHIELD_UP_IDLE );
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case TASK_SHIELD_MAINTAIN_FLIP:
|
|||
|
{
|
|||
|
bool bNeedFlip = false;
|
|||
|
|
|||
|
if ( HaveSequenceForActivity( ACT_SPINAROUND ) == true )
|
|||
|
{
|
|||
|
CBaseEntity *pTarget = GetEnemy();
|
|||
|
if ( pTarget )
|
|||
|
{
|
|||
|
float flIdealYaw = UTIL_VecToYaw( pTarget->GetAbsOrigin() - GetLocalOrigin() );
|
|||
|
float flYawDiff = UTIL_AngleMod( GetLocalAngles().y - flIdealYaw );
|
|||
|
|
|||
|
if ( fabs( flYawDiff - 180.0f ) <= 40.0f )
|
|||
|
{
|
|||
|
bNeedFlip = true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( bNeedFlip == false )
|
|||
|
{
|
|||
|
TaskComplete();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
GetOuter()->SetIdealActivity( ACT_SPINAROUND );
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
BaseClass::StartTask( pTask );
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
// Purpose: routine called every frame when a task is running
|
|||
|
// Input : pTask - the task structure
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
void CAI_ASW_ShieldBehavior::RunTask( const Task_t *pTask )
|
|||
|
{
|
|||
|
switch( pTask->iTask )
|
|||
|
{
|
|||
|
case TASK_SHIELD_RAISE:
|
|||
|
{
|
|||
|
CBaseEntity *pTarget = GetEnemy();
|
|||
|
|
|||
|
if ( pTarget )
|
|||
|
{
|
|||
|
GetMotor()->SetIdealYawAndUpdate( pTarget->GetAbsOrigin() - GetLocalOrigin(), AI_KEEP_YAW_SPEED );
|
|||
|
}
|
|||
|
|
|||
|
if ( GetOuter()->IsActivityFinished() )
|
|||
|
{
|
|||
|
TaskComplete();
|
|||
|
SetBehaviorParam( m_StatusParm, 1 );
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case TASK_SHIELD_LOWER:
|
|||
|
if ( GetOuter()->IsActivityFinished() )
|
|||
|
{
|
|||
|
TaskComplete();
|
|||
|
SetBehaviorParam( m_StatusParm, 0 );
|
|||
|
m_bShieldLowering = false;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case TASK_SHIELD_MAINTAIN:
|
|||
|
{
|
|||
|
bool bNoReset = false;
|
|||
|
|
|||
|
if ( m_TurningGesture != ACT_INVALID )
|
|||
|
{
|
|||
|
CBaseEntity *pTarget = GetEnemy();
|
|||
|
|
|||
|
if ( pTarget )
|
|||
|
{
|
|||
|
GetMotor()->SetIdealYawAndUpdate( pTarget->GetAbsOrigin() - GetLocalOrigin(), AI_KEEP_YAW_SPEED );
|
|||
|
}
|
|||
|
|
|||
|
if ( GetOuter()->IsPlayingGesture( m_TurningGesture ) == false )
|
|||
|
{
|
|||
|
TaskComplete();
|
|||
|
m_TurningGesture = ACT_INVALID;
|
|||
|
|
|||
|
if ( pTarget )
|
|||
|
{
|
|||
|
float flIdealYaw = UTIL_VecToYaw( pTarget->GetAbsOrigin() - GetLocalOrigin() );
|
|||
|
float flYawDiff = UTIL_AngleMod( GetLocalAngles().y - flIdealYaw );
|
|||
|
if ( flYawDiff > 25.0f && flYawDiff < 335.0f )
|
|||
|
{
|
|||
|
bNoReset = true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else if ( GetOuter()->IsActivityFinished() )
|
|||
|
{
|
|||
|
TaskComplete();
|
|||
|
}
|
|||
|
|
|||
|
if ( m_flStartFrozenTime != -1.0f && m_flEndFrozenTime < gpGlobals->curtime && bNoReset == false )
|
|||
|
{
|
|||
|
m_flStartFrozenTime = -1.0f;
|
|||
|
m_flStartDownTime = gpGlobals->curtime + m_flSFrozenDownTime;
|
|||
|
SetBehaviorParam( m_FrozenParm, 0 );
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case TASK_SHIELD_MAINTAIN_FLIP:
|
|||
|
{
|
|||
|
CBaseEntity *pTarget = GetEnemy();
|
|||
|
if ( pTarget )
|
|||
|
{
|
|||
|
GetMotor()->SetIdealYawAndUpdate( pTarget->GetAbsOrigin() - GetLocalOrigin(), AI_KEEP_YAW_SPEED );
|
|||
|
}
|
|||
|
|
|||
|
if ( GetOuter()->IsActivityFinished() )
|
|||
|
{
|
|||
|
TaskComplete();
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
BaseClass::RunTask( pTask );
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
// Purpose: routine called to select what schedule we want to run
|
|||
|
// Output : returns the schedule id of the schedule we want to run
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
int CAI_ASW_ShieldBehavior::SelectSchedule()
|
|||
|
{
|
|||
|
if ( !HasCondition( COND_CAN_MELEE_ATTACK2 ) )
|
|||
|
{
|
|||
|
return SCHED_SHIELD_LOWER;
|
|||
|
}
|
|||
|
|
|||
|
if ( GetBehaviorParam( m_StatusParm ) == 0 )
|
|||
|
{
|
|||
|
return SCHED_SHIELD_PREPARE;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return SCHED_SHIELD_MAINTAIN;
|
|||
|
}
|
|||
|
|
|||
|
#if 0
|
|||
|
if ( m_bShieldLowering == true )
|
|||
|
{
|
|||
|
return SCHED_SHIELD_LOWER;
|
|||
|
}
|
|||
|
|
|||
|
if ( GetBehaviorParam( m_StatusParm ) == 0 )
|
|||
|
{
|
|||
|
return SCHED_SHIELD_PREPARE;
|
|||
|
}
|
|||
|
|
|||
|
if ( HasCondition( COND_SHIELD_CAN_FLICK ) )
|
|||
|
{
|
|||
|
return SCHED_SHIELD_FLICK;
|
|||
|
}
|
|||
|
|
|||
|
return SCHED_SHIELD_MAINTAIN;
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
// Purpose:
|
|||
|
// Input :
|
|||
|
// Output :
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
void CAI_ASW_ShieldBehavior::HandleBehaviorEvent( CBaseEntity *pInflictor, BehaviorEvent_t eEvent, int nParm )
|
|||
|
{
|
|||
|
switch( eEvent )
|
|||
|
{
|
|||
|
case BEHAVIOR_EVENT_TOOK_DAMAGE:
|
|||
|
{
|
|||
|
float flPercent = ( float )nParm / ( float )GetOuter()->GetMaxHealth();
|
|||
|
if ( m_Freezer != pInflictor )
|
|||
|
{
|
|||
|
flPercent *= 3.0f;
|
|||
|
}
|
|||
|
m_flEndFrozenTime -= flPercent * m_flFrozenTimeReductionMultiplier;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case BEHAVIOR_EVENT_DEFLECTED_DAMAGE:
|
|||
|
{
|
|||
|
if ( m_flStartDownTime > gpGlobals->curtime )
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if ( m_flStartFrozenTime == -1.0f )
|
|||
|
{
|
|||
|
m_flStartFrozenTime = gpGlobals->curtime;
|
|||
|
m_flEndFrozenTime = m_flStartFrozenTime;
|
|||
|
m_bReachedFrozenLimit = false;
|
|||
|
SetBehaviorParam( m_FrozenParm, 1 );
|
|||
|
m_Freezer = pInflictor;
|
|||
|
m_bBeganFrozen = false;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
m_flEndFrozenTime += gpGlobals->curtime - m_flStartFrozenTime;
|
|||
|
/* if ( m_bReachedFrozenLimit == false )
|
|||
|
{
|
|||
|
m_flStartFrozenTime = gpGlobals->curtime;
|
|||
|
}
|
|||
|
*/
|
|||
|
}
|
|||
|
|
|||
|
float flPercent = ( float )nParm / ( float )GetOuter()->GetMaxHealth();
|
|||
|
m_flEndFrozenTime += flPercent * m_flFrozenTimeExpansionMultiplier;
|
|||
|
if ( ( m_flEndFrozenTime - m_flStartFrozenTime ) > m_flMaxFrozenTime )
|
|||
|
{
|
|||
|
m_flEndFrozenTime = m_flStartFrozenTime + m_flMaxFrozenTime;
|
|||
|
m_bReachedFrozenLimit = true;
|
|||
|
}
|
|||
|
// Msg( "Time to awake: %g\n", m_flEndFrozenTime - gpGlobals->curtime );
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#if 0
|
|||
|
bool CAI_ASW_ShieldBehavior::GetBehaviorParam( BehaviorParam_t eParam, bool &bResult )
|
|||
|
{
|
|||
|
switch( eParam )
|
|||
|
{
|
|||
|
case BEHAVIOR_PARAM_IS_SHIELDED:
|
|||
|
bResult = ( GetBehaviorParam( m_StatusParm ) == 1 );
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
return BaseClass::GetBehaviorParam( eParam, bResult );
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_ASW_ShieldBehavior )
|
|||
|
|
|||
|
DECLARE_TASK( TASK_SHIELD_RAISE )
|
|||
|
DECLARE_TASK( TASK_SHIELD_MAINTAIN )
|
|||
|
DECLARE_TASK( TASK_SHIELD_MAINTAIN_FLIP )
|
|||
|
DECLARE_TASK( TASK_SHIELD_LOWER )
|
|||
|
|
|||
|
DEFINE_SCHEDULE
|
|||
|
(
|
|||
|
SCHED_SHIELD_PREPARE,
|
|||
|
" Tasks"
|
|||
|
" TASK_STOP_MOVING 0"
|
|||
|
" TASK_SHIELD_RAISE 0"
|
|||
|
""
|
|||
|
" Interrupts"
|
|||
|
);
|
|||
|
|
|||
|
DEFINE_SCHEDULE
|
|||
|
(
|
|||
|
SCHED_SHIELD_MAINTAIN,
|
|||
|
" Tasks"
|
|||
|
// " TASK_PLAY_SEQUENCE_FACE_ENEMY ACTIVITY:ACT_SHIELD_UP_IDLE"
|
|||
|
" TASK_SHIELD_MAINTAIN_FLIP 0"
|
|||
|
" TASK_SHIELD_MAINTAIN 0"
|
|||
|
""
|
|||
|
" Interrupts"
|
|||
|
);
|
|||
|
|
|||
|
DEFINE_SCHEDULE
|
|||
|
(
|
|||
|
SCHED_SHIELD_LOWER,
|
|||
|
" Tasks"
|
|||
|
" TASK_SHIELD_LOWER 0"
|
|||
|
""
|
|||
|
" Interrupts"
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
AI_END_CUSTOM_SCHEDULE_PROVIDER()
|
|||
|
|
|||
|
#include "tier0/memdbgoff.h"
|