mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2025-03-03 17:25:27 +03:00
Optional npc_helicopter damage and stealth changes
This commit is contained in:
parent
fbb7769acd
commit
3f64380755
@ -42,6 +42,10 @@ virtual void NullThink( void );
|
||||
|
||||
ConVar g_debug_basehelicopter( "g_debug_basehelicopter", "0", FCVAR_CHEAT );
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar g_helicopter_use_sight_condition( "g_helicopter_use_sight_condition", "0", 0, "If enabled, helicopters will use the AI sight condition instead of just checking if there's a clear path to the player. This prevents them from cheating." );
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------
|
||||
//---------------------------------------------------------
|
||||
// TODOs
|
||||
@ -702,7 +706,11 @@ void CBaseHelicopter::UpdateEnemy()
|
||||
{
|
||||
CBaseEntity *pEnemy = GetEnemy();
|
||||
GatherEnemyConditions( pEnemy );
|
||||
#ifdef MAPBASE
|
||||
if ( (g_helicopter_use_sight_condition.GetBool() && pEnemy->Classify() != CLASS_BULLSEYE) ? HasCondition( COND_SEE_ENEMY ) : FVisible( pEnemy ) )
|
||||
#else
|
||||
if ( FVisible( pEnemy ) )
|
||||
#endif
|
||||
{
|
||||
if (m_flLastSeen < gpGlobals->curtime - 2)
|
||||
{
|
||||
|
@ -44,6 +44,7 @@
|
||||
|
||||
#ifdef MAPBASE
|
||||
#include "filters.h"
|
||||
#include "ai_hint.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
@ -561,6 +562,13 @@ private:
|
||||
// Death, etc.
|
||||
void InputSelfDestruct( inputdata_t &inputdata );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// This is identical to SelfDestruct, except the helicopter won't throw out chunks while flying to a crash point.
|
||||
// This input is meant to be used when the pilot is killed and there's nothing wrong with the helicopter itself.
|
||||
// If there are no crash points, the helicopter will explode in place as normal.
|
||||
void InputSelfDestructNoFX( inputdata_t &inputdata );
|
||||
#endif
|
||||
|
||||
// Enemy visibility check
|
||||
CBaseEntity *FindTrackBlocker( const Vector &vecViewPoint, const Vector &vecTargetPos );
|
||||
|
||||
@ -584,6 +592,7 @@ private:
|
||||
|
||||
// Various states of the helicopter firing...
|
||||
bool PoseGunTowardTargetDirection( const Vector &vTargetDir );
|
||||
float GetGunPoseSpeed() const;
|
||||
|
||||
// Compute the position to fire at (vehicle + non-vehicle case)
|
||||
void ComputeFireAtPosition( Vector *pVecActualTargetPosition );
|
||||
@ -595,6 +604,17 @@ private:
|
||||
bool DoGunFiring( const Vector &vBasePos, const Vector &vGunDir, const Vector &vecFireAtPosition );
|
||||
void FireElectricityGun( );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Idle aiming
|
||||
bool FindIdleAimTarget();
|
||||
bool ValidIdleAimTarget( CBaseEntity *pAimTarget );
|
||||
|
||||
bool FValidateHintType( CAI_Hint *pHint );
|
||||
|
||||
inline CBaseEntity *GetIdleAimTarget() const { return m_hIdleAimTarget; }
|
||||
inline void SetIdleAimTarget( CBaseEntity *pNewAimTarget ) { m_hIdleAimTarget = pNewAimTarget; }
|
||||
#endif
|
||||
|
||||
// Chooses a point within the circle of death to fire in
|
||||
void PickDirectionToCircleOfDeath( const Vector &vBasePos, const Vector &vecFireAtPosition, Vector *pResult );
|
||||
|
||||
@ -784,6 +804,17 @@ private:
|
||||
bool m_bBombsExplodeOnContact;
|
||||
bool m_bNonCombat;
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool m_bIdleAimAround;
|
||||
EHANDLE m_hIdleAimTarget;
|
||||
Vector m_vecIdleAimDir;
|
||||
float m_flNextIdleAimTime;
|
||||
|
||||
bool m_bDisableSmokeTrails;
|
||||
bool m_bDisableCorpses;
|
||||
bool m_bDisableExplosions;
|
||||
#endif
|
||||
|
||||
int m_nNearShots;
|
||||
int m_nMaxNearShots;
|
||||
|
||||
@ -923,6 +954,15 @@ BEGIN_DATADESC( CNPC_AttackHelicopter )
|
||||
|
||||
#ifdef MAPBASE
|
||||
DEFINE_KEYFIELD( m_flFieldOfView, FIELD_FLOAT, "FieldOfView" ),
|
||||
|
||||
DEFINE_KEYFIELD( m_bIdleAimAround, FIELD_BOOLEAN, "IdleAimAround" ),
|
||||
DEFINE_FIELD( m_hIdleAimTarget, FIELD_EHANDLE ),
|
||||
DEFINE_FIELD( m_vecIdleAimDir, FIELD_VECTOR ),
|
||||
DEFINE_FIELD( m_flNextIdleAimTime, FIELD_TIME ),
|
||||
|
||||
DEFINE_KEYFIELD( m_bDisableSmokeTrails, FIELD_BOOLEAN, "DisableSmokeTrails" ),
|
||||
DEFINE_KEYFIELD( m_bDisableCorpses, FIELD_BOOLEAN, "DisableCorpses" ),
|
||||
DEFINE_KEYFIELD( m_bDisableExplosions, FIELD_BOOLEAN, "DisableExplosions" ),
|
||||
#endif
|
||||
|
||||
DEFINE_FIELD( m_hCrashPoint, FIELD_EHANDLE ),
|
||||
@ -959,6 +999,9 @@ BEGIN_DATADESC( CNPC_AttackHelicopter )
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "EnablePathVisibilityTests", InputEnablePathVisibilityTests ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "SelfDestruct", InputSelfDestruct ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "SelfDestructNoFX", InputSelfDestructNoFX ),
|
||||
#endif
|
||||
|
||||
DEFINE_THINKFUNC( BlinkLightsThink ),
|
||||
DEFINE_THINKFUNC( SpotlightThink ),
|
||||
@ -1709,6 +1752,21 @@ void CNPC_AttackHelicopter::InputSelfDestruct( inputdata_t &inputdata )
|
||||
TakeDamage( info );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
void CNPC_AttackHelicopter::InputSelfDestructNoFX( inputdata_t &inputdata )
|
||||
{
|
||||
m_bDisableSmokeTrails = true;
|
||||
m_bDisableCorpses = true;
|
||||
m_bDisableExplosions = true;
|
||||
|
||||
m_lifeState = LIFE_ALIVE; // Force to die properly.
|
||||
CTakeDamageInfo info( this, this, Vector(0, 0, 1), WorldSpaceCenter(), GetMaxHealth(), CLASS_MISSILE );
|
||||
TakeDamage( info );
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// For scripted times where it *has* to shoot
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2308,21 +2366,23 @@ bool CNPC_AttackHelicopter::PoseGunTowardTargetDirection( const Vector &vTargetD
|
||||
}
|
||||
}
|
||||
|
||||
float flPoseSpeed = GetGunPoseSpeed();
|
||||
|
||||
if (angles.x > m_angGun.x)
|
||||
{
|
||||
m_angGun.x = MIN( angles.x, m_angGun.x + 12 );
|
||||
m_angGun.x = MIN( angles.x, m_angGun.x + flPoseSpeed );
|
||||
}
|
||||
if (angles.x < m_angGun.x)
|
||||
{
|
||||
m_angGun.x = MAX( angles.x, m_angGun.x - 12 );
|
||||
m_angGun.x = MAX( angles.x, m_angGun.x - flPoseSpeed );
|
||||
}
|
||||
if (angles.y > m_angGun.y)
|
||||
{
|
||||
m_angGun.y = MIN( angles.y, m_angGun.y + 12 );
|
||||
m_angGun.y = MIN( angles.y, m_angGun.y + flPoseSpeed );
|
||||
}
|
||||
if (angles.y < m_angGun.y)
|
||||
{
|
||||
m_angGun.y = MAX( angles.y, m_angGun.y - 12 );
|
||||
m_angGun.y = MAX( angles.y, m_angGun.y - flPoseSpeed );
|
||||
}
|
||||
|
||||
SetPoseParameter( m_poseWeapon_Pitch, -m_angGun.x );
|
||||
@ -2332,6 +2392,20 @@ bool CNPC_AttackHelicopter::PoseGunTowardTargetDirection( const Vector &vTargetD
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Various states of the helicopter firing...
|
||||
//------------------------------------------------------------------------------
|
||||
float CNPC_AttackHelicopter::GetGunPoseSpeed() const
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if (m_bIdleAimAround && !GetEnemy())
|
||||
return 4.0f;
|
||||
#endif
|
||||
|
||||
return 12.0f;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Compute the enemy position (non-vehicle case)
|
||||
//------------------------------------------------------------------------------
|
||||
@ -2426,6 +2500,87 @@ bool CNPC_AttackHelicopter::DoGunIdle( const Vector &vGunDir, const Vector &vTar
|
||||
}
|
||||
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Finds an idle aim target. Based on CNPC_PlayerCompanion code
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CNPC_AttackHelicopter::FindIdleAimTarget()
|
||||
{
|
||||
CAI_Hint *pHint;
|
||||
CHintCriteria hintCriteria;
|
||||
CBaseEntity *pPriorAimTarget = GetIdleAimTarget();
|
||||
|
||||
hintCriteria.SetHintType( HINT_WORLD_VISUALLY_INTERESTING );
|
||||
hintCriteria.SetFlag( bits_HINT_NODE_VISIBLE | bits_HINT_NODE_IN_VIEWCONE | bits_HINT_NPC_IN_NODE_FOV | bits_HINT_NODE_USE_GROUP | bits_HINT_NODE_NEAREST );
|
||||
hintCriteria.AddIncludePosition( GetAbsOrigin(), CHOPPER_MAX_GUN_DIST );
|
||||
pHint = CAI_HintManager::FindHint( this, hintCriteria );
|
||||
|
||||
if( pHint )
|
||||
{
|
||||
if ( !ValidIdleAimTarget( pHint ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( pHint != pPriorAimTarget )
|
||||
{
|
||||
// Notify of the change.
|
||||
SetIdleAimTarget( pHint );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Didn't find an aim target, or found the same one.
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Finds an idle aim target. Based on CNPC_PlayerCompanion code
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CNPC_AttackHelicopter::ValidIdleAimTarget( CBaseEntity *pAimTarget )
|
||||
{
|
||||
Vector vecTargetOrigin = pAimTarget->GetAbsOrigin();
|
||||
|
||||
Vector vBasePos;
|
||||
GetAttachment( m_nGunBaseAttachment, vBasePos );
|
||||
|
||||
if ( vecTargetOrigin.z > vBasePos.z || (vecTargetOrigin - vBasePos).Length() < 128.0f )
|
||||
{
|
||||
// Too close!
|
||||
return false;
|
||||
}
|
||||
|
||||
trace_t tr;
|
||||
UTIL_TraceLine( vBasePos, vecTargetOrigin, MASK_BLOCKLOS, this, COLLISION_GROUP_NONE, &tr );
|
||||
|
||||
if ( tr.fraction < 1.0f && tr.m_pEnt != pAimTarget )
|
||||
{
|
||||
// No LOS
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CNPC_AttackHelicopter::FValidateHintType( CAI_Hint *pHint )
|
||||
{
|
||||
switch( pHint->HintType() )
|
||||
{
|
||||
case HINT_WORLD_VISUALLY_INTERESTING:
|
||||
return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return BaseClass::FValidateHintType( pHint );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// How easy is the target to hit?
|
||||
//------------------------------------------------------------------------------
|
||||
@ -3716,12 +3871,20 @@ int CNPC_AttackHelicopter::OnTakeDamage_Alive( const CTakeDamageInfo &info )
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_SMOKE_TRAILS ) && !m_bDisableSmokeTrails )
|
||||
#else
|
||||
if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_SMOKE_TRAILS ) )
|
||||
#endif
|
||||
{
|
||||
AddSmokeTrail( info.GetDamagePosition() );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_CORPSES ) && !m_bDisableCorpses )
|
||||
#else
|
||||
if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_CORPSES ) )
|
||||
#endif
|
||||
{
|
||||
if ( nPrevHealth != GetMaxHealth() )
|
||||
{
|
||||
@ -3729,7 +3892,11 @@ int CNPC_AttackHelicopter::OnTakeDamage_Alive( const CTakeDamageInfo &info )
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_EXPLOSIONS ) && !m_bDisableExplosions )
|
||||
#else
|
||||
if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_EXPLOSIONS ) )
|
||||
#endif
|
||||
{
|
||||
ExplodeAndThrowChunk( info.GetDamagePosition() );
|
||||
}
|
||||
@ -3978,7 +4145,11 @@ void CNPC_AttackHelicopter::PrescheduleThink( void )
|
||||
SetDesiredPosition( GetCrashPoint()->WorldSpaceCenter() );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( !m_bDisableExplosions && random->RandomInt( 0, 4 ) == 0 )
|
||||
#else
|
||||
if ( random->RandomInt( 0, 4 ) == 0 )
|
||||
#endif
|
||||
{
|
||||
Vector explodePoint;
|
||||
CollisionProp()->RandomPointInBounds( Vector(0.25,0.25,0.25), Vector(0.75,0.75,0.75), &explodePoint );
|
||||
@ -5003,6 +5174,55 @@ void CNPC_AttackHelicopter::Hunt( void )
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (m_bIdleAimAround)
|
||||
{
|
||||
if (!GetEnemy())
|
||||
{
|
||||
if (GetIdleAimTarget())
|
||||
{
|
||||
if (!ValidIdleAimTarget( GetIdleAimTarget() ))
|
||||
{
|
||||
SetIdleAimTarget( NULL );
|
||||
m_flNextIdleAimTime = gpGlobals->curtime;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_flNextIdleAimTime < gpGlobals->curtime)
|
||||
{
|
||||
if (!FindIdleAimTarget())
|
||||
{
|
||||
SetIdleAimTarget( NULL );
|
||||
|
||||
// Find a random direction in front of us instead
|
||||
Vector vBasePos, vecForward, vecRight, vecUp;
|
||||
GetAttachment( m_nGunBaseAttachment, vBasePos, &vecForward, &vecRight, &vecUp );
|
||||
|
||||
m_vecIdleAimDir = vecForward + (vecRight * RandomFloat( -0.25f, 0.25f )) + (vecUp * RandomFloat( -0.8f, -0.25f ));
|
||||
}
|
||||
|
||||
m_flNextIdleAimTime = gpGlobals->curtime + RandomFloat( 4.0f, 6.0f );
|
||||
}
|
||||
|
||||
if (GetIdleAimTarget())
|
||||
{
|
||||
// Get gun attachment points
|
||||
Vector vBasePos;
|
||||
GetAttachment( m_nGunBaseAttachment, vBasePos );
|
||||
|
||||
m_vecIdleAimDir = GetIdleAimTarget()->GetAbsOrigin() - vBasePos;
|
||||
VectorNormalize( m_vecIdleAimDir );
|
||||
}
|
||||
|
||||
PoseGunTowardTargetDirection( m_vecIdleAimDir );
|
||||
}
|
||||
else if (GetIdleAimTarget())
|
||||
{
|
||||
SetIdleAimTarget( NULL );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HL2_EPISODIC
|
||||
// Update our bone followers
|
||||
m_BoneFollowerManager.UpdateBoneFollowers(this);
|
||||
|
Loading…
x
Reference in New Issue
Block a user