Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Arbeit heli gibbing and miniscule fixes #322

Draft
wants to merge 3 commits into
base: ez2/mapbase
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
213 changes: 204 additions & 9 deletions sp/src/game/server/hl2/npc_attackchopper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,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;

Expand Down Expand Up @@ -197,7 +206,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


//------------------------------------------------------------------------------
Expand Down Expand Up @@ -663,6 +725,8 @@ class CNPC_AttackHelicopter : public CBaseHelicopter
protected:
#endif

CBaseEntity *FindCrashPoint();

CBaseEntity *GetCrashPoint() { return m_hCrashPoint.Get(); }

private:
Expand Down Expand Up @@ -3806,6 +3870,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<CTargetHelicopterCrash*>(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
//-----------------------------------------------------------------------------
Expand All @@ -3823,7 +3927,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 );
Expand All @@ -3844,6 +3948,12 @@ void CNPC_AttackHelicopter::Event_Killed( const CTakeDamageInfo &info )
return;
}
}
#ifdef MAPBASE
else
{
assert_cast<CTargetHelicopterCrash*>( GetCrashPoint() )->HelicopterCrashedOnTarget( this );
}
#endif

Chopper_BecomeChunks( this );
StopLoopingSounds();
Expand Down Expand Up @@ -4853,6 +4963,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;
}

Expand Down Expand Up @@ -6389,6 +6508,10 @@ class CNPC_ArbeitHelicopter : public CNPC_AttackHelicopter
bool m_bDoorsOpen;
float m_flDoorTransitionTime;

// Crashing
string_t m_iszBodyGibModel;
string_t m_iszTailGibModel;

// Attachments
int m_nGunnerAttachments[ ARBEIT_HELI_MAX_GUNNERS ];
int m_nGunnerJumpAttachments[ ARBEIT_HELI_MAX_GUNNERS ];
Expand Down Expand Up @@ -6423,6 +6546,9 @@ BEGIN_DATADESC( CNPC_ArbeitHelicopter )
DEFINE_KEYFIELD( m_bDoorsOpen, FIELD_BOOLEAN, "DoorsOpen" ),
DEFINE_FIELD( m_flDoorTransitionTime, FIELD_TIME ),

DEFINE_KEYFIELD( m_iszBodyGibModel, FIELD_STRING, "BodyGibModel" ),
DEFINE_KEYFIELD( m_iszTailGibModel, FIELD_STRING, "TailGibModel" ),

DEFINE_INPUTFUNC( FIELD_VOID, "RespawnAllGunners", InputRespawnAllGunners ),
DEFINE_INPUTFUNC( FIELD_VOID, "RespawnRightGunner", InputRespawnRightGunner ),
DEFINE_INPUTFUNC( FIELD_VOID, "RespawnLeftGunner", InputRespawnLeftGunner ),
Expand Down Expand Up @@ -6514,7 +6640,13 @@ void CNPC_ArbeitHelicopter::Precache( void )

if (!m_bNonCombat)
{
PrecacheModel( "models/props_vehicles/arbeit_heli_stationary.mdl" );
if (m_iszBodyGibModel == NULL_STRING)
m_iszBodyGibModel = MAKE_STRING( "models/props_vehicles/arbeit_heli_stationary.mdl" ); // TODO: Unique crash model

PrecacheModel( STRING( m_iszBodyGibModel ) );

if (m_iszTailGibModel != NULL_STRING)
PrecacheModel( STRING( m_iszTailGibModel ) );
}

PrecacheScriptSound( "NPC_ArbeitHelicopter.RotorBlast" );
Expand Down Expand Up @@ -6723,9 +6855,9 @@ void CNPC_ArbeitHelicopter::PrescheduleThink( void )
RefreshGunnerState();

// TODO
if (m_hGunners[0])
if (m_hGunners[0] && m_hGunners[0]->IsAlive())
m_iSideFacing = GUNNER_RIGHT_ONLY;
else if (m_hGunners[1])
else if (m_hGunners[1] && m_hGunners[1]->IsAlive())
m_iSideFacing = GUNNER_LEFT_ONLY;
else
m_iSideFacing = GUNNER_NONE;
Expand Down Expand Up @@ -6783,7 +6915,7 @@ void CNPC_ArbeitHelicopter::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 );
Expand All @@ -6807,6 +6939,10 @@ void CNPC_ArbeitHelicopter::Event_Killed( const CTakeDamageInfo &info )
return;
}
}
else
{
assert_cast<CTargetHelicopterCrash*>( GetCrashPoint() )->HelicopterCrashedOnTarget( this );
}

// Kill our gunners
for (int i = 0; i < ARBEIT_HELI_MAX_GUNNERS; i++)
Expand All @@ -6820,14 +6956,73 @@ void CNPC_ArbeitHelicopter::Event_Killed( const CTakeDamageInfo &info )
m_hGunners[i] = NULL;
}

Vector vecChunkPos, vecChunkVelocity, vecForward, vecRight, vecUp;
QAngle vecChunkAngles;

int nBodyAttachment = LookupAttachment( "damage0" );
if (nBodyAttachment > 0)
{
//GetAttachment( nBodyAttachment, vecChunkPos, vecChunkAngles );

matrix3x4_t attachmentToWorld;
GetAttachment( nBodyAttachment, attachmentToWorld );
MatrixAngles( attachmentToWorld, vecChunkAngles, vecChunkPos );
MatrixGetColumn( attachmentToWorld, 0, vecForward );
//MatrixGetColumn( attachmentToWorld, 1, vecRight );
MatrixGetColumn( attachmentToWorld, 2, vecUp );
}
else
{
vecChunkPos = GetAbsOrigin();
vecChunkAngles = GetAbsAngles();
vecChunkVelocity = GetAbsVelocity();
}

// We need to get a right hand vector to toss the cockpit and tail pieces
// so their motion looks like a continuation of the tailspin animation
// that the chopper plays before crashing.
GetVectors( NULL, &vecRight, NULL );

// For now, create a charred stationary version of ourselves
// TODO: Unique crash model
CHelicopterChunk *pBodyChunk = CHelicopterChunk::CreateHelicopterChunk( GetAbsOrigin(), GetAbsAngles(), GetAbsVelocity(), "models/props_vehicles/arbeit_heli_stationary.mdl", CHUNK_BODY );
CHelicopterChunk *pBodyChunk = CHelicopterChunk::CreateHelicopterChunk( vecChunkPos, vecChunkAngles, vecChunkVelocity, STRING( m_iszBodyGibModel ), CHUNK_BODY );
if (pBodyChunk)
{
pBodyChunk->SetRenderColor( 64, 64, 64 );
}

CHelicopterChunk *pTailChunk = NULL;
if ( m_iszTailGibModel != NULL_STRING )
{
// Tail
vecChunkPos += (vecForward * -175.0f) + (vecUp * 75.0f);
pTailChunk = CHelicopterChunk::CreateHelicopterChunk( vecChunkPos, vecChunkAngles, vecChunkVelocity + (vecRight * -600.0f), STRING( m_iszTailGibModel ), CHUNK_TAIL );
if (pTailChunk)
{
pTailChunk->SetRenderColor( 64, 64, 64 );
pTailChunk->m_hMaster = pBodyChunk;
}
}

if (pBodyChunk && pTailChunk)
{
// Constrain all the pieces together loosely
IPhysicsObject *pBodyObject = pBodyChunk->VPhysicsGetObject();
Assert( pBodyObject );

IPhysicsObject *pTailObject = pTailChunk->VPhysicsGetObject();
Assert( pTailObject );

IPhysicsConstraintGroup *pGroup = NULL;

// Create the constraint
constraint_fixedparams_t fixed;
fixed.Defaults();
fixed.InitWithCurrentObjectState( pBodyObject, pTailObject );
fixed.constraint.Defaults();

pBodyChunk->m_pTailConstraint = physenv->CreateFixedConstraint( pBodyObject, pTailObject, pGroup, fixed );
}

StopLoopingSounds();

m_lifeState = LIFE_DEAD;
Expand Down Expand Up @@ -7063,7 +7258,7 @@ void CNPC_ArbeitHelicopter::InputOpenDoors( inputdata_t &inputdata )
{
m_bDoorsOpen = true;

if (m_flDoorTransitionTime != -1.0f && m_iGunnerSpawnState == GUNNER_NONE)
if (m_flDoorTransitionTime == -1.0f /*&& m_iGunnerSpawnState == GUNNER_NONE*/)
{
m_flDoorTransitionTime = gpGlobals->curtime + ARBEIT_HELI_DOOR_TIME;
SetContextThink( &CNPC_ArbeitHelicopter::OpenDoorsThink, gpGlobals->curtime + TICK_INTERVAL, g_pszGunnerSpawnContext );
Expand All @@ -7076,7 +7271,7 @@ void CNPC_ArbeitHelicopter::InputCloseDoors( inputdata_t &inputdata )
{
m_bDoorsOpen = false;

if (m_flDoorTransitionTime != -1.0f && m_iGunnerSpawnState == GUNNER_NONE)
if (m_flDoorTransitionTime == -1.0f /*&& m_iGunnerSpawnState == GUNNER_NONE*/)
{
m_flDoorTransitionTime = gpGlobals->curtime + ARBEIT_HELI_DOOR_TIME;
SetContextThink( &CNPC_ArbeitHelicopter::CloseDoorsThink, gpGlobals->curtime + TICK_INTERVAL, g_pszGunnerSpawnContext );
Expand Down
25 changes: 25 additions & 0 deletions sp/src/game/server/hl2/npc_combinegunship.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,15 +187,29 @@ class CTargetGunshipCrash : public CPointEntity
{
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 );
Expand All @@ -209,6 +223,9 @@ BEGIN_DATADESC( CTargetGunshipCrash )

// Outputs
DEFINE_OUTPUT( m_OnCrashed, "OnCrashed" ),
#ifdef MAPBASE
DEFINE_OUTPUT( m_OnBeginCrash, "OnBeginCrash" ),
#endif
END_DATADESC()


Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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);
Expand Down
Loading