source-engine/game/shared/dod/weapon_dodsniper.cpp
2022-04-16 12:05:19 +03:00

415 lines
8.8 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "fx_dod_shared.h"
#include "weapon_dodsniper.h"
#ifdef CLIENT_DLL
#include "prediction.h"
#endif
IMPLEMENT_NETWORKCLASS_ALIASED( DODSniperWeapon, DT_SniperWeapon )
#ifdef CLIENT_DLL
void RecvProxy_AnimStart( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
CDODSniperWeapon *pWpn = (CDODSniperWeapon *) pStruct;
pWpn->m_bDoViewAnim = ( pData->m_Value.m_Int > 0 );
}
#endif
BEGIN_NETWORK_TABLE( CDODSniperWeapon, DT_SniperWeapon )
#ifdef CLIENT_DLL
RecvPropBool( RECVINFO( m_bZoomed ) ),
RecvPropInt( RECVINFO( m_bDoViewAnim ), 0, RecvProxy_AnimStart )
#else
SendPropBool( SENDINFO( m_bZoomed ) ),
SendPropBool( SENDINFO( m_bDoViewAnim ) )
#endif
END_NETWORK_TABLE()
#ifdef CLIENT_DLL
BEGIN_PREDICTION_DATA( CDODSniperWeapon )
DEFINE_PRED_FIELD( m_bZoomed, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE )
END_PREDICTION_DATA()
#else
BEGIN_DATADESC( CDODSniperWeapon )
END_DATADESC()
#endif
CDODSniperWeapon::CDODSniperWeapon()
{
}
void CDODSniperWeapon::Spawn( void )
{
BaseClass::Spawn();
ResetTimers();
#ifdef CLIENT_DLL
m_bDoViewAnimCache = false;
m_flZoomPercent = 0.0f;
#endif
m_bShouldRezoomAfterShot = true;
}
void CDODSniperWeapon::ResetTimers( void )
{
m_flUnzoomTime = -1;
m_flRezoomTime = -1;
m_flZoomOutTime = -1;
m_flZoomInTime = -1;
m_bRezoomAfterShot = false;
m_bRezoomAfterReload = false;
}
bool CDODSniperWeapon::Holster( CBaseCombatWeapon *pSwitchingTo )
{
#ifndef CLIENT_DLL
ZoomOut();
ResetTimers();
#endif
return BaseClass::Holster( pSwitchingTo );
}
void CDODSniperWeapon::PrimaryAttack( void )
{
BaseClass::PrimaryAttack();
CDODPlayer *pPlayer = ToDODPlayer( GetOwner() );
if ( IsZoomed() && ShouldZoomOutBetweenShots() )
{
//If we have more bullets, zoom out, play the bolt animation and zoom back in
if( m_iClip1 > 0 && m_bShouldRezoomAfterShot && ( pPlayer && pPlayer->ShouldAutoRezoom() ) )
{
SetRezoom( true, 0.5f ); // zoom out in 0.5 seconds, then rezoom
}
else //just zoom out
{
SetRezoom( false, 0.5f ); // just zoom out in 0.5 seconds
}
}
// overwrite the next secondary attack, so we can zoom sooned after we've fired
if ( m_bRezoomAfterShot && m_iClip1 > 0 )
m_flNextSecondaryAttack = gpGlobals->curtime + 2.0;
else
m_flNextSecondaryAttack = SequenceDuration();
}
void CDODSniperWeapon::SecondaryAttack( void )
{
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
Assert( pPlayer );
if ( !pPlayer )
return;
ToggleZoom();
}
bool CDODSniperWeapon::Reload( void )
{
bool bSuccess = BaseClass::Reload();
if ( bSuccess && IsZoomed() )
{
//if ( ShouldRezoomAfterReload() )
// m_bRezoomAfterReload = true;
ZoomOut();
}
if ( !bSuccess )
m_bRezoomAfterReload = false;
return bSuccess;
}
void CDODSniperWeapon::FinishReload( void )
{
BaseClass::FinishReload();
if ( m_bRezoomAfterReload )
{
ZoomIn();
m_bRezoomAfterReload = false;
}
}
float CDODSniperWeapon::GetWeaponAccuracy( float flPlayerSpeed )
{
//snipers and deployable weapons inherit this and override when we need a different accuracy
float flSpread = m_pWeaponInfo->m_flAccuracy;
if ( IsZoomed() && ( gpGlobals->curtime - m_flZoomChangeTime ) > DOD_SNIPER_ZOOM_CHANGE_TIME )
{
flSpread = m_pWeaponInfo->m_flSecondaryAccuracy;
}
if( flPlayerSpeed > 45 )
flSpread += m_pWeaponInfo->m_flAccuracyMovePenalty;
return flSpread;
}
bool CDODSniperWeapon::IsZoomed( void )
{
// check the player?
return IsSniperZoomed();
}
bool CDODSniperWeapon::ShouldDrawCrosshair( void )
{
//if ( IsFullyZoomed() )
// return false;
// don't draw if we are zoomed at all
if ( m_bZoomed )
return false;
return BaseClass::ShouldDrawCrosshair();
}
#include "in_buttons.h"
void CDODSniperWeapon::ItemPostFrame( void )
{
if ( m_flUnzoomTime > 0 && gpGlobals->curtime > m_flUnzoomTime )
{
if ( m_bRezoomAfterShot )
{
ZoomOutIn();
m_bRezoomAfterShot = false;
}
else
{
ZoomOut();
}
m_flUnzoomTime = -1;
}
CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );
Assert( pPlayer );
if ( m_flRezoomTime > 0 )
{
// if the player is sprinting and moving at all, cancel the rezoom
if ( ( pPlayer->m_nButtons & IN_SPEED ) > 0 &&
pPlayer->GetAbsVelocity().Length2D() > 20 )
{
m_flRezoomTime = -1;
}
else if ( gpGlobals->curtime > m_flRezoomTime )
{
ZoomIn();
m_flRezoomTime = -1;
}
}
if ( m_flZoomInTime > 0 && gpGlobals->curtime > m_flZoomInTime )
{
#ifndef CLIENT_DLL
CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );
Assert( pPlayer );
pPlayer->SetFOV( pPlayer, GetZoomedFOV(), 0.1f );
#endif
m_flZoomInTime = -1;
m_flZoomOutTime = -1;
}
if ( m_flZoomInTime > 0 && (pPlayer->m_nButtons & IN_ATTACK) )
{
m_bInAttack = true;
}
BaseClass::ItemPostFrame();
}
void CDODSniperWeapon::Drop( const Vector &vecVelocity )
{
// If a player is killed while deployed, this resets the weapon state
if ( IsZoomed() )
ZoomOut();
ResetTimers();
BaseClass::Drop( vecVelocity );
}
void CDODSniperWeapon::ToggleZoom( void )
{
CDODPlayer *pPlayer = GetDODPlayerOwner();
if ( !pPlayer->m_Shared.IsJumping() )
{
if( !IsZoomed() )
{
if ( CanAttack() )
{
#ifndef CLIENT_DLL
pPlayer->RemoveHintTimer( m_iAltFireHint );
#endif
ZoomIn();
}
}
else
{
ZoomOut();
}
}
}
void CDODSniperWeapon::ZoomIn( void )
{
m_flZoomInTime = gpGlobals->curtime + DOD_SNIPER_ZOOM_CHANGE_TIME;
#ifndef CLIENT_DLL
SetZoomed( true );
m_bDoViewAnim = !m_bDoViewAnim;
#endif
m_flNextPrimaryAttack = MAX( gpGlobals->curtime + 0.5, m_flNextPrimaryAttack );
m_flNextSecondaryAttack = MAX( gpGlobals->curtime + 0.5, m_flNextSecondaryAttack );
m_flTimeWeaponIdle = gpGlobals->curtime + m_pWeaponInfo->m_flTimeToIdleAfterFire;
m_flZoomChangeTime = gpGlobals->curtime;
}
void CDODSniperWeapon::ZoomOut( void )
{
bool bWasZoomed = IsZoomed();
#ifndef CLIENT_DLL
CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );
Assert( pPlayer );
pPlayer->SetFOV( pPlayer, 90, 0.1f );
SetZoomed( false );
m_bDoViewAnim = !m_bDoViewAnim;
#endif
if ( bWasZoomed )
{
m_flNextPrimaryAttack = MAX( gpGlobals->curtime + 0.5, m_flNextPrimaryAttack );
m_flNextSecondaryAttack = MAX( gpGlobals->curtime + 0.5, m_flNextSecondaryAttack );
m_flTimeWeaponIdle = gpGlobals->curtime + m_pWeaponInfo->m_flTimeToIdleAfterFire;
}
m_flZoomChangeTime = gpGlobals->curtime;
// if we are thinking about zooming, cancel it
m_flZoomInTime = -1;
m_flUnzoomTime = -1;
m_flRezoomTime = -1;
}
// reduce rezoome time, to account for fade in we're replacing with anim
#define REZOOM_TIME 1.2f
void CDODSniperWeapon::ZoomOutIn( void )
{
ZoomOut();
m_flRezoomTime = gpGlobals->curtime + 1.0;
}
void CDODSniperWeapon::SetRezoom( bool bRezoom, float flDelay )
{
m_flUnzoomTime = gpGlobals->curtime + flDelay;
m_bRezoomAfterShot = bRezoom;
}
bool CDODSniperWeapon::IsFullyZoomed( void )
{
return ( IsZoomed() == true &&
(( gpGlobals->curtime - m_flZoomChangeTime ) > DOD_SNIPER_ZOOM_CHANGE_TIME) );
}
bool CDODSniperWeapon::IsZoomingIn( void )
{
return ( m_flZoomInTime > gpGlobals->curtime );
}
#ifdef CLIENT_DLL
float CDODSniperWeapon::GetZoomedPercentage( void )
{
return m_flZoomPercent;
}
Vector CDODSniperWeapon::GetDesiredViewModelOffset( C_DODPlayer *pOwner )
{
static Vector vecLastResult = vec3_origin;
if ( prediction->InPrediction() && !prediction->IsFirstTimePredicted() )
{
return vecLastResult;
}
if ( m_bDoViewAnim != m_bDoViewAnimCache )
{
// start the anim timer
m_flViewAnimTimer = gpGlobals->curtime + DOD_SNIPER_ZOOM_CHANGE_TIME;
m_bDoViewAnimCache = m_bDoViewAnim.m_Value;
}
Vector viewOffset = pOwner->GetViewOffset();
float flPercent = clamp( ( viewOffset.z - VEC_PRONE_VIEW_SCALED( pOwner ).z ) / ( VEC_VIEW_SCALED( pOwner ).z - VEC_PRONE_VIEW_SCALED( pOwner ).z ), 0.0, 1.0 );
Vector offset = ( flPercent * GetDODWpnData().m_vecViewNormalOffset +
( 1.0 - flPercent ) * GetDODWpnData().m_vecViewProneOffset );
// how long since we changed iron sight mode
float flZoomAnimPercent = clamp( ( (m_flViewAnimTimer - gpGlobals->curtime) / ( DOD_SNIPER_ZOOM_CHANGE_TIME ) ), 0.0, 1.0 );
m_flZoomPercent = ( IsZoomed() ? ( 1.0 - flZoomAnimPercent ) : flZoomAnimPercent );
//Msg( "(%.1f) zoom %.2f %.2f\n", gpGlobals->curtime, m_flViewAnimTimer - gpGlobals->curtime, m_flZoomPercent );
// use that percent to interp to iron sight position
Vector vecResult = ( m_flZoomPercent * GetDODWpnData().m_vecIronSightOffset +
( 1.0 - m_flZoomPercent ) * offset );
// store this value to use when called in prediction
vecLastResult = vecResult;
return vecResult;
}
float CDODSniperWeapon::GetViewModelSwayScale( void )
{
if ( IsFullyZoomed() )
return 0;
return BaseClass::GetViewModelSwayScale();
}
#endif //CLIENT_DLL