mirror of
https://github.com/FWGS/hlsdk-xash3d
synced 2024-11-22 01:47:45 +01:00
ba2cab60df
* Get VGUI back (optionally) * Add some missing VGUI invocations * Update CMakeLists.txt to build with vgui for Windows * Move windows.h inclusions only to those places where it's really needed * Try fix mingw build * Update hud_spectator * Merge nekonomicon's vgui branch * Don't include vgui panel and app in cdll_int.cpp if vgui is real * Deduplicate scoreboard global variables * Add options to prefer non-vgui motd and scoreboard when vgui is enabled * Add vgui-dev as a submodule. Add building vith vgui to CI * Fix artifact uploading * Don't use global variable when not necessary * char* to const char* in CMenuHandler_StringCommand constructor * Fix 'format string is not a literal string' warnings * Fix 'always evaluate to true' warnings * Team Fortress classes to const char* * CreateCommandMenu accepts const char* * Fix printf formats. Turn some unsigned longs into unsigned ints since they use only 32 bits anyway * Explicit assignment result as condition * Prevent memory leak on menu reading * Localize button text * Create FileInputStream on stack avoiding the leak * Remove Servers Browser code * Arrow file names to const char* * Fix assignment to the wrong variable
395 lines
12 KiB
C++
395 lines
12 KiB
C++
//=========== (C) Copyright 1996-2002 Valve, L.L.C. All rights reserved. ===========
|
|
//
|
|
// The copyright to the contents herein is the property of Valve, L.L.C.
|
|
// The contents may be used and/or copied only with the written permission of
|
|
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
|
|
// the agreement/contract under which the contents have been supplied.
|
|
//
|
|
// Purpose: TFC Team Menu
|
|
//
|
|
// $Workfile: $
|
|
// $Date: $
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
// $Log: $
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================
|
|
|
|
#include "vgui_int.h"
|
|
#include "VGUI_Font.h"
|
|
#include "VGUI_ScrollPanel.h"
|
|
#include "VGUI_TextImage.h"
|
|
|
|
#include "hud.h"
|
|
#include "cl_util.h"
|
|
#include "vgui_TeamFortressViewport.h"
|
|
|
|
// Team Menu Dimensions
|
|
#define TEAMMENU_TITLE_X XRES(40)
|
|
#define TEAMMENU_TITLE_Y YRES(32)
|
|
#define TEAMMENU_TOPLEFT_BUTTON_X XRES(40)
|
|
#define TEAMMENU_TOPLEFT_BUTTON_Y YRES(80)
|
|
#define TEAMMENU_BUTTON_SIZE_X XRES(124)
|
|
#define TEAMMENU_BUTTON_SIZE_Y YRES(24)
|
|
#define TEAMMENU_BUTTON_SPACER_Y YRES(8)
|
|
#define TEAMMENU_WINDOW_X XRES(176)
|
|
#define TEAMMENU_WINDOW_Y YRES(80)
|
|
#define TEAMMENU_WINDOW_SIZE_X XRES(424)
|
|
#define TEAMMENU_WINDOW_SIZE_Y YRES(312)
|
|
#define TEAMMENU_WINDOW_TITLE_X XRES(16)
|
|
#define TEAMMENU_WINDOW_TITLE_Y YRES(16)
|
|
#define TEAMMENU_WINDOW_TEXT_X XRES(16)
|
|
#define TEAMMENU_WINDOW_TEXT_Y YRES(48)
|
|
#define TEAMMENU_WINDOW_TEXT_SIZE_Y YRES(178)
|
|
#define TEAMMENU_WINDOW_INFO_X XRES(16)
|
|
#define TEAMMENU_WINDOW_INFO_Y YRES(234)
|
|
|
|
// Creation
|
|
CTeamMenuPanel::CTeamMenuPanel( int iTrans, int iRemoveMe, int x, int y, int wide, int tall ) : CMenuPanel( iTrans, iRemoveMe, x, y, wide, tall )
|
|
{
|
|
// Get the scheme used for the Titles
|
|
CSchemeManager *pSchemes = gViewPort->GetSchemeManager();
|
|
|
|
// schemes
|
|
SchemeHandle_t hTitleScheme = pSchemes->getSchemeHandle( "Title Font" );
|
|
SchemeHandle_t hTeamWindowText = pSchemes->getSchemeHandle( "Briefing Text" );
|
|
SchemeHandle_t hTeamInfoText = pSchemes->getSchemeHandle( "Team Info Text" );
|
|
|
|
// get the Font used for the Titles
|
|
Font *pTitleFont = pSchemes->getFont( hTitleScheme );
|
|
int r, g, b, a;
|
|
|
|
// Create the title
|
|
Label *pLabel = new Label( "", TEAMMENU_TITLE_X, TEAMMENU_TITLE_Y );
|
|
pLabel->setParent( this );
|
|
pLabel->setFont( pTitleFont );
|
|
pSchemes->getFgColor( hTitleScheme, r, g, b, a );
|
|
pLabel->setFgColor( r, g, b, a );
|
|
pSchemes->getBgColor( hTitleScheme, r, g, b, a );
|
|
pLabel->setBgColor( r, g, b, a );
|
|
pLabel->setContentAlignment( vgui::Label::a_west );
|
|
pLabel->setText( "%s", gHUD.m_TextMessage.BufferedLocaliseTextString("#Title_SelectYourTeam"));
|
|
|
|
// Create the Info Window
|
|
m_pTeamWindow = new CTransparentPanel( 255, TEAMMENU_WINDOW_X, TEAMMENU_WINDOW_Y, TEAMMENU_WINDOW_SIZE_X, TEAMMENU_WINDOW_SIZE_Y );
|
|
m_pTeamWindow->setParent( this );
|
|
m_pTeamWindow->setBorder( new LineBorder( Color( 255 * 0.7, 170 * 0.7 ,0 ,0 ) ) );
|
|
|
|
// Create the Map Name Label
|
|
m_pMapTitle = new Label( "", TEAMMENU_WINDOW_TITLE_X, TEAMMENU_WINDOW_TITLE_Y );
|
|
m_pMapTitle->setFont( pTitleFont );
|
|
m_pMapTitle->setParent( m_pTeamWindow );
|
|
pSchemes->getFgColor( hTitleScheme, r, g, b, a );
|
|
m_pMapTitle->setFgColor( r, g, b, a );
|
|
pSchemes->getBgColor( hTitleScheme, r, g, b, a );
|
|
m_pMapTitle->setBgColor( r, g, b, a );
|
|
m_pMapTitle->setContentAlignment( vgui::Label::a_west );
|
|
|
|
// Create the Scroll panel
|
|
m_pScrollPanel = new CTFScrollPanel( TEAMMENU_WINDOW_TEXT_X, TEAMMENU_WINDOW_TEXT_Y, TEAMMENU_WINDOW_SIZE_X - ( TEAMMENU_WINDOW_TEXT_X * 2 ), TEAMMENU_WINDOW_TEXT_SIZE_Y );
|
|
m_pScrollPanel->setParent( m_pTeamWindow );
|
|
m_pScrollPanel->setScrollBarVisible( false, false );
|
|
|
|
// Create the Map Briefing panel
|
|
m_pBriefing = new TextPanel("", 0, 0, TEAMMENU_WINDOW_SIZE_X - TEAMMENU_WINDOW_TEXT_X, TEAMMENU_WINDOW_TEXT_SIZE_Y );
|
|
m_pBriefing->setParent( m_pScrollPanel->getClient() );
|
|
m_pBriefing->setFont( pSchemes->getFont( hTeamWindowText ) );
|
|
pSchemes->getFgColor( hTeamWindowText, r, g, b, a );
|
|
m_pBriefing->setFgColor( r, g, b, a );
|
|
pSchemes->getBgColor( hTeamWindowText, r, g, b, a );
|
|
m_pBriefing->setBgColor( r, g, b, a );
|
|
|
|
m_pBriefing->setText( gHUD.m_TextMessage.BufferedLocaliseTextString( "#Map_Description_not_available" ) );
|
|
|
|
// Team Menu buttons
|
|
for( int i = 1; i <= 5; i++ )
|
|
{
|
|
char sz[256];
|
|
|
|
int iYPos = TEAMMENU_TOPLEFT_BUTTON_Y + ( ( TEAMMENU_BUTTON_SIZE_Y + TEAMMENU_BUTTON_SPACER_Y ) * i );
|
|
|
|
// Team button
|
|
m_pButtons[i] = new CommandButton( "", TEAMMENU_TOPLEFT_BUTTON_X, iYPos, TEAMMENU_BUTTON_SIZE_X, TEAMMENU_BUTTON_SIZE_Y, true );
|
|
m_pButtons[i]->setParent( this );
|
|
m_pButtons[i]->setContentAlignment( vgui::Label::a_west );
|
|
m_pButtons[i]->setVisible( false );
|
|
|
|
// AutoAssign button uses special case
|
|
if( i == 5 )
|
|
{
|
|
m_pButtons[5]->setBoundKey( '5' );
|
|
m_pButtons[5]->setText( gHUD.m_TextMessage.BufferedLocaliseTextString( "#Team_AutoAssign" ) );
|
|
m_pButtons[5]->setVisible( true );
|
|
}
|
|
|
|
// Create the Signals
|
|
sprintf( sz, "jointeam %d", i );
|
|
m_pButtons[i]->addActionSignal( new CMenuHandler_StringCommandWatch( sz, true ) );
|
|
m_pButtons[i]->addInputSignal( new CHandler_MenuButtonOver( this, i ) );
|
|
|
|
// Create the Team Info panel
|
|
m_pTeamInfoPanel[i] = new TextPanel( "", TEAMMENU_WINDOW_INFO_X, TEAMMENU_WINDOW_INFO_Y, TEAMMENU_WINDOW_SIZE_X - TEAMMENU_WINDOW_INFO_X, TEAMMENU_WINDOW_SIZE_X - TEAMMENU_WINDOW_INFO_Y );
|
|
m_pTeamInfoPanel[i]->setParent( m_pTeamWindow );
|
|
m_pTeamInfoPanel[i]->setFont( pSchemes->getFont( hTeamInfoText ) );
|
|
m_pTeamInfoPanel[i]->setFgColor( iTeamColors[i % iNumberOfTeamColors][0],
|
|
iTeamColors[i % iNumberOfTeamColors][1],
|
|
iTeamColors[i % iNumberOfTeamColors][2],
|
|
0 );
|
|
m_pTeamInfoPanel[i]->setBgColor( 0, 0, 0, 255 );
|
|
}
|
|
|
|
// Create the Cancel button
|
|
m_pCancelButton = new CommandButton( CHudTextMessage::BufferedLocaliseTextString( "#Menu_Cancel" ), TEAMMENU_TOPLEFT_BUTTON_X, 0, TEAMMENU_BUTTON_SIZE_X, TEAMMENU_BUTTON_SIZE_Y );
|
|
m_pCancelButton->setParent( this );
|
|
m_pCancelButton->addActionSignal( new CMenuHandler_TextWindow( HIDE_TEXTWINDOW ) );
|
|
|
|
// Create the Spectate button
|
|
m_pSpectateButton = new SpectateButton( CHudTextMessage::BufferedLocaliseTextString( "#Menu_Spectate" ), TEAMMENU_TOPLEFT_BUTTON_X, 0, TEAMMENU_BUTTON_SIZE_X, TEAMMENU_BUTTON_SIZE_Y, true );
|
|
m_pSpectateButton->setParent( this );
|
|
m_pSpectateButton->addActionSignal( new CMenuHandler_StringCommand( "spectate", true ) );
|
|
m_pSpectateButton->setBoundKey( '6' );
|
|
m_pSpectateButton->addInputSignal( new CHandler_MenuButtonOver( this, 6 ) );
|
|
|
|
Initialize();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Called each time a new level is started.
|
|
//-----------------------------------------------------------------------------
|
|
void CTeamMenuPanel::Initialize( void )
|
|
{
|
|
m_bUpdatedMapName = false;
|
|
m_iCurrentInfo = 0;
|
|
m_pScrollPanel->setScrollValue( 0, 0 );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Called everytime the Team Menu is displayed
|
|
//-----------------------------------------------------------------------------
|
|
void CTeamMenuPanel::Update( void )
|
|
{
|
|
int iYPos = TEAMMENU_TOPLEFT_BUTTON_Y;
|
|
|
|
// Set the team buttons
|
|
for( int i = 1; i <= 4; i++ )
|
|
{
|
|
if( m_pButtons[i] )
|
|
{
|
|
if( i <= gViewPort->GetNumberOfTeams() )
|
|
{
|
|
m_pButtons[i]->setText( gViewPort->GetTeamName( i ) );
|
|
|
|
// bound key replacement
|
|
char sz[32];
|
|
sprintf( sz, "%d", i );
|
|
m_pButtons[i]->setBoundKey( sz[0] );
|
|
|
|
m_pButtons[i]->setVisible( true );
|
|
m_pButtons[i]->setPos( TEAMMENU_TOPLEFT_BUTTON_X, iYPos );
|
|
iYPos += TEAMMENU_BUTTON_SIZE_Y + TEAMMENU_BUTTON_SPACER_Y;
|
|
|
|
// Start with the first option up
|
|
if( !m_iCurrentInfo )
|
|
SetActiveInfo( i );
|
|
|
|
char szPlayerList[( MAX_PLAYER_NAME_LENGTH + 3 ) * 31]; // name + ", "
|
|
strcpy(szPlayerList, "\n");
|
|
// Update the Team Info
|
|
// Now count the number of teammembers of this class
|
|
int iTotal = 0;
|
|
for( int j = 1; j < MAX_PLAYERS; j++ )
|
|
{
|
|
if( g_PlayerInfoList[j].name == NULL )
|
|
continue; // empty player slot, skip
|
|
if( g_PlayerInfoList[j].thisplayer )
|
|
continue; // skip this player
|
|
if( g_PlayerExtraInfo[j].teamnumber != i )
|
|
continue; // skip over players in other teams
|
|
|
|
iTotal++;
|
|
if( iTotal > 1 )
|
|
strncat( szPlayerList, ", ", sizeof(szPlayerList) - strlen( szPlayerList ) - 1 );
|
|
strncat( szPlayerList, g_PlayerInfoList[j].name, sizeof(szPlayerList) - strlen( szPlayerList ) - 1 );
|
|
szPlayerList[sizeof(szPlayerList) - 1] = '\0';
|
|
}
|
|
|
|
if( iTotal > 0 )
|
|
{
|
|
// Set the text of the info Panel
|
|
char szText[( ( MAX_PLAYER_NAME_LENGTH + 3 ) * 31 ) + 256];
|
|
if( iTotal == 1 )
|
|
sprintf( szText, "%s: %d Player (%d points)", gViewPort->GetTeamName( i ), iTotal, g_TeamInfo[i].frags );
|
|
else
|
|
sprintf( szText, "%s: %d Players (%d points)", gViewPort->GetTeamName( i ), iTotal, g_TeamInfo[i].frags );
|
|
strncat( szText, szPlayerList, sizeof(szText) - strlen( szText ) - 1 );
|
|
szText[sizeof(szText) - 1] = '\0';
|
|
|
|
m_pTeamInfoPanel[i]->setText( szText );
|
|
}
|
|
else
|
|
{
|
|
m_pTeamInfoPanel[i]->setText( "" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Hide the button (may be visible from previous maps)
|
|
m_pButtons[i]->setVisible( false );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Move the AutoAssign button into place
|
|
m_pButtons[5]->setPos( TEAMMENU_TOPLEFT_BUTTON_X, iYPos );
|
|
iYPos += TEAMMENU_BUTTON_SIZE_Y + TEAMMENU_BUTTON_SPACER_Y;
|
|
|
|
// Spectate button
|
|
if( m_pSpectateButton->IsNotValid() )
|
|
{
|
|
m_pSpectateButton->setVisible( false );
|
|
}
|
|
else
|
|
{
|
|
m_pSpectateButton->setPos( TEAMMENU_TOPLEFT_BUTTON_X, iYPos );
|
|
m_pSpectateButton->setVisible( true );
|
|
iYPos += TEAMMENU_BUTTON_SIZE_Y + TEAMMENU_BUTTON_SPACER_Y;
|
|
}
|
|
|
|
// If the player is already in a team, make the cancel button visible
|
|
if( g_iTeamNumber )
|
|
{
|
|
m_pCancelButton->setPos( TEAMMENU_TOPLEFT_BUTTON_X, iYPos );
|
|
iYPos += TEAMMENU_BUTTON_SIZE_Y + TEAMMENU_BUTTON_SPACER_Y;
|
|
m_pCancelButton->setVisible( true );
|
|
}
|
|
else
|
|
{
|
|
m_pCancelButton->setVisible( false );
|
|
}
|
|
|
|
// Set the Map Title
|
|
if( !m_bUpdatedMapName )
|
|
{
|
|
const char *level = gEngfuncs.pfnGetLevelName();
|
|
if( level && level[0] )
|
|
{
|
|
char sz[256];
|
|
char szTitle[256];
|
|
char *ch;
|
|
|
|
// Update the level name
|
|
strcpy( sz, level );
|
|
ch = strchr( sz, '/' );
|
|
if( !ch )
|
|
ch = strchr( sz, '\\' );
|
|
strcpy( szTitle, ch + 1 );
|
|
ch = strchr( szTitle, '.' );
|
|
*ch = '\0';
|
|
m_pMapTitle->setText( "%s", szTitle );
|
|
*ch = '.';
|
|
|
|
// Update the map briefing
|
|
strcpy( sz, level );
|
|
ch = strchr( sz, '.' );
|
|
*ch = '\0';
|
|
strcat( sz, ".txt" );
|
|
char *pfile = (char*)gEngfuncs.COM_LoadFile( sz, 5, NULL );
|
|
if( pfile )
|
|
{
|
|
m_pBriefing->setText( pfile );
|
|
|
|
// Get the total size of the Briefing text and resize the text panel
|
|
int iXSize, iYSize;
|
|
m_pBriefing->getTextImage()->getTextSize( iXSize, iYSize );
|
|
m_pBriefing->setSize( iXSize, iYSize );
|
|
gEngfuncs.COM_FreeFile( pfile );
|
|
}
|
|
|
|
m_bUpdatedMapName = true;
|
|
}
|
|
}
|
|
|
|
m_pScrollPanel->validate();
|
|
}
|
|
|
|
//=====================================
|
|
// Key inputs
|
|
bool CTeamMenuPanel::SlotInput( int iSlot )
|
|
{
|
|
// Check for AutoAssign
|
|
if( iSlot == 5 )
|
|
{
|
|
m_pButtons[5]->fireActionSignal();
|
|
return true;
|
|
}
|
|
|
|
// Spectate
|
|
if( iSlot == 6 )
|
|
{
|
|
m_pSpectateButton->fireActionSignal();
|
|
return true;
|
|
}
|
|
|
|
// Otherwise, see if a particular team is selectable
|
|
if( ( iSlot < 1 ) || ( iSlot > gViewPort->GetNumberOfTeams() ) )
|
|
return false;
|
|
|
|
if( !m_pButtons[iSlot] )
|
|
return false;
|
|
|
|
// Is the button pushable?
|
|
if( m_pButtons[iSlot]->isVisible() )
|
|
{
|
|
m_pButtons[iSlot]->fireActionSignal();
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//======================================
|
|
// Update the Team menu before opening it
|
|
void CTeamMenuPanel::Open( void )
|
|
{
|
|
Update();
|
|
CMenuPanel::Open();
|
|
}
|
|
|
|
void CTeamMenuPanel::paintBackground()
|
|
{
|
|
// make sure we get the map briefing up
|
|
if( !m_bUpdatedMapName )
|
|
Update();
|
|
|
|
CMenuPanel::paintBackground();
|
|
}
|
|
|
|
//======================================
|
|
// Mouse is over a team button, bring up the class info
|
|
void CTeamMenuPanel::SetActiveInfo( int iInput )
|
|
{
|
|
// Remove all the Info panels and bring up the specified one
|
|
m_pSpectateButton->setArmed( false );
|
|
for( int i = 1; i <= 5; i++ )
|
|
{
|
|
m_pButtons[i]->setArmed( false );
|
|
m_pTeamInfoPanel[i]->setVisible( false );
|
|
}
|
|
|
|
// 6 is Spectate
|
|
if( iInput == 6 )
|
|
{
|
|
m_pSpectateButton->setArmed( true );
|
|
}
|
|
else
|
|
{
|
|
m_pButtons[iInput]->setArmed( true );
|
|
m_pTeamInfoPanel[iInput]->setVisible( true );
|
|
}
|
|
|
|
m_iCurrentInfo = iInput;
|
|
|
|
m_pScrollPanel->validate();
|
|
}
|