summaryrefslogtreecommitdiff
path: root/game/shared/dod/weapon_dodbase.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/shared/dod/weapon_dodbase.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/shared/dod/weapon_dodbase.cpp')
-rw-r--r--game/shared/dod/weapon_dodbase.cpp1416
1 files changed, 1416 insertions, 0 deletions
diff --git a/game/shared/dod/weapon_dodbase.cpp b/game/shared/dod/weapon_dodbase.cpp
new file mode 100644
index 0000000..3c1fc98
--- /dev/null
+++ b/game/shared/dod/weapon_dodbase.cpp
@@ -0,0 +1,1416 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "in_buttons.h"
+#include "takedamageinfo.h"
+#include "weapon_dodbase.h"
+#include "ammodef.h"
+#include "dod_gamerules.h"
+
+#ifdef CLIENT_DLL
+extern IVModelInfoClient* modelinfo;
+#else
+extern IVModelInfo* modelinfo;
+#include "ilagcompensationmanager.h"
+#endif
+
+
+#if defined( CLIENT_DLL )
+
+ #include "vgui/ISurface.h"
+ #include "vgui_controls/Controls.h"
+ #include "c_dod_player.h"
+ #include "hud_crosshair.h"
+ #include "SoundEmitterSystem/isoundemittersystembase.h"
+
+#else
+
+ #include "dod_player.h"
+
+#endif
+
+#include "effect_dispatch_data.h"
+
+
+// ----------------------------------------------------------------------------- //
+// Global functions.
+// ----------------------------------------------------------------------------- //
+
+bool IsAmmoType( int iAmmoType, const char *pAmmoName )
+{
+ return GetAmmoDef()->Index( pAmmoName ) == iAmmoType;
+}
+
+//--------------------------------------------------------------------------------------------------------
+//
+// Given a weapon ID, return its alias
+//
+const char *WeaponIDToAlias( int id )
+{
+ if ( (id >= WEAPON_MAX) || (id < 0) )
+ return NULL;
+
+ return s_WeaponAliasInfo[id];
+}
+
+// ----------------------------------------------------------------------------- //
+// CWeaponDODBase tables.
+// ----------------------------------------------------------------------------- //
+
+IMPLEMENT_NETWORKCLASS_ALIASED( WeaponDODBase, DT_WeaponDODBase )
+
+BEGIN_NETWORK_TABLE( CWeaponDODBase, DT_WeaponDODBase )
+#ifdef CLIENT_DLL
+ RecvPropInt( RECVINFO(m_iReloadModelIndex) ),
+ RecvPropVector( RECVINFO( m_vInitialDropVelocity ) ),
+ RecvPropTime( RECVINFO( m_flSmackTime ) )
+#else
+ SendPropVector( SENDINFO( m_vInitialDropVelocity ),
+ 20, // nbits
+ 0, // flags
+ -3000, // low value
+ 3000 // high value
+ ),
+ SendPropModelIndex( SENDINFO(m_iReloadModelIndex) ),
+ SendPropTime( SENDINFO( m_flSmackTime ) )
+#endif
+END_NETWORK_TABLE()
+
+LINK_ENTITY_TO_CLASS( weapon_dod_base, CWeaponDODBase );
+
+
+#ifdef GAME_DLL
+
+ BEGIN_DATADESC( CWeaponDODBase )
+
+ DEFINE_FUNCTION( FallThink ),
+ DEFINE_FUNCTION( Die ),
+
+ DEFINE_FUNCTION( Smack )
+
+ END_DATADESC()
+
+#else
+ BEGIN_PREDICTION_DATA( CWeaponDODBase )
+ DEFINE_PRED_FIELD( m_flSmackTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), // for rifle melee attacks
+ DEFINE_FIELD( m_bInAttack, FIELD_BOOLEAN )
+ END_PREDICTION_DATA()
+#endif
+
+Vector head_hull_mins( -16, -16, -18 );
+Vector head_hull_maxs( 16, 16, 18 );
+
+void FindHullIntersection( const Vector &vecSrc, trace_t &tr, const Vector &mins, const Vector &maxs, CBaseEntity *pEntity )
+{
+ int i, j, k;
+ float distance;
+ Vector minmaxs[2] = {mins, maxs};
+ trace_t tmpTrace;
+ Vector vecHullEnd = tr.endpos;
+ Vector vecEnd;
+
+ CTraceFilterSimple filter( pEntity, COLLISION_GROUP_NONE );
+
+ distance = 1e6f;
+
+ vecHullEnd = vecSrc + ((vecHullEnd - vecSrc)*2);
+ UTIL_TraceLine( vecSrc, vecHullEnd, MASK_SOLID, &filter, &tmpTrace );
+ if ( tmpTrace.fraction < 1.0 )
+ {
+ tr = tmpTrace;
+ return;
+ }
+
+ for ( i = 0; i < 2; i++ )
+ {
+ for ( j = 0; j < 2; j++ )
+ {
+ for ( k = 0; k < 2; k++ )
+ {
+ vecEnd.x = vecHullEnd.x + minmaxs[i][0];
+ vecEnd.y = vecHullEnd.y + minmaxs[j][1];
+ vecEnd.z = vecHullEnd.z + minmaxs[k][2];
+
+ UTIL_TraceLine( vecSrc, vecEnd, MASK_SOLID, &filter, &tmpTrace );
+ if ( tmpTrace.fraction < 1.0 )
+ {
+ float thisDistance = (tmpTrace.endpos - vecSrc).Length();
+ if ( thisDistance < distance )
+ {
+ tr = tmpTrace;
+ distance = thisDistance;
+ }
+ }
+ }
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------- //
+// CWeaponDODBase implementation.
+// ----------------------------------------------------------------------------- //
+CWeaponDODBase::CWeaponDODBase()
+{
+ SetPredictionEligible( true );
+ m_bInAttack = false;
+ m_iAltFireHint = 0;
+ AddSolidFlags( FSOLID_TRIGGER ); // Nothing collides with these but it gets touches.
+
+ m_flNextPrimaryAttack = 0;
+}
+
+
+bool CWeaponDODBase::IsPredicted() const
+{
+ return true;
+}
+
+bool CWeaponDODBase::PlayEmptySound()
+{
+ CPASAttenuationFilter filter( this );
+ filter.UsePredictionRules();
+ EmitSound( filter, entindex(), "Default.ClipEmpty_Rifle" );
+
+ return false;
+}
+
+
+CBasePlayer* CWeaponDODBase::GetPlayerOwner() const
+{
+ return dynamic_cast< CBasePlayer* >( GetOwner() );
+}
+
+CDODPlayer* CWeaponDODBase::GetDODPlayerOwner() const
+{
+ return dynamic_cast< CDODPlayer* >( GetOwner() );
+}
+
+bool CWeaponDODBase::SendWeaponAnim( int iActivity )
+{
+ return BaseClass::SendWeaponAnim( iActivity );
+}
+
+bool CWeaponDODBase::CanAttack( void )
+{
+ CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );
+
+ if ( pPlayer )
+ {
+ return pPlayer->CanAttack();
+ }
+
+ return false;
+}
+
+bool CWeaponDODBase::ShouldAutoReload( void )
+{
+ CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );
+
+ if ( pPlayer )
+ {
+ return pPlayer->ShouldAutoReload();
+ }
+
+ return false;
+}
+
+void CWeaponDODBase::ItemPostFrame()
+{
+ if ( m_flSmackTime > 0 && gpGlobals->curtime > m_flSmackTime )
+ {
+ Smack();
+ m_flSmackTime = -1;
+ }
+
+ CBasePlayer *pPlayer = GetPlayerOwner();
+
+ if ( !pPlayer )
+ return;
+
+#ifdef _DEBUG
+ CDODGameRules *mp = DODGameRules();
+#endif
+
+ assert( mp );
+
+ if ((m_bInReload) && (pPlayer->m_flNextAttack <= gpGlobals->curtime))
+ {
+ // complete the reload.
+ int j = MIN( GetMaxClip1() - m_iClip1, pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) );
+
+ // Add them to the clip
+ m_iClip1 += j;
+ pPlayer->RemoveAmmo( j, m_iPrimaryAmmoType );
+
+ m_bInReload = false;
+
+ FinishReload();
+ }
+
+ if ((pPlayer->m_nButtons & IN_ATTACK2) && (m_flNextSecondaryAttack <= gpGlobals->curtime))
+ {
+ if ( m_iClip2 != -1 && !pPlayer->GetAmmoCount( GetSecondaryAmmoType() ) )
+ {
+ m_bFireOnEmpty = TRUE;
+ }
+
+ SecondaryAttack();
+
+ pPlayer->m_nButtons &= ~IN_ATTACK2;
+ }
+ else if ((pPlayer->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime ) && !m_bInAttack )
+ {
+ if ( (m_iClip1 == 0/* && pszAmmo1()*/) || (GetMaxClip1() == -1 && !pPlayer->GetAmmoCount( GetPrimaryAmmoType() ) ) )
+ {
+ m_bFireOnEmpty = TRUE;
+ }
+
+ if( CanAttack() )
+ PrimaryAttack();
+ }
+ else if ( pPlayer->m_nButtons & IN_RELOAD && GetMaxClip1() != WEAPON_NOCLIP && !m_bInReload && m_flNextPrimaryAttack < gpGlobals->curtime)
+ {
+ // reload when reload is pressed, or if no buttons are down and weapon is empty.
+ Reload();
+ }
+ else if ( !(pPlayer->m_nButtons & (IN_ATTACK|IN_ATTACK2) ) )
+ {
+ // no fire buttons down
+
+ m_bFireOnEmpty = false;
+
+ m_bInAttack = false; //reset semi-auto
+
+ if ( !IsUseable() && m_flNextPrimaryAttack < gpGlobals->curtime )
+ {
+ // Intentionally blank -- used to switch weapons here
+ }
+ else if( ShouldAutoReload() )
+ {
+ // weapon is useable. Reload if empty and weapon has waited as long as it has to after firing
+ if ( m_iClip1 == 0 && !(GetWeaponFlags() & ITEM_FLAG_NOAUTORELOAD) && m_flNextPrimaryAttack < gpGlobals->curtime )
+ {
+ Reload();
+ return;
+ }
+ }
+
+ WeaponIdle( );
+ return;
+ }
+}
+
+void CWeaponDODBase::WeaponIdle()
+{
+ if (m_flTimeWeaponIdle > gpGlobals->curtime)
+ return;
+
+ SendWeaponAnim( GetIdleActivity() );
+
+ m_flTimeWeaponIdle = gpGlobals->curtime + SequenceDuration();
+}
+
+Activity CWeaponDODBase::GetIdleActivity( void )
+{
+ return ACT_VM_IDLE;
+}
+
+const CDODWeaponInfo &CWeaponDODBase::GetDODWpnData() const
+{
+ const FileWeaponInfo_t *pWeaponInfo = &GetWpnData();
+ const CDODWeaponInfo *pDODInfo;
+
+ #ifdef _DEBUG
+ pDODInfo = dynamic_cast< const CDODWeaponInfo* >( pWeaponInfo );
+ Assert( pDODInfo );
+ #else
+ pDODInfo = static_cast< const CDODWeaponInfo* >( pWeaponInfo );
+ #endif
+
+ return *pDODInfo;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+const char *CWeaponDODBase::GetViewModel( int /*viewmodelindex = 0 -- this is ignored in the base class here*/ ) const
+{
+ if ( GetPlayerOwner() == NULL )
+ {
+ return BaseClass::GetViewModel();
+ }
+
+ return GetWpnData().szViewModel;
+}
+
+void CWeaponDODBase::Precache( void )
+{
+ // precache base first, it loads weapon scripts
+ BaseClass::Precache();
+
+ PrecacheScriptSound( "Default.ClipEmpty_Rifle" );
+
+ PrecacheParticleSystem( "muzzle_pistols" );
+ PrecacheParticleSystem( "muzzle_fullyautomatic" );
+ PrecacheParticleSystem( "muzzle_rifles" );
+ PrecacheParticleSystem( "muzzle_rockets" );
+ PrecacheParticleSystem( "muzzle_mg42" );
+
+ PrecacheParticleSystem( "view_muzzle_pistols" );
+ PrecacheParticleSystem( "view_muzzle_fullyautomatic" );
+ PrecacheParticleSystem( "view_muzzle_rifles" );
+ PrecacheParticleSystem( "view_muzzle_rockets" );
+ PrecacheParticleSystem( "view_muzzle_mg42" );
+
+ const CDODWeaponInfo &info = GetDODWpnData();
+
+ int iWpnNameLen = Q_strlen(info.m_szReloadModel);
+
+#ifdef DEBUG
+ // Make sure that if we declare an alt weapon, that we have criteria to show it
+ // and vice-versa
+ //Assert( ((info.m_iAltWpnCriteria & (ALTWPN_CRITERIA_RELOADING | ALTWPN_CRITERIA_FIRING)) > 0 ) ==
+ // (iWpnNameLen > 0) );
+#endif
+
+ if( iWpnNameLen > 0 )
+ m_iReloadModelIndex = CBaseEntity::PrecacheModel( info.m_szReloadModel );
+}
+
+bool CWeaponDODBase::DefaultDeploy( char *szViewModel, char *szWeaponModel, int iActivity, char *szAnimExt )
+{
+ CBasePlayer *pOwner = GetPlayerOwner();
+ if ( !pOwner )
+ {
+ return false;
+ }
+
+ pOwner->SetAnimationExtension( szAnimExt );
+
+ SetViewModel();
+ SendWeaponAnim( iActivity );
+
+ pOwner->SetNextAttack( gpGlobals->curtime + SequenceDuration() );
+ m_flNextPrimaryAttack = MAX( m_flNextPrimaryAttack, gpGlobals->curtime );
+ m_flNextSecondaryAttack = gpGlobals->curtime;
+
+ SetWeaponVisible( true );
+ SetWeaponModelIndex( szWeaponModel );
+
+ CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex );
+
+ Assert( vm );
+
+ if( vm )
+ {
+ //set sleeves to proper team
+ switch( pOwner->GetTeamNumber() )
+ {
+ case TEAM_ALLIES:
+ vm->m_nSkin = SLEEVE_ALLIES;
+ break;
+ case TEAM_AXIS:
+ vm->m_nSkin = SLEEVE_AXIS;
+ break;
+ default:
+ Assert( !"TEAM_UNASSIGNED or spectator getting a view model assigned" );
+ break;
+ }
+ }
+
+ return true;
+}
+
+void CWeaponDODBase::SetWeaponModelIndex( const char *pName )
+{
+ m_iWorldModelIndex = modelinfo->GetModelIndex( pName );
+}
+
+bool CWeaponDODBase::CanBeSelected( void )
+{
+ if ( !VisibleInWeaponSelection() )
+ return false;
+
+ return true;
+}
+
+bool CWeaponDODBase::CanDeploy( void )
+{
+ return BaseClass::CanDeploy();
+}
+
+bool CWeaponDODBase::CanHolster( void )
+{
+ return BaseClass::CanHolster();
+}
+
+void CWeaponDODBase::Drop( const Vector &vecVelocity )
+{
+#ifndef CLIENT_DLL
+ if ( m_iAltFireHint )
+ {
+ CDODPlayer *pPlayer = GetDODPlayerOwner();
+ if ( pPlayer )
+ {
+ pPlayer->StopHintTimer( m_iAltFireHint );
+ }
+ }
+#endif
+
+ // cancel any reload in progress
+ m_bInReload = false;
+
+ m_flSmackTime = -1;
+
+ m_vInitialDropVelocity = vecVelocity;
+
+ BaseClass::Drop( m_vInitialDropVelocity );
+}
+
+bool CWeaponDODBase::Holster( CBaseCombatWeapon *pSwitchingTo )
+{
+#ifndef CLIENT_DLL
+ CDODPlayer *pPlayer = GetDODPlayerOwner();
+
+ if ( pPlayer )
+ {
+ pPlayer->SetFOV( pPlayer, 0 ); // reset the default FOV.
+
+ if ( m_iAltFireHint )
+ {
+ pPlayer->StopHintTimer( m_iAltFireHint );
+ }
+ }
+#endif
+
+ m_bInReload = false;
+
+ m_flSmackTime = -1;
+
+ return BaseClass::Holster( pSwitchingTo );
+}
+
+bool CWeaponDODBase::Deploy()
+{
+#ifndef CLIENT_DLL
+ CDODPlayer *pPlayer = GetDODPlayerOwner();
+
+ if ( pPlayer )
+ {
+ pPlayer->SetFOV( pPlayer, 0 );
+
+ if ( m_iAltFireHint )
+ {
+ pPlayer->StartHintTimer( m_iAltFireHint );
+ }
+ }
+#endif
+
+ return BaseClass::Deploy();
+}
+
+#ifdef CLIENT_DLL
+
+ void CWeaponDODBase::PostDataUpdate( DataUpdateType_t updateType )
+ {
+ // We need to do this before the C_BaseAnimating code starts to drive
+ // clientside animation sequences on this model, which will be using bad sequences for the world model.
+ int iDesiredModelIndex = 0;
+ C_BasePlayer *localplayer = C_BasePlayer::GetLocalPlayer();
+ if ( localplayer && localplayer == GetOwner() && !C_BasePlayer::ShouldDrawLocalPlayer() ) // FIXME: use localplayer->ShouldDrawThisPlayer() instead.
+ {
+ iDesiredModelIndex = m_iViewModelIndex;
+ }
+ else
+ {
+ iDesiredModelIndex = GetWorldModelIndex();
+
+ // Our world models never animate
+ SetSequence( 0 );
+ }
+
+ if ( GetModelIndex() != iDesiredModelIndex )
+ {
+ SetModelIndex( iDesiredModelIndex );
+ }
+
+ BaseClass::PostDataUpdate( updateType );
+ }
+
+ void CWeaponDODBase::OnDataChanged( DataUpdateType_t type )
+ {
+ if ( m_iState == WEAPON_NOT_CARRIED && m_iOldState != WEAPON_NOT_CARRIED )
+ {
+ // we are being notified of the weapon being dropped
+ // add an interpolation history so the movement is smoother
+
+ // Now stick our initial velocity into the interpolation history
+ CInterpolatedVar< Vector > &interpolator = GetOriginInterpolator();
+
+ interpolator.ClearHistory();
+ float changeTime = GetLastChangeTime( LATCH_SIMULATION_VAR );
+
+ // Add a sample 1 second back.
+ Vector vCurOrigin = GetLocalOrigin() - m_vInitialDropVelocity;
+ interpolator.AddToHead( changeTime - 1.0, &vCurOrigin, false );
+
+ // Add the current sample.
+ vCurOrigin = GetLocalOrigin();
+ interpolator.AddToHead( changeTime, &vCurOrigin, false );
+
+ Vector estVel;
+ EstimateAbsVelocity( estVel );
+
+ /*Msg( "estimated velocity ( %.1f %.1f %.1f ) initial velocity ( %.1f %.1f %.1f )\n",
+ estVel.x,
+ estVel.y,
+ estVel.z,
+ m_vInitialDropVelocity.m_Value.x,
+ m_vInitialDropVelocity.m_Value.y,
+ m_vInitialDropVelocity.m_Value.z );*/
+
+ OnWeaponDropped();
+ }
+
+ BaseClass::OnDataChanged( type );
+
+ if ( GetPredictable() && !ShouldPredict() )
+ ShutdownPredictable();
+ }
+
+ int CWeaponDODBase::GetWorldModelIndex( void )
+ {
+ if( m_bUseAltWeaponModel && GetOwner() != NULL )
+ return m_iReloadModelIndex;
+ else
+ return m_iWorldModelIndex;
+ }
+
+ bool CWeaponDODBase::ShouldPredict()
+ {
+ if ( GetOwner() && GetOwner() == C_BasePlayer::GetLocalPlayer() )
+ return true;
+
+ return BaseClass::ShouldPredict();
+ }
+
+ void CWeaponDODBase::ProcessMuzzleFlashEvent()
+ {
+ CDODPlayer *pPlayer = GetDODPlayerOwner();
+ if ( pPlayer )
+ pPlayer->ProcessMuzzleFlashEvent();
+
+ BaseClass::ProcessMuzzleFlashEvent();
+ }
+#else
+
+
+ //-----------------------------------------------------------------------------
+ // Purpose: Get the accuracy derived from weapon and player, and return it
+ //-----------------------------------------------------------------------------
+ const Vector& CWeaponDODBase::GetBulletSpread()
+ {
+ static Vector cone = VECTOR_CONE_8DEGREES;
+ return cone;
+ }
+
+ //-----------------------------------------------------------------------------
+ // Purpose:
+ //-----------------------------------------------------------------------------
+ void CWeaponDODBase::ItemBusyFrame()
+ {
+ if( ShouldAutoReload() && !m_bInReload )
+ {
+ // weapon is useable. Reload if empty and weapon has waited as long as it has to after firing
+ if ( m_iClip1 == 0 && !(GetWeaponFlags() & ITEM_FLAG_NOAUTORELOAD) && m_flNextPrimaryAttack < gpGlobals->curtime )
+ {
+ Reload();
+ }
+ }
+
+ BaseClass::ItemBusyFrame();
+ }
+
+ //-----------------------------------------------------------------------------
+ // Purpose: Match the anim speed to the weapon speed while crouching
+ //-----------------------------------------------------------------------------
+ float CWeaponDODBase::GetDefaultAnimSpeed()
+ {
+ return 1.0;
+ }
+
+ bool CWeaponDODBase::ShouldRemoveOnRoundRestart()
+ {
+ if ( GetPlayerOwner() )
+ return false;
+ else
+ return true;
+ }
+
+
+ //=========================================================
+ // Materialize - make a CWeaponDODBase visible and tangible
+ //=========================================================
+ void CWeaponDODBase::Materialize()
+ {
+ if ( IsEffectActive( EF_NODRAW ) )
+ {
+ RemoveEffects( EF_NODRAW );
+ DoMuzzleFlash();
+ }
+
+ AddSolidFlags( FSOLID_TRIGGER );
+
+ SetThink (&CWeaponDODBase::SUB_Remove);
+ SetNextThink( gpGlobals->curtime + 1 );
+ }
+
+ //=========================================================
+ // AttemptToMaterialize - the item is trying to rematerialize,
+ // should it do so now or wait longer?
+ //=========================================================
+ void CWeaponDODBase::AttemptToMaterialize()
+ {
+ float time = g_pGameRules->FlWeaponTryRespawn( this );
+
+ if ( time == 0 )
+ {
+ Materialize();
+ return;
+ }
+
+ SetNextThink( gpGlobals->curtime + time );
+ }
+
+ //=========================================================
+ // CheckRespawn - a player is taking this weapon, should
+ // it respawn?
+ //=========================================================
+ void CWeaponDODBase::CheckRespawn()
+ {
+ //GOOSEMAN : Do not respawn weapons!
+ return;
+ }
+
+
+ //=========================================================
+ // Respawn- this item is already in the world, but it is
+ // invisible and intangible. Make it visible and tangible.
+ //=========================================================
+ CBaseEntity* CWeaponDODBase::Respawn()
+ {
+ // make a copy of this weapon that is invisible and inaccessible to players (no touch function). The weapon spawn/respawn code
+ // will decide when to make the weapon visible and touchable.
+ CBaseEntity *pNewWeapon = CBaseEntity::Create( GetClassname(), g_pGameRules->VecWeaponRespawnSpot( this ), GetAbsAngles(), GetOwner() );
+
+ if ( pNewWeapon )
+ {
+ pNewWeapon->AddEffects( EF_NODRAW );// invisible for now
+ pNewWeapon->SetTouch( NULL );// no touch
+ pNewWeapon->SetThink( &CWeaponDODBase::AttemptToMaterialize );
+
+ UTIL_DropToFloor( this, MASK_SOLID );
+
+ // not a typo! We want to know when the weapon the player just picked up should respawn! This new entity we created is the replacement,
+ // but when it should respawn is based on conditions belonging to the weapon that was taken.
+ pNewWeapon->SetNextThink( gpGlobals->curtime + g_pGameRules->FlWeaponRespawnTime( this ) );
+ }
+ else
+ {
+ Msg( "Respawn failed to create %s!\n", GetClassname() );
+ }
+
+ return pNewWeapon;
+ }
+
+ bool CWeaponDODBase::Reload()
+ {
+ return BaseClass::Reload();
+ }
+
+ void CWeaponDODBase::Spawn()
+ {
+ BaseClass::Spawn();
+
+ // Set this here to allow players to shoot dropped weapons
+ SetCollisionGroup( COLLISION_GROUP_WEAPON );
+
+ SetExtraAmmoCount(0); //Start with no additional ammo
+
+ CollisionProp()->UseTriggerBounds( true, 10.0f );
+ }
+
+ void CWeaponDODBase::SetDieThink( bool bDie )
+ {
+ if( bDie )
+ SetContextThink( &CWeaponDODBase::Die, gpGlobals->curtime + 45.0f, "DieContext" );
+ else
+ SetContextThink( NULL, gpGlobals->curtime, "DieContext" );
+ }
+
+ void CWeaponDODBase::Die( void )
+ {
+ UTIL_Remove( this );
+ }
+
+#endif
+
+void CWeaponDODBase::OnPickedUp( CBaseCombatCharacter *pNewOwner )
+{
+ BaseClass::OnPickedUp( pNewOwner );
+
+#if !defined( CLIENT_DLL )
+ SetDieThink( false );
+#endif
+}
+
+bool CWeaponDODBase::DefaultReload( int iClipSize1, int iClipSize2, int iActivity )
+{
+ CBaseCombatCharacter *pOwner = GetOwner();
+ if (!pOwner)
+ return false;
+
+ // If I don't have any spare ammo, I can't reload
+ if ( pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0 )
+ return false;
+
+ bool bReload = false;
+
+ // If you don't have clips, then don't try to reload them.
+ if ( UsesClipsForAmmo1() )
+ {
+ // need to reload primary clip?
+ int primary = min(iClipSize1 - m_iClip1, pOwner->GetAmmoCount(m_iPrimaryAmmoType));
+ if ( primary != 0 )
+ {
+ bReload = true;
+ }
+ }
+
+ if ( UsesClipsForAmmo2() )
+ {
+ // need to reload secondary clip?
+ int secondary = min(iClipSize2 - m_iClip2, pOwner->GetAmmoCount(m_iSecondaryAmmoType));
+ if ( secondary != 0 )
+ {
+ bReload = true;
+ }
+ }
+
+ if ( !bReload )
+ return false;
+
+ CDODPlayer *pPlayer = GetDODPlayerOwner();
+ if ( pPlayer )
+ {
+#ifdef CLIENT_DLL
+ PlayWorldReloadSound( pPlayer );
+#else
+ pPlayer->DoAnimationEvent( PLAYERANIMEVENT_RELOAD );
+#endif
+ }
+
+ SendWeaponAnim( iActivity );
+
+ // Play the player's reload animation
+ if ( pOwner->IsPlayer() )
+ {
+ ( ( CBasePlayer * )pOwner)->SetAnimation( PLAYER_RELOAD );
+ }
+
+ float flSequenceEndTime = gpGlobals->curtime + SequenceDuration();
+ pOwner->SetNextAttack( flSequenceEndTime );
+ m_flNextPrimaryAttack = m_flNextSecondaryAttack = flSequenceEndTime;
+
+ m_bInReload = true;
+
+ return true;
+}
+
+#ifdef CLIENT_DLL
+ void CWeaponDODBase::PlayWorldReloadSound( CDODPlayer *pPlayer )
+ {
+ Assert( pPlayer );
+
+ const char *shootsound = GetShootSound( RELOAD );
+ if ( !shootsound || !shootsound[0] )
+ return;
+
+ CSoundParameters params;
+
+ if ( !GetParametersForSound( shootsound, params, NULL ) )
+ return;
+
+ // Play weapon sound from the owner
+ CPASAttenuationFilter filter( pPlayer, params.soundlevel );
+ filter.RemoveRecipient( pPlayer ); // no local player, that is done in the model
+
+ EmitSound( filter, pPlayer->entindex(), shootsound, NULL, 0.0 );
+ }
+#endif
+
+bool CWeaponDODBase::IsUseable()
+{
+ CBasePlayer *pPlayer = GetPlayerOwner();
+
+ if ( Clip1() <= 0 )
+ {
+ if ( pPlayer->GetAmmoCount( GetPrimaryAmmoType() ) <= 0 && GetMaxClip1() != -1 )
+ {
+ // clip is empty (or nonexistant) and the player has no more ammo of this type.
+ return false;
+ }
+ }
+
+ return true;
+}
+
+#ifndef CLIENT_DLL
+ConVar dod_meleeattackforcescale( "dod_meleeattackforcescale", "8.0", FCVAR_CHEAT | FCVAR_GAMEDLL );
+#endif
+
+void CWeaponDODBase::RifleButt( void )
+{
+ //MeleeAttack( 60, MELEE_DMG_BUTTSTOCK | MELEE_DMG_SECONDARYATTACK, 0.2f, 0.9f );
+}
+
+void CWeaponDODBase::Bayonet( void )
+{
+ //MeleeAttack( 60, MELEE_DMG_BAYONET | MELEE_DMG_SECONDARYATTACK, 0.2f, 0.9f );
+}
+
+void CWeaponDODBase::Punch( void )
+{
+ MeleeAttack( 60, MELEE_DMG_FIST | MELEE_DMG_SECONDARYATTACK, 0.2f, 0.4f );
+}
+
+//--------------------------------------------
+// iDamageAmount - how much damage to give
+// iDamageType - DMG_ bits
+// flDmgDelay - delay between attack and the giving of damage, usually timed to animation
+// flAttackDelay - time until we can next attack
+//--------------------------------------------
+CBaseEntity *CWeaponDODBase::MeleeAttack( int iDamageAmount, int iDamageType, float flDmgDelay, float flAttackDelay )
+{
+ if ( !CanAttack() )
+ return NULL;
+
+ CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );
+
+#if !defined (CLIENT_DLL)
+ // Move other players back to history positions based on local player's lag
+ lagcompensation->StartLagCompensation( pPlayer, pPlayer->GetCurrentCommand() );
+#endif
+
+ Vector vForward, vRight, vUp;
+ AngleVectors( pPlayer->EyeAngles(), &vForward, &vRight, &vUp );
+ Vector vecSrc = pPlayer->Weapon_ShootPosition();
+ Vector vecEnd = vecSrc + vForward * 48;
+
+ CTraceFilterSimple filter( pPlayer, COLLISION_GROUP_NONE );
+
+ int iTraceMask = MASK_SOLID | CONTENTS_HITBOX | CONTENTS_DEBRIS;
+
+ trace_t tr;
+ UTIL_TraceLine( vecSrc, vecEnd, iTraceMask, &filter, &tr );
+
+ const float rayExtension = 40.0f;
+ UTIL_ClipTraceToPlayers( vecSrc, vecEnd + vForward * rayExtension, iTraceMask, &filter, &tr );
+
+ // If the exact forward trace did not hit, try a larger swept box
+ if ( tr.fraction >= 1.0 )
+ {
+ Vector head_hull_mins( -16, -16, -18 );
+ Vector head_hull_maxs( 16, 16, 18 );
+
+ UTIL_TraceHull( vecSrc, vecEnd, head_hull_mins, head_hull_maxs, MASK_SOLID, &filter, &tr );
+ if ( tr.fraction < 1.0 )
+ {
+ // Calculate the point of intersection of the line (or hull) and the object we hit
+ // This is and approximation of the "best" intersection
+ CBaseEntity *pHit = tr.m_pEnt;
+ if ( !pHit || pHit->IsBSPModel() )
+ FindHullIntersection( vecSrc, tr, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, pPlayer );
+ vecEnd = tr.endpos; // This is the point on the actual surface (the hull could have hit space)
+
+ // Make sure it is in front of us
+ Vector vecToEnd = vecEnd - vecSrc;
+ VectorNormalize( vecToEnd );
+
+ // if zero length, always hit
+ if ( vecToEnd.Length() > 0 )
+ {
+ float dot = DotProduct( vForward, vecToEnd );
+
+ // sanity that our hit is within range
+ if ( abs(dot) < 0.95 )
+ {
+ // fake that we actually missed
+ tr.fraction = 1.0;
+ }
+ }
+ }
+ }
+
+ WeaponSound( MELEE_MISS );
+
+ bool bDidHit = ( tr.fraction < 1.0f );
+
+ if ( bDidHit ) //if the swing hit
+ {
+ // delay the decal a bit
+ m_trHit = tr;
+
+ // Store the ent in an EHANDLE, just in case it goes away by the time we get into our think function.
+ m_pTraceHitEnt = tr.m_pEnt;
+
+ m_iSmackDamage = iDamageAmount;
+ m_iSmackDamageType = iDamageType;
+
+ m_flSmackTime = gpGlobals->curtime + flDmgDelay;
+ }
+
+ SendWeaponAnim( GetMeleeActivity() );
+
+ // player animation
+ pPlayer->DoAnimationEvent( PLAYERANIMEVENT_SECONDARY_ATTACK );
+
+ m_flNextPrimaryAttack = gpGlobals->curtime + flAttackDelay;
+ m_flNextSecondaryAttack = gpGlobals->curtime + flAttackDelay;
+ m_flTimeWeaponIdle = gpGlobals->curtime + SequenceDuration();
+
+#ifndef CLIENT_DLL
+ IGameEvent * event = gameeventmanager->CreateEvent( "dod_stats_weapon_attack" );
+ if ( event )
+ {
+ event->SetInt( "attacker", pPlayer->GetUserID() );
+ event->SetInt( "weapon", GetAltWeaponID() );
+
+ gameeventmanager->FireEvent( event );
+ }
+
+ lagcompensation->FinishLagCompensation( pPlayer );
+#endif //CLIENT_DLL
+
+ return tr.m_pEnt;
+}
+
+//Think function to delay the impact decal until the animation is finished playing
+void CWeaponDODBase::Smack()
+{
+ Assert( GetPlayerOwner() );
+
+ if ( !GetPlayerOwner() )
+ return;
+
+ CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );
+
+ if ( !pPlayer )
+ return;
+
+ // Check that we are still facing the victim
+ Vector vForward, vRight, vUp;
+ AngleVectors( pPlayer->EyeAngles(), &vForward, &vRight, &vUp );
+ Vector vecSrc = pPlayer->Weapon_ShootPosition();
+ Vector vecEnd = vecSrc + vForward * 48;
+
+ CTraceFilterSimple filter( pPlayer, COLLISION_GROUP_NONE );
+
+ int iTraceMask = MASK_SOLID | CONTENTS_HITBOX | CONTENTS_DEBRIS;
+
+ trace_t tr;
+ UTIL_TraceLine( vecSrc, vecEnd, iTraceMask, &filter, &tr );
+
+ const float rayExtension = 40.0f;
+ UTIL_ClipTraceToPlayers( vecSrc, vecEnd + vForward * rayExtension, iTraceMask, &filter, &tr );
+
+ if ( tr.fraction >= 1.0 )
+ {
+ Vector head_hull_mins( -16, -16, -18 );
+ Vector head_hull_maxs( 16, 16, 18 );
+
+ UTIL_TraceHull( vecSrc, vecEnd, head_hull_mins, head_hull_maxs, MASK_SOLID, &filter, &tr );
+ if ( tr.fraction < 1.0 )
+ {
+ // Calculate the point of intersection of the line (or hull) and the object we hit
+ // This is and approximation of the "best" intersection
+ CBaseEntity *pHit = tr.m_pEnt;
+ if ( !pHit || pHit->IsBSPModel() )
+ FindHullIntersection( vecSrc, tr, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, pPlayer );
+ vecEnd = tr.endpos; // This is the point on the actual surface (the hull could have hit space)
+ }
+ }
+
+ m_trHit = tr;
+
+ if ( !m_trHit.m_pEnt || (m_trHit.surface.flags & SURF_SKY) )
+ return;
+
+ if ( m_trHit.fraction == 1.0 )
+ return;
+
+ CPASAttenuationFilter attenuationFilter( this );
+ attenuationFilter.UsePredictionRules();
+
+ if( m_trHit.m_pEnt->IsPlayer() )
+ {
+ if ( m_iSmackDamageType & MELEE_DMG_STRONGATTACK )
+ WeaponSound( SPECIAL1 );
+ else
+ WeaponSound( MELEE_HIT );
+ }
+ else
+ WeaponSound( MELEE_HIT_WORLD );
+
+ int iDamageType = DMG_CLUB | DMG_NEVERGIB;
+
+#ifndef CLIENT_DLL
+ //if they hit the bounding box, just assume a chest hit
+ if( m_trHit.hitgroup == HITGROUP_GENERIC )
+ m_trHit.hitgroup = HITGROUP_CHEST;
+
+ float flDamage = (float)m_iSmackDamage;
+
+ CTakeDamageInfo info( pPlayer, pPlayer, flDamage, iDamageType );
+
+ if ( m_iSmackDamageType & MELEE_DMG_SECONDARYATTACK )
+ info.SetDamageCustom( MELEE_DMG_SECONDARYATTACK );
+
+ float flScale = (1.0f / flDamage) * dod_meleeattackforcescale.GetFloat();
+
+ Vector vecForceDir = vForward;
+
+ CalculateMeleeDamageForce( &info, vecForceDir, m_trHit.endpos, flScale );
+
+ Assert( m_trHit.m_pEnt != GetPlayerOwner() );
+
+ m_trHit.m_pEnt->DispatchTraceAttack( info, vForward, &m_trHit );
+ ApplyMultiDamage();
+#endif
+
+ // We've gotten minidumps where this happened.
+ if ( !GetPlayerOwner() )
+ return;
+
+ CEffectData data;
+ data.m_vOrigin = m_trHit.endpos;
+ data.m_vStart = m_trHit.startpos;
+ data.m_nSurfaceProp = m_trHit.surface.surfaceProps;
+ data.m_nHitBox = m_trHit.hitbox;
+#ifdef CLIENT_DLL
+ data.m_hEntity = m_trHit.m_pEnt->GetRefEHandle();
+#else
+ data.m_nEntIndex = m_trHit.m_pEnt->entindex();
+#endif
+
+ CPASFilter effectfilter( data.m_vOrigin );
+
+#ifndef CLIENT_DLL
+ effectfilter.RemoveRecipient( GetPlayerOwner() );
+#endif
+
+ data.m_vAngles = GetPlayerOwner()->GetAbsAngles();
+ data.m_fFlags = 0x1; //IMPACT_NODECAL;
+ data.m_nDamageType = iDamageType;
+
+ bool bHitPlayer = m_trHit.m_pEnt && m_trHit.m_pEnt->IsPlayer();
+
+ // don't do any impacts if we hit a teammate and ff is off
+ if ( bHitPlayer &&
+ m_trHit.m_pEnt->GetTeamNumber() == GetPlayerOwner()->GetTeamNumber() &&
+ !friendlyfire.GetBool() )
+ return;
+
+ if ( bHitPlayer )
+ {
+ te->DispatchEffect( effectfilter, 0.0, data.m_vOrigin, "Impact", data );
+ }
+ else if ( m_iSmackDamageType & MELEE_DMG_EDGE )
+ {
+ data.m_nDamageType = DMG_SLASH;
+ te->DispatchEffect( effectfilter, 0.0, data.m_vOrigin, "KnifeSlash", data );
+ }
+}
+
+#if defined( CLIENT_DLL )
+
+ float g_lateralBob = 0;
+ float g_verticalBob = 0;
+
+ static ConVar cl_bobcycle( "cl_bobcycle","0.8" );
+ static ConVar cl_bob( "cl_bob","0.002" );
+ static ConVar cl_bobup( "cl_bobup","0.5" );
+
+ // Register these cvars if needed for easy tweaking
+ static ConVar v_iyaw_cycle( "v_iyaw_cycle", "2"/*, FCVAR_UNREGISTERED*/ );
+ static ConVar v_iroll_cycle( "v_iroll_cycle", "0.5"/*, FCVAR_UNREGISTERED*/ );
+ static ConVar v_ipitch_cycle( "v_ipitch_cycle", "1"/*, FCVAR_UNREGISTERED*/ );
+ static ConVar v_iyaw_level( "v_iyaw_level", "0.3"/*, FCVAR_UNREGISTERED*/ );
+ static ConVar v_iroll_level( "v_iroll_level", "0.1"/*, FCVAR_UNREGISTERED*/ );
+ static ConVar v_ipitch_level( "v_ipitch_level", "0.3"/*, FCVAR_UNREGISTERED*/ );
+
+ //-----------------------------------------------------------------------------
+ // Purpose:
+ // Output : float
+ //-----------------------------------------------------------------------------
+ float CWeaponDODBase::CalcViewmodelBob( void )
+ {
+ static float bobtime;
+ static float lastbobtime;
+ static float lastspeed;
+ float cycle;
+
+ CBasePlayer *player = ToBasePlayer( GetOwner() );
+ //Assert( player );
+
+ //NOTENOTE: For now, let this cycle continue when in the air, because it snaps badly without it
+
+ if ( ( !gpGlobals->frametime ) || ( player == NULL ) )
+ {
+ //NOTENOTE: We don't use this return value in our case (need to restructure the calculation function setup!)
+ return 0.0f;// just use old value
+ }
+
+ //Find the speed of the player
+ float speed = player->GetLocalVelocity().Length2D();
+ float flmaxSpeedDelta = MAX( 0, (gpGlobals->curtime - lastbobtime) * 320.0f );
+
+ // don't allow too big speed changes
+ speed = clamp( speed, lastspeed-flmaxSpeedDelta, lastspeed+flmaxSpeedDelta );
+ speed = clamp( speed, -320, 320 );
+
+ lastspeed = speed;
+
+ //FIXME: This maximum speed value must come from the server.
+ // MaxSpeed() is not sufficient for dealing with sprinting - jdw
+
+ float bob_offset = RemapVal( speed, 0, 320, 0.0f, 1.0f );
+
+ bobtime += ( gpGlobals->curtime - lastbobtime ) * bob_offset;
+ lastbobtime = gpGlobals->curtime;
+
+ //Calculate the vertical bob
+ cycle = bobtime - (int)(bobtime/cl_bobcycle.GetFloat())*cl_bobcycle.GetFloat();
+ cycle /= cl_bobcycle.GetFloat();
+
+ if ( cycle < cl_bobup.GetFloat() )
+ {
+ cycle = M_PI * cycle / cl_bobup.GetFloat();
+ }
+ else
+ {
+ cycle = M_PI + M_PI*(cycle-cl_bobup.GetFloat())/(1.0 - cl_bobup.GetFloat());
+ }
+
+ g_verticalBob = speed*0.005f;
+ g_verticalBob = g_verticalBob*0.3 + g_verticalBob*0.7*sin(cycle);
+
+ g_verticalBob = clamp( g_verticalBob, -7.0f, 4.0f );
+
+ //Calculate the lateral bob
+ cycle = bobtime - (int)(bobtime/cl_bobcycle.GetFloat()*2)*cl_bobcycle.GetFloat()*2;
+ cycle /= cl_bobcycle.GetFloat()*2;
+
+ if ( cycle < cl_bobup.GetFloat() )
+ {
+ cycle = M_PI * cycle / cl_bobup.GetFloat();
+ }
+ else
+ {
+ cycle = M_PI + M_PI*(cycle-cl_bobup.GetFloat())/(1.0 - cl_bobup.GetFloat());
+ }
+
+ g_lateralBob = speed*0.005f;
+ g_lateralBob = g_lateralBob*0.3 + g_lateralBob*0.7*sin(cycle);
+ g_lateralBob = clamp( g_lateralBob, -7.0f, 4.0f );
+
+ //NOTENOTE: We don't use this return value in our case (need to restructure the calculation function setup!)
+ return 0.0f;
+
+ }
+
+ //-----------------------------------------------------------------------------
+ // Purpose:
+ // Input : &origin -
+ // &angles -
+ // viewmodelindex -
+ //-----------------------------------------------------------------------------
+ void CWeaponDODBase::AddViewmodelBob( CBaseViewModel *viewmodel, Vector &origin, QAngle &angles )
+ {
+ Vector forward, right;
+ AngleVectors( angles, &forward, &right, NULL );
+
+ CalcViewmodelBob();
+
+ // Apply bob, but scaled down to 40%
+ VectorMA( origin, g_verticalBob * 0.4f, forward, origin );
+
+ // Z bob a bit more
+ origin[2] += g_verticalBob * 0.1f;
+
+ // bob the angles
+ angles[ ROLL ] += g_verticalBob * 0.5f;
+ angles[ PITCH ] -= g_verticalBob * 0.4f;
+
+ angles[ YAW ] -= g_lateralBob * 0.3f;
+
+ // VectorMA( origin, g_lateralBob * 0.2f, right, origin );
+ }
+
+ #include "c_te_effect_dispatch.h"
+
+ #define NUM_MUZZLE_FLASH_TYPES 4
+
+ bool CWeaponDODBase::OnFireEvent( C_BaseViewModel *pViewModel, const Vector& origin, const QAngle& angles, int event, const char *options )
+ {
+ if( event == 5001 )
+ {
+ if ( ShouldDrawMuzzleFlash() )
+ {
+ Assert( GetOwnerEntity() == C_BasePlayer::GetLocalPlayer() );
+
+ const char *pszMuzzleFlashEffect;
+
+ switch( GetDODWpnData().m_iMuzzleFlashType )
+ {
+ case DOD_MUZZLEFLASH_PISTOL:
+ pszMuzzleFlashEffect = "view_muzzle_pistols";
+ break;
+ case DOD_MUZZLEFLASH_AUTO:
+ pszMuzzleFlashEffect = "view_muzzle_fullyautomatic";
+ break;
+ case DOD_MUZZLEFLASH_RIFLE:
+ pszMuzzleFlashEffect = "view_muzzle_rifles";
+ break;
+ case DOD_MUZZLEFLASH_MG:
+ pszMuzzleFlashEffect = "view_muzzle_miniguns";
+ break;
+ case DOD_MUZZLEFLASH_ROCKET:
+ pszMuzzleFlashEffect = "view_muzzle_rockets";
+ break;
+ case DOD_MUZZLEFLASH_MG42:
+ pszMuzzleFlashEffect = "view_muzzle_mg42";
+ break;
+ default:
+ pszMuzzleFlashEffect = NULL;
+ break;
+ }
+
+ if ( pszMuzzleFlashEffect )
+ {
+ pViewModel->ParticleProp()->Create( pszMuzzleFlashEffect, PATTACH_POINT_FOLLOW, 1 );
+ }
+ }
+ return true;
+ }
+ else if( event == 6002 )
+ {
+ CEffectData data;
+ data.m_nHitBox = atoi( options );
+ data.m_hEntity = GetPlayerOwner() ? GetPlayerOwner()->GetRefEHandle() : INVALID_EHANDLE_INDEX;
+ pViewModel->GetAttachment( 2, data.m_vOrigin, data.m_vAngles );
+
+ DispatchEffect( "DOD_EjectBrass", data );
+ return true;
+ }
+
+ return BaseClass::OnFireEvent( pViewModel, origin, angles, event, options );
+ }
+
+ bool CWeaponDODBase::ShouldAutoEjectBrass( void )
+ {
+ // Don't eject brass if further than N units from the local player
+ C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
+ if ( !pLocalPlayer )
+ return true;
+
+ float flMaxDistSqr = 250;
+ flMaxDistSqr *= flMaxDistSqr;
+
+ float flDistSqr = pLocalPlayer->EyePosition().DistToSqr( GetAbsOrigin() );
+ return ( flDistSqr < flMaxDistSqr );
+ }
+
+ bool CWeaponDODBase::GetEjectBrassShellType( void )
+ {
+ return 1;
+ }
+
+ void CWeaponDODBase::SetUseAltModel( bool bUseAltModel )
+ {
+ m_bUseAltWeaponModel = bUseAltModel;
+ }
+
+ void CWeaponDODBase::CheckForAltWeapon( int iCurrentState )
+ {
+ int iCriteria = GetDODWpnData().m_iAltWpnCriteria;
+
+ bool bUseAltModel = false;
+
+ if( ( iCriteria & iCurrentState ) != 0 )
+ bUseAltModel = true;
+
+ SetUseAltModel( bUseAltModel );
+ }
+
+ Vector CWeaponDODBase::GetDesiredViewModelOffset( C_DODPlayer *pOwner )
+ {
+ Vector viewOffset = pOwner->GetViewOffset();
+
+ float flPercent = ( viewOffset.z - VEC_PRONE_VIEW_SCALED( pOwner ).z ) / ( VEC_VIEW_SCALED( pOwner ).z - VEC_PRONE_VIEW_SCALED( pOwner ).z );
+
+ return ( flPercent * GetDODWpnData().m_vecViewNormalOffset +
+ ( 1.0 - flPercent ) * GetDODWpnData().m_vecViewProneOffset );
+ }
+
+ bool CWeaponDODBase::ShouldDraw( void )
+ {
+ if ( GetModel() == NULL )
+ {
+ // XXX(johns): Removed, doesn't seem to be the proper spot for this warning given that weapons can call
+ // ShouldDraw before their properties are filled.
+
+ // C_DODPlayer *pPlayer = C_DODPlayer::GetLocalDODPlayer();
+
+ // Warning( "BADNESS! Tell Matt that the weapon '%s' tried to draw with a null model ( %d, %d, %s ) \n",
+ // GetDODWpnData().szClassName,
+ // m_iWorldModelIndex.Get(), m_iReloadModelIndex.Get(), m_bUseAltWeaponModel ? "alt" : "not alt" );
+
+ return false;
+ }
+
+ return BaseClass::ShouldDraw();
+ }
+
+#else
+
+ void CWeaponDODBase::AddViewmodelBob( CBaseViewModel *viewmodel, Vector &origin, QAngle &angles )
+ {
+
+ }
+
+ float CWeaponDODBase::CalcViewmodelBob( void )
+ {
+ return 0.0f;
+ }
+
+ void CWeaponDODBase::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
+ {
+ if ( CanDrop() == false )
+ return;
+
+ CDODPlayer *pPlayer = ToDODPlayer( pActivator );
+
+ if ( pPlayer )
+ {
+ pPlayer->PickUpWeapon( this );
+ }
+ }
+
+#endif
+