--[[ 
 
	mmSummonTutorial.lua 
 
	SR3 Mission Script 
 
	DATE: 3-3-2014 
 
	AUTHOR:	Arturo Mata 
 
]]-- 
 
 
 
 
 
-- Debug flags -- 
 
 
 
-- Tweakable Parameters -- 
 
INVALID_EFFECT_HANDLE = -1 
 
-------------------------------------------------------------------------------------------------- 
 
																				--[[ GROUPS ]]-- 
 
-------------------------------------------------------------------------------------------------- 
 
	mmSummonTutorial_group = {  
									--[[ startup GROUPS ]]--	 
 
									 
 
									--[[ Ultor GROUPS ]]--	 
 
		wave_1 =  
 
		{  
			name = "wave_1", 
 
			members =  
 
			{  
				"Demon_Grunt<001>", 
 
			},		 
 
		 
 
			coop_name = "coop_wave_1", 
 
			coop_only_members = 
 
			{  
			"Demon_Grunt<002>", 
 
			}, 
 
 
 
			-- On damage threads 
 
			damage_threads = {  },  
 
 
			-- The reticle triggers for this wave 
 
			--reticle_triggers =  
 
			--{  
			--	-- The list of triggers 
 
			--	triggers = {  
			-- 
 
			--		--example_trigger =  
 
			--		--{  
			--		--	name = "Summon_Reticle_Trigger<000>",		-- The trigger 
 
			--		--	ring_effect = "Vfx Spfc Ring<000>",			-- The name of the VFX associated with the trigger 
 
			--		--	ring_effect_handle = INVALID_EFFECT_HANDLE, -- Used in turning the effect off 
 
			--		--}, 
 
			-- 
 
			--		summon_reticle_trigger_1 =  
 
			--		{  
			--			name = "Summon_Reticle_Trigger<001>", 
 
			--			ring_effect = "Vfx Spfc Ring<001>", 
 
			--			ring_effect_handle = INVALID_EFFECT_HANDLE, 
 
			--		}, 
 
			-- 
 
			--		summon_reticle_trigger_2 =  
 
			--		{  
			--			name = "Summon_Reticle_Trigger<002>", 
 
			--			ring_effect = "Vfx Spfc Ring<002>", 
 
			--			ring_effect_handle = INVALID_EFFECT_HANDLE, 
 
			--		}, 
 
			--	}, 
 
			-- 
 
			--	-- This thread runs the "reticle in trigger" detection. 
 
			--	reticle_trigger_detection_thread = INVALID_THREAD_HANDLE, 
 
			-- 
 
			--}, 
 
 
 
		}, 
 
 
 
		wave_2 =  
 
		{  
			name = "wave_2", 
 
			members =  
 
			{  
				"Demon_Grunt<003>", 
 
 
 
			},		 
 
		 
 
			coop_name = "coop_wave_2", 
 
			coop_only_members = 
 
			{  
			"Demon_Grunt<004>", 
 
			}, 
 
 
 
			damage_threads = {  },  
		-- The reticle triggers for this wave 
 
			reticle_triggers =  
 
			{  
				-- The list of triggers 
 
				triggers =  
 
				{  
					summon_reticle_trigger_1 =  
 
					{  
						name = "Summon_Reticle_Trigger<001>", 
 
						ring_effect = "Vfx Spfc Ring<001>", 
 
						ring_effect_handle = INVALID_EFFECT_HANDLE, 
 
					}, 
 
					summon_reticle_trigger_2 =  
 
					{  
						name = "Summon_Reticle_Trigger<002>", 
 
						ring_effect = "Vfx Spfc Ring<002>", 
 
						ring_effect_handle = INVALID_EFFECT_HANDLE, 
 
					}, 
 
				}, 
 
 
 
				-- This thread runs the "reticle in trigger" detection. 
 
				reticle_trigger_detection_thread = INVALID_THREAD_HANDLE, 
 
 
 
			}, 
 
		}, 
 
			wave_3 =  
 
		{  
			name = "wave_3", 
 
			members =  
 
			{  
				"Demon_Grunt<005>", 
 
				"Demon_Grunt<006>", 
 
			},		 
 
		 
 
			coop_name = "coop_wave_3", 
 
			coop_only_members = 
 
			{  
			}, 
 
 
 
			damage_threads = {  },  
	-- The reticle triggers for this wave 
 
			reticle_triggers =  
 
			{  
				-- The list of triggers 
 
				triggers = {  
 
 
					--example_trigger =  
 
					--{  
					--	name = "Summon_Reticle_Trigger<000>",		-- The trigger 
 
					--	ring_effect = "Vfx Spfc Ring<000>",			-- The name of the VFX associated with the trigger 
 
					--	ring_effect_handle = INVALID_EFFECT_HANDLE, -- Used in turning the effect off 
 
					--}, 
 
 
 
					summon_reticle_trigger_3 =  
 
					{  
						name = "Summon_Reticle_Trigger<003>", 
 
						ring_effect = "Vfx Spfc Ring<003>", 
 
						ring_effect_handle = INVALID_EFFECT_HANDLE, 
 
					}, 
 
					summon_reticle_trigger_4 =  
 
					{  
						name = "Summon_Reticle_Trigger<004>", 
 
						ring_effect = "Vfx Spfc Ring<004>", 
 
						ring_effect_handle = INVALID_EFFECT_HANDLE, 
 
					}, 
 
				}, 
 
 
 
				-- This thread runs the "reticle in trigger" detection. 
 
				reticle_trigger_detection_thread = INVALID_THREAD_HANDLE, 
 
 
 
			}, 
 
		}, 
 
 
 
									--[[  GROUPS ]]-- 
 
	} 
 
 
 
	 
 
mmSummonTutorial_respawn_points =  
 
{  
	-- wave_1 
 
	[ "Demon_Grunt<001>" ] = "Respawn_Navpoint<001>", 
 
	[ "Demon_Grunt<002>" ] = "Respawn_Navpoint<002>", 
 
 
 
	-- wave_2 
 
	[ "Demon_Grunt<003>" ] = "Respawn_Navpoint<003>", 
 
	[ "Demon_Grunt<004>" ] = "Respawn_Navpoint<004>", 
 
	-- wave 3 
 
	[ "Demon_Grunt<005>" ] = "Respawn_Navpoint<005>", 
 
	[ "Demon_Grunt<006>" ] = "Respawn_Navpoint<006>",	 
 
} 
 
 
 
-------------------------------------------------------------------------------------------------- 
 
																				--[[ THREADS ]]-- 
 
-------------------------------------------------------------------------------------------------- 
 
	mmSummonTutorial_thread = {  
		-- = INVALID_THREAD_HANDLE, 
 
		summon_reticle_in_trigger_thread_local	= INVALID_THREAD_HANDLE, 
 
		summon_reticle_in_trigger_thread_remote = INVALID_THREAD_HANDLE, 
 
 
 
 
 
	} 
 
 
 
-------------------------------------------------------------------------------------------------- 
 
																			--[[ CHECKPOINTS ]]-- 
 
-------------------------------------------------------------------------------------------------- 
 
	mmSummonTutorial_checkpoint = {  
		{  
			name = MISSION_START_CHECKPOINT,		-- First Checkpoint (fcp) 
 
			init = "mmSummonTutorial_fcp_init",				-- init(bool mission_restart) 
 
			run = "mmSummonTutorial_fcp_run",					-- run() 
 
			cleanup = "mmSummonTutorial_fcp_cleanup",			-- cleanup(bool mission_exit) (+++MUST RETURN IMMEDIATELY+++) 
 
			--next_checkpoint = "mmSummonTutorial_", 
 
			next_checkpoint = nil, 
 
			host_start = "Player_start_nav_host", 
 
			client_start = "Player_start_nav_client", 
 
			p1_car_nav = "", 
 
			p2_car_nav = "", 
 
			start_groups = { },  
			cp_only_groups = { },  
		}, 
 
	} 
 
	 
 
-------------------------------------------------------------------------------------------------- 
 
																			--[[ CUTSCENES ]]-- 
 
-------------------------------------------------------------------------------------------------- 
 
	mmSummonTutorial_scene = 
 
	{  
		intro = "", 
 
		outro = "" 
 
	} 
 
 
 
-------------------------------------------------------------------------------------------------- 
 
																			--[[ CONVERSATIONS ]]-- 
 
-------------------------------------------------------------------------------------------------- 
 
 
 
	mmSummon_persona =  
 
	{   
		Blackbeard = {  
			persona_name = "BLACKBEARD", 
 
			persona_id = INVALID_PERSONA_HANDLE 
 
		}, 
 
	} 
 
 
 
	mmSummonTutorial_convo = {  
		--[[ = { 
 
			name = "file_name without voice (_bm, _wm, _bf...", 
 
			player_talks = true or false, 
 
			handle = INVALID_CONVERSATION_HANDLE, 
 
			convo_thread = INVALID_THREAD_HANDLE, 
 
			max_wait_seconds = 60,	-- if the conversation doesn't complete before this time, kill it 
 
			timer_thread = INVALID_THREAD_HANDLE, 
 
			priority = CONVO_PRIORITY_HIGH or CONVO_PRIORITY_NORMAL or CONVO_PRIORITY_OPTIONAL 
 
			(optional) persona_line = true,	-- this is a single line 
 
			(required if persona_line) speaker_name = "name of speaker",	-- single line speaker (might be set before call to play is made?) 
 
			(optional)phone_call = true,  -- this is a phone conversation (phone persona must be preloaded) 
 
			(required if phone_call) receiving_call = true or false  -- auto-answer is always true in missions (until proven otherwise) 
 
			 
 
		},]] 
 
			 
 
		--Time�to�summon�one�of�my�favorite�little�hellions,�the�imp,�to�the�Inferno�Room! To start off lets see you summon an imp to do your dirty work and take out those enemies. 
 
		intro =  
 
		{  
			name = "mmSummonTutorial_Intro",  
 
			player_talks = false, 
 
			handle = INVALID_CONVERSATION_HANDLE, 
 
			convo_thread = INVALID_THREAD_HANDLE, 
 
			max_wait_seconds = 60, 
 
			timer_thread = INVALID_THREAD_HANDLE, 
 
			priority = CONVO_PRIORITY_NORMAL, 
 
		}, 
 
		-- Why don't you start off lets see you summon an imp to do your dirty work and take out those enemies. 
 
		wave =  
 
		{  
			name = "mmSummonTutorial_Wave",  
 
			player_talks = false, 
 
			handle = INVALID_CONVERSATION_HANDLE, 
 
			convo_thread = INVALID_THREAD_HANDLE, 
 
			max_wait_seconds = 60, 
 
			timer_thread = INVALID_THREAD_HANDLE, 
 
			priority = CONVO_PRIORITY_NORMAL, 
 
		}, 
 
		-- Took�him�down!�See�if�you�can�take�out�one�more. 
 
		one_down =  
 
		{  
			name = "mmSummonTutorial_OneDown",  
 
			player_talks = false, 
 
			handle = INVALID_CONVERSATION_HANDLE, 
 
			convo_thread = INVALID_THREAD_HANDLE, 
 
			max_wait_seconds = 60, 
 
			timer_thread = INVALID_THREAD_HANDLE, 
 
			priority = CONVO_PRIORITY_NORMAL, 
 
		}, 
 
 
 
		-- Those�little�ankle�biters�are�viscous!�Now�lets�practice�your�aim. Take down the demons on those islands 
 
		distant =  
 
		{  
			name = "mmSummonTutorial_Island",  
 
			player_talks = false, 
 
			handle = INVALID_CONVERSATION_HANDLE, 
 
			convo_thread = INVALID_THREAD_HANDLE, 
 
			max_wait_seconds = 60, 
 
			timer_thread = INVALID_THREAD_HANDLE, 
 
			priority = CONVO_PRIORITY_NORMAL, 
 
		}, 
 
 
 
		--Took�him�down!�See�if�you�can�take�out�one�more. 
 
		encourage =  
 
		{  
			name = "mm_summon_imp_encourage",  
 
			player_talks = false, 
 
			handle = INVALID_CONVERSATION_HANDLE, 
 
			convo_thread = INVALID_THREAD_HANDLE, 
 
			max_wait_seconds = 60, 
 
			timer_thread = INVALID_THREAD_HANDLE, 
 
			priority = CONVO_PRIORITY_NORMAL, 
 
		}, 
 
 
 
		-- Never�took�you�for�the�spell-casting�type.�Well�done. 
 
		success =  
 
		{  
			name = "mmSummonTutorial_Success",  
 
			player_talks = false, 
 
			handle = INVALID_CONVERSATION_HANDLE, 
 
			convo_thread = INVALID_THREAD_HANDLE, 
 
			max_wait_seconds = 60, 
 
			timer_thread = INVALID_THREAD_HANDLE, 
 
			priority = CONVO_PRIORITY_NORMAL, 
 
		}, 
 
 
 
		-- I�know�it's�fun�to�punch�these�things�back�to...�hell,�but�you�will�need�to�Summon�an�Imp�to�do�your�work�for�you�in�order to�complete�this�exercise. 
 
		chide =  
 
		{  
			name = "mmSummonTutorial_Chide",  
 
			player_talks = false, 
 
			handle = INVALID_CONVERSATION_HANDLE, 
 
			convo_thread = INVALID_THREAD_HANDLE, 
 
			max_wait_seconds = 60, 
 
			timer_thread = INVALID_THREAD_HANDLE, 
 
			priority = CONVO_PRIORITY_NORMAL, 
 
		}, 
 
	} 
 
	 
 
	mmSummonTutorial_convo_queue = {  
		--[[start_drive_queue = {   
			{ delay = 2.0, convo = mmSummonTutorial_convo.goto_Ultor },  
			{ delay = 4.0, convo = mmSummonTutorial_convo.goto_Ultor2 },  
			{ delay = 3.0, convo = mmSummonTutorial_convo.goto_Ultor3 },  
			{ delay = 5.0, convo = mmSummonTutorial_convo.goto_Ultor4 }  
		}, 
 
		]]-- 
 
	} 
 
	 
 
-------------------------------------------------------------------------------------------------- 
 
																			--[[ TRIGGERS ]]-- 
 
-------------------------------------------------------------------------------------------------- 
 
	mmSummonTutorial_trigger = {  
		-- = { 
 
		--	name = "_trigger", 
 
		--	hit = false, 
 
		-- 	last_hit_by = nil, -- 	last_hit_human = nil (set to the last human to enter the trigger in the default trigger callback) 
 
		--  (optional)callback = "mmSummonTutorial_function_name_cb" 
 
		--	(optional)marker = TRIGGER_LOCATION or TRIGGER_USE or custom or don't include for no marker 
 
		--  (optional)waypoint = true, 
 
		--  (optional)teleport_to = {  
		--						host = "host_nav", 
 
		--						client = "client_nav"  
 
		--					},		 
 
		--	(optional)conversation = mmSummonTutorial_convo.convo_name  -- play a conversation 
 
		--	(optional)next_trigger = "next_trigger_name" sets up next trigger when triggered (breadcrumbs) 
 
		--}, 
 
		 
 
									--[[ Ultor TRIGGERS ]]-- 
 
		--summon_reticle_trigger_1 = {  
		--	name = "Summon_Reticle_Trigger<001>", 
 
		--	ring_effect = "Vfx Spfc Ring<001>", 
 
		--	reticle_detection_thread = INVALID_THREAD_HANDLE, 
 
		--}, 
 
 
 
		lava_trigger = {  
			name = "lava_trigger", 
 
			callback = "mmTutorial_lava_trigger_callback", 
 
		}, 
 
									--[[  TRIGGERS ]]--	 
 
 
 
	} 
 
	 
 
-------------------------------------------------------------------------------------------------- 
 
																	  --[[ INTERROGATION DATA ]]-- 
 
-------------------------------------------------------------------------------------------------- 
 
	--mmSummonTutorial_interrogate = {  
	--	leader = {  
	--		target = mmSummonTutorial_group.friendly_fire.owner, 
 
	--		persona = "Interrogation", 
 
	--		objective = "mmSummonTutorial_INTERROGATE_OWNER", 
 
	--	--	(optional)conversation = mmSummonTutorial_convo.convo_name  -- play a conversation while interrogating 
 
	--	}, 
 
	--} 
 
		 
 
-------------------------------------------------------------------------------------------------- 
 
																				   --[[ OTHER ]]-- 
 
-------------------------------------------------------------------------------------------------- 
 
mmSummonTutorial_CurrentEnemyCount = 0 
 
mmSummon_runtime =  
 
{  
		bPersonaLoaded = false, 
 
} 
 
-------------------------------------------------------------------------------------------------- 
 
								--[[**********************]]-- 
 
								--[[                      ]]-- 
 
								--[[  Standard functions  ]]-- 
 
								--[[                      ]]-- 
 
								--[[**********************]]-- 
 
 
 
-- This is the primary entry point for the mission, and is responsible for starting up the mission 
 
-- at the specified checkpoint. 
 
-- CALLED FROM CODE 
 
-- 
 
-- start_checkpoint_name:	(string) The checkpoint the mission should begin at 
 
-- is_restart:					(bool) TRUE if the mission is restarting, FALSE otherwise 
 
-- 
 
function mmSummonTutorial_start(start_checkpoint_name, is_restart) 
 
	mission_start_fade_out(0.0) 
 
	 
 
	disable_diversions(true) 
 
	ui_hud_set_current_challenge(-1) 
 
	 
 
	-- Swap to the training facility. 
 
	city_zone_swap( "u_train", true ) 
 
 
 
	set_ped_override_density(.1) 
 
	set_traffic_density(.1) 
 
	parking_spot_disable_all(true) 
 
	-- Set up the warp trigger. 
 
	trigger_setup( mmSummonTutorial_trigger.lava_trigger ) 
 
 
 
	-- initialize systems 
 
	mission_startup(mmSummonTutorial_trigger, mmSummonTutorial_convo) -- mmSummonTutorial_checkpoint 
 
	-- if using interrogations 
 
	--interrogate_startup(mmSummonTutorial_interrogate) 
 
	 
 
	local start_cp = get_table_by_name(mmSummonTutorial_checkpoint, MISSION_START_CHECKPOINT) 
 
 
 
	-- Check if this mission starting from the beginning 
 
	if (start_checkpoint_name == start_cp.name) then 
 
		if (is_restart == false and mmSummonTutorial_scene.intro ~= "") then 
 
			-- First time playing mission 
 
			local fade_in_after = false 
 
			cutscene_play(mmSummonTutorial_scene.intro, nil, {start_cp.host_start, start_cp.client_start}, fade_in_after)  
		else 
 
			teleport_coop(start_cp.host_start, start_cp.client_start, true) 
 
		end 
 
		fade_out(0) 
 
	end 
 
 
 
	-- Handle mission initialization for the current checkpoint 
 
	mmSummonTutorial_initialize(start_checkpoint_name) 
 
 
 
	-- Run the mission from the current checkpoint 
 
	checkpoint_run_mission(mmSummonTutorial_checkpoint, start_checkpoint_name) 
 
		 
 
	mission_end_success("mmSummonTutorial", nil, { "player_end_nav_client", "player_end_nav_host" } )  
end 
 
 
 
-- This is the primary function responsible for cleaning up the entire mission 
 
-- CALLED FROM CODE (+++MUST RETURN IMMEDIATELY+++) 
 
-- 
 
function mmSummonTutorial_cleanup() 
 
	--[[ INSERT ANY MISSION SPECIFIC CLEAN-UP ]]-- 
 
 
 
	city_zone_swap( "u_train", false, true ) 
 
 
 
	imp_aggressive_tutorial_ai_enable( false ) 
 
	 
 
	disable_diversions(false) 
 
	ui_hud_set_current_challenge(-2) 
 
 
 
	-- reset the charge back to normal 
 
	player_super_power_set_regen_scalar_buff(1.0)	 
 
		 
 
	-- Re-enable all superpowers and weapon radial 
 
	inv_weapon_remove_temporary( LOCAL_PLAYER, "Pistol-Gang") 
 
	if coop_is_active() == true then 
 
		inv_weapon_remove_temporary( REMOTE_PLAYER, "Pistol-Gang") 
 
	end 
 
	set_ped_override_density(-1) 
 
	set_traffic_density(1) 
 
	parking_spot_disable_all(false) 
 
	hud_prompt_clear() 
 
 
 
	local enable = true 
 
	player_super_attacks_enable( enable, "Stomp" ) 
 
	player_super_attacks_enable( enable, "Aura" ) 
 
	player_super_attacks_enable( enable, "Freeze" ) 
 
	player_super_power_lock_to_tutorial_element( false ) 
 
	hud_inventory_disable( false ) 
 
 
 
	-- Stop controling the summoning from script 
 
	player_super_power_control_summon_through_script( LOCAL_PLAYER, false )	 
 
	if coop_is_active() then 
 
		player_super_power_control_summon_through_script( REMOTE_PLAYER, false ) 
 
	end 
 
 
 
	--ensure warp to shore is back on 
 
	player_warp_to_shore_enable( LOCAL_PLAYER ) 
 
	if coop_is_active() == true then 
 
		player_warp_to_shore_enable( REMOTE_PLAYER ) 
 
	end 
 
 
 
	-- cleanup all threads 
 
	cleanup_threads(mmSummonTutorial_thread) 
 
	 
 
	-- run checkpoint cleanups (move into mission_shutdown?) 
 
	checkpoint_cleanup_mission(mmSummonTutorial_checkpoint) 
 
	 
 
	-- cleanup triggers, convos, kill_list and interrogations 
 
	mission_shutdown() 
 
	 
 
	-- cleanup all groups 
 
	cleanup_groups(mmSummonTutorial_group)	 
 
		 
 
end 
 
 
 
-- Called when the mission has ended with success 
 
-- CALLED FROM CODE (+++MUST RETURN IMMEDIATELY+++) 
 
-- 
 
function mmSummonTutorial_success() 
 
	--[[ INSERT ANY MISSION SPECIFIC SUCCESS STUFF ]]-- 
 
	 
 
end 
 
 
 
-------------------------------------------------------------------------------------------------- 
 
								--[[**********************]]-- 
 
								--[[                      ]]-- 
 
								--[[ Initialize functions ]]-- 
 
								--[[                      ]]-- 
 
								--[[**********************]]-- 
 
 
 
-- Initialize the mission for the specified checkpoint 
 
-- 
 
-- checkpoint_name:		(string) Checkpoint to initialize the mission to 
 
-- 
 
function mmSummonTutorial_initialize(checkpoint_name) 
 
	-- Common initialization 
 
	mmSummonTutorial_initialize_common() 
 
	 
 
	-- Checkpoint specific initialization 
 
	checkpoint_init(mmSummonTutorial_checkpoint, checkpoint_name) 
 
 
 
	-- Remove any present subtitles 
 
	message_remove_all() 
 
 
 
	-- Start fading in  
 
	mission_start_fade_in() 
 
	 
 
	audio_object_post_event( "Play_mmSummonTutorial" ) 
 
end 
 
 
 
-- Handle any common initialization 
 
-- 
 
function mmSummonTutorial_initialize_common() 
 
	--[[ INSERT ANY COMMON INITIALIZATION CODE HERE ]]-- 
 
	waypoint_remove() 
 
	imp_aggressive_tutorial_ai_enable( true ) 
 
 
 
	mission_set_cancel_warp_location("player_end_nav_host", "player_end_nav_client")  
 
 
	if mmSummon_runtime.bPersonaLoaded == false then 
 
		load_persona(mmSummon_persona.Blackbeard) 
 
		mmSummon_runtime.bPersonaLoaded = true 
 
	end  
 
	-- Disable all superpowers and weapon radial 
 
	local enable = false 
 
	player_super_attacks_enable( enable, "Stomp" ) 
 
	player_super_attacks_enable( enable, "Aura" ) 
 
	player_super_attacks_enable( enable, "Freeze" ) 
 
	player_super_power_lock_to_tutorial_element( true, "summon_imp", SYNC_ALL )		 
 
	player_super_power_select( "Summon", SYNC_ALL, "summon_imp" ) 
 
	hud_inventory_disable( true ) 
 
 
 
end 
 
 
 
-------------------------------------------------------------------------------------------------- 
 
								--[[**********************]]-- 
 
								--[[                      ]]-- 
 
								--[[ Checkpoint functions ]]-- 
 
								--[[                      ]]-- 
 
								--[[**********************]]-- 
 
 
 
-------------------------------------------------------------------------------------------------- 
 
																	--[[ First Checkpoint Name ]]-- 
 
-------------------------------------------------------------------------------------------------- 
 
 
 
-- Initialize this checkpoint. 
 
-- 
 
-- mission_start: (bool) Whether we're initializing from a mission (re)start or from 
 
--					a natural play-through. 
 
-- 
 
function mmSummonTutorial_fcp_init(mission_start) 
 
	 
 
	-- Turn off all pickup drops 
 
	health_pickups_enable(false) 
 
	human_all_stop_dropping_weapons(true) 
 
	human_all_stop_dropping_cash(true) 
 
 
 
	 
 
	-- Disable access to the hub menu 
 
	cellphone_lock( true ) 
 
 
 
	-- Set up the players as invulnerable 
 
	turn_invulnerable( LOCAL_PLAYER ) 
 
	if coop_is_active() == true then 
 
		turn_invulnerable( REMOTE_PLAYER ) 
 
	end 
 
 
 
	-- Disable warp to shore 
 
	player_warp_to_shore_disable( LOCAL_PLAYER ) 
 
	if coop_is_active() == true then 
 
		player_warp_to_shore_disable( REMOTE_PLAYER ) 
 
	end 
 
 
 
	--Remove all summons 
 
	player_super_power_clear_summons(LOCAL_PLAYER) 
 
 
 
	-- In the case that this power isn't unlocked, unlock it. 
 
	-- Really only here for debug purposes when jumping into the mission at hvslice 0. 
 
	player_unlock_super_power( SUPERPOWER_SUMMON, LOCAL_PLAYER, true ) 
 
	if coop_is_active() then 
 
		player_unlock_super_power( SUPERPOWER_SUMMON, REMOTE_PLAYER, true ) 
 
	end 
 
 
 
	-- Enable superpower stuffsmmSummon_convo 
 
	player_super_movement_enable( true ) 
 
	player_super_attacks_enable( true ) 
 
 
 
	-- Disable melee (because if the co-op client melees, they gain ownership of the enemy and that messes up our death callbacks) 
 
	set_player_can_take_human_shields( LOCAL_PLAYER, false ) 
 
	set_player_can_take_human_shields( REMOTE_PLAYER, false ) 
 
	player_allow_weapon_melee( false ) 
 
	 
 
	-- Disable notoriety 
 
	notoriety_set_min_and_max( "luchadores", 0, 0 ) 
 
	notoriety_set_min_and_max( "police", 0, 0 ) 
 
 
 
 
 
end 
 
 
 
-- The first objective 
 
-- 
 
function mmSummonTutorial_fcp_run() 
 
 
 
 
 
	-- Give the player a pistol and make it the only available weapon 
 
	inv_weapon_add_temporary( LOCAL_PLAYER, "Pistol-Gang", 100, true, true, false, true ) 
 
	inv_item_equip("Pistol-Gang", LOCAL_PLAYER)  
	if coop_is_active() == true then 
 
		inv_weapon_add_temporary( REMOTE_PLAYER, "Pistol-Gang", 100, true, true, false, true ) 
 
		inv_item_equip("Pistol-Gang", REMOTE_PLAYER)  
	end 
 
	inv_weapon_disable_all_but_this_slot( WEAPON_SLOT_PISTOL, true, SYNC_ALL ) 
 
 
 
	player_super_power_set_regen_scalar_buff(5.0)	 
 
	convo_start(mmSummonTutorial_convo.intro) 
 
	convo_wait_for_end() 
 
	convo_start(mmSummonTutorial_convo.wave) 
 
	-- Create Wave 1 
 
	objective_text( 0, "SRG_MMSUMMON_OBJECTIVE_ENEMIES", "", "", SYNC_ALL, OI_ASSET_POWER_SUMMON ) 
 
 
 
	hud_prompt(LOCAL_PLAYER, "SRG_MMSUMMON_USE_NAG", "", true) 
 
	 
 
	-- Play the tutorial text 
 
	tutorial_stop_current() 
 
	local tutorial_name = "summon_enemies" 
 
	local delay_ms = 0 
 
	local auto_unlock = false 
 
	local allow_redisplay = false 
 
	local infinite_display = true 
 
	tutorial_start(tutorial_name, delay_ms, auto_unlock, allow_redisplay, infinite_display) 
 
	mmSummonTutorial_wave_setup( mmSummonTutorial_group.wave_1, false ) 
 
 
 
	npc_leash_to_nav("Demon_Grunt<001>", "Respawn_Navpoint<001>", 1.0, false)  
	if coop_is_active() then 
 
	npc_leash_to_nav("Demon_Grunt<002>", "Respawn_Navpoint<002>", 1.0, false)  
	end 
 
	while mmSummonTutorial_CurrentEnemyCount > 0 do 
 
		thread_yield() 
 
	end 
 
	hud_prompt_clear() 
 
	 
 
	-- Create Wave 2	 
 
	convo_start(mmSummonTutorial_convo.one_down)	 
 
	player_super_power_clear_summons( LOCAL_PLAYER ) 
 
	if coop_is_active() then		 
 
		player_super_power_clear_summons( REMOTE_PLAYER ) 
 
	end 
 
	mmSummonTutorial_wave_setup( mmSummonTutorial_group.wave_2, false ) 
 
	-- make sure everybody spawns before leashing them 
 
 
 
	npc_leash_to_nav("Demon_Grunt<003>", "Respawn_Navpoint<003>", 0.5, false)  
	if coop_is_active() then	 
 
		npc_leash_to_nav("Demon_Grunt<004>", "Respawn_Navpoint<004>", 0.5, false)  
	end 
 
	while mmSummonTutorial_CurrentEnemyCount > 0 do 
 
		thread_yield() 
 
	end 
 
	 
 
	objective_text_clear(0)	 
 
	objective_text( 0, "SRG_MMSUMMON_OBJECTIVE_DISTANCE", "", "", SYNC_ALL, OI_ASSET_POWER_SUMMON ) 
 
	-- Create Wave 3	 
 
	convo_start(mmSummonTutorial_convo.distant)		 
 
	-- Clear out any summons. 
 
	player_super_power_clear_summons( LOCAL_PLAYER ) 
 
	if coop_is_active() then		 
 
		player_super_power_clear_summons( REMOTE_PLAYER ) 
 
	end 
 
	-- Set up the summon reticle triggers 
 
	mmSummonTutorial_setup_summon_reticle_triggers( mmSummonTutorial_group.wave_3.reticle_triggers ) 
 
	-- Control the summoning from script 
 
	player_super_power_control_summon_through_script( LOCAL_PLAYER, true ) 
 
	if coop_is_active() then 
 
		player_super_power_control_summon_through_script( REMOTE_PLAYER, true ) 
 
	end 
 
	tutorial_stop_current()	 
 
	tutorial_name = "summon_distance" 
 
	tutorial_start(tutorial_name, delay_ms, auto_unlock, allow_redisplay, infinite_display) 
 
	mmSummonTutorial_wave_setup( mmSummonTutorial_group.wave_3, true ) 
 
	ai_attack_region("Demon_Grunt<005>", "Respawn_Navpoint<005>", 1.8)  
	ai_attack_region("Demon_Grunt<006>", "Respawn_Navpoint<006>", 1.8)  
 
 
	while mmSummonTutorial_CurrentEnemyCount > 0 do 
 
		thread_yield() 
 
	end 
 
		 
 
	-- Clean up the summon reticle triggers 
 
	mmSummonTutorial_cleanup_summon_reticle_trigger( mmSummonTutorial_group.wave_3.reticle_triggers ) 
 
	 
 
	-- Clear out any summons. 
 
	player_super_power_clear_summons( LOCAL_PLAYER ) 
 
	if coop_is_active() then		 
 
		player_super_power_clear_summons( REMOTE_PLAYER ) 
 
	end 
 
	-- Stop controlling the summoning from script 
 
	player_super_power_control_summon_through_script( LOCAL_PLAYER, false )	 
 
	if coop_is_active() then 
 
		player_super_power_control_summon_through_script( REMOTE_PLAYER, false ) 
 
	end 
 
		 
 
	tutorial_stop_current() 
 
	objective_text_clear(0)	 
 
	convo_start(mmSummonTutorial_convo.success) 
 
	convo_wait_for_end()	 
 
	delay(1.0)	 
 
 
 
	-- Fade the screen so we can zone swap. 
 
	fade_out(0.0) 
 
	delay(2.0) 
 
 
 
end 
 
 
 
-- Do any cleanup for this checkpoint. 
 
-- 
 
-- (+++THIS IS CALLED FROM MISSION CLEANUP, MUST RETURN IMMEDIATELY+++) 
 
-- 
 
-- mission_exit: (bool) Whether we're exiting the mission entirely, or just 
 
--					moving on to the next checkpoint. 
 
-- 
 
function mmSummonTutorial_fcp_cleanup(mission_exit) 
 
 
 
	-- Cleanup all of the enemies 
 
	mmTutorial_cleanup_enemies( mmSummonTutorial_group.wave_1 ) 
 
	mmTutorial_cleanup_enemies( mmSummonTutorial_group.wave_2 ) 
 
	mmTutorial_cleanup_enemies( mmSummonTutorial_group.wave_3 ) 
 
 
 
	-- turn back on all pickup drops 
 
	health_pickups_enable(true) 
 
	human_all_stop_dropping_weapons(false) 
 
	human_all_stop_dropping_cash(false) 
 
 
 
	-- Re-enable all weapon slots 
 
	inv_weapon_disable_all_slots( false, SYNC_ALL ) 
 
		 
 
	-- Re-enable access to the hub menu 
 
	cellphone_lock( false ) 
 
 
 
	turn_vulnerable( LOCAL_PLAYER ) 
 
	if coop_is_active() == true then 
 
		turn_vulnerable( REMOTE_PLAYER ) 
 
	end 
 
 
 
	-- Enable warp to shore 
 
	player_warp_to_shore_enable( LOCAL_PLAYER ) 
 
	if coop_is_active() == true then 
 
		player_warp_to_shore_enable( REMOTE_PLAYER ) 
 
	end 
 
 
 
	-- Clean up superpower tweaks. 
 
	on_superpower_equip( "", LOCAL_PLAYER ) 
 
	on_superpower_equip( "", REMOTE_PLAYER ) 
 
	npc_respawn_dist_reset() 
 
 
 
	-- Re-enable melee 
 
	set_player_can_take_human_shields( LOCAL_PLAYER, true ) 
 
	set_player_can_take_human_shields( REMOTE_PLAYER, true ) 
 
	player_allow_weapon_melee( true ) 
 
	 
 
	-- Re-enable notoriety 
 
	notoriety_set_min_and_max( "luchadores", 0, MAX_NOTORIETY_LEVEL ) 
 
	notoriety_set_min_and_max( "police", 0, MAX_NOTORIETY_LEVEL ) 
 
 
 
end 
 
 
 
------------------------------------ 
 
-- 
 
-- Checkpoint helper functions 
 
-- 
 
------------------------------------ 
 
function mmSummonTutorial_wave_setup( wave_group, ignore_coop_wave ) 
 
 
 
	-- Reset our enemy counter 
 
	mmSummonTutorial_CurrentEnemyCount = 0 
 
	 
 
	-- Allow respawning at a close distance 
 
	npc_respawn_dist_override( 100000.0 ) 
 
 
 
	-- Create the wave 
 
	group_create( wave_group.name, true ) 
 
 
 
	-- Set special tutorial wave properties. 
 
	for i, wave_member in pairs( wave_group.members ) do 
 
 
 
		-- Ensure they know about and see the players 
 
		--ai_add_enemy_target( wave_member, LOCAL_PLAYER, ATTACK_ON_SIGHT, false, true ) 
 
		--if coop_is_active() then 
 
		--	ai_add_enemy_target( wave_member, REMOTE_PLAYER, ATTACK_ON_SIGHT, false, true ) 
 
		--end 
 
 
 
		 
 
		turn_invulnerable( wave_member ) 
 
		character_set_never_catch_fire( wave_member, true ) 
 
		on_death( "mmSummonTutorial_on_death_cb", wave_member ) 
 
		character_prevent_explosion_fling( wave_member, true ) 
 
 
 
		wave_group.damage_threads[ wave_member ] = thread_new("mmSummonTutorial_imp_attach_thread", wave_member )  
 
 
		marker_add( wave_member, MINIMAP_ICON_SUMMON, OI_ASSET_POWER_SUMMON, OI_FLAGS_DEFAULT, SYNC_ALL ) 
 
		mmSummonTutorial_CurrentEnemyCount = mmSummonTutorial_CurrentEnemyCount + 1 
 
	end 
 
 
 
	if coop_is_active() and ignore_coop_wave == false then 
 
		 
 
		-- Create the co-op wave 
 
		group_create( wave_group.coop_name ) 
 
 
 
		-- Set special tutorial wave properties. 
 
		for i, wave_member in pairs( wave_group.coop_only_members ) do 
 
 
 
			-- Ensure they know about and see the players 
 
	--		ai_add_enemy_target( wave_member, LOCAL_PLAYER, ATTACK_ON_SIGHT, false, true ) 
 
			if coop_is_active() then 
 
	--			ai_add_enemy_target( wave_member, REMOTE_PLAYER, ATTACK_ON_SIGHT, false, true ) 
 
			end 
 
			 
 
			turn_invulnerable( wave_member ) 
 
 
 
			on_death( "mmSummonTutorial_on_death_cb", wave_member ) 
 
			wave_group.damage_threads[ wave_member ] = thread_new("mmSummonTutorial_imp_attach_thread", wave_member )  
			 
 
			character_prevent_explosion_fling( wave_member, true ) 
 
 
 
			marker_add( wave_member, MINIMAP_ICON_SUMMON, OI_ASSET_POWER_SUMMON, OI_FLAGS_DEFAULT, SYNC_ALL ) 
 
			mmSummonTutorial_CurrentEnemyCount = mmSummonTutorial_CurrentEnemyCount + 1 
 
		end 
 
	end 
 
 
 
end 
 
 
 
function mmSummonTutorial_get_npc_respawn_navpoint( npc_name ) 
 
	 
 
	return mmSummonTutorial_respawn_points[ npc_name ] 
 
 
 
end 
 
 
 
function mmSummonTutorial_setup_summon_reticle_triggers( reticle_triggers ) 
 
	 
 
	-- For each trigger in this group of triggers 
 
	for i, trigger in pairs( reticle_triggers.triggers ) do 
 
 
 
		-- Set up the summon spawn trigger 
 
		trigger_enable( trigger.name, true) 
 
			 
 
		-- Show the marker 
 
		trigger.ring_effect_handle = effect_play( trigger.ring_effect, true ) 
 
	 
 
	end 
 
 
 
	-- Start the thread for detecting if the player has summoned in the trigger 
 
	reticle_triggers.reticle_detection_thread = thread_new( "mmSummonTutorial_summon_reticle_trigger_thread_func", reticle_triggers ) 
 
	 
 
end 
 
 
 
 
 
function mmSummonTutorial_cleanup_summon_reticle_trigger( reticle_triggers ) 
 
	 
 
	-- For each trigger in this group of triggers 
 
	for i, trigger in pairs( reticle_triggers.triggers ) do 
 
 
 
		-- Stop the effect 
 
		effect_stop( trigger.ring_effect_handle ) 
 
 
 
		-- Disable the trigger 
 
		trigger_enable( trigger.name, false ) 
 
	 
 
	end 
 
 
 
	cleanup_threads( reticle_triggers.reticle_trigger_detection_thread ) 
 
 
 
end 
 
 
 
------------------------------------ 
 
-- 
 
-- Checkpoint callback functions 
 
-- 
 
------------------------------------ 
 
function mmSummonTutorial_on_death_cb( npc ) 
 
 
 
	if( character_has_imp_attached( npc ) == true ) then 
 
		mmSummonTutorial_CurrentEnemyCount = mmSummonTutorial_CurrentEnemyCount - 1 
 
		on_death( "", npc ) 
 
		marker_remove( npc ) 
 
	else 
 
			 
 
		-- Play the VFX at the death location 
 
		npc_fade_out( npc, 1.0, false, 0 )  
 
		 
 
		delay( 1.0 ) 
 
				 
 
		-- TODO: Play the VO for an unsuccessful kill. 
 
		if (convo_is_playing() == false) then 
 
			convo_start(mmSummonTutorial_convo.chide) 
 
		end	 
 
		-- Teleport them to their respawn navpoint 
 
		teleport( npc, mmSummonTutorial_get_npc_respawn_navpoint( npc ) ) 
 
		 
 
		-- Play the VFX 
 
		--effect_play_on_human( mmBlastTutorial_effects.respawn_effect, npc )  
 
 
 
		-- Respawn the character (teleport and revive) 
 
		npc_revive( npc ) 
 
		 
 
		-- Show the character and mark them as a target 
 
		character_show( npc ) 
 
		 
 
		-- Give him a decent weapon 
 
		inv_item_add( "Rifle-LavaBolter", 1, npc, true ) 
 
		--COMEBACK 
 
		npc_leash_to_nav(npc, mmSummonTutorial_get_npc_respawn_navpoint(npc), 0.5, false ) 
 
 
 
		marker_add( npc, MINIMAP_ICON_SUMMON, OI_ASSET_POWER_SUMMON, OI_FLAGS_DEFAULT, SYNC_ALL ) 
 
		 
 
 
 
	end 
 
 
 
 
 
 
 
end 
 
 
 
------------------------------------ 
 
-- 
 
-- Checkpoint thread functions 
 
-- 
 
------------------------------------ 
 
function mmSummonTutorial_imp_attach_thread( npc ) 
 
 
 
	while( true )do 
 
		if( character_has_imp_attached( npc ) == true ) then 
 
			turn_vulnerable( npc ) 
 
		else 
 
			turn_invulnerable( npc ) 
 
		end 
 
 
 
		-- Catches npcs which fall into the lava 
 
		-- To make extra sure we catch them, also process enemies near the lava (the lava is at about y: 882) 
 
		if character_is_in_lava( npc ) or (human_get_pos_y(npc) < 883.0) then 
 
			turn_vulnerable( npc ) 
 
			character_kill( npc ) 
 
		end 
 
 
 
		thread_yield() 
 
	end 
 
 
 
end 
 
 
 
-------------------------------------------------------------------------------------------------- 
 
								--[[**********************]]-- 
 
								--[[                      ]]-- 
 
								--[[   Common functions   ]]-- 
 
								--[[                      ]]-- 
 
								--[[**********************]]-- 
 
 
 
function mmTutorial_cleanup_enemies( wave ) 
 
	 
 
	-- Cleanup the damage threads 
 
	cleanup_threads( wave.damage_threads ) 
 
 
 
	-- Cleanup individual wave members 
 
	for i, wave_member in pairs( wave.members ) do 
 
		 
 
		-- Remove the death callback 
 
		on_death( "", wave_member )		 
 
 
 
		-- Remove the respawn callback 
 
		on_respawn( "", wave_member ) 
 
		on_revived( "", wave_member ) 
 
 
 
		-- Remove any object indicators 
 
		marker_remove( wave_member ) 
 
 
 
	end 
 
 
 
	-- Cleanup individual coop wave members 
 
	for i, wave_member in pairs( wave.coop_only_members ) do	 
 
 
 
		-- Remove the death callback 
 
		on_death( "", wave_member )		 
 
 
 
		-- Remove the respawn callback 
 
		on_respawn( "", wave_member ) 
 
		on_revived( "", wave_member ) 
 
 
 
		-- Remove any object indicators 
 
		marker_remove( wave_member ) 
 
 
 
	end 
 
 
 
end 
 
 
 
-------------------------------------------------------------------------------------------------- 
 
								--[[**********************]]-- 
 
								--[[                      ]]-- 
 
								--[[  Callback functions  ]]-- 
 
								--[[                      ]]-- 
 
								--[[**********************]]-- 
 
local processing_lava_player_local = false 
 
local processing_lava_player_remote = false		 
 
function mmTutorial_lava_trigger_callback( human, trigger ) 
 
 
 
	if human == LOCAL_PLAYER then 
 
		if (processing_lava_player_local == false) then 
 
			-- if we aren't currently trying to warp the player, then warp them 
 
			processing_lava_player_local = true 
 
 
 
			delay( 1.0 ) 
 
			fade_out( 0, 0, SYNC_LOCAL ) 
 
			delay( 1.0 ) 
 
			teleport( LOCAL_PLAYER, "Player_start_nav_host" ) 
 
			fade_in( 0, 0, SYNC_LOCAL ) 
 
			 
 
			-- done warping the player 
 
			processing_lava_player_local = false 
 
		end 
 
 
 
	elseif human == REMOTE_PLAYER then 
 
		if (processing_lava_player_remote == false) then 
 
			processing_lava_player_remote = true 
 
			-- if we aren't currently trying to warp the player, then warp them 
 
			 
 
			delay( 1.0 ) 
 
			fade_out( 0, 0, SYNC_REMOTE ) 
 
			delay( 1.0 ) 
 
			teleport( REMOTE_PLAYER, "Player_start_nav_client" ) 
 
			fade_in( 0, 0, SYNC_REMOTE ) 
 
 
 
			-- done warping the player 
 
			processing_lava_player_remote = false 
 
		end 
 
	end 
 
end 
 
 
 
-------------------------------------------------------------------------------------------------- 
 
								--[[**********************]]-- 
 
								--[[                      ]]-- 
 
								--[[   Thread functions   ]]-- 
 
								--[[                      ]]-- 
 
								--[[**********************]]-- 
 
function mmSummonTutorial_summon_reticle_trigger_thread_func( reticle_triggers ) 
 
 
 
	while( true )do 
 
 
 
		local local_player_reticle_in_trigger = false 
 
		local remote_player_reticle_in_trigger = false 
 
 
 
		for i, trigger in pairs( reticle_triggers.triggers ) do 
 
 
 
			-- Only test the reticle if we're still false. 
 
			-- That way, if we hit a trigger, and test against another trigger 
 
			-- it won't override the summon permission. 
 
			if local_player_reticle_in_trigger == false then 
 
				local_player_reticle_in_trigger = player_super_power_is_summon_reticle_in_trigger( LOCAL_PLAYER, trigger.name ) 
 
			end 
 
			 
 
			-- Check the co-op player 
 
			if coop_is_active() and remote_player_reticle_in_trigger == false then 
 
				remote_player_reticle_in_trigger = player_super_power_is_summon_reticle_in_trigger( REMOTE_PLAYER, trigger.name ) 
 
			end 
 
 
 
		end 
 
 
 
		-- Set our "can summon" permissions 
 
		player_super_power_can_summon( LOCAL_PLAYER, local_player_reticle_in_trigger ) 
 
		if coop_is_active() then 
 
			player_super_power_can_summon( REMOTE_PLAYER, remote_player_reticle_in_trigger ) 
 
		end 
 
		 
 
		thread_yield() 
 
	end 
 
end