diff --git a/sp/src/game/server/hl2/npc_attackchopper.cpp b/sp/src/game/server/hl2/npc_attackchopper.cpp index ac6efb1c..b23e1436 100644 --- a/sp/src/game/server/hl2/npc_attackchopper.cpp +++ b/sp/src/game/server/hl2/npc_attackchopper.cpp @@ -164,6 +164,15 @@ ConVar g_helicopter_bullrush_mega_bomb_health( "g_helicopter_bullrush_mega_bomb_ ConVar g_helicopter_bomb_danger_radius( "g_helicopter_bomb_danger_radius", "120" ); +#ifdef MAPBASE +ConVar g_helicopter_crashpoint_nearest( "g_helicopter_crashpoint_nearest", "1", 0, "Selects the nearest crash point instead of just the first in the entity list." ); + +#ifdef HL2_EPISODIC +ConVar g_helicopter_phys_follow_while_crashing( "g_helicopter_phys_follow_while_crashing", "0", 0, "Allows the phys_bone_followers to follow the helicopter while flying to crash point" ); +#endif + +#endif + Activity ACT_HELICOPTER_DROP_BOMB; Activity ACT_HELICOPTER_CRASHING; @@ -191,7 +200,60 @@ enum #define GRENADE_HELICOPTER_MODEL "models/combine_helicopter/helicopter_bomb01.mdl" +#ifdef MAPBASE +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +class CTargetHelicopterCrash : public CPointEntity +{ + DECLARE_CLASS( CTargetHelicopterCrash, CPointEntity ); +public: + DECLARE_DATADESC(); + + void InputEnable( inputdata_t &inputdata ) + { + m_bDisabled = false; + } + void InputDisable( inputdata_t &inputdata ) + { + m_bDisabled = true; + } + bool IsDisabled( void ) + { + return m_bDisabled; + } + void HelicopterCrashedOnTarget( CBaseHelicopter *pChopper ) + { + m_OnCrashed.FireOutput( pChopper, this ); + } + void HelicopterAcquiredCrashTarget( CBaseHelicopter *pChopper ) + { + m_OnBeginCrash.FireOutput( pChopper, this ); + } + +private: + bool m_bDisabled; + + COutputEvent m_OnCrashed; + COutputEvent m_OnBeginCrash; +}; + +LINK_ENTITY_TO_CLASS( info_target_helicopter_crash, CTargetHelicopterCrash ); + +BEGIN_DATADESC( CTargetHelicopterCrash ) + DEFINE_FIELD( m_bDisabled, FIELD_BOOLEAN ), + + // Inputs + DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), + DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), + + // Outputs + DEFINE_OUTPUT( m_OnCrashed, "OnCrashed" ), + DEFINE_OUTPUT( m_OnBeginCrash, "OnBeginCrash" ), +END_DATADESC() +#else LINK_ENTITY_TO_CLASS( info_target_helicopter_crash, CPointEntity ); +#endif //------------------------------------------------------------------------------ @@ -650,6 +712,7 @@ private: void SpotlightStartup(); void SpotlightShutdown(); + CBaseEntity *FindCrashPoint(); CBaseEntity *GetCrashPoint() { return m_hCrashPoint.Get(); } private: @@ -3774,6 +3837,46 @@ void Chopper_BecomeChunks( CBaseEntity *pChopper ) pBodyChunk->m_pCockpitConstraint = physenv->CreateFixedConstraint( pBodyObject, pCockpitObject, pGroup, fixed ); } +//----------------------------------------------------------------------------- +// Purpose: Find a valid crash point +//----------------------------------------------------------------------------- +CBaseEntity *CNPC_AttackHelicopter::FindCrashPoint() +{ +#ifdef MAPBASE + float flNearest = MAX_TRACE_LENGTH * MAX_TRACE_LENGTH; + CTargetHelicopterCrash *pNearest = NULL; + CBaseEntity *pEnt = NULL; + while( (pEnt = gEntList.FindEntityByClassname(pEnt, "info_target_helicopter_crash")) != NULL ) + { + CTargetHelicopterCrash *pCrashTarget = assert_cast(pEnt); + if ( pCrashTarget->IsDisabled() ) + continue; + + if (g_helicopter_crashpoint_nearest.GetBool()) + { + float flDist = ( pEnt->WorldSpaceCenter() - WorldSpaceCenter() ).LengthSqr(); + if( flDist < flNearest ) + { + pNearest = pCrashTarget; + flNearest = flDist; + } + } + else + { + pNearest = pCrashTarget; + break; + } + } + + if (pNearest) + pNearest->HelicopterAcquiredCrashTarget( this ); + + return pNearest; +#else + return gEntList.FindEntityByClassname( NULL, "info_target_helicopter_crash" ); +#endif +} + //----------------------------------------------------------------------------- // Purpose: Start us crashing //----------------------------------------------------------------------------- @@ -3791,7 +3894,7 @@ void CNPC_AttackHelicopter::Event_Killed( const CTakeDamageInfo &info ) if( GetCrashPoint() == NULL ) { - CBaseEntity *pCrashPoint = gEntList.FindEntityByClassname( NULL, "info_target_helicopter_crash" ); + CBaseEntity *pCrashPoint = FindCrashPoint(); if( pCrashPoint != NULL ) { m_hCrashPoint.Set( pCrashPoint ); @@ -3812,6 +3915,12 @@ void CNPC_AttackHelicopter::Event_Killed( const CTakeDamageInfo &info ) return; } } +#ifdef MAPBASE + else + { + assert_cast( GetCrashPoint() )->HelicopterCrashedOnTarget( this ); + } +#endif Chopper_BecomeChunks( this ); StopLoopingSounds(); @@ -4821,6 +4930,15 @@ void CNPC_AttackHelicopter::Hunt( void ) { Flight(); UpdatePlayerDopplerShift( ); + +#if defined(MAPBASE) && defined(HL2_EPISODIC) + if (g_helicopter_phys_follow_while_crashing.GetBool()) + { + // Update our bone followers + m_BoneFollowerManager.UpdateBoneFollowers( this ); + } +#endif // HL2_EPISODIC + return; } diff --git a/sp/src/game/server/hl2/npc_combinegunship.cpp b/sp/src/game/server/hl2/npc_combinegunship.cpp index dfe0aa20..49e7183c 100644 --- a/sp/src/game/server/hl2/npc_combinegunship.cpp +++ b/sp/src/game/server/hl2/npc_combinegunship.cpp @@ -187,15 +187,29 @@ public: { return m_bDisabled; } +#ifdef MAPBASE + void GunshipCrashedOnTarget( CBaseHelicopter *pGunship ) + { + m_OnCrashed.FireOutput( pGunship, this ); + } + void GunshipAcquiredCrashTarget( CBaseHelicopter *pGunship ) + { + m_OnBeginCrash.FireOutput( pGunship, this ); + } +#else void GunshipCrashedOnTarget( void ) { m_OnCrashed.FireOutput( this, this ); } +#endif private: bool m_bDisabled; COutputEvent m_OnCrashed; +#ifdef MAPBASE + COutputEvent m_OnBeginCrash; +#endif }; LINK_ENTITY_TO_CLASS( info_target_gunshipcrash, CTargetGunshipCrash ); @@ -209,6 +223,9 @@ BEGIN_DATADESC( CTargetGunshipCrash ) // Outputs DEFINE_OUTPUT( m_OnCrashed, "OnCrashed" ), +#ifdef MAPBASE + DEFINE_OUTPUT( m_OnBeginCrash, "OnBeginCrash" ), +#endif END_DATADESC() @@ -1564,7 +1581,11 @@ void CNPC_CombineGunship::PrescheduleThink( void ) { BeginDestruct(); m_OnCrashed.FireOutput( this, this ); +#ifdef MAPBASE + m_hCrashTarget->GunshipCrashedOnTarget( this ); +#else m_hCrashTarget->GunshipCrashedOnTarget(); +#endif return; } } @@ -1976,6 +1997,10 @@ bool CNPC_CombineGunship::FindNearestGunshipCrash( void ) m_flNextGunshipCrashFind = gpGlobals->curtime + 0.5; m_flEndDestructTime = 0; +#ifdef MAPBASE + m_hCrashTarget->GunshipAcquiredCrashTarget( this ); +#endif + if ( g_debug_gunship.GetInt() ) { NDebugOverlay::Line(GetAbsOrigin(), m_hCrashTarget->GetAbsOrigin(), 0,255,0, true, 0.5);