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.
619 lines
15 KiB
619 lines
15 KiB
//========= 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
|
|
|