Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

855 lines
21 KiB

//========== Copyright © 2008, Valve Corporation, All rights reserved. ========
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include "ai_behavior_fightfromcover.h"
#include "ai_hint.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
BEGIN_DATADESC( CAI_FightFromCoverBehavior )
DEFINE_FIELD( m_hGoal, FIELD_EHANDLE ),
DEFINE_EMBEDDED( m_FrontMoveMonitor ),
DEFINE_EMBEDDED( m_FrontTimer ),
END_DATADESC();
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
CAI_FightFromCoverBehavior::CAI_FightFromCoverBehavior()
{
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CAI_FightFromCoverBehavior::SetGoal( CAI_FightFromCoverGoal *pGoal )
{
m_hGoal = pGoal;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CAI_FightFromCoverBehavior::ClearGoal()
{
m_hGoal = NULL;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CAI_FightFromCoverBehavior::IsPointInZone( const Vector &v )
{
if ( !m_hGoal->GetFrontDirection().IsValid() )
{
return true;
}
Vector vCenterZone;
vCenterZone = ( m_hGoal->GetFrontDirection() * -m_hGoal->m_BiasZone ) + m_hGoal->GetFrontPosition();
Vector vRelativePos ;
VectorRotate( v - vCenterZone, -m_hGoal->GetFrontAngles(), vRelativePos );
float w = m_hGoal->m_WidthZone * .5, l = m_hGoal->m_LengthZone * .5, h = m_hGoal->m_HeightZone * .5;
Vector mins( -l, -w, -h ), maxs( l, w, h );
if ( vRelativePos.x < mins.x || vRelativePos.x > maxs.x ||
vRelativePos.y < mins.y || vRelativePos.y > maxs.y ||
vRelativePos.z < mins.z || vRelativePos.z > maxs.z )
{
// NDebugOverlay::Cross3D( v, 36, 255, 0, 0, true, 3 );
return false;
}
// NDebugOverlay::Cross3D( v, 36, 0, 255, 0, true, 3 );
return true;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CAI_FightFromCoverBehavior::FValidateHintType ( CAI_Hint *pHint )
{
if ( pHint->HintType() == HINT_GENERIC && pHint->GetGenericType() == m_hGoal->m_GenericHintType )
{
return true;
}
return BaseClass::FValidateHintType( pHint );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CAI_FightFromCoverBehavior::HintSearchFilter( void *pContext, CAI_Hint *pCandidate )
{
CAI_FightFromCoverBehavior *pThis = (CAI_FightFromCoverBehavior *)pContext;
Vector vHintDir;
if ( pThis->m_hGoal->GetFrontDirection().IsValid() )
{
pCandidate->GetVectors( &vHintDir, NULL, NULL );
if ( vHintDir.Dot( pThis->m_hGoal->GetFrontDirection() ) < DOT_45DEGREE )
{
return false;
}
}
return pThis->IsPointInZone( pCandidate->GetAbsOrigin() );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CAI_FightFromCoverBehavior::GatherConditions()
{
BaseClass::GatherConditions();
ClearCondition( COND_FFC_HINT_CHANGE );
if ( !m_hGoal )
{
SetCondition( COND_FFC_HINT_CHANGE );
ClearHintNode();
return;
}
if ( GetHintNode() && m_FrontTimer.Expired() && m_FrontMoveMonitor.TargetMoved( m_hGoal->GetFrontPosition() ) )
{
float flFastRejectDist = MAX( m_hGoal->m_WidthZone, m_hGoal->m_LengthZone ) + m_hGoal->m_BiasZone;
if ( ( GetHintNode()->GetAbsOrigin() - m_hGoal->GetFrontPosition() ).LengthSqr() > Square( flFastRejectDist ) || !IsPointInZone( GetHintNode()->GetAbsOrigin() ) )
{
GetHintNode()->Unlock();
SetHintNode( NULL );
SetCondition( COND_FFC_HINT_CHANGE );
}
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CAI_FightFromCoverBehavior::CanSelectSchedule()
{
return ( m_hGoal != NULL );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CAI_FightFromCoverBehavior::SelectSchedule()
{
Assert( m_hGoal != NULL );
if ( !m_hGoal )
{
return BaseClass::SelectSchedule();
}
if ( !GetHintNode() )
{
if ( m_FrontTimer.Expired() )
{
m_FrontTimer.Set( .75, 1.5 );
Vector vFront = m_hGoal->GetFrontPosition();
CHintCriteria hintCriteria;
hintCriteria.SetHintType( HINT_GENERIC );
hintCriteria.SetGenericType( m_hGoal->m_GenericHintType );
hintCriteria.SetFlag( bits_HINT_NODE_NEAREST | bits_HINT_NODE_USE_GROUP );
// Add the search position
hintCriteria.AddIncludePosition( vFront, MAX( m_hGoal->m_WidthZone, m_hGoal->m_LengthZone ) + m_hGoal->m_BiasZone );
hintCriteria.AddExcludePosition( m_hGoal->GetGoalEntity()->GetAbsOrigin(), 2.5*12 );
hintCriteria.SetFilterFunc( &HintSearchFilter, this );
const Vector &vDir = m_hGoal->GetFrontDirection();
if ( vDir.IsValid() )
{
vFront += vDir * m_hGoal->m_LengthZone;
}
CAI_Hint *pHint = CAI_HintManager::FindHint( GetOuter(), vFront, hintCriteria );
if ( !pHint )
{
// @HACKHACK [5/21/2008 tom]
float lengthSaved = m_hGoal->m_LengthZone, biasSaved = m_hGoal->m_BiasZone, widthSaved = m_hGoal->m_WidthZone;
m_hGoal->m_LengthZone += 2000;
m_hGoal->m_BiasZone += 1000;
m_hGoal->m_WidthZone += 2000;
pHint = CAI_HintManager::FindHint( GetOuter(), vFront, hintCriteria );
m_hGoal->m_LengthZone = lengthSaved;
m_hGoal->m_BiasZone = biasSaved;
m_hGoal->m_WidthZone = widthSaved;
}
if ( pHint )
{
SetHintNode( pHint );
pHint->Lock( GetOuter() );
m_FrontMoveMonitor.SetMark( vFront, 3*12 );
}
}
}
if ( GetHintNode() )
{
if ( ( GetHintNode()->GetAbsOrigin() - GetAbsOrigin() ).LengthSqr() > Square( 12.0 ) )
{
return SCHED_FFC_RUN_TO_HINT;
}
else if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) && !GetOuter()->GetShotRegulator()->IsInRestInterval() )
{
return SCHED_FFC_ATTACK;
}
else if ( HasCondition( COND_NO_PRIMARY_AMMO ) )
{
return SCHED_RELOAD;
}
else
{
GetOuter()->GetShotRegulator()->Reset( true );
return SCHED_FFC_HOLD_COVER;
}
}
return BaseClass::SelectSchedule();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CAI_FightFromCoverBehavior::StartTask( const Task_t *pTask )
{
switch ( pTask->iTask )
{
case TASK_FFC_GET_PATH_TO_HINT:
{
ChainStartTask( TASK_GET_PATH_TO_HINTNODE );
if ( !HasCondition(COND_TASK_FAILED) )
{
UpdateAnimationsFromHint();
}
else
{
// Should mark hint and try to find another one
ClearHintNode( 5 );
}
break;
}
case TASK_FFC_ATTACK:
{
CBaseCombatWeapon *pWeapon = GetOuter()->GetActiveWeapon();
if ( !pWeapon )
{
TaskFail( "No weapon" );
return;
}
int clipSize = pWeapon->GetMaxClip1();
GetOuter()->GetShotRegulator()->SetBurstShotCountRange( clipSize * .3, clipSize * .6 );
GetOuter()->GetShotRegulator()->SetRestInterval( INT_MAX, INT_MAX );
GetOuter()->GetShotRegulator()->Reset();
StartAnimationTask( m_ShootAnim, true, ACT_RANGE_ATTACK1 );
GetOuter()->SetLastAttackTime( gpGlobals->curtime );
GetOuter()->OnRangeAttack1();
break;
}
case TASK_RELOAD:
{
if ( !StartAnimationTask( m_ReloadAnim, true ) )
{
BaseClass::StartTask( pTask );
}
break;
}
case TASK_FFC_PEEK:
{
StartAnimationTask( m_PeekAnim );
break;
}
case TASK_FFC_COVER:
{
StartAnimationTask( m_CoverAnim );
break;
}
default:
BaseClass::StartTask( pTask );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CAI_FightFromCoverBehavior::RunTask( const Task_t *pTask )
{
switch ( pTask->iTask )
{
case TASK_FFC_ATTACK:
{
GetOuter()->AutoMovement( );
if ( GetOuter()->IsActivityFinished() )
{
if ( !GetEnemy() || !GetEnemy()->IsAlive() )
{
TaskComplete();
return;
}
if ( !GetOuter()->GetShotRegulator()->IsInRestInterval() )
{
if ( GetOuter()->GetShotRegulator()->ShouldShoot() )
{
GetOuter()->OnRangeAttack1();
StartAnimationTask( m_ShootAnim, true, ACT_RANGE_ATTACK1 );
}
return;
}
TaskComplete();
}
break;
}
case TASK_FFC_PEEK:
case TASK_FFC_COVER:
{
ChainRunTask( TASK_PLAY_SEQUENCE );
break;
}
default:
BaseClass::RunTask( pTask);
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CAI_FightFromCoverBehavior::OnUpdateShotRegulator()
{
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CAI_FightFromCoverBehavior::UpdateAnimationsFromHint()
{
m_EntryAnim.Reset();
m_MoveAnim.Reset();
m_CoverAnim.Reset();
m_ReloadAnim.Reset();
m_PeekAnim.Reset();
m_ShootAnim.Reset();
m_ExitAnim.Reset();
if ( !GetHintNode() )
{
return;
}
CScriptScope &hintScope = GetHintNode()->m_ScriptScope;
ScriptVariant_t animationsVar;
if ( hintScope.GetValue( "animations", &animationsVar ) )
{
if ( animationsVar.m_type == FIELD_HSCRIPT )
{
CScriptScope animations;
ScriptVariant_t var;
animations.Init( animationsVar.m_hScript );
GetAnimation( animations, "movement", &m_MoveAnim );
GetAnimation( animations, "entry", &m_EntryAnim );
if ( m_EntryAnim.id != ACT_INVALID )
{
DevMsg( "entry anim not yet supported!\n" );
m_EntryAnim.Reset();
}
GetAnimation( animations, "cover", &m_CoverAnim );
GetAnimation( animations, "reload", &m_ReloadAnim );
GetAnimation( animations, "peek", &m_PeekAnim );
GetAnimation( animations, "shoot", &m_ShootAnim );
GetAnimation( animations, "exit", &m_ExitAnim );
if ( m_EntryAnim.id != ACT_INVALID )
{
DevMsg( "exit anim not yet supported!\n" );
m_EntryAnim.Reset();
}
}
else
{
DevMsg( "Unexpected type for script value \"animations\"\n" );
}
hintScope.ReleaseValue( animationsVar );
}
if ( m_MoveAnim.id != ACT_INVALID )
{
if ( m_MoveAnim.bActivity )
{
GetNavigator()->SetMovementActivity( (Activity)m_MoveAnim.id );
}
else
{
GetNavigator()->SetMovementSequence( m_MoveAnim.id );
}
}
else
{
ChainStartTask( TASK_RUN_PATH );
}
if ( m_EntryAnim.id != ACT_INVALID )
{
Assert( 0 );
}
else if ( m_CoverAnim.id != ACT_INVALID )
{
if ( m_CoverAnim.bActivity )
{
GetNavigator()->SetArrivalActivity( (Activity)m_CoverAnim.id );
}
else
{
GetNavigator()->SetArrivalSequence( m_CoverAnim.id );
}
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CAI_FightFromCoverBehavior::GetAnimation( CScriptScope &scope, const char *pszKey, Animation_t *pAnimation )
{
ScriptVariant_t var;
bool result = false;
// Find the movement activity or sequence
if ( scope.GetValue( pszKey, &var ) )
{
if ( var.m_type == FIELD_CSTRING )
{
pAnimation->bActivity = StringHasPrefixCaseSensitive( var, "ACT_" );
if ( !pAnimation->bActivity )
{
pAnimation->id = GetOuter()->LookupSequence( var );
if ( pAnimation->id < 0 )
{
pAnimation->Reset();
}
}
else
{
pAnimation->id = CAI_BaseNPC::GetActivityID( var );
}
if ( pAnimation->id == ACT_INVALID )
{
DevMsg( "Failed to resolve animation \"%s\"\n", var.m_pszString );
}
}
scope.ReleaseValue( var );
}
return result;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CAI_FightFromCoverBehavior::StartAnimationTask( const Animation_t &animation, bool bReset, Activity defaultActivity )
{
if ( animation.id != ACT_INVALID )
{
if ( animation.bActivity )
{
if ( bReset )
GetOuter()->ResetIdealActivity( (Activity)animation.id );
else
GetOuter()->SetIdealActivity( (Activity)animation.id );
}
else
{
GetOuter()->SetIdealSequence( animation.id, bReset );
}
return true;
}
else
{
if ( bReset )
GetOuter()->SetIdealActivity( defaultActivity );
return false;
}
}
//-----------------------------------------------------------------------------
AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_FightFromCoverBehavior )
DECLARE_CONDITION( COND_FFC_HINT_CHANGE )
DECLARE_TASK( TASK_FFC_GET_PATH_TO_HINT )
DECLARE_TASK( TASK_FFC_COVER )
DECLARE_TASK( TASK_FFC_PEEK )
DECLARE_TASK( TASK_FFC_ATTACK )
//---------------------------------
DEFINE_SCHEDULE
(
SCHED_FFC_RUN_TO_HINT,
" Tasks"
" TASK_FFC_GET_PATH_TO_HINT 0"
" TASK_WAIT_FOR_MOVEMENT 0"
" TASK_SET_SCHEDULE SCHEDULE:SCHED_FFC_HOLD_COVER"
""
" Interrupts"
" COND_FFC_HINT_CHANGE"
)
DEFINE_SCHEDULE
(
SCHED_FFC_HOLD_COVER,
" Tasks"
// " TASK_FACE_HINTNODE 0"
" TASK_FFC_COVER 0"
" TASK_WAIT_RANDOM 2.0"
" TASK_SET_SCHEDULE SCHEDULE:SCHED_FFC_PEEK"
""
" Interrupts"
" COND_FFC_HINT_CHANGE"
" COND_NO_PRIMARY_AMMO"
)
DEFINE_SCHEDULE
(
SCHED_FFC_RELOAD,
" Tasks"
" TASK_RELOAD 0"
" TASK_SET_SCHEDULE SCHEDULE:SCHED_FFC_PEEK"
""
" Interrupts"
)
DEFINE_SCHEDULE
(
SCHED_FFC_PEEK,
" Tasks"
" TASK_FFC_PEEK 0"
" TASK_SET_SCHEDULE SCHEDULE:SCHED_FFC_HOLD_PEEK"
""
" Interrupts"
" COND_NEW_ENEMY"
" COND_CAN_RANGE_ATTACK1"
" COND_FFC_HINT_CHANGE"
)
DEFINE_SCHEDULE
(
SCHED_FFC_HOLD_PEEK,
" Tasks"
" TASK_WAIT_RANDOM 1.0"
" TASK_SET_SCHEDULE SCHEDULE:SCHED_FFC_HOLD_COVER"
""
" Interrupts"
" COND_FFC_HINT_CHANGE"
" COND_NEW_ENEMY"
" COND_CAN_RANGE_ATTACK1"
" COND_NO_PRIMARY_AMMO"
)
DEFINE_SCHEDULE
(
SCHED_FFC_ATTACK,
" Tasks"
" TASK_STOP_MOVING 0"
" TASK_FFC_ATTACK 0"
""
" Interrupts"
" COND_NEW_ENEMY"
" COND_ENEMY_DEAD"
" COND_LIGHT_DAMAGE"
" COND_HEAVY_DAMAGE"
" COND_ENEMY_OCCLUDED"
" COND_NO_PRIMARY_AMMO"
" COND_HEAR_DANGER"
" COND_WEAPON_BLOCKED_BY_FRIEND"
" COND_WEAPON_SIGHT_OCCLUDED"
)
AI_END_CUSTOM_SCHEDULE_PROVIDER()
//-----------------------------------------------------------------------------
//
// CAI_FightFromCoverGoal
//
//-----------------------------------------------------------------------------
BEGIN_DATADESC( CAI_FightFromCoverGoal )
DEFINE_KEYFIELD( m_DirectionalMarker, FIELD_STRING, "DirectionalMarker" ),
DEFINE_KEYFIELD( m_GenericHintType, FIELD_STRING, "GenericHintType" ),
DEFINE_KEYFIELD( m_WidthZone, FIELD_FLOAT, "width" ),
DEFINE_KEYFIELD( m_LengthZone, FIELD_FLOAT, "length" ),
DEFINE_KEYFIELD( m_HeightZone, FIELD_FLOAT, "height" ),
DEFINE_KEYFIELD( m_BiasZone, FIELD_FLOAT, "bias" ),
DEFINE_FIELD( m_vFront, FIELD_POSITION_VECTOR ),
DEFINE_INPUTFUNC( FIELD_EHANDLE, "SetDirectionalMarker", InputSetDirectionalMarker ),
DEFINE_THINKFUNC( FrontThink ),
END_DATADESC()
//-------------------------------------
LINK_ENTITY_TO_CLASS( ai_goal_fightfromcover, CAI_FightFromCoverGoal );
//-------------------------------------
CAI_FightFromCoverGoal::CAI_FightFromCoverGoal()
{
m_vDir.Invalidate();
m_WidthZone = 50*12;
m_LengthZone = 40*12;
m_BiasZone = 5*12;
m_HeightZone = 200*12;
}
//-------------------------------------
const Vector &CAI_FightFromCoverGoal::GetFrontPosition()
{
if ( m_hDirectionalMarker != NULL )
{
return m_vFront;
}
else if ( m_hGoalEntity != NULL )
{
return m_hGoalEntity->GetAbsOrigin();
}
return GetAbsOrigin();
}
//-------------------------------------
const Vector &CAI_FightFromCoverGoal::GetFrontDirection()
{
return m_vDir;
}
//-------------------------------------
const QAngle &CAI_FightFromCoverGoal::GetFrontAngles()
{
if ( m_hDirectionalMarker != NULL )
{
return m_hDirectionalMarker->GetAbsAngles();
}
static QAngle invalid( VEC_T_NAN, VEC_T_NAN, VEC_T_NAN );
return invalid;
}
//-------------------------------------
void CAI_FightFromCoverGoal::BeginMovingFront()
{
if ( m_hDirectionalMarker != NULL )
{
if ( m_hGoalEntity != NULL )
{
if ( !m_pfnThink )
{
SetThink( &CAI_FightFromCoverGoal::FrontThink );
SetNextThink( gpGlobals->curtime + .1 );
}
}
else
{
m_vFront = m_hDirectionalMarker->GetAbsOrigin();
}
}
else
{
EndMovingFront();
}
}
//-------------------------------------
void CAI_FightFromCoverGoal::EndMovingFront()
{
SetThink( NULL );
}
//-------------------------------------
void CAI_FightFromCoverGoal::OnActivate()
{
BeginMovingFront();
}
//-------------------------------------
void CAI_FightFromCoverGoal::OnDeactivate()
{
EndMovingFront();
}
//-------------------------------------
void CAI_FightFromCoverGoal::FrontThink()
{
if ( m_hDirectionalMarker != NULL && m_hGoalEntity != NULL )
{
Vector vClosest;
AngleVectors( m_hDirectionalMarker->GetAbsAngles(), &m_vDir );
CalcClosestPointOnLineSegment( m_hGoalEntity->GetAbsOrigin(), m_vFront, m_vFront + m_vDir * 99999, vClosest );
m_vFront = vClosest;
SetNextThink( gpGlobals->curtime + 0.5 );
}
else
{
EndMovingFront();
}
}
//-------------------------------------
void CAI_FightFromCoverGoal::EnableGoal( CAI_BaseNPC *pAI )
{
CAI_FightFromCoverBehavior *pBehavior;
if ( !pAI->GetBehavior( &pBehavior ) )
return;
CBaseEntity *pGoalEntity = GetGoalEntity();
if ( pGoalEntity )
{
pBehavior->SetGoal( this );
}
}
//-------------------------------------
void CAI_FightFromCoverGoal::DisableGoal( CAI_BaseNPC *pAI )
{
CAI_FightFromCoverBehavior *pBehavior;
if ( !pAI || !pAI->GetBehavior( &pBehavior ) )
return;
pBehavior->ClearGoal();
}
//-------------------------------------
void CAI_FightFromCoverGoal::ResolveNames()
{
BaseClass::ResolveNames();
if ( m_hGoalEntity == NULL && AI_IsSinglePlayer() )
{
m_hGoalEntity = UTIL_GetLocalPlayer();
}
if ( m_DirectionalMarker != NULL_STRING )
{
EHANDLE hDirectionalMarker = gEntList.FindEntityByName( NULL, STRING(m_DirectionalMarker) );
if ( m_hDirectionalMarker != hDirectionalMarker )
{
m_hDirectionalMarker = gEntList.FindEntityByName( NULL, STRING(m_DirectionalMarker) );
m_vFront = m_hDirectionalMarker->GetAbsOrigin();
AngleVectors( m_hDirectionalMarker->GetAbsAngles(), &m_vDir );
}
BeginMovingFront();
}
else
{
m_hDirectionalMarker = NULL;
m_vDir.Invalidate();
EndMovingFront();
}
}
//-------------------------------------
void CAI_FightFromCoverGoal::InputSetDirectionalMarker( inputdata_t &inputdata )
{
m_hDirectionalMarker = inputdata.value.Entity();
if ( m_hDirectionalMarker != NULL )
{
m_DirectionalMarker = m_hDirectionalMarker->GetEntityName();
m_vFront = m_hDirectionalMarker->GetAbsOrigin();
AngleVectors( m_hDirectionalMarker->GetAbsAngles(), &m_vDir );
BeginMovingFront();
}
else
{
m_DirectionalMarker = NULL_STRING;
m_vDir.Invalidate();
EndMovingFront();
}
}
//-------------------------------------
int CAI_FightFromCoverGoal::DrawDebugTextOverlays()
{
int text_offset = BaseClass::DrawDebugTextOverlays();
if ( m_debugOverlays & OVERLAY_TEXT_BIT )
{
CFmtStr str;
if ( m_hDirectionalMarker != NULL )
{
EntityText( text_offset++, str.sprintf( "Dir ent: %s", m_hDirectionalMarker->GetEntityNameAsCStr() ), 0 );
NDebugOverlay::YawArrow( m_hDirectionalMarker->GetAbsOrigin() + Vector( 0, 0, 6 ), m_hDirectionalMarker->GetAbsAngles().y, 60, 6, 255, 255, 255, 0, true, 0 );
NDebugOverlay::Cross3DOriented( m_vFront + Vector( 0, 0, 6 ), m_hDirectionalMarker->GetAbsAngles(), 12, 255, 0, 0, true, 0 );
Vector vBoxDrawCenter;
AngleVectors( m_hDirectionalMarker->GetAbsAngles(), &vBoxDrawCenter );
vBoxDrawCenter *= -m_BiasZone;
vBoxDrawCenter += m_vFront;
NDebugOverlay::BoxAngles( vBoxDrawCenter, Vector( -(m_LengthZone/2), -(m_WidthZone/2), -(m_HeightZone/2) ), Vector( m_LengthZone/2, m_WidthZone/2, m_HeightZone/2 ), m_hDirectionalMarker->GetAbsAngles(), 255, 0, 0, 16, 0 );
for ( int i = 0; i < m_actors.Count(); i++ )
{
if ( m_actors[i] != NULL )
{
NDebugOverlay::Line( m_vFront, m_actors[i]->WorldSpaceCenter(), 0, 0, 127, true, 0 );
}
}
}
if ( m_hGoalEntity != NULL )
{
EntityText( text_offset++, str.sprintf( "Front ent: %s", m_hGoalEntity->GetEntityNameAsCStr() ), 0 );
}
}
return text_offset;
}