upload "kind" alien swarm

This commit is contained in:
nillerusr
2023-10-03 17:23:56 +03:00
parent b7bd94c52e
commit 7d3c0d8b5a
4229 changed files with 462903 additions and 495158 deletions

View File

@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -11,18 +11,8 @@
#include "SoundEmitterSystem/isoundemittersystembase.h"
#include "physics_saverestore.h"
#include "datacache/imdlcache.h"
#include "activitylist.h"
// NVNT start extra includes
#include "haptics/haptic_utils.h"
#ifdef CLIENT_DLL
#include "prediction.h"
#endif
// NVNT end extra includes
#if defined ( TF_DLL ) || defined ( TF_CLIENT_DLL )
#include "tf_shareddefs.h"
#endif
#include "tier0/vprof.h"
#include "collisionutils.h"
#if !defined( CLIENT_DLL )
@@ -32,10 +22,6 @@
#include "fmtstr.h"
#include "gameweaponmanager.h"
#ifdef HL2MP
#include "hl2mp_gamerules.h"
#endif
#endif
// memdbgon must be the last include file in a .cpp file!!!
@@ -51,16 +37,7 @@
extern bool UTIL_ItemCanBeTouchedByPlayer( CBaseEntity *pItem, CBasePlayer *pPlayer );
#if defined ( TF_CLIENT_DLL ) || defined ( TF_DLL )
#ifdef _DEBUG
ConVar tf_weapon_criticals_force_random( "tf_weapon_criticals_force_random", "0", FCVAR_REPLICATED | FCVAR_CHEAT );
#endif // _DEBUG
ConVar tf_weapon_criticals_bucket_cap( "tf_weapon_criticals_bucket_cap", "1000.0", FCVAR_REPLICATED | FCVAR_CHEAT );
ConVar tf_weapon_criticals_bucket_bottom( "tf_weapon_criticals_bucket_bottom", "-250.0", FCVAR_REPLICATED | FCVAR_CHEAT );
ConVar tf_weapon_criticals_bucket_default( "tf_weapon_criticals_bucket_default", "300.0", FCVAR_REPLICATED | FCVAR_CHEAT );
#endif // TF
CBaseCombatWeapon::CBaseCombatWeapon() : BASECOMBATWEAPON_DERIVED_FROM()
CBaseCombatWeapon::CBaseCombatWeapon()
{
// Constructor must call this
// CONSTRUCT_PREDICTABLE( CBaseCombatWeapon );
@@ -76,9 +53,6 @@ CBaseCombatWeapon::CBaseCombatWeapon() : BASECOMBATWEAPON_DERIVED_FROM()
// Defaults to zero
m_nViewModelIndex = 0;
m_bFlipViewModel = false;
m_iSubType = 0;
#if defined( CLIENT_DLL )
m_iState = m_iOldState = WEAPON_NOT_CARRIED;
m_iClip1 = -1;
@@ -94,15 +68,7 @@ CBaseCombatWeapon::CBaseCombatWeapon() : BASECOMBATWEAPON_DERIVED_FROM()
m_hWeaponFileInfo = GetInvalidWeaponInfoHandle();
#if defined( TF_DLL )
UseClientSideAnimation();
#endif
#if defined ( TF_CLIENT_DLL ) || defined ( TF_DLL )
m_flCritTokenBucket = tf_weapon_criticals_bucket_default.GetFloat();
m_nCritChecks = 1;
m_nCritSeedRequests = 0;
#endif // TF
}
//-----------------------------------------------------------------------------
@@ -137,12 +103,13 @@ void CBaseCombatWeapon::Activate( void )
#endif
}
void CBaseCombatWeapon::GiveDefaultAmmo( void )
{
// If I use clips, set my clips to the default
if ( UsesClipsForAmmo1() )
{
m_iClip1 = AutoFiresFullClip() ? 0 : GetDefaultClip1();
m_iClip1 = GetDefaultClip1();
}
else
{
@@ -167,8 +134,6 @@ void CBaseCombatWeapon::Spawn( void )
{
Precache();
BaseClass::Spawn();
SetSolid( SOLID_BBOX );
m_flNextEmptySoundTime = 0.0f;
@@ -176,17 +141,21 @@ void CBaseCombatWeapon::Spawn( void )
RemoveEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID );
m_iState = WEAPON_NOT_CARRIED;
SetGlobalFadeScale( 0.0f );
// Assume
m_nViewModelIndex = 0;
GiveDefaultAmmo();
if ( GetWorldModel() )
{
SetModel( GetWorldModel() );
}
SetModel( GetWorldModel() );
#if !defined( CLIENT_DLL )
if ( GetWpnData().szAIAddOn[ 0 ] != '\0' )
{
SetAIAddOn( AllocPooledString( GetWpnData().szAIAddOn ) );
}
if( IsX360() )
{
AddEffects( EF_ITEM_BLINK );
@@ -235,6 +204,7 @@ void CBaseCombatWeapon::Precache( void )
Assert( Q_strlen( GetClassname() ) > 0 );
// Msg( "Client got %s\n", GetClassname() );
#endif
m_iPrimaryAmmoType = m_iSecondaryAmmoType = -1;
// Add this weapon to the weapon registry, and get our index into it
@@ -249,16 +219,7 @@ void CBaseCombatWeapon::Precache( void )
{
Msg("ERROR: Weapon (%s) using undefined primary ammo type (%s)\n",GetClassname(), GetWpnData().szAmmo1);
}
#if defined ( TF_DLL ) || defined ( TF_CLIENT_DLL )
// Ammo override
int iModUseMetalOverride = 0;
CALL_ATTRIB_HOOK_INT( iModUseMetalOverride, mod_use_metal_ammo_type );
if ( iModUseMetalOverride )
{
m_iPrimaryAmmoType = (int)TF_AMMO_METAL;
}
#endif
}
}
if ( GetWpnData().szAmmo2[0] )
{
m_iSecondaryAmmoType = GetAmmoDef()->Index( GetWpnData().szAmmo2 );
@@ -299,8 +260,18 @@ void CBaseCombatWeapon::Precache( void )
Warning( "Error reading weapon data file for: %s\n", GetClassname() );
// Remove( ); //don't remove, this gets released soon!
}
const char *pszTracerName = GetTracerType();
if ( pszTracerName )
{
PrecacheEffect( pszTracerName );
}
PrecacheEffect( "ParticleTracer" );
PrecacheParticleSystem( "weapon_tracers" );
}
//-----------------------------------------------------------------------------
// Purpose: Get my data in the file weapon info array
//-----------------------------------------------------------------------------
@@ -347,13 +318,6 @@ const char *CBaseCombatWeapon::GetPrintName( void ) const
//-----------------------------------------------------------------------------
int CBaseCombatWeapon::GetMaxClip1( void ) const
{
#if defined ( TF_DLL ) || defined ( TF_CLIENT_DLL )
int iModMaxClipOverride = 0;
CALL_ATTRIB_HOOK_INT( iModMaxClipOverride, mod_max_primary_clip_override );
if ( iModMaxClipOverride != 0 )
return iModMaxClipOverride;
#endif
return GetWpnData().iMaxClip1;
}
@@ -554,20 +518,6 @@ CBaseCombatCharacter *CBaseCombatWeapon::GetOwner() const
//-----------------------------------------------------------------------------
void CBaseCombatWeapon::SetOwner( CBaseCombatCharacter *owner )
{
if ( !owner )
{
#ifndef CLIENT_DLL
// Make sure the weapon updates its state when it's removed from the player
// We have to force an active state change, because it's being dropped and won't call UpdateClientData()
int iOldState = m_iState;
m_iState = WEAPON_NOT_CARRIED;
OnActiveStateChanged( iOldState );
#endif
// make sure we clear out our HideThink if we have one pending
SetContextThink( NULL, 0, HIDEWEAPON_THINK_CONTEXT );
}
m_hOwner = owner;
#ifndef CLIENT_DLL
@@ -658,7 +608,6 @@ float CBaseCombatWeapon::GetWeaponIdleTime( void )
void CBaseCombatWeapon::Drop( const Vector &vecVelocity )
{
#if !defined( CLIENT_DLL )
// Once somebody drops a gun, it's fair game for removal when/if
// a game_weapon_manager does a cleanup on surplus weapons in the
// world.
@@ -754,10 +703,6 @@ void CBaseCombatWeapon::OnPickedUp( CBaseCombatCharacter *pNewOwner )
m_OnNPCPickup.FireOutput(pNewOwner, this);
}
#ifdef HL2MP
HL2MPRules()->RemoveLevelDesignerPlacedObject( this );
#endif
// Someone picked me up, so make it so that I can't be removed.
SetRemoveable( false );
#endif
@@ -780,6 +725,10 @@ void CBaseCombatWeapon::MakeTracer( const Vector &vecTracerSrc, const trace_t &t
}
const char *pszTracerName = GetTracerType();
if ( !pszTracerName )
{
pszTracerName = "weapon_tracers";
}
Vector vNewSrc = vecTracerSrc;
int iEntIndex = pOwner->entindex();
@@ -787,25 +736,22 @@ void CBaseCombatWeapon::MakeTracer( const Vector &vecTracerSrc, const trace_t &t
if ( g_pGameRules->IsMultiplayer() )
{
iEntIndex = entindex();
#ifdef CLIENT_DLL
C_BasePlayer *player = ToBasePlayer( pOwner );
if ( C_BasePlayer::IsLocalPlayer( player ) )
{
CBaseEntity *vm = player->GetViewModel();
if ( vm )
{
iEntIndex = vm->entindex();
}
}
#endif
}
int iAttachment = GetTracerAttachment();
switch ( iTracerType )
{
case TRACER_LINE:
UTIL_Tracer( vNewSrc, tr.endpos, iEntIndex, iAttachment, 0.0f, true, pszTracerName );
break;
case TRACER_LINE_AND_WHIZ:
UTIL_Tracer( vNewSrc, tr.endpos, iEntIndex, iAttachment, 0.0f, true, pszTracerName );
break;
}
}
void CBaseCombatWeapon::GiveTo( CBaseEntity *pOther )
{
DefaultTouch( pOther );
UTIL_ParticleTracer( pszTracerName, vNewSrc, tr.endpos, iEntIndex, iAttachment, true );
}
//-----------------------------------------------------------------------------
@@ -1008,10 +954,7 @@ void CBaseCombatWeapon::Equip( CBaseCombatCharacter *pOwner )
void CBaseCombatWeapon::SetActivity( Activity act, float duration )
{
//Adrian: Oh man...
#if !defined( CLIENT_DLL ) && (defined( HL2MP ) || defined( PORTAL ))
SetModel( GetWorldModel() );
#endif
int sequence = SelectWeightedSequence( act );
@@ -1019,10 +962,7 @@ void CBaseCombatWeapon::SetActivity( Activity act, float duration )
if ( sequence == ACTIVITY_NOT_AVAILABLE )
sequence = SelectWeightedSequence( ACT_VM_IDLE );
//Adrian: Oh man again...
#if !defined( CLIENT_DLL ) && (defined( HL2MP ) || defined( PORTAL ))
SetModel( GetViewModel() );
#endif
if ( sequence != ACTIVITY_NOT_AVAILABLE )
{
@@ -1035,7 +975,8 @@ void CBaseCombatWeapon::SetActivity( Activity act, float duration )
{
// FIXME: does this even make sense in non-shoot animations?
m_flPlaybackRate = SequenceDuration( sequence ) / duration;
m_flPlaybackRate = MIN( m_flPlaybackRate, 12.0); // FIXME; magic number!, network encoding range
m_flPlaybackRate = fpmin( m_flPlaybackRate, 12.0); // FIXME; magic number!, network encoding range
Assert( IsFinite( m_flPlaybackRate ) );
}
else
{
@@ -1053,14 +994,7 @@ int CBaseCombatWeapon::UpdateClientData( CBasePlayer *pPlayer )
if ( pPlayer->GetActiveWeapon() == this )
{
if ( pPlayer->m_fOnTarget )
{
iNewState = WEAPON_IS_ONTARGET;
}
else
{
iNewState = WEAPON_IS_ACTIVE;
}
iNewState = WEAPON_IS_ACTIVE;
}
else
{
@@ -1069,9 +1003,7 @@ int CBaseCombatWeapon::UpdateClientData( CBasePlayer *pPlayer )
if ( m_iState != iNewState )
{
int iOldState = m_iState;
m_iState = iNewState;
OnActiveStateChanged( iOldState );
}
return 1;
}
@@ -1105,7 +1037,7 @@ void CBaseCombatWeapon::SendViewModelAnim( int nSequence )
if ( pOwner == NULL )
return;
CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex, false );
CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex );
if ( vm == NULL )
return;
@@ -1167,7 +1099,7 @@ void CBaseCombatWeapon::SetViewModel()
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
if ( pOwner == NULL )
return;
CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex, false );
CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex );
if ( vm == NULL )
return;
Assert( vm->ViewModelIndex() == m_nViewModelIndex );
@@ -1180,18 +1112,10 @@ void CBaseCombatWeapon::SetViewModel()
//-----------------------------------------------------------------------------
bool CBaseCombatWeapon::SendWeaponAnim( int iActivity )
{
#ifdef USES_ECON_ITEMS
#ifdef USES_PERSISTENT_ITEMS
iActivity = TranslateViewmodelHandActivity( (Activity)iActivity );
#endif
// NVNT notify the haptics system of this weapons new activity
#ifdef WIN32
#ifdef CLIENT_DLL
if ( prediction->InPrediction() && prediction->IsFirstTimePredicted() )
#endif
#ifndef _X360
HapticSendWeaponAnim(this,iActivity);
#endif
#endif
//For now, just set the ideal activity and be done with it
return SetIdealActivity( (Activity) iActivity );
}
@@ -1331,7 +1255,13 @@ bool CBaseCombatWeapon::IsWeaponVisible( void )
{
vm = pOwner->GetViewModel( m_nViewModelIndex );
if ( vm )
{
#ifdef CLIENT_DLL
return !vm->IsDormant() && !vm->IsEffectActive(EF_NODRAW);
#else
return ( !vm->IsEffectActive(EF_NODRAW) );
#endif
}
}
return false;
@@ -1361,7 +1291,7 @@ bool CBaseCombatWeapon::ReloadOrSwitchWeapons( void )
else
{
// Weapon is useable. Reload if empty and weapon has waited as long as it has to after firing
if ( UsesClipsForAmmo1() && !AutoFiresFullClip() &&
if ( UsesClipsForAmmo1() &&
(m_iClip1 == 0) &&
(GetWeaponFlags() & ITEM_FLAG_NOAUTORELOAD) == false &&
m_flNextPrimaryAttack < gpGlobals->curtime &&
@@ -1369,7 +1299,9 @@ bool CBaseCombatWeapon::ReloadOrSwitchWeapons( void )
{
// if we're successfully reloading, we're done
if ( Reload() )
{
return true;
}
}
}
@@ -1417,8 +1349,6 @@ bool CBaseCombatWeapon::DefaultDeploy( char *szViewModel, char *szWeaponModel, i
m_bReloadHudHintDisplayed = false;
m_flHudHintPollTime = gpGlobals->curtime + 5.0f;
WeaponSound( DEPLOY );
SetWeaponVisible( true );
/*
@@ -1456,7 +1386,6 @@ bool CBaseCombatWeapon::Holster( CBaseCombatWeapon *pSwitchingTo )
// cancel any reload in progress.
m_bInReload = false;
m_bFiringWholeClip = false;
// kill any think functions
SetThink(NULL);
@@ -1542,66 +1471,6 @@ void CBaseCombatWeapon::HideThink( void )
}
}
bool CBaseCombatWeapon::CanReload( void )
{
if ( AutoFiresFullClip() && m_bFiringWholeClip )
{
return false;
}
return true;
}
#if defined ( TF_CLIENT_DLL ) || defined ( TF_DLL )
//-----------------------------------------------------------------------------
// Purpose: Anti-hack
//-----------------------------------------------------------------------------
void CBaseCombatWeapon::AddToCritBucket( float flAmount )
{
float flCap = tf_weapon_criticals_bucket_cap.GetFloat();
// Regulate crit frequency to reduce client-side seed hacking
if ( m_flCritTokenBucket < flCap )
{
// Treat raw damage as the resource by which we add or subtract from the bucket
m_flCritTokenBucket += flAmount;
m_flCritTokenBucket = Min( m_flCritTokenBucket, flCap );
}
}
//-----------------------------------------------------------------------------
// Purpose: Anti-hack
//-----------------------------------------------------------------------------
bool CBaseCombatWeapon::IsAllowedToWithdrawFromCritBucket( float flDamage )
{
// Note: If we're in this block of code, the assumption is that the
// seed said we should grant a random crit. If allowed, the cost
// will be deducted here.
// Track each seed request - in cases where a player is hacking, we'll
// see a silly ratio.
m_nCritSeedRequests++;
// Adjust token cost based on the ratio of requests vs granted, except
// melee, which crits much more than ranged (as high as 60% chance)
float flMult = ( IsMeleeWeapon() ) ? 0.5f : RemapValClamped( ( (float)m_nCritSeedRequests / (float)m_nCritChecks ), 0.1f, 1.f, 1.f, 3.f );
// Would this take us below our limit?
float flCost = ( flDamage * TF_DAMAGE_CRIT_MULTIPLIER ) * flMult;
if ( flCost > m_flCritTokenBucket )
return false;
// Withdraw
RemoveFromCritBucket( flCost );
float flBottom = tf_weapon_criticals_bucket_bottom.GetFloat();
if ( m_flCritTokenBucket < flBottom )
m_flCritTokenBucket = flBottom;
return true;
}
#endif // TF_DLL
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
@@ -1653,8 +1522,6 @@ void CBaseCombatWeapon::ItemPostFrame( void )
if (!pOwner)
return;
UpdateAutoFire();
//Track the duration of the fire
//FIXME: Check for IN_ATTACK2 as well?
//FIXME: What if we're calling ItemBusyFrame?
@@ -1695,7 +1562,7 @@ void CBaseCombatWeapon::ItemPostFrame( void )
if( !IsX360() || !ClassMatches("weapon_crossbow") )
#endif
{
bFired = ShouldBlockPrimaryFire();
bFired = true;
}
SecondaryAttack();
@@ -1743,22 +1610,13 @@ void CBaseCombatWeapon::ItemPostFrame( void )
}
PrimaryAttack();
if ( AutoFiresFullClip() )
{
m_bFiringWholeClip = true;
}
#ifdef CLIENT_DLL
pOwner->SetFiredWeapon( true );
#endif
}
}
// -----------------------
// Reload pressed / Clip Empty
// -----------------------
if ( ( pOwner->m_nButtons & IN_RELOAD ) && UsesClipsForAmmo1() && !m_bInReload )
if ( (pOwner->m_nButtons & IN_RELOAD) && UsesClipsForAmmo1() && !m_bInReload )
{
// reload when reload is pressed, or if no buttons are down and weapon is empty.
Reload();
@@ -1768,10 +1626,10 @@ void CBaseCombatWeapon::ItemPostFrame( void )
// -----------------------
// No buttons down
// -----------------------
if (!((pOwner->m_nButtons & IN_ATTACK) || (pOwner->m_nButtons & IN_ATTACK2) || (CanReload() && pOwner->m_nButtons & IN_RELOAD)))
if (!((pOwner->m_nButtons & IN_ATTACK) || (pOwner->m_nButtons & IN_ATTACK2) || (pOwner->m_nButtons & IN_RELOAD)))
{
// no fire buttons down or reloading
if ( !ReloadOrSwitchWeapons() && ( m_bInReload == false ) )
if ( ( m_bInReload == false ) && !ReloadOrSwitchWeapons() )
{
WeaponIdle();
}
@@ -1802,7 +1660,6 @@ void CBaseCombatWeapon::HandleFireOnEmpty()
//-----------------------------------------------------------------------------
void CBaseCombatWeapon::ItemBusyFrame( void )
{
UpdateAutoFire();
}
//-----------------------------------------------------------------------------
@@ -2015,27 +1872,6 @@ bool CBaseCombatWeapon::DefaultReload( int iClipSize1, int iClipSize2, int iActi
return true;
}
bool CBaseCombatWeapon::ReloadsSingly( void ) const
{
#if defined ( TF_DLL ) || defined ( TF_CLIENT_DLL )
float fHasReload = 1.0f;
CALL_ATTRIB_HOOK_FLOAT( fHasReload, mod_no_reload_display_only );
if ( fHasReload != 1.0f )
{
return false;
}
int iWeaponMod = 0;
CALL_ATTRIB_HOOK_INT( iWeaponMod, set_scattergun_no_reload_single );
if ( iWeaponMod == 1 )
{
return false;
}
#endif // TF_DLL || TF_CLIENT_DLL
return m_bReloadsSingly;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
@@ -2187,54 +2023,6 @@ void CBaseCombatWeapon::AbortReload( void )
m_bInReload = false;
}
void CBaseCombatWeapon::UpdateAutoFire( void )
{
if ( !AutoFiresFullClip() )
return;
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
if ( !pOwner )
return;
if ( m_iClip1 == 0 )
{
// Ready to reload again
m_bFiringWholeClip = false;
}
if ( m_bFiringWholeClip )
{
// If it's firing the clip don't let them repress attack to reload
pOwner->m_nButtons &= ~IN_ATTACK;
}
// Don't use the regular reload key
if ( pOwner->m_nButtons & IN_RELOAD )
{
pOwner->m_nButtons &= ~IN_RELOAD;
}
// Try to fire if there's ammo in the clip and we're not holding the button
bool bReleaseClip = m_iClip1 > 0 && !( pOwner->m_nButtons & IN_ATTACK );
if ( !bReleaseClip )
{
if ( CanReload() && ( pOwner->m_nButtons & IN_ATTACK ) )
{
// Convert the attack key into the reload key
pOwner->m_nButtons |= IN_RELOAD;
}
// Don't allow attack button if we're not attacking
pOwner->m_nButtons &= ~IN_ATTACK;
}
else
{
// Fake the attack key
pOwner->m_nButtons |= IN_ATTACK;
}
}
//-----------------------------------------------------------------------------
// Purpose: Primary fire button attack
//-----------------------------------------------------------------------------
@@ -2303,7 +2091,7 @@ void CBaseCombatWeapon::PrimaryAttack( void )
info.m_vecSpread = pPlayer->GetAttackSpread( this );
#else
//!!!HACKHACK - what does the client want this function for?
info.m_vecSpread = GetActiveWeapon()->GetBulletSpread();
info.m_vecSpread = pPlayer->GetActiveWeapon()->GetBulletSpread();
#endif // CLIENT_DLL
pPlayer->FireBullets( info );
@@ -2318,6 +2106,82 @@ void CBaseCombatWeapon::PrimaryAttack( void )
AddViewKick();
}
void CBaseCombatWeapon::BaseForceFire( CBaseCombatCharacter *pOperator, CBaseEntity *pTarget )
{
// Ensure we have enough rounds in the clip
m_iClip1++;
// If my clip is empty (and I use clips) start reload
if ( UsesClipsForAmmo1() && !m_iClip1 )
{
Reload();
return;
}
pOperator->DoMuzzleFlash();
SendWeaponAnim( GetPrimaryAttackActivity() );
// player "shoot" animation
//pOperator->SetAnimation( PLAYER_ATTACK1 );
FireBulletsInfo_t info;
QAngle angShootDir;
GetAttachment( LookupAttachment( "muzzle" ), info.m_vecSrc, angShootDir );
if ( pTarget )
{
info.m_vecDirShooting = pTarget->WorldSpaceCenter() - info.m_vecSrc;
VectorNormalize( info.m_vecDirShooting );
}
else
{
AngleVectors( angShootDir, &info.m_vecDirShooting );
}
// To make the firing framerate independent, we may have to fire more than one bullet here on low-framerate systems,
// especially if the weapon we're firing has a really fast rate of fire.
info.m_iShots = 0;
float fireRate = GetFireRate();
while ( m_flNextPrimaryAttack <= gpGlobals->curtime )
{
// MUST call sound before removing a round from the clip of a CMachineGun
WeaponSound(SINGLE, m_flNextPrimaryAttack);
m_flNextPrimaryAttack = m_flNextPrimaryAttack + fireRate;
info.m_iShots++;
if ( !fireRate )
break;
}
// Make sure we don't fire more than the amount in the clip
if ( UsesClipsForAmmo1() )
{
info.m_iShots = MIN( info.m_iShots, m_iClip1 );
m_iClip1 -= info.m_iShots;
}
else
{
info.m_iShots = MIN( info.m_iShots, pOperator->GetAmmoCount( m_iPrimaryAmmoType ) );
pOperator->RemoveAmmo( info.m_iShots, m_iPrimaryAmmoType );
}
info.m_flDistance = MAX_TRACE_LENGTH;
info.m_iAmmoType = m_iPrimaryAmmoType;
info.m_iTracerFreq = 2;
#if !defined( CLIENT_DLL )
// Fire the bullets
info.m_vecSpread = pOperator->GetAttackSpread( this );
#else
//!!!HACKHACK - what does the client want this function for?
info.m_vecSpread = GetBulletSpread();
#endif // CLIENT_DLL
pOperator->FireBullets( info );
}
//-----------------------------------------------------------------------------
// Purpose: Called every frame to check if the weapon is going through transition animations
//-----------------------------------------------------------------------------
@@ -2340,7 +2204,7 @@ void CBaseCombatWeapon::MaintainIdealActivity( void )
}
//-----------------------------------------------------------------------------
// Purpose: Sets the ideal activity for the weapon to be in, allowing for transitional animations inbetween
// Purpose: Sets the ideal activity for the weapon to be in, allowing for transitional animations in between
// Input : ideal - activity to end up at, ideally
//-----------------------------------------------------------------------------
bool CBaseCombatWeapon::SetIdealActivity( Activity ideal )
@@ -2439,81 +2303,79 @@ Activity CBaseCombatWeapon::ActivityOverride( Activity baseAct, bool *pRequired
return baseAct;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CDmgAccumulator::CDmgAccumulator( void )
class CWeaponList : public CAutoGameSystem
{
#ifdef GAME_DLL
SetDefLessFunc( m_TargetsDmgInfo );
#endif // GAME_DLL
m_bActive = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CDmgAccumulator::~CDmgAccumulator()
{
// Did a weapon get deleted while aggregating CTakeDamageInfo events?
Assert( !m_bActive );
}
#ifdef GAME_DLL
//-----------------------------------------------------------------------------
// Collect trace attacks for weapons that fire multiple bullets per attack that also penetrate
//-----------------------------------------------------------------------------
void CDmgAccumulator::AccumulateMultiDamage( const CTakeDamageInfo &info, CBaseEntity *pEntity )
{
if ( !pEntity )
return;
Assert( m_bActive );
#if defined( GAME_DLL )
int iIndex = m_TargetsDmgInfo.Find( pEntity->entindex() );
if ( iIndex == m_TargetsDmgInfo.InvalidIndex() )
public:
CWeaponList( char const *name ) : CAutoGameSystem( name )
{
m_TargetsDmgInfo.Insert( pEntity->entindex(), info );
}
else
virtual void LevelShutdownPostEntity()
{
m_list.Purge();
}
void AddWeapon( CBaseCombatWeapon *pWeapon )
{
CTakeDamageInfo *pInfo = &m_TargetsDmgInfo[iIndex];
if ( pInfo )
m_list.AddToTail( pWeapon );
}
void RemoveWeapon( CBaseCombatWeapon *pWeapon )
{
m_list.FindAndRemove( pWeapon );
}
CUtlLinkedList< CBaseCombatWeapon * > m_list;
};
CWeaponList g_WeaponList( "CWeaponList" );
#ifndef CLIENT_DLL
void OnBaseCombatWeaponCreated( CBaseCombatWeapon *pWeapon )
{
g_WeaponList.AddWeapon( pWeapon );
}
void OnBaseCombatWeaponDestroyed( CBaseCombatWeapon *pWeapon )
{
g_WeaponList.RemoveWeapon( pWeapon );
}
#endif
#ifdef CLIENT_DLL
CUtlLinkedList< CBaseCombatWeapon * >& CBaseCombatWeapon::GetWeaponList( void )
{
return g_WeaponList.m_list;
}
#else
int CBaseCombatWeapon::GetAvailableWeaponsInBox( CBaseCombatWeapon **pList, int listMax, const Vector &mins, const Vector &maxs )
{
// linear search all weapons
int count = 0;
int index = g_WeaponList.m_list.Head();
while ( index != g_WeaponList.m_list.InvalidIndex() )
{
CBaseCombatWeapon *pWeapon = g_WeaponList.m_list[index];
// skip any held weapon
if ( !pWeapon->GetOwner() )
{
// Update
m_TargetsDmgInfo[iIndex].AddDamageType( info.GetDamageType() );
m_TargetsDmgInfo[iIndex].SetDamage( pInfo->GetDamage() + info.GetDamage() );
m_TargetsDmgInfo[iIndex].SetDamageForce( pInfo->GetDamageForce() + info.GetDamageForce() );
m_TargetsDmgInfo[iIndex].SetDamagePosition( info.GetDamagePosition() );
m_TargetsDmgInfo[iIndex].SetReportedPosition( info.GetReportedPosition() );
m_TargetsDmgInfo[iIndex].SetMaxDamage( MAX( pInfo->GetMaxDamage(), info.GetDamage() ) );
m_TargetsDmgInfo[iIndex].SetAmmoType( info.GetAmmoType() );
}
}
#endif // GAME_DLL
}
//-----------------------------------------------------------------------------
// Purpose: Send aggregate info
//-----------------------------------------------------------------------------
void CDmgAccumulator::Process( void )
{
FOR_EACH_MAP( m_TargetsDmgInfo, i )
{
CBaseEntity *pEntity = UTIL_EntityByIndex( m_TargetsDmgInfo.Key( i ) );
if ( pEntity )
{
AddMultiDamage( m_TargetsDmgInfo[i], pEntity );
// restrict to mins/maxs
if ( IsPointInBox( pWeapon->GetAbsOrigin(), mins, maxs ) )
{
if ( count < listMax )
{
pList[count] = pWeapon;
count++;
}
}
}
index = g_WeaponList.m_list.Next( index );
}
m_bActive = false;
m_TargetsDmgInfo.Purge();
return count;
}
#endif // GAME_DLL
#endif
#if defined( CLIENT_DLL )
@@ -2523,7 +2385,7 @@ BEGIN_PREDICTION_DATA( CBaseCombatWeapon )
// Networked
DEFINE_PRED_FIELD( m_hOwner, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ),
// DEFINE_FIELD( m_hWeaponFileInfo, FIELD_SHORT ),
DEFINE_PRED_FIELD( m_iState, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_iState, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_iViewModelIndex, FIELD_INTEGER, FTYPEDESC_INSENDTABLE | FTYPEDESC_MODELINDEX ),
DEFINE_PRED_FIELD( m_iWorldModelIndex, FIELD_INTEGER, FTYPEDESC_INSENDTABLE | FTYPEDESC_MODELINDEX ),
DEFINE_PRED_FIELD_TOL( m_flNextPrimaryAttack, FIELD_FLOAT, FTYPEDESC_INSENDTABLE, TD_MSECTOLERANCE ),
@@ -2539,10 +2401,8 @@ BEGIN_PREDICTION_DATA( CBaseCombatWeapon )
// Not networked
DEFINE_PRED_FIELD( m_flTimeWeaponIdle, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
DEFINE_FIELD( m_bInReload, FIELD_BOOLEAN ),
DEFINE_FIELD( m_bFireOnEmpty, FIELD_BOOLEAN ),
DEFINE_FIELD( m_bFiringWholeClip, FIELD_BOOLEAN ),
DEFINE_FIELD( m_flNextEmptySoundTime, FIELD_FLOAT ),
DEFINE_FIELD( m_Activity, FIELD_INTEGER ),
DEFINE_FIELD( m_fFireDuration, FIELD_FLOAT ),
@@ -2704,29 +2564,6 @@ void* SendProxy_SendLocalWeaponDataTable( const SendProp *pProp, const void *pSt
return NULL;
}
REGISTER_SEND_PROXY_NON_MODIFIED_POINTER( SendProxy_SendLocalWeaponDataTable );
//-----------------------------------------------------------------------------
// Purpose: Only send to non-local players
//-----------------------------------------------------------------------------
void* SendProxy_SendNonLocalWeaponDataTable( const SendProp *pProp, const void *pStruct, const void *pVarData, CSendProxyRecipients *pRecipients, int objectID )
{
pRecipients->SetAllRecipients();
CBaseCombatWeapon *pWeapon = (CBaseCombatWeapon*)pVarData;
if ( pWeapon )
{
CBasePlayer *pPlayer = ToBasePlayer( pWeapon->GetOwner() );
if ( pPlayer )
{
pRecipients->ClearRecipient( pPlayer->GetClientIndex() );
return ( void * )pVarData;
}
}
return NULL;
}
REGISTER_SEND_PROXY_NON_MODIFIED_POINTER( SendProxy_SendNonLocalWeaponDataTable );
#endif
#if PREDICTION_ERROR_CHECK_LEVEL > 1
@@ -2744,9 +2581,7 @@ BEGIN_NETWORK_TABLE_NOBASE( CBaseCombatWeapon, DT_LocalActiveWeaponData )
SendPropInt( SENDINFO( m_nNextThinkTick ) ),
SendPropTime( SENDINFO( m_flTimeWeaponIdle ) ),
#if defined( TF_DLL )
SendPropExclude( "DT_AnimTimeMustBeFirst" , "m_flAnimTime" ),
#endif
#else
RecvPropTime( RECVINFO( m_flNextPrimaryAttack ) ),
@@ -2768,11 +2603,7 @@ BEGIN_NETWORK_TABLE_NOBASE( CBaseCombatWeapon, DT_LocalWeaponData )
SendPropInt( SENDINFO( m_nViewModelIndex ), VIEWMODEL_INDEX_BITS, SPROP_UNSIGNED ),
SendPropInt( SENDINFO( m_bFlipViewModel ) ),
#if defined( TF_DLL )
SendPropExclude( "DT_AnimTimeMustBeFirst" , "m_flAnimTime" ),
#endif
#else
RecvPropIntWithMinusOneFlag( RECVINFO(m_iClip1 )),
@@ -2782,8 +2613,6 @@ BEGIN_NETWORK_TABLE_NOBASE( CBaseCombatWeapon, DT_LocalWeaponData )
RecvPropInt( RECVINFO( m_nViewModelIndex ) ),
RecvPropBool( RECVINFO( m_bFlipViewModel ) ),
#endif
END_NETWORK_TABLE()
@@ -2793,7 +2622,7 @@ BEGIN_NETWORK_TABLE(CBaseCombatWeapon, DT_BaseCombatWeapon)
SendPropDataTable("LocalActiveWeaponData", 0, &REFERENCE_SEND_TABLE(DT_LocalActiveWeaponData), SendProxy_SendActiveLocalWeaponDataTable ),
SendPropModelIndex( SENDINFO(m_iViewModelIndex) ),
SendPropModelIndex( SENDINFO(m_iWorldModelIndex) ),
SendPropInt( SENDINFO(m_iState ), 8, SPROP_UNSIGNED ),
SendPropInt( SENDINFO( m_iState ), 2, SPROP_UNSIGNED ),
SendPropEHandle( SENDINFO(m_hOwner) ),
#else
RecvPropDataTable("LocalWeaponData", 0, 0, &REFERENCE_RECV_TABLE(DT_LocalWeaponData)),
@@ -2804,3 +2633,32 @@ BEGIN_NETWORK_TABLE(CBaseCombatWeapon, DT_BaseCombatWeapon)
RecvPropEHandle( RECVINFO(m_hOwner ) ),
#endif
END_NETWORK_TABLE()
#if defined( CLIENT_DLL )
int Studio_FindAttachment( const CStudioHdr *pStudioHdr, const char *pAttachmentName );
int CBaseCombatWeapon::LookupAttachment( const char *pAttachmentName )
{
int newIndex = GetWorldModelIndex();
if ( newIndex != m_nModelIndex )
{
const model_t *pWorldModel = modelinfo->GetModel( newIndex );
if ( pWorldModel )
{
MDLHandle_t hStudioHdr = modelinfo->GetCacheHandle( pWorldModel );
if ( MDLHANDLE_INVALID != hStudioHdr )
{
const studiohdr_t *pStudioHdr = mdlcache->GetStudioHdr( hStudioHdr );
if ( pStudioHdr )
{
CStudioHdr studioHdrContainer( pStudioHdr, mdlcache );
int iRet = Studio_FindAttachment( &studioHdrContainer, pAttachmentName ) + 1;
return iRet;
}
}
}
}
return BaseClass::LookupAttachment( pAttachmentName );
}
#endif