Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
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.
 
 
 
 
 
 

219 lines
7.3 KiB

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Vehicle mounted machinegun that the driver controls
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "basetfplayer_shared.h"
#include "baseobject_shared.h"
#include "tf_obj_driver_machinegun_shared.h"
#include "engine/IEngineSound.h"
#include "ammodef.h"
#include "tf_gamerules.h"
#if defined( CLIENT_DLL )
#include "hud_ammo.h"
#else
#endif
// ------------------------------------------------------------------------ //
#define DRIVER_MACHINEGUN_MINS Vector(-10, -10, 0)
#define DRIVER_MACHINEGUN_MAXS Vector( 10, 10, 10)
#define DRIVER_MACHINEGUN_MODEL "models/objects/obj_manned_plasmagun.mdl"
IMPLEMENT_NETWORKCLASS_ALIASED( ObjectDriverMachinegun, DT_ObjectDriverMachinegun )
BEGIN_NETWORK_TABLE( CObjectDriverMachinegun, DT_ObjectDriverMachinegun )
#if !defined( CLIENT_DLL )
SendPropInt( SENDINFO(m_nAmmoCount), 7, SPROP_UNSIGNED ),
#else
RecvPropInt( RECVINFO(m_nAmmoCount) ),
#endif
END_NETWORK_TABLE()
LINK_ENTITY_TO_CLASS(obj_driver_machinegun, CObjectDriverMachinegun);
PRECACHE_REGISTER(obj_driver_machinegun);
BEGIN_PREDICTION_DATA( CObjectDriverMachinegun )
DEFINE_PRED_FIELD( m_nAmmoCount, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
END_PREDICTION_DATA()
ConVar obj_driver_machinegun_health( "obj_driver_machinegun_health","100", FCVAR_REPLICATED, "Driver's mounted machinegun health" );
ConVar obj_driver_machinegun_range( "obj_driver_machinegun_range","1048", FCVAR_REPLICATED, "Driver's mounted machinegun range" );
ConVar obj_driver_machinegun_damage( "obj_driver_machinegun_damage","10", FCVAR_REPLICATED, "Driver's mounted machinegun damage" );
ConVar obj_driver_machinegun_max_ammo( "obj_driver_machinegun_max_ammo","30", FCVAR_REPLICATED, "Driver's mounted machinegun ammo" );
ConVar obj_driver_machinegun_ammo_recharge_rate( "obj_driver_machinegun_ammo_recharge_rate","0.5", FCVAR_REPLICATED, "Driver's mounted machinegun ammo recharge rate" );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CObjectDriverMachinegun::CObjectDriverMachinegun()
{
SetPredictionEligible( true );
#if !defined( CLIENT_DLL )
m_iHealth = obj_driver_machinegun_health.GetInt();
#endif
m_flNextAttack = 0;
m_nMaxAmmoCount = m_nAmmoCount = obj_driver_machinegun_max_ammo.GetInt();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CObjectDriverMachinegun::Spawn()
{
Precache();
SetModel( DRIVER_MACHINEGUN_MODEL );
#if !defined( CLIENT_DLL )
SetBodygroup( 1, true );
UTIL_SetSize(this, DRIVER_MACHINEGUN_MINS, DRIVER_MACHINEGUN_MAXS);
m_takedamage = DAMAGE_YES;
SetType( OBJ_DRIVER_MACHINEGUN );
m_fObjectFlags |= OF_SUPPRESS_NOTIFY_UNDER_ATTACK | OF_DONT_AUTO_REPAIR;
SetThink( RechargeThink );
#endif
m_nBarrelAttachment = LookupAttachment( "barrel" );
m_nAmmoType = GetAmmoDef()->Index( "Bullets" );
BaseClass::Spawn();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CObjectDriverMachinegun::Precache()
{
PrecacheModel( DRIVER_MACHINEGUN_MODEL );
PrecacheScriptSound( "DriverMachinegun.Fire" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CObjectDriverMachinegun::CanFireNow( void )
{
if ( !m_nAmmoCount )
return false;
return ( m_flNextAttack < gpGlobals->curtime );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CObjectDriverMachinegun::Fire( CBaseTFPlayer *pDriver )
{
// We have to flush the bone cache because it's possible that only the bone controllers
// have changed since the bonecache was generated, and bone controllers aren't checked.
InvalidateBoneCache();
QAngle vecAng;
Vector vecSrc, vecAim;
GetAttachment( m_nBarrelAttachment, vecSrc, vecAng );
AngleVectors( vecAng, &vecAim, 0, 0 );
static Vector spread = VECTOR_CONE_5DEGREES;
TFGameRules()->FireBullets( CTakeDamageInfo( this, pDriver, obj_driver_machinegun_damage.GetFloat(), DMG_BULLET ),
1, vecSrc, vecAim, spread, obj_driver_machinegun_range.GetFloat(), m_nAmmoType, 4, entindex(), m_nBarrelAttachment );
#if !defined (CLIENT_DLL)
SetActivity( ACT_VM_PRIMARYATTACK );
#else
int sequence = SelectWeightedSequence( ACT_VM_PRIMARYATTACK );
if ( sequence != ACTIVITY_NOT_AVAILABLE )
{
ResetSequence( sequence );
SetCycle( 0 );
m_bClientSideFrameReset = !m_bClientSideFrameReset;
}
#endif
DoMuzzleFlash();
CPASAttenuationFilter filter( this );
filter.UsePredictionRules();
EmitSound( filter, entindex(), "DriverMachinegun.Fire" );
m_nAmmoCount -= 1;
#if !defined (CLIENT_DLL)
SetNextThink( gpGlobals->curtime + obj_driver_machinegun_ammo_recharge_rate.GetFloat() );
#endif
// If I'm EMPed, slow the firing rate down
m_flNextAttack = gpGlobals->curtime + ( HasPowerup(POWERUP_EMP) ? 0.3f : 0.15f );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CObjectDriverMachinegun::SetTargetAngles( const QAngle &vecAngles )
{
BaseClass::SetTargetAngles( vecAngles );
#if !defined( CLIENT_DLL )
SetBoneController( 0, vecAngles[YAW] );
SetBoneController( 1, vecAngles[PITCH] );
#endif
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
Vector CObjectDriverMachinegun::GetFireOrigin( void )
{
Vector vecOrigin;
QAngle dummy;
GetAttachment( m_nBarrelAttachment, vecOrigin, dummy );
return vecOrigin;
}
//-----------------------------------------------------------------------------
// Purpose: Rcharge my ammo count
//-----------------------------------------------------------------------------
void CObjectDriverMachinegun::RechargeThink( void )
{
#if !defined( CLIENT_DLL )
SetNextThink( gpGlobals->curtime + obj_driver_machinegun_ammo_recharge_rate.GetFloat() );
// I can't do anything if I'm not active
if ( !ShouldBeActive() )
return;
if (m_nAmmoCount < m_nMaxAmmoCount)
{
m_nAmmoCount += 1;
}
#endif
}
// Client code only
#if defined( CLIENT_DLL )
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CObjectDriverMachinegun::GetBoneControllers( float controllers[MAXSTUDIOBONECTRLS] )
{
BaseClass::GetBoneControllers( controllers );
controllers[0] = anglemod( m_vecGunAngles[YAW] ) / 360.0;
controllers[1] = anglemod( m_vecGunAngles[PITCH] ) / 360.0;
}
//-----------------------------------------------------------------------------
// Renders hud elements
//-----------------------------------------------------------------------------
void CObjectDriverMachinegun::DrawHudElements( void )
{
GetHudAmmo()->SetPrimaryAmmo( m_nAmmoType, m_nAmmoCount );
GetHudAmmo()->SetSecondaryAmmo( -1, -1 );
}
#endif