2008-09-15 01:07:45 -05:00
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =====//
//
// Purpose: Client-side CBasePlayer.
//
// - Manages the player's flashlight effect.
//
//===========================================================================//
# include "cbase.h"
# include "c_baseplayer.h"
# include "flashlighteffect.h"
# include "weapon_selection.h"
# include "history_resource.h"
# include "iinput.h"
# include "input.h"
# include "view.h"
# include "iviewrender.h"
# include "iclientmode.h"
# include "in_buttons.h"
# include "engine/IEngineSound.h"
# include "c_soundscape.h"
# include "usercmd.h"
# include "c_playerresource.h"
# include "iclientvehicle.h"
# include "view_shared.h"
# include "movevars_shared.h"
# include "prediction.h"
# include "tier0/vprof.h"
# include "filesystem.h"
# include "bitbuf.h"
# include "KeyValues.h"
# include "particles_simple.h"
# include "fx_water.h"
# include "hltvcamera.h"
# include "toolframework/itoolframework.h"
# include "toolframework_client.h"
# include "view_scene.h"
# include "c_vguiscreen.h"
# include "datacache/imdlcache.h"
# include "vgui/isurface.h"
# include "voice_status.h"
# include "fx.h"
// memdbgon must be the last include file in a .cpp file!!!
# include "tier0/memdbgon.h"
// Don't alias here
# if defined( CBasePlayer )
# undef CBasePlayer
# endif
int g_nKillCamMode = OBS_MODE_NONE ;
int g_nKillCamTarget1 = 0 ;
int g_nKillCamTarget2 = 0 ;
extern ConVar mp_forcecamera ; // in gamevars_shared.h
# define FLASHLIGHT_DISTANCE 1000
# define MAX_VGUI_INPUT_MODE_SPEED 30
# define MAX_VGUI_INPUT_MODE_SPEED_SQ (MAX_VGUI_INPUT_MODE_SPEED*MAX_VGUI_INPUT_MODE_SPEED)
static Vector WALL_MIN ( - WALL_OFFSET , - WALL_OFFSET , - WALL_OFFSET ) ;
static Vector WALL_MAX ( WALL_OFFSET , WALL_OFFSET , WALL_OFFSET ) ;
bool CommentaryModeShouldSwallowInput ( C_BasePlayer * pPlayer ) ;
extern ConVar default_fov ;
# ifndef _XBOX
extern ConVar sensitivity ;
# endif
static C_BasePlayer * s_pLocalPlayer = NULL ;
static ConVar cl_customsounds ( " cl_customsounds " , " 0 " , 0 , " Enable customized player sound playback " ) ;
static ConVar spec_track ( " spec_track " , " 0 " , 0 , " Tracks an entity in spec mode " ) ;
static ConVar cl_smooth ( " cl_smooth " , " 1 " , 0 , " Smooth view/eye origin after prediction errors " ) ;
static ConVar cl_smoothtime (
" cl_smoothtime " ,
" 0.1 " ,
0 ,
" Smooth client's view after prediction error over this many seconds " ,
true , 0.01 , // min/max is 0.01/2.0
true , 2.0
) ;
ConVar spec_freeze_time ( " spec_freeze_time " , " 4.0 " , FCVAR_CHEAT | FCVAR_REPLICATED , " Time spend frozen in observer freeze cam. " ) ;
ConVar spec_freeze_traveltime ( " spec_freeze_traveltime " , " 0.4 " , FCVAR_CHEAT | FCVAR_REPLICATED , " Time taken to zoom in to frame a target in observer freeze cam. " , true , 0.01 , false , 0 ) ;
ConVar spec_freeze_distance_min ( " spec_freeze_distance_min " , " 96 " , FCVAR_CHEAT , " Minimum random distance from the target to stop when framing them in observer freeze cam. " ) ;
ConVar spec_freeze_distance_max ( " spec_freeze_distance_max " , " 200 " , FCVAR_CHEAT , " Maximum random distance from the target to stop when framing them in observer freeze cam. " ) ;
void RecvProxy_LocalVelocityX ( const CRecvProxyData * pData , void * pStruct , void * pOut ) ;
void RecvProxy_LocalVelocityY ( const CRecvProxyData * pData , void * pStruct , void * pOut ) ;
void RecvProxy_LocalVelocityZ ( const CRecvProxyData * pData , void * pStruct , void * pOut ) ;
void RecvProxy_ObserverTarget ( const CRecvProxyData * pData , void * pStruct , void * pOut ) ;
// -------------------------------------------------------------------------------- //
// RecvTable for CPlayerState.
// -------------------------------------------------------------------------------- //
BEGIN_RECV_TABLE_NOBASE ( CPlayerState , DT_PlayerState )
RecvPropInt ( RECVINFO ( deadflag ) ) ,
END_RECV_TABLE ( )
BEGIN_RECV_TABLE_NOBASE ( CPlayerLocalData , DT_Local )
RecvPropArray3 ( RECVINFO_ARRAY ( m_chAreaBits ) , RecvPropInt ( RECVINFO ( m_chAreaBits [ 0 ] ) ) ) ,
RecvPropArray3 ( RECVINFO_ARRAY ( m_chAreaPortalBits ) , RecvPropInt ( RECVINFO ( m_chAreaPortalBits [ 0 ] ) ) ) ,
RecvPropInt ( RECVINFO ( m_iHideHUD ) ) ,
// View
RecvPropFloat ( RECVINFO ( m_flFOVRate ) ) ,
RecvPropInt ( RECVINFO ( m_bDucked ) ) ,
RecvPropInt ( RECVINFO ( m_bDucking ) ) ,
RecvPropInt ( RECVINFO ( m_bInDuckJump ) ) ,
RecvPropFloat ( RECVINFO ( m_flDucktime ) ) ,
RecvPropFloat ( RECVINFO ( m_flDuckJumpTime ) ) ,
RecvPropFloat ( RECVINFO ( m_flJumpTime ) ) ,
RecvPropFloat ( RECVINFO ( m_flFallVelocity ) ) ,
# if PREDICTION_ERROR_CHECK_LEVEL > 1
RecvPropFloat ( RECVINFO_NAME ( m_vecPunchAngle . m_Value [ 0 ] , m_vecPunchAngle [ 0 ] ) ) ,
RecvPropFloat ( RECVINFO_NAME ( m_vecPunchAngle . m_Value [ 1 ] , m_vecPunchAngle [ 1 ] ) ) ,
RecvPropFloat ( RECVINFO_NAME ( m_vecPunchAngle . m_Value [ 2 ] , m_vecPunchAngle [ 2 ] ) ) ,
RecvPropFloat ( RECVINFO_NAME ( m_vecPunchAngleVel . m_Value [ 0 ] , m_vecPunchAngleVel [ 0 ] ) ) ,
RecvPropFloat ( RECVINFO_NAME ( m_vecPunchAngleVel . m_Value [ 1 ] , m_vecPunchAngleVel [ 1 ] ) ) ,
RecvPropFloat ( RECVINFO_NAME ( m_vecPunchAngleVel . m_Value [ 2 ] , m_vecPunchAngleVel [ 2 ] ) ) ,
# else
RecvPropVector ( RECVINFO ( m_vecPunchAngle ) ) ,
RecvPropVector ( RECVINFO ( m_vecPunchAngleVel ) ) ,
# endif
RecvPropInt ( RECVINFO ( m_bDrawViewmodel ) ) ,
RecvPropInt ( RECVINFO ( m_bWearingSuit ) ) ,
RecvPropBool ( RECVINFO ( m_bPoisoned ) ) ,
RecvPropFloat ( RECVINFO ( m_flStepSize ) ) ,
RecvPropInt ( RECVINFO ( m_bAllowAutoMovement ) ) ,
// 3d skybox data
RecvPropInt ( RECVINFO ( m_skybox3d . scale ) ) ,
RecvPropVector ( RECVINFO ( m_skybox3d . origin ) ) ,
RecvPropInt ( RECVINFO ( m_skybox3d . area ) ) ,
// 3d skybox fog data
RecvPropInt ( RECVINFO ( m_skybox3d . fog . enable ) ) ,
RecvPropInt ( RECVINFO ( m_skybox3d . fog . blend ) ) ,
RecvPropVector ( RECVINFO ( m_skybox3d . fog . dirPrimary ) ) ,
RecvPropInt ( RECVINFO ( m_skybox3d . fog . colorPrimary ) ) ,
RecvPropInt ( RECVINFO ( m_skybox3d . fog . colorSecondary ) ) ,
RecvPropFloat ( RECVINFO ( m_skybox3d . fog . start ) ) ,
RecvPropFloat ( RECVINFO ( m_skybox3d . fog . end ) ) ,
RecvPropFloat ( RECVINFO ( m_skybox3d . fog . maxdensity ) ) ,
// fog data
RecvPropEHandle ( RECVINFO ( m_PlayerFog . m_hCtrl ) ) ,
// audio data
RecvPropVector ( RECVINFO ( m_audio . localSound [ 0 ] ) ) ,
RecvPropVector ( RECVINFO ( m_audio . localSound [ 1 ] ) ) ,
RecvPropVector ( RECVINFO ( m_audio . localSound [ 2 ] ) ) ,
RecvPropVector ( RECVINFO ( m_audio . localSound [ 3 ] ) ) ,
RecvPropVector ( RECVINFO ( m_audio . localSound [ 4 ] ) ) ,
RecvPropVector ( RECVINFO ( m_audio . localSound [ 5 ] ) ) ,
RecvPropVector ( RECVINFO ( m_audio . localSound [ 6 ] ) ) ,
RecvPropVector ( RECVINFO ( m_audio . localSound [ 7 ] ) ) ,
RecvPropInt ( RECVINFO ( m_audio . soundscapeIndex ) ) ,
RecvPropInt ( RECVINFO ( m_audio . localBits ) ) ,
RecvPropEHandle ( RECVINFO ( m_audio . ent ) ) ,
END_RECV_TABLE ( )
// -------------------------------------------------------------------------------- //
// This data only gets sent to clients that ARE this player entity.
// -------------------------------------------------------------------------------- //
BEGIN_RECV_TABLE_NOBASE ( C_BasePlayer , DT_LocalPlayerExclusive )
RecvPropDataTable ( RECVINFO_DT ( m_Local ) , 0 , & REFERENCE_RECV_TABLE ( DT_Local ) ) ,
RecvPropFloat ( RECVINFO ( m_vecViewOffset [ 0 ] ) ) ,
RecvPropFloat ( RECVINFO ( m_vecViewOffset [ 1 ] ) ) ,
RecvPropFloat ( RECVINFO ( m_vecViewOffset [ 2 ] ) ) ,
RecvPropFloat ( RECVINFO ( m_flFriction ) ) ,
RecvPropArray3 ( RECVINFO_ARRAY ( m_iAmmo ) , RecvPropInt ( RECVINFO ( m_iAmmo [ 0 ] ) ) ) ,
RecvPropInt ( RECVINFO ( m_fOnTarget ) ) ,
RecvPropInt ( RECVINFO ( m_nTickBase ) ) ,
RecvPropInt ( RECVINFO ( m_nNextThinkTick ) ) ,
RecvPropEHandle ( RECVINFO ( m_hLastWeapon ) ) ,
RecvPropEHandle ( RECVINFO ( m_hGroundEntity ) ) ,
RecvPropFloat ( RECVINFO ( m_vecVelocity [ 0 ] ) , 0 , RecvProxy_LocalVelocityX ) ,
RecvPropFloat ( RECVINFO ( m_vecVelocity [ 1 ] ) , 0 , RecvProxy_LocalVelocityY ) ,
RecvPropFloat ( RECVINFO ( m_vecVelocity [ 2 ] ) , 0 , RecvProxy_LocalVelocityZ ) ,
RecvPropVector ( RECVINFO ( m_vecBaseVelocity ) ) ,
RecvPropEHandle ( RECVINFO ( m_hConstraintEntity ) ) ,
RecvPropVector ( RECVINFO ( m_vecConstraintCenter ) ) ,
RecvPropFloat ( RECVINFO ( m_flConstraintRadius ) ) ,
RecvPropFloat ( RECVINFO ( m_flConstraintWidth ) ) ,
RecvPropFloat ( RECVINFO ( m_flConstraintSpeedFactor ) ) ,
RecvPropFloat ( RECVINFO ( m_flDeathTime ) ) ,
RecvPropInt ( RECVINFO ( m_nWaterLevel ) ) ,
RecvPropFloat ( RECVINFO ( m_flLaggedMovementValue ) ) ,
END_RECV_TABLE ( )
// -------------------------------------------------------------------------------- //
// DT_BasePlayer datatable.
// -------------------------------------------------------------------------------- //
IMPLEMENT_CLIENTCLASS_DT ( C_BasePlayer , DT_BasePlayer , CBasePlayer )
// We have both the local and nonlocal data in here, but the server proxies
// only send one.
RecvPropDataTable ( " localdata " , 0 , 0 , & REFERENCE_RECV_TABLE ( DT_LocalPlayerExclusive ) ) ,
RecvPropDataTable ( RECVINFO_DT ( pl ) , 0 , & REFERENCE_RECV_TABLE ( DT_PlayerState ) , DataTableRecvProxy_StaticDataTable ) ,
RecvPropInt ( RECVINFO ( m_iFOV ) ) ,
RecvPropInt ( RECVINFO ( m_iFOVStart ) ) ,
RecvPropFloat ( RECVINFO ( m_flFOVTime ) ) ,
RecvPropInt ( RECVINFO ( m_iDefaultFOV ) ) ,
RecvPropEHandle ( RECVINFO ( m_hZoomOwner ) ) ,
RecvPropEHandle ( RECVINFO ( m_hVehicle ) ) ,
RecvPropEHandle ( RECVINFO ( m_hUseEntity ) ) ,
RecvPropInt ( RECVINFO ( m_iHealth ) ) ,
RecvPropInt ( RECVINFO ( m_lifeState ) ) ,
RecvPropInt ( RECVINFO ( m_iBonusProgress ) ) ,
RecvPropInt ( RECVINFO ( m_iBonusChallenge ) ) ,
RecvPropFloat ( RECVINFO ( m_flMaxspeed ) ) ,
RecvPropInt ( RECVINFO ( m_fFlags ) ) ,
RecvPropInt ( RECVINFO ( m_iObserverMode ) ) ,
RecvPropEHandle ( RECVINFO ( m_hObserverTarget ) , RecvProxy_ObserverTarget ) ,
RecvPropArray ( RecvPropEHandle ( RECVINFO ( m_hViewModel [ 0 ] ) ) , m_hViewModel ) ,
RecvPropString ( RECVINFO ( m_szLastPlaceName ) ) ,
RecvPropInt ( RECVINFO ( m_ubEFNoInterpParity ) ) ,
END_RECV_TABLE ( )
BEGIN_PREDICTION_DATA_NO_BASE ( CPlayerState )
DEFINE_PRED_FIELD ( deadflag , FIELD_BOOLEAN , FTYPEDESC_INSENDTABLE ) ,
// DEFINE_FIELD( netname, string_t ),
// DEFINE_FIELD( fixangle, FIELD_INTEGER ),
// DEFINE_FIELD( anglechange, FIELD_FLOAT ),
// DEFINE_FIELD( v_angle, FIELD_VECTOR ),
END_PREDICTION_DATA ( )
BEGIN_PREDICTION_DATA_NO_BASE ( CPlayerLocalData )
// DEFINE_PRED_TYPEDESCRIPTION( m_skybox3d, sky3dparams_t ),
// DEFINE_PRED_TYPEDESCRIPTION( m_fog, fogparams_t ),
// DEFINE_PRED_TYPEDESCRIPTION( m_audio, audioparams_t ),
DEFINE_FIELD ( m_nStepside , FIELD_INTEGER ) ,
DEFINE_PRED_FIELD ( m_iHideHUD , FIELD_INTEGER , FTYPEDESC_INSENDTABLE ) ,
# if PREDICTION_ERROR_CHECK_LEVEL > 1
DEFINE_PRED_FIELD ( m_vecPunchAngle , FIELD_VECTOR , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD ( m_vecPunchAngleVel , FIELD_VECTOR , FTYPEDESC_INSENDTABLE ) ,
# else
DEFINE_PRED_FIELD_TOL ( m_vecPunchAngle , FIELD_VECTOR , FTYPEDESC_INSENDTABLE , 0.125f ) ,
DEFINE_PRED_FIELD_TOL ( m_vecPunchAngleVel , FIELD_VECTOR , FTYPEDESC_INSENDTABLE , 0.125f ) ,
# endif
DEFINE_PRED_FIELD ( m_bDrawViewmodel , FIELD_BOOLEAN , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD ( m_bWearingSuit , FIELD_BOOLEAN , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD ( m_bPoisoned , FIELD_BOOLEAN , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD ( m_bAllowAutoMovement , FIELD_BOOLEAN , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD ( m_bDucked , FIELD_BOOLEAN , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD ( m_bDucking , FIELD_BOOLEAN , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD ( m_bInDuckJump , FIELD_BOOLEAN , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD ( m_flDucktime , FIELD_FLOAT , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD ( m_flDuckJumpTime , FIELD_FLOAT , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD ( m_flJumpTime , FIELD_FLOAT , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD_TOL ( m_flFallVelocity , FIELD_FLOAT , FTYPEDESC_INSENDTABLE , 0.5f ) ,
// DEFINE_PRED_FIELD( m_nOldButtons, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
DEFINE_FIELD ( m_nOldButtons , FIELD_INTEGER ) ,
DEFINE_PRED_FIELD ( m_flStepSize , FIELD_FLOAT , FTYPEDESC_INSENDTABLE ) ,
DEFINE_FIELD ( m_flFOVRate , FIELD_FLOAT ) ,
END_PREDICTION_DATA ( )
BEGIN_PREDICTION_DATA ( C_BasePlayer )
DEFINE_PRED_TYPEDESCRIPTION ( m_Local , CPlayerLocalData ) ,
DEFINE_PRED_TYPEDESCRIPTION ( pl , CPlayerState ) ,
DEFINE_PRED_FIELD ( m_iFOV , FIELD_INTEGER , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD ( m_hZoomOwner , FIELD_EHANDLE , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD ( m_flFOVTime , FIELD_FLOAT , 0 ) ,
DEFINE_PRED_FIELD ( m_iFOVStart , FIELD_INTEGER , 0 ) ,
DEFINE_PRED_FIELD ( m_hVehicle , FIELD_EHANDLE , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD_TOL ( m_flMaxspeed , FIELD_FLOAT , FTYPEDESC_INSENDTABLE , 0.5f ) ,
DEFINE_PRED_FIELD ( m_iHealth , FIELD_INTEGER , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD ( m_iBonusProgress , FIELD_INTEGER , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD ( m_iBonusChallenge , FIELD_INTEGER , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD ( m_fOnTarget , FIELD_BOOLEAN , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD ( m_nNextThinkTick , FIELD_INTEGER , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD ( m_lifeState , FIELD_CHARACTER , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD ( m_nWaterLevel , FIELD_CHARACTER , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD_TOL ( m_vecBaseVelocity , FIELD_VECTOR , FTYPEDESC_INSENDTABLE , 0.05 ) ,
DEFINE_FIELD ( m_nButtons , FIELD_INTEGER ) ,
DEFINE_FIELD ( m_flWaterJumpTime , FIELD_FLOAT ) ,
DEFINE_FIELD ( m_nImpulse , FIELD_INTEGER ) ,
DEFINE_FIELD ( m_flStepSoundTime , FIELD_FLOAT ) ,
DEFINE_FIELD ( m_flSwimSoundTime , FIELD_FLOAT ) ,
DEFINE_FIELD ( m_vecLadderNormal , FIELD_VECTOR ) ,
DEFINE_FIELD ( m_flPhysics , FIELD_INTEGER ) ,
DEFINE_AUTO_ARRAY ( m_szAnimExtension , FIELD_CHARACTER ) ,
DEFINE_FIELD ( m_afButtonLast , FIELD_INTEGER ) ,
DEFINE_FIELD ( m_afButtonPressed , FIELD_INTEGER ) ,
DEFINE_FIELD ( m_afButtonReleased , FIELD_INTEGER ) ,
// DEFINE_FIELD( m_vecOldViewAngles, FIELD_VECTOR ),
// DEFINE_ARRAY( m_iOldAmmo, FIELD_INTEGER, MAX_AMMO_TYPES ),
//DEFINE_FIELD( m_hOldVehicle, FIELD_EHANDLE ),
// DEFINE_FIELD( m_pModelLight, dlight_t* ),
// DEFINE_FIELD( m_pEnvironmentLight, dlight_t* ),
// DEFINE_FIELD( m_pBrightLight, dlight_t* ),
DEFINE_PRED_FIELD ( m_hLastWeapon , FIELD_EHANDLE , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD ( m_nTickBase , FIELD_INTEGER , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_FIELD ( m_hGroundEntity , FIELD_EHANDLE , FTYPEDESC_INSENDTABLE ) ,
DEFINE_PRED_ARRAY ( m_hViewModel , FIELD_EHANDLE , MAX_VIEWMODELS , FTYPEDESC_INSENDTABLE ) ,
DEFINE_FIELD ( m_surfaceFriction , FIELD_FLOAT ) ,
END_PREDICTION_DATA ( )
LINK_ENTITY_TO_CLASS ( player , C_BasePlayer ) ;
// -------------------------------------------------------------------------------- //
// Functions.
// -------------------------------------------------------------------------------- //
C_BasePlayer : : C_BasePlayer ( ) : m_iv_vecViewOffset ( " C_BasePlayer::m_iv_vecViewOffset " )
{
AddVar ( & m_vecViewOffset , & m_iv_vecViewOffset , LATCH_SIMULATION_VAR ) ;
# ifdef _DEBUG
m_vecLadderNormal . Init ( ) ;
m_vecOldViewAngles . Init ( ) ;
# endif
m_pFlashlight = NULL ;
m_pCurrentVguiScreen = NULL ;
m_pCurrentCommand = NULL ;
m_flPredictionErrorTime = - 100 ;
m_StuckLast = 0 ;
m_bWasFrozen = false ;
m_bResampleWaterSurface = true ;
ResetObserverMode ( ) ;
m_vecPredictionError . Init ( ) ;
m_flPredictionErrorTime = 0 ;
m_surfaceProps = 0 ;
m_pSurfaceData = NULL ;
m_surfaceFriction = 1.0f ;
m_chTextureType = 0 ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_BasePlayer : : ~ C_BasePlayer ( )
{
DeactivateVguiScreen ( m_pCurrentVguiScreen . Get ( ) ) ;
if ( this = = s_pLocalPlayer )
{
s_pLocalPlayer = NULL ;
}
if ( m_pFlashlight )
{
delete m_pFlashlight ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BasePlayer : : Spawn ( void )
{
// Clear all flags except for FL_FULLEDICT
ClearFlags ( ) ;
AddFlag ( FL_CLIENT ) ;
int effects = GetEffects ( ) & EF_NOSHADOW ;
SetEffects ( effects ) ;
m_iFOV = 0 ; // init field of view.
SetModel ( " models/player.mdl " ) ;
Precache ( ) ;
SetThink ( NULL ) ;
SharedSpawn ( ) ;
m_bWasFreezeFraming = false ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool C_BasePlayer : : AudioStateIsUnderwater ( Vector vecMainViewOrigin )
{
if ( IsObserver ( ) )
{
// Just check the view position
int cont = enginetrace - > GetPointContents ( vecMainViewOrigin ) ;
return ( cont & MASK_WATER ) ;
}
return ( GetWaterLevel ( ) > = WL_Eyes ) ;
}
bool C_BasePlayer : : IsHLTV ( ) const
{
return ( IsLocalPlayer ( ) & & engine - > IsHLTV ( ) ) ;
}
CBaseEntity * C_BasePlayer : : GetObserverTarget ( ) const // returns players targer or NULL
{
# ifndef _XBOX
if ( IsHLTV ( ) )
{
return HLTVCamera ( ) - > GetPrimaryTarget ( ) ;
}
# endif
if ( GetObserverMode ( ) = = OBS_MODE_ROAMING )
{
return NULL ; // no target in roaming mode
}
else
{
return m_hObserverTarget ;
}
}
// Called from Recv Proxy, mainly to reset tone map scale
void C_BasePlayer : : SetObserverTarget ( EHANDLE hObserverTarget )
{
// If the observer target is changing to an entity that the client doesn't know about yet,
// it can resolve to NULL. If the client didn't have an observer target before, then
// comparing EHANDLEs directly will see them as equal, since it uses Get(), and compares
// NULL to NULL. To combat this, we need to check against GetEntryIndex() and
// GetSerialNumber().
if ( hObserverTarget . GetEntryIndex ( ) ! = m_hObserverTarget . GetEntryIndex ( ) | |
hObserverTarget . GetSerialNumber ( ) ! = m_hObserverTarget . GetSerialNumber ( ) )
{
// Init based on the new handle's entry index and serial number, so that it's Get()
// has a chance to become non-NULL even if it currently resolves to NULL.
m_hObserverTarget . Init ( hObserverTarget . GetEntryIndex ( ) , hObserverTarget . GetSerialNumber ( ) ) ;
IGameEvent * event = gameeventmanager - > CreateEvent ( " spec_target_updated " ) ;
if ( event )
{
gameeventmanager - > FireEventClientSide ( event ) ;
}
if ( IsLocalPlayer ( ) )
{
ResetToneMapping ( 1.0 ) ;
}
}
}
int C_BasePlayer : : GetObserverMode ( ) const
{
# ifndef _XBOX
if ( IsHLTV ( ) )
{
return HLTVCamera ( ) - > GetMode ( ) ;
}
# endif
return m_iObserverMode ;
}
bool C_BasePlayer : : ViewModel_IsTransparent ( void )
{
return IsTransparent ( ) ;
}
//-----------------------------------------------------------------------------
// Used by prediction, sets the view angles for the player
//-----------------------------------------------------------------------------
void C_BasePlayer : : SetLocalViewAngles ( const QAngle & viewAngles )
{
pl . v_angle = viewAngles ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : ang -
//-----------------------------------------------------------------------------
void C_BasePlayer : : SetViewAngles ( const QAngle & ang )
{
SetLocalAngles ( ang ) ;
SetNetworkAngles ( ang ) ;
}
surfacedata_t * C_BasePlayer : : GetGroundSurface ( )
{
//
// Find the name of the material that lies beneath the player.
//
Vector start , end ;
VectorCopy ( GetAbsOrigin ( ) , start ) ;
VectorCopy ( start , end ) ;
// Straight down
end . z - = 64 ;
// Fill in default values, just in case.
Ray_t ray ;
ray . Init ( start , end , GetPlayerMins ( ) , GetPlayerMaxs ( ) ) ;
trace_t trace ;
UTIL_TraceRay ( ray , MASK_PLAYERSOLID_BRUSHONLY , this , COLLISION_GROUP_PLAYER_MOVEMENT , & trace ) ;
if ( trace . fraction = = 1.0f )
return NULL ; // no ground
return physprops - > GetSurfaceData ( trace . surface . surfaceProps ) ;
}
//-----------------------------------------------------------------------------
// returns the player name
//-----------------------------------------------------------------------------
const char * C_BasePlayer : : GetPlayerName ( )
{
return g_PR ? g_PR - > GetPlayerName ( entindex ( ) ) : " " ;
}
//-----------------------------------------------------------------------------
// Is the player dead?
//-----------------------------------------------------------------------------
bool C_BasePlayer : : IsPlayerDead ( )
{
return pl . deadflag = = true ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BasePlayer : : SetVehicleRole ( int nRole )
{
if ( ! IsInAVehicle ( ) )
return ;
// HL2 has only a player in a vehicle.
if ( nRole > VEHICLE_ROLE_DRIVER )
return ;
char szCmd [ 64 ] ;
Q_snprintf ( szCmd , sizeof ( szCmd ) , " vehicleRole %i \n " , nRole ) ;
engine - > ServerCmd ( szCmd ) ;
}
//-----------------------------------------------------------------------------
// Purpose: Store original ammo data to see what has changed
// Input : bnewentity -
//-----------------------------------------------------------------------------
void C_BasePlayer : : OnPreDataChanged ( DataUpdateType_t updateType )
{
for ( int i = 0 ; i < MAX_AMMO_TYPES ; + + i )
{
m_iOldAmmo [ i ] = GetAmmoCount ( i ) ;
}
m_bWasFreezeFraming = ( GetObserverMode ( ) = = OBS_MODE_FREEZECAM ) ;
m_hOldFogController = m_Local . m_PlayerFog . m_hCtrl ;
BaseClass : : OnPreDataChanged ( updateType ) ;
}
void C_BasePlayer : : PreDataUpdate ( DataUpdateType_t updateType )
{
BaseClass : : PreDataUpdate ( updateType ) ;
m_ubOldEFNoInterpParity = m_ubEFNoInterpParity ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : updateType -
//-----------------------------------------------------------------------------
void C_BasePlayer : : PostDataUpdate ( DataUpdateType_t updateType )
{
// This has to occur here as opposed to OnDataChanged so that EHandles to the player created
// on this same frame are not stomped because prediction thinks there
// isn't a local player yet!!!
if ( updateType = = DATA_UPDATE_CREATED )
{
// Make sure s_pLocalPlayer is correct
int iLocalPlayerIndex = engine - > GetLocalPlayer ( ) ;
if ( g_nKillCamMode )
iLocalPlayerIndex = g_nKillCamTarget1 ;
if ( iLocalPlayerIndex = = index )
{
Assert ( s_pLocalPlayer = = NULL ) ;
s_pLocalPlayer = this ;
// Reset our sound mixed in case we were in a freeze cam when we
// changed level, which would cause the snd_soundmixer to be left modified.
ConVar * pVar = ( ConVar * ) cvar - > FindVar ( " snd_soundmixer " ) ;
pVar - > Revert ( ) ;
}
}
bool bForceEFNoInterp = ( m_ubOldEFNoInterpParity ! = m_ubEFNoInterpParity ) ;
if ( IsLocalPlayer ( ) )
{
SetSimulatedEveryTick ( true ) ;
}
else
{
SetSimulatedEveryTick ( false ) ;
// estimate velocity for non local players
float flTimeDelta = m_flSimulationTime - m_flOldSimulationTime ;
if ( flTimeDelta > 0 & & ! ( IsEffectActive ( EF_NOINTERP ) | | bForceEFNoInterp ) )
{
Vector newVelo = ( GetNetworkOrigin ( ) - GetOldOrigin ( ) ) / flTimeDelta ;
SetAbsVelocity ( newVelo ) ;
}
}
BaseClass : : PostDataUpdate ( updateType ) ;
// Only care about this for local player
if ( IsLocalPlayer ( ) )
{
QAngle angles ;
engine - > GetViewAngles ( angles ) ;
if ( updateType = = DATA_UPDATE_CREATED )
{
SetLocalViewAngles ( angles ) ;
m_flOldPlayerZ = GetLocalOrigin ( ) . z ;
}
SetLocalAngles ( angles ) ;
if ( ! m_bWasFreezeFraming & & GetObserverMode ( ) = = OBS_MODE_FREEZECAM )
{
m_vecFreezeFrameStart = MainViewOrigin ( ) ;
m_flFreezeFrameStartTime = gpGlobals - > curtime ;
m_flFreezeFrameDistance = RandomFloat ( spec_freeze_distance_min . GetFloat ( ) , spec_freeze_distance_max . GetFloat ( ) ) ;
m_flFreezeZOffset = RandomFloat ( - 30 , 20 ) ;
m_bSentFreezeFrame = false ;
IGameEvent * pEvent = gameeventmanager - > CreateEvent ( " show_freezepanel " ) ;
if ( pEvent )
{
pEvent - > SetInt ( " killer " , GetObserverTarget ( ) ? GetObserverTarget ( ) - > entindex ( ) : 0 ) ;
gameeventmanager - > FireEventClientSide ( pEvent ) ;
}
// Force the sound mixer to the freezecam mixer
ConVar * pVar = ( ConVar * ) cvar - > FindVar ( " snd_soundmixer " ) ;
pVar - > SetValue ( " FreezeCam_Only " ) ;
}
else if ( m_bWasFreezeFraming & & GetObserverMode ( ) ! = OBS_MODE_FREEZECAM )
{
IGameEvent * pEvent = gameeventmanager - > CreateEvent ( " hide_freezepanel " ) ;
if ( pEvent )
{
gameeventmanager - > FireEventClientSide ( pEvent ) ;
}
view - > FreezeFrame ( 0 ) ;
ConVar * pVar = ( ConVar * ) cvar - > FindVar ( " snd_soundmixer " ) ;
pVar - > Revert ( ) ;
}
}
// If we are updated while paused, allow the player origin to be snapped by the
// server if we receive a packet from the server
if ( engine - > IsPaused ( ) | | bForceEFNoInterp )
{
ResetLatched ( ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool C_BasePlayer : : CanSetSoundMixer ( void )
{
// Can't set sound mixers when we're in freezecam mode, since it has a code-enforced mixer
return ( GetObserverMode ( ) ! = OBS_MODE_FREEZECAM ) ;
}
void C_BasePlayer : : ReceiveMessage ( int classID , bf_read & msg )
{
if ( classID ! = GetClientClass ( ) - > m_ClassID )
{
// message is for subclass
BaseClass : : ReceiveMessage ( classID , msg ) ;
return ;
}
int messageType = msg . ReadByte ( ) ;
switch ( messageType )
{
case PLAY_PLAYER_JINGLE :
PlayPlayerJingle ( ) ;
break ;
}
}
void C_BasePlayer : : OnRestore ( )
{
BaseClass : : OnRestore ( ) ;
if ( IsLocalPlayer ( ) )
{
// debounce the attack key, for if it was used for restore
input - > ClearInputButton ( IN_ATTACK | IN_ATTACK2 ) ;
// GetButtonBits() has to be called for the above to take effect
input - > GetButtonBits ( 0 ) ;
}
// For ammo history icons to current value so they don't flash on level transtions
for ( int i = 0 ; i < MAX_AMMO_TYPES ; i + + )
{
m_iOldAmmo [ i ] = GetAmmoCount ( i ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Process incoming data
//-----------------------------------------------------------------------------
void C_BasePlayer : : OnDataChanged ( DataUpdateType_t updateType )
{
# if !defined( NO_ENTITY_PREDICTION )
if ( IsLocalPlayer ( ) )
{
SetPredictionEligible ( true ) ;
}
# endif
BaseClass : : OnDataChanged ( updateType ) ;
// Only care about this for local player
if ( IsLocalPlayer ( ) )
{
// Reset engine areabits pointer
render - > SetAreaState ( m_Local . m_chAreaBits , m_Local . m_chAreaPortalBits ) ;
// Check for Ammo pickups.
for ( int i = 0 ; i < MAX_AMMO_TYPES ; i + + )
{
if ( GetAmmoCount ( i ) > m_iOldAmmo [ i ] )
{
// Don't add to ammo pickup if the ammo doesn't do it
const FileWeaponInfo_t * pWeaponData = gWR . GetWeaponFromAmmo ( i ) ;
if ( ! pWeaponData | | ! ( pWeaponData - > iFlags & ITEM_FLAG_NOAMMOPICKUPS ) )
{
// We got more ammo for this ammo index. Add it to the ammo history
CHudHistoryResource * pHudHR = GET_HUDELEMENT ( CHudHistoryResource ) ;
if ( pHudHR )
{
pHudHR - > AddToHistory ( HISTSLOT_AMMO , i , abs ( GetAmmoCount ( i ) - m_iOldAmmo [ i ] ) ) ;
}
}
}
}
Soundscape_Update ( m_Local . m_audio ) ;
if ( m_hOldFogController ! = m_Local . m_PlayerFog . m_hCtrl )
{
FogControllerChanged ( updateType = = DATA_UPDATE_CREATED ) ;
}
}
}
//-----------------------------------------------------------------------------
// Did we just enter a vehicle this frame?
//-----------------------------------------------------------------------------
bool C_BasePlayer : : JustEnteredVehicle ( )
{
if ( ! IsInAVehicle ( ) )
return false ;
return ( m_hOldVehicle = = m_hVehicle ) ;
}
//-----------------------------------------------------------------------------
// Are we in VGUI input mode?.
//-----------------------------------------------------------------------------
bool C_BasePlayer : : IsInVGuiInputMode ( ) const
{
return ( m_pCurrentVguiScreen . Get ( ) ! = NULL ) ;
}
//-----------------------------------------------------------------------------
// Are we inputing to a view model vgui screen
//-----------------------------------------------------------------------------
bool C_BasePlayer : : IsInViewModelVGuiInputMode ( ) const
{
C_BaseEntity * pScreenEnt = m_pCurrentVguiScreen . Get ( ) ;
if ( ! pScreenEnt )
return false ;
Assert ( dynamic_cast < C_VGuiScreen * > ( pScreenEnt ) ) ;
C_VGuiScreen * pVguiScreen = static_cast < C_VGuiScreen * > ( pScreenEnt ) ;
return ( pVguiScreen - > IsAttachedToViewModel ( ) & & pVguiScreen - > AcceptsInput ( ) ) ;
}
//-----------------------------------------------------------------------------
// Check to see if we're in vgui input mode...
//-----------------------------------------------------------------------------
void C_BasePlayer : : DetermineVguiInputMode ( CUserCmd * pCmd )
{
// If we're dead, close down and abort!
if ( ! IsAlive ( ) )
{
DeactivateVguiScreen ( m_pCurrentVguiScreen . Get ( ) ) ;
m_pCurrentVguiScreen . Set ( NULL ) ;
return ;
}
// If we're in vgui mode *and* we're holding down mouse buttons,
// stay in vgui mode even if we're outside the screen bounds
if ( m_pCurrentVguiScreen . Get ( ) & & ( pCmd - > buttons & ( IN_ATTACK | IN_ATTACK2 ) ) )
{
SetVGuiScreenButtonState ( m_pCurrentVguiScreen . Get ( ) , pCmd - > buttons ) ;
// Kill all attack inputs if we're in vgui screen mode
pCmd - > buttons & = ~ ( IN_ATTACK | IN_ATTACK2 ) ;
return ;
}
// We're not in vgui input mode if we're moving, or have hit a key
// that will make us move...
// Not in vgui mode if we're moving too quickly
// ROBIN: Disabled movement preventing VGUI screen usage
//if (GetVelocity().LengthSqr() > MAX_VGUI_INPUT_MODE_SPEED_SQ)
if ( 0 )
{
DeactivateVguiScreen ( m_pCurrentVguiScreen . Get ( ) ) ;
m_pCurrentVguiScreen . Set ( NULL ) ;
return ;
}
// Don't enter vgui mode if we've got combat buttons held down
bool bAttacking = false ;
if ( ( ( pCmd - > buttons & IN_ATTACK ) | | ( pCmd - > buttons & IN_ATTACK2 ) ) & & ! m_pCurrentVguiScreen . Get ( ) )
{
bAttacking = true ;
}
// Not in vgui mode if we're pushing any movement key at all
// Not in vgui mode if we're in a vehicle...
// ROBIN: Disabled movement preventing VGUI screen usage
//if ((pCmd->forwardmove > MAX_VGUI_INPUT_MODE_SPEED) ||
// (pCmd->sidemove > MAX_VGUI_INPUT_MODE_SPEED) ||
// (pCmd->upmove > MAX_VGUI_INPUT_MODE_SPEED) ||
// (pCmd->buttons & IN_JUMP) ||
// (bAttacking) )
if ( bAttacking | | IsInAVehicle ( ) )
{
DeactivateVguiScreen ( m_pCurrentVguiScreen . Get ( ) ) ;
m_pCurrentVguiScreen . Set ( NULL ) ;
return ;
}
// Don't interact with world screens when we're in a menu
if ( vgui : : surface ( ) - > IsCursorVisible ( ) )
{
DeactivateVguiScreen ( m_pCurrentVguiScreen . Get ( ) ) ;
m_pCurrentVguiScreen . Set ( NULL ) ;
return ;
}
// Not in vgui mode if there are no nearby screens
C_BaseEntity * pOldScreen = m_pCurrentVguiScreen . Get ( ) ;
m_pCurrentVguiScreen = FindNearbyVguiScreen ( EyePosition ( ) , pCmd - > viewangles , GetTeamNumber ( ) ) ;
if ( pOldScreen ! = m_pCurrentVguiScreen )
{
DeactivateVguiScreen ( pOldScreen ) ;
ActivateVguiScreen ( m_pCurrentVguiScreen . Get ( ) ) ;
}
if ( m_pCurrentVguiScreen . Get ( ) )
{
SetVGuiScreenButtonState ( m_pCurrentVguiScreen . Get ( ) , pCmd - > buttons ) ;
// Kill all attack inputs if we're in vgui screen mode
pCmd - > buttons & = ~ ( IN_ATTACK | IN_ATTACK2 ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Input handling
//-----------------------------------------------------------------------------
bool C_BasePlayer : : CreateMove ( float flInputSampleTime , CUserCmd * pCmd )
{
// Allow the vehicle to clamp the view angles
if ( IsInAVehicle ( ) )
{
IClientVehicle * pVehicle = m_hVehicle . Get ( ) - > GetClientVehicle ( ) ;
if ( pVehicle )
{
pVehicle - > UpdateViewAngles ( this , pCmd ) ;
engine - > SetViewAngles ( pCmd - > viewangles ) ;
}
}
else
{
# ifndef _X360
if ( joy_autosprint . GetBool ( ) )
# endif
{
if ( input - > KeyState ( & in_joyspeed ) ! = 0.0f )
{
pCmd - > buttons | = IN_SPEED ;
}
}
CBaseCombatWeapon * pWeapon = GetActiveWeapon ( ) ;
if ( pWeapon )
{
pWeapon - > CreateMove ( flInputSampleTime , pCmd , m_vecOldViewAngles ) ;
}
}
// If the frozen flag is set, prevent view movement (server prevents the rest of the movement)
if ( GetFlags ( ) & FL_FROZEN )
{
// Don't stomp the first time we get frozen
if ( m_bWasFrozen )
{
// Stomp the new viewangles with old ones
pCmd - > viewangles = m_vecOldViewAngles ;
engine - > SetViewAngles ( pCmd - > viewangles ) ;
}
else
{
m_bWasFrozen = true ;
}
}
else
{
m_bWasFrozen = false ;
}
m_vecOldViewAngles = pCmd - > viewangles ;
// Check to see if we're in vgui input mode...
DetermineVguiInputMode ( pCmd ) ;
return true ;
}
//-----------------------------------------------------------------------------
// Purpose: Player has changed to a new team
//-----------------------------------------------------------------------------
void C_BasePlayer : : TeamChange ( int iNewTeam )
{
// Base class does nothing
}
//-----------------------------------------------------------------------------
// Purpose: Creates, destroys, and updates the flashlight effect as needed.
//-----------------------------------------------------------------------------
void C_BasePlayer : : UpdateFlashlight ( )
{
// The dim light is the flashlight.
if ( IsEffectActive ( EF_DIMLIGHT ) )
{
if ( ! m_pFlashlight )
{
// Turned on the headlight; create it.
m_pFlashlight = new CFlashlightEffect ( index ) ;
if ( ! m_pFlashlight )
return ;
m_pFlashlight - > TurnOn ( ) ;
}
Vector vecForward , vecRight , vecUp ;
EyeVectors ( & vecForward , & vecRight , & vecUp ) ;
// Update the light with the new position and direction.
m_pFlashlight - > UpdateLight ( EyePosition ( ) , vecForward , vecRight , vecUp , FLASHLIGHT_DISTANCE ) ;
}
else if ( m_pFlashlight )
{
// Turned off the flashlight; delete it.
delete m_pFlashlight ;
m_pFlashlight = NULL ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Creates player flashlight if it's ative
//-----------------------------------------------------------------------------
void C_BasePlayer : : Flashlight ( void )
{
UpdateFlashlight ( ) ;
// Check for muzzle flash and apply to view model
C_BaseAnimating * ve = this ;
if ( GetObserverMode ( ) = = OBS_MODE_IN_EYE )
{
ve = dynamic_cast < C_BaseAnimating * > ( GetObserverTarget ( ) ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Engine is asking whether to add this player to the visible entities list
//-----------------------------------------------------------------------------
void C_BasePlayer : : AddEntity ( void )
{
// FIXME/UNDONE: Should the local player say yes to adding itself now
// and then, when it ges time to render and it shouldn't still do the render with
// STUDIO_EVENTS set so that its attachment points will get updated even if not
// in third person?
// Add in water effects
if ( IsLocalPlayer ( ) )
{
CreateWaterEffects ( ) ;
}
// If set to invisible, skip. Do this before resetting the entity pointer so it has
// valid data to decide whether it's visible.
if ( ! IsVisible ( ) | | ! g_pClientMode - > ShouldDrawLocalPlayer ( this ) )
{
return ;
}
// Server says don't interpolate this frame, so set previous info to new info.
if ( IsEffectActive ( EF_NOINTERP ) | |
Teleported ( ) )
{
ResetLatched ( ) ;
}
// Add in lighting effects
CreateLightEffects ( ) ;
}
extern float UTIL_WaterLevel ( const Vector & position , float minz , float maxz ) ;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BasePlayer : : CreateWaterEffects ( void )
{
// Must be completely submerged to bother
if ( GetWaterLevel ( ) < 3 )
{
m_bResampleWaterSurface = true ;
return ;
}
// Do special setup if this is our first time back underwater
if ( m_bResampleWaterSurface )
{
// Reset our particle timer
m_tWaterParticleTimer . Init ( 32 ) ;
// Find the surface of the water to clip against
m_flWaterSurfaceZ = UTIL_WaterLevel ( WorldSpaceCenter ( ) , WorldSpaceCenter ( ) . z , WorldSpaceCenter ( ) . z + 256 ) ;
m_bResampleWaterSurface = false ;
}
// Make sure the emitter is setup
if ( m_pWaterEmitter = = NULL )
{
if ( ( m_pWaterEmitter = WaterDebrisEffect : : Create ( " splish " ) ) = = NULL )
return ;
}
Vector vecVelocity ;
GetVectors ( & vecVelocity , NULL , NULL ) ;
Vector offset = WorldSpaceCenter ( ) ;
m_pWaterEmitter - > SetSortOrigin ( offset ) ;
SimpleParticle * pParticle ;
float curTime = gpGlobals - > frametime ;
// Add as many particles as we need
while ( m_tWaterParticleTimer . NextEvent ( curTime ) )
{
offset = WorldSpaceCenter ( ) + ( vecVelocity * 128.0f ) + RandomVector ( - 128 , 128 ) ;
// Make sure we don't start out of the water!
if ( offset . z > m_flWaterSurfaceZ )
{
offset . z = ( m_flWaterSurfaceZ - 8.0f ) ;
}
pParticle = ( SimpleParticle * ) m_pWaterEmitter - > AddParticle ( sizeof ( SimpleParticle ) , g_Mat_Fleck_Cement [ random - > RandomInt ( 0 , 1 ) ] , offset ) ;
if ( pParticle = = NULL )
continue ;
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = random - > RandomFloat ( 2.0f , 4.0f ) ;
pParticle - > m_vecVelocity = RandomVector ( - 2.0f , 2.0f ) ;
//FIXME: We should tint these based on the water's fog value!
float color = random - > RandomInt ( 32 , 128 ) ;
pParticle - > m_uchColor [ 0 ] = color ;
pParticle - > m_uchColor [ 1 ] = color ;
pParticle - > m_uchColor [ 2 ] = color ;
pParticle - > m_uchStartSize = 1 ;
pParticle - > m_uchEndSize = 1 ;
pParticle - > m_uchStartAlpha = 255 ;
pParticle - > m_uchEndAlpha = 0 ;
pParticle - > m_flRoll = random - > RandomInt ( 0 , 360 ) ;
pParticle - > m_flRollDelta = random - > RandomFloat ( - 0.5f , 0.5f ) ;
}
}
//-----------------------------------------------------------------------------
// Called when not in tactical mode. Allows view to be overriden for things like driving a tank.
//-----------------------------------------------------------------------------
void C_BasePlayer : : OverrideView ( CViewSetup * pSetup )
{
}
bool C_BasePlayer : : ShouldInterpolate ( )
{
// always interpolate myself
if ( IsLocalPlayer ( ) )
return true ;
# ifndef _XBOX
// always interpolate entity if followed by HLTV
if ( HLTVCamera ( ) - > GetCameraMan ( ) = = this )
return true ;
# endif
return BaseClass : : ShouldInterpolate ( ) ;
}
bool C_BasePlayer : : ShouldDraw ( )
{
return ( ! IsLocalPlayer ( ) | | C_BasePlayer : : ShouldDrawLocalPlayer ( ) | | ( GetObserverMode ( ) = = OBS_MODE_DEATHCAM ) ) & &
BaseClass : : ShouldDraw ( ) ;
}
int C_BasePlayer : : DrawModel ( int flags )
{
// if local player is spectating this player in first person mode, don't draw it
C_BasePlayer * player = C_BasePlayer : : GetLocalPlayer ( ) ;
if ( player & & player - > IsObserver ( ) )
{
if ( player - > GetObserverMode ( ) = = OBS_MODE_IN_EYE & &
player - > GetObserverTarget ( ) = = this )
return 0 ;
}
return BaseClass : : DrawModel ( flags ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
Vector C_BasePlayer : : GetChaseCamViewOffset ( CBaseEntity * target )
{
C_BasePlayer * player = ToBasePlayer ( target ) ;
if ( player & & player - > IsAlive ( ) )
{
if ( player - > GetFlags ( ) & FL_DUCKING )
return VEC_DUCK_VIEW ;
return VEC_VIEW ;
}
// assume it's the players ragdoll
return VEC_DEAD_VIEWHEIGHT ;
}
void C_BasePlayer : : CalcChaseCamView ( Vector & eyeOrigin , QAngle & eyeAngles , float & fov )
{
C_BaseEntity * target = GetObserverTarget ( ) ;
if ( ! target )
{
// just copy a save in-map position
VectorCopy ( EyePosition ( ) , eyeOrigin ) ;
VectorCopy ( EyeAngles ( ) , eyeAngles ) ;
return ;
} ;
// If our target isn't visible, we're at a camera point of some kind.
// Instead of letting the player rotate around an invisible point, treat
// the point as a fixed camera.
if ( ! target - > GetBaseAnimating ( ) & & ! target - > GetModel ( ) )
{
CalcRoamingView ( eyeOrigin , eyeAngles , fov ) ;
return ;
}
// QAngle tmpangles;
Vector forward , viewpoint ;
// GetObserverCamOrigin() returns ragdoll pos if player is ragdolled
Vector origin = target - > GetObserverCamOrigin ( ) ;
VectorAdd ( origin , GetChaseCamViewOffset ( target ) , origin ) ;
QAngle viewangles ;
if ( GetObserverMode ( ) = = OBS_MODE_IN_EYE )
{
viewangles = eyeAngles ;
}
else if ( IsLocalPlayer ( ) )
{
engine - > GetViewAngles ( viewangles ) ;
}
else
{
viewangles = EyeAngles ( ) ;
}
m_flObserverChaseDistance + = gpGlobals - > frametime * 48.0f ;
float flMaxDistance = CHASE_CAM_DISTANCE ;
if ( target & & target - > IsBaseTrain ( ) )
{
// if this is a train, we want to be back a little further so we can see more of it
flMaxDistance * = 2.5f ;
}
m_flObserverChaseDistance = clamp ( m_flObserverChaseDistance , 16 , flMaxDistance ) ;
AngleVectors ( viewangles , & forward ) ;
VectorNormalize ( forward ) ;
VectorMA ( origin , - m_flObserverChaseDistance , forward , viewpoint ) ;
trace_t trace ;
CTraceFilterNoNPCsOrPlayer filter ( target , COLLISION_GROUP_NONE ) ;
C_BaseEntity : : PushEnableAbsRecomputations ( false ) ; // HACK don't recompute positions while doing RayTrace
UTIL_TraceHull ( origin , viewpoint , WALL_MIN , WALL_MAX , MASK_SOLID , & filter , & trace ) ;
C_BaseEntity : : PopEnableAbsRecomputations ( ) ;
if ( trace . fraction < 1.0 )
{
viewpoint = trace . endpos ;
m_flObserverChaseDistance = VectorLength ( origin - eyeOrigin ) ;
}
VectorCopy ( viewangles , eyeAngles ) ;
VectorCopy ( viewpoint , eyeOrigin ) ;
fov = GetFOV ( ) ;
}
void C_BasePlayer : : CalcRoamingView ( Vector & eyeOrigin , QAngle & eyeAngles , float & fov )
{
C_BaseEntity * target = GetObserverTarget ( ) ;
if ( ! target )
{
target = this ;
}
m_flObserverChaseDistance = 0.0 ;
eyeOrigin = target - > EyePosition ( ) ;
eyeAngles = target - > EyeAngles ( ) ;
if ( spec_track . GetInt ( ) > 0 )
{
C_BaseEntity * target = ClientEntityList ( ) . GetBaseEntity ( spec_track . GetInt ( ) ) ;
if ( target )
{
Vector v = target - > GetAbsOrigin ( ) ; v . z + = 54 ;
QAngle a ; VectorAngles ( v - eyeOrigin , a ) ;
NormalizeAngles ( a ) ;
eyeAngles = a ;
engine - > SetViewAngles ( a ) ;
}
}
// Apply a smoothing offset to smooth out prediction errors.
Vector vSmoothOffset ;
GetPredictionErrorSmoothingVector ( vSmoothOffset ) ;
eyeOrigin + = vSmoothOffset ;
fov = GetFOV ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose: Calculate the view for the player while he's in freeze frame observer mode
//-----------------------------------------------------------------------------
void C_BasePlayer : : CalcFreezeCamView ( Vector & eyeOrigin , QAngle & eyeAngles , float & fov )
{
C_BaseEntity * pTarget = GetObserverTarget ( ) ;
if ( ! pTarget )
{
CalcDeathCamView ( eyeOrigin , eyeAngles , fov ) ;
return ;
}
// Zoom towards our target
float flCurTime = ( gpGlobals - > curtime - m_flFreezeFrameStartTime ) ;
float flBlendPerc = clamp ( flCurTime / spec_freeze_traveltime . GetFloat ( ) , 0 , 1 ) ;
flBlendPerc = SimpleSpline ( flBlendPerc ) ;
Vector vecCamDesired = pTarget - > GetObserverCamOrigin ( ) ; // Returns ragdoll origin if they're ragdolled
VectorAdd ( vecCamDesired , GetChaseCamViewOffset ( pTarget ) , vecCamDesired ) ;
Vector vecCamTarget = vecCamDesired ;
if ( pTarget - > IsAlive ( ) )
{
// Look at their chest, not their head
Vector maxs = GameRules ( ) - > GetViewVectors ( ) - > m_vHullMax ;
vecCamTarget . z - = ( maxs . z * 0.5 ) ;
}
else
{
vecCamTarget . z + = VEC_DEAD_VIEWHEIGHT . z ; // look over ragdoll, not through
}
// Figure out a view position in front of the target
Vector vecEyeOnPlane = eyeOrigin ;
vecEyeOnPlane . z = vecCamTarget . z ;
Vector vecTargetPos = vecCamTarget ;
Vector vecToTarget = vecTargetPos - vecEyeOnPlane ;
VectorNormalize ( vecToTarget ) ;
// Stop a few units away from the target, and shift up to be at the same height
vecTargetPos = vecCamTarget - ( vecToTarget * m_flFreezeFrameDistance ) ;
float flEyePosZ = pTarget - > EyePosition ( ) . z ;
vecTargetPos . z = flEyePosZ + m_flFreezeZOffset ;
// Now trace out from the target, so that we're put in front of any walls
trace_t trace ;
C_BaseEntity : : PushEnableAbsRecomputations ( false ) ; // HACK don't recompute positions while doing RayTrace
UTIL_TraceHull ( vecCamTarget , vecTargetPos , WALL_MIN , WALL_MAX , MASK_SOLID , pTarget , COLLISION_GROUP_NONE , & trace ) ;
C_BaseEntity : : PopEnableAbsRecomputations ( ) ;
if ( trace . fraction < 1.0 )
{
// The camera's going to be really close to the target. So we don't end up
// looking at someone's chest, aim close freezecams at the target's eyes.
vecTargetPos = trace . endpos ;
vecCamTarget = vecCamDesired ;
// To stop all close in views looking up at character's chins, move the view up.
vecTargetPos . z + = fabs ( vecCamTarget . z - vecTargetPos . z ) * 0.85 ;
C_BaseEntity : : PushEnableAbsRecomputations ( false ) ; // HACK don't recompute positions while doing RayTrace
UTIL_TraceHull ( vecCamTarget , vecTargetPos , WALL_MIN , WALL_MAX , MASK_SOLID , pTarget , COLLISION_GROUP_NONE , & trace ) ;
C_BaseEntity : : PopEnableAbsRecomputations ( ) ;
vecTargetPos = trace . endpos ;
}
// Look directly at the target
vecToTarget = vecCamTarget - vecTargetPos ;
VectorNormalize ( vecToTarget ) ;
VectorAngles ( vecToTarget , eyeAngles ) ;
VectorLerp ( m_vecFreezeFrameStart , vecTargetPos , flBlendPerc , eyeOrigin ) ;
if ( flCurTime > = spec_freeze_traveltime . GetFloat ( ) & & ! m_bSentFreezeFrame )
{
IGameEvent * pEvent = gameeventmanager - > CreateEvent ( " freezecam_started " ) ;
if ( pEvent )
{
gameeventmanager - > FireEventClientSide ( pEvent ) ;
}
m_bSentFreezeFrame = true ;
view - > FreezeFrame ( spec_freeze_time . GetFloat ( ) ) ;
}
}
void C_BasePlayer : : CalcInEyeCamView ( Vector & eyeOrigin , QAngle & eyeAngles , float & fov )
{
C_BaseEntity * target = GetObserverTarget ( ) ;
if ( ! target )
{
// just copy a save in-map position
VectorCopy ( EyePosition ( ) , eyeOrigin ) ;
VectorCopy ( EyeAngles ( ) , eyeAngles ) ;
return ;
} ;
if ( ! target - > IsAlive ( ) )
{
// if dead, show from 3rd person
CalcChaseCamView ( eyeOrigin , eyeAngles , fov ) ;
return ;
}
fov = GetFOV ( ) ; // TODO use tragets FOV
m_flObserverChaseDistance = 0.0 ;
eyeAngles = target - > EyeAngles ( ) ;
eyeOrigin = target - > GetAbsOrigin ( ) ;
// Apply punch angle
VectorAdd ( eyeAngles , GetPunchAngle ( ) , eyeAngles ) ;
if ( engine - > IsHLTV ( ) )
{
if ( target - > GetFlags ( ) & FL_DUCKING )
{
eyeOrigin + = VEC_DUCK_VIEW ;
}
else
{
eyeOrigin + = VEC_VIEW ;
}
}
else
{
Vector offset = m_vecViewOffset ;
# ifdef HL2MP
offset = target - > GetViewOffset ( ) ;
# endif
eyeOrigin + = offset ; // hack hack
}
engine - > SetViewAngles ( eyeAngles ) ;
}
void C_BasePlayer : : CalcDeathCamView ( Vector & eyeOrigin , QAngle & eyeAngles , float & fov )
{
CBaseEntity * pKiller = NULL ;
if ( mp_forcecamera . GetInt ( ) = = OBS_ALLOW_ALL )
{
// if mp_forcecamera is off let user see killer or look around
pKiller = GetObserverTarget ( ) ;
eyeAngles = EyeAngles ( ) ;
}
float interpolation = ( gpGlobals - > curtime - m_flDeathTime ) / DEATH_ANIMATION_TIME ;
interpolation = clamp ( interpolation , 0.0f , 1.0f ) ;
m_flObserverChaseDistance + = gpGlobals - > frametime * 48.0f ;
m_flObserverChaseDistance = clamp ( m_flObserverChaseDistance , 16 , CHASE_CAM_DISTANCE ) ;
QAngle aForward = eyeAngles ;
Vector origin = EyePosition ( ) ;
IRagdoll * pRagdoll = GetRepresentativeRagdoll ( ) ;
if ( pRagdoll )
{
origin = pRagdoll - > GetRagdollOrigin ( ) ;
origin . z + = VEC_DEAD_VIEWHEIGHT . z ; // look over ragdoll, not through
}
if ( pKiller & & pKiller - > IsPlayer ( ) & & ( pKiller ! = this ) )
{
Vector vKiller = pKiller - > EyePosition ( ) - origin ;
QAngle aKiller ; VectorAngles ( vKiller , aKiller ) ;
InterpolateAngles ( aForward , aKiller , eyeAngles , interpolation ) ;
} ;
Vector vForward ; AngleVectors ( eyeAngles , & vForward ) ;
VectorNormalize ( vForward ) ;
VectorMA ( origin , - m_flObserverChaseDistance , vForward , eyeOrigin ) ;
trace_t trace ; // clip against world
C_BaseEntity : : PushEnableAbsRecomputations ( false ) ; // HACK don't recompute positions while doing RayTrace
UTIL_TraceHull ( origin , eyeOrigin , WALL_MIN , WALL_MAX , MASK_SOLID , this , COLLISION_GROUP_NONE , & trace ) ;
C_BaseEntity : : PopEnableAbsRecomputations ( ) ;
if ( trace . fraction < 1.0 )
{
eyeOrigin = trace . endpos ;
m_flObserverChaseDistance = VectorLength ( origin - eyeOrigin ) ;
}
fov = GetFOV ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose: Return the weapon to have open the weapon selection on, based upon our currently active weapon
// Base class just uses the weapon that's currently active.
//-----------------------------------------------------------------------------
C_BaseCombatWeapon * C_BasePlayer : : GetActiveWeaponForSelection ( void )
{
return GetActiveWeapon ( ) ;
}
C_BaseAnimating * C_BasePlayer : : GetRenderedWeaponModel ( )
{
// Attach to either their weapon model or their view model.
if ( ShouldDrawLocalPlayer ( ) | | ! IsLocalPlayer ( ) )
{
return GetActiveWeapon ( ) ;
}
else
{
return GetViewModel ( ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Gets a pointer to the local player, if it exists yet.
// Output : C_BasePlayer
//-----------------------------------------------------------------------------
C_BasePlayer * C_BasePlayer : : GetLocalPlayer ( void )
{
return s_pLocalPlayer ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : bThirdperson -
//-----------------------------------------------------------------------------
void C_BasePlayer : : ThirdPersonSwitch ( bool bThirdperson )
{
// We've switch from first to third, or vice versa.
UpdateVisibility ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose: single place to decide whether the local player should draw
//-----------------------------------------------------------------------------
bool C_BasePlayer : : ShouldDrawLocalPlayer ( )
{
return input - > CAM_IsThirdPerson ( ) | | ( ToolsEnabled ( ) & & ToolFramework_IsThirdPersonCamera ( ) ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool C_BasePlayer : : IsLocalPlayer ( void ) const
{
return ( GetLocalPlayer ( ) = = this ) ;
}
int C_BasePlayer : : GetUserID ( void )
{
player_info_t pi ;
if ( ! engine - > GetPlayerInfo ( entindex ( ) , & pi ) )
return - 1 ;
return pi . userID ;
}
// For weapon prediction
void C_BasePlayer : : SetAnimation ( PLAYER_ANIM playerAnim )
{
// FIXME
}
void C_BasePlayer : : UpdateClientData ( void )
{
// Update all the items
for ( int i = 0 ; i < WeaponCount ( ) ; i + + )
{
if ( GetWeapon ( i ) ) // each item updates it's successors
GetWeapon ( i ) - > UpdateClientData ( this ) ;
}
}
// Prediction stuff
void C_BasePlayer : : PreThink ( void )
{
# if !defined( NO_ENTITY_PREDICTION )
ItemPreFrame ( ) ;
UpdateClientData ( ) ;
UpdateUnderwaterState ( ) ;
// Update the player's fog data if necessary.
UpdateFogController ( ) ;
if ( m_lifeState > = LIFE_DYING )
return ;
//
// If we're not on the ground, we're falling. Update our falling velocity.
//
if ( ! ( GetFlags ( ) & FL_ONGROUND ) )
{
m_Local . m_flFallVelocity = - GetAbsVelocity ( ) . z ;
}
# endif
}
void C_BasePlayer : : PostThink ( void )
{
# if !defined( NO_ENTITY_PREDICTION )
MDLCACHE_CRITICAL_SECTION ( ) ;
if ( IsAlive ( ) )
{
if ( ! CommentaryModeShouldSwallowInput ( this ) )
{
// do weapon stuff
ItemPostFrame ( ) ;
}
if ( GetFlags ( ) & FL_ONGROUND )
{
m_Local . m_flFallVelocity = 0 ;
}
// Don't allow bogus sequence on player
if ( GetSequence ( ) = = - 1 )
{
SetSequence ( 0 ) ;
}
StudioFrameAdvance ( ) ;
}
// Even if dead simulate entities
SimulatePlayerSimulatedEntities ( ) ;
# endif
}
//-----------------------------------------------------------------------------
// Purpose: send various tool messages - viewoffset, and base class messages (flex and bones)
//-----------------------------------------------------------------------------
void C_BasePlayer : : GetToolRecordingState ( KeyValues * msg )
{
if ( ! ToolsEnabled ( ) )
return ;
VPROF_BUDGET ( " C_BasePlayer::GetToolRecordingState " , VPROF_BUDGETGROUP_TOOLS ) ;
BaseClass : : GetToolRecordingState ( msg ) ;
msg - > SetInt ( " baseplayer " , 1 ) ;
msg - > SetInt ( " localplayer " , IsLocalPlayer ( ) ? 1 : 0 ) ;
msg - > SetString ( " playername " , GetPlayerName ( ) ) ;
static CameraRecordingState_t state ;
state . m_flFOV = GetFOV ( ) ;
float flZNear = view - > GetZNear ( ) ;
float flZFar = view - > GetZFar ( ) ;
CalcView ( state . m_vecEyePosition , state . m_vecEyeAngles , flZNear , flZFar , state . m_flFOV ) ;
state . m_bThirdPerson = ! engine - > IsPaused ( ) & & : : input - > CAM_IsThirdPerson ( ) ;
// this is a straight copy from ClientModeShared::OverrideView,
// When that method is removed in favor of rolling it into CalcView,
// then this code can (should!) be removed
if ( state . m_bThirdPerson )
{
Vector cam_ofs ;
: : input - > CAM_GetCameraOffset ( cam_ofs ) ;
QAngle camAngles ;
camAngles [ PITCH ] = cam_ofs [ PITCH ] ;
camAngles [ YAW ] = cam_ofs [ YAW ] ;
camAngles [ ROLL ] = 0 ;
Vector camForward , camRight , camUp ;
AngleVectors ( camAngles , & camForward , & camRight , & camUp ) ;
VectorMA ( state . m_vecEyePosition , - cam_ofs [ ROLL ] , camForward , state . m_vecEyePosition ) ;
// Override angles from third person camera
VectorCopy ( camAngles , state . m_vecEyeAngles ) ;
}
msg - > SetPtr ( " camera " , & state ) ;
}
//-----------------------------------------------------------------------------
// Purpose: Simulate the player for this frame
//-----------------------------------------------------------------------------
void C_BasePlayer : : Simulate ( )
{
//Frame updates
if ( this = = C_BasePlayer : : GetLocalPlayer ( ) )
{
//Update the flashlight
Flashlight ( ) ;
// Update the player's fog data if necessary.
UpdateFogController ( ) ;
}
else
{
// update step sounds for all other players
Vector vel ;
EstimateAbsVelocity ( vel ) ;
UpdateStepSound ( GetGroundSurface ( ) , GetAbsOrigin ( ) , vel ) ;
}
BaseClass : : Simulate ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : CBaseViewModel
//-----------------------------------------------------------------------------
C_BaseViewModel * C_BasePlayer : : GetViewModel ( int index /*= 0*/ )
{
Assert ( index > = 0 & & index < MAX_VIEWMODELS ) ;
C_BaseViewModel * vm = m_hViewModel [ index ] ;
if ( GetObserverMode ( ) = = OBS_MODE_IN_EYE )
{
C_BasePlayer * target = ToBasePlayer ( GetObserverTarget ( ) ) ;
// get the targets viewmodel unless the target is an observer itself
if ( target & & target ! = this & & ! target - > IsObserver ( ) )
{
vm = target - > GetViewModel ( index ) ;
}
}
return vm ;
}
C_BaseCombatWeapon * C_BasePlayer : : GetActiveWeapon ( void ) const
{
const C_BasePlayer * fromPlayer = this ;
// if localplayer is in InEye spectator mode, return weapon on chased player
if ( ( fromPlayer = = GetLocalPlayer ( ) ) & & ( GetObserverMode ( ) = = OBS_MODE_IN_EYE ) )
{
C_BaseEntity * target = GetObserverTarget ( ) ;
if ( target & & target - > IsPlayer ( ) )
{
fromPlayer = ToBasePlayer ( target ) ;
}
}
return fromPlayer - > C_BaseCombatCharacter : : GetActiveWeapon ( ) ;
}
//=========================================================
// Autoaim
// set crosshair position to point to enemey
//=========================================================
Vector C_BasePlayer : : GetAutoaimVector ( float flScale )
{
// Never autoaim a predicted weapon (for now)
Vector forward ;
AngleVectors ( GetAbsAngles ( ) + m_Local . m_vecPunchAngle , & forward ) ;
return forward ;
}
void C_BasePlayer : : PlayPlayerJingle ( )
{
# ifndef _XBOX
// Find player sound for shooter
player_info_t info ;
engine - > GetPlayerInfo ( entindex ( ) , & info ) ;
if ( ! cl_customsounds . GetBool ( ) )
return ;
// Doesn't have a jingle sound
if ( ! info . customFiles [ 1 ] )
return ;
char soundhex [ 16 ] ;
Q_binarytohex ( ( byte * ) & info . customFiles [ 1 ] , sizeof ( info . customFiles [ 1 ] ) , soundhex , sizeof ( soundhex ) ) ;
// See if logo has been downloaded.
char fullsoundname [ 512 ] ;
Q_snprintf ( fullsoundname , sizeof ( fullsoundname ) , " sound/temp/%s.wav " , soundhex ) ;
if ( ! filesystem - > FileExists ( fullsoundname ) )
{
char custname [ 512 ] ;
Q_snprintf ( custname , sizeof ( custname ) , " downloads/%s.dat " , soundhex ) ;
// it may have been downloaded but not copied under materials folder
if ( ! filesystem - > FileExists ( custname ) )
return ; // not downloaded yet
// copy from download folder to materials/temp folder
// this is done since material system can access only materials/*.vtf files
if ( ! engine - > CopyFile ( custname , fullsoundname ) )
return ;
}
Q_snprintf ( fullsoundname , sizeof ( fullsoundname ) , " temp/%s.wav " , soundhex ) ;
CLocalPlayerFilter filter ;
EmitSound_t ep ;
ep . m_nChannel = CHAN_VOICE ;
ep . m_pSoundName = fullsoundname ;
ep . m_flVolume = VOL_NORM ;
ep . m_SoundLevel = SNDLVL_NORM ;
C_BaseEntity : : EmitSound ( filter , GetSoundSourceIndex ( ) , ep ) ;
# endif
}
// Stuff for prediction
2008-09-15 02:50:57 -05:00
void C_BasePlayer : : SetSuitUpdate ( const char * name , int fgroup , int iNoRepeat )
2008-09-15 01:07:45 -05:00
{
// FIXME: Do something here?
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BasePlayer : : ResetAutoaim ( void )
{
#if 0
if ( m_vecAutoAim . x ! = 0 | | m_vecAutoAim . y ! = 0 )
{
m_vecAutoAim = QAngle ( 0 , 0 , 0 ) ;
engine - > CrosshairAngle ( edict ( ) , 0 , 0 ) ;
}
# endif
m_fOnTarget = false ;
}
bool C_BasePlayer : : ShouldPredict ( void )
{
# if !defined( NO_ENTITY_PREDICTION )
// Do this before calling into baseclass so prediction data block gets allocated
if ( IsLocalPlayer ( ) )
{
return true ;
}
# endif
return false ;
}
//-----------------------------------------------------------------------------
// Purpose: Special processing for player simulation
// NOTE: Don't chain to BaseClass!!!!
//-----------------------------------------------------------------------------
void C_BasePlayer : : PhysicsSimulate ( void )
{
# if !defined( NO_ENTITY_PREDICTION )
VPROF ( " C_BasePlayer::PhysicsSimulate " ) ;
// If we've got a moveparent, we must simulate that first.
CBaseEntity * pMoveParent = GetMoveParent ( ) ;
if ( pMoveParent )
{
pMoveParent - > PhysicsSimulate ( ) ;
}
// Make sure not to simulate this guy twice per frame
if ( m_nSimulationTick = = gpGlobals - > tickcount )
return ;
m_nSimulationTick = gpGlobals - > tickcount ;
if ( ! IsLocalPlayer ( ) )
return ;
C_CommandContext * ctx = GetCommandContext ( ) ;
Assert ( ctx ) ;
Assert ( ctx - > needsprocessing ) ;
if ( ! ctx - > needsprocessing )
return ;
ctx - > needsprocessing = false ;
// Handle FL_FROZEN.
if ( GetFlags ( ) & FL_FROZEN )
{
ctx - > cmd . forwardmove = 0 ;
ctx - > cmd . sidemove = 0 ;
ctx - > cmd . upmove = 0 ;
ctx - > cmd . buttons = 0 ;
ctx - > cmd . impulse = 0 ;
//VectorCopy ( pl.v_angle, ctx->cmd.viewangles );
}
// Run the next command
prediction - > RunCommand (
this ,
& ctx - > cmd ,
MoveHelper ( ) ) ;
# endif
}
const QAngle & C_BasePlayer : : GetPunchAngle ( )
{
return m_Local . m_vecPunchAngle . Get ( ) ;
}
void C_BasePlayer : : SetPunchAngle ( const QAngle & angle )
{
m_Local . m_vecPunchAngle = angle ;
}
float C_BasePlayer : : GetWaterJumpTime ( ) const
{
return m_flWaterJumpTime ;
}
void C_BasePlayer : : SetWaterJumpTime ( float flWaterJumpTime )
{
m_flWaterJumpTime = flWaterJumpTime ;
}
float C_BasePlayer : : GetSwimSoundTime ( ) const
{
return m_flSwimSoundTime ;
}
void C_BasePlayer : : SetSwimSoundTime ( float flSwimSoundTime )
{
m_flSwimSoundTime = flSwimSoundTime ;
}
//-----------------------------------------------------------------------------
// Purpose: Return true if this object can be +used by the player
//-----------------------------------------------------------------------------
bool C_BasePlayer : : IsUseableEntity ( CBaseEntity * pEntity , unsigned int requiredCaps )
{
return false ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : float
//-----------------------------------------------------------------------------
float C_BasePlayer : : GetFOV ( void )
{
if ( GetObserverMode ( ) = = OBS_MODE_IN_EYE )
{
C_BasePlayer * pTargetPlayer = dynamic_cast < C_BasePlayer * > ( GetObserverTarget ( ) ) ;
// get fov from observer target. Not if target is observer itself
if ( pTargetPlayer & & ! pTargetPlayer - > IsObserver ( ) )
{
return pTargetPlayer - > GetFOV ( ) ;
}
}
// Allow our vehicle to override our FOV if it's currently at the default FOV.
float flDefaultFOV ;
IClientVehicle * pVehicle = GetVehicle ( ) ;
if ( pVehicle )
{
CacheVehicleView ( ) ;
flDefaultFOV = ( m_flVehicleViewFOV = = 0 ) ? GetDefaultFOV ( ) : m_flVehicleViewFOV ;
}
else
{
flDefaultFOV = GetDefaultFOV ( ) ;
}
float fFOV = ( m_iFOV = = 0 ) ? flDefaultFOV : m_iFOV ;
// Don't do lerping during prediction. It's only necessary when actually rendering,
// and it'll cause problems due to prediction timing messiness.
if ( ! prediction - > InPrediction ( ) )
{
// See if we need to lerp the values for local player
if ( IsLocalPlayer ( ) & & ( fFOV ! = m_iFOVStart ) & & ( m_Local . m_flFOVRate > 0.0f ) )
{
float deltaTime = ( float ) ( gpGlobals - > curtime - m_flFOVTime ) / m_Local . m_flFOVRate ;
# if !defined( NO_ENTITY_PREDICTION )
if ( GetPredictable ( ) )
{
// m_flFOVTime was set to a predicted time in the future, because the FOV change was predicted.
deltaTime = ( float ) ( GetFinalPredictedTime ( ) - m_flFOVTime ) ;
deltaTime + = ( gpGlobals - > interpolation_amount * TICK_INTERVAL ) ;
deltaTime / = m_Local . m_flFOVRate ;
}
# endif
if ( deltaTime > = 1.0f )
{
//If we're past the zoom time, just take the new value and stop lerping
m_iFOVStart = fFOV ;
}
else
{
fFOV = SimpleSplineRemapValClamped ( deltaTime , 0.0f , 1.0f , ( float ) m_iFOVStart , fFOV ) ;
}
}
}
return fFOV ;
}
void RecvProxy_LocalVelocityX ( const CRecvProxyData * pData , void * pStruct , void * pOut )
{
C_BasePlayer * pPlayer = ( C_BasePlayer * ) pStruct ;
Assert ( pPlayer ) ;
float flNewVel_x = pData - > m_Value . m_Float ;
Vector vecVelocity = pPlayer - > GetLocalVelocity ( ) ;
if ( vecVelocity . x ! = flNewVel_x ) // Should this use an epsilon check?
{
vecVelocity . x = flNewVel_x ;
pPlayer - > SetLocalVelocity ( vecVelocity ) ;
}
}
void RecvProxy_LocalVelocityY ( const CRecvProxyData * pData , void * pStruct , void * pOut )
{
C_BasePlayer * pPlayer = ( C_BasePlayer * ) pStruct ;
Assert ( pPlayer ) ;
float flNewVel_y = pData - > m_Value . m_Float ;
Vector vecVelocity = pPlayer - > GetLocalVelocity ( ) ;
if ( vecVelocity . y ! = flNewVel_y )
{
vecVelocity . y = flNewVel_y ;
pPlayer - > SetLocalVelocity ( vecVelocity ) ;
}
}
void RecvProxy_LocalVelocityZ ( const CRecvProxyData * pData , void * pStruct , void * pOut )
{
C_BasePlayer * pPlayer = ( C_BasePlayer * ) pStruct ;
Assert ( pPlayer ) ;
float flNewVel_z = pData - > m_Value . m_Float ;
Vector vecVelocity = pPlayer - > GetLocalVelocity ( ) ;
if ( vecVelocity . z ! = flNewVel_z )
{
vecVelocity . z = flNewVel_z ;
pPlayer - > SetLocalVelocity ( vecVelocity ) ;
}
}
void RecvProxy_ObserverTarget ( const CRecvProxyData * pData , void * pStruct , void * pOut )
{
C_BasePlayer * pPlayer = ( C_BasePlayer * ) pStruct ;
Assert ( pPlayer ) ;
EHANDLE hTarget ;
RecvProxy_IntToEHandle ( pData , pStruct , & hTarget ) ;
pPlayer - > SetObserverTarget ( hTarget ) ;
}
//-----------------------------------------------------------------------------
// Purpose: Remove this player from a vehicle
//-----------------------------------------------------------------------------
void C_BasePlayer : : LeaveVehicle ( void )
{
if ( NULL = = m_hVehicle . Get ( ) )
return ;
// Let server do this for now
#if 0
IClientVehicle * pVehicle = GetVehicle ( ) ;
Assert ( pVehicle ) ;
int nRole = pVehicle - > GetPassengerRole ( this ) ;
Assert ( nRole ! = VEHICLE_ROLE_NONE ) ;
SetParent ( NULL ) ;
// Find the first non-blocked exit point:
Vector vNewPos = GetAbsOrigin ( ) ;
QAngle qAngles = GetAbsAngles ( ) ;
pVehicle - > GetPassengerExitPoint ( nRole , & vNewPos , & qAngles ) ;
OnVehicleEnd ( vNewPos ) ;
SetAbsOrigin ( vNewPos ) ;
SetAbsAngles ( qAngles ) ;
m_Local . m_iHideHUD & = ~ HIDEHUD_WEAPONSELECTION ;
RemoveEffects ( EF_NODRAW ) ;
SetMoveType ( MOVETYPE_WALK ) ;
SetCollisionGroup ( COLLISION_GROUP_PLAYER ) ;
qAngles [ ROLL ] = 0 ;
SnapEyeAngles ( qAngles ) ;
m_hVehicle = NULL ;
pVehicle - > SetPassenger ( nRole , NULL ) ;
Weapon_Switch ( m_hLastWeapon ) ;
# endif
}
float C_BasePlayer : : GetMinFOV ( ) const
{
if ( gpGlobals - > maxClients = = 1 )
{
// Let them do whatever they want, more or less, in single player
return 5 ;
}
else
{
return 75 ;
}
}
float C_BasePlayer : : GetFinalPredictedTime ( ) const
{
return ( m_nFinalPredictedTick * TICK_INTERVAL ) ;
}
void C_BasePlayer : : NotePredictionError ( const Vector & vDelta )
{
// don't worry about prediction errors when dead
if ( ! IsAlive ( ) )
return ;
# if !defined( NO_ENTITY_PREDICTION )
Vector vOldDelta ;
GetPredictionErrorSmoothingVector ( vOldDelta ) ;
// sum all errors within smoothing time
m_vecPredictionError = vDelta + vOldDelta ;
// remember when last error happened
m_flPredictionErrorTime = gpGlobals - > curtime ;
ResetLatched ( ) ;
# endif
}
// offset curtime and setup bones at that time using fake interpolation
// fake interpolation means we don't have reliable interpolation history (the local player doesn't animate locally)
// so we just modify cycle and origin directly and use that as a fake guess
void C_BasePlayer : : ForceSetupBonesAtTimeFakeInterpolation ( matrix3x4_t * pBonesOut , float curtimeOffset )
{
// we don't have any interpolation data, so fake it
float cycle = m_flCycle ;
Vector origin = GetLocalOrigin ( ) ;
// blow the cached prev bones
InvalidateBoneCache ( ) ;
// reset root position to flTime
Interpolate ( gpGlobals - > curtime + curtimeOffset ) ;
// force cycle back by boneDt
m_flCycle = fmod ( 10 + cycle + m_flPlaybackRate * curtimeOffset , 1.0f ) ;
SetLocalOrigin ( origin + curtimeOffset * GetLocalVelocity ( ) ) ;
// Setup bone state to extrapolate physics velocity
SetupBones ( pBonesOut , MAXSTUDIOBONES , BONE_USED_BY_ANYTHING , gpGlobals - > curtime + curtimeOffset ) ;
m_flCycle = cycle ;
SetLocalOrigin ( origin ) ;
}
void C_BasePlayer : : GetRagdollInitBoneArrays ( matrix3x4_t * pDeltaBones0 , matrix3x4_t * pDeltaBones1 , matrix3x4_t * pCurrentBones , float boneDt )
{
if ( ! IsLocalPlayer ( ) )
{
BaseClass : : GetRagdollInitBoneArrays ( pDeltaBones0 , pDeltaBones1 , pCurrentBones , boneDt ) ;
return ;
}
ForceSetupBonesAtTimeFakeInterpolation ( pDeltaBones0 , - boneDt ) ;
ForceSetupBonesAtTimeFakeInterpolation ( pDeltaBones1 , 0 ) ;
float ragdollCreateTime = PhysGetSyncCreateTime ( ) ;
if ( ragdollCreateTime ! = gpGlobals - > curtime )
{
ForceSetupBonesAtTimeFakeInterpolation ( pCurrentBones , ragdollCreateTime - gpGlobals - > curtime ) ;
}
else
{
SetupBones ( pCurrentBones , MAXSTUDIOBONES , BONE_USED_BY_ANYTHING , gpGlobals - > curtime ) ;
}
}
void C_BasePlayer : : GetPredictionErrorSmoothingVector ( Vector & vOffset )
{
# if !defined( NO_ENTITY_PREDICTION )
if ( engine - > IsPlayingDemo ( ) | | ! cl_smooth . GetInt ( ) | | ! cl_predict - > GetInt ( ) )
{
vOffset . Init ( ) ;
return ;
}
float errorAmount = ( gpGlobals - > curtime - m_flPredictionErrorTime ) / cl_smoothtime . GetFloat ( ) ;
if ( errorAmount > = 1.0f )
{
vOffset . Init ( ) ;
return ;
}
errorAmount = 1.0f - errorAmount ;
vOffset = m_vecPredictionError * errorAmount ;
# else
vOffset . Init ( ) ;
# endif
}
IRagdoll * C_BasePlayer : : GetRepresentativeRagdoll ( ) const
{
return m_pRagdoll ;
}
IMaterial * C_BasePlayer : : GetHeadLabelMaterial ( void )
{
if ( GetClientVoiceMgr ( ) = = NULL )
return NULL ;
return GetClientVoiceMgr ( ) - > GetHeadLabelMaterial ( ) ;
}
bool IsInFreezeCam ( void )
{
C_BasePlayer * pPlayer = C_BasePlayer : : GetLocalPlayer ( ) ;
if ( pPlayer & & pPlayer - > GetObserverMode ( ) = = OBS_MODE_FREEZECAM )
return true ;
return false ;
}
//-----------------------------------------------------------------------------
// Purpose: Set the fog controller data per player.
// Input : &inputdata -
//-----------------------------------------------------------------------------
void C_BasePlayer : : FogControllerChanged ( bool bSnap )
{
if ( m_Local . m_PlayerFog . m_hCtrl )
{
fogparams_t * pFogParams = & ( m_Local . m_PlayerFog . m_hCtrl - > m_fog ) ;
/*
Msg ( " Updating Fog Target: (%d,%d,%d) %.0f,%.0f -> (%d,%d,%d) %.0f,%.0f (%.2f seconds) \n " ,
m_CurrentFog . colorPrimary . GetR ( ) , m_CurrentFog . colorPrimary . GetB ( ) , m_CurrentFog . colorPrimary . GetG ( ) ,
m_CurrentFog . start . Get ( ) , m_CurrentFog . end . Get ( ) ,
pFogParams - > colorPrimary . GetR ( ) , pFogParams - > colorPrimary . GetB ( ) , pFogParams - > colorPrimary . GetG ( ) ,
pFogParams - > start . Get ( ) , pFogParams - > end . Get ( ) , pFogParams - > duration . Get ( ) ) ; */
// Setup the fog color transition.
m_Local . m_PlayerFog . m_OldColor = m_CurrentFog . colorPrimary ;
m_Local . m_PlayerFog . m_flOldStart = m_CurrentFog . start ;
m_Local . m_PlayerFog . m_flOldEnd = m_CurrentFog . end ;
m_Local . m_PlayerFog . m_NewColor = pFogParams - > colorPrimary ;
m_Local . m_PlayerFog . m_flNewStart = pFogParams - > start ;
m_Local . m_PlayerFog . m_flNewEnd = pFogParams - > end ;
m_Local . m_PlayerFog . m_flTransitionTime = bSnap ? - 1 : gpGlobals - > curtime ;
m_CurrentFog = * pFogParams ;
// Update the fog player's local fog data with the fog controller's data if need be.
UpdateFogController ( ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Check to see that the controllers data is up to date.
//-----------------------------------------------------------------------------
void C_BasePlayer : : UpdateFogController ( void )
{
if ( m_Local . m_PlayerFog . m_hCtrl )
{
// Don't bother copying while we're transitioning, since it'll be stomped in UpdateFogBlend();
if ( m_Local . m_PlayerFog . m_flTransitionTime = = - 1 & & ( m_hOldFogController = = m_Local . m_PlayerFog . m_hCtrl ) )
{
fogparams_t * pFogParams = & ( m_Local . m_PlayerFog . m_hCtrl - > m_fog ) ;
if ( m_CurrentFog ! = * pFogParams )
{
/*
Msg ( " FORCING UPDATE: (%d,%d,%d) %.0f,%.0f -> (%d,%d,%d) %.0f,%.0f (%.2f seconds) \n " ,
m_CurrentFog . colorPrimary . GetR ( ) , m_CurrentFog . colorPrimary . GetB ( ) , m_CurrentFog . colorPrimary . GetG ( ) ,
m_CurrentFog . start . Get ( ) , m_CurrentFog . end . Get ( ) ,
pFogParams - > colorPrimary . GetR ( ) , pFogParams - > colorPrimary . GetB ( ) , pFogParams - > colorPrimary . GetG ( ) ,
pFogParams - > start . Get ( ) , pFogParams - > end . Get ( ) , pFogParams - > duration . Get ( ) ) ; */
m_CurrentFog = * pFogParams ;
}
}
}
else
{
if ( m_CurrentFog . farz ! = - 1 | | m_CurrentFog . enable ! = false )
{
// No fog controller in this level. Use default fog parameters.
m_CurrentFog . farz = - 1 ;
m_CurrentFog . enable = false ;
}
}
// Update the fog blending state - of necessary.
UpdateFogBlend ( ) ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void C_BasePlayer : : UpdateFogBlend ( void )
{
// Transition.
if ( m_Local . m_PlayerFog . m_flTransitionTime ! = - 1 )
{
float flTimeDelta = gpGlobals - > curtime - m_Local . m_PlayerFog . m_flTransitionTime ;
if ( flTimeDelta < m_CurrentFog . duration )
{
float flScale = flTimeDelta / m_CurrentFog . duration ;
m_CurrentFog . colorPrimary . SetR ( ( m_Local . m_PlayerFog . m_NewColor . r * flScale ) + ( m_Local . m_PlayerFog . m_OldColor . r * ( 1.0f - flScale ) ) ) ;
m_CurrentFog . colorPrimary . SetG ( ( m_Local . m_PlayerFog . m_NewColor . g * flScale ) + ( m_Local . m_PlayerFog . m_OldColor . g * ( 1.0f - flScale ) ) ) ;
m_CurrentFog . colorPrimary . SetB ( ( m_Local . m_PlayerFog . m_NewColor . b * flScale ) + ( m_Local . m_PlayerFog . m_OldColor . b * ( 1.0f - flScale ) ) ) ;
m_CurrentFog . start . Set ( ( m_Local . m_PlayerFog . m_flNewStart * flScale ) + ( ( m_Local . m_PlayerFog . m_flOldStart * ( 1.0f - flScale ) ) ) ) ;
m_CurrentFog . end . Set ( ( m_Local . m_PlayerFog . m_flNewEnd * flScale ) + ( ( m_Local . m_PlayerFog . m_flOldEnd * ( 1.0f - flScale ) ) ) ) ;
}
else
{
// Slam the final fog values.
m_CurrentFog . colorPrimary . SetR ( m_Local . m_PlayerFog . m_NewColor . r ) ;
m_CurrentFog . colorPrimary . SetG ( m_Local . m_PlayerFog . m_NewColor . g ) ;
m_CurrentFog . colorPrimary . SetB ( m_Local . m_PlayerFog . m_NewColor . b ) ;
m_CurrentFog . start . Set ( m_Local . m_PlayerFog . m_flNewStart ) ;
m_CurrentFog . end . Set ( m_Local . m_PlayerFog . m_flNewEnd ) ;
m_Local . m_PlayerFog . m_flTransitionTime = - 1 ;
/*
Msg ( " Finished transition to (%d,%d,%d) %.0f,%.0f \n " ,
m_CurrentFog . colorPrimary . GetR ( ) , m_CurrentFog . colorPrimary . GetB ( ) , m_CurrentFog . colorPrimary . GetG ( ) ,
m_CurrentFog . start . Get ( ) , m_CurrentFog . end . Get ( ) ) ; */
}
}
}
void CC_DumpClientSoundscapeData ( const CCommand & args )
{
C_BasePlayer * pPlayer = C_BasePlayer : : GetLocalPlayer ( ) ;
if ( ! pPlayer )
return ;
Msg ( " Client Soundscape data dump: \n " ) ;
Msg ( " Position: %.2f %.2f %.2f \n " , pPlayer - > GetAbsOrigin ( ) . x , pPlayer - > GetAbsOrigin ( ) . y , pPlayer - > GetAbsOrigin ( ) . z ) ;
Msg ( " soundscape index: %d \n " , pPlayer - > m_Local . m_audio . soundscapeIndex ) ;
Msg ( " entity index: %d \n " , pPlayer - > m_Local . m_audio . ent . Get ( ) ? pPlayer - > m_Local . m_audio . ent - > entindex ( ) : - 1 ) ;
if ( pPlayer - > m_Local . m_audio . ent . Get ( ) )
{
Msg ( " entity pos: %.2f %.2f %.2f \n " , pPlayer - > m_Local . m_audio . ent . Get ( ) - > GetAbsOrigin ( ) . x , pPlayer - > m_Local . m_audio . ent . Get ( ) - > GetAbsOrigin ( ) . y , pPlayer - > m_Local . m_audio . ent . Get ( ) - > GetAbsOrigin ( ) . z ) ;
if ( pPlayer - > m_Local . m_audio . ent . Get ( ) - > IsDormant ( ) )
{
Msg ( " ENTITY IS DORMANT \n " ) ;
}
}
bool bFoundOne = false ;
for ( int i = 0 ; i < NUM_AUDIO_LOCAL_SOUNDS ; i + + )
{
if ( pPlayer - > m_Local . m_audio . localBits & ( 1 < < i ) )
{
if ( ! bFoundOne )
{
Msg ( " Sound Positions: \n " ) ;
bFoundOne = true ;
}
Vector vecPos = pPlayer - > m_Local . m_audio . localSound [ i ] ;
Msg ( " %d: %.2f %.2f %.2f \n " , i , vecPos . x , vecPos . y , vecPos . z ) ;
}
}
Msg ( " End dump. \n " ) ;
}
static ConCommand soundscape_dumpclient ( " soundscape_dumpclient " , CC_DumpClientSoundscapeData , " Dumps the client's soundscape data. \n " , FCVAR_CHEAT ) ;