sqwarmed/sdk_src/game/shared/swarm/asw_weapon_grenades.cpp

256 lines
6.6 KiB
C++
Raw Normal View History

2024-08-29 19:18:30 -04:00
#include "cbase.h"
#include "asw_weapon_grenades.h"
#include "in_buttons.h"
#ifdef CLIENT_DLL
#include "c_asw_player.h"
#include "c_asw_weapon.h"
#include "c_asw_marine.h"
#include "prediction.h"
#else
#include "asw_marine.h"
#include "asw_player.h"
#include "asw_weapon.h"
#include "npcevent.h"
#include "shot_manipulator.h"
#include "asw_grenade_cluster.h"
#include "asw_marine_speech.h"
#include "asw_gamerules.h"
#endif
#include "asw_marine_skills.h"
#include "asw_util_shared.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define ASW_FLARES_FASTEST_REFIRE_TIME 0.1f
ConVar asw_grenade_throw_delay("asw_grenade_throw_delay", "0.15", FCVAR_REPLICATED | FCVAR_CHEAT, "Delay before grenade entity is spawned when throwing");
IMPLEMENT_NETWORKCLASS_ALIASED( ASW_Weapon_Grenades, DT_ASW_Weapon_Grenades )
BEGIN_NETWORK_TABLE( CASW_Weapon_Grenades, DT_ASW_Weapon_Grenades )
#ifdef CLIENT_DLL
// recvprops
#else
// sendprops
#endif
END_NETWORK_TABLE()
BEGIN_PREDICTION_DATA( CASW_Weapon_Grenades )
END_PREDICTION_DATA()
LINK_ENTITY_TO_CLASS( asw_weapon_grenades, CASW_Weapon_Grenades );
PRECACHE_WEAPON_REGISTER(asw_weapon_grenades);
#ifndef CLIENT_DLL
extern ConVar asw_debug_marine_damage;
//---------------------------------------------------------
// Save/Restore
//---------------------------------------------------------
BEGIN_DATADESC( CASW_Weapon_Grenades )
DEFINE_FIELD( m_flSoonestPrimaryAttack, FIELD_TIME ),
END_DATADESC()
#endif /* not client */
CASW_Weapon_Grenades::CASW_Weapon_Grenades()
{
m_fMinRange1 = 0;
m_fMaxRange1 = 2048;
m_fMinRange2 = 256;
m_fMaxRange2 = 1024;
m_flSoonestPrimaryAttack = gpGlobals->curtime;
}
CASW_Weapon_Grenades::~CASW_Weapon_Grenades()
{
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Activity
//-----------------------------------------------------------------------------
Activity CASW_Weapon_Grenades::GetPrimaryAttackActivity( void )
{
return ACT_VM_PRIMARYATTACK;
}
bool CASW_Weapon_Grenades::OffhandActivate()
{
if (!GetMarine() || GetMarine()->GetFlags() & FL_FROZEN) // don't allow this if the marine is frozen
return false;
PrimaryAttack();
return true;
}
#define FLARE_PROJECTILE_AIR_VELOCITY 400
void CASW_Weapon_Grenades::PrimaryAttack( void )
{
CASW_Player *pPlayer = GetCommander();
if (!pPlayer)
return;
CASW_Marine *pMarine = GetMarine();
bool bThisActive = (pMarine && pMarine->GetActiveWeapon() == this);
// grenade weapon is lost when all grenades are gone
if ( UsesClipsForAmmo1() && !m_iClip1 )
{
#ifndef CLIENT_DLL
if (pMarine)
{
pMarine->Weapon_Detach(this);
if (bThisActive)
pMarine->SwitchToNextBestWeapon(NULL);
}
Kill();
#endif
return;
}
if (pMarine && gpGlobals->curtime > m_flDelayedFire) // firing from a marine
{
#ifdef CLIENT_DLL
if ( !prediction->InPrediction() || prediction->IsFirstTimePredicted() )
{
pMarine->DoAnimationEvent( PLAYERANIMEVENT_THROW_GRENADE );
}
#else
pMarine->DoAnimationEvent( PLAYERANIMEVENT_THROW_GRENADE );
#endif
// start our delayed attack
m_bShotDelayed = true;
m_flNextPrimaryAttack = m_flNextSecondaryAttack = m_flDelayedFire = gpGlobals->curtime + asw_grenade_throw_delay.GetFloat();
if (!bThisActive && pMarine->GetActiveASWWeapon())
{
// if we're offhan activating, make sure our primary weapon can't fire until we're done
pMarine->GetActiveASWWeapon()->m_flNextPrimaryAttack = m_flNextPrimaryAttack + 0.4f;
pMarine->GetActiveASWWeapon()->m_bIsFiring = false;
}
}
}
#ifndef CLIENT_DLL
float CASW_Weapon_Grenades::GetBoomDamage( CASW_Marine *pMarine )
{
return MarineSkills()->GetSkillBasedValueByMarine(pMarine, ASW_MARINE_SKILL_GRENADES, ASW_MARINE_SUBSKILL_GRENADE_CLUSTER_DMG);
}
float CASW_Weapon_Grenades::GetBoomRadius( CASW_Marine *pMarine )
{
return MarineSkills()->GetSkillBasedValueByMarine(pMarine, ASW_MARINE_SKILL_GRENADES, ASW_MARINE_SUBSKILL_GRENADE_RADIUS);
}
#endif
void CASW_Weapon_Grenades::DelayedAttack( void )
{
m_bShotDelayed = false;
CASW_Player *pPlayer = GetCommander();
if ( !pPlayer )
return;
CASW_Marine *pMarine = GetMarine();
if ( !pMarine || pMarine->GetWaterLevel() == 3 )
return;
#ifndef CLIENT_DLL
Vector vecSrc = pMarine->GetOffhandThrowSource();
Vector vecDest = pPlayer->GetCrosshairTracePos();
if ( !pMarine->IsInhabited() )
{
vecDest = pMarine->GetOffhandItemSpot();
}
Vector newVel = UTIL_LaunchVector( vecSrc, vecDest, GetThrowGravity() ) * 28.0f;
float fGrenadeRadius = GetBoomRadius( pMarine );
float fGrenadeDamage = GetBoomDamage( pMarine );
int iClusters = MarineSkills()->GetSkillBasedValueByMarine(pMarine, ASW_MARINE_SKILL_GRENADES, ASW_MARINE_SUBSKILL_GRENADE_CLUSTERS);
if (asw_debug_marine_damage.GetBool())
{
Msg("Grenade damage = %f radius = %f clusters = %d\n", fGrenadeDamage, fGrenadeRadius, iClusters);
}
pMarine->GetMarineSpeech()->Chatter(CHATTER_GRENADE);
if (ASWGameRules())
ASWGameRules()->m_fLastFireTime = gpGlobals->curtime;
CASW_Grenade_Cluster *pGrenade = CASW_Grenade_Cluster::Cluster_Grenade_Create(
fGrenadeDamage,
fGrenadeRadius,
iClusters,
vecSrc, pMarine->EyeAngles(), newVel, AngularImpulse(0,0,0), pMarine, this );
if ( pGrenade )
{
pGrenade->SetGravity( GetThrowGravity() );
}
#endif
// decrement ammo
m_iClip1 -= 1;
#ifndef CLIENT_DLL
DestroyIfEmpty( true );
pMarine->OnWeaponFired( this, 1 );
#endif
m_flSoonestPrimaryAttack = gpGlobals->curtime + ASW_FLARES_FASTEST_REFIRE_TIME;
if (m_iClip1 > 0) // only force the fire wait time if we have ammo for another shot
m_flNextPrimaryAttack = gpGlobals->curtime + GetFireRate();
else
m_flNextPrimaryAttack = gpGlobals->curtime;
}
void CASW_Weapon_Grenades::Precache()
{
BaseClass::Precache();
#ifndef CLIENT_DLL
//UTIL_PrecacheOther( "asw_flare_projectile" );
#endif
}
// flares don't reload
bool CASW_Weapon_Grenades::Reload()
{
return false;
}
void CASW_Weapon_Grenades::ItemPostFrame( void )
{
BaseClass::ItemPostFrame();
if ( m_bInReload )
return;
CBasePlayer *pOwner = GetCommander();
if ( pOwner == NULL )
return;
//Allow a refire as fast as the player can click
if ( ( ( pOwner->m_nButtons & IN_ATTACK ) == false ) && ( m_flSoonestPrimaryAttack < gpGlobals->curtime ) )
{
m_flNextPrimaryAttack = gpGlobals->curtime - 0.1f;
}
}
int CASW_Weapon_Grenades::ASW_SelectWeaponActivity(int idealActivity)
{
// we just use the normal 'no weapon' anims for this
return idealActivity;
}