--[[
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