Files
HL2Overcharged/game/server/overcharged/weapon_binoculars.cpp
2025-05-21 21:20:08 +03:00

585 lines
15 KiB
C++

//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============
//
// Purpose: Implements binoculars.
//
// Primary attack button: zoom in.
// Secondary attack button: zoom out.
//
// $NoKeywords: $
//=============================================================================
#include "cbase.h"
#include "NPCEvent.h"
#include "basehlcombatweapon.h"
#include "basecombatcharacter.h"
#include "AI_BaseNPC.h"
#include "player.h"
#include "gamerules.h" // For g_pGameRules
#include "entitylist.h"
#include "soundenvelope.h"
#include "in_buttons.h"
#include "engine/IEngineSound.h"
#include "materialsystem/IMaterialSystem.h"
#include "materialsystem/IMaterialVar.h"
#include "materialsystem/imaterialsystemhardwareconfig.h"
//#ifdef CLIENT_DLL
//#include "viewrender.h"
//#endif
#define BINOCULARS_MAXSOURCES 50
#define BINOCULARS_CACHEFREQ 1.0
#define BINOCULARS_FAKEDIST 99999
#define BINOCULARS_VIEWCONE 0.6
#define BINOCULARS_ZOOM_RATE 0.15 // Interval between zoom levels in seconds.
#define WB_STATIC_CHANNEL CHAN_VOICE
#define WB_SIGNAL_CHANNEL CHAN_BODY
ConVar oc_weapon_binoculars_overlay( "oc_weapon_binoculars_overlay", "HUD/Binocular", FCVAR_REPLICATED|FCVAR_ARCHIVE, "Binoculars overlay." );
ConVar oc_weapon_binoculars_overlay_draw( "oc_weapon_binoculars_overlay_draw", "0", FCVAR_HIDDEN | FCVAR_REPLICATED, "Draw overlay?" );
enum ZoomMode_t
{
Zoom_Exit = 0,
Zoom_In,
Zoom_Out
};
//-----------------------------------------------------------------------------
// Discrete zoom levels for the scope.
//-----------------------------------------------------------------------------
static int g_nZoomFOV[] =
{
0,
40,
30,
20,
10,
5
};
class CWeaponBinoculars : public CBaseHLCombatWeapon
{
public:
DECLARE_CLASS( CWeaponBinoculars, CBaseHLCombatWeapon );
DECLARE_SERVERCLASS();
DECLARE_ACTTABLE();
void Spawn( void );
CWeaponBinoculars( void );
~CWeaponBinoculars( void );
void Precache( void );
int CapabilitiesGet( void );
bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL );
void ItemPostFrame( void );
void Zoom( ZoomMode_t eMode );
bool Deploy( void );
//void CacheSoundSources( void );
void Drop( const Vector &vecVelocity );
CBaseEntity *LocateBestSound( void );
float GetSoundDist( CBaseEntity *pSound, const Vector &vecLOS );
protected:
//CSoundPatch *m_pSoundStatic;
CSoundPatch *m_pSoundSignal;
float m_fNextZoom;
int m_nZoomLevel;
//static const char *pStaticSounds[]; // L1ght 15 : No more needed
static const char *pSignalSounds[];
float m_NextCacheTime;
EHANDLE m_hSources[ BINOCULARS_MAXSOURCES ];
DECLARE_DATADESC();
};
IMPLEMENT_SERVERCLASS_ST(CWeaponBinoculars, DT_WeaponBinoculars)
END_SEND_TABLE()
LINK_ENTITY_TO_CLASS( weapon_binoculars, CWeaponBinoculars );
PRECACHE_WEAPON_REGISTER(weapon_binoculars);
//---------------------------------------------------------
//---------------------------------------------------------
BEGIN_DATADESC( CWeaponBinoculars )
DEFINE_FIELD( m_NextCacheTime, FIELD_TIME ),
DEFINE_SOUNDPATCH( m_pSoundSignal ),
//DEFINE_SOUNDPATCH( m_pSoundStatic ),
DEFINE_FIELD( m_fNextZoom, FIELD_FLOAT ),
DEFINE_FIELD( m_nZoomLevel, FIELD_INTEGER ),
DEFINE_ARRAY( m_hSources, FIELD_EHANDLE, BINOCULARS_MAXSOURCES ),
END_DATADESC()
acttable_t CWeaponBinoculars::m_acttable[] =
{
{ ACT_HL2MP_IDLE, ACT_IDLE_PACKAGE, false },
{ ACT_HL2MP_RUN, ACT_RUN, false },
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_PHYSGUN, false },
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_PHYSGUN, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_PHYSGUN, false },
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_PHYSGUN, false },
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_PHYSGUN, false },
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SLAM, false },
{ ACT_IDLE_RELAXED, ACT_IDLE_PACKAGE, false }, // L1ght 15 : Anims update
{ ACT_RUN_RELAXED, ACT_RUN, false },
};
IMPLEMENT_ACTTABLE( CWeaponBinoculars );
//---------------------------------------------------------
//---------------------------------------------------------
void CWeaponBinoculars::Spawn( void )
{
BaseClass::Spawn();
int i;
for( i = 0 ; i < BINOCULARS_MAXSOURCES ; i++ )
{
m_hSources[ i ] = NULL;
}
}
//----------------------------------------------------------------------------- // L1ght 15 : No more needed
// Binocular radio sounds
//-----------------------------------------------------------------------------
/*const char *CWeaponBinoculars::pStaticSounds[] =
{
// These sounds are played constantly whilst the binoculars are
// in use.
"weapons/binoculars/buzz.wav",
};*/
//---------------------------------------------------------
//---------------------------------------------------------
const char *CWeaponBinoculars::pSignalSounds[] =
{
// These sounds play when the binoculars are nearly locked onto a signal
//"weapons/binoculars/signal.wav",
"weapons/airboat/airboat_gun_lastshot1.wav",
};
//-----------------------------------------------------------------------------
// Only need to call this every second or so WHEN the binoculars are zoomed in.
//-----------------------------------------------------------------------------
/*void CWeaponBinoculars::CacheSoundSources( void ) // BriJee - NOT work on sdk 2013, will be rewritten if needs
{
EHANDLE *pSources = m_hSources;
CBaseEntity *pEnt;
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
Assert( pPlayer != NULL );
if (pPlayer == NULL)
{
return;
}
pEnt = UTIL_EntitiesInPVS( pPlayer, NULL );
int count = 0;
while( pEnt )
{
if( pEnt->IsSoundSource() )
{
*pSources = pEnt;
pSources++;
count++;
}
if( count == ( BINOCULARS_MAXSOURCES - 1 ) )
{
//Msg( "*** BINOCULARS: TOO MANY SOUND SOURCES!\n" );
break;
}
pEnt = UTIL_EntitiesInPVS( pPlayer, pEnt );
}
pSources = NULL;
m_NextCacheTime = gpGlobals->curtime + BINOCULARS_CACHEFREQ;
}*/
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
bool CWeaponBinoculars::Deploy()
{
// Ensure that we cache sounds as soon as the binoculars zoom in.
m_NextCacheTime = gpGlobals->curtime;
CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
// Create our sounds the first time we're used
if ( /*!m_pSoundStatic ||*/ !m_pSoundSignal )
{
CPASAttenuationFilter filter( this, ATTN_NONE );
//m_pSoundStatic = controller.SoundCreate( filter, entindex(), WB_STATIC_CHANNEL, pStaticSounds[ 0 ], ATTN_NONE );
m_pSoundSignal = controller.SoundCreate( filter, entindex(), WB_SIGNAL_CHANNEL, pSignalSounds[ 0 ], ATTN_NONE );
}
//controller.CommandClear( m_pSoundStatic );
controller.CommandClear( m_pSoundSignal );
//controller.Play( m_pSoundStatic, 0.0, 100 );
controller.Play( m_pSoundSignal, 0.0, 100 );
return BaseClass::Deploy();
}
//-----------------------------------------------------------------------------
// Purpose: Constructor.
//-----------------------------------------------------------------------------
CWeaponBinoculars::CWeaponBinoculars( void )
{
m_fNextZoom = gpGlobals->curtime;
m_nZoomLevel = 0;
//m_pSoundStatic = NULL;
m_pSoundSignal = NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor - Free the sound resources we allocate in Spawn()
//-----------------------------------------------------------------------------
CWeaponBinoculars::~CWeaponBinoculars( void )
{
CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
//controller.SoundDestroy( m_pSoundStatic );
controller.SoundDestroy( m_pSoundSignal );
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : int
//-----------------------------------------------------------------------------
int CWeaponBinoculars::CapabilitiesGet( void )
{
return 0;
}
//-----------------------------------------------------------------------------
// Purpose: Turns off the zoom when the binoculars are holstered.
//-----------------------------------------------------------------------------
bool CWeaponBinoculars::Holster( CBaseCombatWeapon *pSwitchingTo )
{
Zoom( Zoom_Exit );
CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
//controller.SoundDestroy( m_pSoundStatic );
controller.SoundDestroy( m_pSoundSignal );
//m_pSoundStatic = NULL;
m_pSoundSignal = NULL;
return true;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
float CWeaponBinoculars::GetSoundDist( CBaseEntity *pSound, const Vector &vecLOS )
{
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if ( !pPlayer )
return 0.0f;
Vector vecDirToSound;
float flDot;
float flDist;
vecDirToSound = pSound->GetAbsOrigin() - pPlayer->GetAbsOrigin();
VectorNormalize(vecDirToSound);
flDot = DotProduct( vecDirToSound, vecLOS );
if( flDot < BINOCULARS_VIEWCONE )
{
// Don't bother with sounds outside of a reasonable viewcone
return BINOCULARS_FAKEDIST;
}
flDist = ( pSound->GetAbsOrigin() - pPlayer->GetAbsOrigin() ).Length();
return flDist * (1.0 - flDot);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
CBaseEntity *CWeaponBinoculars::LocateBestSound( void )
{
// go through the sound list and find the sound the player is probably trying to listen to.
EHANDLE *pIterate;
CBaseEntity *pBestSound = NULL;
float flBestSoundDist;
float flTestDist;
Vector vecLOS;
flBestSoundDist = BINOCULARS_FAKEDIST;
pIterate = m_hSources;
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if ( !pPlayer )
return NULL;
pPlayer->EyeVectors( &vecLOS );
while( *pIterate )
{
flTestDist = GetSoundDist( *pIterate, vecLOS );
if( flTestDist < flBestSoundDist )
{
flBestSoundDist = flTestDist;
pBestSound = *pIterate;
}
pIterate++;
}
return pBestSound;
}
//-----------------------------------------------------------------------------
// Purpose: Overloaded to handle the zoom functionality.
//-----------------------------------------------------------------------------
void CWeaponBinoculars::ItemPostFrame( void )
{
if (cvar->FindVar("aa_cammode")->GetInt() == 1) //&& (m_bTpszoomRes))
{
if ( m_nZoomLevel != 0 )
{
Zoom( Zoom_Exit );
}
return;
}
/*if( gpGlobals->curtime >= m_NextCacheTime && m_nZoomLevel != 0 )
{
CacheSoundSources();
}*/
CBaseEntity *pSound;
pSound = LocateBestSound();
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if (pPlayer == NULL)
{
return;
}
float flStaticVolume;
float flSignalVolume;
float flDot;
if( m_nZoomLevel != 0 )
{
Vector vecToSound;
Vector vecFacing;
pPlayer->EyeVectors( &vecFacing );
if( pSound )
{
// Trying to tune a sound in.
vecToSound = pSound->GetLocalOrigin() - pPlayer->GetLocalOrigin();
VectorNormalize( vecToSound );
flDot = DotProduct( vecToSound, vecFacing );
/*
// FIXME: Disabled this, the code for doing this must exist on the client
if( flDot > 0.95 )
{
engine->EnableHOrigin( true );
engine->SetHOrigin( pSound->GetLocalOrigin() );
}
else
{
engine->EnableHOrigin( false );
}
*/
// static volume gets louder the farther you are from sound
// signal volume gets louder as you near sound.
flStaticVolume = ( 1.0 - flDot ) * 2.0;
// signal volume gets louder as you near, quieter as you get VERY near.
if( flDot < 0.90 || flDot > 0.9995 )
{
flSignalVolume = 0.1;
}
else
{
//flSignalVolume = (flDot - 0.6) * 2;
flSignalVolume = flDot;
}
}
else
{
// No sound. Static.
flSignalVolume = 0.0;
flStaticVolume = 1.0;
//engine->EnableHOrigin( false );
}
}
else
{
flStaticVolume = flSignalVolume = 0.0;
cvar->FindVar("crosshair")->SetValue("1");
cvar->FindVar("oc_weapon_binoculars_overlay_draw")->SetValue("0");
//engine->EnableHOrigin( false );
}
CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
//controller.SoundChangeVolume( m_pSoundStatic, flStaticVolume, 0.1 );
controller.SoundChangeVolume( m_pSoundSignal, flSignalVolume, 0.1 );
if ( pPlayer->m_nButtons & IN_ATTACK )
{
if ( m_fNextZoom <= gpGlobals->curtime )
{
Zoom( Zoom_In );
pPlayer->m_nButtons &= ~IN_ATTACK;
}
}
else if ( pPlayer->m_nButtons & IN_ATTACK2 )
{
if ( m_fNextZoom <= gpGlobals->curtime )
{
Zoom( Zoom_Out );
pPlayer->m_nButtons &= ~IN_ATTACK2;
}
}
//
// No buttons down.
//
if (!(( pPlayer->m_nButtons & IN_ATTACK ) || ( pPlayer->m_nButtons & IN_ATTACK2 )))
{
WeaponIdle();
return;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponBinoculars::Precache( void )
{
//PrecacheSound( "weapons/binoculars/buzz.wav" );
//PrecacheSound( "weapons/binoculars/signal.wav" );
PrecacheSound( "weapons/airboat/airboat_gun_lastshot1.wav" );
//PrecacheModel ("HUD/Binocular");//(cvar->FindVar("oc_weapon_binoculars_overlay")->GetString());
BaseClass::Precache();
}
//-----------------------------------------------------------------------------
// Purpose: Zooms in using the sniper rifle scope.
//-----------------------------------------------------------------------------
void CWeaponBinoculars::Zoom( ZoomMode_t eMode )
{
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if ( !pPlayer )
return;
//IMaterial *pMaterialZoom = materials->FindMaterial( ZOOM_Material, TEXTURE_GROUP_OTHER, true);
//const Vector *vOrigin = &pPlayer->GetAbsOrigin();
switch ( eMode )
{
//
// Stop zooming with the binoculars.
//
case Zoom_Exit:
{
if ( m_nZoomLevel != 0 )
{
pPlayer->ShowViewModel(true);
WeaponSound( SPECIAL2 );
pPlayer->SetFOV( this, 0 );
m_nZoomLevel = 0;
cvar->FindVar("crosshair")->SetValue("1");
cvar->FindVar("oc_weapon_binoculars_overlay_draw")->SetValue("0");
}
break;
}
//
// Zoom in.
//
case Zoom_In:
{
if (( m_nZoomLevel + 1 ) < ( sizeof( g_nZoomFOV ) / sizeof( g_nZoomFOV[0] )))
{
m_nZoomLevel++;
WeaponSound( SPECIAL1 );
pPlayer->SetFOV( this, g_nZoomFOV[m_nZoomLevel] );
if (g_nZoomFOV[m_nZoomLevel] != 0)
{
pPlayer->ShowViewModel(false);
}
cvar->FindVar("crosshair")->SetValue("0");
cvar->FindVar("oc_weapon_binoculars_overlay_draw")->SetValue("1");
}
else
{
// Can't zoom in any further; play a special sound.
WeaponSound( RELOAD );
}
m_fNextZoom = gpGlobals->curtime + BINOCULARS_ZOOM_RATE;
break;
}
//
// Zoom out.
//
case Zoom_Out:
{
if ( m_nZoomLevel > 0 )
{
m_nZoomLevel--;
WeaponSound( SPECIAL2 );
pPlayer->SetFOV( this, g_nZoomFOV[m_nZoomLevel] );
if ( g_nZoomFOV[m_nZoomLevel] == 0 )
{
pPlayer->ShowViewModel(true);
}
}
m_fNextZoom = gpGlobals->curtime + BINOCULARS_ZOOM_RATE;
break;
}
default:
{
break;
}
}
}
void CWeaponBinoculars::Drop( const Vector &vecVelocity )
{
Zoom( Zoom_Exit );
BaseClass::Drop( vecVelocity );
}