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

📄 hl1_npc_agrunt.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//=========== (C) Copyright 2000 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose: Bullseyes act as targets for other NPC's to attack and to trigger
//			events 
//
// $Workfile:     $
// $Date:         $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================

#include	"cbase.h"
#include	"AI_Default.h"
#include	"AI_Task.h"
#include	"AI_Schedule.h"
#include	"AI_Node.h"
#include	"AI_Hull.h"
#include	"AI_Hint.h"
#include	"AI_Navigator.h"
#include	"AI_Route.h"
#include	"AI_Squad.h"
#include	"AI_SquadSlot.h"
#include	"soundent.h"
#include	"game.h"
#include	"NPCEvent.h"
#include	"EntityList.h"
#include	"activitylist.h"
#include	"animation.h"
#include	"basecombatweapon.h"
#include	"IEffects.h"
#include	"vstdlib/random.h"
#include	"engine/IEngineSound.h"
#include	"ammodef.h"
#include    "te.h"
#include "hl1_ai_basenpc.h"

ConVar sk_agrunt_health( "sk_agrunt_health", "0" );
ConVar sk_agrunt_dmg_punch( "sk_agrunt_dmg_punch", "0" );

//=========================================================
// Monster's Anim Events Go Here
//=========================================================
#define		AGRUNT_AE_HORNET1	( 1 )
#define		AGRUNT_AE_HORNET2	( 2 )
#define		AGRUNT_AE_HORNET3	( 3 )
#define		AGRUNT_AE_HORNET4	( 4 )
#define		AGRUNT_AE_HORNET5	( 5 )
// some events are set up in the QC file that aren't recognized by the code yet.
#define		AGRUNT_AE_PUNCH		( 6 )
#define		AGRUNT_AE_BITE		( 7 )

#define		AGRUNT_AE_LEFT_FOOT	 ( 10 )
#define		AGRUNT_AE_RIGHT_FOOT ( 11 )

#define		AGRUNT_AE_LEFT_PUNCH ( 12 )
#define		AGRUNT_AE_RIGHT_PUNCH ( 13 )

#define		AGRUNT_MELEE_DIST	100

int iAgruntMuzzleFlash;
int ACT_THREAT_DISPLAY;

// -----------------------------------------------
//	> Squad slots
// -----------------------------------------------
enum AGruntSquadSlot_T
{	
	AGRUNT_SQUAD_SLOT_HORNET1 = LAST_SHARED_SQUADSLOT,
	AGRUNT_SQUAD_SLOT_HORNET2,
	AGRUNT_SQUAD_SLOT_CHASE,
};

enum
{
	SCHED_AGRUNT_FAIL = LAST_SHARED_SCHEDULE,
	SCHED_AGRUNT_COMBAT_FAIL,
	SCHED_AGRUNT_STANDOFF,
	SCHED_AGRUNT_SUPPRESS_HORNET,
	SCHED_AGRUNT_RANGE_ATTACK,
	SCHED_AGRUNT_HIDDEN_RANGE_ATTACK,
	SCHED_AGRUNT_TAKE_COVER_FROM_ENEMY,
	SCHED_AGRUNT_VICTORY_DANCE,
	SCHED_AGRUNT_THREAT_DISPLAY,
};

//=========================================================
// monster-specific tasks
//=========================================================
enum 
{
	TASK_AGRUNT_SETUP_HIDE_ATTACK = LAST_SHARED_TASK,
	TASK_AGRUNT_GET_PATH_TO_ENEMY_CORPSE,
};


class CNPC_AlienGrunt : public CHL1BaseNPC
{
	DECLARE_CLASS( CNPC_AlienGrunt, CHL1BaseNPC );
public:

	void Spawn( void );
	void Precache( void );

	static const char *pAttackHitSounds[];
	static const char *pAttackMissSounds[];
	static const char *pAttackSounds[];
	static const char *pDieSounds[];
	static const char *pPainSounds[];
	static const char *pIdleSounds[];
	static const char *pAlertSounds[];
	
	float	MaxYawSpeed( void );
	Class_T Classify ( void ){ return CLASS_ALIEN_MILITARY;	}
	int  GetSoundInterests ( void );
	void HandleAnimEvent( animevent_t *pEvent );

	void AlertSound( void );
	void DeathSound ( void );
	void PainSound ( void );
	void AttackSound ( void );

	bool ShouldSpeak( void );
	void PrescheduleThink ( void );
	
	bool FCanCheckAttacks ( void );

	int MeleeAttack1Conditions ( float flDot, float flDist );
	int RangeAttack1Conditions ( float flDot, float flDist );
	
	void StopTalking ( void );

	void StartTask( const Task_t *pTask );
	int TranslateSchedule( int scheduleType ); //GetScheduleOfType
	int SelectSchedule( void ); // GetSchedule

	void SetObjectCollisionBox( void )
	{
		SetAbsMins( GetAbsOrigin() + Vector( -32, -32, 0 ) );
		SetAbsMaxs( GetAbsOrigin() + Vector( 32, 32, 85 ) );
	}

	void	TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr );
	int		IRelationPriority( CBaseEntity *pTarget );
/*
	int IRelationship( CBaseEntity *pTarget );
*/
public:
	DECLARE_DATADESC();
	DEFINE_CUSTOM_AI;
	
	bool	m_fCanHornetAttack;
	float	m_flNextHornetAttackCheck;

	float	m_flNextPainTime;

	// three hacky fields for speech stuff. These don't really need to be saved.
	float	m_flNextSpeakTime;
	float	m_flNextWordTime;
	int		m_iLastWord;
	float   m_flDamageTime;
};

LINK_ENTITY_TO_CLASS( monster_alien_grunt, CNPC_AlienGrunt );

BEGIN_DATADESC( CNPC_AlienGrunt )
	DEFINE_FIELD( CNPC_AlienGrunt, m_fCanHornetAttack, FIELD_BOOLEAN ),
	DEFINE_FIELD( CNPC_AlienGrunt, m_flNextHornetAttackCheck, FIELD_TIME ),
	DEFINE_FIELD( CNPC_AlienGrunt, m_flNextPainTime, FIELD_TIME ),
	DEFINE_FIELD( CNPC_AlienGrunt, m_flNextSpeakTime, FIELD_TIME ),
	DEFINE_FIELD( CNPC_AlienGrunt, m_flNextWordTime, FIELD_TIME ),
	DEFINE_FIELD( CNPC_AlienGrunt, m_iLastWord, FIELD_INTEGER ),
END_DATADESC()

const char *CNPC_AlienGrunt::pAttackHitSounds[] = 
{
	"zombie/claw_strike1.wav",
	"zombie/claw_strike2.wav",
	"zombie/claw_strike3.wav",
};

const char *CNPC_AlienGrunt::pAttackMissSounds[] = 
{
	"zombie/claw_miss1.wav",
	"zombie/claw_miss2.wav",
};

const char *CNPC_AlienGrunt::pAttackSounds[] =
{
	"agrunt/ag_attack1.wav",
	"agrunt/ag_attack2.wav",
	"agrunt/ag_attack3.wav",
};

const char *CNPC_AlienGrunt::pDieSounds[] =
{
	"agrunt/ag_die1.wav",
	"agrunt/ag_die4.wav",
	"agrunt/ag_die5.wav",
};

const char *CNPC_AlienGrunt::pPainSounds[] =
{
	"agrunt/ag_pain1.wav",
	"agrunt/ag_pain2.wav",
	"agrunt/ag_pain3.wav",
	"agrunt/ag_pain4.wav",
	"agrunt/ag_pain5.wav",
};

const char *CNPC_AlienGrunt::pIdleSounds[] =
{
	"agrunt/ag_idle1.wav",
	"agrunt/ag_idle2.wav",
	"agrunt/ag_idle3.wav",
	"agrunt/ag_idle4.wav",
};

const char *CNPC_AlienGrunt::pAlertSounds[] =
{
	"agrunt/ag_alert1.wav",
	"agrunt/ag_alert3.wav",
	"agrunt/ag_alert4.wav",
	"agrunt/ag_alert5.wav",
};

int CNPC_AlienGrunt::IRelationPriority( CBaseEntity *pTarget )
{
	//I hate grunts more than anything.
	if ( pTarget->Classify() == CLASS_HUMAN_MILITARY )
	{
		if ( FClassnameIs( pTarget, "monster_human_grunt" ) )
		{
			 return ( BaseClass::IRelationPriority ( pTarget ) + 1 );
		}
	}

	return BaseClass::IRelationPriority( pTarget );
}

void CNPC_AlienGrunt::Spawn()
{
	Precache();

	SetModel( "models/agrunt.mdl");
	UTIL_SetSize( this, Vector( -32, -32, 0 ), Vector( 32, 32, 64 ) );

	SetSolid( SOLID_BBOX );
	AddSolidFlags( FSOLID_NOT_STANDABLE );
	SetMoveType( MOVETYPE_STEP );
	m_bloodColor		= BLOOD_COLOR_GREEN;
	m_fEffects			= 0;
	m_iHealth			= sk_agrunt_health.GetFloat();
	m_flFieldOfView		= 0.2;// indicates the width of this monster's forward view cone ( as a dotproduct result )
	m_NPCState			= NPC_STATE_NONE;

	CapabilitiesClear();
	CapabilitiesAdd ( bits_CAP_SQUAD | bits_CAP_MOVE_GROUND );

	CapabilitiesAdd(bits_CAP_INNATE_RANGE_ATTACK1 );

	// Innate range attack for kicking
	CapabilitiesAdd(bits_CAP_INNATE_MELEE_ATTACK1 );

	m_HackedGunPos		= Vector( 24, 64, 48 );

	m_flNextSpeakTime	= m_flNextWordTime = gpGlobals->curtime + 10 + random->RandomInt( 0, 10 );

	SetHullType(HULL_WIDE_HUMAN);
	SetHullSizeNormal();	

	SetRenderColor( 255, 255, 255, 255 );
	
	NPCInit();
	
	BaseClass::Spawn();
}

//=========================================================
// Precache - precaches all resources this monster needs
//=========================================================
void CNPC_AlienGrunt::Precache()
{
	int i;

	engine->PrecacheModel("models/agrunt.mdl");

	for ( i = 0; i < ARRAYSIZE( pAttackHitSounds ); i++ )
		enginesound->PrecacheSound((char *)pAttackHitSounds[i]);

	for ( i = 0; i < ARRAYSIZE( pAttackMissSounds ); i++ )
		enginesound->PrecacheSound((char *)pAttackMissSounds[i]);

	for ( i = 0; i < ARRAYSIZE( pIdleSounds ); i++ )
		enginesound->PrecacheSound((char *)pIdleSounds[i]);

	for ( i = 0; i < ARRAYSIZE( pDieSounds ); i++ )
		enginesound->PrecacheSound((char *)pDieSounds[i]);

	for ( i = 0; i < ARRAYSIZE( pPainSounds ); i++ )
		enginesound->PrecacheSound((char *)pPainSounds[i]);

	for ( i = 0; i < ARRAYSIZE( pAttackSounds ); i++ )
		enginesound->PrecacheSound((char *)pAttackSounds[i]);

	for ( i = 0; i < ARRAYSIZE( pAlertSounds ); i++ )
		enginesound->PrecacheSound((char *)pAlertSounds[i]);

	enginesound->PrecacheSound( "player/pl_ladder1.wav" );
	enginesound->PrecacheSound( "player/pl_ladder2.wav" );
	enginesound->PrecacheSound( "player/pl_ladder3.wav" );
	enginesound->PrecacheSound( "player/pl_ladder4.wav" );

	enginesound->PrecacheSound( "hassault/hw_shoot1.wav" );

	iAgruntMuzzleFlash = engine->PrecacheModel( "sprites/muz4.vmt" );

	UTIL_PrecacheOther( "hornet" );
}	

float CNPC_AlienGrunt::MaxYawSpeed( void )
{
	float ys;

	switch ( GetActivity() )
	{
	case ACT_TURN_LEFT:
	case ACT_TURN_RIGHT:
		ys = 110;
		break;
	default:
		ys = 100;
	}

	return ys;
}

int CNPC_AlienGrunt::GetSoundInterests ( void )
{
	return	SOUND_WORLD	|
			SOUND_COMBAT	|
			SOUND_PLAYER	|
			SOUND_DANGER;
}

//=========================================================
// HandleAnimEvent - catches the monster-specific messages
// that occur when tagged animation frames are played.
//
// Returns number of events handled, 0 if none.
//=========================================================
void CNPC_AlienGrunt::HandleAnimEvent( animevent_t *pEvent )
{
	switch( pEvent->event )
	{
	case AGRUNT_AE_HORNET1:
	case AGRUNT_AE_HORNET2:
	case AGRUNT_AE_HORNET3:
	case AGRUNT_AE_HORNET4:
	case AGRUNT_AE_HORNET5:
		{
			// m_vecEnemyLKP should be center of enemy body
			Vector vecArmPos;
			QAngle angArmDir;
			Vector vecDirToEnemy;
			QAngle angDir;

			if (HasCondition( COND_SEE_ENEMY))
			{
				Vector vecEnemyLKP = GetEnemy()->GetAbsOrigin();

				vecDirToEnemy = ( ( vecEnemyLKP ) - GetAbsOrigin() );
				VectorAngles( vecDirToEnemy, angDir );
				VectorNormalize( vecDirToEnemy );
			}
			else
			{
				angDir = GetAbsAngles();
				angDir.x = -angDir.x;

				Vector vForward;
				AngleVectors( angDir, &vForward );
				vecDirToEnemy = vForward;
			}

			m_fEffects = EF_MUZZLEFLASH;

			// make angles +-180
			if (angDir.x > 180)
			{
				angDir.x = angDir.x - 360;
			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -