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