This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/Commando/dlgcncwinscreen.cpp

672 lines
19 KiB
C++
Raw Permalink Normal View History

/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : commando *
* *
* $Archive:: /Commando/Code/Commando/dlgcncwinscreen.cpp $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 2/24/02 2:10p $*
* *
* $Revision:: 16 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "dlgcncwinscreen.h"
#include "resource.h"
#include "rendobj.h"
#include "pscene.h"
#include "combat.h"
#include "gamedata.h"
#include "playertype.h"
#include "assetmgr.h"
#include "dialogresource.h"
#include "menubackdrop.h"
#include "listctrl.h"
#include "gamemode.h"
#include "wolgmode.h"
#include "translatedb.h"
#include "string_ids.h"
#include "cnetwork.h"
#include "gameinitmgr.h"
#include "gamespyadmin.h"
#include "specialbuilds.h"
#include "dialogtests.h"
#include "dialogmgr.h"
////////////////////////////////////////////////////////////////
// Static member initialization
////////////////////////////////////////////////////////////////
CNCWinScreenMenuClass * CNCWinScreenMenuClass::_TheInstance = NULL;
const float CNCWinScreenMenuClass::UpdateIntervalS = 0.2f;
////////////////////////////////////////////////////////////////
// Constants
////////////////////////////////////////////////////////////////
enum
{
COL_RANK,
COL_NAME,
COL_SCORE,
COL_KILLS,
COL_LADDER,
};
////////////////////////////////////////////////////////////////
//
// CNCWinScreenMenuClass
//
////////////////////////////////////////////////////////////////
CNCWinScreenMenuClass::CNCWinScreenMenuClass (void) :
HeaderModel (NULL),
UpdateTimer (UpdateIntervalS),
ShowLadderPoints(false),
MenuDialogClass (IDD_CNC_WINSCREEN)
{
//
// Configure the blackout renderer
//
StyleMgrClass::Configure_Renderer (&BlackoutRenderer);
BlackoutRenderer.Get_Shader ()->Set_Depth_Compare (ShaderClass::PASS_ALWAYS);
BlackoutRenderer.Add_Quad (Render2DClass::Get_Screen_Resolution (), RGBA_TO_INT32 (0, 0, 0, 200));
WinScreenBackdrop.Clear_Screen (false);
//
// Load the correct banner
//
if (The_Game ()->Get_Winner_ID () == PLAYERTYPE_GDI) {
HeaderModel = WW3DAssetManager::Get_Instance ()->Create_Render_Obj ("HUD_GDIWINBAN");
} else {
HeaderModel = WW3DAssetManager::Get_Instance ()->Create_Render_Obj ("HUD_NODWINBAN");
}
//
// Should we show ladder points?
//
WWASSERT(GameModeManager::Find("WOL") != NULL);
WWASSERT(The_Game() != NULL);
if (GameModeManager::Find("WOL")->Is_Active() && The_Game()->IsLaddered.Is_True()) {
ShowLadderPoints = true;
}
_TheInstance = this;
return ;
}
////////////////////////////////////////////////////////////////
//
// CNCWinScreenMenuClass
//
////////////////////////////////////////////////////////////////
CNCWinScreenMenuClass::~CNCWinScreenMenuClass (void)
{
if (HeaderModel != NULL) {
HeaderModel->Remove ();
REF_PTR_RELEASE (HeaderModel);
}
_TheInstance = NULL;
return ;
}
////////////////////////////////////////////////////////////////
//
// On_Init_Dialog
//
////////////////////////////////////////////////////////////////
void
CNCWinScreenMenuClass::On_Init_Dialog (void)
{
//
// Get a pointer to the list control
//
ListCtrlClass *list_ctrl = (ListCtrlClass *)Get_Dlg_Item (IDC_WIN1_LIST_CTRL);
if (list_ctrl != NULL) {
//
// Configure the columns
//
list_ctrl->Add_Column (TRANSLATE (IDS_MENU_RANK), 0.15F, Vector3 (1, 1, 1));
list_ctrl->Add_Column (TRANSLATE (IDS_MENU_NAME), 0.3F, Vector3 (1, 1, 1));
list_ctrl->Add_Column (TRANSLATE (IDS_MENU_SCORE), 0.2F, Vector3 (1, 1, 1));
list_ctrl->Add_Column (TRANSLATE (IDS_MENU_KILLS), 0.15F, Vector3 (1, 1, 1));
if (ShowLadderPoints) {
list_ctrl->Add_Column (TRANSLATE (IDS_MENU_LADDER), 0.25F, Vector3 (1, 1, 1));
}
}
list_ctrl = (ListCtrlClass *)Get_Dlg_Item (IDC_LOSE1_LIST_CTRL);
if (list_ctrl != NULL) {
//
// Configure the columns
//
list_ctrl->Add_Column (TRANSLATE (IDS_MENU_RANK), 0.15F, Vector3 (1, 1, 1));
list_ctrl->Add_Column (TRANSLATE (IDS_MENU_NAME), 0.3F, Vector3 (1, 1, 1));
list_ctrl->Add_Column (TRANSLATE (IDS_MENU_SCORE), 0.2F, Vector3 (1, 1, 1));
list_ctrl->Add_Column (TRANSLATE (IDS_MENU_KILLS), 0.15F, Vector3 (1, 1, 1));
if (ShowLadderPoints) {
list_ctrl->Add_Column (TRANSLATE (IDS_MENU_LADDER), 0.25F, Vector3 (1, 1, 1));
}
}
//
// Fill in dialog controls
//
if (The_Game ()->Get_Winner_ID () == PLAYERTYPE_GDI) {
Get_Dlg_Item (IDC_TITLE_TEXT_1)->Set_Text_Color (Vector3 (1.0F, 1.0F, 1.0F));
Get_Dlg_Item (IDC_TITLE_TEXT_2)->Set_Text_Color (Vector3 (1.0F, 1.0F, 1.0F));
Populate_Player_Lists (PLAYERTYPE_GDI, IDC_WIN1_LIST_CTRL);
Populate_Player_Lists (PLAYERTYPE_NOD, IDC_LOSE1_LIST_CTRL);
//
// Display the title
//
Set_Dlg_Item_Text (IDC_TITLE_TEXT_1, TRANSLATE (IDS_MENU_GDI_WINS));
//
// Display the team scores
//
WideStringClass team_score_string;
team_score_string.Format (TRANSLATE (IDS_MENU_GDI_SCORE), (int)cTeamManager::Find_Team (PLAYERTYPE_GDI)->Get_Score ());
Set_Dlg_Item_Text (IDC_WINNER_TEAM_SCORE_TEXT, team_score_string);
team_score_string.Format (TRANSLATE (IDS_MENU_NOD_SCORE), (int)cTeamManager::Find_Team (PLAYERTYPE_NOD)->Get_Score ());
Set_Dlg_Item_Text (IDC_LOSER_TEAM_SCORE_TEXT, team_score_string);
} else {
Get_Dlg_Item (IDC_TITLE_TEXT_1)->Set_Text_Color (Vector3 (1.0F, 0.0F, 0.0F));
Get_Dlg_Item (IDC_TITLE_TEXT_2)->Set_Text_Color (Vector3 (1.0F, 0.0F, 0.0F));
//Get_Dlg_Item (IDC_MVP_TEXT)->Set_Text_Color (Vector3 (1.0F, 0.0F, 0.0F));
//Get_Dlg_Item (IDC_TIME_TEXT)->Set_Text_Color (Vector3 (1.0F, 0.0F, 0.0F));
//Get_Dlg_Item (IDC_WINNER_TEAM_SCORE_TEXT)->Set_Text_Color (Vector3 (1.0F, 0.0F, 0.0F));
//Get_Dlg_Item (IDC_LOSER_TEAM_SCORE_TEXT)->Set_Text_Color (Vector3 (1.0F, 0.0F, 0.0F));
Populate_Player_Lists (PLAYERTYPE_NOD, IDC_WIN1_LIST_CTRL);
Populate_Player_Lists (PLAYERTYPE_GDI, IDC_LOSE1_LIST_CTRL);
//
// Display the title
//
Set_Dlg_Item_Text (IDC_TITLE_TEXT_1, TRANSLATE (IDS_MENU_NOD_WINS));
//
// Display the team scores
//
WideStringClass team_score_string;
team_score_string.Format (TRANSLATE (IDS_MENU_NOD_SCORE), (int)cTeamManager::Find_Team (PLAYERTYPE_NOD)->Get_Score ());
Set_Dlg_Item_Text (IDC_WINNER_TEAM_SCORE_TEXT, team_score_string);
team_score_string.Format (TRANSLATE (IDS_MENU_GDI_SCORE), (int)cTeamManager::Find_Team (PLAYERTYPE_GDI)->Get_Score ());
Set_Dlg_Item_Text (IDC_LOSER_TEAM_SCORE_TEXT, team_score_string);
}
//
// Display the MVP's name and num times consecutive as MVP
//
WideStringClass mvp_text;
mvp_text.Format (TRANSLATE (IDS_MENU_MVP_FORMAT), (const WCHAR *)The_Game ()->Get_Mvp_Name ());
if (!The_Game()->Get_Mvp_Name().Is_Empty() && The_Game()->Get_Mvp_Count() > 1) {
WideStringClass consecutives_text;
consecutives_text.Format(L" * %d", The_Game()->Get_Mvp_Count());
mvp_text += consecutives_text;
}
Set_Dlg_Item_Text (IDC_MVP_TEXT, mvp_text);
//
// Display a description of how the team won
//
cGameData::WinTypeEnum win_type = The_Game ()->Get_Win_Type ();
WideStringClass win_description;
switch (win_type)
{
case cGameData::WIN_TYPE_FORCED:
win_description = TRANSLATE (IDS_MENU_WIN_CONDITION_01);
break;
case cGameData::WIN_TYPE_COWARDICE:
win_description = TRANSLATE (IDS_MENU_WIN_CONDITION_02);
break;
case cGameData::WIN_TYPE_TIME:
win_description = TRANSLATE (IDS_MENU_WIN_CONDITION_03);
break;
case cGameData::WIN_TYPE_BASE_DESTRUCTION:
win_description = TRANSLATE (IDS_MENU_WIN_CONDITION_04);
break;
case cGameData::WIN_TYPE_BEACON:
win_description = TRANSLATE (IDS_MENU_WIN_CONDITION_05);
break;
}
Set_Dlg_Item_Text (IDC_TITLE_TEXT_2, win_description);
WideStringClass game_time_string;
Set_Dlg_Item_Text (IDC_TITLE_TEXT_2, win_description);
//
// Display the game time
//
WideStringClass time_string;
int time = (int)The_Game ()->Get_Game_Duration_S ();
int hours = int(time / 3600);
time -= hours * 3600;
int minutes = int(time / 60);
time -= minutes * 60;
int seconds = (int)time;
if (hours > 0) {
time_string.Format (TRANSLATE (IDS_MENU_GAME_TIME_01), hours, minutes, seconds);
} else {
time_string.Format (TRANSLATE (IDS_MENU_GAME_TIME_02), minutes, seconds);
}
Set_Dlg_Item_Text (IDC_TIME_TEXT, time_string);
//
// Set the text that shows the next map to be played.
//
if (The_Game()->Is_Map_Cycle_Over()) {
Set_Dlg_Item_Text (IDC_MENU_TEXT_NEXT_MAP, L"");
} else {
WideStringClass map_info(TRANSLATE(IDS_MENU_NEXT_MAP), true);
//
// Get a copy of the map name from PTheGameData
//
char map_name[256];
strcpy(map_name, The_Game()->Get_Map_Name());
//
// Strip off the .mix if present.
//
strupr(map_name);
char *dot = strstr(map_name, ".MIX");
strcpy(map_name, The_Game()->Get_Map_Name());
if (dot) {
*dot = 0;
}
map_info += WideStringClass(map_name, true);
Set_Dlg_Item_Text (IDC_MENU_TEXT_NEXT_MAP, map_info);
}
MenuDialogClass::On_Init_Dialog ();
return ;
}
////////////////////////////////////////////////////////////////
//
// On_Frame_Update
//
////////////////////////////////////////////////////////////////
void
CNCWinScreenMenuClass::On_Frame_Update (void)
{
UpdateTimer -= TimeManager::Get_Frame_Seconds ();
if (UpdateTimer <= 0) {
cPlayerManager::Sort_Players(false);
//
// Refresh the player lists
//
if (The_Game ()->Get_Winner_ID () == PLAYERTYPE_GDI) {
Populate_Player_Lists (PLAYERTYPE_GDI, IDC_WIN1_LIST_CTRL);
Populate_Player_Lists (PLAYERTYPE_NOD, IDC_LOSE1_LIST_CTRL);
} else {
Populate_Player_Lists (PLAYERTYPE_NOD, IDC_WIN1_LIST_CTRL);
Populate_Player_Lists (PLAYERTYPE_GDI, IDC_LOSE1_LIST_CTRL);
}
//
// Refresh the team scores
//
WideStringClass gdi_score_string;
WideStringClass nod_score_string;
gdi_score_string.Format (TRANSLATE (IDS_MENU_GDI_SCORE), (int)cTeamManager::Find_Team (PLAYERTYPE_GDI)->Get_Score ());
nod_score_string.Format (TRANSLATE (IDS_MENU_NOD_SCORE), (int)cTeamManager::Find_Team (PLAYERTYPE_NOD)->Get_Score ());
if (The_Game ()->Get_Winner_ID () == PLAYERTYPE_GDI) {
Set_Dlg_Item_Text (IDC_WINNER_TEAM_SCORE_TEXT, gdi_score_string);
Set_Dlg_Item_Text (IDC_LOSER_TEAM_SCORE_TEXT, nod_score_string);
} else {
Set_Dlg_Item_Text (IDC_WINNER_TEAM_SCORE_TEXT, nod_score_string);
Set_Dlg_Item_Text (IDC_LOSER_TEAM_SCORE_TEXT, gdi_score_string);
}
UpdateTimer = UpdateIntervalS;
}
MenuDialogClass::On_Frame_Update ();
return ;
}
////////////////////////////////////////////////////////////////
//
// On_Destroy
//
////////////////////////////////////////////////////////////////
void
CNCWinScreenMenuClass::On_Destroy (void)
{
MenuDialogClass::On_Destroy ();
return ;
}
////////////////////////////////////////////////////////////////
//
// Render
//
////////////////////////////////////////////////////////////////
void
CNCWinScreenMenuClass::Render (void)
{
//
// Don't render if we aren't the active menu
//
if (ActiveMenu == this) {
//
// Render the background scene first
//
BackDrop->Render ();
BlackoutRenderer.Render ();
WinScreenBackdrop.Render ();
//
// Now, let the dialog subsystem render the controls and
// such...
//
DialogBaseClass::Render ();
}
return ;
}
////////////////////////////////////////////////////////////////
//
// On_Command
//
////////////////////////////////////////////////////////////////
void
CNCWinScreenMenuClass::On_Command (int ctrl_id, int message_id, DWORD param)
{
switch (ctrl_id)
{
case IDCANCEL:
//
// Close the dialog
//
End_Dialog ();
//
// End the game
//
GameInitMgrClass::End_Game ();
if (cGameSpyAdmin::Get_Is_Launched_From_Gamespy()) {
#ifdef MULTIPLAYERDEMO
DialogMgrClass::Flush_Dialogs ();
START_DIALOG (SplashOutroMenuDialogClass);
#else
extern void Stop_Main_Loop (int);
Stop_Main_Loop(EXIT_SUCCESS);
#endif // MULTIPLAYERDEMO
} else {
GameInitMgrClass::Display_End_Game_Menu ();
}
break;
default:
MenuDialogClass::On_Command (ctrl_id, message_id, param);
break;
}
return ;
}
////////////////////////////////////////////////////////////////
//
// On_Menu_Activate
//
////////////////////////////////////////////////////////////////
void
CNCWinScreenMenuClass::On_Menu_Activate (bool onoff)
{
if (HeaderModel != NULL) {
//
// Either add or remove the header from the scene
//
if (onoff) {
if (HeaderModel->Peek_Scene () == NULL) {
WinScreenBackdrop.Peek_Scene ()->Add_Render_Object (HeaderModel);
}
} else {
HeaderModel->Remove ();
}
}
MenuDialogClass::On_Menu_Activate (onoff);
return ;
}
////////////////////////////////////////////////////////////////
//
// Close_Dialog
//
////////////////////////////////////////////////////////////////
void
CNCWinScreenMenuClass::Close_Dialog (void)
{
if (_TheInstance != NULL) {
_TheInstance->End_Dialog ();
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Populate_Player_Lists
//
////////////////////////////////////////////////////////////////
void
CNCWinScreenMenuClass::Populate_Player_Lists (int team_id, int list_ctrl1_id)
{
//
// Get a pointer to the list control
//
ListCtrlClass *list_ctrl = (ListCtrlClass *)Get_Dlg_Item (list_ctrl1_id);
if (list_ctrl == NULL) {
return ;
}
DynamicVectorClass<cPlayer *> player_list;
//
// Find the player's name that most closely matches the typed name
//
int index = 0;
for ( SLNode<cPlayer> *player_node = cPlayerManager::Get_Player_Object_List ()->Head ();
player_node != NULL;
player_node = player_node->Next ())
{
cPlayer *player = player_node->Data ();
WWASSERT (player != NULL);
if (player->Get_Is_Active().Is_False ()) {
continue;
}
//
// Does this player belong to the same team?
//
if (player->Get_Player_Type () == team_id) {
player_list.Add (player);
}
}
//
// Sort the players
//
if (player_list.Count () > 0) {
::qsort (&player_list[0], player_list.Count (), sizeof (cPlayer *), ListSortCallback);
}
//
// Start fresh
//
list_ctrl->Delete_All_Entries ();
//
// Add the players to the list control
//
for (index = 0; index < player_list.Count (); index ++) {
cPlayer *player = player_list[index];
//
// Make a new entry for this player
//
int item_index = list_ctrl->Insert_Entry (index, L"");
if (item_index >= 0) {
//
// Fill in the player's name
//
WideStringClass displayName(0, true);
Build_Player_Display_Name(player, displayName);
list_ctrl->Set_Entry_Text (item_index, COL_NAME, (const WCHAR*)displayName);
//
// Fill in information about the player
//
list_ctrl->Set_Entry_Int (item_index, COL_RANK, player->Get_Rung ());
list_ctrl->Set_Entry_Int (item_index, COL_SCORE, player->Get_Score ());
list_ctrl->Set_Entry_Int (item_index, COL_KILLS, player->Get_Kills ());
if (ShowLadderPoints) {
list_ctrl->Set_Entry_Int (item_index, COL_LADDER, player->Get_Ladder_Points ());
}
//
// Put a star by the player's name if this is the local player
//
SmartGameObj *game_obj = player->Get_GameObj ();
if (cNetwork::I_Am_Client() && (game_obj == COMBAT_STAR)) {
list_ctrl->Add_Icon (item_index, COL_NAME, "IF_LRGSTAR.TGA");
list_ctrl->Set_Entry_Color (item_index, COL_RANK, Vector3 (1.0F, 1.0F, 1.0F));
list_ctrl->Set_Entry_Color (item_index, COL_NAME, Vector3 (1.0F, 1.0F, 1.0F));
list_ctrl->Set_Entry_Color (item_index, COL_SCORE, Vector3 (1.0F, 1.0F, 1.0F));
list_ctrl->Set_Entry_Color (item_index, COL_KILLS, Vector3 (1.0F, 1.0F, 1.0F));
if (ShowLadderPoints) {
list_ctrl->Set_Entry_Color (item_index, COL_LADDER, Vector3 (1.0F, 1.0F, 1.0F));
}
}
//
// Set the ranking as this entries user data so we can sort by it...
//
list_ctrl->Set_Entry_Data (item_index, COL_RANK, player->Get_Rung ());
}
}
return ;
}
////////////////////////////////////////////////////////////////
//
// ListSortCallbackk
//
////////////////////////////////////////////////////////////////
int __cdecl
CNCWinScreenMenuClass::ListSortCallback
(
const void *elem1,
const void *elem2
)
{
WWASSERT (elem1 != NULL);
WWASSERT (elem2 != NULL);
cPlayer *player1 = *((cPlayer **)elem1);
cPlayer *player2 = *((cPlayer **)elem2);
//
// Sort based on rank
//
int rank1 = (int)player1->Get_Rung ();
int rank2 = (int)player2->Get_Rung ();
return (rank1 - rank2);
}
////////////////////////////////////////////////////////////////
//
// Build_Player_Display_Name
//
////////////////////////////////////////////////////////////////
void
CNCWinScreenMenuClass::Build_Player_Display_Name (const cPlayer *player, WideStringClass &outName)
{
// Denzil 02/24/02 Day 1 Patch - Do not show clan abbreviation for now because
// it does not always fit in the space alloted. For now it is better not to
// show it than to have it chopped off.
#if(0)
GameModeClass* gameMode = GameModeManager::Find("WOL");
if (gameMode && gameMode->Is_Active()) {
WolGameModeClass* wolGame = static_cast<WolGameModeClass*>(gameMode);
WWASSERT(wolGame);
RefPtr<WWOnline::UserData> user = wolGame->Get_WOL_User_Data(player->Get_Name());
if (user.IsValid()) {
// Set there clan information
RefPtr<WWOnline::SquadData> clan = user->GetSquad();
if (clan.IsValid()) {
outName.Format(L"%s [%S]", player->Get_Name(), clan->GetAbbr());
return;
}
}
}
#endif
outName = player->Get_Name();
}