You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
327 lines
9.6 KiB
327 lines
9.6 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: Burst rifle & Shield combo |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
#include "cbase.h" |
|
#include "basetfplayer_shared.h" |
|
#include "weapon_combatshield.h" |
|
#include "weapon_combat_usedwithshieldbase.h" |
|
#include "in_buttons.h" |
|
#include "plasmaprojectile.h" |
|
#include "IEffects.h" |
|
|
|
#if defined( CLIENT_DLL ) |
|
#include "fx.h" |
|
|
|
#define CWeaponCombatBurstRifle C_WeaponCombatBurstRifle |
|
|
|
#endif |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
|
|
// Damage CVars |
|
ConVar weapon_combat_burstrifle_damage( "weapon_combat_burstrifle_damage","10", FCVAR_REPLICATED, "Burst Rifle damage" ); |
|
ConVar weapon_combat_burstrifle_range( "weapon_combat_burstrifle_range","500", FCVAR_REPLICATED, "Burst Rifle maximum range" ); |
|
ConVar weapon_combat_burstrifle_ducking_mod( "weapon_combat_burstrifle_ducking_mod", "0.75", FCVAR_REPLICATED, "Burst Rifle ducking speed modifier" ); |
|
|
|
#define MAX_RIFLE_POWER 3.0 |
|
#define RIFLE_CHARGE_TIME 2.0 |
|
#define BURSTRIFLE_BOOSTED_FIRERATE 0.015f |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
class CWeaponCombatBurstRifle : public CWeaponCombatUsedWithShieldBase |
|
{ |
|
DECLARE_CLASS( CWeaponCombatBurstRifle, CWeaponCombatUsedWithShieldBase ); |
|
public: |
|
DECLARE_NETWORKCLASS(); |
|
DECLARE_PREDICTABLE(); |
|
|
|
CWeaponCombatBurstRifle( void ); |
|
|
|
virtual void ItemPostFrame( void ); |
|
virtual void PrimaryAttack( void ); |
|
virtual float GetFireRate( void ); |
|
virtual float GetDefaultAnimSpeed( void ); |
|
virtual const Vector& GetBulletSpread( void ); |
|
|
|
// All predicted weapons need to implement and return true |
|
virtual bool IsPredicted( void ) const |
|
{ |
|
return true; |
|
} |
|
private: |
|
CWeaponCombatBurstRifle( const CWeaponCombatBurstRifle & ); |
|
|
|
public: |
|
#if defined( CLIENT_DLL ) |
|
virtual bool ShouldPredict( void ) |
|
{ |
|
if ( GetOwner() && |
|
GetOwner() == C_BasePlayer::GetLocalPlayer() ) |
|
return true; |
|
|
|
return BaseClass::ShouldPredict(); |
|
} |
|
|
|
void GetViewmodelBoneControllers( C_BaseViewModel *pViewModel, float controllers[MAXSTUDIOBONECTRLS]); |
|
void ViewModelDrawn( C_BaseViewModel *pViewModel ); |
|
|
|
private: |
|
|
|
void BoostedMuzzleFlash( C_BaseViewModel *pViewModel, const Vector &vecOrigin, const QAngle &angle, float flScale ); |
|
|
|
struct model_t *m_pSpriteBurstRifleFlash[5]; |
|
|
|
#endif |
|
}; |
|
|
|
CWeaponCombatBurstRifle::CWeaponCombatBurstRifle( void ) |
|
{ |
|
SetPredictionEligible( true ); |
|
} |
|
|
|
IMPLEMENT_NETWORKCLASS_ALIASED( WeaponCombatBurstRifle, DT_WeaponCombatBurstRifle ) |
|
|
|
BEGIN_NETWORK_TABLE( CWeaponCombatBurstRifle, DT_WeaponCombatBurstRifle ) |
|
END_NETWORK_TABLE() |
|
|
|
BEGIN_PREDICTION_DATA( CWeaponCombatBurstRifle ) |
|
END_PREDICTION_DATA() |
|
|
|
LINK_ENTITY_TO_CLASS( weapon_combat_burstrifle, CWeaponCombatBurstRifle ); |
|
PRECACHE_WEAPON_REGISTER(weapon_combat_burstrifle); |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CWeaponCombatBurstRifle::ItemPostFrame( void ) |
|
{ |
|
CBaseTFPlayer *pOwner = ToBaseTFPlayer( GetOwner() ); |
|
if (!pOwner) |
|
return; |
|
|
|
if ( UsesClipsForAmmo1() ) |
|
{ |
|
CheckReload(); |
|
} |
|
|
|
// 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: Get the accuracy derived from weapon and player, and return it |
|
//----------------------------------------------------------------------------- |
|
const Vector& CWeaponCombatBurstRifle::GetBulletSpread( void ) |
|
{ |
|
static Vector cone = VECTOR_CONE_5DEGREES; |
|
return cone; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CWeaponCombatBurstRifle::PrimaryAttack( void ) |
|
{ |
|
CBaseTFPlayer *pPlayer = (CBaseTFPlayer*)GetOwner(); |
|
if (!pPlayer) |
|
return; |
|
|
|
WeaponSound(SINGLE); |
|
|
|
// Fire the bullets |
|
Vector vecSrc = pPlayer->Weapon_ShootPosition( ); |
|
Vector vecSpread = GetBulletSpread(); |
|
Vector vecAiming, vecRight, vecUp; |
|
pPlayer->EyeVectors( &vecAiming, &vecRight, &vecUp ); |
|
|
|
// Add some inaccuracy |
|
int seed = 0; |
|
float x, y, z; |
|
do |
|
{ |
|
float x1, x2, y1, y2; |
|
|
|
// Note the additional seed because otherwise we get the same set of random #'s and will get stuck |
|
// in an infinite loop here potentially |
|
// FIXME: Can we use a gaussian random # function instead? ywb |
|
x1 = SHARED_RANDOMFLOAT_SEED( -0.5, 0.5, ++seed ); |
|
x2 = SHARED_RANDOMFLOAT_SEED( -0.5, 0.5, ++seed ); |
|
y1 = SHARED_RANDOMFLOAT_SEED( -0.5, 0.5, ++seed ); |
|
y2 = SHARED_RANDOMFLOAT_SEED( -0.5, 0.5, ++seed ); |
|
|
|
x = x1 + x2; |
|
y = y1 + y2; |
|
|
|
z = x*x+y*y; |
|
} while (z > 1); |
|
Vector vecDir = vecAiming + x * vecSpread.x * vecRight + y * vecSpread.y * vecUp; |
|
|
|
PlayAttackAnimation( GetPrimaryAttackActivity() ); |
|
|
|
// Shift it down a bit so the firer can see it |
|
Vector right, forward; |
|
AngleVectors( pPlayer->EyeAngles() + pPlayer->m_Local.m_vecPunchAngle, &forward, &right, NULL ); |
|
Vector vecStartSpot = vecSrc; |
|
|
|
// Get the firing position |
|
#ifdef CLIENT_DLL |
|
// On our client, grab the viewmodel's firing position |
|
Vector vecWorldOffset = vecStartSpot + Vector(0,0,-8) + right * 12 + forward * 16; |
|
#else |
|
// For everyone else, grab the weapon model's position |
|
/* |
|
Vector vecWorldOffset; |
|
QAngle angIgnore; |
|
GetAttachment( LookupAttachment( "muzzle" ), vecWorldOffset, angIgnore ); |
|
*/ |
|
|
|
Vector vecWorldOffset = vecStartSpot + Vector(0,0,-8) + right * 12 + forward * 16; |
|
#endif |
|
Vector gunOffset = vecWorldOffset - vecStartSpot; |
|
|
|
CPowerPlasmaProjectile *pPlasma = CPowerPlasmaProjectile::CreatePredicted( vecStartSpot, vecDir, gunOffset, DMG_ENERGYBEAM, pPlayer ); |
|
if ( pPlasma ) |
|
{ |
|
pPlasma->SetDamage( weapon_combat_burstrifle_damage.GetFloat() ); |
|
pPlasma->m_hOwner = pPlayer; |
|
pPlasma->SetPower( 2.0 ); |
|
pPlasma->SetMaxRange( weapon_combat_burstrifle_range.GetFloat() ); |
|
pPlasma->Activate(); |
|
} |
|
|
|
m_flNextPrimaryAttack = gpGlobals->curtime + GetFireRate(); |
|
m_iClip1 = m_iClip1 - 1; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
float CWeaponCombatBurstRifle::GetFireRate( void ) |
|
{ |
|
if ( !inv_demo.GetFloat() ) |
|
{ |
|
float flFireRate = ( SequenceDuration() * 0.6f ) + 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_burstrifle_ducking_mod.GetFloat(); |
|
} |
|
} |
|
|
|
return flFireRate; |
|
} |
|
|
|
// Get the player and check to see if we are powered up. |
|
CBaseTFPlayer *pPlayer = ( CBaseTFPlayer* )GetOwner(); |
|
if ( pPlayer && pPlayer->HasPowerup( POWERUP_BOOST ) ) |
|
{ |
|
return BURSTRIFLE_BOOSTED_FIRERATE; |
|
} |
|
|
|
return SHARED_RANDOMFLOAT( 0.075f, 0.15f ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Match the anim speed to the weapon speed while crouching |
|
//----------------------------------------------------------------------------- |
|
float CWeaponCombatBurstRifle::GetDefaultAnimSpeed( void ) |
|
{ |
|
if ( GetOwner() && GetOwner()->IsPlayer() ) |
|
{ |
|
if ( GetOwner()->GetFlags() & FL_DUCKING ) |
|
return (1.0 + (1.0 - weapon_combat_burstrifle_ducking_mod.GetFloat()) ); |
|
} |
|
|
|
return 1.0; |
|
} |
|
|
|
#if defined ( CLIENT_DLL ) |
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CWeaponCombatBurstRifle::GetViewmodelBoneControllers( C_BaseViewModel *pViewModel, |
|
float controllers[MAXSTUDIOBONECTRLS]) |
|
{ |
|
float flAmmoCount; |
|
C_BaseTFPlayer *pPlayer = ( C_BaseTFPlayer* )GetOwner(); |
|
if ( pPlayer && pPlayer->IsDamageBoosted() ) |
|
{ |
|
flAmmoCount = random->RandomFloat( 0.0f, 1.0f ); |
|
} |
|
else |
|
{ |
|
// Dial shows ammo count! |
|
flAmmoCount = ( float )m_iClip1 / ( float )GetMaxClip1(); |
|
} |
|
|
|
// Add some shake |
|
flAmmoCount += RandomFloat( -0.02, 0.02 ); |
|
controllers[0] = flAmmoCount; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CWeaponCombatBurstRifle::ViewModelDrawn( C_BaseViewModel *pViewModel ) |
|
{ |
|
C_BaseTFPlayer *pPlayer = ( C_BaseTFPlayer* )GetOwner(); |
|
if ( pPlayer && pPlayer->IsDamageBoosted() ) |
|
{ |
|
Vector vecBarrelPos; |
|
QAngle angMuzzle; |
|
int iAttachment = pViewModel->LookupAttachment( "muzzle" ); |
|
pViewModel->GetAttachment( iAttachment, vecBarrelPos, angMuzzle ); |
|
|
|
unsigned char color[3]; |
|
color[0] = 50; |
|
color[1] = 128; |
|
color[2] = 50; |
|
FX_Smoke( vecBarrelPos, angMuzzle, 0.5, 1, &color[0], 192 ); |
|
} |
|
} |
|
#endif
|
|
|