You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
251 lines
6.7 KiB
251 lines
6.7 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// TF Generic Bomb |
|
// |
|
//============================================================================= |
|
#include "cbase.h" |
|
#include "tf_generic_bomb.h" |
|
#include "takedamageinfo.h" |
|
#include "tf_shareddefs.h" |
|
#include "props_shared.h" |
|
#ifdef GAME_DLL |
|
#include "te_effect_dispatch.h" |
|
#include "tf_fx.h" |
|
#include "tf_projectile_base.h" |
|
#include "basegrenade_shared.h" |
|
#include "tf_gamerules.h" |
|
#include "tf_weaponbase_rocket.h" |
|
#endif |
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
LINK_ENTITY_TO_CLASS( tf_generic_bomb, CTFGenericBomb ); |
|
|
|
IMPLEMENT_NETWORKCLASS_ALIASED( TFGenericBomb, DT_TFGenericBomb ) |
|
|
|
BEGIN_NETWORK_TABLE( CTFGenericBomb, DT_TFGenericBomb ) |
|
END_NETWORK_TABLE() |
|
|
|
IMPLEMENT_AUTO_LIST( ITFGenericBomb ); |
|
|
|
#ifdef GAME_DLL |
|
BEGIN_DATADESC( CTFGenericBomb ) |
|
// Keyfields |
|
DEFINE_KEYFIELD( m_flDamage, FIELD_FLOAT, "damage" ), |
|
DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "radius" ), |
|
DEFINE_KEYFIELD( m_nHealth, FIELD_INTEGER, "health" ), |
|
DEFINE_KEYFIELD( m_strExplodeParticleName, FIELD_STRING, "explode_particle" ), |
|
DEFINE_KEYFIELD( m_strExplodeSoundName, FIELD_STRING, "sound" ), |
|
DEFINE_KEYFIELD( m_eWhoToDamage, FIELD_INTEGER, "friendlyfire" ), |
|
|
|
// Output |
|
DEFINE_OUTPUT( m_OnDetonate, "OnDetonate" ), |
|
|
|
// Input |
|
DEFINE_INPUTFUNC( FIELD_VOID, "Detonate", Detonate ), |
|
|
|
END_DATADESC() |
|
#endif |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CTFGenericBomb::CTFGenericBomb() |
|
{ |
|
m_bDead = false; |
|
m_bPrecached = false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFGenericBomb::Precache() |
|
{ |
|
BaseClass::Precache(); |
|
|
|
// always allow late precaching |
|
bool bAllowPrecache = CBaseEntity::IsPrecacheAllowed(); |
|
CBaseEntity::SetAllowPrecache( true ); |
|
|
|
int iModel = PrecacheModel( STRING( GetModelName() ) ); |
|
PrecacheGibsForModel( iModel ); |
|
PrecacheModel( STRING( GetModelName() ) ); |
|
if ( STRING( m_strExplodeParticleName ) && STRING( m_strExplodeParticleName )[0] ) |
|
{ |
|
PrecacheParticleSystem( STRING( m_strExplodeParticleName ) ); |
|
} |
|
|
|
if ( STRING( m_strExplodeSoundName ) && STRING( m_strExplodeSoundName )[0] ) |
|
{ |
|
PrecacheScriptSound( STRING( m_strExplodeSoundName ) ); |
|
} |
|
|
|
CBaseEntity::SetAllowPrecache( bAllowPrecache ); |
|
|
|
m_bPrecached = true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void CTFGenericBomb::Spawn() |
|
{ |
|
if ( !m_bPrecached ) |
|
{ |
|
Precache(); |
|
} |
|
|
|
#ifdef GAME_DLL |
|
SetModel( STRING( GetModelName() ) ); |
|
#endif |
|
SetMoveType( MOVETYPE_VPHYSICS ); |
|
SetSolid( SOLID_VPHYSICS ); |
|
|
|
SetHealth( m_nHealth ); |
|
|
|
BaseClass::Spawn(); |
|
|
|
m_takedamage = DAMAGE_YES; |
|
m_bDead = false; |
|
|
|
SetTouch( &CTFGenericBombShim::Touch ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFGenericBomb::GenericTouch( CBaseEntity *pOther ) |
|
{ |
|
if ( !pOther ) |
|
return; |
|
|
|
#ifdef GAME_DLL |
|
if ( pOther->GetFlags() & FL_GRENADE ) |
|
{ |
|
// Only let my team destroy |
|
CBaseEntity *pAttacker = NULL; |
|
|
|
CBaseGrenade *pGrenade = dynamic_cast<CBaseGrenade*>(pOther); |
|
if ( pGrenade ) |
|
{ |
|
pAttacker = pGrenade->GetThrower(); |
|
// Do a proper explosion |
|
Vector velDir = pGrenade->GetAbsVelocity(); |
|
VectorNormalize( velDir ); |
|
Vector vecSpot = pGrenade->GetAbsOrigin() - velDir * 32; |
|
trace_t tr; |
|
UTIL_TraceLine( vecSpot, vecSpot + velDir * 64, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); |
|
// Boom |
|
pGrenade->Explode( &tr, DMG_BLAST ); |
|
} |
|
else |
|
{ |
|
CTFBaseRocket *pRocket = dynamic_cast<CTFBaseRocket*>(pOther); |
|
if ( pRocket ) |
|
{ |
|
Vector velDir = pRocket->GetAbsVelocity(); |
|
VectorNormalize( velDir ); |
|
Vector vecSpot = pRocket->GetAbsOrigin() - velDir * 32; |
|
trace_t tr; |
|
UTIL_TraceLine( vecSpot, vecSpot + velDir * 64, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); |
|
pRocket->Explode( &tr, this ); |
|
} |
|
} |
|
|
|
if ( !pAttacker ) |
|
{ |
|
CTFBaseProjectile *pProj = dynamic_cast<CTFBaseProjectile*>(pOther); |
|
if ( pProj ) |
|
{ |
|
pAttacker = pProj->GetScorer(); |
|
} |
|
} |
|
|
|
TakeDamage( CTakeDamageInfo( pOther, pAttacker, 10.f, DMG_CRUSH ) ); |
|
} |
|
#endif |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
#ifdef GAME_DLL |
|
|
|
void CTFGenericBomb::Detonate( inputdata_t& inputdata ) |
|
{ |
|
CTakeDamageInfo info; |
|
Event_Killed( info ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void CTFGenericBomb::Event_Killed( const CTakeDamageInfo &info ) |
|
{ |
|
if ( m_bDead ) |
|
return; |
|
|
|
m_bDead = true; |
|
|
|
trace_t tr; |
|
Vector vecSpot = GetAbsOrigin() + Vector ( 0 , 0 , 8 ); |
|
UTIL_TraceLine( vecSpot, vecSpot + Vector ( 0, 0, -32 ), MASK_SHOT_HULL, this, COLLISION_GROUP_NONE, &tr ); |
|
|
|
// Explosion effect and gibs. |
|
Vector vecOrigin = GetAbsOrigin(); |
|
QAngle vecAngles = GetAbsAngles(); |
|
int iAttachment = LookupAttachment( "alt-origin" ); |
|
if ( iAttachment > 0 ) |
|
{ |
|
GetAttachment( iAttachment, vecOrigin, vecAngles ); |
|
} |
|
CPVSFilter pvsFilter( vecOrigin ); |
|
if ( STRING( m_strExplodeParticleName ) && STRING( m_strExplodeParticleName )[0] ) |
|
{ |
|
TE_TFParticleEffect( pvsFilter, 0.0f, STRING( m_strExplodeParticleName ), vecOrigin, vecAngles ); |
|
} |
|
|
|
if ( STRING( m_strExplodeSoundName ) && STRING( m_strExplodeSoundName )[0] ) |
|
{ |
|
EmitSound( STRING( m_strExplodeSoundName ) ); |
|
} |
|
|
|
// Get the owner out of the attacker in case of arrows hitting the bomb. |
|
CBaseEntity* pAttacker = info.GetAttacker(); |
|
if ( pAttacker && pAttacker->GetOwnerEntity() ) |
|
{ |
|
pAttacker = pAttacker->GetOwnerEntity(); |
|
} |
|
|
|
// Deal damage. |
|
SetSolid( SOLID_NONE ); |
|
if ( pAttacker ) |
|
{ |
|
ChangeTeam( pAttacker->GetTeamNumber() ); |
|
} |
|
|
|
CTakeDamageInfo damage_info( this, pAttacker, NULL, m_flDamage, DMG_BLAST | DMG_HALF_FALLOFF | DMG_NOCLOSEDISTANCEMOD ); |
|
damage_info.SetDamageCustom( TF_DMG_CUSTOM_NONE ); |
|
|
|
damage_info.SetForceFriendlyFire( m_eWhoToDamage == DAMAGE_EVERYONE ); |
|
|
|
if ( TFGameRules() ) |
|
{ |
|
CTFRadiusDamageInfo radiusinfo( &damage_info, vecOrigin, m_flRadius, this ); |
|
TFGameRules()->RadiusDamage( radiusinfo ); |
|
} |
|
|
|
// Don't decal players with scorch. |
|
if ( tr.m_pEnt && !tr.m_pEnt->IsPlayer() ) |
|
{ |
|
UTIL_DecalTrace( &tr, "Scorch" ); |
|
} |
|
|
|
// Spawns gibs on the client |
|
UserMessageBegin( pvsFilter, "BreakModel" ); |
|
WRITE_SHORT( GetModelIndex() ); |
|
WRITE_VEC3COORD( vecOrigin ); |
|
WRITE_ANGLES( vecAngles ); |
|
WRITE_SHORT( m_nSkin ); |
|
MessageEnd(); |
|
|
|
m_OnDetonate.FireOutput( this, this ); |
|
|
|
BaseClass::Event_Killed( info ); |
|
} |
|
|
|
#endif
|
|
|