📄 hl1_npc_apache.cpp
字号:
#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_Route.h"
#include "soundent.h"
#include "game.h"
#include "NPCEvent.h"
#include "EntityList.h"
#include "activitylist.h"
#include "hl1_basegrenade.h"
#include "animation.h"
#include "IEffects.h"
#include "vstdlib/random.h"
#include "engine/IEngineSound.h"
#include "ammodef.h"
#include "soundenvelope.h"
#include "hl1_cbasehelicopter.h"
#include "ndebugoverlay.h"
#include "smoke_trail.h"
#include "beam_shared.h"
#include "grenade_homer.h"
#define HOMER_TRAIL0_LIFE 0.1
#define HOMER_TRAIL1_LIFE 0.2
#define HOMER_TRAIL2_LIFE 3.0// 1.0
#define SF_NOTRANSITION 128
class CNPC_Apache : public CBaseHelicopter
{
DECLARE_CLASS( CNPC_Apache, CBaseHelicopter );
public:
void Spawn( void );
void Precache( void );
int BloodColor( void ) { return DONT_BLEED; }
Class_T Classify( void ) { return CLASS_HUMAN_MILITARY; };
void InitializeRotorSound( void );
void LaunchRocket( Vector &viewDir, int damage, int radius, Vector vecLaunchPoint );
void Flight( void );
void SetObjectCollisionBox( void )
{
SetAbsMins( GetAbsOrigin() + Vector( -300, -300, -172) );
SetAbsMaxs( GetAbsOrigin() + Vector(300, 300, 8) );
}
bool FireGun( void );
void AimRocketGun( void );
void FireRocket( void );
void DyingThink( void );
int ObjectCaps( void );
/* int Save( CSave &save );
int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
void Spawn( void );
void Precache( void );
void Killed( entvars_t *pevAttacker, int iGib );
void GibMonster( void );
void EXPORT HuntThink( void );
void EXPORT FlyTouch( CBaseEntity *pOther );
void EXPORT CrashTouch( CBaseEntity *pOther );
void EXPORT DyingThink( void );
void EXPORT StartupUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void EXPORT NullThink( void );
void ShowDamage( void );
void Flight( void );
void FireRocket( void );
BOOL FireGun( void );
int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType );
void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);*/
int m_iRockets;
float m_flForce;
float m_flNextRocket;
int m_iAmmoType;
Vector m_vecTarget;
Vector m_posTarget;
Vector m_vecDesired;
Vector m_posDesired;
Vector m_vecGoal;
Vector m_angGun;
int m_iSoundState; // don't save this
int m_iSpriteTexture;
int m_iExplode;
int m_iBodyGibs;
int m_nDebrisModel;
float m_flGoalSpeed;
int m_iDoSmokePuff;
CBeam *m_pBeam;
};
void CNPC_Apache :: Spawn( void )
{
Precache( );
SetModel( "models/apache.mdl" );
UTIL_SetSize( this, Vector( -256, -256, 0 ), Vector( 256, 256, 128 ) );
UTIL_SetOrigin( this, GetAbsOrigin() );
m_spawnflags &= ~SF_AWAITINPUT;
BaseClass::Spawn();
m_iHealth = 100;
m_flFieldOfView = -0.707; // 270 degrees
m_fHelicopterFlags = BITS_HELICOPTER_MISSILE_ON | BITS_HELICOPTER_GUN_ON;
InitBoneControllers();
SetRenderColor( 255, 255, 255, 255 );
m_iRockets = 10;
}
LINK_ENTITY_TO_CLASS ( monster_apache, CNPC_Apache );
int CNPC_Apache::ObjectCaps( void )
{
if ( GetSpawnFlags() & SF_NOTRANSITION )
return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION;
else
return BaseClass::ObjectCaps();
}
void CNPC_Apache::Precache( void )
{
m_iAmmoType = GetAmmoDef()->Index("9mmRound");
engine->PrecacheModel("models/apache.mdl");
enginesound->PrecacheSound("apache/ap_rotor1.wav");
enginesound->PrecacheSound("apache/ap_rotor2.wav");
enginesound->PrecacheSound("apache/ap_rotor3.wav");
enginesound->PrecacheSound("apache/ap_whine1.wav");
enginesound->PrecacheSound("weapons/mortarhit.wav");
//m_iSpriteTexture = PRECACHE_MODEL( "sprites/white.spr" );
enginesound->PrecacheSound("turret/tu_fire1.wav");
engine->PrecacheModel("sprites/lgtning.spr");
// m_iExplode = PRECACHE_MODEL( "sprites/fexplo.spr" );
// m_iBodyGibs = PRECACHE_MODEL( "models/metalplategibs_green.mdl" );
// UTIL_PrecacheOther( "hvr_rocket" );
engine->PrecacheModel( "models/weapons/w_missile.mdl" );
m_nDebrisModel = engine->PrecacheModel( "models/gibs/rock_gibs.mdl" );
BaseClass::Precache();
}
void CNPC_Apache::InitializeRotorSound( void )
{
CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
CPASAttenuationFilter filter( this );
m_pRotorSound = controller.SoundCreate( filter, entindex(), CHAN_STATIC, "apache/ap_rotor2.wav", 0.2 );
BaseClass::InitializeRotorSound();
}
void CNPC_Apache::Flight( void )
{
StudioFrameAdvance( );
float flDistToDesiredPosition = (GetAbsOrigin() - m_vecDesiredPosition).Length();
//NDebugOverlay::Line(GetAbsOrigin(), GetDesiredPosition(), 0,0,255, true, 0.1);
if (m_flGoalSpeed < 800 )
m_flGoalSpeed += GetAcceleration();
// Vector vecGoalOrientation;
if (flDistToDesiredPosition > 250) // 500
{
Vector v1 = (m_vecTargetPosition - GetAbsOrigin());
Vector v2 = (m_vecDesiredPosition - GetAbsOrigin());
VectorNormalize( v1 );
VectorNormalize( v2 );
if (m_flLastSeen + 90 > gpGlobals->curtime && DotProduct( v1, v2 ) > 0.25)
{
m_vecGoalOrientation = ( m_vecTargetPosition - GetAbsOrigin());
}
else
{
m_vecGoalOrientation = (m_vecDesiredPosition - GetAbsOrigin());
}
VectorNormalize( m_vecGoalOrientation );
}
else
{
AngleVectors( m_pGoalEnt->GetAbsAngles(), &m_vecGoalOrientation );
}
// SetGoalOrientation( vecGoalOrientation );
if (m_pGoalEnt)
{
// ALERT( at_console, "%.0f\n", flLength );
if ( HasReachedTarget() )
{
// If we get this close to the desired position, it's assumed that we've reached
// the desired position, so move on.
// Fire target that I've reached my goal
m_AtTarget.FireOutput( m_pGoalEnt, this );
OnReachedTarget( m_pGoalEnt );
m_pGoalEnt = gEntList.FindEntityByName( NULL, m_pGoalEnt->m_target, NULL );
if (m_pGoalEnt)
{
m_vecDesiredPosition = m_pGoalEnt->GetAbsOrigin();
// Vector vecGoalOrientation;
AngleVectors( m_pGoalEnt->GetAbsAngles(), &m_vecGoalOrientation );
// SetGoalOrientation( vecGoalOrientation );
flDistToDesiredPosition = (GetAbsOrigin() - m_vecDesiredPosition).Length();
}
}
}
else
{
// If we can't find a new target, just stay where we are.
m_vecDesiredPosition = GetAbsOrigin();
}
// tilt model 5 degrees
QAngle angAdj = QAngle( 5.0, 0, 0 );
// estimate where I'll be facing in one seconds
Vector forward, right, up;
AngleVectors( GetAbsAngles() + GetLocalAngularVelocity() * 2 + angAdj, &forward, &right, &up );
// Vector vecEst1 = GetAbsOrigin() + pev->velocity + gpGlobals->v_up * m_flForce - Vector( 0, 0, 384 );
// float flSide = DotProduct( m_posDesired - vecEst1, gpGlobals->v_right );
QAngle angVel = GetLocalAngularVelocity();
float flSide = DotProduct( m_vecGoalOrientation, right );
if (flSide < 0)
{
if ( angVel.y < 60)
{
angVel.y += 8; // 9 * (3.0/2.0);
}
}
else
{
if ( angVel.y > -60)
{
angVel.y -= 8; // 9 * (3.0/2.0);
}
}
angVel.y *= 0.98;
SetLocalAngularVelocity( angVel );
Vector vecVel = GetAbsVelocity();
// estimate where I'll be in two seconds
AngleVectors( GetAbsAngles() + GetLocalAngularVelocity() * 1 + angAdj, &forward, &right, &up );
Vector vecEst = GetAbsOrigin() + vecVel * 2.0 + up * m_flForce * 20 - Vector( 0, 0, 384 * 2 );
// add immediate force
AngleVectors( GetAbsAngles() + angAdj, &forward, &right, &up );
vecVel.x += up.x * m_flForce;
vecVel.y += up.y * m_flForce;
vecVel.z += up.z * m_flForce;
// add gravity
vecVel.z -= 38.4; // 32ft/sec
float flSpeed = vecVel.Length();
float flDir = DotProduct( Vector( forward.x, forward.y, 0 ), Vector( vecVel.x, vecVel.y, 0 ) );
if (flDir < 0)
flSpeed = -flSpeed;
float flDist = DotProduct( m_vecDesiredPosition - vecEst, forward );
// float flSlip = DotProduct( pev->velocity, gpGlobals->v_right );
float flSlip = -DotProduct( m_vecDesiredPosition - vecEst, right );
angVel = GetLocalAngularVelocity();
// fly sideways
if (flSlip > 0)
{
if (GetAbsAngles().z > -30 && angVel.z > -15)
angVel.z -= 4;
else
angVel.z += 2;
}
else
{
if (GetAbsAngles().z < 30 && angVel.z < 15)
angVel.z += 4;
else
angVel.z -= 2;
}
SetLocalAngularVelocity( angVel );
// sideways drag
vecVel.x = vecVel.x * (1.0 - fabs( right.x ) * 0.05);
vecVel.y = vecVel.y * (1.0 - fabs( right.y ) * 0.05);
vecVel.z = vecVel.z * (1.0 - fabs( right.z ) * 0.05);
// general drag
vecVel = vecVel * 0.995;
// Set final computed velocity
SetAbsVelocity( vecVel );
// apply power to stay correct height
if (m_flForce < 80 && vecEst.z < m_vecDesiredPosition.z)
{
m_flForce += 12;
}
else if (m_flForce > 30)
{
if (vecEst.z > m_vecDesiredPosition.z)
m_flForce -= 8;
}
angVel = GetLocalAngularVelocity();
// pitch forward or back to get to target
if (flDist > 0 && flSpeed < m_flGoalSpeed && GetAbsAngles().x + angVel.x < 40)
{
// ALERT( at_console, "F " );
// lean forward
angVel.x += 12.0;
}
else if (flDist < 0 && flSpeed > -50 && GetAbsAngles().x + angVel.x > -20)
{
// ALERT( at_console, "B " );
// lean backward
angVel.x -= 12.0;
}
else if (GetAbsAngles().x + angVel.x < 0)
{
// ALERT( at_console, "f " );
angVel.x += 4.0;
}
else if (GetAbsAngles().x + angVel.x > 0)
{
// ALERT( at_console, "b " );
angVel.x -= 4.0;
}
// Set final computed angular velocity
SetLocalAngularVelocity( angVel );
// ALERT( at_console, "%.0f %.0f : %.0f %.0f : %.0f %.0f : %.0f\n", GetAbsOrigin().x, pev->velocity.x, flDist, flSpeed, GetAbsAngles().x, pev->avelocity.x, m_flForce );
// ALERT( at_console, "%.0f %.0f : %.0f %0.f : %.0f\n", GetAbsOrigin().z, pev->velocity.z, vecEst.z, m_posDesired.z, m_flForce );
}
//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -