mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-12 11:49:09 +00:00
1
This commit is contained in:
@@ -0,0 +1,643 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "cbase.h"
|
||||
#include "tf_weapon_pipebomblauncher.h"
|
||||
#include "tf_fx_shared.h"
|
||||
#include "tf_weapon_grenade_pipebomb.h"
|
||||
#include "in_buttons.h"
|
||||
#include "datacache/imdlcache.h"
|
||||
#include "tf_gamerules.h"
|
||||
|
||||
// Client specific.
|
||||
#ifdef CLIENT_DLL
|
||||
#include "c_tf_player.h"
|
||||
#include <vgui_controls/Panel.h>
|
||||
#include <vgui/ISurface.h>
|
||||
#include "prediction.h"
|
||||
#include "c_tf_gamestats.h"
|
||||
// Server specific.
|
||||
#else
|
||||
#include "tf_player.h"
|
||||
#include "tf_gamestats.h"
|
||||
#endif
|
||||
|
||||
#define TF_PIPEBOMB_HIGHLIGHT 1
|
||||
#define TF_PIPEBOMB_DETONATE 2
|
||||
|
||||
#define TF_WEAPON_PIPEBOMBD_MODEL "models/weapons/w_models/w_stickybomb_d.mdl"
|
||||
|
||||
#define TF_WEAPON_PIPEBOMB_LAUNCHER_CHARGE_SOUND "Weapon_StickyBombLauncher.ChargeUp"
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Weapon Pipebomb Launcher tables.
|
||||
//
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( TFPipebombLauncher, DT_WeaponPipebombLauncher )
|
||||
|
||||
BEGIN_NETWORK_TABLE_NOBASE( CTFPipebombLauncher, DT_PipebombLauncherLocalData )
|
||||
#ifdef CLIENT_DLL
|
||||
RecvPropInt( RECVINFO( m_iPipebombCount ) ),
|
||||
RecvPropFloat( RECVINFO( m_flChargeBeginTime ) ),
|
||||
#else
|
||||
SendPropInt( SENDINFO( m_iPipebombCount ), 5, SPROP_UNSIGNED ),
|
||||
SendPropFloat( SENDINFO( m_flChargeBeginTime ) ),
|
||||
#endif
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
|
||||
BEGIN_NETWORK_TABLE( CTFPipebombLauncher, DT_WeaponPipebombLauncher )
|
||||
#ifdef CLIENT_DLL
|
||||
RecvPropDataTable( "PipebombLauncherLocalData", 0, 0, &REFERENCE_RECV_TABLE( DT_PipebombLauncherLocalData ) ),
|
||||
#else
|
||||
SendPropDataTable( "PipebombLauncherLocalData", 0, &REFERENCE_SEND_TABLE( DT_PipebombLauncherLocalData ), SendProxy_SendLocalWeaponDataTable ),
|
||||
#endif
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
BEGIN_PREDICTION_DATA( CTFPipebombLauncher )
|
||||
DEFINE_FIELD( m_flChargeBeginTime, FIELD_FLOAT )
|
||||
END_PREDICTION_DATA()
|
||||
#endif
|
||||
|
||||
LINK_ENTITY_TO_CLASS( tf_weapon_pipebomblauncher, CTFPipebombLauncher );
|
||||
PRECACHE_WEAPON_REGISTER( tf_weapon_pipebomblauncher );
|
||||
|
||||
// Server specific.
|
||||
#ifndef CLIENT_DLL
|
||||
BEGIN_DATADESC( CTFPipebombLauncher )
|
||||
END_DATADESC()
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Weapon Pipebomb Launcher functions.
|
||||
//
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : -
|
||||
//-----------------------------------------------------------------------------
|
||||
CTFPipebombLauncher::CTFPipebombLauncher()
|
||||
{
|
||||
m_bReloadsSingly = true;
|
||||
m_flLastDenySoundTime = 0.0f;
|
||||
m_bNoAutoRelease = false;
|
||||
m_bWantsToShoot = false;
|
||||
#ifdef CLIENT_DLL
|
||||
m_flNextBombCheckTime = 0;
|
||||
m_bBombThinking = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : -
|
||||
//-----------------------------------------------------------------------------
|
||||
CTFPipebombLauncher::~CTFPipebombLauncher()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFPipebombLauncher::Spawn( void )
|
||||
{
|
||||
m_iAltFireHint = HINT_ALTFIRE_PIPEBOMBLAUNCHER;
|
||||
BaseClass::Spawn();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Reset the charge when we holster
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CTFPipebombLauncher::Holster( CBaseCombatWeapon *pSwitchingTo )
|
||||
{
|
||||
m_flChargeBeginTime = 0;
|
||||
|
||||
return BaseClass::Holster( pSwitchingTo );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Reset the charge when we deploy
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CTFPipebombLauncher::Deploy( void )
|
||||
{
|
||||
m_flChargeBeginTime = 0;
|
||||
|
||||
return BaseClass::Deploy();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFPipebombLauncher::WeaponReset( void )
|
||||
{
|
||||
BaseClass::WeaponReset();
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
DetonateRemotePipebombs( true );
|
||||
#endif
|
||||
|
||||
m_flChargeBeginTime = 0.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFPipebombLauncher::ItemPostFrame( void )
|
||||
{
|
||||
BaseClass::ItemPostFrame();
|
||||
|
||||
if ( m_flChargeBeginTime > 0 )
|
||||
{
|
||||
CTFPlayer *pPlayer = ToTFPlayer( GetPlayerOwner() );
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
// If we're not holding down the attack button, launch our grenade
|
||||
if ( m_iClip1 > 0 && !(pPlayer->m_nButtons & IN_ATTACK) && (pPlayer->m_afButtonReleased & IN_ATTACK) )
|
||||
{
|
||||
LaunchGrenade();
|
||||
}
|
||||
else if ( !m_bNoAutoRelease )
|
||||
{
|
||||
float flTotalChargeTime = gpGlobals->curtime - m_flChargeBeginTime;
|
||||
if ( flTotalChargeTime >= GetChargeForceReleaseTime() )
|
||||
{
|
||||
ForceLaunchGrenade();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFPipebombLauncher::PrimaryAttack( void )
|
||||
{
|
||||
// Check for ammunition.
|
||||
if ( m_iClip1 <= 0 && m_iClip1 != -1 )
|
||||
return;
|
||||
|
||||
// Are we capable of firing again?
|
||||
if ( m_flNextPrimaryAttack > gpGlobals->curtime )
|
||||
return;
|
||||
|
||||
if ( !CanAttack() )
|
||||
{
|
||||
m_flChargeBeginTime = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_flChargeBeginTime <= 0 )
|
||||
{
|
||||
// Set the weapon mode.
|
||||
m_iWeaponMode = TF_WEAPON_PRIMARY_MODE;
|
||||
|
||||
// save that we had the attack button down
|
||||
m_flChargeBeginTime = gpGlobals->curtime;
|
||||
|
||||
SendWeaponAnim( ACT_VM_PULLBACK );
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
EmitSound( TF_WEAPON_PIPEBOMB_LAUNCHER_CHARGE_SOUND );
|
||||
#endif // CLIENT_DLL
|
||||
}
|
||||
else
|
||||
{
|
||||
float flTotalChargeTime = gpGlobals->curtime - m_flChargeBeginTime;
|
||||
|
||||
if ( flTotalChargeTime >= GetChargeMaxTime() )
|
||||
{
|
||||
LaunchGrenade();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
if ( GetDetonateMode() == TF_DETONATE_MODE_DOT && !m_bBombThinking )
|
||||
{
|
||||
m_bBombThinking = true;
|
||||
SetContextThink( &CTFPipebombLauncher::BombHighlightThink, gpGlobals->curtime + 0.1f, "BOMB_HIGHLIGHT_THINK" );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifdef CLIENT_DLL
|
||||
void CTFPipebombLauncher::BombHighlightThink( void )
|
||||
{
|
||||
ModifyPipebombsInView( TF_PIPEBOMB_HIGHLIGHT );
|
||||
if ( GetOwner() )
|
||||
{
|
||||
SetContextThink( &CTFPipebombLauncher::BombHighlightThink, gpGlobals->curtime + 0.1f, "BOMB_HIGHLIGHT_THINK" );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFPipebombLauncher::WeaponIdle( void )
|
||||
{
|
||||
CTFPlayer *pPlayer = ToTFPlayer( GetPlayerOwner() );
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
if ( m_flChargeBeginTime > 0 && m_iClip1 > 0 && (pPlayer->m_afButtonReleased & IN_ATTACK) )
|
||||
{
|
||||
if ( m_iClip1 > 0 )
|
||||
{
|
||||
m_bWantsToShoot = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_bWantsToShoot )
|
||||
{
|
||||
LaunchGrenade();
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseClass::WeaponIdle();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFPipebombLauncher::LaunchGrenade( void )
|
||||
{
|
||||
// Get the player owning the weapon.
|
||||
CTFPlayer *pPlayer = ToTFPlayer( GetPlayerOwner() );
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
m_bWantsToShoot = false;
|
||||
|
||||
CalcIsAttackCritical();
|
||||
|
||||
SendWeaponAnim( ACT_VM_PRIMARYATTACK );
|
||||
|
||||
pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
||||
pPlayer->DoAnimationEvent( PLAYERANIMEVENT_ATTACK_PRIMARY );
|
||||
|
||||
CTFGrenadePipebombProjectile *pProjectile = static_cast<CTFGrenadePipebombProjectile*>( FireProjectile( pPlayer ) );
|
||||
if ( pProjectile )
|
||||
{
|
||||
// Save the charge time to scale the detonation timer.
|
||||
pProjectile->SetChargeTime( gpGlobals->curtime - m_flChargeBeginTime );
|
||||
|
||||
#ifdef GAME_DLL
|
||||
if ( GetDetonateMode() == TF_DETONATE_MODE_AIR )
|
||||
{
|
||||
pProjectile->m_bWallShatter = true;
|
||||
}
|
||||
else if ( GetDetonateMode() == TF_DETONATE_MODE_DOT )
|
||||
{
|
||||
pProjectile->m_bDefensiveBomb = true;
|
||||
pProjectile->SetModel( TF_WEAPON_PIPEBOMBD_MODEL );
|
||||
}
|
||||
|
||||
float flChargeDmg = 1.0f;
|
||||
CALL_ATTRIB_HOOK_FLOAT( flChargeDmg, stickybomb_charge_damage_increase );
|
||||
if ( flChargeDmg != 1.0f )
|
||||
{
|
||||
float flDamage = pProjectile->GetDamage();
|
||||
flDamage += flDamage * ( flChargeDmg - 1.0f ) * GetCurrentCharge();
|
||||
pProjectile->SetDamage( flDamage );
|
||||
}
|
||||
#endif // GAME_DLL
|
||||
}
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
C_CTF_GameStats.Event_PlayerFiredWeapon( pPlayer, IsCurrentAttackACrit() );
|
||||
StopSound( TF_WEAPON_PIPEBOMB_LAUNCHER_CHARGE_SOUND );
|
||||
#else
|
||||
pPlayer->SpeakWeaponFire();
|
||||
CTF_GameStats.Event_PlayerFiredWeapon( pPlayer, IsCurrentAttackACrit() );
|
||||
#endif
|
||||
|
||||
// Set next attack times.
|
||||
|
||||
float flFireDelay = ApplyFireDelay( m_pWeaponInfo->GetWeaponData( m_iWeaponMode ).m_flTimeFireDelay );
|
||||
|
||||
m_flNextPrimaryAttack = gpGlobals->curtime + flFireDelay;
|
||||
m_flLastDenySoundTime = gpGlobals->curtime;
|
||||
|
||||
SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() );
|
||||
|
||||
// Check the reload mode and behave appropriately.
|
||||
if ( m_bReloadsSingly )
|
||||
{
|
||||
m_iReloadMode.Set( TF_RELOAD_START );
|
||||
}
|
||||
|
||||
m_flChargeBeginTime = 0;
|
||||
|
||||
if ( TFGameRules()->GameModeUsesUpgrades() )
|
||||
{
|
||||
PlayUpgradedShootSound( "Weapon_Upgrade.DamageBonus" );
|
||||
}
|
||||
}
|
||||
|
||||
float CTFPipebombLauncher::GetProjectileSpeed( void )
|
||||
{
|
||||
float flForwardSpeed = RemapValClamped( ( gpGlobals->curtime - m_flChargeBeginTime ),
|
||||
0.0f,
|
||||
GetChargeMaxTime(),
|
||||
TF_PIPEBOMB_MIN_CHARGE_VEL,
|
||||
TF_PIPEBOMB_MAX_CHARGE_VEL );
|
||||
|
||||
return flForwardSpeed;
|
||||
}
|
||||
|
||||
void CTFPipebombLauncher::AddPipeBomb( CTFGrenadePipebombProjectile *pBomb )
|
||||
{
|
||||
PipebombHandle hHandle;
|
||||
hHandle = pBomb;
|
||||
m_Pipebombs.AddToTail( hHandle );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Add pipebombs to our list as they're fired
|
||||
//-----------------------------------------------------------------------------
|
||||
CBaseEntity *CTFPipebombLauncher::FireProjectile( CTFPlayer *pPlayer )
|
||||
{
|
||||
CBaseEntity *pProjectile = BaseClass::FireProjectile( pPlayer );
|
||||
if ( pProjectile )
|
||||
{
|
||||
#ifdef GAME_DLL
|
||||
// If we've gone over the max pipebomb count, detonate the oldest
|
||||
int nMaxPipebombs = TF_WEAPON_PIPEBOMB_COUNT;
|
||||
CALL_ATTRIB_HOOK_INT( nMaxPipebombs, add_max_pipebombs );
|
||||
if ( m_Pipebombs.Count() >= nMaxPipebombs )
|
||||
{
|
||||
CTFGrenadePipebombProjectile *pTemp = m_Pipebombs[0];
|
||||
if ( pTemp )
|
||||
{
|
||||
pTemp->SetTimer( gpGlobals->curtime ); // explode NOW
|
||||
}
|
||||
|
||||
m_Pipebombs.Remove(0);
|
||||
}
|
||||
|
||||
CTFGrenadePipebombProjectile *pPipebomb = (CTFGrenadePipebombProjectile*)pProjectile;
|
||||
|
||||
PipebombHandle hHandle;
|
||||
hHandle = pPipebomb;
|
||||
m_Pipebombs.AddToTail( hHandle );
|
||||
|
||||
m_iPipebombCount = m_Pipebombs.Count();
|
||||
#endif
|
||||
}
|
||||
|
||||
return pProjectile;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Detonate this demoman's pipebombs if secondary fire is down.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFPipebombLauncher::ItemBusyFrame( void )
|
||||
{
|
||||
#ifdef GAME_DLL
|
||||
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
|
||||
if ( pOwner && pOwner->m_nButtons & IN_ATTACK2 )
|
||||
{
|
||||
// We need to do this to catch the case of player trying to detonate
|
||||
// pipebombs while in the middle of reloading.
|
||||
SecondaryAttack();
|
||||
}
|
||||
#endif
|
||||
|
||||
BaseClass::ItemBusyFrame();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Detonate active pipebombs
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFPipebombLauncher::SecondaryAttack( void )
|
||||
{
|
||||
if ( !CanAttack() )
|
||||
return;
|
||||
|
||||
if ( m_iPipebombCount )
|
||||
{
|
||||
// Get a valid player.
|
||||
CTFPlayer *pPlayer = ToTFPlayer( GetOwner() );
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
//If one or more pipebombs failed to detonate then play a sound.
|
||||
if ( DetonateRemotePipebombs( false ) == true )
|
||||
{
|
||||
if ( m_flLastDenySoundTime <= gpGlobals->curtime )
|
||||
{
|
||||
// Deny!
|
||||
m_flLastDenySoundTime = gpGlobals->curtime + 1;
|
||||
WeaponSound( SPECIAL2 );
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Play a detonate sound.
|
||||
WeaponSound( SPECIAL3 );
|
||||
|
||||
#ifdef GAME_DLL
|
||||
IGameEvent *pDetEvent = gameeventmanager->CreateEvent( "demoman_det_stickies" );
|
||||
|
||||
if ( pDetEvent )
|
||||
{
|
||||
pDetEvent->SetInt( "player", pPlayer->entindex() );
|
||||
|
||||
// Send the event
|
||||
gameeventmanager->FireEvent( pDetEvent );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Server specific functions.
|
||||
//
|
||||
#ifdef GAME_DLL
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFPipebombLauncher::UpdateOnRemove(void)
|
||||
{
|
||||
// If we just died, we want to fizzle our pipebombs.
|
||||
// If the player switched classes, our pipebombs have already been removed.
|
||||
DetonateRemotePipebombs( true );
|
||||
|
||||
BaseClass::UpdateOnRemove();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFPipebombLauncher::ApplyPostHitEffects( const CTakeDamageInfo &inputInfo, CTFPlayer *pPlayer )
|
||||
{
|
||||
if ( !GetTFPlayerOwner() )
|
||||
return;
|
||||
|
||||
if ( pPlayer->m_Shared.GetWeaponKnockbackID() == -1 )
|
||||
{
|
||||
pPlayer->m_Shared.SetWeaponKnockbackID( GetTFPlayerOwner()->GetUserID() );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: If a pipebomb has been removed, remove it from our list
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFPipebombLauncher::DeathNotice( CBaseEntity *pVictim )
|
||||
{
|
||||
Assert( dynamic_cast<CTFGrenadePipebombProjectile*>(pVictim) );
|
||||
|
||||
PipebombHandle hHandle;
|
||||
hHandle = (CTFGrenadePipebombProjectile*)pVictim;
|
||||
m_Pipebombs.FindAndRemove( hHandle );
|
||||
|
||||
m_iPipebombCount = m_Pipebombs.Count();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Remove *with* explosions
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CTFPipebombLauncher::DetonateRemotePipebombs( bool bFizzle )
|
||||
{
|
||||
if ( GetDetonateMode() == TF_DETONATE_MODE_DOT && !bFizzle )
|
||||
{
|
||||
return ModifyPipebombsInView( TF_PIPEBOMB_DETONATE );
|
||||
}
|
||||
|
||||
bool bFailedToDetonate = false;
|
||||
|
||||
int count = m_Pipebombs.Count();
|
||||
|
||||
for ( int i = 0; i < count; i++ )
|
||||
{
|
||||
CTFGrenadePipebombProjectile *pTemp = m_Pipebombs[i];
|
||||
if ( pTemp )
|
||||
{
|
||||
//This guy will die soon enough.
|
||||
if ( pTemp->IsEffectActive( EF_NODRAW ) )
|
||||
continue;
|
||||
#ifdef GAME_DLL
|
||||
if ( bFizzle )
|
||||
{
|
||||
pTemp->Fizzle();
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( bFizzle == false )
|
||||
{
|
||||
if ( ( gpGlobals->curtime - pTemp->m_flCreationTime ) < pTemp->GetLiveTime() )
|
||||
{
|
||||
if ( pTemp->GetLiveTime() <= 0.5f )
|
||||
{
|
||||
pTemp->SetDetonateOnPulse( true );
|
||||
}
|
||||
bFailedToDetonate = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#ifdef GAME_DLL
|
||||
if ( CanDestroyStickies() )
|
||||
{
|
||||
pTemp->DetonateStickies();
|
||||
}
|
||||
pTemp->Detonate();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return bFailedToDetonate;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CTFPipebombLauncher::ModifyPipebombsInView( int iEffect )
|
||||
{
|
||||
CTFPlayer* pPlayer = ToTFPlayer( GetOwner() );
|
||||
if ( !pPlayer )
|
||||
return true;
|
||||
|
||||
// Dot product from the view angle to determine which bombs to detonate.
|
||||
bool bFailedToDetonate = true;
|
||||
int count = m_Pipebombs.Count();
|
||||
for ( int i=0; i<count; ++i )
|
||||
{
|
||||
CTFGrenadePipebombProjectile *pTemp = m_Pipebombs[i];
|
||||
if ( !pTemp || pTemp->IsEffectActive( EF_NODRAW ) )
|
||||
continue;
|
||||
|
||||
Vector vecToTarget;
|
||||
vecToTarget = pTemp->WorldSpaceCenter() - pPlayer->EyePosition();
|
||||
vecToTarget.NormalizeInPlace();
|
||||
|
||||
Vector vecPlayerForward;
|
||||
AngleVectors( pPlayer->EyeAngles(), &vecPlayerForward, NULL, NULL );
|
||||
vecPlayerForward.NormalizeInPlace();
|
||||
|
||||
bool bArmed = ( ( gpGlobals->curtime - pTemp->m_flCreationTime ) > pTemp->GetLiveTime() );
|
||||
float flDist = pPlayer->GetAbsOrigin().DistTo( pTemp->GetAbsOrigin() );
|
||||
float flDot = DotProduct( vecToTarget, vecPlayerForward );
|
||||
|
||||
// Detonate sticky bombs directly under the crosshair or under our feet (to allow sticky jumping)
|
||||
if ( flDot > 0.975f || flDist < pTemp->GetDamageRadius() )
|
||||
{
|
||||
switch ( iEffect )
|
||||
{
|
||||
case TF_PIPEBOMB_HIGHLIGHT:
|
||||
#ifdef CLIENT_DLL
|
||||
pTemp->SetHighlight( true );
|
||||
#endif
|
||||
break;
|
||||
case TF_PIPEBOMB_DETONATE:
|
||||
if ( bArmed )
|
||||
{
|
||||
bFailedToDetonate = false;
|
||||
#ifdef GAME_DLL
|
||||
if ( CanDestroyStickies() )
|
||||
{
|
||||
pTemp->DetonateStickies();
|
||||
}
|
||||
#endif
|
||||
pTemp->Detonate();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ( iEffect == TF_PIPEBOMB_HIGHLIGHT )
|
||||
{
|
||||
#ifdef CLIENT_DLL
|
||||
pTemp->SetHighlight( false );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return bFailedToDetonate;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CTFPipebombLauncher::Reload( void )
|
||||
{
|
||||
if ( m_flChargeBeginTime > 0 )
|
||||
return false;
|
||||
|
||||
return BaseClass::Reload();
|
||||
}
|
||||
Reference in New Issue
Block a user