aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/client
diff options
context:
space:
mode:
authorJohn Schoenick <[email protected]>2015-09-09 18:35:41 -0700
committerJohn Schoenick <[email protected]>2015-09-09 18:35:41 -0700
commit0d8dceea4310fde5706b3ce1c70609d72a38efdf (patch)
treec831ef32c2c801a5c5a80401736b52c7b5a528ec /mp/src/game/client
parentUpdated the SDK with the latest code from the TF and HL2 branches. (diff)
downloadsource-sdk-2013-0d8dceea4310fde5706b3ce1c70609d72a38efdf.tar.xz
source-sdk-2013-0d8dceea4310fde5706b3ce1c70609d72a38efdf.zip
Updated the SDK with the latest code from the TF and HL2 branches.HEADmaster
Diffstat (limited to 'mp/src/game/client')
-rw-r--r--mp/src/game/client/baseanimatedtextureproxy.cpp42
-rw-r--r--mp/src/game/client/bsp_utils.cpp170
-rw-r--r--mp/src/game/client/bsp_utils.h21
-rw-r--r--mp/src/game/client/c_ai_basenpc.cpp16
-rw-r--r--mp/src/game/client/c_ai_basenpc.h4
-rw-r--r--mp/src/game/client/c_baseanimating.cpp168
-rw-r--r--mp/src/game/client/c_baseanimating.h23
-rw-r--r--mp/src/game/client/c_basecombatcharacter.cpp19
-rw-r--r--mp/src/game/client/c_basecombatcharacter.h7
-rw-r--r--mp/src/game/client/c_basecombatweapon.cpp5
-rw-r--r--mp/src/game/client/c_baseentity.cpp64
-rw-r--r--mp/src/game/client/c_baseentity.h5
-rw-r--r--mp/src/game/client/c_baseplayer.cpp50
-rw-r--r--mp/src/game/client/c_baseplayer.h7
-rw-r--r--mp/src/game/client/c_baseviewmodel.cpp17
-rw-r--r--mp/src/game/client/c_rope.cpp20
-rw-r--r--mp/src/game/client/c_sceneentity.cpp6
-rw-r--r--mp/src/game/client/c_slideshow_display.cpp8
-rw-r--r--mp/src/game/client/c_soundscape.cpp2
-rw-r--r--mp/src/game/client/c_team_objectiveresource.h2
-rw-r--r--mp/src/game/client/c_vote_controller.cpp4
-rw-r--r--mp/src/game/client/cdll_bounded_cvars.cpp2
-rw-r--r--mp/src/game/client/cdll_client_int.cpp24
-rw-r--r--mp/src/game/client/client_base.vpc5
-rw-r--r--mp/src/game/client/clientleafsystem.cpp72
-rw-r--r--mp/src/game/client/clientmode_shared.cpp130
-rw-r--r--mp/src/game/client/clientmode_shared.h2
-rw-r--r--mp/src/game/client/clientshadowmgr.cpp3
-rw-r--r--mp/src/game/client/clientsideeffects.cpp27
-rw-r--r--mp/src/game/client/clientsideeffects.h7
-rw-r--r--mp/src/game/client/fx_quad.cpp22
-rw-r--r--mp/src/game/client/fx_quad.h2
-rw-r--r--mp/src/game/client/fx_tracer.cpp27
-rw-r--r--mp/src/game/client/game_controls/MapOverview.cpp4
-rw-r--r--mp/src/game/client/game_controls/SpectatorGUI.cpp3
-rw-r--r--mp/src/game/client/game_controls/basemodel_panel.cpp205
-rw-r--r--mp/src/game/client/game_controls/basemodel_panel.h23
-rw-r--r--mp/src/game/client/game_controls/baseviewport.cpp21
-rw-r--r--mp/src/game/client/game_controls/vguitextwindow.cpp6
-rw-r--r--mp/src/game/client/hl2/c_waterbullet.cpp2
-rw-r--r--mp/src/game/client/hl2/hud_credits.cpp4
-rw-r--r--mp/src/game/client/hltvcamera.cpp2
-rw-r--r--mp/src/game/client/hud_basechat.cpp9
-rw-r--r--mp/src/game/client/hud_basedeathnotice.cpp97
-rw-r--r--mp/src/game/client/hud_basedeathnotice.h10
-rw-r--r--mp/src/game/client/hud_controlpointicons.cpp2
-rw-r--r--mp/src/game/client/hud_vote.cpp412
-rw-r--r--mp/src/game/client/hud_vote.h24
-rw-r--r--mp/src/game/client/in_camera.cpp1
-rw-r--r--mp/src/game/client/in_joystick.cpp2
-rw-r--r--mp/src/game/client/in_mouse.cpp2
-rw-r--r--mp/src/game/client/input.h9
-rw-r--r--mp/src/game/client/particlemgr.cpp70
-rw-r--r--mp/src/game/client/particlemgr.h12
-rw-r--r--mp/src/game/client/particles_new.cpp2
-rw-r--r--mp/src/game/client/particles_new.h9
-rw-r--r--mp/src/game/client/prediction.cpp13
-rw-r--r--mp/src/game/client/rendertexture.cpp4
-rw-r--r--mp/src/game/client/replay/genericclassbased_replay.cpp2
-rw-r--r--mp/src/game/client/sixense/in_sixense.cpp2
-rw-r--r--mp/src/game/client/spritemodel.cpp12
-rw-r--r--mp/src/game/client/vgui_debugoverlaypanel.cpp3
-rw-r--r--mp/src/game/client/vgui_fpspanel.cpp4
-rw-r--r--mp/src/game/client/vgui_loadingdiscpanel.cpp4
-rw-r--r--mp/src/game/client/vgui_messagechars.cpp2
-rw-r--r--mp/src/game/client/vgui_netgraphpanel.cpp14
-rw-r--r--mp/src/game/client/vgui_schemevisualizer.cpp6
-rw-r--r--mp/src/game/client/vgui_video.cpp3
-rw-r--r--mp/src/game/client/view.cpp4
-rw-r--r--mp/src/game/client/weapon_selection.cpp3
70 files changed, 1531 insertions, 459 deletions
diff --git a/mp/src/game/client/baseanimatedtextureproxy.cpp b/mp/src/game/client/baseanimatedtextureproxy.cpp
index 4365e866..b7151114 100644
--- a/mp/src/game/client/baseanimatedtextureproxy.cpp
+++ b/mp/src/game/client/baseanimatedtextureproxy.cpp
@@ -11,6 +11,8 @@
#include "materialsystem/itexture.h"
#include "tier1/KeyValues.h"
#include "toolframework_client.h"
+#include "tier0/minidump.h"
+#include "tier0/stacktools.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
@@ -39,25 +41,33 @@ CBaseAnimatedTextureProxy::~CBaseAnimatedTextureProxy()
bool CBaseAnimatedTextureProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
char const* pAnimatedTextureVarName = pKeyValues->GetString( "animatedTextureVar" );
- if( !pAnimatedTextureVarName )
- return false;
- bool foundVar;
- m_AnimatedTextureVar = pMaterial->FindVar( pAnimatedTextureVarName, &foundVar, false );
- if( !foundVar )
- return false;
-
- char const* pAnimatedTextureFrameNumVarName = pKeyValues->GetString( "animatedTextureFrameNumVar" );
- if( !pAnimatedTextureFrameNumVarName )
- return false;
+ if( pAnimatedTextureVarName )
+ {
+ bool foundVar;
- m_AnimatedTextureFrameNumVar = pMaterial->FindVar( pAnimatedTextureFrameNumVarName, &foundVar, false );
- if( !foundVar )
- return false;
+ m_AnimatedTextureVar = pMaterial->FindVar( pAnimatedTextureVarName, &foundVar, false );
+ if( foundVar )
+ {
+ char const* pAnimatedTextureFrameNumVarName = pKeyValues->GetString( "animatedTextureFrameNumVar" );
+
+ if( pAnimatedTextureFrameNumVarName )
+ {
+ m_AnimatedTextureFrameNumVar = pMaterial->FindVar( pAnimatedTextureFrameNumVarName, &foundVar, false );
+
+ if( foundVar )
+ {
+ m_FrameRate = pKeyValues->GetFloat( "animatedTextureFrameRate", 15 );
+ m_WrapAnimation = !pKeyValues->GetInt( "animationNoWrap", 0 );
+ return true;
+ }
+ }
+ }
+ }
- m_FrameRate = pKeyValues->GetFloat( "animatedTextureFrameRate", 15 );
- m_WrapAnimation = !pKeyValues->GetInt( "animationNoWrap", 0 );
- return true;
+ // Error - null out pointers.
+ Cleanup();
+ return false;
}
void CBaseAnimatedTextureProxy::Cleanup()
diff --git a/mp/src/game/client/bsp_utils.cpp b/mp/src/game/client/bsp_utils.cpp
new file mode 100644
index 00000000..c21c2ada
--- /dev/null
+++ b/mp/src/game/client/bsp_utils.cpp
@@ -0,0 +1,170 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Exposes bsp tools to game for e.g. workshop use
+//
+// $NoKeywords: $
+//===========================================================================//
+
+#include "cbase.h"
+#include <tier2/tier2.h>
+#include "filesystem.h"
+#include "bsp_utils.h"
+#include "utlbuffer.h"
+#include "igamesystem.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+bool BSP_SyncRepack( const char *pszInputMapFile,
+ const char *pszOutputMapFile,
+ IBSPPack::eRepackBSPFlags eRepackFlags )
+{
+ // load the bsppack dll
+ IBSPPack *libBSPPack = NULL;
+ CSysModule *pModule = g_pFullFileSystem->LoadModule( "bsppack" );
+ if ( pModule )
+ {
+ CreateInterfaceFn BSPPackFactory = Sys_GetFactory( pModule );
+ if ( BSPPackFactory )
+ {
+ libBSPPack = ( IBSPPack * )BSPPackFactory( IBSPPACK_VERSION_STRING, NULL );
+ }
+ }
+ if( !libBSPPack )
+ {
+ Warning( "Can't load bsppack library - unable to compress bsp\n" );
+ return false;
+ }
+
+ Msg( "Repacking %s -> %s\n", pszInputMapFile, pszOutputMapFile );
+
+ if ( !g_pFullFileSystem->FileExists( pszInputMapFile ) )
+ {
+ Warning( "Couldn't open input file %s - BSP recompress failed\n", pszInputMapFile );
+ return false;
+ }
+
+ CUtlBuffer inputBuffer;
+ if ( !g_pFullFileSystem->ReadFile( pszInputMapFile, NULL, inputBuffer ) )
+ {
+ Warning( "Couldn't read file %s - BSP compression failed\n", pszInputMapFile );
+ return false;
+ }
+
+ CUtlBuffer outputBuffer;
+
+ if ( !libBSPPack->RepackBSP( inputBuffer, outputBuffer, eRepackFlags ) )
+ {
+ Warning( "Internal error compressing BSP\n" );
+ return false;
+ }
+
+ g_pFullFileSystem->WriteFile( pszOutputMapFile, NULL, outputBuffer );
+
+ Msg( "Successfully repacked %s as %s -- %u -> %u bytes\n",
+ pszInputMapFile, pszOutputMapFile, inputBuffer.TellPut(), outputBuffer.TellPut() );
+
+ return true;
+}
+
+// Helper to create a thread that calls SyncCompressMap, and clean it up when it exists
+void BSP_BackgroundRepack( const char *pszInputMapFile,
+ const char *pszOutputMapFile,
+ IBSPPack::eRepackBSPFlags eRepackFlags )
+{
+ // Make this a gamesystem and thread, so it can check for completion each frame and clean itself up. Run() is the
+ // background thread, Update() is the main thread tick.
+ class BackgroundBSPRepackThread : public CThread, public CAutoGameSystemPerFrame
+ {
+ public:
+ BackgroundBSPRepackThread( const char *pszInputFile, const char *pszOutputFile, IBSPPack::eRepackBSPFlags eRepackFlags )
+ : m_strInput( pszInputFile )
+ , m_strOutput( pszOutputFile )
+ , m_eRepackFlags( eRepackFlags )
+ {
+ Start();
+ }
+
+ // CThread job - returns 0 for success
+ virtual int Run() OVERRIDE
+ {
+ return BSP_SyncRepack( m_strInput.Get(), m_strOutput.Get(), m_eRepackFlags ) ? 0 : 1;
+ }
+
+ // GameSystem
+ virtual const char* Name( void ) OVERRIDE { return "BackgroundBSPRepackThread"; }
+
+ // Runs on main thread
+ void CheckFinished()
+ {
+ if ( !IsAlive() )
+ {
+ // Thread finished
+ if ( GetResult() != 0 )
+ {
+ Warning( "Map compression thread failed :(\n" );
+ }
+
+ // AutoGameSystem deregisters itself on destruction, we're done
+ delete this;
+ }
+ }
+
+ #ifdef CLIENT_DLL
+ virtual void Update( float frametime ) OVERRIDE { CheckFinished(); }
+ #else // GAME DLL
+ virtual void FrameUpdatePostEntityThink() OVERRIDE { CheckFinished(); }
+ #endif
+ private:
+ CUtlString m_strInput;
+ CUtlString m_strOutput;
+ IBSPPack::eRepackBSPFlags m_eRepackFlags;
+ };
+
+ Msg( "Starting BSP repack job %s -> %s\n", pszInputMapFile, pszOutputMapFile );
+
+ // Deletes itself up when done
+ new BackgroundBSPRepackThread( pszInputMapFile, pszOutputMapFile, eRepackFlags );
+}
+
+CON_COMMAND( bsp_repack, "Repack and output a (re)compressed version of a bsp file" )
+{
+#ifdef GAME_DLL
+ if ( !UTIL_IsCommandIssuedByServerAdmin() )
+ return;
+#endif
+
+ // Handle -nocompress
+ bool bCompress = true;
+ const char *szInFilename = NULL;
+ const char *szOutFilename = NULL;
+
+ if ( args.ArgC() == 4 && V_strcasecmp( args.Arg( 1 ), "-nocompress" ) == 0 )
+ {
+ bCompress = false;
+ szInFilename = args.Arg( 2 );
+ szOutFilename = args.Arg( 3 );
+ }
+ else if ( args.ArgC() == 3 )
+ {
+ szInFilename = args.Arg( 1 );
+ szOutFilename = args.Arg( 2 );
+ }
+
+ if ( !szInFilename || !szOutFilename || !strlen( szInFilename ) || !strlen( szOutFilename ) )
+ {
+ Msg( "Usage: bsp_repack [-nocompress] map.bsp output_map.bsp\n" );
+ return;
+ }
+
+ if ( bCompress )
+ {
+ // Use default compress flags
+ BSP_BackgroundRepack( szInFilename, szOutFilename );
+ }
+ else
+ {
+ // No compression
+ BSP_BackgroundRepack( szInFilename, szOutFilename, (IBSPPack::eRepackBSPFlags)0 );
+ }
+}
diff --git a/mp/src/game/client/bsp_utils.h b/mp/src/game/client/bsp_utils.h
new file mode 100644
index 00000000..1cdfaf50
--- /dev/null
+++ b/mp/src/game/client/bsp_utils.h
@@ -0,0 +1,21 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Exposes bsp tools to game for e.g. workshop use
+//
+// $NoKeywords: $
+//===========================================================================//
+
+#include "../utils/common/bsplib.h"
+#include "ibsppack.h"
+
+// Loads bsppack module (IBSPPack) and calls RepackBSP()
+bool BSP_SyncRepack( const char *pszInputMapFile,
+ const char *pszOutputMapFile,
+ IBSPPack::eRepackBSPFlags eRepackFlags = (IBSPPack::eRepackBSPFlags) ( IBSPPack::eRepackBSP_CompressLumps |
+ IBSPPack::eRepackBSP_CompressPackfile ) );
+
+// Helper to spawn a background thread that runs SyncRepack
+void BSP_BackgroundRepack( const char *pszInputMapFile,
+ const char *pszOutputMapFile,
+ IBSPPack::eRepackBSPFlags eRepackFlags = (IBSPPack::eRepackBSPFlags) ( IBSPPack::eRepackBSP_CompressLumps |
+ IBSPPack::eRepackBSP_CompressPackfile ) );
diff --git a/mp/src/game/client/c_ai_basenpc.cpp b/mp/src/game/client/c_ai_basenpc.cpp
index 1b1e2e65..69b675b3 100644
--- a/mp/src/game/client/c_ai_basenpc.cpp
+++ b/mp/src/game/client/c_ai_basenpc.cpp
@@ -153,9 +153,13 @@ void C_AI_BaseNPC::OnDataChanged( DataUpdateType_t type )
}
}
-void C_AI_BaseNPC::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt )
+bool C_AI_BaseNPC::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt )
{
- ForceSetupBonesAtTime( pDeltaBones0, gpGlobals->curtime - boneDt );
+ bool bRet = true;
+
+ if ( !ForceSetupBonesAtTime( pDeltaBones0, gpGlobals->curtime - boneDt ) )
+ bRet = false;
+
GetRagdollCurSequenceWithDeathPose( this, pDeltaBones1, gpGlobals->curtime, m_iDeathPose, m_iDeathFrame );
float ragdollCreateTime = PhysGetSyncCreateTime();
if ( ragdollCreateTime != gpGlobals->curtime )
@@ -164,11 +168,15 @@ void C_AI_BaseNPC::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x
// so initialize the ragdoll at that time so that it will reach the current
// position at curtime. Otherwise the ragdoll will simulate forward from curtime
// and pop into the future a bit at this point of transition
- ForceSetupBonesAtTime( pCurrentBones, ragdollCreateTime );
+ if ( !ForceSetupBonesAtTime( pCurrentBones, ragdollCreateTime ) )
+ bRet = false;
}
else
{
- SetupBones( pCurrentBones, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, gpGlobals->curtime );
+ if ( !SetupBones( pCurrentBones, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, gpGlobals->curtime ) )
+ bRet = false;
}
+
+ return bRet;
}
diff --git a/mp/src/game/client/c_ai_basenpc.h b/mp/src/game/client/c_ai_basenpc.h
index 64636c45..834be64d 100644
--- a/mp/src/game/client/c_ai_basenpc.h
+++ b/mp/src/game/client/c_ai_basenpc.h
@@ -14,7 +14,7 @@
#include "c_basecombatcharacter.h"
-// NOTE: MOved all controller code into c_basestudiomodel
+// NOTE: Moved all controller code into c_basestudiomodel
class C_AI_BaseNPC : public C_BaseCombatCharacter
{
DECLARE_CLASS( C_AI_BaseNPC, C_BaseCombatCharacter );
@@ -29,7 +29,7 @@ public:
bool ShouldAvoidObstacle( void ){ return m_bPerformAvoidance; }
virtual bool AddRagdollToFadeQueue( void ) { return m_bFadeCorpse; }
- virtual void GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt );
+ virtual bool GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt ) OVERRIDE;
int GetDeathPose( void ) { return m_iDeathPose; }
diff --git a/mp/src/game/client/c_baseanimating.cpp b/mp/src/game/client/c_baseanimating.cpp
index 75c9d7a8..78bc38be 100644
--- a/mp/src/game/client/c_baseanimating.cpp
+++ b/mp/src/game/client/c_baseanimating.cpp
@@ -79,6 +79,11 @@ const float RUN_SPEED_ESTIMATE_SQR = 150.0f * 150.0f;
static ConVar dbganimmodel( "dbganimmodel", "" );
#endif
+#if defined( STAGING_ONLY )
+ static ConVar dbg_bonestack_perturb( "dbg_bonestack_perturb", "0", 0);
+ static CInterlockedInt dbg_bonestack_reentrant_count = 0;
+#endif // STAGING_ONLY
+
mstudioevent_t *GetEventIndexForSequence( mstudioseqdesc_t &seqdesc );
C_EntityDissolve *DissolveEffect( C_BaseEntity *pTarget, float flTime );
@@ -632,7 +637,10 @@ void C_ClientRagdoll::Release( void )
}
ClientEntityList().RemoveEntity( GetClientHandle() );
- partition->Remove( PARTITION_CLIENT_SOLID_EDICTS | PARTITION_CLIENT_RESPONSIVE_EDICTS | PARTITION_CLIENT_NON_STATIC_EDICTS, CollisionProp()->GetPartitionHandle() );
+ if ( CollisionProp()->GetPartitionHandle() != PARTITION_INVALID_HANDLE )
+ {
+ partition->Remove( PARTITION_CLIENT_SOLID_EDICTS | PARTITION_CLIENT_RESPONSIVE_EDICTS | PARTITION_CLIENT_NON_STATIC_EDICTS, CollisionProp()->GetPartitionHandle() );
+ }
RemoveFromLeafSystem();
BaseClass::Release();
@@ -744,15 +752,25 @@ C_BaseAnimating::~C_BaseAnimating()
int i = g_PreviousBoneSetups.Find( this );
if ( i != -1 )
g_PreviousBoneSetups.FastRemove( i );
- RemoveFromClientSideAnimationList();
TermRopes();
+
+ Assert( !m_pRagdoll );
+
delete m_pRagdollInfo;
- Assert(!m_pRagdoll);
+ m_pRagdollInfo = NULL;
+
delete m_pIk;
+ m_pIk = NULL;
+
delete m_pBoneMergeCache;
+ m_pBoneMergeCache = NULL;
+
Studio_DestroyBoneCache( m_hitboxBoneCacheHandle );
+
delete m_pJiggleBones;
+ m_pJiggleBones = NULL;
+
InvalidateMdlCache();
// Kill off anything bone attached to us.
@@ -852,7 +870,7 @@ void C_BaseAnimating::UpdateRelevantInterpolatedVars()
{
MDLCACHE_CRITICAL_SECTION();
// Remove any interpolated vars that need to be removed.
- if ( !GetPredictable() && !IsClientCreated() && GetModelPtr() && GetModelPtr()->SequencesAvailable() )
+ if ( !IsMarkedForDeletion() && !GetPredictable() && !IsClientCreated() && GetModelPtr() && GetModelPtr()->SequencesAvailable() )
{
AddBaseAnimatingInterpolatedVars();
}
@@ -892,6 +910,17 @@ void C_BaseAnimating::RemoveBaseAnimatingInterpolatedVars()
}
}
+/*
+ From Ken: Lock() and Unlock() are render frame only, it’s just so the mdlcache
+ doesn’t toss the memory when it reshuffles the data, or at least used to. I
+ don't have any idea if mdlcache even does that anymore, but at one point it would
+ happily throw away the animation data if you ran out of memory on the
+ consoles. Jay adds: Ken is correct and the pointer should be valid until the end
+ of the frame lock (provided you are within a MDLCACHE_LOCK() block or whatever
+
+ Jay also recommends running with a forced small cache size (1MB) to put maximum
+ pressure on the cache when testing changes. Look for datacache ConVar in datacache.cpp.
+ */
void C_BaseAnimating::LockStudioHdr()
{
Assert( m_hStudioHdr == MDLHANDLE_INVALID && m_pStudioHdr == NULL );
@@ -963,6 +992,9 @@ void C_BaseAnimating::UnlockStudioHdr()
mdlcache->UnlockStudioHdr( m_hStudioHdr );
}
m_hStudioHdr = MDLHANDLE_INVALID;
+
+ delete m_pStudioHdr;
+ m_pStudioHdr = NULL;
}
}
@@ -1511,10 +1543,21 @@ void C_BaseAnimating::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quater
if (pbones[i].parent == -1)
{
ConcatTransforms( cameraTransform, bonematrix, goalMX );
- }
+ }
else
{
- ConcatTransforms( GetBone( pbones[i].parent ), bonematrix, goalMX );
+ // If the parent bone has been scaled (like with BuildBigHeadTransformations)
+ // scale it back down so the jiggly bones show up non-scaled in the correct location.
+ matrix3x4_t parentMX = GetBone( pbones[i].parent );
+
+ float fScale = Square( parentMX[0][0] ) + Square( parentMX[1][0] ) + Square( parentMX[2][0] );
+ if ( fScale > Square( 1.0001f ) )
+ {
+ fScale = 1.0f / FastSqrt( fScale );
+ MatrixScaleBy( fScale, parentMX );
+ }
+
+ ConcatTransforms( parentMX, bonematrix, goalMX );
}
// get jiggle properties from QC data
@@ -1995,10 +2038,10 @@ bool C_BaseAnimating::PutAttachment( int number, const matrix3x4_t &attachmentTo
}
-void C_BaseAnimating::SetupBones_AttachmentHelper( CStudioHdr *hdr )
+bool C_BaseAnimating::SetupBones_AttachmentHelper( CStudioHdr *hdr )
{
- if ( !hdr || !hdr->GetNumAttachments() )
- return;
+ if ( !hdr )
+ return false;
// calculate attachment points
matrix3x4_t world;
@@ -2024,6 +2067,8 @@ void C_BaseAnimating::SetupBones_AttachmentHelper( CStudioHdr *hdr )
FormatViewModelAttachment( i, world );
PutAttachment( i + 1, world );
}
+
+ return true;
}
bool C_BaseAnimating::CalcAttachments()
@@ -2214,18 +2259,36 @@ bool C_BaseAnimating::GetSoundSpatialization( SpatializationInfo_t& info )
return true;
}
-
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
bool C_BaseAnimating::IsViewModel() const
{
return false;
}
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void C_BaseAnimating::UpdateOnRemove( void )
+{
+ RemoveFromClientSideAnimationList( true );
+
+ BaseClass::UpdateOnRemove();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
bool C_BaseAnimating::IsMenuModel() const
{
return false;
}
// UNDONE: Seems kind of silly to have this when we also have the cached bones in C_BaseAnimating
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
CBoneCache *C_BaseAnimating::GetBoneCache( CStudioHdr *pStudioHdr )
{
int boneMask = BONE_USED_BY_HITBOX;
@@ -2908,10 +2971,14 @@ bool C_BaseAnimating::SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, i
if( !( oldReadableBones & BONE_USED_BY_ATTACHMENT ) && ( boneMask & BONE_USED_BY_ATTACHMENT ) )
{
- SetupBones_AttachmentHelper( hdr );
+ if ( !SetupBones_AttachmentHelper( hdr ) )
+ {
+ DevWarning( 2, "SetupBones: SetupBones_AttachmentHelper failed.\n" );
+ return false;
+ }
}
}
-
+
// Do they want to get at the bone transforms? If it's just making sure an aiment has
// its bones setup, it doesn't need the transforms yet.
if ( pBoneToWorldOut )
@@ -2922,7 +2989,7 @@ bool C_BaseAnimating::SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, i
}
else
{
- Warning( "SetupBones: invalid bone array size (%d - needs %d)\n", nMaxBones, m_CachedBoneData.Count() );
+ ExecuteNTimes( 25, Warning( "SetupBones: invalid bone array size (%d - needs %d)\n", nMaxBones, m_CachedBoneData.Count() ) );
return false;
}
}
@@ -2989,6 +3056,9 @@ struct BoneAccess
char const *tag;
};
+// the modelcache critical section is insufficient for preventing us from getting into the bone cache at the same time.
+// The bonecache itself is protected by a mutex, but the actual bone access stack needs to be protected separately.
+static CThreadFastMutex g_BoneAccessMutex;
static CUtlVector< BoneAccess > g_BoneAccessStack;
static BoneAccess g_BoneAcessBase;
@@ -3003,6 +3073,9 @@ bool C_BaseAnimating::IsBoneAccessAllowed() const
// (static function)
void C_BaseAnimating::PushAllowBoneAccess( bool bAllowForNormalModels, bool bAllowForViewModels, char const *tagPush )
{
+ AUTO_LOCK( g_BoneAccessMutex );
+ STAGING_ONLY_EXEC( ReentrancyVerifier rv( &dbg_bonestack_reentrant_count, dbg_bonestack_perturb.GetInt() ) );
+
BoneAccess save = g_BoneAcessBase;
g_BoneAccessStack.AddToTail( save );
@@ -3014,6 +3087,9 @@ void C_BaseAnimating::PushAllowBoneAccess( bool bAllowForNormalModels, bool bAll
void C_BaseAnimating::PopBoneAccess( char const *tagPop )
{
+ AUTO_LOCK( g_BoneAccessMutex );
+ STAGING_ONLY_EXEC( ReentrancyVerifier rv( &dbg_bonestack_reentrant_count, dbg_bonestack_perturb.GetInt() ) );
+
// Validate that pop matches the push
Assert( ( g_BoneAcessBase.tag == tagPop ) || ( g_BoneAcessBase.tag && g_BoneAcessBase.tag != ( char const * ) 1 && tagPop && tagPop != ( char const * ) 1 && !strcmp( g_BoneAcessBase.tag, tagPop ) ) );
int lastIndex = g_BoneAccessStack.Count() - 1;
@@ -3481,7 +3557,7 @@ void C_BaseAnimating::DoAnimationEvents( CStudioHdr *pStudioHdr )
}
// Necessary to get the next loop working
- m_flPrevEventCycle = -0.01;
+ m_flPrevEventCycle = flEventCycle - 0.001f;
}
for (int i = 0; i < (int)seqdesc.numevents; i++)
@@ -4496,7 +4572,7 @@ void C_BaseAnimating::OnPreDataChanged( DataUpdateType_t updateType )
m_bLastClientSideFrameReset = m_bClientSideFrameReset;
}
-void C_BaseAnimating::ForceSetupBonesAtTime( matrix3x4_t *pBonesOut, float flTime )
+bool C_BaseAnimating::ForceSetupBonesAtTime( matrix3x4_t *pBonesOut, float flTime )
{
// blow the cached prev bones
InvalidateBoneCache();
@@ -4505,13 +4581,18 @@ void C_BaseAnimating::ForceSetupBonesAtTime( matrix3x4_t *pBonesOut, float flTim
Interpolate( flTime );
// Setup bone state at the given time
- SetupBones( pBonesOut, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, flTime );
+ return SetupBones( pBonesOut, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, flTime );
}
-void C_BaseAnimating::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt )
+bool C_BaseAnimating::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt )
{
- ForceSetupBonesAtTime( pDeltaBones0, gpGlobals->curtime - boneDt );
- ForceSetupBonesAtTime( pDeltaBones1, gpGlobals->curtime );
+ bool bSuccess = true;
+
+ if ( !ForceSetupBonesAtTime( pDeltaBones0, gpGlobals->curtime - boneDt ) )
+ bSuccess = false;
+ if ( !ForceSetupBonesAtTime( pDeltaBones1, gpGlobals->curtime ) )
+ bSuccess = false;
+
float ragdollCreateTime = PhysGetSyncCreateTime();
if ( ragdollCreateTime != gpGlobals->curtime )
{
@@ -4519,12 +4600,15 @@ void C_BaseAnimating::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matri
// so initialize the ragdoll at that time so that it will reach the current
// position at curtime. Otherwise the ragdoll will simulate forward from curtime
// and pop into the future a bit at this point of transition
- ForceSetupBonesAtTime( pCurrentBones, ragdollCreateTime );
+ if ( !ForceSetupBonesAtTime( pCurrentBones, ragdollCreateTime ) )
+ bSuccess = false;
}
else
{
memcpy( pCurrentBones, m_CachedBoneData.Base(), sizeof( matrix3x4_t ) * m_CachedBoneData.Count() );
}
+
+ return bSuccess;
}
C_BaseAnimating *C_BaseAnimating::CreateRagdollCopy()
@@ -4592,14 +4676,32 @@ C_BaseAnimating *C_BaseAnimating::BecomeRagdollOnClient()
{
MoveToLastReceivedPosition( true );
GetAbsOrigin();
+
C_BaseAnimating *pRagdoll = CreateRagdollCopy();
+ if ( pRagdoll )
+ {
+ matrix3x4_t boneDelta0[MAXSTUDIOBONES];
+ matrix3x4_t boneDelta1[MAXSTUDIOBONES];
+ matrix3x4_t currentBones[MAXSTUDIOBONES];
+ const float boneDt = 0.1f;
+
+ bool bInitAsClient = false;
+ bool bInitBoneArrays = GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
+
+ if ( bInitBoneArrays )
+ {
+ bInitAsClient = pRagdoll->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
+ }
+
+ if ( !bInitAsClient || !bInitBoneArrays )
+ {
+ Warning( "C_BaseAnimating::BecomeRagdollOnClient failed. pRagdoll:%p bInitBoneArrays:%d bInitAsClient:%d\n",
+ pRagdoll, bInitBoneArrays, bInitAsClient );
+ pRagdoll->Release();
+ return NULL;
+ }
+ }
- matrix3x4_t boneDelta0[MAXSTUDIOBONES];
- matrix3x4_t boneDelta1[MAXSTUDIOBONES];
- matrix3x4_t currentBones[MAXSTUDIOBONES];
- const float boneDt = 0.1f;
- GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
- pRagdoll->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
return pRagdoll;
}
@@ -5512,6 +5614,13 @@ int C_BaseAnimating::SelectWeightedSequence ( int activity )
}
+int C_BaseAnimating::SelectWeightedSequenceFromModifiers( Activity activity, CUtlSymbol *pActivityModifiers, int iModifierCount )
+{
+ Assert( activity != ACT_INVALID );
+ Assert( GetModelPtr() );
+ return GetModelPtr()->SelectWeightedSequenceFromModifiers( activity, pActivityModifiers, iModifierCount );
+}
+
//=========================================================
//=========================================================
int C_BaseAnimating::LookupPoseParameter( CStudioHdr *pstudiohdr, const char *szName )
@@ -6018,7 +6127,7 @@ void C_BaseAnimating::AddToClientSideAnimationList()
UpdateRelevantInterpolatedVars();
}
-void C_BaseAnimating::RemoveFromClientSideAnimationList()
+void C_BaseAnimating::RemoveFromClientSideAnimationList( bool bBeingDestroyed /*= false*/ )
{
// Not in list yet
if ( INVALID_CLIENTSIDEANIMATION_LIST_HANDLE == m_ClientSideAnimationListHandle )
@@ -6049,7 +6158,10 @@ void C_BaseAnimating::RemoveFromClientSideAnimationList()
// Invalidate our handle no matter what.
m_ClientSideAnimationListHandle = INVALID_CLIENTSIDEANIMATION_LIST_HANDLE;
- UpdateRelevantInterpolatedVars();
+ if ( !bBeingDestroyed )
+ {
+ UpdateRelevantInterpolatedVars();
+ }
}
diff --git a/mp/src/game/client/c_baseanimating.h b/mp/src/game/client/c_baseanimating.h
index f91745ef..f1b0467c 100644
--- a/mp/src/game/client/c_baseanimating.h
+++ b/mp/src/game/client/c_baseanimating.h
@@ -247,7 +247,7 @@ public:
void ForceClientSideAnimationOn();
void AddToClientSideAnimationList();
- void RemoveFromClientSideAnimationList();
+ void RemoveFromClientSideAnimationList( bool bBeingDestroyed = false );
virtual bool IsSelfAnimating();
virtual void ResetLatched();
@@ -298,8 +298,8 @@ public:
virtual void Clear( void );
void ClearRagdoll();
void CreateUnragdollInfo( C_BaseAnimating *pRagdoll );
- void ForceSetupBonesAtTime( matrix3x4_t *pBonesOut, float flTime );
- virtual void GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt );
+ bool ForceSetupBonesAtTime( matrix3x4_t *pBonesOut, float flTime );
+ virtual bool GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt );
// For shadows rendering the correct body + sequence...
virtual int GetBody() { return m_nBody; }
@@ -429,6 +429,7 @@ public:
// For prediction
int SelectWeightedSequence ( int activity );
+ int SelectWeightedSequenceFromModifiers( Activity activity, CUtlSymbol *pActivityModifiers, int iModifierCount );
void ResetSequenceInfo( void );
float SequenceDuration( void );
float SequenceDuration( CStudioHdr *pStudioHdr, int iSequence );
@@ -444,6 +445,7 @@ public:
virtual bool ShouldResetSequenceOnNewModel( void );
virtual bool IsViewModel() const;
+ virtual void UpdateOnRemove( void );
protected:
// View models scale their attachment positions to account for FOV. To get the unmodified
@@ -605,7 +607,7 @@ private:
// Calculated attachment points
CUtlVector<CAttachmentData> m_Attachments;
- void SetupBones_AttachmentHelper( CStudioHdr *pStudioHdr );
+ bool SetupBones_AttachmentHelper( CStudioHdr *pStudioHdr );
EHANDLE m_hLightingOrigin;
EHANDLE m_hLightingOriginRelative;
@@ -758,19 +760,12 @@ inline CStudioHdr *C_BaseAnimating::GetModelPtr() const
inline void C_BaseAnimating::InvalidateMdlCache()
{
- if ( m_pStudioHdr )
- {
- UnlockStudioHdr();
- delete m_pStudioHdr;
- m_pStudioHdr = NULL;
- }
+ UnlockStudioHdr();
}
-
-inline bool C_BaseAnimating::IsModelScaleFractional() const /// very fast way to ask if the model scale is < 1.0f
+inline bool C_BaseAnimating::IsModelScaleFractional() const
{
- COMPILE_TIME_ASSERT( sizeof( m_flModelScale ) == sizeof( int ) );
- return *((const int *) &m_flModelScale) < 0x3f800000;
+ return ( m_flModelScale < 1.0f );
}
inline bool C_BaseAnimating::IsModelScaled() const
diff --git a/mp/src/game/client/c_basecombatcharacter.cpp b/mp/src/game/client/c_basecombatcharacter.cpp
index fee63118..846901a5 100644
--- a/mp/src/game/client/c_basecombatcharacter.cpp
+++ b/mp/src/game/client/c_basecombatcharacter.cpp
@@ -34,6 +34,7 @@ C_BaseCombatCharacter::C_BaseCombatCharacter()
m_pGlowEffect = NULL;
m_bGlowEnabled = false;
m_bOldGlowEnabled = false;
+ m_bClientSideGlowEnabled = false;
#endif // GLOWS_ENABLE
}
@@ -116,6 +117,22 @@ void C_BaseCombatCharacter::GetGlowEffectColor( float *r, float *g, float *b )
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
+/*
+void C_BaseCombatCharacter::EnableGlowEffect( float r, float g, float b )
+{
+ // destroy the existing effect
+ if ( m_pGlowEffect )
+ {
+ DestroyGlowEffect();
+ }
+
+ m_pGlowEffect = new CGlowObject( this, Vector( r, g, b ), 1.0, true );
+}
+*/
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
void C_BaseCombatCharacter::UpdateGlowEffect( void )
{
// destroy the existing effect
@@ -125,7 +142,7 @@ void C_BaseCombatCharacter::UpdateGlowEffect( void )
}
// create a new effect
- if ( m_bGlowEnabled )
+ if ( m_bGlowEnabled || m_bClientSideGlowEnabled )
{
float r, g, b;
GetGlowEffectColor( &r, &g, &b );
diff --git a/mp/src/game/client/c_basecombatcharacter.h b/mp/src/game/client/c_basecombatcharacter.h
index 1d84e4ce..0a135b05 100644
--- a/mp/src/game/client/c_basecombatcharacter.h
+++ b/mp/src/game/client/c_basecombatcharacter.h
@@ -97,6 +97,10 @@ public:
#ifdef GLOWS_ENABLE
CGlowObject *GetGlowObject( void ){ return m_pGlowEffect; }
virtual void GetGlowEffectColor( float *r, float *g, float *b );
+// void EnableGlowEffect( float r, float g, float b );
+
+ void SetClientSideGlowEnabled( bool bEnabled ){ m_bClientSideGlowEnabled = bEnabled; UpdateGlowEffect(); }
+ bool IsClientSideGlowEnabled( void ){ return m_bClientSideGlowEnabled; }
#endif // GLOWS_ENABLE
public:
@@ -121,7 +125,8 @@ private:
CHandle< C_BaseCombatWeapon > m_hActiveWeapon;
#ifdef GLOWS_ENABLE
- bool m_bGlowEnabled;
+ bool m_bClientSideGlowEnabled; // client-side only value used for spectator
+ bool m_bGlowEnabled; // networked value
bool m_bOldGlowEnabled;
CGlowObject *m_pGlowEffect;
#endif // GLOWS_ENABLE
diff --git a/mp/src/game/client/c_basecombatweapon.cpp b/mp/src/game/client/c_basecombatweapon.cpp
index 55d21b39..ef4c845e 100644
--- a/mp/src/game/client/c_basecombatweapon.cpp
+++ b/mp/src/game/client/c_basecombatweapon.cpp
@@ -163,7 +163,10 @@ void C_BaseCombatWeapon::OnDataChanged( DataUpdateType_t updateType )
}
}
- UpdateVisibility();
+ if ( updateType == DATA_UPDATE_CREATED )
+ {
+ UpdateVisibility();
+ }
m_iOldState = m_iState;
diff --git a/mp/src/game/client/c_baseentity.cpp b/mp/src/game/client/c_baseentity.cpp
index 25b089cd..338f986c 100644
--- a/mp/src/game/client/c_baseentity.cpp
+++ b/mp/src/game/client/c_baseentity.cpp
@@ -1150,6 +1150,13 @@ bool C_BaseEntity::InitializeAsClientEntityByIndex( int iIndex, RenderGroup_t re
return true;
}
+void C_BaseEntity::TrackAngRotation( bool bTrack )
+{
+ if ( bTrack )
+ AddVar( &m_angRotation, &m_iv_angRotation, LATCH_SIMULATION_VAR );
+ else
+ RemoveVar( &m_angRotation, false );
+}
void C_BaseEntity::Term()
{
@@ -2459,37 +2466,36 @@ void C_BaseEntity::UnlinkFromHierarchy()
void C_BaseEntity::ValidateModelIndex( void )
{
#ifdef TF_CLIENT_DLL
- if ( m_nModelIndexOverrides[VISION_MODE_NONE] > 0 )
+ if ( IsLocalPlayerUsingVisionFilterFlags( TF_VISION_FILTER_HALLOWEEN ) )
{
- if ( IsLocalPlayerUsingVisionFilterFlags( TF_VISION_FILTER_HALLOWEEN ) )
+ if ( m_nModelIndexOverrides[VISION_MODE_HALLOWEEN] > 0 )
{
- if ( m_nModelIndexOverrides[VISION_MODE_HALLOWEEN] > 0 )
- {
- SetModelByIndex( m_nModelIndexOverrides[VISION_MODE_HALLOWEEN] );
- return;
- }
+ SetModelByIndex( m_nModelIndexOverrides[VISION_MODE_HALLOWEEN] );
+ return;
}
+ }
- if ( IsLocalPlayerUsingVisionFilterFlags( TF_VISION_FILTER_PYRO ) )
+ if ( IsLocalPlayerUsingVisionFilterFlags( TF_VISION_FILTER_PYRO ) )
+ {
+ if ( m_nModelIndexOverrides[VISION_MODE_PYRO] > 0 )
{
- if ( m_nModelIndexOverrides[VISION_MODE_PYRO] > 0 )
- {
- SetModelByIndex( m_nModelIndexOverrides[VISION_MODE_PYRO] );
- return;
- }
+ SetModelByIndex( m_nModelIndexOverrides[VISION_MODE_PYRO] );
+ return;
}
+ }
- if ( IsLocalPlayerUsingVisionFilterFlags( TF_VISION_FILTER_ROME ) )
+ if ( IsLocalPlayerUsingVisionFilterFlags( TF_VISION_FILTER_ROME ) )
+ {
+ if ( m_nModelIndexOverrides[VISION_MODE_ROME] > 0 )
{
- if ( m_nModelIndexOverrides[VISION_MODE_ROME] > 0 )
- {
- SetModelByIndex( m_nModelIndexOverrides[VISION_MODE_ROME] );
- return;
- }
+ SetModelByIndex( m_nModelIndexOverrides[VISION_MODE_ROME] );
+ return;
}
+ }
+ if ( m_nModelIndexOverrides[VISION_MODE_NONE] > 0 )
+ {
SetModelByIndex( m_nModelIndexOverrides[VISION_MODE_NONE] );
-
return;
}
#endif
@@ -2621,14 +2627,6 @@ void C_BaseEntity::PostDataUpdate( DataUpdateType_t updateType )
//-----------------------------------------------------------------------------
void C_BaseEntity::OnDataUnchangedInPVS()
{
- Interp_RestoreToLastNetworked( GetVarMapping() );
-
- // For non-predicted and non-client only ents, we need to latch network values into the interpolation histories
- if ( !GetPredictable() && !IsClientCreated() )
- {
- OnLatchInterpolatedVariables( LATCH_SIMULATION_VAR );
- }
-
Assert( m_hNetworkMoveParent.Get() || !m_hNetworkMoveParent.IsValid() );
HierarchySetParent(m_hNetworkMoveParent);
@@ -6308,6 +6306,9 @@ bool C_BaseEntity::ValidateEntityAttachedToPlayer( bool &bShouldRetry )
if ( FStrEq( pszModel, "models/flag/briefcase.mdl" ) )
return true;
+ if ( FStrEq( pszModel, "models/passtime/ball/passtime_ball.mdl" ) )
+ return true;
+
if ( FStrEq( pszModel, "models/props_doomsday/australium_container.mdl" ) )
return true;
@@ -6323,6 +6324,13 @@ bool C_BaseEntity::ValidateEntityAttachedToPlayer( bool &bShouldRetry )
if ( FStrEq( pszModel, "models/props_moonbase/powersupply_flag.mdl" ) )
return true;
+
+ // The Halloween 2014 doomsday flag replacement
+ if ( FStrEq( pszModel, "models/flag/ticket_case.mdl" ) )
+ return true;
+
+ if ( FStrEq( pszModel, "models/weapons/c_models/c_grapple_proj/c_grapple_proj.mdl" ) )
+ return true;
}
// Any entity that's not an item parented to a player is invalid.
diff --git a/mp/src/game/client/c_baseentity.h b/mp/src/game/client/c_baseentity.h
index f062760d..e90d1e32 100644
--- a/mp/src/game/client/c_baseentity.h
+++ b/mp/src/game/client/c_baseentity.h
@@ -1226,7 +1226,7 @@ protected:
public:
// Accessors for above
- static int GetPredictionRandomSeed( void );
+ static int GetPredictionRandomSeed( bool bUseUnSyncedServerPlatTime = false );
static void SetPredictionRandomSeed( const CUserCmd *cmd );
static C_BasePlayer *GetPredictionPlayer( void );
static void SetPredictionPlayer( C_BasePlayer *player );
@@ -1394,6 +1394,7 @@ public:
virtual bool IsDeflectable() { return false; }
+ bool IsCombatCharacter() { return MyCombatCharacterPointer() == NULL ? false : true; }
protected:
int m_nFXComputeFrame;
@@ -1442,6 +1443,8 @@ public:
// a render handle, and is put into the spatial partition.
bool InitializeAsClientEntityByIndex( int iIndex, RenderGroup_t renderGroup );
+ void TrackAngRotation( bool bTrack );
+
private:
friend void OnRenderStart();
diff --git a/mp/src/game/client/c_baseplayer.cpp b/mp/src/game/client/c_baseplayer.cpp
index 942f7a37..a6c682d0 100644
--- a/mp/src/game/client/c_baseplayer.cpp
+++ b/mp/src/game/client/c_baseplayer.cpp
@@ -122,6 +122,9 @@ ConVar demo_fov_override( "demo_fov_override", "0", FCVAR_CLIENTDLL | FCVAR_DONT
ConVar cl_meathook_neck_pivot_ingame_up( "cl_meathook_neck_pivot_ingame_up", "7.0" );
ConVar cl_meathook_neck_pivot_ingame_fwd( "cl_meathook_neck_pivot_ingame_fwd", "3.0" );
+static ConVar cl_clean_textures_on_death( "cl_clean_textures_on_death", "0", FCVAR_DEVELOPMENTONLY, "If enabled, attempts to purge unused textures every time a freeze cam is shown" );
+
+
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 );
@@ -436,6 +439,7 @@ C_BasePlayer::C_BasePlayer() : m_iv_vecViewOffset( "C_BasePlayer::m_iv_vecViewOf
m_bFiredWeapon = false;
m_nForceVisionFilterFlags = 0;
+ m_nLocalPlayerVisionFlags = 0;
ListenForGameEvent( "base_player_teleported" );
}
@@ -541,6 +545,7 @@ CBaseEntity *C_BasePlayer::GetObserverTarget() const // returns players target o
case OBS_MODE_FIXED: // view from a fixed camera position
case OBS_MODE_IN_EYE: // follow a player in first person view
case OBS_MODE_CHASE: // follow a player in third person view
+ case OBS_MODE_POI: // PASSTIME point of interest - game objective, big fight, anything interesting
case OBS_MODE_ROAMING: // free roaming
return m_hObserverTarget;
break;
@@ -635,6 +640,7 @@ int C_BasePlayer::GetObserverMode() const
case OBS_MODE_FIXED: // view from a fixed camera position
case OBS_MODE_IN_EYE: // follow a player in first person view
case OBS_MODE_CHASE: // follow a player in third person view
+ case OBS_MODE_POI: // PASSTIME point of interest - game objective, big fight, anything interesting
case OBS_MODE_ROAMING: // free roaming
return m_iObserverMode;
break;
@@ -880,6 +886,10 @@ void C_BasePlayer::PostDataUpdate( DataUpdateType_t updateType )
// Force the sound mixer to the freezecam mixer
ConVar *pVar = (ConVar *)cvar->FindVar( "snd_soundmixer" );
pVar->SetValue( "FreezeCam_Only" );
+
+ // When we start, give unused textures an opportunity to unload
+ if ( cl_clean_textures_on_death.GetBool() )
+ g_pMaterialSystem->UncacheUnusedMaterials( false );
}
else if ( m_bWasFreezeFraming && GetObserverMode() != OBS_MODE_FREEZECAM )
{
@@ -897,6 +907,14 @@ void C_BasePlayer::PostDataUpdate( DataUpdateType_t updateType )
m_nForceVisionFilterFlags = 0;
CalculateVisionUsingCurrentFlags();
}
+
+ // force calculate vision when the local vision flags changed
+ int nCurrentLocalPlayerVisionFlags = GetLocalPlayerVisionFilterFlags();
+ if ( m_nLocalPlayerVisionFlags != nCurrentLocalPlayerVisionFlags )
+ {
+ CalculateVisionUsingCurrentFlags();
+ m_nLocalPlayerVisionFlags = nCurrentLocalPlayerVisionFlags;
+ }
}
// If we are updated while paused, allow the player origin to be snapped by the
@@ -2078,7 +2096,7 @@ void C_BasePlayer::GetToolRecordingState( KeyValues *msg )
// then this code can (should!) be removed
if ( state.m_bThirdPerson )
{
- Vector cam_ofs = g_ThirdPersonManager.GetCameraOffsetAngles();
+ const Vector& cam_ofs = g_ThirdPersonManager.GetCameraOffsetAngles();
QAngle camAngles;
camAngles[ PITCH ] = cam_ofs[ PITCH ];
@@ -2594,7 +2612,7 @@ void C_BasePlayer::NotePredictionError( const Vector &vDelta )
// 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 )
+bool C_BasePlayer::ForceSetupBonesAtTimeFakeInterpolation( matrix3x4_t *pBonesOut, float curtimeOffset )
{
// we don't have any interpolation data, so fake it
float cycle = m_flCycle;
@@ -2609,30 +2627,37 @@ void C_BasePlayer::ForceSetupBonesAtTimeFakeInterpolation( matrix3x4_t *pBonesOu
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 );
+ bool bSuccess = SetupBones( pBonesOut, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, gpGlobals->curtime + curtimeOffset );
m_flCycle = cycle;
SetLocalOrigin( origin );
+ return bSuccess;
}
-void C_BasePlayer::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt )
+bool 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 );
+ return BaseClass::GetRagdollInitBoneArrays(pDeltaBones0, pDeltaBones1, pCurrentBones, boneDt);
+
+ bool bSuccess = true;
+
+ if ( !ForceSetupBonesAtTimeFakeInterpolation( pDeltaBones0, -boneDt ) )
+ bSuccess = false;
+ if ( !ForceSetupBonesAtTimeFakeInterpolation( pDeltaBones1, 0 ) )
+ bSuccess = false;
+
float ragdollCreateTime = PhysGetSyncCreateTime();
if ( ragdollCreateTime != gpGlobals->curtime )
{
- ForceSetupBonesAtTimeFakeInterpolation( pCurrentBones, ragdollCreateTime - gpGlobals->curtime );
+ if ( !ForceSetupBonesAtTimeFakeInterpolation( pCurrentBones, ragdollCreateTime - gpGlobals->curtime ) )
+ bSuccess = false;
}
else
{
- SetupBones( pCurrentBones, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, gpGlobals->curtime );
+ if ( !SetupBones( pCurrentBones, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, gpGlobals->curtime ) )
+ bSuccess = false;
}
+ return bSuccess;
}
@@ -2838,6 +2863,7 @@ void C_BasePlayer::UpdateWearables( void )
{
pItem->ValidateModelIndex();
pItem->UpdateVisibility();
+ pItem->CreateShadow();
}
}
}
diff --git a/mp/src/game/client/c_baseplayer.h b/mp/src/game/client/c_baseplayer.h
index 9d3657bf..5e4372bc 100644
--- a/mp/src/game/client/c_baseplayer.h
+++ b/mp/src/game/client/c_baseplayer.h
@@ -169,7 +169,7 @@ public:
virtual IRagdoll* GetRepresentativeRagdoll() const;
// override the initial bone position for ragdolls
- virtual void GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt );
+ virtual bool GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt ) OVERRIDE;
// Returns eye vectors
void EyeVectors( Vector *pForward, Vector *pRight = NULL, Vector *pUp = NULL );
@@ -388,7 +388,7 @@ public:
#if defined USES_ECON_ITEMS
// Wearables
- void UpdateWearables();
+ virtual void UpdateWearables();
C_EconWearable *GetWearable( int i ) { return m_hMyWearables[i]; }
int GetNumWearables( void ) { return m_hMyWearables.Count(); }
#endif
@@ -585,7 +585,7 @@ protected:
virtual bool IsDucked( void ) const { return m_Local.m_bDucked; }
virtual bool IsDucking( void ) const { return m_Local.m_bDucking; }
virtual float GetFallVelocity( void ) { return m_Local.m_flFallVelocity; }
- void ForceSetupBonesAtTimeFakeInterpolation( matrix3x4_t *pBonesOut, float curtimeOffset );
+ bool ForceSetupBonesAtTimeFakeInterpolation( matrix3x4_t *pBonesOut, float curtimeOffset );
float m_flLaggedMovementValue;
@@ -611,6 +611,7 @@ protected:
float m_flNextAchievementAnnounceTime;
int m_nForceVisionFilterFlags; // Force our vision filter to a specific setting
+ int m_nLocalPlayerVisionFlags;
#if defined USES_ECON_ITEMS
// Wearables
diff --git a/mp/src/game/client/c_baseviewmodel.cpp b/mp/src/game/client/c_baseviewmodel.cpp
index 8ae21f63..28c804fb 100644
--- a/mp/src/game/client/c_baseviewmodel.cpp
+++ b/mp/src/game/client/c_baseviewmodel.cpp
@@ -18,6 +18,9 @@
#include "tools/bonelist.h"
#include <KeyValues.h>
#include "hltvcamera.h"
+#ifdef TF_CLIENT_DLL
+ #include "tf_weaponbase.h"
+#endif
#if defined( REPLAY_ENABLED )
#include "replay/replaycamera.h"
@@ -53,8 +56,8 @@ void FormatViewModelAttachment( Vector &vOrigin, bool bInverse )
// aspect ratio cancels out, so only need one factor
// the difference between the screen coordinates of the 2 systems is the ratio
// of the coefficients of the projection matrices (tan (fov/2) is that coefficient)
- float factorX = worldx / viewx;
-
+ // NOTE: viewx was coming in as 0 when folks set their viewmodel_fov to 0 and show their weapon.
+ float factorX = viewx ? ( worldx / viewx ) : 0.0f;
float factorY = factorX;
// Get the coordinates in the viewer's space.
@@ -331,6 +334,16 @@ int C_BaseViewModel::DrawModel( int flags )
}
}
+#ifdef TF_CLIENT_DLL
+ CTFWeaponBase* pTFWeapon = dynamic_cast<CTFWeaponBase*>( pWeapon );
+ if ( ( flags & STUDIO_RENDER ) && pTFWeapon && pTFWeapon->m_viewmodelStatTrakAddon )
+ {
+ pTFWeapon->m_viewmodelStatTrakAddon->RemoveEffects( EF_NODRAW );
+ pTFWeapon->m_viewmodelStatTrakAddon->DrawModel( flags );
+ pTFWeapon->m_viewmodelStatTrakAddon->AddEffects( EF_NODRAW );
+ }
+#endif
+
return ret;
}
diff --git a/mp/src/game/client/c_rope.cpp b/mp/src/game/client/c_rope.cpp
index 9f11fc5d..0c84778c 100644
--- a/mp/src/game/client/c_rope.cpp
+++ b/mp/src/game/client/c_rope.cpp
@@ -12,6 +12,7 @@
#include "input.h"
#ifdef TF_CLIENT_DLL
#include "cdll_util.h"
+#include "tf_gamerules.h"
#endif
#include "rope_helpers.h"
#include "engine/ivmodelinfo.h"
@@ -640,6 +641,15 @@ bool CRopeManager::IsHolidayLightMode( void )
return false;
}
+#ifdef TF_CLIENT_DLL
+ if ( TFGameRules() && TFGameRules()->IsPowerupMode() )
+ {
+ // We don't want to draw the lights for the grapple.
+ // They get left behind for a while and look bad.
+ return false;
+ }
+#endif
+
bool bDrawHolidayLights = false;
#ifdef USES_ECON_ITEMS
@@ -1638,12 +1648,12 @@ struct catmull_t
};
// bake out the terms of the catmull rom spline
-void Catmull_Rom_Spline_Matrix( const Vector &p1, const Vector &p2, const Vector &p3, const Vector &p4, catmull_t &output )
+void Catmull_Rom_Spline_Matrix( const Vector &vecP1, const Vector &vecP2, const Vector &vecP3, const Vector &vecP4, catmull_t &output )
{
- output.t3 = 0.5f * ((-1*p1) + (3*p2) + (-3*p3) + p4); // 0.5 t^3 * [ (-1*p1) + ( 3*p2) + (-3*p3) + p4 ]
- output.t2 = 0.5f * ((2*p1) + (-5*p2) + (4*p3) - p4); // 0.5 t^2 * [ ( 2*p1) + (-5*p2) + ( 4*p3) - p4 ]
- output.t = 0.5f * ((-1*p1) + p3); // 0.5 t * [ (-1*p1) + p3 ]
- output.c = p2; // p2
+ output.t3 = 0.5f * ( ( -1 * vecP1 ) + ( 3 * vecP2 ) + ( -3 * vecP3 ) + vecP4 ); // 0.5 t^3 * [ (-1*p1) + ( 3*p2) + (-3*p3) + p4 ]
+ output.t2 = 0.5f * ( ( 2 * vecP1 ) + ( -5 * vecP2 ) + ( 4 * vecP3 ) - vecP4 ); // 0.5 t^2 * [ ( 2*p1) + (-5*p2) + ( 4*p3) - p4 ]
+ output.t = 0.5f * ( ( -1 * vecP1 ) + vecP3 ); // 0.5 t * [ (-1*p1) + p3 ]
+ output.c = vecP2; // p2
}
// evaluate one point on the spline, t is a vector of (t, t^2, t^3)
diff --git a/mp/src/game/client/c_sceneentity.cpp b/mp/src/game/client/c_sceneentity.cpp
index baf2770e..abd211c0 100644
--- a/mp/src/game/client/c_sceneentity.cpp
+++ b/mp/src/game/client/c_sceneentity.cpp
@@ -219,7 +219,7 @@ void C_SceneEntity::SetupClientOnlyScene( const char *pszFilename, C_BaseFlex *p
{
LoadSceneFromFile( szFilename );
- if (!CommandLine()->FindParm("-hushasserts"))
+ if ( !HushAsserts() )
{
Assert( m_pScene );
}
@@ -257,7 +257,7 @@ void C_SceneEntity::SetupClientOnlyScene( const char *pszFilename, C_BaseFlex *p
if ( m_hOwner.Get() )
{
- if (!CommandLine()->FindParm("-hushasserts"))
+ if ( !HushAsserts() )
{
Assert( m_pScene );
}
@@ -1108,7 +1108,7 @@ void C_SceneEntity::SetCurrentTime( float t, bool forceClientSync )
//-----------------------------------------------------------------------------
void C_SceneEntity::PrefetchAnimBlocks( CChoreoScene *pScene )
{
- if (!CommandLine()->FindParm("-hushasserts"))
+ if ( !HushAsserts() )
{
Assert( pScene && m_bMultiplayer );
}
diff --git a/mp/src/game/client/c_slideshow_display.cpp b/mp/src/game/client/c_slideshow_display.cpp
index 90ee0a74..b721f4c3 100644
--- a/mp/src/game/client/c_slideshow_display.cpp
+++ b/mp/src/game/client/c_slideshow_display.cpp
@@ -272,8 +272,8 @@ void C_SlideshowDisplay::BuildSlideShowImagesList( void )
if ( bLoaded )
{
- char szKeywords[ 256 ];
- Q_strcpy( szKeywords, pMaterialKeys->GetString( "%keywords", "" ) );
+ char szKeywords[ 256 ] = {0};
+ V_strcpy_safe( szKeywords, pMaterialKeys->GetString( "%keywords", "" ) );
char *pchKeyword = szKeywords;
@@ -306,7 +306,7 @@ void C_SlideshowDisplay::BuildSlideShowImagesList( void )
{
// Couldn't find the list, so create it
iList = m_SlideMaterialLists.AddToTail( new SlideMaterialList_t );
- Q_strcpy( m_SlideMaterialLists[ iList ]->szSlideKeyword, pchKeyword );
+ V_strcpy_safe( m_SlideMaterialLists[iList]->szSlideKeyword, pchKeyword );
}
// Add material index to this list
@@ -329,7 +329,7 @@ void C_SlideshowDisplay::BuildSlideShowImagesList( void )
{
// Couldn't find the generic list, so create it
iList = m_SlideMaterialLists.AddToHead( new SlideMaterialList_t );
- Q_strcpy( m_SlideMaterialLists[ iList ]->szSlideKeyword, "" );
+ V_strcpy_safe( m_SlideMaterialLists[iList]->szSlideKeyword, "" );
}
// Add material index to this list
diff --git a/mp/src/game/client/c_soundscape.cpp b/mp/src/game/client/c_soundscape.cpp
index 3196eb94..a9baa479 100644
--- a/mp/src/game/client/c_soundscape.cpp
+++ b/mp/src/game/client/c_soundscape.cpp
@@ -150,7 +150,7 @@ public:
{
Msg( "- %d: %s\n", i, m_soundscapes[i]->GetName() );
}
- if ( m_forcedSoundscapeIndex )
+ if ( m_forcedSoundscapeIndex >= 0 )
{
Msg( "- PLAYING DEBUG SOUNDSCAPE: %d [%s]\n", m_forcedSoundscapeIndex, SoundscapeNameByIndex(m_forcedSoundscapeIndex) );
}
diff --git a/mp/src/game/client/c_team_objectiveresource.h b/mp/src/game/client/c_team_objectiveresource.h
index b7139802..9cc431e2 100644
--- a/mp/src/game/client/c_team_objectiveresource.h
+++ b/mp/src/game/client/c_team_objectiveresource.h
@@ -104,7 +104,7 @@ public:
Assert( iCapper != TEAM_UNASSIGNED );
- return GetIconForTeam( index, iCapper );;
+ return GetIconForTeam( index, iCapper );
}
// Icon for the specified team
diff --git a/mp/src/game/client/c_vote_controller.cpp b/mp/src/game/client/c_vote_controller.cpp
index c900c27e..e99372da 100644
--- a/mp/src/game/client/c_vote_controller.cpp
+++ b/mp/src/game/client/c_vote_controller.cpp
@@ -81,7 +81,7 @@ C_VoteController::~C_VoteController()
void C_VoteController::ResetData()
{
m_iActiveIssueIndex = INVALID_ISSUE;
- m_iOnlyTeamToVote = TEAM_INVALID;
+ m_iOnlyTeamToVote = TEAM_UNASSIGNED;
for( int index = 0; index < MAX_VOTE_OPTIONS; index++ )
{
m_nVoteOptionCount[index] = 0;
@@ -118,9 +118,11 @@ void C_VoteController::ClientThink()
{
if ( m_nPotentialVotes > 0 )
{
+#ifdef STAGING_ONLY
// Currently hard-coded to MAX_VOTE_COUNT options per issue
DevMsg( "Votes: Option1 - %d, Option2 - %d, Option3 - %d, Option4 - %d, Option5 - %d\n",
m_nVoteOptionCount[0], m_nVoteOptionCount[1], m_nVoteOptionCount[2], m_nVoteOptionCount[3], m_nVoteOptionCount[4] );
+#endif // STAGING_ONLY
IGameEvent *event = gameeventmanager->CreateEvent( "vote_changed" );
if ( event )
diff --git a/mp/src/game/client/cdll_bounded_cvars.cpp b/mp/src/game/client/cdll_bounded_cvars.cpp
index 0928b774..fa00db63 100644
--- a/mp/src/game/client/cdll_bounded_cvars.cpp
+++ b/mp/src/game/client/cdll_bounded_cvars.cpp
@@ -133,7 +133,7 @@ float GetClientInterpAmount()
}
else
{
- if (!CommandLine()->FindParm("-hushasserts"))
+ if ( !HushAsserts() )
{
AssertMsgOnce( false, "GetInterpolationAmount: can't get cl_updaterate cvar." );
}
diff --git a/mp/src/game/client/cdll_client_int.cpp b/mp/src/game/client/cdll_client_int.cpp
index 10cce078..5b8f10d9 100644
--- a/mp/src/game/client/cdll_client_int.cpp
+++ b/mp/src/game/client/cdll_client_int.cpp
@@ -141,6 +141,7 @@
#if defined( TF_CLIENT_DLL )
#include "econ/tool_items/custom_texture_cache.h"
+
#endif
#ifdef WORKSHOP_IMPORT_ENABLED
@@ -568,7 +569,8 @@ void DisplayBoneSetupEnts()
if ( pEnt->m_Count >= 3 )
{
printInfo.color[0] = 1;
- printInfo.color[1] = printInfo.color[2] = 0;
+ printInfo.color[1] = 0;
+ printInfo.color[2] = 0;
}
else if ( pEnt->m_Count == 2 )
{
@@ -578,7 +580,9 @@ void DisplayBoneSetupEnts()
}
else
{
- printInfo.color[0] = printInfo.color[0] = printInfo.color[0] = 1;
+ printInfo.color[0] = 1;
+ printInfo.color[1] = 1;
+ printInfo.color[2] = 1;
}
engine->Con_NXPrintf( &printInfo, "%25s / %3d / %3d", pEnt->m_ModelName, pEnt->m_Count, pEnt->m_Index );
printInfo.index++;
@@ -2561,8 +2565,8 @@ void CHLClient::ClientAdjustStartSoundParams( StartSoundParams_t& params )
// Halloween voice futzery?
else
{
- float flHeadScale = 1.f;
- CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( pEntity, flHeadScale, head_scale );
+ float flVoicePitchScale = 1.f;
+ CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( pEntity, flVoicePitchScale, voice_pitch_scale );
int iHalloweenVoiceSpell = 0;
CALL_ATTRIB_HOOK_INT_ON_OTHER( pEntity, iHalloweenVoiceSpell, halloween_voice_modulation );
@@ -2570,17 +2574,9 @@ void CHLClient::ClientAdjustStartSoundParams( StartSoundParams_t& params )
{
params.pitch *= 0.8f;
}
- else if( flHeadScale != 1.f )
+ else if( flVoicePitchScale != 1.f )
{
- // Big head, deep voice
- if( flHeadScale > 1.f )
- {
- params.pitch *= 0.8f;
- }
- else // Small head, high voice
- {
- params.pitch *= 1.3f;
- }
+ params.pitch *= flVoicePitchScale;
}
}
}
diff --git a/mp/src/game/client/client_base.vpc b/mp/src/game/client/client_base.vpc
index 309ffb8c..b1e5ae53 100644
--- a/mp/src/game/client/client_base.vpc
+++ b/mp/src/game/client/client_base.vpc
@@ -1252,7 +1252,8 @@ $Project
$Lib vtf
$ImpLib steam_api
- $Lib $LIBCOMMON/libcrypto [$POSIX]
+ $Libexternal $LIBCOMMON/libcrypto [$OSXALL]
+ $Libexternal "$SRCDIR\lib\common\$(CRYPTOPPDIR)\libcrypto" [$LINUXALL]
$ImpLib "$LIBCOMMON\curl" [$OSXALL]
@@ -1262,7 +1263,7 @@ $Project
$Libexternal libz [$LINUXALL]
$Libexternal "$LIBCOMMON/libcurl" [$LINUXALL]
$Libexternal "$LIBCOMMON/libcurlssl" [$LINUXALL]
- $Libexternal "$LIBCOMMON/libssl" [$LINUXALL]
+ $Libexternal "$SRCDIR\lib\common\$(CRYPTOPPDIR)\libssl" [$LINUXALL]
}
}
diff --git a/mp/src/game/client/clientleafsystem.cpp b/mp/src/game/client/clientleafsystem.cpp
index 0a4018f1..fa3a0097 100644
--- a/mp/src/game/client/clientleafsystem.cpp
+++ b/mp/src/game/client/clientleafsystem.cpp
@@ -189,12 +189,12 @@ private:
void RemoveShadowFromLeaves( ClientLeafShadowHandle_t handle );
// Methods associated with the various bi-directional sets
- static unsigned short& FirstRenderableInLeaf( int leaf )
+ static unsigned int& FirstRenderableInLeaf( int leaf )
{
return s_ClientLeafSystem.m_Leaf[leaf].m_FirstElement;
}
- static unsigned short& FirstLeafInRenderable( unsigned short renderable )
+ static unsigned int& FirstLeafInRenderable( unsigned short renderable )
{
return s_ClientLeafSystem.m_Renderables[renderable].m_LeafList;
}
@@ -248,8 +248,8 @@ private:
int m_RenderFrame2;
int m_EnumCount; // Have I been added to a particular shadow yet?
int m_TranslucencyCalculated;
- unsigned short m_LeafList; // What leafs is it in?
- unsigned short m_RenderLeaf; // What leaf do I render in?
+ unsigned int m_LeafList; // What leafs is it in?
+ unsigned int m_RenderLeaf; // What leaf do I render in?
unsigned char m_Flags; // rendering flags
unsigned char m_RenderGroup; // RenderGroup_t type
unsigned short m_FirstShadow; // The first shadow caster that cast on it
@@ -260,7 +260,7 @@ private:
// The leaf contains an index into a list of renderables
struct ClientLeaf_t
{
- unsigned short m_FirstElement;
+ unsigned int m_FirstElement;
unsigned short m_FirstShadow;
unsigned short m_FirstDetailProp;
@@ -302,7 +302,7 @@ private:
CUtlLinkedList< ShadowInfo_t, ClientLeafShadowHandle_t, false, unsigned int > m_Shadows;
// Maintains the list of all renderables in a particular leaf
- CBidirectionalSet< int, ClientRenderHandle_t, unsigned short, unsigned int > m_RenderablesInLeaf;
+ CBidirectionalSet< int, ClientRenderHandle_t, unsigned int, unsigned int > m_RenderablesInLeaf;
// Maintains a list of all shadows in a particular leaf
CBidirectionalSet< int, ClientLeafShadowHandle_t, unsigned short, unsigned int > m_ShadowsInLeaf;
@@ -343,7 +343,8 @@ void DefaultRenderBoundsWorldspace( IClientRenderable *pRenderable, Vector &absM
{
// Tracker 37433: This fixes a bug where if the stunstick is being wielded by a combine soldier, the fact that the stick was
// attached to the soldier's hand would move it such that it would get frustum culled near the edge of the screen.
- C_BaseEntity *pEnt = pRenderable->GetIClientUnknown()->GetBaseEntity();
+ IClientUnknown *pUnk = pRenderable->GetIClientUnknown();
+ C_BaseEntity *pEnt = pUnk->GetBaseEntity();
if ( pEnt && pEnt->IsFollowingEntity() )
{
C_BaseEntity *pParent = pEnt->GetFollowedEntity();
@@ -629,7 +630,7 @@ void CClientLeafSystem::NewRenderable( IClientRenderable* pRenderable, RenderGro
info.m_Flags = flags;
info.m_RenderGroup = (unsigned char)type;
info.m_EnumCount = 0;
- info.m_RenderLeaf = 0xFFFF;
+ info.m_RenderLeaf = m_RenderablesInLeaf.InvalidIndex();
if ( IsViewModelRenderGroup( (RenderGroup_t)info.m_RenderGroup ) )
{
AddToViewModelList( handle );
@@ -986,7 +987,7 @@ void CClientLeafSystem::AddShadowToLeaf( int leaf, ClientLeafShadowHandle_t shad
m_ShadowsInLeaf.AddElementToBucket( leaf, shadow );
// Add the shadow exactly once to all renderables in the leaf
- unsigned short i = m_RenderablesInLeaf.FirstElement( leaf );
+ unsigned int i = m_RenderablesInLeaf.FirstElement( leaf );
while ( i != m_RenderablesInLeaf.InvalidIndex() )
{
ClientRenderHandle_t renderable = m_RenderablesInLeaf.Element(i);
@@ -1092,7 +1093,54 @@ void CClientLeafSystem::AddRenderableToLeaf( int leaf, ClientRenderHandle_t rend
#ifdef VALIDATE_CLIENT_LEAF_SYSTEM
m_RenderablesInLeaf.ValidateAddElementToBucket( leaf, renderable );
#endif
- m_RenderablesInLeaf.AddElementToBucket( leaf, renderable );
+
+#ifdef DUMP_RENDERABLE_LEAFS
+ static uint32 count = 0;
+ if (count < m_RenderablesInLeaf.NumAllocated())
+ {
+ count = m_RenderablesInLeaf.NumAllocated();
+ Msg("********** frame: %d count:%u ***************\n", gpGlobals->framecount, count );
+
+ if (count >= 20000)
+ {
+ for (int j = 0; j < m_RenderablesInLeaf.NumAllocated(); j++)
+ {
+ const ClientRenderHandle_t& renderable = m_RenderablesInLeaf.Element(j);
+ RenderableInfo_t& info = m_Renderables[renderable];
+
+ char pTemp[256];
+ const char *pClassName = "<unknown renderable>";
+ C_BaseEntity *pEnt = info.m_pRenderable->GetIClientUnknown()->GetBaseEntity();
+ if ( pEnt )
+ {
+ pClassName = pEnt->GetClassname();
+ }
+ else
+ {
+ CNewParticleEffect *pEffect = dynamic_cast< CNewParticleEffect*>( info.m_pRenderable );
+ if ( pEffect )
+ {
+ Vector mins, maxs;
+ pEffect->GetRenderBounds(mins, maxs);
+ Q_snprintf( pTemp, sizeof(pTemp), "ps: %s %.2f,%.2f", pEffect->GetEffectName(), maxs.x - mins.x, maxs.y - mins.y );
+ pClassName = pTemp;
+ }
+ else if ( dynamic_cast< CParticleEffectBinding* >( info.m_pRenderable ) )
+ {
+ pClassName = "<old particle system>";
+ }
+ }
+
+ Msg(" %d: %p group:%d %s %d %d TransCalc:%d renderframe:%d\n", j, info.m_pRenderable, info.m_RenderGroup, pClassName,
+ info.m_LeafList, info.m_RenderLeaf, info.m_TranslucencyCalculated, info.m_RenderFrame);
+ }
+
+ DebuggerBreak();
+ }
+ }
+#endif // DUMP_RENDERABLE_LEAFS
+
+ m_RenderablesInLeaf.AddElementToBucket(leaf, renderable);
if ( !ShouldRenderableReceiveShadow( renderable, SHADOW_FLAGS_PROJECTED_TEXTURE_TYPE_MASK ) )
return;
@@ -1344,7 +1392,7 @@ void CClientLeafSystem::ComputeTranslucentRenderLeaf( int count, const LeafIndex
orderedList.AddToTail( LeafToMarker( leaf ) );
// iterate over all elements in this leaf
- unsigned short idx = m_RenderablesInLeaf.FirstElement(leaf);
+ unsigned int idx = m_RenderablesInLeaf.FirstElement(leaf);
while (idx != m_RenderablesInLeaf.InvalidIndex())
{
RenderableInfo_t& info = m_Renderables[m_RenderablesInLeaf.Element(idx)];
@@ -1512,7 +1560,7 @@ void CClientLeafSystem::CollateRenderablesInLeaf( int leaf, int worldListLeafInd
AddRenderableToRenderList( *info.m_pRenderList, NULL, worldListLeafIndex, RENDER_GROUP_OPAQUE_ENTITY, NULL );
// Collate everything.
- unsigned short idx = m_RenderablesInLeaf.FirstElement(leaf);
+ unsigned int idx = m_RenderablesInLeaf.FirstElement(leaf);
for ( ;idx != m_RenderablesInLeaf.InvalidIndex(); idx = m_RenderablesInLeaf.NextElement(idx) )
{
ClientRenderHandle_t handle = m_RenderablesInLeaf.Element(idx);
diff --git a/mp/src/game/client/clientmode_shared.cpp b/mp/src/game/client/clientmode_shared.cpp
index 68bc89cb..622208a4 100644
--- a/mp/src/game/client/clientmode_shared.cpp
+++ b/mp/src/game/client/clientmode_shared.cpp
@@ -85,6 +85,12 @@ extern ConVar v_viewmodel_fov;
extern ConVar voice_modenable;
extern bool IsInCommentaryMode( void );
+extern const char* GetWearLocalizationString( float flWear );
+
+CON_COMMAND( cl_reload_localization_files, "Reloads all localization files" )
+{
+ g_pVGuiLocalize->ReloadLocalizationFiles();
+}
#ifdef VOICE_VOX_ENABLE
void VoxCallback( IConVar *var, const char *oldString, float oldFloat )
@@ -141,7 +147,7 @@ CON_COMMAND( hud_reloadscheme, "Reloads hud layout and animation scripts." )
if ( !mode )
return;
- mode->ReloadScheme();
+ mode->ReloadScheme(true);
}
#ifdef _DEBUG
@@ -292,8 +298,14 @@ ClientModeShared::~ClientModeShared()
delete m_pViewport;
}
-void ClientModeShared::ReloadScheme( void )
+void ClientModeShared::ReloadScheme( bool flushLowLevel )
{
+ // Invalidate the global cache first.
+ if (flushLowLevel)
+ {
+ KeyValuesSystem()->InvalidateCache();
+ }
+
m_pViewport->ReloadScheme( "resource/ClientScheme.res" );
ClearKeyValuesCache();
}
@@ -335,7 +347,7 @@ void ClientModeShared::Init()
Assert( m_pReplayReminderPanel );
#endif
- ListenForGameEvent( "player_connect" );
+ ListenForGameEvent( "player_connect_client" );
ListenForGameEvent( "player_disconnect" );
ListenForGameEvent( "player_team" );
ListenForGameEvent( "server_cvar" );
@@ -421,7 +433,7 @@ void ClientModeShared::OverrideView( CViewSetup *pSetup )
if( ::input->CAM_IsThirdPerson() )
{
- Vector cam_ofs = g_ThirdPersonManager.GetCameraOffsetAngles();
+ const Vector& cam_ofs = g_ThirdPersonManager.GetCameraOffsetAngles();
Vector cam_ofs_distance = g_ThirdPersonManager.GetFinalCameraOffset();
cam_ofs_distance *= g_ThirdPersonManager.GetDistanceFraction();
@@ -867,7 +879,7 @@ void ClientModeShared::LevelShutdown( void )
void ClientModeShared::Enable()
{
- vgui::VPANEL pRoot = VGui_GetClientDLLRootPanel();;
+ vgui::VPANEL pRoot = VGui_GetClientDLLRootPanel();
// Add our viewport to the root panel.
if( pRoot != 0 )
@@ -894,7 +906,7 @@ void ClientModeShared::Enable()
void ClientModeShared::Disable()
{
- vgui::VPANEL pRoot = VGui_GetClientDLLRootPanel();;
+ vgui::VPANEL pRoot = VGui_GetClientDLLRootPanel();
// Remove our viewport from the root panel.
if( pRoot != 0 )
@@ -923,7 +935,7 @@ void ClientModeShared::Layout()
m_pViewport->SetBounds(0, 0, wide, tall);
if ( changed )
{
- ReloadScheme();
+ ReloadScheme(false);
}
}
}
@@ -955,7 +967,7 @@ void ClientModeShared::FireGameEvent( IGameEvent *event )
const char *eventname = event->GetName();
- if ( Q_strcmp( "player_connect", eventname ) == 0 )
+ if ( Q_strcmp( "player_connect_client", eventname ) == 0 )
{
if ( !hudChat )
return;
@@ -1115,7 +1127,7 @@ void ClientModeShared::FireGameEvent( IGameEvent *event )
{
CBasePlayer *pSpectatorTarget = UTIL_PlayerByIndex( GetSpectatorTarget() );
- if ( pSpectatorTarget && (GetSpectatorMode() == OBS_MODE_IN_EYE || GetSpectatorMode() == OBS_MODE_CHASE) )
+ if ( pSpectatorTarget && (GetSpectatorMode() == OBS_MODE_IN_EYE || GetSpectatorMode() == OBS_MODE_CHASE || GetSpectatorMode() == OBS_MODE_POI) )
{
if ( pSpectatorTarget->GetTeamNumber() == team )
{
@@ -1222,10 +1234,14 @@ void ClientModeShared::FireGameEvent( IGameEvent *event )
entityquality_t iItemQuality = event->GetInt( "quality" );
int iMethod = event->GetInt( "method" );
int iItemDef = event->GetInt( "itemdef" );
+ bool bIsStrange = event->GetInt( "isstrange" );
+ bool bIsUnusual = event->GetInt( "isunusual" );
+ float flWear = event->GetFloat( "wear" );
+
C_BasePlayer *pPlayer = UTIL_PlayerByIndex( iPlayerIndex );
const GameItemDefinition_t *pItemDefinition = dynamic_cast<GameItemDefinition_t *>( GetItemSchema()->GetItemDefinition( iItemDef ) );
- if ( !pPlayer || !pItemDefinition )
+ if ( !pPlayer || !pItemDefinition || pItemDefinition->IsHidden() )
return;
if ( g_PR )
@@ -1245,19 +1261,101 @@ void ClientModeShared::FireGameEvent( IGameEvent *event )
_snwprintf( wszItemFound, ARRAYSIZE( wszItemFound ), L"%ls", g_pVGuiLocalize->Find( pszLocString ) );
wchar_t *colorMarker = wcsstr( wszItemFound, L"::" );
+ const CEconItemRarityDefinition* pItemRarity = GetItemSchema()->GetRarityDefinition( pItemDefinition->GetRarity() );
+
if ( colorMarker )
- {
- const char *pszQualityColorString = EconQuality_GetColorString( (EEconItemQuality)iItemQuality );
- if ( pszQualityColorString )
+ {
+ if ( pItemRarity )
{
- hudChat->SetCustomColor( pszQualityColorString );
- *(colorMarker+1) = COLOR_CUSTOM;
+ attrib_colors_t colorRarity = pItemRarity->GetAttribColor();
+ vgui::HScheme scheme = vgui::scheme()->GetScheme( "ClientScheme" );
+ vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( scheme );
+ Color color = pScheme->GetColor( GetColorNameForAttribColor( colorRarity ), Color( 255, 255, 255, 255 ) );
+ hudChat->SetCustomColor( color );
}
+ else
+ {
+ const char *pszQualityColorString = EconQuality_GetColorString( (EEconItemQuality)iItemQuality );
+ if ( pszQualityColorString )
+ {
+ hudChat->SetCustomColor( pszQualityColorString );
+ }
+ }
+
+ *(colorMarker+1) = COLOR_CUSTOM;
}
// TODO: Update the localization strings to only have two format parameters since that's all we need.
wchar_t wszLocalizedString[256];
- g_pVGuiLocalize->ConstructString( wszLocalizedString, sizeof( wszLocalizedString ), wszItemFound, 3, wszPlayerName, CEconItemLocalizedFullNameGenerator( GLocalizationProvider(), pItemDefinition, iItemQuality ).GetFullName(), L"" );
+ g_pVGuiLocalize->ConstructString(
+ wszLocalizedString,
+ sizeof( wszLocalizedString ),
+ LOCCHAR( "%s1" ),
+ 1,
+ CEconItemLocalizedFullNameGenerator( GLocalizationProvider(), pItemDefinition, iItemQuality ).GetFullName()
+ );
+
+ locchar_t tempName[MAX_ITEM_NAME_LENGTH];
+ if ( pItemRarity )
+ {
+ // grade and Wear
+ loc_scpy_safe( tempName, wszLocalizedString );
+
+ const locchar_t *loc_WearText = LOCCHAR("");
+ const char *pszTooltipText = "TFUI_InvTooltip_Rarity";
+
+ if ( !IsWearableSlot( pItemDefinition->GetDefaultLoadoutSlot() ) )
+ {
+ loc_WearText = g_pVGuiLocalize->Find( GetWearLocalizationString( flWear ) );
+ }
+ else
+ {
+ pszTooltipText = "TFUI_InvTooltip_RarityNoWear";
+ }
+
+ g_pVGuiLocalize->ConstructString( wszLocalizedString,
+ ARRAYSIZE( wszLocalizedString ) * sizeof( locchar_t ),
+ g_pVGuiLocalize->Find( pszTooltipText ),
+ 3,
+ g_pVGuiLocalize->Find( pItemRarity->GetLocKey() ),
+ tempName,
+ loc_WearText
+ );
+
+ if ( bIsUnusual )
+ {
+ loc_scpy_safe( tempName, wszLocalizedString );
+
+ g_pVGuiLocalize->ConstructString( wszLocalizedString,
+ ARRAYSIZE( wszLocalizedString ) * sizeof( locchar_t ),
+ LOCCHAR( "%s1 %s2" ),
+ 2,
+ g_pVGuiLocalize->Find( "rarity4" ),
+ tempName
+ );
+ }
+
+ if ( bIsStrange )
+ {
+ loc_scpy_safe( tempName, wszLocalizedString );
+
+ g_pVGuiLocalize->ConstructString( wszLocalizedString,
+ ARRAYSIZE( wszLocalizedString ) * sizeof( locchar_t ),
+ LOCCHAR( "%s1 %s2" ),
+ 2,
+ g_pVGuiLocalize->Find( "strange" ),
+ tempName
+ );
+ }
+ }
+
+ loc_scpy_safe( tempName, wszLocalizedString );
+ g_pVGuiLocalize->ConstructString(
+ wszLocalizedString,
+ sizeof( wszLocalizedString ),
+ wszItemFound,
+ 3,
+ wszPlayerName, tempName, L"" );
char szLocalized[256];
g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalizedString, szLocalized, sizeof( szLocalized ) );
diff --git a/mp/src/game/client/clientmode_shared.h b/mp/src/game/client/clientmode_shared.h
index 27336964..beef0ad9 100644
--- a/mp/src/game/client/clientmode_shared.h
+++ b/mp/src/game/client/clientmode_shared.h
@@ -66,7 +66,7 @@ public:
virtual void Disable();
virtual void Layout();
- virtual void ReloadScheme( void );
+ virtual void ReloadScheme( bool flushLowLevel );
virtual void OverrideView( CViewSetup *pSetup );
virtual bool ShouldDrawDetailObjects( );
virtual bool ShouldDrawEntity(C_BaseEntity *pEnt);
diff --git a/mp/src/game/client/clientshadowmgr.cpp b/mp/src/game/client/clientshadowmgr.cpp
index c37e7650..bd3e2c2a 100644
--- a/mp/src/game/client/clientshadowmgr.cpp
+++ b/mp/src/game/client/clientshadowmgr.cpp
@@ -1802,6 +1802,9 @@ ClientShadowHandle_t CClientShadowMgr::CreateProjectedTexture( ClientEntityHandl
if( !( flags & SHADOW_FLAGS_FLASHLIGHT ) )
{
IClientRenderable *pRenderable = ClientEntityList().GetClientRenderableFromHandle( entity );
+ if ( !pRenderable )
+ return m_Shadows.InvalidIndex();
+
int modelType = modelinfo->GetModelType( pRenderable->GetModel() );
if (modelType == mod_brush)
{
diff --git a/mp/src/game/client/clientsideeffects.cpp b/mp/src/game/client/clientsideeffects.cpp
index b9cb5f56..c7912e3b 100644
--- a/mp/src/game/client/clientsideeffects.cpp
+++ b/mp/src/game/client/clientsideeffects.cpp
@@ -69,6 +69,15 @@ const char *CClientSideEffect::GetName( void )
}
//-----------------------------------------------------------------------------
+// Purpose: Set the name of effect
+// Input : const char
+//-----------------------------------------------------------------------------
+void CClientSideEffect::SetEffectName( const char *pszName )
+{
+ m_pszName = pszName;
+}
+
+//-----------------------------------------------------------------------------
// Purpose: Is effect still active?
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
@@ -99,6 +108,7 @@ public:
// Add an effect to the effects list
void AddEffect( CClientSideEffect *effect );
// Remove the specified effect
+ void RemoveEffect( CClientSideEffect *effect );
// Draw/update all effects in the current list
void DrawEffects( double frametime );
// Flush out all effects from the list
@@ -161,6 +171,23 @@ void CEffectsList::AddEffect( CClientSideEffect *effect )
}
//-----------------------------------------------------------------------------
+void CEffectsList::RemoveEffect( CClientSideEffect *effect )
+{
+ Assert( effect );
+ CClientSideEffect **end = &m_rgEffects[m_nEffects];
+ for( CClientSideEffect **p = &m_rgEffects[0]; p < end; ++p)
+ {
+ if ( *p == effect )
+ {
+ RemoveEffect( p - &m_rgEffects[0] ); // todo remove this crutch
+ return;
+ }
+ }
+
+ Assert( false ); // don't know this effect
+}
+
+//-----------------------------------------------------------------------------
// Purpose: Remove specified effect by index
// Input : effectIndex -
//-----------------------------------------------------------------------------
diff --git a/mp/src/game/client/clientsideeffects.h b/mp/src/game/client/clientsideeffects.h
index c5aa4fd6..fd749565 100644
--- a/mp/src/game/client/clientsideeffects.h
+++ b/mp/src/game/client/clientsideeffects.h
@@ -32,7 +32,10 @@ public:
virtual bool IsActive( void );
// Sets the effect to inactive so it can be destroed
virtual void Destroy( void );
-
+
+ // Sets the effect name (useful for debugging).
+ virtual void SetEffectName( const char *pszName );
+
private:
// Name of effect ( static data )
const char *m_pszName;
@@ -50,6 +53,8 @@ public:
// Add an effect to the list of effects
virtual void AddEffect( CClientSideEffect *effect ) = 0;
+ // Remove the specified effect
+ virtual void RemoveEffect( CClientSideEffect *effect ) = 0;
// Simulate/Update/Draw effects on list
virtual void DrawEffects( double frametime ) = 0;
// Flush out all effects fbrom the list
diff --git a/mp/src/game/client/fx_quad.cpp b/mp/src/game/client/fx_quad.cpp
index 6a254b97..12d95b7d 100644
--- a/mp/src/game/client/fx_quad.cpp
+++ b/mp/src/game/client/fx_quad.cpp
@@ -13,11 +13,21 @@
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
-CFXQuad::CFXQuad( const FXQuadData_t &data )
+static const char g_EffectName[] = "Quad";
-: CClientSideEffect( "Quad" )
+CFXQuad::CFXQuad( const FXQuadData_t &data )
+ : CClientSideEffect( g_EffectName )
{
m_FXData = data;
+
+ if ( data.m_pMaterial != NULL )
+ {
+ // If we've got a material, use that as our effectname instead of just "Quad".
+ // This should hopefully help narrow down messages like "No room for effect Quad".
+ const char *szMaterialName = data.m_pMaterial->GetName();
+ if ( szMaterialName )
+ SetEffectName( szMaterialName );
+ }
}
CFXQuad::~CFXQuad( void )
@@ -62,6 +72,12 @@ void CFXQuad::Draw( double frametime )
float alpha = m_FXData.m_flStartAlpha + ( ( m_FXData.m_flEndAlpha - m_FXData.m_flStartAlpha ) * alphaTimePerc );
alpha = clamp( alpha, 0.0f, 1.0f );
+
+ // PASSTIME don't bother if alpha is 0
+ if ( alpha == 0 )
+ {
+ return;
+ }
CMatRenderContextPtr pRenderContext( materials );
@@ -152,6 +168,8 @@ bool CFXQuad::IsActive( void )
//-----------------------------------------------------------------------------
void CFXQuad::Destroy( void )
{
+ SetEffectName( g_EffectName );
+
//Release the material
if ( m_FXData.m_pMaterial != NULL )
{
diff --git a/mp/src/game/client/fx_quad.h b/mp/src/game/client/fx_quad.h
index 77563e8b..638547e8 100644
--- a/mp/src/game/client/fx_quad.h
+++ b/mp/src/game/client/fx_quad.h
@@ -82,8 +82,6 @@ public:
virtual void Destroy( void );
virtual void Update( double frametime );
-protected:
-
FXQuadData_t m_FXData;
};
diff --git a/mp/src/game/client/fx_tracer.cpp b/mp/src/game/client/fx_tracer.cpp
index f0ca0e13..cec013a6 100644
--- a/mp/src/game/client/fx_tracer.cpp
+++ b/mp/src/game/client/fx_tracer.cpp
@@ -13,6 +13,9 @@
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
+ConVar r_drawtracers( "r_drawtracers", "1", FCVAR_CHEAT );
+ConVar r_drawtracers_firstperson( "r_drawtracers_firstperson", "1", FCVAR_ARCHIVE, "Toggle visibility of first person weapon tracers" );
+
#define TRACER_SPEED 5000
//-----------------------------------------------------------------------------
@@ -23,7 +26,7 @@ Vector GetTracerOrigin( const CEffectData &data )
Vector vecStart = data.m_vStart;
QAngle vecAngles;
- int iAttachment = data.m_nAttachmentIndex;;
+ int iAttachment = data.m_nAttachmentIndex;
// Attachment?
if ( data.m_fFlags & TRACER_FLAG_USEATTACHMENT )
@@ -77,6 +80,17 @@ void TracerCallback( const CEffectData &data )
if ( !player )
return;
+ if ( !r_drawtracers.GetBool() )
+ return;
+
+ if ( !r_drawtracers_firstperson.GetBool() )
+ {
+ C_BasePlayer *pPlayer = dynamic_cast<C_BasePlayer*>( data.GetEntity() );
+
+ if ( pPlayer && !pPlayer->ShouldDrawThisPlayer() )
+ return;
+ }
+
// Grab the data
Vector vecStart = GetTracerOrigin( data );
float flVelocity = data.m_flScale;
@@ -120,6 +134,17 @@ void ParticleTracerCallback( const CEffectData &data )
if ( !player )
return;
+ if ( !r_drawtracers.GetBool() )
+ return;
+
+ if ( !r_drawtracers_firstperson.GetBool() )
+ {
+ C_BasePlayer *pPlayer = dynamic_cast<C_BasePlayer*>( data.GetEntity() );
+
+ if ( pPlayer && !pPlayer->ShouldDrawThisPlayer() )
+ return;
+ }
+
// Grab the data
Vector vecStart = GetTracerOrigin( data );
Vector vecEnd = data.m_vOrigin;
diff --git a/mp/src/game/client/game_controls/MapOverview.cpp b/mp/src/game/client/game_controls/MapOverview.cpp
index b4262fbb..73d259ff 100644
--- a/mp/src/game/client/game_controls/MapOverview.cpp
+++ b/mp/src/game/client/game_controls/MapOverview.cpp
@@ -181,7 +181,7 @@ void CMapOverview::Init( void )
// register for events as client listener
ListenForGameEvent( "game_newmap" );
ListenForGameEvent( "round_start" );
- ListenForGameEvent( "player_connect" );
+ ListenForGameEvent( "player_connect_client" );
ListenForGameEvent( "player_info" );
ListenForGameEvent( "player_team" );
ListenForGameEvent( "player_spawn" );
@@ -933,7 +933,7 @@ void CMapOverview::FireGameEvent( IGameEvent *event )
ResetRound();
}
- else if ( Q_strcmp(type,"player_connect") == 0 )
+ else if ( Q_strcmp(type,"player_connect_client") == 0 )
{
int index = event->GetInt("index"); // = entity index - 1
diff --git a/mp/src/game/client/game_controls/SpectatorGUI.cpp b/mp/src/game/client/game_controls/SpectatorGUI.cpp
index 1c95068a..3ce30008 100644
--- a/mp/src/game/client/game_controls/SpectatorGUI.cpp
+++ b/mp/src/game/client/game_controls/SpectatorGUI.cpp
@@ -67,6 +67,7 @@ static const char *s_SpectatorModes[] =
"#Spec_Mode2", // OBS_MODE_FIXED,
"#Spec_Mode3", // OBS_MODE_IN_EYE,
"#Spec_Mode4", // OBS_MODE_CHASE,
+ "#Spec_Mode_POI", // OBS_MODE_POI, PASSTIME
"#Spec_Mode5", // OBS_MODE_ROAMING,
};
@@ -806,6 +807,8 @@ CON_COMMAND_F( spec_mode, "Set spectator mode", FCVAR_CLIENTCMD_CAN_EXECUTE )
if ( mode > LAST_PLAYER_OBSERVERMODE )
mode = OBS_MODE_IN_EYE;
+ else if ( mode == OBS_MODE_POI ) // PASSTIME skip POI mode since hltv doesn't have the entity data required to make it work
+ mode = OBS_MODE_ROAMING;
}
// handle the command clientside
diff --git a/mp/src/game/client/game_controls/basemodel_panel.cpp b/mp/src/game/client/game_controls/basemodel_panel.cpp
index e4115ea4..5f834412 100644
--- a/mp/src/game/client/game_controls/basemodel_panel.cpp
+++ b/mp/src/game/client/game_controls/basemodel_panel.cpp
@@ -22,6 +22,7 @@ CBaseModelPanel::CBaseModelPanel( vgui::Panel *pParent, const char *pName ): Bas
m_bForcePos = false;
m_bMousePressed = false;
m_bAllowRotation = false;
+ m_bAllowPitch = false;
m_bAllowFullManipulation = false;
m_bApplyManipulators = false;
m_bForcedCameraPosition = false;
@@ -43,6 +44,7 @@ void CBaseModelPanel::ApplySettings( KeyValues *inResourceData )
// Set whether we render to texture
m_bRenderToTexture = inResourceData->GetBool( "render_texture", true );
+ m_bUseParticle = inResourceData->GetBool( "use_particle", false );
// Grab and set the camera FOV.
float flFOV = GetCameraFOV();
@@ -51,6 +53,7 @@ void CBaseModelPanel::ApplySettings( KeyValues *inResourceData )
// Do we allow rotation on these panels.
m_bAllowRotation = inResourceData->GetBool( "allow_rot", false );
+ m_bAllowPitch = inResourceData->GetBool( "allow_pitch", false );
// Do we allow full manipulation on these panels.
m_bAllowFullManipulation = inResourceData->GetBool( "allow_manip", false );
@@ -64,7 +67,7 @@ void CBaseModelPanel::ApplySettings( KeyValues *inResourceData )
}
}
- SetMouseInputEnabled( m_bAllowFullManipulation || m_bAllowRotation );
+ SetMouseInputEnabled( m_bAllowFullManipulation || m_bAllowRotation || m_bAllowPitch );
}
//-----------------------------------------------------------------------------
@@ -412,13 +415,16 @@ void CBaseModelPanel::OnMousePressed ( vgui::MouseCode code )
return;
}
- if ( !m_bAllowRotation )
+ if ( !m_bAllowRotation && !m_bAllowPitch )
return;
RequestFocus();
EnableMouseCapture( true, code );
+ // Save where they clicked
+ input()->GetCursorPosition( m_nClickStartX, m_nClickStartY );
+
// Warp the mouse to the center of the screen
int width, height;
GetSize( width, height );
@@ -446,11 +452,14 @@ void CBaseModelPanel::OnMouseReleased( vgui::MouseCode code )
return;
}
- if ( !m_bAllowRotation )
+ if ( !m_bAllowRotation && !m_bAllowPitch )
return;
EnableMouseCapture( false );
m_bMousePressed = false;
+
+ // Restore the cursor to where the clicked
+ input()->SetCursorPos( m_nClickStartX, m_nClickStartY );
}
//-----------------------------------------------------------------------------
@@ -467,7 +476,7 @@ void CBaseModelPanel::OnCursorMoved( int x, int y )
return;
}
- if ( !m_bAllowRotation )
+ if ( !m_bAllowRotation && !m_bAllowPitch )
return;
if ( m_bMousePressed )
@@ -476,11 +485,25 @@ void CBaseModelPanel::OnCursorMoved( int x, int y )
int xpos, ypos;
input()->GetCursorPos( xpos, ypos );
- // Only want the x delta.
- float flDelta = xpos - m_nManipStartX;
+ if ( m_bAllowRotation )
+ {
+ // Only want the x delta.
+ float flDelta = xpos - m_nManipStartX;
+
- // Apply the delta and rotate the player.
- RotateYaw( flDelta );
+ // Apply the delta and rotate the player.
+ RotateYaw( flDelta );
+ }
+
+ if ( m_bAllowPitch )
+ {
+ // Only want the y delta.
+ float flDelta = ypos - m_nManipStartY;
+
+
+ // Apply the delta and rotate the player.
+ RotatePitch( flDelta );
+ }
}
}
@@ -503,6 +526,23 @@ void CBaseModelPanel::RotateYaw( float flDelta )
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
+void CBaseModelPanel::RotatePitch( float flDelta )
+{
+ m_angPlayer.x += flDelta;
+ if ( m_angPlayer.x > m_flMaxPitch )
+ {
+ m_angPlayer.x = m_flMaxPitch;
+ }
+ else if ( m_angPlayer.x < -m_flMaxPitch )
+ {
+ m_angPlayer.x = -m_flMaxPitch;
+ }
+
+ SetModelAnglesAndPosition( m_angPlayer, m_vecPlayerPos );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
Vector CBaseModelPanel::GetPlayerPos() const
{
return m_vecPlayerPos;
@@ -643,7 +683,7 @@ void CBaseModelPanel::LookAtBounds( const Vector &vecBoundsMin, const Vector &ve
// Clear the camera pivot and set position matrix.
ResetCameraPivot();
- if (m_bAllowRotation )
+ if (m_bAllowRotation || m_bAllowPitch )
{
vecCameraOffset.x = 0.0f;
}
@@ -651,3 +691,150 @@ void CBaseModelPanel::LookAtBounds( const Vector &vecBoundsMin, const Vector &ve
UpdateCameraTransform();
}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CBaseModelPanel::particle_data_t::~particle_data_t()
+{
+ if ( m_pParticleSystem )
+ {
+ delete m_pParticleSystem;
+ m_pParticleSystem = NULL;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Allocate particle data
+//-----------------------------------------------------------------------------
+void CBaseModelPanel::particle_data_t::UpdateControlPoints( CStudioHdr *pStudioHdr, matrix3x4_t *pWorldMatrix, const CUtlVector< int >& vecAttachments, int iDefaultBone /*= 0*/, const Vector& vecParticleOffset /*= vec3_origin*/ )
+{
+ if ( m_pParticleSystem )
+ {
+ // Update control points which is updating the position of the particles
+ matrix3x4_t matAttachToWorld;
+ Vector vecPosition, vecForward, vecRight, vecUp;
+ if ( vecAttachments.Count() )
+ {
+ for ( int i = 0; i < vecAttachments.Count(); ++i )
+ {
+ const mstudioattachment_t& attach = pStudioHdr->pAttachment( vecAttachments[i] );
+ MatrixMultiply( pWorldMatrix[ attach.localbone ], attach.local, matAttachToWorld );
+
+ MatrixVectors( matAttachToWorld, &vecForward, &vecRight, &vecUp );
+ MatrixPosition( matAttachToWorld, vecPosition );
+
+ m_pParticleSystem->SetControlPointOrientation( i, vecForward, vecRight, vecUp );
+ m_pParticleSystem->SetControlPoint( i, vecPosition + vecParticleOffset );
+ }
+ }
+ else
+ {
+ matAttachToWorld = pWorldMatrix[iDefaultBone];
+ MatrixVectors( matAttachToWorld, &vecForward, &vecRight, &vecUp );
+ MatrixPosition( matAttachToWorld, vecPosition );
+
+ m_pParticleSystem->SetControlPointOrientation( 0, vecForward, vecRight, vecUp );
+ m_pParticleSystem->SetControlPoint( 0, vecPosition + vecParticleOffset );
+ }
+ }
+
+ m_bIsUpdateToDate = true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Allocate particle data
+//-----------------------------------------------------------------------------
+CBaseModelPanel::particle_data_t *CBaseModelPanel::CreateParticleData( const char *pszParticleName )
+{
+ Assert( m_bUseParticle );
+ if ( !m_bUseParticle )
+ return NULL;
+
+ CParticleCollection *pParticle = g_pParticleSystemMgr->CreateParticleCollection( pszParticleName );
+ if ( !pParticle )
+ return NULL;
+
+ particle_data_t *pData = new particle_data_t;
+ pData->m_bIsUpdateToDate = false;
+ pData->m_pParticleSystem = pParticle;
+
+ m_particleList.AddToTail( pData );
+
+ return pData;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: remove and delete particle data
+//-----------------------------------------------------------------------------
+bool CBaseModelPanel::SafeDeleteParticleData( particle_data_t **pData )
+{
+ if ( !m_bUseParticle )
+ return false;
+
+ if ( *pData )
+ {
+ FOR_EACH_VEC( m_particleList, i )
+ {
+ if ( *pData == m_particleList[i] )
+ {
+ delete *pData;
+ *pData = NULL;
+ m_particleList.FastRemove( i );
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CBaseModelPanel::PrePaint3D( IMatRenderContext *pRenderContext )
+{
+ if ( !m_bUseParticle )
+ return;
+
+ // mark all effects need to be updated
+ FOR_EACH_VEC( m_particleList, i )
+ {
+ m_particleList[i]->m_bIsUpdateToDate = false;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CBaseModelPanel::PostPaint3D( IMatRenderContext *pRenderContext )
+{
+ if ( !m_bUseParticle )
+ return;
+
+ // This needs calling to reset various counters.
+ g_pParticleSystemMgr->SetLastSimulationTime( gpGlobals->curtime );
+
+ // Render Particles
+ pRenderContext->MatrixMode( MATERIAL_MODEL );
+ pRenderContext->PushMatrix();
+ pRenderContext->LoadIdentity( );
+
+ FOR_EACH_VEC( m_particleList, i )
+ {
+ if ( m_particleList[i]->m_bIsUpdateToDate )
+ {
+ m_particleList[i]->m_pParticleSystem->Simulate( gpGlobals->frametime, false );
+ m_particleList[i]->m_pParticleSystem->Render( pRenderContext );
+ m_particleList[i]->m_bIsUpdateToDate = false;
+ }
+ }
+
+ pRenderContext->MatrixMode( MATERIAL_MODEL );
+ pRenderContext->PopMatrix();
+}
+
diff --git a/mp/src/game/client/game_controls/basemodel_panel.h b/mp/src/game/client/game_controls/basemodel_panel.h
index b9fa0d68..a71bb7a4 100644
--- a/mp/src/game/client/game_controls/basemodel_panel.h
+++ b/mp/src/game/client/game_controls/basemodel_panel.h
@@ -182,7 +182,8 @@ public:
studiohdr_t* GetStudioHdr( void ) { return m_RootMDL.m_MDL.GetStudioHdr(); }
void SetBody( unsigned int nBody ) { m_RootMDL.m_MDL.m_nBody = nBody; }
- void RotateYaw( float flDelta );
+ void RotateYaw( float flDelta );
+ void RotatePitch( float flDelta );
Vector GetPlayerPos() const;
QAngle GetPlayerAngles() const;
@@ -213,6 +214,7 @@ protected:
bool m_bForcePos;
bool m_bMousePressed;
bool m_bAllowRotation;
+ bool m_bAllowPitch;
bool m_bAllowFullManipulation;
bool m_bApplyManipulators;
bool m_bForcedCameraPosition;
@@ -220,6 +222,25 @@ protected:
// VGUI script accessible variables.
CPanelAnimationVar( bool, m_bStartFramed, "start_framed", "0" );
CPanelAnimationVar( bool, m_bDisableManipulation, "disable_manipulation", "0" );
+ CPanelAnimationVar( bool, m_bUseParticle, "use_particle", "0" );
+ CPanelAnimationVar( float, m_flMaxPitch, "max_pitch", "90" );
+
+ struct particle_data_t
+ {
+ ~particle_data_t();
+
+ void UpdateControlPoints( CStudioHdr *pStudioHdr, matrix3x4_t *pWorldMatrix, const CUtlVector< int >& vecAttachments, int iDefaultBone = 0, const Vector& vecParticleOffset = vec3_origin );
+
+ bool m_bIsUpdateToDate;
+ CParticleCollection *m_pParticleSystem;
+ };
+ CUtlVector< particle_data_t* > m_particleList;
+
+ particle_data_t *CreateParticleData( const char *pszParticleName );
+ bool SafeDeleteParticleData( particle_data_t **pData );
+
+ virtual void PrePaint3D( IMatRenderContext *pRenderContext ) OVERRIDE;
+ virtual void PostPaint3D( IMatRenderContext *pRenderContext ) OVERRIDE;
};
#endif // BASEMODEL_PANEL_H \ No newline at end of file
diff --git a/mp/src/game/client/game_controls/baseviewport.cpp b/mp/src/game/client/game_controls/baseviewport.cpp
index f239cde8..31d8dca2 100644
--- a/mp/src/game/client/game_controls/baseviewport.cpp
+++ b/mp/src/game/client/game_controls/baseviewport.cpp
@@ -65,7 +65,17 @@ vgui::Panel *g_lastPanel = NULL; // used for mouseover buttons, keeps track of t
vgui::Button *g_lastButton = NULL; // used for mouseover buttons, keeps track of the last active button
using namespace vgui;
-ConVar hud_autoreloadscript("hud_autoreloadscript", "0", FCVAR_NONE, "Automatically reloads the animation script each time one is ran");
+void hud_autoreloadscript_callback( IConVar *var, const char *pOldValue, float flOldValue );
+
+ConVar hud_autoreloadscript("hud_autoreloadscript", "0", FCVAR_NONE, "Automatically reloads the animation script each time one is ran", hud_autoreloadscript_callback);
+
+void hud_autoreloadscript_callback( IConVar *var, const char *pOldValue, float flOldValue )
+{
+ if ( g_pClientMode && g_pClientMode->GetViewportAnimationController() )
+ {
+ g_pClientMode->GetViewportAnimationController()->SetAutoReloadScript( hud_autoreloadscript.GetBool() );
+ }
+}
static ConVar cl_leveloverviewmarker( "cl_leveloverviewmarker", "0", FCVAR_CHEAT );
@@ -573,11 +583,12 @@ void CBaseViewport::OnThink()
else
m_pActivePanel = NULL;
}
-
- m_pAnimController->UpdateAnimations( gpGlobals->curtime );
- // check the auto-reload cvar
- m_pAnimController->SetAutoReloadScript(hud_autoreloadscript.GetBool());
+ // TF does this in OnTick in TFViewport. This remains to preserve old
+ // behavior in other games
+#if !defined( TF_CLIENT_DLL )
+ m_pAnimController->UpdateAnimations( gpGlobals->curtime );
+#endif
int count = m_Panels.Count();
diff --git a/mp/src/game/client/game_controls/vguitextwindow.cpp b/mp/src/game/client/game_controls/vguitextwindow.cpp
index 3c641859..3c25eb80 100644
--- a/mp/src/game/client/game_controls/vguitextwindow.cpp
+++ b/mp/src/game/client/game_controls/vguitextwindow.cpp
@@ -138,9 +138,9 @@ void CTextWindow::Reset( void )
// HPE_BEGIN:
// [Forrest] Replace strange hard-coded default message with hard-coded error message.
//=============================================================================
- Q_strcpy( m_szTitle, "Error loading info message." );
- Q_strcpy( m_szMessage, "" );
- Q_strcpy( m_szMessageFallback, "" );
+ V_strcpy_safe( m_szTitle, "Error loading info message." );
+ V_strcpy_safe( m_szMessage, "" );
+ V_strcpy_safe( m_szMessageFallback, "" );
//=============================================================================
// HPE_END
//=============================================================================
diff --git a/mp/src/game/client/hl2/c_waterbullet.cpp b/mp/src/game/client/hl2/c_waterbullet.cpp
index b4491ca1..c758069d 100644
--- a/mp/src/game/client/hl2/c_waterbullet.cpp
+++ b/mp/src/game/client/hl2/c_waterbullet.cpp
@@ -85,7 +85,7 @@ public:
sParticle->m_flDieTime = 0.2f;
sParticle->m_flRoll = random->RandomInt( 0, 360 );
- sParticle->m_flRollDelta = random->RandomInt( -4, 4 );;
+ sParticle->m_flRollDelta = random->RandomInt( -4, 4 );
unsigned char color = random->RandomInt( 200, 255 );
diff --git a/mp/src/game/client/hl2/hud_credits.cpp b/mp/src/game/client/hl2/hud_credits.cpp
index 8021c49a..6ad1488b 100644
--- a/mp/src/game/client/hl2/hud_credits.cpp
+++ b/mp/src/game/client/hl2/hud_credits.cpp
@@ -215,8 +215,8 @@ void CHudCredits::ReadNames( KeyValues *pKeyValue )
while ( pKVNames )
{
creditname_t Credits;
- Q_strcpy( Credits.szCreditName, pKVNames->GetName());
- Q_strcpy( Credits.szFontName, pKeyValue->GetString( Credits.szCreditName, "Default" ) );
+ V_strcpy_safe( Credits.szCreditName, pKVNames->GetName() );
+ V_strcpy_safe( Credits.szFontName, pKeyValue->GetString( Credits.szCreditName, "Default" ) );
m_CreditsList.AddToTail( Credits );
pKVNames = pKVNames->GetNextKey();
diff --git a/mp/src/game/client/hltvcamera.cpp b/mp/src/game/client/hltvcamera.cpp
index 9754b99f..1da4acfd 100644
--- a/mp/src/game/client/hltvcamera.cpp
+++ b/mp/src/game/client/hltvcamera.cpp
@@ -736,7 +736,7 @@ void C_HLTVCamera::FireGameEvent( IGameEvent * event)
}
// after this only auto-director commands follow
- // don't execute them is autodirector is off and PVS is unlocked
+ // don't execute them if autodirector is off and PVS is unlocked
if ( !spec_autodirector.GetBool() && !IsPVSLocked() )
return;
diff --git a/mp/src/game/client/hud_basechat.cpp b/mp/src/game/client/hud_basechat.cpp
index 69d67862..f6b20413 100644
--- a/mp/src/game/client/hud_basechat.cpp
+++ b/mp/src/game/client/hud_basechat.cpp
@@ -24,6 +24,7 @@
#include "vgui/IInput.h"
#include "vgui/ILocalize.h"
#include "multiplay_gamerules.h"
+#include "voice_status.h"
// memdbgon must be the last include file in a .cpp file!!!
@@ -36,6 +37,7 @@ ConVar hud_saytext_time( "hud_saytext_time", "12", 0 );
ConVar cl_showtextmsg( "cl_showtextmsg", "1", 0, "Enable/disable text messages printing on the screen." );
ConVar cl_chatfilters( "cl_chatfilters", "63", FCVAR_CLIENTDLL | FCVAR_ARCHIVE, "Stores the chat filter settings " );
ConVar cl_chatfilter_version( "cl_chatfilter_version", "0", FCVAR_CLIENTDLL | FCVAR_ARCHIVE | FCVAR_HIDDEN, "Stores the chat filter version" );
+ConVar cl_mute_all_comms("cl_mute_all_comms", "1", FCVAR_ARCHIVE, "If 1, then all communications from a player will be blocked when that player is muted, including chat messages.");
const int kChatFilterVersion = 1;
@@ -1750,6 +1752,13 @@ void CBaseHudChat::ChatPrintf( int iPlayerIndex, int iFilter, const char *fmt, .
return;
}
+ // If a player is muted for voice, also mute them for text because jerks gonna jerk.
+ if ( cl_mute_all_comms.GetBool() && iPlayerIndex != 0 )
+ {
+ if ( GetClientVoiceMgr() && GetClientVoiceMgr()->IsPlayerBlocked( iPlayerIndex ) )
+ return;
+ }
+
if ( *pmsg < 32 )
{
hudlcd->AddChatLine( pmsg + 1 );
diff --git a/mp/src/game/client/hud_basedeathnotice.cpp b/mp/src/game/client/hud_basedeathnotice.cpp
index c7499ac6..36a9cc3c 100644
--- a/mp/src/game/client/hud_basedeathnotice.cpp
+++ b/mp/src/game/client/hud_basedeathnotice.cpp
@@ -115,7 +115,9 @@ void CHudBaseDeathNotice::Paint()
DeathNoticeItem &msg = m_DeathNotices[i];
CHudTexture *icon = msg.iconDeath;
- CHudTexture *iconPrekiller = msg.iconPreKiller;
+ CHudTexture *iconPostKillerName = msg.iconPostKillerName;
+ CHudTexture *iconPreKillerName = msg.iconPreKillerName;
+ CHudTexture *iconPostVictimName = msg.iconPostVictimName;
wchar_t victim[256]=L"";
wchar_t killer[256]=L"";
@@ -135,7 +137,11 @@ void CHudBaseDeathNotice::Paint()
int iconWide = 0, iconTall = 0, iDeathInfoOffset = 0, iVictimTextOffset = 0, iconActualWide = 0;
int iPreKillerTextWide = msg.wzPreKillerText[0] ? UTIL_ComputeStringWidth( m_hTextFont, msg.wzPreKillerText ) - xSpacing : 0;
- int iconPrekillerWide = 0, iconPrekillerActualWide = 0, iconPreKillerTall = 0;
+
+ int iconPrekillerWide = 0, iconPrekillerActualWide = 0, iconPrekillerTall = 0;
+ int iconPostkillerWide = 0, iconPostkillerActualWide = 0, iconPostkillerTall = 0;
+
+ int iconPostVictimWide = 0, iconPostVictimActualWide = 0, iconPostVictimTall = 0;
// Get the local position for this notice
if ( icon )
@@ -153,23 +159,53 @@ void CHudBaseDeathNotice::Paint()
iconWide *= flScale;
}
- if ( iconPrekiller )
+ if ( iconPreKillerName )
{
- iconPrekillerActualWide = iconPrekiller->EffectiveWidth( 1.0f );
+ iconPrekillerActualWide = iconPreKillerName->EffectiveWidth( 1.0f );
iconPrekillerWide = iconPrekillerActualWide;
- iconPreKillerTall = iconPrekiller->EffectiveHeight( 1.0f );
+ iconPrekillerTall = iconPreKillerName->EffectiveHeight( 1.0f );
- int iconTallDesired = iLineTall-YRES(2);
+ int iconTallDesired = iLineTall - YRES( 2 );
Assert( 0 != iconTallDesired );
- float flScale = (float) iconTallDesired / (float) iconPreKillerTall;
+ float flScale = (float)iconTallDesired / (float)iconPrekillerTall;
iconPrekillerActualWide *= flScale;
- iconPreKillerTall *= flScale;
+ iconPrekillerTall *= flScale;
iconPrekillerWide *= flScale;
}
+ if ( iconPostKillerName )
+ {
+ iconPostkillerActualWide = iconPostKillerName->EffectiveWidth( 1.0f );
+ iconPostkillerWide = iconPostkillerActualWide;
+ iconPostkillerTall = iconPostKillerName->EffectiveHeight( 1.0f );
+
+ int iconTallDesired = iLineTall-YRES(2);
+ Assert( 0 != iconTallDesired );
+ float flScale = (float) iconTallDesired / (float) iconPostkillerTall;
+
+ iconPostkillerActualWide *= flScale;
+ iconPostkillerTall *= flScale;
+ iconPostkillerWide *= flScale;
+ }
+
+ if ( iconPostVictimName )
+ {
+ iconPostVictimActualWide = iconPostVictimName->EffectiveWidth( 1.0f );
+ iconPostVictimWide = iconPostVictimActualWide;
+ iconPostVictimTall = iconPostVictimName->EffectiveHeight( 1.0f );
+
+ int iconTallDesired = iLineTall - YRES( 2 );
+ Assert( 0 != iconTallDesired );
+ float flScale = (float)iconTallDesired / (float)iconPostVictimTall;
+
+ iconPostVictimActualWide *= flScale;
+ iconPostVictimTall *= flScale;
+ iconPostVictimWide *= flScale;
+ }
+
int iTotalWide = iKillerTextWide + iconWide + iVictimTextWide + iDeathInfoTextWide + iDeathInfoEndTextWide + ( xMargin * 2 );
- iTotalWide += iconPrekillerWide + iPreKillerTextWide;
+ iTotalWide += iconPrekillerWide + iconPostkillerWide + iPreKillerTextWide + iconPostVictimWide;
int y = yStart + ( ( iLineTall + m_flLineSpacing ) * i );
int yText = y + ( ( iLineTall - iTextTall ) / 2 );
@@ -190,6 +226,14 @@ void CHudBaseDeathNotice::Paint()
x += xMargin;
+ // prekiller icon
+ if ( iconPreKillerName )
+ {
+ int yPreIconTall = y + ( ( iLineTall - iconPrekillerTall ) / 2 );
+ iconPreKillerName->DrawSelf( x, yPreIconTall, iconPrekillerActualWide, iconPrekillerTall, m_clrIcon);
+ x += iconPrekillerWide + xSpacing;
+ }
+
if ( killer[0] )
{
// Draw killer's name
@@ -205,12 +249,12 @@ void CHudBaseDeathNotice::Paint()
x += iPreKillerTextWide;
}
- // Prekiller icon
- if ( iconPrekiller )
+ // postkiller icon
+ if ( iconPostKillerName )
{
- int yPreIconTall = y + ( ( iLineTall - iconPreKillerTall ) / 2 );
- iconPrekiller->DrawSelf( x, yPreIconTall, iconPrekillerActualWide, iconPreKillerTall, m_clrIcon );
- x += iconPrekillerWide + xSpacing;
+ int yPreIconTall = y + ( ( iLineTall - iconPostkillerTall ) / 2 );
+ iconPostKillerName->DrawSelf( x, yPreIconTall, iconPostkillerActualWide, iconPostkillerTall, m_clrIcon );
+ x += iconPostkillerWide + xSpacing;
}
// Draw glow behind weapon icon to show it was a crit death
@@ -243,6 +287,14 @@ void CHudBaseDeathNotice::Paint()
DrawText( x + iVictimTextOffset, yText, m_hTextFont, GetTeamColor( msg.Victim.iTeam, msg.bLocalPlayerInvolved ), victim );
x += iVictimTextWide;
+ // postkiller icon
+ if ( iconPostVictimName )
+ {
+ int yPreIconTall = y + ( ( iLineTall - iconPostVictimTall ) / 2 );
+ iconPostVictimName->DrawSelf( x, yPreIconTall, iconPostVictimActualWide, iconPostVictimTall, m_clrIcon );
+ x += iconPostkillerWide + xSpacing;
+ }
+
// Draw Additional Text on the end of the victims name
if ( msg.wzInfoTextEnd[0] )
{
@@ -569,16 +621,27 @@ void CHudBaseDeathNotice::FireGameEvent( IGameEvent *event )
}
}
+ bool bIsHalloween2014 = TFGameRules() && TFGameRules()->IsHalloweenScenario( CTFGameRules::HALLOWEEN_SCENARIO_DOOMSDAY );
+
switch ( iEventType )
{
case TF_FLAGEVENT_PICKUP:
- pszMsgKey = "#Msg_PickedUpFlag";
+ pszMsgKey = bIsHalloween2014 ? "#Msg_PickedUpFlagHalloween2014" : "#Msg_PickedUpFlag";
break;
case TF_FLAGEVENT_CAPTURE:
- pszMsgKey = "#Msg_CapturedFlag";
+ pszMsgKey = bIsHalloween2014 ? "#Msg_CapturedFlagHalloween2014" : "#Msg_CapturedFlag";
break;
case TF_FLAGEVENT_DEFEND:
- pszMsgKey = bIsMvM ? "#Msg_DefendedBomb" : "#Msg_DefendedFlag";
+ if ( bIsMvM )
+ {
+ pszMsgKey = "#Msg_DefendedBomb";
+ }
+ else
+ {
+ pszMsgKey = bIsHalloween2014 ? "#Msg_DefendedFlagHalloween2014" : "#Msg_DefendedFlag";
+ }
+
+
break;
// Add this when we can get localization for it
diff --git a/mp/src/game/client/hud_basedeathnotice.h b/mp/src/game/client/hud_basedeathnotice.h
index 2a9da0c5..b4f34eb8 100644
--- a/mp/src/game/client/hud_basedeathnotice.h
+++ b/mp/src/game/client/hud_basedeathnotice.h
@@ -42,8 +42,10 @@ struct DeathNoticeItem
iKillerID = -1;
iVictimID = -1;
- iconPreKiller = NULL;
+ iconPreKillerName = NULL;
+ iconPostKillerName = NULL;
wzPreKillerText[0] = 0;
+ iconPostVictimName = NULL;
}
float GetExpiryTime();
@@ -56,9 +58,13 @@ struct DeathNoticeItem
CHudTexture *iconDeath;
CHudTexture *iconCritDeath; // crit background icon
- CHudTexture *iconPreKiller;
+ CHudTexture *iconPreKillerName;
+
+ CHudTexture *iconPostKillerName;
wchar_t wzPreKillerText[32];
+ CHudTexture *iconPostVictimName;
+
bool bSelfInflicted;
bool bLocalPlayerInvolved;
bool bCrit;
diff --git a/mp/src/game/client/hud_controlpointicons.cpp b/mp/src/game/client/hud_controlpointicons.cpp
index cc446c83..2c0628e3 100644
--- a/mp/src/game/client/hud_controlpointicons.cpp
+++ b/mp/src/game/client/hud_controlpointicons.cpp
@@ -1402,7 +1402,7 @@ void CControlPointProgressBar::PerformLayout( void )
{
BaseClass::PerformLayout();
- if ( m_pAttachedToIcon && m_pTeardrop && m_pTeardropSide )
+ if ( m_pAttachedToIcon && m_pTeardrop && m_pTeardropSide && m_pAttachedToIcon->GetVPanel() )
{
int iIconX, iIconY;
ipanel()->GetAbsPos(m_pAttachedToIcon->GetVPanel(), iIconX, iIconY );
diff --git a/mp/src/game/client/hud_vote.cpp b/mp/src/game/client/hud_vote.cpp
index 64d3e76e..319255dd 100644
--- a/mp/src/game/client/hud_vote.cpp
+++ b/mp/src/game/client/hud_vote.cpp
@@ -59,7 +59,7 @@ public:
{
g_pVGuiLocalize->ConvertANSIToUnicode( pPlayerName, m_wszPlayerName, sizeof(m_wszPlayerName) );
SetLifetime( 7 );
- SetText( "#Vote_notification_text" );
+ SetText( "#GameUI_Vote_Notification_Text" );
AddStringToken( "initiator", m_wszPlayerName );
}
virtual bool CanBeTriggered()
@@ -68,7 +68,10 @@ public:
}
virtual void Trigger()
{
- CTFGenericConfirmDialog *pDialog = ShowConfirmDialog( "#Vote_notification_title", "#Vote_notification_text", "#Vote_notification_view", "#cancel", &ConfirmShowVoteSetup );
+ CTFGenericConfirmDialog *pDialog = ShowConfirmDialog( "#GameUI_Vote_Notification_Title",
+ "#GameUI_Vote_Notification_Text",
+ "#GameUI_Vote_Notification_View",
+ "#cancel", &ConfirmShowVoteSetup );
pDialog->SetContext( this );
pDialog->AddStringToken( "initiator", m_wszPlayerName );
// so we aren't deleted
@@ -95,7 +98,7 @@ public:
CHudVote *pHudVote = GET_HUDELEMENT( CHudVote );
if ( pHudVote )
{
- pHudVote->ShowVoteUI();
+ pHudVote->ShowVoteUI( true );
}
}
pNotification->SetIsInUse( false );
@@ -291,6 +294,76 @@ void CVoteSetupDialog::ApplySettings(KeyValues *inResourceData)
}
//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CVoteSetupDialog::InitializeIssueList( void )
+{
+ m_pComboBox->RemoveAll();
+ m_pComboBox->SetVisible( false );
+ SetDialogVariable( "combo_label", "" );
+
+ for ( int index = 0; index < m_VoteIssues.Count(); index++ )
+ {
+ if ( !m_VoteIssues[index].szName || !m_VoteIssues[index].szName[0] )
+ continue;
+
+ bool bActive = m_VoteIssues[index].bIsActive;
+
+ char szIssueLocalized[k_MAX_VOTE_NAME_LENGTH] = { 0 };
+ g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find( m_VoteIssues[index].szNameString ), szIssueLocalized, sizeof( szIssueLocalized ) );
+
+ if ( !bActive )
+ {
+ char szDisabled[k_MAX_VOTE_NAME_LENGTH] = { 0 };
+ g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find( "#GameUI_Vote_Disabled" ), szDisabled, sizeof( szDisabled ) );
+ V_strcat_safe( szIssueLocalized, szDisabled );
+ }
+
+ KeyValues *pKeyValues = new KeyValues( "Issue" );
+ pKeyValues->SetString( "Issue", szIssueLocalized );
+ pKeyValues->SetString( "IssueRaw", m_VoteIssues[index].szName );
+ pKeyValues->SetBool( "Active", m_VoteIssues[index].bIsActive );
+ int iId = m_pVoteSetupList->AddItem( 0, pKeyValues );
+ pKeyValues->deleteThis();
+
+ // Setup the list entry style
+ if ( m_hIssueFont != INVALID_FONT )
+ {
+ m_pVoteSetupList->SetItemFont( iId, m_hIssueFont );
+ Color colFG = bActive ? m_IssueFGColor : m_IssueFGColorDisabled;
+ m_pVoteSetupList->SetItemFgColor( iId, colFG );
+ }
+ }
+
+ // Select the first item by default
+ if ( m_pVoteSetupList->GetItemCount() > 0 )
+ {
+ m_pVoteSetupList->SetSelectedItem( 0 );
+ }
+ else
+ {
+ // No active issues
+ char szIssueLocalized[k_MAX_VOTE_NAME_LENGTH] = { 0 };
+ g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find( "#GameUI_Vote_System_Disabled" ), szIssueLocalized, sizeof( szIssueLocalized ) );
+
+ KeyValues *pKeyValues = new KeyValues( "Issue" );
+ pKeyValues->SetString( "Issue", szIssueLocalized );
+ pKeyValues->SetString( "IssueRaw", "Disabled" );
+ pKeyValues->SetBool( "Active", false );
+ int iId = m_pVoteSetupList->AddItem( 0, pKeyValues );
+ pKeyValues->deleteThis();
+
+ if ( m_hIssueFont != INVALID_FONT )
+ {
+ m_pVoteSetupList->SetItemFont( iId, m_hIssueFont );
+ m_pVoteSetupList->SetItemFgColor( iId, m_IssueFGColor );
+ }
+ }
+
+ UpdateCurrentMap();
+}
+
+//-----------------------------------------------------------------------------
// Purpose: Keep track of the current map
//-----------------------------------------------------------------------------
void CVoteSetupDialog::UpdateCurrentMap( void )
@@ -302,7 +375,7 @@ void CVoteSetupDialog::UpdateCurrentMap( void )
//-----------------------------------------------------------------------------
// Purpose: Feeds Issues from the server to this Dialog
//-----------------------------------------------------------------------------
-void CVoteSetupDialog::AddVoteIssues( CUtlStringList &m_VoteSetupIssues )
+void CVoteSetupDialog::AddVoteIssues( CUtlVector< VoteIssue_t > &m_VoteSetupIssues )
{
m_VoteIssues.RemoveAll();
for ( int index = 0; index < m_VoteSetupIssues.Count(); index++ )
@@ -385,36 +458,7 @@ void CVoteSetupDialog::Activate()
m_pVoteParameterList->SetSectionFgColor( 1, m_HeaderFGColor );
}
- // Populate the Issue list
- for ( int index = 0; index < m_VoteIssues.Count(); index++ )
- {
- const char *pszIssue = m_VoteIssues[index];
- if ( !pszIssue || !pszIssue[0] )
- continue;
-
- KeyValues *pKeyValues = new KeyValues( "Issue" );
- pKeyValues->SetString( "Issue", pszIssue );
- int iId = m_pVoteSetupList->AddItem( 0, pKeyValues );
- pKeyValues->deleteThis();
-
- // Setup the list entry style
- if ( m_hIssueFont != INVALID_FONT )
- {
- m_pVoteSetupList->SetItemFont( iId, m_hIssueFont );
-
- bool bDisabled = V_stristr( pszIssue, "(Disabled on Server)" ); // driller: need to localize
- Color colFG = bDisabled ? m_IssueFGColorDisabled : m_IssueFGColor;
- m_pVoteSetupList->SetItemFgColor( iId, colFG );
- }
- }
-
- // Select the first item by default
- if ( m_pVoteSetupList->GetItemCount() > 0 )
- {
- m_pVoteSetupList->SetSelectedItem( 0 );
- }
-
- UpdateCurrentMap();
+ InitializeIssueList();
}
//-----------------------------------------------------------------------------
@@ -432,15 +476,15 @@ void CVoteSetupDialog::OnClose()
void CVoteSetupDialog::OnCommand(const char *command)
{
// We should have enough data to issue a CallVote command
- if ( V_stricmp( command, "CallVote" ) == 0 )
+ if ( !V_stricmp( command, "CallVote" ) )
{
int iSelectedItem = m_pVoteSetupList->GetSelectedItem();
if ( iSelectedItem >= 0 )
{
- char szVoteCommand[128];
+ char szVoteCommand[k_MAX_VOTE_NAME_LENGTH];
KeyValues *pIssueKeyValues = m_pVoteSetupList->GetItemData( iSelectedItem );
- const char *szIssue = pIssueKeyValues->GetString( "Issue" );
- if ( V_stricmp( "changelevel", szIssue ) == 0 || V_stricmp( "nextlevel", szIssue ) == 0 )
+ const char *szIssueRaw = pIssueKeyValues->GetString( "IssueRaw" );
+ if ( !V_stricmp( "ChangeLevel", szIssueRaw ) || !V_stricmp( "NextLevel", szIssueRaw ) )
{
int nSelectedParam = m_pVoteParameterList->GetSelectedItem();
if ( nSelectedParam >= 0 )
@@ -454,13 +498,13 @@ void CVoteSetupDialog::OnCommand(const char *command)
{
// Which Map?
const char *szMapName = pParameterKeyValues->GetString( "Name" );
- Q_snprintf( szVoteCommand, sizeof( szVoteCommand ), "callvote %s %s\n;", szIssue, szMapName );
+ Q_snprintf( szVoteCommand, sizeof( szVoteCommand ), "callvote %s %s\n;", szIssueRaw, szMapName );
engine->ClientCmd( szVoteCommand );
}
}
}
}
- else if ( V_stricmp( "kick", szIssue ) == 0 )
+ else if ( !V_stricmp( "Kick", szIssueRaw ) )
{
// Get selected Player
int iSelectedParam = m_pVoteParameterList->GetSelectedItem();
@@ -476,7 +520,7 @@ void CVoteSetupDialog::OnCommand(const char *command)
if ( engine->GetPlayerInfo( playerIndex, &playerInfo ) )
{
CBasePlayer *pPlayer = UTIL_PlayerByIndex( playerIndex );
- Q_snprintf( szVoteCommand, sizeof( szVoteCommand ), "callvote %s \"%d %s\"\n;", szIssue, pPlayer->GetUserID(), pReasonString );
+ Q_snprintf( szVoteCommand, sizeof( szVoteCommand ), "callvote %s \"%d %s\"\n;", szIssueRaw, pPlayer->GetUserID(), pReasonString );
engine->ClientCmd( szVoteCommand );
#ifdef TF_CLIENT_DLL
CSteamID steamID;
@@ -495,7 +539,7 @@ void CVoteSetupDialog::OnCommand(const char *command)
}
}
#ifdef TF_CLIENT_DLL
- else if ( V_stricmp( "ChangeMission", szIssue ) == 0 )
+ else if ( !V_stricmp( "ChangeMission", szIssueRaw ) )
{
int nSelectedParam = m_pVoteParameterList->GetSelectedItem();
if ( nSelectedParam >= 0 )
@@ -509,7 +553,7 @@ void CVoteSetupDialog::OnCommand(const char *command)
{
// Which Pop File?
const char *szPopFile = pParameterKeyValues->GetString( "Name" );
- Q_snprintf( szVoteCommand, sizeof( szVoteCommand ), "callvote %s %s\n;", szIssue, szPopFile );
+ Q_snprintf( szVoteCommand, sizeof( szVoteCommand ), "callvote %s %s\n;", szIssueRaw, szPopFile );
engine->ClientCmd( szVoteCommand );
}
}
@@ -519,7 +563,7 @@ void CVoteSetupDialog::OnCommand(const char *command)
else
{
// Non-parameter vote. i.e. callvote scrambleteams
- Q_snprintf( szVoteCommand, sizeof(szVoteCommand), "callvote %s\n;", szIssue );
+ Q_snprintf( szVoteCommand, sizeof(szVoteCommand), "callvote %s\n;", szIssueRaw );
engine->ClientCmd( szVoteCommand );
}
@@ -551,22 +595,23 @@ void CVoteSetupDialog::OnItemSelected( vgui::Panel *panel )
if ( !pIssueKeyValues )
return;
+ CHudVote *pHudVote = GET_HUDELEMENT( CHudVote );
+ if ( !pHudVote )
+ return;
+
// We're rebuilding, so clear state
m_bVoteButtonEnabled = false;
m_pVoteParameterList->ClearSelection();
m_pVoteParameterList->RemoveAll();
- const char *szName = pIssueKeyValues->GetString( "Issue" );
- if ( V_stricmp( "Voting disabled on this Server", szName ) == 0 )
- {
- m_bVoteButtonEnabled = false;
- }
- else if ( V_stristr( szName, "(Disabled on Server)" ) ) // driller: need to localize
+ const char *pszIssueRaw = pIssueKeyValues->GetString( "IssueRaw" );
+ bool bActive = pIssueKeyValues->GetBool( "Active" );
+ if ( !pHudVote->IsVoteSystemActive() || !bActive )
{
m_bVoteButtonEnabled = false;
}
// CHANGELEVEL / NEXTLEVEL
- else if ( V_stricmp( "changelevel", szName ) == 0 || V_stricmp( "nextlevel", szName ) == 0 )
+ else if ( !V_stricmp( "ChangeLevel", pszIssueRaw ) || !V_stricmp( "NextLevel", pszIssueRaw ) )
{
// Feed the mapcycle to the parameters list
for ( int index = 0; index < m_VoteIssuesMapCycle.Count(); index++ )
@@ -598,7 +643,7 @@ void CVoteSetupDialog::OnItemSelected( vgui::Panel *panel )
}
}
// KICK
- else if ( V_stricmp( "kick", szName ) == 0 )
+ else if ( !V_stricmp( "Kick", pszIssueRaw ) )
{
// Feed the player list to the parameters list
int nMaxClients = engine->GetMaxClients();
@@ -656,7 +701,7 @@ void CVoteSetupDialog::OnItemSelected( vgui::Panel *panel )
}
#ifdef TF_CLIENT_DLL
// CHANGE POP FILE
- else if ( V_stricmp( "ChangeMission", szName ) == 0 )
+ else if ( !V_stricmp( "ChangeMission", pszIssueRaw ) )
{
// Feed the popfiles to the parameters list
for ( int index = 0; index < m_VoteIssuesPopFiles.Count(); index++ )
@@ -742,8 +787,8 @@ void CVoteSetupDialog::RefreshIssueParameters()
if ( iSelectedItem >= 0 )
{
KeyValues *pIssueKeyValues = m_pVoteSetupList->GetItemData( iSelectedItem );
- const char *szName = pIssueKeyValues->GetString( "Issue" );
- if ( V_stricmp( "kick", szName ) == 0 )
+ const char *pszIssueRaw = pIssueKeyValues->GetString( "IssueRaw" );
+ if ( !V_stricmp( "Kick", pszIssueRaw ) )
{
if ( m_pVoteParameterList->GetItemCount() > 0 )
{
@@ -786,10 +831,10 @@ void CVoteSetupDialog::RefreshIssueParameters()
m_pVoteParameterList->InvalidateItem( index );
}
-
- m_pVoteParameterList->SetImageList( m_pImageList, false );
}
}
+
+ m_pVoteParameterList->SetImageList( m_pImageList, false );
}
}
@@ -799,9 +844,9 @@ void CVoteSetupDialog::RefreshIssueParameters()
void CVoteSetupDialog::ResetData()
{
m_bVoteButtonEnabled = false;
- m_pVoteSetupList->DeleteAllItems();
- m_pVoteParameterList->DeleteAllItems();
- m_pComboBox->DeleteAllItems();
+ m_pVoteSetupList->RemoveAll();
+ m_pVoteParameterList->RemoveAll();
+ m_pComboBox->RemoveAll();
}
//-----------------------------------------------------------------------------
@@ -863,7 +908,7 @@ void CHudVote::Init( void )
ListenForGameEvent( "vote_options" );
ListenForGameEvent( "vote_cast" );
- SetVoteActive( false );
+ m_bVotingActive = false;
m_flVoteResultCycleTime = -1;
m_flHideTime = -1;
m_bIsYesNoVote = true;
@@ -871,6 +916,8 @@ void CHudVote::Init( void )
m_nVoteChoicesCount = 2; // Yes/No is the default
m_bShowVoteActivePanel = false;
m_iVoteCallerIdx = -1;
+ m_bVoteSystemActive = false;
+ m_nVoteTeamIndex = 0;
HOOK_HUD_MESSAGE( CHudVote, CallVoteFailed );
HOOK_HUD_MESSAGE( CHudVote, VoteStart );
@@ -884,7 +931,7 @@ void CHudVote::Init( void )
//-----------------------------------------------------------------------------
void CHudVote::LevelInit( void )
{
- SetVoteActive( false );
+ m_bVotingActive = false;
m_flVoteResultCycleTime = -1;
m_flHideTime = -1;
m_flPostVotedHideTime = -1;
@@ -901,7 +948,7 @@ int CHudVote::KeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBin
if ( !down )
return 1;
- if ( !m_bVoteActive )
+ if ( !m_bVotingActive )
return 1;
if ( m_bPlayerVoted )
@@ -979,21 +1026,19 @@ void CHudVote::MsgFunc_CallVoteFailed( bf_read &msg )
m_pCallVoteFailed->SetVisible( true );
m_pVoteSetupDialog->SetVisible( false );
- m_flHideTime = gpGlobals->curtime + 4.0;
+ m_flHideTime = gpGlobals->curtime + 4.f;
- char szTime[256];
- wchar_t wszTime[256];
+ char szTime[k_MAX_VOTE_NAME_LENGTH];
+ wchar_t wszTime[k_MAX_VOTE_NAME_LENGTH];
bool bMinutes = ( nTime > 65 );
if ( bMinutes )
{
nTime /= 60;
}
- const char *pszTimeString = ( bMinutes ) ? ( ( nTime < 2 ) ? "#GameUI_vote_failed_recently_min" : "#GameUI_vote_failed_recently_mins" ) : "#GameUI_vote_failed_recently";
Q_snprintf( szTime, sizeof ( szTime), "%i", nTime );
g_pVGuiLocalize->ConvertANSIToUnicode( szTime, wszTime, sizeof( wszTime ) );
- wchar_t wszHeaderString[512];
- wchar_t *pwszHeaderString;
+ wchar_t wszHeaderString[k_MAX_VOTE_NAME_LENGTH];
switch( nReason )
{
@@ -1006,10 +1051,12 @@ void CHudVote::MsgFunc_CallVoteFailed( bf_read &msg )
break;
case VOTE_FAILED_RATE_EXCEEDED:
- g_pVGuiLocalize->ConstructString( wszHeaderString, sizeof(wszHeaderString), g_pVGuiLocalize->Find( "#GameUI_vote_failed_vote_spam" ), 1, wszTime );
- pwszHeaderString = wszHeaderString;
- m_pCallVoteFailed->SetDialogVariable( "FailedReason", pwszHeaderString );
+ {
+ const char *pszTimeString = ( bMinutes ) ? ( ( nTime < 2 ) ? "#GameUI_vote_failed_vote_spam_min" : "#GameUI_vote_failed_vote_spam_mins" ) : "#GameUI_vote_failed_vote_spam";
+ g_pVGuiLocalize->ConstructString( wszHeaderString, sizeof( wszHeaderString ), g_pVGuiLocalize->Find( pszTimeString ), 1, wszTime );
+ m_pCallVoteFailed->SetDialogVariable( "FailedReason", wszHeaderString );
break;
+ }
case VOTE_FAILED_ISSUE_DISABLED:
m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_disabled_issue" );
@@ -1028,10 +1075,12 @@ void CHudVote::MsgFunc_CallVoteFailed( bf_read &msg )
break;
case VOTE_FAILED_ON_COOLDOWN:
+ {
+ const char *pszTimeString = ( bMinutes ) ? ( ( nTime < 2 ) ? "#GameUI_vote_failed_recently_min" : "#GameUI_vote_failed_recently_mins" ) : "#GameUI_vote_failed_recently";
g_pVGuiLocalize->ConstructString( wszHeaderString, sizeof( wszHeaderString ), g_pVGuiLocalize->Find( pszTimeString ), 1, wszTime );
- pwszHeaderString = wszHeaderString;
- m_pCallVoteFailed->SetDialogVariable( "FailedReason", pwszHeaderString );
+ m_pCallVoteFailed->SetDialogVariable( "FailedReason", wszHeaderString );
break;
+ }
case VOTE_FAILED_TEAM_CANT_CALL:
m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_team_cant_call" );
@@ -1058,10 +1107,12 @@ void CHudVote::MsgFunc_CallVoteFailed( bf_read &msg )
break;
case VOTE_FAILED_CANNOT_KICK_FOR_TIME:
- g_pVGuiLocalize->ConstructString( wszHeaderString, sizeof(wszHeaderString), g_pVGuiLocalize->Find( "#GameUI_vote_failed_cannot_kick_for_time" ), 1, wszTime );
- pwszHeaderString = wszHeaderString;
- m_pCallVoteFailed->SetDialogVariable( "FailedReason", pwszHeaderString );
+ {
+ const char *pszTimeString = ( bMinutes ) ? ( ( nTime < 2 ) ? "#GameUI_vote_failed_cannot_kick_min" : "#GameUI_vote_failed_cannot_kick_mins" ) : "#GameUI_vote_failed_cannot_kick";
+ g_pVGuiLocalize->ConstructString( wszHeaderString, sizeof( wszHeaderString ), g_pVGuiLocalize->Find( pszTimeString ), 1, wszTime );
+ m_pCallVoteFailed->SetDialogVariable( "FailedReason", wszHeaderString );
break;
+ }
case VOTE_FAILED_CANNOT_KICK_DURING_ROUND:
m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_round_active" );
@@ -1070,6 +1121,14 @@ void CHudVote::MsgFunc_CallVoteFailed( bf_read &msg )
case VOTE_FAILED_MODIFICATION_ALREADY_ACTIVE:
m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_event_already_active" );
break;
+
+ case VOTE_FAILED_VOTE_IN_PROGRESS:
+ m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_vote_in_progress" );
+ break;
+
+ case VOTE_FAILED_KICK_LIMIT_REACHED:
+ m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_kick_limit" );
+ break;
}
}
@@ -1081,14 +1140,14 @@ void CHudVote::MsgFunc_VoteFailed( bf_read &msg )
if ( IsPlayingDemo() )
return;
- int iTeam = msg.ReadByte();
+ m_nVoteTeamIndex = msg.ReadByte();
vote_create_failed_t nReason = (vote_create_failed_t)msg.ReadByte();
// Visibility of this error is handled by OnThink()
- SetVoteActive( false );
+ m_bVotingActive = false;
m_bVotePassed = false;
- m_flVoteResultCycleTime = gpGlobals->curtime + 2;
- m_flHideTime = gpGlobals->curtime + 5;
+ m_flVoteResultCycleTime = gpGlobals->curtime + 2.f;
+ m_flHideTime = gpGlobals->curtime + 5.f;
switch ( nReason )
{
@@ -1105,11 +1164,10 @@ void CHudVote::MsgFunc_VoteFailed( bf_read &msg )
break;
}
- // driller: this event has no listeners - will eventually hook into stats
IGameEvent *event = gameeventmanager->CreateEvent( "vote_failed" );
if ( event )
{
- event->SetInt( "team", iTeam );
+ event->SetInt( "team", m_nVoteTeamIndex );
gameeventmanager->FireEventClientSide( event );
}
@@ -1117,7 +1175,11 @@ void CHudVote::MsgFunc_VoteFailed( bf_read &msg )
if ( !pLocalPlayer )
return;
- pLocalPlayer->EmitSound("Vote.Failed");
+ bool bShowToPlayer = ( !m_nVoteTeamIndex || pLocalPlayer->GetTeamNumber() == m_nVoteTeamIndex );
+ if ( bShowToPlayer )
+ {
+ pLocalPlayer->EmitSound("Vote.Failed");
+ }
}
//-----------------------------------------------------------------------------
@@ -1133,9 +1195,8 @@ void CHudVote::MsgFunc_VoteStart( bf_read &msg )
return;
// Is this a team-only vote?
- int iTeam = msg.ReadByte();
- uint8 invalidTeam = (uint8)TEAM_INVALID;
- if ( iTeam != invalidTeam && iTeam != pLocalPlayer->GetTeamNumber() )
+ m_nVoteTeamIndex = msg.ReadByte();
+ if ( m_nVoteTeamIndex >= FIRST_GAME_TEAM && m_nVoteTeamIndex != pLocalPlayer->GetTeamNumber() )
return;
// Entity calling the vote
@@ -1163,18 +1224,18 @@ void CHudVote::MsgFunc_VoteStart( bf_read &msg )
}
// DisplayString
- char szIssue[256];
+ char szIssue[k_MAX_VOTE_NAME_LENGTH];
szIssue[0] = 0;
msg.ReadString( szIssue, sizeof(szIssue) );
// DetailString
- char szParam1[256];
+ char szParam1[k_MAX_VOTE_NAME_LENGTH];
szParam1[0] = 0;
msg.ReadString( szParam1, sizeof(szParam1) );
m_bIsYesNoVote = msg.ReadByte();
- SetVoteActive( true );
+ m_bVotingActive = true;
m_pVoteFailed->SetVisible( false );
m_pVotePassed->SetVisible( false );
m_pCallVoteFailed->SetVisible( false );
@@ -1204,25 +1265,23 @@ void CHudVote::MsgFunc_VoteStart( bf_read &msg )
// Display vote caller's name
wchar_t wszCallerName[MAX_PLAYER_NAME_LENGTH];
- wchar_t wszHeaderString[512];
- wchar_t *pwszHeaderString;
+ wchar_t wszHeaderString[k_MAX_VOTE_NAME_LENGTH];
// Player
g_pVGuiLocalize->ConvertANSIToUnicode( pszCallerName, wszCallerName, sizeof( wszCallerName ) );
// String
- g_pVGuiLocalize->ConstructString( wszHeaderString, sizeof(wszHeaderString), g_pVGuiLocalize->Find( "#GameUI_vote_header" ), 1, wszCallerName );
- pwszHeaderString = wszHeaderString;
+ g_pVGuiLocalize->ConstructString( wszHeaderString, sizeof( wszHeaderString ), g_pVGuiLocalize->Find( "#GameUI_vote_header" ), 1, wszCallerName );
// Final
- m_pVoteActive->SetDialogVariable( "header", pwszHeaderString );
+ m_pVoteActive->SetDialogVariable( "header", wszHeaderString );
// Display the Issue
wchar_t *pwcParam;
- wchar_t wcParam[128];
+ wchar_t wcParam[k_MAX_VOTE_NAME_LENGTH];
wchar_t *pwcIssue;
- wchar_t wcIssue[512];
+ wchar_t wcIssue[k_MAX_VOTE_NAME_LENGTH];
if ( Q_strlen( szParam1 ) > 0 )
{
@@ -1252,7 +1311,7 @@ void CHudVote::MsgFunc_VoteStart( bf_read &msg )
if ( m_bIsYesNoVote )
{
// YES / NO UI
- wchar_t wzFinal[512] = L"";
+ wchar_t wzFinal[k_MAX_VOTE_NAME_LENGTH] = L"";
wchar_t *pszText = g_pVGuiLocalize->Find( "#GameUI_vote_yes_pc_instruction" );
if ( pszText )
{
@@ -1294,7 +1353,7 @@ void CHudVote::MsgFunc_VoteStart( bf_read &msg )
// Construct Option name
const char *pszChoiceName = m_VoteSetupChoices[iIndex];
- char szOptionName[256];
+ char szOptionName[k_MAX_VOTE_NAME_LENGTH];
Q_snprintf( szOptionName, sizeof( szOptionName ), "F%i. ", iIndex + 1 );
Q_strncat( szOptionName, pszChoiceName, sizeof( szOptionName ), COPY_ALL_CHARACTERS );
@@ -1320,7 +1379,7 @@ void CHudVote::MsgFunc_VoteStart( bf_read &msg )
{
event->SetString( "issue", szIssue );
event->SetString( "param1", szParam1 );
- event->SetInt( "team", iTeam );
+ event->SetInt( "team", m_nVoteTeamIndex );
event->SetInt( "initiator", m_iVoteCallerIdx );
gameeventmanager->FireEventClientSide( event );
}
@@ -1332,10 +1391,10 @@ void CHudVote::MsgFunc_VoteStart( bf_read &msg )
}
else
{
- ShowVoteUI();
+ m_bShowVoteActivePanel = true;
}
#else
- ShowVoteUI();
+ m_bShowVoteActivePanel = true;
#endif // TF_CLIENT_DLL
}
@@ -1347,24 +1406,24 @@ void CHudVote::MsgFunc_VotePass( bf_read &msg )
if ( IsPlayingDemo() )
return;
- int iTeam = msg.ReadByte();
+ m_nVoteTeamIndex = msg.ReadByte();
// Passed string
- char szResult[256];
+ char szResult[k_MAX_VOTE_NAME_LENGTH];
szResult[0] = 0;
msg.ReadString( szResult, sizeof(szResult) );
// Detail string
- char szParam1[256];
+ char szParam1[k_MAX_VOTE_NAME_LENGTH];
szParam1[0] = 0;
msg.ReadString( szParam1, sizeof(szParam1) );
// Localize
wchar_t *pwcParam;
- wchar_t wcParam[128];
+ wchar_t wcParam[k_MAX_VOTE_NAME_LENGTH];
wchar_t *pwcIssue;
- wchar_t wcIssue[512];
+ wchar_t wcIssue[k_MAX_VOTE_NAME_LENGTH];
if ( Q_strlen( szParam1 ) > 0 )
{
@@ -1390,10 +1449,10 @@ void CHudVote::MsgFunc_VotePass( bf_read &msg )
m_pVotePassed->SetDialogVariable( "passedresult", pwcIssue );
- SetVoteActive( false );
+ m_bVotingActive = false;
m_bVotePassed = true;
- m_flVoteResultCycleTime = gpGlobals->curtime + 2;
- m_flHideTime = gpGlobals->curtime + 5;
+ m_flVoteResultCycleTime = gpGlobals->curtime + 2.f;
+ m_flHideTime = gpGlobals->curtime + 5.f;
// driller: this event has no listeners - will eventually hook into stats
IGameEvent *event = gameeventmanager->CreateEvent( "vote_passed" );
@@ -1401,7 +1460,7 @@ void CHudVote::MsgFunc_VotePass( bf_read &msg )
{
event->SetString( "details", szResult );
event->SetString( "param1", szParam1 );
- event->SetInt( "team", iTeam );
+ event->SetInt( "team", m_nVoteTeamIndex );
gameeventmanager->FireEventClientSide( event );
}
@@ -1434,21 +1493,45 @@ void CHudVote::MsgFunc_VoteSetup( bf_read &msg )
int nIssueCount = msg.ReadByte();
if ( nIssueCount )
{
- for ( int index = 0; index < nIssueCount; index++ )
+ for ( int i = 0; i < nIssueCount; i++ )
{
- char szIssue[256];
- msg.ReadString( szIssue, sizeof(szIssue) );
- if ( !m_VoteSetupIssues.HasElement( szIssue ) )
+ char szIssue[k_MAX_VOTE_NAME_LENGTH];
+ char szIssueString[k_MAX_VOTE_NAME_LENGTH];
+ msg.ReadString( szIssue, sizeof( szIssue ) );
+ msg.ReadString( szIssueString, sizeof( szIssueString ) );
+ bool bIsActive = (bool)msg.ReadByte();
+
+ m_bVoteSystemActive |= bIsActive;
+
+ bool bAdd = true;
+ FOR_EACH_VEC( m_VoteSetupIssues, j )
+ {
+ if ( !V_strcmp( szIssue, m_VoteSetupIssues[j].szName ) )
+ {
+ bAdd = false;
+ break;
+ }
+ }
+
+ if ( bAdd )
{
+ // When empty, assume that we just pre-pend #Vote_ to szIssue (reduces msg size)
+ if ( !szIssueString[0] )
+ {
+ V_sprintf_safe( szIssueString, "#Vote_%s", szIssue );
+ }
+
+ VoteIssue_t issue;
+ V_strcpy_safe( issue.szName, szIssue );
+ V_strcpy_safe( issue.szNameString, szIssueString );
+ issue.bIsActive = bIsActive;
+
// Send it over to the listpanel
- m_VoteSetupIssues.CopyAndAddToTail( szIssue );
+ m_VoteSetupIssues.AddToTail( issue );
}
}
}
- else
- {
- m_VoteSetupIssues.CopyAndAddToTail( "Voting disabled on this Server" );
- }
+
m_pVoteSetupDialog->AddVoteIssues( m_VoteSetupIssues );
// Load up the list of Vote Issue Parameters
@@ -1638,50 +1721,51 @@ void CHudVote::FireGameEvent( IGameEvent *event )
//-----------------------------------------------------------------------------
void CHudVote::OnThink()
{
- // We delay hiding the menu after we cast a vote
- if ( m_bPlayerVoted && m_flPostVotedHideTime > 0 && m_flPostVotedHideTime < gpGlobals->curtime )
- {
- m_pVoteActive->SetVisible( false );
- m_bShowVoteActivePanel = false;
- m_flPostVotedHideTime = -1;
- }
-
- if ( m_flVoteResultCycleTime > 0 && m_flVoteResultCycleTime < gpGlobals->curtime )
+ C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
+ if ( pLocalPlayer )
{
- m_pVoteActive->SetVisible( false );
- m_pVoteFailed->SetVisible( !m_bVotePassed );
- m_pVotePassed->SetVisible( m_bVotePassed );
- g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_pVoteActive, "HideVoteBackgrounds" );
-
- m_flVoteResultCycleTime = -1;
- m_bPlayerVoted = false;
- m_bVoteActive = false;
- m_bShowVoteActivePanel = false;
- m_iVoteCallerIdx = -1;
- }
+ bool bShowToPlayer = ( !m_nVoteTeamIndex || pLocalPlayer->GetTeamNumber() == m_nVoteTeamIndex );
- if ( m_bVoteActive )
- {
- // driller: Need to rewrite this to handle all vote types (Yes/No and General)
- if ( m_bIsYesNoVote && m_pVoteActive )
+ // We delay hiding the menu after we cast a vote
+ if ( m_bPlayerVoted && m_flPostVotedHideTime > 0 && gpGlobals->curtime > m_flPostVotedHideTime )
{
- char szYesCount[512] = "";
- Q_snprintf( szYesCount, 512, "%d", m_nVoteOptionCount[0] );
-
- char szNoCount[512] = "";
- Q_snprintf( szNoCount, 512, "%d", m_nVoteOptionCount[1] );
+ m_pVoteActive->SetVisible( false );
+ m_bShowVoteActivePanel = false;
+ m_flPostVotedHideTime = -1;
+ }
- m_pVoteActive->SetControlString( "Option1CountLabel", szYesCount );
- m_pVoteActive->SetControlString( "Option2CountLabel", szNoCount );
+ if ( m_flVoteResultCycleTime > 0 && gpGlobals->curtime > m_flVoteResultCycleTime )
+ {
+ m_pVoteActive->SetVisible( false );
+ m_pVoteFailed->SetVisible( !m_bVotePassed && bShowToPlayer );
+ m_pVotePassed->SetVisible( m_bVotePassed && bShowToPlayer );
+ g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_pVoteActive, "HideVoteBackgrounds" );
+
+ m_flVoteResultCycleTime = -1;
+ m_bPlayerVoted = false;
+ m_bVotingActive = false;
+ m_bShowVoteActivePanel = false;
+ m_iVoteCallerIdx = -1;
}
- if ( !m_pVoteActive->IsVisible() && m_bShowVoteActivePanel )
+ if ( m_bVotingActive && m_bShowVoteActivePanel )
{
- m_pVoteActive->SetVisible( true );
+ // driller: Need to rewrite this to handle all vote types (Yes/No and General)
+ if ( m_bIsYesNoVote && m_pVoteActive )
+ {
+ char szYesCount[k_MAX_VOTE_NAME_LENGTH] = "";
+ Q_snprintf( szYesCount, sizeof( szYesCount ), "%d", m_nVoteOptionCount[0] );
- C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
- if ( pLocalPlayer )
+ char szNoCount[k_MAX_VOTE_NAME_LENGTH] = "";
+ Q_snprintf( szNoCount, sizeof( szNoCount ), "%d", m_nVoteOptionCount[1] );
+
+ m_pVoteActive->SetControlString( "Option1CountLabel", szYesCount );
+ m_pVoteActive->SetControlString( "Option2CountLabel", szNoCount );
+ }
+
+ if ( !m_pVoteActive->IsVisible() && bShowToPlayer )
{
+ m_pVoteActive->SetVisible( true );
pLocalPlayer->EmitSound("Vote.Created");
}
}
@@ -1695,7 +1779,7 @@ void CHudVote::OnThink()
//-----------------------------------------------------------------------------
bool CHudVote::ShouldDraw( void )
{
- return ( m_bVoteActive || m_flHideTime > gpGlobals->curtime );
+ return ( m_bVotingActive || gpGlobals->curtime < m_flHideTime );
}
//-----------------------------------------------------------------------------
@@ -1709,22 +1793,6 @@ bool CHudVote::IsPlayingDemo() const
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
-void CHudVote::SetVoteActive( bool bActive )
-{
- m_bVoteActive = bActive;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CHudVote::ShowVoteUI( void )
-{
- m_bShowVoteActivePanel = true;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
bool CHudVote::IsVoteUIActive( void )
{
return m_bShowVoteActivePanel;
diff --git a/mp/src/game/client/hud_vote.h b/mp/src/game/client/hud_vote.h
index 91ba1e9b..38956366 100644
--- a/mp/src/game/client/hud_vote.h
+++ b/mp/src/game/client/hud_vote.h
@@ -25,6 +25,8 @@ extern INetworkStringTable *g_pStringTableServerPopFiles;
extern INetworkStringTable *g_pStringTableServerMapCycleMvM;
#endif
+static const int k_MAX_VOTE_NAME_LENGTH = 256;
+
namespace vgui
{
class SectionedListPanel;
@@ -32,6 +34,13 @@ namespace vgui
class ImageList;
};
+struct VoteIssue_t
+{
+ char szName[k_MAX_VOTE_NAME_LENGTH];
+ char szNameString[k_MAX_VOTE_NAME_LENGTH];
+ bool bIsActive;
+};
+
class VoteBarPanel : public vgui::Panel, public CGameEventListener
{
DECLARE_CLASS_SIMPLE( VoteBarPanel, vgui::Panel );
@@ -69,8 +78,9 @@ public:
virtual void PostApplySchemeSettings( vgui::IScheme *pScheme );
virtual void ApplySettings(KeyValues *inResourceData);
+ void InitializeIssueList( void );
void UpdateCurrentMap( void );
- void AddVoteIssues( CUtlStringList &m_VoteSetupIssues );
+ void AddVoteIssues( CUtlVector< VoteIssue_t > &m_VoteSetupIssues );
void AddVoteIssueParams_MapCycle( CUtlStringList &m_VoteSetupMapCycle );
#ifdef TF_CLIENT_DLL
@@ -94,7 +104,7 @@ private:
vgui::Button *m_pCallVoteButton;
vgui::ImageList *m_pImageList;
- CUtlVector<const char*> m_VoteIssues;
+ CUtlVector< VoteIssue_t > m_VoteIssues;
CUtlVector<const char*> m_VoteIssuesMapCycle;
#ifdef TF_CLIENT_DLL
@@ -137,12 +147,12 @@ class CHudVote : public vgui::EditablePanel, public CHudElement
void MsgFunc_VoteSetup( bf_read &msg );
void PropagateOptionParameters( void );
- void ShowVoteUI( void );
+ void ShowVoteUI( bool bShow ) { m_bShowVoteActivePanel = bShow; }
bool IsVoteUIActive( void );
+ bool IsVoteSystemActive( void ) { return m_bVoteSystemActive; }
private:
bool IsPlayingDemo() const;
- void SetVoteActive( bool bActive );
EditablePanel *m_pVoteActive;
VoteBarPanel *m_voteBar;
@@ -151,7 +161,7 @@ private:
EditablePanel *m_pCallVoteFailed;
CVoteSetupDialog *m_pVoteSetupDialog;
- CUtlStringList m_VoteSetupIssues;
+ CUtlVector< VoteIssue_t > m_VoteSetupIssues;
CUtlStringList m_VoteSetupMapCycle;
#ifdef TF_CLIENT_DLL
@@ -160,7 +170,8 @@ private:
CUtlStringList m_VoteSetupChoices;
- bool m_bVoteActive;
+ bool m_bVotingActive;
+ bool m_bVoteSystemActive;
float m_flVoteResultCycleTime; // what time will we cycle to the result
float m_flHideTime; // what time will we hide
bool m_bVotePassed; // what mode are we going to cycle to
@@ -172,6 +183,7 @@ private:
float m_flPostVotedHideTime;
bool m_bShowVoteActivePanel;
int m_iVoteCallerIdx;
+ int m_nVoteTeamIndex; // If defined, only players on this team will see/vote on the issue
};
#endif // HUD_VOTE_H
diff --git a/mp/src/game/client/in_camera.cpp b/mp/src/game/client/in_camera.cpp
index aa010732..ec40ac18 100644
--- a/mp/src/game/client/in_camera.cpp
+++ b/mp/src/game/client/in_camera.cpp
@@ -60,6 +60,7 @@ void CAM_ToThirdPerson(void)
{
if ( cl_thirdperson.GetBool() == false )
{
+ g_ThirdPersonManager.SetDesiredCameraOffset( Vector( cam_idealdist.GetFloat(), cam_idealdistright.GetFloat(), cam_idealdistup.GetFloat() ) );
g_ThirdPersonManager.SetOverridingThirdPerson( true );
}
diff --git a/mp/src/game/client/in_joystick.cpp b/mp/src/game/client/in_joystick.cpp
index 71d03a08..a3b63620 100644
--- a/mp/src/game/client/in_joystick.cpp
+++ b/mp/src/game/client/in_joystick.cpp
@@ -800,7 +800,7 @@ void CInput::JoyStickMove( float frametime, CUserCmd *cmd )
if ( m_flPreviousJoystickForward || m_flPreviousJoystickSide || m_flPreviousJoystickPitch || m_flPreviousJoystickYaw )
{
- Vector vTempOffset = g_ThirdPersonManager.GetCameraOffsetAngles();
+ const Vector& vTempOffset = g_ThirdPersonManager.GetCameraOffsetAngles();
// update the ideal pitch and yaw
cam_idealpitch.SetValue( vTempOffset[ PITCH ] - viewangles[ PITCH ] );
diff --git a/mp/src/game/client/in_mouse.cpp b/mp/src/game/client/in_mouse.cpp
index bcf715a1..332b0ea1 100644
--- a/mp/src/game/client/in_mouse.cpp
+++ b/mp/src/game/client/in_mouse.cpp
@@ -522,7 +522,7 @@ void CInput::ApplyMouse( QAngle& viewangles, CUserCmd *cmd, float mouse_x, float
}
else
{
- viewangles[PITCH] += m_pitch->GetFloat() * mouse_y;
+ viewangles[PITCH] += CAM_CapPitch( m_pitch->GetFloat() * mouse_y );
}
// Check pitch bounds
diff --git a/mp/src/game/client/input.h b/mp/src/game/client/input.h
index e34b82db..2fa2cec3 100644
--- a/mp/src/game/client/input.h
+++ b/mp/src/game/client/input.h
@@ -99,7 +99,8 @@ public:
virtual bool CAM_IsOrthographic() const;
virtual void CAM_OrthographicSize( float& w, float& h ) const;
- virtual float CAM_CapYaw( float fVal ) { return fVal; }
+ virtual float CAM_CapYaw( float fVal ) const { return fVal; }
+ virtual float CAM_CapPitch( float fVal ) const { return fVal; }
#if defined( HL2_CLIENT_DLL )
// IK back channel info
@@ -113,7 +114,7 @@ public:
virtual bool EnableJoystickMode();
// Private Implementation
-private:
+protected:
// Implementation specific initialization
void Init_Camera( void );
void Init_Keyboard( void );
@@ -134,8 +135,8 @@ private:
void GetAccumulatedMouseDeltasAndResetAccumulators( float *mx, float *my );
void GetMouseDelta( float inmousex, float inmousey, float *pOutMouseX, float *pOutMouseY );
void ScaleMouse( float *x, float *y );
- void ApplyMouse( QAngle& viewangles, CUserCmd *cmd, float mouse_x, float mouse_y );
- void MouseMove ( CUserCmd *cmd );
+ virtual void ApplyMouse( QAngle& viewangles, CUserCmd *cmd, float mouse_x, float mouse_y );
+ virtual void MouseMove ( CUserCmd *cmd );
// Joystick movement input helpers
void ControllerMove ( float frametime, CUserCmd *cmd );
diff --git a/mp/src/game/client/particlemgr.cpp b/mp/src/game/client/particlemgr.cpp
index f79d17a6..0eb09a43 100644
--- a/mp/src/game/client/particlemgr.cpp
+++ b/mp/src/game/client/particlemgr.cpp
@@ -1540,12 +1540,15 @@ static ConVar r_threaded_particles( "r_threaded_particles", "1" );
static float s_flThreadedPSystemTimeStep;
-static void ProcessPSystem( CNewParticleEffect *&pNewEffect )
+static void ProcessPSystem( ParticleSimListEntry_t& pSimListEntry )
{
// Enable FP exceptions here when FP_EXCEPTIONS_ENABLED is defined,
// to help track down bad math.
FPExceptionEnabler enableExceptions;
+ CNewParticleEffect* pNewEffect = pSimListEntry.m_pNewParticleEffect;
+ bool updateBboxOnly = pSimListEntry.m_bBoundingBoxOnly;
+
// If this is a new effect, then update its bbox so it goes in the
// right leaves (if it has particles).
int bFirstUpdate = pNewEffect->GetNeedsBBoxUpdate();
@@ -1564,12 +1567,12 @@ static void ProcessPSystem( CNewParticleEffect *&pNewEffect )
if ( pNewEffect->GetFirstFrameFlag() )
{
- pNewEffect->Simulate( 0.0f );
+ pNewEffect->Simulate( 0.0f, updateBboxOnly );
pNewEffect->SetFirstFrameFlag( false );
}
else if ( pNewEffect->ShouldSimulate() )
{
- pNewEffect->Simulate( s_flThreadedPSystemTimeStep );
+ pNewEffect->Simulate( s_flThreadedPSystemTimeStep, updateBboxOnly );
}
if ( pNewEffect->IsFinished() )
@@ -1684,7 +1687,7 @@ bool CParticleMgr::RetireParticleCollections( CParticleSystemDefinition* pDef,
// Next, see if there are new particle systems that need early retirement
static ConVar cl_particle_retire_cost( "cl_particle_retire_cost", "0", FCVAR_CHEAT );
-bool CParticleMgr::EarlyRetireParticleSystems( int nCount, CNewParticleEffect **ppEffects )
+bool CParticleMgr::EarlyRetireParticleSystems( int nCount, ParticleSimListEntry_t *ppEffects )
{
// NOTE: Doing a cheap and hacky estimate of worst-case fillrate
const CViewSetup *pViewSetup = view->GetPlayerViewSetup();
@@ -1699,14 +1702,14 @@ bool CParticleMgr::EarlyRetireParticleSystems( int nCount, CNewParticleEffect **
CParticleSystemDefinition **ppDefs = (CParticleSystemDefinition**)stackalloc( nCount * sizeof(CParticleSystemDefinition*) );
for ( int i = 0; i < nCount; ++i )
{
- CParticleSystemDefinition *pDef = ppEffects[i]->m_pDef;
+ CParticleSystemDefinition *pDef = ppEffects[i].m_pNewParticleEffect->m_pDef;
// Skip stuff that doesn't have a cull radius set
if ( pDef->GetCullRadius() == 0.0f )
continue;
// Only perform the cull check on creation
- if ( !ppEffects[i]->GetFirstFrameFlag() )
+ if ( !ppEffects[i].m_pNewParticleEffect->GetFirstFrameFlag() )
continue;
if ( pDef->HasRetirementBeenChecked( gpGlobals->framecount ) )
@@ -1714,7 +1717,7 @@ bool CParticleMgr::EarlyRetireParticleSystems( int nCount, CNewParticleEffect **
pDef->MarkRetirementCheck( gpGlobals->framecount );
- ppDefs[nDefCount++] = ppEffects[i]->m_pDef;
+ ppDefs[nDefCount++] = ppEffects[i].m_pNewParticleEffect->m_pDef;
}
if ( nDefCount == 0 )
@@ -1722,7 +1725,7 @@ bool CParticleMgr::EarlyRetireParticleSystems( int nCount, CNewParticleEffect **
for ( int i = 0; i < nCount; ++i )
{
- ppEffects[i]->MarkShouldPerformCullCheck( true );
+ ppEffects[i].m_pNewParticleEffect->MarkShouldPerformCullCheck( true );
}
Vector vecCameraForward;
@@ -1749,28 +1752,45 @@ bool CParticleMgr::EarlyRetireParticleSystems( int nCount, CNewParticleEffect **
for ( int i = 0; i < nCount; ++i )
{
- ppEffects[i]->MarkShouldPerformCullCheck( false );
+ ppEffects[i].m_pNewParticleEffect->MarkShouldPerformCullCheck( false );
}
return bRetiredCollections;
}
static ConVar particle_sim_alt_cores( "particle_sim_alt_cores", "2" );
-void CParticleMgr::BuildParticleSimList( CUtlVector< CNewParticleEffect* > &list )
+void CParticleMgr::BuildParticleSimList( CUtlVector< ParticleSimListEntry_t > &list )
{
float flNow = g_pParticleSystemMgr->GetLastSimulationTime();
for( CNewParticleEffect *pNewEffect=m_NewEffects.m_pHead; pNewEffect;
pNewEffect=pNewEffect->m_pNext )
{
+ bool bSkip = false;
+ bool bNeedsBboxUpdate = false;
+
if ( flNow >= pNewEffect->m_flNextSleepTime && pNewEffect->m_nActiveParticles > 0 )
- continue;
+ bSkip = true;
if ( pNewEffect->GetRemoveFlag() )
- continue;
- if ( g_bMeasureParticlePerformance )
+ bSkip = true;
+
+ if ( !bSkip && g_bMeasureParticlePerformance )
{
g_nNumParticlesSimulated += pNewEffect->m_nActiveParticles;
}
- list.AddToTail( pNewEffect );
+
+ // Particles that are attached to moving things will need to update their bboxes even if they
+ // otherwise would like to skip the updates. Check that here.
+ if (bSkip)
+ {
+ bNeedsBboxUpdate = pNewEffect->HasMoved();
+ bSkip = !bNeedsBboxUpdate;
+ }
+
+ if (!bSkip)
+ {
+ ParticleSimListEntry_t entry = { pNewEffect, bNeedsBboxUpdate };
+ list.AddToTail( entry );
+ }
}
}
@@ -1812,23 +1832,27 @@ void CParticleMgr::UpdateNewEffects( float flTimeDelta )
int nParticleStatsTriggerCount = cl_particle_stats_trigger_count.GetInt();
BeginSimulateParticles();
- CUtlVector<CNewParticleEffect *> particlesToSimulate;
- BuildParticleSimList( particlesToSimulate );
s_flThreadedPSystemTimeStep = flTimeDelta;
- int nCount = particlesToSimulate.Count();
-
// first, run non-reentrant part to get CP updates from entities
- for( int i=0; i<nCount; i++ )
+ // This is done on all particles, because it updates control point locations which we need to determine whether or not we should
+ // do full simulation later.
+ for (CNewParticleEffect *pNewEffect = m_NewEffects.m_pHead; pNewEffect;
+ pNewEffect = pNewEffect->m_pNext)
{
// this one can call into random entity code which may not be thread-safe
- particlesToSimulate[i]->Update( s_flThreadedPSystemTimeStep );
+ pNewEffect->Update( s_flThreadedPSystemTimeStep );
if ( nParticleStatsTriggerCount > 0 )
{
- nParticleActiveParticlesCount += CountParticleSystemActiveParticles( particlesToSimulate[i] );
+ nParticleActiveParticlesCount += CountParticleSystemActiveParticles( pNewEffect );
}
}
+ CUtlVector<ParticleSimListEntry_t> particlesToSimulate;
+ BuildParticleSimList(particlesToSimulate);
+ int nCount = particlesToSimulate.Count();
+
+
// See if there are new particle systems that need early retirement
// This has to happen after the first update
if ( EarlyRetireParticleSystems( nCount, particlesToSimulate.Base() ) )
@@ -1861,7 +1885,7 @@ void CParticleMgr::UpdateNewEffects( float flTimeDelta )
{
nAltCore = 2;
}
- CParallelProcessor<CNewParticleEffect*, CFuncJobItemProcessor<CNewParticleEffect*> > processor( "CParticleMgr::UpdateNewEffects" );
+ CParallelProcessor<ParticleSimListEntry_t, CFuncJobItemProcessor<ParticleSimListEntry_t> > processor( "CParticleMgr::UpdateNewEffects" );
processor.m_ItemProcessor.Init( ProcessPSystem, NULL, NULL );
processor.Run( particlesToSimulate.Base(), nCount, INT_MAX, m_pThreadPool[nAltCore-1] );
}
@@ -1872,7 +1896,7 @@ void CParticleMgr::UpdateNewEffects( float flTimeDelta )
for( int i=0; i<nCount; i++)
{
// this one can call into random entity code which may not be thread-safe
- particlesToSimulate[i]->DetectChanges();
+ particlesToSimulate[i].m_pNewParticleEffect->DetectChanges();
}
EndSimulateParticles();
diff --git a/mp/src/game/client/particlemgr.h b/mp/src/game/client/particlemgr.h
index 3214a55f..d4537f35 100644
--- a/mp/src/game/client/particlemgr.h
+++ b/mp/src/game/client/particlemgr.h
@@ -236,6 +236,13 @@ public:
IMaterial *m_pMaterial;
};
+// Particle simulation list, used to determine what particles to simulate and how.
+struct ParticleSimListEntry_t
+{
+ CNewParticleEffect* m_pNewParticleEffect;
+ bool m_bBoundingBoxOnly;
+};
+
//-----------------------------------------------------------------------------
// interface IParticleEffect:
@@ -715,8 +722,9 @@ private:
const CViewSetup& view, const VMatrix &worldToPixels, float flFocalDist );
bool RetireParticleCollections( CParticleSystemDefinition* pDef, int nCount, RetireInfo_t *pInfo, float flScreenArea, float flMaxTotalArea );
- void BuildParticleSimList( CUtlVector< CNewParticleEffect* > &list );
- bool EarlyRetireParticleSystems( int nCount, CNewParticleEffect **ppEffects );
+
+ void BuildParticleSimList( CUtlVector< ParticleSimListEntry_t > &list );
+ bool EarlyRetireParticleSystems( int nCount, ParticleSimListEntry_t *ppEffects );
static int RetireSort( const void *p1, const void *p2 );
private:
diff --git a/mp/src/game/client/particles_new.cpp b/mp/src/game/client/particles_new.cpp
index d3dc6599..647d304f 100644
--- a/mp/src/game/client/particles_new.cpp
+++ b/mp/src/game/client/particles_new.cpp
@@ -65,6 +65,8 @@ void CNewParticleEffect::Construct()
m_MaxBounds = Vector( -1.0e6, -1.0e6, -1.0e6 );
m_pDebugName = NULL;
+ m_bViewModelEffect = m_pDef ? m_pDef->IsViewModelEffect() : false;
+
if ( IsValid() && clienttools->IsInRecordingMode() )
{
int nId = AllocateToolParticleEffectId();
diff --git a/mp/src/game/client/particles_new.h b/mp/src/game/client/particles_new.h
index eb80f93a..06d98c9c 100644
--- a/mp/src/game/client/particles_new.h
+++ b/mp/src/game/client/particles_new.h
@@ -91,6 +91,9 @@ public:
void SetControlPointUpVector( int nWhichPoint, const Vector &v );
void SetControlPointRightVector( int nWhichPoint, const Vector &v );
+ void SetIsViewModelEffect ( bool bIsViewModelEffect ) { m_bViewModelEffect = bIsViewModelEffect; }
+ bool GetIsViewModelEffect () { return m_bViewModelEffect; }
+
FORCEINLINE EHANDLE const &GetControlPointEntity( int nWhichPoint )
{
return m_hControlPointOwners[ nWhichPoint ];
@@ -153,6 +156,8 @@ protected:
Vector m_LastMin;
Vector m_LastMax;
+ bool m_bViewModelEffect;
+
private:
// Update the reference count.
void AddRef();
@@ -309,7 +314,7 @@ inline void CNewParticleEffect::MarkShouldPerformCullCheck( bool bEnable )
inline CSmartPtr<CNewParticleEffect> CNewParticleEffect::Create( CBaseEntity *pOwner, const char *pParticleSystemName, const char *pDebugName )
{
CNewParticleEffect *pRet = new CNewParticleEffect( pOwner, pParticleSystemName );
- pRet->m_pDebugName = pDebugName;
+ pRet->m_pDebugName = pDebugName ? pDebugName : pParticleSystemName;
pRet->SetDynamicallyAllocated( true );
return pRet;
}
@@ -317,7 +322,7 @@ inline CSmartPtr<CNewParticleEffect> CNewParticleEffect::Create( CBaseEntity *pO
inline CSmartPtr<CNewParticleEffect> CNewParticleEffect::Create( CBaseEntity *pOwner, CParticleSystemDefinition *pDef, const char *pDebugName )
{
CNewParticleEffect *pRet = new CNewParticleEffect( pOwner, pDef );
- pRet->m_pDebugName = pDebugName;
+ pRet->m_pDebugName = pDebugName ? pDebugName : pDef->GetName();
pRet->SetDynamicallyAllocated( true );
return pRet;
}
diff --git a/mp/src/game/client/prediction.cpp b/mp/src/game/client/prediction.cpp
index 6646f8f9..2a67007b 100644
--- a/mp/src/game/client/prediction.cpp
+++ b/mp/src/game/client/prediction.cpp
@@ -45,6 +45,12 @@ static ConVar cl_predictionentitydump( "cl_pdump", "-1", FCVAR_CHEAT, "Dump info
static ConVar cl_predictionentitydumpbyclass( "cl_pclass", "", FCVAR_CHEAT, "Dump entity by prediction classname." );
static ConVar cl_pred_optimize( "cl_pred_optimize", "2", 0, "Optimize for not copying data if didn't receive a network update (1), and also for not repredicting if there were no errors (2)." );
+#ifdef STAGING_ONLY
+// Do not ship this - testing a fix
+static ConVar cl_pred_optimize_prefer_server_data( "cl_pred_optimize_prefer_server_data", "0", 0, "In the case where we have both server data and predicted data up to the same tick, choose server data over predicted data." );
+//
+#endif // STAGING_ONLY
+
#endif
extern IGameMovement *g_pGameMovement;
@@ -1401,6 +1407,11 @@ int CPrediction::ComputeFirstCommandToExecute( bool received_new_world_update, i
}
else
{
+#ifdef STAGING_ONLY
+ int nPredictedLimit = cl_pred_optimize_prefer_server_data.GetBool() ? m_nCommandsPredicted - 1 : m_nCommandsPredicted;
+#else
+ int nPredictedLimit = m_nCommandsPredicted;
+#endif // STAGING_ONLY
// Otherwise, there is a second optimization, wherein if we did receive an update, but no
// values differed (or were outside their epsilon) and the server actually acknowledged running
// one or more commands, then we can revert the entity to the predicted state from last frame,
@@ -1409,7 +1420,7 @@ int CPrediction::ComputeFirstCommandToExecute( bool received_new_world_update, i
if ( cl_pred_optimize.GetInt() >= 2 &&
!m_bPreviousAckHadErrors &&
m_nCommandsPredicted > 0 &&
- m_nServerCommandsAcknowledged <= m_nCommandsPredicted )
+ m_nServerCommandsAcknowledged <= nPredictedLimit )
{
// Copy all of the previously predicted data back into entity so we can skip repredicting it
// This is the final slot that we previously predicted
diff --git a/mp/src/game/client/rendertexture.cpp b/mp/src/game/client/rendertexture.cpp
index 78780e93..fa2edb28 100644
--- a/mp/src/game/client/rendertexture.cpp
+++ b/mp/src/game/client/rendertexture.cpp
@@ -107,11 +107,11 @@ ITexture *GetFullFrameFrameBufferTexture( int textureIndex )
char name[256];
if( textureIndex != 0 )
{
- sprintf( name, "_rt_FullFrameFB%d", textureIndex );
+ V_sprintf_safe( name, "_rt_FullFrameFB%d", textureIndex );
}
else
{
- Q_strcpy( name, "_rt_FullFrameFB" );
+ V_strcpy_safe( name, "_rt_FullFrameFB" );
}
s_pFullFrameFrameBufferTexture[textureIndex].Init( materials->FindTexture( name, TEXTURE_GROUP_RENDER_TARGET ) );
Assert( !IsErrorTexture( s_pFullFrameFrameBufferTexture[textureIndex] ) );
diff --git a/mp/src/game/client/replay/genericclassbased_replay.cpp b/mp/src/game/client/replay/genericclassbased_replay.cpp
index 00e2feba..13dfacfd 100644
--- a/mp/src/game/client/replay/genericclassbased_replay.cpp
+++ b/mp/src/game/client/replay/genericclassbased_replay.cpp
@@ -141,7 +141,7 @@ bool CGenericClassBasedReplay::Read( KeyValues *pIn )
// Read killer info
m_nKillerClass = pIn->GetInt( "killer_class" );
- V_strcpy( m_szKillerName, pIn->GetString( "killer_name" ) );
+ V_strcpy_safe( m_szKillerName, pIn->GetString( "killer_name" ) );
// Make sure vector is clear
Assert( GetKillCount() == 0 );
diff --git a/mp/src/game/client/sixense/in_sixense.cpp b/mp/src/game/client/sixense/in_sixense.cpp
index e0f4ba39..c8f79ec7 100644
--- a/mp/src/game/client/sixense/in_sixense.cpp
+++ b/mp/src/game/client/sixense/in_sixense.cpp
@@ -2151,7 +2151,7 @@ void SixenseInput::SetPlayerHandPositions( CUserCmd *pCmd, float flFrametime )
// This 'slides' the hold origin if you pull the object back into the player
float min_z_dist = sixense_hold_slide_z_min_dist.GetFloat();
- float xy_radius = sixense_hold_slide_xy_radius.GetFloat();;
+ float xy_radius = sixense_hold_slide_xy_radius.GetFloat();
if ( !m_bScalingLockedOneToOne && (Vector3( ss_right_pos[0], ss_right_pos[1], 0.0f ).length() < xy_radius) && (ss_right_pos[2] > min_z_dist) )
{
diff --git a/mp/src/game/client/spritemodel.cpp b/mp/src/game/client/spritemodel.cpp
index 018e918f..09284865 100644
--- a/mp/src/game/client/spritemodel.cpp
+++ b/mp/src/game/client/spritemodel.cpp
@@ -201,7 +201,7 @@ static void AdjustSubRect(CEngineSprite *pSprite, int frame, float *pfLeft, floa
*pw = rc.right - rc.left;
*ph = rc.bottom - rc.top;
- f = 1.0 / (float)pSprite->GetWidth();;
+ f = 1.0 / (float)pSprite->GetWidth();
*pfLeft = ((float)rc.left + 0.5) * f;
*pfRight = ((float)rc.right - 0.5) * f;
@@ -415,12 +415,14 @@ IMaterial *CEngineSprite::GetMaterial( RenderMode_t nRenderMode, int nFrame )
m_VideoMaterial->SetFrame( nFrame );
}
-
IMaterial *pMaterial = m_material[nRenderMode];
- IMaterialVar* pFrameVar = pMaterial->FindVarFast( "$frame", &frameCache );
- if ( pFrameVar )
+ if ( pMaterial )
{
- pFrameVar->SetIntValue( nFrame );
+ IMaterialVar* pFrameVar = pMaterial->FindVarFast( "$frame", &frameCache );
+ if ( pFrameVar )
+ {
+ pFrameVar->SetIntValue( nFrame );
+ }
}
return pMaterial;
diff --git a/mp/src/game/client/vgui_debugoverlaypanel.cpp b/mp/src/game/client/vgui_debugoverlaypanel.cpp
index c3734147..32a7ee83 100644
--- a/mp/src/game/client/vgui_debugoverlaypanel.cpp
+++ b/mp/src/game/client/vgui_debugoverlaypanel.cpp
@@ -166,7 +166,8 @@ public:
if ( debugOverlayPanel )
{
debugOverlayPanel->SetParent( (vgui::Panel *)NULL );
- delete debugOverlayPanel;
+ debugOverlayPanel->MarkForDeletion();
+ debugOverlayPanel = NULL;
}
}
};
diff --git a/mp/src/game/client/vgui_fpspanel.cpp b/mp/src/game/client/vgui_fpspanel.cpp
index a1e88875..7458b702 100644
--- a/mp/src/game/client/vgui_fpspanel.cpp
+++ b/mp/src/game/client/vgui_fpspanel.cpp
@@ -395,7 +395,7 @@ public:
if ( fpsPanel )
{
fpsPanel->SetParent( (vgui::Panel *)NULL );
- delete fpsPanel;
+ fpsPanel->MarkForDeletion();
fpsPanel = NULL;
}
}
@@ -814,7 +814,7 @@ public:
if ( ioPanel )
{
ioPanel->SetParent( (vgui::Panel *)NULL );
- delete ioPanel;
+ ioPanel->MarkForDeletion();
ioPanel = NULL;
}
}
diff --git a/mp/src/game/client/vgui_loadingdiscpanel.cpp b/mp/src/game/client/vgui_loadingdiscpanel.cpp
index 94b2a9fb..2dc7dd8f 100644
--- a/mp/src/game/client/vgui_loadingdiscpanel.cpp
+++ b/mp/src/game/client/vgui_loadingdiscpanel.cpp
@@ -128,14 +128,14 @@ public:
if ( loadingDiscPanel )
{
loadingDiscPanel->SetParent( (vgui::Panel *)NULL );
- delete loadingDiscPanel;
+ loadingDiscPanel->MarkForDeletion();
loadingDiscPanel = NULL;
}
if ( m_pPauseDiscPanel )
{
m_pPauseDiscPanel->SetParent( (vgui::Panel *)NULL );
- delete m_pPauseDiscPanel;
+ m_pPauseDiscPanel->MarkForDeletion();
m_pPauseDiscPanel = NULL;
}
diff --git a/mp/src/game/client/vgui_messagechars.cpp b/mp/src/game/client/vgui_messagechars.cpp
index 1d1410f1..6bde7566 100644
--- a/mp/src/game/client/vgui_messagechars.cpp
+++ b/mp/src/game/client/vgui_messagechars.cpp
@@ -378,7 +378,7 @@ public:
if ( messageCharsPanel )
{
messageCharsPanel->SetParent( (vgui::Panel *)NULL );
- delete messageCharsPanel;
+ messageCharsPanel->MarkForDeletion();
messageCharsPanel = NULL;
}
}
diff --git a/mp/src/game/client/vgui_netgraphpanel.cpp b/mp/src/game/client/vgui_netgraphpanel.cpp
index 0f601438..adf3e4b9 100644
--- a/mp/src/game/client/vgui_netgraphpanel.cpp
+++ b/mp/src/game/client/vgui_netgraphpanel.cpp
@@ -492,6 +492,10 @@ void CNetGraphPanel::DrawTimes( vrect_t vrect, cmdinfo_t *cmdinfo, int x, int w,
{
i = ( m_OutgoingSequence - a ) & ( TIMINGS - 1 );
h = MIN( ( cmdinfo[i].cmd_lerp / 3.0 ) * LERP_HEIGHT, LERP_HEIGHT );
+ if ( h < 0 )
+ {
+ h = LERP_HEIGHT;
+ }
rcFill.x = x + w -a - 1;
rcFill.width = 1;
@@ -514,7 +518,9 @@ void CNetGraphPanel::DrawTimes( vrect_t vrect, cmdinfo_t *cmdinfo, int x, int w,
for ( j = start; j < h; j++ )
{
- DrawLine(&rcFill, colors[j + extrap_point], 255 );
+ int index = j + extrap_point;
+ Assert( (size_t)index < Q_ARRAYSIZE( colors ) );
+ DrawLine(&rcFill, colors[ index ], 255 );
rcFill.y--;
}
}
@@ -532,7 +538,9 @@ void CNetGraphPanel::DrawTimes( vrect_t vrect, cmdinfo_t *cmdinfo, int x, int w,
for ( j = 0; j < h; j++ )
{
- DrawLine(&rcFill, colors[j + oldh], 255 );
+ int index = j + oldh;
+ Assert( (size_t)index < Q_ARRAYSIZE( colors ) );
+ DrawLine(&rcFill, colors[ index ], 255 );
rcFill.y--;
}
}
@@ -1533,7 +1541,7 @@ public:
if ( netGraphPanel )
{
netGraphPanel->SetParent( (Panel *)NULL );
- delete netGraphPanel;
+ netGraphPanel->MarkForDeletion();
netGraphPanel = NULL;
}
}
diff --git a/mp/src/game/client/vgui_schemevisualizer.cpp b/mp/src/game/client/vgui_schemevisualizer.cpp
index b2a6f774..afde874d 100644
--- a/mp/src/game/client/vgui_schemevisualizer.cpp
+++ b/mp/src/game/client/vgui_schemevisualizer.cpp
@@ -178,11 +178,13 @@ void CSchemeVisualizer::AddFontsToList()
{
#ifdef POSIX
const char strOAccent[] = { (char)0xc3, (char)0x93, 0x00 }; // UTF-8 for U+00D3 (LATIN CAPITAL LETTER O WITH ACUTE)
+ const char strSkull[] = { (char)0xe2, (char)0x98, (char)0xa0, 0x00 };
#else
const uint8 strOAccent[] = { 0xd3, 0x00 };
+ const char strSkull[] = "";
#endif
// Stick an intl character in here to test accents (O')
- CFmtStr fmtText( "ABCDEFGHIJKLMN%sPQRSTUVWXYZabcdefhijklmnopqrstuvwxyz0123456789!@#$%%^&*()-_=+", strOAccent );
+ CFmtStr fmtText( "ABCDEFGHIJKLMN%sPQRSTUVWXYZ%sabcdefhijklmnopqrstuvwxyz0123456789!@#$%%^&*()-_=+", strOAccent, strSkull );
const int nFontCount = m_pViewScheme->GetFontCount();
@@ -288,4 +290,4 @@ void CSchemeVisualizer::OnTick()
// Update the list now
UpdateList( nType );
-} \ No newline at end of file
+}
diff --git a/mp/src/game/client/vgui_video.cpp b/mp/src/game/client/vgui_video.cpp
index 3badea3f..57323f40 100644
--- a/mp/src/game/client/vgui_video.cpp
+++ b/mp/src/game/client/vgui_video.cpp
@@ -348,7 +348,8 @@ bool VideoPanel_Create( unsigned int nXPos, unsigned int nYPos,
// Start it going
if ( pVideoPanel->BeginPlayback( pVideoFilename ) == false )
{
- delete pVideoPanel;
+ pVideoPanel->MarkForDeletion();
+ pVideoPanel = NULL;
return false;
}
diff --git a/mp/src/game/client/view.cpp b/mp/src/game/client/view.cpp
index 333a2756..d74d326e 100644
--- a/mp/src/game/client/view.cpp
+++ b/mp/src/game/client/view.cpp
@@ -110,9 +110,9 @@ static ConVar v_centerspeed( "v_centerspeed","500" );
#ifdef TF_CLIENT_DLL
// 54 degrees approximates a 35mm camera - we determined that this makes the viewmodels
// and motions look the most natural.
-ConVar v_viewmodel_fov( "viewmodel_fov", "54", FCVAR_ARCHIVE );
+ConVar v_viewmodel_fov( "viewmodel_fov", "54", FCVAR_ARCHIVE, "Sets the field-of-view for the viewmodel.", true, 0.1, true, 179.9 );
#else
-ConVar v_viewmodel_fov( "viewmodel_fov", "54", FCVAR_CHEAT );
+ConVar v_viewmodel_fov( "viewmodel_fov", "54", FCVAR_CHEAT, "Sets the field-of-view for the viewmodel.", true, 0.1, true, 179.9 );
#endif
ConVar mat_viewportscale( "mat_viewportscale", "1.0", FCVAR_ARCHIVE, "Scale down the main viewport (to reduce GPU impact on CPU profiling)", true, (1.0f / 640.0f), true, 1.0f );
ConVar mat_viewportupscale( "mat_viewportupscale", "1", FCVAR_ARCHIVE, "Scale the viewport back up" );
diff --git a/mp/src/game/client/weapon_selection.cpp b/mp/src/game/client/weapon_selection.cpp
index 66666b59..dc2adf4e 100644
--- a/mp/src/game/client/weapon_selection.cpp
+++ b/mp/src/game/client/weapon_selection.cpp
@@ -101,6 +101,7 @@ void CBaseHudWeaponSelection::Reset(void)
// Start hidden
m_bSelectionVisible = false;
m_flSelectionTime = gpGlobals->curtime;
+ gHUD.UnlockRenderGroup( gHUD.LookupRenderGroupIndexByName( "weapon_selection" ) );
}
//-----------------------------------------------------------------------------
@@ -207,6 +208,7 @@ bool CBaseHudWeaponSelection::IsInSelectionMode()
void CBaseHudWeaponSelection::OpenSelection( void )
{
m_bSelectionVisible = true;
+ gHUD.LockRenderGroup( gHUD.LookupRenderGroupIndexByName( "weapon_selection" ) );
}
//-----------------------------------------------------------------------------
@@ -215,6 +217,7 @@ void CBaseHudWeaponSelection::OpenSelection( void )
void CBaseHudWeaponSelection::HideSelection( void )
{
m_bSelectionVisible = false;
+ gHUD.UnlockRenderGroup( gHUD.LookupRenderGroupIndexByName( "weapon_selection" ) );
}
//-----------------------------------------------------------------------------