aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/shared/basegrenade_shared.cpp
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/shared/basegrenade_shared.cpp
parentMark some more files as text. (diff)
downloadsource-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz
source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/shared/basegrenade_shared.cpp')
-rw-r--r--mp/src/game/shared/basegrenade_shared.cpp1116
1 files changed, 558 insertions, 558 deletions
diff --git a/mp/src/game/shared/basegrenade_shared.cpp b/mp/src/game/shared/basegrenade_shared.cpp
index 7ac9becd..b981d078 100644
--- a/mp/src/game/shared/basegrenade_shared.cpp
+++ b/mp/src/game/shared/basegrenade_shared.cpp
@@ -1,558 +1,558 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//=============================================================================//
-#include "cbase.h"
-#include "decals.h"
-#include "basegrenade_shared.h"
-#include "shake.h"
-#include "engine/IEngineSound.h"
-
-#if !defined( CLIENT_DLL )
-
-#include "soundent.h"
-#include "entitylist.h"
-#include "gamestats.h"
-
-#endif
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-extern short g_sModelIndexFireball; // (in combatweapon.cpp) holds the index for the fireball
-extern short g_sModelIndexWExplosion; // (in combatweapon.cpp) holds the index for the underwater explosion
-extern short g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud
-extern ConVar sk_plr_dmg_grenade;
-
-#if !defined( CLIENT_DLL )
-
-// Global Savedata for friction modifier
-BEGIN_DATADESC( CBaseGrenade )
- // nextGrenade
- DEFINE_FIELD( m_hThrower, FIELD_EHANDLE ),
- // m_fRegisteredSound ???
- DEFINE_FIELD( m_bIsLive, FIELD_BOOLEAN ),
- DEFINE_FIELD( m_DmgRadius, FIELD_FLOAT ),
- DEFINE_FIELD( m_flDetonateTime, FIELD_TIME ),
- DEFINE_FIELD( m_flWarnAITime, FIELD_TIME ),
- DEFINE_FIELD( m_flDamage, FIELD_FLOAT ),
- DEFINE_FIELD( m_iszBounceSound, FIELD_STRING ),
- DEFINE_FIELD( m_bHasWarnedAI, FIELD_BOOLEAN ),
-
- // Function Pointers
- DEFINE_THINKFUNC( Smoke ),
- DEFINE_ENTITYFUNC( BounceTouch ),
- DEFINE_ENTITYFUNC( SlideTouch ),
- DEFINE_ENTITYFUNC( ExplodeTouch ),
- DEFINE_USEFUNC( DetonateUse ),
- DEFINE_THINKFUNC( DangerSoundThink ),
- DEFINE_THINKFUNC( PreDetonate ),
- DEFINE_THINKFUNC( Detonate ),
- DEFINE_THINKFUNC( TumbleThink ),
-
-END_DATADESC()
-
-void SendProxy_CropFlagsToPlayerFlagBitsLength( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID);
-
-#endif
-
-IMPLEMENT_NETWORKCLASS_ALIASED( BaseGrenade, DT_BaseGrenade )
-
-BEGIN_NETWORK_TABLE( CBaseGrenade, DT_BaseGrenade )
-#if !defined( CLIENT_DLL )
- SendPropFloat( SENDINFO( m_flDamage ), 10, SPROP_ROUNDDOWN, 0.0, 256.0f ),
- SendPropFloat( SENDINFO( m_DmgRadius ), 10, SPROP_ROUNDDOWN, 0.0, 1024.0f ),
- SendPropInt( SENDINFO( m_bIsLive ), 1, SPROP_UNSIGNED ),
-// SendPropTime( SENDINFO( m_flDetonateTime ) ),
- SendPropEHandle( SENDINFO( m_hThrower ) ),
-
- SendPropVector( SENDINFO( m_vecVelocity ), 0, SPROP_NOSCALE ),
- // HACK: Use same flag bits as player for now
- SendPropInt ( SENDINFO(m_fFlags), PLAYER_FLAG_BITS, SPROP_UNSIGNED, SendProxy_CropFlagsToPlayerFlagBitsLength ),
-#else
- RecvPropFloat( RECVINFO( m_flDamage ) ),
- RecvPropFloat( RECVINFO( m_DmgRadius ) ),
- RecvPropInt( RECVINFO( m_bIsLive ) ),
-// RecvPropTime( RECVINFO( m_flDetonateTime ) ),
- RecvPropEHandle( RECVINFO( m_hThrower ) ),
-
- // Need velocity from grenades to make animation system work correctly when running
- RecvPropVector( RECVINFO(m_vecVelocity), 0, RecvProxy_LocalVelocity ),
-
- RecvPropInt( RECVINFO( m_fFlags ) ),
-#endif
-END_NETWORK_TABLE()
-
-LINK_ENTITY_TO_CLASS( grenade, CBaseGrenade );
-
-#if defined( CLIENT_DLL )
-
-BEGIN_PREDICTION_DATA( CBaseGrenade )
-
- DEFINE_PRED_FIELD( m_hThrower, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ),
- DEFINE_PRED_FIELD( m_bIsLive, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
- DEFINE_PRED_FIELD( m_DmgRadius, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
-// DEFINE_PRED_FIELD_TOL( m_flDetonateTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE, TD_MSECTOLERANCE ),
- DEFINE_PRED_FIELD( m_flDamage, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
-
- DEFINE_PRED_FIELD_TOL( m_vecVelocity, FIELD_VECTOR, FTYPEDESC_INSENDTABLE, 0.5f ),
- DEFINE_PRED_FIELD_TOL( m_flNextAttack, FIELD_FLOAT, FTYPEDESC_INSENDTABLE, TD_MSECTOLERANCE ),
-
-// DEFINE_FIELD( m_fRegisteredSound, FIELD_BOOLEAN ),
-// DEFINE_FIELD( m_iszBounceSound, FIELD_STRING ),
-
-END_PREDICTION_DATA()
-
-#endif
-
-// Grenades flagged with this will be triggered when the owner calls detonateSatchelCharges
-#define SF_DETONATE 0x0001
-
-// UNDONE: temporary scorching for PreAlpha - find a less sleazy permenant solution.
-void CBaseGrenade::Explode( trace_t *pTrace, int bitsDamageType )
-{
-#if !defined( CLIENT_DLL )
-
- SetModelName( NULL_STRING );//invisible
- AddSolidFlags( FSOLID_NOT_SOLID );
-
- m_takedamage = DAMAGE_NO;
-
- // Pull out of the wall a bit
- if ( pTrace->fraction != 1.0 )
- {
- SetAbsOrigin( pTrace->endpos + (pTrace->plane.normal * 0.6) );
- }
-
- Vector vecAbsOrigin = GetAbsOrigin();
- int contents = UTIL_PointContents ( vecAbsOrigin );
-
-#if defined( TF_DLL )
- // Since this code only runs on the server, make sure it shows the tempents it creates.
- // This solves a problem with remote detonating the pipebombs (client wasn't seeing the explosion effect)
- CDisablePredictionFiltering disabler;
-#endif
-
- if ( pTrace->fraction != 1.0 )
- {
- Vector vecNormal = pTrace->plane.normal;
- surfacedata_t *pdata = physprops->GetSurfaceData( pTrace->surface.surfaceProps );
- CPASFilter filter( vecAbsOrigin );
-
- te->Explosion( filter, -1.0, // don't apply cl_interp delay
- &vecAbsOrigin,
- !( contents & MASK_WATER ) ? g_sModelIndexFireball : g_sModelIndexWExplosion,
- m_DmgRadius * .03,
- 25,
- TE_EXPLFLAG_NONE,
- m_DmgRadius,
- m_flDamage,
- &vecNormal,
- (char) pdata->game.material );
- }
- else
- {
- CPASFilter filter( vecAbsOrigin );
- te->Explosion( filter, -1.0, // don't apply cl_interp delay
- &vecAbsOrigin,
- !( contents & MASK_WATER ) ? g_sModelIndexFireball : g_sModelIndexWExplosion,
- m_DmgRadius * .03,
- 25,
- TE_EXPLFLAG_NONE,
- m_DmgRadius,
- m_flDamage );
- }
-
-#if !defined( CLIENT_DLL )
- CSoundEnt::InsertSound ( SOUND_COMBAT, GetAbsOrigin(), BASEGRENADE_EXPLOSION_VOLUME, 3.0 );
-#endif
-
- // Use the thrower's position as the reported position
- Vector vecReported = m_hThrower ? m_hThrower->GetAbsOrigin() : vec3_origin;
-
- CTakeDamageInfo info( this, m_hThrower, GetBlastForce(), GetAbsOrigin(), m_flDamage, bitsDamageType, 0, &vecReported );
-
- RadiusDamage( info, GetAbsOrigin(), m_DmgRadius, CLASS_NONE, NULL );
-
- UTIL_DecalTrace( pTrace, "Scorch" );
-
- EmitSound( "BaseGrenade.Explode" );
-
- SetThink( &CBaseGrenade::SUB_Remove );
- SetTouch( NULL );
- SetSolid( SOLID_NONE );
-
- AddEffects( EF_NODRAW );
- SetAbsVelocity( vec3_origin );
-
-#if HL2_EPISODIC
- // Because the grenade is zipped out of the world instantly, the EXPLOSION sound that it makes for
- // the AI is also immediately destroyed. For this reason, we now make the grenade entity inert and
- // throw it away in 1/10th of a second instead of right away. Removing the grenade instantly causes
- // intermittent bugs with env_microphones who are listening for explosions. They will 'randomly' not
- // hear explosion sounds when the grenade is removed and the SoundEnt thinks (and removes the sound)
- // before the env_microphone thinks and hears the sound.
- SetNextThink( gpGlobals->curtime + 0.1 );
-#else
- SetNextThink( gpGlobals->curtime );
-#endif//HL2_EPISODIC
-
-#if defined( HL2_DLL )
- CBasePlayer *pPlayer = ToBasePlayer( m_hThrower.Get() );
- if ( pPlayer )
- {
- gamestats->Event_WeaponHit( pPlayer, true, "weapon_frag", info );
- }
-#endif
-
-#endif
-}
-
-
-void CBaseGrenade::Smoke( void )
-{
- Vector vecAbsOrigin = GetAbsOrigin();
- if ( UTIL_PointContents ( vecAbsOrigin ) & MASK_WATER )
- {
- UTIL_Bubbles( vecAbsOrigin - Vector( 64, 64, 64 ), vecAbsOrigin + Vector( 64, 64, 64 ), 100 );
- }
- else
- {
- CPVSFilter filter( vecAbsOrigin );
-
- te->Smoke( filter, 0.0,
- &vecAbsOrigin, g_sModelIndexSmoke,
- m_DmgRadius * 0.03,
- 24 );
- }
-#if !defined( CLIENT_DLL )
- SetThink ( &CBaseGrenade::SUB_Remove );
-#endif
- SetNextThink( gpGlobals->curtime );
-}
-
-void CBaseGrenade::Event_Killed( const CTakeDamageInfo &info )
-{
- Detonate( );
-}
-
-#if !defined( CLIENT_DLL )
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CBaseGrenade::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
-{
- // Support player pickup
- if ( useType == USE_TOGGLE )
- {
- CBasePlayer *pPlayer = ToBasePlayer( pActivator );
- if ( pPlayer )
- {
- pPlayer->PickupObject( this );
- return;
- }
- }
-
- // Pass up so we still call any custom Use function
- BaseClass::Use( pActivator, pCaller, useType, value );
-}
-#endif
-
-//-----------------------------------------------------------------------------
-// Purpose: Timed grenade, this think is called when time runs out.
-//-----------------------------------------------------------------------------
-void CBaseGrenade::DetonateUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
-{
- SetThink( &CBaseGrenade::Detonate );
- SetNextThink( gpGlobals->curtime );
-}
-
-void CBaseGrenade::PreDetonate( void )
-{
-#if !defined( CLIENT_DLL )
- CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin(), 400, 1.5, this );
-#endif
-
- SetThink( &CBaseGrenade::Detonate );
- SetNextThink( gpGlobals->curtime + 1.5 );
-}
-
-
-void CBaseGrenade::Detonate( void )
-{
- trace_t tr;
- Vector vecSpot;// trace starts here!
-
- SetThink( NULL );
-
- vecSpot = GetAbsOrigin() + Vector ( 0 , 0 , 8 );
- UTIL_TraceLine ( vecSpot, vecSpot + Vector ( 0, 0, -32 ), MASK_SHOT_HULL, this, COLLISION_GROUP_NONE, & tr);
-
- if( tr.startsolid )
- {
- // Since we blindly moved the explosion origin vertically, we may have inadvertently moved the explosion into a solid,
- // in which case nothing is going to be harmed by the grenade's explosion because all subsequent traces will startsolid.
- // If this is the case, we do the downward trace again from the actual origin of the grenade. (sjb) 3/8/2007 (for ep2_outland_09)
- UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, -32), MASK_SHOT_HULL, this, COLLISION_GROUP_NONE, &tr );
- }
-
- Explode( &tr, DMG_BLAST );
-
- if ( GetShakeAmplitude() )
- {
- UTIL_ScreenShake( GetAbsOrigin(), GetShakeAmplitude(), 150.0, 1.0, GetShakeRadius(), SHAKE_START );
- }
-}
-
-
-//
-// Contact grenade, explode when it touches something
-//
-void CBaseGrenade::ExplodeTouch( CBaseEntity *pOther )
-{
- trace_t tr;
- Vector vecSpot;// trace starts here!
-
- Assert( pOther );
- if ( !pOther->IsSolid() )
- return;
-
- Vector velDir = GetAbsVelocity();
- VectorNormalize( velDir );
- vecSpot = GetAbsOrigin() - velDir * 32;
- UTIL_TraceLine( vecSpot, vecSpot + velDir * 64, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );
-
- Explode( &tr, DMG_BLAST );
-}
-
-
-void CBaseGrenade::DangerSoundThink( void )
-{
- if (!IsInWorld())
- {
- Remove( );
- return;
- }
-
-#if !defined( CLIENT_DLL )
- CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin() + GetAbsVelocity() * 0.5, GetAbsVelocity().Length( ), 0.2, this );
-#endif
-
- SetNextThink( gpGlobals->curtime + 0.2 );
-
- if (GetWaterLevel() != 0)
- {
- SetAbsVelocity( GetAbsVelocity() * 0.5 );
- }
-}
-
-
-void CBaseGrenade::BounceTouch( CBaseEntity *pOther )
-{
- if ( pOther->IsSolidFlagSet(FSOLID_TRIGGER | FSOLID_VOLUME_CONTENTS) )
- return;
-
- // don't hit the guy that launched this grenade
- if ( pOther == GetThrower() )
- return;
-
- // only do damage if we're moving fairly fast
- if ( (pOther->m_takedamage != DAMAGE_NO) && (m_flNextAttack < gpGlobals->curtime && GetAbsVelocity().Length() > 100))
- {
- if (m_hThrower)
- {
-#if !defined( CLIENT_DLL )
- trace_t tr;
- tr = CBaseEntity::GetTouchTrace( );
- ClearMultiDamage( );
- Vector forward;
- AngleVectors( GetLocalAngles(), &forward, NULL, NULL );
- CTakeDamageInfo info( this, m_hThrower, 1, DMG_CLUB );
- CalculateMeleeDamageForce( &info, GetAbsVelocity(), GetAbsOrigin() );
- pOther->DispatchTraceAttack( info, forward, &tr );
- ApplyMultiDamage();
-#endif
- }
- m_flNextAttack = gpGlobals->curtime + 1.0; // debounce
- }
-
- Vector vecTestVelocity;
- // m_vecAngVelocity = Vector (300, 300, 300);
-
- // this is my heuristic for modulating the grenade velocity because grenades dropped purely vertical
- // or thrown very far tend to slow down too quickly for me to always catch just by testing velocity.
- // trimming the Z velocity a bit seems to help quite a bit.
- vecTestVelocity = GetAbsVelocity();
- vecTestVelocity.z *= 0.45;
-
- if ( !m_bHasWarnedAI && vecTestVelocity.Length() <= 60 )
- {
- // grenade is moving really slow. It's probably very close to where it will ultimately stop moving.
- // emit the danger sound.
-
- // register a radius louder than the explosion, so we make sure everyone gets out of the way
-#if !defined( CLIENT_DLL )
- CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin(), m_flDamage / 0.4, 0.3, this );
-#endif
- m_bHasWarnedAI = true;
- }
-
- if (GetFlags() & FL_ONGROUND)
- {
- // add a bit of static friction
-// SetAbsVelocity( GetAbsVelocity() * 0.8 );
-
- // SetSequence( random->RandomInt( 1, 1 ) ); // FIXME: missing tumble animations
- }
- else
- {
- // play bounce sound
- BounceSound();
- }
- m_flPlaybackRate = GetAbsVelocity().Length() / 200.0;
- if (m_flPlaybackRate > 1.0)
- m_flPlaybackRate = 1;
- else if (m_flPlaybackRate < 0.5)
- m_flPlaybackRate = 0;
-
-}
-
-
-
-void CBaseGrenade::SlideTouch( CBaseEntity *pOther )
-{
- // don't hit the guy that launched this grenade
- if ( pOther == GetThrower() )
- return;
-
- // m_vecAngVelocity = Vector (300, 300, 300);
-
- if (GetFlags() & FL_ONGROUND)
- {
- // add a bit of static friction
-// SetAbsVelocity( GetAbsVelocity() * 0.95 );
-
- if (GetAbsVelocity().x != 0 || GetAbsVelocity().y != 0)
- {
- // maintain sliding sound
- }
- }
- else
- {
- BounceSound();
- }
-}
-
-void CBaseGrenade ::BounceSound( void )
-{
- // Doesn't need to do anything anymore! Physics makes the sound.
-}
-
-void CBaseGrenade ::TumbleThink( void )
-{
- if (!IsInWorld())
- {
- Remove( );
- return;
- }
-
- StudioFrameAdvance( );
- SetNextThink( gpGlobals->curtime + 0.1f );
-
- //
- // Emit a danger sound one second before exploding.
- //
- if (m_flDetonateTime - 1 < gpGlobals->curtime)
- {
-#if !defined( CLIENT_DLL )
- CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin() + GetAbsVelocity() * (m_flDetonateTime - gpGlobals->curtime), 400, 0.1, this );
-#endif
- }
-
- if (m_flDetonateTime <= gpGlobals->curtime)
- {
- SetThink( &CBaseGrenade::Detonate );
- }
-
- if (GetWaterLevel() != 0)
- {
- SetAbsVelocity( GetAbsVelocity() * 0.5 );
- m_flPlaybackRate = 0.2;
- }
-}
-
-void CBaseGrenade::Precache( void )
-{
- BaseClass::Precache( );
-
- PrecacheScriptSound( "BaseGrenade.Explode" );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Output : CBaseCombatCharacter
-//-----------------------------------------------------------------------------
-CBaseCombatCharacter *CBaseGrenade::GetThrower( void )
-{
- CBaseCombatCharacter *pResult = ToBaseCombatCharacter( m_hThrower );
- if ( !pResult && GetOwnerEntity() != NULL )
- {
- pResult = ToBaseCombatCharacter( GetOwnerEntity() );
- }
- return pResult;
-}
-
-//-----------------------------------------------------------------------------
-
-void CBaseGrenade::SetThrower( CBaseCombatCharacter *pThrower )
-{
- m_hThrower = pThrower;
-
- // if this is the first thrower, set it as the original thrower
- if ( NULL == m_hOriginalThrower )
- {
- m_hOriginalThrower = pThrower;
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Destructor
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-CBaseGrenade::~CBaseGrenade(void)
-{
-};
-
-//-----------------------------------------------------------------------------
-// Purpose: Constructor
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-CBaseGrenade::CBaseGrenade(void)
-{
- m_hThrower = NULL;
- m_hOriginalThrower = NULL;
- m_bIsLive = false;
- m_DmgRadius = 100;
- m_flDetonateTime = 0;
- m_bHasWarnedAI = false;
-
- SetSimulatedEveryTick( true );
-};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+#include "cbase.h"
+#include "decals.h"
+#include "basegrenade_shared.h"
+#include "shake.h"
+#include "engine/IEngineSound.h"
+
+#if !defined( CLIENT_DLL )
+
+#include "soundent.h"
+#include "entitylist.h"
+#include "gamestats.h"
+
+#endif
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+extern short g_sModelIndexFireball; // (in combatweapon.cpp) holds the index for the fireball
+extern short g_sModelIndexWExplosion; // (in combatweapon.cpp) holds the index for the underwater explosion
+extern short g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud
+extern ConVar sk_plr_dmg_grenade;
+
+#if !defined( CLIENT_DLL )
+
+// Global Savedata for friction modifier
+BEGIN_DATADESC( CBaseGrenade )
+ // nextGrenade
+ DEFINE_FIELD( m_hThrower, FIELD_EHANDLE ),
+ // m_fRegisteredSound ???
+ DEFINE_FIELD( m_bIsLive, FIELD_BOOLEAN ),
+ DEFINE_FIELD( m_DmgRadius, FIELD_FLOAT ),
+ DEFINE_FIELD( m_flDetonateTime, FIELD_TIME ),
+ DEFINE_FIELD( m_flWarnAITime, FIELD_TIME ),
+ DEFINE_FIELD( m_flDamage, FIELD_FLOAT ),
+ DEFINE_FIELD( m_iszBounceSound, FIELD_STRING ),
+ DEFINE_FIELD( m_bHasWarnedAI, FIELD_BOOLEAN ),
+
+ // Function Pointers
+ DEFINE_THINKFUNC( Smoke ),
+ DEFINE_ENTITYFUNC( BounceTouch ),
+ DEFINE_ENTITYFUNC( SlideTouch ),
+ DEFINE_ENTITYFUNC( ExplodeTouch ),
+ DEFINE_USEFUNC( DetonateUse ),
+ DEFINE_THINKFUNC( DangerSoundThink ),
+ DEFINE_THINKFUNC( PreDetonate ),
+ DEFINE_THINKFUNC( Detonate ),
+ DEFINE_THINKFUNC( TumbleThink ),
+
+END_DATADESC()
+
+void SendProxy_CropFlagsToPlayerFlagBitsLength( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID);
+
+#endif
+
+IMPLEMENT_NETWORKCLASS_ALIASED( BaseGrenade, DT_BaseGrenade )
+
+BEGIN_NETWORK_TABLE( CBaseGrenade, DT_BaseGrenade )
+#if !defined( CLIENT_DLL )
+ SendPropFloat( SENDINFO( m_flDamage ), 10, SPROP_ROUNDDOWN, 0.0, 256.0f ),
+ SendPropFloat( SENDINFO( m_DmgRadius ), 10, SPROP_ROUNDDOWN, 0.0, 1024.0f ),
+ SendPropInt( SENDINFO( m_bIsLive ), 1, SPROP_UNSIGNED ),
+// SendPropTime( SENDINFO( m_flDetonateTime ) ),
+ SendPropEHandle( SENDINFO( m_hThrower ) ),
+
+ SendPropVector( SENDINFO( m_vecVelocity ), 0, SPROP_NOSCALE ),
+ // HACK: Use same flag bits as player for now
+ SendPropInt ( SENDINFO(m_fFlags), PLAYER_FLAG_BITS, SPROP_UNSIGNED, SendProxy_CropFlagsToPlayerFlagBitsLength ),
+#else
+ RecvPropFloat( RECVINFO( m_flDamage ) ),
+ RecvPropFloat( RECVINFO( m_DmgRadius ) ),
+ RecvPropInt( RECVINFO( m_bIsLive ) ),
+// RecvPropTime( RECVINFO( m_flDetonateTime ) ),
+ RecvPropEHandle( RECVINFO( m_hThrower ) ),
+
+ // Need velocity from grenades to make animation system work correctly when running
+ RecvPropVector( RECVINFO(m_vecVelocity), 0, RecvProxy_LocalVelocity ),
+
+ RecvPropInt( RECVINFO( m_fFlags ) ),
+#endif
+END_NETWORK_TABLE()
+
+LINK_ENTITY_TO_CLASS( grenade, CBaseGrenade );
+
+#if defined( CLIENT_DLL )
+
+BEGIN_PREDICTION_DATA( CBaseGrenade )
+
+ DEFINE_PRED_FIELD( m_hThrower, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ),
+ DEFINE_PRED_FIELD( m_bIsLive, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
+ DEFINE_PRED_FIELD( m_DmgRadius, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
+// DEFINE_PRED_FIELD_TOL( m_flDetonateTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE, TD_MSECTOLERANCE ),
+ DEFINE_PRED_FIELD( m_flDamage, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
+
+ DEFINE_PRED_FIELD_TOL( m_vecVelocity, FIELD_VECTOR, FTYPEDESC_INSENDTABLE, 0.5f ),
+ DEFINE_PRED_FIELD_TOL( m_flNextAttack, FIELD_FLOAT, FTYPEDESC_INSENDTABLE, TD_MSECTOLERANCE ),
+
+// DEFINE_FIELD( m_fRegisteredSound, FIELD_BOOLEAN ),
+// DEFINE_FIELD( m_iszBounceSound, FIELD_STRING ),
+
+END_PREDICTION_DATA()
+
+#endif
+
+// Grenades flagged with this will be triggered when the owner calls detonateSatchelCharges
+#define SF_DETONATE 0x0001
+
+// UNDONE: temporary scorching for PreAlpha - find a less sleazy permenant solution.
+void CBaseGrenade::Explode( trace_t *pTrace, int bitsDamageType )
+{
+#if !defined( CLIENT_DLL )
+
+ SetModelName( NULL_STRING );//invisible
+ AddSolidFlags( FSOLID_NOT_SOLID );
+
+ m_takedamage = DAMAGE_NO;
+
+ // Pull out of the wall a bit
+ if ( pTrace->fraction != 1.0 )
+ {
+ SetAbsOrigin( pTrace->endpos + (pTrace->plane.normal * 0.6) );
+ }
+
+ Vector vecAbsOrigin = GetAbsOrigin();
+ int contents = UTIL_PointContents ( vecAbsOrigin );
+
+#if defined( TF_DLL )
+ // Since this code only runs on the server, make sure it shows the tempents it creates.
+ // This solves a problem with remote detonating the pipebombs (client wasn't seeing the explosion effect)
+ CDisablePredictionFiltering disabler;
+#endif
+
+ if ( pTrace->fraction != 1.0 )
+ {
+ Vector vecNormal = pTrace->plane.normal;
+ surfacedata_t *pdata = physprops->GetSurfaceData( pTrace->surface.surfaceProps );
+ CPASFilter filter( vecAbsOrigin );
+
+ te->Explosion( filter, -1.0, // don't apply cl_interp delay
+ &vecAbsOrigin,
+ !( contents & MASK_WATER ) ? g_sModelIndexFireball : g_sModelIndexWExplosion,
+ m_DmgRadius * .03,
+ 25,
+ TE_EXPLFLAG_NONE,
+ m_DmgRadius,
+ m_flDamage,
+ &vecNormal,
+ (char) pdata->game.material );
+ }
+ else
+ {
+ CPASFilter filter( vecAbsOrigin );
+ te->Explosion( filter, -1.0, // don't apply cl_interp delay
+ &vecAbsOrigin,
+ !( contents & MASK_WATER ) ? g_sModelIndexFireball : g_sModelIndexWExplosion,
+ m_DmgRadius * .03,
+ 25,
+ TE_EXPLFLAG_NONE,
+ m_DmgRadius,
+ m_flDamage );
+ }
+
+#if !defined( CLIENT_DLL )
+ CSoundEnt::InsertSound ( SOUND_COMBAT, GetAbsOrigin(), BASEGRENADE_EXPLOSION_VOLUME, 3.0 );
+#endif
+
+ // Use the thrower's position as the reported position
+ Vector vecReported = m_hThrower ? m_hThrower->GetAbsOrigin() : vec3_origin;
+
+ CTakeDamageInfo info( this, m_hThrower, GetBlastForce(), GetAbsOrigin(), m_flDamage, bitsDamageType, 0, &vecReported );
+
+ RadiusDamage( info, GetAbsOrigin(), m_DmgRadius, CLASS_NONE, NULL );
+
+ UTIL_DecalTrace( pTrace, "Scorch" );
+
+ EmitSound( "BaseGrenade.Explode" );
+
+ SetThink( &CBaseGrenade::SUB_Remove );
+ SetTouch( NULL );
+ SetSolid( SOLID_NONE );
+
+ AddEffects( EF_NODRAW );
+ SetAbsVelocity( vec3_origin );
+
+#if HL2_EPISODIC
+ // Because the grenade is zipped out of the world instantly, the EXPLOSION sound that it makes for
+ // the AI is also immediately destroyed. For this reason, we now make the grenade entity inert and
+ // throw it away in 1/10th of a second instead of right away. Removing the grenade instantly causes
+ // intermittent bugs with env_microphones who are listening for explosions. They will 'randomly' not
+ // hear explosion sounds when the grenade is removed and the SoundEnt thinks (and removes the sound)
+ // before the env_microphone thinks and hears the sound.
+ SetNextThink( gpGlobals->curtime + 0.1 );
+#else
+ SetNextThink( gpGlobals->curtime );
+#endif//HL2_EPISODIC
+
+#if defined( HL2_DLL )
+ CBasePlayer *pPlayer = ToBasePlayer( m_hThrower.Get() );
+ if ( pPlayer )
+ {
+ gamestats->Event_WeaponHit( pPlayer, true, "weapon_frag", info );
+ }
+#endif
+
+#endif
+}
+
+
+void CBaseGrenade::Smoke( void )
+{
+ Vector vecAbsOrigin = GetAbsOrigin();
+ if ( UTIL_PointContents ( vecAbsOrigin ) & MASK_WATER )
+ {
+ UTIL_Bubbles( vecAbsOrigin - Vector( 64, 64, 64 ), vecAbsOrigin + Vector( 64, 64, 64 ), 100 );
+ }
+ else
+ {
+ CPVSFilter filter( vecAbsOrigin );
+
+ te->Smoke( filter, 0.0,
+ &vecAbsOrigin, g_sModelIndexSmoke,
+ m_DmgRadius * 0.03,
+ 24 );
+ }
+#if !defined( CLIENT_DLL )
+ SetThink ( &CBaseGrenade::SUB_Remove );
+#endif
+ SetNextThink( gpGlobals->curtime );
+}
+
+void CBaseGrenade::Event_Killed( const CTakeDamageInfo &info )
+{
+ Detonate( );
+}
+
+#if !defined( CLIENT_DLL )
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CBaseGrenade::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
+{
+ // Support player pickup
+ if ( useType == USE_TOGGLE )
+ {
+ CBasePlayer *pPlayer = ToBasePlayer( pActivator );
+ if ( pPlayer )
+ {
+ pPlayer->PickupObject( this );
+ return;
+ }
+ }
+
+ // Pass up so we still call any custom Use function
+ BaseClass::Use( pActivator, pCaller, useType, value );
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// Purpose: Timed grenade, this think is called when time runs out.
+//-----------------------------------------------------------------------------
+void CBaseGrenade::DetonateUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
+{
+ SetThink( &CBaseGrenade::Detonate );
+ SetNextThink( gpGlobals->curtime );
+}
+
+void CBaseGrenade::PreDetonate( void )
+{
+#if !defined( CLIENT_DLL )
+ CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin(), 400, 1.5, this );
+#endif
+
+ SetThink( &CBaseGrenade::Detonate );
+ SetNextThink( gpGlobals->curtime + 1.5 );
+}
+
+
+void CBaseGrenade::Detonate( void )
+{
+ trace_t tr;
+ Vector vecSpot;// trace starts here!
+
+ SetThink( NULL );
+
+ vecSpot = GetAbsOrigin() + Vector ( 0 , 0 , 8 );
+ UTIL_TraceLine ( vecSpot, vecSpot + Vector ( 0, 0, -32 ), MASK_SHOT_HULL, this, COLLISION_GROUP_NONE, & tr);
+
+ if( tr.startsolid )
+ {
+ // Since we blindly moved the explosion origin vertically, we may have inadvertently moved the explosion into a solid,
+ // in which case nothing is going to be harmed by the grenade's explosion because all subsequent traces will startsolid.
+ // If this is the case, we do the downward trace again from the actual origin of the grenade. (sjb) 3/8/2007 (for ep2_outland_09)
+ UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, -32), MASK_SHOT_HULL, this, COLLISION_GROUP_NONE, &tr );
+ }
+
+ Explode( &tr, DMG_BLAST );
+
+ if ( GetShakeAmplitude() )
+ {
+ UTIL_ScreenShake( GetAbsOrigin(), GetShakeAmplitude(), 150.0, 1.0, GetShakeRadius(), SHAKE_START );
+ }
+}
+
+
+//
+// Contact grenade, explode when it touches something
+//
+void CBaseGrenade::ExplodeTouch( CBaseEntity *pOther )
+{
+ trace_t tr;
+ Vector vecSpot;// trace starts here!
+
+ Assert( pOther );
+ if ( !pOther->IsSolid() )
+ return;
+
+ Vector velDir = GetAbsVelocity();
+ VectorNormalize( velDir );
+ vecSpot = GetAbsOrigin() - velDir * 32;
+ UTIL_TraceLine( vecSpot, vecSpot + velDir * 64, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );
+
+ Explode( &tr, DMG_BLAST );
+}
+
+
+void CBaseGrenade::DangerSoundThink( void )
+{
+ if (!IsInWorld())
+ {
+ Remove( );
+ return;
+ }
+
+#if !defined( CLIENT_DLL )
+ CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin() + GetAbsVelocity() * 0.5, GetAbsVelocity().Length( ), 0.2, this );
+#endif
+
+ SetNextThink( gpGlobals->curtime + 0.2 );
+
+ if (GetWaterLevel() != 0)
+ {
+ SetAbsVelocity( GetAbsVelocity() * 0.5 );
+ }
+}
+
+
+void CBaseGrenade::BounceTouch( CBaseEntity *pOther )
+{
+ if ( pOther->IsSolidFlagSet(FSOLID_TRIGGER | FSOLID_VOLUME_CONTENTS) )
+ return;
+
+ // don't hit the guy that launched this grenade
+ if ( pOther == GetThrower() )
+ return;
+
+ // only do damage if we're moving fairly fast
+ if ( (pOther->m_takedamage != DAMAGE_NO) && (m_flNextAttack < gpGlobals->curtime && GetAbsVelocity().Length() > 100))
+ {
+ if (m_hThrower)
+ {
+#if !defined( CLIENT_DLL )
+ trace_t tr;
+ tr = CBaseEntity::GetTouchTrace( );
+ ClearMultiDamage( );
+ Vector forward;
+ AngleVectors( GetLocalAngles(), &forward, NULL, NULL );
+ CTakeDamageInfo info( this, m_hThrower, 1, DMG_CLUB );
+ CalculateMeleeDamageForce( &info, GetAbsVelocity(), GetAbsOrigin() );
+ pOther->DispatchTraceAttack( info, forward, &tr );
+ ApplyMultiDamage();
+#endif
+ }
+ m_flNextAttack = gpGlobals->curtime + 1.0; // debounce
+ }
+
+ Vector vecTestVelocity;
+ // m_vecAngVelocity = Vector (300, 300, 300);
+
+ // this is my heuristic for modulating the grenade velocity because grenades dropped purely vertical
+ // or thrown very far tend to slow down too quickly for me to always catch just by testing velocity.
+ // trimming the Z velocity a bit seems to help quite a bit.
+ vecTestVelocity = GetAbsVelocity();
+ vecTestVelocity.z *= 0.45;
+
+ if ( !m_bHasWarnedAI && vecTestVelocity.Length() <= 60 )
+ {
+ // grenade is moving really slow. It's probably very close to where it will ultimately stop moving.
+ // emit the danger sound.
+
+ // register a radius louder than the explosion, so we make sure everyone gets out of the way
+#if !defined( CLIENT_DLL )
+ CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin(), m_flDamage / 0.4, 0.3, this );
+#endif
+ m_bHasWarnedAI = true;
+ }
+
+ if (GetFlags() & FL_ONGROUND)
+ {
+ // add a bit of static friction
+// SetAbsVelocity( GetAbsVelocity() * 0.8 );
+
+ // SetSequence( random->RandomInt( 1, 1 ) ); // FIXME: missing tumble animations
+ }
+ else
+ {
+ // play bounce sound
+ BounceSound();
+ }
+ m_flPlaybackRate = GetAbsVelocity().Length() / 200.0;
+ if (m_flPlaybackRate > 1.0)
+ m_flPlaybackRate = 1;
+ else if (m_flPlaybackRate < 0.5)
+ m_flPlaybackRate = 0;
+
+}
+
+
+
+void CBaseGrenade::SlideTouch( CBaseEntity *pOther )
+{
+ // don't hit the guy that launched this grenade
+ if ( pOther == GetThrower() )
+ return;
+
+ // m_vecAngVelocity = Vector (300, 300, 300);
+
+ if (GetFlags() & FL_ONGROUND)
+ {
+ // add a bit of static friction
+// SetAbsVelocity( GetAbsVelocity() * 0.95 );
+
+ if (GetAbsVelocity().x != 0 || GetAbsVelocity().y != 0)
+ {
+ // maintain sliding sound
+ }
+ }
+ else
+ {
+ BounceSound();
+ }
+}
+
+void CBaseGrenade ::BounceSound( void )
+{
+ // Doesn't need to do anything anymore! Physics makes the sound.
+}
+
+void CBaseGrenade ::TumbleThink( void )
+{
+ if (!IsInWorld())
+ {
+ Remove( );
+ return;
+ }
+
+ StudioFrameAdvance( );
+ SetNextThink( gpGlobals->curtime + 0.1f );
+
+ //
+ // Emit a danger sound one second before exploding.
+ //
+ if (m_flDetonateTime - 1 < gpGlobals->curtime)
+ {
+#if !defined( CLIENT_DLL )
+ CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin() + GetAbsVelocity() * (m_flDetonateTime - gpGlobals->curtime), 400, 0.1, this );
+#endif
+ }
+
+ if (m_flDetonateTime <= gpGlobals->curtime)
+ {
+ SetThink( &CBaseGrenade::Detonate );
+ }
+
+ if (GetWaterLevel() != 0)
+ {
+ SetAbsVelocity( GetAbsVelocity() * 0.5 );
+ m_flPlaybackRate = 0.2;
+ }
+}
+
+void CBaseGrenade::Precache( void )
+{
+ BaseClass::Precache( );
+
+ PrecacheScriptSound( "BaseGrenade.Explode" );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Output : CBaseCombatCharacter
+//-----------------------------------------------------------------------------
+CBaseCombatCharacter *CBaseGrenade::GetThrower( void )
+{
+ CBaseCombatCharacter *pResult = ToBaseCombatCharacter( m_hThrower );
+ if ( !pResult && GetOwnerEntity() != NULL )
+ {
+ pResult = ToBaseCombatCharacter( GetOwnerEntity() );
+ }
+ return pResult;
+}
+
+//-----------------------------------------------------------------------------
+
+void CBaseGrenade::SetThrower( CBaseCombatCharacter *pThrower )
+{
+ m_hThrower = pThrower;
+
+ // if this is the first thrower, set it as the original thrower
+ if ( NULL == m_hOriginalThrower )
+ {
+ m_hOriginalThrower = pThrower;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Destructor
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+CBaseGrenade::~CBaseGrenade(void)
+{
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+CBaseGrenade::CBaseGrenade(void)
+{
+ m_hThrower = NULL;
+ m_hOriginalThrower = NULL;
+ m_bIsLive = false;
+ m_DmgRadius = 100;
+ m_flDetonateTime = 0;
+ m_bHasWarnedAI = false;
+
+ SetSimulatedEveryTick( true );
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+