diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/client/hl2mp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/client/hl2mp')
| -rw-r--r-- | game/client/hl2mp/c_hl2mp_player.cpp | 985 | ||||
| -rw-r--r-- | game/client/hl2mp/c_hl2mp_player.h | 173 | ||||
| -rw-r--r-- | game/client/hl2mp/c_te_hl2mp_shotgun_shot.cpp | 160 | ||||
| -rw-r--r-- | game/client/hl2mp/clientmode_hl2mpnormal.cpp | 128 | ||||
| -rw-r--r-- | game/client/hl2mp/clientmode_hl2mpnormal.h | 47 | ||||
| -rw-r--r-- | game/client/hl2mp/hl2mp_hud_chat.cpp | 116 | ||||
| -rw-r--r-- | game/client/hl2mp/hl2mp_hud_chat.h | 65 | ||||
| -rw-r--r-- | game/client/hl2mp/hl2mp_hud_target_id.cpp | 222 | ||||
| -rw-r--r-- | game/client/hl2mp/hl2mp_hud_team.cpp | 189 | ||||
| -rw-r--r-- | game/client/hl2mp/hud_deathnotice.cpp | 352 | ||||
| -rw-r--r-- | game/client/hl2mp/ui/backgroundpanel.cpp | 431 | ||||
| -rw-r--r-- | game/client/hl2mp/ui/backgroundpanel.h | 43 | ||||
| -rw-r--r-- | game/client/hl2mp/ui/hl2mpclientscoreboard.cpp | 653 | ||||
| -rw-r--r-- | game/client/hl2mp/ui/hl2mpclientscoreboard.h | 63 | ||||
| -rw-r--r-- | game/client/hl2mp/ui/hl2mptextwindow.cpp | 174 | ||||
| -rw-r--r-- | game/client/hl2mp/ui/hl2mptextwindow.h | 67 |
16 files changed, 3868 insertions, 0 deletions
diff --git a/game/client/hl2mp/c_hl2mp_player.cpp b/game/client/hl2mp/c_hl2mp_player.cpp new file mode 100644 index 0000000..49e55e2 --- /dev/null +++ b/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/game/client/hl2mp/c_hl2mp_player.h b/game/client/hl2mp/c_hl2mp_player.h new file mode 100644 index 0000000..bac4197 --- /dev/null +++ b/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/game/client/hl2mp/c_te_hl2mp_shotgun_shot.cpp b/game/client/hl2mp/c_te_hl2mp_shotgun_shot.cpp new file mode 100644 index 0000000..4283c3b --- /dev/null +++ b/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/game/client/hl2mp/clientmode_hl2mpnormal.cpp b/game/client/hl2mp/clientmode_hl2mpnormal.cpp new file mode 100644 index 0000000..35bfd1c --- /dev/null +++ b/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/game/client/hl2mp/clientmode_hl2mpnormal.h b/game/client/hl2mp/clientmode_hl2mpnormal.h new file mode 100644 index 0000000..2b06a6f --- /dev/null +++ b/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/game/client/hl2mp/hl2mp_hud_chat.cpp b/game/client/hl2mp/hl2mp_hud_chat.cpp new file mode 100644 index 0000000..67f4714 --- /dev/null +++ b/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/game/client/hl2mp/hl2mp_hud_chat.h b/game/client/hl2mp/hl2mp_hud_chat.h new file mode 100644 index 0000000..5eb2157 --- /dev/null +++ b/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/game/client/hl2mp/hl2mp_hud_target_id.cpp b/game/client/hl2mp/hl2mp_hud_target_id.cpp new file mode 100644 index 0000000..dc7f164 --- /dev/null +++ b/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/game/client/hl2mp/hl2mp_hud_team.cpp b/game/client/hl2mp/hl2mp_hud_team.cpp new file mode 100644 index 0000000..c3f0c05 --- /dev/null +++ b/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/game/client/hl2mp/hud_deathnotice.cpp b/game/client/hl2mp/hud_deathnotice.cpp new file mode 100644 index 0000000..cbdaa02 --- /dev/null +++ b/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/game/client/hl2mp/ui/backgroundpanel.cpp b/game/client/hl2mp/ui/backgroundpanel.cpp new file mode 100644 index 0000000..da35a96 --- /dev/null +++ b/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/game/client/hl2mp/ui/backgroundpanel.h b/game/client/hl2mp/ui/backgroundpanel.h new file mode 100644 index 0000000..54cb2ca --- /dev/null +++ b/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/game/client/hl2mp/ui/hl2mpclientscoreboard.cpp b/game/client/hl2mp/ui/hl2mpclientscoreboard.cpp new file mode 100644 index 0000000..941c976 --- /dev/null +++ b/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/game/client/hl2mp/ui/hl2mpclientscoreboard.h b/game/client/hl2mp/ui/hl2mpclientscoreboard.h new file mode 100644 index 0000000..d933658 --- /dev/null +++ b/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/game/client/hl2mp/ui/hl2mptextwindow.cpp b/game/client/hl2mp/ui/hl2mptextwindow.cpp new file mode 100644 index 0000000..dcf5a07 --- /dev/null +++ b/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/game/client/hl2mp/ui/hl2mptextwindow.h b/game/client/hl2mp/ui/hl2mptextwindow.h new file mode 100644 index 0000000..55e378f --- /dev/null +++ b/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 |