286 lines
8.2 KiB
C++
286 lines
8.2 KiB
C++
|
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
|
|||
|
//
|
|||
|
// Purpose: Dissolve entity to be attached to target entity. Serves two purposes:
|
|||
|
//
|
|||
|
// 1) An entity that can be placed by a level designer and triggered
|
|||
|
// to ignite a target entity.
|
|||
|
//
|
|||
|
// 2) An entity that can be created at runtime to ignite a target entity.
|
|||
|
//
|
|||
|
//===========================================================================//
|
|||
|
|
|||
|
#include "cbase.h"
|
|||
|
#include "RagdollBoogie.h"
|
|||
|
#include "physics_prop_ragdoll.h"
|
|||
|
#include "effect_dispatch_data.h"
|
|||
|
#include "te_effect_dispatch.h"
|
|||
|
#include "IEffects.h"
|
|||
|
|
|||
|
// memdbgon must be the last include file in a .cpp file!!!
|
|||
|
#include "tier0/memdbgon.h"
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Make electriciy every so often
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
static const char *s_pZapContext = "ZapContext";
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Save/load
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
BEGIN_DATADESC( CRagdollBoogie )
|
|||
|
|
|||
|
DEFINE_FIELD( m_flStartTime, FIELD_TIME ),
|
|||
|
DEFINE_FIELD( m_flBoogieLength, FIELD_FLOAT ),
|
|||
|
DEFINE_FIELD( m_flMagnitude, FIELD_FLOAT ),
|
|||
|
|
|||
|
// Think this should be handled by StartTouch/etc.
|
|||
|
// DEFINE_FIELD( m_nSuppressionCount, FIELD_INTEGER ),
|
|||
|
|
|||
|
DEFINE_FUNCTION( BoogieThink ),
|
|||
|
DEFINE_FUNCTION( ZapThink ),
|
|||
|
|
|||
|
END_DATADESC()
|
|||
|
|
|||
|
LINK_ENTITY_TO_CLASS( env_ragdoll_boogie, CRagdollBoogie );
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Purpose: Creates a flame and attaches it to a target entity.
|
|||
|
// Input : pTarget -
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
CRagdollBoogie *CRagdollBoogie::Create( CBaseEntity *pTarget, float flMagnitude,
|
|||
|
float flStartTime, float flLengthTime, int nSpawnFlags )
|
|||
|
{
|
|||
|
CRagdollProp *pRagdoll = dynamic_cast< CRagdollProp* >( pTarget );
|
|||
|
if ( !pRagdoll )
|
|||
|
return NULL;
|
|||
|
|
|||
|
CRagdollBoogie *pBoogie = (CRagdollBoogie *)CreateEntityByName( "env_ragdoll_boogie" );
|
|||
|
if ( pBoogie == NULL )
|
|||
|
return NULL;
|
|||
|
|
|||
|
pBoogie->AddSpawnFlags( nSpawnFlags );
|
|||
|
pBoogie->AttachToEntity( pTarget );
|
|||
|
pBoogie->SetBoogieTime( flStartTime, flLengthTime );
|
|||
|
pBoogie->SetMagnitude( flMagnitude );
|
|||
|
pBoogie->Spawn();
|
|||
|
return pBoogie;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Spawn
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
void CRagdollBoogie::Precache()
|
|||
|
{
|
|||
|
BaseClass::Precache();
|
|||
|
|
|||
|
PrecacheEffect( "TeslaHitboxes" );
|
|||
|
|
|||
|
#ifdef HL2_EPISODIC
|
|||
|
PrecacheScriptSound( "RagdollBoogie.Zap" );
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Spawn
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
void CRagdollBoogie::Spawn()
|
|||
|
{
|
|||
|
Precache();
|
|||
|
|
|||
|
BaseClass::Spawn();
|
|||
|
|
|||
|
SetThink( &CRagdollBoogie::BoogieThink );
|
|||
|
SetNextThink( gpGlobals->curtime + 0.01f );
|
|||
|
|
|||
|
if ( HasSpawnFlags( SF_RAGDOLL_BOOGIE_ELECTRICAL ) )
|
|||
|
{
|
|||
|
SetContextThink( &CRagdollBoogie::ZapThink, gpGlobals->curtime + random->RandomFloat( 0.1f, 0.3f ), s_pZapContext );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Zap!
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
void CRagdollBoogie::ZapThink()
|
|||
|
{
|
|||
|
if ( !GetMoveParent() )
|
|||
|
return;
|
|||
|
|
|||
|
CBaseAnimating *pRagdoll = GetMoveParent()->GetBaseAnimating();
|
|||
|
if ( !pRagdoll )
|
|||
|
return;
|
|||
|
|
|||
|
// Make electricity on the client
|
|||
|
CStudioHdr *pStudioHdr = pRagdoll->GetModelPtr( );
|
|||
|
if (!pStudioHdr)
|
|||
|
return;
|
|||
|
|
|||
|
mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( pRagdoll->GetHitboxSet() );
|
|||
|
|
|||
|
if ( set->numhitboxes == 0 )
|
|||
|
return;
|
|||
|
|
|||
|
if ( m_nSuppressionCount == 0 )
|
|||
|
{
|
|||
|
CEffectData data;
|
|||
|
|
|||
|
data.m_nEntIndex = GetMoveParent()->entindex();
|
|||
|
data.m_flMagnitude = 4;
|
|||
|
data.m_flScale = HasSpawnFlags(SF_RAGDOLL_BOOGIE_ELECTRICAL_NARROW_BEAM) ? 1.0f : 2.0f;
|
|||
|
|
|||
|
DispatchEffect( "TeslaHitboxes", data );
|
|||
|
}
|
|||
|
|
|||
|
#ifdef HL2_EPISODIC
|
|||
|
EmitSound( "RagdollBoogie.Zap" );
|
|||
|
#endif
|
|||
|
|
|||
|
SetContextThink( &CRagdollBoogie::ZapThink, gpGlobals->curtime + random->RandomFloat( 0.1f, 0.3f ), s_pZapContext );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Suppression count
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
void CRagdollBoogie::IncrementSuppressionCount( CBaseEntity *pTarget )
|
|||
|
{
|
|||
|
// Look for other boogies on the ragdoll + kill them
|
|||
|
for ( CBaseEntity *pChild = pTarget->FirstMoveChild(); pChild; pChild = pChild->NextMovePeer() )
|
|||
|
{
|
|||
|
CRagdollBoogie *pBoogie = dynamic_cast<CRagdollBoogie*>(pChild);
|
|||
|
if ( !pBoogie )
|
|||
|
continue;
|
|||
|
|
|||
|
++pBoogie->m_nSuppressionCount;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void CRagdollBoogie::DecrementSuppressionCount( CBaseEntity *pTarget )
|
|||
|
{
|
|||
|
// Look for other boogies on the ragdoll + kill them
|
|||
|
CBaseEntity *pNext;
|
|||
|
for ( CBaseEntity *pChild = pTarget->FirstMoveChild(); pChild; pChild = pNext )
|
|||
|
{
|
|||
|
pNext = pChild->NextMovePeer();
|
|||
|
CRagdollBoogie *pBoogie = dynamic_cast<CRagdollBoogie*>(pChild);
|
|||
|
if ( !pBoogie )
|
|||
|
continue;
|
|||
|
|
|||
|
if ( --pBoogie->m_nSuppressionCount <= 0 )
|
|||
|
{
|
|||
|
pBoogie->m_nSuppressionCount = 0;
|
|||
|
|
|||
|
float dt = gpGlobals->curtime - pBoogie->m_flStartTime;
|
|||
|
if ( dt >= pBoogie->m_flBoogieLength )
|
|||
|
{
|
|||
|
PhysCallbackRemove( pBoogie->NetworkProp() );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Attach to an entity
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
void CRagdollBoogie::AttachToEntity( CBaseEntity *pTarget )
|
|||
|
{
|
|||
|
m_nSuppressionCount = 0;
|
|||
|
|
|||
|
// Look for other boogies on the ragdoll + kill them
|
|||
|
CBaseEntity *pNext;
|
|||
|
for ( CBaseEntity *pChild = pTarget->FirstMoveChild(); pChild; pChild = pNext )
|
|||
|
{
|
|||
|
pNext = pChild->NextMovePeer();
|
|||
|
CRagdollBoogie *pBoogie = dynamic_cast<CRagdollBoogie*>(pChild);
|
|||
|
if ( !pBoogie )
|
|||
|
continue;
|
|||
|
|
|||
|
m_nSuppressionCount = pBoogie->m_nSuppressionCount;
|
|||
|
UTIL_Remove( pChild );
|
|||
|
}
|
|||
|
|
|||
|
FollowEntity( pTarget );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Purpose:
|
|||
|
// Input : lifetime -
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
void CRagdollBoogie::SetBoogieTime( float flStartTime, float flLengthTime )
|
|||
|
{
|
|||
|
m_flStartTime = flStartTime;
|
|||
|
m_flBoogieLength = flLengthTime;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Purpose: Burn targets around us
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
void CRagdollBoogie::SetMagnitude( float flMagnitude )
|
|||
|
{
|
|||
|
m_flMagnitude = flMagnitude;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Purpose: Burn targets around us
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
void CRagdollBoogie::BoogieThink( void )
|
|||
|
{
|
|||
|
CRagdollProp *pRagdoll = dynamic_cast< CRagdollProp* >( GetMoveParent() );
|
|||
|
if ( !pRagdoll )
|
|||
|
{
|
|||
|
UTIL_Remove( this );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
float flMagnitude = m_flMagnitude;
|
|||
|
if ( m_flBoogieLength != 0 )
|
|||
|
{
|
|||
|
float dt = gpGlobals->curtime - m_flStartTime;
|
|||
|
if ( dt >= m_flBoogieLength )
|
|||
|
{
|
|||
|
// Don't remove while suppressed... this helps if we try to start another boogie
|
|||
|
if ( m_nSuppressionCount == 0 )
|
|||
|
{
|
|||
|
UTIL_Remove( this );
|
|||
|
}
|
|||
|
SetThink( NULL );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if ( dt < 0 )
|
|||
|
{
|
|||
|
SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.1, 0.2f ) );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
flMagnitude = SimpleSplineRemapVal( dt, 0.0f, m_flBoogieLength, m_flMagnitude, 0.0f );
|
|||
|
}
|
|||
|
|
|||
|
#ifndef _XBOX
|
|||
|
if ( m_nSuppressionCount == 0 )
|
|||
|
{
|
|||
|
ragdoll_t *pRagdollPhys = pRagdoll->GetRagdoll( );
|
|||
|
for ( int j = 0; j < pRagdollPhys->listCount; ++j )
|
|||
|
{
|
|||
|
float flMass = pRagdollPhys->list[j].pObject->GetMass();
|
|||
|
float flForce = m_flMagnitude * flMass;
|
|||
|
|
|||
|
Vector vecForce;
|
|||
|
vecForce = RandomVector( -flForce, flForce );
|
|||
|
pRagdollPhys->list[j].pObject->ApplyForceCenter( vecForce );
|
|||
|
}
|
|||
|
}
|
|||
|
#endif // !_XBOX
|
|||
|
|
|||
|
SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.1, 0.2f ) );
|
|||
|
}
|