//=========== (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(); }