diff options
Diffstat (limited to 'game/shared/dod/weapon_dodbasegrenade.cpp')
| -rw-r--r-- | game/shared/dod/weapon_dodbasegrenade.cpp | 474 |
1 files changed, 474 insertions, 0 deletions
diff --git a/game/shared/dod/weapon_dodbasegrenade.cpp b/game/shared/dod/weapon_dodbasegrenade.cpp new file mode 100644 index 0000000..d04255a --- /dev/null +++ b/game/shared/dod/weapon_dodbasegrenade.cpp @@ -0,0 +1,474 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "cbase.h" +#include "weapon_dodbasegrenade.h" +#include "in_buttons.h" +#include "dod_gamerules.h" + + +#if defined( CLIENT_DLL ) + #include "c_dod_player.h" +#else + #include "dod_player.h" +#endif + +extern ConVar dod_bonusround; + +IMPLEMENT_NETWORKCLASS_ALIASED( WeaponDODBaseGrenade, DT_WeaponDODBaseGrenade ) + +BEGIN_NETWORK_TABLE(CWeaponDODBaseGrenade, DT_WeaponDODBaseGrenade) +#if !defined( CLIENT_DLL ) + SendPropBool( SENDINFO( m_bPinPulled ) ), + SendPropBool( SENDINFO( m_bArmed ) ), +#else + RecvPropBool( RECVINFO( m_bPinPulled ) ), + RecvPropBool( RECVINFO( m_bArmed ) ), +#endif +END_NETWORK_TABLE() + +BEGIN_PREDICTION_DATA( CWeaponDODBaseGrenade ) +END_PREDICTION_DATA() + +LINK_ENTITY_TO_CLASS( weapon_basedodgrenade, CWeaponDODBaseGrenade ); + +acttable_t CWeaponDODBaseGrenade::m_acttable[] = +{ + // Move this out to the specific grenades??? + { ACT_DOD_STAND_AIM, ACT_DOD_STAND_AIM_GREN_FRAG, false }, + { ACT_DOD_CROUCH_AIM, ACT_DOD_CROUCH_AIM_GREN_FRAG, false }, + { ACT_DOD_CROUCHWALK_AIM, ACT_DOD_CROUCHWALK_AIM_GREN_FRAG, false }, + { ACT_DOD_WALK_AIM, ACT_DOD_WALK_AIM_GREN_FRAG, false }, + { ACT_DOD_RUN_AIM, ACT_DOD_RUN_AIM_GREN_FRAG, false }, + { ACT_PRONE_IDLE, ACT_DOD_PRONE_AIM_GREN_FRAG, false }, + { ACT_PRONE_FORWARD, ACT_DOD_PRONEWALK_AIM_GREN_FRAG, false }, + { ACT_DOD_STAND_IDLE, ACT_DOD_STAND_AIM_GREN_FRAG, false }, + { ACT_DOD_CROUCH_IDLE, ACT_DOD_CROUCH_AIM_GREN_FRAG, false }, + { ACT_DOD_CROUCHWALK_IDLE, ACT_DOD_CROUCHWALK_AIM_GREN_FRAG, false }, + { ACT_DOD_WALK_IDLE, ACT_DOD_WALK_AIM_GREN_FRAG, false }, + { ACT_DOD_RUN_IDLE, ACT_DOD_RUN_AIM_GREN_FRAG, false }, + { ACT_SPRINT, ACT_DOD_SPRINT_AIM_GREN_FRAG, false }, + + { ACT_RANGE_ATTACK1, ACT_DOD_PRIMARYATTACK_GREN_FRAG, false }, + { ACT_DOD_PRIMARYATTACK_PRONE, ACT_DOD_PRIMARYATTACK_PRONE_GREN_FRAG, false }, + { ACT_DOD_PRIMARYATTACK_CROUCH, ACT_DOD_PRIMARYATTACK_CROUCH_GREN_FRAG, false }, + + // Hand Signals + { ACT_DOD_HS_IDLE, ACT_DOD_HS_IDLE_STICKGRENADE, false }, + { ACT_DOD_HS_CROUCH, ACT_DOD_HS_CROUCH_STICKGRENADE, false }, +}; + +IMPLEMENT_ACTTABLE( CWeaponDODBaseGrenade ); + +CWeaponDODBaseGrenade::CWeaponDODBaseGrenade() +{ + m_bRedraw = false; + m_bPinPulled = false; + SetArmed( false ); + + m_iAltFireHint = HINT_USE_PRIME; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CWeaponDODBaseGrenade::CanHolster( void ) +{ + // can only holster hand grenades when not primed! + return ( m_bPinPulled == false && !IsArmed() ); +} + +#ifdef CLIENT_DLL + + void CWeaponDODBaseGrenade::PrimaryAttack() + { + //nothing on the client + } + +#else + + BEGIN_DATADESC( CWeaponDODBaseGrenade ) + DEFINE_FIELD( m_bRedraw, FIELD_BOOLEAN ), + DEFINE_INPUTFUNC( FIELD_FLOAT, "DetonateTime", InputSetDetonateTime ), + END_DATADESC() + + //----------------------------------------------------------------------------- + // Purpose: + //----------------------------------------------------------------------------- + void CWeaponDODBaseGrenade::Precache() + { + PrecacheScriptSound( "Weapon_Grenade.Throw" ); + + // Precache all the grenade minimap icons. + PrecacheMaterial( "sprites/minimap_icons/minimap_riflegren_ger" ); + PrecacheMaterial( "sprites/minimap_icons/minimap_riflegren_us" ); + PrecacheMaterial( "sprites/minimap_icons/grenade_hltv" ); + PrecacheMaterial( "sprites/minimap_icons/stick_hltv" ); + PrecacheMaterial( "sprites/minimap_icons/minimap_smoke_us" ); + PrecacheMaterial( "sprites/minimap_icons/minimap_smoke_ger" ); + + BaseClass::Precache(); + } + + //----------------------------------------------------------------------------- + // Purpose: + //----------------------------------------------------------------------------- + bool CWeaponDODBaseGrenade::Deploy() + { + m_bRedraw = false; + m_bPinPulled = false; + + return BaseClass::Deploy(); + } + + //----------------------------------------------------------------------------- + // Purpose: + // Output : Returns true on success, false on failure. + //----------------------------------------------------------------------------- + bool CWeaponDODBaseGrenade::Holster( CBaseCombatWeapon *pSwitchingTo ) + { + m_bRedraw = false; + +#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. + + CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() ); + + if( pPlayer && pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0 ) + { + pPlayer->Weapon_Drop( this, NULL, NULL ); + UTIL_Remove(this); + } +#endif + + return BaseClass::Holster( pSwitchingTo ); + } + + //----------------------------------------------------------------------------- + // Purpose: + // Output : Returns true on success, false on failure. + //----------------------------------------------------------------------------- + bool CWeaponDODBaseGrenade::Reload() + { + if ( ( m_bRedraw ) && ( m_flNextPrimaryAttack <= gpGlobals->curtime ) && ( m_flNextSecondaryAttack <= gpGlobals->curtime ) ) + { + //Redraw the weapon + SendWeaponAnim( GetDrawActivity() ); + + //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; + } + +enum +{ + THROW_THROW = 0, + THROW_PRIME +}; + + //----------------------------------------------------------------------------- + // Purpose: + //----------------------------------------------------------------------------- + void CWeaponDODBaseGrenade::PrimaryAttack() + { + if ( IsArmed() ) // live grenade already? + { + StartThrow( THROW_THROW ); + } + else + { + StartThrow( THROW_PRIME ); + } + } + + void CWeaponDODBaseGrenade::StartThrow( int throwType ) + { + if( GetPlayerOwner()->GetWaterLevel() > 2 ) + { + PlayEmptySound(); + m_flNextPrimaryAttack = gpGlobals->curtime + 1.0; + return; + } + + if ( !m_bPinPulled ) + { + m_bPinPulled = true; + + SendWeaponAnim( GetPrimaryAttackActivity() ); + + // Can't prime an already primed grenade! + if ( !IsArmed() && throwType == THROW_PRIME ) + { + SetArmed( true ); + + m_flDetonateTime = gpGlobals->curtime + GetDetonateTimerLength(); + + // start the hissing noise + } + + m_flTimeWeaponIdle = gpGlobals->curtime + SequenceDuration(); + m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); + m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); + } + } + + //----------------------------------------------------------------------------- + // Purpose: + //----------------------------------------------------------------------------- + void CWeaponDODBaseGrenade::ItemPostFrame() + { + CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() ); + if ( !pPlayer ) + return; + + CBaseViewModel *pViewModel = pPlayer->GetViewModel( m_nViewModelIndex ); + if ( !pViewModel ) + return; + + if( IsArmed() && gpGlobals->curtime > m_flDetonateTime ) + { + //Drop it! + DropGrenade(); + m_flNextPrimaryAttack = gpGlobals->curtime + 1.0; + m_flNextSecondaryAttack = gpGlobals->curtime + 1.0; + return; + } + + if ( m_bPinPulled && + !(pPlayer->m_nButtons & IN_ATTACK) && + !(pPlayer->m_nButtons & IN_ATTACK2) // If they let go of the fire button, they want to throw the grenade. + ) + { + pPlayer->DoAnimationEvent( PLAYERANIMEVENT_THROW_GRENADE ); + + ThrowGrenade(false); + + m_bRedraw = true; + m_bPinPulled = false; + SetArmed( false ); + + DecrementAmmo( pPlayer ); + + SendWeaponAnim( ACT_VM_THROW ); + } + else + { + BaseClass::ItemPostFrame(); + + if ( m_bRedraw ) + { + if (pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0) + { + pPlayer->Weapon_Drop( this, NULL, NULL ); + UTIL_Remove(this); + } + else + Reload(); + } + } + } + + + //----------------------------------------------------------------------------- + // Purpose: + // Input : *pOwner - + //----------------------------------------------------------------------------- + void CWeaponDODBaseGrenade::DecrementAmmo( CBaseCombatCharacter *pOwner ) + { + pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType ); + + if (pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0) + { + pOwner->Weapon_Drop( this, NULL, NULL ); + UTIL_Remove(this); + } + } + + void CWeaponDODBaseGrenade::DropGrenade( void ) + { + CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() ); + if ( !pPlayer ) + return; + + pPlayer->DoAnimationEvent( PLAYERANIMEVENT_THROW_GRENADE ); + + bool bThrow = true; + + DODRoundState state = DODGameRules()->State_Get(); + + // If the player is holding a nade that is going to explode + // and the round is over, not allowing them to throw it + // just don't emit a grenade. + if ( dod_bonusround.GetBool() ) + { + int team = pPlayer->GetTeamNumber(); + + if ( ( team == TEAM_ALLIES && state == STATE_AXIS_WIN ) || + ( team == TEAM_AXIS && state == STATE_ALLIES_WIN ) ) + { + bThrow = false; + } + } + + if ( bThrow ) + ThrowGrenade(true); + + m_bRedraw = true; + m_bPinPulled = false; + SetArmed( false ); + + DecrementAmmo( pPlayer ); + + SendWeaponAnim( ACT_VM_THROW ); + } + + ConVar dod_grenadespeed( "dod_grenadespeed", "4.2", FCVAR_CHEAT ); + ConVar dod_grenademaxspeed( "dod_grenademaxspeed", "1400", FCVAR_CHEAT ); + ConVar dod_grenademinspeed( "dod_grenademinspeed", "500", FCVAR_CHEAT ); + + //----------------------------------------------------------------------------- + // Purpose: + //----------------------------------------------------------------------------- + void CWeaponDODBaseGrenade::ThrowGrenade( bool bDrop ) + { + CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); + if ( !pPlayer ) + { + Assert( false ); + return; + } + + QAngle angThrow = pPlayer->LocalEyeAngles(); + + Vector vForward, vRight, vUp; + + if( angThrow.x > 180 ) + angThrow.x -= 360; + + if (angThrow.x < 0) + angThrow.x = -10 + angThrow.x * ((90 - 10) / 90.0); + else + angThrow.x = -10 + angThrow.x * ((90 + 10) / 90.0); + + AngleVectors( angThrow, &vForward, &vRight, &vUp ); + + Vector eyes = pPlayer->GetAbsOrigin() + pPlayer->GetViewOffset(); + Vector vecSrc = eyes + vForward * 16; + + // Start with the player's velocity as the grenade vel + Vector vecPlayerVel; + pPlayer->GetVelocity( &vecPlayerVel, NULL ); + + // Get player angles, not eye angles! + QAngle angPlayerAngles = pPlayer->GetAbsAngles(); + Vector vecPlayerForward; + AngleVectors( angPlayerAngles, &vecPlayerForward ); + Vector vecThrow = DotProduct( vecPlayerVel, vecPlayerForward ) * vecPlayerForward; + + if( bDrop ) + { + vecThrow = vForward; + } + else // we are throwing the grenade + { + // change the speed depending on the throw angle + // straight down is 0%, straight up is 100%, linear between + float flSpeed = ( 90 - angThrow.x ) * dod_grenadespeed.GetFloat(); + + //Msg( "speed %.f\n", flSpeed ); + + flSpeed = clamp( flSpeed, dod_grenademinspeed.GetFloat(), dod_grenademaxspeed.GetFloat() ); + + vecThrow += vForward * flSpeed; + } + + trace_t tr; + UTIL_TraceLine( eyes, vecSrc, MASK_SOLID, NULL, COLLISION_GROUP_NONE, &tr ); + + // don't go into the ground + if( tr.fraction < 1.0 ) + { + vecSrc = tr.endpos; + } + + float flTimeLeft; + + if ( IsArmed() ) + flTimeLeft = MAX( 0, m_flDetonateTime - gpGlobals->curtime ); + else + flTimeLeft = GetDetonateTimerLength(); + + EmitGrenade( vecSrc, vec3_angle, vecThrow, AngularImpulse(600,random->RandomInt(-1200,1200),0), pPlayer, flTimeLeft ); + + pPlayer->EmitSound( "Weapon_Grenade.Throw" ); + +#ifndef CLIENT_DLL + IGameEvent * event = gameeventmanager->CreateEvent( "dod_stats_weapon_attack" ); + if ( event ) + { + event->SetInt( "attacker", pPlayer->GetUserID() ); + event->SetInt( "weapon", GetStatsWeaponID() ); + + gameeventmanager->FireEvent( event ); + } +#endif //CLIENT_DLL + } + + //----------------------------------------------------------------------------- + // Purpose: + //----------------------------------------------------------------------------- + void CWeaponDODBaseGrenade::EmitGrenade( Vector vecSrc, QAngle vecAngles, Vector vecVel, AngularImpulse angImpulse, CBasePlayer *pPlayer, float flLifeTime /* = GRENADE_FUSE_LENGTH */ ) + { + Assert( 0 && "CBaseCSGrenade::EmitGrenade should not be called. Make sure to implement this in your subclass!\n" ); + } + + //----------------------------------------------------------------------------- + // Purpose: + //----------------------------------------------------------------------------- + bool CWeaponDODBaseGrenade::AllowsAutoSwitchFrom( void ) const + { + return ( m_bPinPulled == false ); + } + + void CWeaponDODBaseGrenade::InputSetDetonateTime( inputdata_t &inputdata ) + { + SetDetonateTime( inputdata.value.Float() ); + } + +#endif // !CLIENT_DLL + +Activity CWeaponDODBaseGrenade::GetIdleActivity( void ) +{ + if ( IsArmed() ) + return ACT_VM_IDLE_EMPTY; + else + return ACT_VM_IDLE; +} + +Activity CWeaponDODBaseGrenade::GetPrimaryAttackActivity( void ) +{ + if ( IsArmed() ) + return ACT_VM_PRIMARYATTACK_EMPTY; + else + return ACT_VM_PULLPIN; +} + +Activity CWeaponDODBaseGrenade::GetDrawActivity( void ) +{ + if ( IsArmed() ) + return ACT_VM_DRAW_EMPTY; + else + return ACT_VM_DRAW; +} + |