diff options
Diffstat (limited to 'game/shared/tf/tf_weapon_flaregun.cpp')
| -rw-r--r-- | game/shared/tf/tf_weapon_flaregun.cpp | 619 |
1 files changed, 619 insertions, 0 deletions
diff --git a/game/shared/tf/tf_weapon_flaregun.cpp b/game/shared/tf/tf_weapon_flaregun.cpp new file mode 100644 index 0000000..b5a13fc --- /dev/null +++ b/game/shared/tf/tf_weapon_flaregun.cpp @@ -0,0 +1,619 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// +//============================================================================= +#include "cbase.h" +#include "tf_weapon_flaregun.h" +#include "tf_fx_shared.h" +#include "in_buttons.h" + +// Client specific. +#ifdef CLIENT_DLL +#include "c_tf_player.h" +#include "soundenvelope.h" +// Server specific. +#else +#include "tf_gamestats.h" +#include "tf_player.h" +#endif + +//============================================================================= +// +// Weapon Flare Gun tables. +// +IMPLEMENT_NETWORKCLASS_ALIASED( TFFlareGun, DT_WeaponFlareGun ) + +BEGIN_NETWORK_TABLE( CTFFlareGun, DT_WeaponFlareGun ) +#ifdef CLIENT_DLL + RecvPropFloat( RECVINFO( m_flChargeBeginTime ) ), +#else + SendPropFloat( SENDINFO( m_flChargeBeginTime ) ), +#endif +END_NETWORK_TABLE() + +BEGIN_PREDICTION_DATA( CTFFlareGun ) +END_PREDICTION_DATA() + +LINK_ENTITY_TO_CLASS( tf_weapon_flaregun, CTFFlareGun ); +PRECACHE_WEAPON_REGISTER( tf_weapon_flaregun ); + +// Server specific. +#ifndef CLIENT_DLL +BEGIN_DATADESC( CTFFlareGun ) +END_DATADESC() +#endif + + +//============================ +IMPLEMENT_NETWORKCLASS_ALIASED( TFFlareGun_Revenge, DT_WeaponFlareGun_Revenge ) + +BEGIN_NETWORK_TABLE( CTFFlareGun_Revenge, DT_WeaponFlareGun_Revenge ) +#ifdef CLIENT_DLL +RecvPropFloat( RECVINFO( m_fLastExtinguishTime ) ), +#else +SendPropFloat( SENDINFO( m_fLastExtinguishTime ) ), +#endif +END_NETWORK_TABLE() + +BEGIN_PREDICTION_DATA( CTFFlareGun_Revenge ) +END_PREDICTION_DATA() + +LINK_ENTITY_TO_CLASS( tf_weapon_flaregun_revenge, CTFFlareGun_Revenge ); +PRECACHE_WEAPON_REGISTER( tf_weapon_flaregun_revenge ); + + +//============================================================================= +// +// Weapon Flare Gun functions. +// + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CTFFlareGun::CTFFlareGun() +{ + m_bEffectsThinking = false; + m_flLastDenySoundTime = 0.0f; + +#ifdef CLIENT_DLL + m_bReadyToFire = false; +#endif + + StopCharge(); +} + +CTFFlareGun::~CTFFlareGun() +{ + DestroySounds(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFFlareGun::Precache() +{ + BaseClass::Precache(); + + PrecacheParticleSystem( "stickybombtrail_blue" ); + PrecacheParticleSystem( "stickybombtrail_red" ); + PrecacheParticleSystem( "critical_grenade_blue" ); + PrecacheParticleSystem( "critical_grenade_red" ); +} + +void CTFFlareGun::DestroySounds( void ) +{ + StopCharge(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFFlareGun::PrimaryAttack( void ) +{ + // Get the player owning the weapon. + CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() ); + if ( !pOwner ) + return; + + if ( m_flChargeBeginTime > 0.0f ) + return; + + // Don't attack if we're underwater + if ( pOwner->GetWaterLevel() != WL_Eyes ) + { + BaseClass::PrimaryAttack(); + } + else + { + if ( gpGlobals->curtime > m_flLastDenySoundTime ) + { + WeaponSound( SPECIAL2 ); + m_flLastDenySoundTime = gpGlobals->curtime + 1.0f; + } + } + +#ifdef CLIENT_DLL + m_bReadyToFire = false; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: Detonate flare +//----------------------------------------------------------------------------- +void CTFFlareGun::SecondaryAttack( void ) +{ + if ( GetFlareGunType() != FLAREGUN_DETONATE ) + return; + + if ( !CanAttack() ) + return; + + CTFPlayer *pPlayer = ToTFPlayer( GetOwner() ); + if ( !pPlayer ) + return; + +#ifdef GAME_DLL + if ( m_iFlareCount ) + { + int iCount = m_Flares.Count(); + for ( int i = 0; i < iCount; i++ ) + { + CTFProjectile_Flare *pTemp = m_Flares[i]; + if ( pTemp ) + { + pTemp->Detonate(); + } + } + } +#endif // GAME_DLL +} + +#ifdef GAME_DLL +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFFlareGun::AddFlare( CTFProjectile_Flare *pFlare ) +{ + FlareHandle hHandle; + hHandle = pFlare; + m_Flares.AddToTail( hHandle ); + + m_iFlareCount = m_Flares.Count(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFFlareGun::DeathNotice( CBaseEntity *pVictim ) +{ + Assert( dynamic_cast<CTFProjectile_Flare*>( pVictim ) ); + + FlareHandle hHandle; + hHandle = (CTFProjectile_Flare*)pVictim; + m_Flares.FindAndRemove( hHandle ); + + m_iFlareCount = m_Flares.Count(); +} +#endif + +bool CTFFlareGun::Holster( CBaseCombatWeapon *pSwitchingTo ) +{ +#ifdef CLIENT_DLL + m_bEffectsThinking = false; + StopCharge(); + + m_bReadyToFire = false; +#endif + + return BaseClass::Holster( pSwitchingTo ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CTFFlareGun::Deploy( void ) +{ +#ifdef CLIENT_DLL + m_bEffectsThinking = true; + SetContextThink( &CTFFlareGun::ClientEffectsThink, gpGlobals->curtime + 0.25f, "EFFECTS_THINK" ); + + m_bReadyToFire = false; +#endif + + return BaseClass::Deploy(); +} + +void CTFFlareGun::WeaponReset( void ) +{ + BaseClass::WeaponReset(); + +#if defined( CLIENT_DLL ) + StopCharge(); +#endif +} + +void CTFFlareGun::ItemPostFrame( void ) +{ + BaseClass::ItemPostFrame(); + + if ( m_flChargeBeginTime > 0.0f ) + { + CTFPlayer *pPlayer = ToTFPlayer( GetPlayerOwner() ); + if ( !pPlayer ) + return; + + // If we're not holding down the attack button + if ( !(pPlayer->m_nButtons & IN_ATTACK2) ) + { + StopCharge(); + } + else + { + ChargePostFrame(); + } + } + +#ifdef CLIENT_DLL + if ( !m_bEffectsThinking ) + { + m_bEffectsThinking = true; + SetContextThink( &CTFFlareGun::ClientEffectsThink, gpGlobals->curtime + 0.25f, "EFFECTS_THINK" ); + } +#endif +} + +#ifdef CLIENT_DLL +void CTFFlareGun::DispatchMuzzleFlash( const char* effectName, C_BaseEntity* pAttachEnt ) +{ + DispatchParticleEffect( effectName, PATTACH_POINT_FOLLOW, pAttachEnt, "muzzle", GetParticleColor( 1 ), GetParticleColor( 2 ) ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFFlareGun::ClientEffectsThink( void ) +{ + CTFPlayer *pPlayer = GetTFPlayerOwner(); + if ( !pPlayer ) + return; + + if ( !pPlayer->IsLocalPlayer() ) + return; + + if ( !pPlayer->GetViewModel() ) + return; + + if ( !m_bEffectsThinking ) + return; + + if ( !GetOwner() || GetOwner()->GetActiveWeapon() != this ) + { + m_bEffectsThinking = false; + } + else + { + SetContextThink( &CTFFlareGun::ClientEffectsThink, gpGlobals->curtime + 0.25f, "EFFECTS_THINK" ); + } + + if ( GetFlareGunType() == FLAREGUN_GRORDBORT && m_flNextPrimaryAttack <= gpGlobals->curtime ) + { + ParticleProp()->Init( this ); + CNewParticleEffect* pEffect = ParticleProp()->Create( "drg_bison_idle", PATTACH_POINT_FOLLOW, "muzzle" ); + if ( pEffect ) + { + pEffect->SetControlPoint( CUSTOM_COLOR_CP1, GetParticleColor( 1 ) ); + pEffect->SetControlPoint( CUSTOM_COLOR_CP2, GetParticleColor( 2 ) ); + } + + ParticleProp()->Create( "drg_manmelter_idle", PATTACH_POINT_FOLLOW, "muzzle" ); + + if ( !m_bReadyToFire ) + { + m_bReadyToFire = true; + + EmitSound( "Weapon_SniperRailgun.NonScoped" ); + } + } +} + +void CTFFlareGun::StartChargeEffects() +{ + CTFPlayer *pPlayer = ToTFPlayer( GetPlayerOwner() ); + if ( pPlayer ) + { + DispatchParticleEffect( GetChargeEffect(), PATTACH_POINT_FOLLOW, GetAppropriateWorldOrViewModel(), "muzzle", GetParticleColor( 1 ), GetParticleColor( 2 ) ); + } +} + +void CTFFlareGun::StopChargeEffects() +{ + CTFPlayer *pPlayer = ToTFPlayer( GetPlayerOwner() ); + if ( pPlayer ) + { + GetAppropriateWorldOrViewModel()->ParticleProp()->StopParticlesNamed( GetChargeEffect(), false ); + } +} + +#endif + +void CTFFlareGun::StartCharge( void ) +{ + StartChargeStartTime(); + +#ifdef CLIENT_DLL + if ( !m_pChargeLoop ) + { + CLocalPlayerFilter filter; + CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); + m_pChargeLoop = controller.SoundCreate( filter, entindex(), GetShootSound( WPN_DOUBLE ) ); + controller.Play( m_pChargeLoop, 1.0, 100 ); + } + + StartChargeEffects(); +#endif +} + +void CTFFlareGun::StopCharge( void ) +{ + m_flChargeBeginTime = 0.0f; + +#ifdef CLIENT_DLL + if ( m_pChargeLoop ) + { + CSoundEnvelopeController::GetController().SoundDestroy( m_pChargeLoop ); + } + + m_pChargeLoop = NULL; + + StopChargeEffects(); +#endif +} + + +CTFFlareGun_Revenge::CTFFlareGun_Revenge() +{ + m_fLastExtinguishTime = 0.0f; + +#ifdef CLIENT_DLL + m_nOldRevengeCrits = 0; +#endif +} + +void CTFFlareGun_Revenge::Precache() +{ + BaseClass::Precache(); + + PrecacheParticleSystem( "drg_manmelter_vacuum" ); + PrecacheParticleSystem( "drg_manmelter_vacuum_flames" ); + PrecacheParticleSystem( "drg_manmelter_muzzleflash" ); +} + +int CTFFlareGun_Revenge::GetCustomDamageType() const +{ + CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() ); + if ( pOwner ) + { + int iRevengeCrits = pOwner->m_Shared.GetRevengeCrits(); + return iRevengeCrits > 0 ? TF_DMG_CUSTOM_SHOTGUN_REVENGE_CRIT : TF_DMG_CUSTOM_NONE; + } + return TF_DMG_CUSTOM_NONE; +} + +bool CTFFlareGun_Revenge::Holster( CBaseCombatWeapon *pSwitchingTo ) +{ +#ifdef GAME_DLL + CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() ); + if ( pOwner && pOwner->m_Shared.GetRevengeCrits() ) + { + pOwner->m_Shared.RemoveCond( TF_COND_CRITBOOSTED ); + } +#endif + + StopCharge(); + + return BaseClass::Holster( pSwitchingTo ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CTFFlareGun_Revenge::Deploy( void ) +{ +#ifdef GAME_DLL + CTFPlayer *pOwner = ToTFPlayer( GetOwner() ); + if ( pOwner && pOwner->m_Shared.GetRevengeCrits() ) + { + pOwner->m_Shared.AddCond( TF_COND_CRITBOOSTED ); + } +#endif + + StopCharge(); + + return BaseClass::Deploy(); +} + +#ifdef GAME_DLL +//----------------------------------------------------------------------------- +// Purpose: Reset revenge crits when the flaregun is changed +//----------------------------------------------------------------------------- +void CTFFlareGun_Revenge::Detach( void ) +{ + CTFPlayer *pPlayer = GetTFPlayerOwner(); + if ( pPlayer ) + { + pPlayer->m_Shared.SetRevengeCrits( 0 ); + pPlayer->m_Shared.RemoveCond( TF_COND_CRITBOOSTED ); + } + + BaseClass::Detach(); +} +#endif + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int CTFFlareGun_Revenge::GetCount( void ) +{ + CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() ); + if ( pOwner ) + { + return pOwner->m_Shared.GetRevengeCrits(); + } + + return 0; +} + +void CTFFlareGun_Revenge::PrimaryAttack() +{ + if ( !CanAttack() ) + return; + + BaseClass::PrimaryAttack(); + + // Lower the reveng crit count + CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() ); + if ( pOwner ) + { + int iNewRevengeCrits = MAX( pOwner->m_Shared.GetRevengeCrits() - 1, 0 ); + pOwner->m_Shared.SetRevengeCrits( iNewRevengeCrits ); + } +} + +void CTFFlareGun_Revenge::SecondaryAttack( void ) +{ + if ( m_flNextSecondaryAttack > gpGlobals->curtime ) + { + return; + } + + CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() ); + if ( !pOwner ) + return; + + if ( GetChargeBeginTime() == 0.0f ) + { + StartCharge(); + +#ifdef GAME_DLL + //SendWeaponAnim( ACT_VM_PULLBACK ); +#endif + } + + m_flNextSecondaryAttack = gpGlobals->curtime + 0.5f; +} + +void CTFFlareGun_Revenge::ChargePostFrame( void ) +{ + BaseClass::ChargePostFrame(); + + if ( gpGlobals->curtime > m_fLastExtinguishTime + 0.5f ) + { + CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() ); + if ( pOwner ) + { + // Extinguish friends + Vector vecEye = pOwner->EyePosition(); + Vector vecForward, vecRight, vecUp; + AngleVectors( pOwner->EyeAngles(), &vecForward, NULL, NULL ); + + const Vector vHull = Vector( 16.0f, 16.0f, 16.0f ); + + trace_t tr; + UTIL_TraceHull( vecEye, vecEye + vecForward * 256.0f, -vHull, vHull, MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); + + CTFPlayer *pTarget = ToTFPlayer( tr.m_pEnt ); + if ( pTarget ) + { +#ifdef GAME_DLL + // Get the player that ignited them before we extinguish + CTFPlayer *pBurner = pTarget->m_Shared.GetOriginalBurnAttacker(); +#endif + + if ( ExtinguishPlayerInternal( pTarget, pOwner ) ) + { + m_fLastExtinguishTime = gpGlobals->curtime; + +#ifdef GAME_DLL + // Make sure the team isn't burning themselves to earn crits + if ( pBurner && pBurner->GetTeamNumber() != pOwner->GetTeamNumber() ) + { + // Grant revenge crits + pOwner->m_Shared.SetRevengeCrits( pOwner->m_Shared.GetRevengeCrits() + 1 ); + + // Return health to the Pyro. + int iRestoreHealthOnExtinguish = 0; + CALL_ATTRIB_HOOK_INT( iRestoreHealthOnExtinguish, extinguish_restores_health ); + if ( iRestoreHealthOnExtinguish > 0 && pOwner->TakeHealth( 20, DMG_GENERIC ) > 0 ) + { + IGameEvent *healevent = gameeventmanager->CreateEvent( "player_healonhit" ); + if ( healevent ) + { + healevent->SetInt( "amount", iRestoreHealthOnExtinguish ); + healevent->SetInt( "entindex", pOwner->entindex() ); + item_definition_index_t healingItemDef = INVALID_ITEM_DEF_INDEX; + if ( GetAttributeContainer() && GetAttributeContainer()->GetItem() ) + { + healingItemDef = GetAttributeContainer()->GetItem()->GetItemDefIndex(); + } + healevent->SetInt( "weapon_def_index", healingItemDef ); + + gameeventmanager->FireEvent( healevent ); + } + } + } +#endif + } + } + } + } +} + +#ifdef GAME_DLL +extern void ExtinguishPlayer( CEconEntity *pExtinguisher, CTFPlayer *pOwner, CTFPlayer *pTarget, const char *pExtinguisherName ); +#endif // GAME_DLL + +bool CTFFlareGun_Revenge::ExtinguishPlayerInternal( CTFPlayer *pTarget, CTFPlayer *pOwner ) +{ + if ( pTarget->GetTeamNumber() == pOwner->GetTeamNumber() ) + { + if ( pTarget->m_Shared.InCond( TF_COND_BURNING ) ) + { +#ifdef GAME_DLL + ExtinguishPlayer( this, pOwner, pTarget, GetName() ); +#endif // GAME_DLL + + return true; + } + } + + return false; +} + +#ifdef CLIENT_DLL +void CTFFlareGun_Revenge::OnDataChanged( DataUpdateType_t type ) +{ + BaseClass::OnDataChanged( type ); + + CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() ); + if ( pOwner ) + { + if ( m_nOldRevengeCrits < pOwner->m_Shared.GetRevengeCrits() ) + { + DoAbsorbEffect(); + } + + m_nOldRevengeCrits = pOwner->m_Shared.GetRevengeCrits(); + } +} + +void CTFFlareGun_Revenge::DoAbsorbEffect( void ) +{ + WeaponSound( SPECIAL1 ); + + CTFPlayer *pPlayer = ToTFPlayer( GetPlayerOwner() ); + if ( pPlayer ) + { + DispatchParticleEffect( "drg_manmelter_vacuum_flames", PATTACH_POINT_FOLLOW, GetAppropriateWorldOrViewModel(), "muzzle", GetParticleColor( 1 ), GetParticleColor( 2 ) ); + } +} +#endif |