diff options
Diffstat (limited to 'game/client/tf2/c_tf_hints.cpp')
| -rw-r--r-- | game/client/tf2/c_tf_hints.cpp | 1468 |
1 files changed, 1468 insertions, 0 deletions
diff --git a/game/client/tf2/c_tf_hints.cpp b/game/client/tf2/c_tf_hints.cpp new file mode 100644 index 0000000..b12ff20 --- /dev/null +++ b/game/client/tf2/c_tf_hints.cpp @@ -0,0 +1,1468 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// +#include "cbase.h" +#include "c_tf_basehint.h" +#include "tf_hints.h" +#include "hintitemorderbase.h" +#include "iclientmode.h" +#include "clientmode_commander.h" +#include "hud_technologytreedoc.h" +#include "paneleffect.h" +#include "techtree.h" +#include "hintitemobjectbase.h" +#include "c_order.h" +#include "c_basetfplayer.h" +#include "weapon_selection.h" +#include <KeyValues.h> +#include "c_weapon_builder.h" +#include "VGuiMatSurface/IMatSystemSurface.h" +#include "c_tf_hints.h" +#include "c_hint_events.h" +#include "c_tf_hintmanager.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +// Class Hierarchy +// CHintItemBase -- base class for hint items +// CHintItemOrderBase -- base class for hints derived from orders ( know how to draw +// a white line from the hint to the order panel ) +// CHintItemObjectBase -- base class for hints that care about another object ( stores the object type name ) +// CHintGotoObject -- Contains logic that relates to the other object +// CHintWaitBuilding +// CHintChangeToCommander -- first level hint, doesn't rely on object, but does rely on UI manipulation +// CHintChooseAnyTechnology -- doesn't try to draw line to order since it's in tactical view? +// + + +//----------------------------------------------------------------------------- +// Purpose: Change to commander view hint +//----------------------------------------------------------------------------- +class CHintChangeToCommander : public CHintItemOrderBase +{ + DECLARE_CLASS( CHintChangeToCommander, CHintItemOrderBase ); + +public: + CHintChangeToCommander( vgui::Panel *parent, const char *panelName ); + virtual void Think( void ); +}; + +DECLARE_HINTITEMFACTORY( CHintChangeToCommander ) + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *parent - +// *panelName - +// *text - +// itemwidth - +//----------------------------------------------------------------------------- +CHintChangeToCommander::CHintChangeToCommander( vgui::Panel *parent, const char *panelName ) +: BaseClass( parent, panelName ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: Set completed flag if we've made it to commander mode +// Output : virtual void +//----------------------------------------------------------------------------- +void CHintChangeToCommander::Think( void ) +{ + BaseClass::Think(); + + if ( g_pClientMode == ClientModeCommander() ) + { + m_bCompleted = true; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +class CHintGotoObject : public CHintItemObjectBase +{ + DECLARE_CLASS( CHintGotoObject, CHintItemObjectBase ); + +public: + CHintGotoObject( vgui::Panel *parent, const char *panelName ); + virtual void Think( void ); + +private: + enum + { + MAX_OBJECT_TYPE = 128, + }; + + EFFECT_HANDLE m_ArrowEffect; + + float m_flNextDistanceCheck; + IClientMode *m_pPreviousMode; +}; + +DECLARE_HINTITEMFACTORY( CHintGotoObject ) + +#define ZONE_DISTANCE_CHECK_INTERVAL 0.5f + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *parent - +// *panelName - +//----------------------------------------------------------------------------- +CHintGotoObject::CHintGotoObject( vgui::Panel *parent, const char *panelName ) + : BaseClass( parent, panelName ) +{ + m_ArrowEffect = CreateArrowEffect( this, parent, NULL ); + + m_flNextDistanceCheck = 0.0f; + + m_pPreviousMode = NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHintGotoObject::Think( void ) +{ + BaseClass::Think(); + + ClientModeTFBase *basemode = ( ClientModeTFBase * )g_pClientMode; + CMinimapPanel *minimap = basemode->GetMinimap(); + + CPanelEffect *e = g_pTF2RootPanel->FindEffect( m_ArrowEffect ); + if ( e && minimap ) + { + e->SetPanelOther( minimap ); + } + + // Check right away if we switch modes + if ( g_pClientMode != m_pPreviousMode ) + { + m_flNextDistanceCheck = 0.0f; + m_pPreviousMode = g_pClientMode; + } + + if ( gpGlobals->curtime < m_flNextDistanceCheck ) + { + return; + } + + m_flNextDistanceCheck = gpGlobals->curtime + ZONE_DISTANCE_CHECK_INTERVAL; + + // The order contains the resource zone target + C_TFBaseHint *hint = static_cast< C_TFBaseHint * >( GetParent() ); + if ( hint ) + { + C_Order *order = dynamic_cast< C_Order * >( ClientEntityList().GetEnt( hint->GetEntity() ) ); + if ( order ) + { + C_BaseEntity *pTarget = ClientEntityList().GetEnt( order->GetTarget() ); + if ( IsObjectOfType( pTarget ) ) + { + Vector zonecenter = pTarget->WorldSpaceCenter( ); + + if ( e && minimap ) + { + float mapx, mapy; + + // Convert target center to map position + CMinimapPanel::MinimapPanel()->WorldToMinimap( MINIMAP_CLIP, zonecenter, mapx, mapy ); + + e->SetUsingOffset( true, (int)mapx, (int)mapy ); + } + + Vector delta; + + C_BaseTFPlayer *local = C_BaseTFPlayer::GetLocalPlayer(); + if ( local ) + { + delta = local->GetAbsOrigin() - zonecenter; + if ( delta.Length() < 256.0f ) + { + m_bCompleted = true; + } + } + } + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +class CHintDeployWeapon : public CHintItemOrderBase +{ + DECLARE_CLASS( CHintDeployWeapon, CHintItemOrderBase ); + +public: + CHintDeployWeapon( vgui::Panel *parent, const char *panelName ); + + virtual void Think( void ); + + virtual void SetWeaponType( const char *type ); + virtual char const *GetWeaponType( void ); + + virtual char const *GetKeyName( void ); + + virtual void SetPrintName( const char *name ); + virtual char const *GetPrintName( void ); + + virtual void ParseItem( KeyValues *pKeyValues ); + + virtual bool CheckKeyAndValue( const char *instring, int* keylength, const char **ppOutstring ); + +private: + enum + { + MAX_WEAPON_TYPE = 128, + MAX_WEAPON_NAME = 128, + }; + + char m_szWeaponType[ MAX_WEAPON_TYPE ]; + char m_szPrintName[ MAX_WEAPON_NAME ]; +}; + +DECLARE_HINTITEMFACTORY( CHintDeployWeapon ) + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *parent - +// *panelName - +//----------------------------------------------------------------------------- +CHintDeployWeapon::CHintDeployWeapon( vgui::Panel *parent, const char *panelName ) +: BaseClass( parent, panelName ) +{ + SetWeaponType( "" ); + SetPrintName( "" ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *instring - +// keylength - +// **ppOutstring - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CHintDeployWeapon::CheckKeyAndValue( const char *instring, int* keylength, const char **ppOutstring ) +{ + if ( !Q_strnicmp( instring, "keyname", strlen( "keyname" ) ) ) + { + *keylength = strlen( "keyname" ); + *ppOutstring = GetKeyName(); + return true; + } + else if ( !Q_strnicmp( instring, "printname", strlen( "printname" ) ) ) + { + *keylength = strlen( "printname" ); + *ppOutstring = GetPrintName(); + return true; + } + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *type - +//----------------------------------------------------------------------------- +void CHintDeployWeapon::SetWeaponType( const char *type ) +{ + Q_strncpy( m_szWeaponType, type, MAX_WEAPON_TYPE ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : char const +//----------------------------------------------------------------------------- +const char *CHintDeployWeapon::GetWeaponType( void ) +{ + return m_szWeaponType; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *name - +//----------------------------------------------------------------------------- +void CHintDeployWeapon::SetPrintName( const char *name ) +{ + Q_strncpy( m_szPrintName, name, MAX_WEAPON_NAME ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : char const +//----------------------------------------------------------------------------- +const char *CHintDeployWeapon::GetPrintName( void ) +{ + return m_szPrintName; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : char const +//----------------------------------------------------------------------------- +const char *CHintDeployWeapon::GetKeyName( void ) +{ + static char keyname[ 128 ]; + + keyname[ 0 ] = 0; + + CBaseHudWeaponSelection *pHudSelection = GetHudWeaponSelection(); + if ( pHudSelection ) + { + C_BasePlayer *player = C_BasePlayer::GetLocalPlayer(); + if ( player ) + { + for ( int slot = 0; slot < MAX_WEAPON_SLOTS; slot++ ) + { + C_BaseCombatWeapon *weapon = pHudSelection->GetFirstPos( slot ); + if ( !weapon ) + continue; + + if ( !stricmp( weapon->GetName(), GetWeaponType() ) ) + { + Q_snprintf( keyname, sizeof( keyname ), GetKeyNameForBinding( VarArgs( "slot%i", slot + 1 ) ) ); + break; + } + } + } + } + + return keyname; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pKeyValues - +//----------------------------------------------------------------------------- +void CHintDeployWeapon::ParseItem( KeyValues *pKeyValues ) +{ + BaseClass::ParseItem( pKeyValues ); + + const char *type = pKeyValues->GetString( "weapon", "" ); + if ( type ) + { + SetWeaponType( type ); + } + + const char *printname = pKeyValues->GetString( "printname", "" ); + if ( printname ) + { + SetPrintName( printname ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHintDeployWeapon::Think( void ) +{ + BaseClass::Think(); + + C_BaseTFPlayer *player = C_BaseTFPlayer::GetLocalPlayer(); + if ( !player ) + return; + + // Get the weapon selection Hud Element + CBaseHudWeaponSelection *pHudSelection = GetHudWeaponSelection(); + // Make sure it's not still active + if ( pHudSelection->IsActive() ) + return; + + C_BaseCombatWeapon *weapon = GetActiveWeapon(); + if ( !weapon ) + return; + + if ( !stricmp( weapon->GetClientClass()->m_pNetworkName, "CWeaponBuilder" ) ) + { + m_bCompleted = true; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +class CHintStartPlacing : public CHintItemOrderBase +{ + DECLARE_CLASS( CHintStartPlacing, CHintItemOrderBase ); + +public: + CHintStartPlacing( vgui::Panel *parent, const char *panelName ); + + virtual void Think( void ); +private: +}; + +DECLARE_HINTITEMFACTORY( CHintStartPlacing ) + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *parent - +// *panelName - +//----------------------------------------------------------------------------- +CHintStartPlacing::CHintStartPlacing( vgui::Panel *parent, const char *panelName ) +: BaseClass( parent, panelName ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHintStartPlacing::Think( void ) +{ + BaseClass::Think(); + + C_WeaponBuilder *builder = dynamic_cast< C_WeaponBuilder * >( GetActiveWeapon() ); + if ( builder && builder->IsPlacingObject() ) + { + m_bCompleted = true; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +class CHintStartBuilding : public CHintItemOrderBase +{ + DECLARE_CLASS( CHintStartBuilding, CHintItemOrderBase ); + +public: + CHintStartBuilding( vgui::Panel *parent, const char *panelName ); + + virtual void Think( void ); +private: +}; + +DECLARE_HINTITEMFACTORY( CHintStartBuilding ) + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *parent - +// *panelName - +//----------------------------------------------------------------------------- +CHintStartBuilding::CHintStartBuilding( vgui::Panel *parent, const char *panelName ) + : BaseClass( parent, panelName ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHintStartBuilding::Think( void ) +{ + BaseClass::Think(); + + C_WeaponBuilder *builder = dynamic_cast< C_WeaponBuilder * >( GetActiveWeapon() ); + if ( builder && builder->IsBuildingObject() ) + { + m_bCompleted = true; + } +} + +#define CHECK_FOR_BUILDING_INTERVAL 1.0f + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +class CHintWaitBuilding : public CHintItemObjectBase +{ + DECLARE_CLASS( CHintWaitBuilding, CHintItemObjectBase ); + +public: + CHintWaitBuilding( vgui::Panel *parent, const char *panelName ); + + virtual void Think( void ); +private: + + float m_flNextCheck; +}; + + +DECLARE_HINTITEMFACTORY( CHintWaitBuilding ) + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *parent - +// *panelName - +//----------------------------------------------------------------------------- +CHintWaitBuilding::CHintWaitBuilding( vgui::Panel *parent, const char *panelName ) + : BaseClass( parent, panelName ) +{ + m_flNextCheck = 0.0f; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHintWaitBuilding::Think( void ) +{ + BaseClass::Think(); + + if ( !GetActive() ) + return; + + C_BaseTFPlayer *player = C_BaseTFPlayer::GetLocalPlayer(); + if ( !player ) + return; + + if ( gpGlobals->curtime < m_flNextCheck ) + return; + + m_flNextCheck = gpGlobals->curtime + CHECK_FOR_BUILDING_INTERVAL; + + // Find resource zone + ClientEntityHandle_t e = ClientEntityList().FirstHandle(); + for ( ; e != ClientEntityList().InvalidHandle(); e = ClientEntityList().NextHandle( e ) ) + { + C_BaseEntity *ent = C_BaseEntity::Instance( e ); + if ( !ent ) + continue; + + if ( IsObjectOfType( ent ) ) + { + C_BaseObject *obj = static_cast< C_BaseObject * >( ent ); + + Assert( obj ); + + if ( obj->GetTeamNumber() == player->GetTeamNumber() && obj->IsOwnedByLocalPlayer() ) + { + m_bCompleted = true; + break; + } + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +class CHintBuilderSelection : public CHintItemOrderBase +{ + DECLARE_CLASS( CHintBuilderSelection, CHintItemOrderBase ); + +public: + CHintBuilderSelection( vgui::Panel *parent, const char *panelName ); + + virtual void Think( void ); + virtual void SetSelection( const char *type ); + virtual char const *GetSelection( void ); + + virtual void ParseItem( KeyValues *pKeyValues ); + + virtual bool CheckKeyAndValue( const char *instring, int* keylength, const char **ppOutstring ); + +private: + enum + { + MAX_SELECTION_NAME = 128, + }; + + char m_szSelection[ MAX_SELECTION_NAME ]; +}; + +DECLARE_HINTITEMFACTORY( CHintBuilderSelection ) + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *parent - +// *panelName - +//----------------------------------------------------------------------------- +CHintBuilderSelection::CHintBuilderSelection( vgui::Panel *parent, const char *panelName ) + : BaseClass( parent, panelName ) +{ + SetSelection( "" ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *instring - +// keylength - +// **ppOutstring - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CHintBuilderSelection::CheckKeyAndValue( const char *instring, int* keylength, const char **ppOutstring ) +{ + if ( !Q_strnicmp( instring, "selection", strlen( "selection" ) ) ) + { + *keylength = strlen( "selection" ); + *ppOutstring = GetSelection(); + return true; + } + + return BaseClass::CheckKeyAndValue( instring, keylength, ppOutstring ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *selection - +//----------------------------------------------------------------------------- +void CHintBuilderSelection::SetSelection( const char *selection ) +{ + Q_strncpy( m_szSelection, selection, MAX_SELECTION_NAME ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : char const +//----------------------------------------------------------------------------- +const char *CHintBuilderSelection::GetSelection( void ) +{ + return m_szSelection; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pKeyValues - +//----------------------------------------------------------------------------- +void CHintBuilderSelection::ParseItem( KeyValues *pKeyValues ) +{ + BaseClass::ParseItem( pKeyValues ); + + const char *selection = pKeyValues->GetString( "selection", "" ); + if ( selection ) + { + SetSelection( selection ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHintBuilderSelection::Think( void ) +{ + BaseClass::Think(); + + C_BaseTFPlayer *player = C_BaseTFPlayer::GetLocalPlayer(); + if ( !player ) + return; + + C_WeaponBuilder *builder = dynamic_cast< C_WeaponBuilder * >( GetActiveWeapon() ); + if ( !builder ) + return; + + const char *selection = builder->GetCurrentSelectionObjectName(); + if ( !selection ) + return; + + if ( !stricmp( selection, GetSelection() ) ) + { + m_bCompleted = true; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +class CHintBuilderStartAction : public CHintItemOrderBase +{ + DECLARE_CLASS( CHintBuilderStartAction, CHintItemOrderBase ); + +public: + CHintBuilderStartAction( vgui::Panel *parent, const char *panelName ); + + virtual void Think( void ); + virtual void SetAction( const char *type ); + virtual char const *GetAction( void ); + + virtual void ParseItem( KeyValues *pKeyValues ); + + virtual bool CheckKeyAndValue( const char *instring, int* keylength, const char **ppOutstring ); + +private: + enum + { + MAX_ACTION_NAME = 128, + }; + + char m_szAction[ MAX_ACTION_NAME ]; +}; + +DECLARE_HINTITEMFACTORY( CHintBuilderStartAction ) + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *parent - +// *panelName - +//----------------------------------------------------------------------------- +CHintBuilderStartAction::CHintBuilderStartAction( vgui::Panel *parent, const char *panelName ) + : BaseClass( parent, panelName ) +{ + SetAction( "" ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *instring - +// keylength - +// **ppOutstring - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CHintBuilderStartAction::CheckKeyAndValue( const char *instring, int* keylength, const char **ppOutstring ) +{ + if ( !Q_strnicmp( instring, "action", strlen( "action" ) ) ) + { + *keylength = strlen( "action" ); + *ppOutstring = GetAction(); + return true; + } + + return BaseClass::CheckKeyAndValue( instring, keylength, ppOutstring ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *action - +//----------------------------------------------------------------------------- +void CHintBuilderStartAction::SetAction( const char *action ) +{ + Q_strncpy( m_szAction, action, MAX_ACTION_NAME ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : char const +//----------------------------------------------------------------------------- +const char *CHintBuilderStartAction::GetAction( void ) +{ + return m_szAction; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pKeyValues - +//----------------------------------------------------------------------------- +void CHintBuilderStartAction::ParseItem( KeyValues *pKeyValues ) +{ + BaseClass::ParseItem( pKeyValues ); + + const char *action = pKeyValues->GetString( "action", "" ); + if ( action ) + { + SetAction( action ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHintBuilderStartAction::Think( void ) +{ + BaseClass::Think(); + + C_BaseTFPlayer *player = C_BaseTFPlayer::GetLocalPlayer(); + if ( !player ) + return; + + C_WeaponBuilder *builder = dynamic_cast< C_WeaponBuilder * >( GetActiveWeapon() ); + if ( !builder ) + return; +} + +//----------------------------------------------------------------------------- +// Purpose: A fake hud element used to force the weapon hud element to draw when it's +// not actually active +//----------------------------------------------------------------------------- +class CHudWeaponFlashHelper : public CHudElement, public vgui::Panel +{ + DECLARE_CLASS_SIMPLE( CHudWeaponFlashHelper, vgui::Panel ); +public: + CHudWeaponFlashHelper( const char *name ); + + virtual void Init( void ); + virtual bool ShouldDraw( void ); + virtual void Paint(); + virtual void ApplySchemeSettings( vgui::IScheme *scheme ); + + // Associate a weapon + void SetFlashWeapon( C_BaseCombatWeapon *weapon ); + + // Start/stop flashing + void StartFlashing( void ); + void StopFlashing( void ); + + // Get position of weapon icon + void GetWeaponIconBounds( C_BaseCombatWeapon *weapon, int& x, int& y, int& w, int& h ); + + // Is player using the regular weapon selection UI? + bool IsWeaponSelectionActive( void ); + +private: + + // Currently flashing + bool m_bFlashing; + + // The weapon to highlight + EHANDLE m_hWeapon; + + // The actual weapon selection hud element + CBaseHudWeaponSelection *m_pWeaponSelection; +}; + +DECLARE_HUDELEMENT( CHudWeaponFlashHelper ) + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *name - +//----------------------------------------------------------------------------- +CHudWeaponFlashHelper::CHudWeaponFlashHelper( const char *name ) + : CHudElement( name ), BaseClass( NULL, "HudWeaponFlashHelper" ) +{ + vgui::Panel *pParent = g_pClientMode->GetViewport(); + SetParent( pParent ); + + m_bFlashing = false; + m_pWeaponSelection = NULL; + + SetHiddenBits( HIDEHUD_MISCSTATUS | HIDEHUD_PLAYERDEAD ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHudWeaponFlashHelper::Init( void ) +{ + CHudElement::Init(); + + m_pWeaponSelection = GetHudWeaponSelection(); + Assert( m_pWeaponSelection ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CHudWeaponFlashHelper::ShouldDraw( void ) +{ + return ( CHudElement::ShouldDraw() && m_bFlashing && m_pWeaponSelection ); +} + +void CHudWeaponFlashHelper::ApplySchemeSettings( vgui::IScheme *scheme ) +{ + BaseClass::ApplySchemeSettings( scheme ); + + SetPaintBackgroundEnabled( false ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHudWeaponFlashHelper::Paint() +{ + // Stop immediately if user starts to choose weapons + if ( m_pWeaponSelection->IsActive() ) + { + StopFlashing(); + return; + } + + if ( g_pClientMode == ClientModeCommander() ) + return; + + C_BaseCombatWeapon *w = ( C_BaseCombatWeapon * )( (C_BaseEntity *)m_hWeapon ); + if ( !w ) + return; + + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + if ( !pPlayer ) + return; + + // Redo drawing of Weapon Menu + m_pWeaponSelection->DrawWList( pPlayer, w, true, EFFECT_R, EFFECT_G, EFFECT_B, EFFECT_A ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *weapon - +//----------------------------------------------------------------------------- +void CHudWeaponFlashHelper::SetFlashWeapon( C_BaseCombatWeapon *weapon ) +{ + m_hWeapon = weapon; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHudWeaponFlashHelper::StartFlashing( void ) +{ + m_bFlashing = true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHudWeaponFlashHelper::StopFlashing( void ) +{ + m_bFlashing = false; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *weapon - +// x - +// y - +// w - +// h - +//----------------------------------------------------------------------------- +void CHudWeaponFlashHelper::GetWeaponIconBounds( C_BaseCombatWeapon *weapon, int& x, int& y,int& w, int& h ) +{ + x = y = w = h = 0; + + if ( !m_pWeaponSelection || !weapon ) + return; + + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + if ( !pPlayer ) + { + return; + } + + wrect_t outrect; + if ( !m_pWeaponSelection->ComputeRect( pPlayer, weapon, &outrect ) ) + return; + + x = outrect.left; + y = outrect.top; + w = outrect.right - outrect.left; + h = outrect.bottom - outrect.top; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CHudWeaponFlashHelper::IsWeaponSelectionActive( void ) +{ + if ( m_pWeaponSelection && m_pWeaponSelection->IsActive() ) + return true; + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: Change to commander view hint +//----------------------------------------------------------------------------- +class CHintHudWeaponFlash : public CHintItemBase +{ + DECLARE_CLASS( CHintHudWeaponFlash, CHintItemBase ); + +public: + CHintHudWeaponFlash( vgui::Panel *parent, const char *panelName ); + ~CHintHudWeaponFlash( void ); + + virtual void SetKeyValue( const char *key, const char *value ); + + void SetWeaponName( const char *name ); + char const *GetWeaponName( void ); + + virtual bool CheckKeyAndValue( const char *instring, int* keylength, const char **ppOutstring ); + + virtual void SetActive( bool bActive ); + + virtual void Think( void ); + +private: + C_BaseCombatWeapon *GetWeaponOfType( const char *type ); + + enum + { + MAX_WEAPON_NAME = 128, + }; + + bool m_bWeaponSet; + + EHANDLE m_hWeapon; + + char m_szWeaponName[ MAX_WEAPON_NAME ]; + + CHudWeaponFlashHelper *m_pWeaponFlashHelper; + + EFFECT_HANDLE m_hLineEffect; +}; + +DECLARE_HINTITEMFACTORY( CHintHudWeaponFlash ) + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *parent - +// *panelName - +// *text - +// itemwidth - +//----------------------------------------------------------------------------- +CHintHudWeaponFlash::CHintHudWeaponFlash( vgui::Panel *parent, const char *panelName ) +: BaseClass( parent, panelName ) +{ + m_bWeaponSet = false; + SetWeaponName( "" ); + m_pWeaponFlashHelper = NULL; + m_hLineEffect = EFFECT_INVALID_HANDLE; + + CreateFlashEffect( this, parent ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CHintHudWeaponFlash::~CHintHudWeaponFlash( void ) +{ + if ( m_pWeaponFlashHelper ) + { + m_pWeaponFlashHelper->StopFlashing(); + m_pWeaponFlashHelper->SetFlashWeapon( NULL ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *instring - +// keylength - +// **ppOutstring - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CHintHudWeaponFlash::CheckKeyAndValue( const char *instring, int* keylength, const char **ppOutstring ) +{ + if ( !Q_strnicmp( instring, "weapon", strlen( "weapon" ) ) ) + { + *keylength = strlen( "weapon" ); + *ppOutstring = GetWeaponName(); + return true; + } + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : char const +//----------------------------------------------------------------------------- +C_BaseCombatWeapon *CHintHudWeaponFlash::GetWeaponOfType( const char *type ) +{ + CBaseHudWeaponSelection *pHudSelection = GetHudWeaponSelection(); + if ( !pHudSelection ) + return NULL; + + C_BasePlayer *player = C_BasePlayer::GetLocalPlayer(); + if ( player ) + { + for ( int slot = 0; slot < MAX_WEAPON_SLOTS; slot++ ) + { + for ( int iPos = 0; iPos < MAX_WEAPON_POSITIONS; iPos++ ) + { + C_BaseCombatWeapon *weapon = pHudSelection->GetWeaponInSlot( slot, iPos ); + if ( !weapon ) + continue; + + if ( !stricmp( weapon->GetName(), type ) ) + { + return weapon; + } + } + } + } + + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *key - +// *value - +//----------------------------------------------------------------------------- +void CHintHudWeaponFlash::SetKeyValue( const char *key, const char *value ) +{ + BaseClass::SetKeyValue( key, value ); + + if ( !stricmp( key, "weapon" ) ) + { + SetWeaponName( value ); + + ComputeTitle(); + } + else if ( !stricmp( key, "weapontype" ) ) + { + // Find the weapon itself + C_BaseCombatWeapon *w = GetWeaponOfType( value ); + if ( w ) + { + m_hWeapon = w; + + // Create open up hud effect, etc. + m_pWeaponFlashHelper = GET_HUDELEMENT( CHudWeaponFlashHelper ); + if ( m_pWeaponFlashHelper ) + { + m_pWeaponFlashHelper->SetFlashWeapon( w ); + + int x, y, wide, tall; + + m_pWeaponFlashHelper->GetWeaponIconBounds( w, x, y, wide, tall ); + + C_TFBaseHint *hint = static_cast< C_TFBaseHint * >( GetParent() ); + + m_hLineEffect = CreateAxialLineEffectToRect( this, hint, x, y, wide, tall ); + + hint->SetDesiredPosition( x, y + tall + 50 ); + } + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHintHudWeaponFlash::Think( void ) +{ + BaseClass::Think(); + + if ( !m_pWeaponFlashHelper ) + return; + + if ( m_pWeaponFlashHelper->IsWeaponSelectionActive() ) + { + m_bCompleted = true; + } + + bool incommander = ( g_pClientMode == ClientModeCommander() ); + + CPanelEffect *effect = g_pTF2RootPanel->FindEffect( m_hLineEffect ); + if ( effect ) + { + effect->SetVisible( !incommander ); + + C_BaseCombatWeapon *w = static_cast< C_BaseCombatWeapon * >( ( C_BaseEntity * )m_hWeapon ); + + // Update target rectangle + if ( w ) + { + int x, y, wide, tall; + + m_pWeaponFlashHelper->GetWeaponIconBounds( w, x, y, wide, tall ); + + effect->SetTargetRect( x, y, wide, tall ); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : bActive - +//----------------------------------------------------------------------------- +void CHintHudWeaponFlash::SetActive( bool bActive ) +{ + BaseClass::SetActive( bActive ); + + if ( !m_pWeaponFlashHelper ) + return; + + if ( bActive ) + { + m_pWeaponFlashHelper->StartFlashing(); + } + else + { + m_pWeaponFlashHelper->StopFlashing(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *name - +//----------------------------------------------------------------------------- +void CHintHudWeaponFlash::SetWeaponName( const char *name ) +{ + Q_strncpy( m_szWeaponName, name, MAX_WEAPON_NAME ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : char const +//----------------------------------------------------------------------------- +const char *CHintHudWeaponFlash::GetWeaponName( void ) +{ + return m_szWeaponName; +} + + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +struct FUNCTIONLIST_t +{ + const char *name; + HINTCOMPLETIONFUNCTION pfn; +}; + +static FUNCTIONLIST_t g_CompletionFunctions[]= +{ + { NULL, NULL }, +}; + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *name - +// Output : HINTCOMPLETIONFUNCTION +//----------------------------------------------------------------------------- +HINTCOMPLETIONFUNCTION LookupCompletionFunction( const char *name ) +{ + int i = 0; + while ( 1 ) + { + FUNCTIONLIST_t *f = &g_CompletionFunctions[ i ]; + if ( !f->name ) + break; + + if ( !stricmp( f->name, name ) ) + { + return f->pfn; + } + i++; + } + + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +struct HINTITEM_t +{ + const char *name; + CHintItemBase *( *pfn )( vgui::Panel *parent, const char *name ); +}; + +static HINTITEM_t g_HintItems[]= +{ + { "CHintChangeToCommander", GET_HINTITEMFACTORY_NAME( CHintChangeToCommander ) }, + { "CHintGotoObject", GET_HINTITEMFACTORY_NAME( CHintGotoObject ) }, + { "CHintDeployWeapon", GET_HINTITEMFACTORY_NAME( CHintDeployWeapon ) }, + { "CHintStartPlacing", GET_HINTITEMFACTORY_NAME( CHintStartPlacing ) }, + { "CHintStartBuilding", GET_HINTITEMFACTORY_NAME( CHintStartBuilding ) }, + { "CHintWaitBuilding", GET_HINTITEMFACTORY_NAME( CHintWaitBuilding ) }, + { "CHintBuilderSelection", GET_HINTITEMFACTORY_NAME( CHintBuilderSelection ) }, + { "CHintBuilderStartAction", GET_HINTITEMFACTORY_NAME( CHintBuilderStartAction ) }, + { "CHintHudWeaponFlash", GET_HINTITEMFACTORY_NAME( CHintHudWeaponFlash ) }, + { NULL, NULL }, +}; + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *parent - +// *name - +// Output : CHintItemBase +//----------------------------------------------------------------------------- +CHintItemBase *CreateHintItem( vgui::Panel *parent, const char *name ) +{ + int i = 0; + while ( 1 ) + { + HINTITEM_t *hi = &g_HintItems[ i ]; + if ( !hi->name ) + break; + + if ( !stricmp( hi->name, name ) ) + { + if ( hi->pfn ) + { + return (*hi->pfn)( parent, name ); + } + else + { + Assert( !"Missing function pointer in CreateHintItem table!" ); + return NULL; + } + } + i++; + } + + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- + +CHintData g_HintDatas[] = +{ + // Vote + { "TF_HINT_VOTEFORTECHNOLOGY", TF_HINT_VOTEFORTECHNOLOGY, 0, NULL, -1 }, + + // Build + { "TF_HINT_BUILDRESOURCEPUMP", TF_HINT_BUILDRESOURCEPUMP, 0, HintEventFn_BuildObject, OBJ_RESOURCEPUMP }, + { "TF_HINT_BUILDSENTRYGUN_PLASMA", TF_HINT_BUILDSENTRYGUN_PLASMA, 0, HintEventFn_BuildObject, OBJ_SENTRYGUN_PLASMA }, + + // Object interaction + { "TF_HINT_REPAIROBJECT", TF_HINT_REPAIROBJECT, 0, NULL, -1 }, + + // Technology discovery + { "TF_HINT_NEWTECHNOLOGY", TF_HINT_NEWTECHNOLOGY, 0, NULL, -1 }, + { "TF_HINT_WEAPONRECEIVED", TF_HINT_WEAPONRECEIVED, 0, NULL, -1 }, + + // Sentinal + { NULL, 0, 0, NULL, -1 }, +}; + + +int GetNumHintDatas() +{ + return ARRAYSIZE( g_HintDatas ); +} + + +CHintData* GetHintData( int i ) +{ + return &g_HintDatas[i]; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : id - +// Output : char const +//----------------------------------------------------------------------------- +const char *LookupHintName( int id ) +{ + int i = 0; + while ( 1 ) + { + CHintData *h = &g_HintDatas[ i ]; + if ( !h->name ) + break; + + if ( h->id == id ) + { + return h->name; + } + + i++; + } + + return NULL; +} + +DECLARE_HINTFACTORY( C_TFBaseHint ) + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +typedef struct +{ + const char *name; + C_TFBaseHint *( *pfn )( int id, int entity ); +} +HINT_t; + +static HINT_t g_Hints[]= +{ + { "C_TFBaseHint", GET_HINTFACTORY_NAME( C_TFBaseHint ) }, + { NULL, NULL }, +}; + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *name - +// id - +// entity - +// Output : C_TFBaseHint +//----------------------------------------------------------------------------- +C_TFBaseHint *FactoryCreateHint( const char *name, int id, int entity ) +{ + int i = 0; + while ( 1 ) + { + HINT_t *hi = &g_Hints[ i ]; + if ( !hi->name ) + break; + + if ( !stricmp( hi->name, name ) ) + { + if ( hi->pfn ) + { + return (*hi->pfn)( id, entity ); + } + else + { + Assert( !"Missing function pointer in FactoryCreateHint table!" ); + return NULL; + } + } + i++; + } + + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: Generic factory for hints +// Input : id - +// entity - +// Output : C_TFBaseHint +//----------------------------------------------------------------------------- +C_TFBaseHint *C_TFBaseHint::CreateHint( int id, const char *subsection, int entity ) +{ + C_TFBaseHint *hint = NULL; + const char *hintname = LookupHintName( id ); + if ( !hintname ) + return NULL; + + // See if we should see this hint any more + KeyValues *pkvStats = GetHintDisplayStats(); + if ( pkvStats ) + { + KeyValues *pkvStatSection = pkvStats->FindKey( hintname, true ); + if ( pkvStatSection ) + { + if ( subsection && subsection[0] ) + { + pkvStatSection = pkvStatSection->FindKey( subsection, true ); + } + } + + if ( !pkvStatSection ) + { + Assert( !"C_TFBaseHint::CreateHint: Problem creating hint subsection" ); + return NULL; + } + + int times_shown = pkvStatSection->GetInt( "times_shown", 0 ); + pkvStatSection->SetString( "times_shown", VarArgs( "%i", times_shown ) ); + + int times_max = pkvStatSection->GetInt( "times_max", 3 ); + pkvStatSection->SetString( "times_max", VarArgs( "%i", times_max ) ); + + if ( times_shown >= times_max ) + return NULL; + + // Remember that we've seen it again + times_shown++; + pkvStatSection->SetString( "times_shown", VarArgs( "%i", times_shown ) ); + } + + // Ask Hint manager API for key values + KeyValues *pkvHintSystem = GetHintKeyValues(); + if ( pkvHintSystem ) + { + // + // Parse the list of hints looking for name + KeyValues *pkvHint = pkvHintSystem->FindKey( hintname ); + if ( pkvHint ) + { + // Use classname string to construct hint + const char *defaultclass = "C_TFBaseHint"; + const char *classname = pkvHint->GetString( "classname" ); + if ( !classname || !classname[ 0 ] || !stricmp( classname, "default" ) ) + { + classname = defaultclass; + } + + hint = FactoryCreateHint( classname, id, entity ); + if ( hint ) + { + hint->ParseFromData( pkvHint ); + } + } + } + + return hint; +} |