mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-14 12:46:58 +00:00
1
This commit is contained in:
@@ -0,0 +1,870 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
#include "cbase.h"
|
||||
#include "hud.h"
|
||||
#include "hudelement.h"
|
||||
#include "c_tf_player.h"
|
||||
#include "iclientmode.h"
|
||||
#include "ienginevgui.h"
|
||||
#include <vgui/ILocalize.h>
|
||||
#include <vgui/ISurface.h>
|
||||
#include <vgui/IVGui.h>
|
||||
#include "c_baseobject.h"
|
||||
#include "tf_gamerules.h"
|
||||
#include "tf_item_inventory.h"
|
||||
#include "tf_hud_menu_spy_build.h"
|
||||
|
||||
// NVNT haptics for buildings
|
||||
#include "haptics/haptic_utils.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#ifdef STAGING_ONLY
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
// Set to 1 to simulate xbox-style menu interaction
|
||||
extern ConVar tf_build_menu_controller_mode;
|
||||
|
||||
const SpyConstructBuilding_t g_kSpyBuildings[ NUM_SPY_BUILDINGS ] =
|
||||
{
|
||||
// Sap Trap
|
||||
SpyConstructBuilding_t( true,
|
||||
OBJ_SPY_TRAP,
|
||||
MODE_SPY_TRAP_RADIUS_STEALTH,
|
||||
"spy_trap_active.res",
|
||||
"spy_trap_already_built.res",
|
||||
"spy_trap_cant_afford.res",
|
||||
"spy_trap_unavailable.res",
|
||||
"spy_trap_active.res",
|
||||
"spy_trap_inactive.res",
|
||||
"spy_trap_inactive.res" ),
|
||||
|
||||
// Reprogrammer
|
||||
SpyConstructBuilding_t( true,
|
||||
OBJ_SPY_TRAP,
|
||||
MODE_SPY_TRAP_REPROGRAM,
|
||||
"spy_trap_reprog_active.res",
|
||||
"spy_trap_reprog_already_built.res",
|
||||
"spy_trap_reprog_cant_afford.res",
|
||||
"spy_trap_reprog_unavailable.res",
|
||||
"spy_trap_reprog_active.res",
|
||||
"spy_trap_reprog_inactive.res",
|
||||
"spy_trap_reprog_inactive.res" ),
|
||||
|
||||
// Pulse Magnet
|
||||
SpyConstructBuilding_t( true,
|
||||
OBJ_SPY_TRAP,
|
||||
MODE_SPY_TRAP_MAGNET,
|
||||
"spy_trap_magnet_active.res",
|
||||
"spy_trap_magnet_already_built.res",
|
||||
"spy_trap_magnet_cant_afford.res",
|
||||
"spy_trap_magnet_unavailable.res",
|
||||
"spy_trap_magnet_active.res",
|
||||
"spy_trap_magnet_inactive.res",
|
||||
"spy_trap_magnet_inactive.res" ),
|
||||
|
||||
// // Repulsor
|
||||
// SpyConstructBuilding_t( true,
|
||||
// OBJ_SPY_TRAP,
|
||||
// MODE_SPY_TRAP_REPULSOR,
|
||||
// "tele_exit_active.res",
|
||||
// "tele_exit_already_built.res",
|
||||
// "tele_exit_cant_afford.res",
|
||||
// "tele_exit_unavailable.res",
|
||||
// "tele_exit_active.res",
|
||||
// "tele_exit_inactive.res",
|
||||
// "tele_exit_inactive.res" )
|
||||
};
|
||||
|
||||
|
||||
static int trapSlots[NUM_SPY_BUILDINGS] =
|
||||
{
|
||||
0x01,
|
||||
0x02
|
||||
// 0x04,
|
||||
};
|
||||
|
||||
const SpyConstructBuildingReplacement_t s_alternateSpyBuildings[] =
|
||||
{
|
||||
// Temp - modify this
|
||||
SpyConstructBuildingReplacement_t(
|
||||
OBJ_CATAPULT,
|
||||
0,
|
||||
"spy_trap_active.res",
|
||||
"spy_trap_already_built.res",
|
||||
"spy_trap_cant_afford.res",
|
||||
"spy_trap_unavailable.res",
|
||||
"spy_trap_active.res",
|
||||
"spy_trap_inactive.res",
|
||||
"spy_trap_inactive.res",
|
||||
trapSlots[0],
|
||||
trapSlots[1]
|
||||
),
|
||||
// Add more objects here
|
||||
};
|
||||
|
||||
|
||||
//======================================
|
||||
DECLARE_HUDELEMENT_DEPTH( CHudMenuSpyBuild, 40 );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CHudMenuSpyBuild::CHudMenuSpyBuild( const char *pElementName )
|
||||
: CHudBaseBuildMenu( pElementName, "HudMenuSpyBuild" )
|
||||
{
|
||||
Panel *pParent = g_pClientMode->GetViewport();
|
||||
SetParent( pParent );
|
||||
|
||||
SetHiddenBits( HIDEHUD_MISCSTATUS );
|
||||
|
||||
for ( int i = 0; i < NUM_SPY_BUILDINGS; i++ )
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
Q_snprintf( buf, sizeof(buf), "active_item_%d", i+1 );
|
||||
m_pAvailableObjects[i] = new EditablePanel( this, buf );
|
||||
|
||||
Q_snprintf( buf, sizeof(buf), "already_built_item_%d", i+1 );
|
||||
m_pAlreadyBuiltObjects[i] = new EditablePanel( this, buf );
|
||||
|
||||
Q_snprintf( buf, sizeof(buf), "cant_afford_item_%d", i+1 );
|
||||
m_pCantAffordObjects[i] = new EditablePanel( this, buf );
|
||||
|
||||
Q_snprintf( buf, sizeof(buf), "unavailable_item_%d", i+1 );
|
||||
m_pUnavailableObjects[i] = new EditablePanel( this, buf );
|
||||
}
|
||||
|
||||
vgui::ivgui()->AddTickSignal( GetVPanel() );
|
||||
|
||||
m_pActiveSelection = NULL;
|
||||
m_iSelectedItem = -1;
|
||||
m_pBuildLabelBright = NULL;
|
||||
m_pBuildLabelDim = NULL;
|
||||
m_pDestroyLabelBright = NULL;
|
||||
m_pDestroyLabelDim = NULL;
|
||||
m_bInConsoleMode = false;
|
||||
m_iCurrentBuildMenuLayout = SPY_BUILDMENU_DEFAULT;
|
||||
|
||||
RegisterForRenderGroup( "mid" );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudMenuSpyBuild::ApplySchemeSettings( IScheme *pScheme )
|
||||
{
|
||||
// load control settings...
|
||||
bool b360Style = ( IsConsole() || tf_build_menu_controller_mode.GetBool() );
|
||||
if ( b360Style )
|
||||
{
|
||||
// This entire block is unused and ancient. Will need to support a controller
|
||||
// once we deem spy traps as shippable, but for now they're a prototype.
|
||||
|
||||
// LoadControlSettings( "resource/UI/build_menu_360/HudMenuSpyBuild.res" );
|
||||
//
|
||||
// // Load the already built images, destroyable
|
||||
// m_pAlreadyBuiltObjects[0]->LoadControlSettings( "resource/UI/build_menu_360/sentry_already_built.res" );
|
||||
// m_pAlreadyBuiltObjects[1]->LoadControlSettings( "resource/UI/build_menu_360/dispenser_already_built.res" );
|
||||
// m_pAlreadyBuiltObjects[2]->LoadControlSettings( "resource/UI/build_menu_360/tele_entrance_already_built.res" );
|
||||
// m_pAlreadyBuiltObjects[3]->LoadControlSettings( "resource/UI/build_menu_360/tele_exit_already_built.res" );
|
||||
//
|
||||
// m_pAvailableObjects[0]->LoadControlSettings( "resource/UI/build_menu_360/sentry_active.res" );
|
||||
// m_pAvailableObjects[1]->LoadControlSettings( "resource/UI/build_menu_360/dispenser_active.res" );
|
||||
// m_pAvailableObjects[2]->LoadControlSettings( "resource/UI/build_menu_360/tele_entrance_active.res" );
|
||||
// m_pAvailableObjects[3]->LoadControlSettings( "resource/UI/build_menu_360/tele_exit_active.res" );
|
||||
//
|
||||
// m_pCantAffordObjects[0]->LoadControlSettings( "resource/UI/build_menu_360/sentry_cant_afford.res" );
|
||||
// m_pCantAffordObjects[1]->LoadControlSettings( "resource/UI/build_menu_360/dispenser_cant_afford.res" );
|
||||
// m_pCantAffordObjects[2]->LoadControlSettings( "resource/UI/build_menu_360/tele_entrance_cant_afford.res" );
|
||||
// m_pCantAffordObjects[3]->LoadControlSettings( "resource/UI/build_menu_360/tele_exit_cant_afford.res" );
|
||||
//
|
||||
// m_pUnavailableObjects[0]->LoadControlSettings( "resource/UI/build_menu/sentry_unavailable.res" );
|
||||
// m_pUnavailableObjects[1]->LoadControlSettings( "resource/UI/build_menu/dispenser_unavailable.res" );
|
||||
// m_pUnavailableObjects[2]->LoadControlSettings( "resource/UI/build_menu/tele_entrance_unavailable.res" );
|
||||
// m_pUnavailableObjects[3]->LoadControlSettings( "resource/UI/build_menu/tele_exit_unavailable.res" );
|
||||
//
|
||||
// m_pActiveSelection = dynamic_cast< CIconPanel * >( FindChildByName( "active_selection_bg" ) );
|
||||
// m_pBuildLabelBright = dynamic_cast< CExLabel * >( FindChildByName( "BuildHintLabel_Bright" ) );
|
||||
// m_pBuildLabelDim = dynamic_cast< CExLabel * >( FindChildByName( "BuildHintLabel_Dim" ) );
|
||||
// m_pDestroyLabelBright = dynamic_cast< CExLabel * >( FindChildByName( "DestroyHintLabel_Bright" ) );
|
||||
// m_pDestroyLabelDim = dynamic_cast< CExLabel * >( FindChildByName( "DestroyHintLabel_Dim" ) );
|
||||
|
||||
// Reposition the activeselection to the default position
|
||||
m_iSelectedItem = -1; // force reposition
|
||||
SetSelectedItem( 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *pszCustomDir = NULL;
|
||||
switch( m_iCurrentBuildMenuLayout )
|
||||
{
|
||||
default:
|
||||
case SPY_BUILDMENU_DEFAULT:
|
||||
pszCustomDir = "resource/UI/build_menu";
|
||||
break;
|
||||
}
|
||||
|
||||
LoadControlSettings( VarArgs("%s/HudMenuSpyBuild.res",pszCustomDir) );
|
||||
|
||||
// Load the already built images, not destroyable
|
||||
for ( int i = 0; i < NUM_SPY_BUILDINGS; ++i )
|
||||
{
|
||||
m_pAvailableObjects[i]->LoadControlSettings( VarArgs( "%s/%s", pszCustomDir, m_Buildings[i].m_pszConstructAvailableObjectRes ) );
|
||||
m_pAlreadyBuiltObjects[i]->LoadControlSettings( VarArgs( "%s/%s", pszCustomDir, m_Buildings[i].m_pszConstructAlreadyBuiltObjectRes ) );
|
||||
m_pCantAffordObjects[i]->LoadControlSettings( VarArgs( "%s/%s", pszCustomDir, m_Buildings[i].m_pszConstructCantAffordObjectRes ) );
|
||||
m_pUnavailableObjects[i]->LoadControlSettings( VarArgs( "%s/%s", pszCustomDir, m_Buildings[i].m_pszConstructUnavailableObjectRes ) );
|
||||
}
|
||||
|
||||
m_pActiveSelection = NULL;
|
||||
m_pBuildLabelBright = NULL;
|
||||
m_pBuildLabelDim = NULL;
|
||||
m_pDestroyLabelBright = NULL;
|
||||
m_pDestroyLabelDim = NULL;
|
||||
}
|
||||
|
||||
// Set the cost label
|
||||
for ( int i = 0; i < NUM_SPY_BUILDINGS; i++ )
|
||||
{
|
||||
int iBuilding, iMode;
|
||||
GetBuildingIDAndModeFromSlot( i+1, iBuilding, iMode, m_Buildings );
|
||||
int iCost = GetObjectInfo( iBuilding )->m_Cost;
|
||||
|
||||
m_pAvailableObjects[i]->SetDialogVariable( "metal", iCost );
|
||||
m_pAlreadyBuiltObjects[i]->SetDialogVariable( "metal", iCost );
|
||||
m_pCantAffordObjects[i]->SetDialogVariable( "metal", iCost );
|
||||
m_pUnavailableObjects[i]->SetDialogVariable( "metal", iCost );
|
||||
}
|
||||
|
||||
BaseClass::ApplySchemeSettings( pScheme );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CHudMenuSpyBuild::ShouldDraw( void )
|
||||
{
|
||||
if ( !TFGameRules() || !TFGameRules()->GameModeUsesUpgrades() )
|
||||
return false;
|
||||
|
||||
CTFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
|
||||
if ( !pPlayer )
|
||||
return false;
|
||||
|
||||
if ( !pPlayer->m_Shared.CanBuildSpyTraps() )
|
||||
return false;
|
||||
|
||||
return BaseClass::ShouldDraw();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudMenuSpyBuild::GetBuildingIDAndModeFromSlot( int iSlot, int &iBuilding, int &iMode, const SpyConstructBuilding_t (&buildings)[ NUM_SPY_BUILDINGS ] )
|
||||
{
|
||||
iBuilding = OBJ_LAST;
|
||||
iMode = 0;
|
||||
int index = iSlot - 1;
|
||||
if ( index >= 0 && index < NUM_SPY_BUILDINGS )
|
||||
{
|
||||
iBuilding = buildings[index].m_iObjectType;
|
||||
iMode = buildings[index].m_iMode;
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert( !"What slot are we asking for and why?" );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Keyboard input hook. Return 0 if handled
|
||||
//-----------------------------------------------------------------------------
|
||||
int CHudMenuSpyBuild::HudElementKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding )
|
||||
{
|
||||
if ( !ShouldDraw() )
|
||||
return 1;
|
||||
|
||||
if ( !down )
|
||||
return 1;
|
||||
|
||||
bool bController = ( IsConsole() || ( keynum >= JOYSTICK_FIRST ) );
|
||||
if ( bController )
|
||||
{
|
||||
int iNewSelection = m_iSelectedItem;
|
||||
|
||||
switch( keynum )
|
||||
{
|
||||
case KEY_XBUTTON_UP:
|
||||
case STEAMCONTROLLER_DPAD_UP:
|
||||
// jump to last
|
||||
iNewSelection = NUM_SPY_BUILDINGS;
|
||||
break;
|
||||
|
||||
case KEY_XBUTTON_DOWN:
|
||||
case STEAMCONTROLLER_DPAD_DOWN:
|
||||
// jump to first
|
||||
iNewSelection = 1;
|
||||
break;
|
||||
|
||||
case KEY_XBUTTON_RIGHT:
|
||||
case STEAMCONTROLLER_DPAD_RIGHT:
|
||||
// move selection to the right
|
||||
iNewSelection++;
|
||||
if ( iNewSelection > NUM_SPY_BUILDINGS )
|
||||
iNewSelection = 1;
|
||||
break;
|
||||
|
||||
case KEY_XBUTTON_LEFT:
|
||||
case STEAMCONTROLLER_DPAD_LEFT:
|
||||
// move selection to the left
|
||||
iNewSelection--;
|
||||
if ( iNewSelection < 1 )
|
||||
iNewSelection = NUM_SPY_BUILDINGS;
|
||||
break;
|
||||
|
||||
case KEY_XBUTTON_A:
|
||||
case KEY_XBUTTON_RTRIGGER:
|
||||
case STEAMCONTROLLER_A:
|
||||
// build selected item
|
||||
SendBuildMessage( m_iSelectedItem );
|
||||
return 0;
|
||||
|
||||
case KEY_XBUTTON_Y:
|
||||
case KEY_XBUTTON_LTRIGGER:
|
||||
case STEAMCONTROLLER_Y:
|
||||
{
|
||||
// destroy selected item
|
||||
bool bSuccess = SendDestroyMessage( m_iSelectedItem );
|
||||
|
||||
if ( bSuccess )
|
||||
{
|
||||
engine->ExecuteClientCmd( "lastinv" );
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
case KEY_XBUTTON_B:
|
||||
case STEAMCONTROLLER_B:
|
||||
// cancel, close the menu
|
||||
engine->ExecuteClientCmd( "lastinv" );
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return 1; // key not handled
|
||||
}
|
||||
|
||||
SetSelectedItem( iNewSelection );
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int iSlot = 0;
|
||||
|
||||
// convert slot1, slot2 etc to 1,2,3,4
|
||||
if( pszCurrentBinding && ( !Q_strncmp( pszCurrentBinding, "slot", NUM_SPY_BUILDINGS ) && Q_strlen(pszCurrentBinding) > NUM_SPY_BUILDINGS ) )
|
||||
{
|
||||
const char *pszNum = pszCurrentBinding + Q_strlen( "slot" );
|
||||
iSlot = atoi(pszNum);
|
||||
|
||||
// slot10 cancels
|
||||
if ( iSlot == 10 )
|
||||
{
|
||||
engine->ExecuteClientCmd( "lastinv" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// allow slot1 - slot4
|
||||
if ( iSlot < 1 || iSlot > NUM_SPY_BUILDINGS )
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( keynum )
|
||||
{
|
||||
case KEY_1:
|
||||
iSlot = 1;
|
||||
break;
|
||||
case KEY_2:
|
||||
iSlot = 2;
|
||||
break;
|
||||
case KEY_3:
|
||||
iSlot = 3;
|
||||
break;
|
||||
case KEY_4:
|
||||
iSlot = 4;
|
||||
break;
|
||||
|
||||
case KEY_5:
|
||||
case KEY_6:
|
||||
case KEY_7:
|
||||
case KEY_8:
|
||||
case KEY_9:
|
||||
// Eat these keys
|
||||
return 0;
|
||||
|
||||
case KEY_0:
|
||||
case KEY_XBUTTON_B:
|
||||
case STEAMCONTROLLER_B:
|
||||
// cancel, close the menu
|
||||
engine->ExecuteClientCmd( "lastinv" );
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return 1; // key not handled
|
||||
}
|
||||
}
|
||||
|
||||
if ( iSlot > 0 )
|
||||
{
|
||||
SendBuildMessage( iSlot );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1; // key not handled
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudMenuSpyBuild::SendBuildMessage( int iSlot )
|
||||
{
|
||||
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
|
||||
|
||||
if ( !pLocalPlayer )
|
||||
return;
|
||||
|
||||
int iBuilding, iMode;
|
||||
GetBuildingIDAndModeFromSlot( iSlot, iBuilding, iMode, m_Buildings );
|
||||
|
||||
if ( CanBuild( iSlot ) == false )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
C_BaseObject *pObj = pLocalPlayer->GetObjectOfType( iBuilding, iMode );
|
||||
int iCost = pLocalPlayer->m_Shared.CalculateObjectCost( pLocalPlayer, iBuilding );
|
||||
|
||||
if ( !pObj && pLocalPlayer->GetAmmoCount( TF_AMMO_GRENADES1 ) >= iCost )
|
||||
{
|
||||
char szCmd[128];
|
||||
Q_snprintf( szCmd, sizeof(szCmd), "build %d %d", iBuilding, iMode );
|
||||
engine->ClientCmd( szCmd );
|
||||
// NVNT send the build command
|
||||
if ( haptics )
|
||||
haptics->ProcessHapticEvent(2, "Game", szCmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
pLocalPlayer->EmitSound( "Player.DenyWeaponSelection" );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CHudMenuSpyBuild::SendDestroyMessage( int iSlot )
|
||||
{
|
||||
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
|
||||
|
||||
if ( !pLocalPlayer )
|
||||
return false;
|
||||
|
||||
bool bSuccess = false;
|
||||
|
||||
int iBuilding, iMode;
|
||||
GetBuildingIDAndModeFromSlot( iSlot, iBuilding, iMode, m_Buildings );
|
||||
|
||||
C_BaseObject *pObj = pLocalPlayer->GetObjectOfType( iBuilding, iMode );
|
||||
|
||||
if ( pObj != NULL )
|
||||
{
|
||||
char szCmd[128];
|
||||
Q_snprintf( szCmd, sizeof(szCmd), "destroy %d %d", iBuilding, iMode );
|
||||
engine->ClientCmd( szCmd );
|
||||
// NVNT send the destroy command
|
||||
if ( haptics )
|
||||
haptics->ProcessHapticEvent(2, "Game", szCmd);
|
||||
bSuccess = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
pLocalPlayer->EmitSound( "Player.DenyWeaponSelection" );
|
||||
}
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudMenuSpyBuild::OnTick( void )
|
||||
{
|
||||
if ( !IsVisible() )
|
||||
return;
|
||||
|
||||
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
|
||||
|
||||
if ( !pLocalPlayer )
|
||||
return;
|
||||
|
||||
int iAmmo = pLocalPlayer->GetAmmoCount( TF_AMMO_GRENADES1 );
|
||||
|
||||
for ( int i = 0;i < NUM_SPY_BUILDINGS; i++ )
|
||||
{
|
||||
int iRemappedObjectID, iMode;
|
||||
GetBuildingIDAndModeFromSlot( i + 1, iRemappedObjectID, iMode, m_Buildings );
|
||||
|
||||
// update this slot
|
||||
C_BaseObject *pObj = NULL;
|
||||
|
||||
if ( pLocalPlayer )
|
||||
{
|
||||
pObj = pLocalPlayer->GetObjectOfType( iRemappedObjectID, iMode );
|
||||
}
|
||||
|
||||
m_pAvailableObjects[i]->SetVisible( false );
|
||||
m_pAlreadyBuiltObjects[i]->SetVisible( false );
|
||||
m_pCantAffordObjects[i]->SetVisible( false );
|
||||
m_pUnavailableObjects[i]->SetVisible( false );
|
||||
|
||||
if ( !m_Buildings[i].m_bEnabled )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int iCost = pLocalPlayer->m_Shared.CalculateObjectCost( pLocalPlayer, iRemappedObjectID );
|
||||
bool bAvailable = CanBuild( i + 1 );
|
||||
|
||||
// If the building is already built, and we don't have an ability to build more than one (sentry)
|
||||
if ( pObj != NULL && !pObj->IsPlacing() && !( pLocalPlayer->CanBuild( iRemappedObjectID, iMode ) == CB_CAN_BUILD ) )
|
||||
{
|
||||
m_pAlreadyBuiltObjects[i]->SetVisible( true );
|
||||
}
|
||||
// unavailable
|
||||
else if ( bAvailable == false )
|
||||
{
|
||||
m_pUnavailableObjects[i]->SetVisible( true );
|
||||
}
|
||||
// See if we can afford it
|
||||
else if ( iAmmo < iCost )
|
||||
{
|
||||
m_pCantAffordObjects[i]->SetVisible( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
// we can buy it
|
||||
m_pAvailableObjects[i]->SetVisible( true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudMenuSpyBuild::SetVisible( bool state )
|
||||
{
|
||||
if ( state == true )
|
||||
{
|
||||
InitBuildings();
|
||||
|
||||
// close the weapon selection menu
|
||||
engine->ClientCmd( "cancelselect" );
|
||||
|
||||
bool bConsoleMode = ( IsConsole() || tf_build_menu_controller_mode.GetBool() );
|
||||
|
||||
if ( bConsoleMode != m_bInConsoleMode )
|
||||
{
|
||||
InvalidateLayout( true, true );
|
||||
m_bInConsoleMode = bConsoleMode;
|
||||
}
|
||||
else
|
||||
{
|
||||
// See if our layout needs to change, due to equipped items
|
||||
int iDesired = CalcCustomBuildMenuLayout();
|
||||
if ( iDesired != m_iCurrentBuildMenuLayout )
|
||||
{
|
||||
m_iCurrentBuildMenuLayout = (spybuildmenulayouts_t)iDesired;
|
||||
InvalidateLayout( true, true );
|
||||
}
|
||||
}
|
||||
|
||||
// set the %lastinv% dialog var to our binding
|
||||
const char *key = engine->Key_LookupBinding( "lastinv" );
|
||||
if ( !key )
|
||||
{
|
||||
key = "< not bound >";
|
||||
}
|
||||
|
||||
SetDialogVariable( "lastinv", key );
|
||||
|
||||
// Set selection to the first available building that we can build
|
||||
|
||||
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
|
||||
if ( !pLocalPlayer )
|
||||
return;
|
||||
|
||||
int iDefaultSlot = 1;
|
||||
|
||||
// Find the first slot that represents a building that we haven't built
|
||||
int iSlot;
|
||||
for ( iSlot = 1; iSlot <= NUM_SPY_BUILDINGS; iSlot++ )
|
||||
{
|
||||
int iBuilding, iMode;
|
||||
GetBuildingIDAndModeFromSlot( iSlot, iBuilding, iMode, m_Buildings );
|
||||
C_BaseObject *pObj = pLocalPlayer->GetObjectOfType( iBuilding, iMode );
|
||||
|
||||
if ( pObj == NULL )
|
||||
{
|
||||
iDefaultSlot = iSlot;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_iSelectedItem = -1; //force redo
|
||||
SetSelectedItem( iDefaultSlot );
|
||||
|
||||
HideLowerPriorityHudElementsInGroup( "mid" );
|
||||
|
||||
for ( int i = 0; i < NUM_SPY_BUILDINGS; i++ )
|
||||
{
|
||||
int iBuilding, iMode;
|
||||
GetBuildingIDAndModeFromSlot( i + 1, iBuilding, iMode, m_Buildings );
|
||||
int iCost = pLocalPlayer->m_Shared.CalculateObjectCost( pLocalPlayer, iBuilding );
|
||||
m_pAvailableObjects[i]->SetDialogVariable( "metal", iCost );
|
||||
m_pAlreadyBuiltObjects[i]->SetDialogVariable( "metal", iCost );
|
||||
m_pCantAffordObjects[i]->SetDialogVariable( "metal", iCost );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UnhideLowerPriorityHudElementsInGroup( "mid" );
|
||||
}
|
||||
|
||||
BaseClass::SetVisible( state );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudMenuSpyBuild::SetSelectedItem( int iSlot )
|
||||
{
|
||||
if ( m_iSelectedItem != iSlot )
|
||||
{
|
||||
m_iSelectedItem = iSlot;
|
||||
|
||||
// move the selection item to the new position
|
||||
if ( m_pActiveSelection )
|
||||
{
|
||||
// move the selection background
|
||||
int x, y;
|
||||
m_pAlreadyBuiltObjects[m_iSelectedItem-1]->GetPos( x, y );
|
||||
|
||||
x -= XRES(NUM_SPY_BUILDINGS);
|
||||
y -= XRES(NUM_SPY_BUILDINGS);
|
||||
|
||||
m_pActiveSelection->SetPos( x, y );
|
||||
|
||||
UpdateHintLabels();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudMenuSpyBuild::UpdateHintLabels( void )
|
||||
{
|
||||
// hilight the action we can perform ( build or destroy or neither )
|
||||
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
|
||||
|
||||
if ( pLocalPlayer )
|
||||
{
|
||||
int iBuilding, iMode;
|
||||
GetBuildingIDAndModeFromSlot( m_iSelectedItem, iBuilding, iMode, m_Buildings );
|
||||
C_BaseObject *pObj = pLocalPlayer->GetObjectOfType( iBuilding );
|
||||
|
||||
bool bDestroyLabelBright = false;
|
||||
bool bBuildLabelBright = false;
|
||||
|
||||
int iCost = pLocalPlayer->m_Shared.CalculateObjectCost( pLocalPlayer, iBuilding );
|
||||
|
||||
if ( pObj )
|
||||
{
|
||||
// hilight destroy, we have a building
|
||||
bDestroyLabelBright = true;
|
||||
}
|
||||
else if ( pLocalPlayer->GetAmmoCount( TF_AMMO_GRENADES1 ) >= iCost ) // I can afford it
|
||||
{
|
||||
// hilight build, we can build this
|
||||
bBuildLabelBright = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// dim both, do nothing
|
||||
}
|
||||
|
||||
if ( m_pDestroyLabelBright && m_pDestroyLabelDim && m_pBuildLabelBright && m_pBuildLabelDim )
|
||||
{
|
||||
m_pDestroyLabelBright->SetVisible( bDestroyLabelBright );
|
||||
m_pDestroyLabelDim->SetVisible( !bDestroyLabelBright );
|
||||
m_pBuildLabelBright->SetVisible( bBuildLabelBright );
|
||||
m_pBuildLabelDim->SetVisible( !bBuildLabelBright );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
int CHudMenuSpyBuild::CalcCustomBuildMenuLayout( void ) const
|
||||
{
|
||||
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
|
||||
if ( !pLocalPlayer )
|
||||
return SPY_BUILDMENU_DEFAULT;
|
||||
|
||||
int iMenu = SPY_BUILDMENU_DEFAULT;
|
||||
CALL_ATTRIB_HOOK_INT_ON_OTHER( pLocalPlayer, iMenu, set_custom_buildmenu );
|
||||
return iMenu;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudMenuSpyBuild::InitBuildings()
|
||||
{
|
||||
for( int i = 0; i < NUM_SPY_BUILDINGS; ++i )
|
||||
{
|
||||
m_Buildings[i] = g_kSpyBuildings[i];
|
||||
}
|
||||
|
||||
ReplaceBuildings( m_Buildings );
|
||||
|
||||
InvalidateLayout( true, true );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudMenuSpyBuild::ReplaceBuildings( SpyConstructBuilding_t (&targetBuildings)[NUM_SPY_BUILDINGS] )
|
||||
{
|
||||
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
|
||||
if ( !pLocalPlayer )
|
||||
return;
|
||||
|
||||
int iOverrideType = -1;
|
||||
CALL_ATTRIB_HOOK_INT_ON_OTHER( pLocalPlayer, iOverrideType, override_engineer_object_type );
|
||||
|
||||
CUtlVector< const SpyConstructBuildingReplacement_t* > vecReplacements;
|
||||
|
||||
if ( iOverrideType >= 0 && iOverrideType < ARRAYSIZE( s_alternateSpyBuildings ) )
|
||||
{
|
||||
vecReplacements.AddToTail( &s_alternateSpyBuildings[iOverrideType] );
|
||||
}
|
||||
// add more replacement attributes here
|
||||
|
||||
// verify the override data to make sure that they don't conflict with each other
|
||||
int iReplacedSlots = 0;
|
||||
int iDisabledSlots = 0;
|
||||
bool bReplaced = false;
|
||||
for ( int i = 0; i < vecReplacements.Count(); ++i )
|
||||
{
|
||||
const SpyConstructBuildingReplacement_t* pReplace = vecReplacements[i];
|
||||
int iReplacingSlots = pReplace->m_iReplacementSlots;
|
||||
int iDisablingSlots = pReplace->m_iDisableSlots;
|
||||
|
||||
if ( iReplacedSlots & iReplacingSlots )
|
||||
{
|
||||
AssertMsg( 0, "Trying to replace the same engineer building slot multiple time" );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( iReplacedSlots & iDisablingSlots )
|
||||
{
|
||||
AssertMsg( 0, "Trying to disable a replaced engineer building slot" );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( iDisabledSlots & iReplacingSlots )
|
||||
{
|
||||
AssertMsg( 0, "Trying to replace a disabled slot" );
|
||||
continue;
|
||||
}
|
||||
|
||||
// no conflict, replace the building
|
||||
for ( int j = 0; j < ARRAYSIZE( trapSlots ); ++j )
|
||||
{
|
||||
COMPILE_TIME_ASSERT( ARRAYSIZE( targetBuildings ) == ARRAYSIZE( trapSlots ) );
|
||||
if ( trapSlots[j] & iReplacingSlots )
|
||||
{
|
||||
targetBuildings[j] = pReplace->m_building;
|
||||
}
|
||||
else if ( trapSlots[j] & iDisablingSlots )
|
||||
{
|
||||
targetBuildings[j].m_bEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
iReplacedSlots |= iReplacingSlots;
|
||||
iDisabledSlots |= iDisablingSlots;
|
||||
bReplaced = true;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CHudMenuSpyBuild::CanBuild( int iSlot )
|
||||
{
|
||||
bool bInTraining = TFGameRules() && TFGameRules()->IsInTraining();
|
||||
if ( bInTraining == false )
|
||||
{
|
||||
int slot = iSlot - 1;
|
||||
if ( slot >= 0 && slot < NUM_SPY_BUILDINGS )
|
||||
{
|
||||
return m_Buildings[slot].m_bEnabled;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bCanBuild = true;
|
||||
switch ( iSlot )
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
ConVarRef training_can_build_sentry( "training_can_build_sentry");
|
||||
bCanBuild = training_can_build_sentry.GetInt() != 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
ConVarRef training_can_build_dispenser( "training_can_build_dispenser");
|
||||
bCanBuild = training_can_build_dispenser.GetInt() != 0;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
ConVarRef training_can_build_tele_entrance( "training_can_build_tele_entrance");
|
||||
bCanBuild = training_can_build_tele_entrance.GetInt() != 0;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
ConVarRef training_can_build_tele_exit( "training_can_build_tele_exit");
|
||||
bCanBuild = training_can_build_tele_exit.GetInt() != 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return bCanBuild;
|
||||
}
|
||||
#endif // STAGING_ONLY
|
||||
|
||||
Reference in New Issue
Block a user