sr2lua/bh02.lua

  1. -- bh02.lua 
  2. -- SR2 mission script 
  3. -- 3/28/07 
  4.  
  5. -- Global constants 
  6. 	-- Mission state constants 
  7.  
  8. 	-- End mission states 
  9.  
  10.    -- Help text ( note that not all help text is here ) 
  11.    HT_PRESS_TO_DETONATE_BOMB = "bh02_press_to_detonate_bomb" 
  12.    HT_SEE_TRUCK_TO_DETONATE = "bh02_see_truck_to_detonate" 
  13.    HT_SWITCH_TO_DETONATOR = "bh02_switch_to_detonator" 
  14.  
  15. 	-- Assorted constants -- 
  16. 		CURRENT_MISSION =			"bh02" 
  17. 		ENEMY_GANG =				"Brotherhood" 
  18.  
  19. 		DROPOFF_DISTANCE =			15		-- Distance from the drop target where Donnie will get out 
  20. 		DROPOFF_SPEED =				10		-- Maximum speed you can be going where Donnie will get out 
  21.  
  22.       FIND_NEW_SEAT_LOCATION_TIME_SECONDS = 7 
  23. 		BOMB_PLANT_TIME =			30		-- Length of time to plant a bomb 
  24. 		PLANT_BOMB_MAX_DISTANCE =	2.5		-- Maximum distance from car center to keep planting bomb 
  25. 		STATE_PLANT_BOMB =			"crouch plant bomb"		-- Bomb planting animation state 
  26.  
  27. 		DETONATOR_ITEM =			"Detonator"	-- Name of detonator inventory item 
  28. 		ACTION_DETONATE =			"detonate"	-- Bomb detonation animation action 
  29. 		DETONATION_DISTANCE =		30			-- Distance you must travel before the bombs detonate 
  30. 		EXPLOSION_NAME =			"Car Bomb"	-- Name of the explosion to use for the bomb 
  31. 		 
  32. 		FINAL_DETONATION_DISTANCE =	50			-- Distance for broken detonator 
  33. 		FINAL_EXPLOSION_NAME =		"Car Bomb Big"	-- Broken detonator explosion name 
  34.  
  35. 		BROKEN_DETONATOR_TIME_MS =		30000		-- Length of time before the broken detonator explodes 
  36.  
  37. 		DONNIE_SOLO_HP_MULTIPLIER =	5		-- Health multiplier in single-player 
  38. 		DONNIE_WARNING_PERCENTAGE = 0.3		-- Percentage of damage before displaying the warning 
  39.  
  40. 		MINIMAP_ICON_EXPLODING =	"map_other_blip_human" 
  41.  
  42. 		NEXT_TARGET_ALERT_RADIUS = 25 
  43.       DRIVING_LINES_DELAY_MIN_SECONDS = 30 
  44.       DRIVING_LINES_DELAY_MAX_SECONDS = 45 
  45.  
  46.       CLOSE_ENOUGH_TO_DONNIE_DIST_METERS = 5.0 
  47.  
  48.       -- These are intended to be indexed by "IN_COOP." So the "false" values are 
  49.       -- the single player values and the "true" values are the coop values. 
  50.       FIRST_TARGET_MIN_NOTORIETIES = { [false] = 2, [true] = 2 } 
  51.       SECOND_TARGET_MIN_NOTORIETIES = { [false] = 2, [true] = 3 } 
  52.       THIRD_TARGET_MIN_NOTORIETIES = { [false] = 2, [true] = 3 } 
  53.  
  54.       DETONATE_TRUCK_MESSAGES_VISIBLE_TIME_SECONDS = 3 
  55.  
  56. 	-- Navpoints -- 
  57. 		NAVPOINT_START =							"bh02_$player_start" 
  58.       NAVPOINT_START_REMOTE =					"bh02_$coop_player_start" 
  59.  
  60. 	-- Groups -- 
  61. 		GROUP_ALLIES =								"bh02_$allies" 
  62. 		GROUP_BOMB_TARGETS =						"bh02_$bomb_targets" 
  63. 		GROUP_GANG_SPAWN_1 =						"bh02_$gang_group_01" 
  64. 		GROUP_GANG_SPAWN_2a =					"bh02_$gang_group_02a" 
  65. 		GROUP_GANG_INTERMEDIATE =				"bh02_$group_gang_intermediate" 
  66. 		GROUP_GANG_SPAWN_2b =					"bh02_$gang_group_02b" 
  67. 		GROUP_GANG_SPAWN_3a =					"bh02_$gang_group_03a" 
  68. 		GROUP_GANG_SPAWN_3b =					"bh02_$gang_group_03b" 
  69. 		-- GROUP_GANG_ROADBLOCKS =				"bh02_$gang_group_roadblocks" 
  70.  
  71. 	-- Individual Objects -- 
  72. 		CHAR_DONNIE =								"bh02_$donnie" 
  73. 		CHAR_GANG_SPAWN_1a =						"bh02_$gang_01a" 
  74. 		CHAR_GANG_SPAWN_1b =						"bh02_$gang_01b" 
  75. 		CHAR_GANG_SPAWN_1c =						"bh02_$gang_01c" 
  76.  
  77. 		VEHICLE_GANG_SPAWN_2 =					"bh02_$gang_car_02"	 
  78. 		VEHICLE_GANG_SPAWN_INTERMEDIATE =	"bh02_$gang_car_intermediate"	 
  79. 		VEHICLE_LIN_MOBILE =						"bh02_$lin_mobile" 
  80.  
  81. 		BOMB_TARGET_1 =							"bh02_$bomb_target_01" 
  82. 		BOMB_TARGET_2a =							"bh02_$bomb_target_02a" 
  83. 		BOMB_TARGET_2b =							"bh02_$bomb_target_02b" 
  84. 		BOMB_TARGET_3 =							"bh02_$bomb_target_03" 
  85.  
  86.       BOMB_TARGET_PLANT_LOCATIONS = { [BOMB_TARGET_1] = { "bh02_$bomb_plant_loc1_1", "bh02_$bomb_plant_loc1_2" }, 
  87.                                       [BOMB_TARGET_2a] = { "bh02_$bomb_plant_loc2a_1", "bh02_$bomb_plant_loc2a_2" }, 
  88.                                       [BOMB_TARGET_2b] = { "bh02_$bomb_plant_loc2b_1", "bh02_$bomb_plant_loc2b_2" }, 
  89.                                       [BOMB_TARGET_3] = { "bh02_$bomb_plant_loc3_1", "bh02_$bomb_plant_loc3_2" } } 
  90.  
  91. 	-- Tables -- 
  92. 		TABLE_ALL_GROUPS =		{ GROUP_ALLIES, GROUP_BOMB_TARGETS, GROUP_GANG_SPAWN_1, GROUP_GANG_SPAWN_2a, GROUP_GANG_SPAWN_2b, GROUP_GANG_SPAWN_3a, GROUP_GANG_SPAWN_3b, GROUP_GANG_INTERMEDIATE, } 
  93. 		TABLE_GANG_SPAWN_2b =		{ "bh02_$gang_02c", "bh02_$gang_02d", "bh02_$gang_02e" } 
  94. 		TABLE_GANG_SPAWN_INTERMEDIATE =	{ "bh02_$gang_intermediate01", "bh02_$gang_intermediate02" } 
  95. 		TABLE_GANG_SPAWN_3b =		{ "bh02_$gang_03c", "bh02_$gang_03d", "bh02_$gang_03e", "bh02_$gang_03f" } 
  96.  
  97. 	-- Cutscenes -- 
  98. 		CUTSCENE_IN =						"br02-01" 
  99. 		CUTSCENE_OUT =						"br02-02" 
  100.  
  101. 	-- Voice -- 
  102. 		VOICE_INTRO =					{{"PLAYER_BR02_INTRO_L1", LOCAL_PLAYER, 1}, 
  103. 											 {"BR02_INTRO_L2", CHAR_DONNIE, 1}, 
  104. 											 {"PLAYER_BR02_INTRO_L3", LOCAL_PLAYER, 1}} 
  105.       -- Lines 
  106.       DONNIE_WHINING_LINES = { "DONNIE_BR02_WHINING_1", "DONNIE_BR02_WHINING_2", "DONNIE_BR02_WHINING_3", "DONNIE_BR02_WHINING_4", "DONNIE_BR02_WHINING_5" } 
  107.       NUM_WHINING_LINES = sizeof_table( DONNIE_WHINING_LINES ) 
  108.       DONNIE_DRIVING_LINES = { "DONNIE_BR02_DRIVING_1", "DONNIE_BR02_DRIVING_2", "DONNIE_BR02_DRIVING_3", "DONNIE_BR02_DRIVING_4" } 
  109.       NUM_DRIVING_LINES = sizeof_table( DONNIE_DRIVING_LINES ) 
  110.  
  111. 		DONNIE_BOMBSTART_LINES = { "DONNIE_BR02_BOMBSTART_1", "DONNIE_BR02_BOMBSTART_2", "DONNIE_BR02_BOMBSTART_3", "DONNIE_BR02_BOMBSTART_4", "DONNIE_BR02_BOMBSTART_5" } 
  112.       NUM_BOMBSTART_LINES = sizeof_table( DONNIE_BOMBSTART_LINES ) 
  113. 		DONNIE_BOMBFINISH_LINES = { "DONNIE_BR02_BOMBFINISH_1", "DONNIE_BR02_BOMBFINISH_2", "DONNIE_BR02_BOMBFINISH_3", "DONNIE_BR02_BOMBFINISH_4", "DONNIE_BR02_BOMBFINISH_5" } 
  114. 		NUM_BOMBFINISH_LINES = sizeof_table( DONNIE_BOMBFINISH_LINES ) 
  115.  
  116.       -- Persona overrides 
  117.       DONNIE_WHINING_PERSONA_SITUATION = "custom line 1" 
  118.  
  119.       DONNIE_PERSONA_OVERRIDES = { { "hostage - barters", "DONNIE_BR02_BARTER" }, 
  120.                                    { "misc - respond to player taunt w/taunt", "DONNIE_BR02_TAUNT" }, 
  121.                                    { "observe - praised by PC", "DONNIE_BR02_PRAISED" }, 
  122.                                    { "observe - passenger when driver hits cars", "DONNIE_BR02_HITCAR" }, 
  123.                                    { "observe - passenger when driver hits object", "DONNIE_BR02_HITOBJ" }, 
  124.                                    { "observe - passenger when driver hits peds", "DONNIE_BR02_HITPED" }, 
  125.                                    { "threat - alert (solo attack)", "DONNIE_BR02_ATTACK" }, 
  126.                                    { "threat - alert (group attack)", "DONNIE_BR02_ATTACK" }, 
  127.                                    { "threat - damage received (firearm)", "DONNIE_BR02_TAKEDAM" }, 
  128.                                    { "threat - damage received (melee)", "DONNIE_BR02_TAKEDAM" }--[[, 
  129.                                    { DONNIE_WHINING_PERSONA_SITUATION, "DONNIE_BR02_WHINING" }]] } 
  130.       BH02_BROTHERHOOD_PERSONAS = { 
  131.                                     ["HM_Bro1"]	=	"HMBRO1", 
  132.                                     ["HM_Bro2"]	=	"HMBRO2", 
  133.                                     ["HM_Bro3"]	=	"HMBRO3", 
  134.  
  135.                                     ["HF_Bro2"]	=	"HFBRO2", 
  136.  
  137.                                     ["WM_Bro3"]	=	"WMBRO3", 
  138.  
  139.                                     ["WF_Bro1"]	=	"WFBRO1", 
  140.                                     ["WF_Bro2"]	=	"WFBRO2", 
  141.                                  } 
  142. 	-- Threads -- 
  143. 		THREAD_NEXT_TARGET =			-1 
  144. 		THREAD_CHASE =					-1 
  145. 		THREAD_DONNIE_ABANDONED =	-1 
  146. 		TABLE_ALL_THREADS =			{THREAD_NEXT_TARGET, THREAD_CHASE, THREAD_DONNIE_ABANDONED} 
  147.  
  148. 	-- Roadblock Additions 
  149. 	-- These are making the mission too hard at the third stop so I am commenting them out for now.  - BD 
  150. 		GROUP_GANG_ROADBLOCKS =			"bh02_$gang_group_roadblocks" 
  151. 		NAV_ROADBLOCK01 =			"bh02_$nav_roadblock01" 
  152. 		NAV_ROADBLOCK02 = 			"bh02_$nav_roadblock02" 
  153. 		NAV_ROADBLOCK03 = 			"bh02_$nav_roadblock03" 
  154. 		VEHICLE_GANG_ROADBLOCK01 =		"bh02_$vehicle_roadblock01" 
  155. 		VEHICLE_GANG_ROADBLOCK02 =		"bh02_$vehicle_roadblock02" 
  156. 		VEHICLE_GANG_ROADBLOCK03 =		"bh02_$vehicle_roadblock03" 
  157. 		TABLE_GANG_ROADBLOCK01 =		{ "bh02_$gang_roadblock01a", "bh02_$gang_roadblock01b" } 
  158. 		TABLE_GANG_ROADBLOCK02 =		{ "bh02_$gang_roadblock02a", "bh02_$gang_roadblock02b" } 
  159. 		TABLE_GANG_ROADBLOCK03 =		{ "bh02_$gang_roadblock03a", "bh02_$gang_roadblock03b" } 
  160.  
  161. -- Donnie dialogue while planting bombs 
  162. 	DONNIE_BOMB_DIALOGUE = {"bh02_bomb_planting_diag1", "bh02_bomb_planting_diag2", "bh02_bomb_planting_diag3", "bh02_bomb_planting_diag4",  
  163. 									"bh02_bomb_planting_diag5", "bh02_bomb_planting_diag6", "bh02_bomb_planting_diag7", "bh02_bomb_planting_diag8"} 
  164.  
  165. -- Global Variables 
  166. 	Current_bomb_target =			false 
  167. 	Current_bomb_target_2nd =		false 
  168.  
  169. 	Mission_Successful =				false 
  170.  
  171. 	Current_target_seat =			1 
  172.  
  173. 	Num_targets_destroyed =			0 
  174. 	Bomb_countdown_timer =			BOMB_PLANT_TIME 
  175. 	Detonator_triggered =			true 
  176. 	Explosion =				EXPLOSION_NAME 
  177. 	Next_target =				false 
  178. 	IN_COOP =					false 
  179.    Prev_weapon = "" 
  180.    Message_sent_for_this_damage = false 
  181.    Timer_thread_handles = { INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE } 
  182.    Targets_visible = false 
  183.    Detonator_timer_expired = false 
  184.    Last_seat_index = -1 
  185.    Donnie_canceled_by_not_being_watched = false 
  186.  
  187. 	Cur_bombstart_line = 0 
  188. 	Cur_bombfinish_line = 0 
  189.  
  190.    Cur_whining_line = 0 
  191.  
  192. 	LINS_CAR_HEALTH_MULTIPLIER = 1.5 
  193.  
  194. -- Main mission function 
  195. function bh02_start(bh02_checkpoint, is_restart) 
  196. 	set_mission_author("Kevin J. Price, Aaron Hanson, and Mark Gabby") 
  197.  
  198. 	if coop_is_active() then 
  199. 		IN_COOP = true 
  200. 	end 
  201.  
  202. 	local start_groups = {GROUP_ALLIES, GROUP_BOMB_TARGETS} 
  203.  
  204.    mission_start_fade_out() 
  205. 	if (not is_restart) then 
  206. 		cutscene_play( CUTSCENE_IN, start_groups, {NAVPOINT_START, NAVPOINT_START_REMOTE}, false)	 
  207. 	else 
  208. 		for i,group in pairs(start_groups) do 
  209. 			group_create_hidden(group, true) 
  210. 		end 
  211.  
  212. 		-- Bring both players to the mission start location 
  213. 		teleport_coop( NAVPOINT_START, NAVPOINT_START_REMOTE ) 
  214.  
  215. 	end 
  216. 	group_show(GROUP_ALLIES) 
  217.  
  218.    -- Don't allow Brotherhood notoriety to go over 2 in this mission 
  219. 	notoriety_set_max(ENEMY_GANG, 2) 
  220. 	notoriety_set_max("Police", 2) 
  221.  
  222. 	-- Load Donnie and the bomb targets (that'd be a terrible name for a band) 
  223. 	vehicle_infinite_mass(BOMB_TARGET_3, true) 
  224. 	party_add( CHAR_DONNIE, LOCAL_PLAYER ) 
  225. 	set_max_hit_points(VEHICLE_LIN_MOBILE, get_max_hit_points(VEHICLE_LIN_MOBILE) * LINS_CAR_HEALTH_MULTIPLIER, true) 
  226.  
  227.    -- In single player, we may need to make Donnie the first follower so that he's in the 
  228.    -- correct seat when teleported in 
  229.    if ( coop_is_active() == false ) then 
  230.       -- Find his current index 
  231.       local donnie_follower_index = party_get_follower_index( CHAR_DONNIE ) 
  232.       -- If he's not the first follower, swap him and the first one 
  233.       if ( donnie_follower_index > 0 ) then 
  234.          party_swap_follower_indices( 0, donnie_follower_index ) 
  235. 	      delay( 1.0 ) 
  236.       end 
  237.    end 
  238. 	vehicle_enter_teleport(LOCAL_PLAYER, VEHICLE_LIN_MOBILE, 0) 
  239.  
  240. 	if ( coop_is_active() ) then 
  241. 		vehicle_enter_teleport(REMOTE_PLAYER, VEHICLE_LIN_MOBILE, 2) 
  242. 	end 
  243.  
  244. 	bh02_start_persona_overrides() 
  245.  
  246.    mission_start_fade_in() 
  247.  
  248.    bh02_run_mission() 
  249. end 
  250.  
  251. function bh02_donnie_killed() 
  252. 	mission_end_failure( CURRENT_MISSION, "bh02_donnie_died" ) 
  253. end 
  254.  
  255. function bh02_donnie_warning() 
  256. 	mission_help_table_nag("bh02_donnie_health_warning") 
  257. end 
  258.  
  259. function bh02_run_mission() 
  260. 	-- Should do this in the editor now that I can 
  261. 	character_set_cannot_be_grabbed(CHAR_DONNIE, true) 
  262. 	 
  263. 	 
  264. 	-- Setup callback for Donnie's untimely death 
  265. 	on_dismiss("failure_donnie_dismiss", CHAR_DONNIE) 
  266. 	on_death( "bh02_donnie_killed", CHAR_DONNIE ) 
  267. 	on_damage( "bh02_donnie_warning", CHAR_DONNIE, DONNIE_WARNING_PERCENTAGE ) 
  268. 	-- By design, Donnie can't be revived 
  269. 	character_set_unrevivable( CHAR_DONNIE, true ) 
  270.  
  271. 	-- Donnie is a pansy 
  272. 	npc_combat_enable(CHAR_DONNIE, false) 
  273.  
  274. 	-- Play intro dialogue 
  275. 	thread_new("bh02_play_intro_conversation_then_start_driving_lines") 
  276.  
  277. 	-- Set up stuff 
  278. 	if not coop_is_active() then 
  279. 		set_max_hit_points(CHAR_DONNIE, DONNIE_SOLO_HP_MULTIPLIER * get_max_hit_points(CHAR_DONNIE)) 
  280. 	end 
  281. 	objective_text(0, "bh02_trucks_destroyed", 0, 4) 
  282. 	delay(3) 
  283.  
  284. 	mission_help_table("bh02_go_to_first_truck") 
  285.  
  286.    bh02_setup_first_target() 
  287.  
  288. 	-- First target 
  289.    bh02_do_first_target() 
  290. 	delay(5) 
  291.  
  292. 	-- Pre-emptively create the second target 
  293.    bh02_setup_second_target() 
  294.  
  295. 	detonate_at_distance(BOMB_TARGET_1) 
  296. 	bh02_update_truck_destroyed_counter() 
  297.  
  298.    bh02_cleanup_first_target() 
  299.  
  300.    bh02_create_intermediate_gang_attack_group() 
  301.  
  302. 	-- Second targets 
  303. 	mission_help_table("bh02_go_to_second_truck") 
  304.  
  305.    bh02_do_second_target() 
  306. 	delay(5) 
  307.  
  308. 	-- Preemptively create the third target 
  309.    bh02_setup_third_target() 
  310. 	 
  311. 	detonate_at_distance(BOMB_TARGET_2a, BOMB_TARGET_2b) 
  312. 	bh02_update_truck_destroyed_counter() 
  313. 	bh02_update_truck_destroyed_counter() 
  314.  
  315.    bh02_cleanup_second_target() 
  316. 	delay(3) 
  317.  
  318. 	-- Third target 
  319. 	mission_help_table("bh02_go_to_third_truck") 
  320.  
  321.    bh02_do_third_target() 
  322. 	delay(5) 
  323.  
  324. 	minimap_icon_add_vehicle_radius(Current_bomb_target, MINIMAP_ICON_EXPLODING, FINAL_DETONATION_DISTANCE) 
  325. 	 
  326. 	mission_help_table("bh02_get_away") 
  327.  
  328.    --[[ 
  329. 	-- BDillow Addition 8/01 
  330. 	-- One last truck to hopefully get in the player's way. 
  331. 	vehicle_enter_group_teleport(TABLE_GANG_ROADBLOCK03, VEHICLE_GANG_ROADBLOCK03) 
  332. 	delay(1) 
  333. 	vehicle_pathfind_to(VEHICLE_GANG_ROADBLOCK03, NAV_ROADBLOCK03, true, true) 
  334.    ]] 
  335.  
  336. 	while not_far_enough_away(Current_bomb_target, FINAL_DETONATION_DISTANCE) do 
  337. 		thread_yield() 
  338. 	end 
  339.  
  340. 	-- The chase is on! 
  341. 	THREAD_CHASE = thread_new("bh02_chase_players") 
  342.  
  343. 	audio_play_for_character("DONNIE_BR02_BREAKDET", CHAR_DONNIE, "voice") 
  344. 	hud_timer_set( 1, BROKEN_DETONATOR_TIME_MS, "bh02_detonator_timer_expires" ) 
  345. 	delay(5) 
  346. 	mission_help_table("bh02_stay_away") 
  347.  
  348. 	repeat 
  349. 		thread_yield() 
  350. 	until ( Detonator_timer_expired ) 
  351.  
  352. 	on_vehicle_destroyed("", BOMB_TARGET_3) 
  353.  
  354. 	if not vehicle_is_destroyed(BOMB_TARGET_3) then 
  355. 		if THREAD_CHASE ~= -1 then 
  356. 			thread_kill(THREAD_CHASE) 
  357. 		end 
  358. 		bomb_explode(BOMB_TARGET_3) 
  359. 	end 
  360. 	release_to_world(BOMB_TARGET_3) 
  361. 	bh02_update_truck_destroyed_counter() 
  362.  
  363. 	mission_end_success( CURRENT_MISSION, CUTSCENE_OUT ) 
  364. end 
  365.  
  366. function bh02_detonator_timer_expires() 
  367.    Detonator_timer_expired = true 
  368. end 
  369.  
  370. function bh02_setup_vehicle_target( target_vehicle_name ) 
  371. 	vehicle_show( target_vehicle_name ) 
  372. 	on_vehicle_destroyed("failure_vehicle_death", target_vehicle_name ) 
  373.    vehicle_infinite_mass( target_vehicle_name, true ) 
  374.    turn_invulnerable( target_vehicle_name ) 
  375.    vehicle_prevent_explosion_fling( target_vehicle_name, true ) 
  376. 	set_unjackable_flag( target_vehicle_name, true ) 
  377.    vehicle_set_untowable( target_vehicle_name, true ) 
  378. end 
  379.  
  380. function bh02_setup_first_target() 
  381.    bh02_setup_vehicle_target( BOMB_TARGET_1 ) 
  382. end 
  383.  
  384. function bh02_setup_second_target() 
  385.    bh02_setup_vehicle_target( BOMB_TARGET_2a ) 
  386.    bh02_setup_vehicle_target( BOMB_TARGET_2b ) 
  387.  
  388. 	group_create(GROUP_GANG_SPAWN_2a, true) 
  389. 	Next_target = BOMB_TARGET_2a 
  390. 	THREAD_NEXT_TARGET = thread_new("bh02_next_target_watch") 
  391. end 
  392.  
  393. function bh02_setup_third_target() 
  394.    bh02_setup_vehicle_target( BOMB_TARGET_3 ) 
  395.  
  396. 	group_create(GROUP_GANG_SPAWN_3a, true) 
  397. 	Next_target = BOMB_TARGET_3 
  398. 	THREAD_NEXT_TARGET = thread_new("bh02_next_target_watch") 
  399. end 
  400.  
  401. function bh02_do_first_target() 
  402. 	group_create(GROUP_GANG_SPAWN_1, true) 
  403. 	Current_bomb_target = BOMB_TARGET_1 
  404. 	bh02_get_near_target() 
  405. 	follower_make_independent(CHAR_DONNIE, true) 
  406. 	mission_help_table("bh02_guard_donnie") 
  407. 	bh02_donnie_plant_bomb() 
  408. 	bh02_wait_until_planted(BOMB_PLANT_TIME/2) 
  409. 	 
  410.    notoriety_set_min( ENEMY_GANG, FIRST_TARGET_MIN_NOTORIETIES[IN_COOP] ) 
  411.  
  412.    audio_play_persona_line( CHAR_GANG_SPAWN_1a, POT_CUSTOM_1 ) 
  413. 	attack(CHAR_GANG_SPAWN_1a, CHAR_DONNIE, false) 
  414.    audio_play_persona_line( CHAR_GANG_SPAWN_1b, POT_CUSTOM_1 ) 
  415. 	attack(CHAR_GANG_SPAWN_1b, CHAR_DONNIE, false) 
  416. 	audio_play_persona_line( CHAR_GANG_SPAWN_1c, POT_CUSTOM_1 ) 
  417. 	attack(CHAR_GANG_SPAWN_1c, CHAR_DONNIE, false) 
  418.  
  419. 	bh02_wait_until_planted() 
  420. 	follower_make_independent(CHAR_DONNIE, false) 
  421. end 
  422.  
  423. function bh02_do_second_target() 
  424. 	Current_bomb_target = BOMB_TARGET_2a 
  425. 	Current_bomb_target_2nd = BOMB_TARGET_2b 
  426. 	Current_target_seat = 0 
  427. 	bh02_get_near_target() 
  428. 	group_create(GROUP_GANG_SPAWN_2b, true) 
  429. 	for index, name in pairs( TABLE_GANG_SPAWN_2b ) do 
  430. 		vehicle_enter_teleport( name, VEHICLE_GANG_SPAWN_2, index - 1, false ) 
  431. 	end 
  432. 	follower_make_independent(CHAR_DONNIE, true) 
  433. 	--mission_help_table("bh02_guard_donnie") 
  434. 	bh02_donnie_plant_bomb() 
  435.  
  436. 	notoriety_set_min( ENEMY_GANG, SECOND_TARGET_MIN_NOTORIETIES[IN_COOP] ) 
  437. 	bh02_wait_until_planted() 
  438. 	 
  439. 	vehicle_chase(VEHICLE_GANG_SPAWN_2, CHAR_DONNIE) 
  440. 	 
  441. 	Current_bomb_target = BOMB_TARGET_2b 
  442. 	Current_target_seat = 1 
  443. 	bh02_donnie_plant_bomb() 
  444. 	bh02_wait_until_planted() 
  445. 	follower_make_independent(CHAR_DONNIE, false) 
  446. end 
  447.  
  448. function bh02_do_third_target() 
  449. 	Current_bomb_target	= BOMB_TARGET_3 
  450. 	Current_bomb_target_2nd = false 
  451. 	Current_target_seat = 0 
  452. 	Explosion = FINAL_EXPLOSION_NAME 
  453. 	bh02_get_near_target() 
  454. 	follower_make_independent(CHAR_DONNIE, true) 
  455. 	--mission_help_table("bh02_guard_donnie") 
  456. 	bh02_donnie_plant_bomb() 
  457.  
  458.    notoriety_set_min( ENEMY_GANG, THIRD_TARGET_MIN_NOTORIETIES[IN_COOP] ) 
  459.  
  460. 	-- BDillow Addition 05/08/08 
  461. 	-- These additions are proving to make the mission too hard, commenting them out for now 
  462.  
  463. 	-- delay(3) 
  464. 	-- group_create(GROUP_GANG_ROADBLOCKS, true) 
  465. 	-- vehicle_enter_group_teleport(TABLE_GANG_ROADBLOCK01, VEHICLE_GANG_ROADBLOCK01) 
  466. 	-- delay(1) 
  467. 	-- vehicle_pathfind_to(VEHICLE_GANG_ROADBLOCK01, NAV_ROADBLOCK01, true, true) 
  468. 	-- delay(3) 
  469. 	-- vehicle_enter_group_teleport(TABLE_GANG_ROADBLOCK02, VEHICLE_GANG_ROADBLOCK02) 
  470. 	-- delay(1) 
  471. 	-- vehicle_pathfind_to(VEHICLE_GANG_ROADBLOCK02, NAV_ROADBLOCK02, true, true) 
  472. 	-- delay(1) 
  473.  
  474. 	bh02_wait_until_planted() 
  475. 	follower_make_independent(CHAR_DONNIE, false) 
  476. end 
  477.  
  478. function bh02_cleanup_first_target() 
  479. 	release_to_world(BOMB_TARGET_1) 
  480. 	release_to_world(GROUP_GANG_SPAWN_1) 
  481. 	thread_kill(THREAD_NEXT_TARGET) 
  482. end 
  483.  
  484. function bh02_cleanup_second_target() 
  485. 	release_to_world(BOMB_TARGET_2a) 
  486. 	release_to_world(BOMB_TARGET_2b) 
  487. 	release_to_world(GROUP_GANG_SPAWN_2a) 
  488. 	release_to_world(GROUP_GANG_INTERMEDIATE) 
  489. 	release_to_world(GROUP_GANG_SPAWN_2b) 
  490. 	thread_kill(THREAD_NEXT_TARGET) 
  491. end 
  492.  
  493. function bh02_create_intermediate_gang_attack_group() 
  494. 	delay(1) 
  495. 	group_create(GROUP_GANG_INTERMEDIATE, true) 
  496. 	for index, name in pairs( TABLE_GANG_SPAWN_INTERMEDIATE ) do 
  497. 		vehicle_enter_teleport( name, VEHICLE_GANG_SPAWN_INTERMEDIATE, index - 1, false ) 
  498. 	end 
  499. 	delay(1) 
  500. 	vehicle_chase(VEHICLE_GANG_SPAWN_INTERMEDIATE, LOCAL_PLAYER) 
  501. 	delay(1) 
  502. end 
  503.  
  504. function bh02_start_persona_overrides() 
  505. 	persona_override_group_start( BH02_BROTHERHOOD_PERSONAS, POT_SITUATIONS[POT_ATTACK], "BR02_ATTACK" ) 
  506. 	persona_override_group_start( BH02_BROTHERHOOD_PERSONAS, POT_SITUATIONS[POT_CUSTOM_1], "BR02_BOMBS" ) 
  507.    for index, override in pairs ( DONNIE_PERSONA_OVERRIDES ) do 
  508.       persona_override_character_start(CHAR_DONNIE, override[1], override[2] ) 
  509.    end 
  510. end 
  511.  
  512. function bh02_stop_persona_overrides() 
  513.    if ( group_is_loaded( GROUP_ALLIES ) == true ) then 
  514.       persona_override_group_stop( BH02_BROTHERHOOD_PERSONAS, POT_SITUATIONS[POT_ATTACK] ) 
  515.       persona_override_group_stop( BH02_BROTHERHOOD_PERSONAS, POT_SITUATIONS[POT_CUSTOM_1] ) 
  516.       for index, override in pairs ( DONNIE_PERSONA_OVERRIDES ) do 
  517.          persona_override_character_stop(CHAR_DONNIE, override[1] ) 
  518.       end 
  519.    end 
  520. end 
  521.  
  522. function bh02_play_intro_conversation_then_start_driving_lines() 
  523. 	delay(2) 
  524. 	audio_play_conversation(VOICE_INTRO, NOT_CALL) 
  525.  
  526.    thread_new( "bh02_donnie_say_driving_lines" ) 
  527. end 
  528.  
  529. function bh02_donnie_say_driving_lines() 
  530.    -- Say all four lines 
  531.    for line_count = 1, NUM_DRIVING_LINES do 
  532.       -- Keep trying until we've played this line 
  533.       local cur_line_said = false 
  534.       while ( cur_line_said == false ) do 
  535.          -- Wait a random amount of time 
  536.          local pre_line_delay = rand_float( DRIVING_LINES_DELAY_MIN_SECONDS, 
  537.                                             DRIVING_LINES_DELAY_MAX_SECONDS ) 
  538.  
  539.          delay ( pre_line_delay ) 
  540.          if ( character_is_in_vehicle( CHAR_DONNIE ) ) then 
  541.             audio_play_for_character( DONNIE_DRIVING_LINES[line_count], CHAR_DONNIE, "voice", false, false ) 
  542.             --audio_play_persona_line( CHAR_DONNIE, DONNIE_COMPLAIN_PERSONA_SITUATION ) 
  543.             cur_line_said = true 
  544.          end 
  545.       end 
  546.    end 
  547. end 
  548.  
  549. function bh02_update_truck_destroyed_counter() 
  550. 	Num_targets_destroyed = Num_targets_destroyed + 1 
  551. 	objective_text(0, "bh02_trucks_destroyed", Num_targets_destroyed, 4) 
  552. end 
  553.  
  554. -- Wait until Donnie is sufficiently close to the bomb target before returning 
  555. function bh02_get_near_target() 
  556. 	marker_add_vehicle(Current_bomb_target, MINIMAP_ICON_KILL, INGAME_EFFECT_VEHICLE_KILL) 
  557. 	if Current_bomb_target_2nd then 
  558. 		marker_add_vehicle(Current_bomb_target_2nd, "", INGAME_EFFECT_VEHICLE_KILL) 
  559. 	end 
  560. 	mission_waypoint_add(Current_bomb_target) 
  561. 	local reached_truck_message_displayed = false 
  562. 	while ( get_vehicle_speed(CHAR_DONNIE) > DROPOFF_SPEED or 
  563.            get_dist_char_to_vehicle(CHAR_DONNIE, Current_bomb_target) > DROPOFF_DISTANCE ) do 
  564.  
  565. 		if ( ( Current_bomb_target == BOMB_TARGET_1) and 
  566.            ( not reached_truck_message_displayed) and 
  567.            ( get_dist_char_to_vehicle(CHAR_DONNIE, Current_bomb_target) < 80) ) then 
  568. 			reached_truck_message_displayed = true 
  569. 			 
  570. 		end 
  571. 		thread_yield() 
  572. 	end 
  573.  
  574.    mission_debug( "near target: "..Current_bomb_target ) 
  575. end 
  576.  
  577. -- Start donnie planting a bomb 
  578. function bh02_donnie_plant_bomb() 
  579. 	marker_remove_vehicle(Current_bomb_target) 
  580. 	if Current_bomb_target_2nd then 
  581. 		marker_remove_vehicle(Current_bomb_target_2nd) 
  582. 	end 
  583. 	mission_waypoint_remove() 
  584. 	Bomb_countdown_timer = BOMB_PLANT_TIME 
  585. 	patrol("bh02_plant_bomb", CHAR_DONNIE) 
  586. end 
  587.  
  588. function bh02_get_next_whining_line_index() 
  589.    Cur_whining_line = Cur_whining_line + 1 
  590.  
  591.    if ( Cur_whining_line > NUM_WHINING_LINES ) then 
  592.       Cur_whining_line = 1 
  593.    end 
  594.  
  595.    return Cur_whining_line 
  596. end 
  597.  
  598. function bh02_get_next_bombstart_line_index() 
  599. 	Cur_bombstart_line = Cur_bombstart_line + 1 
  600.  
  601.    if ( Cur_bombstart_line > NUM_BOMBSTART_LINES ) then 
  602.       Cur_bombstart_line = 1 
  603.    end 
  604.  
  605. 	return Cur_bombstart_line 
  606. end 
  607.  
  608. function bh02_get_next_bombfinish_line_index() 
  609. 	Cur_bombfinish_line = Cur_bombfinish_line + 1 
  610.  
  611.    if ( Cur_bombfinish_line > NUM_BOMBFINISH_LINES ) then 
  612.       Cur_bombfinish_line = 1 
  613.    end 
  614.  
  615. 	return Cur_bombfinish_line 
  616. end 
  617.  
  618.  
  619.  
  620. function bh02_force_facing() 
  621. 	while ( 1 ) do 
  622. 		turn_to( CHAR_DONNIE, Current_bomb_target ) 
  623. 		delay( 3.0 ) 
  624. 	end 
  625. end 
  626.  
  627. -- Actual bomb planting patrol function 
  628. function bh02_plant_bomb(donnie) 
  629. 	vehicle_exit(donnie) 
  630.  
  631. 	if coop_is_active() then 
  632. 		mission_help_table("bh02_target_donnie") 
  633. 	end 
  634.  
  635. 	local crouching = false 
  636.  
  637. 	on_vehicle_destroyed("failure_vehicle_donnie_death", Current_bomb_target) 
  638. 	--coop_scorebox_show() 
  639.  
  640. 	THREAD_DONNIE_ABANDONED = thread_new("bh02_donnie_abandoned_watch") 
  641.  
  642. 	persona_override_group_stop(BH02_BROTHERHOOD_PERSONAS, POT_SITUATIONS[POT_ATTACK]) 
  643. 	persona_override_group_start(BH02_BROTHERHOOD_PERSONAS, POT_SITUATIONS[POT_ATTACK], "BR02_BOMBS") 
  644.  
  645. 	local bomb_planting_audio 
  646.  
  647. 	local diag1_shown = false 
  648. 	local diag2_shown = false 
  649.  
  650. 	local force_facing_thread_handle = thread_new( "bh02_force_facing" ) 
  651. 	local line_index = bh02_get_next_bombstart_line_index() 
  652. 	audio_play_for_character( DONNIE_BOMBSTART_LINES[line_index], donnie, "voice", false, true) 
  653.  
  654. 	while Bomb_countdown_timer > 0  do 
  655. 		thread_yield() 
  656.  
  657.       if ((not diag1_shown) and (Bomb_countdown_timer < 25)) then 
  658.          diag1_shown = true 
  659.          local next_line_index = bh02_get_next_whining_line_index() 
  660.          audio_play_for_character( DONNIE_WHINING_LINES[next_line_index], CHAR_DONNIE, "voice", false, false ) 
  661.          --audio_play_persona_line( CHAR_DONNIE, DONNIE_WHINING_PERSONA_SITUATION ) 
  662.       elseif ((not diag2_shown) and (Bomb_countdown_timer < 12)) then 
  663.          diag2_shown = true 
  664.          local next_line_index = bh02_get_next_whining_line_index() 
  665.          audio_play_for_character( DONNIE_WHINING_LINES[next_line_index], CHAR_DONNIE, "voice", false, false ) 
  666.          --audio_play_persona_line( CHAR_DONNIE, DONNIE_WHINING_PERSONA_SITUATION ) 
  667.       end 
  668.  
  669.       if ( bh02_donnie_close_enough( donnie ) == false or 
  670.            not check_animation_state(donnie, STATE_PLANT_BOMB) ) then 
  671.  
  672. 			while ( crouch_is_crouching( donnie ) ) do 
  673. 				clear_animation_state(donnie) 
  674. 				crouch_stop( donnie ) 
  675.  
  676. 				thread_yield() 
  677. 			end 
  678.  
  679.          --move_to( donnie, BOMB_TARGET_PLANT_LOCATIONS[Current_bomb_target][1], 3, true, false ) 
  680.          --move_to( donnie, BOMB_TARGET_PLANT_LOCATIONS[Current_bomb_target][2], 1, true, false ) 
  681.          bh02_donnie_get_to_bomb_plant_location( donnie, Current_bomb_target ) 
  682.          set_animation_state(donnie, STATE_PLANT_BOMB) 
  683.          bomb_planting_audio = audio_play_for_navpoint("SFX_DON_BOMBPLANTING", Current_bomb_target, "foley") 
  684.       else 
  685.          if not crouch_is_crouching(donnie) then 
  686.             crouch_start(donnie) 
  687.             delay(1) 
  688.          end 
  689.  
  690.          -- If we're in singleplayer, fallthrough. In coop, a player must be near Donnie for him to plant the 
  691.          -- bomb. 
  692.          if ( ( coop_is_active() == false ) or bh02_either_player_near_donnie() ) then 
  693.             if not check_animation_state(donnie, STATE_PLANT_BOMB) then 
  694.                set_animation_state(donnie, STATE_PLANT_BOMB) 
  695.             end 
  696.             Bomb_countdown_timer = Bomb_countdown_timer - get_frame_time() 
  697.          else 
  698.             Donnie_canceled_by_not_being_watched = true 
  699.             if check_animation_state(donnie, STATE_PLANT_BOMB) then 
  700.                clear_animation_state(donnie) 
  701.             end 
  702.  
  703.             -- Don't continue until a player returns to being nearby 
  704.             if ( coop_is_active() ) then 
  705.                while ( bh02_either_player_near_donnie() == false ) do 
  706.                   thread_yield() 
  707.                end 
  708.             end 
  709.          end 
  710.       end 
  711. 	end 
  712.    mission_debug( "fell out of bomb planting loop", 15 ) 
  713.  
  714. 	audio_stop(bomb_planting_audio) 
  715. 	audio_play_for_navpoint("SFX_DON_BOMBPLANTED", Current_bomb_target, "foley") 
  716. 	local line_index = bh02_get_next_bombfinish_line_index() 
  717. 	audio_play_for_character( DONNIE_BOMBFINISH_LINES[line_index], donnie, "voice") 
  718. 	clear_animation_state(donnie) 
  719. 	if crouch_is_crouching(donnie) then 
  720. 		crouch_stop(donnie) 
  721. 	end		 
  722. 	thread_kill( force_facing_thread_handle ) 
  723.  
  724. 	persona_override_group_stop(BH02_BROTHERHOOD_PERSONAS, POT_SITUATIONS[POT_ATTACK]) 
  725. 	persona_override_group_start(BH02_BROTHERHOOD_PERSONAS, POT_SITUATIONS[POT_ATTACK], "BR02_ATTACK") 
  726.  
  727. 	--coop_scorebox_hide() 
  728. 	--on_vehicle_destroyed("bomb_explode", Current_bomb_target) 
  729. 	on_vehicle_destroyed("failure_vehicle_death", Current_bomb_target) 
  730.  
  731. 	if THREAD_DONNIE_ABANDONED ~= -1 then 
  732.       hud_timer_stop(2) 
  733.       marker_remove_npc(CHAR_DONNIE, SYNC_ALL) 
  734. 		thread_kill(THREAD_DONNIE_ABANDONED) 
  735. 	end 
  736. end 
  737.  
  738. function bh02_donnie_move_to_door( donnie, target_seat ) 
  739. 	while ( crouch_is_crouching( donnie ) ) do 
  740. 		clear_animation_state(donnie) 
  741. 		crouch_stop( donnie ) 
  742.  
  743. 		thread_yield() 
  744. 	end 
  745.  
  746.    move_to_vehicle_entry_point(donnie, Current_bomb_target, target_seat, 2 ) 
  747. end 
  748.  
  749. function bh02_donnie_get_to_bomb_plant_location( donnie, Current_bomb_target ) 
  750.    local LEFT = 0 
  751.    local RIGHT = 1 
  752.    local target_half = LEFT 
  753.  
  754.    local move_to_door_thread_handle = INVALID_THREAD_HANDLE 
  755.    local seat_to_move_to = -1 
  756.  
  757.    repeat 
  758.       if ( move_to_door_thread_handle ~= INVALID_THREAD_HANDLE ) then 
  759.          thread_kill( move_to_door_thread_handle ) 
  760.          move_to_door_thread_handle = INVALID_THREAD_HANDLE 
  761.       end 
  762.  
  763.       -- Choose a half of the vehicle to try to move to ( switch between them ) 
  764.       if ( target_half == RIGHT ) then 
  765.          target_half = LEFT 
  766.       else 
  767.          target_half = RIGHT 
  768.       end 
  769.  
  770.       seat_to_move_to = rand_int( 0, 1 ) 
  771.  
  772.       -- Choose a door on this half 
  773.       if ( target_half == LEFT ) then 
  774.          if ( seat_to_move_to == 1 ) then 
  775.             seat_to_move_to = 2 
  776.          end 
  777.       else -- target_half == RIGHT 
  778.          if ( seat_to_move_to == 0 ) then 
  779.             seat_to_move_to = 1 
  780.          else 
  781.             seat_to_move_to = 3 
  782.          end 
  783.       end 
  784.  
  785.       -- Don't switch around seats if the reason Donnie's re-doing this is because he wasn't watched. 
  786.       -- This way he doesn't run around the car constantly. 
  787.       if ( Donnie_canceled_by_not_being_watched ) then 
  788.          seat_to_move_to = Last_seat_index 
  789.          Donnie_canceled_by_not_being_watched = false 
  790.       end 
  791.  
  792.       -- Try to move to it 
  793.       mission_debug( "moving donnie to half "..target_half.." seat "..seat_to_move_to..".", 15 ) 
  794.       move_to_door_thread_handle = thread_new( "bh02_donnie_move_to_door", donnie, seat_to_move_to ) 
  795.       -- If, after some amount of time, we're not done moving there, try the whole thing again 
  796.       for i = 1, FIND_NEW_SEAT_LOCATION_TIME_SECONDS do 
  797.          delay( 1 ) 
  798.          if ( thread_check_done( move_to_door_thread_handle ) == true and bh02_donnie_close_enough( donnie ) ) then 
  799.             break 
  800.          end 
  801.       end 
  802.    until ( thread_check_done( move_to_door_thread_handle ) == true and bh02_donnie_close_enough( donnie ) ) 
  803.  
  804.    -- If we succeed, then crouch and start the hacking 
  805.    crouch_start(donnie) 
  806.    delay(1) 
  807.  
  808.    Last_seat_index = seat_to_move_to 
  809. end 
  810.  
  811. function bh02_donnie_close_enough( donnie ) 
  812.    return get_dist( donnie, Current_bomb_target ) < PLANT_BOMB_MAX_DISTANCE 
  813. end 
  814.  
  815. function bh02_donnie_abandoned_watch() 
  816. 	while 1 do 
  817. 		thread_yield() 
  818. 		if (get_dist_char_to_char(LOCAL_PLAYER, CHAR_DONNIE) > 50) then 
  819. 			minimap_icon_add_npc_radius(CHAR_DONNIE, "map_other_blip_human", 50, "", SYNC_LOCAL) 
  820. 			mission_help_table_nag("bh02_abandoning_donnie", SYNC_LOCAL) 
  821. 			hud_timer_set(2, 30000, "failure_donnie_dismiss", true) 
  822. 			while (get_dist_char_to_char(LOCAL_PLAYER, CHAR_DONNIE) > 50) do 
  823. 				thread_yield() 
  824. 			end 
  825. 			hud_timer_stop(2) 
  826. 			marker_remove_npc(CHAR_DONNIE, SYNC_ALL) 
  827. 		end 
  828. 	end 
  829. end 
  830.  
  831. function bh02_either_player_near_donnie() 
  832.    local dist = get_dist_closest_player_to_object( CHAR_DONNIE ) 
  833.    if ( dist <= CLOSE_ENOUGH_TO_DONNIE_DIST_METERS ) then 
  834.       return true 
  835.    end 
  836.  
  837.    return false 
  838. end 
  839.  
  840. function bh02_wait_until_planted(length) 
  841. 	if length == nil then 
  842. 		length = 0 
  843. 	end 
  844.  
  845. 	while (Bomb_countdown_timer > length) do 
  846. 		thread_yield() 
  847. 	end	 
  848. end 
  849.  
  850. function bh02_fix_detonator() 
  851. 	Bomb_countdown_timer = DETONATOR_FIX_TIME 
  852. 	while Bomb_countdown_timer > 0  do 
  853. 		thread_yield() 
  854. 		Bomb_countdown_timer = Bomb_countdown_timer - get_frame_time() 
  855. 	end 
  856. end 
  857.  
  858. function bh02_help_text_update_timer() 
  859.    delay( DETONATE_TRUCK_MESSAGES_VISIBLE_TIME_SECONDS + 1 ) 
  860. end 
  861.  
  862. function bh02_calculate_targets_visibility( target1, target2 ) 
  863.    if ( navpoint_in_player_fov( target1 ) ) then 
  864.       if ( target2 ) then 
  865.          if ( navpoint_in_player_fov( target2 ) ) then 
  866.             return true 
  867.          end 
  868.       else 
  869.          return true 
  870.       end 
  871.    end 
  872.  
  873.    return false 
  874. end 
  875. function bh02_detonator_equipped() 
  876.    if ( inv_item_get_equipped_item( LOCAL_PLAYER ) == DETONATOR_ITEM ) then 
  877.       return true 
  878.    end 
  879.  
  880.    return false 
  881. end 
  882.  
  883. function detonate_at_distance(target1, target2) 
  884. 	minimap_icon_add_vehicle_radius(target1, MINIMAP_ICON_EXPLODING, DETONATION_DISTANCE) 
  885. 	if target2 then 
  886. 		minimap_icon_add_vehicle_radius(target2, MINIMAP_ICON_EXPLODING, DETONATION_DISTANCE) 
  887. 	end 
  888. 	mission_help_table("bh02_get_away") 
  889.  
  890. 	while not_far_enough_away(target1, DETONATION_DISTANCE) and (not target2 or not_far_enough_away(target2, DETONATION_DISTANCE)) do 
  891. 		if target2 and vehicle_is_destroyed(target2) then 
  892. 			target2 = nil 
  893. 			minimap_icon_remove_vehicle(target2) 
  894. 		end 
  895. 		if vehicle_is_destroyed(target1) then 
  896. 			minimap_icon_remove_vehicle(target1) 
  897. 			if target2 then 
  898. 				target1 = target2 
  899. 				target2 = nil 
  900. 			else 
  901. 				return 
  902. 			end 
  903. 		end 
  904. 		thread_yield() 
  905. 	end 
  906.  
  907.    waypoint_add( target1, SYNC_ALL ) 
  908.  
  909.    -- Can't assign nil to a global variable 
  910.    if ( inv_item_get_equipped_item( LOCAL_PLAYER ) ~= nil ) then 
  911.       Prev_weapon = inv_item_get_equipped_item( LOCAL_PLAYER ) 
  912.    else 
  913.       Prev_weapon = "" 
  914.    end 
  915.    inv_weapon_add_temporary(LOCAL_PLAYER, DETONATOR_ITEM, 1, true ) 
  916. 	inv_item_equip(DETONATOR_ITEM, LOCAL_PLAYER) 
  917. 	Detonator_triggered = false 
  918.  
  919. 	on_vehicle_destroyed("", target1) 
  920. 	if target2 then 
  921. 		on_vehicle_destroyed("", target2) 
  922. 	end 
  923. 	 
  924. 	on_weapon_fired("trigger_detonator", LOCAL_PLAYER ) 
  925. 	 
  926. 	--mission_help_table("bh02_detonate", "", "", SYNC_LOCAL) 
  927.  
  928. 	repeat 
  929. 		thread_yield() 
  930. 		if target2 and vehicle_is_destroyed(target2) then 
  931. 			minimap_icon_remove_vehicle(target2) 
  932. 			target2 = nil 
  933. 			if not Detonator_triggered then 
  934. 				failure_vehicle_death(target2) 
  935. 			end 
  936. 		end 
  937. 		if vehicle_is_destroyed(target1) then 
  938. 			minimap_icon_remove_vehicle(target1) 
  939. 			if target2 then 
  940. 				target1 = target2 
  941. 				target2 = nil 
  942. 			else 
  943. 				target1 = nil 
  944. 			end 
  945. 			if not Detonator_triggered then 
  946. 				failure_vehicle_death(target1) 
  947. 			end 
  948. 		end 
  949.  
  950.       Targets_visible = bh02_calculate_targets_visibility( target1, target2 ) 
  951.  
  952.       -- Prompt the player for correct situations in which to detonate the truck 
  953.       -- If he doesn't have the truck in view, let him know 
  954.       --  
  955.       if ( Targets_visible == false ) then 
  956.          if ( thread_check_done( Timer_thread_handles[1] ) ) then 
  957.             mission_help_clear( SYNC_LOCAL ) 
  958.             mission_help_table_nag( HT_SEE_TRUCK_TO_DETONATE, "", "", SYNC_LOCAL ) 
  959.             Timer_thread_handles[1] = thread_new( "bh02_help_text_update_timer" ) 
  960.          end 
  961.       elseif ( bh02_detonator_equipped() == false ) then 
  962.          if ( thread_check_done( Timer_thread_handles[2] ) ) then 
  963.             mission_help_clear( SYNC_LOCAL ) 
  964.             mission_help_table_nag( HT_SWITCH_TO_DETONATOR, "", "", SYNC_LOCAL ) 
  965.             Timer_thread_handles[2] = thread_new( "bh02_help_text_update_timer" ) 
  966.          end 
  967.       else -- detonator equipped and truck in view 
  968.          if ( thread_check_done( Timer_thread_handles[3] ) ) then 
  969.             mission_help_clear( SYNC_LOCAL ) 
  970.             mission_help_table_nag( HT_PRESS_TO_DETONATE_BOMB, "", "", SYNC_LOCAL ) 
  971.             Timer_thread_handles[3] = thread_new( "bh02_help_text_update_timer" ) 
  972.          end 
  973.       end 
  974.  
  975. 	until Detonator_triggered or target1 == nil 
  976.     
  977.    waypoint_remove( SYNC_ALL ) 
  978.    mission_help_clear( SYNC_LOCAL ) 
  979.  
  980. 	if not Detonator_triggered then 
  981. 		on_weapon_fired("", LOCAL_PLAYER) 
  982. 		inv_weapon_remove_temporary(LOCAL_PLAYER, DETONATOR_ITEM) 
  983.       inv_item_equip( Prev_weapon, LOCAL_PLAYER ) 
  984. 		failure_vehicle_death(target1) 
  985. 	end 
  986.  
  987. 	if target1 then 
  988. 		minimap_icon_remove_vehicle(target1) 
  989. 		bomb_explode(target1) 
  990. 	end 
  991.  
  992. 	if target2 then 
  993. 		minimap_icon_remove_vehicle(target2) 
  994. 		bomb_explode(target2) 
  995. 	end 
  996. end 
  997.  
  998. function trigger_detonator( player, weapon ) 
  999. 	if weapon == DETONATOR_ITEM and not Detonator_triggered then 
  1000.       -- Only allow the detonator to be set off if all current targets are visible 
  1001.       if ( Targets_visible ) then 
  1002.          Detonator_triggered = true 
  1003.          audio_play_for_character( "SFX_DON_BOMB_DETONATE", player, "foley" ) 
  1004.          if ( character_is_in_vehicle( player ) == false ) then 
  1005.             action_play(player, ACTION_DETONATE) 
  1006.          end 
  1007.          delay(0.5) 
  1008.          inv_weapon_remove_temporary(LOCAL_PLAYER, DETONATOR_ITEM) 
  1009.          inv_item_equip( Prev_weapon, LOCAL_PLAYER ) 
  1010.          on_weapon_fired("", player) 
  1011.       else 
  1012.          inv_weapon_remove_temporary(LOCAL_PLAYER, DETONATOR_ITEM) 
  1013.          inv_weapon_add_temporary(LOCAL_PLAYER, DETONATOR_ITEM, 1, true ) 
  1014. 	      inv_item_equip(DETONATOR_ITEM, LOCAL_PLAYER) 
  1015.       end 
  1016. 	end 
  1017. end 
  1018.  
  1019. function not_far_enough_away(target, distance) 
  1020. 	return get_dist(CHAR_DONNIE, target) < distance or get_dist(LOCAL_PLAYER, target) < distance or ( coop_is_active() and get_dist(REMOTE_PLAYER, target) < distance) 
  1021. end 
  1022.  
  1023. function bh02_chase_players() 
  1024. 	group_create(GROUP_GANG_SPAWN_3b, true) 
  1025. 	set_unjackable_flag(BOMB_TARGET_3, false) 
  1026. 	vehicle_enter_group_teleport(TABLE_GANG_SPAWN_3b, Current_bomb_target) 
  1027. 	set_unjackable_flag(BOMB_TARGET_3, true) 
  1028. 	vehicle_suppress_npc_exit(Current_bomb_target, true) 
  1029. 	repeat  
  1030. 		thread_yield() 
  1031. 		vehicle_chase(Current_bomb_target, get_closest_target(Current_bomb_target), false, true, true) 
  1032. 		delay(5) 
  1033. 	until vehicle_is_destroyed(Current_bomb_target)	 
  1034. end 
  1035.  
  1036. function get_closest_target(attacker) 
  1037. 	local dist_to_donnie = get_dist(attacker, CHAR_DONNIE) 
  1038. 	local dist_to_local_player = get_dist(attacker, LOCAL_PLAYER) 
  1039. 	local dist_to_remote_player = dist_to_local_player + 1000 
  1040. 	 
  1041. 	if coop_is_active() then 
  1042. 		dist_to_remote_player = get_dist(attacker, REMOTE_PLAYER) 
  1043. 	end 
  1044. 	 
  1045. 	if dist_to_donnie < dist_to_local_player and dist_to_donnie < dist_to_remote_player then 
  1046. 		return CHAR_DONNIE 
  1047. 	end 
  1048. 	 
  1049. 	if dist_to_local_player < dist_to_remote_player then 
  1050. 		return LOCAL_PLAYER 
  1051. 	end 
  1052. 	 
  1053. 	return REMOTE_PLAYER 
  1054. end 
  1055.  
  1056. function bomb_explode(vehicle) 
  1057.    vehicle_infinite_mass( vehicle, false ) 
  1058.    vehicle_prevent_explosion_fling( vehicle, false ) 
  1059.  
  1060.    turn_vulnerable( vehicle ) 
  1061. 	explosion_create(Explosion, vehicle, CHAR_DONNIE, false) 
  1062. 	if not vehicle_is_destroyed(vehicle) then 
  1063. 		vehicle_detonate(vehicle) 
  1064. 	end 
  1065. end 
  1066.  
  1067.  
  1068. function bh02_next_target_watch() 
  1069. 	repeat 
  1070. 		thread_yield() 
  1071. 		if get_dist(Next_target, LOCAL_PLAYER) < NEXT_TARGET_ALERT_RADIUS or (coop_is_active() and get_dist(Next_target, REMOTE_PLAYER) < NEXT_TARGET_ALERT_RADIUS ) then 
  1072. 			mission_help_table("bh02_detonate_last_target") 
  1073. 			delay(5) 
  1074. 		else 
  1075. 			delay(1) 
  1076. 		end 
  1077. 	until false 
  1078. end 
  1079.  
  1080. function failure_donnie_dismiss() 
  1081. 	delay(3) 
  1082. 	mission_end_failure(CURRENT_MISSION, "bh02_donnie_dismissed") 
  1083. end 
  1084.  
  1085. function failure_vehicle_death(vehicle) 
  1086. 	delay(3) 
  1087. 	mission_end_failure(CURRENT_MISSION, "bh02_vehicle_lost") 
  1088. end 
  1089.  
  1090. function failure_vehicle_donnie_death(vehicle) 
  1091. 	objective_text_clear(0) 
  1092. 	hud_timer_stop(1) 
  1093. 	character_kill(CHAR_DONNIE) 
  1094. 	bomb_explode(vehicle) 
  1095. 	delay(3) 
  1096. 	mission_end_failure(CURRENT_MISSION, "bh02_donnie_died") 
  1097. end 
  1098.  
  1099. function bh02_success() 
  1100. 	Mission_Successful = true 
  1101. end 
  1102.  
  1103. function bh02_cleanup() 
  1104. 	for i, thread in pairs(TABLE_ALL_THREADS) do 
  1105. 		thread_kill(thread) 
  1106. 	end 
  1107.  
  1108. 	if not Detonator_triggered then 
  1109. 		Detonator_triggered = false 
  1110. 		inv_weapon_remove_temporary(LOCAL_PLAYER, DETONATOR_ITEM) 
  1111. 		on_weapon_fired("", LOCAL_PLAYER) 
  1112.       inv_item_equip( Prev_weapon, LOCAL_PLAYER ) 
  1113. 	end 
  1114. 	 
  1115. 	notoriety_reset( ENEMY_GANG ) 
  1116. 	notoriety_reset ( "Police" ) 
  1117.  
  1118. 	objective_text_clear(0) 
  1119.  
  1120. 	hud_timer_stop(1) 
  1121.  
  1122. 	bh02_stop_persona_overrides() 
  1123.  
  1124. 	--party_dismiss(CHAR_DONNIE) 
  1125. 	object_destroy(CHAR_DONNIE) 
  1126. 	if (Mission_Successful == false) then 
  1127. 	object_destroy(VEHICLE_LIN_MOBILE) 
  1128. 	end	 
  1129. 	mission_waypoint_remove() 
  1130. 	 
  1131. 	if Current_bomb_target then 
  1132. 		marker_remove_vehicle(Current_bomb_target) 
  1133. 	end 
  1134.  
  1135. 	for i, group in pairs(TABLE_ALL_GROUPS) do 
  1136. 		release_to_world(group) 
  1137. 	end 
  1138. end 
  1139.