./m20.lua

  1.  
  2. --[[ 
  3. 	m20.lua 
  4. 	SR3 Mission Script 
  5. 	DATE: 8/23/2010 
  6. 	AUTHOR:	Nick Heilmann 
  7. ]]-- 
  8.  
  9.  
  10. HELI_DEFAULT_SPEED = 45 
  11. HELI_HIGH_SPEED = 90 
  12. VEHICLE_SEAT_DRIVER = 0 
  13. VEHICLE_SEAT_PASSENGER = 1 
  14. VEHICLE_SEAT_HELI_BACK_DOOR = 2 
  15. VEHICLE_SEAT_WRESTLER_BACK_SEAT = 3 
  16. PEDS_TO_HIT = 15 
  17. M20_LW_APPROACH_DIST = 50 
  18. M20_CTH_FLEE_DIST = 150 
  19. M20_CTH_CRASH_DIST = 10 
  20. M20_RC_RANGE = 500		-- default is currently 200 
  21. M20_ANGEL_MAX_BANK = 12		-- degrees 
  22.  
  23. -- Debug flags -- 
  24.  
  25. 	M20_DEBUG = { 
  26. 		infinity = 999999999, 
  27. 	} 
  28.  
  29. -- Tweakable Parameters -- 
  30.  
  31. 	M20_status = { 
  32. 		gym_reached = false, 
  33. 		boat_reached = false, 
  34. 		player_has_rc_vehicle = false, 
  35. 		rc_car_destroyed = false, 
  36. 		rc_car_peds_hit = 0, 
  37. 		rc_boat_destroyed = false, 
  38. 		rc_tank_destroyed = false, 
  39. 		beach_party_crashed = false, 
  40. 		circular_path_reached = false, 
  41. 		wrestler_heli_destroyed = false, 
  42. 		stag_tanks_remaining = 0, 
  43. 		my_rc_boat = nil, 
  44. 	} 
  45.  
  46. -- Weapons -- 
  47.  
  48. 	M20_weapon = { 
  49. 		rc_gun = "Special-RCVehicleGun", 
  50.  
  51. 		cleanup = { "Special-RCVehicleGun" }, 
  52. 	} 
  53.  
  54. -- Camera Navpoints -- 
  55.  
  56. 	M20_cam_nav = { 
  57. 		rc_car = { "Nav Cam RC Car 001", "Nav Cam RC Car 002" }, 
  58. 		beach = { "Nav Beach Cam 001", "Nav Beach Cam 002" }, 
  59. 	} 
  60.  
  61. -- Navpoints -- 
  62. 	M20_navpoint = { 
  63. 		cp_starts = { 
  64. 			mission_start = { player_local = "Nav CP Mission Start Local", player_remote = "Nav CP Mission Start Remote" }, 
  65. 			crash_the_car = { player_local = "Nav CP CTC Local", player_remote = "Nav CP CTC Remote" }, 
  66. 			crash_the_boat = { player_local = "Nav CP CTB Local", player_remote = "Nav CP CTB Remote" }, 
  67. 			crash_the_heli = { player_local = "Nav CP CTH Local", player_remote = "Nav CP CTH Remote" }, 
  68. 			airport = { player_local = "Nav CP LW Local", player_remote = "Nav CP LW Remote" }, 
  69. 		}, 
  70.  
  71. 		angel_heli_float = { 
  72. 			bar = "Nav Heli Float Bar", 
  73. 			bar_coop = "Nav Heli Mission Start Coop", 
  74. 			gym = "Nav Heli Float Gym", 
  75. 			boat = "Nav Heli Float Boat", 
  76. 			heli = "Nav Heli Float Heli", 
  77. 			airport = "Nav Heli Float Airport", 
  78. 		}, 
  79.  
  80. 		angel_heli_teleport = { 
  81. 			bar = "Nav Heli Teleport Bar", 
  82. 			bar_coop = "Nav Heli Mission Start Coop", 
  83. 			gym = "Nav Heli Teleport Gym", 
  84. 			boat = "Nav Heli Teleport Boat", 
  85. 			heli = "Nav Heli Teleport Heli", 
  86. 			airport = "Nav Heli Teleport Airport", 
  87. 		}, 
  88.  
  89. 		gas_station = "Nav Gas Station", 
  90.  
  91. 		beach_party = "Nav Beach Party", 
  92.  
  93. 		ramp = "Nav Ramp", 
  94.  
  95. 		tourist_heli_rand = { "Nav Heli Rand 001<001>", "Nav Heli Rand 002<001>", "Nav Heli Rand 003<001>", "Nav Heli Rand 004<001>", "Nav Heli Rand 005<001>", "Nav Heli Rand 006<001>", 
  96. 												"Nav Heli Rand 007<001>", "Nav Heli Rand 008<001>", "Nav Heli Rand 009<001>", "Nav Heli Rand 010<001>", "Nav Heli Rand 011<001>", "Nav Heli Rand 012<001>" }, 
  97.  
  98. 		wrestler_heli_rand = { "Nav Heli Rand 001", "Nav Heli Rand 002", "Nav Heli Rand 003", "Nav Heli Rand 004", "Nav Heli Rand 005", "Nav Heli Rand 006", 
  99. 													"Nav Heli Rand 007", "Nav Heli Rand 008", "Nav Heli Rand 009", "Nav Heli Rand 010", "Nav Heli Rand 011", "Nav Heli Rand 012" }, 
  100.  
  101. 		wrestler_teleport = "Nav Wrestler Teleport", 
  102. 		rc_heli_teleport = "Nav RC Heli Teleport", 
  103.  
  104. 		airport_lw_approach = "Nav Approach LW Plane <001>", 
  105.  
  106. 		end_local = "Nav End Local", 
  107. 		end_remote = "Nav End Remote", 
  108. 		 
  109. 		success_local = "Nav Success Local", 
  110. 		success_remote = "Nav Success Remote", 
  111. 	} 
  112.  
  113. -- Scripted Paths -- 
  114. 	M20_scripted_path = { 
  115. 		angel_enter = "SP Angel Enter", 
  116. 		heli_to_gym = "SP Heli To Gym", 
  117. 		heli_to_boat = "SP Heli To Boat", 
  118. 		heli_to_heli = "SP Heli to Heli", 
  119. 		heli_to_airport = "SP Heli To Airport", 
  120. 		heli_around_airport = "SP Heli Around Airport", 
  121.  
  122. 		cth_target_flee_paths = { 
  123. 			[ 1 ] = { sp_name = "SP CTH Flee Path <001>", n = { 6, 7 }, }, 
  124. 			[ 2 ] = { sp_name = "SP CTH Flee Path <002>", p = { -3, -4, -8 }, n = { 9 }, }, 
  125. 			[ 3 ] = { sp_name = "SP CTH Flee Path <003>", p = { -5 }, n = { 2, -4, -8 }, super_slow = true, }, 
  126. 			[ 4 ] = { sp_name = "SP CTH Flee Path <004>", p = { 5, -6 }, n = { 2, -3, -8 }, super_slow = true, }, 
  127. 			[ 5 ] = { sp_name = "SP CTH Flee Path <005>", p = { 4, -6 }, n = { 3 }, }, 
  128. 			[ 6 ] = { sp_name = "SP CTH Flee Path <006>", p = { 7 }, n = { 4, 5 }, }, 
  129. 			[ 7 ] = { sp_name = "SP CTH Flee Path <007>", p = { 6 }, n = { -9, 8 }, super_slow = true, }, 
  130. 			[ 8 ] = { sp_name = "SP CTH Flee Path <008>", p = { -9, -7 }, n = { 2, -3, -4 }, }, 
  131. 			[ 9 ] = { sp_name = "SP CTH Flee Path <009>", p = { -2 }, n = {  -7, 8 }, super_slow = true, }, 
  132. 		}, 
  133.  
  134. 		airport_wrestler_flee_paths = { 
  135. 			[ 1 ] = 		{ sp_name = "SP Wrestler Flee<001>", p = { 8, 10 }, n = { 2, 9, 11 } }, 
  136. 			[ 2 ] = 		{ sp_name = "SP Wrestler Flee<002>", p = { -1, 9, 11 },  n = { 3 } }, 
  137. 			[ 3 ] = 		{ sp_name = "SP Wrestler Flee<003>", p = { -2 },  n = { 4, 5 } }, 
  138. 			[ 4 ] = 		{ sp_name = "SP Wrestler Flee<004>", p = { -3, 5 },  n = { -6, -7, 8, -11 } }, 
  139. 			[ 5 ] = 		{ sp_name = "SP Wrestler Flee<005>", p = { -3, 4 },  n = { 6, 7 } }, 
  140. 			[ 6 ] = 		{ sp_name = "SP Wrestler Flee<006>", p = { -5, 7 },  n = { -7, 8, -11 } }, 
  141. 			[ 7 ] = 		{ sp_name = "SP Wrestler Flee<007>", p = { -5, 6 },  n = { -4, -6, 8, -11 } }, 
  142. 			[ 8 ] = 		{ sp_name = "SP Wrestler Flee<008>", p = { -4, -6, -7, -11 },  n = { 1, -10 } }, 
  143. 			[ 9 ] = 		{ sp_name = "SP Wrestler Flee<009>", p = { -1, 2,  11 },  n = { 10 } }, 
  144. 			[ 10 ] =	{ sp_name = "SP Wrestler Flee<010>", p = { -9 },  n = { 1, -8 } }, 
  145. 			[ 11 ] =	{ sp_name = "SP Wrestler Flee<011>", p = { -1, 2, 9, 11 },  n = { -4, -6, -7, 8 } }, 
  146. 		}, 
  147. 	} 
  148.  
  149. -- Triggers -- 
  150.  
  151. 	M20_trigger = { 
  152. 		gym = "Trigger Gym", 
  153. 		boat = "Trigger Boat", 
  154. 		beach_party = "Trigger Beach Party", 
  155. 		circular_path = "Trigger Circular Path", 
  156. 		tank_path = "Trigger Tank Path", 
  157. 		gas_station = { 
  158. 			"Trigger Gas Station<001>", "Trigger Gas Station<002>", "Trigger Gas Station<003>",  
  159. 			"Trigger Gas Station<004>", "Trigger Gas Station<005>", "Trigger Gas Station<006>",  
  160. 		} 
  161. 	} 
  162.  
  163. --[[ Items -- 
  164.  
  165. 	M20_item = { 
  166. 	} 
  167.  
  168. ]]-- Characters -- 
  169.  
  170. 	M20_char = { 
  171. 		angel = "NPC Angel MS", 
  172. 		car_target = { "NPC Car Target 001", "NPC Car Target 002", "NPC Car Target 003" }, 
  173. 		rc_car = { "NPC RC Car Driver", "NPC RC Car Passenger" }, 
  174. 		rc_boat = { "NPC RC Boat Driver 001", "NPC RC Boat Driver 002", "NPC RC Boat Driver 003" }, 
  175. 		rc_heli = "NPC RC Heli Driver", 
  176. 		beach_wrestler = "NPC Wrestler Beach", 
  177. 		wrestler = "NPC Heli Wrestler", 
  178. 		pilot = "NPC Heli Pilot", 
  179. 		stag_tank = { 
  180. 			"NPC STAG Tank 001", "NPC STAG Tank 002", "NPC STAG Tank 003", "NPC STAG Tank 004", 
  181. 			"NPC STAG Tank 005", "NPC STAG Tank 006", "NPC STAG Tank 007", "NPC STAG Tank 008", 
  182. 			"NPC STAG Tank 009", "NPC STAG Tank 010", "NPC STAG Tank 011", "NPC STAG Tank 012", 
  183. 			"NPC STAG Tank 013", "NPC STAG Tank 014", 
  184. 			"NPC STAG Tank 003<001>", "NPC STAG Tank 004<001>", "NPC STAG Tank 005<001>", "NPC STAG Tank 006<001>", 
  185. 			"NPC STAG Tank 007<001>", "NPC STAG Tank 008<001>", "NPC STAG Tank 009<001>", "NPC STAG Tank 010<001>", 
  186. 			"NPC STAG Tank 011<001>", "NPC STAG Tank 012<001>", 
  187. 		}, 
  188. 		stag_tank_driver = "NPC STAG Tank Driver", 
  189. 		last_wrestler = "NPC Last Wrestler", 
  190. 		mascots = { 
  191. 		 { "NPC Mascot<001>", "NPC Mascot<002>", "NPC Mascot<003>", "NPC Mascot<004>", }, 
  192. 		 { "NPC Mascot<005>", "NPC Mascot<006>", "NPC Mascot<007>", "NPC Mascot<008>", }, 
  193. 		}, 
  194. 	} 
  195.  
  196. -- Vehicles -- 
  197.  
  198. 	M20_vehicle = { 
  199. 		angel_heli = "Veh Angel Heli MS", 
  200. 		rc_car = "Veh RC Car", 
  201. 		rc_boat = { "Veh RC Boat 001", "Veh RC Boat 002", "Veh RC Boat 003" }, 
  202. 		rc_heli = "Veh RC Heli", 
  203. 		beach_party = { "Veh Beach Party 001", "Veh Beach Party 002", "Veh Beach Party 003", "Veh Beach Party 007" }, 
  204. 		wrestler = "Veh Heli Wrestler", 
  205. 		stag_tank = { "Veh STAG Tank 001", "Veh STAG Tank 002", "Veh STAG Tank 003", "Veh STAG Tank 004", "Veh STAG Tank 005", "Veh STAG Tank 006" , "Veh STAG Tank 007" }, 
  206. 		lw_plane = "Veh LW Plane", 
  207. 		lw_truck = "Veh Last Wrestler Truck" 
  208. 	} 
  209.  
  210. -- Groups -- 
  211.  
  212. 	M20_group = { 
  213. 		angel = { name = "GRP Angel MS", chars = { M20_char.angel }, vehicles = { M20_vehicle.angel_heli } }, 
  214. 		car_target = { name = "GRP Car Targets", chars = { M20_char.car_target } }, 
  215. 		rc_car = { name = "GRP RC Car", chars = M20_char.rc_car, vehicles = { M20_vehicle.rc_car } }, 
  216. 		rc_boat = { name = "GRP RC Boat", chars = M20_char.rc_boat, vehicles = M20_vehicle.rc_boat }, 
  217. 		rc_heli = { name = "GRP RC Heli", chars = { M20_char.rc_heli }, vehicles = { M20_vehicle.rc_heli } }, 
  218. 		beach_party = { name = "GRP Beach Party", chars = { M20_char.beach_wrestler }, vehicles = { M20_vehicle.beach_party } }, -- Bunch of NPCs and vehicles, but we don't really care about (most of) them 
  219. 		wrestler = { name = "GRP Heli Wrestler", chars = { M20_char.wrestler, M20_char.pilot, }, vehicles = { M20_vehicle.wrestler } }, 
  220. 		stag_tank = { name = "GRP STAG Tank", chars = M20_char.stag_tank, vehicles = M20_vehicle.stag_tank }, 
  221. 		airport = { name = "GRP Airport", chars = {  }, vehicles = { M20_vehicle.lw_plane } }, 
  222. 		last_wrestler = { name = "GRP Last Wrestler", chars = { M20_char.last_wrestler }, vehicles = {  } }, 
  223. 		airport_tank_driver = { name = "GRP STAG Tank Driver", chars = { M20_char.stag_tank_driver }, vehicles = { } }, 
  224. 		mascots = { 
  225. 			{ name = "GRP Mascots 01", chars = M20_char.mascots[ 1 ], }, 
  226. 			{ name = "GRP Mascots 02", chars = M20_char.mascots[ 2 ], }, 
  227. 		}, 
  228. 	} 
  229.  
  230. 	-- tracks the peds that have been hit during the "crash the peds" objective 
  231. 	M20_peds_hit = { } 
  232.  
  233. 	M20_convo_queue = { } 
  234.  
  235. 	M20_previous_rc_range = 0 
  236.  
  237. --[[ Spawn Groups -- 
  238.  
  239. 	M20_spawn_group = { 
  240. 	} 
  241.  
  242. -- Spawn Regions -- 
  243.  
  244. 	M20_spawn_region = { 
  245. 	} 
  246.  
  247. ]]-- Threads -- 
  248.  
  249. 	M20_thread = { 
  250. 		angel_heli_float = INVALID_THREAD_HANDLE, 
  251. 		angel_enter_phone_call = INVALID_THREAD_HANDLE, 
  252. 		viola_phone_call_to_gym = INVALID_THREAD_HANDLE, 
  253. 		player_tells_angel_plan = INVALID_THREAD_HANDLE, 
  254. 		fly_to_gym = INVALID_THREAD_HANDLE, 
  255. 		fly_to_boat = INVALID_THREAD_HANDLE, 
  256. 		wait_for_enter = INVALID_THREAD_HANDLE, 
  257. 		rc_car_enter = { }, 
  258. 		beach_party_polling = INVALID_THREAD_HANDLE, 
  259. 		boat_flipped_watchdog = INVALID_THREAD_HANDLE, 
  260. 		boat_on_land_watchdog = INVALID_THREAD_HANDLE, 
  261. 		crash_the_helicopter_convo = INVALID_THREAD_HANDLE, 
  262. 		follow_rc_vehicle = INVALID_THREAD_HANDLE, 
  263. 		heli_rand_flying = INVALID_THREAD_HANDLE, 
  264. 		heli_to_heli = INVALID_THREAD_HANDLE, 
  265. 		one_last_wrestler = INVALID_THREAD_HANDLE, 
  266. 		starting_convos = INVALID_THREAD_HANDLE, 
  267. 		airport_lw_behavior = INVALID_THREAD_HANDLE, 
  268. 		convo_manager = INVALID_THREAD_HANDLE, 
  269. 		airport_attack_player = INVALID_THREAD_HANDLE, 
  270. 	} 
  271.  
  272. -- Checkpoints -- 
  273.  
  274. 	--M20_CHECKPOINT_MISSION_START = MISSION_START_CHECKPOINT -- defined in ug_lib.lua 
  275. 	M20_CHECKPOINT_CRASH_THE_CAR = "ctc" 
  276. 	M20_CHECKPOINT_CRASH_THE_BOAT = "ctb" 
  277. 	M20_CHECKPOINT_CRASH_THE_HELI = "cth" 
  278. 	M20_CHECKPOINT_AIRPORT = "airport" 
  279.  
  280. -- Cutscenes -- 
  281.  
  282. 	M20_cutscene = { 
  283. 		mission_intro = "20_in", 
  284. 		mission_outro = "20_out", 
  285. 	} 
  286.  
  287. -- Text -- 
  288.  
  289. 	M20_text = { 
  290. 		get_in_angel_heli = "M20_OBJ_GET_IN_ANGEL_HELI", 
  291. 		go_to_gym = "M20_OBJ_GO_TO_GYM", 
  292. 		align_heli = "M20_OBJ_ALIGN_HELI", 
  293. 		align_to_boats = "M20_OBJ_ALIGN_TO_BOATS", 
  294. 		align_to_tanks = "M20_OBJ_ALIGN_TO_TANKS", 
  295. 		stay_close = "M20_OBJ_STAY_CLOSE", 
  296. 		rc_the_car = "M20_OBJ_RC_THE_CAR", 
  297. 		run_over_people = "M20_OBJ_RUN_OVER_PEOPLE", 
  298. 		wait_for_enter = "M20_OBJ_WAIT_FOR_ENTER", 
  299. 		get_up_to_speed = "M20_OBJ_GET_UP_TO_SPEED", 
  300. 		go_to_gas_station = "M20_OBJ_GO_TO_GAS_STATION", 
  301. 		crash_the_car = "M20_OBJ_CRASH_THE_CAR", 
  302. 		go_to_boat = "M20_OBJ_GO_TO_BOAT", 
  303. 		go_to_harbor = "M20_OBJ_GO_TO_HARBOR", 
  304. 		rc_the_boat = "M20_OBJ_RC_THE_BOAT", 
  305. 		rc_a_boat = "M20_OBJ_RC_A_BOAT", 
  306. 		crash_beach_party = "M20_OBJ_CRASH_BEACH_PARTY", 
  307. 		use_ramp = "M20_OBJ_USE_RAMP", 
  308. 		crash_the_boat = "M20_OBJ_CRASH_THE_BOAT", 
  309. 		go_to_helicopter = "M20_OBJ_GO_TO_HELICOPTER", 
  310. 		rc_the_helicopter = "M20_OBJ_RC_THE_HELICOPTER", 
  311. 		crash_the_heli = "M20_OBJ_CRASH_THE_HELICOPTER", 
  312. 		go_to_airport = "M20_OBJ_GO_TO_AIRPORT", 
  313. 		rc_a_tank = "M20_OBJ_RC_A_TANK", 
  314. 		kill_the_last_wrestler = "M20_OBJ_KILL_THE_LAST_WRESTLER", 
  315. 	   peds_label = "M20_PEDS", 
  316.  
  317. 		failure_angel_heli_destroyed = "m20_failure_angel_heli_destroyed", 
  318. 		failure_rc_too_late = "m20_failure_rc_too_late", 
  319. 		failure_rc_heli_destroyed = "m20_failure_rc_heli_destroyed", 
  320. 		failure_premature_hijackulation = "m20_failure_premature_hijackulation", 
  321. 		failure_no_tanks_to_you = "m20_failure_no_tanks_to_you", 
  322. 		failure_ctc_destroyed = "m20_failure_ctc_destroyed", 
  323. 		failure_ctb_destroyed = "m20_failure_ctb_destroyed", 
  324. 		failure_lost_signal = "m20_failure_lost_signal", 
  325. 	} 
  326.  
  327. -- Conversations -- 
  328.  
  329. 	M20_convo = { 
  330. 		-- Angel, Kinzie, Player  
  331. 		mission_start = { convo_name = "m20_mission_start", speakers_2d = { "Kinzie" }, player_speaks = true, delay_after = 3 }, 
  332.  
  333. 		-- Angel, Player 
  334. 		flight_1 = { convo_name = "m20_flight_conversation_01", player_speaks = true, delay_after = 3 },  
  335. 		 
  336. 		-- radio announcement played on way to ctc 
  337. 		conference_announcement_1 = { persona_2d_params = { "M20_Conference_Announcment_01" }, speakers_2d = { "Interrogation" }  }, 
  338. 		 
  339. 		-- Angel, Player - when arriving at murderdome 
  340. 		first_luchadore = { convo_name = "m20_first_luchadore", player_speaks = true }, 
  341.  
  342. 		-- luchadore, when car is rc'd 
  343. 		car_controlled = { persona_2d_params = { "M20_First_Car_Controlled_Start" }, delay_after = 3, speakers_2d = { "Interrogation" } }, 
  344. 		 
  345. 		-- player, when "crash the peds" objective is displayed 
  346. 		crash_the_peds = { persona_3d_params = { LOCAL_PLAYER, "M20_Start_Running_Down_People" }, }, 
  347. 		 
  348. 		-- luchedore, when hitting the 4th, 10th, and 13th ped 
  349. 		ped_hit_1 = { persona_2d_params = { "M20_First_Car_Hitting_People_01" }, delay_after = 3, speakers_2d = { "Interrogation" } }, 
  350. 		ped_hit_2 = { persona_2d_params = { "M20_First_Car_Hitting_People_02" }, delay_after = 3, speakers_2d = { "Interrogation" } }, 
  351. 		ped_hit_3 = { persona_2d_params = { "M20_First_Car_Hitting_People_03" }, delay_after = 3, speakers_2d = { "Interrogation" } }, 
  352. 		 
  353. 		-- player, before "crash into pump" objective is displayed 
  354. 		hit_gas_pump = { persona_3d_params = { LOCAL_PLAYER, "M20_First_Luchadore_Crash" }, }, 
  355. 		 
  356. 		-- player, after car exploded 
  357. 		car_destroyed = { persona_3d_params = { LOCAL_PLAYER, "M20_First_One_Dead_01" }, delay_after = 3 }, 
  358. 		 
  359. 		-- player, angel - after car_destroyed 
  360. 		explain_2nd_target = { convo_name = "M20_Explain_Second_Target", player_speaks = true, delay_after = 3 },  
  361.  
  362. 		-- Kinzie, Player - after explain_2nd_target 
  363. 		flight_2 = { convo_name = "m20_flight_conversation_02", speakers_2d = { "Kinzie" }, player_speaks = true, delay_after = 3 }, 
  364. 		 
  365. 		-- Radio - after flight_2 
  366. 		breaking_news_1 =	{ persona_2d_params = { "M20_Breaking_News_Car_Crash" }, speakers_2d = { "Anna" }, delay_after = 2  }, 
  367. 		conference_announcement_3 = { persona_2d_params = { "M20_Conference_Announcment_03" }, speakers_2d = { "Interrogation" }  }, 
  368.  
  369. 		-- boat driver - upon rc boat 
  370. 		boat_takeover_start = { persona_2d_params = { "M20_Second_Boat_Takeover_Start" }, speakers_2d = { "Interrogation" }  }, 
  371.  
  372. 		-- boat driver - when boat hits ramp 
  373. 		boat_takeover_ramp = { persona_2d_params = { "M20_Second_Boat_Takeover_Ramp" }, speakers_2d = { "Interrogation" }  }, 
  374. 		 
  375. 		-- Angel, Player  not used any more? 
  376. 		-- second_luchadore_boat = { convo_name = "m20_second_luchadore_boat", player_speaks = true }, 
  377.  
  378. 		-- Angel, Player 
  379. 		second_one_dead = { convo_name = "m20_second_one_dead", player_speaks = true, delay_after = 3 }, 
  380. 		 
  381. 		-- breaking news about boat - after second_one dead 
  382. 		breaking_news_2 =	{ persona_2d_params = { "M20_Breaking_News_Boat_Crash" }, speakers_2d = { "Anna" }  }, 
  383. 		conference_announcement_4 = { persona_2d_params = { "M20_Conference_Announcment_04" }, speakers_2d = { "Interrogation" }  }, 
  384.  
  385. 		-- Angel, Player 
  386. 		third_luchadore = { convo_name = "m20_third_luchadore", player_speaks = true }, 
  387.  
  388. 		-- Angel, Player 
  389. 		third_one_dead = { convo_name = "m20_third_one_dead", player_speaks = true, delay_after = 3 }, 
  390. 		 
  391. 		-- Player, Angel - after third_one_dead 
  392. 		flight_3 = { convo_name = "M20_Flight_Conversation_03", player_speaks = true, delay_after = 3 }, 
  393. 		 
  394. 		-- breaking news about heli - after third_one_dead 
  395. 		breaking_news_3 =	{ persona_2d_params = { "M20_Breaking_News_Heli_Crash" }, speakers_2d = { "Anna" }, delay_after = 2  }, 
  396. 		conference_announcement_5 = { persona_2d_params = { "M20_Conference_Announcment_05" }, speakers_2d = { "Interrogation" }  }, 
  397.  
  398. 		-- Kinzie, when rc signal < 25% signal strength 
  399. 		losing_signal = { persona_2d_params = { "M20_Vehicle_Almost_Too_Far" }, speakers_2d = { "Kinzie" }  }, 
  400.  
  401. 		-- Kinzie, at rc signal lost 
  402. 		lost_signal = { persona_2d_params = { "M20_Signal_Lost" }, speakers_2d = { "Kinzie" }, delay_after = 2  }, 
  403. 	} 
  404. 	 
  405. 	M20_movers = { 
  406. 		gas_pumps = { 
  407. 			"Mover Gas Pump <002>", "Mover Gas Pump <003>", 
  408. 			"Mover Gas Pump <006>", "Mover Gas Pump <007>", 
  409. 			"Mover Gas Pump <010>", "Mover Gas Pump <011>", 
  410. 			"Mover Gas Pump <013>", "Mover Gas Pump <015>", 
  411. 			"Mover Gas Pump <017>", "Mover Gas Pump <020>", 
  412. 			"Mover Gas Pump <022>", "Mover Gas Pump <024>", 
  413. 		}, 
  414. 	} 
  415.  
  416. -- ************************* 
  417. -- 
  418. -- Standard functions 
  419. -- 
  420. -- ************************* 
  421.  
  422. -- This is the primary entry point for the mission, and is responsible for starting up the mission 
  423. -- at the specified checkpoint. 
  424. -- CALLED FROM CODE 
  425. -- 
  426. -- m20_checkpoint:	The checkpoint the mission should begin at 
  427. -- is_restart:			TRUE if the mission is restarting, FALSE otherwise 
  428. -- 
  429. function m20_start(m20_checkpoint, is_restart) 
  430. 	-- Make sure the screen is completly faded out 
  431. 	mission_start_fade_out(0.0) 
  432.  
  433. 	-- Check if this mission starting from the beginning 
  434. 	if (m20_checkpoint == MISSION_START_CHECKPOINT) then
    		if is_restart == false then 
  435. 			cutscene_play( M20_cutscene.mission_intro, nil, {  M20_navpoint.cp_starts.mission_start.player_local, M20_navpoint.cp_starts.mission_start.player_remote }, false ) 
  436. 		end 
  437. 	end 
  438. 	 
  439. 	-- Handle mission initialization for the current checkpoint 
  440. 	m20_initialize(m20_checkpoint) 
  441.  
  442. 	-- Run the mission from the current checkpoint 
  443. 	m20_run(m20_checkpoint) 
  444.  
  445. end 
  446.  
  447. -- This is the primary function responsible for running the entire mission from start to finish. 
  448. -- 
  449. -- first_checkpoint:	The first checkpoint to begin running the mission at 
  450. -- 
  451. function m20_run(first_checkpoint) 
  452. 	local current_checkpoint = first_checkpoint 
  453.  
  454. 	local ignore_vehicles = true 
  455. 	local ignore_notoriety = true 
  456.  
  457. 	if (current_checkpoint == MISSION_START_CHECKPOINT) then 
  458. 		m20_objective_go_to_the_gym() 
  459.  
  460. 		current_checkpoint = M20_CHECKPOINT_CRASH_THE_CAR 
  461. 		mission_set_checkpoint(M20_CHECKPOINT_CRASH_THE_CAR, ignore_vehicles, ignore_notoriety) 
  462. 	end 
  463.  
  464. 	if (current_checkpoint == M20_CHECKPOINT_CRASH_THE_CAR) then 
  465. 		m20_objective_take_control_of_the_car() 
  466.       m20_objective_crash_peds() 
  467. 		m20_objective_crash_the_car() 
  468.  
  469. 		current_checkpoint = M20_CHECKPOINT_CRASH_THE_BOAT 
  470. 		mission_set_checkpoint(M20_CHECKPOINT_CRASH_THE_BOAT, ignore_vehicles, ignore_notoriety) 
  471. 	end 
  472.  
  473. 	if (current_checkpoint == M20_CHECKPOINT_CRASH_THE_BOAT) then 
  474. 		m20_objective_crash_the_boat() 
  475.  
  476. 		current_checkpoint = M20_CHECKPOINT_CRASH_THE_HELI 
  477. 		mission_set_checkpoint(M20_CHECKPOINT_CRASH_THE_HELI, ignore_vehicles, ignore_notoriety) 
  478. 	end 
  479.  
  480. 	if (current_checkpoint == M20_CHECKPOINT_CRASH_THE_HELI) then 
  481. 		m20_objective_crash_the_helicopter() 
  482.  
  483. 		current_checkpoint = M20_CHECKPOINT_AIRPORT 
  484. 		mission_set_checkpoint(M20_CHECKPOINT_AIRPORT, ignore_vehicles, ignore_notoriety) 
  485. 	end 
  486.  
  487. 	if (current_checkpoint == M20_CHECKPOINT_AIRPORT) then 
  488. 		m20_objective_airport() 
  489. 		m20_objective_tanks_to_you() 
  490. 	end 
  491. 	 
  492. 	mission_end_success("m20", M20_cutscene.mission_outro, { M20_navpoint.success_local, M20_navpoint.success_remote } ) 
  493. end 
  494.  
  495. -- This is the primary function responsible for cleaning up the entire mission 
  496. -- CALLED FROM CODE (+++MUST RETURN IMMEDIATELY+++) 
  497. -- 
  498. function m20_cleanup() 
  499.  
  500. 	hud_x_of_y_remove(0) 
  501.  
  502. 	notoriety_force_no_spawn("luchadores", false) 
  503. 	notoriety_force_no_spawn("deckers", false) 
  504. 	notoriety_force_no_spawn("morningstar", false) 
  505. 	notoriety_force_no_spawn("police", false) 
  506.  
  507. 	vehicle_suppress_npc_exit(M20_vehicle.angel_heli, false) 
  508. 	set_player_can_enter_exit_vehicles(LOCAL_PLAYER, true) 
  509. 	set_player_can_enter_exit_rc_vehicles(LOCAL_PLAYER, true) 
  510.  
  511. 	if (coop_is_active()) then 
  512. 		set_player_can_enter_exit_vehicles(REMOTE_PLAYER, true) 
  513. 		set_player_can_enter_exit_rc_vehicles(REMOTE_PLAYER, true) 
  514. 	end 
  515.  
  516. 	cleanup_threads(M20_thread) 
  517. 	cleanup_callbacks( { M20_char, M20_vehicle } ) 
  518. 	cleanup_groups(M20_group) 
  519. 	call_function_on_each_member(m20_clear_trigger, M20_trigger) 
  520.  
  521. 	m20_convo_cleanup( M20_convo ) 
  522. 	inv_weapon_disable_all_slots(false) 
  523. 	cleanup_temporary_weapons(M20_weapon.cleanup) 
  524.  
  525. 	rc_set_max_signal_range( M20_previous_rc_range ) 
  526. 	hud_timer_stop( 1 ) 
  527.  
  528. 	spawn_override_clear_override_for_hood( "HOOD_YEARWOOD" ) 
  529. 	spawn_global_override_clear_category() 
  530. 	party_set_recruitable( true ) 
  531. end 
  532.  
  533. -- Called when the mission has ended with success 
  534. -- CALLED FROM CODE (+++MUST RETURN IMMEDIATLY+++) 
  535. -- 
  536. function m20_success() 
  537. 	--[[ INSERT ANY MISSION SPECIFIC SUCCESS STUFF ]]-- 
  538.  
  539. end 
  540.  
  541. -- ************************* 
  542. -- 
  543. -- Local functions 
  544. -- 
  545. -- ************************* 
  546.  
  547. -- Initialize the mission for the specified checkpoint 
  548. -- 
  549. -- checkpoint:		Checkpoint to initialize the mission to 
  550. -- 
  551. function m20_initialize(checkpoint) 
  552. 	-- Set the mission author 
  553. 	set_mission_author("Nick Heilmann") 
  554.  
  555. 	-- Common initialization 
  556. 	m20_initialize_common() 
  557.  
  558. 	if checkpoint ~= MISSION_START_CHECKPOINT then 
  559. 		-- give magic tank rc gun 
  560. 		inv_weapon_add_temporary(LOCAL_PLAYER, M20_weapon.rc_gun, 1, true, false, false, false, WEAPON_LEVEL4) 
  561. 		inv_weapon_disable_all_but_this_slot(WEAPON_SLOT_SPECIAL, true, SYNC_LOCAL) 
  562. 	end 
  563.  
  564. 	-- Checkpoint specific initialization 
  565. 	m20_initialize_checkpoint(checkpoint) 
  566.  
  567. 	-- Start fading in 
  568. 	mission_start_fade_in() 
  569. end 
  570.  
  571. -- *************************************************** 
  572. -- 
  573. -- m20_run Helper Functions 
  574. -- 
  575. -- *************************************************** 
  576.  
  577. --[[ ANGEL'S WINGS, GO TO THE GYM (MISSION START) ]]-- 
  578.  
  579. function m20_initialize_mission_start() 
  580. 	--fade_out(0.5) 
  581. 	 
  582. 	M20_char.angel = "NPC Angel MS" 
  583. 	M20_vehicle.angel_heli = "Veh Angel Heli MS" 
  584. 	M20_group.angel = { name = "GRP Angel MS", chars = { M20_char.angel }, vehicles = { M20_vehicle.angel_heli } } 
  585.  
  586. 	group_create_hidden(M20_group.angel.name, true) 
  587.  
  588. 	on_vehicle_destroyed("m20_angel_heli_destroyed_cb", M20_vehicle.angel_heli) 
  589.  
  590. 	player_force_vehicle_seat(LOCAL_PLAYER, 2, M20_vehicle.angel_heli) 
  591.  
  592. 	teleport_vehicle(M20_vehicle.angel_heli, M20_navpoint.angel_heli_float.bar) 
  593.  
  594. 	if (coop_is_active()) then 
  595. 		player_force_vehicle_seat(REMOTE_PLAYER, 0, M20_vehicle.angel_heli) 
  596.  
  597. 		vehicle_enter_teleport(REMOTE_PLAYER, M20_vehicle.angel_heli, VEHICLE_SEAT_DRIVER, true) 
  598. 		helicopter_fly_to_stop( M20_vehicle.angel_heli, M20_navpoint.angel_heli_float.bar ) 
  599.  
  600. 		vehicle_enter_teleport(M20_char.angel, M20_vehicle.angel_heli, VEHICLE_SEAT_PASSENGER) 
  601. 		vehicle_enter_teleport(LOCAL_PLAYER, M20_vehicle.angel_heli, VEHICLE_SEAT_HELI_BACK_DOOR, true) 
  602.  
  603. 		set_player_can_enter_exit_vehicles(LOCAL_PLAYER, false) 
  604. 		set_player_can_enter_exit_vehicles(REMOTE_PLAYER, false) 
  605.  
  606. 		thread_yield() 
  607. 	else 
  608. 		vehicle_enter_teleport(M20_char.angel, M20_vehicle.angel_heli, VEHICLE_SEAT_DRIVER) 
  609. 		vehicle_enter_teleport(LOCAL_PLAYER, M20_vehicle.angel_heli, VEHICLE_SEAT_HELI_BACK_DOOR, true) 
  610. 		 
  611. 		set_player_can_enter_exit_vehicles(LOCAL_PLAYER, false) 
  612. 		 
  613. 		thread_yield() 
  614. 	end 
  615.  
  616. 	helicopter_set_max_bank_angle( M20_vehicle.angel_heli, M20_ANGEL_MAX_BANK ) 
  617. 	vehicle_suppress_npc_exit(M20_vehicle.angel_heli, true) 
  618.  
  619. 	-- give magic tank rc gun 
  620. 	inv_weapon_add_temporary(LOCAL_PLAYER, M20_weapon.rc_gun, 1, true, false, false, false, WEAPON_LEVEL4) 
  621. 	inv_weapon_disable_all_but_this_slot(WEAPON_SLOT_SPECIAL, true, SYNC_LOCAL) 
  622.  
  623. 	group_show( M20_group.angel.name ) 
  624.  
  625. 	fade_in(0.5) 
  626. end 
  627.  
  628. -- Angel's heli flies to the gym 
  629. -- 
  630. function m20_objective_go_to_the_gym() 
  631. 	objective_text_clear(0) 
  632. 	objective_text(0, M20_text.go_to_gym, nil, nil, SYNC_ALL, OI_ASSET_LOCATION) 
  633. 	 
  634. 	-- turn on special spawning for the destination hood 
  635. 	spawn_override_set_override_category_for_hood( "HOOD_YEARWOOD", "sp_cat_m20Yearwood"  ) 
  636. 	spawn_global_override_set_category( "sp_cat_m20Yearwood" ) 
  637.  
  638.  
  639. 	M20_status.gym_reached = false 
  640. 	m20_set_trigger(M20_trigger.gym, "m20_gym_reached_cb", true, true) 
  641. 	 
  642. 	if coop_is_active() == false then 
  643. 		thread_kill(M20_thread.angel_heli_float) 
  644. 		M20_thread.angel_heli_float = INVALID_THREAD_HANDLE 
  645. 		M20_thread.fly_to_gym = thread_new("m20_wrapper_thread_forever", helicopter_fly_to_direct, M20_vehicle.angel_heli, HELI_DEFAULT_SPEED, M20_scripted_path.heli_to_gym) 
  646. 	end 
  647.  
  648. 	-- mission start convos 
  649. 	m20_convo_play( M20_convo.mission_start ) 
  650. 	m20_convo_play( M20_convo.flight_1 ) 
  651. 	m20_convo_play( M20_convo.conference_announcement_1 ) 
  652.  
  653. 	-- Create the car and wrestler 
  654. 	group_create(M20_group.rc_car, true) 
  655.  
  656. 	-- create mascots 
  657. 	for i, g in pairs( M20_group.mascots ) do 
  658. 		group_create( g.name ) 
  659. 	end 
  660.  
  661. 	-- Make sure the NPCs won't break their path by going into combat 
  662. 	npc_combat_enable(M20_char.rc_car[1], false) 
  663. 	npc_combat_enable(M20_char.rc_car[2], false) 
  664.  
  665. 	on_vehicle_destroyed("m20_rc_car_destroyed_cb", M20_vehicle.rc_car) 
  666.  
  667. 	local npcs_in_motion = false 
  668. 	 
  669. 	while true do 
  670. 		if M20_status.gym_reached ~= true then 
  671. 			if object_is_in_trigger( M20_trigger.gym, LOCAL_PLAYER ) == true then 
  672. 				m20_gym_reached_cb() 
  673. 			end 
  674. 		end 
  675. 		 
  676. 		-- get the wrestlers walking to thier car when the player enters the trigger 
  677. 		if npcs_in_motion == false and M20_status.gym_reached == true then 
  678. 			M20_thread.rc_car_enter[1] = thread_new("m20_walk_to_and_enter_vehicle_thread", M20_char.rc_car[1], M20_vehicle.rc_car, VEHICLE_SEAT_DRIVER) 
  679. 			M20_thread.rc_car_enter[2] = thread_new("m20_walk_to_and_enter_vehicle_thread", M20_char.rc_car[2], M20_vehicle.rc_car, VEHICLE_SEAT_WRESTLER_BACK_SEAT) 
  680.  
  681. 			m20_mascot_brawl( M20_group.mascots[ 1 ], M20_group.mascots[ 2 ] ) 
  682. 			 
  683. 			npcs_in_motion = true 
  684. 		end 
  685.  
  686. 		if coop_is_active() then 
  687. 			-- coop just move on when we reach the trigger area 
  688. 			if M20_status.gym_reached then 
  689. 				break 
  690. 			end 
  691. 		else 
  692. 			-- SP wait until heli is in position 
  693. 			if get_dist( M20_vehicle.angel_heli, M20_navpoint.angel_heli_float.gym ) < 10 then 
  694. 				marker_remove( M20_navpoint.angel_heli_float.gym ) 
  695. 				thread_kill( M20_thread.fly_to_gym ) 
  696. 				M20_thread.fly_to_gym = INVALID_THREAD_HANDLE 
  697. 				break 
  698. 			end 
  699. 		end 
  700.  
  701. 		thread_yield() 
  702. 	end 
  703.  
  704. 	m20_clear_trigger( M20_trigger.gym ) 
  705. 	objective_text_clear(0) 
  706. end 
  707.  
  708. -- make the mascots in two groups attack each other 
  709. function m20_mascot_brawl( g1, g2 ) 
  710. 		for j, c1 in pairs( g1.chars ) do 
  711. 			if g2.chars[ j ] ~= nil then 
  712. 		 
  713. 				while character_is_ready( c1 ) == false do 
  714. 					thread_yield() 
  715. 				end 
  716. 				 
  717. 				ai_add_enemy_target( c1, g2.chars[ j ], ATTACK_NOW, true ) 
  718. 			end 
  719. 		end 
  720. end 
  721.  
  722. --[[ CRASH THE CAR ]]-- 
  723.  
  724.  
  725. function m20_initialize_crash_the_car() 
  726. 	teleport_coop(M20_navpoint.cp_starts.crash_the_car.player_local, M20_navpoint.cp_starts.crash_the_car.player_remote, true) 
  727.  
  728. 	M20_char.angel = "NPC Angel CTC" 
  729. 	M20_vehicle.angel_heli = "Veh Angel Heli CTC" 
  730. 	M20_group.angel = { name = "GRP Angel CTC", chars = { M20_char.angel }, vehicles = { M20_vehicle.angel_heli } } 
  731.  
  732. 	-- Create Angel and the heli 
  733. 	group_create(M20_group.angel.name, true) 
  734. 	on_vehicle_destroyed("m20_angel_heli_destroyed_cb", M20_vehicle.angel_heli) 
  735.  
  736. 	-- Now teleport the vehicle to the floating position 
  737. 	teleport_vehicle(M20_vehicle.angel_heli, M20_navpoint.angel_heli_teleport.gym) 
  738.  
  739. 	if coop_is_active() == false then 
  740. 		helicopter_set_max_bank_angle( M20_vehicle.angel_heli, M20_ANGEL_MAX_BANK ) 
  741. 	end 
  742.  
  743. 	-- put angel in the heli 
  744. 	while (not character_is_in_vehicle(M20_char.angel, M20_vehicle.angel_heli)) do 
  745. 		if (coop_is_active()) then 
  746. 			vehicle_enter_teleport(M20_char.angel, M20_vehicle.angel_heli, VEHICLE_SEAT_PASSENGER) 
  747. 		else 
  748. 			vehicle_enter_teleport(M20_char.angel, M20_vehicle.angel_heli, VEHICLE_SEAT_DRIVER) 
  749. 		end 
  750. 		thread_yield() 
  751. 	end 
  752. 	 
  753. 	vehicle_suppress_npc_exit(M20_vehicle.angel_heli, true) 
  754. 	 
  755. 	-- put local player in 
  756. 	while (not character_is_in_vehicle(LOCAL_PLAYER, M20_vehicle.angel_heli)) do 
  757. 		vehicle_enter_teleport(LOCAL_PLAYER, M20_vehicle.angel_heli, VEHICLE_SEAT_HELI_BACK_DOOR) 
  758. 		thread_yield() 
  759. 	end 
  760. 	set_player_can_enter_exit_vehicles(LOCAL_PLAYER, false) 
  761. 	 
  762. 	-- and remote player or angel's flying thread 
  763. 	if (coop_is_active()) then 
  764. 		while (not character_is_in_vehicle(REMOTE_PLAYER, M20_vehicle.angel_heli)) do 
  765. 			vehicle_enter_teleport(REMOTE_PLAYER, M20_vehicle.angel_heli, VEHICLE_SEAT_DRIVER) 
  766. 			thread_yield() 
  767. 		end 
  768. 		set_player_can_enter_exit_vehicles(REMOTE_PLAYER, false) 
  769. 	else 
  770. 		M20_thread.angel_heli_float = thread_new("m20_wrapper_thread", helicopter_fly_to_direct, M20_vehicle.angel_heli, HELI_DEFAULT_SPEED, M20_navpoint.angel_heli_float.gym) 
  771. 	end 
  772. 	 
  773. --	group_show( M20_group.angel.name ) 
  774.  
  775. 	group_create(M20_group.rc_car, true) 
  776. 	on_vehicle_destroyed("m20_rc_car_destroyed_cb", M20_vehicle.rc_car) 
  777.  
  778. 	for i, g in pairs( M20_group.mascots ) do 
  779. 		group_create( g.name ) 
  780. 	end 
  781.  
  782. 	m20_mascot_brawl( M20_group.mascots[ 1 ], M20_group.mascots[ 2 ] ) 
  783.  
  784. 	M20_thread.rc_car_enter[1] = thread_new("m20_walk_to_and_enter_vehicle_thread", M20_char.rc_car[1], M20_vehicle.rc_car, VEHICLE_SEAT_DRIVER) 
  785. 	M20_thread.rc_car_enter[2] = thread_new("m20_walk_to_and_enter_vehicle_thread", M20_char.rc_car[2], M20_vehicle.rc_car, VEHICLE_SEAT_WRESTLER_BACK_SEAT) 
  786.  
  787. 	if (not coop_is_active()) then 
  788. 		thread_kill(M20_thread.angel_heli_float) 
  789. 		M20_thread.angel_heli_float = INVALID_THREAD_HANDLE 
  790. 	end 
  791. end 
  792.  
  793. -- Wrestler and his driver walk to and enter the car, player takes control of it 
  794. -- 
  795. function m20_objective_take_control_of_the_car() 
  796. 	-- Sub-objective 1: RC the car 
  797. 	objective_text(0, M20_text.rc_the_car, nil, nil, SYNC_LOCAL, OI_ASSET_USE) 
  798. 	marker_add(M20_vehicle.rc_car, MINIMAP_ICON_USE, OI_ASSET_USE, OI_FLAGS_DEFAULT, SYNC_LOCAL) 
  799.  
  800. 	if (coop_is_active()) then 
  801. 		objective_text(1, M20_text.align_heli, nil, nil, SYNC_REMOTE, OI_ASSET_LOCATION) 
  802. 		marker_add(M20_vehicle.rc_car, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_DEFAULT, SYNC_REMOTE) 
  803. 		-- Give them some time to get aligned, since it will be a bit more difficult in co-op than it is for a scripted path 
  804. 		delay(3) 
  805. 	end 
  806.  
  807. 	m20_convo_play( M20_convo.first_luchadore, false, true ) 
  808.  
  809. 	-- give the player some time to rc the car 
  810. 	hud_timer_set( 1, 45 * 1000, "m20_rc_car_timer_expired", SYNC_ALL ) 
  811.  
  812. 	local player_controls_car = false 
  813. 	local wrestlers_in_car = false 
  814.  
  815. 	while true do 
  816. 		thread_yield() 
  817.  
  818. 		if player_controls_car == false and player_is_rc_driver( LOCAL_PLAYER, M20_vehicle.rc_car ) == true then 
  819. 			set_player_can_enter_exit_rc_vehicles( LOCAL_PLAYER, false ) 
  820. 			player_controls_car = true 
  821.  
  822. 			hud_timer_stop( 1 ) 
  823.  
  824. 			-- Don't let the player move the car until the wrestler enters 
  825. 			player_controls_disable(LOCAL_PLAYER) 
  826. 			 
  827. 			-- remove marker for both players 
  828. 			marker_remove(M20_vehicle.rc_car, SYNC_ALL) 
  829.  
  830. 			if coop_is_active() then 
  831. 				-- change remote message to "stay close..." 
  832. 				objective_text_clear( 1 ) 
  833. 				m20_coop_follow_obj_start( M20_vehicle.rc_car ) 
  834. 			end 
  835. 			 
  836. 			m20_kinzie_watch_signal_start( M20_vehicle.rc_car ) 
  837. 			 
  838. 			if wrestlers_in_car == false then 
  839. 				-- change local message to say "wait for wrestler to enter car" 
  840. 				objective_text(0, M20_text.wait_for_enter, nil, nil, SYNC_LOCAL, OI_ASSET_USE) 
  841. 			end 
  842. 			 
  843. 		end 
  844. 		 
  845. 		if wrestlers_in_car == false then 
  846. 			if thread_check_done( M20_thread.rc_car_enter[ 1 ] ) and thread_check_done( M20_thread.rc_car_enter[ 2 ] ) then 
  847. 				wrestlers_in_car = true 
  848. 				vehicle_suppress_npc_exit(M20_vehicle.rc_car, true) 
  849. 				character_set_cannot_exit_rc_vehicle( M20_char.rc_car[ 1 ], true ) 
  850. 				character_set_cannot_exit_rc_vehicle( M20_char.rc_car[ 2 ], true ) 
  851. 			end 
  852. 		end 
  853.  
  854. 		-- if the player is in control of the vehicle and the wrestlers are in the car then continue 
  855. 		if player_controls_car and wrestlers_in_car then 
  856. 			break 
  857. 		end 
  858. 	end 
  859.  
  860. 	m20_convo_play( M20_convo.car_controlled ) 
  861. 	 
  862. 	hud_timer_stop( 1 ) 
  863.  
  864. 	-- Now that the wrestler is in the car, let the player move again 
  865. 	player_controls_enable(LOCAL_PLAYER) 
  866.  
  867. end 
  868.  
  869. -- Player gets the vehicle up to speed, then crashes it 
  870. -- 
  871. function m20_objective_crash_the_car() 
  872. 	m20_convo_play( M20_convo.hit_gas_pump, true, true ) 
  873.  
  874. 	objective_text(0, M20_text.go_to_gas_station, nil, nil, SYNC_LOCAL, OI_ASSET_LOCATION) 
  875. 	marker_add(M20_navpoint.gas_station, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_FULL, SYNC_LOCAL) 
  876. 	mission_waypoint_add(M20_navpoint.gas_station) 
  877. 	M20_status.rc_car_destroyed = false 
  878.  
  879. 	M20_status.rc_car_prev_hp = get_current_hit_points( M20_vehicle.rc_car ) 
  880. 	on_take_damage( "m20_on_take_damage_rc_car", M20_vehicle.rc_car ) 
  881.  
  882. 	if coop_is_active() == false then 
  883. 		M20_thread.follow_rc_vehicle = thread_new("m20_wrapper_thread_forever", helicopter_fly_to_direct_follow, M20_vehicle.angel_heli, 50, M20_vehicle.rc_car, nil, 150, true) 
  884. 	end 
  885.  
  886. 	local close_to_gas_station = false 
  887.  
  888. 	while vehicle_is_destroyed( M20_vehicle.rc_car ) == false do 
  889. 		if player_is_rc_driver( LOCAL_PLAYER, M20_vehicle.rc_car ) == false then 
  890. 			m20_convo_play( M20_convo.lost_signal, true, true ) 
  891. 			mission_end_failure( "m20", M20_text.failure_lost_signal ) 
  892. 			return 
  893. 		end 
  894.  
  895. 		-- change objective when they are near the gas station 
  896. 		if close_to_gas_station == false and get_dist( M20_vehicle.rc_car, M20_navpoint.gas_station ) < 50 then 
  897. 			objective_text(0, M20_text.crash_the_car, nil, nil, SYNC_LOCAL, OI_ASSET_LOCATION) 
  898. 			close_to_gas_station = true 
  899. 		end 
  900. 		 
  901.  
  902. 		thread_yield() 
  903. 	end 
  904. 	 
  905. 	m20_kinzie_watch_signal_stop() 
  906.  
  907. 	if coop_is_active() == false then 
  908. 			-- Stop following the vehicle (the thread should already have been killed, but just to be safe...) 
  909. 			thread_kill(M20_thread.follow_rc_vehicle) 
  910. 			M20_thread.follow_rc_vehicle = INVALID_THREAD_HANDLE 
  911. 	end 
  912.  
  913. 	on_take_damage( "", M20_vehicle.rc_car ) 
  914.  
  915. 	set_player_can_enter_exit_rc_vehicles(LOCAL_PLAYER, true) 
  916.  
  917. 	-- Remove whatever message may still be displayed from the debug conversations being played 
  918. 	message_remove_all() 
  919. 	 
  920. 	-- delay a few seconds for camera to pan out from explosion 
  921. 	delay( 1 ) 
  922. 	m20_convo_play( M20_convo.car_destroyed, false, true ) 
  923. 	delay( 3 ) 
  924. 	 
  925. 	m20_convo_play( M20_convo.explain_2nd_target ) 
  926. 	m20_convo_play( M20_convo.breaking_news_1 ) 
  927. --	m20_convo_play( M20_convo.conference_announcement_3 ) 
  928.  
  929. 	cleanup_groups(M20_group.rc_car) 
  930.  
  931. 	if (not coop_is_active()) then 
  932. 		M20_thread.fly_to_boat = thread_new("m20_wrapper_thread", helicopter_fly_to_direct, M20_vehicle.angel_heli, 50, M20_scripted_path.heli_to_boat) 
  933. 	end 
  934. 	 
  935. 	m20_coop_follow_obj_stop() 
  936. 	marker_remove( M20_navpoint.gas_station ) 
  937. 	mission_waypoint_remove() 
  938. 	marker_remove( M20_vehicle.rc_car ) 
  939. 	objective_text_clear(0) 
  940. 	 
  941. 	group_create(M20_group.beach_party.name, false) 
  942. 	group_create(M20_group.rc_boat.name, true) 
  943.  
  944. 	for i,npc in pairs(M20_char.rc_boat) do 
  945. 		vehicle_enter_teleport(npc, M20_vehicle.rc_boat[i]) 
  946. 	end 
  947. end 
  948.  
  949. -- Player crashes the vehicle into some peds 
  950. -- 
  951. function m20_objective_crash_peds() 
  952. 	objective_text(0, M20_text.run_over_people, nil, nil, SYNC_LOCAL, OI_ASSET_KILL) 
  953.  
  954. 	m20_convo_play( M20_convo.crash_the_peds ) 
  955.  
  956. 	M20_status.rc_car_peds_hit = 0 
  957. 	M20_peds_hit = { } 
  958. 	local line_played = 0 
  959.  
  960. 	on_hit_ped("m20_rc_car_hit_ped_cb", M20_vehicle.rc_car) 
  961.  
  962. 	hud_x_of_y_add( 0, M20_text.peds_label, 0, PEDS_TO_HIT, false, SYNC_LOCAL ) 
  963.  
  964. 	if coop_is_active() == false then 
  965. 		-- follow the player 
  966. 		M20_thread.follow_rc_vehicle = thread_new("m20_wrapper_thread_forever", helicopter_fly_to_direct_follow, M20_vehicle.angel_heli, 50, M20_vehicle.rc_car, nil, 150, true) 
  967. 	end 
  968.  
  969. 	repeat 
  970. 		thread_yield() 
  971. 		hud_x_of_y_update(0, M20_status.rc_car_peds_hit) 
  972. 		 
  973. 		-- play a line when thresholds are hit 
  974. 		if line_played < 1 and M20_status.rc_car_peds_hit > 3 then 
  975. 			m20_convo_play( M20_convo.ped_hit_1, false, true ) 
  976. 		elseif line_played < 2 and M20_status.rc_car_peds_hit > 9 then 
  977. 			m20_convo_play( M20_convo.ped_hit_2, false, true ) 
  978. 		elseif line_played < 3 and M20_status.rc_car_peds_hit > 12 then 
  979. 			m20_convo_play( M20_convo.ped_hit_3, false, true ) 
  980. 		end 
  981. 		 
  982. 		-- update line played 
  983. 		-- do it seperate so we don't get two in same frame at least 
  984. 		if M20_status.rc_car_peds_hit > 12 then 
  985. 			line_played = 3 
  986. 		elseif M20_status.rc_car_peds_hit > 9 then 
  987. 			line_played = 2 
  988. 		elseif M20_status.rc_car_peds_hit > 3 then 
  989. 			line_played = 1 
  990. 		end 
  991. 		 
  992. 		if player_is_rc_driver( LOCAL_PLAYER, M20_vehicle.rc_car ) == false then 
  993. 			m20_convo_play( M20_convo.lost_signal, true, true ) 
  994. 			mission_end_failure( "m20", M20_text.failure_lost_signal ) 
  995. 			return 
  996. 		end 
  997. 	until M20_status.rc_car_peds_hit >= PEDS_TO_HIT 
  998.  
  999. 	if coop_is_active() == false then 
  1000. 		-- Stop following the vehicle 
  1001. 		thread_kill(M20_thread.follow_rc_vehicle) 
  1002. 		M20_thread.follow_rc_vehicle = INVALID_THREAD_HANDLE 
  1003. 	end 
  1004. 	 
  1005. 	on_hit_ped("", M20_vehicle.rc_car) 
  1006. 	hud_x_of_y_remove(0) 
  1007.  
  1008. 	-- Remove whatever message may still be displayed from the debug conversations being played 
  1009. 	message_remove_all() 
  1010.  
  1011. 	objective_text_clear(0) 
  1012. end 
  1013.  
  1014.  
  1015.  
  1016. --[[ CRASH THE BOAT ]]-- 
  1017.  
  1018.  
  1019. function m20_initialize_crash_the_boat() 
  1020. 	teleport_coop(M20_navpoint.cp_starts.crash_the_boat.player_local, M20_navpoint.cp_starts.crash_the_boat.player_remote, true) 
  1021.  
  1022. 	M20_char.angel = "NPC Angel CTB" 
  1023. 	M20_vehicle.angel_heli = "Veh Angel Heli CTB" 
  1024. 	M20_group.angel = { name = "GRP Angel CTB", chars = { M20_char.angel }, vehicles = { M20_vehicle.angel_heli } } 
  1025.  
  1026. 	-- Create Angel and the heli 
  1027. 	group_create_hidden(M20_group.angel.name, true) 
  1028. 	on_vehicle_destroyed("m20_angel_heli_destroyed_cb", M20_vehicle.angel_heli) 
  1029.  
  1030. 	if coop_is_active() == false then 
  1031. 		helicopter_set_max_bank_angle( M20_vehicle.angel_heli, M20_ANGEL_MAX_BANK ) 
  1032. 	end 
  1033.  
  1034. 	-- Put them in the vehicle before teleporting anything 
  1035. 	while (not character_is_in_vehicle(M20_char.angel, M20_vehicle.angel_heli)) do 
  1036. 		if (coop_is_active()) then 
  1037. 			vehicle_enter_teleport(M20_char.angel, M20_vehicle.angel_heli, VEHICLE_SEAT_PASSENGER) 
  1038. 		else 
  1039. 			vehicle_enter_teleport(M20_char.angel, M20_vehicle.angel_heli, VEHICLE_SEAT_DRIVER) 
  1040. 		end 
  1041. 		thread_yield() 
  1042. 	end 
  1043. 	 
  1044. 	vehicle_suppress_npc_exit(M20_vehicle.angel_heli, true) 
  1045. 	 
  1046. 	while (not character_is_in_vehicle(LOCAL_PLAYER, M20_vehicle.angel_heli)) do 
  1047. 		vehicle_enter_teleport(LOCAL_PLAYER, M20_vehicle.angel_heli, VEHICLE_SEAT_HELI_BACK_DOOR) 
  1048. 		thread_yield() 
  1049. 	end 
  1050. 	 
  1051. 	set_player_can_enter_exit_vehicles(LOCAL_PLAYER, false) 
  1052. 	 
  1053. 	if (coop_is_active()) then 
  1054. 		while (not character_is_in_vehicle(REMOTE_PLAYER, M20_vehicle.angel_heli)) do 
  1055. 			vehicle_enter_teleport(REMOTE_PLAYER, M20_vehicle.angel_heli, VEHICLE_SEAT_DRIVER) 
  1056. 			thread_yield() 
  1057. 		end 
  1058. 		set_player_can_enter_exit_vehicles(REMOTE_PLAYER, false) 
  1059. 	else 
  1060. 		-- Now teleport the vehicle to the floating position 
  1061. 		teleport_vehicle(M20_vehicle.angel_heli, M20_navpoint.angel_heli_teleport.boat) 
  1062. 		M20_thread.angel_heli_float = thread_new("m20_wrapper_thread", helicopter_fly_to_direct, M20_vehicle.angel_heli, HELI_DEFAULT_SPEED, M20_navpoint.angel_heli_float.boat) 
  1063. 	end 
  1064. 	 
  1065. 	group_show( M20_group.angel.name ) 
  1066.  
  1067. 	if (not coop_is_active()) then 
  1068. 		thread_kill(M20_thread.angel_heli_float) 
  1069. 		M20_thread.angel_heli_float = INVALID_THREAD_HANDLE 
  1070. 	else 
  1071. 		vehicle_stop( M20_vehicle.angel_heli, true ) 
  1072. 	end 
  1073.  
  1074. 	group_create(M20_group.rc_boat.name, true) 
  1075. 	group_create(M20_group.beach_party.name, false) 
  1076.  
  1077. 	for i,npc in pairs(M20_char.rc_boat) do 
  1078. 		vehicle_enter_teleport(npc, M20_vehicle.rc_boat[i]) 
  1079. 	end 
  1080. end 
  1081.  
  1082. function m20_objective_crash_the_boat() 
  1083. 	-- Sub-objective 1: Go to boat 
  1084. 	objective_text(0, M20_text.go_to_harbor, nil, nil, SYNC_ALL, OI_ASSET_LOCATION) 
  1085.  
  1086. 	m20_convo_play( M20_convo.flight_2 ) 
  1087.  
  1088. 	if (coop_is_active()) then 
  1089. 		M20_status.boat_reached = false 
  1090. 		m20_set_trigger(M20_trigger.boat, "m20_boat_reached_cb", true, true) 
  1091.  
  1092. 		repeat 
  1093. 			thread_yield() 
  1094. 		until M20_status.boat_reached 
  1095.  
  1096. 		m20_clear_trigger(M20_trigger.boat) 
  1097. 	else 
  1098. 		mission_waypoint_add( M20_navpoint.angel_heli_float.boat ) 
  1099. 		marker_add(M20_navpoint.angel_heli_float.boat, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_DEFAULT) 
  1100.  
  1101. 		repeat 
  1102. 			thread_yield() 
  1103. 		until (get_dist(M20_vehicle.angel_heli, M20_navpoint.angel_heli_float.boat) < 60) 
  1104.  
  1105. 		mission_waypoint_remove() 
  1106. 		marker_remove(M20_navpoint.angel_heli_float.boat) 
  1107. 	end 
  1108.  
  1109. 	-- Sub-objective 2: RC the boat 
  1110. 	objective_text_clear(0) 
  1111. 	objective_text(0, M20_text.rc_a_boat, nil, nil, SYNC_LOCAL, OI_ASSET_USE) 
  1112.  
  1113. 	if (coop_is_active()) then 
  1114. 		objective_text(1, M20_text.align_to_boats, nil, nil, SYNC_REMOTE, OI_ASSET_LOCATION) 
  1115. 		for i,boat in pairs(M20_vehicle.rc_boat) do 
  1116. 			marker_add(boat, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_DEFAULT, SYNC_REMOTE) 
  1117. 		end 
  1118. 	end 
  1119.  
  1120. 	for i,boat in pairs(M20_vehicle.rc_boat) do 
  1121. 		marker_add(boat, MINIMAP_ICON_USE, OI_ASSET_USE, OI_FLAGS_DEFAULT, SYNC_LOCAL) 
  1122. 	end 
  1123.  
  1124. 	M20_status.player_has_rc_vehicle = false 
  1125. 	repeat 
  1126. 		thread_yield() 
  1127. 		for i,boat in pairs(M20_vehicle.rc_boat) do 
  1128. 			if (player_is_rc_driver(LOCAL_PLAYER, boat)) then 
  1129. 				set_player_can_enter_exit_rc_vehicles(LOCAL_PLAYER, false) 
  1130. 				on_vehicle_destroyed("m20_rc_boat_destroyed_cb", boat) 
  1131. 				M20_status.my_rc_boat = boat 
  1132. 				M20_status.player_has_rc_vehicle = true 
  1133. 			end 
  1134. 		end 
  1135. 	until (M20_status.player_has_rc_vehicle) 
  1136.  
  1137. 	objective_text_clear(0) 
  1138.  
  1139. 	for i,boat in pairs(M20_vehicle.rc_boat) do 
  1140. 		marker_remove(boat) 
  1141. 	end 
  1142.  
  1143. 	if (coop_is_active()) then 
  1144. 		objective_text_clear( 1 ) 
  1145. 		m20_coop_follow_obj_start( M20_status.my_rc_boat ) 
  1146. 	end 
  1147. 	 
  1148. 	m20_kinzie_watch_signal_start( M20_status.my_rc_boat ) 
  1149. 	m20_convo_play( M20_convo.boat_takeover_start, false, true ) 
  1150.  
  1151. 	marker_add(M20_char.beach_wrestler, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_DEFAULT, SYNC_LOCAL) 
  1152.  
  1153. 	-- Sub-objective 3: Crash the beach party 
  1154. 	objective_text(0, M20_text.crash_beach_party, nil, nil, SYNC_LOCAL, OI_ASSET_LOCATION) 
  1155.  
  1156. 	M20_status.rc_boat_destroyed = false 
  1157. 	M20_status.beach_party_crashed = false 
  1158.  
  1159. 	M20_thread.beach_party_polling = thread_new("m20_beach_party_polling_thread") 
  1160. 	M20_thread.boat_validation = thread_new("m20_boat_validation_thread") 
  1161.  
  1162. 	if (coop_is_active()) then 
  1163. 		repeat 
  1164. 			if player_is_rc_driver( LOCAL_PLAYER, M20_status.my_rc_boat ) == false then 
  1165. 				m20_convo_play( M20_convo.lost_signal, true, true ) 
  1166. 				mission_end_failure( "m20", M20_text.failure_lost_signal ) 
  1167. 				return 
  1168. 			end 
  1169.  
  1170. 			thread_yield() 
  1171. 		until M20_status.beach_party_crashed 
  1172. 	else 
  1173. 		repeat 
  1174. 			-- Have the helicopter follow the target vehicle from here on out 
  1175. 			M20_thread.follow_rc_vehicle = thread_new("m20_wrapper_thread", helicopter_fly_to_direct_follow, M20_vehicle.angel_heli, 50, M20_status.my_rc_boat, nil, 150, true) 
  1176. 			thread_yield() 
  1177. 			thread_kill(M20_thread.follow_rc_vehicle) 
  1178.  
  1179. 			if player_is_rc_driver( LOCAL_PLAYER, M20_status.my_rc_boat ) == false then 
  1180. 				m20_convo_play( M20_convo.lost_signal, true, true ) 
  1181. 				mission_end_failure( "m20", M20_text.failure_lost_signal ) 
  1182. 				return 
  1183. 			end 
  1184. 		until (M20_status.beach_party_crashed) 
  1185.  
  1186. 		-- Stop following the vehicle (the thread should already have been killed, but just to be safe...) 
  1187. 		thread_kill(M20_thread.follow_rc_vehicle) 
  1188. 		M20_thread.follow_rc_vehicle = INVALID_THREAD_HANDLE 
  1189. 	end 
  1190. 	 
  1191. 	m20_coop_follow_obj_stop() 
  1192. 	m20_kinzie_watch_signal_stop() 
  1193. 	m20_convo_play( M20_convo.boat_takeover_ramp, false, true ) 
  1194. 	m20_convo_play( M20_convo.second_one_dead ) 
  1195. 	m20_convo_play( M20_convo.breaking_news_2 ) 
  1196. --	m20_convo_play( M20_convo.conference_announcement_4 ) 
  1197.  
  1198. 	if (vehicle_exists(M20_status.my_rc_boat) and not vehicle_is_destroyed(M20_status.my_rc_boat)) then 
  1199. 		vehicle_detonate(M20_status.my_rc_boat) 
  1200. 	end 
  1201. 	 
  1202. 	for i,vehicle in pairs(M20_vehicle.beach_party) do 
  1203. 		if (vehicle_exists(vehicle) and not vehicle_is_destroyed(vehicle)) then 
  1204. 			vehicle_detonate(vehicle) 
  1205. 		end 
  1206. 	end 
  1207. 	 
  1208. 	-- kill the target 
  1209. 	character_kill( M20_char.beach_wrestler ) 
  1210. 	marker_remove(M20_char.beach_wrestler) 
  1211.  
  1212. 	-- delay to show the boat exploding 
  1213. 	delay(4) 
  1214.  
  1215. 	-- Remove whatever message may still be displayed from the debug conversations being played 
  1216. 	message_remove_all() 
  1217. 	set_player_can_enter_exit_rc_vehicles(LOCAL_PLAYER, true) 
  1218.  
  1219. 	cleanup_groups(M20_group.rc_boat) 
  1220.  
  1221. 	objective_text_clear(0) 
  1222. end 
  1223.  
  1224.  
  1225. --[[ CRASH THE HELICOPTER ]]-- 
  1226.  
  1227.  
  1228. function m20_initialize_crash_the_helicopter() 
  1229. 	teleport_coop(M20_navpoint.cp_starts.crash_the_heli.player_local, M20_navpoint.cp_starts.crash_the_heli.player_remote, true) 
  1230.  
  1231. 	M20_char.angel = "NPC Angel CTH" 
  1232. 	M20_vehicle.angel_heli = "Veh Angel Heli CTH" 
  1233. 	M20_group.angel = { name = "GRP Angel CTH", chars = { M20_char.angel }, vehicles = { M20_vehicle.angel_heli } } 
  1234.  
  1235. 	-- Create Angel and the heli 
  1236. 	group_create(M20_group.angel.name, true) 
  1237. 	on_vehicle_destroyed("m20_angel_heli_destroyed_cb", M20_vehicle.angel_heli) 
  1238.  
  1239. 	if coop_is_active() == false then 
  1240. 		helicopter_set_max_bank_angle( M20_vehicle.angel_heli, M20_ANGEL_MAX_BANK ) 
  1241. 	end 
  1242.  
  1243. 	-- Put them in the vehicle before teleporting anything 
  1244. 	while (not character_is_in_vehicle(M20_char.angel, M20_vehicle.angel_heli)) do 
  1245. 		if (coop_is_active()) then 
  1246. 			vehicle_enter_teleport(M20_char.angel, M20_vehicle.angel_heli, VEHICLE_SEAT_PASSENGER) 
  1247. 		else 
  1248. 			vehicle_enter_teleport(M20_char.angel, M20_vehicle.angel_heli, VEHICLE_SEAT_DRIVER) 
  1249. 		end 
  1250. 		thread_yield() 
  1251. 	end 
  1252. 	vehicle_suppress_npc_exit(M20_vehicle.angel_heli, true) 
  1253. 	while (not character_is_in_vehicle(LOCAL_PLAYER, M20_vehicle.angel_heli)) do 
  1254. 		vehicle_enter_teleport(LOCAL_PLAYER, M20_vehicle.angel_heli, VEHICLE_SEAT_HELI_BACK_DOOR) 
  1255. 		thread_yield() 
  1256. 	end 
  1257. 	set_player_can_enter_exit_vehicles(LOCAL_PLAYER, false) 
  1258. 	if (coop_is_active()) then 
  1259. 		while (not character_is_in_vehicle(REMOTE_PLAYER, M20_vehicle.angel_heli)) do 
  1260. 			vehicle_enter_teleport(REMOTE_PLAYER, M20_vehicle.angel_heli, VEHICLE_SEAT_DRIVER) 
  1261. 			thread_yield() 
  1262. 		end 
  1263. 		set_player_can_enter_exit_vehicles(REMOTE_PLAYER, false) 
  1264. 	else 
  1265. 		-- Now teleport the vehicle to the floating position 
  1266. 		teleport_vehicle(M20_vehicle.angel_heli, M20_navpoint.angel_heli_teleport.heli) 
  1267. 		M20_thread.angel_heli_float = thread_new("m20_wrapper_thread", helicopter_fly_to_direct, M20_vehicle.angel_heli, HELI_DEFAULT_SPEED, M20_navpoint.angel_heli_float.heli) 
  1268. 	end 
  1269.  
  1270. 	if (not coop_is_active()) then 
  1271. 		thread_kill(M20_thread.angel_heli_float) 
  1272. 		M20_thread.angel_heli_float = INVALID_THREAD_HANDLE 
  1273. 	end 
  1274. end 
  1275.  
  1276. function m20_objective_crash_the_helicopter() 
  1277. 	-- Sub-objective 1: Go to helicopter 
  1278. 	objective_text( 0, M20_text.go_to_helicopter, nil, nil, SYNC_ALL, OI_ASSET_LOCATION ) 
  1279.  
  1280. 	M20_status.circular_path_reached = false 
  1281. 	m20_set_trigger( M20_trigger.circular_path, "m20_circular_path_reached_cb", true, true ) 
  1282.  
  1283. 	if not coop_is_active() then 
  1284. 		M20_thread.heli_to_heli = thread_new( "m20_heli_to_heli_thread", HELI_DEFAULT_SPEED ) 
  1285. 	end 
  1286.  
  1287. 	repeat 
  1288. 		thread_yield() 
  1289. 	until M20_status.circular_path_reached 
  1290.  
  1291. 	if not coop_is_active() then 
  1292. 		thread_kill( M20_thread.heli_to_heli ) 
  1293. 		M20_thread.heli_to_heli = thread_new( "m20_heli_to_heli_thread", 15 ) 
  1294. 	end 
  1295.  
  1296. 	-- create and manage random behavior of target civ heli 
  1297. 	M20_thread.heli_rand_flying = thread_new( "m20_heli_rand_flying_thread", M20_group.rc_heli.name, M20_vehicle.rc_heli, M20_char.rc_heli, M20_navpoint.rc_heli_teleport ) 
  1298.  
  1299. 	repeat 
  1300. 		thread_yield() 
  1301. 	until group_is_loaded( M20_group.rc_heli.name ) 
  1302.  
  1303. 	on_vehicle_destroyed( "m20_rc_heli_destroyed_cb", M20_vehicle.rc_heli ) 
  1304.  
  1305. 	on_collision( "m20_angel_heli_collided_cb", M20_vehicle.angel_heli ) 
  1306.  
  1307. 	-- Sub-objective 2: RC the helicopter 
  1308. 	objective_text_clear( 0 ) 
  1309. 	objective_text( 0, M20_text.rc_the_helicopter, nil, nil, SYNC_LOCAL, OI_ASSET_USE ) 
  1310.  
  1311. 	if coop_is_active() then 
  1312. 		objective_text( 1, M20_text.align_heli, nil, nil, SYNC_REMOTE, OI_ASSET_LOCATION ) 
  1313. 	end 
  1314.  
  1315. 	repeat 
  1316. 		thread_yield() 
  1317. 	until group_is_loaded( M20_group.rc_heli.name ) 
  1318.  
  1319. 	M20_status.player_has_rc_vehicle = false 
  1320.  
  1321. 	repeat 
  1322. 		thread_yield() 
  1323. 		if player_is_rc_driver( LOCAL_PLAYER, M20_vehicle.rc_heli ) then 
  1324. 			set_player_can_enter_exit_rc_vehicles( LOCAL_PLAYER, false ) 
  1325. 			M20_status.player_has_rc_vehicle = true 
  1326. 		end 
  1327. 	until M20_status.player_has_rc_vehicle 
  1328.  
  1329. 	-- Stop the vehicle so the player can actually control it 
  1330. 	vehicle_stop( M20_vehicle.rc_heli, false ) 
  1331. 	thread_kill( M20_thread.heli_rand_flying ) 
  1332. 	M20_thread.heli_rand_flying = INVALID_THREAD_HANDLE 
  1333. 	vehicle_max_speed( M20_vehicle.rc_heli, HELI_HIGH_SPEED ) 
  1334.  
  1335. 	-- Sub-objective 3: Crash the helicopter 
  1336. 	objective_text( 0, M20_text.crash_the_heli, nil, nil, SYNC_LOCAL, OI_ASSET_KILL ) 
  1337.  
  1338. 	if coop_is_active() then 
  1339. 		objective_text_clear( 1 ) 
  1340. 		m20_coop_follow_obj_start( M20_vehicle.rc_heli ) 
  1341. 	end 
  1342. 	 
  1343. 	m20_kinzie_watch_signal_start( M20_vehicle.rc_heli ) 
  1344. 	M20_thread.heli_rand_flying = thread_new( "m20_cth_target_behavior" ) 
  1345.  
  1346. 	repeat 
  1347. 		thread_yield() 
  1348. 	until group_is_loaded( M20_group.wrestler.name ) 
  1349.  
  1350. 	on_vehicle_destroyed( "m20_wrestler_heli_destroyed_cb", M20_vehicle.wrestler ) 
  1351.  
  1352. 	-- Only show the indicator on the helicopter you want to crash into 
  1353. 	marker_remove( M20_vehicle.rc_heli, SYNC_LOCAL ) 
  1354.  
  1355. 	if coop_is_active() == false then 
  1356. 		-- Have the helicopter follow the target vehicle from here on out 
  1357. 		vehicle_max_speed( M20_vehicle.angel_heli, HELI_HIGH_SPEED ) 
  1358. 		thread_kill( M20_thread.heli_to_heli ) 
  1359. 		M20_thread.follow_rc_vehicle = thread_new( "m20_wrapper_thread_forever", helicopter_fly_to_direct_follow, M20_vehicle.angel_heli, HELI_HIGH_SPEED, M20_vehicle.rc_heli, nil, 150, true ) 
  1360. 	end 
  1361.  
  1362. 	-- wait for heli to be destroyed 
  1363. 	while vehicle_exists( M20_vehicle.wrestler ) and vehicle_is_destroyed( M20_vehicle.wrestler ) == false do 
  1364. 		 
  1365. 		-- blow up the helis when they get close enough 
  1366. 		if get_dist( M20_vehicle.rc_heli, M20_vehicle.wrestler ) < M20_CTH_CRASH_DIST then 
  1367. 			vehicle_detonate( M20_vehicle.rc_heli ) 
  1368. 			vehicle_detonate( M20_vehicle.wrestler ) 
  1369. 		elseif player_is_rc_driver( LOCAL_PLAYER, M20_vehicle.rc_heli ) == false then 
  1370. 			m20_convo_play( M20_convo.lost_signal, true, true ) 
  1371. 			mission_end_failure( "m20", M20_text.failure_lost_signal ) 
  1372. 			return 
  1373. 		end 
  1374. 		 
  1375. 		thread_yield() 
  1376. 	end 
  1377. 	 
  1378. 	m20_kinzie_watch_signal_stop() 
  1379.  
  1380. 	if coop_is_active() then 
  1381. 		m20_coop_follow_obj_stop() 
  1382. 	else 
  1383. 		-- Stop the follow thread 
  1384. 		thread_kill( M20_thread.follow_rc_vehicle ) 
  1385. 		M20_thread.follow_rc_vehicle = INVALID_THREAD_HANDLE 
  1386. 	end 
  1387.  
  1388. 	-- delay a few seconds for camera to pan out from explosion 
  1389. 	delay( 4 ) 
  1390.  
  1391. 	on_collision( "", M20_vehicle.angel_heli ) 
  1392.  
  1393. 	thread_kill( M20_thread.heli_rand_flying ) 
  1394. 	M20_thread.heli_rand_flying = INVALID_THREAD_HANDLE 
  1395.  
  1396. 	m20_convo_play( M20_convo.third_one_dead ) 
  1397. 	m20_convo_play( M20_convo.breaking_news_3 ) 
  1398. --	m20_convo_play( M20_convo.conference_announcement_5 ) 
  1399.  
  1400. 	-- Remove whatever message may still be displayed from the debug conversations being played 
  1401. 	message_remove_all() 
  1402. 	set_player_can_enter_exit_rc_vehicles( LOCAL_PLAYER, true ) 
  1403.  
  1404. 	cleanup_groups( { M20_group.wrestler, M20_group.rc_heli } ) 
  1405.  
  1406. 	objective_text_clear(0) 
  1407. end 
  1408.  
  1409. -- controls the behavior of the target heli 
  1410. -- in crash the helicoptor objective 
  1411. function m20_cth_target_behavior() 
  1412. 	local path_iteration = 1 
  1413.  
  1414. 	-- bunch of crap needed to do inline pf'ing 
  1415. 	local direct = true 
  1416. 	local follow = "" 
  1417. 	local continue_at_goal = false 
  1418. 	local follow_dist = 0.0 
  1419. 	local directly_above = false 
  1420. 	local loop_path = false 
  1421.  
  1422. 	-- create and set up target heli 
  1423. 	group_create( M20_group.wrestler.name, true ) 
  1424. 	vehicle_enter_teleport( M20_char.wrestler, M20_vehicle.wrestler, VEHICLE_SEAT_DRIVER ) 
  1425. 	vehicle_enter_teleport( M20_char.pilot, M20_vehicle.wrestler, VEHICLE_SEAT_PASSENGER ) 
  1426. 	marker_add( M20_vehicle.wrestler, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_LOCAL ) 
  1427. 	teleport_vehicle( M20_vehicle.wrestler, M20_navpoint.wrestler_teleport ) 
  1428. 	helicopter_fly_to_do( M20_vehicle.wrestler, HELI_DEFAULT_SPEED, direct, follow, continue_at_goal, get_random_table_entry( M20_navpoint.wrestler_heli_rand ), follow_dist, directly_above, loop_path ) 
  1429.  
  1430. 	while vehicle_exists( M20_vehicle.wrestler ) and not vehicle_is_destroyed( M20_vehicle.wrestler ) do 
  1431.  
  1432. 		-- see if target should start fleeing 
  1433. 		if get_dist( M20_vehicle.rc_heli, M20_vehicle.wrestler ) < M20_CTH_FLEE_DIST then 
  1434. 			break 
  1435. 		end 
  1436.  
  1437. 		-- otherwise see if we should move to a new rand point 
  1438. 		if vehicle_pathfind_check_done( M20_vehicle.wrestler ) ~= 0 then 
  1439. 			delay( 5 ) 
  1440. 			helicopter_fly_to_do( M20_vehicle.wrestler, HELI_DEFAULT_SPEED, direct, follow, continue_at_goal, get_random_table_entry( M20_navpoint.wrestler_heli_rand ), follow_dist, directly_above, loop_path ) 
  1441. 		end 
  1442.  
  1443. 		thread_yield() 
  1444. 	end 
  1445.  
  1446. 	thread_new( "vehicle_exit_dive", M20_char.pilot ) 
  1447. 	 
  1448. 	delay( 1 ) 
  1449. 	 
  1450. 	if vehicle_exists( M20_vehicle.wrestler ) and not vehicle_is_destroyed( M20_vehicle.wrestler ) then 
  1451. 		m20_convo_play( M20_convo.third_luchadore ) 
  1452. 	end 
  1453. 	 
  1454. 	local target_path_index  = 1 
  1455. 	local reverse = false 
  1456. 	local paths = M20_scripted_path.cth_target_flee_paths 
  1457. 	local speed 
  1458.  
  1459. 	while vehicle_exists( M20_vehicle.wrestler ) and not vehicle_is_destroyed( M20_vehicle.wrestler ) do 
  1460. 		if paths[ target_path_index ].super_slow == true then 
  1461. 			speed = 10 
  1462. 		else 
  1463. 			speed = 25 
  1464. 		end 
  1465. 		 
  1466. 		helicopter_fly_to( M20_vehicle.wrestler, speed, paths[ target_path_index ].sp_name, reverse ) 
  1467.  
  1468. 		if reverse then 
  1469. 			target_path_index = get_random_table_entry( paths[ target_path_index ].p ) 
  1470. 		else 
  1471. 			target_path_index = get_random_table_entry( paths[ target_path_index ].n ) 
  1472. 		end 
  1473. 		 
  1474. 		if target_path_index < 0 then 
  1475. 			reverse = true 
  1476. 			target_path_index = target_path_index * -1 
  1477. 		else 
  1478. 			reverse = false 
  1479. 		end 
  1480. 	end 
  1481. 	 
  1482. 	m20_convo_cleanup( M20_convo ) 
  1483. end 
  1484.  
  1485. --[[ LAST MAN STANDING, TANKS TO YOU ]]-- 
  1486.  
  1487. function m20_initialize_airport() 
  1488. 	teleport_coop(M20_navpoint.cp_starts.airport.player_local, M20_navpoint.cp_starts.airport.player_remote, true) 
  1489.  
  1490. 	M20_char.angel = "NPC Angel LW" 
  1491. 	M20_vehicle.angel_heli = "Veh Angel Heli LW" 
  1492. 	M20_group.angel = { name = "GRP Angel LW", chars = { M20_char.angel }, vehicles = { M20_vehicle.angel_heli } } 
  1493.  
  1494. 	-- Create Angel and the heli 
  1495. 	group_create(M20_group.angel.name, true) 
  1496. 	on_vehicle_destroyed("m20_angel_heli_destroyed_cb", M20_vehicle.angel_heli) 
  1497.  
  1498. 	if coop_is_active() == false then 
  1499. 		helicopter_set_max_bank_angle( M20_vehicle.angel_heli, M20_ANGEL_MAX_BANK ) 
  1500. 	end 
  1501.  
  1502. 	-- Put them in the vehicle before teleporting anything 
  1503. 	while (not character_is_in_vehicle(M20_char.angel, M20_vehicle.angel_heli)) do 
  1504. 		if (coop_is_active()) then 
  1505. 			vehicle_enter_teleport(M20_char.angel, M20_vehicle.angel_heli, VEHICLE_SEAT_PASSENGER) 
  1506. 		else 
  1507. 			vehicle_enter_teleport(M20_char.angel, M20_vehicle.angel_heli, VEHICLE_SEAT_DRIVER) 
  1508. 		end 
  1509. 		thread_yield() 
  1510. 	end 
  1511. 	vehicle_suppress_npc_exit(M20_vehicle.angel_heli, true) 
  1512. 	while (not character_is_in_vehicle(LOCAL_PLAYER, M20_vehicle.angel_heli)) do 
  1513. 		vehicle_enter_teleport(LOCAL_PLAYER, M20_vehicle.angel_heli, VEHICLE_SEAT_HELI_BACK_DOOR) 
  1514. 		thread_yield() 
  1515. 	end 
  1516. 	set_player_can_enter_exit_vehicles(LOCAL_PLAYER, false) 
  1517. 	if (coop_is_active()) then 
  1518. 		while (not character_is_in_vehicle(REMOTE_PLAYER, M20_vehicle.angel_heli)) do 
  1519. 			vehicle_enter_teleport(REMOTE_PLAYER, M20_vehicle.angel_heli, VEHICLE_SEAT_DRIVER) 
  1520. 			thread_yield() 
  1521. 		end 
  1522. 		set_player_can_enter_exit_vehicles(REMOTE_PLAYER, false) 
  1523. 	else 
  1524. 		-- Now teleport the vehicle to the floating position 
  1525. 		teleport_vehicle(M20_vehicle.angel_heli, M20_navpoint.angel_heli_teleport.airport) 
  1526. 		M20_thread.angel_heli_float = thread_new("m20_wrapper_thread", helicopter_fly_to_direct, M20_vehicle.angel_heli, HELI_DEFAULT_SPEED, M20_navpoint.angel_heli_float.airport) 
  1527. 	end 
  1528.  
  1529. 	if (not coop_is_active()) then 
  1530. 		thread_kill(M20_thread.angel_heli_float) 
  1531. 		M20_thread.angel_heli_float = INVALID_THREAD_HANDLE 
  1532. 	end 
  1533. end 
  1534.  
  1535. function m20_objective_airport() 
  1536. 	objective_text(0, M20_text.go_to_airport, nil, nil, SYNC_ALL, OI_ASSET_LOCATION) 
  1537.  
  1538. 	M20_status.tank_path_reached = false 
  1539. 	m20_set_trigger(M20_trigger.tank_path, "m20_tank_path_reached_cb", true, true) 
  1540.  
  1541. 	if (not coop_is_active()) then 
  1542. 		M20_thread.heli_to_airport = thread_new("m20_heli_to_airport_thread", HELI_DEFAULT_SPEED) 
  1543. 	end 
  1544.  
  1545. 	repeat 
  1546. 		thread_yield() 
  1547. 	until (M20_status.tank_path_reached) 
  1548.  
  1549. 	M20_thread.convo_fourth_luchadore = thread_new("m20_wrapper_thread", audio_play_persona_line, LOCAL_PLAYER, "M20_Fourth_Luchadore") 
  1550.  
  1551. 	if (not coop_is_active()) then 
  1552. 		M20_thread.heli_to_airport = thread_new("m20_heli_around_airport_thread", 15) 
  1553. 	end 
  1554.  
  1555. 	M20_status.last_wrestler_killed = false 
  1556. 	group_create(M20_group.stag_tank.name, true) 
  1557. 	group_create(M20_group.airport.name, true) 
  1558.  
  1559. 	for i,tank in pairs( M20_vehicle.stag_tank ) do 
  1560. 		-- no weapons for the player 
  1561. 		on_vehicle_destroyed("m20_stag_tank_destroyed_cb", tank) 
  1562. 	end 
  1563.  
  1564. 	objective_text_clear(0) 
  1565. end 
  1566.  
  1567. function m20_objective_tanks_to_you() 
  1568. 	M20_status.rc_tank_destroyed = false 
  1569. 	local rc_tank = nil 
  1570.  
  1571. 	-- spawn the last wrestler 
  1572. 	group_create( M20_group.last_wrestler, true ) 
  1573. 	on_death( "m20_last_wrestler_killed_cb", M20_char.last_wrestler ) 
  1574. 	set_dont_attack_me_on_sight_flag( M20_char.last_wrestler, true ) 
  1575. 	M20_thread.airport_lw_behavior = thread_new( "m20_airport_lw_behavior" ) 
  1576. 	 
  1577.  
  1578. 	repeat 
  1579. 		M20_status.stag_tanks_remaining = 0 
  1580.  
  1581. 		for i,tank in pairs( M20_vehicle.stag_tank ) do 
  1582. 			if vehicle_is_destroyed( tank)  == false then 
  1583. 				marker_add( tank, MINIMAP_ICON_USE, OI_ASSET_USE, OI_FLAGS_FULL, SYNC_LOCAL ) 
  1584. 				M20_status.stag_tanks_remaining = M20_status.stag_tanks_remaining + 1 
  1585. 				 
  1586. 				if coop_is_active() then 
  1587. 					marker_add( tank, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_FULL, SYNC_REMOTE ) 
  1588. 				end 
  1589. 			end 
  1590. 		end 
  1591.  
  1592. 		-- If there are no tanks left, fail the mission 
  1593. 		if (M20_status.stag_tanks_remaining == 0) then 
  1594. 			mission_end_failure("m20", M20_text.failure_no_tanks_to_you) 
  1595. 			return 
  1596. 		end 
  1597.  
  1598. 		-- Sub-objective 1: RC a STAG tank 
  1599. 		objective_text(0, M20_text.rc_a_tank, nil, nil, SYNC_LOCAL, OI_ASSET_USE) 
  1600. 		if (coop_is_active()) then 
  1601. 			objective_text(1, M20_text.align_to_tanks, nil, nil, SYNC_REMOTE, OI_ASSET_LOCATION) 
  1602. 		end 
  1603.  
  1604. 		if (M20_status.rc_tank_destroyed) then 
  1605. 			M20_status.rc_tank_destroyed = false 
  1606.  
  1607. 			if (not coop_is_active()) then 
  1608. 				M20_thread.heli_to_airport = thread_new("m20_heli_around_airport_thread", 15) 
  1609. 			end 
  1610. 		end 
  1611.  
  1612. 		-- wait for player to rc a tank 
  1613. 		M20_status.player_has_rc_vehicle = false 
  1614.  
  1615. 		repeat 
  1616. 			thread_yield() 
  1617. 			for i,stag_tank in pairs(M20_vehicle.stag_tank) do 
  1618. 				if (vehicle_exists(stag_tank) and not vehicle_is_destroyed(stag_tank)) then 
  1619. 					if (player_is_rc_driver(LOCAL_PLAYER, stag_tank)) then 
  1620. 						rc_tank = stag_tank 
  1621. 						set_player_can_enter_exit_rc_vehicles(LOCAL_PLAYER, false) 
  1622. 						M20_status.player_has_rc_vehicle = true 
  1623. 						break 
  1624. 					end 
  1625. 				end 
  1626. 			end 
  1627. 		until  M20_status.player_has_rc_vehicle 
  1628.  
  1629. 		-- create a driver for the tank so the soldiers will attack it 
  1630. 		group_create( M20_group.airport_tank_driver.name, true ) 
  1631. 		vehicle_enter_teleport( M20_char.stag_tank_driver, rc_tank, VEHICLE_SEAT_DRIVER ) 
  1632. 		vehicle_suppress_npc_exit( rc_tank, true ) 
  1633. 		set_team( M20_char.stag_tank_driver, "Playas" ) 
  1634.  
  1635. 		-- npcs attack player in a bit 
  1636. 		if M20_thread.airport_attack_player ~= INVALID_THREAD_HANDLE then 
  1637. 			thread_kill( M20_thread.airport_attack_player ) 
  1638. 		end 
  1639.  
  1640. 		ai_add_enemy_target( M20_char.last_wrestler, M20_char.stag_tank_driver, ATTACK_NOW, true ) 
  1641.  
  1642. 		M20_thread.airport_attack_player = thread_new( "m20_airport_attack_player_in_n_seconds", rc_tank, 3 ) 
  1643.  
  1644. 		-- give the rc tank a bump in hp 
  1645. 		-- set_max_hit_points( rc_tank, get_max_hit_points( rc_tank ) * 4 , true) 
  1646.  
  1647. 		on_vehicle_destroyed( "m20_rc_tank_destroyed_cb", rc_tank ) 
  1648. 		on_vehicle_enter_water( "m20_rc_tank_destroyed_cb", rc_tank ) 
  1649. 		marker_remove( M20_vehicle.stag_tank ) 
  1650.  
  1651. 		-- Sub-objective 2: Kill the last wrestler 
  1652. 		objective_text( 0, M20_text.kill_the_last_wrestler, nil, nil, SYNC_LOCAL, OI_ASSET_KILL ) 
  1653.  
  1654. 		-- mark target for local player 
  1655. 		marker_add( M20_vehicle.lw_truck, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_LOCAL) 
  1656. 		 
  1657. 		m20_kinzie_watch_signal_start( rc_tank ) 
  1658.  
  1659. 		if (coop_is_active()) then 
  1660. 			objective_text_clear( 1 ) 
  1661. 			m20_coop_follow_obj_start( rc_tank ) 
  1662. 		else 
  1663. 			-- Have the helicopter follow the target vehicle from here on out 
  1664. 			M20_thread.follow_rc_vehicle = thread_new("m20_wrapper_thread", helicopter_fly_to_direct_follow, M20_vehicle.angel_heli, 50, rc_tank, nil, 50, true) 
  1665. 		end 
  1666.  
  1667. 		-- wait until rc tank is destroyed or the wrestler is dead 
  1668. 		repeat 
  1669. 			thread_yield() 
  1670. 		until M20_status.rc_tank_destroyed or M20_status.last_wrestler_killed 
  1671. 		 
  1672. 		inv_item_equip(M20_weapon.rc_gun, LOCAL_PLAYER) 
  1673. 		m20_kinzie_watch_signal_stop() 
  1674.  
  1675. 		if coop_is_active() then 
  1676. 			m20_coop_follow_obj_stop() 
  1677. 		else 
  1678. 			-- Stop following the vehicle (the thread should already have been killed, but just to be safe...) 
  1679. 			thread_kill(M20_thread.follow_rc_vehicle) 
  1680. 			M20_thread.follow_rc_vehicle = INVALID_THREAD_HANDLE 
  1681. 		end 
  1682.  
  1683. 		marker_remove( M20_vehicle.lw_truck, SYNC_LOCAL ) 
  1684.  
  1685. 		objective_text_clear(0) 
  1686.  
  1687. 	until (M20_status.last_wrestler_killed) 
  1688.  
  1689. 	audio_play_persona_line(LOCAL_PLAYER, "M20_Fourth_One_Dead") 
  1690. end 
  1691.  
  1692. function m20_airport_attack_player_in_n_seconds( rc_tank, seconds ) 
  1693. 	-- wait a bit before having tank drivers to attack player 
  1694. 	delay( seconds ) 
  1695.  
  1696. 	-- make other tanks attack rc'd tank 
  1697. 	local tank_driver = vehicle_get_driver( rc_tank, false ) 
  1698.  
  1699. 	for i,npc in pairs( M20_char.stag_tank ) do 
  1700. 		if character_is_dead( npc ) == false then 
  1701. 			ai_add_enemy_target( npc, tank_driver, ATTACK_NOW, true ) 
  1702. 		end 
  1703. 	end 
  1704.  
  1705. 	M20_thread.airport_attack_player = INVALID_THREAD_HANDLE 
  1706. end 
  1707.  
  1708. function m20_airport_lw_behavior() 
  1709. 	local target_path_index  = 1 
  1710. 	local paths = M20_scripted_path.airport_wrestler_flee_paths 
  1711.  
  1712. 	-- turn off his ai as he seems to like getting distracted 
  1713. 	set_ignore_ai_flag( M20_char.last_wrestler, true ) 
  1714. 	turn_invulnerable( M20_char.last_wrestler ) 
  1715.  
  1716. 	-- run to truck 
  1717. 	ai_do_scripted_move( M20_char.last_wrestler, M20_vehicle.lw_truck , true, false) 
  1718.  
  1719. 	repeat 
  1720. 		if character_is_dead( M20_char.last_wrestler ) then 
  1721. 			return 
  1722. 		end 
  1723.  
  1724. 		thread_yield() 
  1725. 	until get_dist( M20_char.last_wrestler, M20_vehicle.lw_truck ) < 4 or character_is_dead( M20_char.last_wrestler ) 
  1726.  
  1727. 	-- get in truck 
  1728. 	ai_clear_scripted_action( M20_char.last_wrestler ) 
  1729. 	vehicle_enter_teleport( M20_char.last_wrestler, M20_vehicle.lw_truck, 0 ) 
  1730. 	vehicle_suppress_npc_exit( M20_vehicle.lw_truck ) 
  1731. 	vehicle_disable_chase( M20_vehicle.lw_truck ) 
  1732. 	vehicle_disable_flee( M20_vehicle.lw_truck ) 
  1733. 	on_vehicle_destroyed( "m20_last_wrestler_killed_cb", M20_vehicle.lw_truck ) 
  1734. 	vehicle_set_keyframed_physics( M20_vehicle.lw_truck, false ) 
  1735. 	set_ignore_ai_flag( M20_char.last_wrestler, false ) 
  1736.  
  1737. 	-- make truck killable 
  1738. 	set_max_hit_points( M20_vehicle.lw_truck, get_max_hit_points( M20_vehicle.lw_truck ) * 4, true ) 
  1739. 	vehicle_set_invulnerable( M20_vehicle.lw_truck, false ) 
  1740.  
  1741. 	local reverse = false 
  1742. 	local target_path_index  = 1 
  1743. 	local paths = M20_scripted_path.airport_wrestler_flee_paths 
  1744.  
  1745. 	-- ongoing cyclicle fleeing 
  1746. 	while true do 
  1747. 		vehicle_pathfind_to( M20_vehicle.lw_truck, paths[ target_path_index ].sp_name, true, false, false, true ) 
  1748.  
  1749. 		-- bail if we are done 
  1750. 		if character_is_dead( M20_char.last_wrestler ) or vehicle_is_destroyed( M20_vehicle.lw_truck ) then 
  1751. 			break 
  1752. 		end 
  1753.  
  1754. 		if reverse then 
  1755. 			target_path_index = get_random_table_entry( paths[ target_path_index ].p ) 
  1756. 		else 
  1757. 			target_path_index = get_random_table_entry( paths[ target_path_index ].n ) 
  1758. 		end 
  1759. 		 
  1760. 		if target_path_index < 0 then 
  1761. 			reverse = true 
  1762. 			target_path_index = target_path_index * -1 
  1763. 		else 
  1764. 			reverse = false 
  1765. 		end 
  1766.  
  1767. 		thread_yield() 
  1768. 	end 
  1769. end 
  1770.  
  1771.  
  1772.  
  1773. -- *************************************************** 
  1774. -- 
  1775. -- m20_initialize Helper Functions 
  1776. -- 
  1777. -- *************************************************** 
  1778.  
  1779.  
  1780.  
  1781.  
  1782.  
  1783. -- Handle any common initialization 
  1784. -- 
  1785. function m20_initialize_common() 
  1786. 	-- Set it to midday 
  1787. 	--set_time_of_day(12, 00) 
  1788.  
  1789. 	notoriety_force_no_spawn("luchadores", true) 
  1790. 	notoriety_force_no_spawn("deckers", true) 
  1791. 	notoriety_force_no_spawn("morningstar", true) 
  1792. 	notoriety_force_no_spawn("police", true) 
  1793.  
  1794. 	M20_previous_rc_range = rc_set_max_signal_range( M20_RC_RANGE ) 
  1795. 	 
  1796. 	party_dismiss_all() 
  1797. 	party_set_recruitable( false ) 
  1798. 	 
  1799. 	mission_set_cancel_warp_location( M20_navpoint.end_local, M20_navpoint.end_remote ) 
  1800. end 
  1801.  
  1802. -- Checkpoint specific initialization 
  1803. -- 
  1804. -- checkpoint:		The checkpoint to be initialized 
  1805. function m20_initialize_checkpoint(checkpoint) 
  1806.  
  1807. 	if (checkpoint == MISSION_START_CHECKPOINT) then 
  1808. 		m20_initialize_mission_start() 
  1809. 	elseif (checkpoint == M20_CHECKPOINT_CRASH_THE_CAR) then 
  1810. 		m20_initialize_crash_the_car() 
  1811. 	elseif (checkpoint == M20_CHECKPOINT_CRASH_THE_BOAT) then 
  1812. 		m20_initialize_crash_the_boat() 
  1813. 	elseif (checkpoint == M20_CHECKPOINT_CRASH_THE_HELI) then 
  1814. 		m20_initialize_crash_the_helicopter() 
  1815. 	elseif (checkpoint == M20_CHECKPOINT_AIRPORT) then 
  1816. 		m20_initialize_airport() 
  1817. 	end 
  1818.  
  1819. end 
  1820.  
  1821.  
  1822.  
  1823.  
  1824.  
  1825. -- *************************************************** 
  1826. -- 
  1827. -- Miscellaneous m20 Helper Funcrtions 
  1828. -- 
  1829. -- *************************************************** 
  1830.  
  1831.  
  1832.  
  1833.  
  1834.  
  1835. -- Set a trigger enabled with a mission marker 
  1836. -- 
  1837. -- trigger:				(string) Name of the trigger 
  1838. -- trigger_callback:	(string) Function name to call when trigger is activated 
  1839. -- add_waypoint:		(bool, optional) true to add a waypoint, false otherwise (defaults to true) 
  1840. -- add_marker:			(bool, optional) true to add a marker, false otherwise (defaults to true) 
  1841. -- 
  1842. function m20_set_trigger(trigger, trigger_callback, add_waypoint, add_marker) 
  1843. 	trigger_enable(trigger, true) 
  1844.  
  1845. 	if (add_waypoint ~= false) then 
  1846. 		mission_waypoint_add(trigger) 
  1847. 	end 
  1848.  
  1849. 	if (add_marker ~= false) then 
  1850. 		marker_add_trigger(trigger, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL) 
  1851. 	end 
  1852.  
  1853. 	on_trigger(trigger_callback, trigger) 
  1854. end 
  1855.  
  1856. -- Disable trigger 
  1857. -- 
  1858. -- trigger:		(string) Name of the trigger 
  1859. -- 
  1860. function m20_clear_trigger(trigger) 
  1861. 	on_trigger("", trigger) 
  1862. 	trigger_enable(trigger, false) 
  1863. 	marker_remove_trigger(trigger, SYNC_ALL) 
  1864. 	mission_waypoint_remove() 
  1865. end 
  1866.  
  1867. -- Play an audio conversation 
  1868. -- 
  1869. -- convo:	(table) the conversation to play - contains a name, handle, and table of non-player speakers 
  1870. -- wait:		(bool) don't return until convo has played 
  1871. -- clear:		(bool) clear any pending convos 
  1872. -- 
  1873. function m20_convo_play( convo, wait, clear ) 
  1874. 	if (convo == nil) then 
  1875. 		return 
  1876. 	end 
  1877. 	 
  1878. 	if clear == true then 
  1879. 		m20_convo_cleanup( M20_convo ) 
  1880. 	end 
  1881.  
  1882. 	-- add to end of queue 
  1883. 	M20_convo_queue[ #M20_convo_queue + 1 ] = convo 
  1884.  
  1885. 	-- start a manager thread if needed 
  1886. 	if M20_thread.convo_manager == INVALID_THREAD_HANDLE then 
  1887. 		M20_thread.convo_manager = thread_new( "m20_convo_manager" ) 
  1888. 	end 
  1889.  
  1890. 	-- wait for convo to finish playing if requested 
  1891. 	if wait == true  then 
  1892. 		local found = true 
  1893.  
  1894. 		while found == true do 
  1895. 			thread_yield() 
  1896. 			found = false 
  1897.  
  1898. 			-- see if convo is still playing 
  1899. 			for i, c in pairs( M20_convo_queue ) do 
  1900. 				if c == convo then 
  1901. 					found = true 
  1902. 					break 
  1903. 				end 
  1904. 			end -- for 
  1905. 		end -- while 
  1906. 	end -- if 
  1907. end -- function 
  1908.  
  1909. function m20_convo_manager() 
  1910. 	local convo 
  1911.  
  1912. 	while #M20_convo_queue > 0 do 
  1913. 		convo = M20_convo_queue[ 1 ] 
  1914. 		convo.persona_handles = { } 
  1915.  
  1916. 		-- Load 2D personas when necessary 
  1917. 		if convo.speakers_2d ~= nil then 
  1918. 			for i, persona in pairs( convo.speakers_2d ) do 
  1919. 				convo.persona_handles[ i ] = audio_persona_load_2d( persona ) 
  1920. 			 
  1921. 				-- if we needed to load a persona, delay some to allow soundbank to load.  Could be heavy streaming going on 
  1922. 				delay(.5) 
  1923. 			end 
  1924. 		end 
  1925.  
  1926. 		-- Load the conversation 
  1927. 		if convo.persona_3d_params ~= nil then 
  1928. 			audio_play_persona_line( unpack( convo.persona_3d_params ) ) 
  1929. 			 
  1930. 			debug_print( "MAD", "playing 3D persona line '".. convo.persona_3d_params[ 2 ] .. "'\n" ) 
  1931. 			 
  1932. 			while audio_persona_line_playing( convo.persona_3d_params[ 1 ] ) == true do 
  1933. 				thread_yield() 
  1934. 			end 
  1935. 		elseif convo.persona_2d_params ~= nil then 
  1936. 			-- a speakers_2d must have been specified 
  1937. 			if convo.persona_handles[ 1 ] ~= nil then 
  1938. 				convo.audio_id = audio_play_persona_line_2d( convo.persona_handles[ 1 ], convo.persona_2d_params[ 1 ] ) 
  1939.  
  1940. 				debug_print( "MAD", "playing 2D persona line '".. convo.persona_2d_params[ 1 ] .. "'\n" ) 
  1941. 				 
  1942. 				-- see note below 
  1943. 				if convo.persona_2d_params[ 2 ] ~= nil then 
  1944. 					delay( convo.persona_2d_params[ 2 ] ) 
  1945. 				end 
  1946. 				 
  1947. 				-- audio_is_playing() doesn't currently work with this id 
  1948. 				-- I am told it should so I'll leave it here but the delay above 
  1949. 				-- is what's going to make this work right now  -SDR 
  1950. 				while audio_is_playing( convo.audio_id ) == true do 
  1951. 					thread_yield() 
  1952. 				end 
  1953. 				 
  1954. 				convo.audio_id = nil 
  1955. 			end 
  1956. 		elseif convo.audio_event_params ~= nil then 
  1957. 			convo.audio_id = audio_object_post_event( unpack( convo.audio_event_params ) ) 
  1958. 			 
  1959. 			while audio_is_playing( convo.audio_id ) == true do 
  1960. 				thread_yield() 
  1961. 			end 
  1962. 			 
  1963. 			convo.audio_id = nil 
  1964. 		elseif convo.convo_name ~= nil then 
  1965. 			-- load convo 
  1966. 			if convo.player_speaks then 
  1967. 				convo.convo_handle = audio_conversation_load( convo.convo_name ) 
  1968. 			else 
  1969. 				convo.convo_handle = audio_conversation_load_direct( convo.convo_name ) 
  1970. 			end 
  1971.  
  1972. 			-- play the conversation 
  1973. 			debug_print( "MAD", "Playing convo: " .. convo.convo_name .. "\n" ) 
  1974. 			audio_conversation_play( convo.convo_handle ) 
  1975. 			thread_yield() 
  1976.  
  1977. 			-- wait for the conversation to end 
  1978. 			audio_conversation_wait_for_end( convo.convo_handle ) 
  1979. 			convo.convo_handle = nil 
  1980. 		end 
  1981.  
  1982. 		-- clean up personas 
  1983. 		for i, handle in pairs( convo.persona_handles ) do 
  1984. 			audio_persona_remove_2d( handle ) 
  1985. 		end 
  1986. 		convo.persona_handles = nil 
  1987.  
  1988. 		-- delay if needed 
  1989. 		if convo.delay_after ~= nil then 
  1990. 			delay( convo.delay_after ) 
  1991. 		end 
  1992.  
  1993. 		-- roll up the queue 
  1994. 		if #M20_convo_queue > 1 then 
  1995. 			for i = 2, #M20_convo_queue do 
  1996. 				M20_convo_queue[ i - 1 ] = M20_convo_queue[ i ] 
  1997. 			end 
  1998. 		end 
  1999.  
  2000. 		M20_convo_queue[ #M20_convo_queue ] = nil 
  2001. 	end 
  2002.  
  2003. 	-- if there's no convos to play just exit the thread 
  2004. 	M20_thread.convo_manager  = INVALID_THREAD_HANDLE 
  2005. end 
  2006.  
  2007.  
  2008.  
  2009.  
  2010.  
  2011. -- ************************* 
  2012. -- 
  2013. -- Callback functions 
  2014. -- 
  2015. -- ************************* 
  2016.  
  2017.  
  2018. -- Callback for the RC car hitting a ped 
  2019. -- 
  2020. -- vehicle:	(string) name of the vehicle that hit a ped 
  2021. -- 
  2022. function m20_rc_car_hit_ped_cb(vehicle, human) 
  2023. 	if M20_status.rc_car_peds_hit > PEDS_TO_HIT or M20_peds_hit[ human ] == true then 
  2024. 		return 
  2025. 	end 
  2026.  
  2027. 	M20_status.rc_car_peds_hit = M20_status.rc_car_peds_hit + 1 
  2028. 	M20_peds_hit[ human ] = true 
  2029. end 
  2030.  
  2031.  
  2032. -- Callback for the RC car being destroyed 
  2033. -- 
  2034. -- vehicle:	(string) name of the vehicle that was destroyed 
  2035. -- 
  2036. function m20_rc_car_destroyed_cb(vehicle) 
  2037. 	-- Can't blow this thing up before the people have been killed 
  2038. 	if (not (M20_status.rc_car_peds_hit >= PEDS_TO_HIT)) then 
  2039. 		mission_end_failure("m20", M20_text.failure_ctc_destroyed) 
  2040. 		return 
  2041. 	end 
  2042.  
  2043. 	-- when the vehicle gets destroyed, the audio listening position moves away, and you  
  2044. 	-- cannot hear the explosion.  Post a 2D event for an explosion 
  2045. 	audio_object_post_event("M20_RC_Vehicle_Explode") 
  2046.  
  2047. 	on_vehicle_destroyed("", vehicle) 
  2048. 	set_player_can_enter_exit_rc_vehicles(LOCAL_PLAYER, true) 
  2049. 	if (coop_is_active()) then 
  2050. 		set_player_can_enter_exit_rc_vehicles(REMOTE_PLAYER, true) 
  2051. 	end 
  2052. 	marker_remove(vehicle) 
  2053. 	M20_status.rc_car_destroyed = true 
  2054. end 
  2055.  
  2056. -- Callback for the RC boat being destroyed 
  2057. -- 
  2058. -- vehicle:	(string) name of the vehicle that was destroyed 
  2059. -- 
  2060. function m20_rc_boat_destroyed_cb(vehicle) 
  2061. 	 
  2062. 	-- when the boat gets destroyed, the audio listening position moves away, and you  
  2063. 	-- cannot hear the explosion.  Post a 2D event for an explosion 
  2064. 	audio_object_post_event("M20_RC_Vehicle_Explode") 
  2065.  
  2066. 	on_vehicle_destroyed("", vehicle) 
  2067. 	audio_play( "M20_Explo" ) 
  2068. 	set_player_can_enter_exit_rc_vehicles(LOCAL_PLAYER, true) 
  2069. 	if (coop_is_active()) then 
  2070. 		set_player_can_enter_exit_rc_vehicles(REMOTE_PLAYER, true) 
  2071. 	end 
  2072. 	if (not M20_status.beach_party_crashed) then 
  2073. 		mission_end_failure("m20", M20_text.failure_ctb_destroyed) 
  2074. 	end 
  2075. 	--marker_remove(vehicle) 
  2076. 	M20_status.rc_boat_destroyed = true 
  2077. end 
  2078.  
  2079. -- Callback for one of the RC tanks being destroyed 
  2080. -- 
  2081. -- vehicle:	(string) name of the vehicle that was destroyed 
  2082. -- 
  2083. function m20_rc_tank_destroyed_cb(vehicle) 
  2084. 	on_vehicle_destroyed("", vehicle) 
  2085. 	audio_play( "M20_Explo" ) 
  2086. 	 
  2087. 	-- this also gets called if the tank enters water 
  2088. 	if vehicle_is_destroyed( vehicle ) == false then 
  2089. 		vehicle_detonate( vehicle ) 
  2090. 	end 
  2091. 	 
  2092. 	set_player_can_enter_exit_rc_vehicles(LOCAL_PLAYER, true) 
  2093. 	 
  2094. 	if coop_is_active() then 
  2095. 		set_player_can_enter_exit_rc_vehicles(REMOTE_PLAYER, true) 
  2096. 	end 
  2097. 	 
  2098. 	marker_remove(vehicle) 
  2099. 	M20_status.rc_tank_destroyed = true 
  2100.  
  2101. 		-- destory the driver - we'll resurrect him if another tank gets rc'd 
  2102. 	group_destroy( M20_group.airport_tank_driver.name ) 
  2103.  
  2104. end 
  2105.  
  2106. -- Callback for reaching the gym trigger (co-op only) 
  2107. -- 
  2108. function m20_gym_reached_cb() 
  2109. 	M20_status.gym_reached = true 
  2110. end 
  2111.  
  2112. -- Callback for reaching the boat/harbor trigger (co-op only) 
  2113. -- 
  2114. function m20_boat_reached_cb() 
  2115. 	M20_status.boat_reached = true 
  2116. end 
  2117.  
  2118. -- Callback for Angel's heli reaching the path around the wrestler's heli 
  2119. -- 
  2120. function m20_circular_path_reached_cb() 
  2121. 	m20_clear_trigger(M20_trigger.circular_path) 
  2122. 	M20_status.circular_path_reached = true 
  2123. end 
  2124.  
  2125. -- Callback for Angel's heli being destroyed 
  2126. -- 
  2127. -- heli:	(string) name of Angel's heli 
  2128. -- 
  2129. function m20_angel_heli_destroyed_cb(heli) 
  2130. 	-- NOTE: When Angel's heli is destroyed, there is no arbitrary delay 
  2131. 	-- because this is a failure condition that trumps all other scenarios 
  2132. 	on_vehicle_destroyed("", heli) 
  2133. 	mission_end_failure("m20", M20_text.failure_angel_heli_destroyed) 
  2134. end 
  2135.  
  2136. -- Callback for the RC heli being destroyed 
  2137. -- 
  2138. -- vehicle:	(string) name of the RC heli 
  2139. -- 
  2140. function m20_rc_heli_destroyed_cb(vehicle) 
  2141. 	on_vehicle_destroyed("", vehicle) 
  2142. 	marker_remove(vehicle) 
  2143. 	set_player_can_enter_exit_rc_vehicles(LOCAL_PLAYER, true) 
  2144. 	if (coop_is_active()) then 
  2145. 		set_player_can_enter_exit_rc_vehicles(REMOTE_PLAYER, true) 
  2146. 	end 
  2147. 	-- Arbitrary delay to make sure Angel's heli destroyed callback occurs first if they collided with each other 
  2148. 	delay(.5) 
  2149. 	--if (not M20_status.wrestler_heli_destroyed) then 
  2150. 	if (vehicle_exists(M20_vehicle.wrestler) and not vehicle_is_destroyed(M20_vehicle.wrestler)) then 
  2151. 		mission_end_failure("m20", M20_text.failure_rc_heli_destroyed) 
  2152. 	end 
  2153. end 
  2154.  
  2155. -- Callback for the wrestler's heli being destroyed 
  2156. -- 
  2157. -- vehicle:	(string) name of the wrestler's heli 
  2158. -- 
  2159. function m20_wrestler_heli_destroyed_cb(vehicle) 
  2160. 	on_vehicle_destroyed("", vehicle) 
  2161. 	audio_play( "M20_Explo" ) 
  2162. 	marker_remove(vehicle) 
  2163. 	set_player_can_enter_exit_rc_vehicles(LOCAL_PLAYER, true) 
  2164. 	if (coop_is_active()) then 
  2165. 		set_player_can_enter_exit_rc_vehicles(REMOTE_PLAYER, true) 
  2166. 	end 
  2167. 	-- Arbitrary delay to make sure Angel's heli destroyed callback occurs first if they collided with each other 
  2168. 	delay(.5) 
  2169. 	-- If the wrestler's heli was blown up by something over than the RC heli, 
  2170. 	-- detonate the RC heli to make sure the player isn't stuck in RC mode 
  2171. 	if (vehicle_exists(M20_vehicle.rc_heli) and not vehicle_is_destroyed(M20_vehicle.rc_heli)) then 
  2172. 		vehicle_detonate(M20_vehicle.rc_heli) 
  2173. 	end 
  2174. 	M20_status.wrestler_heli_destroyed = true 
  2175. end 
  2176.  
  2177. -- Callback for when Angel's heli collides with something (used for the RC heli section) 
  2178. -- 
  2179. -- angel_heli:			(string) name of Angel's heli 
  2180. -- other_obj:			(string) name of the mover/vehicle that was collided with, or nil if the collision was with the world 
  2181. -- speed_of_impact:	(float) speed of the impact (not important for our purposes here) 
  2182. -- 
  2183. function m20_angel_heli_collided_cb(angel_heli, other_obj, speed_of_impact) 
  2184. 	-- If Angel's heli hits the RC heli or the wrestler's heli, blow it up and fail the mission 
  2185. 	if (other_obj == M20_vehicle.rc_heli or other_obj == M20_vehicle.wrestler) then 
  2186. 		on_collision("", angel_heli) 
  2187. 		vehicle_detonate(angel_heli) 
  2188. 		mission_end_failure("m20", M20_text.failure_angel_heli_destroyed) 
  2189. 	end 
  2190. end 
  2191.  
  2192. -- Callback for Angel's heli reaching the path around the STAG tanks 
  2193. -- 
  2194. function m20_tank_path_reached_cb() 
  2195. 	m20_clear_trigger(M20_trigger.tank_path) 
  2196. 	M20_status.tank_path_reached = true 
  2197. end 
  2198.  
  2199. -- Callback for the last wrestler being killed 
  2200. -- 
  2201. function m20_last_wrestler_killed_cb() 
  2202. 	on_death("", M20_char.last_wrestler) 
  2203. 	M20_status.last_wrestler_killed = true 
  2204. end 
  2205.  
  2206. -- Callback for one of the STAG tanks at the airport being destroyed 
  2207. -- 
  2208. -- tank:	(string) the tank that was destroyed 
  2209. -- 
  2210. function m20_stag_tank_destroyed_cb(tank) 
  2211. 	on_vehicle_destroyed("", tank) 
  2212. 	marker_remove(tank) 
  2213. end 
  2214.  
  2215. -- Callback for one of the targets in the RC car section being killed 
  2216. -- 
  2217. -- npc:	(string) the target that was killed 
  2218. -- 
  2219. function m20_target_death_cb(npc) 
  2220. 	marker_remove(npc) 
  2221. 	on_death("", npc) 
  2222. end 
  2223.  
  2224. -- ************************* 
  2225. -- 
  2226. -- Thread functions 
  2227. -- 
  2228. -- ************************* 
  2229.  
  2230. -- Causes the NPC to walk toward the vehicle, and when close, enter the vehicle in the selected seat 
  2231. -- NOTE: For now, NPCs can't be in the driver seat while the player has RC'd the vehicle, so we'll be putting them in passenger seats 
  2232. -- 
  2233. -- npc:			(string) name of the NPC we are sending to the vehicle 
  2234. -- vehicle:		(string) name of the vehicle 
  2235. -- seat:			(number) seat index we want the person to sit in once they reach the vehicle 
  2236. -- distance:	(number) distance from the vehicle at which we will teleport them in (right now NPCs won't get into a vehicle the player has RC control over, so we have to teleport them) 
  2237. -- 
  2238. function m20_walk_to_and_enter_vehicle_thread(npc, vehicle, seat, distance) 
  2239. 	if (distance == nil) then 
  2240. 		distance = 4 
  2241. 	end 
  2242.  
  2243. 	-- Have them walk toward, and not fire at, the vehicle 
  2244. 	ai_do_scripted_move(npc, vehicle, false, false) 
  2245.  
  2246. 	-- Wait until they get close enough to the vehicle 
  2247. 	repeat 
  2248. 		thread_yield() 
  2249. 	until (get_dist(npc, vehicle) < distance) 
  2250.  
  2251. 	-- Teleport them into the seat 
  2252. 	vehicle_enter(npc, vehicle, seat) 
  2253. end 
  2254.  
  2255. -- Sits and waits for the beach party to be crashed 
  2256. -- 
  2257. function m20_beach_party_polling_thread() 
  2258. 	repeat 
  2259. 		thread_yield() 
  2260. 	until object_is_in_trigger(M20_trigger.beach_party, M20_status.my_rc_boat) 
  2261. 	M20_status.beach_party_crashed = true 
  2262. end 
  2263.  
  2264. -- Does some validation on the boat's status, making sure it hasn't capsized or gotten stuck on land 
  2265. -- 
  2266. function m20_boat_validation_thread() 
  2267. 	repeat 
  2268. 		thread_yield() 
  2269.  
  2270. 		-- Make sure we haven't capsized 
  2271. 		if (vehicle_is_flipped(M20_status.my_rc_boat)) then 
  2272. 			if (M20_thread.boat_flipped_watchdog == INVALID_THREAD_HANDLE) then 
  2273. 				-- If this is the first time the boat is recognized as being flipped over, start the watchdog thread (which is basically just a fail timer) 
  2274. 				M20_thread.boat_flipped_watchdog = thread_new("m20_boat_flipped_watchdog_thread") 
  2275. 			end 
  2276. 		elseif (M20_thread.boat_flipped_watchdog ~= INVALID_THREAD_HANDLE) then 
  2277. 			-- If the watchdog timer is active, but the boat is no longer upside down (perhaps you were just doing a barrel roll?), stop the watchdog timer 
  2278. 			thread_kill(M20_thread.boat_flipped_watchdog) 
  2279. 			M20_thread.boat_flipped_watchdog = INVALID_THREAD_HANDLE 
  2280. 		end 
  2281.  
  2282. 		-- Make sure we're not stuck on land 
  2283. 		if (not vehicle_in_water(M20_status.my_rc_boat)) then 
  2284. 			if (M20_thread.boat_on_land_watchdog == INVALID_THREAD_HANDLE) then 
  2285. 				M20_thread.boat_on_land_watchdog = thread_new("m20_boat_on_land_watchdog_thread") 
  2286. 			end 
  2287. 		elseif (M20_thread.boat_on_land_watchdog ~= INVALID_THREAD_HANDLE) then 
  2288. 			thread_kill(M20_thread.boat_on_land_watchdog) 
  2289. 			M20_thread.boat_on_land_watchdog = INVALID_THREAD_HANDLE 
  2290. 		end 
  2291. 	until M20_status.beach_party_crashed 
  2292. 	thread_kill(M20_thread.boat_flipped_watchdog) 
  2293. 	M20_thread.boat_flipped_watchdog = INVALID_THREAD_HANDLE 
  2294. 	thread_kill(M20_thread.boat_on_land_watchdog) 
  2295. 	M20_thread.boat_on_land_watchdog = INVALID_THREAD_HANDLE 
  2296. end 
  2297.  
  2298. -- Starts a timer when the boat flips. If this thread isn't killed before time is up, the mission will fail. 
  2299. -- 
  2300. function m20_boat_flipped_watchdog_thread() 
  2301. 	delay(3) 
  2302. 	mission_end_failure("m20", M20_text.failure_ctb_destroyed) 
  2303. end 
  2304.  
  2305. -- Starts a timer when the boat is on land. If this thread isn't killed before time is up, the mission will fail. 
  2306. -- 
  2307. function m20_boat_on_land_watchdog_thread() 
  2308. 	delay(3) 
  2309. 	mission_end_failure("m20", M20_text.failure_ctb_destroyed) 
  2310. end 
  2311.  
  2312. -- Have a heli fly back and forth randomly between a set of navpoints in the air 
  2313. -- 
  2314. -- group_name:		(string) name of the group to spawn 
  2315. -- heli:				(string) name of the heli that's flying around 
  2316. -- pilot:			(string) name of the pilot 
  2317. -- teleport_nav:	(string) name of the navpoint to teleport to 
  2318. -- 
  2319. function m20_heli_rand_flying_thread(group_name, heli, pilot, teleport_nav) 
  2320. 	group_create(group_name, true) 
  2321. 	vehicle_enter_teleport(pilot, heli, VEHICLE_SEAT_DRIVER) 
  2322. 	if (heli == M20_vehicle.rc_heli) then 
  2323. 		if (coop_is_active()) then 
  2324. 			marker_add(heli, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_FULL, SYNC_REMOTE) 
  2325. 		end 
  2326. 		marker_add(heli, MINIMAP_ICON_USE, OI_ASSET_USE, OI_FLAGS_FULL, SYNC_LOCAL) 
  2327. 	else 
  2328. 		marker_add(heli, MINIMAP_ICON_KILL, OI_ASSET_KILL, OI_FLAGS_FULL, SYNC_LOCAL) 
  2329. 	end 
  2330. 	teleport_vehicle(heli, teleport_nav) 
  2331. 	helicopter_fly_to_direct(heli, HELI_DEFAULT_SPEED, teleport_nav) 
  2332.  
  2333. 	while (vehicle_exists(heli) and not vehicle_is_destroyed(heli)) do 
  2334. 		thread_yield() 
  2335. 		helicopter_fly_to_direct(heli, 15, get_random_table_entry(M20_navpoint.tourist_heli_rand)) 
  2336. 		thread_yield() 
  2337. 		delay(5) 
  2338. 	end 
  2339. end 
  2340.  
  2341. -- Angel's heli flying circles around the area the wrestler's heli is in 
  2342. -- 
  2343. -- speed:	(number) speed at which the heli should fly 
  2344. -- 
  2345. function m20_heli_to_heli_thread(speed) 
  2346. 	while (1) do 
  2347. 		thread_yield() 
  2348. 		helicopter_fly_to_direct_dont_stop(M20_vehicle.angel_heli, speed, M20_scripted_path.heli_to_heli) 
  2349. 	end 
  2350. end 
  2351.  
  2352. -- Angel's heli flying circles around the area the STAG tanks are in 
  2353. -- 
  2354. -- speed:	(number) speed at which the heli should fly 
  2355. -- 
  2356. function m20_heli_to_airport_thread(speed) 
  2357. 	helicopter_fly_to_dont_stop(M20_vehicle.angel_heli, speed, M20_scripted_path.heli_to_airport) 
  2358. 	m20_heli_around_airport_thread( speed ) 
  2359. end 
  2360.  
  2361. function m20_heli_around_airport_thread(speed) 
  2362. 	while (1) do 
  2363. 		thread_yield() 
  2364. 		helicopter_fly_to_direct_dont_stop(M20_vehicle.angel_heli, speed, M20_scripted_path.heli_around_airport) 
  2365. 	end 
  2366. end 
  2367.  
  2368. function m20_wrapper_thread(function_ref, ...) 
  2369. 	function_ref(unpack(arg)) 
  2370. end 
  2371.  
  2372. function m20_wrapper_thread_forever(function_ref, ...) 
  2373. 	while true do 
  2374. 		function_ref(unpack(arg)) 
  2375. 		thread_yield() 
  2376. 	end 
  2377. end 
  2378.  
  2379. function m20_rc_car_timer_expired() 
  2380. 	mission_end_failure("m20", M20_text.failure_rc_too_late) 
  2381. end 
  2382.  
  2383. function m20_coop_follow_obj_start( target_vehicle ) 
  2384. 	if coop_is_active() == false then 
  2385. 		return 
  2386. 	end 
  2387. 	 
  2388. 	-- turn on bar 
  2389. 	hud_bar_on( 1, "default", M20_text.stay_close, 1, SYNC_REMOTE ) 
  2390. 	marker_add( target_vehicle, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_FULL, SYNC_REMOTE ) 
  2391. 	M20_status.coop_follow_target_vehicle = target_vehicle 
  2392.  
  2393. 	-- start thread 
  2394. 	M20_thread.coop_follow_obj_thread_id = thread_new( "m20_coop_follow_obj_thread", target_vehicle ) 
  2395. end 
  2396.  
  2397. function m20_coop_follow_obj_stop() 
  2398. 	if coop_is_active() == false then 
  2399. 		return 
  2400. 	end 
  2401.  
  2402. 	-- kill thread 
  2403. 	thread_kill( M20_thread.coop_follow_obj_thread_id ) 
  2404. 	M20_thread.coop_follow_obj_thread_id = nil 
  2405. 	 
  2406. 	-- turn off bar 
  2407. 	hud_bar_off( 1, SYNC_REMOTE ) 
  2408. 	marker_remove( M20_status.coop_follow_target_vehicle ) 
  2409. end 
  2410.  
  2411. function m20_coop_follow_obj_thread( target_vehicle ) 
  2412. 	local current_value = -1 
  2413. 	local v 
  2414. 	while true do 
  2415. 		v = vehicle_rc_get_signal_strength( target_vehicle, LOCAL_PLAYER ) 
  2416. 		 
  2417. 		if v ~= current_value then 
  2418. 			-- update bar 
  2419. 			current_value = v 
  2420. 			hud_bar_set_value( 1, v, SYNC_REMOTE ) 
  2421. 		end 
  2422. 		 
  2423. 		thread_yield() 
  2424. 	end 
  2425. end 
  2426.  
  2427. function m20_convo_cleanup() 
  2428. 	-- kill manager thread 
  2429. 	if M20_thread.convo_manager ~= INVALID_THREAD_HANDLE then 
  2430. 		thread_kill( M20_thread.convo_manager ) 
  2431. 		M20_thread.convo_manager = INVALID_THREAD_HANDLE 
  2432. 	end 
  2433. 	 
  2434. 	-- sweep all convo data and clean it up 
  2435. 	for i, convo in pairs( M20_convo_queue ) do 
  2436. 		m20_convo_cleanup_item( convo ) 
  2437. 	end 
  2438. 	 
  2439. 	-- clear pending events 
  2440. 	M20_convo_queue = { } 
  2441. end 
  2442. 	 
  2443. function m20_convo_cleanup_item( convo ) 
  2444. 	if convo.convo_handle ~= nil then 
  2445. 		audio_conversation_end( convo.convo_handle ) 
  2446. 		convo.convo_handle = nil 
  2447. 	end 
  2448. 	 
  2449. 	if convo.audio_id ~= nil then 
  2450. 		audio_stop( convo.audio_id ) 
  2451. 		convo.audio_id = nil 
  2452. 	end 
  2453. 	 
  2454. 	-- clean up loaded personas 
  2455. 	if convo.persona_handles ~= nil then 
  2456. 		for i, handle in pairs( convo.persona_handles ) do 
  2457. 			audio_persona_remove_2d( handle ) 
  2458. 		end 
  2459. 		convo.persona_handles = nil 
  2460. 	end 
  2461. end 
  2462.  
  2463. function m20_kinzie_watch_signal_start( target_vehicle ) 
  2464. 	m20_kinzie_watch_signal_stop() 
  2465. 	M20_thread.kinzie_watch_signal = thread_new( "m20_kinzie_watch_signal_thread", target_vehicle ) 
  2466. end 
  2467.  
  2468. function m20_kinzie_watch_signal_stop() 
  2469. 	if M20_thread.kinzie_watch_signal ~= nil then 
  2470. 		thread_kill( M20_thread.kinzie_watch_signal ) 
  2471. 		M20_thread.kinzie_watch_signal = nil 
  2472. 	end 
  2473. end 
  2474.  
  2475. function m20_kinzie_watch_signal_thread( target_vehicle ) 
  2476. 	while true do 
  2477. 		-- signal dips below 25% then have Kinzie say something 
  2478. 		while vehicle_rc_get_signal_strength( target_vehicle, LOCAL_PLAYER ) > 0.25 do 
  2479. 			thread_yield() 
  2480. 		end 
  2481. 		 
  2482. 		m20_convo_play( M20_convo.losing_signal, false, true ) 
  2483. 		 
  2484. 		-- don't say anything for 3 seconds 
  2485. 		delay( 3 ) 
  2486. 		 
  2487. 		-- wait until signal is > 30% before repeating 
  2488. 		while vehicle_rc_get_signal_strength( target_vehicle, LOCAL_PLAYER ) < 0.3 do 
  2489. 			thread_yield() 
  2490. 		end 
  2491. 	end 
  2492. end 
  2493.  
  2494.  
  2495. function m20_on_take_damage_rc_car( name, attacker, hp ) 
  2496. 	-- looking for a hit > threshold 
  2497. 	local current_hp = get_max_hit_points( name ) * hp 
  2498. 	if M20_status.rc_car_prev_hp - current_hp < 150 then 
  2499. 		M20_status.rc_car_prev_hp = current_hp 
  2500. 		return 
  2501. 	end 
  2502. 	 
  2503. 	-- see if in trigger 
  2504. 	local in_trigger = false 
  2505. 	for i, trigger in pairs( M20_trigger.gas_station ) do 
  2506. 		if object_is_in_trigger( trigger, name ) == true then 
  2507. 			in_trigger = true 
  2508. 			break 
  2509. 		end 
  2510. 	end 
  2511. 	 
  2512. 	if in_trigger == true then 
  2513. 		on_take_damage( "", name ) 
  2514. 		audio_play( "M20_Explo" ) 
  2515. 		vehicle_detonate( name ) 
  2516. 	end 
  2517. end