./m24.lua

  1. --[[ 
  2. 	m24.lua 
  3. 	SR3 Mission Script 
  4. 	DATE: 09/02/10 
  5. 	AUTHOR:	John Karczewski 
  6. ]]-- 
  7.  
  8.  
  9. -- Debug flags -- 
  10.  
  11. -- Tweakable Parameters -- 
  12.  
  13. 	NUM_TERMINALS_SINGLE = 3 
  14. 	NUM_TERMINALS_COOP = 3 -- Coop uses the full 5 
  15.  
  16. 	MINIMUM_DISTANCE_FROM_DOOR = 23  
  17. 	TIME_TO_GET_AWAY_FROM_DOOR_MS = 10000 -- milliseconds 
  18.  
  19. 	MAGMA_CRYSTAL_RESPAWN_TIME = 60 -- seconds 
  20. 	LAIR_NPC_RESPAWN_TIME = 10.0 -- seconds 
  21. 	 
  22. 	-- Marsquakes 
  23. 	M24_MARSQUAKE_SHAKE = "m24_marsquake" 
  24. 	M24_MIN_MQ_INTERVAL = 10  -- Minimum time between marsquakes 
  25. 	M24_MAX_MQ_INTERVAL = 25 -- Max time between marsquakes 
  26. 	M24_MIN_MQ_INTENSITY = 0.2  
  27. 	M24_MAX_MQ_INTENSITY = 6.0 
  28. 	 
  29. 	-- Marsquakes 
  30. 	M24_MIN_BIG_MQ_INTERVAL = 5  -- Minimum time between marsquakes 
  31. 	M24_MAX_BIG_MQ_INTERVAL = 8 -- Max time between marsquakes 
  32. 	M24_MIN_BIG_MQ_INTENSITY = 0.2  
  33. 	M24_MAX_BIG_MQ_INTENSITY = 6.0 
  34.  
  35. 	-- Homie "death" nOOOOO! 
  36. 	M24_HOMIE_DEATH_ANIM_DIST = 4.0 
  37. 	M24_HOMIE_DEATH_PLAYER_ANIM = "m24 dramatic no" 
  38. 	M24_HOMIE_DEATH_DELAY = 2.0 
  39. 	M24_HOMIE_DEATH_ANIM_DELAY = 3.0 
  40. 	 
  41. 	M24_GAT_CHATTER_MIN_DELAY = 10.0 
  42. 	M24_GAT_CHATTER_MAX_DELAY = 20.0 
  43. 	M24_GAT_CHATTER_INITIAL_DELAY = 25.0 
  44. 	 
  45. 	M24_deaths = { 
  46. 		{ 
  47. 			pos = "Homie_Wounded_Nav_01", 
  48. 		}, 
  49. 		 
  50. 		{ 
  51. 			pos = "Homie_Wounded_Nav_02", 
  52. 		}, 
  53. 		 
  54. 		{ 
  55. 			pos = "Homie_Wounded_Nav_03", 
  56. 		}, 
  57. 	} 
  58.  
  59. -- Groups -- 
  60.  
  61. 	M24_groups = { 
  62. 	 
  63. 		homies = { 
  64. 			name = "Group_Homies", 
  65. 			members = { "Homie_Pierce", "Homie_Shaundi", "Homie_Gat" }, 
  66. 			spawned = false, 
  67. 			 
  68. 			gat = "Homie_Gat", 
  69. 			pierce = "Homie_Pierce", 
  70. 			shaundi = "Homie_Shaundi", 
  71. 		}, 
  72. 		 
  73. 		luchadores = { 
  74. 			name = "Group_Forcefield_01", 
  75. 			-- two member lists for chatter 
  76. 			members_luchadore = { "Lucha_NPC 002", "Lucha_NPC 015", "Lucha_NPC 016", "Lucha_NPC 017", "Lucha_NPC 025", "Lucha_NPC 026", "Lucha_NPC 024", "Lucha_NPC 027", "Lucha_NPC 028",  }, 
  77. 			members_saints = { "Saint_NPC 002", "Saint_NPC 005", "Saint_NPC 006", "Saint_NPC 004"  }, 
  78. 			spawned = false, 
  79. 		}, 
  80. 		 
  81. 		-- groups spawned after each terminal 
  82. 		terminal = { 
  83. 			{ 
  84. 				name = "Group_Forcefield_02", 
  85. 				members = { "Lucha_NPC 001", "Lucha_NPC 005", "Lucha_NPC 006", "Lucha_NPC 018", "Lucha_NPC 019", "Lucha_NPC 020", "Lucha_NPC 021", "Lucha_NPC 022", "Lucha_NPC 019<001>", "Lucha_NPC 019<002>", "Lucha_NPC 019<003>", "Lucha_NPC 019<004>", "Lucha_NPC 001<001>",  
  86. 				"Lucha_NPC 007<001>", "Lucha_NPC 007<002>", "Lucha_NPC 007<003>", "Lucha_NPC 007<004>", "Lucha_NPC 007<005>", "Lucha_NPC 007<006>", "Lucha_NPC 007<007>", "Lucha_NPC 007<008>", "Lucha_NPC 007<009>", "Lucha_NPC 007<010>", "Lucha_NPC 006<001>", "Lucha_NPC 006<002>", "Lucha_NPC 001<004>",  
  87. 				"Lucha_NPC 001<005>", "Lucha_NPC 001<006>", "Lucha_NPC 001<007>", "Lucha_NPC 022<002>", }, 
  88. 				spawned = false, 
  89. 			}, 
  90. 			 
  91. 			{ 
  92. 				name = "Group_Forcefield_03", 
  93. 				members = { "Lucha_NPC 004", "Lucha_NPC 023<001>", "Lucha_NPC 023<002>", "Lucha_NPC 023<003>", "Lucha_NPC 023<004>", "Lucha_NPC 023<005>", "Lucha_NPC 023<007>", "Lucha_NPC 023<008>", "Lucha_NPC 023<010>", "Lucha_NPC 023<011>", "Lucha_NPC 023<012>", "Lucha_NPC 004<001>", "Lucha_NPC 023<013>",  }, 
  94. 				spawned = false, 
  95. 			}, 
  96. 			 
  97. 			{ 
  98. 				name = "Group_Gate", 
  99. 				members = { "Lucha_NPC 010", "Lucha_NPC 011", "Lucha_NPC 012", "Lucha_NPC 013", "Lucha_NPC 014", "Lucha_NPC 009<002>", "Lucha_NPC 009<003>", "Lucha_NPC 009<004>", "Lucha_NPC 009<005>", "Lucha_NPC 011<001>", "Lucha_NPC 012<001>",  }, 
  100. 				spawned = false, 
  101. 			}, 
  102. 		}, 
  103. 		 
  104. 		saints = { 
  105. 			name = "Group_Saints", 
  106. 			members = { "Saint_NPC 001", "Saint_NPC 002", "Saint_NPC 003", "Saint_NPC 004", "Saint_NPC 005",  
  107. 						"Saint_NPC 006", "Saint_NPC 007", "Saint_NPC 008"}, 
  108. 			spawned = false, 
  109. 		}, 
  110. 		 
  111. 		bridge = { 
  112. 			name = "Group_Bridge", 
  113. 			members = { "Mars_Bridge_NPC 001", "Mars_Bridge_NPC 002", "Mars_Bridge_NPC 003", "Mars_Bridge_NPC 004", "Mars_Bridge_NPC 005", 
  114. 						"Mars_Bridge_NPC 006", "Mars_Bridge_NPC 007", "Mars_Bridge_NPC 008", "Mars_Bridge_NPC 009", "Mars_Bridge_NPC 010", 
  115. 						"Mars_Bridge_NPC 011", "Mars_Bridge_NPC 012", "Mars_Bridge_NPC 013", "Mars_Bridge_NPC 014", "Mars_Bridge_NPC 015", 
  116. 						"Mars_Bridge_NPC 016", "Mars_Bridge_NPC 017", "Mars_Bridge_NPC 018", "Mars_Bridge_NPC 019", "Mars_Bridge_NPC 020" }, 
  117. 			spawned = false, 
  118. 		}, 
  119. 	 
  120. 		killbane = { 
  121. 			name = "Group_Killbane", 
  122. 			members = { "Killbane" }, 
  123. 			spawned = false, 
  124. 			killbane = "Killbane", 
  125. 		}, 
  126. 		cte_npcs = { 
  127. 			name = "Group_CTE_NPC", 
  128. 		}, 
  129. 		 
  130. 		cte_killbane = { 
  131. 			name = "Group_CTE_Killbane", 
  132. 		}, 
  133. 	} 
  134.  
  135. -- Navpoints -- 
  136. 	M24_navpoints = { 
  137. 		local_start = "Local_Player_Start", 
  138. 		remote_start = "Remote_Player_Start", 
  139. 		local_exit = "M24_Local_Player_Exit", 
  140. 		remote_exit = "M24_Remote_Player_Exit", 
  141. 		bomb_door = "Bomb_Door_Navpoint", 
  142. 		bridge_start = "Bridge_Start_Navpoint", 
  143. 		bridge_start_coop = "Bridge_Start_Navpoint_a", 
  144. 		killbane_fight_start = "Killbane_Fight_Start_Navpoint", 
  145. 		killbane_fight_start_coop = "Killbane_Fight_Start_Navpoint_a", 
  146. 		terminals = {"Terminal_Navpoint_01", "Terminal_Navpoint_02", "Terminal_Navpoint_03"}, 
  147. 		terminals_coop = {"Terminal_Navpoint_01a", "Terminal_Navpoint_02a", "Terminal_Navpoint_03a"}, 
  148. 		homie_start_navs = { 
  149. 			[ "m24_terminal2" ] = { nil, "Nav Shaundi Terminal 1",  "Nav Gat Terminal 1" }, 
  150. 			[ "m24_terminal3" ] = { nil, nil,  "Nav Gat Terminal 2" }, 
  151. 		}, 
  152. 		lava_height = "Lava_Height_Navpoint", 
  153. 		bombs = { 
  154. --			"bomb_nav_01", 
  155. 			"bomb_nav_02", 
  156. 			"bomb_nav_03", 
  157. --			"bomb_nav_04" 
  158. 		}, 
  159. 		 
  160. 		stumbles = { "nav stumble dir <001>", "nav stumble dir <002>", "nav stumble dir <003>", "nav stumble dir <004>" }, 
  161. 	} 
  162. 	 
  163. -- Triggers -- 
  164. 	M24_triggers = { 
  165. 		terminal_triggers = { "Terminal_Trigger 001", "Terminal_Trigger 002", "Terminal_Trigger 003", "Terminal_Trigger 004", "Terminal_Trigger 005" }, 
  166. 		junction_triggers = { 
  167. --			"Junction_Trigger 001", 
  168. 			"Junction_Trigger 002", 
  169. 			"Junction_Trigger 003", 
  170. --			"Junction_Trigger 004", 
  171. 		}, 
  172. 		end_of_bridge = "End_of_bridge_trigger", 
  173. 		lava_death = "Lava_Death_Trigger", 
  174. 		jet_convo = "Trigger_Jet_Wreckage_Convo", 
  175. 		active_breadcrumb = "", 
  176. 	} 
  177. 	 
  178. 	M24_forcefields = { 
  179. 		{ 
  180. 			door = "m24_forcefield_door_01", 
  181. 			emitter = "force_field_0", 
  182. 		}, 
  183. 		{ 
  184. 			door = "m24_forcefield_door_02", 
  185. 			emitter = "force_field_1", 
  186. 		}, 
  187. 		{ 
  188. 			door = "m24_forcefield_door_03", 
  189. 			emitter = "force_field_2", 
  190. 		}, 
  191. 	} 
  192. 	 
  193. 	M24_terminal_breadcrumbs = { 
  194. 		{nil}, 
  195. 		{"breadcrumb_trigger_01", "breadcrumb_trigger_02"}, 
  196. 		{"breadcrumb_trigger_03"}, 
  197. 	} 
  198.  
  199. -- Characters -- 
  200. 	M24_characters = { 
  201. 		killbane = M24_groups.killbane.killbane 
  202. 	} 
  203.  
  204. -- Vehicles -- 
  205. 	M24_vehicles = { 
  206. 		"Mars_Rover_01", 
  207. 		"Mars_Rover_02", 
  208. 		"Mars_Rover_06", 
  209. 		"Mars_Rover_07", 
  210. 		"Mars_Rover_09", 
  211. 		"Mars_Rover_10", 
  212. 		"Mars_Rover_11", 
  213. 	} 
  214.  
  215. -- Mesh Movers -- 
  216.  
  217. 	M24_movers = { 
  218. 		magma_crystals = { "magma_crystal 001", "magma_crystal 002", "magma_crystal 003", "magma_crystal 004",  
  219. 							"magma_crystal 005", "magma_crystal 006", "magma_crystal 007", "magma_crystal 008",  
  220. 							"magma_crystal 009", "magma_crystal 010", "magma_crystal 011", "magma_crystal 012",  
  221. 							"magma_crystal 013", "magma_crystal 014", "magma_crystal 015", "magma_crystal 016",  
  222. 							"magma_crystal 017", "magma_crystal 018", "magma_crystal 019", "magma_crystal 020",  
  223. 							"magma_crystal 021", "magma_crystal 022", "magma_crystal 023", "magma_crystal 024", 
  224. 							"magma_crystal 025", "magma_crystal 026", "magma_crystal 027", "magma_crystal 028", 
  225. 							"magma_crystal 029" } 
  226. 	} 
  227.  
  228. -- Text -- 
  229. 	M24_text = { 
  230. 		failure_death = { 
  231. 			[M24_groups.homies.pierce]			= "m07_failure_pierce_died", 
  232. 			[M24_groups.homies.shaundi]			= "m07_failure_shaundi_died", 
  233. 			[M24_groups.homies.gat]				= "m01_failure_gat_died", 
  234. 		}, 
  235. 	} 
  236.  
  237. -- Threads -- 
  238. 	M24_threads = { 
  239. 		convo_handle = INVALID_THREAD_HANDLE, 
  240. 		mover_respawn_handles = { INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, 
  241. 									INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, 
  242. 									INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, 
  243. 									INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, 
  244. 									INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, 
  245. 									INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, 
  246. 									INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, 
  247. 									INVALID_THREAD_HANDLE }, 
  248. 		marsquake_handle = INVALID_THREAD_HANDLE, 
  249. 		homie_death_thread_handle = INVALID_THREAD_HANDLE, 
  250. 		vehicle_lava_handle = INVALID_THREAD_HANDLE, 
  251. 		gat_chatter_handle = INVALID_THREAD_HANDLE, 
  252. 		breadcrumb_thread = INVALID_THREAD_HANDLE, 
  253. 	} 
  254.  
  255. -- Checkpoints -- 
  256. 	M24_checkpoints = { 
  257. 		start = { 
  258. 			name = MISSION_START_CHECKPOINT 
  259. 		}, 
  260. 		 
  261. 		terminal1 = { 
  262. 			name = "m24_terminal2" 
  263. 		}, 
  264. 		 
  265. 		terminal2 = { 
  266. 			name = "m24_terminal3" 
  267. 		}, 
  268. 		 
  269. 		junction = { 
  270. 			name = "m24_bombs" 
  271. 		}, 
  272. 		 
  273. 		cross_bridge = { 
  274. 			name = "m24_bridge" 
  275. 		}, 
  276. 		 
  277. 		kill_killbane = { 
  278. 			name = "m24_killbane" 
  279. 		} 
  280. 		 
  281. 	} 
  282. 	 
  283. -- Continuous Spawn Groups -- 
  284. 	M24_spawn_groups = { 
  285. 		mars = { 
  286. 			saints = { "Group_CS_Saint 001", "Group_CS_Saint 002", "Group_CS_Saint 003", "Group_CS_Saint 004" }, 
  287. 			luchadores = { "Group_CS_Lucha 001", "Group_CS_Lucha 002", "Group_CS_Lucha 003", "Group_CS_Lucha 004" } 
  288. 		}, 
  289. 		 
  290. 		lair = { "Group_Lair_Reinforcement 001", "Group_Lair_Reinforcement 002", 
  291. 								"Group_Lair_Reinforcement 003", "Group_Lair_Reinforcement 004" } 
  292. 	} 
  293. 	 
  294. -- Spawn Regions -- 
  295. 	M24_spawn_regions = { 
  296. 		mars = { "Script_Spawn_Region 001", "Script_Spawn_Region 002", "Script_Spawn_Region 003", "Script_Spawn_Region 004",  
  297. 							"Script_Spawn_Region 005", "Script_Spawn_Region 006", "Script_Spawn_Region 007", "Script_Spawn_Region 008",  
  298. 							"Script_Spawn_Region 009", "Script_Spawn_Region 010", "Script_Spawn_Region 011" }, 
  299. 		lair = { "Lair_Spawn_Region 001", "Lair_Spawn_Region 002", "Lair_Spawn_Region 003", "Lair_Spawn_Region 004" } 
  300. 	} 
  301. 	 
  302. -- Cutscenes -- 
  303. 	CUTSCENE_MISSION_INTRO				= "22_out2" 
  304. 	CUTSCENE_MISSION_CTE_BRIDGE_SETUP	=	"m24_cte_01" 
  305. 	CUTSCENE_MISSION_CTE_LAIR_SETUP		=	"m24_cte_02" 
  306. 	CUTSCENE_MISSION_OUTRO				=	"24_Out" 
  307.  
  308. -- Conversations -- 
  309. 	M24_conversations = { 
  310. 		mission_start = { 
  311. 			name = "M24_Mission_Start", 
  312. 			handle = INVALID_CONVERSATION_HANDLE, 
  313. 			played = false, 
  314. 			direct = false, 
  315. 		}, 
  316. 	 
  317. 		all_terminals_down = { 
  318. 			name = "M24_All_Terminals_Down", 
  319. 			handle = INVALID_CONVERSATION_HANDLE, 
  320. 			played = false, 
  321. 			direct = false, 
  322. 		}, 
  323. 		 
  324. 		cross_bridge = { 
  325. 			name = "M24_Gate_Down", 
  326. 			handle = INVALID_CONVERSATION_HANDLE, 
  327. 			played = false, 
  328. 			direct = false, 
  329. 		}, 
  330. 		 
  331. 		enter_lair = { 
  332. 			name = "M24_Enter_Lair", 
  333. 			handle = INVALID_CONVERSATION_HANDLE, 
  334. 			played = false, 
  335. 			direct = false, 
  336. 		}, 
  337.  
  338. 		final_battle_begins = { 
  339. 			name = "M24_Final_Battle_Begins", 
  340. 			handle = INVALID_CONVERSATION_HANDLE, 
  341. 			played = false, 
  342. 			direct = false, 
  343. 		}, 
  344. 		 
  345. 		final_battle_1 = { 
  346. 			name = "M24_Killbane_Battle_1", 
  347. 			handle = INVALID_CONVERSATION_HANDLE, 
  348. 			played = false, 
  349. 			direct = false, 
  350. 		}, 
  351. 		 
  352. 		final_battle_2 = { 
  353. 			name = "M24_Killbane_Battle_2", 
  354. 			handle = INVALID_CONVERSATION_HANDLE, 
  355. 			played = false, 
  356. 			direct = false, 
  357. 		}, 
  358. 		 
  359. 		final_battle_3 = { 
  360. 			name = "M24_Final_Battle", 
  361. 			handle = INVALID_CONVERSATION_HANDLE, 
  362. 			played = false, 
  363. 			direct = false, 
  364. 		}, 
  365. 	} 
  366. 	 
  367. 	M24_dialog_lines = { 
  368. 		gat_chatter = { 
  369. 			"M24_Movie_Lines_01", 
  370. 			"M24_Movie_Lines_02", 
  371. 			"M24_Movie_Lines_03", 
  372. 			"M24_Movie_Lines_04", 
  373. 			"M24_Movie_Lines_06", 
  374. 			"M24_Movie_Lines_07", 
  375. 			"M24_Movie_Lines_08", 
  376. 			"M24_Movie_Lines_09", 
  377. 			"M24_Movie_Lines_10", 
  378. 			"M24_Movie_Lines_13", 
  379. 			"M24_Movie_Lines_14", 
  380. 			"M24_Movie_Lines_15", 
  381. 			"M24_Movie_Lines_16", 
  382. 			"M24_Movie_Lines_17", 
  383. 			"M24_Movie_Lines_18", 
  384. 			"M24_Movie_Lines_19", 
  385. 		}, 
  386. 		 
  387. 		gat_death_lines = { 
  388. 			"M24_Movie_Lines_18", 
  389. 			"M24_Movie_Lines_11", 
  390. 			nil, 
  391. 		}, 
  392. 		 
  393. 		homie_death_lines = { 
  394. 			"M24_Pierce_Dies_01", 
  395. 			"M24_Shaundi_Dies_01", 
  396. 			"M24_Movie_Lines_05", 
  397. 		}, 
  398. 		 
  399. 		homie_hurt_lines = {	 
  400. 			"M24_Pierce_Hit", 
  401. 			"M24_Shaundi_Hit", 
  402. 			"M24_Movie_Lines_04", 
  403. 		}, 
  404. 		 
  405. 		terminal_down = { 
  406. 			"M24_First_Terminal_Down", 
  407. 			"M24_Second_Terminal_Down", 
  408. 			nil, 
  409. 		}, 
  410. 		 
  411. 		wrecked_jets = "M24_Crashed_Jets", 
  412. 		escape_blast_area = "M24_Escaping_Blast_Area", 
  413. 	} 
  414. 	 
  415. 	M24_personas = { 
  416. 		kinzie = { 
  417. 			name = "Kinzie", 
  418. 			persona_id = INVALID_PERSONA_HANDLE, 
  419. 		}, 
  420. 	} 
  421.  
  422. 		 
  423. -- Other -- 
  424. 	in_coop = false 
  425. 	 
  426. 	objective_reached = false 
  427. 	door_exploded = false 
  428. 	junctions_remaining = #M24_triggers.junction_triggers 
  429. 	-- Todo: get the extra terminals for co-op working again. 
  430. 	terminals_remaining = NUM_TERMINALS_SINGLE 
  431. 	terminals_completed = 0 
  432. 	 
  433. 	M24_killbane_reacting = false 
  434. 	M24_killbane_dead = false 
  435. 	 
  436. 	M24_PLAYER_PISTOL = "Pistol-Gang" 
  437. 	M24_PLAYER_SHOTGUN = "Shotgun-Gang" 
  438. 	M24_PLAYER_RIFLE = "Rifle-STAG" 
  439. 	M24_PLAYER_SMG = "SMG-Gang" 
  440. 	PLAYER_LOADOUT = { M24_PLAYER_PISTOL, M24_PLAYER_SHOTGUN, M24_PLAYER_SMG } 
  441. 	 
  442. 	M24_active_conversation = { 
  443. 		convo_table = nil 
  444. 	} 
  445. 	 
  446. 	-- Killbane fight parameters 
  447. 	MAGMA_CRYSTAL_PERCENT_DAMAGE = 10 -- will inflict 10% of killbane's health; player/npc dmg will be different 
  448. 	HP_PERCENT_FOR_FIRST_DOWN = 70 
  449. 	HP_PERCENT_FOR_SECOND_DOWN = 40 
  450. 	HP_PERCENT_FOR_FINAL_DOWN = 12 
  451. 	 
  452. 	M24_KILLBANE_EXPLOSION_STUN_TIME_MS = 3000 
  453. 	 
  454. 	M24_status = { 
  455. 		homie_is_dying = { }, 
  456. 	} 
  457. 	 
  458. 	M24_general_chatterers = { } 
  459.  
  460. -- ************************* 
  461. -- 
  462. -- Standard functions 
  463. -- 
  464. -- ************************* 
  465.  
  466. function m24_clear_breadcrumb() 
  467. 	if (M24_triggers.active_breadcrumb ~= "") then 
  468. 		on_trigger("", M24_triggers.active_breadcrumb) 
  469. 		trigger_enable(M24_triggers.active_breadcrumb, false) 
  470. 		marker_remove_trigger(M24_triggers.active_breadcrumb, SYNC_ALL) 
  471. 	end 
  472. 	M24_triggers.active_breadcrumb = "" 
  473. end 
  474.  
  475. function m24_on_breadcrumb_reached()	 
  476. 	m24_clear_breadcrumb() 
  477. end 
  478.  
  479. function m24_set_breadcrumb(trig_name) 
  480. 	m24_clear_breadcrumb() 
  481. 	 
  482. 	trigger_enable(trig_name, true) 
  483. 	marker_add_trigger(trig_name, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL) 
  484. 	on_trigger("m24_on_breadcrumb_reached", trig_name) 
  485. 	 
  486. 	M24_triggers.active_breadcrumb = trig_name 
  487. end 
  488.  
  489. -- This is the primary entry point for the mission, and is responsible for starting up the mission 
  490. -- at the specified checkpoint. 
  491. -- CALLED FROM CODE 
  492. -- 
  493. -- m24_checkpoint:	The checkpoint the mission should begin at 
  494. -- is_restart:					TRUE if the mission is restarting, FALSE otherwise 
  495. -- 
  496. function m24_start(m24_checkpoint, is_restart) 
  497. 	-- Make sure the screen is completly faded out 
  498. 	mission_start_fade_out(0.0) 
  499.  
  500. 	in_coop = coop_is_active() 
  501. 	city_zone_swap( "Mars", true ) 
  502. 	 
  503. 	local terminal_checkpoint = false 
  504. 	if (m24_checkpoint == M24_checkpoints.start.name) then 
  505. 		if (is_restart == false) then 
  506. 			-- First time playing mission 
  507. 			cutscene_play(CUTSCENE_MISSION_INTRO, nil, { M24_navpoints.local_start, M24_navpoints.remote_start } ) 
  508. 		else 
  509. 			teleport_coop( M24_navpoints.local_start, M24_navpoints.remote_start ) 
  510. 		end 
  511. 	end 
  512.  
  513. 	-- Handle mission initialization for the current checkpoint 
  514. 	m24_initialize(m24_checkpoint) 
  515. 	 
  516. 	-- post voice event to mute non-modulated voice 
  517. 	audio_object_post_event("Mission_VO_Override") 
  518.  
  519. 	m24_setup_mission_surface(m24_checkpoint) 
  520. 	 
  521. 	if m24_checkpoint == M24_checkpoints.kill_killbane.name then 
  522. 		m24_cutscene_killbane() 
  523. 	end 
  524. 	 
  525. 	-- Start fading in  
  526. 	mission_start_fade_in() 
  527.  
  528. 	-- Run the mission from the current checkpoint 
  529. 	m24_run(m24_checkpoint) 
  530. 	 
  531. end 
  532.  
  533. -- This is the primary function responsible for running the entire mission from start to finish. 
  534. -- 
  535. -- first_checkpoint:	The first checkpoint to begin running the mission at 
  536. -- 
  537. function m24_run(first_checkpoint) 
  538. 	local current_checkpoint = first_checkpoint 
  539. 	 
  540. 	-- Run the mission from the beginning 
  541. 	if current_checkpoint == M24_checkpoints.start.name then 
  542. 	 
  543. 	character_ragdoll_set_last_resort_position(M24_navpoints.local_start) 
  544. 	 
  545. 		-- All terminals down, play convo. 
  546. 		m24_play_conversation(M24_conversations.mission_start, 1.0) 
  547. 		 
  548. 		m24_hack_terminal(1) 
  549. 		 
  550. 		current_checkpoint = M24_checkpoints.terminal1.name 
  551. 		mission_set_checkpoint(M24_checkpoints.terminal1.name) 
  552. 	end 
  553. 	 
  554. 	-- First terminal complete 
  555. 	if current_checkpoint == M24_checkpoints.terminal1.name then 
  556. 	 
  557. 	character_ragdoll_set_last_resort_position(M24_navpoints.terminals[1]) 
  558. 	 
  559. 		m24_hack_terminal(2) 
  560. 		 
  561. 		current_checkpoint = M24_checkpoints.terminal2.name 
  562. 		mission_set_checkpoint(M24_checkpoints.terminal2.name) 
  563. 	end 
  564. 	 
  565. 	-- Second terminal complete 
  566. 	if current_checkpoint == M24_checkpoints.terminal2.name then 
  567. 	 
  568. 	character_ragdoll_set_last_resort_position(M24_navpoints.terminals[2]) 
  569. 	 
  570. 		m24_hack_terminal(3) 
  571. 		m24_hack_terminal(4) 
  572. 		m24_hack_terminal(5) 
  573. 		 
  574. 		-- Spawn bridge forces 
  575. 		group_create(M24_groups.bridge.name, true) 
  576. 		M24_groups.bridge.spawned = true 
  577. 		 
  578. 		m24_add_chatterers( M24_groups.bridge.members, { "M24_Attack" } ) 
  579. 		 
  580. 		-- All terminals down, play convo. 
  581. 		m24_play_conversation(M24_conversations.all_terminals_down, 1.0) 
  582. 		 
  583. 		current_checkpoint = M24_checkpoints.junction.name 
  584. 		mission_set_checkpoint(M24_checkpoints.junction.name) 
  585. 	end 
  586. 	 
  587. 	-- Third terminal complete 
  588. 	if current_checkpoint == M24_checkpoints.junction.name then 
  589. 	 
  590. 	character_ragdoll_set_last_resort_position(M24_navpoints.terminals[3]) 
  591. 	 
  592. 		m24_remove_forcefields() 
  593. 		m24_process_junction_boxes() 
  594. 		m24_door_blown_cutscene() 
  595. 		 
  596. 		--destroy all the terminal groups.  we won't see them anymore 
  597. 		m24_cleanup_terminal_groups() 
  598. 		 
  599. 		current_checkpoint = M24_checkpoints.cross_bridge.name 
  600. 		mission_set_checkpoint(M24_checkpoints.cross_bridge.name) 
  601. 	end 
  602. 	 
  603. 	if current_checkpoint == M24_checkpoints.cross_bridge.name then 
  604. 	 
  605. 	character_ragdoll_set_last_resort_position(M24_navpoints.bridge_start) 
  606. 	 
  607. 		m24_remove_forcefields() 
  608. 		m24_bridge_sequence() 
  609. 	 
  610. 		current_checkpoint = M24_checkpoints.kill_killbane.name 
  611. 		mission_set_checkpoint(M24_checkpoints.kill_killbane.name)	 
  612.  
  613. 		m24_cutscene_killbane() 
  614. 		fade_in(0.5) 
  615. 		fade_in_block() 
  616. 	end 
  617. 	 
  618. 	if current_checkpoint == M24_checkpoints.kill_killbane.name then 
  619. 	 
  620. 	character_ragdoll_set_last_resort_position(M24_navpoints.killbane_fight_start) 
  621. 		m24_remove_forcefields() 
  622. 		m24_kill_killbane_sequence() 
  623. 	end 
  624. 	 
  625. 	mission_end_success("m24", CUTSCENE_MISSION_OUTRO, {M24_navpoints.local_exit, M24_navpoints.remote_exit} ) 
  626. 	 
  627. end 
  628.  
  629. function m24_cleanup_terminal_groups() 
  630.  
  631. 	if (group_is_loaded(M24_groups.luchadores.name)) then 
  632. 		group_destroy(M24_groups.luchadores.name) 
  633. 		M24_groups.luchadores.spawned = false 
  634. 		m24_remove_chatterers( M24_groups.luchadores.members_saints ) 
  635. 		m24_remove_chatterers( M24_groups.luchadores.members_luchadore ) 
  636. 	end 
  637. 		 
  638. 	-- destroy the terminal groups 
  639. 	for i, group in pairs(M24_groups.terminal) do 
  640. 		if (group_is_loaded(group.name)) then 
  641. 			group_destroy(group.name) 
  642. 			group.spawned = false 
  643. 			m24_remove_chatterers( group.members ) 
  644. 		end 
  645. 	end 
  646. end 
  647.  
  648. function m24_release_terminal_groups() 
  649.  
  650. 	if (group_is_loaded(M24_groups.luchadores.name)) then 
  651. 		release_to_world(M24_groups.luchadores.name) 
  652. 		M24_groups.luchadores.spawned = false 
  653. 		m24_remove_chatterers( M24_groups.luchadores.members_saints ) 
  654. 		m24_remove_chatterers( M24_groups.luchadores.members_luchadore ) 
  655. 	end 
  656.  
  657. 	-- release the terminal groups 
  658. 	for i, group in pairs(M24_groups.terminal) do 
  659. 		if (group_is_loaded(group.name)) then 
  660. 			release_to_world(group.name) 
  661. 			group.spawned = false 
  662. 			m24_remove_chatterers( group.members ) 
  663. 		end 
  664. 	end 
  665. end 
  666.  
  667. -- This is the primary function responsible for cleaning up the entire mission 
  668. -- CALLED FROM CODE (+++MUST RETURN IMMEDIATLY+++) 
  669. -- 
  670. function m24_cleanup() 
  671.  
  672. 	-- stop muting voice 
  673. 	audio_object_post_event("Mission_VO_Override_Stop") 
  674. 	 
  675. 	-- unregister the dismissal callbacks. 
  676. 	if group_is_loaded(M24_groups.homies.name) then 
  677. 		for i, homie in pairs(M24_groups.homies.members) do 
  678. 			on_dismiss("", homie) 
  679. 			on_death("", homie) 
  680. 		end 
  681. 	end 
  682. 	 
  683. 	-- despawn the groups 
  684. 	if group_is_loaded( M24_groups.saints ) then 
  685. 		group_destroy(M24_groups.saints) 
  686. 		M24_groups.saints.spawned = false 
  687. 	end 
  688. 	 
  689. 	if group_is_loaded( M24_groups.luchadores ) then 
  690. 		group_destroy(M24_groups.luchadores) 
  691. 		M24_groups.luchadores.spawned = false 
  692. 	end 
  693. 	 
  694. 	if group_is_loaded( M24_groups.homies ) then 
  695. 		group_destroy(M24_groups.homies) 
  696. 		M24_groups.homies.spawned = false 
  697. 	end 
  698. 	 
  699. 	m24_cleanup_terminal_groups() 
  700. 	 
  701. 	-- Remove costumes 
  702. 	customization_item_revert() 
  703.  
  704. 	hud_timer_set(1, 0, "") 
  705. 	hud_timer_hide(1, true) 
  706. 	hud_timer_stop(1) 
  707. 	objective_text_clear(0) 
  708. 	on_take_damage("", M24_characters.killbane) 
  709. 	 
  710. 	inv_remove_temp_loadout(PLAYER_LOADOUT) 
  711. 	 
  712. 	-- Remove the stag rifle. 
  713. 	inv_weapon_remove_temporary(LOCAL_PLAYER, M24_PLAYER_RIFLE) 
  714. 	inv_weapon_remove_temporary(REMOTE_PLAYER, M24_PLAYER_RIFLE) 
  715. 	 
  716. 	cleanup_groups(M24_groups) 
  717. 	m24_cleanup_conversations() 
  718. 	m24_cleanup_personas() 
  719. 	m24_cleanup_triggers(M24_triggers) 
  720. 	m24_cleanup_threads(M24_threads) 
  721. 	m24_cleanup_movers(M24_movers) 
  722. 	m24_cleanup_continuous_spawn_groups(M24_spawn_groups) 
  723. 	m24_cleanup_continuous_spawn_regions(M24_spawn_regions) 
  724.  
  725. 	boss_battle_mars_killbane_active(DISABLE) 
  726. 	qte_cleanup() 
  727. 	party_allow_max_followers(false) 
  728. 	 
  729. 	inv_weapon_disable_all_slots(false) 
  730. 	 
  731. 	city_zone_swap( "Mars", false ) 
  732. 	 
  733. 	-- Stop using the mission specified ragdoll get up last resort. 
  734. 	character_ragdoll_clear_last_resort_position() 
  735. 	 
  736. 	-- for some reason the player exits the mission wearing a backpack/parachute 
  737. 	-- we'll just put a stop to that right here 
  738. 	player_parachute_wear_backpack( LOCAL_PLAYER, false ) 
  739. 	character_set_never_catch_fire( LOCAL_PLAYER, false ) 
  740. 	 
  741. 	if coop_is_active() then 
  742. 		character_set_never_catch_fire( REMOTE_PLAYER, false ) 
  743. 		player_parachute_wear_backpack( REMOTE_PLAYER, false ) 
  744. 	end 
  745. 	 
  746. 	player_grenades_enable() 
  747. end 
  748. -- Called when the mission has ended with success 
  749. -- CALLED FROM CODE (+++MUST RETURN IMMEDIATLY+++) 
  750. -- 
  751. function m24_success() 
  752. 	--[[ INSERT ANY MISSION SPECIFIC SUCCESS STUFF ]]-- 
  753. 	 
  754. 	--'Win the Game' World State Changes  
  755. 	 
  756. 	local skip_teleport = true 
  757. 	m23_m24_coop_skip(skip_teleport) -- do the stuff we'd do in the skip case 
  758. end 
  759.  
  760.  
  761. -- ************************* 
  762. -- 
  763. -- Local functions 
  764. -- 
  765. -- ************************* 
  766.  
  767. -- Initialize the mission for the specified checkpoint 
  768. -- 
  769. -- checkpoint:		Checkpoint to initialize the mission to 
  770. -- 
  771. function m24_initialize(checkpoint) 
  772. 	-- Dress up players 
  773. 	customization_outfit_wear("Lets Pretend Male A") 
  774.  
  775. 	-- Set the mission author 
  776. 	set_mission_author("Mike Slone") 
  777.  
  778. 	-- Common initialization 
  779. 	m24_initialize_common() 
  780. 		 
  781. 	if checkpoint ~= M24_checkpoints.terminal2 and checkpoint ~= M24_checkpoints.junction then 
  782. 		trigger_enable(M24_triggers.jet_convo, true) 
  783. 		on_trigger("m24_jet_convo_callback", M24_triggers.jet_convo) 
  784. 	end 
  785. 	 
  786. 	m24_checkpoint_teleport(checkpoint, false) 
  787. end 
  788.  
  789. function m24_forcefield_hide(ff) 
  790. 	mesh_mover_hide(ff.door) 
  791. 	audio_ambient_emitter_stop(ff.emitter) 
  792. end 
  793.  
  794. function m24_remove_forcefields() 
  795. 	for i, forcefield in pairs(M24_forcefields) do 
  796. 		m24_forcefield_hide(forcefield) 
  797. 	end 
  798. end 
  799.  
  800. -- Sets up all the npcs, continuous spawns, and homies that are present during the surface portion of the mission 
  801. function m24_setup_mission_surface(checkpoint) 
  802.  
  803. 	-- Spawn ambient homies 
  804. 	if checkpoint == M24_checkpoints.start.name or checkpoint == M24_checkpoints.terminal1.name or checkpoint == M24_checkpoints.terminal2.name then 
  805. 		group_create(M24_groups.homies, true) 
  806. 		M24_groups.homies.spawned = true 
  807. 	end 
  808. 		 
  809. 	local start_nav = "" 
  810. 	 
  811. 	-- Spawn the appropriate homies 
  812. 	local num_homies = 0 
  813. 	 
  814. 	if checkpoint == M24_checkpoints.start.name then 
  815. 		num_homies = 3 
  816. 		 
  817. 		group_create(M24_groups.saints, true) 
  818. 		group_create(M24_groups.luchadores, true) 
  819. 		 
  820. 		m24_add_chatterers( M24_groups.saints.members, { "M24_Mars_Saints", "M24_Lava" } ) 
  821. 		m24_add_chatterers( M24_groups.luchadores.members_saints, { "M24_Mars_Saints", "M24_Lava" } ) 
  822. 		m24_add_chatterers( M24_groups.luchadores.members_luchadore, { "M24_Attack" } ) 
  823. 		 
  824. 		M24_groups.saints.spawned = true 
  825. 		M24_groups.luchadores.spawned = true 
  826. 	end 
  827. 	 
  828. 	if checkpoint == M24_checkpoints.terminal1.name then 
  829. 		num_homies = 2 
  830. 		start_nav = M24_navpoints.terminals[1] 
  831. 		 
  832. 		group_create(M24_groups.terminal[1].name, true) 
  833. 		M24_groups.terminal[1].spawned = true 
  834. 		m24_add_chatterers( M24_groups.terminal[1].members, { "M24_Attack" } ) 
  835. 	end 
  836. 	 
  837. 	if checkpoint == M24_checkpoints.terminal2.name then 
  838. 		num_homies = 1 
  839. 		start_nav = M24_navpoints.terminals[2] 
  840. 		 
  841. 		group_create(M24_groups.terminal[2].name, true) 
  842. 		M24_groups.terminal[2].spawned = true 
  843. 		m24_add_chatterers( M24_groups.terminal[2].members, { "M24_Attack" } ) 
  844. 	end 
  845. 	 
  846. 	if checkpoint == M24_checkpoints.junction.name then 
  847. 		start_nav = M24_navpoints.terminals[3] 
  848. 		 
  849. 		group_create(M24_groups.terminal[3].name, true) 
  850. 		M24_groups.terminal[3].spawned = true 
  851. 		m24_add_chatterers( M24_groups.terminal[3].members, { "M24_Attack" } ) 
  852. 	end 
  853. 	 
  854. 	if (checkpoint == M24_checkpoints.junction.name or checkpoint == M24_checkpoints.cross_bridge.name) then 
  855. 		-- Spawn bridge forces 
  856. 		group_create(M24_groups.bridge.name, true) 
  857. 		M24_groups.bridge.spawned = true 
  858. 		m24_add_chatterers( M24_groups.bridge.members, { "M24_Attack" } ) 
  859. 	end 
  860. 	 
  861. 	-- Either add or kill each of the homies. 
  862. 	if M24_groups.homies.spawned then 
  863. 		for i, homie in pairs(M24_groups.homies.members) do 
  864. 			local local_homie = M24_groups.homies.members[4 - i] 
  865. 			if i <= num_homies then 
  866. 				-- teleport before adding to party 
  867. 				if M24_navpoints.homie_start_navs[ checkpoint ] ~= nil and M24_navpoints.homie_start_navs[ checkpoint ][ 4 - i ] ~= nil then 
  868. 					teleport( local_homie, M24_navpoints.homie_start_navs[ checkpoint ][ 4 - i ] ) 
  869. 				end 
  870. 				thread_yield() 
  871. 				 
  872. 				party_add_ignore_limits(local_homie) 
  873. 				follower_make_independent(local_homie, false) 
  874. 				character_prevent_explosion_fling(local_homie, true) 
  875. 				turn_invulnerable(local_homie) 
  876. 				follower_set_can_abandon(local_homie, true) 
  877. 				on_dismiss("m24_failure_dismissed_cb", local_homie) 
  878. 				on_death("m24_failure_died_cb", local_homie)				 
  879. 			else 
  880. 				-- teleport them to their corresponding trigger and kill them. 
  881. 				teleport(local_homie, M24_deaths[4 - i].pos) 
  882. 				character_kill(local_homie) 
  883. 			end 
  884. 		end 
  885. 		 
  886. 		if num_homies >= 1 then 
  887. 			M24_threads.gat_chatter_handle = thread_new("m24_gat_chatter_thread", 3 - num_homies) 
  888. 		end 
  889. 	end 
  890. 	 
  891. 	local bridge_or_later = (checkpoint == M24_checkpoints.cross_bridge.name) or (checkpoint == M24_checkpoints.kill_killbane.name) 
  892. 	 
  893. 	if not bridge_or_later then 
  894. 	 
  895. 		-- Enable the spawn regions and spawn groups 
  896. 		m24_start_continuous_spawn_groups(M24_spawn_groups.mars) 
  897. 		m24_enable_continuous_spawn_regions(M24_spawn_regions.mars) 
  898. 		 
  899. 		-- Turn off all the radios 
  900. 		for i, vehicle in pairs(M24_vehicles) do 
  901. 			if (vehicle_exists(vehicle)) then 
  902. 				radio_block(vehicle) 
  903. 			end 
  904. 		end 
  905. 	end 
  906. end 
  907.  
  908. -- Sequence where the players must hack terminals before proceeding to the first door 
  909. function m24_hack_terminal(terminal_num) 
  910.  
  911. 	-- Hide all previous terminals 
  912. 	for i, forcefield in pairs(M24_forcefields) do 
  913. 		if i < terminal_num then 
  914. 			m24_forcefield_hide(forcefield) 
  915. 		end 
  916. 	end 
  917. 	 
  918. 	objective_text_clear(0) 
  919. 	objective_text( 0, "M24_OBJ_DISABLE_SECURITY_NETWORK", "", "", SYNC_ALL, OI_ASSET_USE) 
  920. 	 
  921. 	-- Reduce the number of terminals to activate for single player 
  922. 	local terminals_total = NUM_TERMINALS_SINGLE 
  923. 	if in_coop then 
  924. 		terminals_total = NUM_TERMINALS_COOP 
  925. 	end 
  926. 	 
  927. 	-- If we are in single player, we only want to activate a certain number of terminals 
  928. 	if terminal_num <= terminals_total then 
  929. 	 
  930. 		-- wait at each breadcrumb. 
  931. 		for i, breadcrumb in pairs(M24_terminal_breadcrumbs[terminal_num]) do 
  932. 			m24_set_breadcrumb(breadcrumb) 
  933. 			while (M24_triggers.active_breadcrumb ~= "") do 
  934. 				thread_yield() 
  935. 			end 
  936. 		end 
  937. 	 
  938. 		local trigger = M24_triggers.terminal_triggers[terminal_num] 
  939. 		trigger_enable(trigger, true) 
  940. 		on_trigger("m24_terminal_hack_cb", trigger) 
  941. 		marker_add_trigger(trigger, MINIMAP_ICON_USE, INGAME_EFFECT_CHECKPOINT, OI_ASSET_USE, OI_FLAGS_LOCATION, SYNC_ALL) 
  942. 		 
  943. 		-- set up the character who will be killed 
  944. 		if M24_groups.homies.members[terminal_num] ~= nil then 
  945. 			local char_to_kill = M24_groups.homies.members[terminal_num] 
  946. 			M24_threads.homie_death_thread_handle = thread_new("m24_homie_death_thread", char_to_kill) 
  947. 		end 
  948. 		 
  949. 		while terminals_completed < terminal_num do 
  950. 			thread_yield() 
  951. 		end 
  952. 		 
  953. 		-- Hide the forcefield door, kill a homie, say a line, if there is one. 
  954. 		if (M24_forcefields[terminal_num] ~= nil) then 
  955. 			m24_forcefield_hide(M24_forcefields[terminal_num]) 
  956.  
  957. 			-- play forcefield power down event, 3D.  Use emitter as location. 
  958. 			audio_object_post_event("m24_forcefield_pwr_dwn", nil, nil, M24_forcefields[terminal_num].emitter) 
  959. 			 
  960. 				-- TODO:  does this belong?  it might overlap audio from the death thread. 
  961. 			if M24_dialog_lines.terminal_down[terminal_num] ~= nil then 
  962. 				audio_play_persona_line(LOCAL_PLAYER, M24_dialog_lines.terminal_down[terminal_num]) 
  963. 			end 
  964. 		end 
  965. 	end 
  966. 	 
  967. 	local next_group = M24_groups.terminal[terminal_num] 
  968. 	 
  969. 	-- release the previous groups before creating the next one. 
  970. 	m24_release_terminal_groups() 
  971. 	 
  972. 	-- create the next group 
  973. 	if (next_group ~= nil and next_group.name ~= "") then 
  974. 		group_create(next_group.name) 
  975. 		next_group.spawned = true 
  976. 	end 
  977. 	 
  978. 	-- wait for homie death scene to finish 
  979. 	while M24_threads.homie_death_thread_handle ~= INVALID_THREAD_HANDLE do 
  980. 		thread_yield() 
  981. 	end 
  982. end 
  983.  
  984. -- Sequence where the player must goto the 4 junction boxes and plant explosives 
  985. function m24_process_junction_boxes() 
  986. 	 
  987. 	objective_text_clear(0) 
  988. 	objective_text( 0, "m24_obj_goto_killbane_lair", "", "", SYNC_ALL, OI_ASSET_LOCATION ) 
  989.  
  990. 	-- set the breadcrumb and wait till you get there. 
  991. 	m24_set_breadcrumb("breadcrumb_trigger_04") 
  992. 	while (M24_triggers.active_breadcrumb ~= "") do 
  993. 		thread_yield() 
  994. 	end 
  995.  
  996. 	objective_text( 0, "m24_obj_plant_charges", "", "", SYNC_ALL, OI_ASSET_USE ) 
  997. 	 
  998. 	for i, trigger in pairs(M24_triggers.junction_triggers) do 
  999. 		trigger_enable(trigger, true) 
  1000. 		on_trigger("m24_junction_bomb_cb", trigger) 
  1001. 		marker_add_trigger(trigger, MINIMAP_ICON_USE, INGAME_EFFECT_CHECKPOINT, OI_ASSET_USE, OI_FLAGS_LOCATION, SYNC_ALL) 
  1002. 	end 
  1003. 	 
  1004. 	while junctions_remaining > 0 do 
  1005. 		thread_yield() 
  1006. 	end 
  1007. 	 
  1008. 	--message("The player yells to get away from the door!", 3) 
  1009. 	delay(2) 
  1010. 	 
  1011. 	objective_text_clear(0) 
  1012. 	objective_text( 0, "m24_obj_run_for_cover", "", "", SYNC_ALL, OI_ASSET_LOCATION ) 
  1013. 	 
  1014. 	-- The door will explode 
  1015. 	hud_timer_set(1, TIME_TO_GET_AWAY_FROM_DOOR_MS, "m24_door_explosion_cb") 
  1016. 	audio_play_persona_line( LOCAL_PLAYER, M24_dialog_lines.escape_blast_area ) 
  1017. 	 
  1018. 	-- Wait until the door has exploded or the player has gotten out of the blast radius 
  1019. 	local players_are_safe = m24_check_player_distance_to_door() 
  1020. 	while (not door_exploded) and (not players_are_safe) do 
  1021. 		players_are_safe = m24_check_player_distance_to_door() 
  1022. 		thread_yield() 
  1023. 	end 
  1024.  
  1025. 	hud_timer_stop(1) 
  1026.  
  1027. 	-- Clean up all the continuous spawn stuff 
  1028. 	m24_cleanup_continuous_spawn_groups(M24_spawn_groups.mars) 
  1029. 	m24_cleanup_continuous_spawn_regions(M24_spawn_regions.mars) 
  1030. 	 
  1031. 	-- Clean up all of the stuff from this part of the mission 
  1032. 	party_dismiss_all() 
  1033. 	 
  1034. 	if (M24_groups.saints.spawned) then 
  1035. 		group_destroy(M24_groups.saints) 
  1036. 		M24_groups.saints.spawned = false 
  1037. 		m24_remove_chatterers( M24_groups.saints.members ) 
  1038. 	end 
  1039. 	 
  1040. 	if (M24_groups.luchadores.spawned) then 
  1041. 		group_destroy(M24_groups.luchadores) 
  1042. 		M24_groups.luchadores.spawned = false 
  1043. 		m24_remove_chatterers( M24_groups.luchadores.members_saints ) 
  1044. 		m24_remove_chatterers( M24_groups.luchadores.members_luchadore ) 
  1045. 	end 
  1046. 	 
  1047. 	if (M24_groups.homies) then 
  1048. 		group_destroy(M24_groups.homies) 
  1049. 		M24_groups.homies.spawned = false 
  1050. 	end 
  1051. end 
  1052.  
  1053. function m24_door_blown_cutscene() 
  1054.    fade_out(0.5) 
  1055.    fade_out_block() 
  1056.     
  1057. 	cutscene_in() 
  1058. 	group_create(M24_groups.cte_npcs.name, true) 
  1059. 	cutscene_play( CUTSCENE_MISSION_CTE_BRIDGE_SETUP, nil, { M24_navpoints.bridge_start, M24_navpoints.bridge_start_coop } ) 
  1060. 	group_destroy(M24_groups.cte_npcs.name) 
  1061. 	cutscene_out() 
  1062. 	-- message("The door opens allowing the player to access the bridge.",5) 
  1063. 	 
  1064.    fade_in(0.5) 
  1065.    fade_in_block() 
  1066. end 
  1067.  
  1068. -- Bridge sequence leading up to Killbane's lair 
  1069. function m24_bridge_sequence() 
  1070. 	-- big quakes, restart quake thread so it kicks in sooner 
  1071. 	M24_status.big_quakes = true 
  1072. 	thread_kill( M24_threads.marsquake_handle ) 
  1073.  
  1074. 	objective_text_clear(0) 
  1075. 	objective_text( 0, "m24_obj_goto_killbane_lair", "", "", SYNC_ALL, OI_ASSET_LOCATION ) 
  1076. 	marker_add(M24_triggers.end_of_bridge, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION) 
  1077. 	 
  1078. 	trigger_enable(M24_triggers.end_of_bridge, true) 
  1079. 	on_trigger("m24_objective_reached_cb", M24_triggers.end_of_bridge) 
  1080. 	objective_reached = false 
  1081. 	 
  1082. 	M24_groups.bridge.spawned = true 
  1083.  
  1084. 	delay( 3 ) 
  1085.  
  1086. 	M24_threads.marsquake_handle = thread_new("m24_marsquake_thread") 
  1087. 	 
  1088. 	delay( 1 ) 
  1089. 	 
  1090. 	-- Gate down, play convo. 
  1091. 	m24_play_conversation(M24_conversations.cross_bridge, 1.0) 
  1092. 	-- blocks until convo is played 
  1093. 	 
  1094. 	local laugh_1_played = false 
  1095. 	local laugh_2_played = false 
  1096. 	local time_accum = 0 
  1097. 	 
  1098. 	while objective_reached == false do 
  1099. 		if laugh_1_played == false and time_accum > 1 then 
  1100. 			audio_object_post_event( "m24_bridge_laugh_01" ) 
  1101. 			laugh_1_played = true 
  1102. 		elseif laugh_2_played == false and time_accum > 6 then 
  1103. 			audio_object_post_event( "m24_bridge_laugh_02" ) 
  1104. 			laugh_2_played = true 
  1105. 		end 
  1106. 		 
  1107. 		thread_yield() 
  1108. 		time_accum = time_accum + get_frame_time()  
  1109. 	end 
  1110.  
  1111. 	while not objective_reached do 
  1112. 		thread_yield() 
  1113. 	end 
  1114. 	 
  1115. 	if (group_is_loaded(M24_groups.bridge) ) then 
  1116. 		group_destroy(M24_groups.bridge) 
  1117. 		m24_remove_chatterers( M24_groups.bridge.members ) 
  1118. 		M24_groups.bridge.spawned = false 
  1119. 	end 
  1120. 	 
  1121. 	marker_remove(M24_triggers.end_of_bridge) 
  1122. 	 
  1123. 	M24_status.big_quakes = false 
  1124. 	 
  1125. 	-- Warp the players into the lair 
  1126. 	fade_out(0.5) 
  1127. 	fade_out_block() 
  1128. 	m24_checkpoint_teleport(M24_checkpoints.kill_killbane.name, false) 
  1129. end 
  1130.  
  1131. function m24_cutscene_killbane() 
  1132. 	group_create(M24_groups.cte_killbane, true) 
  1133. 	cutscene_play(CUTSCENE_MISSION_CTE_LAIR_SETUP, nil, { M24_navpoints.killbane_fight_start, M24_navpoints.killbane_fight_start_coop}) 
  1134. 	group_destroy(M24_groups.cte_killbane) 
  1135. end 
  1136.  
  1137. -- Boss battle with killbane 
  1138. function m24_kill_killbane_sequence() 
  1139. 	group_create(M24_groups.killbane, true) 
  1140. 	M24_groups.killbane.spawned = true 
  1141. 	turn_invulnerable(M24_characters.killbane) -- Killbane is immune to all damage. Explosions damage him via 'm24_killbane_took_damage_cb' 
  1142. 	character_prevent_flinching( M24_characters.killbane, true ) 
  1143. 	 
  1144. 	character_set_never_catch_fire( LOCAL_PLAYER, true ) 
  1145. 	 
  1146. 	if coop_is_active() then 
  1147. 		character_set_never_catch_fire( REMOTE_PLAYER, true ) 
  1148. 	end 
  1149. 	 
  1150. 	-- Start up continuous spawn of Killbane's thugs 
  1151. 	--m24_enable_continuous_spawn_regions(M24_spawn_regions.lair) 
  1152. 	--m24_start_continuous_spawn_groups(M24_spawn_groups.lair, 0, LAIR_NPC_RESPAWN_TIME) 
  1153. 	 
  1154. 	boss_battle_mars_killbane_active() -- Start the fight 
  1155. 	ai_add_enemy_target(M24_characters.killbane, CLOSEST_PLAYER, ATTACK_ON_SIGHT) 
  1156. 	on_take_damage("m24_killbane_took_damage_cb", M24_characters.killbane) 
  1157. 	 
  1158. 	objective_text_clear(0) 
  1159. 	objective_text( 0, "m24_obj_defeat_killbane", "", "", SYNC_ALL, OI_ASSET_KILL ) 
  1160. 	marker_add(M24_characters.killbane, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL) 
  1161. 	 
  1162. 	-- Set up all magma crystals 
  1163. 	for i, mover in pairs(M24_movers.magma_crystals) do 
  1164. 		on_mover_destroyed("m24_magma_crystal_destroyed_cb", mover) 
  1165. 	end 
  1166. 	 
  1167. 	--m24_play_conversation(  M24_conversations.enter_lair, 0 ) 
  1168. 	 
  1169. 	--delay( 5 ) 
  1170.  
  1171. 	audio_play_persona_line( M24_characters.killbane, "M24_Final_Battle_Begins_01" ) 
  1172. 	 
  1173. 	while M24_killbane_dead == false and character_is_dead( M24_characters.killbane ) == false do 
  1174. 		thread_yield() 
  1175. 	end	 
  1176. end 
  1177.  
  1178.  
  1179. -- *************************************************** 
  1180. -- m24_run Helper Functions 
  1181. -- *************************************************** 
  1182.  
  1183. -- Starts a table of continuous spawn groups 
  1184. -- 
  1185. -- cs_group:		(string) table of spawn groups 
  1186. -- max_spawns:		(int) number of times to spawn the group (0 is infinite) 
  1187. -- respawn_delay:	(float) time between respawns, in seconds 
  1188. function m24_start_continuous_spawn_groups(cs_group, max_spawns, respawn_delay) 
  1189. 	for i, spawn_group in pairs(cs_group) do 
  1190. 		if (type(spawn_group) == "table") then 
  1191. 			m24_start_continuous_spawn_groups(spawn_group, max_spawns, respawn_delay) 
  1192. 		else		 
  1193. 			continuous_spawn_start(spawn_group, max_spawns, respawn_delay) 
  1194. 		end 
  1195. 	end 
  1196. end 
  1197.  
  1198. -- Enables a table of active spawn regions 
  1199. -- 
  1200. -- cs_region:	(string) table of spawn regions 
  1201. function m24_enable_continuous_spawn_regions(cs_region) 
  1202. 	for i, region in pairs(cs_region) do 
  1203. 		if (type(region) == "table") then 
  1204. 			m24_enable_continuous_spawn_region(region) 
  1205. 		else		 
  1206. 			spawn_region_enable(region, ENABLE) 
  1207. 		end 
  1208. 	end 
  1209. end 
  1210.  
  1211. -- Checks if the player(s) are a safe distance from the exploding door 
  1212. -- 
  1213. -- returns:		(bool) true - player(s) is/are outside the blast radius, false - player(s) is/are inside 
  1214. function m24_check_player_distance_to_door() 
  1215. 	local distance_p1 = get_dist(LOCAL_PLAYER, M24_navpoints.bomb_door) 
  1216. 	if distance_p1 < MINIMUM_DISTANCE_FROM_DOOR then 
  1217. 		return false 
  1218. 	end 
  1219. 	 
  1220. 	if in_coop then 
  1221. 		local distance_p2 = get_dist(REMOTE_PLAYER, M24_navpoints.bomb_door) 
  1222. 		if distance_p2 < MINIMUM_DISTANCE_FROM_DOOR then 
  1223. 			return false 
  1224. 		end 
  1225. 	end 
  1226. 	 
  1227. 	return true 
  1228. end 
  1229.  
  1230. -- Loads and plays a conversation 
  1231. -- 
  1232. -- conversation_table:			(table) table containing information about the conversation to played 
  1233. -- delay_time						(int)	time to wait before playing the animation 
  1234. function m24_play_conversation(conversation_table, delay_time) 
  1235. 	if M24_active_conversation.convo_table ~= nil then 
  1236. 		-- currently playing a conversation, kill it 
  1237. 		audio_conversation_end(M24_active_conversation.convo_table.handle) 
  1238. 		M24_active_conversation.convo_table.handle = INVALID_CONVERSATION_HANDLE 
  1239. 		M24_active_conversation.convo_table = nil 
  1240. 	end 
  1241.  
  1242. 	-- Load the conversation 
  1243. 	if conversation_table.direct  then 
  1244. 		conversation_table.handle = audio_conversation_load_direct(conversation_table.name) 
  1245. 	else 
  1246. 		conversation_table.handle = audio_conversation_load(conversation_table.name) 
  1247. 	end 
  1248. 	 
  1249. 	-- Keep track of the active conversation 
  1250. 	M24_active_conversation.convo_table = conversation_table 
  1251. 	 
  1252. 	delay(delay_time) 
  1253. 	 
  1254. 	conversation_table.played = true 
  1255. 	 
  1256. 	-- Play the conversation and wait for it to end 
  1257. 	audio_conversation_play(conversation_table.handle) 
  1258. 	audio_conversation_wait_for_end(conversation_table.handle) 
  1259. 	audio_conversation_end(conversation_table.handle) 
  1260. 	 
  1261. 	conversation_table.handle = INVALID_CONVERSATION_HANDLE 
  1262. 	M24_active_conversation.convo_table = nil 
  1263. 	M24_threads.convo_handle = INVALID_THREAD_HANDLE 
  1264. end 
  1265.  
  1266. -- *************************************************** 
  1267. -- m24_initialize Helper Functions 
  1268. -- *************************************************** 
  1269.  
  1270. -- Handle any common initialization 
  1271. -- 
  1272. function m24_initialize_common() 
  1273. 	inv_add_temp_loadout(PLAYER_LOADOUT) 
  1274.  
  1275. 	-- Add the STAG rifle. 
  1276. 	inv_weapon_add_temporary(LOCAL_PLAYER, M24_PLAYER_RIFLE, 1, true, true, false, true, WEAPON_LEVEL4) 
  1277. 	inv_weapon_add_temporary(REMOTE_PLAYER, M24_PLAYER_RIFLE, 1, true, true, false, true, WEAPON_LEVEL4) 
  1278. 	 
  1279. 	inv_weapon_disable_all_but_this_slot( WEAPON_SLOT_RIFLE, true, SYNC_ALL ) 
  1280. 	 
  1281. 	--set_time_of_day(19, 00) 
  1282. 	 
  1283. 	M24_threads.marsquake_handle = thread_new("m24_marsquake_thread") 
  1284. 	M24_threads.vehicle_lava_handle = thread_new("m24_vehicle_lava_thread") 
  1285. 	 
  1286. 	-- Load 2d personas 
  1287. 	M24_personas.kinzie.persona_id = audio_persona_load_2d(M24_personas.kinzie.name) 
  1288. 	 
  1289. 	-- Set up the kill trigger 
  1290. 	trigger_enable(M24_triggers.lava_death, true) 
  1291. 	trigger_allow_dead_guys(M24_triggers.lava_death, true) 
  1292. 	on_trigger("m24_lava_death_callback", M24_triggers.lava_death) 
  1293. 	 
  1294. 	party_allow_max_followers(true) 
  1295. 	 
  1296. 	M24_threads.general_chatter_thread = thread_new( "m24_general_chatter_thread" ) 
  1297. 	 
  1298. 	-- uncomment to put killbane in downed state every 5 seconds 
  1299. 	--M24_threads.killbane_debug = thread_new( "m24_debug_killbane_damage_thread" ) 
  1300. 	 
  1301. 	for i, forcefield in pairs( M24_forcefields ) do 
  1302. 		mesh_mover_show( forcefield.door ) 
  1303. 		audio_ambient_emitter_start( forcefield.emitter) 
  1304. 	end 
  1305.  
  1306. 	player_grenades_disable() 
  1307.  
  1308. 	mission_set_cancel_warp_location( M24_navpoints.local_exit, M24_navpoints.remote_exit ) 
  1309. end 
  1310.  
  1311. -- Checkpoint specific initialization 
  1312. -- 
  1313. -- checkpoint:		The checkpoint to be initialized 
  1314. function m24_checkpoint_teleport(checkpoint, do_fade) 
  1315.  
  1316. 	local warp_local = "" 
  1317. 	local warp_remote = "" 
  1318. 	local pierce_port, shaundi_port 
  1319. 	 
  1320. 	local terminals_total = NUM_TERMINALS_SINGLE 
  1321. 	if in_coop then 
  1322. 		terminals_total = NUM_TERMINALS_COOP 
  1323. 	end 
  1324. 	 
  1325. 	if (checkpoint == M24_checkpoints.start.name) then 
  1326. 		junctions_remaining = #M24_triggers.junction_triggers 
  1327. 		terminals_completed = 0 
  1328. 	end 
  1329. 	 
  1330. 	if checkpoint == M24_checkpoints.terminal1.name then 
  1331. 		warp_local = M24_navpoints.terminals[1] 
  1332. 		warp_remote = M24_navpoints.terminals_coop[1] 
  1333. 		terminals_completed = 1 
  1334. 		pierce_port = M24_navpoints.pierce_terminal1 
  1335. 		shaundi_port = M24_navpoints.shaundi_terminal1 
  1336. 	end 
  1337. 	 
  1338. 	if checkpoint == M24_checkpoints.terminal2.name then 
  1339. 		warp_local = M24_navpoints.terminals[2] 
  1340. 		warp_remote = M24_navpoints.terminals_coop[2] 
  1341. 		shaundi_port = M24_navpoints.shaundi_terminal2 
  1342. 		terminals_completed = 2 
  1343. 	end 
  1344. 	 
  1345. 	if checkpoint == M24_checkpoints.junction.name then 
  1346. 		warp_local = M24_navpoints.terminals[3] 
  1347. 		warp_remote = M24_navpoints.terminals_coop[3] 
  1348. 		terminals_completed = 3 
  1349. 	end 
  1350. 	 
  1351. 	if checkpoint == M24_checkpoints.cross_bridge.name then	 
  1352. 		warp_local = M24_navpoints.bridge_start 
  1353. 		warp_remote = M24_navpoints.bridge_start_coop 
  1354. 		terminals_completed = terminals_total 
  1355. 	end 
  1356. 	 
  1357. 	if (checkpoint == M24_checkpoints.kill_killbane.name) then 
  1358. 		warp_local = M24_navpoints.killbane_fight_start 
  1359. 		warp_remote = M24_navpoints.killbane_fight_start_coop 
  1360. 		terminals_completed = terminals_total 
  1361. 	end 
  1362. 	 
  1363. 	-- Calculate the number of terminals remaining 
  1364. 	terminals_remaining = terminals_total - terminals_completed 
  1365. 	 
  1366. 	-- If there's a warp to do, do it. 
  1367. 	if not (warp_local == "" and warp_remote == "") then 
  1368. 		if do_fade then 
  1369. 			mission_start_fade_out() 
  1370. 		end 
  1371. 		teleport_coop(warp_local, warp_remote) 
  1372. 		if do_fade then 
  1373. 			mission_start_fade_in() 
  1374. 		end 
  1375. 	end 
  1376. end 
  1377.  
  1378. -- *************************************************** 
  1379. -- Miscellaneous m24 Helper Funcrtions 
  1380. -- *************************************************** 
  1381.  
  1382. -- Cleans up a table of trigger regions by reseting their on_trigger callback and disabling them 
  1383. -- 
  1384. -- trigger_group:		(string) table of trigger names 
  1385. function m24_cleanup_triggers(trigger_group) 
  1386. 	for i, trigger in pairs(trigger_group) do 
  1387. 		if (type(trigger) == "table") then 
  1388. 			m24_cleanup_triggers(trigger) 
  1389. 		elseif trigger ~= "" then 
  1390. 			on_trigger("", trigger) 
  1391. 			trigger_enable(trigger, false) 
  1392. 		end 
  1393. 	end 
  1394. end 
  1395.  
  1396. -- Cleans up a table of thread handles by killing them and resetting their thread handle 
  1397. -- 
  1398. -- thread_group:		(string) table of thread names 
  1399. function m24_cleanup_threads(thread_group) 
  1400. 	for i, thread in pairs(thread_group) do 
  1401. 		if (type(thread) == "table") then 
  1402. 			--recurrrrr 
  1403. 			m24_cleanup_threads(thread) 
  1404. 		else		 
  1405. 			if thread ~= INVALID_THREAD_HANDLE then 
  1406. 				thread_kill(thread) 
  1407. 				thread = INVALID_THREAD_HANDLE 
  1408. 			end 
  1409. 		end 
  1410. 	end 
  1411. end 
  1412.  
  1413. -- Cleans up a table of mover names by resetting their on_mover_destroyed callback and removing any HUD markers 
  1414. -- 
  1415. -- mover_group:		(string) table of mover names 
  1416. function m24_cleanup_movers(mover_group) 
  1417. 	for i, mover in pairs(mover_group) do 
  1418. 		if (type(mover) == "table") then 
  1419. 			m24_cleanup_movers(mover) 
  1420. 		else		 
  1421. 			on_mover_destroyed("", mover) 
  1422. 			marker_remove(mover) 
  1423. 		end 
  1424. 	end 
  1425. end 
  1426.  
  1427. -- Cleans up any active continuous spawn groups 
  1428. -- 
  1429. -- cs_group:	(string) table of spawn groups 
  1430. function m24_cleanup_continuous_spawn_groups(cs_group) 
  1431. 	for i, spawn_group in pairs(cs_group) do 
  1432. 		if (type(spawn_group) == "table") then 
  1433. 			m24_cleanup_continuous_spawn_groups(spawn_group) 
  1434. 		else		 
  1435. 			continuous_spawn_stop(spawn_group, true) 
  1436. 		end 
  1437. 	end 
  1438. end 
  1439.  
  1440. -- Disables any active spawn regions 
  1441. -- 
  1442. -- cs_region:	(string) table of spawn regions 
  1443. function m24_cleanup_continuous_spawn_regions(cs_region) 
  1444. 	for i, region in pairs(cs_region) do 
  1445. 		if (type(region) == "table") then 
  1446. 			m24_cleanup_continuous_spawn_regions(region) 
  1447. 		else		 
  1448. 			spawn_region_enable(region, DISABLE) 
  1449. 		end 
  1450. 	end 
  1451. end 
  1452.  
  1453. -- Stops any active conversation and restores the handle to invalid 
  1454. function m24_cleanup_conversations() 
  1455. 	-- If we have a conversation thread active, kill it 
  1456. 	if M24_threads.convo_handle ~= INVALID_THREAD_HANDLE then 
  1457. 		thread_kill(M24_threads.convo_handle) 
  1458. 		M24_threads.convo_handle = INVALID_CONVERSATION_HANDLE	 
  1459. 	end 
  1460. 	 
  1461. 	if M24_active_conversation.convo_table ~= nil then 
  1462. 		audio_conversation_end(M24_active_conversation.convo_table.handle) 
  1463. 		M24_active_conversation.convo_table.handle = INVALID_CONVERSATION_HANDLE 
  1464. 		M24_active_conversation.convo_table = nil 
  1465. 	end 
  1466. end 
  1467.  
  1468. -- Unloads any 2d personas used in the mission 
  1469. function m24_cleanup_personas() 
  1470. 	for i, persona in pairs(M24_personas) do 
  1471. 		if persona.persona_id ~= INVALID_PERSONA_HANDLE then 
  1472. 				audio_persona_remove_2d(persona.persona_id) 
  1473. 				persona.persona_id = INVALID_PERSONA_HANDLE 
  1474. 		end 
  1475. 	end 
  1476. end 
  1477.  
  1478. -- ************************* 
  1479. -- 
  1480. -- Callback functions 
  1481. -- 
  1482. -- ************************* 
  1483.  
  1484. -- on_trigger callback for the juction area 
  1485. -- 
  1486. -- triggerer_name:			(string) name of the person who stepped into the trigger 
  1487. -- trigger_name:			(string) name of the trigger 
  1488. -- 
  1489. function m24_objective_reached_cb(triggerer_name, trigger_name) 
  1490. 	objective_reached = true 
  1491. 	trigger_enable(trigger_name, false) 
  1492. 	on_trigger("", trigger_name) 
  1493. end 
  1494.  
  1495. function m24_lava_death_callback(char, trig) 
  1496. 	if char == nil then 
  1497. 		return 
  1498. 	end 
  1499. 	 
  1500. 	character_set_never_catch_fire( char, false ) 
  1501. 	turn_vulnerable(char) 
  1502. 	character_ignite(char) 
  1503. 	character_ragdoll(char) 
  1504. 	 
  1505. 	delay(3.0) 
  1506. 	 
  1507. 	-- if this is a homie then fail mission 
  1508. 	for i, homie in pairs(M24_groups.homies.members) do 
  1509. 		if char == homie then 
  1510. 			m24_failure_died_cb( homie ) 
  1511. 			return 
  1512. 		end 
  1513. 	end 
  1514. 	 
  1515. 	character_kill(char) 
  1516. end 
  1517.  
  1518. function m24_jet_convo_callback(char, trig) 
  1519. 	if (char == LOCAL_PLAYER) then 
  1520. 		on_trigger("", M24_triggers.jet_convo) 
  1521. 		audio_play_persona_line(LOCAL_PLAYER, M24_dialog_lines.wrecked_jets) 
  1522. 	end 
  1523. end 
  1524.  
  1525. -- hud_timer_set callback.  Determines if the player is too close to the explosion. 
  1526. -- 
  1527. function m24_door_explosion_cb() 
  1528. 	hud_timer_hide(1, true) 
  1529. 	 
  1530. 	if not m24_check_player_distance_to_door() then 
  1531. 		mission_end_failure("m24", "m24_failure_killed_in_blast") 
  1532. 	end 
  1533. 	 
  1534. 	door_exploded = true 
  1535. end 
  1536.  
  1537. -- on_take_damage callback for killbane.  If he takes explosive damage, it will reduce his hp by MAGMA_CRYSTAL_PERCENT_DAMAGE 
  1538. -- 
  1539. -- killbane:			(string) name of the victim 
  1540. -- attacker:			(string) person that inflicted the damage 
  1541. -- hp_percent:			(int) health 
  1542. -- was_explosion:		(bool) true/false 
  1543. -- was_melee:			(bool) true/false 
  1544. -- 
  1545. function m24_killbane_took_damage_cb(killbane, attacker, hp_percent, was_explosion, was_melee) 
  1546. 	if was_explosion then 
  1547. 		if attacker ~= nil and human_is_downed(M24_characters.killbane)  == false and M24_killbane_reacting == false and qte_human_is_used( M24_characters.killbane ) == false then 
  1548. 			local killbane_max_hp = get_max_hit_points(M24_characters.killbane) 
  1549. 			local killbane_hp = get_current_hit_points(M24_characters.killbane) 
  1550. 			 
  1551. 			-- calculate how much damage a blast does and subtract that from killbane's health 
  1552. 			local damage_amount = (MAGMA_CRYSTAL_PERCENT_DAMAGE/100) * killbane_max_hp 
  1553. 			killbane_hp = killbane_hp - damage_amount 
  1554. 		 
  1555. 			-- set his hit points to that new value 
  1556. 			set_current_hit_points(M24_characters.killbane, killbane_hp) 
  1557. 			 
  1558. 			local new_killbane_percent_hp = (killbane_hp/killbane_max_hp) * 100 
  1559. 			 
  1560. 			-- if Killbane is at one of the set qte health %'s, down him for real 
  1561. 			if (new_killbane_percent_hp == HP_PERCENT_FOR_FIRST_DOWN or 
  1562. 				new_killbane_percent_hp == HP_PERCENT_FOR_SECOND_DOWN or 
  1563. 				new_killbane_percent_hp <= HP_PERCENT_FOR_FINAL_DOWN) then 
  1564. 				 
  1565. 				--character_ignite( M24_characters.killbane ) 
  1566. 				m24_play_lovely_killbane_action( "m24 lava hit" ) 
  1567.  
  1568. 				human_enter_downed(M24_characters.killbane) 
  1569. 				 
  1570. 				delay(0.5) 
  1571. 				 
  1572. 				-- remove the mission kill marker 
  1573. 				marker_remove( M24_characters.killbane ) 
  1574. 				 
  1575. 				-- this will, amoung other things, add a finisher marker 
  1576. 				human_downed_set_mars_kb_interactable(M24_characters.killbane) 
  1577. 			 
  1578. 			-- otherwise, play a "stunned" animation. 
  1579. 			else 
  1580. 				m24_play_lovely_killbane_action( "brute melee flashbang" ) 
  1581.  
  1582. 				-- check to see if the convo has played, and if there's already a convo playing. 
  1583. 				if (M24_active_conversation.convo_table == nil) then 
  1584. 					if (new_killbane_percent_hp > HP_PERCENT_FOR_FIRST_DOWN) then 
  1585. 						if not M24_conversations.final_battle_1.played then 
  1586. 							m24_play_conversation(M24_conversations.final_battle_1, 0.0) 
  1587. 						end 
  1588. 					elseif (new_killbane_percent_hp > HP_PERCENT_FOR_SECOND_DOWN) then 
  1589. 						if not M24_conversations.final_battle_2.played then 
  1590. 							m24_play_conversation(M24_conversations.final_battle_2, 0.0) 
  1591. 						end 
  1592. 					else 
  1593. 						if not M24_conversations.final_battle_3.played then 
  1594. 							m24_play_conversation(M24_conversations.final_battle_3, 0.0) 
  1595. 						end 
  1596. 					end 
  1597. 				end 
  1598. 				 
  1599. 			end 
  1600. 		end 
  1601. 	end 
  1602. end 
  1603.  
  1604. function m24_play_lovely_killbane_action( action ) 
  1605. 	M24_killbane_reacting = true 
  1606. 	 
  1607. 	set_ignore_ai_flag( M24_characters.killbane, true ) 
  1608. 	 
  1609. 	-- wait ? frames to let kb transition out of whatever mode he's in 
  1610. 	thread_yield() 
  1611. 	thread_yield() 
  1612. 	thread_yield() 
  1613. 	thread_yield() 
  1614.  
  1615. 	action_play(M24_characters.killbane, action, action, true, 0.8, true, true) 
  1616. 	 
  1617. 	while not action_play_is_finished(M24_characters.killbane) do 
  1618. 		thread_yield() 
  1619. 	end 
  1620. 	 
  1621. 	set_ignore_ai_flag( M24_characters.killbane, false ) 
  1622.  
  1623. 	M24_killbane_reacting = false 
  1624. end 
  1625.  
  1626. -- on_mover_destroyed callback for the magma crystals.  Spawns a thread for the crystal which will respawn it 
  1627. -- 
  1628. -- mover_name:			(string) name of the mover that was destroyed 
  1629. -- attacker_name:		(string) name of the attacker 
  1630. function m24_magma_crystal_destroyed_cb(mover_name, attacker_name) 
  1631. 	for i, thread in pairs(M24_threads.mover_respawn_handles) do 
  1632. 		if thread == INVALID_THREAD_HANDLE then 
  1633. 			M24_threads.mover_respawn_handles[i] = thread_new("m24_respawn_magma_crystal_thread", mover_name, i) 
  1634. 			break 
  1635. 		end 
  1636. 	end 
  1637. end 
  1638.  
  1639. -- callback for when you abandon a homie 
  1640. -- 
  1641. function m24_failure_dismissed_cb() 
  1642. 	mission_end_failure("m24", "m06_failure_homie_dismissed") 
  1643. end 
  1644.  
  1645. -- Callback for when a homie dies. 
  1646. -- 
  1647. function m24_failure_died_cb(homie_name) 
  1648. 	if M24_status.homie_is_dying[ homie_name ] == true then 
  1649. 		return 
  1650. 	end 
  1651. 	 
  1652. 	mission_end_failure("m24", M24_text.failure_death[homie_name]) 
  1653. end 
  1654.  
  1655. -- Callback for when the player uses the trigger region to hack a terminal 
  1656. -- 
  1657. -- triggerer_name:		(string) name of the player that hacked the terminal 
  1658. -- trigger_name:		(string) name of the trigger that was used 
  1659. -- 
  1660. function m24_terminal_hack_cb(triggerer_name, trigger_name) 
  1661. 	trigger_enable(trigger_name, false) 
  1662. 	on_trigger("", trigger_name) 
  1663. 	marker_remove(trigger_name) 
  1664. 	 
  1665. 	-- play the hacking animation 
  1666. 	local anim_name = "m24 computer hack" 
  1667. 	local force_play = false	 
  1668. 	local percentage = 1.0 
  1669. 	local stand_still = true 
  1670. 	local zero_movement = true 
  1671. 	action_play(triggerer_name, anim_name, anim_name, force_play, percentage, stand_still, zero_movement, M24_navpoints.terminals[terminals_completed+1]) 
  1672. 	 
  1673. 	delay(3.0) 
  1674. 	 
  1675. 	terminals_remaining = terminals_remaining - 1 
  1676. 	terminals_completed = terminals_completed + 1 
  1677. end 
  1678.  
  1679. -- Callback for when the player uses the trigger region to plant a charge on a junction box 
  1680. -- 
  1681. -- triggerer_name:		(string) name of the player that set the charge 
  1682. -- trigger_name:		(string) name of the trigger that was used 
  1683. -- 
  1684. function m24_junction_bomb_cb(triggerer_name, trigger_name) 
  1685. 	trigger_enable(trigger_name, false) 
  1686. 	on_trigger("", trigger_name) 
  1687. 	marker_remove(trigger_name) 
  1688. 	 
  1689. 	local navpoint = nil 
  1690. 	for i, bomb_nav in pairs(M24_navpoints.bombs) do 
  1691. 		if (M24_triggers.junction_triggers[i] == trigger_name) then 
  1692. 			navpoint = bomb_nav 
  1693. 		end 
  1694. 	end 
  1695. 	 
  1696. 	-- Set up the character for the animation. 
  1697. 	character_prevent_explosion_fling(triggerer_name, true) 
  1698. 	character_allow_ragdoll(triggerer_name, false) 
  1699. 	character_prevent_flinching(triggerer_name, true) 
  1700. 	--player_controls_disable(triggerer_name) 
  1701. 	 
  1702. 	local anim_name = "plant explosive enter" 
  1703. 	local force_play = false	 
  1704. 	local percentage = 0.8 
  1705. 	local stand_still = false 
  1706. 	local zero_movement = false 
  1707. 		 
  1708. 	-- start the action 
  1709. 	action_play(triggerer_name, anim_name, anim_name, force_play, percentage, stand_still, zero_movement, navpoint) 
  1710. 	 
  1711. 	-- Set up the middle section of the animation. 
  1712. 	set_animation_state(triggerer_name, "plant explosive idle") 
  1713. 	if character_is_dead(triggerer_name) == false then 
  1714. 		delay(3.0) 
  1715. 	end 
  1716. 	clear_animation_state(triggerer_name) 
  1717. 	 
  1718. 	-- Play the outro animation. 
  1719. 	anim_name = "plant explosive exit" 
  1720. 	action_play(triggerer_name, anim_name, anim_name, force_play, percentage, stand_still, zero_movement, navpoint) 
  1721. 	 
  1722. 	-- Clean up any settings we applied for the animation. 
  1723. 	player_controls_enable(triggerer_name) 
  1724. 	character_prevent_flinching(triggerer_name, false) 
  1725. 	character_allow_ragdoll(triggerer_name, true) 
  1726. 	character_prevent_explosion_fling(triggerer_name, false) 
  1727. 	 
  1728. 	-- one less junction remains. 
  1729. 	junctions_remaining = junctions_remaining - 1 
  1730. end 
  1731.  
  1732. -- ************************* 
  1733. -- 
  1734. -- Thread functions 
  1735. -- 
  1736. -- ************************* 
  1737.  
  1738. -- Thread function that delays and then resets a crystal mover 
  1739. -- 
  1740. -- name:			(string) name of the mover 
  1741. -- thread_index:	(int) index into M24_threads.mover_respawn_handles used to clean up 
  1742. -- 
  1743. function m24_respawn_magma_crystal_thread(name, thread_index) 
  1744. 	delay(MAGMA_CRYSTAL_RESPAWN_TIME) 
  1745. 	mesh_mover_reset(name) 
  1746. 	M24_threads.mover_respawn_handles[thread_index] = INVALID_THREAD_HANDLE 
  1747. end 
  1748.  
  1749. -- Thread function to process Gat's chatter. 
  1750. -- 
  1751. -- num_dead_homies: the number of dead homies at the beginning of this thread 
  1752. -- 
  1753. function m24_gat_chatter_thread(num_dead_homies) 
  1754.  
  1755. 	local pierce_dead = num_dead_homies >= 1 
  1756. 	local shaundi_dead = num_dead_homies >= 2 
  1757. 	 
  1758. 	local pierce_name = M24_groups.homies.pierce 
  1759. 	local shaundi_name = M24_groups.homies.shaundi 
  1760. 	local gat_name = M24_groups.homies.gat 
  1761.  
  1762. 	if num_dead_homies == 0 then 
  1763. 		-- Delay for the first line to allow the first convo to play 
  1764. 		delay(M24_GAT_CHATTER_INITIAL_DELAY) 
  1765. 	else 
  1766. 		-- randomly delay 
  1767. 		delay(rand_float(M24_GAT_CHATTER_MIN_DELAY, M24_GAT_CHATTER_MAX_DELAY)) 
  1768. 	end 
  1769. 	 
  1770. 	local num_lines = #(M24_dialog_lines.gat_chatter) 
  1771.  
  1772. 	while (num_lines ~= 0 and not character_is_dead(gat_name)) do 
  1773. 	 
  1774. 		local line_name = "" 
  1775. 	 
  1776. 		-- Leave room for Shaundi's death line. 
  1777. 		if (not shaundi_dead and character_is_dead(shaundi_name)) then 
  1778. 			shaundi_dead = true 
  1779. 			 
  1780. 		-- Leave room for Pierce's death line. 
  1781. 		elseif (not pierce_dead and character_is_dead(pierce_name)) then 
  1782. 			pierce_dead = true 
  1783. 		 
  1784. 		-- Play any ol line. 
  1785. 		else 
  1786. 			-- choose a random line number 
  1787. 			local line_num = rand_int(1,num_lines) 
  1788. 		 
  1789. 			line_name = M24_dialog_lines.gat_chatter[line_num] 
  1790. 			 
  1791. 			-- remove it from the list 
  1792. 			-- This is super-ghetto because we don't load the standard Lua libraries, and so we don't have tremove or table.remove... 
  1793. 			M24_dialog_lines.gat_chatter[line_num] = M24_dialog_lines.gat_chatter[num_lines] 
  1794. 			M24_dialog_lines.gat_chatter[num_lines] = nil 
  1795. 			num_lines = num_lines - 1 
  1796. 		end 
  1797. 		 
  1798. 		-- don't talk during the death sequence. 
  1799. 		if (M24_threads.homie_death_thread_handle ~= INVALID_THREAD_HANDLE) then 
  1800. 			line_name = "" 
  1801. 		end 
  1802. 		 
  1803. 		if line_name ~= "" then 
  1804. 			-- play that line 
  1805. 			audio_play_persona_line(gat_name, line_name) 
  1806. 		end 
  1807. 		 
  1808. 		-- randomly delay 
  1809. 		delay(rand_float(M24_GAT_CHATTER_MIN_DELAY, M24_GAT_CHATTER_MAX_DELAY)) 
  1810. 	end 
  1811. 	 
  1812. 	M24_threads.gat_chatter_handle = INVALID_THREAD_HANDLE 
  1813. end 
  1814.  
  1815. -- Thread function that plays the "Nooooo!" animation when the player gets near their downed homie. 
  1816. -- 
  1817. -- homie:			(string) Name of the downed homie we're looking for. 
  1818. -- 
  1819. function m24_homie_death_thread(homie) 
  1820. 	 
  1821. 	local old_terminals_remaining = terminals_remaining 
  1822. 	local gat_name = M24_groups.homies.gat 
  1823. 	local play_id 
  1824. 	 
  1825. 	M24_status.homie_is_dying[ homie ]  = true 
  1826. 	 
  1827. 	local homie_index = 1 
  1828. 	if (homie == M24_groups.homies.members[1]) then 
  1829. 		homie_index = 1 
  1830. 	elseif (homie == M24_groups.homies.members[2]) then 
  1831. 		homie_index = 2 
  1832. 	elseif (homie == M24_groups.homies.members[3]) then 
  1833. 		homie_index = 3 
  1834. 	end 
  1835. 	 
  1836. 	-- wait for the player(s) to get near the terminal 
  1837. 	while get_dist_closest_player_to_object(M24_deaths[homie_index].pos) > 20.0 do 
  1838. 		thread_yield() 
  1839. 	end 
  1840. 	 
  1841. 	follower_make_independent(homie, true) 
  1842. 	follower_set_can_abandon( homie, false ) 
  1843. 	ai_do_scripted_move(homie, M24_deaths[homie_index].pos, true, false) 
  1844. 	-- He can't be dismissed anymore 
  1845. 	on_dismiss("", homie) 
  1846. 	 
  1847. 	while true do 
  1848. 		if get_dist( homie,  M24_deaths[homie_index].pos ) < 5 then 
  1849. 			break 
  1850. 			 
  1851. 		-- if they didn't make it there by the time we activated the terminal, warp them. 
  1852. 		elseif (old_terminals_remaining ~= terminals_remaining) then 
  1853. 			teleport(homie, M24_deaths[homie_index].pos) 
  1854. 			break 
  1855. 			 
  1856. 		else 
  1857. 			thread_yield() 
  1858. 		end 
  1859. 	end 
  1860. 	 
  1861. 	-- now set their leash so they don't go anywheres. 
  1862. 	npc_leash_to_nav(homie, M24_deaths[homie_index].pos, 1.0) 
  1863. 	 
  1864. 	-- wait for the terminal to be activated. 
  1865. 	while (old_terminals_remaining == terminals_remaining) do 
  1866. 		thread_yield() 
  1867. 	end 
  1868. 	 
  1869. 	-- Now that the player is close, completely kill your homie. 
  1870. 	turn_vulnerable(homie) 
  1871. 	effect_play_on_human( "Effect BloodHit", homie, "Head" ) 
  1872.  
  1873. 	-- play a homie "ouch" line. We're thinking there are custom lines. 
  1874. 	if M24_dialog_lines.homie_death_lines[ homie_index ] ~= nil then 
  1875. 		play_id = audio_play_persona_line( homie, M24_dialog_lines.homie_hurt_lines[ homie_index ] ) 
  1876. 		while audio_is_playing( play_id ) do 
  1877. 			thread_yield() 
  1878. 		end 
  1879. 	end 
  1880. 	 
  1881. 	human_enter_downed(homie) 
  1882. 	-- must get downed first before we allow death 
  1883. 	on_death("", homie) 
  1884. 	 
  1885. 	-- revive homie objective 
  1886. 	objective_text( 0, "PLAYER_REVIVE_FOLLOWER", "", "", SYNC_ALL, OI_ASSET_REVIVE ) 
  1887.  
  1888. 	while not human_being_revived(homie) do 
  1889. 		thread_yield() 
  1890. 	end 
  1891. 	 
  1892. 	local reviver = human_being_revived_by( homie ) 
  1893. 	if reviver ~= LOCAL_PLAYER and reviver ~= REMOTE_PLAYER then 
  1894. 		reviver = LOCAL_PLAYER 
  1895. 	end 
  1896. 	 
  1897. 	-- dramatic music, player screams 
  1898. 	audio_object_post_event("m24_homie_death") 
  1899. 	local play_id = audio_play_persona_line( reviver, "M24_PC_Scream_In_Agony" ) 
  1900.  
  1901. 	-- play homie's death line 
  1902. 	if M24_dialog_lines.homie_death_lines[homie_index] ~= nil then 
  1903. 		play_id = audio_play_persona_line(homie, M24_dialog_lines.homie_death_lines[homie_index]) 
  1904. 		while audio_is_playing( play_id ) do 
  1905. 			thread_yield() 
  1906. 		end 
  1907. 	end 
  1908. 	 
  1909. 	-- let the stinger audio start, then play the line. 
  1910. 	if (homie ~= gat_name) then 
  1911. 		delay(4.0) 
  1912. 		 
  1913. 		-- Gat says farewell 
  1914. 		play_id = audio_play_persona_line(gat_name, M24_dialog_lines.gat_death_lines[homie_index]) 
  1915. 		while audio_is_playing( play_id ) do 
  1916. 			thread_yield() 
  1917. 		end 
  1918. 	end 
  1919. 	 
  1920. 	while (human_is_downed(homie)) do 
  1921. 		thread_yield() 
  1922. 	end 
  1923. 	 
  1924. 	character_kill(homie, true, "", false) 
  1925. 	 
  1926. 	-- Thread done, clear it. 
  1927. 	M24_threads.homie_death_thread_handle = INVALID_THREAD_HANDLE 
  1928. end 
  1929.  
  1930. -- Simple thread that plays camera shakes periodically to mimic earthquakes 
  1931. -- 
  1932. function m24_marsquake_thread() 
  1933. 	local interval, intensity 
  1934. 	 
  1935. 	while true do 
  1936. 		if M24_status.big_quakes == true then 
  1937. 			interval = 9 
  1938. 			intensity = rand_float( M24_MIN_BIG_MQ_INTENSITY, M24_MAX_BIG_MQ_INTENSITY)  
  1939. 			camera_shake_play(M24_MARSQUAKE_SHAKE, intensity) 
  1940. 			audio_object_post_event( "m24_rumble_bridge" ) 
  1941. 			 
  1942. 			m24_stumble() 
  1943. 		else 
  1944. 			interval = rand_int (M24_MIN_MQ_INTERVAL,M24_MAX_MQ_INTERVAL)  
  1945. 			intensity = rand_float( M24_MIN_MQ_INTENSITY, M24_MAX_MQ_INTENSITY)  
  1946. 			 
  1947. 			audio_object_post_event( "m24_camera_shake" ) 
  1948.  
  1949. 			camera_shake_play(M24_MARSQUAKE_SHAKE, intensity) 
  1950. 		end 
  1951.  
  1952. 		delay(interval) 
  1953. 		thread_yield() 
  1954. 	end 
  1955. end 
  1956.  
  1957. function m24_stumble() 
  1958. 	local dir = get_random_table_entry( M24_navpoints.stumbles ) 
  1959.  
  1960. 	m24_character_stumble( LOCAL_PLAYER, dir ) 
  1961. 	 
  1962. 	if coop_is_active() then 
  1963. 		m24_character_stumble( REMOTE_PLAYER, dir ) 
  1964. 	end 
  1965. end 
  1966.  
  1967. function m24_character_stumble( player, dir ) 
  1968. 	if character_is_ready( player ) == true and character_is_jumping( player ) == false then 
  1969. 		if M24_threads.stumble_threads == nil then 
  1970. 			M24_threads.stumble_threads = { } 
  1971. 		end 
  1972.  
  1973. 		if M24_threads.stumble_threads[ player ] ~= nil then 
  1974. 			return 
  1975. 		end 
  1976. 		 
  1977. 		M24_threads.stumble_threads[ player ] = thread_new( "m24_character_stumble_thread", player, dir ) 
  1978. 	end 
  1979. end 
  1980.  
  1981. function m24_character_stumble_thread( player, dir ) 
  1982. 		player_release_human_shield(player, true) 
  1983. 		character_clear_combat_move(player)  
  1984. 		action_play_directional_stumble(player, dir) 
  1985. 		M24_threads.stumble_threads[ player ] = nil 
  1986. end 
  1987.  
  1988. -- Checks to see if you drove the rover into the lava, and if so, blows it up. 
  1989. function m24_vehicle_lava_thread() 
  1990.  
  1991. 	-- this is very shady, but other methods were, for some reason, unreliable. 
  1992. 	-- I came to this number through trial and error, as vehicle positioning seems inconsistent. 
  1993. 	-- Todo: get a navpoint as our basline position. 
  1994. 	local y0 = 1080.36 
  1995. 	 
  1996. 	while not (vehicle_exists(M24_vehicles[1]) and vehicle_exists(M24_vehicles[2])) do 
  1997. 		thread_yield() 
  1998. 	end 
  1999. 	 
  2000. 	while true do 
  2001. 		for i, vehicle in pairs(M24_vehicles) do 
  2002. 			local x, y, z = get_object_pos(vehicle) 
  2003. 			if y < y0 then 
  2004. 				vehicle_detonate(vehicle) 
  2005. 			end 
  2006. 		end 
  2007. 		thread_yield() 
  2008. 	end 
  2009. end 
  2010.  
  2011. function m24_killbane_on_death() 
  2012. 	M24_killbane_dead = true 
  2013. end 
  2014.  
  2015. function m24_killbane_on_undowned() 
  2016. 	marker_add( M24_characters.killbane, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL ) 
  2017. end 
  2018.  
  2019. function m24_general_chatter_thread() 
  2020. 	local chatterer, situation, situation_table, index, count, n 
  2021. 	 
  2022. 	while true do 
  2023. 		n = sizeof_table( M24_general_chatterers ) 
  2024. 		 
  2025. 		if M24_status.no_chatter ~= true and n > 0 then 
  2026. 			-- pick someone to say something 
  2027. 			index = rand_int( 1,  n ) 
  2028. 			count = 1 
  2029. 			 
  2030. 			for k, v in pairs( M24_general_chatterers ) do 
  2031. 				if count == index then 
  2032. 					chatterer = k 
  2033. 					situation_table = v 
  2034. 					break 
  2035. 				end 
  2036. 				 
  2037. 				count = count + 1 
  2038. 			end 
  2039. 			 
  2040. 			-- pick an appropriate event 
  2041. 			situation = situation_table[ rand_int( 1, #situation_table ) ] 
  2042. 			 
  2043. 			-- play it 
  2044. 			if character_exists( chatterer ) == true and character_is_dead( chatterer ) == false then 
  2045. 				audio_play_persona_line( chatterer, situation ) 
  2046. 			end 
  2047. 			 
  2048. 		end 
  2049. 		 
  2050. 		delay( rand_float( 5, 15 ) ) 
  2051. 	end 
  2052. end 
  2053.  
  2054. function m24_add_chatterers( chatterers, situations ) 
  2055. 	for k, v in pairs( chatterers ) do 
  2056. 		M24_general_chatterers[ v ] = situations 
  2057. 	end 
  2058. end 
  2059.  
  2060. function m24_remove_chatterers( chatterers ) 
  2061. 	for k, v in pairs( chatterers ) do 
  2062. 		M24_general_chatterers[ v ] = nil 
  2063. 	end 
  2064. end 
  2065.  
  2066. function m24_debug_killbane_damage_thread() 
  2067. 	MAGMA_CRYSTAL_PERCENT_DAMAGE = 30 
  2068. 	M24_status.debug_damage_killbane = true 
  2069. 	 
  2070. 	while true do 
  2071. 		delay( 5 ) 
  2072. 	 
  2073. 		if character_exists( M24_characters.killbane ) == true and character_is_dead( M24_characters.killbane ) == false then 
  2074. 			m24_killbane_took_damage_cb( "", "LOCAL_PLAYER", .1, true, false ) 
  2075. 		end 
  2076. 	end 
  2077. end