./m19.lua

  1. --[[ 
  2. 	m19.lua 
  3. 	SR3 Mission Script 
  4. 	DATE: 08-17-2010 
  5. 	AUTHOR:	Neil Ryan and Craig Williams 
  6. ]]-- 
  7.  
  8.  
  9. -- Debug flags -- 
  10. 	M19_enable_binks        = true 
  11. 	M19_chem_moved_distance = 1.0 
  12.  
  13. -- Tweakable Parameters -- 
  14. 	M19_ped_density = .50 
  15. 	M19_ped_density_in_truck = 0.8 
  16. 	M19_ped_density_fix_mask = 0.35 
  17. 	M19_ped_density_at_rimjobs = 0.15 
  18. 	M19_player_sprint_ms = 3500 -- Amount of time a full sprint bar will last 
  19. 	M19_player_sprint_recharge_ms = 10000 -- Amount of time it takes to fully recharge the sprint bar 
  20. 	M19_player_sprint_recharge_delay_ms = 2500 -- Amount of time to wait before starting to recharge the sprint bar 
  21.  
  22. -- Groups -- 
  23.  
  24. 	M19_group = { 
  25. 		start_car = { 
  26. 			name = "start_car" 
  27. 		}, 
  28. 		 
  29. 		stag_guard = { 
  30. 			name = "stag_guard", 
  31. 			members = { "npc_stag_guard 001", "npc_stag_guard 002" }, 
  32. 		}, 
  33. 		 
  34. 		chem_01 = { 
  35. 			name = "chem_01_group" 
  36. 		}, 
  37. 		 
  38. 		chem_02 = { 
  39. 			name = "chem_02_group" 
  40. 		}, 
  41. 		 
  42. 		chem_02_brute = { 
  43. 			name = "chem_02_brute_group", 
  44. 			brute = "chem_02_brute", 
  45. 			detection_callback = "m19_brute_02_cb", 
  46. 			death_callback = "m19_first_brute_dead_cb", 
  47. 		}, 
  48. 		 
  49. 		chem_03 = { 
  50. 			name = "chem_03_group" 
  51. 		}, 
  52. 		 
  53. 		chem_03_brute = { 
  54. 			name = "chem_03_brute_group", 
  55. 			brute = "chem_03_brute", 
  56. 			detection_callback = "m19_brute_03_cb", 
  57. 			death_callback = "m19_first_brute_dead_cb", 
  58. 		}, 
  59. 		 
  60. 		chem_final = { 
  61. 			name = "chem_final_group" 
  62. 		}, 
  63. 		 
  64. 		chem_truck = { 
  65. 			name = "chem_truck_group", 
  66. 			vehicle = "chem_truck", 
  67. 		}, 
  68. 		 
  69. 		spawn_small_a = { 
  70. 			name = "continuous_small_a" 
  71. 		}, 
  72. 		 
  73. 		spawn_small_b = { 
  74. 			name = "continuous_small_b" 
  75. 		}, 
  76. 		 
  77. 		spawn_small_c = { 
  78. 			name = "continuous_small_c" 
  79. 		}, 
  80. 		 
  81. 		spawn_small_d = { 
  82. 			name = "continuous_small_d" 
  83. 		}, 
  84. 		 
  85. 		spawn_small_e = { 
  86. 			name = "continuous_small_e" 
  87. 		}, 
  88. 		 
  89. 		start_homies = { 
  90. 			name = "start_homies", 
  91. 			suko = "Suko_start" 
  92. 		}, 
  93. 		 
  94. 		inside_homies = { 
  95. 			name = "inside_homies", 
  96. 			suko = "Suko_inside" 
  97. 		}, 
  98. 		 
  99. 		checkpoint_homies = { 
  100. 			name = "checkpoint_homies", 
  101. 			suko = "Suko_checkpoint" 
  102. 		}, 
  103. 		 
  104. 		viola_attack_zombies = { 
  105. 			name = "attack_zombies", 
  106. 			-- car = "m19_viola_car", 
  107. 			members	= 	{ "m19_viola_zombie 001", "m19_viola_zombie 002", "m19_viola_zombie 003", "m19_viola_zombie 004"	}, 
  108. 		}, 
  109. 		 
  110. 		rim_jobs_spawns_01 = { 
  111. 			spawns = {"mask_spawn_a", "mask_spawn_b"}, 
  112. 		}, 
  113. 		 
  114. 		rim_jobs_spawns_02 = { 
  115. 			spawns = {"mask_spawn_c"}, 
  116. 		}, 
  117. 		 
  118. 		rim_jobs_spawns_03 = { 
  119. 			spawns = {"mask_spawn_d"}, 
  120. 		}, 
  121. 		 
  122. 		rim_jobs_spawns_all = { 
  123. 			spawns = {"mask_spawn_a", "mask_spawn_b", "mask_spawn_c", "mask_spawn_d"}, 
  124. 		}, 
  125. 		 
  126. 		flaming_brute = { 
  127. 			name = "flaming_brute_group", 
  128. 			brute = "m19_flaming_brute", 
  129. 		}, 
  130. 		 
  131. 		cte_zombie_group = { 
  132. 			name = "m19_cte_zombies_01", 
  133. 		}, 
  134. 		 
  135. 		cte_suko_group = { 
  136. 			name = "m19_cte_suko_01", 
  137. 		}, 
  138. 		 
  139. 	} 
  140. 	 
  141. 	M19_cte = { 
  142. 		name = "m19_cte_01", 
  143. 	 
  144. 	} 
  145. 	 
  146. 	--we need to not stop and start the same spawns at each level or we get extra spawns 
  147. 	M19_c_spawn = { 
  148. 		level_1 = { M19_group.spawn_small_a.name, M19_group.spawn_small_b.name }, 
  149. 		stop_level2 = { M19_group.spawn_small_a.name }, 
  150. 		start_level2 = { M19_group.spawn_small_c.name }, 
  151. 		stop_level3 = { M19_group.spawn_small_b.name }, 
  152. 		start_level3 = { M19_group.spawn_small_d.name, M19_group.spawn_small_e.name }, 
  153. 	} 
  154.  
  155. -- Spawn Regions -- 
  156. 	M19_spawn_regions = { 
  157. 		"Script_Spawn_Region 001", 
  158. 		"Script_Spawn_Region 002", 
  159. 		"Script_Spawn_Region 003", 
  160. 		"Script_Spawn_Region 004", 
  161. 		"Script_Spawn_Region 005", 
  162. 		"Script_Spawn_Region 006", 
  163. 		"Script_Spawn_Region 007", 
  164. 		"Script_Spawn_Region 008", 
  165. 		"Script_Spawn_Region 009", 
  166. 		"Script_Spawn_Region 010" 
  167. 	} 
  168. 	 
  169. 	M19_mask_spawn_regions = { 
  170. 		"Mask_Spawn_Region 01", 
  171. 		"Mask_Spawn_Region 02", 
  172. 		"Mask_Spawn_Region 03", 
  173. 		"Mask_Spawn_Region 04", 
  174. 	} 
  175. 	 
  176. -- Navpoints -- 
  177. 	M19_nav = { 
  178. 		escape_here1 = { 
  179. 			name = "Escape_here_nav 001" 
  180. 		}, 
  181. 		 
  182. 		neutralize_here = { 
  183. 			name = "neutralize_chem_truck_nav" 
  184. 		}, 
  185. 		 
  186. 		mission_end = { "m19_end_nav_local", "m19_end_nav_coop" }, 
  187. 		 
  188. 		zombie_attack_leash_point = { 
  189. 			name = "zombie_attack_nav1" 
  190. 		}, 
  191. 		 
  192. 		mask_fix_point = { 
  193. 			name = "Mask_fix_navpoint" 
  194. 		}, 
  195. 		 
  196. 		rimjobs_door_open_point = { 
  197. 			name = "M19_OpenDoor_Offset" 
  198. 		}, 
  199. 		 
  200. 		mask_search_point = { 
  201. 			name = "viola_mask_search_nav" 
  202. 		}, 
  203. 	} 
  204. 	 
  205. -- Triggers -- 
  206. 	M19_trigger = { 
  207. 		doors = { 
  208. 			name = "doors_trigger", 
  209. 			hit = false, 
  210. 		}, 
  211. 		 
  212. 		freeze = { 
  213. 			name = "m19_trigger_vehicle_freeze", 
  214. 			hit = false, 
  215. 		}, 
  216. 		 
  217. 		escape1 = { 
  218. 			name = "Escape_trigger 001", 
  219. 			hit = false, 
  220. 		}, 
  221. 		 
  222. 		escape2 = { 
  223. 			name = "Neutralize_audio_trigger", 
  224. 			hit = false, 
  225. 		}, 
  226. 		 
  227. 		dumpster = { 
  228. 			name = "m19_trigger_dumpster", 
  229. 			hit = false, 
  230. 		}, 
  231. 		 
  232. 		roof = { 
  233. 			name = "m19_trigger_roof", 
  234. 			hit = false, 
  235. 		}, 
  236. 		 
  237. 		rim_jobs = { 
  238. 			name = "mask_fix_trigger", 
  239. 			hit = false, 
  240. 			inside = 0, 
  241. 		}, 
  242. 		 
  243. 		rim_jobs_door = { 
  244. 			name = "m19_trigger_rimjobs_door", 
  245. 		}, 
  246. 		 
  247. 		traffic = { 
  248. 			name = "m19_disable_traffic", 
  249. 		}, 
  250. 		 
  251. 		island = { 
  252. 			name = "Trigger_island_area", 
  253. 			hit = false, 
  254. 		}, 
  255. 	} 
  256. 		 
  257.  
  258. -- Characters -- 
  259.  
  260. -- Vehicles -- 
  261.  
  262. -- Mesh Movers -- 
  263. 	M19_chemical = { 
  264. 		container1 = { 
  265. 			name = "Chemicalcontainer B 001", 
  266. 			script_mover_name = "Chem 001", 
  267. 			start_nav = "Chem_start 001",			-- navpoint under the chem container used to see if the container has been moved 
  268. 			end_nav = "Chem_end 001", 
  269. 			vfx = { nav = "vfx_zombie_fog 001", handle = -1 }, 
  270. 			zombies = M19_group.chem_01.name, 
  271. 			brute_group = "", 
  272. 			moved = false, 
  273. 			complete = false, 
  274. 			setup = false, 
  275. 			spawn_trigger = "Chem_01_spawn_trigger", 
  276. 			spawn_callback = "m19_chem_01_spawn_cb", 
  277. 		}, 
  278. 		 
  279. 		container2 = { 
  280. 			name = "Chemicalcontainer B 002", 
  281. 			script_mover_name = "Chem 002", 
  282. 			start_nav = "Chem_start 002",			-- navpoint under the chem container used to see if the container has been moved 
  283. 			end_nav = "Chem_end 002", 
  284. 			vfx = { nav = "vfx_zombie_fog 002", handle = -1 }, 
  285. 			zombies = M19_group.chem_02.name, 
  286. 			brute_group = M19_group.chem_02_brute, 
  287. 			moved = false, 
  288. 			complete = false, 
  289. 			setup = false, 
  290. 			spawn_trigger = "Chem_02_spawn_trigger", 
  291. 			spawn_callback = "m19_chem_02_spawn_cb", 
  292. 		}, 
  293. 		 
  294. 		container3 = { 
  295. 			name = "Chemicalcontainer B 003", 
  296. 			script_mover_name = "Chem 003", 
  297. 			start_nav = "Chem_start 003",			-- navpoint under the chem container used to see if the container has been moved 
  298. 			end_nav = "Chem_end 003", 
  299. 			vfx = { nav = "vfx_zombie_fog 003", handle = -1 }, 
  300. 			zombies = M19_group.chem_03.name, 
  301. 			brute_group = M19_group.chem_03_brute, 
  302. 			moved = false, 
  303. 			complete = false, 
  304. 			setup = false, 
  305. 			spawn_trigger = "Chem_03_spawn_trigger", 
  306. 			spawn_callback = "m19_chem_03_spawn_cb", 
  307. 		}, 
  308. 		 
  309. 	} 
  310. 			 
  311. -- Text -- 
  312.  
  313. -- Threads -- 
  314. 	M19_closest_container_thread = INVALID_THREAD_HANDLE 
  315. 	M19_moved_or_found_thread = INVALID_THREAD_HANDLE 
  316. 	M19_out_of_mask_trigger_thread = INVALID_THREAD_HANDLE 
  317. 	M19_brute_flame_thread = INVALID_THREAD_HANDLE 
  318. 	M19_local_player_health_thread = INVALID_THREAD_HANDLE 
  319. 	M19_remote_player_health_thread = INVALID_THREAD_HANDLE 
  320.  
  321. -- Checkpoints -- 
  322. 	M19_INSIDE_DOOR1 = "doors_start_nav 001" 
  323. 	 
  324. 	M19_warp_points = { 
  325. 		bridge = { 
  326. 			player1 = "player1_bridge_nav", 
  327. 			player2 = "player2_bridge_nav", 
  328. 			viola = "viola_bridge_nav", 
  329. 		}, 
  330. 		 
  331. 		rimjobs = { 
  332. 			player1 = "player1_rimjobs_nav", 
  333. 			player2 = "player2_rimjobs_nav", 
  334. 			viola = "viola_rimjobs_nav", 
  335. 		}, 
  336. 	 
  337. 	} 
  338. 	 
  339. 	M19_checkpoint = { 
  340. 		start = { 
  341. 			name = MISSION_START_CHECKPOINT, 
  342. 			nav = { "start_nav 001", "start_nav 002" }, 
  343. 		}, 
  344. 		 
  345. 		doors = { 
  346. 			name = "m19_doors", 
  347. 			nav1 = "doors_start_nav 001", 
  348. 			nav2 = "doors_start_nav 002", 
  349. 		}, 
  350. 		 
  351. 		-- checkpoints for any 1 container 
  352. 		chem_01 = { name = "m19_chem_01" }, 
  353. 		chem_02 = { name = "m19_chem_02" }, 
  354. 		chem_03 = { name = "m19_chem_03" }, 
  355. 		 
  356. 		-- checkpoints for 1 container and viola rescued 
  357. 		chem_01_rescue = { name = "m19_chem_01_rescue" }, 
  358. 		chem_02_rescue = { name = "m19_chem_02_rescue" }, 
  359. 		chem_03_rescue = { name = "m19_chem_03_rescue" }, 
  360. 		 
  361. 		-- checkpoints for any 2 containers 
  362. 		chem_12 = { name = "m19_chem_12" }, 
  363. 		chem_23 = { name = "m19_chem_23" }, 
  364. 		chem_13 = { name = "m19_chem_13" }, 
  365. 		 
  366. 		-- checkpoints for any 2 containers and mask fixed 
  367. 		chem_12_fixed = { name = "m19_chem_12_fixed" }, 
  368. 		chem_23_fixed = { name = "m19_chem_23_fixed" }, 
  369. 		chem_13_fixed = { name = "m19_chem_13_fixed" }, 
  370. 		 
  371. 		all_no_mask = { name = "m19_no_mask" }, 
  372. 		 
  373. 		final = { 
  374. 			name = "m19_final", 
  375. 			nav1 = "doors_start_nav 001", 
  376. 			nav2 = "doors_start_nav 002", 
  377. 		} 
  378. 	} 
  379. 	 
  380. -- Cutscenes -- 
  381. 	CUTSCENE_MISSION_INTRO = "19_in" 
  382. 	CUTSCENE_MISSION_OUTRO = "19_out" 
  383.  
  384. -- Conversations -- 
  385. 	M19_convo = { 
  386. 		mission_start = {-- 
  387. 			files = { 
  388. 				{name = "M19_Mission_Start", delay = 2.0, phonecall = false}, 
  389. 				{name = "M19_Drive_01", delay = 0.0, phonecall = false}, 
  390. 			}, 
  391. 			thread = INVALID_THREAD_HANDLE, 
  392. 		}, 
  393. 		 
  394. 		help_me_call = {-- 
  395. 			files = { 
  396. 				{name = "M19_Help_Me_Call", delay = 0.0, phonecall = true, recieveing = false}, 
  397. 			}, 
  398. 			thread = INVALID_THREAD_HANDLE, 
  399. 		}, 
  400. 		 
  401. 		viola_rescued = {-- 
  402. 			files = { 
  403. 				{name = "M19_viola_Rescued", delay = 0.0, phonecall = false}, 
  404. 			}, 
  405. 			thread = INVALID_THREAD_HANDLE, 
  406. 		}, 
  407. 		 
  408. 		zombie_killing_01 = {-- 
  409. 			files = { 
  410. 				{name = "", delay = 15.0, phonecall = false}, 
  411. 				{name = "M19_Zombie_Killing_01", delay = 8.0, phonecall = false}, 
  412. 				{name = "M19_More_Zombie_Killing", delay = 10.0, phonecall = false}, 
  413. 				{name = "M19_More_Zombie_Killing_2", delay = 0.0, phonecall = false}, 
  414. 			}, 
  415. 			thread = INVALID_THREAD_HANDLE, 
  416. 		}, 
  417. 		 
  418. 		broken_mask = {-- 
  419. 			files = { 
  420. 				{name = "M19_Broken_Mask", delay = 0.0, phonecall = false}, 
  421. 			}, 
  422. 			thread = INVALID_THREAD_HANDLE, 
  423. 		}, 
  424. 		 
  425. 		rim_jobs_start = {-- 
  426. 			files = { 
  427. 				{name = "M19_Hold_Off_Zombies_RJ", delay = 10.0, phonecall = false}, 
  428. 				{name = "M19_Hurry_Up_in_Rim_Jobs", delay = 10.0, phonecall = false}, 
  429. 				{name = "M19_Hurry_Up_in_Rim_Jobs_2", delay = 9.0, phonecall = false}, 
  430. 				{name = "M19_Found_Hose_In_Rim_Jobs", delay = 0.0, phonecall = false}, 
  431. 			}, 
  432. 			thread = INVALID_THREAD_HANDLE, 
  433. 		}, 
  434. 		-- zombie_killing_02 = { 
  435. 		-- 	files = { 
  436. 		-- 		{name = "", delay = 15.0}, 
  437. 		-- 		{name = "M19_Zombie_Killing_02", delay = 0.0}, 
  438. 		-- 	}, 
  439. 		--	thread = INVALID_THREAD_HANDLE, 
  440. 		-- }, 
  441. 		 
  442. 		zombie_killing_03 = {-- 
  443. 			files = { 
  444. 				{name = "", delay = 15.0, phonecall = false}, 
  445. 				{name = "M19_Zombie_Killing_03", delay = 10.0, phonecall = false}, 
  446. 				{name = "M19_Zombie_Killing_04", delay = 0.0, phonecall = false}, 
  447. 			}, 
  448. 			thread = INVALID_THREAD_HANDLE, 
  449. 		}, 
  450. 		 
  451. 		take_sample = {-- 
  452. 			files = { 
  453. 				{name = "M19_Finish_The_Job_Call", delay = 5.0, phonecall = true, recieveing = true}, 
  454. 				{name = "M19_Take_Sample_Call", delay = 0.0, phonecall = true, recieveing = true}, 
  455. 			}, 
  456. 			thread = INVALID_THREAD_HANDLE, 
  457. 		}, 
  458. 		 
  459. 		left_with_truck = {-- 
  460. 			files = { 
  461. 				{name = "M19_Flatbed_Truck", delay = 0.0, phonecall = false}, 
  462. 			}, 
  463. 			thread = INVALID_THREAD_HANDLE, 
  464. 		}, 
  465. 		 
  466. 		jump_truck = {-- 
  467. 			files = { 
  468. 				{name = "M19_Jump_Truck", delay = 0.0, phonecall = false}, 
  469. 			}, 
  470. 			thread = INVALID_THREAD_HANDLE, 
  471. 		}, 
  472. 	} 
  473. 	 
  474. 	M19_personas = { 
  475. 		{ name = "Oleg", handle = INVALID_PERSONA_HANDLE }, 
  476. 		{ name = "Suko", handle = INVALID_PERSONA_HANDLE }, 
  477. 		{ name = "Burt", handle = INVALID_PERSONA_HANDLE }, 
  478. 	} 
  479.  
  480. 	M19_persona_line = { 
  481. 		easy_enough	= { name = "M19_First_Container_Done_01", 	character = LOCAL_PLAYER, play_2d = false},-- 
  482. 		blasting_containers = { name = "M19_Blasting_Containers", character = LOCAL_PLAYER, play_2d = false},-- 
  483. 		see_zombie = { name = "M19_More_Zombie_Brute_01", character = LOCAL_PLAYER, play_2d = false}, 
  484. 		 
  485. 		-- Character set by m19_setup_crew() 
  486. 		one_more = { name = "M19_Third_Container_Done", character = "", play_2d = false},-- 
  487. 		brute_on_fire = { name = "M19_Brute_On_Fire", character = LOCAL_PLAYER, play_2d = false}, 
  488. 		brute_on_fire_dead = { name = "M19_Brute_On_Fire_Dead", character = LOCAL_PLAYER, play_2d = false}, 
  489. 	} 
  490. 	 
  491. 	M19_island_emitter = "M19_amb_zombie_island" 
  492. 	 
  493. 	M19_emitters = { 
  494. 		"M19_em_crashed_plane_groans", 
  495. 	} 
  496. 		 
  497. -- Other -- 
  498. 	M19_SONIC_GUN = "Special-SonicGun" 
  499. 	 
  500. 	M19_PLAYER_LOADOUT = { M19_SONIC_GUN } 
  501. 	 
  502. 	M19_containers_disturbed = 0 
  503. 	M19_containers_found = 0 
  504. 	M19_spawn_level = 0 
  505. 	M19_doors_started = false 
  506. 	 
  507. 	-- record decision 
  508. 	M19_decision = { 
  509. 		took_chem_truck = false, 
  510. 		chem_truck_in_water = false, 
  511. 	} 
  512. 	 
  513. 	M19_NOT_CLOSE_DISTANCE = 5000.0 
  514. 	 
  515. 	M19_waypoint_target = "" 
  516. 	 
  517. 	M19_active_convo = "" 
  518.  
  519. 	M19_rim_jobs_old_door = "m19_rimjobs_door_mover" 
  520. 	M19_rim_jobs_new_door = "rim_jobs_zombie_door_mover" 
  521. 	 
  522. 	M19_container_splash_effect = "Wtr Splash Zombie" 
  523. 	 
  524. 	M19_mask_finished = false 
  525. 	M19_initial_brute_down = false 
  526. 	 
  527. 	Current_Suko = "" 
  528. 	 
  529. 	M19_phonecall_finished = false 
  530. 	M19_first_brute_dead = false 
  531.  
  532. -- ************************* 
  533. -- 
  534. -- Standard functions 
  535. -- 
  536. -- ************************* 
  537.  
  538. -- This is the primary entry point for the mission, and is responsible for starting up the mission 
  539. -- at the specified checkpoint. 
  540. -- CALLED FROM CODE 
  541. -- 
  542. -- m19_checkpoint:	The checkpoint the mission should begin at 
  543. -- is_restart:					TRUE if the mission is restarting, FALSE otherwise 
  544. -- 
  545. function m19_start(m19_checkpoint, is_restart) 
  546.  
  547. 	-- Check if this mission starting from the beginning 
  548. 	if (m19_checkpoint == M19_checkpoint.start.name) then 
  549. 		if (is_restart == false) then 
  550. 			-- First time playing mission 
  551. 			 
  552. 			-- Play an intro cutscene??? 
  553. 			if (CUTSCENE_MISSION_INTRO ~= "") then 
  554. 				cutscene_play(CUTSCENE_MISSION_INTRO, nil, M19_checkpoint.start.nav, false) 
  555. 			elseif M19_enable_binks then 
  556. 				bink_play("19_IN_v2") 
  557. 			end 
  558. 		end 
  559. 		fade_out(0) 
  560. 	end 
  561.  
  562. 	-- Handle mission initialization for the current checkpoint 
  563. 	m19_initialize(m19_checkpoint) 
  564.  
  565. 	-- Run the mission from the current checkpoint 
  566. 	m19_run(m19_checkpoint) 
  567. 	 
  568. end 
  569.  
  570. -- This is the primary function responsible for running the entire mission from start to finish. 
  571. -- 
  572. -- first_checkpoint:	The first checkpoint to begin running the mission at 
  573. -- 
  574. function m19_run(first_checkpoint) 
  575. 	local current_checkpoint = first_checkpoint 
  576. 	local ignore_vehicles = true 
  577. 	local ignore_notoriety = true 
  578. 	spawn_override_change_hood_alternate_spawning("HOOD_ZOMBIE", true) 
  579. 	 
  580. 	-- post voice event to mute non-modulated voice 
  581. 	audio_object_post_event("Mission_VO_Override") 
  582.  
  583. 	--set the cancel navpoints 
  584. 	mission_set_cancel_warp_location(M19_checkpoint.start.nav[1], M19_checkpoint.start.nav[2]) 
  585. 	 
  586. 	-- Run the mission from the beginning 
  587. 	if current_checkpoint == M19_checkpoint.start.name then 
  588. 		objective_text( 0, "M19_OBJ_GO_TO_ENTRANCE", "", "", SYNC_ALL, OI_ASSET_LOCATION )	 
  589. 		m19_go_to_entrance() 
  590. 		 
  591. 		m19_guards_scene()	 
  592. 		tutorial_start("weap_charge_weapon", 0, true, true)  
  593. 		 
  594. 		current_checkpoint = M19_checkpoint.doors.name 
  595. 		mission_set_checkpoint(M19_checkpoint.doors.name, ignore_vehicles, ignore_notoriety) 
  596. 	end 
  597. 	 
  598. 	spawn_region_max_spawn_dist(150.0) 
  599. 	notoriety_force_no_spawn("morningstar", true) 
  600. 	notoriety_set_min("morningstar", 0) 
  601. 	notoriety_set_max("morningstar", 0) 
  602. 	notoriety_force_no_spawn("luchadores", true) 
  603. 	notoriety_set_min("luchadores", 0) 
  604. 	notoriety_set_max("luchadores", 0) 
  605. 	notoriety_force_no_spawn("deckers", true) 
  606. 	notoriety_set_min("deckers", 0) 
  607. 	notoriety_set_max("deckers", 0) 
  608. 	notoriety_force_no_spawn("police", true) 
  609. 	notoriety_force_no_spawn("stag", true) 
  610. 	 
  611. 	--start audio emitters 
  612. 	for i, emitter in pairs(M19_emitters) do 
  613. 		audio_ambient_emitter_start(emitter) 
  614. 	end 
  615. 	 
  616. 	 
  617. 	--start health monitoring 
  618. 	M19_local_player_health_thread = thread_new("m19_player_health_thread", LOCAL_PLAYER) 
  619. 	if (coop_is_active()) then 
  620. 		M19_remote_player_health_thread = thread_new("m19_player_health_thread", REMOTE_PLAYER) 
  621. 	end 
  622. 	 
  623. 	m19_setup_containers_for_checkpoint(current_checkpoint) 
  624. 	 
  625. 	-- determine which checkpoint is hit 
  626. 	if(m19_get_num_destroyed_containers() < 1) then 
  627. 		current_checkpoint = m19_do_containers_checkpoints(current_checkpoint, 1) 
  628. 		mission_set_checkpoint(current_checkpoint, ignore_vehicles, ignore_notoriety) 
  629. 	end 
  630. 	 
  631. 	if (current_checkpoint == M19_checkpoint.chem_01.name or current_checkpoint == M19_checkpoint.chem_02.name or current_checkpoint == M19_checkpoint.chem_03.name) then 
  632. 		current_checkpoint = m19_do_rescue() 
  633. 		m19_start_convo_thread(M19_convo.zombie_killing_01) 
  634. 	 
  635. 	end  
  636. 	-- from this poitn on viola should be invulnerable 
  637. 	--mute viola's normal persona lines 
  638. 	npc_suppress_persona(Current_Suko, true) 
  639. 	 
  640. 	if(m19_get_num_destroyed_containers() < 2) then 
  641. 		current_checkpoint = m19_do_containers_checkpoints(current_checkpoint, 2) 
  642. 		mission_set_checkpoint(current_checkpoint, ignore_vehicles, ignore_notoriety) 
  643. 	end 
  644. 	 
  645. 	if (current_checkpoint == M19_checkpoint.chem_12.name or current_checkpoint == M19_checkpoint.chem_13.name or current_checkpoint == M19_checkpoint.chem_23.name or current_checkpoint == M19_checkpoint.all_no_mask.name) then 
  646. 		current_checkpoint = m19_do_mask() 
  647. 		m19_start_convo_thread(M19_convo.zombie_killing_03) 
  648. 	 
  649. 	end 
  650. 	 
  651. 	 
  652. 	if(m19_get_num_destroyed_containers() < 3) then 
  653. 		current_checkpoint = m19_do_containers_checkpoints(current_checkpoint, 3) 
  654. 		mission_set_checkpoint(current_checkpoint, ignore_vehicles, ignore_notoriety) 
  655. 	end 
  656. 	 
  657. 	if current_checkpoint == M19_checkpoint.final.name then 
  658. 		m19_take_or_destroy_chem_truck() 
  659. 	end 
  660.  
  661. 	-- if (CUTSCENE_MISSION_OUTRO ~= "") then 
  662. 	-- 	cutscene_play(CUTSCENE_MISSION_OUTRO) 
  663. 	-- elseif M19_enable_binks then 
  664. 	-- 	bink_play("19_Out_v2") 
  665. 	-- end 
  666. 	 
  667. 	-- fade_out(0.5) 
  668. 	-- fade_out_block() 
  669. 	-- teleport_coop(M19_nav.mission_end_local.name, M19_nav.mission_end_coop.name, true) 
  670. 	-- fade_in(0.5) 
  671. 	-- fade_in_block() 
  672. 	 
  673. 	mission_end_success("m19", CUTSCENE_MISSION_OUTRO, M19_nav.mission_end) 
  674. 	 
  675. end 
  676.  
  677. -- This is the primary function responsible for cleaning up the entire mission 
  678. -- CALLED FROM CODE (+++MUST RETURN IMMEDIATLY+++) 
  679. -- 
  680. function m19_cleanup() 
  681.  
  682. 	-- stop muting voice 
  683. 	audio_object_post_event("Mission_VO_Override_Stop") 
  684. 	audio_object_post_event("M19_Music_STOP", nil, nil, LOCAL_PLAYER) 
  685.  
  686. 	-- Unload any audio 
  687. 	m19_unload_all_convos() 
  688. 	m19_unload_personas() 
  689. 	 
  690. 	-- re-enable traffic 
  691. 	traffic_disable_lanes(M19_trigger.traffic.name, false) 
  692. 	sidewalk_disable_nodes(M19_trigger.island.name, true) 
  693. 	 
  694. 	--fix rimjobs door 
  695. 	mesh_mover_hide(M19_rim_jobs_new_door) 
  696. 	mesh_mover_show(M19_rim_jobs_old_door) 
  697. 	 
  698. 	spawn_region_max_spawn_dist_reset() 
  699. 	-- shut down continuous spawns 
  700. 	m19_stop_continuous_spawns() 
  701. 	for i,spawn in pairs(M19_group.rim_jobs_spawns_all.spawns) do 
  702. 		continuous_spawn_stop(spawn) 
  703. 	end 
  704. 	continuous_spawn_regions_enable(M19_spawn_regions, false) 
  705. 	continuous_spawn_regions_enable(M19_mask_spawn_regions, false) 
  706. 	-- clear tod settings 
  707. 	m19_clear_tod() 
  708.  
  709. 	-- remove temp weapons 
  710. 	inv_remove_temp_loadout(M19_PLAYER_LOADOUT) 
  711. 	 
  712. 	-- kill the water check	 
  713. 	if M19_moved_or_found_thread ~= INVALID_THREAD_HANDLE then 
  714. 		thread_kill(M19_moved_or_found_thread) 
  715. 		M19_moved_or_found_thread = INVALID_THREAD_HANDLE 
  716. 	end 
  717. 	if M19_closest_container_thread ~= INVALID_THREAD_HANDLE then 
  718. 		thread_kill(M19_closest_container_thread) 
  719. 		M19_closest_container_thread = INVALID_THREAD_HANDLE 
  720. 	end 
  721. 	if M19_brute_flame_thread ~= INVALID_THREAD_HANDLE then 
  722. 		thread_kill(M19_brute_flame_thread) 
  723. 		M19_brute_flame_thread = INVALID_THREAD_HANDLE 
  724. 	end 
  725. 	 
  726. 	if M19_local_player_health_thread ~= INVALID_THREAD_HANDLE then 
  727. 		thread_kill(M19_local_player_health_thread) 
  728. 		M19_local_player_health_thread = INVALID_THREAD_HANDLE 
  729. 	end 
  730. 	if M19_remote_player_health_thread ~= INVALID_THREAD_HANDLE then 
  731. 		thread_kill(M19_remote_player_health_thread) 
  732. 		M19_remote_player_health_thread = INVALID_THREAD_HANDLE 
  733. 	end 
  734. 	if M19_out_of_mask_trigger_thread ~= INVALID_THREAD_HANDLE then 
  735. 		thread_kill(M19_out_of_mask_trigger_thread) 
  736. 		M19_out_of_mask_trigger_thread = INVALID_THREAD_HANDLE 
  737. 	end 
  738. 	 
  739. 	-- clear container markers 
  740. 	m19_clear_container(M19_chemical.container1) 
  741. 	m19_clear_container(M19_chemical.container2) 
  742. 	m19_clear_container(M19_chemical.container3) 
  743.  
  744. 	-- cleanup truck 
  745. 	on_vehicle_destroyed("", M19_group.chem_truck.vehicle) 
  746. 	 
  747. 	--cleanup zombies 
  748. 	for i, zombie in pairs(M19_group.viola_attack_zombies.members) do 
  749. 		on_death("", zombie) 
  750. 	end 
  751. 	 
  752. 	--cleanup first brutes 
  753. 	on_detection("", M19_group.chem_02_brute.brute) 
  754. 	on_detection("", M19_group.chem_03_brute.brute) 
  755. 	on_death("", M19_group.chem_02_brute.brute) 
  756. 	on_death("", M19_group.chem_03_brute.brute) 
  757. 	 
  758. 	-- Cleanup the decision scene 
  759. 	m19_cleanup_decision() 
  760. 	 
  761. 	-- clear triggers 
  762. 	for key, trigger in pairs(M19_trigger) do 
  763. 		m19_clear_trigger(trigger.name) 
  764. 	end 
  765. 	 
  766. 	-- cleanup groups 
  767. 	m19_cleanup_groups() 
  768. 	m19_cleanup_crew(M19_group.start_homies) 
  769. 	m19_cleanup_crew(M19_group.inside_homies) 
  770. 	m19_cleanup_crew(M19_group.checkpoint_homies) 
  771. 	 
  772. 	notoriety_set_max("luchadores", 5) 
  773. 	notoriety_set_max("deckers", 5) 
  774. 	notoriety_set_max("morningstar", 5) 
  775. 	notoriety_force_no_spawn("luchadores", false) 
  776. 	notoriety_force_no_spawn("deckers", false) 
  777. 	notoriety_force_no_spawn("morningstar", false) 
  778. 	notoriety_force_no_spawn("police", false) 
  779. 	notoriety_force_no_spawn("stag", false) 
  780.  
  781. 	-- Remove any sprint restrictions 
  782. 	player_override_clear_sprint() 
  783. 	player_override_clear_sprint_delay() 
  784. 	player_override_clear_sprint_recharge() 
  785. 	 
  786. 	-- cleanup timer callback 
  787. 	hud_timer_set(1, 0, "") 
  788. 	hud_timer_stop(1) 
  789. 	hud_timer_hide(1, true) 
  790. 	 
  791. 	-- do spawning again 
  792. 	spawning_vehicles(true) 
  793.  
  794. 	-- takeoff player mask 
  795. 	customization_item_revert() 
  796. 	audio_object_post_event("m19_sfx_gas_mask_STOP", nil, nil, LOCAL_PLAYER) 
  797. 	if (coop_is_active()) then 
  798. 		audio_object_post_event("m19_sfx_gas_mask_STOP", nil, nil, REMOTE_PLAYER) 
  799. 	end 
  800. 	audio_object_post_event("m19_amb_PC_poisoned_STOP") 
  801. 	 
  802. 	--stop audio emitters 
  803. 	for i, emitter in pairs(M19_emitters) do 
  804. 		audio_ambient_emitter_stop(emitter) 
  805. 	end 
  806. 	audio_ambient_emitter_stop(M19_island_emitter) 
  807. 	 
  808. 	--kill any phonecalls that may be occuring 
  809. 	 
  810. 	audio_remove_mission_cellphone("M19_Help_Me_Call") 
  811. 	audio_remove_mission_cellphone("M19_Finish_The_Job_Call") 
  812. 	audio_remove_mission_cellphone("M19_Take_Sample_Call") 
  813. 	 
  814. 	 
  815. 	--kill all other mission audio 
  816. 	audio_play("M19_unload") 
  817. 	 
  818. 	--clear drug effects 
  819. 	drug_effect_clear_override_values() 
  820. 	refraction_situation_clear() 
  821. 	 
  822. end 
  823.  
  824. -- Called when the mission has ended with success 
  825. -- CALLED FROM CODE (+++MUST RETURN IMMEDIATLY+++) 
  826. -- 
  827. function m19_success() 
  828. end 
  829.  
  830.  
  831. -- ************************* 
  832. -- 
  833. -- Local functions 
  834. -- 
  835. -- ************************* 
  836.  
  837. -- Initialize the mission for the specified checkpoint 
  838. -- 
  839. -- checkpoint:		Checkpoint to initialize the mission to 
  840. -- 
  841. function m19_initialize(checkpoint) 
  842. 	-- Zone swap 
  843. 	-- city_zone_swap("chemcrash") 
  844. 	city_zone_swap("zombies") 
  845. 	city_zone_swap("mayoroff") 
  846. 	mesh_mover_hide(M19_rim_jobs_old_door) 
  847. 	mesh_mover_show(M19_rim_jobs_new_door) 
  848. 	-- city_zone_swap("burn") 
  849. 	traffic_disable_lanes(M19_trigger.traffic.name, true) 
  850. 	sidewalk_disable_nodes(M19_trigger.island.name, false) 
  851. 	 
  852. 	-- Make sure the screen is completly faded out 
  853. 	mission_start_fade_out(0.0) 
  854.  
  855. 	-- Set the mission author 
  856. 	set_mission_author("Neil Ryan") 
  857.  
  858. 	-- Common initialization 
  859. 	m19_initialize_common() 
  860.  
  861. 	-- Checkpoint specific initialization 
  862. 	m19_initialize_checkpoint(checkpoint) 
  863.  
  864. 	-- Start fading in  
  865. 	mission_start_fade_in() 
  866.  
  867. end 
  868.  
  869. -- Go to the entrance of the zombie area 
  870. -- 
  871. function m19_go_to_entrance() 
  872. 	m19_setup_crew(M19_group.start_homies) 
  873. 	group_create(M19_group.stag_guard) 
  874. 	for i, npc in pairs(M19_group.stag_guard.members) do 
  875. 		npc_detection_enable(npc, false) 
  876. 	end 
  877. 	 
  878. 	m19_set_trigger(M19_trigger.island.name, "m19_island_entrance_cb", false) 
  879. 	 
  880. 	m19_set_trigger(M19_trigger.doors.name, "m19_doors_cb") 
  881. 	mission_waypoint_add(M19_trigger.doors.name, SYNC_ALL) 
  882. 	marker_add(M19_trigger.doors.name, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL) 
  883. 	 
  884. 	m19_start_convo_thread(M19_convo.mission_start) 
  885.  
  886. 	m19_set_trigger(M19_trigger.freeze.name, "m19_doors_freeze_cb", false) 
  887. 	 
  888. 	set_ped_density(M19_ped_density) 
  889. 	while not M19_trigger.doors.hit do 
  890. 		thread_yield() 
  891. 	end 
  892. 	 
  893. 	if character_is_in_vehicle(LOCAL_PLAYER) then 
  894. 		vehicle_speed_override(LOCAL_PLAYER, 0) 
  895. 	end 
  896. 	if character_is_in_vehicle(REMOTE_PLAYER) then 
  897. 		vehicle_speed_override(REMOTE_PLAYER, 0) 
  898. 	end 
  899. 	--start the zombie island emitter 
  900. 	audio_ambient_emitter_start(M19_island_emitter) 
  901. 	 
  902. end 
  903.  
  904. -- Z-scene of guards letting you into the infected area 
  905. function m19_guards_scene() 
  906.  
  907. 	if M19_trigger.island.hit == true then 
  908. 		for i, container in pairs(M19_chemical) do 
  909. 			mesh_mover_show(container.script_mover_name) 
  910. 		end 
  911. 	end 
  912. 	m19_clear_trigger(M19_trigger.island.name) 
  913.  
  914. 	--fade_out(0.5) 
  915. 	--fade_out_block() 
  916. 	cutscene_in() 
  917. 	group_create_hidden( M19_group.cte_suko_group.name, true ) 
  918. 	group_create_hidden( M19_group.cte_zombie_group.name, true ) 
  919. 	customization_item_wear("cm_gasmask", "cm_mask_gasmask.cmeshx", "cm_mask_gasmask", true, SYNC_ALL, true) 
  920. 	character_add_prop("m19_cte_suko", "gasmask")  
  921. 	cutscene_play( M19_cte.name, nil, {M19_checkpoint.doors.nav1, M19_checkpoint.doors.nav2} ) 
  922. 	--cutscene_play( M19_cte.name) 
  923. 	group_destroy( M19_group.cte_zombie_group.name ) 
  924. 	group_destroy( M19_group.cte_suko_group.name ) 
  925.  
  926. 	M19_doors_started = true 
  927. 	 
  928. 	-- teleport players into the bad area 
  929. 	--local exit_vehicle = true 
  930. 	--teleport_coop(M19_checkpoint.doors.nav1, M19_checkpoint.doors.nav2, exit_vehicle) 
  931. 	--delay(5) 
  932. 	 
  933. 	m19_cleanup_crew(M19_group.start_homies) 
  934. 	 
  935. 	-- if group_is_loaded(M19_group.start_car.name) then 
  936. 	-- 	group_destroy(M19_group.start_car.name) 
  937. 	-- end 
  938. 	 
  939. 	if group_is_loaded(M19_group.stag_guard.name) then 
  940. 		group_destroy(M19_group.stag_guard.name) 
  941. 	end 
  942. 	 
  943. 	--m19_setup_crew(M19_group.inside_homies) 
  944. 	spawning_vehicles(false) 
  945. 	m19_restrict_players_sprint() 
  946. 	inv_item_equip("Special-SonicGun", LOCAL_PLAYER) 
  947. 	if (coop_is_active()) then 
  948. 		inv_item_equip("Special-SonicGun", REMOTE_PLAYER) 
  949. 	end 
  950. 	 
  951. 	customization_item_wear("cm_gasmask", "cm_mask_gasmask.cmeshx", "cm_mask_gasmask", true, SYNC_ALL, true) 
  952. 	--play gasmask sounds 
  953. 	audio_object_post_event("m19_sfx_gas_mask_normal", nil, nil, LOCAL_PLAYER) 
  954. 	if (coop_is_active()) then 
  955. 		audio_object_post_event("m19_sfx_gas_mask_normal", nil, nil, REMOTE_PLAYER) 
  956. 	end 
  957. 	 
  958. 	--setup the exit truck here while we can be sure the players aren't in a custom car 
  959. 	m19_setup_chemical_truck() 
  960. 	 
  961. 	cutscene_out() 
  962. 	--fade_in(0.5) 
  963. 	--fade_in_block() 
  964. end 
  965.  
  966. function m19_setup_containers_for_checkpoint(current_checkpoint) 
  967. 	local do_1 = false 
  968. 	local do_2 = false 
  969. 	local do_3 = false 
  970. 	local checkpoint_found = true 
  971. 	 
  972. 	-- figure out which containers we have left for the checkpoint 
  973. 	if current_checkpoint == M19_checkpoint.doors.name then 
  974. 		-- just got here, still need to do all of the containers 
  975. 		do_1 = true 
  976. 		do_2 = true 
  977. 		do_3 = true 
  978. 	elseif (current_checkpoint == M19_checkpoint.chem_01_rescue.name or 
  979. 		    current_checkpoint == M19_checkpoint.chem_01.name) then 
  980. 		do_2 = true 
  981. 		do_3 = true 
  982. 	elseif (current_checkpoint == M19_checkpoint.chem_02_rescue.name  or 
  983. 			current_checkpoint == M19_checkpoint.chem_02.name) then 
  984. 		do_1 = true 
  985. 		do_3 = true 
  986. 	elseif (current_checkpoint == M19_checkpoint.chem_03_rescue.name or 
  987. 			current_checkpoint == M19_checkpoint.chem_03.name) then 
  988. 		do_1 = true 
  989. 		do_2 = true 
  990. 	elseif (current_checkpoint == M19_checkpoint.chem_12_fixed.name or 
  991. 			current_checkpoint == M19_checkpoint.chem_12.name) then 
  992. 		do_3 = true 
  993. 	elseif (current_checkpoint == M19_checkpoint.chem_23_fixed.name or 
  994. 			current_checkpoint == M19_checkpoint.chem_23.name) then 
  995. 		do_1 = true 
  996. 	elseif (current_checkpoint == M19_checkpoint.chem_13_fixed.name or 
  997. 			current_checkpoint == M19_checkpoint.chem_13.name) then 
  998. 		do_2 = true 
  999. 	end 
  1000. 		 
  1001. 	continuous_spawn_regions_enable(M19_spawn_regions, true) 
  1002. 	 
  1003. 	-- setup or destroy container 
  1004. 	if do_1 then 
  1005. 		m19_setup_container(M19_chemical.container1) 
  1006. 	else 
  1007. 		m19_checkpoint_complete_container(M19_chemical.container1) 
  1008. 	end 
  1009. 	 
  1010. 	if do_2 then 
  1011. 		m19_setup_container(M19_chemical.container2) 
  1012. 	else 
  1013. 		m19_checkpoint_complete_container(M19_chemical.container2) 
  1014. 	end 
  1015. 	 
  1016. 	if do_3 then 
  1017. 		m19_setup_container(M19_chemical.container3) 
  1018. 	else 
  1019. 		m19_checkpoint_complete_container(M19_chemical.container3) 
  1020. 	end 
  1021.  
  1022. end 
  1023.  
  1024. -- determine what we have done and what needs to be done 
  1025. -- 
  1026. -- current_checkpoint:		(string) name of the current checkpoint 
  1027. -- 
  1028. function m19_do_containers_checkpoints(current_checkpoint, size) 
  1029.  
  1030. 	--had to setup containers, but we've already finished this goal, don't mess with the rest 
  1031. 	if (m19_get_num_destroyed_containers() >= size) then 
  1032. 		return current_checkpoint 
  1033. 	end 
  1034. 		 
  1035. 	-- set objective text to whatever it needs to be 
  1036. 	m19_set_3_way_objective_text() 
  1037. 	 
  1038. 	-- check to see if containers have been moved or found 
  1039. 	M19_moved_or_found_thread = thread_new("m19_container_moved_or_found_thread") 
  1040. 	 
  1041. 	if (size == 1) then 
  1042. 		--this should happen just after we get inside or if we restart at the doors checkpoint 
  1043. 		audio_object_post_event("M19_music_mission_start", nil, nil, LOCAL_PLAYER) 
  1044. 	end 
  1045. 	 
  1046. 	--check all current containers and possibly re-add their OIs 
  1047. 	m19_update_container_markers() 
  1048. 	 
  1049. 	-- keep waypoint on the closest container 
  1050. 	M19_closest_container_thread = thread_new("m19_nav_to_closest_thread") 
  1051. 	 
  1052. 	while (m19_get_num_destroyed_containers() < size) do 
  1053. 		thread_yield() 
  1054. 	end 
  1055. 	 
  1056. 	-- potentially clean up threads 
  1057. 	if M19_moved_or_found_thread ~= INVALID_THREAD_HANDLE then 
  1058. 		thread_kill(M19_moved_or_found_thread) 
  1059. 		M19_moved_or_found_thread = INVALID_THREAD_HANDLE 
  1060. 	end 
  1061. 	if M19_closest_container_thread ~= INVALID_THREAD_HANDLE then 
  1062. 		thread_kill(M19_closest_container_thread) 
  1063. 		M19_closest_container_thread = INVALID_THREAD_HANDLE 
  1064. 	end 
  1065. 	m19_clear_container_markers() 
  1066. 	-- keep track of where we're currently at 
  1067. 	return m19_get_container_checkpoint()		 
  1068. end 
  1069.  
  1070. function m19_update_container_markers() 
  1071. 	for i, container in pairs(M19_chemical) do 
  1072. 		if(container.moved and not container.complete) then 
  1073. 			marker_remove(container.script_mover_name) 
  1074. 			marker_add(container.script_mover_name, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_ALL) 
  1075. 			waypoint_add(container.end_nav) 
  1076. 			marker_add(container.end_nav, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_FULL, SYNC_ALL) 
  1077. 		end 
  1078. 	end 
  1079. 	 
  1080. end 
  1081.  
  1082. function m19_clear_container_markers() 
  1083. 	for i, container in pairs(M19_chemical) do 
  1084. 		marker_remove(container.script_mover_name, SYNC_ALL) 
  1085. 		marker_remove(container.end_nav, SYNC_ALL) 
  1086. 	end 
  1087. end 
  1088.  
  1089. -- after one container is destroyed, rescue viola 
  1090. function m19_do_rescue() 
  1091. 	local current_checkpoint_name 
  1092. 	waypoint_remove() 
  1093. 	 
  1094. 	-- set objective text to whatever it needs to be 
  1095. 	m19_set_3_way_objective_text() 
  1096. 	 
  1097. 	m19_start_convo_thread(M19_convo.help_me_call) 
  1098. 	--spawn viola and zombies 
  1099. 	m19_setup_crew(M19_group.inside_homies) 
  1100. 	Current_Suko = M19_group.inside_homies.suko 
  1101. 	character_add_prop(Current_Suko, "gasmask") 
  1102. 	npc_leash_to_nav(Current_Suko, M19_nav.zombie_attack_leash_point.name, 1) 
  1103. 	character_prevent_flinching(Current_Suko, true) 
  1104. 	character_prevent_bumping(Current_Suko, true) 
  1105. 	--mute viola's normal persona lines 
  1106. 	npc_suppress_persona(Current_Suko, true) 
  1107. 	--set_ignore_ai_flag(Current_Suko, true) 
  1108. 	group_create(M19_group.viola_attack_zombies.name, true) 
  1109. 	for i, zombie in pairs(M19_group.viola_attack_zombies.members) do 
  1110. 		turn_invulnerable(zombie) 
  1111. 	end 
  1112. 	 
  1113. 	 
  1114. 	--wait on conversation 
  1115. 	while M19_convo.help_me_call.thread ~= INVALID_THREAD_HANDLE do 
  1116. 		thread_yield() 
  1117. 	end 
  1118. 	 
  1119. 	--guide the player to viola 
  1120. 	m19_set_trigger(M19_trigger.dumpster.name, "m19_dumpster_cb", true) 
  1121. 	objective_text( 0, "M19_OBJ_RESCUE_VIOLA", "", "", SYNC_ALL, OI_ASSET_LOCATION )	 
  1122. 	repeat 
  1123. 		--seriously stay the hell there. wtf. stop it. 
  1124. 		if (get_dist(Current_Suko, M19_nav.zombie_attack_leash_point.name) > 2.0) then 
  1125. 			teleport(Current_Suko, M19_nav.zombie_attack_leash_point.name) 
  1126. 			npc_leash_to_nav(Current_Suko, M19_nav.zombie_attack_leash_point.name, 1) 
  1127. 		end 
  1128. 		thread_yield() 
  1129. 	until (M19_trigger.dumpster.hit) 
  1130. 	 
  1131. 	m19_set_trigger(M19_trigger.roof.name, "m19_roof_cb", true)	 
  1132. 	repeat 
  1133. 		thread_yield() 
  1134. 	until (M19_trigger.roof.hit) 
  1135. 	 
  1136. 	--set waypoint to viola 
  1137. 	marker_add(Current_Suko, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_LOCATION) 
  1138. 	--objective_text(0, "get to viola") 
  1139. 	 
  1140. 	 
  1141. 	--set_ignore_ai_flag(Current_Suko, false) 
  1142. 	--wait till you're close 
  1143. 	while (get_dist_closest_player_to_object(Current_Suko) > 25) do 
  1144. 		thread_yield() 
  1145. 	end 
  1146. 	-- once you're there, set goal to kill zombies, make viola not invulnerable 
  1147. 	--objective_text(0, "kill zombies!") 
  1148. 	objective_text( 0, "M19_OBJ_KILL_ZOMBiES", "", "", SYNC_ALL, OI_ASSET_KILL )	 
  1149. 	marker_remove(Current_Suko) 
  1150. 	--follower_set_can_abandon( Current_Suko, true) 
  1151. 	turn_vulnerable(Current_Suko) 
  1152. 	npc_leash_remove(Current_Suko) 
  1153. 	character_prevent_flinching(Current_Suko, false) 
  1154. 	character_prevent_bumping(Current_Suko, false) 
  1155. 	for i, zombie in pairs(M19_group.viola_attack_zombies.members) do 
  1156. 		turn_vulnerable(zombie) 
  1157. 		marker_add(zombie, MINIMAP_ICON_KILL, OI_ASSET_KILL, OI_FLAGS_DEFAULT, SYNC_ALL) 
  1158. 		on_death("m19_viola_zombie_death_cb", zombie) 
  1159. 	end 
  1160. 	 
  1161. 	--while any zombies left wait 
  1162. 	while ( group_members_alive(M19_group.viola_attack_zombies.name) > 0) do 
  1163. 		thread_yield() 
  1164. 	end 
  1165. 	m19_start_convo_thread(M19_convo.viola_rescued) 
  1166. 	npc_leash_remove(Current_Suko) 
  1167. 	marker_remove(Current_Suko) 
  1168. 	set_dont_attack_me_on_sight_flag(Current_Suko, true) 
  1169. 	turn_invulnerable(Current_Suko) 
  1170. 	current_checkpoint_name = m19_get_container_checkpoint(true, false) 
  1171. 	mission_set_checkpoint(current_checkpoint_name, true, true) 
  1172. 	delay(10) 
  1173. 	return current_checkpoint_name 
  1174. end 
  1175.  
  1176. function m19_viola_zombie_death_cb(zombie, attacker) 
  1177. 	marker_remove(zombie, SYNC_ALL) 
  1178. 	on_death("", zombie) 
  1179. end 
  1180.  
  1181. -- after two containers are destroyed, fix your mask 
  1182. function m19_do_mask() 
  1183. 	local current_checkpoint_name 
  1184. 	waypoint_remove() 
  1185. 	 
  1186. 	-- set objective text to whatever it needs to be 
  1187. 	m19_set_3_way_objective_text() 
  1188. 	 
  1189. 	--change gasmask sounds 
  1190. 	audio_object_post_event("m19_sfx_gas_mask_panic", nil, nil, LOCAL_PLAYER) 
  1191. 	if (coop_is_active()) then 
  1192. 		audio_object_post_event("m19_sfx_gas_mask_panic", nil, nil, REMOTE_PLAYER) 
  1193. 	end 
  1194.  
  1195. 	audio_object_post_event("m19_amb_PC_poisoned", nil, nil, LOCAL_PLAYER) 
  1196. 	audio_object_post_event( "M19_music_PC_poisoned", nil, nil, LOCAL_PLAYER) 
  1197. 	drug_effect_set_override_values(0.15,0) 
  1198. 	refraction_situation_set("drug weak") 
  1199. 	 
  1200. 	m19_start_convo_thread(M19_convo.broken_mask) 
  1201. 	--wait on conversation 
  1202. 	while M19_convo.broken_mask.thread ~= INVALID_THREAD_HANDLE do 
  1203. 		thread_yield() 
  1204. 	end 
  1205. 	 
  1206. 	-- Turn down peds 
  1207. 	set_ped_density(M19_ped_density_fix_mask) 
  1208. 	 
  1209. 	-- Set waypoint to rim_jobs 
  1210. 	trigger_enable(M19_trigger.rim_jobs.name, true) 
  1211. 	marker_add_trigger(M19_trigger.rim_jobs.name, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL) 
  1212. 	on_trigger("m19_mask_trigger_enter_cb", M19_trigger.rim_jobs.name) 
  1213. 	on_trigger_exit("m19_mask_trigger_exit_cb", M19_trigger.rim_jobs.name) 
  1214. 	 
  1215. 	continuous_spawn_regions_enable(M19_spawn_regions, false) 
  1216. 	continuous_spawn_regions_enable(M19_mask_spawn_regions, true) 
  1217. 	objective_text( 0, "M19_OBJ_GO_TO_RIMJOBS", "", "", SYNC_ALL, OI_ASSET_LOCATION )	 
  1218. 	 
  1219. 	-- Wait till the player gets there 
  1220. 	hud_timer_set(1, 120000, "get_to_rimjobs_cb") 
  1221. 	 
  1222. 	local num_players = 1 
  1223. 	if (coop_is_active()) then 
  1224. 		num_players = 2 
  1225. 	end 
  1226. 	 
  1227. 	repeat 
  1228. 		thread_yield() 
  1229. 	until (M19_trigger.rim_jobs.inside == num_players) 
  1230. 	hud_timer_set(1, 0, "") 
  1231. 	hud_timer_stop(1) 
  1232. 	hud_timer_hide(1, true) 
  1233. 	marker_remove_trigger(M19_trigger.rim_jobs.name, SYNC_ALL) 
  1234. 	 
  1235. 	-- Open the door to rimjobs 
  1236. 	--door_open(M19_rim_jobs_door) 
  1237. 	door_lock(M19_rim_jobs_new_door, true) 
  1238. 	objective_text( 0, "M19_OBJ_OPEN_DOOR", "", "", SYNC_ALL, OI_ASSET_USE ) 
  1239. 	marker_add(M19_rim_jobs_new_door, MINIMAP_ICON_USE, OI_ASSET_USE, OI_FLAGS_DEFAULT, SYNC_ALL) 
  1240. 	trigger_enable(M19_trigger.rim_jobs_door.name, true) 
  1241. 	on_trigger("m19_open_rimjobs_cb", M19_trigger.rim_jobs_door.name) 
  1242. 	repeat 
  1243. 		thread_yield() 
  1244. 	until (door_is_open(M19_rim_jobs_new_door)) 
  1245. 	--make sure this trigger is cleared 
  1246. 	m19_clear_trigger(M19_trigger.rim_jobs_door.name) 
  1247. 	 
  1248. 	--up the drugged effects 
  1249. 	marker_remove(M19_rim_jobs_new_door, SYNC_ALL) 
  1250. 	drug_effect_set_override_values(0.25,0) 
  1251. 	-- refraction_situation_set("drug medium") 
  1252. 	 
  1253. 	-- Turn down peds 
  1254. 	set_ped_density(M19_ped_density_at_rimjobs) 
  1255. 	 
  1256. 	-- Start spawns/setup fight 
  1257. 	objective_text( 0, "M19_OBJ_PROTECT_VIOLA", "", "", SYNC_ALL, OI_ASSET_DEFEND ) 
  1258. 	marker_add(Current_Suko, MINIMAP_ICON_PROTECT_ACQUIRE, OI_ASSET_DEFEND, OI_FLAGS_FULL, SYNC_ALL) 
  1259. 	 
  1260. 	-- 
  1261. 	-- marker_add_trigger(M19_trigger.rim_jobs.name, MINIMAP_ICON_USE, INGAME_EFFECT_LOCATION, OI_ASSET_USE, OI_FLAGS_LOCATION) 
  1262. 	 
  1263. 	-- Make viola go to her spot 
  1264. 	local should_run = true 
  1265. 	local should_fire = false 
  1266. 	 
  1267. 	while (get_dist(Current_Suko, M19_nav.mask_search_point.name) > 2.0) do 
  1268. 		ai_do_scripted_move(Current_Suko, M19_nav.mask_search_point.name, should_run, should_fire) 
  1269. 		npc_combat_enable(Current_Suko, false) 
  1270. 		 
  1271. 		while not ai_scripted_action_is_complete(Current_Suko) do 
  1272. 			thread_yield() 
  1273. 		end 
  1274. 	end 
  1275. 	 
  1276. 	-- Start area monitoring thread 
  1277. 	M19_out_of_mask_trigger_thread = thread_new("m19_handle_mask_trigger_thread") 
  1278. 	m19_start_convo_thread(M19_convo.rim_jobs_start) 
  1279. 	hud_timer_set(1, 45000, "") 
  1280. 	-- Put her into searching state 
  1281. 	npc_leash_to_nav(Current_Suko, M19_nav.mask_search_point.name, 10) 
  1282. 	set_animation_state(Current_Suko, "walk investigate") 
  1283. 	 
  1284. 	for i,spawn in pairs(M19_group.rim_jobs_spawns_01.spawns) do 
  1285. 		continuous_spawn_start(spawn, 0, 15) 
  1286. 		continuous_spawn_set_orders(spawn, "attack", "", -1) 
  1287. 	end 
  1288. 	 
  1289. 	-- Spawn a flaming brute 
  1290. 	group_create(M19_group.flaming_brute.name, true) 
  1291. 	character_ignite(M19_group.flaming_brute.brute) 
  1292. 	 
  1293. 	-- Voice line about zombie brutes being weak to fire 
  1294. 	M19_brute_flame_thread = thread_new("m19_flaming_brute_thread") 
  1295. 	 
  1296. 	--up the drugged effects 
  1297. 	drug_effect_set_override_values(0.25,0) 
  1298. 	 
  1299. 	-- Wait on timer, spawn new groups of zombies after intervals 
  1300. 	delay(15.0) 
  1301. 	-- for i,spawn in pairs(M19_group.rim_jobs_spawns_02.spawns) do 
  1302. 	-- 	continuous_spawn_start(spawn) 
  1303. 	-- 	continuous_spawn_set_orders(spawn, "attack", "", -1) 
  1304. 	-- end 
  1305. 	 
  1306. 	--up the drugged effects 
  1307. 	--drug_effect_set_override_values(0.35,0) 
  1308. 	refraction_situation_set("drug medium") 
  1309. 	 
  1310. 	delay(15.0) 
  1311. 	for i,spawn in pairs(M19_group.rim_jobs_spawns_03.spawns) do 
  1312. 		continuous_spawn_start(spawn, 0, 15) 
  1313. 		continuous_spawn_set_orders(spawn, "attack", "", -1) 
  1314. 	end 
  1315. 	 
  1316. 	--up the drugged effects 
  1317. 	drug_effect_set_override_values(0.45,0) 
  1318. 	--refraction_situation_set("drug strongest") 
  1319. 	 
  1320. 	delay(15.0) 
  1321. 	while(M19_trigger.rim_jobs.inside == false) do 
  1322. 		thread_yield() 
  1323. 	end 
  1324. 	 
  1325. 	hud_timer_set(1, 0, "") 
  1326. 	hud_timer_stop(1) 
  1327. 	hud_timer_hide(1, true) 
  1328. 	 
  1329. 	-- Success! 
  1330. 	if (M19_brute_flame_thread ~= INVALID_THREAD_HANDLE) then 
  1331. 		thread_kill(M19_brute_flame_thread) 
  1332. 		M19_brute_flame_thread = INVALID_THREAD_HANDLE 
  1333. 	end 
  1334. 	 
  1335. 	--go to viola to fix your mask 
  1336. 	marker_remove(Current_Suko) 
  1337. 	m19_clear_trigger(M19_trigger.rim_jobs.name) 
  1338. 	marker_add(Current_Suko, MINIMAP_ICON_USE, OI_ASSET_LOCATION, OI_FLAGS_DEFAULT, SYNC_ALL) 
  1339. 	objective_text( 0, "M19_OBJ_GO_TO_VIOLA", "", "", SYNC_ALL, OI_ASSET_LOCATION ) 
  1340. 	 
  1341. 	while(get_dist_closest_player_to_object(Current_Suko) > 5.0 or human_is_downed(Current_Suko)) do 
  1342. 		thread_yield() 
  1343. 	end 
  1344. 	 
  1345. 	-- kill the monitoring thread 
  1346. 	if M19_out_of_mask_trigger_thread ~= INVALID_THREAD_HANDLE then 
  1347. 		thread_kill(M19_out_of_mask_trigger_thread) 
  1348. 		hud_critical_timer_stop() 
  1349. 		M19_out_of_mask_trigger_thread = INVALID_THREAD_HANDLE 
  1350. 	end 
  1351. 	m19_clear_trigger(M19_trigger.rim_jobs.name) 
  1352. 	 
  1353. 	--message("your mask has been fixed!") 
  1354. 	npc_combat_enable(Current_Suko, true) 
  1355. 	npc_leash_remove(Current_Suko) 
  1356. 	clear_animation_state(Current_Suko) 
  1357. 	audio_object_post_event("m19_sfx_gas_mask_normal", nil, nil, LOCAL_PLAYER) 
  1358. 	if (coop_is_active()) then 
  1359. 		audio_object_post_event("m19_sfx_gas_mask_normal", nil, nil, REMOTE_PLAYER) 
  1360. 	end 
  1361. 	 
  1362. 	audio_object_post_event("m19_amb_PC_poisoned_STOP", nil, nil, LOCAL_PLAYER) 
  1363. 	audio_object_post_event( "M19_music_zombie_island", nil, nil, LOCAL_PLAYER ) 
  1364. 	 
  1365. 	marker_remove(Current_Suko) 
  1366. 	-- minimap_icon_remove_radius(M19_trigger.rim_jobs.name, SYNC_ALL) 
  1367. 	for i,spawn in pairs(M19_group.rim_jobs_spawns_all.spawns) do 
  1368. 		continuous_spawn_stop(spawn) 
  1369. 	end 
  1370. 	drug_effect_set_override_values(0.35,0) 
  1371. 	refraction_situation_set("drug medium") 
  1372. 	delay(1.0) 
  1373. 	drug_effect_set_override_values(0.25,0) 
  1374. 	--refraction_situation_set("drug medium") 
  1375. 	delay(1.0) 
  1376. 	drug_effect_set_override_values(0.15,0) 
  1377. 	refraction_situation_set("drug weak") 
  1378. 	delay(1.0) 
  1379. 	drug_effect_clear_override_values() 
  1380. 	refraction_situation_clear() 
  1381. 	 
  1382. 	-- Restore ped density 
  1383. 	set_ped_density(M19_ped_density) 
  1384. 	continuous_spawn_regions_enable(M19_mask_spawn_regions, false) 
  1385. 	continuous_spawn_regions_enable(M19_spawn_regions, true) 
  1386. 	current_checkpoint_name = m19_get_container_checkpoint(false, true) 
  1387. 	mission_set_checkpoint(current_checkpoint_name, true, true) 
  1388. 	M19_mask_finished = true 
  1389. 	return current_checkpoint_name 
  1390. end 
  1391.  
  1392. -- Take the chemical truck or destroy it 
  1393. -- 
  1394. function m19_take_or_destroy_chem_truck() 
  1395. 	waypoint_remove() 
  1396. 	group_create(M19_group.chem_final.name) 
  1397. 	 
  1398. 	zscene_prep(CUTSCENE_MISSION_OUTRO)	 
  1399. 	vehicle_show(M19_group.chem_truck.vehicle) 
  1400. 	objective_text( 0, "M19_OBJ_GET_IN_TRUCK", "", "", SYNC_ALL, OI_ASSET_USE ) 
  1401. 	 
  1402. 	 
  1403. 	-- Allow the player to enter the chemical truck again 
  1404. 	set_unjackable_flag(M19_group.chem_truck.vehicle, false) 
  1405. 	 
  1406. 	-- Register some callbacks to detect what the player has done to the vehicle 
  1407. 	on_vehicle_enter("m19_player_in_chem_truck_cb", M19_group.chem_truck.vehicle) 
  1408. 	on_vehicle_enter_water("m19_chem_truck_in_water", M19_group.chem_truck.vehicle) 
  1409. 	 
  1410. 	-- Point out where the vehicle is 
  1411. 	mission_waypoint_add(M19_group.chem_truck.vehicle) 
  1412. 	marker_add(M19_group.chem_truck.vehicle, MINIMAP_ICON_USE, OI_ASSET_USE, OI_FLAGS_FULL, SYNC_ALL) 
  1413.  
  1414. 	while M19_convo.zombie_killing_03.thread ~= INVALID_THREAD_HANDLE do 
  1415. 		thread_yield() 
  1416. 	end 
  1417. 	m19_start_convo_thread(M19_convo.take_sample) 
  1418. 	 
  1419. 	while not M19_decision.took_chem_truck and not M19_decision.chem_truck_in_water do 
  1420. 		thread_yield() 
  1421. 	end 
  1422. 	 
  1423. 	marker_remove(M19_group.chem_truck.vehicle) 
  1424. 	mission_waypoint_remove() 
  1425. 	 
  1426. 	while M19_convo.take_sample.thread ~= INVALID_THREAD_HANDLE do 
  1427. 		thread_yield() 
  1428. 	end 
  1429. 	 
  1430. 	--player_choice_tut_open("m19") 
  1431. 	-- Increase the ped count to give the player some extra stuff to run over 
  1432. 	set_ped_density(M19_ped_density_in_truck) 
  1433. 	 
  1434. 	 
  1435. 	objective_text( 0, "M19_OBJ_CHOICE", "", "", SYNC_ALL, OI_ASSET_INVALID ) 
  1436. 	 
  1437. 	vehicle_infinite_mass(M19_group.chem_truck.vehicle, false) 
  1438. 	vehicle_prevent_explosion_fling(M19_group.chem_truck.vehicle, false) 
  1439. 	vehicle_speed_override(M19_group.chem_truck.vehicle, 45.0) 
  1440. 	 
  1441. 	marker_add(M19_trigger.escape1.name, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_DEFAULT, SYNC_ALL) 
  1442. 	marker_add(M19_nav.neutralize_here.name, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_ALL) 
  1443. 	m19_set_trigger(M19_trigger.escape1.name, "m19_escape1_cb") 
  1444. 	m19_set_trigger(M19_trigger.escape2.name, "m19_escape2_cb", false) 
  1445. 	object_indicator_add_objective_text(M19_trigger.escape1.name, "PLAYER_CHOICE_M19_OPTION1_TITLE", "PLAYER_CHOICE_M19_OPTION1_BODY") 
  1446. 	object_indicator_add_objective_text(M19_nav.neutralize_here.name, "PLAYER_CHOICE_M19_OPTION2_TITLE", "PLAYER_CHOICE_M19_OPTION2_BODY") 
  1447.  
  1448. 	while true do 
  1449. 		if M19_trigger.escape1.hit or M19_decision.chem_truck_in_water then 
  1450. 			break 
  1451. 		end 
  1452. 	 
  1453. 		-- Nag the player to get back into the truck if they are no longer in it 
  1454. 		local player_in_vehicle = character_is_in_vehicle(LOCAL_PLAYER, M19_group.chem_truck.vehicle) 
  1455. 		if (player_in_vehicle == false) then 
  1456. 			player_in_vehicle = character_is_in_vehicle(REMOTE_PLAYER, M19_group.chem_truck.vehicle) 
  1457. 		end 
  1458. 		if not player_in_vehicle then 
  1459. 			m19_clear_trigger(M19_trigger.escape1.name) 
  1460. 			m19_clear_trigger(M19_trigger.escape2.name) 
  1461. 			marker_remove(M19_trigger.escape1.name) 
  1462. 			marker_remove(M19_nav.neutralize_here.name) 
  1463. 			 
  1464. 			M19_decision.took_chem_truck = false 
  1465. 			 
  1466. 			objective_text( 0, "M19_OBJ_GET_IN_TRUCK", "", "", SYNC_ALL, OI_ASSET_USE ) 
  1467. 			marker_add(M19_group.chem_truck.vehicle, MINIMAP_ICON_USE, OI_ASSET_USE, OI_FLAGS_DEFAULT, SYNC_ALL) 
  1468. 			 
  1469. 			while not M19_decision.took_chem_truck and not M19_decision.chem_truck_in_water do 
  1470. 				thread_yield() 
  1471. 			end 
  1472. 			 
  1473. 			marker_remove(M19_group.chem_truck.vehicle) 
  1474. 			 
  1475. 			objective_text( 0, "M19_OBJ_CHOICE", "", "", SYNC_ALL, OI_ASSET_INVALID ) 
  1476. 			marker_add(M19_trigger.escape1.name, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_DEFAULT, SYNC_ALL) 
  1477. 			marker_add(M19_nav.neutralize_here.name, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_ALL) 
  1478. 			m19_set_trigger(M19_trigger.escape1.name, "m19_escape1_cb") 
  1479. 			m19_set_trigger(M19_trigger.escape2.name, "m19_escape2_cb", false) 
  1480. 		end 
  1481. 		 
  1482. 		thread_yield() 
  1483. 	end 
  1484.  
  1485. 	if M19_decision.chem_truck_in_water then 
  1486. 		-- If the chem truck is in the water, we get SWAT instead of zombies. 
  1487. 		-- Exclude the zombie reward 
  1488. 		mission_set_excluded_reward("Homie_Zombie_Backup") 
  1489. 	else 
  1490. 		m19_play_convo_set(M19_convo.left_with_truck) 
  1491. 		mission_set_excluded_reward("Homie_Mayor_Reynolds") 
  1492. 		mission_set_excluded_reward("Homie_SWAT_Backup") 
  1493. 	end 
  1494. 	 
  1495. 	audio_object_post_event( "M19_music_zombie_island_end", nil, nil, LOCAL_PLAYER ) 
  1496. 	 
  1497. 	m19_cleanup_decision() 
  1498. end 
  1499.  
  1500. -- Cleanup anything setup for the decision scene 
  1501. function m19_cleanup_decision() 
  1502. 	on_vehicle_enter("", M19_group.chem_truck.vehicle) 
  1503. 	on_vehicle_enter_water("", M19_group.chem_truck.vehicle) 
  1504. 	 
  1505. 	marker_remove(M19_group.chem_truck.vehicle) 
  1506. 	marker_remove(M19_trigger.escape1.name) 
  1507. 	marker_remove(M19_nav.neutralize_here.name) 
  1508. 	m19_clear_trigger(M19_trigger.escape1.name) 
  1509. end 
  1510.  
  1511. -- *************************************************** 
  1512. -- m19_run Helper Functions 
  1513. -- *************************************************** 
  1514.  
  1515.  
  1516. -- *************************************************** 
  1517. -- m19_initialize Helper Functions 
  1518. -- *************************************************** 
  1519.  
  1520. -- Handle any common initialization 
  1521. -- 
  1522. function m19_initialize_common() 
  1523. 	-- We only use fake notoriety, so make sure checkpoint system doesn't screw this up for us 
  1524. 	notoriety_reset("luchadores") 
  1525. 	notoriety_reset("deckers") 
  1526. 	notoriety_reset("morningstar") 
  1527. 	inv_add_temp_loadout(M19_PLAYER_LOADOUT) 
  1528. 			 
  1529. 	for i, container in pairs(M19_chemical) do 
  1530. 		container.setup = false 
  1531. 	end 
  1532. 	M19_mask_finished = false 
  1533. 	M19_initial_brute_down = false 
  1534. 	m19_set_tod() 
  1535. 	m19_load_personas() 
  1536. end 
  1537.  
  1538. -- set the time of day for the mission 
  1539. function m19_set_tod() 
  1540. 	-- make it blood red night 
  1541. 	set_time_of_day(20, 00) -- evening 
  1542. end 
  1543.  
  1544. -- clear the time of day for the mission 
  1545. function m19_clear_tod() 
  1546. end 
  1547.  
  1548. -- Checkpoint specific initialization 
  1549. -- 
  1550. -- checkpoint:		The checkpoint to be initialized 
  1551. -- 
  1552. function m19_initialize_checkpoint(checkpoint) 
  1553.  
  1554. 	if (checkpoint == M19_checkpoint.start.name) then 
  1555. 		teleport_coop(M19_checkpoint.start.nav[1], M19_checkpoint.start.nav[2], true) 
  1556. 		group_create(M19_group.start_car.name, true) 
  1557. 	else 
  1558. 		--equip the sonic gun 
  1559. 		inv_item_equip("Special-SonicGun", LOCAL_PLAYER) 
  1560. 		if (coop_is_active()) then 
  1561. 			inv_item_equip("Special-SonicGun", REMOTE_PLAYER) 
  1562. 		end 
  1563. 		customization_item_wear("cm_gasmask", "cm_mask_gasmask.cmeshx", "cm_mask_gasmask", true, SYNC_ALL, true) 
  1564. 		audio_object_post_event("m19_sfx_gas_mask_normal", nil, nil, LOCAL_PLAYER) 
  1565. 		audio_ambient_emitter_start(M19_island_emitter) 
  1566. 		 
  1567. 		if (coop_is_active()) then 
  1568. 			audio_object_post_event("m19_sfx_gas_mask_normal", nil, nil, REMOTE_PLAYER) 
  1569. 		end 
  1570. 		if (checkpoint ~= M19_checkpoint.doors.name) then 
  1571. 			--only play this if we're starting after the doors checkpoint 
  1572. 			audio_object_post_event( "M19_music_regular_checkpoint", nil, nil, LOCAL_PLAYER ) 
  1573. 		end 
  1574. 		 
  1575. 		if (checkpoint ~= M19_checkpoint.doors.name and  
  1576. 			checkpoint ~= M19_checkpoint.chem_01.name and  
  1577. 			checkpoint ~= M19_checkpoint.chem_02.name and  
  1578. 			checkpoint ~= M19_checkpoint.chem_03.name) then 
  1579. 			--m19_setup_crew(M19_group.inside_homies) 
  1580. 			--Current_Suko = M19_group.inside_homies.suko 
  1581. 			m19_setup_crew(M19_group.checkpoint_homies) 
  1582. 			Current_Suko = M19_group.checkpoint_homies.suko 
  1583. 			character_add_prop(Current_Suko, "gasmask") 
  1584. 		end 
  1585. 		 
  1586. 		--possibly teleport 
  1587. 		if (checkpoint == M19_checkpoint.chem_12.name or 
  1588. 			checkpoint == M19_checkpoint.chem_23.name or 
  1589. 			checkpoint == M19_checkpoint.chem_13.name or 
  1590. 			checkpoint == M19_checkpoint.all_no_mask.name) then 
  1591. 			teleport_coop(M19_warp_points.bridge.player1, M19_warp_points.bridge.player2, true) 
  1592. 			teleport(Current_Suko, M19_warp_points.bridge.viola, true) 
  1593. 			M19_initial_brute_down = true 
  1594. 		elseif (checkpoint == M19_checkpoint.chem_12_fixed.name or 
  1595. 			checkpoint == M19_checkpoint.chem_13_fixed.name or 
  1596. 			checkpoint == M19_checkpoint.chem_23_fixed.name or 
  1597. 			checkpoint == M19_checkpoint.final.name) then 
  1598. 			teleport_coop(M19_warp_points.rimjobs.player1, M19_warp_points.rimjobs.viola, true) 
  1599. 			-- teleport(Current_Suko, M19_warp_points.rimjobs.viola, true) 
  1600. 			M19_mask_finished = true 
  1601. 			M19_initial_brute_down = true 
  1602. 		else	 
  1603. 			-- default is teleporting inside the door 
  1604. 			teleport_coop(M19_checkpoint.doors.nav1, M19_checkpoint.doors.nav2, true)	 
  1605. 		end 
  1606. 		--setup the end truck 
  1607. 		m19_setup_chemical_truck() 
  1608. 		 
  1609. 		spawning_vehicles(false) 
  1610. 		set_ped_density(M19_ped_density) 
  1611. 		m19_restrict_players_sprint() 
  1612. 	end 
  1613. end 
  1614.  
  1615. -- Sets up the mission critical chemical truck for the final decision scene 
  1616. -- 
  1617. function m19_setup_chemical_truck() 
  1618. 	group_create(M19_group.chem_truck.name) 
  1619. 	vehicle_infinite_mass(M19_group.chem_truck.vehicle, true) 
  1620. 	vehicle_prevent_explosion_fling(M19_group.chem_truck.vehicle, true) 
  1621. 	set_unjackable_flag(M19_group.chem_truck.vehicle, true) 
  1622. 	on_vehicle_destroyed("m19_mover_destroyed_cb", M19_group.chem_truck.vehicle) 
  1623. 	vehicle_hide(M19_group.chem_truck.vehicle) 
  1624. end 
  1625.  
  1626. -- Add the radius thing to the chem container and setup callbacks and flags. 
  1627. -- 
  1628. -- setup_container:		(table) container information 
  1629. -- 
  1630. function m19_setup_container(setup_container) 
  1631. 	if (setup_container.setup == false) then 
  1632. 		while (mesh_mover_ready(setup_container.script_mover_name) == false) do 
  1633. 			thread_yield() 
  1634. 		end 
  1635. 		mesh_mover_reset(setup_container.script_mover_name) 
  1636. 		on_mover_enter_water("m19_container_in_water_cb", setup_container.script_mover_name) 
  1637. 		on_mover_destroyed("m19_mover_destroyed_cb", setup_container.script_mover_name) 
  1638. 		m19_set_trigger(setup_container.spawn_trigger, setup_container.spawn_callback, false) 
  1639. 		-- setup_container.hiss_id = audio_object_post_event("m19_sfx_virus_tank_beep_hiss", nil, nil, setup_container.script_mover_name) 
  1640. 		setup_container.complete = false 
  1641. 		setup_container.moved = false 
  1642. 		setup_container.vfx.handle = effect_play(setup_container.vfx.nav, true, SYNC_ALL) 
  1643. 		setup_container.setup = true 
  1644. 	end 
  1645. end 
  1646.  
  1647. -- Mark container as completed and destroy it. 
  1648. -- This function is for loading from a checkpoint. 
  1649. -- The normal clearing of a container is handled in the checkpoint. 
  1650. -- 
  1651. -- complete_container:		(table) container information 
  1652. -- 
  1653. function m19_checkpoint_complete_container(complete_container) 
  1654. 	mesh_mover_hide(complete_container.script_mover_name) 
  1655. 	if (complete_container.moved ~= true) then 
  1656. 		complete_container.moved = true 
  1657. 		M19_containers_disturbed = M19_containers_disturbed + 1 
  1658. 		M19_containers_found = M19_containers_found + 1 
  1659. 	end 
  1660. 	 
  1661. 	complete_container.complete = true 
  1662. 	m19_adjust_spawning() 
  1663. end 
  1664.  
  1665. -- Remove markers/callbacks for a container 
  1666. -- 
  1667. -- container:		(table) container information 
  1668. -- 
  1669. function m19_clear_container(container) 
  1670. 	marker_remove(container.script_mover_name, SYNC_ALL) 
  1671. 	marker_remove(container.end_nav, SYNC_ALL) 
  1672. 	on_mover_enter_water("", container.script_mover_name) 
  1673. 	on_mover_destroyed("", container.script_mover_name) 
  1674. 	m19_clear_trigger(container.spawn_trigger) 
  1675. end 
  1676.  
  1677.  
  1678. -- *************************************************** 
  1679. -- Miscellaneous m19 Helper Funcrtions 
  1680. -- *************************************************** 
  1681.  
  1682. -- Reduce the player's ability to sprint 
  1683. -- 
  1684. function m19_restrict_players_sprint() 
  1685. 	-- Change how long a full sprint bar will last. Unlimited sprint is ignored if once this value is set. 
  1686. 	player_override_set_sprint(M19_player_sprint_ms) 
  1687. 	 
  1688. 	-- Change how long it takes to recharge the full sprint bar 
  1689. 	player_override_set_sprint_recharge(M19_player_sprint_recharge_ms) 
  1690. 	 
  1691. 	-- Change the delay before the sprint bar starts to regenerate 
  1692. 	player_override_set_sprint_delay(M19_player_sprint_recharge_delay_ms) 
  1693. end 
  1694.  
  1695. -- Spawn and setup homies 
  1696. -- 
  1697. -- homie_setup:	(table) homie information 
  1698. -- 
  1699. function m19_setup_crew(homie_setup) 
  1700. 	group_create(homie_setup.name, true) 
  1701. 	 
  1702. 	party_add( homie_setup.suko, LOCAL_PLAYER ) 
  1703. 	follower_set_can_abandon( homie_setup.suko, false) 
  1704. 	on_death("m19_failure_suko_died_cb", homie_setup.suko) 
  1705. 	on_dismiss("m19_failure_suko_abandon_cb", homie_setup.suko) 
  1706. 	set_behavior_set(homie_setup.suko, "Viola Zombie Fight") 
  1707.  
  1708. 	M19_persona_line.one_more.character = homie_setup.suko 
  1709. 	 
  1710. 	turn_invulnerable(homie_setup.suko) 
  1711. 	inv_item_remove_all(homie_setup.suko) 
  1712. 	inv_item_add("Shotgun-Police", 1, homie_setup.suko, true) 
  1713. 	inv_item_equip(WEAPON_SLOT_SHOTGUN, homie_setup.suko) 
  1714. 	npc_weapon_pickup_override(homie_setup.suko, false) 
  1715. end 
  1716.  
  1717. -- Cleanup homies 
  1718. -- 
  1719. -- homie_cleanup:	(table) homie information 
  1720. -- 
  1721. function m19_cleanup_crew(homie_cleanup) 
  1722. 	if group_is_loaded(homie_cleanup.name) then 
  1723. 		on_death("", homie_cleanup.suko) 
  1724. 		on_dismiss("", homie_cleanup.suko) 
  1725. 		group_destroy(homie_cleanup.name) 
  1726. 	end 
  1727. end 
  1728.  
  1729. -- Set a trigger enabled with a mission marker 
  1730. -- 
  1731. -- trigger:					(string) Name of the trigger 
  1732. -- trigger_callback:		(string) Function name to call when trigger is activated 
  1733. -- 
  1734. function m19_set_trigger(trigger, trigger_callback, add_marker) 
  1735. 	trigger_enable(trigger, true) 
  1736. 	if add_marker ~= false then 
  1737. 		marker_add_trigger(trigger, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL) 
  1738. 	end 
  1739. 	on_trigger(trigger_callback, trigger) 
  1740. end 
  1741.  
  1742. -- Disable trigger 
  1743. -- 
  1744. -- trigger:			(string) Name of the trigger 
  1745. -- 
  1746. function m19_clear_trigger(trigger) 
  1747. 	on_trigger("", trigger) 
  1748. 	on_trigger_exit("", trigger) 
  1749. 	trigger_enable(trigger, false) 
  1750. 	marker_remove_trigger(trigger, SYNC_ALL) 
  1751. 	mission_waypoint_remove() 
  1752. end 
  1753.  
  1754. -- Cleanup all mission groups 
  1755. -- 
  1756. function m19_cleanup_groups() 
  1757. 	if group_is_loaded(M19_group.start_car.name) then 
  1758. 		group_destroy(M19_group.start_car.name) 
  1759. 	end 
  1760. 	if group_is_loaded(M19_group.stag_guard.name) then 
  1761. 		group_destroy(M19_group.stag_guard.name) 
  1762. 	end 
  1763. 	if group_is_loaded(M19_group.chem_01.name) then 
  1764. 		group_destroy(M19_group.chem_01.name) 
  1765. 	end 
  1766. 	if group_is_loaded(M19_group.chem_02.name) then 
  1767. 		group_destroy(M19_group.chem_02.name) 
  1768. 	end 
  1769. 	if group_is_loaded(M19_group.chem_03.name) then 
  1770. 		group_destroy(M19_group.chem_03.name) 
  1771. 	end 
  1772. 	if group_is_loaded(M19_group.chem_final.name) then 
  1773. 		group_destroy(M19_group.chem_final.name) 
  1774. 	end 
  1775. 	if group_is_loaded(M19_group.chem_truck.name) then 
  1776. 		group_destroy(M19_group.chem_truck.name) 
  1777. 	end 
  1778. end 
  1779.  
  1780. -- start a group of continuous spawns 
  1781. -- 
  1782. -- spawn_table:	(table) continuous spawns to start 
  1783. -- 
  1784. function m19_start_continuous_spawns(spawn_table) 
  1785. 	for i,spawn in pairs(spawn_table) do 
  1786. 		continuous_spawn_start(spawn, 0, 15) 
  1787. 	end 
  1788. end 
  1789.  
  1790. function m19_stop_continuous_spawn_table(spawn_table) 
  1791. 	for i,spawn in pairs(spawn_table) do 
  1792. 		continuous_spawn_stop(spawn) 
  1793. 	end 
  1794. end 
  1795.  
  1796. function m19_stop_continuous_spawns() 
  1797. 	continuous_spawn_stop(M19_group.spawn_small_a.name) 
  1798. 	continuous_spawn_stop(M19_group.spawn_small_b.name) 
  1799. 	continuous_spawn_stop(M19_group.spawn_small_c.name) 
  1800. 	continuous_spawn_stop(M19_group.spawn_small_d.name) 
  1801. 	continuous_spawn_stop(M19_group.spawn_small_e.name) 
  1802. end 
  1803.  
  1804. -- adjust the continuous spawning based on the number of containers found 
  1805. -- 
  1806. function m19_adjust_spawning() 
  1807. 	 
  1808. 	if (M19_containers_disturbed <= M19_spawn_level) then 
  1809. 		return -- spawn rate only goes up 
  1810. 	end 
  1811. 	 
  1812. 	if (M19_spawn_level == 0 and M19_containers_disturbed >= 1) then 
  1813. 		m19_start_continuous_spawns(M19_c_spawn.level_1) 
  1814. 		M19_spawn_level = 1 
  1815. 	end  
  1816. 	 
  1817. 	if (M19_spawn_level == 1 and M19_containers_disturbed >= 2 and M19_first_brute_dead == true )then 
  1818. 		m19_stop_continuous_spawn_table(M19_c_spawn.stop_level2) 
  1819. 		m19_start_continuous_spawns(M19_c_spawn.start_level2) 
  1820. 		M19_spawn_level = 2 
  1821. 	end 
  1822. 	 
  1823. 	if (M19_spawn_level == 2 and M19_containers_disturbed == 3) then 
  1824. 		m19_stop_continuous_spawn_table(M19_c_spawn.stop_level3) 
  1825. 		m19_start_continuous_spawns(M19_c_spawn.start_level3) 
  1826. 		M19_spawn_level = 3 
  1827. 	end 
  1828. end 
  1829.  
  1830. -- Determine how many containers have been destroyed and play appropriate line 
  1831. function m19_play_container_destroyed_audio() 
  1832. 	local destroyed_count = 0 
  1833. 	 
  1834. 	if M19_chemical.container1.complete then 
  1835. 		destroyed_count = destroyed_count + 1 
  1836. 	end 
  1837. 	if M19_chemical.container2.complete then 
  1838. 		destroyed_count = destroyed_count + 1 
  1839. 	end 
  1840. 	if M19_chemical.container3.complete then 
  1841. 		destroyed_count = destroyed_count + 1 
  1842. 	end 
  1843. 	 
  1844. 	if destroyed_count == 1 then 
  1845. 		m19_play_persona_line(M19_persona_line.easy_enough) 
  1846. 	elseif destroyed_count == 2 then 
  1847. 		-- m19_start_convo_thread(M19_convo.zombie_killing_02) 
  1848. 	elseif destroyed_count == 3 then 
  1849. 		m19_play_persona_line(M19_persona_line.one_more) 
  1850. 	end 
  1851. end 
  1852.  
  1853. -- set the objective text based on how many containers are taken care of 
  1854. function m19_set_3_way_objective_text() 
  1855. 	local destroyed_count = 0 
  1856. 	 
  1857. 	if M19_chemical.container1.complete then 
  1858. 		destroyed_count = destroyed_count + 1 
  1859. 	end 
  1860. 	if M19_chemical.container2.complete then 
  1861. 		destroyed_count = destroyed_count + 1 
  1862. 	end 
  1863. 	if M19_chemical.container3.complete then 
  1864. 		destroyed_count = destroyed_count + 1 
  1865. 	end 
  1866. 	 
  1867. 	if destroyed_count < 3 then 
  1868. 		objective_text( 0, "M19_OBJ_NEUTRALIZE_CONTAINERS", destroyed_count, 3, SYNC_ALL, OI_ASSET_KILL ) 
  1869. 	else 
  1870. 		objective_text( 0, "M19_OBJ_GET_IN_TRUCK", "", "", SYNC_ALL, OI_ASSET_USE ) 
  1871. 	end 
  1872. end 
  1873.  
  1874. -- Determine which checkpoint we just completed 
  1875. -- rescue and mask are set to true only if we *just* did one of them 
  1876. function m19_get_container_checkpoint( rescue, mask ) 
  1877. 	local did1 = M19_chemical.container1.complete 
  1878. 	local did2 = M19_chemical.container2.complete 
  1879. 	local did3 = M19_chemical.container3.complete 
  1880. 	 
  1881. 	local current_checkpoint 
  1882. 	 
  1883. 	if (rescue) then 
  1884. 		if did1 and did2 and did3 then 
  1885. 			current_checkpoint = M19_checkpoint.all_no_mask.name 
  1886. 		elseif did1 and did2 then 
  1887. 			current_checkpoint = M19_checkpoint.chem_12.name 
  1888. 		elseif did2 and did3 then 
  1889. 			current_checkpoint = M19_checkpoint.chem_23.name 
  1890. 		elseif did1 and did3 then 
  1891. 			current_checkpoint = M19_checkpoint.chem_13.name 
  1892. 		elseif did3 then 
  1893. 			current_checkpoint = M19_checkpoint.chem_03_rescue.name 
  1894. 		elseif did2 then 
  1895. 			current_checkpoint = M19_checkpoint.chem_02_rescue.name 
  1896. 		elseif did1 then 
  1897. 			current_checkpoint = M19_checkpoint.chem_01_rescue.name 
  1898. 		end 
  1899. 	elseif (mask) then 
  1900. 		if did1 and did2 and did3 then 
  1901. 			current_checkpoint = M19_checkpoint.final.name 
  1902. 		elseif did1 and did2 then 
  1903. 			current_checkpoint = M19_checkpoint.chem_12_fixed.name 
  1904. 		elseif did2 and did3 then 
  1905. 			current_checkpoint = M19_checkpoint.chem_23_fixed.name 
  1906. 		elseif did1 and did3 then 
  1907. 			current_checkpoint = M19_checkpoint.chem_13_fixed.name 
  1908. 		end 
  1909. 	else 
  1910. 		if did1 and did2 and did3 and M19_mask_finished then 
  1911. 			current_checkpoint = M19_checkpoint.final.name 
  1912. 		elseif did1 and did2 and did3 then 
  1913. 			current_checkpoint = M19_checkpoint.all_no_mask.name 
  1914. 		elseif did1 and did2 then 
  1915. 			current_checkpoint = M19_checkpoint.chem_12.name 
  1916. 		elseif did2 and did3 then 
  1917. 			current_checkpoint = M19_checkpoint.chem_23.name 
  1918. 		elseif did1 and did3 then 
  1919. 			current_checkpoint = M19_checkpoint.chem_13.name 
  1920. 		elseif did3 then 
  1921. 			current_checkpoint = M19_checkpoint.chem_03.name 
  1922. 		elseif did2 then 
  1923. 			current_checkpoint = M19_checkpoint.chem_02.name 
  1924. 		elseif did1 then 
  1925. 			current_checkpoint = M19_checkpoint.chem_01.name 
  1926. 		end 
  1927. 	end 
  1928. 	return current_checkpoint 
  1929. end 
  1930.  
  1931. -- check container to see if the has moved 
  1932. -- separated from found becasue moved == attack 
  1933. -- 
  1934. -- container_table:		(table) container to test 
  1935. -- 
  1936. function m19_moved_container_test(container_table)	 
  1937. 	if (M19_chem_moved_distance < get_dist(container_table.start_nav, container_table.script_mover_name)) then 
  1938. 		container_table.moved = true 
  1939.  
  1940. 		m19_clear_waypoint_target() 
  1941. 		 
  1942. 		-- Ensure there are no makers on the container beforehand 
  1943. 		marker_remove(container_table.script_mover_name) 
  1944. 		marker_add(container_table.script_mover_name, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_ALL) 
  1945. 		waypoint_add(container_table.end_nav) 
  1946. 		marker_add(container_table.end_nav, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_FULL, SYNC_ALL) 
  1947.  
  1948. 		M19_containers_found = M19_containers_found + 1		 
  1949. 		 
  1950. 		if (container_table.brute_group ~= "" and M19_initial_brute_down == false) then 
  1951. 			--make sure the brute if alive sees you 
  1952. 			if (character_is_dead(container_table.brute_group.brute) == false) then 
  1953. 				set_always_sees_player_flag(container_table.brute_group.brute, true) 
  1954. 			end 
  1955. 		end 
  1956. 		 
  1957. 		--Stop the VFX for this container 
  1958. 		if (container_table.vfx.handle ~= -1) then 
  1959. 			effect_stop(container_table.vfx.handle) 
  1960. 			container_table.vfx.handle = -1 
  1961. 		end 
  1962. 		 
  1963. 		-- if (container_table.hiss_id ~= nil) then 
  1964. 			-- audio_stop(container_table.hiss_id) 
  1965. 		-- end 
  1966. 		 
  1967. 		--play an audio line 
  1968. 		m19_play_persona_line(M19_persona_line.blasting_containers) 
  1969. 		 
  1970. 		-- bump up the continuous spawn 
  1971. 		M19_containers_disturbed = M19_containers_disturbed + 1 
  1972. 		m19_adjust_spawning() 
  1973. 	end	 
  1974. end 
  1975.  
  1976. -- Clear any previously set waypoint markers, and then add a marker to the specified container 
  1977. -- 
  1978. -- container:	(table) container to add a marker to 
  1979. -- 
  1980. function m19_set_waypoint_target(container) 
  1981. 	-- Ignore the container if we already have a marker on it 
  1982. 	if M19_waypoint_target ~= "" and M19_waypoint_target.script_mover_name == container.script_mover_name then 
  1983. 		return 
  1984. 	end 
  1985.  
  1986. 	-- Clear any old markers 
  1987. 	m19_clear_waypoint_target() 
  1988. 	 
  1989. 	-- Add the new marker 
  1990. 	M19_waypoint_target = container 
  1991. 	marker_add(container.script_mover_name, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_ALL) 
  1992. end 
  1993.  
  1994. -- Remove any previously set waypoint markers. 
  1995. -- 
  1996. function m19_clear_waypoint_target() 
  1997. 	if M19_waypoint_target == "" then 
  1998. 		return 
  1999. 	end 
  2000.  
  2001. 	-- Only remove the marker if the container hasn't been touched. Otherwise, we want to leave the marker 
  2002. 	-- on the container. 
  2003. 	if not M19_waypoint_target.moved then 
  2004. 		marker_remove(M19_waypoint_target.script_mover_name) 
  2005. 	end 
  2006. 	 
  2007. 	M19_waypoint_target = "" 
  2008. end 
  2009.  
  2010. function m19_get_num_destroyed_containers() 
  2011. 	local destroyed_count = 0 
  2012. 	 
  2013. 	if M19_chemical.container1.complete then 
  2014. 		destroyed_count = destroyed_count + 1 
  2015. 	end 
  2016. 	if M19_chemical.container2.complete then 
  2017. 		destroyed_count = destroyed_count + 1 
  2018. 	end 
  2019. 	if M19_chemical.container3.complete then 
  2020. 		destroyed_count = destroyed_count + 1 
  2021. 	end 
  2022.  
  2023. 	return destroyed_count 
  2024. 	 
  2025. end 
  2026.  
  2027. -- ************************* 
  2028. -- 
  2029. -- Callback functions 
  2030. -- 
  2031. -- ************************* 
  2032.  
  2033. -- Suko died, you lose 
  2034. function m19_failure_suko_died_cb() 
  2035. 	mission_end_failure("m19", "m19_failure_suko_died") 
  2036. end 
  2037.  
  2038. -- Suko abandoned, you lose 
  2039. function m19_failure_suko_abandon_cb() 
  2040. 	hud_critical_timer_stop() 
  2041. 	mission_end_failure("m19", "m19_failure_suko_abandoned") 
  2042. end 
  2043.  
  2044. function m19_island_entrance_cb() 
  2045. 	for i, container in pairs(M19_chemical) do 
  2046. 		mesh_mover_hide(container.script_mover_name) 
  2047. 	end 
  2048. 	M19_trigger.island.hit = true 
  2049. end 
  2050.  
  2051. function m19_doors_freeze_cb() 
  2052. 	while M19_doors_started == false do 
  2053. 		if character_is_in_vehicle(LOCAL_PLAYER) then 
  2054. 			vehicle_freeze(LOCAL_PLAYER, true) 
  2055. 		end 
  2056. 		if character_is_in_vehicle(REMOTE_PLAYER) then 
  2057. 			vehicle_freeze(REMOTE_PLAYER, true) 
  2058. 		end 
  2059. 		thread_yield() 
  2060. 	end 
  2061. 	m19_clear_trigger(M19_trigger.freeze.name) 
  2062. end 
  2063.  
  2064. -- a player has activiated the doors trigger region 
  2065. function m19_doors_cb() 
  2066. 	M19_trigger.doors.hit = true 
  2067. 	m19_clear_trigger(M19_trigger.doors.name) 
  2068. end 
  2069.  
  2070. -- a player has hit the escape trigger 
  2071. function m19_escape1_cb() 
  2072. 	M19_trigger.escape1.hit = true 
  2073. 	m19_clear_trigger(M19_trigger.escape1.name) 
  2074. end 
  2075.  
  2076. function m19_escape2_cb() 
  2077. 	m19_start_convo_thread(M19_convo.jump_truck) 
  2078. 	m19_clear_trigger(M19_trigger.escape2.name) 
  2079. end 
  2080.  
  2081. --spawn the dudes around a specific container 
  2082. function m19_chem_01_spawn_cb(player, trigger) 
  2083. 	local setup_container = M19_chemical.container1 
  2084. 	if (setup_container.complete == false ) then 
  2085. 		group_create(setup_container.zombies) 
  2086. 		if (setup_container.brute_group ~= "" and M19_initial_brute_down == false) then 
  2087. 			group_create(setup_container.brute_group.name) 
  2088. 			on_detection(setup_container.brute_group.detection_callback, setup_container.brute_group.brute) 
  2089. 			on_death(setup_container.brute_group.death_callback, setup_container.brute_group.brute) 
  2090. 		end 
  2091. 	end 
  2092. 	m19_clear_trigger(trigger) 
  2093. end 
  2094.  
  2095. function m19_chem_02_spawn_cb(player, trigger) 
  2096. 	local setup_container = M19_chemical.container2 
  2097. 	if (setup_container.complete == false) then 
  2098. 		group_create(setup_container.zombies) 
  2099. 		if (setup_container.brute_group ~= "" and M19_initial_brute_down == false) then 
  2100. 			group_create(setup_container.brute_group.name) 
  2101. 			on_detection(setup_container.brute_group.detection_callback, setup_container.brute_group.brute) 
  2102. 			on_death(setup_container.brute_group.death_callback, setup_container.brute_group.brute) 
  2103. 		end 
  2104. 	end 
  2105. 	m19_clear_trigger(trigger) 
  2106. end 
  2107.  
  2108. function m19_chem_03_spawn_cb(player, trigger) 
  2109. 	local setup_container = M19_chemical.container3 
  2110. 	if (setup_container.complete == false) then 
  2111. 		group_create(setup_container.zombies) 
  2112. 		if (setup_container.brute_group ~= "" and M19_initial_brute_down == false) then 
  2113. 			group_create(setup_container.brute_group.name) 
  2114. 			on_detection(setup_container.brute_group.detection_callback, setup_container.brute_group.brute) 
  2115. 			on_death(setup_container.brute_group.death_callback, setup_container.brute_group.brute) 
  2116. 		end 
  2117. 	end 
  2118. 	m19_clear_trigger(trigger) 
  2119. end 
  2120.  
  2121. -- determine a chemical container is in the water 
  2122. function m19_container_in_water_cb(mover_name) 
  2123. 	-- find the container 
  2124. 	for i, container in pairs(M19_chemical) do 
  2125. 		if container.script_mover_name == mover_name then 
  2126. 			--message("Container neutralized", 10.0) 
  2127. 			container.complete = true 
  2128. 			container.moved = true 
  2129. 			 
  2130. 			--play sound 
  2131. 			--audio_object_post_event("m19_sfx_virus_tank_splash", nil, nil, container.script_mover_name) 
  2132. 			effect_play_on_script_object(M19_container_splash_effect, container.script_mover_name) 
  2133. 			-- clean up any container stuff 
  2134. 			m19_clear_container(container) 
  2135. 			 
  2136. 			-- play amusing audio line 
  2137. 			m19_play_container_destroyed_audio() 
  2138. 			 
  2139. 			-- Remove the callback so m19_mover_destroyed_cb() doesn't get called  
  2140. 			on_mover_destroyed("", container.script_mover_name) 
  2141. 			marker_remove(container.end_nav, SYNC_ALL) 
  2142. 			 
  2143. 			delay(1) 
  2144. 			 
  2145. 			-- destroy the container mesh 
  2146. 			mesh_mover_set_damaged_by_player_only(container.script_mover_name, false) 
  2147. 			mesh_mover_kill(container.script_mover_name) 
  2148. 		end 
  2149. 	end 
  2150. end 
  2151.  
  2152. function m19_mover_destroyed_cb(mover_name) 
  2153. 	mission_end_failure("m19", "m19_failure_container_destroyed") 
  2154. end 
  2155.  
  2156. -- Someone has entered the chemical truck 
  2157. function m19_player_in_chem_truck_cb(player, vehicle) 
  2158. 	-- if player == LOCAL_PLAYER then 
  2159. 		M19_decision.took_chem_truck = true 
  2160. 	-- end 
  2161. end 
  2162.  
  2163. -- The chemical truck fell into the water 
  2164. function m19_chem_truck_in_water() 
  2165. 	M19_decision.chem_truck_in_water = true 
  2166. 	on_vehicle_destroyed("", M19_group.chem_truck.vehicle) 
  2167. end 
  2168.  
  2169. --viola rescue callbacks 
  2170. function m19_dumpster_cb() 
  2171. 	-- Clear the trigger 
  2172. 	m19_clear_trigger(M19_trigger.dumpster.name) 
  2173. 	-- Notify script that we reached the trigger 
  2174. 	M19_trigger.dumpster.hit = true 
  2175. end 
  2176.  
  2177. function m19_roof_cb() 
  2178. 	-- Clear the trigger 
  2179. 	m19_clear_trigger(M19_trigger.roof.name) 
  2180. 	-- Notify script that we reached the trigger 
  2181. 	M19_trigger.roof.hit = true 
  2182. end 
  2183.  
  2184. function m19_mask_trigger_enter_cb(player) 
  2185. 	M19_trigger.rim_jobs.inside = M19_trigger.rim_jobs.inside + 1 
  2186. end 
  2187.  
  2188. function m19_mask_trigger_exit_cb(player) 
  2189. 	M19_trigger.rim_jobs.inside = M19_trigger.rim_jobs.inside - 1 
  2190. end 
  2191.  
  2192.  
  2193. function get_to_rimjobs_cb() 
  2194. 	mission_end_failure("m19", "m19_failure_rimjobs_timer") 
  2195. end 
  2196.  
  2197. function m19_open_rimjobs_cb(player) 
  2198. 	--ai_do_scripted_move(LOCAL_PLAYER, M19_nav.rimjobs_door_open_point, true) 
  2199. 	door_lock(M19_rim_jobs_new_door, false) 
  2200. 	door_open(M19_rim_jobs_new_door, false, true, player, "M19 Open Garage Door", M19_nav.rimjobs_door_open_point.name) 
  2201. 	--action_play(player, "M19 Open Garage Door") 
  2202. 	m19_clear_trigger(M19_trigger.rim_jobs_door.name) 
  2203. end 
  2204.  
  2205.  
  2206. function m19_brute_02_cb() 
  2207. 	--play a line 
  2208. 	delay(5) 
  2209. 	m19_play_persona_line(M19_persona_line.see_zombie) 
  2210. 	--kill other brute 
  2211. 	on_death("", M19_group.chem_03_brute.brute) 
  2212. 	if (character_exists(M19_group.chem_03_brute.brute)) then 
  2213. 		character_kill(M19_group.chem_03_brute.brute) 
  2214. 	end 
  2215. 	--remove callbacks 
  2216. 	on_detection("", M19_group.chem_02_brute.brute) 
  2217. 	on_detection("", M19_group.chem_03_brute.brute) 
  2218. 	M19_initial_brute_down = true 
  2219. end 
  2220.  
  2221. function m19_brute_03_cb() 
  2222. 	--play a line 
  2223. 	delay(5) 
  2224. 	m19_play_persona_line(M19_persona_line.see_zombie) 
  2225. 	--kill other brute 
  2226. 	on_death("", M19_group.chem_02_brute.brute) 
  2227. 	if (character_exists(M19_group.chem_02_brute.brute)) then 
  2228. 		character_kill(M19_group.chem_02_brute.brute) 
  2229. 	end 
  2230. 	--remove callbacks 
  2231. 	on_detection("", M19_group.chem_02_brute.brute) 
  2232. 	on_detection("", M19_group.chem_03_brute.brute) 
  2233. 	M19_initial_brute_down = true 
  2234. end 
  2235.  
  2236. function m19_first_brute_dead_cb(char) 
  2237. 	m19_adjust_spawning() 
  2238. 	on_death("", char) 
  2239. end 
  2240.  
  2241. function m19_finish_phonecall_cb() 
  2242. 	M19_phonecall_finished = true 
  2243. end 
  2244. -- ************************* 
  2245. -- 
  2246. -- Thread functions 
  2247. -- 
  2248. -- ************************* 
  2249.  
  2250. -- Find the closest container or container area and set a waypoint to it 
  2251. function m19_nav_to_closest_thread() 
  2252. 	while true do 
  2253. 		-- If a container has been moved, but it still hasn't been pushed into the water, the container will have 
  2254. 		-- a marker on it. Wait until the container is neutralized before we point out another container. 
  2255. 		local player_moving_container = true 
  2256. 		while player_moving_container do 
  2257. 			player_moving_container = false 
  2258. 		 
  2259. 			for i, container in pairs(M19_chemical) do 
  2260. 				while not container.complete and container.moved do 
  2261. 					thread_yield() 
  2262. 					player_moving_container = true 
  2263. 				end 
  2264. 			end 
  2265. 		end 
  2266. 		 
  2267. 		-- Find the closest non-moved container 
  2268. 		local closest = "" 
  2269. 		local closest_dist = M19_NOT_CLOSE_DISTANCE 
  2270. 		for i, container in pairs(M19_chemical) do 
  2271. 			if not container.moved then 
  2272. 				local dist = get_dist(LOCAL_PLAYER, container.script_mover_name) 
  2273. 				if dist < closest_dist then 
  2274. 					closest_dist = dist 
  2275. 					closest = container 
  2276. 				end 
  2277. 			end 
  2278. 		end 
  2279. 		 
  2280. 		-- If we did not find a near by container, they have all been found.  
  2281. 		if closest == "" then 
  2282. 			break 
  2283. 		end 
  2284.  
  2285. 		-- Set the waypoint target to the closest container. This will clear the old marker for us as well. 
  2286. 		m19_set_waypoint_target(closest) 
  2287.  
  2288. 		-- don't update this so often 
  2289. 		delay(1.0) 
  2290. 	end 
  2291. 	 
  2292. 	M19_closest_container_thread = INVALID_THREAD_HANDLE 
  2293. end 
  2294.  
  2295. -- determine if a container has been moved or found 
  2296. --  
  2297. function m19_container_moved_or_found_thread() 
  2298. 	local all_complete = false 
  2299. 	while not all_complete do 
  2300. 		all_complete = true 
  2301. 		for i, container in pairs(M19_chemical) do 
  2302. 			if not container.complete and not container.moved then 
  2303. 				all_complete = false 
  2304. 				thread_yield()	-- test over multiple frames 
  2305. 				m19_moved_container_test(container) 
  2306. 			end 
  2307. 		end 
  2308.  
  2309. 		thread_yield() 
  2310. 	end 
  2311. 	 
  2312. 	M19_moved_or_found_thread = INVALID_THREAD_HANDLE 
  2313. end 
  2314.  
  2315. --keep track of players being out of the trigger area and abandoning viola 
  2316. function m19_handle_mask_trigger_thread() 
  2317. 	local num_players = 1 
  2318. 	if (coop_is_active()) then 
  2319. 		num_players = 2 
  2320. 	end 
  2321. 	local players_inside = true 
  2322. 	while (true) do 
  2323. 		if (players_inside == true) then 
  2324. 			if(M19_trigger.rim_jobs.inside < num_players) then 
  2325. 				players_inside = false 
  2326. 				--start a warning and fail chance 
  2327. 				hud_critical_timer_set(10000, "m19_obj_protect_viola", "m19_failure_suko_abandon_cb") 
  2328. 			end 
  2329. 		else 
  2330. 			if(M19_trigger.rim_jobs.inside == num_players) then 
  2331. 				players_inside = true 
  2332. 				--kill the warning and fail chance 
  2333. 				hud_critical_timer_stop() 
  2334. 			end 
  2335. 		end 
  2336. 		thread_yield() 
  2337. 	end 
  2338. end 
  2339.  
  2340. --handle the player being out of the trigger area during the fix the mask section 
  2341. function m19_out_of_mask_trigger_thread() 
  2342. 	--objective_text(0, "get to back to Viola!") 
  2343. 	m19_set_trigger(M19_trigger.rim_jobs.name, "m19_mask_trigger_return_cb", true) 
  2344. 	--message("Get back to rim jobs!") 
  2345. 	hud_critical_timer_set(10000, "m19_obj_protect_viola") 
  2346. 	 
  2347. 	delay(10.0) 
  2348. 	hud_critical_timer_stop() 
  2349. 	--mission_end_failure("m19", "m19_failure_suko_abandoned") 
  2350. end 
  2351.  
  2352. function m19_flaming_brute_thread() 
  2353. 	delay(1) 
  2354. 	m19_play_persona_line(M19_persona_line.brute_on_fire) 
  2355. 	while (get_dist_closest_player_to_object(M19_group.flaming_brute.brute) > 5.0) do 
  2356. 		thread_yield() 
  2357. 	end 
  2358. 	 
  2359. 	--kill the brute 
  2360. 	character_kill(M19_group.flaming_brute.brute) 
  2361. 	m19_play_persona_line(M19_persona_line.brute_on_fire_dead) 
  2362. 	M19_brute_flame_thread = INVALID_THREAD_HANDLE 
  2363. end 
  2364.  
  2365. function m19_player_health_thread(player) 
  2366. 	local over_half = true 
  2367. 	local over_quarter = true 
  2368. 	local max_health = get_max_hit_points(player) 
  2369. 	while (true) do 
  2370. 		local current_health = get_current_hit_points(player) 
  2371. 		local ratio = current_health / max_health 
  2372. 		if (ratio > 0.5) then 
  2373. 			--over half health 
  2374. 			if(over_half == false) then 
  2375. 				over_half = true 
  2376. 				over_quarter = true 
  2377. 				audio_object_post_event("m19_sfx_gas_mask_normal", nil, nil, player) 
  2378. 			end 
  2379. 		elseif (ratio > 0.25) then 
  2380. 			if(over_quarter == false or over_half == true) then 
  2381. 				over_half = false 
  2382. 				over_quarter = true 
  2383. 				audio_object_post_event("m19_sfx_gas_mask_sprint", nil, nil, LOCAL_PLAYER) 
  2384. 			end 
  2385. 		else 
  2386. 			if(over_quarter == true or over_half == true) then 
  2387. 				over_half = false 
  2388. 				over_quarter = false 
  2389. 				audio_object_post_event("m19_sfx_gas_mask_panic", nil, nil, LOCAL_PLAYER) 
  2390. 			end 
  2391. 		end 
  2392. 		delay(2) 
  2393. 	end 
  2394.  
  2395. end 
  2396.  
  2397.  
  2398.  
  2399.  
  2400.  
  2401.  
  2402.  
  2403.  
  2404.  
  2405.  
  2406.  
  2407.  
  2408.  
  2409.  
  2410.  
  2411.  
  2412.  
  2413.  
  2414.  
  2415.  
  2416. -- Plays a conversation 
  2417. -- 
  2418. -- convo: Conversation to play 
  2419. function m19_play_convo(convo) 
  2420. 	if convo.name ~= "" and convo.name ~= nil then 
  2421. 		--local msg_handle = message("Playing Convo: " .. convo.name, 99999999.0) 
  2422. 		if(convo.phonecall == true) then 
  2423. 			M19_phonecall_finished = false 
  2424. 			convo.handle = INVALID_CONVERSATION_HANDLE 
  2425. 			audio_play_for_mission_cellphone(convo.name , convo.recieveing , true, "", "m19_finish_phonecall_cb") 
  2426. 			while (M19_phonecall_finished == false) do 
  2427. 				thread_yield() 
  2428. 			end 
  2429. 			convo.handle = nil 
  2430. 		else 
  2431. 			convo.handle = audio_conversation_load(convo.name) 
  2432. 			audio_conversation_play(convo.handle) 
  2433.  
  2434. 			audio_conversation_wait_for_end(convo.handle) 
  2435.  
  2436. 			convo.handle = nil 
  2437. 		end 
  2438. 		--message_remove(msg_handle) 
  2439. 	end 
  2440.  
  2441. 	if convo.delay ~= nil and convo.delay > 0.01 then 
  2442. 		delay(convo.delay) 
  2443. 	end 
  2444. end 
  2445.  
  2446. -- Unloads a conversation 
  2447. -- 
  2448. -- convo: Conversation to unload 
  2449. function m19_unload_convo(convo) 
  2450. 	if convo.handle == nil then 
  2451. 		return 
  2452. 	end 
  2453.  
  2454. 	audio_conversation_end(convo.handle) 
  2455. 	convo.handle = nil 
  2456. end 
  2457.  
  2458. -- Unloads all conversations from the convo table 
  2459. -- 
  2460. function m19_unload_all_convos() 
  2461. 	for convo_key, convo_set in pairs(M19_convo) do 
  2462. 		m19_unload_convo_set(convo_set) 
  2463.  
  2464. 		if convo_set.thread ~= INVALID_THREAD_HANDLE then 
  2465. 			thread_kill(convo_set.thread) 
  2466. 		end 
  2467. 	end 
  2468. end 
  2469.  
  2470. -- Iterates through a table of conversations and plays them. 
  2471. -- 
  2472. -- convo_set: Table of conversations 
  2473. -- 
  2474. function m19_play_convo_set(convo_set) 
  2475. 	for key, convo in pairs(convo_set.files) do 
  2476. 		m19_play_convo(convo) 
  2477. 	end 
  2478. end 
  2479.  
  2480. -- Unloads a convo table (array) 
  2481. -- 
  2482. -- convo_set Table of conversations to unload 
  2483. -- 
  2484. function m19_unload_convo_set(convo_set) 
  2485. 	for key, convo in pairs(convo_set.files) do 
  2486. 		m19_unload_convo(convo) 
  2487. 	end 
  2488. end 
  2489.  
  2490. -- Starts an audio conversation as a thread 
  2491. -- 
  2492. -- convo_table: Conversation to play 
  2493. -- 
  2494. function m19_start_convo_thread(convo_table) 
  2495. 	if M19_active_convo ~= "" then 
  2496. 		m19_unload_convo_set(M19_active_convo) 
  2497. 		M19_active_convo = "" 
  2498. 	end 
  2499. 	convo_table.thread = thread_new("m19_audio_thread", convo_table) 
  2500. end 
  2501.  
  2502. -- Loads the necessary 2D personas for the heli rail sequence 
  2503. -- 
  2504. function m19_load_personas() 
  2505. 	for key, persona in pairs(M19_personas) do 
  2506. 		persona.handle = audio_persona_load_2d(persona.name) 
  2507. 	end 
  2508. end 
  2509.  
  2510. -- Unloads all 2d personas 
  2511. -- 
  2512. function m19_unload_personas() 
  2513. 	for key, persona in pairs(M19_personas) do 
  2514. 		if persona.handle ~= INVALID_PERSONA_HANDLE then 
  2515. 			audio_persona_remove_2d(persona.handle) 
  2516. 			persona.handle = INVALID_PERSONA_HANDLE 
  2517. 		end 
  2518. 	end 
  2519. end 
  2520.  
  2521. -- Gets the 2d persona handle from a character name 
  2522. -- 
  2523. function m19_get_persona_handle(line) 
  2524. 	for key, persona in pairs(M19_personas) do 
  2525. 		if persona.name == line.character then 
  2526. 			return persona.handle 
  2527. 		end 
  2528. 	end 
  2529.  
  2530. 	return nil 
  2531. end 
  2532.  
  2533. -- Plays a persona line. 
  2534. -- 
  2535. function m19_play_persona_line(line) 
  2536. 	local convo_active = true 
  2537. 	while(M19_active_convo ~= "" and convo_active == true) do 
  2538. 		convo_active = false 
  2539. 		for key, convo in pairs(M19_active_convo.files) do 
  2540. 			if (convo.handle ~= nil) then 
  2541. 				convo_active = true 
  2542. 			end 
  2543. 		end 
  2544. 		thread_yield() 
  2545. 	end 
  2546.  
  2547. 	if line.play_2d then 
  2548. 		audio_play_persona_line_2d(m19_get_persona_handle(line), line.name) 
  2549. 	else 
  2550. 		audio_play_persona_line(line.character, line.name) 
  2551. 	end 
  2552. end 
  2553.  
  2554.  
  2555.  
  2556. -- Play a audio conversation 
  2557. -- 
  2558. -- convo_table: Table of the audio conversation files to play 
  2559. -- 
  2560. function m19_audio_thread(convo_table) 
  2561. 	M19_active_convo = convo_table 
  2562. 	m19_play_convo_set(convo_table) 
  2563. 	convo_table.thread = INVALID_THREAD_HANDLE 
  2564. 	M19_active_convo = "" 
  2565. end 
  2566.