aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/client/hl2mp
diff options
context:
space:
mode:
authorJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
committerJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
commit39ed87570bdb2f86969d4be821c94b722dc71179 (patch)
treeabc53757f75f40c80278e87650ea92808274aa59 /mp/src/game/client/hl2mp
downloadsource-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz
source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/game/client/hl2mp')
-rw-r--r--mp/src/game/client/hl2mp/c_hl2mp_player.cpp985
-rw-r--r--mp/src/game/client/hl2mp/c_hl2mp_player.h173
-rw-r--r--mp/src/game/client/hl2mp/c_te_hl2mp_shotgun_shot.cpp160
-rw-r--r--mp/src/game/client/hl2mp/clientmode_hl2mpnormal.cpp128
-rw-r--r--mp/src/game/client/hl2mp/clientmode_hl2mpnormal.h47
-rw-r--r--mp/src/game/client/hl2mp/hl2mp_hud_chat.cpp116
-rw-r--r--mp/src/game/client/hl2mp/hl2mp_hud_chat.h65
-rw-r--r--mp/src/game/client/hl2mp/hl2mp_hud_target_id.cpp222
-rw-r--r--mp/src/game/client/hl2mp/hl2mp_hud_team.cpp189
-rw-r--r--mp/src/game/client/hl2mp/hud_deathnotice.cpp352
-rw-r--r--mp/src/game/client/hl2mp/ui/backgroundpanel.cpp431
-rw-r--r--mp/src/game/client/hl2mp/ui/backgroundpanel.h43
-rw-r--r--mp/src/game/client/hl2mp/ui/hl2mpclientscoreboard.cpp653
-rw-r--r--mp/src/game/client/hl2mp/ui/hl2mpclientscoreboard.h63
-rw-r--r--mp/src/game/client/hl2mp/ui/hl2mptextwindow.cpp174
-rw-r--r--mp/src/game/client/hl2mp/ui/hl2mptextwindow.h67
16 files changed, 3868 insertions, 0 deletions
diff --git a/mp/src/game/client/hl2mp/c_hl2mp_player.cpp b/mp/src/game/client/hl2mp/c_hl2mp_player.cpp
new file mode 100644
index 00000000..d68c5215
--- /dev/null
+++ b/mp/src/game/client/hl2mp/c_hl2mp_player.cpp
@@ -0,0 +1,985 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Player for HL2.
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "vcollide_parse.h"
+#include "c_hl2mp_player.h"
+#include "view.h"
+#include "takedamageinfo.h"
+#include "hl2mp_gamerules.h"
+#include "in_buttons.h"
+#include "iviewrender_beams.h" // flashlight beam
+#include "r_efx.h"
+#include "dlight.h"
+
+// Don't alias here
+#if defined( CHL2MP_Player )
+#undef CHL2MP_Player
+#endif
+
+LINK_ENTITY_TO_CLASS( player, C_HL2MP_Player );
+
+IMPLEMENT_CLIENTCLASS_DT(C_HL2MP_Player, DT_HL2MP_Player, CHL2MP_Player)
+ RecvPropFloat( RECVINFO( m_angEyeAngles[0] ) ),
+ RecvPropFloat( RECVINFO( m_angEyeAngles[1] ) ),
+ RecvPropEHandle( RECVINFO( m_hRagdoll ) ),
+ RecvPropInt( RECVINFO( m_iSpawnInterpCounter ) ),
+ RecvPropInt( RECVINFO( m_iPlayerSoundType) ),
+
+ RecvPropBool( RECVINFO( m_fIsWalking ) ),
+END_RECV_TABLE()
+
+BEGIN_PREDICTION_DATA( C_HL2MP_Player )
+ DEFINE_PRED_FIELD( m_fIsWalking, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
+END_PREDICTION_DATA()
+
+#define HL2_WALK_SPEED 150
+#define HL2_NORM_SPEED 190
+#define HL2_SPRINT_SPEED 320
+
+static ConVar cl_playermodel( "cl_playermodel", "none", FCVAR_USERINFO | FCVAR_ARCHIVE | FCVAR_SERVER_CAN_EXECUTE, "Default Player Model");
+static ConVar cl_defaultweapon( "cl_defaultweapon", "weapon_physcannon", FCVAR_USERINFO | FCVAR_ARCHIVE, "Default Spawn Weapon");
+
+void SpawnBlood (Vector vecSpot, const Vector &vecDir, int bloodColor, float flDamage);
+
+C_HL2MP_Player::C_HL2MP_Player() : m_PlayerAnimState( this ), m_iv_angEyeAngles( "C_HL2MP_Player::m_iv_angEyeAngles" )
+{
+ m_iIDEntIndex = 0;
+ m_iSpawnInterpCounterCache = 0;
+
+ m_angEyeAngles.Init();
+
+ AddVar( &m_angEyeAngles, &m_iv_angEyeAngles, LATCH_SIMULATION_VAR );
+
+ m_EntClientFlags |= ENTCLIENTFLAG_DONTUSEIK;
+ m_blinkTimer.Invalidate();
+
+ m_pFlashlightBeam = NULL;
+}
+
+C_HL2MP_Player::~C_HL2MP_Player( void )
+{
+ ReleaseFlashlight();
+}
+
+int C_HL2MP_Player::GetIDTarget() const
+{
+ return m_iIDEntIndex;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Update this client's target entity
+//-----------------------------------------------------------------------------
+void C_HL2MP_Player::UpdateIDTarget()
+{
+ if ( !IsLocalPlayer() )
+ return;
+
+ // Clear old target and find a new one
+ m_iIDEntIndex = 0;
+
+ // don't show IDs in chase spec mode
+ if ( GetObserverMode() == OBS_MODE_CHASE ||
+ GetObserverMode() == OBS_MODE_DEATHCAM )
+ return;
+
+ trace_t tr;
+ Vector vecStart, vecEnd;
+ VectorMA( MainViewOrigin(), 1500, MainViewForward(), vecEnd );
+ VectorMA( MainViewOrigin(), 10, MainViewForward(), vecStart );
+ UTIL_TraceLine( vecStart, vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );
+
+ if ( !tr.startsolid && tr.DidHitNonWorldEntity() )
+ {
+ C_BaseEntity *pEntity = tr.m_pEnt;
+
+ if ( pEntity && (pEntity != this) )
+ {
+ m_iIDEntIndex = pEntity->entindex();
+ }
+ }
+}
+
+void C_HL2MP_Player::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator )
+{
+ Vector vecOrigin = ptr->endpos - vecDir * 4;
+
+ float flDistance = 0.0f;
+
+ if ( info.GetAttacker() )
+ {
+ flDistance = (ptr->endpos - info.GetAttacker()->GetAbsOrigin()).Length();
+ }
+
+ if ( m_takedamage )
+ {
+ AddMultiDamage( info, this );
+
+ int blood = BloodColor();
+
+ CBaseEntity *pAttacker = info.GetAttacker();
+
+ if ( pAttacker )
+ {
+ if ( HL2MPRules()->IsTeamplay() && pAttacker->InSameTeam( this ) == true )
+ return;
+ }
+
+ if ( blood != DONT_BLEED )
+ {
+ SpawnBlood( vecOrigin, vecDir, blood, flDistance );// a little surface blood.
+ TraceBleed( flDistance, vecDir, ptr, info.GetDamageType() );
+ }
+ }
+}
+
+
+C_HL2MP_Player* C_HL2MP_Player::GetLocalHL2MPPlayer()
+{
+ return (C_HL2MP_Player*)C_BasePlayer::GetLocalPlayer();
+}
+
+void C_HL2MP_Player::Initialize( void )
+{
+ m_headYawPoseParam = LookupPoseParameter( "head_yaw" );
+ GetPoseParameterRange( m_headYawPoseParam, m_headYawMin, m_headYawMax );
+
+ m_headPitchPoseParam = LookupPoseParameter( "head_pitch" );
+ GetPoseParameterRange( m_headPitchPoseParam, m_headPitchMin, m_headPitchMax );
+
+ CStudioHdr *hdr = GetModelPtr();
+ for ( int i = 0; i < hdr->GetNumPoseParameters() ; i++ )
+ {
+ SetPoseParameter( hdr, i, 0.0 );
+ }
+}
+
+CStudioHdr *C_HL2MP_Player::OnNewModel( void )
+{
+ CStudioHdr *hdr = BaseClass::OnNewModel();
+
+ Initialize( );
+
+ return hdr;
+}
+
+//-----------------------------------------------------------------------------
+/**
+ * Orient head and eyes towards m_lookAt.
+ */
+void C_HL2MP_Player::UpdateLookAt( void )
+{
+ // head yaw
+ if (m_headYawPoseParam < 0 || m_headPitchPoseParam < 0)
+ return;
+
+ // orient eyes
+ m_viewtarget = m_vLookAtTarget;
+
+ // blinking
+ if (m_blinkTimer.IsElapsed())
+ {
+ m_blinktoggle = !m_blinktoggle;
+ m_blinkTimer.Start( RandomFloat( 1.5f, 4.0f ) );
+ }
+
+ // Figure out where we want to look in world space.
+ QAngle desiredAngles;
+ Vector to = m_vLookAtTarget - EyePosition();
+ VectorAngles( to, desiredAngles );
+
+ // Figure out where our body is facing in world space.
+ QAngle bodyAngles( 0, 0, 0 );
+ bodyAngles[YAW] = GetLocalAngles()[YAW];
+
+
+ float flBodyYawDiff = bodyAngles[YAW] - m_flLastBodyYaw;
+ m_flLastBodyYaw = bodyAngles[YAW];
+
+
+ // Set the head's yaw.
+ float desired = AngleNormalize( desiredAngles[YAW] - bodyAngles[YAW] );
+ desired = clamp( desired, m_headYawMin, m_headYawMax );
+ m_flCurrentHeadYaw = ApproachAngle( desired, m_flCurrentHeadYaw, 130 * gpGlobals->frametime );
+
+ // Counterrotate the head from the body rotation so it doesn't rotate past its target.
+ m_flCurrentHeadYaw = AngleNormalize( m_flCurrentHeadYaw - flBodyYawDiff );
+ desired = clamp( desired, m_headYawMin, m_headYawMax );
+
+ SetPoseParameter( m_headYawPoseParam, m_flCurrentHeadYaw );
+
+
+ // Set the head's yaw.
+ desired = AngleNormalize( desiredAngles[PITCH] );
+ desired = clamp( desired, m_headPitchMin, m_headPitchMax );
+
+ m_flCurrentHeadPitch = ApproachAngle( desired, m_flCurrentHeadPitch, 130 * gpGlobals->frametime );
+ m_flCurrentHeadPitch = AngleNormalize( m_flCurrentHeadPitch );
+ SetPoseParameter( m_headPitchPoseParam, m_flCurrentHeadPitch );
+}
+
+void C_HL2MP_Player::ClientThink( void )
+{
+ bool bFoundViewTarget = false;
+
+ Vector vForward;
+ AngleVectors( GetLocalAngles(), &vForward );
+
+ for( int iClient = 1; iClient <= gpGlobals->maxClients; ++iClient )
+ {
+ CBaseEntity *pEnt = UTIL_PlayerByIndex( iClient );
+ if(!pEnt || !pEnt->IsPlayer())
+ continue;
+
+ if ( pEnt->entindex() == entindex() )
+ continue;
+
+ Vector vTargetOrigin = pEnt->GetAbsOrigin();
+ Vector vMyOrigin = GetAbsOrigin();
+
+ Vector vDir = vTargetOrigin - vMyOrigin;
+
+ if ( vDir.Length() > 128 )
+ continue;
+
+ VectorNormalize( vDir );
+
+ if ( DotProduct( vForward, vDir ) < 0.0f )
+ continue;
+
+ m_vLookAtTarget = pEnt->EyePosition();
+ bFoundViewTarget = true;
+ break;
+ }
+
+ if ( bFoundViewTarget == false )
+ {
+ m_vLookAtTarget = GetAbsOrigin() + vForward * 512;
+ }
+
+ UpdateIDTarget();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+int C_HL2MP_Player::DrawModel( int flags )
+{
+ if ( !m_bReadyToDraw )
+ return 0;
+
+ return BaseClass::DrawModel(flags);
+}
+
+//-----------------------------------------------------------------------------
+// Should this object receive shadows?
+//-----------------------------------------------------------------------------
+bool C_HL2MP_Player::ShouldReceiveProjectedTextures( int flags )
+{
+ Assert( flags & SHADOW_FLAGS_PROJECTED_TEXTURE_TYPE_MASK );
+
+ if ( IsEffectActive( EF_NODRAW ) )
+ return false;
+
+ if( flags & SHADOW_FLAGS_FLASHLIGHT )
+ {
+ return true;
+ }
+
+ return BaseClass::ShouldReceiveProjectedTextures( flags );
+}
+
+void C_HL2MP_Player::DoImpactEffect( trace_t &tr, int nDamageType )
+{
+ if ( GetActiveWeapon() )
+ {
+ GetActiveWeapon()->DoImpactEffect( tr, nDamageType );
+ return;
+ }
+
+ BaseClass::DoImpactEffect( tr, nDamageType );
+}
+
+void C_HL2MP_Player::PreThink( void )
+{
+ 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();
+
+ HandleSpeedChanges();
+
+ if ( m_HL2Local.m_flSuitPower <= 0.0f )
+ {
+ if( IsSprinting() )
+ {
+ StopSprinting();
+ }
+ }
+}
+
+const QAngle &C_HL2MP_Player::EyeAngles()
+{
+ if( IsLocalPlayer() )
+ {
+ return BaseClass::EyeAngles();
+ }
+ else
+ {
+ return m_angEyeAngles;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void C_HL2MP_Player::AddEntity( void )
+{
+ BaseClass::AddEntity();
+
+ QAngle vTempAngles = GetLocalAngles();
+ vTempAngles[PITCH] = m_angEyeAngles[PITCH];
+
+ SetLocalAngles( vTempAngles );
+
+ m_PlayerAnimState.Update();
+
+ // Zero out model pitch, blending takes care of all of it.
+ SetLocalAnglesDim( X_INDEX, 0 );
+
+ if( this != C_BasePlayer::GetLocalPlayer() )
+ {
+ if ( IsEffectActive( EF_DIMLIGHT ) )
+ {
+ int iAttachment = LookupAttachment( "anim_attachment_RH" );
+
+ if ( iAttachment < 0 )
+ return;
+
+ Vector vecOrigin;
+ QAngle eyeAngles = m_angEyeAngles;
+
+ GetAttachment( iAttachment, vecOrigin, eyeAngles );
+
+ Vector vForward;
+ AngleVectors( eyeAngles, &vForward );
+
+ trace_t tr;
+ UTIL_TraceLine( vecOrigin, vecOrigin + (vForward * 200), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
+
+ if( !m_pFlashlightBeam )
+ {
+ BeamInfo_t beamInfo;
+ beamInfo.m_nType = TE_BEAMPOINTS;
+ beamInfo.m_vecStart = tr.startpos;
+ beamInfo.m_vecEnd = tr.endpos;
+ beamInfo.m_pszModelName = "sprites/glow01.vmt";
+ beamInfo.m_pszHaloName = "sprites/glow01.vmt";
+ beamInfo.m_flHaloScale = 3.0;
+ beamInfo.m_flWidth = 8.0f;
+ beamInfo.m_flEndWidth = 35.0f;
+ beamInfo.m_flFadeLength = 300.0f;
+ beamInfo.m_flAmplitude = 0;
+ beamInfo.m_flBrightness = 60.0;
+ beamInfo.m_flSpeed = 0.0f;
+ beamInfo.m_nStartFrame = 0.0;
+ beamInfo.m_flFrameRate = 0.0;
+ beamInfo.m_flRed = 255.0;
+ beamInfo.m_flGreen = 255.0;
+ beamInfo.m_flBlue = 255.0;
+ beamInfo.m_nSegments = 8;
+ beamInfo.m_bRenderable = true;
+ beamInfo.m_flLife = 0.5;
+ beamInfo.m_nFlags = FBEAM_FOREVER | FBEAM_ONLYNOISEONCE | FBEAM_NOTILE | FBEAM_HALOBEAM;
+
+ m_pFlashlightBeam = beams->CreateBeamPoints( beamInfo );
+ }
+
+ if( m_pFlashlightBeam )
+ {
+ BeamInfo_t beamInfo;
+ beamInfo.m_vecStart = tr.startpos;
+ beamInfo.m_vecEnd = tr.endpos;
+ beamInfo.m_flRed = 255.0;
+ beamInfo.m_flGreen = 255.0;
+ beamInfo.m_flBlue = 255.0;
+
+ beams->UpdateBeamInfo( m_pFlashlightBeam, beamInfo );
+
+ dlight_t *el = effects->CL_AllocDlight( 0 );
+ el->origin = tr.endpos;
+ el->radius = 50;
+ el->color.r = 200;
+ el->color.g = 200;
+ el->color.b = 200;
+ el->die = gpGlobals->curtime + 0.1;
+ }
+ }
+ else if ( m_pFlashlightBeam )
+ {
+ ReleaseFlashlight();
+ }
+ }
+}
+
+ShadowType_t C_HL2MP_Player::ShadowCastType( void )
+{
+ if ( !IsVisible() )
+ return SHADOWS_NONE;
+
+ return SHADOWS_RENDER_TO_TEXTURE_DYNAMIC;
+}
+
+
+const QAngle& C_HL2MP_Player::GetRenderAngles()
+{
+ if ( IsRagdoll() )
+ {
+ return vec3_angle;
+ }
+ else
+ {
+ return m_PlayerAnimState.GetRenderAngles();
+ }
+}
+
+bool C_HL2MP_Player::ShouldDraw( void )
+{
+ // If we're dead, our ragdoll will be drawn for us instead.
+ if ( !IsAlive() )
+ return false;
+
+// if( GetTeamNumber() == TEAM_SPECTATOR )
+// return false;
+
+ if( IsLocalPlayer() && IsRagdoll() )
+ return true;
+
+ if ( IsRagdoll() )
+ return false;
+
+ return BaseClass::ShouldDraw();
+}
+
+void C_HL2MP_Player::NotifyShouldTransmit( ShouldTransmitState_t state )
+{
+ if ( state == SHOULDTRANSMIT_END )
+ {
+ if( m_pFlashlightBeam != NULL )
+ {
+ ReleaseFlashlight();
+ }
+ }
+
+ BaseClass::NotifyShouldTransmit( state );
+}
+
+void C_HL2MP_Player::OnDataChanged( DataUpdateType_t type )
+{
+ BaseClass::OnDataChanged( type );
+
+ if ( type == DATA_UPDATE_CREATED )
+ {
+ SetNextClientThink( CLIENT_THINK_ALWAYS );
+ }
+
+ UpdateVisibility();
+}
+
+void C_HL2MP_Player::PostDataUpdate( DataUpdateType_t updateType )
+{
+ if ( m_iSpawnInterpCounter != m_iSpawnInterpCounterCache )
+ {
+ MoveToLastReceivedPosition( true );
+ ResetLatched();
+ m_iSpawnInterpCounterCache = m_iSpawnInterpCounter;
+ }
+
+ BaseClass::PostDataUpdate( updateType );
+}
+
+void C_HL2MP_Player::ReleaseFlashlight( void )
+{
+ if( m_pFlashlightBeam )
+ {
+ m_pFlashlightBeam->flags = 0;
+ m_pFlashlightBeam->die = gpGlobals->curtime - 1;
+
+ m_pFlashlightBeam = NULL;
+ }
+}
+
+float C_HL2MP_Player::GetFOV( void )
+{
+ //Find our FOV with offset zoom value
+ float flFOVOffset = C_BasePlayer::GetFOV() + GetZoom();
+
+ // Clamp FOV in MP
+ int min_fov = GetMinFOV();
+
+ // Don't let it go too low
+ flFOVOffset = MAX( min_fov, flFOVOffset );
+
+ return flFOVOffset;
+}
+
+//=========================================================
+// Autoaim
+// set crosshair position to point to enemey
+//=========================================================
+Vector C_HL2MP_Player::GetAutoaimVector( float flDelta )
+{
+ // Never autoaim a predicted weapon (for now)
+ Vector forward;
+ AngleVectors( EyeAngles() + m_Local.m_vecPunchAngle, &forward );
+ return forward;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns whether or not we are allowed to sprint now.
+//-----------------------------------------------------------------------------
+bool C_HL2MP_Player::CanSprint( void )
+{
+ return ( (!m_Local.m_bDucked && !m_Local.m_bDucking) && (GetWaterLevel() != 3) );
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void C_HL2MP_Player::StartSprinting( void )
+{
+ if( m_HL2Local.m_flSuitPower < 10 )
+ {
+ // Don't sprint unless there's a reasonable
+ // amount of suit power.
+ CPASAttenuationFilter filter( this );
+ filter.UsePredictionRules();
+ EmitSound( filter, entindex(), "HL2Player.SprintNoPower" );
+ return;
+ }
+
+ CPASAttenuationFilter filter( this );
+ filter.UsePredictionRules();
+ EmitSound( filter, entindex(), "HL2Player.SprintStart" );
+
+ SetMaxSpeed( HL2_SPRINT_SPEED );
+ m_fIsSprinting = true;
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void C_HL2MP_Player::StopSprinting( void )
+{
+ SetMaxSpeed( HL2_NORM_SPEED );
+ m_fIsSprinting = false;
+}
+
+void C_HL2MP_Player::HandleSpeedChanges( void )
+{
+ int buttonsChanged = m_afButtonPressed | m_afButtonReleased;
+
+ if( buttonsChanged & IN_SPEED )
+ {
+ // The state of the sprint/run button has changed.
+ if ( IsSuitEquipped() )
+ {
+ if ( !(m_afButtonPressed & IN_SPEED) && IsSprinting() )
+ {
+ StopSprinting();
+ }
+ else if ( (m_afButtonPressed & IN_SPEED) && !IsSprinting() )
+ {
+ if ( CanSprint() )
+ {
+ StartSprinting();
+ }
+ else
+ {
+ // Reset key, so it will be activated post whatever is suppressing it.
+ m_nButtons &= ~IN_SPEED;
+ }
+ }
+ }
+ }
+ else if( buttonsChanged & IN_WALK )
+ {
+ if ( IsSuitEquipped() )
+ {
+ // The state of the WALK button has changed.
+ if( IsWalking() && !(m_afButtonPressed & IN_WALK) )
+ {
+ StopWalking();
+ }
+ else if( !IsWalking() && !IsSprinting() && (m_afButtonPressed & IN_WALK) && !(m_nButtons & IN_DUCK) )
+ {
+ StartWalking();
+ }
+ }
+ }
+
+ if ( IsSuitEquipped() && m_fIsWalking && !(m_nButtons & IN_WALK) )
+ StopWalking();
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void C_HL2MP_Player::StartWalking( void )
+{
+ SetMaxSpeed( HL2_WALK_SPEED );
+ m_fIsWalking = true;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void C_HL2MP_Player::StopWalking( void )
+{
+ SetMaxSpeed( HL2_NORM_SPEED );
+ m_fIsWalking = false;
+}
+
+void C_HL2MP_Player::ItemPreFrame( void )
+{
+ if ( GetFlags() & FL_FROZEN )
+ return;
+
+ // Disallow shooting while zooming
+ if ( m_nButtons & IN_ZOOM )
+ {
+ //FIXME: Held weapons like the grenade get sad when this happens
+ m_nButtons &= ~(IN_ATTACK|IN_ATTACK2);
+ }
+
+ BaseClass::ItemPreFrame();
+
+}
+
+void C_HL2MP_Player::ItemPostFrame( void )
+{
+ if ( GetFlags() & FL_FROZEN )
+ return;
+
+ BaseClass::ItemPostFrame();
+}
+
+C_BaseAnimating *C_HL2MP_Player::BecomeRagdollOnClient()
+{
+ // Let the C_CSRagdoll entity do this.
+ // m_builtRagdoll = true;
+ return NULL;
+}
+
+void C_HL2MP_Player::CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov )
+{
+ if ( m_lifeState != LIFE_ALIVE && !IsObserver() )
+ {
+ 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_HL2MP_Player::GetRepresentativeRagdoll() const
+{
+ if ( m_hRagdoll.Get() )
+ {
+ C_HL2MPRagdoll *pRagdoll = (C_HL2MPRagdoll*)m_hRagdoll.Get();
+
+ return pRagdoll->GetIRagdoll();
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+//HL2MPRAGDOLL
+
+
+IMPLEMENT_CLIENTCLASS_DT_NOBASE( C_HL2MPRagdoll, DT_HL2MPRagdoll, CHL2MPRagdoll )
+ 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_HL2MPRagdoll::C_HL2MPRagdoll()
+{
+
+}
+
+C_HL2MPRagdoll::~C_HL2MPRagdoll()
+{
+ PhysCleanupFrictionSounds( this );
+
+ if ( m_hPlayer )
+ {
+ m_hPlayer->CreateModelInstance();
+ }
+}
+
+void C_HL2MPRagdoll::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_HL2MPRagdoll::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 );
+
+ // Blood spray!
+// FX_CS_BloodSpray( hitpos, dir, 10 );
+ }
+
+ m_pRagdoll->ResetRagdollSleepAfterTime();
+}
+
+
+void C_HL2MPRagdoll::CreateHL2MPRagdoll( 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_HL2MP_Player *pPlayer = dynamic_cast< C_HL2MP_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_HL2MPRagdoll::OnDataChanged( DataUpdateType_t type )
+{
+ BaseClass::OnDataChanged( type );
+
+ if ( type == DATA_UPDATE_CREATED )
+ {
+ CreateHL2MPRagdoll();
+ }
+}
+
+IRagdoll* C_HL2MPRagdoll::GetIRagdoll() const
+{
+ return m_pRagdoll;
+}
+
+void C_HL2MPRagdoll::UpdateOnRemove( void )
+{
+ VPhysicsSetObject( NULL );
+
+ BaseClass::UpdateOnRemove();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: clear out any face/eye values stored in the material system
+//-----------------------------------------------------------------------------
+void C_HL2MPRagdoll::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 );
+ }
+ }
+}
+
+void C_HL2MP_Player::PostThink( void )
+{
+ BaseClass::PostThink();
+
+ // Store the eye angles pitch so the client can compute its animation state correctly.
+ m_angEyeAngles = EyeAngles();
+} \ No newline at end of file
diff --git a/mp/src/game/client/hl2mp/c_hl2mp_player.h b/mp/src/game/client/hl2mp/c_hl2mp_player.h
new file mode 100644
index 00000000..4ff46946
--- /dev/null
+++ b/mp/src/game/client/hl2mp/c_hl2mp_player.h
@@ -0,0 +1,173 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#ifndef HL2MP_PLAYER_H
+#define HL2MP_PLAYER_H
+#pragma once
+
+class C_HL2MP_Player;
+#include "c_basehlplayer.h"
+#include "hl2mp_player_shared.h"
+#include "beamdraw.h"
+
+//=============================================================================
+// >> HL2MP_Player
+//=============================================================================
+class C_HL2MP_Player : public C_BaseHLPlayer
+{
+public:
+ DECLARE_CLASS( C_HL2MP_Player, C_BaseHLPlayer );
+
+ DECLARE_CLIENTCLASS();
+ DECLARE_PREDICTABLE();
+ DECLARE_INTERPOLATION();
+
+
+ C_HL2MP_Player();
+ ~C_HL2MP_Player( void );
+
+ void ClientThink( void );
+
+ static C_HL2MP_Player* GetLocalHL2MPPlayer();
+
+ virtual int DrawModel( int flags );
+ virtual void AddEntity( void );
+
+ QAngle GetAnimEyeAngles( void ) { return m_angEyeAngles; }
+ Vector GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget = NULL );
+
+
+ // Should this object cast shadows?
+ virtual ShadowType_t ShadowCastType( void );
+ virtual C_BaseAnimating *BecomeRagdollOnClient();
+ virtual const QAngle& GetRenderAngles();
+ virtual bool ShouldDraw( void );
+ virtual void OnDataChanged( DataUpdateType_t type );
+ virtual float GetFOV( void );
+ virtual CStudioHdr *OnNewModel( void );
+ virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator );
+ virtual void ItemPreFrame( void );
+ virtual void ItemPostFrame( void );
+ virtual float GetMinFOV() const { return 5.0f; }
+ virtual Vector GetAutoaimVector( float flDelta );
+ virtual void NotifyShouldTransmit( ShouldTransmitState_t state );
+ virtual void CreateLightEffects( void ) {}
+ virtual bool ShouldReceiveProjectedTextures( int flags );
+ virtual void PostDataUpdate( DataUpdateType_t updateType );
+ virtual void PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, float fvol, bool force );
+ virtual void PreThink( void );
+ virtual void DoImpactEffect( trace_t &tr, int nDamageType );
+ IRagdoll* GetRepresentativeRagdoll() const;
+ virtual void CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov );
+ virtual const QAngle& EyeAngles( void );
+
+
+ bool CanSprint( void );
+ void StartSprinting( void );
+ void StopSprinting( void );
+ void HandleSpeedChanges( void );
+ void UpdateLookAt( void );
+ void Initialize( void );
+ int GetIDTarget() const;
+ void UpdateIDTarget( void );
+ void PrecacheFootStepSounds( void );
+ const char *GetPlayerModelSoundPrefix( void );
+
+ HL2MPPlayerState State_Get() const;
+
+ // Walking
+ void StartWalking( void );
+ void StopWalking( void );
+ bool IsWalking( void ) { return m_fIsWalking; }
+
+ virtual void PostThink( void );
+
+private:
+
+ C_HL2MP_Player( const C_HL2MP_Player & );
+
+ CPlayerAnimState m_PlayerAnimState;
+
+ QAngle m_angEyeAngles;
+
+ CInterpolatedVar< QAngle > m_iv_angEyeAngles;
+
+ EHANDLE m_hRagdoll;
+
+ int m_headYawPoseParam;
+ int m_headPitchPoseParam;
+ float m_headYawMin;
+ float m_headYawMax;
+ float m_headPitchMin;
+ float m_headPitchMax;
+
+ bool m_isInit;
+ Vector m_vLookAtTarget;
+
+ float m_flLastBodyYaw;
+ float m_flCurrentHeadYaw;
+ float m_flCurrentHeadPitch;
+
+ int m_iIDEntIndex;
+
+ CountdownTimer m_blinkTimer;
+
+ int m_iSpawnInterpCounter;
+ int m_iSpawnInterpCounterCache;
+
+ int m_iPlayerSoundType;
+
+ void ReleaseFlashlight( void );
+ Beam_t *m_pFlashlightBeam;
+
+ CNetworkVar( HL2MPPlayerState, m_iPlayerState );
+
+ bool m_fIsWalking;
+};
+
+inline C_HL2MP_Player *ToHL2MPPlayer( CBaseEntity *pEntity )
+{
+ if ( !pEntity || !pEntity->IsPlayer() )
+ return NULL;
+
+ return dynamic_cast<C_HL2MP_Player*>( pEntity );
+}
+
+
+class C_HL2MPRagdoll : public C_BaseAnimatingOverlay
+{
+public:
+ DECLARE_CLASS( C_HL2MPRagdoll, C_BaseAnimatingOverlay );
+ DECLARE_CLIENTCLASS();
+
+ C_HL2MPRagdoll();
+ ~C_HL2MPRagdoll();
+
+ 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_HL2MPRagdoll( const C_HL2MPRagdoll & ) {}
+
+ void Interp_Copy( C_BaseAnimatingOverlay *pDestinationEntity );
+ void CreateHL2MPRagdoll( void );
+
+private:
+
+ EHANDLE m_hPlayer;
+ CNetworkVector( m_vecRagdollVelocity );
+ CNetworkVector( m_vecRagdollOrigin );
+};
+
+#endif //HL2MP_PLAYER_H
diff --git a/mp/src/game/client/hl2mp/c_te_hl2mp_shotgun_shot.cpp b/mp/src/game/client/hl2mp/c_te_hl2mp_shotgun_shot.cpp
new file mode 100644
index 00000000..c22757aa
--- /dev/null
+++ b/mp/src/game/client/hl2mp/c_te_hl2mp_shotgun_shot.cpp
@@ -0,0 +1,160 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "c_basetempentity.h"
+#include <cliententitylist.h>
+#include "ammodef.h"
+#include "c_te_effect_dispatch.h"
+#include "shot_manipulator.h"
+
+class C_TEHL2MPFireBullets : public C_BaseTempEntity
+{
+public:
+ DECLARE_CLASS( C_TEHL2MPFireBullets, C_BaseTempEntity );
+ DECLARE_CLIENTCLASS();
+
+ virtual void PostDataUpdate( DataUpdateType_t updateType );
+
+ void CreateEffects( void );
+
+public:
+ int m_iPlayer;
+ Vector m_vecOrigin;
+ Vector m_vecDir;
+ int m_iAmmoID;
+ int m_iWeaponIndex;
+ int m_iSeed;
+ float m_flSpread;
+ int m_iShots;
+ bool m_bDoImpacts;
+ bool m_bDoTracers;
+};
+
+class CTraceFilterSkipPlayerAndViewModelOnly : public CTraceFilter
+{
+public:
+ virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask )
+ {
+ C_BaseEntity *pEntity = EntityFromEntityHandle( pServerEntity );
+ if( pEntity &&
+ ( ( dynamic_cast<C_BaseViewModel *>( pEntity ) != NULL ) ||
+ ( dynamic_cast<C_BasePlayer *>( pEntity ) != NULL ) ) )
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+};
+
+void C_TEHL2MPFireBullets::CreateEffects( void )
+{
+ CAmmoDef* pAmmoDef = GetAmmoDef();
+
+ if ( pAmmoDef == NULL )
+ return;
+
+ C_BaseEntity *pEnt = ClientEntityList().GetEnt( m_iPlayer );
+
+ if ( pEnt )
+ {
+ C_BasePlayer *pPlayer = dynamic_cast<C_BasePlayer *>(pEnt);
+
+ if ( pPlayer && pPlayer->GetActiveWeapon() )
+ {
+ C_BaseCombatWeapon *pWpn = dynamic_cast<C_BaseCombatWeapon *>( pPlayer->GetActiveWeapon() );
+
+ if ( pWpn )
+ {
+ int iSeed = m_iSeed;
+
+ CShotManipulator Manipulator( m_vecDir );
+
+ for (int iShot = 0; iShot < m_iShots; iShot++)
+ {
+ RandomSeed( iSeed ); // init random system with this seed
+
+ // Don't run the biasing code for the player at the moment.
+ Vector vecDir = Manipulator.ApplySpread( Vector( m_flSpread, m_flSpread, m_flSpread ) );
+ Vector vecEnd = m_vecOrigin + vecDir * MAX_TRACE_LENGTH;
+ trace_t tr;
+ CTraceFilterSkipPlayerAndViewModelOnly traceFilter;
+
+ if( m_iShots > 1 && iShot % 2 )
+ {
+ // Half of the shotgun pellets are hulls that make it easier to hit targets with the shotgun.
+ UTIL_TraceHull( m_vecOrigin, vecEnd, Vector( -3, -3, -3 ), Vector( 3, 3, 3 ), MASK_SHOT, &traceFilter, &tr );
+ }
+ else
+ {
+ UTIL_TraceLine( m_vecOrigin, vecEnd, MASK_SHOT, &traceFilter, &tr);
+ }
+
+ if ( m_bDoTracers )
+ {
+ const char *pTracerName = pWpn->GetTracerType();
+
+ CEffectData data;
+ data.m_vStart = tr.startpos;
+ data.m_vOrigin = tr.endpos;
+ data.m_hEntity = pWpn->GetRefEHandle();
+ data.m_flScale = 0.0f;
+ data.m_fFlags |= TRACER_FLAG_USEATTACHMENT;
+ // Stomp the start, since it's not going to be used anyway
+ data.m_nAttachmentIndex = 1;
+
+ if ( pTracerName )
+ {
+ DispatchEffect( pTracerName, data );
+ }
+ else
+ {
+ DispatchEffect( "Tracer", data );
+ }
+ }
+
+ if ( m_bDoImpacts )
+ {
+ pWpn->DoImpactEffect( tr, pAmmoDef->DamageType( m_iAmmoID ) );
+ }
+
+ iSeed++;
+ }
+ }
+ }
+ }
+
+}
+
+void C_TEHL2MPFireBullets::PostDataUpdate( DataUpdateType_t updateType )
+{
+ if ( m_bDoTracers || m_bDoImpacts )
+ {
+ CreateEffects();
+ }
+}
+
+
+IMPLEMENT_CLIENTCLASS_EVENT( C_TEHL2MPFireBullets, DT_TEHL2MPFireBullets, CTEHL2MPFireBullets );
+
+
+BEGIN_RECV_TABLE_NOBASE(C_TEHL2MPFireBullets, DT_TEHL2MPFireBullets )
+ RecvPropVector( RECVINFO( m_vecOrigin ) ),
+ RecvPropVector( RECVINFO( m_vecDir ) ),
+ RecvPropInt( RECVINFO( m_iAmmoID ) ),
+ RecvPropInt( RECVINFO( m_iSeed ) ),
+ RecvPropInt( RECVINFO( m_iShots ) ),
+ RecvPropInt( RECVINFO( m_iPlayer ) ),
+ RecvPropInt( RECVINFO( m_iWeaponIndex ) ),
+ RecvPropFloat( RECVINFO( m_flSpread ) ),
+ RecvPropBool( RECVINFO( m_bDoImpacts ) ),
+ RecvPropBool( RECVINFO( m_bDoTracers ) ),
+END_RECV_TABLE()
+
+
diff --git a/mp/src/game/client/hl2mp/clientmode_hl2mpnormal.cpp b/mp/src/game/client/hl2mp/clientmode_hl2mpnormal.cpp
new file mode 100644
index 00000000..6c784781
--- /dev/null
+++ b/mp/src/game/client/hl2mp/clientmode_hl2mpnormal.cpp
@@ -0,0 +1,128 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Draws the normal TF2 or HL2 HUD.
+//
+// $Workfile: $
+// $Date: $
+// $NoKeywords: $
+//=============================================================================//
+#include "cbase.h"
+#include "clientmode_hl2mpnormal.h"
+#include "vgui_int.h"
+#include "hud.h"
+#include <vgui/IInput.h>
+#include <vgui/IPanel.h>
+#include <vgui/ISurface.h>
+#include <vgui_controls/AnimationController.h>
+#include "iinput.h"
+#include "hl2mpclientscoreboard.h"
+#include "hl2mptextwindow.h"
+#include "ienginevgui.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+//-----------------------------------------------------------------------------
+// Globals
+//-----------------------------------------------------------------------------
+vgui::HScheme g_hVGuiCombineScheme = 0;
+
+
+// Instance the singleton and expose the interface to it.
+IClientMode *GetClientModeNormal()
+{
+ static ClientModeHL2MPNormal g_ClientModeNormal;
+ return &g_ClientModeNormal;
+}
+
+ClientModeHL2MPNormal* GetClientModeHL2MPNormal()
+{
+ Assert( dynamic_cast< ClientModeHL2MPNormal* >( GetClientModeNormal() ) );
+
+ return static_cast< ClientModeHL2MPNormal* >( GetClientModeNormal() );
+}
+
+//-----------------------------------------------------------------------------
+// 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 IViewPortPanel *CreatePanelByName( const char *szPanelName );
+};
+
+int ClientModeHL2MPNormal::GetDeathMessageStartHeight( void )
+{
+ return m_pViewport->GetDeathMessageStartHeight();
+}
+
+IViewPortPanel* CHudViewport::CreatePanelByName( const char *szPanelName )
+{
+ IViewPortPanel* newpanel = NULL;
+
+ if ( Q_strcmp( PANEL_SCOREBOARD, szPanelName) == 0 )
+ {
+ newpanel = new CHL2MPClientScoreBoardDialog( this );
+ return newpanel;
+ }
+ else if ( Q_strcmp(PANEL_INFO, szPanelName) == 0 )
+ {
+ newpanel = new CHL2MPTextWindow( this );
+ return newpanel;
+ }
+ else if ( Q_strcmp(PANEL_SPECGUI, szPanelName) == 0 )
+ {
+ newpanel = new CHL2MPSpectatorGUI( this );
+ return newpanel;
+ }
+
+
+ return BaseClass::CreatePanelByName( szPanelName );
+}
+
+//-----------------------------------------------------------------------------
+// ClientModeHLNormal implementation
+//-----------------------------------------------------------------------------
+ClientModeHL2MPNormal::ClientModeHL2MPNormal()
+{
+ m_pViewport = new CHudViewport();
+ m_pViewport->Start( gameuifuncs, gameeventmanager );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+ClientModeHL2MPNormal::~ClientModeHL2MPNormal()
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void ClientModeHL2MPNormal::Init()
+{
+ BaseClass::Init();
+
+ // Load up the combine control panel scheme
+ g_hVGuiCombineScheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/CombinePanelScheme.res", "CombineScheme" );
+ if (!g_hVGuiCombineScheme)
+ {
+ Warning( "Couldn't load combine panel scheme!\n" );
+ }
+}
+
+
+
diff --git a/mp/src/game/client/hl2mp/clientmode_hl2mpnormal.h b/mp/src/game/client/hl2mp/clientmode_hl2mpnormal.h
new file mode 100644
index 00000000..a5140a0c
--- /dev/null
+++ b/mp/src/game/client/hl2mp/clientmode_hl2mpnormal.h
@@ -0,0 +1,47 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $Workfile: $
+// $Date: $
+// $NoKeywords: $
+//=============================================================================//
+#if !defined( CLIENTMODE_HLNORMAL_H )
+#define CLIENTMODE_HLNORMAL_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "clientmode_shared.h"
+#include <vgui_controls/EditablePanel.h>
+#include <vgui/Cursor.h>
+
+class CHudViewport;
+
+namespace vgui
+{
+ typedef unsigned long HScheme;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+class ClientModeHL2MPNormal : public ClientModeShared
+{
+public:
+ DECLARE_CLASS( ClientModeHL2MPNormal, ClientModeShared );
+
+ ClientModeHL2MPNormal();
+ ~ClientModeHL2MPNormal();
+
+ virtual void Init();
+ virtual int GetDeathMessageStartHeight( void );
+};
+
+extern IClientMode *GetClientModeNormal();
+extern vgui::HScheme g_hVGuiCombineScheme;
+
+extern ClientModeHL2MPNormal* GetClientModeHL2MPNormal();
+
+#endif // CLIENTMODE_HLNORMAL_H
diff --git a/mp/src/game/client/hl2mp/hl2mp_hud_chat.cpp b/mp/src/game/client/hl2mp/hl2mp_hud_chat.cpp
new file mode 100644
index 00000000..65163609
--- /dev/null
+++ b/mp/src/game/client/hl2mp/hl2mp_hud_chat.cpp
@@ -0,0 +1,116 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "hl2mp_hud_chat.h"
+#include "hud_macros.h"
+#include "text_message.h"
+#include "vguicenterprint.h"
+#include "vgui/ILocalize.h"
+#include "c_team.h"
+#include "c_playerresource.h"
+#include "c_hl2mp_player.h"
+#include "hl2mp_gamerules.h"
+#include "ihudlcd.h"
+
+
+
+DECLARE_HUDELEMENT( CHudChat );
+
+DECLARE_HUD_MESSAGE( CHudChat, SayText );
+DECLARE_HUD_MESSAGE( CHudChat, SayText2 );
+DECLARE_HUD_MESSAGE( CHudChat, TextMsg );
+
+
+//=====================
+//CHudChatLine
+//=====================
+
+void CHudChatLine::ApplySchemeSettings(vgui::IScheme *pScheme)
+{
+ BaseClass::ApplySchemeSettings( pScheme );
+}
+
+//=====================
+//CHudChatInputLine
+//=====================
+
+void CHudChatInputLine::ApplySchemeSettings(vgui::IScheme *pScheme)
+{
+ BaseClass::ApplySchemeSettings(pScheme);
+}
+
+//=====================
+//CHudChat
+//=====================
+
+CHudChat::CHudChat( const char *pElementName ) : BaseClass( pElementName )
+{
+
+}
+
+void CHudChat::CreateChatInputLine( void )
+{
+ m_pChatInput = new CHudChatInputLine( this, "ChatInputLine" );
+ m_pChatInput->SetVisible( false );
+}
+
+void CHudChat::CreateChatLines( void )
+{
+ m_ChatLine = new CHudChatLine( this, "ChatLine1" );
+ m_ChatLine->SetVisible( false );
+}
+
+void CHudChat::ApplySchemeSettings( vgui::IScheme *pScheme )
+{
+ BaseClass::ApplySchemeSettings( pScheme );
+}
+
+
+void CHudChat::Init( void )
+{
+ BaseClass::Init();
+
+ HOOK_HUD_MESSAGE( CHudChat, SayText );
+ HOOK_HUD_MESSAGE( CHudChat, SayText2 );
+ HOOK_HUD_MESSAGE( CHudChat, TextMsg );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Overrides base reset to not cancel chat at round restart
+//-----------------------------------------------------------------------------
+void CHudChat::Reset( void )
+{
+}
+
+int CHudChat::GetChatInputOffset( void )
+{
+ if ( m_pChatInput->IsVisible() )
+ {
+ return m_iFontHeight;
+ }
+ else
+ return 0;
+}
+
+Color CHudChat::GetClientColor( int clientIndex )
+{
+ if ( clientIndex == 0 ) // console msg
+ {
+ return g_ColorYellow;
+ }
+ else if( g_PR )
+ {
+ switch ( g_PR->GetTeam( clientIndex ) )
+ {
+ case TEAM_COMBINE : return g_ColorBlue;
+ case TEAM_REBELS : return g_ColorRed;
+ default : return g_ColorYellow;
+ }
+ }
+
+ return g_ColorYellow;
+} \ No newline at end of file
diff --git a/mp/src/game/client/hl2mp/hl2mp_hud_chat.h b/mp/src/game/client/hl2mp/hl2mp_hud_chat.h
new file mode 100644
index 00000000..ee2ea38c
--- /dev/null
+++ b/mp/src/game/client/hl2mp/hl2mp_hud_chat.h
@@ -0,0 +1,65 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef CS_HUD_CHAT_H
+#define CS_HUD_CHAT_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include <hud_basechat.h>
+
+class CHudChatLine : public CBaseHudChatLine
+{
+ DECLARE_CLASS_SIMPLE( CHudChatLine, CBaseHudChatLine );
+
+public:
+ CHudChatLine( vgui::Panel *parent, const char *panelName ) : CBaseHudChatLine( parent, panelName ) {}
+
+ virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
+
+ void MsgFunc_SayText(bf_read &msg);
+
+
+
+private:
+ CHudChatLine( const CHudChatLine & ); // not defined, not accessible
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: The prompt and text entry area for chat messages
+//-----------------------------------------------------------------------------
+class CHudChatInputLine : public CBaseHudChatInputLine
+{
+ DECLARE_CLASS_SIMPLE( CHudChatInputLine, CBaseHudChatInputLine );
+
+public:
+ CHudChatInputLine( CBaseHudChat *parent, char const *panelName ) : CBaseHudChatInputLine( parent, panelName ) {}
+
+ virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
+};
+
+class CHudChat : public CBaseHudChat
+{
+ DECLARE_CLASS_SIMPLE( CHudChat, CBaseHudChat );
+
+public:
+ CHudChat( const char *pElementName );
+
+ virtual void CreateChatInputLine( void );
+ virtual void CreateChatLines( void );
+
+ virtual void Init( void );
+ virtual void Reset( void );
+ virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
+
+ int GetChatInputOffset( void );
+
+ virtual Color GetClientColor( int clientIndex );
+};
+
+#endif //CS_HUD_CHAT_H \ No newline at end of file
diff --git a/mp/src/game/client/hl2mp/hl2mp_hud_target_id.cpp b/mp/src/game/client/hl2mp/hl2mp_hud_target_id.cpp
new file mode 100644
index 00000000..f88279b9
--- /dev/null
+++ b/mp/src/game/client/hl2mp/hl2mp_hud_target_id.cpp
@@ -0,0 +1,222 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: HUD Target ID element
+//
+// $NoKeywords: $
+//=============================================================================//
+#include "cbase.h"
+#include "hud.h"
+#include "hudelement.h"
+#include "c_hl2mp_player.h"
+#include "c_playerresource.h"
+#include "vgui_entitypanel.h"
+#include "iclientmode.h"
+#include "vgui/ILocalize.h"
+#include "hl2mp_gamerules.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+#define PLAYER_HINT_DISTANCE 150
+#define PLAYER_HINT_DISTANCE_SQ (PLAYER_HINT_DISTANCE*PLAYER_HINT_DISTANCE)
+
+static ConVar hud_centerid( "hud_centerid", "1" );
+static ConVar hud_showtargetid( "hud_showtargetid", "1" );
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+class CTargetID : public CHudElement, public vgui::Panel
+{
+ DECLARE_CLASS_SIMPLE( CTargetID, vgui::Panel );
+
+public:
+ CTargetID( const char *pElementName );
+ void Init( void );
+ virtual void ApplySchemeSettings( vgui::IScheme *scheme );
+ virtual void Paint( void );
+ void VidInit( void );
+
+private:
+ Color GetColorForTargetTeam( int iTeamNumber );
+
+ vgui::HFont m_hFont;
+ int m_iLastEntIndex;
+ float m_flLastChangeTime;
+};
+
+DECLARE_HUDELEMENT( CTargetID );
+
+using namespace vgui;
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CTargetID::CTargetID( const char *pElementName ) :
+ CHudElement( pElementName ), BaseClass( NULL, "TargetID" )
+{
+ vgui::Panel *pParent = g_pClientMode->GetViewport();
+ SetParent( pParent );
+
+ m_hFont = g_hFontTrebuchet24;
+ m_flLastChangeTime = 0;
+ m_iLastEntIndex = 0;
+
+ SetHiddenBits( HIDEHUD_MISCSTATUS );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Setup
+//-----------------------------------------------------------------------------
+void CTargetID::Init( void )
+{
+};
+
+void CTargetID::ApplySchemeSettings( vgui::IScheme *scheme )
+{
+ BaseClass::ApplySchemeSettings( scheme );
+
+ m_hFont = scheme->GetFont( "TargetID", IsProportional() );
+
+ SetPaintBackgroundEnabled( false );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: clear out string etc between levels
+//-----------------------------------------------------------------------------
+void CTargetID::VidInit()
+{
+ CHudElement::VidInit();
+
+ m_flLastChangeTime = 0;
+ m_iLastEntIndex = 0;
+}
+
+Color CTargetID::GetColorForTargetTeam( int iTeamNumber )
+{
+ return GameResources()->GetTeamColor( iTeamNumber );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Draw function for the element
+//-----------------------------------------------------------------------------
+void CTargetID::Paint()
+{
+#define MAX_ID_STRING 256
+ wchar_t sIDString[ MAX_ID_STRING ];
+ sIDString[0] = 0;
+
+ C_HL2MP_Player *pPlayer = C_HL2MP_Player::GetLocalHL2MPPlayer();
+
+ if ( !pPlayer )
+ return;
+
+ Color c;
+
+ // Get our target's ent index
+ int iEntIndex = pPlayer->GetIDTarget();
+ // Didn't find one?
+ if ( !iEntIndex )
+ {
+ // Check to see if we should clear our ID
+ if ( m_flLastChangeTime && (gpGlobals->curtime > (m_flLastChangeTime + 0.5)) )
+ {
+ m_flLastChangeTime = 0;
+ sIDString[0] = 0;
+ m_iLastEntIndex = 0;
+ }
+ else
+ {
+ // Keep re-using the old one
+ iEntIndex = m_iLastEntIndex;
+ }
+ }
+ else
+ {
+ m_flLastChangeTime = gpGlobals->curtime;
+ }
+
+ // Is this an entindex sent by the server?
+ if ( iEntIndex )
+ {
+ C_BasePlayer *pPlayer = static_cast<C_BasePlayer*>(cl_entitylist->GetEnt( iEntIndex ));
+ C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
+
+ const char *printFormatString = NULL;
+ wchar_t wszPlayerName[ MAX_PLAYER_NAME_LENGTH ];
+ wchar_t wszHealthText[ 10 ];
+ bool bShowHealth = false;
+ bool bShowPlayerName = false;
+
+ // Some entities we always want to check, cause the text may change
+ // even while we're looking at it
+ // Is it a player?
+ if ( IsPlayerIndex( iEntIndex ) )
+ {
+ c = GetColorForTargetTeam( pPlayer->GetTeamNumber() );
+
+ bShowPlayerName = true;
+ g_pVGuiLocalize->ConvertANSIToUnicode( pPlayer->GetPlayerName(), wszPlayerName, sizeof(wszPlayerName) );
+
+ if ( HL2MPRules()->IsTeamplay() == true && pPlayer->InSameTeam(pLocalPlayer) )
+ {
+ printFormatString = "#Playerid_sameteam";
+ bShowHealth = true;
+ }
+ else
+ {
+ printFormatString = "#Playerid_diffteam";
+ }
+
+
+ if ( bShowHealth )
+ {
+ _snwprintf( wszHealthText, ARRAYSIZE(wszHealthText) - 1, L"%.0f%%", ((float)pPlayer->GetHealth() / (float)pPlayer->GetMaxHealth() ) );
+ wszHealthText[ ARRAYSIZE(wszHealthText)-1 ] = '\0';
+ }
+ }
+
+ if ( printFormatString )
+ {
+ if ( bShowPlayerName && bShowHealth )
+ {
+ g_pVGuiLocalize->ConstructString( sIDString, sizeof(sIDString), g_pVGuiLocalize->Find(printFormatString), 2, wszPlayerName, wszHealthText );
+ }
+ else if ( bShowPlayerName )
+ {
+ g_pVGuiLocalize->ConstructString( sIDString, sizeof(sIDString), g_pVGuiLocalize->Find(printFormatString), 1, wszPlayerName );
+ }
+ else if ( bShowHealth )
+ {
+ g_pVGuiLocalize->ConstructString( sIDString, sizeof(sIDString), g_pVGuiLocalize->Find(printFormatString), 1, wszHealthText );
+ }
+ else
+ {
+ g_pVGuiLocalize->ConstructString( sIDString, sizeof(sIDString), g_pVGuiLocalize->Find(printFormatString), 0 );
+ }
+ }
+
+ if ( sIDString[0] )
+ {
+ int wide, tall;
+ int ypos = YRES(260);
+ int xpos = XRES(10);
+
+ vgui::surface()->GetTextSize( m_hFont, sIDString, wide, tall );
+
+ if( hud_centerid.GetInt() == 0 )
+ {
+ ypos = YRES(420);
+ }
+ else
+ {
+ xpos = (ScreenWidth() - wide) / 2;
+ }
+
+ vgui::surface()->DrawSetTextFont( m_hFont );
+ vgui::surface()->DrawSetTextPos( xpos, ypos );
+ vgui::surface()->DrawSetTextColor( c );
+ vgui::surface()->DrawPrintText( sIDString, wcslen(sIDString) );
+ }
+ }
+}
diff --git a/mp/src/game/client/hl2mp/hl2mp_hud_team.cpp b/mp/src/game/client/hl2mp/hl2mp_hud_team.cpp
new file mode 100644
index 00000000..85e19b7f
--- /dev/null
+++ b/mp/src/game/client/hl2mp/hl2mp_hud_team.cpp
@@ -0,0 +1,189 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: HUD Target ID element
+//
+// $NoKeywords: $
+//=============================================================================//
+#include "cbase.h"
+#include "hud.h"
+#include "hudelement.h"
+#include "c_hl2mp_player.h"
+#include "c_playerresource.h"
+#include "vgui_entitypanel.h"
+#include "iclientmode.h"
+#include "vgui/ILocalize.h"
+#include "hl2mp_gamerules.h"
+#include "c_team.h"
+#include <vgui_controls/AnimationController.h>
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Displays current ammunition level
+//-----------------------------------------------------------------------------
+class CTeamPlayHud : public vgui::Panel, public CHudElement
+{
+ DECLARE_CLASS_SIMPLE( CTeamPlayHud, vgui::Panel );
+
+public:
+ CTeamPlayHud( const char *pElementName );
+ void Reset();
+
+ virtual void PerformLayout();
+
+protected:
+ virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
+ virtual void OnThink();
+
+private:
+ vgui::HFont m_hFont;
+ Color m_bgColor;
+
+ vgui::Label *m_pWarmupLabel; // "Warmup Mode"
+
+ vgui::Label *m_pBackground; // black box
+
+ bool m_bSuitAuxPowerUsed;
+
+ CPanelAnimationVarAliasType( int, m_iTextX, "text_xpos", "8", "proportional_int" );
+ CPanelAnimationVarAliasType( int, m_iTextY, "text_ypos", "8", "proportional_int" );
+};
+
+DECLARE_HUDELEMENT( CTeamPlayHud );
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CTeamPlayHud::CTeamPlayHud( const char *pElementName ) : BaseClass(NULL, "TeamDisplay"), CHudElement( pElementName )
+{
+ vgui::Panel *pParent = g_pClientMode->GetViewport();
+ SetParent( pParent );
+ SetVisible( false );
+ SetAlpha( 255 );
+
+ m_pBackground = new vgui::Label( this, "Background", "" );
+
+ m_pWarmupLabel = new vgui::Label( this, "RoundState_warmup", "test label" /*g_pVGuiLocalize->Find( "#Clan_warmup_mode" )*/ );
+ m_pWarmupLabel->SetPaintBackgroundEnabled( false );
+ m_pWarmupLabel->SetPaintBorderEnabled( false );
+ m_pWarmupLabel->SizeToContents();
+ m_pWarmupLabel->SetContentAlignment( vgui::Label::a_west );
+ m_pWarmupLabel->SetFgColor( GetFgColor() );
+
+ m_bSuitAuxPowerUsed = false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTeamPlayHud::Reset()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTeamPlayHud::ApplySchemeSettings( vgui::IScheme *pScheme )
+{
+ BaseClass::ApplySchemeSettings( pScheme );
+
+ SetFgColor( Color(0,0,0,0) ); //GetSchemeColor("RoundStateFg", pScheme) );
+ m_hFont = pScheme->GetFont( "Default", true );
+
+ m_pBackground->SetBgColor( GetSchemeColor("BgColor", pScheme) );
+ m_pBackground->SetPaintBackgroundType( 2 );
+
+ SetAlpha( 255 );
+ SetBgColor( Color( 0, 0, 0, 0 ) );
+ SetPaintBackgroundType( 0 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Resizes the label
+//-----------------------------------------------------------------------------
+void CTeamPlayHud::PerformLayout()
+{
+
+ BaseClass::PerformLayout();
+
+ int wide, tall;
+ GetSize( wide, tall );
+
+ // find the widest line
+ int labelWide = m_pWarmupLabel->GetWide();
+
+ // find the total height
+ int fontTall = vgui::surface()->GetFontTall( m_hFont );
+ int labelTall = fontTall;
+
+ labelWide += m_iTextX*2;
+ labelTall += m_iTextY*2;
+
+ m_pBackground->SetBounds( 0, 0, labelWide, labelTall );
+
+ int xOffset = (labelWide - m_pWarmupLabel->GetWide())/2;
+ m_pWarmupLabel->SetPos( 0 + xOffset, 0 + m_iTextY );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Updates the label color each frame
+//-----------------------------------------------------------------------------
+void CTeamPlayHud::OnThink()
+{
+ SetVisible( false );
+
+ C_BaseHLPlayer *pLocalPlayer = (C_BaseHLPlayer *)C_BasePlayer::GetLocalPlayer();
+
+ if ( pLocalPlayer == NULL )
+ return;
+
+ if ( HL2MPRules()->IsTeamplay() == false )
+ return;
+
+ if ( pLocalPlayer->IsAlive() == false )
+ return;
+
+ if ( pLocalPlayer->m_HL2Local.m_flSuitPower < 100 )
+ {
+ if ( m_bSuitAuxPowerUsed == false )
+ {
+ g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("FadeOutTeamLine");
+ m_bSuitAuxPowerUsed = true;
+ }
+ }
+ else
+ {
+ if ( m_bSuitAuxPowerUsed == true )
+ {
+ g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("FadeInTeamLine");
+ m_bSuitAuxPowerUsed = false;
+ }
+ }
+
+ int iTeamNumber = pLocalPlayer->GetTeamNumber();
+ Color c = GameResources()->GetTeamColor( iTeamNumber );
+
+ wchar_t string1[1024];
+ C_Team *pTeam = GetGlobalTeam( iTeamNumber );
+
+ if ( pTeam )
+ {
+ wchar_t TeamName[64];
+ g_pVGuiLocalize->ConvertANSIToUnicode( pTeam->Get_Name(), TeamName, sizeof(TeamName) );
+
+ g_pVGuiLocalize->ConstructString( string1, sizeof(string1), g_pVGuiLocalize->Find("#Team"), 1, TeamName );
+
+ m_pBackground->SetFgColor( GetFgColor() );
+ m_pWarmupLabel->SetFgColor(c);
+
+ m_pWarmupLabel->SetText( string1 );
+ m_pWarmupLabel->SetVisible( true );
+
+ m_pWarmupLabel->SizeToContents();
+
+ SetVisible( true );
+ }
+
+ InvalidateLayout();
+}
diff --git a/mp/src/game/client/hl2mp/hud_deathnotice.cpp b/mp/src/game/client/hl2mp/hud_deathnotice.cpp
new file mode 100644
index 00000000..a4808a81
--- /dev/null
+++ b/mp/src/game/client/hl2mp/hud_deathnotice.cpp
@@ -0,0 +1,352 @@
+//========= 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 <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" );
+
+ // 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 = GetClientModeHL2MPNormal()->GetDeathMessageStartHeight();
+
+ surface()->DrawSetTextFont( m_hTextFont );
+ surface()->DrawSetTextColor( GameResources()->GetTeamColor( 0 ) );
+
+
+ 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 = GetWide() - 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", sDeathMsg );
+}
+
+
+
diff --git a/mp/src/game/client/hl2mp/ui/backgroundpanel.cpp b/mp/src/game/client/hl2mp/ui/backgroundpanel.cpp
new file mode 100644
index 00000000..b54edffd
--- /dev/null
+++ b/mp/src/game/client/hl2mp/ui/backgroundpanel.cpp
@@ -0,0 +1,431 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "backgroundpanel.h"
+
+#include <vgui/IVGui.h>
+#include <vgui/IScheme.h>
+#include <vgui/ISurface.h>
+#include <vgui_controls/Label.h>
+#include <vgui/ILocalize.h>
+#include "vgui_controls/BuildGroup.h"
+#include "vgui_controls/BitmapImagePanel.h"
+
+using namespace vgui;
+
+#define DEBUG_WINDOW_RESIZING 0
+#define DEBUG_WINDOW_REPOSITIONING 0
+
+class CaptionLabel : public Label
+{
+public:
+ CaptionLabel(Panel *parent, const char *panelName, const char *text) : Label(parent, panelName, text)
+ {
+ }
+
+ virtual void ApplySchemeSettings( vgui::IScheme *pScheme )
+ {
+ Label::ApplySchemeSettings( pScheme );
+ SetFont( pScheme->GetFont( "MenuTitle", IsProportional() ) );
+ }
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: transform a normalized value into one that is scaled based the minimum
+// of the horizontal and vertical ratios
+//-----------------------------------------------------------------------------
+static int GetAlternateProportionalValueFromNormal(int normalizedValue)
+{
+ int wide, tall;
+ GetHudSize( wide, tall );
+ int proH, proW;
+ surface()->GetProportionalBase( proW, proH );
+ double scaleH = (double)tall / (double)proH;
+ double scaleW = (double)wide / (double)proW;
+ double scale = (scaleW < scaleH) ? scaleW : scaleH;
+
+ return (int)( normalizedValue * scale );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: transform a standard scaled value into one that is scaled based the minimum
+// of the horizontal and vertical ratios
+//-----------------------------------------------------------------------------
+int GetAlternateProportionalValueFromScaled( HScheme hScheme, int scaledValue)
+{
+ return GetAlternateProportionalValueFromNormal( scheme()->GetProportionalNormalizedValueEx( hScheme, scaledValue ) );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: moves and resizes a single control
+//-----------------------------------------------------------------------------
+static void RepositionControl( Panel *pPanel )
+{
+ int x, y, w, h;
+ pPanel->GetBounds(x, y, w, h);
+
+#if DEBUG_WINDOW_RESIZING
+ int x1, y1, w1, h1;
+ pPanel->GetBounds(x1, y1, w1, h1);
+ int x2, y2, w2, h2;
+ x2 = scheme()->GetProportionalNormalizedValueEx( pPanel->GetScheme(), x1 );
+ y2 = scheme()->GetProportionalNormalizedValueEx( pPanel->GetScheme(), y1 );
+ w2 = scheme()->GetProportionalNormalizedValueEx( pPanel->GetScheme(), w1 );
+ h2 = scheme()->GetProportionalNormalizedValueEx( pPanel->GetScheme(), h1 );
+#endif
+
+ x = GetAlternateProportionalValueFromScaled(pPanel->GetScheme(),x);
+ y = GetAlternateProportionalValueFromScaled(pPanel->GetScheme(),y);
+ w = GetAlternateProportionalValueFromScaled(pPanel->GetScheme(),w);
+ h = GetAlternateProportionalValueFromScaled(pPanel->GetScheme(),h);
+
+ pPanel->SetBounds(x, y, w, h);
+
+#if DEBUG_WINDOW_RESIZING
+ DevMsg( "Resizing '%s' from (%d,%d) %dx%d to (%d,%d) %dx%d -- initially was (%d,%d) %dx%d\n",
+ pPanel->GetName(), x1, y1, w1, h1, x, y, w, h, x2, y2, w2, h2 );
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Sets colors etc for background image panels
+//-----------------------------------------------------------------------------
+void ApplyBackgroundSchemeSettings( EditablePanel *pWindow, vgui::IScheme *pScheme )
+{
+ Color bgColor = Color( 255, 255, 255, pScheme->GetColor( "BgColor", Color( 0, 0, 0, 0 ) )[3] );
+ Color fgColor = pScheme->GetColor( "FgColor", Color( 0, 0, 0, 0 ) );
+
+ if ( !pWindow )
+ return;
+
+ CBitmapImagePanel *pBitmapPanel;
+
+ // corners --------------------------------------------
+ pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "TopLeftPanel" ));
+ if ( pBitmapPanel )
+ {
+ pBitmapPanel->setImageColor( bgColor );
+ }
+ pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "TopRightPanel" ));
+ if ( pBitmapPanel )
+ {
+ pBitmapPanel->setImageColor( bgColor );
+ }
+ pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "BottomLeftPanel" ));
+ if ( pBitmapPanel )
+ {
+ pBitmapPanel->setImageColor( bgColor );
+ }
+ pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "BottomRightPanel" ));
+ if ( pBitmapPanel )
+ {
+ pBitmapPanel->setImageColor( bgColor );
+ }
+
+ // background -----------------------------------------
+ pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "TopSolid" ));
+ if ( pBitmapPanel )
+ {
+ pBitmapPanel->setImageColor( bgColor );
+ }
+ pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "UpperMiddleSolid" ));
+ if ( pBitmapPanel )
+ {
+ pBitmapPanel->setImageColor( bgColor );
+ }
+ pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "LowerMiddleSolid" ));
+ if ( pBitmapPanel )
+ {
+ pBitmapPanel->setImageColor( bgColor );
+ }
+ pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "BottomSolid" ));
+ if ( pBitmapPanel )
+ {
+ pBitmapPanel->setImageColor( bgColor );
+ }
+
+ // Logo -----------------------------------------------
+ pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "ExclamationPanel" ));
+ if ( pBitmapPanel )
+ {
+ pBitmapPanel->setImageColor( fgColor );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Re-aligns background image panels so they are touching.
+//-----------------------------------------------------------------------------
+static void FixupBackgroundPanels( EditablePanel *pWindow, int offsetX, int offsetY )
+{
+ if ( !pWindow )
+ return;
+
+ int screenWide, screenTall;
+ pWindow->GetSize( screenWide, screenTall );
+
+ int inset = GetAlternateProportionalValueFromNormal( 20 );
+ int cornerSize = GetAlternateProportionalValueFromNormal( 10 );
+
+ int titleHeight = GetAlternateProportionalValueFromNormal( 42 );
+ int mainHeight = GetAlternateProportionalValueFromNormal( 376 );
+
+ int logoSize = titleHeight;
+
+ int captionInset = GetAlternateProportionalValueFromNormal( 76 );
+
+ Panel *pPanel;
+
+ // corners --------------------------------------------
+ pPanel = pWindow->FindChildByName( "TopLeftPanel" );
+ if ( pPanel )
+ {
+ pPanel->SetZPos( -20 );
+ pPanel->SetBounds( offsetX + inset, offsetY + inset, cornerSize, cornerSize );
+ }
+
+ pPanel = pWindow->FindChildByName( "TopRightPanel" );
+ if ( pPanel )
+ {
+ pPanel->SetZPos( -20 );
+ pPanel->SetBounds( screenWide - offsetX - inset - cornerSize, offsetY + inset, cornerSize, cornerSize );
+ }
+
+ pPanel = pWindow->FindChildByName( "BottomLeftPanel" );
+ if ( pPanel )
+ {
+ pPanel->SetZPos( -20 );
+ pPanel->SetBounds( offsetX + inset, screenTall - offsetY - inset - cornerSize, cornerSize, cornerSize );
+ }
+
+ pPanel = pWindow->FindChildByName( "BottomRightPanel" );
+ if ( pPanel )
+ {
+ pPanel->SetZPos( -20 );
+ pPanel->SetBounds( screenWide - offsetX - inset - cornerSize, screenTall - offsetY - inset - cornerSize, cornerSize, cornerSize );
+ }
+
+ // background -----------------------------------------
+ pPanel = pWindow->FindChildByName( "TopSolid" );
+ if ( pPanel )
+ {
+ pPanel->SetZPos( -20 );
+ pPanel->SetBounds( offsetX + inset + cornerSize, offsetY + inset, screenWide - 2*offsetX - 2*inset - 2*cornerSize, cornerSize );
+ }
+
+ pPanel = pWindow->FindChildByName( "UpperMiddleSolid" );
+ if ( pPanel )
+ {
+ pPanel->SetZPos( -20 );
+ pPanel->SetBounds( offsetX + inset, offsetY + inset + cornerSize, screenWide - 2*offsetX - 2*inset, titleHeight );
+ }
+
+ pPanel = pWindow->FindChildByName( "LowerMiddleSolid" );
+ if ( pPanel )
+ {
+ pPanel->SetZPos( -20 );
+ pPanel->SetBounds( offsetX + inset + cornerSize, screenTall - offsetY - inset - cornerSize, screenWide - 2*offsetX - 2*inset - 2*cornerSize, cornerSize );
+ }
+
+ pPanel = pWindow->FindChildByName( "BottomSolid" );
+ if ( pPanel )
+ {
+ pPanel->SetZPos( -20 );
+ pPanel->SetBounds( offsetX + inset, screenTall - offsetY - inset - cornerSize - mainHeight, screenWide - 2*offsetX - 2*inset, mainHeight );
+ }
+
+ // transparent border ---------------------------------
+ pPanel = pWindow->FindChildByName( "TopClear" );
+ if ( pPanel )
+ {
+ pPanel->SetZPos( -20 );
+ pPanel->SetBounds( 0, 0, screenWide, offsetY + inset );
+ }
+
+ pPanel = pWindow->FindChildByName( "BottomClear" );
+ if ( pPanel )
+ {
+ pPanel->SetZPos( -20 );
+ pPanel->SetBounds( 0, screenTall - offsetY - inset, screenWide, offsetY + inset );
+ }
+
+ pPanel = pWindow->FindChildByName( "LeftClear" );
+ if ( pPanel )
+ {
+ pPanel->SetZPos( -20 );
+ pPanel->SetBounds( 0, offsetY + inset, offsetX + inset, screenTall - 2*offsetY - 2*inset );
+ }
+
+ pPanel = pWindow->FindChildByName( "RightClear" );
+ if ( pPanel )
+ {
+ pPanel->SetZPos( -20 );
+ pPanel->SetBounds( screenWide - offsetX - inset, offsetY + inset, offsetX + inset, screenTall - 2*offsetY - 2*inset );
+ }
+
+ // Logo -----------------------------------------------
+ int logoInset = (cornerSize + titleHeight - logoSize)/2;
+ pPanel = pWindow->FindChildByName( "ExclamationPanel" );
+ if ( pPanel )
+ {
+ pPanel->SetZPos( -19 ); // higher than the background
+ pPanel->SetBounds( offsetX + inset + logoInset, offsetY + inset + logoInset, logoSize, logoSize );
+ }
+
+ // Title caption --------------------------------------
+ pPanel = dynamic_cast< Label * >(pWindow->FindChildByName( "CaptionLabel" ));
+ if ( pPanel )
+ {
+ pPanel->SetZPos( -19 ); // higher than the background
+ pPanel->SetBounds( offsetX + captionInset/*inset + 2*logoInset + logoSize*/, offsetY + inset + logoInset, screenWide, logoSize );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Creates background image panels
+//-----------------------------------------------------------------------------
+void CreateBackground( EditablePanel *pWindow )
+{
+ // corners --------------------------------------------
+ new CBitmapImagePanel( pWindow, "TopLeftPanel", "gfx/vgui/round_corner_nw" );
+ new CBitmapImagePanel( pWindow, "TopRightPanel", "gfx/vgui/round_corner_ne" );
+ new CBitmapImagePanel( pWindow, "BottomLeftPanel", "gfx/vgui/round_corner_sw" );
+ new CBitmapImagePanel( pWindow, "BottomRightPanel", "gfx/vgui/round_corner_se" );
+
+ // background -----------------------------------------
+ new CBitmapImagePanel( pWindow, "TopSolid", "gfx/vgui/solid_background" );
+ new CBitmapImagePanel( pWindow, "UpperMiddleSolid", "gfx/vgui/solid_background" );
+ new CBitmapImagePanel( pWindow, "LowerMiddleSolid", "gfx/vgui/solid_background" );
+ new CBitmapImagePanel( pWindow, "BottomSolid", "gfx/vgui/solid_background" );
+
+ // transparent border ---------------------------------
+ new CBitmapImagePanel( pWindow, "TopClear", "gfx/vgui/trans_background" );
+ new CBitmapImagePanel( pWindow, "BottomClear", "gfx/vgui/trans_background" );
+ new CBitmapImagePanel( pWindow, "LeftClear", "gfx/vgui/trans_background" );
+ new CBitmapImagePanel( pWindow, "RightClear", "gfx/vgui/trans_background" );
+
+ // Logo -----------------------------------------------
+ new CBitmapImagePanel( pWindow, "ExclamationPanel", "gfx/vgui/hl2mp_logo" );
+
+ // Title caption --------------------------------------
+ Panel *pPanel = dynamic_cast< Label * >(pWindow->FindChildByName( "CaptionLabel" ));
+ if ( !pPanel )
+ new CaptionLabel( pWindow, "CaptionLabel", "" );
+}
+
+void ResizeWindowControls( EditablePanel *pWindow, int tall, int wide, int offsetX, int offsetY )
+{
+ if (!pWindow || !pWindow->GetBuildGroup() || !pWindow->GetBuildGroup()->GetPanelList())
+ return;
+
+ CUtlVector<PHandle> *panelList = pWindow->GetBuildGroup()->GetPanelList();
+ CUtlVector<Panel *> resizedPanels;
+ CUtlVector<Panel *> movedPanels;
+
+ // Resize to account for 1.25 aspect ratio (1280x1024) screens
+ {
+ for ( int i = 0; i < panelList->Size(); ++i )
+ {
+ PHandle handle = (*panelList)[i];
+
+ Panel *panel = handle.Get();
+
+ bool found = false;
+ for ( int j = 0; j < resizedPanels.Size(); ++j )
+ {
+ if (panel == resizedPanels[j])
+ found = true;
+ }
+
+ if (!panel || found)
+ {
+ continue;
+ }
+
+ resizedPanels.AddToTail( panel ); // don't move a panel more than once
+
+ if ( panel != pWindow )
+ {
+ RepositionControl( panel );
+ }
+ }
+ }
+
+ // and now re-center them. Woohoo!
+ for ( int i = 0; i < panelList->Size(); ++i )
+ {
+ PHandle handle = (*panelList)[i];
+
+ Panel *panel = handle.Get();
+
+ bool found = false;
+ for ( int j = 0; j < movedPanels.Size(); ++j )
+ {
+ if (panel == movedPanels[j])
+ found = true;
+ }
+
+ if (!panel || found)
+ {
+ continue;
+ }
+
+ movedPanels.AddToTail( panel ); // don't move a panel more than once
+
+ if ( panel != pWindow )
+ {
+ int x, y;
+
+ panel->GetPos( x, y );
+ panel->SetPos( x + offsetX, y + offsetY );
+
+#if DEBUG_WINDOW_REPOSITIONING
+ DevMsg( "Repositioning '%s' from (%d,%d) to (%d,%d) -- a distance of (%d,%d)\n",
+ panel->GetName(), x, y, x + offsetX, y + offsetY, offsetX, offsetY );
+#endif
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Resizes windows to fit completely on-screen (for 1280x1024), and
+// centers them on the screen. Sub-controls are also resized and moved.
+//-----------------------------------------------------------------------------
+void LayoutBackgroundPanel( EditablePanel *pWindow )
+{
+ if ( !pWindow )
+ return;
+
+ int screenW, screenH;
+ GetHudSize( screenW, screenH );
+
+ int wide, tall;
+ pWindow->GetSize( wide, tall );
+
+ int offsetX = 0;
+ int offsetY = 0;
+
+ // Slide everything over to the center
+ pWindow->SetBounds( 0, 0, screenW, screenH );
+
+ if ( wide != screenW || tall != screenH )
+ {
+ wide = GetAlternateProportionalValueFromScaled(pWindow->GetScheme(), wide);
+ tall = GetAlternateProportionalValueFromScaled(pWindow->GetScheme(), tall);
+
+ offsetX = (screenW - wide)/2;
+ offsetY = (screenH - tall)/2;
+
+ ResizeWindowControls( pWindow, tall, wide, offsetX, offsetY );
+ }
+
+ // now that the panels are moved/resized, look for some bg panels, and re-align them
+ FixupBackgroundPanels( pWindow, offsetX, offsetY );
+}
+
+//-----------------------------------------------------------------------------
+
diff --git a/mp/src/game/client/hl2mp/ui/backgroundpanel.h b/mp/src/game/client/hl2mp/ui/backgroundpanel.h
new file mode 100644
index 00000000..2088c6b1
--- /dev/null
+++ b/mp/src/game/client/hl2mp/ui/backgroundpanel.h
@@ -0,0 +1,43 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef CSBACKGROUND_H
+#define CSBACKGROUND_H
+
+#include <vgui_controls/Frame.h>
+#include <vgui_controls/EditablePanel.h>
+
+//-----------------------------------------------------------------------------
+// Purpose: Creates background image panels
+//-----------------------------------------------------------------------------
+void CreateBackground( vgui::EditablePanel *pWindow );
+
+//-----------------------------------------------------------------------------
+// Purpose: Resizes windows to fit completely on-screen (for 1280x1024), and
+// centers them on the screen. Sub-controls are also resized and moved.
+//-----------------------------------------------------------------------------
+void LayoutBackgroundPanel( vgui::EditablePanel *pWindow );
+
+//-----------------------------------------------------------------------------
+// Purpose: Sets colors etc for background image panels
+//-----------------------------------------------------------------------------
+void ApplyBackgroundSchemeSettings( vgui::EditablePanel *pWindow, vgui::IScheme *pScheme );
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void ResizeWindowControls( vgui::EditablePanel *pWindow, int tall, int wide, int offsetX, int offsetY );
+
+//-----------------------------------------------------------------------------
+// Purpose: transform a standard scaled value into one that is scaled based the minimum
+// of the horizontal and vertical ratios
+//-----------------------------------------------------------------------------
+int GetAlternateProportionalValueFromScaled( vgui::HScheme hScheme, int scaledValue );
+
+//-----------------------------------------------------------------------------
+
+#endif // CSBACKGROUND_H
diff --git a/mp/src/game/client/hl2mp/ui/hl2mpclientscoreboard.cpp b/mp/src/game/client/hl2mp/ui/hl2mpclientscoreboard.cpp
new file mode 100644
index 00000000..f3407e84
--- /dev/null
+++ b/mp/src/game/client/hl2mp/ui/hl2mpclientscoreboard.cpp
@@ -0,0 +1,653 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "hud.h"
+#include "hl2mpclientscoreboard.h"
+#include "c_team.h"
+#include "c_playerresource.h"
+#include "c_hl2mp_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"
+
+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,
+ SCORESECTION_SPECTATOR = 4
+};
+
+const int NumSegments = 7;
+static int coord[NumSegments+1] = {
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 6,
+ 9,
+ 10
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: Konstructor
+//-----------------------------------------------------------------------------
+CHL2MPClientScoreBoardDialog::CHL2MPClientScoreBoardDialog(IViewPort *pViewPort):CClientScoreBoardDialog(pViewPort)
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Destructor
+//-----------------------------------------------------------------------------
+CHL2MPClientScoreBoardDialog::~CHL2MPClientScoreBoardDialog()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Paint background for rounded corners
+//-----------------------------------------------------------------------------
+void CHL2MPClientScoreBoardDialog::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 );
+
+ 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 CHL2MPClientScoreBoardDialog::PaintBorder()
+{
+ 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 CHL2MPClientScoreBoardDialog::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 CHL2MPClientScoreBoardDialog::InitScoreboardSections()
+{
+ m_pPlayerList->SetBgColor( Color(0, 0, 0, 0) );
+ m_pPlayerList->SetBorder(NULL);
+
+ // fill out the structure of the scoreboard
+ AddHeader();
+
+ if ( HL2MPRules()->IsTeamplay() )
+ {
+ // add the team sections
+ AddSection( TYPE_TEAM, TEAM_COMBINE );
+ AddSection( TYPE_TEAM, TEAM_REBELS );
+ }
+ else
+ {
+ AddSection( TYPE_TEAM, TEAM_UNASSIGNED );
+ }
+ AddSection( TYPE_TEAM, TEAM_SPECTATOR );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: resets the scoreboard team info
+//-----------------------------------------------------------------------------
+void CHL2MPClientScoreBoardDialog::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 ( HL2MPRules()->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_snwprintf(val, ARRAYSIZE(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_snwprintf(val, ARRAYSIZE(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 CHL2MPClientScoreBoardDialog::AddHeader()
+{
+ // add the top header
+ m_pPlayerList->AddSection(0, "");
+ m_pPlayerList->SetSectionAlwaysVisible(0);
+ HFont hFallbackFont = scheme()->GetIScheme( GetScheme() )->GetFont( "DefaultVerySmallFallBack", false );
+ m_pPlayerList->AddColumnToSection(0, "name", "", 0, scheme()->GetProportionalScaledValueEx( GetScheme(), CSTRIKE_NAME_WIDTH ), hFallbackFont );
+ m_pPlayerList->AddColumnToSection(0, "class", "", 0, scheme()->GetProportionalScaledValueEx( GetScheme(), CSTRIKE_CLASS_WIDTH ) );
+ m_pPlayerList->AddColumnToSection(0, "frags", "#PlayerScore", 0 | SectionedListPanel::COLUMN_RIGHT, scheme()->GetProportionalScaledValueEx( GetScheme(), CSTRIKE_SCORE_WIDTH ) );
+ m_pPlayerList->AddColumnToSection(0, "deaths", "#PlayerDeath", 0 | SectionedListPanel::COLUMN_RIGHT, scheme()->GetProportionalScaledValueEx( GetScheme(), CSTRIKE_DEATH_WIDTH ) );
+ m_pPlayerList->AddColumnToSection(0, "ping", "#PlayerPing", 0 | SectionedListPanel::COLUMN_RIGHT, scheme()->GetProportionalScaledValueEx( GetScheme(), CSTRIKE_PING_WIDTH ) );
+// m_pPlayerList->AddColumnToSection(0, "voice", "#PlayerVoice", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::HEADER_TEXT| SectionedListPanel::COLUMN_CENTER, scheme()->GetProportionalScaledValueEx( GetScheme(), CSTRIKE_VOICE_WIDTH ) );
+// m_pPlayerList->AddColumnToSection(0, "tracker", "#PlayerTracker", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::HEADER_TEXT, scheme()->GetProportionalScaledValueEx( GetScheme(), CSTRIKE_FRIENDS_WIDTH ) );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Adds a new section to the scoreboard (i.e the team header)
+//-----------------------------------------------------------------------------
+void CHL2MPClientScoreBoardDialog::AddSection(int teamType, int teamNumber)
+{
+ HFont hFallbackFont = scheme()->GetIScheme( GetScheme() )->GetFont( "DefaultVerySmallFallBack", false );
+
+ int sectionID = GetSectionFromTeamNumber( teamNumber );
+ if ( teamType == TYPE_TEAM )
+ {
+ m_pPlayerList->AddSection(sectionID, "", StaticPlayerSortFunc);
+
+ // setup the columns
+ m_pPlayerList->AddColumnToSection(sectionID, "name", "", 0, scheme()->GetProportionalScaledValueEx( GetScheme(), CSTRIKE_NAME_WIDTH ), hFallbackFont );
+ m_pPlayerList->AddColumnToSection(sectionID, "class", "" , 0, scheme()->GetProportionalScaledValueEx( GetScheme(), CSTRIKE_CLASS_WIDTH ) );
+ m_pPlayerList->AddColumnToSection(sectionID, "frags", "", SectionedListPanel::COLUMN_RIGHT, scheme()->GetProportionalScaledValueEx( GetScheme(), CSTRIKE_SCORE_WIDTH ) );
+ m_pPlayerList->AddColumnToSection(sectionID, "deaths", "", SectionedListPanel::COLUMN_RIGHT, scheme()->GetProportionalScaledValueEx( GetScheme(), CSTRIKE_DEATH_WIDTH ) );
+ m_pPlayerList->AddColumnToSection(sectionID, "ping", "", SectionedListPanel::COLUMN_RIGHT, scheme()->GetProportionalScaledValueEx( GetScheme(), 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()->GetProportionalScaledValueEx( GetScheme(), CSTRIKE_NAME_WIDTH ), hFallbackFont );
+ m_pPlayerList->AddColumnToSection(sectionID, "class", "" , 0, scheme()->GetProportionalScaledValueEx( GetScheme(), 100 ) );
+ }
+}
+
+int CHL2MPClientScoreBoardDialog::GetSectionFromTeamNumber( int teamNumber )
+{
+ switch ( teamNumber )
+ {
+ case TEAM_COMBINE:
+ return SCORESECTION_COMBINE;
+ case TEAM_REBELS:
+ return SCORESECTION_REBELS;
+ case TEAM_SPECTATOR:
+ return SCORESECTION_SPECTATOR;
+ default:
+ return SCORESECTION_FREEFORALL;
+ }
+ return SCORESECTION_FREEFORALL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Adds a new row to the scoreboard, from the playerinfo structure
+//-----------------------------------------------------------------------------
+bool CHL2MPClientScoreBoardDialog::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 CHL2MPClientScoreBoardDialog::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);
+ }
+
+
+}
diff --git a/mp/src/game/client/hl2mp/ui/hl2mpclientscoreboard.h b/mp/src/game/client/hl2mp/ui/hl2mpclientscoreboard.h
new file mode 100644
index 00000000..3a97b32f
--- /dev/null
+++ b/mp/src/game/client/hl2mp/ui/hl2mpclientscoreboard.h
@@ -0,0 +1,63 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef CHL2MPCLIENTSCOREBOARDDIALOG_H
+#define CHL2MPCLIENTSCOREBOARDDIALOG_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include <clientscoreboarddialog.h>
+
+//-----------------------------------------------------------------------------
+// Purpose: Game ScoreBoard
+//-----------------------------------------------------------------------------
+class CHL2MPClientScoreBoardDialog : public CClientScoreBoardDialog
+{
+private:
+ DECLARE_CLASS_SIMPLE(CHL2MPClientScoreBoardDialog, CClientScoreBoardDialog);
+
+public:
+ CHL2MPClientScoreBoardDialog(IViewPort *pViewPort);
+ ~CHL2MPClientScoreBoardDialog();
+
+
+protected:
+ // scoreboard overrides
+ virtual void InitScoreboardSections();
+ virtual void UpdateTeamInfo();
+ virtual bool GetPlayerScoreInfo(int playerIndex, KeyValues *outPlayerInfo);
+ virtual void UpdatePlayerInfo();
+
+ // 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 = 320,
+ 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 // CHL2MPCLIENTSCOREBOARDDIALOG_H
diff --git a/mp/src/game/client/hl2mp/ui/hl2mptextwindow.cpp b/mp/src/game/client/hl2mp/ui/hl2mptextwindow.cpp
new file mode 100644
index 00000000..6944e08e
--- /dev/null
+++ b/mp/src/game/client/hl2mp/ui/hl2mptextwindow.cpp
@@ -0,0 +1,174 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "hl2mptextwindow.h"
+#include "backgroundpanel.h"
+#include <cdll_client_int.h>
+
+#include <vgui/IScheme.h>
+#include <vgui/ILocalize.h>
+#include <vgui/ISurface.h>
+#include <filesystem.h>
+#include <KeyValues.h>
+#include <convar.h>
+#include <vgui_controls/ImageList.h>
+
+#include <vgui_controls/TextEntry.h>
+#include <vgui_controls/Button.h>
+#include <vgui_controls/BuildGroup.h>
+
+#include "IGameUIFuncs.h" // for key bindings
+#include <igameresources.h>
+extern IGameUIFuncs *gameuifuncs; // for key binding details
+
+#include <game/client/iviewport.h>
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+using namespace vgui;
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CHL2MPTextWindow::CHL2MPTextWindow(IViewPort *pViewPort) : CTextWindow( pViewPort )
+{
+ SetProportional( true );
+
+ m_iScoreBoardKey = BUTTON_CODE_INVALID; // this is looked up in Activate()
+
+ CreateBackground( this );
+ m_backgroundLayoutFinished = false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Destructor
+//-----------------------------------------------------------------------------
+CHL2MPTextWindow::~CHL2MPTextWindow()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHL2MPTextWindow::Update()
+{
+ BaseClass::Update();
+
+ m_pOK->RequestFocus();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHL2MPTextWindow::SetVisible(bool state)
+{
+ BaseClass::SetVisible(state);
+
+ if ( state )
+ {
+ m_pOK->RequestFocus();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: shows the text window
+//-----------------------------------------------------------------------------
+void CHL2MPTextWindow::ShowPanel(bool bShow)
+{
+ if ( bShow )
+ {
+ // get key binding if shown
+ if ( m_iScoreBoardKey == BUTTON_CODE_INVALID ) // you need to lookup the jump key AFTER the engine has loaded
+ {
+ m_iScoreBoardKey = gameuifuncs->GetButtonCodeForBind( "showscores" );
+ }
+ }
+
+ BaseClass::ShowPanel( bShow );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHL2MPTextWindow::OnKeyCodePressed(KeyCode code)
+{
+ if ( m_iScoreBoardKey != BUTTON_CODE_INVALID && m_iScoreBoardKey == code )
+ {
+ gViewPortInterface->ShowPanel( PANEL_SCOREBOARD, true );
+ gViewPortInterface->PostMessageToPanel( PANEL_SCOREBOARD, new KeyValues( "PollHideCode", "code", code ) );
+ }
+ else
+ {
+ BaseClass::OnKeyCodePressed( code );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: The CS background is painted by image panels, so we should do nothing
+//-----------------------------------------------------------------------------
+void CHL2MPTextWindow::PaintBackground()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Scale / center the window
+//-----------------------------------------------------------------------------
+void CHL2MPTextWindow::PerformLayout()
+{
+ BaseClass::PerformLayout();
+
+ // stretch the window to fullscreen
+ if ( !m_backgroundLayoutFinished )
+ LayoutBackgroundPanel( this );
+ m_backgroundLayoutFinished = true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHL2MPTextWindow::ApplySchemeSettings( vgui::IScheme *pScheme )
+{
+ BaseClass::ApplySchemeSettings( pScheme );
+ ApplyBackgroundSchemeSettings( this, pScheme );
+}
+
+CHL2MPSpectatorGUI::CHL2MPSpectatorGUI(IViewPort *pViewPort) : CSpectatorGUI(pViewPort)
+{
+}
+
+
+bool CHL2MPSpectatorGUI::NeedsUpdate( void )
+{
+ if ( !C_BasePlayer::GetLocalPlayer() )
+ return false;
+
+ if ( m_nLastSpecMode != C_BasePlayer::GetLocalPlayer()->GetObserverMode() )
+ return true;
+
+ if ( m_nLastSpecTarget != C_BasePlayer::GetLocalPlayer()->GetObserverTarget() )
+ return true;
+
+ return BaseClass::NeedsUpdate();
+}
+
+
+void CHL2MPSpectatorGUI::Update()
+{
+ BaseClass::Update();
+
+ C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
+
+ if( pLocalPlayer )
+ {
+ m_nLastSpecMode = pLocalPlayer->GetObserverMode();
+ m_nLastSpecTarget = pLocalPlayer->GetObserverTarget();
+ }
+}
+
+
diff --git a/mp/src/game/client/hl2mp/ui/hl2mptextwindow.h b/mp/src/game/client/hl2mp/ui/hl2mptextwindow.h
new file mode 100644
index 00000000..95d28564
--- /dev/null
+++ b/mp/src/game/client/hl2mp/ui/hl2mptextwindow.h
@@ -0,0 +1,67 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef CSTEXTWINDOW_H
+#define CSTEXTWINDOW_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "vguitextwindow.h"
+#include <spectatorgui.h>
+
+//-----------------------------------------------------------------------------
+// Purpose: displays the MOTD
+//-----------------------------------------------------------------------------
+
+class CHL2MPTextWindow : public CTextWindow
+{
+private:
+ DECLARE_CLASS_SIMPLE( CHL2MPTextWindow, CTextWindow );
+
+public:
+ CHL2MPTextWindow(IViewPort *pViewPort);
+ virtual ~CHL2MPTextWindow();
+
+ virtual void Update();
+ virtual void SetVisible(bool state);
+ virtual void ShowPanel( bool bShow );
+ virtual void OnKeyCodePressed(vgui::KeyCode code);
+
+protected:
+ ButtonCode_t m_iScoreBoardKey;
+
+ // Background panel -------------------------------------------------------
+
+public:
+ virtual void PaintBackground();
+ virtual void PerformLayout();
+ virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
+ bool m_backgroundLayoutFinished;
+
+ // End background panel ---------------------------------------------------
+};
+
+class CHL2MPSpectatorGUI : public CSpectatorGUI
+{
+private:
+ DECLARE_CLASS_SIMPLE( CHL2MPSpectatorGUI, CSpectatorGUI );
+
+public:
+ CHL2MPSpectatorGUI( IViewPort *pViewPort );
+
+ virtual void Update( void );
+ virtual bool NeedsUpdate( void );
+
+protected:
+ int m_nLastSpecMode;
+ CBaseEntity *m_nLastSpecTarget;
+};
+
+
+
+#endif // CSTEXTWINDOW_H