aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/shared/hl2mp/weapon_frag.cpp
diff options
context:
space:
mode:
authorJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
committerJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
commit39ed87570bdb2f86969d4be821c94b722dc71179 (patch)
treeabc53757f75f40c80278e87650ea92808274aa59 /mp/src/game/shared/hl2mp/weapon_frag.cpp
downloadsource-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz
source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/game/shared/hl2mp/weapon_frag.cpp')
-rw-r--r--mp/src/game/shared/hl2mp/weapon_frag.cpp552
1 files changed, 552 insertions, 0 deletions
diff --git a/mp/src/game/shared/hl2mp/weapon_frag.cpp b/mp/src/game/shared/hl2mp/weapon_frag.cpp
new file mode 100644
index 00000000..9319b869
--- /dev/null
+++ b/mp/src/game/shared/hl2mp/weapon_frag.cpp
@@ -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;
+}
+