initial
This commit is contained in:
704
game/shared/cstrike15/weapon_basecsgrenade.cpp
Normal file
704
game/shared/cstrike15/weapon_basecsgrenade.cpp
Normal file
@@ -0,0 +1,704 @@
|
||||
//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "weapon_csbase.h"
|
||||
#include "gamerules.h"
|
||||
#include "npcevent.h"
|
||||
#include "engine/IEngineSound.h"
|
||||
#include "weapon_basecsgrenade.h"
|
||||
#include "in_buttons.h"
|
||||
#include "datacache/imdlcache.h"
|
||||
|
||||
#include "cs_shareddefs.h"
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
|
||||
#include "c_cs_player.h"
|
||||
#include "HUD/sfweaponselection.h"
|
||||
#include "c_rumble.h"
|
||||
#include "rumble_shared.h"
|
||||
#else
|
||||
|
||||
#include "cs_player.h"
|
||||
#include "items.h"
|
||||
#include "cs_gamestats.h"
|
||||
|
||||
#endif
|
||||
|
||||
// NOTE: This has to be the last file included!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
#define GRENADE_TIMER 1.5f //Seconds
|
||||
|
||||
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( BaseCSGrenade, DT_BaseCSGrenade )
|
||||
|
||||
BEGIN_NETWORK_TABLE(CBaseCSGrenade, DT_BaseCSGrenade)
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
SendPropBool( SENDINFO(m_bRedraw) ),
|
||||
SendPropBool( SENDINFO(m_bIsHeldByPlayer) ),
|
||||
SendPropBool( SENDINFO(m_bPinPulled) ),
|
||||
SendPropFloat( SENDINFO(m_fThrowTime), 0, SPROP_NOSCALE ),
|
||||
SendPropBool( SENDINFO( m_bLoopingSoundPlaying ) ),
|
||||
#ifdef GRENADE_UNDERHAND_FEATURE_ENABLED
|
||||
SendPropFloat( SENDINFO(m_flThrowStrength), 0, SPROP_NOSCALE ),
|
||||
#endif
|
||||
#else
|
||||
RecvPropBool( RECVINFO(m_bRedraw) ),
|
||||
RecvPropBool( RECVINFO(m_bIsHeldByPlayer) ),
|
||||
RecvPropBool( RECVINFO(m_bPinPulled) ),
|
||||
RecvPropFloat( RECVINFO(m_fThrowTime) ),
|
||||
RecvPropBool( RECVINFO( m_bLoopingSoundPlaying ) ),
|
||||
#ifdef GRENADE_UNDERHAND_FEATURE_ENABLED
|
||||
RecvPropFloat( RECVINFO(m_flThrowStrength) ),
|
||||
#endif
|
||||
#endif
|
||||
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
#if defined CLIENT_DLL
|
||||
BEGIN_PREDICTION_DATA( CBaseCSGrenade )
|
||||
DEFINE_PRED_FIELD( m_bRedraw, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_FIELD( m_bPinPulled, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
|
||||
#ifdef GRENADE_UNDERHAND_FEATURE_ENABLED
|
||||
DEFINE_PRED_FIELD( m_flThrowStrength, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
|
||||
#endif
|
||||
END_PREDICTION_DATA()
|
||||
#endif
|
||||
|
||||
LINK_ENTITY_TO_CLASS_ALIASED( weapon_basecsgrenade, BaseCSGrenade );
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
ConVar sv_ignoregrenaderadio( "sv_ignoregrenaderadio", "0", FCVAR_RELEASE, "Turn off Fire in the hole messages" );
|
||||
#endif
|
||||
|
||||
#ifdef GRENADE_UNDERHAND_FEATURE_ENABLED
|
||||
#define GRENADE_SECONDARY_DAMPENING 0.3f
|
||||
#define GRENADE_SECONDARY_LOWER 12.0f
|
||||
#define GRENADE_SECONDARY_TRANSITION 1.3f
|
||||
#define GRENADE_SECONDARY_INTERP 2.0f
|
||||
#endif
|
||||
|
||||
CBaseCSGrenade::CBaseCSGrenade()
|
||||
{
|
||||
m_bRedraw = false;
|
||||
m_bIsHeldByPlayer = false;
|
||||
m_bPinPulled = false;
|
||||
m_fThrowTime = 0;
|
||||
m_bLoopingSoundPlaying = false;
|
||||
#ifdef GRENADE_UNDERHAND_FEATURE_ENABLED
|
||||
m_flThrowStrength = 1.0f;
|
||||
m_flThrowStrengthClientSmooth = 1.0f;
|
||||
#endif
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
m_bHasEmittedProjectile = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseCSGrenade::Precache()
|
||||
{
|
||||
BaseClass::Precache();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseCSGrenade::Deploy()
|
||||
{
|
||||
m_bRedraw = false;
|
||||
m_bIsHeldByPlayer = true;
|
||||
m_bPinPulled = false;
|
||||
#ifdef GRENADE_UNDERHAND_FEATURE_ENABLED
|
||||
m_flThrowStrength = 1.0f;
|
||||
m_flThrowStrengthClientSmooth = 1.0f;
|
||||
#endif
|
||||
m_fThrowTime = 0;
|
||||
#ifndef CLIENT_DLL
|
||||
// if we're officially out of grenades, ditch this weapon
|
||||
CCSPlayer *pPlayer = GetPlayerOwner();
|
||||
if ( !pPlayer )
|
||||
return false;
|
||||
|
||||
if ( pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0 )
|
||||
{
|
||||
pPlayer->Weapon_Drop( this, NULL, NULL );
|
||||
UTIL_Remove(this);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return BaseClass::Deploy();
|
||||
}
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
int CBaseCSGrenade::DrawModel( int flags, const RenderableInstance_t &instance )
|
||||
{
|
||||
//hide the grenade that's in the player's hand while playing grenade throwing animations
|
||||
CCSPlayer *pPlayer = GetPlayerOwner();
|
||||
if ( pPlayer )
|
||||
{
|
||||
if ( !pPlayer->m_bUseNewAnimstate && pPlayer->m_PlayerAnimState && pPlayer->m_PlayerAnimState->ShouldHideGrenadeDuringThrow() )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return BaseClass::DrawModel( flags, instance );
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseCSGrenade::Holster( CBaseCombatWeapon *pSwitchingTo )
|
||||
{
|
||||
m_bRedraw = false;
|
||||
// we don't want to set m_bIsHeldByPlayer to true because the weapon actually holsters before it's removed from the inventory after the last grenade has been thrown
|
||||
// this causes a visual bug in the weapon selection UI
|
||||
m_bPinPulled = false; // when this is holstered make sure the pin isnt pulled.
|
||||
#ifdef GRENADE_UNDERHAND_FEATURE_ENABLED
|
||||
m_flThrowStrength = 1.0f;
|
||||
m_flThrowStrengthClientSmooth = 1.0f;
|
||||
#endif
|
||||
m_fThrowTime = 0;
|
||||
#ifndef CLIENT_DLL
|
||||
// If they attempt to switch weapons before the throw animation is done,
|
||||
// allow it, but kill the weapon if we have to.
|
||||
CCSPlayer *pPlayer = GetPlayerOwner();
|
||||
if ( !pPlayer )
|
||||
return false;
|
||||
|
||||
if( pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0 )
|
||||
{
|
||||
CBaseCombatCharacter *pOwner = (CBaseCombatCharacter *)pPlayer;
|
||||
pOwner->Weapon_Drop( this );
|
||||
UTIL_Remove(this);
|
||||
}
|
||||
#endif
|
||||
|
||||
return BaseClass::Holster( pSwitchingTo );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseCSGrenade::PrimaryAttack()
|
||||
{
|
||||
if ( !m_bIsHeldByPlayer || m_bPinPulled || m_fThrowTime > 0.0f )
|
||||
return;
|
||||
|
||||
CCSPlayer *pPlayer = GetPlayerOwner();
|
||||
if ( !pPlayer || pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
|
||||
return;
|
||||
|
||||
// Ensure that the player can use this grenade
|
||||
if ( !pPlayer->CanUseGrenade( GetCSWeaponID() ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
pPlayer->DoAnimationEvent( PLAYERANIMEVENT_GRENADE_PULL_PIN );
|
||||
#endif
|
||||
|
||||
// The pull pin animation has to finish, then we wait until they aren't holding the primary
|
||||
// attack button, then throw the grenade.
|
||||
SendWeaponAnim( ACT_VM_PULLPIN );
|
||||
m_bPinPulled = true;
|
||||
|
||||
// Don't let weapon idle interfere in the middle of a throw!
|
||||
MDLCACHE_CRITICAL_SECTION();
|
||||
SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() );
|
||||
|
||||
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseCSGrenade::SecondaryAttack()
|
||||
{
|
||||
|
||||
#ifdef GRENADE_UNDERHAND_FEATURE_ENABLED
|
||||
if ( !m_bPinPulled )
|
||||
{
|
||||
m_flThrowStrength = 0.0f;
|
||||
m_flThrowStrengthClientSmooth = 0.0f;
|
||||
}
|
||||
|
||||
if ( CSGameRules()->IsFreezePeriod() ) // Don't let Brian molotov the team during freezetime
|
||||
return;
|
||||
|
||||
PrimaryAttack();
|
||||
return;
|
||||
#endif
|
||||
|
||||
/*if ( m_bRedraw )
|
||||
return;
|
||||
|
||||
CCSPlayer *pPlayer = GetPlayerOwner();
|
||||
|
||||
if ( pPlayer == NULL )
|
||||
return;
|
||||
|
||||
//See if we're ducking
|
||||
if ( pPlayer->GetFlags() & FL_DUCKING )
|
||||
{
|
||||
//Send the weapon animation
|
||||
SendWeaponAnim( ACT_VM_SECONDARYATTACK );
|
||||
}
|
||||
else
|
||||
{
|
||||
//Send the weapon animation
|
||||
SendWeaponAnim( ACT_VM_HAULBACK );
|
||||
}
|
||||
|
||||
// Don't let weapon idle interfere in the middle of a throw!
|
||||
SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() );
|
||||
|
||||
m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();*/
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseCSGrenade::Reload()
|
||||
{
|
||||
if ( ( m_bRedraw ) && ( m_flNextPrimaryAttack <= gpGlobals->curtime ) && ( m_flNextSecondaryAttack <= gpGlobals->curtime ) )
|
||||
{
|
||||
//Redraw the weapon
|
||||
SendWeaponAnim( ACT_VM_DRAW );
|
||||
|
||||
//Update our times
|
||||
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
|
||||
m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
|
||||
|
||||
SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() );
|
||||
|
||||
//Mark this as done
|
||||
// m_bRedraw = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pPicker -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseCSGrenade::OnPickedUp( CBaseCombatCharacter *pNewOwner )
|
||||
{
|
||||
BaseClass::OnPickedUp( pNewOwner );
|
||||
|
||||
#if !defined( CLIENT_DLL )
|
||||
if ( pNewOwner )
|
||||
{
|
||||
m_bIsHeldByPlayer = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void CBaseCSGrenade::ItemPreFrame()
|
||||
{
|
||||
BaseClass::ItemPreFrame();
|
||||
|
||||
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
|
||||
if ( pOwner == NULL )
|
||||
return;
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
//we want to control the grenade model's visibility so opt out of the fast path
|
||||
if (GetBaseAnimating())
|
||||
GetBaseAnimating()->SetAllowFastPath(false);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef GRENADE_UNDERHAND_FEATURE_ENABLED
|
||||
float CBaseCSGrenade::ApproachThrownStrength()
|
||||
{
|
||||
m_flThrowStrengthClientSmooth = Approach(
|
||||
m_flThrowStrength,
|
||||
m_flThrowStrengthClientSmooth,
|
||||
gpGlobals->frametime * GRENADE_SECONDARY_INTERP
|
||||
);
|
||||
return m_flThrowStrengthClientSmooth;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseCSGrenade::ItemPostFrame()
|
||||
{
|
||||
CCSPlayer *pPlayer = GetPlayerOwner();
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
CBaseViewModel *vm = pPlayer->GetViewModel( m_nViewModelIndex );
|
||||
if ( !vm )
|
||||
return;
|
||||
|
||||
bool bPrimaryHeld = (pPlayer->m_nButtons & IN_ATTACK) != 0;
|
||||
bool bSecondaryHeld = (pPlayer->m_nButtons & IN_ATTACK2) != 0;
|
||||
|
||||
#ifdef GRENADE_UNDERHAND_FEATURE_ENABLED
|
||||
if ( m_bPinPulled && ( bPrimaryHeld || bSecondaryHeld ) )
|
||||
{
|
||||
float flIdealThrowStrength = 0.5f;
|
||||
|
||||
if ( bPrimaryHeld )
|
||||
flIdealThrowStrength += 0.5f;
|
||||
|
||||
if ( bSecondaryHeld )
|
||||
flIdealThrowStrength -= 0.5f;
|
||||
|
||||
m_flThrowStrength = Approach( flIdealThrowStrength, m_flThrowStrength, gpGlobals->frametime * GRENADE_SECONDARY_TRANSITION );
|
||||
}
|
||||
#endif
|
||||
|
||||
// If they let go of the fire buttons, they want to throw the grenade.
|
||||
if ( m_bPinPulled && !(bPrimaryHeld) && !(bSecondaryHeld) )
|
||||
{
|
||||
#ifndef CLIENT_DLL
|
||||
#ifdef GRENADE_UNDERHAND_FEATURE_ENABLED
|
||||
if ( IsThrownUnderhand() )
|
||||
{
|
||||
pPlayer->DoAnimationEvent( PLAYERANIMEVENT_THROW_GRENADE_UNDERHAND );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
pPlayer->DoAnimationEvent( PLAYERANIMEVENT_THROW_GRENADE );
|
||||
}
|
||||
#endif
|
||||
|
||||
StartGrenadeThrow();
|
||||
|
||||
MDLCACHE_CRITICAL_SECTION();
|
||||
m_bPinPulled = false;
|
||||
|
||||
#ifdef GRENADE_UNDERHAND_FEATURE_ENABLED
|
||||
if ( IsThrownUnderhand() )
|
||||
{
|
||||
SendWeaponAnim( ACT_VM_RELEASE );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
SendWeaponAnim( ACT_VM_THROW );
|
||||
}
|
||||
|
||||
SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() );
|
||||
|
||||
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); // we're still throwing, so reset our next primary attack
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
IGameEvent * event = gameeventmanager->CreateEvent( "weapon_fire" );
|
||||
if( event )
|
||||
{
|
||||
const char *weaponName = STRING( m_iClassname );
|
||||
if ( IsWeaponClassname( weaponName ) )
|
||||
{
|
||||
weaponName += WEAPON_CLASSNAME_PREFIX_LENGTH;
|
||||
}
|
||||
|
||||
event->SetInt( "userid", pPlayer->GetUserID() );
|
||||
event->SetString( "weapon", weaponName );
|
||||
event->SetBool( "silenced", false );
|
||||
gameeventmanager->FireEvent( event );
|
||||
}
|
||||
|
||||
#else
|
||||
RumbleEffect( XBX_GetUserId( pPlayer->GetSplitScreenPlayerSlot() ), RUMBLE_CROWBAR_SWING, 0, RUMBLE_FLAG_RESTART );
|
||||
#endif
|
||||
}
|
||||
else if ((m_fThrowTime > 0) && (m_fThrowTime < gpGlobals->curtime))
|
||||
{
|
||||
// only decrement our ammo when we actually create the projectile
|
||||
DecrementAmmo( pPlayer );
|
||||
|
||||
ThrowGrenade();
|
||||
}
|
||||
else if( !m_bIsHeldByPlayer )
|
||||
{
|
||||
// Has the throw animation finished playing
|
||||
if( m_flTimeWeaponIdle < gpGlobals->curtime )
|
||||
{
|
||||
// if we're officially out of grenades, ditch this weapon
|
||||
int nAmmoCount = pPlayer->GetAmmoCount(m_iPrimaryAmmoType);
|
||||
if( nAmmoCount <= 0 )
|
||||
{
|
||||
pPlayer->Weapon_Drop( this, NULL, NULL );
|
||||
#ifndef CLIENT_DLL
|
||||
//pPlayer->RemoveWeaponOnPlayer( this );
|
||||
UTIL_Remove(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
pPlayer->SwitchToNextBestWeapon( this );
|
||||
}
|
||||
#if defined (CLIENT_DLL)
|
||||
// when a grenade is removed, force the local player to update thier inventory screen
|
||||
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
|
||||
if ( pLocalPlayer && pLocalPlayer == pPlayer )
|
||||
{
|
||||
SFWeaponSelection *pHudWS = GET_HUDELEMENT( SFWeaponSelection );
|
||||
if ( pHudWS )
|
||||
{
|
||||
int nAmmoCount = pPlayer->GetAmmoCount(m_iPrimaryAmmoType);
|
||||
if ( nAmmoCount <= 0 )
|
||||
{
|
||||
pHudWS->ShowAndUpdateSelection( WEPSELECT_DROP, this );
|
||||
}
|
||||
else
|
||||
{
|
||||
// we need to tell the hud that this weapon still exists and then update the selected weapon
|
||||
pHudWS->ShowAndUpdateSelection( WEPSELECT_PICKUP, this );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return; //don't animate this grenade any more!
|
||||
}
|
||||
}
|
||||
else if( !m_bRedraw )
|
||||
{
|
||||
BaseClass::ItemPostFrame();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
|
||||
void CBaseCSGrenade::DecrementAmmo( CBaseCombatCharacter *pOwner )
|
||||
{
|
||||
}
|
||||
|
||||
void CBaseCSGrenade::DropGrenade()
|
||||
{
|
||||
m_bRedraw = true;
|
||||
m_bIsHeldByPlayer = false;
|
||||
m_fThrowTime = 0.0f;
|
||||
}
|
||||
|
||||
void CBaseCSGrenade::ThrowGrenade()
|
||||
{
|
||||
m_bRedraw = true;
|
||||
m_bIsHeldByPlayer = false;
|
||||
m_fThrowTime = 0.0f;
|
||||
|
||||
CBaseHudWeaponSelection *pHudSelection = GetHudWeaponSelection();
|
||||
if ( pHudSelection )
|
||||
{
|
||||
pHudSelection->OnWeaponDrop( this );
|
||||
}
|
||||
}
|
||||
|
||||
void CBaseCSGrenade::StartGrenadeThrow()
|
||||
{
|
||||
m_fThrowTime = gpGlobals->curtime + 0.1f;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
BEGIN_DATADESC( CBaseCSGrenade )
|
||||
DEFINE_FIELD( m_bRedraw, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( m_bIsHeldByPlayer, FIELD_BOOLEAN ),
|
||||
END_DATADESC()
|
||||
|
||||
int CBaseCSGrenade::CapabilitiesGet()
|
||||
{
|
||||
return bits_CAP_WEAPON_RANGE_ATTACK1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pOwner -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseCSGrenade::DecrementAmmo( CBaseCombatCharacter *pOwner )
|
||||
{
|
||||
pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType );
|
||||
}
|
||||
|
||||
void CBaseCSGrenade::StartGrenadeThrow()
|
||||
{
|
||||
m_fThrowTime = gpGlobals->curtime + 0.1f;
|
||||
|
||||
CBroadcastRecipientFilter filter;
|
||||
CSoundParameters params;
|
||||
if ( GetParametersForSound( GetShootSound( SINGLE ), params, NULL ) )
|
||||
{
|
||||
//CPASAttenuationFilter filter( this );
|
||||
EmitSound( filter, entindex(), GetShootSound( SINGLE ));
|
||||
}
|
||||
|
||||
//WeaponSound(SINGLE, gpGlobals->curtime + 3.0f);
|
||||
}
|
||||
|
||||
void CBaseCSGrenade::ThrowGrenade()
|
||||
{
|
||||
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
|
||||
if ( !pPlayer )
|
||||
{
|
||||
Assert( false );
|
||||
return;
|
||||
}
|
||||
|
||||
QAngle angThrow = pPlayer->GetFinalAimAngle();
|
||||
|
||||
if ( angThrow[PITCH] > 90.0f )
|
||||
{
|
||||
angThrow[PITCH] -= 360.0f;
|
||||
}
|
||||
else if ( angThrow[PITCH] < -90.0f )
|
||||
{
|
||||
angThrow[PITCH] += 360.0f;
|
||||
}
|
||||
|
||||
AssertMsg( angThrow[PITCH] <= 90.0f && angThrow[PITCH] >= -90.0f, "Grenade throw pitch angle must be between -90 and 90 for the adustments to work.");
|
||||
|
||||
// NB. a pitch of +90 is looking straight down, -90 is looking straight up
|
||||
|
||||
// add a 10 degrees upwards angle to the throw when looking horizontal, lerp the upwards boost to 0 at the pitch extremes
|
||||
angThrow[PITCH] -= 10.0f * (90.0f - fabsf(angThrow[PITCH])) / 90.0f;
|
||||
|
||||
const float kBaseVelocity = GetThrowVelocity();
|
||||
//const float kThrowVelocityClampRatio = 750.0f / 540.0f; // from original CSS values
|
||||
|
||||
//float flVel = clamp((90 - angThrow.x) / 90, 0.0f, kThrowVelocityClampRatio) * kBaseVelocity;
|
||||
float flVel = clamp( (kBaseVelocity * 0.9f), 15, 750 );
|
||||
|
||||
#ifdef GRENADE_UNDERHAND_FEATURE_ENABLED
|
||||
//clamp the throw strength ranges just to be sure
|
||||
float flClampedThrowStrength = m_flThrowStrength;
|
||||
flClampedThrowStrength = clamp( flClampedThrowStrength, 0.0f, 1.0f );
|
||||
|
||||
flVel *= Lerp( flClampedThrowStrength, GRENADE_SECONDARY_DAMPENING, 1.0f );
|
||||
#endif
|
||||
Vector vForward;
|
||||
AngleVectors( angThrow, &vForward );
|
||||
|
||||
Vector vecSrc = pPlayer->GetAbsOrigin() + pPlayer->GetViewOffset();
|
||||
|
||||
#ifdef GRENADE_UNDERHAND_FEATURE_ENABLED
|
||||
vecSrc += Vector(0, 0, Lerp( flClampedThrowStrength, -GRENADE_SECONDARY_LOWER, 0.0f ) );
|
||||
#endif
|
||||
// We want to throw the grenade from 16 units out. But that can cause problems if we're facing
|
||||
// a thin wall. Do a hull trace to be safe.
|
||||
// Wills: Moved the trace length out to 22 inches, then subtract 6. This way we default to 16,
|
||||
// but pull back 6 from wherever we hit, so we don't emit from EXACTLY inside the close surface, which can lead to
|
||||
// the grenade penetrating the wall anyway.
|
||||
trace_t trace;
|
||||
Vector mins( -2, -2, -2 );
|
||||
Vector maxs( 2, 2, 2 );
|
||||
UTIL_TraceHull( vecSrc, vecSrc + vForward * 22, mins, maxs, MASK_SOLID | CONTENTS_GRENADECLIP, pPlayer, COLLISION_GROUP_NONE, &trace );
|
||||
vecSrc = trace.endpos - (vForward * 6);
|
||||
|
||||
Vector vecThrow = vForward * flVel + (pPlayer->GetAbsVelocity() * 1.25);
|
||||
|
||||
EmitGrenade( vecSrc, vec3_angle, vecThrow, AngularImpulse(600,random->RandomInt(-1200,1200),0), pPlayer, GetCSWpnData() );
|
||||
|
||||
m_bHasEmittedProjectile = true; // Flag the grenade weapon as having emitted a projectile. The 'grenade' is now flying away from the player, so we don't want to drop *this* grenade on death (that'll make a duplicate)
|
||||
|
||||
m_bRedraw = true;
|
||||
m_bIsHeldByPlayer = false;
|
||||
m_fThrowTime = 0.0f;
|
||||
|
||||
CCSPlayer *pCSPlayer = ToCSPlayer( pPlayer );
|
||||
|
||||
if ( pCSPlayer )
|
||||
{
|
||||
int iWeaponId = GetCSWeaponID();
|
||||
|
||||
pCSPlayer->PlayerUsedGrenade( iWeaponId );
|
||||
|
||||
if ( !sv_ignoregrenaderadio.GetBool() )
|
||||
{
|
||||
if ( iWeaponId == WEAPON_FLASHBANG )
|
||||
pCSPlayer->Radio( "Radio.Flashbang", "#SFUI_TitlesTXT_Flashbang_in_the_hole", true );
|
||||
else if ( iWeaponId == WEAPON_SMOKEGRENADE )
|
||||
pCSPlayer->Radio( "Radio.Smoke", "#SFUI_TitlesTXT_Smoke_in_the_hole", true );
|
||||
else if ( iWeaponId == WEAPON_MOLOTOV )
|
||||
pCSPlayer->Radio( "Radio.Molotov", "#SFUI_TitlesTXT_Molotov_in_the_hole", true );
|
||||
else if ( iWeaponId == WEAPON_INCGRENADE )
|
||||
pCSPlayer->Radio( "Radio.Incendiary", "#SFUI_TitlesTXT_Incendiary_in_the_hole", true );
|
||||
else if ( iWeaponId == WEAPON_DECOY )
|
||||
pCSPlayer->Radio( "Radio.Decoy", "#SFUI_TitlesTXT_Decoy_in_the_hole", true );
|
||||
else
|
||||
pCSPlayer->Radio( "Radio.FireInTheHole", "#SFUI_TitlesTXT_Fire_in_the_hole", true );
|
||||
}
|
||||
CCS_GameStats.IncrementStat( pCSPlayer, CSSTAT_GRENADES_THROWN, 1 );
|
||||
}
|
||||
|
||||
IGameEvent * event = gameeventmanager->CreateEvent( "grenade_thrown" );
|
||||
if ( event )
|
||||
{
|
||||
const char *weaponName = STRING( m_iClassname );
|
||||
if ( IsWeaponClassname( weaponName ) )
|
||||
{
|
||||
weaponName += WEAPON_CLASSNAME_PREFIX_LENGTH;
|
||||
}
|
||||
|
||||
event->SetInt( "userid", pPlayer->GetUserID() );
|
||||
event->SetString( "weapon", weaponName );
|
||||
gameeventmanager->FireEvent( event );
|
||||
}
|
||||
}
|
||||
|
||||
void CBaseCSGrenade::DropGrenade()
|
||||
{
|
||||
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
|
||||
if ( !pPlayer )
|
||||
{
|
||||
Assert( false );
|
||||
return;
|
||||
}
|
||||
|
||||
Vector vForward;
|
||||
pPlayer->EyeVectors( &vForward );
|
||||
Vector vecSrc = pPlayer->GetAbsOrigin() + pPlayer->GetViewOffset() + vForward * 16;
|
||||
|
||||
Vector vecVel = pPlayer->GetAbsVelocity();
|
||||
|
||||
EmitGrenade( vecSrc, vec3_angle, vecVel, AngularImpulse(600,random->RandomInt(-1200,1200),0), pPlayer, GetCSWpnData() );
|
||||
|
||||
CCSPlayer *pCSPlayer = ToCSPlayer( pPlayer );
|
||||
if( pCSPlayer )
|
||||
{
|
||||
CCS_GameStats.IncrementStat( pCSPlayer, CSSTAT_GRENADES_THROWN, 1 );
|
||||
}
|
||||
|
||||
m_bRedraw = true;
|
||||
m_bIsHeldByPlayer = false;
|
||||
m_fThrowTime = 0.0f;
|
||||
}
|
||||
|
||||
void CBaseCSGrenade::EmitGrenade( Vector vecSrc, QAngle vecAngles, Vector vecVel, AngularImpulse angImpulse, CBasePlayer *pPlayer, const CCSWeaponInfo& weaponInfo )
|
||||
{
|
||||
Assert( 0 && "CBaseCSGrenade::EmitGrenade should not be called. Make sure to implement this in your subclass!\n" );
|
||||
}
|
||||
|
||||
bool CBaseCSGrenade::AllowsAutoSwitchFrom( void ) const
|
||||
{
|
||||
return !m_bPinPulled;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user