#include "..\..\source\fun3d\ScriptUtils.h"

#include <crtdbg.h>

/*
	demo03Mission

	This is for the 12/15/98 demo

*/


class demo03Mission {
public:
	demo03Mission(void);
	~demo03Mission();

	bool Load(void);
	bool PostLoad(void);
	bool Save(void);

	void Update(void);

	void AddObject(Handle h);

private:
	void Setup(void);
	void Execute(void);
/*
	Here is where you add the variables.	
*/

	// bools
	union {
		struct {
			bool

				start_done,
				walker_stop,
				camera_1, camera_done,
				second_wave, next_wave,
				win_mission, loose_mission, mission_over,
				message_1,
				Ftank_2_attack, Ftank_4_attack, Ftank_6_attack,
				walker_1_dead,
				at_nav, attack_bridge, bridge_destroyed,
				at_nav_2, fight, fighter_dead, fight_again, fight2,
				b_last;

		};
		bool b_array[22];
	};

	// floats
	union {
		struct {
			float

				f1,
				camera_time,
				wave1_time, wave2_time, wave3_time,
				end_mission_check,
				at_nav_check,
				distance_check,
				nav_2_check,
				f_last;

		};
		float f_array[9];
	};

	// handles
	union {
		struct {
			Handle

				player,
				h1,
				nav_1, nav_2,
				walker_1, walker_2, walker_3,
				service_truck,
				Ftank_1, Ftank_2, Ftank_3, Ftank_4, Ftank_5, Ftank_6,
				Ftank_extra,
				bridge, fighter,
				h_last;
		};
		Handle h_array[17];
	};

	// integers
	union {
		struct {
			int

				i1,
				end_check,
				audiomessage_1,
				n2_dist,
				i_last;
		};
		int i_array[4];
	};
};

bool missionSave;
demo03Mission *mission;

void demo03Mission::Setup(void)
{
/*
	Here's where you set the values at the start.  
*/

	start_done = false;
	camera_1 = false;
	camera_done = false;
	walker_stop = false;
	second_wave = false;
	next_wave = false;
	win_mission = false;
	loose_mission = false;
	mission_over = false;
	message_1 = false;
	Ftank_2_attack = false;
	Ftank_4_attack = false;
	Ftank_6_attack = false;
	walker_1_dead = false;
	at_nav = false;
	attack_bridge = false;
	bridge_destroyed = false;
	at_nav_2 = false;
	fight = false;
	fighter_dead = false;
	fight_again = false;
	fight2 = false;

	wave1_time = 999999.9f;
	camera_time = 999999.9f;
	wave2_time = 999999.9f;
	wave3_time = 999999.9f;
	at_nav_check = 240.0f;
	end_mission_check = 999999.f;
	distance_check = 999999.9f;
	nav_2_check = 3.0f;

	player = GetPlayerHandle();
	nav_1 = GetHandle("nav_1");
	nav_2 = GetHandle("nav_2");
	walker_1 = GetHandle("walker_1");
	walker_2 = GetHandle("walker_2");
	walker_3 = NULL; // GetHandle("walker_3");
	service_truck = NULL; // GetHandle("service_truck");
	Ftank_1 = NULL;
	Ftank_2 = NULL;
	Ftank_3 = NULL;
	Ftank_4 = NULL;
	Ftank_5 = NULL;
	Ftank_6 = NULL;
	Ftank_extra = NULL;
	bridge = GetHandle("bridge");
	fighter = NULL;


}

void demo03Mission::AddObject(Handle h)
{
}

void demo03Mission::Execute(void)
{
/*
	Here is the execute loop
*/

// This is the opening cineractive setting up the walkers////////

	if (IsAlive(nav_1))
	{
		if (GetHealth(nav_1) < 0.80f)
		{
			AddHealth(nav_1, 500.0f);
		}
	}

	if (IsAlive(nav_2))
	{
		if (GetHealth(nav_2) < 0.80f)
		{
			AddHealth(nav_2, 500.0f);
		}
	}

	if (!IsAlive(Ftank_2))
	{
		Ftank_2_attack = false;		 
	}
	if (!IsAlive(Ftank_4))
	{
		Ftank_4_attack = false;		 
	}
	if (!IsAlive(Ftank_6))
	{
		Ftank_6_attack = false;		 
	}

	if (!walker_stop)
	{
		if (IsAlive(walker_1))
		{
			Stop(walker_1);
		}
		if (IsAlive(walker_2))
		{
			Stop(walker_2);
		}

		CameraReady();
		camera_time = GetTime() + 20.0f;
		audiomessage_1 = AudioMessage("Demo0301.wav");

		walker_stop = true;
	}

	if ((!camera_done) && (walker_stop))
	{
		if (IsAlive(walker_2))
		{
			CameraPath("camera_path", 400, 300, walker_1);
			camera_1 = true;
		}
	}

	if ((!camera_done) && (camera_1))
	{
//		if (CameraCancelled())
//		{
//			CameraFinish();
//			StopAudioMessage(audiomessage_1);
//			camera_done = true;
//		}
		if ((camera_time < GetTime()) && (!camera_done))
		{
			CameraFinish();
			camera_done = true;
		}
	}

//////Starts walkers to nav//////////////////////////////////////

	if (camera_done)
	{
		if (!message_1)
		{
//			AudioMessage("Demo0302.wav");

			if (IsAlive(walker_1))
			{
				if (IsAlive(nav_1))
				{
					Goto(walker_1, nav_1);
				}

				if (IsAlive(walker_2))
				{
					Follow(walker_2, walker_1);
				}
			}

			wave1_time = GetTime() + 15.0f;
			message_1 = true;
		}

		if (!walker_1_dead)
		{
			if ((!IsAlive(walker_1)) && (IsAlive(walker_2)) && (IsAlive(nav_1)))
			{
				Goto(walker_2, nav_1);
				walker_1_dead = true;
			}
		}
	}


/////// indicates when player is at nav_2/////////////////////

	if (IsAlive(nav_2))
	{
		if ((!at_nav_2) && (GetTime() > nav_2_check))
		{
			nav_2_check = GetTime() + 3.0f;
			n2_dist = GetDistance(player, nav_2);

			if (n2_dist < 100.0f)
			{
				StartCockpitTimer(5, 3, 1);
				at_nav_2 = true;
			}
		}

		if ((at_nav_2) && (GetCockpitTimer() == 0) && (!fight))
		{
			AudioMessage("Demo0306.wav"); // FIGHT!
			HideCockpitTimer();
			fighter = BuildObject("fvtank", 2, "fight_spawn");
			fight = true;
		}


		
		if ((fight) && (!IsAlive(fighter)) && (!fighter_dead))
		{
			nav_2_check = GetTime() + 10.0f;
			fight2 = false;
			fighter_dead = true;
		}

		if ((!fight_again) && (fighter_dead) && (GetTime() > nav_2_check))
		{
			nav_2_check = GetTime() + 3.0f;
			n2_dist = GetDistance(player, nav_2);

			if (n2_dist < 100.0f)
			{
				StartCockpitTimer(5, 3, 1);
				fight_again = true;
			}
		}

		if ((fight_again) && (GetCockpitTimer() == 0) && (!fight2))
		{
			AudioMessage("Demo0306.wav"); // FIGHT!
			HideCockpitTimer();
			fighter = BuildObject("fvtank", 2, "fight_spawn");
			fight2 = true;
			fight_again = false;
			fighter_dead = false;
		}

	}
///////Starts the first attack wave of furies/////////////////
		if ((!start_done) && (GetTime() > wave1_time))
	{
		Ftank_1 = BuildObject("fvtank01", 2, "spawn_1");
		Ftank_2 = BuildObject("fvtank01", 2, "spawn_2");

		if (IsAlive(Ftank_1))
		{
			Goto(Ftank_1, "path_1");

			if (IsAlive(Ftank_2))
			{
				Follow(Ftank_2, Ftank_1);
			}
		}

//			AudioMessage("wohoo.wav"); // test
		distance_check = GetTime() + 10.0f;
		wave1_time = GetTime() + 240.0f;
		start_done = true;
	}

	//starts the second attack wave of furies 4 minutes after the first
	if ((start_done) && (!second_wave) && (wave1_time < GetTime()))
	{
		Ftank_3 = BuildObject("fvtank01", 2, "spawn_1");
		Ftank_4 = BuildObject("fvtank01", 2, "spawn_2");
		Ftank_extra = BuildObject("fvtank01", 2, "spawn_3");

		if (IsAlive(Ftank_3))
		{
			Goto(Ftank_3, "path_1");

			if (IsAlive(Ftank_4))
			{
				Follow(Ftank_4, Ftank_3);

				if (IsAlive(Ftank_extra))
				{
					Follow(Ftank_extra, Ftank_4);
				}
			}
		}

//			AudioMessage("wohoo.wav"); // test
		wave1_time = GetTime() + 240.0f;
		second_wave = true;
	}

	//sends attack waves of furies every 4 minutes after the second
	if ((second_wave) && (!next_wave) && (wave1_time < GetTime()))
	{
		Ftank_5 = BuildObject("fvtank", 2, "spawn_1");
		Ftank_6 = BuildObject("fvtank01", 2, "spawn_2");

		if (IsAlive(Ftank_5))
		{
			Goto(Ftank_5, "path_1");

			if (IsAlive(Ftank_6))
			{
				Follow(Ftank_6, Ftank_5);
			}
		}

//			AudioMessage("wohoo.wav"); // test
		wave1_time = GetTime() + 240.0f;
		next_wave = true;
	}

	if ((next_wave) && (wave1_time < GetTime()))
	{
		wave1_time = GetTime() + 1.0f;
		next_wave = false;
	}

////////this is sending the furies after the walkers if they get within a certain range///////

	if (distance_check < GetTime())
	{
		distance_check = GetTime() + 10.0f;

		if ((!Ftank_2_attack) && (IsAlive(Ftank_2)) && (IsAlive(walker_2)))
		{
			if (GetDistance(Ftank_2, walker_2) < 100.0f)
			{
				Attack(Ftank_2, walker_2);
//					AudioMessage("wohoo.wav"); // test
				Ftank_2_attack = true;
			}
		}
		else if ((!Ftank_2_attack) && (IsAlive(Ftank_2)) && (IsAlive(walker_1)))
		{
			if (GetDistance(Ftank_2, walker_1) < 100.0f)
			{
				Attack(Ftank_2, walker_1);
//					AudioMessage("wohoo.wav"); // test
				Ftank_2_attack = true;
			}
		}

		if ((!Ftank_4_attack) && (IsAlive(Ftank_4)) && (IsAlive(walker_2)))
		{
			if (GetDistance(Ftank_4, walker_2) < 100.0f)
			{
				Attack(Ftank_4, walker_2);
				Ftank_4_attack = true;
			}
		}
		else if ((!Ftank_4_attack) && (IsAlive(Ftank_4)) && (IsAlive(walker_1)))
		{
			if (GetDistance(Ftank_4, walker_1) < 100.0f)
			{
				Attack(Ftank_4, walker_1);
				Ftank_4_attack = true;
			}
		}

		if ((!Ftank_6_attack) && (IsAlive(Ftank_6)) && (IsAlive(walker_2)))
		{
			if (GetDistance(Ftank_6, walker_2) < 100.0f)
			{
				Attack(Ftank_6, walker_2);
				Ftank_6_attack = true;
			}
		}
		else if ((!Ftank_6_attack) && (IsAlive(Ftank_6)) && (IsAlive(walker_1)))
		{
			if (GetDistance(Ftank_6, walker_1) < 100.0f)
			{
				Attack(Ftank_6, walker_1);
				Ftank_6_attack = true;
			}
		}
	}


/////////This is chscking to see of either walker is close to the nav//////
	if (!mission_over) 
	{
		if ((!at_nav) && (at_nav_check < GetTime()))
		{
			at_nav_check = GetTime() + 10.0f;

			if ((IsAlive(walker_1)) && (IsAlive(nav_1)))
			{
				end_check = GetDistance(walker_1, nav_1);
				
				if (end_check < 50.0f)
				{
					at_nav = true;
				}
			}

			if ((!win_mission) && (IsAlive(walker_2)) && (IsAlive(nav_1)))
			{
				end_check = GetDistance(walker_2, nav_1);

				if (end_check < 50.0f)
				{
					at_nav = true;
				}
			}
		}
		
		// this tells the walkers to attack the bridge
		if ((at_nav) && (!attack_bridge))
		{
			if ((IsAlive(walker_1)) && (IsAlive(bridge)))
			{
				SetWeaponMask(walker_1, 4);
				Attack(walker_1, bridge);

				if (IsAlive(walker_2))
				{
					SetWeaponMask(walker_2, 4);
					Attack(walker_2, bridge);
				}
				
				AudioMessage("Demo0305.wav"); // get away from bridge
				attack_bridge = true;
			}
			else if ((!attack_bridge) && (IsAlive(walker_2)) && (IsAlive(bridge)))
			{
				SetWeaponMask(walker_2, 4);
				Attack(walker_2, bridge);
				AudioMessage("Demo0305.wav"); // get away from bridge
				attack_bridge = true;
			}
		}

		if ((!bridge_destroyed) && (attack_bridge) && (!IsAlive(bridge)))
		{
			bridge_destroyed = true;
			win_mission = true;
		}

		if (win_mission)
		{
			AudioMessage("Demo0303.wav"); // you win
			SucceedMission(GetTime() + 15.0f);
			mission_over = true;
		}
	}

	if ((!mission_over) && (!IsAlive(walker_1)) && (!IsAlive(walker_2)))
	{
		AudioMessage("Demo0304.wav"); // you loose
		FailMission(GetTime() + 15.0f);
		mission_over = true;
	}

}
demo03Mission::demo03Mission(void)
{
}

demo03Mission::~demo03Mission()
{
}

bool demo03Mission::Load(void)
{
	if (missionSave) {
		int i;

		// init bools
		int b_count = &b_last - b_array;
		_ASSERTE(b_count == SIZEOF(b_array));
		for (i = 0; i < b_count; i++)
			b_array[i] = false;

		// init floats
		int f_count = &f_last - f_array;
		_ASSERTE(f_count == SIZEOF(f_array));
		for (i = 0; i < f_count; i++)
			f_array[i] = 99999.0f;

		// init handles
		int h_count = &h_last - h_array;
		_ASSERTE(h_count == SIZEOF(h_array));
		for (i = 0; i < h_count; i++)
			h_array[i] = 0;

		// init ints
		int i_count = &i_last - i_array;
		_ASSERTE(i_count == SIZEOF(i_array));
		for (i = 0; i < i_count; i++)
			i_array[i] = 0;

		Setup();
		return true;
	}

	bool ret = true;

	// bools
/*
	int b_count = &b_last - b_array;
	_ASSERTE(b_count == SIZEOF(b_array));
	ret = ret && in(b_array, sizeof(b_array));

	// floats
	int f_count = &f_last - f_array;
	_ASSERTE(f_count == SIZEOF(f_array));
	ret = ret && in(f_array, sizeof(f_array));

	// Handles
	int h_count = &h_last - h_array;
	_ASSERTE(h_count == SIZEOF(h_array));
	ret = ret && in(h_array, sizeof(h_array));

	// ints
	int i_count = &i_last - i_array;
	_ASSERTE(i_count == SIZEOF(i_array));
	ret = ret && in(i_array, sizeof(i_array));
*/
	return ret;
}

bool demo03Mission::PostLoad(void)
{
	if (missionSave)
		return true;

	bool ret = true;

	int h_count = &h_last - h_array;
/*
	for (int i = 0; i < h_count; i++)
		h_array[i] = ConvertHandle(h_array[i]);
*/
	return ret;
}

bool demo03Mission::Save(void)
{
	if (missionSave)
		return true;

	bool ret = true;
/*
	// bools
	int b_count = &b_last - b_array;
	_ASSERTE(b_count == SIZEOF(b_array));
	ret = ret && out(b_array, sizeof(b_array), "b_array");

	// floats
	int f_count = &f_last - f_array;
	_ASSERTE(f_count == SIZEOF(f_array));
	ret = ret && out(f_array, sizeof(f_array), "f_array");

	// Handles
	int h_count = &h_last - h_array;
	_ASSERTE(h_count == SIZEOF(h_array));
	ret = ret && out(h_array, sizeof(h_array), "h_array");

	// ints
	int i_count = &i_last - i_array;
	_ASSERTE(i_count == SIZEOF(i_array));
	ret = ret && out(i_array, sizeof(i_array), "i_array");
*/
	return ret;
}

void demo03Mission::Update(void)
{
	Execute();
}

bool Save(bool misnSave)
{
	missionSave = misnSave;
	return mission->Save();
}

bool Load(bool misnSave)
{
	mission = new demo03Mission();
	missionSave = misnSave;
	return mission->Load();
}

bool PostLoad(bool misnSave)
{
	missionSave = misnSave;
	return mission->PostLoad();
}

void AddObject(Handle h)
{
	mission->AddObject(h);
}

void Update(void)
{
	mission->Update();
}

void PostRun(void)
{
	delete mission;
}

bool AddPlayer(DPID id, bool IsRemote)
{
	_ASSERTE(FALSE);
	return false;
}

void DeletePlayer(DPID id)
{
}

EjectKillRetCodes PlayerEjected(void)
{
	return DoEjectPilot;
}

EjectKillRetCodes PlayerKilled(int KillersHandle)
{
	return DoRespawnSafest;
}

static MisnExport misnExport;
MisnImport misnImport;

MisnExport * __cdecl GetMisnAPI(MisnImport *import)
{
	misnImport = *import;
	misnExport.version = LATEST_DLL_VERSION;
	misnExport.misnImport = &misnImport;
	misnExport.Save = Save;
	misnExport.Load = Load;
	misnExport.PostLoad = PostLoad;
	misnExport.AddObject = AddObject;
	misnExport.Update = Update;
	misnExport.PostRun= PostRun;
	misnExport.AddPlayer = AddPlayer;
	misnExport.DeletePlayer = DeletePlayer;
	misnExport.PlayerEjected = PlayerEjected;
	misnExport.PlayerKilled = PlayerKilled;
	return &misnExport;
}
