diff options
Diffstat (limited to 'game/client/tfc')
| -rw-r--r-- | game/client/tfc/c_tfc_player.cpp | 202 | ||||
| -rw-r--r-- | game/client/tfc/c_tfc_player.h | 69 | ||||
| -rw-r--r-- | game/client/tfc/c_tfc_team.cpp | 33 | ||||
| -rw-r--r-- | game/client/tfc/c_tfc_team.h | 36 | ||||
| -rw-r--r-- | game/client/tfc/clientmode_tfc.cpp | 139 | ||||
| -rw-r--r-- | game/client/tfc/clientmode_tfc.h | 51 | ||||
| -rw-r--r-- | game/client/tfc/fx_tfc_impacts.cpp | 29 | ||||
| -rw-r--r-- | game/client/tfc/tfc_hud_ammo.cpp | 355 | ||||
| -rw-r--r-- | game/client/tfc/tfc_hud_weaponselection.cpp | 682 | ||||
| -rw-r--r-- | game/client/tfc/tfc_in_main.cpp | 23 | ||||
| -rw-r--r-- | game/client/tfc/tfc_prediction.cpp | 53 | ||||
| -rw-r--r-- | game/client/tfc/vgui/tfcclassmenu.cpp | 61 | ||||
| -rw-r--r-- | game/client/tfc/vgui/tfcclassmenu.h | 42 | ||||
| -rw-r--r-- | game/client/tfc/vgui/tfcteammenu.cpp | 118 | ||||
| -rw-r--r-- | game/client/tfc/vgui/tfcteammenu.h | 42 | ||||
| -rw-r--r-- | game/client/tfc/vgui/tfcviewport.cpp | 96 | ||||
| -rw-r--r-- | game/client/tfc/vgui/tfcviewport.h | 40 | ||||
| -rw-r--r-- | game/client/tfc/vgui/vgui_rootpanel_tfc.cpp | 106 | ||||
| -rw-r--r-- | game/client/tfc/vgui/vgui_rootpanel_tfc.h | 56 |
19 files changed, 2233 insertions, 0 deletions
diff --git a/game/client/tfc/c_tfc_player.cpp b/game/client/tfc/c_tfc_player.cpp new file mode 100644 index 0000000..e62e88f --- /dev/null +++ b/game/client/tfc/c_tfc_player.cpp @@ -0,0 +1,202 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "cbase.h" +#include "c_tfc_player.h" +#include "c_user_message_register.h" +#include "view.h" +#include "iclientvehicle.h" +#include "ivieweffects.h" +#include "input.h" +#include "IEffects.h" +#include "fx.h" +#include "c_basetempentity.h" +#include "hud_macros.h" +#include "engine/ivdebugoverlay.h" +#include "smoke_fog_overlay.h" +#include "playerandobjectenumerator.h" +#include "bone_setup.h" +#include "in_buttons.h" +#include "r_efx.h" +#include "dlight.h" +#include "shake.h" +#include "cl_animevent.h" +#include "weapon_tfcbase.h" + +#if defined( CTFCPlayer ) + #undef CTFCPlayer +#endif + +#include "materialsystem/imesh.h" //for materials->FindMaterial +#include "iviewrender.h" //for view-> + + +// -------------------------------------------------------------------------------- // +// 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_TFCPlayer *pPlayer = dynamic_cast< C_TFCPlayer* >( m_hPlayer.Get() ); + if ( pPlayer && !pPlayer->IsDormant() ) + { + pPlayer->DoAnimationEvent( (PlayerAnimEvent_t)m_iEvent.Get(), m_nData ); + } + } + +public: + CNetworkHandle( CBasePlayer, m_hPlayer ); + CNetworkVar( int, m_iEvent ); + CNetworkVar( int, m_nData ); +}; + +IMPLEMENT_CLIENTCLASS_EVENT( C_TEPlayerAnimEvent, DT_TEPlayerAnimEvent, CTEPlayerAnimEvent ); + + +// ------------------------------------------------------------------------------------------ // +// Data tables and prediction tables. +// ------------------------------------------------------------------------------------------ // + +BEGIN_RECV_TABLE_NOBASE( C_TEPlayerAnimEvent, DT_TEPlayerAnimEvent ) + RecvPropEHandle( RECVINFO( m_hPlayer ) ), + RecvPropInt( RECVINFO( m_iEvent ) ), + RecvPropInt( RECVINFO( m_nData ) ) +END_RECV_TABLE() + +IMPLEMENT_CLIENTCLASS_DT( C_TFCPlayer, DT_TFCPlayer, CTFCPlayer ) + RecvPropFloat( RECVINFO( m_angEyeAngles[0] ) ), + RecvPropFloat( RECVINFO( m_angEyeAngles[1] ) ), + RecvPropDataTable( RECVINFO_DT( m_Shared ), 0, &REFERENCE_RECV_TABLE( DT_TFCPlayerShared ) ) +END_RECV_TABLE() + + +BEGIN_PREDICTION_DATA( C_TFCPlayer ) + DEFINE_PRED_TYPEDESCRIPTION( m_Shared, CTFCPlayerShared ), +END_PREDICTION_DATA() + + + +// ------------------------------------------------------------------------------------------ // +// C_TFCPlayer implementation. +// ------------------------------------------------------------------------------------------ // + +C_TFCPlayer::C_TFCPlayer() : + m_iv_angEyeAngles( "C_TFCPlayer::m_iv_angEyeAngles" ) +{ + m_PlayerAnimState = CreatePlayerAnimState( this ); + m_Shared.Init( this ); + + AddVar( &m_angEyeAngles, &m_iv_angEyeAngles, LATCH_SIMULATION_VAR ); +} + + +C_TFCPlayer::~C_TFCPlayer() +{ + m_PlayerAnimState->Release(); +} + + +C_TFCPlayer* C_TFCPlayer::GetLocalTFCPlayer() +{ + return ToTFCPlayer( C_BasePlayer::GetLocalPlayer() ); +} + +const QAngle& C_TFCPlayer::GetRenderAngles() +{ + if ( IsRagdoll() ) + { + return vec3_angle; + } + else + { + return m_PlayerAnimState->GetRenderAngles(); + } +} + + +void C_TFCPlayer::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_TFCPlayer::GetLocalTFCPlayer() ) + m_PlayerAnimState->Update( EyeAngles()[YAW], m_angEyeAngles[PITCH] ); + else + m_PlayerAnimState->Update( m_angEyeAngles[YAW], m_angEyeAngles[PITCH] ); + + BaseClass::UpdateClientSideAnimation(); +} + + +void C_TFCPlayer::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_TFCPlayer::DoAnimationEvent( PlayerAnimEvent_t event, int nData ) +{ + m_PlayerAnimState->DoAnimationEvent( event, nData ); +} + + +void C_TFCPlayer::ProcessMuzzleFlashEvent() +{ + // Reenable when the weapons have muzzle flash attachments in the right spot. + if ( this != C_BasePlayer::GetLocalPlayer() ) + { + Vector vAttachment; + QAngle dummyAngles; + + C_WeaponTFCBase *pWeapon = m_Shared.GetActiveTFCWeapon(); + + if ( pWeapon ) + { + int iAttachment = pWeapon->LookupAttachment( "muzzle_flash" ); + + if ( iAttachment > 0 ) + { + float flScale = 1; + pWeapon->GetAttachment( iAttachment, vAttachment, dummyAngles ); + + // The way the models are setup, the up vector points along the barrel. + Vector vForward, vRight, vUp; + AngleVectors( dummyAngles, &vForward, &vRight, &vUp ); + VectorAngles( vUp, dummyAngles ); + + FX_MuzzleEffect( vAttachment, dummyAngles, flScale, INVALID_EHANDLE_INDEX, NULL, true ); + } + } + } + + Vector vAttachment; + QAngle dummyAngles; + + bool bFoundAttachment = GetAttachment( 1, vAttachment, dummyAngles ); + // If we have an attachment, then stick a light on it. + if ( bFoundAttachment ) + { + dlight_t *el = effects->CL_AllocDlight( LIGHT_INDEX_MUZZLEFLASH + index ); + el->origin = vAttachment; + el->radius = 24; + el->decay = el->radius / 0.05f; + el->die = gpGlobals->curtime + 0.05f; + el->color.r = 255; + el->color.g = 192; + el->color.b = 64; + el->color.exponent = 5; + } +} diff --git a/game/client/tfc/c_tfc_player.h b/game/client/tfc/c_tfc_player.h new file mode 100644 index 0000000..41d5e58 --- /dev/null +++ b/game/client/tfc/c_tfc_player.h @@ -0,0 +1,69 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef C_TFC_PLAYER_H +#define C_TFC_PLAYER_H +#ifdef _WIN32 +#pragma once +#endif + + +#include "tfc_playeranimstate.h" +#include "c_baseplayer.h" +#include "tfc_shareddefs.h" +#include "baseparticleentity.h" +#include "tfc_player_shared.h" + + +class C_TFCPlayer : public C_BasePlayer +{ +public: + DECLARE_CLASS( C_TFCPlayer, C_BasePlayer ); + DECLARE_CLIENTCLASS(); + DECLARE_PREDICTABLE(); + DECLARE_INTERPOLATION(); + + C_TFCPlayer(); + ~C_TFCPlayer(); + + static C_TFCPlayer* GetLocalTFCPlayer(); + + virtual const QAngle& GetRenderAngles(); + virtual void UpdateClientSideAnimation(); + virtual void PostDataUpdate( DataUpdateType_t updateType ); + virtual void ProcessMuzzleFlashEvent(); + + +public: + + CTFCPlayerShared m_Shared; + + +// Called by shared code. +public: + + void DoAnimationEvent( PlayerAnimEvent_t event, int nData ); + + ITFCPlayerAnimState *m_PlayerAnimState; + + + QAngle m_angEyeAngles; + CInterpolatedVar< QAngle > m_iv_angEyeAngles; + + +private: + C_TFCPlayer( const C_TFCPlayer & ); +}; + + +inline C_TFCPlayer* ToTFCPlayer( CBasePlayer *pPlayer ) +{ + Assert( dynamic_cast< C_TFCPlayer* >( pPlayer ) != NULL ); + return static_cast< C_TFCPlayer* >( pPlayer ); +} + + +#endif // C_TFC_PLAYER_H diff --git a/game/client/tfc/c_tfc_team.cpp b/game/client/tfc/c_tfc_team.cpp new file mode 100644 index 0000000..57876d6 --- /dev/null +++ b/game/client/tfc/c_tfc_team.cpp @@ -0,0 +1,33 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Client side C_TFCTeam class +// +// $NoKeywords: $ +//=============================================================================// +#include "cbase.h" +#include "engine/IEngineSound.h" +#include "hud.h" +#include "recvproxy.h" +#include "c_tfc_team.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +IMPLEMENT_CLIENTCLASS_DT(C_TFCTeam, DT_TFCTeam, CTFCTeam) +END_RECV_TABLE() + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +C_TFCTeam::C_TFCTeam() +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +C_TFCTeam::~C_TFCTeam() +{ +} + diff --git a/game/client/tfc/c_tfc_team.h b/game/client/tfc/c_tfc_team.h new file mode 100644 index 0000000..2ce80f6 --- /dev/null +++ b/game/client/tfc/c_tfc_team.h @@ -0,0 +1,36 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Client side CTFTeam class +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef C_TFC_TEAM_H +#define C_TFC_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_TFCTeam : public C_Team +{ + DECLARE_CLASS( C_TFCTeam, C_Team ); + DECLARE_CLIENTCLASS(); + +public: + + C_TFCTeam(); + virtual ~C_TFCTeam(); +}; + + +#endif // C_TFC_TEAM_H diff --git a/game/client/tfc/clientmode_tfc.cpp b/game/client/tfc/clientmode_tfc.cpp new file mode 100644 index 0000000..4af9ba6 --- /dev/null +++ b/game/client/tfc/clientmode_tfc.cpp @@ -0,0 +1,139 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// +#include "cbase.h" +#include "hud.h" +#include "clientmode_tfc.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; + + +// --------------------------------------------------------------------------------- // +// CTFCModeManager. +// --------------------------------------------------------------------------------- // + +class CTFCModeManager : 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 CTFCModeManager g_ModeManager; +IVModeManager *modemanager = ( IVModeManager * )&g_ModeManager; + + +// --------------------------------------------------------------------------------- // +// CTFCModeManager implementation. +// --------------------------------------------------------------------------------- // + +#define SCREEN_FILE "scripts/vgui_screens.txt" + +void CTFCModeManager::Init() +{ + g_pClientMode = GetClientModeNormal(); + + PanelMetaClassMgr()->LoadMetaClassDefinitionFile( SCREEN_FILE ); +} + +void CTFCModeManager::LevelInit( const char *newmap ) +{ + g_pClientMode->LevelInit( newmap ); +} + +void CTFCModeManager::LevelShutdown( void ) +{ + g_pClientMode->LevelShutdown(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +ClientModeTFCNormal::ClientModeTFCNormal() +{ +} + +//----------------------------------------------------------------------------- +// Purpose: If you don't know what a destructor is by now, you are probably going to get fired +//----------------------------------------------------------------------------- +ClientModeTFCNormal::~ClientModeTFCNormal() +{ +} + + +void ClientModeTFCNormal::InitViewport() +{ + m_pViewport = new TFCViewport(); + m_pViewport->Start( gameuifuncs, gameeventmanager ); +} + +ClientModeTFCNormal g_ClientModeNormal; + +IClientMode *GetClientModeNormal() +{ + return &g_ClientModeNormal; +} + + +ClientModeTFCNormal* GetClientModeTFCNormal() +{ + Assert( dynamic_cast< ClientModeTFCNormal* >( GetClientModeNormal() ) ); + + return static_cast< ClientModeTFCNormal* >( GetClientModeNormal() ); +} + +float g_flViewModelFOV = 90; +float ClientModeTFCNormal::GetViewModelFOV( void ) +{ + return g_flViewModelFOV; +} + +int ClientModeTFCNormal::GetDeathMessageStartHeight( void ) +{ + return m_pViewport->GetDeathMessageStartHeight(); +} + +void ClientModeTFCNormal::FireGameEvent( KeyValues * event) +{ + BaseClass::FireGameEvent( event ); +} + + +void ClientModeTFCNormal::PostRenderVGui() +{ +} + + + + diff --git a/game/client/tfc/clientmode_tfc.h b/game/client/tfc/clientmode_tfc.h new file mode 100644 index 0000000..95a92c8 --- /dev/null +++ b/game/client/tfc/clientmode_tfc.h @@ -0,0 +1,51 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//===========================================================================// + +#ifndef TFC_CLIENTMODE_H +#define TFC_CLIENTMODE_H +#ifdef _WIN32 +#pragma once +#endif + +#include "clientmode_shared.h" +#include "tfcviewport.h" + +class ClientModeTFCNormal : public ClientModeShared +{ +DECLARE_CLASS( ClientModeTFCNormal, ClientModeShared ); + +private: + +// IClientMode overrides. +public: + + ClientModeTFCNormal(); + virtual ~ClientModeTFCNormal(); + + virtual void InitViewport(); + + virtual int KeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ); + + virtual float GetViewModelFOV( void ); + + int GetDeathMessageStartHeight( void ); + + virtual void FireGameEvent( KeyValues * event); + virtual void PostRenderVGui(); + + +private: + + // void UpdateSpectatorMode( void ); + +}; + + +extern IClientMode *GetClientModeNormal(); +extern ClientModeTFCNormal* GetClientModeTFCNormal(); + + +#endif // TFC_CLIENTMODE_H diff --git a/game/client/tfc/fx_tfc_impacts.cpp b/game/client/tfc/fx_tfc_impacts.cpp new file mode 100644 index 0000000..915f4dd --- /dev/null +++ b/game/client/tfc/fx_tfc_impacts.cpp @@ -0,0 +1,29 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "cbase.h" +#include "fx_impact.h" + + +void TFCImpact( const CEffectData &data ) +{ + Vector vOrigin, vStart, vDir; + short nSurfaceProp; + int iMaterial, iDamageType, iHitbox; + C_BaseEntity *pEntity = ParseImpactData( data, &vOrigin, &vStart, &vDir, nSurfaceProp, iMaterial, iDamageType, iHitbox ); + + trace_t tr; + if ( Impact( vOrigin, vStart, iMaterial, iDamageType, iHitbox, iEntIndex, tr ) ) + { + // Check for custom effects based on the Decal index + PerformCustomEffects( vOrigin, tr, vDir, iMaterial, 1.0 ); + } + + PlayImpactSound( pEntity, tr, vOrigin, nSurfaceProp ); +} + + +DECLARE_CLIENT_EFFECT( "Impact", TFCImpact ); diff --git a/game/client/tfc/tfc_hud_ammo.cpp b/game/client/tfc/tfc_hud_ammo.cpp new file mode 100644 index 0000000..70d57cf --- /dev/null +++ b/game/client/tfc/tfc_hud_ammo.cpp @@ -0,0 +1,355 @@ +//========= 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 "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; + + 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; + } +} + +//----------------------------------------------------------------------------- +// 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/tfc/tfc_hud_weaponselection.cpp b/game/client/tfc/tfc_hud_weaponselection.cpp new file mode 100644 index 0000000..886a9d0 --- /dev/null +++ b/game/client/tfc/tfc_hud_weaponselection.cpp @@ -0,0 +1,682 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "cbase.h" +#include "weapon_selection.h" +#include "iclientmode.h" +#include "history_resource.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" + +#include <string.h> + +//----------------------------------------------------------------------------- +// Purpose: cstrike 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); + + 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_flIconXPos, "IconXPos", "16", "proportional_float" ); + CPanelAnimationVarAliasType( float, m_flIconYPos, "IconYPos", "8", "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" ); + + CPanelAnimationVar( int, m_iMaxSlots, "MaxSlots", "6" ); + CPanelAnimationVar( bool, m_bPlaySelectionSounds, "PlaySelectSounds", "1" ); +}; + +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 ); +} + +//----------------------------------------------------------------------------- +// 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( HISTSLOT_WEAP, pWeapon ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: updates animation status +//----------------------------------------------------------------------------- +void CHudWeaponSelection::OnThink() +{ +} + +//----------------------------------------------------------------------------- +// 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(); + + m_iMaxSlots = clamp( m_iMaxSlots, 0, MAX_WEAPON_SLOTS ); +} + +//------------------------------------------------------------------------- +// 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 = (m_iMaxSlots - 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 < m_iMaxSlots; 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 selected weapon + DrawBox(xpos, ypos, largeBoxWide, largeBoxTall, selectedColor, m_flSelectionAlphaOverride, bFirstItem ? i + 1 : -1); + + // draw icon + Color col = GetFgColor(); + // icons use old system, drawing in screen space + if ( pWeapon->GetSpriteActive() ) + { + 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; + } + pWeapon->GetSpriteActive()->DrawSelf( xpos + m_flIconXPos, ypos + m_flIconYPos, 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; + { + for (wchar_t *pch = text; *pch != 0; pch++) + { + if (*pch == '\n') + { + // newline character, drop to the next line + if (slen > maxslen) + { + maxslen = slen; + } + slen = 0; + } + else if (*pch == '\r') + { + // do nothing + } + else + { + slen += surface()->GetCharacterWidth( m_hTextFont, *pch ); + charCount++; + } + } + } + if (slen > maxslen) + { + maxslen = slen; + } + + int tx = xpos + ((largeBoxWide - maxslen) / 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 +//----------------------------------------------------------------------------- +void CHudWeaponSelection::HideSelection( void ) +{ + CBaseHudWeaponSelection::HideSelection(); + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("CloseWeaponSelectionMenu"); +} + +//----------------------------------------------------------------------------- +// 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( hud_fastswitch.GetInt() > 0 ) + { + SelectWeapon(); + } + else if ( !IsInSelectionMode() ) + { + OpenSelection(); + } + + // Play the "cycle to next weapon" sound + if( m_bPlaySelectionSounds ) + 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( hud_fastswitch.GetInt() > 0 ) + { + SelectWeapon(); + } + else if ( !IsInSelectionMode() ) + { + OpenSelection(); + } + + // Play the "cycle to next weapon" sound + if( m_bPlaySelectionSounds ) + pPlayer->EmitSound( "Player.WeaponSelectionMoveSlot" ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: returns the weapon in the specified slot +//----------------------------------------------------------------------------- +C_BaseCombatWeapon *CHudWeaponSelection::GetWeaponInSlot( int iSlot, int iSlotPos ) +{ + C_BasePlayer *player = C_BasePlayer::GetLocalPlayer(); + if ( !player ) + return NULL; + + for ( int i = 0; i < MAX_WEAPONS; i++ ) + { + C_BaseCombatWeapon *pWeapon = player->GetWeapon(i); + + if ( pWeapon == NULL ) + continue; + + if ( pWeapon->GetSlot() == iSlot && pWeapon->GetPosition() == iSlotPos ) + return pWeapon; + } + + return NULL; +} + + +//----------------------------------------------------------------------------- +// Purpose: Moves selection to the specified slot +//----------------------------------------------------------------------------- +void CHudWeaponSelection::SelectWeaponSlot( int iSlot ) +{ + // iSlot is one higher than it should be, since it's the number key, not the 0-based index into the weapons + --iSlot; + + // Get the local player. + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + if ( !pPlayer ) + return; + + // Don't try and read past our possible number of slots + if ( iSlot > MAX_WEAPON_SLOTS ) + return; + + // Make sure the player's allowed to switch weapons + if ( pPlayer->IsAllowedToSwitchWeapons() == false ) + 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 ) + { + // Mark the change + SetSelectedWeapon( pActiveWeapon ); + + if( hud_fastswitch.GetInt() > 0 ) + { + SelectWeapon(); + } + else if ( !IsInSelectionMode() ) + { + // open the weapon selection + OpenSelection(); + } + } + + if( m_bPlaySelectionSounds ) + pPlayer->EmitSound( "Player.WeaponSelectionMoveSlot" ); +} diff --git a/game/client/tfc/tfc_in_main.cpp b/game/client/tfc/tfc_in_main.cpp new file mode 100644 index 0000000..ef8350a --- /dev/null +++ b/game/client/tfc/tfc_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 CTFCInput : public CInput +{ +public: +}; + +static CTFCInput g_Input; + +// Expose this interface +IInput *input = ( IInput * )&g_Input; + diff --git a/game/client/tfc/tfc_prediction.cpp b/game/client/tfc/tfc_prediction.cpp new file mode 100644 index 0000000..c9785b5 --- /dev/null +++ b/game/client/tfc/tfc_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 CTFCPrediction : public CPrediction +{ +DECLARE_CLASS( CTFCPrediction, 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 CTFCPrediction::SetupMove( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, + CMoveData *move ) +{ + // Call the default SetupMove code. + BaseClass::SetupMove( player, ucmd, pHelper, move ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFCPrediction::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 CTFCPrediction g_Prediction; + +EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CTFCPrediction, IPrediction, VCLIENT_PREDICTION_INTERFACE_VERSION, g_Prediction ); + +CPrediction *prediction = &g_Prediction; + diff --git a/game/client/tfc/vgui/tfcclassmenu.cpp b/game/client/tfc/vgui/tfcclassmenu.cpp new file mode 100644 index 0000000..5fb66c0 --- /dev/null +++ b/game/client/tfc/vgui/tfcclassmenu.cpp @@ -0,0 +1,61 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" +#include "tfcclassmenu.h" + +#include <KeyValues.h> +#include <filesystem.h> +#include <vgui_controls/Button.h> +#include <vgui/IVGui.h> + +#include "hud.h" // for gEngfuncs +#include "tfc_gamerules.h" +#include "viewport_panel_names.h" +#include "c_tfc_player.h" + + +using namespace vgui; + + +// ----------------------------------------------------------------------------- // +// CTFCClassMenu +// ----------------------------------------------------------------------------- // + +CTFCClassMenu::CTFCClassMenu(IViewPort *pViewPort) : CClassMenu(pViewPort) +{ +} + +const char *CTFCClassMenu::GetName( void ) +{ + return PANEL_CLASS; +} + +void CTFCClassMenu::ShowPanel(bool bShow) +{ + if ( bShow) + { + engine->CheckPoint( "ClassMenu" ); + } + + BaseClass::ShowPanel( bShow ); + +} + +void CTFCClassMenu::Update() +{ + // Force them to pick a class if they haven't picked one yet. + if ( C_TFCPlayer::GetLocalTFCPlayer()->m_Shared.GetPlayerClass() == PC_UNDEFINED ) + { + SetVisibleButton( "CancelButton", false ); + } + else + { + SetVisibleButton( "CancelButton", true ); + } +} + diff --git a/game/client/tfc/vgui/tfcclassmenu.h b/game/client/tfc/vgui/tfcclassmenu.h new file mode 100644 index 0000000..4d369c3 --- /dev/null +++ b/game/client/tfc/vgui/tfcclassmenu.h @@ -0,0 +1,42 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef TFCCLASSMENU_H +#define TFCCLASSMENU_H +#ifdef _WIN32 +#pragma once +#endif + +#include <classmenu.h> +#include <commandpanel.h> +#include <vgui_controls/EditablePanel.h> +#include <filesystem.h> +#include "tfc_shareddefs.h" +#include "cbase.h" +#include "tfc_gamerules.h" +#include "vgui_controls/ImagePanel.h" + + +//----------------------------------------------------------------------------- +// Purpose: Draws the Terrorist class menu +//----------------------------------------------------------------------------- + +class CTFCClassMenu : public CClassMenu +{ +private: + DECLARE_CLASS_SIMPLE( CTFCClassMenu, CClassMenu ); + +public: + CTFCClassMenu::CTFCClassMenu(IViewPort *pViewPort); + + const char *GetName( void ); + void ShowPanel(bool bShow); + void Update(); +}; + + +#endif // TFCCLASSMENU_H diff --git a/game/client/tfc/vgui/tfcteammenu.cpp b/game/client/tfc/vgui/tfcteammenu.cpp new file mode 100644 index 0000000..15847ee --- /dev/null +++ b/game/client/tfc/vgui/tfcteammenu.cpp @@ -0,0 +1,118 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" +#include "tfcteammenu.h" +#include <convar.h> +#include "hud.h" // for gEngfuncs +#include "c_tfc_player.h" +#include "tfc_gamerules.h" + +using namespace vgui; + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CTFCTeamMenu::CTFCTeamMenu(IViewPort *pViewPort) : CTeamMenu(pViewPort) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +CTFCTeamMenu::~CTFCTeamMenu() +{ +} + +void CTFCTeamMenu::ApplySettings(KeyValues *inResourceData) +{ + BaseClass::ApplySettings( inResourceData ); +} + +void CTFCTeamMenu::ShowPanel(bool bShow) +{ + if ( bShow ) + { + engine->CheckPoint( "TeamMenu" ); + } + + BaseClass::ShowPanel( bShow ); +} + +//----------------------------------------------------------------------------- +// Purpose: called to update the menu with new information +//----------------------------------------------------------------------------- +void CTFCTeamMenu::Update( void ) +{ + BaseClass::Update(); + + const ConVar *allowspecs = cvar->FindVar( "mp_allowspectators" ); + + if ( allowspecs && allowspecs->GetBool() ) + { + C_TFCPlayer *pPlayer = C_TFCPlayer::GetLocalTFCPlayer(); + if ( !pPlayer || !TFCGameRules() ) + return; + + // if we're not already a CT or T...or the freeze time isn't over yet...or we're dead + if ( pPlayer->GetTeamNumber() == TEAM_UNASSIGNED || + ( pPlayer && pPlayer->IsPlayerDead() ) ) + { + SetVisibleButton("specbutton", true); + } + else + { + SetVisibleButton("specbutton", false); + } + } + else + { + SetVisibleButton("specbutton", false ); + } + + char mapName[MAX_MAP_NAME]; + + Q_FileBase( engine->GetLevelName(), mapName, sizeof(mapName) ); + if( C_TFCPlayer::GetLocalTFCPlayer()->GetTeamNumber() == TEAM_UNASSIGNED ) // we aren't on a team yet + { + SetVisibleButton("CancelButton", false); + } + else + { + SetVisibleButton("CancelButton", true); + } +} + +//----------------------------------------------------------------------------- +// Purpose: When a team button is pressed it triggers this function to +// cause the player to join a team +//----------------------------------------------------------------------------- +void CTFCTeamMenu::OnCommand( const char *command ) +{ + if ( Q_stricmp( command, "vguicancel" ) ) + { + engine->ClientCmd( command ); + } + + + BaseClass::OnCommand(command); + + gViewPortInterface->ShowBackGround( false ); + OnClose(); +} + +//----------------------------------------------------------------------------- +// Purpose: Sets the visibility of a button by name +//----------------------------------------------------------------------------- +void CTFCTeamMenu::SetVisibleButton(const char *textEntryName, bool state) +{ + Button *entry = dynamic_cast<Button *>(FindChildByName(textEntryName)); + if (entry) + { + entry->SetVisible(state); + } +} diff --git a/game/client/tfc/vgui/tfcteammenu.h b/game/client/tfc/vgui/tfcteammenu.h new file mode 100644 index 0000000..3d31372 --- /dev/null +++ b/game/client/tfc/vgui/tfcteammenu.h @@ -0,0 +1,42 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef TFCTEAMMENU_H +#define TFCTEAMMENU_H +#ifdef _WIN32 +#pragma once +#endif + +#include <teammenu.h> + +//----------------------------------------------------------------------------- +// Purpose: Displays the team menu +//----------------------------------------------------------------------------- +class CTFCTeamMenu : public CTeamMenu +{ +private: + DECLARE_CLASS_SIMPLE( CTFCTeamMenu, CTeamMenu ); + +public: + CTFCTeamMenu(IViewPort *pViewPort); + ~CTFCTeamMenu(); + + virtual void ApplySettings( KeyValues *inResourceData ); + + void Update(); + void ShowPanel( bool bShow ); + +private: + enum { NUM_TEAMS = 3 }; + + // VGUI2 override + void OnCommand( const char *command); + // helper functions + void SetVisibleButton(const char *textEntryName, bool state); +}; + +#endif // TFCTEAMMENU_H diff --git a/game/client/tfc/vgui/tfcviewport.cpp b/game/client/tfc/vgui/tfcviewport.cpp new file mode 100644 index 0000000..92eaeb2 --- /dev/null +++ b/game/client/tfc/vgui/tfcviewport.cpp @@ -0,0 +1,96 @@ +//========= 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 "TFCViewport.h" +#include "tfcteammenu.h" + +#include "vguicenterprint.h" +#include "text_message.h" +#include "tfcclassmenu.h" + + + +// +// This is the main function of the viewport. Right here is where we create our class menu, +// team menu, and anything else that we want to turn on and off in the UI. +// +void TFCViewport::CreateDefaultPanels( void ) +{ + AddNewPanel( new CTFCTeamMenu( this ), "CTFCTeamMenu" ); + AddNewPanel( new CTFCClassMenu( this ), "CTFCClassMenu" ); + + BaseClass::CreateDefaultPanels(); +} + + +void TFCViewport::ApplySchemeSettings( vgui::IScheme *pScheme ) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + gHUD.InitColors( pScheme ); + + SetPaintBackgroundEnabled( false ); +} + + +IViewPortPanel* TFCViewport::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; +} + +int TFCViewport::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/tfc/vgui/tfcviewport.h b/game/client/tfc/vgui/tfcviewport.h new file mode 100644 index 0000000..625d452 --- /dev/null +++ b/game/client/tfc/vgui/tfcviewport.h @@ -0,0 +1,40 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef TFCVIEWPORT_H +#define TFCVIEWPORT_H + + +#include "tfc_shareddefs.h" +#include "baseviewport.h" + + +using namespace vgui; + +namespace vgui +{ + class Panel; +} + +class TFCViewport : public CBaseViewport +{ + +private: + DECLARE_CLASS_SIMPLE( TFCViewport, CBaseViewport ); + +public: + + IViewPortPanel* CreatePanelByName(const char *szPanelName); + void CreateDefaultPanels( void ); + + virtual void ApplySchemeSettings( vgui::IScheme *pScheme ); + + int GetDeathMessageStartHeight( void ); +}; + + +#endif // TFCViewport_H diff --git a/game/client/tfc/vgui/vgui_rootpanel_tfc.cpp b/game/client/tfc/vgui/vgui_rootpanel_tfc.cpp new file mode 100644 index 0000000..699a997 --- /dev/null +++ b/game/client/tfc/vgui/vgui_rootpanel_tfc.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_tfc.h" +#include "vgui/IVGui.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +C_TFCRootPanel *g_pRootPanel = NULL; + + +//----------------------------------------------------------------------------- +// Global functions. +//----------------------------------------------------------------------------- +void VGUI_CreateClientDLLRootPanel( void ) +{ + g_pRootPanel = new C_TFCRootPanel( enginevgui->GetPanel( PANEL_CLIENTDLL ) ); +} + +void VGUI_DestroyClientDLLRootPanel( void ) +{ + delete g_pRootPanel; + g_pRootPanel = NULL; +} + +vgui::VPANEL VGui_GetClientDLLRootPanel( void ) +{ + return g_pRootPanel->GetVPanel(); +} + + +//----------------------------------------------------------------------------- +// C_TFCRootPanel implementation. +//----------------------------------------------------------------------------- +C_TFCRootPanel::C_TFCRootPanel( vgui::VPANEL parent ) + : BaseClass( NULL, "TFC 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_TFCRootPanel::~C_TFCRootPanel( void ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_TFCRootPanel::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_TFCRootPanel::RenderPanelEffects( void ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_TFCRootPanel::OnTick( void ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: Reset effects on level load/shutdown +//----------------------------------------------------------------------------- +void C_TFCRootPanel::LevelInit( void ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_TFCRootPanel::LevelShutdown( void ) +{ +} + diff --git a/game/client/tfc/vgui/vgui_rootpanel_tfc.h b/game/client/tfc/vgui/vgui_rootpanel_tfc.h new file mode 100644 index 0000000..7ed80e3 --- /dev/null +++ b/game/client/tfc/vgui/vgui_rootpanel_tfc.h @@ -0,0 +1,56 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef VGUI_ROOTPANEL_TFC_H +#define VGUI_ROOTPANEL_TFC_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_TFCRootPanel : public vgui::Panel +{ + typedef vgui::Panel BaseClass; +public: + C_TFCRootPanel( vgui::VPANEL parent ); + virtual ~C_TFCRootPanel( 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_TFC_H |