/*
**	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/>.
*/

#include "scripts.h"
#include "MissionX0.h"


// MX0 A02 PROTOTYPING SCRIPT SECTION

DECLARE_SCRIPT (MX0_A02_Controller, "")
{
	int MX0_A02_UNIT_ID [MX0_A02_ACTOR_HEADCOUNT];
	bool pre_ambient_on;
	bool ran_startup;
	bool player_retreat;
	bool sequence_active;
	bool prevent_spawns;
	bool retreat_sequence;
	bool call_heli_destroy_once;
	bool entered_tank;
	int havoc_entered_tank;
	int pre_ambient_count;
	int MX0_A02_HUMM_VEE_ID;
	int MX0_A02_MED_TANK_ID;
	int MX0_A02_GDI_APC_ID;
	int	MX0_A01_NOD_SNIPER_01;
	int MX0_A01_NOD_SNIPER_02;
	int MX0_A02_BLOCKAGE_ID;
	int nod_spawn_sequence;
	int current_nod_target;
	int engineer_01_id;
	int engineer_02_id;
	int congrats_loop;
	int soldier_congrats_loop;
	int death_counter;
	int wrong_way_count;

	REGISTER_VARIABLES()
	{
		SAVE_VARIABLE (MX0_A02_UNIT_ID, 1);
		SAVE_VARIABLE (pre_ambient_on, 2);
		SAVE_VARIABLE (pre_ambient_count, 3);
		SAVE_VARIABLE (MX0_A02_HUMM_VEE_ID, 4);
		SAVE_VARIABLE (MX0_A02_MED_TANK_ID, 5);
		SAVE_VARIABLE (MX0_A02_GDI_APC_ID, 6);
		SAVE_VARIABLE (MX0_A01_NOD_SNIPER_01, 7);
		SAVE_VARIABLE (MX0_A01_NOD_SNIPER_02, 8);
		SAVE_VARIABLE (player_retreat, 9);
		SAVE_VARIABLE (nod_spawn_sequence, 10);
		SAVE_VARIABLE (sequence_active, 11);
		SAVE_VARIABLE (current_nod_target, 12);
		SAVE_VARIABLE (prevent_spawns, 13);
		SAVE_VARIABLE (MX0_A02_BLOCKAGE_ID, 14);
		SAVE_VARIABLE (retreat_sequence, 15);
		SAVE_VARIABLE (call_heli_destroy_once, 16);
		SAVE_VARIABLE (havoc_entered_tank, 17);
		SAVE_VARIABLE (engineer_01_id, 18);
		SAVE_VARIABLE (engineer_02_id, 19);
		SAVE_VARIABLE (congrats_loop, 20);
		SAVE_VARIABLE (soldier_congrats_loop, 21);
		SAVE_VARIABLE (entered_tank, 22);
		SAVE_VARIABLE (death_counter, 23);
		SAVE_VARIABLE (wrong_way_count, 24);
		SAVE_VARIABLE (ran_startup, 25);
	}

	void Created (GameObject * obj)
	{
		ran_startup = false;
		pre_ambient_on = false;
		player_retreat = false;
		sequence_active = true;
		prevent_spawns = false;
		retreat_sequence = false;
		call_heli_destroy_once = false;
		entered_tank = false;
		havoc_entered_tank = 0;
		pre_ambient_count = 0;
		MX0_A02_HUMM_VEE_ID = 0;
		MX0_A02_MED_TANK_ID = 0;
		MX0_A02_GDI_APC_ID = 0;
		MX0_A01_NOD_SNIPER_01 = 0;
		MX0_A01_NOD_SNIPER_02 = 0;
		MX0_A02_BLOCKAGE_ID = 0;
		nod_spawn_sequence = 0;
		current_nod_target = 0;
		engineer_01_id = 0;
		engineer_02_id = 0;
		congrats_loop = 0;
		soldier_congrats_loop = 0;
		death_counter = 0;
		wrong_way_count = 1;
	}

	void Attach_Unit_Script (GameObject * unit, int count)
	{
		if (unit)
		{
			Commands->Attach_Script (unit, "MX0_A02_ACTOR", "0");
			MX0_A02_UNIT_ID [count] = Commands->Get_ID (unit);
			Commands->Send_Custom_Event (unit, unit, MX0_A02_CUSTOM_TYPE_REGISTER_ACTOR_ID, count, 0.1f);
		}
	}

	void Custom (GameObject * obj, int type, int param, GameObject * sender)
	{
		switch (type)
		{
		case (MX0_A02_CUSTOM_TYPE_MAIN_ENDING):
			{
				// Send shutoff announcements to all my registered actors.
				int count = 1;
				GameObject * actor = obj;
				while (count < MX0_A02_ACTOR_HEADCOUNT)
				{
					actor = Commands->Find_Object (MX0_A02_UNIT_ID [count]);
					if (actor)
					{
						Commands->Send_Custom_Event (obj, actor, MX0_A02_CUSTOM_TYPE_MAIN_ENDING, MX0_A02_CUSTOM_PARAM_DEFAULT);
					}
					count++;
				}
				//DEBUG send out the required A03 custom.
				Commands->Destroy_Object (obj);
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_HANDOFF_SNIPER_01_ID):
			{
				if (sender)
				{
					Commands->Send_Custom_Event (obj, sender, MX0_A02_CUSTOM_KILL_SNIPER_01, MX0_A01_NOD_SNIPER_01);
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_HANDOFF_SNIPER_02_ID):
			{
				if (sender)
				{
					Commands->Send_Custom_Event (obj, sender, MX0_A02_CUSTOM_KILL_SNIPER_02, MX0_A01_NOD_SNIPER_02);
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_GET_SNIPER_01_ID):
			{
				MX0_A01_NOD_SNIPER_01 = param;
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_GET_SNIPER_02_ID):
			{
				MX0_A01_NOD_SNIPER_02 = param;
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_MAIN_STARTUP):
			{
				if (!ran_startup)
				{
					ran_startup = true;
					GameObject * spawnloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_01);
					GameObject * unit = Commands->Find_Object (MX0_A02_MOVE_OBJ_01);
					if (spawnloc)
					{
						unit = Commands->Create_Object ("MX0_GDI_MiniGunner_0_B", Commands->Get_Position(spawnloc));
						Attach_Unit_Script (unit, 1);
						Commands->Attach_Script(unit, "M00_Send_Object_ID", "1400041,11,0.0f");
					}
					spawnloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_03);
					if (spawnloc)
					{
						unit = Commands->Create_Object ("MX0_GDI_MiniGunner_1Off", Commands->Get_Position(spawnloc));
						Attach_Unit_Script (unit, 2);
					}
					spawnloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_05);
					if (spawnloc)
					{
						unit = Commands->Create_Object ("MX0_GDI_RocketSoldier_1Off", Commands->Get_Position(spawnloc));
						Attach_Unit_Script (unit, 3);
					}
					spawnloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_07);
					if (spawnloc)
					{
						unit = Commands->Create_Object ("MX0_GDI_MiniGunner_0", Commands->Get_Position(spawnloc));
						Attach_Unit_Script (unit, 4);
					}
					spawnloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_09);
					if (spawnloc)
					{
						unit = Commands->Create_Object ("MX0_Nod_Minigunner_0", Commands->Get_Position(spawnloc));
						Attach_Unit_Script (unit, 5);
					}
					spawnloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_11);
					if (spawnloc)
					{
						unit = Commands->Create_Object ("MX0_Nod_Minigunner_0", Commands->Get_Position(spawnloc));
						Attach_Unit_Script (unit, 6);
					}
					spawnloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_13);
					if (spawnloc)
					{
						unit = Commands->Create_Object ("MX0_Nod_Minigunner_0", Commands->Get_Position(spawnloc));
						Attach_Unit_Script (unit, 7);
					}
					spawnloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_15);
					if (spawnloc)
					{
						unit = Commands->Create_Object ("MX0_Nod_Minigunner_0", Commands->Get_Position(spawnloc));
						Attach_Unit_Script (unit, 8);
					}
					pre_ambient_on = true;
					pre_ambient_count = 1;
					Commands->Start_Timer (obj, this, 1.0f, MX0_A02_TIMER_PRE_AMBIENT);

					GameObject * humm_vee = Commands->Create_Object ("MX0_GDI_Humm-Vee_destroyed", Vector3(-84.582f,-60.035f,1.050f));
					if (humm_vee)
					{
						Commands->Attach_Script (humm_vee, "MX0_A02_GDI_VEHICLE", "");
						Commands->Set_Facing (humm_vee, 50.0f);
						MX0_A02_HUMM_VEE_ID = Commands->Get_ID (humm_vee);
					}

					GameObject * med_tank = Commands->Create_Object ("MX0_GDI_Medium_Tank_Dec", Vector3(-90.183f,-51.691f,1.216f));
					if (med_tank)
					{
						Commands->Attach_Script (med_tank, "MX0_A02_GDI_VEHICLE", "");
						Commands->Set_Facing (med_tank, -20.0f);
						MX0_A02_MED_TANK_ID = Commands->Get_ID (med_tank);
					}
					GameObject * gdi_apc = Commands->Create_Object ("MX0_GDI_APC", Vector3(-101.576f,-54.945f,1.050f));
					if (gdi_apc)
					{
						Commands->Attach_Script (gdi_apc, "MX0_A02_GDI_APC", "");
						Commands->Set_Facing (gdi_apc, -45.0f);
						MX0_A02_GDI_APC_ID = Commands->Get_ID (gdi_apc);
					}

					GameObject * debris = Commands->Create_Object ("Simple_Level_x0_A02_Blockage", Vector3(-71.233f, -41.517f, 0.181f));
					if (debris)
					{
						MX0_A02_BLOCKAGE_ID = Commands->Get_ID (debris);
						Commands->Set_Facing (debris, -40.000f);
					}

					GameObject * a01_controller = Commands->Find_Object (MX0_A01_CONTROLLER_ID);
					if (a01_controller)
					{
						Commands->Send_Custom_Event (obj, a01_controller, MX0_A02_CUSTOM_TYPE_GET_SNIPER_01_ID, MX0_A02_CUSTOM_PARAM_DEFAULT);
						Commands->Send_Custom_Event (obj, a01_controller, MX0_A02_CUSTOM_TYPE_GET_SNIPER_02_ID, MX0_A02_CUSTOM_PARAM_DEFAULT);
					}
					Commands->Start_Timer (obj, this, 1.0f, MX0_A02_TIMER_RANDOM_EXPLOSIONS);
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_REQUEST_TARGET):
			{
				if (sender)
				{
					if (param < MX0_A02_ACTOR_NOD_START)
					{
						Commands->Send_Custom_Event (obj, sender, MX0_A02_CUSTOM_TYPE_REQUEST_TARGET, MX0_A02_UNIT_ID[Get_Int_Random(MX0_A02_ACTOR_NOD_START, (MX0_A02_ACTOR_HEADCOUNT - 1))]);
					}
					else
					{
						Commands->Send_Custom_Event (obj, sender, MX0_A02_CUSTOM_TYPE_REQUEST_TARGET, MX0_A02_UNIT_ID[Get_Int_Random(1, (MX0_A02_ACTOR_NOD_START - 1))]);
					}
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_STARTUP):
			{
				// Check if the First Nod Sniper is still alive. If so, send unit 03 after him.

				if (!player_retreat)
				{
					player_retreat = true;
					GameObject * sniper = Commands->Find_Object (MX0_A01_NOD_SNIPER_01);
					if (sniper)
					{
						GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[3]);
						if (soldier)
						{
							Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_KILL_SNIPER_01, MX0_A01_NOD_SNIPER_01);
						}
					}
					else
					{
						sniper = Commands->Find_Object (MX0_A01_NOD_SNIPER_02);
						if (sniper)
						{
							GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[3]);
							if (soldier)
							{
								Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_KILL_SNIPER_02, MX0_A01_NOD_SNIPER_02);
							}
						}
					}

					// Start greeting sequence with Unit 01.

					GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[1]);
					if (soldier)
					{
						Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_START_GDI_01, MX0_A02_CUSTOM_PARAM_DEFAULT);
					}

					// Tell the APC it's okay to start shooting.

					GameObject * apc = Commands->Find_Object (MX0_A02_GDI_APC_ID);
					if (apc)
					{
						Commands->Send_Custom_Event (obj, apc, MX0_A02_CUSTOM_TYPE_STARTUP, MX0_A02_CUSTOM_PARAM_DEFAULT);
					}
				}
			}

			// Pre ambient shuts off regardless when sequence is started.

		case (MX0_A02_CUSTOM_TYPE_PRE_AMBIENT_OFF):
			{
				pre_ambient_on = false;
				Commands->Start_Timer (obj, this, 1.0f, MX0_A02_TIMER_PLAYER_RETREAT);
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_CONTINUE):
			{
				// Make the Nod soldiers able to be killed.

				int nod_count = MX0_A02_ACTOR_NOD_START;
				GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[1]);
				while (nod_count < MX0_A02_ACTOR_HEADCOUNT)
				{
					soldier = Commands->Find_Object (MX0_A02_UNIT_ID[nod_count]);
					if (soldier)
					{
						Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_DAMAGE_ON, MX0_A02_CUSTOM_PARAM_DEFAULT);
					}
					nod_count++;
				}
				sequence_active = false;
				nod_spawn_sequence = 0;


				// Have the Nod Officer say something.
				Commands->Create_2D_Sound ("MX0_NODOFFICER_044");
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_START_GDI_02):
			{
				GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[2]);
				if (soldier)
				{
					Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_START_GDI_02, MX0_A02_CUSTOM_PARAM_DEFAULT);
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_START_GDI_03):
			{
				GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[1]);
				if (soldier)
				{
					Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_START_GDI_03, MX0_A02_CUSTOM_PARAM_DEFAULT);
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_START_GDI_04):
			{
				GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[2]);
				if (soldier)
				{
					Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_START_GDI_04, MX0_A02_CUSTOM_PARAM_DEFAULT);
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_START_GDI_05):
			{
				GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[3]);
				if (soldier)
				{
					Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_START_GDI_05, MX0_A02_CUSTOM_PARAM_DEFAULT);
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_PLAYER_KILLED_NOD):
			{
				GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[Get_Int_Random(1,4)]);
				if (soldier)
				{
					if (congrats_loop > 9)
					{
						congrats_loop = 0;
					}
					Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_PLAYER_CONGRATS, congrats_loop);
					congrats_loop++;
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_SOLDIER_KILLED_NOD):
			{

				GameObject * soldier = Commands->Find_Object (param);
				if (soldier)
				{
					if (soldier_congrats_loop > 3)
					{
						soldier_congrats_loop = 0;
					}
					Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_SOLDIER_CONGRATS, soldier_congrats_loop);
					soldier_congrats_loop++;
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_NEXT_SEQUENCE):
			{
				current_nod_target = 0;
				sequence_active = false;
				nod_spawn_sequence++;
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_NOD_SOLDIER_KILLED):
			{
				//Remove this soldier's record from the lineup.

				int count = MX0_A02_ACTOR_NOD_START + 1;
				int space_available = 0;

				while (count < MX0_A02_ACTOR_HEADCOUNT)
				{
					GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[count]);
					if ((count == param) || (!soldier))
					{
						MX0_A02_UNIT_ID[count] = 0;
					}
					if (MX0_A02_UNIT_ID[count] == 0)
					{
						death_counter++;
						space_available++;
					}
					count++;
				}

				if ((death_counter > 2) && (death_counter < 99))
				{
					death_counter = 99;
					Commands->Fade_Background_Music( "Level 0 Hero.mp3", 2, 2);
				}
				if (!retreat_sequence)
				{
					if (sequence_active)
					{
						if ((current_nod_target == param) && (current_nod_target))
						{
							current_nod_target = 0;
							sequence_active = false;
							nod_spawn_sequence++;
						}
					}
					if (!prevent_spawns)
					{
						prevent_spawns = true;

						if (!sequence_active)
						{
							//If the amount of unit space is adequate, increment the sequence and spawn the units. Tell them what they are to do.

							if (space_available)
							{
								switch (nod_spawn_sequence)
								{
								case(0): // Nod Guy falls off ledge after getting shot.
									{
										GameObject * soldier = Commands->Create_Object ("MX0_Nod_Minigunner_0", Vector3(-78.442f,-78.044f,6.404f));
										if (soldier)
										{
											space_available--;
											sequence_active = true;
											Commands->Attach_Script (soldier, "MX0_A02_ACTOR", "1");
											MX0_A02_Fill_Empty_Slot (soldier, true);
										}
										break;
									}
								case (1): // Second Nod guy falls off ledge after getting shot.
									{
										GameObject * soldier = Commands->Create_Object ("MX0_Nod_Minigunner_0", Vector3(-102.985f,-73.331f,4.415f));
										if (soldier)
										{
											space_available--;
											sequence_active = true;
											Commands->Attach_Script (soldier, "MX0_A02_ACTOR", "2");
											MX0_A02_Fill_Empty_Slot (soldier, true);
										}
										break;
									}
								case (2):
									{
										GameObject * soldier = Commands->Create_Object ("Nod_RocketSoldier_0", Vector3(-78.442f,-78.044f,6.404f));
										if (soldier)
										{
											space_available--;
											sequence_active = true;
											Commands->Attach_Script (soldier, "MX0_A02_ACTOR", "3");
											MX0_A02_Fill_Empty_Slot (soldier, false);
										}
										break;
									}
								case (3): // Nod Chopper drops 2 minigunners, not tracked.
									{
										GameObject * chinook_obj1 = Commands->Create_Object("Invisible_Object", Vector3(-71.497f,-47.387f,9.0f));
										if (chinook_obj1)
										{
											sequence_active = true;
											Commands->Set_Facing(chinook_obj1, -100.0f);
											Commands->Attach_Script(chinook_obj1, "MX0_A02_HELICOPTER", "0");
											Commands->Attach_Script(chinook_obj1, "Test_Cinematic", "X0I_Drop02_A02_E01.txt");
											Commands->Start_Timer (obj, this, 20.0f, MX0_A02_TIMER_AFTER_HELI_01);
										}
										GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[2]);
										if (soldier)
										{
											Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_GDI_NOTICES_HELI_01, MX0_A02_CUSTOM_PARAM_DEFAULT, 10.0f);
										}
										break;
									}
								case (4): // Next chopper arrives with FlameThrower infantry.
									{
										nod_spawn_sequence = 5;
										GameObject * chinook_obj1 = Commands->Create_Object("Invisible_Object", Vector3(-83.454f,-70.323f,9.60f));
										if (chinook_obj1)
										{
											sequence_active = true;
											Commands->Set_Facing(chinook_obj1, 90.0f);
											Commands->Attach_Script(chinook_obj1, "MX0_A02_HELICOPTER", "1");
											Commands->Attach_Script(chinook_obj1, "Test_Cinematic", "X0I_Drop02_A02_E02.txt");
										}
										GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[2]);
										if (soldier)
										{
											Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_GDI_NOTICES_HELI_02, MX0_A02_CUSTOM_PARAM_DEFAULT, 10.0f);
										}
										break;
									}
								default:
									{
										break;
									}
								}
							}
						}

						// Fill up any remaining space with generic units.

						if (space_available)
						{
							int count = MX0_A02_ACTOR_NOD_START;
							while (count < MX0_A02_ACTOR_HEADCOUNT)
							{
								if (!MX0_A02_UNIT_ID[count])
								{
									int spawnloc_id = 0;
									switch (count)
									{
									case (6):
										{
											spawnloc_id = MX0_A02_SPAWNER_01;
											break;
										}
									case (7):
										{
											spawnloc_id = MX0_A02_SPAWNER_02;
											break;
										}
									case (8):
										{
											spawnloc_id = MX0_A02_SPAWNER_03;
											break;
										}
									default:
										{
											break;
										}
									}
									GameObject * spawnloc = Commands->Trigger_Spawner (spawnloc_id);
									if (spawnloc)
									{
										Attach_Unit_Script (spawnloc, count);
										Commands->Send_Custom_Event (obj, spawnloc, MX0_A02_CUSTOM_TYPE_DAMAGE_ON, MX0_A02_CUSTOM_PARAM_DEFAULT, 0.1f);
										count = MX0_A02_ACTOR_HEADCOUNT;
									}
								}
								count++;
							}
						}
						Commands->Start_Timer (obj, this, 3.0f, MX0_A02_TIMER_PREVENT_SPAWNS);
					}
				}
				else
				{
					GameObject * spawner = Commands->Find_Object (MX0_A02_SPAWNER_01);
					if (spawner)
					{
						Commands->Destroy_Object (spawner);
					}
					spawner = Commands->Find_Object (MX0_A02_SPAWNER_02);
					if (spawner)
					{
						Commands->Destroy_Object (spawner);
					}
					spawner = Commands->Find_Object (MX0_A02_SPAWNER_03);
					if (spawner)
					{
						Commands->Destroy_Object (spawner);
					}
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_GDI_NOTICES_NOD_01):
			{
				// Make GDI 01 say something about the soldier spotted.

				GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[1]);
				if (soldier)
				{
					GameObject * target = Commands->Find_Object (MX0_A02_UNIT_ID[current_nod_target]);
					if (target)
					{
						Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_GDI_NOTICES_NOD_01, MX0_A02_CUSTOM_PARAM_DEFAULT);
					}
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_GDI_SHOOTS_NOD_01):
			{
				// Time for GDI to shoot at the first falling soldier.

				GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[2]);
				if (soldier)
				{
					GameObject * target = Commands->Find_Object (MX0_A02_UNIT_ID[current_nod_target]);
					if (target)
					{
						Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_GDI_SHOOTS_NOD_01, MX0_A02_UNIT_ID[current_nod_target]);
					}
				}

				break;
			}
		case (MX0_A02_CUSTOM_TYPE_GDI_RESPONDS_01):
			{
				// Make 01 say something about the falling soldier.

				GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[1]);
				if (soldier)
				{
					Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_GDI_RESPONDS_01, MX0_A02_CUSTOM_PARAM_DEFAULT);
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_GDI_SHOOTS_NOD_02):
			{
				// Time for GDI to shoot at the second falling soldier.

				GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[4]);
				if (soldier)
				{
					GameObject * target = Commands->Find_Object (MX0_A02_UNIT_ID[current_nod_target]);
					if (target)
					{
						Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_GDI_SHOOTS_NOD_02, MX0_A02_UNIT_ID[current_nod_target]);
					}
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_APC_BLOWITUP):
			{
				GameObject * apc = Commands->Find_Object (MX0_A02_GDI_APC_ID);
				if (apc)
				{
					Commands->Send_Custom_Event (obj, apc, MX0_A02_CUSTOM_TYPE_DESTROY_APC, MX0_A02_CUSTOM_PARAM_DEFAULT, 2.0f);
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_GET_APC_ID):
			{
				GameObject * apc = Commands->Find_Object (MX0_A02_GDI_APC_ID);
				if (apc)
				{
					if (sender)
					{
						Commands->Send_Custom_Event (obj, sender, MX0_A02_CUSTOM_TYPE_GET_APC_ID, MX0_A02_GDI_APC_ID);
					}
				}
				else
				{
					if (sender)
					{
						Commands->Send_Custom_Event (obj, sender, MX0_A02_CUSTOM_TYPE_GET_APC_ID, 0);
					}
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_HELI_DESTROYED):
			{
				GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[2]);
				if (soldier)
				{
					Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_HELI_DESTROYED, MX0_A02_CUSTOM_PARAM_DEFAULT);
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_GDI_NOTICES_FLAME):
			{
				GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[3]);
				if (soldier)
				{
					Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_GDI_NOTICES_FLAME, MX0_A02_CUSTOM_PARAM_DEFAULT);
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_GDI_NOTICES_FLAME_DEAD):
			{
				GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[4]);
				if (soldier)
				{
					Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_GDI_NOTICES_FLAME_DEAD, MX0_A02_CUSTOM_PARAM_DEFAULT);
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_HELI_DESTROYED_02):
			{
				if (!call_heli_destroy_once)
				{
					player_retreat = false;
					call_heli_destroy_once = true;
					GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[2]);
					if (soldier)
					{
						Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_HELI_DESTROYED_02, MX0_A02_CUSTOM_PARAM_DEFAULT, 0.5f);
					}
					soldier = Commands->Find_Object (MX0_A02_UNIT_ID[1]);
					if (soldier)
					{
						Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_HELI_DESTROYED_02, MX0_A02_CUSTOM_PARAM_DEFAULT, 1.5f);
					}
					Commands->Start_Timer (obj, this, 1.0f, MX0_A02_TIMER_NOD_RETREAT);
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_ENDING_02):
			{
				GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[4]);
				if (soldier)
				{
					Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_ENDING_02, MX0_A02_CUSTOM_PARAM_DEFAULT);
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_ENDING_03):
			{
				GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[1]);
				if (soldier)
				{
					Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_ENDING_03, MX0_A02_CUSTOM_PARAM_DEFAULT);
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_ENDING_04):
			{
				GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[2]);
				if (soldier)
				{
					Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_ENDING_04, MX0_A02_CUSTOM_PARAM_DEFAULT);
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_ENDING_05):
			{
				GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[3]);
				if (soldier)
				{
					Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_ENDING_05, MX0_A02_CUSTOM_PARAM_DEFAULT);
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_ENDING_06):
			{
				Commands->Create_2D_Sound ("MX0_GDIEAGLEBASE_110");
				Commands->Start_Timer (obj, this, 5.0f, MX0_A02_TIMER_EAGLE_BASE);
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_ENGINEER_MOVETOTANK):
			{
				if (sender)
				{
					engineer_01_id = Commands->Get_ID (sender);
					Commands->Send_Custom_Event (obj, sender, MX0_A02_CUSTOM_TYPE_ENGINEER_MOVETOTANK, MX0_A02_MED_TANK_ID);
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_ENGINEER_DONE):
			{
				GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[1]);
				if (soldier)
				{
					Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_SAY_TANK, MX0_A02_CUSTOM_PARAM_DEFAULT);
					Commands->Start_Timer (obj, this, 5.0f, MX0_A02_TIMER_ENTER_TANK);
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_ENGINEER_02_REGISTER):
			{
				engineer_02_id = Commands->Get_ID (sender);
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_ENTERED_TANK):
			{
				entered_tank = true;
				GameObject * controller = Commands->Find_Object (1400041);
				if (controller)
				{
					Commands->Send_Custom_Event (obj, controller, MX0_A03_CUSTOM_TYPE_START_ZONE, MX0_A02_CUSTOM_PARAM_DEFAULT, 2.0f);
				}
				GameObject * soldier = Commands->Find_Object (engineer_02_id);
				if (soldier)
				{
					Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_SAY_FIREHOLE, MX0_A02_CUSTOM_PARAM_DEFAULT);
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_EXPLODE):
			{
				GameObject * debris = Commands->Find_Object (MX0_A02_BLOCKAGE_ID);
				if (debris)
				{
					Commands->Create_Explosion ("Ground Explosion 01 - Harmless", Vector3(-71.233f, -41.517f, 0.181f), NULL);					Commands->Set_Animation (debris, "AG_L0_BLOCKAGE1.AG_L0_BLOCKAGE1", false);
					Commands->Start_Timer (obj, this, 2.0f, MX0_A02_TIMER_DESTROY_RUBBLE);
				}
				GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[1]);
				if (soldier)
				{
					Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_FOLLOW_HAVOC, MX0_A02_CUSTOM_PARAM_DEFAULT);
				}
				Commands->Start_Timer (obj, this, 1.0f, MX0_A02_TIMER_WRONG_WAY);
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_SAY_APC_DOWN):
			{
				GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[3]);
				if (soldier)
				{
					Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_SAY_APC_DOWN, MX0_A02_CUSTOM_PARAM_DEFAULT);
				}
				break;
			}
		case (MX0_A02_CUSTOM_TYPE_SHOOT_HELI_02):
			{
				int count = 1;
				while (count < 5)
				{
					GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[count]);
					if (soldier)
					{
						Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_SHOOT_HELI_02, MX0_A02_CUSTOM_PARAM_DEFAULT);
					}
					count++;
				}
			}
		default:
			{
				break;
			}
		}
	}

	void Timer_Expired (GameObject * obj, int timer_id)
	{
		switch (timer_id)
		{
		case (MX0_A02_TIMER_PRE_AMBIENT):
			{
				if (pre_ambient_on)
				{
					GameObject * soldier = NULL;
					switch (pre_ambient_count)
					{
					case (1):
						{
							soldier = Commands->Find_Object (MX0_A02_UNIT_ID[2]);
							break;
						}
					case (2):
						{
							soldier = Commands->Find_Object (MX0_A02_UNIT_ID[3]);
							break;
						}
					case (3):
						{
							soldier = Commands->Find_Object (MX0_A02_UNIT_ID[4]);
							break;
						}
					case (4):
						{
							soldier = Commands->Find_Object (MX0_A02_UNIT_ID[2]);
							break;
						}
					case (5):
						{
							soldier = Commands->Find_Object (MX0_A02_UNIT_ID[1]);
							break;
						}
					case (6):
						{
							soldier = Commands->Find_Object (MX0_A02_UNIT_ID[4]);
							break;
						}
					case (7):
						{
							soldier = Commands->Find_Object (MX0_A02_UNIT_ID[4]);
							break;
						}
					case (8):
						{
							soldier = Commands->Find_Object (MX0_A02_UNIT_ID[2]);
							break;
						}
					case (9):
						{
							soldier = Commands->Find_Object (MX0_A02_UNIT_ID[1]);
							break;
						}
					case (10):
						{
							soldier = Commands->Find_Object (MX0_A02_UNIT_ID[3]);
							break;
						}
					case (11):
						{
							soldier = Commands->Find_Object (MX0_A02_UNIT_ID[4]);
							break;
						}
					default:
						{
							break;
						}
					}
					if (soldier)
					{
						Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_PRE_AMBIENT, pre_ambient_count);
					}
					pre_ambient_count++;
					if (pre_ambient_count > MX0_A02_PRE_AMBIENT_MAX)
					{
						pre_ambient_count = 1;
					}
					Commands->Start_Timer (obj, this, Get_Int_Random (2, 4), MX0_A02_TIMER_PRE_AMBIENT);
				}
				break;
			}
		case (MX0_A02_TIMER_PLAYER_RETREAT):
			{
				if (player_retreat)
				{
					Vector3 player_loc = Commands->Get_Position (STAR);
					Vector3 controller_loc = Commands->Get_Position (obj);
					float distance = Commands->Get_Distance (player_loc, controller_loc);
					if (distance > MX0_A02_PLAYER_RETREAT_DISTANCE)
					{
						GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[Get_Int_Random(1,4)]);
						if (soldier)
						{
							Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_PLAYER_RETREAT, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
					}
					Commands->Start_Timer (obj, this, 3.0f, MX0_A02_TIMER_PLAYER_RETREAT);
				}
				break;
			}
		case (MX0_A02_TIMER_PREVENT_SPAWNS):
			{
				if (!retreat_sequence)
				{
					prevent_spawns = false;
					Commands->Send_Custom_Event (obj, obj, MX0_A02_CUSTOM_TYPE_NOD_SOLDIER_KILLED, 0, 0.1f);
				}
				break;
			}
		case (MX0_A02_TIMER_AFTER_HELI_01):
			{
				Commands->Send_Custom_Event (obj, obj, MX0_A02_CUSTOM_TYPE_NEXT_SEQUENCE, MX0_A02_CUSTOM_PARAM_DEFAULT);
				break;
			}
		case (MX0_A02_TIMER_NOD_RETREAT):
			{
				sequence_active = false;
				prevent_spawns = true;
				retreat_sequence = true;
				player_retreat = false;

				GameObject * chinook_obj1 = Commands->Create_Object("Invisible_Object", Vector3(-106.497f,-37.154f,1.093f));
				if (chinook_obj1)
				{
					Commands->Set_Facing(chinook_obj1, -55.0f);
					Commands->Attach_Script(chinook_obj1, "Test_Cinematic", "X0I_GDI_Drop02_Engineer.txt");
				}
				GameObject * music_control = Commands->Find_Object (1700006);
				if (music_control)
				{
					Commands->Destroy_Object (music_control);
				}

				int count = MX0_A02_ACTOR_NOD_START;
				while (count < MX0_A02_ACTOR_HEADCOUNT)
				{
					if (MX0_A02_UNIT_ID[count])
					{
						GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[count]);
						if (soldier)
						{
							Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_RETREAT_SEQUENCE, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
					}
					count++;
				}
				Commands->Create_2D_Sound ("MX0_NODSOLDIER1_101");
				Commands->Start_Timer (obj, this, 3.0f, MX0_A02_TIMER_RETREAT_DONE);
				break;
			}
		case (MX0_A02_TIMER_RETREAT_DONE):
			{
				// Make soldiers move to default positions.

				int count = 1;
				while (count < MX0_A02_ACTOR_NOD_START)
				{
					GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[count]);
					if (soldier)
					{
						Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_RETREAT_DONE, MX0_A02_CUSTOM_PARAM_DEFAULT);
						if (count == 2)
						{
							Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_ENDING_01, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
					}
					count++;
				}
				break;
			}
		case (MX0_A02_TIMER_EAGLE_BASE):
			{
				Commands->Create_2D_Sound ("MX0_GDIEAGLEBASE_116");
				break;
			}
		case (MX0_A02_TIMER_ENTER_TANK):
			{
				if ((havoc_entered_tank < 3) && (!entered_tank))
				{
					switch (havoc_entered_tank)
					{
					case (0):
						{
							GameObject * soldier = Commands->Find_Object (engineer_02_id);
							if (soldier)
							{
								Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_TANKSAY_01, MX0_A02_CUSTOM_PARAM_DEFAULT);
							}
							break;
						}
					case (1):
						{
							GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[1]);
							if (soldier)
							{
								Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_TANKSAY_02, MX0_A02_CUSTOM_PARAM_DEFAULT);
							}
							break;
						}
					case (2):
						{
							GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[2]);
							if (soldier)
							{
								Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_TANKSAY_03, MX0_A02_CUSTOM_PARAM_DEFAULT);
							}
							break;
						}
					default:
						{
							break;
						}
					}
					havoc_entered_tank++;
					Commands->Start_Timer (obj, this, 5.0f, MX0_A02_TIMER_ENTER_TANK);
				}
				break;
			}
		case (MX0_A02_TIMER_RANDOM_EXPLOSIONS):
			{
				if (!retreat_sequence)
				{
					GameObject * location = Commands->Find_Object (MX0_A02_MOVE_OBJ_SNIPER_01);
					int choice = Get_Int_Random (1, 16);
					switch (choice)
					{
					case (1):
						{
							location = Commands->Find_Object (MX0_A02_MOVE_OBJ_01);
							break;
						}
					case (2):
						{
							location = Commands->Find_Object (MX0_A02_MOVE_OBJ_02);
							break;
						}
					case (3):
						{
							location = Commands->Find_Object (MX0_A02_MOVE_OBJ_03);
							break;
						}
					case (4):
						{
							location = Commands->Find_Object (MX0_A02_MOVE_OBJ_04);
							break;
						}
					case (5):
						{
							location = Commands->Find_Object (MX0_A02_MOVE_OBJ_05);
							break;
						}
					case (6):
						{
							location = Commands->Find_Object (MX0_A02_MOVE_OBJ_06);
							break;
						}
					case (7):
						{
							location = Commands->Find_Object (MX0_A02_MOVE_OBJ_07);
							break;
						}
					case (8):
						{
							location = Commands->Find_Object (MX0_A02_MOVE_OBJ_08);
							break;
						}
					case (9):
						{
							location = Commands->Find_Object (MX0_A02_MOVE_OBJ_09);
							break;
						}
					case (10):
						{
							location = Commands->Find_Object (MX0_A02_MOVE_OBJ_10);
							break;
						}
					case (11):
						{
							location = Commands->Find_Object (MX0_A02_MOVE_OBJ_11);
							break;
						}
					case (12):
						{
							location = Commands->Find_Object (MX0_A02_MOVE_OBJ_12);
							break;
						}
					case (13):
						{
							location = Commands->Find_Object (MX0_A02_MOVE_OBJ_13);
							break;
						}
					case (14):
						{
							location = Commands->Find_Object (MX0_A02_MOVE_OBJ_14);
							break;
						}
					case (15):
						{
							location = Commands->Find_Object (MX0_A02_MOVE_OBJ_15);
							break;
						}
					case (16):
						{
							location = Commands->Find_Object (MX0_A02_MOVE_OBJ_16);
							break;
						}
					default:
						{
							break;
						}
					}
					if (location)
					{
						Vector3 location_pos = Commands->Get_Position (location);
						location_pos.X += float(Get_Int_Random(-2,2));
						location_pos.Y += float(Get_Int_Random(-2,2));
						Commands->Create_Explosion ("Explosion_MX0", location_pos, obj);
						Commands->Start_Timer (obj, this, float(Get_Int_Random(3,6)), MX0_A02_TIMER_RANDOM_EXPLOSIONS);
					}
				}
				break;
			}
		case (MX0_A02_TIMER_DESTROY_RUBBLE):
			{
				GameObject * blockage = Commands->Find_Object (MX0_A02_BLOCKAGE_ID);
				if (blockage)
				{
					Commands->Destroy_Object (blockage);
				}
				break;
			}
		case (MX0_A02_TIMER_WRONG_WAY):
			{
				wrong_way_count++;
				if (wrong_way_count > 4)
				{
					wrong_way_count = 2;
				}
				GameObject * soldier = Commands->Find_Object (MX0_A02_UNIT_ID[wrong_way_count]);
				if (soldier)
				{
					Commands->Send_Custom_Event (obj, soldier, MX0_A02_CUSTOM_TYPE_SAY_WRONG_WAY, MX0_A02_CUSTOM_PARAM_DEFAULT);
				}
				Commands->Start_Timer (obj, this, 5.0f, MX0_A02_TIMER_WRONG_WAY);
			}
		default:
			{
				break;
			}
		}
	}

	void MX0_A02_Fill_Empty_Slot (GameObject * obj, bool current_target)
	{
		int count = MX0_A02_ACTOR_NOD_START;
		while (count < MX0_A02_ACTOR_HEADCOUNT)
		{
			if (!MX0_A02_UNIT_ID[count])
			{
				MX0_A02_UNIT_ID[count] = Commands->Get_ID (obj);
				if (current_target)
				{
					current_nod_target = count;
				}
				else
				{
					current_nod_target = 0;
				}
				Commands->Send_Custom_Event (obj, obj, MX0_A02_CUSTOM_TYPE_REGISTER_ACTOR_ID, count, 0.1f);
				count = MX0_A02_ACTOR_HEADCOUNT;
			}
			count++;
		}
	}
};


DECLARE_SCRIPT (MX0_A02_ACTOR, "ActorID=0:int")
{
	bool can_damage;
	bool default_state;
	bool active_actor;
	bool death_animation;
	float start_health;
	float last_armor;
	int my_sniper_target;
	int my_register_id;
	int MX0_A02_NOD_SNIPER_01;
	int MX0_A02_NOD_SNIPER_02;
	int medtank_id;

	REGISTER_VARIABLES()
	{
		SAVE_VARIABLE (can_damage, 1);
		SAVE_VARIABLE (start_health, 2);
		SAVE_VARIABLE (my_sniper_target, 3);
		SAVE_VARIABLE (default_state, 4);
		SAVE_VARIABLE (my_register_id, 5);
		SAVE_VARIABLE (last_armor, 6);
		SAVE_VARIABLE (MX0_A02_NOD_SNIPER_01, 7);
		SAVE_VARIABLE (MX0_A02_NOD_SNIPER_02, 8);
		SAVE_VARIABLE (active_actor, 9);
		SAVE_VARIABLE (death_animation, 10);
		SAVE_VARIABLE (medtank_id, 11);
	}

	// On Created, place unit in Default State
	// Random crouch walk or run between two points and fire at targets
	
	void Created (GameObject * obj)
	{
		Commands->Attach_Script (obj, "M00_Soldier_Powerup_Disable", "");
		active_actor = true;
		start_health = Commands->Get_Health (obj);
		last_armor = Commands->Get_Shield_Strength (obj);
		Commands->Innate_Disable (obj);
		my_sniper_target = 0;
		my_register_id = 0;
		can_damage = false;
		default_state = false;
		death_animation = false;
		MX0_A02_NOD_SNIPER_01 = 0;
		MX0_A02_NOD_SNIPER_02 = 0;
		medtank_id = 0;

		Commands->Enable_Enemy_Seen (obj, false);

		int actor_id = Get_Int_Parameter("ActorID");
		if (!actor_id)
		{
			Commands->Send_Custom_Event (obj, obj, MX0_A02_CUSTOM_TYPE_DEFAULT_STATE_ON, MX0_A02_CUSTOM_PARAM_DEFAULT);
		}
		else
		{
			switch (actor_id)
			{
			case (1): // First falling Nod guy moves into position.
				{
					ActionParamsStruct params;
					params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_NODFALL01_MOVE);
					params.Set_Movement(Vector3(-79.172f,-72.536f,6.0f), RUN, 0.5f, false);
					Commands->Action_Goto (obj, params);
					Commands->Enable_Enemy_Seen (obj, true);
					break;
				}
			case (2): // Second falling Nod guy moves into position.
				{
					ActionParamsStruct params;
					params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_NODFALL02_MOVE);
					params.Set_Movement(Vector3(-97.415f,-68.822f,3.944f), RUN, 0.5f, false);
					Commands->Action_Goto (obj, params);
					Commands->Enable_Enemy_Seen (obj, true);
					break;
				}
			case (3): // Nod Rocket Soldier shoots APC.
				{
					ActionParamsStruct params;
					params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_NOD_MOVETO_APC);
					params.Set_Movement(Vector3(-79.172f,-72.536f,6.0f), RUN, 0.5f, false);
					Commands->Action_Goto (obj, params);
					break;
				}
			case (4): // Nod soldiers that get dropped from the helicopter 01.
				{
					ActionParamsStruct params;
					params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_NOD_HELI_01_MOVE);
					params.Set_Movement(Vector3(0,0,0), RUN, 0.5f, false);
					params.WaypathID = MX0_A02_WAYPATH_01;
					Commands->Action_Goto (obj, params);
					can_damage = true;
					Commands->Start_Timer (obj, this, 20.0f, MX0_A02_TIMER_DESTROY_MINIGUNNER);
					break;
				}
			case (5): // Nod FlameThrower jumps down and fires at targets until dead.
				{
					ActionParamsStruct params;
					params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_NOD_HELI_02_MOVE);
					params.Set_Attack(STAR, 300.0f, 0.0f, true);
					params.Set_Movement(Vector3(0,0,0), RUN, 0.5f, false);
					params.WaypathID = MX0_A02_WAYPATH_02;
					params.AttackCheckBlocked = false;
					params.AttackForceFire = true;
					Commands->Action_Attack (obj, params);
					can_damage = true;
					Commands->Start_Timer (obj, this, 10.0f, MX0_A02_TIMER_DESTROY_FLAME);
					Commands->Trigger_Weapon (obj, true, Vector3(-90.941f,-60.470f,0.069f));
					GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
					if (controller)
					{
						Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_GDI_NOTICES_FLAME, MX0_A02_CUSTOM_PARAM_DEFAULT);
					}
					break;
				}
			case (6): // Nod FlameThrower explodes shortly after creation, before ending rappel.
				{
					can_damage = true;
					Commands->Start_Timer (obj, this, 2.0f, MX0_A02_TIMER_DESTROY_FLAME);
					break;
				}
			case (7): // Engineer 01 moves to repair the tank.
				{
					Commands->Start_Timer (obj, this, 4.0f, MX0_A02_TIMER_WAITFOR_MOVETOTANK);
					break;
				}
			case (8): // Engineer 02 moves to destroy the rubble.
				{
					Commands->Start_Timer (obj, this, 4.0f, MX0_A02_TIMER_WAITFOR_MOVETORUBBLE);
					break;
				}
			default:
				{
					break;
				}
			}
		}
	}

	void Damaged (GameObject * obj, GameObject * damager, float amount)
	{
		if (active_actor)
		{
			if (!can_damage)
			{
				if (default_state)
				{
					last_armor -= 1.0f;
				}
				Commands->Set_Shield_Strength (obj, last_armor);
				Commands->Set_Health (obj, start_health);
			}
			else
			{
				last_armor = Commands->Get_Shield_Strength (obj);
			}
			if (default_state)
			{
				if (damager)
				{
					if (my_register_id < MX0_A02_ACTOR_NOD_START)
					{
						if (damager != STAR)
						{
							int	my_type = Commands->Get_Player_Type (obj);
							int their_type = Commands->Get_Player_Type (damager);
							if (my_type != their_type)
							{
								ActionParamsStruct params;
								params.Set_Basic(this, MX0_A02_PRIORITY_DEFAULT_SHOOT, MX0_A02_ACTION_DEFAULT);
								params.Set_Attack(damager, 300.0f, 0.0f, true);
								if (my_register_id >= MX0_A02_ACTOR_NOD_START)
								{
									params.AttackCheckBlocked = false;
								}
								Commands->Action_Attack (obj, params);
							}
						}
					}
					else
					{
						ActionParamsStruct params;
						params.Set_Basic(this, MX0_A02_PRIORITY_DEFAULT_SHOOT, MX0_A02_ACTION_DEFAULT);
						params.Set_Attack(damager, 300.0f, 0.0f, true);
						if (my_register_id >= MX0_A02_ACTOR_NOD_START)
						{
							params.AttackCheckBlocked = false;
						}
						Commands->Action_Attack (obj, params);
					}
				}
			}
			else
			{
				if ((!death_animation) && (can_damage))
				{
					death_animation = true;
					// Check here for any special death animations that need to be played.

					int my_id = Get_Int_Parameter ("ActorID");
					switch (my_id)
					{
					case (1):
						{
							//DEBUG insert falling death animation here. Animation must kill unit at completion.
							Commands->Debug_Message ("XXXX INSERT FALLING DEATH ANIMATION HERE.\n");
							//DEBUG also, play a sound effect for the falling scream.
							Commands->Apply_Damage (obj, 10000.0f, "Blamokiller", obj);
							GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
							if (controller)
							{
								Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_GDI_RESPONDS_01, MX0_A02_CUSTOM_PARAM_DEFAULT);
							}
							break;
						}
					case (2):
						{
							//DEBUG insert falling death animation here. Animation must kill unit at completion.
							Commands->Debug_Message ("XXXX INSERT FALLING DEATH ANIMATION HERE.\n");
							//DEBUG also, play a sound effect for the falling scream.
							Commands->Apply_Damage (obj, 10000.0f, "Blamokiller", obj);

							// Response from here is action complete send to destroy APC.
							break;
						}
					default:
						{
							break;
						}
					}
				}
			}
		}
	}

	void Killed (GameObject * obj, GameObject * killer)
	{
		if (active_actor)
		{
			GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
			if (controller)
			{
				if (killer == STAR)
				{
					Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_PLAYER_KILLED_NOD, MX0_A02_CUSTOM_PARAM_DEFAULT);
				}
				else
				{
					if (killer)
					{
						int killer_id = Commands->Get_ID (killer);
						Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_SOLDIER_KILLED_NOD, killer_id);
					}
				}
				if (my_register_id >= MX0_A02_ACTOR_NOD_START)
				{
					Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_NOD_SOLDIER_KILLED, my_register_id, 0.1f);
				}
			}
		}
	}

	void Custom (GameObject * obj, int type, int param, GameObject * sender)
	{
		if (active_actor)
		{
			switch (type)
			{
			case (MX0_A02_CUSTOM_TYPE_MAIN_ENDING):
				{
					active_actor = false;
					default_state = false;
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_REGISTER_ACTOR_ID):
				{
					my_register_id = param;
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_DAMAGE_ON):
				{
					can_damage = true;
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_DAMAGE_OFF):
				{
					can_damage = false;
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_DEFAULT_STATE_ON):
				{
					Commands->Start_Timer (obj, this, 0.1f, MX0_A02_TIMER_BASIC_MOVE_02);
					default_state = true;
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_DEFAULT_STATE_OFF):
				{
					default_state = false;
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_REQUEST_TARGET):
				{
					if (default_state)
					{
						GameObject * target = Commands->Find_Object (param);
						if (target)
						{
							ActionParamsStruct params;
							params.Set_Basic(this, MX0_A02_PRIORITY_DEFAULT_SHOOT, MX0_A02_ACTION_DEFAULT);
							params.Set_Attack(target, 300.0f, 0.0f, true);
							params.MoveCrouched = true;
							params.AttackCrouched = true;
							if (my_register_id >= MX0_A02_ACTOR_NOD_START)
							{
								params.AttackCheckBlocked = false;
							}
							Commands->Action_Attack (obj, params);
						}
					}
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_PRE_AMBIENT):
				{
					MX0_A02_Say_Something (obj, param, false);
					break;
				}
			case (MX0_A02_CUSTOM_KILL_SNIPER_01):
				{
					default_state = false;
					GameObject * sniper = Commands->Find_Object (param);
					if (sniper)
					{
						MX0_A02_NOD_SNIPER_01 = Commands->Get_ID (sniper);
						GameObject * location = Commands->Find_Object (MX0_A02_MOVE_OBJ_SNIPER_02);
						if (location)
						{
							ActionParamsStruct params;
							params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_ROCKET_SNIPER_MOVE);
							params.Set_Movement(Commands->Get_Position (location), RUN, 0.5f, false);
							Commands->Action_Goto (obj, params);
						}
						else
						{
							GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
							if (controller)
							{
								Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_HANDOFF_SNIPER_02_ID, MX0_A02_CUSTOM_PARAM_DEFAULT);
							}
						}
					}
					else
					{
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_HANDOFF_SNIPER_02_ID, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
					}
					break;
				}
			case (MX0_A02_CUSTOM_KILL_SNIPER_02):
				{
					default_state = false;
					GameObject * sniper = Commands->Find_Object (param);
					if (sniper)
					{
						MX0_A02_NOD_SNIPER_02 = Commands->Get_ID (sniper);
						GameObject * location = Commands->Find_Object (MX0_A02_MOVE_OBJ_SNIPER_02);
						if (location)
						{
							ActionParamsStruct params;
							params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_ROCKET_SNIPER_MOVE_02);
							params.Set_Movement(Commands->Get_Position (location), RUN, 0.5f, false);
							Commands->Action_Goto (obj, params);
						}
						else
						{
							Commands->Send_Custom_Event (obj, obj, MX0_A02_CUSTOM_TYPE_DEFAULT_STATE_ON, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
					}
					else
					{
						Commands->Send_Custom_Event (obj, obj, MX0_A02_CUSTOM_TYPE_DEFAULT_STATE_ON, MX0_A02_CUSTOM_PARAM_DEFAULT);
					}
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_START_GDI_01):
				{
					Commands->Start_Timer (obj, this, 1.0f, MX0_A02_TIMER_SOLDIER_02_START);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_START_GDI_03):
				{
					MX0_A02_Say_Something (obj, MX0_A02_SPEECH_GDI_01_STARTUP_02, true);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_START_GDI_04):
				{
					default_state = false;
					Vector3 my_loc = Commands->Get_Position (obj);
					Vector3 star_loc = Commands->Get_Position (STAR);
					float distance = Commands->Get_Distance (my_loc, star_loc);
					if (distance > MX0_A02_APPROACH_DISTANCE)
					{
						ActionParamsStruct params;
						params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_APPROACH_HAVOC_01);
						params.Set_Movement(STAR, RUN, 3.0f, false);
						Commands->Action_Goto (obj, params);
					}
					else
					{
						MX0_A02_Say_Something (obj, MX0_A02_SPEECH_GDI_02_BECKON, false);
					}
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_START_GDI_05):
				{
					MX0_A02_Say_Something (obj, MX0_A02_SPEECH_GDI_03_STARTUP, false);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_PLAYER_CONGRATS):
				{
					if (default_state)
					{
						int speech_num = MX0_A02_SPEECH_GDI_PLAYER_CONGRATS_01 + param;
						MX0_A02_Say_Something (obj, speech_num, false);
					}
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_SOLDIER_CONGRATS):
				{
					if (default_state)
					{
						int speech_num = MX0_A02_SPEECH_GDI_SOLDIER_CONGRATS_01 + param;
						MX0_A02_Say_Something (obj, speech_num, false);
					}
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_PLAYER_RETREAT):
				{
					int speech_num = MX0_A02_SPEECH_GDI_PLAYER_RETREAT_01 + my_register_id - 1;
					MX0_A02_Say_Something (obj, speech_num, false);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_GDI_NOTICES_NOD_01):
				{
					MX0_A02_Say_Something (obj, MX0_A02_SPEECH_GDI_NOTICES_NOD_01, false);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_GDI_SHOOTS_NOD_01):
				{
					GameObject * target = Commands->Find_Object (param);
					if (target)
					{
						ActionParamsStruct params;
						params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_GDI_SHOOTS_NOD_01);
						params.Set_Attack(target, 300.0f, 0.0f, true);
						Commands->Action_Attack (obj, params);
					}
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_GDI_RESPONDS_01):
				{
					MX0_A02_Say_Something (obj, MX0_A02_SPEECH_GDI_RESPONDS_01, false);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_GDI_SHOOTS_NOD_02):
				{
					GameObject * target = Commands->Find_Object (param);
					if (target)
					{
						ActionParamsStruct params;
						params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_GDI_SHOOTS_NOD_02);
						params.Set_Attack(target, 300.0f, 0.0f, true);
						Commands->Action_Attack (obj, params);
					}
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_GET_APC_ID):
				{
					GameObject * apc = Commands->Find_Object (param);
					if (apc)
					{
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_APC_BLOWITUP, MX0_A02_CUSTOM_PARAM_DEFAULT, 1.0f);
						}
						ActionParamsStruct params;
						params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_NOD_SHOOT_APC);
						params.Set_Attack(apc, 300.0f, 0.0f, true);
						Commands->Action_Attack (obj, params);
					}
					else
					{
						ActionParamsStruct params;
						params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_NOD_DONEWITH_APC);
						params.Set_Movement(Vector3(-78.442f,-78.044f,6.404f), RUN, 0.5f, false);
						Commands->Action_Goto (obj, params);
					}
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_HELI_DESTROYED):
				{
					MX0_A02_Say_Something (obj, MX0_A02_SPEECH_GDI_SPOTS_HELI_DESTROY, false);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_GDI_NOTICES_HELI_01):
				{
					MX0_A02_Say_Something (obj, MX0_A02_SPEECH_GDI_SPOTS_HELI_01, false);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_GDI_NOTICES_HELI_02):
				{
					MX0_A02_Say_Something (obj, MX0_A02_SPEECH_GDI_SPOTS_HELI_02, false);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_GDI_NOTICES_FLAME):
				{
					MX0_A02_Say_Something (obj, MX0_A02_SPEECH_GDI_NOTICES_FLAME, false);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_GDI_NOTICES_FLAME_DEAD):
				{
					MX0_A02_Say_Something (obj, MX0_A02_SPEECH_GDI_NOTICES_FLAME_DEAD, false);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_HELI_DESTROYED_02):
				{
					if (my_register_id == 1)
					{
						MX0_A02_Say_Something (obj, MX0_A02_SPEECH_GDI_SPOTS_HELI_DESTROY, false);
					}
					else
					{
						MX0_A02_Say_Something (obj, MX0_A02_SPEECH_NOD_HELI_DESTROYED_02, false);
					}
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_RETREAT_SEQUENCE):
				{
					GameObject * moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_16);
					switch (my_register_id)
					{
					case (5):
						{
							moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_09);
							break;
						}
					case (6):
						{
							moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_11);
							break;
						}
					case (7):
						{
							moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_13);
							break;
						}
					case (8):
						{
							moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_15);
							break;
						}
					default:
						{
							break;
						}
					}
					if (moveloc)
					{
						ActionParamsStruct params;
						params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_RETREAT_MOVE);
						params.Set_Movement(Commands->Get_Position (moveloc), RUN, 0.5f, false);
						Commands->Action_Goto (obj, params);
					}
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_RETREAT_DONE):
				{
					Vector3 move_location = Vector3(-105.302f,-55.383f,0.0f);
					switch (my_register_id)
					{
					case (1):
						{
							move_location = Vector3(-78.74f,-60.34f,0.0f);
							break;
						}
					case (2):
						{
							move_location = Vector3(-90.786f,-65.492f,0.0f);
							break;
						}
					case (3):
						{
							move_location = Vector3(-94.756f,-59.510f,0.0f);
							break;
						}
					case (4):
						{
							move_location = Vector3(-104.989f,-49.282f,0.0f);
							break;
						}
					default:
						{
							break;
						}
					}
					default_state = false;
					ActionParamsStruct params;
					params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_DEFAULT);
					params.Set_Movement(move_location, 0.2f, 3.0f, false);
					Commands->Action_Goto (obj, params);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_ENDING_01):
				{
					MX0_A02_Say_Something (obj, MX0_A02_SPEECH_ENDING_01, false);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_ENDING_02):
				{
					MX0_A02_Say_Something (obj, MX0_A02_SPEECH_ENDING_02, false);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_ENDING_03):
				{
					MX0_A02_Say_Something (obj, MX0_A02_SPEECH_ENDING_03, false);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_ENDING_04):
				{
					MX0_A02_Say_Something (obj, MX0_A02_SPEECH_ENDING_04, true);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_ENDING_05):
				{
					MX0_A02_Say_Something (obj, MX0_A02_SPEECH_ENDING_05, false);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_ENGINEER_MOVETOTANK):
				{
					MX0_A02_Say_Something (obj, MX0_A02_SPEECH_ENGINEER_TANK_01, false);
					GameObject * tank = Commands->Find_Object (param);
					if (tank)
					{
						medtank_id = param;
						GameObject * moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_06);
						if (moveloc)
						{
							ActionParamsStruct params;
							params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_ENGINEER_01_MEDTANK);
							params.Set_Movement(Commands->Get_Position(moveloc), RUN, 3.0f, false);
							Commands->Action_Goto (obj, params);
						}
					}
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_SAY_TANK):
				{
					MX0_A02_Say_Something (obj, MX0_A02_SPEECH_UNSTOPPABLE, false);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_TANKSAY_01):
				{
					MX0_A02_Say_Something (obj, MX0_A02_SPEECH_TANKSAY_01, false);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_TANKSAY_02):
				{
					MX0_A02_Say_Something (obj, MX0_A02_SPEECH_TANKSAY_02, false);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_TANKSAY_03):
				{
					MX0_A02_Say_Something (obj, MX0_A02_SPEECH_TANKSAY_03, false);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_SAY_FIREHOLE):
				{
					MX0_A02_Say_Something (obj, MX0_A02_SPEECH_TANKSAY_04, false);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_FOLLOW_HAVOC):
				{
					ActionParamsStruct params;
					params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_DEFAULT);
					params.Set_Movement(STAR, RUN, 10.0f, false);
					Commands->Action_Goto (obj, params);
					//HANDOFF MY ID TO THE NEW CONTROLLER HERE!
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_SAY_APC_DOWN):
				{
					MX0_A02_Say_Something (obj, MX0_A02_SPEECH_APC_DOWN, false);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_SHOOT_HELI_02):
				{
					ActionParamsStruct params;
					params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_DEFAULT);
					params.Set_Attack(Vector3(-85.66f,-73.31f,22.81f), 300.0f, 0.0f, true);
					params.AttackCheckBlocked = false;
					Commands->Action_Attack (obj, params);
					break;
				}
			case (MX0_A02_CUSTOM_TYPE_SAY_WRONG_WAY):
				{
					Vector3 my_loc = Commands->Get_Position (obj);
					Vector3 star_loc = Commands->Get_Position (STAR);
					float distance = Commands->Get_Distance (my_loc, star_loc);
					if (distance < 10.0f)
					{
						switch (my_register_id)
						{
						case (2):
							{
								MX0_A02_Say_Something (obj, MX0_A02_SPEECH_WRONGWAY_01, true);
								break;
							}
						case (3):
							{
								MX0_A02_Say_Something (obj, MX0_A02_SPEECH_WRONGWAY_02, true);
								break;
							}
						case (4):
							{
								MX0_A02_Say_Something (obj, MX0_A02_SPEECH_WRONGWAY_03, true);
								break;
							}
						default:
							{
								break;
							}
						}
					}
					break;
				}
			default:
				{
					break;
				}
			}
		}
	}

	void Action_Complete (GameObject * obj, int action_id, ActionCompleteReason complete_reason)
	{
		if (active_actor)
		{
			if ((complete_reason == ACTION_COMPLETE_CONVERSATION_ENDED)	|| (complete_reason == ACTION_COMPLETE_CONVERSATION_INTERRUPTED) || (complete_reason == ACTION_COMPLETE_CONVERSATION_UNABLE_TO_INIT))
			{
				switch (action_id)
				{
				case (MX0_A02_SPEECH_GDI_01_STARTUP):
					{
						default_state = true;
						Commands->Start_Timer (obj, this, 0.1f, MX0_A02_TIMER_BASIC_MOVE_02);
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_START_GDI_02, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
						break;
					}
				case (MX0_A02_SPEECH_GDI_02_STARTUP):
					{
						default_state = true;
						Commands->Start_Timer (obj, this, 0.1f, MX0_A02_TIMER_BASIC_MOVE_02);
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_START_GDI_04, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
						break;
					}
				case (MX0_A02_SPEECH_GDI_01_STARTUP_02):
					{
						default_state = true;
						Commands->Start_Timer (obj, this, 0.1f, MX0_A02_TIMER_BASIC_MOVE_02);
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_START_GDI_05, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
						break;
					}
				case (MX0_A02_SPEECH_GDI_02_BECKON):
					{
						default_state = true;
						Commands->Start_Timer (obj, this, 0.1f, MX0_A02_TIMER_BASIC_MOVE_02);
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_START_GDI_03, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
						break;
					}
				case (MX0_A02_SPEECH_GDI_03_STARTUP):
					{
						default_state = true;
						Commands->Start_Timer (obj, this, 0.1f, MX0_A02_TIMER_BASIC_MOVE_02);
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_CONTINUE, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
						break;
					}
				case (MX0_A02_SPEECH_GDI_NOTICES_NOD_01):
					{
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_GDI_SHOOTS_NOD_01, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
						break;
					}
				case (MX0_A02_SPEECH_ENDING_01):
					{
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_ENDING_02, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
						break;
					}
				case (MX0_A02_SPEECH_ENDING_02):
					{
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_ENDING_03, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
						break;
					}
				case (MX0_A02_SPEECH_ENDING_03):
					{
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_ENDING_04, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
						break;
					}
				case (MX0_A02_SPEECH_ENDING_04):
					{
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_ENDING_05, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
						break;
					}
				case (MX0_A02_SPEECH_ENDING_05):
					{
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_ENDING_06, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
						break;
					}
				case (MX0_A02_SPEECH_ENGINEER_DONE):
					{
						Commands->Create_2D_Sound ("MX0_GDIEAGLEBASE_117");
						Commands->Set_HUD_Help_Text(IDS_MTUDSGN_DSGN0397I1DSGN_TXT, TEXT_COLOR_OBJECTIVE_PRIMARY);
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_ENGINEER_DONE, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
						break;
					}
				case (MX0_A02_SPEECH_TANKSAY_04):
					{
						GameObject * location = Commands->Find_Object (MX0_A02_MOVE_OBJ_SNIPER_02);
						if (location)
						{
							ActionParamsStruct params;
							params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_ENGINEER_RETREAT);
							params.Set_Movement(Commands->Get_Position (location), RUN, 5.0f, false);
							Commands->Action_Goto (obj, params);
						}
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_EXPLODE, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
						break;
					}
				case (MX0_A02_SPEECH_GDI_SPOTS_HELI_02):
					{
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_SHOOT_HELI_02, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
						break;
					}
				default:
					{
						break;
					}
				}
			}
			else
			{
				switch (action_id)
				{
				case (MX0_A02_ACTION_ROCKET_SNIPER_MOVE):
					{
						GameObject * sniper = Commands->Find_Object (MX0_A02_NOD_SNIPER_01);
						if (sniper)
						{
							ActionParamsStruct params;
							params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_ROCKET_SNIPER_SHOOT);
							params.Set_Attack(sniper, 300.0f, 0.0f, true);
							params.AttackCheckBlocked = false;
							Commands->Action_Attack (obj, params);
						}
						else
						{
							GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
							if (controller)
							{
								Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_HANDOFF_SNIPER_02_ID, MX0_A02_CUSTOM_PARAM_DEFAULT);
							}
						}
						break;
					}
				case (MX0_A02_ACTION_ROCKET_SNIPER_MOVE_02):
					{
						GameObject * sniper = Commands->Find_Object (MX0_A02_NOD_SNIPER_02);
						if (sniper)
						{
							ActionParamsStruct params;
							params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_ROCKET_SNIPER_SHOOT_02);
							params.Set_Attack(sniper, 300.0f, 0.0f, true);
							params.AttackCheckBlocked = false;
							Commands->Action_Attack (obj, params);
						}
						else
						{
							Commands->Send_Custom_Event (obj, obj, MX0_A02_CUSTOM_TYPE_DEFAULT_STATE_ON, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
						break;
					}
				case (MX0_A02_ACTION_ROCKET_SNIPER_SHOOT):
					{
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_HANDOFF_SNIPER_02_ID, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
						break;
					}
				case (MX0_A02_ACTION_ROCKET_SNIPER_SHOOT_02):
					{
						Commands->Send_Custom_Event (obj, obj, MX0_A02_CUSTOM_TYPE_DEFAULT_STATE_ON, MX0_A02_CUSTOM_PARAM_DEFAULT);
						break;
					}
				case (MX0_A02_ACTION_BASIC_MOVE_01):
				case (MX0_A02_ACTION_BASIC_MOVE_02):
					{
						if (default_state)
						{
							GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
							if (controller)
							{
								Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_REQUEST_TARGET, my_register_id);
							}
						}
						break;
					}
				case (MX0_A02_ACTION_APPROACH_HAVOC_01):
					{
						MX0_A02_Say_Something (obj, MX0_A02_SPEECH_GDI_02_BECKON, true);
						break;
					}
				case (MX0_A02_ACTION_NODFALL01_MOVE):
					{
						can_damage = true;
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_GDI_NOTICES_NOD_01, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
						break;
					}
				case (MX0_A02_ACTION_NODFALL02_MOVE):
					{
						can_damage = true;
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_GDI_SHOOTS_NOD_02, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
						break;
					}
				case (MX0_A02_ACTION_NOD_MOVETO_APC):
					{
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_GET_APC_ID, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
						break;
					}
				case (MX0_A02_ACTION_NOD_SHOOT_APC):
					{
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_SAY_APC_DOWN, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
						ActionParamsStruct params;
						params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_NOD_DONEWITH_APC);
						params.Set_Movement(Vector3(-78.442f,-78.044f,6.404f), RUN, 0.5f, false);
						Commands->Action_Goto (obj, params);
						break;
					}
				case (MX0_A02_ACTION_NOD_DONEWITH_APC):
					{
						Commands->Destroy_Object (obj);
						GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
						if (controller)
						{
							Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_NEXT_SEQUENCE, MX0_A02_CUSTOM_PARAM_DEFAULT);
						}
						break;
					}
				case (MX0_A02_ACTION_NOD_HELI_01_MOVE):
					{
						Commands->Enable_Enemy_Seen (obj, true);
						break;
					}
				case (MX0_A02_ACTION_NOD_HELI_02_MOVE):
					{
						ActionParamsStruct params;
						params.Set_Basic(this, MX0_A02_PRIORITY_DEFAULT_SHOOT, MX0_A02_ACTION_DEFAULT);
						params.Set_Attack(STAR, 30.0f, 0.0f, true);
						params.Set_Movement (STAR, RUN, 1.0f, false);
						Commands->Action_Attack (obj, params);
						break;
					}
				case (MX0_A02_ACTION_RETREAT_MOVE):
					{
						Commands->Apply_Damage (obj, 10000.0f, "Blamokiller", NULL);
						break;
					}
				case (MX0_A02_ACTION_ENGINEER_01_MEDTANK):
					{
						GameObject * tank = Commands->Find_Object (medtank_id);
						if (tank)
						{
							ActionParamsStruct params;
							params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_DEFAULT);
							params.Set_Attack(tank, 300.0f, 0.0f, false);
							params.AttackCheckBlocked = false;
							Commands->Action_Attack (obj, params);
							Commands->Start_Timer (obj, this, 5.0f, MX0_A02_TIMER_ENGINEER_FIX_TANK);
						}
						break;
					}
				case (MX0_A02_ACTION_ENGINEER_02_RUBBLE):
					{
						ActionParamsStruct params;
						params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_DEFAULT);
						params.Set_Attack(Vector3(-75.0f,-43.4f,0.1f), 0.0f, 0.0f, true);
						params.MoveCrouched = true;
						params.AttackCrouched = true;
						Commands->Action_Attack (obj, params);
						break;
					}
				default:
					{
						break;
					}
				}
			}
		}
	}

	void Enemy_Seen (GameObject * obj, GameObject * enemy)
	{
		ActionParamsStruct params;
		params.Set_Basic(this, MX0_A02_PRIORITY_DEFAULT_SHOOT, MX0_A02_ACTION_DEFAULT);
		params.Set_Attack(enemy, 300.0f, 0.0f, true);
		params.MoveCrouched = true;
		params.AttackCrouched = true;
		Commands->Action_Attack (obj, params);
	}

	void Timer_Expired (GameObject * obj, int timer_id)
	{
		if (active_actor)
		{
			switch (timer_id)
			{
			case (MX0_A02_TIMER_BASIC_MOVE_01):
				{
					if (default_state)
					{
						GameObject * moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_16);
						switch (my_register_id)
						{
						case (1):
							{
								moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_02);
								break;
							}
						case (2):
							{
								moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_04);						
								break;
							}
						case (3):
							{
								moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_06);
								break;
							}
						case (4):
							{
								moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_08);
								break;
							}
						case (5):
							{
								moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_10);
								break;
							}
						case (6):
							{
								moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_12);
								break;
							}
						case (7):
							{
								moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_14);
								break;
							}
						case (8):
							{
								moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_16);
								break;
							}
						default:
							{
								break;
							}
						}
						if (moveloc)
						{
							ActionParamsStruct params;
							params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_BASIC_MOVE_01);
							params.Set_Movement(Commands->Get_Position (moveloc), RUN, 0.5f, false);
							Commands->Action_Goto (obj, params);
						}
						Commands->Start_Timer (obj, this, (MX0_A02_TIMERLENGTH_BASIC_MOVE + Get_Int_Random(0, MX0_A02_TIMERLENGTH_BASIC_MOVE)), MX0_A02_TIMER_BASIC_MOVE_02);
					}
					break;
				}
			case (MX0_A02_TIMER_BASIC_MOVE_02):
				{
					if (default_state)
					{
						GameObject * moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_16);
						switch (my_register_id)
						{
						case (1):
							{
								moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_01);
								break;
							}
						case (2):
							{
								moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_03);						
								break;
							}
						case (3):
							{
								moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_05);
								break;
							}
						case (4):
							{
								moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_07);
								break;
							}
						case (5):
							{
								moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_09);
								break;
							}
						case (6):
							{
								moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_11);
								break;
							}
						case (7):
							{
								moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_13);
								break;
							}
						case (8):
							{
								moveloc = Commands->Find_Object (MX0_A02_MOVE_OBJ_15);
								break;
							}
						default:
							{
								break;
							}
						}
						if (moveloc)
						{
							ActionParamsStruct params;
							params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_BASIC_MOVE_02);
							params.Set_Movement(Commands->Get_Position (moveloc), RUN, 0.5f, false);
							Commands->Action_Goto (obj, params);
						}
						Commands->Start_Timer (obj, this, (MX0_A02_TIMERLENGTH_BASIC_MOVE + Get_Int_Random(0, MX0_A02_TIMERLENGTH_BASIC_MOVE)), MX0_A02_TIMER_BASIC_MOVE_01);
					}
					break;
				}
			case (MX0_A02_TIMER_SOLDIER_01_START):
				{
					Vector3 my_location = Commands->Get_Position (obj);
					Vector3 star_location = Commands->Get_Position (STAR);
					float distance = Commands->Get_Distance (my_location, star_location);
					if (distance < MX0_A02_APPROACH_DISTANCE)
					{
						default_state = false;
						MX0_A02_Say_Something (obj, MX0_A02_SPEECH_GDI_01_STARTUP, true);
					}
					else
					{
						Commands->Start_Timer (obj, this, 1.0f, MX0_A02_TIMER_SOLDIER_01_START);
					}
					break;
				}
			case(MX0_A02_TIMER_SOLDIER_02_START):
				{
					Vector3 my_location = Commands->Get_Position (obj);
					Vector3 star_location = Commands->Get_Position (STAR);
					float distance = Commands->Get_Distance (my_location, star_location);
					if (distance < MX0_A02_APPROACH_DISTANCE)
					{
						default_state = false;
						MX0_A02_Say_Something (obj, MX0_A02_SPEECH_GDI_02_STARTUP, true);
					}
					else
					{
						ActionParamsStruct params;
						params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_DEFAULT);
						params.Set_Movement(star_location, RUN, 0.5f, false);
						Commands->Action_Goto (obj, params);
						Commands->Start_Timer (obj, this, 1.0f, MX0_A02_TIMER_SOLDIER_02_START);
					}
					break;
				}
			case (MX0_A02_TIMER_DESTROY_FLAME):
				{
					GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
					if (controller)
					{
						Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_GDI_NOTICES_FLAME_DEAD, MX0_A02_CUSTOM_PARAM_DEFAULT, 1.0f);
					}
					Commands->Apply_Damage (obj, 10000.0f, "Blamokiller", obj);
					break;
				}
			case (MX0_A02_TIMER_DESTROY_MINIGUNNER):
				{
					Commands->Apply_Damage (obj, 10000.0f, "Blamokiller", obj);
					break;
				}
			case (MX0_A02_TIMER_ENGINEER_FIX_TANK):
				{
					GameObject * tank = Commands->Find_Object (medtank_id);
					if (tank)
					{
						Vector3 tank_pos = Commands->Get_Position (tank);
						float tank_facing = Commands->Get_Facing (tank);
						Commands->Destroy_Object (tank);
						GameObject * newtank = Commands->Create_Object ("GDI_Medium_Tank_Player", tank_pos);
						if (newtank)
						{
							Commands->Attach_Script( obj, "M00_Send_Object_ID", "1400041,13,0.0f");
							Commands->Set_Facing (newtank, tank_facing);
							MX0_A02_Say_Something (obj, MX0_A02_SPEECH_ENGINEER_DONE, true);
							Commands->Attach_Script (newtank, "MX0_A02_GDI_MEDTANK", "");
						}
					}
					break;
				}
			case (MX0_A02_TIMER_WAITFOR_MOVETOTANK):
				{
					GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
					if (controller)
					{
						Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_ENGINEER_MOVETOTANK, MX0_A02_CUSTOM_PARAM_DEFAULT);
					}
					break;
				}
			case (MX0_A02_TIMER_WAITFOR_MOVETORUBBLE):
				{
					GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
					if (controller)
					{
						Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_ENGINEER_02_REGISTER, MX0_A02_CUSTOM_PARAM_DEFAULT);
					}
					ActionParamsStruct params;
					params.Set_Basic(this, MX0_A02_PRIORITY_FORCED_ACTION, MX0_A02_ACTION_ENGINEER_02_RUBBLE);
					params.Set_Movement(Vector3(-76.3f,-45.0f,0.1f), RUN, 1.0f, false);
					Commands->Action_Goto (obj, params);
					break;
				}
			default:
				{
					break;
				}
			}
		}
	}

	void MX0_A02_Say_Something (GameObject * obj, int speech_id, bool face_target)
	{
		if (active_actor)
		{
			int priority = 100;
			const char *conv_name = ("MX0_A02_PREAMB_01"); //DEFAULT
			switch (speech_id)
			{
			case (1):
				{
					conv_name = ("MX0_GDITROOPER2_051");
					break;
				}
			case (2):
				{
					conv_name = ("MX0_GDITROOPER3_053");
					break;
				}
			case (3):
				{
					conv_name = ("MX0_GDITROOPER4_054");
					break;
				}
			case (4):
				{
					conv_name = ("MX0_GDITROOPER2_056");
					break;
				}
			case (5):
				{
					conv_name = ("MX0_GDITROOPER1_057");
					break;
				}
			case (6):
				{
					conv_name = ("MX0_GDITROOPER4_058");
					break;
				}
			case (7):
				{
					conv_name = ("MX0_GDITROOPER4_060");
					break;
				}
			case (8):
				{
					conv_name = ("MX0_GDITROOPER2_062");
					break;
				}
			case (9):
				{
					conv_name = ("MX0_GDITROOPER1_063");
					break;
				}
			case (10):
				{
					conv_name = ("MX0_GDITROOPER3_064");
					break;
				}
			case (11):
				{
					conv_name = ("MX0_GDITROOPER4_065");
					break;
				}
			case (MX0_A02_SPEECH_GDI_02_BECKON):
				{
					conv_name = ("MX0_GDITROOPER2_069"); //DEBUG "Captain Havoc! This way sir!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_01_STARTUP):
				{
					conv_name = ("MX0_GDITROOPER1_066"); //DEBUG "Reinforcements? There's just one guy!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_02_STARTUP):
				{
					conv_name = ("MX0_GDITROOPER2_067"); //DEBUG "Hey, it's Havoc!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_01_STARTUP_02):
				{
					conv_name = ("MX0_GDITROOPER1_068"); //DEBUG "Are we glad to see you!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_03_STARTUP):
				{
					priority = 99;
					conv_name = ("MX0_GDITROOPER3_070"); //DEBUG "Payback time!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_SOLDIER_CONGRATS_01):
				{
					conv_name = ("MX0_GDITROOPER1_071"); //DEBUG "Hey, I got one!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_SOLDIER_CONGRATS_02):
				{
					conv_name = ("MX0_GDITROOPER4_072"); //DEBUG "Nice shot!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_SOLDIER_CONGRATS_03):
				{
					conv_name = ("MX0_GDITROOPER3_073"); //DEBUG "There's one!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_SOLDIER_CONGRATS_04):
				{
					conv_name = ("MX0_GDITROOPER2_074"); //DEBUG "Come and get it!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_PLAYER_CONGRATS_01):
				{
					conv_name = ("MX0_GDITROOPER1_075"); //DEBUG "Great shot, sir!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_PLAYER_CONGRATS_02):
				{
					conv_name = ("MX0_GDITROOPER4_076"); //DEBUG "You got him, Havoc!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_PLAYER_CONGRATS_03):
				{
					conv_name = ("MX0_GDITROOPER2_078"); //DEBUG "Outstanding Havoc!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_PLAYER_CONGRATS_04):
				{
					conv_name = ("MX0_GDITROOPER3_ALT13"); //DEBUG "Watch it!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_PLAYER_CONGRATS_05):
				{
					conv_name = ("MX0_GDITROOPER1_ALT09"); //DEBUG "Yeah!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_PLAYER_CONGRATS_06):
				{
					conv_name = ("MX0_GDITROOPER4_ALT07"); //DEBUG "Go!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_PLAYER_CONGRATS_07):
				{
					conv_name = ("MX0_GDITROOPER3_ALT13"); //DEBUG "Good work!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_PLAYER_CONGRATS_08):
				{
					conv_name = ("MX0_GDITROOPER1_ALT10"); //DEBUG "Alright!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_PLAYER_CONGRATS_09):
				{
					conv_name = ("MX0_GDITROOPER2_ALT01"); //DEBUG "Nice shot!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_PLAYER_CONGRATS_10):
				{
					conv_name = ("MX0_GDITROOPER4_ALT06"); //DEBUG "Yeah!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_PLAYER_RETREAT_01):
				{
					conv_name = ("MX0_GDITROOPER1_079"); //DEBUG "Don't leave us sir!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_PLAYER_RETREAT_02):
				{
					conv_name = ("MX0_GDITROOPER2_082"); //DEBUG "Hey! We need your help!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_PLAYER_RETREAT_03):
				{
					conv_name = ("MX0_GDITROOPER3_081"); //DEBUG "Havoc! Come back!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_PLAYER_RETREAT_04):
				{
					conv_name = ("MX0_GDITROOPER4_080"); //DEBUG "Wait! Where are you going Havoc?"
					break;
				}
			case (MX0_A02_SPEECH_GDI_NOTICES_NOD_01):
				{
					conv_name = ("MX0_GDITROOPER1_086"); //DEBUG "Up there on the rocks!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_RESPONDS_01):
				{
					conv_name = ("MX0_GDITROOPER1_088"); //DEBUG "Ha! Look at that!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_SPOTS_HELI_DESTROY):
				{
					conv_name = ("MX0_GDITROOPER2_093"); //DEBUG "Chopper down and out!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_SPOTS_HELI_01):
				{
					conv_name = ("MX0_GDITROOPER2_092"); //DEBUG "Chopper! They're dropping more troops!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_SPOTS_HELI_02):
				{
					conv_name = ("MX0_GDITROOPER2_095"); //DEBUG "Another chopper - take it out!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_NOTICES_FLAME):
				{
					conv_name = ("MX0_GDITROOPER3_096"); //DEBUG "Flame Troopers! Watch your back!"
					break;
				}
			case (MX0_A02_SPEECH_GDI_NOTICES_FLAME_DEAD):
				{
					conv_name = ("MX0_GDITROOPER4_097"); //DEBUG "Roasted!"
					break;
				}
			case (MX0_A02_SPEECH_NOD_HELI_DESTROYED_01):
				{
					conv_name = ("MX0_GDITROOPER1_099"); //DEBUG "All Right!"
					break;
				}
			case (MX0_A02_SPEECH_NOD_HELI_DESTROYED_02):
				{
					conv_name = ("MX0_GDITROOPER2_098"); //DEBUG "Woo hoo!"
					break;
				}
			case (MX0_A02_SPEECH_ENDING_01):
				{
					conv_name = ("MX0_GDITROOPER2_105"); //DEBUG "We pushed 'em back!"
					break;
				}
			case (MX0_A02_SPEECH_ENDING_02):
				{
					conv_name = ("MX0_GDITROOPER4_106"); //DEBUG "Look! They're on the run!"
					break;
				}
			case (MX0_A02_SPEECH_ENDING_03):
				{
					conv_name = ("MX0_GDITROOPER1_107"); //DEBUG "We did it!"
					break;
				}
			case (MX0_A02_SPEECH_ENDING_04):
				{
					conv_name = ("MX0_GDITROOPER2_108"); //DEBUG "Thanks Havoc. We owe you big time."
					break;
				}
			case (MX0_A02_SPEECH_ENDING_05):
				{
					conv_name = ("MX0_GDITROOPER3_109"); //DEBUG "Recon One to Eagle Base. We've taken casualties, but we're okay."
					break;
				}
			case (MX0_A02_SPEECH_ENGINEER_TANK_01):
				{
					conv_name = ("MX0_ENGINEER1_115"); //DEBUG "Stand by for repairs."
					break;
				}
			case (MX0_A02_SPEECH_ENGINEER_DONE):
				{
					conv_name = ("MX0_ENGINEER1_118"); //DEBUG "Your tank is repaired and ready to roll, Havoc."
					break;
				}
			case (MX0_A02_SPEECH_UNSTOPPABLE):
				{
					conv_name = ("MX0_GDITROOPER1_119"); //DEBUG "You'll be unstoppable in that tank, sir!"
					break;
				}
			case (MX0_A02_SPEECH_TANKSAY_01):
				{
					conv_name = ("MX0_ENGINEER2_120"); //DEBUG "I'll clear the road once you're inside the tank, Havoc."
					break;
				}
			case (MX0_A02_SPEECH_TANKSAY_02):
				{
					conv_name = ("MX0_GDITROOPER1_121"); //DEBUG "Your tank's ready and waiting, sir!"
					break;
				}
			case (MX0_A02_SPEECH_TANKSAY_03):
				{
					conv_name = ("MX0_GDITROOPER2_122"); //DEBUG "The tank's yours, Havoc! Rock and roll!"
					break;
				}
			case (MX0_A02_SPEECH_TANKSAY_04):
				{
					conv_name = ("MX0_ENGINEER2_123"); //DEBUG "C4's set... fire in the hole!"
					break;
				}
			case (MX0_A02_SPEECH_APC_DOWN):
				{
					conv_name = ("MX0_GDITROOPER3_090"); //DEBUG "Argh! We lost our APC!"
					break;
				}
			case (MX0_A02_SPEECH_WRONGWAY_01):
				{
					conv_name = ("MX0_A02_SPEECH_WRONGWAY_01");
					break;
				}
			case (MX0_A02_SPEECH_WRONGWAY_02):
				{
					conv_name = ("MX0_A02_SPEECH_WRONGWAY_02");
					break;
				}
			case (MX0_A02_SPEECH_WRONGWAY_03):
				{
					conv_name = ("MX0_A02_SPEECH_WRONGWAY_03");
					break;
				}
			default:
				{
					break;
				}
			}
			int conversation = Commands->Create_Conversation (conv_name, priority, 300.0f, false);
			if (face_target)
			{
				Commands->Join_Conversation (obj, conversation, false, true, true);
			}
			else
			{
				Commands->Join_Conversation (obj, conversation, false, true, true);
			}
			Commands->Join_Conversation(STAR, conversation, false, false, false);
			Commands->Start_Conversation (conversation, speech_id);
			Commands->Monitor_Conversation (obj, conversation);
		}
	}
};


// This script is for the vehicles to prevent them from taking any further damage.

DECLARE_SCRIPT (MX0_A02_GDI_VEHICLE, "")
{
	void Created (GameObject * obj)
	{
		Commands->Set_Health (obj, 10.0f);
	}

	void Damaged (GameObject * obj, GameObject * damager, float amount)
	{
		Commands->Set_Health (obj, 10.0f);
	}
};


// This script is for the GDI Medium Tank. It is a trigger for entry that tells the controller.

DECLARE_SCRIPT (MX0_A02_GDI_MEDTANK, "")
{
	bool entered;

	REGISTER_VARIABLES()
	{
		SAVE_VARIABLE (entered, 1);
	}
	
	void Created (GameObject * obj)
	{
		entered = false;
	}

	void Damaged (GameObject * obj, GameObject * damager, float amount)
	{
		Commands->Set_Health (obj, Commands->Get_Max_Health (obj));
	}

	void Custom (GameObject * obj, int type, int param, GameObject * sender)
	{
		if ((type == CUSTOM_EVENT_VEHICLE_ENTERED) && (!entered))
		{
			entered = true;
			Commands->Fade_Background_Music( "Level 0 Tiberium.mp3", 2, 2);
			GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
			if (controller)
			{
				Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_ENTERED_TANK, MX0_A02_CUSTOM_PARAM_DEFAULT);
			}
		}
	}
};


// This script is for the GDI APC, which cannot take damage until it is to be destroyed.

DECLARE_SCRIPT (MX0_A02_GDI_APC, "")
{
	bool can_damage;

	void Created (GameObject * obj)
	{
		can_damage = false;
	}

	void Damaged (GameObject * obj, GameObject * damager, float amount)
	{
		if (!can_damage)
		{
			Commands->Set_Health (obj, Commands->Get_Max_Health (obj));
		}
	}

	void Enemy_Seen (GameObject * obj, GameObject * enemy)
	{
		ActionParamsStruct params;
		params.Set_Basic(this, MX0_A02_PRIORITY_DEFAULT_SHOOT, MX0_A02_ACTION_DEFAULT);
		params.Set_Attack(enemy, 300.0f, 0.0f, true);
		params.AttackCheckBlocked = false;
		Commands->Action_Attack (obj, params);
	}

	void Custom (GameObject * obj, int type, int param, GameObject * sender)
	{
		if (type == MX0_A02_CUSTOM_TYPE_DESTROY_APC)
		{
			can_damage = true;
			Commands->Apply_Damage (obj, 10000.0f, "Blamokiller", sender);
		}
		else if (type == MX0_A02_CUSTOM_TYPE_STARTUP)
		{
			Commands->Innate_Enable (obj);
			Commands->Enable_Enemy_Seen (obj, true);
		}
	}
};


// This script is for the trigger zone that activates the entire sequence.

DECLARE_SCRIPT (MX0_A02_ZONE_STARTUP, "")
{
	void Entered (GameObject * obj, GameObject * enterer)
	{
		GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
		if (controller)
		{
			Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_STARTUP, MX0_A02_CUSTOM_PARAM_DEFAULT);
			Commands->Destroy_Object (obj);
		}
	}
};


// This script is for the helicopters to send a custom to the controller when they are destroyed.

DECLARE_SCRIPT (MX0_A02_HELICOPTER, "ActorID=0:int")
{
	void Created (GameObject * obj)
	{
		int actor_id = Get_Int_Parameter ("ActorID");
		if (actor_id)
		{
			Commands->Start_Timer (obj, this, 23.0f, MX0_A02_TIMER_DESTROY_HELI_02);
		}
	}

	void Killed (GameObject * obj, GameObject * killer)
	{
		int actor_id = Get_Int_Parameter ("ActorID");
		if (!actor_id)
		{
			GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
			if (controller)
			{
				Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_HELI_DESTROYED, MX0_A02_CUSTOM_PARAM_DEFAULT);
			}
		}
		else
		{
			GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
			if (controller)
			{
				Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_HELI_DESTROYED_02, MX0_A02_CUSTOM_PARAM_DEFAULT);
			}
		}
	}

	void Timer_Expired (GameObject * obj, int timer_id)
	{
		if (timer_id == MX0_A02_TIMER_DESTROY_HELI_02)
		{
			Commands->Apply_Damage (obj, 10000.0f, "Blamokiller", NULL);
		}
	}
};


// This is a default script for testing. It shuts off a unit.

DECLARE_SCRIPT (MX0_A02_DEFAULT_OFF, "")
{
	void Created (GameObject * obj)
	{
		Commands->Innate_Disable (obj);
	}

	void Damaged (GameObject * obj, GameObject * damager, float amount)
	{
		if (damager != STAR)
		{
			Commands->Apply_Damage (obj, 10000.0f, "Blamokiller", obj);
		}
	}
};

DECLARE_SCRIPT (MX0_A02_ZONE_DEFAULT_ON, "")
{
	void Entered (GameObject * obj, GameObject * enterer)
	{
		GameObject * controller = Commands->Find_Object (MX0_A02_CONTROLLER_ID);
		if (controller)
		{
			Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_MAIN_STARTUP, MX0_A02_CUSTOM_PARAM_DEFAULT);
			Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_GET_SNIPER_01_ID, 1200017);
			Commands->Send_Custom_Event (obj, controller, MX0_A02_CUSTOM_TYPE_GET_SNIPER_02_ID, 1200023);
		}
	}
};

/////////////////////////////////////


/* Evacuation System

  This system spawns soldiers near the base area that run to the dock and disappear behind
  the concrete bunker at the end. They are evacuating the base.

  1. When the commando passes the start zone, three soldiers are spawned with random time
  delays in one of two sets of coordinates. The coordinates used depend on which reinforcement
  swap zone the commando entered last. This helps insure that the commando cannot see the
  spawns as they take place. The soldiers run along one of three waypaths, with a random action
  priority that will make some attack and others not.

  2. If a soldier is killed, he spawns again. If a soldier makes it to the dock, he destroys
  himself and spawns again.

*/

const Vector3 M03_A05_spawn_location [3] =
{
	Vector3(-53.33f,37.58f,8.87f),
	Vector3(-111.40f,32.27f,9.31f),
	Vector3(-166.93f,8.75f,9.43f)
};

DECLARE_SCRIPT (M03_A05_Evac_Zone, "")
{
	bool script_active;
	bool spawn_set;

	void Created (GameObject * obj)
	{
		script_active = true;
		spawn_set = false;
	}

	void Entered (GameObject * obj, GameObject * enterer)
	{
		int count;

		if ((Commands->Is_A_Star(enterer)) && (script_active))
		{
			script_active = false;

			for (count = 0;count < 3;count++)
			{
				Create_Soldier(M03_A05_spawn_location [count]);
			}
		}
	}

	void Create_Soldier (Vector3 position)
	{
		GameObject* soldier_obj_1;
		soldier_obj_1 = Commands->Create_Object("Nod MiniGunner", position);

		ActionParamsStruct params;
		
		if (soldier_obj_1)
		{
			Commands->Attach_Script(soldier_obj_1, "M00_Trigger_When_Destroyed_RMV", "1,2,1,0,1000004,1000,1,0.0,0.0,0");
			if (Commands->Get_Random(0.0f,1.0f) < 0.75f)
			{
				params.Set_Basic(this, 99, 1);
			}
			else
			{
				params.Set_Basic(this, 85, 1);
			}
			params.Set_Movement(Vector3(-330.0f,75.0f,4.0f), 1.0f, 1.0f);
			Commands->Action_Goto(soldier_obj_1, params);
		}
	}

	void Custom (GameObject * obj, int type, int param, GameObject * sender)
	{
		Vector3 spawn_set_location;

		if (type == 1000) // Destroyed Soldier Needs Spawning
		{
			if (spawn_set)
			{
				spawn_set_location = Vector3(-167.38f,0.09f,9.46f);
			}
			else
			{
				spawn_set_location = Vector3(-99.50f,80.53f,9.00f);
			}
			Create_Soldier (spawn_set_location);
		}
		if (type == 1001) // Player entered Zone A
		{
			spawn_set = true;
		}
		if (type == 1002) // Player entered Zone B
		{
			spawn_set = false;
		}
	}
};


DECLARE_SCRIPT (M00_Test_Sound_RAD, "")
{
	void Created (GameObject * obj)
	{
		int id = Commands->Create_Conversation("M00_TEST_CONVERSATION", 100, 300, true);
		Commands->Stop_All_Conversations (); /// <--- This cancels the following conversation!
		Commands->Join_Conversation(NULL, id);
		Commands->Join_Conversation (STAR, id, true, false, false);
		Commands->Start_Conversation(id);
	}
};