diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /sp/src/game/server/hl2/npc_launcher.cpp | |
| parent | Mark some more files as text. (diff) | |
| download | source-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.cpp | 826 |
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; +} |