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

520 lines
14 KiB
C++
Raw Permalink Normal View History

/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Commando/gdcnc.cpp $*
* *
* $Author:: Bhayes $*
* *
* $Modtime:: 4/15/02 4:12p $*
* *
* $Revision:: 47 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "gdcnc.h"
#include "specialbuilds.h"
#include "cnetwork.h"
#include "translatedb.h"
#include "string_ids.h"
#include "assets.h"
#include "multihud.h"
#include "playerdata.h"
#include "player.h"
#include "playertype.h"
#include "consolemode.h"
//-----------------------------------------------------------------------------
cGameDataCnc::cGameDataCnc(void) :
IsPlaying (false),
cGameData()
{
//WWDEBUG_SAY(("cGameDataCnc::cGameDataCnc\n"));
Set_Time_Limit_Minutes(25);
Set_Ini_Filename("svrcfg_cnc.ini");
Set_Ip_And_Port();
BaseDestructionEndsGame.Set(true);
BeaconPlacementEndsGame.Set(true);
StartingCredits = 0;
IsTeamChangingAllowed.Set(false);
RemixTeams.Set(true);
Set_Radar_Mode(RADAR_TEAMMATES);
}
//-----------------------------------------------------------------------------
cGameDataCnc::~cGameDataCnc(void)
{
//WWDEBUG_SAY(("cGameDataCnc::~cGameDataCnc\n"));
}
//-----------------------------------------------------------------------------
cGameDataCnc& cGameDataCnc::operator=(const cGameDataCnc& rhs)
{
//
// Call the base class
//
cGameData::operator=(rhs);
BaseDestructionEndsGame = rhs.BaseDestructionEndsGame;
BeaconPlacementEndsGame = rhs.BeaconPlacementEndsGame;
StartingCredits = rhs.StartingCredits;
return (*this);
}
//-----------------------------------------------------------------------------
const WCHAR* cGameDataCnc::Get_Static_Game_Name(void)
{
return TRANSLATION(IDS_MP_GAME_TYPE_CNC);
}
//-----------------------------------------------------------------------------
void cGameDataCnc::Reset_Game(bool is_reloaded)
{
WWDEBUG_SAY(("cGameDataCnc::Reset_Game\n"));
cGameData::Reset_Game(is_reloaded);
//
// TSS091201 - hack - On_Game_End not called in correct places
//
if (IsPlaying) {
BaseGDI.Shutdown ();
BaseNOD.Shutdown ();
IsPlaying = false;
}
//
// Initialize the base controllers
//
BaseGDI.Initialize ( PLAYERTYPE_GDI );
BaseNOD.Initialize ( PLAYERTYPE_NOD );
return ;
}
//-----------------------------------------------------------------------------
void
cGameDataCnc::On_Game_Begin (void)
{
WWDEBUG_SAY(("cGameDataCnc::On_Game_Begin\n"));
cGameData::On_Game_Begin();
CombatManager::Set_Beacon_Placement_Ends_Game(BeaconPlacementEndsGame.Get());
//
// Initialize the bases
//
IsPlaying = true;
return ;
}
//-----------------------------------------------------------------------------
void
cGameDataCnc::On_Game_End (void)
{
WWDEBUG_SAY(("cGameDataCnc::On_Game_End\n"));
//
// Close the bases
//
BaseGDI.Shutdown ();
BaseNOD.Shutdown ();
IsPlaying = false;
cGameData::On_Game_End();
return ;
}
//-----------------------------------------------------------------------------
void
cGameDataCnc::Soldier_Added (SoldierGameObj *soldier)
{
cGameData::Soldier_Added (soldier);
//
// Give the soldier some starting credits
//
if ( soldier != NULL &&
soldier->Get_Player_Data() != NULL &&
soldier->Get_Player_Data()->Get_Game_Time () == 0)
{
soldier->Get_Player_Data ()->Set_Money (StartingCredits);
}
return ;
}
//-----------------------------------------------------------------------------
void cGameDataCnc::Think(void)
{
cGameData::Think();
if (!cNetwork::I_Am_Server()) {
return;
}
//
// Let the bases think
//
if (IsPlaying) {
BaseGDI.Think ();
BaseNOD.Think ();
}
return ;
}
//-----------------------------------------------------------------------------
void cGameDataCnc::Set_Starting_Credits(int credits)
{
Set_Generic_Num(credits, 0, MAX_CREDITS, StartingCredits);
}
//-----------------------------------------------------------------------------
void cGameDataCnc::Export_Tier_2_Data(cPacket & packet)
{
cGameData::Export_Tier_2_Data(packet);
packet.Add(BaseDestructionEndsGame.Get());
packet.Add(BeaconPlacementEndsGame.Get());
packet.Add(StartingCredits);
}
//-----------------------------------------------------------------------------
void cGameDataCnc::Import_Tier_2_Data(cPacket & packet)
{
cGameData::Import_Tier_2_Data(packet);
bool b_placeholder;
int i_placeholder;
BaseDestructionEndsGame.Set( packet.Get(b_placeholder));
BeaconPlacementEndsGame.Set( packet.Get(b_placeholder));
Set_Starting_Credits( packet.Get(i_placeholder));
}
//-----------------------------------------------------------------------------
void cGameDataCnc::Base_Destruction_Score_Tweaking(void)
{
WWASSERT(cNetwork::I_Am_Server());
cTeam * p_nod = cTeamManager::Find_Team(PLAYERTYPE_NOD);
WWASSERT(p_nod != NULL);
cTeam * p_gdi = cTeamManager::Find_Team(PLAYERTYPE_GDI);
WWASSERT(p_gdi != NULL);
float nod_score = p_nod->Get_Score();
float gdi_score = p_gdi->Get_Score();
const int BASE_DESTRUCTION_POINTS_REWARD = 5000;
//
// Base destroyer gets a points reward.
// If this isn't enough to beat other team, nudge score ahead by 1 point.
//
if (BaseGDI.Is_Base_Destroyed()) {
nod_score += BASE_DESTRUCTION_POINTS_REWARD;
if (nod_score <= gdi_score) {
nod_score = gdi_score + 1;
}
p_nod->Set_Score(nod_score);
} else {
WWASSERT(BaseNOD.Is_Base_Destroyed());
gdi_score += BASE_DESTRUCTION_POINTS_REWARD;
if (gdi_score <= nod_score) {
gdi_score = nod_score + 1;
}
p_gdi->Set_Score(gdi_score);
}
}
//-----------------------------------------------------------------------------
bool cGameDataCnc::Is_Game_Over(void)
{
WWASSERT(cNetwork::I_Am_Server());
bool is_game_over = cGameData::Is_Game_Over();
if (!is_game_over && BaseDestructionEndsGame.Is_True())
{
//
// If a base is destroyed then the game is over and the other team wins.
// To ensure this we may need to tweak the base-destroyer's score.
//
if (BaseGDI.Is_Base_Destroyed() || BaseNOD.Is_Base_Destroyed()) {
is_game_over = true;
Base_Destruction_Score_Tweaking();
if (BaseGDI.Did_Beacon_Destroy_Base() || BaseNOD.Did_Beacon_Destroy_Base()) {
Set_Win_Type(WIN_TYPE_BEACON);
} else {
Set_Win_Type(WIN_TYPE_BASE_DESTRUCTION);
}
}
}
//
// Beacon placement end game works via above base destruction method.
//
return is_game_over;
}
//-----------------------------------------------------------------------------
void cGameDataCnc::Load_From_Server_Config(void)
{
cGameData::Load_From_Server_Config(Get_Ini_Filename());
INIClass * p_ini = Get_INI(Get_Ini_Filename());
WWASSERT(p_ini != NULL);
bool b;
int i;
//float f;
i = p_ini->Get_Int( INI_SECTION_NAME, "MaxPlayers", Get_Max_Players());
Set_Max_Players(i);
b = p_ini->Get_Bool( INI_SECTION_NAME, "IsFriendlyFirePermitted", IsFriendlyFirePermitted.Get());
IsFriendlyFirePermitted.Set(b);
b = p_ini->Get_Bool( INI_SECTION_NAME, "DoMapsLoop", DoMapsLoop);
DoMapsLoop = b;
b = p_ini->Get_Bool( INI_SECTION_NAME, "IsTeamChangingAllowed", IsTeamChangingAllowed.Get());
IsTeamChangingAllowed.Set(b);
b = p_ini->Get_Bool( INI_SECTION_NAME, "IsClanGame", IsClanGame.Get());
IsClanGame.Set(b);
b = p_ini->Get_Bool( INI_SECTION_NAME, "BaseDestructionEndsGame", BaseDestructionEndsGame.Get());
BaseDestructionEndsGame.Set(b);
b = p_ini->Get_Bool( INI_SECTION_NAME, "BeaconPlacementEndsGame", BeaconPlacementEndsGame.Get());
BeaconPlacementEndsGame.Set(b);
i = p_ini->Get_Int( INI_SECTION_NAME, "StartingCredits", Get_Starting_Credits());
Set_Starting_Credits(i);
Release_INI(p_ini);
return ;
}
//-----------------------------------------------------------------------------
void cGameDataCnc::Save_To_Server_Config(void)
{
cGameData::Save_To_Server_Config(Get_Ini_Filename());
INIClass * p_ini = Get_INI(Get_Ini_Filename());
WWASSERT(p_ini != NULL);
p_ini->Put_Bool( INI_SECTION_NAME, "IsFriendlyFirePermitted", IsFriendlyFirePermitted.Get());
p_ini->Put_Bool( INI_SECTION_NAME, "DoMapsLoop", DoMapsLoop);
p_ini->Put_Bool( INI_SECTION_NAME, "IsTeamChangingAllowed", IsTeamChangingAllowed.Get());
p_ini->Put_Bool( INI_SECTION_NAME, "IsClanGame", IsClanGame.Get());
p_ini->Put_Int( INI_SECTION_NAME, "MaxPlayers", Get_Max_Players());
p_ini->Put_Bool( INI_SECTION_NAME, "BaseDestructionEndsGame", BaseDestructionEndsGame.Get());
p_ini->Put_Bool( INI_SECTION_NAME, "BeaconPlacementEndsGame", BeaconPlacementEndsGame.Get());
p_ini->Put_Int( INI_SECTION_NAME, "StartingCredits", Get_Starting_Credits());
Save_INI(p_ini, Get_Ini_Filename());
Release_INI(p_ini);
}
//-----------------------------------------------------------------------------
void cGameDataCnc::Show_My_Money(void)
{
if (cNetwork::I_Am_Client()) {
cPlayer * p_player = cNetwork::Get_My_Player_Object();
if (p_player != NULL) {
WideStringClass text(0,true);
text.Format(L"%s: %d",
TRANSLATION(IDS_MP_MONEY), (int) p_player->Get_Money());
Add_Bottom_Text(text);
}
}
}
//-----------------------------------------------------------------------------
void cGameDataCnc::Show_Game_Settings_Limits(void)
{
/*
if (IsIntermission.Is_True()) {
return;
}
*/
Show_My_Money();
cGameData::Show_Game_Settings_Limits();
}
//-----------------------------------------------------------------------------
bool cGameDataCnc::Is_Limited(void) const
{
return Is_Time_Limit() || BaseDestructionEndsGame.Is_True();
}
//-----------------------------------------------------------------------------
void cGameDataCnc::Get_Description(WideStringClass & description)
{
//
// Call base class
//
cGameData::Get_Description(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);
//
// Starting Credits
//
attribute = TRANSLATE(IDS_MENU_TEXT349);
value.Format(L"%d", StartingCredits);
description += (attribute + delimiter + value + newline);
//
// Base Destruction Ends Game
//
attribute = TRANSLATE(IDS_MENU_TEXT314);
value = (BaseDestructionEndsGame.Get() ? yes : no);
description += (attribute + delimiter + value + newline);
//
// Beacon Placement Ends Game
//
attribute = TRANSLATE(IDS_MENU_TEXT315);
value = (BeaconPlacementEndsGame.Get() ? yes : no);
description += (attribute + delimiter + value + newline);
}
#define PRINT_CONFIG_ERROR ConsoleBox.Print("File %s - Error:\r\n\t ", Get_Ini_Filename());
//-----------------------------------------------------------------------------
bool cGameDataCnc::Is_Valid_Settings(WideStringClass& outMsg, bool check_as_server)
{
/*
** Check the base settings first.
*/
if (!cGameData::Is_Valid_Settings(outMsg, check_as_server)) {
return(false);
}
#ifdef FREEDEDICATEDSERVER
if (BaseDestructionEndsGame.Is_False() && BeaconPlacementEndsGame.Is_True()) {
//cHelpText::Set(TRANSLATION(IDS_MP_GAMEMODE_NEEDS_LIMIT));
PRINT_CONFIG_ERROR;
ConsoleBox.Print("Cannot allow beacons to end game without base destruction ending game.\n\n");
outMsg = TRANSLATE(IDS_HOPTERR_NO_GAMEEND);
return false;
}
#endif
return(true);
}
//-----------------------------------------------------------------------------
bool cGameDataCnc::Is_Gameplay_Permitted(void)
{
bool permitted = cGameData::Is_Gameplay_Permitted();
if (permitted && Get_Max_Players() > 1)
{
//
// If your maxplayers is set to more than 1 then you must have an opponent.
//
permitted =
cPlayerManager::Tally_Team_Size(PLAYERTYPE_NOD) > 0 &&
cPlayerManager::Tally_Team_Size(PLAYERTYPE_GDI) > 0;
}
return permitted;
}
/*
void cGameDataCnc::Get_Description(WideStringClass & description)
{
//
// Call base class
//
cGameData::Get_Description(description);
const WideStringClass newline = L"\n";
const WideStringClass yes = L"yes";
const WideStringClass no = L"no";
WideStringClass line(0, true);
line.Format(L"Starting Credits\t%d", StartingCredits);
IDS_MENU_TEXT349
description += line;
description += newline;
line.Format(L"Base Destruction Ends Game\t%s", BaseDestructionEndsGame.Get() ? yes : no);
IDS_MENU_TEXT314
description += line;
description += newline;
line.Format(L"Beacon Placement Ends Game\t%s", BeaconPlacementEndsGame.Get() ? yes : no);
IDS_MENU_TEXT315
description += line;
description += newline;
}
*/
//-----------------------------------------------------------------------------