📄 hl1_npc_hassassin.cpp
字号:
m_iFrustration = 0;
return SCHED_RANGE_ATTACK1;
}
if ( HasCondition ( COND_SEE_ENEMY ) )
{
//Msg( "face\n");
return SCHED_COMBAT_FACE;
}
// new enemy
if ( HasCondition ( COND_NEW_ENEMY ) )
{
//Msg( "take cover\n");
return SCHED_TAKE_COVER_FROM_ENEMY;
}
// ALERT( at_console, "stand\n");
return SCHED_ALERT_STAND;
}
break;
}
return BaseClass::SelectSchedule();
}
//=========================================================
// HandleAnimEvent - catches the monster-specific messages
// that occur when tagged animation frames are played.
//
// Returns number of events handled, 0 if none.
//=========================================================
void CNPC_HAssassin::HandleAnimEvent( animevent_t *pEvent )
{
switch( pEvent->event )
{
case ASSASSIN_AE_SHOOT1:
Shoot( );
break;
case ASSASSIN_AE_TOSS1:
{
Vector vTossPos;
QAngle vAngles;
GetAttachment( "grenadehand", vTossPos, vAngles );
CHL1BaseGrenade *pGrenade = (CHL1BaseGrenade*)CreateNoSpawn( "npc_handgrenade", vTossPos, vec3_angle, this );
pGrenade->SetAbsVelocity( m_vecTossVelocity );
pGrenade->m_flDetonateTime = gpGlobals->curtime + 2.0;
pGrenade->Spawn( );
pGrenade->SetOwner( this );
pGrenade->SetOwnerEntity( this );
pGrenade->SetGravity( 0.5 );
m_flNextGrenadeCheck = gpGlobals->curtime + 6;// wait six seconds before even looking again to see if a grenade can be thrown.
m_fThrowGrenade = FALSE;
// !!!LATER - when in a group, only try to throw grenade if ordered.
}
break;
case ASSASSIN_AE_JUMP:
{
SetMoveType( MOVETYPE_FLYGRAVITY );
RemoveFlag( FL_ONGROUND );
SetAbsVelocity( m_vecJumpVelocity );
m_flNextJump = gpGlobals->curtime + 3.0;
}
return;
default:
BaseClass::HandleAnimEvent( pEvent );
break;
}
}
//=========================================================
// Shoot
//=========================================================
void CNPC_HAssassin::Shoot ( void )
{
Vector vForward, vRight, vUp;
Vector vecShootOrigin;
QAngle vAngles;
if ( GetEnemy() == NULL)
{
return;
}
GetAttachment( "guntip", vecShootOrigin, vAngles );
Vector vecShootDir = GetShootEnemyDir( vecShootOrigin );
if (m_flLastShot + 2 < gpGlobals->curtime)
{
m_flDiviation = 0.10;
}
else
{
m_flDiviation -= 0.01;
if (m_flDiviation < 0.02)
m_flDiviation = 0.02;
}
m_flLastShot = gpGlobals->curtime;
AngleVectors( GetAbsAngles(), &vForward, &vRight, &vUp );
Vector vecShellVelocity = vRight * random->RandomFloat(40,90) + vUp * random->RandomFloat(75,200) + vForward * random->RandomFloat(-40, 40);
//EjectBrass ( pev->origin + gpGlobals->v_up * 32 + gpGlobals->v_forward * 12, vecShellVelocity, pev->angles.y, m_iShell, TE_BOUNCE_SHELL);
FireBullets( 1, vecShootOrigin, vecShootDir, Vector( m_flDiviation, m_flDiviation, m_flDiviation ), 2048, m_iAmmoType ); // shoot +-8 degrees
//NDebugOverlay::Line( vecShootOrigin, vecShootOrigin + vecShootDir * 2048, 255, 0, 0, true, 2.0 );
CPASAttenuationFilter filter( this );
switch( random->RandomInt( 0, 1 ))
{
case 0:
enginesound->EmitSound( filter, entindex(), CHAN_WEAPON, "weapons/pl_gun1.wav", random->RandomFloat(0.6, 0.8), ATTN_NORM );
break;
case 1:
enginesound->EmitSound( filter, entindex(), CHAN_WEAPON, "weapons/pl_gun2.wav", random->RandomFloat(0.6, 0.8), ATTN_NORM );
break;
}
m_fEffects |= EF_MUZZLEFLASH;
VectorAngles( vecShootDir, vAngles );
SetPoseParameter( "shoot", vecShootDir.x );
m_cAmmoLoaded--;
}
//=========================================================
//=========================================================
int CNPC_HAssassin::TranslateSchedule ( int scheduleType )
{
// Msg( "%d\n", m_iFrustration );
switch ( scheduleType )
{
case SCHED_TAKE_COVER_FROM_ENEMY:
if ( m_iHealth > 30 )
return SCHED_ASSASSIN_TAKE_COVER_FROM_ENEMY1;
else
return SCHED_ASSASSIN_TAKE_COVER_FROM_ENEMY2;
case SCHED_TAKE_COVER_FROM_BEST_SOUND:
return SCHED_ASSASSIN_TAKE_COVER_FROM_BEST_SOUND;
case SCHED_FAIL:
if ( m_NPCState == NPC_STATE_COMBAT )
return SCHED_ASSASSIN_FAIL;
break;
case SCHED_ALERT_STAND:
if ( m_NPCState == NPC_STATE_COMBAT )
return SCHED_ASSASSIN_HIDE;
break;
//case SCHED_CHASE_ENEMY:
// return SCHED_ASSASSIN_HUNT;
case SCHED_MELEE_ATTACK1:
if ( GetFlags() & FL_ONGROUND)
{
if (m_flNextJump > gpGlobals->curtime)
{
// can't jump yet, go ahead and fail
return SCHED_ASSASSIN_FAIL;
}
else
{
return SCHED_ASSASSIN_JUMP;
}
}
else
{
return SCHED_ASSASSIN_JUMP_ATTACK;
}
}
return BaseClass::TranslateSchedule( scheduleType );
}
//=========================================================
// RunAI
//=========================================================
void CNPC_HAssassin::RunAI( void )
{
BaseClass::RunAI();
// always visible if moving
// always visible is not on hard
if (g_iSkillLevel != SKILL_HARD || GetEnemy() == NULL || m_lifeState == LIFE_DEAD || GetActivity() == ACT_RUN || GetActivity() == ACT_WALK || !(GetFlags() & FL_ONGROUND))
m_iTargetRanderamt = 255;
else
m_iTargetRanderamt = 20;
CPASAttenuationFilter filter( this );
if ( GetRenderColor().a > m_iTargetRanderamt)
{
if ( GetRenderColor().a == 255)
{
enginesound->EmitSound( filter, entindex(), CHAN_BODY, "debris/beamstart1.wav", 0.2, ATTN_NORM );
}
SetRenderColorA( max( GetRenderColor().a - 50, m_iTargetRanderamt ) );
m_nRenderMode = kRenderTransTexture;
}
else if ( GetRenderColor().a < m_iTargetRanderamt)
{
SetRenderColorA ( min( GetRenderColor().a + 50, m_iTargetRanderamt ) );
if (GetRenderColor().a == 255)
m_nRenderMode = kRenderNormal;
}
if ( GetActivity() == ACT_RUN || GetActivity() == ACT_WALK)
{
static int iStep = 0;
iStep = ! iStep;
if (iStep)
{
switch( random->RandomInt( 0, 3 ) )
{
case 0: enginesound->EmitSound( filter, entindex(), CHAN_BODY, "player/pl_step1.wav", 0.5, ATTN_NORM ); break;
case 1: enginesound->EmitSound( filter, entindex(), CHAN_BODY, "player/pl_step3.wav", 0.5, ATTN_NORM ); break;
case 2: enginesound->EmitSound( filter, entindex(), CHAN_BODY, "player/pl_step2.wav", 0.5, ATTN_NORM ); break;
case 3: enginesound->EmitSound( filter, entindex(), CHAN_BODY, "player/pl_step4.wav", 0.5, ATTN_NORM ); break;
}
}
}
}
AI_BEGIN_CUSTOM_NPC( monster_human_assassin, CNPC_HAssassin )
DECLARE_TASK( TASK_ASSASSIN_FALL_TO_GROUND )
DECLARE_ACTIVITY( ACT_ASSASSIN_FLY_UP )
DECLARE_ACTIVITY( ACT_ASSASSIN_FLY_ATTACK )
DECLARE_ACTIVITY( ACT_ASSASSIN_FLY_DOWN )
//=========================================================
// AI Schedules Specific to this monster
//=========================================================
//=========================================================
// Enemy exposed assasin's cover
//=========================================================
//=========================================================
// > SCHED_ASSASSIN_EXPOSED
//=========================================================
DEFINE_SCHEDULE
(
SCHED_ASSASSIN_EXPOSED,
" Tasks"
" TASK_STOP_MOVING 0"
" TASK_RANGE_ATTACK1 0"
" TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ASSASSIN_JUMP"
" TASK_SET_SCHEDULE SCHEDULE:SCHED_TAKE_COVER_FROM_ENEMY"
" "
" Interrupts"
" COND_CAN_MELEE_ATTACK1"
)
//=========================================================
// > SCHED_ASSASSIN_JUMP
//=========================================================
DEFINE_SCHEDULE
(
SCHED_ASSASSIN_JUMP,
" Tasks"
" TASK_STOP_MOVING 0"
" TASK_PLAY_SEQUENCE ACTIVITY:ACT_HOP"
" TASK_SET_SCHEDULE SCHEDULE:SCHED_ASSASSIN_JUMP_ATTACK"
" "
" Interrupts"
)
//=========================================================
// > SCHED_ASSASSIN_JUMP_ATTACK
//=========================================================
DEFINE_SCHEDULE
(
SCHED_ASSASSIN_JUMP_ATTACK,
" Tasks"
" TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ASSASSIN_JUMP_LAND"
" TASK_ASSASSIN_FALL_TO_GROUND 0"
" "
" Interrupts"
)
//=========================================================
// > SCHED_ASSASSIN_JUMP_LAND
//=========================================================
DEFINE_SCHEDULE
(
SCHED_ASSASSIN_JUMP_LAND,
" Tasks"
" TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ASSASSIN_EXPOSED"
" TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE"
" TASK_REMEMBER MEMORY:CUSTOM1"
" TASK_FIND_NODE_COVER_FROM_ENEMY 0"
" TASK_RUN_PATH 0"
" TASK_FORGET MEMORY:CUSTOM1"
" TASK_WAIT_FOR_MOVEMENT 0"
" TASK_REMEMBER MEMORY:INCOVER"
" TASK_FACE_ENEMY 0"
" TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_RANGE_ATTACK1"
" "
" Interrupts"
)
//=========================================================
// Fail Schedule
//=========================================================
//=========================================================
// > SCHED_ASSASSIN_FAIL
//=========================================================
DEFINE_SCHEDULE
(
SCHED_ASSASSIN_FAIL,
" Tasks"
" TASK_STOP_MOVING 0"
" TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE"
" TASK_WAIT_FACE_ENEMY 2"
" TASK_SET_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY"
" "
" Interrupts"
" COND_LIGHT_DAMAGE"
" COND_HEAVY_DAMAGE"
" COND_CAN_RANGE_ATTACK1"
" COND_CAN_RANGE_ATTACK2"
" COND_CAN_MELEE_ATTACK1"
" COND_HEAR_DANGER"
" COND_HEAR_PLAYER"
)
//=========================================================
// > SCHED_ASSASSIN_TAKE_COVER_FROM_ENEMY1
//=========================================================
DEFINE_SCHEDULE
(
SCHED_ASSASSIN_TAKE_COVER_FROM_ENEMY1,
" Tasks"
" TASK_STOP_MOVING 0"
" TASK_WAIT 0.2"
" TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_RANGE_ATTACK1"
" TASK_FIND_COVER_FROM_ENEMY 0"
" TASK_RUN_PATH 0"
" TASK_WAIT_FOR_MOVEMENT 0"
" TASK_REMEMBER MEMORY:INCOVER"
" TASK_FACE_ENEMY 0"
" "
" Interrupts"
" COND_CAN_MELEE_ATTACK1"
" COND_NEW_ENEMY"
" COND_HEAR_DANGER"
)
//=========================================================
// > SCHED_ASSASSIN_TAKE_COVER_FROM_ENEMY2
//=========================================================
DEFINE_SCHEDULE
(
SCHED_ASSASSIN_TAKE_COVER_FROM_ENEMY2,
" Tasks"
" TASK_STOP_MOVING 0"
" TASK_WAIT 0.2"
" TASK_FACE_ENEMY 0"
" TASK_RANGE_ATTACK1 0"
" TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_RANGE_ATTACK1"
" TASK_FIND_COVER_FROM_ENEMY 0"
" TASK_RUN_PATH 0"
" TASK_WAIT_FOR_MOVEMENT 0"
" TASK_REMEMBER MEMORY:INCOVER"
" TASK_FACE_ENEMY 0"
" "
" Interrupts"
" COND_CAN_MELEE_ATTACK1"
" COND_NEW_ENEMY"
" COND_HEAR_DANGER"
)
//=========================================================
// hide from the loudest sound source
//=========================================================
//=========================================================
// > SCHED_ASSASSIN_TAKE_COVER_FROM_BEST_SOUND
//=========================================================
DEFINE_SCHEDULE
(
SCHED_ASSASSIN_TAKE_COVER_FROM_BEST_SOUND,
" Tasks"
" TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_MELEE_ATTACK1"
" TASK_STOP_MOVING 0"
" TASK_FIND_COVER_FROM_BEST_SOUND 0"
" TASK_RUN_PATH 0"
" TASK_WAIT_FOR_MOVEMENT 0"
" TASK_REMEMBER MEMORY:INCOVER"
" TASK_TURN_LEFT 179"
" "
" Interrupts"
" COND_NEW_ENEMY"
)
//=========================================================
// > SCHED_ASSASSIN_HIDE
//=========================================================
DEFINE_SCHEDULE
(
SCHED_ASSASSIN_HIDE,
" Tasks"
" TASK_STOP_MOVING 0"
" TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE"
" TASK_WAIT 2.0"
" TASK_SET_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY"
" Interrupts"
" COND_NEW_ENEMY"
" COND_SEE_ENEMY"
" COND_SEE_FEAR"
" COND_LIGHT_DAMAGE"
" COND_HEAVY_DAMAGE"
" COND_PROVOKED"
" COND_HEAR_DANGER"
)
//=========================================================
// > SCHED_ASSASSIN_HUNT
//=========================================================
DEFINE_SCHEDULE
(
SCHED_ASSASSIN_HUNT,
" Tasks"
" TASK_STOP_MOVING 0"
" TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ASSASSIN_TAKE_COVER_FROM_ENEMY2"
" TASK_GET_PATH_TO_ENEMY 0"
" TASK_RUN_PATH 0"
" TASK_WAIT_FOR_MOVEMENT 0"
" Interrupts"
" COND_NEW_ENEMY"
" COND_CAN_RANGE_ATTACK1"
" COND_HEAR_DANGER"
)
AI_END_CUSTOM_NPC()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -