📄 hl1_npc_hgrunt.cpp
字号:
case 2: // statement
SENTENCEG_PlayRndSz( edict(), "HG_IDLE", HGRUNT_SENTENCE_VOLUME, SNDLVL_NORM, 0, m_voicePitch);
break;
}
}
else
{
switch (g_fGruntQuestion)
{
case 1: // check in
SENTENCEG_PlayRndSz( edict(), "HG_CLEAR", HGRUNT_SENTENCE_VOLUME, SNDLVL_NORM, 0, m_voicePitch);
break;
case 2: // question
SENTENCEG_PlayRndSz( edict(), "HG_ANSWER", HGRUNT_SENTENCE_VOLUME, SNDLVL_NORM, 0, m_voicePitch);
break;
}
g_fGruntQuestion = 0;
}
JustSpoke();
}
}
bool CNPC_HGrunt::HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt)
{
if (interactionType == g_interactionBarnacleVictimDangle)
{
// Force choosing of a new schedule
ClearSchedule();
m_bInBarnacleMouth = true;
return true;
}
else if ( interactionType == g_interactionBarnacleVictimReleased )
{
SetState ( NPC_STATE_IDLE );
m_bInBarnacleMouth = false;
SetAbsVelocity( vec3_origin );
SetMoveType( MOVETYPE_STEP );
return true;
}
else if ( interactionType == g_interactionBarnacleVictimGrab )
{
if ( GetFlags() & FL_ONGROUND )
{
RemoveFlag( FL_ONGROUND );
}
//Maybe this will break something else.
if ( GetState() == NPC_STATE_SCRIPT )
{
m_hCine->CancelScript();
ClearSchedule();
}
SetState( NPC_STATE_PRONE );
PainSound();
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose: Combine needs to check ammo
// Input :
// Output :
//-----------------------------------------------------------------------------
void CNPC_HGrunt::CheckAmmo ( void )
{
if ( m_cAmmoLoaded <= 0 )
SetCondition( COND_NO_PRIMARY_AMMO );
}
//=========================================================
//=========================================================
CBaseEntity *CNPC_HGrunt::Kick( void )
{
trace_t tr;
Vector forward;
AngleVectors( GetAbsAngles(), &forward );
Vector vecStart = GetAbsOrigin();
vecStart.z += WorldAlignSize().z * 0.5;
Vector vecEnd = vecStart + (forward * 70);
UTIL_TraceHull( vecStart, vecEnd, Vector(-16,-16,-18), Vector(16,16,18), MASK_SHOT_HULL, this, COLLISION_GROUP_NONE, &tr );
if ( tr.m_pEnt )
{
CBaseEntity *pEntity = tr.m_pEnt;
return pEntity;
}
return NULL;
}
Vector CNPC_HGrunt::Weapon_ShootPosition( void )
{
if ( m_fStanding )
return GetAbsOrigin() + Vector( 0, 0, 60 );
else
return GetAbsOrigin() + Vector( 0, 0, 48 );
}
void CNPC_HGrunt::Event_Killed( const CTakeDamageInfo &info )
{
Vector vecGunPos;
QAngle vecGunAngles;
GetAttachment( "0", vecGunPos, vecGunAngles );
// switch to body group with no gun.
SetBodygroup( GUN_GROUP, GUN_NONE );
// now spawn a gun.
if (FBitSet( m_iWeapons, HGRUNT_SHOTGUN ))
{
DropItem( "weapon_shotgun", vecGunPos, vecGunAngles );
}
else
{
DropItem( "weapon_mp5", vecGunPos, vecGunAngles );
}
if (FBitSet( m_iWeapons, HGRUNT_GRENADELAUNCHER ))
{
DropItem( "ammo_ARgrenades", BodyTarget( GetAbsOrigin() ), vecGunAngles );
}
BaseClass::Event_Killed( info );
}
//=========================================================
// HandleAnimEvent - catches the monster-specific messages
// that occur when tagged animation frames are played.
//=========================================================
void CNPC_HGrunt::HandleAnimEvent( animevent_t *pEvent )
{
Vector vecShootDir;
Vector vecShootOrigin;
switch( pEvent->event )
{
case HGRUNT_AE_RELOAD:
{
CPASAttenuationFilter filter( this );
enginesound->EmitSound( filter, entindex(), CHAN_WEAPON, "hgrunt/gr_reload1.wav", 1, ATTN_NORM );
m_cAmmoLoaded = m_iClipSize;
ClearCondition( COND_NO_PRIMARY_AMMO);
}
break;
case HGRUNT_AE_GREN_TOSS:
{
CHandGrenade *pGrenade = (CHandGrenade*)CreateNoSpawn( "grenade_hand", GetAbsOrigin() + Vector(0,0,60), vec3_angle, this );
// alway explode 3 seconds after the pin was pulled
pGrenade->m_flDetonateTime = gpGlobals->curtime + 3.5;
pGrenade->Spawn( );
pGrenade->SetOwner( this );
pGrenade->SetOwnerEntity( this );
pGrenade->SetGravity( 0.5 );
pGrenade->SetAbsVelocity( m_vecTossVelocity );
pGrenade->SetDamage( sk_plr_dmg_grenade.GetFloat() );
pGrenade->SetDamageRadius( pGrenade->GetDamage() * 2.5 );
m_iLastGrenadeCondition = COND_NONE;
m_flNextGrenadeCheck = gpGlobals->curtime + 6;// wait six seconds before even looking again to see if a grenade can be thrown.
Msg( this, "Tossing a grenade to flush you out!\n" );
}
break;
case HGRUNT_AE_GREN_LAUNCH:
{
CPASAttenuationFilter filter2( this );
enginesound->EmitSound( filter2, entindex(), CHAN_WEAPON, "weapons/glauncher.wav", 0.8, ATTN_NORM );
Vector vecSrc;
QAngle angAngles;
GetAttachment( "0", vecSrc, angAngles );
CGrenadeMP5 * m_pMyGrenade = (CGrenadeMP5*)Create( "grenade_mp5", vecSrc, angAngles, this );
m_pMyGrenade->SetAbsVelocity( m_vecTossVelocity );
m_pMyGrenade->SetLocalAngularVelocity( QAngle( random->RandomFloat( -100, -500 ), 0, 0 ) );
m_pMyGrenade->SetMoveType( MOVETYPE_FLYGRAVITY );
m_pMyGrenade->SetOwner( this );
m_pMyGrenade->SetDamage( sk_plr_dmg_mp5_grenade.GetFloat() );
if (g_iSkillLevel == SKILL_HARD)
m_flNextGrenadeCheck = gpGlobals->curtime + random->RandomFloat( 2, 5 );// wait a random amount of time before shooting again
else
m_flNextGrenadeCheck = gpGlobals->curtime + 6;// wait six seconds before even looking again to see if a grenade can be thrown.
m_iLastGrenadeCondition = COND_NONE;
Msg( this, "Using grenade launcer to flush you out!\n" );
}
break;
case HGRUNT_AE_GREN_DROP:
{
CBaseGrenade *pGrenade = (CBaseGrenade*)CreateNoSpawn( "grenade_hand", Weapon_ShootPosition(), vec3_angle, this );
pGrenade->SetAbsVelocity( m_vecTossVelocity );
pGrenade->m_flDetonateTime = gpGlobals->curtime + 3.5;
pGrenade->Spawn( );
pGrenade->SetOwner( this );
pGrenade->SetOwnerEntity( this );
m_iLastGrenadeCondition = COND_NONE;
Msg( this, "Dropping a grenade!\n" );
}
break;
case HGRUNT_AE_BURST1:
{
if ( FBitSet( m_iWeapons, HGRUNT_9MMAR ) )
{
Shoot();
CPASAttenuationFilter filter3( this );
// the first round of the three round burst plays the sound and puts a sound in the world sound list.
if ( random->RandomInt(0,1) )
{
enginesound->EmitSound( filter3, entindex(), CHAN_WEAPON, "hgrunt/gr_mgun1.wav", 1, ATTN_NORM );
}
else
{
enginesound->EmitSound( filter3, entindex(), CHAN_WEAPON, "hgrunt/gr_mgun2.wav", 1, ATTN_NORM );
}
}
else
{
Shotgun( );
CPASAttenuationFilter filter4( this );
enginesound->EmitSound( filter4, entindex(), CHAN_WEAPON, "weapons/sbarrel1.wav", 1, ATTN_NORM );
}
CSoundEnt::InsertSound ( SOUND_COMBAT, GetAbsOrigin(), 384, 0.3 );
}
break;
case HGRUNT_AE_BURST2:
case HGRUNT_AE_BURST3:
Shoot();
break;
case HGRUNT_AE_KICK:
{
CBaseEntity *pHurt = Kick();
if ( pHurt )
{
// SOUND HERE!
Vector forward, up;
AngleVectors( GetAbsAngles(), &forward, NULL, &up );
if ( pHurt->GetFlags() & ( FL_NPC | FL_CLIENT ) )
pHurt->ViewPunch( QAngle( 15, 0, 0) );
pHurt->SetAbsVelocity( pHurt->GetAbsVelocity() + forward * 100 + up * 50 );
CTakeDamageInfo info( this, this, sk_hgrunt_kick.GetFloat(), DMG_CLUB );
CalculateMeleeDamageForce( &info, forward, pHurt->GetAbsOrigin() );
pHurt->TakeDamage( info );
}
}
break;
case HGRUNT_AE_CAUGHT_ENEMY:
{
if ( FOkToSpeak() )
{
SENTENCEG_PlayRndSz( edict(), "HG_ALERT", HGRUNT_SENTENCE_VOLUME, GRUNT_SNDLVL, 0, m_voicePitch);
JustSpoke();
}
}
default:
BaseClass::HandleAnimEvent( pEvent );
break;
}
}
void CNPC_HGrunt::SetAim( const Vector &aimDir )
{
QAngle angDir;
VectorAngles( aimDir, angDir );
float curPitch = GetPoseParameter( "XR" );
float newPitch = curPitch + UTIL_AngleDiff( UTIL_ApproachAngle( angDir.x, curPitch, 60 ), curPitch );
SetPoseParameter( "XR", -newPitch );
}
//=========================================================
// Shoot
//=========================================================
void CNPC_HGrunt::Shoot ( void )
{
if ( GetEnemy() == NULL )
return;
Vector vecShootOrigin = Weapon_ShootPosition();
Vector vecShootDir = GetShootEnemyDir( vecShootOrigin );
Vector forward, right, up;
AngleVectors( GetAbsAngles(), &forward, &right, &up );
Vector vecShellVelocity = right * random->RandomFloat(40,90) + up * random->RandomFloat( 75,200 ) + forward * random->RandomFloat( -40, 40 );
// EjectBrass ( vecShootOrigin - vecShootDir * 24, vecShellVelocity, GetAbsAngles().y, m_iBrassShell, TE_BOUNCE_SHELL);
FireBullets(1, vecShootOrigin, vecShootDir, VECTOR_CONE_10DEGREES, 2048, m_iAmmoType ); // shoot +-5 degrees
m_fEffects |= EF_MUZZLEFLASH;
m_cAmmoLoaded--;// take away a bullet!
SetAim( vecShootDir );
}
//=========================================================
// Shoot
//=========================================================
void CNPC_HGrunt :: Shotgun ( void )
{
if ( GetEnemy() == NULL )
return;
Vector vecShootOrigin = Weapon_ShootPosition();
Vector vecShootDir = GetShootEnemyDir( vecShootOrigin );
Vector forward, right, up;
AngleVectors( GetAbsAngles(), &forward, &right, &up );
Vector vecShellVelocity = right * random->RandomFloat(40,90) + up * random->RandomFloat( 75,200 ) + forward * random->RandomFloat( -40, 40 );
//EjectBrass ( vecShootOrigin - vecShootDir * 24, vecShellVelocity, GetAbsAngles().y, m_iShotgunShell, TE_BOUNCE_SHOTSHELL);
FireBullets( sk_hgrunt_pellets.GetFloat(), vecShootOrigin, vecShootDir, VECTOR_CONE_15DEGREES, 2048, m_iAmmoType, 0 ); // shoot +-7.5 degrees
m_fEffects |= EF_MUZZLEFLASH;
m_cAmmoLoaded--;// take away a bullet!
SetAim( vecShootDir );
}
//=========================================================
// start task
//=========================================================
void CNPC_HGrunt::StartTask ( const Task_t *pTask )
{
switch ( pTask->iTask )
{
case TASK_GRUNT_CHECK_FIRE:
if ( !NoFriendlyFire() )
{
SetCondition( COND_WEAPON_BLOCKED_BY_FRIEND );
}
TaskComplete();
break;
case TASK_GRUNT_SPEAK_SENTENCE:
SpeakSentence();
TaskComplete();
break;
case TASK_WALK_PATH:
case TASK_RUN_PATH:
// grunt no longer assumes he is covered if he moves
Forget( bits_MEMORY_INCOVER );
BaseClass ::StartTask( pTask );
break;
case TASK_RELOAD:
SetIdealActivity( ACT_RELOAD );
break;
case TASK_GRUNT_FACE_TOSS_DIR:
break;
case TASK_FACE_IDEAL:
case TASK_FACE_ENEMY:
BaseClass::StartTask( pTask );
if (GetMoveType() == MOVETYPE_FLY)
{
SetIdealActivity( ACT_GLIDE );
}
break;
default:
BaseClass::StartTask( pTask );
break;
}
}
//=========================================================
// RunTask
//=========================================================
void CNPC_HGrunt::RunTask ( const Task_t *pTask )
{
switch ( pTask->iTask )
{
case TASK_GRUNT_FACE_TOSS_DIR:
{
// project a point along the toss vector and turn to face that point.
GetMotor()->SetIdealYawToTargetAndUpdate( GetAbsOrigin() + m_vecTossVelocity * 64, AI_KEEP_YAW_SPEED );
if ( FacingIdeal() )
{
TaskComplete();
}
break;
}
default:
{
BaseClass::RunTask( pTask );
break;
}
}
}
//=========================================================
// PainSound
//=========================================================
void CNPC_HGrunt::PainSound ( void )
{
if ( gpGlobals->curtime > m_flNextPainTime )
{
CPASAttenuationFilter filter( this );
switch ( random->RandomInt( 0,6 ) )
{
case 0:
enginesound->EmitSound( filter, entindex(), CHAN_VOICE, "hgrunt/gr_pain3.wav", 1, ATTN_NORM );
break;
case 1:
enginesound->EmitSound( filter, entindex(), CHAN_VOICE, "hgrunt/gr_pain4.wav", 1, ATTN_NORM );
break;
case 2:
enginesound->EmitSound( filter, entindex(), CHAN_VOICE, "hgrunt/gr_pain5.wav", 1, ATTN_NORM );
break;
case 3:
enginesound->EmitSound( filter, entindex(), CHAN_VOICE, "hgrunt/gr_pain1.wav", 1, ATTN_NORM );
break;
case 4:
enginesound->EmitSound( filter, entindex(), CHAN_VOICE, "hgrunt/gr_pain2.wav", 1, ATTN_NORM );
break;
}
m_flNextPainTime = gpGlobals->curtime + 1;
}
}
//=========================================================
// DeathSound
//=========================================================
void CNPC_HGrunt::DeathSound ( void )
{
CPASAttenuationFilter filter( this, ATTN_IDLE );
switch ( random->RandomInt(0,2) )
{
case 0:
enginesound->EmitSound( filter, entindex(), CHAN_VOICE, "hgrunt/gr_die1.wav", 1, ATTN_IDLE );
break;
case 1:
enginesound->EmitSound( filter, entindex(), CHAN_VOICE, "hgrunt/gr_die2.wav", 1, ATTN_IDLE );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -