summaryrefslogtreecommitdiff
path: root/game/client/hl1
diff options
context:
space:
mode:
Diffstat (limited to 'game/client/hl1')
-rw-r--r--game/client/hl1/c_hl1mp_player.cpp602
-rw-r--r--game/client/hl1/c_hl1mp_player.h131
-rw-r--r--game/client/hl1/hl1_c_legacytempents.cpp101
-rw-r--r--game/client/hl1/hl1_c_player.cpp31
-rw-r--r--game/client/hl1/hl1_c_player.h50
-rw-r--r--game/client/hl1/hl1_c_rpg_rocket.cpp48
-rw-r--r--game/client/hl1/hl1_c_weapon__stubs.cpp34
-rw-r--r--game/client/hl1/hl1_clientmode.cpp168
-rw-r--r--game/client/hl1/hl1_clientmode.h35
-rw-r--r--game/client/hl1/hl1_clientscoreboard.cpp703
-rw-r--r--game/client/hl1/hl1_clientscoreboard.h65
-rw-r--r--game/client/hl1/hl1_fx_gauss.cpp238
-rw-r--r--game/client/hl1/hl1_fx_gibs.cpp306
-rw-r--r--game/client/hl1/hl1_fx_impacts.cpp34
-rw-r--r--game/client/hl1/hl1_fx_shelleject.cpp21
-rw-r--r--game/client/hl1/hl1_hud_ammo.cpp224
-rw-r--r--game/client/hl1/hl1_hud_battery.cpp184
-rw-r--r--game/client/hl1/hl1_hud_damageindicator.cpp331
-rw-r--r--game/client/hl1/hl1_hud_damagetiles.cpp322
-rw-r--r--game/client/hl1/hl1_hud_deathnotice.cpp358
-rw-r--r--game/client/hl1/hl1_hud_flashlight.cpp132
-rw-r--r--game/client/hl1/hl1_hud_geiger.cpp227
-rw-r--r--game/client/hl1/hl1_hud_health.cpp225
-rw-r--r--game/client/hl1/hl1_hud_history_resource.cpp307
-rw-r--r--game/client/hl1/hl1_hud_numbers.cpp113
-rw-r--r--game/client/hl1/hl1_hud_numbers.h35
-rw-r--r--game/client/hl1/hl1_hud_train.cpp143
-rw-r--r--game/client/hl1/hl1_hud_weaponselection.cpp670
28 files changed, 5838 insertions, 0 deletions
diff --git a/game/client/hl1/c_hl1mp_player.cpp b/game/client/hl1/c_hl1mp_player.cpp
new file mode 100644
index 0000000..53bfbbc
--- /dev/null
+++ b/game/client/hl1/c_hl1mp_player.cpp
@@ -0,0 +1,602 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "c_hl1mp_player.h"
+#include "c_basetempentity.h"
+#include "iinput.h"
+
+// Don't alias here
+#if defined( CHL1MP_Player )
+#undef CHL1MP_Player
+#endif
+
+
+//////////////////////////////////////////////////////////////////////
+
+
+class C_TEPlayerAnimEvent : public C_BaseTempEntity
+{
+public:
+ DECLARE_CLASS( C_TEPlayerAnimEvent, C_BaseTempEntity );
+ DECLARE_CLIENTCLASS();
+
+ virtual void PostDataUpdate( DataUpdateType_t updateType )
+ {
+ // Create the effect.
+ C_HL1MP_Player *pPlayer = dynamic_cast< C_HL1MP_Player* >( m_hPlayer.Get() );
+ if ( pPlayer && !pPlayer->IsDormant() )
+ {
+ pPlayer->DoAnimationEvent( (PlayerAnimEvent_t)m_iEvent.Get(), m_nData );
+ }
+ }
+
+public:
+ CNetworkHandle( CBasePlayer, m_hPlayer );
+ CNetworkVar( int, m_iEvent );
+ CNetworkVar( int, m_nData );
+};
+
+IMPLEMENT_CLIENTCLASS_EVENT( C_TEPlayerAnimEvent, DT_TEPlayerAnimEvent, CTEPlayerAnimEvent );
+
+// ------------------------------------------------------------------------------------------ //
+// Data tables and prediction tables.
+// ------------------------------------------------------------------------------------------ //
+
+BEGIN_RECV_TABLE_NOBASE( C_TEPlayerAnimEvent, DT_TEPlayerAnimEvent )
+ RecvPropEHandle( RECVINFO( m_hPlayer ) ),
+ RecvPropInt( RECVINFO( m_iEvent ) ),
+ RecvPropInt( RECVINFO( m_nData ) )
+END_RECV_TABLE()
+
+IMPLEMENT_CLIENTCLASS_DT( C_HL1MP_Player, DT_HL1MP_Player, CHL1MP_Player )
+ RecvPropFloat( RECVINFO( m_angEyeAngles[0] ) ),
+ RecvPropFloat( RECVINFO( m_angEyeAngles[1] ) ),
+ RecvPropEHandle( RECVINFO( m_hRagdoll ) ),
+ RecvPropInt( RECVINFO( m_iSpawnInterpCounter ) ),
+ RecvPropInt( RECVINFO( m_iRealSequence ) ),
+// RecvPropDataTable( RECVINFO_DT( m_Shared ), 0, &REFERENCE_RECV_TABLE( DT_TFCPlayerShared ) )
+END_RECV_TABLE()
+
+BEGIN_PREDICTION_DATA( C_HL1MP_Player )
+END_PREDICTION_DATA()
+
+/////////////////////////////////////////////////////////////////////
+
+static ConVar cl_playermodel( "cl_playermodel", "none", FCVAR_USERINFO | FCVAR_ARCHIVE | FCVAR_SERVER_CAN_EXECUTE, "Default Player Model");
+
+C_HL1MP_Player::C_HL1MP_Player( void ) :
+ m_iv_angEyeAngles( "C_HL1MP_Player::m_iv_angEyeAngles" )
+{
+ m_PlayerAnimState = CreatePlayerAnimState( this );
+ m_angEyeAngles.Init();
+
+ m_fLastPredFreeze = -1;
+
+// cant interpolate ... buggy? it keeps resetting the angle to 0,0,0
+// AddVar( &m_angEyeAngles, &m_iv_angEyeAngles, LATCH_SIMULATION_VAR );
+}
+
+C_HL1MP_Player::~C_HL1MP_Player()
+{
+ m_PlayerAnimState->Release();
+}
+
+const QAngle& C_HL1MP_Player::GetRenderAngles()
+{
+ if ( IsRagdoll() )
+ {
+ return vec3_angle;
+ }
+ else
+ {
+ return m_PlayerAnimState->GetRenderAngles();
+ }
+}
+
+void C_HL1MP_Player::UpdateClientSideAnimation()
+{
+ // Update the animation data. It does the local check here so this works when using
+ // a third-person camera (and we don't have valid player angles).
+ if ( this == C_BasePlayer::GetLocalPlayer() )
+ m_PlayerAnimState->Update( EyeAngles()[YAW], m_angEyeAngles[PITCH] );
+ else
+ m_PlayerAnimState->Update( m_angEyeAngles[YAW], m_angEyeAngles[PITCH] );
+
+ BaseClass::UpdateClientSideAnimation();
+}
+
+
+void C_HL1MP_Player::DoAnimationEvent( PlayerAnimEvent_t event, int nData )
+{
+ m_PlayerAnimState->DoAnimationEvent( event, nData );
+}
+
+
+void C_HL1MP_Player::ProcessMuzzleFlashEvent()
+{
+#if 0
+ // Reenable when the weapons have muzzle flash attachments in the right spot.
+ if ( this != C_BasePlayer::GetLocalPlayer() )
+ {
+ Vector vAttachment;
+ QAngle dummyAngles;
+
+ C_WeaponTFCBase *pWeapon = m_Shared.GetActiveTFCWeapon();
+
+ if ( pWeapon )
+ {
+ int iAttachment = pWeapon->LookupAttachment( "muzzle_flash" );
+
+ if ( iAttachment > 0 )
+ {
+ float flScale = 1;
+ pWeapon->GetAttachment( iAttachment, vAttachment, dummyAngles );
+
+ // The way the models are setup, the up vector points along the barrel.
+ Vector vForward, vRight, vUp;
+ AngleVectors( dummyAngles, &vForward, &vRight, &vUp );
+ VectorAngles( vUp, dummyAngles );
+
+ FX_MuzzleEffect( vAttachment, dummyAngles, flScale, 0, NULL, true );
+ }
+ }
+ }
+
+ Vector vAttachment;
+ QAngle dummyAngles;
+
+ bool bFoundAttachment = GetAttachment( 1, vAttachment, dummyAngles );
+ // If we have an attachment, then stick a light on it.
+ if ( bFoundAttachment )
+ {
+ dlight_t *el = effects->CL_AllocDlight( LIGHT_INDEX_MUZZLEFLASH + index );
+ el->origin = vAttachment;
+ el->radius = 24;
+ el->decay = el->radius / 0.05f;
+ el->die = gpGlobals->curtime + 0.05f;
+ el->color.r = 255;
+ el->color.g = 192;
+ el->color.b = 64;
+ el->color.exponent = 5;
+ }
+#endif
+}
+
+
+void C_HL1MP_Player::Spawn( void )
+{
+ BaseClass::Spawn();
+
+// SetModel( "models/player/mp/barney/barney.mdl" );
+
+ m_iSpawnInterpCounterCache = 0;
+
+ UpdateVisibility();
+}
+
+void C_HL1MP_Player::AddEntity( void )
+{
+ BaseClass::AddEntity();
+
+ //m_PlayerAnimState.Update();
+
+// SetLocalAnglesDim( X_INDEX, 0 );
+}
+
+void C_HL1MP_Player::OnDataChanged( DataUpdateType_t type )
+{
+ BaseClass::OnDataChanged( type );
+
+ if ( type == DATA_UPDATE_CREATED )
+ {
+ SetNextClientThink( CLIENT_THINK_ALWAYS );
+ }
+
+ UpdateVisibility();
+}
+
+C_BaseAnimating *C_HL1MP_Player::BecomeRagdollOnClient()
+{
+ // Handled elsewhere
+ return NULL;
+}
+
+void C_HL1MP_Player::PreThink( void )
+{
+ BaseClass::PreThink();
+ return;
+
+ QAngle vTempAngles = GetLocalAngles();
+
+ if ( GetLocalPlayer() == this )
+ {
+ vTempAngles[PITCH] = EyeAngles()[PITCH];
+ }
+ else
+ {
+ vTempAngles[PITCH] = m_angEyeAngles[PITCH];
+ }
+
+ if ( vTempAngles[YAW] < 0.0f )
+ {
+ vTempAngles[YAW] += 360.0f;
+ }
+
+ SetLocalAngles( vTempAngles );
+
+ BaseClass::PreThink();
+#if 0
+ HandleSpeedChanges();
+
+ if ( m_HL2Local.m_flSuitPower <= 0.0f )
+ {
+ if( IsSprinting() )
+ {
+ StopSprinting();
+ }
+ }
+#endif
+}
+
+void C_HL1MP_Player::PostDataUpdate( DataUpdateType_t updateType )
+{
+ // C_BaseEntity assumes we're networking the entity's angles, so pretend that it
+ // networked the same value we already have.
+ SetNetworkAngles( GetLocalAngles() );
+
+ BaseClass::PostDataUpdate( updateType );
+}
+
+
+void C_HL1MP_Player::ClientThink( void )
+{
+ BaseClass::ClientThink();
+// m_PlayerAnimState.Update();
+}
+
+
+//HL1MPRAGDOLL
+
+
+IMPLEMENT_CLIENTCLASS_DT_NOBASE( C_HL1MPRagdoll, DT_HL1MPRagdoll, CHL1MPRagdoll )
+ RecvPropVector( RECVINFO(m_vecRagdollOrigin) ),
+ RecvPropEHandle( RECVINFO( m_hPlayer ) ),
+ RecvPropInt( RECVINFO( m_nModelIndex ) ),
+ RecvPropInt( RECVINFO(m_nForceBone) ),
+ RecvPropVector( RECVINFO(m_vecForce) ),
+ RecvPropVector( RECVINFO( m_vecRagdollVelocity ) )
+END_RECV_TABLE()
+
+
+
+C_HL1MPRagdoll::C_HL1MPRagdoll()
+{
+
+}
+
+C_HL1MPRagdoll::~C_HL1MPRagdoll()
+{
+ PhysCleanupFrictionSounds( this );
+
+ if ( m_hPlayer )
+ {
+ m_hPlayer->CreateModelInstance();
+ }
+}
+
+void C_HL1MPRagdoll::Interp_Copy( C_BaseAnimatingOverlay *pSourceEntity )
+{
+ if ( !pSourceEntity )
+ return;
+
+ VarMapping_t *pSrc = pSourceEntity->GetVarMapping();
+ VarMapping_t *pDest = GetVarMapping();
+
+ // Find all the VarMapEntry_t's that represent the same variable.
+ for ( int i = 0; i < pDest->m_Entries.Count(); i++ )
+ {
+ VarMapEntry_t *pDestEntry = &pDest->m_Entries[i];
+ const char *pszName = pDestEntry->watcher->GetDebugName();
+ for ( int j=0; j < pSrc->m_Entries.Count(); j++ )
+ {
+ VarMapEntry_t *pSrcEntry = &pSrc->m_Entries[j];
+ if ( !Q_strcmp( pSrcEntry->watcher->GetDebugName(), pszName ) )
+ {
+ pDestEntry->watcher->Copy( pSrcEntry->watcher );
+ break;
+ }
+ }
+ }
+}
+
+void C_HL1MPRagdoll::ImpactTrace( trace_t *pTrace, int iDamageType, const char *pCustomImpactName )
+{
+ IPhysicsObject *pPhysicsObject = VPhysicsGetObject();
+
+ if( !pPhysicsObject )
+ return;
+
+ Vector dir = pTrace->endpos - pTrace->startpos;
+
+ if ( iDamageType == DMG_BLAST )
+ {
+ dir *= 4000; // adjust impact strenght
+
+ // apply force at object mass center
+ pPhysicsObject->ApplyForceCenter( dir );
+ }
+ else
+ {
+ Vector hitpos;
+
+ VectorMA( pTrace->startpos, pTrace->fraction, dir, hitpos );
+ VectorNormalize( dir );
+
+ dir *= 4000; // adjust impact strenght
+
+ // apply force where we hit it
+ pPhysicsObject->ApplyForceOffset( dir, hitpos );
+
+ }
+
+ m_pRagdoll->ResetRagdollSleepAfterTime();
+}
+
+
+void C_HL1MP_Player::CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov )
+{
+ if ( m_lifeState != LIFE_ALIVE )
+ {
+ Vector origin = EyePosition();
+
+ IRagdoll *pRagdoll = GetRepresentativeRagdoll();
+
+ if ( pRagdoll )
+ {
+ origin = pRagdoll->GetRagdollOrigin();
+ origin.z += VEC_DEAD_VIEWHEIGHT_SCALED( this ).z; // look over ragdoll, not through
+ }
+
+ BaseClass::CalcView( eyeOrigin, eyeAngles, zNear, zFar, fov );
+
+ eyeOrigin = origin;
+
+ Vector vForward;
+ AngleVectors( eyeAngles, &vForward );
+
+ VectorNormalize( vForward );
+ VectorMA( origin, -CHASE_CAM_DISTANCE_MAX, vForward, eyeOrigin );
+
+ Vector WALL_MIN( -WALL_OFFSET, -WALL_OFFSET, -WALL_OFFSET );
+ Vector WALL_MAX( WALL_OFFSET, WALL_OFFSET, WALL_OFFSET );
+
+ trace_t trace; // clip against world
+ C_BaseEntity::PushEnableAbsRecomputations( false ); // HACK don't recompute positions while doing RayTrace
+ UTIL_TraceHull( origin, eyeOrigin, WALL_MIN, WALL_MAX, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trace );
+ C_BaseEntity::PopEnableAbsRecomputations();
+
+ if (trace.fraction < 1.0)
+ {
+ eyeOrigin = trace.endpos;
+ }
+
+ return;
+ }
+
+ BaseClass::CalcView( eyeOrigin, eyeAngles, zNear, zFar, fov );
+}
+
+IRagdoll* C_HL1MP_Player::GetRepresentativeRagdoll() const
+{
+ if ( m_hRagdoll.Get() )
+ {
+ C_HL1MPRagdoll *pRagdoll = (C_HL1MPRagdoll*)m_hRagdoll.Get();
+
+ return pRagdoll->GetIRagdoll();
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+void C_HL1MPRagdoll::CreateHL1MPRagdoll( void )
+{
+ // First, initialize all our data. If we have the player's entity on our client,
+ // then we can make ourselves start out exactly where the player is.
+ C_HL1MP_Player *pPlayer = dynamic_cast< C_HL1MP_Player* >( m_hPlayer.Get() );
+
+ if ( pPlayer && !pPlayer->IsDormant() )
+ {
+ // move my current model instance to the ragdoll's so decals are preserved.
+ pPlayer->SnatchModelInstance( this );
+
+ VarMapping_t *varMap = GetVarMapping();
+
+ // Copy all the interpolated vars from the player entity.
+ // The entity uses the interpolated history to get bone velocity.
+ bool bRemotePlayer = (pPlayer != C_BasePlayer::GetLocalPlayer());
+ if ( bRemotePlayer )
+ {
+ Interp_Copy( pPlayer );
+
+ SetAbsAngles( pPlayer->GetRenderAngles() );
+ GetRotationInterpolator().Reset();
+
+ m_flAnimTime = pPlayer->m_flAnimTime;
+ SetSequence( pPlayer->GetSequence() );
+ m_flPlaybackRate = pPlayer->GetPlaybackRate();
+ }
+ else
+ {
+ // This is the local player, so set them in a default
+ // pose and slam their velocity, angles and origin
+ SetAbsOrigin( m_vecRagdollOrigin );
+
+ SetAbsAngles( pPlayer->GetRenderAngles() );
+
+ SetAbsVelocity( m_vecRagdollVelocity );
+
+ int iSeq = pPlayer->GetSequence();
+ if ( iSeq == -1 )
+ {
+ Assert( false ); // missing walk_lower?
+ iSeq = 0;
+ }
+
+ SetSequence( iSeq ); // walk_lower, basic pose
+ SetCycle( 0.0 );
+
+ Interp_Reset( varMap );
+ }
+ }
+ else
+ {
+ // overwrite network origin so later interpolation will
+ // use this position
+ SetNetworkOrigin( m_vecRagdollOrigin );
+
+ SetAbsOrigin( m_vecRagdollOrigin );
+ SetAbsVelocity( m_vecRagdollVelocity );
+
+ Interp_Reset( GetVarMapping() );
+
+ }
+
+ SetModelIndex( m_nModelIndex );
+
+ // Make us a ragdoll..
+ m_nRenderFX = kRenderFxRagdoll;
+
+ matrix3x4_t boneDelta0[MAXSTUDIOBONES];
+ matrix3x4_t boneDelta1[MAXSTUDIOBONES];
+ matrix3x4_t currentBones[MAXSTUDIOBONES];
+ const float boneDt = 0.05f;
+
+ if ( pPlayer && !pPlayer->IsDormant() )
+ {
+ pPlayer->GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
+ }
+ else
+ {
+ GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
+ }
+
+ InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
+}
+
+
+void C_HL1MPRagdoll::OnDataChanged( DataUpdateType_t type )
+{
+ BaseClass::OnDataChanged( type );
+
+ if ( type == DATA_UPDATE_CREATED )
+ {
+ CreateHL1MPRagdoll();
+ }
+}
+
+IRagdoll* C_HL1MPRagdoll::GetIRagdoll() const
+{
+ return m_pRagdoll;
+}
+
+void C_HL1MPRagdoll::UpdateOnRemove( void )
+{
+ VPhysicsSetObject( NULL );
+
+ BaseClass::UpdateOnRemove();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: clear out any face/eye values stored in the material system
+//-----------------------------------------------------------------------------
+void C_HL1MPRagdoll::SetupWeights( const matrix3x4_t *pBoneToWorld, int nFlexWeightCount, float *pFlexWeights, float *pFlexDelayedWeights )
+{
+ BaseClass::SetupWeights( pBoneToWorld, nFlexWeightCount, pFlexWeights, pFlexDelayedWeights );
+
+ static float destweight[128];
+ static bool bIsInited = false;
+
+ CStudioHdr *hdr = GetModelPtr();
+ if ( !hdr )
+ return;
+
+ int nFlexDescCount = hdr->numflexdesc();
+ if ( nFlexDescCount )
+ {
+ Assert( !pFlexDelayedWeights );
+ memset( pFlexWeights, 0, nFlexWeightCount * sizeof(float) );
+ }
+
+ if ( m_iEyeAttachment > 0 )
+ {
+ matrix3x4_t attToWorld;
+ if (GetAttachment( m_iEyeAttachment, attToWorld ))
+ {
+ Vector local, tmp;
+ local.Init( 1000.0f, 0.0f, 0.0f );
+ VectorTransform( local, attToWorld, tmp );
+ modelrender->SetViewTarget( GetModelPtr(), GetBody(), tmp );
+ }
+ }
+}
+
+bool C_HL1MP_Player::ShouldDraw( void )
+{
+ if ( !IsAlive() )
+ return false;
+
+ if ( IsLocalPlayer() && IsRagdoll() )
+ return true;
+
+ if ( IsRagdoll() )
+ return false;
+
+ return BaseClass::ShouldDraw();
+}
+
+bool C_HL1MP_Player::ShouldPredict( void )
+{
+ // Do this before calling into baseclass so prediction data block gets allocated
+ if ( IsLocalPlayer() )
+ {
+#if 0
+ // Disable prediction when player hops onto a moving train or elevator :-/
+ if ( GetGroundEntity() && GetGroundEntity()->GetMoveType() == MOVETYPE_PUSH )
+ {
+ Vector vel = GetGroundEntity()->GetLocalVelocity();
+ if ( vel.Length() > 0.002f )
+ {
+ m_fLastPredFreeze = gpGlobals->curtime;
+ }
+ }
+
+ // disable prediction for 3 seconds after touching a moving entity
+ if ( ( gpGlobals->curtime - m_fLastPredFreeze ) < 3 )
+ {
+ if ( GetPredictable() )
+ {
+ QuickShutdownPredictable();
+ }
+
+ return false;
+ }
+
+ if ( !GetPredictable() && IsIntermediateDataAllocated() )
+ {
+ QuickInitPredictable();
+ }
+#endif
+
+ return true;
+ }
+
+ return false;
+}
diff --git a/game/client/hl1/c_hl1mp_player.h b/game/client/hl1/c_hl1mp_player.h
new file mode 100644
index 0000000..1d47850
--- /dev/null
+++ b/game/client/hl1/c_hl1mp_player.h
@@ -0,0 +1,131 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#ifndef HL1MP_PLAYER_H
+#define HL1MP_PLAYER_H
+#pragma once
+
+#include "cbase.h"
+#include "hl1_c_player.h"
+#include "hl1_player_shared.h"
+
+
+class C_HL1MP_Player : public C_HL1_Player
+{
+public:
+ DECLARE_CLASS( C_HL1MP_Player, C_HL1_Player );
+ DECLARE_CLIENTCLASS();
+ DECLARE_PREDICTABLE();
+ DECLARE_INTERPOLATION();
+
+ C_HL1MP_Player( void );
+ ~C_HL1MP_Player();
+
+ virtual const QAngle& GetRenderAngles();
+ virtual void UpdateClientSideAnimation();
+ virtual void ProcessMuzzleFlashEvent();
+
+ void DoAnimationEvent( PlayerAnimEvent_t event, int nData = 0 );
+
+ virtual bool ShouldPredict( void );
+ virtual void CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov );
+ IRagdoll* GetRepresentativeRagdoll() const;
+
+ virtual void Spawn( void );
+ virtual void AddEntity( void );
+ virtual bool ShouldDraw( void );
+ virtual void OnDataChanged( DataUpdateType_t type );
+ virtual void PostDataUpdate( DataUpdateType_t updateType );
+ virtual void ClientThink( void );
+ virtual C_BaseAnimating *BecomeRagdollOnClient();
+ //QAngle GetAnimEyeAngles( void ) { return m_angEyeAngles; }
+ const QAngle& EyeAngles( void )
+ {
+ if ( IsLocalPlayer() )
+ {
+ return BaseClass::EyeAngles();
+ }
+ else
+ {
+ return m_angEyeAngles;
+ }
+ }
+
+ virtual ShadowType_t ShadowCastType()
+ {
+ if ( !IsVisible() )
+ return SHADOWS_NONE;
+
+ return SHADOWS_RENDER_TO_TEXTURE_DYNAMIC;
+ }
+
+ void PreThink( void );
+
+ int m_iRealSequence;
+
+private:
+ C_HL1MP_Player( const C_HL1MP_Player & );
+
+ EHANDLE m_hRagdoll;
+
+ QAngle m_angEyeAngles;
+
+ CInterpolatedVar< QAngle > m_iv_angEyeAngles;
+
+ IHL1MPPlayerAnimState* m_PlayerAnimState;
+
+ int m_iSpawnInterpCounter;
+ int m_iSpawnInterpCounterCache;
+
+ float m_fLastPredFreeze;
+};
+
+
+class C_HL1MPRagdoll : public C_BaseAnimatingOverlay
+{
+public:
+ DECLARE_CLASS( C_HL1MPRagdoll, C_BaseAnimatingOverlay );
+ DECLARE_CLIENTCLASS();
+
+ C_HL1MPRagdoll();
+ ~C_HL1MPRagdoll();
+
+ virtual void OnDataChanged( DataUpdateType_t type );
+
+ int GetPlayerEntIndex() const;
+ IRagdoll* GetIRagdoll() const;
+
+ void ImpactTrace( trace_t *pTrace, int iDamageType, const char *pCustomImpactName );
+ void UpdateOnRemove( void );
+ virtual void SetupWeights( const matrix3x4_t *pBoneToWorld, int nFlexWeightCount, float *pFlexWeights, float *pFlexDelayedWeights );
+
+private:
+
+ C_HL1MPRagdoll( const C_HL1MPRagdoll & ) {}
+
+ void Interp_Copy( C_BaseAnimatingOverlay *pSourceEntity );
+ void CreateHL1MPRagdoll( void );
+
+private:
+
+ EHANDLE m_hPlayer;
+ CNetworkVector( m_vecRagdollVelocity );
+ CNetworkVector( m_vecRagdollOrigin );
+};
+
+
+inline C_HL1MP_Player *ToHL1MPPlayer( CBaseEntity *pEntity )
+{
+ if ( !pEntity || !pEntity->IsPlayer() )
+ return NULL;
+
+ return dynamic_cast<C_HL1MP_Player*>( pEntity );
+}
+
+
+
+#endif
diff --git a/game/client/hl1/hl1_c_legacytempents.cpp b/game/client/hl1/hl1_c_legacytempents.cpp
new file mode 100644
index 0000000..a107cc4
--- /dev/null
+++ b/game/client/hl1/hl1_c_legacytempents.cpp
@@ -0,0 +1,101 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//===========================================================================//
+
+
+#include "cbase.h"
+#include "tempentity.h"
+#include "tempent.h"
+#include "c_te_legacytempents.h"
+
+
+#define NUM_MUZZLE_SPRITES 3
+
+
+class CHL1TempEnts : public CTempEnts
+{
+public:
+ CHL1TempEnts( void ) { };
+ virtual ~CHL1TempEnts( void ) { };
+
+public:
+ virtual void Init( void );
+ virtual void LevelInit();
+ void MuzzleFlash( const Vector &pos1, const QAngle &angles, int type, ClientEntityHandle_t hEntity, bool firstPerson = false );
+
+private:
+ CHL1TempEnts( const CHL1TempEnts & );
+
+private:
+ struct model_t *m_pSpriteMuzzleFlash[ NUM_MUZZLE_SPRITES ];
+};
+
+
+// Temp entity interface
+static CHL1TempEnts g_TempEnts;
+// Expose to rest of the client .dll
+ITempEnts *tempents = ( ITempEnts * )&g_TempEnts;
+
+void CHL1TempEnts::LevelInit()
+{
+ CTempEnts::LevelInit();
+
+ m_pSpriteMuzzleFlash[0] = (model_t *)engine->LoadModel( "sprites/muzzleflash1.vmt" );
+ m_pSpriteMuzzleFlash[1] = (model_t *)engine->LoadModel( "sprites/muzzleflash2.vmt" );
+ m_pSpriteMuzzleFlash[2] = (model_t *)engine->LoadModel( "sprites/muzzleflash3.vmt" );
+}
+
+void CHL1TempEnts::Init( void )
+{
+ CTempEnts::Init();
+
+ m_pSpriteMuzzleFlash[0] = (model_t *)engine->LoadModel( "sprites/muzzleflash1.vmt" );
+ m_pSpriteMuzzleFlash[1] = (model_t *)engine->LoadModel( "sprites/muzzleflash2.vmt" );
+ m_pSpriteMuzzleFlash[2] = (model_t *)engine->LoadModel( "sprites/muzzleflash3.vmt" );
+}
+
+
+void CHL1TempEnts::MuzzleFlash( const Vector& pos1, const QAngle& angles, int type, ClientEntityHandle_t hEntity, bool firstPerson )
+{
+ C_LocalTempEntity *pTemp;
+ int index;
+ float scale;
+ int frameCount;
+ QAngle ang;
+
+ index = type % 10;
+ index = index % NUM_MUZZLE_SPRITES;
+
+ scale = ( type / 10 ) * 0.1;
+ if ( scale == 0 )
+ scale = 0.5;
+
+ frameCount = modelinfo->GetModelFrameCount( m_pSpriteMuzzleFlash[index] );
+
+ // DevMsg( 1,"%d %f\n", index, scale );
+ pTemp = TempEntAlloc( pos1, ( model_t * )m_pSpriteMuzzleFlash[index] );
+ if (!pTemp)
+ return;
+
+ pTemp->SetRenderMode( kRenderTransAdd );
+ pTemp->m_nRenderFX = 0;
+ pTemp->SetRenderColor( 255, 255, 255, 255 );
+ pTemp->m_flSpriteScale = scale;
+ pTemp->SetAbsOrigin( pos1 );
+ pTemp->die = gpGlobals->curtime + 0.01;
+ pTemp->m_flFrame = random->RandomInt( 0, frameCount-1 );
+ pTemp->m_flFrameMax = frameCount - 1;
+
+ ang = vec3_angle;
+ if (index == 0)
+ {
+ ang.z = random->RandomInt( 0, 20 );
+ }
+ else
+ {
+ ang.z = random->RandomInt( 0, 359 );
+ }
+ pTemp->SetAbsAngles( ang );
+}
diff --git a/game/client/hl1/hl1_c_player.cpp b/game/client/hl1/hl1_c_player.cpp
new file mode 100644
index 0000000..e7e1e56
--- /dev/null
+++ b/game/client/hl1/hl1_c_player.cpp
@@ -0,0 +1,31 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "hl1_c_player.h"
+
+ConVar cl_npc_speedmod_intime( "cl_npc_speedmod_intime", "0.25", FCVAR_CLIENTDLL | FCVAR_ARCHIVE );
+ConVar cl_npc_speedmod_outtime( "cl_npc_speedmod_outtime", "1.5", FCVAR_CLIENTDLL | FCVAR_ARCHIVE );
+
+#if defined( CHL1_Player )
+#undef CHL1_Player
+#endif
+
+IMPLEMENT_CLIENTCLASS_DT( C_HL1_Player, DT_HL1Player, CHL1_Player )
+ RecvPropInt( RECVINFO( m_bHasLongJump ) ),
+ RecvPropInt( RECVINFO( m_nFlashBattery ) ),
+ RecvPropBool( RECVINFO( m_bIsPullingObject ) ),
+
+ RecvPropFloat( RECVINFO( m_flStartCharge ) ),
+ RecvPropFloat( RECVINFO( m_flAmmoStartCharge ) ),
+ RecvPropFloat( RECVINFO( m_flPlayAftershock ) ),
+ RecvPropFloat( RECVINFO( m_flNextAmmoBurn ) )
+END_RECV_TABLE()
+
+C_HL1_Player::C_HL1_Player()
+{
+
+} \ No newline at end of file
diff --git a/game/client/hl1/hl1_c_player.h b/game/client/hl1/hl1_c_player.h
new file mode 100644
index 0000000..e94cbea
--- /dev/null
+++ b/game/client/hl1/hl1_c_player.h
@@ -0,0 +1,50 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#ifndef C_HL1_PLAYER_H
+#define C_HL1_PLAYER_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "c_baseplayer.h"
+
+
+#define CHL1_Player C_HL1_Player
+
+class C_HL1_Player : public C_BasePlayer
+{
+public:
+ DECLARE_CLASS( C_HL1_Player, C_BasePlayer );
+ DECLARE_CLIENTCLASS();
+
+ C_HL1_Player();
+
+ bool IsPullingObject() { return m_bIsPullingObject; }
+
+ CNetworkVar( bool, m_bHasLongJump );
+ CNetworkVar( int, m_nFlashBattery );
+ CNetworkVar( bool, m_bIsPullingObject );
+
+ CNetworkVar( float, m_flStartCharge );
+ CNetworkVar( float, m_flAmmoStartCharge );
+ CNetworkVar( float, m_flPlayAftershock );
+ CNetworkVar( float, m_flNextAmmoBurn ); // while charging, when to absorb another unit of player's ammo?
+
+private:
+ C_HL1_Player( const C_HL1_Player & );
+
+};
+
+inline C_HL1_Player *ToHL1Player( CBaseEntity *pEntity )
+{
+ if ( !pEntity || !pEntity->IsPlayer() )
+ return NULL;
+
+ return dynamic_cast<C_HL1_Player*>( pEntity );
+}
+
+#endif //C_HL1_PLAYER_H \ No newline at end of file
diff --git a/game/client/hl1/hl1_c_rpg_rocket.cpp b/game/client/hl1/hl1_c_rpg_rocket.cpp
new file mode 100644
index 0000000..c8dc3ee
--- /dev/null
+++ b/game/client/hl1/hl1_c_rpg_rocket.cpp
@@ -0,0 +1,48 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+
+#include "cbase.h"
+#include "dlight.h"
+#include "tempent.h"
+#include "iefx.h"
+#include "c_te_legacytempents.h"
+#include "basegrenade_shared.h"
+
+
+class C_RpgRocket : public C_BaseGrenade
+{
+public:
+ DECLARE_CLASS( C_RpgRocket, C_BaseGrenade );
+ DECLARE_CLIENTCLASS();
+
+public:
+ C_RpgRocket( void ) { }
+ C_RpgRocket( const C_RpgRocket & );
+
+public:
+ void CreateLightEffects( void );
+};
+
+
+IMPLEMENT_CLIENTCLASS_DT( C_RpgRocket, DT_RpgRocket, CRpgRocket )
+END_RECV_TABLE()
+
+
+void C_RpgRocket::CreateLightEffects( void )
+{
+ dlight_t *dl;
+ if ( IsEffectActive(EF_DIMLIGHT) )
+ {
+ dl = effects->CL_AllocDlight ( index );
+ dl->origin = GetAbsOrigin();
+ dl->color.r = dl->color.g = dl->color.b = 100;
+ dl->radius = 200;
+ dl->die = gpGlobals->curtime + 0.001;
+
+ tempents->RocketFlare( GetAbsOrigin() );
+ }
+}
diff --git a/game/client/hl1/hl1_c_weapon__stubs.cpp b/game/client/hl1/hl1_c_weapon__stubs.cpp
new file mode 100644
index 0000000..8abc64c
--- /dev/null
+++ b/game/client/hl1/hl1_c_weapon__stubs.cpp
@@ -0,0 +1,34 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+
+#include "cbase.h"
+#include "c_weapon__stubs.h"
+#include "hl1_basecombatweapon_shared.h"
+
+
+STUB_WEAPON_CLASS( foo_weapon_basebludgeonweapon, BaseBludgeonWeapon, C_BaseCombatWeapon );
+
+STUB_WEAPON_CLASS( cycler_weapon, WeaponCycler, C_BaseCombatWeapon );
+STUB_WEAPON_CLASS( weapon_physcannon, PhysgunCannon, C_BaseCombatWeapon );
+
+// HL1 stuff
+//STUB_WEAPON_CLASS( weapon_357, Weapon357, C_BaseHL1CombatWeapon );
+//STUB_WEAPON_CLASS( weapon_crossbow, WeaponCrossbow, C_BaseHL1CombatWeapon );
+//STUB_WEAPON_CLASS( weapon_crowbar, WeaponCrowbar, C_BaseHL1CombatWeapon );
+//STUB_WEAPON_CLASS( weapon_egon, WeaponEgon, C_BaseHL1CombatWeapon );
+//STUB_WEAPON_CLASS( weapon_gauss, WeaponGauss, C_BaseHL1CombatWeapon );
+//STUB_WEAPON_CLASS( weapon_glock, WeaponGlock, C_BaseHL1CombatWeapon );
+//STUB_WEAPON_CLASS( weapon_handgrenade, WeaponHandGrenade, C_BaseHL1CombatWeapon );
+//STUB_WEAPON_CLASS( weapon_hornetgun, WeaponHgun, C_BaseHL1CombatWeapon );
+//STUB_WEAPON_CLASS( weapon_mp5, WeaponMP5, C_BaseHL1CombatWeapon );
+//STUB_WEAPON_CLASS( weapon_rpg, WeaponRPG, C_BaseHL1CombatWeapon );
+//STUB_WEAPON_CLASS( weapon_satchel, WeaponSatchel, C_BaseHL1CombatWeapon );
+//STUB_WEAPON_CLASS( weapon_shotgun, WeaponShotgun, C_BaseHL1CombatWeapon );
+STUB_WEAPON_CLASS( weapon_snark, WeaponSnark, C_BaseHL1CombatWeapon );
+STUB_WEAPON_CLASS( weapon_tripmine, WeaponTripMine, C_BaseHL1CombatWeapon );
+STUB_WEAPON_CLASS( weapon_cubemap, WeaponCubemap, C_BaseCombatWeapon );
diff --git a/game/client/hl1/hl1_clientmode.cpp b/game/client/hl1/hl1_clientmode.cpp
new file mode 100644
index 0000000..cf1e92e
--- /dev/null
+++ b/game/client/hl1/hl1_clientmode.cpp
@@ -0,0 +1,168 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#include "cbase.h"
+#include "ivmodemanager.h"
+#include "clientmode_hlnormal.h"
+#include "hl1_clientmode.h"
+#include "hl1_clientscoreboard.h"
+
+// default FOV for HL1
+ConVar default_fov( "default_fov", "90", FCVAR_CHEAT );
+ConVar fov_desired( "fov_desired", "90", FCVAR_ARCHIVE | FCVAR_USERINFO, "Sets the base field-of-view.", true, 75.0, true, 90.0 );
+
+// The current client mode. Always ClientModeNormal in HL.
+IClientMode *g_pClientMode = NULL;
+
+class CHLModeManager : public IVModeManager
+{
+public:
+ CHLModeManager( void );
+ virtual ~CHLModeManager( void );
+
+ virtual void Init( void );
+ virtual void SwitchMode( bool commander, bool force );
+ virtual void OverrideView( CViewSetup *pSetup );
+ virtual void CreateMove( float flInputSampleTime, CUserCmd *cmd );
+ virtual void LevelInit( const char *newmap );
+ virtual void LevelShutdown( void );
+};
+
+CHLModeManager::CHLModeManager( void )
+{
+}
+
+CHLModeManager::~CHLModeManager( void )
+{
+}
+
+void CHLModeManager::Init( void )
+{
+ g_pClientMode = GetClientModeNormal();
+}
+
+void CHLModeManager::SwitchMode( bool commander, bool force )
+{
+}
+
+void CHLModeManager::OverrideView( CViewSetup *pSetup )
+{
+}
+
+void CHLModeManager::CreateMove( float flInputSampleTime, CUserCmd *cmd )
+{
+}
+
+void CHLModeManager::LevelInit( const char *newmap )
+{
+ g_pClientMode->LevelInit( newmap );
+}
+
+void CHLModeManager::LevelShutdown( void )
+{
+ g_pClientMode->LevelShutdown();
+}
+
+static CHLModeManager g_HLModeManager;
+IVModeManager *modemanager = &g_HLModeManager;
+
+//-----------------------------------------------------------------------------
+// Purpose: this is the viewport that contains all the hud elements
+//-----------------------------------------------------------------------------
+class CHudViewport : public CBaseViewport
+{
+private:
+ DECLARE_CLASS_SIMPLE( CHudViewport, CBaseViewport );
+
+protected:
+ virtual void ApplySchemeSettings( vgui::IScheme *pScheme )
+ {
+ BaseClass::ApplySchemeSettings( pScheme );
+
+ gHUD.InitColors( pScheme );
+
+ SetPaintBackgroundEnabled( false );
+ }
+
+ virtual void CreateDefaultPanels( void )
+ {
+ CBaseViewport::CreateDefaultPanels();
+ }
+
+ virtual IViewPortPanel *CreatePanelByName( const char *szPanelName );
+};
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+ClientModeHL1Normal::ClientModeHL1Normal()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: If you don't know what a destructor is by now, you are probably going to get fired
+//-----------------------------------------------------------------------------
+ClientModeHL1Normal::~ClientModeHL1Normal()
+{
+}
+
+void ClientModeHL1Normal::InitViewport()
+{
+ m_pViewport = new CHudViewport();
+ m_pViewport->Start( gameuifuncs, gameeventmanager );
+}
+
+float ClientModeHL1Normal::GetViewModelFOV( void )
+{
+ return 90.0f;
+}
+
+
+int ClientModeHL1Normal::GetDeathMessageStartHeight( void )
+{
+ return m_pViewport->GetDeathMessageStartHeight();
+}
+
+
+ClientModeHL1Normal g_ClientModeNormal;
+
+IClientMode *GetClientModeNormal()
+{
+ return &g_ClientModeNormal;
+}
+
+ClientModeHL1Normal* GetClientModeHL1Normal()
+{
+ Assert( dynamic_cast< ClientModeHL1Normal* >( GetClientModeNormal() ) );
+
+ return static_cast< ClientModeHL1Normal* >( GetClientModeNormal() );
+}
+
+IViewPortPanel* CHudViewport::CreatePanelByName( const char *szPanelName )
+{
+
+#ifdef HL1MP_CLIENT_DLL
+ IViewPortPanel* newpanel = NULL;
+ if ( Q_strcmp( PANEL_SCOREBOARD, szPanelName) == 0 )
+ {
+ newpanel = new CHL1MPClientScoreBoardDialog( this );
+ return newpanel;
+ }
+#endif
+ /* else if ( Q_strcmp(PANEL_INFO, szPanelName) == 0 )
+ {
+ newpanel = new CHL2MPTextWindow( this );
+ return newpanel;
+ }*/
+
+ return BaseClass::CreatePanelByName( szPanelName );
+}
+
+
+
+
+
diff --git a/game/client/hl1/hl1_clientmode.h b/game/client/hl1/hl1_clientmode.h
new file mode 100644
index 0000000..c9f8ab6
--- /dev/null
+++ b/game/client/hl1/hl1_clientmode.h
@@ -0,0 +1,35 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#ifndef HL1_CLIENTMODE_H
+#define HL1_CLIENTMODE_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "clientmode_shared.h"
+
+class ClientModeHL1Normal : public ClientModeShared
+{
+DECLARE_CLASS( ClientModeHL1Normal, ClientModeShared );
+
+public:
+ ClientModeHL1Normal();
+ virtual ~ClientModeHL1Normal();
+
+ virtual void InitViewport();
+
+ virtual float GetViewModelFOV( void );
+
+ virtual int GetDeathMessageStartHeight( void );
+};
+
+
+extern IClientMode *GetClientModeNormal();
+extern ClientModeHL1Normal* GetClientModeHL1Normal();
+
+
+#endif // HL1_CLIENTMODE_H \ No newline at end of file
diff --git a/game/client/hl1/hl1_clientscoreboard.cpp b/game/client/hl1/hl1_clientscoreboard.cpp
new file mode 100644
index 0000000..0af498a
--- /dev/null
+++ b/game/client/hl1/hl1_clientscoreboard.cpp
@@ -0,0 +1,703 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "hud.h"
+#include "hl1_clientscoreboard.h"
+#include "c_team.h"
+#include "c_playerresource.h"
+#include "c_hl1mp_player.h"
+//#include "hl2mp_gamerules.h"
+
+#include <KeyValues.h>
+
+#include <vgui/IScheme.h>
+#include <vgui/ILocalize.h>
+#include <vgui/ISurface.h>
+#include <vgui/IVGui.h>
+#include <vgui_controls/SectionedListPanel.h>
+
+#include "voice_status.h"
+
+#include "hl1mp_gamerules.h"
+
+#if 1
+
+enum
+{
+ TEAM_COMBINE = 2,
+ TEAM_REBELS,
+};
+
+using namespace vgui;
+
+#define TEAM_MAXCOUNT 5
+
+// id's of sections used in the scoreboard
+enum EScoreboardSections
+{
+ SCORESECTION_COMBINE = 1,
+ SCORESECTION_REBELS = 2,
+ SCORESECTION_FREEFORALL = 3,
+};
+
+const int NumSegments = 7;
+static int coord[NumSegments+1] = {
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 6,
+ 9,
+ 10
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: Konstructor
+//-----------------------------------------------------------------------------
+CHL1MPClientScoreBoardDialog::CHL1MPClientScoreBoardDialog(IViewPort *pViewPort):CClientScoreBoardDialog(pViewPort)
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Destructor
+//-----------------------------------------------------------------------------
+CHL1MPClientScoreBoardDialog::~CHL1MPClientScoreBoardDialog()
+{
+}
+
+void CHL1MPClientScoreBoardDialog::Paint()
+{
+// int m_nTextureID = vgui::surface()->CreateNewTextureID();
+// vgui::surface()->DrawSetTexture( TrackerImage );
+// vgui::surface()->DrawTexturedRect( 0, 0, 640, 480 );
+// m_pPlayerList->SetBgColor( Color(0, 0, 0, 0) );
+// surface()->DrawSetColor( 0, 0, 0, 128 );
+// vgui::surface()->DrawFilledRect( 0,0, 4000,4000 );
+
+// const ConVar * hostname = cvar->FindVar( "hostname" );
+// SetControlString("ServerName", hostname->GetString() );
+// MoveLabelToFront("ServerName");
+// Label *entry = dynamic_cast<Label *>(FindChildByName("ServerName"));
+// entry->SetText("ThisSucks");
+// entry->SetFgColor( Color(255,0,0,255) );
+// entry->SetBgColor( Color(0,0,0,255) );
+
+// SetBgColor( Color(0,0,0,255) );
+
+// Label *entry = dynamic_cast<Label *>(FindChildByName("ServerName"));
+
+// m_pPlayerList->SetFgColor( Color(255, 0, 0, 255) );
+// m_pPlayerList->SetBgColor( Color(0, 0, 0, 255) );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Paint background for rounded corners
+//-----------------------------------------------------------------------------
+void CHL1MPClientScoreBoardDialog::PaintBackground()
+{
+ m_pPlayerList->SetBgColor( Color(0, 0, 0, 0) );
+ m_pPlayerList->SetBorder(NULL);
+
+ int x1, x2, y1, y2;
+ surface()->DrawSetColor(m_bgColor);
+ surface()->DrawSetTextColor(m_bgColor);
+
+ int wide, tall;
+ GetSize( wide, tall );
+
+ surface()->DrawFilledRect( 0, 0, wide, tall );
+ return;
+
+ int i;
+
+ // top-left corner --------------------------------------------------------
+ int xDir = 1;
+ int yDir = -1;
+ int xIndex = 0;
+ int yIndex = NumSegments - 1;
+ int xMult = 1;
+ int yMult = 1;
+ int x = 0;
+ int y = 0;
+ for ( i=0; i<NumSegments; ++i )
+ {
+ x1 = MIN( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
+ x2 = MAX( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
+ y1 = MAX( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
+ y2 = y + coord[NumSegments];
+ surface()->DrawFilledRect( x1, y1, x2, y2 );
+
+ xIndex += xDir;
+ yIndex += yDir;
+ }
+
+ // top-right corner -------------------------------------------------------
+ xDir = 1;
+ yDir = -1;
+ xIndex = 0;
+ yIndex = NumSegments - 1;
+ x = wide;
+ y = 0;
+ xMult = -1;
+ yMult = 1;
+ for ( i=0; i<NumSegments; ++i )
+ {
+ x1 = MIN( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
+ x2 = MAX( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
+ y1 = MAX( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
+ y2 = y + coord[NumSegments];
+ surface()->DrawFilledRect( x1, y1, x2, y2 );
+ xIndex += xDir;
+ yIndex += yDir;
+ }
+
+ // bottom-right corner ----------------------------------------------------
+ xDir = 1;
+ yDir = -1;
+ xIndex = 0;
+ yIndex = NumSegments - 1;
+ x = wide;
+ y = tall;
+ xMult = -1;
+ yMult = -1;
+ for ( i=0; i<NumSegments; ++i )
+ {
+ x1 = MIN( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
+ x2 = MAX( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
+ y1 = y - coord[NumSegments];
+ y2 = MIN( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
+ surface()->DrawFilledRect( x1, y1, x2, y2 );
+ xIndex += xDir;
+ yIndex += yDir;
+ }
+
+ // bottom-left corner -----------------------------------------------------
+ xDir = 1;
+ yDir = -1;
+ xIndex = 0;
+ yIndex = NumSegments - 1;
+ x = 0;
+ y = tall;
+ xMult = 1;
+ yMult = -1;
+ for ( i=0; i<NumSegments; ++i )
+ {
+ x1 = MIN( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
+ x2 = MAX( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
+ y1 = y - coord[NumSegments];
+ y2 = MIN( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
+ surface()->DrawFilledRect( x1, y1, x2, y2 );
+ xIndex += xDir;
+ yIndex += yDir;
+ }
+
+ // paint between top left and bottom left ---------------------------------
+ x1 = 0;
+ x2 = coord[NumSegments];
+ y1 = coord[NumSegments];
+ y2 = tall - coord[NumSegments];
+ surface()->DrawFilledRect( x1, y1, x2, y2 );
+
+ // paint between left and right -------------------------------------------
+ x1 = coord[NumSegments];
+ x2 = wide - coord[NumSegments];
+ y1 = 0;
+ y2 = tall;
+ surface()->DrawFilledRect( x1, y1, x2, y2 );
+
+ // paint between top right and bottom right -------------------------------
+ x1 = wide - coord[NumSegments];
+ x2 = wide;
+ y1 = coord[NumSegments];
+ y2 = tall - coord[NumSegments];
+ surface()->DrawFilledRect( x1, y1, x2, y2 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Paint border for rounded corners
+//-----------------------------------------------------------------------------
+void CHL1MPClientScoreBoardDialog::PaintBorder()
+{
+ return;
+ int x1, x2, y1, y2;
+ surface()->DrawSetColor(m_borderColor);
+ surface()->DrawSetTextColor(m_borderColor);
+
+ int wide, tall;
+ GetSize( wide, tall );
+
+ int i;
+
+ // top-left corner --------------------------------------------------------
+ int xDir = 1;
+ int yDir = -1;
+ int xIndex = 0;
+ int yIndex = NumSegments - 1;
+ int xMult = 1;
+ int yMult = 1;
+ int x = 0;
+ int y = 0;
+ for ( i=0; i<NumSegments; ++i )
+ {
+ x1 = MIN( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
+ x2 = MAX( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
+ y1 = MIN( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
+ y2 = MAX( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
+ surface()->DrawFilledRect( x1, y1, x2, y2 );
+
+ xIndex += xDir;
+ yIndex += yDir;
+ }
+
+ // top-right corner -------------------------------------------------------
+ xDir = 1;
+ yDir = -1;
+ xIndex = 0;
+ yIndex = NumSegments - 1;
+ x = wide;
+ y = 0;
+ xMult = -1;
+ yMult = 1;
+ for ( i=0; i<NumSegments; ++i )
+ {
+ x1 = MIN( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
+ x2 = MAX( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
+ y1 = MIN( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
+ y2 = MAX( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
+ surface()->DrawFilledRect( x1, y1, x2, y2 );
+ xIndex += xDir;
+ yIndex += yDir;
+ }
+
+ // bottom-right corner ----------------------------------------------------
+ xDir = 1;
+ yDir = -1;
+ xIndex = 0;
+ yIndex = NumSegments - 1;
+ x = wide;
+ y = tall;
+ xMult = -1;
+ yMult = -1;
+ for ( i=0; i<NumSegments; ++i )
+ {
+ x1 = MIN( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
+ x2 = MAX( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
+ y1 = MIN( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
+ y2 = MAX( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
+ surface()->DrawFilledRect( x1, y1, x2, y2 );
+ xIndex += xDir;
+ yIndex += yDir;
+ }
+
+ // bottom-left corner -----------------------------------------------------
+ xDir = 1;
+ yDir = -1;
+ xIndex = 0;
+ yIndex = NumSegments - 1;
+ x = 0;
+ y = tall;
+ xMult = 1;
+ yMult = -1;
+ for ( i=0; i<NumSegments; ++i )
+ {
+ x1 = MIN( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
+ x2 = MAX( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
+ y1 = MIN( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
+ y2 = MAX( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
+ surface()->DrawFilledRect( x1, y1, x2, y2 );
+ xIndex += xDir;
+ yIndex += yDir;
+ }
+
+ // top --------------------------------------------------------------------
+ x1 = coord[NumSegments];
+ x2 = wide - coord[NumSegments];
+ y1 = 0;
+ y2 = 1;
+ surface()->DrawFilledRect( x1, y1, x2, y2 );
+
+ // bottom -----------------------------------------------------------------
+ x1 = coord[NumSegments];
+ x2 = wide - coord[NumSegments];
+ y1 = tall - 1;
+ y2 = tall;
+ surface()->DrawFilledRect( x1, y1, x2, y2 );
+
+ // left -------------------------------------------------------------------
+ x1 = 0;
+ x2 = 1;
+ y1 = coord[NumSegments];
+ y2 = tall - coord[NumSegments];
+ surface()->DrawFilledRect( x1, y1, x2, y2 );
+
+ // right ------------------------------------------------------------------
+ x1 = wide - 1;
+ x2 = wide;
+ y1 = coord[NumSegments];
+ y2 = tall - coord[NumSegments];
+ surface()->DrawFilledRect( x1, y1, x2, y2 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Apply scheme settings
+//-----------------------------------------------------------------------------
+void CHL1MPClientScoreBoardDialog::ApplySchemeSettings( vgui::IScheme *pScheme )
+{
+ BaseClass::ApplySchemeSettings( pScheme );
+
+ m_bgColor = GetSchemeColor("SectionedListPanel.BgColor", GetBgColor(), pScheme);
+ m_borderColor = pScheme->GetColor( "FgColor", Color( 0, 0, 0, 0 ) );
+
+ SetBgColor( Color(0, 0, 0, 0) );
+ SetBorder( pScheme->GetBorder( "BaseBorder" ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: sets up base sections
+//-----------------------------------------------------------------------------
+void CHL1MPClientScoreBoardDialog::InitScoreboardSections()
+{
+ m_pPlayerList->SetBgColor( Color(0, 0, 0, 0) );
+ m_pPlayerList->SetBorder(NULL);
+
+ // fill out the structure of the scoreboard
+ AddHeader();
+
+ if ( HL1MPRules() && HL1MPRules()->IsTeamplay() )
+ {
+ // add the team sections
+// AddSection( TYPE_TEAM, 2 );
+// AddSection( TYPE_TEAM, 3 );
+
+ for ( int i = 2; i < g_Teams.Count(); i++ )
+ {
+ AddSection( TYPE_TEAM, i );
+ }
+ }
+ else
+ {
+ AddSection( TYPE_TEAM, TEAM_UNASSIGNED );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: resets the scoreboard team info
+//-----------------------------------------------------------------------------
+void CHL1MPClientScoreBoardDialog::UpdateTeamInfo()
+{
+ if ( g_PR == NULL )
+ return;
+
+ int iNumPlayersInGame = 0;
+
+ for ( int j = 1; j <= gpGlobals->maxClients; j++ )
+ {
+ if ( g_PR->IsConnected( j ) )
+ {
+ iNumPlayersInGame++;
+ }
+ }
+
+ // update the team sections in the scoreboard
+ for ( int i = TEAM_SPECTATOR; i < TEAM_MAXCOUNT; i++ )
+ {
+ wchar_t *teamName = NULL;
+ int sectionID = 0;
+ C_Team *team = GetGlobalTeam(i);
+
+ if ( team )
+ {
+ sectionID = GetSectionFromTeamNumber( i );
+
+ // update team name
+ wchar_t name[64];
+ wchar_t string1[1024];
+ wchar_t wNumPlayers[6];
+
+ if ( !HL1MPRules() || HL1MPRules()->IsTeamplay() == false )
+ {
+ _snwprintf( wNumPlayers, ARRAYSIZE(wNumPlayers), L"%i", iNumPlayersInGame );
+
+#ifdef WIN32
+ _snwprintf( name, ARRAYSIZE(name), L"%s", g_pVGuiLocalize->Find("#ScoreBoard_Deathmatch") );
+#else
+ _snwprintf( name, ARRAYSIZE(name), L"%S", g_pVGuiLocalize->Find("#ScoreBoard_Deathmatch") );
+#endif
+
+ teamName = name;
+
+ if ( iNumPlayersInGame == 1)
+ {
+ g_pVGuiLocalize->ConstructString( string1, sizeof(string1), g_pVGuiLocalize->Find("#ScoreBoard_Player"), 2, teamName, wNumPlayers );
+ }
+ else
+ {
+ g_pVGuiLocalize->ConstructString( string1, sizeof(string1), g_pVGuiLocalize->Find("#ScoreBoard_Players"), 2, teamName, wNumPlayers );
+ }
+ }
+ else
+ {
+ _snwprintf(wNumPlayers, ARRAYSIZE(wNumPlayers), L"%i", team->Get_Number_Players());
+
+ if (!teamName && team)
+ {
+ g_pVGuiLocalize->ConvertANSIToUnicode(team->Get_Name(), name, sizeof(name));
+ teamName = name;
+ }
+
+ if (team->Get_Number_Players() == 1)
+ {
+ g_pVGuiLocalize->ConstructString( string1, sizeof(string1), g_pVGuiLocalize->Find("#ScoreBoard_Player"), 2, teamName, wNumPlayers );
+ }
+ else
+ {
+ g_pVGuiLocalize->ConstructString( string1, sizeof(string1), g_pVGuiLocalize->Find("#ScoreBoard_Players"), 2, teamName, wNumPlayers );
+ }
+
+ // update stats
+ wchar_t val[6];
+ V_swprintf_safe(val, L"%d", team->Get_Score());
+ m_pPlayerList->ModifyColumn(sectionID, "frags", val);
+ if (team->Get_Ping() < 1)
+ {
+ m_pPlayerList->ModifyColumn(sectionID, "ping", L"");
+ }
+ else
+ {
+ V_swprintf_safe(val, L"%d", team->Get_Ping());
+ m_pPlayerList->ModifyColumn(sectionID, "ping", val);
+ }
+
+ }
+
+ m_pPlayerList->ModifyColumn(sectionID, "name", string1);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: adds the top header of the scoreboars
+//-----------------------------------------------------------------------------
+void CHL1MPClientScoreBoardDialog::AddHeader()
+{
+ // add the top header
+ m_pPlayerList->AddSection(0, "");
+ m_pPlayerList->SetSectionAlwaysVisible(0);
+ m_pPlayerList->AddColumnToSection(0, "name", "", 0, scheme()->GetProportionalScaledValue( CSTRIKE_NAME_WIDTH ) );
+ m_pPlayerList->AddColumnToSection(0, "class", "", 0, scheme()->GetProportionalScaledValue( CSTRIKE_CLASS_WIDTH ) );
+ m_pPlayerList->AddColumnToSection(0, "frags", "#PlayerScore", 0 | SectionedListPanel::COLUMN_RIGHT, scheme()->GetProportionalScaledValue( CSTRIKE_SCORE_WIDTH ) );
+ m_pPlayerList->AddColumnToSection(0, "deaths", "#PlayerDeath", 0 | SectionedListPanel::COLUMN_RIGHT, scheme()->GetProportionalScaledValue( CSTRIKE_DEATH_WIDTH ) );
+ m_pPlayerList->AddColumnToSection(0, "ping", "#PlayerPing", 0 | SectionedListPanel::COLUMN_RIGHT, scheme()->GetProportionalScaledValue( CSTRIKE_PING_WIDTH ) );
+// m_pPlayerList->AddColumnToSection(0, "voice", "#PlayerVoice", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::HEADER_TEXT| SectionedListPanel::COLUMN_CENTER, scheme()->GetProportionalScaledValue( CSTRIKE_VOICE_WIDTH ) );
+// m_pPlayerList->AddColumnToSection(0, "tracker", "#PlayerTracker", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::HEADER_TEXT, scheme()->GetProportionalScaledValue( CSTRIKE_FRIENDS_WIDTH ) );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Adds a new section to the scoreboard (i.e the team header)
+//-----------------------------------------------------------------------------
+void CHL1MPClientScoreBoardDialog::AddSection(int teamType, int teamNumber)
+{
+ int sectionID = GetSectionFromTeamNumber( teamNumber );
+ if ( teamType == TYPE_TEAM )
+ {
+ m_pPlayerList->AddSection(sectionID, "", StaticPlayerSortFunc);
+
+ // setup the columns
+ m_pPlayerList->AddColumnToSection(sectionID, "name", "", 0, scheme()->GetProportionalScaledValue( CSTRIKE_NAME_WIDTH ) );
+ m_pPlayerList->AddColumnToSection(sectionID, "class", "" , 0, scheme()->GetProportionalScaledValue( CSTRIKE_CLASS_WIDTH ) );
+ m_pPlayerList->AddColumnToSection(sectionID, "frags", "", SectionedListPanel::COLUMN_RIGHT, scheme()->GetProportionalScaledValue( CSTRIKE_SCORE_WIDTH ) );
+ m_pPlayerList->AddColumnToSection(sectionID, "deaths", "", SectionedListPanel::COLUMN_RIGHT, scheme()->GetProportionalScaledValue( CSTRIKE_DEATH_WIDTH ) );
+ m_pPlayerList->AddColumnToSection(sectionID, "ping", "", SectionedListPanel::COLUMN_RIGHT, scheme()->GetProportionalScaledValue( CSTRIKE_PING_WIDTH ) );
+
+ // set the section to have the team color
+ if ( teamNumber )
+ {
+ if ( GameResources() )
+ m_pPlayerList->SetSectionFgColor(sectionID, GameResources()->GetTeamColor(teamNumber));
+ }
+
+ m_pPlayerList->SetSectionAlwaysVisible(sectionID);
+ }
+ else if ( teamType == TYPE_SPECTATORS )
+ {
+ m_pPlayerList->AddSection(sectionID, "");
+ m_pPlayerList->AddColumnToSection(sectionID, "name", "#Spectators", 0, scheme()->GetProportionalScaledValue( CSTRIKE_NAME_WIDTH ));
+ m_pPlayerList->AddColumnToSection(sectionID, "class", "" , 0, scheme()->GetProportionalScaledValue( 100 ) );
+ }
+}
+
+int CHL1MPClientScoreBoardDialog::GetSectionFromTeamNumber( int teamNumber )
+{
+ if ( !HL1MPRules() || !HL1MPRules()->IsTeamplay() )
+ {
+ return teamNumber+1;
+ }
+
+ if ( teamNumber >= 2 )
+ return teamNumber - 1;
+
+ return g_Teams.Count();
+#if 0
+ switch ( teamNumber )
+ {
+ case TEAM_COMBINE:
+ return SCORESECTION_COMBINE;
+ case TEAM_REBELS:
+ return SCORESECTION_REBELS;
+ default:
+ return SCORESECTION_FREEFORALL;
+ }
+ return SCORESECTION_FREEFORALL;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Adds a new row to the scoreboard, from the playerinfo structure
+//-----------------------------------------------------------------------------
+bool CHL1MPClientScoreBoardDialog::GetPlayerScoreInfo(int playerIndex, KeyValues *kv)
+{
+ kv->SetInt("playerIndex", playerIndex);
+ kv->SetInt("team", g_PR->GetTeam( playerIndex ) );
+ kv->SetString("name", g_PR->GetPlayerName(playerIndex) );
+ kv->SetInt("deaths", g_PR->GetDeaths( playerIndex ));
+ kv->SetInt("frags", g_PR->GetPlayerScore( playerIndex ));
+ kv->SetString("class", "");
+
+ if (g_PR->GetPing( playerIndex ) < 1)
+ {
+ if ( g_PR->IsFakePlayer( playerIndex ) )
+ {
+ kv->SetString("ping", "BOT");
+ }
+ else
+ {
+ kv->SetString("ping", "");
+ }
+ }
+ else
+ {
+ kv->SetInt("ping", g_PR->GetPing( playerIndex ));
+ }
+
+ return true;
+}
+
+enum {
+ MAX_PLAYERS_PER_TEAM = 16,
+ MAX_SCOREBOARD_PLAYERS = 32
+};
+struct PlayerScoreInfo
+{
+ int index;
+ int frags;
+ int deaths;
+ bool important;
+ bool alive;
+};
+
+int PlayerScoreInfoSort( const PlayerScoreInfo *p1, const PlayerScoreInfo *p2 )
+{
+ // check local
+ if ( p1->important )
+ return -1;
+ if ( p2->important )
+ return 1;
+
+ // check alive
+ if ( p1->alive && !p2->alive )
+ return -1;
+ if ( p2->alive && !p1->alive )
+ return 1;
+
+ // check frags
+ if ( p1->frags > p2->frags )
+ return -1;
+ if ( p2->frags > p1->frags )
+ return 1;
+
+ // check deaths
+ if ( p1->deaths < p2->deaths )
+ return -1;
+ if ( p2->deaths < p1->deaths )
+ return 1;
+
+ // check index
+ if ( p1->index < p2->index )
+ return -1;
+
+ return 1;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHL1MPClientScoreBoardDialog::UpdatePlayerInfo()
+{
+ m_iSectionId = 0; // 0'th row is a header
+ int selectedRow = -1;
+ int i;
+
+ CBasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
+
+ if ( !pPlayer || !g_PR )
+ return;
+
+ // walk all the players and make sure they're in the scoreboard
+ for ( i = 1; i <= gpGlobals->maxClients; i++ )
+ {
+ bool shouldShow = g_PR->IsConnected( i );
+ if ( shouldShow )
+ {
+ // add the player to the list
+ KeyValues *playerData = new KeyValues("data");
+ GetPlayerScoreInfo( i, playerData );
+ int itemID = FindItemIDForPlayerIndex( i );
+ int sectionID = GetSectionFromTeamNumber( g_PR->GetTeam( i ) );
+
+ if (itemID == -1)
+ {
+ // add a new row
+ itemID = m_pPlayerList->AddItem( sectionID, playerData );
+ }
+ else
+ {
+ // modify the current row
+ m_pPlayerList->ModifyItem( itemID, sectionID, playerData );
+ }
+
+ if ( i == pPlayer->entindex() )
+ {
+ selectedRow = itemID; // this is the local player, hilight this row
+ }
+
+ // set the row color based on the players team
+ m_pPlayerList->SetItemFgColor( itemID, g_PR->GetTeamColor( g_PR->GetTeam( i ) ) );
+
+ playerData->deleteThis();
+ }
+ else
+ {
+ // remove the player
+ int itemID = FindItemIDForPlayerIndex( i );
+ if (itemID != -1)
+ {
+ m_pPlayerList->RemoveItem(itemID);
+ }
+ }
+ }
+
+ if ( selectedRow != -1 )
+ {
+ m_pPlayerList->SetSelectedItem(selectedRow);
+ }
+
+
+}
+#endif
diff --git a/game/client/hl1/hl1_clientscoreboard.h b/game/client/hl1/hl1_clientscoreboard.h
new file mode 100644
index 0000000..5539f22
--- /dev/null
+++ b/game/client/hl1/hl1_clientscoreboard.h
@@ -0,0 +1,65 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef CHL1MPClientScoreBoardDialog_H
+#define CHL1MPClientScoreBoardDialog_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include <clientscoreboarddialog.h>
+
+//-----------------------------------------------------------------------------
+// Purpose: Game ScoreBoard
+//-----------------------------------------------------------------------------
+class CHL1MPClientScoreBoardDialog : public CClientScoreBoardDialog
+{
+private:
+ DECLARE_CLASS_SIMPLE(CHL1MPClientScoreBoardDialog, CClientScoreBoardDialog);
+
+public:
+ CHL1MPClientScoreBoardDialog(IViewPort *pViewPort);
+ ~CHL1MPClientScoreBoardDialog();
+
+
+protected:
+ // scoreboard overrides
+ virtual void InitScoreboardSections();
+ virtual void UpdateTeamInfo();
+ virtual bool GetPlayerScoreInfo(int playerIndex, KeyValues *outPlayerInfo);
+ virtual void UpdatePlayerInfo();
+
+ virtual void Paint();
+
+ // vgui overrides for rounded corner background
+ virtual void PaintBackground();
+ virtual void PaintBorder();
+ virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
+
+private:
+ virtual void AddHeader(); // add the start header of the scoreboard
+ virtual void AddSection(int teamType, int teamNumber); // add a new section header for a team
+
+ int GetSectionFromTeamNumber( int teamNumber );
+ enum
+ {
+ CSTRIKE_NAME_WIDTH = 220,
+ CSTRIKE_CLASS_WIDTH = 56,
+ CSTRIKE_SCORE_WIDTH = 40,
+ CSTRIKE_DEATH_WIDTH = 46,
+ CSTRIKE_PING_WIDTH = 46,
+// CSTRIKE_VOICE_WIDTH = 40,
+// CSTRIKE_FRIENDS_WIDTH = 24,
+ };
+
+ // rounded corners
+ Color m_bgColor;
+ Color m_borderColor;
+};
+
+
+#endif // CHL1MPClientScoreBoardDialog_H
diff --git a/game/client/hl1/hl1_fx_gauss.cpp b/game/client/hl1/hl1_fx_gauss.cpp
new file mode 100644
index 0000000..0a9c28c
--- /dev/null
+++ b/game/client/hl1/hl1_fx_gauss.cpp
@@ -0,0 +1,238 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+
+#include "cbase.h"
+#include "fx.h"
+#include "c_te_effect_dispatch.h"
+#include "c_te_legacytempents.h"
+#include "tempent.h"
+#include "c_te_basebeam.h"
+#include "iviewrender_beams.h"
+#include "c_baseplayer.h"
+#include "beam_shared.h"
+
+
+#define GAUSS_GLOW_SPRITE "sprites/hotglow.vmt"
+#define GAUSS_BEAM_SPRITE "sprites/smoke.vmt"
+
+
+int m_nGlowIndex;
+int m_nBeamIndex;
+
+
+void PrecacheGaussEffects(void *pUser)
+{
+ m_nGlowIndex = modelinfo->GetModelIndex( GAUSS_GLOW_SPRITE );
+ m_nBeamIndex = modelinfo->GetModelIndex( GAUSS_BEAM_SPRITE );
+}
+PRECACHE_REGISTER_FN(PrecacheGaussEffects);
+
+
+void HL1GaussBeam( const CEffectData &data )
+{
+ // beam expects ent + attach to be encoded in the entity index (legacy system)
+ int nStartEntity = data.entindex() | ((1 & 0xF)<<12);
+
+ C_BaseEntity * pEnt = cl_entitylist->GetEnt( BEAMENT_ENTITY(nStartEntity) );
+
+ if ( !pEnt->IsPlayer() )
+ return;
+
+ C_BasePlayer * pPlayer = static_cast<C_BasePlayer*>(pEnt);
+ int nStartAttachment = -1;
+
+ if ( pPlayer->IsLocalPlayer() )
+ {
+ nStartEntity = pPlayer->GetViewModel()->entindex();
+ }
+ else
+ {
+ if ( !pPlayer->GetActiveWeapon() ) // TODO : make sure we have the gauss gun
+ return;
+
+ nStartEntity = pPlayer->GetActiveWeapon()->entindex();
+ nStartAttachment = 2;
+ }
+
+ nStartEntity |= ((1 & 0xF)<<12);
+
+ Vector vecEndPoint = data.m_vOrigin;
+ bool fIsPrimaryFire = data.m_fFlags;
+ float flStartWidth;
+ float flEndWidth;
+ color32 beamColor;
+
+ if ( fIsPrimaryFire ) // primary attack
+ {
+ flStartWidth = 1.0;
+ flEndWidth = 1.0;
+
+ beamColor.r = 255;
+ beamColor.g = 255;
+ beamColor.b = 0;
+ beamColor.a = 255;
+ }
+ else // secondary
+ {
+ flStartWidth = 2.5;
+ flEndWidth = 2.5;
+
+ beamColor.r = 255;
+ beamColor.g = 255;
+ beamColor.b = 255;
+ beamColor.a = 255;
+ }
+
+ beams->CreateBeamEntPoint(
+ nStartEntity, // start ent
+ NULL, // start pos
+ 0, // end ent
+ &vecEndPoint, // end pos
+ m_nBeamIndex, // model index
+ NULL, // halo index
+ 0.0, // halo scale
+ 0.1, // life
+ flStartWidth, // startwidth
+ flEndWidth, // endwidth
+ 0.0, // fade length
+ 0, // amplitude
+ beamColor.a, // brightness
+ 0, // speed
+ 0, // startframe
+ 0, // framerate
+ beamColor.r, // R
+ beamColor.g, // G
+ beamColor.b // B
+ );
+
+ //ADRIANHL1MP
+}
+DECLARE_CLIENT_EFFECT( "HL1GaussBeam", HL1GaussBeam );
+
+
+void HL1GaussBeamReflect( const CEffectData &data )
+{
+ Vector vecStartPoint = data.m_vStart;
+ Vector vecEndPoint = data.m_vOrigin;
+ bool fIsPrimaryFire = data.m_fFlags;
+ float flStartWidth;
+ float flEndWidth;
+ color32 beamColor;
+
+ if ( fIsPrimaryFire ) // primary attack
+ {
+ flStartWidth = 1.0;
+ flEndWidth = 1.0;
+
+ beamColor.r = 255;
+ beamColor.g = 255;
+ beamColor.b = 0;
+ beamColor.a = 255;
+ }
+ else // secondary
+ {
+ flStartWidth = 2.5;
+ flEndWidth = 2.5;
+
+ beamColor.r = 255;
+ beamColor.g = 255;
+ beamColor.b = 255;
+ beamColor.a = 255;
+ }
+
+ beams->CreateBeamPoints(
+ vecStartPoint, // start pos
+ vecEndPoint, // end pos
+ m_nBeamIndex, // model index
+ NULL, // halo index
+ 0.0, // halo scale
+ 0.1, // life
+ flStartWidth, // startwidth
+ flEndWidth, // endwidth
+ 0.0, // fade length
+ 0, // amplitude
+ beamColor.a, // brightness
+ 0, // speed
+ 0, // startframe
+ 0, // framerate
+ beamColor.r, // R
+ beamColor.g, // G
+ beamColor.b // B
+ );
+}
+DECLARE_CLIENT_EFFECT( "HL1GaussBeamReflect", HL1GaussBeamReflect );
+
+
+void HL1GaussReflect( const CEffectData &data )
+{
+ Vector vecStart = data.m_vOrigin;
+ Vector vecNormal = data.m_vNormal;
+ float flMagnitude = data.m_flMagnitude;
+
+ tempents->TempSprite( vecStart, vec3_origin, 0.2, m_nGlowIndex, kRenderGlow, kRenderFxNoDissipation, flMagnitude / 255.0, flMagnitude * 0.05, FTENT_FADEOUT );
+
+ Vector vecForward;
+ VectorAdd( vecStart, vecNormal, vecForward );
+
+ tempents->Sprite_Trail( vecStart, vecForward, m_nGlowIndex, 3, 0.1, random->RandomFloat( 0.1, 0.2 ), 100, 255, 100 );
+}
+DECLARE_CLIENT_EFFECT( "HL1GaussReflect", HL1GaussReflect );
+
+
+void HL1GaussWallPunchEnter( const CEffectData &data )
+{
+ Vector vecStart = data.m_vOrigin;
+ Vector vecNormal = data.m_vNormal;
+
+ Vector vecForward;
+ VectorSubtract( vecStart, vecNormal, vecForward );
+
+ tempents->Sprite_Trail( vecStart, vecForward, m_nGlowIndex, 3, 0.1, random->RandomFloat( 0.1, 0.2 ), 100, 255, 100 );
+}
+DECLARE_CLIENT_EFFECT( "HL1GaussWallPunchEnter", HL1GaussWallPunchEnter );
+
+
+void HL1GaussWallPunchExit( const CEffectData &data )
+{
+ Vector vecStart = data.m_vOrigin;
+ Vector vecNormal = data.m_vNormal;
+ float flMagnitude = data.m_flMagnitude;
+
+ tempents->TempSprite( vecStart, vec3_origin, 0.1, m_nGlowIndex, kRenderGlow, kRenderFxNoDissipation, flMagnitude * 1.2 / 255.0, 6.0, FTENT_FADEOUT );
+
+ Vector vecForward;
+ VectorSubtract( vecStart, vecNormal, vecForward );
+
+ tempents->Sprite_Trail( vecStart, vecForward, m_nGlowIndex, flMagnitude * 0.3, 0.1, random->RandomFloat( 0.1, 0.2 ), 200, 255, 40 );
+}
+DECLARE_CLIENT_EFFECT( "HL1GaussWallPunchExit", HL1GaussWallPunchExit );
+
+
+void HL1GaussWallImpact1( const CEffectData &data )
+{
+ Vector vecStart = data.m_vOrigin;
+ float flMagnitude = data.m_flMagnitude;
+
+ tempents->TempSprite( vecStart, vec3_origin, 1, m_nGlowIndex, kRenderGlow, kRenderFxNoDissipation, flMagnitude / 255.0, 6.0, FTENT_FADEOUT );
+}
+DECLARE_CLIENT_EFFECT( "HL1GaussWallImpact1", HL1GaussWallImpact1 );
+
+
+void HL1GaussWallImpact2( const CEffectData &data )
+{
+ Vector vecStart = data.m_vOrigin;
+ Vector vecNormal = data.m_vNormal;
+
+ tempents->TempSprite( vecStart, vec3_origin, 0.2, m_nGlowIndex, kRenderGlow, kRenderFxNoDissipation, 240.0 / 255.0, 0.3, FTENT_FADEOUT );
+
+ Vector vecForward;
+ VectorAdd( vecStart, vecNormal, vecForward );
+
+ tempents->Sprite_Trail( vecStart, vecForward, m_nGlowIndex, 8, 0.6, random->RandomFloat( 0.1, 0.2 ), 100, 255, 200 );
+}
+DECLARE_CLIENT_EFFECT( "HL1GaussWallImpact2", HL1GaussWallImpact2 );
+
diff --git a/game/client/hl1/hl1_fx_gibs.cpp b/game/client/hl1/hl1_fx_gibs.cpp
new file mode 100644
index 0000000..a75a06b
--- /dev/null
+++ b/game/client/hl1/hl1_fx_gibs.cpp
@@ -0,0 +1,306 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "fx.h"
+#include "c_gib.h"
+#include "c_te_effect_dispatch.h"
+#include "iefx.h"
+#include "decals.h"
+
+#define HUMAN_GIBS 1
+#define ALIEN_GIBS 2
+
+#define MAX_GIBS 4
+
+#define HUMAN_GIB_COUNT 6
+#define ALIEN_GIB_COUNT 4
+
+const char *pHumanGibsModel = "models/gibs/hgibs.mdl";
+const char *pAlienGibsModel = "models/gibs/agibs.mdl";
+
+void GetBloodColorHL1( int bloodtype, unsigned char &r, unsigned char &g, unsigned char &b )
+{
+ if (bloodtype == BLOOD_COLOR_RED)
+ {
+ r = 64;
+ g = 0;
+ b = 0;
+ }
+ else if ( bloodtype == BLOOD_COLOR_GREEN )
+ {
+ r = 195;
+ g = 195;
+ b = 0;
+ }
+ else if ( bloodtype == BLOOD_COLOR_YELLOW )
+ {
+ r = 0;
+ g = 195;
+ b = 195;
+ }
+}
+
+class C_HL1Gib : public C_Gib
+{
+ typedef C_BaseAnimating BaseClass;
+public:
+
+ static C_HL1Gib *CreateClientsideGib( const char *pszModelName, Vector vecOrigin, Vector vecForceDir, AngularImpulse vecAngularImp )
+ {
+ C_HL1Gib *pGib = new C_HL1Gib;
+
+ if ( pGib == NULL )
+ return NULL;
+
+ if ( pGib->InitializeGib( pszModelName, vecOrigin, vecForceDir, vecAngularImp ) == false )
+ return NULL;
+
+ return pGib;
+ }
+
+ // Decal the surface
+ virtual void HitSurface( C_BaseEntity *pOther )
+ {
+ int index = -1;
+ if ( m_iType == HUMAN_GIBS )
+ {
+ if ( !UTIL_IsLowViolence() ) // no blood decals if we're low violence.
+ {
+ index = decalsystem->GetDecalIndexForName( "Blood" );
+ }
+ }
+ else
+ {
+ index = decalsystem->GetDecalIndexForName( "YellowBlood" );
+ }
+
+ if ( index >= 0 )
+ {
+ effects->DecalShoot( index, pOther->entindex(), pOther->GetModel(), pOther->GetAbsOrigin(), pOther->GetAbsAngles(), GetAbsOrigin(), 0, 0 );
+ }
+
+
+ if ( GetFlags() & FL_ONGROUND )
+ {
+ QAngle vAngles = GetAbsAngles();
+ QAngle vAngularVelocity = GetLocalAngularVelocity();
+
+ SetAbsVelocity( GetAbsVelocity() * 0.9 );
+
+ vAngles.x = 0;
+ vAngles.z = 0;
+ vAngularVelocity.x = 0;
+ vAngularVelocity.z = 0;
+
+ SetAbsAngles( vAngles );
+ SetLocalAngularVelocity( vAngularVelocity );
+ }
+ }
+
+ virtual void ClientThink( void );
+
+ int m_iType;
+};
+
+void C_HL1Gib::ClientThink( void )
+{
+ SetRenderMode( kRenderTransAlpha );
+ m_nRenderFX = kRenderFxFadeSlow;
+
+ if ( m_clrRender->a == 5 )
+ {
+ Release();
+ return;
+ }
+
+ SetNextClientThink( gpGlobals->curtime + 1.0f );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : &origin -
+//-----------------------------------------------------------------------------
+void FX_HL1Gib( const Vector &origin, const Vector &direction, float scale, int iType, int iHealth, int iColor )
+{
+ Vector offset;
+ int i;
+
+ offset = RandomVector( -16, 16 ) + origin;
+
+ if ( iType == HUMAN_GIBS )
+ {
+ Vector vVelocity;
+ AngularImpulse aImpulse;
+
+ // mix in some noise
+ vVelocity.x = random->RandomFloat( -100,100 );
+ vVelocity.y = random->RandomFloat ( -100,100 );
+ vVelocity.z = random->RandomFloat ( 200,300 );
+
+ aImpulse.x = random->RandomFloat ( 100, 200 );
+ aImpulse.y = random->RandomFloat ( 100, 300 );
+
+ if ( iHealth > -50)
+ {
+ vVelocity = vVelocity * 0.7;
+ }
+ else if ( iHealth > -200)
+ {
+ vVelocity = vVelocity * 2;
+ }
+ else
+ {
+ vVelocity = vVelocity * 4;
+ }
+
+
+ C_HL1Gib *pGib = C_HL1Gib::CreateClientsideGib( pHumanGibsModel, offset, vVelocity * 2, aImpulse );
+
+ //Spawn a head.
+ if ( pGib )
+ {
+ pGib->m_nBody = 0;
+ pGib->m_iType = iType;
+ }
+ }
+
+ // Spawn all the unique gibs
+ for ( i = 0; i < MAX_GIBS; i++ )
+ {
+ const char *pModelName = NULL;
+ int iNumBody = 0;
+
+ offset = RandomVector( -16, 16 ) + origin;
+
+ //TODO
+ Vector vVelocity = direction;
+ AngularImpulse aAImpulse;
+
+ // mix in some noise
+ vVelocity.x += random->RandomFloat( -0.25, 0.25 );
+ vVelocity.y += random->RandomFloat ( -0.25, 0.25 );
+ vVelocity.z += random->RandomFloat ( -0.25, 0.25 );
+
+ vVelocity = vVelocity * random->RandomFloat ( 300, 400 );
+
+ if ( iHealth > -50)
+ {
+ vVelocity = vVelocity * 0.7;
+ }
+ else if ( iHealth > -200)
+ {
+ vVelocity = vVelocity * 2;
+ }
+ else
+ {
+ vVelocity = vVelocity * 4;
+ }
+
+ aAImpulse.x = random->RandomFloat ( 100, 200 );
+ aAImpulse.y = random->RandomFloat ( 100, 300 );
+
+ if ( iType == HUMAN_GIBS )
+ {
+ pModelName = pHumanGibsModel;
+ iNumBody = HUMAN_GIB_COUNT;
+ }
+ else
+ {
+ pModelName = pAlienGibsModel;
+ iNumBody = ALIEN_GIB_COUNT;
+ }
+
+
+ C_HL1Gib *pGib = C_HL1Gib::CreateClientsideGib( pModelName, offset, vVelocity * 2, aAImpulse );
+
+ if ( pGib )
+ {
+ if ( iType == HUMAN_GIBS )
+ pGib->m_nBody = random->RandomInt( 1, iNumBody-1 );
+ else
+ pGib->m_nBody = random->RandomInt( 0, iNumBody-1 );
+
+ pGib->m_iType = iType;
+ }
+ }
+
+ //
+ // Throw some blood (unless we're low violence, then we're done)
+ //
+ if ( iColor == BLOOD_COLOR_RED && UTIL_IsLowViolence() )
+ return;
+
+ CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "FX_HL1Gib" );
+ pSimple->SetSortOrigin( origin );
+
+ Vector vDir;
+
+ vDir.Random( -1.0f, 1.0f );
+
+ for ( i = 0; i < 4; i++ )
+ {
+ SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], origin );
+
+ if ( sParticle == NULL )
+ return;
+
+ sParticle->m_flLifetime = 0.0f;
+ sParticle->m_flDieTime = 1;
+
+ float speed = random->RandomFloat( 32.0f, 128.0f );
+
+ sParticle->m_vecVelocity = vDir * -speed;
+ sParticle->m_vecVelocity[2] -= 16.0f;
+
+ GetBloodColorHL1( iColor, sParticle->m_uchColor[0], sParticle->m_uchColor[1], sParticle->m_uchColor[2] );
+
+ sParticle->m_uchStartAlpha = 255;
+ sParticle->m_uchEndAlpha = 0;
+ sParticle->m_uchStartSize = random->RandomInt( 16, 32 );
+ sParticle->m_uchEndSize = sParticle->m_uchStartSize*random->RandomInt( 1, 4 );
+ sParticle->m_flRoll = random->RandomInt( 0, 360 );
+ sParticle->m_flRollDelta = random->RandomFloat( -4.0f, 4.0f );
+ }
+
+ for ( i = 0; i < 4; i++ )
+ {
+ SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[1], origin );
+
+ if ( sParticle == NULL )
+ {
+ return;
+ }
+
+ sParticle->m_flLifetime = 0.0f;
+ sParticle->m_flDieTime = 1;
+
+ float speed = random->RandomFloat( 16.0f, 128.0f );
+
+ sParticle->m_vecVelocity = vDir * -speed;
+ sParticle->m_vecVelocity[2] -= 16.0f;
+
+ GetBloodColorHL1( iColor, sParticle->m_uchColor[0], sParticle->m_uchColor[1], sParticle->m_uchColor[2] );
+
+ sParticle->m_uchStartAlpha = random->RandomInt( 64, 128 );
+ sParticle->m_uchEndAlpha = 0;
+ sParticle->m_uchStartSize = random->RandomInt( 16, 32 );
+ sParticle->m_uchEndSize = sParticle->m_uchStartSize*random->RandomInt( 1, 4 );
+ sParticle->m_flRoll = random->RandomInt( 0, 360 );
+ sParticle->m_flRollDelta = random->RandomFloat( -2.0f, 2.0f );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : &data -
+//-----------------------------------------------------------------------------
+void HL1GibCallback( const CEffectData &data )
+{
+ FX_HL1Gib( data.m_vOrigin, data.m_vNormal, data.m_flScale, data.m_nMaterial, -data.m_nHitBox, data.m_nColor );
+}
+
+DECLARE_CLIENT_EFFECT( "HL1Gib", HL1GibCallback );
diff --git a/game/client/hl1/hl1_fx_impacts.cpp b/game/client/hl1/hl1_fx_impacts.cpp
new file mode 100644
index 0000000..d90b31b
--- /dev/null
+++ b/game/client/hl1/hl1_fx_impacts.cpp
@@ -0,0 +1,34 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Game-specific impact effect hooks
+//
+//=============================================================================//
+#include "cbase.h"
+#include "fx_impact.h"
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Handle weapon impacts
+//-----------------------------------------------------------------------------
+void ImpactCallback( const CEffectData &data )
+{
+ trace_t tr;
+ Vector vecOrigin, vecStart, vecShotDir;
+ int iMaterial, iDamageType, iHitbox;
+ short nSurfaceProp;
+ C_BaseEntity *pEntity = ParseImpactData( data, &vecOrigin, &vecStart, &vecShotDir, nSurfaceProp, iMaterial, iDamageType, iHitbox );
+
+ if ( !pEntity )
+ return;
+
+ // If we hit, perform our custom effects and play the sound
+ if ( Impact( vecOrigin, vecStart, iMaterial, iDamageType, iHitbox, pEntity, tr ) )
+ {
+ // Check for custom effects based on the Decal index
+ PerformCustomEffects( vecOrigin, tr, vecShotDir, iMaterial, 1.0 );
+ }
+
+ PlayImpactSound( pEntity, tr, vecOrigin, nSurfaceProp );
+}
+
+DECLARE_CLIENT_EFFECT( "Impact", ImpactCallback );
diff --git a/game/client/hl1/hl1_fx_shelleject.cpp b/game/client/hl1/hl1_fx_shelleject.cpp
new file mode 100644
index 0000000..ec95ed7
--- /dev/null
+++ b/game/client/hl1/hl1_fx_shelleject.cpp
@@ -0,0 +1,21 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+
+#include "cbase.h"
+#include "fx.h"
+#include "c_te_effect_dispatch.h"
+#include "c_te_legacytempents.h"
+
+
+void HL1ShellEjectCallback( const CEffectData &data )
+{
+ int iType = data.m_fFlags; // 0 = shell, 1 = shotgun shell
+
+ tempents->HL1EjectBrass( data.m_vOrigin, data.m_vAngles, data.m_vStart, iType );
+}
+
+DECLARE_CLIENT_EFFECT( "HL1ShellEject", HL1ShellEjectCallback );
diff --git a/game/client/hl1/hl1_hud_ammo.cpp b/game/client/hl1/hl1_hud_ammo.cpp
new file mode 100644
index 0000000..3fb52c8
--- /dev/null
+++ b/game/client/hl1/hl1_hud_ammo.cpp
@@ -0,0 +1,224 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "hud.h"
+#include "hudelement.h"
+#include "hud_macros.h"
+#include "iclientmode.h"
+#include "hl1_hud_numbers.h"
+
+#include <vgui/ISurface.h>
+#include <vgui_controls/Panel.h>
+#include "ihudlcd.h"
+
+#define MIN_ALPHA 100
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Displays current ammunition level
+//-----------------------------------------------------------------------------
+class CHudAmmo : public CHudElement, public CHL1HudNumbers
+{
+ DECLARE_CLASS_SIMPLE( CHudAmmo, CHL1HudNumbers );
+
+public:
+ CHudAmmo( const char *pElementName );
+ void Init( void );
+ void VidInit( void );
+ void OnThink( void );
+
+private:
+ void Paint( void );
+ void ApplySchemeSettings(vgui::IScheme *pScheme);
+
+private:
+ CHandle<C_BaseCombatWeapon> m_hLastPickedUpWeapon;
+ float m_flFade;
+};
+
+DECLARE_HUDELEMENT( CHudAmmo );
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CHudAmmo::CHudAmmo( const char *pElementName ) : CHudElement( pElementName ), BaseClass(NULL, "HudAmmo")
+{
+ SetHiddenBits( HIDEHUD_HEALTH | HIDEHUD_PLAYERDEAD | HIDEHUD_NEEDSUIT | HIDEHUD_WEAPONSELECTION );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudAmmo::Init( void )
+{
+ m_hLastPickedUpWeapon = NULL;
+ m_flFade = 0.0;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudAmmo::VidInit( void )
+{
+ Reset();
+
+ BaseClass::VidInit();
+}
+
+void CHudAmmo::OnThink( void )
+{
+ C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
+ if ( !pPlayer )
+ return;
+
+ // find and display our current selection
+ C_BaseCombatWeapon *pActiveWeapon = GetActiveWeapon();
+ if ( !pActiveWeapon )
+ {
+ m_hLastPickedUpWeapon = NULL;
+ return;
+ }
+
+ if ( m_hLastPickedUpWeapon != pActiveWeapon )
+ {
+ m_flFade = 200.0f;
+ m_hLastPickedUpWeapon = pActiveWeapon;
+ }
+}
+
+void CHudAmmo::Paint( void )
+{
+ int r, g, b, a, nUnused;
+ int x, y;
+ Color clrAmmo;
+
+ if (!ShouldDraw())
+ return;
+
+ C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
+ C_BaseCombatWeapon *pActiveWeapon = GetActiveWeapon();
+ // find and display our current selection
+
+ if ( !pPlayer || !pActiveWeapon )
+ {
+ hudlcd->SetGlobalStat( "(ammo_primary)", "n/a" );
+ hudlcd->SetGlobalStat( "(ammo_secondary)", "n/a" );
+ return;
+ }
+
+ hudlcd->SetGlobalStat( "(weapon_print_name)", pActiveWeapon ? pActiveWeapon->GetPrintName() : " " );
+ hudlcd->SetGlobalStat( "(weapon_name)", pActiveWeapon ? pActiveWeapon->GetName() : " " );
+
+ if ( ( pActiveWeapon->GetPrimaryAmmoType() == -1 ) && ( pActiveWeapon->GetSecondaryAmmoType() == -1 ) )
+ return;
+
+ int nFontWidth = GetNumberFontWidth();
+ int nFontHeight = GetNumberFontHeight();
+
+ a = (int)MAX( MIN_ALPHA, m_flFade );
+
+ if ( m_flFade > 0 )
+ m_flFade -= ( gpGlobals->frametime * 20 );
+
+ (gHUD.m_clrYellowish).GetColor( r, g, b, nUnused );
+ clrAmmo.SetColor( r, g, b, a );
+
+ int nHudElemWidth, nHudElemHeight;
+ GetSize( nHudElemWidth, nHudElemHeight );
+
+ // Does this weapon have a clip?
+ y = nHudElemHeight - ( nFontHeight * 1.5 );
+
+ // Does weapon have any ammo at all?
+ if ( pActiveWeapon->GetPrimaryAmmoType() != -1 )
+ {
+ CHudTexture *icon_ammo = gWR.GetAmmoIconFromWeapon( pActiveWeapon->GetPrimaryAmmoType() );
+
+ if ( !icon_ammo )
+ {
+ return;
+ }
+
+ int nIconWidth = icon_ammo->Width();
+
+ if ( pActiveWeapon->UsesClipsForAmmo1() )
+ {
+ // room for the number and the '|' and the current ammo
+
+ x = nHudElemWidth - (8 * nFontWidth) - nIconWidth;
+ x = DrawHudNumber( x, y, pActiveWeapon->Clip1(), clrAmmo );
+
+ int nBarWidth = nFontWidth / 10;
+
+ x += nFontWidth / 2;
+
+ (gHUD.m_clrYellowish).GetColor( r, g, b, nUnused );
+ clrAmmo.SetColor( r, g, b, a );
+
+ // draw the | bar
+ clrAmmo.SetColor( r, g, b, a );
+ vgui::surface()->DrawSetColor( clrAmmo );
+ vgui::surface()->DrawFilledRect( x, y, x + nBarWidth, y + nFontHeight );
+
+ x += nBarWidth + nFontWidth / 2;
+
+ x = DrawHudNumber( x, y, pPlayer->GetAmmoCount( pActiveWeapon->GetPrimaryAmmoType() ), clrAmmo );
+ }
+ else
+ {
+ // SPR_Draw a bullets only line
+ x = nHudElemWidth - 4 * nFontWidth - nIconWidth;
+ x = DrawHudNumber( x, y, pPlayer->GetAmmoCount( pActiveWeapon->GetPrimaryAmmoType() ), clrAmmo );
+ }
+
+ // Draw the ammo Icon
+ icon_ammo->DrawSelf( x, y, clrAmmo );
+
+ hudlcd->SetGlobalStat( "(ammo_primary)", VarArgs( "%d", pPlayer->GetAmmoCount( pActiveWeapon->GetPrimaryAmmoType() ) ) );
+ }
+ else
+ {
+ hudlcd->SetGlobalStat( "(ammo_primary)", "n/a" );
+ }
+
+ // Does weapon have seconday ammo?
+ if ( pActiveWeapon->GetSecondaryAmmoType() != -1 )
+ {
+ CHudTexture *icon_ammo = gWR.GetAmmoIconFromWeapon( pActiveWeapon->GetSecondaryAmmoType() );
+
+ if ( !icon_ammo )
+ {
+ return;
+ }
+
+ int nIconWidth = icon_ammo->Width();
+
+ // Do we have secondary ammo?
+ if ( pPlayer->GetAmmoCount( pActiveWeapon->GetSecondaryAmmoType() ) > 0 )
+ {
+ y -= ( nFontHeight * 1.25 );
+ x = nHudElemWidth - 4 * nFontWidth - nIconWidth;
+ x = DrawHudNumber( x, y, pPlayer->GetAmmoCount( pActiveWeapon->GetSecondaryAmmoType() ), clrAmmo );
+
+ // Draw the ammo Icon
+ icon_ammo->DrawSelf( x, y, clrAmmo );
+ }
+
+ hudlcd->SetGlobalStat( "(ammo_secondary)", VarArgs( "%d", pPlayer->GetAmmoCount( pActiveWeapon->GetSecondaryAmmoType() ) ) );
+ }
+ else
+ {
+ hudlcd->SetGlobalStat( "(ammo_secondary)", "n/a" );
+ }
+
+}
+
+void CHudAmmo::ApplySchemeSettings(vgui::IScheme *pScheme)
+{
+ BaseClass::ApplySchemeSettings(pScheme);
+ SetPaintBackgroundEnabled(false);
+}
diff --git a/game/client/hl1/hl1_hud_battery.cpp b/game/client/hl1/hl1_hud_battery.cpp
new file mode 100644
index 0000000..7582046
--- /dev/null
+++ b/game/client/hl1/hl1_hud_battery.cpp
@@ -0,0 +1,184 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "hud.h"
+#include "hud_macros.h"
+#include "view.h"
+
+#include "iclientmode.h"
+
+#include <KeyValues.h>
+#include <vgui/ISurface.h>
+#include <vgui/ISystem.h>
+#include <vgui_controls/Panel.h>
+
+using namespace vgui;
+
+#include "hudelement.h"
+#include "hl1_hud_numbers.h"
+
+#include "convar.h"
+
+#define FADE_TIME 100
+#define MIN_ALPHA 100
+
+//-----------------------------------------------------------------------------
+// Purpose: Health panel
+//-----------------------------------------------------------------------------
+class CHudBattery : public CHudElement, public CHL1HudNumbers
+{
+ DECLARE_CLASS_SIMPLE( CHudBattery, CHL1HudNumbers );
+
+public:
+ CHudBattery( const char *pElementName );
+
+ void Init( void );
+ void Reset( void );
+ void VidInit( void );
+ void MsgFunc_Battery(bf_read &msg);
+
+private:
+ void Paint( void );
+ void ApplySchemeSettings(vgui::IScheme *pScheme);
+
+private:
+ CHudTexture *icon_suit_empty;
+ CHudTexture *icon_suit_full;
+ int m_iBattery;
+ float m_flFade;
+};
+
+DECLARE_HUDELEMENT( CHudBattery );
+DECLARE_HUD_MESSAGE( CHudBattery, Battery );
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CHudBattery::CHudBattery( const char *pElementName ) : CHudElement( pElementName ), BaseClass(NULL, "HudSuit")
+{
+ SetHiddenBits( HIDEHUD_HEALTH | HIDEHUD_NEEDSUIT );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudBattery::Init()
+{
+ HOOK_HUD_MESSAGE( CHudBattery, Battery );
+ Reset();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudBattery::Reset()
+{
+ m_iBattery = 0;
+ m_flFade = 0;
+}
+
+void CHudBattery::VidInit()
+{
+ Reset();
+
+ BaseClass::VidInit();
+}
+
+void CHudBattery::Paint()
+{
+ Color clrHealth;
+ int a;
+ int x;
+ int y;
+
+ BaseClass::Paint();
+
+ if ( !icon_suit_empty )
+ {
+ icon_suit_empty = gHUD.GetIcon( "suit_empty" );
+ }
+
+ if ( !icon_suit_full )
+ {
+ icon_suit_full = gHUD.GetIcon( "suit_full" );
+ }
+
+ if ( !icon_suit_empty || !icon_suit_full )
+ {
+ return;
+ }
+
+ // Has health changed? Flash the health #
+ if ( m_flFade )
+ {
+ if (m_flFade > FADE_TIME)
+ m_flFade = FADE_TIME;
+
+ m_flFade -= ( gpGlobals->frametime * 20 );
+ if ( m_flFade <= 0 )
+ {
+ a = 128;
+ m_flFade = 0;
+ }
+ else
+ {
+ // Fade the health number back to dim
+ a = MIN_ALPHA + ( m_flFade / FADE_TIME ) * 128;
+ }
+ }
+ else
+ {
+ a = MIN_ALPHA;
+ }
+
+ int r, g, b, nUnused;
+ (gHUD.m_clrYellowish).GetColor( r, g, b, nUnused );
+ clrHealth.SetColor( r, g, b, a );
+
+ int nFontHeight = GetNumberFontHeight();
+
+ int nHudElemWidth, nHudElemHeight;
+ GetSize( nHudElemWidth, nHudElemHeight );
+
+ int iOffset = icon_suit_empty->Height() / 6;
+
+ x = nHudElemWidth / 5;
+ y = nHudElemHeight - ( nFontHeight * 1.5 );
+
+ icon_suit_empty->DrawSelf( x, y - iOffset, clrHealth );
+
+ if ( m_iBattery > 0 )
+ {
+ int nSuitOffset = icon_suit_full->Height() * ((float)(100-(MIN(100,m_iBattery))) * 0.01); // battery can go from 0 to 100 so * 0.01 goes from 0 to 1
+ icon_suit_full->DrawSelfCropped( x, y - iOffset + nSuitOffset, 0, nSuitOffset, icon_suit_full->Width(), icon_suit_full->Height() - nSuitOffset, clrHealth );
+ }
+
+ x += icon_suit_empty->Width();
+ DrawHudNumber( x, y, m_iBattery, clrHealth );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudBattery::MsgFunc_Battery( bf_read &msg )
+{
+ int x = msg.ReadShort();
+
+ if ( x != m_iBattery )
+ {
+ m_flFade = FADE_TIME;
+ m_iBattery = x;
+ }
+}
+
+void CHudBattery::ApplySchemeSettings(vgui::IScheme *pScheme)
+{
+ BaseClass::ApplySchemeSettings(pScheme);
+ SetPaintBackgroundEnabled(false);
+}
diff --git a/game/client/hl1/hl1_hud_damageindicator.cpp b/game/client/hl1/hl1_hud_damageindicator.cpp
new file mode 100644
index 0000000..9cdc0fc
--- /dev/null
+++ b/game/client/hl1/hl1_hud_damageindicator.cpp
@@ -0,0 +1,331 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "hud.h"
+#include "text_message.h"
+#include "hud_macros.h"
+#include "iclientmode.h"
+#include "view.h"
+#include <KeyValues.h>
+#include <vgui/ISurface.h>
+#include <vgui_controls/Panel.h>
+#include "VGuiMatSurface/IMatSystemSurface.h"
+#include "materialsystem/imaterial.h"
+#include "materialsystem/imesh.h"
+#include "materialsystem/imaterialvar.h"
+#include "IEffects.h"
+#include "hudelement.h"
+
+using namespace vgui;
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+//-----------------------------------------------------------------------------
+// Purpose: HDU Damage indication
+//-----------------------------------------------------------------------------
+class CHudDamageIndicator : public CHudElement, public vgui::Panel
+{
+ DECLARE_CLASS_SIMPLE( CHudDamageIndicator, vgui::Panel );
+
+public:
+ CHudDamageIndicator( const char *pElementName );
+
+ void Init( void );
+ void Reset( void );
+ bool ShouldDraw( void );
+
+ // Handler for our message
+ void MsgFunc_Damage(bf_read &msg);
+
+private:
+ void Paint();
+ void ApplySchemeSettings(vgui::IScheme *pScheme);
+
+private:
+ void CalcDamageDirection( const Vector &vecFrom );
+ void DrawDamageIndicatorFront( float flFade );
+ void DrawDamageIndicatorRear( float flFade );
+ void DrawDamageIndicatorLeft( float flFade );
+ void DrawDamageIndicatorRight( float flFade );
+
+private:
+ float m_flAttackFront;
+ float m_flAttackRear;
+ float m_flAttackLeft;
+ float m_flAttackRight;
+
+ Color m_clrIndicator;
+
+ CHudTexture *icon_up;
+ CHudTexture *icon_down;
+ CHudTexture *icon_left;
+ CHudTexture *icon_right;
+};
+
+DECLARE_HUDELEMENT( CHudDamageIndicator );
+DECLARE_HUD_MESSAGE( CHudDamageIndicator, Damage );
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CHudDamageIndicator::CHudDamageIndicator( const char *pElementName ) : CHudElement( pElementName ), BaseClass(NULL, "HudDamageIndicator")
+{
+ vgui::Panel *pParent = g_pClientMode->GetViewport();
+ SetParent( pParent );
+
+ SetHiddenBits( HIDEHUD_HEALTH );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudDamageIndicator::Reset( void )
+{
+ m_flAttackFront = 0.0;
+ m_flAttackRear = 0.0;
+ m_flAttackRight = 0.0;
+ m_flAttackLeft = 0.0;
+
+ m_clrIndicator.SetColor( 250, 0, 0, 255 );
+}
+
+void CHudDamageIndicator::Init( void )
+{
+ HOOK_HUD_MESSAGE( CHudDamageIndicator, Damage );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CHudDamageIndicator::ShouldDraw( void )
+{
+ if ( !CHudElement::ShouldDraw() )
+ return false;
+
+ if ( ( m_flAttackFront <= 0.0 ) && ( m_flAttackRear <= 0.0 ) && ( m_flAttackLeft <= 0.0 ) && ( m_flAttackRight <= 0.0 ) )
+ return false;
+
+ return true;
+}
+
+void CHudDamageIndicator::DrawDamageIndicatorFront( float flFade )
+{
+ if ( m_flAttackFront > 0.4 )
+ {
+ if ( !icon_up )
+ {
+ icon_up = gHUD.GetIcon( "pain_up" );
+ }
+
+ if ( !icon_up )
+ {
+ return;
+ }
+
+ int x = ( ScreenWidth() / 2 ) - icon_up->Width() / 2;
+ int y = ( ScreenHeight() / 2 ) - icon_up->Height() * 3;
+ icon_up->DrawSelf( x, y, m_clrIndicator );
+
+ m_flAttackFront = MAX( 0.0, m_flAttackFront - flFade );
+ }
+ else
+ {
+ m_flAttackFront = 0.0;
+ }
+}
+
+void CHudDamageIndicator::DrawDamageIndicatorRear( float flFade )
+{
+ if ( m_flAttackRear > 0.4 )
+ {
+ if ( !icon_down )
+ {
+ icon_down = gHUD.GetIcon( "pain_down" );
+ }
+
+ if ( !icon_down )
+ {
+ return;
+ }
+
+ int x = ( ScreenWidth() / 2 ) - icon_down->Width() / 2;
+ int y = ( ScreenHeight() / 2 ) + icon_down->Height() * 2;
+ icon_down->DrawSelf( x, y, m_clrIndicator );
+
+ m_flAttackRear = MAX( 0.0, m_flAttackRear - flFade );
+ }
+ else
+ {
+ m_flAttackRear = 0.0;
+ }
+}
+
+
+void CHudDamageIndicator::DrawDamageIndicatorLeft( float flFade )
+{
+ if ( m_flAttackLeft > 0.4 )
+ {
+ if ( !icon_left )
+ {
+ icon_left = gHUD.GetIcon( "pain_left" );
+ }
+
+ if ( !icon_left )
+ {
+ return;
+ }
+
+ int x = ( ScreenWidth() / 2 ) - icon_left->Width() * 3;
+ int y = ( ScreenHeight() / 2 ) - icon_left->Height() / 2;
+ icon_left->DrawSelf( x, y, m_clrIndicator );
+
+ m_flAttackLeft = MAX( 0.0, m_flAttackLeft - flFade );
+ }
+ else
+ {
+ m_flAttackLeft = 0.0;
+ }
+}
+
+
+void CHudDamageIndicator::DrawDamageIndicatorRight( float flFade )
+{
+ if ( m_flAttackRight > 0.4 )
+ {
+ if ( !icon_right )
+ {
+ icon_right = gHUD.GetIcon( "pain_right" );
+ }
+
+ if ( !icon_right )
+ {
+ return;
+ }
+
+ int x = ( ScreenWidth() / 2 ) + icon_right->Width() * 2;
+ int y = ( ScreenHeight() / 2 ) - icon_right->Height() / 2;
+ icon_right->DrawSelf( x, y, m_clrIndicator );
+
+ m_flAttackRight = MAX( 0.0, m_flAttackRight - flFade );
+ }
+ else
+ {
+ m_flAttackRight = 0.0;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Paints the damage display
+//-----------------------------------------------------------------------------
+void CHudDamageIndicator::Paint()
+{
+ // draw damage indicators
+ float flFade = gpGlobals->frametime * 2;
+ DrawDamageIndicatorFront( flFade );
+ DrawDamageIndicatorRear( flFade );
+ DrawDamageIndicatorLeft( flFade );
+ DrawDamageIndicatorRight( flFade);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Message handler for Damage message
+//-----------------------------------------------------------------------------
+void CHudDamageIndicator::MsgFunc_Damage( bf_read &msg )
+{
+ int armor = msg.ReadByte(); // armor
+ int damageTaken = msg.ReadByte(); // health
+ msg.ReadLong(); // damage bits, ignore
+ Vector vecFrom;
+ vecFrom.x = msg.ReadFloat();
+ vecFrom.y = msg.ReadFloat();
+ vecFrom.z = msg.ReadFloat();
+
+ if ( damageTaken > 0 || armor > 0 )
+ {
+ CalcDamageDirection( vecFrom );
+ }
+}
+
+void CHudDamageIndicator::CalcDamageDirection( const Vector &vecFrom )
+{
+ if ( vecFrom == vec3_origin )
+ {
+ m_flAttackFront = 0.0;
+ m_flAttackRear = 0.0;
+ m_flAttackRight = 0.0;
+ m_flAttackLeft = 0.0;
+
+ return;
+ }
+
+ C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
+ if ( !pLocalPlayer )
+ {
+ return;
+ }
+
+ Vector vecDelta = ( vecFrom - pLocalPlayer->GetRenderOrigin() );
+
+ if ( vecDelta.Length() <= 50 )
+ {
+ m_flAttackFront = 1.0;
+ m_flAttackRear = 1.0;
+ m_flAttackRight = 1.0;
+ m_flAttackLeft = 1.0;
+
+ return;
+ }
+
+ VectorNormalize( vecDelta );
+
+ Vector forward;
+ Vector right;
+ AngleVectors( MainViewAngles(), &forward, &right, NULL );
+
+ float flFront = DotProduct( vecDelta, forward );
+ float flSide = DotProduct( vecDelta, right );
+
+ if ( flFront > 0 )
+ {
+ if ( flFront > 0.3 )
+ m_flAttackFront = MAX( m_flAttackFront, flFront );
+ }
+ else
+ {
+ float f = fabs( flFront );
+ if ( f > 0.3 )
+ m_flAttackRear = MAX( m_flAttackRear, f );
+ }
+
+ if ( flSide > 0 )
+ {
+ if ( flSide > 0.3 )
+ m_flAttackRight = MAX( m_flAttackRight, flSide );
+ }
+ else
+ {
+ float f = fabs( flSide );
+ if ( f > 0.3 )
+ m_flAttackLeft = MAX( m_flAttackLeft, f );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: hud scheme settings
+//-----------------------------------------------------------------------------
+void CHudDamageIndicator::ApplySchemeSettings(vgui::IScheme *pScheme)
+{
+ BaseClass::ApplySchemeSettings(pScheme);
+ SetPaintBackgroundEnabled(false);
+
+ int wide, tall;
+ GetHudSize(wide, tall);
+ SetSize(wide, tall);
+}
diff --git a/game/client/hl1/hl1_hud_damagetiles.cpp b/game/client/hl1/hl1_hud_damagetiles.cpp
new file mode 100644
index 0000000..cc21c51
--- /dev/null
+++ b/game/client/hl1/hl1_hud_damagetiles.cpp
@@ -0,0 +1,322 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+
+#include "cbase.h"
+#include "hud.h"
+#include "text_message.h"
+#include "hud_macros.h"
+#include "iclientmode.h"
+#include "view.h"
+#include <KeyValues.h>
+#include <vgui/ISurface.h>
+#include <vgui_controls/Panel.h>
+#include "VGuiMatSurface/IMatSystemSurface.h"
+#include "materialsystem/imaterial.h"
+#include "materialsystem/imesh.h"
+#include "materialsystem/imaterialvar.h"
+#include "IEffects.h"
+#include "hudelement.h"
+
+using namespace vgui;
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+#define DMG_IMAGE_LIFE 2 // seconds that image is up
+#define NUM_DMG_TYPES 8
+
+typedef struct
+{
+ float flExpire;
+ float flBaseline;
+ int x;
+ int y;
+ CHudTexture *icon;
+ long fFlags;
+} damagetile_t;
+
+//-----------------------------------------------------------------------------
+// Purpose: HDU Damage type tiles
+//-----------------------------------------------------------------------------
+class CHudDamageTiles : public CHudElement, public vgui::Panel
+{
+ DECLARE_CLASS_SIMPLE( CHudDamageTiles, vgui::Panel );
+
+public:
+ CHudDamageTiles( const char *pElementName );
+
+ void Init( void );
+ void VidInit( void );
+ void Reset( void );
+ bool ShouldDraw( void );
+
+ // Handler for our message
+ void MsgFunc_Damage(bf_read &msg);
+
+private:
+ void Paint();
+ void ApplySchemeSettings(vgui::IScheme *pScheme);
+
+private:
+ CHudTexture *DamageTileIcon( int i );
+ long DamageTileFlags( int i );
+ void UpdateTiles( long bits );
+
+private:
+ long m_bitsDamage;
+ damagetile_t m_dmgTileInfo[ NUM_DMG_TYPES ];
+};
+
+
+DECLARE_HUDELEMENT( CHudDamageTiles );
+DECLARE_HUD_MESSAGE( CHudDamageTiles, Damage );
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CHudDamageTiles::CHudDamageTiles( const char *pElementName ) : CHudElement( pElementName ), BaseClass(NULL, "HudDamageTiles")
+{
+ vgui::Panel *pParent = g_pClientMode->GetViewport();
+ SetParent( pParent );
+
+ SetHiddenBits( HIDEHUD_HEALTH | HIDEHUD_PLAYERDEAD | HIDEHUD_NEEDSUIT );
+}
+
+void CHudDamageTiles::Init( void )
+{
+ HOOK_HUD_MESSAGE( CHudDamageTiles, Damage );
+}
+
+
+void CHudDamageTiles::VidInit( void )
+{
+ Reset();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudDamageTiles::Reset( void )
+{
+ m_bitsDamage = 0;
+ for ( int i = 0; i < NUM_DMG_TYPES; i++ )
+ {
+ m_dmgTileInfo[ i ].flExpire = 0;
+ m_dmgTileInfo[ i ].flBaseline = 0;
+ m_dmgTileInfo[ i ].x = 0;
+ m_dmgTileInfo[ i ].y = 0;
+ m_dmgTileInfo[ i ].icon = DamageTileIcon( i );
+ m_dmgTileInfo[ i ].fFlags = DamageTileFlags( i );
+ }
+}
+
+
+CHudTexture *CHudDamageTiles::DamageTileIcon( int i )
+{
+ switch ( i )
+ {
+ case 0:
+ default:
+ return gHUD.GetIcon( "dmg_poison" );
+ break;
+ case 1:
+ return gHUD.GetIcon( "dmg_chem" );
+ break;
+ case 2:
+ return gHUD.GetIcon( "dmg_cold" );
+ break;
+ case 3:
+ return gHUD.GetIcon( "dmg_drown" );
+ break;
+ case 4:
+ return gHUD.GetIcon( "dmg_heat" );
+ break;
+ case 5:
+ return gHUD.GetIcon( "dmg_gas" );
+ break;
+ case 6:
+ return gHUD.GetIcon( "dmg_rad" );
+ break;
+ case 7:
+ return gHUD.GetIcon( "dmg_shock" );
+ break;
+ }
+}
+
+long CHudDamageTiles::DamageTileFlags( int i )
+{
+ switch ( i )
+ {
+ case 0:
+ default:
+ return DMG_POISON;
+
+ case 1:
+ return DMG_ACID;
+
+ case 2:
+ // HL2 hijacked DMG_FREEZE and made it DMG_VEHICLE
+ // HL2 hijacked DMG_SLOWFREEZE and made it DMG_DISSOLVE
+// return DMG_FREEZE | DMG_SLOWFREEZE;
+ return DMG_VEHICLE | DMG_DISSOLVE;
+
+ case 3:
+ return DMG_DROWN;
+
+ case 4:
+ return DMG_BURN | DMG_SLOWBURN;
+
+ case 5:
+ return DMG_NERVEGAS;
+
+ case 6:
+ return DMG_RADIATION;
+
+ case 7:
+ return DMG_SHOCK;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Message handler for Damage message
+//-----------------------------------------------------------------------------
+void CHudDamageTiles::MsgFunc_Damage( bf_read &msg )
+{
+ msg.ReadByte(); // armor
+ msg.ReadByte(); // health
+ long bitsDamage = msg.ReadLong(); // damage bits, ignore
+
+ UpdateTiles( bitsDamage );
+}
+
+bool CHudDamageTiles::ShouldDraw( void )
+{
+ if ( !CHudElement::ShouldDraw() )
+ return false;
+
+ if ( !m_bitsDamage )
+ return false;
+
+ return true;
+}
+
+void CHudDamageTiles::Paint( void )
+{
+ int r, g, b, a, nUnused;
+ damagetile_t *pDmgTile;
+ Color clrTile;
+
+ (gHUD.m_clrYellowish).GetColor( r, g, b, nUnused );
+ a = (int)( fabs( sin( gpGlobals->curtime * 2 ) ) * 256.0 );
+ clrTile.SetColor( r, g, b, a );
+
+ int i;
+ // Draw all the items
+ for ( i = 0; i < NUM_DMG_TYPES; i++ )
+ {
+ pDmgTile = &m_dmgTileInfo[ i ];
+ if ( m_bitsDamage & pDmgTile->fFlags )
+ {
+ if ( pDmgTile->icon )
+ {
+ ( pDmgTile->icon )->DrawSelf( pDmgTile->x, pDmgTile->y, clrTile );
+ }
+ }
+ }
+
+ // check for bits that should be expired
+ for ( i = 0; i < NUM_DMG_TYPES; i++ )
+ {
+ pDmgTile = &m_dmgTileInfo[ i ];
+
+ if ( m_bitsDamage & pDmgTile->fFlags )
+ {
+ pDmgTile->flExpire = MIN( gpGlobals->curtime + DMG_IMAGE_LIFE, pDmgTile->flExpire );
+
+ if ( pDmgTile->flExpire <= gpGlobals->curtime // when the time has expired
+ && a < 40 ) // and the flash is at the low point of the cycle
+ {
+ pDmgTile->flExpire = 0;
+
+ int y = pDmgTile->y;
+ pDmgTile->x = 0;
+ pDmgTile->y = 0;
+
+ m_bitsDamage &= ~pDmgTile->fFlags; // clear the bits
+
+ // move everyone above down
+ for ( int j = 0; j < NUM_DMG_TYPES; j++ )
+ {
+ damagetile_t *pDmgTileIter = &m_dmgTileInfo[ j ];
+ if ( ( pDmgTileIter->y ) && ( pDmgTileIter->y < y ) && ( pDmgTileIter->icon ) )
+ pDmgTileIter->y += ( pDmgTileIter->icon )->Height();
+ }
+ }
+ }
+ }
+}
+
+
+void CHudDamageTiles::UpdateTiles( long bitsDamage )
+{
+ damagetile_t *pDmgTile;
+
+ // Which types are new?
+ long bitsOn = ~m_bitsDamage & bitsDamage;
+
+ for ( int i = 0; i < NUM_DMG_TYPES; i++ )
+ {
+ pDmgTile = &m_dmgTileInfo[ i ];
+
+ // Is this one already on?
+ if ( m_bitsDamage & pDmgTile->fFlags )
+ {
+ pDmgTile->flExpire = gpGlobals->curtime + DMG_IMAGE_LIFE; // extend the duration
+ if ( !pDmgTile->flBaseline )
+ {
+ pDmgTile->flBaseline = gpGlobals->curtime;
+ }
+ }
+
+ // Are we just turning it on?
+ if ( bitsOn & pDmgTile->fFlags )
+ {
+ // put this one at the bottom
+ if ( pDmgTile->icon )
+ {
+ pDmgTile->x = ( pDmgTile->icon )->Width() / 8;
+ pDmgTile->y = GetTall() - ( pDmgTile->icon )->Height() * 2;
+ }
+ pDmgTile->flExpire = gpGlobals->curtime + DMG_IMAGE_LIFE;
+
+ // move everyone else up
+ for ( int j = 0; j < NUM_DMG_TYPES; j++ )
+ {
+ if ( j == i )
+ continue;
+
+ pDmgTile = &m_dmgTileInfo[ j ];
+ if ( pDmgTile->y && pDmgTile->icon )
+ pDmgTile->y -= ( pDmgTile->icon )->Height();
+
+ }
+ pDmgTile = &m_dmgTileInfo[ i ];
+ }
+ }
+
+ // damage bits are only turned on here; they are turned off when the draw time has expired (in Paint())
+ m_bitsDamage |= bitsDamage;
+}
+
+void CHudDamageTiles::ApplySchemeSettings(vgui::IScheme *pScheme)
+{
+ BaseClass::ApplySchemeSettings(pScheme);
+ SetPaintBackgroundEnabled(false);
+}
diff --git a/game/client/hl1/hl1_hud_deathnotice.cpp b/game/client/hl1/hl1_hud_deathnotice.cpp
new file mode 100644
index 0000000..3118e92
--- /dev/null
+++ b/game/client/hl1/hl1_hud_deathnotice.cpp
@@ -0,0 +1,358 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Draws CSPort's death notices
+//
+// $NoKeywords: $
+//=============================================================================//
+#include "cbase.h"
+#include "hudelement.h"
+#include "hud_macros.h"
+#include "c_playerresource.h"
+//#include "clientmode_hl2mpnormal.h"
+#include "iclientmode.h"
+#include "hl1_clientmode.h"
+#include <vgui_controls/Controls.h>
+#include <vgui_controls/Panel.h>
+#include <vgui/ISurface.h>
+#include <vgui/ILocalize.h>
+#include <KeyValues.h>
+#include "c_baseplayer.h"
+#include "c_team.h"
+
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+static ConVar hud_deathnotice_time( "hud_deathnotice_time", "6", 0 );
+
+// Player entries in a death notice
+struct DeathNoticePlayer
+{
+ char szName[MAX_PLAYER_NAME_LENGTH];
+ int iEntIndex;
+};
+
+// Contents of each entry in our list of death notices
+struct DeathNoticeItem
+{
+ DeathNoticePlayer Killer;
+ DeathNoticePlayer Victim;
+ CHudTexture *iconDeath;
+ int iSuicide;
+ float flDisplayTime;
+ bool bHeadshot;
+};
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+class CHudDeathNotice : public CHudElement, public vgui::Panel
+{
+ DECLARE_CLASS_SIMPLE( CHudDeathNotice, vgui::Panel );
+public:
+ CHudDeathNotice( const char *pElementName );
+
+ void Init( void );
+ void VidInit( void );
+ virtual bool ShouldDraw( void );
+ virtual void Paint( void );
+ virtual void ApplySchemeSettings( vgui::IScheme *scheme );
+
+ void SetColorForNoticePlayer( int iTeamNumber );
+ void RetireExpiredDeathNotices( void );
+
+ virtual void FireGameEvent( IGameEvent * event );
+
+
+private:
+
+ CPanelAnimationVarAliasType( float, m_flLineHeight, "LineHeight", "15", "proportional_float" );
+
+ CPanelAnimationVar( float, m_flMaxDeathNotices, "MaxDeathNotices", "4" );
+
+ CPanelAnimationVar( bool, m_bRightJustify, "RightJustify", "1" );
+
+// CPanelAnimationVar( vgui::HFont, m_hTextFont, "TextFont", "HudNumbersTimer" );
+ // TODO : use another font
+ CPanelAnimationVar( vgui::HFont, m_hTextFont, "TextFont", "Default" );
+
+ // Texture for skull symbol
+ CHudTexture *m_iconD_skull;
+ CHudTexture *m_iconD_headshot;
+
+ CUtlVector<DeathNoticeItem> m_DeathNotices;
+};
+
+using namespace vgui;
+
+DECLARE_HUDELEMENT( CHudDeathNotice );
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CHudDeathNotice::CHudDeathNotice( const char *pElementName ) :
+ CHudElement( pElementName ), BaseClass( NULL, "HudDeathNotice" )
+{
+ vgui::Panel *pParent = g_pClientMode->GetViewport();
+ SetParent( pParent );
+
+ m_iconD_headshot = NULL;
+ m_iconD_skull = NULL;
+
+ SetHiddenBits( HIDEHUD_MISCSTATUS );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudDeathNotice::ApplySchemeSettings( IScheme *scheme )
+{
+ BaseClass::ApplySchemeSettings( scheme );
+ SetPaintBackgroundEnabled( false );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudDeathNotice::Init( void )
+{
+ ListenForGameEvent( "player_death" );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudDeathNotice::VidInit( void )
+{
+ m_iconD_skull = gHUD.GetIcon( "d_skull" );
+ m_DeathNotices.Purge();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Draw if we've got at least one death notice in the queue
+//-----------------------------------------------------------------------------
+bool CHudDeathNotice::ShouldDraw( void )
+{
+ return ( CHudElement::ShouldDraw() && ( m_DeathNotices.Count() ) );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudDeathNotice::SetColorForNoticePlayer( int iTeamNumber )
+{
+ surface()->DrawSetTextColor( GameResources()->GetTeamColor( iTeamNumber ) );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudDeathNotice::Paint()
+{
+ if ( !m_iconD_skull )
+ return;
+
+ int yStart = GetClientModeHL1Normal()->GetDeathMessageStartHeight();//GetClientModeHL2MPNormal()->GetDeathMessageStartHeight();
+
+ surface()->DrawSetTextFont( m_hTextFont );
+ surface()->DrawSetTextColor( GameResources()->GetTeamColor( 0 ) );
+ if ( GetWide() != ScreenWidth() )
+ SetSize( ScreenWidth(), GetTall() );
+
+ int iCount = m_DeathNotices.Count();
+ for ( int i = 0; i < iCount; i++ )
+ {
+ CHudTexture *icon = m_DeathNotices[i].iconDeath;
+ if ( !icon )
+ continue;
+
+ wchar_t victim[ 256 ];
+ wchar_t killer[ 256 ];
+
+ // Get the team numbers for the players involved
+ int iKillerTeam = 0;
+ int iVictimTeam = 0;
+
+ if( g_PR )
+ {
+ iKillerTeam = g_PR->GetTeam( m_DeathNotices[i].Killer.iEntIndex );
+ iVictimTeam = g_PR->GetTeam( m_DeathNotices[i].Victim.iEntIndex );
+ }
+
+ g_pVGuiLocalize->ConvertANSIToUnicode( m_DeathNotices[i].Victim.szName, victim, sizeof( victim ) );
+ g_pVGuiLocalize->ConvertANSIToUnicode( m_DeathNotices[i].Killer.szName, killer, sizeof( killer ) );
+
+ // Get the local position for this notice
+ int len = UTIL_ComputeStringWidth( m_hTextFont, victim );
+ int y = yStart + (m_flLineHeight * i);
+
+ int iconWide;
+ int iconTall;
+
+ if( icon->bRenderUsingFont )
+ {
+ iconWide = surface()->GetCharacterWidth( icon->hFont, icon->cCharacterInFont );
+ iconTall = surface()->GetFontTall( icon->hFont );
+ }
+ else
+ {
+ float scale = ( (float)ScreenHeight() / 480.0f ); //scale based on 640x480
+ iconWide = (int)( scale * (float)icon->Width() );
+ iconTall = (int)( scale * (float)icon->Height() );
+ }
+
+ int x;
+ if ( m_bRightJustify )
+ {
+ x = ScreenWidth() - len - iconWide;
+ }
+ else
+ {
+ x = 0;
+ }
+
+ // Only draw killers name if it wasn't a suicide
+ if ( !m_DeathNotices[i].iSuicide )
+ {
+ if ( m_bRightJustify )
+ {
+ x -= UTIL_ComputeStringWidth( m_hTextFont, killer );
+ }
+
+ SetColorForNoticePlayer( iKillerTeam );
+
+ // Draw killer's name
+ surface()->DrawSetTextPos( x, y );
+ surface()->DrawSetTextFont( m_hTextFont );
+ surface()->DrawUnicodeString( killer );
+ surface()->DrawGetTextPos( x, y );
+ }
+
+ Color iconColor( 255, 80, 0, 255 );
+
+ // Draw death weapon
+ //If we're using a font char, this will ignore iconTall and iconWide
+ icon->DrawSelf( x, y, iconWide, iconTall, iconColor );
+ x += iconWide;
+
+ SetColorForNoticePlayer( iVictimTeam );
+
+ // Draw victims name
+ surface()->DrawSetTextPos( x, y );
+ surface()->DrawSetTextFont( m_hTextFont ); //reset the font, draw icon can change it
+ surface()->DrawUnicodeString( victim );
+ }
+
+ // Now retire any death notices that have expired
+ RetireExpiredDeathNotices();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: This message handler may be better off elsewhere
+//-----------------------------------------------------------------------------
+void CHudDeathNotice::RetireExpiredDeathNotices( void )
+{
+ // Loop backwards because we might remove one
+ int iSize = m_DeathNotices.Size();
+ for ( int i = iSize-1; i >= 0; i-- )
+ {
+ if ( m_DeathNotices[i].flDisplayTime < gpGlobals->curtime )
+ {
+ m_DeathNotices.Remove(i);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Server's told us that someone's died
+//-----------------------------------------------------------------------------
+void CHudDeathNotice::FireGameEvent( IGameEvent * event )
+{
+ if (!g_PR)
+ return;
+
+ if ( hud_deathnotice_time.GetFloat() == 0 )
+ return;
+
+ // the event should be "player_death"
+ int killer = engine->GetPlayerForUserID( event->GetInt("attacker") );
+ int victim = engine->GetPlayerForUserID( event->GetInt("userid") );
+ const char *killedwith = event->GetString( "weapon" );
+
+ char fullkilledwith[128];
+ if ( killedwith && *killedwith )
+ {
+ Q_snprintf( fullkilledwith, sizeof(fullkilledwith), "death_%s", killedwith );
+ }
+ else
+ {
+ fullkilledwith[0] = 0;
+ }
+
+ // Do we have too many death messages in the queue?
+ if ( m_DeathNotices.Count() > 0 &&
+ m_DeathNotices.Count() >= (int)m_flMaxDeathNotices )
+ {
+ // Remove the oldest one in the queue, which will always be the first
+ m_DeathNotices.Remove(0);
+ }
+
+ // Get the names of the players
+ const char *killer_name = g_PR->GetPlayerName( killer );
+ const char *victim_name = g_PR->GetPlayerName( victim );
+
+ if ( !killer_name )
+ killer_name = "";
+ if ( !victim_name )
+ victim_name = "";
+
+ // Make a new death notice
+ DeathNoticeItem deathMsg;
+ deathMsg.Killer.iEntIndex = killer;
+ deathMsg.Victim.iEntIndex = victim;
+ Q_strncpy( deathMsg.Killer.szName, killer_name, MAX_PLAYER_NAME_LENGTH );
+ Q_strncpy( deathMsg.Victim.szName, victim_name, MAX_PLAYER_NAME_LENGTH );
+ deathMsg.flDisplayTime = gpGlobals->curtime + hud_deathnotice_time.GetFloat();
+ deathMsg.iSuicide = ( !killer || killer == victim );
+
+ // Try and find the death identifier in the icon list
+ deathMsg.iconDeath = gHUD.GetIcon( fullkilledwith );
+
+ if ( !deathMsg.iconDeath || deathMsg.iSuicide )
+ {
+ // Can't find it, so use the default skull & crossbones icon
+ deathMsg.iconDeath = m_iconD_skull;
+ }
+
+ // Add it to our list of death notices
+ m_DeathNotices.AddToTail( deathMsg );
+
+ char sDeathMsg[512];
+
+ // Record the death notice in the console
+ if ( deathMsg.iSuicide )
+ {
+ if ( !strcmp( fullkilledwith, "d_worldspawn" ) )
+ {
+ Q_snprintf( sDeathMsg, sizeof( sDeathMsg ), "%s died.\n", deathMsg.Victim.szName );
+ }
+ else //d_world
+ {
+ Q_snprintf( sDeathMsg, sizeof( sDeathMsg ), "%s suicided.\n", deathMsg.Victim.szName );
+ }
+ }
+ else
+ {
+ Q_snprintf( sDeathMsg, sizeof( sDeathMsg ), "%s killed %s", deathMsg.Killer.szName, deathMsg.Victim.szName );
+
+ if ( fullkilledwith && *fullkilledwith && (*fullkilledwith > 13 ) )
+ {
+ Q_strncat( sDeathMsg, VarArgs( " with %s.\n", fullkilledwith+6 ), sizeof( sDeathMsg ), COPY_ALL_CHARACTERS );
+ }
+ }
+
+ Msg( "%s\n", sDeathMsg );
+}
+
+
+
diff --git a/game/client/hl1/hl1_hud_flashlight.cpp b/game/client/hl1/hl1_hud_flashlight.cpp
new file mode 100644
index 0000000..c3872b7
--- /dev/null
+++ b/game/client/hl1/hl1_hud_flashlight.cpp
@@ -0,0 +1,132 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+
+#include "cbase.h"
+#include "hud.h"
+#include "hudelement.h"
+#include "hud_macros.h"
+#include "iclientmode.h"
+#include "hl1_c_player.h"
+
+#include <vgui/ISurface.h>
+#include <vgui_controls/Panel.h>
+
+
+#define MIN_ALPHA 100
+
+
+class CHudFlashlight : public CHudElement, public vgui::Panel
+{
+ DECLARE_CLASS_SIMPLE( CHudFlashlight, vgui::Panel );
+
+public:
+ CHudFlashlight( const char *pElementName );
+
+private:
+ void Paint( void );
+ void ApplySchemeSettings(vgui::IScheme *pScheme);
+
+private:
+ CHudTexture *icon_flash_empty;
+ CHudTexture *icon_flash_full;
+ CHudTexture *icon_flash_beam;
+ Color m_clrReddish;
+};
+
+DECLARE_HUDELEMENT( CHudFlashlight );
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CHudFlashlight::CHudFlashlight( const char *pElementName ) : CHudElement( pElementName ), BaseClass(NULL, "HudFlashlight")
+{
+ vgui::Panel *pParent = g_pClientMode->GetViewport();
+ SetParent( pParent );
+
+ SetHiddenBits( HIDEHUD_HEALTH | HIDEHUD_PLAYERDEAD | HIDEHUD_NEEDSUIT );
+}
+
+void CHudFlashlight::Paint( void )
+{
+ int r, g, b, a, nUnused;
+ int x, y;
+ bool bIsOn;
+ Color clrFlash;
+
+ C_HL1_Player *pPlayer = ToHL1Player( C_HL1_Player::GetLocalPlayer() );
+ if ( !pPlayer )
+ return;
+
+ if ( !icon_flash_empty )
+ {
+ icon_flash_empty = gHUD.GetIcon( "flash_empty" );
+ }
+
+ if ( !icon_flash_full )
+ {
+ icon_flash_full = gHUD.GetIcon( "flash_full" );
+ }
+
+ if ( !icon_flash_beam )
+ {
+ icon_flash_beam = gHUD.GetIcon( "flash_beam" );
+ }
+
+ if ( !icon_flash_empty || !icon_flash_full || !icon_flash_beam )
+ {
+ return;
+ }
+
+ bIsOn = pPlayer->IsEffectActive( EF_DIMLIGHT );
+
+ if ( bIsOn )
+ a = 225;
+ else
+ a = MIN_ALPHA;
+
+ if ( pPlayer->m_nFlashBattery < 20 )
+ {
+ m_clrReddish.GetColor( r, g, b, nUnused );
+ }
+ else
+ {
+ (gHUD.m_clrYellowish).GetColor( r, g, b, nUnused );
+ }
+
+ clrFlash.SetColor( r, g, b, a );
+
+ y = icon_flash_empty->Height() / 2;
+ x = GetWide() - ( icon_flash_empty->Width() * 1.5 );
+
+ // Draw the flashlight casing
+ icon_flash_empty->DrawSelf( x, y, clrFlash );
+
+ if ( bIsOn )
+ { // draw the flashlight beam
+ x = GetWide() - icon_flash_empty->Width() / 2;
+
+ icon_flash_beam->DrawSelf( x, y, clrFlash );
+ }
+
+ // draw the flashlight energy level
+ x = GetWide() - ( icon_flash_empty->Width() * 1.5 );
+
+ int nOffset = icon_flash_empty->Width() * ( 1.0 - ( (float)pPlayer->m_nFlashBattery / 100.0 ) );
+ if ( nOffset < icon_flash_empty->Width() )
+ {
+ icon_flash_full->DrawSelfCropped( x + nOffset, y, nOffset, 0, icon_flash_full->Width() - nOffset, icon_flash_full->Height(), clrFlash );
+ }
+}
+
+void CHudFlashlight::ApplySchemeSettings(vgui::IScheme *pScheme)
+{
+ BaseClass::ApplySchemeSettings(pScheme);
+ SetPaintBackgroundEnabled(false);
+
+ m_clrReddish = pScheme->GetColor( "Reddish", Color( 255, 16, 16, 255 ) );
+}
diff --git a/game/client/hl1/hl1_hud_geiger.cpp b/game/client/hl1/hl1_hud_geiger.cpp
new file mode 100644
index 0000000..9d6c816
--- /dev/null
+++ b/game/client/hl1/hl1_hud_geiger.cpp
@@ -0,0 +1,227 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+//
+// Geiger.cpp
+//
+// implementation of CHudAmmo class
+//
+#include "cbase.h"
+#include "hudelement.h"
+#include "hud_macros.h"
+#include "engine/IEngineSound.h"
+#include "SoundEmitterSystem/isoundemittersystembase.h"
+#include "iclientmode.h"
+#include <vgui_controls/Controls.h>
+#include <vgui_controls/Panel.h>
+#include <vgui/ISurface.h>
+
+using namespace vgui;
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+static const float TARGET_FRAMETIME = 1.0 / 60.0;
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+class CHudGeiger: public CHudElement, public vgui::Panel
+{
+ DECLARE_CLASS_SIMPLE( CHudGeiger, vgui::Panel );
+public:
+ CHudGeiger( const char *pElementName );
+ void Init( void );
+ void VidInit( void );
+ bool ShouldDraw( void );
+ virtual void ApplySchemeSettings( vgui::IScheme *scheme );
+ virtual void Paint( void );
+ void MsgFunc_Geiger(bf_read &msg);
+
+private:
+ int m_iGeigerRange;
+
+};
+
+DECLARE_HUDELEMENT( CHudGeiger );
+DECLARE_HUD_MESSAGE( CHudGeiger, Geiger );
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CHudGeiger::CHudGeiger( const char *pElementName ) :
+ CHudElement( pElementName ), BaseClass( NULL, "HudGeiger" )
+{
+ vgui::Panel *pParent = g_pClientMode->GetViewport();
+ SetParent( pParent );
+
+ SetHiddenBits( HIDEHUD_HEALTH );
+}
+
+void CHudGeiger::ApplySchemeSettings( IScheme *scheme )
+{
+ BaseClass::ApplySchemeSettings( scheme );
+
+ SetPaintBackgroundEnabled( false );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudGeiger::Init(void)
+{
+ HOOK_HUD_MESSAGE( CHudGeiger, Geiger );
+
+ m_iGeigerRange = 0;
+};
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudGeiger::VidInit(void)
+{
+ m_iGeigerRange = 0;
+};
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudGeiger::MsgFunc_Geiger(bf_read &msg)
+{
+ // update geiger data
+ m_iGeigerRange = msg.ReadByte();
+ m_iGeigerRange = m_iGeigerRange << 2;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CHudGeiger::ShouldDraw( void )
+{
+ return ( CHudElement::ShouldDraw() && ( m_iGeigerRange < 1000 && m_iGeigerRange > 0 ) );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudGeiger::Paint()
+{
+ int pct;
+ float flvol=0;
+ bool highsound = false;
+
+ // piecewise linear is better than continuous formula for this
+ if (m_iGeigerRange > 800)
+ {
+ pct = 0; //Msg ( "range > 800\n");
+ }
+ else if (m_iGeigerRange > 600)
+ {
+ pct = 2;
+ flvol = 0.4; //Msg ( "range > 600\n");
+ }
+ else if (m_iGeigerRange > 500)
+ {
+ pct = 4;
+ flvol = 0.5; //Msg ( "range > 500\n");
+ }
+ else if (m_iGeigerRange > 400)
+ {
+ pct = 8;
+ flvol = 0.6; //Msg ( "range > 400\n");
+ highsound = true;
+ }
+ else if (m_iGeigerRange > 300)
+ {
+ pct = 8;
+ flvol = 0.7; //Msg ( "range > 300\n");
+ highsound = true;
+ }
+ else if (m_iGeigerRange > 200)
+ {
+ pct = 28;
+ flvol = 0.78; //Msg ( "range > 200\n");
+ highsound = true;
+ }
+ else if (m_iGeigerRange > 150)
+ {
+ pct = 40;
+ flvol = 0.80; //Msg ( "range > 150\n");
+ highsound = true;
+ }
+ else if (m_iGeigerRange > 100)
+ {
+ pct = 60;
+ flvol = 0.85; //Msg ( "range > 100\n");
+ highsound = true;
+ }
+ else if (m_iGeigerRange > 75)
+ {
+ pct = 80;
+ flvol = 0.9; //Msg ( "range > 75\n");
+ //gflGeigerDelay = cl.time + GEIGERDELAY * 0.75;
+ highsound = true;
+ }
+ else if (m_iGeigerRange > 50)
+ {
+ pct = 90;
+ flvol = 0.95; //Msg ( "range > 50\n");
+ }
+ else
+ {
+ pct = 95;
+ flvol = 1.0; //Msg ( "range < 50\n");
+ }
+
+ int n = random->RandomInt( 0, 64 );
+
+ // Make geiger noise chance framerate independent
+ float flMultiplier = 1 / ( gpGlobals->frametime / TARGET_FRAMETIME );
+
+ // Constrain the multiplier
+ if ( flMultiplier > 10 )
+ {
+ flMultiplier = 10;
+ }
+ else if ( flMultiplier < 0.1 )
+ {
+ flMultiplier = 0.1;
+ }
+
+ n *= flMultiplier;
+
+ if ( n < pct )
+ {
+ char sz[256];
+ if ( highsound )
+ {
+ strcpy( sz, "Geiger.BeepHigh" );
+ }
+ else
+ {
+ strcpy( sz, "Geiger.BeepLow" );
+ }
+
+ CSoundParameters params;
+
+ if ( C_BaseEntity::GetParametersForSound( sz, params, NULL ) )
+ {
+ flvol = ( flvol * ( random->RandomInt( 0,127 ) ) / 255 ) + 0.25;
+
+ CLocalPlayerFilter filter;
+
+ EmitSound_t ep;
+ ep.m_nChannel = params.channel;
+ ep.m_pSoundName = params.soundname;
+ ep.m_flVolume = flvol;
+ ep.m_SoundLevel = params.soundlevel;
+ ep.m_nPitch = params.pitch;
+
+ C_BaseEntity::EmitSound( filter, SOUND_FROM_LOCAL_PLAYER, ep );
+ }
+ }
+}
diff --git a/game/client/hl1/hl1_hud_health.cpp b/game/client/hl1/hl1_hud_health.cpp
new file mode 100644
index 0000000..601081d
--- /dev/null
+++ b/game/client/hl1/hl1_hud_health.cpp
@@ -0,0 +1,225 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+//
+// Health.cpp
+//
+// implementation of CHudHealth class
+//
+#include "cbase.h"
+#include "hud.h"
+#include "hud_macros.h"
+#include "view.h"
+
+#include "iclientmode.h"
+
+#include "hl1_hud_numbers.h"
+
+#include <KeyValues.h>
+#include <vgui/ISurface.h>
+#include <vgui/ISystem.h>
+#include <vgui_controls/Panel.h>
+
+using namespace vgui;
+
+#include "hudelement.h"
+
+#include "convar.h"
+
+#define INIT_HEALTH -1
+
+#define FADE_TIME 100
+#define MIN_ALPHA 100
+
+//-----------------------------------------------------------------------------
+// Purpose: Health panel
+//-----------------------------------------------------------------------------
+class CHudHealth : public CHudElement, public CHL1HudNumbers
+{
+ DECLARE_CLASS_SIMPLE( CHudHealth, CHL1HudNumbers );
+
+public:
+ CHudHealth( const char *pElementName );
+
+ void Init( void );
+ void VidInit( void );
+ void Reset( void );
+ void OnThink();
+ void MsgFunc_Damage(bf_read &msg);
+
+private:
+ void Paint( void );
+ void ApplySchemeSettings(vgui::IScheme *pScheme);
+
+private:
+ CHudTexture *icon_cross;
+ int m_iHealth;
+ float m_flFade;
+ int m_bitsDamage;
+};
+
+DECLARE_HUDELEMENT( CHudHealth );
+DECLARE_HUD_MESSAGE( CHudHealth, Damage );
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CHudHealth::CHudHealth( const char *pElementName ) : CHudElement( pElementName ), BaseClass(NULL, "HudHealth")
+{
+ SetHiddenBits( HIDEHUD_HEALTH | HIDEHUD_PLAYERDEAD | HIDEHUD_NEEDSUIT );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudHealth::Init()
+{
+ HOOK_HUD_MESSAGE( CHudHealth, Damage );
+ Reset();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudHealth::Reset()
+{
+ m_iHealth = INIT_HEALTH;
+ m_flFade = 0;
+ m_bitsDamage = 0;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudHealth::VidInit()
+{
+ Reset();
+ BaseClass::VidInit();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudHealth::OnThink()
+{
+ int x = 0;
+ C_BasePlayer *local = C_BasePlayer::GetLocalPlayer();
+ if ( local )
+ {
+ // Never below zero
+ x = MAX( local->GetHealth(), 0 );
+ }
+
+ // Only update the fade if we've changed health
+ if ( x == m_iHealth )
+ {
+ return;
+ }
+
+ m_flFade = FADE_TIME;
+ m_iHealth = x;
+}
+
+void CHudHealth::Paint()
+{
+ Color clrHealth;
+ int a;
+ int x;
+ int y;
+
+ BaseClass::Paint();
+
+ if ( !icon_cross )
+ {
+ icon_cross = gHUD.GetIcon( "cross" );
+ }
+
+ if ( !icon_cross )
+ {
+ return;
+ }
+
+ // Has health changed? Flash the health #
+ if ( m_flFade )
+ {
+ m_flFade -= ( gpGlobals->frametime * 20 );
+ if ( m_flFade <= 0 )
+ {
+ a = MIN_ALPHA;
+ m_flFade = 0;
+ }
+ else
+ {
+ // Fade the health number back to dim
+ a = MIN_ALPHA + ( m_flFade / FADE_TIME ) * 128;
+ }
+ }
+ else
+ {
+ a = MIN_ALPHA;
+ }
+
+ // If health is getting low, make it bright red
+ if ( m_iHealth <= 15 )
+ a = 255;
+
+ if (m_iHealth > 25)
+ {
+ int r, g, b, nUnused;
+
+ (gHUD.m_clrYellowish).GetColor( r, g, b, nUnused );
+ clrHealth.SetColor( r, g, b, a );
+ }
+ else
+ {
+ clrHealth.SetColor( 250, 0, 0, a );
+ }
+
+ int nFontWidth = GetNumberFontWidth();
+ int nFontHeight = GetNumberFontHeight();
+ int nCrossWidth = icon_cross->Width();
+
+ x = nCrossWidth / 2;
+ y = GetTall() - ( nFontHeight * 1.5 );
+
+ icon_cross->DrawSelf( x, y, clrHealth );
+
+ x = nCrossWidth + ( nFontWidth / 2 );
+
+ x = DrawHudNumber( x, y, m_iHealth, clrHealth );
+
+ x += nFontWidth / 2;
+
+ int iHeight = nFontHeight;
+ int iWidth = nFontWidth / 10;
+
+ clrHealth.SetColor( 255, 160, 0, a );
+ vgui::surface()->DrawSetColor( clrHealth );
+ vgui::surface()->DrawFilledRect( x, y, x + iWidth, y + iHeight );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudHealth::MsgFunc_Damage(bf_read &msg)
+{
+ msg.ReadByte(); // armor
+ msg.ReadByte(); // health
+ msg.ReadLong(); // damage bits
+
+ Vector vecFrom;
+
+ vecFrom.x = msg.ReadBitCoord();
+ vecFrom.y = msg.ReadBitCoord();
+ vecFrom.z = msg.ReadBitCoord();
+}
+
+void CHudHealth::ApplySchemeSettings(vgui::IScheme *pScheme)
+{
+ BaseClass::ApplySchemeSettings(pScheme);
+ SetPaintBackgroundEnabled(false);
+}
diff --git a/game/client/hl1/hl1_hud_history_resource.cpp b/game/client/hl1/hl1_hud_history_resource.cpp
new file mode 100644
index 0000000..ec36282
--- /dev/null
+++ b/game/client/hl1/hl1_hud_history_resource.cpp
@@ -0,0 +1,307 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Item pickup history displayed onscreen when items are picked up.
+//
+// $NoKeywords: $
+//=============================================================================//
+#include "cbase.h"
+#include "history_resource.h"
+#include "hud_macros.h"
+#include <vgui_controls/Controls.h>
+#include <vgui/ISurface.h>
+#include "iclientmode.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+using namespace vgui;
+
+extern ConVar hud_drawhistory_time;
+
+#define HISTORY_PICKUP_GAP (m_iHistoryGap + 5)
+#define HISTORY_PICKUP_PICK_HEIGHT (32 + (m_iHistoryGap * 2))
+#define HISTORY_PICKUP_HEIGHT_MAX (GetTall() - 100)
+#define ITEM_GUTTER_SIZE 48
+
+
+DECLARE_HUDELEMENT( CHudHistoryResource );
+DECLARE_HUD_MESSAGE( CHudHistoryResource, ItemPickup );
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CHudHistoryResource::CHudHistoryResource( const char *pElementName ) :
+ CHudElement( pElementName ), BaseClass( NULL, "HudHistoryResource" )
+{
+ vgui::Panel *pParent = g_pClientMode->GetViewport();
+ SetParent( pParent );
+ SetHiddenBits( HIDEHUD_MISCSTATUS );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *pScheme -
+//-----------------------------------------------------------------------------
+void CHudHistoryResource::ApplySchemeSettings( IScheme *pScheme )
+{
+ BaseClass::ApplySchemeSettings( pScheme );
+ SetPaintBackgroundEnabled( false );
+
+ m_hNumberFont = pScheme->GetFont( "HudNumbersSmall" );
+}
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudHistoryResource::Init( void )
+{
+ HOOK_HUD_MESSAGE( CHudHistoryResource, ItemPickup );
+
+ m_iHistoryGap = 0;
+ Reset();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudHistoryResource::Reset( void )
+{
+ m_PickupHistory.RemoveAll();
+ m_iCurrentHistorySlot = 0;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Set a new minimum size gap between history icons
+//-----------------------------------------------------------------------------
+void CHudHistoryResource::SetHistoryGap( int iNewHistoryGap )
+{
+ if ( iNewHistoryGap > m_iHistoryGap )
+ {
+ m_iHistoryGap = iNewHistoryGap;
+ }
+}
+
+void CHudHistoryResource::AddToHistory( C_BaseCombatWeapon *weapon )
+{
+ // Check to see if the pic would have to be drawn too high. If so, start again from the bottom
+ if ( ((HISTORY_PICKUP_GAP * m_iCurrentHistorySlot) + HISTORY_PICKUP_PICK_HEIGHT) > HISTORY_PICKUP_HEIGHT_MAX )
+ {
+ m_iCurrentHistorySlot = 0;
+ }
+
+ // ensure the size
+ m_PickupHistory.EnsureCount(m_iCurrentHistorySlot + 1);
+
+ // default to just writing to the first slot
+ HIST_ITEM *freeslot = &m_PickupHistory[m_iCurrentHistorySlot++];
+ freeslot->type = HISTSLOT_WEAP;
+ freeslot->iId = weapon->entindex();
+ freeslot->m_hWeapon = weapon;
+ freeslot->iCount = 0;
+ freeslot->DisplayTime = gpGlobals->curtime + hud_drawhistory_time.GetFloat();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Add a new entry to the pickup history
+//-----------------------------------------------------------------------------
+void CHudHistoryResource::AddToHistory( int iType, int iId, int iCount )
+{
+ // Ignore adds with no count
+ if ( iType == HISTSLOT_AMMO && !iCount )
+ return;
+
+ // Check to see if the pic would have to be drawn too high. If so, start again from the bottom
+ if ( ((HISTORY_PICKUP_GAP * m_iCurrentHistorySlot) + HISTORY_PICKUP_PICK_HEIGHT) > HISTORY_PICKUP_HEIGHT_MAX )
+ {
+ m_iCurrentHistorySlot = 0;
+ }
+
+ // ensure the size
+ m_PickupHistory.EnsureCount(m_iCurrentHistorySlot + 1);
+
+ // default to just writing to the first slot
+ HIST_ITEM *freeslot = &m_PickupHistory[m_iCurrentHistorySlot++];
+ freeslot->type = iType;
+ freeslot->iId = iId;
+ freeslot->m_hWeapon = NULL;
+ freeslot->iCount = iCount;
+ freeslot->DisplayTime = gpGlobals->curtime + hud_drawhistory_time.GetFloat();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Add a new entry to the pickup history
+//-----------------------------------------------------------------------------
+void CHudHistoryResource::AddToHistory( int iType, const char *szName, int iCount )
+{
+ if ( iType != HISTSLOT_ITEM )
+ return;
+
+ // Check to see if the pic would have to be drawn too high. If so, start again from the bottom
+ if ( ((HISTORY_PICKUP_GAP * m_iCurrentHistorySlot) + HISTORY_PICKUP_PICK_HEIGHT) > HISTORY_PICKUP_HEIGHT_MAX )
+ {
+ m_iCurrentHistorySlot = 0;
+ }
+
+ // ensure the size
+ m_PickupHistory.EnsureCount(m_iCurrentHistorySlot + 1);
+
+ // default to just writing to the first slot
+ HIST_ITEM *freeslot = &m_PickupHistory[m_iCurrentHistorySlot++];
+
+ // Get the item's icon
+ CHudTexture *i = gHUD.GetIcon( szName );
+ if ( i == NULL )
+ return;
+
+ freeslot->iId = 1;
+ freeslot->icon = i;
+ freeslot->type = iType;
+ freeslot->m_hWeapon = NULL;
+ freeslot->iCount = iCount;
+ freeslot->DisplayTime = gpGlobals->curtime + hud_drawhistory_time.GetFloat();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Handle an item pickup event from the server
+//-----------------------------------------------------------------------------
+void CHudHistoryResource::MsgFunc_ItemPickup(bf_read &msg)
+{
+ char szString[2048];
+
+ msg.ReadString( szString, sizeof(szString) );
+
+ // Add the item to the history
+ AddToHistory( HISTSLOT_ITEM, szString );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: If there aren't any items in the history, clear it out.
+//-----------------------------------------------------------------------------
+void CHudHistoryResource::CheckClearHistory( void )
+{
+ for ( int i = 0; i < m_PickupHistory.Count(); i++ )
+ {
+ if ( m_PickupHistory[i].type )
+ return;
+ }
+
+ m_iCurrentHistorySlot = 0;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CHudHistoryResource::ShouldDraw( void )
+{
+ return ( CHudElement::ShouldDraw() && m_iCurrentHistorySlot );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Draw the pickup history
+//-----------------------------------------------------------------------------
+void CHudHistoryResource::Paint( void )
+{
+ for ( int i = 0; i < m_PickupHistory.Count(); i++ )
+ {
+ if ( m_PickupHistory[i].type )
+ {
+ m_PickupHistory[i].DisplayTime = MIN( m_PickupHistory[i].DisplayTime, gpGlobals->curtime + hud_drawhistory_time.GetFloat() );
+ if ( m_PickupHistory[i].DisplayTime <= gpGlobals->curtime )
+ { // pic drawing time has expired
+ memset( &m_PickupHistory[i], 0, sizeof(HIST_ITEM) );
+ CheckClearHistory();
+ continue;
+ }
+
+ float elapsed = m_PickupHistory[i].DisplayTime - gpGlobals->curtime;
+ float scale = elapsed * 80;
+
+ int r, g, b, nUnused;
+ (gHUD.m_clrYellowish).GetColor( r, g, b, nUnused );
+
+ Color clrAmmo( r, g, b, MIN( scale, 255 ) );
+
+ int nHudElemWidth, nHudElemHeight;
+ GetSize( nHudElemWidth, nHudElemHeight );
+
+ switch ( m_PickupHistory[i].type )
+ {
+ case HISTSLOT_AMMO:
+ {
+ CHudTexture *icon = gWR.GetAmmoIconFromWeapon( m_PickupHistory[i].iId );
+ if ( icon )
+ {
+ // Draw the pic
+ int ypos = nHudElemHeight - ( HISTORY_PICKUP_PICK_HEIGHT + ( HISTORY_PICKUP_GAP * i ) );
+ int xpos = nHudElemWidth - 24;
+
+ // the dll has to make sure it has sent info the weapons you need
+ icon->DrawSelf( xpos, ypos, clrAmmo );
+
+ //Offset the number to sit properly next to the icon
+ ypos -= ( surface()->GetFontTall( m_hNumberFont ) - icon->Height() ) / 2;
+
+ vgui::surface()->DrawSetTextFont( m_hNumberFont );
+ vgui::surface()->DrawSetTextColor( clrAmmo );
+ vgui::surface()->DrawSetTextPos( GetWide() - ( ITEM_GUTTER_SIZE * 0.85f ), ypos );
+
+ if ( m_PickupHistory[i].iCount )
+ {
+ char sz[ 32 ];
+ int len = Q_snprintf( sz, sizeof( sz ), "%i", m_PickupHistory[i].iCount );
+
+ for ( int ch = 0; ch < len; ch++ )
+ {
+ char c = sz[ ch ];
+ vgui::surface()->DrawUnicodeChar( c );
+ }
+ }
+ }
+ }
+ break;
+ case HISTSLOT_WEAP:
+ {
+ C_BaseCombatWeapon *pWeapon = m_PickupHistory[i].m_hWeapon;
+ if ( !pWeapon )
+ return;
+
+ if ( !pWeapon->HasAmmo() )
+ {
+ // if the weapon doesn't have ammo, display it as red
+ Color clrReddish( 255, 16, 16, 255 );
+ clrReddish.GetColor( r, g, b, nUnused );
+ clrAmmo.SetColor( r, g, b, MIN( scale, 255 ) );
+ }
+
+ int ypos = nHudElemHeight - (HISTORY_PICKUP_PICK_HEIGHT + (HISTORY_PICKUP_GAP * i));
+ int xpos = nHudElemWidth - pWeapon->GetSpriteInactive()->Width();
+
+ pWeapon->GetSpriteInactive()->DrawSelf( xpos, ypos, clrAmmo );
+ }
+ break;
+ case HISTSLOT_ITEM:
+ {
+ if ( !m_PickupHistory[i].iId )
+ continue;
+
+ CHudTexture *icon = m_PickupHistory[i].icon;
+ if ( !icon )
+ continue;
+
+ int ypos = ScreenHeight() - ( HISTORY_PICKUP_PICK_HEIGHT + ( HISTORY_PICKUP_GAP * i ) );
+ int xpos = ScreenWidth() - icon->Width() - 10;
+
+ icon->DrawSelf( xpos, ypos, clrAmmo );
+ }
+ break;
+ default:
+ {
+ // Unknown history type???!!!
+ Assert( 0 );
+ }
+ break;
+ }
+ }
+ }
+}
+
+
diff --git a/game/client/hl1/hl1_hud_numbers.cpp b/game/client/hl1/hl1_hud_numbers.cpp
new file mode 100644
index 0000000..1abcabc
--- /dev/null
+++ b/game/client/hl1/hl1_hud_numbers.cpp
@@ -0,0 +1,113 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "hud.h"
+#include "hudelement.h"
+#include "hud_macros.h"
+#include "iclientmode.h"
+#include "hl1_hud_numbers.h"
+
+
+// This is a bad way to implement HL1 style sprite fonts, but it will work for now
+
+CHL1HudNumbers::CHL1HudNumbers( vgui::Panel *parent, const char *name ) : BaseClass( parent, name )
+{
+ vgui::Panel *pParent = g_pClientMode->GetViewport();
+ SetParent( pParent );
+}
+
+
+void CHL1HudNumbers::VidInit( void )
+{
+ for ( int i = 0; i < 10; i++ )
+ {
+ char szNumString[ 10 ];
+
+ sprintf( szNumString, "number_%d", i );
+ icon_digits[ i ] = gHUD.GetIcon( szNumString );
+ }
+}
+
+
+int CHL1HudNumbers::GetNumberFontHeight( void )
+{
+ if ( icon_digits[ 0 ] )
+ {
+ return icon_digits[ 0 ]->Height();
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+int CHL1HudNumbers::GetNumberFontWidth( void )
+{
+ if ( icon_digits[ 0 ] )
+ {
+ return icon_digits[ 0 ]->Width();
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+int CHL1HudNumbers::DrawHudNumber( int x, int y, int iNumber, Color &clrDraw )
+{
+ int iWidth = GetNumberFontWidth();
+ int k;
+
+ if ( iNumber > 0 )
+ {
+ // SPR_Draw 100's
+ if ( iNumber >= 100 )
+ {
+ k = iNumber / 100;
+ icon_digits[ k ]->DrawSelf( x, y, clrDraw );
+ x += iWidth;
+ }
+ else
+ {
+ x += iWidth;
+ }
+
+ // SPR_Draw 10's
+ if ( iNumber >= 10 )
+ {
+ k = ( iNumber % 100 ) / 10;
+ icon_digits[ k ]->DrawSelf( x, y, clrDraw );
+ x += iWidth;
+ }
+ else
+ {
+ x += iWidth;
+ }
+
+ // SPR_Draw ones
+ k = iNumber % 10;
+ icon_digits[ k ]->DrawSelf( x, y, clrDraw );
+ x += iWidth;
+ }
+ else
+ {
+ // SPR_Draw 100's
+ x += iWidth;
+
+ // SPR_Draw 10's
+ x += iWidth;
+
+ // SPR_Draw ones
+ k = 0;
+ icon_digits[ k ]->DrawSelf( x, y, clrDraw );
+ x += iWidth;
+ }
+
+ return x;
+}
diff --git a/game/client/hl1/hl1_hud_numbers.h b/game/client/hl1/hl1_hud_numbers.h
new file mode 100644
index 0000000..e5deec1
--- /dev/null
+++ b/game/client/hl1/hl1_hud_numbers.h
@@ -0,0 +1,35 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#ifndef HL1_HUD_NUMBERS_H
+#define HL1_HUD_NUMBERS_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#include <vgui_controls/Panel.h>
+
+
+class CHL1HudNumbers : public vgui::Panel
+{
+ DECLARE_CLASS_SIMPLE( CHL1HudNumbers, vgui::Panel );
+
+public:
+ CHL1HudNumbers( vgui::Panel *parent, const char *name );
+ void VidInit( void );
+
+protected:
+ int DrawHudNumber( int x, int y, int iNumber, Color &clrDraw );
+ int GetNumberFontHeight( void );
+ int GetNumberFontWidth( void );
+
+private:
+ CHudTexture *icon_digits[ 10 ];
+};
+
+
+#endif // HL1_HUD_NUMBERS_H
diff --git a/game/client/hl1/hl1_hud_train.cpp b/game/client/hl1/hl1_hud_train.cpp
new file mode 100644
index 0000000..443f6a5
--- /dev/null
+++ b/game/client/hl1/hl1_hud_train.cpp
@@ -0,0 +1,143 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "hudelement.h"
+#include "hud_macros.h"
+#include "iclientmode.h"
+#include "materialsystem/imaterialsystem.h"
+#include "materialsystem/imaterial.h"
+#include "materialsystem/imaterialvar.h"
+#include "hl1_hud_numbers.h"
+
+#include <vgui_controls/Controls.h>
+#include <vgui_controls/Panel.h>
+#include <vgui/ISurface.h>
+
+using namespace vgui;
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+class CHudTrain: public CHudElement, public CHL1HudNumbers
+{
+ DECLARE_CLASS_SIMPLE( CHudTrain, CHL1HudNumbers );
+public:
+ CHudTrain( const char *pElementName );
+ void Init( void );
+ void VidInit( void );
+ bool ShouldDraw( void );
+ void MsgFunc_Train(bf_read &msg);
+
+private:
+ void Paint( void );
+ void ApplySchemeSettings( vgui::IScheme *scheme );
+
+private:
+ int m_iPos;
+ CHudTexture *icon_train;
+};
+
+//
+//-----------------------------------------------------
+//
+
+DECLARE_HUDELEMENT( CHudTrain );
+DECLARE_HUD_MESSAGE( CHudTrain, Train )
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CHudTrain::CHudTrain( const char *pElementName ) : CHudElement( pElementName ), BaseClass(NULL, "HudTrain")
+{
+ SetHiddenBits( HIDEHUD_MISCSTATUS );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *scheme -
+//-----------------------------------------------------------------------------
+void CHudTrain::ApplySchemeSettings( IScheme *scheme )
+{
+ BaseClass::ApplySchemeSettings( scheme );
+
+ SetPaintBackgroundEnabled( false );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudTrain::Init(void)
+{
+ HOOK_HUD_MESSAGE( CHudTrain, Train );
+
+ m_iPos = 0;
+}
+
+void CHudTrain::VidInit(void)
+{
+ BaseClass::VidInit();
+
+ m_iPos = 0;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CHudTrain::ShouldDraw( void )
+{
+ return ( CHudElement::ShouldDraw() && m_iPos );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudTrain::Paint()
+{
+ if ( !icon_train )
+ {
+ icon_train = gHUD.GetIcon( "train" );
+ }
+
+ if ( !icon_train )
+ {
+ return;
+ }
+
+ int r, g, b, a;
+ int x, y;
+ Color clrTrain;
+
+ (gHUD.m_clrYellowish).GetColor( r, g, b, a );
+ clrTrain.SetColor( r, g, b, a );
+
+ int nHudElemWidth, nHudElemHeight;
+ GetSize( nHudElemWidth, nHudElemHeight );
+
+ // This should show up to the right and part way up the armor number
+ y = nHudElemHeight - icon_train->Height() - GetNumberFontHeight();
+ x = nHudElemWidth / 3 + icon_train->Width() / 4;
+
+ IMaterial *material = materials->FindMaterial( icon_train->szTextureFile, TEXTURE_GROUP_VGUI );
+ if ( material )
+ {
+ bool found;
+ IMaterialVar* pFrameVar = material->FindVar( "$frame", &found, false );
+ if ( found )
+ {
+ pFrameVar->SetFloatValue( m_iPos - 1 );
+ }
+ }
+
+ icon_train->DrawSelf( x, y, clrTrain );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudTrain::MsgFunc_Train( bf_read &msg )
+{
+ m_iPos = msg.ReadByte();
+}
diff --git a/game/client/hl1/hl1_hud_weaponselection.cpp b/game/client/hl1/hl1_hud_weaponselection.cpp
new file mode 100644
index 0000000..1916066
--- /dev/null
+++ b/game/client/hl1/hl1_hud_weaponselection.cpp
@@ -0,0 +1,670 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "weapon_selection.h"
+#include "iclientmode.h"
+#include "ammodef.h"
+#include "input.h"
+
+#include <KeyValues.h>
+#include <vgui/IScheme.h>
+#include <vgui/ISurface.h>
+#include <vgui/ISystem.h>
+#include <vgui_controls/Panel.h>
+
+#include <string.h>
+
+
+#define HL1_MAX_WEAPON_SLOTS 5
+
+
+//-----------------------------------------------------------------------------
+// Purpose: hl2 weapon selection hud element
+//-----------------------------------------------------------------------------
+class CHudWeaponSelection : public CBaseHudWeaponSelection, public vgui::Panel
+{
+ DECLARE_CLASS_SIMPLE( CHudWeaponSelection, vgui::Panel );
+
+public:
+ CHudWeaponSelection(const char *pElementName );
+
+ bool ShouldDraw();
+
+ void CycleToNextWeapon( void );
+ void CycleToPrevWeapon( void );
+
+ C_BaseCombatWeapon *GetWeaponInSlot( int iSlot, int iSlotPos );
+ void SelectWeaponSlot( int iSlot );
+
+ C_BaseCombatWeapon *GetSelectedWeapon( void )
+ {
+ return m_hSelectedWeapon;
+ }
+
+ void VidInit( void );
+ C_BaseCombatWeapon *GetNextActivePos( int iSlot, int iSlotPos );
+
+protected:
+ void Paint();
+ void ApplySchemeSettings(vgui::IScheme *pScheme);
+
+private:
+ C_BaseCombatWeapon *FindNextWeaponInWeaponSelection(int iCurrentSlot, int iCurrentPosition);
+ C_BaseCombatWeapon *FindPrevWeaponInWeaponSelection(int iCurrentSlot, int iCurrentPosition);
+
+ void FastWeaponSwitch( int iWeaponSlot );
+
+ void DrawAmmoBar( C_BaseCombatWeapon *pWeapon, int x, int y, int nWidth, int nHeight );
+ int DrawBar( int x, int y, int width, int height, float f );
+
+ void SetSelectedWeapon( C_BaseCombatWeapon *pWeapon )
+ {
+ m_hSelectedWeapon = pWeapon;
+ }
+
+ CHudTexture *icon_buckets[ HL1_MAX_WEAPON_SLOTS ];
+ CHudTexture *icon_selection;
+ Color m_clrReddish;
+ Color m_clrGreenish;
+};
+
+DECLARE_HUDELEMENT( CHudWeaponSelection );
+
+using namespace vgui;
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CHudWeaponSelection::CHudWeaponSelection( const char *pElementName ) : CBaseHudWeaponSelection(pElementName), BaseClass(NULL, "HudWeaponSelection")
+{
+ vgui::Panel *pParent = g_pClientMode->GetViewport();
+ SetParent( pParent );
+}
+
+void CHudWeaponSelection::VidInit()
+{
+ Reset();
+
+ for ( int i = 0; i < HL1_MAX_WEAPON_SLOTS; i++ )
+ {
+ char szNumString[ 10 ];
+
+ sprintf( szNumString, "bucket%d", i );
+ icon_buckets[ i ] = gHUD.GetIcon( szNumString );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns true if the panel should draw
+//-----------------------------------------------------------------------------
+bool CHudWeaponSelection::ShouldDraw()
+{
+ C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
+ if ( !pPlayer )
+ {
+ if ( IsInSelectionMode() )
+ {
+ HideSelection();
+ }
+ return false;
+ }
+
+ bool bret = CBaseHudWeaponSelection::ShouldDraw();
+ if ( !bret )
+ return false;
+
+ return ( m_bSelectionVisible ) ? true : false;
+}
+
+//-------------------------------------------------------------------------
+// Purpose: draws the selection area
+//-------------------------------------------------------------------------
+void CHudWeaponSelection::Paint()
+{
+ if (!ShouldDraw())
+ return;
+
+ C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
+ if ( !pPlayer )
+ return;
+
+ // find and display our current selection
+ C_BaseCombatWeapon *pSelectedWeapon = GetSelectedWeapon();
+ if ( !pSelectedWeapon )
+ return;
+
+ int iActiveSlot = (pSelectedWeapon ? pSelectedWeapon->GetSlot() : -1);
+
+ int xpos = 10;
+
+ // iterate over all the weapon slots
+ for ( int i = 0; i < HL1_MAX_WEAPON_SLOTS; i++ )
+ {
+ int nWidth;
+ int r1, g1, b1, a1;
+
+ (gHUD.m_clrYellowish).GetColor( r1, g1, b1, a1 );
+
+ int ypos = 10;
+
+ icon_buckets[ i ]->DrawSelf( xpos, ypos, Color( r1, g1, b1, 255 ) );
+
+ ypos = icon_buckets[ i ]->Height() + 10;
+
+ if ( i == iActiveSlot )
+ {
+ bool bFirstItem = true;
+ nWidth = icon_buckets[ i ]->Width();
+
+ for ( int slotpos = 0; slotpos < MAX_WEAPON_POSITIONS; slotpos++ )
+ {
+ C_BaseCombatWeapon *pWeapon = GetWeaponInSlot( i, slotpos );
+ if ( !pWeapon )
+ continue;
+
+ // icons use old system, drawing in screen space
+ if ( pWeapon->GetSpriteActive() )
+ {
+ int r, g, b, a;
+
+ (gHUD.m_clrYellowish).GetColor( r, g, b, a );
+
+ if (pWeapon == pSelectedWeapon)
+ {
+ pWeapon->GetSpriteActive()->DrawSelf( xpos, ypos, Color( r, g, b, a ) );
+
+ if ( !icon_selection )
+ {
+ icon_selection = gHUD.GetIcon( "selection" );
+ }
+
+ if ( icon_selection )
+ {
+ icon_selection->DrawSelf( xpos, ypos, Color( r, g, b, a ) );
+ }
+ }
+ else
+ {
+ if ( pWeapon->HasAmmo() )
+ {
+ a = 192;
+ }
+ else
+ {
+ m_clrReddish.GetColor( r, g, b, a );
+ a = 128;
+ }
+
+ if ( pWeapon->GetSpriteInactive() )
+ {
+ pWeapon->GetSpriteInactive()->DrawSelf( xpos, ypos, Color( r, g, b, a ) );
+ }
+ }
+ }
+
+ // Draw Ammo Bar
+ DrawAmmoBar( pWeapon, xpos + 10, ypos, 20, 4 );
+
+ ypos += pWeapon->GetSpriteActive()->Height() + 5;
+
+ if ( bFirstItem )
+ {
+ nWidth = pWeapon->GetSpriteActive()->Width();
+ bFirstItem = false;
+ }
+ }
+ }
+ else
+ {
+ // Draw Row of weapons.
+ for ( int iPos = 0; iPos < MAX_WEAPON_POSITIONS; iPos++ )
+ {
+ int r2, g2, b2, a2;
+ C_BaseCombatWeapon *pWeapon = GetWeaponInSlot( i, iPos );
+
+ if ( !pWeapon )
+ continue;
+
+ if ( pWeapon->HasAmmo() )
+ {
+ (gHUD.m_clrYellowish).GetColor( r2, g2, b2, a2 );
+ a2 = 128;
+ }
+ else
+ {
+ m_clrReddish.GetColor( r2, g2, b2, a2 );
+ a2 = 96;
+ }
+
+ Color clrBox( r2, g2, b2, a2 );
+ vgui::surface()->DrawSetColor( clrBox );
+ vgui::surface()->DrawFilledRect( xpos, ypos, xpos + icon_buckets[ i ]->Width(), ypos + icon_buckets[ i ]->Height() );
+
+ ypos += icon_buckets[ i ]->Height() + 5;
+ }
+
+ nWidth = icon_buckets[ i ]->Width();
+ }
+
+ // advance position
+ xpos += nWidth + 5;
+ }
+}
+
+void CHudWeaponSelection::DrawAmmoBar( C_BaseCombatWeapon *pWeapon, int x, int y, int nWidth, int nHeight )
+{
+ if ( pWeapon->GetPrimaryAmmoType() != -1 )
+ {
+ C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
+
+ int nAmmoCount = pPlayer->GetAmmoCount( pWeapon->GetPrimaryAmmoType() );
+ if ( !nAmmoCount )
+ return;
+
+ float flPct = (float)nAmmoCount / (float)GetAmmoDef()->MaxCarry( pWeapon->GetPrimaryAmmoType() );
+
+ x = DrawBar( x, y, nWidth, nHeight, flPct );
+
+ // Do we have secondary ammo too?
+ if ( pWeapon->GetSecondaryAmmoType() != -1 )
+ {
+ flPct = (float)pPlayer->GetAmmoCount( pWeapon->GetSecondaryAmmoType() ) / (float)GetAmmoDef()->MaxCarry( pWeapon->GetSecondaryAmmoType() );
+
+ x += 5; //!!!
+
+ DrawBar( x, y, nWidth, nHeight, flPct );
+ }
+ }
+}
+
+int CHudWeaponSelection::DrawBar( int x, int y, int nWidth, int nHeight, float flPct )
+{
+ Color clrBar;
+ int r, g, b, a;
+
+ if ( flPct < 0 )
+ {
+ flPct = 0;
+ }
+ else if ( flPct > 1 )
+ {
+ flPct = 1;
+ }
+
+ if ( flPct )
+ {
+ int nBarWidth = flPct * nWidth;
+
+ // Always show at least one pixel if we have ammo.
+ if (nBarWidth <= 0)
+ nBarWidth = 1;
+
+ m_clrGreenish.GetColor( r, g, b, a );
+
+ clrBar.SetColor( r, g, b, 255 );
+ vgui::surface()->DrawSetColor( clrBar );
+ vgui::surface()->DrawFilledRect( x, y, x + nBarWidth, y + nHeight );
+
+ x += nBarWidth;
+ nWidth -= nBarWidth;
+ }
+
+ (gHUD.m_clrYellowish).GetColor( r, g, b, a );
+
+ clrBar.SetColor( r, g, b, 128 );
+ vgui::surface()->DrawSetColor( clrBar );
+ vgui::surface()->DrawFilledRect( x, y, x + nWidth, y + nHeight );
+
+ return ( x + nWidth );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: hud scheme settings
+//-----------------------------------------------------------------------------
+void CHudWeaponSelection::ApplySchemeSettings(vgui::IScheme *pScheme)
+{
+ BaseClass::ApplySchemeSettings(pScheme);
+ SetPaintBackgroundEnabled(false);
+
+ // set our size
+ int screenWide, screenTall;
+ int x, y;
+ GetPos(x, y);
+ GetHudSize(screenWide, screenTall);
+ SetBounds(0, y, screenWide, screenTall - y);
+
+ m_clrReddish = pScheme->GetColor( "Reddish", Color( 255, 16, 16, 255 ) );
+ m_clrGreenish = pScheme->GetColor( "Greenish", Color( 255, 16, 16, 255 ) );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the next available weapon item in the weapon selection
+//-----------------------------------------------------------------------------
+C_BaseCombatWeapon *CHudWeaponSelection::FindNextWeaponInWeaponSelection(int iCurrentSlot, int iCurrentPosition)
+{
+ C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
+ if ( !pPlayer )
+ return NULL;
+
+ C_BaseCombatWeapon *pNextWeapon = NULL;
+
+ // search all the weapons looking for the closest next
+ int iLowestNextSlot = HL1_MAX_WEAPON_SLOTS;
+ int iLowestNextPosition = MAX_WEAPON_POSITIONS;
+ for ( int i = 0; i < MAX_WEAPONS; i++ )
+ {
+ C_BaseCombatWeapon *pWeapon = pPlayer->GetWeapon(i);
+ if ( !pWeapon )
+ continue;
+
+ if ( pWeapon->CanBeSelected() )
+ {
+ int weaponSlot = pWeapon->GetSlot(), weaponPosition = pWeapon->GetPosition();
+
+ // see if this weapon is further ahead in the selection list
+ if ( weaponSlot > iCurrentSlot || (weaponSlot == iCurrentSlot && weaponPosition > iCurrentPosition) )
+ {
+ // see if this weapon is closer than the current lowest
+ if ( weaponSlot < iLowestNextSlot || (weaponSlot == iLowestNextSlot && weaponPosition < iLowestNextPosition) )
+ {
+ iLowestNextSlot = weaponSlot;
+ iLowestNextPosition = weaponPosition;
+ pNextWeapon = pWeapon;
+ }
+ }
+ }
+ }
+
+ return pNextWeapon;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the prior available weapon item in the weapon selection
+//-----------------------------------------------------------------------------
+C_BaseCombatWeapon *CHudWeaponSelection::FindPrevWeaponInWeaponSelection(int iCurrentSlot, int iCurrentPosition)
+{
+ C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
+ if ( !pPlayer )
+ return NULL;
+
+ C_BaseCombatWeapon *pPrevWeapon = NULL;
+
+ // search all the weapons looking for the closest next
+ int iLowestPrevSlot = -1;
+ int iLowestPrevPosition = -1;
+ for ( int i = 0; i < MAX_WEAPONS; i++ )
+ {
+ C_BaseCombatWeapon *pWeapon = pPlayer->GetWeapon(i);
+ if ( !pWeapon )
+ continue;
+
+ if ( pWeapon->CanBeSelected() )
+ {
+ int weaponSlot = pWeapon->GetSlot(), weaponPosition = pWeapon->GetPosition();
+
+ // see if this weapon is further ahead in the selection list
+ if ( weaponSlot < iCurrentSlot || (weaponSlot == iCurrentSlot && weaponPosition < iCurrentPosition) )
+ {
+ // see if this weapon is closer than the current lowest
+ if ( weaponSlot > iLowestPrevSlot || (weaponSlot == iLowestPrevSlot && weaponPosition > iLowestPrevPosition) )
+ {
+ iLowestPrevSlot = weaponSlot;
+ iLowestPrevPosition = weaponPosition;
+ pPrevWeapon = pWeapon;
+ }
+ }
+ }
+ }
+
+ return pPrevWeapon;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Moves the selection to the next item in the menu
+//-----------------------------------------------------------------------------
+void CHudWeaponSelection::CycleToNextWeapon( void )
+{
+ // Get the local player.
+ C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
+ if ( !pPlayer )
+ return;
+
+ C_BaseCombatWeapon *pNextWeapon = NULL;
+ if ( IsInSelectionMode() )
+ {
+ // find the next selection spot
+ C_BaseCombatWeapon *pWeapon = GetSelectedWeapon();
+ if ( !pWeapon )
+ return;
+
+ pNextWeapon = FindNextWeaponInWeaponSelection( pWeapon->GetSlot(), pWeapon->GetPosition() );
+ }
+ else
+ {
+ // open selection at the current place
+ pNextWeapon = pPlayer->GetActiveWeapon();
+ if ( pNextWeapon )
+ {
+ pNextWeapon = FindNextWeaponInWeaponSelection( pNextWeapon->GetSlot(), pNextWeapon->GetPosition() );
+ }
+ }
+
+ if ( !pNextWeapon )
+ {
+ // wrap around back to start
+ pNextWeapon = FindNextWeaponInWeaponSelection(-1, -1);
+ }
+
+ if ( pNextWeapon )
+ {
+ SetSelectedWeapon( pNextWeapon );
+
+ if( hud_fastswitch.GetInt() > 0 )
+ {
+ SelectWeapon();
+ }
+ else if ( !IsInSelectionMode() )
+ {
+ OpenSelection();
+ }
+
+ // Play the "cycle to next weapon" sound
+ pPlayer->EmitSound( "Player.WeaponSelectionMoveSlot" );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Moves the selection to the previous item in the menu
+//-----------------------------------------------------------------------------
+void CHudWeaponSelection::CycleToPrevWeapon( void )
+{
+ // Get the local player.
+ C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
+ if ( !pPlayer )
+ return;
+
+ C_BaseCombatWeapon *pNextWeapon = NULL;
+ if ( IsInSelectionMode() )
+ {
+ // find the next selection spot
+ C_BaseCombatWeapon *pWeapon = GetSelectedWeapon();
+ if ( !pWeapon )
+ return;
+
+ pNextWeapon = FindPrevWeaponInWeaponSelection( pWeapon->GetSlot(), pWeapon->GetPosition() );
+ }
+ else
+ {
+ // open selection at the current place
+ pNextWeapon = pPlayer->GetActiveWeapon();
+ if ( pNextWeapon )
+ {
+ pNextWeapon = FindPrevWeaponInWeaponSelection( pNextWeapon->GetSlot(), pNextWeapon->GetPosition() );
+ }
+ }
+
+ if ( !pNextWeapon )
+ {
+ // wrap around back to end of weapon list
+ pNextWeapon = FindPrevWeaponInWeaponSelection( HL1_MAX_WEAPON_SLOTS, MAX_WEAPON_POSITIONS );
+ }
+
+ if ( pNextWeapon )
+ {
+ SetSelectedWeapon( pNextWeapon );
+
+ if( hud_fastswitch.GetInt() > 0 )
+ {
+ SelectWeapon();
+ }
+ else if ( !IsInSelectionMode() )
+ {
+ OpenSelection();
+ }
+
+ // Play the "cycle to next weapon" sound
+ pPlayer->EmitSound( "Player.WeaponSelectionMoveSlot" );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the weapon in the specified slot
+//-----------------------------------------------------------------------------
+C_BaseCombatWeapon *CHudWeaponSelection::GetWeaponInSlot( int iSlot, int iSlotPos )
+{
+ C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
+ if ( !player )
+ return NULL;
+
+ for ( int i = 0; i < MAX_WEAPONS; i++ )
+ {
+ C_BaseCombatWeapon *pWeapon = player->GetWeapon(i);
+
+ if ( pWeapon == NULL )
+ continue;
+
+ if ( pWeapon->GetSlot() == iSlot && pWeapon->GetPosition() == iSlotPos )
+ return pWeapon;
+ }
+
+ return NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Moves selection to the specified slot
+//-----------------------------------------------------------------------------
+void CHudWeaponSelection::SelectWeaponSlot( int iSlot )
+{
+ // iSlot is one higher than it should be, since it's the number key, not the 0-based index into the weapons
+ --iSlot;
+
+ // Get the local player.
+ C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
+ if ( !pPlayer )
+ return;
+
+ // Don't try and read past our possible number of slots
+ if ( iSlot > HL1_MAX_WEAPON_SLOTS )
+ return;
+
+ // Make sure the player's allowed to switch weapons
+ if ( pPlayer->IsAllowedToSwitchWeapons() == false )
+ return;
+
+ // do a fast switch if set
+ if ( hud_fastswitch.GetBool() )
+ {
+ FastWeaponSwitch( iSlot );
+ return;
+ }
+
+ int slotPos = 0;
+ C_BaseCombatWeapon *pActiveWeapon = GetSelectedWeapon();
+
+ // start later in the list
+ if ( IsInSelectionMode() && pActiveWeapon && pActiveWeapon->GetSlot() == iSlot )
+ {
+ slotPos = pActiveWeapon->GetPosition() + 1;
+ }
+
+ // find the weapon in this slot
+ pActiveWeapon = GetNextActivePos( iSlot, slotPos );
+ if ( !pActiveWeapon )
+ {
+ pActiveWeapon = GetNextActivePos( iSlot, 0 );
+ }
+
+ if ( pActiveWeapon != NULL )
+ {
+ SetSelectedWeapon( pActiveWeapon );
+
+ if( hud_fastswitch.GetInt() > 0 )
+ {
+ // only one active item in bucket, so change directly to weapon
+ SelectWeapon();
+ }
+ else if ( !IsInSelectionMode() )
+ {
+ // open the weapon selection
+ OpenSelection();
+ }
+ }
+
+ pPlayer->EmitSound( "Player.WeaponSelectionMoveSlot" );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Opens the next weapon in the slot
+//-----------------------------------------------------------------------------
+void CHudWeaponSelection::FastWeaponSwitch( int iWeaponSlot )
+{
+ // get the slot the player's weapon is in
+ C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
+ if ( !pPlayer )
+ return;
+
+ // see where we should start selection
+ int iPosition = -1;
+ C_BaseCombatWeapon *pActiveWeapon = pPlayer->GetActiveWeapon();
+ if ( pActiveWeapon && pActiveWeapon->GetSlot() == iWeaponSlot )
+ {
+ // start after this weapon
+ iPosition = pActiveWeapon->GetPosition();
+ }
+
+ C_BaseCombatWeapon *pNextWeapon = NULL;
+
+ // search for the weapon after the current one
+ pNextWeapon = FindNextWeaponInWeaponSelection(iWeaponSlot, iPosition);
+ // make sure it's in the same bucket
+ if ( !pNextWeapon || pNextWeapon->GetSlot() != iWeaponSlot )
+ {
+ // just look for any weapon in this slot
+ pNextWeapon = FindNextWeaponInWeaponSelection(iWeaponSlot, -1);
+ }
+
+ // see if we found a weapon that's different from the current and in the selected slot
+ if ( pNextWeapon && pNextWeapon != pActiveWeapon && pNextWeapon->GetSlot() == iWeaponSlot )
+ {
+ // select the new weapon
+ ::input->MakeWeaponSelection( pNextWeapon );
+ }
+ else if ( pNextWeapon != pActiveWeapon )
+ {
+ // error sound
+ pPlayer->EmitSound( "Player.DenyWeaponSelection" );
+ }
+}
+
+C_BaseCombatWeapon *CHudWeaponSelection::GetNextActivePos( int iSlot, int iSlotPos )
+{
+ if ( iSlot >= HL1_MAX_WEAPON_SLOTS )
+ return NULL;
+
+ return CBaseHudWeaponSelection::GetNextActivePos( iSlot, iSlotPos );
+}