sr2lua/rn10.lua

  1. -- rn10.lua 
  2. -- SR2 mission script 
  3. -- 3/28/07 
  4.  
  5. -- DEBUGGING STUFF 
  6. Debug_ronin = "" 
  7.  
  8. -- Global constants ( ALL_CAPS means that they shouldn't be modified in running code, except for maybe	group_create_hidden(group) in a setup function ) 
  9.  
  10. 	-- KNOBS_TO_TURN -- 
  11.  
  12. 		AKUJI_USE_SWORD = false 
  13.  
  14. 			--[[ *** READ ME *** 
  15. 			 
  16. 				Whenever a script function looks up a wave parameter, a naming convention is used to select the appropriate value. 
  17. 				Parameter values for single player missions can use any name, say "PARAMETER_1" for example. If you wish to have 
  18. 				a different value for that parameter in coop, then prepend "COOP" to the parameter name. In this case, we get 
  19. 				"COOP_PARAMETER_1". 
  20.  
  21. 				When a mission function needs to access "PARAMETER_1", it will search for the appropriate overloaded values first: 
  22.  
  23. 					*	Single player will use the value stored in "PARAMETER_1". 
  24. 				 
  25. 					*	Coop will use the value stored in "COOP_PARAMETER_1", if it exists. Otherwise it will use the 
  26. 						default single player value stored in "PARAMETER_1". 
  27. 			 ]] 
  28.  
  29. 			-- Mission parameters 
  30. 			rn10_PARAMETERS	=  
  31. 				{	 
  32.  
  33. 					-- Stage 1, defend the HQ 
  34.  
  35. 						-- single-player values 
  36. 						["WAVE_MIN_SIZE"]			=	3, -- Smallest # of enemies that will spawn in a given wave. 
  37. 						["WAVE_MAX_SIZE"]			=	5, -- Largeset # of enemies that will spawn in a given wave. 
  38. 						["WAVE_MAX_ATTACKERS"]	=	8, -- Max # of enemies that can be attacking at one time. 
  39.  
  40. 						["WAVE_RPG_CHANCE"]		= .2,-- Probability that the Ronin will have an rpg 
  41. 						["WAVE_GRENADE_CHANCE"] = .5, -- If no rpg, probability to have grenades 
  42. 						["WAVE_MOLOTOV_CHANCE"] = .3, -- If no grenades, probability to hvae molotov 
  43.  
  44. 						["PILLAR_MAX_HIT_POINTS"] = 1000, -- Number of "hit points" each set of supports has. 
  45. 						["PILLAR_DEFEND_TIME_S"]	= 80,  -- How long the player(s) must defend each set of supports. 
  46.  
  47. 						["BATTLE_RESPAWN_DIST"] = 20, -- Min distance at which to respawn a Ronin/Saints battle 
  48. 						 
  49. 						-- coop values 
  50.  
  51. 					-- Stage 2, boss fight 
  52. 					 
  53. 						-- single-player values 
  54. 						["AKUJI_HIT_POINTS"]			= 3500, 
  55. 						["AKUJI_LTNT_HIT_POINTS"]	= 1500, 
  56. 						["AKUJI_FLEE_HEALTH_RATIO"] = .2, -- Current to max health ratio at which Akuji flees 
  57.  
  58. 						-- coop values 
  59.  
  60. 				} 
  61.  
  62. 	-- COOP MISSION? --  
  63. 		IN_COOP	= false 
  64.  
  65. 	-- CHARACTERS -- 
  66.  
  67. 		CHARACTER_PIERCE		= "rn10_$Cpierce" 
  68. 		CHARACTER_GAT			= "rn10_$Cgat" 
  69. 		CHARACTER_WONG			= "rn10_$Cwong" 
  70. 		CHARACTER_TRANSLATOR	= "rn10_$Ctranslator" 
  71. 		CHARACTER_AKUJI		= "rn10_$Cakuji" 
  72.  
  73. 	-- CHECKPOINTS 
  74. 		 
  75. 		CHECKPOINT_START			= MISSION_START_CHECKPOINT			-- defined in ug_lib.lua 
  76. 		CHECKPOINT_FIRST_PILLAR = "rn10_checkpoint_first_pillar" -- first set of pillars defended 
  77. 		CHECKPOINT_AKUJI			= "rn10_checkpoint_akuji"			-- just before the fight w/ Akuji begins 
  78. 		 
  79. 	-- GROUPS -- 
  80.  
  81. 		GROUP_RONIN_STAGE_1		= "rn10_$Gronin_stage_1" 
  82. 		GROUP_RONIN_STAGE_2		= "rn10_$Gronin_stage_2" 
  83.  
  84. 		GROUP_CHAOS_SAINTS_1		= "rn10_$Gchaos_saints_1" 
  85. 		GROUP_CHAOS_RONIN_1		= "rn10_$Gchaos_ronin_1" 
  86. 		GROUP_CHAOS_SAINTS_2		= "rn10_$Gchaos_saints_2" 
  87. 		GROUP_CHAOS_RONIN_2		= "rn10_$Gchaos_ronin_2" 
  88.  
  89. 	-- GROUP MEMBER TABLES --  
  90.  
  91. 		MEMBERS_GROUP_RONIN_STAGE_1	= {	"rn10_$c000", "rn10_$c001", "rn10_$c002", "rn10_$c003", 
  92. 														"rn10_$c004", "rn10_$c005", "rn10_$c006", "rn10_$c007", 
  93. 														"rn10_$c008", "rn10_$c009", "rn10_$c010", "rn10_$c011", 
  94. 														"rn10_$c012", "rn10_$c013", "rn10_$c014", "rn10_$c015", 
  95. 														"rn10_$c016", "rn10_$c017", "rn10_$c018", "rn10_$c019"} 
  96. 	 
  97. 		MEMBERS_GROUP_CHAOS_SAINTS_1	= {	"rn10_$c024", "rn10_$c025", "rn10_$c026"}	 
  98. 		MEMBERS_GROUP_CHAOS_RONIN_1	= {	"rn10_$c027", "rn10_$c028", "rn10_$c029"} 
  99. 		MEMBERS_GROUP_CHAOS_SAINTS_2	= {	"rn10_$c033", "rn10_$c034", "rn10_$c035"}	 
  100. 		MEMBERS_GROUP_CHAOS_RONIN_2	= {	"rn10_$c030", "rn10_$c031", "rn10_$c032"} 
  101.  
  102. 	-- HELPTEXT 
  103.  
  104. 		-- localized helptext messages 
  105.  
  106. 			-- Failure conditions 
  107. 			HELPTEXT_FAILURE_GAT_ABANDONED		= "rn10_failure_gat_abandoned" 
  108. 			HELPTEXT_FAILURE_GAT_DIED				= "rn10_failure_gat_died" 
  109. 			HELPTEXT_FAILURE_PIERCE_ABANDONED	= "rn10_failure_pierce_abandoned" 
  110. 			HELPTEXT_FAILURE_PIERCE_DIED			= "rn10_failure_pierce_died" 
  111. 			HELPTEXT_FAILURE_SUPPORT_COLLAPSED	= "rn10_failure_support_collapsed" -- The ceiling collapsed. 
  112.  
  113. 			-- Hud 
  114. 			HELPTEXT_HUD_PILLAR_HEALTH				= "rn10_hud_pillar_health"	-- Structural Integrity 
  115. 			HELPTEXT_HUD_AKUJI_HEALTH				= "rn10_hud_akuji_health" 
  116.  
  117. 			-- Prompts 
  118. 			HELPTEXT_PROMPT_MISSION_START			= "rn10_prompt_mission_start"	-- Find out what the Ronin are doing in the underground. 
  119. 			HELPTEXT_PROMPT_PROTECT_SUPPORTS		= "rn10_prompt_protect_supports" -- Don't let the Ronin blow up the ceiling supports. 
  120. 			HELPTEXT_PROMPT_NEXT_DEFENSE			= "rn10_prompt_next_defense" -- 	Look for other Ronin demolition teams. 
  121. 			HELPTEXT_PROMPT_KILL_AKUJI				= "rn10_prompt_kill_akuji" -- Kill Akuji 
  122.  
  123. 			-- Objectives 
  124. 			--HELPTECT_OBJECTIVE_PROTECT_SUPPORTS	= "rn10_objective_protect_supports" -- Protect the ceiling supports. 
  125.  
  126. 			-- Misc. 
  127.  
  128. 		-- unlocalized helptext messages 
  129.  
  130. 	-- MOVERS 
  131.  
  132. 	-- NAVPOINTS 
  133.  
  134. 		NAVPOINT_LOCAL_PLAYER_START		= "rn10_$Nlocal_player_start" 
  135. 		NAVPOINT_REMOTE_PLAYER_START		= "rn10_$Nremote_player_start" 
  136.  
  137. 	-- TRIGGERS --  
  138. 	 
  139. 		-- List of all triggers, makes cleaning up more convenient 
  140. 		TABLE_ALL_TRIGGERS		= {	}		 
  141.  
  142. 	-- VEHICLES -- 
  143.  
  144.  
  145. 	-- MISC CONSTANTS 
  146.  
  147. 		RONIN_RESPAWN_TIME_MS			= 1000  -- Time in MS before respawning 
  148. 		RONIN_RESPAWN_DISTANCE			= 0.01 
  149.  
  150.  
  151. 		OTHER_PLAYER	=	{	[LOCAL_PLAYER]	= REMOTE_PLAYER, 
  152. 									[REMOTE_PLAYER] = LOCAL_PLAYER, 
  153. 								} 
  154.  
  155. 		PLAYER_SYNC		=	{	[LOCAL_PLAYER]	= SYNC_LOCAL, 
  156. 									[REMOTE_PLAYER] = SYNC_REMOTE, 
  157. 								} 
  158.  
  159. 		-- defense locations are numbered in the same order as the map on  
  160. 		-- http://wiki.volition.net//tiki-index.php?page=SR2+Ronin+Mission+10 
  161.  
  162. 		-- Each defense objective is an area containing one or more ceiling supports. Players must 
  163. 		-- defend the supports as incoming waves of Ronin attack them. 
  164. 		DEFENSE_OBJECTIVES	= 
  165. 			{ 
  166. 				{ 
  167. 					-- Regions which trigger the start of a defense objective. 
  168. 					["trigger"]		= "rn10_$Tdefense_1", 
  169.  
  170. 					-- Floating navpoints inside the pillars at which the Ronin will shoot. 
  171. 					["ai targets"]	= {"rn10_$Ndefense_1_pillar_1", "rn10_$Ndefense_1_pillar_2"}, 
  172.  
  173. 					-- Spawn locations which are close to this objective. 
  174. 					["spawn locations"] = {1,2,3,6}, 
  175.  
  176. 					-- Spawn location(s) at which we'd prefer to spawn the initial allotment 
  177. 					-- of Ronin to attack this area. 
  178. 					["preferred initial locations"] = {6}, 
  179. 				}, 
  180. 				--[[ 
  181. 				{ 
  182. 					["trigger"]		= "rn10_$Tdefense_2", 
  183. 					["ai targets"]	= {"rn10_$Tdefense_2_pillar_1", "rn10_$Tdefense_2_pillar_2"}, 
  184. 					["spawn locations"] = {2,3,4}, 
  185. 					["preferred initial locations"] = {4}, 
  186. 				}, 
  187. 				]] 
  188. 				{ 
  189. 					["trigger"]		= "rn10_$Tdefense_3", 
  190. 					["ai targets"]	= {"rn10_$Tdefense_3_pillar_1", "rn10_$Tdefense_3_pillar_2", 
  191. 											"rn10_$Tdefense_3_pillar_3", "rn10_$Tdefense_3_pillar_4"}, 
  192. 					["spawn locations"] = {7,8,9,10,2}, 
  193. 					["preferred initial locations"] = {7,8}, 
  194. 				}, 
  195. 			} 
  196.  
  197. 		-- Navpoints from which the ai targets can be attacked 
  198. 		TARGET_ATTACK_POSITIONS = 
  199. 			{ 
  200. 				["rn10_$Ndefense_1_pillar_1"] = {"rn10_$n018", "rn10_$n019", "rn10_$n020", "rn10_$n021", 
  201. 															"rn10_$n022", "rn10_$n023", "rn10_$n024", "rn10_$n025"}, 
  202. 				["rn10_$Ndefense_1_pillar_2"] = {"rn10_$n026", "rn10_$n027", "rn10_$n028", "rn10_$n029", 
  203. 															"rn10_$n030", "rn10_$n031", "rn10_$n032", "rn10_$n033"}, 
  204. 				["rn10_$Tdefense_2_pillar_1"] = {"rn10_$n037", "rn10_$n038", "rn10_$n039", "rn10_$n040", 
  205. 															"rn10_$n041", "rn10_$n048", "rn10_$n049", "rn10_$n050"}, 
  206. 				["rn10_$Tdefense_2_pillar_2"] = {"rn10_$n042", "rn10_$n043", "rn10_$n044", "rn10_$n045", 
  207. 															"rn10_$n046", "rn10_$n047", "rn10_$n051", "rn10_$n052"}, 
  208. 				["rn10_$Tdefense_3_pillar_1"] = {"rn10_$n053", "rn10_$n054", "rn10_$n055", "rn10_$n057", 
  209. 															"rn10_$n066", "rn10_$n067", "rn10_$n068", "rn10_$n069"}, 
  210. 				["rn10_$Tdefense_3_pillar_2"] = {"rn10_$n053", "rn10_$n054", "rn10_$n055", "rn10_$n056", 
  211. 															"rn10_$n057", "rn10_$n058", "rn10_$n066", "rn10_$n067"}, 
  212. 				["rn10_$Tdefense_3_pillar_3"] = {"rn10_$n053", "rn10_$n054", "rn10_$n055", "rn10_$n056", 
  213. 															"rn10_$n057", "rn10_$n058", "rn10_$n066", "rn10_$n067", 
  214. 															"rn10_$n068", "rn10_$n069"}, 
  215. 				["rn10_$Tdefense_3_pillar_4"] = {"rn10_$n058", "rn10_$n059", "rn10_$n060", "rn10_$n061", 
  216. 															"rn10_$n062", "rn10_$n063", "rn10_$n064", "rn10_$n065"}, 
  217. 			} 
  218. 		 
  219. 		-- Spawn locations for the waves of Ronin attackers in stage 1. 
  220. 		SPAWN_LOCATIONS =	 
  221. 			{	 
  222. 				[1] = {	-- The set of triggers defining the portion of the level with line-of-sight to  
  223. 							-- the spawn navpoints. If no player is in any of these triggers, then we can 
  224. 							-- safely spawn ronin in this location without fear of popping. 
  225. 							["triggers"]	= {"rn10_$Tspawn_location_1_trigger_1"},  
  226.  
  227. 							-- The actual navpoints at which the Ronin spawn. 
  228. 							["navpoints"]	= {	"rn10_$n000", "rn10_$n001", "rn10_$n002", "rn10_$n003", 
  229. 														"rn10_$n004", "rn10_$n005", "rn10_$n006", "rn10_$n007"}, 
  230.  
  231. 							-- The first navpoint to which the spawned Ronin pathfind. Often, the spawn 
  232. 							-- navpoints are set in small, out of the way rooms and the Ronin have difficulty 
  233. 							-- pathfinding out. Kevin P. has made improvements to pathfinding which probably 
  234. 							-- make the exit navpoint obsolete. 
  235. 							["exit"]			= {	"rn10_$n034"}, 
  236. 						}, 
  237. 				[2] = {	["triggers"]	= {"rn10_$Tspawn_location_2_trigger_1"},  
  238. 							["navpoints"]	= {	"rn10_$n008", "rn10_$n009", "rn10_$n010", "rn10_$n011"}, 
  239. 							["exit"]			= {	"rn10_$n035"}, 
  240. 						}, 
  241. 				[3] = {	["triggers"]	= {"rn10_$Tspawn_location_3_trigger_1"},  
  242. 							["navpoints"]	= {	"rn10_$n070", "rn10_$n071", "rn10_$n072", "rn10_$n073", 
  243. 														"rn10_$n074", "rn10_$n075"}, 
  244. 							["exit"]			= {	"rn10_$n076"}, 
  245. 						}, 
  246. 				[4] = {	["triggers"]	= {"rn10_$Tspawn_location_4_trigger_1"},  
  247. 							["navpoints"]	= {	"rn10_$n077", "rn10_$n078", "rn10_$n079", "rn10_$n080", 
  248. 														"rn10_$n081", "rn10_$n082"}, 
  249. 							["exit"]			= {	"rn10_$n083"}, 
  250. 						}, 
  251. 				[6] = {	["triggers"]	= {"rn10_$Tspawn_location_6_trigger_1"}, 
  252. 							["navpoints"]	= {	"rn10_$n012", "rn10_$n013", "rn10_$n014", "rn10_$n015", 
  253. 														"rn10_$n016", "rn10_$n017"}, 
  254. 							["exit"]			= {	"rn10_$n036"}, 
  255. 						}, 
  256. 				-- Spawn locations 7 and 8 intentionally share a trigger. 
  257. 				[7] = {	["triggers"]	= {"rn10_$Tspawn_location_7_trigger_1"}, 
  258. 							["navpoints"]	= {	"rn10_$n084", "rn10_$n085", "rn10_$n086", "rn10_$n087"}, 
  259. 							["exit"]			= {	"rn10_$n088"}, 
  260. 						}, 
  261. 				[8] = {	["triggers"]	= {"rn10_$Tspawn_location_7_trigger_1"}, 
  262. 							["navpoints"]	= {	"rn10_$n089", "rn10_$n090", "rn10_$n091", "rn10_$n092"}, 
  263. 							["exit"]			= {	"rn10_$n093"}, 
  264. 						}, 
  265. 				[9] = {	["triggers"]	= {"rn10_$Tspawn_location_9_trigger_1"}, 
  266. 							["navpoints"]	= {	"rn10_$n094", "rn10_$n096"}, 
  267. 							["exit"]			= {	"rn10_$n095"}, 
  268. 						}, 
  269. 				[10] = {	["triggers"]	= {"rn10_$Tspawn_location_10_trigger_1"}, 
  270. 							["navpoints"]	= {	"rn10_$n097", "rn10_$n098", "rn10_$n099", "rn10_$n100"}, 
  271. 							["exit"]			= {	"rn10_$n101"}, 
  272. 						}, 
  273. 			} 
  274.  
  275. 	STATIONARY_BATTLES =  
  276. 		{ 
  277. 			{ 
  278. 				["group"] = "", 
  279. 				["saints"] = {}, 
  280. 				["ronin"] = {}, 
  281. 			}, 
  282. 			{ 
  283. 				["group"] = "", 
  284. 				["saints"] = {}, 
  285. 				["ronin"] = {}, 
  286. 			}, 
  287. 			{ 
  288. 				["group"] = "", 
  289. 				["saints"] = {}, 
  290. 				["ronin"] = {}, 
  291. 			}, 
  292. 		} 
  293.  
  294. RN10_RONIN_PERSONAS	= { 
  295. 	["AM_Ron2"]	=	"AMRON2", 
  296.  
  297. 	["AF_Ron1"]	=	"AFRON1", 
  298. 	["AF_Ron3"]	=	"AFRON3", 
  299.  
  300. 	["WM_Ron1"]	=	"WMRON1", 
  301.  
  302. 	["WF_Ron1"]	=	"WFRON1", 
  303. 	["WF_Ron2"]	=	"WFRON2", 
  304. } 
  305.  
  306. RN10_SAINTS_PERSONAS = { 
  307. 	["AM_TSS2"]	=	"AMTSS2", 
  308. 	["AM_TSS3"]	=	"AMTSS3", 
  309.  
  310. 	["BM_TSS1"]	=	"BMTSS1", 
  311. 	["BM_TSS2"]	=	"BMTSS2", 
  312.  
  313. 	["BF_TSS1"]	=	"BFTSS1", 
  314. 	["BF_TSS2"]	=	"BFTSS2", 
  315.  
  316. 	["HM_TSS1"]	=	"HMTSS1", 
  317. 	["HM_TSS2"]	=	"HMTSS2", 
  318. 	["HM_TSS3"]	=	"HMTSS3", 
  319.  
  320. 	["HF_TSS3"]	=	"HFTSS3", 
  321.  
  322. 	["WM_TSS2"]	=	"WMTSS2", 
  323. 	["WM_TSS3"]	=	"WMTSS3", 
  324.  
  325. 	["WF_TSS1"]	=	"WFTSS1", 
  326. 	["WF_TSS2"]	=	"WFTSS2", 
  327. 	["WF_TSS3"]	=	"WFTSS3", 
  328. } 
  329.  
  330.  
  331. -- Progress flags 
  332. 	Akuji_fleeing						= false  -- Is Akuji fleeing the players in the final stage. 
  333.  
  334. -- Misc 
  335.  
  336. 	-- Spawn locations are defined by one more more triggers. This structure maps trigger -> spawn location index. 
  337. 	Map_trigger_to_spawn_location_index = {} -- Maps from trigger -> spawn location index 
  338.  
  339. 	-- Maps spawn location -> (# times a player entered the location's trigger(s)) - (# of times a player left) 
  340. 	-- Technically, this isn't a count of how many players are in the spawn location because it could have two 
  341. 	-- or more overlapping triggers. However, it is still the case that no players are in the spawn location if 
  342. 	-- and only if the value is 0 
  343. 	Num_players_in_spawn_locations = {} 
  344.  
  345. 	-- Each defense objective has an associated trigger. If a player completes an objective while they are standing 
  346. 	-- inside the trigger of another incomplete objective, then they should immediately start or join that objective. 
  347. 	-- This structure keeps track of which defense objective triggers each player occupies. 
  348. 	--[[  
  349.  
  350. 	*** (This structure is now defined in mission_gloabls.lua) *** 
  351.  
  352. 	Rn10_player_defense_objectives_occupied_at_checkpoint = 
  353. 		{ 
  354. 			[LOCAL_PLAYER]		= {}, 
  355. 			[REMOTE_PLAYER]	= {}, 
  356. 		} 
  357. 	]] 
  358.  
  359. 	Rn10_player_defense_objectives_occupied = 
  360. 		{ 
  361. 			[LOCAL_PLAYER]		= {}, 
  362. 			[REMOTE_PLAYER]	= {}, 
  363. 		} 
  364.  
  365. 	-- Defense objectives that have been completed: 
  366. 	Defense_objective_completed = {} 
  367. 	 
  368. 	-- Which defense objective each player is working on. 
  369. 	NO_ACTIVE_DEFENSE_OBJECTIVE = 0 
  370. 	Player_active_defense_objective =  
  371. 		{ 
  372. 			[LOCAL_PLAYER]		= NO_ACTIVE_DEFENSE_OBJECTIVE, 
  373. 			[REMOTE_PLAYER]	= NO_ACTIVE_DEFENSE_OBJECTIVE, 
  374. 		} 
  375.  
  376. 	-- Ronin which aren't currently spawned. 
  377. 	Spawnable_ronin	= {} 
  378.  
  379. 	-- For each spawn location, store the index of the next navpoint at which to spawn a ronin 
  380. 	-- The index is modularly incremented. I use this to decrease the chance that ronin will 
  381. 	-- be spawned on top of each other. 
  382. 	Spawn_locations_next_navpoint_index = {} 
  383.  
  384. 	-- Track which defense objective the ronin is attacking. 
  385. 	Ronin_defense_objective_targeted = {} 
  386.  
  387. 	-- Total number of ronin attacking each defense objective 
  388. 	Num_living_attackers = {} 
  389.  
  390. 	-- Each support has a number of associated nav points from which the Ronin have line of sight 
  391. 	-- to attack. This structure tracks which Ronin occupy each of these attack positions so that 
  392. 	-- I don't have them pathfinding to the same spot. 
  393. 	Target_attack_position_occupants = {} 
  394.  
  395. 	-- First navpoint that the Ronin should pathfind to after spawning 
  396. 	Spawn_area_exits = {} 
  397.  
  398. 	-- Pillar health 
  399. 	Pillar_max_hit_points = {}; 
  400.  
  401. 	-- Patrol threads for attacking ronin. 
  402. 	Ronin_patrol_threads = {} 
  403. 	 
  404.  
  405. -- Main Thread: 
  406. function rn10_start(rn10_checkpoint, is_restart) 
  407.  
  408. 	if (rn10_checkpoint == CHECKPOINT_START) then 
  409. 		if (not is_restart) then 
  410. 			cutscene_play("ro10-01") 
  411. 		end 
  412. 		fade_out(0) 
  413. 	end 
  414.  
  415. 	rn10_initialize(rn10_checkpoint) 
  416.  
  417. 	-- Stage 1, defend structural weak points in the Ronin HQ from sappers 
  418. 	if(rn10_checkpoint == CHECKPOINT_START) then 
  419.  
  420. 		-- Defend the first objective 
  421. 		rn10_defend_objective(1) 
  422.  
  423. 		-- CHECKPOINT! 
  424. 		for trigger, occupied in pairs(Rn10_player_defense_objectives_occupied[LOCAL_PLAYER]) do 
  425. 			Rn10_player_defense_objectives_occupied_at_checkpoint[LOCAL_PLAYER][trigger] = occupied 
  426. 		end 
  427. 		for trigger, occupied in pairs(Rn10_player_defense_objectives_occupied[REMOTE_PLAYER]) do 
  428. 			Rn10_player_defense_objectives_occupied_at_checkpoint[REMOTE_PLAYER][trigger] = occupied 
  429. 		end		mission_set_checkpoint(CHECKPOINT_FIRST_PILLAR) 
  430. 		rn10_checkpoint = CHECKPOINT_FIRST_PILLAR 
  431. 		delay(1.0) 
  432.  
  433. 	end -- ends CHECKPOINT_START 
  434.  
  435. 	-- Stage 1b, defend structural weak points in the Ronin HQ from sappers 
  436. 	if(rn10_checkpoint == CHECKPOINT_FIRST_PILLAR) then 
  437.  
  438. 		-- Defend the second objective 
  439. 		rn10_defend_objective(2) 
  440.  
  441. 		-- CHECKPOINT! 
  442. 		mission_set_checkpoint(CHECKPOINT_AKUJI) 
  443. 		rn10_checkpoint = CHECKPOINT_AKUJI 
  444. 		delay(1.0) 
  445.  
  446. 	end -- ends CHECKPOINT_START 
  447.  
  448.  
  449. 	-- Stage 2, fight Akuji 
  450. 	if ( rn10_checkpoint == CHECKPOINT_AKUJI ) then 
  451.  
  452. 		-- Fight Akuji 
  453. 		rn10_akuji() 
  454.  
  455. 		-- Player(s) win. Yay! 
  456. 		rn10_complete() 
  457.  
  458. 	end 
  459. end 
  460.  
  461. function rn10_initialize(checkpoint) 
  462.  
  463. 	mission_start_fade_out(0.0) 
  464.  
  465. 	rn10_initialize_common() 
  466.  
  467. 	rn10_initialize_checkpoint(checkpoint) 
  468.  
  469. 	mission_start_fade_in() 
  470.  
  471. end 
  472.  
  473. -- Initialization code shared by all checkpoints. 
  474. function rn10_initialize_common() 
  475.  
  476. 	-- Start trigger is hit...the activate button was hit 
  477. 	set_mission_author("Phillip Alexander") 
  478.  
  479. 	if (coop_is_active()) then 
  480. 		IN_COOP	= true 
  481. 	end 
  482.  
  483. 	-- Start persona overrides 
  484. 	persona_override_group_start(RN10_RONIN_PERSONAS,POT_SITUATIONS[POT_ATTACK], "RO10_ATTACK") 
  485. 	persona_override_group_start(RN10_SAINTS_PERSONAS,POT_SITUATIONS[POT_ATTACK], "RO10_DEFEND") 
  486.  
  487. 		 
  488. 	--Set notoriety to level 4 for mission duration 
  489. 	notoriety_set("Ronin", 4) 
  490. 	notoriety_set_min("Ronin", 4) 
  491. 	notoriety_set_max("Ronin", 4) 
  492.  
  493.  
  494. 	rn10_hide_shanties() 
  495.  
  496. end 
  497.  
  498. -- Initialization code specific to the checkpoint. 
  499. function rn10_initialize_checkpoint(checkpoint) 
  500.  
  501. 	if (checkpoint == CHECKPOINT_START) then 
  502.  
  503. 		Rn10_player_defense_objectives_occupied = 
  504. 		{ 
  505. 			[LOCAL_PLAYER]		= {}, 
  506. 			[REMOTE_PLAYER]	= {}, 
  507. 		} 
  508. 		Rn10_player_defense_objectives_occupied_at_checkpoint = 
  509. 		{ 
  510. 			[LOCAL_PLAYER]		= {}, 
  511. 			[REMOTE_PLAYER]	= {}, 
  512. 		} 
  513.  
  514. 		teleport_coop(NAVPOINT_LOCAL_PLAYER_START, NAVPOINT_REMOTE_PLAYER_START) 
  515. 	 
  516. 		--Prepare triggers that will activate the defense objectives 
  517. 		for i, defense_objective in pairs(DEFENSE_OBJECTIVES) do 
  518. 			trigger_enable(defense_objective["trigger"], true) 
  519. 			on_trigger("rn10_defense_objective_trigger_enter", defense_objective["trigger"]) 
  520. 			on_trigger_exit("rn10_defense_objective_trigger_exit", defense_objective["trigger"])		 
  521. 		end 
  522.  
  523. 	end 
  524.  
  525. 	if (checkpoint == CHECKPOINT_FIRST_PILLAR) then 
  526. 		for trigger, occupied in pairs(Rn10_player_defense_objectives_occupied_at_checkpoint[LOCAL_PLAYER]) do 
  527. 			Rn10_player_defense_objectives_occupied[LOCAL_PLAYER][trigger] = occupied 
  528. 		end 
  529. 		for trigger, occupied in pairs(Rn10_player_defense_objectives_occupied_at_checkpoint[REMOTE_PLAYER]) do 
  530. 			Rn10_player_defense_objectives_occupied[REMOTE_PLAYER][trigger] = occupied 
  531. 		end 
  532. 		trigger_enable(DEFENSE_OBJECTIVES[2]["trigger"], true) 
  533. 		on_trigger("rn10_defense_objective_trigger_enter", DEFENSE_OBJECTIVES[2]["trigger"]) 
  534. 		on_trigger_exit("rn10_defense_objective_trigger_exit", DEFENSE_OBJECTIVES[2]["trigger"]) 
  535. 	end 
  536.  
  537. 	if ( (checkpoint == CHECKPOINT_START) or (checkpoint == CHECKPOINT_FIRST_PILLAR) ) then 
  538.  
  539. 		-- Start the thread that spawns Ronin to attack active defense objectives 
  540. 		thread_new("rn10_ronin_attack_defense_objectives") 
  541.  
  542. 		-- Setup the triggers associated w/ each spawn location so that we can spawn Ronin out-of-sight. 
  543. 		for i, spawn_location in pairs(SPAWN_LOCATIONS) do 
  544.  
  545. 			Num_players_in_spawn_locations[i]	= 0				 
  546. 			for j, trigger in pairs(spawn_location["triggers"]) do 
  547. 				 
  548. 				-- Remember which spawn location this trigger is associated with. 
  549. 				Map_trigger_to_spawn_location_index[trigger] = i 
  550. 				trigger_enable(trigger, true) 
  551. 				on_trigger("rn10_spawn_location_trigger_enter", trigger) 
  552. 				on_trigger_exit("rn10_spawn_location_trigger_exit", trigger) 
  553. 			end 
  554.  
  555. 		end 
  556.  
  557. 		thread_new("rn10_respawning_battles") 
  558. 		--thread_new("rn10_setup_battle", GROUP_CHAOS_RONIN_1, GROUP_CHAOS_SAINTS_1, MEMBERS_GROUP_CHAOS_RONIN_1, MEMBERS_GROUP_CHAOS_SAINTS_1) 
  559. 		-- Wait for some dudes to be spawned 
  560. 		while(Battle_living == 0) do 
  561. 			thread_yield() 
  562. 		end 
  563.  
  564. 	end 
  565.  
  566. end 
  567.  
  568. -- Stage 1 functions 
  569.  
  570. function rn10_hide_shanties() 
  571. 	for i=1, 13, 1 do 
  572. 		mesh_mover_hide("rn10_Shanty" .. i) 
  573. 	end 
  574. end 
  575.  
  576. function rn10_show_shanties() 
  577. 	for i=1, 13, 1 do 
  578. 		mesh_mover_show("rn10_Shanty" .. i) 
  579. 	end 
  580. end 
  581.  
  582. -- Defend an objective 
  583. function rn10_defend_objective(objective_index) 
  584. 	 
  585. 	marker_add_trigger(DEFENSE_OBJECTIVES[objective_index]["trigger"],MINIMAP_ICON_LOCATION,"",SYNC_ALL) 
  586. 	mission_waypoint_add(DEFENSE_OBJECTIVES[objective_index]["trigger"], SYNC_ALL) 
  587.  
  588. 	if (objective_index == 1) then 
  589. 		mission_help_table(HELPTEXT_PROMPT_MISSION_START) 
  590. 	else 
  591. 		mission_help_table(HELPTEXT_PROMPT_NEXT_DEFENSE) 
  592. 	end 
  593.  
  594. 	-- Wait for a player to enter the trigger area 
  595. 	local player_present = false 
  596. 	while( not player_present) do 
  597. 		player_present = Rn10_player_defense_objectives_occupied[LOCAL_PLAYER][objective_index] 
  598. 		player_present = player_present or Rn10_player_defense_objectives_occupied[REMOTE_PLAYER][objective_index] 
  599. 		thread_yield() 
  600. 	end 
  601.  
  602. 	marker_remove_trigger(DEFENSE_OBJECTIVES[objective_index]["trigger"], SYNC_ALL) 
  603. 	mission_waypoint_remove(SYNC_ALL) 
  604.  
  605. 	-- Begin the defense 
  606. 	rn10_begin_defense_objective(LOCAL_PLAYER, objective_index) 
  607. 	if(IN_COOP) then 
  608. 		rn10_begin_defense_objective(REMOTE_PLAYER, objective_index) 
  609. 	end 
  610.  
  611. 	-- Wait for the players to successfully defend the objective 
  612. 	while (not Defense_objective_completed[objective_index]) do 
  613. 		thread_yield() 
  614. 	end 
  615. end 
  616.  
  617. -- A player exited a defense objective 
  618. function rn10_defense_objective_trigger_exit(player, trigger) 
  619.  
  620. 	-- determine the index of the defense objective that we're dealing with 
  621. 	local defense_objective_index = 0 
  622. 	for i,defense_objective in pairs(DEFENSE_OBJECTIVES) do 
  623. 		if (defense_objective["trigger"] == trigger) then 
  624. 			defense_objective_index = i 
  625. 			break 
  626. 		end 
  627. 	end 
  628.  
  629. 	-- Remember that the player exited this trigger 
  630. 	Rn10_player_defense_objectives_occupied[player][defense_objective_index] = nil 
  631. end 
  632.  
  633. -- A player entered a defense objective 
  634. function rn10_defense_objective_trigger_enter(player, trigger) 
  635.  
  636. 	-- determine the index of the defense objective that we're dealing with 
  637. 	local defense_objective_index = 0 
  638. 	for i,defense_objective in pairs(DEFENSE_OBJECTIVES) do 
  639. 		if (defense_objective["trigger"] == trigger) then 
  640. 			defense_objective_index = i 
  641. 			break 
  642. 		end 
  643. 	end 
  644.  
  645. 	-- Remember that the player entered this trigger 
  646. 	Rn10_player_defense_objectives_occupied[player][defense_objective_index] = true 
  647.  
  648. end 
  649.  
  650. -- Called when a player starts a defense objective _or_ joins one already in progress. 
  651. function rn10_begin_defense_objective(player, defense_objective_index) 
  652.  
  653. 	Player_active_defense_objective[player] = defense_objective_index 
  654. 	 
  655. 	local player_sync = PLAYER_SYNC[player] 
  656.  
  657. 	-- Add defend icons to structural weak points 
  658. 	for i, ai_target in DEFENSE_OBJECTIVES[defense_objective_index]["ai targets"] do 
  659. 		 
  660.  
  661. 		trigger_enable(ai_target, true) 
  662. 		marker_add_trigger(	ai_target,  
  663. 									MINIMAP_ICON_PROTECT_ACQUIRE,  
  664. 									INGAME_EFFECT_VEHICLE_LOCATION, 
  665. 									player_sync) 		 
  666. 	end 
  667.  
  668. 	-- Player(s) must defend the pillar for a set amount of time. 
  669. 	mission_help_table(HELPTEXT_PROMPT_PROTECT_SUPPORTS, "", "", player_sync) 
  670. 	hud_timer_set(0, rn10_get_parameter_value("PILLAR_DEFEND_TIME_S")*1000, 
  671. 							"rn10_pillar_defended_" .. defense_objective_index) 
  672. 	 
  673. 	-- Display the Pillar's health 
  674. 	hud_bar_on(0, "Health", HELPTEXT_HUD_PILLAR_HEALTH, Pillar_max_hit_points[defense_objective_index]) 
  675. 	hud_bar_set_range(0, 0, Pillar_max_hit_points[defense_objective_index], SYNC_ALL) 
  676. 	hud_bar_set_value(0, Pillar_max_hit_points[defense_objective_index], SYNC_ALL) 
  677.  
  678. end 
  679.  
  680. -- Defense objective complete wrappers 
  681. function rn10_pillar_defended_1() 
  682. 	rn10_pillar_defended(1) 
  683. end 
  684. function rn10_pillar_defended_2() 
  685. 	rn10_pillar_defended(2) 
  686. end 
  687. function rn10_pillar_defended_3() 
  688. 	rn10_pillar_defended(3) 
  689. end 
  690.  
  691. -- Called when a pillar has been successfully defended (still has health when timer elapses) 
  692. function rn10_pillar_defended(defense_objective_index) 
  693. 	 
  694. 	-- Kill all off the old patrol threads and have the ronin spawned for this mission 
  695. 	-- attack the player(s) 
  696. 	for i, ronin in pairs(MEMBERS_GROUP_RONIN_STAGE_1) do 
  697. 		local patrol_thread = Ronin_patrol_threads[ronin] 
  698. 		if (	(not character_is_dead(ronin)) and  
  699. 				(patrol_thread ~= nil)) then 
  700. 			thread_kill(Ronin_patrol_threads[ronin]) 
  701. 			Ronin_patrol_threads[ronin] = nil 
  702. 			--marker_remove_npc(ronin) 
  703. 			attack(ronin) 
  704. 			npc_hearing_enable(ronin,true) 
  705. 			set_always_sees_player_flag(ronin,true) 
  706. 		end 
  707. 	end 
  708.  
  709. 	-- Eliminate the minimap icons associated with the defense objectives structural weak points. 
  710. 	for i, ai_target in DEFENSE_OBJECTIVES[defense_objective_index]["ai targets"] do 
  711. 		trigger_enable(ai_target, false) 
  712. 		marker_remove_trigger(ai_target) 
  713. 	end 
  714.  
  715. 	-- Clear the hud. 
  716. 	hud_bar_off(0) 
  717. 	hud_timer_stop(0) 
  718. 	--objective_text_clear(0)	 
  719. 	 
  720. 	-- Book keeping. 
  721. 	Defense_objective_completed[defense_objective_index] = true 
  722. 	if (Player_active_defense_objective[LOCAL_PLAYER] == defense_objective_index) then 
  723. 		Player_active_defense_objective[LOCAL_PLAYER] = NO_ACTIVE_DEFENSE_OBJECTIVE 
  724. 	end 
  725. 	if (Player_active_defense_objective[REMOTE_PLAYER] == defense_objective_index) then 
  726. 		Player_active_defense_objective[REMOTE_PLAYER] = NO_ACTIVE_DEFENSE_OBJECTIVE 
  727. 	end 
  728.  
  729. end 
  730.  
  731. -- A player entered a spawn location trigger 
  732. function rn10_spawn_location_trigger_enter(player, trigger) 
  733.  
  734. 	local spawn_location_index = Map_trigger_to_spawn_location_index[trigger] 
  735. 	local num_players = Num_players_in_spawn_locations[spawn_location_index] 
  736. 	Num_players_in_spawn_locations[spawn_location_index] = num_players + 1 
  737. end 
  738.  
  739. -- A player exited a spawn location trigger 
  740. function rn10_spawn_location_trigger_exit(player, trigger) 
  741.  
  742. 	local spawn_location_index = Map_trigger_to_spawn_location_index[trigger] 
  743. 	local num_players = Num_players_in_spawn_locations[spawn_location_index] 
  744. 	Num_players_in_spawn_locations[spawn_location_index] = num_players - 1 
  745. end 
  746.  
  747. -- Spawn waves of ronin to attack ceiling supports that the player(s) is(are) defending 
  748. function rn10_ronin_attack_defense_objectives() 
  749.  
  750. 	-- Start loading the ronin 
  751. 	group_create_hidden(GROUP_RONIN_STAGE_1) 
  752.  
  753. 	-- Set respawn dist threshold very low. 
  754. 	npc_respawn_dist_override(RONIN_RESPAWN_DISTANCE) 
  755. 	 
  756. 	-- All ronin are initially spawnable 
  757. 	for i, ronin in pairs(MEMBERS_GROUP_RONIN_STAGE_1) do 
  758. 		Spawnable_ronin[ronin] = true 
  759. 	end 
  760.  
  761. 	-- Convenience variables for wave size parameters. 
  762. 	local min_wave_size = rn10_get_parameter_value("WAVE_MIN_SIZE") 
  763. 	local max_wave_size = rn10_get_parameter_value("WAVE_MAX_SIZE") 
  764. 	local max_attackers = rn10_get_parameter_value("WAVE_MAX_ATTACKERS") 
  765.  
  766. 	-- Size of the next wave to spawn at each defense objective. 
  767. 	local next_wave_sizes = {} 
  768.  
  769. 	-- Initialize per-objective data 
  770. 	for i, defense_objective in pairs(DEFENSE_OBJECTIVES) do 
  771.  
  772. 		-- Determine the size of the next wave 
  773. 		next_wave_sizes[i] = rand_int(min_wave_size, max_wave_size) 
  774.  
  775. 		-- No Ronin are attacking yet. 
  776. 		Num_living_attackers[i] = 0 
  777.  
  778. 		-- All Pillars at full health 
  779. 		Pillar_max_hit_points[i] = rn10_get_parameter_value("PILLAR_MAX_HIT_POINTS") 
  780.  
  781. 	end 
  782.  
  783. 	-- Wait for all Ronin to load. 
  784. 	while (not group_is_loaded(GROUP_RONIN_STAGE_1)) do 
  785. 		thread_yield() 
  786. 	end 
  787.  
  788. 	-- Continuously check the number of Ronin attacking each location, spawn more if needed. 
  789. 	while(true) do 
  790.  
  791. 		-- Examine each objective 
  792. 		for i, defense_objective in pairs(DEFENSE_OBJECTIVES) do 
  793.  
  794. 			-- Only spawn ronin if players are actively defending this objecive 
  795. 			if (	Player_active_defense_objective[LOCAL_PLAYER] == i or 
  796. 					Player_active_defense_objective[REMOTE_PLAYER] == i) then 
  797. 							 
  798. 				-- Spawn the next wave if there is room. 
  799. 				if (next_wave_sizes[i] + Num_living_attackers[i] <= max_attackers) then 
  800.  
  801. 					local num_ronin_spawned = rn10_send_wave(i, next_wave_sizes[i]) 
  802. 					Num_living_attackers[i] = Num_living_attackers[i] + num_ronin_spawned 
  803. 					next_wave_sizes[i] = rand_int(min_wave_size, max_wave_size) 
  804.  
  805. 				end -- Spawn the next wave if we have room. 
  806. 			 
  807. 			end -- end Only spawn ronin if players are actively defending this objecive 
  808.  
  809. 		end -- end Examine each objective 
  810.  
  811. 		thread_yield() 
  812.  
  813. 	end -- end while(true) 
  814.  
  815. end 
  816.  
  817. -- Send a wave of ronin to attack a structural weakness 
  818. -- 
  819. -- defense_objective_index: index of defense objective to attack. 
  820. --  
  821. -- wave_size: number of attackers to send 
  822. -- 
  823. -- returns number of attackers successfully spawned 
  824. function rn10_send_wave(defense_objective_index, wave_size) 
  825.  
  826. 	local num_ronin_spawned = 0 
  827.  
  828. 	-- For each Ronin to be spawned 
  829. 	for i=1, wave_size, 1 do 
  830.  
  831. 		-- Get a ronin to spawn and a safe spawning location.  
  832. 		local ronin = rn10_get_spawnable_ronin() 
  833. 		local spawn_navpoint, spawn_location_index = rn10_get_safe_spawn(defense_objective_index) 
  834.  
  835. 		-- If any of these aren't found, return # ronin already spawned. 
  836. 		if ( (spawn_navpoint == nil) or (spawn_location_index == nil) or (ronin == nil)) then 
  837. 			return num_ronin_spawned 
  838. 		end 
  839.  
  840. 		-- We're gonna spawn this guy, do some book keeping. 
  841. 		num_ronin_spawned = num_ronin_spawned + 1 
  842. 		Spawnable_ronin[ronin] = false 
  843. 		Ronin_defense_objective_targeted[ronin] = defense_objective_index 
  844. 		Spawn_area_exits[ronin] = SPAWN_LOCATIONS[spawn_location_index]["exit"] 
  845.  
  846. 		-- Teleport to the spawn navpoint 
  847. 		teleport(ronin, spawn_navpoint) 
  848.  
  849. 		-- Tell the ronin to respawn, override default respawn time 
  850. 		npc_respawn_after_death(ronin, true) 
  851. 		npc_respawn_after_death_time_override(ronin, RONIN_RESPAWN_TIME_MS, true) 
  852. 		on_respawn("rn10_respawn_ronin",ronin) 
  853. 		on_death("rn10_cleanup_ronin",ronin) 
  854.  
  855. 		-- Show the ronin and start its patrol 
  856. 		character_show(ronin) 
  857. 		--marker_add_npc(ronin, MINIMAP_ICON_KILL, INGAME_EFFECT_KILL, SYNC_ALL)  
  858. 		Ronin_patrol_threads[ronin] = thread_new("rn10_ronin_patrol_" .. defense_objective_index, ronin) 
  859.  
  860. 		-- Delay a little bit, gives the ronin time to leave the spawn area and keeps congestion down. 
  861. 		delay(.2,.5) 
  862.  
  863. 	end 
  864.  
  865. 	-- Return num of ronin spawned 
  866. 	return num_ronin_spawned 
  867.  
  868. end 
  869.  
  870. -- Returns a spawnable ronin if one is available, nil else. 
  871. function rn10_get_spawnable_ronin() 
  872.  
  873. 	for i, ronin in pairs(MEMBERS_GROUP_RONIN_STAGE_1) do 
  874. 		if (Spawnable_ronin[ronin] == true) then 
  875. 			return ronin 
  876. 		end 
  877. 	end 
  878.  
  879. 	return nil 
  880.  
  881. end 
  882.  
  883. -- Wrappers for patrols at different defense objectives 
  884. function rn10_ronin_patrol_1(ronin) 
  885. 	rn10_ronin_patrol(ronin, 1) 
  886. end 
  887. function rn10_ronin_patrol_2(ronin) 
  888. 	rn10_ronin_patrol(ronin, 2) 
  889. end 
  890. function rn10_ronin_patrol_3(ronin) 
  891. 	rn10_ronin_patrol(ronin, 3) 
  892. end 
  893.  
  894. function rn10_ronin_patrol(ronin, defense_objective_index) 
  895.  
  896. 	local has_rpg_launcher = false 
  897. 	local moved_to_entrance = false 
  898.  
  899. 	-- Maybe equip w/ an Rpg launcher 
  900. 	local rpg_roll = rand_float(0.0,1.0) 
  901. 	if (rpg_roll < rn10_get_parameter_value("WAVE_RPG_CHANCE")) then 
  902. 		inv_item_add("rpg_launcher", 0, ronin)  
  903. 		inv_item_equip("rpg_launcher", ronin) 
  904. 		has_rpg_launcher = true	 
  905. 	end 
  906.  
  907. 	-- DEBUG 
  908. 	if (Debug_ronin == "") then 
  909. 		Debug_ronin = ronin 
  910. 	end 
  911.  
  912. 	-- attack player on sight 
  913. 	set_attack_player_flag(ronin,true) 
  914.  
  915. 	-- disable hearing 
  916. 	npc_hearing_enable(ronin,false) 
  917. 	 
  918. 	-- how long to spend attacking player before checking for a new target 
  919. 	local min_attack_time = 4.0 
  920. 	local max_attack_time = 10.0 
  921.  
  922. 	-- objective target being attacked, position from which it is attacked 
  923. 	local objective_target = "" 
  924. 	local attack_position = "" 
  925.  
  926. 	while(not character_is_dead(ronin)) do 
  927.  
  928. 		-- See if there is a player that should be attacked. 
  929. 		local player_to_attack = rn10_get_player_to_attack(ronin) 
  930. 		--local player_to_attack = nil 
  931.  
  932. 		-- If so, then attack the player. 
  933. 		if (player_to_attack ~= nil) then 
  934.  
  935. 			-- Do some book keeping. 
  936. 			if (objective_target ~= "") then 
  937. 				Target_attack_position_occupants[attack_position] = nil 
  938. 				objective_target = "" 
  939. 				attack_position = "" 
  940. 			end 
  941.  
  942. 			-- Attack the player for a bit. The always sees player flag ensures that the  
  943. 			-- player can't get everyone's attention and go hide in a corner. 
  944. 			local attack_time = rand_float(min_attack_time, max_attack_time) 
  945. 			set_always_sees_player_flag(ronin,true) 
  946. 			attack(ronin, player_to_attack, false) 
  947. 			delay(min_attack_time, max_attack_time) 
  948.  
  949. 			-- Clear the flag so that the Ronin might go back to attacking the pillar.		 
  950. 			set_always_sees_player_flag(ronin,false) 
  951.  
  952. 		-- attack objective 
  953. 		else 
  954.  
  955. 			-- If we already have a target, then attack it. 
  956. 			if (objective_target ~= "") then 
  957.  
  958. 				-- move to the attack position... don't retry on failure, can shoot as we go 
  959. 				move_to(ronin,attack_position,2,false, true) 
  960.  
  961.  
  962. 				-- Check again, objective may have completed while pathfinding 
  963. 				if (objective_target ~= "") then 
  964. 					-- If the Ronin doesn't have an rpg launcher, then they might use a grenade or a molotov. 
  965. 					local thrown_weapon = "" 
  966. 					if (not has_rpg_launcher) then 
  967.  
  968. 						-- Maybe select a thrown weapon 
  969. 						local grenade_roll = rand_float(0.0,1.0) 
  970. 						if (grenade_roll < rn10_get_parameter_value("WAVE_GRENADE_CHANCE")) then 
  971. 							thrown_weapon = "grenade"		 
  972. 						else 
  973. 							local molotov_roll = rand_float(0.0,1.0) 
  974. 							if (molotov_roll < rn10_get_parameter_value("WAVE_MOLOTOV_CHANCE")) then 
  975. 								thrown_weapon = "molotov" 
  976. 							end 
  977. 						end 
  978.  
  979. 					end 
  980.  
  981. 					-- I can't really detect when a shot has hit the pillar, so make sure 
  982. 					-- that the Ronin don't miss it. 
  983. 					set_perfect_aim(ronin,true) 
  984. 					if (thrown_weapon ~= "") then 
  985. 					 
  986. 						inv_item_add(thrown_weapon, 1, ronin) 
  987. 						inv_item_equip(thrown_weapon, ronin) 
  988. 						force_throw(ronin, objective_target) 
  989. 						npc_unholster_best_weapon(ronin) 
  990.  
  991. 					-- Didn't throw an explosive, better shoot 
  992. 					else 
  993.  
  994. 						local shots_to_fire = 1 
  995.  
  996. 						if (not has_rpg_launcher) then 
  997. 							shots_to_fire = rand_int(1,3) 
  998. 						end 
  999. 						for i=1, shots_to_fire, 1 do 
  1000. 							force_fire(ronin, objective_target, true) 
  1001. 						end 
  1002. 					end 
  1003. 					set_perfect_aim(ronin,false) 
  1004.  
  1005. 					-- Damage the pillar 
  1006. 					local damage_dealt = 0.0 
  1007. 					if (has_rpg_launcher) then 
  1008. 						damage_dealt = rand_int(90,180) 
  1009. 					elseif (thrown_weapon == "grenade") then 
  1010. 						damage_dealt = rand_int(60,120) 
  1011. 					elseif (thrown_weapon == "molotov") then 
  1012. 						damage_dealt = rand_int(40,80) 
  1013. 					else  
  1014. 						damage_dealt = rand_int (35,50) 
  1015. 					end 
  1016.  
  1017. 					Pillar_max_hit_points[defense_objective_index] =  
  1018. 						Pillar_max_hit_points[defense_objective_index] - damage_dealt 
  1019. 					if(Pillar_max_hit_points[defense_objective_index] <= 0) then 
  1020. 						Pillar_max_hit_points[defense_objective_index] = 0 
  1021. 					end 
  1022. 					hud_bar_set_value(0, Pillar_max_hit_points[defense_objective_index], SYNC_ALL ) 
  1023.  
  1024. 					if (Pillar_max_hit_points[defense_objective_index] == 0) then 
  1025. 						rn10_failure_support_collapse() 
  1026. 					end 
  1027.  
  1028. 					local all_shots_fired_delay = rand_float (0.4,1.0) 
  1029. 					if (thrown_weapon ~= "" or has_rpg_launcher) then 
  1030. 						all_shots_fired_delay = all_shots_fired_delay * 5.0 
  1031. 					end 
  1032. 					delay(all_shots_fired_delay) 
  1033. 				end 
  1034.  
  1035. 			-- else, if we haven't moved to the spawn location's exit, do that first. 
  1036. 			-- move to the spawn location's exit ... don't retry on failure, can shoot as we go 
  1037. 			elseif (not moved_to_entrance) then 
  1038. 				move_to(ronin,Spawn_area_exits[ronin],2,true, true) 
  1039. 				moved_to_entrance = true 
  1040.  
  1041. 			-- Find a target and move to a non-occupied position from which to attack it. 
  1042. 			else 
  1043.  
  1044. 				-- Find the closest target 
  1045. 				local closest_target = "" 
  1046. 				local closest_dist	= 0 
  1047. 				for i, ai_target in pairs(DEFENSE_OBJECTIVES[defense_objective_index]["ai targets"]) do 
  1048. 					local cur_dist = get_dist(ronin, ai_target) 
  1049. 					if (cur_dist < closest_dist or closest_target == "") then 
  1050. 						closest_dist = cur_dist 
  1051. 						closest_target = ai_target 
  1052. 					end 
  1053. 				end 
  1054. 				objective_target = closest_target 
  1055.  
  1056. 				-- Find the closest unoccupied attack position for that target 
  1057. 				local closest_attack_position = "" 
  1058. 				closest_dist = 0 
  1059. 				for i, attack_position in pairs(TARGET_ATTACK_POSITIONS[objective_target]) do 
  1060. 					if (Target_attack_position_occupants[attack_position] == nil) then 
  1061. 						local cur_dist = get_dist(ronin, attack_position) 
  1062. 						if (cur_dist < closest_dist or closest_attack_position == "") then 
  1063. 							closest_dist = cur_dist 
  1064. 							closest_attack_position = attack_position 
  1065. 						end					 
  1066. 					end 
  1067. 				end 
  1068. 				attack_position = closest_attack_position 
  1069.  
  1070. 				-- Mark the position as occupied even though we're not there yet. We don't want 
  1071. 				-- everyone trying to get into the same spot. 
  1072. 				Target_attack_position_occupants[attack_position] = ronin 
  1073.  
  1074. 				-- move to the attack position... don't retry on failure, can shoot as we go 
  1075. 				move_to(ronin,attack_position,2,false, true) 
  1076.  
  1077. 			end 
  1078.  
  1079. 		end		 
  1080.  
  1081. 		thread_yield() 
  1082.  
  1083. 	end 
  1084.  
  1085. end 
  1086.  
  1087. -- Gets the next player to attack (returns nil if should attack objective)  
  1088. function rn10_get_player_to_attack(ronin) 
  1089.  
  1090. 	-- TODO... maybe prefer attacking player working on this objective? 
  1091.  
  1092. 	-- These two variables define a range w/in which the player may be attacked. If closer, 
  1093. 	-- he'll definitely be attacked. If further, he might be. Combat is _not_ disabled, so the 
  1094. 	-- Ronin might attack if the player is spotted form further away. 
  1095. 	local always_attack_player_dist = 3.0 
  1096. 	local ignore_player_dist = 8.0 
  1097.  
  1098. 	-- Always attack the objective if the player is too far away. Always attack player if they are very close. 
  1099. 	local dist, closest_player = get_dist_closest_player_to_object(ronin) 
  1100. 	if (dist > ignore_player_dist) then 
  1101. 		return nil 
  1102. 	elseif (dist < always_attack_player_dist) then 
  1103. 		return closest_player 
  1104.  
  1105. 	-- Otherwise, scale the chance of attacking the player depending on the distance between them 
  1106. 	else 
  1107.  
  1108. 		-- Convert distance to player to a probability that they will be attacked 
  1109. 		local attack_chance = dist - always_attack_player_dist 
  1110. 		attack_chance = dist / (ignore_player_dist - always_attack_player_dist) 
  1111.  
  1112. 		local roll = rand_float(0.0,1.0) 
  1113. 		if ( roll < attack_chance) then 
  1114. 			return closest_player 
  1115. 		else 
  1116. 			return nil 
  1117. 		end 
  1118.  
  1119. 	end -- ends if (dist > ignore_player_dist) 
  1120.  
  1121. end 
  1122.  
  1123. -- TODO: have the following function use the preferred starting location for the initial spawns. 
  1124.  
  1125. -- Find a navpoint at which we can safely (without popping) spawn a Ronin. 
  1126. -- 
  1127. -- defense_objective_index: the index of the defense objective that the spawned ronin will attack 
  1128. -- 
  1129. -- returns spawn_navpoint, spawn_location_index 
  1130. --  
  1131. --		spawn_navpoint: navpoint at which to spawn 
  1132. --		spawn_location_index: index of the spawn location that contains spawn_navpoint 
  1133. function rn10_get_safe_spawn(defense_objective_index) 
  1134.  
  1135. 	local spawn_location_index_to_return = nil 
  1136. 	local navpoint_to_return = nil 
  1137.  
  1138. 	-- Indices of spawn locations that are currently safe 
  1139. 	local safe_spawn_location_indices = {} 
  1140. 	local num_safe_spawn_locations = 0; 
  1141.  
  1142. 	-- Add spawn locations to the list if they are near the objective and not occupied by a player. 
  1143. 	for i, spawn_location_index in pairs(DEFENSE_OBJECTIVES[defense_objective_index]["spawn locations"]) do 
  1144.  
  1145. 		if (Num_players_in_spawn_locations[spawn_location_index] == 0) then 
  1146.  
  1147. 			num_safe_spawn_locations = num_safe_spawn_locations + 1 
  1148. 			safe_spawn_location_indices[num_safe_spawn_locations] = spawn_location_index			 
  1149.  
  1150. 		end 
  1151.  
  1152. 	end 
  1153.  
  1154. 	-- Can't do anything if there are no safe spawn areas. 
  1155. 	if (num_safe_spawn_locations == 0) then 
  1156. 		return navpoint_to_return, spawn_location_index_to_return 
  1157. 	end 
  1158.  
  1159. 	-- Select a random safe spawn area 
  1160. 	spawn_location_index_to_return = safe_spawn_location_indices[rand_int(1,num_safe_spawn_locations)] 
  1161.  
  1162. 	-- Select a navpoint 
  1163. 	local next_navpoint_index = Spawn_locations_next_navpoint_index[spawn_location_index_to_return] 
  1164. 	if (next_navpoint_index == nil) then 
  1165. 		next_navpoint_index = 1 
  1166. 	end 
  1167. 	navpoint_to_return = SPAWN_LOCATIONS[spawn_location_index_to_return]["navpoints"][next_navpoint_index] 
  1168.  
  1169. 	-- Increment next navpoint index for this spawn location 
  1170. 	next_navpoint_index = next_navpoint_index + 1 
  1171. 	if (	next_navpoint_index >  
  1172. 			sizeof_table(SPAWN_LOCATIONS[spawn_location_index_to_return]["navpoints"])) then 
  1173.  
  1174. 			next_navpoint_index = 1 
  1175. 	end 
  1176. 	Spawn_locations_next_navpoint_index[spawn_location_index_to_return] = next_navpoint_index 
  1177.  
  1178. 	return navpoint_to_return, spawn_location_index_to_return 
  1179.  
  1180. end 
  1181.  
  1182. -- Handle the death of an attacking Ronin. 
  1183. function rn10_cleanup_ronin(ronin) 
  1184. 	--marker_remove_npc(ronin) 
  1185. 	if (Ronin_patrol_threads[ronin] ~= nil) then 
  1186. 		thread_kill(Ronin_patrol_threads[ronin]) 
  1187. 		Ronin_patrol_threads[ronin] = nil 
  1188. 	end 
  1189. end 
  1190.  
  1191. -- Handle the respawning of an attacking Ronin. 
  1192. function rn10_respawn_ronin(ronin) 
  1193.  
  1194. 	-- keep the ronin hidden for now 
  1195. 	character_hide(ronin) 
  1196.  
  1197. 	-- Make sure that we don't have this ronin listed as occupying an attack position 
  1198. 	for attack_position, occupant in pairs(Target_attack_position_occupants) do 
  1199. 		if (occupant == ronin) then 
  1200. 			Target_attack_position_occupants[attack_position] = nil 
  1201. 		end 
  1202. 	end 
  1203.  
  1204. 	-- Update the count of living ronin 
  1205. 	local defense_objective_index = Ronin_defense_objective_targeted[ronin] 
  1206. 	Num_living_attackers[defense_objective_index] = Num_living_attackers[defense_objective_index] - 1 
  1207.  
  1208. 	-- Make this ronin available for spawning again 
  1209. 	delay(.5) 
  1210. 	Ronin_defense_objective_targeted[ronin] = nil 
  1211. 	Spawnable_ronin[ronin] = true 
  1212.  
  1213. end 
  1214.  
  1215. -- Stage 2 functions 
  1216.  
  1217. function rn10_akuji() 
  1218.  
  1219. 	group_create_hidden(GROUP_RONIN_STAGE_2) 
  1220.  
  1221. 	--disable Chainsaws for Boss Battle 
  1222. 	if inv_has_item("chainsaw", LOCAL_PLAYER) then 
  1223. 		inv_weapon_disable_slot(WEAPON_SLOT_MELEE) 
  1224. 	end 
  1225. 	 
  1226. 	-- Setup Akuji 
  1227. 	 
  1228. 		--Override akuji's persona lines 
  1229. 		persona_override_character_start(CHARACTER_AKUJI, POT_SITUATIONS[POT_ATTACK],"KAZUO_RON10_ATTACK") 
  1230. 		persona_override_character_start(CHARACTER_AKUJI, POT_SITUATIONS[POT_TAKE_DAMAGE],"KAZUO_RON10_TAKEDAM") 
  1231.  
  1232. 		-- During faux boss battle, handle Akuji taking damage in script 
  1233. 		turn_invulnerable(CHARACTER_AKUJI, false) 
  1234. 		on_take_damage("rn10_akuji_damaged",CHARACTER_AKUJI) 
  1235.  
  1236. 		-- Set Akuji's health and display his health bar. 
  1237. 		set_max_hit_points( CHARACTER_AKUJI, rn10_get_parameter_value("AKUJI_HIT_POINTS") ) 
  1238. 		damage_indicator_on(0,CHARACTER_AKUJI,0.0, HELPTEXT_HUD_AKUJI_HEALTH) 
  1239.  
  1240. 		-- Not using boss ai for now.	 
  1241. 		--npc_set_boss_type(CHARACTER_AKUJI, AI_BOSS_AKUJI) 
  1242. 		character_set_cannot_be_grabbed(CHARACTER_AKUJI, true) 
  1243. 		set_cant_flee_flag(CHARACTER_AKUJI, true) 
  1244. 		character_prevent_flinching(CHARACTER_AKUJI, true) 
  1245.  
  1246. 		-- Akuji attacks everything in sight 
  1247. 		set_attack_peds_flag(CHARACTER_AKUJI, true) 
  1248. 		set_always_sees_player_flag(CHARACTER_AKUJI,true) 
  1249. 		attack(CHARACTER_AKUJI) 
  1250.  
  1251. 		-- And he uses a sword. 
  1252. 		if (AKUJI_USE_SWORD) then 
  1253. 			set_blitz_flag(CHARACTER_AKUJI, true) 
  1254. 			inv_item_remove_all(CHARACTER_AKUJI) 
  1255. 			inv_item_add("samurai_sword", 1, CHARACTER_AKUJI)  
  1256. 			inv_item_equip("samurai_sword",CHARACTER_AKUJI) 
  1257. 			npc_weapon_pickup_override(CHARACTER_AKUJI,false) 
  1258. 		end 
  1259.  
  1260. 		vehicle_enter_teleport(CHARACTER_AKUJI,"rn10_$v000",0) 
  1261. 	 
  1262. 	-- Setup Akuji's lieutenants 
  1263. 	 
  1264. 		set_max_hit_points( "rn10_$c020", rn10_get_parameter_value("AKUJI_LTNT_HIT_POINTS") ) 
  1265. 		set_max_hit_points( "rn10_$c021", rn10_get_parameter_value("AKUJI_LTNT_HIT_POINTS") ) 
  1266. 		set_max_hit_points( "rn10_$c022", rn10_get_parameter_value("AKUJI_LTNT_HIT_POINTS") ) 
  1267. 		vehicle_enter_teleport("rn10_$c020","rn10_$v001",0) 
  1268. 		vehicle_enter_teleport("rn10_$c021","rn10_$v002",0) 
  1269. 		vehicle_enter_teleport("rn10_$c022","rn10_$v003",0) 
  1270.  
  1271. 	-- Wait for loading to finish, then have the Ronin attack and make them visible 
  1272.  
  1273. 		while (not group_is_loaded(GROUP_RONIN_STAGE_2) ) do 
  1274. 			thread_yield() 
  1275. 		end 
  1276. 	 
  1277. 		group_show(GROUP_RONIN_STAGE_2) 
  1278.  
  1279. 		-- Returns a random player 
  1280. 		local function rn01_player_to_chase() 
  1281. 			local player = LOCAL_PLAYER 
  1282. 			if (IN_COOP) then 
  1283. 				if (rand_int(1,2) == 2) then 
  1284. 					player = REMOTE_PLAYER 
  1285. 				end 
  1286. 			end 
  1287. 			return player 
  1288. 		end 
  1289.  
  1290. 		vehicle_chase("rn10_$v000", rn01_player_to_chase(), true, true) 
  1291. 		vehicle_chase("rn10_$v001", rn01_player_to_chase(), true, true) 
  1292. 		vehicle_chase("rn10_$v002", rn01_player_to_chase(), true, true) 
  1293. 		vehicle_chase("rn10_$v003", rn01_player_to_chase(), true, true) 
  1294.  
  1295. 	-- Tell the player(s) to kill Akuji and add the kill icon/effect 
  1296. 	mission_help_table(HELPTEXT_PROMPT_KILL_AKUJI) 
  1297. 	marker_add_npc(CHARACTER_AKUJI, MINIMAP_ICON_KILL, INGAME_EFFECT_KILL, SYNC_ALL)  
  1298.  
  1299. 	-- Wait for Akuji to run away. 
  1300. 	while( not Akuji_fleeing) do 
  1301. 		thread_yield() 
  1302. 	end	 
  1303.  
  1304. end 
  1305.  
  1306. -- Handle Akuji taking damage. 
  1307. function rn10_akuji_damaged(akuji, attacker, damage_percent) 
  1308.  
  1309. 	local new_hit_points = damage_percent * get_max_hit_points(akuji) 
  1310.  
  1311. 	-- Make sure Akuji always has at least a sliver of health 
  1312. 	if (new_hit_points < 100) then 
  1313. 		new_hit_points = 100 
  1314. 	end 
  1315.  
  1316. 	set_current_hit_points(CHARACTER_AKUJI, new_hit_points) 
  1317.  
  1318. 	if (	damage_percent < rn10_get_parameter_value("AKUJI_FLEE_HEALTH_RATIO") ) then 
  1319. 		character_ragdoll(akuji) 
  1320. 		Akuji_fleeing = true 
  1321. 	end 
  1322.  
  1323. end 
  1324.  
  1325. -- Other functions 
  1326.  
  1327. function rn10_cleanup() 
  1328.  
  1329. 	IN_COOP = coop_is_active() 
  1330.  
  1331. 	hud_timer_stop(0) 
  1332.  
  1333. 	local function cleanup_battle_group(group_members) 
  1334. 		for i, npc in pairs(group_members) do 
  1335. 			if (character_exists(npc) and (not character_is_dead(npc))) then 
  1336. 				on_death("", npc) 
  1337. 			end 
  1338. 		end 
  1339. 	end 
  1340.  
  1341. 	cleanup_battle_group(MEMBERS_GROUP_CHAOS_RONIN_1, MEMBERS_GROUP_CHAOS_SAINTS_1, MEMBERS_GROUP_CHAOS_RONIN_2, MEMBERS_GROUP_CHAOS_SAINTS_2) 
  1342. 	 
  1343. 	--re-enable all weapons 
  1344. 	inv_weapon_enable_or_disable_all_slots(true, SYNC_ALL) 
  1345.  
  1346. 	-- Don't worry about showing the shanties... it was causing them to fall through the world for some reason. 
  1347. 	--rn10_show_shanties() 
  1348.  
  1349. 	-- End persona overrides 
  1350. 	persona_override_group_stop(RONIN_PERSONAS,POT_SITUATIONS[POT_ATTACK]) 
  1351.  
  1352. 	-- kill ronin patrol threads 
  1353. 	for i,thread in pairs(Ronin_patrol_threads) do 
  1354. 		if(thread ~= nil) then 
  1355. 			thread_kill(thread) 
  1356. 		end 
  1357. 	end 
  1358.  
  1359. 	-- reset global variables 
  1360.  
  1361. 		-- Reset the respawn distance 
  1362. 		npc_respawn_dist_reset() 
  1363.  
  1364. 	-- reset notoriety 
  1365. 		 
  1366. 	-- remove markers 
  1367. 		 
  1368. 		for i, ronin in pairs(MEMBERS_GROUP_RONIN_STAGE_1) do 
  1369. 			--marker_remove_npc(ronin) 
  1370. 			on_respawn("",ronin) 
  1371. 			on_death("",ronin) 
  1372. 		end 
  1373.  
  1374. 	-- remove callbacks 
  1375.  
  1376. 		-- disable all triggers, remove callbacks, remove from map 
  1377. 		for i, trigger in pairs(TABLE_ALL_TRIGGERS) do 
  1378. 			on_trigger("",trigger) 
  1379. 			trigger_enable(trigger,false) 
  1380. 			marker_remove_trigger(trigger) 
  1381. 		end 
  1382. 		for i, defense_objective in pairs(DEFENSE_OBJECTIVES) do 
  1383. 			on_trigger("", defense_objective["trigger"]) 
  1384. 			trigger_enable(defense_objective["trigger"], false) 
  1385. 			marker_remove_trigger(defense_objective["trigger"]) 
  1386. 		end 
  1387. 		for i, spawn_location in pairs(SPAWN_LOCATIONS) do 
  1388.  
  1389. 			for j, trigger in pairs(spawn_location["triggers"]) do 
  1390. 				trigger_enable(trigger, false) 
  1391. 				on_trigger("", trigger) 
  1392. 				on_trigger_exit("", trigger) 
  1393. 				marker_remove_trigger(trigger) 
  1394. 			end 
  1395.  
  1396. 		end 
  1397.  
  1398. 	-- clear the hud 
  1399. 		damage_indicator_off(0) 
  1400. 		hud_bar_off(0) 
  1401. 		--objective_text_clear(0)	 
  1402. end 
  1403.  
  1404. function rn10_success() 
  1405. 	-- Called when the mission has ended with success 
  1406. end 
  1407.  
  1408. function rn10_complete() 
  1409.  
  1410. 	-- End the mission with success 
  1411. 	mission_end_success("rn10", "ro10-02") 
  1412. end 
  1413.  
  1414. -- Get the value of the mission parameter. 
  1415. -- 
  1416. -- parameter	Mission parameter whose value the function should return 
  1417. --	i				If the parameter is a table, then i indexes the entry that should be returned 
  1418. -- 
  1419. -- Returns mission paramater value. 
  1420. function rn10_get_parameter_value(parameter, i) 
  1421.  
  1422. 	local return_val = nil 
  1423.  
  1424. 	-- Check for a coop value: 
  1425. 	if (IN_COOP) then 
  1426. 		if (i) then 
  1427. 			if (rn10_PARAMETERS["COOP_" .. parameter] ~= nil) then 
  1428. 				return_val = rn10_PARAMETERS["COOP_" .. parameter][i] 
  1429. 			end 
  1430. 		else 
  1431. 			return_val = rn10_PARAMETERS["COOP_" .. parameter] 
  1432. 		end 
  1433. 	end 
  1434.  
  1435. 	-- If no coop value was found, then return the standard value. 
  1436. 	if (return_val == nil) then 
  1437. 		if (i) then 
  1438. 			if (rn10_PARAMETERS[parameter] ~= nil) then 
  1439. 				return_val = rn10_PARAMETERS[parameter][i] 
  1440. 			end 
  1441. 		else 
  1442. 			return_val = rn10_PARAMETERS[parameter] 
  1443. 		end 
  1444. 	end 
  1445.  
  1446. 	return return_val 
  1447. end 
  1448.  
  1449.  
  1450. Battle_max_living = 12 
  1451. Battle_living = 0 
  1452. Battle_saints_living = {} 
  1453. Battle_ronin_living = {} 
  1454. Battle_member_to_group = {} 
  1455.  
  1456. function rn10_respawning_battles() 
  1457.  
  1458. 	local rn10_battles =  
  1459. 		{ 
  1460. 			{GROUP_CHAOS_RONIN_1, GROUP_CHAOS_SAINTS_1, MEMBERS_GROUP_CHAOS_RONIN_1, MEMBERS_GROUP_CHAOS_SAINTS_1}, 
  1461. 			{GROUP_CHAOS_RONIN_2, GROUP_CHAOS_SAINTS_2, MEMBERS_GROUP_CHAOS_RONIN_2, MEMBERS_GROUP_CHAOS_SAINTS_2}, 
  1462. 		} 
  1463.  
  1464. 	local function can_start_battle(ronin_group, saints_group, ronin_members, saints_members) 
  1465.  
  1466. 		-- Can't restart the battle if there are already npcs spawned from a previous instance 
  1467. 		if ( Battle_saints_living[saints_group] ~= nil ) then 
  1468. 			if (Battle_saints_living[saints_group] > 0) then 
  1469. 				return false 
  1470. 			end 
  1471. 		end 
  1472. 		if ( Battle_ronin_living[ronin_group] ~= nil ) then 
  1473. 			if ( Battle_ronin_living[ronin_group] > 0) then 
  1474. 				return false 
  1475. 			end 
  1476. 		end 
  1477.  
  1478. 		-- Can't start the battle if too many battle npcs will be created 
  1479. 		local num_ronin = sizeof_table(ronin_members) 
  1480. 		local num_saints = sizeof_table(saints_members) 
  1481. 		if (num_ronin + num_saints + Battle_living > Battle_max_living) then 
  1482. 			return false 
  1483. 		end 
  1484. 	 
  1485. 		-- If the game is faded out, don't need to do fov checks 
  1486. 		if(fade_get_percent() > .99) then 
  1487. 			return true 
  1488. 		end 
  1489. 		-- Can start battle if everyone is outside of fov 
  1490. 		local min_dist = rn10_get_parameter_value("BATTLE_RESPAWN_DIST") 
  1491. 		for i, ronin in pairs(ronin_members) do 
  1492. 			if (rn10_navpoint_in_fov(ronin, 1.5) or (get_dist_closest_player_to_object(ronin) < min_dist)) then 
  1493. 				return false 
  1494. 			end 
  1495. 		end 
  1496. 		for i, saint in pairs(saints_members) do 
  1497. 			if (rn10_navpoint_in_fov(saint, 1.5) or (get_dist_closest_player_to_object(saint) < min_dist)) then 
  1498. 				return false 
  1499. 			end 
  1500. 		end 
  1501. 		return true 
  1502. 	end 
  1503.  
  1504. 	while(true) do 
  1505.  
  1506. 		thread_yield() 
  1507.  
  1508. 		for i, battle in pairs(rn10_battles) do 
  1509.  
  1510. 			if (not group_is_loaded(battle[1])) then 
  1511. 				group_create_hidden(battle[1]) 
  1512. 			end 
  1513. 			if (not group_is_loaded(battle[2])) then 
  1514. 				group_create_hidden(battle[2]) 
  1515. 			end 
  1516.  
  1517. 			if (can_start_battle(battle[1], battle[2], battle[3], battle[4])) then 
  1518. 				thread_new("rn10_setup_battle", battle[1], battle[2], battle[3], battle[4]) 
  1519. 			end 
  1520.  
  1521. 			thread_yield() 
  1522. 		end 
  1523.  
  1524. 	end 
  1525.  
  1526. end 
  1527.  
  1528. function rn10_setup_battle(ronin_group, saints_group, ronin_members, saints_members) 
  1529.  
  1530. 	local num_ronin = sizeof_table(ronin_members) 
  1531. 	local num_saints = sizeof_table(saints_members) 
  1532.  
  1533. 	Battle_saints_living[saints_group] = num_saints 
  1534. 	Battle_ronin_living[ronin_group] = num_ronin 
  1535. 	Battle_living = Battle_living + num_ronin + num_saints 
  1536.  
  1537. 	for i,ronin in pairs(ronin_members) do 
  1538. 		on_death("battle_ronin_killed", ronin) 
  1539. 		Battle_member_to_group[ronin] = ronin_group 
  1540. 	end 
  1541. 	for i,saint in pairs(saints_members) do 
  1542. 		on_death("battle_saint_killed", saint) 
  1543. 		Battle_member_to_group[saint] = saints_group 
  1544. 	end 
  1545.  
  1546. 	group_show(ronin_group) 
  1547. 	group_show(saints_group) 
  1548.  
  1549. 	for i,ronin in pairs(ronin_members) do 
  1550. 		attack(ronin, saints_members[rand_int(1,num_saints)]) 
  1551. 	end 
  1552. 	for i,saint in pairs(saints_members) do 
  1553. 		attack(saint, ronin_members[rand_int(1,num_ronin)]) 
  1554. 	end 
  1555.  
  1556. 	while(Battle_saints_living[saints_group] > 0 and Battle_ronin_living[ronin_group] > 0) do 
  1557. 		thread_yield() 
  1558. 	end 
  1559.  
  1560. 	if (Battle_saints_living[saints_group] == 0) then  
  1561. 		release_to_world(saints_group) 
  1562. 	else 
  1563. 		-- Find the set of living Ronin 
  1564. 		local living_ronin = {} 
  1565. 		local num_living_ronin = 0 
  1566. 		for ronin, spawnable in pairs(Spawnable_ronin) do 
  1567. 			if ( (not spawnable) and character_exists(ronin) and (not character_is_dead(ronin)) ) then 
  1568. 				num_living_ronin = num_living_ronin + 1 
  1569. 				living_ronin[num_living_ronin] = ronin 
  1570. 			end 
  1571. 		end 
  1572.  
  1573. 		for i,saint in pairs(saints_members) do 
  1574. 			-- Find the closest living Ronin to attack 
  1575. 			local nearest_ronin = "" 
  1576. 			local nearest_ronin_dist = 1000 
  1577. 			for i, ronin in pairs(living_ronin) do 
  1578. 				local cur_dist = get_dist(ronin, saint) 
  1579. 				if (cur_dist < nearest_ronin_dist) then 
  1580. 					nearest_ronin_dist = cur_dist 
  1581. 					nearest_ronin = ronin 
  1582. 				end 
  1583. 			end 
  1584. 			if (nearest_ronin ~= "") then 
  1585. 				attack(nearest_ronin) 
  1586. 			end 
  1587. 		end 
  1588. 		while(not Battle_saints_living[saints_group] == 0) do 
  1589. 			thread_yield() 
  1590. 		end 
  1591. 	end 
  1592.  
  1593. 	if (Battle_ronin_living[ronin_group] == 0) then 
  1594. 		release_to_world(ronin_group) 
  1595. 	else 
  1596. 		for i,ronin in pairs(ronin_members) do 
  1597. 			if(character_exists(ronin) and (not character_is_dead(ronin))) then 
  1598. 				attack(ronin) 
  1599. 			end 
  1600. 		end		 
  1601. 		while(Battle_ronin_living[ronin_group] ~= 0) do 
  1602. 			thread_yield() 
  1603. 		end 
  1604. 	end 
  1605.  
  1606. end 
  1607.  
  1608. function battle_saint_killed(saint) 
  1609.  
  1610. 	local group = Battle_member_to_group[saint] 
  1611. 	if (Battle_saints_living[group] == 1) then 
  1612. 		release_to_world(group) 
  1613. 		group_create_hidden(group, true) 
  1614. 	end 
  1615. 	Battle_saints_living[group] = Battle_saints_living[group] - 1 
  1616. 	Battle_living = Battle_living - 1 
  1617. end 
  1618.  
  1619. function battle_ronin_killed(ronin) 
  1620.  
  1621. 	local group = Battle_member_to_group[ronin] 
  1622. 	if (Battle_ronin_living[group] == 1) then 
  1623. 		release_to_world(group) 
  1624. 		group_create_hidden(group, true) 
  1625. 	end 
  1626. 	Battle_ronin_living[group] = Battle_ronin_living[group] - 1 
  1627. 	Battle_living = Battle_living - 1 
  1628. end 
  1629.  
  1630. --[[ 
  1631. Rn10_stationary_battle_max_attackers = 12 
  1632. Rn10_stationary_battle_attackers = 0 
  1633. MAX_STATIONARY_BATTLE_SPAWN_DIST = 150 
  1634. MIN_STATIONARY_BATTLE_SPAWN_DIST = 50 
  1635. function rn10_chaos_stationary_battles() 
  1636.  
  1637. 	while(true) do 
  1638. 		 
  1639. 		thread_yield() 
  1640.  
  1641. 		-- Look for a battle that isn't already spawned, is out of sight, and relatively close by. 
  1642. 		for i,battle in pairs(STATIONARY_BATTLES) do 
  1643.  
  1644. 			local can_spawn = not group_exists(battle["saints"]) 
  1645. 			local num_npcs = sizeof_table(battle["saints"]) + sizeof_table(battle["ronin"]) 
  1646.  
  1647. 			if (can_spawn) then				 
  1648. 				if ( num_npcs + Rn10_stationary_battle_attackers  > Rn10_stationary_battle_max_attackers) then 
  1649. 					can_spawn = false 
  1650. 				end 
  1651. 			end 
  1652.  
  1653. 			local function can_spawn_npc(npc) 
  1654. 				local in_sight = rn10_navpoint_in_fov(npc) 
  1655. 				local dist = get_dist_closest_player_to_object( npc) 
  1656. 				local too_far = dist > MAX_STATIONARY_BATTLE_SPAWN_DIST 
  1657. 				local too_close = dist < MIN_STATIONARY_BATTLE_SPAWN_DIST 
  1658. 				if (in_sight or too_far or too_close) then 
  1659. 					return false 
  1660. 				end 
  1661. 				return true 
  1662. 			end 
  1663.  
  1664. 			if (can_spawn) then 
  1665. 				for i,saint in pairs(battle["saints"]) 
  1666. 					if (not can_spawn_npc(saint)) then 
  1667. 						can_spawn = false 
  1668. 						break 
  1669. 					end 
  1670. 				end 
  1671. 			end 
  1672.  
  1673. 			if (can_spawn) then 
  1674. 				for i,ronin in pairs(battle["ronin"]) 
  1675. 					if (not can_spawn_npc(ronin)) then 
  1676. 						can_spawn = false 
  1677. 						break 
  1678. 					end 
  1679. 				end 
  1680. 			end 
  1681.  
  1682. 			if (can_spawn) then 
  1683. 		 
  1684. 				Rn10_stationary_battle_attackers = Rn10_stationary_battle_attackers + num_npcs 
  1685.  
  1686. 				group_create_hidden(battle["group"]) 
  1687. 				for i, ronin in pairs(battle["ronin"]) 
  1688. 					on_death("rn10_battle_member_killed") 
  1689. 				end 
  1690. 				for i, saint in pairs(battle["saint"]) 
  1691. 					on_death("rn10_battle_member_killed") 
  1692. 				end 
  1693. 				group_show(battle["group"] 
  1694.  
  1695. 			end 
  1696.  
  1697. 		end 
  1698. 	end 
  1699.  
  1700. end 
  1701.  
  1702. function rn10_battle_member_killed(member) 
  1703. 	on_death("", member) 
  1704. 	Rn10_stationary_battle_attackers = Rn10_stationary_battle_attackers - 1 
  1705. end 
  1706.  
  1707. function rn10_despawn_battles() 
  1708.  
  1709. 	while(true) do 
  1710. 		 
  1711. 		-- If everyone in a battle is dead, release the group to the world 
  1712. 		for i,battle in pairs(STATIONARY_BATTLES) do 
  1713.  
  1714. 			if (group_is_loaded(battle["group"])) then 
  1715.  
  1716. 				local all_ronin_dead = true 
  1717. 				for i, ronin in pairs(battle["ronin"]) 
  1718. 					if (not character_is_dead(ronin)) then 
  1719. 						all_ronin_dead = false 
  1720. 						break 
  1721. 					end 
  1722. 				end 
  1723.  
  1724. 				local all_saints_dead = true 
  1725. 				for i, saint in pairs(battle["saint"]) 
  1726. 					if (not character_is_dead(saint)) then 
  1727. 						all_saints_dead = false 
  1728. 						break 
  1729. 					end 
  1730. 				end 
  1731.  
  1732. 				if(all_ronin_dead and all_saints_dead) then 
  1733. 					release_to_world(battle["group"]) 
  1734. 				end 
  1735.  
  1736. 			end 
  1737.  
  1738. 		end 
  1739. 	end 
  1740.  
  1741. end 
  1742. ]] 
  1743.  
  1744. function rn10_navpoint_in_fov(navpoint, radius) 
  1745.  
  1746. 	local navpoint_in_local_fov = navpoint_in_player_fov(navpoint, LOCAL_PLAYER, radius) 
  1747. 	local navpoint_in_remote_fov = false 
  1748. 	if (IN_COOP) then 
  1749. 		navpoint_in_remote_fov = navpoint_in_player_fov(navpoint, REMOTE_PLAYER, radius) 
  1750. 	end 
  1751.  
  1752. 	return (navpoint_in_local_fov or navpoint_in_remote_fov) 
  1753.  
  1754. end 
  1755.  
  1756. function rn10_group_create_maybe_coop(group_always, group_coop, blocking) 
  1757. 	group_create(group_always, blocking) 
  1758. 	if (IN_COOP) then 
  1759. 		group_create(group_coop, blocking) 
  1760. 	end 
  1761. end 
  1762.  
  1763. function rn10_group_loaded_maybe_coop(group_always, group_coop) 
  1764. 	local group_always_is_loaded = group_is_loaded(group_always) 
  1765. 	if (IN_COOP) then 
  1766. 		return (group_always_is_loaded and group_is_loaded(group_always)) 
  1767. 	else 
  1768. 		return group_always_is_loaded 
  1769. 	end 
  1770. end 
  1771.  
  1772. function rn10_group_create_hidden_maybe_coop(group_always, group_coop) 
  1773. 	group_create_hidden(group_always) 
  1774. 	if (IN_COOP) then 
  1775. 		group_create_hidden(group_coop) 
  1776. 	end 
  1777. end 
  1778.  
  1779. function rn10_group_show_maybe_coop(group_always, group_coop) 
  1780. 	group_show(group_always) 
  1781. 	if (IN_COOP) then 
  1782. 		group_show(group_coop) 
  1783. 	end 
  1784. end 
  1785.  
  1786. -- MISSION FAILURE FUNCTIONS -------------------------------- 
  1787.  
  1788. function rn10_failure_gat_abandoned() 
  1789. 	-- End the mission, Gat abandoned 
  1790. 	delay(2.0) 
  1791. 	mission_end_failure("rn10", HELPTEXT_FAILURE_GAT_ABANDONED) 
  1792. end 
  1793.  
  1794. function rn10_failure_gat_died() 
  1795. 	-- End the mission, Gat died 
  1796. 	delay(2.0) 
  1797. 	mission_end_failure("rn10", HELPTEXT_FAILURE_GAT_DIED) 
  1798. end 
  1799.  
  1800. function rn10_failure_pierce_abandoned() 
  1801. 	-- End the mission, Pierce abandoned 
  1802. 	delay(2.0) 
  1803. 	mission_end_failure("rn10", HELPTEXT_FAILURE_PIERCE_ABANDONED) 
  1804. end 
  1805.  
  1806. function rn10_failure_pierce_died() 
  1807. 	-- End the mission, Pierce died 
  1808. 	delay(2.0) 
  1809. 	mission_end_failure("rn10", HELPTEXT_FAILURE_PIERCE_DIED) 
  1810. end 
  1811.  
  1812. function rn10_failure_support_collapse() 
  1813. 	-- End the mission, a support pillar has collapsed 
  1814. 	camera_shake_start(0.03,2000,2000) 
  1815. 	mission_end_failure("rn10", HELPTEXT_FAILURE_SUPPORT_COLLAPSED) 
  1816. end