--[[
m11.lua
SR3 Mission Script
DATE: 8/9/2010
AUTHOR: Albert McDaniel & Darryl Davis
]]--
-- Debug flags --
-- Tweakable Parameters --
-- Groups --
M11_groups = {
vehicle_start = {
name = "grp_veh_start",
vehicles = { "veh_start" }
},
vehicle_cp = {
name = "grp_veh_cp",
vehicles = { "veh_cp_vtol 001", "veh_cp_vtol 002" },
},
stag_bases = {
-- Base 1 (the hijacking objective)
{
name = "sb 001",
npcs = {
"n_sb1_grunt 001", "n_sb1_grunt 002", "n_sb1_grunt 003", "n_sb1_grunt 004",
"n_sb1_grunt 006", "n_sb1_grunt 008", "n_sb1_grunt 009", "n_sb1_grunt 010",
"n_sb1_grunt 011", "n_sb1_grunt 014", "n_sb1_grunt 015", "n_sb1_grunt 016",
"n_sb1_grunt 017", "n_sb1_grunt 018", "n_sb1_grunt 019", "n_sb1_grunt 020",
"n_sb1_grunt 021", "n_sb1_grunt 022", "n_sb1_grunt 023",
},
boxes = {
{ name = "mov_sb1_battlebox 001", destroyed = false },
{ name = "mov_sb1_battlebox 002", destroyed = false },
{ name = "mov_sb1_battlebox 003", destroyed = false },
{ name = "mov_sb1_battlebox 004", destroyed = false },
{ name = "mov_sb1_battlebox 005", destroyed = false },
{ name = "mov_sb1_battlebox 006", destroyed = false },
},
vehicle_group = "sb 001 vehicles",
vehicles_created = false,
vtols = {
name = "sb 001 vtols",
save = false,
vehicles = { "v_sb1_vtol 001", "v_sb1_vtol 002" },
},
nav = "nav_sb1",
location = "t_sb1_location",
zone = "t_sb1_zone",
restricted = "t_sb1_restricted",
destroyed = false,
},
-- Base 2
{
name = "sb 002",
npcs = {
"n_sb2_grunt 001", "n_sb2_grunt 002", "n_sb2_grunt 003", "n_sb2_grunt 004",
"n_sb2_grunt 005", "n_sb2_grunt 006", "n_sb2_grunt 007", "n_sb2_grunt 008",
"n_sb2_grunt 009", "n_sb2_grunt 010", "n_sb2_grunt 011", "n_sb2_grunt 012",
"n_sb2_grunt 013", "n_sb2_grunt 014", "n_sb2_grunt 015",
},
boxes = {
{ name = "mov_sb2_battlebox 001", destroyed = false },
{ name = "mov_sb2_battlebox 002", destroyed = false },
{ name = "mov_sb2_battlebox 003", destroyed = false },
{ name = "mov_sb2_battlebox 004", destroyed = false },
{ name = "mov_sb2_battlebox 005", destroyed = false },
{ name = "mov_sb2_battlebox 006", destroyed = false },
},
vehicle_group = "sb 002 vehicles",
vehicles_created = false,
vtols = {
name = "sb 002 vtols",
save = false,
vehicles = { "v_sb2_vtol 001", "v_sb2_vtol 002" },
},
script = {
name = "sb 002 script",
trigger = "t_sb2_script",
vehicles = {
{ name = "v_sb2_vtol 003", pilot = "n_sb2_pilot<001>", nav = "nav_sb2_lift<001>" },
{ name = "v_sb2_vtol 004", pilot = "n_sb2_pilot<002>", nav = "nav_sb2_lift<002>" },
{ name = "v_sb2_vtol 005", pilot = "n_sb2_pilot<003>", nav = { "nav_sb2_land<001>", "nav_sb2_land<002>" }, },
},
},
nav = "nav_sb2",
location = "t_sb2_location",
zone = "t_sb2_zone",
destroyed = false,
},
-- Base 3
{
name = "sb 003",
npcs = {
"n_sb3_grunt 001", "n_sb3_grunt 002", "n_sb3_grunt 003", "n_sb3_grunt 004",
"n_sb3_grunt 005", "n_sb3_grunt 006", "n_sb3_grunt 007", "n_sb3_grunt 008",
"n_sb3_grunt 009", "n_sb3_grunt 010", "n_sb3_grunt 011",
},
boxes = {
{ name = "mov_sb3_battlebox 001", destroyed = false },
{ name = "mov_sb3_battlebox 002", destroyed = false },
{ name = "mov_sb3_battlebox 003", destroyed = false },
{ name = "mov_sb3_battlebox 004", destroyed = false },
{ name = "mov_sb3_battlebox 005", destroyed = false },
{ name = "mov_sb3_battlebox 006", destroyed = false },
},
vehicle_group = "sb 003 vehicles",
vehicles_created = false,
vtols = {
name = "sb 003 vtols",
save = false,
vehicles = { "v_sb3_vtol 001"},
},
nav = "nav_sb3",
location = "t_sb3_location",
zone = "t_sb3_zone",
destroyed = false,
},
-- Base 5
{
name = "sb 005",
npcs = {
"n_sb5_grunt 001", "n_sb5_grunt 002", "n_sb5_grunt 003", "n_sb5_grunt 004", "n_sb5_grunt 005",
"n_sb5_grunt 006", "n_sb5_grunt 007", "n_sb5_grunt 008", "n_sb5_grunt 009",
"n_sb5_sniper 001", "n_sb5_sniper 002", "n_sb5_sniper 003", "n_sb5_sniper 004"
},
boxes = {
{ name = "mov_sb5_battlebox 001", destroyed = false },
{ name = "mov_sb5_battlebox 002", destroyed = false },
{ name = "mov_sb5_battlebox 003", destroyed = false },
{ name = "mov_sb5_battlebox 004", destroyed = false },
},
vtols = {
name = "sb 005 vtols",
save = false,
vehicles = { "v_sb5_vtol 001", "v_sb5_vtol 002" },
},
nav = "nav_sb5",
location = "t_sb5_location",
zone = "t_sb5_zone",
destroyed = false,
},
},
roadblocks = {
{
name = "rb 001",
npcs = {
"n_rb1_stag 001", "n_rb1_stag 002", "n_rb1_stag 003", "n_rb1_stag 004", "n_rb1_stag 005", "n_rb1_stag 006",
"n_rb1_stag 007", "n_rb1_stag 008", "n_rb1_stag 009", "n_rb1_stag 010", "n_rb1_stag 011", "n_rb1_stag 012",
"n_rb1_stag 013", "n_rb1_stag 014"
},
vehicles = {
"v_rb1_apc 001", "v_rb1_apc 002", "v_rb1_apc 003", "v_rb1_apc 004", "v_rb1_apc 005", "v_rb1_apc 006",
"v_rb1_tank 001", "v_rb1_tank 002", "v_rb1_tank 003", "v_rb1_tank 004"
},
tanks = {
{ name = "v_rb1_tank 001", driver = "n_rb1_stag 001" },
{ name = "v_rb1_tank 002", driver = "n_rb1_stag 002" },
{ name = "v_rb1_tank 003", driver = "n_rb1_stag 013" },
{ name = "v_rb1_tank 004", driver = "n_rb1_stag 012" },
},
convoy = {
pierce = "n_rb1_pierce",
-- convoy vehicles, followed by an array of who goes in that vehicle
vehicles = {
{ name = "v_rb1_convoy 001", passengers = { "n_rb1_pierce" }, },
{ name = "v_rb1_convoy 002", passengers = { "n_rb1_saint 001" }, },
{ name = "v_rb1_truck 001", passengers = { "n_rb1_saint 002" }, },
{ name = "v_rb1_truck 002", passengers = { "n_rb1_saint 003" }, },
},
},
location = "t_rb1_location",
destroyed = false,
},
},
air_base = {
name = "grp_sba",
npcs = { "n_sba 001", "n_sba 002", "n_sba 003",
--"n_sba 004", "n_sba 005", "n_sba 006",
"n_sba 007", "n_sba 008", "n_sba 009",
--"n_sba 010", "n_sba 011"
},
vehicles = { --"v_sba 001",
"v_sba 002", "v_sba 003",
--"v_sba 004", "v_sba 005", "v_sba 006",
"v_sba_target 002", "v_sba_target 003",
--"v_sba_target 004", "v_sba_target 005"
},
guards = {
--{ vehicle = "v_sba 001", pilot = "n_sba 001", path = "p_sba 001" },
{ vehicle = "v_sba 002", pilot = "n_sba 002", path = "p_sba 004" },
{ vehicle = "v_sba 003", pilot = "n_sba 003", path = "p_sba 005" },
--[[
{ vehicle = "v_sba 004", pilot = "n_sba 004", path = "p_sba 004" },
{ vehicle = "v_sba 005", pilot = "n_sba 005", path = "p_sba 005" },
{ vehicle = "v_sba 006", pilot = "n_sba 006", path = "p_sba 001" },
--]]
},
targets = {
{ vehicle = "v_sba_target 002", pilot = "n_sba 008", path = "p_sba 002" },
{ vehicle = "v_sba_target 003", pilot = "n_sba 009", path = "p_sba 003" },
--[[
{ vehicle = "v_sba_target 004", pilot = "n_sba 010", path = "p_sba 002" },
{ vehicle = "v_sba_target 005", pilot = "n_sba 011", path = "p_sba 003" },
--]]
},
final_plane = { vehicle = "v_sba_target 001", pilot = "n_sba 007", path = "p_sba 001" },
},
air_base_jumbo_plane = {
name = "grp_sba_jumbo_plane",
vehicles = { "v_sba_target 001" },
},
oleg_battle = {
location = "t_oleg_battle",
nav = { "nav_ob_stag_n 001", "nav_ob_stag_n 002" },
nav_vtol = { "nav_ob_stag_v 001", "nav_ob_stag_v 002" },
dest = { "nav_ob_stag_n_dest 001", "nav_ob_stag_n_dest 002", },
oleg = {
name = "grp_oleg",
oleg = "n_oleg",
},
oleg_vtols = {
name = "grp_oleg_vtols",
save = false,
vtols = { "veh_oleg_vtol<001>", "veh_oleg_vtol<002>" },
},
tank1 = {
name = "oleg tanks",
vehicle = "v_ob_tank 002",
members = { "n_ob_stag_t 001"},
dest = "nav_tank_spline 001",
move_thread = INVALID_THREAD_HANDLE,
},
tank2 = {
name = "oleg tanks2",
vehicle = "v_ob_tank 003",
members = { "n_ob_stag_t 002"},
dest = "nav_tank_spline 002",
move_thread = INVALID_THREAD_HANDLE,
},
tank3 = {
name = "oleg tanks3",
vehicle = "v_ob_tank 004",
members = { "n_ob_stag_t 003"},
dest = "nav_tank_spline 003",
move_thread = INVALID_THREAD_HANDLE,
},
waves = {
{
name = "oleg_battle 001",
vehicles = {
{ name = "v_ob_apc 001" },
{ name = "v_ob_apc 002" },
{ name = "v_ob_apc 003" },
},
npcs = {
"n_ob_stag 001", "n_ob_stag 002", "n_ob_stag 003", "n_ob_stag 005", "n_ob_stag 006", "n_ob_stag 007", "n_ob_stag 008",
},
-- tanks = {
-- { name = "v_ob_tank 002", driver = "n_ob_stag_t 001", dest = "nav_dest_tank 001" },
-- { name = "v_ob_tank 003", driver = "n_ob_stag_t 002", dest = "nav_dest_tank 002" },
-- { name = "v_ob_tank 004", driver = "n_ob_stag_t 003", dest = "nav_dest_tank 003" },
-- },
},
{
name = "oleg_battle 002",
vehicles = {
{ name = "v_ob_apc 004", members = { "n_ob_stag 013", "n_ob_stag 014", "n_ob_stag 015", "n_ob_stag 016", } },
{ name = "v_ob_apc 005", members = { "n_ob_stag 017", "n_ob_stag 018", "n_ob_stag 019", "n_ob_stag 020", } },
},
},
{
name = "oleg_battle_vtols 002",
vehicles = {
{ name = "v_ob_vtol 001", driver = "n_ob_vpilot 001" },
{ name = "v_ob_vtol 002", driver = "n_ob_vpilot 002" },
},
},
--{
--name = "oleg_battle 003",
--vehicles = {
-- { name = "v_ob_tank 002", driver = "n_ob_stag_t 001", gunner = "n_ob_stag_t 002" },
--},
--},
},
},
}
oleg_tanks = { M11_groups.oleg_battle.tank1, M11_groups.oleg_battle.tank2, M11_groups.oleg_battle.tank3 }
-- Navpoints --
M11_navpoints = {
start_local = "nav_start_local",
start_remote = "nav_start_remote",
end_local = "nav_end_local",
end_remote = "nav_end_remote",
}
-- Threads --
M11_threads = {
stag_attention = nil,
pilots = {
[1] = INVALID_THREAD_HANDLE,
[2] = INVALID_THREAD_HANDLE,
[3] = INVALID_THREAD_HANDLE,
},
battle = {
[1] = INVALID_THREAD_HANDLE,
[2] = INVALID_THREAD_HANDLE,
[3] = INVALID_THREAD_HANDLE,
[4] = INVALID_THREAD_HANDLE,
[5] = INVALID_THREAD_HANDLE,
},
fly_guard = {
[1] = INVALID_THREAD_HANDLE,
[2] = INVALID_THREAD_HANDLE,
[3] = INVALID_THREAD_HANDLE,
[4] = INVALID_THREAD_HANDLE,
[5] = INVALID_THREAD_HANDLE,
[6] = INVALID_THREAD_HANDLE,
},
fly_target = {
[1] = INVALID_THREAD_HANDLE,
[2] = INVALID_THREAD_HANDLE,
[3] = INVALID_THREAD_HANDLE,
[4] = INVALID_THREAD_HANDLE,
[5] = INVALID_THREAD_HANDLE,
},
fly_final_plane = INVALID_THREAD_HANDLE,
local_player_vtol_health = INVALID_THREAD_HANDLE,
remote_player_vtol_health = INVALID_THREAD_HANDLE,
radio_chatter = INVALID_THREAD_HANDLE,
convoy_cleanup = INVALID_THREAD_HANDLE,
intro_convos = INVALID_THREAD_HANDLE,
air_base_convos = INVALID_THREAD_HANDLE,
}
-- Checkpoints --
M11_checkpoints = {
start = MISSION_START_CHECKPOINT,
destroy_bases = "destroy_bases",
roadblock12 = "roadblock12",
roadblock13 = "roadblock13",
roadblock14 = "roadblock14",
roadblock23 = "roadblock23",
roadblock24 = "roadblock24",
roadblock34 = "roadblock34",
oleg_battle = "oleg_battle",
air_base = "air_base",
}
-- Cutscenes --
M11_cutscenes = {
intro = "11_in",
outro = "11_out",
}
M11_personas = {
oleg = {
name = "Oleg",
handle = INVALID_PERSONA_HANDLE,
},
pierce = {
name = "Pierce",
handle = INVALID_PERSONA_HANDLE,
},
stag_am = {
name = "STAG_AM",
handle = INVALID_PERSONA_HANDLE,
},
stag_bm = {
name = "STAG_BM",
handle = INVALID_PERSONA_HANDLE,
},
stag_wf = {
name = "STAG_WF",
handle = INVALID_PERSONA_HANDLE,
},
stag_wm = {
name = "STAG_WM",
handle = INVALID_PERSONA_HANDLE,
},
cyrus = {
name = "Cyrus",
handle = INVALID_PERSONA_HANDLE,
},
kia = {
name = "Kia",
handle = INVALID_PERSONA_HANDLE,
},
interrogation = {
name = "Interrogation",
handle = INVALID_PERSONA_HANDLE,
},
}
M11_stag_personas = { M11_personas.stag_am, M11_personas.stag_bm, M11_personas.stag_wf, M11_personas.stag_wm }
--- Lines ---
M11_lines = {
vtol_steal = "M11_Vtol_Steal",--
arrive_at_first_base = "M11_Arriving_At_First_Base",--
vtols_are_cool = "M11_VTOLs_Are_Cool",--
inside_vtol = "M11_Inside_VTOL",--
jet_mode = "M11_Jet_Mode_Awesomeness",--
vtol_damaged = "M11_Need_New_VTOL_01",--
vtol_very_damaged = "M11_Need_New_VTOL_02",--
get_to_base = "M11_Get_To_A_Base",--
roadblock_start = "M11_Roadblock_01",--
roadblock_finish = "M11_Roadblock_Thanks_01",--
after_takeoff1 = "M11_STAG_Convo_After_Takeoff_01a",--
after_takeoff2 = "M11_STAG_Convo_After_Takeoff_02",--
fight_at_park = "M11_Fight_At_Park_03",--
stag_chatter = "M11_Stag_Radio_Chatter",--
air_base = "M11_STAG_Convo_To_Air_Base_03",--
random_lines = {
lines = {
{
name = "M11_STAG_Attention_01",
persona = M11_personas.pierce,
played = false,
},
{
name = "M11_STAG_Attention_02",
persona = M11_personas.pierce,
played = false,
},
{
name = "M11_Oleg_Is_Attacking_01",
persona = M11_personas.stag_wf,
played = false,
},
{
name = "M11_Oleg_Is_Attacking_02",
persona = M11_personas.stag_wf,
played = false,
},
{
name = "M11_Cyrus_Warns_Bases",
persona = M11_personas.cyrus,
played = false,
},
{
name = "M11_Cyrus_Lookout_For_Convoy",
persona = M11_personas.cyrus,
played = false,
},
{
name = "M11_Cyrus_Reports_Of_Convoy",
persona = M11_personas.cyrus,
played = false,
},
{
name = "M11_Cyrus_Park_Is_Diversion",
persona = M11_personas.cyrus,
played = false,
},
{
name = "M11_Cyrus_Generic_Orders_01",
persona = M11_personas.cyrus,
played = false,
},
{
name = "M11_Cyrus_Generic_Orders_02",
persona = M11_personas.cyrus,
played = false,
},
{
name = "M11_Cyrus_Generic_Orders_03",
persona = M11_personas.cyrus,
played = false,
},
{
name = "M11_Cyrus_Generic_Orders_04",
persona = M11_personas.cyrus,
played = false,
},
{
name = "M11_Kia_Bring_Down_VTOL_Order",
persona = M11_personas.kia,
played = false,
},
{
name = "M11_Kia_Warns_Bases",
persona = M11_personas.kia,
played = false,
},
{
name = "M11_Kia_Set_Up_Roadblocks",
persona = M11_personas.kia,
played = false,
},
{
name = "M11_Kia_Focus_Fire_On_VTOL",
persona = M11_personas.kia,
played = false,
},
{
name = "M11_Kia_Prepare_For_Support",
persona = M11_personas.kia,
played = false,
},
{
name = "M11_Kia_Generic_Orders_01",
persona = M11_personas.kia,
played = false,
},
{
name = "M11_Kia_Generic_Orders_02",
persona = M11_personas.kia,
played = false,
},
{
name = "M11_Kia_Generic_Orders_03",
persona = M11_personas.kia,
played = false,
},
},
num_lines = 20,
num_played = 0,
}
}
-- Conversations --
M11_conv = {
start = {--
name = "M11_Mission_Start",
handle = INVALID_CONVERSATION_HANDLE,
},
pack = {--
name = "M11_Drive_1",
handle = INVALID_CONVERSATION_HANDLE,
},
to_vtols = {--
name = "M11_Get_To_VTOL",
handle = INVALID_CONVERSATION_HANDLE,
},
convoy_start = {--
name = "M11_Convoy_Start",
handle = INVALID_CONVERSATION_HANDLE,
},
call_plane = {--
name = "M11_Call_In_Plane",
handle = INVALID_CONVERSATION_HANDLE,
},
oleg_help = {--
name = "M11_Oleg_Help",
handle = INVALID_CONVERSATION_HANDLE,
},
oleg_arrive = {--
name = "M11_Arrive_At_Park",
handle = INVALID_CONVERSATION_HANDLE,
},
reinforcements = {--
name = "M11_Air_Reinforcement",
handle = INVALID_CONVERSATION_HANDLE,
},
awacs = {--
name = "M11_On_Way_To_AWACS",
handle = INVALID_CONVERSATION_HANDLE,
play = false,
kill = false,
},
air_base = {--
name = "M11_STAG_Convo_Air_Base",
handle = INVALID_CONVERSATION_HANDLE,
},
killing_escorts = {--
name = "M11_Killing_Escort_Crafts_1",
handle = INVALID_CONVERSATION_HANDLE,
play = false,
kill = false,
},
kill_plane = {--
name = "M11_Hurry_Kill_Plane",
handle = INVALID_CONVERSATION_HANDLE,
},
pierce_end = {--
name = "M11_Pierce_End",
handle = INVALID_CONVERSATION_HANDLE,
},
}
M11_audio_emitters = {
alarm = "M11_alarm_a",
}
-- These emitters are automatically stopped at the end of the mission.
M11_temporary_audio_emitters = { M11_audio_emitters.alarm, }
-- Other --
M11_globals = {
-- Objective flags
vtol_hijacked = false,
objective_reached = false,
-- STAG progress
stag_attention = {
max_value = 1.0,
value = 1.0,
diminish_rate = 3,
diminish_value = 0.02,
target_value = 0.20,
first_warning = false,
second_warning = false,
third_warning = false,
},
air_base_time = 240000,
warn_time = 120000,
num_bases_destroyed = 0,
num_bases_destroyed_goal = 0,
first_base_destroyed = false,
third_base_destroyed = false,
num_guards = 0,
num_targets = 0,
num_transports = 0,
final_plane_alive = false,
final_targets_attack = false,
local_vtol_jet = false,
local_vtol_hover = false,
remote_vtol_jet = false,
remote_vtol_hover = false,
playing_line = false,
ped_density = 0.1,
vehicle_density = 0.25,
cell_call_finished = true,
cur_cell_call = "",
}
M11_triggers = {
traffic_rb = "tgr_traffic_rb1 001",
}
-- *************************
--
-- 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
--
-- m11_checkpoint: The checkpoint the mission should begin at
-- is_restart: TRUE if the mission is restarting, FALSE otherwise
--
function m11_start(m11_checkpoint, is_restart)
-- Debug checkpoint override
--m11_checkpoint = M11_checkpoints.oleg_battle
-- Check if this mission starting from the beginning
if (m11_checkpoint == M11_checkpoints.start) then
if (is_restart == false) then
-- First time playing mission
-- TODO: Play an intro cutscene
if (M11_cutscenes.intro ~= "") then
cutscene_play(M11_cutscenes.intro, nil, {M11_navpoints.start_local, M11_navpoints.start_remote}, false)
end
end
fade_out(0)
end
-- Handle mission initialization for the current checkpoint
m11_initialize(m11_checkpoint, is_restart)
-- Run the mission from the current checkpoint
m11_run(m11_checkpoint)
end
-- This is the primary function responsible for running the entire mission from start to finish.
--
-- first_checkpoint: The first checkpoint to begin running the mission at
--
function m11_run(first_checkpoint)
local current_checkpoint = first_checkpoint
-- Run the mission from the beginning
if (current_checkpoint == M11_checkpoints.start) then
-- OBJECTIVE: Get to the base
m11_go_to_first_base()
-- OBJECTIVE: Hijack a VTOL
m11_hijack_vtol()
-- Next checkpoint
current_checkpoint = M11_checkpoints.destroy_bases
mission_set_checkpoint(M11_checkpoints.destroy_bases, true)
end
-- Fake notoriety from here on
notoriety_set_can_decay(false)
notoriety_spawn_only_air(true)
notoriety_force_no_spawn("police", true)
notoriety_force_no_spawn("stag", true)
notoriety_set_min("police", 2)
hud_set_fake_notoriety("police", true, 5)
--lower ped density from here on out
set_ped_density(M11_globals.ped_density)
set_traffic_density(M11_globals.vehicle_density)
-- Start radio chatter thread
M11_globals.playing_line = false
M11_threads.radio_chatter = thread_new("m11_radio_chatter_thread")
-- Enable the STAG Attention bar
--m11_setup_stag_attention()
if (current_checkpoint == M11_checkpoints.destroy_bases) then
-- Start the Pierce phone call
M11_conv.convoy_start.handle = audio_conversation_load(M11_conv.convoy_start.name)
audio_conversation_play(M11_conv.convoy_start.handle)
-- OBJECTIVE: The players must destroy 2 bases to proceed
-- Have them kill one base, then we need to do some setup
M11_globals.num_bases_destroyed_goal = 1
m11_distract_stag()
-- Spawn the convoy group now, so that its good to go when we need it
group_create_hidden(M11_groups.roadblocks[1])
M11_globals.num_bases_destroyed_goal = 2
m11_distract_stag()
audio_conversation_wait_for_end(M11_conv.convoy_start.handle)
M11_conv.convoy_start.handle = INVALID_CONVERSATION_HANDLE
m11_wait_for_audio()
M11_globals.playing_line = true
audio_play_persona_line(LOCAL_PLAYER, M11_lines.get_to_base)
delay(3)
M11_globals.playing_line = false
-- Figure out the next checkpoint based on destroyed bases
current_checkpoint = m11_determine_checkpoint()
mission_set_checkpoint(current_checkpoint, true)
end
if ((current_checkpoint == M11_checkpoints.roadblock12) or (current_checkpoint == M11_checkpoints.roadblock13) or
(current_checkpoint == M11_checkpoints.roadblock14) or (current_checkpoint == M11_checkpoints.roadblock23) or
(current_checkpoint == M11_checkpoints.roadblock24) or (current_checkpoint == M11_checkpoints.roadblock34)) then
-- OBJECTIVE: Help Convoy
m11_help_convoy(M11_groups.roadblocks[1])
-- Re-enable STAG notoriety aircraft.
notoriety_force_no_spawn("stag", false)
-- Increase notoriety
notoriety_set_min("police", 4)
-- Pierce calls with the OK
m11_wait_for_audio()
M11_globals.playing_line = true
audio_play_persona_line_2d(M11_personas.pierce.handle, M11_lines.roadblock_finish)
delay(5)
M11_globals.playing_line = false
M11_conv.call_plane.handle = audio_conversation_load(M11_conv.call_plane.name)
audio_conversation_play(M11_conv.call_plane.handle)
audio_conversation_wait_for_end(M11_conv.call_plane.handle)
M11_conv.call_plane.handle = INVALID_CONVERSATION_HANDLE
-- OBJECTIVE: The players must destroy the remaining bases to proceed
M11_globals.num_bases_destroyed_goal = 4
m11_distract_stag()
-- Disable STAG notoriety aircraft again.
notoriety_force_no_spawn("stag", true)
-- Next checkpoint
current_checkpoint = M11_checkpoints.oleg_battle
mission_set_checkpoint(M11_checkpoints.oleg_battle, true)
end
-- Decrease notoriety
notoriety_set_min("police", 2)
notoriety_set_max("police", 2)
if (current_checkpoint == M11_checkpoints.oleg_battle) then
-- OBJECTIVE: Help Oleg
m11_help_oleg()
current_checkpoint = M11_checkpoints.air_base
mission_set_checkpoint(M11_checkpoints.air_base, true)
end
-- Slow the attention meter due to travel distance
--M11_globals.stag_attention.diminish_value = 0.015
-- Increase notoriety
notoriety_set_max("police", 4)
notoriety_set_min("police", 4)
if (current_checkpoint == M11_checkpoints.air_base) then
-- OBJECTIVE: Take out the Air Base
m11_air_base()
end
-- Stop the attention meter
--m11_remove_stag_attention()
-- End at Shaundi's ex's
-- Call mission success
mission_end_success("m11", M11_cutscenes.outro, {M11_navpoints.end_local, M11_navpoints.end_remote})
end
-- This is the primary function responsible for cleaning up the entire mission
-- CALLED FROM CODE (+++MUST RETURN IMMEDIATLY+++)
--
function m11_cleanup()
waypoint_remove(SYNC_ALL)
objective_text_clear(0)
m11_cleanup_hijack_vtol()
m11_cleanup_help_oleg()
-- Kill the HUD bar and threads
--m11_remove_stag_attention()
hud_timer_stop(1)
cleanup_threads(M11_threads)
-- Stop all conversations
for i, convo in pairs(M11_conv) do
if (convo.handle ~= INVALID_CONVERSATION_HANDLE) then
audio_conversation_end(convo.handle)
convo.handle = INVALID_CONVERSATION_HANDLE
end
end
-- Stop all temporary audio emitters
for i, emitter in pairs(M11_temporary_audio_emitters) do
audio_ambient_emitter_stop(emitter)
end
-- Unload personas
for i, persona in pairs(M11_personas) do
if (persona.handle ~= INVALID_PERSONA_HANDLE) then
audio_persona_remove_2d(persona.handle)
persona.handle = INVALID_PERSONA_HANDLE
end
end
-- Unregister callbacks
on_trigger("", M11_groups.stag_bases[1].restricted)
on_trigger("", M11_groups.stag_bases[2].script.trigger)
on_trigger("", M11_groups.oleg_battle.location)
-- Destroy the STAG bases
for i, base in pairs(M11_groups.stag_bases) do
on_trigger("", base.location)
on_trigger_exit("", base.location)
on_trigger("", base.zone)
on_trigger_exit("", base.zone)
marker_remove(base.nav, SYNC_ALL)
for i, box in pairs(base.boxes) do
if (not mesh_mover_destroyed(box.name)) then
marker_remove(box.name, SYNC_ALL)
on_mover_destroyed("", box.name)
end
end
if (group_is_loaded(base.name)) then
group_destroy(base.name)
end
if base.vehicle_group ~= nil then
if group_is_loaded(base.vehicle_group) then
group_destroy(base.vehicle_group)
end
end
if (group_is_loaded(base.vtols.name)) then
for i, vtol in pairs(base.vtols.vehicles) do
marker_remove(vtol, SYNC_ALL)
on_vehicle_enter("", vtol)
end
group_destroy(base.vtols.name)
end
end
-- Clean up road blocks
for i, roadblock in pairs(M11_groups.roadblocks) do
marker_remove_trigger(roadblock.location, SYNC_ALL)
on_trigger("", roadblock.location)
for j, vehicle in pairs(roadblock.vehicles) do
marker_remove(vehicle, SYNC_ALL)
on_vehicle_destroyed("", vehicle)
end
for j, vehicle in pairs(roadblock.convoy.vehicles) do
marker_remove(vehicle, SYNC_ALL)
on_vehicle_destroyed("", vehicle.name)
for j, person in pairs(vehicle.passengers) do
on_death("", person)
end
end
if (group_is_loaded(roadblock.name)) then
group_destroy(roadblock.name)
end
end
if (group_is_loaded(M11_groups.stag_bases[2].script.name)) then
group_destroy(M11_groups.stag_bases[2].script.name)
end
if (group_is_loaded(M11_groups.air_base.name)) then
for i, target in pairs(M11_groups.air_base.targets) do
on_vehicle_destroyed("", target.vehicle)
marker_remove(target.vehicle, SYNC_ALL)
end
for i, guard in pairs(M11_groups.air_base.guards) do
on_vehicle_destroyed("", guard.vehicle)
marker_remove(guard.vehicle, SYNC_ALL)
end
on_vehicle_destroyed("", M11_groups.air_base.final_plane.vehicle)
on_damage("", M11_groups.air_base.final_plane.vehicle)
marker_remove(M11_groups.air_base.final_plane.vehicle, SYNC_ALL)
group_destroy(M11_groups.air_base.name)
end
for i, battle in pairs(M11_groups.oleg_battle.waves) do
if (group_is_loaded(battle.name)) then
for i, vehicle in pairs(battle.vehicles) do
marker_remove(vehicle.name, SYNC_ALL)
on_vehicle_destroyed("", vehicle.name)
end
group_destroy(battle.name)
end
end
if (group_is_loaded(M11_groups.oleg_battle.oleg_vtols.name)) then
for i, vtol in pairs(M11_groups.oleg_battle.oleg_vtols.vtols) do
on_vehicle_enter("", vtol)
end
group_destroy(M11_groups.oleg_battle.oleg_vtols.name)
end
if (group_is_loaded(M11_groups.oleg_battle.oleg.name)) then
group_destroy(M11_groups.oleg_battle.oleg.name)
on_death("", M11_groups.oleg_battle.oleg.oleg)
end
if group_is_loaded(M11_groups.vehicle_start.name) then
group_destroy(M11_groups.vehicle_start.name)
end
if group_is_loaded(M11_groups.vehicle_cp.name) then
group_destroy(M11_groups.vehicle_cp.name)
end
-- Reset notoriety
hud_set_fake_notoriety("police", false, 0)
notoriety_set_can_decay(true)
notoriety_reset("police")
notoriety_force_no_spawn("police", false)
notoriety_force_no_spawn("stag", false)
notoriety_spawn_only_air(false)
notoriety_force_no_air_spawn(false)
-- Reset ambient density.
set_ped_density(1.0)
set_traffic_density(1.0)
audio_remove_mission_cellphone(M11_globals.cur_cell_call)
end
-- Called when the mission has ended with success
-- CALLED FROM CODE (+++MUST RETURN IMMEDIATLY+++)
function m11_success()
--[[ INSERT ANY MISSION SPECIFIC SUCCESS STUFF ]]--
end
-- *************************
--
-- Local functions
--
-- *************************
-- Figure out the next checkpoint based on destroyed bases
-- Returns: Checkpoint name
function m11_determine_checkpoint()
-- 12, 13, 14, 23, 24, or 34
if (M11_groups.stag_bases[1].destroyed) then
-- 12, 13, or 14
if (M11_groups.stag_bases[2].destroyed) then
return M11_checkpoints.roadblock12
elseif (M11_groups.stag_bases[3].destroyed) then
return M11_checkpoints.roadblock13
else
return M11_checkpoints.roadblock14
end
elseif (M11_groups.stag_bases[2].destroyed) then
-- 23 or 24
if (M11_groups.stag_bases[3].destroyed) then
return M11_checkpoints.roadblock23
else
return M11_checkpoints.roadblock24
end
else
return M11_checkpoints.roadblock34
end
end
-- Initialize the mission for the specified checkpoint
--
-- checkpoint: Checkpoint to initialize the mission to
-- is_restart: Whether or not the mission is restarting.
function m11_initialize(checkpoint, is_restart)
-- Make sure the screen is completly faded out
mission_start_fade_out(0.0)
-- Set the mission author
set_mission_author("Albert McDaniel")
-- This can be removed in the future after the world takes care of stag
set_stag_active(true)
-- Always warp to the start location on cancel
mission_set_cancel_warp_location(M11_navpoints.start_local, M11_navpoints.start_remote)
-- Load the personas used
for i, persona in pairs(M11_personas) do
persona.handle = audio_persona_load_2d(persona.name)
end
-- create the giant plane so we make sure we have the resources (customized vehicle slot)
group_create_hidden(M11_groups.air_base_jumbo_plane.name, true)
group_create_hidden(M11_groups.air_base.name, true)
-- Checkpoint specific initialization
m11_initialize_checkpoint(checkpoint, is_restart)
-- Start fading in
mission_start_fade_in()
end
-- ***************************************************
-- m11_initialize Helper Functions
-- ***************************************************
-- Checkpoint specific initialization
--
-- checkpoint: The checkpoint to be initialized
-- is_restart: Whether or not the mission is restarting.
function m11_initialize_checkpoint(checkpoint, is_restart)
-- Always use the same start location
if is_restart == true then
teleport_coop(M11_navpoints.start_local, M11_navpoints.start_remote)
end
if (checkpoint == M11_checkpoints.start) then
group_create(M11_groups.vehicle_start.name, true)
vehicle_set_team(M11_groups.vehicle_start.vehicles[1], "Playas")
-- Start with low STAG attention to force the players to fill it
--M11_globals.stag_attention.value = M11_globals.stag_attention.max_value * 0.4
else
if (checkpoint ~= M11_checkpoints.destroy_bases) then
--don't play plane lines again
M11_globals.local_vtol_jet = true
M11_globals.local_vtol_hover = true
M11_globals.remote_vtol_jet = true
M11_globals.remote_vtol_hover = true
end
-- If not the starting cp, spawn the players in VTOLs
group_create(M11_groups.vehicle_cp.name, true)
while not vehicle_enter_teleport(LOCAL_PLAYER, M11_groups.vehicle_cp.vehicles[1], 0) do
thread_yield()
end
if (coop_is_active()) then
vehicle_enter_teleport(REMOTE_PLAYER, M11_groups.vehicle_cp.vehicles[2], 0)
else
object_destroy(M11_groups.vehicle_cp.vehicles[2])
end
--start threads to keep track of players VTOL health
M11_threads.local_player_vtol_health = thread_new("m11_player_vtol_tracking_thread", LOCAL_PLAYER)
if (coop_is_active()) then
M11_threads.remote_player_vtol_heath = thread_new("m11_player_vtol_tracking_thread", REMOTE_PLAYER)
end
-- Start with full STAG attention, as the bases are far away
--M11_globals.stag_attention.value = M11_globals.stag_attention.max_value
end
-- Determine how many bases have been destroyed
if (checkpoint == M11_checkpoints.roadblock12) then
M11_groups.stag_bases[1].destroyed = true
M11_groups.stag_bases[2].destroyed = true
elseif (checkpoint == M11_checkpoints.roadblock13) then
M11_groups.stag_bases[1].destroyed = true
M11_groups.stag_bases[3].destroyed = true
elseif (checkpoint == M11_checkpoints.roadblock14) then
M11_groups.stag_bases[1].destroyed = true
M11_groups.stag_bases[4].destroyed = true
elseif (checkpoint == M11_checkpoints.roadblock23) then
M11_groups.stag_bases[2].destroyed = true
M11_groups.stag_bases[3].destroyed = true
elseif (checkpoint == M11_checkpoints.roadblock24) then
M11_groups.stag_bases[2].destroyed = true
M11_groups.stag_bases[4].destroyed = true
elseif (checkpoint == M11_checkpoints.roadblock34) then
M11_groups.stag_bases[3].destroyed = true
M11_groups.stag_bases[4].destroyed = true
elseif (checkpoint == M11_checkpoints.oleg_battle) then
M11_groups.stag_bases[1].destroyed = true
M11_groups.stag_bases[2].destroyed = true
M11_groups.stag_bases[3].destroyed = true
M11_groups.stag_bases[4].destroyed = true
elseif (checkpoint == M11_checkpoints.air_base) then
M11_groups.stag_bases[1].destroyed = true
M11_groups.stag_bases[2].destroyed = true
M11_groups.stag_bases[3].destroyed = true
M11_groups.stag_bases[4].destroyed = true
end
-- Set up the remaining bases
m11_initialize_bases()
end
-- Set up all bases that have not already been destroyed
function m11_initialize_bases()
-- Check if each base has been destroyed; if not, set it up
for i, base in pairs(M11_groups.stag_bases) do
if (base.destroyed) then
-- Count the destroyed bases
M11_globals.num_bases_destroyed = M11_globals.num_bases_destroyed + 1
else
-- Set up the spawn and despawn regions
trigger_enable(base.location, true)
on_trigger("m11_base_spawn_callback", base.location)
on_trigger_exit("m11_base_despawn_callback", base.location)
-- Set all boxes to invulnerable until the player is close and register their destroyed callback
for i, box in pairs(base.boxes) do
mesh_mover_set_invulnerable(box.name, true)
on_mover_destroyed("m11_box_destroyed", box.name)
end
end
end
-- Set up the airport base script sequence
if (M11_groups.stag_bases[2].destroyed == false) then
trigger_enable(M11_groups.stag_bases[2].script.trigger, true)
on_trigger("m11_airport_spawn_callback", M11_groups.stag_bases[2].script.trigger)
end
end
-- *************************
-- Objective: Go to STAG Base
-- *************************
-- Setup for the initial "Go to STAG Base" objective
function m11_go_to_first_base()
-- Tell the player to get to the closest STAG base
objective_text(0, "M11_OBJ_GO_STAG_BASE", nil, nil, SYNC_ALL, OI_ASSET_LOCATION)
-- Intro animations
-- Player(s) look cool GO!
local anim_name = "M06 Player Mission Start"
local morph_name = "M06 Player Mission Start"
local force_play = false
local stand_still = false
local zero_movement = false
action_play_non_blocking(LOCAL_PLAYER, anim_name, morph_name, force_play, stand_still, zero_movement)
player_script_controlled_clear(LOCAL_PLAYER) -- let player escape this animation
if (coop_is_active()) then
action_play_non_blocking(REMOTE_PLAYER, anim_name, morph_name, force_play, stand_still, zero_movement)
player_script_controlled_clear(REMOTE_PLAYER) -- let player escape this animation
end
-- Set the base as the destination
M11_globals.objective_reached = false
trigger_enable(M11_groups.stag_bases[1].restricted, true)
on_trigger("m11_reached_callback", M11_groups.stag_bases[1].restricted)
marker_add(M11_groups.stag_bases[1].nav, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
waypoint_add(M11_groups.stag_bases[1].location)
M11_threads.intro_convos = thread_new("m11_intro_convos_thread")
-- Wait until the player reaches the first base
while not M11_globals.objective_reached do
thread_yield()
end
waypoint_remove(SYNC_ALL)
marker_remove(M11_groups.stag_bases[1].nav, SYNC_ALL)
objective_text_clear(0)
-- these conversations should be done
thread_kill(M11_threads.intro_convos)
end
-- *************************
-- Objective: Hijack VTOL
-- *************************
-- Setup for the hijack a VTOL objective at the first STAG base
function m11_hijack_vtol()
-- Increase notoriety
notoriety_set_min("police", 2)
-- Ensure the VTOLs are loaded
while not group_is_loaded(M11_groups.stag_bases[1].vtols.name) do
thread_yield()
end
M11_globals.vtol_hijacked = false
audio_conversation_wait_for_end(M11_conv.pack.handle)
M11_conv.pack.handle = INVALID_CONVERSATION_HANDLE
m11_wait_for_audio()
M11_globals.playing_line = true
audio_play_persona_line(LOCAL_PLAYER, M11_lines.arrive_at_first_base)
delay(4.0)
M11_globals.playing_line = false
--For Aaron
--M11_conv.to_vtols.handle = audio_conversation_load(M11_conv.to_vtols.name)
--audio_conversation_play(M11_conv.to_vtols.handle)
--audio_conversation_wait_for_end(M11_conv.to_vtols.handle)
-- Tell the player to hijack a VTOL
objective_text(0, "M11_OBJ_HIJACK_VTOL", nil, nil, SYNC_ALL, OI_ASSET_USE)
-- Mark each vtol in the first base
for i, vtol in pairs(M11_groups.stag_bases[1].vtols.vehicles) do
marker_add(vtol, MINIMAP_ICON_USE, OI_ASSET_USE, OI_FLAGS_DEFAULT, SYNC_ALL)
-- If both are destroyed, auto-advance
on_vehicle_destroyed("m11_vtol_destroyed_callback", vtol)
on_vehicle_enter_water("m11_vtol_destroyed_callback", vtol)
end
-- Wait for the player to hijack a vtol
while (M11_globals.vtol_hijacked == false) do
thread_yield()
end
objective_text_clear(0)
delay(1)
audio_ambient_emitter_start(M11_audio_emitters.alarm)
delay(1)
-- Play a line on the nearest living STAG dude about the player stealing the VTOL.
local nearest_dist = 999999
local nearest_dude = ""
for i, npc in pairs(M11_groups.stag_bases[1].npcs) do
local dist = get_dist(npc, M11_groups.stag_bases[1].vtols.vehicles[1])
if dist < nearest_dist then
nearest_dist = dist
nearest_dude = npc
end
end
if nearest_dude ~= "" then
audio_play_persona_line(nearest_dude, M11_lines.vtol_steal)
delay(2)
end
-- Cleanup first objective
for i, vtol in pairs(M11_groups.stag_bases[1].vtols.vehicles) do
marker_remove(vtol, SYNC_ALL)
on_vehicle_destroyed("", vtol)
end
--start threads to keep track of players VTOL health
M11_threads.local_player_vtol_health = thread_new("m11_player_vtol_tracking_thread", LOCAL_PLAYER)
if (coop_is_active()) then
M11_threads.remote_player_vtol_heath = thread_new("m11_player_vtol_tracking_thread", REMOTE_PLAYER)
end
-- Show the player the bases
m11_wait_for_audio()
M11_globals.playing_line = true
audio_play_persona_line(LOCAL_PLAYER, M11_lines.inside_vtol)
delay(4)
M11_globals.playing_line = false
m11_cleanup_hijack_vtol()
end
function m11_cleanup_hijack_vtol()
for i, vtol in pairs(M11_groups.stag_bases[1].vtols.vehicles) do
marker_remove(vtol, SYNC_ALL)
on_vehicle_destroyed("", vtol)
on_vehicle_enter_water("", vtol)
end
end
-- *************************
-- Objective: Distract STAG
-- *************************
-- The player must destroy STAG bases to keep them distracted
function m11_distract_stag()
objective_text_clear(0)
objective_text_clear(1)
objective_text(0, "M11_OBJ_DISTRACT_STAG", nil, nil, SYNC_LOCAL, OI_ASSET_LOCATION)
objective_text(1, "M11_OBJ_DISTRACT_STAG", nil, nil, SYNC_REMOTE, OI_ASSET_LOCATION)
-- Check if each base has been destroyed; if not, mark it
for i, base in pairs(M11_groups.stag_bases) do
if (not base.destroyed) then
-- Set up the enter and leave regions
trigger_enable(base.zone, true)
on_trigger("m11_base_entered_callback", base.zone)
on_trigger_exit("m11_base_left_callback", base.zone)
-- Mark the base
marker_add(base.nav, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
end
end
-- Wait until the player has destroyed the requisite number of bases
while (M11_globals.num_bases_destroyed < M11_globals.num_bases_destroyed_goal) do
--possibly play some lines
if (M11_globals.num_bases_destroyed == 3 and M11_globals.third_base_destroyed == false) then
M11_globals.third_base_destroyed = true
m11_wait_for_audio()
M11_globals.playing_line = true
audio_play_persona_line_2d(M11_personas.kia.handle, M11_lines.after_takeoff1)
delay(3)
audio_play_persona_line_2d(M11_personas.stag_bm.handle, M11_lines.after_takeoff2)
delay(3)
M11_globals.playing_line = false
end
thread_yield()
end
-- Remove all base markers
for i, base in pairs(M11_groups.stag_bases) do
marker_remove(base.nav, SYNC_ALL)
end
objective_text_clear(0)
objective_text_clear(1)
end
-- *************************
-- Objective: Help Convoy
-- *************************
-- Add markers, objectives, to go to a roadblock
function m11_help_convoy(roadblock)
-- Pierce calls about a roadblock
m11_wait_for_audio()
M11_globals.playing_line = true
audio_play_persona_line_2d(M11_personas.pierce.handle, M11_lines.roadblock_start)
-- Spawn the roadblock
m11_spawn_roadblock(roadblock)
traffic_disable_lanes(M11_triggers.traffic_rb, true)
-- Change the objective to the convoy
objective_text(0, "M11_OBJ_HELP_CONVOY", nil, nil, SYNC_ALL, OI_ASSET_LOCATION)
M11_globals.objective_reached = false
trigger_enable(roadblock.location, true)
on_trigger("m11_reached_callback", roadblock.location)
marker_add_trigger(roadblock.location, MINIMAP_ICON_LOCATION, "", OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
waypoint_add(roadblock.location)
delay(3)
M11_globals.playing_line = false
-- wait for roadblock group to spawn
while group_is_loaded(roadblock.name) == false do
thread_yield()
end
-- mark all targets invul
for i, vehicle in pairs(roadblock.vehicles) do
vehicle_set_invulnerable( vehicle, true )
end
-- Wait until a player approaches the roadblock
while (M11_globals.objective_reached == false) do
thread_yield()
end
-- clear invul flag
for i, vehicle in pairs(roadblock.vehicles) do
vehicle_set_invulnerable( vehicle, false )
end
trigger_enable(roadblock.location, false)
on_trigger("", roadblock.location)
marker_remove_trigger(roadblock.location, SYNC_ALL)
waypoint_remove(SYNC_ALL)
-- Change the objective to the roadblock
objective_text_clear(0)
objective_text(0, "M11_OBJ_KILL_ROADBLOCK", nil, nil, SYNC_ALL, OI_ASSET_KILL)
-- Mark the targets
for i, vehicle in pairs(roadblock.vehicles) do
if vehicle_is_tank(vehicle) then
marker_add(vehicle, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_ALL)
else
marker_add(vehicle, MINIMAP_ICON_KILL, OI_ASSET_KILL, OI_FLAGS_DEFAULT, SYNC_ALL)
end
end
-- Mark the convoy as defend targets
for i, vehicle in pairs(roadblock.convoy.vehicles) do
marker_add(vehicle.name, MINIMAP_ICON_PROTECT_ACQUIRE, OI_ASSET_DEFEND, OI_FLAG_STICKY, SYNC_ALL)
end
-- Wait until all targets have been destroyed
while (M11_globals.num_targets > 0) do
thread_yield()
end
-- Remove convoy markers
for i, vehicle in pairs(roadblock.convoy.vehicles) do
marker_remove(vehicle.name, SYNC_ALL)
end
-- Start a tracking thread before waiting to release the convoy
M11_threads.convoy_cleanup = thread_new("m11_convoy_cleanup_thread", roadblock)
traffic_disable_lanes(M11_triggers.traffic_rb, false)
roadblock.destroyed = true
--M11_globals.stag_attention.value = M11_globals.stag_attention.max_value
objective_text_clear(0)
end
-- Spawns and sets up a roadblock
function m11_spawn_roadblock(roadblock)
-- Spawn the roadblock
if not group_is_loaded(roadblock.name) then
group_create(roadblock.name, true)
end
-- Set up death callbacks
M11_globals.num_targets = 0
for i, vehicle in pairs(roadblock.vehicles) do
on_vehicle_destroyed("m11_target_destroyed", vehicle)
M11_globals.num_targets = M11_globals.num_targets + 1
end
-- Put the drivers in the tanks
for i, tank in pairs(roadblock.tanks) do
vehicle_enter_teleport(tank.driver, tank.name, 0)
vehicle_max_speed(tank.name, 15)
vehicle_disable_chase(tank.name)
vehicle_disable_flee(tank.name)
end
-- Set up the convoy
for i, vehicle in pairs(roadblock.convoy.vehicles) do
-- Fail if any convoy vehicle dies
on_vehicle_destroyed("m11_pre_obj_convoy_death_callback", vehicle.name)
-- Prevent jacking
set_unjackable_flag(vehicle.name, true)
vehicle_suppress_npc_exit(vehicle.name, true)
-- Put the Saints in the vehicles and prevent AI from attacking them
for j, person in pairs(vehicle.passengers) do
vehicle_enter_teleport(person, vehicle.name, j - 1)
set_ignore_ai_flag(person, true)
set_dont_attack_me_on_sight_flag(person, true)
on_death("m11_pre_obj_convoy_death_callback", person)
end
end
group_show(roadblock.name)
end
-- *************************
-- Objective: Air Base
-- *************************
-- Spawn and setup the air base
function m11_air_base()
-- Create the group
group_show(M11_groups.air_base.name)
group_show(M11_groups.air_base_jumbo_plane.name)
helicopter_set_dont_explode_in_air(M11_groups.air_base.final_plane.vehicle , true)
helicopter_set_large_dspiral(M11_groups.air_base.final_plane.vehicle , true)
helicopter_set_path_orientation(M11_groups.air_base.final_plane.vehicle, HELI_PF_PATH_PITCH)
helicopter_set_max_bank_angle(M11_groups.air_base.final_plane.vehicle, 0)
vehicle_prevent_vehicle_collision_damage(M11_groups.air_base.final_plane.vehicle, true)
vehicle_infinite_mass(M11_groups.air_base.final_plane.vehicle, true)
--we're low on high component vehicles don't spawn any for notoriety
notoriety_force_no_air_spawn(true)
notoriety_force_no_spawn("stag", true)
-- Set up the targets
M11_globals.num_transports = 0
M11_globals.num_guards = 0
M11_globals.final_targets_attack = false
for i, target in pairs(M11_groups.air_base.targets) do
vehicle_enter_teleport(target.pilot, target.vehicle, 0)
M11_threads.fly_target[i] = thread_new("m11_fly_path_target_thread", target.vehicle, target.path)
vehicle_set_invulnerable(target.vehicle, true)
end
--setup the final plane
vehicle_enter_teleport(M11_groups.air_base.final_plane.pilot, M11_groups.air_base.final_plane.vehicle, 0)
M11_threads.fly_final_plane = thread_new("m11_fly_path_thread", M11_groups.air_base.final_plane.vehicle, M11_groups.air_base.final_plane.path)
on_vehicle_destroyed("m11_final_plane_destroyed", M11_groups.air_base.final_plane.vehicle)
on_damage("m11_final_plane_destroyed", M11_groups.air_base.final_plane.vehicle, 0.1)
M11_globals.final_plane_alive = true
vehicle_set_invulnerable(M11_groups.air_base.final_plane.vehicle, true)
M11_conv.awacs.play = false
M11_conv.awacs.kill = false
M11_conv.killing_escorts.play = false
M11_conv.killing_escorts.kill = false
M11_threads.air_base_convos = thread_new("m11_air_base_convos_thread")
-- Set up the guards
for i, guard in pairs(M11_groups.air_base.guards) do
vehicle_enter_teleport(guard.pilot, guard.vehicle, 0)
M11_threads.fly_guard[i] = thread_new("m11_fly_path_guard_thread", guard.vehicle, guard.path)
vehicle_set_invulnerable(guard.vehicle, true)
end
M11_conv.awacs.play = true
-- Send the player to the air base
objective_text(0, "M11_OBJ_GO_AIR_BASE", nil, nil, SYNC_ALL, OI_ASSET_LOCATION)
marker_add(M11_groups.air_base.final_plane.vehicle, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
--waypoint_add(M11_groups.air_base.final_plane.vehicle)
-- Limit them with a timer
M11_threads.stag_attention = thread_new("m11_timer_thread")
-- Repair the player's vehicle and make it mission critical
vehicle_repair(get_char_vehicle_name(LOCAL_PLAYER))
if coop_is_active() then
vehicle_repair(get_char_vehicle_name(REMOTE_PLAYER))
end
-- Wait for the player to arrive
while (get_dist_closest_player_to_object(M11_groups.air_base.final_plane.vehicle) > 600) do
thread_yield()
end
-- Been having a bit of problems with the callbacks in release final. Setting up later to hopfully get better results
for i, target in pairs(M11_groups.air_base.targets) do
if not vehicle_is_destroyed(target.vehicle) then
vehicle_set_invulnerable(target.vehicle, false)
on_vehicle_destroyed("m11_transport_destroyed", target.vehicle)
M11_globals.num_transports = M11_globals.num_transports + 1
end
end
for i, guard in pairs(M11_groups.air_base.guards) do
if not vehicle_is_destroyed(guard.vehicle) then
vehicle_set_invulnerable(guard.vehicle, false)
on_vehicle_destroyed("m11_guard_destroyed", guard.vehicle)
M11_globals.num_guards = M11_globals.num_guards + 1
end
end
on_damage("m11_final_plane_destroyed", M11_groups.air_base.final_plane.vehicle, 0.1)
M11_conv.awacs.kill = true
-- Decrease notoriety
notoriety_set_min("police", 2)
--waypoint_remove(SYNC_ALL)
marker_remove(M11_groups.air_base.final_plane.vehicle)
objective_text_clear(0)
--== WAYPOINT ==--
objective_text(0, "M11_OBJ_KILL_AIR_BASE", nil, nil, SYNC_ALL, OI_ASSET_KILL)
-- Mark the guards and targets
for i, guard in pairs(M11_groups.air_base.guards) do
marker_add(guard.vehicle, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_ALL)
end
m11_wait_for_audio()
M11_globals.playing_line = true
audio_play_persona_line(LOCAL_PLAYER, M11_lines.air_base)
delay(3)
M11_globals.playing_line = false
-- End the Saints chatter and start up some STAG chatter.
thread_kill(M11_threads.radio_chatter)
M11_globals.playing_line = false
M11_threads.radio_chatter = thread_new("m11_stag_vtol_radio_chatter_thread")
delay(10)
M11_conv.killing_escorts.play = true
-- Wait for the guards to be destroyed
while (M11_globals.num_guards > 0) do
thread_yield()
end
vehicle_prevent_explosion_fling(M11_groups.air_base.final_plane.vehicle, true)
objective_text_clear(0)
--== WAYPOINT ==--
objective_text(0, "M11_OBJ_KILL_AIR_BASE", nil, nil, SYNC_ALL, OI_ASSET_KILL)
M11_globals.final_targets_attack = true
-- Mark the targets and attack the player
for i, target in pairs(M11_groups.air_base.targets) do
marker_add(target.vehicle, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_ALL)
ai_add_enemy_target(target.pilot, CLOSEST_PLAYER, ATTACK_ON_SIGHT)
end
M11_conv.killing_escorts.kill = true
-- Wait for the targets to be destroyed
local dist = 0
local player = nil
while (M11_globals.num_transports > 0) do
thread_yield()
end
-- End the STAG chatter after the guards are killed.
thread_kill(M11_threads.radio_chatter)
M11_globals.playing_line = false
M11_threads.radio_chatter = INVALID_THREAD_HANDLE
-- Mark the final plane
marker_add(M11_groups.air_base.final_plane.vehicle, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_ALL)
vehicle_set_invulnerable(M11_groups.air_base.final_plane.vehicle, false)
while (M11_globals.final_plane_alive) do
thread_yield()
end
audio_object_post_event( "m11_carrier_plane_dive" )
--make the plane play a specail 'on fire' effect
effect_play_on_script_object("Vfx Mis11 Big Engine Fire 001", M11_groups.air_base.final_plane.vehicle, nil, true)
hud_timer_stop(1)
thread_kill(M11_threads.stag_attention)
M11_threads.stag_attention = INVALID_THREAD_HANDLE
objective_text_clear(0)
M11_conv.pierce_end.handle = audio_conversation_load(M11_conv.pierce_end.name)
audio_conversation_play(M11_conv.pierce_end.handle)
-- Delay a short time before ending
delay(6)
end
-- *************************
-- Objective: Help Oleg
-- *************************
-- Spawn Oleg, and setup the big battle
function m11_help_oleg()
-- Start the Oleg battle phone call
M11_conv.oleg_help.handle = audio_conversation_load(M11_conv.oleg_help.name)
audio_conversation_play(M11_conv.oleg_help.handle)
-- Set up the VTOLs
group_create(M11_groups.oleg_battle.oleg_vtols.name, true)
for i, vtol in pairs(M11_groups.oleg_battle.oleg_vtols.vtols) do
on_vehicle_enter("m11_vtol_hijacked_callback_oleg", vtol)
end
-- Set up the targets
group_create(M11_groups.oleg_battle.waves[1].name, true)
M11_globals.num_targets = 0
for i, vehicle in pairs(M11_groups.oleg_battle.waves[1].vehicles) do
on_vehicle_destroyed("m11_target_destroyed", vehicle.name)
M11_globals.num_targets = M11_globals.num_targets + 1
end
for i, npc in pairs(M11_groups.oleg_battle.waves[1].npcs) do
on_death("m11_target_destroyed", npc)
M11_globals.num_targets = M11_globals.num_targets + 1
end
--Spawn Tank Group
m11_spawn_oleg_tanks()
vehicle_enter_teleport(M11_groups.oleg_battle.waves[1].npcs[1], M11_groups.oleg_battle.waves[1].vehicles[1].name, 3, false)
-- Send the player to help Oleg
M11_globals.objective_reached = false
trigger_enable(M11_groups.oleg_battle.location, true)
on_trigger("m11_reached_callback", M11_groups.oleg_battle.location)
objective_text(0, "M11_OBJ_GO_OLEG", nil, nil, SYNC_ALL, OI_ASSET_LOCATION)
marker_add(M11_groups.oleg_battle.location, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
waypoint_add(M11_groups.oleg_battle.location)
-- Wait for the player to arrive
while (M11_globals.objective_reached == false) do
thread_yield()
end
waypoint_remove(SYNC_ALL)
marker_remove(M11_groups.oleg_battle.location)
trigger_enable(M11_groups.oleg_battle.location, false)
on_trigger("", M11_groups.oleg_battle.location)
-- Change the objective to defense
objective_text_clear(0)
objective_text(0, "M11_OBJ_HELP_OLEG", nil, nil, SYNC_ALL, OI_ASSET_DEFEND)
-- Add markers for the enemies
for i, vehicle in pairs(M11_groups.oleg_battle.waves[1].vehicles) do
if not vehicle_is_destroyed(vehicle.name) then
marker_add(vehicle.name, MINIMAP_ICON_KILL, OI_ASSET_KILL, OI_FLAGS_DEFAULT, SYNC_ALL)
end
end
for i, npc in pairs(M11_groups.oleg_battle.waves[1].npcs) do
if not character_is_dead(npc) then
marker_add(npc, MINIMAP_ICON_KILL, OI_ASSET_KILL, OI_FLAGS_DEFAULT, SYNC_ALL)
end
end
vehicle_enter_teleport(M11_groups.oleg_battle.waves[1].npcs[1], M11_groups.oleg_battle.waves[1].vehicles[1].name, 4)
--Make the tanks targets
m11_tank_targets()
--Deploy Tanks oleg_tanks
m11_deploy_tanks()
-- Unload Oleg's persona before Oleg is loaded
audio_conversation_wait_for_end(M11_conv.oleg_help.handle)
M11_conv.oleg_help.handle = INVALID_CONVERSATION_HANDLE
audio_persona_remove_2d(M11_personas.oleg.handle)
M11_personas.oleg.handle = INVALID_PERSONA_HANDLE
-- Create Oleg
group_create(M11_groups.oleg_battle.oleg.name, true)
set_max_hit_points(M11_groups.oleg_battle.oleg.oleg, 50000, true)
on_death("m11_oleg_died_callback", M11_groups.oleg_battle.oleg.oleg)
marker_add(M11_groups.oleg_battle.oleg.oleg, MINIMAP_ICON_PROTECT_ACQUIRE, OI_ASSET_DEFEND, OI_FLAG_STICKY + OI_FLAG_DISPLAY_DISTANCE, SYNC_ALL)
for i, npc in pairs(M11_groups.oleg_battle.waves[1].npcs) do
if not character_is_dead(npc) then
ai_add_enemy_target(npc, M11_groups.oleg_battle.oleg.oleg, ATTACK_NOW, true)
end
end
m11_tank_attack()
-- This is hanging in release. commenting out until its fixed
--M11_conv.oleg_arrive.handle = audio_conversation_load(M11_conv.oleg_arrive.name)
--audio_conversation_play(M11_conv.oleg_arrive.handle)
--audio_conversation_wait_for_end(M11_conv.oleg_arrive.handle)
--M11_conv.oleg_arrive.handle = INVALID_CONVERSATION_HANDLE
delay(5)
m11_wait_for_audio()
M11_globals.playing_line = true
audio_play_persona_line(M11_groups.oleg_battle.oleg.oleg, M11_lines.fight_at_park)
delay(3)
M11_globals.playing_line = false
-- Wait for us to win this wave
while (M11_globals.num_targets > 0) do
thread_yield()
end
-- Release the remnants
if group_is_loaded(M11_groups.oleg_battle.waves[1].name) then
release_to_world(M11_groups.oleg_battle.waves[1].name)
group_destroy(M11_groups.oleg_battle.waves[1].name)
end
delay(3.0)
-- Spawn a second wave
M11_globals.num_targets = 0
-- group_create(M11_groups.oleg_battle.waves[2].name, true)
group_create(M11_groups.oleg_battle.waves[3].name, true)
for i, vehicle in pairs (M11_groups.oleg_battle.waves[3].vehicles) do
vehicle_enter_teleport(vehicle.driver, vehicle.name, 0)
teleport_vehicle(vehicle.name, M11_groups.oleg_battle.nav_vtol[i])
marker_add(vehicle.name, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_ALL)
on_vehicle_destroyed("m11_target_destroyed", vehicle.name)
M11_globals.num_targets = M11_globals.num_targets + 1
-- Set up a move-to-and-attack thread
M11_threads.battle[i] = thread_new("m11_battle_thread", vehicle, i)
end
-- End the Saints chatter and start up some STAG chatter.
thread_kill(M11_threads.radio_chatter)
M11_globals.playing_line = false
M11_threads.radio_chatter = thread_new("m11_stag_vtol_radio_chatter_thread")
-- Wait for us to win
while (M11_globals.num_targets > 0) do
thread_yield()
end
-- Clear the threads
for i, th in pairs(M11_threads.battle) do
if (th ~= INVALID_THREAD_HANDLE) then
thread_kill(th)
M11_threads.battle[i] = INVALID_THREAD_HANDLE
end
end
-- Release the remnants
if group_is_loaded(M11_groups.oleg_battle.waves[2].name) then
release_to_world(M11_groups.oleg_battle.waves[2].name)
group_destroy(M11_groups.oleg_battle.waves[2].name)
end
M11_conv.reinforcements.handle = audio_conversation_load(M11_conv.reinforcements.name)
audio_conversation_play(M11_conv.reinforcements.handle)
delay(2.0)
objective_text_clear(0)
audio_conversation_wait_for_end(M11_conv.reinforcements.handle)
M11_conv.reinforcements.handle = INVALID_CONVERSATION_HANDLE
-- Switch back to Saints chatter
thread_kill(M11_threads.radio_chatter)
M11_globals.playing_line = false
M11_threads.radio_chatter = thread_new("m11_radio_chatter_thread")
m11_cleanup_help_oleg()
end
function m11_cleanup_help_oleg()
-- Clean up battle waves.
if group_is_loaded(M11_groups.oleg_battle.waves[1].name) then
for i, vehicle in pairs(M11_groups.oleg_battle.waves[1].vehicles) do
on_vehicle_destroyed("", vehicle.name)
end
for i, npc in pairs(M11_groups.oleg_battle.waves[1].npcs) do
on_death("", npc)
end
end
if group_is_loaded(M11_groups.oleg_battle.waves[3].name) then
for i, vehicle in pairs (M11_groups.oleg_battle.waves[3].vehicles) do
marker_remove(vehicle.name)
on_vehicle_destroyed("", vehicle.name)
if M11_threads.battle[i] ~= nil then
thread_kill(M11_threads.battle[i])
end
M11_threads.battle[i] = INVALID_THREAD_HANDLE
end
end
-- Clean up tanks.
for i,group in pairs(oleg_tanks) do
if group_is_loaded(group.name) then
marker_remove(group.vehicle)
on_vehicle_destroyed("", group.vehicle)
if group.move_thread ~= nil then
thread_kill(group.move_thread)
end
group.move_thread = INVALID_THREAD_HANDLE
end
end
on_death("", M11_groups.oleg_battle.oleg.oleg)
marker_remove(M11_groups.oleg_battle.oleg.oleg)
end
-- ***************************************************
-- Miscellaneous m11 Helper Functions
-- ***************************************************
function m11_cell_convo_finished()
M11_globals.cell_call_finished = true
end
function m11_play_cell_convo(conv_name, receiving_call, persona_override_id)
while M11_globals.cell_call_finished == false do
thread_yield()
end
M11_globals.cell_call_finished = false
audio_play_for_mission_cellphone(conv_name, receiving_call, true, "", "m11_cell_convo_finished", persona_override_id)
M11_globals.cur_cell_call = conv_name
while M11_globals.cell_call_finished == false do
thread_yield()
end
M11_globals.cur_cell_call = ""
end
-- Add the GSI meter
--function m11_setup_stag_attention()
-- hud_bar_on(1, "annoyance", "", M11_globals.stag_attention.max_value, SYNC_ALL)
--
-- -- Reset the variables pertaining to stag_attention
-- M11_globals.stag_attention.first_warning = false
-- M11_globals.stag_attention.second_warning = false
-- M11_globals.stag_attention.third_warning = false
--
-- M11_threads.stag_attention = thread_new("m11_process_stag_attention_thread")
--end
-- Remove the GSI meter
--function m11_remove_stag_attention()
-- hud_bar_off(1)
--
-- if (M11_threads.stag_attention ~= nil) then
-- thread_kill(M11_threads.stag_attention)
-- end
-- M11_threads.stag_attention = nil
--end
-- Check if all targets in the STAG base have been destroyed, and update the base if so
function m11_check_base_destroyed(base)
-- Only check bases that have not yet been destroyed
if ((base == nil) or base.destroyed) then
return
end
-- Check the battle boxes
for i, box in pairs(base.boxes) do
if not box.destroyed then
-- There is a surviving target
return
end
end
-- All targets have been destroyed
base.destroyed = true
--M11_globals.stag_attention.value = M11_globals.stag_attention.max_value
M11_globals.num_bases_destroyed = M11_globals.num_bases_destroyed + 1
-- Remove the stream-in trigger, but leave the stream-out
-- NOTE: This is because releasing them as ambient causes them to immediately despawn due to distance, so for now they must remain script NPCs
on_trigger("", base.location)
-- Remove the base marker and zone callbacks
trigger_enable(base.zone, true)
on_trigger("", base.zone)
on_trigger_exit("", base.zone)
marker_remove(base.nav, SYNC_ALL)
-- Release the ground vehicles so the player can drive them off.
if base.vehicle_group ~= nil and group_is_loaded(base.vehicle_group) then
release_to_world(base.vehicle_group)
group_destroy(base.vehicle_group)
end
-- Despawn the base
if (group_is_loaded(base.name)) then
release_to_world(base.name)
group_destroy(base.name)
end
-- Skip the rest if not hunting bases
if (M11_globals.num_bases_destroyed >= M11_globals.num_bases_destroyed_goal) then
return
end
-- Figure out which players are in this base
local sync = nil
if coop_is_active() then
if object_is_in_trigger(base.zone, REMOTE_PLAYER) then
if object_is_in_trigger(base.zone, LOCAL_PLAYER) then
sync = SYNC_ALL
else
sync = SYNC_REMOTE
end
elseif object_is_in_trigger(base.zone, LOCAL_PLAYER) then
sync = SYNC_LOCAL
end
elseif object_is_in_trigger(base.zone, LOCAL_PLAYER) then
sync = SYNC_ALL
end
-- Update the objective accordingly
if (sync == SYNC_ALL or sync == SYNC_LOCAL) then
objective_text_clear(0)
objective_text(0, "M11_OBJ_DISTRACT_STAG", nil, nil, SYNC_LOCAL, OI_ASSET_LOCATION)
-- Restore all base markers
for i, base in pairs(M11_groups.stag_bases) do
if (not base.destroyed) then
marker_add(base.nav, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_LOCAL)
end
end
end
if coop_is_active() then
if (sync == SYNC_ALL or sync == SYNC_REMOTE) then
objective_text_clear(1)
objective_text(1, "M11_OBJ_DISTRACT_STAG", nil, nil, SYNC_REMOTE, OI_ASSET_LOCATION)
-- Restore all base markers
for i, base in pairs(M11_groups.stag_bases) do
if (not base.destroyed) then
marker_add(base.nav, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_REMOTE)
end
end
end
end
end
-- *************************
--
-- Callback functions
--
-- *************************
-- Called when the player reaches their objective
function m11_reached_callback(player_name, trigger_name)
M11_globals.objective_reached = true
end
-- Vehicle Callback: Called when a vehicle in the Convoy is destroyed before the objective is completed
function m11_pre_obj_convoy_death_callback(victim_name)
mission_end_failure("m11", "m11_fail_convoy")
end
-- Vehicle Callback: Called when a vehicle in the Convoy is destroyed after the objective is completed
function m11_post_obj_convoy_death_callback(victim_name, attacker_name)
if (attacker_name == LOCAL_PLAYER or attacker_name == REMOTE_PLAYER) then
mission_end_failure("m11", "m11_fail_convoy")
end
end
-- NPC Callback: Called if Oleg is killed, ending the mission
function m11_oleg_died_callback()
mission_end_failure("m11", "m11_fail_oleg")
end
-- Fail if the timer runs out
function m11_fail_timer()
mission_end_failure("m11", "m11_fail_stag")
end
-- *************************
-- VTOL Callbacks
-- *************************
-- Called when the player enters a VTOL
function m11_vtol_hijacked_callback1(player_name, vehicle_name, seat_index)
M11_globals.vtol_hijacked = true
marker_remove(vehicle_name, SYNC_ALL)
on_vehicle_destroyed("", vehicle_name)
on_vehicle_enter("", vehicle_name)
--release_to_world(vehicle_name)
--don't release, mark the group as don't destroy so we can track the players vehicle
M11_groups.stag_bases[1].vtols.save = true
end
function m11_vtol_hijacked_callback2(player_name, vehicle_name, seat_index)
M11_globals.vtol_hijacked = true
marker_remove(vehicle_name, SYNC_ALL)
on_vehicle_destroyed("", vehicle_name)
on_vehicle_enter("", vehicle_name)
--release_to_world(vehicle_name)
--don't release, mark the group as don't destroy so we can track the players vehicle
M11_groups.stag_bases[2].vtols.save = true
end
function m11_vtol_hijacked_callback3(player_name, vehicle_name, seat_index)
M11_globals.vtol_hijacked = true
marker_remove(vehicle_name, SYNC_ALL)
on_vehicle_destroyed("", vehicle_name)
on_vehicle_enter("", vehicle_name)
--release_to_world(vehicle_name)
--don't release, mark the group as don't destroy so we can track the players vehicle
M11_groups.stag_bases[3].vtols.save = true
end
function m11_vtol_hijacked_callback4(player_name, vehicle_name, seat_index)
M11_globals.vtol_hijacked = true
marker_remove(vehicle_name, SYNC_ALL)
on_vehicle_destroyed("", vehicle_name)
on_vehicle_enter("", vehicle_name)
--release_to_world(vehicle_name)
--don't release, mark the group as don't destroy so we can track the players vehicle
M11_groups.stag_bases[4].vtols.save = true
end
function m11_vtol_hijacked_callback_oleg(player_name, vehicle_name, seat_index)
M11_globals.vtol_hijacked = true
marker_remove(vehicle_name, SYNC_ALL)
on_vehicle_destroyed("", vehicle_name)
on_vehicle_enter("", vehicle_name)
--release_to_world(vehicle_name)
--don't release, mark the group as don't destroy so we can track the players vehicle
M11_groups.oleg_battle.oleg_vtols.save = true
end
-- Called when a VTOL is destroyed in STAG base 1
function m11_vtol_destroyed_callback(vtol)
marker_remove(vtol, SYNC_ALL)
on_vehicle_destroyed("", vtol)
on_vehicle_enter_water("", vtol)
on_vehicle_enter("", vtol)
-- Check if both VTOLs are destroyed
for i, vtol in pairs(M11_groups.stag_bases[1].vtols.vehicles) do
if (vehicle_exists(vtol) and not vehicle_is_destroyed(vtol) and not vehicle_in_water(vtol)) then
return
end
end
-- Progress the mission if they destroy both VTOLs
M11_globals.vtol_hijacked = true
end
-- *************************
-- STAG Base Callbacks
-- *************************
-- Called when the player nears one of the STAG bases
function m11_base_spawn_callback(player_name, trigger_name)
-- Find which base it is
local base_entered = nil
local base_num = nil
for i, base in pairs(M11_groups.stag_bases) do
if (trigger_name == base.location) then
-- This is the base we reached
base_entered = base
base_num = i
end
end
-- Skip if this base has already been destroyed
if base_entered.destroyed then
return
end
-- Spawn the ground vehicles they will be released rather than destroyed
-- when the player exits the base so they can drive them off. As such
-- we only want to spawn them once.
if base_entered.vehicle_group ~= nil then
if base_entered.vehicles_created == false then
base_entered.vehicles_created = true
group_create(base_entered.vehicle_group, true)
end
end
-- Spawn the base (if not already spawned)
if (not group_is_loaded(base_entered.name)) then
group_create(base_entered.name, true)
end
if (not group_is_loaded(base_entered.vtols.name)) then
group_create(base_entered.vtols.name, true)
-- Set up the VTOL hijack callback
for i, vtol in pairs(base_entered.vtols.vehicles) do
if(base_num == 1) then
on_vehicle_enter("m11_vtol_hijacked_callback1", vtol)
elseif (base_num == 2) then
on_vehicle_enter("m11_vtol_hijacked_callback2", vtol)
elseif (base_num == 3) then
on_vehicle_enter("m11_vtol_hijacked_callback3", vtol)
else
on_vehicle_enter("m11_vtol_hijacked_callback4", vtol)
end
end
end
end
-- Called when the player gets too far from one of the STAG bases
function m11_base_despawn_callback(player_name, trigger_name)
-- Find which base it is
local base_left = nil
for i, base in pairs(M11_groups.stag_bases) do
if (trigger_name == base.location) then
-- This is the base we reached
base_left = base
end
end
-- Skip if another player is still in the base
if (object_is_in_trigger(trigger_name, LOCAL_PLAYER) or (coop_is_active() and object_is_in_trigger(trigger_name, REMOTE_PLAYER))) then
return
end
-- Release the ground vehicles so the player can drive them off.
if base_left.vehicle_group ~= nil and group_is_loaded(base_left.vehicle_group) then
release_to_world(base_left.vehicle_group)
group_destroy(base_left.vehicle_group)
end
-- Despawn the base
if (group_is_loaded(base_left.name)) then
group_destroy(base_left.name)
end
if (group_is_loaded(base_left.vtols.name)) then
-- Remove the VTOL hijack callback
for i, vtol in pairs(base_left.vtols.vehicles) do
on_vehicle_enter("", vtol)
end
if (base_left.vtols.save == false) then
group_destroy(base_left.vtols.name)
end
end
end
-- Called when the player enters one of the STAG bases
function m11_base_entered_callback(player_name, trigger_name)
-- Find which base it is
local base_entered = nil
for i, base in pairs(M11_groups.stag_bases) do
if (trigger_name == base.zone) then
-- This is the base we reached
base_entered = base
break
end
end
-- Skip if this base has already been destroyed, or if not currently hunting bases
if base_entered.destroyed or (M11_globals.num_bases_destroyed >= M11_globals.num_bases_destroyed_goal) then
return
end
-- Was this the local or remote player
local sync = SYNC_LOCAL
local tag_num = 0
if (coop_is_active() and (player_name == REMOTE_PLAYER)) then
sync = SYNC_REMOTE
tag_num = 1
end
-- Remove all base markers
for i, base in pairs(M11_groups.stag_bases) do
marker_remove(base.nav, sync)
end
-- Change the objective
objective_text_clear(tag_num)
objective_text(tag_num, "M11_OBJ_DESTROY_STAG", nil, nil, sync, OI_ASSET_KILL)
-- Enable and mark the battle boxes
for i, box in pairs(base_entered.boxes) do
if not box.destroyed then
mesh_mover_set_invulnerable(box.name, false)
marker_add(box.name, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, sync)
end
end
end
-- Called when the player exits one of the STAG bases
function m11_base_left_callback(player_name, trigger_name)
-- Find which base it is
local base_left = nil
for i, base in pairs(M11_groups.stag_bases) do
if (trigger_name == base.zone) then
-- This is the base we reached
base_left = base
break
end
end
-- Was this the local or remote player
local sync = SYNC_LOCAL
local tag_num = 0
if (coop_is_active() and (player_name == REMOTE_PLAYER)) then
sync = SYNC_REMOTE
tag_num = 1
end
-- Is the other player still inside the trigger?
local other_player_inside = false
if coop_is_active() then
if player_name == LOCAL_PLAYER then
other_player_inside = object_is_in_trigger(trigger_name, REMOTE_PLAYER)
else
other_player_inside = object_is_in_trigger(trigger_name, LOCAL_PLAYER)
end
end
-- Disable the battle boxes
for i, box in pairs(base_left.boxes) do
marker_remove(box.name, sync)
if not other_player_inside and not box.destroyed then
mesh_mover_set_invulnerable(box.name, true)
end
end
-- Skip the rest if not currently hunting bases
if (M11_globals.num_bases_destroyed >= M11_globals.num_bases_destroyed_goal) then
return
end
-- Restore all base markers
for i, base in pairs(M11_groups.stag_bases) do
if (not base.destroyed) then
marker_add(base.nav, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, sync)
end
end
-- Change the objective
objective_text_clear(tag_num)
objective_text(tag_num, "M11_OBJ_DISTRACT_STAG", nil, nil, sync, OI_ASSET_LOCATION)
end
-- Called when the player first nears the airport STAG base
function m11_airport_spawn_callback(player_name, trigger_name)
on_trigger("", M11_groups.stag_bases[2].script.trigger)
-- Spawn the script and set up a thread for each of the pilots
group_create(M11_groups.stag_bases[2].script.name, true)
M11_threads.pilots[1] = thread_new("m11_airport_lift_thread", M11_groups.stag_bases[2].script.vehicles[1])
M11_threads.pilots[2] = thread_new("m11_airport_lift_thread", M11_groups.stag_bases[2].script.vehicles[2])
M11_threads.pilots[3] = thread_new("m11_airport_land_thread", M11_groups.stag_bases[2].script.vehicles[3])
end
-- *************************
-- Target Callbacks
-- *************************
-- Called when one of the STAG targets at a base is destroyed
function m11_box_destroyed(box_name)
-- Add STAG attention
--M11_globals.stag_attention.value = M11_globals.stag_attention.value + M11_globals.stag_attention.target_value
--if (M11_globals.stag_attention.value > M11_globals.stag_attention.max_value) then
-- M11_globals.stag_attention.value = M11_globals.stag_attention.max_value
--end
--hud_bar_set_value(1, M11_globals.stag_attention.value)
-- Remove the marker and callback
marker_remove(box_name, SYNC_ALL)
on_mover_destroyed("", box_name)
-- Find the base this mover belonged to
local base_in = nil
for i, base in pairs(M11_groups.stag_bases) do
if base.destroyed == false and base_in == nil then
for j, box in pairs(base.boxes) do
if box_name == box.name then
box.destroyed = true
base_in = base
break
end
end
end
end
-- Check if the base has now been destroyed
m11_check_base_destroyed(base_in)
end
-- Called when one of the STAG air guards is destroyed
function m11_guard_destroyed(guard_name)
M11_globals.num_guards = M11_globals.num_guards - 1
marker_remove(guard_name, SYNC_ALL)
on_vehicle_destroyed("", guard_name)
end
-- Called when one of the STAG targets at a roadblock is destroyed
function m11_target_destroyed(target_name)
M11_globals.num_targets = M11_globals.num_targets - 1
-- Update STAG attention
--M11_globals.stag_attention.value = M11_globals.stag_attention.value + M11_globals.stag_attention.target_value
--if (M11_globals.stag_attention.value > M11_globals.stag_attention.max_value) then
-- M11_globals.stag_attention.value = M11_globals.stag_attention.max_value
--end
--hud_bar_set_value(1, M11_globals.stag_attention.value)
marker_remove(target_name, SYNC_ALL)
if (is_a_vehicle(target_name)) then
on_vehicle_destroyed("", target_name)
else
on_death("", target_name)
end
end
-- Called when one of the VTOL Tansports is destroyed
function m11_transport_destroyed(target_name)
M11_globals.num_transports = M11_globals.num_transports - 1
marker_remove(target_name, SYNC_ALL)
on_vehicle_destroyed("", target_name)
end
function m11_final_plane_destroyed(plane_name)
M11_globals.final_plane_alive = false
marker_remove(plane_name, SYNC_ALL)
on_vehicle_destroyed("", plane_name)
on_damage("", plane_name)
end
function m11_wait_for_audio()
while (audio_any_conversation_playing() or M11_globals.playing_line) do
delay(2)
end
end
-- *************************
--
-- Thread functions
--
-- *************************
-- Wrapper function for calling thread functions. Any function that begins with the mission name
-- will automatically have their thread killed when the mission ends in case we forget to clean it up.
--
function m11_wrapper_thread(function_ref, ...)
function_ref(unpack(arg))
end
function m11_intro_convos_thread()
-- make sure we are initialized
M11_globals.cell_call_finished = true
-- Start the Oleg phone call
m11_play_cell_convo(M11_conv.start.name, true)
delay(12.0)
-- Once the conversation is finished, play the next one
m11_play_cell_convo(M11_conv.pack.name, true)
end
function m11_stag_vtol_radio_chatter_thread()
-- Loop until we kill the thread.
while true do
-- Pick a random STAG persona to play the line.
local persona = get_random_table_entry(M11_stag_personas)
m11_wait_for_audio()
-- Say one of the VTOL lines.
M11_globals.playing_line = true
audio_play_persona_line_2d(persona.handle, M11_lines.stag_chatter)
delay(3)
M11_globals.playing_line = false
delay(rand_int(20, 30))
end
end
function m11_radio_chatter_thread()
while true do
local delay_time = rand_int(25, 35)
delay(delay_time)
local in_vehicle = character_is_in_vehicle(LOCAL_PLAYER)
if(coop_is_active() and not in_vehicle) then
in_vehicle = character_is_in_vehicle(REMOTE_PLAYER)
end
if(in_vehicle) then
--select a line to play
local starting_line = rand_int(1, M11_lines.random_lines.num_lines)
local play_line
for i=0,M11_lines.random_lines.num_lines - 1 do
play_line = starting_line + i
if (play_line > M11_lines.random_lines.num_lines) then
play_line = play_line - M11_lines.random_lines.num_lines
end
if (M11_lines.random_lines.lines[play_line].played == false) then
break
end
end
--now we've selected a random line that hasn't yet been played
m11_wait_for_audio()
M11_globals.playing_line = true
audio_play_persona_line_2d(M11_lines.random_lines.lines[play_line].persona.handle, M11_lines.random_lines.lines[play_line].name)
delay(3)
M11_globals.playing_line = false
M11_lines.random_lines.lines[play_line].played = true
M11_lines.random_lines.num_played = M11_lines.random_lines.num_played + 1
if(M11_lines.random_lines.num_played >= M11_lines.random_lines.num_lines) then
m11_clear_rand_lines()
end
end
end
end
function m11_clear_rand_lines()
for i=1,M11_lines.random_lines.num_lines do
M11_lines.random_lines.lines[i].played = false
end
M11_lines.random_lines.num_played = 0
end
function m11_player_vtol_tracking_thread(player)
local below_50 = false
local below_15 = false
while true do
local player_vehicle = get_char_vehicle_name(player)
if (player_vehicle ~= nil and player_vehicle ~= "") then
if (get_vehicle_type(player_vehicle) == 4) then --4 = SSVT_VTOL
--if (vehicle_is_vtol(player_vehicle)) then
-- health tracking
local current_health = get_current_hit_points(player_vehicle)
local max_health = get_max_hit_points(player_vehicle)
local pct = current_health/max_health
if(pct > 0.50) then
below_50 = false
below_15 = false
elseif((pct > 0.15) and (below_50 == false)) then
below_50 = true
below_15 = false
--play line
m11_wait_for_audio()
M11_globals.playing_line = true
audio_play_persona_line(player, M11_lines.vtol_damaged)
delay(3)
M11_globals.playing_line = false
elseif (below_15 == false) then
below_50 = true
below_15 = true
--play line
m11_wait_for_audio()
M11_globals.playing_line = true
audio_play_persona_line(player, M11_lines.vtol_very_damaged)
delay(3)
M11_globals.playing_line = false
end
--vtol mode tracking
if (player == LOCAL_PLAYER) then
if(vehicle_is_vtol_jet(player_vehicle) and M11_globals.local_vtol_jet == false) then
M11_globals.local_vtol_jet = true
m11_wait_for_audio()
M11_globals.playing_line = true
audio_play_persona_line(player, M11_lines.jet_mode)
delay(3)
M11_globals.playing_line = false
--play line
elseif(vehicle_is_vtol_hover(player_vehicle) and M11_globals.local_vtol_jet == true and M11_globals.local_vtol_hover == false) then
M11_globals.local_vtol_hover = true
m11_wait_for_audio()
M11_globals.playing_line = true
audio_play_persona_line(player, M11_lines.vtols_are_cool)
delay(3)
M11_globals.playing_line = false
--play line
end
else
if(vehicle_is_vtol_jet(player_vehicle) and M11_globals.remote_vtol_jet == false) then
M11_globals.remote_vtol_jet = true
m11_wait_for_audio()
M11_globals.playing_line = true
audio_play_persona_line(player, M11_lines.jet_mode)
delay(3)
M11_globals.playing_line = false
--play line
elseif(vehicle_is_vtol_hover(player_vehicle) and M11_globals.remote_vtol_jet == true and M11_globals.remote_vtol_hover == false) then
M11_globals.remote_vtol_hover = true
m11_wait_for_audio()
M11_globals.playing_line = true
audio_play_persona_line(player, M11_lines.vtols_are_cool)
delay(3)
M11_globals.playing_line = false
--play line
end
end
--end
end
end
delay(2)
end
end
-- Trigger Pierce's warning line when appropriate
function m11_timer_thread()
-- Start the countdown
hud_timer_set(1, M11_globals.air_base_time, "m11_fail_timer", SYNC_ALL)
local played = false
while not played do
if (hud_timer_get_remainder(1) < M11_globals.warn_time) then
M11_conv.kill_plane.handle = audio_conversation_load(M11_conv.kill_plane.name)
audio_conversation_play(M11_conv.kill_plane.handle)
played = true
end
thread_yield()
end
end
-- Process decrementing the attention meter, and trigger Pierce's lines when appropriate
--function m11_process_stag_attention_thread()
-- while true do
-- delay(M11_globals.stag_attention.diminish_rate)
-- M11_globals.stag_attention.value = M11_globals.stag_attention.value - M11_globals.stag_attention.diminish_value
-- hud_bar_set_value(1, M11_globals.stag_attention.value)
--
-- -- Only play the warnings exactly at the marks
-- if (M11_globals.stag_attention.value < 0.75 and M11_globals.stag_attention.value >= 0.74 and M11_globals.stag_attention.first_warning == false) then
-- -- Play Pierce's 75% complaint
-- audio_play_persona_line_2d(M11_personas.pierce.handle, "M11_STAG_Attention_01")
-- M11_globals.stag_attention.first_warning = true
-- elseif (M11_globals.stag_attention.value < 0.5 and M11_globals.stag_attention.value >= 0.49 and M11_globals.stag_attention.second_warning == false) then
-- -- Play Pierce's 50% complaint
-- audio_play_persona_line_2d(M11_personas.pierce.handle, "M11_STAG_Attention_02")
-- M11_globals.stag_attention.second_warning = true
-- elseif (M11_globals.stag_attention.value < 0.25 and M11_globals.stag_attention.third_warning == false) then
-- -- TODO: Play Pierce's 25% complaint
-- audio_play_persona_line_2d(M11_personas.pierce.handle, "M11_STAG_Attention_01")
-- M11_globals.stag_attention.third_warning = true
-- elseif (M11_globals.stag_attention.value < 0.01) then
-- -- The player has failed
-- mission_end_failure("m11", "m11_fail_stag")
-- end
-- end
--end
-- Take off to a given location
--
-- lifter: (table) table containing a vtol, pilot, and destination navpoint
--
function m11_airport_lift_thread(lifter)
-- Wait for a player to get close
while (get_dist_closest_player_to_object(lifter.pilot) > 200) do
thread_yield()
end
-- Send the pilot running to the VTOL
vehicle_enter_teleport(lifter.pilot, lifter.name, 0, true)
-- TODO: No vehicle animations for VTOL, so this doesn't work, yet
--vehicle_enter(lifter.pilot, lifter.name, 0, true, true)
-- Lift off!
helicopter_fly_to_direct(lifter.name, 10.0, lifter.nav)
-- Once the destination is reached, attack the player
vehicle_chase(lifter.name, CLOSEST_PLAYER, false)
end
-- Land at a given location
--
-- lander: (table) table containing a vtol, pilot, and landing navpoints
--
function m11_airport_land_thread(lander)
-- Warp the pilot in and start the VTOL on its way
vehicle_enter_teleport(lander.pilot, lander.name, 0)
helicopter_fly_to_direct_dont_stop(lander.name, 25.0, lander.nav[1])
-- Once the destination is reached, land
helicopter_land(lander.name, lander.nav[2])
delay(10)
-- Release the VTOL, now that its script is done
release_to_world(lander.name)
release_to_world(lander.pilot)
end
-- Drive to the specified point and perform a new action
--
-- vehicle: (table) contains the name of the vehicle to move and its occupants
-- index: (int) index of the navpoint to move to, also used for following action
--
function m11_battle_thread(vehicle, index)
if (vehicle_is_vtol(vehicle.name)) then
-- Start aiming at player
ai_add_enemy_target(vehicle.driver, CLOSEST_PLAYER, ATTACK_NOW, true)
vehicle_chase(vehicle.name, CLOSEST_PLAYER)
-- -- Path to the player
-- vehicle_pathfind_to(vehicle.name, M11_groups.oleg_battle.dest[index], false, true)
-- while not vehicle_pathfind_check_done(vehicle.name) do
-- thread_yield()
-- end
else
-- Focus on Oleg to provide threat
-- Chase Oleg (via navmesh; no traffic splines in his area)
vehicle_pathfind_to(vehicle.name, M11_groups.oleg_battle.dest[index], true, false)
while not vehicle_pathfind_check_done(vehicle.name) do
thread_yield()
end
vehicle_disable_chase(vehicle.name)
vehicle_exit_group(vehicle.members)
for i, npc in pairs (vehicle.members) do
ai_add_enemy_target(npc, M11_groups.oleg_battle.oleg.oleg, ATTACK_NOW_NEVER_LOSE, true)
end
--vehicle_chase(vehicle.name, M11_groups.oleg_battle.oleg.oleg, false, false, true, false)
end
end
function m11_spawn_oleg_tanks()
for i,group in pairs(oleg_tanks) do
if group_is_loaded(group.name) == false then
group_create(group.name, true)
end
vehicle_enter_group_teleport(group.members, group.vehicle)
--Mark tanks add to required kill group
--marker_add(group.vehicle, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAG_STICKY)
--on_vehicle_destroyed("m11_target_destroyed", group.vehicle)
--M11_globals.num_targets = M11_globals.num_targets + 1
end
end
-- Send tanks to their destinations
--
function m11_deploy_tanks()
for i,group in pairs(oleg_tanks) do
if not vehicle_is_destroyed(group.vehicle) then
group.move_thread = thread_new( "m11_wrapper_thread", vehicle_pathfind_to, group.vehicle, group.dest, true )
--vehicle_pathfind_to(group.vehicle, group.dest, use_navmesh, stop_at_goal, force_path, suppress_errors)
end
end
end
function m11_tank_targets()
for i,group in pairs(oleg_tanks) do
if not vehicle_is_destroyed(group.vehicle) then
--ai_add_enemy_target(group.driver, M11_groups.oleg_battle.oleg.oleg, ATTACK_NOW_NEVER_LOSE, true)
--Mark tanks add to required kill group
marker_add(group.vehicle, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAG_STICKY)
on_vehicle_destroyed("m11_target_destroyed", group.vehicle)
M11_globals.num_targets = M11_globals.num_targets + 1
end
end
end
function m11_tank_attack()
for i,group in pairs(oleg_tanks) do
ai_add_enemy_target(group.members[1], M11_groups.oleg_battle.oleg.oleg, ATTACK_NOW_NEVER_LOSE, true)
ai_add_enemy_target(group.members[1], M11_groups.oleg_battle.oleg.oleg, ATTACK_NOW_NEVER_LOSE, true)
ai_add_enemy_target(group.members[1], M11_groups.oleg_battle.oleg.oleg, ATTACK_NOW_NEVER_LOSE, true)
end
end
-- Fly a helicopter along the specified path
--
-- heli: (string) name of the helicotper to move
-- nav: (string) name of the path to move along
--
function m11_fly_path_thread(heli, path)
-- Force the heli to keep following the path
while (true) do
helicopter_fly_to_direct_dont_stop(heli, 25.0, path)
thread_yield()
end
end
-- Fly a helicopter along the specified path, but chase nearby players
--
-- heli: (string) name of the helicotper to move
-- nav: (string) name of the path to move along
--
function m11_fly_path_guard_thread(heli, path)
local abort = false
local dist = 0
local player = nil
-- Send it on a path
helicopter_fly_to_do(heli, 25.0, true, "", true, path, 0.0, false)
while not abort do
-- If the player approaches, break off and attack
dist, player = get_dist_closest_player_to_object(heli)
if (dist < 500) then
vehicle_chase(heli, player, false, false)
abort = true
--elseif vehicle_pathfind_check_done(heli) then
-- -- If the path is finished, send it on the same path again
-- helicopter_fly_to_do(heli, 25.0, true, "", true, path, 0.0, false)
end
thread_yield()
end
end
function m11_fly_path_target_thread(heli, path)
local abort = false
local dist = 0
local player = nil
-- Send it on a path
helicopter_fly_to_do(heli, 25.0, true, "", true, path, 0.0, false)
while not M11_globals.final_targets_attack do
thread_yield()
end
while not abort do
-- If the player approaches, break off and attack
dist, player = get_dist_closest_player_to_object(heli)
if (dist < 500) then
vehicle_chase(heli, player, false, false)
abort = true
--elseif vehicle_pathfind_check_done(heli) then
-- -- If the path is finished, send it on the same path again
-- helicopter_fly_to_do(heli, 25.0, true, "", true, path, 0.0, false)
end
thread_yield()
end
end
function m11_convoy_cleanup_thread(roadblock)
-- Set up the convoy
for i, vehicle in pairs(roadblock.convoy.vehicles) do
-- Now we should fail only if the players kill the convoy
on_vehicle_destroyed("m11_post_obj_convoy_death_callback", vehicle.name)
for j, person in pairs(vehicle.passengers) do
on_death("m11_post_obj_convoy_death_callback", person)
end
end
local abort = false
local dist = 0
local player = nil
while not abort do
-- When the player gets a good distance away, release the convoy to the world.
dist, player = get_dist_closest_player_to_object(roadblock.location)
if (dist > 500) then
-- Release the remnants
if group_is_loaded(roadblock.name) then
release_to_world(roadblock.name)
group_destroy(roadblock.name)
end
abort = true
end
thread_yield()
end
end
-- Thead the convos for the air base because they tend to get stuck
function m11_air_base_convos_thread()
M11_conv.awacs.handle = audio_conversation_load(M11_conv.awacs.name)
while not M11_conv.awacs.play do
thread_yield()
end
audio_conversation_play(M11_conv.awacs.handle)
delay(1.0)
-- emergency kill if needed
local convo_over = false
while not convo_over do
if not audio_conversation_playing(M11_conv.awacs.handle) then
convo_over = true
end
if M11_conv.awacs.kill then
convo_over = true
end
thread_yield()
end
audio_conversation_end(M11_conv.awacs.handle)
M11_conv.awacs.handle = INVALID_CONVERSATION_HANDLE
M11_conv.killing_escorts.handle = audio_conversation_load(M11_conv.killing_escorts.name)
while not M11_conv.killing_escorts.play do
thread_yield()
end
audio_conversation_play(M11_conv.killing_escorts.handle)
delay(1.0)
-- emergency kill if needed
convo_over = false
while not convo_over do
if not audio_conversation_playing(M11_conv.killing_escorts.handle) then
convo_over = true
end
if M11_conv.killing_escorts.kill then
convo_over = true
end
thread_yield()
end
audio_conversation_end(M11_conv.killing_escorts.handle)
M11_conv.killing_escorts.handle = INVALID_CONVERSATION_HANDLE
end