/*
** 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 .
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Commando/gamedata.cpp $*
* *
* $Author:: Steve_t $*
* *
* $Modtime:: 11/01/02 4:32p $*
* *
* $Revision:: 221 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "gamedata.h"
#include
#include
#include "win.h"
#include "miscutil.h"
#include "cnetwork.h"
#include "chatshre.h"
#include "wwdebug.h"
#include "netinterface.h"
#include "translatedb.h"
#include "playertype.h"
#include "teammanager.h"
#include "playermanager.h"
#include "assets.h"
#include "translatedb.h"
#include "string_ids.h"
#include "gamemode.h"
#include "savegame.h"
#include "bandwidth.h"
#include "gametype.h"
#include "systimer.h"
#include "objlibrary.h"
#include "scriptzone.h"
#include "aabox.h"
#include "rendobj.h"
#include "weaponbag.h"
#include "multihud.h"
#include "wwaudio.h"
#include "textdisplay.h"
#include "render2d.h"
#include "render2dsentence.h"
#include "wwprofile.h"
#include "winevent.h"
#include "realcrc.h"
#include "useroptions.h"
#include "gdsingleplayer.h"
#include "gdcnc.h"
#include "wolgmode.h"
#include "font3d.h"
#include "nat.h"
#include "csdamageevent.h"
#include "sctextobj.h"
#include "widestring.h"
#include "vehicle.h"
#include "wolgameinfo.h"
#include "spawn.h"
#include "dlgcncwinscreen.h"
#include "dialogmgr.h"
#include "rawfile.h"
#include "consolemode.h"
#include "gamedataupdateevent.h"
#include "stylemgr.h"
#include "modpackagemgr.h"
#include "modpackage.h"
#include "bandwidthcheck.h"
#include "serversettings.h"
#include "gamespyadmin.h"
#include "specialbuilds.h"
#include "demosupport.h"
#include "specialbuilds.h"
const int cGameData::MAX_TIME_LIMIT = 999;
cGameData * PTheGameData = NULL;
static WideStringClass renderer_time_text;
static WideStringClass renderer_dedicated_server_label;
static WideStringClass renderer_gameplay_label;
static unsigned renderer_dedicated_server_color;
static unsigned renderer_gameplay_color;
//
// Class statics
//
const StringClass cGameData::INI_SECTION_NAME = "Settings";
const float cGameData::LIMITS_X_POS = 0.8f;
Render2DSentenceClass * cGameData::PTextRenderer = NULL;
int cGameData::HostedGameNumber = 0;
bool cGameData::IsManualRestart = false;
bool cGameData::IsManualExit = false;
WideStringClass cGameData::WinText;
//
// hack
//
ULONG g_ip_override = INADDR_NONE;
//------------------------------------------------------------------------------------
void cGameData::Onetime_Init(void)
{
WWDEBUG_SAY(("cGameData::Onetime_Init\n"));
if (!ConsoleBox.Is_Exclusive()) {
PTextRenderer = new Render2DSentenceClass;
StyleMgrClass::Assign_Font(PTextRenderer, StyleMgrClass::FONT_INGAME_TXT);
PTextRenderer->Set_Mono_Spaced(true);
PTextRenderer->Set_Clipping_Rect(Render2DClass::Get_Screen_Resolution());
}
}
//------------------------------------------------------------------------------------
void cGameData::Onetime_Shutdown(void)
{
WWDEBUG_SAY(("cGameData::Onetime_Shutdown\n"));
if (!ConsoleBox.Is_Exclusive()) {
WWASSERT(PTextRenderer != NULL);
delete PTextRenderer;
PTextRenderer = NULL;
}
}
//-----------------------------------------------------------------------------
cGameData::cGameData(void) :
DoExeVersionsMatch (true),
DoStringVersionsMatch (true),
DoMapsLoop (true),
IsMapCycleOver (false),
MapCycleIndex(0)
{
//WWDEBUG_SAY(("cGameData::cGameData\n"));
IsIntermission.Set( false);
IsDedicated.Set( false);
IsAutoRestart.Set( false);
IsFriendlyFirePermitted.Set( false);
IsTeamChangingAllowed.Set( true);
IsPassworded.Set( false);
IsFreeWeapons.Set( false);
IsLaddered.Set( false);
IsClanGame.Set( false);
IsClientTrusted.Set( true);
RemixTeams.Set( false);
CanRepairBuildings.Set( true);
DriverIsAlwaysGunner.Set( true);
SpawnWeapons.Set( false);
mWinnerID = -1;
MaxPlayers = 16;
TimeLimitMinutes = 0;
RadarMode = RADAR_ALL;
IniFilename = "";
Motd.Format(L"");
Set_Password( L"");
//Set_Owner( "UNOWNED");
Set_Owner( cNetInterface::Get_Nickname());
IntermissionTimeSeconds = 15;
Set_Version_Number( cNetwork::Get_Exe_Key());
Set_Ip_Address(0);
Set_Port( 4848);//TSS - hardcoded port
Set_Current_Players(0);
IntermissionTimeRemaining = 0;
TimeRemainingSeconds = 0;
MaximumWorldDistance = 0;
MinQualifyingTimeMinutes = 2;
IsQuickMatchServer = false;
//ServerIsGameplayPermitted = false;
WinType = WIN_TYPE_TIME;
GameDurationS = 0;
LastServerConfigModTime = 0;
SettingsDescription = TRANSLATE(IDS_SERVER_SAVELOAD_CUSTOM_DEFAULT);
Clear_Clans();
MvpCount = 0;
#ifdef MULTIPLAYERDEMO
MapName.Format("C&C_Under.mix");
#endif // MULTIPLAYERDEMO
}
//-----------------------------------------------------------------------------
cGameData::~cGameData(void)
{
//WWDEBUG_SAY(("cGameData::~cGameData\n"));
}
//-----------------------------------------------------------------------------
cGameData& cGameData::operator=(const cGameData& rhs)
{
IsIntermission = rhs.IsIntermission;
IsDedicated = rhs.IsDedicated;
IsAutoRestart = rhs.IsAutoRestart;
IsFriendlyFirePermitted = rhs.IsFriendlyFirePermitted;
IsTeamChangingAllowed = rhs.IsTeamChangingAllowed;
IsPassworded = rhs.IsPassworded;
IsFreeWeapons = rhs.IsFreeWeapons;
IsLaddered = rhs.IsLaddered;
IsClanGame = rhs.IsClanGame;
IsClientTrusted = rhs.IsClientTrusted;
RemixTeams = rhs.RemixTeams;
CanRepairBuildings = rhs.CanRepairBuildings;
DriverIsAlwaysGunner = rhs.DriverIsAlwaysGunner;
SpawnWeapons = rhs.SpawnWeapons;
Password = rhs.Password;
GameTitle = rhs.GameTitle;
Motd = rhs.Motd;
#ifdef MULTIPLAYERDEMO
MapName.Format("C&C_Under.mix");
#else
MapName = rhs.MapName;
ModName = rhs.ModName;
#endif
Owner = rhs.Owner;
MaxPlayers = rhs.MaxPlayers;
TimeLimitMinutes = rhs.TimeLimitMinutes;
IntermissionTimeSeconds = rhs.IntermissionTimeSeconds;
VersionNumber = rhs.VersionNumber;
IpAddress = rhs.IpAddress;
Port = rhs.Port;
IniFilename = rhs.IniFilename;
RadarMode = rhs.RadarMode;
CurrentPlayers = rhs.CurrentPlayers;
IntermissionTimeRemaining = rhs.IntermissionTimeRemaining;
TimeRemainingSeconds = rhs.TimeRemainingSeconds;
MaximumWorldDistance = rhs.MaximumWorldDistance;
MinQualifyingTimeMinutes = rhs.MinQualifyingTimeMinutes;
for (int clanSlot = 0; clanSlot < MAX_CLAN_SLOTS; ++clanSlot) {
mClanSlots[clanSlot] = rhs.mClanSlots[clanSlot];
}
return (*this);
}
//-----------------------------------------------------------------------------
void cGameData::Reset_Game(bool is_reloaded)
{
WWDEBUG_SAY(("cGameData::Reset_Game\n"));
//
// Game_Reset is called on both C & S at the beginning of every game.
//
mWinnerID = -1;
IsIntermission.Set(false);
//
// 12/11/01
// This dialog flush was added to remove the purchase screen because it persists
// over reload.
//
if (GameModeManager::Find ("Combat")->Is_Active ()) {
if (GameModeManager::Find ("Menu")->Is_Active ()) {
GameModeManager::Find ("Menu")->Deactivate ();
} else {
DialogMgrClass::Flush_Dialogs ();
}
}
if (Get_Text_Display()) {
WWASSERT(Get_Text_Display() != NULL);
Get_Text_Display()->Flush();
}
if (!IS_MISSION) {
WWAudioClass::Get_Instance()->Create_Instant_Sound("Game_Start", Matrix3D(1));
}
//TSS092601 if ( !is_reloaded ) {
if ( !IS_MISSION || !is_reloaded ) {
cPlayerManager::Reset_Players();
}
//}
cTeamManager::Reset_Teams();
if (Is_Time_Limit()) {
Reset_Time_Remaining_Seconds();
if (cNetwork::I_Am_Server()) {
cGameDataUpdateEvent * p_event = new cGameDataUpdateEvent();
p_event->Init(-1);
}
}
if (cNetwork::I_Am_Server())
{
HostedGameNumber++;
}
}
//-----------------------------------------------------------------------------
void cGameData::Swap_Team_Sides(void)
{
//WWASSERT(Is_Team_Game());
WWASSERT(cNetwork::I_Am_Server());
for (
SLNode * player_node = cPlayerManager::Get_Player_Object_List()->Head();
player_node;
player_node = player_node->Next()) {
cPlayer * p_player = player_node->Data();
WWASSERT(p_player != NULL);
int team = p_player->Get_Player_Type();
WWASSERT(team == PLAYERTYPE_NOD || team == PLAYERTYPE_GDI);
int new_team = PLAYERTYPE_NOD;
if (team == PLAYERTYPE_NOD)
{
new_team = PLAYERTYPE_GDI;
}
else
{
new_team = PLAYERTYPE_NOD;
}
p_player->Set_Player_Type(new_team);
}
//
// Inform the players
//
//WideStringClass text;
//text.Format(L"_TEAMS_SWAPPED_!_");
WideStringClass text = TRANSLATE(IDS_MP_TEAMS_SWAPPED);
cScTextObj * p_text_obj = new cScTextObj();
p_text_obj->Init(text, TEXT_MESSAGE_PUBLIC, false, HOST_TEXT_SENDER, -1);
}
//-----------------------------------------------------------------------------
void cGameData::Remix_Team_Sides(void)
{
//WWASSERT(Is_Team_Game());
WWASSERT(cNetwork::I_Am_Server());
WWASSERT(IsClanGame.Is_False() && "Remix teams not allowed");
if (IsClanGame.Is_True()) {
return;
}
//
// Randomly choose a team for each player
//
for (
SLNode * player_node = cPlayerManager::Get_Player_Object_List()->Head();
player_node;
player_node = player_node->Next()) {
cPlayer * p_player = player_node->Data();
WWASSERT(p_player != NULL);
int new_team = PLAYERTYPE_NOD;
if (rand() % 2 == 0)
{
new_team = PLAYERTYPE_GDI;
}
else
{
new_team = PLAYERTYPE_NOD;
}
p_player->Set_Player_Type(new_team);
}
//
// Inform the players
//
//WideStringClass text;
//text.Format(L"_TEAMS_REMIXED_!_");
WideStringClass text = TRANSLATE(IDS_MP_TEAMS_REMIXED);
cScTextObj * p_text_obj = new cScTextObj();
p_text_obj->Init(text, TEXT_MESSAGE_PUBLIC, false, HOST_TEXT_SENDER, -1);
}
//-----------------------------------------------------------------------------
void cGameData::Rebalance_Team_Sides(void)
{
//WWASSERT(Is_Team_Game());
WWASSERT(cNetwork::I_Am_Server());
WWASSERT(IsClanGame.Is_False() && "Rebalance teams not allowed");
if (IsClanGame.Is_True()) {
return;
}
//
// Rebalance teams numerically
//
cTeam * p_nod = cTeamManager::Find_Team(PLAYERTYPE_NOD);
WWASSERT(p_nod != NULL);
cTeam * p_gdi = cTeamManager::Find_Team(PLAYERTYPE_GDI);
WWASSERT(p_gdi != NULL);
int move_count = 0;
int nod_tally = 0;
int gdi_tally = 0;
do
{
nod_tally = p_nod->Tally_Size();
gdi_tally = p_gdi->Tally_Size();
if (nod_tally > gdi_tally + 1)
{
cPlayer * p_player = cPlayerManager::Find_Team_Player(PLAYERTYPE_NOD);
WWASSERT(p_player != NULL);
p_player->Set_Player_Type(PLAYERTYPE_GDI);
move_count++;
}
else if (gdi_tally > nod_tally + 1)
{
cPlayer * p_player = cPlayerManager::Find_Team_Player(PLAYERTYPE_GDI);
WWASSERT(p_player != NULL);
p_player->Set_Player_Type(PLAYERTYPE_NOD);
move_count++;
}
} while (::abs(nod_tally - gdi_tally) > 1);
if (move_count > 0) {
//
// Inform the players
//
//WideStringClass text;
//text.Format(L"_TEAMS_REBALANCED_!_");
WideStringClass text = TRANSLATE(IDS_MP_TEAMS_REBALANCED);
cScTextObj * p_text_obj = new cScTextObj();
p_text_obj->Init(text, TEXT_MESSAGE_PUBLIC, false, HOST_TEXT_SENDER, -1);
}
}
//-----------------------------------------------------------------------------
void cGameData::Set_Ip_And_Port(void)
{
/*
SOCKADDR_IN local_address;
bool retcode = cNetUtil::Get_Local_Address(&local_address);
WWASSERT(retcode == true);
//
// hack
//
if (g_ip_override != INADDR_NONE) {
local_address.sin_addr.s_addr = g_ip_override;
}
Set_Ip_Address(local_address.sin_addr.s_addr);
*/
ULONG ip = 0;
if (cGameSpyAdmin::Get_Is_Server_Gamespy_Listed()) {
ip = cUserOptions::PreferredGameSpyNic.Get();
} else {
ip = cUserOptions::PreferredLanNic.Get();
}
if (g_ip_override != INADDR_NONE) {
ip = g_ip_override;
}
//
// IP is set automatically in WOL unless there is an IP override and a port overrride.
//
if (GameModeManager::Find("WOL")->Is_Active()) {
if (g_ip_override == INADDR_NONE || WOLNATInterface.Get_Force_Port() == 0) {
unsigned long temp = FirewallHelper.Get_Local_Address();
if (temp) {
//ip = temp;
ip = ::ntohl(temp);
}
}
}
//WWASSERT(ip != 0);
Set_Ip_Address(ip);
}
//-----------------------------------------------------------------------------
//
// A convenience function...
//
bool cGameData::Set_Generic_Num(int generic_num,
int lower_bound, int upper_bound, int & set_num)
{
if (generic_num >= lower_bound && generic_num <= upper_bound) {
set_num = generic_num;
return true;
} else {
return false;
}
}
//-----------------------------------------------------------------------------
bool cGameData::Set_Max_Players(int max)
{
return Set_Generic_Num(max, 0, MAX_PLAYERS, MaxPlayers);
}
//-----------------------------------------------------------------------------
bool cGameData::Set_Time_Limit_Minutes(int time_limit_minutes)
{
return Set_Generic_Num(time_limit_minutes, 0, MAX_TIME_LIMIT, TimeLimitMinutes);
}
//-----------------------------------------------------------------------------
void cGameData::Set_Radar_Mode(RadarModeEnum mode)
{
RadarMode = mode;
}
//-----------------------------------------------------------------------------
void cGameData::Set_Intermission_Time_Seconds(int time)
{
WWASSERT(time >= 0);
IntermissionTimeSeconds = time;
}
//-----------------------------------------------------------------------------
void cGameData::Set_Motd(const WCHAR * motd)
{
WWASSERT(motd != NULL);
Motd = motd;
}
//-----------------------------------------------------------------------------
void cGameData::Set_Mod_Name(const StringClass &mod_name)
{
ModName = mod_name;
ModPackageMgrClass::Set_Current_Package (ModName);
return ;
}
//-----------------------------------------------------------------------------
void cGameData::Set_Map_Name(const StringClass & map_name)
{
#ifdef MULTIPLAYERDEMO
MapName.Format("C&C_Under.mix");
#else
MapName = map_name;
#endif
}
//-----------------------------------------------------------------------------
bool cGameData::Set_Current_Players(int current)
{
return Set_Generic_Num(current, 0, MAX_PLAYERS, CurrentPlayers);
}
//-----------------------------------------------------------------------------
void cGameData::Set_Owner(WideStringClass & owner)
{
Owner = owner;
}
//-----------------------------------------------------------------------------
void cGameData::Set_Ip_Address(ULONG ip_address)
{
IpAddress = ip_address;
}
//-----------------------------------------------------------------------------
void cGameData::Set_Port(int port)
{
WWASSERT(port >= MIN_SERVER_PORT && port <= MAX_SERVER_PORT);
Port = port;
}
//-----------------------------------------------------------------------------
bool cGameData::Is_Limited(void) const
{
return Is_Time_Limit();
}
//-----------------------------------------------------------------------------
bool cGameData::Is_Map_Valid(char **out_filename)
{
bool map_exists = false;
if (ModName.Is_Empty () == false) {
if (out_filename) {
*out_filename = ModName.Peek_Buffer();
}
map_exists = cMiscUtil::File_Exists (ModName);
} else {
if (out_filename) {
*out_filename = MapName.Peek_Buffer();
}
map_exists = cMiscUtil::File_Exists (MapName);
}
return(map_exists);
}
#define PRINT_CONFIG_ERROR ConsoleBox.Print("File %s - Error:\r\n\t ", Get_Ini_Filename());
//-----------------------------------------------------------------------------
bool cGameData::Is_Valid_Settings(WideStringClass& outMsg, bool check_as_server)
{
if (MapName.Is_Empty()) {
//cHelpText::Set(TRANSLATION(IDS_MP_NO_LEVEL_SELECTED));
Debug_Say(( "cGameData::No level file selected.\n" ));
PRINT_CONFIG_ERROR;
ConsoleBox.Print("No initial level file selected\n\n");
outMsg = TRANSLATE(IDS_HOPTERR_NO_LEVEL);
return false;
} else {
//
// Test to see whether or not the map exists
//
char *filename = NULL;
if (!Is_Map_Valid(&filename)) {
Debug_Say(("cGameData::Is_Valid_Settings: Level \"%s\" not found\n", filename));
PRINT_CONFIG_ERROR;
ConsoleBox.Print("Map file '%s' not found\n\n", filename);
outMsg.Format(TRANSLATE(IDS_HOPTERR_MAP_NOTFOUND), filename);
return(false);
}
}
if (IsPassworded.Is_True() && Password.Get_Length () == 0) {
//cHelpText::Set(TRANSLATION(IDS_MP_BLANK_PASSWORD_ILLEGAL));
Debug_Say(( "cGameData::Is_Valid_Settings: You can not use a blank password.\n" ));
PRINT_CONFIG_ERROR;
ConsoleBox.Print("Blank passwords are not allowed\n\n");
outMsg = TRANSLATE(IDS_HOPTERR_BLANK_PASS);
return false;
}
#ifndef FREEDEDICATEDSERVER
if (GameModeManager::Find("WOL")->Is_Active()) {
#endif //FREEDEDICATEDSERVER
if (IsPassworded.Is_True() && Is_QuickMatch_Server()) {
Debug_Say(("cGameData::Is_Valid_Settings: Quickmatch can not have passwords.\n" ));
PRINT_CONFIG_ERROR;
ConsoleBox.Print("A password cannot be used on a Quickmatch server\n\n");
outMsg = TRANSLATE(IDS_HOPTERR_QM_HASPASS);
return false;
}
if (Is_QuickMatch_Server() && IsLaddered.Is_False()) {
Debug_Say(("cGameData::Is_Valid_Settings: Quickmatch must be laddered.\n" ));
PRINT_CONFIG_ERROR;
ConsoleBox.Print("A Quickmatch server must also be laddered\n\n");
outMsg = TRANSLATE(IDS_HOPTERR_QM_NOLADDER);
return false;
}
if (Is_QuickMatch_Server() && IsClanGame.Is_True()) {
Debug_Say(("cGameData::Is_Valid_Settings: Quickmatch cannot be clanned.\n" ));
PRINT_CONFIG_ERROR;
ConsoleBox.Print("Clans are not allowed in a quickmatch server\n\n");
outMsg = TRANSLATE(IDS_HOPTERR_QM_NOCLANS);
return false;
}
if (IsLaddered.Is_True() && IsTeamChangingAllowed.Is_True()) {
PRINT_CONFIG_ERROR;
ConsoleBox.Print("Team changing not allowed on a laddered server\n\n");
outMsg = TRANSLATE(IDS_HOPTERR_NO_TEAMCHANGE);
return false;
}
if (IsClanGame.Is_True() && (IsTeamChangingAllowed.Is_True() || RemixTeams.Is_True())) {
PRINT_CONFIG_ERROR;
ConsoleBox.Print("Team changing or Team Remix not allowed on a clan game server.\n");
outMsg = "Team changing or Team Remix not allowed on a clan game server."; //TRANSLATE(IDS_HOPTERR_NO_TEAMCHANGE);
return false;
}
#ifndef FREEDEDICATEDSERVER
}
#endif //FREEDEDICATEDSERVER
#ifdef FREEDEDICATEDSERVER
if (Get_Max_Players() == 0 && ServerSettingsClass::Get_Game_Mode() !=
ServerSettingsClass::MODE_WOL) {
#else
if (Get_Max_Players() == 0) {
#endif
PRINT_CONFIG_ERROR;
ConsoleBox.Print("Max player count must be greater than 0\n\n");
outMsg = TRANSLATE(IDS_HOPTERR_MAXPLAYER_0);
return(false);
}
// Check server only parameters
if (check_as_server || ConsoleBox.Is_Exclusive()) {
if (Get_Max_Players() > NetworkObjectClass::MAX_CLIENT_COUNT-1) {
PRINT_CONFIG_ERROR;
ConsoleBox.Print("Max player count must be less than %d\n\n", NetworkObjectClass::MAX_CLIENT_COUNT);
outMsg.Format(TRANSLATE(IDS_HOPTERR_MAXPLAYER_TOOBIG), NetworkObjectClass::MAX_CLIENT_COUNT);
return(false);
}
if (DoMapsLoop && Get_Map_Cycle(0).Get_Length() == 0) {
PRINT_CONFIG_ERROR;
ConsoleBox.Print("Map cycling is enabled but there are no maps in the cycle\n\n");
outMsg = TRANSLATE(IDS_HOPTERR_NO_MAPCYCLE);
return(false);
}
/*
** Make sure all the maps exist.
*/
if (DoMapsLoop && ModName.Is_Empty ()) {
for (int i=0 ; i MAX_MOTD_LENGTH) {
PRINT_CONFIG_ERROR;
ConsoleBox.Print("Message of the day cannot exceed %d characters\n\n", MAX_MOTD_LENGTH);
outMsg.Format(TRANSLATE(IDS_HOPTERR_MOTD_TOOBIG), MAX_MOTD_LENGTH);
return false;
}
/*
** Check the game title for length. The buffers are pretty much all 256 bytes but 100 seems a more reasonable figure.
*/
if (GameTitle.Get_Length() > 100) {
PRINT_CONFIG_ERROR;
ConsoleBox.Print("Game title cannot exceed %d characters\n\n", 100);
outMsg.Format(TRANSLATE(IDS_HOPTERR_TITLE_TOOBIG), 100);
return false;
}
}
return true; // it's valid !
}
//-----------------------------------------------------------------------------
//
// Server options are exported in 2 tiers. Tier 1 is the basic parameters
// that show up in the list of games. Tier 2 is the remainder of the full
// set of server settings.
//
void cGameData::Export_Tier_1_Data(cPacket & packet)
{
packet.Add(IpAddress);
packet.Add_Wide_Terminated_String(Owner);
packet.Add_Wide_Terminated_String(GameTitle, true);
packet.Add(Port);
packet.Add(CurrentPlayers);
packet.Add(MaxPlayers);
packet.Add(VersionNumber);
//
// Send the individual CRC's (for internal use)
//
packet.Add(cNetwork::Get_Exe_CRC ());
packet.Add(cNetwork::Get_Strings_CRC ());
packet.Add(IsDedicated.Get());
packet.Add(IsTeamChangingAllowed.Get());
packet.Add(IsPassworded.Get());
packet.Add(IsLaddered.Get());
packet.Add(IsClanGame.Get());
#ifndef MULTIPLAYERDEMO
packet.Add(::CRC_Stringi(MapName));
packet.Add(::CRC_Stringi(ModName));
#endif // MULTIPLAYERDEMO
}
//-----------------------------------------------------------------------------
void cGameData::Import_Tier_1_Data(cPacket & packet)
{
ULONG ip_address = packet.Get(ip_address);
Set_Ip_Address(ip_address);
WideStringClass owner;
packet.Get_Wide_Terminated_String(owner.Get_Buffer(256), 256);
Set_Owner(owner);
WideStringClass title;
packet.Get_Wide_Terminated_String(title.Get_Buffer(256), 256, true);
Set_Game_Title(title);
int i_placeholder;
bool b_placeholder;
Set_Port( packet.Get(i_placeholder));
Set_Current_Players( packet.Get(i_placeholder));
Set_Max_Players( packet.Get(i_placeholder));
Set_Version_Number( packet.Get(i_placeholder));
//
// Compare the individual CRC's against our own
//
DoExeVersionsMatch = (packet.Get(i_placeholder) == cNetwork::Get_Exe_CRC ());
DoStringVersionsMatch = (packet.Get(i_placeholder) == cNetwork::Get_Strings_CRC ());
IsDedicated.Set( packet.Get(b_placeholder));
IsTeamChangingAllowed.Set( packet.Get(b_placeholder));
IsPassworded.Set( packet.Get(b_placeholder));
IsLaddered.Set( packet.Get(b_placeholder));
IsClanGame.Set( packet.Get(b_placeholder));
#ifndef MULTIPLAYERDEMO
//
// Get the CRC of the map and the mod
//
ULONG map_name_crc = packet.Get(map_name_crc);
ULONG mod_name_crc = packet.Get(mod_name_crc);
//
// Determine what the name of the mod and the map are from their CRC's
//
StringClass mod_name(0,true);
StringClass map_name(0,true);
if (ModPackageMgrClass::Get_Mod_Map_Name_From_CRC (mod_name_crc, map_name_crc, &mod_name, &map_name)) {
Set_Mod_Name (mod_name);
Set_Map_Name (map_name);
} else {
ModName = L"";
MapName = L"";
}
#endif // MULTIPLAYERDEMO
return ;
}
//-----------------------------------------------------------------------------
bool cGameData::Does_Map_Exist (void)
{
bool retval = true;
//
// If the map and mod names are empty then it is due to the fact
// that we couldn't find the map and/or mod when we looked
//
if (ModName.Is_Empty () && MapName.Is_Empty ()) {
retval = false;
}
return retval;
}
//-----------------------------------------------------------------------------
void cGameData::Import_Tier_1_Data(const WOLGameInfo& gameInfo)
{
Set_Map_Name(gameInfo.MapName());
Set_Mod_Name(gameInfo.ModName());
WideStringClass title(0, true);
title.Convert_From(gameInfo.Title());
Set_Game_Title(title);
Set_Max_Players(gameInfo.MaxPlayers());
Set_Current_Players(gameInfo.NumPlayers());
// Set game flags
IsDedicated.Set(gameInfo.IsDedicated());
IsPassworded.Set(gameInfo.IsPassworded());
IsLaddered.Set(gameInfo.IsLaddered());
IsFriendlyFirePermitted.Set(gameInfo.IsFriendlyFire());
IsFreeWeapons.Set(gameInfo.IsFreeWeapons());
RemixTeams.Set(gameInfo.IsTeamRemix());
IsTeamChangingAllowed.Set(gameInfo.IsTeamChange());
IsClanGame.Set(gameInfo.IsClanGame());
IsQuickMatchServer = gameInfo.IsQuickmatch();
CanRepairBuildings.Set(gameInfo.IsRepairBuildings());
DriverIsAlwaysGunner.Set(gameInfo.IsDriverGunner());
SpawnWeapons.Set(gameInfo.IsSpawnWeapons());
Clear_Clans();
mClanSlots[0] = gameInfo.ClanID1();
mClanSlots[1] = gameInfo.ClanID2();
}
//-----------------------------------------------------------------------------
void cGameData::Export_Tier_2_Data(cPacket & packet)
{
packet.Add(TimeLimitMinutes);
packet.Add((int) RadarMode);
packet.Add(IntermissionTimeSeconds);
packet.Add(MinQualifyingTimeMinutes);
packet.Add(IsFriendlyFirePermitted.Get());
packet.Add(IsFreeWeapons.Get());
packet.Add(IsClientTrusted.Get());
packet.Add(RemixTeams.Get());
if (Is_Cnc()) {
packet.Add(CanRepairBuildings.Get());
packet.Add(DriverIsAlwaysGunner.Get());
packet.Add(SpawnWeapons.Get());
}
packet.Add_Wide_Terminated_String(Motd, true);
}
//-----------------------------------------------------------------------------
void cGameData::Import_Tier_2_Data(cPacket & packet)
{
int i_placeholder = 0;
bool b_placeholder = false;
Set_Time_Limit_Minutes( packet.Get(i_placeholder));
Set_Radar_Mode((RadarModeEnum) packet.Get(i_placeholder));
Set_Intermission_Time_Seconds( packet.Get(i_placeholder));
Set_Min_Qualifying_Time_Minutes( packet.Get(i_placeholder));
IsFriendlyFirePermitted.Set( packet.Get(b_placeholder));
IsFreeWeapons.Set( packet.Get(b_placeholder));
IsClientTrusted.Set( packet.Get(b_placeholder));
RemixTeams.Set( packet.Get(b_placeholder));
if (Is_Cnc()) {
CanRepairBuildings.Set( packet.Get(b_placeholder));
DriverIsAlwaysGunner.Set( packet.Get(b_placeholder));
SpawnWeapons.Set( packet.Get(b_placeholder));
}
WideStringClass motd;
packet.Get_Wide_Terminated_String(motd.Get_Buffer(MAX_MOTD_LENGTH), MAX_MOTD_LENGTH, true);
Set_Motd(motd);
}
//-----------------------------------------------------------------------------
void cGameData::Load_From_Server_Config(LPCSTR config_file)
{
WWASSERT(config_file != NULL);
WWASSERT(cMiscUtil::Is_String_Different(config_file, ""));
INIClass * p_ini = Get_INI(config_file);
StringClass full_filename(config_file, true);
if (p_ini == NULL) {
full_filename.Format("data\\%s", config_file);
FILE * file = fopen(full_filename, "w");
fclose(file);
p_ini = Get_INI(config_file);
}
WWASSERT(p_ini != NULL);
LastServerConfigModTime = Get_Config_File_Mod_Time();
char map_name[MAX_MAPNAME_SIZE];
char mod_name[MAX_MAPNAME_SIZE];
char string8[256];
bool b;
int i;
//float f;
//p_ini->Get_String( INI_SECTION_NAME, "Password", Get_Password(), password, sizeof(password));
//Set_Password(password);
p_ini->Get_String( INI_SECTION_NAME, "MapName", "", map_name, sizeof(map_name));
StringClass map(map_name,true);
Set_Map_Name(map);
p_ini->Get_String( INI_SECTION_NAME, "ModName", "", mod_name, sizeof(mod_name));
StringClass mod(mod_name,true);
Set_Mod_Name(mod);
i = p_ini->Get_Int( INI_SECTION_NAME, "TimeLimitMinutes", Get_Time_Limit_Minutes());
Set_Time_Limit_Minutes(i);
i = p_ini->Get_Int( INI_SECTION_NAME, "RadarMode", Get_Radar_Mode());
Set_Radar_Mode((RadarModeEnum) i);
//i = p_ini->Get_Int( INI_SECTION_NAME, "IntermissionTimeSeconds", Get_Intermission_Time_Seconds());
//Set_Intermission_Time_Seconds(i);
#ifndef FREEDEDICATEDSERVER
i = p_ini->Get_Int( INI_SECTION_NAME, "Port", Get_Port());
Set_Port(i);
b = p_ini->Get_Bool( INI_SECTION_NAME, "IsDedicated", IsDedicated.Get());
IsDedicated.Set(b);
#else ////FREEDEDICATEDSERVER
IsDedicated.Set(true);
#endif //FREEDEDICATEDSERVER
b = p_ini->Get_Bool( INI_SECTION_NAME, "IsAutoRestart", IsAutoRestart.Get());
IsAutoRestart.Set(b);
b = p_ini->Get_Bool( INI_SECTION_NAME, "IsPassworded", IsPassworded.Get());
IsPassworded.Set(b);
b = p_ini->Get_Bool( INI_SECTION_NAME, "IsQuickMatch", IsQuickMatchServer.Get());
IsQuickMatchServer.Set(b);
b = p_ini->Get_Bool( INI_SECTION_NAME, "IsLaddered", IsLaddered.Get());
#ifndef FREEDEDICATEDSERVER
b = ((IsQuickMatchServer.Get() == true) ? true : b);
#endif //FREEDEDICATEDSERVER
IsLaddered.Set(b);
b = p_ini->Get_Bool( INI_SECTION_NAME, "IsClanGame", IsClanGame.Get());
#ifndef FREEDEDICATEDSERVER
b = ((IsQuickMatchServer.Get() == true) ? false : b);
#endif /FREEDEDICATEDSERVER
IsClanGame.Set(b);
b = p_ini->Get_Bool( INI_SECTION_NAME, "RemixTeams", RemixTeams.Get());
RemixTeams.Set(b);
b = p_ini->Get_Bool( INI_SECTION_NAME, "CanRepairBuildings", CanRepairBuildings.Get());
CanRepairBuildings.Set(b);
b = p_ini->Get_Bool( INI_SECTION_NAME, "DriverIsAlwaysGunner", DriverIsAlwaysGunner.Get());
DriverIsAlwaysGunner.Set(b);
b = p_ini->Get_Bool( INI_SECTION_NAME, "SpawnWeapons", SpawnWeapons.Get());
SpawnWeapons.Set(b);
//
// Disguise "IsClientTrusted" with something that sounds like you need it but
// that doesn't scream "hack me"
//
//b = p_ini->Get_Bool( INI_SECTION_NAME, "IsClientTrusted", IsClientTrusted.Get());
b = p_ini->Get_Bool( INI_SECTION_NAME, "UseLagReduction", IsClientTrusted.Get());
IsClientTrusted.Set(b);
// Read the 8 bit versions of the strings first and use those as defaults.
p_ini->Get_String(INI_SECTION_NAME, "bGameTitle", "", string8, sizeof(string8));
Set_Game_Title(WideStringClass(string8, true));
p_ini->Get_String(INI_SECTION_NAME, "bMotd", "", string8, sizeof(string8));
Set_Motd(WideStringClass(string8, true));
p_ini->Get_String(INI_SECTION_NAME, "bPassword", "", string8, sizeof(string8));
Set_Password(WideStringClass(string8, true));
p_ini->Get_String(INI_SECTION_NAME, "bConfigName", "", string8, sizeof(string8));
Set_Settings_Description(WideStringClass(string8, true));
// Now read the 16 bit versions as overrides.
WideStringClass wide_string(Get_Game_Title(), true);
p_ini->Get_Wide_String(wide_string, INI_SECTION_NAME, "wGameTitle", wide_string.Peek_Buffer());
Set_Game_Title(wide_string);
wide_string = Get_Password();
p_ini->Get_Wide_String(wide_string, INI_SECTION_NAME, "wPassword", wide_string.Peek_Buffer());
Set_Password(wide_string);
wide_string = Get_Motd();
p_ini->Get_Wide_String(wide_string, INI_SECTION_NAME, "wMotd", wide_string.Peek_Buffer());
Set_Motd(wide_string);
wide_string = Get_Settings_Description();
p_ini->Get_Wide_String(wide_string, INI_SECTION_NAME, "wConfigName", wide_string.Peek_Buffer());
Set_Settings_Description(wide_string);
for (int j = 0; j < MAX_MAPS; j++) {
StringClass item_name(0,true);
item_name.Format("MapName%02d", j);
p_ini->Get_String( INI_SECTION_NAME, item_name, "", map_name, sizeof(map_name));
StringClass map(map_name,true);
MapCycle[j] = map;
}
//char motd[2 * MAX_MOTD_LENGTH];
//p_ini->Get_String( INI_SECTION_NAME, "Motd", "", motd, sizeof(motd));
//if (::strlen(motd) > 0) {
// Motd.Convert_From(motd);
//}
Release_INI(p_ini);
}
//-----------------------------------------------------------------------------
void cGameData::Save_To_Server_Config(LPCSTR config_file)
{
WWASSERT(config_file != NULL);
WWASSERT(cMiscUtil::Is_String_Different(config_file, ""));
INIClass * p_ini = Get_INI(config_file);
WWASSERT(p_ini != NULL);
//
// We can't overwrite entries, so clear them out first.
//
p_ini->Clear(INI_SECTION_NAME);
p_ini->Put_Wide_String( INI_SECTION_NAME, "wConfigName", Get_Settings_Description());
p_ini->Put_Wide_String( INI_SECTION_NAME, "wPassword", Get_Password());
p_ini->Put_String( INI_SECTION_NAME, "MapName", Get_Map_Name());
p_ini->Put_String( INI_SECTION_NAME, "ModName", Get_Mod_Name());
p_ini->Put_Int( INI_SECTION_NAME, "TimeLimitMinutes", Get_Time_Limit_Minutes());
p_ini->Put_Int( INI_SECTION_NAME, "RadarMode", Get_Radar_Mode());
//p_ini->Put_Int( INI_SECTION_NAME, "IntermissionTimeSeconds", Get_Intermission_Time_Seconds());
p_ini->Put_Int( INI_SECTION_NAME, "Port", Get_Port());
p_ini->Put_Bool( INI_SECTION_NAME, "IsDedicated", IsDedicated.Get());
p_ini->Put_Bool( INI_SECTION_NAME, "IsAutoRestart", IsAutoRestart.Get());
p_ini->Put_Bool( INI_SECTION_NAME, "IsPassworded", IsPassworded.Get());
p_ini->Put_Bool( INI_SECTION_NAME, "IsQuickMatch", IsQuickMatchServer.Get());
p_ini->Put_Bool( INI_SECTION_NAME, "IsLaddered", IsLaddered.Get());
p_ini->Put_Bool( INI_SECTION_NAME, "IsClanGame", IsClanGame.Get());
p_ini->Put_Bool( INI_SECTION_NAME, "RemixTeams", RemixTeams.Get());
p_ini->Put_Bool( INI_SECTION_NAME, "CanRepairBuildings", CanRepairBuildings.Get());
p_ini->Put_Bool( INI_SECTION_NAME, "DriverIsAlwaysGunner", DriverIsAlwaysGunner.Get());
p_ini->Put_Bool( INI_SECTION_NAME, "SpawnWeapons", SpawnWeapons.Get());
//p_ini->Put_Bool( INI_SECTION_NAME, "IsClientTrusted", IsClientTrusted.Get());
p_ini->Put_Bool( INI_SECTION_NAME, "UseLagReduction", IsClientTrusted.Get());
p_ini->Put_Wide_String( INI_SECTION_NAME, "wGameTitle", Get_Game_Title());
p_ini->Put_Wide_String( INI_SECTION_NAME, "wMOTD", Get_Motd());
#if (0)
// Save out 8 bit string versions too.
StringClass string8(256, true);
WideStringClass(Get_Game_Title(), true).Convert_To(string8);
p_ini->Put_String( INI_SECTION_NAME, "bGameTitle", string8);
WideStringClass(Get_Motd(), true).Convert_To(string8);
p_ini->Put_String( INI_SECTION_NAME, "bMOTD", string8);
WideStringClass(Get_Password(), true).Convert_To(string8);
p_ini->Put_String( INI_SECTION_NAME, "bPassword", string8);
#endif //(0)
for (int j = 0; j < MAX_MAPS; j++) {
StringClass item_name(0,true);
item_name.Format("MapName%02d", j);
p_ini->Put_String( INI_SECTION_NAME, item_name, MapCycle[j]);
}
if (!Motd.Is_Empty()) {
StringClass motd;
Motd.Convert_To(motd);
p_ini->Put_String( INI_SECTION_NAME, "Motd", motd.Peek_Buffer());
}
Save_INI(p_ini, config_file);
Release_INI(p_ini);
}
//-----------------------------------------------------------------------------
void cGameData::Soldier_Added(SoldierGameObj * p_soldier)
{
WWASSERT(p_soldier != NULL);
if (IsFreeWeapons.Is_True() &&
p_soldier->Get_Player_Type() != PLAYERTYPE_NEUTRAL) {
p_soldier->Give_All_Weapons();
int weapon = 0;
if (p_soldier->Is_Human_Controlled()) {
weapon = 1;
} else {
weapon = 1 + rand() % 7;
}
WWASSERT(p_soldier->Get_Weapon_Bag() != NULL);
p_soldier->Get_Weapon_Bag()->Select_Key_Number(weapon);
}
}
//-----------------------------------------------------------------------------
void cGameData::Begin_Intermission(void)
{
// If we are transitioning from one game to another we must first end the
// previous game.
GameModeClass* gameMode = GameModeManager::Find("WOL");
if (gameMode && gameMode->Is_Active()) {
WolGameModeClass* wolGame = reinterpret_cast(gameMode);
wolGame->End_Game();
}
IsIntermission.Set(true);
IntermissionTimeRemaining = Get_Intermission_Time_Seconds();
//
// Display a dialog with the win information on it
//
if (!ConsoleBox.Is_Exclusive()) {
START_DIALOG (CNCWinScreenMenuClass);
}
return ;
}
//-----------------------------------------------------------------------------
void cGameData::Set_Maximum_World_Distance(float distance)
{
//
// You will typically get this assert if you don't have the level file.
//
WWASSERT(distance > 0);
MaximumWorldDistance = distance;
}
//-----------------------------------------------------------------------------
void cGameData::Set_Min_Qualifying_Time_Minutes(int minutes)
{
WWASSERT(minutes >= 0);
MinQualifyingTimeMinutes = minutes;
}
//-----------------------------------------------------------------------------
int cGameData::Get_Duration_Seconds(void)
{
return (int)(TimeLimitMinutes * 60 - TimeRemainingSeconds);
}
//-----------------------------------------------------------------------------
WideStringClass cGameData::Get_Team_Word(void)
{
//
// In clan games, the work "Clan" is used instead of "Team"
//
if (IsClanGame.Is_True()) {
return TRANSLATION(IDS_MP_CLAN);
} else {
return TRANSLATION(IDS_MP_TEAM);
}
}
//-----------------------------------------------------------------------------
void cGameData::Set_Time_Remaining_Seconds(float time_remaining_seconds)
{
WWASSERT(time_remaining_seconds >= 0);
TimeRemainingSeconds = time_remaining_seconds;
}
//-----------------------------------------------------------------------------
void cGameData::Reset_Time_Remaining_Seconds(void)
{
TimeRemainingSeconds = 60 * TimeLimitMinutes;
}
//-----------------------------------------------------------------------------
float cGameData::Get_Time_Remaining_Seconds(void)
{
return TimeRemainingSeconds;
}
//-----------------------------------------------------------------------------
bool cGameData::Is_Valid_Player_Type(int player_type)
{
bool is_valid = true;
if (!Is_Single_Player()) {
//if (player_type == PLAYERTYPE_RENEGADE &&
// Is_Team_Game()) {
if (player_type == PLAYERTYPE_RENEGADE) {
is_valid = false;
}
/*
if ((player_type == PLAYERTYPE_NOD || player_type == PLAYERTYPE_GDI) &&
!Is_Team_Game()) {
is_valid = false;
}
*/
}
return is_valid;
}
//-----------------------------------------------------------------------------
int cGameData::Choose_Player_Type(cPlayer* player, int team_choice, bool is_grunt)
{
if (IsClanGame.Is_True() && !is_grunt) {
// Bots are assigned to the smallest team.
if (player && !player->Is_Human()) {
int team = Choose_Smallest_Team();
WWDEBUG_SAY(("CLANS: Bot '%S' assigned to smallest team (%d)\n",
(const WCHAR*)player->Get_Name(), team));
return team;
}
// If there are other players from the same clan then team up them.
// Otherwise we must be the first of our clan so select the next available team.
cPlayer* clanMate = cPlayerManager::Find_Clan_Mate(player);
if (clanMate) {
int team = clanMate->Get_Player_Type();
WWDEBUG_SAY(("CLANS: Player '%S' assigned to team with clanmates (%d)\n",
(const WCHAR*)player->Get_Name(), team));
return team;
} else {
int team = Choose_Available_Team(team_choice);
WWDEBUG_SAY(("CLANS: Player '%S' assigned to available team (%d)\n",
(const WCHAR*)player->Get_Name(), team));
return team;
}
WWDEBUG_SAY(("CLANS: ERROR - Player not assigned to team\n"));
WWASSERT("ERROR: Player not assigned to team");
} else {
if (PLAYERTYPE_RENEGADE == team_choice || IsTeamChangingAllowed.Is_False()) {
return Choose_Smallest_Team();
}
}
return team_choice;
}
int cGameData::Choose_Available_Team(int preference)
{
// If the perferred team is available then use it.
if (preference != -1) {
cTeam* team = cTeamManager::Find_Team(preference);
if (team && (team->Tally_Size() == 0)) {
return team->Get_Id();
}
}
// Find the next available team
cTeam* team = cTeamManager::Find_Empty_Team();
if (team) {
return team->Get_Id();
}
WWDEBUG_SAY(("ERROR: No available team found\n"));
WWASSERT("ERROR: No available team found");
return -1;
}
//-----------------------------------------------------------------------------
int cGameData::Choose_Smallest_Team(void)
{
//WWASSERT(Is_Team_Game());
cTeam * p_team_0 = cTeamManager::Find_Team(0);
WWASSERT(p_team_0 != NULL);
cTeam * p_team_1 = cTeamManager::Find_Team(1);
WWASSERT(p_team_1 != NULL);
int team = -999;
int size_team_0 = p_team_0->Tally_Size();
int size_team_1 = p_team_1->Tally_Size();
if (size_team_0 < size_team_1) {
team = p_team_0->Get_Id();
} else if (size_team_1 < size_team_0) {
team = p_team_1->Get_Id();
} else {
//
// Both teams are equal in size, so choose the losing team.
//
if (p_team_0->Get_Score() < p_team_1->Get_Score()) {
team = p_team_0->Get_Id();
} else if (p_team_0->Get_Score() > p_team_1->Get_Score()) {
team = p_team_1->Get_Id();
} else {
//
// Both teams have the same score. Choose Randomly.
//
if (rand() % 2 == 0) {
team = p_team_0->Get_Id();
} else {
team = p_team_1->Get_Id();
}
}
}
WWASSERT(team != -999);
return team;
}
//-----------------------------------------------------------------------------
bool cGameData::Is_Game_Over(void)
{
WWASSERT(cNetwork::I_Am_Server());
bool is_game_over = false;
//
// Games may be manually ended with the "gameover" command.
//
if (IsManualRestart) {
IsManualRestart = false;
WinType = WIN_TYPE_FORCED;
is_game_over = true;
}
//
// Games may be ended with the "quit" command.
//
if (!is_game_over && IsManualExit) {
WinType = WIN_TYPE_FORCED;
is_game_over = true;
}
//
// Time expired?
//
if (!is_game_over && Is_Time_Limit() && TimeRemainingSeconds <= WWMATH_EPSILON) {
WinType = WIN_TYPE_TIME;
is_game_over = true;
}
//
// If game time has passed but gameplay now pends, end the game
//
if (!is_game_over && Get_Game_Duration_S() > 0 && !Is_Gameplay_Permitted()) {
WinType = WIN_TYPE_FORCED;
is_game_over = true;
}
/*
//
// THIS NEEDS REFINEMENT
//
// The following test will end a non-mission game when your opponents
// abandon you. To determine whether any combat has occurred we simply
// examine the IsBloodShed flag.
//
if (!Is_Mission() && IsBloodShed.Is_True() &&
((Is_Team_Game() && cTeamManager::Get_Living_Count() <= 1) ||
(!Is_Team_Game() && cPlayerManager::Get_Living_Count() <= 1))) {
return true;
}
*/
if (is_game_over)
{
TimeRemainingSeconds = 0;
}
return is_game_over;
}
//-----------------------------------------------------------------------------
bool cGameData::Has_Config_File_Changed(void)
{
unsigned long mod_time = Get_Config_File_Mod_Time();
if (LastServerConfigModTime != mod_time) {
return(true);
}
return(false);
}
//-----------------------------------------------------------------------------
unsigned long cGameData::Get_Config_File_Mod_Time(void)
{
StringClass full_filename(IniFilename, true);
RawFileClass file(full_filename);
if (!file.Is_Available()) {
full_filename.Format("data\\%s", IniFilename);
file.Set_Name(full_filename);
}
if (file.Is_Available()) {
file.Open();
unsigned long mod_time = file.Get_Date_Time();
file.Close();
return(mod_time);
}
return(0);
}
//-----------------------------------------------------------------------------
void cGameData::Game_Over_Processing(void)
{
WWDEBUG_SAY(("cGameData::Game_Over_Processing\n"));
WWASSERT(cNetwork::I_Am_Server());
int winning_team = cTeamManager::Get_Leaders_Id();
//
// Reload the game settings if they changed on disk.
//
if (Has_Config_File_Changed()) {
//
// Verify that the new settings are good.
//
cGameDataCnc *test_game_settings = (cGameDataCnc*) Create_Game_Of_Type(cGameData::GAME_TYPE_CNC);
WWASSERT(test_game_settings != NULL);
bool ok = false;
if (test_game_settings) {
test_game_settings->Set_Ini_Filename(IniFilename);
test_game_settings->Load_From_Server_Config();
WideStringClass outMsg;
ok = test_game_settings->Is_Valid_Settings(outMsg, true);
delete test_game_settings;
}
//
// If they are good settings then reload them.
//
if (ok) {
ConsoleBox.Print("Game settings changed - realoading settings\n");
Load_From_Server_Config();
}
}
Rotate_Map();
cPlayerManager::Increment_Player_Times();
//
// Compute the game duration
//
DWORD duration_s = (int)((TIMEGETTIME() - GameStartTimeMs) / 1000.0f);
Set_Game_Duration_S(duration_s);
//
// Record the MVP name and track the number of consecutives
//
WideStringClass mvp_name = cPlayerManager::Determine_Mvp_Name();
if (mvp_name.Compare_No_Case(MvpName)) {
Set_Mvp_Count(1);
Set_Mvp_Name(cPlayerManager::Determine_Mvp_Name());
} else {
Increment_Mvp_Count();
}
mWinnerID = winning_team;
cWinEvent * p_win = new cWinEvent;
p_win->Init(mWinnerID, PLAYER_ID_UNKNOWN, IsMapCycleOver);
cPlayerManager::Compute_Ladder_Points(winning_team);
cTeamManager::Log_Team_List();
cPlayerManager::Log_Player_List();
//
// Results logs wrap back to 1 after 100, and overwrite.
//
int log_num = cUserOptions::ResultsLogNumber.Get();
log_num++;
if (log_num > 100)
{
log_num = 1;
}
cUserOptions::ResultsLogNumber.Set(log_num);
Begin_Intermission();
}
//-----------------------------------------------------------------------------
bool cGameData::Is_Gameplay_Permitted(void)
{
bool permitted = true;
if (IsIntermission.Is_True()) {
permitted = false;
}
if (!GameModeManager::Find ("Combat")->Is_Active ()) {
permitted = false;
}
return permitted;
}
void cGameData::Set_Clan(int slot, unsigned long clanID)
{
WWASSERT(slot >= 0 && slot < MAX_CLAN_SLOTS);
mClanSlots[slot] = clanID;
}
unsigned long cGameData::Get_Clan(int slot) const
{
WWASSERT(slot >= 0 && slot < MAX_CLAN_SLOTS);
return mClanSlots[slot];
}
void cGameData::Clear_Clans(void)
{
for (int slot = 0; slot < MAX_CLAN_SLOTS; ++slot) {
mClanSlots[slot] = 0;
}
}
int cGameData::Find_Free_Clan_Slot(void) const
{
if (IsClanGame.Is_True()) {
for (int slot = 0; slot < MAX_CLAN_SLOTS; ++slot) {
if (mClanSlots[slot] == 0) {
return slot;
}
}
}
return -1;
}
bool cGameData::Is_Clan_Competing(unsigned long clanID) const
{
if (IsClanGame.Is_True() && (clanID != 0)) {
for (int slot = 0; slot < MAX_CLAN_SLOTS; ++slot) {
if (mClanSlots[slot] == clanID) {
return true;
}
}
}
return false;
}
//-----------------------------------------------------------------------------
bool cGameData::Is_Clan_Game_Open(void) const
{
if (IsClanGame.Is_True()) {
for (int slot = 0; slot < MAX_CLAN_SLOTS; ++slot) {
if (mClanSlots[slot] == 0) {
return true;
}
}
}
return false;
}
//-----------------------------------------------------------------------------
cGameData * cGameData::Create_Game_Of_Type(GameTypeEnum game_type)
{
/*
cGameData * p_game_data = NULL;
switch (game_type) {
//case GAME_TYPE_DEATHMATCH: p_game_data = new cGameDataDeathMatch; break;
//case GAME_TYPE_TEAM_DEATHMATCH: p_game_data = new cGameDataTeamDeathMatch; break;
case GAME_TYPE_CNC: p_game_data = new cGameDataCnc; break;
default: DIE; break;
}
return p_game_data;
*/
WWASSERT(game_type == GAME_TYPE_CNC);
return new cGameDataCnc;
}
/*
//-----------------------------------------------------------------------------
const char* cGameData::Get_Game_Type_Name(GameTypeEnum type)
{
static const char* _modeNames[] = {"SP", "SK", "CNC"};
return _modeNames[type];
}
*/
//-----------------------------------------------------------------------------
const char * cGameData::Get_Game_Type_Name(void) const
{
WideStringClass wide_name;
wide_name.Format(L"%s", Get_Game_Name());
StringClass name;
wide_name.Convert_To(name);
return name.Peek_Buffer();
}
//-----------------------------------------------------------------------------
void cGameData::Add_Bottom_Text(WideStringClass & text)
{
//WWASSERT(text != NULL);
/* WWASSERT(PFont != NULL);
float x = Render2DClass::Get_Screen_Resolution().Center().X -
PFont->String_Width(text) / 2.0f;
float y = MultiHUDClass::Get_Bottom_Text_Y_Pos();
y -= 1.2 * PFont->Char_Height();
MultiHUDClass::Set_Bottom_Text_Y_Pos(y);
WWASSERT(PTextRenderer != NULL);
PTextRenderer->Set_Location(Vector2(cMathUtil::Round(x), cMathUtil::Round(y)));
PTextRenderer->Draw_Text(text);
*/
BottomText.Add(text);
}
//-----------------------------------------------------------------------------
void cGameData::Show_Game_Settings_Limits(void)
{
if (PTextRenderer == NULL) {
return;
}
bool changed=false;
WideStringClass text(0,true);
unsigned color;
Get_Time_Limit_Text(text);
if (text!=renderer_time_text) {
renderer_time_text=text;
changed=true;
}
// Dedicated server label
if (cNetwork::I_Am_Only_Server()) {
Get_Dedicated_Server_Label(text,color);
}
else {
text="";
color=0;
}
if (text!=renderer_dedicated_server_label) {
renderer_dedicated_server_label=text;
changed=true;
}
if (color!=renderer_dedicated_server_color) {
renderer_dedicated_server_color=color;
changed=true;
}
// Gameplay pending label -
bool show_gameplay_label = false;
if (!Is_Gameplay_Permitted() || (COMBAT_STAR == NULL)) {
show_gameplay_label = true;
}
//if (IsIntermission.Is_False() && (!Is_Gameplay_Permitted() || (COMBAT_STAR == NULL))) {
if (show_gameplay_label) {
Get_Gameplay_Not_Permitted_Label(text,color);
} else {
text="";
color=0;
}
if (text!=renderer_gameplay_label) {
renderer_gameplay_label=text;
changed=true;
}
if (color!=renderer_gameplay_color) {
renderer_gameplay_color=color;
changed=true;
}
if (!changed) {
if (BottomText.Count()!=OldBottomText.Count()) {
changed=true;
}
else {
for (int j=0;jPeek_Font()->Get_Char_Height();
if (!changed) {
// Proceed the multihud by one line (as we are caching the time render which would usually do this)
float y = MultiHUDClass::Get_Bottom_Text_Y_Pos();
y -= 1.2 * charHeight;
MultiHUDClass::Set_Bottom_Text_Y_Pos(y);
BottomText.Reset_Active();
return;
}
// Re-compose the OldBottomText vector
OldBottomText.Reset_Active();
for (int j=0;jReset();
float x,y;
// Render bottom text (start with time text, which is to be first)
Vector2 textExtent = PTextRenderer->Get_Text_Extents(text);
x = Render2DClass::Get_Screen_Resolution().Center().X - textExtent.X / 2.0f;
//Always draw on the bottom
MultiHUDClass::Set_Bottom_Text_Y_Pos( Render2DClass::Get_Screen_Resolution().Bottom - 15 );
y = MultiHUDClass::Get_Bottom_Text_Y_Pos();
y -= 1.2 * charHeight;
Vector2 loc(cMathUtil::Round(x), cMathUtil::Round(y));
PTextRenderer->Set_Location(loc);
PTextRenderer->Build_Sentence(renderer_time_text);
PTextRenderer->Draw_Sentence();
for (j=0;jSet_Location(loc);
PTextRenderer->Build_Sentence(OldBottomText[j]);
PTextRenderer->Draw_Sentence();
}
MultiHUDClass::Set_Bottom_Text_Y_Pos(y);
// Dedicated server label
if (cNetwork::I_Am_Only_Server()) {
Vector2 extent = PTextRenderer->Get_Text_Extents(renderer_dedicated_server_label);
x = Render2DClass::Get_Screen_Resolution().Center().X - extent.X / 2.0f;
y = Render2DClass::Get_Screen_Resolution().Center().Y;
PTextRenderer->Set_Location(Vector2(cMathUtil::Round(x), cMathUtil::Round(y)));
PTextRenderer->Build_Sentence(renderer_dedicated_server_label);
PTextRenderer->Draw_Sentence(renderer_dedicated_server_color);
}
// Gameplay pending label
if (show_gameplay_label) {
Vector2 extent = PTextRenderer->Get_Text_Extents(renderer_gameplay_label);
x = Render2DClass::Get_Screen_Resolution().Center().X - extent.X / 2.0f;
y = Render2DClass::Get_Screen_Resolution().Center().Y + 1.2 * charHeight;
PTextRenderer->Set_Location(Vector2(cMathUtil::Round(x), cMathUtil::Round(y)));
PTextRenderer->Build_Sentence(renderer_gameplay_label);
PTextRenderer->Draw_Sentence(color);
}
}
//-----------------------------------------------------------------------------
void cGameData::Get_Dedicated_Server_Label(WideStringClass& text, unsigned& color)
{
color = 0xFFFFFFFF; // white
if (cMathUtil::Round(TimeManager::Get_Seconds()) % 2 != 0) {
color = 0xFF00FF00; // green
}
text = TRANSLATION(IDS_MP_DEDICATED_SERVER);
}
//-----------------------------------------------------------------------------
void cGameData::Get_Gameplay_Not_Permitted_Label(WideStringClass& text, unsigned& color)
{
color = 0xFFFFFFFF; // white
if (cMathUtil::Round(TimeManager::Get_Seconds()) % 2 != 0) {
color = 0xFF00FF00; // green
}
text = TRANSLATION(IDS_MP_GAMEPLAY_PENDING);
}
//-----------------------------------------------------------------------------
void cGameData::Get_Time_Limit_Text(WideStringClass& text)
{
if (IsIntermission.Is_True()) {
text.Format(
L"%s: %d",
TRANSLATION(IDS_MP_NEXTGAME_COUNTDOWN),
cMathUtil::Round(Get_Intermission_Time_Remaining()));
} else if (Is_Time_Limit()) {
int hours = 0;
int mins = 0;
int seconds = 0;
cMiscUtil::Seconds_To_Hms(TimeRemainingSeconds, hours, mins, seconds);
WideStringClass time_string(0, true);
time_string.Format(L"%02d:%02d:%02d", hours, mins, seconds);
text.Format(L"%s: %s", TRANSLATION(IDS_MP_TIME_REMAINING), time_string);
}
}
//-----------------------------------------------------------------------------
void cGameData::Think(void)
{
if (IsIntermission.Is_True()) {
IntermissionTimeRemaining -= TimeManager::Get_Frame_Real_Seconds();
if (IntermissionTimeRemaining < 0) {
IntermissionTimeRemaining = 0;
}
} else if (Is_Gameplay_Permitted()) {
TimeRemainingSeconds -= TimeManager::Get_Frame_Real_Seconds();
if (TimeRemainingSeconds < 0) {
TimeRemainingSeconds = 0;
}
DWORD duration_s = (int)((TIMEGETTIME() - GameStartTimeMs) / 1000.0f);
Set_Game_Duration_S(duration_s);
}
if (cNetwork::I_Am_Server()) {
//
// Update CurrentPlayers
//
int max = (int) WWMath::Max(
cPlayerManager::Count(),
cNetwork::PServerConnection->Get_Num_RHosts());
Set_Current_Players(max);
}
DEMO_SECURITY_CHECK;
FrameCount++;
}
//-----------------------------------------------------------------------------
void cGameData::Render(void)
{
Show_Game_Settings_Limits();
if (PTextRenderer != NULL) {
WWPROFILE("cGameData::Render");
PTextRenderer->Render();
}
}
//-----------------------------------------------------------------------------
void cGameData::On_Game_Begin(void)
{
//
// Note, On_Game_Begin happens after load.
//
WWDEBUG_SAY(("cGameData::On_Game_Begin\n"));
GetSystemTime(&GameStartTime);
FrameCount = 0;
GameStartTimeMs = TIMEGETTIME();
//
// Clear the MVP name
// Let MVP carry over into next game.
//
//MvpName.Format(L"");
//MvpCount = 0;
//
// Reset the game duration
//
GameDurationS = 0;
//
// Notify the combat layer about various server options
//
cCsDamageEvent::Set_Are_Clients_Trusted(IsClientTrusted.Get());
BuildingGameObj::Set_Can_Repair_Buildings(CanRepairBuildings.Get());
VehicleGameObj::Set_Default_Driver_Is_Gunner(DriverIsAlwaysGunner.Get());
CombatManager::Set_Friendly_Fire_Permitted(IsFriendlyFirePermitted.Get());
CombatManager::Set_Beacon_Placement_Ends_Game(false);
//
// Filter out unwanted spawners
//
if (cNetwork::I_Am_Server()) {
Filter_Spawners();
}
//
// Adjust teaming for auto-teamed games
//
//if (!IS_MISSION && cNetwork::I_Am_Server() && Is_Team_Game() && IsTeamChangingAllowed.Is_False()) {
if (!IS_MISSION && cNetwork::I_Am_Server()) {
if (IsClanGame.Is_False() && IsTeamChangingAllowed.Is_False() && RemixTeams.Is_True()) {
//
// Remix Teams if the server option is set.
//
Remix_Team_Sides();
} else {
//
// In non-remixed C&C mode, we have a 50-50 chance of the teams being swapped. I prefer this
// to simply alternating, because if you alternate and the number of maps in the
// cycle is even, you will always play GDI on the same 50% of the maps.
//
if (Is_Skirmish() || (Is_Cnc() && (rand() % 2 == 0))) {
Swap_Team_Sides();
}
}
if (IsClanGame.Is_False() && IsTeamChangingAllowed.Is_False())
{
//
// We always rebalance the teams numerically
//
Rebalance_Team_Sides();
}
}
GameModeClass* gameMode = GameModeManager::Find("WOL");
if (gameMode && gameMode->Is_Active()) {
WolGameModeClass* wolGame = reinterpret_cast(gameMode);
WWASSERT(wolGame != NULL);
wolGame->Start_Game(this);
}
}
//-----------------------------------------------------------------------------
void cGameData::On_Game_End(void)
{
WWDEBUG_SAY(("cGameData::On_Game_End\n"));
GameModeClass* gameMode = GameModeManager::Find("WOL");
if (gameMode && gameMode->Is_Active()) {
WolGameModeClass* wolGame = reinterpret_cast(gameMode);
wolGame->End_Game();
}
}
//-----------------------------------------------------------------------------
int cGameData::Get_Mission_Number_From_Map_Name( const char * map_name )
{
// If tutorial, return tutorial number
if ( ::strnicmp( map_name, "M00_T", 5 ) == 0 ) {
#define TUTORIAL_LOAD_MENU_NUMBER 90
return TUTORIAL_LOAD_MENU_NUMBER;
}
// Assume the map name is in the form "mXX.mix" where xx is the level number
if ( ::strlen( map_name ) > 0 ) {
return ::atoi( ((const char *)map_name)+1 );
}
return 0;
}
//-----------------------------------------------------------------------------
const StringClass& cGameData::Get_Map_Cycle(int map)
{
WWASSERT(map >= 0 && map < MAX_MAPS);
#ifdef MULTIPLAYERDEMO
MapCycle[map].Format("C&C_Under.mix");
#endif // MULTIPLAYERDEMO
return MapCycle[map];
}
//-----------------------------------------------------------------------------
void
cGameData::Set_Map_Cycle(int map, const StringClass & map_name)
{
WWASSERT(map >= 0 && map < MAX_MAPS);
MapCycle[map] = map_name;
}
//-----------------------------------------------------------------------------
void
cGameData::Clear_Map_Cycle(void)
{
for (int i = 0; i < MAX_MAPS; i++)
{
MapCycle[i].Format("");
}
}
//-----------------------------------------------------------------------------
void
cGameData::Rotate_Map(void)
{
IsMapCycleOver = false;
//
// Determine the current map
//
int current_map = MapCycleIndex;
#if (0)
int current_map = 0;
for (int i = 0; i < MAX_MAPS; i++)
{
if (MapName == MapCycle[i]) {
current_map = i;
break;
}
}
#endif //(0)
//
// Increment it
//
current_map++;
//
// Go back to the first map if necessary
//
if (current_map >= MAX_MAPS || MapCycle[current_map].Is_Empty()) {
current_map = 0;
if (DoMapsLoop == false) {
IsMapCycleOver = true;
}
}
//
// Set the map name
//
#ifdef MULTIPLAYERDEMO
MapName.Format("C&C_Under.mix");
#else
MapName = MapCycle[current_map];
#endif
MapCycleIndex = current_map;
return ;
}
//-----------------------------------------------------------------------------
void cGameData::Set_Win_Text(WideStringClass & text)
{
WinText = text;
}
//-----------------------------------------------------------------------------
void cGameData::ReceiveSignal(MPChooseTeamSignal& choice)
{
if (choice.GetItemA() == true) {
//
// Do nothing if the player selected 'auto' rather than GDI or NOD.
//
if (choice.GetItemB() != PLAYERTYPE_RENEGADE) {
cNetwork::SwitchTeam(choice.GetItemB());
}
}
}
//-----------------------------------------------------------------------------
void cGameData::Filter_Spawners(void)
{
WWASSERT(cNetwork::I_Am_Server());
if (SpawnWeapons.Is_False()) {
//
// Disable multiplay weapons spawners
//
DynamicVectorClass spawner_list = SpawnManager::Get_Spawner_List();
for (int i = 0; i < spawner_list.Count(); i++) {
WWASSERT(spawner_list[i] != NULL);
if (spawner_list[i]->Get_Definition().Is_Multiplay_Weapon_Spawner()) {
spawner_list[i]->Enable(false);
}
}
}
}
//------------------------------------------------------------------------------------
void cGameData::Set_Mvp_Name(const WideStringClass name)
{
MvpName = name;
}
//------------------------------------------------------------------------------------
void cGameData::Set_Mvp_Count(int count)
{
WWASSERT(count >= 0);
MvpCount = count;
}
//------------------------------------------------------------------------------------
void cGameData::Set_Win_Type(WinTypeEnum type)
{
WinType = type;
}
//------------------------------------------------------------------------------------
void cGameData::Set_Game_Duration_S(DWORD seconds)
{
GameDurationS = seconds;
}
//-----------------------------------------------------------------------------
void cGameData::Get_Description(WideStringClass & description)
{
const WideStringClass delimiter = L"\t";
const WideStringClass newline = L"\n";
const WideStringClass yes = TRANSLATE(IDS_YES);
const WideStringClass no = TRANSLATE(IDS_NO);
WideStringClass attribute(0, true);
WideStringClass value(0, true);
//
// Host
//
attribute = TRANSLATE(IDS_MP_HOST);
value = Owner;
description += (attribute + delimiter + value + newline);
//
// Game Name
//
attribute = TRANSLATE(IDS_MENU_TEXT292);
value = GameTitle;
description += (attribute + delimiter + value + newline);
//
// Map Name
//
if (ModName.Is_Empty () == false) {
attribute = L"Mod Name:";
value = ModName;
description += (attribute + delimiter + value + newline);
}
//
// Map Name
//
attribute = TRANSLATE(IDS_MP_GAME_LIST_HEADER_GAME_MAP);
value = MapName;
description += (attribute + delimiter + value + newline);
//
// Time Limit
//
attribute = TRANSLATE(IDS_MENU_TEXT298);
if (Is_Time_Limit()) {
value.Format(L"%d %s", TimeLimitMinutes, TRANSLATE(IDS_MP_MINUTES));
} else {
value = TRANSLATE(IDS_MP_NONE);
}
description += (attribute + delimiter + value + newline);
//
// Max. Players
//
attribute = TRANSLATE(IDS_MENU_TEXT294);
value.Format(L"%d", MaxPlayers);
description += (attribute + delimiter + value + newline);
//
// Radar
//
attribute = TRANSLATE(IDS_MENU_TEXT488);
switch (RadarMode) {
case RADAR_NOBODY:
value = TRANSLATION(IDS_MP_RADAR_MODE_NOBODY);
break;
case RADAR_TEAMMATES:
value = TRANSLATION(IDS_MP_RADAR_MODE_TEAMMATES);
break;
case RADAR_ALL:
value = TRANSLATION(IDS_MP_RADAR_MODE_ALL);
break;
default:
DIE;
}
description += (attribute + delimiter + value + newline);
//
// Allow Quickmatching
//
attribute = TRANSLATE(IDS_MENU_TEXT584);
value = (IsQuickMatchServer.Get() ? yes : no);
description += (attribute + delimiter + value + newline);
//
// Dedicated
//
attribute = TRANSLATE(IDS_MENU_TEXT309);
value = (IsDedicated.Get() ? yes : no);
description += (attribute + delimiter + value + newline);
//
// Friendly Fire
//
attribute = TRANSLATE(IDS_MENU_TEXT301);
value = (IsFriendlyFirePermitted.Get() ? yes : no);
description += (attribute + delimiter + value + newline);
//
// Manual Teaming
//
attribute = TRANSLATE(IDS_MENU_TEXT490);
value = (IsTeamChangingAllowed.Get() ? yes : no);
description += (attribute + delimiter + value + newline);
//
// Passworded
//
attribute = TRANSLATE(IDS_MP_PASSWORDED);
value = (IsPassworded.Get() ? yes : no);
description += (attribute + delimiter + value + newline);
//
// Laddered
//
attribute = TRANSLATE(IDS_MENU_TEXT496);
value = (IsLaddered.Get() ? yes : no);
description += (attribute + delimiter + value + newline);
//
// Clan Game
//
attribute = TRANSLATE(IDS_MENU_TEXT497);
value = (IsClanGame.Get() ? yes : no);
description += (attribute + delimiter + value + newline);
/*
//
// Trust Clients
//
attribute = TRANSLATE(IDS_MENU_TEXT585);
value = (IsClientTrusted.Get() ? yes : no);
description += (attribute + delimiter + value + newline);
*/
//
// Remix Teams
//
attribute = TRANSLATE(IDS_MENU_TEXT587);
value = (RemixTeams.Get() ? yes : no);
description += (attribute + delimiter + value + newline);
//
// Can Repair Buildings
//
attribute = TRANSLATE(IDS_MENU_TEXT590);
value = (CanRepairBuildings.Get() ? yes : no);
description += (attribute + delimiter + value + newline);
//
// Driver Is Always Gunner
//
attribute = TRANSLATE(IDS_MENU_TEXT591);
value = (DriverIsAlwaysGunner.Get() ? yes : no);
description += (attribute + delimiter + value + newline);
//
// Weapon spawning
//
attribute = TRANSLATE(IDS_MENU_TEXT592);
value = (SpawnWeapons.Get() ? yes : no);
description += (attribute + delimiter + value + newline);
}
//-----------------------------------------------------------------------------
//cGameData * The_Game(void) {WWASSERT(PTheGameData != NULL); return PTheGameData;}
cGameData * The_Game(void) {return PTheGameData;}
cGameDataSinglePlayer * The_Single_Player_Game(void) {WWASSERT(The_Game()->As_Single_Player() != NULL); return The_Game()->As_Single_Player();}
cGameDataSkirmish * The_Skirmish_Game(void) {WWASSERT(The_Game()->As_Skirmish() != NULL); return The_Game()->As_Skirmish();}
cGameDataCnc * The_Cnc_Game(void) {WWASSERT(The_Game()->As_Cnc() != NULL); return The_Game()->As_Cnc();}
/*
if (Is_Team_Game()) {
has_opponents =
cPlayerManager::Get_Count(PLAYERTYPE_NOD) > 0 &&
cPlayerManager::Get_Count(PLAYERTYPE_GDI) > 0;
} else {
has_opponents = (cPlayerManager::Get_Count(PLAYERTYPE_RENEGADE) > 1);
}
*/
/*
//-----------------------------------------------------------------------------
void cGameData::Set_Min_Game_Time_Required_Mins(int mins)
{
WWASSERT(mins >= 0 );
MinGameTimeRequiredMins = mins;
}
*/
/*
//-----------------------------------------------------------------------------
void cGameData::Set_Full_Score_Time_Threshold_Mins(int mins)
{
WWASSERT(mins >= 0);
FullScoreTimeThresholdMins = mins;
}
*/
//#include "helptext.h"
//#include "gddeathmatch.h"
//#include "gdteamdeathmatch.h"
//MinGameTimeRequiredMins = 10;
//FullScoreTimeThresholdMins = 30;
//MinGameTimeRequiredMins = rhs.MinGameTimeRequiredMins;
//FullScoreTimeThresholdMins = rhs.FullScoreTimeThresholdMins;
//packet.Add(MinGameTimeRequiredMins);
//packet.Add(FullScoreTimeThresholdMins);
//Set_Min_Game_Time_Required_Mins( packet.Get(i_placeholder));
//Set_Full_Score_Time_Threshold_Mins( packet.Get(i_placeholder));
//cGameDataDeathMatch * The_Deathmatch_Game(void) {WWASSERT(The_Game()->As_Deathmatch() != NULL); return The_Game()->As_Deathmatch();}
//cGameDataTeamDeathMatch * The_Team_Deathmatch_Game(void) {WWASSERT(The_Game()->As_Team_Deathmatch() != NULL); return The_Game()->As_Team_Deathmatch();}
//if (Is_Team_Game()) {
/*
} else {
has_opponents = (cPlayerManager::Tally_Team_Size(PLAYERTYPE_RENEGADE) > 1);
}
*/
//IsBloodShed.Set( false);
//IsBloodShed = rhs.IsBloodShed;
/*
if (cNetwork::I_Am_Server()) {
IsBloodShed.Set(false);
}
*/