⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hl1_npc_hgrunt.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
			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 + -