--[[
	m22.lua
	SR3 Mission Script
	DATE: 08-09-10
	AUTHOR:	John Karczewski
]]--


-- Debug flags --

-- Tweakable Parameters --
	
	-- Battle Zones --
	NUM_ZONES_TO_COMPLETE_TO_SUCCEED = 2
	NOTORIETY_FAILSAFE_TIME = 1 * 60 -- Time before notoriety spawns are automatically re-enabled during battle zones.
	NUM_ZONE_ENEMIES_TO_RELEASE = 20  -- Number of initial spawn enemies that will be released immediately when they are killed.
	
	-- Stop Killbane --
	NUM_HITS_TO_STOP_PLANE = 4
	
	-- Save the Saints --
	STATUE_EXPLOSION_TIME = 300  -- seconds
	
	-- Boss Battle -- 
	PLAYER_STARTING_FART_IN_JAR_AMMO = 0
	FART_IN_JAR_RESPAWN_TIME = 15 -- seconds
	
	-- Kia --
	KIA_VTOL_RESPAWN_TIME = 5
	VTOL_HOVER_TIME = 5
	KIA_COOP_REINFORCEMENTS_TIME = 10
	
	KIA_WEAPON_SPREAD_MULTIPLIER = 0.25
	KIA_DESIRED_PLAYER_KEEP_DISTANCE = 10.0	-- distance from the player Kia will try to maintain
	KIA_ATTACK_POSITION_LEASH_RADIUS = 5.0 -- leash radius while Kia is at an attack navpoint position
	KIA_DEFENSIVE_POSITION_LEASH_RADIUS = 1.0 -- defensive leash radius (while in cover)
	KIA_NUM_TIMES_TO_VOMIT = 2 -- number of times Kia should vomit when hit with a FIAJ
	KIA_DAMAGE_MULTIPLIER_HUMAN_SHIELD = 0.5 -- damage multiplier for Kia when she has Shaundi as a human shield
	KIA_DAMAGE_MULTIPLIER_VOMITING = 1.75 -- damage multiplier for Kia when she is vomiting from a FIAJ
	
	KIA_ATTACK_VTOL_IDLE_TIME = 10.0
	KIA_ATTACK_VTOL_PRE_ATTACK_TIME = 3.0
	KIA_ATTACK_VTOL_POST_ATTACK_TIME = 2.0
	KIA_ATTACK_VTOL_RESAPWN_TIME = 20.0
	
	KIA_TEMPORARY_WEAPON = "Special-SonicGun"
	KIA_TEMPORARY_GRENADE = "flashbang"
	KIA_FIAJ_REACTION_SYNCED_ANIM = "M22_Human_Shield_FIAJ"

-- Groups --

	M22_groups = {
	
	---------------------------
	----- ZONE ONE GROUPS -----
	---------------------------
	
	--[[
		Zone_One_Initial = { 
			name = "Group_battle_zone 001",
			members = { "NPC_sind_one 001", "NPC_sind_one 002", "NPC_sind_one 003", "NPC_sind_one 004", "NPC_sind_one 005",
						"NPC_sind_one 006", "NPC_sind_one 007", "NPC_sind_one 008", "NPC_sind_one 009", "NPC_sind_one 010",
						"NPC_sind_one 011", "NPC_sind_one 012", "NPC_sind_one 013", "NPC_sind_one 014", "NPC_sind_one 015",
						"NPC_sind_one 016", "NPC_sind_one 017", "NPC_sind_one 018", "NPC_sind_one 019", "NPC_sind_one 020",
						"NPC_sind_one 021", "NPC_sind_one 022", "NPC_sind_one 023", "NPC_sind_one 024",
						
						"NPC_stag_one 001", "NPC_stag_one 002", "NPC_stag_one 003", "NPC_stag_one 004", "NPC_stag_one 005",
						"NPC_stag_one 006", "NPC_stag_one 007", "NPC_stag_one 008", "NPC_stag_one 009", "NPC_stag_one 010",
						"NPC_stag_one 011", "NPC_stag_one 012", "NPC_stag_one 013", "NPC_stag_one 014", "NPC_stag_one 015",
						"NPC_stag_one 016", "NPC_stag_one 017", "NPC_stag_one 018", "NPC_stag_one 019", "NPC_stag_one 020",
						"NPC_stag_one 021", "NPC_stag_one 022", "NPC_stag_one 023", "NPC_stag_one 024" },
						
			vehicles = { "veh_Zone1_synd 001", "veh_Zone1_synd 002", "veh_Zone1_synd 003",
						"veh_Zone1_synd 004", "veh_Zone1_synd 005", "veh_Zone1_synd 006", "veh_Zone1_stag 001", "veh_Zone1_stag 002",
						"veh_Zone1_stag 003", "veh_Zone1_stag 004", "veh_Zone1_stag 005", "veh_Zone1_stag 006", "veh_Zone1_stag 007" },
		},

		Zone_One_Courtesy = {
			name = "Group_battle_zone_courtesy 001",
			vehicles = { "Vehicle_Zone1_Courtesy 001", "Vehicle_Zone1_Courtesy 002" },
		},
	--]]
		
		---------------------------
		----- ZONE TWO GROUPS -----
		---------------------------	
		
		Zone_Two_Initial = { 
			name = "Group_battle_zone 002",
			members = { "NPC_sind_two 001", "NPC_sind_two 002", "NPC_sind_two 003", "NPC_sind_two 004", "NPC_sind_two 005",
						"NPC_sind_two 006", "NPC_sind_two 007", "NPC_sind_two 008", "NPC_sind_two 009", "NPC_sind_two 010",
						"NPC_sind_two 011", "NPC_sind_two 012", "NPC_sind_two 013", "NPC_sind_two 014", "NPC_sind_two 015",
						"NPC_sind_two 016", "NPC_sind_two 017", "NPC_sind_two 018", "NPC_sind_two 019", "NPC_sind_two 020",
						"NPC_sind_two 021", "NPC_sind_two 022", "NPC_sind_two 023", "NPC_sind_two 024",
						
						"NPC_stag_two 001", "NPC_stag_two 002", "NPC_stag_two 003", "NPC_stag_two 004", "NPC_stag_two 005",
						"NPC_stag_two 006", "NPC_stag_two 007", "NPC_stag_two 008", "NPC_stag_two 009", "NPC_stag_two 010",
						"NPC_stag_two 011", "NPC_stag_two 012", "NPC_stag_two 013", "NPC_stag_two 014", "NPC_stag_two 015",
						"NPC_stag_two 016", "NPC_stag_two 017", "NPC_stag_two 022", "NPC_stag_two 023", "NPC_stag_two 024", 
						"NPC_stag_two 025", "NPC_stag_two 026", "NPC_stag_two 027", "NPC_stag_two 028" },
		},
		
		Zone_Two_Vehicles = {
			name = "Group_battle_zone_vehicles 2",
			spawned = false,
		},
		
		Zone_Two_Courtesy = { 
			name = "Group_battle_zone_courtesy 002",
			vehicles = { "Vehicle_Zone2_Courtesy 001", "Vehicle_Zone2_Courtesy 002" },
		},
		
		Zone_Two_Saints = {
			name = "Group_BZ2_Saints 001",
			cars = {
				{
					vehicle = "veh_bz2_saint 001",
					members = { "npc_bz2_saint 001", "npc_bz2_saint 002", "npc_bz2_saint 003" },
				},
				{
					vehicle = "veh_bz2_saint 002",
					members = { "npc_bz2_saint 004", "npc_bz2_saint 005", "npc_bz2_saint 006" },
				},
			},
			start_positions = {
				{
					nav = "nav_BZ2_saints_start 001", 
					path = "path_bz2_saints 1",
				},
				{
					nav = "nav_BZ2_saints_start 002", 
					path = "path_bz2_saints 2",
				},
				{
					nav = "nav_BZ2_saints_start 003",
					path = "path_bz2_saints 3",
				},
			},
		},
	

		---------------------------
		----- ZONE Three GROUPS ---
		---------------------------	
		
		Zone_Three_Initial = { 
			name = "Group_battle_zone 003",
			members = { "NPC_sind_three 001", "NPC_sind_three 002", "NPC_sind_three 003", "NPC_sind_three 004", "NPC_sind_three 005",
						"NPC_sind_three 006", "NPC_sind_three 007", "NPC_sind_three 008", "NPC_sind_three 009", "NPC_sind_three 010",
						"NPC_sind_three 011", "NPC_sind_three 012", "NPC_sind_three 013", "NPC_sind_three 014", "NPC_sind_three 015",
						"NPC_sind_three 016", "NPC_sind_three 017", "NPC_sind_three 018", "NPC_sind_three 019", "NPC_sind_three 020",
						"NPC_sind_three 021", "NPC_sind_three 022", "NPC_sind_three 023", "NPC_sind_three 024",

						"NPC_stag_three 001", "NPC_stag_three 002", "NPC_stag_three 003", "NPC_stag_three 004", "NPC_stag_three 005",
						"NPC_stag_three 006", "NPC_stag_three 007", "NPC_stag_three 008", "NPC_stag_three 009", "NPC_stag_three 010",
						"NPC_stag_three 011", "NPC_stag_three 012", "NPC_stag_three 013", "NPC_stag_three 014", "NPC_stag_three 015",
						"NPC_stag_three 016", "NPC_stag_three 017", "NPC_stag_three 018", "NPC_stag_three 019", "NPC_stag_three 020",
						"NPC_stag_three 021", "NPC_stag_three 022", "NPC_stag_three 023", "NPC_stag_three 024" },
		},
		
		Zone_Three_Vehicles = {
			name = "Group_battle_zone_vehicles 3",
			spawned = false,
		},
		
		Zone_Three_Courtesy = {
			name = "Group_battle_zone_courtesy 003",
			vehicles = { "Vehicle_Zone3_Courtesy 001", "Vehicle_Zone3_Courtesy 002" },
		},
		
		Zone_Three_Saints = {
			name = "Group_BZ3_Saints 001",
			cars = {
				{
					vehicle = "veh_bz3_saint 001",
					members = { "npc_bz3_saint 001", "npc_bz3_saint 002", "npc_bz3_saint 003" },
				},
				{
					vehicle = "veh_bz3_saint 002",
					members = { "npc_bz3_saint 004", "npc_bz3_saint 005", "npc_bz3_saint 006" },
				},				
			},
			start_positions = {
				{
					nav = "nav_BZ3_saints_start 001", 
					path = "path_bz3_saints 1",
				},
				{
					nav = "nav_BZ3_saints_start 002", 
					path = "path_bz3_saints 2",
				},
				{
					nav = "nav_BZ3_saints_start 003",
					path = "path_bz3_saints 3",
				},
			},
		},
		
		---------------------------
		----- ZONE FOUR GROUPS ----
		---------------------------	
		
		Zone_Four_Initial = { 
			name = "Group_battle_zone 004",
			members = { "NPC_sind_four 001", "NPC_sind_four 002", "NPC_sind_four 003", "NPC_sind_four 004", "NPC_sind_four 005",
						"NPC_sind_four 006", "NPC_sind_four 007", "NPC_sind_four 008", "NPC_sind_four 009", "NPC_sind_four 010",
						"NPC_sind_four 011", "NPC_sind_four 015", "NPC_sind_four 016", "NPC_sind_four 017",	"NPC_sind_four 018",
						"NPC_sind_four 019", "NPC_sind_four 020", "NPC_sind_four 021", "NPC_sind_four 022",	"NPC_sind_four 024", 
						"NPC_sind_four 025", "NPC_sind_four 026", "NPC_sind_four 029", "NPC_sind_four 030",

						"NPC_stag_four 001", "NPC_stag_four 002", "NPC_stag_four 003", "NPC_stag_four 004", "NPC_stag_four 005",
						"NPC_stag_four 006", "NPC_stag_four 007", "NPC_stag_four 008", "NPC_stag_four 009", "NPC_stag_four 010",
						"NPC_stag_four 011", "NPC_stag_four 012", "NPC_stag_four 013", "NPC_stag_four 014", "NPC_stag_four 015",
						"NPC_stag_four 016", "NPC_stag_four 017", "NPC_stag_four 018", "NPC_stag_four 019", "NPC_stag_four 020",
						"NPC_stag_four 021", "NPC_stag_four 022", "NPC_stag_four 023", "NPC_stag_four 024" },
		},
		
		Zone_Four_Vehicles = {
			name = "Group_battle_zone_vehicles 4",
			spawned = false,
		},
		
		Zone_Four_Courtesy = {
			name = "Group_battle_zone_courtesy 004",
			vehicles = { "Vehicle_Zone4_Courtesy 001", "Vehicle_Zone4_Courtesy 002" },
		},
		
		Zone_Four_Saints = {
			name = "Group_BZ4_Saints 001",
			cars = {
				{
					vehicle = "veh_bz4_saint 001",
					members = { "npc_bz4_saint 001", "npc_bz4_saint 002", "npc_bz4_saint 003" },
				},
				{
					vehicle = "veh_bz4_saint 002",
					members = { "npc_bz4_saint 004", "npc_bz4_saint 005", "npc_bz4_saint 006" },
				}
			},
			start_positions = {
				{
					nav = "nav_BZ4_saints_start 001", 
					path = "path_bz4_saints 1",
				},
				{
					nav = "nav_BZ4_saints_start 002", 
					path = "path_bz4_saints 2",
				},
				{
					nav = "nav_BZ4_saints_start 003",
					path = "path_bz4_saints 3",
				},
			},
		},

		
		---------------------------
		----- ARMORY GROUPS -----
		---------------------------	
		
		Armory_Initial = { 
			name = "Group_armory",
			members = { "NPC_synd_armory 001", "NPC_synd_armory 002", "NPC_synd_armory 003", "NPC_synd_armory 005", "NPC_synd_armory 006",
						"NPC_synd_armory 007", "NPC_synd_armory 008", "NPC_synd_armory 009", "NPC_synd_armory 010",	"NPC_synd_armory 011",
						"NPC_synd_armory 012", "NPC_synd_armory 013", "NPC_synd_armory 014", "NPC_synd_armory 015",	"NPC_synd_armory 016",
						"NPC_synd_armory 017", "NPC_synd_armory 018", "NPC_synd_armory 019", "NPC_synd_armory 020",	"NPC_synd_armory 021",
						"NPC_synd_armory 022", "NPC_synd_armory 023", "NPC_synd_armory 024", "NPC_synd_armory 025",

						"NPC_stag_armory 001", "NPC_stag_armory 003", "NPC_stag_armory 004", "NPC_stag_armory 005",	"NPC_stag_armory 006",
						"NPC_stag_armory 007", "NPC_stag_armory 009", "NPC_stag_armory 010", "NPC_stag_armory 011", "NPC_stag_armory 012",
						"NPC_stag_armory 013", "NPC_stag_armory 014", "NPC_stag_armory 015", "NPC_stag_armory 016", "NPC_stag_armory 017",
						"NPC_stag_armory 018", "NPC_stag_armory 019", "NPC_stag_armory 020", "NPC_stag_armory 021", "NPC_stag_armory 022",
						"NPC_stag_armory 023", "NPC_stag_armory 024", "NPC_stag_armory 025", "NPC_stag_armory 026" },
		},
		
		Armory_Vehicles = {
			name = "Group_armory_vehicles",
			spawned = false,
		},
		
		Armory_Courtesy = {
			name = "Group_Courtesy_Armory",
			vehicles = { "Vehicle_Armory_Courtesy 001", "Vehicle_Armory_Courtesy 002" },
		},

		Statue_Boats = {
			name = "Group_heli",
			members = { "veh_StatueHeli", "veh_StatueHeli<001>" },
		},
		
		---------------------------
		----- MISC GROUPS -----
		---------------------------	
		
		Start_Vehicle = {
			name = "Group_Start_Vehicle",
			vehicles = { "Vehicle_Courtesy 001", "Vehicle_Courtesy 002" },
		},
		
		Oleg_and_Pierce = {
			name = "Group_Oleg_and_Pierce",
			members = { "Oleg_gameplay", "Pierce_gameplay"},
			oleg = "Oleg_gameplay",
			pierce = "Pierce_gameplay"
		},
		
		Angel = {
			name = "Group_Angel",
			members = { "Angel_gameplay" },
			vehicle = "Angel_Car",
			npc = "Angel_gameplay"
		},
		
		Angels_Attackers = {
			name = "Group_Angels_Attackers",
			members = { "Angel_attacker_NPC 001", "Angel_attacker_NPC 002", "Angel_attacker_NPC 003",
						"Angel_attacker_NPC 004", "Angel_attacker_NPC 005", "Angel_attacker_NPC 006",
						"Angel_attacker_NPC 007", "Angel_attacker_NPC 008" },
			vehicles = { "Angel_attacker_Car 001", "Angel_attacker_Car 002" }
		},
		
		Airport = {
			name = "Group airport initial",
			members = { "Killbane_gameplay" },
			killbane = "Killbane_gameplay" -- The cutscene creates a dude named "Killbane" that conflicts...
		},
		
		Airport_Roadblock_one = {
			name = "Group airport roadblock 001",
			members = { "Roadblock_1_NPC 001", "Roadblock_1_NPC 002", "Roadblock_1_NPC 003", "Roadblock_1_NPC 004",
						"Roadblock_1_NPC 005", "Roadblock_1_NPC 006", "Roadblock_1_NPC 007", "Roadblock_1_NPC 008" },
			cars = { "Roadblock_1_Vehicle 001", "Roadblock_1_Vehicle 002", "Roadblock_1_Vehicle 003", "Roadblock_1_Vehicle 004",
					 "Roadblock_1_Vehicle 005", "Roadblock_1_Vehicle 006", "Roadblock_1_Vehicle 007", "Roadblock_1_Vehicle 008" }
		},
		
		Airport_Roadblock_two = {
			name = "Group airport roadblock 002",
			members = { "Roadblock_2_NPC 001", "Roadblock_2_NPC 002", "Roadblock_2_NPC 003", "Roadblock_2_NPC 004" },
			cars = { "Roadblock_2_Vehicle 001", "Roadblock_2_Vehicle 002", "Roadblock_2_Vehicle 003", "Roadblock_2_Vehicle 004" }
		},

		Airport_Roadblock_three = {
			name = "Group airport roadblock 003",
			members = { "Roadblock_3_NPC 001", "Roadblock_3_NPC 002", "Roadblock_3_NPC 003", "Roadblock_3_NPC 004" },
			cars = { "Roadblock_3_Vehicle 001", "Roadblock_3_Vehicle 002", "Roadblock_3_Vehicle 003", "Roadblock_3_Vehicle 004" }
		},
		
		Airport_Roadblock_four = {
			name = "Group airport roadblock 004",
			members = { "Roadblock_4_NPC 001", "Roadblock_4_NPC 002", "Roadblock_4_NPC 003", "Roadblock_4_NPC 004" },
			cars = { "Roadblock_4_Vehicle 001", "Roadblock_4_Vehicle 002", "Roadblock_4_Vehicle 003", "Roadblock_4_Vehicle 004" }
		},
		
		Killbane_QTE = {
			name = "Group_killbane_qte",
			members = "Killbane_qte",
			killbane = "Killbane_qte"
		},
		
		Killbane_QTE_Nomask = {
			name = "Group_killbane_qte_nomask",
			members = "Killbane_qte_nomask",
			killbane = "Killbane_qte_nomask"
		},
		
		Kia = {
			name = "Group_kia",
			members = "Kia_gameplay",
			kia = "Kia_gameplay",
		},
		
		Kia_Thugs = {
			name = "Group_kia_thugs",
			members = { "Kia_Thug 001", "Kia_Thug 002", "Kia_Thug 003", "Kia_Thug 004", "Kia_Thug 005", "Kia_Thug 006", 
						"Kia_Thug 007", "Kia_Thug 008", "Kia_Thug 009", "Kia_Thug 010", "Kia_Thug 011", "Kia_Thug 012" },		
		},
		
		Kia_Vtol1 = {
			name = "Group_kia_vtol 001",
			vtols = {
				{
					vtol = "veh_kia_vtol 001",
					members = { "char_kia_vtol_pilot 001" },
					path_intro = "path_kia_vtol_intro 001",
					path_looping = "path_kia_vtol_loop 001",
					loop_speed = 130,
					thread_id = INVALID_THREAD_HANDLE,
				},
				{
					vtol = "veh_kia_vtol 002",
					members = { "char_kia_vtol_pilot 002" },
					path_intro = "path_kia_vtol_intro 002",
					path_looping = "path_kia_vtol_loop 002",
					loop_speed = 122,
					thread_id = INVALID_THREAD_HANDLE,
				},				
				{
					vtol = "veh_kia_vtol 003",
					members = { "char_kia_vtol_pilot 003" },
					path_intro = "path_kia_vtol_intro 003",
					path_looping = "path_kia_vtol_loop 003",
					loop_speed = 135,
					thread_id = INVALID_THREAD_HANDLE,
				},
			},
			path_break_off = "path_kia_vtol_break_off 001",
			path_east_west = "path_kia_vtol_east_west 001",
			path_west_east = "path_kia_vtol_west_east 001",
		},
		
		vtol_reinforcement = {
			name = "Group_vtol_reinforcement",
			members = { "Kia_Thug 001", "Kia_Thug 002", "Kia_Thug 003", "Kia_Thug 004", "Kia_Thug 005", "Kia_Thug 006",
							"Vtol_driver 002" },
					vtol = "veh_reinforcement_vtol 001",
					pilots = { "Vtol_driver 002" },
					drop_offs = {
						soldiers = { "Kia_Thug 001", "Kia_Thug 002", "Kia_Thug 003",
										"Kia_Thug 004", "Kia_Thug 005", "Kia_Thug 006" },
						path = "Vtol_landing_path 001",
					},
					thread_id = -1,
		},
		
		vtol_coop_reinforcement = {
			name = "Group_vtol_coop_rein",
			members = { "Kia_Thug_Coop 001", "Kia_Thug_Coop 002", "Kia_Thug_Coop 003", "Kia_Thug_Coop 004",
							"Vtol_driver 003" },
					vtol = "veh_reinforcement_vtol 002",
					pilots = { "Vtol_driver 003" },
					drop_offs = {
						soldiers = { "Kia_Thug_Coop 001", "Kia_Thug_Coop 002", "Kia_Thug_Coop 003", "Kia_Thug_Coop 004" },
						path = "Vtol_landing_path 002",
					},
					thread_id = -1,
		},
		
		Statue_Base = {
			name = "Group_statue_base",
			members = { "Synd_Statue_NPC 001", "Synd_Statue_NPC 002", "Synd_Statue_NPC 003", "Synd_Statue_NPC 004", "Synd_Statue_NPC 005",
						"Synd_Statue_NPC 006", "Synd_Statue_NPC 007", "Synd_Statue_NPC 008", "Synd_Statue_NPC 009", "Synd_Statue_NPC 010",
						"Synd_Statue_NPC 011", "Synd_Statue_NPC 012", "Synd_Statue_NPC 013", "Synd_Statue_NPC 014", "Synd_Statue_NPC 015",
						"Synd_Statue_NPC 016", "Stag_Statue_NPC 001", "Stag_Statue_NPC 002", "Stag_Statue_NPC 003", "Stag_Statue_NPC 004",
						"Stag_Statue_NPC 005", "Stag_Statue_NPC 006", "Stag_Statue_NPC 007", "Stag_Statue_NPC 008", "Stag_Statue_NPC 009",
						"Stag_Statue_NPC 010", "Stag_Statue_NPC 011", "Stag_Statue_NPC 012", "Stag_Statue_NPC 013", "Stag_Statue_NPC 014",
						"Stag_Statue_NPC 015", "Stag_Statue_NPC 016" }
		},		
		
		Statue = {
			name = "Group_statue",
			members = { "Trapped_Saint 001", "Trapped_Saint 002", "Trapped_Saint 003", "Trapped_Saint 004" },
			saints = { "Trapped_Saint 001", "Trapped_Saint 002", "Trapped_Saint 003", "Trapped_Saint 004" },
		},
		
		Statue_CTE = {
			name = "Group_CTE_Statue_Stags",
		},
		
		Viola = {
			name = "Group_Viola",
			members = { "Viola_gameplay" },
			viola = "Viola_gameplay"
		},
		
		Kinzie = {
			name = "Group_Kinzie",
			members = { "Kinzie" },
			kinzie = "Kinzie",
		},
		Hostages = {
			name = "Group_Hostages",
			members = { "Mayor_Hostage", "Shaundi_Hostage" },
			shaundi = "Shaundi_Hostage",
			mayor = "Mayor_Hostage",
		},
		
		Kia_battle_props = {
			name = "Group_kia_boss_battle_props",
			fart_jars = { "Itm_fart_jar 001", "Itm_fart_jar 002", "Itm_fart_jar 003", "Itm_fart_jar 004" },
		},
		
		BattleZone_Finale1 = {
			name = "Group_BZfinale1",
			members = { "npc_BZFinale1 Brute1", },
		},
		
		BattleZone_Finale1v2 = {
			name = "Group_BZfinale1v2",
			members = { "npc_BZFinale1 Brute2", },
		},
		
		BattleZone_Finale2 = {
			name = "Group_BZfinale2",
			members = { "npc_BZFinale2 Stag 001", "npc_BZFinale2 Stag 002" },
			vehicle = "veh_BZFinale2 Tank",
		},
		
		BattleZone_Finale3v1 = {
			name = "Group_BZfinale3v1",
			members = { "npc_BZFinale3 Brute" },
		},
		
		BattleZone_Finale3v2 = {
			name = "Group_BZfinale3v2",
			members = { "npc_BZFinale3 Stag 001", "npc_BZFinale3 Stag 002" },
			vehicles = { "veh_BZFinale3 Tank" },
		},
		
		Armory_Finale1 = {
			name = "Group_ARMFinale1",
			members = { "npc_ARMFinale Brute1" },
		},
		
		Armory_Finale2 = {
			name = "Group_ARMFinale2",
			members = { "npc_ARMFinale Brute2" },
		},
		
		Armory_Finale3 = {
			name = "Group_ARMFinale3",
			members = { "npc_ARMFinale Stag 001", "npc_ARMFinale Stag 002" },
			vehicles = { "veh_ARMFinale Tank" },
		},
		
		Statue_Spawn1 = {
			name = "Group_Statue_Spawn1",
			members = { "Statue_Stag 001", "Statue_Stag 002" },
		},
		
		Statue_Spawn2 = {
			name = "Group_Statue_Spawn2",
			members = { "Statue_Stag 003", "Statue_Stag 004" },
		},
		
		Statue_Spawn3 = {
			name = "Group_Statue_Spawn3",
			members = { "Statue_Stag 005", "Statue_Stag 006" },
		},
		
		Statue_Spawn4 = {
			name = "Group_Statue_Spawn4",
			members = { "Statue_Stag 007", "Statue_Stag 008" },
		},
		
		Statue_Spawn5 = {
			name = "Group_Statue_Spawn5",
			members = { "Statue_Stag 009", "Statue_Stag 010" },
		},
		
	}
	
	Battle_Zone_Groups = { 
		-- MLG: Removing Battlezone area 1 since we wanted to reduce the number of battlezones
		--[[
		{
			initial_spawn = M22_groups.Zone_One_Initial, 
			courtesy_vehicles = M22_groups.Zone_One_Courtesy,
			boss_spawn_regions = { "sr_BZ1_region 001", "sr_BZ1_region 002", "sr_BZ1_region 003", 
									"sr_BZ1_region 004", "sr_BZ1_region 005", "sr_BZ1_region 006" },					
			center_pos = "Battle_Zone_Navpoint 001",
			player_starts = { "nav_player_start_bz01_ 001", "nav_player_start_bz01_ 002" },
			trigger = "BZ1_Spawn_Trigger",
			battle_area = "BZ1_Battle_Area",
			required_kills = 26,
			cleared = false,
			index = 1,
		},
		--]]
		{
			initial_spawn = M22_groups.Zone_Two_Initial, 
			initial_vehicles = M22_groups.Zone_Two_Vehicles,
			courtesy_vehicles = M22_groups.Zone_Two_Courtesy,
			saints_group = M22_groups.Zone_Two_Saints,
			boss_spawn_regions = { "sr_BZ2_region 001", "sr_BZ2_region 002", "sr_BZ2_region 003",
									"sr_BZ2_region 004", "sr_BZ2_region 005", "sr_BZ2_region 006" },
			center_pos = "Battle_Zone_Navpoint 002",
			player_starts = { "nav_player_start_bz02_ 001", "nav_player_start_bz02_ 002" },
			trigger = "BZ2_Spawn_Trigger",
			battle_area = "BZ2_Battle_Area",
			required_kills = 26,
			cleared = false,
			index = 1,
		},
		{
			initial_spawn = M22_groups.Zone_Three_Initial, 
			initial_vehicles = M22_groups.Zone_Three_Vehicles,
			courtesy_vehicles = M22_groups.Zone_Three_Courtesy,
			saints_group = M22_groups.Zone_Three_Saints,
			boss_spawn_regions = { "sr_BZ3_region 001", "sr_BZ3_region 002", "sr_BZ3_region 003",
									"sr_BZ3_region 004", "sr_BZ3_region 005", "sr_BZ3_region 006" },			
			center_pos = "Battle_Zone_Navpoint 003",
			player_starts = { "nav_player_start_bz03_ 001", "nav_player_start_bz03_ 002" },
			trigger = "BZ3_Spawn_Trigger",
			battle_area = "BZ3_Battle_Area",
			required_kills = 26,
			cleared = false,
			index = 2,
		},
		{
			initial_spawn = M22_groups.Zone_Four_Initial, 
			initial_vehicles = M22_groups.Zone_Four_Vehicles,
			courtesy_vehicles = M22_groups.Zone_Four_Courtesy,
			boss_spawn_regions = { "sr_BZ4_region 001", "sr_BZ4_region 002", "sr_BZ4_region 003",
									"sr_BZ4_region 004", "sr_BZ4_region 005", "sr_BZ4_region 006" },		
			saints_group = M22_groups.Zone_Four_Saints,
			center_pos = "Battle_Zone_Navpoint 004",
			player_starts = { "nav_player_start_bz04_ 001", "nav_player_start_bz04_ 002" },
			trigger = "BZ4_Spawn_Trigger",
			battle_area = "BZ4_Battle_Area",
			required_kills = 26,
			cleared = false,
			index = 3,
		},
	}
	
	Battle_Zone_Finales = {
		{ M22_groups.BattleZone_Finale1, M22_groups.BattleZone_Finale1v2 },
		{ M22_groups.BattleZone_Finale2 },
		{ M22_groups.BattleZone_Finale3v1, M22_groups.BattleZone_Finale3v2 },
		{ M22_groups.Armory_Finale1, M22_groups.Armory_Finale2, M22_groups.Armory_Finale3 },
	}
	
	Armory_battle_zone = {
		initial_spawn = M22_groups.Armory_Initial,
		initial_vehicles = M22_groups.Armory_Vehicles,
		courtesy_vehicles = M22_groups.Armory_Courtesy,
		boss_spawn_regions = { "sr_ARM_region 001", "sr_ARM_region 002", "sr_ARM_region 003", 
								"sr_ARM_region 004", "sr_ARM_region 005", "sr_ARM_region 006" },
		center_pos = "Armory_Navpoint",
		player_starts = { "nav_player_start_armory_ 001", "nav_player_start_armory_ 002" },
		trigger = "Armory_Spawn_Trigger",
		battle_area = "Armory_Battle_Area",
		required_kills = 20,
		cleared = false,
		index = 5,
	}

	cte_plane_group = {
		name = "m22_cte_plane_01"
		
	}
	
	cte_kia_group = {
		name = "Group_CTE_Kia"
		
	}	

-- Navpoints --
	M22_navpoints = {
		local_start = "Local_Player_Start",
		remote_start = "Remote_Player_Start",
		rail_begin = "Airport_Rail_Begin",
		roadblock_one_move_tos = { "Roadblock_1_Nav 001", "Roadblock_1_Nav 002", "Roadblock_1_Nav 003", "Roadblock_1_Nav 004",
								   "Roadblock_1_Nav 005", "Roadblock_1_Nav 006", "Roadblock_1_Nav 007", "Roadblock_1_Nav 008" },
		roadblock_two_move_tos = { "Roadblock_2_Nav 001", "Roadblock_2_Nav 002", "Roadblock_2_Nav 003", "Roadblock_2_Nav 004" },
		roadblock_three_move_tos = { "Roadblock_3_Nav 001", "Roadblock_3_Nav 002", "Roadblock_3_Nav 003", "Roadblock_3_Nav 004" },
		roadblock_four_move_tos = { "Roadblock_4_Nav 001", "Roadblock_4_Nav 002", "Roadblock_4_Nav 003", "Roadblock_4_Nav 004" },
		player_angel_start = { "nav_player_start_stop_kb 001", "nav_player_start_stop_kb 002" },
		player_kbfight_start = { "Local_kbfight_start", "Remote_kbfight_start" },
		player_kia_fight_start = { "Local_Kia_Fight_Start", "Remote_Kia_Fight_Start" },
		player_dock_start = { "nav_player_start_dock 001", "nav_player_start_dock 002" },
		statue_obs_deck = "Statue_Obs_Deck_Navpoint",
		statue_boat_loc = "nav_statue_boat_location",
		kia_attack_navs = { "Nav_kia_attack_pos 001", "Nav_kia_attack_pos 002", "Nav_kia_attack_pos 003", "Nav_kia_attack_pos 004" },
		kia_defence_east_navs= { "Nav_kia_defense_pos_east 001", "Nav_kia_defense_pos_east 002", "Nav_kia_defense_pos_east 003",
									"Nav_kia_defense_pos_east 004", "Nav_kia_defense_pos_east 005", "Nav_kia_defense_pos_east 006" },
		kia_defence_west_navs= { "Nav_kia_defense_pos_west 001", "Nav_kia_defense_pos_west 002", "Nav_kia_defense_pos_west 003",
									"Nav_kia_defense_pos_west 004", "Nav_kia_defense_pos_west 005", "Nav_kia_defense_pos_west 006" },
		kia_vtol_east_attack = { "nav_kia_vtol_idle_east 001", "nav_kia_vtol_attack_east 001" },
		kia_vtol_west_attack = { "nav_kia_vtol_idle_west 001", "nav_kia_vtol_attack_west 001" },
	}

-- Triggers --
	M22_triggers = {
		kill_killbane_perimeter = "Kill_Killbane_Perimeter_Trigger",
		kill_killbane = "Kill_Killbane_Trigger",
		save_saints_perimeter = "Save_Saints_Perimeter_Trigger",
		save_saints = "Save_Saints_Trigger",
		roadblock_one = "Roadblock_Trigger 001",
		roadblock_two = "Roadblock_Trigger 002",
		roadblock_three = "Roadblock_Trigger 003",
		roadblock_four = "Roadblock_Trigger 004",
		statue_elevator = "Statue_Elevator_Trigger",
		statue_explosion_region = "Explosion_Region",
		untie = { "Untie_Saint_Trigger 001", "Untie_Saint_Trigger 002", "Untie_Saint_Trigger 003", "Untie_Saint_Trigger 004" },
		First_Floor = "First_Floor_Trigger",
		Second_Floor = "Second_Floor_Trigger",
		Player_reached_top = "Player_reached_top_trigger",
		Kia_Breadcrumb = "Kia_Breadcrumb_Trigger",
		Kia_Boss_Area = "Trigger_Kia_Boss_Area 001",
		fart_jars = { "Fart_jar_trigger 001", "Fart_jar_trigger 002", "Fart_jar_trigger 003", "Fart_jar_trigger 004" },
	}

-- Characters --
	M22_characters =  {
		Killbane = M22_groups.Airport.killbane,
		Killbane_QTE = "", -- Initialized when we spawn Killbane, he may be masked or unmasked.
		Kia = M22_groups.Kia.kia,
		Oleg = M22_groups.Oleg_and_Pierce.oleg,
		Pierce =  M22_groups.Oleg_and_Pierce.pierce,
		Angel = M22_groups.Angel.npc,
		Viola = M22_groups.Viola.viola,
		Mayor = M22_groups.Hostages.mayor,
		Shaundi = M22_groups.Hostages.shaundi,
	}

-- Vehicles --
	M22_vehicles = {
		Start = M22_groups.Start_Vehicle.vehicle,
		Killbanes_Plane = "Killbane_Plane",
		Angels_Car = M22_groups.Angel.vehicle,
		Kia_Vtol1 = M22_groups.Kia_Vtol1.vtol,
	}

-- Mesh Movers --
	M22_movers = {
		c4 = {	"C4_Mover 001", "C4_Mover 002", "C4_Mover 003", "C4_Mover 004" },
		first_floor = { "C4_Mover 005", "C4_Mover 006", "C4_Mover 007", "C4_Mover 008" },
	}

-- Text --

-- Threads --
	M22_threads = {
		convo_handle = INVALID_THREAD_HANDLE,
		drive_convo_handle = INVALID_THREAD_HANDLE,
		battle_zone_gps = INVALID_THREAD_HANDLE,
		battle_zone_instance = INVALID_THREAD_HANDLE,
		battle_zone_followers = INVALID_THREAD_HANDLE,
		battle_zone_saints = INVALID_THREAD_HANDLE,
		battle_zone_notoriety_failsafe = INVALID_THREAD_HANDLE,
		killbane_path_handle = INVALID_THREAD_HANDLE,
		kill_killbane_dialog = INVALID_THREAD_HANDLE,
		player_path_handle = INVALID_THREAD_HANDLE,	
		vtol_one_handle = INVALID_THREAD_HANDLE,
		vtol_two_handle = INVALID_THREAD_HANDLE,
		kill_kia_dialog = INVALID_THREAD_HANDLE,
		burt_dialog = INVALID_THREAD_HANDLE,
		kia_boss_handle = INVALID_THREAD_HANDLE,
		kia_vomit_handle = INVALID_THREAD_HANDLE,
		respawn_handles = { INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE,
							INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE },
		player_car_speed_handle = INVALID_THREAD_HANDLE,
		roadblock_driveto_handles = { INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE,
												INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE },
		audio_failsafe = INVALID_THREAD_HANDLE,
	}

-- Checkpoints --
	M22_checkpoints = {
		CHECKPOINT_START = MISSION_START_CHECKPOINT,			-- defined in ug_lib.lua
		
		BATTLE_ZONE_1 = "m22_checkpoint_text_battle_zone_1",
		BATTLE_ZONE_2 = "m22_checkpoint_text_battle_zone_2",
		BATTLE_ZONE_3 = "m22_checkpoint_text_battle_zone_3",
		--BATTLE_ZONE_4 = "m22_checkpoint_text_battle_zone_4",
		
		-- These checkpoint save when the player completes their 3rd battle zone
		-- Depending on which zone we are, trigger a different checkpoint so that we can 
		-- warp them and their homies back to the correct zone if they die.
		GOTO_ARMORY1 = "m22_checkpoint_text_get_to_the_armory1", -- DT
		GOTO_ARMORY2 = "m22_checkpoint_text_get_to_the_armory2", -- NW
		GOTO_ARMORY3 = "m22_checkpoint_text_get_to_the_armory3", -- SW
		
		ARMORY_FIGHT = "m22_checkpoint_text_armory_fight",
		MAKE_YOUR_CHOICE = "m22_checkpoint_text_make_your_choice",
		HELP_ANGEL = "m22_checkpoint_text_help_angel",
		STOP_KILLBANE = "m22_checkpoint_text_stop_killbane_from_escaping",
		KILL_KILLBANE = "m22_checkpoint_text_kill_killbane",
		GOTO_SAINTS = "m22_checkpoint_text_go_to_statue",
		SAVE_SAINTS = "m22_checkpoint_text_save_saints",
		KILL_KIA = "m22_checkpoint_text_kill_kia",
		
		DEBUG_AIRPORT_CHOICE = "m22_debug_checkpoint_airport_choice",
		DEBUG_STATUE_CHOICE = "m22_debug_checkpoint_statue_choice",
		DEBUG_STATUE_CTE = "m22_debug_checkpoint_statue_cte",
	}
	
-- Cutscenes --
	M22_cutscenes = {
		mission_intro = "22_in",
		choice = "22_choice",
		mission_killbane_outro = "22_out1",
		mission_kia_outro = "22_out2",
		plane_destroyed = "22_Z01"
	}

	-- Replaced by "22_choice" cutscene.
	--[[
	M22_cte_choice_01 = {
		name = "m22_cte_01",
	}
	
	M22_cte_statue_01 = {
		name = "m22_cte_02",
	}
	--]]

	M22_cte_statue_02 = {
		name = "m22_cte_03",
	}
	
-- Conversations --
	M22_conversations = {
		mission_start = {
			name = "M22_Mission_Start",
			handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
		},
		--[[
		drive_convos = {
			{
				name = "M22_Drive_01",
				handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
			},
			{
				name = "M22_Drive_02",
				handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
			},
			{
				name = "M22_Drive_03",
				handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
			},
		},
		]]--
		boss_battle_intros = {
			{
				name = "M22_Gang_Fight_01",
				handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
			},
			--[[
			{
				name = "M22_Gang_Fight_02",
				handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
			},
			{
				name = "M22_Gang_Fight_03",
				handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
			},
			]]--
			{
				name = "M22_Second_Battle_Zone", 
				handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
			},	
		},
		--[[
		boss_battle_middle = {
			{
				name = "M22_First_Battle_Zone", 
				handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
			},
			{
				name = "M22_Second_Battle_Zone", 
				handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
			},				
			{
				name = "M22_Third_Battle_Zone", 
				handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
			},
		},
		]]--
		boss_battle_complete = {
			--[[
			{
				name = "M22_End_First_Battle_Zone",
				handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
			},
			]]--
			{
				name = "M22_End_Second_Battle_Zone",
				handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
			},
			{
				name = "M22_End_Third_Battle_Zone",
				handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
			},
		},
		armory = {
			name = "M22_Armory",
			handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
		},
		armory_fight = {
			name = "M22_Armory_Fight",
			handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
		},
		armory_middle = {
			name = "M22_Armory_Battle_Zone",
			handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
		},
		choice_phone_call = {
			name = "M22_Choice_Call",
			handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
		},
		convincing_call = {
			name = "M22_Convincing",
			handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
		},
		
		-- Save Shaundi 
		kinzie_phone_call = {
			name = "M22_Kinzie_Phone_Call",
			handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
		},
		kinzie_monument = {
			name = "M22_Kinzie_Monument",
			handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
		},
		
		-- CUT
		--[[
		viola_monument = {
			name = "M22_Viola_Monument",
			handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
		},
		--]]
		
		kia_fight = {
			name = "M22_Kia_Fight",
			handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
		},
		
		-- Kill Killbane
		angel_phone_call = {
			name = "M22_Angel_Under_Fire",
			handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
		},
		angel_car_chase = {
			name = "M22_Angel_Car_Chase",
			handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
		},
		angel_car_chase2 = {
			name = "M22_More_Angel_Car_Case",
			handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
		},
		angel_shoot_plane = {
			name = "M22_Angel_Shoot_Plane",
			handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
		},
		
		-- CUT
		--[[
		plane_shot_down = {
			name = "M22_Plane_Shot_Down",
			handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
		},
		--]]
		
		-- CUT
		--[[
		killbane_fight_01 = {
			name = "M22_Killbane_Fight_01",
			handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
		},
		--]]
		
		killbane_fight_04 = {
			name = "M22_Killbane_Fight_04",
			handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
		},
	}
	
	M22_dialog_lines = {
		pierce_saints_arrive = { "M22_First_Battle_Saints_Arrive", "M22_Second_Battle_Saints_Arrive" },
		pierce_leave_oleg = { "M22_Oleg_Fell_Behind_01", "M22_Oleg_Fell_Behind_02" },
		player_armory_clear = "M22_End_Armory_Battle_Zone",
		
		choice_call = { "M22_Choice_Call_01", "M22_Choice_Call_02" },
		--kia_vs_vtol = "m22_vtol_attacking_kia",
		oleg_convincing = "M22_Convincing_02",
		pierce_convincing = "M22_Convincing_01",
		kinzie_dock = "M22_Kinzie_Monument_01",
		killbane_fight_02 = "M22_Killbane_Fight_02",
		killbane_fight_03 = "M22_Killbane_Fight_03",
		
		burt_encouragement = { "M22_Burt_Encouragement_01", "M22_Burt_Encouragement_02", "M22_Burt_Encouragement_03", "M22_Burt_Encouragement_04", "M22_Burt_Encouragement_05" },
		burt_damaged = { "M22_Burt_Collateral_Damage_01", "M22_Burt_Collateral_Damage_02", "M22_Burt_Collateral_Damage_03", "M22_Burt_Collateral_Damage_04", "M22_Burt_Collateral_Damage_05" },
		burt_fiaj = { "M22_Burt_React_FIAJ_01", "M22_Burt_React_FIAJ_02", "M22_Burt_React_FIAJ_03", "M22_Burt_React_FIAJ_04", "M22_Burt_React_FIAJ_05" },
		
		shaundi_grab_fiaj = "M22_Pick_Up_Grenades",
		shaundi_grab_fiaj_nag = "M22_Nag_About_Grenades",
		player_grabbed_fiaj = "M22_Pick_Up_Grenades_02",
		
		angel_attacked = { "M22_Angel_Being_Attacked_01", "M22_Angel_Being_Attacked_02", "M22_Angel_Being_Attacked_03" },
		angel_chase = { "M22_More_Angel_Car_Chase_02_01", "M22_More_Angel_Car_Chase_03_01" },
		angel_encourage_shoot = { "M22_Angel_Encourage_Plane_Shot_01", "M22_Angel_Encourage_Shot_02", "M22_Angel_Encourage_Shot_03" },
		plane_down = "M22_Plane_Shot_Down",
	}
	
	M22_personas = {
		kinzie = {
			name = "Kinzie",
			persona_id = INVALID_PERSONA_HANDLE,
		},
		oleg = {
			name = "Oleg",
			persona_id = INVALID_PERSONA_HANDLE,
		},
		pierce = {
			name = "Pierce",
			persona_id = INVALID_PERSONA_HANDLE,
		},
		kia = {
			name = "Kia",
			persona_id = INVALID_PERSONA_HANDLE,
		},
		angel = {
			name = "Angel",
			persona_id = INVALID_PERSONA_HANDLE,
		},
	}
	
	M22_audio_events = {
		music_start = "M22_Hero_Music_Start",
		music_start_checkpoint = "M22_Hero_Music_Checkpoint",
		music_fade_out = "M22_Hero_Music_Fade",
		music_stop = "M22_Hero_Music_Stop",
		music_kia_start = "M22_Kia_Music_Start",
		music_kia_finish = "M22_Kia_Music_Finish",
		music_kia_stop = "M22_Kia_Music_Stop",
		battle_ambience_start = "M22_Battle_Ambience",
		battle_anbience_stop = "M22_Battle_Ambience_Stop",
		music_kb_zscene_fade = "M22_Hero_Fade_Zscene",
	}
		
	
	M22_roadblocks = {
		-- Example
		--{ layout = "police_lvl2_2lane", navpoint = "nav_roadblock", handle = -1 },
		{layout = "m22_skirmish_4lane", navpoint = "nav_dt_roadblock 001", handle = -1},
		{layout = "m22_skirmish_4lane", navpoint = "nav_dt_roadblock 002", handle = -1},
		{layout = "m22_wreckage_2lane", navpoint = "nav_dt_roadblock 003", handle = -1},
		{layout = "m22_skirmish_4lane", navpoint = "nav_dt_roadblock 004", handle = -1},
		{layout = "m22_skirmish_4lane", navpoint = "nav_dt_roadblock 005", handle = -1},
		{layout = "m22_wreckage_4lane", navpoint = "nav_dt_roadblock 006", handle = -1},
		{layout = "m22_skirmish_2lane", navpoint = "nav_dt_roadblock 007", handle = -1},
		{layout = "m22_skirmish_2lane", navpoint = "nav_dt_roadblock 008", handle = -1},
		{layout = "m22_wreckage_2lane", navpoint = "nav_ne_roadblock 001", handle = -1},
		{layout = "m22_skirmish_2lane", navpoint = "nav_ne_roadblock 002", handle = -1},
		{layout = "m22_skirmish_4lane", navpoint = "nav_ne_roadblock 003", handle = -1},
		{layout = "m22_wreckage_4lane", navpoint = "nav_ne_roadblock 004", handle = -1},
		{layout = "m22_skirmish_4lane", navpoint = "nav_ne_roadblock 005", handle = -1},
		{layout = "m22_skirmish_2lane", navpoint = "nav_ne_roadblock 006", handle = -1},
		{layout = "m22_wreckage_2lane", navpoint = "nav_nw_roadblock 001", handle = -1},
		{layout = "m22_skirmish_4lane", navpoint = "nav_nw_roadblock 002", handle = -1},
		{layout = "m22_skirmish_2lane", navpoint = "nav_nw_roadblock 003", handle = -1},
		{layout = "m22_wreckage_2lane", navpoint = "nav_nw_roadblock 004", handle = -1},
		{layout = "m22_skirmish_2lane", navpoint = "nav_nw_roadblock 005", handle = -1},
		{layout = "m22_skirmish_4lane", navpoint = "nav_nw_roadblock 006", handle = -1},
		{layout = "m22_wreckage_4lane", navpoint = "nav_sw_roadblock 001", handle = -1},
		{layout = "m22_skirmish_2lane", navpoint = "nav_sw_roadblock 002", handle = -1},
		{layout = "m22_wreckage_2lane", navpoint = "nav_sw_roadblock 003", handle = -1},
		{layout = "m22_skirmish_4lane", navpoint = "nav_sw_roadblock 004", handle = -1},
		{layout = "m22_wreckage_2lane", navpoint = "nav_sw_roadblock 005", handle = -1},
		{layout = "m22_skirmish_4lane", navpoint = "nav_sw_roadblock 006", handle = -1},
	}
	
	m22_statue_spawn_regions = {
		"sr_statue_spawn_region 001", "sr_statue_spawn_region 002", "sr_statue_spawn_region 003", "sr_statue_spawn_region 004",
		"sr_statue_spawn_region 005", "sr_statue_spawn_region 006", "sr_statue_spawn_region 007", "sr_statue_spawn_region 008",
	}
	
	M22_anims = {
		fiaj_reactions = {
			{ intro = "Stand_to_FIAJ_ReactA", outro = "FIAJ_ReactA_To_Stand" },
			{ intro = "Stand_to_FIAJ_ReactB", outro = "FIAJ_ReactB_To_Stand" },
			{ intro = "Stand_to_FIAJ_ReactC", outro = "FIAJ_ReactC_To_Stand" },
			{ intro = "Stand_to_FIAJ_ReactD", outro = "FIAJ_ReactD_To_Stand" },
		},
	}
	
-- Other --
	in_coop = false
	Completed_m23 = false
	Completed_m24 = false
	
	NO_ZONE = 0
	ZONE_ACTIVE = 1
	STAG = true
	SYND = false
	
	Active_conversation = {
		convo_table = nil
	}
	
	Current_bz = { 
		zone = NO_ZONE, 
		num_initial_stag_alive = 0, 
		num_initial_synd_alive = 0, 
		kills = 0, 
		num_bosses = 0,
		bosses_killed = 0,
		num_enemies_released = 0,
	}
	
	Nearest_bz_center = ""
	
	Number_of_zones_cleared = 0
	Latest_zone_cleared = 0
	
	Local_player_zone = NO_ZONE		-- These are either FIRST/SECOND
	Remote_player_zone = NO_ZONE	-- Tells us what zones the players are in.
	
	Mission_23_name = "m23"
	Mission_24_name = "m24"
	
	-- Armory
	Armory_reached = false
	
	-- Player Choice
	Player_choice = "none"
	Next_mission = Mission_23_name -- default to mission 23 for mission_win
	
	-- Airport
	M22_ROCKET_LAUNCHER = "Explosive-RocketLauncher"
	M22_SONICWAVE_GUN = "Special-SonicGun"
	M22_RC_GUN = "Special-RCVehicleGun"
	
	M22_PLAYER_KB_LOADOUT = { M22_ROCKET_LAUNCHER }
	M22_PLAYER_SONIC_LOADOUT = { M22_SONICWAVE_GUN }
	
	Airport_player_path = {
		"Player Airport Spline 001",
		"Player Airport Spline 001b",
		"Player Airport Spline 002",
		"Player Airport Spline 003",
		"Player Airport Spline 004",
		"Player Airport Spline 005",
		"Player Airport Spline 006",
	}
	Airport_Killbane_Path1 = "Killbane Airport Spline 001"
	Airport_Killbane_Path2 = "Killbane Airport Spline 002"
	Airport_Killbane_Path3 = "Killbane Airport Spline 003"
	Airport_Killbane_Path4 = "Killbane Airport Spline 004"
	Airport_Killbane_Path5 = "Killbane Airport Spline 005"
	
	Num_plane_hits = 0
	
	Killbane_qte_finished = false
	
	-- Statue
	
	M22_statue_populated = false
	
	Num_c4_left_to_destroy = 0
	Total_c4_to_destroy = 0
	Num_c4_left_first_floor = 0
	Player_used_elevator = false
	First_floor_cleared = false
	Second_floor_reached = false
	Player_reached_breadcrumb = false
	Player_reached_top = false
	Player_got_fiaj = false
	M22_burt_can_play_damage_line = true
	
	Vtol_path1 = "Vtol_path 001"
	Vtol_path2 = "Vtol_path 002"
	
	Battle_zone_boss_hud_bar_factor = 3
	
	-- Kia Boss Battle
	Kia_boss_ai = {
		current_navpoint = nil,
		attack_vtol_side = nil,
		attack_vtol_attacking = false,
	}
	
	M22_cur_cell_call_name = ""
		


-- *************************
--
-- Standard functions
--
-- *************************

-- This is the primary entry point for the mission, and is responsible for starting up the mission
-- at the specified checkpoint.
-- CALLED FROM CODE
--
-- m22_checkpoint:	The checkpoint the mission should begin at
-- is_restart:					TRUE if the mission is restarting, FALSE otherwise
--
function m22_start(m22_checkpoint, is_restart)
	in_coop = coop_is_active()

	--m22_checkpoint = M22_checkpoints.ARMORY_FIGHT
	-- Check if this mission starting from the beginning
	if (m22_checkpoint == M22_checkpoints.CHECKPOINT_START) then
		if (is_restart == false) then
			-- First time playing mission
			local cutscene_navs = { "Local_Player_Start", "Remote_Player_Start" }
			-- Play an intro cutscene???
			if (M22_cutscenes.mission_intro ~= "") then
				cutscene_play(M22_cutscenes.mission_intro, nil, cutscene_navs, false)
			end
		end
	end

	-- Handle mission initialization for the current checkpoint
	m22_initialize(m22_checkpoint)

	-- Run the mission from the current checkpoint
	m22_run(m22_checkpoint)
	
end

-- This is the primary function responsible for cleaning up the entire mission
-- CALLED FROM CODE (+++MUST RETURN IMMEDIATLY+++)
--
function m22_cleanup()
	hud_timer_stop(1)
	
	-- Cleanup the QTE system
	qte_cleanup()
	
	-- Disable zone swaps
	city_zone_swap("planecrash", DISABLE) -- Cleanup Killbane plane crash
	city_zone_swap("burn", DISABLE) -- Turn off the city burning
	
	-- If the player is replaying this mission, and the statue got blown
	-- up previously, redo that.
	if Completed_m23 == true and Completed_m24 == false then
		city_zone_swap("rubble", true)
	end
	
	m22_cleanup_battle_zones()
	m22_cleanup_goto_armory_sequence()
	m22_cleanup_kill_kia()
	
	m22_cleanup_triggers(M22_triggers)
	m22_cleanup_threads(M22_threads)
	m22_cleanup_movers(M22_movers)
	m22_cleanup_conversations()
	m22_cleanup_personas()
	cleanup_groups(M22_groups)
	mission_waypoint_remove()
	
	shop_ignore_clerk(false)
	
	--boss_battle_kia_active(false)
	
	on_qte_animation_trigger("")
	on_human_killed("")
	on_projectile_hit("")
	notoriety_force_no_spawn("police", DISABLE)
	notoriety_force_no_spawn("stag", false) -- AC: Test
	notoriety_force_no_spawn("luchadores", DISABLE)
	
	notoriety_force_no_spawn_group("stag_tank", false)
	notoriety_force_no_spawn_group("stag_attack_heli", false)
	notoriety_force_no_spawn_group("stag_heli", false)
	notoriety_force_no_spawn_group("stag_riot", false)
	
	-- Remove Fake Notoriety
	hud_set_fake_notoriety("police", false)
	hud_set_fake_notoriety("luchadores", false)
	
	set_stag_active(DISABLE)
	notoriety_set_can_decay(ENABLE)
	--notoriety_force_no_spawn("syndicate", false)
	
	disable_specific_notoriety_group("stag", 2, "G_STAG_CopCar", false)
	disable_specific_notoriety_group("stag", 3, "G_STAG_CopCar", false)
	disable_specific_notoriety_group("stag", 4, "G_STAG_CopCar", false)
	disable_specific_notoriety_group("stag", 5, "G_STAG_CopCar", false)
	disable_specific_notoriety_group("stag", 2, "G_STAG_BikeCop", false)
	disable_specific_notoriety_group("stag", 3, "G_STAG_BikeCop", false)
	
	for i, spawn in pairs(m22_statue_spawn_regions) do
		cleanup_spawn_regions(m22_statue_spawn_regions[i], false)
	end
	cleanup_spawn_groups(M22_groups.Statue_Spawn1.name)
	cleanup_spawn_groups(M22_groups.Statue_Spawn2.name)
	cleanup_spawn_groups(M22_groups.Statue_Spawn3.name)
	cleanup_spawn_groups(M22_groups.Statue_Spawn4.name)
	cleanup_spawn_groups(M22_groups.Statue_Spawn5.name)
	
	-- turn roadblocks and ambient roadblocks back on
	roadblocks_ambient_traffic_enable(true)
	roadblocks_enable(true)
	
	set_civilians_flee(DISABLE)
	
	flashpoints_enable(ENABLE) -- reenable flashpoints
	
	on_death("", M22_characters.Oleg)
	on_death("", M22_characters.Pierce)
	on_dismiss("", M22_characters.Pierce)
	
	-- Cleanup on_death callback for the tied up saints
	for i, saint in pairs(M22_groups.Statue.saints) do
		on_death("", saint)
	end
	
	set_player_can_enter_exit_vehicles(LOCAL_PLAYER, true)
	
	-- Make sure all the weapon slots are enabled again
	inv_weapon_disable_all_slots(DISABLE)
	
	if in_coop then
		set_player_can_enter_exit_vehicles(REMOTE_PLAYER, true)
	end
	
	-- Destroy the roadblocks around the city
	for i, roadblock in pairs(M22_roadblocks) do
		roadblock_destroy(roadblock.handle)
	end
	
	-- Reset density of peds and traffic
	set_ped_density(1)
	set_traffic_density(1)
	spawning_pedestrians(true)
	
	-- Reset parked car spawning.
	parking_spot_reset_max()
	
	audio_object_post_event("M22_QTE_Music_Stop", nil, nil, LOCAL_PLAYER)
	audio_object_post_event(M22_audio_events.music_kia_stop, nil, nil, LOCAL_PLAYER)
	
	inv_remove_temp_loadout(M22_PLAYER_KB_LOADOUT)
	
	player_movement_enable(LOCAL_PLAYER)
	if coop_is_active() then
		player_movement_enable(REMOTE_PLAYER)
	end
end

-- Called when the mission has ended with success
-- CALLED FROM CODE (+++MUST RETURN IMMEDIATLY+++)
--
function m22_success()
	--[[ INSERT ANY MISSION SPECIFIC SUCCESS STUFF ]]--
	if (Next_mission == Mission_23_name) then
		game_choice_set_state( MISSION_22_CHOICE, M22_CHOICE_KILLBANE_KILL )
	else
		game_choice_set_state( MISSION_22_CHOICE, M22_CHOICE_KILLBANE_ESCAPE )
	end

	local skip_teleport = true
	m22_coop_skip(skip_teleport) -- do the stuff we'd do in the skip case
end


-- *************************
--
-- Local functions
--
-- *************************

-- Initialize the mission for the specified checkpoint
--
-- checkpoint:		Checkpoint to initialize the mission to
--
function m22_initialize(checkpoint)
	-- Make sure the screen is completly faded out
	mission_start_fade_out(0.0)

	-- Set the mission author
	set_mission_author("John Karczewski")

	-- Common initialization
	m22_initialize_common()

	-- Checkpoint specific initialization
	m22_initialize_checkpoint(checkpoint)

	-- Reduce density of peds and traffic
	set_ped_density(0.25)
	set_traffic_density(0.1)
	
	-- Start fading in 
	mission_start_fade_in()
end


-- This is the primary function responsible for running the entire mission from start to finish.
--
-- first_checkpoint:	The first checkpoint to begin running the mission at
--
function m22_run(first_checkpoint)
	local current_checkpoint = first_checkpoint

	-- Run the mission from the beginning or from a battle zone checkpoint
	if (current_checkpoint == M22_checkpoints.CHECKPOINT_START or m22_checkpoint_is_battle_zone(current_checkpoint) == true) then
		m22_process_battle_zone_sequence()
		
		current_checkpoint = m22_set_post_battle_zone_checkpoint()
	end
	
	if  (m22_checkpoint_is_get_to_armory(current_checkpoint) == true) then
		m22_goto_armory_sequence()
		
		current_checkpoint = M22_checkpoints.ARMORY_FIGHT
		mission_set_checkpoint(M22_checkpoints.ARMORY_FIGHT, true)
	end
	
	if current_checkpoint == M22_checkpoints.ARMORY_FIGHT then
		m22_process_armory_fight()
		
		-- Play dialog lines prior to the cutscene
		--[[
		M22_threads.convo_handle = thread_new("m22_play_cell_convo", M22_conversations.mission_start.name, true)
		local line_handle = audio_play_persona_line_2d(M22_personas.angel.persona_id, M22_dialog_lines.choice_call[1])
		-- Wait for the line to finish
		while (audio_is_playing(line_handle) == true)do
			thread_yield()
		end
		audio_stop(line_handle)
		]]--
		m22_play_cell_convo(M22_dialog_lines.choice_call[1], true, M22_personas.angel.persona_id)
	
		local line_handle = audio_play_persona_line(LOCAL_PLAYER, M22_dialog_lines.choice_call[2])
		--delay(1.0)
		-- Wait for the line to finish
		m22_wait_for_foley_safe(line_handle, 60.0)
		audio_stop(line_handle)
		
		-- Play the cutscene
		cutscene_play(M22_cutscenes.choice, nil, { Armory_battle_zone.center_pos, Armory_battle_zone.center_pos })
		
		current_checkpoint = M22_checkpoints.MAKE_YOUR_CHOICE
		mission_set_checkpoint(M22_checkpoints.MAKE_YOUR_CHOICE)
	end
	
	-- Replaced by "22_choice" cutscene.
	--[[
	if current_checkpoint == M22_checkpoints.DEBUG_AIRPORT_CHOICE then
		m22_choice_airport_cutscene()
		
		current_checkpoint = M22_checkpoints.DEBUG_STATUE_CHOICE
	end
	
	if current_checkpoint == M22_checkpoints.DEBUG_STATUE_CHOICE then
		m22_choice_statue_cutscene()
	
		current_checkpoint = M22_checkpoints.MAKE_YOUR_CHOICE
		mission_set_checkpoint(M22_checkpoints.MAKE_YOUR_CHOICE)
	end
	--]]
	
	if current_checkpoint == M22_checkpoints.MAKE_YOUR_CHOICE then
		m22_process_player_choice_sequence()
		
		if (Player_choice == "killbane") then
			current_checkpoint = M22_checkpoints.STOP_KILLBANE
			mission_set_checkpoint(M22_checkpoints.STOP_KILLBANE)
		else
			current_checkpoint = M22_checkpoints.DEBUG_STATUE_CTE
		end
	end	
	
	if current_checkpoint == M22_checkpoints.STOP_KILLBANE then
		m22_protect_angel_sequence()
		m22_in_transit_to_airport()
		m22_setup_killbane_chase_sequence()
		m22_process_killbane_chase_sequence()
		
		audio_object_post_event(M22_audio_events.music_kb_zscene_fade, nil, nil, LOCAL_PLAYER)
		
		-- Setup the killbane fight and cinematic (need a screen fade here since we need to apply the zone-swap)
		mission_start_fade_out(0.0)
		m22_setup_kill_killbane()
		mission_start_fade_in()
		
		current_checkpoint = M22_checkpoints.KILL_KILLBANE
		mission_set_checkpoint(M22_checkpoints.KILL_KILLBANE, true) -- don't save out their vehicle
	end
	
	if current_checkpoint == M22_checkpoints.KILL_KILLBANE then		
		m22_killbane_plane_destroyed_scene()
		m22_process_kill_killbane()
		Player_choice = "killbane"
	end
	
	if current_checkpoint == M22_checkpoints.DEBUG_STATUE_CTE then
		m22_arrived_at_dock_sequence()
		m22_c4_objective_cte()
		
		current_checkpoint = M22_checkpoints.GOTO_SAINTS
		mission_set_checkpoint(M22_checkpoints.GOTO_SAINTS, false)
	end
	
	if current_checkpoint == M22_checkpoints.GOTO_SAINTS then
		m22_go_to_statue_sequence()
		m22_setup_save_the_saints()	
		
		fade_out(0.5)
		fade_out_block()
		teleport_coop(M22_navpoints.statue_obs_deck, M22_navpoints.statue_obs_deck, true)
		
		-- Equip the sonic gun.
		m22_equip_temp_weapons_for_save_saints()
		
		fade_in(0.5)
		fade_in_block()
		
		m22_cleanup_statue_courtesy_boats()
	
		current_checkpoint = M22_checkpoints.SAVE_SAINTS
		mission_set_checkpoint(M22_checkpoints.SAVE_SAINTS, false)
	end

	if current_checkpoint == M22_checkpoints.SAVE_SAINTS then
		m22_process_save_the_saints()
		m22_cleanup_save_the_saints()
		
		current_checkpoint = M22_checkpoints.KILL_KIA
		mission_set_checkpoint(M22_checkpoints.KILL_KIA, true) -- don't save out their vehicle
	end
	
	if current_checkpoint == M22_checkpoints.KILL_KIA then
		m22_process_kill_kia()
		m22_cleanup_kill_kia()
		Player_choice = "shaundi"
	end
	
	-- Call mission success??
	if Player_choice == "killbane" then
		mission_end_success("m22", M22_cutscenes.mission_killbane_outro, M22_navpoints.player_kbfight_start)
	else
		fade_out(0.5)
		fade_out_block()
		mission_set_completed( "m22" )
		mission_unlock( "m24" )
		mission_autosave()
		mission_end_to_activity( "m22", "m24" )
	end
end

-- Primary function to process all of the battlezones the player must clear before moving on in the mission
function m22_process_battle_zone_sequence()
	-- Enable all the battlezone triggers
	for i, battle_zone in pairs(Battle_Zone_Groups) do
		on_trigger("m22_zone_triggered_cb", battle_zone.trigger)
		on_trigger_exit("m22_zone_exited_cb", battle_zone.trigger)
		trigger_enable(battle_zone.trigger, true)
	end

	if (Number_of_zones_cleared == 0) then
		-- Play some dialog
		M22_threads.convo_handle = thread_new("m22_play_cell_convo", M22_conversations.mission_start.name, true)
	end
	
	local oleg_tutorial_displayed = false
	
	-- Loop until all the zones have been completed
	while (Number_of_zones_cleared < NUM_ZONES_TO_COMPLETE_TO_SUCCEED) do
		-- Update the object text to get to the battle zone
		objective_text_clear(0)
		objective_text_clear(1)
		objective_text( 0, "m22_obj_goto_battlezone", "", "", SYNC_LOCAL, OI_ASSET_LOCATION)
		objective_text( 1, "m22_obj_goto_battlezone", "", "", SYNC_REMOTE, OI_ASSET_LOCATION)
		
		-- Initialize the current battle zone data
		Current_bz.zone = NO_ZONE
		
		-- Setup all the battle zones triggers (for any remaining battle zones)
		m22_show_remaining_battle_zones()
		
		-- Begin plotting GPS paths to the nearest battle zone.
		M22_threads.battle_zone_gps = thread_new("m22_thread_neareast_battlezone_gps")
		
		-- Set the notoriery respawn timers
		notoriety_force_no_spawn("stag",false)
		notoriety_force_no_spawn("luchadores", false)
		notoriety_spawn_group_set_delay("luchadores", 80000)
		notoriety_spawn_group_set_delay("stag", 80000)
		
		-- Set the ped/traffic density for traveling between zones
		set_ped_density(0.25)
		set_traffic_density(0.1)
		spawning_pedestrians(true)
		
		-- Make Oleg invulnerable
		turn_invulnerable(M22_characters.Oleg, true)
		
		-- Start a thread to process when to play the driving conversation
	--	M22_threads.drive_convo_handle = thread_new("m22_thread_process_drive_convo")
		
		-- Start the ambient battle audio until the player reaches a battle area
		audio_object_post_event(M22_audio_events.battle_ambience_start, nil, nil, LOCAL_PLAYER)
		
		-- Display a tutorial telling the player that they can leave Oleg behind after completing 
		-- the first battle zone.
		if Number_of_zones_cleared == 1 and oleg_tutorial_displayed == false then
			oleg_tutorial_displayed = true
			tutorial_start("mis_22_oleg_follow", 5000, true, true) 
		end

		-- Wait until the player has reached one fo the battle zone areas
		Current_bz.zone = NO_ZONE
		while (Current_bz.zone == NO_ZONE) do
			thread_yield()
		end
		
		-- Stop auto-updating the GPS.
		mission_waypoint_remove()
		thread_kill(M22_threads.battle_zone_gps)
		M22_threads.battle_zone_gps = INVALID_THREAD_HANDLE
		
		-- Turn notoriety off and disable peds and traffic while in the battle zone
		m22_set_stag_synd_notoriety(0)
		set_ped_density(0.01)
		set_traffic_density(0.01)
		spawning_pedestrians(false)
		
		-- Stop the ambient battle audio while the player is in an active battle area
		audio_object_post_event(M22_audio_events.battle_anbience_stop, nil, nil, LOCAL_PLAYER)
		
		-- Make Oleg vulnerable again
		turn_vulnerable(M22_characters.Oleg)
		
		-- Kill the driving convo thread
		thread_kill(M22_threads.drive_convo_handle)

		-- Kick off a thread to process the battle zone instance (do this in a thread so it can be interrupted if the player leaves)
		M22_threads.battle_zone_instance = thread_new("m22_process_active_battle_zone_thread")
		
		-- Wait until the battle zone thread has finished (either completed, or the player left)
		while(thread_check_done(M22_threads.battle_zone_instance) == false) do
			thread_yield()
		end
		
		-- Clear the players' zone flags.
		Local_player_zone = NO_ZONE
		Remote_player_zone = NO_ZONE
		
		-- Turn notoriety and traffic back on
		m22_set_stag_synd_notoriety(3)
		set_ped_density(0.25)
		set_traffic_density(0.1)
		spawning_pedestrians(true)
		
		-- Clean-up the active battle zone
		m22_cleanup_active_battle_zone()
	end
	
	m22_cleanup_battle_zones()
end

-- Primary thread to process a battle zone area from start to finish
function m22_process_active_battle_zone_thread()
	-- Do the initial battlezone spawn
	m22_spawn_battle_zone(Current_bz.zone)
	
	-- Create a thread to process the follower leash behaviors
	M22_threads.battle_zone_followers = thread_new("m22_thread_process_battle_zone_followers")
	
	-- Play some dialog
	M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.boss_battle_intros[Number_of_zones_cleared + 1], 0.0)	

	-- Process the battle zone sections
	m22_process_battle_zone_kill_enemies()
	
	-- Play some dialog
--	M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.boss_battle_middle[Number_of_zones_cleared + 1], 0.0)	
	
	-- Process the finale
	m22_process_battle_zone_finale()

	-- Play some dialog
	M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.boss_battle_complete[Number_of_zones_cleared + 1], 0.0)		
	
	-- Kick of a new thread to process the Saints reinforcements
	M22_threads.battle_zone_saints = thread_new("m22_thread_process_battle_zone_saint_reinforcements")
	
	m22_cleanup_active_battle_zone()
	
	-- Battle zone is complete, update our bookkeeping
	Current_bz.zone.cleared = true
	Number_of_zones_cleared = Number_of_zones_cleared + 1
	Latest_zone_cleared = Current_bz.zone.index
	Current_bz.zone = NO_ZONE
	
	-- Set the new checkpoint
	m22_set_battle_zone_complete_checkpoint()
end

-- Function to process the initial enemies the player must kill at a battle zone
function m22_process_battle_zone_kill_enemies()
	-- Reduce density of peds and traffic
	set_ped_density(0.01)
	set_traffic_density(0.01)
	
	on_human_killed("m22_battle_zone_initial_died_cb")
	
	notoriety_force_no_spawn("stag", true)
	notoriety_force_no_spawn("luchadores", true)

	-- Set notoriety timer for when spawning starts up again
	notoriety_set_override_timer("stag", true, 3000, 5000)
	notoriety_set_override_timer("gang LD", true, 3000, 5000)
	
	-- Start a failsafe thread that will re-enable notoriety spawns anyway if
	-- something goes horribly wrong.
	M22_threads.battle_zone_notoriety_failsafe = thread_new("m22_thread_notoriety_failsafe")

	-- Wait until the player has almsot killed enough enemies
	while (Current_bz.kills < (Current_bz.zone.required_kills - 5) ) do
		thread_yield()
	end
	
	-- Wait until the player has killed enough enemies
	while (Current_bz.kills < Current_bz.zone.required_kills) do
		thread_yield()
	end
	
	m22_cleanup_battle_zone_kill_enemies()
end

-- Function to clean-up the initial enemies the player must kill at a battle zone
function m22_cleanup_battle_zone_kill_enemies()	
	-- Remove callbacks on enemy NPCs (we don't need to count kills anymore)
	m22_remove_on_death_callbacks(Current_bz.zone)
	
	-- Stop the notoriety failsafe thread if it's still running.
	if M22_threads.battle_zone_notoriety_failsafe ~= INVALID_THREAD_HANDLE then
		thread_kill(M22_threads.battle_zone_notoriety_failsafe)
		M22_threads.battle_zone_notoriety_failsafe = INVALID_THREAD_HANDLE
	end
	
	on_human_killed("")
end

-- Function to process the battle zone finale (boss enemey spawns)
function m22_process_battle_zone_finale()
	-- Set up spawn regions for finale boss(es)
	for i, spawn_region in pairs(Current_bz.zone.boss_spawn_regions)do
		spawn_region_enable(spawn_region, true)
	end
	
	-- Spawn a finale boss set
	for i, spawn_group in pairs(Battle_Zone_Finales[Number_of_zones_cleared + 1]) do
		-- Tell the group to attack the nearest player and spawn them.
		continuous_spawn_set_orders(spawn_group.name, "attack", "", -1)
		continuous_spawn_start(spawn_group.name, 1, 0, "m22_bz_boss_killed_cb", SRF_DEFAULT, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, MINIMAP_ICON_KILL)
	end
	
	-- Turn off override spawn times
	notoriety_set_override_timer("stag", false, 10000, 15000)
	notoriety_set_override_timer("gang LD", false, 10000, 15000)
		
	notoriety_spawn_group_set_delay("luchadores", 60000)
	notoriety_spawn_group_set_delay("stag", 60000)
	
	notoriety_force_no_spawn("stag", false)
	notoriety_force_no_spawn("luchadores", false)
	
	notoriety_spawn_group_clear_destination("stag")
	notoriety_spawn_group_clear_destination("luchadores")
	
	-- Wait until all the bosses have been destroyed
	while(Current_bz.bosses_killed < Current_bz.num_bosses) do
		thread_yield()
	end
	
	m22_cleanup_battle_zone_finale()
end

-- Function to cleanup the battle zone finale
function m22_cleanup_battle_zone_finale()
	-- Cleanup any battle zone finale continuous spawns
	for i, finale_group in pairs(Battle_Zone_Finales[Number_of_zones_cleared + 1]) do
		cleanup_spawn_groups(finale_group.name)
	end

	-- Cleanup any battle zone spawn regions
	for i, spawn in pairs(Current_bz.zone.boss_spawn_regions) do
		continuous_spawn_regions_enable(spawn, false)
	end
end

-- Thread to process spawning a group of Saints reinforcements at a battle area
function m22_thread_process_battle_zone_saint_reinforcements()
	local saints_group = Current_bz.zone.saints_group
	local dest = Current_bz.zone.center_pos
	local zones_cleared = Number_of_zones_cleared

	-- Setup the vehicles
	group_create_hidden(saints_group.name, true)
	for i, car_group in pairs(saints_group.cars) do
		vehicle_enter_group_teleport(car_group.members, car_group.vehicle)
	end
	
	-- Find a good navpoint set to use
	local best_dist = 0
	local best_start_pos = nil
	for i, start_pos in pairs(saints_group.start_positions) do
		local dist = get_dist_closest_player_to_object(start_pos.nav)
		if (dist > best_dist) then
			best_dist = dist
			best_start_pos = start_pos
		end
	end
	
	-- If we didn't find a nav greater than 50m away, then don't show the Saints
	if (best_start_pos == nil or best_dist < 50.0) then
		return
	end
	
	-- Teleport the cars into place, and send them towards the Battlezone
	for i, car_group in pairs(saints_group.cars) do
		-- Teleport the vehicle into place
		teleport_vehicle(car_group.vehicle, best_start_pos.nav)
		
		-- Show the car and Saints guys
		vehicle_show(car_group.vehicle)
		for j, member in pairs(car_group.members) do
			character_show(member)
		end
		
		-- Follow the path associated with the start position.
		vehicle_pathfind_navmesh_do(car_group.vehicle, best_start_pos.path, false, true, false, 1)
		
		delay(3.0)
	end
	
	-- Wait until at least one vehicle has arrived
	local arrived = false
	while(arrived == false) do
		for i, car_group in pairs(saints_group.cars) do
			if (vehicle_pathfind_check_done(car_group.vehicle) == 1) then
				arrived = true
			end
		end
		
		thread_yield()
	end
	
	-- Play some dialog
	audio_play_persona_line(M22_characters.Pierce, M22_dialog_lines.pierce_saints_arrive[zones_cleared + 1])
	
	for i, car_group in pairs(saints_group.cars)do
		vehicle_exit_group(car_group.members)
	end
end

-- Thread to process leashing of followers at battle zones
function m22_thread_process_battle_zone_followers()
	while(true) do
		local dist = get_dist(LOCAL_PLAYER, M22_characters.Pierce)
		if (dist > 25.0 or character_is_in_vehicle(LOCAL_PLAYER) == true) then
			follower_make_independent(M22_characters.Pierce, false)
		else
			follower_make_independent(M22_characters.Pierce, true)
		end
		
		dist = get_dist(LOCAL_PLAYER, M22_characters.Oleg)
		if (dist > 25.0 or character_is_in_vehicle(LOCAL_PLAYER) == true) then
			follower_make_independent(M22_characters.Oleg, false)
		else
			follower_make_independent(M22_characters.Oleg, true)
		end
		
		thread_yield()
	end
end

-- Cleanup saints reinforcements
function m22_cleanup_battle_zone_saint_reinforcements()
	-- Kill the thread processing the Saints reinforcements
	thread_kill(M22_threads.battle_zone_saints)

	-- Clean-up the script group
	if (group_is_loaded(Current_bz.zone.saints_group.name) == true) then
		release_to_world(Current_bz.zone.saints_group.name)
		group_destroy(Current_bz.zone.saints_group.name)
	end
end

-- External clean-up function to clean-up the active battle zone (on completion, player exit, or mission cancel)
function m22_cleanup_active_battle_zone()
	-- Clean-up an active battle
	if (Current_bz.zone ~= NO_ZONE) then
		m22_cleanup_battle_zone_kill_enemies()
		m22_cleanup_battle_zone_finale()

		-- Remove the battle area callback and radius from the minimap
		m22_cleanup_trigger(Current_bz.zone.battle_area)
		minimap_icon_remove_radius(Current_bz.zone.center_pos)
		marker_remove(Current_bz.zone.center_pos)
		
		-- Kill the thread processing the battle zone followers
		thread_kill(M22_threads.battle_zone_followers)
		follower_make_independent(M22_characters.Pierce, false)
		follower_make_independent(M22_characters.Oleg, false)
	end
	
	-- Turn off the progress bar
	hud_bar_off(0)
	hud_bar_off(1)
end

-- Removes enter trigger and disables battle zones
function m22_cleanup_battle_zones()
	m22_cleanup_active_battle_zone()
	
	-- Clean up the zone triggers
	for i, battle_zone in pairs(Battle_Zone_Groups) do
		m22_cleanup_trigger(battle_zone.trigger)
		m22_cleanup_trigger(battle_zone.battle_area)
		
		m22_remove_on_death_callbacks(battle_zone)
	end
	
	-- Stop auto-updating the GPS.
	mission_waypoint_remove()
	thread_kill(M22_threads.battle_zone_gps)
	M22_threads.battle_zone_gps = INVALID_THREAD_HANDLE
end

-- Set the appropriate battle zone complete checkpoint name
function m22_set_battle_zone_complete_checkpoint()
	local checkpoint_name = "m22_checkpoint_text_battle_zone_" .. Latest_zone_cleared
	
	--[[
	for i, zone in pairs(Battle_Zone_Groups) do
		if (zone.cleared == true and i~= Latest_zone_cleared) then
			checkpoint_name = checkpoint_name .. "_" .. i
			break
		end
	end
	--]]
	
	mission_set_checkpoint(checkpoint_name)
end

-- The player must goto the armory
function m22_goto_armory_sequence()
	objective_text_clear(0)
	objective_text_clear(1)
	objective_text( 0, "m22_obj_goto_armory", "", "", SYNC_LOCAL, OI_ASSET_LOCATION)
	objective_text( 1, "m22_obj_goto_armory", "", "", SYNC_REMOTE, OI_ASSET_LOCATION)
	
	-- Enable the armory trigger
	on_trigger("m22_armory_reached_cb", Armory_battle_zone.trigger)
	trigger_enable(Armory_battle_zone.trigger)
	marker_add_trigger(Armory_battle_zone.trigger, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
	mission_waypoint_add(Armory_battle_zone.trigger)

	-- Battle Zones are over, delay the spawning of some things
	notoriety_spawn_group_set_delay("stag_tank", 80000)
	notoriety_force_no_spawn_group("stag_tank", false)

	notoriety_spawn_group_set_delay("stag_attack_heli", 80000)
	notoriety_force_no_spawn_group("stag_attack_heli", false)

	notoriety_spawn_group_set_delay("stag_heli", 80000)
	notoriety_force_no_spawn_group("stag_heli", false)

	notoriety_spawn_group_set_delay("stag_riot", 80000)
	notoriety_force_no_spawn_group("stag_riot", false)	
	
	M22_threads.convo_handle = thread_new("m22_play_cell_convo", M22_conversations.armory.name, true)
	
	-- Make Oleg invulnerable
	turn_invulnerable(M22_characters.Oleg, true)	
	
	-- Start the ambient battle audio until the player reaches a battle area
	audio_object_post_event(M22_audio_events.battle_ambience_start, nil, nil, LOCAL_PLAYER)

	while not Armory_reached do
		thread_yield()
	end
	
	-- Stop the ambient battle audio while the player is in an active battle area
	audio_object_post_event(M22_audio_events.battle_anbience_stop, nil, nil, LOCAL_PLAYER)
	
	-- Make Oleg vulnerable again
	turn_vulnerable(M22_characters.Oleg)	
	
	m22_cleanup_goto_armory_sequence()
end

-- Cleanup the goto armory sequence
function m22_cleanup_goto_armory_sequence()
	on_trigger("", Armory_battle_zone.trigger)
end

-- Spawns the initial forces of the armory fight
function m22_process_armory_fight()
	-- Set the battle zone to the armory
	Current_bz.zone = Armory_battle_zone

	-- Add the battle area radius, and a marker to the center of the battle area
	minimap_icon_add_radius(Current_bz.zone.center_pos, trigger_get_radius(Current_bz.zone.battle_area), SYNC_ALL)
	marker_add(Current_bz.zone.center_pos, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL)

	-- Enable the trigger for the battle area (so we can update the marker on the battle area)
	on_trigger("m22_battle_area_triggered_cb", Current_bz.zone.battle_area)
	on_trigger_exit("m22_battle_area_exited_cb", Current_bz.zone.battle_area)
	trigger_enable(Current_bz.zone.battle_area, true)
	
	-- Turn notoriety off and disable peds and traffic while in the armory battle area
	m22_set_stag_synd_notoriety(0)
	set_ped_density(0.1)
	set_traffic_density(0.1)		
	spawning_pedestrians(false)

	-- Do the initial battlezone spawn
	m22_spawn_battle_zone(Current_bz.zone)

	-- Update the GSI
	objective_text_clear(0)
	local hud_bar_size = Armory_battle_zone.required_kills + Battle_zone_boss_hud_bar_factor * #Battle_Zone_Finales[Number_of_zones_cleared + 1]
	hud_bar_on(0, "Health", "m22_obj_clear_armory", hud_bar_size, SYNC_LOCAL, OI_ASSET_KILL)	
	hud_bar_set_value(0, hud_bar_size, SYNC_LOCAL)
	if (coop_is_active() == true) then
		objective_text_clear(1)
		hud_bar_on(1, "Health", "m22_obj_clear_armory", hud_bar_size, SYNC_REMOTE, OI_ASSET_KILL)	
		hud_bar_set_value(1, hud_bar_size, SYNC_REMOTE)
	end
	
	-- Wait until one of the player's has reached the Armory area
	while(object_is_in_trigger(Current_bz.zone.battle_area, LOCAL_PLAYER) == false and
			(coop_is_active() == false or object_is_in_trigger(Current_bz.zone.battle_area, REMOTE_PLAYER) == false)) do
		thread_yield()
	end
	
	-- Play some dialog
	M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.armory_fight, 0.0)
	
	-- Process the armory battle zone
	m22_process_battle_zone_kill_enemies()
	
	-- Play some dialog
	M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.armory_middle, 0.0)
	
	m22_process_battle_zone_finale()
	
	-- Play some dialog
	local line_handle = audio_play_persona_line(LOCAL_PLAYER, M22_dialog_lines.player_armory_clear)
	m22_wait_for_foley_safe(line_handle, 60.0)
	audio_stop(line_handle)
	
	-- Oleg and Pierce are no longer part of the player's party
	party_dismiss(M22_characters.Oleg)
	party_dismiss(M22_characters.Pierce)
	turn_invulnerable(M22_characters.Oleg, true)	-- shouldn't die unless the player kills them
	turn_invulnerable(M22_characters.Pierce, true)	-- shouldn't die unless the player kills them
	on_dismiss("", M22_characters.Pierce)	-- Don't fail the mission on dismissal
	on_death("", M22_characters.Oleg)
	on_death("", M22_characters.Pierce)
	
	-- Revive them if they are downed
	npc_revive(M22_characters.Oleg)
	npc_revive(M22_characters.Pierce)
	
	m22_cleanup_active_battle_zone()
	
	-- Destroy the guys we spawned
	if group_is_loaded(Armory_battle_zone.initial_spawn.name) then
		group_destroy(Armory_battle_zone.initial_spawn.name)
	end
		
	-- Turn peds and traffic back on
	set_ped_density(0.25)
	set_traffic_density(0.1)
	spawning_pedestrians(true)
	
	delay(0.5)
end

-- Depending on what the last battle zone cleared was, sets the appropriate checkpoint
--
-- returns:			entry from M22_checkpoints
function m22_set_post_battle_zone_checkpoint() 		
	if Latest_zone_cleared == 1 then
		mission_set_checkpoint(M22_checkpoints.GOTO_ARMORY1, true)
		return M22_checkpoints.GOTO_ARMORY1
	elseif Latest_zone_cleared == 2 then
		mission_set_checkpoint(M22_checkpoints.GOTO_ARMORY2, true)
		return M22_checkpoints.GOTO_ARMORY2
	elseif Latest_zone_cleared == 3 then
		mission_set_checkpoint(M22_checkpoints.GOTO_ARMORY3, true)
		return M22_checkpoints.GOTO_ARMORY3
	end	
end

function m22_setup_statue_courtesy_boats()
	-- Create the courtesy helicoper
	group_create(M22_groups.Statue_Boats, true)
	
	-- Set it up so that the player can't change the radio station
	radio_block(M22_groups.Statue_Boats.members[1])
	radio_block(M22_groups.Statue_Boats.members[2])
end

-- Callback when the player enters the perimeter of the statue
function m22_save_saints_perimeter()
	m22_cleanup_trigger(M22_triggers.save_saints_perimeter)
	
	M22_threads.convo_handle = thread_new("m22_play_cell_convo", M22_conversations.kinzie_phone_call.name, true)
	
	group_create(M22_groups.Kinzie, true)
end

-- Callback when the player enters the perimeter of the killbane boss area
function m22_kill_killbane_perimeter()
	m22_cleanup_trigger(M22_triggers.kill_killbane_perimeter)
	
--	M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.angel_phone_call, 0.0)
	M22_threads.convo_handle = thread_new("m22_play_cell_convo", M22_conversations.angel_phone_call.name, true)
end

-- Waits until the the player has hit a trigger and then determines what to do
function m22_process_player_choice_sequence()
	-- Clear the objective text
	objective_text_clear(0)
	objective_text_clear(1)
	
	-- Let's add some complications
	-- If the player has completed the game as Host, mission 22 will become unlocked again
	-- We want to give the player the opportunity to play the finale the other way, so we will force their choice
	-- to be the one they did not select the last time
	local block_m23 = false
	local block_m24 = false
	
	if Completed_m23 and not Completed_m24 then
		block_m23 = true
	end
	if not Completed_m23 and Completed_m24 then
		block_m24 = true
	end	
	-- if both are competed, I don't know how you got here, so good luck!
	
	-- maybe change objective if it is chosen for you
	objective_text( 0, "m22_obj_killbane_or_shaundi", "", "", SYNC_ALL , OI_ASSET_LOCATION)
	
	-- Setup the perimiter triggers for the two choice areas
	if not block_m24 then
		on_trigger("m22_save_saints_perimeter", M22_triggers.save_saints_perimeter)
		trigger_enable(M22_triggers.save_saints_perimeter, true)
	end
	
	if not block_m23 then			
		on_trigger("m22_kill_killbane_perimeter", M22_triggers.kill_killbane_perimeter)
		trigger_enable(M22_triggers.kill_killbane_perimeter, true)	
	end
		
	-- Setup the player choice triggers
	if not block_m24 then
		on_trigger("m22_player_choice_cb", M22_triggers.save_saints)
		trigger_enable(M22_triggers.save_saints)
		marker_add_trigger(M22_triggers.save_saints, MINIMAP_ICON_PROTECT_ACQUIRE, INGAME_EFFECT_CHECKPOINT, OI_ASSET_DEFEND, OI_FLAGS_LOCATION, SYNC_ALL)
	end
	if not block_m23 then
		on_trigger("m22_player_choice_cb", M22_triggers.kill_killbane)
		trigger_enable(M22_triggers.kill_killbane)
		marker_add_trigger(M22_triggers.kill_killbane, MINIMAP_ICON_KILL, INGAME_EFFECT_CHECKPOINT, OI_ASSET_KILL_FULL, OI_FLAGS_LOCATION, SYNC_ALL)
	end
	
	if not block_m24 then
		object_indicator_add_objective_text(M22_triggers.save_saints, "PLAYER_CHOICE_M22_OPTION2_TITLE", "PLAYER_CHOICE_M22_OPTION2_BODY")
	end
	
	if not block_m23 then
		object_indicator_add_objective_text(M22_triggers.kill_killbane, "PLAYER_CHOICE_M22_OPTION1_TITLE", "PLAYER_CHOICE_M22_OPTION1_BODY")
	end
	
	-- add waypoint if we are forcing you to go somewhere
	if block_m24 then
		mission_waypoint_add(M22_triggers.kill_killbane)
	end
	if block_m23 then
		mission_waypoint_add(M22_triggers.save_saints)
	end
	
	-- Start playing the music "I need a Hero"
	delay(1.0)
	audio_object_post_event(M22_audio_events.music_start, nil, nil, LOCAL_PLAYER)
	
	-- Wait until the player choice phone call has finished (or the player already made it to a choice trigger)
	while(thread_check_done(M22_threads.convo_handle) == false and Player_choice == "none") do
		thread_yield()
	end
	
	delay(1.0)

	if group_is_loaded(M22_groups.Oleg_and_Pierce.name) then		
		-- Play Pierce's convincing phone call (if the player hasn't already made their choice)
		if (Player_choice == "none") then
			audio_play_persona_line(M22_groups.Oleg_and_Pierce.pierce, M22_dialog_lines.pierce_convincing)
			delay(0.5)
			
			-- Wait for the line to finish
			while audio_persona_line_playing(M22_groups.Oleg_and_Pierce.pierce) do
				thread_yield()
			end
		end
		
		-- Play Oleg's convincing phone call (if the player hasn't already made their choice)
		if (Player_choice == "none") then
			audio_play_persona_line(M22_groups.Oleg_and_Pierce.oleg, M22_dialog_lines.oleg_convincing)
			delay(0.5)
			
			-- Wait for the line to finish
			while audio_persona_line_playing(M22_groups.Oleg_and_Pierce.oleg) do
				thread_yield()
			end
		end
	end

	while Player_choice == "none" do
		thread_yield()
	end
end

-- Clean up left over npcs from the armory
function m22_cleanup_statue_courtesy_boats()
	if group_is_loaded(M22_groups.Statue_Boats) then
		group_destroy(M22_groups.Statue_Boats)
	end
end

-- The cutscene showing the player's choices
function m22_choice_airport_cutscene()
	-- Kick off a thread for the player choice conversation, and wait for it to finish
	-- M22_threads.convo_handle = thread_new("m22_play_cell_convo", M22_conversations.choice_phone_call.name, true)

	local line_handle = audio_play_persona_line_2d(M22_personas.angel.persona_id, M22_dialog_lines.choice_call[1])
	-- Wait for the line to finish
	m22_wait_for_foley_safe(line_handle, 60.0)
	audio_stop(line_handle)
	
	line_handle = audio_play_persona_line(LOCAL_PLAYER, M22_dialog_lines.choice_call[2])
	delay(1.0)
	-- Wait for the line to finish
	m22_wait_for_foley_safe(line_handle, 60.0)
	audio_stop(line_handle)
	
	-- Play the CTE showing the airport
	cutscene_in()
	group_create( cte_plane_group.name, true )
	
	cutscene_play( M22_cte_choice_01.name )
	while(cutscene_check_exiting() == true) do
		thread_yield()
	end
	
	group_destroy( cte_plane_group.name )
	cutscene_out()
end

function m22_choice_statue_cutscene()
	-- Play the CTE showing the statue
	cutscene_in()
	group_create( M22_groups.Hostages.name, true )
	group_create( cte_kia_group.name, true )
	local teleport_navs = { Armory_battle_zone.center_pos, Armory_battle_zone.center_pos }
	cutscene_play( M22_cte_statue_01.name, nil, teleport_navs )
	group_destroy( M22_groups.Hostages.name )
	group_destroy( cte_kia_group.name )
	cutscene_out()
end

-- Cutscene for the airpot angel rail sequence
function m22_angel_rail_cutscene()

	fade_out(0.5)
   fade_out_block()
	delay(1)
	
	--message("After protecting Angel he will explain in a CTE cutscene that Killbane is getting on his personal jet and will be taking off in short order.", 5)
	--delay(5)
	
	--message("The player tells Angel to “get me there” and they both will then run to a nearby spawned vehicle (4-door, convertible if possible) and get into it. ", 5)
	--message("Angel will drive.", 5)
	--delay(5)
	
	fade_in(0.5)
   fade_in_block()
end

-- Handles the sequence where Angel drives the player to the airport
function m22_in_transit_to_airport()
	objective_text_clear(0)
	objective_text( 0, "m22_obj_stop_killbane", "", "", SYNC_ALL , OI_ASSET_KILL)
	
	set_ignore_ai_flag(M22_characters.Angel)
	
	-- Setup notoriety
	notoriety_set("luchadores", 5) -- AC: Changed from 3 to 5
	notoriety_set_can_decay(false)
	notoriety_force_no_spawn("luchadores", false)
	notoriety_force_no_spawn_group("stag_tank", true)
	notoriety_force_no_spawn_group("stag_attack_heli", true)
	notoriety_force_no_spawn_group("stag_heli", true)
	notoriety_force_no_spawn_group("stag_riot", true)
	
	-- Set up a delay so the transition is not jarring
	delay(2.0)
	
	fade_out(0.5)
	fade_out_block()
	
	teleport_coop(M22_navpoints.player_angel_start[1], M22_navpoints.player_angel_start[2], true)
	
	inv_add_temp_loadout(M22_PLAYER_KB_LOADOUT)
	
	set_unjackable_flag(M22_vehicles.Angels_Car, false)
		
	vehicle_enter_teleport(M22_characters.Angel, M22_vehicles.Angels_Car, 0, true, true)
	set_seatbelt_flag(M22_characters.Angel, ENABLE)
	vehicle_enter_teleport(LOCAL_PLAYER, M22_vehicles.Angels_Car, 1, true, true)
	set_player_can_enter_exit_vehicles(LOCAL_PLAYER, false)
	if in_coop then
		vehicle_enter_teleport(REMOTE_PLAYER, M22_vehicles.Angels_Car, 2, true, true)
		set_player_can_enter_exit_vehicles(REMOTE_PLAYER, false)
	end
	
	fade_in(0.5)
	fade_in_block()
	
	vehicle_suppress_flipping(M22_vehicles.Angels_Car)
	vehicle_suppress_npc_exit(M22_vehicles.Angels_Car)
	vehicle_speed_override(M22_vehicles.Angels_Car, 45)
	vehicle_set_allow_ram_ped(M22_vehicles.Angels_Car, ENABLE)
	vehicle_set_ignore_rail_obstacles(M22_vehicles.Angels_Car, ENABLE)
	vehicle_ignore_repulsors(M22_vehicles.Angels_Car, ENABLE) 
	vehicle_set_crazy(M22_vehicles.Angels_Car, ENABLE)
	vehicle_prevent_transition_to_ambient(M22_vehicles.Angels_Car, true)
	set_unjackable_flag(M22_vehicles.Angels_Car, true)
	vehicle_set_script_hard_goto(M22_vehicles.Angels_Car, true)
	
	-- Turn off roadblocks for this part
	roadblocks_enable(false)
	
	-- Infinite mass for car
	vehicle_infinite_mass(M22_vehicles.Angels_Car, ENABLE)
	
	M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.angel_car_chase, 5.0)
	
	-- Don't allow this pathfind to fail.  If it does, keep trying.
	while get_dist(M22_vehicles.Angels_Car, "Airport_Rail_Begin") > 10.0 do
		vehicle_pathfind_to(M22_vehicles.Angels_Car, "Airport_Rail_Begin", false, false)
		thread_yield()
	end
	
	vehicle_set_crazy(M22_vehicles.Angels_Car, DISABLE)
end

-- Player meets up with angel and must protect him
function m22_protect_angel_sequence()
	objective_text_clear(0)
	objective_text( 0, "m22_obj_help_angel", "", "", SYNC_ALL , OI_ASSET_DEFEND)
	
	if group_is_loaded(M22_groups.Angel.name) == false then
		group_create(M22_groups.Angel.name, true)
	end
	if group_is_loaded(M22_groups.Angels_Attackers.name) == false then
		group_create(M22_groups.Angels_Attackers.name, true)
	end
	
	-- Make sure the player can't enter Angel's car before he's supposed to.
	set_unjackable_flag(M22_vehicles.Angels_Car, true)

	marker_add(M22_groups.Angel.members[1], MINIMAP_ICON_PROTECT_ACQUIRE, OI_ASSET_DEFEND, OI_FLAGS_DEFAULT, SYNC_ALL)
	process_enemy_set(M22_groups.Angels_Attackers.members)

	notoriety_force_no_spawn("luchadores", true)
	
	marker_remove(M22_groups.Angel.members[1])
	
	-- Apparently this cutscene was cut; all it does is fade out and in... which is bad.
	--m22_angel_rail_cutscene()
end

-- Performs all the necessary operations to set up the chase sequence
function m22_setup_killbane_chase_sequence()
	notoriety_force_no_spawn("police", false) -- turn of stag notoriety spawns for this sequence - AC: turned back on for test
	notoriety_force_no_spawn("luchadores", false) -- turn of notoriety spawns for now, makes rail sequence too hard - AC: turned back on for test
	notoriety_set("luchadores", 5)
	notoriety_set_can_decay(false)

	Num_plane_hits = 0
	group_create(M22_groups.Airport, true)
	
	vehicle_enter_teleport(M22_characters.Killbane, M22_vehicles.Killbanes_Plane, 0, true)
	marker_add(M22_vehicles.Killbanes_Plane, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL)
	on_projectile_hit("m22_projectile_hit_cb")
	vehicle_set_invulnerable_to_player_explosives(M22_vehicles.Killbanes_Plane, true)
	vehicle_suppress_flipping(M22_vehicles.Killbanes_Plane)
	-- Infinite mass for car
	vehicle_infinite_mass(M22_vehicles.Angels_Car, ENABLE)
	-- Infinite mass for Killbane's airplane
	vehicle_infinite_mass(M22_vehicles.Killbanes_Plane, ENABLE)
	vehicle_set_allow_ram_ped(M22_vehicles.Killbanes_Plane, ENABLE)
	vehicle_set_ignore_rail_obstacles(M22_vehicles.Killbanes_Plane, ENABLE)
	vehicle_ignore_repulsors(M22_vehicles.Killbanes_Plane, ENABLE) 
	vehicle_set_crazy(M22_vehicles.Killbanes_Plane, ENABLE)
	vehicle_prevent_transition_to_ambient(M22_vehicles.Killbanes_Plane, true)
	set_unjackable_flag(M22_vehicles.Killbanes_Plane, true)
	vehicle_set_script_hard_goto(M22_vehicles.Killbanes_Plane, true)
	
	M22_threads.killbane_path_handle = thread_new("m22_airport_killbane_path_thread")
	M22_threads.player_path_handle = thread_new("m22_angel_car_path_thread")
	M22_threads.player_car_speed_handle = thread_new("m22_manage_players_car_speed_thread")
	
	on_trigger("m22_spawn_first_roadblock_cb", M22_triggers.roadblock_one)
	on_trigger("m22_spawn_second_roadblock_cb", M22_triggers.roadblock_two)
	on_trigger("m22_spawn_third_roadblock_cb", M22_triggers.roadblock_three)
	on_trigger("m22_spawn_fourth_roadblock_cb", M22_triggers.roadblock_four)
	trigger_enable(M22_triggers.roadblock_one)
	trigger_enable(M22_triggers.roadblock_two)
	trigger_enable(M22_triggers.roadblock_three)
	trigger_enable(M22_triggers.roadblock_four)
end

-- Waits for Killbane's plane to be destroyed before continueing
function m22_process_killbane_chase_sequence()
	while(not vehicle_is_destroyed(M22_vehicles.Killbanes_Plane)) do
		thread_yield()
	end
	
--	vehicle_max_speed(M22_vehicles.Angels_Car, 40)
--	delay(3)
	
--	vehicle_max_speed(M22_vehicles.Angels_Car, 20)
--	delay(3)
	
	vehicle_max_speed(M22_vehicles.Angels_Car, 10)
	delay(1)
	
	vehicle_freeze(M22_vehicles.Angels_Car)
	
	
	delay(1.0)
	
	--[[ CONVERSATION CUT
	while M22_threads.convo_handle ~= INVALID_THREAD_HANDLE do
		-- wait for the conversation to finish
		thread_yield()
	end
	--]]
	
	-- remove temp weapons
	inv_remove_temp_loadout(M22_PLAYER_KB_LOADOUT)
	vehicle_exit(LOCAL_PLAYER)
	set_player_can_enter_exit_vehicles(LOCAL_PLAYER, true)
	if in_coop then
		vehicle_exit(REMOTE_PLAYER)
		set_player_can_enter_exit_vehicles(REMOTE_PLAYER, true)
	end
	
	-- Clean up the two remaining roadblocks
	group_destroy(M22_groups.Angel)
	group_destroy(M22_groups.Airport_Roadblock_three) -- cleanup the first roadblock
	group_destroy(M22_groups.Airport_Roadblock_four) -- cleanup the first roadblock
end

-- Simple function that performs the necessary setup for the Killbane boss portion of M22
function m22_setup_kill_killbane()
	-- Teleport the players first so that we can wait for Killbane to activate in group_create
	teleport_coop(M22_navpoints.player_kbfight_start[1], M22_navpoints.player_kbfight_start[2])
	
	if game_choice_get_state(MISSION_21_CHOICE) == M21_CHOICE_KILLBANE_UNMASKED then
		group_create_hidden(M22_groups.Killbane_QTE_Nomask.name, true)
		M22_characters.Killbane_QTE = M22_groups.Killbane_QTE_Nomask.killbane
	else
		group_create_hidden(M22_groups.Killbane_QTE.name, true)
		M22_characters.Killbane_QTE = M22_groups.Killbane_QTE.killbane
	end

	zscene_prep(M22_cutscenes.plane_destroyed)
	
	turn_vulnerable(M22_characters.Killbane_QTE)
	character_set_never_catch_fire(M22_characters.Killbane_QTE, true)
	set_ignore_ai_flag(M22_characters.Killbane_QTE, false)
	
	-- Apply the plane crash zone swap
	city_zone_swap("planecrash")
	
	-- Disable all player's weapons
	inv_weapon_disable_all_slots(true)
	
	inv_item_equip(nil, LOCAL_PLAYER)
	if in_coop then
		inv_item_equip(nil, REMOTE_PLAYER)
	end
	
	-- AC: Turn off notoriety for this
	notoriety_force_no_spawn("police", true) -- turn off stag notoriety spawns for this sequence
	notoriety_force_no_spawn("stag", true) -- AC: Test - turn off stag notoriety spawns for this sequence
	notoriety_force_no_spawn("luchadores", true) -- turn off notoriety spawns for now,
	
	-- Make sure Killbane is ready to go.
	--while (not character_is_ready(M22_characters.Killbane_QTE)) do
	--	thread_yield()
	--end
	
	while(zscene_is_loaded() == false) do
		thread_yield()
	end
end

-- Waits for Killbane to die before continueing
function m22_process_kill_killbane()
	audio_object_post_event("M22_QTE_Music_Start", nil, nil, LOCAL_PLAYER)
	qte_start(LOCAL_PLAYER, "M22_BossFight", "m22_killbane_qte_completed_cb", M22_characters.Killbane_QTE)
	
	objective_text_clear(0)
	objective_text( 0, "m22_obj_kill_killbane", "", "", SYNC_ALL , OI_ASSET_KILL)
	
	-- Kick off a thread to process the dialog for this sequence
--	M22_threads.kill_killbane_dialog = thread_new("m22_process_kill_killbane_dialog_thread")

	-- Register a callback to stop the QTE and fade out before the QTE actually finishes and
	-- Killbane goes all floppy on the ground.
	on_qte_animation_trigger("on_killbane_qte_fade_out_trigger")

	-- Wait until the QTE is finished
	while(not Killbane_qte_finished) do
		thread_yield()
	end
	
	-- Let the players move again.
	player_movement_enable(LOCAL_PLAYER)
	if coop_is_active() then
		player_movement_enable(REMOTE_PLAYER)
	end
	
	-- Kill the thread processing the dialog
--	thread_kill(M22_threads.kill_killbane_dialog)
--	M22_threads.kill_killbane_dialog = INVALID_THREAD_HANDLE
	
	Next_mission = Mission_23_name
end

function on_killbane_qte_fade_out_trigger()
	on_qte_animation_trigger("")
	qte_cleanup()
	fade_out(0.5)
	Killbane_qte_finished = true
end

-- Plays the bink of killbane emerging from the rubble
function m22_killbane_plane_destroyed_scene()
	-- Prevent the players from moving, that can screw up the orientation of the QTE.
	player_movement_disable(LOCAL_PLAYER)
	if coop_is_active() then
		player_movement_disable(REMOTE_PLAYER)
	end

	-- Play the bink
	cutscene_play(M22_cutscenes.plane_destroyed, nil, M22_navpoints.player_kbfight_start, false)
	
	-- Unhide Killbane, he should be in place
	character_show(M22_characters.Killbane_QTE)

	-- Wait for Killbane to be ready before fading in.
	--while ( not character_is_ready(M22_characters.Killbane_QTE)) do
	--	thread_yield()
	--end
	
	fade_in(0.5)
	fade_in_block()
end

function m22_killbane_qte_completed_cb()
	Killbane_qte_finished = true
end

-- Thread to process Killbane's dialog
function m22_process_kill_killbane_dialog_thread()

	-- Play the second dialog line
	m22_play_persona_line_and_wait(M22_characters.Killbane_QTE, M22_dialog_lines.killbane_fight_02)
	
	delay(5.0)
	
	-- Play the third dialog line
	m22_play_persona_line_and_wait(M22_characters.Killbane_QTE, M22_dialog_lines.killbane_fight_03)
	
	delay(3.0)
	
	-- Play the 4th dialog line
	M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.killbane_fight_04, 0.0)
	while(thread_check_done(M22_threads.convo_handle) == false) do
		thread_yield()
	end
end

-- Process the sequence when the player arrives at the doc
function m22_arrived_at_dock_sequence()
	objective_text_clear(0)	
	-- Play some dialog of the player talking to Kinzie
	m22_play_persona_line_and_wait(LOCAL_PLAYER, M22_dialog_lines.kinzie_dock)
	
	--delay(1.5)
end

-- Player arrived at the statue to find a battle going on
function m22_go_to_statue_sequence()
	objective_text_clear(0)
	objective_text( 0, "m22_obj_goto_statue", "", "", SYNC_ALL, OI_ASSET_LOCATION )
	
	m22_helper_populate_statue()
	
	group_create(M22_groups.Statue_Base.name)

	on_trigger("m22_player_used_elevator_cb", M22_triggers.statue_elevator)
	trigger_enable(M22_triggers.statue_elevator, true)
	marker_add_trigger(M22_triggers.statue_elevator, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)

	while not Player_used_elevator do
		thread_yield()
	end

	group_destroy(M22_groups.Statue_Base.name)
end

-- Helper to spawn the initial NPCs at the statue
function m22_helper_populate_statue()
	if (M22_statue_populated == false) then
		group_create(M22_groups.Statue.name)
		
		for i, saint in pairs(M22_groups.Statue.saints) do
			m22_setup_hostage(saint)
			set_ignore_ai_flag(saint, true)
			turn_invulnerable(saint)

			-- Set the animation state
			set_script_animation_state(saint, "hostage idle")

			-- AC Test
			inv_item_remove_all(M22_groups.Statue.saints[i])
			
			-- Register some callbacks
			on_trigger("m22_saint_untied_cb", M22_triggers.untie[i])
			on_death("m22_saint_died_cb", saint)
			trigger_enable(M22_triggers.untie[i], true)
		end		
		
		-- Set up continuous spawn
		for i, spawn in pairs(m22_statue_spawn_regions)do
			spawn_region_enable(m22_statue_spawn_regions[i], true)
		end
		continuous_spawn_start(M22_groups.Statue_Spawn1.name, 0, 1)
		continuous_spawn_start(M22_groups.Statue_Spawn2.name, 0, 1)
		continuous_spawn_start(M22_groups.Statue_Spawn3.name, 0, 1)
		continuous_spawn_start(M22_groups.Statue_Spawn4.name, 0, 1)
		continuous_spawn_start(M22_groups.Statue_Spawn5.name, 0, 1)		
	end
	
	M22_statue_populated = true
end

-- Sets up npcs, triggers and movers for the save the saints sequence
function m22_setup_save_the_saints()
	group_create(M22_groups.Viola, true)
	m22_setup_hostage(M22_characters.Viola)
	
	m22_helper_populate_statue()
	
	for i, mover in pairs(M22_movers.c4) do
		on_mover_destroyed("m22_c4_destroyed_cb", mover)
		on_take_damage("m22_c4_damaged_cb", mover)
		on_mover_enter_water("m22_c4_entered_water_cb", mover)
		mesh_mover_reset(mover)
		mesh_mover_show(mover)
	--	marker_add(mover, MINIMAP_ICON_USE, OI_ASSET_USE, OI_FLAGS_DEFAULT, SYNC_ALL)
		Num_c4_left_to_destroy = Num_c4_left_to_destroy + 1
	end
	
	for i, mover in pairs(M22_movers.first_floor)do
		on_mover_destroyed("m22_c41_destroyed_cb", mover)
		on_take_damage("m22_c4_damaged_cb", mover)
		on_mover_enter_water("m22_c41_entered_water_cb", mover)
		mesh_mover_reset(mover)
		mesh_mover_show(mover)
		marker_add(mover, MINIMAP_ICON_USE, OI_ASSET_USE, OI_FLAGS_DEFAULT, SYNC_ALL)
		Num_c4_left_to_destroy = Num_c4_left_to_destroy + 1
		Num_c4_left_first_floor = Num_c4_left_first_floor + 1
	end
	
	trigger_enable(M22_triggers.statue_explosion_region, ENABLE)
	on_trigger_exit("m22_human_left_statue_cb", M22_triggers.statue_explosion_region)
	
	Total_c4_to_destroy = Num_c4_left_to_destroy
end

-- Processing function that waits until all the c4 has been destroyed
function m22_process_save_the_saints()
	objective_text( 0, "m22_obj_remove_bombs", Total_c4_to_destroy - Num_c4_left_to_destroy, Total_c4_to_destroy .. " ", SYNC_ALL, OI_ASSET_USE )

	local time_in_ms = STATUE_EXPLOSION_TIME * 1000
	hud_timer_set(1, time_in_ms, "m22_statue_times_up_cb")

	while(Num_c4_left_first_floor > 0)do
		thread_yield()
	end
	-- Disable first floor spawn regions
	spawn_region_enable(m22_statue_spawn_regions[1], false)
	spawn_region_enable(m22_statue_spawn_regions[4], false)
	spawn_region_enable(m22_statue_spawn_regions[5], false)
	spawn_region_enable(m22_statue_spawn_regions[8], false)
	
	objective_text( 0, "m22_obj_proceed_up_statue", "", "", SYNC_ALL, OI_ASSET_LOCATION )
	on_trigger("m22_first_floor_cb", M22_triggers.First_Floor)
	trigger_enable(M22_triggers.First_Floor, true)
	marker_add_trigger(M22_triggers.First_Floor, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
	
	while not Second_floor_reached do
		thread_yield()
	end
	
	objective_text( 0, "m22_obj_remove_bombs", Total_c4_to_destroy - Num_c4_left_to_destroy, Total_c4_to_destroy .. " ", SYNC_ALL, OI_ASSET_USE )

	--M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.viola_monument, 0.0)

	local played_music_fade = false
	while(Num_c4_left_to_destroy > 0) do
		-- If there's only 5 seconds left, start fading out the music
		if (played_music_fade == false and hud_timer_get_remainder(1) < 5000) then
			audio_object_post_event(M22_audio_events.music_fade_out, nil, nil, LOCAL_PLAYER)
			played_music_fade = true
		end
		thread_yield()
	end
	
	-- If the music isn't already fading, then stop it
	if (played_music_fade == false) then
		audio_object_post_event(M22_audio_events.music_fade_out, nil, nil, LOCAL_PLAYER)
	end
end

-- Cleans everything up from save the saints sequence
function m22_cleanup_save_the_saints()
	
	on_trigger("m22_player_reached_breadcrumb_cb", M22_triggers.Kia_Breadcrumb)
	trigger_enable(M22_triggers.Kia_Breadcrumb, true)
	marker_add_trigger(M22_triggers.Kia_Breadcrumb, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
	party_dismiss_all()
	
	hud_timer_stop(1) -- stop the clock
	
	objective_text_clear(0)
	objective_text( 0, "m22_obj_proceed_up_statue", "", "", SYNC_ALL, OI_ASSET_LOCATION )
	delay(3)
	
	while not Player_reached_breadcrumb do
		thread_yield()
	end
	
	on_trigger("m22_player_reached_top_cb", M22_triggers.Player_reached_top)
	trigger_enable(M22_triggers.Player_reached_top, true)
	marker_add_trigger(M22_triggers.Player_reached_top, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)	
	
	while not Player_reached_top do
		thread_yield()
	end
	
	for i, saint in pairs(M22_groups.Statue.saints) do
		on_death("", saint)
		m22_cleanup_trigger(M22_triggers.untie[i])
	end
	
	-- Stop continuous spawn
	for i, spawn in pairs(m22_statue_spawn_regions)do
		spawn_region_enable(m22_statue_spawn_regions[i], false)
	end
	continuous_spawn_stop(M22_groups.Statue_Spawn1.name)
	continuous_spawn_stop(M22_groups.Statue_Spawn2.name)
	continuous_spawn_stop(M22_groups.Statue_Spawn3.name)
	continuous_spawn_stop(M22_groups.Statue_Spawn4.name)
	continuous_spawn_stop(M22_groups.Statue_Spawn5.name)
	
	-- remove sonic gun
	--inv_remove_temp_loadout(M22_PLAYER_SONIC_LOADOUT)
	
	on_trigger_exit("", M22_triggers.statue_explosion_region)
	trigger_enable(M22_triggers.statue_explosion_region, DISABLE)
	
	group_destroy(M22_groups.Statue.name)
	group_destroy(M22_groups.Viola)
	m22_kia_fight_cte()
end

-- Performs all the needed setup for the Kia fight
function m22_setup_kill_kia()
	objective_text_clear(0)
	objective_text( 0, "m22_obj_kill_kia", "", "", SYNC_ALL , OI_ASSET_KILL)
	
	
	
	group_create(M22_groups.Kia, true)
	group_create(M22_groups.Hostages, true)
	group_create(M22_groups.Viola, true)
	group_create(M22_groups.Kia_battle_props, true)
	
	-- Setup the hostages
	m22_setup_hostage(M22_characters.Mayor)
	m22_setup_hostage(M22_characters.Shaundi)
	m22_setup_hostage(M22_characters.Viola)
	
	-- Setup Kia
	character_allow_ragdoll(M22_characters.Kia, false)
	character_set_immune_to_explosion_vomit(M22_characters.Kia, true)
	character_set_no_explosive_panic(M22_characters.Kia, true)
	character_set_never_catch_fire(M22_characters.Kia, true)
	npc_weapon_spread(M22_characters.Kia, KIA_WEAPON_SPREAD_MULTIPLIER)
	on_take_damage("m22_kia_damaged_cb", M22_characters.Kia)
	marker_add(M22_characters.Kia, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL)
	
	-- Setup Shaundi
	character_set_immune_to_explosion_vomit(M22_characters.Shaundi, true)
	character_set_no_explosive_panic(M22_characters.Shaundi, true)
	character_set_never_catch_fire(M22_characters.Shaundi, true)
	turn_invulnerable(M22_characters.Shaundi, true) -- can still be hurt by the player
	on_death("m22_shaundi_killed_cb", M22_characters.Shaundi)
	
	-- Setup the Mayor (Burt)
	on_take_damage("m22_burt_damaged_cb", M22_characters.Mayor)
	set_script_animation_state(M22_characters.Mayor, "hostage idle")
	set_script_animation_state(M22_characters.Viola, "hostage idle")

	-- Setup the Fart in a Jar ammo triggers
	for i, trigger in pairs(M22_triggers.fart_jars) do
		trigger_enable(trigger, true)
		marker_add_trigger(trigger, MINIMAP_ICON_USE, nil, OI_ASSET_USE, OI_FLAGS_DEFAULT, SYNC_ALL)
		on_trigger("m22_give_fart_in_jar_ammo_cb", trigger)
	end
	
	-- Setup the player killed triggers
	trigger_enable(M22_triggers.Kia_Boss_Area, ENABLE)
	on_trigger_exit("m22_human_left_statue_cb", M22_triggers.Kia_Boss_Area)
end

-- Spins until Kia dies
function m22_process_kill_kia()
	-- Start boss fight music.
	audio_object_post_event(M22_audio_events.music_kia_start, nil, nil, LOCAL_PLAYER)
	
	M22_threads.kia_boss_handle = thread_new("m22_kia_boss_ai_thread")

	M22_threads.vtol_one_handle = thread_new("m22_process_kia_vtols_thread")
	if in_coop then
		M22_threads.vtol_two_handle = thread_new("m22_kia_coop_reinforcements_thread")
	end

	M22_threads.kill_kia_dialog = thread_new("m22_process_kill_kia_dialog_thread")

	while not character_is_dead(M22_characters.Kia) do
		thread_yield()
	end
	
	-- End boss fight music.
	audio_object_post_event(M22_audio_events.music_kia_finish, nil, nil, LOCAL_PLAYER)
	
	-- Delay so the end isn't so jarring.
	delay(1.0)
	

	thread_kill(M22_threads.kill_kia_dialog)
	M22_threads.kill_kia_dialog = INVALID_THREAD_HANDLE
end

-- Thread to process Kia's dialog
function m22_process_kill_kia_dialog_thread()
	M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.kia_fight, 0.0)
	while(thread_check_done(M22_threads.convo_handle) == false) do
		thread_yield()
	end
	
	delay(1.5)
	
	-- Tell the player to grab the FIAJ
	audio_play_persona_line(M22_characters.Shaundi, M22_dialog_lines.shaundi_grab_fiaj)
	
	delay(2.0)
	
	M22_threads.burt_dialog = thread_new("m22_process_burt_dialog_thread")
	
	-- Process Shaundi FIAJ nags
	delay(10.0)
	while(true) do
		-- Play the line
		audio_play_persona_line(M22_characters.Shaundi, M22_dialog_lines.shaundi_grab_fiaj_nag)
		
		-- Add a delay and then wait until Shaundi isn't actively vomitting
		delay(rand_int(15, 25))
		while(thread_check_done(M22_threads.kia_vomit_handle) == false) do
			thread_yield()
		end
		
		-- If one of the players got a FIAJ, then stop processing the nags
		if (Player_got_fiaj == true) then
			break
		end
	end
end

-- Thread to process Burt's dialog
function m22_process_burt_dialog_thread()
	while(true) do
		audio_play_persona_line(M22_characters.Mayor, M22_dialog_lines.burt_encouragement[rand_int(1, #M22_dialog_lines.burt_encouragement)])
		
		delay(rand_int(15, 25))
	end
end

-- Cleans up the kia fight - kills of the vtol threads
function m22_cleanup_kill_kia()
	Next_mission = Mission_24_name
	
	on_take_damage("", M22_characters.Kia)
	marker_remove(M22_characters.Kia)
	
	on_death("", M22_characters.Shaundi)
	on_take_damage("", M22_characters.Mayor)
	
	m22_remove_temp_weapons_for_save_saints()
	
	on_trigger_exit("", M22_triggers.Kia_Boss_Area)
	trigger_enable(M22_triggers.Kia_Boss_Area, DISABLE)	
	
	-- Disable the Fart in a Jar ammo triggers
	for i, trigger in pairs(M22_triggers.fart_jars) do
		trigger_enable(trigger, false)
		on_trigger("", trigger)
	end
	
	thread_kill(M22_threads.vtol_one_handle)
	M22_threads.vtol_one_handle = INVALID_THREAD_HANDLE
	
	thread_kill(M22_threads.vtol_two_handle)
	M22_threads.vtol_two_handle = INVALID_THREAD_HANDLE
end

function m22_c4_objective_cte()
	fade_out(0.5)
	fade_out_block()
	
	-- Unhide all the C4 at the statue
	for i, mover in pairs(M22_movers.c4) do
		mesh_mover_reset(mover)
		mesh_mover_show(mover)
	end
	for i, mover in pairs(M22_movers.first_floor) do
		mesh_mover_reset(mover)
		mesh_mover_show(mover)
	end
	
	--group_create( M22_groups.Statue.name, true )
	m22_setup_statue_courtesy_boats()
	group_create( M22_groups.Statue_CTE.name, true )
	cutscene_play( M22_cte_statue_02.name, nil, M22_navpoints.player_dock_start )
	group_destroy( M22_groups.Statue_CTE.name )
	--group_destroy( M22_groups.Statue.name )
	
	-- Give the players sonic guns and farts in jars.
	m22_give_temp_weapons_for_save_saints()
	
	--Get rid of Kinzie
	if group_is_loaded(M22_groups.Kinzie)then
		group_destroy(M22_groups.Kinzie)
	end
	
	-- Hide all the C4 at the statue until it's time for that objective
	for i, mover in pairs(M22_movers.c4) do
		mesh_mover_hide(mover)
	end
	for i, mover in pairs(M22_movers.first_floor) do
		mesh_mover_hide(mover)
	end
	
	fade_in(0.5)
	fade_in_block()
end

function m22_kia_fight_cte()
	fade_out(0.5)
	fade_out_block()
	
	message("-- CTE Plays Here --", 5)
	message("Kia is shown on the girder of the statue and she curses her plans being foiled by those meddling kids", 5)	
	
	m22_setup_kill_kia()
	delay(5)
	
	fade_in(0.5)
	fade_in_block()
end

-- ***************************************************
-- m22_run Helper Functions
-- ***************************************************

-- Waits for a script foley (persona line) to finish playing, 
-- or stops the foley and continues on if a maximum wait time has
-- expired.
--
-- foley_id:  (int)   the ID of the foley to wait for.
-- max_wait:  (float) the maximum time to wait for the foley.
--
function m22_wait_for_foley_safe(foley_id, max_wait)
	-- Wait for anything else that was using the failsafe thread handle to finish.
	while M22_threads.audio_failsafe ~= INVALID_THREAD_HANDLE do
		thread_yield()
	end
	
	M22_threads.audio_failsafe = thread_new("delay", max_wait)
	
	-- Wait until the line has ended or our maximum wait time has elapsed.
	while audio_is_playing(foley_id) and thread_check_done(M22_threads.audio_failsafe) == false do
		thread_yield()
	end
	
	-- Kill the voice line if it's still playing.
	if audio_is_playing(foley_id) then
		audio_stop(foley_id)
	end
	
	thread_kill(M22_threads.audio_failsafe)
	M22_threads.audio_failsafe = INVALID_THREAD_HANDLE
end

-- This function adds a GPS path to the nearest battle zone.
--
function m22_gps_path_to_nearest_battle()
	local nearest_dist = nil
	local nearest_group_nav = nil
	for i, group in pairs(Battle_Zone_Groups) do
		if group.cleared == false then
			local cur_dist = get_dist_closest_player_to_object(group.center_pos)
			if nearest_dist == nil or cur_dist < nearest_dist then
				nearest_dist = cur_dist
				nearest_group_nav = group.center_pos
			end
		end
	end
	
	if nearest_group_nav ~= nil then
		if Nearest_bz_center ~= nearest_group_nav then
			Nearest_bz_center = nearest_group_nav
			mission_waypoint_add(nearest_group_nav)
		end
	end
end

-- Plays a persona line on a character and waits for it to finish.
--
function m22_play_persona_line_and_wait(character, persona_line)
	local play_success = audio_play_persona_line(character, persona_line)
	if play_success then
		delay(1.0)
		while(audio_persona_line_playing(character) == true) do
			thread_yield()
		end
	end
end

function m22_cell_convo_finished()
	M22_cur_cell_call_name = ""
end

function m22_play_cell_convo(conv_name, receiving_call, persona_override_id)
	while M22_cur_cell_call_name ~= "" do
		thread_yield()
	end
	M22_cur_cell_call_name = conv_name
	audio_play_for_mission_cellphone(conv_name, receiving_call, true, "", "m22_cell_convo_finished", persona_override_id)
	while M22_cur_cell_call_name ~= "" do
		thread_yield()
	end
	M22_cur_cell_call_name = ""
end

-- Spawns the initial npc group for a battle zone.  It then sets each member's on_death callback
-- used for kill count management and reinforcemences.
--
-- battle_zone:	(string) name of a table containing tables of the Stag and Syndicate groups
						 -- EX:
						 --	Battle_Zone_One = { Battle_Zone_One_Stag, Battle_Zone_One_Synd }
function m22_spawn_battle_zone(battle_zone)
	Current_bz.num_initial_synd_alive = 0
	Current_bz.num_initial_stag_alive = 0
	Current_bz.kills = 0
	Current_bz.num_bosses = 0
	Current_bz.bosses_killed = 0
	Current_bz.num_enemies_released = 0
		
	-- Initialize the hud bar.
	m22_helper_update_battle_zone_hud()
	
	-- Spawn a finale boss set
	
	for i, spawn_group in pairs(Battle_Zone_Finales[Number_of_zones_cleared + 1]) do
		Current_bz.num_bosses = Current_bz.num_bosses + 1
	end
	
	-- Check if there are any old battle zone groups that need to be destroyed
	for i, battle_zone_group in pairs(Battle_Zone_Groups) do
		if (group_is_loaded(battle_zone_group.initial_spawn.name) == true) then
			group_destroy(battle_zone_group.initial_spawn.name)
		end
		if (group_is_loaded(battle_zone_group.saints_group.name) == true) then
			release_to_world(battle_zone_group.saints_group.name)
			group_destroy(battle_zone_group.saints_group.name)
		end
	end
	delay(1.0)	-- arbitrary time to allow group to be cleaned up

	-- Spawn the initial spawn group group
	group_create(battle_zone.initial_spawn.name, true)
	for i, member in pairs(battle_zone.initial_spawn.members) do
		if (character_is_dead(member) == false) then
			-- Set up the on death callback for all members of the initial Stag force
			local team = get_team(member)
			if (team == "STAG") then
				on_death("m22_battle_zone_stag_initial_died_cb", member)
				Current_bz.num_initial_stag_alive = Current_bz.num_initial_stag_alive + 1
			elseif (team == "Luchadores" or team == "Morningstar" or team == "Deckers") then
				on_death("m22_battle_zone_synd_initial_died_cb", member)
				Current_bz.num_initial_synd_alive = Current_bz.num_initial_synd_alive + 1
			end
		end
	end
	
	-- Spawn and immediately release the vehicles for the battle zone.
	if battle_zone.initial_vehicles.spawned == false then
		battle_zone.initial_vehicles.spawned = true
		group_create(battle_zone.initial_vehicles.name, true)
		release_to_world(battle_zone.initial_vehicles.name)
		group_destroy(battle_zone.initial_vehicles.name)
	end

	-- Spawn courtesy vehicle
	m22_create_player_courtesy_vehicle(battle_zone.courtesy_vehicles)
end

-- Helper function to update the the battle zone HUD
function m22_helper_update_battle_zone_hud()
	-- Update the progress bar
	local kills_remaining = max((Current_bz.zone.required_kills - Current_bz.kills), 0)
	local bosses_remaining = max((#Battle_Zone_Finales[Number_of_zones_cleared + 1] - Current_bz.bosses_killed), 0)
	local bar_remaining = kills_remaining + bosses_remaining * Battle_zone_boss_hud_bar_factor
	
	if (Local_player_zone == ZONE_ACTIVE) then
		hud_bar_set_value(0, bar_remaining, SYNC_LOCAL)
	end
	if (Remote_player_zone == ZONE_ACTIVE) then
		hud_bar_set_value(1, bar_remaining, SYNC_REMOTE)
	end
end

-- Given a player, this checks the other player's current zone slot
--
-- player:		(string) name of the player
--
-- returns: 	FIRST/SECOND
function m22_other_player_in_zone(player)
	if player == LOCAL_PLAYER then
		-- Need to see if the remote player is in zone
		return (Remote_player_zone)
	else
		return (Local_player_zone)
	end
end

-- Sets a player's zone slot
--
-- player:		(string) name of a player
--
function m22_set_players_zone(player)
	if LOCAL_PLAYER == player then
		Local_player_zone = ZONE_ACTIVE
	elseif REMOTE_PLAYER == player then
		Remote_player_zone = ZONE_ACTIVE
	end	
end

-- Gets a player's zone slot
--
-- player:		(string) name of a player
--
-- returns:		FIRST/SECOND
function m22_get_players_zone(player)
	if player == LOCAL_PLAYER then
		return (Local_player_zone)
	else
		return (Remote_player_zone)
	end
end

-- Removes all on_death callbacks for a given zone
--
-- zone_groups:	group of the initial stag/synd	
function m22_remove_on_death_callbacks(zone_groups)
	for k, char_name in pairs(zone_groups.initial_spawn.members) do
		on_death("", char_name)
	end
end

-- Displays location markers for all unbeaten battle zones to the players
function m22_show_remaining_battle_zones()
	for i, battle_zone in pairs(Battle_Zone_Groups) do
		if (battle_zone.cleared == false) then
			marker_add_trigger(battle_zone.trigger, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
		end
	end
end

-- Setup a STAG transport VTOL (assumes the group has already been created) *copied from M10, written by Matt G*
--
-- vtol_table:		Lua table defining the STAG transport
function m22_setup_stag_transport(vtol_table)
	local seat_idx = 0
	for i, char in pairs(vtol_table.pilots) do
		-- Put the pilots into the vehicle
		vehicle_enter_teleport(char, vtol_table.vtol, seat_idx, true)
		follower_remain_in_car(char, true)
		
		seat_idx = seat_idx + 1
	end
	--for i, drop_off in pairs(vtol_table.drop_offs) do
		for j, char in pairs(vtol_table.drop_offs.soldiers) do
			-- Put the soldiers into the vehicle
			vehicle_enter_teleport(char, vtol_table.vtol, seat_idx, true)
			follower_remain_in_car(char, true)
			
			seat_idx = seat_idx + 1
		end
	--end
end

-- Sets up a hostage character for the statue sequence. No ragdoll, flinching, or attacking this character.
--
-- hostage_name:	(string) name of the hostage in question
--
function m22_setup_hostage(hostage_name)
	character_allow_ragdoll(hostage_name, DISABLE)
	character_prevent_flinching(hostage_name, ENABLE)
	character_prevent_bumping(hostage_name, true)
	set_dont_attack_me_on_sight_flag(hostage_name, true)
end

function m22_spawn_and_move_roadblock(group_name, dest_navpoint_set_name)
	group_create(group_name, true)

	for i, member in pairs(group_name.members) do
		local car = group_name.cars[i]
		vehicle_enter_teleport(member, car) -- teleport each driver in their car
		M22_threads.roadblock_driveto_handles[i] = thread_new("m22_roadblock_drive_to_thread", member, car, dest_navpoint_set_name[i], i)
	end
end

-- Create a player coutesy vehicle group
function m22_create_player_courtesy_vehicle(courtesy_vehicle_group)
	group_create(courtesy_vehicle_group.name, true)
	
	-- If this isn't coop, hide the second vehicle
	if (coop_is_active() == false) then
		vehicle_hide(courtesy_vehicle_group.vehicles[2])
	end
end

-- Function to setup a player's courtesy vehicle by teleporting the player(s) and homies into the vehicle seats
function m22_setup_player_courtesy_vehicle(courtesy_vehicle_group)
	-- Put the players into the vehicle
	local seat_idx = 0
	vehicle_enter_teleport(LOCAL_PLAYER, courtesy_vehicle_group.vehicles[1], seat_idx, true)
	seat_idx = seat_idx + 1	-- increment to the next seat
	if (coop_is_active() == true) then
		vehicle_enter_teleport(REMOTE_PLAYER, courtesy_vehicle_group.vehicles[1], seat_idx, true)
		seat_idx = seat_idx + 1	-- increment to the next seat
	end
	
	-- Put the homies into the vehicle
	vehicle_enter_teleport(M22_characters.Pierce, courtesy_vehicle_group.vehicles[1], seat_idx, true)
	vehicle_enter_teleport(M22_characters.Oleg, courtesy_vehicle_group.vehicles[1], 5, true) -- force Oleg into his "special" seat in the back
end

-- Simple function that enables/disables notoriety spawning of brutes.  The ordering matters when enableing/disabling
--
-- enable:			(bool) true - turns brutes on, false - turns brutes off
function m22_brute_enable(enable)
	if enable then
		-- Enable brutes
		disable_specific_notoriety_group("luchadores", 4, "G_Luchadore_Brute_M", false)
		disable_specific_notoriety_group("luchadores", 4, "G_Luchadore_Brute_F", false)
		disable_specific_notoriety_group("luchadores", 4, "G_Luchadore_Brute_G", false)
		disable_specific_notoriety_group("luchadores", 5, "G_Luchadore_Brute_M", false)
		disable_specific_notoriety_group("luchadores", 5, "G_Luchadore_Brute_F", false)
		disable_specific_notoriety_group("luchadores", 5, "G_Luchadore_Brute_G", false)			
	else
		-- Disable brutes
		disable_specific_notoriety_group("luchadores", 4, "G_Luchadore_Brute_M", true)
		disable_specific_notoriety_group("luchadores", 4, "G_Luchadore_Brute_F", true)
		disable_specific_notoriety_group("luchadores", 4, "G_Luchadore_Brute_G", true)
		disable_specific_notoriety_group("luchadores", 5, "G_Luchadore_Brute_M", true)
		disable_specific_notoriety_group("luchadores", 5, "G_Luchadore_Brute_F", true)
		disable_specific_notoriety_group("luchadores", 5, "G_Luchadore_Brute_G", true)
	end
end

-- Function that sets Stag and Syndacite min/max notorieties to a specific level.
--
-- level:	(int) level to set notoriety to
function m22_set_stag_synd_notoriety(level)
	notoriety_set_min_and_max("police", level, level)
	notoriety_set("police", level)
	notoriety_set_min_and_max("luchadores", level, level)
	notoriety_set("luchadores", level)
end

-- Gives the sonic gun and farts in jars to both players.
--
function m22_give_temp_weapons_for_save_saints()
	inv_weapon_add_temporary(LOCAL_PLAYER, KIA_TEMPORARY_WEAPON, 1, false, false, false, true)
	-- Remove any normal flashbangs and replace them with farts in jars.
	inv_item_remove(KIA_TEMPORARY_GRENADE, LOCAL_PLAYER)
	inv_weapon_add_temporary(LOCAL_PLAYER, KIA_TEMPORARY_GRENADE, 2, false, false, false, true, WEAPON_LEVEL4)
	if coop_is_active() then
		inv_weapon_add_temporary(REMOTE_PLAYER, KIA_TEMPORARY_WEAPON, 1, false, false, false, true)
		-- Remove any normal flashbangs and replace them with farts in jars.
		inv_item_remove(KIA_TEMPORARY_GRENADE, REMOTE_PLAYER)
		inv_weapon_add_temporary(REMOTE_PLAYER, KIA_TEMPORARY_GRENADE, 2, false, false, false, true, WEAPON_LEVEL4)
	end
end

-- Removes the temporary sonic gun and farts in jars from both players.
--
function m22_remove_temp_weapons_for_save_saints()
	inv_weapon_remove_temporary(LOCAL_PLAYER, KIA_TEMPORARY_WEAPON)
	inv_weapon_remove_temporary(LOCAL_PLAYER, KIA_TEMPORARY_GRENADE)
	if (coop_is_active() == true) then
		inv_weapon_remove_temporary(REMOTE_PLAYER, KIA_TEMPORARY_WEAPON)
		inv_weapon_remove_temporary(REMOTE_PLAYER, KIA_TEMPORARY_GRENADE)
	end
end

-- Equips the sonic gun on both players when entering the statue.
--
function m22_equip_temp_weapons_for_save_saints()
	inv_item_equip(KIA_TEMPORARY_WEAPON, LOCAL_PLAYER)
	if coop_is_active() then
		inv_item_equip(KIA_TEMPORARY_WEAPON, REMOTE_PLAYER)
	end
end

-- ***************************************************
-- m22_initialize Helper Functions
-- ***************************************************

-- Handle any common initialization
--
function m22_initialize_common()	
	Completed_m23 = mission_is_complete("m23")
	Completed_m24 = mission_is_complete("m24")
	
	city_zone_swap("burn", ENABLE)
	
	-- If the player is replaying this mission, and the statue got blown
	-- up previously, undo that for the duration of the mission.
	city_zone_swap("rubble", false)
	
	-- Let people buy stuff even though there's notoriety.
	shop_ignore_clerk(true)
	
	--notoriety_force_no_spawn("police", true)
	flashpoints_enable(DISABLE) -- no flashpoints for this mission
	set_stag_active(ENABLE)
	
	disable_specific_notoriety_group("stag", 2, "G_STAG_CopCar", true)
	disable_specific_notoriety_group("stag", 3, "G_STAG_CopCar", true)
	disable_specific_notoriety_group("stag", 4, "G_STAG_CopCar", true)
	disable_specific_notoriety_group("stag", 5, "G_STAG_CopCar", true)
	disable_specific_notoriety_group("stag", 2, "G_STAG_BikeCop", true)
	disable_specific_notoriety_group("stag", 3, "G_STAG_BikeCop", true)
	
	notoriety_set_can_decay(DISABLE)
	
	notoriety_force_no_spawn_group("stag_tank", true)
	notoriety_force_no_spawn_group("stag_attack_heli", true)
	notoriety_force_no_spawn_group("stag_heli", true)
	notoriety_force_no_spawn_group("stag_riot", true)
	
	roadblocks_ambient_traffic_enable(false)
	
	-- Show Fake Notoriety
	hud_set_fake_notoriety("police", true, 5)
	hud_set_fake_notoriety("luchadores", true, 5)

	set_civilians_flee(ENABLE, ENABLE, LOCAL_PLAYER)
	
	-- Create the roadblocks around the city
	for i, roadblock in pairs(M22_roadblocks) do
		roadblock.handle = roadblock_create(roadblock.layout, roadblock.navpoint)
	end
	
	-- Hide alll the C4 at the statue until it's time for that objective
	for i, mover in pairs(M22_movers.c4) do
		mesh_mover_hide(mover)
	end
	for i, mover in pairs(M22_movers.first_floor) do
		mesh_mover_hide(mover)
	end
	
	-- Load up kinzie's persona
	M22_personas.kinzie.persona_id = audio_persona_load_2d(M22_personas.kinzie.name)
	M22_personas.kia.persona_id = audio_persona_load_2d(M22_personas.kia.name)
	M22_personas.angel.persona_id = audio_persona_load_2d(M22_personas.angel.name)
	
	-- Spawn fewer parked cars so we have room for all the vehicles at the battle zones.
	parking_spot_set_max(4)
end

-- Check if the given checkpoint name is a battle zone checkpoint
--
-- checkpoint_name:				Name of the checkpoint
-- 
-- returns:
--		is_battle_zone:			True if the checkpoint is for a battle zone
--		last_zone_completed:	Last battle zone that was completed
--		second_zone_complted:	The second battle zone that was completed (or nil if only one battle zone has been completed)
function m22_checkpoint_is_battle_zone(checkpoint_name)
	if (checkpoint_name == M22_checkpoints.BATTLE_ZONE_1) then
		return true, 1
	elseif (checkpoint_name == M22_checkpoints.BATTLE_ZONE_2) then
		return true, 2
	elseif (checkpoint_name == M22_checkpoints.BATTLE_ZONE_3) then
		return true, 3
	end
	
	return false
end

-- Check if the given checkpoint name is an armory checkpoint
--
-- checkpoint_name:				Name of the checkpoint
-- 
-- returns:
--		is_armory_checkpoint:	True if the checkpoint is for a battle zone
--		last_zone_completed:	Last battle zone that was completed
function m22_checkpoint_is_get_to_armory(checkpoint_name)
	if (checkpoint_name == M22_checkpoints.GOTO_ARMORY1) then
		return true, 1
	elseif (checkpoint_name == M22_checkpoints.GOTO_ARMORY2) then
		return true, 2
	elseif (checkpoint_name == M22_checkpoints.GOTO_ARMORY3) then
		return true, 3
	end
	
	return false
end

-- Checkpoint specific initialization
--
-- checkpoint:		The checkpoint to be initialized
function m22_initialize_checkpoint(checkpoint)
	if (checkpoint == M22_checkpoints.CHECKPOINT_START) then
		Number_of_zones_cleared = 0
		Latest_zone_cleared = 0
		
		m22_create_player_courtesy_vehicle(M22_groups.Start_Vehicle)
		m22_setup_oleg_and_pierce()
		
		teleport_coop(M22_navpoints.local_start, M22_navpoints.remote_start, true)
		
		-- Setup the courtesy vehicle
		m22_setup_player_courtesy_vehicle(M22_groups.Start_Vehicle)
		
		m22_brute_enable(DISABLE) -- turn off notoriety brute spawning
		m22_set_stag_synd_notoriety(2)
		
	end
	
	local is_battle_zone, zone1, zone2 = m22_checkpoint_is_battle_zone(checkpoint)
	if (is_battle_zone == true) then
		Latest_zone_cleared = zone1
		Battle_Zone_Groups[zone1].cleared = true
		
		if (zone2 == nil) then
			Number_of_zones_cleared = 1
		else
			Number_of_zones_cleared = 2
			Battle_Zone_Groups[zone2].cleared = true
		end
		
		m22_setup_oleg_and_pierce()
		m22_brute_enable(DISABLE) -- turn off notoriety brute spawning
		m22_set_stag_synd_notoriety(2)
		
		-- Create the courtesy vehicles
		m22_create_player_courtesy_vehicle(Battle_Zone_Groups[Latest_zone_cleared].courtesy_vehicles)
		
		-- Create the Saints groups
		group_create(Battle_Zone_Groups[Latest_zone_cleared].saints_group.name, true)
		
		teleport_coop(Battle_Zone_Groups[Latest_zone_cleared].player_starts[1], Battle_Zone_Groups[Latest_zone_cleared].player_starts[2], true)

		-- Setup the courtesy vehicle
		m22_setup_player_courtesy_vehicle(Battle_Zone_Groups[Latest_zone_cleared].courtesy_vehicles)
	end
	
	local is_go_to_armory, last_zone = m22_checkpoint_is_get_to_armory(checkpoint)
	if (is_go_to_armory == true) then
		Latest_zone_cleared = last_zone
		Number_of_zones_cleared = 2
	
		m22_setup_oleg_and_pierce()
		m22_brute_enable(DISABLE) -- turn off notoriety brute spawning
		m22_set_stag_synd_notoriety(4)
		
		-- Create the courtesy vehicles
		m22_create_player_courtesy_vehicle(Battle_Zone_Groups[Latest_zone_cleared].courtesy_vehicles)
		
		teleport_coop(Battle_Zone_Groups[Latest_zone_cleared].player_starts[1], Battle_Zone_Groups[Latest_zone_cleared].player_starts[2], true)
		
		-- Setup the courtesy vehicle
		m22_setup_player_courtesy_vehicle(Battle_Zone_Groups[Latest_zone_cleared].courtesy_vehicles)
	end

	if (checkpoint == M22_checkpoints.ARMORY_FIGHT) then
		Number_of_zones_cleared = 3
	
		m22_setup_oleg_and_pierce()
		
		Local_player_zone = ZONE_ACTIVE
		Remote_player_zone = ZONE_ACTIVE
		
		teleport_coop(Armory_battle_zone.player_starts[1], Armory_battle_zone.player_starts[2], true)
		Armory_reached = true
		m22_brute_enable(DISABLE) -- turn off notoriety brute spawning
	end
	
	if (checkpoint == M22_checkpoints.DEBUG_AIRPORT_CHOICE or checkpoint == M22_checkpoints.DEBUG_STATUE_CHOICE) then
		-- NOTHING TO DO
	end
	
	if (checkpoint == M22_checkpoints.MAKE_YOUR_CHOICE) then
		-- Spawn courtesy vehicle
		m22_create_player_courtesy_vehicle(Armory_battle_zone.courtesy_vehicles)
		teleport_coop(Armory_battle_zone.player_starts[1], Armory_battle_zone.player_starts[2], true)		
	end
	
	if (checkpoint == M22_checkpoints.STOP_KILLBANE) then
		group_create(M22_groups.Angel.name, true)
		group_create(M22_groups.Angels_Attackers.name, true)		
		
		teleport_coop(M22_navpoints.player_angel_start[1], M22_navpoints.player_angel_start[2], true)
		-- Play some music where we left off
		audio_object_post_event(M22_audio_events.music_start_checkpoint, nil, nil, LOCAL_PLAYER)
	end
	
	if (checkpoint == M22_checkpoints.KILL_KILLBANE) then
		m22_setup_kill_killbane()
	end
	
	if (checkpoint == M22_checkpoints.GOTO_SAINTS or checkpoint == M22_checkpoints.DEBUG_STATUE_CTE) then
		-- Create the courtesy vehicles
		m22_setup_statue_courtesy_boats()	
		
		teleport_coop(M22_navpoints.player_dock_start[1], M22_navpoints.player_dock_start[2])
		
		-- Play some music where we left off
		audio_object_post_event(M22_audio_events.music_start_checkpoint, nil, nil, LOCAL_PLAYER)		
	end	

	if (checkpoint == M22_checkpoints.SAVE_SAINTS) then
		
		m22_setup_save_the_saints()
		
		-- Give the player the sonic gun and farts in jars.
		m22_give_temp_weapons_for_save_saints()
		-- Equip the sonic gun.
		m22_equip_temp_weapons_for_save_saints()
		
		teleport_coop(M22_navpoints.statue_obs_deck, M22_navpoints.statue_obs_deck)
		
		-- Play some music where we left off
		audio_object_post_event(M22_audio_events.music_start_checkpoint, nil, nil, LOCAL_PLAYER)		
	end
	
	if (checkpoint == M22_checkpoints.KILL_KIA) then
		m22_setup_kill_kia()
		
		-- Give the player the sonic gun and farts in jars.
		m22_give_temp_weapons_for_save_saints()
		
		teleport_coop(M22_navpoints.player_kia_fight_start[1] , M22_navpoints.player_kia_fight_start[2])
	end

end


-- ***************************************************
-- Miscellaneous m22 Helper Funcrtions
-- ***************************************************

-- Create Oleg and Pierce and assigns them as homies
function m22_setup_oleg_and_pierce()
	group_create(M22_groups.Oleg_and_Pierce.name, true)
	party_add(M22_characters.Pierce, LOCAL_PLAYER)
	
	if in_coop then
		party_add(M22_characters.Oleg, REMOTE_PLAYER)
	else
		party_add(M22_characters.Oleg, LOCAL_PLAYER)
	end
	
	party_set_dismissable(false)
	on_death("m22_oleg_died_cb", M22_characters.Oleg)
	on_death("m22_pierce_died_cb", M22_characters.Pierce)
	on_dismiss("m22_pierce_abandoned_cb", M22_characters.Pierce)
	follower_set_can_abandon(M22_characters.Pierce, ENABLE)
end

-- Resets callbacks and disables a given trigger
--
-- trigger_name:		(string) name of the trigger to clean up
--
function m22_cleanup_trigger(trigger_name)
	on_trigger("", trigger_name)
	on_trigger_exit("", trigger_name)
	trigger_enable(trigger_name, false)
	marker_remove_trigger(trigger_name)
end

-- Cleans up all triggers
--
function m22_cleanup_triggers(trigger_group)
	for i, trigger in pairs(trigger_group) do
		if (type(trigger) == "table") then
			m22_cleanup_triggers(trigger)
		else		
			m22_cleanup_trigger(trigger)
		end
	end
end

--  Cleans up all threads
--
function m22_cleanup_threads(thread_group)
	for i, thread in pairs(thread_group) do
		if (type(thread) == "table") then
			m22_cleanup_threads(thread)
		else		
			if thread ~= INVALID_THREAD_HANDLE then
				thread_kill(thread)
				thread = INVALID_THREAD_HANDLE
			end
		end
	end
end

-- Resets the on_mover_destroyed callback for all movers
--
function m22_cleanup_movers(mover_group)
	for i, mover in pairs(mover_group) do
		if (type(mover) == "table") then
			m22_cleanup_movers(mover)
		else		
			on_mover_destroyed("", mover)
			on_take_damage("", mover)
			on_mover_enter_water("", mover)
		end
	end
end

-- Stops any active conversation and restores the handle to invalid
function m22_cleanup_conversations()
	-- If we have a conversation thread active, kill it
	if M22_threads.convo_handle ~= INVALID_THREAD_HANDLE then
		if Active_conversation.convo_table ~= nil then
			audio_conversation_end(Active_conversation.convo_table.handle)
			Active_conversation.convo_table.handle = INVALID_CONVERSATION_HANDLE
			Active_conversation.convo_table = nil
		end
		thread_kill(M22_threads.convo_handle)
		M22_threads.convo_handle = INVALID_CONVERSATION_HANDLE
	end
	
	audio_remove_mission_cellphone(M22_cur_cell_call_name)
	M22_cur_cell_call_name = ""
end

-- Unloads any 2d personas used in the mission
function m22_cleanup_personas()
	for i, persona in pairs(M22_personas) do
		if persona.persona_id ~= INVALID_PERSONA_HANDLE then
			audio_persona_remove_2d(persona.persona_id)
			persona.persona_id = INVALID_PERSONA_HANDLE
		end
	end
end
-- *************************
--
-- Callback functions
--
-- *************************

function m22_oleg_died_cb()
	mission_end_failure("m22", "m22_failure_oleg_died")
end

function m22_pierce_died_cb()
	mission_end_failure("m22", "m22_failure_pierce_died")
end

function m22_pierce_abandoned_cb()
	mission_end_failure("m22", "m22_failure_pierce_abandoned")
end

-- On killed callback for all humanoids within a battle zone. Increments the player's kill count.
--
-- team:		(string) Team that this particular humanoid belongs to
-- killer:	(string) The name of the character/player that killed them
function m22_battle_zone_initial_died_cb(team, killer)

	if (team == "Civilian") then
		return
	end
	
	if (team == "Saints") then
		return
	end

	if (killer == LOCAL_PLAYER or killer == REMOTE_PLAYER) then
		if killer ~= nil then
			if object_is_in_trigger(Current_bz.zone.trigger, killer) then
				Current_bz.kills = Current_bz.kills + 1
				m22_helper_update_battle_zone_hud()
			end
		end
	end
end

-- Callback for a initial stag spawn within a battle zone.  This function, will update kill credit and
-- spawn numbers, and then spawn reinforcements as necessary.
--
-- npc:		(string) name of the npc who died
-- killer:	(string) name of the character that killed them
function m22_battle_zone_stag_initial_died_cb(npc, killer)
	-- MLG (07/06/11): We're running out of animation memory, so we need to be stricter with how we clean-up guys.
	--					Don't release these NPCs into the world, since we're going to destroy their group before the next
	--					battle location spawns
	-- WillA (9/5/2011): We need to release some of these guys to free up NPC slots for notoriety, so we'll release the first
	--                     NUM_ZONE_ENEMIES_TO_RELEASE guys that die.
	-- character is dead, release it if we need to
	if Current_bz.num_enemies_released < NUM_ZONE_ENEMIES_TO_RELEASE then
		Current_bz.num_enemies_released = Current_bz.num_enemies_released + 1
		if not character_is_released(npc) then
			release_to_world(npc)
			thread_yield()
		end
	end
	
	Current_bz.num_initial_stag_alive = Current_bz.num_initial_stag_alive - 1	

	-- Spawn the backup waves based on how many of the initial spawn remain.
	if (Current_bz.num_initial_stag_alive <= 10) then

		local level = 3
		if (Number_of_zones_cleared == 2) then
			level = 4
		end
		
		m22_set_stag_synd_notoriety(level)
	
		notoriety_force_no_spawn("stag", false)
		--notoriety_force_no_spawn("luchadores", false)
		
		local stag_navpoint_name = Current_bz.zone.center_pos
		--local luchadore_navpoint_name = Current_bz.zone.center_pos
		
		notoriety_spawn_group_set_destination("stag", stag_navpoint_name)
		--notoriety_spawn_group_set_destination("luchadores", luchadore_navpoint_name)
	end
end

-- Callback for a initial synd spawn within a battle zone.  This function, will update kill credit and
-- spawn numbers, and then spawn reinforcements as necessary.
--
-- npc:		(string) name of the npc who died
-- killer:	(string) name of the character that killed them
function m22_battle_zone_synd_initial_died_cb(npc, killer)
	-- MLG (07/06/11): We're running out of animation memory, so we need to be stricter with how we clean-up guys.
	--					Don't release these NPCs into the world, since we're going to destroy their group before the next
	--					battle location spawns	
	-- WillA (9/5/2011): We need to release some of these guys to free up NPC slots for notoriety, so we'll release the first
	--                     NUM_ZONE_ENEMIES_TO_RELEASE guys that die.
	-- character is dead, release it if we need to
	if Current_bz.num_enemies_released < NUM_ZONE_ENEMIES_TO_RELEASE then
		Current_bz.num_enemies_released = Current_bz.num_enemies_released + 1
		if not character_is_released(npc) then
			release_to_world(npc)
			thread_yield()
		end
	end
	
	Current_bz.num_initial_synd_alive = Current_bz.num_initial_synd_alive - 1			
	
	-- Spawn the backup waves based on how many of the initial spawn remain.
	if (Current_bz.num_initial_synd_alive <= 10) then
		local level = 3
		if (Number_of_zones_cleared == 2) then
			level = 4
		end
	
		m22_set_stag_synd_notoriety(level)
		
		--notoriety_force_no_spawn("stag", false)
		notoriety_force_no_spawn("luchadores", false)
		
		--local stag_navpoint_name = Current_bz.zone.center_pos
		local luchadore_navpoint_name = Current_bz.zone.center_pos
		
		--notoriety_spawn_group_set_destination("stag", stag_navpoint_name)
		notoriety_spawn_group_set_destination("luchadores", luchadore_navpoint_name)
	end
end

-- On_trigger callback for battle zone triggers.  Figures out which zone was triggered, associates the player
-- with that zone, spawns it if it hasn't already started, and then sets up the on_trigger_exit callback.
--
-- player:			(string) name of the player who triggered the zone
-- trigger_name:	(string) name of the trigger
--
function m22_zone_triggered_cb(player, trigger_name)
	-- Find out which zone was triggered
	local battle_zone = m22_helper_battle_zone_from_trigger(trigger_name)
	
	-- We don't care if the battlezone is already cleared
	if (battle_zone.cleared == true) then
		return
	end
	
	-- If there's already a battle zone active, we only care if the player is entering that zone
	if (Current_bz.zone ~= NO_ZONE and Current_bz.zone ~= battle_zone) then
		return
	end
	
	-- Remove all the trigger markers
	for i, battle_zone in pairs(Battle_Zone_Groups) do
		marker_remove_trigger(battle_zone.trigger, SYNC_ALL)
	end
	
	-- Check to see if this is a new zone that needs to go active
	if Current_bz.zone == NO_ZONE then
		Current_bz.zone = battle_zone

		-- Enable the battle area trigger
		on_trigger("m22_battle_area_triggered_cb", Current_bz.zone.battle_area)
		on_trigger_exit("m22_battle_area_exited_cb", Current_bz.zone.battle_area)
		trigger_enable(Current_bz.zone.battle_area, true)		
	end
	m22_set_players_zone(player)
	
	local other_player_in_zone = m22_other_player_in_zone(player)
	local hud_bar_size = Current_bz.zone.required_kills + Battle_zone_boss_hud_bar_factor * #Battle_Zone_Finales[Number_of_zones_cleared + 1]

	if player == LOCAL_PLAYER then
		objective_text_clear(0)
		hud_bar_on(0, "Health", "m22_obj_clear_battlezone", hud_bar_size, SYNC_LOCAL, OI_ASSET_KILL)
		
		-- Add the battle area radius, and a marker to the center of the battle area
		minimap_icon_add_radius(Current_bz.zone.center_pos, trigger_get_radius(Current_bz.zone.battle_area), SYNC_LOCAL)
		marker_add(Current_bz.zone.center_pos, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_LOCAL)
	
		if m22_other_player_in_zone(player) ~= ZONE_ACTIVE then
			-- remote player isnt in a zone
			marker_add_trigger(trigger_name, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_REMOTE)
		end
	elseif player == REMOTE_PLAYER then
		objective_text_clear(1)
		hud_bar_on(1, "Health", "m22_obj_clear_battlezone", hud_bar_size, SYNC_REMOTE, OI_ASSET_KILL)
		
		-- Add the battle area radius, and a marker to the center of the battle area
		minimap_icon_add_radius(Current_bz.zone.center_pos, trigger_get_radius(Current_bz.zone.battle_area), SYNC_REMOTE)
		marker_add(Current_bz.zone.center_pos, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_REMOTE)

		if m22_other_player_in_zone(player) ~= ZONE_ACTIVE then
			-- host player isnt in a zone
			marker_add_trigger(trigger_name, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_LOCAL)
		end
	end
end

-- On_trigger_exit callback used for when a player exits a zone.  Will shut down the battle zone if the player
-- is the last one to leave the zone
--
-- player:			(string) name of the player who triggered the zone
-- trigger_name:	(string) name of the trigger
--
function m22_zone_exited_cb(player, trigger_name)
	local other_player_zone = m22_other_player_in_zone(player)
	
	-- Don't care if there is no active zone
	if (Current_bz.zone == NO_ZONE) then
		return
	end
	
	--Check to see if the other player is still in the zone
	if other_player_zone ~= ZONE_ACTIVE then
		-- Kill the thread processing the battle zone
		thread_kill(M22_threads.battle_zone_instance)
		
		m22_cleanup_battle_zone_kill_enemies()
		
		-- Destroy the guys we spawned
		if (group_is_loaded(Current_bz.zone.initial_spawn.name) == true) then
			group_destroy(Current_bz.zone.initial_spawn.name)
		end
		
		-- Release the courtesy vehicle to the world and destroy the group
		if group_is_loaded(Current_bz.zone.courtesy_vehicles.name) then
			release_to_world(Current_bz.zone.courtesy_vehicles.name)
			group_destroy(Current_bz.zone.courtesy_vehicles.name)
		end		
		
		m22_cleanup_battle_zone_saint_reinforcements()
	else 
		-- We're in coop, and this player left the zone before their partner
		if (Current_bz.zone.cleared == false) then
			-- Was the zone cleared? If not, give them the icon to get back in to help their friend
			marker_add_trigger(trigger_name, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, sync_from_player(player))
		end
	end
	
	if LOCAL_PLAYER == player then
		Local_player_zone = NO_ZONE
		hud_bar_off(0)
		objective_text( 0, "m22_obj_goto_battlezone", "", "", SYNC_LOCAL , OI_ASSET_LOCATION)
		
		minimap_icon_remove_radius(Current_bz.zone.center_pos, SYNC_LOCAL)
		marker_remove(Current_bz.zone.center_pos, SYNC_LOCAL)
	else
		Remote_player_zone = NO_ZONE
		hud_bar_off(1)
		objective_text( 1, "m22_obj_goto_battlezone", "", "", SYNC_REMOTE , OI_ASSET_LOCATION)
		
		minimap_icon_remove_radius(Current_bz.zone.center_pos, SYNC_REMOTE)
		marker_remove(Current_bz.zone.center_pos, SYNC_REMOTE)
	end
end

-- Get a battle zone table from a trigger name (used for callbacks)
--
-- trigger_name:	Name of the trigger 
function m22_helper_battle_zone_from_trigger(trigger_name)
	-- Find out which zone was triggered
	for i, battle_zone in pairs(Battle_Zone_Groups) do
		if (battle_zone.trigger == trigger_name or battle_zone.battle_area == trigger_name) then
			return battle_zone
		end
	end

	if (Armory_battle_zone.trigger == trigger_name or Armory_battle_zone.battle_area == trigger_name) then
		return Armory_battle_zone
	end
	
	return NO_ZONE
end

-- Callback when the player enters the battle area for a batttle zone
function m22_battle_area_triggered_cb(player, trigger_name)
	-- If a battle zone isn't active or this isn't the battle area for that zone, just return
	local battle_zone = m22_helper_battle_zone_from_trigger(trigger_name)
	if (Current_bz.zone == NO_ZONE or Current_bz.zone ~= battle_zone) then
		return
	end
	
	-- Remove the marker leading the player to the battle area
	if LOCAL_PLAYER == player then
		marker_remove(battle_zone.center_pos, SYNC_LOCAL)
	else
		marker_remove(battle_zone.center_pos, SYNC_REMOTE)
	end
end

-- Callback when the players leaves the battle area for a battle zone
function m22_battle_area_exited_cb(player, trigger_name)
	-- If a battle zone isn't active or this isn't the battle area for that zone, just return
	local battle_zone = m22_helper_battle_zone_from_trigger(trigger_name)
	if (Current_bz.zone == NO_ZONE or  Current_bz.zone ~= battle_zone) then
		return
	end

	-- Add the marker leading the player to the battle area
	if LOCAL_PLAYER == player then
		marker_add(battle_zone.center_pos, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_LOCAL)
	else
		marker_add(battle_zone.center_pos, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_REMOTE)
	end	
end

-- On_trigger callback used to determine when a player reaches the armory
--
-- player:			(string) name of the player that entered the trigger
-- trigger_name:	(string) name of the trigger entered
--
function m22_armory_reached_cb(player, trigger_name)
	m22_set_players_zone(LOCAL_PLAYER)
	if (coop_is_active() == true) then
		m22_set_players_zone(REMOTE_PLAYER)
	end

	Armory_reached = true
	mission_waypoint_remove()
	m22_cleanup_trigger(trigger_name)
end

-- On_trigger callback used to determine which area the player went to
--
-- player:			(string) name of the player that entered the trigger
-- trigger_name:	(string) name of the trigger entered
--
function m22_player_choice_cb(player, trigger_name)
	if trigger_name == M22_triggers.kill_killbane then
		Player_choice = "killbane"
	elseif trigger_name == M22_triggers.save_saints then
		Player_choice = "shaundi"
	end
	
	-- Cleanup the triggers
	m22_cleanup_trigger(M22_triggers.kill_killbane_perimeter)
	m22_cleanup_trigger(M22_triggers.save_saints_perimeter)
	m22_cleanup_trigger(M22_triggers.kill_killbane)
	m22_cleanup_trigger(M22_triggers.save_saints)
end

-- On_vehicle_enter callback used to determine when a player has entered a vehicle capable of reaching the statue
function m22_player_entered_vehicle_cb(player, vehicle_name)
	local veh_type = get_vehicle_type(vehicle_name)
	if (veh_type == VT_AIRPLANE or veh_type == VT_HELICOPTER or veh_type == VT_VTOL or veh_type == VT_WATERCRAFT) then
		marker_remove(M22_navpoints.statue_boat_loc)
		marker_add_trigger(M22_triggers.save_saints, MINIMAP_ICON_PROTECT_ACQUIRE, INGAME_EFFECT_CHECKPOINT, OI_ASSET_DEFEND, OI_FLAGS_LOCATION, SYNC_ALL)
	end
end

-- On_projectile_hit callback that is used to monitor Killbanes plane for RPG hits
--
-- object_hit_type:		(string) type of object that was hit by a projectile
-- object_hit_name:		(string) name of the object that was hit
-- weapon:				(string) name of the weapon type from which the projectile originated
--
function m22_projectile_hit_cb(object_hit_type, object_hit_name, weapon)
	if object_hit_type == "vehicle" and object_hit_name == M22_vehicles.Killbanes_Plane then
		Num_plane_hits = Num_plane_hits + 1
		if Num_plane_hits == NUM_HITS_TO_STOP_PLANE then
			on_projectile_hit("")
			
			-- Clean up the pathing threads
			thread_kill(M22_threads.killbane_path_handle)
			thread_kill(M22_threads.player_path_handle)
			thread_kill(M22_threads.player_car_speed_handle)
			M22_threads.killbane_path_handle = INVALID_THREAD_HANDLE
			M22_threads.player_path_handle = INVALID_THREAD_HANDLE
			M22_threads.player_car_speed_handle = INVALID_THREAD_HANDLE
			
			-- Destroy the Airplane
			turn_vulnerable(M22_vehicles.Killbanes_Plane)
			vehicle_detonate(M22_vehicles.Killbanes_Plane)
			marker_remove(M22_vehicles.Killbanes_Plane)
			vehicle_stop(M22_vehicles.Angels_Car)

		else
			-- Reduce the HP of the plan 
			local max = get_max_hit_points(M22_vehicles.Killbanes_Plane)
			set_current_hit_points(M22_vehicles.Killbanes_Plane, max * ((NUM_HITS_TO_STOP_PLANE - Num_plane_hits) / NUM_HITS_TO_STOP_PLANE))
		end		
	end

end

-- On_trigger callback that spawns and moves the first roadblock of the Killbane chase sequence
--
-- player:			(string) name of the player that triggered the trigger
-- trigger_name:	(string) name of the trigger
--
function m22_spawn_first_roadblock_cb(player, trigger_name)
	m22_cleanup_trigger(trigger_name)
	m22_spawn_and_move_roadblock(M22_groups.Airport_Roadblock_one, M22_navpoints.roadblock_one_move_tos)
end

-- On_trigger callback that spawns and moves the second roadblock of the Killbane chase sequence
--
-- player:			(string) name of the player that triggered the trigger
-- trigger_name:	(string) name of the trigger
--
function m22_spawn_second_roadblock_cb(player, trigger_name)
	m22_cleanup_trigger(trigger_name)
	M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.angel_shoot_plane, 5.0)
	m22_spawn_and_move_roadblock(M22_groups.Airport_Roadblock_two, M22_navpoints.roadblock_two_move_tos)
end

-- On_trigger callback that spawns and moves the third roadblock of the Killbane chase sequence
--
-- player:			(string) name of the player that triggered the trigger
-- trigger_name:	(string) name of the trigger
--
function m22_spawn_third_roadblock_cb(player, trigger_name)
	group_destroy(M22_groups.Airport_Roadblock_one) -- cleanup the first roadblock
	m22_cleanup_trigger(trigger_name)
	m22_spawn_and_move_roadblock(M22_groups.Airport_Roadblock_three, M22_navpoints.roadblock_three_move_tos)
end

-- On_trigger callback that spawns and moves the third roadblock of the Killbane chase sequence
--
-- player:			(string) name of the player that triggered the trigger
-- trigger_name:	(string) name of the trigger
--
function m22_spawn_fourth_roadblock_cb(player, trigger_name)
	group_destroy(M22_groups.Airport_Roadblock_two) -- cleanup the second roadblock
	m22_cleanup_trigger(trigger_name)
	m22_spawn_and_move_roadblock(M22_groups.Airport_Roadblock_four, M22_navpoints.roadblock_four_move_tos)
end

-- On_mover_destroyed callback used to keep track of the C4
--
-- mover_name:		(string) name of the script mover
-- attacker:		(string) name of the character that destroyed the mover
--
function m22_c4_destroyed_cb(mover_name, attacker)
	on_take_damage("", mover_name)
	on_mover_destroyed("", mover_name)
	on_mover_enter_water("", mover_name)

	if object_is_in_trigger(M22_triggers.statue_explosion_region, mover_name) then
		-- Bomb blew up on the statue.
		character_kill(LOCAL_PLAYER)
		
		if in_coop then
			character_kill(REMOTE_PLAYER)
		end
		mission_end_failure("m22", "m22_failure_statue_blown_up")	
		
		for i, mover in pairs(M22_movers.c4) do
			mesh_mover_kill (mover, LOCAL_PLAYER)
		end
	else
		Num_c4_left_to_destroy = Num_c4_left_to_destroy - 1 
		marker_remove(mover_name)

		objective_text( 0, "m22_obj_remove_bombs", Total_c4_to_destroy - Num_c4_left_to_destroy, Total_c4_to_destroy .. " ", SYNC_ALL, OI_ASSET_USE )
	end
end
-- On_mover_destroyed callback used to keep track of the C4 on the first floor
--
-- mover_name:		(string) name of the script mover
-- attacker:		(string) name of the character that destroyed the mover
--
function m22_c41_destroyed_cb(mover_name, attacker)
	on_take_damage("", mover_name)
	on_mover_destroyed("", mover_name)
	on_mover_enter_water("", mover_name)

	if object_is_in_trigger(M22_triggers.statue_explosion_region, mover_name) then
		-- Bomb blew up on the statue.
		character_kill(LOCAL_PLAYER)
		
		if in_coop then
			character_kill(REMOTE_PLAYER)
		end
		mission_end_failure("m22", "m22_failure_statue_blown_up")	
		
		for i, mover in pairs(M22_movers.c4) do
			mesh_mover_kill (mover, LOCAL_PLAYER)
		end
	else
		Num_c4_left_to_destroy = Num_c4_left_to_destroy - 1
		Num_c4_left_first_floor = Num_c4_left_first_floor - 1
		marker_remove(mover_name)

		objective_text( 0, "m22_obj_remove_bombs", Total_c4_to_destroy - Num_c4_left_to_destroy, Total_c4_to_destroy .. " ", SYNC_ALL, OI_ASSET_USE )
	end
end
-- Callback for when a C4 mover is damaged
--
-- mover_name:		(string) name of the script mover
-- attacker:		(string) name of the character that damaged the mover
-- hitpoint_pct:	(float) percent of hitpoints remaining
-- from_exp:		(bool) true if the mover was damaged from an explosion
-- from_melee:		(bool) true if the mover was damaged from melee
-- from_sonic:		(bool) true if the mover was damaged from a sonic gun
--
function m22_c4_damaged_cb(mover_name, attacker, hitpoint_pct, from_exp, from_melee, from_sonic)
	if (from_sonic == false) then
		if (object_is_in_trigger(M22_triggers.statue_explosion_region, mover_name) == false) then
			on_take_damage("", mover_name)			
			thread_yield()
			mesh_mover_kill(mover_name, LOCAL_PLAYER)
		end
	end
end

-- on_mover_enter_water callback used to keep track of the C4
--
-- mover_name:		(string) name of the script mover
--
function m22_c41_entered_water_cb(mover_name)
	Num_c4_left_to_destroy = Num_c4_left_to_destroy - 1
	Num_c4_left_first_floor = Num_c4_left_first_floor - 1
	marker_remove(mover_name)
	
	on_mover_enter_water("", mover_name)
	on_mover_destroyed("", mover_name)
	on_take_damage("", mover_name)
	
	mesh_mover_kill(mover_name, LOCAL_PLAYER)

	objective_text_clear(0)
	objective_text( 0, "m22_obj_remove_bombs", Total_c4_to_destroy - Num_c4_left_to_destroy, Total_c4_to_destroy .. " ", SYNC_ALL, OI_ASSET_USE )
end
-- on_mover_enter_water callback used to keep track of the C4 on the first floor
--
-- mover_name:		(string) name of the script mover
--
function m22_c4_entered_water_cb(mover_name)
	Num_c4_left_to_destroy = Num_c4_left_to_destroy - 1 
	marker_remove(mover_name)
	
	on_mover_enter_water("", mover_name)
	on_mover_destroyed("", mover_name)
	on_take_damage("", mover_name)
	
	mesh_mover_kill(mover_name, LOCAL_PLAYER)

	objective_text_clear(0)
	objective_text( 0, "m22_obj_remove_bombs", Total_c4_to_destroy - Num_c4_left_to_destroy, Total_c4_to_destroy .. " ", SYNC_ALL, OI_ASSET_USE )
end
-- on_trigger_exit callback used to kill humans leaving the statue
function m22_human_left_statue_cb(character_name, trigger_name)
	--if character_name ~= LOCAL_PLAYER and character_name ~= REMOTE_PLAYER then
	if character_name ~= nil then
		character_ragdoll(character_name)
		character_kill(character_name, true)
	end
	--end
end

-- Callback for when the player takes the elevator up the statue
--
-- char_name:		(string) name of the player that triggered the trigger
-- trigger_name:	(string) name of the trigger
--
function m22_player_used_elevator_cb(char_name, trigger_name)
	Player_used_elevator = true
	m22_cleanup_trigger(trigger_name)
end
-- Callback for when the player reaches the breadcrumb
--
-- char_name:		(string) name of the player that triggered the trigger
-- trigger_name:	(string) name of the trigger
--
function m22_player_reached_breadcrumb_cb(char_name, trigger_name)
	Player_reached_breadcrumb = true
	m22_cleanup_trigger(trigger_name)
end
-- Callback for when the player reaches the top of the statue
--
-- char_name:		(string) name of the player that triggered the trigger
-- trigger_name:	(string) name of the trigger
--
function m22_player_reached_top_cb(char_name, trigger_name)
	Player_reached_top = true
	m22_cleanup_trigger(trigger_name)
end

-- Callback for when the player unties a saint
--
-- char_name:		(string) name of the player that triggered the trigger
-- trigger_name:	(string) name of the trigger
--
function m22_saint_untied_cb(char_name, trigger_name)
	m22_cleanup_trigger(trigger_name)

	
	for i, trigger in pairs(M22_triggers.untie) do
		if trigger == trigger_name then
			set_script_animation_state(M22_groups.Statue.saints[i], nil)
			
			action_play_synced(char_name, M22_groups.Statue.saints[i], "Hostage Release")
			turn_vulnerable(M22_groups.Statue.saints[i])
					
			-- Clear their hostage state
			if (character_is_dead(M22_groups.Statue.saints[i]) == false) then
				set_ignore_ai_flag(M22_groups.Statue.saints[i], false)
				set_dont_attack_me_on_sight_flag(M22_groups.Statue.saints[i], false)
				character_allow_ragdoll(M22_groups.Statue.saints[i], ENABLE)
				character_prevent_flinching(M22_groups.Statue.saints[i], DISABLE)
				character_prevent_bumping(M22_groups.Statue.saints[i], DISABLE)
				
				party_add(M22_groups.Statue.saints[i])
			end
			
			break
		end
	end
end

-- Callback called when a tied up saint is killed.  Cleans up trigger and character callbacks.
--
-- char_name:		(string) name of the saint that died
-- attacker_name:	(string) name of the person that killed the saint or nil
--
function m22_saint_died_cb(char_name, attacker_name)
	on_death("", char_name)
	
	for i, saint in pairs(M22_groups.Statue.saints) do
		if saint == char_name then
			m22_cleanup_trigger(M22_triggers.untie[i])
			break
		end
	end
end

-- Callback called when the player runs out of time during the statue sequence.
function m22_statue_times_up_cb()
	-- Bomb blew up on the statue.
	character_kill(LOCAL_PLAYER)
	
	if in_coop then
		character_kill(REMOTE_PLAYER)
	end

	mission_end_failure("m22", "m22_failure_statue_blown_up")	
end

-- Callback for when Kia is damaged
function m22_kia_damaged_cb(victim, attacker, hitpoints, from_explosion, from_melee, causes_vomit)
	-- Only care about the damage if it should cause her to vomit
	if (causes_vomit == true) then
		-- If we're not already processing a vomit, then kick off a new thread
		if (thread_check_done(M22_threads.kia_vomit_handle) == true) then
			M22_threads.kia_vomit_handle = thread_new("m22_kia_process_vomit_thread")
		end
	end
end

-- Callback when the Mayor Burt is damaged
function m22_burt_damaged_cb(victim, attacker, hitpoints, from_explosion, from_melee, causes_vomit)
	if (M22_burt_can_play_damage_line == true) then
		-- Play a situational line
		if (causes_vomit == true) then
			audio_play_persona_line(M22_characters.Mayor, M22_dialog_lines.burt_fiaj[rand_int(1, #M22_dialog_lines.burt_fiaj)])
		else
			audio_play_persona_line(M22_characters.Mayor, M22_dialog_lines.burt_damaged[rand_int(1, #M22_dialog_lines.burt_damaged)])
		end
		
		M22_burt_can_play_damage_line = false
		delay(5.0)
		M22_burt_can_play_damage_line = true
	end
end

-- Callback when Shaundi is killed
function m22_shaundi_killed_cb()
	mission_end_failure("m22", "m22_failure_shaundi_died")	
end

-- Callback for when a player enters a trigger to get Fart in a Jar ammo
--
-- triggerer:		Name of the player that entered the trigger region
-- trigger:			Name of the trigger region that was entered
function m22_give_fart_in_jar_ammo_cb(triggerer, trigger)
	-- Figure out which trigger volume was triggered
	for i, fart_jar_trigger in pairs(M22_triggers.fart_jars) do
		if (fart_jar_trigger == trigger) then
			-- Disable the trigger, and hide the item
			trigger_enable(trigger, false)
			item_hide(M22_groups.Kia_battle_props.fart_jars[i])
			marker_remove_trigger(trigger, SYNC_ALL)
	
			-- Give them a FIAJ
			if (inv_item_get_weapon_upgrades(KIA_TEMPORARY_GRENADE, triggerer) ~= WEAPON_LEVEL4) then
				-- If the player doesn't already have the FIAJ flashbang upgrade then give it to them
				inv_weapon_add_temporary(triggerer, KIA_TEMPORARY_GRENADE, 0, false, false, false, true, WEAPON_LEVEL4)
			else
				-- Otherwise just give them some ammo
				inv_item_add_ammo(triggerer, KIA_TEMPORARY_GRENADE, 1)
			end

			Player_got_fiaj = true
			
			-- Delay until the respawn time has elapsed
			delay(FART_IN_JAR_RESPAWN_TIME)
			
			-- Re-enable the trigger, and show the item
			trigger_enable(trigger, true)
			item_show(M22_groups.Kia_battle_props.fart_jars[i])	
			marker_add_trigger(trigger, MINIMAP_ICON_USE, nil, OI_ASSET_USE, OI_FLAGS_DEFAULT, SYNC_ALL)
			
			break
		end
	end
end
-- Callback for when a battle zone boss dies
--
-- group_name:		Name of the continuous spawn group that was killed
function m22_bz_boss_killed_cb(group_name)
	Current_bz.bosses_killed = Current_bz.bosses_killed + 1
	m22_helper_update_battle_zone_hud()
end

-- Callback for when the player reaches the first floor breadcrumb on the statue
--
-- char_name:		(string) name of the player that triggered the trigger
-- trigger_name:	(string) name of the trigger
function m22_first_floor_cb(char_name, trigger_name)
	m22_cleanup_trigger(trigger_name)

	-- Set up trigger for the second floor
	on_trigger("m22_second_floor_cb", M22_triggers.Second_Floor)
	trigger_enable(M22_triggers.Second_Floor, true)
	marker_add_trigger(M22_triggers.Second_Floor, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)

end
-- Callback for when the player reaches the second floor breadcrumb on the statue
--
-- char_name:		(string) name of the player that triggered the trigger
-- trigger_name:	(string) name of the trigger
function m22_second_floor_cb(char_name, trigger_name)
	Second_floor_reached = true
	m22_cleanup_trigger(trigger_name)

	for i, mover in pairs(M22_movers.c4) do
		if not (mesh_mover_destroyed(mover))then
			marker_add(mover, MINIMAP_ICON_USE, OI_ASSET_USE, OI_FLAGS_DEFAULT, SYNC_ALL)
		end
	end
end


-- *************************
--
-- Thread functions
--
-- *************************

-- Failsafe thread that will re-enable notoriety after a certain amount of
-- time during the "kill some dudes" section of a battle zone.
--
function m22_thread_notoriety_failsafe()
	delay(NOTORIETY_FAILSAFE_TIME)

	local level = 3
	if (Number_of_zones_cleared == 2) then
		level = 4
	end
	
	m22_set_stag_synd_notoriety(level)
	
	notoriety_force_no_spawn("stag", false)
	notoriety_force_no_spawn("luchadores", false)
	
	--notoriety_spawn_group_clear_destination("stag")
	--notoriety_spawn_group_clear_destination("luchadores")
end

function m22_thread_neareast_battlezone_gps()
	while true do
		m22_gps_path_to_nearest_battle()
		delay(1.0)
	end
end

function m22_helper_play_conversation(conversation_table, delay_time)
	if Active_conversation.convo_table ~= nil then
		-- currently playing a conversation, kill it
		audio_conversation_end(Active_conversation.convo_table.handle)
		Active_conversation.convo_table.handle = INVALID_CONVERSATION_HANDLE
		Active_conversation.convo_table = nil
	end

	-- Load the conversation
	if conversation_table.direct  then
		conversation_table.handle = audio_conversation_load_direct(conversation_table.name)
	else
		conversation_table.handle = audio_conversation_load(conversation_table.name)
	end
	
	Active_conversation.convo_table = conversation_table
	
	delay(delay_time)
	
	-- Wait for anything else that was using the failsafe thread handle to finish.
	while M22_threads.audio_failsafe ~= INVALID_THREAD_HANDLE do
		thread_yield()
	end
	
	M22_threads.audio_failsafe = thread_new("delay", 120.0)
	
	conversation_table.played = true
	
	-- Play the conversation and wait for it to end or for the maximum wait time to elapse.
	audio_conversation_play(conversation_table.handle)
	
	while audio_conversation_playing(conversation_table.handle) and thread_check_done(M22_threads.audio_failsafe) == false do
		thread_yield()
	end
	audio_conversation_end(conversation_table.handle)
	
	thread_kill(M22_threads.audio_failsafe)
	M22_threads.audio_failsafe = INVALID_THREAD_HANDLE
	
	conversation_table.handle = INVALID_CONVERSATION_HANDLE
	Active_conversation.convo_table = nil
	M22_threads.convo_handle = INVALID_THREAD_HANDLE
end

-- Thread function responsible for controling Killbanes plane
function m22_airport_killbane_path_thread()
	-- Stop notoriety spawning during the take off sequence.
	notoriety_force_no_spawn("stag", true)
	notoriety_force_no_spawn("luchadores", true)
	
	delay(10)
	vehicle_max_speed(M22_vehicles.Killbanes_Plane, 35)  -- AC: Previously 20 turned it up to 30
	vehicle_pathfind_to(M22_vehicles.Killbanes_Plane, Airport_Killbane_Path1, true, false)
	vehicle_max_speed(M22_vehicles.Killbanes_Plane, 45)
	vehicle_pathfind_to(M22_vehicles.Killbanes_Plane, Airport_Killbane_Path2, true, false)
	vehicle_max_speed(M22_vehicles.Killbanes_Plane, 45)
	vehicle_pathfind_to(M22_vehicles.Killbanes_Plane, Airport_Killbane_Path3, true, false)
	vehicle_max_speed(M22_vehicles.Killbanes_Plane, 30)
	vehicle_pathfind_to(M22_vehicles.Killbanes_Plane, Airport_Killbane_Path4, true, false)
	--vehicle_max_speed(M22_vehicles.Killbanes_Plane, 35)	
	
	
	vehicle_max_speed(M22_vehicles.Killbanes_Plane, 55)
	vehicle_pathfind_to(M22_vehicles.Killbanes_Plane, Airport_Killbane_Path5, true, false)
	--airplane_takeoff(M22_vehicles.Killbanes_Plane)
	mission_end_failure("m22", "m22_failure_killbane_escaped")
end

-- Thread function responsible for controling Angels car
function m22_angel_car_path_thread()
	for i, segment_name in pairs(Airport_player_path) do
		vehicle_pathfind_to(M22_vehicles.Angels_Car, segment_name, true, false)
	end
	mission_end_failure("m22", "m22_failure_killbane_escaped")
end

-- Thread function that will drive to a specific spot, used for roadblocks in the airplane chase sequence
--
-- driver_name:			(string) name of the driver
-- car_name:			(string) name of the car
-- nav_point_name:		(string) name of the destination navpoint
-- thread_index:		(int) index into M22_threads.roadblock_drive_to_handles, to clean up when this thread ends
--
function m22_roadblock_drive_to_thread(driver_name, car_name, nav_point_name, thread_index)
	vehicle_max_speed(car_name, 65) -- AC: Test
	vehicle_pathfind_to(car_name, nav_point_name, true, true)
	vehicle_exit_group( { driver_name } )
	-- Get the drivers to attack the player
	npc_combat_enable(driver_name, true)
	ai_add_enemy_target(driver_name, M22_groups.Angel.members[1], ATTACK_NOW, true)
	
	M22_threads.roadblock_driveto_handles[thread_index] = INVALID_THREAD_HANDLE
end

-- Thread to process one of the attack VTOLs as it circles around the statue
--
-- vtol_table:		Lua table defining the VTOL objects
function m22_process_kia_vtol_circling(vtol_table)
	vehicle_max_speed(vtol_table.vtol, vtol_table.loop_speed)
	helicopter_set_path_orientation(vtol_table.vtol, HELI_PF_PATH_PITCH)
	helicopter_fly_to_direct_dont_stop(vtol_table.vtol, vtol_table.loop_speed, vtol_table.path_intro)
	
	while(vehicle_is_destroyed(vtol_table.vtol) == false) do
		-- MLG: This would have been nice, but the minimum follow distance is 20m, which is way to far to keep these VTOLs in formation
		--[[
		-- Find a potential follow target
		local follow_target = nil
		for i, vtol in pairs(M22_groups.Kia_Vtol1.vtols) do
			if (vtol == vtol_table) then
				-- We didn't find any VTOLs in front of us in the list, so break without a VTOL follow target
				break
			elseif (thread_check_done(vtol.thread_id) == false) then
				-- The VTOL still has a looping thread, so it hasn't broken off yet.  Follow this guy
				follow_target = vtol.vtol
				break
			end
		end
		--]]
	
	--[[
		if (follow_target ~= nil) then
			helicopter_fly_to_follow_dont_stop(vtol_table.vtol, 150.0, follow_target, vtol_table.path_looping, 20.0, false)
		else
		--]]
			helicopter_fly_to_direct_dont_stop(vtol_table.vtol, vtol_table.loop_speed, vtol_table.path_looping)
			--[[
		end
		--]]
		thread_yield()
	end
end

-- Thread to process the attack VTOLs that circle the status and attack the player during the Kia Boss Battle
function m22_process_kia_vtols_thread()
	-- Loop forever
	while (true) do
		-- Create the script group for the VTOLs
		group_create_hidden(M22_groups.Kia_Vtol1.name, true)
		group_show(M22_groups.Kia_Vtol1.name)
		
		-- Setup each VTOL in the group, and set them on the intor paths
		for i, vtol in pairs(M22_groups.Kia_Vtol1.vtols) do
			vehicle_enter_group_teleport(vtol.members, vtol.vtol)
			vehicle_suppress_npc_exit(vtol.vtol)
			vtol.thread_id = thread_new("m22_process_kia_vtol_circling", vtol)
		end
		
		-- Start a loop to break one VTOL off at a time and attack the player
		while(true) do
			-- Find the first VTOL that is still alive (search this last backwards, since we want to break of the following plane's first)
			local attack_vtol_table = nil
			for i=(#M22_groups.Kia_Vtol1.vtols), 1, -1 do
				if (vehicle_is_destroyed(M22_groups.Kia_Vtol1.vtols[i].vtol) == false) then
					attack_vtol_table = M22_groups.Kia_Vtol1.vtols[i]
					break
				end
			end
			
			-- If we didn't find an attack VTOL, they must all have died, break out of this loop so we can create another wave
			if (attack_vtol_table == nil) then
				break
			end
			
			-- Kill the circling path thread
			thread_kill(attack_vtol_table.thread_id)
			
			-- Wait until the attack VTOL has finished the current loop it's on
			while(vehicle_pathfind_check_done(attack_vtol_table.vtol) == 0) do
				thread_yield()
			end
			
			-- Fly the break-off path
			helicopter_fly_to_direct(attack_vtol_table.vtol, -1, M22_groups.Kia_Vtol1.path_break_off)
			
			-- Process this VTOL attacking until it dies
			Kia_boss_ai.attack_vtol_side = "east"
			local attack_navs = M22_navpoints.kia_vtol_east_attack
			while(vehicle_is_destroyed(attack_vtol_table.vtol) == false) do
				-- Move the VTOL to the idle attack position, and wait
				helicopter_set_path_orientation(attack_vtol_table.vtol, HELI_PF_FACE_TARGET, LOCAL_PLAYER)
				helicopter_fly_to_direct(attack_vtol_table.vtol, -1, attack_navs[1])				
				delay(KIA_ATTACK_VTOL_IDLE_TIME)
				
				-- Start the attack, and move down to the attack navpoint
				Kia_boss_ai.attack_vtol_attacking = true
				delay(1.0) -- sneak a little delay in here, so Kia has time to get into cover
				helicopter_fly_to_direct(attack_vtol_table.vtol, -1, attack_navs[2])
				
				-- Fire on the player
				set_ignore_ai_flag(attack_vtol_table.members[1], true) -- ignore AI so we don't fire while at the idle location
				delay(KIA_ATTACK_VTOL_PRE_ATTACK_TIME)
				set_ignore_ai_flag(attack_vtol_table.members[1], false) -- turn AI back on
				helicopter_shoot_human(attack_vtol_table.vtol, LOCAL_PLAYER)
				delay(KIA_ATTACK_VTOL_POST_ATTACK_TIME)
				
				-- Stop attacking
				Kia_boss_ai.attack_vtol_attacking = false
				
				-- Select a random side to attack from next
				local prev_attack_side = Kia_boss_ai.attack_vtol_side
				if (rand_int(1, 2) == 1) then
					Kia_boss_ai.attack_vtol_side = "east"
					attack_navs = M22_navpoints.kia_vtol_east_attack
				else
					Kia_boss_ai.attack_vtol_side = "west"
					attack_navs = M22_navpoints.kia_vtol_west_attack
				end
				
				-- Check if we're switching sides
				if (Kia_boss_ai.attack_vtol_side ~= prev_attack_side) then
					-- Switching sides, so do a transition pathfind depending on which side we're going to
					helicopter_set_path_orientation(attack_vtol_table.vtol, HELI_PF_PATH_PITCH)
					if (Kia_boss_ai.attack_vtol_side == "east") then
						helicopter_fly_to_direct(attack_vtol_table.vtol, -1, M22_groups.Kia_Vtol1.path_west_east)
					else
						helicopter_fly_to_direct(attack_vtol_table.vtol, -1, M22_groups.Kia_Vtol1.path_east_west)
					end
				end
			end
		end
		
		-- Release the now dead group to the world and destroy the group, so we can recreate them
		release_to_world(M22_groups.Kia_Vtol1.name)
		group_destroy(M22_groups.Kia_Vtol1.name)
		
		delay(KIA_ATTACK_VTOL_RESAPWN_TIME)
	end
end

-- Thread to process Kia's AI during the boss battle
function m22_kia_boss_ai_thread()
	-- Make Kia grab Shaundi
	character_take_human_shield(M22_characters.Kia, M22_characters.Shaundi, true) -- bypass AI to take the human shield immediately
	
	npc_leash_remove(M22_characters.Kia)
	
	-- Register both players as enemy targets
	ai_add_enemy_target(M22_characters.Kia, LOCAL_PLAYER, ATTACK_NOW_NEVER_LOSE)
	if (coop_is_active() == true) then
		ai_add_enemy_target(M22_characters.Kia, REMOTE_PLAYER, ATTACK_NOW_NEVER_LOSE)
	end
	
	-- Do per-frame AI processing until Kia has died
	while(character_is_dead(M22_characters.Kia) == false) do
		-- Evaluate if Kia should move to a new position
		m22_kia_boss_ai_evaluate_move()
		
		thread_yield()
	end
end

function m22_kia_boss_ai_evaluate_move()
	-- Don't process move to AI if Kia is vomiting
	if (thread_check_done(M22_threads.kia_vomit_handle) == false) then
		return
	end
	
	-- Don't process move to AI if Kia doesn't have Shaundi as a human shield
	if (character_has_human_shield(M22_characters.Kia) == false) then
		return
	end
	
	if (Kia_boss_ai.attack_vtol_attacking == true) then
		-- Attack VTOL is about to attack, take cover
		m22_kia_do_take_cover_from_vtol()
	else
		-- No immediate thread, so just try and keep away from the player(s)
		m22_kia_do_move_away_from_player()
	end
end

-- Per frame processing for Kia to try and take cover from an attack VTOL
function m22_kia_do_take_cover_from_vtol()
	-- Figure out which group of cover nodes to search through, based on which side the VTOL is attacking from
	local search_navs = nil
	if (Kia_boss_ai.attack_vtol_side == "east") then
		-- VTOL is attacking from the east, so look for cover on the west
		search_navs = M22_navpoints.kia_defence_west_navs
	else
		-- VTOL is attacking from the west, so look for cover on the east
		search_navs = M22_navpoints.kia_defence_east_navs
	end
	
	-- Find the closest cover navpoint
	local closest_nav_dist = 100000 -- big number
	local closest_nav = nil
	for i, nav in pairs(search_navs) do
		local distance = get_dist(nav, M22_characters.Kia)
		if (distance < closest_nav_dist) then
			-- We have a new closest navpoint
			closest_nav = nav
			closest_nav_dist = distance
		end
	end
	
	-- If this navpoint is different than Kia's current navpoint, then move there
	if (closest_nav ~= Kia_boss_ai.current_navpoint) then
		npc_leash_remove(M22_characters.Kia)
		npc_leash_to_object(M22_characters.Kia, closest_nav, KIA_DEFENSIVE_POSITION_LEASH_RADIUS)
		
		Kia_boss_ai.current_navpoint = closest_nav
	end
end

-- Per frame processing for Kia to try and maintain a safe distance from the player
function m22_kia_do_move_away_from_player()
	local dist_to_player, closest_player = get_dist_closest_player_to_object(M22_characters.Kia)
	if (dist_to_player <= KIA_DESIRED_PLAYER_KEEP_DISTANCE) then
		-- We're too close to a player, see if we should consider a new attack position
		
		-- First, check to see if our destination position is too close to a player
		if (Kia_boss_ai.current_navpoint ~= nil) then
			local dest_dist_to_player, dest_closest_player = get_dist_closest_player_to_object(Kia_boss_ai.current_navpoint)
			if (dest_dist_to_player >= KIA_DESIRED_PLAYER_KEEP_DISTANCE) then
				-- Our current destination is far enough away, just stay the course
				return
			end
		end
		
		-- See if any of the other navpoints are a better pick
		local best_nav = nil
		local closest_nav_dist = 100000 -- big number
		local furthest_from_player_dist = 0
		local furthest_from_player_nav = nil
		for i, nav in pairs(M22_navpoints.kia_attack_navs) do
			local nav_dist_to_player = get_dist_closest_player_to_object(nav)
			local dist_to_nav = get_dist(M22_characters.Kia, nav)
			
			if (nav_dist_to_player > KIA_DESIRED_PLAYER_KEEP_DISTANCE) then
				-- If the nav is outside of the desired keep distance, compare how close it is to other navs outside of the keep distance
				if (dist_to_nav < closest_nav_dist) then
					best_nav = nav
					closest_nav_dist = dist_to_nav
				end
			else
				-- Track the furthest navpoint away from the player that falls within the keep distance
				if (nav_dist_to_player > furthest_from_player_dist) then
					furthest_from_player_nav = nav
					furthest_from_player_dist = nav_dist_to_player
				end
			end
		end
		
		-- If there was no suitable navpoint outside of the keep radius, then check if we should consider the furthest navpoint inside the keep radius
		if (best_nav == nil and furthest_from_player_nav ~= nil) then
			-- Is this at least 10% further away from the closest player?
			if (furthest_from_player_dist > (dist_to_player * 1.1)) then
				best_nav = furthest_from_player_nav
			end
		end
		
		-- If there's a better navpoint, then move there
		if (best_nav ~= nil) then
			npc_leash_remove(M22_characters.Kia)
			npc_leash_to_object(M22_characters.Kia, best_nav, KIA_ATTACK_POSITION_LEASH_RADIUS)
			
			Kia_boss_ai.current_navpoint = best_nav
		end
	end
end

-- Thread to process character's custom FIAJ reaction for Mission22
--
-- character_name:		Name of the character
-- loop:				TRUE if the FIAJ should loop indefinitely, FALSE if it should play only once
function m22_do_character_fiaj_thread(character_name, loop)
	repeat
		-- Pick a random fiaj reaction
		local fiaj_reaction = M22_anims.fiaj_reactions[rand_int(1, #M22_anims.fiaj_reactions)]

		-- Play the FIAJ reaction animations
		action_play(character_name, fiaj_reaction.intro)
		action_play(character_name, fiaj_reaction.outro)
	until (loop == false)
end

-- Process Kia vomitting
function m22_kia_process_vomit_thread()
	-- Release Shaundi
	--[[
	character_release_human_shield(M22_characters.Kia)
	while(character_has_human_shield(M22_characters.Kia) == true) do
		thread_yield()
	end
	--]]
	
	-- Apply the vomiting damage multiplier to Kia, and disable AI (so she won't attack the player between vomits - it looks bad)
	character_set_damage_multiplier(M22_characters.Kia, KIA_DAMAGE_MULTIPLIER_VOMITING)
	set_ignore_ai_flag(M22_characters.Kia, true)
	set_ignore_ai_flag(M22_characters.Shaundi, true)
	
	action_play_synced(M22_characters.Kia, M22_characters.Shaundi, KIA_FIAJ_REACTION_SYNCED_ANIM)
	
	--[[
	local shaundi_reaction_thread = thread_new("m22_do_character_fiaj_thread", M22_characters.Shaundi, true)
	m22_do_character_fiaj_thread(M22_characters.Kia, false)
	--]]
	
	-- Apply the normal damage multiplyer on Kia, and re-enable AI processing
	character_set_damage_multiplier(M22_characters.Kia, KIA_DAMAGE_MULTIPLIER_HUMAN_SHIELD)
	set_ignore_ai_flag(M22_characters.Kia, false)
	
	--[[
	while character_is_ready(M22_characters.Kia) == false do
		thread_yield()
	end

	-- Grab Shaundi again
	character_take_human_shield(M22_characters.Kia, M22_characters.Shaundi, true)
	
	while(character_has_human_shield(M22_characters.Kia) == false) do
		thread_yield()
	end
	--]]
	
	set_ignore_ai_flag(M22_characters.Shaundi, false)
	
	--thread_kill(shaundi_reaction_thread)
	
	-- Continue moving to the destination navpoint, if there is one
	if (Kia_boss_ai.current_navpoint ~= nil) then
		npc_leash_remove(M22_characters.Kia)
		npc_leash_to_object(M22_characters.Kia, Kia_boss_ai.current_navpoint, KIA_ATTACK_POSITION_LEASH_RADIUS)
	end
end

-- Thread function that spawns continuous heli reinforcements during the Kia boss battle 
function m22_kia_coop_reinforcements_thread()
	while true do
		group_create(M22_groups.vtol_coop_reinforcement)
		m22_setup_stag_transport(M22_groups.vtol_coop_reinforcement)
		helicopter_fly_to_direct(M22_groups.vtol_coop_reinforcement.vtol, -1, M22_groups.vtol_coop_reinforcement.drop_offs.path)
		
		-- Tell the soldiers to exit the transport VTOL
		for i, soldier in pairs(M22_groups.vtol_coop_reinforcement.drop_offs.soldiers) do
			teleport(soldier, "nav_vtol_dropoff_coop", true)
		end
		
		delay(1)
		helicopter_fly_to_direct(M22_groups.vtol_coop_reinforcement.vtol, -1, "nav_vtol_dropoff_flee_coop")
		helicopter_enter_retreat(M22_groups.vtol_coop_reinforcement.vtol)
		release_to_world(M22_groups.vtol_coop_reinforcement.name)
		delay(KIA_COOP_REINFORCEMENTS_TIME)
	end
end

-- Thread function that maintains a certain speed on the player's vehicle based on it's distance from Killbane's plane
function m22_manage_players_car_speed_thread()
	local distance_from_killbane
	while true do
		distance_from_killbane = get_dist(M22_vehicles.Angels_Car, M22_vehicles.Killbanes_Plane)
		
		if distance_from_killbane < 30 then
			vehicle_max_speed(M22_vehicles.Angels_Car, 35)
		else 
			if distance_from_killbane < 100 then
				vehicle_max_speed(M22_vehicles.Angels_Car, 75)
			else
				vehicle_max_speed(M22_vehicles.Angels_Car, 100)
			end
		end
		
		delay(3)
	end
end

-- Function to process when to trigger a driving conversation between battlezones
function m22_thread_process_drive_convo(convo_table)
	if (Number_of_zones_cleared > 1) then
		-- Wait until the player gets into a car
		while(character_is_in_vehicle(LOCAL_PLAYER) == false) do
			thread_yield()
		end
	
		audio_play_persona_line(M22_characters.Pierce, M22_dialog_lines.pierce_leave_oleg[Number_of_zones_cleared])
	end

	-- If the driving convo has already played, then just return
	if (M22_conversations.drive_convos[Number_of_zones_cleared + 1].played == true) then
		return
	end

	delay(10)
	while(thread_check_done(M22_threads.convo_handle) == false or character_is_in_vehicle(LOCAL_PLAYER) == false) do
		thread_yield()
	end
	
	M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.drive_convos[Number_of_zones_cleared + 1], 0.0)
end
