/*
**	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/gdskirmish.cpp                           $* 
 *                                                                                             * 
 *                      $Author:: Tom_s                                                       $* 
 *                                                                                             * 
 *                     $Modtime:: 4/12/02 4:01p                                               $* 
 *                                                                                             * 
 *                    $Revision:: 12                                                          $* 
 *                                                                                             * 
 *---------------------------------------------------------------------------------------------* 
 * Functions:                                                                                  * 
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

#include "gdskirmish.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 "gameobjmanager.h"
#include "spawn.h"

//-----------------------------------------------------------------------------
cGameDataSkirmish::cGameDataSkirmish(void)	:
	IsPlaying (false),
	cGameData()
{
   //WWDEBUG_SAY(("cGameDataSkirmish::cGameDataSkirmish\n"));

	Set_Time_Limit_Minutes(25);
	Set_Ini_Filename("svrcfg_skirmish.ini");
	BaseDestructionEndsGame.Set(true);
	BeaconPlacementEndsGame.Set(true);
	StartingCredits = 400;
	//IsTeamChangingAllowed.Set(false);
	IsTeamChangingAllowed.Set(true);
	Set_Max_Players(1);
	Set_Radar_Mode(RADAR_TEAMMATES);

	Load_From_Server_Config();
	Save_To_Server_Config();
	
	//
	// Reload again to avoid LastServerConfigModTime issues
	//
	Load_From_Server_Config();
}

//-----------------------------------------------------------------------------
cGameDataSkirmish::~cGameDataSkirmish(void)
{
   //WWDEBUG_SAY(("cGameDataSkirmish::~cGameDataSkirmish\n"));
}

//-----------------------------------------------------------------------------
cGameDataSkirmish& cGameDataSkirmish::operator=(const cGameDataSkirmish& rhs)
{
	// 
	// Call the base class
	//
	cGameData::operator=(rhs);

	BaseDestructionEndsGame				= rhs.BaseDestructionEndsGame;
	BeaconPlacementEndsGame				= rhs.BeaconPlacementEndsGame;
	StartingCredits						= rhs.StartingCredits;

	return (*this);
}

//-----------------------------------------------------------------------------
const WCHAR* cGameDataSkirmish::Get_Static_Game_Name(void)
{
	return TRANSLATION(IDS_MP_GAME_TYPE_SKIRMISH);
}

//-----------------------------------------------------------------------------
void cGameDataSkirmish::Reset_Game(bool is_reloaded)
{
   WWDEBUG_SAY(("cGameDataSkirmish::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
cGameDataSkirmish::On_Game_Begin (void)
{
   WWDEBUG_SAY(("cGameDataSkirmish::On_Game_Begin\n"));

	cGameData::On_Game_Begin();

	CombatManager::Set_Beacon_Placement_Ends_Game(BeaconPlacementEndsGame.Get());

	//
	//	Initialize the bases
	//
	IsPlaying = true;
}

//-----------------------------------------------------------------------------
void
cGameDataSkirmish::On_Game_End (void)
{
   WWDEBUG_SAY(("cGameDataSkirmish::On_Game_End\n"));

	//
	//	Close the bases
	//
	BaseGDI.Shutdown ();
	BaseNOD.Shutdown ();
	IsPlaying = false;

	cGameData::On_Game_End();
	return ;
}

//-----------------------------------------------------------------------------
void
cGameDataSkirmish::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 cGameDataSkirmish::Think(void)
{
	cGameData::Think();

	if (!cNetwork::I_Am_Server()) {
		return;
	}

	//
	//	Let the bases think
	//
	if (IsPlaying) {
		BaseGDI.Think ();
		BaseNOD.Think ();
	}

	//
	// Weed out any soldiers or spawners that shouldn't be present.
	//
	Filter_Soldiers();

	return ;
}

//-----------------------------------------------------------------------------
void cGameDataSkirmish::Set_Starting_Credits(int credits)
{
   Set_Generic_Num(credits, 0, MAX_CREDITS, StartingCredits);
}

//-----------------------------------------------------------------------------
void cGameDataSkirmish::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 cGameDataSkirmish::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;
			Set_Win_Type(WIN_TYPE_BASE_DESTRUCTION);
			Base_Destruction_Score_Tweaking();
		}
	}

	//
	// Beacon placement end game works via above base destruction method.
	//

	return is_game_over;
}

//-----------------------------------------------------------------------------
void cGameDataSkirmish::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, "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 cGameDataSkirmish::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, "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 cGameDataSkirmish::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 cGameDataSkirmish::Show_Game_Settings_Limits(void)
{  
	/*
	if (IsIntermission.Is_True()) {
		return;
	}
	*/

	Show_My_Money();

	cGameData::Show_Game_Settings_Limits();
}

//-----------------------------------------------------------------------------
void cGameDataSkirmish::Filter_Soldiers(void)
{  
	//
	// Remove any soldiers or spawners on your side, leaving only opponents.
	//

	cPlayer * p_player = cNetwork::Get_My_Player_Object();

	if (p_player != NULL) {

		//int my_team = p_player->Get_Player_Type();

		/*
		//
		// Remove soldiers
		// Whoa, design now wants these... comment out this code.
		//
		for (
			SLNode<SmartGameObj> * objnode = GameObjManager::Get_Smart_Game_Obj_List()->Head(); 
			objnode != NULL; 
			objnode = objnode->Next()) 
		{
			SmartGameObj * p_smart_obj = objnode->Data();
			WWASSERT(p_smart_obj != NULL);

			if (	p_smart_obj->As_SoldierGameObj() != NULL && 
					!p_smart_obj->Is_Delete_Pending() && 
					!p_smart_obj->Has_Player() &&
					p_smart_obj->Get_Player_Type() == my_team) {

				p_smart_obj->Set_Delete_Pending();
			}
		}
		*/

		/*
		//
		// Remove spawners... ugh how do I select just the appropriate ones?
		//
		DynamicVectorClass<SpawnerClass*> 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().Get_Player_Type() == my_team) {
				spawner_list[i]->Enable(false);
			}
		}
		*/
	}
}

//-----------------------------------------------------------------------------
void cGameDataSkirmish::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);
}
