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

📄 hl1_npc_osprey.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#include	"cbase.h"
#include	"beam_shared.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_Route.h"
#include	"AI_Senses.h"
#include	"hl1_npc_hgrunt.h"
#include	"soundent.h"
#include	"game.h"
#include	"NPCEvent.h"
#include	"EntityList.h"
#include	"activitylist.h"
#include	"animation.h"
#include	"engine/IEngineSound.h"
#include	"ammodef.h"
#include	"basecombatweapon.h"
#include	"hl1_basegrenade.h"
#include	"customentity.h"
#include	"soundenvelope.h"
#include	"hl1_cbasehelicopter.h"
#include	"IEffects.h"

extern short	g_sModelIndexFireball;

typedef struct 
{
	int isValid;
	EHANDLE hGrunt;
	Vector	vecOrigin;
	Vector  vecAngles;
} t_ospreygrunt;

#define LOADED_WITH_GRUNTS 0 //WORST NAME EVER!
#define UNLOADING_GRUNTS 1
#define GRUNTS_DEPLOYED 2 //Waiting for them to finish repelin
#define SF_WAITFORTRIGGER	0x40
#define MAX_CARRY	24
#define DEFAULT_SPEED 250
#define HELICOPTER_THINK_INTERVAL		0.1

class CNPC_Osprey : public CBaseHelicopter
{
	DECLARE_CLASS( CNPC_Osprey, CBaseHelicopter );
public:

	int		ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
	
	void Spawn( void );
	void Precache( void );
	Class_T  Classify( void ) { return CLASS_NONE; };
	int  BloodColor( void ) { return DONT_BLEED; }

	void FindAllThink( void );
	void DeployThink( void );
	bool HasDead( void );
	void Flight( void );
	void HoverThink( void );
	CAI_BaseNPC *MakeGrunt( Vector vecSrc );

	void InitializeRotorSound( void );
	void PrescheduleThink( void );

	void Event_Killed( CBaseEntity *pInflictor, CBaseEntity *pAttacker, float flDamage, int bitsDamageType );
	void DyingThink( void );

/*	
	
	void CrashTouch( CBaseEntity *pOther );
	void DyingThink( void );
	void CommandUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );

	// int  TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType );
	void TraceAttack( CBaseEntity *pAttacker, float flDamage, const Vector &vecDir, trace_t *ptr, int bitsDamageType);
	void ShowDamage( void );*/

	float m_startTime;

	float m_flIdealtilt;
	float m_flRotortilt;

	float m_flRightHealth;
	float m_flLeftHealth;

	int	m_iUnits;
	EHANDLE m_hGrunt[MAX_CARRY];
	Vector m_vecOrigin[MAX_CARRY];
	EHANDLE m_hRepel[4];

	int m_iSoundState;
	int m_iSpriteTexture;

	int m_iPitch;

	int m_iExplode;
	int	m_iTailGibs;
	int	m_iBodyGibs;
	int	m_iEngineGibs;

	int m_iDoLeftSmokePuff;
	int m_iDoRightSmokePuff;

	int m_iRepelState;
	float m_flPrevGoalVel;

	int m_iRotorAngle;
	int	m_nDebrisModel;


	DECLARE_DATADESC();
};

LINK_ENTITY_TO_CLASS( monster_osprey, CNPC_Osprey );

BEGIN_DATADESC( CNPC_Osprey )
	DEFINE_FIELD( CNPC_Osprey, m_startTime, FIELD_TIME ),

	DEFINE_FIELD( CNPC_Osprey, m_flIdealtilt, FIELD_FLOAT ),
	DEFINE_FIELD( CNPC_Osprey, m_flRotortilt, FIELD_FLOAT ),

	DEFINE_FIELD( CNPC_Osprey, m_flRightHealth, FIELD_FLOAT ),
	DEFINE_FIELD( CNPC_Osprey, m_flLeftHealth, FIELD_FLOAT ),

	DEFINE_FIELD( CNPC_Osprey, m_iUnits, FIELD_INTEGER ),
	DEFINE_ARRAY( CNPC_Osprey, m_hGrunt, FIELD_EHANDLE, MAX_CARRY ),
	DEFINE_ARRAY( CNPC_Osprey, m_vecOrigin, FIELD_POSITION_VECTOR, MAX_CARRY ),
	DEFINE_ARRAY( CNPC_Osprey, m_hRepel, FIELD_EHANDLE, 4 ),

	// DEFINE_FIELD( CNPC_Osprey, m_iSoundState, FIELD_INTEGER ),
	// DEFINE_FIELD( CNPC_Osprey, m_iSpriteTexture, FIELD_INTEGER ),
	// DEFINE_FIELD( CNPC_Osprey, m_iPitch, FIELD_INTEGER ),

	DEFINE_FIELD( CNPC_Osprey, m_iDoLeftSmokePuff, FIELD_INTEGER ),
	DEFINE_FIELD( CNPC_Osprey, m_iDoRightSmokePuff, FIELD_INTEGER ),

	DEFINE_THINKFUNC( CNPC_Osprey, FindAllThink ),
	DEFINE_THINKFUNC( CNPC_Osprey, DeployThink ),
	
/*	DEFINE_FUNCTION ( CNPC_Osprey, HoverThink ),
	DEFINE_FUNCTION ( CNPC_Osprey, CrashTouch ),
	DEFINE_FUNCTION ( CNPC_Osprey, DyingThink ),
	DEFINE_FUNCTION ( CNPC_Osprey, CommandUse ),*/
END_DATADESC()


void CNPC_Osprey :: Spawn( void )
{
	Precache( );
	// motor
	SetModel( "models/osprey.mdl" );

	m_spawnflags &= ~SF_AWAITINPUT;

	BaseClass::Spawn();
	
	Vector mins, maxs;
	ExtractBbox( 0, mins, maxs );
//	UTIL_SetSize( this, Vector ( -6, -6, -6 ), Vector ( 6, 6, 6 ) ); //HACKHACK - Temp for demo.
	UTIL_SetSize( this, mins, maxs ); 
	UTIL_SetOrigin( this, GetAbsOrigin() );

	AddFlag( FL_NPC );
	m_takedamage		= DAMAGE_YES;
	m_flRightHealth		= 200;
	m_flLeftHealth		= 200;
	m_iHealth			= 69;

	m_flFieldOfView = 0; // 180 degrees

	SetSequence( 0 );
	ResetSequenceInfo( );
	m_flCycle = random->RandomInt( 0,0xFF );

//	InitBoneControllers();

	m_startTime = gpGlobals->curtime + 1;

	//FindAllThink();
//	SetUse( CommandUse );

/*	if (!( m_spawnflags & SF_WAITFORTRIGGER))
	{
		SetThink( gpGlobals->curtime + 1.0 );
	}*/

	m_flMaxSpeed = (float)BASECHOPPER_MAX_SPEED / 2;
	
	m_iRepelState = LOADED_WITH_GRUNTS;
	m_flPrevGoalVel = 9999;

	m_iRotorAngle = -1;
	SetBoneController( 0, m_iRotorAngle );
	
}


void CNPC_Osprey::Precache( void )
{
	UTIL_PrecacheOther( "monster_human_grunt" );

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

	enginesound->PrecacheSound("apache/ap_rotor4.wav");
	enginesound->PrecacheSound("weapons/mortarhit.wav");

	m_iSpriteTexture = engine->PrecacheModel( "sprites/rope.vmt" );

	m_iExplode	= engine->PrecacheModel( "sprites/fexplo.vmt" );
	m_iTailGibs = engine->PrecacheModel( "models/osprey_tailgibs.mdl" );
	m_iBodyGibs = engine->PrecacheModel( "models/osprey_bodygibs.mdl" );
	m_iEngineGibs = engine->PrecacheModel( "models/osprey_enginegibs.mdl" );

	m_nDebrisModel = engine->PrecacheModel( "models/gibs/metalgibs.mdl" );

	BaseClass::Precache();
}

//------------------------------------------------------------------------------
// Purpose : 
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CNPC_Osprey::InitializeRotorSound( void )
{
	CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();

	CPASAttenuationFilter filter( this );
	m_pRotorSound = controller.SoundCreate( filter, entindex(), CHAN_STATIC, "apache/ap_rotor4.wav", 0.2 );

	BaseClass::InitializeRotorSound();
}

void CNPC_Osprey::FindAllThink( void )
{
	CBaseEntity *pEntity = NULL;

	m_iUnits = 0;
	while ( ( pEntity = gEntList.FindEntityByClassname( pEntity, "monster_human_grunt" ) ) != NULL)
	{
		if ( m_iUnits > MAX_CARRY )
			 break;

		if (pEntity->IsAlive())
		{
			m_hGrunt[m_iUnits]		= pEntity;
			m_vecOrigin[m_iUnits]	= pEntity->GetAbsOrigin();
			m_iUnits++;
		}
	}

	if (m_iUnits == 0)
	{
		Msg( "osprey error: no grunts to resupply\n");
		UTIL_Remove( this );
		return;
	}

	m_startTime = 0.0f;
}

void CNPC_Osprey :: DeployThink( void )
{
	Vector vecForward;
	Vector vecRight;
	Vector vecUp;
	Vector vecSrc;

	SetLocalAngularVelocity( QAngle ( 0, 0, 0 ) );
	SetAbsVelocity( Vector ( 0, 0, 0 ) );

	AngleVectors( GetAbsAngles(), &vecForward, &vecRight, &vecUp );

	trace_t tr;
	UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, -4096.0), MASK_SOLID_BRUSHONLY, this,COLLISION_GROUP_NONE, &tr);
	CSoundEnt::InsertSound ( SOUND_DANGER, tr.endpos, 400, 0.3 );

	vecSrc = GetAbsOrigin() + vecForward *  32 + vecRight *  100 + vecUp * -96;
	m_hRepel[0] = MakeGrunt( vecSrc );

	vecSrc = GetAbsOrigin() + vecForward * -64 + vecRight *  100 + vecUp * -96;
	m_hRepel[1] = MakeGrunt( vecSrc );

	vecSrc = GetAbsOrigin() + vecForward *  32 + vecRight * -100 + vecUp * -96;
	m_hRepel[2] = MakeGrunt( vecSrc );

	vecSrc = GetAbsOrigin() + vecForward * -64 + vecRight * -100 + vecUp * -96;
	m_hRepel[3] = MakeGrunt( vecSrc );

	m_iRepelState = GRUNTS_DEPLOYED;

	HoverThink();
}

bool CNPC_Osprey :: HasDead( )
{
	for (int i = 0; i < m_iUnits; i++)
	{
		if (m_hGrunt[i] == NULL || !m_hGrunt[i]->IsAlive())
		{
			return TRUE;
		}
		else
		{
			m_vecOrigin[i] = m_hGrunt[i]->GetAbsOrigin();  // send them to where they died
		}
	}
	return FALSE;
}

void CNPC_Osprey::HoverThink( void )
{
	int i = 0;
	for (i = 0; i < 4; i++)
	{
		CBaseEntity *pRepel = (CBaseEntity*)m_hRepel[i];

		if ( pRepel != NULL && pRepel->m_iHealth > 0 && pRepel->GetMoveType() == MOVETYPE_FLY )
		{
			break;
		}
	}

	if ( i == 4 )
		 m_iRepelState = LOADED_WITH_GRUNTS;
	
//	ShowDamage();

}

CAI_BaseNPC *CNPC_Osprey::MakeGrunt( Vector vecSrc )
{
	CBaseEntity *pEntity;
	CAI_BaseNPC *pGrunt;

	trace_t tr;
	UTIL_TraceLine( vecSrc, vecSrc + Vector( 0, 0, -4096.0), MASK_NPCSOLID,  this, COLLISION_GROUP_NONE, &tr);
	
	if ( tr.m_pEnt && tr.m_pEnt->GetSolid() != SOLID_BSP) 
		return NULL;

	for (int i = 0; i < m_iUnits; i++)
	{
		if (m_hGrunt[i] == NULL || !m_hGrunt[i]->IsAlive())
		{
			if (m_hGrunt[i] != NULL && m_hGrunt[i]->m_nRenderMode == kRenderNormal)
			{
				m_hGrunt[i]->SUB_StartFadeOut( );
			}
			pEntity = Create( "monster_human_grunt", vecSrc, GetAbsAngles() );
			pGrunt = pEntity->MyNPCPointer( );
			pGrunt->SetMoveType( MOVETYPE_FLY );
			pGrunt->SetAbsVelocity( Vector( 0, 0, random->RandomFloat( -196, -128 ) ) );
			pGrunt->SetActivity( ACT_GLIDE );
			pGrunt->RemoveFlag( FL_ONGROUND );

			pGrunt->SetOwnerEntity(this);


			CBeam *pBeam = CBeam::BeamCreate( "sprites/rope.vmt", 1.0 );
			pBeam->PointEntInit( vecSrc + Vector(0,0,112), pGrunt );
			pBeam->SetBeamFlags( FBEAM_SOLID );
			pBeam->SetColor( 255, 255, 255 );
			pBeam->SetThink( SUB_Remove );
			pBeam->SetNextThink( gpGlobals->curtime + -4096.0 * tr.fraction / pGrunt->GetAbsVelocity().z + 0.5 );
			

			// ALERT( at_console, "%d at %.0f %.0f %.0f\n", i, m_vecOrigin[i].x, m_vecOrigin[i].y, m_vecOrigin[i].z );  
			pGrunt->m_vecLastPosition = m_vecOrigin[i];
			m_hGrunt[i] = pGrunt;
			return pGrunt;
		}
	}
	// ALERT( at_console, "none dead\n");
	return NULL;
}

void CNPC_Osprey::Flight( void )
{
	if ( m_iRepelState == LOADED_WITH_GRUNTS )
	{
		BaseClass::Flight();

		// adjust angle of osprey rotors 
		if ( m_angleVelocity > 0 )
		{
			m_iRotorAngle = UTIL_Approach(-45, m_iRotorAngle, 5 * (m_angleVelocity / 10));
		}
		else
		{
			m_iRotorAngle = UTIL_Approach(-1, m_iRotorAngle, 5);
		}
		SetBoneController( 0, m_iRotorAngle );

	}
}

void CNPC_Osprey::PrescheduleThink( void )
{
	BaseClass::PrescheduleThink();
	
	StudioFrameAdvance( );

	if ( m_startTime != 0.0 && m_startTime <= gpGlobals->curtime )
		 FindAllThink();

	if ( m_pGoalEnt )
	{
		if ( m_flPrevGoalVel != m_pGoalEnt->m_flSpeed )
		{
			if ( m_flPrevGoalVel == 0 && m_pGoalEnt->m_flSpeed != 0 )
			{
				if ( HasDead() && m_iRepelState == LOADED_WITH_GRUNTS )
					 m_iRepelState = UNLOADING_GRUNTS;
			}

			m_flPrevGoalVel = m_pGoalEnt->m_flSpeed;
		}
	}
	
	if ( m_iRepelState == UNLOADING_GRUNTS )
		 DeployThink();
	else if ( m_iRepelState == GRUNTS_DEPLOYED )
		 HoverThink();
}

void CNPC_Osprey::Event_Killed( CBaseEntity *pInflictor, CBaseEntity *pAttacker, float flDamage, int bitsDamageType )
{
	SetMoveType( MOVETYPE_FLYGRAVITY );
	SetGravity( 0.3 );
	SetLocalAngularVelocity( QAngle( random->RandomFloat( -20, 20 ), 0, random->RandomFloat( -50, 50 ) ) );
	//STOP_SOUND( ENT(pev), CHAN_STATIC, "apache/ap_rotor4.wav" );

	// add gravity
	UTIL_SetSize( this, Vector( -32, -32, -64), Vector( 32, 32, 0) );
	SetThink( DyingThink );
	SetTouch( CrashTouch );
//	pev->nextthink = gpGlobals->curtime + 0.1;
	m_iHealth = 0;
	m_takedamage = DAMAGE_NO;

	m_startTime = gpGlobals->curtime + 4.0;
}


//-----------------------------------------------------------------------------
// Purpose:	Lame, temporary death
//-----------------------------------------------------------------------------
void CNPC_Osprey::DyingThink( void )
{
	StudioFrameAdvance( );
	SetNextThink( gpGlobals->curtime + 0.1f );

	if( random->RandomInt( 0, 50 ) == 1 )
	{
		Vector vecSize = Vector( 60, 60, 30 );
		CPVSFilter filter( GetAbsOrigin() );
		te->BreakModel( filter, 0.0, &GetAbsOrigin(), &vecSize, &vec3_origin, m_nDebrisModel, 100, 0, 2.5, BREAK_METAL );
	}

	QAngle angVel = GetLocalAngularVelocity();
	if( angVel.y < 400 )
	{
		angVel.y *= 1.1;
		SetLocalAngularVelocity( angVel );

⌨️ 快捷键说明

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