diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/shared/tf/tf_weaponbase_grenade.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/shared/tf/tf_weaponbase_grenade.cpp')
| -rw-r--r-- | game/shared/tf/tf_weaponbase_grenade.cpp | 377 |
1 files changed, 377 insertions, 0 deletions
diff --git a/game/shared/tf/tf_weaponbase_grenade.cpp b/game/shared/tf/tf_weaponbase_grenade.cpp new file mode 100644 index 0000000..07a1c74 --- /dev/null +++ b/game/shared/tf/tf_weaponbase_grenade.cpp @@ -0,0 +1,377 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: TF Base Grenade. +// +//=============================================================================// +#include "cbase.h" +#include "tf_weaponbase.h" +#include "tf_weaponbase_grenade.h" +#include "tf_gamerules.h" +#include "npcevent.h" +#include "engine/IEngineSound.h" +#include "in_buttons.h" +#include "tf_weaponbase_grenadeproj.h" +#include "eventlist.h" + +// Client specific. +#ifdef CLIENT_DLL +#include "c_tf_player.h" +// Server specific. +#else +#include "tf_player.h" +#include "items.h" +#endif + +#define GRENADE_TIMER 1.5f // seconds + +//============================================================================= +// +// TF Grenade tables. +// + +IMPLEMENT_NETWORKCLASS_ALIASED( TFWeaponBaseGrenade, DT_TFWeaponBaseGrenade ) + +BEGIN_NETWORK_TABLE( CTFWeaponBaseGrenade, DT_TFWeaponBaseGrenade ) +// Client specific. +#ifdef CLIENT_DLL + RecvPropBool( RECVINFO( m_bPrimed ) ), + RecvPropFloat( RECVINFO( m_flThrowTime ) ), + RecvPropBool( RECVINFO( m_bThrow ) ), +// Server specific. +#else + SendPropBool( SENDINFO( m_bPrimed ) ), + SendPropTime( SENDINFO( m_flThrowTime ) ), + SendPropBool( SENDINFO( m_bThrow ) ), +#endif +END_NETWORK_TABLE() + +BEGIN_PREDICTION_DATA( CTFWeaponBaseGrenade ) +#ifdef CLIENT_DLL + DEFINE_PRED_FIELD( m_bPrimed, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), + DEFINE_PRED_FIELD( m_flThrowTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), + DEFINE_PRED_FIELD( m_bThrow, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), +#endif +END_PREDICTION_DATA() + +LINK_ENTITY_TO_CLASS( tf_weaponbase_grenade, CTFWeaponBaseGrenade ); + +//============================================================================= +// +// TF Grenade functions. +// + +CTFWeaponBaseGrenade::CTFWeaponBaseGrenade() +{ +} + +//----------------------------------------------------------------------------- +// Purpose: Constructor. +//----------------------------------------------------------------------------- +void CTFWeaponBaseGrenade::Spawn( void ) +{ + BaseClass::Spawn(); + + SetViewModelIndex( 1 ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFWeaponBaseGrenade::Precache() +{ + BaseClass::Precache(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CTFWeaponBaseGrenade::IsPrimed( void ) +{ + return m_bPrimed; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CTFWeaponBaseGrenade::Deploy( void ) +{ + if ( BaseClass::Deploy() ) + { + Prime(); + return true; + } + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFWeaponBaseGrenade::Prime() +{ + CTFWeaponInfo weaponInfo = GetTFWpnData(); + m_flThrowTime = gpGlobals->curtime + weaponInfo.m_flPrimerTime; + m_bPrimed = true; + +#ifndef CLIENT_DLL + if ( GetWeaponID() != TF_WEAPON_GRENADE_SMOKE_BOMB ) + { + // Get the player owning the weapon. + CTFPlayer *pPlayer = ToTFPlayer( GetPlayerOwner() ); + if ( !pPlayer ) + return; + + pPlayer->RemoveInvisibility(); + } +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFWeaponBaseGrenade::Throw() +{ + if ( !m_bPrimed ) + return; + + m_bPrimed = false; + m_bThrow = false; + + // Get the owning player. + CTFPlayer *pPlayer = ToTFPlayer( GetOwner() ); + if ( !pPlayer ) + return; + +#ifdef GAME_DLL + // Calculate the time remaining. + float flTime = m_flThrowTime - gpGlobals->curtime; + bool bExplodingInHand = ( flTime <= 0.0f ); + + // Players who are dying may not have their death state set, so check that too + bool bExplodingOnDeath = ( !pPlayer->IsAlive() || pPlayer->StateGet() == TF_STATE_DYING ); + + Vector vecSrc, vecThrow; + vecSrc = pPlayer->Weapon_ShootPosition(); + + if ( bExplodingInHand || bExplodingOnDeath ) + { + vecThrow = vec3_origin; + } + else + { + // Determine the throw angle and velocity. + QAngle angThrow = pPlayer->LocalEyeAngles(); + if ( angThrow.x < 90.0f ) + { + angThrow.x = -10.0f + angThrow.x * ( ( 90.0f + 10.0f ) / 90.0f ); + } + else + { + angThrow.x = 360.0f - angThrow.x; + angThrow.x = -10.0f + angThrow.x * -( ( 90.0f - 10.0f ) / 90.0f ); + } + + // Adjust for the lowering of the spawn point + angThrow.x -= 10; + + float flVelocity = ( 90.0f - angThrow.x ) * 8.0f; + if ( flVelocity > 950.0f ) + { + flVelocity = 950.0f; + } + + Vector vForward, vRight, vUp; + AngleVectors( angThrow, &vForward, &vRight, &vUp ); + + // Throw from the player's left hand position. + vecSrc += vForward * 16.0f + vRight * -8.0f + vUp * -20.0f; + + vecThrow = vForward * flVelocity; + } + +#if 0 + // Debug!!! + char str[256]; + Q_snprintf( str, sizeof( str ),"GrenadeTime = %f\n", flTime ); + NDebugOverlay::ScreenText( 0.5f, 0.38f, str, 255, 255, 255, 255, 2.0f ); +#endif + + QAngle vecAngles = RandomAngle( 0, 360 ); + + // Create the projectile and send in the time remaining. + if ( !bExplodingInHand ) + { + EmitGrenade( vecSrc, vecAngles, vecThrow, AngularImpulse( 600, random->RandomInt( -1200, 1200 ), 0 ), pPlayer, flTime ); + } + else + { + // We're holding onto an exploding grenade + CTFWeaponBaseGrenadeProj *pGrenade = EmitGrenade( vecSrc, vecAngles, vecThrow, AngularImpulse( 600, random->RandomInt( -1200, 1200 ), 0 ), pPlayer, 0.0 ); + if ( pGrenade ) + { + pGrenade->Detonate(); + } + } + + // The grenade is about to be destroyed, so it won't be able to holster. + // Handle the viewmodel hiding for it. + if ( bExplodingInHand || bExplodingOnDeath ) + { + SendWeaponAnim( ACT_VM_IDLE ); + CBaseViewModel *vm = pPlayer->GetViewModel( 1 ); + if ( vm ) + { + vm->AddEffects( EF_NODRAW ); + } + } +#endif + + // Reset the throw time + m_flThrowTime = 0.0f; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CTFWeaponBaseGrenade::ShouldDetonate( void ) +{ + return ( m_flThrowTime != 0.0f ) && ( m_flThrowTime < gpGlobals->curtime ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFWeaponBaseGrenade::ItemPostFrame() +{ + CTFPlayer *pPlayer = ToTFPlayer( GetPlayerOwner() ); + if ( !pPlayer ) + return; + + if ( m_bPrimed ) + { + // Is our timer up? If so, blow up immediately + if ( ShouldDetonate() ) + { + Throw(); + return; + } + + if ( !m_bThrow && !( pPlayer->m_nButtons & IN_GRENADE1 || pPlayer->m_nButtons & IN_GRENADE2 ) ) + { + // Start throwing + pPlayer->DoAnimationEvent( PLAYERANIMEVENT_ATTACK_GRENADE ); + m_bThrow = true; + } + } + + if ( m_bThrow ) + { + if ( GetActivity() != ACT_VM_PRIMARYATTACK ) + { + // Start the throw animation + if ( !SendWeaponAnim( ACT_VM_PRIMARYATTACK ) ) + { + Throw(); + } + } + else if ( HasWeaponIdleTimeElapsed() ) + { + // The Throw call here exists solely to catch the lone case of thirdperson where the + // viewmodel isn't being drawn, and hence the anim event doesn't trigger and force a throw. + // In all other cases, it'll do nothing because the grenade has already been thrown. + Throw(); + } + return; + } + + if ( !m_bPrimed && !m_bThrow ) + { + // Once we've finished being holstered, we'll be hidden. When that happens, + // tell our player that we're all done with the grenade throw. + if ( IsEffectActive(EF_NODRAW) ) + { + pPlayer->FinishThrowGrenade(); + return; + } + + // We've been thrown. Go away. + if ( HasWeaponIdleTimeElapsed() ) + { + Holster(); + } + } + + // Go straight to idle anim when deploy is done + if ( m_flTimeWeaponIdle <= gpGlobals->curtime ) + { + SendWeaponAnim( ACT_VM_IDLE ); + } +} + +bool CTFWeaponBaseGrenade::ShouldLowerMainWeapon( void ) +{ + return GetTFWpnData().m_bLowerWeapon; +} + +//============================================================================= +// +// Client specific functions. +// +#ifdef CLIENT_DLL + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CTFWeaponBaseGrenade::ShouldDraw( void ) +{ + if ( !BaseClass::ShouldDraw() ) + { + // Grenades need to be visible whenever they're being primed & thrown + if ( !m_bPrimed ) + return false; + + // Don't draw primed grenades for local player in first person players + if ( !(ToPlayer(GetOwner())->ShouldDrawThisPlayer()) ) + return false; + } + + return true; +} + +//============================================================================= +// +// Server specific functions. +// +#else + +BEGIN_DATADESC( CTFWeaponBaseGrenade ) +END_DATADESC() + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFWeaponBaseGrenade::HandleAnimEvent( animevent_t *pEvent ) +{ + if ( (pEvent->type & AE_TYPE_NEWEVENTSYSTEM) ) + { + if ( pEvent->event == AE_WPN_PRIMARYATTACK ) + { + Throw(); + return; + } + } + + BaseClass::HandleAnimEvent( pEvent ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CTFWeaponBaseGrenadeProj *CTFWeaponBaseGrenade::EmitGrenade( Vector vecSrc, QAngle vecAngles, Vector vecVel, AngularImpulse angImpulse, CBasePlayer *pPlayer, float flTime, int iFlags ) +{ + Assert( 0 && "CBaseCSGrenade::EmitGrenade should not be called. Make sure to implement this in your subclass!\n" ); + return NULL; +} + +#endif + |