mirror of
https://github.com/celisej567/source-engine.git
synced 2026-01-04 18:09:53 +03:00
1
This commit is contained in:
552
game/shared/hl2mp/weapon_frag.cpp
Normal file
552
game/shared/hl2mp/weapon_frag.cpp
Normal file
@@ -0,0 +1,552 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "npcevent.h"
|
||||
#include "in_buttons.h"
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
#include "c_hl2mp_player.h"
|
||||
#include "c_te_effect_dispatch.h"
|
||||
#else
|
||||
#include "hl2mp_player.h"
|
||||
#include "te_effect_dispatch.h"
|
||||
#include "grenade_frag.h"
|
||||
#endif
|
||||
|
||||
#include "weapon_ar2.h"
|
||||
#include "effect_dispatch_data.h"
|
||||
#include "weapon_hl2mpbasehlmpcombatweapon.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#define GRENADE_TIMER 2.5f //Seconds
|
||||
|
||||
#define GRENADE_PAUSED_NO 0
|
||||
#define GRENADE_PAUSED_PRIMARY 1
|
||||
#define GRENADE_PAUSED_SECONDARY 2
|
||||
|
||||
#define GRENADE_RADIUS 4.0f // inches
|
||||
|
||||
#define GRENADE_DAMAGE_RADIUS 250.0f
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
#define CWeaponFrag C_WeaponFrag
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Fragmentation grenades
|
||||
//-----------------------------------------------------------------------------
|
||||
class CWeaponFrag: public CBaseHL2MPCombatWeapon
|
||||
{
|
||||
DECLARE_CLASS( CWeaponFrag, CBaseHL2MPCombatWeapon );
|
||||
public:
|
||||
|
||||
DECLARE_NETWORKCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
|
||||
CWeaponFrag();
|
||||
|
||||
void Precache( void );
|
||||
void PrimaryAttack( void );
|
||||
void SecondaryAttack( void );
|
||||
void DecrementAmmo( CBaseCombatCharacter *pOwner );
|
||||
void ItemPostFrame( void );
|
||||
|
||||
bool Deploy( void );
|
||||
bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL );
|
||||
|
||||
bool Reload( void );
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator );
|
||||
#endif
|
||||
|
||||
void ThrowGrenade( CBasePlayer *pPlayer );
|
||||
bool IsPrimed( bool ) { return ( m_AttackPaused != 0 ); }
|
||||
|
||||
private:
|
||||
|
||||
void RollGrenade( CBasePlayer *pPlayer );
|
||||
void LobGrenade( CBasePlayer *pPlayer );
|
||||
// check a throw from vecSrc. If not valid, move the position back along the line to vecEye
|
||||
void CheckThrowPosition( CBasePlayer *pPlayer, const Vector &vecEye, Vector &vecSrc );
|
||||
|
||||
CNetworkVar( bool, m_bRedraw ); //Draw the weapon again after throwing a grenade
|
||||
|
||||
CNetworkVar( int, m_AttackPaused );
|
||||
CNetworkVar( bool, m_fDrawbackFinished );
|
||||
|
||||
CWeaponFrag( const CWeaponFrag & );
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
DECLARE_ACTTABLE();
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
|
||||
acttable_t CWeaponFrag::m_acttable[] =
|
||||
{
|
||||
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_GRENADE, false },
|
||||
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_GRENADE, false },
|
||||
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_GRENADE, false },
|
||||
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_GRENADE, false },
|
||||
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_GRENADE, false },
|
||||
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_GRENADE, false },
|
||||
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_GRENADE, false },
|
||||
};
|
||||
|
||||
IMPLEMENT_ACTTABLE(CWeaponFrag);
|
||||
|
||||
#endif
|
||||
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( WeaponFrag, DT_WeaponFrag )
|
||||
|
||||
BEGIN_NETWORK_TABLE( CWeaponFrag, DT_WeaponFrag )
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
RecvPropBool( RECVINFO( m_bRedraw ) ),
|
||||
RecvPropBool( RECVINFO( m_fDrawbackFinished ) ),
|
||||
RecvPropInt( RECVINFO( m_AttackPaused ) ),
|
||||
#else
|
||||
SendPropBool( SENDINFO( m_bRedraw ) ),
|
||||
SendPropBool( SENDINFO( m_fDrawbackFinished ) ),
|
||||
SendPropInt( SENDINFO( m_AttackPaused ) ),
|
||||
#endif
|
||||
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
BEGIN_PREDICTION_DATA( CWeaponFrag )
|
||||
DEFINE_PRED_FIELD( m_bRedraw, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_FIELD( m_fDrawbackFinished, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_FIELD( m_AttackPaused, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
|
||||
END_PREDICTION_DATA()
|
||||
#endif
|
||||
|
||||
LINK_ENTITY_TO_CLASS( weapon_frag, CWeaponFrag );
|
||||
PRECACHE_WEAPON_REGISTER(weapon_frag);
|
||||
|
||||
CWeaponFrag::CWeaponFrag( void ) :
|
||||
CBaseHL2MPCombatWeapon()
|
||||
{
|
||||
m_bRedraw = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CWeaponFrag::Precache( void )
|
||||
{
|
||||
BaseClass::Precache();
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
UTIL_PrecacheOther( "npc_grenade_frag" );
|
||||
#endif
|
||||
|
||||
PrecacheScriptSound( "WeaponFrag.Throw" );
|
||||
PrecacheScriptSound( "WeaponFrag.Roll" );
|
||||
}
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pEvent -
|
||||
// *pOperator -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CWeaponFrag::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator )
|
||||
{
|
||||
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
|
||||
bool fThrewGrenade = false;
|
||||
|
||||
switch( pEvent->event )
|
||||
{
|
||||
case EVENT_WEAPON_SEQUENCE_FINISHED:
|
||||
m_fDrawbackFinished = true;
|
||||
break;
|
||||
|
||||
case EVENT_WEAPON_THROW:
|
||||
ThrowGrenade( pOwner );
|
||||
DecrementAmmo( pOwner );
|
||||
fThrewGrenade = true;
|
||||
break;
|
||||
|
||||
case EVENT_WEAPON_THROW2:
|
||||
RollGrenade( pOwner );
|
||||
DecrementAmmo( pOwner );
|
||||
fThrewGrenade = true;
|
||||
break;
|
||||
|
||||
case EVENT_WEAPON_THROW3:
|
||||
LobGrenade( pOwner );
|
||||
DecrementAmmo( pOwner );
|
||||
fThrewGrenade = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
BaseClass::Operator_HandleAnimEvent( pEvent, pOperator );
|
||||
break;
|
||||
}
|
||||
|
||||
#define RETHROW_DELAY 0.5
|
||||
if( fThrewGrenade )
|
||||
{
|
||||
m_flNextPrimaryAttack = gpGlobals->curtime + RETHROW_DELAY;
|
||||
m_flNextSecondaryAttack = gpGlobals->curtime + RETHROW_DELAY;
|
||||
m_flTimeWeaponIdle = FLT_MAX; //NOTE: This is set once the animation has finished up!
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CWeaponFrag::Deploy( void )
|
||||
{
|
||||
m_bRedraw = false;
|
||||
m_fDrawbackFinished = false;
|
||||
|
||||
return BaseClass::Deploy();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CWeaponFrag::Holster( CBaseCombatWeapon *pSwitchingTo )
|
||||
{
|
||||
m_bRedraw = false;
|
||||
m_fDrawbackFinished = false;
|
||||
|
||||
return BaseClass::Holster( pSwitchingTo );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CWeaponFrag::Reload( void )
|
||||
{
|
||||
if ( !HasPrimaryAmmo() )
|
||||
return false;
|
||||
|
||||
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();
|
||||
m_flTimeWeaponIdle = gpGlobals->curtime + SequenceDuration();
|
||||
|
||||
//Mark this as done
|
||||
m_bRedraw = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CWeaponFrag::SecondaryAttack( void )
|
||||
{
|
||||
if ( m_bRedraw )
|
||||
return;
|
||||
|
||||
if ( !HasPrimaryAmmo() )
|
||||
return;
|
||||
|
||||
CBaseCombatCharacter *pOwner = GetOwner();
|
||||
|
||||
if ( pOwner == NULL )
|
||||
return;
|
||||
|
||||
CBasePlayer *pPlayer = ToBasePlayer( pOwner );
|
||||
|
||||
if ( pPlayer == NULL )
|
||||
return;
|
||||
|
||||
// Note that this is a secondary attack and prepare the grenade attack to pause.
|
||||
m_AttackPaused = GRENADE_PAUSED_SECONDARY;
|
||||
SendWeaponAnim( ACT_VM_PULLBACK_LOW );
|
||||
|
||||
// Don't let weapon idle interfere in the middle of a throw!
|
||||
m_flTimeWeaponIdle = FLT_MAX;
|
||||
m_flNextSecondaryAttack = FLT_MAX;
|
||||
|
||||
// If I'm now out of ammo, switch away
|
||||
if ( !HasPrimaryAmmo() )
|
||||
{
|
||||
pPlayer->SwitchToNextBestWeapon( this );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CWeaponFrag::PrimaryAttack( void )
|
||||
{
|
||||
if ( m_bRedraw )
|
||||
return;
|
||||
|
||||
CBaseCombatCharacter *pOwner = GetOwner();
|
||||
|
||||
if ( pOwner == NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );;
|
||||
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
// Note that this is a primary attack and prepare the grenade attack to pause.
|
||||
m_AttackPaused = GRENADE_PAUSED_PRIMARY;
|
||||
SendWeaponAnim( ACT_VM_PULLBACK_HIGH );
|
||||
|
||||
// Put both of these off indefinitely. We do not know how long
|
||||
// the player will hold the grenade.
|
||||
m_flTimeWeaponIdle = FLT_MAX;
|
||||
m_flNextPrimaryAttack = FLT_MAX;
|
||||
|
||||
// If I'm now out of ammo, switch away
|
||||
if ( !HasPrimaryAmmo() )
|
||||
{
|
||||
pPlayer->SwitchToNextBestWeapon( this );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pOwner -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CWeaponFrag::DecrementAmmo( CBaseCombatCharacter *pOwner )
|
||||
{
|
||||
pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CWeaponFrag::ItemPostFrame( void )
|
||||
{
|
||||
if( m_fDrawbackFinished )
|
||||
{
|
||||
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
|
||||
|
||||
if (pOwner)
|
||||
{
|
||||
switch( m_AttackPaused )
|
||||
{
|
||||
case GRENADE_PAUSED_PRIMARY:
|
||||
if( !(pOwner->m_nButtons & IN_ATTACK) )
|
||||
{
|
||||
SendWeaponAnim( ACT_VM_THROW );
|
||||
m_fDrawbackFinished = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case GRENADE_PAUSED_SECONDARY:
|
||||
if( !(pOwner->m_nButtons & IN_ATTACK2) )
|
||||
{
|
||||
//See if we're ducking
|
||||
if ( pOwner->m_nButtons & IN_DUCK )
|
||||
{
|
||||
//Send the weapon animation
|
||||
SendWeaponAnim( ACT_VM_SECONDARYATTACK );
|
||||
}
|
||||
else
|
||||
{
|
||||
//Send the weapon animation
|
||||
SendWeaponAnim( ACT_VM_HAULBACK );
|
||||
}
|
||||
|
||||
m_fDrawbackFinished = false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BaseClass::ItemPostFrame();
|
||||
|
||||
if ( m_bRedraw )
|
||||
{
|
||||
if ( IsViewModelSequenceFinished() )
|
||||
{
|
||||
Reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check a throw from vecSrc. If not valid, move the position back along the line to vecEye
|
||||
void CWeaponFrag::CheckThrowPosition( CBasePlayer *pPlayer, const Vector &vecEye, Vector &vecSrc )
|
||||
{
|
||||
trace_t tr;
|
||||
|
||||
UTIL_TraceHull( vecEye, vecSrc, -Vector(GRENADE_RADIUS+2,GRENADE_RADIUS+2,GRENADE_RADIUS+2), Vector(GRENADE_RADIUS+2,GRENADE_RADIUS+2,GRENADE_RADIUS+2),
|
||||
pPlayer->PhysicsSolidMaskForEntity(), pPlayer, pPlayer->GetCollisionGroup(), &tr );
|
||||
|
||||
if ( tr.DidHit() )
|
||||
{
|
||||
vecSrc = tr.endpos;
|
||||
}
|
||||
}
|
||||
|
||||
void DropPrimedFragGrenade( CHL2MP_Player *pPlayer, CBaseCombatWeapon *pGrenade )
|
||||
{
|
||||
CWeaponFrag *pWeaponFrag = dynamic_cast<CWeaponFrag*>( pGrenade );
|
||||
|
||||
if ( pWeaponFrag )
|
||||
{
|
||||
pWeaponFrag->ThrowGrenade( pPlayer );
|
||||
pWeaponFrag->DecrementAmmo( pPlayer );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pPlayer -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CWeaponFrag::ThrowGrenade( CBasePlayer *pPlayer )
|
||||
{
|
||||
#ifndef CLIENT_DLL
|
||||
Vector vecEye = pPlayer->EyePosition();
|
||||
Vector vForward, vRight;
|
||||
|
||||
pPlayer->EyeVectors( &vForward, &vRight, NULL );
|
||||
Vector vecSrc = vecEye + vForward * 18.0f + vRight * 8.0f;
|
||||
CheckThrowPosition( pPlayer, vecEye, vecSrc );
|
||||
// vForward[0] += 0.1f;
|
||||
vForward[2] += 0.1f;
|
||||
|
||||
Vector vecThrow;
|
||||
pPlayer->GetVelocity( &vecThrow, NULL );
|
||||
vecThrow += vForward * 1200;
|
||||
CBaseGrenade *pGrenade = Fraggrenade_Create( vecSrc, vec3_angle, vecThrow, AngularImpulse(600,random->RandomInt(-1200,1200),0), pPlayer, GRENADE_TIMER, false );
|
||||
|
||||
if ( pGrenade )
|
||||
{
|
||||
if ( pPlayer && pPlayer->m_lifeState != LIFE_ALIVE )
|
||||
{
|
||||
pPlayer->GetVelocity( &vecThrow, NULL );
|
||||
|
||||
IPhysicsObject *pPhysicsObject = pGrenade->VPhysicsGetObject();
|
||||
if ( pPhysicsObject )
|
||||
{
|
||||
pPhysicsObject->SetVelocity( &vecThrow, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
pGrenade->SetDamage( GetHL2MPWpnData().m_iPlayerDamage );
|
||||
pGrenade->SetDamageRadius( GRENADE_DAMAGE_RADIUS );
|
||||
}
|
||||
#endif
|
||||
|
||||
m_bRedraw = true;
|
||||
|
||||
WeaponSound( SINGLE );
|
||||
|
||||
// player "shoot" animation
|
||||
pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pPlayer -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CWeaponFrag::LobGrenade( CBasePlayer *pPlayer )
|
||||
{
|
||||
#ifndef CLIENT_DLL
|
||||
Vector vecEye = pPlayer->EyePosition();
|
||||
Vector vForward, vRight;
|
||||
|
||||
pPlayer->EyeVectors( &vForward, &vRight, NULL );
|
||||
Vector vecSrc = vecEye + vForward * 18.0f + vRight * 8.0f + Vector( 0, 0, -8 );
|
||||
CheckThrowPosition( pPlayer, vecEye, vecSrc );
|
||||
|
||||
Vector vecThrow;
|
||||
pPlayer->GetVelocity( &vecThrow, NULL );
|
||||
vecThrow += vForward * 350 + Vector( 0, 0, 50 );
|
||||
CBaseGrenade *pGrenade = Fraggrenade_Create( vecSrc, vec3_angle, vecThrow, AngularImpulse(200,random->RandomInt(-600,600),0), pPlayer, GRENADE_TIMER, false );
|
||||
|
||||
if ( pGrenade )
|
||||
{
|
||||
pGrenade->SetDamage( GetHL2MPWpnData().m_iPlayerDamage );
|
||||
pGrenade->SetDamageRadius( GRENADE_DAMAGE_RADIUS );
|
||||
}
|
||||
#endif
|
||||
|
||||
WeaponSound( WPN_DOUBLE );
|
||||
|
||||
// player "shoot" animation
|
||||
pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
||||
|
||||
m_bRedraw = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pPlayer -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CWeaponFrag::RollGrenade( CBasePlayer *pPlayer )
|
||||
{
|
||||
#ifndef CLIENT_DLL
|
||||
// BUGBUG: Hardcoded grenade width of 4 - better not change the model :)
|
||||
Vector vecSrc;
|
||||
pPlayer->CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 0.0f ), &vecSrc );
|
||||
vecSrc.z += GRENADE_RADIUS;
|
||||
|
||||
Vector vecFacing = pPlayer->BodyDirection2D( );
|
||||
// no up/down direction
|
||||
vecFacing.z = 0;
|
||||
VectorNormalize( vecFacing );
|
||||
trace_t tr;
|
||||
UTIL_TraceLine( vecSrc, vecSrc - Vector(0,0,16), MASK_PLAYERSOLID, pPlayer, COLLISION_GROUP_NONE, &tr );
|
||||
if ( tr.fraction != 1.0 )
|
||||
{
|
||||
// compute forward vec parallel to floor plane and roll grenade along that
|
||||
Vector tangent;
|
||||
CrossProduct( vecFacing, tr.plane.normal, tangent );
|
||||
CrossProduct( tr.plane.normal, tangent, vecFacing );
|
||||
}
|
||||
vecSrc += (vecFacing * 18.0);
|
||||
CheckThrowPosition( pPlayer, pPlayer->WorldSpaceCenter(), vecSrc );
|
||||
|
||||
Vector vecThrow;
|
||||
pPlayer->GetVelocity( &vecThrow, NULL );
|
||||
vecThrow += vecFacing * 700;
|
||||
// put it on its side
|
||||
QAngle orientation(0,pPlayer->GetLocalAngles().y,-90);
|
||||
// roll it
|
||||
AngularImpulse rotSpeed(0,0,720);
|
||||
CBaseGrenade *pGrenade = Fraggrenade_Create( vecSrc, orientation, vecThrow, rotSpeed, pPlayer, GRENADE_TIMER, false );
|
||||
|
||||
if ( pGrenade )
|
||||
{
|
||||
pGrenade->SetDamage( GetHL2MPWpnData().m_iPlayerDamage );
|
||||
pGrenade->SetDamageRadius( GRENADE_DAMAGE_RADIUS );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
WeaponSound( SPECIAL1 );
|
||||
|
||||
// player "shoot" animation
|
||||
pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
||||
|
||||
m_bRedraw = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user