aboutsummaryrefslogtreecommitdiff
path: root/sp/src/game/server/hl2/npc_missiledefense.cpp
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /sp/src/game/server/hl2/npc_missiledefense.cpp
parentMark some more files as text. (diff)
downloadsource-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz
source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip
Fix line endings. WHAMMY.
Diffstat (limited to 'sp/src/game/server/hl2/npc_missiledefense.cpp')
-rw-r--r--sp/src/game/server/hl2/npc_missiledefense.cpp992
1 files changed, 496 insertions, 496 deletions
diff --git a/sp/src/game/server/hl2/npc_missiledefense.cpp b/sp/src/game/server/hl2/npc_missiledefense.cpp
index 5f77e2a5..f07984cf 100644
--- a/sp/src/game/server/hl2/npc_missiledefense.cpp
+++ b/sp/src/game/server/hl2/npc_missiledefense.cpp
@@ -1,496 +1,496 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//=============================================================================//
-
-#include "cbase.h"
-#include "ai_basenpc.h"
-#include "ai_hull.h"
-#include "ai_senses.h"
-#include "ai_memory.h"
-#include "soundent.h"
-#include "smoke_trail.h"
-#include "weapon_rpg.h"
-#include "gib.h"
-#include "ndebugoverlay.h"
-#include "IEffects.h"
-#include "vstdlib/random.h"
-#include "engine/IEngineSound.h"
-#include "ammodef.h"
-#include "hl2_shareddefs.h"
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-#define MD_FULLAMMO 50
-
-
-#define MD_BC_YAW 0
-#define MD_BC_PITCH 1
-#define MD_AP_LGUN 2
-#define MD_AP_RGUN 1
-#define MD_GIB_COUNT 4
-#define MD_GIB_MODEL "models/gibs/missile_defense_gibs.mdl"
-#define MD_YAW_SPEED 24
-#define MD_PITCH_SPEED 12
-
-//=========================================================
-//=========================================================
-class CNPC_MissileDefense : public CAI_BaseNPC
-{
- DECLARE_CLASS( CNPC_MissileDefense, CAI_BaseNPC );
- DECLARE_DATADESC();
-
-public:
- CNPC_MissileDefense( void ) { };
- void Precache( void );
- void Spawn( void );
- Class_T Classify( void ) { return CLASS_NONE; }
- int GetSoundInterests( void ) { return SOUND_NONE; }
- float MaxYawSpeed( void ) { return 90.f; }
-
- void RunAI(void);
- void FireCannons( void );
- void AimGun( void );
- void EnemyShootPosition(CBaseEntity* pEnemy, Vector *vPosition);
-
- void Event_Killed( const CTakeDamageInfo &info );
- int OnTakeDamage_Alive( const CTakeDamageInfo &info );
- void Gib();
- void GetGunAim( Vector *vecAim );
- ~CNPC_MissileDefense();
-
- Vector m_vGunAng;
- int m_iAmmoLoaded;
- float m_flReloadedTime;
-};
-
-LINK_ENTITY_TO_CLASS( npc_missiledefense, CNPC_MissileDefense );
-
-//=========================================================
-//=========================================================
-BEGIN_DATADESC( CNPC_MissileDefense )
-
- DEFINE_FIELD( m_iAmmoLoaded, FIELD_INTEGER ),
- DEFINE_FIELD( m_flReloadedTime, FIELD_TIME ),
- DEFINE_FIELD( m_vGunAng, FIELD_VECTOR ),
-
-END_DATADESC()
-
-//---------------------------------------------------------
-//---------------------------------------------------------
-void CNPC_MissileDefense::Precache( void )
-{
- PrecacheModel("models/missile_defense.mdl");
- PrecacheModel(MD_GIB_MODEL);
-
- PrecacheScriptSound( "NPC_MissileDefense.Attack" );
- PrecacheScriptSound( "NPC_MissileDefense.Reload" );
- PrecacheScriptSound( "NPC_MissileDefense.Turn" );
-
-}
-
-
-//---------------------------------------------------------
-//---------------------------------------------------------
-void CNPC_MissileDefense::GetGunAim( Vector *vecAim )
-{
- Vector vecPos;
- QAngle vecAng;
-
- GetAttachment( MD_AP_LGUN, vecPos, vecAng );
-
- vecAng.x = GetLocalAngles().x + GetBoneController( MD_BC_PITCH );
- vecAng.z = 0;
- vecAng.y = GetLocalAngles().y + GetBoneController( MD_BC_YAW );
-
- Vector vecForward;
- AngleVectors( vecAng, &vecForward );
-
- *vecAim = vecForward;
-}
-
-
-#define NOISE 0.035f
-#define MD_ATTN_CANNON 0.4
-//------------------------------------------------------------------------------
-// Purpose :
-// Input :
-// Output :
-//------------------------------------------------------------------------------
-void CNPC_MissileDefense::FireCannons( void )
-{
- // ----------------------------------------------
- // Make sure I have an enemy
- // ----------------------------------------------
- if (GetEnemy() == NULL)
- {
- return;
- }
-
- // ----------------------------------------------
- // Make sure I have ammo
- // ----------------------------------------------
- if( m_iAmmoLoaded < 1 )
- {
- return;
- }
- // ----------------------------------------------
- // Make sure gun it pointing in right direction
- // ----------------------------------------------
- Vector vGunDir;
- GetGunAim( &vGunDir );
- Vector vTargetPos;
- EnemyShootPosition(GetEnemy(),&vTargetPos);
-
- Vector vTargetDir = vTargetPos - GetAbsOrigin();
- VectorNormalize( vTargetDir );
-
- float fDotPr = DotProduct( vGunDir, vTargetDir );
- if (fDotPr < 0.95)
- {
- return;
- }
-
- // ----------------------------------------------
- // Check line of sight
- // ----------------------------------------------
- trace_t tr;
- AI_TraceLine( GetEnemy()->EyePosition(), GetAbsOrigin(), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr);
- if (tr.fraction < 1.0)
- {
- return;
- }
-
- Vector vecRight;
- Vector vecDir;
- Vector vecCenter;
- AngleVectors( GetLocalAngles(), NULL, &vecRight, NULL );
-
- vecCenter = WorldSpaceCenter();
-
- if( GetEnemy() == NULL )
- {
- return;
- }
-
- bool fSound = false;
- if( random->RandomInt( 0, 3 ) == 0 )
- {
- fSound = true;
- }
-
-
- EmitSound( "NPC_MissileDefense.Attack" );
-
- Vector vecGun;
- QAngle vecAng;
-
- GetAttachment( MD_AP_LGUN, vecGun, vecAng );
-
- Vector vecTarget;
- EnemyShootPosition(GetEnemy(),&vecTarget);
-
- vecDir = vecTarget - vecCenter;
- VectorNormalize(vecDir);
- vecDir.x += random->RandomFloat( -NOISE, NOISE );
- vecDir.y += random->RandomFloat( -NOISE, NOISE );
-
- Vector vecStart = vecGun + vecDir * 110;
- Vector vecEnd = vecGun + vecDir * 4096;
- UTIL_Tracer( vecStart, vecEnd, 0, TRACER_DONT_USE_ATTACHMENT, 3000 + random->RandomFloat( 0, 2000 ), fSound );
-
- vecDir = vecTarget - vecCenter;
- VectorNormalize(vecDir);
- vecDir.x += random->RandomFloat( -NOISE, NOISE );
- vecDir.y += random->RandomFloat( -NOISE, NOISE );
- vecDir.z += random->RandomFloat( -NOISE, NOISE );
-
- GetAttachment( MD_AP_RGUN, vecGun, vecAng );
- vecStart = vecGun + vecDir * 110;
- vecEnd = vecGun + vecDir * 4096;
- UTIL_Tracer( vecStart, vecEnd, 0, TRACER_DONT_USE_ATTACHMENT, 3000 + random->RandomFloat( 0, 2000 ) );
-
- m_iAmmoLoaded -= 2;
-
- if( m_iAmmoLoaded < 1 )
- {
- // Incite a reload.
- EmitSound( "NPC_MissileDefense.Reload" );
- m_flReloadedTime = gpGlobals->curtime + 0.3;
- return;
- }
-
- // Do damage to the missile based on distance.
- // if < 1, make damage 0.
-
- float flDist = (GetEnemy()->GetLocalOrigin() - vecGun).Length();
- float flDamage;
-
- flDamage = 4000 - flDist;
-
- flDamage /= 1000.0;
-
- if( flDamage > 0 )
- {
- if( flDist <= 1500 )
- {
- flDamage *= 2;
- }
-
- CTakeDamageInfo info( this, this, flDamage, DMG_MISSILEDEFENSE );
- CalculateBulletDamageForce( &info, GetAmmoDef()->Index("SMG1"), vecDir, GetEnemy()->GetAbsOrigin() );
- GetEnemy()->TakeDamage( info );
- }
-}
-
-
-//---------------------------------------------------------
-//---------------------------------------------------------
-void CNPC_MissileDefense::Spawn( void )
-{
- Precache();
-
- SetModel( "models/missile_defense.mdl" );
- UTIL_SetSize( this, Vector( -36, -36 , 0 ), Vector( 36, 36, 64 ) );
-
- SetSolid( SOLID_BBOX );
- SetMoveType( MOVETYPE_NONE );
- m_takedamage = DAMAGE_YES;
- SetBloodColor( DONT_BLEED );
- m_iHealth = 10;
- m_flFieldOfView = 0.1;
- m_NPCState = NPC_STATE_NONE;
- CapabilitiesClear();
- CapabilitiesAdd ( bits_CAP_INNATE_RANGE_ATTACK1 );
-
- // Hate missiles
- AddClassRelationship( CLASS_MISSILE, D_HT, 5 );
-
- m_spawnflags |= SF_NPC_LONG_RANGE;
-
- m_flReloadedTime = gpGlobals->curtime;
-
- InitBoneControllers();
-
- NPCInit();
-
- SetBoneController( MD_BC_YAW, 10 );
- SetBoneController( MD_BC_PITCH, 0 );
-
- SetBodygroup( 1, 1 );
- SetBodygroup( 2, 1 );
- SetBodygroup( 3, 1 );
- SetBodygroup( 4, 1 );
-
- m_NPCState = NPC_STATE_IDLE;
-}
-
-//------------------------------------------------------------------------------
-// Purpose :
-// Input :
-// Output :
-//------------------------------------------------------------------------------
-int CNPC_MissileDefense::OnTakeDamage_Alive( const CTakeDamageInfo &info )
-{
- // Only take blast damage
- if (info.GetDamageType() & DMG_BLAST )
- {
- return BaseClass::OnTakeDamage_Alive( info );
- }
- else
- {
- return 0;
- }
-}
-
-//------------------------------------------------------------------------------
-// Purpose :
-// Input :
-// Output :
-//------------------------------------------------------------------------------
-void CNPC_MissileDefense::Event_Killed( const CTakeDamageInfo &info )
-{
- StopSound( "NPC_MissileDefense.Turn" );
- Gib();
-}
-
-//------------------------------------------------------------------------------
-// Purpose :
-// Input :
-// Output :
-//------------------------------------------------------------------------------
-void CNPC_MissileDefense::Gib(void)
-{
- // Sparks
- for (int i = 0; i < 4; i++)
- {
- Vector sparkPos = GetAbsOrigin();
- sparkPos.x += random->RandomFloat(-12,12);
- sparkPos.y += random->RandomFloat(-12,12);
- sparkPos.z += random->RandomFloat(-12,12);
- g_pEffects->Sparks(sparkPos);
- }
- // Smoke
- UTIL_Smoke(GetAbsOrigin(), random->RandomInt(10, 15), 10);
-
- // Light
- CBroadcastRecipientFilter filter;
-
- te->DynamicLight( filter, 0.0,
- &GetAbsOrigin(), 255, 180, 100, 0, 100, 0.1, 0 );
-
- // Remove top parts
- SetBodygroup( 1, 0 );
- SetBodygroup( 2, 0 );
- SetBodygroup( 3, 0 );
- SetBodygroup( 4, 0 );
- m_takedamage = 0;
- SetThink(NULL);
-
- // Throw manhackgibs
- CGib::SpawnSpecificGibs( this, MD_GIB_COUNT, 300, 500, MD_GIB_MODEL);
-}
-
-//------------------------------------------------------------------------------
-// Purpose :
-// Input :
-// Output :
-//------------------------------------------------------------------------------
-void CNPC_MissileDefense::RunAI( void )
-{
- // If my enemy is dead clear the memory and reset m_hEnemy
- if (GetEnemy() != NULL &&
- !GetEnemy()->IsAlive())
- {
- ClearEnemyMemory();
- SetEnemy( NULL );
- }
-
- if (GetEnemy() == NULL )
- {
- GetSenses()->Look( 4092 );
- SetEnemy( BestEnemy( ) );
-
- if (GetEnemy() != NULL)
- {
- m_iAmmoLoaded = MD_FULLAMMO;
- m_flReloadedTime = gpGlobals->curtime;
- }
- }
-
- if( m_iAmmoLoaded < 1 && gpGlobals->curtime > m_flReloadedTime )
- {
- m_iAmmoLoaded = MD_FULLAMMO;
- }
-
- AimGun();
- FireCannons();
- SetNextThink( gpGlobals->curtime + 0.05 );
-}
-
-//------------------------------------------------------------------------------
-// Purpose : Add a little prediction into my enemy aim position
-// Input :
-// Output :
-//------------------------------------------------------------------------------
-void CNPC_MissileDefense::EnemyShootPosition(CBaseEntity* pEnemy, Vector *vPosition)
-{
- // This should never happen, but just in case
- if (!pEnemy)
- {
- return;
- }
-
- *vPosition = pEnemy->GetAbsOrigin();
-
- // Add prediction but prevents us from flipping around as enemy approaches us
- float flDist = (pEnemy->GetAbsOrigin() - GetAbsOrigin()).Length();
- Vector vPredVel = pEnemy->GetSmoothedVelocity() * 0.5;
- if ( flDist > vPredVel.Length())
- {
- *vPosition += vPredVel;
- }
-}
-
-//------------------------------------------------------------------------------
-// Purpose :
-// Input :
-// Output :
-//------------------------------------------------------------------------------
-void CNPC_MissileDefense::AimGun( void )
-{
- if (GetEnemy() == NULL)
- {
- StopSound( "NPC_MissileDefense.Turn" );
- return;
- }
-
- Vector forward, right, up;
- AngleVectors( GetLocalAngles(), &forward, &right, &up );
-
- // Get gun attachment points
- Vector vBasePos;
- QAngle vBaseAng;
- GetAttachment( MD_AP_LGUN, vBasePos, vBaseAng );
-
- Vector vTargetPos;
- EnemyShootPosition(GetEnemy(),&vTargetPos);
-
- Vector vTargetDir = vTargetPos - vBasePos;
- VectorNormalize( vTargetDir );
-
- Vector vecOut;
- vecOut.x = DotProduct( forward, vTargetDir );
- vecOut.y = -DotProduct( right, vTargetDir );
- vecOut.z = DotProduct( up, vTargetDir );
-
- QAngle angles;
- VectorAngles(vecOut, angles);
-
- if (angles.y > 180)
- angles.y = angles.y - 360;
- if (angles.y < -180)
- angles.y = angles.y + 360;
- if (angles.x > 180)
- angles.x = angles.x - 360;
- if (angles.x < -180)
- angles.x = angles.x + 360;
-
- float flOldX = m_vGunAng.x;
- float flOldY = m_vGunAng.y;
-
- if (angles.x > m_vGunAng.x)
- m_vGunAng.x = MIN( angles.x, m_vGunAng.x + MD_PITCH_SPEED );
- if (angles.x < m_vGunAng.x)
- m_vGunAng.x = MAX( angles.x, m_vGunAng.x - MD_PITCH_SPEED );
- if (angles.y > m_vGunAng.y)
- m_vGunAng.y = MIN( angles.y, m_vGunAng.y + MD_YAW_SPEED );
- if (angles.y < m_vGunAng.y)
- m_vGunAng.y = MAX( angles.y, m_vGunAng.y - MD_YAW_SPEED );
-
- m_vGunAng.y = SetBoneController( MD_BC_YAW, m_vGunAng.y );
- m_vGunAng.x = SetBoneController( MD_BC_PITCH, m_vGunAng.x );
-
- if (flOldX != m_vGunAng.x || flOldY != m_vGunAng.y)
- {
- EmitSound( "NPC_MissileDefense.Turn" );
- }
- else
- {
- StopSound( "NPC_MissileDefense.Turn" );
- }
-}
-
-
-//------------------------------------------------------------------------------
-// Purpose :
-// Input :
-// Output :
-//------------------------------------------------------------------------------
-CNPC_MissileDefense::~CNPC_MissileDefense(void)
-{
- StopSound( "NPC_MissileDefense.Turn" );
-}
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "ai_basenpc.h"
+#include "ai_hull.h"
+#include "ai_senses.h"
+#include "ai_memory.h"
+#include "soundent.h"
+#include "smoke_trail.h"
+#include "weapon_rpg.h"
+#include "gib.h"
+#include "ndebugoverlay.h"
+#include "IEffects.h"
+#include "vstdlib/random.h"
+#include "engine/IEngineSound.h"
+#include "ammodef.h"
+#include "hl2_shareddefs.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+#define MD_FULLAMMO 50
+
+
+#define MD_BC_YAW 0
+#define MD_BC_PITCH 1
+#define MD_AP_LGUN 2
+#define MD_AP_RGUN 1
+#define MD_GIB_COUNT 4
+#define MD_GIB_MODEL "models/gibs/missile_defense_gibs.mdl"
+#define MD_YAW_SPEED 24
+#define MD_PITCH_SPEED 12
+
+//=========================================================
+//=========================================================
+class CNPC_MissileDefense : public CAI_BaseNPC
+{
+ DECLARE_CLASS( CNPC_MissileDefense, CAI_BaseNPC );
+ DECLARE_DATADESC();
+
+public:
+ CNPC_MissileDefense( void ) { };
+ void Precache( void );
+ void Spawn( void );
+ Class_T Classify( void ) { return CLASS_NONE; }
+ int GetSoundInterests( void ) { return SOUND_NONE; }
+ float MaxYawSpeed( void ) { return 90.f; }
+
+ void RunAI(void);
+ void FireCannons( void );
+ void AimGun( void );
+ void EnemyShootPosition(CBaseEntity* pEnemy, Vector *vPosition);
+
+ void Event_Killed( const CTakeDamageInfo &info );
+ int OnTakeDamage_Alive( const CTakeDamageInfo &info );
+ void Gib();
+ void GetGunAim( Vector *vecAim );
+ ~CNPC_MissileDefense();
+
+ Vector m_vGunAng;
+ int m_iAmmoLoaded;
+ float m_flReloadedTime;
+};
+
+LINK_ENTITY_TO_CLASS( npc_missiledefense, CNPC_MissileDefense );
+
+//=========================================================
+//=========================================================
+BEGIN_DATADESC( CNPC_MissileDefense )
+
+ DEFINE_FIELD( m_iAmmoLoaded, FIELD_INTEGER ),
+ DEFINE_FIELD( m_flReloadedTime, FIELD_TIME ),
+ DEFINE_FIELD( m_vGunAng, FIELD_VECTOR ),
+
+END_DATADESC()
+
+//---------------------------------------------------------
+//---------------------------------------------------------
+void CNPC_MissileDefense::Precache( void )
+{
+ PrecacheModel("models/missile_defense.mdl");
+ PrecacheModel(MD_GIB_MODEL);
+
+ PrecacheScriptSound( "NPC_MissileDefense.Attack" );
+ PrecacheScriptSound( "NPC_MissileDefense.Reload" );
+ PrecacheScriptSound( "NPC_MissileDefense.Turn" );
+
+}
+
+
+//---------------------------------------------------------
+//---------------------------------------------------------
+void CNPC_MissileDefense::GetGunAim( Vector *vecAim )
+{
+ Vector vecPos;
+ QAngle vecAng;
+
+ GetAttachment( MD_AP_LGUN, vecPos, vecAng );
+
+ vecAng.x = GetLocalAngles().x + GetBoneController( MD_BC_PITCH );
+ vecAng.z = 0;
+ vecAng.y = GetLocalAngles().y + GetBoneController( MD_BC_YAW );
+
+ Vector vecForward;
+ AngleVectors( vecAng, &vecForward );
+
+ *vecAim = vecForward;
+}
+
+
+#define NOISE 0.035f
+#define MD_ATTN_CANNON 0.4
+//------------------------------------------------------------------------------
+// Purpose :
+// Input :
+// Output :
+//------------------------------------------------------------------------------
+void CNPC_MissileDefense::FireCannons( void )
+{
+ // ----------------------------------------------
+ // Make sure I have an enemy
+ // ----------------------------------------------
+ if (GetEnemy() == NULL)
+ {
+ return;
+ }
+
+ // ----------------------------------------------
+ // Make sure I have ammo
+ // ----------------------------------------------
+ if( m_iAmmoLoaded < 1 )
+ {
+ return;
+ }
+ // ----------------------------------------------
+ // Make sure gun it pointing in right direction
+ // ----------------------------------------------
+ Vector vGunDir;
+ GetGunAim( &vGunDir );
+ Vector vTargetPos;
+ EnemyShootPosition(GetEnemy(),&vTargetPos);
+
+ Vector vTargetDir = vTargetPos - GetAbsOrigin();
+ VectorNormalize( vTargetDir );
+
+ float fDotPr = DotProduct( vGunDir, vTargetDir );
+ if (fDotPr < 0.95)
+ {
+ return;
+ }
+
+ // ----------------------------------------------
+ // Check line of sight
+ // ----------------------------------------------
+ trace_t tr;
+ AI_TraceLine( GetEnemy()->EyePosition(), GetAbsOrigin(), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr);
+ if (tr.fraction < 1.0)
+ {
+ return;
+ }
+
+ Vector vecRight;
+ Vector vecDir;
+ Vector vecCenter;
+ AngleVectors( GetLocalAngles(), NULL, &vecRight, NULL );
+
+ vecCenter = WorldSpaceCenter();
+
+ if( GetEnemy() == NULL )
+ {
+ return;
+ }
+
+ bool fSound = false;
+ if( random->RandomInt( 0, 3 ) == 0 )
+ {
+ fSound = true;
+ }
+
+
+ EmitSound( "NPC_MissileDefense.Attack" );
+
+ Vector vecGun;
+ QAngle vecAng;
+
+ GetAttachment( MD_AP_LGUN, vecGun, vecAng );
+
+ Vector vecTarget;
+ EnemyShootPosition(GetEnemy(),&vecTarget);
+
+ vecDir = vecTarget - vecCenter;
+ VectorNormalize(vecDir);
+ vecDir.x += random->RandomFloat( -NOISE, NOISE );
+ vecDir.y += random->RandomFloat( -NOISE, NOISE );
+
+ Vector vecStart = vecGun + vecDir * 110;
+ Vector vecEnd = vecGun + vecDir * 4096;
+ UTIL_Tracer( vecStart, vecEnd, 0, TRACER_DONT_USE_ATTACHMENT, 3000 + random->RandomFloat( 0, 2000 ), fSound );
+
+ vecDir = vecTarget - vecCenter;
+ VectorNormalize(vecDir);
+ vecDir.x += random->RandomFloat( -NOISE, NOISE );
+ vecDir.y += random->RandomFloat( -NOISE, NOISE );
+ vecDir.z += random->RandomFloat( -NOISE, NOISE );
+
+ GetAttachment( MD_AP_RGUN, vecGun, vecAng );
+ vecStart = vecGun + vecDir * 110;
+ vecEnd = vecGun + vecDir * 4096;
+ UTIL_Tracer( vecStart, vecEnd, 0, TRACER_DONT_USE_ATTACHMENT, 3000 + random->RandomFloat( 0, 2000 ) );
+
+ m_iAmmoLoaded -= 2;
+
+ if( m_iAmmoLoaded < 1 )
+ {
+ // Incite a reload.
+ EmitSound( "NPC_MissileDefense.Reload" );
+ m_flReloadedTime = gpGlobals->curtime + 0.3;
+ return;
+ }
+
+ // Do damage to the missile based on distance.
+ // if < 1, make damage 0.
+
+ float flDist = (GetEnemy()->GetLocalOrigin() - vecGun).Length();
+ float flDamage;
+
+ flDamage = 4000 - flDist;
+
+ flDamage /= 1000.0;
+
+ if( flDamage > 0 )
+ {
+ if( flDist <= 1500 )
+ {
+ flDamage *= 2;
+ }
+
+ CTakeDamageInfo info( this, this, flDamage, DMG_MISSILEDEFENSE );
+ CalculateBulletDamageForce( &info, GetAmmoDef()->Index("SMG1"), vecDir, GetEnemy()->GetAbsOrigin() );
+ GetEnemy()->TakeDamage( info );
+ }
+}
+
+
+//---------------------------------------------------------
+//---------------------------------------------------------
+void CNPC_MissileDefense::Spawn( void )
+{
+ Precache();
+
+ SetModel( "models/missile_defense.mdl" );
+ UTIL_SetSize( this, Vector( -36, -36 , 0 ), Vector( 36, 36, 64 ) );
+
+ SetSolid( SOLID_BBOX );
+ SetMoveType( MOVETYPE_NONE );
+ m_takedamage = DAMAGE_YES;
+ SetBloodColor( DONT_BLEED );
+ m_iHealth = 10;
+ m_flFieldOfView = 0.1;
+ m_NPCState = NPC_STATE_NONE;
+ CapabilitiesClear();
+ CapabilitiesAdd ( bits_CAP_INNATE_RANGE_ATTACK1 );
+
+ // Hate missiles
+ AddClassRelationship( CLASS_MISSILE, D_HT, 5 );
+
+ m_spawnflags |= SF_NPC_LONG_RANGE;
+
+ m_flReloadedTime = gpGlobals->curtime;
+
+ InitBoneControllers();
+
+ NPCInit();
+
+ SetBoneController( MD_BC_YAW, 10 );
+ SetBoneController( MD_BC_PITCH, 0 );
+
+ SetBodygroup( 1, 1 );
+ SetBodygroup( 2, 1 );
+ SetBodygroup( 3, 1 );
+ SetBodygroup( 4, 1 );
+
+ m_NPCState = NPC_STATE_IDLE;
+}
+
+//------------------------------------------------------------------------------
+// Purpose :
+// Input :
+// Output :
+//------------------------------------------------------------------------------
+int CNPC_MissileDefense::OnTakeDamage_Alive( const CTakeDamageInfo &info )
+{
+ // Only take blast damage
+ if (info.GetDamageType() & DMG_BLAST )
+ {
+ return BaseClass::OnTakeDamage_Alive( info );
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Purpose :
+// Input :
+// Output :
+//------------------------------------------------------------------------------
+void CNPC_MissileDefense::Event_Killed( const CTakeDamageInfo &info )
+{
+ StopSound( "NPC_MissileDefense.Turn" );
+ Gib();
+}
+
+//------------------------------------------------------------------------------
+// Purpose :
+// Input :
+// Output :
+//------------------------------------------------------------------------------
+void CNPC_MissileDefense::Gib(void)
+{
+ // Sparks
+ for (int i = 0; i < 4; i++)
+ {
+ Vector sparkPos = GetAbsOrigin();
+ sparkPos.x += random->RandomFloat(-12,12);
+ sparkPos.y += random->RandomFloat(-12,12);
+ sparkPos.z += random->RandomFloat(-12,12);
+ g_pEffects->Sparks(sparkPos);
+ }
+ // Smoke
+ UTIL_Smoke(GetAbsOrigin(), random->RandomInt(10, 15), 10);
+
+ // Light
+ CBroadcastRecipientFilter filter;
+
+ te->DynamicLight( filter, 0.0,
+ &GetAbsOrigin(), 255, 180, 100, 0, 100, 0.1, 0 );
+
+ // Remove top parts
+ SetBodygroup( 1, 0 );
+ SetBodygroup( 2, 0 );
+ SetBodygroup( 3, 0 );
+ SetBodygroup( 4, 0 );
+ m_takedamage = 0;
+ SetThink(NULL);
+
+ // Throw manhackgibs
+ CGib::SpawnSpecificGibs( this, MD_GIB_COUNT, 300, 500, MD_GIB_MODEL);
+}
+
+//------------------------------------------------------------------------------
+// Purpose :
+// Input :
+// Output :
+//------------------------------------------------------------------------------
+void CNPC_MissileDefense::RunAI( void )
+{
+ // If my enemy is dead clear the memory and reset m_hEnemy
+ if (GetEnemy() != NULL &&
+ !GetEnemy()->IsAlive())
+ {
+ ClearEnemyMemory();
+ SetEnemy( NULL );
+ }
+
+ if (GetEnemy() == NULL )
+ {
+ GetSenses()->Look( 4092 );
+ SetEnemy( BestEnemy( ) );
+
+ if (GetEnemy() != NULL)
+ {
+ m_iAmmoLoaded = MD_FULLAMMO;
+ m_flReloadedTime = gpGlobals->curtime;
+ }
+ }
+
+ if( m_iAmmoLoaded < 1 && gpGlobals->curtime > m_flReloadedTime )
+ {
+ m_iAmmoLoaded = MD_FULLAMMO;
+ }
+
+ AimGun();
+ FireCannons();
+ SetNextThink( gpGlobals->curtime + 0.05 );
+}
+
+//------------------------------------------------------------------------------
+// Purpose : Add a little prediction into my enemy aim position
+// Input :
+// Output :
+//------------------------------------------------------------------------------
+void CNPC_MissileDefense::EnemyShootPosition(CBaseEntity* pEnemy, Vector *vPosition)
+{
+ // This should never happen, but just in case
+ if (!pEnemy)
+ {
+ return;
+ }
+
+ *vPosition = pEnemy->GetAbsOrigin();
+
+ // Add prediction but prevents us from flipping around as enemy approaches us
+ float flDist = (pEnemy->GetAbsOrigin() - GetAbsOrigin()).Length();
+ Vector vPredVel = pEnemy->GetSmoothedVelocity() * 0.5;
+ if ( flDist > vPredVel.Length())
+ {
+ *vPosition += vPredVel;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Purpose :
+// Input :
+// Output :
+//------------------------------------------------------------------------------
+void CNPC_MissileDefense::AimGun( void )
+{
+ if (GetEnemy() == NULL)
+ {
+ StopSound( "NPC_MissileDefense.Turn" );
+ return;
+ }
+
+ Vector forward, right, up;
+ AngleVectors( GetLocalAngles(), &forward, &right, &up );
+
+ // Get gun attachment points
+ Vector vBasePos;
+ QAngle vBaseAng;
+ GetAttachment( MD_AP_LGUN, vBasePos, vBaseAng );
+
+ Vector vTargetPos;
+ EnemyShootPosition(GetEnemy(),&vTargetPos);
+
+ Vector vTargetDir = vTargetPos - vBasePos;
+ VectorNormalize( vTargetDir );
+
+ Vector vecOut;
+ vecOut.x = DotProduct( forward, vTargetDir );
+ vecOut.y = -DotProduct( right, vTargetDir );
+ vecOut.z = DotProduct( up, vTargetDir );
+
+ QAngle angles;
+ VectorAngles(vecOut, angles);
+
+ if (angles.y > 180)
+ angles.y = angles.y - 360;
+ if (angles.y < -180)
+ angles.y = angles.y + 360;
+ if (angles.x > 180)
+ angles.x = angles.x - 360;
+ if (angles.x < -180)
+ angles.x = angles.x + 360;
+
+ float flOldX = m_vGunAng.x;
+ float flOldY = m_vGunAng.y;
+
+ if (angles.x > m_vGunAng.x)
+ m_vGunAng.x = MIN( angles.x, m_vGunAng.x + MD_PITCH_SPEED );
+ if (angles.x < m_vGunAng.x)
+ m_vGunAng.x = MAX( angles.x, m_vGunAng.x - MD_PITCH_SPEED );
+ if (angles.y > m_vGunAng.y)
+ m_vGunAng.y = MIN( angles.y, m_vGunAng.y + MD_YAW_SPEED );
+ if (angles.y < m_vGunAng.y)
+ m_vGunAng.y = MAX( angles.y, m_vGunAng.y - MD_YAW_SPEED );
+
+ m_vGunAng.y = SetBoneController( MD_BC_YAW, m_vGunAng.y );
+ m_vGunAng.x = SetBoneController( MD_BC_PITCH, m_vGunAng.x );
+
+ if (flOldX != m_vGunAng.x || flOldY != m_vGunAng.y)
+ {
+ EmitSound( "NPC_MissileDefense.Turn" );
+ }
+ else
+ {
+ StopSound( "NPC_MissileDefense.Turn" );
+ }
+}
+
+
+//------------------------------------------------------------------------------
+// Purpose :
+// Input :
+// Output :
+//------------------------------------------------------------------------------
+CNPC_MissileDefense::~CNPC_MissileDefense(void)
+{
+ StopSound( "NPC_MissileDefense.Turn" );
+}