--[[
_____ _ _______ _
|_ _| | | |__ __| (_)
_ __ ___ | | _ __ | |_ _ __ ___ | |_ ___ _ __ ___
| '_ ` _ \ | | | '_ \| __| '__/ _ \| \ \ /\ / / | '_ \/ __|
| | | | | |_| |_| | | | |_| | | (_) | |\ V V /| | | | \__ \
|_| |_| |_|_____|_| |_|\__|_| \___/|_| \_/\_/ |_|_| |_|___/
--]]
--[[
mIntroTwins.lua
SRG Map Event Script
DATE: 2014-05-05
AUTHOR: Kevin Tyska
]]--
-- Tweakable Parameters --
SUPERPOWER_BLAST = 3
PLAYER_SUPERPOWER_BLAST_STONE = 12
--------------------------------------------------------------------------------------------------
--[[
_____
/ ____|
| | __ _ __ ___ _ _ _ __ ___
| | |_ | '__/ _ \| | | | '_ \/ __|
| |__| | | | (_) | |_| | |_) \__ \
\_____|_| \___/ \__,_| .__/|___/
| |
|_|
]]--
--------------------------------------------------------------------------------------------------
mIntroTwins_group = {
--HOMIE GROUPS
kiki_npc_combat = {
name = "kiki_combat_group",
npcs = { "kiki_combat_npc" },
kiki = "kiki_combat_npc",
},
viola_npc_combat = {
name = "viola_combat_group",
npcs = { "viola_combat_npc" },
viola = "viola_combat_npc",
},
--SAM GRUNTS
SAM_Demon_01 = {
name = "SAM_grunt_01",
sam = "SAM_grunt<001>",
},
SAM_Demon_02 = {
name = "SAM_grunt_02",
sam = "SAM_grunt<002>",
},
SAM_Demon_03 = {
name = "SAM_grunt_03",
sam = "SAM_grunt<003>",
},
--ENEMY GROUPS
w1_squad_01 = {
name = "twins_w1_squad_01",
members = { "w1_squad_01<001>", "w1_squad_01<002>" },
destination = "w1_squad_01_nav",
},
w1_squad_02 = {
name = "twins_w1_squad_02",
members = { "w1_squad_02<001>", "w1_squad_02<002>" },
},
w1_squad_03 = {
name = "twins_w1_squad_03",
members = { "w1_squad_03<001>", "w1_squad_03<002>" },
destination = "w1_squad_03_nav",
},
w2_squad_01 = {
name = "twins_w2_squad_01",
members = { "w2_squad_01<001>", "w2_squad_01<002>" },
},
w2_squad_02 = {
name = "twins_w2_squad_02",
members = { "w2_squad_02<001>"},
},
w2_squad_03 = {
name = "twins_w2_squad_03",
members = { "w2_squad_03<001>", "w2_squad_03<002>" },
destination = "w2_squad_03_nav",
},
w2_squad_04 = {
name = "twins_w2_squad_04",
members = { "w2_squad_02<002>" },
},
w3_squad_01 = {
name = "twins_w3_squad_01",
members = { "w3_squad_01<001>" },
},
w3_squad_02 = {
name = "twins_w3_squad_02",
members = { "w3_squad_01<002>" },
},
w4_squad_01 = {
name = "twins_w4_squad_01",
members = { "w4_squad_01<001>", "w4_squad_01<002>", "w4_squad_01<003>" },
destination = "w4_squad_01_nav",
},
w4_squad_02 = {
name = "twins_w4_squad_02",
members = { "w4_squad_02<001>", "w4_squad_02<002>", "w4_squad_02<003>" },
destination = "w4_squad_02_nav",
},
w4_boss_01 = {
name = "twins_w4_boss",
members = { "boss<001>" },
},
--ENEMY VEHICLES
vehicle_01 = {
name = "vehicle_01_group",
hidden = true,
members = { "vehicle01_troop<001>", "vehicle01_troop<002>" },
vehicle = "vehicle_01",
path = "vehicle_01_nav",
thread = INVALID_THREAD_HANDLE,
},
vehicle_02 = {
name = "vehicle_02_group",
hidden = true,
members = { "vehicle02_troop<001>", "vehicle02_troop<002>" },
vehicle = "vehicle_02",
path = "vehicle_02_nav",
thread = INVALID_THREAD_HANDLE,
},
}
--------------------------------------------------------------------------------------------------
--[[
_ _ _ _
| \ | | (_) | |
| \| | __ ___ ___ __ ___ _ _ __ | |_ ___
| . ` |/ _` \ \ / / '_ \ / _ \| | '_ \| __/ __|
| |\ | (_| |\ V /| |_) | (_) | | | | | |_\__ \
|_| \_|\__,_| \_/ | .__/ \___/|_|_| |_|\__|___/
| |
|_|
]]--
--------------------------------------------------------------------------------------------------
mIntroTwins_navpoints = {
}
--------------------------------------------------------------------------------------------------
--[[
_______ _ _
|__ __| | | |
| | | |__ _ __ ___ __ _ __| |___
| | | '_ \| '__/ _ \/ _` |/ _` / __|
| | | | | | | | __/ (_| | (_| \__ \
|_| |_| |_|_| \___|\__,_|\__,_|___/
]]--
--------------------------------------------------------------------------------------------------
mIntroTwins_thread = {
}
--------------------------------------------------------------------------------------------------
--[[
_ _ _ _ _____ _
/\ (_) | \ | | | | | __ \ | |
/ \ _ __ _ _ __ ___ | \| | ___ __| | ___ | | | | __ _| |_ __ _
/ /\ \ | '_ \| | '_ ` _ \ | . ` |/ _ \ / _` |/ _ \ | | | |/ _` | __/ _` |
/ ____ \| | | | | | | | | | | |\ | (_) | (_| | __/ | |__| | (_| | || (_| |
/_/ \_\_| |_|_|_| |_| |_| |_| \_|\___/ \__,_|\___| |_____/ \__,_|\__\__,_|
]]--
--------------------------------------------------------------------------------------------------
mIntroTwins_anim_node = {
}
--------------------------------------------------------------------------------------------------
--[[
_____ _ _ _ _
/ ____| | | | (_) | |
| | | |__ ___ ___| | ___ __ ___ _ _ __ | |_ ___
| | | '_ \ / _ \/ __| |/ / '_ \ / _ \| | '_ \| __/ __|
| |____| | | | __/ (__| <| |_) | (_) | | | | | |_\__ \
\_____|_| |_|\___|\___|_|\_\ .__/ \___/|_|_| |_|\__|___/
| |
|_|
]]--
--------------------------------------------------------------------------------------------------
mIntroTwins_checkpoint = {
{
name = MISSION_START_CHECKPOINT, -- Twins SAM (sam)
init = "mIntroTwins_sam_init",
run = "mIntroTwins_sam_run",
cleanup = "mIntroTwins_sam_cleanup",
next_checkpoint = "Kill_Demons",
host_start = "player_start_host",
client_start = "player_start_client",
p1_car_nav = "",
p2_car_nav = "",
start_groups = { },
cp_only_groups = {},
},
{
name = "Kill_Demons", -- First Checkpoint (kil)
init = "mIntroTwins_kil_init",
run = "mIntroTwins_kil_run",
cleanup = "mIntroTwins_kil_cleanup",
next_checkpoint = "nil",
host_start = "player_start_host",
client_start = "player_start_client",
p1_car_nav = "",
p2_car_nav = "",
start_groups = { mIntroTwins_group.vehicle_01, mIntroTwins_group.vehicle_02 },
cp_only_groups = {},
},
}
--------------------------------------------------------------------------------------------------
--[[
_____ _
/ ____| | |
| | _ _| |_ ___ ___ ___ _ __ ___ ___
| | | | | | __/ __|/ __/ _ \ '_ \ / _ \/ __|
| |___| |_| | |_\__ \ (_| __/ | | | __/\__ \
\_____\__,_|\__|___/\___\___|_| |_|\___||___/
]]--
--------------------------------------------------------------------------------------------------
mIntroTwins_scene = {
intro = "",
outro = "Bink_Twins_Aided"
}
--------------------------------------------------------------------------------------------------
--[[
_____ _ _
/ ____| | | (_)
| | ___ _ ____ _____ _ __ ___ __ _| |_ _ ___ _ __ ___
| | / _ \| '_ \ \ / / _ \ '__/ __|/ _` | __| |/ _ \| '_ \/ __|
| |___| (_) | | | \ V / __/ | \__ \ (_| | |_| | (_) | | | \__ \
\_____\___/|_| |_|\_/ \___|_| |___/\__,_|\__|_|\___/|_| |_|___/
]]--
--------------------------------------------------------------------------------------------------
mIntroTwins_persona = {
Johnny = {
persona_name = "Johnny_Gat",
persona_id = INVALID_PERSONA_HANDLE
},
Kinzie = {
persona_name = "Kinzie",
persona_id = INVALID_PERSONA_HANDLE
},
Kiki = {
persona_name = "kiki",
persona_id = INVALID_PERSONA_HANDLE
},
Viola = {
persona_name = "suko",
persona_id = INVALID_PERSONA_HANDLE
},
}
mIntroTwins_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)
},]]
Gat_Convo_A = {
name = "mIntroTwins_Con_Gat_A",
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,
},
Gat_Convo_B = {
name = "mIntroTwins_Con_Gat_B",
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,
},
Kinzie_Convo_A = {
name = "mIntroTwins_Con_Kinzie_A",
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,
},
Kinzie_Convo_B = {
name = "mIntroTwins_Con_Kinzie_B",
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,
},
Grant_Power = {
name = "mIntroTwins_grant_power",
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,
},
Gat_End = {
name = "mIntroTwins_End_Gat",
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,
},
Kinzie_End = {
name = "mIntroTwins_End_Kinzie",
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,
},
}
mIntroTwins_convo_queue = {
--[[start_drive_queue = {
{ delay = 2.0, convo = mIntroTwins_convo.goto_first_checkpoint_nav },
{ delay = 4.0, convo = mIntroTwins_convo.goto_first_checkpoint_nav2 },
{ delay = 3.0, convo = mIntroTwins_convo.goto_first_checkpoint_nav3 },
{ delay = 5.0, convo = mIntroTwins_convo.goto_first_checkpoint_nav4 }
},
]]--
}
--------------------------------------------------------------------------------------------------
--[[
_______ _
|__ __| (_)
| |_ __ _ __ _ __ _ ___ _ __ ___
| | '__| |/ _` |/ _` |/ _ \ '__/ __|
| | | | | (_| | (_| | __/ | \__ \
|_|_| |_|\__, |\__, |\___|_| |___/
__/ | __/ |
|___/ |___/
]]--
--------------------------------------------------------------------------------------------------
mIntroTwins_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 = "mIntroTwins_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 = mIntroTwins_convo.convo_name -- play a conversation
-- (optional)next_trigger = "next_trigger_name" sets up next trigger when triggered (breadcrumbs)
--},
}
--------------------------------------------------------------------------------------------------
--[[ INTERROGATION DATA ]]--
--------------------------------------------------------------------------------------------------
--mIntroTwins_interrogate = {
-- leader = {
-- target = mIntroTwins_group.friendly_fire.owner,
-- persona = "Interrogation",
-- objective = "mIntroTwins_INTERROGATE_OWNER",
-- -- (optional)conversation = mIntroTwins_convo.convo_name -- play a conversation while interrogating
-- },
--}
--------------------------------------------------------------------------------------------------
--[[
____ _ _
/ __ \| | | |
| | | | |_| |__ ___ _ __
| | | | __| '_ \ / _ \ '__|
| |__| | |_| | | | __/ |
\____/ \__|_| |_|\___|_|
]]--
--------------------------------------------------------------------------------------------------
mIntroTwins_homie = {
viola = "",
kiki = "",
}
mIntroTwins_tweakables = {
}
mIntroTwins_players = {}
mIntroTwins_runtime = {
cerberus_sam_complete = false,
}
mIntroTwins_VFX =
{
power_up = { name = "vfx_Altars_PowerUp", handle = "" },
}
--------------------------------------------------------------------------------------------------
--[[
_____ _ _ _ ______ _ _
/ ____| | | | | | | ____| | | (_)
| (___ | |_ __ _ _ __ __| | __ _ _ __ __| | | |__ _ _ _ __ ___| |_ _ ___ _ __ ___
\___ \| __/ _` | '_ \ / _` |/ _` | '__/ _` | | __| | | | '_ \ / __| __| |/ _ \| '_ \/ __|
____) | || (_| | | | | (_| | (_| | | | (_| | | | | |_| | | | | (__| |_| | (_) | | | \__ \
|_____/ \__\__,_|_| |_|\__,_|\__,_|_| \__,_| |_| \__,_|_| |_|\___|\__|_|\___/|_| |_|___/
]]--
-- 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 mIntroTwins_start(start_checkpoint_name, is_restart)
mission_start_fade_out(0.0)
-- initialize systems
mission_startup(mIntroTwins_trigger, mIntroTwins_convo) -- mIntroTwins_checkpoint
-- HVS_BDF: we don't necessarily want to call load_persona() because this creates a 2D
-- version, which can prevent actual in-game characters from lip syncing their VO if
-- the 2D persona was loaded prior to their character being spawned.
-- In the case of PC characters, they are present in the world and their characters should lip sync their VO.
--load_persona(mIntro_persona.Johnny)
--load_persona(mIntro_persona.Kinzie)
-- if using interrogations
--interrogate_startup(mIntroTwins_interrogate)
local start_cp = get_table_by_name(mIntroTwins_checkpoint, MISSION_START_CHECKPOINT)
-- TEMPORARY: give player approximate loadout of weapons & superpowers
-- TODO: remove this before the game ships!!!
--hvUnlockLoadout("mIntroTwins")
-- Check if this mission starting from the beginning
if (start_checkpoint_name == start_cp.name) then
if (is_restart == false and mIntroTwins_scene.intro ~= "") then
-- First time playing mission
local fade_in_after = false
audio_object_post_event("Play_IntroTwins_SamSFX")
cutscene_play(mIntroTwins_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
mIntroTwins_initialize(start_checkpoint_name)
-- Run the mission from the current checkpoint
checkpoint_run_mission(mIntroTwins_checkpoint, start_checkpoint_name)
mission_end_success("mIntroTwins") --, mIntroTwins_scene.outro, {"player_start_host", "player_start_client"})
end
-- This is the primary function responsible for cleaning up the entire mission
-- CALLED FROM CODE (+++MUST RETURN IMMEDIATELY+++)
--
function mIntroTwins_cleanup()
--[[ INSERT ANY MISSION SPECIFIC CLEAN-UP ]]--
-- cleanup all threads
cleanup_threads(mIntroTwins_thread)
-- run checkpoint cleanups (move into mission_shutdown?)
checkpoint_cleanup_mission(mIntroTwins_checkpoint)
-- cleanup triggers, convos, kill_list and interrogations
mission_shutdown()
-- cleanup all groups
cleanup_groups(mIntroTwins_group)
--return normal player jump/sprint values
notoriety_set_min_and_max("police", 0, MAX_NOTORIETY_LEVEL)
mIntroTwins_safe_thread_kill( mIntroTwins_group.vehicle_01.thread )
mIntroTwins_safe_thread_kill( mIntroTwins_group.vehicle_02.thread )
for i, player in pairs( mIntroTwins_players ) do
player_warp_to_shore_enable( player )
end
spawning_allow_cop_ambient_spawns(true)
on_seamless_animated_moment_end("")
seamless_animated_moment_cleanup()
if not mission_is_failed() then
player_unlock_super_power( SUPERPOWER_BLAST, LOCAL_PLAYER, true )
if coop_is_active() then
player_unlock_super_power( SUPERPOWER_BLAST, REMOTE_PLAYER, true )
end
end
end
-- Called when the mission has ended with success
-- CALLED FROM CODE (+++MUST RETURN IMMEDIATELY+++)
--
function mIntroTwins_success()
--[[ INSERT ANY MISSION SPECIFIC SUCCESS STUFF ]]--
-- Equip the superpower if we finished successfully
player_super_power_select( "freeze", SYNC_ALL, "blast_stone" )
end
--------------------------------------------------------------------------------------------------
--[[
_____ _ _ _ _ _ ______ _ _
|_ _| (_) | (_) | (_) | ____| | | (_)
| | _ __ _| |_ _ __ _| |_ _______ | |__ _ _ _ __ ___| |_ _ ___ _ __ ___
| | | '_ \| | __| |/ _` | | |_ / _ \ | __| | | | '_ \ / __| __| |/ _ \| '_ \/ __|
_| |_| | | | | |_| | (_| | | |/ / __/ | | | |_| | | | | (__| |_| | (_) | | | \__ \
|_____|_| |_|_|\__|_|\__,_|_|_/___\___| |_| \__,_|_| |_|\___|\__|_|\___/|_| |_|___/
]]--
-- Initialize the mission for the specified checkpoint
--
-- checkpoint_name: (string) Checkpoint to initialize the mission to
--
function mIntroTwins_initialize(checkpoint_name)
-- Common initialization
mIntroTwins_initialize_common()
-- Get the player names
mIntroTwins_players = player_names_get_all()
-- Checkpoint specific initialization
checkpoint_init(mIntroTwins_checkpoint, checkpoint_name)
-- Remove any present subtitles
message_remove_all()
-- Start fading in
mission_start_fade_in()
end
-- Handle any common initialization
--
function mIntroTwins_initialize_common()
--[[ INSERT ANY COMMON INITIALIZATION CODE HERE ]]--
notoriety_set_min_and_max("police", 0, 1)
spawning_allow_cop_ambient_spawns(false)
end
--------------------------------------------------------------------------------------------------
--[[
_____ _ _ _ _ ______ _ _
/ ____| | | | (_) | | | ____| | | (_)
| | | |__ ___ ___| | ___ __ ___ _ _ __ | |_ | |__ _ _ _ __ ___| |_ _ ___ _ __ ___
| | | '_ \ / _ \/ __| |/ / '_ \ / _ \| | '_ \| __| | __| | | | '_ \ / __| __| |/ _ \| '_ \/ __|
| |____| | | | __/ (__| <| |_) | (_) | | | | | |_ | | | |_| | | | | (__| |_| | (_) | | | \__ \
\_____|_| |_|\___|\___|_|\_\ .__/ \___/|_|_| |_|\__| |_| \__,_|_| |_|\___|\__|_|\___/|_| |_|___/
| |
|_|
]]--
--------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------
--[[
_ ___ _ _ _____
| |/ (_) | | | __ \
| ' / _| | | | | | | ___ _ __ ___ ___ _ __ ___
| < | | | | | | | |/ _ \ '_ ` _ \ / _ \| '_ \/ __|
| . \| | | | | |__| | __/ | | | | | (_) | | | \__ \
|_|\_\_|_|_| |_____/ \___|_| |_| |_|\___/|_| |_|___/
]]--
--------------------------------------------------------------------------------------------------
-- Initialize this checkpoint.
--
-- mission_start: (bool) Whether we're initializing from a mission (re)start or from
-- a natural play-through.
--
--
function mIntroTwins_sam_init(mission_start)
fade_out(0.0)
-- HVS_BDF: moved the spawning of the demons before Kiki and Viola, as there were
-- strange timing issues on the client that were causing certain demons to be
-- NULL during the prep and play phases.
group_create( mIntroTwins_group.SAM_Demon_01.name, true )
group_create( mIntroTwins_group.SAM_Demon_02.name, true )
group_create( mIntroTwins_group.SAM_Demon_03.name, true )
--Cerberus SAM
group_create( mIntroTwins_group.kiki_npc_combat.name, true )
turn_invulnerable( mIntroTwins_group.kiki_npc_combat.npcs[1] )
character_set_never_catch_fire(mIntroTwins_group.kiki_npc_combat.npcs[1])
group_create( mIntroTwins_group.viola_npc_combat.name, true )
turn_invulnerable( mIntroTwins_group.viola_npc_combat.npcs[1] )
character_set_never_catch_fire(mIntroTwins_group.viola_npc_combat.npcs[1])
on_seamless_animated_moment_end("SAM_Cerberus_complete")
local actor_list = { mIntroTwins_group.viola_npc_combat.viola, mIntroTwins_group.SAM_Demon_01.sam, mIntroTwins_group.SAM_Demon_02.sam, mIntroTwins_group.SAM_Demon_03.sam, LOCAL_PLAYER, mIntroTwins_group.kiki_npc_combat.kiki }
seamless_animated_moment_prep("SAM_Cerberus", actor_list)
seamless_animated_moment_start("SAM_Cerberus", actor_list)
audio_object_post_event("Play_IntroTwins_SamSFX")
audio_object_post_event("Play_TwinsMusic")
fade_in(0.2)
--Wait until the SAM has completed
while(mIntroTwins_runtime.cerberus_sam_complete == false) do
thread_yield()
end
on_seamless_animated_moment_end("")
end
-- The next objective
--
function mIntroTwins_sam_run()
objective_text_clear(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 mIntroTwins_sam_cleanup(mission_exit)
if mission_exit then
end
end
function mIntroTwins_kil_init(mission_start)
if mission_start then
group_create( mIntroTwins_group.kiki_npc_combat.name, true )
turn_invulnerable( mIntroTwins_group.kiki_npc_combat.npcs[1] )
character_set_never_catch_fire(mIntroTwins_group.kiki_npc_combat.npcs[1])
group_create( mIntroTwins_group.viola_npc_combat.name, true )
turn_invulnerable( mIntroTwins_group.viola_npc_combat.npcs[1] )
character_set_never_catch_fire(mIntroTwins_group.viola_npc_combat.npcs[1])
group_create( mIntroTwins_group.SAM_Demon_01.name, true )
group_create( mIntroTwins_group.SAM_Demon_02.name, true )
group_create( mIntroTwins_group.SAM_Demon_03.name, true )
audio_object_post_event("Play_TwinsMusic")
end
end
-- The next objective
--
function mIntroTwins_kil_run()
party_allow_max_followers(true)
mIntroTwins_setup_homies ( mIntroTwins_group.kiki_npc_combat )
set_suppress_synced_attacks_flag(mIntroTwins_group.kiki_npc_combat.kiki, true)
set_gibbable(mIntroTwins_group.kiki_npc_combat.kiki, false)
turn_invulnerable(mIntroTwins_group.kiki_npc_combat.kiki)
mIntroTwins_setup_homies ( mIntroTwins_group.viola_npc_combat )
set_suppress_synced_attacks_flag(mIntroTwins_group.viola_npc_combat.viola, true)
set_gibbable(mIntroTwins_group.viola_npc_combat.viola, false)
turn_invulnerable(mIntroTwins_group.viola_npc_combat.viola)
npc_leash_to_nav( mIntroTwins_homie.kiki, "leash_kiki", 75)
npc_leash_to_nav( mIntroTwins_homie.viola, "leash_viola", 75)
notoriety_set_min_and_max("police", 1, 1)
-- Disable warp to shore
for i, player in pairs( mIntroTwins_players ) do
player_warp_to_shore_disable( player )
end
-- if player is johnny, play johnny line. If not, play kinzie line
if character_get_anim_set(LOCAL_PLAYER) == "PLYM" then
convo_start(mIntroTwins_convo.Gat_Convo_A)
else
convo_start(mIntroTwins_convo.Kinzie_Convo_A)
end
--HVS_BAS - so we have an issue in coop that the remote player can leave the area, which is bad
--SO for coop, lets give him a follower so we cant just abandon them.
--also, we want to do this after all the flags and such are set, because
--we dont want to flood the network, since the remote player will own
--viola from here on out.
if coop_is_active() then
party_add(mIntroTwins_homie.viola, REMOTE_PLAYER)
else
party_add(mIntroTwins_homie.viola, LOCAL_PLAYER)
end
--WAVE 01
mIntroTwins_attack(mIntroTwins_group.w1_squad_01)
mIntroTwins_attack(mIntroTwins_group.w1_squad_03)
group_create( mIntroTwins_group.w1_squad_02.name, true )
--mIntroTwins_tank_start(mIntroTwins_group.tank_01)
objective_text( 0, "", "GM_INTRO_KILL_DEMONS", "", SYNC_ALL, OI_ASSET_KILL )
kill_list_add( mIntroTwins_group.w1_squad_02.members, OI_ASSET_KILL )
kill_list_add( mIntroTwins_group.SAM_Demon_01.sam, OI_ASSET_KILL )
kill_list_add( mIntroTwins_group.SAM_Demon_02.sam, OI_ASSET_KILL )
kill_list_add( mIntroTwins_group.SAM_Demon_03.sam, OI_ASSET_KILL )
kill_list_wait_for_complete()
--WAVE 02
delay(3.5)
--group_create( mIntroTwins_group.w2_squad_01.name, true )
group_create( mIntroTwins_group.w2_squad_02.name, true )
group_create( mIntroTwins_group.w2_squad_04.name, true )
npc_leash_to_nav( mIntroTwins_group.w2_squad_02.members[1], "flight_nav<001>", 15.0)
npc_leash_to_nav( mIntroTwins_group.w2_squad_04.members[1], "flight_nav<002>", 15.0)
mIntroTwins_attack(mIntroTwins_group.w2_squad_03)
--kill_list_add( mIntroTwins_group.w2_squad_01.members, OI_ASSET_KILL )
kill_list_add( mIntroTwins_group.w2_squad_02.members, OI_ASSET_KILL )
kill_list_add( mIntroTwins_group.w2_squad_04.members, OI_ASSET_KILL )
delay(2.5)
mIntroTwins_vehicle_start(mIntroTwins_group.vehicle_01)
kill_list_wait_for_complete()
--WAVE 03
-- if player is johnny, play johnny line. If not, play kinzie line
if character_get_anim_set(LOCAL_PLAYER) == "PLYM" then
convo_start(mIntroTwins_convo.Gat_Convo_B)
else
convo_start(mIntroTwins_convo.Kinzie_Convo_B)
end
convo_wait_for_end()
group_create( mIntroTwins_group.w3_squad_01.name, true )
group_create( mIntroTwins_group.w3_squad_02.name, true )
npc_leash_to_nav( mIntroTwins_group.w3_squad_01.members[1], "flight_nav<003>", 15.0)
npc_leash_to_nav( mIntroTwins_group.w3_squad_02.members[1], "flight_nav<004>", 15.0)
kill_list_add( mIntroTwins_group.w3_squad_01.members, OI_ASSET_KILL )
kill_list_add( mIntroTwins_group.w3_squad_02.members, OI_ASSET_KILL )
delay(2.0)
mIntroTwins_vehicle_start(mIntroTwins_group.vehicle_02)
kill_list_wait_for_complete()
--WAVE 04
group_create( mIntroTwins_group.w4_boss_01.name, true )
kill_list_add( mIntroTwins_group.w4_boss_01.members, OI_ASSET_KILL_FULL )
mIntroTwins_attack(mIntroTwins_group.w4_squad_01)
mIntroTwins_attack(mIntroTwins_group.w4_squad_02)
kill_list_wait_for_complete()
delay(1.0)
objective_text_clear(0)
-- if player is johnny, play johnny line. If not, play kinzie line
if character_get_anim_set(LOCAL_PLAYER) == "PLYM" then
convo_start(mIntroTwins_convo.Gat_End)
else
convo_start(mIntroTwins_convo.Kinzie_End)
end
convo_wait_for_end()
player_controls_disable(LOCAL_PLAYER)
if coop_is_active() then
player_controls_enable(REMOTE_PLAYER)
end
cutscene_play(mIntroTwins_scene.outro, nil, {"player_start_host", "player_start_client"}, true )
teleport( mIntroTwins_homie.kiki, "kiki_nav")
teleport( mIntroTwins_homie.viola, "viola_nav")
npc_leash_remove( mIntroTwins_homie.kiki )
npc_leash_remove( mIntroTwins_homie.viola )
npc_leash_to_nav( mIntroTwins_homie.kiki, "kiki_nav", 1)
npc_leash_to_nav( mIntroTwins_homie.viola, "viola_nav", 1)
party_dismiss(mIntroTwins_homie.kiki)
party_dismiss(mIntroTwins_homie.viola)
if cutscene_check_exiting() then
thread_yield()
end
convo_start(mIntroTwins_convo.Grant_Power)
delay(2.5)
-- Have player(s) fully power up (non-blocking)
local anim_name = "altars_powerup"
local morph_name = anim_name
local force_play = false
local stand_still = true
local zero_movement = true
effect_play_on_human( mIntroTwins_VFX.power_up.name, LOCAL_PLAYER, "spine2" )
action_play_non_blocking(LOCAL_PLAYER, anim_name, morph_name, force_play, stand_still, zero_movement, "player_start_host" )
if coop_is_active() then
effect_play_on_human( mIntroTwins_VFX.power_up.name, REMOTE_PLAYER, "spine2" )
action_play_non_blocking(REMOTE_PLAYER, anim_name, morph_name, force_play, stand_still, zero_movement, "player_start_client" )
end
-- Wait for player to react
delay(6)
fade_out(1)
fade_out_block()
player_super_power_select( "freeze", SYNC_ALL, "blast_stone" )
force_spawn_contacts()
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 mIntroTwins_kil_cleanup(mission_exit)
if mission_exit then
mIntroTwins_cleanup_homies()
party_allow_max_followers(false)
--player_unlock_element( PLAYER_SUPERPOWER_BLAST_STONE )
player_super_attacks_enable( true )
end
end
------------------------------------
--
-- Checkpoint helper functions
--
------------------------------------
function mIntroTwins_tank_start(group_table)
vehicle_enter_group_teleport(group_table.members, group_table.vehicle)
group_show(group_table.name, true)
group_table.thread = thread_new( "mIntroTwins_tank" , group_table)
kill_list_add( group_table.members, OI_ASSET_KILL)
end
function mIntroTwins_vehicle_start(group_table)
vehicle_enter_group_teleport(group_table.members, group_table.vehicle)
group_show(group_table.name, true)
group_table.thread = thread_new( "mIntroTwins_vehicle" , group_table)
kill_list_add( group_table.members, OI_ASSET_KILL)
end
------------------------------------
--
-- Checkpoint callback functions
--
------------------------------------
function SAM_Cerberus_complete()
mIntroTwins_runtime.cerberus_sam_complete = true
end
------------------------------------
--
-- Checkpoint thread functions
--
------------------------------------
function mIntroTwins_tank(car_table)
local use_navmesh = true
vehicle_pathfind_to(car_table.vehicle, car_table.path, use_navmesh)
end
function mIntroTwins_vehicle(car_table)
local use_navmesh = true
vehicle_max_speed(car_table.vehicle, 60)
vehicle_pathfind_to(car_table.vehicle, car_table.path, use_navmesh)
vehicle_exit_group(car_table.members)
end
--------------------------------------------------------------------------------------------------
--[[
_____ ______ _ _
/ ____| | ____| | | (_)
| | ___ _ __ ___ _ __ ___ ___ _ __ | |__ _ _ _ __ ___| |_ _ ___ _ __ ___
| | / _ \| '_ ` _ \| '_ ` _ \ / _ \| '_ \ | __| | | | '_ \ / __| __| |/ _ \| '_ \/ __|
| |___| (_) | | | | | | | | | | | (_) | | | | | | | |_| | | | | (__| |_| | (_) | | | \__ \
\_____\___/|_| |_| |_|_| |_| |_|\___/|_| |_| |_| \__,_|_| |_|\___|\__|_|\___/|_| |_|___/
]]--
function mIntroTwins_setup_homies ( homie_group )
if homie_group.kiki ~= nil and homie_group.kiki ~= "" then
mIntroTwins_homie.kiki = homie_group.kiki
party_add(mIntroTwins_homie.kiki, LOCAL_PLAYER)
follower_set_can_abandon( mIntroTwins_homie.kiki, true )
on_death ( "mIntroTwins_failure_kiki_died_cb", mIntroTwins_homie.kiki )
on_dismiss ( "mIntroTwins_failure_dismissed_cb", mIntroTwins_homie.kiki )
party_set_dismissable(false)
--npc_super_powers_enable(mIntroTwins_homie.kiki)
--ai_set_super_attack_cool_down(mIntroTwins_homie.kiki,20)
--ai_set_preferred_super_attack(mIntroTwins_homie.kiki,"super energy blast")
end
if homie_group.viola ~= nil and homie_group.viola ~= "" then
mIntroTwins_homie.viola = homie_group.viola
follower_set_can_abandon( mIntroTwins_homie.viola, true )
on_death ( "mIntroTwins_failure_viola_died_cb", mIntroTwins_homie.viola )
on_dismiss ( "mIntroTwins_failure_dismissed_cb", mIntroTwins_homie.viola )
party_set_dismissable(false)
--npc_super_powers_enable(mIntroTwins_homie.viola)
--ai_set_super_attack_cool_down(mIntroTwins_homie.viola,20)
--ai_set_preferred_super_attack(mIntroTwins_homie.viola,"super energy blast")
end
end
function mIntroTwins_cleanup_homies()
if mIntroTwins_homie.kiki ~= nil and mIntroTwins_homie.kiki ~= "" then
on_death("", mIntroTwins_homie.kiki)
on_dismiss("", mIntroTwins_homie.kiki)
end
if mIntroTwins_homie.viola ~= nil and mIntroTwins_homie.viola ~= "" then
on_death("", mIntroTwins_homie.viola)
on_dismiss("", mIntroTwins_homie.viola)
end
end
--Reinforcement spawn
function mIntroTwins_attack(group)
local block = true
local should_run = true
local should_fire = false
group_create( group.name, true, block )
for index, npc in pairs( group.members ) do
ai_do_scripted_move( npc, group.destination, should_run, should_fire )
kill_list_add( group.members, OI_ASSET_KILL)
end
end
--Thread Killer
function mIntroTwins_safe_thread_kill( thread )
if( thread ~= nil ) then
if( thread ~= INVALID_THREAD_HANDLE) then
thread_kill( thread )
thread = INVALID_THREAD_HANDLE
end
end
end
--------------------------------------------------------------------------------------------------
--[[
_____ _ _ _ _ ______ _ _
/ ____| | | | | | | | ____| | | (_)
| | __ _| | | |__ __ _ ___| | __ | |__ _ _ _ __ ___| |_ _ ___ _ __ ___
| | / _` | | | '_ \ / _` |/ __| |/ / | __| | | | '_ \ / __| __| |/ _ \| '_ \/ __|
| |___| (_| | | | |_) | (_| | (__| < | | | |_| | | | | (__| |_| | (_) | | | \__ \
\_____\__,_|_|_|_.__/ \__,_|\___|_|\_\ |_| \__,_|_| |_|\___|\__|_|\___/|_| |_|___/
]]--
function mIntroTwins_failure_kiki_died_cb()
mission_end_failure("mIntroTwins", "GM_INTROTWINS_FAIL_KIKI_DIED")
end
function mIntroTwins_failure_viola_died_cb()
mission_end_failure("mIntroTwins", "GM_INTROTWINS_FAIL_VIOLA_DIED")
end
function mIntroTwins_failure_dismissed_cb()
mission_end_failure("mIntroTwins", "GM_INTROTWINS_FAIL_TWIN_DIS")
end
--------------------------------------------------------------------------------------------------
--[[
_______ _ _ ______ _ _
|__ __| | | | | ____| | | (_)
| | | |__ _ __ ___ __ _ __| | | |__ _ _ _ __ ___| |_ _ ___ _ __ ___
| | | '_ \| '__/ _ \/ _` |/ _` | | __| | | | '_ \ / __| __| |/ _ \| '_ \/ __|
| | | | | | | | __/ (_| | (_| | | | | |_| | | | | (__| |_| | (_) | | | \__ \
|_| |_| |_|_| \___|\__,_|\__,_| |_| \__,_|_| |_|\___|\__|_|\___/|_| |_|___/
]]--