| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661 |
- /*
- ** 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/>.
- */
- /***********************************************************************************************
- *** Confidential - Westwood Studios ***
- ***********************************************************************************************
- * *
- * Project Name : Commando *
- * *
- * $Archive:: /Commando/Code/Commando/teammanager.cpp $*
- * *
- * $Author:: Tom_s $*
- * *
- * $Modtime:: 2/22/02 11:29a $*
- * *
- * $Revision:: 73 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "teammanager.h" // I WANNA BE FIRST!
- #include <stdio.h>
- #include "miscutil.h"
- #include "_globals.h"
- #include "assets.h"
- #include "cnetwork.h"
- //#include "gamesettings.h"
- #include "multihud.h"
- #include <win.h>
- #include "player.h"
- #include "font3d.h"
- #include "gamedata.h"
- #include "useroptions.h"
- #include "smartgameobj.h"
- #include "playertype.h"
- #include "colors.h"
- #include "render2d.h"
- #include "wwprofile.h"
- #include "gametype.h"
- #include "playermanager.h"
- #include "translatedb.h"
- #include "string_ids.h"
- #include "consolemode.h"
- #include "gamespyadmin.h"
- //
- // Class statics
- //
- SList<cTeam> cTeamManager::TeamList;
- cTeam * cTeamManager::Team_Array[];
- float cTeamManager::TeamListHeight = 0;
- Render2DTextClass * cTeamManager::PTextRenderer = NULL;
- Font3DInstanceClass * cTeamManager::PFont = NULL;
- const float cTeamManager::Y_INCREMENT_FACTOR = 1.2f;
- int cTeamManager::XPos = 0;
- int cTeamManager::YPos = 0;
- static WideStringClass renderer_team_heading;
- static WideStringClass renderer_team_strings[MAX_TEAMS];
- static Vector3 renderer_team_colors[MAX_TEAMS];
- static bool renderer_is_intermission_true;
- //------------------------------------------------------------------------------------
- void cTeamManager::Onetime_Init(void)
- {
- if (!ConsoleBox.Is_Exclusive()) {
- WWASSERT(PFont == NULL);
- WWASSERT(WW3DAssetManager::Get_Instance() != NULL);
- PFont = WW3DAssetManager::Get_Instance()->Get_Font3DInstance("FONT6x8.TGA");
- WWASSERT(PFont != NULL);
- PFont->Set_Mono_Spaced();
- SET_REF_OWNER(PFont);
- WWASSERT(PTextRenderer == NULL);
- PTextRenderer = new Render2DTextClass(PFont);
- WWASSERT(PTextRenderer != NULL);
- PTextRenderer->Set_Coordinate_Range(Render2DClass::Get_Screen_Resolution());
- }
- renderer_team_heading=L"";
- renderer_is_intermission_true=false;
- }
- //------------------------------------------------------------------------------------
- void cTeamManager::Onetime_Shutdown(void)
- {
- if (!ConsoleBox.Is_Exclusive()) {
- WWASSERT(PTextRenderer != NULL);
- delete PTextRenderer;
- PTextRenderer = NULL;
- WWASSERT(PFont != NULL);
- PFont->Release_Ref();
- PFont = NULL;
- }
- }
- //------------------------------------------------------------------------------------
- void cTeamManager::Think(void)
- {
- WWPROFILE( "cTeamManager::Think" );
- if (PTextRenderer == NULL) {
- return;
- }
- if (MultiHUDClass::Is_On()) {
- WWASSERT(PTextRenderer != NULL);
- Render_Team_List();
- }
- else {
- // This will make sure the team list disappears if it is not displayed
- if (PTextRenderer) PTextRenderer->Reset();
- }
- }
- //-----------------------------------------------------------------------------------
- void cTeamManager::Render(void)
- {
- WWPROFILE("cTeamManager::Render");
- if (PTextRenderer == NULL) {
- return;
- }
- WWASSERT(PTextRenderer != NULL);
- PTextRenderer->Render();
- }
- //------------------------------------------------------------------------------------
- cTeam * cTeamManager::Find_Team(int team_number)
- {
- WWASSERT(team_number >= 0 && team_number < MAX_TEAMS);
- SLNode<cTeam> * objnode;
- cTeam *obj;
- for (objnode = TeamList.Head(); objnode; objnode = objnode->Next()) {
- obj = objnode->Data();
- WWASSERT(obj != NULL);
- if (obj->Get_Id() == team_number) {
- return obj; // found it
- }
- }
- return NULL; // Not found
- }
- cTeam* cTeamManager::Find_Empty_Team(void)
- {
- SLNode<cTeam>* node = TeamList.Head();
- while (node) {
- cTeam* team = node->Data();
- if (team && (team->Tally_Size() == 0)) {
- return team;
- }
- node = node->Next();
- }
- return NULL;
- }
- //------------------------------------------------------------------------------------
- void cTeamManager::Add(cTeam * p_team)
- {
- WWASSERT(p_team != NULL);
- TeamList.Add_Tail(p_team);
- }
- //------------------------------------------------------------------------------------
- void cTeamManager::Remove(cTeam * p_team)
- {
- WWASSERT(p_team != NULL);
- TeamList.Remove(p_team);
- delete p_team;
- }
- //------------------------------------------------------------------------------------
- void cTeamManager::Remove(int team_number)
- {
- WWASSERT(team_number >= 0 && team_number < MAX_TEAMS);
- cTeam * p_team = Find_Team(team_number);
- if (p_team != NULL) {
- Remove(p_team);
- }
- }
- //------------------------------------------------------------------------------------
- void cTeamManager::Remove_All(void)
- {
- for (SLNode<cTeam> * objnode = TeamList.Head(); objnode != NULL;) {
- cTeam * p_team = objnode->Data();
- objnode = objnode->Next();
- Remove(p_team);
- }
- }
- //------------------------------------------------------------------------------------
- int cTeamManager::Compute_Team_List_Height(void)
- {
- /*
- int height = 0;
- if (The_Game()->Is_Team_Game()) {
- WWASSERT(PFont != NULL);
- height = (int)(4 * PFont->Char_Height() * Y_INCREMENT_FACTOR);
- }
- */
- WWASSERT(PFont != NULL);
- int height = (int)(4 * PFont->Char_Height() * Y_INCREMENT_FACTOR);
- return height;
- }
- //-----------------------------------------------------------------------------
- void cTeamManager::Log_Team_List(void)
- {
- WWDEBUG_SAY(("cTeamManager::Log_Team_List\n"));
- StringClass results_filename;
- results_filename.Format("results%d.txt", cUserOptions::ResultsLogNumber.Get());
- FILE * file = ::fopen(results_filename, "wt");
- if (file != NULL) {
- char line[2000] = "";
- WideStringClass wide_text(0, true);
- Construct_Heading(wide_text);//, true);
- StringClass text;
- wide_text.Convert_To(text);
- ::sprintf(line, "%s\n", text.Peek_Buffer());
- ::fwrite(line, 1, ::strlen(line), file);
- for (int j = 0; j < MAX_TEAMS; j++) {
- cTeam * p_team = Team_Array[j];
- if (p_team != NULL) {
- //p_team->Get_Player_String(j + 1, wide_text, true);
- p_team->Get_Team_String(j + 1, wide_text);
- wide_text.Convert_To(text);
- ::sprintf(line, "%s\n", text.Peek_Buffer());
- ::fwrite(line, 1, ::strlen(line), file);
- }
- }
- ::sprintf(line, "\n");
- ::fwrite(line, 1, ::strlen(line), file);
- ::fclose(file);
- }
- }
- //-----------------------------------------------------------------------------
- WideStringClass cTeamManager::Get_Team_Name(int team_number)
- {
- WWASSERT(team_number >= 0 && team_number < MAX_TEAMS);
- cTeam * p_team = cTeamManager::Find_Team(team_number);
- WWASSERT(p_team != NULL);
- return p_team->Get_Name();
- }
- //-----------------------------------------------------------------------------
- void cTeamManager::Reset_Teams(void)
- {
- SLNode<cTeam> * objnode;
- cTeam * p_team = NULL;
- for (objnode = TeamList.Head(); objnode != NULL; objnode = objnode->Next()) {
- p_team = objnode->Data();
- WWASSERT(p_team != NULL);
- p_team->Reset();
- }
- }
- //-----------------------------------------------------------------------------
- int cTeamManager::Get_Non_Empty_Team_Count(void)
- {
- int num_teams = 0;
- cTeam * p_team;
- for (SLNode<cTeam> * objnode = TeamList.Head(); objnode != NULL; objnode = objnode->Next()) {
- p_team = objnode->Data();
- WWASSERT(p_team != NULL);
- if (p_team->Tally_Size() > 0) {
- num_teams++;
- }
- }
- return num_teams;
- }
- //-----------------------------------------------------------------------------
- void cTeamManager::Sort_Teams(void)
- {
- WWPROFILE("cTeamManager::Sort_Teams");
- ZeroMemory(Team_Array, sizeof(Team_Array));
- int num_teams = 0;
- cTeam * p_team;
- for (SLNode<cTeam> * objnode = TeamList.Head(); objnode != NULL; objnode = objnode->Next()) {
- p_team = objnode->Data();
- WWASSERT(p_team != NULL);
- WWASSERT(num_teams < MAX_TEAMS);
- Team_Array[num_teams] = p_team;
- num_teams++;
- }
- qsort(&Team_Array[0], num_teams, sizeof(cTeam *), &Team_Compare);
- }
- //-----------------------------------------------------------------------------
- int cTeamManager::Get_Leaders_Id(void)
- {
- WWASSERT(Team_Array[0] != NULL);
- return Team_Array[0]->Get_Id();
- }
- //-----------------------------------------------------------------------------
- int cTeamManager::Sort_Score_Ktd_Kills(cTeam * p_team1, cTeam * p_team2)
- {
- WWASSERT(p_team1 != NULL);
- WWASSERT(p_team2 != NULL);
- int result;
- if (p_team1->Get_Score() > p_team2->Get_Score()) {
- result = -1;
- } else if (p_team1->Get_Score() == p_team2->Get_Score()) {
- //if (p_team1->Get_Kill_To_Death_Ratio() > p_team2->Get_Kill_To_Death_Ratio()) {
- // result = -1;
- //} else if (p_team1->Get_Kill_To_Death_Ratio() == p_team2->Get_Kill_To_Death_Ratio()) {
- if (p_team1->Get_Kills() > p_team2->Get_Kills()) {
- result = -1;
- } else if (p_team1->Get_Kills() == p_team2->Get_Kills()) {
- //
- // OK, give up, they are equal
- //
- result = 0;
- } else {
- result = 1;
- }
- //} else {
- // result = 1;
- //}
- } else {
- result = 1;
- }
- return result;
- }
- //-----------------------------------------------------------------------------
- int cTeamManager::Team_Compare(const void * elem1, const void * elem2)
- {
- //
- // Used by qsort
- //
- WWASSERT(elem1 != NULL);
- WWASSERT(elem2 != NULL);
- cTeam * p_team1 = *((cTeam **)elem1);
- cTeam * p_team2 = *((cTeam **)elem2);
- WWASSERT(p_team1 != NULL);
- WWASSERT(p_team2 != NULL);
- //
- // Sort order:
- // 1. If there is a life limit, sort on lives.
- // 2. Sort on score.
- // 3. Sort on KTD ratio.
- // 4. Sort on Kills
- //
- int result = Sort_Score_Ktd_Kills(p_team1, p_team2);
- return result;
- }
- //-----------------------------------------------------------------------------
- void cTeamManager::List_Print(WideStringClass & text, Vector3 color)
- {
- //WWASSERT(text != NULL);
- //WWASSERT(::strlen(text) > 0);
- if (PTextRenderer == NULL) {
- return;
- }
- WWASSERT(PTextRenderer != NULL);
- PTextRenderer->Set_Location(Vector2(cMathUtil::Round(XPos), cMathUtil::Round(YPos)));
- int c = ((int)(color[0]*255)&0xFF) << 16 | ((int)(color[1]*255)&0xFF) << 8 | ((int)(color[2]*255)&0xFF) << 0 | 0xFF000000;
- PTextRenderer->Draw_Text(text, c);
- WWASSERT(PFont != NULL);
- YPos += PFont->Char_Height() * Y_INCREMENT_FACTOR;
- }
- //-----------------------------------------------------------------------------
- void cTeamManager::Construct_Heading(WideStringClass & string)
- {
- string.Format(L"");
- WWASSERT(PTheGameData != NULL);
- //bool is_verbose = The_Game()->IsIntermission.Get() || MultiHUDClass::Get_Verbose_Lists();
- bool is_verbose = //force_verbose ||
- The_Game()->IsIntermission.Is_True() ||
- //MultiHUDClass::Get_Verbose_Lists();
- (MultiHUDClass::Get_Playerlist_Format() == PLAYERLIST_FORMAT_FULL);
- WideStringClass substring(0,true);
- //
- // Num Players
- //
- substring.Format(L"%-3s", L"");
- string += substring;
- /*
- //
- // Standing
- //
- if (is_verbose) {
- substring.Format(L"%-5s", L"");
- string += substring;
- }
- */
- //
- // "Team" or "Clan"
- //
- //GAMESPY
- //substring.Format(L"%-11s", The_Game()->Get_Team_Word());
- if (cGameSpyAdmin::Is_Gamespy_Game()) {
- substring.Format(L"%-36s", The_Game()->Get_Team_Word());
- } else {
- substring.Format(L"%-11s", The_Game()->Get_Team_Word());
- }
- string += substring;
- //
- // Kills
- //
- if (is_verbose) {
- substring.Format(L"%-8s", TRANSLATION(IDS_MP_KILLS));
- string += substring;
- }
- //
- // Deaths
- //
- if (is_verbose) {
- substring.Format(L"%-8s", TRANSLATION(IDS_MP_DEATHS));
- string += substring;
- }
- //
- // Kill to Death ratio
- //
- if (is_verbose) {
- substring.Format(L"%-8s", TRANSLATION(IDS_MP_KILL_TO_DEATH_RATIO));
- string += substring;
- }
- /**/
- //
- // Money
- //
- if ((The_Game()->Is_Cnc() || The_Game()->Is_Skirmish()) && is_verbose) {
- substring.Format(L"%-8s", TRANSLATION(IDS_MP_MONEY));
- string += substring;
- }
- /**/
- //
- // Score
- //
- substring.Format(L"%-8s", TRANSLATION(IDS_MP_SCORE));
- string += substring;
- }
- //-----------------------------------------------------------------------------
- void cTeamManager::Render_Team_List(void)
- {
- if (PTextRenderer == NULL) {
- return;
- }
- WWASSERT(PFont != NULL);
- WWASSERT(PTextRenderer != NULL);
- WWASSERT(PTheGameData != NULL);
- if (GameModeManager::Find("Combat") == NULL ||
- !GameModeManager::Find("Combat")->Is_Active() ||
- The_Game()->IsIntermission.Is_True()) {
- PTextRenderer->Reset();
- return;
- }
- //
- // Format:
- // AAAAAAAAAxxNNNNxxNNNxNNNxNNNxNxxNNNxxNNNNN, e.g:
- // Charlie 5 25 13 1.5 12 1203
- //
- // Fields are name, num players, kills, death, kills-to-deaths, num-lives, score
- //
- /*
- if (!The_Game()->Is_Team_Game()) {
- PTextRenderer->Reset();
- return;
- }
- */
- /*
- //
- // Count the non-empty teams
- //
- int num_teams = Get_Non_Empty_Team_Count();
- if (num_teams == 0) {
- return;
- }
- */
- bool changed=false;
- //
- // Build heading
- //
- WideStringClass heading(0,true);
- Construct_Heading(heading);
- if (heading!=renderer_team_heading) {
- renderer_team_heading=heading;
- changed=true;
- }
- // Verify that the team list is valid
- for (int j = 0; j < MAX_TEAMS; j++) {
- if (!Team_Array[j]) {
- Sort_Teams();
- break;
- }
- }
- for (j = 0; j < MAX_TEAMS; j++) {
- cTeam * p_team = Team_Array[j];
- WWASSERT(p_team != NULL);
- renderer_team_colors[j]=p_team->Get_Color();
- if (changed) {
- p_team->Get_Team_String(j + 1, renderer_team_strings[j]);
- }
- else {
- WideStringClass team_string(0,true);
- p_team->Get_Team_String(j + 1, team_string);
- if (team_string!=renderer_team_strings[j]) {
- changed=true;
- renderer_team_strings[j]=team_string;
- }
- }
- }
- WWASSERT(PTheGameData != NULL);
- if (The_Game()->IsIntermission.Is_True()!=renderer_is_intermission_true) {
- renderer_is_intermission_true=The_Game()->IsIntermission.Is_True();
- changed=true;
- }
- if (!changed) return;
- PTextRenderer->Reset();
- //
- // Determine left edge placement
- //
- XPos = 0;
- float text_len = PFont->String_Width(heading);
- if (The_Game()->IsIntermission.Is_True()) {
- XPos = Render2DClass::Get_Screen_Resolution().Center().X - text_len / 2.0f;
- } else {
- XPos = Render2DClass::Get_Screen_Resolution().Right - 20 - text_len;
- }
- YPos = 10;
- //
- // Show Win text
- //
- WWASSERT(PTheGameData != NULL);
- if (The_Game()->IsIntermission.Is_True()) {
- int combined_height =
- Compute_Team_List_Height() +
- cPlayerManager::Compute_Full_Player_List_Height() +
- 2 * PFont->Char_Height() * Y_INCREMENT_FACTOR;
- YPos = (int)(Render2DClass::Get_Screen_Resolution().Height() / 2.0 - combined_height / 2.0);
- if (YPos < 10) {
- YPos = 10;
- }
- WideStringClass text(cGameData::Get_Win_Text(),true);
- float x = Render2DClass::Get_Screen_Resolution().Center().X -
- PFont->String_Width(text) / 2.0f;
- float y = YPos;
- PTextRenderer->Set_Location(Vector2(cMathUtil::Round(x), cMathUtil::Round(y)));
- PTextRenderer->Draw_Text(text);
- YPos += 2 * PFont->Char_Height() * Y_INCREMENT_FACTOR;
- }
- //
- // Draw the teamlist heading
- //
- List_Print(heading, Vector3(1, 1, 1));
- for (j = 0; j < MAX_TEAMS; j++) {
- List_Print(renderer_team_strings[j], renderer_team_colors[j]);
- }
- }
|