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.
415 lines
11 KiB
415 lines
11 KiB
![]()
4 years ago
|
//========= 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 <vgui/ILocalize.h>
|
||
|
#include <vgui/ISurface.h>
|
||
|
#include <vgui/IVGui.h>
|
||
|
#include "c_baseobject.h"
|
||
|
#include "inputsystem/iinputsystem.h"
|
||
|
|
||
|
#include "tf_hud_menu_eureka_teleport.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"
|
||
|
|
||
|
using namespace vgui;
|
||
|
|
||
|
// Set to 1 to simulate xbox-style menu interaction
|
||
|
extern ConVar tf_build_menu_controller_mode;
|
||
|
|
||
|
|
||
|
DECLARE_HUDELEMENT_DEPTH( CHudEurekaEffectTeleportMenu, 41 ); // in front of engy building status
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CHudEurekaEffectTeleportMenu::CHudEurekaEffectTeleportMenu( const char *pElementName )
|
||
|
: CHudElement( pElementName )
|
||
|
, BaseClass( NULL, "HudEurekaEffectTeleportMenu" )
|
||
|
, m_bWantsToTeleport( false )
|
||
|
, m_eSelectedTeleportTarget( EUREKA_TELEPORT_HOME )
|
||
|
, m_eCurrentBuildMenuLayout( BUILDMENU_DEFAULT )
|
||
|
{
|
||
|
Panel *pParent = g_pClientMode->GetViewport();
|
||
|
SetParent( pParent );
|
||
|
|
||
|
SetHiddenBits( HIDEHUD_MISCSTATUS );
|
||
|
|
||
|
vgui::ivgui()->AddTickSignal( GetVPanel() );
|
||
|
|
||
|
for( int i=0; i < EUREKA_NUM_TARGETS; ++i )
|
||
|
{
|
||
|
m_pAvilableTargets[ i ] = new EditablePanel( this, VarArgs( "available_target_%d", i+1 ) );
|
||
|
m_pUnavailableTargets[ i ] = new EditablePanel( this, VarArgs( "unavailable_target_%d", i+1 ) );
|
||
|
}
|
||
|
|
||
|
RegisterForRenderGroup( "mid" );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CHudEurekaEffectTeleportMenu::ApplySchemeSettings( IScheme *pScheme )
|
||
|
{
|
||
|
const char *pszCustomDir = NULL;
|
||
|
switch( m_eCurrentBuildMenuLayout )
|
||
|
{
|
||
|
case BUILDMENU_PIPBOY:
|
||
|
pszCustomDir = "resource/UI/build_menu/pipboy";
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
case BUILDMENU_DEFAULT:
|
||
|
if ( ::input->IsSteamControllerActive() )
|
||
|
{
|
||
|
pszCustomDir = "resource/UI/build_menu_sc";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pszCustomDir = "resource/UI/build_menu";
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
LoadControlSettings( VarArgs( "%s/HudMenuEurekaEffect.res", pszCustomDir) );
|
||
|
|
||
|
m_pAvilableTargets[ EUREKA_TELEPORT_HOME ]->LoadControlSettings( VarArgs( "%s/eureka_target_home_avail.res", pszCustomDir ) );
|
||
|
m_pAvilableTargets[ EUREKA_TELEPORT_TELEPORTER_EXIT ]->LoadControlSettings( VarArgs( "%s/eureka_target_tele_exit_avail.res", pszCustomDir ) );
|
||
|
|
||
|
m_pUnavailableTargets[ EUREKA_TELEPORT_HOME ]->LoadControlSettings( VarArgs( "%s/eureka_target_home_unavail.res", pszCustomDir ) );
|
||
|
m_pUnavailableTargets[ EUREKA_TELEPORT_TELEPORTER_EXIT ]->LoadControlSettings( VarArgs( "%s/eureka_target_tele_exit_unavail.res", pszCustomDir ) );
|
||
|
|
||
|
BaseClass::ApplySchemeSettings( pScheme );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CHudEurekaEffectTeleportMenu::ShouldDraw( void )
|
||
|
{
|
||
|
if ( !CanTeleport() )
|
||
|
{
|
||
|
m_bWantsToTeleport = false;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CHudEurekaEffectTeleportMenu::SetVisible( bool bState )
|
||
|
{
|
||
|
if ( bState == true )
|
||
|
{
|
||
|
// close the weapon selection menu
|
||
|
engine->ClientCmd( "cancelselect" );
|
||
|
|
||
|
// See if our layout needs to change, due to equipped items
|
||
|
buildmenulayouts_t eDesired = CHudMenuEngyBuild::CalcCustomBuildMenuLayout();
|
||
|
if ( eDesired != m_eCurrentBuildMenuLayout )
|
||
|
{
|
||
|
m_eCurrentBuildMenuLayout = eDesired;
|
||
|
InvalidateLayout( true, true );
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
|
||
|
m_eSelectedTeleportTarget = EUREKA_TELEPORT_HOME;
|
||
|
SetSelectedItem( m_eSelectedTeleportTarget );
|
||
|
|
||
|
HideLowerPriorityHudElementsInGroup( "mid" );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
UnhideLowerPriorityHudElementsInGroup( "mid" );
|
||
|
}
|
||
|
|
||
|
BaseClass::SetVisible( bState );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CHudEurekaEffectTeleportMenu::CanTeleport() const
|
||
|
{
|
||
|
if ( !m_bWantsToTeleport )
|
||
|
return false;
|
||
|
|
||
|
CTFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
|
||
|
if ( !pPlayer )
|
||
|
return false;
|
||
|
|
||
|
CTFWeaponBase *pWpn = pPlayer->GetActiveTFWeapon();
|
||
|
|
||
|
if ( !pWpn )
|
||
|
return false;
|
||
|
|
||
|
// Don't show the menu for first person spectator
|
||
|
if ( pPlayer != pWpn->GetOwner() )
|
||
|
return false;
|
||
|
|
||
|
if ( !const_cast<CHudEurekaEffectTeleportMenu*>(this)->CHudElement::ShouldDraw() )
|
||
|
return false;
|
||
|
|
||
|
return ( pWpn->GetWeaponID() == TF_WEAPON_WRENCH );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CHudEurekaEffectTeleportMenu::SendTeleportMessage( eEurekaTeleportTargets eTeleportTarget )
|
||
|
{
|
||
|
// They've made their selection. Setting this to false will close this panel.
|
||
|
m_bWantsToTeleport = false;
|
||
|
|
||
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
|
||
|
|
||
|
if ( !pLocalPlayer )
|
||
|
return;
|
||
|
|
||
|
// We do code elsewhere that set the available targets panel visible if they're available.
|
||
|
// If it's not visible, it's not available.
|
||
|
|
||
|
// Can not use while karting
|
||
|
if ( !m_pAvilableTargets[ eTeleportTarget ]->IsVisible() || pLocalPlayer->m_Shared.InCond( TF_COND_HALLOWEEN_KART ) )
|
||
|
{
|
||
|
pLocalPlayer->EmitSound( "Player.DenyWeaponSelection" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
char szCmd[128];
|
||
|
Q_snprintf( szCmd, sizeof(szCmd), "eureka_teleport %d", (int)eTeleportTarget );
|
||
|
engine->ClientCmd( szCmd );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int CHudEurekaEffectTeleportMenu::HudElementKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding )
|
||
|
{
|
||
|
if ( !ShouldDraw() )
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
if ( !down )
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
bool bConsoleController = ( IsConsole() || ( keynum >= JOYSTICK_FIRST && !IsSteamControllerCode(keynum)) );
|
||
|
|
||
|
if ( bConsoleController )
|
||
|
{
|
||
|
int nNewSelection = m_eSelectedTeleportTarget;
|
||
|
|
||
|
switch( keynum )
|
||
|
{
|
||
|
case KEY_XBUTTON_UP:
|
||
|
// jump to last
|
||
|
nNewSelection = EUREKA_LAST_TARGET;
|
||
|
break;
|
||
|
|
||
|
case KEY_XBUTTON_DOWN:
|
||
|
// jump to first
|
||
|
nNewSelection = EUREKA_FIRST_TARGET;
|
||
|
break;
|
||
|
|
||
|
case KEY_XBUTTON_RIGHT:
|
||
|
// move selection to the right
|
||
|
nNewSelection++;
|
||
|
if ( nNewSelection > EUREKA_LAST_TARGET )
|
||
|
nNewSelection = EUREKA_FIRST_TARGET;
|
||
|
break;
|
||
|
|
||
|
case KEY_XBUTTON_LEFT:
|
||
|
// move selection to the left
|
||
|
nNewSelection--;
|
||
|
if ( nNewSelection <= 0 )
|
||
|
nNewSelection = EUREKA_LAST_TARGET;
|
||
|
break;
|
||
|
|
||
|
case KEY_XBUTTON_A:
|
||
|
case KEY_XBUTTON_RTRIGGER:
|
||
|
case KEY_XBUTTON_Y:
|
||
|
case KEY_XBUTTON_LTRIGGER:
|
||
|
// build selected item
|
||
|
SendTeleportMessage( (eEurekaTeleportTargets)nNewSelection );
|
||
|
return 0;
|
||
|
|
||
|
case KEY_XBUTTON_B:
|
||
|
// cancel, close the menu
|
||
|
engine->ExecuteClientCmd( "lastinv" );
|
||
|
return 0;
|
||
|
|
||
|
default:
|
||
|
return 1; // key not handled
|
||
|
}
|
||
|
|
||
|
SetSelectedItem( (eEurekaTeleportTargets)nNewSelection );
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int iSlot = 0;
|
||
|
|
||
|
// convert slot1, slot2 etc to 1,2,3,4
|
||
|
if( pszCurrentBinding && ( !Q_strncmp( pszCurrentBinding, "slot", NUM_ENGY_BUILDINGS ) && Q_strlen(pszCurrentBinding) > NUM_ENGY_BUILDINGS ) )
|
||
|
{
|
||
|
const char *pszNum = pszCurrentBinding+NUM_ENGY_BUILDINGS;
|
||
|
iSlot = atoi(pszNum);
|
||
|
|
||
|
// slot10 cancels
|
||
|
if ( iSlot == 10 )
|
||
|
{
|
||
|
engine->ExecuteClientCmd( "lastinv" );
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// allow slot1 - slot4
|
||
|
if ( iSlot < 1 || iSlot > EUREKA_NUM_TARGETS )
|
||
|
return 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
switch( keynum )
|
||
|
{
|
||
|
case KEY_1:
|
||
|
iSlot = 1;
|
||
|
break;
|
||
|
case KEY_2:
|
||
|
iSlot = 2;
|
||
|
break;
|
||
|
case KEY_3:
|
||
|
case KEY_4:
|
||
|
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;
|
||
|
|
||
|
case STEAMCONTROLLER_DPAD_LEFT:
|
||
|
SendTeleportMessage( EUREKA_TELEPORT_HOME );
|
||
|
return 0;
|
||
|
|
||
|
case STEAMCONTROLLER_DPAD_RIGHT:
|
||
|
SendTeleportMessage( EUREKA_TELEPORT_TELEPORTER_EXIT );
|
||
|
return 0;
|
||
|
|
||
|
default:
|
||
|
return 1; // key not handled
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( iSlot > 0 )
|
||
|
{
|
||
|
SendTeleportMessage( (eEurekaTeleportTargets)(iSlot-1) );
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 1; // key not handled
|
||
|
}
|
||
|
|
||
|
|
||
|
void CHudEurekaEffectTeleportMenu::WantsToTeleport()
|
||
|
{
|
||
|
m_bWantsToTeleport = true;
|
||
|
InvalidateLayout( true, true );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CHudEurekaEffectTeleportMenu::SetSelectedItem( eEurekaTeleportTargets eSelectedTeleportTarget )
|
||
|
{
|
||
|
if ( m_eSelectedTeleportTarget != eSelectedTeleportTarget )
|
||
|
{
|
||
|
m_eSelectedTeleportTarget = eSelectedTeleportTarget;
|
||
|
|
||
|
// move the selection item to the new position
|
||
|
if ( m_pActiveSelection )
|
||
|
{
|
||
|
// move the selection background
|
||
|
int x, y;
|
||
|
m_pAvilableTargets[m_eSelectedTeleportTarget]->GetPos( x, y );
|
||
|
|
||
|
x -= XRES(4);
|
||
|
y -= XRES(4);
|
||
|
|
||
|
m_pActiveSelection->SetPos( x, y );
|
||
|
|
||
|
UpdateHintLabels();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CHudEurekaEffectTeleportMenu::OnTick( void )
|
||
|
{
|
||
|
if ( !IsVisible() )
|
||
|
return;
|
||
|
|
||
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
|
||
|
|
||
|
if ( !pLocalPlayer )
|
||
|
return;
|
||
|
|
||
|
m_pAvilableTargets[ EUREKA_TELEPORT_HOME ]->SetVisible( true );
|
||
|
m_pUnavailableTargets[ EUREKA_TELEPORT_HOME ]->SetVisible( false );
|
||
|
|
||
|
const C_BaseObject *pObj = pLocalPlayer->GetObjectOfType( OBJ_TELEPORTER, MODE_TELEPORTER_EXIT );
|
||
|
bool bTeleAvailable = pObj
|
||
|
&& !pObj->IsBuilding()
|
||
|
&& !pObj->IsPlacing()
|
||
|
&& !pObj->IsUpgrading()
|
||
|
&& !pObj->IsCarried();
|
||
|
|
||
|
m_pAvilableTargets[ EUREKA_TELEPORT_TELEPORTER_EXIT ]->SetVisible( bTeleAvailable );
|
||
|
m_pUnavailableTargets[ EUREKA_TELEPORT_TELEPORTER_EXIT ]->SetVisible( !bTeleAvailable );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CHudEurekaEffectTeleportMenu::UpdateHintLabels( void )
|
||
|
{
|
||
|
}
|