halflife-photomode/cl_dll/vgui_teammenu.cpp

393 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, bool 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()
{
m_bUpdatedMapName = false;
m_iCurrentInfo = 0;
m_pScrollPanel->setScrollValue(0, 0);
}
//-----------------------------------------------------------------------------
// Purpose: Called everytime the Team Menu is displayed
//-----------------------------------------------------------------------------
void CTeamMenuPanel::Update()
{
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 (0 == 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_HUD; j++)
{
if (g_PlayerInfoList[j].name == NULL)
continue; // empty player slot, skip
if (0 != 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));
strncat(szPlayerList, g_PlayerInfoList[j].name, sizeof(szPlayerList) - strlen(szPlayerList));
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));
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 (0 != 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 && '\0' != 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()
{
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();
}