Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
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

5 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 )
{
}