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.
322 lines
8.8 KiB
322 lines
8.8 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: Chargeable Plasma & Shield combo |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
#include "cbase.h" |
|
#include "tf_player.h" |
|
#include "weapon_combat_usedwithshieldbase.h" |
|
#include "weapon_combatshield.h" |
|
#include "tf_guidedplasma.h" |
|
#include "in_buttons.h" |
|
#include "tf_gamerules.h" |
|
|
|
#define BURST_FIRE_RATE 0.15 |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
class CWeaponCombat_ChargeablePlasma : public CWeaponCombatUsedWithShieldBase |
|
{ |
|
DECLARE_CLASS( CWeaponCombat_ChargeablePlasma, CWeaponCombatUsedWithShieldBase ); |
|
public: |
|
DECLARE_SERVERCLASS(); |
|
|
|
virtual void ItemPostFrame( void ); |
|
virtual void PrimaryAttack( void ); |
|
virtual float GetFireRate( void ); |
|
virtual void Spawn(); |
|
virtual bool Deploy( void ); |
|
virtual bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); |
|
virtual void Precache( void ); |
|
virtual void GainedNewTechnology( CBaseTechnology *pTechnology ); |
|
virtual CBaseEntity *GetLockTarget( void ); |
|
|
|
private: |
|
CNetworkVar( bool, m_bCharging ); |
|
float m_flChargeStartTime; |
|
float m_flPower; |
|
float m_flNextBurstShotTime; |
|
int m_iBurstShotsRemaining; |
|
bool m_bHasBurstShot; |
|
bool m_bHasCharge; |
|
|
|
// Guidance |
|
EHANDLE m_hLockTarget; |
|
Vector m_vecTargetOffset; |
|
float m_flLockedAt; |
|
}; |
|
|
|
IMPLEMENT_SERVERCLASS_ST(CWeaponCombat_ChargeablePlasma, DT_WeaponCombat_ChargeablePlasma ) |
|
SendPropInt( SENDINFO( m_bCharging ), 1, SPROP_UNSIGNED ), |
|
END_SEND_TABLE() |
|
|
|
LINK_ENTITY_TO_CLASS( weapon_combat_chargeableplasma, CWeaponCombat_ChargeablePlasma ); |
|
PRECACHE_WEAPON_REGISTER(weapon_combat_chargeableplasma); |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Spawn weapon |
|
//----------------------------------------------------------------------------- |
|
void CWeaponCombat_ChargeablePlasma::Spawn() |
|
{ |
|
BaseClass::Spawn(); |
|
m_bHasBurstShot = false; |
|
m_bHasCharge = false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CWeaponCombat_ChargeablePlasma::Precache( void ) |
|
{ |
|
BaseClass::Precache(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// New technologies: |
|
//----------------------------------------------------------------------------- |
|
void CWeaponCombat_ChargeablePlasma::GainedNewTechnology( CBaseTechnology *pTechnology ) |
|
{ |
|
BaseClass::GainedNewTechnology( pTechnology ); |
|
|
|
CBaseTFPlayer *pPlayer = ToBaseTFPlayer( (CBaseEntity*)GetOwner() ); |
|
if ( pPlayer ) |
|
{ |
|
// Charge-up mode? |
|
if ( pPlayer->HasNamedTechnology( "com_comboshield_charge" ) ) |
|
{ |
|
m_bHasCharge = true; |
|
} |
|
else |
|
{ |
|
m_bHasCharge = false; |
|
} |
|
|
|
// Burst shot mode? |
|
if ( pPlayer->HasNamedTechnology( "com_comboshield_tripleshot" ) ) |
|
{ |
|
m_bHasBurstShot = true; |
|
} |
|
else |
|
{ |
|
m_bHasBurstShot = false; |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CWeaponCombat_ChargeablePlasma::ItemPostFrame( void ) |
|
{ |
|
CBaseTFPlayer *pOwner = ToBaseTFPlayer( GetOwner() ); |
|
if (!pOwner) |
|
return; |
|
|
|
if ( UsesClipsForAmmo1() ) |
|
{ |
|
CheckReload(); |
|
} |
|
|
|
// If burst shots are firing, ignore input |
|
if ( m_iBurstShotsRemaining > 0 ) |
|
{ |
|
if ( gpGlobals->curtime < m_flNextBurstShotTime ) |
|
return; |
|
|
|
if ( m_iClip1 > 0 ) |
|
{ |
|
PrimaryAttack(); |
|
} |
|
|
|
m_iBurstShotsRemaining--; |
|
m_flNextBurstShotTime = gpGlobals->curtime + BURST_FIRE_RATE; |
|
m_flNextPrimaryAttack = gpGlobals->curtime + GetFireRate(); |
|
return; |
|
} |
|
|
|
// Handle charge firing |
|
if ( m_iClip1 > 0 && GetShieldState() == SS_DOWN && !m_bInReload ) |
|
{ |
|
if ( (pOwner->m_nButtons & IN_ATTACK ) ) |
|
{ |
|
if (m_bHasCharge) |
|
{ |
|
if ( !m_bCharging && (m_flNextPrimaryAttack <= gpGlobals->curtime) ) |
|
{ |
|
m_bCharging = true; |
|
m_flChargeStartTime = gpGlobals->curtime; |
|
|
|
// Get a lock target right now |
|
m_hLockTarget = GetLockTarget(); |
|
} |
|
} |
|
else |
|
{ |
|
// Fire the plasma shot |
|
if (m_flNextPrimaryAttack <= gpGlobals->curtime) |
|
PrimaryAttack(); |
|
} |
|
} |
|
else if ( m_bCharging ) |
|
{ |
|
m_bCharging = false; |
|
|
|
// Fire the plasma shot |
|
PrimaryAttack(); |
|
|
|
// We might be firing a burst shot |
|
if (m_bHasBurstShot) |
|
{ |
|
if ( m_flPower >= (MAX_CHARGED_TIME * 0.5) ) |
|
{ |
|
if ( m_flPower >= MAX_CHARGED_TIME ) |
|
{ |
|
m_iBurstShotsRemaining = 2; |
|
} |
|
else |
|
{ |
|
m_iBurstShotsRemaining = 1; |
|
} |
|
|
|
m_flNextBurstShotTime = gpGlobals->curtime + BURST_FIRE_RATE; |
|
} |
|
} |
|
} |
|
} |
|
|
|
// Reload button |
|
if ( m_iBurstShotsRemaining == 0 && !m_bCharging ) |
|
{ |
|
if ( pOwner->m_nButtons & IN_RELOAD && UsesClipsForAmmo1() && !m_bInReload ) |
|
{ |
|
Reload(); |
|
} |
|
} |
|
|
|
// Prevent shield post frame if we're not ready to attack, or we're charging |
|
AllowShieldPostFrame( !m_bCharging && ((m_flNextPrimaryAttack <= gpGlobals->curtime) || m_bInReload) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CWeaponCombat_ChargeablePlasma::PrimaryAttack( void ) |
|
{ |
|
CBaseTFPlayer *pPlayer = (CBaseTFPlayer*)GetOwner(); |
|
if (!pPlayer) |
|
return; |
|
|
|
WeaponSound(SINGLE); |
|
|
|
// Fire the bullets |
|
Vector vecSrc = pPlayer->Weapon_ShootPosition( ); |
|
Vector vecAiming; |
|
pPlayer->EyeVectors( &vecAiming ); |
|
|
|
// If we already have a lock target from button down, see if we shouldn't try and get a new one |
|
// Only do this is the button was released immediately |
|
if ( !m_hLockTarget || ( m_flLockedAt < gpGlobals->curtime ) ) |
|
{ |
|
m_hLockTarget = GetLockTarget(); |
|
} |
|
|
|
PlayAttackAnimation( GetPrimaryAttackActivity() ); |
|
|
|
// Shift it down a bit so the firer can see it |
|
Vector right; |
|
AngleVectors( pPlayer->EyeAngles() + pPlayer->m_Local.m_vecPunchAngle, NULL, &right, NULL ); |
|
Vector vecStartSpot = vecSrc + Vector(0,0,-8) + right * 12; |
|
|
|
CGuidedPlasma *pShot = CGuidedPlasma::Create(vecStartSpot, vecAiming, m_hLockTarget, m_vecTargetOffset, pPlayer); |
|
|
|
// Set it's charged power level |
|
if (m_bHasCharge) |
|
m_flPower = MIN( MAX_CHARGED_TIME, gpGlobals->curtime - m_flChargeStartTime ); |
|
else |
|
m_flPower = 0.0f; |
|
|
|
float flDamageMult = RemapVal( m_flPower, 0, MAX_CHARGED_TIME, 1.0, MAX_CHARGED_POWER ); |
|
pShot->SetPowerLevel( flDamageMult ); |
|
|
|
m_flNextPrimaryAttack = gpGlobals->curtime + GetFireRate(); |
|
m_iClip1 = m_iClip1 - 1; |
|
m_hLockTarget = NULL; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
float CWeaponCombat_ChargeablePlasma::GetFireRate( void ) |
|
{ |
|
return SequenceDuration(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool CWeaponCombat_ChargeablePlasma::Deploy( void ) |
|
{ |
|
if ( BaseClass::Deploy() ) |
|
{ |
|
GainedNewTechnology(NULL); |
|
return true; |
|
} |
|
|
|
return false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Our player just died |
|
//----------------------------------------------------------------------------- |
|
bool CWeaponCombat_ChargeablePlasma::Holster( CBaseCombatWeapon *pSwitchingTo ) |
|
{ |
|
bool bReturn = BaseClass::Holster(pSwitchingTo); |
|
|
|
// Stop the charging sound |
|
if ( m_bCharging ) |
|
{ |
|
m_bCharging = false; |
|
} |
|
|
|
return bReturn; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Try and find an entity to lock onto |
|
//----------------------------------------------------------------------------- |
|
CBaseEntity *CWeaponCombat_ChargeablePlasma::GetLockTarget( void ) |
|
{ |
|
CBaseTFPlayer *pPlayer = (CBaseTFPlayer*)GetOwner(); |
|
if ( !pPlayer ) |
|
return NULL; |
|
|
|
Vector vecSrc = pPlayer->Weapon_ShootPosition( ); |
|
Vector vecAiming; |
|
pPlayer->EyeVectors( &vecAiming ); |
|
Vector vecEnd = vecSrc + vecAiming * MAX_TRACE_LENGTH; |
|
|
|
trace_t tr; |
|
TFGameRules()->WeaponTraceLine( vecSrc, vecEnd, MASK_SHOT, pPlayer, GetDamageType(), &tr ); |
|
|
|
if ( (tr.fraction < 1.0f) && tr.m_pEnt ) |
|
{ |
|
CBaseEntity *pTargetEntity = tr.m_pEnt; |
|
|
|
// Don't guide on same team or on anything other than players, objects, and NPCs |
|
if ( pTargetEntity->InSameTeam(pPlayer) || (!pTargetEntity->IsPlayer() |
|
&& (pTargetEntity->MyNPCPointer() == NULL)) ) |
|
return NULL; |
|
|
|
// Compute the target offset relative to the target |
|
Vector vecWorldOffset; |
|
VectorSubtract( tr.endpos, pTargetEntity->GetAbsOrigin(), vecWorldOffset ); |
|
VectorIRotate( vecWorldOffset, pTargetEntity->EntityToWorldTransform(), m_vecTargetOffset ); |
|
m_flLockedAt = gpGlobals->curtime + 0.2; |
|
return pTargetEntity; |
|
} |
|
|
|
return NULL; |
|
}
|
|
|