aboutsummaryrefslogtreecommitdiff
path: root/sp/src/game/server/hl2/npc_launcher.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_launcher.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_launcher.cpp')
-rw-r--r--sp/src/game/server/hl2/npc_launcher.cpp826
1 files changed, 413 insertions, 413 deletions
diff --git a/sp/src/game/server/hl2/npc_launcher.cpp b/sp/src/game/server/hl2/npc_launcher.cpp
index 098c6b4e..9e942862 100644
--- a/sp/src/game/server/hl2/npc_launcher.cpp
+++ b/sp/src/game/server/hl2/npc_launcher.cpp
@@ -1,413 +1,413 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//=============================================================================//
-
-#include "cbase.h"
-#include "ai_basenpc.h"
-#include "ai_senses.h"
-#include "ai_squad.h"
-#include "grenade_homer.h"
-#include "grenade_pathfollower.h"
-#include "explode.h"
-#include "ndebugoverlay.h"
-#include "engine/IEngineSound.h"
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-#define LAUNCHER_REST_TIME 3
-
-
-//------------------------------------
-// Spawnflags
-//------------------------------------
-#define SF_LAUNCHER_CHECK_LOS (1 << 16)
-
-
-//=========================================================
-// >> CNPC_Launcher
-//=========================================================
-class CNPC_Launcher : public CAI_BaseNPC
-{
- DECLARE_CLASS( CNPC_Launcher, CAI_BaseNPC );
-
-public:
- int m_nStartOn;
- string_t m_sMissileModel;
- string_t m_sLaunchSound;
- string_t m_sFlySound;
- int m_nSmokeTrail;
- bool m_bSmokeLaunch;
- int m_nLaunchDelay;
- float m_flLaunchSpeed;
- string_t m_sPathCornerName; // If following a path
- float m_flHomingSpeed;
- int m_nHomingStrength;
- float m_flHomingDelay; // How long before homing starts
- float m_flHomingRampUp; // How much time to ramp up to full homing
- float m_flHomingDuration; // How long does homing last
- float m_flHomingRampDown; // How long to ramp down to no homing
- float m_flMissileGravity;
- float m_flMinAttackDist;
- float m_flMaxAttackDist;
- float m_flSpinMagnitude;
- float m_flSpinSpeed;
- float m_flDamage;
- float m_flDamageRadius;
-
- // ----------------
- // Outputs
- // ----------------
- COutputEvent m_OnLaunch; // Triggered when missile is launched.
-
- // ----------------
- // Inputs
- // ----------------
- void InputTurnOn( inputdata_t &inputdata );
- void InputTurnOff( inputdata_t &inputdata );
- void InputLOSCheckOn( inputdata_t &inputdata );
- void InputLOSCheckOff( inputdata_t &inputdata );
- void InputSetEnemy( inputdata_t &inputdata );
- void InputClearEnemy( inputdata_t &inputdata );
- void InputFireOnce( inputdata_t &inputdata );
-
- void LauncherTurnOn(void);
-
- void Precache( void );
- void Spawn( void );
- Class_T Classify( void );
- bool IsValidEnemy(CBaseEntity *pTarget );
- void LaunchGrenade(CBaseEntity* pLauncher );
- void LauncherThink(void );
- bool FInViewCone( CBaseEntity *pEntity );
-
- int DrawDebugTextOverlays(void);
-
- DECLARE_DATADESC();
-};
-
-
-BEGIN_DATADESC( CNPC_Launcher )
-
- // Inputs
- DEFINE_KEYFIELD( m_nStartOn, FIELD_INTEGER, "StartOn" ),
- DEFINE_KEYFIELD( m_sMissileModel, FIELD_STRING, "MissileModel" ),
- DEFINE_KEYFIELD( m_sLaunchSound, FIELD_STRING, "LaunchSound" ),
- DEFINE_KEYFIELD( m_sFlySound, FIELD_STRING, "FlySound" ),
- DEFINE_KEYFIELD( m_nSmokeTrail, FIELD_INTEGER, "SmokeTrail" ),
- DEFINE_KEYFIELD( m_bSmokeLaunch, FIELD_BOOLEAN, "LaunchSmoke" ),
- DEFINE_KEYFIELD( m_nLaunchDelay, FIELD_INTEGER, "LaunchDelay" ),
- DEFINE_KEYFIELD( m_flLaunchSpeed, FIELD_FLOAT, "LaunchSpeed" ),
- DEFINE_KEYFIELD( m_sPathCornerName, FIELD_STRING, "PathCornerName" ),
- DEFINE_KEYFIELD( m_flHomingSpeed, FIELD_FLOAT, "HomingSpeed" ),
- DEFINE_KEYFIELD( m_nHomingStrength, FIELD_INTEGER, "HomingStrength" ),
- DEFINE_KEYFIELD( m_flHomingDelay, FIELD_FLOAT, "HomingDelay" ),
- DEFINE_KEYFIELD( m_flHomingRampUp, FIELD_FLOAT, "HomingRampUp" ),
- DEFINE_KEYFIELD( m_flHomingDuration, FIELD_FLOAT, "HomingDuration" ),
- DEFINE_KEYFIELD( m_flHomingRampDown, FIELD_FLOAT, "HomingRampDown" ),
- DEFINE_KEYFIELD( m_flGravity, FIELD_FLOAT, "Gravity" ),
- DEFINE_KEYFIELD( m_flMinAttackDist, FIELD_FLOAT, "MinRange" ),
- DEFINE_KEYFIELD( m_flMaxAttackDist, FIELD_FLOAT, "MaxRange" ),
- DEFINE_KEYFIELD( m_flSpinMagnitude, FIELD_FLOAT, "SpinMagnitude" ),
- DEFINE_KEYFIELD( m_flSpinSpeed, FIELD_FLOAT, "SpinSpeed" ),
- DEFINE_KEYFIELD( m_flDamage, FIELD_FLOAT, "Damage" ),
- DEFINE_KEYFIELD( m_flDamageRadius, FIELD_FLOAT, "DamageRadius" ),
- DEFINE_FIELD( m_flMissileGravity, FIELD_FLOAT ),
-
- DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ),
- DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ),
- DEFINE_INPUTFUNC( FIELD_VOID, "LOSCheckOn", InputLOSCheckOn ),
- DEFINE_INPUTFUNC( FIELD_VOID, "LOSCheckOn", InputLOSCheckOn ),
- DEFINE_INPUTFUNC( FIELD_VOID, "FireOnce", InputFireOnce ),
- DEFINE_INPUTFUNC( FIELD_EHANDLE, "SetEnemyEntity", InputSetEnemy ),
- DEFINE_INPUTFUNC( FIELD_VOID, "ClearEnemyEntity", InputClearEnemy ),
-
- DEFINE_OUTPUT( m_OnLaunch, "OnLaunch" ),
-
- // Function Pointers
- DEFINE_THINKFUNC( LauncherThink ),
-
-END_DATADESC()
-
-LINK_ENTITY_TO_CLASS( npc_launcher, CNPC_Launcher );
-
-
-// ===================
-// Input Functions
-// ===================
-void CNPC_Launcher::InputTurnOn( inputdata_t &inputdata )
-{
- LauncherTurnOn();
-}
-
-void CNPC_Launcher::InputTurnOff( inputdata_t &inputdata )
-{
- SetThink(NULL);
-}
-
-void CNPC_Launcher::InputLOSCheckOn( inputdata_t &inputdata )
-{
- m_spawnflags |= SF_LAUNCHER_CHECK_LOS;
-}
-
-void CNPC_Launcher::InputLOSCheckOff( inputdata_t &inputdata )
-{
- m_spawnflags &= ~SF_LAUNCHER_CHECK_LOS;
-}
-
-void CNPC_Launcher::InputSetEnemy( inputdata_t &inputdata )
-{
- SetEnemy( inputdata.value.Entity().Get() );
-}
-
-void CNPC_Launcher::InputClearEnemy( inputdata_t &inputdata )
-{
- SetEnemy( NULL );
-}
-
-void CNPC_Launcher::InputFireOnce( inputdata_t &inputdata )
-{
- m_flNextAttack = 0;
-
- // If I using path following missiles just launch
- if (m_sPathCornerName != NULL_STRING)
- {
- LaunchGrenade(NULL);
- }
- // Otherwise only launch if I have an enemy
- else
- {
- LauncherThink();
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CNPC_Launcher::Precache( void )
-{
- // This is a dummy model that is never used!
- PrecacheModel("models/player.mdl");
- PrecacheModel(STRING(m_sMissileModel));
- PrecacheScriptSound( STRING(m_sLaunchSound));
- PrecacheScriptSound( STRING(m_sFlySound));
-
- UTIL_PrecacheOther( "grenade_homer");
- BaseClass::Precache();
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CNPC_Launcher::LauncherTurnOn(void)
-{
- SetThink(&CNPC_Launcher::LauncherThink);
- SetNextThink( gpGlobals->curtime );
- m_flNextAttack = 0;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CNPC_Launcher::Spawn( void )
-{
- Precache();
-
- // This is a dummy model that is never used!
- SetModel( "models/player.mdl" );
-
- UTIL_SetSize(this, vec3_origin, vec3_origin);
-
- m_takedamage = DAMAGE_NO;
-
- if (m_nHomingStrength > 100)
- {
- m_nHomingStrength = 100;
- Warning("WARNING: NPC_Launcher Homing Strength must be between 0 and 100\n");
- }
-
- SetSolid( SOLID_NONE );
- SetMoveType( MOVETYPE_NONE );
- SetBloodColor( DONT_BLEED );
- AddEffects( EF_NODRAW );
-
- AddFlag( FL_NPC );
-
- CapabilitiesAdd( bits_CAP_SQUAD );
-
- InitRelationshipTable();
-
- if (m_nStartOn)
- {
- LauncherTurnOn();
- }
-
- // -------------------------------------------------------
- // If I form squads add me to a squad
- // -------------------------------------------------------
- // @TODO (toml 12-05-02): RECONCILE WITH SAVE/RESTORE
- if (!m_pSquad)
- {
- m_pSquad = g_AI_SquadManager.FindCreateSquad(this, m_SquadName);
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-Class_T CNPC_Launcher::Classify( void )
-{
- return CLASS_NONE;
-}
-
-//------------------------------------------------------------------------------
-// Purpose:
-//------------------------------------------------------------------------------
-void CNPC_Launcher::LaunchGrenade( CBaseEntity* pEnemy )
-{
- // If a path following missile, create a path following missile
- if (m_sPathCornerName != NULL_STRING)
- {
- CGrenadePathfollower *pGrenade = CGrenadePathfollower::CreateGrenadePathfollower( m_sMissileModel, m_sFlySound, GetAbsOrigin(), vec3_angle, edict() );
- pGrenade->SetDamage(m_flDamage);
- pGrenade->SetDamageRadius(m_flDamageRadius);
- pGrenade->Launch(m_flLaunchSpeed,m_sPathCornerName);
- }
- else
- {
- Vector vUp;
- AngleVectors( GetAbsAngles(), NULL, NULL, &vUp );
- Vector vLaunchVelocity = (vUp * m_flLaunchSpeed);
-
- CGrenadeHomer *pGrenade = CGrenadeHomer::CreateGrenadeHomer( m_sMissileModel, m_sFlySound, GetAbsOrigin(), vec3_angle, edict() );
- pGrenade->Spawn( );
- pGrenade->SetSpin(m_flSpinMagnitude,m_flSpinSpeed);
- pGrenade->SetHoming((0.01*m_nHomingStrength),m_flHomingDelay,m_flHomingRampUp,m_flHomingDuration,m_flHomingRampDown);
- pGrenade->SetDamage(m_flDamage);
- pGrenade->SetDamageRadius(m_flDamageRadius);
- pGrenade->Launch(this,pEnemy,vLaunchVelocity,m_flHomingSpeed,GetGravity(),m_nSmokeTrail);
- }
-
- CPASAttenuationFilter filter( this, 0.3 );
-
- EmitSound_t ep;
- ep.m_nChannel = CHAN_WEAPON;
- ep.m_pSoundName = STRING(m_sLaunchSound);
- ep.m_SoundLevel = SNDLVL_NORM;
-
- EmitSound( filter, entindex(), ep );
-
- if (m_bSmokeLaunch)
- {
- UTIL_Smoke(GetAbsOrigin(), random->RandomInt(20,30), random->RandomInt(10,15));
- }
- m_flNextAttack = gpGlobals->curtime + LAUNCHER_REST_TIME;
-
-}
-
-//------------------------------------------------------------------------------
-// Purpose : Launcher sees 360 degrees
-//------------------------------------------------------------------------------
-bool CNPC_Launcher::FInViewCone( CBaseEntity *pEntity )
-{
- return true;
-}
-
-//------------------------------------------------------------------------------
-// Purpose : Override base class to check range and visibility
-//------------------------------------------------------------------------------
-bool CNPC_Launcher::IsValidEnemy( CBaseEntity *pTarget )
-{
- // ---------------------------------
- // Check range
- // ---------------------------------
- float flTargetDist = (GetAbsOrigin() - pTarget->GetAbsOrigin()).Length();
- if (flTargetDist < m_flMinAttackDist)
- {
- return false;
- }
- if (flTargetDist > m_flMaxAttackDist)
- {
- return false;
- }
-
- if (!FBitSet (m_spawnflags, SF_LAUNCHER_CHECK_LOS))
- {
- return true;
- }
- // ------------------------------------------------------
- // Make sure I can see the target from above my position
- // ------------------------------------------------------
- trace_t tr;
-
- // Trace from launch position to target position.
- // Use position above actual barral based on vertical launch speed
- Vector vStartPos = GetAbsOrigin() + Vector(0,0,0.2*m_flLaunchSpeed);
- Vector vEndPos = pTarget->GetAbsOrigin();
- AI_TraceLine( vStartPos, vEndPos, MASK_SHOT, pTarget, COLLISION_GROUP_NONE, &tr );
-
- if (tr.fraction == 1.0)
- {
- return true;
- }
- return false;
-}
-
-//------------------------------------------------------------------------------
-// Purpose :
-//------------------------------------------------------------------------------
-void CNPC_Launcher::LauncherThink( void )
-{
- if (gpGlobals->curtime > m_flNextAttack)
- {
- // If enemy was set, fire at enemy
- if (GetEnemy())
- {
- LaunchGrenade(GetEnemy());
- m_OnLaunch.FireOutput(GetEnemy(), this);
- m_flNextAttack = gpGlobals->curtime + m_nLaunchDelay;
- }
- // Otherwise look for enemy to fire at
- else
- {
- GetSenses()->Look(m_flMaxAttackDist);
- CBaseEntity* pBestEnemy = BestEnemy();
-
- if (pBestEnemy)
- {
- LaunchGrenade(pBestEnemy);
- m_OnLaunch.FireOutput(pBestEnemy, this);
- m_flNextAttack = gpGlobals->curtime + m_nLaunchDelay;
- }
- }
- }
- SetNextThink( gpGlobals->curtime + 0.1f );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Draw any debug text overlays
-// Output : Current text offset from the top
-//-----------------------------------------------------------------------------
-int CNPC_Launcher::DrawDebugTextOverlays(void)
-{
- int text_offset = BaseClass::DrawDebugTextOverlays();
-
- if (m_debugOverlays & OVERLAY_TEXT_BIT)
- {
- char tempstr[512];
- Q_snprintf(tempstr,sizeof(tempstr),"State: %s", (m_pfnThink) ? "On" : "Off" );
- EntityText(text_offset,tempstr,0);
- text_offset++;
-
- Q_snprintf(tempstr,sizeof(tempstr),"LOS: %s", (FBitSet (m_spawnflags, SF_LAUNCHER_CHECK_LOS)) ? "On" : "Off" );
- EntityText(text_offset,tempstr,0);
- text_offset++;
- }
- return text_offset;
-}
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "ai_basenpc.h"
+#include "ai_senses.h"
+#include "ai_squad.h"
+#include "grenade_homer.h"
+#include "grenade_pathfollower.h"
+#include "explode.h"
+#include "ndebugoverlay.h"
+#include "engine/IEngineSound.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+#define LAUNCHER_REST_TIME 3
+
+
+//------------------------------------
+// Spawnflags
+//------------------------------------
+#define SF_LAUNCHER_CHECK_LOS (1 << 16)
+
+
+//=========================================================
+// >> CNPC_Launcher
+//=========================================================
+class CNPC_Launcher : public CAI_BaseNPC
+{
+ DECLARE_CLASS( CNPC_Launcher, CAI_BaseNPC );
+
+public:
+ int m_nStartOn;
+ string_t m_sMissileModel;
+ string_t m_sLaunchSound;
+ string_t m_sFlySound;
+ int m_nSmokeTrail;
+ bool m_bSmokeLaunch;
+ int m_nLaunchDelay;
+ float m_flLaunchSpeed;
+ string_t m_sPathCornerName; // If following a path
+ float m_flHomingSpeed;
+ int m_nHomingStrength;
+ float m_flHomingDelay; // How long before homing starts
+ float m_flHomingRampUp; // How much time to ramp up to full homing
+ float m_flHomingDuration; // How long does homing last
+ float m_flHomingRampDown; // How long to ramp down to no homing
+ float m_flMissileGravity;
+ float m_flMinAttackDist;
+ float m_flMaxAttackDist;
+ float m_flSpinMagnitude;
+ float m_flSpinSpeed;
+ float m_flDamage;
+ float m_flDamageRadius;
+
+ // ----------------
+ // Outputs
+ // ----------------
+ COutputEvent m_OnLaunch; // Triggered when missile is launched.
+
+ // ----------------
+ // Inputs
+ // ----------------
+ void InputTurnOn( inputdata_t &inputdata );
+ void InputTurnOff( inputdata_t &inputdata );
+ void InputLOSCheckOn( inputdata_t &inputdata );
+ void InputLOSCheckOff( inputdata_t &inputdata );
+ void InputSetEnemy( inputdata_t &inputdata );
+ void InputClearEnemy( inputdata_t &inputdata );
+ void InputFireOnce( inputdata_t &inputdata );
+
+ void LauncherTurnOn(void);
+
+ void Precache( void );
+ void Spawn( void );
+ Class_T Classify( void );
+ bool IsValidEnemy(CBaseEntity *pTarget );
+ void LaunchGrenade(CBaseEntity* pLauncher );
+ void LauncherThink(void );
+ bool FInViewCone( CBaseEntity *pEntity );
+
+ int DrawDebugTextOverlays(void);
+
+ DECLARE_DATADESC();
+};
+
+
+BEGIN_DATADESC( CNPC_Launcher )
+
+ // Inputs
+ DEFINE_KEYFIELD( m_nStartOn, FIELD_INTEGER, "StartOn" ),
+ DEFINE_KEYFIELD( m_sMissileModel, FIELD_STRING, "MissileModel" ),
+ DEFINE_KEYFIELD( m_sLaunchSound, FIELD_STRING, "LaunchSound" ),
+ DEFINE_KEYFIELD( m_sFlySound, FIELD_STRING, "FlySound" ),
+ DEFINE_KEYFIELD( m_nSmokeTrail, FIELD_INTEGER, "SmokeTrail" ),
+ DEFINE_KEYFIELD( m_bSmokeLaunch, FIELD_BOOLEAN, "LaunchSmoke" ),
+ DEFINE_KEYFIELD( m_nLaunchDelay, FIELD_INTEGER, "LaunchDelay" ),
+ DEFINE_KEYFIELD( m_flLaunchSpeed, FIELD_FLOAT, "LaunchSpeed" ),
+ DEFINE_KEYFIELD( m_sPathCornerName, FIELD_STRING, "PathCornerName" ),
+ DEFINE_KEYFIELD( m_flHomingSpeed, FIELD_FLOAT, "HomingSpeed" ),
+ DEFINE_KEYFIELD( m_nHomingStrength, FIELD_INTEGER, "HomingStrength" ),
+ DEFINE_KEYFIELD( m_flHomingDelay, FIELD_FLOAT, "HomingDelay" ),
+ DEFINE_KEYFIELD( m_flHomingRampUp, FIELD_FLOAT, "HomingRampUp" ),
+ DEFINE_KEYFIELD( m_flHomingDuration, FIELD_FLOAT, "HomingDuration" ),
+ DEFINE_KEYFIELD( m_flHomingRampDown, FIELD_FLOAT, "HomingRampDown" ),
+ DEFINE_KEYFIELD( m_flGravity, FIELD_FLOAT, "Gravity" ),
+ DEFINE_KEYFIELD( m_flMinAttackDist, FIELD_FLOAT, "MinRange" ),
+ DEFINE_KEYFIELD( m_flMaxAttackDist, FIELD_FLOAT, "MaxRange" ),
+ DEFINE_KEYFIELD( m_flSpinMagnitude, FIELD_FLOAT, "SpinMagnitude" ),
+ DEFINE_KEYFIELD( m_flSpinSpeed, FIELD_FLOAT, "SpinSpeed" ),
+ DEFINE_KEYFIELD( m_flDamage, FIELD_FLOAT, "Damage" ),
+ DEFINE_KEYFIELD( m_flDamageRadius, FIELD_FLOAT, "DamageRadius" ),
+ DEFINE_FIELD( m_flMissileGravity, FIELD_FLOAT ),
+
+ DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ),
+ DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ),
+ DEFINE_INPUTFUNC( FIELD_VOID, "LOSCheckOn", InputLOSCheckOn ),
+ DEFINE_INPUTFUNC( FIELD_VOID, "LOSCheckOn", InputLOSCheckOn ),
+ DEFINE_INPUTFUNC( FIELD_VOID, "FireOnce", InputFireOnce ),
+ DEFINE_INPUTFUNC( FIELD_EHANDLE, "SetEnemyEntity", InputSetEnemy ),
+ DEFINE_INPUTFUNC( FIELD_VOID, "ClearEnemyEntity", InputClearEnemy ),
+
+ DEFINE_OUTPUT( m_OnLaunch, "OnLaunch" ),
+
+ // Function Pointers
+ DEFINE_THINKFUNC( LauncherThink ),
+
+END_DATADESC()
+
+LINK_ENTITY_TO_CLASS( npc_launcher, CNPC_Launcher );
+
+
+// ===================
+// Input Functions
+// ===================
+void CNPC_Launcher::InputTurnOn( inputdata_t &inputdata )
+{
+ LauncherTurnOn();
+}
+
+void CNPC_Launcher::InputTurnOff( inputdata_t &inputdata )
+{
+ SetThink(NULL);
+}
+
+void CNPC_Launcher::InputLOSCheckOn( inputdata_t &inputdata )
+{
+ m_spawnflags |= SF_LAUNCHER_CHECK_LOS;
+}
+
+void CNPC_Launcher::InputLOSCheckOff( inputdata_t &inputdata )
+{
+ m_spawnflags &= ~SF_LAUNCHER_CHECK_LOS;
+}
+
+void CNPC_Launcher::InputSetEnemy( inputdata_t &inputdata )
+{
+ SetEnemy( inputdata.value.Entity().Get() );
+}
+
+void CNPC_Launcher::InputClearEnemy( inputdata_t &inputdata )
+{
+ SetEnemy( NULL );
+}
+
+void CNPC_Launcher::InputFireOnce( inputdata_t &inputdata )
+{
+ m_flNextAttack = 0;
+
+ // If I using path following missiles just launch
+ if (m_sPathCornerName != NULL_STRING)
+ {
+ LaunchGrenade(NULL);
+ }
+ // Otherwise only launch if I have an enemy
+ else
+ {
+ LauncherThink();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CNPC_Launcher::Precache( void )
+{
+ // This is a dummy model that is never used!
+ PrecacheModel("models/player.mdl");
+ PrecacheModel(STRING(m_sMissileModel));
+ PrecacheScriptSound( STRING(m_sLaunchSound));
+ PrecacheScriptSound( STRING(m_sFlySound));
+
+ UTIL_PrecacheOther( "grenade_homer");
+ BaseClass::Precache();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CNPC_Launcher::LauncherTurnOn(void)
+{
+ SetThink(&CNPC_Launcher::LauncherThink);
+ SetNextThink( gpGlobals->curtime );
+ m_flNextAttack = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CNPC_Launcher::Spawn( void )
+{
+ Precache();
+
+ // This is a dummy model that is never used!
+ SetModel( "models/player.mdl" );
+
+ UTIL_SetSize(this, vec3_origin, vec3_origin);
+
+ m_takedamage = DAMAGE_NO;
+
+ if (m_nHomingStrength > 100)
+ {
+ m_nHomingStrength = 100;
+ Warning("WARNING: NPC_Launcher Homing Strength must be between 0 and 100\n");
+ }
+
+ SetSolid( SOLID_NONE );
+ SetMoveType( MOVETYPE_NONE );
+ SetBloodColor( DONT_BLEED );
+ AddEffects( EF_NODRAW );
+
+ AddFlag( FL_NPC );
+
+ CapabilitiesAdd( bits_CAP_SQUAD );
+
+ InitRelationshipTable();
+
+ if (m_nStartOn)
+ {
+ LauncherTurnOn();
+ }
+
+ // -------------------------------------------------------
+ // If I form squads add me to a squad
+ // -------------------------------------------------------
+ // @TODO (toml 12-05-02): RECONCILE WITH SAVE/RESTORE
+ if (!m_pSquad)
+ {
+ m_pSquad = g_AI_SquadManager.FindCreateSquad(this, m_SquadName);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+Class_T CNPC_Launcher::Classify( void )
+{
+ return CLASS_NONE;
+}
+
+//------------------------------------------------------------------------------
+// Purpose:
+//------------------------------------------------------------------------------
+void CNPC_Launcher::LaunchGrenade( CBaseEntity* pEnemy )
+{
+ // If a path following missile, create a path following missile
+ if (m_sPathCornerName != NULL_STRING)
+ {
+ CGrenadePathfollower *pGrenade = CGrenadePathfollower::CreateGrenadePathfollower( m_sMissileModel, m_sFlySound, GetAbsOrigin(), vec3_angle, edict() );
+ pGrenade->SetDamage(m_flDamage);
+ pGrenade->SetDamageRadius(m_flDamageRadius);
+ pGrenade->Launch(m_flLaunchSpeed,m_sPathCornerName);
+ }
+ else
+ {
+ Vector vUp;
+ AngleVectors( GetAbsAngles(), NULL, NULL, &vUp );
+ Vector vLaunchVelocity = (vUp * m_flLaunchSpeed);
+
+ CGrenadeHomer *pGrenade = CGrenadeHomer::CreateGrenadeHomer( m_sMissileModel, m_sFlySound, GetAbsOrigin(), vec3_angle, edict() );
+ pGrenade->Spawn( );
+ pGrenade->SetSpin(m_flSpinMagnitude,m_flSpinSpeed);
+ pGrenade->SetHoming((0.01*m_nHomingStrength),m_flHomingDelay,m_flHomingRampUp,m_flHomingDuration,m_flHomingRampDown);
+ pGrenade->SetDamage(m_flDamage);
+ pGrenade->SetDamageRadius(m_flDamageRadius);
+ pGrenade->Launch(this,pEnemy,vLaunchVelocity,m_flHomingSpeed,GetGravity(),m_nSmokeTrail);
+ }
+
+ CPASAttenuationFilter filter( this, 0.3 );
+
+ EmitSound_t ep;
+ ep.m_nChannel = CHAN_WEAPON;
+ ep.m_pSoundName = STRING(m_sLaunchSound);
+ ep.m_SoundLevel = SNDLVL_NORM;
+
+ EmitSound( filter, entindex(), ep );
+
+ if (m_bSmokeLaunch)
+ {
+ UTIL_Smoke(GetAbsOrigin(), random->RandomInt(20,30), random->RandomInt(10,15));
+ }
+ m_flNextAttack = gpGlobals->curtime + LAUNCHER_REST_TIME;
+
+}
+
+//------------------------------------------------------------------------------
+// Purpose : Launcher sees 360 degrees
+//------------------------------------------------------------------------------
+bool CNPC_Launcher::FInViewCone( CBaseEntity *pEntity )
+{
+ return true;
+}
+
+//------------------------------------------------------------------------------
+// Purpose : Override base class to check range and visibility
+//------------------------------------------------------------------------------
+bool CNPC_Launcher::IsValidEnemy( CBaseEntity *pTarget )
+{
+ // ---------------------------------
+ // Check range
+ // ---------------------------------
+ float flTargetDist = (GetAbsOrigin() - pTarget->GetAbsOrigin()).Length();
+ if (flTargetDist < m_flMinAttackDist)
+ {
+ return false;
+ }
+ if (flTargetDist > m_flMaxAttackDist)
+ {
+ return false;
+ }
+
+ if (!FBitSet (m_spawnflags, SF_LAUNCHER_CHECK_LOS))
+ {
+ return true;
+ }
+ // ------------------------------------------------------
+ // Make sure I can see the target from above my position
+ // ------------------------------------------------------
+ trace_t tr;
+
+ // Trace from launch position to target position.
+ // Use position above actual barral based on vertical launch speed
+ Vector vStartPos = GetAbsOrigin() + Vector(0,0,0.2*m_flLaunchSpeed);
+ Vector vEndPos = pTarget->GetAbsOrigin();
+ AI_TraceLine( vStartPos, vEndPos, MASK_SHOT, pTarget, COLLISION_GROUP_NONE, &tr );
+
+ if (tr.fraction == 1.0)
+ {
+ return true;
+ }
+ return false;
+}
+
+//------------------------------------------------------------------------------
+// Purpose :
+//------------------------------------------------------------------------------
+void CNPC_Launcher::LauncherThink( void )
+{
+ if (gpGlobals->curtime > m_flNextAttack)
+ {
+ // If enemy was set, fire at enemy
+ if (GetEnemy())
+ {
+ LaunchGrenade(GetEnemy());
+ m_OnLaunch.FireOutput(GetEnemy(), this);
+ m_flNextAttack = gpGlobals->curtime + m_nLaunchDelay;
+ }
+ // Otherwise look for enemy to fire at
+ else
+ {
+ GetSenses()->Look(m_flMaxAttackDist);
+ CBaseEntity* pBestEnemy = BestEnemy();
+
+ if (pBestEnemy)
+ {
+ LaunchGrenade(pBestEnemy);
+ m_OnLaunch.FireOutput(pBestEnemy, this);
+ m_flNextAttack = gpGlobals->curtime + m_nLaunchDelay;
+ }
+ }
+ }
+ SetNextThink( gpGlobals->curtime + 0.1f );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Draw any debug text overlays
+// Output : Current text offset from the top
+//-----------------------------------------------------------------------------
+int CNPC_Launcher::DrawDebugTextOverlays(void)
+{
+ int text_offset = BaseClass::DrawDebugTextOverlays();
+
+ if (m_debugOverlays & OVERLAY_TEXT_BIT)
+ {
+ char tempstr[512];
+ Q_snprintf(tempstr,sizeof(tempstr),"State: %s", (m_pfnThink) ? "On" : "Off" );
+ EntityText(text_offset,tempstr,0);
+ text_offset++;
+
+ Q_snprintf(tempstr,sizeof(tempstr),"LOS: %s", (FBitSet (m_spawnflags, SF_LAUNCHER_CHECK_LOS)) ? "On" : "Off" );
+ EntityText(text_offset,tempstr,0);
+ text_offset++;
+ }
+ return text_offset;
+}