#include "MW4Headers.hpp"

#include "MWGame.hpp"
#include "MWMission.hpp"
#include "Salvage.hpp"
#include "lancemate.hpp"
#include "MWCampaign.hpp"
#include "MWApplication.hpp"
#include "ScriptErrorHeader.hpp"
#include "MWTable.hpp"
#include "MWDamageObject.hpp"
#include "AI_Groups.hpp"
#include "SearchLight.hpp"

#include <Adept\Tool.hpp>

#include <MissionLang\Resource.h>

#include "..\buildnum\buildnum.h"

extern bool g_bCOOP; // COin OPeration

//#############################################################################
//##############################     PilotPlug   ##############################
//#############################################################################

void 
	PilotPlug::SavePilotToStream(Stuff::MemoryStream *stream)
{
	Check_Object(this);
	Check_Pointer(stream);

	*stream << m_isLeader;

	//Write out the mech plug info
	MString mech_plug_name = "";
	if(m_mechPlug)
		mech_plug_name = m_mechPlug->GetMechName();
	*stream << mech_plug_name;

	//Write out the lance pilot plug info
	MString lance_plug_name = "";
	if(m_pilot)
		lance_plug_name = m_pilot->m_lancemateName;
	*stream << lance_plug_name;
	
}

//#############################################################################
//##############################     MWGame   #################################
//#############################################################################

MWGame::MWGame(const char *game_file_name) :
	Plug(Plug::DefaultData),
	m_lancePilots(NULL, true),
	m_mechTable(NULL, true),
	m_gameResourceFile(NULL)
{
	Check_Pointer(game_file_name);
	
	//
	//----------------------------------------------
	//We need to open the resource file for our game
	//----------------------------------------------
	//
	//MString res_path = "Resource\\Games\\";
	MString res_path = "Resource\\Pilots\\";
	res_path += MWApplication::GetInstance()->m_pilotName;
	res_path += "\\Games\\";
	res_path += game_file_name;
	MString res_file = res_path;
	res_file += ".mw4";
//	MString dep_file = res_path;
//	dep_file += ".dep";
	
	Check_Object(ResourceManager::Instance);
	ResourceFile *resource_file = ResourceManager::Instance->OpenResourceFile(
		(const char *)res_file,
		NULL,
		GameResourceFileID,
		VER_CONTENTVERSION,
		false,
		false,
		false
	);

	Check_Object(resource_file);
	m_gameResourceFile.Add(resource_file);
	//
	//-------------------------------------------------------------
	//We need to create all of our parts with the correct resources
	//-------------------------------------------------------------
	//

	//First check the version resource and verify this is a good save game
	ResourceID version_id(GameResourceFileID, VersionResourceID);
	Resource version_resource(version_id);
	Verify(version_resource.DoesResourceExist());

	MString version;
	version_resource >> version;

	MString curver = CURRENT_BUILD_FULL_STRING;

	if (version > curver)
	{
		PAUSE(("You are loading a game saved by a newer game version.  The saved game might not work correctly."));
	}

	//General Game Data
	ResourceID game_data_id(GameResourceFileID, GeneralGameResourceID);
	Resource game_data_resource(game_data_id);
	Verify(game_data_resource.DoesResourceExist());

	LoadGeneralGameData(&game_data_resource);

	//Campaign
	ResourceID campaign_id(GameResourceFileID, CampaignResourceID);
	Resource campaign_resource(campaign_id);
	Verify(campaign_resource.DoesResourceExist());

	m_campaign = MWCampaign::MakeNewCampaign(campaign_id);
	Check_Object(m_campaign);

	//Salvage
	ResourceID salvage_id(GameResourceFileID, SalvageResourceID);
	Resource salvage_resource(salvage_id);
	Verify(salvage_resource.DoesResourceExist());

	m_salvageManager = SalvageManager::MakeNewSalvageManager(salvage_id);
	Check_Object(m_salvageManager);

	//Lancemate
	ResourceID lancemate_id(GameResourceFileID, LancemateResourceID);
	Resource lancemate_resource(lancemate_id);
	Verify(lancemate_resource.DoesResourceExist());

	m_lancemates = LancemateManager::MakeNewLancemateManager(lancemate_id);
	Check_Object(m_lancemates);


	//Mission
	Resource mission_resource("{Mission}", m_gameResourceFile.GetCurrent());
	if(mission_resource.DoesResourceExist())
	{
		//this tells us that we have an in game save
		m_hasInGameSave = true;
	}
	m_hasInGameSave = false;

	//Mech and Lancemate setup
	ResourceID game_setup_id(GameResourceFileID, SetupResourceID);
	Resource game_setup_resource(game_setup_id);
	Verify(game_setup_resource.DoesResourceExist());

	//Mech Table
	ResourceID mech_table_id(GameResourceFileID, MechTableResourceID);
	Resource mech_table_resource(mech_table_id);
	Verify(mech_table_resource.DoesResourceExist());

	mech_table_resource.Rewind();
	CreateMechTable(&mech_table_resource);

	//MUST HAPPEN AFTER THE MECH TABLE IS CONSTRUCTED!
	game_setup_resource.Rewind();
	LoadGameSetup(&game_setup_resource);

	MWApplication::GetInstance()->SetDifficultyLevel(m_gameLevel);
	m_gameName = game_file_name;
	m_currentMechPlug = NULL;
//	InitializePilots(4);

	//Ok so here we want to react to finishing a mission....because we did at one point and
	//we want to reque all movies.
	
	//First check if we have killed anyone
	SortedChainIteratorOf<PilotPlug *, int> iterator(&m_lancePilots);
	PilotPlug *pilot;
	while((pilot = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(pilot);
		if(pilot->GetPilot())
		{
			if(pilot->GetPilot()->State() > 1)
			{
				m_campaign->m_movieManager->ExecuteLancemateReturn(pilot->GetPilot()->m_lancemateName);
			}	
			pilot->GetPilot()->State(LancematePlug::OK);
		}
	}
	//Second see if anyone is returning
	
	//DAVE MUST RETURN STUFF HERE

	//Third play all success movies
	if(m_campaign->m_lastMissionPlug->m_status == MWCampaign::Completed)
	{
		MString mission_name = m_campaign->m_lastMissionPlug->m_missionName;
		mission_name.StripDirectory();
		mission_name.StripExtension();
		m_campaign->m_movieManager->ExecuteMissionSuccess(mission_name);
	}

	m_hasLaunched = false;
	m_isNewGame = false;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MWGame::MWGame(const char *game_file_name, const char *campaign_name) :
	Plug(Plug::DefaultData),
	m_lancePilots(NULL, true),
	m_mechTable(NULL, true),
	m_gameResourceFile(NULL)
{
	//
	//----------------------------------------------
	//We need to open the resource file for our game
	//----------------------------------------------
	//
	MString res_path = "Resource\\Pilots\\";
	res_path += MWApplication::GetInstance()->m_pilotName;
	res_path += "\\Games\\";
	res_path += game_file_name;
	MString res_file = res_path;
	res_file += ".mw4";
//	MString dep_file = res_path;
//	dep_file += ".dep";
	
	Check_Object(ResourceManager::Instance);
	ResourceFile *resource_file = ResourceManager::Instance->OpenResourceFile(
		(const char *)res_file,
		NULL,
		GameResourceFileID,
		VER_CONTENTVERSION,
		false,
		true,
		false
	);
	Check_Object(resource_file);

	m_gameResourceFile.Add(resource_file);
	MString campaign_path = campaign_name;
	campaign_path.StripExtension();

	m_hasInGameSave = false;
	m_campaign = MWCampaign::MakeNewCampaign(campaign_name);
	Check_Object(m_campaign);

	MString salvage_name = campaign_path;
	salvage_name += ".salvage";
	m_salvageManager = SalvageManager::MakeNewSalvageManager(salvage_name);
	Check_Object(m_salvageManager);

	MString lancemate_name = campaign_path;
	lancemate_name += ".lancemate";
	m_lancemates = LancemateManager::MakeNewLancemateManager(lancemate_name);
	Check_Object(m_lancemates);

	m_mission = NULL;
	m_gameLevel = 1;
	MWApplication::GetInstance()->SetDifficultyLevel(m_gameLevel);

	//
	//------------------------------------------------------------
	//We need to create slots for all the resources in a save game
	//------------------------------------------------------------
	//
	Resource dependancy_resource((const char *)res_file, m_gameResourceFile.GetCurrent());
	DynamicMemoryStream dependancy_stream;
	MString dependancy_string = "";
	dependancy_stream << dependancy_string;
	dependancy_resource.Save(&dependancy_stream, NULL);

	Resource version_resource("{Version}", m_gameResourceFile.GetCurrent());
	DynamicMemoryStream version_stream;
	MString version_string = CURRENT_BUILD_FULL_STRING;
	version_stream << version_string;
	version_resource.Save(&version_stream, NULL);
	Verify(version_resource.GetResourceID().GetRecordID() == VersionResourceID);

	Resource game_data_resource("{GameData}", m_gameResourceFile.GetCurrent());
	game_data_resource.Save(NULL, NULL);
	Verify(game_data_resource.GetResourceID().GetRecordID() == GeneralGameResourceID);
	
	Resource campaign_resource("{Campaign}", m_gameResourceFile.GetCurrent());
	DynamicMemoryStream campaign_stream;
	m_campaign->Save(&campaign_stream);
	campaign_resource.Save(&campaign_stream, NULL);
	Verify(campaign_resource.GetResourceID().GetRecordID() == CampaignResourceID);

	Resource salvage_resource("{Salvage}", m_gameResourceFile.GetCurrent());
	DynamicMemoryStream salvage_stream;
	m_salvageManager->Save(&salvage_stream);
	salvage_resource.Save(&salvage_stream, NULL);
	Verify(salvage_resource.GetResourceID().GetRecordID() == SalvageResourceID);

	Resource lancemate_resource("{Lancemates}", m_gameResourceFile.GetCurrent());
	DynamicMemoryStream lancemate_stream;
	m_lancemates->Save(&lancemate_stream);
	lancemate_resource.Save(&lancemate_stream, NULL);
	Verify(lancemate_resource.GetResourceID().GetRecordID() == LancemateResourceID);

	Resource mission_resource("{Mission}", m_gameResourceFile.GetCurrent());
	mission_resource.Save(NULL, NULL);
	Verify(mission_resource.GetResourceID().GetRecordID() == MissionResourceID);

	Resource game_setup_resource("{GameSetup}", m_gameResourceFile.GetCurrent());
	game_setup_resource.Save(NULL, NULL);
	Verify(game_setup_resource.GetResourceID().GetRecordID() == SetupResourceID);

	Resource mech_table_resource("{MechTable}", m_gameResourceFile.GetCurrent());
	mech_table_resource.Save(NULL, NULL);
	Verify(mech_table_resource.GetResourceID().GetRecordID() == MechTableResourceID);

	m_gameName = game_file_name;
	
	m_currentMechPlug = NULL;
	InitializeMechTable(true);
	InitializePilots(4);

	m_hasLaunched = false;
	m_isNewGame = true;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MWGame::~MWGame()
{
	m_lancePilots.DeletePlugs();
	m_mechTable.DeletePlugs();
	if(m_lancemates)
		delete m_lancemates;
	if(m_salvageManager)
		delete m_salvageManager;
	if(m_gameResourceFile.GetCurrent())
		delete m_gameResourceFile.GetCurrent();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWGame::CreateMechTable(Stuff::MemoryStream *stream)
{
	Check_Pointer(stream);
	
	while(stream->GetBytesRemaining() > 0)
	{
		MechTablePlug *mech_plug = new MechTablePlug(stream);
		Check_Object(mech_plug);

		m_mechTable.AddValue(mech_plug, mech_plug->GetMechName());
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWGame::SaveMechTable(Stuff::MemoryStream *stream)
{
	Check_Pointer(stream);
	
	SortedChainIteratorOf<MechTablePlug *, MString> iterator(&m_mechTable);
	MechTablePlug *mech_plug;
	while((mech_plug = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(mech_plug);
		mech_plug->SaveMechTablePlug(stream);
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWGame::ConstructMWGameStream(NotationFile *notation_file, MemoryStream *stream)
{
	Check_Pointer(notation_file);
	Check_Pointer(stream);

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWGame::SaveInMissionGame()
{
	Check_Object(this);

	MString game_file_name = m_gameName;
	game_file_name += "(In Game)";

	if(m_hasInGameSave)
	{
		//This means we already have one so overwrite!
		SaveMWGame((const char *)game_file_name, true, true);
	}
	else
	{
		SaveMWGame((const char *)game_file_name, false, true);
	}

	m_hasInGameSave = true;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWGame::SaveMWGame(const char *game_file_name, bool overwrite, bool save_mission)
{
	Check_Object(this);
	Check_Pointer(game_file_name);
	
	//
	//----------------------------------------------
	//We need to open the resource file for our game
	//----------------------------------------------
	//
	MString res_path = "Resource\\Pilots\\";
	res_path += MWApplication::GetInstance()->m_pilotName;
	res_path += "\\Games\\";
	res_path += game_file_name;
	MString res_file = res_path;
	res_file += ".mw4";
//	MString dep_file = res_path;
//	dep_file += ".dep";

	//This is written this way because we do not have a save.  All Saves work like
	//Save As and therefore we must shut down the last file and open a new one.  If
	//we ever do have a save that overwrites a file of the same name this should
	//be removed

//	if(m_gameResourceFile)
//	{
	//	Check_Object(m_gameResourceFile);
	//	m_gameResourceFile->Save();
	//	delete m_gameResourceFile;
	//	m_gameResourceFile = NULL;
#if 0
		if(overwrite)
		{
			//We are to delete our last file.
			MString old_res_path = "Resource\\Pilots\\";
			old_res_path += MWApplication::GetInstance()->m_pilotName;
			old_res_path += "\\Games\\";
			old_res_path += m_gameName;
			MString old_res_file = old_res_path;
			old_res_file += ".mw4";

			gos_DeleteFile(old_res_file);
		}
#endif
//	}

#if 0
	Check_Object(ResourceManager::Instance);
	m_gameResourceFile = ResourceManager::Instance->OpenResourceFile(
		(const char *)res_file,
		NULL,
		GameResourceFileID,
		VER_CONTENTVERSION,
		false,
		true,
		false
	);
#endif
	//
	//------------------------------------------------------------
	//We need to create slots for all the resources in a save game
	//------------------------------------------------------------
	//
	{
	//	if(overwrite)
	//	{
			ResourceID dependancy_id(GameResourceFileID, 0);
	//	Resource dependancy_resource((const char *)res_file, m_gameResourceFile);
			Resource dependancy_resource(dependancy_id);
			dependancy_resource.ChangeName(res_file);
	//	}

	#if 0
		DynamicMemoryStream dependancy_stream;
		MString dependancy_string = "";
		dependancy_stream << dependancy_string;
		dependancy_resource.Save(&dependancy_stream, NULL);
	#endif

		Resource version_resource("{Version}", m_gameResourceFile.GetCurrent());
		DynamicMemoryStream version_stream;
		MString version_string = CURRENT_BUILD_FULL_STRING;
		version_stream << version_string;
		version_resource.Save(&version_stream, NULL);
		Verify(version_resource.GetResourceID().GetRecordID() == VersionResourceID);

		m_gameLevel = MWApplication::GetInstance()->GetDifficultyLevel();

		Resource game_data_resource("{GameData}", m_gameResourceFile.GetCurrent());
		DynamicMemoryStream game_data_stream;
		SaveGeneralGameData(&game_data_stream);
		game_data_resource.Save(&game_data_stream, NULL);
		Verify(game_data_resource.GetResourceID().GetRecordID() == GeneralGameResourceID);

		Resource campaign_resource("{Campaign}", m_gameResourceFile.GetCurrent());
		DynamicMemoryStream campaign_stream;
		m_campaign->Save(&campaign_stream);
		campaign_resource.Save(&campaign_stream, NULL);
		Verify(campaign_resource.GetResourceID().GetRecordID() == CampaignResourceID);

		Resource salvage_resource("{Salvage}", m_gameResourceFile.GetCurrent());
		DynamicMemoryStream salvage_stream;
		m_salvageManager->Save(&salvage_stream);
		salvage_resource.Save(&salvage_stream, NULL);
		Verify(salvage_resource.GetResourceID().GetRecordID() == SalvageResourceID);

		Resource lancemate_resource("{Lancemates}", m_gameResourceFile.GetCurrent());
		DynamicMemoryStream lancemate_stream;
		m_lancemates->Save(&lancemate_stream);
		lancemate_resource.Save(&lancemate_stream, NULL);
		Verify(lancemate_resource.GetResourceID().GetRecordID() == LancemateResourceID);

		if(save_mission)
		{
			Resource mission_resource("{Mission}", m_gameResourceFile.GetCurrent());
			DynamicMemoryStream mission_stream;
			Check_Object(Mission::GetInstance());
			Mission::GetInstance()->SaveMakeMessage(&mission_stream, m_gameResourceFile.GetCurrent());
			mission_resource.Save(&mission_stream, NULL);
			Verify(mission_resource.GetResourceID().GetRecordID() == MissionResourceID);
		}
		else
		{
			Resource mission_resource("{Mission}", m_gameResourceFile.GetCurrent());
			mission_resource.Save(NULL, NULL);
			Verify(mission_resource.GetResourceID().GetRecordID() == MissionResourceID);
			m_hasInGameSave = false;
		}

		Resource game_setup_resource("{GameSetup}", m_gameResourceFile.GetCurrent());
		DynamicMemoryStream game_setup_stream;
		SaveGameSetup(&game_setup_stream);
		game_setup_resource.Save(&game_setup_stream, NULL);
		Verify(game_setup_resource.GetResourceID().GetRecordID() == SetupResourceID);

		Resource mech_table_resource("{MechTable}", m_gameResourceFile.GetCurrent());
		DynamicMemoryStream mech_table_stream;
		SaveMechTable(&mech_table_stream);
		mech_table_resource.Save(&mech_table_stream, NULL);
		Verify(mech_table_resource.GetResourceID().GetRecordID() == MechTableResourceID);
	}
	
	m_gameResourceFile.GetCurrent()->SaveAs(res_file);

	if(overwrite)
	{
		//We are to delete our last file.
		MString old_res_path = "Resource\\Pilots\\";
		old_res_path += MWApplication::GetInstance()->m_pilotName;
		old_res_path += "\\Games\\";
		old_res_path += m_gameName;
		MString old_res_file = old_res_path;
		old_res_file += ".mw4";

		gos_DeleteFile(old_res_file);
	}

	if ((char *)m_gameName != game_file_name)
		m_gameName = game_file_name;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWGame::Reload()
{
	Check_Object(this);
	Check_Object(m_gameResourceFile.GetCurrent());
	
	//---------------------------------
	//We need to reset all of our parts
	//---------------------------------
	//

	//First check the version resource and verify this is a good save game
	ResourceID version_id(GameResourceFileID, VersionResourceID);
	Resource version_resource(version_id);
	Verify(version_resource.DoesResourceExist());

	MString version;
	version_resource >> version;

	MString curver = CURRENT_BUILD_FULL_STRING;

	if (version > curver)
	{
		PAUSE(("You are loading a game saved by a newer game version.  The saved game might not work correctly."));
	}

	//Campaign
	ResourceID campaign_id(GameResourceFileID, CampaignResourceID);
	Resource campaign_resource(campaign_id);
	Verify(campaign_resource.DoesResourceExist());

	m_campaign = MWCampaign::MakeNewCampaign(campaign_id);
	Check_Object(m_campaign);

	//Salvage
	ResourceID salvage_id(GameResourceFileID, SalvageResourceID);
	Resource salvage_resource(salvage_id);
	Verify(salvage_resource.DoesResourceExist());

	m_salvageManager = SalvageManager::MakeNewSalvageManager(salvage_id);
	Check_Object(m_salvageManager);

	//Lancemate
	ResourceID lancemate_id(GameResourceFileID, LancemateResourceID);
	Resource lancemate_resource(lancemate_id);
	Verify(lancemate_resource.DoesResourceExist());

	m_lancemates = LancemateManager::MakeNewLancemateManager(lancemate_id);
	Check_Object(m_lancemates);


	//Mission
	Resource mission_resource("{Mission}", m_gameResourceFile.GetCurrent());
	if(mission_resource.DoesResourceExist())
	{
		//this tells us that we have an in game save
		m_hasInGameSave = true;
	}
	m_hasInGameSave = false;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWGame::LoadMWGame(const char *game_file_name)
{
	Check_Pointer(game_file_name);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWGame::ReactToEndMission(bool success)
{
	Check_Object(this);
	Check_Object(m_campaign);
	Check_Object(m_campaign->m_currentMissionPlug);

	if(m_hasLaunched)
	{
		//if we have succeded then we must mark the mission a success and save
		//We also must check the status of the lancemates(this will be set by their deaths)
		Check_Object(MWMission::GetInstance());
		MWMission *mission = Cast_Object(MWMission*,MWMission::GetInstance());
		
        EarlyReactToEndMission(); // jcem

		m_hasLaunched = false;
		int name_index = m_campaign->m_currentMissionPlug->m_displayNameIndex;
		MString file_name = MWApplication::GetInstance()->GetLocString(name_index);

		if(mission->EndMissionState())
		{
			//We have succeeded!
			m_campaign->MissionSuccess();	
			char *completed_string = MWApplication::GetInstance()->GetLocString(IDS_COMPLETEDLOC);
			file_name += completed_string;

			//First run through the mechs and mark the damaged ones to being ready
			SortedChainIteratorOf<MechTablePlug *, MString> mech_iterator(&m_mechTable);
			MechTablePlug *mech_plug;
			while((mech_plug = mech_iterator.ReadAndNext()) != NULL)
			{
				if(mech_plug->GetStatus() == MechTablePlug::DamagedStatus)
					mech_plug->SetStatus(MechTablePlug::ReadyStatus);
			}
			//Here we should run through and reset damaged mechs to being fixed and set mechs
			//to being damaged if the have been damaged in the game past a certain point.
			std::vector<MWObject*> members;
			MW4AI::Groups::GetLancemates(members, true);
			std::vector<MWObject*>::iterator i = members.begin();
			int damage_count = 0;
			while((i != members.end()) && (damage_count < 2))
			{
				Mech *lance_mech = Cast_Object(Mech *, *i);

				if(lance_mech->IsDestroyed())
				{
                  if (!g_bCOOP) // jcem
					lance_mech->m_mechTablePlug->SetStatus(MechTablePlug::DestroyedStatus);
				}
				else
				{
				//First check mech damage
					MWInternalDamageObject *center_torso = lance_mech->internalDamageObjects.Find(InternalDamageObject::CenterTorsoZone);
					if(center_torso)
					{
						if(center_torso->CanRepair())
						{
							lance_mech->m_mechTablePlug->SetStatus(MechTablePlug::DamagedStatus);
							damage_count ++;
						}
					}
				}
				i++;
			}

			//If we are the last mission then don't save
			if(!m_campaign->m_currentMissionPlug->m_doesEnd)
			{
				//If we have saved in the middle
				if(m_hasInGameSave)
					SaveMWGame(file_name, true);
				else
					SaveMWGame(file_name, false);
			}
			else
			{
				MWApplication::GetInstance()->m_campaignIsComplete = true;
			}
		}
		else
		{
		//If we have failed then we need to do a "re-load" to erase all of their failing
		//progress.
			//We need to write the file out since we opened with an overwrite
		//	m_gameResourceFile->Save();
			MString res_path = "Resource\\Pilots\\";
			res_path += MWApplication::GetInstance()->m_pilotName;
			res_path += "\\Games\\";
			res_path += file_name;
			MString res_file = res_path;
			res_file += ".mw4";
			m_gameResourceFile.GetCurrent()->SaveAs(res_file);
		}

//		m_campaign->m_currentMissionPlug = NULL;
    }
}

void MWGame::EarlyReactToEndMission()
{
    MWApplication* app = MWApplication::GetInstance();
  if (0 < app->m_nCamp_Stage) {
	if(m_hasLaunched)
	{
		//if we have succeded then we must mark the mission a success and save
		//We also must check the status of the lancemates(this will be set by their deaths)
		Check_Object(MWMission::GetInstance());
		MWMission *mission = Cast_Object(MWMission*,MWMission::GetInstance());
		
        MechTablePlug *mech_plug = MWGame::GetInstance()->GetPilotLeader()->GetMechPlug();
	    Check_Object(mech_plug);


        // from here jcem
        if (mission) {
            app->m_nCamp_Time += (int)(mission->GetMissionTime() * 1000);
        }
        app->m_nCamp_Mech = mech_plug->m_mechID;

        int nCamp_Stage_Saved = app->m_nCamp_Stage;
        app->CheckCampaignEnd(); // jcem - m_nCamp_Stage will be changed...

		NotationFile highscore_ini("highscore.ini", NotationFile::Standard, true);
		Page *page = highscore_ini.SetPage("single");
        Note* pNote = page->SetNote("last");
        char sz[100];
        sprintf(sz, "%s,%d,%d,%d,%d,%d,%d,%d",
                "", // pilot name...
                nCamp_Stage_Saved,
                app->m_nCamp_Score, app->m_nCamp_Kills, app->m_nCamp_Deaths,
                app->m_nCamp_Time, app->m_nCamp_Mech, app->m_bCamp_Success);
        pNote->SetEntry(sz);
        highscore_ini.Save();
        // to here jcem
    } else {
        // already processed?
      #if 0
        // from here jcem
        NotationFile highscore_ini("highscore.ini", NotationFile::Standard, true);
		Page *page = highscore_ini.FindPage("single");
        if (page) {
            Note* pNote = page->FindNote("last");
            if (pNote)
                pNote->SetEntry("");
        }
        highscore_ini.Save();
        // from here jcem
      #endif
    }
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWGame::StartMission(char *mission_name)
{
	Check_Object(this);

	//Tell the campaign what the new mission is!
	CampaignMissionPlug *mission_plug;
	MString mission_path = "content\\missions\\";
	mission_path += mission_name;
	mission_path += "\\";
	mission_path += mission_name;
	mission_path += ".instance";

	m_hasLaunched = true;
	mission_plug = m_campaign->FindMission(mission_path);
	Check_Object(mission_plug);

	int maxlance,count;
	maxlance = mission_plug->m_NumLancemates;

	SortedChainIteratorOf<PilotPlug *, int> iterator(&m_lancePilots);
	PilotPlug *pilot_plug;
	count = 0;
	while((pilot_plug = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(pilot_plug);
		if (count>maxlance)
		{
			pilot_plug->SetLancePlug (NULL);
		}
		count++;
	}
	
	//Save the mission and overwrite the (Completed) one!
	m_campaign->m_currentMissionPlug = mission_plug;
	MString game_name = MWApplication::GetInstance()->GetLocString(mission_plug->m_displayNameIndex);
	char *completed_string = MWApplication::GetInstance()->GetLocString(IDS_COMPLETEDLOC);
	if(strstr((const char *)m_gameName, completed_string))
		SaveMWGame((char *)game_name, true);
	else
		SaveMWGame((char *)game_name, false);

	m_currentMechPlug = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWGame::InitializePilots(int num)
{
	Check_Object(this);

	m_lancePilots.DeletePlugs();
	//Create and add the first plug as the player (leader)
	PilotPlug *leader_plug =  new PilotPlug(NULL, true);
	Check_Object(leader_plug);

	m_lancePilots.AddValue(leader_plug, 0);

	MechTablePlug *mech_plug;
	SortedChainIteratorOf<MechTablePlug *, MString> iterator(&m_mechTable);
	mech_plug = iterator.GetCurrent();
	if(mech_plug)
		leader_plug->SetMech(mech_plug);

	for(int i=1; i<num; i++)
	{
		PilotPlug *plug = new PilotPlug(NULL);
		Check_Object(plug);

		m_lancePilots.AddValue(plug, i);
	}

	m_currentPilot = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
PilotPlug*
	MWGame::GetPilot(int id)
{
	Check_Object(this);
	Verify(id < m_lancePilots.GetSize());

	return m_lancePilots.Find(id);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MWGame::SetLancemate(int lance_id, char *lance_name)
{

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MWGame::SetLancemateMech(int lance_id, char *mech_name)
{
	Check_Object(this);
	Check_Pointer(mech_name);

	Check_Object(this);
	Verify(lance_id >= 0);

	MechTablePlug *mech_plug = m_mechTable.Find(mech_name);

	PilotPlug *current_pilot_plug = GetPilot(lance_id);
	Check_Object(current_pilot_plug);

	if(mech_plug)
	{
		//First we need to see if someone is already him!  If so make him ""
		SortedChainIteratorOf<PilotPlug *, int> iterator(&m_lancePilots);
		PilotPlug *pilot_plug;
		while((pilot_plug = iterator.ReadAndNext()) != NULL)
		{
			Check_Object(pilot_plug);
			if(pilot_plug->GetMechPlug())
			{
				if(!_stricmp(pilot_plug->GetMechPlug()->GetMechName(), mech_name))
				{
					pilot_plug->SetMech(NULL);
				}
			}
		}
	}
	//Then we need to make our new assignment!
	current_pilot_plug->SetMech(mech_plug);
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWGame::SetPilot(int lance_id, const MString& lance_name)
{
	Check_Object(this);
	Verify(lance_id >= 0);

	LancematePlug *lance_plug = m_lancemates->FindLancemate(lance_name);

	PilotPlug *current_pilot_plug = GetPilot(lance_id);
	Check_Object(current_pilot_plug);

	//First we need to see if someone is already him!  If so make him ""
	SortedChainIteratorOf<PilotPlug *, int> iterator(&m_lancePilots);
	PilotPlug *pilot_plug;
	while((pilot_plug = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(pilot_plug);
		if(pilot_plug->GetPilot())
		{
			if(pilot_plug->GetPilot()->m_lancemateName == lance_name)
			{
				pilot_plug->SetLancePlug(NULL);
			}
		}
	}
	//Then we need to make our new assignment!
	current_pilot_plug->SetLancePlug(lance_plug);

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MWGame::VerifyLaunchData()
{
	Check_Object(this);

	//This is to make sure that the have mechs and such set before clicking launch

	PilotPlug *pilot_plug;

	int maxlance,count;
	maxlance = m_campaign->m_currentMissionPlug->m_NumLancemates;

	SortedChainIteratorOf<PilotPlug *, int> iterator(&m_lancePilots);
	count = 0;
	while((pilot_plug = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(pilot_plug);
		if (count>maxlance)
		{
			pilot_plug->SetLancePlug (NULL);
			pilot_plug->SetMech(NULL);
		}
		count++;
	}

	iterator.First();
	while((pilot_plug = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(pilot_plug);
		if(pilot_plug->IsPlayer())
		{
			//we are the player...just verify we have a mech!
			if(!pilot_plug->GetMechPlug())
			{
				return E_NoPlayerMechSelected;  //Player does not have a mech assigned
			}
		}
		else
		{
			//we are a lance...make sure that we have both pilot and mech or none
			if(!pilot_plug->GetPilot() && pilot_plug->GetMechPlug())
			{
				return E_NoLancemateLanceSelected;
			}
			if(!pilot_plug->GetMechPlug() && pilot_plug->GetPilot())
			{
				return E_NoLancemateMechSelected;
			}
		}
	}

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWGame::GetAndAddMechInstance(const char *salvage_string, int is_new)
{
	Check_Pointer(salvage_string);

	//First dig out the instance resource of the thing we are adding.
//	MWTable *mech_table;
	Check_Object(MWApplication::GetInstance());
	Check_Object(MWApplication::GetInstance()->m_mechTable);
	
//	mech_table = MWApplication::GetInstance()->m_mechTable;
	MWTableEntry *mech_entry = MWApplication::GetInstance()->m_mechTable->FindEntry(salvage_string);

	Check_Object(mech_entry);

	Resource mech_resource(mech_entry->GetEntryResourceID());
	Verify(mech_resource.DoesResourceExist());

	//Name the resourece and make sure that it will be unique
	char original_name[256];
	sprintf(original_name, "%s%d",salvage_string, m_mechTable.GetSize());

	Resource new_mech_resource(original_name, m_gameResourceFile.GetCurrent());
	new_mech_resource.Save(NULL, NULL);

	//Save the resource
	mech_resource.Rewind();
//	Stuff::FileDependencies dependancies;
//	dependancies.AddDependency("");
	new_mech_resource.Save(&mech_resource, NULL);

	//create an entry in the mech table
	MString new_mech_name = original_name;
	Mech::CreateMessage *mech_create_message;
	mech_create_message = Cast_Pointer(Mech::CreateMessage *, mech_resource.GetPointer());
	Resource model_resource;
	Entity::GetGameModelResourceFromDataListID(&model_resource, mech_create_message->dataListID);
	Mech::GameModel *mech_model = Cast_Pointer(Mech::GameModel *, model_resource.GetPointer());
	MechTablePlug *mech_plug = new MechTablePlug(new_mech_resource.GetResourceID(), new_mech_name, mech_model->mechID, is_new);
	Check_Object(mech_plug);

	m_mechTable.AddValue(mech_plug, mech_plug->GetMechName());
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWGame::AddMechInstance(Mech *mech)
{
	Check_Object(mech);

	//First make the alignment to Player
	mech->m_doesHaveInstanceName = true;
	mech->m_localizeIndex = -1;
	mech->executionState->RequestState(Mech::ExecutionStateEngine::NeverExecuteState);
	mech->SetAlignment(Entity::Player);
	mech->ReuseArmature();
	Resource sub_resource(mech->subsystemStreamResourceID);
	Verify(sub_resource.DoesResourceExist());
	mech->ReuseSubsystems(&sub_resource);
	//Name the resourece and make sure that it will be unique
	char original_name[256];
	MString model_name = mech->GetModelName();
	model_name.StripExtension();
	model_name.StripDirectory();
	sprintf(original_name, "%s%d",(char*)model_name, m_mechTable.GetSize());

	Resource new_mech_resource(original_name, m_gameResourceFile.GetCurrent());
	new_mech_resource.Save(NULL, NULL);

	DynamicMemoryStream stream;
	//Fake it from thinking that it is dead
	mech->ClearDestroyedFlag();
	mech->SaveMakeMessage(&stream, m_gameResourceFile.GetCurrent());
	//Make it dead again.
	mech->SetDestroyedFlag(InternalDamageObject::DestructionDamageMode);
	stream.Rewind();
	Mech::CreateMessage *mech_message = Cast_Pointer(Mech::CreateMessage *, stream.GetPointer());
	mech_message->initialAge = 0.0f;
	mech_message->teamDecal = 2;
	mech_message->pilotDecal = 2;

	if(mech->GetSearchLight())
		mech->GetSearchLight()->SyncMatrices(true);

	//Save the resource
//	Stuff::FileDependencies dependancies;
//	dependancies.AddDependency("");
	
	new_mech_resource.Save(&stream, NULL);

	//create an entry in the mech table
	MString new_mech_name = original_name;
	const Mech::GameModel *mech_model = mech->GetGameModel();
	Check_Object(mech_model);

	MechTablePlug *mech_plug = new MechTablePlug(new_mech_resource.GetResourceID(), new_mech_name, mech_model->mechID);
	Check_Object(mech_plug);

	m_mechTable.AddValue(mech_plug, mech_plug->GetMechName());
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWGame::InitializeMechTable(bool new_campaign)
{
	Check_Object(m_salvageManager);
	
	ChainIteratorOf<PlugOf<MString>*> iterator(&m_salvageManager->m_mechSalvageNames);
	PlugOf<MString> *name_plug;
	while((name_plug = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(name_plug);
		if(new_campaign)
			GetAndAddMechInstance(name_plug->GetItem(), 0);
		else
			GetAndAddMechInstance(name_plug->GetItem());
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWGame::LoadGeneralGameData(Stuff::MemoryStream *stream)
{
	Check_Object(this);
	Check_Pointer(stream);

	*stream >> m_gameLevel;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWGame::SaveGeneralGameData(Stuff::MemoryStream *stream)
{
	Check_Object(this);
	Check_Pointer(stream);

	*stream << m_gameLevel;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWGame::LoadGameSetup(Stuff::MemoryStream *stream)
{	
	Check_Object(this);
	Check_Pointer(stream);

	//This is used to store the last setup of mechs and lances the user had.  It will also
	//store some other information too.
	int i = 0;
//	int num_pilots;
//	*stream >> num_pilots;
	while(stream->GetBytesRemaining() > 0)
	{
		bool is_leader;
		*stream >> is_leader;

		PilotPlug *pilot_plug = new PilotPlug(NULL, is_leader);
		//Ok I hope that this works right
		MString mech_plug_name;
		*stream >> mech_plug_name;
		if(mech_plug_name)
		{
			MechTablePlug *mech_plug = m_mechTable.Find(mech_plug_name);
			if(mech_plug)
				pilot_plug->SetMech(mech_plug);
		}

		MString lance_plug_name;
		*stream >> lance_plug_name;
		if(lance_plug_name)
		{
			LancematePlug *lance_plug = m_lancemates->FindLancemate(lance_plug_name);
			if(lance_plug)
				pilot_plug->SetLancePlug(lance_plug);
		}

		m_lancePilots.AddValue(pilot_plug, i);
		i++;
	}

	//Seed the rest so that they are empty.
//	for(int j=i; j<num_pilots; j++)
//	{
//		PilotPlug *pilot_plug = new PilotPlug(NULL, false);
//		m_lancePilots.AddValue(pilot_plug, i);
//	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWGame::SaveGameSetup(Stuff::MemoryStream *stream)
{
	Check_Object(this);
	Check_Pointer(stream);

	SortedChainIteratorOf<PilotPlug *, int> iterator(&m_lancePilots);
	PilotPlug *pilot;
//	*stream << m_lancePilots.GetSize();
	while((pilot = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(pilot);
		pilot->SavePilotToStream(stream);
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWGame::ResetSalvageManager()
{
	Check_Object(this);
	if(m_salvageManager)
		delete m_salvageManager;

	ResourceID salvage_id(GameResourceFileID, SalvageResourceID);
	Resource salvage_resource(salvage_id);
	Verify(salvage_resource.DoesResourceExist());

	m_salvageManager = SalvageManager::MakeNewSalvageManager(salvage_id);
	Check_Object(m_salvageManager);
}