📄 hl1_npc_controller.cpp
字号:
CBroadcastRecipientFilter filter;
te->DynamicLight( filter, 0.0, &vecStart, 255, 192, 64, 0, 1 /*radius*/, 0.2, -32 );
m_iBall[0] = 192;
m_iBallTime[0] = gpGlobals->curtime + atoi( pEvent->options ) / 15.0;
m_iBall[1] = 255;
m_iBallTime[1] = gpGlobals->curtime + atoi( pEvent->options ) / 15.0;
}
break;
case CONTROLLER_AE_BALL_SHOOT:
{
Vector vecStart;
QAngle angleGun;
GetAttachment( 1, vecStart, angleGun );
CBroadcastRecipientFilter filter;
te->DynamicLight( filter, 0.0, &vecStart, 255, 192, 64, 0, 1 /*radius*/, 0.1, 32 );
CAI_BaseNPC *pBall = (CAI_BaseNPC*)Create( "controller_head_ball", vecStart, angleGun );
pBall->SetAbsVelocity( Vector(0,0,32) );
pBall->SetEnemy( GetEnemy() );
// DevMsg( 1, "controller shooting head ball\n" );
m_iBall[0] = 0;
m_iBall[1] = 0;
}
break;
case CONTROLLER_AE_SMALL_SHOOT:
{
AttackSound( );
m_flShootTime = gpGlobals->curtime;
m_flShootEnd = m_flShootTime + atoi( pEvent->options ) / 15.0;
}
break;
case CONTROLLER_AE_POWERUP_FULL:
{
m_iBall[0] = 255;
m_iBallTime[0] = gpGlobals->curtime + atoi( pEvent->options ) / 15.0;
m_iBall[1] = 255;
m_iBallTime[1] = gpGlobals->curtime + atoi( pEvent->options ) / 15.0;
}
break;
case CONTROLLER_AE_POWERUP_HALF:
{
m_iBall[0] = 192;
m_iBallTime[0] = gpGlobals->curtime + atoi( pEvent->options ) / 15.0;
m_iBall[1] = 192;
m_iBallTime[1] = gpGlobals->curtime + atoi( pEvent->options ) / 15.0;
}
break;
default:
BaseClass::HandleAnimEvent( pEvent );
break;
}
}
//=========================================================
// AI Schedules Specific to this monster
//=========================================================
AI_BEGIN_CUSTOM_NPC( monster_alien_controller, CNPC_Controller )
//declare our tasks
DECLARE_TASK( TASK_CONTROLLER_CHASE_ENEMY )
DECLARE_TASK( TASK_CONTROLLER_STRAFE )
DECLARE_TASK( TASK_CONTROLLER_TAKECOVER )
DECLARE_TASK( TASK_CONTROLLER_FAIL )
//=========================================================
// > SCHED_CONTROLLER_CHASE_ENEMY
//=========================================================
DEFINE_SCHEDULE
(
SCHED_CONTROLLER_CHASE_ENEMY,
" Tasks"
" TASK_GET_PATH_TO_ENEMY 128"
" TASK_WAIT_FOR_MOVEMENT 0"
" "
" Interrupts"
" COND_NEW_ENEMY"
" COND_TASK_FAILED"
)
//=========================================================
// > SCHED_CONTROLLER_STRAFE
//=========================================================
DEFINE_SCHEDULE
(
SCHED_CONTROLLER_STRAFE,
" Tasks"
" TASK_WAIT 0.2"
" TASK_GET_PATH_TO_ENEMY 128"
" TASK_WAIT_FOR_MOVEMENT 0"
" TASK_WAIT 1"
" "
" Interrupts"
" COND_NEW_ENEMY"
)
//=========================================================
// > SCHED_CONTROLLER_TAKECOVER
//=========================================================
DEFINE_SCHEDULE
(
SCHED_CONTROLLER_TAKECOVER,
" Tasks"
" TASK_WAIT 0.2"
" TASK_FIND_COVER_FROM_ENEMY 0"
" TASK_WAIT_FOR_MOVEMENT 0"
" TASK_WAIT 1"
" "
" Interrupts"
" COND_NEW_ENEMY"
)
//=========================================================
// > SCHED_CONTROLLER_FAIL
//=========================================================
DEFINE_SCHEDULE
(
SCHED_CONTROLLER_FAIL,
" Tasks"
" TASK_STOP_MOVING 0"
" TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE"
" TASK_WAIT 2"
" TASK_WAIT_PVS 0"
)
AI_END_CUSTOM_NPC()
//=========================================================
// StartTask
//=========================================================
void CNPC_Controller::StartTask( const Task_t *pTask )
{
BaseClass::StartTask( pTask );
}
Vector Intersect( Vector vecSrc, Vector vecDst, Vector vecMove, float flSpeed )
{
Vector vecTo = vecDst - vecSrc;
float a = DotProduct( vecMove, vecMove ) - flSpeed * flSpeed;
float b = 0 * DotProduct(vecTo, vecMove); // why does this work?
float c = DotProduct( vecTo, vecTo );
float t;
if (a == 0)
{
t = c / (flSpeed * flSpeed);
}
else
{
t = b * b - 4 * a * c;
t = sqrt( t ) / (2.0 * a);
float t1 = -b +t;
float t2 = -b -t;
if (t1 < 0 || t2 < t1)
t = t2;
else
t = t1;
}
if (t < 0.1)
t = 0.1;
if (t > 10.0)
t = 10.0;
Vector vecHit = vecTo + vecMove * t;
VectorNormalize( vecHit );
return vecHit * flSpeed;
}
int CNPC_Controller::LookupFloat( )
{
if (m_velocity.Length( ) < 32.0)
{
return LookupSequence( "up" );
}
Vector vecForward, vecRight, vecUp;
AngleVectors( GetAbsAngles(), &vecForward, &vecRight, &vecUp );
float x = DotProduct( vecForward, m_velocity );
float y = DotProduct( vecRight, m_velocity );
float z = DotProduct( vecUp, m_velocity );
if (fabs(x) > fabs(y) && fabs(x) > fabs(z))
{
if (x > 0)
return LookupSequence( "forward");
else
return LookupSequence( "backward");
}
else if (fabs(y) > fabs(z))
{
if (y > 0)
return LookupSequence( "right");
else
return LookupSequence( "left");
}
else
{
if (z > 0)
return LookupSequence( "up");
else
return LookupSequence( "down");
}
}
//=========================================================
// RunTask
//=========================================================
void CNPC_Controller::RunTask ( const Task_t *pTask )
{
if (m_flShootEnd > gpGlobals->curtime)
{
Vector vecHand;
QAngle vecAngle;
GetAttachment( 2, vecHand, vecAngle );
while (m_flShootTime < m_flShootEnd && m_flShootTime < gpGlobals->curtime)
{
Vector vecSrc = vecHand + GetAbsVelocity() * (m_flShootTime - gpGlobals->curtime);
Vector vecDir;
if (GetEnemy() != NULL)
{
if (HasCondition( COND_SEE_ENEMY ))
{
m_vecEstVelocity = m_vecEstVelocity * 0.5 + GetEnemy()->GetAbsVelocity() * 0.5;
}
else
{
m_vecEstVelocity = m_vecEstVelocity * 0.8;
}
vecDir = Intersect( vecSrc, GetEnemy()->BodyTarget( GetAbsOrigin() ), m_vecEstVelocity, sk_controller_speedball.GetFloat() );
float delta = 0.03490; // +-2 degree
vecDir = vecDir + Vector( random->RandomFloat( -delta, delta ), random->RandomFloat( -delta, delta ), random->RandomFloat( -delta, delta ) ) * sk_controller_speedball.GetFloat();
vecSrc = vecSrc + vecDir * (gpGlobals->curtime - m_flShootTime);
CAI_BaseNPC *pBall = (CAI_BaseNPC*)Create( "controller_energy_ball", vecSrc, GetAbsAngles(), this );
pBall->SetAbsVelocity( vecDir );
// DevMsg( 2, "controller shooting energy ball\n" );
}
m_flShootTime += 0.2;
}
if (m_flShootTime > m_flShootEnd)
{
m_iBall[0] = 64;
m_iBallTime[0] = m_flShootEnd;
m_iBall[1] = 64;
m_iBallTime[1] = m_flShootEnd;
m_fInCombat = FALSE;
}
}
switch ( pTask->iTask )
{
case TASK_WAIT_FOR_MOVEMENT:
case TASK_WAIT:
case TASK_WAIT_FACE_ENEMY:
case TASK_WAIT_PVS:
{
if( GetEnemy() )
{
float idealYaw = UTIL_VecToYaw( GetEnemy()->GetAbsOrigin() - GetAbsOrigin() );
GetMotor()->SetIdealYawAndUpdate( idealYaw );
}
if ( IsSequenceFinished() || GetActivity() == ACT_IDLE)
{
m_fInCombat = false;
}
BaseClass::RunTask ( pTask );
if (!m_fInCombat)
{
if( HasCondition( COND_CAN_RANGE_ATTACK1 ))
{
SetActivity( ACT_RANGE_ATTACK1 );
m_flCycle = 0;
ResetSequenceInfo( );
m_fInCombat = true;
}
else if( HasCondition( COND_CAN_RANGE_ATTACK2 ) )
{
SetActivity( ACT_RANGE_ATTACK2 );
m_flCycle = 0;
ResetSequenceInfo( );
m_fInCombat = true;
}
else
{
int iFloat = LookupFloat();
if( IsSequenceFinished() || iFloat != GetSequence() )
{
SetSequence( iFloat );
m_flCycle = 0;
ResetSequenceInfo( );
}
}
}
}
break;
default:
BaseClass::RunTask ( pTask );
break;
}
}
void CNPC_Controller::SetSequence( int nSequence )
{
int x;
x = 4;
BaseClass::SetSequence( nSequence );
}
//=========================================================
//=========================================================
int CNPC_Controller::TranslateSchedule( int scheduleType )
{
switch ( scheduleType )
{
case SCHED_CHASE_ENEMY:
return SCHED_CONTROLLER_CHASE_ENEMY;
case SCHED_RANGE_ATTACK1:
return SCHED_CONTROLLER_STRAFE;
case SCHED_RANGE_ATTACK2:
case SCHED_MELEE_ATTACK1:
case SCHED_MELEE_ATTACK2:
case SCHED_TAKE_COVER_FROM_ENEMY:
return SCHED_CONTROLLER_TAKECOVER;
case SCHED_FAIL:
return SCHED_CONTROLLER_FAIL;
default:
break;
}
return BaseClass::TranslateSchedule( scheduleType );
}
//=========================================================
// CheckRangeAttack1 - shoot a bigass energy ball out of their head
//=========================================================
int CNPC_Controller::RangeAttack1Conditions ( float flDot, float flDist )
{
if( flDist > 2048 )
{
return COND_TOO_FAR_TO_ATTACK;
}
if( flDist <= 256 )
{
return COND_TOO_CLOSE_TO_ATTACK;
}
// if( flDot <= 0.5 )
// {
// return COND_NOT_FACING_ATTACK;
// }
return COND_CAN_RANGE_ATTACK1;
}
//=========================================================
// CheckRangeAttack1 - head
//=========================================================
int CNPC_Controller::RangeAttack2Conditions ( float flDot, float flDist )
{
if( flDist > 2048 )
{
return COND_TOO_FAR_TO_ATTACK;
}
if( flDist <= 64 )
{
return COND_TOO_CLOSE_TO_ATTACK;
}
// if( flDot <= 0.5 )
// {
// return COND_NOT_FACING_ATTACK;
// }
return COND_CAN_RANGE_ATTACK2;
}
//=========================================================
// SetActivity -
//=========================================================
void CNPC_Controller::SetActivity ( Activity NewActivity )
{
BaseClass::SetActivity( NewActivity );
m_flGroundSpeed = 100;
}
//=========================================================
// RunAI
//=========================================================
void CNPC_Controller::RunAI( void )
{
BaseClass::RunAI();
Vector vecStart;
QAngle angleGun;
//some kind of hack in hl1 ?
// if ( HasMemory( bits_MEMORY_KILLED ) )
//use this instead
if( !IsAlive() )
return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -