2020-04-22 18:56:21 +02:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Laser Rifle & Shield combo
//
// $NoKeywords: $
//=============================================================================//
# include "cbase.h"
# include "in_buttons.h"
# include "takedamageinfo.h"
# include "weapon_csbase.h"
# include "ammodef.h"
# include "cs_gamerules.h"
# define ALLOW_WEAPON_SPREAD_DISPLAY 0
# if defined( CLIENT_DLL )
# include "vgui/ISurface.h"
# include "vgui_controls/Controls.h"
# include "c_cs_player.h"
# include "hud_crosshair.h"
# include "c_te_effect_dispatch.h"
# include "c_te_legacytempents.h"
extern IVModelInfoClient * modelinfo ;
# else
# include "cs_player.h"
# include "te_effect_dispatch.h"
# include "KeyValues.h"
# include "cs_ammodef.h"
extern IVModelInfo * modelinfo ;
# endif
ConVar weapon_accuracy_model ( " weapon_accuracy_model " , " 2 " , FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY | FCVAR_ARCHIVE ) ;
// ----------------------------------------------------------------------------- //
// Global functions.
// ----------------------------------------------------------------------------- //
struct WeaponAliasTranslationInfoStruct
{
const char * alias ;
const char * translatedAlias ;
} ;
static const WeaponAliasTranslationInfoStruct s_WeaponAliasTranslationInfo [ ] =
{
{ " cv47 " , " ak47 " } ,
{ " defender " , " galil " } ,
{ " krieg552 " , " sg552 " } ,
{ " magnum " , " awp " } ,
{ " d3au1 " , " g3sg1 " } ,
{ " clarion " , " famas " } ,
{ " bullpup " , " aug " } ,
{ " krieg550 " , " sg550 " } ,
{ " 9x19mm " , " glock " } ,
{ " km45 " , " usp " } ,
{ " 228compact " , " p228 " } ,
{ " nighthawk " , " deagle " } ,
{ " elites " , " elite " } ,
{ " fn57 " , " fiveseven " } ,
{ " 12gauge " , " m3 " } ,
{ " autoshotgun " , " xm1014 " } ,
{ " mp " , " tmp " } ,
{ " smg " , " mp5navy " } ,
{ " mp5 " , " mp5navy " } ,
{ " c90 " , " p90 " } ,
{ " vest " , " kevlar " } ,
{ " vesthelm " , " assaultsuit " } ,
{ " smokegrenade " , " sgren " } ,
{ " smokegrenade " , " sgren " } ,
{ " nvgs " , " nightvision " } ,
{ " " , " " } // this needs to be last
} ;
struct WeaponAliasInfo
{
CSWeaponID id ;
const char * alias ;
} ;
WeaponAliasInfo s_weaponAliasInfo [ ] =
{
{ WEAPON_P228 , " p228 " } ,
{ WEAPON_GLOCK , " glock " } ,
{ WEAPON_SCOUT , " scout " } ,
{ WEAPON_XM1014 , " xm1014 " } ,
{ WEAPON_MAC10 , " mac10 " } ,
{ WEAPON_AUG , " aug " } ,
{ WEAPON_ELITE , " elite " } ,
{ WEAPON_FIVESEVEN , " fiveseven " } ,
{ WEAPON_UMP45 , " ump45 " } ,
{ WEAPON_SG550 , " sg550 " } ,
{ WEAPON_GALIL , " galil " } ,
{ WEAPON_FAMAS , " famas " } ,
{ WEAPON_USP , " usp " } ,
{ WEAPON_AWP , " awp " } ,
{ WEAPON_MP5NAVY , " mp5navy " } ,
{ WEAPON_M249 , " m249 " } ,
{ WEAPON_M3 , " m3 " } ,
{ WEAPON_M4A1 , " m4a1 " } ,
{ WEAPON_TMP , " tmp " } ,
{ WEAPON_G3SG1 , " g3sg1 " } ,
{ WEAPON_DEAGLE , " deagle " } ,
{ WEAPON_SG552 , " sg552 " } ,
{ WEAPON_AK47 , " ak47 " } ,
{ WEAPON_P90 , " p90 " } ,
{ WEAPON_KNIFE , " knife " } ,
{ WEAPON_C4 , " c4 " } ,
{ WEAPON_FLASHBANG , " flashbang " } ,
{ WEAPON_SMOKEGRENADE , " smokegrenade " } ,
{ WEAPON_SMOKEGRENADE , " sgren " } ,
{ WEAPON_HEGRENADE , " hegrenade " } ,
{ WEAPON_HEGRENADE , " hegren " } ,
// not sure any of these are needed
{ WEAPON_SHIELDGUN , " shield " } ,
{ WEAPON_SHIELDGUN , " shieldgun " } ,
{ WEAPON_KEVLAR , " kevlar " } ,
{ WEAPON_ASSAULTSUIT , " assaultsuit " } ,
{ WEAPON_NVG , " nightvision " } ,
{ WEAPON_NVG , " nvg " } ,
{ WEAPON_NONE , " none " } ,
} ;
bool IsAmmoType ( int iAmmoType , const char * pAmmoName )
{
return GetAmmoDef ( ) - > Index ( pAmmoName ) = = iAmmoType ;
}
//--------------------------------------------------------------------------------------------------------
//
// Given an alias, return the translated alias.
//
const char * GetTranslatedWeaponAlias ( const char * szAlias )
{
for ( int i = 0 ; i < ARRAYSIZE ( s_WeaponAliasTranslationInfo ) ; + + i )
{
if ( Q_stricmp ( s_WeaponAliasTranslationInfo [ i ] . alias , szAlias ) = = 0 )
{
return s_WeaponAliasTranslationInfo [ i ] . translatedAlias ;
}
}
return szAlias ;
}
//--------------------------------------------------------------------------------------------------------
//
// Given a translated alias, return the alias.
//
const char * GetWeaponAliasFromTranslated ( const char * translatedAlias )
{
int i = 0 ;
const WeaponAliasTranslationInfoStruct * info = & ( s_WeaponAliasTranslationInfo [ i ] ) ;
while ( info - > alias [ 0 ] ! = 0 )
{
if ( Q_stricmp ( translatedAlias , info - > translatedAlias ) = = 0 )
{
return info - > alias ;
}
info = & ( s_WeaponAliasTranslationInfo [ + + i ] ) ;
}
return translatedAlias ;
}
//--------------------------------------------------------------------------------------------------------
//
// Given an alias, return the associated weapon ID
//
CSWeaponID AliasToWeaponID ( const char * szAlias )
{
if ( szAlias )
{
for ( int i = 0 ; i < ARRAYSIZE ( s_weaponAliasInfo ) ; + + i )
{
if ( Q_stricmp ( s_weaponAliasInfo [ i ] . alias , szAlias ) = = 0 )
return s_weaponAliasInfo [ i ] . id ;
}
}
return WEAPON_NONE ;
}
//--------------------------------------------------------------------------------------------------------
//
// Given a weapon ID, return its alias
//
const char * WeaponIDToAlias ( int id )
{
for ( int i = 0 ; i < ARRAYSIZE ( s_weaponAliasInfo ) ; + + i )
{
if ( s_weaponAliasInfo [ i ] . id = = id )
return s_weaponAliasInfo [ i ] . alias ;
}
return NULL ;
}
//--------------------------------------------------------------------------------------------------------
//
// Return true if given weapon ID is a primary weapon
//
bool IsPrimaryWeapon ( CSWeaponID id )
{
const CCSWeaponInfo * pWeaponInfo = GetWeaponInfo ( id ) ;
if ( pWeaponInfo )
{
return pWeaponInfo - > iSlot = = WEAPON_SLOT_RIFLE ;
}
return false ;
}
//--------------------------------------------------------------------------------------------------------
//
// Return true if given weapon ID is a secondary weapon
//
bool IsSecondaryWeapon ( CSWeaponID id )
{
const CCSWeaponInfo * pWeaponInfo = GetWeaponInfo ( id ) ;
if ( pWeaponInfo )
return pWeaponInfo - > iSlot = = WEAPON_SLOT_PISTOL ;
return false ;
}
# ifdef CLIENT_DLL
int GetShellForAmmoType ( const char * ammoname )
{
if ( ! Q_strcmp ( BULLET_PLAYER_762MM , ammoname ) )
return CS_SHELL_762NATO ;
if ( ! Q_strcmp ( BULLET_PLAYER_556MM , ammoname ) )
return CS_SHELL_556 ;
if ( ! Q_strcmp ( BULLET_PLAYER_338MAG , ammoname ) )
return CS_SHELL_338MAG ;
if ( ! Q_strcmp ( BULLET_PLAYER_BUCKSHOT , ammoname ) )
return CS_SHELL_12GAUGE ;
if ( ! Q_strcmp ( BULLET_PLAYER_57MM , ammoname ) )
return CS_SHELL_57 ;
// default 9 mm
return CS_SHELL_9MM ;
}
# endif
// ----------------------------------------------------------------------------- //
// CWeaponCSBase tables.
// ----------------------------------------------------------------------------- //
IMPLEMENT_NETWORKCLASS_ALIASED ( WeaponCSBase , DT_WeaponCSBase )
BEGIN_NETWORK_TABLE ( CWeaponCSBase , DT_WeaponCSBase )
# if !defined( CLIENT_DLL )
SendPropInt ( SENDINFO ( m_weaponMode ) , 1 , SPROP_UNSIGNED ) ,
2024-04-03 00:18:21 +02:00
SendPropFloat ( SENDINFO ( m_fAccuracyPenalty ) )
2020-04-22 18:56:21 +02:00
// SendPropExclude( "DT_LocalActiveWeaponData", "m_flTimeWeaponIdle" ),
# else
RecvPropInt ( RECVINFO ( m_weaponMode ) ) ,
RecvPropFloat ( RECVINFO ( m_fAccuracyPenalty ) ) ,
# endif
END_NETWORK_TABLE ( )
# if defined(CLIENT_DLL)
BEGIN_PREDICTION_DATA ( CWeaponCSBase )
DEFINE_PRED_FIELD ( m_flTimeWeaponIdle , FIELD_FLOAT , FTYPEDESC_OVERRIDE | FTYPEDESC_NOERRORCHECK ) ,
DEFINE_PRED_FIELD ( m_flNextPrimaryAttack , FIELD_FLOAT , FTYPEDESC_OVERRIDE | FTYPEDESC_NOERRORCHECK ) ,
DEFINE_PRED_FIELD ( m_flNextSecondaryAttack , FIELD_FLOAT , FTYPEDESC_OVERRIDE | FTYPEDESC_NOERRORCHECK ) ,
DEFINE_PRED_FIELD ( m_bDelayFire , FIELD_BOOLEAN , 0 ) ,
DEFINE_PRED_FIELD ( m_flAccuracy , FIELD_FLOAT , 0 ) ,
DEFINE_PRED_FIELD ( m_weaponMode , FIELD_INTEGER , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD_TOL ( m_fAccuracyPenalty , FIELD_FLOAT , FTYPEDESC_INSENDTABLE , 0.00005f ) ,
END_PREDICTION_DATA ( )
# endif
LINK_ENTITY_TO_CLASS ( weapon_cs_base , CWeaponCSBase ) ;
# ifdef GAME_DLL
BEGIN_DATADESC ( CWeaponCSBase )
//DEFINE_FUNCTION( DefaultTouch ),
DEFINE_THINKFUNC ( FallThink )
END_DATADESC ( )
# endif
# if defined( CLIENT_DLL )
ConVar cl_crosshaircolor ( " cl_crosshaircolor " , " 0 " , FCVAR_CLIENTDLL | FCVAR_ARCHIVE , " Set crosshair color: 0=green, 1=red, 2=blue, 3=yellow, 4=cyan, 5=custom " ) ;
ConVar cl_dynamiccrosshair ( " cl_dynamiccrosshair " , " 1 " , FCVAR_CLIENTDLL | FCVAR_ARCHIVE , " Enables dynamic crosshair; 0=off, 1=normal behavior (based on actual weapon accuracy), 2=legacy simulated dynamic behavior, 3=legacy simulated static behavior " ) ;
ConVar cl_crosshairspreadscale ( " cl_crosshairspreadscale " , " 0.3 " , FCVAR_CLIENTDLL | FCVAR_ARCHIVE ) ;
ConVar cl_scalecrosshair ( " cl_scalecrosshair " , " 1 " , FCVAR_CLIENTDLL | FCVAR_ARCHIVE , " Enable crosshair scaling (deprecated) " ) ;
ConVar cl_crosshairscale ( " cl_crosshairscale " , " 0 " , FCVAR_CLIENTDLL | FCVAR_ARCHIVE , " Crosshair scaling factor (deprecated) " ) ;
ConVar cl_crosshairalpha ( " cl_crosshairalpha " , " 200 " , FCVAR_CLIENTDLL | FCVAR_ARCHIVE ) ;
ConVar cl_crosshairusealpha ( " cl_crosshairusealpha " , " 1 " , FCVAR_CLIENTDLL | FCVAR_ARCHIVE ) ;
ConVar cl_crosshairsize ( " cl_crosshairsize " , " 5 " , FCVAR_CLIENTDLL | FCVAR_ARCHIVE ) ;
ConVar cl_crosshairthickness ( " cl_crosshairthickness " , " 0.5 " , FCVAR_CLIENTDLL | FCVAR_ARCHIVE ) ;
ConVar cl_crosshairdot ( " cl_crosshairdot " , " 0 " , FCVAR_CLIENTDLL | FCVAR_ARCHIVE ) ;
ConVar cl_crosshaircolor_r ( " cl_crosshaircolor_r " , " 50 " , FCVAR_CLIENTDLL | FCVAR_ARCHIVE ) ;
ConVar cl_crosshaircolor_g ( " cl_crosshaircolor_g " , " 250 " , FCVAR_CLIENTDLL | FCVAR_ARCHIVE ) ;
ConVar cl_crosshaircolor_b ( " cl_crosshaircolor_b " , " 50 " , FCVAR_CLIENTDLL | FCVAR_ARCHIVE ) ;
# if ALLOW_WEAPON_SPREAD_DISPLAY
ConVar weapon_debug_spread_show ( " weapon_debug_spread_show " , " 0 " , FCVAR_CLIENTDLL | FCVAR_DEVELOPMENTONLY , " Enables display of weapon accuracy; 1: show accuracy box, 2: show box with recoil offset " ) ;
ConVar weapon_debug_spread_gap ( " weapon_debug_spread_gap " , " 0.67 " , FCVAR_CLIENTDLL | FCVAR_DEVELOPMENTONLY ) ;
# endif
// [paquin] make sure crosshair scales independent of frame rate
// unless legacy cvar is set
ConVar cl_legacy_crosshair_recoil ( " cl_legacy_crosshair_recoil " , " 0 " , FCVAR_CLIENTDLL | FCVAR_ARCHIVE , " Enable legacy framerate dependent crosshair recoil " ) ;
// use old scaling behavior
ConVar cl_legacy_crosshair_scale ( " cl_legacy_crosshair_scale " , " 0 " , FCVAR_CLIENTDLL | FCVAR_ARCHIVE , " Enable legacy crosshair scaling " ) ;
void DrawCrosshairRect ( int x0 , int y0 , int x1 , int y1 , bool bAdditive )
{
if ( bAdditive )
{
vgui : : surface ( ) - > DrawTexturedRect ( x0 , y0 , x1 , y1 ) ;
}
else
{
// Alpha-blended crosshair
vgui : : surface ( ) - > DrawFilledRect ( x0 , y0 , x1 , y1 ) ;
}
}
# endif
// must be included after the above macros
# ifndef CLIENT_DLL
# include "cs_bot.h"
# endif
// ----------------------------------------------------------------------------- //
// CWeaponCSBase implementation.
// ----------------------------------------------------------------------------- //
CWeaponCSBase : : CWeaponCSBase ( )
{
SetPredictionEligible ( true ) ;
m_bDelayFire = true ;
m_nextPrevOwnerTouchTime = 0.0 ;
m_prevOwner = NULL ;
AddSolidFlags ( FSOLID_TRIGGER ) ; // Nothing collides with these but it gets touches.
# ifdef CLIENT_DLL
m_iCrosshairTextureID = 0 ;
# else
m_iDefaultExtraAmmo = 0 ;
# endif
m_fAccuracyPenalty = 0.0f ;
m_weaponMode = Primary_Mode ;
}
# ifndef CLIENT_DLL
bool CWeaponCSBase : : KeyValue ( const char * szKeyName , const char * szValue )
{
if ( ! BaseClass : : KeyValue ( szKeyName , szValue ) )
{
if ( FStrEq ( szKeyName , " ammo " ) )
{
int bullets = atoi ( szValue ) ;
if ( bullets < 0 )
return false ;
m_iDefaultExtraAmmo = bullets ;
return true ;
}
}
return false ;
}
# endif
bool CWeaponCSBase : : IsPredicted ( ) const
{
return true ;
}
bool CWeaponCSBase : : IsPistol ( ) const
{
return GetCSWpnData ( ) . m_WeaponType = = WEAPONTYPE_PISTOL ;
}
bool CWeaponCSBase : : IsFullAuto ( ) const
{
return GetCSWpnData ( ) . m_bFullAuto ;
}
bool CWeaponCSBase : : PlayEmptySound ( )
{
//MIKETODO: certain weapons should override this to make it empty:
// C4
// Flashbang
// HE Grenade
// Smoke grenade
CPASAttenuationFilter filter ( this ) ;
filter . UsePredictionRules ( ) ;
if ( IsPistol ( ) )
{
EmitSound ( filter , entindex ( ) , " Default.ClipEmpty_Pistol " ) ;
}
else
{
EmitSound ( filter , entindex ( ) , " Default.ClipEmpty_Rifle " ) ;
}
return 0 ;
}
CCSPlayer * CWeaponCSBase : : GetPlayerOwner ( ) const
{
return dynamic_cast < CCSPlayer * > ( GetOwner ( ) ) ;
}
//=============================================================================
// HPE_BEGIN:
//=============================================================================
//[dwenger] Accessors for the prior owner list
void CWeaponCSBase : : AddToPriorOwnerList ( CCSPlayer * pPlayer )
{
if ( ! IsAPriorOwner ( pPlayer ) )
{
// Add player to prior owner list
m_PriorOwners . AddToTail ( pPlayer ) ;
}
}
bool CWeaponCSBase : : IsAPriorOwner ( CCSPlayer * pPlayer )
{
return ( m_PriorOwners . Find ( pPlayer ) ! = - 1 ) ;
}
//=============================================================================
// HPE_END
//=============================================================================
void CWeaponCSBase : : SecondaryAttack ( void )
{
# ifndef CLIENT_DLL
CCSPlayer * pPlayer = GetPlayerOwner ( ) ;
if ( ! pPlayer )
return ;
if ( pPlayer - > HasShield ( ) = = false )
BaseClass : : SecondaryAttack ( ) ;
else
{
pPlayer - > SetShieldDrawnState ( ! pPlayer - > IsShieldDrawn ( ) ) ;
if ( pPlayer - > IsShieldDrawn ( ) )
SendWeaponAnim ( ACT_SHIELD_UP ) ;
else
SendWeaponAnim ( ACT_SHIELD_DOWN ) ;
m_flNextSecondaryAttack = gpGlobals - > curtime + 0.4 ;
m_flNextPrimaryAttack = gpGlobals - > curtime + 0.4 ;
}
# endif
}
bool CWeaponCSBase : : SendWeaponAnim ( int iActivity )
{
# ifdef CS_SHIELD_ENABLED
CCSPlayer * pPlayer = GetPlayerOwner ( ) ;
if ( pPlayer & & pPlayer - > HasShield ( ) )
{
CBaseViewModel * vm = pPlayer - > GetViewModel ( 1 ) ;
if ( vm = = NULL )
return false ;
vm - > SetWeaponModel ( SHIELD_VIEW_MODEL , this ) ;
int idealSequence = vm - > SelectWeightedSequence ( ( Activity ) iActivity ) ;
if ( idealSequence > = 0 )
{
vm - > SendViewModelMatchingSequence ( idealSequence ) ;
}
}
# endif
return BaseClass : : SendWeaponAnim ( iActivity ) ;
}
void CWeaponCSBase : : ItemPostFrame ( )
{
CCSPlayer * pPlayer = GetPlayerOwner ( ) ;
if ( ! pPlayer )
return ;
UpdateAccuracyPenalty ( ) ;
UpdateShieldState ( ) ;
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 ;
}
if ( ( pPlayer - > m_nButtons & IN_ATTACK2 ) & & ( m_flNextSecondaryAttack < = gpGlobals - > curtime ) )
{
if ( pPlayer - > HasShield ( ) )
CWeaponCSBase : : SecondaryAttack ( ) ;
else
SecondaryAttack ( ) ;
pPlayer - > m_nButtons & = ~ IN_ATTACK2 ;
}
else if ( ( pPlayer - > m_nButtons & IN_ATTACK ) & & ( m_flNextPrimaryAttack < = gpGlobals - > curtime ) )
{
if ( CSGameRules ( ) - > IsFreezePeriod ( ) ) // Can't shoot during the freeze period
return ;
if ( pPlayer - > m_bIsDefusing )
return ;
if ( pPlayer - > State_Get ( ) ! = STATE_ACTIVE )
return ;
if ( pPlayer - > IsShieldDrawn ( ) )
return ;
// we have to reset the FireOnEmpty flag before we can fire on an empty clip
if ( m_iClip1 = = 0 & & ! m_bFireOnEmpty )
return ;
// don't repeat fire if this is not a full auto weapon
if ( pPlayer - > m_iShotsFired > 0 & & ! IsFullAuto ( ) )
return ;
# if !defined(CLIENT_DLL)
// allow the bots to react to the gunfire
if ( GetCSWpnData ( ) . m_WeaponType ! = WEAPONTYPE_GRENADE )
{
IGameEvent * event = gameeventmanager - > CreateEvent ( ( HasAmmo ( ) ) ? " weapon_fire " : " weapon_fire_on_empty " ) ;
if ( event )
{
const char * weaponName = STRING ( m_iClassname ) ;
if ( strncmp ( weaponName , " weapon_ " , 7 ) = = 0 )
{
weaponName + = 7 ;
}
event - > SetInt ( " userid " , pPlayer - > GetUserID ( ) ) ;
event - > SetString ( " weapon " , weaponName ) ;
gameeventmanager - > FireEvent ( event ) ;
}
}
# endif
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.
//MIKETODO: add code for shields...
//if ( !FBitSet( m_iWeaponState, WPNSTATE_SHIELD_DRAWN ) )
if ( ! pPlayer - > IsShieldDrawn ( ) )
{
if ( Reload ( ) )
{
# ifndef CLIENT_DLL
// allow the bots to react to the reload
IGameEvent * event = gameeventmanager - > CreateEvent ( " weapon_reload " ) ;
if ( event )
{
event - > SetInt ( " userid " , pPlayer - > GetUserID ( ) ) ;
gameeventmanager - > FireEvent ( event ) ;
}
# endif
}
}
}
else if ( ! ( pPlayer - > m_nButtons & ( IN_ATTACK | IN_ATTACK2 ) ) )
{
if ( weapon_accuracy_model . GetInt ( ) = = 2 )
{
// Fire button not down -- reset the shots fired count
if ( pPlayer - > m_iShotsFired > 0 & & ( ! IsFullAuto ( ) | | m_iClip1 = = 0 ) )
{
pPlayer - > m_iShotsFired = 0 ;
}
}
// The following code prevents the player from tapping the firebutton repeatedly
// to simulate full auto and retaining the single shot accuracy of single fire
if ( m_bDelayFire )
{
m_bDelayFire = false ;
if ( pPlayer - > m_iShotsFired > 15 )
pPlayer - > m_iShotsFired = 15 ;
m_flDecreaseShotsFired = gpGlobals - > curtime + 0.4 ;
}
m_bFireOnEmpty = true ;
// if it's a pistol then set the shots fired to 0 after the player releases a button
if ( IsPistol ( ) )
{
pPlayer - > m_iShotsFired = 0 ;
}
else
{
if ( ( pPlayer - > m_iShotsFired > 0 ) & & ( m_flDecreaseShotsFired < gpGlobals - > curtime ) )
{
m_flDecreaseShotsFired = gpGlobals - > curtime + 0.0225 ;
pPlayer - > m_iShotsFired - - ;
}
}
if ( ( ! IsUseable ( ) & & m_flNextPrimaryAttack < gpGlobals - > curtime ) )
{
// Intentionally blank -- used to switch weapons here
}
else
{
// 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 CWeaponCSBase : : ItemBusyFrame ( )
{
UpdateAccuracyPenalty ( ) ;
BaseClass : : ItemBusyFrame ( ) ;
}
float CWeaponCSBase : : GetInaccuracy ( ) const
{
CCSPlayer * pPlayer = GetPlayerOwner ( ) ;
if ( ! pPlayer )
return 0.0f ;
const CCSWeaponInfo & weaponInfo = GetCSWpnData ( ) ;
float fMaxSpeed = GetMaxSpeed ( ) ;
if ( fMaxSpeed = = 0.0f )
fMaxSpeed = GetCSWpnData ( ) . m_flMaxSpeed ;
return m_fAccuracyPenalty +
RemapValClamped ( pPlayer - > GetAbsVelocity ( ) . Length2D ( ) ,
fMaxSpeed * CS_PLAYER_SPEED_DUCK_MODIFIER ,
fMaxSpeed * 0.95f , // max out at 95% of run speed to avoid jitter near max speed
0.0f , weaponInfo . m_fInaccuracyMove [ m_weaponMode ] ) ;
}
float CWeaponCSBase : : GetSpread ( ) const
{
if ( weapon_accuracy_model . GetInt ( ) = = 1 )
return 0.0f ;
return GetCSWpnData ( ) . m_fSpread [ m_weaponMode ] ;
}
float CWeaponCSBase : : GetMaxSpeed ( ) const
{
// The weapon should have set this in its constructor.
float flRet = GetCSWpnData ( ) . m_flMaxSpeed ;
Assert ( flRet > 1 ) ;
return flRet ;
}
const CCSWeaponInfo & CWeaponCSBase : : GetCSWpnData ( ) const
{
const FileWeaponInfo_t * pWeaponInfo = & GetWpnData ( ) ;
const CCSWeaponInfo * pCSInfo ;
# ifdef _DEBUG
pCSInfo = dynamic_cast < const CCSWeaponInfo * > ( pWeaponInfo ) ;
Assert ( pCSInfo ) ;
# else
pCSInfo = static_cast < const CCSWeaponInfo * > ( pWeaponInfo ) ;
# endif
return * pCSInfo ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char * CWeaponCSBase : : GetViewModel ( int /*viewmodelindex = 0 -- this is ignored in the base class here*/ ) const
{
CCSPlayer * pOwner = GetPlayerOwner ( ) ;
if ( pOwner = = NULL )
return BaseClass : : GetViewModel ( ) ;
if ( pOwner - > HasShield ( ) & & GetCSWpnData ( ) . m_bCanUseWithShield )
return GetCSWpnData ( ) . m_szShieldViewModel ;
else
return GetWpnData ( ) . szViewModel ;
return BaseClass : : GetViewModel ( ) ;
}
void CWeaponCSBase : : Precache ( void )
{
BaseClass : : Precache ( ) ;
# ifdef CS_SHIELD_ENABLED
if ( GetCSWpnData ( ) . m_bCanUseWithShield )
{
PrecacheModel ( GetCSWpnData ( ) . m_szShieldViewModel ) ;
}
# endif
PrecacheScriptSound ( " Default.ClipEmpty_Pistol " ) ;
PrecacheScriptSound ( " Default.ClipEmpty_Rifle " ) ;
PrecacheScriptSound ( " Default.Zoom " ) ;
}
Activity CWeaponCSBase : : GetDeployActivity ( void )
{
return ACT_VM_DRAW ;
}
bool CWeaponCSBase : : DefaultDeploy ( char * szViewModel , char * szWeaponModel , int iActivity , char * szAnimExt )
{
// Msg( "deploy %s at %f\n", GetClassname(), gpGlobals->curtime );
CCSPlayer * pOwner = GetPlayerOwner ( ) ;
if ( ! pOwner )
{
return false ;
}
pOwner - > SetAnimationExtension ( szAnimExt ) ;
SetViewModel ( ) ;
SendWeaponAnim ( GetDeployActivity ( ) ) ;
pOwner - > SetNextAttack ( gpGlobals - > curtime + SequenceDuration ( ) ) ;
m_flNextPrimaryAttack = gpGlobals - > curtime ;
m_flNextSecondaryAttack = gpGlobals - > curtime ;
SetWeaponVisible ( true ) ;
pOwner - > SetShieldDrawnState ( false ) ;
if ( pOwner - > HasShield ( ) = = true )
SetWeaponModelIndex ( SHIELD_WORLD_MODEL ) ;
else
SetWeaponModelIndex ( szWeaponModel ) ;
return true ;
}
void CWeaponCSBase : : UpdateShieldState ( void )
{
//empty by default.
CCSPlayer * pOwner = GetPlayerOwner ( ) ;
if ( pOwner = = NULL )
return ;
//ADRIANTODO
//Make the hitbox set switches here!!!
if ( pOwner - > HasShield ( ) = = false )
{
pOwner - > SetShieldDrawnState ( false ) ;
//pOwner->SetHitBoxSet( 0 );
return ;
}
else
{
//pOwner->SetHitBoxSet( 1 );
}
}
void CWeaponCSBase : : SetWeaponModelIndex ( const char * pName )
{
m_iWorldModelIndex = modelinfo - > GetModelIndex ( pName ) ;
}
bool CWeaponCSBase : : CanBeSelected ( void )
{
if ( ! VisibleInWeaponSelection ( ) )
return false ;
return true ;
}
bool CWeaponCSBase : : CanDeploy ( void )
{
CCSPlayer * pPlayer = GetPlayerOwner ( ) ;
if ( ! pPlayer )
return false ;
if ( pPlayer - > HasShield ( ) & & GetCSWpnData ( ) . m_bCanUseWithShield = = false )
return false ;
return BaseClass : : CanDeploy ( ) ;
}
float CWeaponCSBase : : CalculateNextAttackTime ( float fCycleTime )
{
float fCurAttack = m_flNextPrimaryAttack ;
float fDeltaAttack = gpGlobals - > curtime - fCurAttack ;
if ( fDeltaAttack < 0 | | fDeltaAttack > gpGlobals - > interval_per_tick )
{
fCurAttack = gpGlobals - > curtime ;
}
m_flNextSecondaryAttack = m_flNextPrimaryAttack = fCurAttack + fCycleTime ;
return fCurAttack ;
}
bool CWeaponCSBase : : Holster ( CBaseCombatWeapon * pSwitchingTo )
{
CCSPlayer * pPlayer = GetPlayerOwner ( ) ;
if ( ! pPlayer )
return false ;
if ( pPlayer )
pPlayer - > SetFOV ( pPlayer , 0 ) ; // reset the default FOV.
if ( pPlayer )
pPlayer - > SetShieldDrawnState ( false ) ;
return BaseClass : : Holster ( pSwitchingTo ) ;
}
bool CWeaponCSBase : : Deploy ( )
{
CCSPlayer * pPlayer = GetPlayerOwner ( ) ;
# ifdef CLIENT_DLL
m_iAlpha = 80 ;
if ( pPlayer )
{
pPlayer - > m_iLastZoom = 0 ;
pPlayer - > SetFOV ( pPlayer , 0 ) ;
}
# else
m_flDecreaseShotsFired = gpGlobals - > curtime ;
if ( pPlayer )
{
pPlayer - > m_iShotsFired = 0 ;
pPlayer - > m_bResumeZoom = false ;
pPlayer - > m_iLastZoom = 0 ;
pPlayer - > SetFOV ( pPlayer , 0 ) ;
}
# endif
m_fAccuracyPenalty = 0.0f ;
return BaseClass : : Deploy ( ) ;
}
# ifndef CLIENT_DLL
bool CWeaponCSBase : : IsRemoveable ( )
{
if ( BaseClass : : IsRemoveable ( ) = = true )
{
if ( m_nextPrevOwnerTouchTime > gpGlobals - > curtime )
{
return false ;
}
}
return BaseClass : : IsRemoveable ( ) ;
}
# endif
void CWeaponCSBase : : Drop ( const Vector & vecVelocity )
{
# ifdef CLIENT_DLL
BaseClass : : Drop ( vecVelocity ) ;
return ;
# else
// 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.
SetRemoveable ( true ) ;
StopAnimation ( ) ;
StopFollowingEntity ( ) ;
SetMoveType ( MOVETYPE_FLYGRAVITY ) ;
// clear follow stuff, setup for collision
SetGravity ( 1.0 ) ;
m_iState = WEAPON_NOT_CARRIED ;
RemoveEffects ( EF_NODRAW ) ;
FallInit ( ) ;
SetGroundEntity ( NULL ) ;
m_bInReload = false ; // stop reloading
SetThink ( NULL ) ;
m_nextPrevOwnerTouchTime = gpGlobals - > curtime + 0.8f ;
m_prevOwner = GetPlayerOwner ( ) ;
SetTouch ( & CWeaponCSBase : : DefaultTouch ) ;
IPhysicsObject * pObj = VPhysicsGetObject ( ) ;
if ( pObj ! = NULL )
{
AngularImpulse angImp ( 200 , 200 , 200 ) ;
pObj - > AddVelocity ( & vecVelocity , & angImp ) ;
}
else
{
SetAbsVelocity ( vecVelocity ) ;
}
SetNextThink ( gpGlobals - > curtime ) ;
SetOwnerEntity ( NULL ) ;
SetOwner ( NULL ) ;
# endif
}
// whats going on here is that if the player drops this weapon, they shouldn't take it back themselves
// for a little while. But if they throw it at someone else, the other player should get it immediately.
void CWeaponCSBase : : DefaultTouch ( CBaseEntity * pOther )
{
if ( ( m_prevOwner ! = NULL ) & & ( pOther = = m_prevOwner ) & & ( gpGlobals - > curtime < m_nextPrevOwnerTouchTime ) )
{
return ;
}
BaseClass : : DefaultTouch ( pOther ) ;
}
# if defined( CLIENT_DLL )
//-----------------------------------------------------------------------------
// Purpose: Draw the weapon's crosshair
//-----------------------------------------------------------------------------
void CWeaponCSBase : : DrawCrosshair ( )
{
if ( ! crosshair . GetInt ( ) )
return ;
CHudCrosshair * pCrosshair = GET_HUDELEMENT ( CHudCrosshair ) ;
if ( ! pCrosshair )
return ;
// clear crosshair
pCrosshair - > SetCrosshair ( 0 , Color ( 255 , 255 , 255 , 255 ) ) ;
CCSPlayer * pPlayer = ( CCSPlayer * ) C_BasePlayer : : GetLocalPlayer ( ) ;
if ( ! pPlayer )
return ;
// localplayer must be owner if not in Spec mode
Assert ( ( pPlayer = = GetPlayerOwner ( ) ) | | ( pPlayer - > GetObserverMode ( ) = = OBS_MODE_IN_EYE ) ) ;
// Draw the targeting zone around the pCrosshair
if ( pPlayer - > IsInVGuiInputMode ( ) )
return ;
int r , g , b ;
switch ( cl_crosshaircolor . GetInt ( ) )
{
case 0 : r = 50 ; g = 250 ; b = 50 ; break ;
case 1 : r = 250 ; g = 50 ; b = 50 ; break ;
case 2 : r = 50 ; g = 50 ; b = 250 ; break ;
case 3 : r = 250 ; g = 250 ; b = 50 ; break ;
case 4 : r = 50 ; g = 250 ; b = 250 ; break ;
case 5 :
r = cl_crosshaircolor_r . GetInt ( ) ;
g = cl_crosshaircolor_g . GetInt ( ) ;
b = cl_crosshaircolor_b . GetInt ( ) ;
break ;
default : r = 50 ; g = 250 ; b = 50 ; break ;
}
// if user is using nightvision, make the crosshair red.
if ( pPlayer - > m_bNightVisionOn )
{
r = 250 ;
g = 50 ;
b = 50 ;
}
int alpha = clamp ( cl_crosshairalpha . GetInt ( ) , 0 , 255 ) ;
vgui : : surface ( ) - > DrawSetColor ( r , g , b , alpha ) ;
if ( ! m_iCrosshairTextureID )
{
CHudTexture * pTexture = gHUD . GetIcon ( " whiteAdditive " ) ;
if ( pTexture )
{
m_iCrosshairTextureID = pTexture - > textureId ;
}
}
bool bAdditive = ! cl_crosshairusealpha . GetBool ( ) & & ! pPlayer - > m_bNightVisionOn ;
if ( bAdditive )
{
vgui : : surface ( ) - > DrawSetColor ( r , g , b , 200 ) ;
vgui : : surface ( ) - > DrawSetTexture ( m_iCrosshairTextureID ) ;
}
if ( pPlayer - > HasShield ( ) & & pPlayer - > IsShieldDrawn ( ) = = true )
return ;
// no crosshair for sniper rifles
bool bCrosshairVisible = crosshair . GetBool ( ) & & GetCSWpnData ( ) . m_WeaponType ! = WEAPONTYPE_SNIPER_RIFLE ;
if ( ! bCrosshairVisible
# if ALLOW_WEAPON_SPREAD_DISPLAY
& & ! weapon_debug_spread_show . GetBool ( )
# endif
)
return ;
float fHalfFov = DEG2RAD ( pPlayer - > GetFOV ( ) ) * 0.5f ;
int iCrosshairDistance ;
int iBarSize = RoundFloatToInt ( YRES ( cl_crosshairsize . GetFloat ( ) ) ) ;
int iBarThickness = MAX ( 1 , RoundFloatToInt ( YRES ( cl_crosshairthickness . GetFloat ( ) ) ) ) ;
switch ( cl_dynamiccrosshair . GetInt ( ) )
{
case 0 :
default :
{
// static crosshair
float fSpread = ( GetCSWpnData ( ) . m_fSpread [ m_weaponMode ] + GetCSWpnData ( ) . m_fInaccuracyStand [ m_weaponMode ] ) * 320.0f / tanf ( fHalfFov ) ;
iCrosshairDistance = MAX ( 0 , RoundFloatToInt ( YRES ( fSpread * cl_crosshairspreadscale . GetFloat ( ) ) ) ) ;
}
break ;
case 1 :
{
float fSpread = ( GetInaccuracy ( ) + GetSpread ( ) ) * 320.0f / tanf ( fHalfFov ) ;
iCrosshairDistance = MAX ( 0 , RoundFloatToInt ( YRES ( fSpread * cl_crosshairspreadscale . GetFloat ( ) ) ) ) ;
}
break ;
case 2 :
case 3 :
{
float fCrosshairDistanceGoal = GetCSWpnData ( ) . m_iCrosshairMinDistance ; // The minimum distance the crosshair can achieve...
// legacy dynamic crosshair
if ( cl_dynamiccrosshair . GetInt ( ) = = 2 )
{
if ( ! ( pPlayer - > GetFlags ( ) & FL_ONGROUND ) )
fCrosshairDistanceGoal * = 2.0f ;
else if ( pPlayer - > GetFlags ( ) & FL_DUCKING )
fCrosshairDistanceGoal * = 0.5f ;
else if ( pPlayer - > GetAbsVelocity ( ) . Length ( ) > 100 )
fCrosshairDistanceGoal * = 1.5f ;
}
// [jpaquin] changed to only bump up the crosshair size if the player is still shooting or is spectating someone else
int iDeltaDistance = GetCSWpnData ( ) . m_iCrosshairDeltaDistance ; // Amount by which the crosshair expands when shooting (per frame)
if ( pPlayer - > m_iShotsFired > m_iAmmoLastCheck & & ( pPlayer - > m_nButtons & ( IN_ATTACK | IN_ATTACK2 ) ) )
fCrosshairDistanceGoal + = iDeltaDistance ;
m_iAmmoLastCheck = pPlayer - > m_iShotsFired ;
if ( m_flCrosshairDistance > fCrosshairDistanceGoal )
{
// [jpaquin] if we're not in legacy crosshair mode, use an exponential decay function so
// that the crosshair shrinks at the same rate regardless of the frame rate
if ( ! cl_legacy_crosshair_recoil . GetBool ( ) )
{
// .44888 on the next line makes the decay very close to what old method produces at 100fps.
m_flCrosshairDistance = Lerp ( expf ( - gpGlobals - > frametime / 0.44888f ) , fCrosshairDistanceGoal , m_flCrosshairDistance ) ;
}
else
{
m_flCrosshairDistance - = 0.1f + m_flCrosshairDistance * 0.013 ;
}
}
// clamp max crosshair expansion
m_flCrosshairDistance = clamp ( m_flCrosshairDistance , fCrosshairDistanceGoal , 25.0f ) ;
if ( cl_legacy_crosshair_scale . GetBool ( ) )
{
//scale bar size to the resolution
int crosshairScale = cl_crosshairscale . GetInt ( ) ;
if ( crosshairScale < 1 )
{
if ( ScreenHeight ( ) < = 600 )
{
crosshairScale = 600 ;
}
else if ( ScreenHeight ( ) < = 768 )
{
crosshairScale = 768 ;
}
else
{
crosshairScale = 1200 ;
}
}
float scale ;
if ( cl_scalecrosshair . GetBool ( ) = = false )
{
scale = 1.0f ;
}
else
{
scale = ( float ) ScreenHeight ( ) / ( float ) crosshairScale ;
}
// calculate the inner distance of the crosshair in current screen units
iCrosshairDistance = ( int ) ceil ( m_flCrosshairDistance * scale ) ;
iBarSize = XRES ( 5 ) ; // + (iCrosshairDistance - fCrosshairDistanceGoal) / 2;
iBarSize = MAX ( 1 , ( int ) ( ( float ) iBarSize * scale ) ) ;
iBarThickness = MAX ( 1 , ( int ) floor ( scale + 0.5f ) ) ;
}
else
{
iCrosshairDistance = RoundFloatToInt ( m_flCrosshairDistance * ScreenHeight ( ) / 1200.0f ) ;
}
}
break ;
}
int iCenterX = ScreenWidth ( ) / 2 ;
int iCenterY = ScreenHeight ( ) / 2 ;
if ( bCrosshairVisible )
{
// draw horizontal crosshair lines
int iInnerLeft = iCenterX - iCrosshairDistance - iBarThickness / 2 ;
int iInnerRight = iInnerLeft + 2 * iCrosshairDistance + iBarThickness ;
int iOuterLeft = iInnerLeft - iBarSize ;
int iOuterRight = iInnerRight + iBarSize ;
int y0 = iCenterY - iBarThickness / 2 ;
int y1 = y0 + iBarThickness ;
DrawCrosshairRect ( iOuterLeft , y0 , iInnerLeft , y1 , bAdditive ) ;
DrawCrosshairRect ( iInnerRight , y0 , iOuterRight , y1 , bAdditive ) ;
// draw vertical crosshair lines
int iInnerTop = iCenterY - iCrosshairDistance - iBarThickness / 2 ;
int iInnerBottom = iInnerTop + 2 * iCrosshairDistance + iBarThickness ;
int iOuterTop = iInnerTop - iBarSize ;
int iOuterBottom = iInnerBottom + iBarSize ;
int x0 = iCenterX - iBarThickness / 2 ;
int x1 = x0 + iBarThickness ;
DrawCrosshairRect ( x0 , iOuterTop , x1 , iInnerTop , bAdditive ) ;
DrawCrosshairRect ( x0 , iInnerBottom , x1 , iOuterBottom , bAdditive ) ;
// draw dot
if ( cl_crosshairdot . GetBool ( ) )
{
int x0 = iCenterX - iBarThickness / 2 ;
int x1 = x0 + iBarThickness ;
int y0 = iCenterY - iBarThickness / 2 ;
int y1 = y0 + iBarThickness ;
DrawCrosshairRect ( x0 , y0 , x1 , y1 , bAdditive ) ;
}
}
# if ALLOW_WEAPON_SPREAD_DISPLAY
// show accuracy brackets
if ( weapon_debug_spread_show . GetInt ( ) = = 1 | | weapon_debug_spread_show . GetInt ( ) = = 2 )
{
if ( weapon_debug_spread_show . GetInt ( ) = = 2 )
{
const QAngle & punchAngles = pPlayer - > GetPunchAngle ( ) ;
Vector vecDirShooting ;
AngleVectors ( punchAngles , & vecDirShooting ) ;
float iOffsetX = RoundFloatToInt ( YRES ( vecDirShooting . y * 320.0f / tanf ( fHalfFov ) ) ) ;
float iOffsetY = RoundFloatToInt ( YRES ( vecDirShooting . z * 320.0f / tanf ( fHalfFov ) ) ) ;
iCenterX - = iOffsetX ;
iCenterY - = iOffsetY ;
}
// colors
r = 250 ;
g = 250 ;
b = 50 ;
vgui : : surface ( ) - > DrawSetColor ( r , g , b , alpha ) ;
int iBarThickness = MAX ( 1 , RoundFloatToInt ( YRES ( cl_crosshairthickness . GetFloat ( ) ) ) ) ;
float fSpreadDistance = ( GetInaccuracy ( ) + GetSpread ( ) ) * 320.0f / tanf ( fHalfFov ) ;
int iSpreadDistance = RoundFloatToInt ( YRES ( fSpreadDistance ) ) ;
// draw vertical spread lines
int iInnerLeft = iCenterX - iSpreadDistance ;
int iInnerRight = iCenterX + iSpreadDistance ;
int iOuterLeft = iInnerLeft - iBarThickness ;
int iOuterRight = iInnerRight + iBarThickness ;
int iInnerTop = iCenterY - iSpreadDistance ;
int iInnerBottom = iCenterY + iSpreadDistance ;
int iOuterTop = iInnerTop - iBarThickness ;
int iOuterBottom = iInnerBottom + iBarThickness ;
int iGap = RoundFloatToInt ( weapon_debug_spread_gap . GetFloat ( ) * iSpreadDistance ) ;
// draw horizontal lines
DrawCrosshairRect ( iOuterLeft , iOuterTop , iCenterX - iGap , iInnerTop , bAdditive ) ;
DrawCrosshairRect ( iCenterX + iGap , iOuterTop , iOuterRight , iInnerTop , bAdditive ) ;
DrawCrosshairRect ( iOuterLeft , iInnerBottom , iCenterX - iGap , iOuterBottom , bAdditive ) ;
DrawCrosshairRect ( iCenterX + iGap , iInnerBottom , iOuterRight , iOuterBottom , bAdditive ) ;
// draw vertical lines
DrawCrosshairRect ( iOuterLeft , iOuterTop , iInnerLeft , iCenterY - iGap , bAdditive ) ;
DrawCrosshairRect ( iOuterLeft , iCenterY + iGap , iInnerLeft , iOuterBottom , bAdditive ) ;
DrawCrosshairRect ( iInnerRight , iOuterTop , iOuterRight , iCenterY - iGap , bAdditive ) ;
DrawCrosshairRect ( iInnerRight , iCenterY + iGap , iOuterRight , iOuterBottom , bAdditive ) ;
}
# endif
}
void CWeaponCSBase : : OnDataChanged ( DataUpdateType_t type )
{
BaseClass : : OnDataChanged ( type ) ;
if ( GetPredictable ( ) & & ! ShouldPredict ( ) )
ShutdownPredictable ( ) ;
}
bool CWeaponCSBase : : ShouldPredict ( )
{
if ( GetOwner ( ) & & GetOwner ( ) = = C_BasePlayer : : GetLocalPlayer ( ) )
return true ;
return BaseClass : : ShouldPredict ( ) ;
}
void CWeaponCSBase : : ProcessMuzzleFlashEvent ( )
{
// This is handled from the player's animstate, so it can match up to the beginning of the fire animation
}
bool CWeaponCSBase : : OnFireEvent ( C_BaseViewModel * pViewModel , const Vector & origin , const QAngle & angles , int event , const char * options )
{
if ( event = = 5001 )
{
C_CSPlayer * pPlayer = ToCSPlayer ( GetOwner ( ) ) ;
if ( pPlayer & & pPlayer - > GetFOV ( ) < pPlayer - > GetDefaultFOV ( ) & & HideViewModelWhenZoomed ( ) )
return true ;
CEffectData data ;
data . m_fFlags = 0 ;
data . m_hEntity = pViewModel - > GetRefEHandle ( ) ;
data . m_nAttachmentIndex = 1 ;
data . m_flScale = GetCSWpnData ( ) . m_flMuzzleScale ;
switch ( GetMuzzleFlashStyle ( ) )
{
case CS_MUZZLEFLASH_NONE :
break ;
case CS_MUZZLEFLASH_X :
{
DispatchEffect ( " CS_MuzzleFlash_X " , data ) ;
}
break ;
case CS_MUZZLEFLASH_NORM :
default :
{
DispatchEffect ( " CS_MuzzleFlash " , data ) ;
}
break ;
}
return true ;
}
return BaseClass : : OnFireEvent ( pViewModel , origin , angles , event , options ) ;
}
int CWeaponCSBase : : GetMuzzleFlashStyle ( void )
{
return GetCSWpnData ( ) . m_iMuzzleFlashStyle ;
}
int CWeaponCSBase : : GetMuzzleAttachment ( void )
{
return LookupAttachment ( " muzzle_flash " ) ;
}
# else
//-----------------------------------------------------------------------------
// Purpose: Get the accuracy derived from weapon and player, and return it
//-----------------------------------------------------------------------------
const Vector & CWeaponCSBase : : GetBulletSpread ( )
{
static Vector cone = VECTOR_CONE_8DEGREES ;
return cone ;
}
//-----------------------------------------------------------------------------
// Purpose: Match the anim speed to the weapon speed while crouching
//-----------------------------------------------------------------------------
float CWeaponCSBase : : GetDefaultAnimSpeed ( )
{
return 1.0 ;
}
//-----------------------------------------------------------------------------
// Purpose: Draw the laser rifle effect
//-----------------------------------------------------------------------------
void CWeaponCSBase : : BulletWasFired ( const Vector & vecStart , const Vector & vecEnd )
{
}
bool CWeaponCSBase : : ShouldRemoveOnRoundRestart ( )
{
if ( GetPlayerOwner ( ) )
return false ;
else
return true ;
}
//=============================================================================
// HPE_BEGIN:
// [dwenger] Handle round restart processing for the weapon.
//=============================================================================
void CWeaponCSBase : : OnRoundRestart ( )
{
// Clear out the list of prior owners
m_PriorOwners . RemoveAll ( ) ;
}
//=============================================================================
// HPE_END
//=============================================================================
//=========================================================
// Materialize - make a CWeaponCSBase visible and tangible
//=========================================================
void CWeaponCSBase : : Materialize ( )
{
if ( IsEffectActive ( EF_NODRAW ) )
{
// changing from invisible state to visible.
RemoveEffects ( EF_NODRAW ) ;
DoMuzzleFlash ( ) ;
}
AddSolidFlags ( FSOLID_TRIGGER ) ;
//SetTouch( &CWeaponCSBase::DefaultTouch );
SetThink ( NULL ) ;
}
//=========================================================
// AttemptToMaterialize - the item is trying to rematerialize,
// should it do so now or wait longer?
//=========================================================
void CWeaponCSBase : : 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 CWeaponCSBase : : 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 * CWeaponCSBase : : 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 ( & CWeaponCSBase : : 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 ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponCSBase : : Use ( CBaseEntity * pActivator , CBaseEntity * pCaller , USE_TYPE useType , float value )
{
CBasePlayer * pPlayer = ToBasePlayer ( pActivator ) ;
if ( pPlayer )
{
m_OnPlayerUse . FireOutput ( pActivator , pCaller ) ;
}
}
bool CWeaponCSBase : : Reload ( )
{
CCSPlayer * pPlayer = GetPlayerOwner ( ) ;
if ( ! pPlayer )
return false ;
pPlayer - > m_iShotsFired = 0 ;
bool retval = BaseClass : : Reload ( ) ;
return retval ;
}
void CWeaponCSBase : : Spawn ( )
{
BaseClass : : Spawn ( ) ;
// Override the bloat that our base class sets as it's a little bit bigger than we want.
// If it's too big, you drop a weapon and its box is so big that you're still touching it
// when it falls and you pick it up again right away.
CollisionProp ( ) - > UseTriggerBounds ( true , 30 ) ;
// Set this here to allow players to shoot dropped weapons
SetCollisionGroup ( COLLISION_GROUP_WEAPON ) ;
SetExtraAmmoCount ( m_iDefaultExtraAmmo ) ; //Start with no additional ammo
m_nextPrevOwnerTouchTime = 0.0 ;
m_prevOwner = NULL ;
//=============================================================================
// HPE_BEGIN:
//=============================================================================
// [tj] initialize donor of this weapon
m_donor = NULL ;
m_donated = false ;
m_weaponMode = Primary_Mode ;
//=============================================================================
// HPE_END
//=============================================================================
}
bool CWeaponCSBase : : DefaultReload ( int iClipSize1 , int iClipSize2 , int iActivity )
{
if ( BaseClass : : DefaultReload ( iClipSize1 , iClipSize2 , iActivity ) )
{
SendReloadEvents ( ) ;
return true ;
}
else
{
return false ;
}
}
void CWeaponCSBase : : SendReloadEvents ( )
{
CCSPlayer * pPlayer = dynamic_cast < CCSPlayer * > ( GetOwner ( ) ) ;
if ( ! pPlayer )
return ;
// Send a message to any clients that have this entity to play the reload.
CPASFilter filter ( pPlayer - > GetAbsOrigin ( ) ) ;
filter . RemoveRecipient ( pPlayer ) ;
UserMessageBegin ( filter , " ReloadEffect " ) ;
WRITE_SHORT ( pPlayer - > entindex ( ) ) ;
MessageEnd ( ) ;
// Make the player play his reload animation.
pPlayer - > DoAnimationEvent ( PLAYERANIMEVENT_RELOAD ) ;
}
# endif
bool CWeaponCSBase : : DefaultPistolReload ( )
{
CCSPlayer * pPlayer = GetPlayerOwner ( ) ;
if ( ! pPlayer )
return false ;
if ( pPlayer - > GetAmmoCount ( GetPrimaryAmmoType ( ) ) < = 0 )
return true ;
if ( ! DefaultReload ( GetCSWpnData ( ) . iDefaultClip1 , 0 , ACT_VM_RELOAD ) )
return false ;
pPlayer - > m_iShotsFired = 0 ;
return true ;
}
bool CWeaponCSBase : : IsUseable ( )
{
CCSPlayer * pPlayer = GetPlayerOwner ( ) ;
if ( ! pPlayer )
return false ;
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 ;
}
# if defined( CLIENT_DLL )
float g_lateralBob = 0 ;
float g_verticalBob = 0 ;
static ConVar cl_bobcycle ( " cl_bobcycle " , " 0.8 " , FCVAR_CHEAT ) ;
static ConVar cl_bob ( " cl_bob " , " 0.002 " , FCVAR_CHEAT ) ;
static ConVar cl_bobup ( " cl_bobup " , " 0.5 " , FCVAR_CHEAT ) ;
//-----------------------------------------------------------------------------
// Purpose:
// Output : float
//-----------------------------------------------------------------------------
float CWeaponCSBase : : 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 ) | |
( cl_bobcycle . GetFloat ( ) < = 0.0f ) | |
( cl_bobup . GetFloat ( ) < = 0.0f ) | |
( cl_bobup . GetFloat ( ) > = 1.0f ) )
{
//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 CWeaponCSBase : : 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 );
}
# else
void CWeaponCSBase : : AddViewmodelBob ( CBaseViewModel * viewmodel , Vector & origin , QAngle & angles )
{
}
float CWeaponCSBase : : CalcViewmodelBob ( void )
{
return 0.0f ;
}
# endif
# ifndef CLIENT_DLL
bool CWeaponCSBase : : PhysicsSplash ( const Vector & centerPoint , const Vector & normal , float rawSpeed , float scaledSpeed )
{
if ( rawSpeed > 20 )
{
float size = 4.0f ;
if ( ! IsPistol ( ) )
size + = 2.0f ;
// adjust splash size based on speed
size + = RemapValClamped ( rawSpeed , 0 , 400 , 0 , 3 ) ;
CEffectData data ;
data . m_vOrigin = centerPoint ;
data . m_vNormal = normal ;
data . m_flScale = random - > RandomFloat ( size , size + 1.0f ) ;
if ( GetWaterType ( ) & CONTENTS_SLIME )
{
data . m_fFlags | = FX_WATER_IN_SLIME ;
}
DispatchEffect ( " gunshotsplash " , data ) ;
return true ;
}
return false ;
}
# endif // !CLIENT_DLL
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pPicker -
//-----------------------------------------------------------------------------
void CWeaponCSBase : : OnPickedUp ( CBaseCombatCharacter * pNewOwner )
{
# if !defined( CLIENT_DLL )
RemoveEffects ( EF_ITEM_BLINK ) ;
if ( pNewOwner - > IsPlayer ( ) & & pNewOwner - > IsAlive ( ) )
{
m_OnPlayerPickup . FireOutput ( pNewOwner , this ) ;
// Play the pickup sound for 1st-person observers
CRecipientFilter filter ;
for ( int i = 0 ; i < gpGlobals - > maxClients ; + + i )
{
CBasePlayer * player = UTIL_PlayerByIndex ( i ) ;
if ( player & & ! player - > IsAlive ( ) & & player - > GetObserverMode ( ) = = OBS_MODE_IN_EYE )
{
filter . AddRecipient ( player ) ;
}
}
if ( filter . GetRecipientCount ( ) )
{
CBaseEntity : : EmitSound ( filter , pNewOwner - > entindex ( ) , " Player.PickupWeapon " ) ;
}
// Robin: We don't want to delete weapons the player has picked up, so
// clear the name of the weapon. This prevents wildcards that are meant
// to find NPCs finding weapons dropped by the NPCs as well.
SetName ( NULL_STRING ) ;
}
// Someone picked me up, so make it so that I can't be removed.
SetRemoveable ( false ) ;
# endif
}
void CWeaponCSBase : : UpdateAccuracyPenalty ( )
{
CCSPlayer * pPlayer = GetPlayerOwner ( ) ;
if ( ! pPlayer )
return ;
const CCSWeaponInfo & weaponInfo = GetCSWpnData ( ) ;
float fNewPenalty = 0.0f ;
// on ladder?
if ( pPlayer - > GetMoveType ( ) = = MOVETYPE_LADDER )
{
fNewPenalty + = weaponInfo . m_fInaccuracyStand [ m_weaponMode ] + weaponInfo . m_fInaccuracyLadder [ m_weaponMode ] ;
}
// in the air?
// else if ( !FBitSet( pPlayer->GetFlags(), FL_ONGROUND ) )
// {
// fNewPenalty += weaponInfo.m_fInaccuracyStand[m_weaponMode] + weaponInfo.m_fInaccuracyJump[m_weaponMode];
// }
else if ( FBitSet ( pPlayer - > GetFlags ( ) , FL_DUCKING ) )
{
fNewPenalty + = weaponInfo . m_fInaccuracyCrouch [ m_weaponMode ] ;
}
else
{
fNewPenalty + = weaponInfo . m_fInaccuracyStand [ m_weaponMode ] ;
}
if ( m_bInReload )
{
fNewPenalty + = weaponInfo . m_fInaccuracyReload ;
}
if ( fNewPenalty > m_fAccuracyPenalty )
{
m_fAccuracyPenalty = fNewPenalty ;
}
else
{
float fDecayFactor ;
if ( pPlayer - > GetMoveType ( ) = = MOVETYPE_LADDER )
{
fDecayFactor = logf ( 10.0f ) / weaponInfo . m_fRecoveryTimeStand ;
}
else if ( ! FBitSet ( pPlayer - > GetFlags ( ) , FL_ONGROUND ) ) // in air
{
// enforce a large recovery speed penalty (300%) for players in the air; this helps to provide
// comparable in-air accuracy to the old weapon model
fDecayFactor = logf ( 10.0f ) / ( weaponInfo . m_fRecoveryTimeCrouch * 3.0f ) ;
}
else if ( FBitSet ( pPlayer - > GetFlags ( ) , FL_DUCKING ) )
{
fDecayFactor = logf ( 10.0f ) / weaponInfo . m_fRecoveryTimeCrouch ;
}
else
{
fDecayFactor = logf ( 10.0f ) / weaponInfo . m_fRecoveryTimeStand ;
}
m_fAccuracyPenalty = Lerp ( expf ( TICK_INTERVAL * - fDecayFactor ) , fNewPenalty , ( float ) m_fAccuracyPenalty ) ;
}
}
const float kJumpVelocity = sqrtf ( 2.0f * 800.0f * 57.0f ) ; // see CCSGameMovement::CheckJumpButton()
void CWeaponCSBase : : OnJump ( float fImpulse )
{
m_fAccuracyPenalty + = GetCSWpnData ( ) . m_fInaccuracyJump [ m_weaponMode ] * fImpulse / kJumpVelocity ;
}
void CWeaponCSBase : : OnLand ( float fVelocity )
{
float fPenalty = GetCSWpnData ( ) . m_fInaccuracyLand [ m_weaponMode ] * fVelocity / kJumpVelocity ;
m_fAccuracyPenalty + = fPenalty ;
/*
// this bit of code is only if we want to punch the player view on all landings
CCSPlayer * pPlayer = GetPlayerOwner ( ) ;
if ( ! pPlayer )
return ;
QAngle angle = pPlayer - > GetPunchAngle ( ) ;
float fVKick = RAD2DEG ( asinf ( fPenalty ) ) * 0.4f ;
float fHKick = SharedRandomFloat ( " LandPunchAngleYaw " , - 1.0f , + 1.0f ) * fVKick * 0.1f ;
angle . x + = fVKick ; // pitch
angle . y + = fHKick ; // yaw
pPlayer - > SetPunchAngle ( angle ) ;
*/
}