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/sdk | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/client/sdk')
22 files changed, 3448 insertions, 0 deletions
diff --git a/game/client/sdk/c_sdk_env_sparkler.cpp b/game/client/sdk/c_sdk_env_sparkler.cpp new file mode 100644 index 0000000..7e4cb62 --- /dev/null +++ b/game/client/sdk/c_sdk_env_sparkler.cpp @@ -0,0 +1,194 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: A simple test entity for creating special effects +// +//============================================================================= + +#include "cbase.h" +#include "c_te_effect_dispatch.h" +#include "particles_simple.h" + +// Declare the sparkler entity for the client-side +class C_Sparkler : public C_BaseEntity +{ +public: + DECLARE_CLIENTCLASS(); + DECLARE_CLASS( C_Sparkler, C_BaseEntity ); + + virtual void OnDataChanged( DataUpdateType_t updateType ); // Called when data changes on the server + virtual void ClientThink( void ); // Client-side think function for the entity + +private: + bool m_bEmit; // Determines whether or not we should emit particles + float m_flScale; // Size of the effect + + CSmartPtr<CSimpleEmitter> m_hEmitter; // Particle emitter for this entity + PMaterialHandle m_hMaterial; // Material handle used for this entity's particles + TimedEvent m_tParticleTimer; // Timer used to control particle emission rate +}; + +// Declare the data-table for server/client communication +IMPLEMENT_CLIENTCLASS_DT( C_Sparkler, DT_Sparkler, CSparkler ) + RecvPropInt( RECVINFO( m_bEmit ) ), // Boolean state from the server + RecvPropFloat( RECVINFO( m_flScale ) ), +END_RECV_TABLE() + +//----------------------------------------------------------------------------- +// Purpose: Called when data changes on the server +//----------------------------------------------------------------------------- +void C_Sparkler::OnDataChanged( DataUpdateType_t updateType ) +{ + // NOTE: We MUST call the base classes' implementation of this function + BaseClass::OnDataChanged( updateType ); + + // Setup our entity's particle system on creation + if ( updateType == DATA_UPDATE_CREATED ) + { + // Creat the emitter + m_hEmitter = CSimpleEmitter::Create( "env_sparkler" ); + + // Obtain a reference handle to our particle's desired material + if ( m_hEmitter.IsValid() ) + { + m_hMaterial = m_hEmitter->GetPMaterial( "effects/yellowflare" ); + } + + // Spawn 128 particles per second + m_tParticleTimer.Init( 128 ); + + // Call our ClientThink() function once every client frame + SetNextClientThink( CLIENT_THINK_ALWAYS ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Client-side think function for the entity +//----------------------------------------------------------------------------- +void C_Sparkler::ClientThink( void ) +{ + // We must have a valid emitter + if ( m_hEmitter == NULL ) + return; + + // We must be allowed to emit particles by the server + if ( m_bEmit == false ) + return; + + SimpleParticle *pParticle; + + float curTime = gpGlobals->frametime; + + // Add as many particles as required this frame + while ( m_tParticleTimer.NextEvent( curTime ) ) + { + // Create the particle + pParticle = m_hEmitter->AddSimpleParticle( m_hMaterial, GetAbsOrigin() ); + + if ( pParticle == NULL ) + return; + + // Setup our size + pParticle->m_uchStartSize = (unsigned char) m_flScale; + pParticle->m_uchEndSize = 0; + + // Setup our roll + pParticle->m_flRoll = random->RandomFloat( 0, 2*M_PI ); + pParticle->m_flRollDelta = random->RandomFloat( -DEG2RAD( 180 ), DEG2RAD( 180 ) ); + + // Set our color + pParticle->m_uchColor[0] = 255; + pParticle->m_uchColor[1] = 255; + pParticle->m_uchColor[2] = 255; + + // Setup our alpha values + pParticle->m_uchStartAlpha = 255; + pParticle->m_uchEndAlpha = 255; + + // Obtain a random direction + Vector velocity = RandomVector( -1.0f, 1.0f ); + VectorNormalize( velocity ); + + // Obtain a random speed + float speed = random->RandomFloat( 4.0f, 8.0f ) * m_flScale; + + // Set our velocity + pParticle->m_vecVelocity = velocity * speed; + + // Die in a short range of time + pParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f ); + } +} + +// ============================================================================ +// +// Dispatch Effect version +// +// ============================================================================ + +//----------------------------------------------------------------------------- +// Purpose: Callback to create a sparkle effect on the client +// Input : &data - information about the effect +//----------------------------------------------------------------------------- +void SparkleCallback( const CEffectData &data ) +{ + // Create a simple particle emitter + CSmartPtr<CSimpleEmitter> pSparkleEmitter = CSimpleEmitter::Create( "Sparkle" ); + + if ( pSparkleEmitter == NULL ) + return; + + // Make local versions of our passed in data + Vector origin = data.m_vOrigin; + float scale = data.m_flScale; + + // Set our sort origin to make the system cull properly + pSparkleEmitter->SetSortOrigin( origin ); + + // Find the material handle we wish to use for these particles + PMaterialHandle hMaterial = pSparkleEmitter->GetPMaterial( "effects/yellowflare" ); + + SimpleParticle *pParticle; + + // Make a group of particles in the world + for ( int i = 0; i < 64; i++ ) + { + // Create a particle + pParticle = pSparkleEmitter->AddSimpleParticle( hMaterial, origin ); + + if ( pParticle == NULL ) + return; + + // Set our sizes + pParticle->m_uchStartSize = (unsigned char) scale; + pParticle->m_uchEndSize = 0; + + // Set our roll + pParticle->m_flRoll = random->RandomFloat( 0, 2*M_PI ); + pParticle->m_flRollDelta = random->RandomFloat( -DEG2RAD( 180 ), DEG2RAD( 180 ) ); + + // Set our color + pParticle->m_uchColor[0] = 255; // Red + pParticle->m_uchColor[1] = 255; // Green + pParticle->m_uchColor[2] = 255; // Blue + + // Set our alpha + pParticle->m_uchStartAlpha = 0; + pParticle->m_uchEndAlpha = 255; + + // Create a random vector + Vector velocity = RandomVector( -1.0f, 1.0f ); + VectorNormalize( velocity ); + + // Find a random speed for the particle + float speed = random->RandomFloat( 4.0f, 8.0f ) * scale; + + // Build and set the velocity of the particle + pParticle->m_vecVelocity = velocity * speed; + + // Declare our lifetime + pParticle->m_flDieTime = 1.0f; + } +} + +// This links our server-side call to a client-side function +DECLARE_CLIENT_EFFECT( "Sparkle", SparkleCallback ); diff --git a/game/client/sdk/c_sdk_player.cpp b/game/client/sdk/c_sdk_player.cpp new file mode 100644 index 0000000..414e4e7 --- /dev/null +++ b/game/client/sdk/c_sdk_player.cpp @@ -0,0 +1,407 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "cbase.h" +#include "c_sdk_player.h" +#include "weapon_sdkbase.h" +#include "c_basetempentity.h" + +#if defined( CSDKPlayer ) + #undef CSDKPlayer +#endif + + + + +// -------------------------------------------------------------------------------- // +// Player animation event. Sent to the client when a player fires, jumps, reloads, etc.. +// -------------------------------------------------------------------------------- // + +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_SDKPlayer *pPlayer = dynamic_cast< C_SDKPlayer* >( 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 ); + +BEGIN_RECV_TABLE_NOBASE( C_TEPlayerAnimEvent, DT_TEPlayerAnimEvent ) + RecvPropEHandle( RECVINFO( m_hPlayer ) ), + RecvPropInt( RECVINFO( m_iEvent ) ), + RecvPropInt( RECVINFO( m_nData ) ) +END_RECV_TABLE() + +BEGIN_RECV_TABLE_NOBASE( C_SDKPlayer, DT_SDKLocalPlayerExclusive ) + RecvPropInt( RECVINFO( m_iShotsFired ) ), +END_RECV_TABLE() + + +IMPLEMENT_CLIENTCLASS_DT( C_SDKPlayer, DT_SDKPlayer, CSDKPlayer ) + RecvPropDataTable( "sdklocaldata", 0, 0, &REFERENCE_RECV_TABLE(DT_SDKLocalPlayerExclusive) ), + RecvPropFloat( RECVINFO( m_angEyeAngles[0] ) ), + RecvPropFloat( RECVINFO( m_angEyeAngles[1] ) ), + RecvPropInt( RECVINFO( m_iThrowGrenadeCounter ) ), + RecvPropEHandle( RECVINFO( m_hRagdoll ) ), +END_RECV_TABLE() + +BEGIN_PREDICTION_DATA( C_SDKPlayer ) + DEFINE_PRED_FIELD( m_flCycle, FIELD_FLOAT, FTYPEDESC_OVERRIDE | FTYPEDESC_PRIVATE | FTYPEDESC_NOERRORCHECK ), + DEFINE_PRED_FIELD( m_iShotsFired, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), +END_PREDICTION_DATA() + +class C_SDKRagdoll : public C_BaseAnimatingOverlay +{ +public: + DECLARE_CLASS( C_SDKRagdoll, C_BaseAnimatingOverlay ); + DECLARE_CLIENTCLASS(); + + C_SDKRagdoll(); + ~C_SDKRagdoll(); + + virtual void OnDataChanged( DataUpdateType_t type ); + + int GetPlayerEntIndex() const; + IRagdoll* GetIRagdoll() const; + + void ImpactTrace( trace_t *pTrace, int iDamageType, const char *pCustomImpactName ); + +private: + + C_SDKRagdoll( const C_SDKRagdoll & ) {} + + void Interp_Copy( C_BaseAnimatingOverlay *pSourceEntity ); + + void CreateRagdoll(); + + +private: + + EHANDLE m_hPlayer; + CNetworkVector( m_vecRagdollVelocity ); + CNetworkVector( m_vecRagdollOrigin ); +}; + + +IMPLEMENT_CLIENTCLASS_DT_NOBASE( C_SDKRagdoll, DT_SDKRagdoll, CSDKRagdoll ) + 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_SDKRagdoll::C_SDKRagdoll() +{ +} + +C_SDKRagdoll::~C_SDKRagdoll() +{ + PhysCleanupFrictionSounds( this ); +} + +void C_SDKRagdoll::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]; + for ( int j=0; j < pSrc->m_Entries.Count(); j++ ) + { + VarMapEntry_t *pSrcEntry = &pSrc->m_Entries[j]; + if ( !Q_strcmp( pSrcEntry->watcher->GetDebugName(), + pDestEntry->watcher->GetDebugName() ) ) + { + pDestEntry->watcher->Copy( pSrcEntry->watcher ); + break; + } + } + } +} + +void C_SDKRagdoll::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_SDKRagdoll::CreateRagdoll() +{ + // 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_SDKPlayer *pPlayer = dynamic_cast< C_SDKPlayer* >( 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 = LookupSequence( "walk_lower" ); + 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_SDKRagdoll::OnDataChanged( DataUpdateType_t type ) +{ + BaseClass::OnDataChanged( type ); + + if ( type == DATA_UPDATE_CREATED ) + { + CreateRagdoll(); + } +} + +IRagdoll* C_SDKRagdoll::GetIRagdoll() const +{ + return m_pRagdoll; +} + +C_BaseAnimating * C_SDKPlayer::BecomeRagdollOnClient() +{ + // Let the C_CSRagdoll entity do this. + // m_builtRagdoll = true; + return NULL; +} + + +IRagdoll* C_SDKPlayer::GetRepresentativeRagdoll() const +{ + if ( m_hRagdoll.Get() ) + { + C_SDKRagdoll *pRagdoll = (C_SDKRagdoll*)m_hRagdoll.Get(); + + return pRagdoll->GetIRagdoll(); + } + else + { + return NULL; + } +} + + + +C_SDKPlayer::C_SDKPlayer() : + m_iv_angEyeAngles( "C_SDKPlayer::m_iv_angEyeAngles" ) +{ + m_PlayerAnimState = CreatePlayerAnimState( this, this, LEGANIM_9WAY, true ); + + m_angEyeAngles.Init(); + AddVar( &m_angEyeAngles, &m_iv_angEyeAngles, LATCH_SIMULATION_VAR ); +} + + +C_SDKPlayer::~C_SDKPlayer() +{ + m_PlayerAnimState->Release(); +} + + +C_SDKPlayer* C_SDKPlayer::GetLocalSDKPlayer() +{ + return ToSDKPlayer( C_BasePlayer::GetLocalPlayer() ); +} + + +const QAngle& C_SDKPlayer::GetRenderAngles() +{ + if ( IsRagdoll() ) + { + return vec3_angle; + } + else + { + return m_PlayerAnimState->GetRenderAngles(); + } +} + + +void C_SDKPlayer::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_SDKPlayer::GetLocalSDKPlayer() ) + m_PlayerAnimState->Update( EyeAngles()[YAW], m_angEyeAngles[PITCH] ); + else + m_PlayerAnimState->Update( m_angEyeAngles[YAW], m_angEyeAngles[PITCH] ); + + BaseClass::UpdateClientSideAnimation(); +} + + +void C_SDKPlayer::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_SDKPlayer::OnDataChanged( DataUpdateType_t type ) +{ + BaseClass::OnDataChanged( type ); + + if ( type == DATA_UPDATE_CREATED ) + { + SetNextClientThink( CLIENT_THINK_ALWAYS ); + } + + UpdateVisibility(); +} + + +void C_SDKPlayer::DoAnimationEvent( PlayerAnimEvent_t event, int nData ) +{ + if ( event == PLAYERANIMEVENT_THROW_GRENADE ) + { + // Let the server handle this event. It will update m_iThrowGrenadeCounter and the client will + // pick up the event in CCSPlayerAnimState. + } + else + { + m_PlayerAnimState->DoAnimationEvent( event, nData ); + } +} + +bool C_SDKPlayer::ShouldDraw( void ) +{ + // If we're dead, our ragdoll will be drawn for us instead. + if ( !IsAlive() ) + return false; + + if( GetTeamNumber() == TEAM_SPECTATOR ) + return false; + + if( IsLocalPlayer() && IsRagdoll() ) + return true; + + return BaseClass::ShouldDraw(); +} + +CWeaponSDKBase* C_SDKPlayer::GetActiveSDKWeapon() const +{ + return dynamic_cast< CWeaponSDKBase* >( GetActiveWeapon() ); +}
\ No newline at end of file diff --git a/game/client/sdk/c_sdk_player.h b/game/client/sdk/c_sdk_player.h new file mode 100644 index 0000000..e4986b9 --- /dev/null +++ b/game/client/sdk/c_sdk_player.h @@ -0,0 +1,87 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef C_SDK_PLAYER_H +#define C_SDK_PLAYER_H +#ifdef _WIN32 +#pragma once +#endif + + +#include "sdk_playeranimstate.h" +#include "c_baseplayer.h" +#include "sdk_shareddefs.h" +#include "baseparticleentity.h" + + +class C_SDKPlayer : public C_BasePlayer, public ISDKPlayerAnimStateHelpers +{ +public: + DECLARE_CLASS( C_SDKPlayer, C_BasePlayer ); + DECLARE_CLIENTCLASS(); + DECLARE_PREDICTABLE(); + DECLARE_INTERPOLATION(); + + C_SDKPlayer(); + ~C_SDKPlayer(); + + static C_SDKPlayer* GetLocalSDKPlayer(); + + virtual const QAngle& GetRenderAngles(); + virtual void UpdateClientSideAnimation(); + virtual void PostDataUpdate( DataUpdateType_t updateType ); + virtual void OnDataChanged( DataUpdateType_t updateType ); + + +// Called by shared code. +public: + + // ISDKPlayerAnimState overrides. + virtual CWeaponSDKBase* SDKAnim_GetActiveWeapon(); + virtual bool SDKAnim_CanMove(); + + void DoAnimationEvent( PlayerAnimEvent_t event, int nData = 0 ); + bool ShouldDraw(); + + ISDKPlayerAnimState *m_PlayerAnimState; + + QAngle m_angEyeAngles; + CInterpolatedVar< QAngle > m_iv_angEyeAngles; + + CNetworkVar( int, m_iThrowGrenadeCounter ); // used to trigger grenade throw animations. + CNetworkVar( int, m_iShotsFired ); // number of shots fired recently + + EHANDLE m_hRagdoll; + + CWeaponSDKBase *GetActiveSDKWeapon() const; + + C_BaseAnimating *BecomeRagdollOnClient(); + IRagdoll* C_SDKPlayer::GetRepresentativeRagdoll() const; + + void FireBullet( + Vector vecSrc, + const QAngle &shootAngles, + float vecSpread, + int iDamage, + int iBulletType, + CBaseEntity *pevAttacker, + bool bDoEffects, + float x, + float y ); + +private: + C_SDKPlayer( const C_SDKPlayer & ); +}; + + +inline C_SDKPlayer* ToSDKPlayer( CBaseEntity *pPlayer ) +{ + Assert( dynamic_cast< C_SDKPlayer* >( pPlayer ) != NULL ); + return static_cast< C_SDKPlayer* >( pPlayer ); +} + + +#endif // C_SDK_PLAYER_H diff --git a/game/client/sdk/c_sdk_team.cpp b/game/client/sdk/c_sdk_team.cpp new file mode 100644 index 0000000..47ab46a --- /dev/null +++ b/game/client/sdk/c_sdk_team.cpp @@ -0,0 +1,33 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Client side C_SDKTeam class +// +// $NoKeywords: $ +//=============================================================================// +#include "cbase.h" +#include "engine/IEngineSound.h" +#include "hud.h" +#include "recvproxy.h" +#include "c_sdk_team.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +IMPLEMENT_CLIENTCLASS_DT(C_SDKTeam, DT_SDKTeam, CSDKTeam) +END_RECV_TABLE() + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +C_SDKTeam::C_SDKTeam() +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +C_SDKTeam::~C_SDKTeam() +{ +} + diff --git a/game/client/sdk/c_sdk_team.h b/game/client/sdk/c_sdk_team.h new file mode 100644 index 0000000..4cd2702 --- /dev/null +++ b/game/client/sdk/c_sdk_team.h @@ -0,0 +1,36 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Client side CTFTeam class +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef C_SDK_TEAM_H +#define C_SDK_TEAM_H +#ifdef _WIN32 +#pragma once +#endif + +#include "c_team.h" +#include "shareddefs.h" + +class C_BaseEntity; +class C_BaseObject; +class CBaseTechnology; + +//----------------------------------------------------------------------------- +// Purpose: TF's Team manager +//----------------------------------------------------------------------------- +class C_SDKTeam : public C_Team +{ + DECLARE_CLASS( C_SDKTeam, C_Team ); + DECLARE_CLIENTCLASS(); + +public: + + C_SDKTeam(); + virtual ~C_SDKTeam(); +}; + + +#endif // C_SDK_TEAM_H diff --git a/game/client/sdk/c_te_firebullets.cpp b/game/client/sdk/c_te_firebullets.cpp new file mode 100644 index 0000000..846be23 --- /dev/null +++ b/game/client/sdk/c_te_firebullets.cpp @@ -0,0 +1,62 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "cbase.h" +#include "sdk_fx_shared.h" +#include "c_sdk_player.h" +#include "c_basetempentity.h" +#include <cliententitylist.h> + + +class C_TEFireBullets : public C_BaseTempEntity +{ +public: + DECLARE_CLASS( C_TEFireBullets, C_BaseTempEntity ); + DECLARE_CLIENTCLASS(); + + virtual void PostDataUpdate( DataUpdateType_t updateType ); + +public: + int m_iPlayer; + Vector m_vecOrigin; + QAngle m_vecAngles; + int m_iWeaponID; + int m_iMode; + int m_iSeed; + float m_flSpread; +}; + + +void C_TEFireBullets::PostDataUpdate( DataUpdateType_t updateType ) +{ + // Create the effect. + + m_vecAngles.z = 0; + + FX_FireBullets( + m_iPlayer+1, + m_vecOrigin, + m_vecAngles, + m_iWeaponID, + m_iMode, + m_iSeed, + m_flSpread ); +} + + +IMPLEMENT_CLIENTCLASS_EVENT( C_TEFireBullets, DT_TEFireBullets, CTEFireBullets ); + + +BEGIN_RECV_TABLE_NOBASE(C_TEFireBullets, DT_TEFireBullets) + RecvPropVector( RECVINFO( m_vecOrigin ) ), + RecvPropFloat( RECVINFO( m_vecAngles[0] ) ), + RecvPropFloat( RECVINFO( m_vecAngles[1] ) ), + RecvPropInt( RECVINFO( m_iWeaponID ) ), + RecvPropInt( RECVINFO( m_iMode ) ), + RecvPropInt( RECVINFO( m_iSeed ) ), + RecvPropInt( RECVINFO( m_iPlayer ) ), + RecvPropFloat( RECVINFO( m_flSpread ) ), +END_RECV_TABLE()
\ No newline at end of file diff --git a/game/client/sdk/clientmode_sdk.cpp b/game/client/sdk/clientmode_sdk.cpp new file mode 100644 index 0000000..284d609 --- /dev/null +++ b/game/client/sdk/clientmode_sdk.cpp @@ -0,0 +1,131 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// +#include "cbase.h" +#include "hud.h" +#include "clientmode_sdk.h" +#include "cdll_client_int.h" +#include "iinput.h" +#include "vgui/ISurface.h" +#include "vgui/IPanel.h" +#include <vgui_controls/AnimationController.h> +#include "ivmodemanager.h" +#include "buymenu.h" +#include "filesystem.h" +#include "vgui/IVGui.h" +#include "hud_chat.h" +#include "view_shared.h" +#include "view.h" +#include "ivrenderview.h" +#include "model_types.h" +#include "iefx.h" +#include "dlight.h" +#include <imapoverview.h> +#include "c_playerresource.h" +#include <KeyValues.h> +#include "text_message.h" +#include "panelmetaclassmgr.h" + + +ConVar default_fov( "default_fov", "90", FCVAR_CHEAT ); + +IClientMode *g_pClientMode = NULL; + + +// --------------------------------------------------------------------------------- // +// CSDKModeManager. +// --------------------------------------------------------------------------------- // + +class CSDKModeManager : public IVModeManager +{ +public: + virtual void Init(); + virtual void SwitchMode( bool commander, bool force ) {} + virtual void LevelInit( const char *newmap ); + virtual void LevelShutdown( void ); + virtual void ActivateMouse( bool isactive ) {} +}; + +static CSDKModeManager g_ModeManager; +IVModeManager *modemanager = ( IVModeManager * )&g_ModeManager; + +// --------------------------------------------------------------------------------- // +// CSDKModeManager implementation. +// --------------------------------------------------------------------------------- // + +#define SCREEN_FILE "scripts/vgui_screens.txt" + +void CSDKModeManager::Init() +{ + g_pClientMode = GetClientModeNormal(); + + PanelMetaClassMgr()->LoadMetaClassDefinitionFile( SCREEN_FILE ); +} + +void CSDKModeManager::LevelInit( const char *newmap ) +{ + g_pClientMode->LevelInit( newmap ); +} + +void CSDKModeManager::LevelShutdown( void ) +{ + g_pClientMode->LevelShutdown(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +ClientModeSDKNormal::ClientModeSDKNormal() +{ +} + +//----------------------------------------------------------------------------- +// Purpose: If you don't know what a destructor is by now, you are probably going to get fired +//----------------------------------------------------------------------------- +ClientModeSDKNormal::~ClientModeSDKNormal() +{ +} + + +void ClientModeSDKNormal::InitViewport() +{ + m_pViewport = new SDKViewport(); + m_pViewport->Start( gameuifuncs, gameeventmanager ); +} + +ClientModeSDKNormal g_ClientModeNormal; + +IClientMode *GetClientModeNormal() +{ + return &g_ClientModeNormal; +} + + +ClientModeSDKNormal* GetClientModeSDKNormal() +{ + Assert( dynamic_cast< ClientModeSDKNormal* >( GetClientModeNormal() ) ); + + return static_cast< ClientModeSDKNormal* >( GetClientModeNormal() ); +} + +float ClientModeSDKNormal::GetViewModelFOV( void ) +{ + return 74.0f; +} + +int ClientModeSDKNormal::GetDeathMessageStartHeight( void ) +{ + return m_pViewport->GetDeathMessageStartHeight(); +} + +void ClientModeSDKNormal::PostRenderVGui() +{ +} + + + + diff --git a/game/client/sdk/clientmode_sdk.h b/game/client/sdk/clientmode_sdk.h new file mode 100644 index 0000000..cbe11cc --- /dev/null +++ b/game/client/sdk/clientmode_sdk.h @@ -0,0 +1,48 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef SDK_CLIENTMODE_H +#define SDK_CLIENTMODE_H +#ifdef _WIN32 +#pragma once +#endif + +#include "clientmode_shared.h" +#include "sdkviewport.h" + +class ClientModeSDKNormal : public ClientModeShared +{ +DECLARE_CLASS( ClientModeSDKNormal, ClientModeShared ); + +private: + +// IClientMode overrides. +public: + + ClientModeSDKNormal(); + virtual ~ClientModeSDKNormal(); + + virtual void InitViewport(); + + virtual float GetViewModelFOV( void ); + + int GetDeathMessageStartHeight( void ); + + virtual void PostRenderVGui(); + + +private: + + // void UpdateSpectatorMode( void ); + +}; + + +extern IClientMode *GetClientModeNormal(); +extern ClientModeSDKNormal* GetClientModeSDKNormal(); + + +#endif // SDK_CLIENTMODE_H diff --git a/game/client/sdk/sdk_fx_impacts.cpp b/game/client/sdk/sdk_fx_impacts.cpp new file mode 100644 index 0000000..c1ae37f --- /dev/null +++ b/game/client/sdk/sdk_fx_impacts.cpp @@ -0,0 +1,44 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Game-specific impact effect hooks +// +//=============================================================================// +#include "cbase.h" +#include "fx_impact.h" +#include "engine/IEngineSound.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 ); + + //Play a ricochet sound some of the time + if( random->RandomInt(1,10) <= 3 && (iDamageType == DMG_BULLET) ) + { + CLocalPlayerFilter filter; + C_BaseEntity::EmitSound( filter, SOUND_FROM_WORLD, "Bounce.Shrapnel", &vecOrigin ); + } + } + + PlayImpactSound( pEntity, tr, vecOrigin, nSurfaceProp ); +} + +DECLARE_CLIENT_EFFECT( "Impact", ImpactCallback ); diff --git a/game/client/sdk/sdk_fx_weaponfx.cpp b/game/client/sdk/sdk_fx_weaponfx.cpp new file mode 100644 index 0000000..b0fe4f1 --- /dev/null +++ b/game/client/sdk/sdk_fx_weaponfx.cpp @@ -0,0 +1,40 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Game-specific impact effect hooks +// +//=============================================================================// +#include "cbase.h" +#include "fx_impact.h" +#include "tempent.h" +#include "c_te_effect_dispatch.h" +#include "c_te_legacytempents.h" + + +//----------------------------------------------------------------------------- +// Purpose: Handle weapon effect callbacks +//----------------------------------------------------------------------------- +void SDK_EjectBrass( int shell, const CEffectData &data ) +{ + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + + if( !pPlayer ) + return; + + tempents->CSEjectBrass( data.m_vOrigin, data.m_vAngles, data.m_fFlags, shell, pPlayer ); +} + +void SDK_FX_EjectBrass_9mm_Callback( const CEffectData &data ) +{ + SDK_EjectBrass( CS_SHELL_9MM, data ); +} + +void SDK_FX_EjectBrass_12Gauge_Callback( const CEffectData &data ) +{ + SDK_EjectBrass( CS_SHELL_12GAUGE, data ); +} + + + +DECLARE_CLIENT_EFFECT( "EjectBrass_9mm", SDK_FX_EjectBrass_9mm_Callback ); +DECLARE_CLIENT_EFFECT( "EjectBrass_12Gauge",SDK_FX_EjectBrass_12Gauge_Callback ); + diff --git a/game/client/sdk/sdk_hud_ammo.cpp b/game/client/sdk/sdk_hud_ammo.cpp new file mode 100644 index 0000000..a5dfb6a --- /dev/null +++ b/game/client/sdk/sdk_hud_ammo.cpp @@ -0,0 +1,426 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "cbase.h" +#include "hud.h" +#include "hudelement.h" +#include "hud_macros.h" +#include "hud_numericdisplay.h" +#include "iclientmode.h" +#include "iclientvehicle.h" +#include <vgui_controls/AnimationController.h> +#include <vgui/ILocalize.h> +#include "ihudlcd.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//----------------------------------------------------------------------------- +// Purpose: Displays current ammunition level +//----------------------------------------------------------------------------- +class CHudAmmo : public CHudNumericDisplay, public CHudElement +{ + DECLARE_CLASS_SIMPLE( CHudAmmo, CHudNumericDisplay ); + +public: + CHudAmmo( const char *pElementName ); + void Init( void ); + void VidInit( void ); + void Reset(); + + void SetAmmo(int ammo, bool playAnimation); + void SetAmmo2(int ammo2, bool playAnimation); + +protected: + virtual void OnThink(); + + void UpdateAmmoDisplays(); + void UpdatePlayerAmmo( C_BasePlayer *player ); + +private: + CHandle< C_BaseCombatWeapon > m_hCurrentActiveWeapon; + CHandle< C_BaseEntity > m_hCurrentVehicle; + int m_iAmmo; + int m_iAmmo2; +}; + +DECLARE_HUDELEMENT( CHudAmmo ); + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CHudAmmo::CHudAmmo( const char *pElementName ) : BaseClass(NULL, "HudAmmo"), CHudElement( pElementName ) +{ + SetHiddenBits( HIDEHUD_HEALTH | HIDEHUD_PLAYERDEAD | HIDEHUD_NEEDSUIT | HIDEHUD_WEAPONSELECTION ); + + hudlcd->SetGlobalStat( "(ammo_primary)", "0" ); + hudlcd->SetGlobalStat( "(ammo_secondary)", "0" ); + hudlcd->SetGlobalStat( "(weapon_print_name)", "" ); + hudlcd->SetGlobalStat( "(weapon_name)", "" ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHudAmmo::Init( void ) +{ + m_iAmmo = -1; + m_iAmmo2 = -1; + + wchar_t *tempString = g_pVGuiLocalize->Find("#Valve_Hud_AMMO"); + if (tempString) + { + SetLabelText(tempString); + } + else + { + SetLabelText(L"AMMO"); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHudAmmo::VidInit( void ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: Resets hud after save/restore +//----------------------------------------------------------------------------- +void CHudAmmo::Reset() +{ + BaseClass::Reset(); + + m_hCurrentActiveWeapon = NULL; + m_hCurrentVehicle = NULL; + m_iAmmo = 0; + m_iAmmo2 = 0; + + UpdateAmmoDisplays(); +} + +//----------------------------------------------------------------------------- +// Purpose: called every frame to get ammo info from the weapon +//----------------------------------------------------------------------------- +void CHudAmmo::UpdatePlayerAmmo( C_BasePlayer *player ) +{ + // Clear out the vehicle entity + m_hCurrentVehicle = NULL; + + C_BaseCombatWeapon *wpn = GetActiveWeapon(); + + hudlcd->SetGlobalStat( "(weapon_print_name)", wpn ? wpn->GetPrintName() : " " ); + hudlcd->SetGlobalStat( "(weapon_name)", wpn ? wpn->GetName() : " " ); + + if ( !wpn || !player || !wpn->UsesPrimaryAmmo() ) + { + hudlcd->SetGlobalStat( "(ammo_primary)", "n/a" ); + hudlcd->SetGlobalStat( "(ammo_secondary)", "n/a" ); + + SetPaintEnabled(false); + SetPaintBackgroundEnabled(false); + return; + } + + SetPaintEnabled(true); + SetPaintBackgroundEnabled(true); + + // get the ammo in our clip + int ammo1 = wpn->Clip1(); + int ammo2; + if (ammo1 < 0) + { + // we don't use clip ammo, just use the total ammo count + ammo1 = player->GetAmmoCount(wpn->GetPrimaryAmmoType()); + ammo2 = 0; + } + else + { + // we use clip ammo, so the second ammo is the total ammo + ammo2 = player->GetAmmoCount(wpn->GetPrimaryAmmoType()); + } + + hudlcd->SetGlobalStat( "(ammo_primary)", VarArgs( "%d", ammo1 ) ); + hudlcd->SetGlobalStat( "(ammo_secondary)", VarArgs( "%d", ammo2 ) ); + + if (wpn == m_hCurrentActiveWeapon) + { + // same weapon, just update counts + SetAmmo(ammo1, true); + SetAmmo2(ammo2, true); + } + else + { + // diferent weapon, change without triggering + SetAmmo(ammo1, false); + SetAmmo2(ammo2, false); + + // update whether or not we show the total ammo display + if (wpn->UsesClipsForAmmo1()) + { + SetShouldDisplaySecondaryValue(true); + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponUsesClips"); + } + else + { + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponDoesNotUseClips"); + SetShouldDisplaySecondaryValue(false); + } + + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponChanged"); + m_hCurrentActiveWeapon = wpn; + } +} + +/* +void CHudAmmo::UpdateVehicleAmmo( C_BasePlayer *player, IClientVehicle *pVehicle ) +{ + m_hCurrentActiveWeapon = NULL; + CBaseEntity *pVehicleEnt = pVehicle->GetVehicleEnt(); + + if ( !pVehicleEnt || pVehicle->GetPrimaryAmmoType() < 0 ) + { + SetPaintEnabled(false); + SetPaintBackgroundEnabled(false); + return; + } + + SetPaintEnabled(true); + SetPaintBackgroundEnabled(true); + + // get the ammo in our clip + int ammo1 = pVehicle->GetPrimaryAmmoClip(); + int ammo2; + if (ammo1 < 0) + { + // we don't use clip ammo, just use the total ammo count + ammo1 = pVehicle->GetPrimaryAmmoCount(); + ammo2 = 0; + } + else + { + // we use clip ammo, so the second ammo is the total ammo + ammo2 = pVehicle->GetPrimaryAmmoCount(); + } + + if (pVehicleEnt == m_hCurrentVehicle) + { + // same weapon, just update counts + SetAmmo(ammo1, true); + SetAmmo2(ammo2, true); + } + else + { + // diferent weapon, change without triggering + SetAmmo(ammo1, false); + SetAmmo2(ammo2, false); + + // update whether or not we show the total ammo display + if (pVehicle->PrimaryAmmoUsesClips()) + { + SetShouldDisplaySecondaryValue(true); + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponUsesClips"); + } + else + { + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponDoesNotUseClips"); + SetShouldDisplaySecondaryValue(false); + } + + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponChanged"); + m_hCurrentVehicle = pVehicleEnt; + } +} +*/ + +//----------------------------------------------------------------------------- +// Purpose: called every frame to get ammo info from the weapon +//----------------------------------------------------------------------------- +void CHudAmmo::OnThink() +{ + UpdateAmmoDisplays(); +} + +//----------------------------------------------------------------------------- +// Purpose: updates the ammo display counts +//----------------------------------------------------------------------------- +void CHudAmmo::UpdateAmmoDisplays() +{ + C_BasePlayer *player = C_BasePlayer::GetLocalPlayer(); + + UpdatePlayerAmmo( player ); +} + +//----------------------------------------------------------------------------- +// Purpose: Updates ammo display +//----------------------------------------------------------------------------- +void CHudAmmo::SetAmmo(int ammo, bool playAnimation) +{ + if (ammo != m_iAmmo) + { + if (ammo == 0) + { + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("AmmoEmpty"); + } + else if (ammo < m_iAmmo) + { + // ammo has decreased + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("AmmoDecreased"); + } + else + { + // ammunition has increased + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("AmmoIncreased"); + } + + m_iAmmo = ammo; + } + + SetDisplayValue(ammo); +} + +//----------------------------------------------------------------------------- +// Purpose: Updates 2nd ammo display +//----------------------------------------------------------------------------- +void CHudAmmo::SetAmmo2(int ammo2, bool playAnimation) +{ + if (ammo2 != m_iAmmo2) + { + if (ammo2 == 0) + { + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("Ammo2Empty"); + } + else if (ammo2 < m_iAmmo2) + { + // ammo has decreased + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("Ammo2Decreased"); + } + else + { + // ammunition has increased + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("Ammo2Increased"); + } + + m_iAmmo2 = ammo2; + } + + SetSecondaryValue(ammo2); +} + +//----------------------------------------------------------------------------- +// Purpose: Displays the secondary ammunition level +//----------------------------------------------------------------------------- +class CHudSecondaryAmmo : public CHudNumericDisplay, public CHudElement +{ + DECLARE_CLASS_SIMPLE( CHudSecondaryAmmo, CHudNumericDisplay ); + +public: + CHudSecondaryAmmo( const char *pElementName ) : BaseClass( NULL, "HudAmmoSecondary" ), CHudElement( pElementName ) + { + m_iAmmo = -1; + + SetHiddenBits( HIDEHUD_HEALTH | HIDEHUD_WEAPONSELECTION | HIDEHUD_PLAYERDEAD | HIDEHUD_NEEDSUIT ); + } + + void Init( void ) + { + } + + void VidInit( void ) + { + } + + void SetAmmo( int ammo ) + { + if (ammo != m_iAmmo) + { + if (ammo == 0) + { + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("AmmoSecondaryEmpty"); + } + else if (ammo < m_iAmmo) + { + // ammo has decreased + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("AmmoSecondaryDecreased"); + } + else + { + // ammunition has increased + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("AmmoSecondaryIncreased"); + } + + m_iAmmo = ammo; + } + SetDisplayValue( ammo ); + } + + void Reset() + { + // hud reset, update ammo state + BaseClass::Reset(); + m_iAmmo = 0; + m_hCurrentActiveWeapon = NULL; + SetAlpha( 0 ); + UpdateAmmoState(); + } + +protected: + virtual void OnThink() + { + // set whether or not the panel draws based on if we have a weapon that supports secondary ammo + C_BaseCombatWeapon *wpn = GetActiveWeapon(); + C_BasePlayer *player = C_BasePlayer::GetLocalPlayer(); + IClientVehicle *pVehicle = player ? player->GetVehicle() : NULL; + if (!wpn || !player || pVehicle) + { + m_hCurrentActiveWeapon = NULL; + SetPaintEnabled(false); + SetPaintBackgroundEnabled(false); + return; + } + else + { + SetPaintEnabled(true); + SetPaintBackgroundEnabled(true); + } + + UpdateAmmoState(); + } + + void UpdateAmmoState() + { + C_BaseCombatWeapon *wpn = GetActiveWeapon(); + C_BasePlayer *player = C_BasePlayer::GetLocalPlayer(); + + if (player && wpn && wpn->UsesSecondaryAmmo()) + { + SetAmmo(player->GetAmmoCount(wpn->GetSecondaryAmmoType())); + } + + if ( m_hCurrentActiveWeapon != wpn ) + { + if ( wpn->UsesSecondaryAmmo() ) + { + // we've changed to a weapon that uses secondary ammo + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponUsesSecondaryAmmo"); + } + else + { + // we've changed away from a weapon that uses secondary ammo + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponDoesNotUseSecondaryAmmo"); + } + m_hCurrentActiveWeapon = wpn; + } + } + +private: + CHandle< C_BaseCombatWeapon > m_hCurrentActiveWeapon; + int m_iAmmo; +}; + +DECLARE_HUDELEMENT( CHudSecondaryAmmo ); + diff --git a/game/client/sdk/sdk_hud_chat.cpp b/game/client/sdk/sdk_hud_chat.cpp new file mode 100644 index 0000000..bdeaf48 --- /dev/null +++ b/game/client/sdk/sdk_hud_chat.cpp @@ -0,0 +1,471 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "cbase.h" +#include "sdk_hud_chat.h" +//#include "c_sdk_player.h" +//#include "c_sdk_playerresource.h" +#include "hud_macros.h" +#include "text_message.h" +#include "vguicenterprint.h" +#include "vgui/ILocalize.h" +#include "ihudlcd.h" + +ConVar cl_showtextmsg( "cl_showtextmsg", "1", 0, "Enable/disable text messages printing on the screen." ); + +float g_ColorGreen[3] = { 153, 255, 153 }; +float g_ColorYellow[3] = { 255, 178.5, 0.0 }; + +float *GetClientColor( int clientIndex ) +{ + if ( clientIndex == 0 ) // console msg + { + return g_ColorGreen; + } + else + { + return g_ColorYellow; + } +} + +// converts all '\r' characters to '\n', so that the engine can deal with the properly +// returns a pointer to str +static char* ConvertCRtoNL( char *str ) +{ + for ( char *ch = str; *ch != 0; ch++ ) + if ( *ch == '\r' ) + *ch = '\n'; + return str; +} + +// converts all '\r' characters to '\n', so that the engine can deal with the properly +// returns a pointer to str +static wchar_t* ConvertCRtoNL( wchar_t *str ) +{ + for ( wchar_t *ch = str; *ch != 0; ch++ ) + if ( *ch == L'\r' ) + *ch = L'\n'; + return str; +} + +static void StripEndNewlineFromString( char *str ) +{ + int s = strlen( str ) - 1; + if ( s >= 0 ) + { + if ( str[s] == '\n' || str[s] == '\r' ) + str[s] = 0; + } +} + +static void StripEndNewlineFromString( wchar_t *str ) +{ + int s = wcslen( str ) - 1; + if ( s >= 0 ) + { + if ( str[s] == L'\n' || str[s] == L'\r' ) + str[s] = 0; + } +} + +DECLARE_HUDELEMENT( CHudChat ); + +DECLARE_HUD_MESSAGE( CHudChat, SayText ); +DECLARE_HUD_MESSAGE( CHudChat, TextMsg ); + + +//===================== +//CHudChatLine +//===================== + +void CHudChatLine::ApplySchemeSettings(vgui::IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + m_hFont = pScheme->GetFont( "ChatFont" ); + SetBorder( NULL ); + SetBgColor( Color( 0, 0, 0, 0 ) ); + SetFgColor( Color( 0, 0, 0, 0 ) ); + + SetFont( m_hFont ); +} + +void CHudChatLine::PerformFadeout( void ) +{ + // Flash + Extra bright when new + float curtime = gpGlobals->curtime; + + int lr = m_clrText[0]; + int lg = m_clrText[1]; + int lb = m_clrText[2]; + + //CSPort chat only fades out, no blinking. + if ( curtime <= m_flExpireTime && curtime > m_flExpireTime - CHATLINE_FADE_TIME ) + { + float frac = ( m_flExpireTime - curtime ) / CHATLINE_FADE_TIME; + + int alpha = frac * 255; + alpha = clamp( alpha, 0, 255 ); + + wchar_t wbuf[4096]; + + GetText(0, wbuf, sizeof(wbuf)); + + SetText( "" ); + + if ( m_iNameLength > 0 ) + { + wchar_t wText[4096]; + // draw the first x characters in the player color + wcsncpy( wText, wbuf, MIN( m_iNameLength + 1, MAX_PLAYER_NAME_LENGTH+32) ); + wText[ MIN( m_iNameLength, MAX_PLAYER_NAME_LENGTH+31) ] = 0; + + m_clrNameColor[3] = alpha; + + InsertColorChange( m_clrNameColor ); + InsertString( wText ); + + wcsncpy( wText, wbuf + ( m_iNameLength ), wcslen( wbuf + m_iNameLength ) ); + wText[ wcslen( wbuf + m_iNameLength ) ] = '\0'; + InsertColorChange( Color( g_ColorYellow[0], g_ColorYellow[1], g_ColorYellow[2], alpha ) ); + InsertString( wText ); + InvalidateLayout( true ); + } + else + { + InsertColorChange( Color( lr, lg, lb, alpha ) ); + InsertString( wbuf ); + } + } + + OnThink(); +} + + + +//===================== +//CHudChatInputLine +//===================== + +void CHudChatInputLine::ApplySchemeSettings(vgui::IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings(pScheme); + + vgui::HFont hFont = pScheme->GetFont( "ChatFont" ); + + m_pPrompt->SetFont( hFont ); + m_pInput->SetFont( hFont ); + + m_pInput->SetFgColor( pScheme->GetColor( "Chat.TypingText", pScheme->GetColor( "Panel.FgColor", Color( 255, 255, 255, 255 ) ) ) ); +} + + + +//===================== +//CHudChat +//===================== + +CHudChat::CHudChat( const char *pElementName ) : BaseClass( pElementName ) +{ + +} + +void CHudChat::CreateChatInputLine( void ) +{ + m_pChatInput = new CHudChatInputLine( this, "ChatInputLine" ); + m_pChatInput->SetVisible( false ); +} + +void CHudChat::CreateChatLines( void ) +{ + for ( int i = 0; i < CHAT_INTERFACE_LINES; i++ ) + { + char sz[ 32 ]; + Q_snprintf( sz, sizeof( sz ), "ChatLine%02i", i ); + m_ChatLines[ i ] = new CHudChatLine( this, sz ); + m_ChatLines[ i ]->SetVisible( false ); + } +} + +void CHudChat::ApplySchemeSettings( vgui::IScheme *pScheme ) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + SetBgColor( Color( 0, 0, 0, 0 ) ); + SetFgColor( Color( 0, 0, 0, 0 ) ); +} + + +void CHudChat::Init( void ) +{ + BaseClass::Init(); + + HOOK_HUD_MESSAGE( CHudChat, SayText ); + HOOK_HUD_MESSAGE( CHudChat, TextMsg ); +} + +//----------------------------------------------------------------------------- +// Purpose: Overrides base reset to not cancel chat at round restart +//----------------------------------------------------------------------------- +void CHudChat::Reset( void ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pszName - +// iSize - +// *pbuf - +//----------------------------------------------------------------------------- +void CHudChat::MsgFunc_SayText( bf_read &msg ) +{ + char szString[256]; + + int client = msg.ReadByte(); + msg.ReadString( szString, sizeof(szString) ); + bool bWantsToChat = msg.ReadByte(); + + if ( bWantsToChat ) + { + // print raw chat text + ChatPrintf( client, "%s", szString ); + } + else + { + // try to lookup translated string + Printf( "%s", hudtextmessage->LookupString( szString ) ); + } + + Msg( "%s", szString ); +} + +wchar_t* ReadLocalizedRadioCommandString( bf_read &msg, wchar_t *pOut, int outSize, bool bStripNewline ) +{ + char szString[2048]; + msg.ReadString( szString, sizeof(szString) ); + + const wchar_t *pBuf = g_pVGuiLocalize->Find( szString ); + if ( pBuf ) + { + wcsncpy( pOut, pBuf, outSize/sizeof(wchar_t) ); + pOut[outSize/sizeof(wchar_t)-1] = 0; + } + else + { + g_pVGuiLocalize->ConvertANSIToUnicode( szString, pOut, outSize ); + } + + if ( bStripNewline ) + StripEndNewlineFromString( pOut ); + + return pOut; +} + +// Message handler for text messages +// displays a string, looking them up from the titles.txt file, which can be localised +// parameters: +// byte: message direction ( HUD_PRINTCONSOLE, HUD_PRINTNOTIFY, HUD_PRINTCENTER, HUD_PRINTTALK ) +// string: message +// optional parameters: +// string: message parameter 1 +// string: message parameter 2 +// string: message parameter 3 +// string: message parameter 4 +// any string that starts with the character '#' is a message name, and is used to look up the real message in titles.txt +// the next (optional) one to four strings are parameters for that string (which can also be message names if they begin with '#') +void CHudChat::MsgFunc_TextMsg( bf_read &msg ) +{ + char szString[2048]; + int msg_dest = msg.ReadByte(); + + wchar_t szBuf[5][128]; + wchar_t outputBuf[256]; + + for ( int i=0; i<5; ++i ) + { + msg.ReadString( szString, sizeof(szString) ); + char *tmpStr = hudtextmessage->LookupString( szString, &msg_dest ); + const wchar_t *pBuf = g_pVGuiLocalize->Find( tmpStr ); + if ( pBuf ) + { + // Copy pBuf into szBuf[i]. + int nMaxChars = sizeof( szBuf[i] ) / sizeof( wchar_t ); + wcsncpy( szBuf[i], pBuf, nMaxChars ); + szBuf[i][nMaxChars-1] = 0; + } + else + { + if ( i ) + { + StripEndNewlineFromString( tmpStr ); // these strings are meant for subsitution into the main strings, so cull the automatic end newlines + } + g_pVGuiLocalize->ConvertANSIToUnicode( tmpStr, szBuf[i], sizeof(szBuf[i]) ); + } + } + + if ( !cl_showtextmsg.GetInt() ) + return; + + int len; + switch ( msg_dest ) + { + case HUD_PRINTCENTER: + g_pVGuiLocalize->ConstructString( outputBuf, sizeof(outputBuf), szBuf[0], 4, szBuf[1], szBuf[2], szBuf[3], szBuf[4] ); + internalCenterPrint->Print( ConvertCRtoNL( outputBuf ) ); + break; + + case HUD_PRINTNOTIFY: + g_pVGuiLocalize->ConstructString( outputBuf, sizeof(outputBuf), szBuf[0], 4, szBuf[1], szBuf[2], szBuf[3], szBuf[4] ); + g_pVGuiLocalize->ConvertUnicodeToANSI( outputBuf, szString, sizeof(szString) ); + len = strlen( szString ); + if ( len && szString[len-1] != '\n' && szString[len-1] != '\r' ) + { + Q_strncat( szString, "\n", sizeof(szString), 1 ); + } + Msg( "%s", ConvertCRtoNL( szString ) ); + break; + + case HUD_PRINTTALK: + g_pVGuiLocalize->ConstructString( outputBuf, sizeof(outputBuf), szBuf[0], 4, szBuf[1], szBuf[2], szBuf[3], szBuf[4] ); + g_pVGuiLocalize->ConvertUnicodeToANSI( outputBuf, szString, sizeof(szString) ); + len = strlen( szString ); + if ( len && szString[len-1] != '\n' && szString[len-1] != '\r' ) + { + Q_strncat( szString, "\n", sizeof(szString), 1 ); + } + Printf( "%s", ConvertCRtoNL( szString ) ); + break; + + case HUD_PRINTCONSOLE: + g_pVGuiLocalize->ConstructString( outputBuf, sizeof(outputBuf), szBuf[0], 4, szBuf[1], szBuf[2], szBuf[3], szBuf[4] ); + g_pVGuiLocalize->ConvertUnicodeToANSI( outputBuf, szString, sizeof(szString) ); + len = strlen( szString ); + if ( len && szString[len-1] != '\n' && szString[len-1] != '\r' ) + { + Q_strncat( szString, "\n", sizeof(szString), 1 ); + } + Msg( "%s", ConvertCRtoNL( szString ) ); + break; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *fmt - +// ... - +//----------------------------------------------------------------------------- +void CHudChat::ChatPrintf( int iPlayerIndex, const char *fmt, ... ) +{ + va_list marker; + char msg[4096]; + + va_start(marker, fmt); + Q_vsnprintf(msg, sizeof( msg), fmt, marker); + va_end(marker); + + // Strip any trailing '\n' + if ( strlen( msg ) > 0 && msg[ strlen( msg )-1 ] == '\n' ) + { + msg[ strlen( msg ) - 1 ] = 0; + } + + // Strip leading \n characters ( or notify/color signifiers ) + char *pmsg = msg; + while ( *pmsg && ( *pmsg == '\n' || *pmsg == 1 || *pmsg == 2 ) ) + { + pmsg++; + } + + if ( !*pmsg ) + return; + + if ( *pmsg < 32 ) + { + hudlcd->AddChatLine( pmsg + 1 ); + } + else + { + hudlcd->AddChatLine( pmsg ); + } + + CHudChatLine *line = (CHudChatLine *)FindUnusedChatLine(); + if ( !line ) + { + ExpireOldest(); + line = (CHudChatLine *)FindUnusedChatLine(); + } + + if ( !line ) + { + return; + } + + line->SetText( "" ); + + int iNameLength = 0; + + player_info_t sPlayerInfo; + if ( iPlayerIndex == 0 ) + { + Q_memset( &sPlayerInfo, 0, sizeof(player_info_t) ); + Q_strncpy( sPlayerInfo.name, "Console", sizeof(sPlayerInfo.name) ); + } + else + { + engine->GetPlayerInfo( iPlayerIndex, &sPlayerInfo ); + } + + const char *pName = sPlayerInfo.name; + + if ( pName ) + { + const char *nameInString = strstr( pmsg, pName ); + + if ( nameInString ) + { + iNameLength = strlen( pName ) + (nameInString - pmsg); + } + } + else + line->InsertColorChange( Color( g_ColorYellow[0], g_ColorYellow[1], g_ColorYellow[2], 255 ) ); + + char *buf = static_cast<char *>( _alloca( strlen( pmsg ) + 1 ) ); + wchar_t *wbuf = static_cast<wchar_t *>( _alloca( (strlen( pmsg ) + 1 ) * sizeof(wchar_t) ) ); + if ( buf ) + { + float *flColor = GetClientColor( iPlayerIndex ); + + line->SetExpireTime(); + + // draw the first x characters in the player color + Q_strncpy( buf, pmsg, MIN( iNameLength + 1, MAX_PLAYER_NAME_LENGTH+32) ); + buf[ MIN( iNameLength, MAX_PLAYER_NAME_LENGTH+31) ] = 0; + line->InsertColorChange( Color( flColor[0], flColor[1], flColor[2], 255 ) ); + line->InsertString( buf ); + Q_strncpy( buf, pmsg + iNameLength, strlen( pmsg )); + buf[ strlen( pmsg + iNameLength ) ] = '\0'; + line->InsertColorChange( Color( g_ColorYellow[0], g_ColorYellow[1], g_ColorYellow[2], 255 ) ); + g_pVGuiLocalize->ConvertANSIToUnicode( buf, wbuf, strlen(pmsg)*sizeof(wchar_t)); + line->InsertString( wbuf ); + line->SetVisible( true ); + line->SetNameLength( iNameLength ); + line->SetNameColor( Color( flColor[0], flColor[1], flColor[2], 255 ) ); + } + + CLocalPlayerFilter filter; + C_BaseEntity::EmitSound( filter, -1 /*SOUND_FROM_LOCAL_PLAYER*/, "HudChat.Message" ); +} + +int CHudChat::GetChatInputOffset( void ) +{ + if ( m_pChatInput->IsVisible() ) + { + return m_iFontHeight; + } + else + return 0; +} diff --git a/game/client/sdk/sdk_hud_chat.h b/game/client/sdk/sdk_hud_chat.h new file mode 100644 index 0000000..26d3e58 --- /dev/null +++ b/game/client/sdk/sdk_hud_chat.h @@ -0,0 +1,68 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef SDK_HUD_CHAT_H +#define SDK_HUD_CHAT_H +#ifdef _WIN32 +#pragma once +#endif + +#include <hud_basechat.h> + +class CHudChatLine : public CBaseHudChatLine +{ + DECLARE_CLASS_SIMPLE( CHudChatLine, CBaseHudChatLine ); + +public: + CHudChatLine( vgui::Panel *parent, const char *panelName ) : CBaseHudChatLine( parent, panelName ) {} + + virtual void ApplySchemeSettings(vgui::IScheme *pScheme); + + void PerformFadeout( void ); + + void MsgFunc_SayText(bf_read &msg); + +private: + CHudChatLine( const CHudChatLine & ); // not defined, not accessible +}; + +//----------------------------------------------------------------------------- +// Purpose: The prompt and text entry area for chat messages +//----------------------------------------------------------------------------- +class CHudChatInputLine : public CBaseHudChatInputLine +{ + DECLARE_CLASS_SIMPLE( CHudChatInputLine, CBaseHudChatInputLine ); + +public: + CHudChatInputLine( CBaseHudChat *parent, char const *panelName ) : CBaseHudChatInputLine( parent, panelName ) {} + + virtual void ApplySchemeSettings(vgui::IScheme *pScheme); +}; + +class CHudChat : public CBaseHudChat +{ + DECLARE_CLASS_SIMPLE( CHudChat, CBaseHudChat ); + +public: + CHudChat( const char *pElementName ); + + virtual void CreateChatInputLine( void ); + virtual void CreateChatLines( void ); + + virtual void Init( void ); + virtual void Reset( void ); + virtual void ApplySchemeSettings(vgui::IScheme *pScheme); + + void MsgFunc_SayText( bf_read &msg ); + void MsgFunc_TextMsg( bf_read &msg ); + + void ChatPrintf( int iPlayerIndex, PRINTF_FORMAT_STRING const char *fmt, ... ); + + int GetChatInputOffset( void ); +}; + +#endif //SDK_HUD_CHAT_H
\ No newline at end of file diff --git a/game/client/sdk/sdk_hud_health.cpp b/game/client/sdk/sdk_hud_health.cpp new file mode 100644 index 0000000..9f984a0 --- /dev/null +++ b/game/client/sdk/sdk_hud_health.cpp @@ -0,0 +1,170 @@ +//========= 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 <KeyValues.h> +#include <vgui/ISurface.h> +#include <vgui/ISystem.h> +#include <vgui_controls/AnimationController.h> + +#include <vgui/ILocalize.h> + +using namespace vgui; + +#include "hudelement.h" +#include "hud_numericdisplay.h" + +#include "ConVar.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#define INIT_HEALTH -1 + +//----------------------------------------------------------------------------- +// Purpose: Health panel +//----------------------------------------------------------------------------- +class CHudHealth : public CHudElement, public CHudNumericDisplay +{ + DECLARE_CLASS_SIMPLE( CHudHealth, CHudNumericDisplay ); + +public: + CHudHealth( const char *pElementName ); + virtual void Init( void ); + virtual void VidInit( void ); + virtual void Reset( void ); + virtual void OnThink(); + void MsgFunc_Damage( bf_read &msg ); + +private: + // old variables + int m_iHealth; + + int m_bitsDamage; +}; + +DECLARE_HUDELEMENT( CHudHealth ); +DECLARE_HUD_MESSAGE( CHudHealth, Damage ); + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CHudHealth::CHudHealth( const char *pElementName ) : CHudElement( pElementName ), CHudNumericDisplay(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_bitsDamage = 0; + + wchar_t *tempString = g_pVGuiLocalize->Find("#Valve_Hud_HEALTH"); + + if (tempString) + { + SetLabelText(tempString); + } + else + { + SetLabelText(L"HEALTH"); + } + SetDisplayValue(m_iHealth); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHudHealth::VidInit() +{ + Reset(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHudHealth::OnThink() +{ + int newHealth = 0; + C_BasePlayer *local = C_BasePlayer::GetLocalPlayer(); + if ( local ) + { + // Never below zero + newHealth = MAX( local->GetHealth(), 0 ); + } + + // Only update the fade if we've changed health + if ( newHealth == m_iHealth ) + { + return; + } + + m_iHealth = newHealth; + + if ( m_iHealth >= 20 ) + { + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("HealthIncreasedAbove20"); + } + else if ( m_iHealth > 0 ) + { + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("HealthIncreasedBelow20"); + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("HealthLow"); + } + + SetDisplayValue(m_iHealth); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHudHealth::MsgFunc_Damage( bf_read &msg ) +{ + + int armor = msg.ReadByte(); // armor + int damageTaken = msg.ReadByte(); // health + long bitsDamage = msg.ReadLong(); // damage bits + bitsDamage; // variable still sent but not used + + Vector vecFrom; + + vecFrom.x = msg.ReadBitCoord(); + vecFrom.y = msg.ReadBitCoord(); + vecFrom.z = msg.ReadBitCoord(); + + // Actually took damage? + if ( damageTaken > 0 || armor > 0 ) + { + if ( damageTaken > 0 ) + { + // start the animation + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("HealthDamageTaken"); + } + } +}
\ No newline at end of file diff --git a/game/client/sdk/sdk_hud_message.cpp b/game/client/sdk/sdk_hud_message.cpp new file mode 100644 index 0000000..a774abf --- /dev/null +++ b/game/client/sdk/sdk_hud_message.cpp @@ -0,0 +1,107 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Simple HUD element +// +//============================================================================= + +#include "cbase.h" +#include "hudelement.h" +#include "hud_macros.h" +#include "iclientmode.h" +#include "view.h" + +using namespace vgui; + +#include <vgui_controls/Panel.h> +#include <vgui_controls/Frame.h> +#include <vgui/IScheme.h> +#include <vgui/ISurface.h> +#include <vgui/ILocalize.h> + +class CHudGameMessage : public CHudElement, public vgui::Panel +{ +private: + DECLARE_CLASS_SIMPLE( CHudGameMessage, vgui::Panel ); + +public: + + CHudGameMessage( const char *pElementName ) : CHudElement( pElementName ), vgui::Panel( NULL, "HudGameMessage" ) + { + // Set our parent window + SetParent( g_pClientMode->GetViewport() ); + + m_pIcon = NULL; + + // Never hide + SetHiddenBits( 0 ); + }; + + void Init( void ); + void VidInit( void ); + void Paint( void ); + + // Callback function for the "GameMessage" user message + void MsgFunc_GameMessage( bf_read &msg ); + +private: + CHudTexture *m_pIcon; // Icon texture reference + wchar_t m_pText[256]; // Unicode text buffer + + float m_flStartTime; // When the message was recevied + float m_flDuration; // Duration of the message +}; + +DECLARE_HUDELEMENT( CHudGameMessage ); +DECLARE_HUD_MESSAGE( CHudGameMessage, GameMessage ); + +void CHudGameMessage::VidInit( void ) +{ + // Store off a reference to our icon + m_pIcon = gHUD.GetIcon( "message_icon" ); + + m_pText[0] = '\0'; +} + +void CHudGameMessage::Init( void ) +{ + HOOK_HUD_MESSAGE( CHudGameMessage, GameMessage ); +} + +void CHudGameMessage::MsgFunc_GameMessage( bf_read &msg ) +{ + // Read in our string + char szString[256]; + msg.ReadString( szString, sizeof(szString) ); + + // Convert it to localize friendly unicode + g_pVGuiLocalize->ConvertANSIToUnicode( szString, m_pText, sizeof(m_pText) ); + + // Setup our time trackers + m_flStartTime = gpGlobals->curtime; + m_flDuration = 5.0f; +} + +void CHudGameMessage::Paint( void ) +{ + if ( !m_pIcon ) + return; + + // Find our fade based on our time shown + float dt = ( m_flStartTime - gpGlobals->curtime ); + float flAlpha = SimpleSplineRemapVal( dt, 0.0f, m_flDuration, 255, 0 ); + flAlpha = clamp( flAlpha, 0.0f, 255.0f ); + + // Draw our icon + m_pIcon->DrawSelf( 0, 0, 32, 32, Color(255,255,255,flAlpha) ); + + // Get our scheme and font information + vgui::HScheme scheme = vgui::scheme()->GetScheme( "ClientScheme" ); + vgui::HFont hFont = vgui::scheme()->GetIScheme(scheme)->GetFont( "Default" ); + + // Draw our text + surface()->DrawSetTextFont( hFont ); // set the font + surface()->DrawSetTextColor( 255, 255, 255, flAlpha ); // white + surface()->DrawSetTextPos( 32, 8 ); // x,y position + surface()->DrawPrintText( m_pText, wcslen(m_pText) ); // print text +} + diff --git a/game/client/sdk/sdk_hud_weaponselection.cpp b/game/client/sdk/sdk_hud_weaponselection.cpp new file mode 100644 index 0000000..7757747 --- /dev/null +++ b/game/client/sdk/sdk_hud_weaponselection.cpp @@ -0,0 +1,761 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "cbase.h" +#include "weapon_selection.h" +#include "iclientmode.h" +#include "history_resource.h" +#include "input.h" + +#include <KeyValues.h> +#include <vgui/IScheme.h> +#include <vgui/ISurface.h> +#include <vgui/ISystem.h> +#include <vgui_controls/AnimationController.h> +#include <vgui_controls/Panel.h> + +#include "vgui/ILocalize.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//----------------------------------------------------------------------------- +// Purpose: hl2 weapon selection hud element +//----------------------------------------------------------------------------- +class CHudWeaponSelection : public CBaseHudWeaponSelection, public vgui::Panel +{ + DECLARE_CLASS_SIMPLE( CHudWeaponSelection, vgui::Panel ); + +public: + CHudWeaponSelection(const char *pElementName ); + + virtual bool ShouldDraw(); + virtual void OnWeaponPickup( C_BaseCombatWeapon *pWeapon ); + + virtual void CycleToNextWeapon( void ); + virtual void CycleToPrevWeapon( void ); + + virtual C_BaseCombatWeapon *GetWeaponInSlot( int iSlot, int iSlotPos ); + virtual void SelectWeaponSlot( int iSlot ); + + virtual C_BaseCombatWeapon *GetSelectedWeapon( void ) + { + return m_hSelectedWeapon; + } + + virtual void OpenSelection( void ); + virtual void HideSelection( void ); + + virtual void LevelInit(); + +protected: + virtual void OnThink(); + virtual void Paint(); + virtual void ApplySchemeSettings(vgui::IScheme *pScheme); + + virtual bool IsWeaponSelectable() + { + if (IsInSelectionMode()) + return true; + + return false; + } + +private: + C_BaseCombatWeapon *FindNextWeaponInWeaponSelection(int iCurrentSlot, int iCurrentPosition); + C_BaseCombatWeapon *FindPrevWeaponInWeaponSelection(int iCurrentSlot, int iCurrentPosition); + + void FastWeaponSwitch( int iWeaponSlot ); + + virtual void SetSelectedWeapon( C_BaseCombatWeapon *pWeapon ) + { + m_hSelectedWeapon = pWeapon; + } + + void DrawBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha, int number); + + CPanelAnimationVar( vgui::HFont, m_hNumberFont, "NumberFont", "HudSelectionNumbers" ); + CPanelAnimationVar( vgui::HFont, m_hTextFont, "TextFont", "HudSelectionText" ); + + CPanelAnimationVarAliasType( float, m_flSmallBoxSize, "SmallBoxSize", "32", "proportional_float" ); + CPanelAnimationVarAliasType( float, m_flLargeBoxWide, "LargeBoxWide", "108", "proportional_float" ); + CPanelAnimationVarAliasType( float, m_flLargeBoxTall, "LargeBoxTall", "72", "proportional_float" ); + + CPanelAnimationVarAliasType( float, m_flBoxGap, "BoxGap", "12", "proportional_float" ); + + CPanelAnimationVarAliasType( float, m_flSelectionNumberXPos, "SelectionNumberXPos", "4", "proportional_float" ); + CPanelAnimationVarAliasType( float, m_flSelectionNumberYPos, "SelectionNumberYPos", "4", "proportional_float" ); + + CPanelAnimationVarAliasType( float, m_flTextYPos, "TextYPos", "54", "proportional_float" ); + + CPanelAnimationVar( float, m_flAlphaOverride, "Alpha", "255" ); + CPanelAnimationVar( float, m_flSelectionAlphaOverride, "SelectionAlpha", "255" ); + + + CPanelAnimationVar( Color, m_TextColor, "TextColor", "SelectionTextFg" ); + CPanelAnimationVar( Color, m_NumberColor, "NumberColor", "SelectionNumberFg" ); + CPanelAnimationVar( Color, m_EmptyBoxColor, "EmptyBoxColor", "SelectionEmptyBoxBg" ); + CPanelAnimationVar( Color, m_BoxColor, "BoxColor", "SelectionBoxBg" ); + CPanelAnimationVar( Color, m_SelectedBoxColor, "SelectedBoxClor", "SelectionSelectedBoxBg" ); + + CPanelAnimationVar( float, m_flWeaponPickupGrowTime, "SelectionGrowTime", "0.1" ); + + CPanelAnimationVar( float, m_flTextScan, "TextScan", "1.0" ); + + bool m_bFadingOut; +}; + +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 ); + m_bFadingOut = false; +} + +//----------------------------------------------------------------------------- +// Purpose: sets up display for showing weapon pickup +//----------------------------------------------------------------------------- +void CHudWeaponSelection::OnWeaponPickup( C_BaseCombatWeapon *pWeapon ) +{ + // add to pickup history + CHudHistoryResource *pHudHR = GET_HUDELEMENT( CHudHistoryResource ); + if ( pHudHR ) + { + pHudHR->AddToHistory( pWeapon ); + } +} + +#define SELECTION_TIMEOUT_THRESHOLD 5.0f // Seconds +#define SELECTION_FADEOUT_TIME 1.5f + +//----------------------------------------------------------------------------- +// Purpose: updates animation status +//----------------------------------------------------------------------------- +void CHudWeaponSelection::OnThink( void ) +{ + // Time out after awhile of inactivity + if ( ( gpGlobals->curtime - m_flSelectionTime ) > SELECTION_TIMEOUT_THRESHOLD ) + { + if (!m_bFadingOut) + { + // start fading out + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "FadeOutWeaponSelectionMenu" ); + m_bFadingOut = true; + } + else if (gpGlobals->curtime - m_flSelectionTime > SELECTION_TIMEOUT_THRESHOLD + SELECTION_FADEOUT_TIME) + { + // finished fade, close + HideSelection(); + } + } + else if (m_bFadingOut) + { + // stop us fading out, show the animation again + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "OpenWeaponSelectionMenu" ); + m_bFadingOut = false; + } +} + +//----------------------------------------------------------------------------- +// 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: +//----------------------------------------------------------------------------- +void CHudWeaponSelection::LevelInit() +{ + CHudElement::LevelInit(); +} + +//------------------------------------------------------------------------- +// 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); + + // interpolate the selected box size between the small box size and the large box size + // interpolation has been removed since there is no weapon pickup animation anymore, so it's all at the largest size + float percentageDone = 1.0f; //min(1.0f, (gpGlobals->curtime - m_flPickupStartTime) / m_flWeaponPickupGrowTime); + int largeBoxWide = m_flSmallBoxSize + ((m_flLargeBoxWide - m_flSmallBoxSize) * percentageDone); + int largeBoxTall = m_flSmallBoxSize + ((m_flLargeBoxTall - m_flSmallBoxSize) * percentageDone); + Color selectedColor; + {for (int i = 0; i < 4; i++) + { + selectedColor[i] = m_BoxColor[i] + ((m_SelectedBoxColor[i] - m_BoxColor[i]) * percentageDone); + }} + + // calculate where to start drawing + int width = (MAX_WEAPON_SLOTS - 1) * (m_flSmallBoxSize + m_flBoxGap) + largeBoxWide; + int xpos = (GetWide() - width) / 2; + int ypos = 0; + + // iterate over all the weapon slots + for ( int i = 0; i < MAX_WEAPON_SLOTS; i++ ) + { + if ( i == iActiveSlot ) + { + bool bFirstItem = true; + for (int slotpos = 0; slotpos < MAX_WEAPON_POSITIONS; slotpos++) + { + C_BaseCombatWeapon *pWeapon = GetWeaponInSlot(i, slotpos); + if ( !pWeapon ) + continue; + + // draw box for selected weapon + DrawBox(xpos, ypos, largeBoxWide, largeBoxTall, selectedColor, m_flSelectionAlphaOverride, bFirstItem ? i + 1 : -1); + + // draw icon + Color col = GetFgColor(); + if ( pWeapon->GetSpriteActive() ) + { + // find the center of the box to draw in + int iconWidth = pWeapon->GetSpriteActive()->Width(); + int iconHeight = pWeapon->GetSpriteActive()->Height(); + + int x_offs = (largeBoxWide - iconWidth) / 2; + int y_offs = (largeBoxTall - iconHeight) / 2; + + if (!pWeapon->CanBeSelected()) + { + // unselectable weapon, display as such + col = Color(255, 0, 0, col[3]); + } + else if (pWeapon == pSelectedWeapon) + { + // currently selected weapon, display brighter + col[3] = m_flSelectionAlphaOverride; + + // draw an active version over the top + pWeapon->GetSpriteActive()->DrawSelf( xpos + x_offs, ypos + y_offs, col ); + } + + // draw the inactive version + pWeapon->GetSpriteInactive()->DrawSelf( xpos + x_offs, ypos + y_offs, col ); + } + + // draw text + col = m_TextColor; + const FileWeaponInfo_t &weaponInfo = pWeapon->GetWpnData(); + + if (pWeapon == pSelectedWeapon) + { + wchar_t text[128]; + wchar_t *tempString = g_pVGuiLocalize->Find(weaponInfo.szPrintName); + + // setup our localized string + if ( tempString ) + { +#ifdef WIN32 + _snwprintf(text, sizeof(text)/sizeof(wchar_t) - 1, L"%s", tempString); +#else + _snwprintf(text, sizeof(text)/sizeof(wchar_t) - 1, L"%S", tempString); +#endif + text[sizeof(text)/sizeof(wchar_t) - 1] = 0; + } + else + { + // string wasn't found by g_pVGuiLocalize->Find() + g_pVGuiLocalize->ConvertANSIToUnicode(weaponInfo.szPrintName, text, sizeof(text)); + } + + surface()->DrawSetTextColor( col ); + surface()->DrawSetTextFont( m_hTextFont ); + + // count the position + int slen = 0, charCount = 0, maxslen = 0; + int firstslen = 0; + { + for (wchar_t *pch = text; *pch != 0; pch++) + { + if (*pch == '\n') + { + // newline character, drop to the next line + if (slen > maxslen) + { + maxslen = slen; + } + if (!firstslen) + { + firstslen = slen; + } + + slen = 0; + } + else if (*pch == '\r') + { + // do nothing + } + else + { + slen += surface()->GetCharacterWidth( m_hTextFont, *pch ); + charCount++; + } + } + } + if (slen > maxslen) + { + maxslen = slen; + } + if (!firstslen) + { + firstslen = maxslen; + } + + int tx = xpos + ((largeBoxWide - firstslen) / 2); + int ty = ypos + (int)m_flTextYPos; + surface()->DrawSetTextPos( tx, ty ); + // adjust the charCount by the scan amount + charCount *= m_flTextScan; + for (wchar_t *pch = text; charCount > 0; pch++) + { + if (*pch == '\n') + { + // newline character, move to the next line + surface()->DrawSetTextPos( xpos + ((largeBoxWide - slen) / 2), ty + (surface()->GetFontTall(m_hTextFont) * 1.1f)); + } + else if (*pch == '\r') + { + // do nothing + } + else + { + surface()->DrawUnicodeChar(*pch); + charCount--; + } + } + } + + ypos += (largeBoxTall + m_flBoxGap); + bFirstItem = false; + } + + xpos += largeBoxWide; + } + else + { + // check to see if there is a weapons in this bucket + if ( GetFirstPos( i ) ) + { + // draw has weapon in slot + DrawBox(xpos, ypos, m_flSmallBoxSize, m_flSmallBoxSize, m_BoxColor, m_flAlphaOverride, i + 1); + } + else + { + // draw empty slot + DrawBox(xpos, ypos, m_flSmallBoxSize, m_flSmallBoxSize, m_EmptyBoxColor, m_flAlphaOverride, -1); + } + + xpos += m_flSmallBoxSize; + } + + // reset position + ypos = 0; + xpos += m_flBoxGap; + } +} + +//----------------------------------------------------------------------------- +// Purpose: draws a selection box +//----------------------------------------------------------------------------- +void CHudWeaponSelection::DrawBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha, int number) +{ + BaseClass::DrawBox( x, y, wide, tall, color, normalizedAlpha / 255.0f ); + + // draw the number + if (number >= 0) + { + Color numberColor = m_NumberColor; + numberColor[3] *= normalizedAlpha / 255.0f; + surface()->DrawSetTextColor(numberColor); + surface()->DrawSetTextFont(m_hNumberFont); + wchar_t wch = '0' + number; + surface()->DrawSetTextPos(x + m_flSelectionNumberXPos, y + m_flSelectionNumberYPos); + surface()->DrawUnicodeChar(wch); + } +} + +//----------------------------------------------------------------------------- +// 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); +} + +//----------------------------------------------------------------------------- +// Purpose: Opens weapon selection control +//----------------------------------------------------------------------------- +void CHudWeaponSelection::OpenSelection( void ) +{ + Assert(!IsInSelectionMode()); + + CBaseHudWeaponSelection::OpenSelection(); + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("OpenWeaponSelectionMenu"); +} + +//----------------------------------------------------------------------------- +// Purpose: Closes weapon selection control immediately +//----------------------------------------------------------------------------- +void CHudWeaponSelection::HideSelection( void ) +{ + CBaseHudWeaponSelection::HideSelection(); + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("CloseWeaponSelectionMenu"); + m_bFadingOut = false; +} + +//----------------------------------------------------------------------------- +// 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 = 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 ( !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(MAX_WEAPON_SLOTS, MAX_WEAPON_POSITIONS); + } + + if ( pNextWeapon ) + { + SetSelectedWeapon( pNextWeapon ); + + 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: 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" ); + } +} + +//----------------------------------------------------------------------------- +// 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 > 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 ) + { + if ( !IsInSelectionMode() ) + { + // open the weapon selection + OpenSelection(); + } + + // Mark the change + SetSelectedWeapon( pActiveWeapon ); + } + + pPlayer->EmitSound( "Player.WeaponSelectionMoveSlot" ); +} diff --git a/game/client/sdk/sdk_in_main.cpp b/game/client/sdk/sdk_in_main.cpp new file mode 100644 index 0000000..1ce48c7 --- /dev/null +++ b/game/client/sdk/sdk_in_main.cpp @@ -0,0 +1,23 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: TF2 specific input handling +// +// $NoKeywords: $ +//=============================================================================// +#include "cbase.h" +#include "kbutton.h" +#include "input.h" + +//----------------------------------------------------------------------------- +// Purpose: TF Input interface +//----------------------------------------------------------------------------- +class CSDKInput : public CInput +{ +public: +}; + +static CSDKInput g_Input; + +// Expose this interface +IInput *input = ( IInput * )&g_Input; + diff --git a/game/client/sdk/sdk_prediction.cpp b/game/client/sdk/sdk_prediction.cpp new file mode 100644 index 0000000..c72a990 --- /dev/null +++ b/game/client/sdk/sdk_prediction.cpp @@ -0,0 +1,53 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// +#include "cbase.h" +#include "prediction.h" +#include "c_baseplayer.h" +#include "igamemovement.h" + + +static CMoveData g_MoveData; +CMoveData *g_pMoveData = &g_MoveData; + + +class CSDKPrediction : public CPrediction +{ +DECLARE_CLASS( CSDKPrediction, CPrediction ); + +public: + virtual void SetupMove( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ); + virtual void FinishMove( C_BasePlayer *player, CUserCmd *ucmd, CMoveData *move ); +}; + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CSDKPrediction::SetupMove( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, + CMoveData *move ) +{ + // Call the default SetupMove code. + BaseClass::SetupMove( player, ucmd, pHelper, move ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CSDKPrediction::FinishMove( C_BasePlayer *player, CUserCmd *ucmd, CMoveData *move ) +{ + // Call the default FinishMove code. + BaseClass::FinishMove( player, ucmd, move ); +} + + +// Expose interface to engine +// Expose interface to engine +static CSDKPrediction g_Prediction; + +EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CSDKPrediction, IPrediction, VCLIENT_PREDICTION_INTERFACE_VERSION, g_Prediction ); + +CPrediction *prediction = &g_Prediction; + diff --git a/game/client/sdk/vgui/sdkviewport.cpp b/game/client/sdk/vgui/sdkviewport.cpp new file mode 100644 index 0000000..5fd3627 --- /dev/null +++ b/game/client/sdk/vgui/sdkviewport.cpp @@ -0,0 +1,85 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Client DLL VGUI2 Viewport +// +// $Workfile: $ +// $Date: $ +// +//----------------------------------------------------------------------------- +// $Log: $ +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" + +#pragma warning( disable : 4800 ) // disable forcing int to bool performance warning + +// VGUI panel includes +#include <vgui_controls/Panel.h> +#include <vgui/ISurface.h> +#include <KeyValues.h> +#include <vgui/Cursor.h> +#include <vgui/IScheme.h> +#include <vgui/IVGui.h> +#include <vgui/ILocalize.h> +#include <vgui/VGUI.h> + +// client dll/engine defines +#include "hud.h" +#include <voice_status.h> + +// viewport definitions +#include <baseviewport.h> +#include "SDKViewport.h" + +#include "vguicenterprint.h" +#include "text_message.h" + + +void SDKViewport::ApplySchemeSettings( vgui::IScheme *pScheme ) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + gHUD.InitColors( pScheme ); + + SetPaintBackgroundEnabled( false ); +} + + +IViewPortPanel* SDKViewport::CreatePanelByName(const char *szPanelName) +{ + IViewPortPanel* newpanel = NULL; + +// Up here, strcmp against each type of panel we know how to create. +// else if ( Q_strcmp(PANEL_OVERVIEW, szPanelName) == 0 ) +// { +// newpanel = new CCSMapOverview( this ); +// } + + // create a generic base panel, don't add twice + newpanel = BaseClass::CreatePanelByName( szPanelName ); + + return newpanel; +} + +void SDKViewport::CreateDefaultPanels( void ) +{ + BaseClass::CreateDefaultPanels(); +} + +int SDKViewport::GetDeathMessageStartHeight( void ) +{ + int x = YRES(2); + + IViewPortPanel *spectator = gViewPortInterface->FindPanelByName( PANEL_SPECGUI ); + + //TODO: Link to actual height of spectator bar + if ( spectator && spectator->IsVisible() ) + { + x += YRES(52); + } + + return x; +} + diff --git a/game/client/sdk/vgui/sdkviewport.h b/game/client/sdk/vgui/sdkviewport.h new file mode 100644 index 0000000..159da39 --- /dev/null +++ b/game/client/sdk/vgui/sdkviewport.h @@ -0,0 +1,40 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef SDKVIEWPORT_H +#define SDKVIEWPORT_H + + +#include "sdk_shareddefs.h" +#include "baseviewport.h" + + +using namespace vgui; + +namespace vgui +{ + class Panel; +} + +class SDKViewport : public CBaseViewport +{ + +private: + DECLARE_CLASS_SIMPLE( SDKViewport, CBaseViewport ); + +public: + + IViewPortPanel* CreatePanelByName(const char *szPanelName); + void CreateDefaultPanels( void ); + + virtual void ApplySchemeSettings( vgui::IScheme *pScheme ); + + int GetDeathMessageStartHeight( void ); +}; + + +#endif // SDKViewport_H diff --git a/game/client/sdk/vgui/vgui_rootpanel_sdk.cpp b/game/client/sdk/vgui/vgui_rootpanel_sdk.cpp new file mode 100644 index 0000000..e756829 --- /dev/null +++ b/game/client/sdk/vgui/vgui_rootpanel_sdk.cpp @@ -0,0 +1,106 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// +#include "cbase.h" +#include "vgui_int.h" +#include "ienginevgui.h" +#include "vgui_rootpanel_sdk.h" +#include "vgui/IVGui.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +C_SDKRootPanel *g_pRootPanel = NULL; + + +//----------------------------------------------------------------------------- +// Global functions. +//----------------------------------------------------------------------------- +void VGUI_CreateClientDLLRootPanel( void ) +{ + g_pRootPanel = new C_SDKRootPanel( enginevgui->GetPanel( PANEL_CLIENTDLL ) ); +} + +void VGUI_DestroyClientDLLRootPanel( void ) +{ + delete g_pRootPanel; + g_pRootPanel = NULL; +} + +vgui::VPANEL VGui_GetClientDLLRootPanel( void ) +{ + return g_pRootPanel->GetVPanel(); +} + + +//----------------------------------------------------------------------------- +// C_SDKRootPanel implementation. +//----------------------------------------------------------------------------- +C_SDKRootPanel::C_SDKRootPanel( vgui::VPANEL parent ) + : BaseClass( NULL, "SDK Root Panel" ) +{ + SetParent( parent ); + SetPaintEnabled( false ); + SetPaintBorderEnabled( false ); + SetPaintBackgroundEnabled( false ); + + // This panel does post child painting + SetPostChildPaintEnabled( true ); + + // Make it screen sized + SetBounds( 0, 0, ScreenWidth(), ScreenHeight() ); + + // Ask for OnTick messages + vgui::ivgui()->AddTickSignal( GetVPanel() ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +C_SDKRootPanel::~C_SDKRootPanel( void ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_SDKRootPanel::PostChildPaint() +{ + BaseClass::PostChildPaint(); + + // Draw all panel effects + RenderPanelEffects(); +} + +//----------------------------------------------------------------------------- +// Purpose: For each panel effect, check if it wants to draw and draw it on +// this panel/surface if so +//----------------------------------------------------------------------------- +void C_SDKRootPanel::RenderPanelEffects( void ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_SDKRootPanel::OnTick( void ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: Reset effects on level load/shutdown +//----------------------------------------------------------------------------- +void C_SDKRootPanel::LevelInit( void ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_SDKRootPanel::LevelShutdown( void ) +{ +} + diff --git a/game/client/sdk/vgui/vgui_rootpanel_sdk.h b/game/client/sdk/vgui/vgui_rootpanel_sdk.h new file mode 100644 index 0000000..448abbc --- /dev/null +++ b/game/client/sdk/vgui/vgui_rootpanel_sdk.h @@ -0,0 +1,56 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef VGUI_ROOTPANEL_SDK_H +#define VGUI_ROOTPANEL_SDK_H +#ifdef _WIN32 +#pragma once +#endif + + +#include <vgui_controls/Panel.h> +#include <vgui_controls/EditablePanel.h> +#include "utlvector.h" + + +class CPanelEffect; + + +// Serial under of effect, for safe lookup +typedef unsigned int EFFECT_HANDLE; + +//----------------------------------------------------------------------------- +// Purpose: Sits between engine and client .dll panels +// Responsible for drawing screen overlays +//----------------------------------------------------------------------------- +class C_SDKRootPanel : public vgui::Panel +{ + typedef vgui::Panel BaseClass; +public: + C_SDKRootPanel( vgui::VPANEL parent ); + virtual ~C_SDKRootPanel( void ); + + // Draw Panel effects here + virtual void PostChildPaint(); + + // Clear list of Panel Effects + virtual void LevelInit( void ); + virtual void LevelShutdown( void ); + + // Run effects and let them decide whether to remove themselves + void OnTick( void ); + +private: + + // Render all panel effects + void RenderPanelEffects( void ); + + // List of current panel effects + CUtlVector< CPanelEffect *> m_Effects; +}; + + +#endif // VGUI_ROOTPANEL_SDK_H |