summaryrefslogtreecommitdiff
path: root/game/shared/tf2/weapon_combat_laserrifle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/shared/tf2/weapon_combat_laserrifle.cpp')
-rw-r--r--game/shared/tf2/weapon_combat_laserrifle.cpp375
1 files changed, 375 insertions, 0 deletions
diff --git a/game/shared/tf2/weapon_combat_laserrifle.cpp b/game/shared/tf2/weapon_combat_laserrifle.cpp
new file mode 100644
index 0000000..e751686
--- /dev/null
+++ b/game/shared/tf2/weapon_combat_laserrifle.cpp
@@ -0,0 +1,375 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Laser Rifle & Shield combo
+//
+// $NoKeywords: $
+//=============================================================================//
+#include "cbase.h"
+#include "weapon_combatshield.h"
+#include "weapon_combat_usedwithshieldbase.h"
+#include "in_buttons.h"
+#include "takedamageinfo.h"
+#include "beam_shared.h"
+#include "tf_gamerules.h"
+
+// Damage CVars
+ConVar weapon_combat_laserrifle_damage( "weapon_combat_laserrifle_damage","20", FCVAR_REPLICATED, "Laser rifle damage" );
+ConVar weapon_combat_laserrifle_range( "weapon_combat_laserrifle_range","1000", FCVAR_REPLICATED, "Laser rifle maximum range" );
+ConVar weapon_combat_laserrifle_ducking_mod( "weapon_combat_laserrifle_ducking_mod", "0.75", FCVAR_REPLICATED, "Laser rifle ducking ROF modifier" );
+
+#if defined( CLIENT_DLL )
+#include "fx.h"
+#include "hud.h"
+#include "c_te_effect_dispatch.h"
+#include <vgui/ISurface.h>
+
+#define CWeaponCombatLaserRifle C_WeaponCombatLaserRifle
+
+#else
+
+#include "te_effect_dispatch.h"
+
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+class CWeaponCombatLaserRifle : public CWeaponCombatUsedWithShieldBase
+{
+ DECLARE_CLASS( CWeaponCombatLaserRifle, CWeaponCombatUsedWithShieldBase );
+public:
+ DECLARE_NETWORKCLASS();
+ DECLARE_PREDICTABLE();
+
+ CWeaponCombatLaserRifle( void );
+
+ virtual const Vector& GetBulletSpread( void );
+ virtual void ItemBusyFrame( void );
+ virtual void ItemPostFrame( void );
+ virtual void PrimaryAttack( void );
+ virtual float GetFireRate( void );
+ virtual float GetDefaultAnimSpeed( void );
+ virtual void BulletWasFired( const Vector &vecStart, const Vector &vecEnd );
+
+ void RecalculateAccuracy( void );
+
+ // All predicted weapons need to implement and return true
+ virtual bool IsPredicted( void ) const
+ {
+ return true;
+ }
+private:
+ CWeaponCombatLaserRifle( const CWeaponCombatLaserRifle & );
+
+public:
+#if defined( CLIENT_DLL )
+ virtual bool ShouldPredict( void )
+ {
+ if ( GetOwner() &&
+ GetOwner() == C_BasePlayer::GetLocalPlayer() )
+ return true;
+
+ return BaseClass::ShouldPredict();
+ }
+ virtual void DrawCrosshair( void );
+#endif
+
+private:
+ float m_flInaccuracy;
+ float m_flAccuracyTime;
+};
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CWeaponCombatLaserRifle::CWeaponCombatLaserRifle( void )
+{
+ SetPredictionEligible( true );
+ m_flInaccuracy = 0;
+ m_flAccuracyTime = 0;
+}
+
+IMPLEMENT_NETWORKCLASS_ALIASED( WeaponCombatLaserRifle, DT_WeaponCombatLaserRifle )
+
+BEGIN_NETWORK_TABLE( CWeaponCombatLaserRifle, DT_WeaponCombatLaserRifle )
+END_NETWORK_TABLE()
+
+BEGIN_PREDICTION_DATA( CWeaponCombatLaserRifle )
+END_PREDICTION_DATA()
+
+LINK_ENTITY_TO_CLASS( weapon_combat_laserrifle, CWeaponCombatLaserRifle );
+PRECACHE_WEAPON_REGISTER(weapon_combat_laserrifle);
+
+//-----------------------------------------------------------------------------
+// Purpose: Get the accuracy derived from weapon and player, and return it
+//-----------------------------------------------------------------------------
+const Vector& CWeaponCombatLaserRifle::GetBulletSpread( void )
+{
+ static Vector cone = VECTOR_CONE_8DEGREES;
+ return cone;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponCombatLaserRifle::ItemBusyFrame( void )
+{
+ BaseClass::ItemBusyFrame();
+
+ RecalculateAccuracy();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponCombatLaserRifle::ItemPostFrame( void )
+{
+ CBaseTFPlayer *pOwner = ToBaseTFPlayer( GetOwner() );
+ if (!pOwner)
+ return;
+
+ if ( UsesClipsForAmmo1() )
+ {
+ CheckReload();
+ }
+
+ RecalculateAccuracy();
+
+ // Handle firing
+ if ( GetShieldState() == SS_DOWN && !m_bInReload )
+ {
+ if ( (pOwner->m_nButtons & IN_ATTACK ) && (m_flNextPrimaryAttack <= gpGlobals->curtime) )
+ {
+ if ( m_iClip1 > 0 )
+ {
+ // Fire the plasma shot
+ PrimaryAttack();
+ }
+ else
+ {
+ Reload();
+ }
+ }
+
+ // Reload button (or fire button when we're out of ammo)
+ if ( m_flNextPrimaryAttack <= gpGlobals->curtime )
+ {
+ if ( pOwner->m_nButtons & IN_RELOAD )
+ {
+ Reload();
+ }
+ else if ( !((pOwner->m_nButtons & IN_ATTACK) || (pOwner->m_nButtons & IN_ATTACK2) || (pOwner->m_nButtons & IN_RELOAD)) )
+ {
+ if ( !m_iClip1 && HasPrimaryAmmo() )
+ {
+ Reload();
+ }
+ }
+ }
+ }
+
+ // Prevent shield post frame if we're not ready to attack, or we're charging
+ AllowShieldPostFrame( m_flNextPrimaryAttack <= gpGlobals->curtime || m_bInReload );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponCombatLaserRifle::PrimaryAttack( void )
+{
+ CBaseTFPlayer *pPlayer = (CBaseTFPlayer*)GetOwner();
+ if (!pPlayer)
+ return;
+
+ WeaponSound(SINGLE);
+
+ // Fire the bullets
+ Vector vecSrc = pPlayer->Weapon_ShootPosition( );
+ Vector vecAiming;
+ pPlayer->EyeVectors( &vecAiming );
+
+ PlayAttackAnimation( GetPrimaryAttackActivity() );
+
+ // Reduce the spread if the player's ducking
+ Vector vecSpread = GetBulletSpread();
+ vecSpread *= m_flInaccuracy;
+
+ TFGameRules()->FireBullets( CTakeDamageInfo( this, pPlayer, weapon_combat_laserrifle_damage.GetFloat(), DMG_PLASMA), 1,
+ vecSrc, vecAiming, vecSpread, weapon_combat_laserrifle_range.GetFloat(), m_iPrimaryAmmoType, 0, entindex(), 0 );
+
+ m_flInaccuracy += 0.3;
+ m_flInaccuracy = clamp(m_flInaccuracy, 0, 1);
+
+ m_flNextPrimaryAttack = gpGlobals->curtime + GetFireRate();
+ m_iClip1 = m_iClip1 - 1;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+float CWeaponCombatLaserRifle::GetFireRate( void )
+{
+ float flFireRate = ( SequenceDuration() * 0.4 ) + SHARED_RANDOMFLOAT( 0.0, 0.035f );
+
+ CBaseTFPlayer *pPlayer = static_cast<CBaseTFPlayer*>( GetOwner() );
+ if ( pPlayer )
+ {
+ // Ducking players should fire more rapidly.
+ if ( pPlayer->GetFlags() & FL_DUCKING )
+ {
+ flFireRate *= weapon_combat_laserrifle_ducking_mod.GetFloat();
+ }
+ }
+
+ return flFireRate;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponCombatLaserRifle::RecalculateAccuracy( void )
+{
+ CBaseTFPlayer *pPlayer = (CBaseTFPlayer*)GetOwner();
+ if (!pPlayer)
+ return;
+
+ m_flAccuracyTime += gpGlobals->frametime;
+
+ while ( m_flAccuracyTime > 0.05 )
+ {
+ if ( !(pPlayer->GetFlags() & FL_ONGROUND) )
+ {
+ m_flInaccuracy += 0.05;
+ }
+ else if ( pPlayer->GetFlags() & FL_DUCKING )
+ {
+ m_flInaccuracy -= 0.08;
+ }
+/*
+ else if ( pPlayer->GetLocalVelocity().LengthSqr() > (100*100) )
+ {
+ // Never get worse than 1/2 accuracy from running
+ if ( m_flInaccuracy < 0.25 )
+ {
+ m_flInaccuracy += 0.01;
+ if ( m_flInaccuracy > 0.5 )
+ {
+ m_flInaccuracy = 0.5;
+ }
+ }
+ else if ( m_flInaccuracy > 0.25 )
+ {
+ m_flInaccuracy -= 0.01;
+ }
+ }
+*/
+ else
+ {
+ m_flInaccuracy -= 0.04;
+ }
+
+ // Crouching prevents accuracy ever going beyond a point
+ if ( pPlayer->GetFlags() & FL_DUCKING )
+ {
+ m_flInaccuracy = clamp(m_flInaccuracy, 0, 0.8);
+ }
+ else
+ {
+ m_flInaccuracy = clamp(m_flInaccuracy, 0, 1);
+ }
+
+ m_flAccuracyTime -= 0.05;
+
+#ifndef CLIENT_DLL
+ //if ( m_flInaccuracy )
+ //Msg("Inaccuracy %.2f (%.2f)\n", m_flInaccuracy, gpGlobals->curtime );
+#endif
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Match the anim speed to the weapon speed while crouching
+//-----------------------------------------------------------------------------
+float CWeaponCombatLaserRifle::GetDefaultAnimSpeed( void )
+{
+ if ( GetOwner() && GetOwner()->IsPlayer() )
+ {
+ if ( GetOwner()->GetFlags() & FL_DUCKING )
+ return (1.0 + (1.0 - weapon_combat_laserrifle_ducking_mod.GetFloat()) );
+ }
+
+ return 1.0;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Draw the laser rifle effect
+//-----------------------------------------------------------------------------
+void CWeaponCombatLaserRifle::BulletWasFired( const Vector &vecStart, const Vector &vecEnd )
+{
+ // Humans fire jazzed up bullets, Aliens fire laserbeams
+ if ( GetTeamNumber() == TEAM_HUMANS )
+ {
+ UTIL_Tracer( (Vector&)vecStart, (Vector&)vecEnd, entindex(), 1, 5000, false, "HLaserTracer" );
+ }
+ else
+ {
+ UTIL_Tracer( (Vector&)vecStart, (Vector&)vecEnd, entindex(), 1, 5000, false, "ALaserTracer" );
+ }
+}
+
+#ifdef CLIENT_DLL
+//-----------------------------------------------------------------------------
+// Purpose: Draw the weapon's crosshair
+//-----------------------------------------------------------------------------
+void CWeaponCombatLaserRifle::DrawCrosshair( void )
+{
+ BaseClass::DrawCrosshair();
+
+ // Draw the targeting zone around the crosshair
+ int r, g, b, a;
+ gHUD.m_clrYellowish.GetColor( r, g, b, a );
+
+ // Check to see if we are in vgui mode
+ C_BaseTFPlayer *pPlayer = static_cast<C_BaseTFPlayer*>( GetOwner() );
+ if ( !pPlayer || pPlayer->IsInVGuiInputMode() )
+ return;
+
+ // Draw a crosshair & accuracy hoodad
+ int iBarWidth = XRES(10);
+ int iBarHeight = YRES(10);
+ int iTotalWidth = (iBarWidth * 2) + (40 * m_flInaccuracy) + XRES(10);
+ int iTotalHeight = (iBarHeight * 2) + (40 * m_flInaccuracy) + YRES(10);
+
+ // Horizontal bars
+ int iLeft = (ScreenWidth() - iTotalWidth) / 2;
+ int iMidHeight = (ScreenHeight() / 2);
+
+ Color dark( r, g, b, 32 );
+ Color light( r, g, b, 160 );
+
+ vgui::surface()->DrawSetColor( dark );
+
+ vgui::surface()->DrawFilledRect( iLeft, iMidHeight-1, iLeft+ iBarWidth, iMidHeight + 2 );
+ vgui::surface()->DrawFilledRect( iLeft + iTotalWidth - iBarWidth, iMidHeight-1, iLeft + iTotalWidth, iMidHeight + 2 );
+
+ vgui::surface()->DrawSetColor( light );
+
+ vgui::surface()->DrawFilledRect( iLeft, iMidHeight, iLeft + iBarWidth, iMidHeight + 1 );
+ vgui::surface()->DrawFilledRect( iLeft + iTotalWidth - iBarWidth, iMidHeight, iLeft + iTotalWidth, iMidHeight + 1 );
+
+ // Vertical bars
+ int iTop = (ScreenHeight() - iTotalHeight) / 2;
+ int iMidWidth = (ScreenWidth() / 2);
+
+ vgui::surface()->DrawSetColor( dark );
+
+ vgui::surface()->DrawFilledRect( iMidWidth-1, iTop, iMidWidth + 2, iTop + iBarHeight );
+ vgui::surface()->DrawFilledRect( iMidWidth-1, iTop + iTotalHeight - iBarHeight, iMidWidth + 2, iTop + iTotalHeight );
+
+ vgui::surface()->DrawSetColor( light );
+
+ vgui::surface()->DrawFilledRect( iMidWidth, iTop, iMidWidth + 1, iTop + iBarHeight );
+ vgui::surface()->DrawFilledRect( iMidWidth, iTop + iTotalHeight - iBarHeight, iMidWidth + 1, iTop + iTotalHeight );
+}
+#endif \ No newline at end of file