You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1671 lines
43 KiB
1671 lines
43 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//===========================================================================// |
|
|
|
#include "cbase.h" |
|
#include "weapon_selection.h" |
|
#include "iclientmode.h" |
|
#include "basetfcombatweapon_shared.h" |
|
#include "weapon_objectselection.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 "keydefs.h" |
|
|
|
#include <vgui/IVGui.h> |
|
|
|
#include "weapon_twohandedcontainer.h" |
|
#ifdef CLIENT_DLL |
|
#include "c_weapon_builder.h" |
|
#include "iinput.h" |
|
#else |
|
#include "weapon_builder.h" |
|
#endif |
|
|
|
using namespace vgui; |
|
|
|
class CHudWeaponSelection; |
|
|
|
typedef enum |
|
{ |
|
IMAGE_BACKGROUND = 0, |
|
IMAGE_CURRENT, |
|
IMAGE_INVALID |
|
} WeaponBoxType_t; |
|
|
|
enum |
|
{ |
|
HUMAN_WEAPON_SELECTION = 0, |
|
ALIEN_WEAPON_SELECTION, |
|
}; |
|
|
|
struct CSlotInfo |
|
{ |
|
bool active; |
|
bool valid; |
|
CHudTexture const *icon; |
|
bool drawAmmo; |
|
float ammoPerc; |
|
bool ammoCaution; |
|
char printname[ 128 ]; |
|
CHandle< C_BaseCombatWeapon > weapon; |
|
}; |
|
|
|
struct CWeaponMenuItem |
|
{ |
|
// If true, it's a dummy item |
|
bool buildslot; |
|
int priority; |
|
int hotkey; |
|
int openbuildmenu; |
|
bool isvalidmenuitem; |
|
CHandle< C_BaseCombatWeapon > weapon; |
|
}; |
|
|
|
class WeaponMenu |
|
{ |
|
public: |
|
WeaponMenu() : items( 0, 0, WeaponLessFunc ) |
|
{ |
|
m_bIsBuildMenu = false; |
|
m_nActiveItem = 0; |
|
} |
|
|
|
void SetActiveItem( int item ) |
|
{ |
|
bool changed = ( m_nActiveItem != item ); |
|
|
|
m_nActiveItem = item; |
|
|
|
if ( !changed ) |
|
return; |
|
|
|
const char *prefix = m_bIsBuildMenu ? "WeaponHiliteBuildMenu" : "WeaponHiliteWeaponMenu"; |
|
|
|
if ( m_nActiveItem >= 1 ) |
|
{ |
|
char slotSequence[ 128 ]; |
|
Q_snprintf( slotSequence, sizeof( slotSequence ), "%s%i", prefix, m_nActiveItem ); |
|
|
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( slotSequence ); |
|
} |
|
} |
|
|
|
int GetActiveItem() |
|
{ |
|
return m_nActiveItem; |
|
} |
|
|
|
static bool WeaponLessFunc( const CWeaponMenuItem& w1, const CWeaponMenuItem& w2 ) |
|
{ |
|
return w1.priority < w2.priority; |
|
} |
|
|
|
CUtlRBTree< CWeaponMenuItem, int > items; |
|
int m_nActiveItem; |
|
bool m_bIsBuildMenu; |
|
}; |
|
|
|
class CHudWeaponItemPanel : public vgui::Panel |
|
{ |
|
DECLARE_CLASS_SIMPLE( CHudWeaponItemPanel, vgui::Panel ); |
|
|
|
public: |
|
CHudWeaponItemPanel( vgui::Panel *parent, const char *panelName ); |
|
|
|
CPanelAnimationVarAliasType( float, m_flIconWidth, "IconWidth", "60", "proportional_float" ); |
|
CPanelAnimationVarAliasType( float, m_flIconHeight, "IconHeight", "30", "proportional_float" ); |
|
CPanelAnimationVarAliasType( float, m_flIconXPos, "IconXPos", "10", "proportional_float" ); |
|
CPanelAnimationVarAliasType( float, m_flIconYPos, "IconYPos", "4", "proportional_float" ); |
|
CPanelAnimationVarAliasType( float, m_flTextXPos, "TextXPos", "10", "proportional_float" ); |
|
CPanelAnimationVarAliasType( float, m_flTextYPos, "TextYPos", "35", "proportional_float" ); |
|
CPanelAnimationVarAliasType( float, m_flAmmoBarX, "AmmoBarX", "75", "proportional_float" ); |
|
CPanelAnimationVarAliasType( float, m_flAmmoBarWide, "AmmoBarWide", "4", "proportional_float" ); |
|
CPanelAnimationVarAliasType( float, m_flSelectionNumberXPos, "SelectionNumberXPos", "4", "proportional_float" ); |
|
CPanelAnimationVarAliasType( float, m_flSelectionNumberYPos, "SelectionNumberYPos", "4", "proportional_float" ); |
|
|
|
CPanelAnimationVarAliasType( float, m_flPriceXEndPos, "PriceXEndPos", "4", "proportional_float" ); |
|
CPanelAnimationVarAliasType( float, m_flPriceYEndPos, "PriceYEndPos", "4", "proportional_float" ); |
|
|
|
CPanelAnimationVar( float, m_flGrowFraction, "GrowFraction", "1.0" ); |
|
|
|
bool m_bInUse; |
|
|
|
bool m_bDrawNumbers; |
|
int m_nSlotNumber; |
|
bool m_bBuildMenu; |
|
|
|
// Copies of data |
|
CSlotInfo info; |
|
CWeaponMenuItem menuItem; |
|
|
|
virtual void Paint(); |
|
|
|
virtual void ApplySchemeSettings( vgui::IScheme *scheme ); |
|
|
|
void SetupIcons(); |
|
|
|
enum |
|
{ |
|
NUM_SLOT_TEAMS = 2, |
|
NUM_MENU_TYPES = 3, |
|
}; |
|
|
|
CHudTexture *m_BackgroundIcons[ NUM_SLOT_TEAMS ][ NUM_MENU_TYPES ]; |
|
|
|
private: |
|
void TranslateColor( float percent, Color& clr ); |
|
void DrawBox( bool isbuildmenu, int x, int y, int wide, int tall, bool isactive, bool isvalid, float normalizedAlpha, int number ); |
|
int GetTeamIndex(); |
|
void OnWeaponSelectionDrawn( CHudWeaponSelection *selection, C_WeaponObjectSelection *weapon, bool bCurrentlySelected, |
|
int wide, int tall, Color& clr ); |
|
}; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: tf2 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( void ); |
|
|
|
virtual void VidInit(void); |
|
|
|
virtual void CycleToNextWeapon( void ); |
|
virtual void CycleToPrevWeapon( void ); |
|
virtual void SwitchToLastWeapon( void ); |
|
|
|
virtual C_BaseCombatWeapon *GetWeaponInSlot( int iSlot, int iSlotPos ); |
|
virtual void SelectWeaponSlot( int iSlot ); |
|
|
|
virtual void OnWeaponPickup( C_BaseCombatWeapon *pWeapon ); |
|
|
|
virtual void SelectWeapon( void ); |
|
|
|
virtual C_BaseCombatWeapon *GetSelectedWeapon( void ); |
|
|
|
virtual void OpenSelection( void ); |
|
|
|
virtual int KeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ); |
|
|
|
virtual void HideSelection( void ); |
|
|
|
protected: |
|
virtual void OnTick(); |
|
virtual void ApplySchemeSettings(vgui::IScheme *pScheme); |
|
virtual void ApplySettings( KeyValues *resourceData ); |
|
private: |
|
|
|
// Offensive |
|
// Defensive |
|
// General Purpose |
|
enum |
|
{ |
|
BUILD_OFFENSIVE = 0, |
|
BUILD_DEFENSIVE, |
|
BUILD_GENERAL_PURPOSE, |
|
|
|
NUM_BUILD_MENUS, |
|
}; |
|
|
|
enum |
|
{ |
|
MAX_WEAPON_MENU_ITEMS = 7, |
|
MAX_BUILD_MENU_ITEMS = 6, |
|
}; |
|
|
|
void SetupWeaponMenu( WeaponMenu& menu, C_BaseCombatWeapon *activeItem, bool drawNumbers ); |
|
void SetupBuildMenu( WeaponMenu& menu, C_BaseCombatWeapon *activeItem ); |
|
|
|
void DrawBox( bool isbuildmenu, int x, int y, int wide, int tall, bool current, bool isvalid, float normalizedAlpha, int number ); |
|
|
|
void TranslateColor( float percent, Color& clr ); |
|
|
|
void ShowBuildMenu( int buildmenu ); |
|
void ShowBuildMenu( WeaponMenu& buildMenu ); |
|
void HideBuildMenu( void ); |
|
WeaponMenu& GetActiveMenu(); |
|
int GetLowIndex( WeaponMenu& menu ); |
|
void WrapIndexToRange( int& index, int low, int high ); |
|
int FindSlotForHotKey( WeaponMenu& menu, int hotkey ); |
|
int FindNextSelectableWeaponInMenu( WeaponMenu& menu, int startindex, int direction ); |
|
int CountSelectableItems( WeaponMenu& menu ); |
|
CWeaponMenuItem *GetFirstSelectableWeapon( WeaponMenu& menu ); |
|
const char *GetBuildMenuName( int slot ); |
|
const char *GetBuildMenuMaterial( int slot ); |
|
|
|
void SelectBuildMenuSlot( WeaponMenu& buildMenu ); |
|
|
|
void CreateWeaponItemPanels(); |
|
|
|
void ClearBuildMenu(); |
|
void RebuildMenus(); |
|
void AssignSlots( WeaponMenu& menu, int firstindex ); |
|
void CollapseSingleItemBuildMenus(); |
|
|
|
void GetSlotInfo( const CWeaponMenuItem *w, C_BaseCombatWeapon *active, CSlotInfo& info ); |
|
|
|
int GetTeamIndex(); |
|
|
|
void SetupIcons(); |
|
|
|
CPanelAnimationVar( float, m_flAlphaOverride, "Alpha", "255.0" ); |
|
CPanelAnimationVar( float, m_flSelectionAlphaOverride, "SelectionAlpha", "255.0" ); |
|
|
|
CPanelAnimationVar( Color, m_TextColor, "TextColor", "SelectionTextFg" ); |
|
CPanelAnimationVar( Color, m_InvalidActiveColor, "InvalidActiveColor", "InvalidActiveSlotFg" ); |
|
CPanelAnimationVar( Color, m_InvalidActiveTextColor, "InvalidActiveTextColor", "InvalidActiveSlotText" ); |
|
CPanelAnimationVar( Color, m_InvalidColor, "InvalidColor", "InvalidSlotFg" ); |
|
CPanelAnimationVar( Color, m_InvalidTextColor, "InvalidTextColor", "InvalidSlotText" ); |
|
CPanelAnimationVar( Color, m_OtherColor, "OtherColor", "OtherSlotFg" ); |
|
CPanelAnimationVar( Color, m_OtherTextColor, "OtherTextColor", "OtherSlotText" ); |
|
CPanelAnimationVar( Color, m_AmmoNormalColor, "AmmoNormalColor", "AmmoNormal" ); |
|
CPanelAnimationVar( Color, m_AmmoCautionColor, "AmmoCautionColor", "AmmoCaution" ); |
|
|
|
CPanelAnimationVar( vgui::HFont, m_hNumberFont, "NumberFont", "HudSelectionNumbers" ); |
|
CPanelAnimationVar( vgui::HFont, m_hTextFont, "TextFont", "HudSelectionText" ); |
|
CPanelAnimationVar( vgui::HFont, m_hTextFontSmall, "TextFontSmall", "HudSelectionTextSmall" ); |
|
CPanelAnimationVar( vgui::HFont, m_hPriceFont, "PriceFont", "HudSelectionTextSmall" ); |
|
|
|
CPanelAnimationVar( float, m_flGrowFraction, "GrowFraction", "0.0" ); |
|
|
|
CHandle<C_BaseCombatWeapon> m_hLastPickedUpWeapon; |
|
bool m_bInSelectionMode; |
|
int m_nLastBuildTick; |
|
bool m_bInBuildMenu; |
|
int m_nActiveBuildMenu; |
|
|
|
WeaponMenu *m_PreviousBuildMenu; |
|
|
|
WeaponMenu m_Weapons; |
|
WeaponMenu m_BuildObjects[ NUM_BUILD_MENUS ]; |
|
|
|
CHudWeaponItemPanel *m_pWeaponPanels[ MAX_WEAPON_MENU_ITEMS ]; |
|
CHudWeaponItemPanel *m_pBuildPanels[ MAX_BUILD_MENU_ITEMS ]; |
|
|
|
CWeaponMenuItem *FindWeapon( WeaponMenu& menu, int hotkey ); |
|
|
|
friend class CHudWeaponItemPanel; |
|
}; |
|
|
|
DECLARE_HUDELEMENT( CHudWeaponSelection ); |
|
|
|
void CHudWeaponSelection::VidInit(void) |
|
{ |
|
CBaseHudWeaponSelection::VidInit(); |
|
|
|
SetupIcons(); |
|
} |
|
|
|
void CHudWeaponSelection::SetupIcons() |
|
{ |
|
int i; |
|
|
|
for ( i = 0; i < MAX_WEAPON_MENU_ITEMS; i++ ) |
|
{ |
|
m_pWeaponPanels[ i ]->SetupIcons(); |
|
} |
|
|
|
for ( i = 0; i < MAX_BUILD_MENU_ITEMS; i++ ) |
|
{ |
|
m_pBuildPanels[ i ]->SetupIcons(); |
|
} |
|
} |
|
|
|
|
|
void CHudWeaponSelection::AssignSlots( WeaponMenu& menu, int firstindex ) |
|
{ |
|
int slot = firstindex; |
|
|
|
for ( int i = menu.items.FirstInorder(); i != menu.items.InvalidIndex(); i = menu.items.NextInorder( i ) ) |
|
{ |
|
CWeaponMenuItem *w = &menu.items[ i ]; |
|
w->hotkey = slot++; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CHudWeaponSelection::CreateWeaponItemPanels() |
|
{ |
|
int i; |
|
char sz[ 128 ]; |
|
for ( i = 0; i < MAX_WEAPON_MENU_ITEMS; i++ ) |
|
{ |
|
Q_snprintf( sz, sizeof( sz ), "WeaponMenu%i", i + 1 ); |
|
m_pWeaponPanels[ i ] = new CHudWeaponItemPanel( this, sz ); |
|
m_pWeaponPanels[ i ]->m_nSlotNumber = i; |
|
m_pWeaponPanels[ i ]->m_bBuildMenu = false; |
|
} |
|
|
|
for ( i = 0; i < MAX_BUILD_MENU_ITEMS; i++ ) |
|
{ |
|
Q_snprintf( sz, sizeof( sz ), "BuildMenu%i", i + 1 ); |
|
m_pBuildPanels[ i ] = new CHudWeaponItemPanel( this, sz ); |
|
m_pBuildPanels[ i ]->m_nSlotNumber = i; |
|
m_pBuildPanels[ i ]->m_bBuildMenu = true; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CHudWeaponSelection::RebuildMenus() |
|
{ |
|
int i; |
|
|
|
if ( gpGlobals->tickcount == m_nLastBuildTick ) |
|
return; |
|
|
|
m_nLastBuildTick = gpGlobals->tickcount; |
|
|
|
|
|
C_BasePlayer *player = C_BasePlayer::GetLocalPlayer(); |
|
if ( !player ) |
|
return; |
|
|
|
m_Weapons.items.RemoveAll(); |
|
for ( i = 0; i < NUM_BUILD_MENUS; i++ ) |
|
{ |
|
m_BuildObjects[ i ].items.RemoveAll(); |
|
} |
|
|
|
CWeaponMenuItem item; |
|
|
|
int c = MAX_WEAPONS; |
|
for ( i = 0; i < c; i++ ) |
|
{ |
|
C_BaseCombatWeapon *pWeapon = player->GetWeapon( i ); |
|
if ( !pWeapon ) |
|
{ |
|
continue; |
|
} |
|
|
|
if ( !pWeapon->VisibleInWeaponSelection() ) |
|
{ |
|
continue; |
|
} |
|
|
|
item.priority = pWeapon->GetSlot() * 10 + pWeapon->GetPosition(); |
|
item.buildslot = false; |
|
item.openbuildmenu = -1; |
|
item.weapon = pWeapon; |
|
item.isvalidmenuitem = true; |
|
|
|
if ( dynamic_cast< C_WeaponObjectSelection * >( pWeapon ) ) |
|
{ |
|
// HACK |
|
int firstbuildslot = 4; |
|
int whichBuildMenu = clamp( pWeapon->GetSlot() - firstbuildslot, 0, NUM_BUILD_MENUS - 1 ); |
|
|
|
m_BuildObjects[ whichBuildMenu ].items.Insert( item ); |
|
} |
|
else |
|
{ |
|
m_Weapons.items.Insert( item ); |
|
} |
|
} |
|
|
|
while ( m_Weapons.items.Count() < 3 ) |
|
{ |
|
// Add build item menus |
|
item.priority = 999; |
|
item.buildslot = false; |
|
item.openbuildmenu = -1; |
|
item.weapon = NULL; |
|
item.isvalidmenuitem = false; |
|
m_Weapons.items.Insert( item ); |
|
|
|
m_Weapons.m_bIsBuildMenu = false; |
|
} |
|
|
|
for ( i = 0; i < NUM_BUILD_MENUS; i++ ) |
|
{ |
|
// Add build item menus |
|
item.priority = 999; |
|
item.buildslot = true; |
|
item.openbuildmenu = i; |
|
item.weapon = NULL; |
|
item.isvalidmenuitem = CountSelectableItems( m_BuildObjects[ i ] ) > 0 ? true : false; |
|
m_Weapons.items.Insert( item ); |
|
|
|
// Assign build menu slots |
|
AssignSlots( m_BuildObjects[ i ], 0 ); |
|
|
|
m_BuildObjects[ i ].m_bIsBuildMenu = true; |
|
} |
|
|
|
// Now walk in order and assign hotkeys |
|
AssignSlots( m_Weapons, 1 ); |
|
|
|
// Merge single item build menus into main menu |
|
CollapseSingleItemBuildMenus(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CHudWeaponSelection::CollapseSingleItemBuildMenus() |
|
{ |
|
for ( int i = 0; i < NUM_BUILD_MENUS; i++ ) |
|
{ |
|
int count = m_BuildObjects[ i ].items.Count(); |
|
|
|
// Not an issue |
|
if ( count > 1 ) |
|
continue; |
|
|
|
CWeaponMenuItem *mainItem = FindWeapon( m_Weapons, 4 + i ); |
|
if ( !mainItem ) |
|
continue; |
|
|
|
// It's empty, need to make main item a disabled slot |
|
if ( count == 0 ) |
|
{ |
|
// Add build item menus |
|
mainItem->isvalidmenuitem = false; |
|
} |
|
else |
|
{ |
|
// Only one item in sub menu, copy it over |
|
CWeaponMenuItem *buildItem = &m_BuildObjects[ i ].items[ 0 ]; |
|
mainItem->buildslot = false; |
|
mainItem->openbuildmenu = -1; |
|
mainItem->isvalidmenuitem = true; |
|
mainItem->weapon = buildItem->weapon; |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CHudWeaponSelection::ClearBuildMenu() |
|
{ |
|
for ( int i = 0; i < MAX_BUILD_MENU_ITEMS; i++ ) |
|
{ |
|
m_pBuildPanels[ i ]->m_bInUse = false; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Constructor |
|
//----------------------------------------------------------------------------- |
|
CHudWeaponSelection::CHudWeaponSelection(const char *pElementName ) : |
|
CBaseHudWeaponSelection(pElementName), BaseClass(NULL, "HudWeaponSelection") |
|
{ |
|
vgui::Panel *pParent = g_pClientMode->GetViewport(); |
|
SetParent( pParent ); |
|
|
|
m_nLastBuildTick = -1; |
|
|
|
m_hNumberFont = NULL; |
|
m_bInSelectionMode = false; |
|
|
|
CreateWeaponItemPanels(); |
|
|
|
vgui::ivgui()->AddTickSignal( GetVPanel() ); |
|
} |
|
|
|
void CHudWeaponSelection::ShowBuildMenu( int buildmenu ) |
|
{ |
|
bool wasinbuild = m_bInBuildMenu; |
|
|
|
int mainItem = buildmenu + 4; |
|
m_Weapons.SetActiveItem( mainItem ); |
|
|
|
m_bInBuildMenu = true; |
|
m_nActiveBuildMenu = buildmenu; |
|
GetActiveMenu().SetActiveItem( GetLowIndex( GetActiveMenu() ) ); |
|
|
|
if ( !wasinbuild ) |
|
{ |
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponOpenBuildSubMenu"); |
|
|
|
switch ( buildmenu ) |
|
{ |
|
default: |
|
case BUILD_OFFENSIVE: |
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponOpenBuildOffensive"); |
|
break; |
|
case BUILD_DEFENSIVE: |
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponOpenBuildDefensive"); |
|
break; |
|
case BUILD_GENERAL_PURPOSE: |
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponOpenBuildGeneral"); |
|
break; |
|
} |
|
} |
|
} |
|
|
|
void CHudWeaponSelection::ShowBuildMenu( WeaponMenu& buildMenu ) |
|
{ |
|
int c = m_Weapons.items.Count(); |
|
for ( int i = 0; i < c; i++ ) |
|
{ |
|
CWeaponMenuItem *item = &m_Weapons.items[ i ]; |
|
if ( !item || !item->buildslot ) |
|
continue; |
|
|
|
WeaponMenu &menu = m_BuildObjects[ item->openbuildmenu ]; |
|
if ( &menu == &buildMenu ) |
|
{ |
|
ShowBuildMenu( item->openbuildmenu ); |
|
return; |
|
} |
|
} |
|
|
|
Assert( 0 ); |
|
} |
|
|
|
void CHudWeaponSelection::HideBuildMenu( void ) |
|
{ |
|
bool wasinbuild = m_bInBuildMenu; |
|
|
|
GetActiveMenu().SetActiveItem( GetLowIndex( GetActiveMenu() ) ); |
|
m_bInBuildMenu = false; |
|
|
|
if ( wasinbuild ) |
|
{ |
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponCloseBuildSubMenu"); |
|
} |
|
|
|
m_nActiveBuildMenu = -1; |
|
} |
|
|
|
WeaponMenu& CHudWeaponSelection::GetActiveMenu() |
|
{ |
|
return m_bInBuildMenu ? m_BuildObjects[ m_nActiveBuildMenu ] : m_Weapons; |
|
} |
|
|
|
int CHudWeaponSelection::GetLowIndex( WeaponMenu& menu ) |
|
{ |
|
if ( menu.items.Count() == 0 ) |
|
return 1; |
|
|
|
int lowindex = menu.items[ menu.items.FirstInorder() ].hotkey; |
|
return lowindex; |
|
} |
|
|
|
void CHudWeaponSelection::WrapIndexToRange( int& index, int low, int high ) |
|
{ |
|
int delta = ( high - low ) + 1; |
|
while ( index < low ) |
|
{ |
|
index += delta; |
|
} |
|
|
|
while ( index > high ) |
|
{ |
|
index -= delta; |
|
} |
|
} |
|
|
|
int CHudWeaponSelection::FindSlotForHotKey( WeaponMenu& menu, int hotkey ) |
|
{ |
|
int count = menu.items.Count(); |
|
for ( int i = 0; i < count;i++ ) |
|
{ |
|
if ( menu.items[ i ].hotkey == hotkey ) |
|
return i; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
int CHudWeaponSelection::FindNextSelectableWeaponInMenu( WeaponMenu& menu, int startindex, int direction ) |
|
{ |
|
direction = direction > 0 ? 1 : -1; |
|
|
|
int count = menu.items.Count(); |
|
int lowindex = GetLowIndex( menu ); |
|
int highindex = lowindex + count - 1; |
|
|
|
for ( int offset = 1; offset <= count; offset++ ) |
|
{ |
|
int current = startindex + offset * direction; |
|
|
|
WrapIndexToRange( current, lowindex, highindex ); |
|
|
|
//int slot = FindSlotForHotKey( menu, current ); |
|
|
|
//C_BaseCombatWeapon *w = menu.items[ slot ].weapon; |
|
//if ( w && !w->CanBeSelected() ) |
|
// continue; |
|
|
|
return current; |
|
} |
|
|
|
return startindex; |
|
} |
|
|
|
int CHudWeaponSelection::CountSelectableItems( WeaponMenu& menu ) |
|
{ |
|
int count = 0; |
|
int c = menu.items.Count(); |
|
for ( int i = 0; i < c; i++ ) |
|
{ |
|
C_BaseCombatWeapon *w = menu.items[ i ].weapon; |
|
if ( w && w->CanBeSelected() ) |
|
{ |
|
count++; |
|
} |
|
} |
|
return count; |
|
} |
|
|
|
CWeaponMenuItem *CHudWeaponSelection::GetFirstSelectableWeapon( WeaponMenu& menu ) |
|
{ |
|
int c = menu.items.Count(); |
|
for ( int i = 0; i < c; i++ ) |
|
{ |
|
C_BaseCombatWeapon *w = menu.items[ i ].weapon; |
|
if ( w && w->CanBeSelected() ) |
|
{ |
|
return &menu.items[ i ]; |
|
} |
|
} |
|
return NULL; |
|
} |
|
|
|
const char *CHudWeaponSelection::GetBuildMenuName( int slot ) |
|
{ |
|
switch ( slot ) |
|
{ |
|
default: |
|
case BUILD_OFFENSIVE: |
|
return "Offensive Object"; |
|
case BUILD_DEFENSIVE: |
|
return "Defensive Object"; |
|
case BUILD_GENERAL_PURPOSE: |
|
return "General Purpose"; |
|
} |
|
|
|
return "General Purpose"; |
|
} |
|
|
|
const char *CHudWeaponSelection::GetBuildMenuMaterial( int slot ) |
|
{ |
|
switch ( slot ) |
|
{ |
|
default: |
|
case BUILD_OFFENSIVE: |
|
return "weapon_selection_offensive"; |
|
case BUILD_DEFENSIVE: |
|
return "weapon_selection_defensive"; |
|
case BUILD_GENERAL_PURPOSE: |
|
return "weapon_selection_general"; |
|
} |
|
|
|
return "hud/menu/weapon_selection_general"; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: sets up display for showing weapon pickup |
|
//----------------------------------------------------------------------------- |
|
void CHudWeaponSelection::OnWeaponPickup( C_BaseCombatWeapon *pWeapon ) |
|
{ |
|
// Nothing in TF2 |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: returns true if the panel should draw |
|
//----------------------------------------------------------------------------- |
|
bool CHudWeaponSelection::ShouldDraw() |
|
{ |
|
C_BaseTFPlayer *pPlayer = C_BaseTFPlayer::GetLocalPlayer(); |
|
if ( !pPlayer || pPlayer->GetPlayerClass() == NULL ) |
|
{ |
|
if ( IsInSelectionMode() ) |
|
{ |
|
HideSelection(); |
|
} |
|
return false; |
|
} |
|
|
|
bool bret = CBaseHudWeaponSelection::ShouldDraw(); |
|
|
|
if ( !bret ) |
|
return false; |
|
|
|
return ( m_bSelectionVisible || ( m_flGrowFraction > 0.0f ) ) ? true : false; |
|
} |
|
|
|
void CHudWeaponSelection::TranslateColor( float percent, Color& clr ) |
|
{ |
|
if ( percent >= 1.0f ) |
|
return; |
|
|
|
if ( percent <= 0.75f ) |
|
{ |
|
clr = Color( 0, 0, 0, 0 ); |
|
} |
|
else |
|
{ |
|
float frac = ( percent - 0.75f ) / 0.25f; |
|
|
|
clr = Color( clr[0] * frac, |
|
clr[1] * frac, |
|
clr[2] * frac, |
|
clr[3] * frac ); |
|
} |
|
} |
|
|
|
void CHudWeaponSelection::GetSlotInfo( const CWeaponMenuItem *w, C_BaseCombatWeapon *active, CSlotInfo& info ) |
|
{ |
|
if ( w->buildslot ) |
|
{ |
|
info.active = !m_bInBuildMenu && ( GetActiveMenu().GetActiveItem() == w->hotkey ); |
|
info.valid = w->isvalidmenuitem; |
|
info.icon = gHUD.GetIcon( GetBuildMenuMaterial( w->openbuildmenu ) ); |
|
info.drawAmmo = false; |
|
info.ammoCaution = false; |
|
Q_snprintf( info.printname, sizeof( info.printname ), GetBuildMenuName( w->openbuildmenu ) ); |
|
info.weapon = NULL; |
|
} |
|
else if ( !w->weapon ) |
|
{ |
|
info.active =false; |
|
info.valid = false; |
|
info.icon = NULL; |
|
info.drawAmmo = false; |
|
info.ammoCaution = false; |
|
info.printname[0]=0; |
|
info.weapon = NULL; |
|
} |
|
else |
|
{ |
|
C_BaseCombatWeapon *pWeapon = w->weapon; |
|
Assert( pWeapon ); |
|
|
|
info.active = active == pWeapon; |
|
info.valid = pWeapon->CanBeSelected(); |
|
info.icon = info.active ? pWeapon->GetSpriteActive() : pWeapon->GetSpriteInactive(); |
|
|
|
info.drawAmmo = false; |
|
info.ammoPerc = 1.0f; |
|
// Don't know the max ammo, so if I don't use clips, just go red on no ammo left |
|
if ( pWeapon->UsesClipsForAmmo1() || pWeapon->HasAmmo() ) |
|
{ |
|
info.ammoPerc = 1.0f - ( (float) pWeapon->Clip1() ) / ( (float)pWeapon->GetMaxClip1() ); |
|
info.drawAmmo = true; |
|
} |
|
info.ammoCaution = ( info.ammoPerc >= CLIP_PERC_THRESHOLD ) ? true : false; |
|
|
|
Q_snprintf( info.printname, sizeof( info.printname ), "%s", pWeapon->GetPrintName() ); |
|
info.weapon = pWeapon; |
|
} |
|
|
|
strupr(info.printname); |
|
} |
|
|
|
void CHudWeaponSelection::SetupWeaponMenu( WeaponMenu& menu, C_BaseCombatWeapon *activeItem, bool drawNumbers ) |
|
{ |
|
int panelPosition = 0; |
|
for ( int item = menu.items.FirstInorder(); item != menu.items.InvalidIndex() && panelPosition < MAX_WEAPON_MENU_ITEMS; item = menu.items.NextInorder( item ) ) |
|
{ |
|
CWeaponMenuItem *w = &menu.items[ item ]; |
|
Assert( w ); |
|
|
|
CSlotInfo info; |
|
GetSlotInfo( w, activeItem, info ); |
|
|
|
CHudWeaponItemPanel *panel = m_pWeaponPanels[ panelPosition++ ]; |
|
if ( !panel ) |
|
{ |
|
Assert( 0 ); |
|
continue; |
|
} |
|
|
|
panel->m_bInUse = true; |
|
panel->info = info; |
|
panel->menuItem = *w; |
|
panel->m_bDrawNumbers = drawNumbers; |
|
} |
|
|
|
for ( ; panelPosition < MAX_WEAPON_MENU_ITEMS; ) |
|
{ |
|
CHudWeaponItemPanel *panel = m_pWeaponPanels[ panelPosition++ ]; |
|
panel->m_bInUse = false; |
|
} |
|
} |
|
|
|
void CHudWeaponSelection::SetupBuildMenu( WeaponMenu& menu, C_BaseCombatWeapon *activeItem ) |
|
{ |
|
int panelPosition = 0; |
|
for ( int item = menu.items.FirstInorder(); item != menu.items.InvalidIndex() && panelPosition < MAX_BUILD_MENU_ITEMS; item = menu.items.NextInorder( item ) ) |
|
{ |
|
CWeaponMenuItem *w = &menu.items[ item ]; |
|
Assert( w ); |
|
|
|
CSlotInfo info; |
|
GetSlotInfo( w, activeItem, info ); |
|
|
|
CHudWeaponItemPanel *panel = m_pBuildPanels[ panelPosition++ ]; |
|
if ( !panel ) |
|
{ |
|
Assert( 0 ); |
|
continue; |
|
} |
|
|
|
panel->m_bInUse = true; |
|
panel->info = info; |
|
panel->menuItem = *w; |
|
panel->m_bDrawNumbers = false; |
|
} |
|
|
|
for ( ; panelPosition < MAX_BUILD_MENU_ITEMS; ) |
|
{ |
|
CHudWeaponItemPanel *panel = m_pBuildPanels[ panelPosition++ ]; |
|
panel->m_bInUse = false; |
|
} |
|
} |
|
|
|
void CHudWeaponSelection::OnTick() |
|
{ |
|
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); |
|
if ( !pPlayer ) |
|
return; |
|
|
|
RebuildMenus(); |
|
|
|
int x, y; |
|
GetPos(x, y); |
|
|
|
C_BaseCombatWeapon *wpn = GetSelectedWeapon(); |
|
|
|
// Draw main menu |
|
SetupWeaponMenu( m_Weapons, wpn, true ); |
|
|
|
CWeaponMenuItem *item = FindWeapon( GetActiveMenu(), GetActiveMenu().GetActiveItem() ); |
|
|
|
WeaponMenu* otherMenu = NULL; |
|
int buildMenuNumber= 0; |
|
|
|
// Drawing build menu |
|
if ( m_bInBuildMenu ) |
|
{ |
|
otherMenu = &m_BuildObjects[ m_nActiveBuildMenu ]; |
|
buildMenuNumber = m_nActiveBuildMenu; |
|
} |
|
else if ( item && item->buildslot && item->hotkey == GetActiveMenu().GetActiveItem() ) |
|
{ |
|
otherMenu = &m_BuildObjects[ item->openbuildmenu ]; |
|
buildMenuNumber = item->openbuildmenu; |
|
} |
|
else if ( m_nActiveBuildMenu >= 0 ) |
|
{ |
|
otherMenu = &m_BuildObjects[ m_nActiveBuildMenu ]; |
|
buildMenuNumber = m_nActiveBuildMenu; |
|
} |
|
|
|
if ( otherMenu ) |
|
{ |
|
SetupBuildMenu( *otherMenu, wpn ); |
|
} |
|
else |
|
{ |
|
ClearBuildMenu(); |
|
} |
|
|
|
if ( otherMenu != m_PreviousBuildMenu ) |
|
{ |
|
m_PreviousBuildMenu = otherMenu; |
|
|
|
if ( otherMenu ) |
|
{ |
|
switch ( buildMenuNumber ) |
|
{ |
|
default: |
|
case BUILD_OFFENSIVE: |
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponOpenBuildOffensive"); |
|
break; |
|
case BUILD_DEFENSIVE: |
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponOpenBuildDefensive"); |
|
break; |
|
case BUILD_GENERAL_PURPOSE: |
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponOpenBuildGeneral"); |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: hud scheme settings |
|
//----------------------------------------------------------------------------- |
|
void CHudWeaponSelection::ApplySchemeSettings(vgui::IScheme *pScheme) |
|
{ |
|
BaseClass::ApplySchemeSettings(pScheme); |
|
SetPaintBackgroundEnabled(false); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Select the next item in the weapon list |
|
//----------------------------------------------------------------------------- |
|
void CHudWeaponSelection::CycleToNextWeapon( void ) |
|
{ |
|
// Get the local player. |
|
C_BaseTFPlayer *pPlayer = C_BaseTFPlayer::GetLocalPlayer(); |
|
if ( !pPlayer || !pPlayer->GetPlayerClass() ) |
|
return; |
|
|
|
// Make it active |
|
bool justopened = false; |
|
if ( !IsInSelectionMode() ) |
|
{ |
|
OpenSelection(); |
|
justopened = true; |
|
} |
|
|
|
RebuildMenus(); |
|
|
|
WeaponMenu& menu = GetActiveMenu(); |
|
int c = menu.items.Count(); |
|
if ( c != 0 && !justopened ) |
|
{ |
|
GetActiveMenu().SetActiveItem( FindNextSelectableWeaponInMenu( menu, GetActiveMenu().GetActiveItem(), +1 ) ); |
|
} |
|
|
|
// Play the "cycle to next weapon" sound |
|
pPlayer->EmitSound( "Player.WeaponSelectionMoveSlot" ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Selects the previous item in the menu |
|
//----------------------------------------------------------------------------- |
|
void CHudWeaponSelection::CycleToPrevWeapon( void ) |
|
{ |
|
C_BaseTFPlayer *pPlayer = C_BaseTFPlayer::GetLocalPlayer(); |
|
if ( !pPlayer || !pPlayer->GetPlayerClass() ) |
|
return; |
|
|
|
// Make it active |
|
bool justopened = false; |
|
if ( !IsInSelectionMode() ) |
|
{ |
|
OpenSelection(); |
|
justopened = true; |
|
} |
|
|
|
RebuildMenus(); |
|
|
|
WeaponMenu& menu = GetActiveMenu(); |
|
int c = menu.items.Count(); |
|
if ( c != 0 && !justopened ) |
|
{ |
|
GetActiveMenu().SetActiveItem( FindNextSelectableWeaponInMenu( menu, GetActiveMenu().GetActiveItem(), -1 ) ); |
|
} |
|
|
|
// Play the "cycle to next weapon" sound |
|
pPlayer->EmitSound( "Player.WeaponSelectionMoveSlot" ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Switches the last weapon the player was using |
|
//----------------------------------------------------------------------------- |
|
void CHudWeaponSelection::SwitchToLastWeapon( void ) |
|
{ |
|
// Get the player's last weapon |
|
C_BaseTFPlayer *pPlayer = C_BaseTFPlayer::GetLocalPlayer(); |
|
if ( !pPlayer ) |
|
return; |
|
|
|
// If we're currently using the builder weapon, switch to the weapon we were |
|
// using before we started using it. |
|
C_BaseCombatWeapon *pActiveWeapon = pPlayer->GetActiveWeapon(); |
|
// Handle the twohanded weapon container |
|
CWeaponTwoHandedContainer *pContainer = dynamic_cast< CWeaponTwoHandedContainer * >( pActiveWeapon ); |
|
if ( pContainer ) |
|
{ |
|
pActiveWeapon = pContainer->GetLeftWeapon(); |
|
} |
|
|
|
if ( dynamic_cast< C_WeaponBuilder* >( pActiveWeapon ) ) |
|
{ |
|
::input->MakeWeaponSelection( pPlayer->GetLastWeaponBeforeObject() ); |
|
return; |
|
} |
|
|
|
// Switch to previous weapon normally |
|
::input->MakeWeaponSelection( pPlayer->GetLastWeapon() ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CWeaponMenuItem *CHudWeaponSelection::FindWeapon( WeaponMenu& menu, int hotkey ) |
|
{ |
|
RebuildMenus(); |
|
|
|
int c = menu.items.Count(); |
|
|
|
for ( int i = 0; i < c; i++ ) |
|
{ |
|
CWeaponMenuItem *item = &menu.items[ i ]; |
|
if ( item->hotkey == hotkey ) |
|
return item; |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
C_BaseCombatWeapon *CHudWeaponSelection::GetWeaponInSlot( int iSlot, int iSlotPos ) |
|
{ |
|
CWeaponMenuItem *item = FindWeapon( GetActiveMenu(), iSlot ); |
|
if ( item ) |
|
{ |
|
return item->weapon; |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
C_BaseCombatWeapon *CHudWeaponSelection::GetSelectedWeapon( void ) |
|
{ |
|
RebuildMenus(); |
|
|
|
return GetWeaponInSlot( GetActiveMenu().GetActiveItem(), 0 ); |
|
} |
|
|
|
void CHudWeaponSelection::SelectBuildMenuSlot( WeaponMenu& buildMenu ) |
|
{ |
|
// Get the local player. |
|
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); |
|
if ( !pPlayer ) |
|
return; |
|
|
|
int numSelectable = CountSelectableItems( buildMenu ); |
|
|
|
if ( numSelectable >= 1 ) |
|
{ |
|
// Single item, just fast switch to it |
|
CWeaponMenuItem *fastSwitchItem = GetFirstSelectableWeapon( buildMenu ); |
|
C_BaseCombatWeapon *w = fastSwitchItem ? fastSwitchItem->weapon : NULL; |
|
|
|
Assert( w && w->CanBeSelected() ); |
|
if ( 0 && numSelectable == 1 && w && w->CanBeSelected() ) |
|
{ |
|
ShowBuildMenu( buildMenu ); |
|
|
|
m_hSelectedWeapon = w; |
|
GetActiveMenu().SetActiveItem( fastSwitchItem->hotkey ); |
|
|
|
// There's only one active item in bucket, so change directly to weapon |
|
SetWeaponSelected(); |
|
engine->ClientCmd( "cancelselect\n" ); |
|
} |
|
else |
|
{ |
|
// Play the "open weapon selection" sound |
|
pPlayer->EmitSound( "Player.WeaponSelectionOpen" ); |
|
|
|
ShowBuildMenu( buildMenu ); |
|
} |
|
} |
|
else |
|
{ |
|
pPlayer->EmitSound( "Player.DenyWeaponSelection" ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Weapon selection code |
|
//----------------------------------------------------------------------------- |
|
void CHudWeaponSelection::SelectWeaponSlot( int iSlot ) |
|
{ |
|
// Get the local player. |
|
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); |
|
if ( !pPlayer ) |
|
return; |
|
|
|
// Make sure the player's allowed to switch weapons |
|
if ( pPlayer->IsAllowedToSwitchWeapons() == false ) |
|
return; |
|
|
|
// Make it active |
|
if ( !IsInSelectionMode() ) |
|
{ |
|
OpenSelection(); |
|
} |
|
|
|
RebuildMenus(); |
|
CWeaponMenuItem *item = FindWeapon( GetActiveMenu(), iSlot ); |
|
|
|
C_BaseCombatWeapon *weapon = item ? item->weapon : NULL; |
|
|
|
if ( item && item->buildslot ) |
|
{ |
|
SelectBuildMenuSlot( m_BuildObjects[ item->openbuildmenu ] ); |
|
return; |
|
} |
|
|
|
if ( m_bInBuildMenu ) |
|
{ |
|
CWeaponMenuItem *mainItem = FindWeapon( m_Weapons, iSlot ); |
|
if ( mainItem ) |
|
{ |
|
if ( mainItem->buildslot ) |
|
{ |
|
if ( mainItem->openbuildmenu == m_nActiveBuildMenu ) |
|
{ |
|
CycleToNextWeapon(); |
|
} |
|
else |
|
{ |
|
SelectBuildMenuSlot( m_BuildObjects[ mainItem->openbuildmenu ] ); |
|
} |
|
} |
|
else if ( mainItem->weapon ) |
|
{ |
|
// Play the "open weapon selection" sound |
|
pPlayer->EmitSound( "Player.WeaponSelectionOpen" ); |
|
|
|
m_bInBuildMenu = false; |
|
m_hSelectedWeapon = mainItem->weapon; |
|
GetActiveMenu().SetActiveItem( mainItem->hotkey ); |
|
|
|
// Check for fast weapon switch mode |
|
if ( GetSelectedWeapon() && GetSelectedWeapon()->CanBeSelected() ) |
|
{ |
|
// There's only one active item in bucket, so change directly to weapon |
|
SetWeaponSelected(); |
|
engine->ClientCmd( "cancelselect\n" ); |
|
return; |
|
} |
|
} |
|
} |
|
return; |
|
} |
|
|
|
if ( item && weapon ) |
|
{ |
|
// Play the "open weapon selection" sound |
|
pPlayer->EmitSound( "Player.WeaponSelectionOpen" ); |
|
|
|
if ( !weapon->CanBeSelected() ) |
|
{ |
|
if ( GetActiveMenu().GetActiveItem() == item->hotkey ) |
|
{ |
|
pPlayer->EmitSound( "Player.DenyWeaponSelection" ); |
|
} |
|
} |
|
|
|
m_hSelectedWeapon = weapon; |
|
GetActiveMenu().SetActiveItem( item->hotkey ); |
|
|
|
// Check for fast weapon switch mode |
|
if ( GetSelectedWeapon() && GetSelectedWeapon()->CanBeSelected() ) |
|
{ |
|
// There's only one active item in bucket, so change directly to weapon |
|
SetWeaponSelected(); |
|
engine->ClientCmd( "cancelselect\n" ); |
|
return; |
|
} |
|
} |
|
else |
|
{ |
|
pPlayer->EmitSound( "Player.DenyWeaponSelection" ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Player has chosen to draw the currently selected weapon |
|
//----------------------------------------------------------------------------- |
|
void CHudWeaponSelection::SelectWeapon( void ) |
|
{ |
|
C_BasePlayer *player = C_BasePlayer::GetLocalPlayer(); |
|
if ( !player ) |
|
return; |
|
|
|
CWeaponMenuItem *item = FindWeapon( GetActiveMenu(), GetActiveMenu().GetActiveItem() ); |
|
if ( !item ) |
|
{ |
|
engine->ClientCmd( "cancelselect\n" ); |
|
return; |
|
} |
|
|
|
if ( item->buildslot ) |
|
{ |
|
SelectBuildMenuSlot( m_BuildObjects[ item->openbuildmenu ] ); |
|
return; |
|
} |
|
|
|
CBaseHudWeaponSelection::SelectWeapon(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : down - |
|
// keynum - |
|
// *pszCurrentBinding - |
|
//----------------------------------------------------------------------------- |
|
int CHudWeaponSelection::KeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ) |
|
{ |
|
if ( !down ) |
|
return 1; |
|
|
|
if ( keynum != KEY_ESCAPE ) |
|
return 1; |
|
|
|
C_BasePlayer *player = C_BasePlayer::GetLocalPlayer(); |
|
if ( !player ) |
|
return 1; |
|
|
|
if ( !IsInSelectionMode() ) |
|
return 1; |
|
|
|
if ( !m_bInBuildMenu ) |
|
{ |
|
engine->ClientCmd( "cancelselect\n" ); |
|
return 0; |
|
} |
|
|
|
// Play the "open weapon selection" sound |
|
player->EmitSound( "Player.WeaponSelectionOpen" ); |
|
|
|
HideBuildMenu(); |
|
|
|
// Swallow the key |
|
return 0; |
|
} |
|
|
|
void CHudWeaponSelection::OpenSelection( void ) |
|
{ |
|
HideBuildMenu(); |
|
m_nActiveBuildMenu = -1; |
|
|
|
CBaseHudWeaponSelection::OpenSelection(); |
|
|
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponOpenWeaponMenu"); |
|
} |
|
|
|
void CHudWeaponSelection::HideSelection( void ) |
|
{ |
|
CBaseHudWeaponSelection::HideSelection(); |
|
|
|
if ( m_bInBuildMenu ) |
|
{ |
|
HideBuildMenu(); |
|
} |
|
|
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("WeaponCloseWeaponMenu"); |
|
} |
|
|
|
int CHudWeaponSelection::GetTeamIndex() |
|
{ |
|
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); |
|
if(!pPlayer) |
|
return HUMAN_WEAPON_SELECTION; |
|
int team = pPlayer->GetTeamNumber(); |
|
if ( !team ) |
|
return HUMAN_WEAPON_SELECTION; |
|
|
|
bool human = ( team == TEAM_HUMANS ) ? true : false; |
|
return human ? HUMAN_WEAPON_SELECTION : ALIEN_WEAPON_SELECTION; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: serializes settings from a resource data container |
|
//----------------------------------------------------------------------------- |
|
void CHudWeaponSelection::ApplySettings( KeyValues *resourceData ) |
|
{ |
|
BaseClass::ApplySettings( resourceData ); |
|
|
|
// loop through all the keys, applying them wherever |
|
for (KeyValues *controlKeys = resourceData->GetFirstSubKey(); controlKeys != NULL; controlKeys = controlKeys->GetNextKey()) |
|
{ |
|
// Skip keys that are atomic.. |
|
if (controlKeys->GetDataType() != KeyValues::TYPE_NONE) |
|
continue; |
|
|
|
Panel *panel = FindChildByName( controlKeys->GetName() ); |
|
if ( !panel ) |
|
continue; |
|
|
|
// apply the settings |
|
panel->ApplySettings(controlKeys); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *parent - |
|
// *panelName - |
|
//----------------------------------------------------------------------------- |
|
CHudWeaponItemPanel::CHudWeaponItemPanel( vgui::Panel *parent, const char *panelName ) |
|
: BaseClass( parent, panelName ) |
|
{ |
|
m_bInUse = false; |
|
m_bDrawNumbers = false; |
|
m_nSlotNumber = 0; |
|
|
|
// Copies of data |
|
memset( &info, 0, sizeof( info ) ); |
|
memset( &menuItem, 0, sizeof( menuItem ) ); |
|
|
|
memset( m_BackgroundIcons, 0, sizeof( m_BackgroundIcons ) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *scheme - |
|
//----------------------------------------------------------------------------- |
|
void CHudWeaponItemPanel::ApplySchemeSettings( vgui::IScheme *scheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings( scheme ); |
|
SetPaintBackgroundEnabled( false ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CHudWeaponItemPanel::Paint() |
|
{ |
|
if ( !m_bInUse ) |
|
return; |
|
|
|
CHudWeaponSelection *selection = static_cast< CHudWeaponSelection * >( GetParent() ); |
|
if ( !selection ) |
|
return; |
|
|
|
int wide, tall; |
|
GetSize( wide, tall ); |
|
|
|
float transparencyfrac = m_flGrowFraction; |
|
|
|
float sizefracw = m_flGrowFraction; |
|
float sizefrach = m_flGrowFraction; |
|
float sizefrac = m_flGrowFraction; |
|
|
|
bool buildMenu = m_bBuildMenu; |
|
|
|
bool isactive = info.active; |
|
bool isvalid = info.valid; |
|
|
|
Color iconColor = selection->GetFgColor(); |
|
Color textColor = selection->m_TextColor; |
|
if ( isactive ) |
|
{ |
|
if ( !isvalid ) |
|
{ |
|
iconColor = selection->m_InvalidActiveColor; |
|
textColor = selection->m_InvalidActiveTextColor; |
|
} |
|
} |
|
else |
|
{ |
|
if ( isvalid ) |
|
{ |
|
iconColor = selection->m_OtherColor; |
|
textColor = selection->m_OtherTextColor; |
|
} |
|
else |
|
{ |
|
iconColor = selection->m_InvalidColor; |
|
textColor = selection->m_InvalidTextColor; |
|
} |
|
} |
|
|
|
Color ammoColor = info.ammoCaution ? selection->m_AmmoCautionColor : selection->m_AmmoNormalColor; |
|
|
|
TranslateColor( transparencyfrac, iconColor ); |
|
TranslateColor( transparencyfrac, textColor ); |
|
TranslateColor( transparencyfrac, ammoColor ); |
|
|
|
// Draw box |
|
DrawBox( buildMenu, 0, 0, wide, tall, isactive, isvalid, m_flGrowFraction * 255, m_bDrawNumbers ? menuItem.hotkey : -1 ); |
|
|
|
// icons use old system, drawing in screen space |
|
int iconXPos = m_flIconXPos; |
|
int iconYPos = m_flIconYPos; |
|
int iconWide = m_flIconWidth; |
|
int iconTall = m_flIconHeight; |
|
|
|
if ( info.icon ) |
|
{ |
|
info.icon->DrawSelf( sizefracw * iconXPos, sizefrach * iconYPos, sizefracw * iconWide, sizefrach * iconTall, |
|
iconColor ); |
|
} |
|
|
|
surface()->DrawSetTextColor( textColor ); |
|
HFont textFont = sizefrac < 1.0 ? selection->m_hTextFontSmall : selection->m_hTextFont; |
|
surface()->DrawSetTextFont( textFont ); |
|
//int slen = UTIL_ComputeStringWidth( textFont, info.printname ); |
|
int charCount = Q_strlen( info.printname ); |
|
|
|
int textYPos = m_flTextYPos; |
|
int textXPos = m_flTextXPos; |
|
|
|
surface()->DrawSetTextPos( sizefracw * textXPos, sizefrach * textYPos ); |
|
for (char *pch = info.printname; charCount > 0; pch++, charCount--) |
|
{ |
|
surface()->DrawUnicodeChar(*pch); |
|
} |
|
|
|
if ( info.drawAmmo ) |
|
{ |
|
int ammoBarX = m_flAmmoBarX; |
|
int ammoBarWide = m_flAmmoBarWide; |
|
|
|
// Draw the clip ratio bar |
|
gHUD.DrawProgressBar( |
|
sizefracw * ammoBarX, sizefrach * iconYPos, |
|
sizefracw * ammoBarWide, sizefrach * iconTall, info.ammoPerc, |
|
ammoColor, CHud::HUDPB_VERTICAL ); |
|
} |
|
|
|
// Let the weapon draw stuff too |
|
if ( info.weapon ) |
|
{ |
|
C_WeaponObjectSelection *selectionWeapon = dynamic_cast< C_WeaponObjectSelection * >( info.weapon.Get() ); |
|
if ( selectionWeapon ) |
|
{ |
|
OnWeaponSelectionDrawn( selection, selectionWeapon, isactive, wide, tall, textColor ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: We've just been drawn in the weapon selection |
|
//----------------------------------------------------------------------------- |
|
void CHudWeaponItemPanel::OnWeaponSelectionDrawn( CHudWeaponSelection *selection, C_WeaponObjectSelection *weapon, |
|
bool bCurrentlySelected, int wide, int tall, Color& clr ) |
|
{ |
|
CBaseTFPlayer *pOwner = ToBaseTFPlayer( weapon->GetOwner() ); |
|
if ( !pOwner ) |
|
return; |
|
|
|
// Draw our resource cost |
|
int fontHeight = vgui::surface()->GetFontTall( selection->m_hPriceFont ); |
|
int iCost = CalculateObjectCost( weapon->GetSubType(), pOwner->GetNumObjects(weapon->GetSubType()), pOwner->GetTeamNumber() ); |
|
|
|
int x = wide - m_flPriceXEndPos; |
|
int y = tall - m_flPriceYEndPos - fontHeight; |
|
|
|
char text[ 32 ]; |
|
Q_snprintf( text, sizeof( text ), "%i", iCost ); |
|
|
|
// Compute pixels needed so we can right justify it |
|
int pixels = 0; |
|
char *pch; |
|
for (pch = text; *pch != 0; pch++) |
|
{ |
|
pixels += vgui::surface()->GetCharacterWidth( selection->m_hPriceFont, *pch ); |
|
} |
|
|
|
vgui::surface()->DrawSetTextFont( selection->m_hPriceFont ); |
|
vgui::surface()->DrawSetTextPos( x - pixels, y ); |
|
vgui::surface()->DrawSetTextColor( clr ); |
|
for ( pch = text; *pch; pch++ ) |
|
{ |
|
vgui::surface()->DrawUnicodeChar(*pch); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : percent - |
|
// clr - |
|
//----------------------------------------------------------------------------- |
|
void CHudWeaponItemPanel::TranslateColor( float percent, Color& clr ) |
|
{ |
|
if ( percent >= 1.0f ) |
|
return; |
|
|
|
if ( percent <= 0.75f ) |
|
{ |
|
clr = Color( 0, 0, 0, 0 ); |
|
} |
|
else |
|
{ |
|
float frac = ( percent - 0.75f ) / 0.25f; |
|
|
|
clr = Color( clr[0] * frac, |
|
clr[1] * frac, |
|
clr[2] * frac, |
|
clr[3] * frac ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: draws a selection box |
|
//----------------------------------------------------------------------------- |
|
void CHudWeaponItemPanel::DrawBox( bool isbuildmenu, int x, int y, int wide, int tall, bool isactive, bool isvalid, float normalizedAlpha, int number ) |
|
{ |
|
CHudWeaponSelection *selection = static_cast< CHudWeaponSelection * >( GetParent() ); |
|
if ( !selection ) |
|
{ |
|
Assert( 0 ); |
|
return; |
|
} |
|
|
|
int team = GetTeamIndex(); |
|
|
|
Color boxColor = Color( 255, 255, 255, 255 ); |
|
boxColor[3] *= ( normalizedAlpha / 255.0f ); |
|
|
|
Color numberColor = selection->m_TextColor; |
|
|
|
CHudTexture *texture; |
|
|
|
texture = m_BackgroundIcons[ team ][ (int)IMAGE_BACKGROUND ]; |
|
if ( texture ) |
|
{ |
|
texture->DrawSelf( x, y, wide, tall, boxColor ); |
|
} |
|
|
|
if ( isactive ) |
|
{ |
|
if ( !isvalid ) |
|
{ |
|
texture = m_BackgroundIcons[ team ][ (int)IMAGE_INVALID ]; |
|
if ( texture ) |
|
{ |
|
texture->DrawSelf( x, y, wide, tall, boxColor ); |
|
} |
|
|
|
numberColor = selection->m_InvalidActiveColor; |
|
} |
|
else |
|
{ |
|
texture = m_BackgroundIcons[ team ][ (int)IMAGE_CURRENT ]; |
|
if ( texture ) |
|
{ |
|
texture->DrawSelf( x, y, wide, tall, boxColor ); |
|
} |
|
|
|
numberColor = selection->m_OtherColor; |
|
} |
|
} |
|
else |
|
{ |
|
if ( !isvalid ) |
|
{ |
|
numberColor = selection->m_InvalidColor; |
|
} |
|
else |
|
{ |
|
numberColor = selection->m_OtherColor; |
|
} |
|
} |
|
|
|
// draw the number |
|
if (number >= 0) |
|
{ |
|
numberColor[3] *= ( normalizedAlpha / 255.0f ); |
|
surface()->DrawSetTextColor(numberColor); |
|
surface()->DrawSetTextFont(selection->m_hNumberFont); |
|
wchar_t wch = '0' + number; |
|
surface()->DrawSetTextPos(x + m_flSelectionNumberXPos, y + m_flSelectionNumberYPos); |
|
surface()->DrawUnicodeChar(wch); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : int |
|
//----------------------------------------------------------------------------- |
|
int CHudWeaponItemPanel::GetTeamIndex() |
|
{ |
|
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); |
|
if(!pPlayer) |
|
return HUMAN_WEAPON_SELECTION; |
|
int team = pPlayer->GetTeamNumber(); |
|
if ( !team ) |
|
return HUMAN_WEAPON_SELECTION; |
|
|
|
bool human = ( team == TEAM_HUMANS ) ? true : false; |
|
return human ? HUMAN_WEAPON_SELECTION : ALIEN_WEAPON_SELECTION; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CHudWeaponItemPanel::SetupIcons() |
|
{ |
|
memset( m_BackgroundIcons, 0, sizeof( m_BackgroundIcons ) ); |
|
|
|
const char *menutypestr = m_bBuildMenu ? "build" : "selection"; |
|
|
|
for ( int team = 0; team < NUM_SLOT_TEAMS; team++ ) |
|
{ |
|
const char *teamtype = team == 0 ? "human" : "alien"; |
|
|
|
for ( int type = 0; type < NUM_MENU_TYPES; type++ ) |
|
{ |
|
const char *slottype = type == 0 ? "background" : type == 1 ? "current" : "invalid"; |
|
|
|
char sz[ 256 ]; |
|
Q_snprintf( sz, sizeof( sz ), "%s_weapon_%s_%s_%i", |
|
teamtype, menutypestr, slottype, m_nSlotNumber + 1 ); |
|
|
|
m_BackgroundIcons[ team ][ type ] = gHUD.GetIcon( sz );; |
|
} |
|
} |
|
}
|
|
|