466 lines
12 KiB
C++
466 lines
12 KiB
C++
/*
|
|
** 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/team.cpp $*
|
|
* *
|
|
* $Author:: Tom_s $*
|
|
* *
|
|
* $Modtime:: 2/05/02 11:22a $*
|
|
* *
|
|
* $Revision:: 58 $*
|
|
* *
|
|
*---------------------------------------------------------------------------------------------*
|
|
* Functions: *
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
|
|
#include "team.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "teammanager.h"
|
|
#include "miscutil.h"
|
|
#include "cnetwork.h"
|
|
#include "playermanager.h"
|
|
#include "gamedata.h"
|
|
#include "wwdebug.h"
|
|
#include "useroptions.h"
|
|
#include "playertype.h"
|
|
#include "colors.h"
|
|
#include "networkobjectfactory.h"
|
|
#include "netclassids.h"
|
|
#include "gameobjmanager.h"
|
|
#include "translatedb.h"
|
|
#include "string_ids.h"
|
|
#include "multihud.h"
|
|
#include "apppackettypes.h"
|
|
#include "devoptions.h"
|
|
#include "gamespyadmin.h"
|
|
|
|
DECLARE_NETWORKOBJECT_FACTORY(cTeam, NETCLASSID_TEAM);
|
|
|
|
//------------------------------------------------------------------------------------
|
|
cTeam::cTeam(void)
|
|
{
|
|
Reset();
|
|
|
|
Set_App_Packet_Type(APPPACKETTYPE_TEAM);
|
|
|
|
cTeamManager::Add(this);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
cTeam::~cTeam(void)
|
|
{
|
|
//WWDEBUG_SAY(("* Destroying team object %d (%s)\n", TeamNumber, Name));
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
void cTeam::Init(int team_number)//, WideStringClass & name)
|
|
{
|
|
WWASSERT(team_number >= 0 && team_number < MAX_TEAMS);
|
|
WWASSERT(cNetwork::I_Am_Server());
|
|
|
|
//WWDEBUG_SAY(("* Adding team object %d (%s)\n", team_number, name));
|
|
|
|
Set_Object_Dirty_Bit(NetworkObjectClass::BIT_CREATION, true);
|
|
|
|
/*
|
|
//
|
|
// This doesn't work because at this point we are not yet a client
|
|
//
|
|
if (cNetwork::I_Am_Client()) {
|
|
//
|
|
// Turn off for self
|
|
//
|
|
Set_Object_Dirty_Bit(cNetwork::Get_My_Id(), NetworkObjectClass::BIT_CREATION, false);
|
|
}
|
|
/**/
|
|
|
|
TeamNumber = team_number;
|
|
Init_Team_Name();
|
|
|
|
//
|
|
// Special-case the IDs because this code is executed before loading,
|
|
// and in loading the dynamic range is reset.
|
|
//
|
|
if (TeamNumber == PLAYERTYPE_NOD) {
|
|
Set_Network_ID(NETID_NOD_TEAM);
|
|
} else {
|
|
WWASSERT(TeamNumber == PLAYERTYPE_GDI);
|
|
Set_Network_ID(NETID_GDI_TEAM);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
void cTeam::Init_Team_Name(void)
|
|
{
|
|
if (TeamNumber == PLAYERTYPE_NOD) {
|
|
Name = TRANSLATION(IDS_MP_TEAMNAME_MISSIONS_TEAM_0);
|
|
} else {
|
|
WWASSERT(TeamNumber == PLAYERTYPE_GDI);
|
|
Name = TRANSLATION(IDS_MP_TEAMNAME_MISSIONS_TEAM_1);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
void cTeam::Reset(void)
|
|
{
|
|
Kills = 0;
|
|
Deaths = 0;
|
|
Score = 0;
|
|
Money = 0;
|
|
|
|
Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
void cTeam::Set_Kills(int new_kills)
|
|
{
|
|
WWASSERT(cNetwork::I_Am_Only_Client());
|
|
WWASSERT(new_kills >= 0);
|
|
|
|
Kills = new_kills;
|
|
|
|
Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
void cTeam::Set_Deaths(int new_deaths)
|
|
{
|
|
WWASSERT(cNetwork::I_Am_Only_Client());
|
|
WWASSERT(new_deaths >= 0);
|
|
|
|
Deaths = new_deaths;
|
|
|
|
Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
void cTeam::Set_Score(float new_score)
|
|
{
|
|
//WWASSERT(cNetwork::I_Am_Only_Client());
|
|
|
|
Score = new_score;
|
|
|
|
Set_Object_Dirty_Bit(NetworkObjectClass::BIT_OCCASIONAL, true);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
int cTeam::Tally_Size(void) const
|
|
{
|
|
//
|
|
// For the sake of simplicity/at the cost of efficiency, we calculate
|
|
// team size, rather than storing and maintaining it.
|
|
// To remind you of this I use "tally" instead of "get".
|
|
//
|
|
|
|
return cPlayerManager::Tally_Team_Size(TeamNumber);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
void cTeam::Increment_Kills(void)
|
|
{
|
|
if (!CombatManager::Is_Gameplay_Permitted()) {
|
|
return;
|
|
}
|
|
|
|
WWASSERT(cNetwork::I_Am_Server());
|
|
|
|
Kills++;
|
|
|
|
Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
void cTeam::Increment_Deaths(void)
|
|
{
|
|
if (!CombatManager::Is_Gameplay_Permitted()) {
|
|
return;
|
|
}
|
|
|
|
WWASSERT(cNetwork::I_Am_Server());
|
|
|
|
Deaths++;
|
|
|
|
Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
void cTeam::Increment_Score(float increment)
|
|
{
|
|
if (!CombatManager::Is_Gameplay_Permitted()) {
|
|
return;
|
|
}
|
|
|
|
WWASSERT(cNetwork::I_Am_Server());
|
|
|
|
Score += increment;
|
|
|
|
Set_Object_Dirty_Bit(NetworkObjectClass::BIT_OCCASIONAL, true);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
float cTeam::Get_Kill_To_Death_Ratio(void) const
|
|
{
|
|
//
|
|
// If Deaths = 0, return -1;
|
|
//
|
|
float ktd = -1;
|
|
if (Deaths > 0) {
|
|
ktd = Kills / (float) Deaths;
|
|
}
|
|
|
|
return ktd;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
void cTeam::Get_Team_String(int rank, WideStringClass & string) const
|
|
{
|
|
//
|
|
// Compose a string description of a team's stats for display
|
|
//
|
|
|
|
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;
|
|
|
|
//
|
|
// Num Players
|
|
//
|
|
substring.Format(L"%-2d ", Tally_Size());
|
|
string += substring;
|
|
|
|
/*
|
|
//
|
|
// Standing
|
|
//
|
|
if (is_verbose) {
|
|
substring.Format(L" %2d. ", rank);
|
|
string += substring;
|
|
}
|
|
*/
|
|
|
|
//
|
|
// Name
|
|
//
|
|
//GAMESPY
|
|
//substring.Format(L"%-11s", Name);
|
|
if (cGameSpyAdmin::Is_Gamespy_Game()) {
|
|
substring.Format(L"%-36s", Name);
|
|
} else {
|
|
substring.Format(L"%-11s", Name);
|
|
}
|
|
string += substring;
|
|
|
|
|
|
//
|
|
// Kills
|
|
//
|
|
if (is_verbose) {
|
|
substring.Format(L"%-8d", Kills);
|
|
string += substring;
|
|
}
|
|
|
|
//
|
|
// Deaths
|
|
//
|
|
if (is_verbose) {
|
|
substring.Format(L"%-8d", Deaths);
|
|
string += substring;
|
|
}
|
|
|
|
//
|
|
// Kill to Death ratio
|
|
//
|
|
if (is_verbose) {
|
|
float ktd = Get_Kill_To_Death_Ratio();
|
|
if (ktd >= 0) {
|
|
substring.Format(L"%-8.1f", ktd);
|
|
} else {
|
|
substring.Format(L"%-8s", "-");
|
|
}
|
|
string += substring;
|
|
}
|
|
|
|
/**/
|
|
//
|
|
// Money
|
|
//
|
|
WWASSERT(PTheGameData != NULL);
|
|
if ((The_Game()->Is_Cnc() || The_Game()->Is_Skirmish()) && is_verbose) {
|
|
|
|
#ifdef WWDEBUG
|
|
bool show = cDevOptions::ShowMoney.Is_True() ||
|
|
#else
|
|
bool show =
|
|
#endif // WWDEBUG
|
|
cNetwork::I_Am_Only_Server() ||
|
|
(cNetwork::I_Am_Client() &&
|
|
cNetwork::Get_My_Player_Object() != NULL &&
|
|
(cNetwork::Get_My_Team_Number() == TeamNumber));
|
|
|
|
if (show) {
|
|
substring.Format(L"%-8d", Tally_Money());
|
|
} else {
|
|
substring.Format(L"%-8s", "-");
|
|
}
|
|
|
|
string += substring;
|
|
}
|
|
/**/
|
|
|
|
//
|
|
// Score
|
|
//
|
|
substring.Format(L"%-8d", (int) Score);
|
|
string += substring;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
Vector3 cTeam::Get_Color(void) const
|
|
{
|
|
return Get_Color_For_Team(TeamNumber);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
int cTeam::Tally_Money(void) const
|
|
{
|
|
int tally = 0;
|
|
|
|
for ( SLNode<cPlayer> * player_node = cPlayerManager::Get_Player_Object_List()->Head();
|
|
player_node != NULL;
|
|
player_node = player_node->Next ())
|
|
{
|
|
cPlayer * p_player = player_node->Data();
|
|
WWASSERT(p_player != NULL);
|
|
|
|
if (p_player->Get_Is_Active().Is_True() &&
|
|
p_player->Get_Player_Type() == TeamNumber)
|
|
{
|
|
tally += (int) p_player->Get_Money();
|
|
}
|
|
}
|
|
|
|
return tally;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
void cTeam::Export_Creation(BitStreamClass &packet)
|
|
{
|
|
NetworkObjectClass::Export_Creation (packet);
|
|
|
|
packet.Add(TeamNumber);
|
|
//packet.Add_Wide_Terminated_String(Name);//XXX
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
void cTeam::Import_Creation(BitStreamClass &packet)
|
|
{
|
|
NetworkObjectClass::Import_Creation(packet);
|
|
|
|
packet.Get(TeamNumber);
|
|
//packet.Get_Wide_Terminated_String(Name, sizeof(Name));
|
|
//packet.Get_Wide_Terminated_String(Name.Get_Buffer(256), 256);
|
|
Init_Team_Name();
|
|
|
|
WWASSERT(cNetwork::I_Am_Only_Client());
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
void cTeam::Export_Rare(BitStreamClass &packet)
|
|
{
|
|
packet.Add(Kills);
|
|
packet.Add(Deaths);
|
|
//packet.Add(Score);
|
|
////packet.Add(Money);
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
void cTeam::Import_Rare(BitStreamClass &packet)
|
|
{
|
|
int placeholder = 0;
|
|
//float float_placeholder = 0;
|
|
|
|
Set_Kills( packet.Get(placeholder));
|
|
Set_Deaths( packet.Get(placeholder));
|
|
//Set_Score( packet.Get(float_placeholder));
|
|
////Set_Money( packet.Get(placeholder));
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
void cTeam::Export_Occasional(BitStreamClass &packet)
|
|
{
|
|
packet.Add(Score);
|
|
//packet.Add(Money);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
void cTeam::Import_Occasional(BitStreamClass &packet)
|
|
{
|
|
//int placeholder = 0;
|
|
float float_placeholder = 0;
|
|
|
|
Set_Score( packet.Get(float_placeholder));
|
|
//Set_Money( packet.Get(placeholder));
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
void cTeam::Export_Frequent(BitStreamClass &packet)
|
|
{
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
void cTeam::Import_Frequent(BitStreamClass &packet)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//FlagCaps = 0;
|
|
//FlagLosses = 0;
|