--[[
m10.lua
SR3 Mission Script
DATE: 9-14-10
AUTHOR: John Karczewski
]]--
-- Debug flags --
-- Tweakable Parameters --
M10_tweak_parameters = {
roof_vtol_shoot_delay = { 20.0, 35.0 }, -- (min, max) in seconds
club_fake_notoriety_level = 4,
goto_hq_notoriety_level = 4,
drive_01_dist_from_hq = 1600,
shaundi_update_dist_from_hq = 900,
-- drive_02_dist_from_hq = 1200,
rooftop_soldier_spread_mult = 0.0001,
}
M10_timed_lines = {
stag = {
situation = "m10_attack",
delay = 10.0,
callback = "m10_stag_attack_cb",
timer = INVALID_THREAD_HANDLE
}
}
-- Dialog lines --
M10_dialog_lines = {
mission_start = "M10_Mission_Start",
laser_guns = "M10_Call_Out_Laser_Guns",
get_to_roof = "M10_Get_To_Roof",
rooftop_start = "M10_Rooftop_Start",
first_dropoff = "M10_First_Dropoff_On_Roof_01",
second_dropoff = "M10_Second_Dropoff_On_Roof_01",
third_dropoff = "M10_Third_Dropoff_On_Roof_01",
first_wave = "M10_First_VTOL_Wave_01",
second_wave = "M10_Second_VTOL_Wave_01",
across_street = "M10_Dropoff_Across_Street_01",
stag_bullhorn_01 = "M10_STAG_Ground_Bullhorn_01",
stag_bullhorn_02 = "M10_STAG_Ground_Bullhorn_02",
stag_bullhorn_03 = "M10_STAG_Ground_Bullhorn_03",
stag_bullhorn_04 = "M10_STAG_Ground_Bullhorn_04",
stag_bullhorn_vtol_01 = "M10_STAG_VTOL_Bullhorn_01",
stag_bullhorn_vtol_02 = "M10_STAG_VTOL_Bullhorn_02",
ammo_callout = "M10_Call_Out_Ammo_On_Roof",
oleg_downed = "M10_Oleg_Down",
oleg_help = "M10_Help_Oleg_Up",
oleg_revived = "M10_Oleg_Up",
oleg_roar = "M10_Oleg_Leap",
oleg_vtol = "M10_Oleg_VTOL",
oleg_jump_player = "M10_STAG_VTOL_Oleg_Jumps_On",
oleg_riding_vtol = "M10_See_Oleg_On_VTOL",
elevator_fixed = "M10_Elevator_Fixed",
off_the_roof = "M10_Leaving",
exit_building = "M10_Exiting_Building",
roadblocks_01 = "M10_Roadblocks_01",--**
roadblocks_02 = "M10_Roadblocks_02",--**
radio_drive = "M10_End_Radio_Newscast",
}
-- Conversations --
M10_convo = {
stag_entrance = {
name = "M10_Stag_Entrance_01",
handle = INVALID_CONVERSATION_HANDLE,
load_direct = false,
},
building_surrounded = {
name = "M10_Building_Surrounded",
handle = INVALID_CONVERSATION_HANDLE,
load_direct = false,
},
elevators = {
name = "M10_Power_Cut_To_Elevator",
handle = INVALID_CONVERSATION_HANDLE,
load_direct = true,
},
viola_check_in = {
name = "M10_Checkin_In_On_Viola",
handle = INVALID_CONVERSATION_HANDLE,
load_direct = false,
},
oleg_check_in = {
name = "M10_Checkin_In_On_Oleg",
handle = INVALID_CONVERSATION_HANDLE,
load_direct = false,
},
oleg_walking = {
name = "M10_Oleg_Walking_To_Spot",
handle = INVALID_CONVERSATION_HANDLE,
load_direct = false,
},
to_hq = {
name = "M10_Saints_HQ",
handle = INVALID_CONVERSATION_HANDLE,
load_direct = false,
},
drive_01 = {
name = "M10_Drive_01",
handle = INVALID_CONVERSATION_HANDLE,
load_direct = false,
},
oleg_flyby = { --**
name = "M10_Oleg_Flies_By_On_VTOL",
handle = INVALID_CONVERSATION_HANDLE,
load_direct = false,
},
city_update = {
name = "M10_City_Update_Call_01",
handle = INVALID_CONVERSATION_HANDLE,
load_direct = false,
},
}
-- Checkpoints --
M10_checkpoints = {
start = {
name = MISSION_START_CHECKPOINT, -- defined in ug_lib.lua
player_starts = { "nav_player_start_chk_01_ 001", "nav_player_start_chk_01_ 002" },
},
survive = {
name = "m10_checkpoint_survive",
player_starts = { "nav_player_start_chk_02_ 001", "nav_player_start_chk_02_ 002" },
},
oleg_to_the_rescue = {
name = "m10_checkpoint_oleg_to_the_rescue",
player_starts = { "nav_player_start_chk_02_ 001", "nav_player_start_chk_02_ 002" },
},
escape_to_hq = {
name = "m10_checkpoint_escape_to_hq",
player_starts = { "nav_player_start_chk_04_ 001", "nav_player_start_chk_04_ 002" },
}
}
-- Groups --
M10_groups = {
oleg = {
name = "Group_oleg 001",
members = { "char_oleg 001" },
oleg = "char_oleg 001"
},
viola = {
name = "Group_viola 001",
members = { "char_viola 001" },
viola = "char_viola 001"
},
strippers = {
name = "Group_club_ambient_peds 001",
members = { "char_npc_stripper 001", "char_npc_stripper 002", "char_npc_stripper 003",
"char_npc_stripper 004",
},
anims = { "Stand_Strip", "PoleDancer_C", "Stand_Strip", "PoleDancer_B" }
},
stag_ambush = {
name = "Group_stag_ambush 001",
squads = {
-- back_hall = {
-- chars = { "char_stag_back_hall 001", "char_stag_back_hall 002", "char_stag_back_hall 003" },
-- destination = "nav_stag_back_hall_dest 001",
-- },
front_door = {
chars = { "char_stag_front_door 001", "char_stag_front_door 002", },
destination = "nav_stag_front_door_dest 001",
},
main_stage_01 = {
chars = { "char_stag_main_stage 001", "char_stag_main_stage 002" },
destination = "nav_stag_main_stage_dest 001",
},
main_stage_02 = {
chars = { "char_stag_main_stage 003", "char_stag_main_stage 004" },
destination = "nav_stag_main_stage_dest 002",
},
main_stage_03 = {
chars = { "char_stag_main_stage 005", "char_stag_main_stage 006" },
destination = "nav_stag_main_stage_dest 003",
},
-- side_stage = {
-- chars = { "char_stag_side_stage 001", "char_stag_side_stage 002" },
-- destination = "nav_stag_side_stage_dest 001",
-- },
},
flashbang_throwers = {
chars = { "char_stag_main_stage 005", "char_stag_main_stage 003" },
targets = { "nav_stag_flashbang 001", "nav_stag_flashbang 002" },
},
},
police_containment = {
name = "Group_police_containment 001",
vehicles = { "veh_containment_cop_car 001", "veh_containment_cop_car 002", "veh_containment_cop_car 003",
"veh_containment_cop_car 004", "veh_containment_cop_car 005", "veh_containment_cop_car 006",
"veh_containment_cop_car 007", "veh_containment_cop_car 008", "veh_containment_cop_car 009" },
},
emergency_responders = {
name = "Group_emergency_responders 001",
vehicles = {
{
vehicle = "veh_emt_cop_car 001",
chars = { },
},
},
},
stag_ground_troops = {
name = "Group_stag_ground_troops 001",
tanks = {
{
tank = "veh_stag_tank 001",
chars = { "char_stag_tank_driver 001" },-- "char_stag_tank_gunner 001" },
chase_path = "path_stag_tank_chase 001",
thread_id = -1,
},
{
tank = "veh_stag_tank 002",
chars = { "char_stag_tank_driver 002" },--, "char_stag_tank_gunner 002" },
chase_path = "path_stag_tank_chase 001",
thread_id = -1,
},
{
tank = "veh_stag_tank 003",
chars = { "char_stag_tank_driver 003" },--, "char_stag_tank_gunner 003" },
chase_path = "path_stag_tank_chase 002",
thread_id = -1,
},
{
tank = "veh_stag_tank 004",
chars = { "char_stag_tank_driver 004"},--, "char_stag_tank_gunner 004" },
chase_path = "path_stag_tank_chase 002",
thread_id = -1,
},
},
troops = { "char_stag_trooper 009", "char_stag_trooper 010", "char_stag_trooper 011", "char_stag_trooper 012",
"char_stag_trooper 013", "char_stag_trooper 014", "char_stag_trooper 015" },
},
stag_ext_aftermath = {
name = "group_stag_ext_aftermath 001",
vehicle = { "veh_stag_aftermath 001", "veh_stag_aftermath 002", "veh_stag_aftermath 003", "veh_stag_aftermath 004",
"veh_stag_aftermath 005" },
gunners = { "char_gunner_aftermath 001", "char_gunner_aftermath 002" },
chars = { "char_stag_aftermath 001", "char_stag_aftermath 002", "char_stag_aftermath 003", "char_stag_aftermath 004",
"char_stag_aftermath 005" },
},
vtol_cont_spawn_02 = {
name = "Group_vtol_cont_spawn 002",
vtol = "veh_vtol_cont_spawn_02_ 001",
chars = { "char_vtol_cont_spawn_02_ 001", "char_vtol_cont_spawn_02_ 002", "char_vtol_cont_spawn_02_ 003",
"char_vtol_cont_spawn_02_ 004", "char_vtol_cont_spawn_02_ 005" },
path = "path_vtol_cont_spawn_02_ 001",
},
vtol_intro_flyby_01 = {
name = "Group_vtol_intro 001",
vtols = {
{
vehicle = "veh_vtol_intro_01_ 001",
chars = { "char_vtol_intro_pilot_01_ 001" },
path = "path_vtol_intro_01_ 001",
speed = 120.0,
invulnerable = false,
thread_id = -1,
},
{
vehicle = "veh_vtol_intro_01_ 002",
chars = { "char_vtol_intro_pilot_01_ 002" },
path = "path_vtol_intro_01_ 002",
speed = 120.0,
invulnerable = false,
thread_id = -1,
},
{
vehicle = "veh_vtol_intro_01_ 003",
chars = { "char_vtol_intro_pilot_01_ 003" },
path = "path_vtol_intro_01_ 003",
speed = 120.0,
invulnerable = false,
thread_id = -1,
},
{
vehicle = "veh_vtol_intro_01_ 004",
chars = { "char_vtol_intro_pilot_01_ 004" },
path = "path_vtol_intro_01_ 004",
speed = 120.0,
invulnerable = false,
thread_id = -1,
},
},
},
vtol_transport_flyby_01 = {
name = "Group_vtol_trans_flyby 001",
vtols = {
{
vehicle = "veh_trans_flyby_01_ 001",
chars = { "char_trans_flyby_pilot_01_ 001" },
path = "path_trans_flyby_01_ 001",
speed = 100.0,
invulnerable = false,
thread_id = -1,
},
{
vehicle = "veh_trans_flyby_01_ 002",
chars = { "char_trans_flyby_pilot_01_ 002" },
path = "path_trans_flyby_01_ 002",
speed = 100.0,
invulnerable = false,
thread_id = -1,
},
{
vehicle = "veh_trans_flyby_01_ 003",
chars = { "char_trans_flyby_pilot_01_ 003" },
path = "path_trans_flyby_01_ 003",
speed = 100.0,
invulnerable = false,
thread_id = -1,
},
{
vehicle = "veh_trans_flyby_01_ 004",
chars = { "char_trans_flyby_pilot_01_ 004" },
path = "path_trans_flyby_01_ 004",
speed = 100.0,
invulnerable = false,
thread_id = -1,
},
},
},
--[[
attack_vtols_01 = {
name = "Group_attack_vtol 001",
vtols = {
{
vtol = "veh_attack_vtol_01_ 001",
chars = { "char_attack_vtol_pilot_01_ 001" },
destination = "nav_attack_vtol_dest_01_ 001",
delay = 1.0,
speed = 10.0,
thread_id = -1,
},
},
},
--]]
attack_vtols_02 = {
name = "Group_attack_vtol 002",
vtols = {
{
vtol = "veh_attack_vtol_02_ 001",
chars = { "char_attack_vtol_pilot_02_ 001" },
destination = "path_attack_vtol_02_ 001",
delay = 0.0,
speed = 120.0,
thread_id = -1,
},
--[[
{
vtol = "veh_attack_vtol_02_ 002",
chars = { "char_attack_vtol_pilot_02_ 002" },
destination = "path_attack_vtol_02_ 002",
delay = 0.0,
speed = 100.0,
thread_id = -1,
},
--]]
},
},
stag_transport_01a = {
name = "Group_stag_transport 001a",
vtol = "veh_stag_transport_01a_ 001",
pilots = { "char_stag_trans_pilot_01a_ 001" },
drop_offs = {
{
soldiers = { "char_stag_trans_soldier_01a_ 001", "char_stag_trans_soldier_01a_ 002", "char_stag_trans_soldier_01a_ 003",
"char_stag_trans_soldier_01a_ 004" },
navs = { "nav_stag_trans_soldier_01a_ 001", "nav_stag_trans_soldier_01a_ 002", "nav_stag_trans_soldier_01a_ 003",
"nav_stag_trans_soldier_01a_ 004" },
path = "path_stag_transport_01a_ 001",
},
},
heli_dropoff_nav = "nav_trans_dropoff_01a",
escape_path = "path_stag_transport_01a_ 002",
rooftop_trigger = "tgr_rooftop_area 001a",
thread_id = -1,
marker_added = false,
marker_removed = false,
snipers = false,
oleg_line = M10_dialog_lines.first_dropoff,
},
stag_transport_01a_vtol = {
name = "Group_stag_transport_vtol 001a",
vtol = "veh_stag_transport_01a_ 001",
},
stag_transport_01 = {
name = "Group_stag_transport 001",
vtol = "veh_stag_transport_01_ 001",
pilots = { "char_stag_trans_pilot_01_ 001" },
drop_offs = {
{
soldiers = { "char_stag_trans_soldier_01_ 001", "char_stag_trans_soldier_01_ 002", "char_stag_trans_soldier_01_ 003",
"char_stag_trans_soldier_01_ 004" },
navs = { "nav_stag_trans_soldier_01_ 001", "nav_stag_trans_soldier_01_ 002", "nav_stag_trans_soldier_01_ 003",
"nav_stag_trans_soldier_01_ 004" },
path = "path_stag_transport_01_ 001",
dialog = { speaker = "Interrogation", line = "M10_STAG_Ground_Bullhorn_01" },
},
},
heli_dropoff_nav = "nav_trans_dropoff_01",
escape_path = "",
rooftop_trigger = "tgr_rooftop_area 001",
thread_id = -1,
marker_added = false,
marker_removed = false,
bullhorn = "",
snipers = false,
oleg_line = "",
},
stag_transport_01_vtol = {
name = "Group_stag_transport_vtol 001",
vtol = "veh_stag_transport_01_ 001",
},
stag_transport_02 = {
name = "Group_stag_transport 002",
vtol = "veh_stag_transport_02_ 001",
pilots = { "char_stag_trans_pilot_02_ 001" },
drop_offs = {
{
soldiers = { "char_stag_trans_soldier_02_ 001", "char_stag_trans_soldier_02_ 002", "char_stag_trans_soldier_02_ 003",
"char_stag_trans_soldier_02_ 004" },
navs = { "nav_stag_trans_soldier_02_ 001", "nav_stag_trans_soldier_02_ 002", "nav_stag_trans_soldier_02_ 003",
"nav_stag_trans_soldier_02_ 004" },
path = "path_stag_transport_02_ 001",
dialog = { speaker = "Interrogation", line = "M10_STAG_Ground_Bullhorn_02" },
},
},
heli_dropoff_nav = "nav_trans_dropoff_02",
escape_path = "",
rooftop_trigger = "tgr_rooftop_area 002",
thread_id = -1,
marker_added = false,
marker_removed = false,
snipers = false,
oleg_line = "",
},
stag_transport_02_vtol = {
name = "Group_stag_transport_vtol 002",
vtol = "veh_stag_transport_02_ 001",
},
stag_transport_02b = {
name = "Group_stag_transpot 002b",
vtol = "veh_stag_transport_02b_ 001",
pilots = { "char_stag_trans_pilot_02b_ 001" },
drop_offs = {
{
soldiers = { "char_stag_trans_soldier_02b_ 001", "char_stag_trans_soldier_02b_ 002", "char_stag_trans_soldier_02b_ 003", "char_stag_trans_soldier_02b_ 004" },
navs = { "nav_stag_trans_soldier_02b_ 001", "nav_stag_trans_soldier_02b_ 002", "nav_stag_trans_soldier_02b_ 003",
"nav_stag_trans_soldier_02b_ 004" },
path = "path_stag_transport_02b_ 001",
-- dialog = { speaker = LOCAL_PLAYER, line = "M10_Call_Out_Ammo_On_Roof" },
},
},
heli_dropoff_nav = "nav_trans_dropoff_02b",
escape_path = "path_stag_transport_01a_ 002",
rooftop_trigger = "tgr_rooftop_area 002b",
thread_id = -1,
marker_added = false,
marker_removed = false,
snipers = false,
oleg_line = M10_dialog_lines.second_dropoff,
},
stag_transport_02b_vtol = {
name = "Group_stag_transport_vtol 002b",
vtol = "veh_stag_transport_02b_ 001",
},
stag_transport_03 = {
name = "Group_stag_transport 003",
vtol = "veh_stag_transport_03_ 001",
pilots = { "char_stag_trans_pilot_03_ 001" },
drop_offs = {
{
soldiers = { "char_stag_trans_soldier_03_ 001", "char_stag_trans_soldier_03_ 002", "char_stag_trans_soldier_03_ 003",
"char_stag_trans_soldier_03_ 004" },
navs = { "nav_stag_trans_soldier_03_ 001", "nav_stag_trans_soldier_03_ 002", "nav_stag_trans_soldier_03_ 003",
"nav_stag_trans_soldier_03_ 004" },
path = "path_stag_transport_03_ 001",
dialog = { speaker = "Interrogation", line = "M10_STAG_Ground_Bullhorn_03" },
},
},
heli_dropoff_nav = "nav_trans_dropoff_03",
escape_path = "",
rooftop_trigger = "tgr_rooftop_area 003",
thread_id = -1,
marker_added = false,
marker_removed = false,
snipers = false,
oleg_line = "",
},
stag_transport_03_vtol = {
name = "Group_stag_transport_vtol 003",
vtol = "veh_stag_transport_03_ 001",
},
stag_transport_04 = {
name = "Group_stag_transport 004",
vtol = "veh_stag_transport_04_ 001",
pilots = { "char_stag_trans_pilot_04_ 001" },
drop_offs = {
{
soldiers = { "char_stag_trans_soldier_04_ 001", "char_stag_trans_soldier_04_ 002", "char_stag_trans_soldier_04_ 003", "char_stag_trans_soldier_04_ 004" },
navs = { "nav_stag_trans_soldier_04_ 001", "nav_stag_trans_soldier_04_ 002", "nav_stag_trans_soldier_04_ 003",
"nav_stag_trans_soldier_04_ 004" },
path = "path_stag_transport_04_ 001",
dialog = { speaker = "char_viola 001", line = "M10_Rooftop_02" },
},
},
heli_dropoff_nav = "nav_trans_dropoff_04",
escape_path = "",
rooftop_trigger = "tgr_rooftop_area 004",
thread_id = -1,
marker_added = false,
marker_removed = false,
snipers = true,
oleg_line = "",
},
stag_transport_04_vtol = {
name = "Group_stag_transport_vtol 004",
vtol = "veh_stag_transport_04_ 001",
},
stag_transport_05 = {
name = "Group_stag_transport 005",
vtol = "veh_stag_transport_05_ 001",
pilots = { "char_stag_trans_pilot_05_ 001" },
drop_offs = {
{
soldiers = { "char_stag_trans_soldier_05_ 001", "char_stag_trans_soldier_05_ 002", "char_stag_trans_soldier_05_ 003", "char_stag_trans_soldier_05_ 004" },
navs = { "nav_stag_trans_soldier_05_ 001", "nav_stag_trans_soldier_05_ 002", "nav_stag_trans_soldier_05_ 003",
"nav_stag_trans_soldier_05_ 004" },
path = "path_stag_transport_05_ 001",
dialog = { speaker = "Interrogation", line = "M10_STAG_Ground_Bullhorn_04" },
},
},
heli_dropoff_nav = "nav_trans_dropoff_05",
escape_path = "path_stag_transport_01a_ 002",
rooftop_trigger = "tgr_rooftop_area 005",
thread_id = -1,
marker_added = false,
marker_removed = false,
snipers = false,
oleg_line = M10_dialog_lines.third_dropoff,
},
stag_transport_05_vtol = {
name = "Group_stag_transport_vtol 005",
vtol = "veh_stag_transport_05_ 001",
},
vtol_flyby_01 = {
name = "Group_vtol_flyby 001",
vtols = {
{
vehicle = "veh_vtol_flyby_01_ 001",
chars = { "char_vtol_flyby_pilot_01_ 001" },
path = "path_vtol_flyby_01_ 001",
target = "",
target_nav = "nav_vtol_flyby_01_ 001",
speed = 120.0,
invulnerable = false,
fired = false,
rockets = false,
thread_id = -1,
},
{
vehicle = "veh_vtol_flyby_01_ 002",
chars = { "char_vtol_flyby_pilot_01_ 002" },
path = "path_vtol_flyby_01_ 002",
target = "",
target_nav = "nav_vtol_flyby_01_ 002",
speed = 120.0,
invulnerable = false,
fired = false,
rockets = false,
thread_id = -1,
},
},
},
vtol_flyby_02 = {
name = "Group_vtol_flyby 002",
vtols = {
{
vehicle = "veh_vtol_flyby_02_ 001",
chars = { "char_vtol_flyby_pilot_02_ 001", "char_vtol_flyby_copilot_02_ 001" },
path = "path_vtol_flyby_02_ 001",
target = "char_oleg 001",
speed = 120.0,
invulnerable = true,
fired = false,
rockets = true,
thread_id = -1,
},
{
vehicle = "veh_vtol_flyby_02_ 002",
chars = { "char_vtol_flyby_pilot_02_ 002", "char_vtol_flyby_copilot_02_ 002" },
path = "path_vtol_flyby_02_ 002",
target = "char_oleg 001",
target_nav = "nav_vtol_flyby_02_ 002",
speed = 120.0,
invulnerable = true,
fired = false,
rockets = false,
thread_id = -1,
},
},
},
oleg_vtol = {
name = "Group_oleg_vtol 001",
member = "char_oleg_vtol_driver 001",
vtol = "veh_oleg_vtol 001",
driver = "char_oleg_vtol_driver 001",
path_approach = "path_oleg_vtol_approach 001",
path_dest = "path_oleg_vtol_dest 001",
nav_dest = "nav_oleg_vtol_dest 001",
-- Panic/escape
path = "path_oleg_vtol_jerky 001",
path_flee = "path_oleg_vtol_flee 001",
fire_navs = {
{ nav = "nav_oleg_vtol_shoot 001", duration = 1.0, alt_fire = false },
{ nav = "nav_oleg_vtol_shoot 002", duration = 2.0, alt_fire = false },
{ nav = "nav_oleg_vtol_shoot 003", duration = 1.0, alt_fire = true },
{ nav = "nav_oleg_vtol_shoot 004", duration = 2.0, alt_fire = false },
{ nav = "nav_oleg_vtol_shoot 005", duration = 3.0, alt_fire = false, destroy_vehicles = { "veh_stag_tank 001" } },
{ nav = "nav_oleg_vtol_shoot 006", duration = 1.0, alt_fire = true, destroy_vehicles = { "veh_stag_tank 002" } },
{ nav = "nav_oleg_vtol_shoot 007", duration = 2.0, alt_fire = false },
},
},
stag_elevator_guys = {
name = "Group_stag_elevator 001",
chars = { "char_stag_elevator 001", "char_stag_elevator 002", "char_stag_elevator 003", "char_stag_elevator 004"},
},
stag_club_aftermath = {
name = "Group_stag_club_aftermath 001",
members = { "char_stag_club_aftermath 001", "char_stag_club_aftermath 002", "char_stag_club_aftermath 003" },
},
saints_hq = {
name = "Group_saints_hq 001",
},
stag_encounter_bridge_01 = {
name = "Group_stag_bridge_encounter 001",
vehicles = {
{
vehicle = "veh_bridge_suv_01_ 001",
chars = { "char_bridge_suv_01_01_ 001", "char_bridge_suv_01_01_ 002" },
behavior = "exit_at_dest",
path = "path_bridge_suv_01_ 001", use_navmesh = true,
thread_id = -1,
},
{
vehicle = "veh_bridge_suv_01_ 002",
chars = { "char_bridge_suv_01_02_ 001", "char_bridge_suv_01_02_ 002" },
behavior = "exit_at_dest",
path = "path_bridge_suv_01_ 002", use_navmesh = true,
thread_id = -1,
},
{
vehicle = "veh_bridge_tank_01_ 001",
chars = { "char_bridge_tank_01_01_ 001", "char_bridge_tank_01_01_ 002" },
behavior = "stop_at_dest",
path = "path_bridge_tank_01_ 001", use_navmesh = true,
thread_id = -1,
},
},
creation_trigger = "tgr_bridge_creation 001",
action_trigger = "tgr_bridge_do_action 001",
max_activations = 1,
thread_id = INVALID_THREAD_HANDLE,
},
stag_encounter_bridge_02 = {
name = "Group_stag_bridge_encounter 002",
vehicles = {
{
vehicle = "veh_bridge_suv_02_ 001",
chars = { "char_bridge_suv_02_01_ 001", "char_bridge_suv_02_01_ 002" },
behavior = "exit_at_dest",
path = "path_bridge_suv_02_ 001", use_navmesh = true,
thread_id = -1,
},
{
vehicle = "veh_bridge_suv_02_ 002",
chars = { "char_bridge_suv_02_02_ 001", "char_bridge_suv_02_02_ 002" },
behavior = "exit_at_dest",
path = "path_bridge_suv_02_ 002", use_navmesh = true,
thread_id = -1,
},
{
vehicle = "veh_bridge_tank_02_ 001",
chars = { "char_bridge_tank_02_01_ 001", "char_bridge_tank_02_01_ 002" },
behavior = "stop_at_dest",
path = "path_bridge_tank_02_ 001", use_navmesh = false,
thread_id = -1,
},
},
creation_trigger = "tgr_bridge_creation 002",
action_trigger = "tgr_bridge_do_action 002",
max_activations = 1,
thread_id = INVALID_THREAD_HANDLE,
},
stag_encounter_chem_01 = {
name = "Group_stag_chem_encounter 001",
vehicles = {
{
vehicle = "veh_vtol_chem_plant 001",
chars = { "char_vtol_chem_plant_pilot 001" },
behavior = "fly_by",
path = "path_vtol_chem_plant 001",
speed = 100.0,
no_perfect_aim = true,
thread_id = -1,
},
{
vehicle = "veh_vtol_chem_plant 002",
chars = { "char_vtol_chem_plant_pilot 002" },
behavior = "fly_by",
path = "path_vtol_chem_plant 002",
speed = 100.0,
no_perfect_aim = true,
thread_id = -1,
},
},
creation_trigger = "tgr_chem_plant_creation 001",
action_trigger = "tgr_chem_plant_do_action 001",
max_activations = 1,
thread_id = INVALID_THREAD_HANDLE,
},
stag_encounter_bridge_03 = {
name = "Group_stag_encounter_bridge 001",
vehicles = {
{
vehicle = "veh_tank_bridge_03_ 001",
chars = { "char_tank_bridge_03_ 001", "char_tank_bridge_03_ 002" },
behavior = "stop_at_dest",
path = "path_tank_bridge_03_ 001", use_navmesh = false,
thread_id = -1,
},
{
vehicle = "veh_vtol_bridge_03_ 001",
chars = { "char_vtol_bridge_03_pilot 001", "char_vtol_bridge_03_copilot 001", "char_vtol_bridge_03_oleg 001" },
behavior = "fly_by_and_shoot",
path = "path_vtol_bridge_03_ 001",
target = "char_tank_bridge_03_ 001",
trigger = "tgr_vtol_bridge_03_fire 001",
speed = 50.0, invulnerable = true, fired = false,
rockets = true,
thread_id = -1,
},
},
creation_trigger = "tgr_bridge_creation 003",
action_trigger = "tgr_bridge_do_action 003",
max_activations = 1,
thread_id = INVALID_THREAD_HANDLE,
},
stag_encounter_bridge_04 = {
name = "Group_stag_bridge_encounter 004",
vehicles = {
{
vehicle = "veh_bridge_suv_04_ 001",
chars = { "char_bridge_suv_04_01_ 001", "char_bridge_suv_04_01_ 002" },
behavior = "exit_at_dest",
path = "path_bridge_suv_04_ 001", use_navmesh = true,
thread_id = -1,
},
{
vehicle = "veh_bridge_suv_04_ 002",
chars = { "char_bridge_suv_04_02_ 001", "char_bridge_suv_04_02_ 002" },
behavior = "exit_at_dest",
path = "path_bridge_suv_04_ 002", use_navmesh = true,
thread_id = -1,
},
{
vehicle = "veh_bridge_suv_04_ 003",
chars = { "char_bridge_suv_04_03_ 001", "char_bridge_suv_04_03_ 002" },
behavior = "exit_at_dest",
path = "path_bridge_suv_04_ 003", use_navmesh = true,
thread_id = -1,
},
},
creation_trigger = "tgr_bridge_creation 004",
action_trigger = "tgr_bridge_do_action 004",
max_activations = 1,
thread_id = INVALID_THREAD_HANDLE,
},
stag_encounter_bridge_05 = {
name = "Group_stag_bridge_encounter 005",
vehicles = {
{
vehicle = "veh_bridge_suv_05_ 001",
chars = { "char_bridge_suv_05_01_ 001", "char_bridge_suv_05_01_ 002" },
behavior = "exit_at_dest",
path = "path_bridge_suv_05_ 001", use_navmesh = true,
thread_id = -1,
},
{
vehicle = "veh_bridge_suv_05_ 002",
chars = { "char_bridge_suv_05_02_ 001", "char_bridge_suv_05_02_ 002" },
behavior = "exit_at_dest",
path = "path_bridge_suv_05_ 002", use_navmesh = true,
thread_id = -1,
},
},
creation_trigger = "tgr_bridge_creation 005",
action_trigger = "tgr_bridge_do_action 005",
max_activations = 1,
thread_id = INVALID_THREAD_HANDLE,
},
heli_soldiers = {"char_stag_trans_soldier_01a_ 001", "char_stag_trans_soldier_01a_ 002", "char_stag_trans_soldier_01a_ 003", "char_stag_trans_soldier_01a_ 004",
"char_stag_trans_soldier_01_ 001", "char_stag_trans_soldier_01_ 002", "char_stag_trans_soldier_01_ 003", "char_stag_trans_soldier_01_ 004",
"char_stag_trans_soldier_02_ 001", "char_stag_trans_soldier_02_ 002", "char_stag_trans_soldier_02_ 003", "char_stag_trans_soldier_02_ 004",
"char_stag_trans_soldier_02b_ 001", "char_stag_trans_soldier_02b_ 002", "char_stag_trans_soldier_02b_ 003", "char_stag_trans_soldier_02b_ 004",
"char_stag_trans_soldier_03_ 001", "char_stag_trans_soldier_03_ 002", "char_stag_trans_soldier_03_ 003", "char_stag_trans_soldier_03_ 004",
"char_stag_trans_soldier_04_ 001", "char_stag_trans_soldier_04_ 002", "char_stag_trans_soldier_04_ 003", "char_stag_trans_soldier_04_ 004",
"char_stag_trans_soldier_05_ 001", "char_stag_trans_soldier_05_ 002", "char_stag_trans_soldier_05_ 003", "char_stag_trans_soldier_05_ 004" },
weapons = { name = "Group_weapons 001" },
}
-- Navpoints --
M10_navpoints = {
mission_cancel = { "nav_player_mission_exit 001", "nav_player_mission_exit 002" },
oleg_start = "nav_oleg_start_chk_01_ 001",
viola_start = "nav_viola_start_chk_01_ 001",
oleg_roof = "nav_oleg_start_chk_02_ 001",
viola_roof = "nav_viola_start_chk_02_ 001",
roof_viola_investigate = "nav_viola_roof_investigate 001",
roof_oleg_investigate = "nav_oleg_roof_investigate 001",
roof_viola_fix_elevator = "nav_viola_roof_fix_elev 001",
roof_oleg_dest = "nav_roof_oleg_dest 001",
roof_viola_dest = "nav_roof_viola_dest 001",
oleg_sequence_oleg = "nav_oleg_sequence_oleg 001",
viola_roof_edge = "nav_viola_roof_edge 001",
mission_win = { "nav_player_mission_complete 001", "nav_player_mission_complete 002"},
clear_airspace_points = { "nav_clear_airspace_dest 001", "nav_clear_airspace_dest 002", "nav_clear_airspace_dest 003",
"nav_clear_airspace_dest 004", "nav_clear_airspace_dest 005", "nav_clear_airspace_dest 006",
"nav_clear_airspace_dest 007", "nav_clear_airspace_dest 008", "nav_clear_airspace_dest 009" },
stag_aftermath_rush = "nav_stag_aftermath 001"
}
-- Triggers --
M10_triggers = {
club_door = "tgr_club_door 001",
stag_ambush_01 = "tgr_stag_ambush 001",
front_door_exit = "tgr_front_door 001",
roof_kill_region = "tgr_roof_kill_region 001",
roof_air_space = "tgr_roof_air_space 001",
vtol_flyby_fire_01 = "tgr_vtol_flyby_fire 001",
vtol_flyby_fire_02 = "tgr_vtol_flyby_fire 002",
vtol_oi_01 = "tgr_vtol_OI 001",
vtol_oi_02 = "tgr_vtol_OI 002",
club_roof_area = "tgr_club_roof_area 001",
rooftop_elevator = "tgr_rooftop_elevator 001",
club_exit = "tgr_club_exit 001",
start_notoriety = "tgr_start_notoriety 001",
saints_hq = "tgr_saints_hq 001",
--saints_hq_traffic = "tgr_saints_hq 002",
}
-- Characters --
M10_characters = {
oleg = M10_groups.oleg.oleg,
viola = M10_groups.viola.viola
}
-- Vehicles --
M10_vehicles = {
oleg_vtol = M10_groups.oleg_vtol.vtol
}
-- Mesh Movers --
M10_movers = {
club_doors = {
main_stage = {
door_movers = { "mvr_main_stage_door 001" },
locked = false,
open = true,
},
front_door = {
door_movers = { "mvr_front_door 001" },
locked = true,
open = false,
},
back_door = {
door_movers = { "mvr_back_door 001" },
locked = true,
open = false,
},
lobby_door = {
door_movers = { "mvr_lobby_door 001" },
locked = false,
open = true,
},
roof_entry = {
door_movers = { "mvr_roof_entry_door 001" },
locked = true,
open = false,
},
roof_exit = {
door_movers = { "mvr_roof_exit_door 001" },
locked = true,
open = false,
},
},
}
-- Continuous Spawn Groups --
M10_spawn_groups = {
stag_roof = { "Group_stag_roof_cont_spawn 001", "Group_stag_roof_cont_spawn 002", "Group_stag_roof_cont_spawn 003" },
stag_club = { "Group_stag_club_cont_spawn 001", "Group_stag_club_cont_spawn 002" },
}
-- Spawn Regions --
M10_spawn_regions = {
stag_roof = { "spr_rooftop 001", "spr_rooftop 002" },
stag_club = { "spr_stag_club_cont_spawn 001", "spr_stag_club_cont_spawn 002", "spr_stag_club_cont_spawn 003" }
}
-- Text --
M10_strings = {
objective_escape_stag = "m10_obj_escape_stag",
objective_kill_rooftop_enemies = "m10_obj_kill_stag_on_roofs",
objective_kill_snipers = "m10_obj_kill_stag_snipers",
objective_kill_vtol = "m10_obj_kill_stag_vtol",
objective_survive = "m10_obj_survive",
objective_obj_escape_to_saints_hq = "m10_obj_escape_to_saints_hq",
failure_oleg_died = "m10_failure_oleg_died",
failure_viola_died = "m10_failure_viola_died",
failure_oleg_dismissed = "m10_failure_oleg_dismissed",
failure_viola_dismissed = "m10_failure_viola_dismissed",
}
-- Threads --
M10_threads = {
viola_rooftop_intro = INVALID_THREAD_HANDLE,
oleg_rooftop_intro = INVALID_THREAD_HANDLE,
vtol_flyby = INVALID_THREAD_HANDLE,
vtol_panic = INVALID_THREAD_HANDLE,
escape_convo = INVALID_THREAD_HANDLE,
soldier_count = INVALID_THREAD_HANDLE,
}
-- Cutscenes --
M10_cutscenes = {
mission_intro = "10_in",
rooftop_intro = "10_Mid",
mission_outro = "10_Out", --"10_out_v3" cannot find this video
}
-- Off-screen personas --
M10_personas = {
shaundi = {
name = "Shaundi",
persona_id = -1,
},
interrogation = {
name = "Interrogation",
persona_id = -1,
},
}
-- Other --
M10_cover_nodes = {
oleg_roof = "cvr_roof_oleg 001",
viola_roof = "cvr_roof_viola 001",
}
M10_vtol_cont_spawn = {
groups = {M10_groups.vtol_cont_spawn_02 },
thread_id = -1,
}
M10_runtime = {
mission10_completed = false,
player_reached_objective = false,
phonecall_complete = false,
ambush_soldiers_alive = 0,
transport_soldiers_alive = 0,
transport_snipers_alive = 0,
roof_attack_vtols_active = 0,
roof_attack_vtols_killed = 0,
vehicles_in_airspace = { },
damaged_vehicles_exiting = { },
spawned_vtols = { },
transport_vtols = { },
vtol_flyby_groups = { },
rooftop_trigger_chars = { },
stag_encounters = { },
}
-- *************************
--
-- 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
--
-- m10_checkpoint: The checkpoint the mission should begin at
-- is_restart: TRUE if the mission is restarting, FALSE otherwise
--
function m10_start(m10_checkpoint, is_restart)
-- Make sure the screen is completly faded out
mission_start_fade_out(0.0)
-- Check if this mission starting from the beginning
if (m10_checkpoint == M10_checkpoints.start.name) then
if (is_restart == false) then
-- First time playing mission
-- Play an intro cutscene???
if (M10_cutscenes.mission_intro ~= "") then
cutscene_play(M10_cutscenes.mission_intro, nil, M10_checkpoints.start.player_starts)
--bink_play(M10_cutscenes.mission_intro)
end
else
teleport_coop(M10_checkpoints.start.player_starts[1], M10_checkpoints.start.player_starts[2])
end
end
-- Handle mission initialization for the current checkpoint
m10_initialize(m10_checkpoint)
-- Start fading in
mission_start_fade_in()
-- Run the mission from the current checkpoint
m10_run(m10_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 m10_run(first_checkpoint)
local current_checkpoint = first_checkpoint
set_traffic_density(0.00001)
-- Run the mission from the beginning
if (current_checkpoint == M10_checkpoints.start.name) then
m10_run_get_to_the_front_door()
m10_run_lobby_cutscene()
-- Setup the perimeter and the rooftop
teleport( M10_characters.oleg, M10_navpoints.oleg_roof )
teleport( M10_characters.viola, M10_navpoints.viola_roof )
m10_setup_perimeter()
m10_setup_rooftop()
m10_setup_rooftop_intro()
-- Set the checkpoint
current_checkpoint = M10_checkpoints.survive.name
mission_set_checkpoint(M10_checkpoints.survive.name)
end
if (current_checkpoint == M10_checkpoints.survive.name) then
m10_run_rooftop_intro()
m10_run_vtol_transports_01()
m10_run_rooftop_attack_vtols()
-- Set the checkpoint
current_checkpoint = M10_checkpoints.oleg_to_the_rescue.name
mission_set_checkpoint(M10_checkpoints.oleg_to_the_rescue.name)
end
if (current_checkpoint == M10_checkpoints.oleg_to_the_rescue.name) then
m10_run_oleg_gets_downed()
m10_run_oleg_jump_on_vtol()
m10_run_oleg_vtol_panic()
m10_run_rooftop_escape()
thread_yield()
m10_setup_club_aftermath()
mission_start_fade_out()
teleport_coop(M10_checkpoints.escape_to_hq.player_starts[1], M10_checkpoints.escape_to_hq.player_starts[2])
mission_start_fade_in()
-- Set the checkpoint
current_checkpoint = M10_checkpoints.escape_to_hq.name
mission_set_checkpoint(M10_checkpoints.escape_to_hq.name)
end
if (current_checkpoint == M10_checkpoints.escape_to_hq.name) then
m10_run_escape_club_aftermath()
m10_run_escape_to_saints_hq()
end
-- Call mission success??
M10_runtime.mission10_completed = true -- Used to keep track of world state
mission_end_success("m10", M10_cutscenes.mission_outro, M10_navpoints.mission_win)
end
-- This is the primary function responsible for cleaning up the entire mission
-- CALLED FROM CODE (+++MUST RETURN IMMEDIATLY+++)
--
function m10_cleanup()
-- Call the clean-up functions for each sectin of the mission
m10_cleanup_get_to_the_front_door()
m10_cleanup_lobby_cutscene()
m10_cleanup_vtol_transports_01(true)
m10_cleanup_rooftop_attack_vtols()
m10_cleanup_oleg_gets_downed()
m10_cleanup_oleg_jump_on_vtol()
m10_cleanup_oleg_vtol_panic()
m10_cleanup_rooftop_escape()
m10_cleanup_escape_club_aftermath()
m10_cleanup_escape_to_saints_hq()
-- Clean up Oleg and Viola
party_dismiss_all()
m10_cleanup_oleg()
m10_cleanup_viola()
-- Reset notoriety
notoriety_set_can_decay(ENABLE)
hud_set_fake_notoriety("police", false)
notoriety_force_no_spawn("police", false)
notoriety_reset("police")
-- Clean-up all the script groups
cleanup_groups(M10_groups)
-- Make sure all the triggers have been cleared
for i, trigger in pairs(M10_triggers) do
m10_clear_trigger(trigger)
end
-- Clean-up any threads that are still running
for i, thread in pairs(M10_threads) do
if (thread_check_done(thread) == false) then
thread_kill(thread)
end
end
-- Cleanup any threads from VTOL fly-bys
for i, vtol in pairs(M10_groups.vtol_intro_flyby_01.vtols) do
if (thread_check_done(vtol.thread_id) == false) then
thread_kill(vtol.thread_id)
vtol.thread_id = -1
end
end
-- Cleanup any threads from VTOL fly-bys
for i, vtol in pairs(M10_groups.vtol_flyby_01.vtols) do
if (thread_check_done(vtol.thread_id) == false) then
thread_kill(vtol.thread_id)
vtol.thread_id = -1
end
end
-- Reverting World State Changes if Mission Failed
if (not M10_runtime.mission10_completed) then
set_stag_active(false)
end
-- Clean-up and conversations
for i, convo in pairs(M10_convo) do
if (convo.handle ~= INVALID_CONVERSATION_HANDLE) then
audio_conversation_end(convo.handle)
convo.handle = INVALID_CONVERSATION_HANDLE
end
end
-- clean up phonecalls
audio_remove_mission_cellphone(M10_convo.city_update.name)
audio_ambient_emitter_start( "m10_stripclub_music" )
-- Unload any loaded personas
for i, persona in pairs(M10_personas) do
if (persona.persona_id ~= -1) then
audio_persona_remove_2d(persona.persona_id)
persona.persona_id = -1
end
end
--cleanup callbacks
for i, squad in pairs(M10_groups.stag_ambush.squads) do
for j, char in pairs(squad.chars) do
on_death("", char)
on_attack_performed("", char)
end
end
for j, char in pairs(M10_groups.heli_soldiers) do
on_attack_performed("", char)
end
--make sure the player isn't a priority target anymore
character_make_priority_target(LOCAL_PLAYER, false)
if (coop_is_active()) then
character_make_priority_target(REMOTE_PLAYER, false)
end
-- Reset ped/vehicle density
set_ped_density(1.0)
set_traffic_density(1.0)
-- Re-enable roadblocks
roadblocks_enable(true)
city_zone_swap("thermint1", DISABLE) -- Disable the NW Thermopolye
end
-- Called when the mission has ended with success
-- CALLED FROM CODE (+++MUST RETURN IMMEDIATLY+++)
--
function m10_success()
--[[ INSERT ANY MISSION SPECIFIC SUCCESS STUFF ]]--
-- Set STAG to Spawn Heavy in their HQ Hood and be the active law group
M10_runtime.mission10_completed = true -- Sets Mission Completed if you use 'Mission_Win' for testing
local skip_teleport = true
m10_coop_skip(skip_teleport) -- do the stuff we'd do in the skip case
end
-- *************************
--
-- Local functions
--
-- *************************
-- Initialize the mission for the specified checkpoint
--
-- checkpoint: Checkpoint to initialize the mission to
--
function m10_initialize(checkpoint)
-- Set the mission author
set_mission_author("John Karczewski")
-- Common initialization
m10_initialize_common()
-- Checkpoint specific initialization
m10_initialize_checkpoint(checkpoint)
end
-- ***************************************************
-- m10_initialize Helper Functions
-- ***************************************************
-- Handle any common initialization
--
function m10_initialize_common()
set_stag_active(ENABLE)
-- Load the persona for STAG members
M10_personas.interrogation.persona_id = audio_persona_load_2d(M10_personas.interrogation.name)
-- Setup the doors to their initial states
for i, door in pairs(M10_movers.club_doors) do
m10_setup_door(door)
end
hud_set_fake_notoriety("police", true, M10_tweak_parameters.club_fake_notoriety_level)
notoriety_force_no_spawn("police", true)
notoriety_set_max("police", 1)
notoriety_set("police", 1)
city_zone_swap("thermint1")
-- Set the mission cancel warp locations
mission_set_cancel_warp_location(M10_navpoints.mission_cancel[1], M10_navpoints.mission_cancel[2])
end
-- Checkpoint specific initialization
--
-- checkpoint: The checkpoint to be initialized
function m10_initialize_checkpoint(checkpoint)
audio_object_post_event( "m10_all_checkpoint_restore" )
if (checkpoint == M10_checkpoints.start.name) then
-- Intro animations
-- Player(s) look cool GO!
local anim_name = "M10 Player Mission Start"
local morph_name = "M10 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
m10_setup_oleg()
m10_setup_viola()
m10_setup_club()
roadblocks_enable(false)
--teleport_coop(M10_checkpoints.start.player_starts[1], M10_checkpoints.start.player_starts[2], true)
teleport( M10_characters.oleg, M10_navpoints.oleg_start )
teleport( M10_characters.viola, M10_navpoints.viola_start )
end
if (checkpoint == M10_checkpoints.survive.name) then
m10_setup_oleg()
m10_setup_viola()
teleport_coop(M10_checkpoints.survive.player_starts[1], M10_checkpoints.survive.player_starts[2], true)
teleport( M10_characters.oleg, M10_navpoints.oleg_roof )
teleport( M10_characters.viola, M10_navpoints.viola_roof )
m10_setup_perimeter()
m10_setup_rooftop()
m10_setup_rooftop_intro()
roadblocks_enable(false)
end
if (checkpoint == M10_checkpoints.oleg_to_the_rescue.name) then
m10_setup_oleg()
m10_setup_viola()
-- Setup Oleg
follower_make_independent(M10_characters.oleg, true)
teleport(M10_characters.oleg, M10_navpoints.roof_oleg_dest)
npc_leash_to_nav(M10_characters.oleg, M10_navpoints.roof_oleg_dest, 1.0, false)
-- Setup Viola
follower_make_independent(M10_characters.viola, true)
teleport(M10_characters.viola, M10_navpoints.roof_viola_investigate)
npc_leash_to_nav(M10_characters.viola, M10_navpoints.roof_viola_investigate, 1.0, false)
turn_invulnerable(M10_characters.viola)
set_dont_attack_me_on_sight_flag(M10_characters.viola, true)
teleport_coop(M10_checkpoints.oleg_to_the_rescue.player_starts[1], M10_checkpoints.oleg_to_the_rescue.player_starts[2], true)
m10_setup_perimeter()
m10_setup_rooftop()
roadblocks_enable(false)
end
if (checkpoint == M10_checkpoints.escape_to_hq.name) then
m10_setup_viola()
m10_setup_perimeter()
m10_setup_club_aftermath() -- must happen after the perimeter has been created
set_dont_attack_me_on_sight_flag(M10_characters.viola, true)
turn_invulnerable(M10_characters.viola)
-- Turn police (STAG) notoriety on
hud_set_fake_notoriety("police", false)
notoriety_reset("police")
notoriety_set("police", M10_tweak_parameters.goto_hq_notoriety_level)
notoriety_set_can_decay(DISABLE)
-- Just hide the tanks at the front of the club that chased after the VTOL Oleg hijacked
for i, tank in pairs(M10_groups.stag_ground_troops.tanks) do
if (tank.chase_path ~= "") then
vehicle_hide(tank.tank)
end
end
teleport_coop(M10_checkpoints.escape_to_hq.player_starts[1], M10_checkpoints.escape_to_hq.player_starts[2], true)
end
end
-- ***************************************************
-- m10_run Helper Functions
-- ***************************************************
--[[
CHECKPOINT 01: Mission Start (Strip Club Inteior)
--]]
-- First checkpoint where the player(s) must battle through the STAG forces to get to the roof
function m10_run_get_to_the_front_door()
objective_text_clear(0)
objective_text( 0, "m10_obj_escape_stag", "", "", SYNC_ALL, OI_ASSET_LOCATION )
-- Setup the trigger for the first door
trigger_enable(M10_triggers.club_door, true)
on_trigger("m10_player_reached_objective_cb", M10_triggers.club_door)
marker_add_trigger(M10_triggers.club_door, MINIMAP_ICON_LOCATION, INGAME_EFFECT_LOCATION, OI_ASSET_LOCATION, SYNC_ALL)
-- Setup the trigger for the stag ambush
trigger_enable(M10_triggers.stag_ambush_01, true)
on_trigger("m10_trigger_stag_ambush_cb", M10_triggers.stag_ambush_01)
audio_play_persona_line(M10_characters.viola, M10_dialog_lines.mission_start)
-- Put the strippers into their animation states
for i, stripper in pairs(M10_groups.strippers.members) do
npc_use_closest_action_node_of_type(stripper, M10_groups.strippers.anims[i])
end
delay(3.0)
m10_helper_play_conversation(M10_convo.stag_entrance, false)
zscene_prep(M10_cutscenes.rooftop_intro)
-- Wait til the player gets to the club
while not M10_runtime.player_reached_objective do
thread_yield()
end
-- Setup the trigger for the front door
M10_runtime.player_reached_objective = false
trigger_enable(M10_triggers.front_door_exit, true)
on_trigger("m10_player_reached_objective_cb", M10_triggers.front_door_exit)
marker_add_trigger(M10_triggers.front_door_exit, MINIMAP_ICON_LOCATION, INGAME_EFFECT_LOCATION, OI_ASSET_LOCATION, SYNC_ALL)
while((not M10_runtime.player_reached_objective) and (M10_runtime.ambush_soldiers_alive > 0)) do
thread_yield()
end
-- Start the continuous spawn for the club
continuous_spawn_regions_enable(M10_spawn_regions.stag_club, true)
for i, spawn_group in pairs(M10_spawn_groups.stag_club) do
continuous_spawn_start(spawn_group, 0, 3)
end
if (M10_runtime.ambush_soldiers_alive == 0) then
audio_play_persona_line(LOCAL_PLAYER, M10_dialog_lines.get_to_roof)
end
-- Wait til the player gets to the stairs
while not M10_runtime.player_reached_objective do
thread_yield()
end
m10_cleanup_get_to_the_front_door()
end
-- Cleanup for getting to the front door
function m10_cleanup_get_to_the_front_door()
-- Remove the triggers
m10_clear_trigger(M10_triggers.front_door_exit)
m10_clear_trigger(M10_triggers.stag_ambush_01)
-- MLG 04/02/11 - Fix for Bug #12442: Releasing these guys to the world can cause an assert since they are still doing
-- their script action (which is bad)
-- Clean-up the stag ambush group
--[[
for i, squad in pairs(M10_groups.stag_ambush.squads) do
for j, char in pairs(squad.chars) do
release_to_world(char)
end
end
--]]
group_destroy(M10_groups.stag_ambush.name)
-- Stop the continuous spawn for the club
continuous_spawn_regions_enable(M10_spawn_regions.stag_club, false)
for i, spawn_group in pairs(M10_spawn_groups.stag_club) do
continuous_spawn_stop(spawn_group, true)
end
for i, squad in pairs(M10_groups.stag_ambush.squads) do
for j, char in pairs(squad.chars) do
on_death("", char)
end
end
-- Destroy the group for the strippers (we need those slots!!)
group_destroy(M10_groups.strippers.name)
-- End the STAG entrance conversation
audio_conversation_end(M10_convo.stag_entrance.handle)
audio_object_post_event( "m10_flashbang_stop" )
end
-- Trigger callback for when the play enters the area for the STAG ambush on the club
--
-- triggerer: Charcter that entered the trigger region
-- trigger_name: Name of the trigger that the character entered
function m10_trigger_stag_ambush_cb(triggerer, trigger_name)
-- Clear the trigger for the STAG ambush
m10_clear_trigger(M10_triggers.stag_ambush_01)
-- Throw the flashbangs
for i, char in pairs(M10_groups.stag_ambush.flashbang_throwers.chars) do
explosion_create("Flashbang", M10_groups.stag_ambush.flashbang_throwers.targets[i], char, false)
delay(0.3)
end
audio_object_post_event( "m10_flashbang" )
-- Show the stag ambush, and move all the characters to their destinations
group_show(M10_groups.stag_ambush.name)
for i, squad in pairs(M10_groups.stag_ambush.squads) do
for j, char in pairs(squad.chars) do
on_death("m10_stag_ambush_soldier_killed_cb", char)
ai_do_scripted_move(char, squad.destination, true, true)
end
end
delay(3.0)
audio_play_persona_line(LOCAL_PLAYER, M10_dialog_lines.laser_guns)
end
-- Callback for when an ambush soldier is killed
--
-- victim: Name of the soldier killed
function m10_stag_ambush_soldier_killed_cb(victim)
on_death("", victim)
on_attack_performed("", victim)
M10_runtime.ambush_soldiers_alive = M10_runtime.ambush_soldiers_alive - 1
end
-- Proccessing for the mid-mission cutscene in the lobby
function m10_run_lobby_cutscene()
-- Play the cinematic
--bink_play(M10_cutscenes.rooftop_intro)
cutscene_play(M10_cutscenes.rooftop_intro, nil, M10_checkpoints.survive.player_starts)
m10_cleanup_lobby_cutscene()
end
-- Cleanup for the mid-mission cutscene in the lobby
function m10_cleanup_lobby_cutscene()
--[[ NOTHING TO DO ]]--
end
-- Run the intro sequence on the rooftop
function m10_run_rooftop_intro()
objective_text_clear(0)
objective_text( 0, M10_strings.objective_survive, "", "", SYNC_ALL, OI_ASSET_DEFEND )
turn_invulnerable(M10_characters.viola)
set_dont_attack_me_on_sight_flag(M10_characters.viola, true)
character_make_priority_target(LOCAL_PLAYER, true)
if (coop_is_active()) then
character_make_priority_target(REMOTE_PLAYER, true)
end
-- Make the door open
door_open(M10_movers.club_doors.roof_entry.door_movers[1], false, false)
-- Add infinite respawning pistols to rooftop
group_create(M10_groups.weapons.name, true)
-- Setup the VTOLs that are flying-by as the cutscene ends
group_show(M10_groups.vtol_intro_flyby_01.name)
M10_threads.vtol_flyby = thread_new("m10_thread_process_flyby", M10_groups.vtol_intro_flyby_01)
delay(0.5)
audio_play_persona_line(LOCAL_PLAYER, M10_dialog_lines.rooftop_start)
audio_object_post_event( "m10_vtol_group_flyby" )
-- Close and lock the roof entry door
door_close(M10_movers.club_doors.roof_entry.door_movers[1], true)
door_lock(M10_movers.club_doors.roof_entry.door_movers[1], true)
M10_threads.viola_rooftop_intro = thread_new("m10_thread_process_viola_rooftop_intro")
M10_threads.oleg_rooftop_intro = thread_new("m10_thread_process_oleg_rooftop_intro")
-- Initialize our enemy counts
M10_runtime.transport_soldiers_alive = 0
M10_runtime.transport_snipers_alive = 0
--spawn an initial group of baddies towards the roof
delay(1.0)
group_create_hidden(M10_groups.stag_transport_01a.name, true)
group_create_hidden(M10_groups.stag_transport_01a_vtol.name, true)
m10_setup_stag_transport(M10_groups.stag_transport_01a, false) -- not snipers
--audio_play_persona_line(M10_characters.oleg, M10_dialog_lines.first_dropoff)
M10_groups.stag_transport_01a.thread_id = thread_new("m10_vtol_transport_drop_off_thread", M10_groups.stag_transport_01a, true) -- show markers
-- Wait for the two threads to finish
while(thread_check_done(M10_threads.viola_rooftop_intro) == false or thread_check_done(M10_threads.oleg_rooftop_intro) == false) do
thread_yield()
end
-- Move Viola to the elevator to start fixing it
npc_leash_remove(M10_characters.viola)
ai_do_scripted_move(M10_characters.viola, M10_navpoints.roof_viola_fix_elevator, true, false)
m10_helper_play_conversation(M10_convo.elevators, false)
-- Wait for Viola to stop moving
while(ai_scripted_action_is_complete(M10_characters.viola) == false) do
thread_yield()
end
-- audio_play_persona_line(M10_characters.viola, M10_dialog_lines.power_elevators_02)
--m10_helper_play_conversation(M10_convo.elevators, false)
-- Leash Viola near the elevator
npc_leash_to_nav(M10_characters.viola, M10_navpoints.roof_viola_fix_elevator, 0.0, false)
set_ignore_ai_flag(M10_characters.viola, true)
set_animation_state(M10_characters.viola, "m10_viola_elevator_fix", M10_navpoints.roof_viola_fix_elevator, true)
character_prevent_flinching(M10_characters.viola, true)
character_prevent_bumping(M10_characters.viola, true)
character_allow_ragdoll(M10_characters.viola, false)
character_set_immune_to_explosion_vomit(M10_characters.viola, true)
m10_cleanup_rooftop_intro()
end
-- Process Viola running over to the elevator
function m10_thread_process_viola_rooftop_intro()
-- Move Viola to check out the perimeter
follower_make_independent(M10_characters.viola, true)
ai_do_scripted_move(M10_characters.viola, M10_navpoints.roof_viola_investigate, true, false)
-- Wait for Viola to stop moving
while(ai_scripted_action_is_complete(M10_characters.viola) == false) do
thread_yield()
end
delay(0.3)
-- Play the "building surrounded" convo
m10_helper_play_conversation(M10_convo.building_surrounded, false)
-- Leash Viola near the elevator
npc_leash_to_nav(M10_characters.viola, M10_navpoints.roof_viola_investigate, 1.0, false)
end
-- Process Oleg checking out the perimeter
function m10_thread_process_oleg_rooftop_intro()
-- Move Oleg to check out the elevators
follower_make_independent(M10_characters.oleg, true)
ai_do_scripted_move(M10_characters.oleg, M10_navpoints.roof_oleg_investigate, true, false)
-- Wait for Oleg to stop moving, then have him return to the player
while(ai_scripted_action_is_complete(M10_characters.oleg) == false) do
thread_yield()
end
delay(0.3)
-- audio_play_persona_line(M10_characters.oleg, M10_dialog_lines.power_elevators)
-- follower_make_independent(M10_characters.oleg, false)
end
-- Handle any clean-up for the rooftop intro section
function m10_cleanup_rooftop_intro()
-- Kill the threads processing Viola and Oleg
if (thread_check_done(M10_threads.viola_rooftop_intro) == false) then
thread_kill(M10_threads.viola_rooftop_intro)
M10_threads.viola_rooftop_intro = INVALID_THREAD_HANDLE
end
if (thread_check_done(M10_threads.oleg_rooftop_intro) == false) then
thread_kill(M10_threads.oleg_rooftop_intro)
M10_threads.oleg_rooftop_intro = INVALID_THREAD_HANDLE
end
end
--[[
CHECKPOINT 02 - Survive the Rooftop Battle
--]]
function m10_run_vtol_transports_01()
-- Update the objective text
objective_text( 0, M10_strings.objective_kill_rooftop_enemies, "", "", SYNC_ALL, OI_ASSET_KILL )
-- Start the continuous spawn VTOL transport thread
-- M10_vtol_cont_spawn.thread_id = thread_new("m10_club_drop_off_cont_spawn_thread", M10_vtol_cont_spawn, 25)
trigger_enable(M10_triggers.vtol_oi_01, true)
on_trigger("m10_vtol_oi_tgr_cb", M10_triggers.vtol_oi_01)
-- Setup the first transport
group_create_hidden(M10_groups.stag_transport_01.name, true)
group_create_hidden(M10_groups.stag_transport_01_vtol.name, true)
m10_setup_stag_transport(M10_groups.stag_transport_01, false) -- not snipers
m10_vtol_transport_drop_off_thread(M10_groups.stag_transport_01, true) -- regular marker
-- Wait until there 5 seconds have passed, or all the enemies have been killeds
--local elapsed_time = 0.0
--while((elapsed_time < 5.0) and (M10_runtime.transport_soldiers_alive > 3)) do
-- elapsed_time = elapsed_time + get_frame_time()
-- thread_yield()
--end
-- Setup the second transport
group_create_hidden(M10_groups.stag_transport_02.name, true)
group_create_hidden(M10_groups.stag_transport_02_vtol.name, true)
m10_setup_stag_transport(M10_groups.stag_transport_02, false) -- not snipers
M10_groups.stag_transport_02.thread_id = thread_new("m10_vtol_transport_drop_off_thread", M10_groups.stag_transport_02, true) -- show markers
-- Wait until there are 0 guys remaining
while(M10_runtime.transport_soldiers_alive > 3) do
thread_yield()
end
-- Setup the 2B transport TEMP TESTING SCRIPT
group_create_hidden(M10_groups.stag_transport_02b.name, true)
group_create_hidden(M10_groups.stag_transport_02b_vtol.name, true)
m10_setup_stag_transport(M10_groups.stag_transport_02b, false) -- not snipers
--audio_play_persona_line(M10_characters.oleg, M10_dialog_lines.first_dropoff)
M10_groups.stag_transport_02b.thread_id = thread_new("m10_vtol_transport_drop_off_thread", M10_groups.stag_transport_02b, true) -- show markers
-- Wait until there are 3 guys remaining
while(M10_runtime.transport_soldiers_alive > 3) do
thread_yield()
end
m10_helper_play_conversation(M10_convo.viola_check_in, false)
-- Wait until there are 1 guy1 remaining
while(M10_runtime.transport_soldiers_alive > 1) do
thread_yield()
end
-- Enable the triggers to turn on the object indicators
trigger_enable(M10_triggers.vtol_oi_01, false)
on_trigger("", M10_triggers.vtol_oi_01)
trigger_enable(M10_triggers.vtol_oi_02, true)
on_trigger("m10_vtol_oi_tgr_cb", M10_triggers.vtol_oi_02)
-- Setup the third transport
group_create_hidden(M10_groups.stag_transport_03.name, true)
group_create_hidden(M10_groups.stag_transport_03_vtol.name, true)
m10_setup_stag_transport(M10_groups.stag_transport_03, false) -- not snipers
M10_groups.stag_transport_03.thread_id = thread_new("m10_vtol_transport_drop_off_thread", M10_groups.stag_transport_03, true) -- show markers
-- Setup the forth transport (with snipers)
-- Don't do this in a thread, we want to know when the transport has dropped off the snipers (or was destroyed)
group_create_hidden(M10_groups.stag_transport_04.name, true)
group_create_hidden(M10_groups.stag_transport_04_vtol.name, true)
group_create_hidden(M10_groups.vtol_transport_flyby_01.name, true)
m10_setup_stag_transport(M10_groups.stag_transport_04, true) -- SNIPERS!!
m10_vtol_transport_drop_off_thread(M10_groups.stag_transport_04, true) -- show markers
-- Time to spawn a wave of VTOL flying by the player
group_show(M10_groups.vtol_transport_flyby_01.name)
M10_threads.vtol_flyby = thread_new("m10_thread_process_flyby", M10_groups.vtol_transport_flyby_01)
delay(2)
audio_play_persona_line(M10_characters.viola, M10_dialog_lines.first_wave)
audio_object_post_event( "m10_vtol_group_flyby" )
-- delay(5)
-- If there are any snipers remaining (after being dropped off) then update the objective
-- if (M10_runtime.transport_snipers_alive > 0) then
-- Call out the snipers
-- audio_play_persona_line(M10_characters.viola, M10_dialog_lines.sniper_transport)
-- end
-- Wait until all the snipers have been killed
--while(M10_runtime.transport_snipers_alive > 0) do
-- thread_yield()
--end
--end
local total_soldiers = M10_runtime.transport_snipers_alive + M10_runtime.transport_soldiers_alive
-- Wait until all soldiers have been killed
while(total_soldiers > 4) do
thread_yield()
total_soldiers = M10_runtime.transport_snipers_alive + M10_runtime.transport_soldiers_alive
end
trigger_enable(M10_triggers.vtol_oi_02, false)
on_trigger("", M10_triggers.vtol_oi_02)
-- Setup the fifth transport
group_create_hidden(M10_groups.stag_transport_05.name, true)
group_create_hidden(M10_groups.stag_transport_05_vtol.name, true)
m10_setup_stag_transport(M10_groups.stag_transport_05, false) -- not snipers
M10_groups.stag_transport_05.thread_id = thread_new("m10_vtol_transport_drop_off_thread", M10_groups.stag_transport_05, true) -- show markers
--audio_play_persona_line(M10_characters.oleg, M10_dialog_lines.second_dropoff)
-- Wait until all soldiers have been killed
total_soldiers = M10_runtime.transport_snipers_alive + M10_runtime.transport_soldiers_alive
while(total_soldiers > 0) do
thread_yield()
total_soldiers = M10_runtime.transport_snipers_alive + M10_runtime.transport_soldiers_alive
end
m10_helper_play_conversation(M10_convo.oleg_check_in, false)
--don't clear out the soldiers the last 2 may be left
m10_cleanup_vtol_transports_01(false)
end
-- Callback for when a VTOL enters the OI trigger region
function m10_vtol_oi_tgr_cb(triggerer, trigger)
-- Search for the transport group containing this character
local transport_table = nil
for i, transport in pairs(M10_runtime.transport_vtols) do
for i, char in pairs(transport.pilots) do
if (char == triggerer) then
-- Fount it!
transport_table = transport
break
end
end
end
-- Maybe add a marker, if we haven't already
if (transport_table ~= nil and transport_table.marker_added == false and transport_table.marker_removed == false) then
marker_add(transport_table.vtol, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL)
transport_table.marker_added = true
end
end
-- Setup a STAG transport VTOL (assumes the group has already been created)
--
-- vtol_table: Lua table defining the STAG transport (as defined for M10_groups::stag_transport_01)
-- snipers: TRUE if the transport's soldiers should be tracked as snipers, FALSE otherwise
function m10_setup_stag_transport(vtol_table, snipers)
vehicle_show(vtol_table.vtol)
--set up on destroyed
on_vehicle_destroyed("m10_transport_vtol_destroyed_cb", vtol_table.vtol)
-- Keep track of which vehicle seats have been filled
local seat_idx = 0
-- Put the pilots into the VTOL
for i, char in pairs(vtol_table.pilots) do
character_show(char)
-- Put the pilots into the vehicle
vehicle_enter_teleport(char, vtol_table.vtol, seat_idx, true)
follower_remain_in_car(char, true)
-- Make 'em angry
ai_add_enemy_target(char, CLOSEST_PLAYER, ATTACK_ON_SIGHT, false)
seat_idx = seat_idx + 1
ai_set_action_delay(char, "throw grenade", 9999)
end
-- Move the seat index to the rear seats if all the pilot seats haven't been filled
if (seat_idx < 2) then
seat_idx = 2
end
-- Setup the soldiers
for i, drop_off in pairs(vtol_table.drop_offs) do
local even_soldier = false
for j, char in pairs(drop_off.soldiers) do
character_show(char)
on_attack_performed(M10_timed_lines.stag.callback, char)
-- Put the soldiers into the vehicle
vehicle_enter_teleport(char, vtol_table.vtol, seat_idx, true)
--follower_remain_in_car(char, true)
--give these dudes better aim than normal
npc_weapon_spread(char, M10_tweak_parameters.rooftop_soldier_spread_mult)
--give half of em perfect aim
if (even_soldier) then
set_perfect_aim(char)
even_soldier = false
else
even_soldier = true
end
--make them not attack while in the helicopter
npc_combat_enable(char, false)
-- Track the soldier/sniper
if (snipers == true) then
on_death("m10_stag_transport_sniper_killed_cb", char)
M10_runtime.transport_snipers_alive = M10_runtime.transport_snipers_alive + 1
else
on_death("m10_stag_transport_soldier_killed_cb", char)
M10_runtime.transport_soldiers_alive = M10_runtime.transport_soldiers_alive + 1
end
seat_idx = seat_idx + 1
end
end
-- Enable the trigger region on the rooftop (so we can kill enemeis that fall off the roof)
trigger_enable(vtol_table.rooftop_trigger, true)
on_trigger_exit("m10_rooftop_trigger_exit_cb", vtol_table.rooftop_trigger)
end
-- Cleanup a STAG transport VTOL
--
-- vtol_table: Lua table defining the STAG transport (as defined for M10_groups::stag_transport_01)
function m10_cleanup_stag_transport(vtol_table, clear_soldiers)
-- Release the group to the world
--release_to_world(vtol_table.name)
-- Remove the marker on the VTOL
marker_remove(vtol_table.vtol)
-- Remove the markers on the soldier, and clear their on_death callback
if (clear_soldiers) then
for i, drop_off in pairs(vtol_table.drop_offs) do
for j, char in pairs(drop_off.soldiers) do
marker_remove(char)
on_death("", char)
end
end
end
-- Kill any active threads
if (vtol_table.thread_id ~= nil and vtol_table.thread_id ~= -1) then
if (thread_check_done(vtol_table.thread_id) == false) then
thread_kill(vtol_table.thread_id)
end
end
--disable on destroyed cb
on_vehicle_destroyed("", vtol_table.vtol)
-- Disable the trigger region on the rooftop
trigger_enable(vtol_table.rooftop_trigger, false)
on_trigger_exit("", vtol_table.rooftop_trigger)
end
-- Callback for when a transport soldier is killed
--
-- victim: Name of the soldier killed
function m10_stag_transport_soldier_killed_cb(victim)
on_death("", victim)
marker_remove(victim)
on_attack_performed("", victim)
M10_runtime.transport_soldiers_alive = M10_runtime.transport_soldiers_alive - 1
end
-- Callback for when a transport sniper is killed
--
-- victim: Name of the soldier killed
function m10_stag_transport_sniper_killed_cb(victim)
on_death("", victim)
marker_remove(victim)
on_attack_performed("", victim)
M10_runtime.transport_snipers_alive = M10_runtime.transport_snipers_alive - 1
end
-- Callback for when an enemy dropped off by a STAG transport exits the trigger on the rooftop
--
-- triggerer: Name of the character that exited the rooftop area
-- trigger_name: Name of the trigger
function m10_rooftop_trigger_exit_cb(triggerer, trigger_name)
-- Check to see if the triggerer is in the lsit of rooftop trigger characters
for i, char in pairs(M10_runtime.rooftop_trigger_chars) do
if (char == triggerer) then
character_kill(triggerer)
break
end
end
end
-- Clean-up the stag transports
function m10_cleanup_vtol_transports_01(clear_soldiers)
m10_cleanup_stag_transport(M10_groups.stag_transport_01a, clear_soldiers)
m10_cleanup_stag_transport(M10_groups.stag_transport_01, clear_soldiers)
m10_cleanup_stag_transport(M10_groups.stag_transport_02, clear_soldiers)
m10_cleanup_stag_transport(M10_groups.stag_transport_02b, clear_soldiers)
m10_cleanup_stag_transport(M10_groups.stag_transport_03, clear_soldiers)
m10_cleanup_stag_transport(M10_groups.stag_transport_04, clear_soldiers)
m10_cleanup_stag_transport(M10_groups.stag_transport_05, clear_soldiers)
end
-- Process the second wave of attack VTOLs (plus some VTOL flybys)
function m10_run_rooftop_attack_vtols()
-- Create the script groups
group_create_hidden(M10_groups.attack_vtols_02.name, true)
group_create_hidden(M10_groups.vtol_flyby_01.name, true)
group_show(M10_groups.attack_vtols_02.name)
-- Enable the trigger region for when the VTOLs should open fire
trigger_enable(M10_triggers.vtol_flyby_fire_01, true)
on_trigger("m10_vtol_flyby_fire_cb", M10_triggers.vtol_flyby_fire_01)
-- Kick-off the attack VTOL group
for i, vtol in pairs(M10_groups.attack_vtols_02.vtols) do
m10_setup_stag_attack_vtol(vtol, true)
vtol.thread_id = thread_new("m10_vtol_attack_thread", vtol, true)
end
-- Setup the VTOL flybys
group_show(M10_groups.vtol_flyby_01.name)
M10_threads.vtol_flyby = thread_new("m10_thread_process_flyby", M10_groups.vtol_flyby_01)
M10_threads.solider_count = thread_new("m10_solider_count_thread")
delay(1)
audio_object_post_event( "m10_vtol_group_flyby" )
delay(7.0)
if (M10_threads.solider_count ~= INVALID_THREAD_HANDLE) then
thread_kill(M10_threads.solider_count)
M10_threads.solider_count = INVALID_THREAD_HANDLE
end
objective_text( 0, M10_strings.objective_kill_vtol, "", "", SYNC_ALL, OI_ASSET_KILL )
audio_play_persona_line(M10_characters.viola, M10_dialog_lines.second_wave)
-- Add a minimum delay, in case an attack VTOL gets killed before the flyby is finished
delay(5.0)
audio_play_persona_line_2d(M10_personas.interrogation.persona_id, M10_dialog_lines.stag_bullhorn_vtol_01)
-- Wait until all the active attack VTOLs have been killed
while((M10_runtime.roof_attack_vtols_active - M10_runtime.roof_attack_vtols_killed) > 0) do
thread_yield()
end
--make sure we've polished off the soldiers
local total_soldiers = M10_runtime.transport_snipers_alive + M10_runtime.transport_soldiers_alive
if (total_soldiers > 0) then
objective_text( 0, M10_strings.objective_kill_rooftop_enemies, "", "", SYNC_ALL, OI_ASSET_KILL )
while (total_soldiers > 0) do
thread_yield()
total_soldiers = M10_runtime.transport_snipers_alive + M10_runtime.transport_soldiers_alive
end
end
m10_cleanup_rooftop_attack_vtols()
end
-- Clean-up the second wave of attack VTOLs
function m10_cleanup_rooftop_attack_vtols()
-- Remove the fire region trigger for the VTOL flyby
m10_clear_trigger(M10_triggers.vtol_flyby_fire_01)
-- Clean-up the attack vtols, since we know they are all destroyed now
for i, vtol in pairs(M10_groups.attack_vtols_02.vtols) do
-- Kill any thread that's still running
if (thread_check_done(vtol.thread_id) == false) then
thread_kill(vtol.thread_id)
end
on_vehicle_destroyed("", vtol.vtol)
marker_remove(vtol.vtol)
end
end
function m10_solider_count_thread()
local total_soldiers = M10_runtime.transport_snipers_alive + M10_runtime.transport_soldiers_alive
while (total_soldiers > 0) do
thread_yield()
total_soldiers = M10_runtime.transport_snipers_alive + M10_runtime.transport_soldiers_alive
end
objective_text( 0, M10_strings.objective_survive, "", "", SYNC_ALL, OI_ASSET_DEFEND )
end
--[[
CHECKPOINT 03: Oleg to the Resuce (This is the sequence where Oleg jumps onto a VTOL)
--]]
-- VTOL flyby downs Oleg
function m10_run_oleg_gets_downed()
objective_text( 0, M10_strings.objective_survive, "", "", SYNC_ALL, OI_ASSET_DEFEND )
--
-- Leash Oleg again
npc_leash_to_nav(M10_characters.oleg, M10_navpoints.oleg_sequence_oleg, 0.5)
ai_do_scripted_move(M10_characters.oleg, M10_navpoints.oleg_sequence_oleg, true)
m10_helper_play_conversation(M10_convo.oleg_walking, false)
-- Enable the trigger region for when the VTOLs should open fire
trigger_enable(M10_triggers.vtol_flyby_fire_02, true)
on_trigger("m10_vtol_flyby_fire_cb", M10_triggers.vtol_flyby_fire_02)
-- Setup the VTOL flybys
group_create(M10_groups.vtol_flyby_02.name, true)
for i, vtol in pairs(M10_groups.vtol_flyby_02.vtols) do
vtol.thread_id = thread_new("m10_thread_run_stag_flyby_vtol", vtol)
end
--make sure Oleg is in his spot!
while(ai_scripted_action_is_processing(M10_characters.oleg) == true) do
thread_yield()
end
-- Setup the VTOL that Oleg is going to jump onto
group_create(M10_groups.oleg_vtol.name, true)
vehicle_enter_teleport(M10_groups.oleg_vtol.driver, M10_groups.oleg_vtol.vtol)
turn_invulnerable(M10_groups.oleg_vtol.vtol, false)
--delay(1.0)
-- Wait until the VTOL has fired at Oleg
local break_loop = false
while((M10_groups.vtol_flyby_02.vtols[2].fired == false) and (break_loop == false)) do
--someone destroyed our invulnearable vehicle? wtf
if (vehicle_is_destroyed(M10_groups.vtol_flyby_02.vtols[2].vehicle)) then
break_loop = true
end
-- thread ended, it hides the vehicles at the end, we won't be shooting at all
if (vehicle_hidden(M10_groups.vtol_flyby_02.vtols[2].vehicle)) then
break_loop = true
end
--someone killed our invulnerable pilot, wtf
for i, char in pairs(M10_groups.vtol_flyby_02.vtols[2].chars) do
if (character_is_dead(char)) then
break_loop = true
end
end
thread_yield()
end
-- Clear any corpses that might have landed on the rooftop (so it doesn't break Oleg's path)
m10_helper_clear_club_rooftop()
-- Down Oleg
turn_invulnerable(M10_characters.oleg)
delay(3.0)
human_enter_downed(M10_characters.oleg)
-- Register a callback for when a player revives Oleg
M10_runtime.oleg_revived = false
on_revived("m10_oleg_revived_cb", M10_characters.oleg)
-- Play some dialog
delay(0.4)
audio_play_persona_line(LOCAL_PLAYER, M10_dialog_lines.oleg_downed)
-- Move the VTOL that Oleg will jump on into position
helicopter_fly_to_direct(M10_vehicles.oleg_vtol, -1, M10_groups.oleg_vtol.path_approach)
-- Wait until Oleg is revived
while(M10_runtime.oleg_revived == false) do
thread_yield()
end
-- At this point, Oleg is invulnerable
turn_invulnerable(M10_characters.oleg, false)
m10_cleanup_oleg_gets_downed()
end
-- Cleanup Oleg getting downed by a VTOL flyby
function m10_cleanup_oleg_gets_downed()
-- Clear the trigger for the flyby fire region
m10_clear_trigger(M10_triggers.vtol_flyby_fire_02)
-- Clear the callbacks on Oleg
on_revived("", M10_characters.oleg)
end
-- Callback for when Oleg gets revived
--
-- character_name: Name of the character that was revived
function m10_oleg_revived_cb(character_name)
M10_runtime.oleg_revived = true
on_revived("", M10_characters.oleg)
audio_play_persona_line(LOCAL_PLAYER, M10_dialog_lines.oleg_help)
end
-- Oleg jumps onto the vtol and beats the crap out of it.
function m10_run_oleg_jump_on_vtol()
-- Create the guys in the elevator
-- group_create(M10_groups.stag_elevator_guys.name, true)
-- Remove Viola's leash, and make her follow the player again
set_ignore_ai_flag(M10_characters.viola, false)
npc_leash_remove(M10_characters.viola)
character_prevent_flinching(M10_characters.viola, false)
character_prevent_bumping(M10_characters.viola, false)
character_allow_ragdoll(M10_characters.viola, true)
character_set_immune_to_explosion_vomit(M10_characters.viola, false)
follower_make_independent(M10_characters.viola, false)
-- Move the helicopter into postion, and freeze it
turn_invulnerable(M10_groups.oleg_vtol.vtol, false)
helicopters_set_jitter_override(0.1, 0.1)
helicopter_fly_to_direct(M10_groups.oleg_vtol.vtol, -1, M10_groups.oleg_vtol.path_dest)
--removed, end of the direct path is close enough and there's correction built into the animation, should be ok, removes the snap
--teleport_vehicle(M10_groups.oleg_vtol.vtol, M10_groups.oleg_vtol.nav_dest)
vehicle_set_keyframed_physics(M10_groups.oleg_vtol.vtol, true)
audio_play_persona_line_2d(M10_personas.interrogation.persona_id, M10_dialog_lines.stag_bullhorn_vtol_02)
delay(2)
-- Add an object indicator on the VTOL
marker_add(M10_groups.oleg_vtol.vtol, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL)
audio_play_persona_line(M10_characters.oleg, M10_dialog_lines.oleg_revived)
-- Move Oleg into position
npc_leash_remove(M10_characters.oleg)
ai_clear_scripted_action(M10_characters.oleg)
local tries = 0
while (ai_scripted_action_is_complete(M10_characters.oleg) == false and tries < 3) do
ai_do_scripted_move(M10_characters.oleg, M10_navpoints.oleg_sequence_oleg, true)
while(ai_scripted_action_is_processing(M10_characters.oleg) == true) do
thread_yield()
end
tries = tries + 1
thread_yield()
end
audio_play_persona_line(M10_characters.oleg, M10_dialog_lines.oleg_roar)
delay(3.0)
audio_play_persona_line(LOCAL_PLAYER, M10_dialog_lines.oleg_jump_player)
-- Make the VTOL fire at Oleg
-- ai_set_action_delay(M10_groups.oleg_vtol.driver, "throw grenade", 9999)
-- helicopter_shoot_human(M10_groups.oleg_vtol.vtol, M10_characters.oleg, false)
-- Have Oleg jump onto the VTOL (Oleg is no longer a member of the player's party)
tries = 0
local success = false
while(success == false and tries < 5) do
success = vehicle_enter(M10_characters.oleg, M10_groups.oleg_vtol.vtol, 2, true, false, true, nil, true)
tries = tries + 1
thread_yield()
end
-- Vehicel enter failed, just do a teleport
if (success == false) then
vehicle_enter_teleport(M10_characters.oleg, M10_groups.oleg_vtol.vtol, 2, true, true, true)
end
vehicle_set_keyframed_physics(M10_groups.oleg_vtol.vtol, false)
--M10_threads.vtol_panic = thread_new("m10_vtol_panic_thread")
party_dismiss(M10_characters.oleg)
marker_remove(M10_groups.oleg_vtol.vtol)
audio_play_persona_line(M10_characters.oleg, M10_dialog_lines.oleg_vtol)
m10_cleanup_oleg_jump_on_vtol()
end
-- Cleanup the Oleg vs VTOL sequence
function m10_cleanup_oleg_jump_on_vtol()
-- Restor the normal helicopter jitter
helicopters_set_jitter_override(1.0, 1.0)
-- Make Viola follow the player again
ai_set_personality(M10_characters.viola, "gang defensive")
if (character_exists(M10_characters.oleg)) then
npc_suppress_persona(M10_characters.oleg, true)
end
character_prevent_explosion_fling(M10_characters.viola, false)
-- npc_suppress_persona(M10_characters.oleg, true)
-- Remove the marker on the VTOL Oleg jumps on
marker_remove(M10_groups.oleg_vtol.vtol)
end
function m10_vtol_panic_thread()
vehicle_anim_start(M10_groups.oleg_vtol.vtol, "", "plane stumble forward")
end
-- Handle the VTOL panicing with Oleg on it
function m10_run_oleg_vtol_panic()
-- Tell the helicopter to fly around trying to shake off Oleg
m10_process_oleg_vtol_panic_thread()
--audio_play_persona_line(LOCAL_PLAYER, M10_dialog_lines.oleg_riding_vtol)
helicopter_fly_to_do(M10_groups.oleg_vtol.vtol, -1, true, "", true, M10_groups.oleg_vtol.path_flee)
-- These tanks are now dead because the VTOL Oleg jumped on shot and destroyed them
--[[
-- The tanks at the front entrance should chase the VTOL now (to make a path for the player to escape)
for i, tank in pairs(M10_groups.stag_ground_troops.tanks) do
if (tank.chase_path ~= "") then
set_dont_attack_me_on_sight_flag(char, false) -- so homies can attack the tanks
tank.thread_id = thread_new("m10_process_tank_chase_thread", tank)
end
end
--]]
m10_cleanup_oleg_vtol_panic()
end
-- Process the VTOL with Oleg on it panicing and shooting wildly
function m10_process_oleg_vtol_panic_thread()
-- Start the pathfind
vehicle_anim_start(M10_groups.oleg_vtol.vtol, "Oleg vtol attack", "Oleg vtol jump")
helicopter_fly_to_do(M10_groups.oleg_vtol.vtol, 15, true, "", false, M10_groups.oleg_vtol.path)
-- We don't want AI firing on their own, 20 seconds should be enough time
-- (they should be allowed to shoot after that)
ai_set_action_delay(M10_groups.oleg_vtol.driver, "fire", 20000)
-- Start firing
for i, fire_nav in pairs(M10_groups.oleg_vtol.fire_navs) do
if (fire_nav.alt_fire == true) then
-- Fire the alt weapon (missles)
set_perfect_aim(M10_groups.oleg_vtol.driver, true) -- give AI perfect aim for this shot (missles are very inaccurate)
helicopter_shoot_navpoint(M10_groups.oleg_vtol.vtol, fire_nav.nav, true)
set_perfect_aim(M10_groups.oleg_vtol.driver, false) -- restore regular AI aim
-- Wait for the specified duration
delay(fire_nav.duration)
else
-- Fire the primary weapon (laser) - need to hold down the trigger for the duration (by shooting every frame)
local elapsed_time = 0
while(elapsed_time < fire_nav.duration) do
-- Shoot this frame
helicopter_shoot_navpoint(M10_groups.oleg_vtol.vtol, fire_nav.nav, false)
-- Increment the timer
elapsed_time = elapsed_time + get_frame_time()
thread_yield()
end
end
-- Destroy any vehicles that should go boom
if (fire_nav.destroy_vehicles ~= nil) then
for i, vehicle in pairs(fire_nav.destroy_vehicles) do
vehicle_detonate(vehicle)
end
end
end
while (vehicle_anim_finished(M10_groups.oleg_vtol.vtol) == false) do
thread_yield()
end
-- Now just wait for the pathfind to finish (if it hasn't already)
--while (vehicle_pathfind_check_done(M10_groups.oleg_vtol.vtol) == 0) do
-- thread_yield()
--end
end
-- Cleanup the Oleg VTOL panicing
function m10_cleanup_oleg_vtol_panic()
-- Nothing to do here
end
-- Process the rooftop escape
function m10_run_rooftop_escape()
objective_text_clear(0)
objective_text( 0, "m10_obj_escape_to_saints_hq", "", "", SYNC_ALL, OI_ASSET_LOCATION )
--turn_vulnerable(M10_characters.viola)
character_make_priority_target(LOCAL_PLAYER, false)
if (coop_is_active()) then
character_make_priority_target(REMOTE_PLAYER, false)
end
-- Setup the trigger for the elevator
M10_runtime.player_reached_objective = false
on_trigger("m10_player_reached_objective_cb", M10_triggers.rooftop_elevator)
trigger_enable(M10_triggers.rooftop_elevator, true)
marker_add_trigger(M10_triggers.rooftop_elevator, MINIMAP_ICON_LOCATION, INGAME_EFFECT_LOCATION, OI_ASSET_LOCATION, SYNC_ALL)
-- Turn police (STAG) notoriety on
hud_set_fake_notoriety("police", false)
notoriety_reset("police")
notoriety_set("police", M10_tweak_parameters.goto_hq_notoriety_level)
notoriety_spawn_only_air(true)
notoriety_set_can_decay(DISABLE)
-- Unlock the elevator
door_lock(M10_movers.club_doors.roof_exit.door_movers[1], false)
audio_play_persona_line(M10_characters.viola, M10_dialog_lines.elevator_fixed)
delay(4.0)
-- Play some dialog
audio_play_persona_line(LOCAL_PLAYER, M10_dialog_lines.off_the_roof)
delay(4.0)
-- audio_play_persona_line(LOCAL_PLAYER, M10_dialog_lines.back_to_hq)
-- Wait until the player gets into the elevator
while not M10_runtime.player_reached_objective do
thread_yield()
end
m10_cleanup_rooftop_escape()
end
-- Cleanup for the rooftop escape
function m10_cleanup_rooftop_escape()
-- Disable the kill region for the roof
m10_clear_trigger(M10_triggers.roof_kill_region)
-- Clean-up for any vehicles that were over the club's airspace, and disable the trigger
for i, vehicle in pairs(M10_runtime.vehicles_in_airspace) do
if (vehicle ~= "") then
on_damage("", vehicle, 0.0)
end
end
m10_clear_trigger(M10_triggers.roof_air_space)
-- Disable the trigger for the elevator
m10_clear_trigger(M10_triggers.rooftop_elevator)
-- Stop the continuous spawn for the rooftops
continuous_spawn_regions_enable(M10_spawn_regions.stag_roof, false)
for i, spawn_group in pairs(M10_spawn_groups.stag_roof) do
continuous_spawn_stop(spawn_group, true)
end
-- Stop the VTOL continuous spawn
if (thread_check_done(M10_vtol_cont_spawn.thread_id) == false) then
thread_kill(M10_vtol_cont_spawn.thread_id)
end
for i, group in pairs(M10_vtol_cont_spawn.groups) do
if (group_is_loaded(group.name) == true) then
group_destroy(group.name)
end
-- Make sure the markers got cleaned up
marker_remove(group.vtol)
end
-- Clean-up any threads still running for the tanks chasing Oleg on the VTOL
for i, tank in pairs(M10_groups.stag_ground_troops.tanks) do
if (thread_check_done(tank.thread_id) == false) then
thread_kill(tank.thread_id)
end
end
if (group_is_loaded(M10_groups.stag_ground_troops.name) == true) then
group_destroy(M10_groups.stag_ground_troops.name)
end
-- Clean-up Oleg and the VTOL
if (group_is_loaded(M10_groups.oleg_vtol.name)) then
group_destroy(M10_groups.oleg_vtol.name)
end
m10_cleanup_oleg()
-- Clean-up all of the STAG script groups used on the rooftop
--[[
if (group_is_loaded(M10_groups.attack_vtols_01.name) == true) then
group_destroy(M10_groups.attack_vtols_01.name)
end
--]]
if (group_is_loaded(M10_groups.attack_vtols_02.name) == true) then
group_destroy(M10_groups.attack_vtols_02.name)
end
if (group_is_loaded(M10_groups.stag_transport_01.name) == true) then
group_destroy(M10_groups.stag_transport_01.name)
end
if (group_is_loaded(M10_groups.vtol_flyby_01.name) == true) then
group_destroy(M10_groups.vtol_flyby_01.name)
end
if (group_is_loaded(M10_groups.vtol_flyby_02.name) == true) then
group_destroy(M10_groups.vtol_flyby_02.name)
end
if (group_is_loaded(M10_groups.stag_elevator_guys.name) == true) then
group_destroy(M10_groups.stag_elevator_guys.name)
end
if group_is_loaded(M10_groups.weapons.name) then
group_destroy(M10_groups.weapons.name)
end
-- Set the ambient ped/traffic density back to normal
set_ped_density(1.0)
end
--[[
CHECKPOINT 04: Escape to the Saints HQ
--]]
-- Process escaping through the club after the rooftop battle
function m10_run_escape_club_aftermath()
objective_text_clear(0)
objective_text( 0, "m10_obj_escape_to_saints_hq", "", "", SYNC_ALL, OI_ASSET_LOCATION )
roadblocks_enable(true)
--setup ground notoriety, no air spawns, but everyoen else is good to start
-- will enable air spawns later
notoriety_spawn_only_air(false)
notoriety_force_no_air_spawn(true)
set_ped_density(0.00001)
set_traffic_density(0.00001)
-- Enable the trigger at the strip club exit
M10_runtime.player_reached_objective = false
trigger_enable(M10_triggers.front_door_exit, true)
on_trigger("m10_player_reached_objective_cb", M10_triggers.front_door_exit)
marker_add_trigger(M10_triggers.front_door_exit, MINIMAP_ICON_LOCATION, INGAME_EFFECT_LOCATION, OI_ASSET_LOCATION, SYNC_ALL)
-- Unlock the front doors (and make sure they're closed)
for i, door in pairs(M10_movers.club_doors.front_door.door_movers) do
door_lock(door, false)
door_close(door)
-- Register a callback for when the front door is opened by the player
on_door_opened("m10_front_door_opened_cb", door)
end
door_open(M10_movers.club_doors.lobby_door.door_movers[1], false, false)
-- Interior troops rush and set up at the door
for i, npc in pairs(M10_groups.stag_club_aftermath.members) do
ai_add_enemy_target(npc, CLOSEST_PLAYER, ATTACK_ON_SIGHT, false)
-- ai_attack_region(npc, M10_navpoints.stag_aftermath_rush, 8)
end
-- Disable the driver in the tank at the front of the club, from firing the main tank cannon
-- npc_combat_enable(M10_groups.stag_ground_troops.tanks[5].chars[1], false)
delay(1.5)
m10_helper_play_conversation(M10_convo.to_hq, false)
while (M10_runtime.player_reached_objective == false) do
thread_yield()
end
M10_runtime.player_reached_objective = false
trigger_enable(M10_triggers.club_exit, true)
on_trigger("m10_player_reached_objective_cb", M10_triggers.club_exit)
marker_add_trigger(M10_triggers.club_exit, MINIMAP_ICON_LOCATION, INGAME_EFFECT_LOCATION, OI_ASSET_LOCATION, SYNC_ALL)
-- Wait until the player reaches the trigger for the strip club exit
M10_runtime.player_reached_objective = false
while (M10_runtime.player_reached_objective == false) do
thread_yield()
end
audio_play_persona_line(LOCAL_PLAYER, M10_dialog_lines.exit_building)
m10_cleanup_escape_club_aftermath()
end
-- Handle any cleanup for the sequence escaping the strip club interior
function m10_cleanup_escape_club_aftermath()
m10_clear_trigger(M10_triggers.club_exit)
end
-- Processing for the excape to Saint's HQ sequence
function m10_run_escape_to_saints_hq()
-- Setup the trigger at the Saint's HQ
M10_runtime.player_reached_objective = false
on_trigger("m10_player_reached_objective_cb", M10_triggers.saints_hq)
trigger_enable(M10_triggers.saints_hq, true)
marker_add_trigger(M10_triggers.saints_hq, MINIMAP_ICON_LOCATION, INGAME_EFFECT_LOCATION, OI_ASSET_LOCATION, SYNC_ALL)
waypoint_add(M10_triggers.saints_hq)
--traffic_disable_lanes(M10_trigger.saints_hq_traffic, true)
trigger_enable(M10_triggers.start_notoriety, true)
on_trigger_exit("m10_start_notoriety_cb", M10_triggers.start_notoriety)
M10_threads.escape_convo = thread_new("m10_thread_process_escape_to_hq_conversations")
zscene_prep(M10_cutscenes.mission_outro)
-- Wait until the player reaches the Saint's HQ
while not M10_runtime.player_reached_objective do
thread_yield()
end
audio_object_post_event( "m10_chase_music_stop" )
-- MLG (04/16/11): Don't clean up this checkpoint immediatly
--m10_cleanup_escape_to_saints_hq()
end
-- Thread to process the conversations on the way back to the Saints' HQ
function m10_thread_process_escape_to_hq_conversations()
while(get_dist(LOCAL_PLAYER, M10_triggers.saints_hq) > M10_tweak_parameters.drive_01_dist_from_hq) do
thread_yield()
end
m10_helper_play_conversation(M10_convo.drive_01, true)
audio_conversation_end(M10_convo.drive_01.handle)
delay(3.0)
while(get_dist(LOCAL_PLAYER, M10_triggers.saints_hq) > M10_tweak_parameters.shaundi_update_dist_from_hq) do
thread_yield()
end
M10_runtime.phonecall_complete = false
audio_play_for_mission_cellphone(M10_convo.city_update.name , true, true, "", "m10_finish_phonecall_cb")
while (M10_runtime.phonecall_complete == false) do
thread_yield()
end
delay(3.0)
-- while(get_dist(LOCAL_PLAYER, M10_triggers.saints_hq) > M10_tweak_parameters.drive_02_dist_from_hq) do
-- thread_yield()
-- end
-- m10_helper_play_conversation(M10_convo.drive_02, true)
-- audio_conversation_end(M10_convo.drive_02.handle)
end
-- Cleanup for the escape to Saints HQ sequence
function m10_cleanup_escape_to_saints_hq()
m10_clear_trigger(M10_triggers.saints_hq)
--traffic_disable_lanes(M10_trigger.saints_hq_traffic, false)
waypoint_remove()
-- Clear the callbacks on the front doors
for i, door in pairs(M10_movers.club_doors.front_door.door_movers) do
on_door_opened("", door)
end
group_destroy(M10_groups.stag_club_aftermath.name)
group_destroy(M10_groups.stag_ext_aftermath.name)
group_destroy(M10_groups.saints_hq.name)
-- Disable the STAG encounters
m10_helper_cleanup_stag_encounter(M10_groups.stag_encounter_bridge_01)
m10_helper_cleanup_stag_encounter(M10_groups.stag_encounter_bridge_02)
m10_helper_cleanup_stag_encounter(M10_groups.stag_encounter_chem_01)
m10_helper_cleanup_stag_encounter(M10_groups.stag_encounter_bridge_03)
m10_helper_cleanup_stag_encounter(M10_groups.stag_encounter_bridge_04)
m10_helper_cleanup_stag_encounter(M10_groups.stag_encounter_bridge_05)
-- Clean-up the conversation thread
if (thread_check_done(M10_threads.escape_convo) == false) then
thread_kill(M10_threads.escape_convo)
M10_threads.escape_convo = INVALID_THREAD_HANDLE
end
end
-- Callback for when the front door is opened by the player
--
-- door_name: Name of the door that was opened
function m10_front_door_opened_cb(door_name)
-- Clear the mission cancel warp location
mission_set_cancel_warp_location()
-- Clear the callbacks on the front doors
for i, door in pairs(M10_movers.club_doors.front_door.door_movers) do
on_door_opened("", door)
end
-- Remove the leash on the STAG in the streets, and allow notoriety to spawn ground troops
-- delay(1.5)
-- for i, char in pairs(M10_groups.stag_ground_troops.troops) do
-- npc_leash_remove(char)
-- end
-- Wait 20 seconds before allowing ground notoriety troops to be spawned
-- delay(20.0)
-- notoriety_spawn_only_air(false)
end
-- Start normal notoriety spawns when leaving the club
function m10_start_notoriety_cb()
notoriety_reset("police")
notoriety_set("police", M10_tweak_parameters.goto_hq_notoriety_level)
notoriety_set_can_decay(DISABLE)
notoriety_force_no_air_spawn(false)
-- Set the ambient ped/traffic density
set_ped_density(0.7)
set_traffic_density(0.3)
end
-- ***************************************************
-- Miscellaneous m10 Helper Funcrtions
-- ***************************************************
-- Simple function that spawns Oleg, adds him to the player's party, and sets his callbacks
function m10_setup_oleg()
group_create(M10_groups.oleg.name, true)
party_add(M10_characters.oleg)
follower_set_can_abandon(M10_characters.oleg, true)
on_death("m10_oleg_died_cb", M10_characters.oleg)
on_dismiss("m10_oleg_dismissed_cb", M10_characters.oleg)
end
-- Clean-up Oleg
function m10_cleanup_oleg()
if (group_is_loaded(M10_groups.oleg.name) == true) then
party_dismiss(M10_characters.oleg)
on_death("", M10_characters.oleg)
on_dismiss("", M10_characters.oleg)
group_destroy(M10_groups.oleg.name)
end
end
-- Simple function that spawns Viola, adds her to the player's party, and sets her callbacks
function m10_setup_viola()
group_create(M10_groups.viola.name, true)
party_add(M10_characters.viola)
follower_set_can_abandon(M10_characters.viola, true)
on_death("m10_viola_died_cb", M10_characters.viola)
on_dismiss("m10_viola_dismissed_cb", M10_characters.viola)
end
-- Clean-up Viola
function m10_cleanup_viola()
if (group_is_loaded(M10_groups.viola.name) == true) then
party_dismiss(M10_characters.viola)
on_death("", M10_characters.viola)
on_dismiss("", M10_characters.viola)
group_destroy(M10_groups.viola.name)
end
end
-- Setup the string club interior
function m10_setup_club()
-- Initialize our enemy counts
M10_runtime.ambush_soldiers_alive = 0
audio_ambient_emitter_start( "m10_stripclub_music" )
-- Create the strippers and the stag ambush groups
group_create(M10_groups.strippers.name, true)
group_create_hidden(M10_groups.stag_ambush.name, true)
for i, squad in pairs(M10_groups.stag_ambush.squads) do
for j, char in pairs(squad.chars) do
M10_runtime.ambush_soldiers_alive = M10_runtime.ambush_soldiers_alive + 1
on_death("m10_stag_ambush_soldier_killed_cb", char)
on_attack_performed(M10_timed_lines.stag.callback, char)
end
end
end
-- Setup the perimeter around the strip club
function m10_setup_perimeter()
-- Create all the perimeter groups
group_create(M10_groups.police_containment.name, true)
group_create(M10_groups.emergency_responders.name, true)
group_create(M10_groups.stag_ground_troops.name, true)
-- All the police vehicles should have flashers going
for i, vehicle in pairs(M10_groups.police_containment.vehicles) do
vehicle_set_sirenlights(vehicle, true)
end
-- Turn on the flashing lights for the emergency response vehicles, and put characters in their vehicles
for i, vehicle in pairs(M10_groups.emergency_responders.vehicles) do
-- Put all of the characters into the vehicle
for j, char in pairs(vehicle.chars) do
vehicle_enter_teleport(char, vehicle.vehicle, (j - 1), false) -- don't block
end
-- This vehicle should not move
vehicle_disable_chase(vehicle.vehicle, true)
vehicle_disable_flee(vehicle.vehicle, true)
-- Turn the lights on
vehicle_set_sirenlights(vehicle.vehicle, true)
end
-- Setup the STAG tanks
for i, tank in pairs(M10_groups.stag_ground_troops.tanks) do
-- Put all the characters into the tank
for j, char in pairs(tank.chars) do
vehicle_enter_teleport(char, tank.tank, (j - 1), false) -- don't block
set_dont_attack_me_on_sight_flag(char, true) -- so homies don't attack the tanks
end
-- Make the tank stationary
vehicle_disable_chase(tank.tank, true)
vehicle_disable_flee(tank.tank, true)
end
-- Setup the ground troops
for i, char in pairs(M10_groups.stag_ground_troops.troops) do
ai_do_scripted_take_cover(char)
end
-- STAG should all be combat ready
set_force_combat_ready_team("stag")
end
-- Setup for the rooftop
function m10_setup_rooftop()
audio_ambient_emitter_stop( "m10_stripclub_music" )
audio_object_post_event( "m10_amb_rooftop" )
-- Setup the kill region trigger (if the player get's flung off the roof)
trigger_enable(M10_triggers.roof_kill_region, true)
on_trigger("m10_roof_kill_region_cb", M10_triggers.roof_kill_region)
-- Setup the trigger region for the roof airspace (so we can make sure helicopters don't crash on the roof)
trigger_enable(M10_triggers.roof_air_space, true)
on_trigger("m10_roof_air_space_entered", M10_triggers.roof_air_space)
on_trigger_exit("m10_roof_air_space_exited", M10_triggers.roof_air_space)
-- Adjust the player's homies to react to the VTOL threat
ai_set_personality(M10_characters.oleg, "gang offensive")
ai_set_personality(M10_characters.viola, "gang defensive")
character_prevent_explosion_fling(M10_characters.oleg, true)
character_prevent_explosion_fling(M10_characters.viola, true)
follower_set_can_abandon(M10_characters.oleg, false)
follower_set_can_abandon(M10_characters.viola, false)
-- npc_suppress_persona(M10_characters.oleg, true)
-- npc_suppress_persona(M10_characters.viola, true)
set_ped_density(0.00001)
set_traffic_density(0.00001)
end
-- Setup the rooftop intro
function m10_setup_rooftop_intro()
-- Create the initial group of VTOL flying by the player
group_create_hidden(M10_groups.vtol_intro_flyby_01.name, true)
end
-- Setup the aftermath when the player escapes through the strip club
function m10_setup_club_aftermath()
-- Setup some stag remaining in the club
group_create(M10_groups.stag_club_aftermath.name, true)
group_create(M10_groups.stag_ext_aftermath.name, true)
group_create(M10_groups.saints_hq.name, true)
for i, npc in pairs(M10_groups.stag_ext_aftermath.gunners) do
vehicle_enter_teleport(npc, M10_groups.stag_ext_aftermath.vehicle[i], 4, true)
end
-- Enable the STAG encounters
m10_helper_setup_stag_encounter(M10_groups.stag_encounter_bridge_01)
m10_helper_setup_stag_encounter(M10_groups.stag_encounter_bridge_02)
m10_helper_setup_stag_encounter(M10_groups.stag_encounter_chem_01)
m10_helper_setup_stag_encounter(M10_groups.stag_encounter_bridge_03)
m10_helper_setup_stag_encounter(M10_groups.stag_encounter_bridge_04)
m10_helper_setup_stag_encounter(M10_groups.stag_encounter_bridge_05)
-- Load the persona for Shaundi
M10_personas.shaundi.persona_id = audio_persona_load_2d(M10_personas.shaundi.name)
-- Turn notoriety off
notoriety_reset("police")
notoriety_force_no_spawn("police", true)
-- Viola can be abandoned again
follower_set_can_abandon(M10_characters.viola, false)
audio_object_post_event( "m10_amb_rooftop_stop" )
audio_object_post_event( "m10_chase_music" )
-- npc_suppress_persona(M10_characters.viola, true)
end
-- Disable trigger, clear callback, and remove marker
--
-- trigger: (string) Name of the trigger
function m10_clear_trigger(trigger)
on_trigger("", trigger)
on_trigger_exit("", trigger)
trigger_enable(trigger, DISABLE)
marker_remove_trigger(trigger, SYNC_ALL)
end
-- Setup a door into it's initial state
--
-- door: (lua table) for the door, as defined under M10_movers::club_doors
function m10_setup_door(door)
for i, mover in pairs(door.door_movers) do
-- Open/close the door
if (door.open == true) then
door_open(mover)
else
door_close(mover)
end
-- Lock/unlock the door
door_lock(mover, door.locked)
end
end
-- Setup helper for STAG attack VTOLs (assumes the group has already been created)
--
-- vtol_table: (lua table) for the VTOL, as defined under M10_groups::attack_vtol
function m10_setup_stag_attack_vtol(vtol_table)
on_vehicle_destroyed("m10_vtol_destroyed_cb", vtol_table.vtol)
-- Add the VTOL to the list of spawned VTOLs
M10_runtime.spawned_vtols[#M10_runtime.spawned_vtols + 1] = vtol_table.vtol
vehicle_enter_group_teleport(vtol_table.chars, vtol_table.vtol)
vehicle_disable_flee(vtol_table.vtol, true)
-- Add the VTOL to our active count
M10_runtime.roof_attack_vtols_active = M10_runtime.roof_attack_vtols_active + 1
end
-- Helper function to play a mission conversation
--
-- convo_table: Lua table defining the conversation to play (see M10_convo)
-- block: TRUE if the function should block until the conversation is finished, FALSE otherwise
function m10_helper_play_conversation(convo_table, block)
-- Load the conversation data
if (convo_table.load_direct == false) then
convo_table.handle = audio_conversation_load(convo_table.name)
else
convo_table.handle = audio_conversation_load_direct(convo_table.name)
end
-- Play the conversation
audio_conversation_play(convo_table.handle)
-- Should we wait for the conversation to end?
if (block == true) then
audio_conversation_wait_for_end(convo_table.handle)
audio_conversation_end(convo_table.handle)
convo_table.handle = INVALID_CONVERSATION_HANDLE
end
end
-- Thread to process moving a vechile to a destination, and forcing all the occupants to exit the vehicle
--
-- vehicle_table: Lua table defining the vehicle info, path, etc. (see M10_groups.stag_encounter_bridge.vehicles)
function m10_do_vehicle_exit_at_dest_thread(vehicle_table)
-- Teleport the characters into the group, setup the vehicle
vehicle_enter_group_teleport(vehicle_table.chars, vehicle_table.vehicle)
vehicle_ignore_repulsors(vehicle_table.vehicle, true)
-- vehicle_infinite_mass(vehicle_table.vehicle, true)
-- Do the pathfind
vehicle_pathfind_to(vehicle_table.vehicle, vehicle_table.path, vehicle_table.use_navmesh, true)
-- Turn off infinite mass
vehicle_ignore_repulsors(vehicle_table.vehicle, false)
-- vehicle_infinite_mass(vehicle_table.vehicle, false)
-- Wait a second and then force the enemies to exit the vehicle
delay(1.0)
vehicle_exit_group(vehicle_table.chars)
end
-- Thread to process moving a vehicle to a destination and stopping (and staying put with occupants inside)
--
-- vehicle_table: Lua table defining the vehicle info, path, etc. (see M10_groups.stag_encounter_bridge.vehicles)
function m10_do_vehicle_stop_at_dest_thread(vehicle_table)
-- Teleport the characters into the group, setup the vehicle
vehicle_enter_group_teleport(vehicle_table.chars, vehicle_table.vehicle)
vehicle_suppress_npc_exit(vehicle_table.vehicle, true)
vehicle_ignore_repulsors(vehicle_table.vehicle, true)
-- vehicle_infinite_mass(vehicle_table.vehicle, true)
-- Do the pathfind
if (vehicle_table.path ~= nil and vehicle_table.path ~= "") then
vehicle_pathfind_to(vehicle_table.vehicle, vehicle_table.path, vehicle_table.use_navmesh, true)
end
-- Turn off infinite mass
vehicle_ignore_repulsors(vehicle_table.vehicle, false)
-- vehicle_infinite_mass(vehicle_table.vehicle, false)
-- Disable fleeing and chasing
vehicle_disable_flee(vehicle_table.vehicle, true)
vehicle_disable_chase(vehicle_table.vehicle, true)
end
-- Create the script group for a STAG encounter
--
-- encounter_table: Lua table defining the STAG encounter info (see M10_groups.stag_encounter_bridge)
function m10_create_stag_encounter_thread(encounter_table)
-- Create the script group
if (group_is_loaded(encounter_table.name) == false) then
group_create_hidden(encounter_table.name, true)
end
end
-- Destroy a STAG encounter
--
-- encounter_table: Lua table defining the STAG encounter info (see M10_groups.stag_encounter_bridge)
function m10_destroy_stag_encounter_thread(encounter_table)
-- Stop any running vehicel threads
for i, vehicle in pairs(encounter_table.vehicles) do
if (thread_check_done(vehicle.thread_id) == false) then
thread_kill(vehicle.thread_id)
vehicle.thread_id = INVALID_THREAD_HANDLE
end
-- Remvoe any vehicle trigger
if (vehicle.trigger ~= nil) then
trigger_enable(vehicle.trigger, false)
on_trigger("", vehicle.trigger)
end
end
-- Destroy the script group
if (group_is_loaded(encounter_table.name) == true) then
group_destroy(encounter_table.name)
end
encounter_table.active = false
end
-- Callback when the player enters the creation trigger region for a STAG encounter
--
-- triggerer: Name of the player that triggered the callback
-- trigger_name: Name of the trigger that was entered
function m10_stag_encounter_entered_cb(triggerer, trigger_name)
-- Search through all the encounters that have been setup
for i, encounter in pairs(M10_runtime.stag_encounters) do
if (encounter.creation_trigger == trigger_name) then
-- If the player count was at 0, then start the encounter
if (encounter.player_count == 0) then
-- Kill any existing threads for the encounter, and start a new thread to start-up the encounter
if (thread_check_done(encounter.thread_id) == false) then
thread_kill(encounter.thread_id)
end
encounter.thread_id = thread_new("m10_create_stag_encounter_thread", encounter)
end
-- Increment the player counter
encounter.player_count = encounter.player_count + 1
break
end
end
end
-- Callback when the players exits the creation trigger region for a STAG encounter
--
-- triggerer: Name of the player that triggered the callback
-- trigger_name: Name of the trigger that was entered
function m10_stag_encounter_exited_cb(triggerer, trigger_name)
-- Search through all the encounters that have been setup
for i, encounter in pairs(M10_runtime.stag_encounters) do
if (encounter.creation_trigger == trigger_name) then
-- Decrement the player count
encounter.player_count = encounter.player_count - 1
-- If the player count is at zero, stop the encounter
if (encounter.player_count <= 0) then
-- Kill any existing threads for the encounter, and start a new thread to stop the encounter
if (thread_check_done(encounter.thread_id) == false) then
thread_kill(encounter.thread_id)
end
encounter.thread_id = thread_new("m10_destroy_stag_encounter_thread", encounter)
end
break
end
end
end
-- Callback when a player enter the trigger region that activates the "action" on a STAG encounter (show enemies and do individual behaviors)
--
-- triggerer: Name of the player that triggered the callback
-- trigger_name: Name of the trigger that was entered
function m10_stag_encounter_do_action_cb(triggerer, trigger_name)
-- Search through all the encounters that have been setup
for i, encounter in pairs(M10_runtime.stag_encounters) do
if (encounter.action_trigger == trigger_name) then
if (encounter.active == false and group_is_loaded(encounter.name) == true) then
if (encounter.max_activations == -1 or encounter.num_activations < encounter.max_activations) then
-- Show the group
group_show(encounter.name)
-- Setup all the vehicles
for i, vehicle in pairs(encounter.vehicles) do
-- This is the tank Oleg targets during his encounter
if (vehicle.vehicle == "veh_tank_bridge_03_ 001") then
on_vehicle_destroyed("m13_oleg_tank_cb", vehicle.vehicle)
end
-- This is Oleg's VTOL on his bridge encounter
if (vehicle.vehicle == "veh_vtol_bridge_03_ 001") then
vehicle_anim_start(vehicle.vehicle, "Oleg vtol attack", "Oleg vtol jump")
end
if (vehicle.behavior == "exit_at_dest") then
vehicle.thread_id = thread_new("m10_do_vehicle_exit_at_dest_thread", vehicle)
elseif (vehicle.behavior == "stop_at_dest") then
vehicle.thread_id = thread_new("m10_do_vehicle_stop_at_dest_thread", vehicle)
elseif (vehicle.behavior == "fly_by") then
vehicle.thread_id = thread_new("m10_thread_run_stag_flyby_vtol", vehicle)
elseif (vehicle.behavior == "fly_by_and_shoot") then
-- Setup the shoot trigger
trigger_enable(vehicle.trigger, true)
on_trigger("m10_vtol_flyby_fire_cb", vehicle.trigger)
vehicle.thread_id = thread_new("m10_thread_run_stag_flyby_vtol", vehicle)
end
end
-- Flag the encounter as active
encounter.active = true
encounter.num_activations = encounter.num_activations + 1
end
end
break
end
end
end
function m13_oleg_tank_cb(vehicle)
on_vehicle_destroyed("", vehicle)
audio_play_persona_line(LOCAL_PLAYER, M10_dialog_lines.oleg_riding_vtol)
end
-- Setup a STAG encounter
--
-- encounter_table: Lua table defining the STAG encounter info (see M10_groups.stag_encounter_bridge)
function m10_helper_setup_stag_encounter(encounter_table)
-- Enable the creation and action triggers
trigger_enable(encounter_table.creation_trigger, true)
on_trigger("m10_stag_encounter_entered_cb", encounter_table.creation_trigger)
on_trigger_exit("m10_stag_encounter_exited_cb", encounter_table.creation_trigger)
trigger_enable(encounter_table.action_trigger, true)
on_trigger("m10_stag_encounter_do_action_cb", encounter_table.action_trigger)
-- Initialize the player count and add this encounter table to the array
encounter_table.player_count = 0
encounter_table.num_activations = 0
encounter_table.active = false
M10_runtime.stag_encounters[#M10_runtime.stag_encounters + 1] = encounter_table
end
-- Clean-up a STAG encounter
--
-- encounter_table: Lua table defining the STAG encounter info (see M10_groups.stag_encounter_bridge)
function m10_helper_cleanup_stag_encounter(encounter_table)
-- Clean-up the creation and action triggers
trigger_enable(encounter_table.creation_trigger, false)
on_trigger("", encounter_table.creation_trigger)
on_trigger_exit("", encounter_table.creation_trigger)
trigger_enable(encounter_table.action_trigger, false)
on_trigger("", encounter_table.action_trigger)
-- Stop any running threads
if (thread_check_done(encounter_table.thread_id) == false) then
thread_kill(encounter_table.thread_id)
encounter_table.thread_id = INVALID_THREAD_HANDLE
end
-- Stop the encoutner (in case it was still running)
m10_destroy_stag_encounter_thread(encounter_table)
-- Remove the encounter from the list of encounters
for i, encounter in pairs(M10_runtime.stag_encounters) do
if (encounter_table == encounter) then
M10_runtime.stag_encounters[i] = M10_runtime.stag_encounters[#M10_runtime.stag_encounters]
end
end
end
-- Helper function to clear any vehicle corpses from the club's rooftop
function m10_helper_clear_club_rooftop()
for i, vtol in pairs(M10_runtime.spawned_vtols) do
if (object_is_in_trigger(M10_triggers.club_roof_area, vtol) == true) then
vehicle_hide(vtol, true)
end
end
end
-- *************************
--
-- Callback functions
--
-- *************************
--finished a phonecall
function m10_finish_phonecall_cb()
M10_runtime.phonecall_complete = true
end
--attack callback
function m10_stag_attack_cb(name)
-- don't play this if we have done this recently
if (not thread_check_done(M10_timed_lines.stag.timer)) then
return
end
-- start timer
M10_timed_lines.stag.timer = thread_new("delay", M10_timed_lines.stag.delay)
-- play situation
audio_play_persona_line(name, M10_timed_lines.stag.situation)
end
-- Oleg died, fail the mission
function m10_oleg_died_cb()
mission_end_failure("m10", M10_strings.failure_oleg_died)
end
-- Viola died, fail the mission
function m10_viola_died_cb()
mission_end_failure("m10", M10_strings.failure_viola_died)
end
-- Oleg dismissed, fail the mission
function m10_oleg_dismissed_cb()
mission_end_failure("m10", M10_strings.failure_oleg_dismissed)
end
-- Viola dismissed, fail the mission
function m10_viola_dismissed_cb()
mission_end_failure("m10", M10_strings.failure_viola_dismissed)
end
-- Callback triggered when a player enters a destination trigger region
--
-- triggerer: Name of the character that entered the trigger region
-- trigger_name: Name of the trigger region that the character entered
function m10_player_reached_objective_cb(triggerer, trigger_name)
M10_runtime.player_reached_objective = true
m10_clear_trigger(trigger_name)
end
-- Callback when a player enters the kill region for falling off the roof
--
-- triggerer: Name of the character that entered the trigger region
-- trigger_name: Name of the trigger region that the character entered
function m10_roof_kill_region_cb(triggerer, trigger_name)
if ((triggerer == LOCAL_PLAYER) or (triggerer == REMOTE_PLAYER) or (triggerer == M10_characters.oleg) or (triggerer == M10_characters.viola)) then
character_kill(triggerer, true)
end
end
-- Callback when a character enters the airspace above the strip club roof
--
-- triggerer: Name of the character that entered the trigger region
-- trigger_name: Name of the trigger region that the character entered
function m10_roof_air_space_entered(triggerer, trigger_name)
if (triggerer == nil or triggerer == "") then
return
end
local vehicle_name = get_char_vehicle_name(triggerer)
if (vehicle_name == nil or vehicle_name == "") then
return
end
for i, vehicle in pairs(M10_runtime.vehicles_in_airspace) do
if (vehicle == vehicle_name) then
return
end
end
-- If the character is in a valid vehicle, then see if we need to do any setup on it
if ((vehicle_is_helicopter(vehicle_name) == true or vehicle_is_vtol(vehicle_name) == true)) then
local free_idx = -1
-- Check if the vehicle is already in the list
for i, vehicle in pairs(M10_runtime.vehicles_in_airspace) do
if (vehicle == vehicle_name) then
-- Already in the list, nothing to do
return
elseif (vehicle == "") then
-- Mark any free slots we've found
free_idx = i
end
end
-- The vehicle wasn't in the list, so we need to set it up
on_damage("m10_vehicle_over_roof_damaged", vehicle_name, 0.1)
local new_min = get_max_hit_points(vehicle_name) * 0.1
set_min_hit_points(vehicle_name, new_min)
local driver = vehicle_get_driver(vehicle_name)
if (driver ~= nil) then
turn_invulnerable(vehicle_get_driver(vehicle_name))
end
-- Store the name of the vehicle
if (free_idx == -1) then
free_idx = sizeof_table(M10_runtime.vehicles_in_airspace) + 1
end
M10_runtime.vehicles_in_airspace[free_idx] = vehicle_name
end
end
-- Callback when a character enters the airspace above the strip club roof
--
-- triggerer: Name of the character that entered the trigger region
-- trigger_name: Name of the trigger region that the character entered
function m10_roof_air_space_exited(triggerer, trigger_name)
if (triggerer == nil or triggerer == "") then
return
end
local vehicle_name = get_char_vehicle_name(triggerer)
if (vehicle_name == nil or vehicle_name == "") then
return
end
if (vehicle_name ~= "") then
-- Find the vehicle in our list
for i, vehicle in pairs(M10_runtime.vehicles_in_airspace) do
if (vehicle == vehicle_name) then
on_damage("", vehicle_name)
local driver = vehicle_get_driver(vehicle_name)
if (driver ~= nil) then
turn_vulnerable(driver)
end
set_min_hit_points(vehicle_name, 0)
M10_runtime.vehicles_in_airspace[i] = ""
return
end
end
end
end
-- Callback when a vehicle currently in the airspace above the strip club is damaged past 0.1 health
--
-- victim: Name of the object that was damaged
function m10_vehicle_over_roof_damaged(victim)
if (victim == "") then
return
end
-- Remove this callback
on_damage("", victim)
turn_invulnerable(victim)
--add this guy to a list
-- Check if the vehicle is already in the list
local free_idx = -1
local found_vehicle = false
for i, vehicle in pairs(M10_runtime.damaged_vehicles_exiting) do
if (vehicle == victim) then
-- Already in the list, nothing to do
found_vehicle = true
elseif (vehicle == "") then
-- Mark any free slots we've found
free_idx = i
end
end
if (free_idx == -1) then
free_idx = sizeof_table(M10_runtime.damaged_vehicles_exiting) + 1
end
M10_runtime.damaged_vehicles_exiting[free_idx] = victim
-- Smoke and fire time
vehicle_set_smoke_and_fire_state(victim, true, false)
-- Pick a random point to fly to outside of the club's airspace, and fly to it
local point_idx = rand_int(1, sizeof_table(M10_navpoints.clear_airspace_points))
helicopter_fly_to_dont_stop(victim, -1, M10_navpoints.clear_airspace_points[point_idx])
-- Now destroy the helicopter
vehicle_set_smoke_and_fire_state(victim, true, true)
set_min_hit_points(victim, 0)
delay(1)
turn_vulnerable(victim)
vehicle_detonate(victim)
for i, vehicle in pairs(M10_runtime.damaged_vehicles_exiting) do
if (vehicle == victim) then
M10_runtime.damaged_vehicles_exiting[i] = ""
return
end
end
end
-- Called when one of the vtols the player must destroy dies
--
-- vehicle_name: Name of the vehicle that wsa destroyed
function m10_vtol_destroyed_cb(vehicle_name)
M10_runtime.roof_attack_vtols_killed = M10_runtime.roof_attack_vtols_killed + 1
on_vehicle_destroyed("", vehicle_name)
marker_remove(vehicle_name)
end
function m10_transport_vtol_destroyed_cb(victim)
on_vehicle_destroyed("", victim)
--wait, then unload this dude, high component vehicles suck
delay(10)
if (victim == M10_groups.stag_transport_01a_vtol.vtol) then
cleanup_groups(M10_groups.stag_transport_01a_vtol.name)
elseif (victim == M10_groups.stag_transport_01_vtol.vtol) then
cleanup_groups(M10_groups.stag_transport_01_vtol.name)
elseif (victim == M10_groups.stag_transport_02_vtol.vtol) then
cleanup_groups(M10_groups.stag_transport_02_vtol.name)
elseif (victim == M10_groups.stag_transport_02b_vtol.vtol) then
cleanup_groups(M10_groups.stag_transport_02b_vtol.name)
elseif (victim == M10_groups.stag_transport_03_vtol.vtol) then
cleanup_groups(M10_groups.stag_transport_03_vtol.name)
elseif (victim == M10_groups.stag_transport_04_vtol.vtol) then
cleanup_groups(M10_groups.stag_transport_04_vtol.name)
elseif (victim == M10_groups.stag_transport_05_vtol.vtol) then
cleanup_groups(M10_groups.stag_transport_05_vtol.name)
end
end
-- Callback when a character in a VTOL in the flyby enters the fire region
--
-- triggerer: Character that entered the trigger region
-- trigger_name: Name of the trigger region that the chracter entered
function m10_vtol_flyby_fire_cb(triggerer, trigger_name)
local vtol_group = nil
-- Find the VTOL group containing this triggerer
for i, vtol in pairs(M10_runtime.vtol_flyby_groups) do
for j, char in pairs(vtol.chars) do
if (char == triggerer) then
vtol_group = vtol
end
end
end
-- If we found a VTOL group and it hasn't fired yet, then trigger the forced fire
if (vtol_group ~= nil and vtol_group.fired == false) then
for i, char in pairs(vtol_group.chars) do
-- Need to add an enemy, to make sure the pilot equips the VTOL weapon
if (vtol_group.target ~= "") then
ai_add_enemy_target(char, vtol_group.target, ATTACK_NOW_NEVER_LOSE, false)
end
set_perfect_aim(char, true)
end
-- Mark that this VTOL has fired
vtol_group.fired = true
-- Determine what type of target this VTOL is supposed to shoot at
if (vtol_group.target_nav ~= nil) then
helicopter_shoot_navpoint(vtol_group.vehicle, vtol_group.target_nav, vtol_group.rockets)
elseif (vtol_group.target ~= "") then
helicopter_shoot_human(vtol_group.vehicle, vtol_group.target, false, 0.0, vtol_group.rockets)
end
end
--audio_play_persona_line(LOCAL_PLAYER, M10_dialog_lines.oleg_riding_vtol)
end
-- *************************
--
-- Thread functions
--
-- *************************
-- Helper function to process an attack VTOL flying to it's initial destination
--
-- vehicle_table: VTOL Lua table (as defined in M10_groups::attack_vtols::vtols)
function m10_attack_vtol_fly_to(vehicle_table)
-- Wait the specified amount of time
delay(vehicle_table.delay)
-- Fly to the destination
vehicle_max_speed(vehicle_table.vtol, vehicle_table.speed)
helicopter_fly_to_direct(vehicle_table.vtol, vehicle_table.speed, vehicle_table.destination)
vehicle_max_speed(vehicle_table.vtol, -1.0)
end
-- Main thread for the vtols in the survive portion of the mission
--
-- vehicle_table: VTOL Lua table (as defined in M10_groups::attack_vtols::vtols)
-- do_pathfind: TRUE if the VTOL should do the initial pathfind, false otherwise
function m10_vtol_attack_thread(vehicle_table, do_pathfind)
-- Check if we should do the initial pathfind
if (do_pathfind == true) then
m10_attack_vtol_fly_to(vehicle_table)
end
-- Register all the enemies
ai_add_enemy_target(vehicle_table.chars[1], LOCAL_PLAYER, ATTACK_ON_SIGHT)
ai_add_enemy_target(vehicle_table.chars[1], M10_characters.viola, ATTACK_ON_SIGHT)
ai_add_enemy_target(vehicle_table.chars[1], M10_characters.oleg, ATTACK_ON_SIGHT)
if (coop_is_active() == true) then
ai_add_enemy_target(vehicle_table.chars[1], REMOTE_PLAYER, ATTACK_ON_SIGHT)
end
ai_set_action_delay(vehicle_table.chars[1], "throw grenade", 9999)
-- Add a marker and put the VTOL in chase mode
marker_add(vehicle_table.vtol, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL)
vehicle_chase(vehicle_table.vtol, LOCAL_PLAYER, false, false, true, false)
end
-- Process a VTOL transport drop-off
--
-- transport_table: VTOL transport Lua table (as defined in M10_groups::stag_transport_01)
-- soldier_markers: TRUE to add markers to the soldiers when the exit VTOL, FALSE to now put markers on the soldier
function m10_vtol_transport_drop_off_thread(transport_table, soldier_markers)
-- Add this transport to the transport array
local transport_idx = #M10_runtime.transport_vtols + 1
M10_runtime.transport_vtols[transport_idx] = transport_table
-- Add the VTOL to the list of spawned VTOLs
M10_runtime.spawned_vtols[#M10_runtime.spawned_vtols + 1] = transport_table.vtol
-- Add a maker
--marker_add(transport_table.vtol, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL)
-- Play a bullhorn announcement
-- Loop over all of the drop off points, and do the drop-offs
for i, drop_off in pairs(transport_table.drop_offs) do
helicopter_fly_to_direct(transport_table.vtol, -1, drop_off.path)
-- Stop processing if the VTOL has been destroyed
local found_vehicle = false
for i, damaged_veh in pairs(M10_runtime.damaged_vehicles_exiting) do
if (damaged_veh == transport_table.vtol) then
found_vehicle = true
end
end
if (found_vehicle) then
--don't keep going, we were destroyed on the way in
break
end
-- If there's any dialog, then trigger it now
if (drop_off.dialog ~= nil) then
if (drop_off.dialog.speaker == "Interrogation" ) then
audio_play_persona_line_2d(M10_personas.interrogation.persona_id, drop_off.dialog.line)
else
audio_play_persona_line(drop_off.dialog.speaker, drop_off.dialog.line)
end
end
helicopter_enter_dropoff(transport_table.vtol, transport_table.heli_dropoff_nav, false, LOCAL_PLAYER, false)
while (vehicle_pathfind_check_done(transport_table.vtol) == 0) do
thread_yield()
end
-- Force all the soldiers that got dropped off to take cover
for j, char in pairs(drop_off.soldiers) do
if (character_is_dead(char) == false) then
--vehicle_exit(char, true)
npc_combat_enable(char, true)
npc_leash_to_nav(char, drop_off.navs[j], 8.0)
ai_add_enemy_target(M10_characters.oleg, char, ATTACK_NOW_NEVER_LOSE, false) -- tell oleg to attack these guys.
character_make_priority_target(char, true) -- make these guy a higher priority target
-- Some time is passed, make sure they're still alive
if (character_is_dead(char) == false) then
-- Add the marker
if (soldier_markers == true) then
marker_add(char, MINIMAP_ICON_KILL, OI_ASSET_KILL)
end
-- Make sure they made it onto the rooftop area
if (object_is_in_trigger(transport_table.rooftop_trigger, char) == false) then
-- They didn't make it onto the roof, kill them
character_kill(char)
else
-- They're on the roof for now - add them to the list so we know if they've fallen off
M10_runtime.rooftop_trigger_chars[#M10_runtime.rooftop_trigger_chars + 1] = char
end
end
end
end
--[[
-- Tell the soldiers to exit the transport VTOL
vehicle_exit_group(drop_off.soldiers, true) -- unenterable to make sure the soldiers don't try to get back in the transport
delay(3)
--]]
-- Stop processing if the VTOL has been destroyed
if (vehicle_is_destroyed(transport_table.vtol) == true) then
break
end
end
if (transport_table.snipers and M10_runtime.transport_snipers_alive > 0) then
--audio_play_persona_line(LOCAL_PLAYER, M10_dialog_lines.rooftop)
elseif (transport_table.oleg_line ~= "") then
audio_play_persona_line(M10_characters.oleg, transport_table.oleg_line)
end
-- Remove the marker
marker_remove(transport_table.vtol)
transport_table.marker_removed = true
-- All drop offs are complete, so tell it to retreat
-- if it's smoking or on fire and it's invulnerable, it's already destroyed, just running away from the roof
local smoke, fire = vehicle_get_smoke_and_fire_state(transport_table.vtol)
local dying = vehicle_is_invulnerable(transport_table.vtol) and (smoke or fire)
if (vehicle_is_destroyed(transport_table.vtol) == false and dying == false ) then
--fly a path before retreating
if (transport_table.escape_path ~= "") then
helicopter_fly_to_direct(transport_table.vtol, -1, transport_table.escape_path)
end
--now retreat
helicopter_enter_retreat(transport_table.vtol)
-- whatever we do, never ever release a vehicle that's in our airspace
local in_airspace = true
while (in_airspace == true) do
in_airspace = false
for i, vehicle in pairs(M10_runtime.vehicles_in_airspace) do
if (vehicle == transport_table.vtol) then
in_airspace = true
end
end
delay(1)
end
--or being scripted to fly away due to damage
local dying_helicopter = true
while (dying_helicopter == true) do
dying_helicopter = false
for i, vehicle in pairs(M10_runtime.damaged_vehicles_exiting) do
if (vehicle == transport_table.vtol) then
dying_helicopter = true
end
end
delay(1)
end
-- Release the transport VTOL and the pilots to the world
release_to_world(transport_table.vtol)
for i, pilot in pairs(transport_table.pilots) do
release_to_world(pilot)
end
end
-- Remove this transport to the transport array
M10_runtime.transport_vtols[transport_idx] = M10_runtime.transport_vtols[#M10_runtime.transport_vtols]
M10_runtime.transport_vtols[#M10_runtime.transport_vtols] = nil
end
-- Thread to process a STAG VTOL flyby
--
-- vtol_table: Lua table defining the VTOL
function m10_thread_run_stag_flyby_vtol(vtol_table)
-- Track this VTOL flyby group
local group_idx = #M10_runtime.vtol_flyby_groups + 1
M10_runtime.vtol_flyby_groups[group_idx] = vtol_table
-- Add the VTOL to the list of spawned VTOLs
M10_runtime.spawned_vtols[#M10_runtime.spawned_vtols + 1] = vtol_table.vehicle
if (vtol_table.invulnerable == true) then
turn_invulnerable(vtol_table.vehicle, false)
for i, char in pairs (vtol_table.chars) do
turn_invulnerable(char, false)
end
end
if (vtol_table.vehicle == "veh_vtol_bridge_03_ 001") then
vehicle_enter_teleport(vtol_table.chars[1], vtol_table.vehicle, 0, true, true)
vehicle_enter_teleport(vtol_table.chars[2], vtol_table.vehicle, 1, true, true)
vehicle_enter_teleport(vtol_table.chars[3], vtol_table.vehicle, 2, true, true, true)
else
vehicle_enter_group_teleport(vtol_table.chars, vtol_table.vehicle)
end
vehicle_max_speed(vtol_table.vehicle, vtol_table.speed)
-- "Pre-aim" at the target, so the VTOL Laser can better track the position (otherwise the weapons can keep up with the movement)
if (vtol_table.target ~= nil) then
for i, char in pairs(vtol_table.chars) do
ai_add_enemy_target(char, vtol_table.target, ATTACK_NOW_NEVER_LOSE, false)
end
else
for i, char in pairs(vtol_table.chars) do
npc_combat_enable(char, false)
end
end
ai_set_action_delay(vtol_table.chars[1], "throw grenade", 9999)
if (vtol_table.target_nav ~= nil) then
helicopter_shoot_navpoint(vtol_table.vehicle, vtol_table.target_nav)
else
-- If not target is specified, assume Oleg's current position navpoint
helicopter_shoot_navpoint(vtol_table.vehicle, M10_navpoints.roof_oleg_dest)
end
-- Give them perfect aim (they need to hit their targets)
if (vtol_table.no_perfect_aim == nil or vtol_table.no_perfect_aim == false) then
set_perfect_aim(vtol_table.chars[1], true)
end
-- vehicle_anim_start(vtol_table.vehicle, "vtol jet flyby", nil)
helicopter_set_path_orientation(vtol_table.vehicle, HELI_PF_PATH_PITCH)
helicopter_fly_to_direct(vtol_table.vehicle, vtol_table.speed, vtol_table.path)
-- Hide the vehicle at the end of the pathfind
vehicle_hide(vtol_table.vehicle)
-- Unregister this VTOL flyby group
M10_runtime.vtol_flyby_groups[group_idx] = M10_runtime.vtol_flyby_groups[#M10_runtime.vtol_flyby_groups]
M10_runtime.vtol_flyby_groups[#M10_runtime.vtol_flyby_groups] = nil
end
-- Thread to process a squadron of VTOLs doing a flyby
--
-- vtol_group: Lua table defining the group of VTOLs doing a flyby
function m10_thread_process_flyby(vtol_group)
-- Create a thread for each VTOL in the flyby
for i, vtol in pairs(vtol_group.vtols) do
vtol.thread_id = thread_new("m10_thread_run_stag_flyby_vtol", vtol)
end
-- Wait until each thread has finished
local flyby_finished = false
while(flyby_finished == false) do
flyby_finished = true
for i, vtol in pairs(vtol_group.vtols) do
if (thread_check_done(vtol.thread_id) == false) then
flyby_finished = false
end
end
thread_yield()
end
-- Destroy the script group
group_destroy(vtol_group.name)
end
-- Process the continuous spawn of transport VTOLs dropping enemies off on the strip club roof
--
-- vtol_cont_spawn: The VTOL continuous spawn Lua table (as defined in M10_vtol_cont_spawn)
-- delay_time: Time (in seconds) to delay before starting the continuous spawn
function m10_club_drop_off_cont_spawn_thread(vtol_cont_spawn, delay_time)
-- Add a delay before the first VTOL drop-off occurs
delay(delay_time)
-- Loop forever
local group_idx = 1
while (true) do
thread_yield()
-- Create the VTOL group
if (group_is_loaded(vtol_cont_spawn.groups[group_idx].name) == true) then
group_destroy(vtol_cont_spawn.groups[group_idx].name)
thread_yield()
end
group_create(vtol_cont_spawn.groups[group_idx].name, true)
-- Put all the soldiers in the VTOL
local seat_idx = 0
for i, char in pairs(vtol_cont_spawn.groups[group_idx].chars) do
vehicle_enter_teleport(char, vtol_cont_spawn.groups[group_idx].vtol, seat_idx, true)
-- Increment the seat index
seat_idx = seat_idx + 1
if (i == 1) then
-- Make the pilot stay in the vehicle
follower_remain_in_car(char, true)
-- Skip the first passenger seat
seat_idx = seat_idx + 1
end
end
-- Add a marker to the VTOL
--marker_add(vtol_cont_spawn.groups[group_idx].vtol, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL)
-- Start a pathfind to a random destination point
local dest_idx = rand_int(1, sizeof_table(vtol_cont_spawn.groups[group_idx].dest_navs))
helicopter_fly_to_direct(vtol_cont_spawn.groups[group_idx].vtol, -1, vtol_cont_spawn.groups[group_idx].path)
-- Check if the VTOL made it to the drop-off point (if it got blown up mid-flight, we should just create a new continuous spawn)
if (vehicle_is_destroyed(vtol_cont_spawn.groups[group_idx].vtol) == false) then
-- Unlease Oleg
npc_leash_remove(M10_characters.oleg)
-- Make the soldiers exit the VTOL
for i, char in pairs(vtol_cont_spawn.groups[group_idx].chars) do
if (i ~= 1) then
vehicle_exit(char, true)
ai_add_enemy_target(M10_characters.oleg, char, ATTACK_ON_SIGHT)
end
end
-- Remove the marker, and retreat
delay(1.0)
--marker_remove(vtol_cont_spawn.groups[group_idx].vtol)
helicopter_enter_retreat(vtol_cont_spawn.groups[group_idx].vtol)
-- Wait until all the soldiers are incapacitated
local all_soldiers_incapacitated = false
while(all_soldiers_incapacitated == false) do
-- Loop over all the soldiers in the VTOL, to see if any are still alive
all_soldiers_incapacitated = true
for i, char in pairs(vtol_cont_spawn.groups[group_idx].chars) do
-- Skip the pilot
if (i ~= 1) then
-- If this guy is alive (and not in a vehicle) then not all the soliders have been incapacitated
if (character_is_dead(char) == false and character_is_in_vehicle(char) == false) then
all_soldiers_incapacitated = false
ai_add_enemy_target(M10_characters.oleg, char, ATTACK_NOW)
break
end
end
end
thread_yield()
end
-- Leash Oleg again
ai_do_scripted_move(M10_characters.oleg, M10_navpoints.roof_oleg_dest, true)
npc_leash_to_nav(M10_characters.oleg, M10_navpoints.roof_oleg_dest, 1.0)
end
--marker_remove(vtol_cont_spawn.groups[group_idx].vtol)
-- Wait 50 seconds before respawning the continuous spawn
delay(50.0)
-- Remove the group
group_destroy(vtol_cont_spawn.groups[group_idx].name)
local group_idx = group_idx + 1
if (group_idx > sizeof_table(vtol_cont_spawn.groups)) then
group_idx = 1
end
end
end
-- Process the tanks chasing after the VTOL with Oleg on it
--
-- tank_table: Tank Lua table (as defined in M10_groups::stag_ground_troops::tanks)
function m10_process_tank_chase_thread(tank_table)
vehicle_pathfind_to(tank_table.tank, tank_table.chase_path, true, false)
vehicle_chase(tank_table.tank, M10_characters.oleg)
end