--[[
m01.lua
SR3 Mission Script
DATE: 03-10-2010
AUTHOR: Neil Ryan
]]--
-- Debug flags --
-- Tweakable Parameters --
M01_TRANSITION_TIME = 1000
M01_seconds_to_wait_for_gat_to_kill_guard = 18
M01_MIN_PITCH = -20
M01_MAX_PITCH = 20
M01_MIN_HEADING = -45
M01_MAX_HEADING = 45
M01_VAULT_TARGET_TIME1 = 3.0
M01_VAULT_TARGET_TIME2 = 6.0
-- damage required to kill the first helicopter as percent health left
M01_HELI_DAMAGE = 0.80
-- delay between calling the M01_Get_Robbed situation
M01_Get_Robbed_Line_Time = 15.0
-- delay between calling the M01_Attack situation
M01_Attack_Line_Time = 10.0
M01_player_health = {
shot1 = 0.7,
shot2 = 0.4,
shot3 = 0.3,
break_chains = 0.2
}
-- Groups --
M01_group = {
lobby_cower = {
name = "cower_npc_group",
on_ground = { "cower_npc<001>", "cower_npc<003>", --"cower_npc<002>",
"cower_npc<006>", --"cower_npc<004>", "cower_npc<005>",
"cower_npc<007>", "cower_npc<008>", "cower_npc<009>" },
members = { "cower_npc<010>", "cower_npc<011>", "cower_npc<012>",
"cower_npc<013>", "cower_npc<014>", "cower_npc<015>",
"cower_npc<016>", "cower_npc<017>" },
saints_fan = "cower_npc<009>"
},
lobby = {
name = "lobby_group 001",
members = { "lobby_guard 001", "lobby_guard 002", --"lobby_guard 003", "lobby_guard 004", "lobby_guard 005",
"Teller 001", "Teller 002", "Teller 003", "Teller 004" },
tellers = { "Teller 001", "Teller 002", "Teller 003", "Teller 004" },
moving_guards = { "lobby_guard 001", "lobby_guard 002"},-- "lobby_guard 003", "lobby_guard 004" },
guard_navs = { "Lobby_guard_nav<001>", "Lobby_guard_nav<002>"},-- "Lobby_guard_nav<003>", "Lobby_guard_nav<004>" },
},
lobby2 = {
name = "lobby_group 002",
members = { "lobby2_guard 001", "lobby2_guard 002" },
},
lobby3 = {
name = "lobby_group 003",
doorman = "lobby2_guard 003",
members = { "lobby2_guard 004", "lobby2_guard 005", "lobby2_guard 006" },
},
fine_aim = {
name = "fine_aim_group",
members = { "fine_aim 001", "fine_aim 002" }
},
second_floor = {
name = "second_floor_group 001",
members = { "second_floor 001", "second_floor 002", "second_floor 003",
"second_floor 004", "second_floor 005", "second_floor 006" },
shaundi_attacker = "shaundi_attacker"
},
third_floor = {
name = "third_floor_group 001",
to_second_members = { "third_floor 003", "third_floor 004" }
},
bomb_security2 = {
name = "bomb_security 002",
members = { "fourth_floor 001", "fourth_floor 002", "fourth_floor 003",
"fourth_floor 004", "fourth_floor 005", "fourth_floor 006" },
rocket_guys = { "fourth_floor 006" },
},
bomb_cower = {
name = "bomb_cower_group",
on_ground = {},
members = { "bomb_cower<001>", "bomb_cower<002>", "bomb_cower<003>",
"bomb_cower<004>" }
},
bomb_flee = {
name = "bomb_flee_group",
members = { "bomb_flee<001>", --"bomb_flee<002>", "bomb_flee<003>",
--"bomb_flee<004>", --"bomb_flee<005>", "bomb_flee<006>",
--"bomb_flee<007>",
--"bomb_flee<008>", --"bomb_flee<009>",
--"bomb_flee<010>"
},
dest = "bomb_flee_dest"
},
autograph = {
name = "autograph_guy_group",
guy = "autograph_guy",
trigger = "autograph_trigger",
josh_nav = "Josh_autograph",
josh_close_nav = "Josh_autograph_close",
thread = INVALID_THREAD_HANDLE,
effect_handle = -1
},
rope = {
name = "rope_group",
members = {
{ name = "rope<001>",
is_down = false },
{ name = "rope<002>",
is_down = false },
{ name = "rope<003>",
is_down = false },
{ name = "rope<004>",
is_down = false },
{ name = "rope<005>",
is_down = false },
{ name = "rope<006>", -- place of 2a
is_down = false },
}
},
swat1_pair = {
name = "swat1_pair_group",
members = { "swat1_pair<001>", "swat1_pair<002>" },
navs = { { "window_mark 005", "window_mark 004" },
{ "window_mark 005", "window_mark 004" } },
ropes = { 5, 4 },
set = 1,
thread = INVALID_THREAD_HANDLE,
entry_thread = INVALID_THREAD_HANDLE,
window_entry = true,
active = false
},
swat2_pair = {
name = "swat2_pair_group",
members = { "swat2_pair<001>", "swat2_pair<002>" },
navs = { { "window_mark 003", "window_mark 002a" },
{ "window_mark 003", "window_mark 002a" } },
ropes = { 3, 6 },
set = 1,
thread = INVALID_THREAD_HANDLE,
entry_thread = INVALID_THREAD_HANDLE,
window_entry = true,
active = false
},
swat3_pair = {
name = "swat3_pair_group",
members = { "swat3_pair<001>", "swat3_pair<002>" },
navs = { { "window_mark 002", "window_mark 001" },
{ "window_mark 002", "window_mark 001" } },
ropes = { 2, 1 },
set = 1,
thread = INVALID_THREAD_HANDLE,
entry_thread = INVALID_THREAD_HANDLE,
window_entry = true,
active = false
},
swat4_pair = {
name = "swat4_pair_group",
members = { "swat4_pair 001", "swat4_pair 002" },
navs = { { "fifth_floor_mark 001", "fifth_floor_mark 002" },
{ "fifth_floor_mark 001", "fifth_floor_mark 002" } },
set = 1,
thread = INVALID_THREAD_HANDLE,
window_entry = false,
active = false
},
swat5_pair = {
name = "swat5_pair_group",
members = { "swat5_pair 001", "swat5_pair 002" },
navs = { { "fifth_floor_mark 003", "fifth_floor_mark 004" },
{ "fifth_floor_mark 003", "fifth_floor_mark 004" } },
set = 1,
thread = INVALID_THREAD_HANDLE,
window_entry = false,
active = false
},
swat_riot_pair = {
name = "swat_riot_pair_group",
members = { "swat_riot_pair<001>", "swat_riot_pair<002>" },
navs = { { "window_mark 005", "window_mark 004" },
{ "window_mark 005", "window_mark 004" } },
ropes = { 5, 4 },
set = 1,
thread = INVALID_THREAD_HANDLE,
entry_thread = INVALID_THREAD_HANDLE,
window_entry = true,
active = false
},
-- *****************
-- News Heli's
-- News helis have spotlights that move around and no gunner. These are just for show.
-- News helis have multiple locations and interest points to highlight the action.
-- A global control M01_news_location determines where to be and what to look at
-- If a M01_news_location is greater than max_locations, news chopper stays at last location.
-- *****************
news_heli1 = {
name = "news1_heli_group",
vehicle = "News1_heli",
members = { "News1_pilot<001>", "News1_pilot<002>" },
float_nav = "news1_float",
location = {
{ -- 1 fine_aim
hover_nav = "fine_aim_news1_nav", -- place to hover (or looping path)
looping_path = false,
interest = { "fine_aim_spot<001>", "fine_aim_spot<002>" }, -- groups of 2 interest points for each location
delay_time = 4.0, -- time to look at each point of interest
},
{ -- 2 swat
hover_nav = "swat_news1_nav",
looping_path = false,
interest = { "glass<001>", "glass<005>" },
delay_time = 2.2,
},
{ -- 3 vault
hover_nav = "news1_vault<001>",
looping_path = false,
interest = { "roof_mark 001", "roof_mark 007" },
delay_time = 4.0,
},
{ -- 4 loop
hover_nav = "news1_loop_path",
looping_path = true,
interest = { "roof_mark 001", "roof_mark 007" },
delay_time = 4.0,
},
},
max_locations = 4, -- number of locations setup for this heli (interest groups and locations)
news_thread = INVALID_THREAD_HANDLE,
thread = INVALID_THREAD_HANDLE
},
news_heli2 = {
name = "news2_heli_group",
vehicle = "News2_heli",
members = { "News2_pilot<001>", "News2_pilot<002>" },
float_nav = "news2_float",
location = {
{ -- 1 fine_aim
hover_nav = "fine_aim_news2_nav",
looping_path = false,
interest = { "fine_aim_spot<002>", "fine_aim_spot<001>" },
delay_time = 3.0,
},
{ -- 2 swat
hover_nav = "swat_news2_nav",
looping_path = false,
interest = { "glass<005>", "glass<001>" },
delay_time = 2.0,
},
{ -- 3 vault
hover_nav = "news2_vault<001>",
looping_path = false,
interest = { LOCAL_PLAYER, "roof_mark 001" },
delay_time = 6.0,
},
{ -- 4 loop
hover_nav = "news2_loop_path",
looping_path = true,
interest = { LOCAL_PLAYER, "roof_mark 001" },
delay_time = 6.0,
},
},
max_locations = 4,
news_thread = INVALID_THREAD_HANDLE,
thread = INVALID_THREAD_HANDLE
},
vault_heli = {
name = "vault_heli_group",
vehicle = "heli_vault 001",
pilot = "vault_pilot 001",
nav = "vault_nav 001"
},
vault_attackers2 = {
name = "vault_attackers_group",
members = { "vault_attacker<001>", "vault_attacker<002>", "vault_attacker<003>", "vault_attacker<004>",
"vault_attacker<005>", "vault_attacker<006>", "vault_attacker<007>", "vault_attacker<008>",
"vault_attacker<009>", "vault_attacker<010>" },
navs = { "vault_attack_nav<001>", "vault_attack_nav<002>", "vault_attack_nav<003>", "vault_attack_nav<004>",
"vault_attack_nav<005>", "vault_attack_nav<006>", "vault_attack_nav<007>", "vault_attack_nav<008>",
"vault_attack_nav<009>", "vault_attack_nav<010>" },
gat = "vault_attacker Gat",
shaundi = "vault_attacker Shaundi"
},
roof1_pair = {
name = "roof1_pair_group",
members = { "roof1_pair 001", "roof1_pair 002" },
navs = { { "roof_mark 001", "roof_mark 002" },
{ "roof_mark 003", "roof_mark 004" } },
set = 1,
thread = INVALID_THREAD_HANDLE,
window_entry = false,
active = false
},
roof2_pair = {
name = "roof2_pair_group",
members = { "roof2_pair 001", "roof2_pair 002" },
navs = { { "roof_mark 003", "roof_mark 004" },
{ "roof_mark 001", "roof_mark 002" } },
set = 1,
thread = INVALID_THREAD_HANDLE,
window_entry = false,
active = false
},
roof3_pair = {
name = "roof3_pair_group",
members = { "roof3_pair 001", "roof3_pair 002" },
navs = { { "roof_mark 007", "roof_mark 008" },
{ "roof_mark 001", "roof_mark 002" } },
set = 1,
thread = INVALID_THREAD_HANDLE,
window_entry = false,
active = false
},
roof4_pair = {
name = "roof4_pair_group",
members = { "roof4_pair 001", "roof4_pair 002" },
navs = { { "Fifth_window 001", "Fifth_window 002" },
{ "Fifth_window 003", "Fifth_window 004" } },
set = 1,
thread = INVALID_THREAD_HANDLE,
window_entry = false,
active = false
},
roof5_pair = {
name = "roof5_pair_group",
members = { "roof5_pair 001", "roof5_pair 002" },
navs = { { "Fifth_window 003", "Fifth_window 004" },
{ "Fifth_window 001", "Fifth_window 002" } },
set = 1,
thread = INVALID_THREAD_HANDLE,
window_entry = false,
active = false
},
-- *****************
-- Transports
-- Transports float high above. They land, drop off their soldiers and fly away
-- *****************
transport1 = {
name = "transport1_heli_group",
vehicle = "transport1_heli",
pilots = { "transport1_heli_pilot 001", "transport1_heli_pilot 002" },
soldiers = { "transport1_heli_soldier 001", "transport1_heli_soldier 002", "transport1_heli_soldier 003"},
soldier_dest = "roof_mark 005",
float_nav = "transport1_float",
path = "transport1_heli_nav",
exit_nav = "transport1_float",
pilot_persona = "",
persona_line = "",
complete = false,
ground_delay = 3.0,
thread = INVALID_THREAD_HANDLE,
drop_off_thread = INVALID_THREAD_HANDLE,
setup_thread = INVALID_THREAD_HANDLE
},
transport2 = {
name = "transport2_heli_group",
vehicle = "transport2_heli",
pilots = { "transport2_heli_pilot 001", "transport2_heli_pilot 002" },
soldiers = { "transport2_heli_soldier 001", "transport2_heli_soldier 002", "transport2_heli_soldier 003"},
soldier_dest = "roof_mark 006",
float_nav = "transport2_float",
path = "transport2_heli_nav",
exit_nav = "transport2_float",
pilot_persona = "Interrogation",
persona_line = "M01_Bullhorn_Heli_Drop_02",
complete = false,
ground_delay = 3.0,
flyby_float = "transport2_flyby_start",
flyby_path = "transport2_flyby_path",
thread = INVALID_THREAD_HANDLE,
drop_off_thread = INVALID_THREAD_HANDLE,
setup_thread = INVALID_THREAD_HANDLE
},
transport3 = {
name = "transport3_heli_group",
vehicle = "transport3_heli",
pilots = { "transport3_heli_pilot<001>", "transport3_heli_pilot<002>" },
soldiers = { "transport3_heli_soldier<001>", "transport3_heli_soldier<002>", "transport3_heli_soldier<003>"},
soldier_dest = "roof_mark 002",
float_nav = "transport3_float",
path = "transport3_heli_nav",
exit_nav = "transport3_float",
pilot_persona = "Interrogation",
persona_line = "M01_Bullhorn_Heli_Drop_After_Crash",
complete = false,
ground_delay = 7.0,
flyby_float = "transport3_flyby_start",
flyby_path = "transport3_flyby_path",
thread = INVALID_THREAD_HANDLE,
drop_off_thread = INVALID_THREAD_HANDLE,
setup_thread = INVALID_THREAD_HANDLE
},
roof2 = {
name = "roof_2set_group",
members = { "roof_2set 001", "roof_2set 002", "roof_2set 003",
"roof_2set 004", "roof_2set 005" }
},
heli_police1 = {
name= "heli_police_group 001",
vehicle = "police_heli 001",
members = { "heli_police 001", "heli_police 002" },
shooter = "heli_police 003",
shooter_seat = 4,
crash_nav = "cubicle_cover 002",
pilot_persona = "Interrogation",
persona_line = "M01_Bullhorn_Sniper_Heli_02",
thread = INVALID_THREAD_HANDLE,
setup_thread = INVALID_THREAD_HANDLE
},
heli_police2 = {
name= "heli_police_group 002",
vehicle = "police_heli 002",
members = { "heli_police 004", "heli_police 005" },
shooter = "heli_police 006",
home_nav = "heli_police2_home",
shooter_seat = 4,
crash_nav = "police_heli_nav 005",
pilot_persona = "Interrogation",
persona_line = "M01_Bullhorn_Sniper_Heli_01",
thread = INVALID_THREAD_HANDLE,
setup_thread = INVALID_THREAD_HANDLE
},
heli_fighter1 = {
name= "heli_police_group 003",
vehicle = "police_heli 003",
members = { "heli_police 007", "heli_police 008" },
damaged = false,
damage1 = 0.6,
damage2 = 0.4,
damage3 = 0.2,
flyby_float = "flyby_float_nav",
flyby_path = "flyby 001",
run1 = {
enter_path = "run1_enter",
exit_path = "run1_exit",
float_from_nav = "run1_dest<001>", -- start gunning here
float_to_nav = "run1_dest<002>", -- end gunning here
float_speed = 4.0,
gun_target = "run1_gun_target",
gun_time = 3.0,
hit_delay = 0.7,
persona_line = "M01_Bullhorn_Attack_Heli_Hover_01"
},
run2 = {
enter_path = "run2_enter",
exit_path = "run2_exit",
float_from_nav = "run2_dest<001>", -- start gunning here
float_to_nav = "run2_dest<002>", -- end gunning here
float_speed = 1.0,
gun_target = "run2_gun_target",
gun_time = 2.2,
hit_delay = 0.8,
persona_line = "M01_Bullhorn_Attack_Heli_Hover_02"
},
attack_path1 = "attack_path 001",
attack_path2 = "attack_path 002",
first_float = "first_float_nav",
roof_target = "roof_target",
first_target = "first_target",
hover_nav2 = "behind_building_nav",
attack_nav1 = "attack_position_nav",
attack_target1 = "attack_target1_nav",
attack_path2_part2 = "attack_path 002<001>",
attack_nav2 = "attack_position2_nav",
attack_target2 = "attack_target2_nav",
attack_path3 = "attack_path 003",
bail_path = "bail_path",
from_behind_float = "from_behind_float_nav",
from_behind_path = "from_behind_path",
suicide_path = "suicide_path",
final_nav = { "final_battle<001>", "final_battle<002>" },
attack_run_thread = INVALID_THREAD_HANDLE,
thread = INVALID_THREAD_HANDLE,
permission_to_fire = false,
gunner_thread = INVALID_THREAD_HANDLE
},
start_homies = {
name = "start_homies",
gat = "Gat_bobble",
gat_bobble = true,
shaundi = "Shaundi_bobble",
shaundi_bobble = true,
josh = "Josh_bobble",
josh_bobble = true,
captive = "gat_captive",
captive_nav = "gat_captive_nav"
},
bomb_homies = {
name = "bomb_homies",
gat = "Gat_bomb",
gat_bobble = false,
shaundi = "Shaundi_bomb",
shaundi_bobble = false,
josh = "Josh_bomb",
josh_bobble = false,
},
swat_homies = {
name = "swat_homies",
gat = "Gat_swat",
gat_bobble = false,
shaundi = "Shaundi_swat",
shaundi_bobble = false,
josh = "",
josh_bobble = false,
},
}
M01_josh = ""
M01_gat = ""
M01_shaundi = ""
M01_nyteblayde_advance_nav = { "lobby_mark 001", "lobby_mark 005", "second_floor_mark 004", "second_floor_mark 004", "Vault_player_nav" }
M01_grandstand_nav = "grandstand_nav"
M01_heli_police_groups = { M01_group.heli_police1, M01_group.heli_police2, M01_group.heli_fighter1 }
M01_pairs_spawned = 0
M01_HELI_SHOOTER_GROUP = "heli_shooter_group 001"
M01_HELI_SHOOTER = "heli_shooter 001"
M01_HELI_SHOOTER2 = "heli_shooter 002"
-- Navpoints --
CAMERA_TARGET1 = "res_cam_target 001"
CAMERA_TARGET2 = "res_cam_target 002"
CAMERA_TARGET3 = "res_cam_target 003"
CAMERA_TARGET4 = "res_cam_target 004"
CAMERA_TARGET_YOUR_HELI = "res_cam_target 005"
LOBBY_MARK = { "lobby_mark 001", "lobby_mark 002" }
LOBBY_MARK2 = { "lobby_mark 004", "lobby_mark 005", "lobby_mark 006" }
SECOND_FLOOR_MARK = { "second_floor_mark 001", "second_floor_mark 002", "second_floor_mark 003",
"second_floor_mark 004", "second_floor_mark 005", "second_floor_mark 006" }
M01_HOMIE_VAULT_MARK = { "Gat_mark_vault", "Shaundi_mark_vault", "Josh_mark_vault" }
M01_HOMIE_BOMB_MARK = { "Gat_mark_bomb", "Shaundi_mark_bomb", "Josh_mark_bomb" }
FIFTH_FLOOR_MARK = { "fifth_floor_mark 001", "fifth_floor_mark 002", "fifth_floor_mark 003", "fifth_floor_mark 004" }
ROOF_MARK = { "roof_mark 001", "roof_mark 002", "roof_mark 003",
"roof_mark 004", "roof_mark 005" }
ROCKET_MARK = { "roof_mark 006" }
POLICE_HELI_NEWS_NAV = "police_heli_nav 001"
POLICE_HELI_WAIT_LOCATION1 = "police_heli_nav 002"
POLICE_HELI_WAIT_LOCATION2 = "police_heli_nav 003"
POLICE_HELI_SHOOT_AT_ME1 = "police_heli_nav 004"
POLICE_HELI_BUILDING_CRASH = "police_heli_nav 005"
POLICE_HELI2_START = "police_heli_nav 006"
POLICE_HELI_WAIT_LOCATION3 = "police_heli_nav 009"
POLICE_HELI_SHOOT_AT_ME2 = "police_heli_nav 007"
POLICE_HELI_SHOOT_AT_ME3 = "police_heli_nav 008"
POLICE_HELI_TO_HELI_CRASH = "police_heli_nav 010"
POLICE_HELI_CLOSE_CALL = "police_heli_nav 011"
POLICE_HELI_SURPRISE_NAV1 = "surprise_nav 001"
M01_cover = {
tellers = {
shaundi = "shaundi_tellers",
gat = "gat_tellers"
},
lobby2 = {
shaundi = "shaundi_lobby2",
gat = "gat_lobby2"
},
fine_aim = {
shaundi = "fine_aim_navpoint<001>",
gat = "fine_aim_navpoint<002>"
},
second_floor = {
shaundi = "shaundi_2floor",
gat = "gat_2floor"
}
}
-- Triggers --
M01_trigger = {
freerun = {
name = "Freerun_trigger 001",
hit = false
},
shaundi_attack = {
name = "shaundi_attack_trigger",
hit = false
},
pre_vault = {
name = "vault_trigger 000",
hit = false
},
vault = {
name = "vault_trigger 001",
hit = false
},
pre_bomb = {
name = "bomb_trigger 000",
hit = false
},
pre_bomb2 = {
name = "bomb_trigger 000<001>",
hit = false
},
bomb = {
name = "bomb_trigger 001",
hit = false
},
kill = {
name = "Kill_trigger",
hit = false
},
swat_kill = {
name = "Swat_kill_trigger",
hit = false
},
horse = {
name = "Horse_trigger",
hit = false
},
}
-- Characters --
-- Vehicles --
-- Mesh Movers --
LOBBY_DOOR01 = "Bank_Lobby_Door 001"
LOBBY_DOOR02 = "Bank_Lobby_Door 002"
M01_ELEVATOR_DOOR = "Bank_Lobby_Elevator"
M01_vault_mover = "Bank_vault"
M01_fine_aim_glass = { "fine_aim_glass<001>", "fine_aim_glass<002>", "fine_aim_glass<003>" }
-- Effects --
-- Text --
HELPTEXT_FAILURE_GAT_DIED = "m01_failure_gat_died"
HELPTEXT_FAILURE_SHAUNDI_DIED = "m01_failure_shaundi_died"
HELPTEXT_FAILURE_JOSH_DIED = "m01_failure_josh_died"
-- Threads --
M01_thread = {
move_guards = INVALID_THREAD_HANDLE,
josh_ai = INVALID_THREAD_HANDLE,
people_cower = INVALID_THREAD_HANDLE,
fine_aim_glass = INVALID_THREAD_HANDLE,
saints_fan = INVALID_THREAD_HANDLE,
conversation = INVALID_THREAD_HANDLE,
gat_hostage = INVALID_THREAD_HANDLE,
shaundi_move = INVALID_THREAD_HANDLE,
gat_move = INVALID_THREAD_HANDLE,
elevator = INVALID_THREAD_HANDLE,
respawn_timer = INVALID_THREAD_HANDLE,
homies_prep = INVALID_THREAD_HANDLE,
tutorial_timer = INVALID_THREAD_HANDLE,
battle_timer = INVALID_THREAD_HANDLE,
vault_setup = INVALID_THREAD_HANDLE,
vault_environ_setup = INVALID_THREAD_HANDLE,
attack_line_timer = INVALID_THREAD_HANDLE,
reset_movers = INVALID_THREAD_HANDLE,
line_timer = INVALID_THREAD_HANDLE,
}
M01_TUTORIAL_FINEAIM = INVALID_THREAD_HANDLE
M01_TUTORIAL_SWITCH_WEAPON = INVALID_THREAD_HANDLE
-- Checkpoints --
M01_checkpoint = {
start = {
name = MISSION_START_CHECKPOINT,
nav1 = "Start_player_nav<001>",
nav2 = "Start_player_nav<002>"
},
plant_bombs = {
name = "m01_checkpoint_plant_bombs",
nav1 = "Vault_player_nav",
nav2 = "Vault_player_nav<001>"
},
survive = {
name = "m01_checkpoint_survive",
nav1 = "player1_swat",
nav2 = "player2_swat"
},
ride_vault = {
name = "m01_checkpoint_ride_vault",
nav1 = "player1_vault",
nav2 = "player2_vault"
},
debug_swaps = {
name = "m01_just_swap",
nav1 = "debug_nav",
nav2 = "debug_nav"
},
}
-- Cutscenes --
M01_scene = {
intro = "01_IN",
at_vault = "01_z01",
explosives = "01_Z02",
connect_vault = "01_Z03",
heli_crash = "01_Z04",
}
-- Conversations --
M01_convo = {
gat_interrogate = {
name = "m01_convo_2",
handle = INVALID_CONVERSATION_HANDLE
},
gat_interrogate2 = {
name = "m01_convo_2a",
handle = INVALID_CONVERSATION_HANDLE
},
berate_josh = {
name = "M01_Berating_Josh",
handle = INVALID_CONVERSATION_HANDLE
},
look_for_vault = {
name = "m01_convo_3",
handle = INVALID_CONVERSATION_HANDLE
},
morningstar = {
name = "m01_convo_8",
handle = INVALID_CONVERSATION_HANDLE
},
josh_and_shaundi = {
name = "M01_Josh_Banter",
handle = INVALID_CONVERSATION_HANDLE
},
more_guys = {
name = "M01_More_Guys_Coming",
handle = INVALID_CONVERSATION_HANDLE
},
sign_autograph = {
name = "M01_Celebrity_Autographs",
handle = INVALID_CONVERSATION_HANDLE
},
set_explosives = {
name = "m01_convo_6",
handle = INVALID_CONVERSATION_HANDLE
},
swat_on_way = {
name = "M01_Swat_Almost_There",
handle = INVALID_CONVERSATION_HANDLE
},
swat_chit_chat = {
name = "M01_Annoyed_At_Birk_SWAT",
handle = INVALID_CONVERSATION_HANDLE
},
attack_chopper = {
name = "M01_Attack_Chopper",
handle = INVALID_CONVERSATION_HANDLE
},
hooked_up = {
name = "M01_Heli_Hooked_On",
handle = INVALID_CONVERSATION_HANDLE,
start = false,
delay = 0.0
},
heli_rising = {
name = "M01_Helicopter_Rising",
handle = INVALID_CONVERSATION_HANDLE,
start = false,
delay = 0.0
},
heli_jerk_back = {
name = "M01_Helicopter_Jerks_Back",
handle = INVALID_CONVERSATION_HANDLE,
start = false,
delay = 0.0
},
heli_not_leaving = {
name = "M01_Heli_Not_Leaving",
handle = INVALID_CONVERSATION_HANDLE,
start = false,
delay = 0.0
},
heli_drag_vault = {
name = "M01_Helicopter_Drag_Vault",
handle = INVALID_CONVERSATION_HANDLE,
start = false,
delay = 2.0
},
heli_near_collision = {
name = "M01_Heli_Near_Collision",
handle = INVALID_CONVERSATION_HANDLE,
start = false,
delay = 3.2
},
vault_tipped = {
name = "M01_Heli_Vault_Tipped",
handle = INVALID_CONVERSATION_HANDLE,
start = false,
delay = 0.0
},
}
M01_conversation_playing = false
M01_doing_autograph = false
M01_setting_bomb = false
M01_gat_attack_info = {
situation = "M01_Gat_attack",
delay = 10.0,
callback = "m01_process_gat_attack_cb",
timer = INVALID_THREAD_HANDLE
}
-- Audio --
M01_audio_emitter = {
bank_lobby = { "Bank_Lobby" },
fine_aim = { "Fine_Aim_City_Ambience" },
office = { "Office_Ambience" },
city_noise = { "Distant_Traffic" },
vault_noise = { "Distant_Sirens" },
}
-- HUD states --
M01_hud_state = {
hide_minimap = -1,
hide_everything = -1
}
-- Other --
-- heli-vault animations
M01_WAIT = true
M01_DO_NOT_WAIT = false
M01_INTERRUPT = true
M01_DO_NOT_INTERRUPT = false
M01_PLAYER_PISTOL = "Pistol-Gang"
M01_PLAYER_SHOTGUN = "Shotgun-Police"
M01_PLAYER_RIFLE = "Rifle-Gang"
M01_PLAYER_SMG = "SMG-Gang"
M01_PLAYER_GRENADE = "grenade"
M01_PLAYER_PISTOL_UPGRADES = WEAPON_LEVEL2
M01_PLAYER_SHOTGUN_UPGRADES = 0
M01_PLAYER_RIFLE_UPGRADES = WEAPON_LEVEL4
SNAP_CAMERA = true
BLEND_CAMERA = false
FLOOR_LEASH_RADIUS_METERS = 4.5
Helicopter_killed = false
M01_skip_fineaim_release = false
M01_weapon_changed = false
M01_guard_killed = false
M01_player_over_desk = false
M01_gat_at_door = false
M01_gat_finished_shooting = false
M01_lobby_cleared = false
M01_josh_grandstanded = false
M01_zone_name = "bank"
M01_zone_damaged_name = "bank_destroy"
M01_zone_stilwater = "stilwater"
M01_end_mission_nav1 = "end_mission 001"
M01_end_mission_nav2 = "end_mission 002"
M01_end_mission_demo = "end_mission_demo"
M01_window_entry_melee_id = 0
M01_throw_flashbangs = false
-- SWAT section lighting for power outage
M01_light_group = {
alarm = {
name = "Game_alarm_lights",
intensity = 0.0 -- scripted intensity is "off"
}
}
-- tell news choppers where to go and what to look at
M01_news = {
fine_aim = 1,
swat = 2,
vault = 3,
loop = 4
}
M01_news_location = M01_news.fine_aim
M01_fighter_run_complete = false
-- Shaundi attack info
M01_shaundi_attack = {
shuandi_nav = "shaundi_attacked_nav<001>",
shuandi_attack = "shaundi_attacked_nav",
josh_nav = "Josh_mark_vault",
in_place = false,
attacker = M01_group.second_floor.shaundi_attacker,
thread = INVALID_THREAD_HANDLE
}
M01_vault_camera_shake = "m01_vault_ride"
M01_swap_vault_seats = false
-- *************************
--
-- Standard functions
--
-- *************************
-- This is the primary entry point for the mission, and is responsible for starting up the mission
-- at the specified checkpoint.
-- CALLED FROM CODE
--
-- m01_checkpoint: The checkpoint the mission should begin at
-- is_restart: TRUE if the mission is restarting, FALSE otherwise
--
function m01_start(m01_checkpoint, is_restart)
mission_start_fade_out(0.0)
crib_weapon_add_disable()
-- turn off spawning for the speedz
m01_do_ambient_spawns(false)
-- turn off grenade drops
npc_drop_grenades(false)
-- debug checkpoint
if m01_checkpoint == "m01_checkpoint_coop" then
M01_swap_vault_seats = true
m01_checkpoint = M01_checkpoint.ride_vault.name
end
-- do swaps before we get to the cutscene
m01_initialize_swaps(m01_checkpoint)
-- suit up
customization_item_wear( "cm_suit_gatsuit", "cm_suit_gatsuit.cmeshx", "mGat_Body", false )
customization_item_wear( "cm_hat_gatbobble", "Cm_hat_gatbobble.cmeshx", "Gatbobble", false )
customization_swap_player_rig( "cm_body.rig", "PLYM" )
-- Check if this mission starting from the beginning
if (m01_checkpoint == M01_checkpoint.start.name) then
if (is_restart == false) then
-- First time playing mission
local player_starts = {M01_checkpoint.start.nav1, M01_checkpoint.start.nav2}
local fade_in_after = false
cutscene_play(M01_scene.intro, nil, player_starts, fade_in_after)
else
-- put players back at the start
teleport_coop(M01_checkpoint.start.nav1, M01_checkpoint.start.nav2, true)
end
end
-- Handle mission initialization for the current checkpoint
m01_initialize(m01_checkpoint)
-- Run the mission from the current checkpoint
m01_run(m01_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 m01_run(first_checkpoint)
local current_checkpoint = first_checkpoint
local ignore_vehicles = true
local ignore_notoriety = true
-- post voice event to mute non-modulated voice
audio_object_post_event("Mission_VO_Override")
-- Run the mission from the beginning
if current_checkpoint == M01_checkpoint.start.name then
objective_text( 0, "m01_kill_lobby_guards", "", "", SYNC_ALL, OI_ASSET_KILL )
m01_kill_lobby_guards()
zscene_prep(M01_scene.at_vault)
m01_kill_lobby2_guards()
m01_fine_aim_guards()
objective_text_clear(0)
objective_text( 0, "m01_go_to_vault", "", "", SYNC_ALL, OI_ASSET_LOCATION )
m01_go_to_vault()
objective_text_clear(0)
m01_plan_b_scene()
current_checkpoint = M01_checkpoint.plant_bombs.name
mission_set_checkpoint(M01_checkpoint.plant_bombs.name, ignore_vehicles, ignore_notoriety)
end
if current_checkpoint == M01_checkpoint.plant_bombs.name then
zscene_prep(M01_scene.explosives)
m01_set_bomb()
objective_text_clear(0)
m01_detonate_bomb_scene()
current_checkpoint = M01_checkpoint.survive.name
mission_set_checkpoint(M01_checkpoint.survive.name, ignore_vehicles, ignore_notoriety)
end
notoriety_set_min_and_max("Police", 1, 1) -- since we don't see it, just give enough to attack us
if current_checkpoint == M01_checkpoint.survive.name then
-- Hang out a beat until power is cut
m01_cut_power()
zscene_prep(M01_scene.connect_vault)
objective_text( 0, "m01_survive", "", "", SYNC_ALL, OI_ASSET_DEFEND )
-- defend against cops
m01_survive_cops()
objective_text_clear(0)
m01_heli_arrive_scene()
current_checkpoint = M01_checkpoint.ride_vault.name
mission_set_checkpoint(M01_checkpoint.ride_vault.name, ignore_vehicles, ignore_notoriety)
end
if current_checkpoint == M01_checkpoint.ride_vault.name then
zscene_prep(M01_scene.heli_crash)
--objective_text( 0, "m01_ride_vault", "", "", SYNC_ALL, OI_ASSET_INVALID )
objective_text( 0, "m01_survive", "", "", SYNC_ALL, OI_ASSET_DEFEND )
m01_vault_above_cam()
m01_vault_first_guards()
m01_vault_roof_setup()
m01_roof_guards1()
m01_shoot_heli_alt()
m01_building_crash()
m01_heli_crash_other_building()
m01_shoot_even_more()
m01_break_chains()
m01_shoot_most()
m01_finale_scene()
end
-- debug only swap
if current_checkpoint == M01_checkpoint.debug_swaps.name then
-- big delay to start
delay(1.0)
while true do
delay(3.0)
city_zone_swap(M01_zone_damaged_name, true)
delay(3.0)
city_zone_swap(M01_zone_name, false)
delay(0.5)
city_zone_swap(M01_zone_damaged_name, false)
delay(0.5)
city_zone_swap(M01_zone_name, true)
end
end
-- Go directly to customization misson (w/Do_intro_sequence)
mission_set_next_mission("mm_m1_5")
-- we're done
mission_end_success("m01", M01_scene.heli_crash)
end
-- This is the primary function responsible for cleaning up the entire mission
-- CALLED FROM CODE
--
function m01_cleanup()
-- default it up
character_set_damage_multiplier(LOCAL_PLAYER, 1.0)
character_set_damage_multiplier(REMOTE_PLAYER, 1.0)
-- turn spawning back on
m01_do_ambient_spawns(true)
-- stop muting voice
audio_object_post_event("Mission_VO_Override_Stop")
flashlights_enable()
m01_players_stop_vault_health()
-- Stop the camera shake
camera_shake_stop()
m01_clear_hud_states()
-- this should be a light swap
--set_time_of_day(21, 0)
-- Audio emitters
m01_stop_all_emitters()
-- turn off the lights before you go
-- not needed and causes problems on success -- m01_all_lights_off()
-- clear objective
objective_text_clear( 0 )
m01_clear_tutorial(true)
-- clean up the valut sequence
action_sequence_end()
-- cleanup groups
m01_cleanup_first_checkpoint_groups()
m01_cleanup_first_checkpoint_crew()
m01_cleanup_second_checkpoint_groups()
m01_cleanup_second_checkpoint_crew()
m01_cleanup_cop_wave_groups()
m01_cleanup_swat_crew()
m01_cleanup_final_checkpoint_groups()
m01_kill_heli_move_threads()
m01_stop_respawn_pairs()
-- cleanup the threads
cleanup_threads(M01_thread)
-- end any conversations
m01_end_conversations()
-- remove triggers
m01_clear_trigger(M01_trigger.freerun.name)
m01_clear_trigger(M01_trigger.shaundi_attack.name)
m01_clear_trigger(M01_trigger.pre_vault.name)
m01_clear_trigger(M01_trigger.vault.name)
m01_clear_trigger(M01_trigger.pre_bomb.name)
m01_clear_trigger(M01_trigger.pre_bomb2.name)
m01_clear_trigger(M01_trigger.bomb.name)
m01_clear_trigger(M01_trigger.kill.name)
m01_clear_trigger(M01_trigger.swat_kill.name)
m01_clear_trigger(M01_trigger.horse.name)
-- remove temp weapons
m01_clear_player_loadout()
-- re-enable all weapons
inv_weapon_disable_all_slots(false)
-- Don't force me to look at anything
camera_restrict_set_active(DISABLE)
-- camera_end_look_through( SNAP_CAMERA )
-- allow notoriety spawning again
notoriety_set_min_and_max("Police", 0, MAX_NOTORIETY_LEVEL)
notoriety_set_min_and_max("morningstar", 0, MAX_NOTORIETY_LEVEL)
notoriety_force_no_spawn("police", false)
notoriety_force_no_spawn("morningstar", false)
-- allow enter/exit vehicles
action_stop_custom(LOCAL_PLAYER)
clear_animation_state(LOCAL_PLAYER)
set_player_can_enter_exit_vehicles(LOCAL_PLAYER, true)
player_movement_enable(LOCAL_PLAYER)
if coop_is_active() then
action_stop_custom(REMOTE_PLAYER)
clear_animation_state(REMOTE_PLAYER)
set_player_can_enter_exit_vehicles(REMOTE_PLAYER, true)
player_movement_enable(REMOTE_PLAYER)
end
mission_set_cancel_warp_location( M01_end_mission_demo, M01_end_mission_demo )
--[[ DEMO
mission_set_cancel_warp_location( M01_end_mission_nav1, M01_end_mission_nav1 )
]]--
-- turn player back
customization_item_revert( )
customization_restore_player_rig( )
-- done swap
city_zone_swap(M01_zone_name, false)
city_zone_swap(M01_zone_damaged_name, false)
city_zone_swap(M01_zone_stilwater, false)
crib_weapon_add_enable()
end
-- Called when the mission has ended with success
-- CALLED FROM CODE
--
function m01_success()
--[[ INSERT ANY MISSION SPECIFIC SUCCESS STUFF ]]--
-- teleport players to not be in mid-air
local exit_vehicles = true
teleport(LOCAL_PLAYER, M01_end_mission_demo, exit_vehicles)
if (coop_is_active()) then
teleport( REMOTE_PLAYER, M01_end_mission_demo, exit_vehicles)
end
--[[ DEMO
teleport(LOCAL_PLAYER, M01_end_mission_nav1, exit_vehicles)
if (coop_is_active()) then
teleport( REMOTE_PLAYER, M01_end_mission_nav2, exit_vehicles)
end
]]--
-- turn player back
customization_item_revert( )
customization_restore_player_rig( )
end
-- *************************
--
-- Local functions
--
-- *************************
-- Initialize the mission for the specified checkpoint
--
-- checkpoint: Checkpoint to initialize the mission to
--
function m01_initialize(checkpoint)
-- Set the mission author
set_mission_author("Neil Ryan")
-- Common initialization
m01_initialize_common()
-- Checkpoint specific initialization
m01_initialize_checkpoint(checkpoint)
-- any notoriety is fake for this mission
notoriety_force_no_spawn("police", true)
notoriety_force_no_spawn("morningstar", true)
-- set a kill trigger to kill anything that falls
m01_set_trigger(M01_trigger.kill.name, "m01_kill_trigger_cb")
-- Start fading in
mission_start_fade_in()
end
-- Kill the first group of guards
--
function m01_kill_lobby_guards()
M01_gat_finished_shooting = false
M01_player_over_desk = false
-- send in the guards
M01_thread.move_guards = thread_new("m01_enter_guards_thread")
-- everyone else cowers
M01_thread.people_cower = thread_new("m01_group_cower_thread", M01_group.lobby_cower)
-- saints fan blabs
M01_thread.saints_fan = thread_new("m01_get_robbed_line_thread", M01_group.lobby_cower.saints_fan)
M01_thread.josh_ai = thread_new("m01_josh_is_dumbass_thread")
-- make sure peds and guards fight
m01_group_no_flee_or_cower(M01_group.lobby.tellers)
-- action!
clear_animation_state(LOCAL_PLAYER)
-- trigger Gat interrogate
M01_thread.conversation = thread_new("m01_gat_guard_convo_thread")
-- Player look cool, go!
local anim_name = "Mission 1 Start"
local morph_name = "Mission 1 Start"
local force_play = false
local percentage = 1.0
local stand_still = true
local zero_movement = true
action_play(LOCAL_PLAYER, anim_name, morph_name, force_play, percentage, stand_still, zero_movement, M01_checkpoint.start.nav1)
M01_player_over_desk = true
set_ignore_ai_flag( M01_shaundi, false )
hud_display_remove_state(M01_hud_state.hide_everything)
M01_hud_state.hide_everything = -1
-- Josh and Shaundi can start moving
npc_leash_remove(M01_group.start_homies.josh)
npc_leash_remove(M01_group.start_homies.shaundi)
follower_make_independent(M01_group.start_homies.shaundi, true)
-- 1 spotlight heli for fine_aim area
M01_news_location = M01_news.fine_aim
-- kill the guards
process_enemy_set(M01_group.lobby.members)
M01_lobby_cleared = true
M01_thread.fine_aim_glass = thread_new("m01_fine_aim_glass_thread")
delay(2.0)
end
-- Kill the second group of guards
--
function m01_kill_lobby2_guards()
group_create_hidden(M01_group.second_floor.name, true)
local should_run = true
local should_fire = false
ai_do_scripted_move(M01_group.start_homies.shaundi, M01_cover.lobby2.shaundi, should_run, should_fire)
-- keep her out of the way
npc_leash_to_nav( M01_shaundi, M01_cover.lobby2.shaundi, 1.0 )
group_create_hidden(M01_group.lobby3.name, true)
group_create(M01_group.fine_aim.name, true)
m01_setup_see_saints(M01_group.fine_aim.members)
-- when Gat is in position, do the action and open the door
while not M01_josh_grandstanded do
thread_yield()
end
-- move Gat to door
npc_leash_remove(M01_group.start_homies.gat)
set_ignore_ai_flag( M01_group.start_homies.gat, true )
ai_do_scripted_move(M01_group.start_homies.gat, "grandstand_nav", should_run, should_fire)
while not ai_scripted_action_is_complete(M01_group.start_homies.gat) do
thread_yield()
end
group_show(M01_group.lobby3.name)
npc_unholster_best_weapon(M01_group.lobby3.doorman)
local anim_name = "Gat Door Kick Killed"
local morph_name = "Gat Door Kick Killed"
local force_play = false
local percentage = 1.0
local stand_still = true
local zero_movement = true
--gatdoor
local reverse_door = true
local animate_door = true
door_open(LOBBY_DOOR02, reverse_door, animate_door, M01_group.start_homies.gat, "Gat Door Kick", "grandstand_nav")
-- this will force Gat to wait
action_play(M01_group.lobby3.doorman, anim_name, morph_name, force_play, percentage, stand_still, zero_movement)
character_kill(M01_group.lobby3.doorman)
set_ignore_ai_flag( M01_group.start_homies.gat, false )
M01_gat_finished_shooting = true
npc_leash_remove(M01_shaundi)
recall_crew()
-- setup freerun trigger now in case of advanced player
M01_trigger.freerun.hit = false
m01_set_trigger(M01_trigger.freerun.name, "m01_reached_freerun")
-- gotta prep this waaaay early...dammit QA
M01_shaundi_attack.thread = thread_new( "m01_shaundi_attacked_thread" )
-- spawn threads to move guards to their marks
for i, guard in pairs(M01_group.lobby3.members) do
ai_do_scripted_move(guard, LOBBY_MARK2[i])
end
recall_crew()
process_enemy_set(M01_group.lobby3.members)
recall_crew()
if not M01_trigger.freerun.hit then -- if this was already hit, she should be headed upstairs
M01_thread.shaundi_move = thread_new("m01_homie_move_thread", M01_group.start_homies.shaundi, M01_cover.fine_aim.shaundi)
end
M01_thread.gat_move = thread_new("m01_homie_move_thread", M01_group.start_homies.gat, M01_cover.fine_aim.gat)
end
-- Do fine aim tutorial and kill the fine aim group of guards
--
function m01_fine_aim_guards()
-- Start the fine aim tutorial
M01_skip_fineaim_release = false
if M01_TUTORIAL_FINEAIM ~= INVALID_THREAD_HANDLE then
thread_close(M01_TUTORIAL_FINEAIM)
end
M01_TUTORIAL_FINEAIM = thread_new("m01_fineaim_tutorial")
M01_thread.tutorial_timer = thread_new("delay", 2.0)
-- Josh takes off
-- kill Josh's current thread
thread_kill(M01_thread.josh_ai)
clear_animation_state(M01_josh)
set_ignore_ai_flag(M01_josh, false)
thread_yield()
M01_thread.josh_ai = thread_new("m01_josh_run_upstairs")
process_enemy_set(M01_group.fine_aim.members)
recall_crew()
if not M01_trigger.freerun.hit then -- if this was already hit, she should be headed upstairs
M01_thread.shaundi_move = thread_new("m01_homie_move_thread", M01_group.start_homies.shaundi, M01_cover.second_floor.shaundi)
end
M01_thread.gat_move = thread_new("m01_homie_move_thread", M01_group.start_homies.gat, M01_cover.second_floor.gat)
end
-- Reinforcements on the second floor, kill them
--
function m01_second_floor_guards()
notoriety_set_min_and_max("morningstar", 1, 1) -- since we don't see it, just give enough to attack us
-- show all of these guys now so we can't watch them pop in
group_show(M01_group.second_floor.name)
m01_setup_see_saints(M01_group.second_floor.members)
local should_run = true
local should_fire = false
for i, guard in pairs(M01_group.second_floor.members) do
ai_do_scripted_move(guard, SECOND_FLOOR_MARK[i], should_run, should_fire)
end
end
-- Set the vault as the next objective. There's a lot of guards, but not required kills
function m01_go_to_vault()
-- Add the bread crumb to lead to the vault
M01_trigger.pre_vault.hit = false
if not M01_trigger.freerun.hit then
-- tell player where to go
objective_text( 0, "M01_GO_UPSTAIRS", "", "", SYNC_ALL, OI_ASSET_LOCATION )
m01_set_trigger(M01_trigger.pre_vault.name, "m01_reached_vault_breadcrumb")
marker_add_trigger(M01_trigger.pre_vault.name, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
end
while not M01_trigger.freerun.hit do
thread_yield()
end
objective_text( 0, "m01_kill_lobby_guards", "", "", SYNC_ALL, OI_ASSET_KILL )
m01_clear_trigger(M01_trigger.pre_vault.name)
-- set the trigger again without the marker
M01_trigger.pre_vault.hit = false
m01_set_trigger(M01_trigger.pre_vault.name, "m01_reached_vault_breadcrumb")
-- create new homies hidden as we go into cutscene (preload way early so all character resources are loaded for
-- the zscene)
local block = false
group_create_hidden(M01_group.bomb_homies.name, block)
process_enemy_set(M01_group.second_floor.members)
-- if we haven't hit it yet
if not M01_trigger.pre_vault.hit then
-- tell player where to go
objective_text( 0, "M01_GO_UPSTAIRS", "", "", SYNC_ALL, OI_ASSET_LOCATION )
marker_add_trigger(M01_trigger.pre_vault.name, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
end
while not M01_trigger.pre_vault.hit do
thread_yield()
end
recall_crew()
objective_text( 0, "m01_go_to_vault", "", "", SYNC_ALL, OI_ASSET_LOCATION )
M01_trigger.vault.hit = false
m01_set_trigger(M01_trigger.vault.name, "m01_reached_vault")
marker_add_trigger(M01_trigger.vault.name, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
-- wait until you get to the vault
while not M01_trigger.vault.hit do
thread_yield()
end
m01_clear_tutorial()
-- kill conversations
thread_kill(M01_thread.conversation)
M01_thread.conversation = INVALID_THREAD_HANDLE
m01_end_conversations()
-- stop custom Josh ai
thread_kill(M01_thread.josh_ai)
end
-- Gat says it is time for plan B
function m01_plan_b_scene()
thread_kill(M01_thread.fine_aim_glass)
m01_stop_emitters(M01_audio_emitter.fine_aim)
audio_object_post_event("M01_Score_Z01_Start")
local teleport_navs = { M01_checkpoint.plant_bombs.nav1, M01_checkpoint.plant_bombs.nav2 }
cutscene_play(M01_scene.at_vault, nil, teleport_navs)
player_controls_disable(LOCAL_PLAYER) -- don't move while doing the animation thing
--[[
set_animation_state(LOCAL_PLAYER, "M01 Z01 Stand")
local anim_name = "m01 z01 transition"
local morph_name = "m01 z01 transition"
local force_play = false
local percentage = 0.8
local stand_still = true
local zero_movement = true
action_play(LOCAL_PLAYER, anim_name, morph_name, force_play, percentage, stand_still, zero_movement)
clear_animation_state(LOCAL_PLAYER)
]]--
m01_cleanup_first_checkpoint_groups()
-- cleanup old guys
m01_cleanup_first_checkpoint_crew()
-- make sure new homies are spawned
while (not(group_create_check_done(M01_group.bomb_homies.name))) do
thread_yield()
end
group_show(M01_group.bomb_homies)
m01_setup_crew(M01_group.bomb_homies)
-- Horse is broke
mesh_mover_update_control("Horsie", "is statue broken", true)
-- doors need to be opened again (WTF?)
local reverse_door = true
door_open(LOBBY_DOOR01, reverse_door)
door_open(LOBBY_DOOR02, reverse_door)
-- make Shaundi and Josh independent for their conversation
follower_make_independent(M01_josh, true)
follower_make_independent(M01_shaundi, true)
-- wait until the player is done with his animation
delay(2.7)
player_controls_enable(LOCAL_PLAYER)
end
function m01_set_bomb()
-- tell guards to do their thing
M01_thread.elevator = thread_new("m01_elevator_guards_thread")
--group_create(M01_group.bomb_flee)
M01_thread.people_cower = thread_new("m01_group_cower_thread", M01_group.bomb_cower)
M01_group.autograph.thread = thread_new("m01_setup_autograph_thread")
objective_text( 0, "M01_GO_UPSTAIRS", "", "", SYNC_ALL, OI_ASSET_LOCATION )
on_attack_performed(M01_gat_attack_info.callback, M01_gat)
character_prevent_flinching(M01_josh, true)
character_prevent_flinching(M01_shaundi, true)
M01_trigger.pre_bomb.hit = false
m01_set_trigger(M01_trigger.pre_bomb.name, "m01_reached_pre_bomb")
m01_set_trigger(M01_trigger.pre_bomb2.name, "m01_reached_pre_bomb") -- hidden trigger for other staircase
marker_add_trigger(M01_trigger.pre_bomb.name, MINIMAP_ICON_LOCATION, INGAME_EFFECT_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
M01_thread.conversation = thread_new("m01_bomb_convo_thread")
-- allow time for Josh to get to the doorway
delay(1.0)
while not M01_trigger.pre_bomb.hit and ai_scripted_action_is_processing(M01_josh) do
thread_yield()
end
if not M01_trigger.pre_bomb.hit then
M01_thread.josh_ai = thread_new("m01_josh_just_cower_thread")
end
-- wait until you get to the stairs
while not M01_trigger.pre_bomb.hit do
thread_yield()
end
-- stop custom Josh ai
--thread_kill(M01_thread.josh_ai)
-- give Josh time to get upstairs
delay(5.0)
-- Shaundi can stop force-firing at guy
npc_leash_remove(M01_shaundi)
ai_clear_scripted_action(M01_shaundi)
npc_leash_remove(M01_gat)
--follower_make_independent(M01_josh, false)
follower_make_independent(M01_shaundi, false)
follower_make_independent(M01_gat, false)
objective_text( 0, "m01_set_explosives", "", "", SYNC_ALL, OI_ASSET_USE )
-- target the bomb area
M01_trigger.bomb.hit = false
M01_setting_bomb = false
m01_set_trigger(M01_trigger.bomb.name, "m01_reached_bomb")
marker_add_trigger(M01_trigger.bomb.name, MINIMAP_ICON_USE, INGAME_EFFECT_CHECKPOINT, OI_ASSET_USE, OI_FLAGS_LOCATION, SYNC_ALL)
delay(1.0)
-- wait until you get to the bomb
while not M01_trigger.bomb.hit do
thread_yield()
end
thread_kill(M01_thread.elevator)
-- kill conversations
thread_kill(M01_thread.conversation)
M01_thread.conversation = INVALID_THREAD_HANDLE
m01_end_conversations()
thread_kill(M01_thread.josh_ai)
end
-- Set off bomb and trigger the alarm
function m01_detonate_bomb_scene()
group_create_hidden(M01_group.swat_homies.name, true)
--bink_play(M01_scene.explosives)
local teleport_navs = { M01_checkpoint.survive.nav1, M01_checkpoint.survive.nav2 }
local fade_in_after = true
m01_stop_emitters(M01_audio_emitter.office)
cutscene_play(M01_scene.explosives, nil, teleport_navs, fade_in_after)
-- swap to damaged version of bank
city_zone_swap(M01_zone_name, false)
city_zone_swap(M01_zone_damaged_name, true)
M01_thread.reset_movers = thread_new("m01_reset_movers_thread")
audio_object_post_event("M01_Office_Heli_Mute")
m01_start_emitters(M01_audio_emitter.city_noise)
audio_object_post_event("M01_Score_SWAT")
m01_cleanup_second_checkpoint_groups()
m01_cleanup_second_checkpoint_crew()
-- spawn new homies
M01_thread.homies_prep = thread_new("m01_homies_prep_thread")
-- make sure everyone can move (may be turned off due to autograph sign)
player_movement_enable(LOCAL_PLAYER)
if coop_is_active() then
player_movement_enable(REMOTE_PLAYER)
end
end
function m01_cut_power()
-- alarm lights are on
m01_alarm_lights(true)
m01_setup_ropes()
m01_start_swat_respawn_pairs()
-- no weapons so we can do tutorial
inv_item_equip(nil, LOCAL_PLAYER) -- Unequip the current weapon on the player
if coop_is_active() then
inv_item_equip(nil, REMOTE_PLAYER) -- Unequip the current weapon on the player
end
if M01_TUTORIAL_SWITCH_WEAPON ~= INVALID_THREAD_HANDLE then
thread_kill(M01_TUTORIAL_SWITCH_WEAPON)
end
M01_TUTORIAL_SWITCH_WEAPON = thread_new("m01_change_weapons_tutorial")
-- kill any cops that fall below your floor
m01_set_trigger(M01_trigger.swat_kill.name, "m01_kill_trigger_cb")
delay(2.0)
M01_convo.swat_on_way.handle = audio_conversation_load(M01_convo.swat_on_way.name)
audio_conversation_play(M01_convo.swat_on_way.handle)
on_attack_performed(M01_gat_attack_info.callback, M01_gat)
delay(4.0)
-- cut the power -- not anymore
--local lights_on = false
--m01_set_lights_on(lights_on)
M01_news_location = M01_news.swat
--M01_group.news_heli1.news_thread = thread_new("m01_news_heli_thread", M01_group.news_heli1)
--M01_group.news_heli2.news_thread = thread_new("m01_news_heli_thread", M01_group.news_heli2)
end
-- defend against the waves of cops
function m01_survive_cops()
-- spawn and float attack chopper
group_create(M01_group.heli_fighter1.name, true)
vehicle_enter_group_teleport(M01_group.heli_fighter1.members, M01_group.heli_fighter1.vehicle)
-- don't take explosion damage
vehicle_set_explosion_damage_multiplier(M01_group.heli_fighter1.vehicle, 0.0)
vehicle_prevent_explosion_fling(M01_group.heli_fighter1.vehicle, true)
vehicle_suppress_npc_exit(M01_group.heli_fighter1.vehicle, true)
m01_float_heli(M01_group.heli_fighter1, M01_group.heli_fighter1.flyby_float)
npc_combat_enable(M01_group.heli_fighter1.members[1], false)
npc_combat_enable(M01_group.heli_fighter1.members[2], false)
-- set hard limit on how much damage can be taken
local total_hitpoints = get_max_hit_points(M01_group.heli_fighter1.vehicle)
set_min_hit_points(M01_group.heli_fighter1.vehicle, total_hitpoints * M01_group.heli_fighter1.damage2)
--M01_convo.set_explosives.handle = audio_conversation_load(M01_convo.set_explosives.name)
M01_convo.attack_chopper.handle = audio_conversation_load(M01_convo.attack_chopper.name)
-- attack wall diagram
-- Respawn pairs go here (pair 1 = p1)
-- Riot guys use pair 1's positions
--------------------------------------------------------
-- | p5 || p5 | | p4 || p4 || | <---Uppper floor
-----------------------------------------------
-- | p1 || p1 | | p2 || p2 p3 || p3 | <---Lower floor
-----------------------------------------------
-- Spawn in first set
M01_throw_flashbangs = true
-- two guys up front
M01_group.swat2_pair.active = true
M01_group.swat3_pair.active = true
-- give them a second to spawn
delay(1.0)
-- turn them off
M01_group.swat2_pair.active = false
M01_group.swat3_pair.active = false
delay(1.0)
audio_conversation_wait_for_end(M01_convo.swat_on_way.handle)
M01_convo.swat_on_way.handle = INVALID_CONVERSATION_HANDLE
set_ignore_ai_flag( M01_gat, false )
set_ignore_ai_flag( M01_shaundi, false )
delay(3.0)
-- "Here they come" "Cover me"
--audio_conversation_play(M01_convo.set_explosives.handle)
--thread_yield()
--audio_conversation_wait_for_end(M01_convo.set_explosives.handle)
--M01_convo.set_explosives.handle = INVALID_CONVERSATION_HANDLE
-- just say "Here they come"
audio_play_persona_line(M01_gat, "M01_Set_Explosives_02")
M01_thread.line_timer = thread_new("delay", 3.0) -- emergency timer in case line fails
thread_yield()
while audio_persona_line_playing(M01_gat) and (not thread_check_done(M01_thread.line_timer)) do
thread_yield()
end
delay(0.5)
-- Flashbang callout!
audio_play_persona_line(M01_shaundi, "M01_Flashbang_Callout")
delay(1.0)
-- just blow up the player
explosion_create("Flashbang", LOCAL_PLAYER, M01_group.swat2_pair.members[1], false)
-- and the remote player
if (coop_is_active() == true) then
explosion_create("Flashbang", REMOTE_PLAYER, M01_group.swat2_pair.members[1], false)
end
clear_animation_state(M01_shaundi)
clear_animation_state(M01_gat)
delay(10.0) -- give some time for player to figure out what is going on and kill some guys
M01_throw_flashbangs = false
-- start spawn group 2 and 3
M01_group.swat2_pair.active = true
M01_group.swat3_pair.active = true
-- shoot for a little bit
delay(10.0)
-- add some upstairs action
M01_group.swat4_pair.active = true
-- Shanundi bitching
M01_convo.swat_chit_chat.handle = audio_conversation_load(M01_convo.swat_chit_chat.name)
audio_conversation_play(M01_convo.swat_chit_chat.handle)
audio_conversation_wait_for_end(M01_convo.swat_chit_chat.handle)
M01_convo.swat_chit_chat.handle = INVALID_CONVERSATION_HANDLE
delay(10.0)
audio_object_post_event("M01_Office_Heli_Closer")
-- more guys
M01_group.swat1_pair.active = true
-- less on right
M01_group.swat3_pair.active = false
delay(5.0)
-- move upstairs spawns
--M01_group.swat5_pair.active = true
--M01_group.swat4_pair.active = false
delay(10.0)
M01_group.swat2_pair.active = false
-- two riot sheild guys
M01_group.swat_riot_pair.active = true
delay(2.0)
M01_group.swat_riot_pair.active = false
-- Gat says almost done
audio_play_persona_line(M01_group.swat_homies.gat, "M01_Wait_For_Helicopter")
M01_thread.line_timer = thread_new("delay", 3.0) -- emergency timer in case line fails
thread_yield()
while audio_persona_line_playing(M01_gat) and (not thread_check_done(M01_thread.line_timer)) do
thread_yield()
end
audio_play_persona_line(M01_shaundi, "M01_Calling_Out_Riot_Shields")
delay(10.0)
-- turn off continuous spawn
M01_group.swat1_pair.active = false
M01_group.swat2_pair.active = false
M01_group.swat3_pair.active = false
M01_group.swat4_pair.active = false
M01_group.swat5_pair.active = false
-- wait until most are killed
while M01_pairs_spawned > 2 do
thread_yield()
end
-- send guys trhough the front windows again
M01_group.swat1_pair.active = true
delay(1.0)
M01_group.swat1_pair.active = false
-- let the chopper come in
-- send heli in
audio_object_post_event("M01_Office_Heli_PassBy", nil, nil, M01_group.heli_fighter1.vehicle)
M01_group.heli_fighter1.thread = thread_new("m01_fly_direct_thread", M01_group.heli_fighter1.vehicle, M01_group.heli_fighter1.flyby_path, 30.0)
M01_group.heli_fighter1.permission_to_fire = false
M01_group.heli_fighter1.gunner_thread = thread_new("m01_attack_heli_building_battle_thread", M01_group.heli_fighter1)
delay(6.0)
-- notice attack heli
audio_conversation_play(M01_convo.attack_chopper.handle)
audio_conversation_wait_for_end(M01_convo.attack_chopper.handle)
M01_convo.attack_chopper.handle = INVALID_CONVERSATION_HANDLE
-- require XX% damage on heli
M01_group.heli_fighter1.damaged = false
turn_vulnerable(M01_group.heli_fighter1.vehicle)
marker_add(M01_group.heli_fighter1.vehicle, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL)
objective_text( 0, "M01_KILL_CHOPPER", "", "", SYNC_ALL, OI_ASSET_KILL )
on_damage("m01_attack_heli_damaged_cb", M01_group.heli_fighter1.vehicle, M01_group.heli_fighter1.damage1)
delay(1.0)
M01_group.heli_fighter1.permission_to_fire = true
delay(2.0)
audio_play_persona_line(M01_shaundi, "M01_Helicopter")
-- wait for heli damage
while not M01_group.heli_fighter1.damaged do
thread_yield()
end
-- start a thread to get the vault created
--M01_thread.vault_setup = thread_new("m01_vault_setup_part1_thread")
thread_kill(M01_group.heli_fighter1.gunner_thread)
marker_remove(M01_group.heli_fighter1.vehicle)
objective_text( 0, "m01_survive", "", "", SYNC_ALL, OI_ASSET_DEFEND )
M01_group.heli_fighter1.permission_to_fire = false
npc_combat_enable(M01_group.heli_fighter1.members[1], false)
npc_combat_enable(M01_group.heli_fighter1.members[2], false)
thread_kill(M01_group.heli_fighter1.thread)
M01_group.heli_fighter1.thread = thread_new("m01_fly_direct_thread", M01_group.heli_fighter1.vehicle, "heli_police2_home", 30.0)
audio_object_post_event("M01_Score_Z03_Transition")
delay(1.7)
audio_play_persona_line(M01_shaundi, "M01_Chopper_Arrives")
delay(1.0)
m01_stop_swat_respawn_pairs()
m01_clear_tutorial()
m01_clear_trigger(M01_trigger.swat_kill.name)
end
-- Helicopter arrives to take vault away
function m01_heli_arrive_scene()
-- make sure any conversations are over
m01_end_conversations()
local teleport_navs = { M01_checkpoint.ride_vault.nav1, M01_checkpoint.ride_vault.nav2 }
local fade_in_after = false
cutscene_play(M01_scene.connect_vault, nil, teleport_navs, fade_in_after)
m01_vault_setup_part1_thread( )
-- get on the vault
m01_vault_setup_part2_thread()
fade_in(0.5)
-- cleanup groups
m01_cleanup_cop_wave_groups()
m01_cleanup_swat_crew()
end
-- Show helicopter coming out of m01, pan down to player
function m01_vault_above_cam()
audio_object_post_event("M01_Vault_Foley")
-- start thread to spawn everything else
M01_thread.vault_environ_setup = thread_new("m01_vault_environ_setup_thread")
-- back to more normal restrictions (infinite down look)
camera_restrict_set_limits( M01_MIN_PITCH, 90, M01_MIN_HEADING, M01_MAX_HEADING )
end
-- Kill guards hanging out on the fifth floor
function m01_vault_first_guards()
-- and now the news!
M01_news_location = M01_news.vault
M01_group.news_heli1.news_thread = thread_new("m01_news_heli_thread", M01_group.news_heli1)
M01_group.news_heli2.news_thread = thread_new("m01_news_heli_thread", M01_group.news_heli2)
audio_object_post_event("M01_Vault_Liftoff")
delay(2.0)
M01_convo.hooked_up.start = true
delay(4.1)
end
-- move guards to the roof and show them setting up
function m01_vault_roof_setup()
M01_group.roof1_pair.active = true
M01_group.roof2_pair.active = true
M01_group.roof3_pair.active = true
ai_set_action_delay(M01_group.heli_fighter1.members[1], "throw grenade", 99999)
ai_set_action_delay(M01_group.heli_fighter1.members[2], "throw grenade", 99999)
-- no more shooting
npc_combat_enable(M01_group.heli_fighter1.members[1], false)
npc_combat_enable(M01_group.heli_fighter1.members[2], false)
-- start moving
camera_shake_play("explosion_large", 4.0)
-- switch to new animation
m01_play_next_vault_animations(M01_DO_NOT_WAIT, M01_INTERRUPT)
-- do a slow, looping camera shake while on the vault
camera_shake_play_looping(M01_vault_camera_shake)
delay(2.0)
M01_convo.heli_rising.start = true
delay(6.0)
m01_heli_move_to(POLICE_HELI_WAIT_LOCATION1, M01_group.heli_police1)
m01_path_complete_thread()
M01_news_location = M01_news.loop
-- vulnerable up to a point
turn_vulnerable(M01_group.heli_fighter1.vehicle)
M01_group.heli_fighter1.damaged = false
on_damage("m01_attack_heli_damaged_cb", M01_group.heli_fighter1.vehicle, M01_group.heli_fighter1.damage2)
-- It's a fighter!
delay(0.7)
-- It's a moving fighter!
thread_kill(M01_group.heli_fighter1.thread)
M01_group.heli_fighter1.attack_run_thread = thread_new("m01_fighter_attack_run_thread", M01_group.heli_fighter1, M01_group.heli_fighter1.run1)
delay(3.0)
audio_play_persona_line(LOCAL_PLAYER, "M01_Same_Attack_Chopper_01")
-- remove Gat, Shaundi and SWAT because they can pop out if we look down at them
if group_is_loaded(M01_group.vault_attackers2.name) then
group_destroy(M01_group.vault_attackers2.name)
end
while not M01_fighter_run_complete do
thread_yield()
end
m01_players_set_vault_health(M01_player_health.shot1)
camera_restrict_set_active(DISABLE)
m01_play_next_vault_animations(M01_DO_NOT_WAIT, M01_INTERRUPT)
thread_yield() -- wait for camera to change
camera_restrict_set_limits( M01_MIN_PITCH, M01_MAX_PITCH, M01_MIN_HEADING, M01_MAX_HEADING )
camera_restrict_target_object(CAMERA_TARGET3)
camera_restrict_set_active(ENABLE)
M01_convo.heli_jerk_back.start = true
--delay(1.0)
m01_transport_show(M01_group.transport1, true)
-- hack in other line (you won't get to hear transport1's line during dropoff)
persona_override_persona_start(M01_group.transport2.pilots[1], "Interrogation")
-- choppa!
delay(1.0)
M01_group.transport2.setup_thread = thread_new("m01_transport_flyby_thread", M01_group.transport2)
delay(2.0)
M01_group.transport3.setup_thread = thread_new("m01_transport_flyby_thread", M01_group.transport3)
-- wait until moving is done
m01_path_complete_thread()
end
-- Kill guards on roof, end with chopper
function m01_roof_guards1()
delay(1.5)
audio_play_persona_line(M01_group.transport2.pilots[1], "M01_Bullhorn_Heli_Drop_01")
-- send heli across the screen
-- teleport first so he is hopefully facing the correct direction
m01_float_heli(M01_group.heli_police1, POLICE_HELI_WAIT_LOCATION1)
thread_yield()
m01_heli_move_to(POLICE_HELI_WAIT_LOCATION2, M01_group.heli_police1)
-- kill chopper
Helicopter_killed = false
m01_heli_move_to(POLICE_HELI_SHOOT_AT_ME1, M01_group.heli_police2)
turn_vulnerable( M01_group.heli_police2.vehicle )
persona_override_persona_start(M01_group.heli_police2.members[1], M01_group.heli_police2.pilot_persona)
on_damage("m01_crash_heli", M01_group.heli_police2.vehicle, M01_HELI_DAMAGE)
ai_add_enemy_target(M01_group.heli_police2.shooter, LOCAL_PLAYER, ATTACK_NOW_NEVER_LOSE, true)
-- prep the fighter
m01_float_heli(M01_group.heli_fighter1, M01_group.heli_fighter1.hover_nav2)
m01_do_transport(M01_group.transport1)
delay(3.0)
audio_play_persona_line(M01_group.heli_police2.members[1], M01_group.heli_police2.persona_line)
delay(2.0)
M01_convo.heli_not_leaving.start = true
persona_override_persona_stop(M01_group.transport2.pilots[1])
-- make sure transport is out of the way
while not M01_group.transport1.complete do
thread_yield()
end
delay(1.0)
-- move heli back
-- teleport first so he is hopefully facing the correct direction
m01_float_heli(M01_group.heli_police1, POLICE_HELI_WAIT_LOCATION2)
thread_yield()
m01_heli_move_to(POLICE_HELI_WAIT_LOCATION1, M01_group.heli_police1)
end
-- shoot down another heli getting real close to you
function m01_shoot_heli_alt()
M01_group.heli_fighter1.attack_run_thread = thread_new("m01_fighter_attack_run_thread", M01_group.heli_fighter1, M01_group.heli_fighter1.run2)
delay(3.0)
persona_override_persona_stop(M01_group.heli_police2.members[1])
-- Are you still alive? Get out of here
if vehicle_exists(M01_group.heli_police2.vehicle) and not vehicle_is_destroyed(M01_group.heli_police2.vehicle) then
m01_heli_move_to(M01_group.heli_police2.home_nav, M01_group.heli_police2)
on_damage("", M01_group.heli_police2.vehicle, 0.99)
end
while not M01_fighter_run_complete do
thread_yield()
end
-- back over here
m01_heli_move_to(POLICE_HELI_WAIT_LOCATION2, M01_group.heli_police1)
camera_restrict_target_object(CAMERA_TARGET3)
end
-- Player's heli is shot again. Crash through roof
function m01_building_crash()
-- transition to the next area
M01_convo.heli_drag_vault.start = true
m01_players_set_vault_health(M01_player_health.shot2)
m01_play_next_vault_animations(M01_DO_NOT_WAIT, M01_DO_NOT_INTERRUPT)
-- put this guy in place for "surprise"
m01_float_heli(M01_group.heli_police1, POLICE_HELI_SURPRISE_NAV1)
delay(2.0)
-- don't wait for this group. If the spawn fails, the game is stuck. Not going to crash for these guys
group_create(M01_group.roof2.name, false)
-- delete first transport corpse completely
vehicle_delete_all_corpses()
delay(8.0)
-- now finish coming back around
thread_kill(M01_group.heli_fighter1.thread)
M01_group.heli_fighter1.thread = thread_new("m01_fly_direct_thread", M01_group.heli_fighter1.vehicle, M01_group.heli_fighter1.attack_path2_part2, 40.0)
-- wait until the animation is done
m01_path_complete_thread()
delay(3.0)
marker_add(M01_group.heli_fighter1.vehicle, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL)
if not M01_group.heli_fighter1.damaged then
turn_vulnerable(M01_group.heli_fighter1.vehicle)
end
objective_text( 0, "M01_KILL_CHOPPER", "", "", SYNC_ALL, OI_ASSET_KILL )
delay(4.0)
M01_thread.line_timer = thread_new("m01_same_chopper2_thread") -- threaded because this could go poorly
--[[ delay(4.9)
-- do some blasting
npc_combat_enable(M01_group.heli_fighter1.members[1], true)
npc_combat_enable(M01_group.heli_fighter1.members[2], true)
-- shoot here
m01_heli_shoot_gun_at_nav(M01_group.heli_fighter1.vehicle, "hang_on_target", 1.5)
npc_combat_enable(M01_group.heli_fighter1.members[1], false)
npc_combat_enable(M01_group.heli_fighter1.members[2], false)
]]--
end
function m01_heli_crash_other_building()
--[[ while get_dist(M01_group.heli_fighter1.vehicle, M01_group.heli_fighter1.attack_nav2) > 30.0 do
thread_yield()
end]]--
-- when you are close, shoot the player's heli
while get_dist(M01_group.heli_fighter1.vehicle, M01_group.heli_fighter1.attack_nav2) > 20.0 do
thread_yield()
end
m01_fighter_shoot_vault(0.6)
thread_yield()
marker_remove(M01_group.heli_fighter1.vehicle)
objective_text( 0, "m01_survive", "", "", SYNC_ALL, OI_ASSET_DEFEND )
m01_players_set_vault_health(M01_player_health.shot3)
m01_play_next_vault_animations(M01_DO_NOT_WAIT, M01_DO_NOT_INTERRUPT)
camera_restrict_set_active(DISABLE)
M01_convo.heli_near_collision.start = true
delay(3.0)
-- send in another transport
m01_do_transport(M01_group.transport2)
-- wait until the animation is done
m01_path_complete_thread()
-- target your current view
camera_restrict_target_object()
camera_restrict_set_limits( 0.0, 0.0, 0.0, 0.0)
-- lock it
camera_restrict_set_active(ENABLE)
thread_yield()
-- follow the chopper
camera_restrict_target_object(CAMERA_TARGET3, 500)
camera_restrict_set_limits( M01_MIN_PITCH, M01_MAX_PITCH, M01_MIN_HEADING, M01_MAX_HEADING )
-- we should be done with these lines
thread_kill(M01_thread.line_timer)
end
-- Oh Shit!
function m01_shoot_even_more()
-- a lot of guys on the way on transports, so chill the spawns a bit
M01_group.roof2_pair.active = false
M01_group.roof3_pair.active = false
-- and another
delay(4.0)
m01_do_transport(M01_group.transport3)
thread_kill(M01_group.heli_fighter1.thread)
delay(3.0)
end
function m01_break_chains()
-- Play creaking noise before cables break
delay(5.0)
-- big explosion!!
camera_shake_play("explosion_large", 4.0)
m01_players_set_vault_health(M01_player_health.break_chains)
m01_play_next_vault_animations(M01_WAIT, M01_DO_NOT_INTERRUPT)
M01_convo.vault_tipped.start = true
-- change "seats"
end
function m01_shoot_most()
delay(1.0)
M01_group.heli_fighter1.thread = thread_new("m01_fly_direct_thread", M01_group.heli_fighter1.vehicle, M01_group.heli_fighter1.attack_path3, 30.0)
-- another sniper
Helicopter_killed = false
persona_override_persona_start(M01_group.heli_police1.members[1], M01_group.heli_police1.pilot_persona)
m01_heli_move_to("sniper_heli_nav<002>", M01_group.heli_police1)
turn_vulnerable( M01_group.heli_police1.vehicle )
on_damage("m01_crash_heli", M01_group.heli_police1.vehicle, M01_HELI_DAMAGE)
ai_add_enemy_target(M01_group.heli_police1.shooter, LOCAL_PLAYER, ATTACK_NOW_NEVER_LOSE, true)
delay(1.0)
delay(5.0)
audio_play_persona_line(M01_group.heli_police1.members[1], M01_group.heli_police1.persona_line)
M01_group.heli_fighter1.damaged = false
turn_vulnerable(M01_group.heli_fighter1.vehicle)
marker_add(M01_group.heli_fighter1.vehicle, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL)
objective_text( 0, "M01_KILL_CHOPPER", "", "", SYNC_ALL, OI_ASSET_KILL )
on_damage("m01_attack_heli_damaged_cb", M01_group.heli_fighter1.vehicle, M01_group.heli_fighter1.damage3)
-- allow more damage
local total_hitpoints = get_max_hit_points(M01_group.heli_fighter1.vehicle)
set_min_hit_points(M01_group.heli_fighter1.vehicle, (total_hitpoints * M01_group.heli_fighter1.damage3) - 10)
M01_group.heli_fighter1.gunner_thread = thread_new("m01_attack_heli_gunner_thread", M01_group.heli_fighter1)
M01_group.heli_fighter1.permission_to_fire = true
delay(4.0)
-- pilot is losing it
audio_play_persona_line(M01_group.vault_heli.pilot, "M01_Helicopter_Going_Down_01")
delay(4.0)
audio_play_persona_line(M01_group.heli_fighter1.members[1], "M01_Bullhorn_Cables_Break")
-- wait for heli damage
while not M01_group.heli_fighter1.damaged do
thread_yield()
end
marker_remove(M01_group.heli_fighter1.vehicle)
objective_text( 0, "m01_survive", "", "", SYNC_ALL, OI_ASSET_DEFEND )
M01_group.heli_fighter1.permission_to_fire = false
npc_combat_enable(M01_group.heli_fighter1.members[1], false)
npc_combat_enable(M01_group.heli_fighter1.members[2], false)
-- That's enough damage
turn_invulnerable(M01_group.heli_fighter1.vehicle)
-- light it up
vehicle_set_smoke_and_fire_state(M01_group.heli_fighter1.vehicle, true, false)
-- do a little dance
local anim_state = ""
local anim_action = "heli trans21"
audio_object_post_event("M01_Score_Z04_Transition")
vehicle_anim_start(M01_group.heli_fighter1.vehicle, anim_state, anim_action)
audio_play_persona_line(LOCAL_PLAYER, "M01_Shot_Down_Attack_Chopper")
delay(0.5)
while not vehicle_anim_finished(M01_group.heli_fighter1.vehicle, 0.9) do
thread_yield()
end
end
-- mission finale
function m01_finale_scene()
-- Stop the camera shake
camera_shake_stop()
-- stop threads that may cause problems with the cutscene
thread_kill(M01_group.heli_police1.setup_thread)
thread_kill(M01_group.heli_police1.thread)
thread_kill(M01_group.heli_police2.setup_thread)
thread_kill(M01_group.heli_police2.thread)
thread_kill(M01_group.heli_fighter1.thread)
thread_kill(M01_group.heli_fighter1.gunner_thread)
thread_kill(M01_group.transport1.drop_off_thread)
thread_kill(M01_group.transport1.setup_thread)
thread_kill(M01_group.transport1.thread)
thread_kill(M01_group.transport2.drop_off_thread)
thread_kill(M01_group.transport2.setup_thread)
thread_kill(M01_group.transport2.thread)
thread_kill(M01_group.transport3.drop_off_thread)
thread_kill(M01_group.transport3.setup_thread)
thread_kill(M01_group.transport3.thread)
thread_kill(M01_group.news_heli1.news_thread)
thread_kill(M01_group.news_heli1.thread)
thread_kill(M01_group.news_heli2.news_thread)
thread_kill(M01_group.news_heli2.thread)
audio_object_post_event("M01_Heli_Heist_Stop")
end
-- ***************************************************
-- m01_run Helper Functions
-- ***************************************************
-- ***************************************************
-- m01_initialize Helper Functions
-- ***************************************************
-- Turn on or off the spawning systems to speed things up
--
-- enable_spawn: (bool) true to enable the spawns, false to disable the spawns
--
function m01_do_ambient_spawns(enable_spawn)
spawning_boats(enable_spawn)
spawning_pedestrians(enable_spawn)
spawning_vehicles(enable_spawn)
end
-- setup all of our hud states
--
function m01_setup_hud_states()
M01_hud_state.hide_minimap = hud_display_create_state()
hud_display_set_element(M01_hud_state.hide_minimap, HUD_ELEM_MINIMAP, HUD_FADE_HIDDEN)
-- hide minimap for the whole mission
hud_display_commit_state(M01_hud_state.hide_minimap)
end
-- clear out all of the hud states
function m01_clear_hud_states()
for i, hud_state in pairs(M01_hud_state) do
if (hud_state ~= -1) then
hud_display_remove_state(hud_state)
hud_state = -1
end
end
end
-- Handle any common initialization
--
function m01_initialize_common()
--[[ INSERT ANY COMMON INITIALIZATION CODE HERE ]]--
flashlights_disable()
m01_set_player_loadout()
M01_window_entry_melee_id = melee_get_move_id_from_name("Window Entry")
team_make_allies("Police", "Morningstar")
m01_setup_hud_states()
-- Make it easy because Greg isn't that good
character_set_damage_multiplier(LOCAL_PLAYER, 0.44)
character_set_damage_multiplier(REMOTE_PLAYER, 0.44)
end
-- do swap stuff right away
--
-- checkpoint: The checkpoint to be initialized
function m01_initialize_swaps(checkpoint)
city_zone_swap(M01_zone_stilwater, true)
if (checkpoint == M01_checkpoint.start.name) then
city_zone_swap(M01_zone_damaged_name, false)
city_zone_swap(M01_zone_name, true)
end
if (checkpoint == M01_checkpoint.plant_bombs.name) then
-- swap!
city_zone_swap(M01_zone_name, true)
end
if (checkpoint == M01_checkpoint.survive.name) then
-- swap to damaged version of bank
city_zone_swap(M01_zone_damaged_name, true)
end
if (checkpoint == M01_checkpoint.ride_vault.name) then
-- swap to damaged version of bank
city_zone_swap(M01_zone_damaged_name, true)
end
if (checkpoint == M01_checkpoint.debug_swaps.name) then
-- swap to damaged version of bank
city_zone_swap(M01_zone_name, true)
end
end
-- Checkpoint specific initialization
--
-- checkpoint: The checkpoint to be initialized
function m01_initialize_checkpoint(checkpoint)
local lights_on = true
local alarm_lights = false
local animate_door = false
door_close(M01_ELEVATOR_DOOR, animate_door)
local locked = true
door_lock(M01_ELEVATOR_DOOR, locked)
if (checkpoint == M01_checkpoint.start.name) then
m01_start_emitters(M01_audio_emitter.office)
m01_start_emitters(M01_audio_emitter.bank_lobby)
-- no hud until after animation
M01_hud_state.hide_everything = hud_display_create_state()
hud_display_set_element(M01_hud_state.hide_everything, HUD_ALL_ELEM, HUD_FADE_HIDDEN)
hud_display_commit_state(M01_hud_state.hide_everything)
-- start by spawning everyone without blocking
local block = true
mesh_mover_reset("Horsie")
mesh_mover_update_control("Horsie", "is statue broken", false)
-- spawn guards and tellers
group_create(M01_group.lobby.name, block)
-- spawn my crew
group_create(M01_group.start_homies.name, block)
-- make sure Gat is ready before starting (or we error on animations)
while not character_is_ready(M01_group.start_homies.gat) do
thread_yield()
end
M01_thread.gat_hostage = thread_new("m01_take_hostage", M01_group.start_homies.gat, M01_group.start_homies.captive)
-- setup my crew
m01_setup_crew(M01_group.start_homies)
npc_leash_to_nav( M01_group.start_homies.gat, M01_group.start_homies.captive_nav, 0.0 )
npc_leash_to_nav( M01_group.start_homies.captive, M01_group.start_homies.captive_nav, FLOOR_LEASH_RADIUS_METERS )
character_allow_ragdoll(M01_group.start_homies.gat, false)
character_allow_ragdoll(M01_group.start_homies.captive, false)
character_prevent_flinching(M01_group.start_homies.captive, true)
character_prevent_flinching(M01_group.start_homies.gat, true)
--character_take_human_shield(M01_group.start_homies.gat, M01_group.start_homies.captive)
npc_leash_to_nav( M01_shaundi, "Shaundi_start_leash", 1.0 )
set_animation_state(LOCAL_PLAYER, "Mission 1 Start State")
persona_override_persona_start(M01_group.start_homies.captive, "Interrogation")
-- start with some pissed off guards
notoriety_set_min_and_max("Police", 1, 1) -- since we don't see it, just give enough to attack us
notoriety_set_min_and_max("morningstar", 1, 1) -- since we don't see it, just give enough to attack us
thread_yield()
else
local reverse_door = true
door_open(LOBBY_DOOR01, reverse_door)
door_open(LOBBY_DOOR02, reverse_door)
end
if (checkpoint == M01_checkpoint.plant_bombs.name) then
m01_start_emitters(M01_audio_emitter.office)
-- teleport players
teleport_coop(M01_checkpoint.plant_bombs.nav1, M01_checkpoint.plant_bombs.nav2, true)
-- Horse is broke
mesh_mover_update_control("Horsie", "is statue broken", true)
audio_object_post_event("M01_Checkpoint_Plant")
--set_animation_state(LOCAL_PLAYER, "M01 Z01 Stand")
-- spawn new homies
group_create(M01_group.bomb_homies.name, true)
m01_setup_crew(M01_group.bomb_homies)
-- make Shaundi and Josh independent for their conversation
follower_make_independent(M01_josh, true)
follower_make_independent(M01_shaundi, true)
notoriety_set_min_and_max("Police", 1, 1) -- since we don't see it, just give enough to attack us
notoriety_set_min_and_max("morningstar", 1, 1) -- since we don't see it, just give enough to attack us
end
if (checkpoint == M01_checkpoint.survive.name) then
-- teleport players
teleport_coop(M01_checkpoint.survive.nav1, M01_checkpoint.survive.nav2, true)
-- spawn new homies
group_create_hidden(M01_group.swat_homies.name, true)
M01_thread.homies_prep = thread_new("m01_homies_prep_thread")
audio_object_post_event("M01_Office_Heli_Mute")
m01_start_emitters(M01_audio_emitter.city_noise)
audio_object_post_event("M01_Checkpoint_Survive")
M01_thread.reset_movers = thread_new("m01_reset_movers_thread")
alarm_lights = true
notoriety_set_min_and_max("Police", 1, 1) -- since we don't see it, just give enough to attack us
notoriety_set_min_and_max("morningstar", 1, 1) -- since we don't see it, just give enough to attack us
end
if (checkpoint == M01_checkpoint.ride_vault.name) then
-- teleport players
teleport_coop(M01_checkpoint.ride_vault.nav1, M01_checkpoint.ride_vault.nav2, true)
m01_start_emitters(M01_audio_emitter.city_noise)
m01_start_emitters(M01_audio_emitter.vault_noise)
audio_object_post_event("M01_Checkpoint_Ride_Vault")
M01_thread.reset_movers = thread_new("m01_reset_movers_thread")
-- run setup parts sequentially
m01_vault_setup_part1_thread()
m01_vault_setup_part2_thread()
-- only checkpoint to start with the lights off
lights_on = false
alarm_lights = true
notoriety_set_min_and_max("Police", 1, 1) -- since we don't see it, just give enough to attack us
notoriety_set_min_and_max("morningstar", 1, 1) -- since we don't see it, just give enough to attack us
end
if (checkpoint == M01_checkpoint.debug_swaps.name) then
-- teleport players
teleport_coop(M01_checkpoint.debug_swaps.nav1, M01_checkpoint.debug_swaps.nav2, true)
end
m01_setup_light_group(M01_light_group.alarm)
m01_alarm_lights(alarm_lights)
end
-- setup script light groups
--
-- light_group_table: (table) info about light group
--
function m01_setup_light_group(light_group_table)
if light_group_table.name ~= "" then
light_group_set_intensity(light_group_table.name, light_group_table.intensity)
end
end
-- Turn the lights on or off
--
-- lights_on: (bool) true to turn lights on, false to turn lights off
--
function m01_set_lights_on(lights_on)
-- This looks a bit confusing
-- The scripted intensity is 0.0. Using this intenstiy esentially turns off that light.
-- If the lights are on, 'light' set has normal intensity and 'dark' set has 0 intensity
local set_intensity_to_0 = false --not lights_on
if M01_light_group.light.name ~= "" then
light_group_use_intensity(M01_light_group.light.name, set_intensity_to_0)
end
end
-- Turn on or off the alarm lights
--
-- turn_on: (bool) true to turn alarm lights on, false to turn them off
function m01_alarm_lights(turn_on)
local set_intensity_to_0 = not turn_on
if M01_light_group.alarm.name ~= "" then
light_group_use_intensity(M01_light_group.alarm.name, set_intensity_to_0)
end
end
-- turn off all of the script intensity before you leave
function m01_all_lights_off()
local lights_on = false
for i,light in pairs(M01_light_group) do
if light.name ~= "" then
light_group_use_intensity(light.name, lights_on)
end
end
end
-- setup followers as necessary
function m01_setup_crew( homie_table )
party_add( homie_table.gat, LOCAL_PLAYER )
on_death("m01_failure_gat_died", homie_table.gat)
turn_invulnerable(homie_table.gat)
M01_gat = homie_table.gat
if homie_table.gat_bobble then
character_add_prop(homie_table.gat, "bobblehead_gat")
character_add_prop(homie_table.gat, "voice_modulator_gat")
end
-- in coop, remote gets Shaundi
if coop_is_active() then
party_add( homie_table.shaundi, REMOTE_PLAYER )
else
party_add( homie_table.shaundi, LOCAL_PLAYER )
end
on_death("m01_failure_shaundi_died", homie_table.shaundi)
turn_invulnerable(homie_table.shaundi)
if homie_table.shaundi_bobble then
character_add_prop(homie_table.shaundi, "bobblehead_shaundi")
character_add_prop(homie_table.shaundi, "voice_modulator_shaundi")
end
M01_shaundi = homie_table.shaundi
-- Josh might have left
if homie_table.josh ~= "" then
party_add( homie_table.josh, LOCAL_PLAYER )
turn_invulnerable(homie_table.josh)
on_death("m01_failure_josh_died", homie_table.josh)
inv_item_dual_wield(homie_table.josh, WEAPON_SLOT_PISTOL)
if homie_table.josh_bobble then
character_add_prop(homie_table.josh, "bobblehead_josh")
character_add_prop(homie_table.josh, "voice_modulator_josh")
end
character_add_prop(homie_table.josh, "Josh_DuffelBag")
-- Josh is no combat EVAR!
npc_combat_enable(homie_table.josh, false)
end
M01_josh = homie_table.josh
end
-- clear followers as necessary
function m01_clear_crew( homie_table )
on_death("", homie_table.gat)
on_attack_performed("", homie_table.gat)
on_death("", homie_table.shaundi)
-- Josh might have left
if homie_table.josh ~= "" then
on_death("", homie_table.josh)
end
end
-- teleport followers to a set of navpoints
function m01_teleport_crew( homie_table, navs )
teleport(homie_table.gat, navs[1])
teleport(homie_table.shaundi, navs[2])
if homie_table.josh ~= "" then
teleport(homie_table.josh, navs[3])
end
end
-- set crew to ignore ai (to say lines)
function m01_dumb_crew( homie_table )
set_ignore_ai_flag( homie_table.gat, true )
set_ignore_ai_flag( homie_table.shaundi, true )
if homie_table.josh ~= "" then
set_ignore_ai_flag( homie_table.josh, true )
end
end
-- recall crew back to your side
function recall_crew()
-- only care about Gat and Shaundi. Josh does his own thing
thread_kill(M01_thread.shaundi_move)
follower_make_independent(M01_shaundi, false)
ai_clear_scripted_action(M01_shaundi)
ai_clear_priority_target(M01_shaundi)
ai_set_personality(M01_shaundi, "gang normal")
ai_set_in_scripted_cover(M01_shaundi, false)
npc_leash_remove(M01_shaundi)
thread_kill(M01_thread.gat_move)
follower_make_independent(M01_gat, false)
ai_clear_scripted_action(M01_gat)
ai_clear_priority_target(M01_gat)
ai_set_personality(M01_gat, "gang normal")
ai_set_in_scripted_cover(M01_gat, false)
npc_leash_remove(M01_gat)
thread_yield()
end
-- ***************************************************
-- Miscellaneous m01 Helper Funcrtions
-- ***************************************************
function m01_set_player_loadout()
-- Clear out what you have. You only get what we give you
inv_item_remove_all(LOCAL_PLAYER)
local magazines = 1
local unlimited = true
local equip_now = false
local dual_wield = false
local force_override = false
inv_weapon_add_temporary(LOCAL_PLAYER, M01_PLAYER_PISTOL, magazines, unlimited, equip_now, dual_wield, force_override, M01_PLAYER_PISTOL_UPGRADES)
inv_weapon_add_temporary(LOCAL_PLAYER, M01_PLAYER_SHOTGUN, magazines, unlimited, equip_now, dual_wield, force_override, M01_PLAYER_SHOTGUN_UPGRADES)
inv_weapon_add_temporary(LOCAL_PLAYER, M01_PLAYER_RIFLE, magazines, unlimited, true, dual_wield, force_override, M01_PLAYER_RIFLE_UPGRADES)
inv_weapon_add_temporary(LOCAL_PLAYER, M01_PLAYER_SMG, magazines, unlimited, equip_now, dual_wield, force_override)
--inv_weapon_add_temporary(LOCAL_PLAYER, M01_PLAYER_GRENADE, magazines, false, equip_now, dual_wield)
if coop_is_active() then
inv_item_remove_all(REMOTE_PLAYER)
inv_weapon_add_temporary(REMOTE_PLAYER, M01_PLAYER_PISTOL, magazines, unlimited, equip_now, dual_wield, force_override, M01_PLAYER_PISTOL_UPGRADES)
inv_weapon_add_temporary(REMOTE_PLAYER, M01_PLAYER_SHOTGUN, magazines, unlimited, equip_now, dual_wield, force_override, M01_PLAYER_SHOTGUN_UPGRADES)
inv_weapon_add_temporary(REMOTE_PLAYER, M01_PLAYER_RIFLE, magazines, unlimited, true, dual_wield, force_override, M01_PLAYER_RIFLE_UPGRADES)
inv_weapon_add_temporary(REMOTE_PLAYER, M01_PLAYER_SMG, magazines, unlimited, equip_now, dual_wield, force_override)
--inv_weapon_add_temporary(REMOTE_PLAYER, M01_PLAYER_GRENADE, magazines, false, equip_now, dual_wield)
end
end
-- remove all of the player's temp weapons
function m01_clear_player_loadout()
inv_weapon_remove_temporary(LOCAL_PLAYER, M01_PLAYER_PISTOL)
inv_weapon_remove_temporary(LOCAL_PLAYER, M01_PLAYER_SHOTGUN)
inv_weapon_remove_temporary(LOCAL_PLAYER, M01_PLAYER_RIFLE)
inv_weapon_remove_temporary(LOCAL_PLAYER, M01_PLAYER_SMG)
--inv_weapon_remove_temporary(LOCAL_PLAYER, M01_PLAYER_GRENADE)
if coop_is_active() then
inv_weapon_remove_temporary(REMOTE_PLAYER, M01_PLAYER_PISTOL)
inv_weapon_remove_temporary(REMOTE_PLAYER, M01_PLAYER_SHOTGUN)
inv_weapon_remove_temporary(REMOTE_PLAYER, M01_PLAYER_RIFLE)
inv_weapon_remove_temporary(REMOTE_PLAYER, M01_PLAYER_SMG)
--inv_weapon_remove_temporary(REMOTE_PLAYER, M01_PLAYER_GRENADE)
end
end
-- set a group to not flee or cower (used so peds act like cops)
--
-- group_table: (table) information about the group
function m01_group_no_flee_or_cower(group_table)
for i,npc in pairs(group_table) do
set_cant_cower_flag(npc, true)
set_cant_flee_flag(npc, true)
set_behavior_set(npc, "Civilian Rifle")
set_team(npc, "Police")
ai_add_enemy_target(npc, LOCAL_PLAYER, ATTACK_NOW_NEVER_LOSE)
if coop_is_active() then
ai_add_enemy_target(npc, LOCAL_PLAYER, ATTACK_NOW_NEVER_LOSE)
end
end
end
function m01_clear_tutorial(force_kill)
if tutorial_queued("combat_fineaim") then
-- Tutorial is waiting to be played. Just remove it.
tutorial_stop("combat_fineaim")
elseif tutorial_active("combat_fineaim") then
-- Let the tutorial play out if possible (not waiting for a trigger)
if tutorial_get_case("combat_fineaim") == 0 or force_kill then
tutorial_stop("combat_fineaim")
end
end
if M01_TUTORIAL_FINEAIM ~= INVALID_THREAD_HANDLE then
thread_kill(M01_TUTORIAL_FINEAIM)
M01_TUTORIAL_FINEAIM = INVALID_THREAD_HANDLE
end
if tutorial_queued("combat_weapons") then
tutorial_stop("combat_weapons")
elseif tutorial_active("combat_weapons") then
-- Let the tutorial play out if possible (not waiting for a trigger)
if tutorial_get_case("combat_weapons") == 0 or force_kill then
tutorial_stop("combat_weapons")
end
end
if M01_TUTORIAL_SWITCH_WEAPON ~= INVALID_THREAD_HANDLE then
thread_kill(M01_TUTORIAL_SWITCH_WEAPON)
M01_TUTORIAL_SWITCH_WEAPON = INVALID_THREAD_HANDLE
end
on_weapon_equip("", LOCAL_PLAYER)
end
-- End all conversations
function m01_end_conversations()
for i,convo in pairs(M01_convo) do
if convo.handle ~= INVALID_CONVERSATION_HANDLE then
audio_conversation_end(convo.handle)
convo.handle = INVALID_CONVERSATION_HANDLE
end
end
end
function m01_cleanup_first_checkpoint_groups()
thread_kill(M01_shaundi_attack.thread)
if group_is_loaded(M01_group.lobby.name) then
group_destroy(M01_group.lobby.name)
end
if group_is_loaded(M01_group.lobby_cower.name) then
persona_override_persona_stop(M01_group.lobby_cower.saints_fan)
group_destroy(M01_group.lobby_cower.name)
end
if group_is_loaded(M01_group.lobby2.name) then
group_destroy(M01_group.lobby2.name)
end
if group_is_loaded(M01_group.lobby3.name) then
group_destroy(M01_group.lobby3.name)
end
if group_is_loaded(M01_group.fine_aim.name) then
m01_clear_see_saints(M01_group.fine_aim.members)
group_destroy(M01_group.fine_aim.name)
end
if group_is_loaded(M01_group.second_floor.name) then
m01_clear_see_saints(M01_group.second_floor.members)
group_destroy(M01_group.second_floor.name)
end
if group_is_loaded(M01_group.third_floor.name) then
group_destroy(M01_group.third_floor.name)
end
if group_is_loaded(M01_group.news_heli2.name) then
thread_kill(M01_group.news_heli2.news_thread)
thread_kill(M01_group.news_heli2.thread)
group_destroy(M01_group.news_heli2.name)
end
end
function m01_cleanup_first_checkpoint_crew()
if group_is_loaded(M01_group.start_homies.name) then
persona_override_persona_stop(M01_group.start_homies.captive)
m01_clear_crew(M01_group.start_homies)
group_destroy(M01_group.start_homies.name)
end
end
function m01_cleanup_second_checkpoint_groups()
if group_is_loaded(M01_group.bomb_security2.name) then
m01_clear_see_saints(M01_group.bomb_security2.members)
group_destroy(M01_group.bomb_security2.name)
end
if group_is_loaded(M01_group.bomb_cower.name) then
group_destroy(M01_group.bomb_cower.name)
end
if group_is_loaded(M01_group.bomb_flee.name) then
group_destroy(M01_group.bomb_flee.name)
end
if group_is_loaded(M01_group.autograph.name) then
if (M01_group.autograph.effect_handle ~= -1) then
effect_stop(M01_group.autograph.effect_handle)
M01_group.autograph.effect_handle = -1
end
m01_clear_trigger(M01_group.autograph.trigger)
thread_kill(M01_group.autograph.thread)
on_death("", M01_group.autograph.guy)
on_take_damage("", M01_group.autograph.guy)
group_destroy(M01_group.autograph.name)
end
end
function m01_cleanup_second_checkpoint_crew()
if group_is_loaded(M01_group.bomb_homies.name) then
m01_clear_crew(M01_group.bomb_homies)
group_destroy(M01_group.bomb_homies.name)
end
end
function m01_cleanup_cop_wave_groups()
if group_is_loaded(M01_group.rope.name) then
group_destroy(M01_group.rope.name)
end
if group_is_loaded(M01_group.swat1_pair.name) then
on_attack_performed("", M01_group.swat1_pair.members[1])
on_attack_performed("", M01_group.swat1_pair.members[2])
group_destroy(M01_group.swat1_pair.name)
end
if group_is_loaded(M01_group.swat2_pair.name) then
on_attack_performed("", M01_group.swat2_pair.members[1])
on_attack_performed("", M01_group.swat2_pair.members[2])
group_destroy(M01_group.swat2_pair.name)
end
if group_is_loaded(M01_group.swat3_pair.name) then
on_attack_performed("", M01_group.swat3_pair.members[1])
on_attack_performed("", M01_group.swat3_pair.members[2])
group_destroy(M01_group.swat3_pair.name)
end
if group_is_loaded(M01_group.swat4_pair.name) then
on_attack_performed("", M01_group.swat4_pair.members[1])
on_attack_performed("", M01_group.swat4_pair.members[2])
group_destroy(M01_group.swat4_pair.name)
end
if group_is_loaded(M01_group.swat5_pair.name) then
on_attack_performed("", M01_group.swat5_pair.members[1])
on_attack_performed("", M01_group.swat5_pair.members[2])
group_destroy(M01_group.swat5_pair.name)
end
if group_is_loaded(M01_group.swat_riot_pair.name) then
on_attack_performed("", M01_group.swat_riot_pair.members[1])
on_attack_performed("", M01_group.swat_riot_pair.members[2])
group_destroy(M01_group.swat_riot_pair.name)
end
if group_is_loaded(M01_group.news_heli1.name) then
thread_kill(M01_group.news_heli1.news_thread)
thread_kill(M01_group.news_heli1.thread)
group_destroy(M01_group.news_heli1.name)
end
if group_is_loaded(M01_group.news_heli2.name) then
thread_kill(M01_group.news_heli2.news_thread)
thread_kill(M01_group.news_heli2.thread)
group_destroy(M01_group.news_heli2.name)
end
end
function m01_cleanup_swat_crew()
if group_is_loaded(M01_group.swat_homies.name) then
m01_clear_crew(M01_group.swat_homies)
group_destroy(M01_group.swat_homies.name)
end
end
function m01_cleanup_final_checkpoint_groups()
if group_is_loaded(M01_group.vault_heli.name) then
persona_override_persona_stop(M01_group.vault_heli.pilot)
group_destroy(M01_group.vault_heli.name)
end
if group_is_loaded(M01_group.vault_attackers2.name) then
group_destroy(M01_group.vault_attackers2.name)
end
if group_is_loaded(M01_group.roof2.name) then
group_destroy(M01_group.roof2.name)
end
if group_is_loaded(M01_HELI_SHOOTER_GROUP) then
group_destroy(M01_HELI_SHOOTER_GROUP)
end
if group_is_loaded(M01_group.heli_police1.name) then
persona_override_persona_stop(M01_group.heli_police1.members[1])
on_damage("", M01_group.heli_police1.vehicle, 0.99)
thread_kill(M01_group.heli_police1.setup_thread)
thread_kill(M01_group.heli_police1.thread)
group_destroy(M01_group.heli_police1.name)
end
if group_is_loaded(M01_group.heli_police2.name) then
persona_override_persona_stop(M01_group.heli_police2.members[1])
on_damage("", M01_group.heli_police2.vehicle, 0.99)
thread_kill(M01_group.heli_police2.setup_thread)
thread_kill(M01_group.heli_police2.thread)
group_destroy(M01_group.heli_police2.name)
end
if group_is_loaded(M01_group.heli_fighter1.name) then
persona_override_persona_stop(M01_group.heli_fighter1.members[1])
on_damage("", M01_group.heli_fighter1.vehicle, 0.99)
thread_kill(M01_group.heli_fighter1.thread)
thread_kill(M01_group.heli_fighter1.gunner_thread)
group_destroy(M01_group.heli_fighter1.name)
end
if group_is_loaded(M01_group.roof1_pair.name) then
group_destroy(M01_group.roof1_pair.name)
end
if group_is_loaded(M01_group.roof2_pair.name) then
group_destroy(M01_group.roof2_pair.name)
end
if group_is_loaded(M01_group.roof3_pair.name) then
group_destroy(M01_group.roof3_pair.name)
end
if group_is_loaded(M01_group.roof4_pair.name) then
group_destroy(M01_group.roof4_pair.name)
end
if group_is_loaded(M01_group.roof5_pair.name) then
group_destroy(M01_group.roof5_pair.name)
end
if group_is_loaded(M01_group.transport1.name) then
persona_override_persona_stop(M01_group.transport1.pilots[1])
thread_kill(M01_group.transport1.drop_off_thread)
thread_kill(M01_group.transport1.setup_thread)
thread_kill(M01_group.transport1.thread)
on_vehicle_destroyed("", M01_group.transport1.vehicle)
group_destroy(M01_group.transport1.name)
end
if group_is_loaded(M01_group.transport2.name) then
persona_override_persona_stop(M01_group.transport2.pilots[1])
thread_kill(M01_group.transport2.drop_off_thread)
thread_kill(M01_group.transport2.setup_thread)
thread_kill(M01_group.transport2.thread)
on_vehicle_destroyed("", M01_group.transport2.vehicle)
group_destroy(M01_group.transport2.name)
end
if group_is_loaded(M01_group.transport3.name) then
persona_override_persona_stop(M01_group.transport3.pilots[1])
thread_kill(M01_group.transport3.drop_off_thread)
thread_kill(M01_group.transport3.setup_thread)
thread_kill(M01_group.transport3.thread)
on_vehicle_destroyed("", M01_group.transport3.vehicle)
group_destroy(M01_group.transport3.name)
end
if group_is_loaded(M01_group.news_heli1.name) then
thread_kill(M01_group.news_heli1.news_thread)
thread_kill(M01_group.news_heli1.thread)
group_destroy(M01_group.news_heli1.name)
end
if group_is_loaded(M01_group.news_heli2.name) then
thread_kill(M01_group.news_heli2.news_thread)
thread_kill(M01_group.news_heli2.thread)
group_destroy(M01_group.news_heli2.name)
end
end
-- Set a trigger enabled with a mission marker
--
-- trigger: (string) Name of the trigger
-- trigger_callback: (string) Function name to call when trigger is activated
--
function m01_set_trigger(trigger, trigger_callback)
trigger_enable(trigger, true)
-- marker_add_trigger(trigger, MINIMAP_ICON_LOCATION, INGAME_EFFECT_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
on_trigger(trigger_callback, trigger)
end
-- Disable trigger
--
-- trigger: (string) Name of the trigger
--
function m01_clear_trigger(trigger)
on_trigger("", trigger)
trigger_enable(trigger, false)
marker_remove_trigger(trigger, SYNC_ALL)
mission_waypoint_remove()
end
-- Move police heli to a navpoint
--
-- go_here: (string) navpoint name to move to
-- heli_group: (table) heli group table
--
function m01_heli_move_to(go_here, heli_group)
-- kill this thread if currently active (we gotta go somewhere else)
thread_kill(heli_group.thread)
heli_group.thread = thread_new("m01_fly_direct_thread", heli_group.vehicle, go_here, 45.0)
end
-- Teleport and float a heli at a navpoint
--
-- heli_table: (table) helicopter table info
-- float_nav: (string) name of navpoint to float at
function m01_float_heli(heli_table, float_nav)
-- teleport heli into position
teleport_vehicle(heli_table.vehicle, float_nav)
-- wait for that
thread_yield()
-- tell choppers to move there so they stay in place
m01_heli_move_to(float_nav, heli_table)
end
-- tell the attack heli to fire at the vault
--
-- hit_delay: (float) time to wait for missiles to "hit"
function m01_fighter_shoot_vault(hit_delay)
npc_combat_enable(M01_group.heli_fighter1.members[1], true)
npc_combat_enable(M01_group.heli_fighter1.members[2], true)
while not helicopter_shoot_human(M01_group.heli_fighter1.vehicle, M01_group.vault_heli.pilot, false) do
thread_yield()
end
-- no more shooting
npc_combat_enable(M01_group.heli_fighter1.members[1], false)
npc_combat_enable(M01_group.heli_fighter1.members[2], false)
-- wait for missiles to hit
delay(hit_delay)
-- explosions
camera_shake_play("explosion_large", 4.0)
end
-- Do the drop-off sequence
--
-- transport_table: (table) transportatiion information
--
function m01_do_transport(transport_table)
-- make sure we aren't doing something else
thread_kill(transport_table.thread)
transport_table.drop_off_thread = thread_new("m01_transport_drop_off_thread", transport_table)
end
-- setup health on the players so we control how much damage he takes
function m01_players_start_vault_health()
-- beef them up
local max_hp = get_max_hit_points(LOCAL_PLAYER)
set_current_hit_points(LOCAL_PLAYER, max_hp)
if coop_is_active() then
set_current_hit_points(REMOTE_PLAYER, max_hp)
end
-- only I will kill you
turn_invulnerable(LOCAL_PLAYER)
if coop_is_active() then
turn_invulnerable(REMOTE_PLAYER)
end
-- Only I will give you life
character_dont_regenerate(LOCAL_PLAYER, true)
if coop_is_active() then
character_dont_regenerate(REMOTE_PLAYER, true)
end
end
-- ok, back to normal, nothing to see here
function m01_players_stop_vault_health()
-- die freely
turn_vulnerable(LOCAL_PLAYER)
if coop_is_active() then
turn_vulnerable(REMOTE_PLAYER)
end
-- Regen again
character_dont_regenerate(LOCAL_PLAYER, false)
if coop_is_active() then
character_dont_regenerate(REMOTE_PLAYER, false)
end
end
-- set player's health
--
-- health_pct: (float) percentage of health for players to go to
function m01_players_set_vault_health(health_pct)
local max_hp = get_max_hit_points(LOCAL_PLAYER)
local new_hp = max_hp * health_pct
set_current_hit_points(LOCAL_PLAYER, new_hp)
if coop_is_active() then
set_current_hit_points(REMOTE_PLAYER, new_hp)
end
end
-- unleash and move to navpoint
function m01_swat_backup(guard_table, nav_table)
for i, guard in pairs(guard_table) do
npc_leash_remove( guard )
ai_do_scripted_move(guard, nav_table[i])
end
end
-- every half-second check to see if someone in the group is still alive
function m01_delay_or_dead(wait_time, group_table)
local time_elapsed = 0.0
delay(0.5)
time_elapsed = time_elapsed + 0.5
while (time_elapsed < wait_time) do
local alive = false
for i, enemy in pairs(group_table) do
if(not alive) and (not character_is_dead(enemy)) then
alive = true
end
end
if not alive then
-- if everyone is dead, exit early
time_elapsed = wait_time
else
delay(0.5)
time_elapsed = time_elapsed + 0.5
end
end
end
-- Play the next vault animations
-- Handle all animations while on the vault including
-- vault vehicle animations
-- vfx
-- player animations
-- player animation state changes
--
-- wait: (bool) true to wait for the vehicle actions to complete
-- interrupt: (bool) true to possibly interrupt a playing animation
function m01_play_next_vault_animations(wait, interrupt)
action_sequence_advance(interrupt)
if wait then
repeat
thread_yield()
until not action_sequence_is_playing()
end
end
-- start up the swat respawn pairs threads
function m01_start_swat_respawn_pairs()
M01_pairs_spawned = 0
M01_group.swat1_pair.thread = thread_new("m01_respawn_pair_thread", M01_group.swat1_pair)
M01_group.swat2_pair.thread = thread_new("m01_respawn_pair_thread", M01_group.swat2_pair)
M01_group.swat3_pair.thread = thread_new("m01_respawn_pair_thread", M01_group.swat3_pair)
M01_group.swat4_pair.thread = thread_new("m01_respawn_pair_thread", M01_group.swat4_pair)
M01_group.swat5_pair.thread = thread_new("m01_respawn_pair_thread", M01_group.swat5_pair)
M01_group.swat_riot_pair.thread = thread_new("m01_respawn_pair_thread", M01_group.swat_riot_pair)
end
-- shut down the swat respawn pairs threads
function m01_stop_swat_respawn_pairs()
thread_kill(M01_group.swat1_pair.thread)
thread_kill(M01_group.swat2_pair.thread)
thread_kill(M01_group.swat3_pair.thread)
thread_kill(M01_group.swat_riot_pair.thread)
thread_kill(M01_group.swat4_pair.thread)
thread_kill(M01_group.swat5_pair.thread)
M01_pairs_spawned = 0
end
-- start up the respawn pairs threads
function m01_start_respawn_pairs()
M01_pairs_spawned = 0
M01_group.roof1_pair.thread = thread_new("m01_respawn_pair_thread", M01_group.roof1_pair)
M01_group.roof2_pair.thread = thread_new("m01_respawn_pair_thread", M01_group.roof2_pair)
M01_group.roof3_pair.thread = thread_new("m01_respawn_pair_thread", M01_group.roof3_pair)
M01_group.roof4_pair.thread = thread_new("m01_respawn_pair_thread", M01_group.roof4_pair)
M01_group.roof5_pair.thread = thread_new("m01_respawn_pair_thread", M01_group.roof5_pair)
end
-- shut down the respawn pairs threads
function m01_stop_respawn_pairs()
thread_kill(M01_group.roof1_pair.thread)
thread_kill(M01_group.roof2_pair.thread)
thread_kill(M01_group.roof3_pair.thread)
thread_kill(M01_group.roof4_pair.thread)
thread_kill(M01_group.roof5_pair.thread)
M01_pairs_spawned = 0
end
-- setup ropes for action
function m01_setup_ropes()
group_create(M01_group.rope.name, true)
local action = ""
local high_priority = false
local state = "Rope Up"
for i,rope in pairs(M01_group.rope.members) do
item_anim_play(rope.name, action, high_priority, state)
rope.is_down = false
end
end
-- put rope into lowered position or return if already lowered
--
-- rope_index: (int) number of rope to lower
function m01_lower_rope(rope_index)
local rope = M01_group.rope.members[rope_index]
if not rope.is_down then
local action = "Rope Drop"
local high_priority = false
local state = "Rope Down"
item_anim_play(rope.name, action, high_priority, state)
rope.is_down = true
delay(4.0)
end
end
-- play rope entry animation (hopefully matching the repelling human)
--
-- rope_index: (int) number of rope to play anim
function m01_rope_entry(rope_index)
local action = "Window Entry"
local high_priority = true -- use high priority to override the drop animation if necessary
item_anim_play(M01_group.rope.members[rope_index].name, action, high_priority)
end
-- do the swat repelling animation
--
-- npc_name: (string) name of npc to do repelling
-- navpoint: (string) name of navpoint to enter from
-- rope_index: (int) number of rope repelling from
--
function m01_swat_entry(npc_name, navpoint, rope_index)
-- grab the global value as it may change before we use it
local throw_flashbangs = M01_throw_flashbangs
local action = "Window Entry"
local anim_name = action
local morph_name = action
local force_play = true
local percentage = 0.9
local stand_still = true
local zero_movement = true
ai_add_enemy_target(npc_name, LOCAL_PLAYER, ATTACK_NOW, false)
-- turn AI off while we do the action
set_ignore_ai_flag( npc_name, true )
human_gravity_enable( npc_name, false )
character_prevent_flinching(npc_name, true)
-- he needs his weapon equipped to get the animation
while not inv_item_is_firearm_equipped(npc_name) and not character_is_dead(npc_name) do
npc_unholster_best_weapon(npc_name)
delay(0.4)
end
m01_lower_rope(rope_index)
-- make sure he starts exactly on the navpoint
teleport(npc_name, navpoint)
-- tell npc to play action at navpoint (sliding into place as necessary)
if not character_is_dead(npc_name) then
m01_rope_entry(rope_index)
action_play(npc_name, anim_name, morph_name, force_play, percentage, stand_still, zero_movement, navpoint)
end
-- turn AI back on
set_ignore_ai_flag( npc_name, false )
human_gravity_enable( npc_name, true )
character_prevent_flinching(npc_name, false)
character_set_combat_ready( npc_name, true, 3000 )
-- setup attack lines
on_attack_performed("m01_swat_attack_line_cb", npc_name)
--if throw_flashbangs then
-- force_throw_char(npc_name, LOCAL_PLAYER)
--end
end
-- tell the heli to shoot gun at a navpoint for a given amout of time
--
-- heli_name: (string) name of heli to shoot
-- nav_name: (string) name of navpoint to shoot at
-- seconds: (float) time to shoot at navpoint
--
function m01_heli_shoot_gun_at_nav(heli_name, nav_name, seconds)
M01_thread.battle_timer = thread_new("delay", seconds)
local alt_fire = false
while (not thread_check_done(M01_thread.battle_timer)) do
helicopter_shoot_navpoint(heli_name, nav_name, alt_fire)
thread_yield()
end
end
-- tell the heli to shoot gun at a human for a given amout of time
--
-- heli_name: (string) name of heli to shoot
-- human_name: (string) name of human to shoot at
-- seconds: (float) time to shoot at human
--
function m01_heli_shoot_gun_at_human(heli_name, human_name, seconds)
M01_thread.battle_timer = thread_new("delay", seconds)
local alt_fire = false
local unit_sphere = true
local multiplier = 1.0
while (not thread_check_done(M01_thread.battle_timer)) do
helicopter_shoot_human(heli_name, human_name, unit_sphere, multiplier, alt_fire)
thread_yield()
end
end
-- Break the horsie
--
function m01_break_horsie()
-- clear trigger
m01_clear_trigger(M01_trigger.horse.name)
M01_trigger.horse.hit = true
-- kill the dude
character_prevent_flinching(M01_group.start_homies.captive, false)
turn_vulnerable(M01_group.start_homies.captive)
character_kill(M01_group.start_homies.captive)
action_stop_synced_state(M01_group.start_homies.captive)
-- update, launch guard into statue and blow it up
mesh_mover_update_control("Horsie", "is statue broken", true)
-- play the sound
audio_object_post_event("Mission_01", "Mission_01", "Statue_Fall", "Horsie")
local explode_source = false
explosion_create("M1_StatueExp", "horsie_nav", M01_group.start_homies.gat, explode_source)
effect_play("Vfx Horse Fall<001>")
delay(3.6)
-- set off an explosion
camera_shake_play("explosion_large", 4.0)
end
-- setup the (Morningstar) see saints line callbacks
--
-- members: (table) list of group members to setup callback on
--
function m01_setup_see_saints(members)
for i,thug in pairs(members) do
on_detection("m01_morningstar_see_saints_line_cb", thug)
end
end
-- clear the (Morningstar) see saints line callbacks
--
-- members: (table) list of group members to setup callback on
--
function m01_clear_see_saints(members)
for i,thug in pairs(members) do
on_detection("", thug)
end
end
-- *************************
--
-- Audio functions
--
-- *************************
-- start emitters in a group
--
-- emitter_group: (table) list of emitter names to start
--
function m01_start_emitters(emitter_group)
for i,emitter in pairs(emitter_group) do
audio_ambient_emitter_start(emitter)
end
end
-- stop emitters in a group
--
-- emitter_group: (table) list of emitter names to stop
--
function m01_stop_emitters(emitter_group)
for i,emitter in pairs(emitter_group) do
audio_ambient_emitter_stop(emitter)
end
end
-- stop all mission emitters
function m01_stop_all_emitters()
for i,emitter_group in pairs(M01_audio_emitter) do
m01_stop_emitters(emitter_group)
end
end
-- *************************
--
-- Callback functions
--
-- *************************
-- do the horse stuff
function m01_trigger_horse_cb(human, trigger)
-- not our guy, we don't care
if human == M01_group.start_homies.captive then
-- break horsie clears trigger in case of emergency
-- do the horsie
m01_break_horsie()
end
end
-- Player has reached the freerun trigger
function m01_reached_freerun()
M01_trigger.freerun.hit = true
m01_clear_trigger(M01_trigger.freerun.name)
m01_second_floor_guards()
end
-- Player reached trigger to make shaundi get attacked
function m01_attack_shaundi_cb()
-- if Shaundi isn't ready, don't try to do the animation
if not M01_shaundi_attack.in_place then
-- kill the thread
thread_kill(M01_shaundi_attack.thread)
-- make attacker and shaundi not dumb
set_ignore_ai_flag(M01_shaundi, false)
set_ignore_ai_flag(M01_shaundi_attack.attacker, false)
end
M01_trigger.shaundi_attack.hit = true
m01_clear_trigger(M01_trigger.shaundi_attack.name)
end
-- Player has reached the vault breadcrumb
function m01_reached_vault_breadcrumb()
M01_trigger.pre_vault.hit = true
m01_clear_trigger(M01_trigger.pre_vault.name)
end
-- Player has reached the vault trigger
function m01_reached_vault()
M01_trigger.vault.hit = true
m01_clear_trigger(M01_trigger.vault.name)
end
-- Player has reached the pre bomb trigger
function m01_reached_pre_bomb()
M01_trigger.pre_bomb.hit = true
m01_clear_trigger(M01_trigger.pre_bomb.name)
m01_clear_trigger(M01_trigger.pre_bomb2.name)
-- peds flee
--local should_run = true
--local should_fire = false
--for i, flee_ped in pairs(M01_group.bomb_flee.members) do
-- -- if ignore AI isn't set, they just run all over the place
-- set_ignore_ai_flag(flee_ped, false)
-- ai_do_scripted_move(flee_ped, M01_group.bomb_flee.dest, should_run, should_fire)
--end
-- tell Josh to go to his autograph navpoint
thread_kill(M01_thread.josh_ai)
M01_thread.josh_ai = thread_new("m01_josh_to_autograph")
end
-- Player signs an autograph for his fan
--
-- triggerer: (string) name of person that fired the trigger
--
function m01_sign_autograph_cb(triggerer)
if M01_doing_autograph then
-- one per customer, thank you
return
end
M01_doing_autograph = true
-- kill startup thread
thread_kill(M01_group.autograph.thread)
-- clear trigger
m01_clear_trigger(M01_group.autograph.trigger)
-- end effect
if (M01_group.autograph.effect_handle ~= -1) then
effect_stop(M01_group.autograph.effect_handle)
M01_group.autograph.effect_handle = -1
end
-- Don't fuck with autograph guy (girl)
turn_invulnerable( M01_group.autograph.guy )
character_allow_ragdoll(M01_group.autograph.guy, false)
character_prevent_flinching(M01_group.autograph.guy, true)
-- kill any running conversations
m01_end_conversations()
-- make sure they are done playing
while audio_any_conversation_playing() do
thread_yield()
end
if M01_setting_bomb then
return
end
M01_convo.more_guys.handle = audio_conversation_load_direct(M01_convo.more_guys.name)
-- load and play autograph conversation
M01_convo.sign_autograph.handle = audio_conversation_load(M01_convo.sign_autograph.name)
audio_conversation_play(M01_convo.sign_autograph.handle)
thread_kill(M01_thread.josh_ai)
M01_thread.josh_ai = thread_new("m01_josh_to_autograph2")
-- sign stuff
player_movement_disable(triggerer)
action_play_synced_non_blocking(triggerer, M01_group.autograph.guy, "AutoGraph Sign")
repeat
-- watch for that crazy coop player screwing things up
if M01_setting_bomb then
return
end
thread_yield()
until action_play_synced_is_finished(triggerer, M01_group.autograph.guy)
player_movement_enable(triggerer)
if M01_setting_bomb then
return
end
delay(3.0)
if M01_setting_bomb then
return
end
local anim_name = "react Avoid Person"
local morph_name = "react Avoid Person"
local force_play = false
local percentage = 0.1
local stand_still = true
local zero_movement = true
action_play(M01_group.autograph.guy, anim_name, morph_name, force_play, percentage, stand_still, zero_movement, "Facing_josh")
repeat
-- watch for that crazy coop player screwing things up
if M01_setting_bomb then
return
end
thread_yield()
until action_play_is_finished(M01_group.autograph.guy, 1.0)
delay(2.5)
if M01_setting_bomb then
return
end
-- react Avoid Person
clear_animation_state(M01_group.autograph.guy)
on_death("", M01_group.autograph.guy)
on_take_damage("", M01_group.autograph.guy)
character_prevent_flinching(M01_group.autograph.guy, false)
turn_vulnerable( M01_group.autograph.guy )
character_allow_ragdoll(M01_group.autograph.guy, true)
if M01_setting_bomb then
return
end
-- send dude on his way
local should_run = true
local should_fire = false
ai_do_scripted_move(M01_group.autograph.guy, M01_group.bomb_flee.dest, should_run, should_fire)
audio_conversation_wait_for_end(M01_convo.sign_autograph.handle)
M01_convo.sign_autograph.handle = INVALID_CONVERSATION_HANDLE
-- slight delay so if we have waiting conversations, they don't run together
delay(3.0)
M01_doing_autograph = false
end
-- Oh Noes! Shut down all autograph guy stuffs
function m01_autograph_death_cb()
m01_clear_trigger(M01_group.autograph.trigger)
on_death("", M01_group.autograph.guy)
on_take_damage("", M01_group.autograph.guy)
-- end effect
if (M01_group.autograph.effect_handle ~= -1) then
effect_stop(M01_group.autograph.effect_handle)
M01_group.autograph.effect_handle = -1
end
end
-- Player has reached the bomb trigger
--
-- triggerer: (string) name of person triggering
--
function m01_reached_bomb(triggerer)
if M01_setting_bomb then
return
end
M01_setting_bomb = true
-- make sure this is done
thread_kill(M01_group.autograph.thread)
thread_kill(M01_thread.josh_ai)
inv_item_equip(nil, triggerer) -- Unequip the current weapon on the player
audio_object_post_event("M01_Score_Z02_Transition")
m01_clear_trigger(M01_trigger.bomb.name)
-- Player sets the bomb
local anim_name = "Bomb Plant"
local morph_name = "Bomb Plant"
local force_play = false
local percentage = 0.8
local stand_still = true
local zero_movement = true
action_play(triggerer, anim_name, morph_name, force_play, percentage, stand_still, zero_movement)
M01_trigger.bomb.hit = true
end
-- have swat say a line when attacking
--
-- name: (string) name of character detecting player
-- player: (string) name of player detected
--
function m01_morningstar_see_saints_line_cb(name, player)
-- SAY IT!
local situation = "M01_See_Saints"
-- wait until we are not in a conversation
while M01_conversation_playing do
thread_yield()
end
-- don't play this if we have done this recently
if (not thread_check_done(M01_thread.attack_line_timer)) then
return
end
-- start timer
M01_thread.attack_line_timer = thread_new("delay", 10.0)
-- play situation
audio_play_persona_line(name, situation)
end
-- have swat say a line when attacking
--
-- name: (string) name of character
-- weapon: (string) name of weapon
-- attack: (string) type of attack performed
--
function m01_swat_attack_line_cb(name, weapon, attack)
-- SAY IT!
local situation = "M01_Attack"
-- don't play this if we have done this recently
if (not thread_check_done(M01_thread.attack_line_timer)) then
return
end
-- start timer
M01_thread.attack_line_timer = thread_new("delay", M01_Attack_Line_Time)
-- play situation
audio_play_persona_line(name, situation)
end
-- Handle playing the attack lines
--
-- name: (string) name of character
-- weapon: (string) name of weapon
-- attack: (string) type of attack performed
--
function m01_process_gat_attack_cb(name, weapon, attack)
-- don't play this if we have done this recently
if (not thread_check_done(M01_gat_attack_info.timer)) then
return
end
if M01_conversation_playing then
return
end
-- start timer
M01_gat_attack_info.timer = thread_new("delay", M01_gat_attack_info.delay)
-- play situation
if not audio_play_persona_line(name, M01_gat_attack_info.situation) then
-- line didn't play, kill our timer
thread_kill(M01_gat_attack_info.timer)
M01_gat_attack_info.timer = INVALID_THREAD_HANDLE
end
end
-- Cause the helicopter to fly into building
function m01_crash_heli(heli_name, killer)
on_damage("", heli_name, 0.99)
local heli_group = M01_group.heli_police2
if heli_name == M01_group.heli_police1.vehicle then
heli_group = M01_group.heli_police1
end
-- make everyone vulnerable
for i,pilot in pairs(heli_group.members) do
turn_vulnerable(pilot)
end
turn_vulnerable(heli_group.shooter)
-- go to the forbidden navpoint
m01_heli_move_to(heli_group.crash_nav, heli_group)
delay(1.0)
vehicle_detonate(heli_name)
Helicopter_killed = true
end
-- Send heli to final location and watch it move
function m01_move_heli(heli_name, killer)
Helicopter_killed = true
on_damage("", heli_name, 0.99)
-- don't damage us more...yet
turn_invulnerable( heli_name )
-- reset camera restrict
camera_restrict_set_active(DISABLE)
-- target your current view
camera_restrict_target_object()
camera_restrict_set_limits( 0.0, 0.0, 0.0, 0.0)
-- lock it
camera_restrict_set_active(ENABLE)
thread_yield()
-- follow the chopper
camera_restrict_target_object(heli_name, 500)
delay(1.0)
-- go to the last navpoint
m01_heli_move_to(POLICE_HELI_SHOOT_AT_ME3, M01_group.heli_police1)
delay(2.5)
camera_restrict_target_object(CAMERA_TARGET4, 500)
camera_restrict_set_limits( M01_MIN_PITCH, M01_MAX_PITCH, M01_MIN_HEADING, M01_MAX_HEADING )
Helicopter_killed = true
end
function m01_failure_gat_died()
-- End the mission, Gat died
mission_end_failure("m01", HELPTEXT_FAILURE_GAT_DIED)
end
function m01_failure_shaundi_died()
-- End the mission, Shaundi died
mission_end_failure("m01", HELPTEXT_FAILURE_SHAUNDI_DIED)
end
function m01_failure_josh_died()
-- End the mission, Josh died
mission_end_failure("m01", HELPTEXT_FAILURE_JOSH_DIED)
end
function m01_weapon_was_equiped(weapon, is_firearm)
M01_weapon_changed = true
on_weapon_equip("", LOCAL_PLAYER)
end
-- kill whoever triggered this
function m01_kill_trigger_cb(human, trigger)
if human ~= nil then
if human == M01_gat or human == M01_shaundi then
teleport(human, "Fifth_window 003")
else
character_kill(human)
end
end
end
-- the attack heli has met the damage threshold
--
-- vehicle: (string) name of the vehicle damaged
-- attacker: (string) name of person causing the damage
function m01_attack_heli_damaged_cb(vehicle, attacker)
on_damage("", M01_group.heli_fighter1.vehicle)
M01_group.heli_fighter1.damaged = true
turn_invulnerable(M01_group.heli_fighter1.vehicle)
end
-- notify that a transport has been destroyed
--
-- vehicle: (string) name of vehicle destroyed
--
function m01_transport_destroyed_cb(vehicle)
-- find out which transport this was
local transport_group
if vehicle == M01_group.transport1.vehicle then
transport_group = M01_group.transport1
elseif vehicle == M01_group.transport2.vehicle then
transport_group = M01_group.transport2
elseif vehicle == M01_group.transport2.vehicle then
transport_group = M01_group.transport3
else
-- that's all we had. IDK what this is
return
end
on_vehicle_destroyed("", transport_group.vehicle)
transport_group.complete = true
-- make sure pilots are killed
for i,pilot in pairs(transport_group.pilots) do
turn_vulnerable(pilot)
character_kill(pilot)
end
persona_override_persona_stop(transport_group.pilots[1])
-- short cleanup delay
delay(1.5)
vehicle_delete_all_corpses()
-- release so we can really delete the corpse when we have the chance
release_to_world(transport_group.name)
end
-- *************************
--
-- Thread functions
--
-- *************************
-- Reset all our movers
--
function m01_reset_movers_thread()
mesh_mover_reset(M01_vault_mover)
-- make sure our roof is in place
mesh_mover_reset("Break_ceiling")
mesh_mover_reset("Break_roof")
mesh_mover_reset("Break_wall")
mesh_mover_reset("Break_light<001>")
mesh_mover_reset("Break_light<002>")
end
-- setup fine aim glass to turn on emitter when broken
--
function m01_fine_aim_glass_thread()
for i,pane in pairs(M01_fine_aim_glass) do
mesh_mover_reset(pane)
end
local broken = false
while not broken do
for i, pane in pairs(M01_fine_aim_glass) do
if mesh_mover_destroyed(pane) then
broken = true
end
end
thread_yield()
end
if broken then
m01_start_emitters(M01_audio_emitter.fine_aim)
end
end
-- Open the door and let the guards out
--
function m01_enter_guards_thread()
-- wait for player's animation to get going
delay(1.5)
-- open the door
local reverse_door = true
local animate_door = true
door_open(LOBBY_DOOR01, reverse_door, animate_door) --, M01_group.lobby.moving_guards[1])
-- wait for door to open
--delay(0.5)
-- go here
local should_run = true
local should_fire = false
for i,guard in pairs(M01_group.lobby.moving_guards) do
ai_do_scripted_move(guard, M01_group.lobby.guard_navs[i], should_run, should_fire)
delay(1.0)
end
end
-- Say the get robbed line
--
-- name: (string) name of character
--
function m01_get_robbed_line_thread(name)
local situation = "M01_Get_Robbed"
-- setup the persona
persona_override_persona_start(name, "Saints_Fan_AM")
while not character_is_dead(name) do
delay(M01_Get_Robbed_Line_Time)
-- SAY IT!
if not character_is_dead(name) then
audio_play_persona_line(name, situation)
end
end
end
-- spawn a group of peds and make them cower (threaded because it takes some time to desync anims)
--
-- group_table: (table) information about the group to make cower
function m01_group_cower_thread(group_table)
group_create(group_table.name)
for i,npc in pairs(group_table.on_ground) do
while not character_is_ready(npc) do
thread_yield() -- once the first is done, the rest should be done
end
set_cower_variant(npc, 1)
set_cant_cower_flag(npc, false)
set_cant_flee_flag(npc, true)
cower(npc, LOCAL_PLAYER, true, true)
delay(0.1) -- don't start everyone at the same time
end
for i,npc in pairs(group_table.members) do
set_cant_cower_flag(npc, false)
set_cant_flee_flag(npc, true)
cower(npc, LOCAL_PLAYER, true, true)
delay(0.1) -- don't start everyone at the same time
end
end
-- keep telling homie to take the hostage
-- attacker: (string) attacker to take the hostage
-- hostage: (string) name of hostage
function m01_take_hostage(attacker, hostage)
-- tell Gat to grab the guard (bypass AI because we've set them up for this)
character_take_human_shield(attacker, hostage, true)
end
-- tell a homie to move to a navpoint and find cover
--
-- homie_name: (string) name of homie to move
-- navpoint: (string) nave of navpoint to go to
--
function m01_homie_move_thread(homie_name, navpoint)
-- need to do this on your own
follower_make_independent(homie_name, true)
ai_clear_scripted_action(homie_name)
-- find cover
ai_do_scripted_take_cover(homie_name, navpoint)
ai_set_in_scripted_cover(homie_name, true)
npc_leash_to_nav(homie_name, navpoint, 5)
ai_set_personality(homie_name, "gang defensive")
-- wait for completion
while not ai_scripted_action_is_complete(homie_name) do
thread_yield()
end
end
function m01_gat_guard_convo_thread()
-- Not waiting yet
M01_guard_killed = false
M01_gat_at_door = false
M01_lobby_cleared = false
M01_convo.gat_interrogate.handle = audio_conversation_load(M01_convo.gat_interrogate.name)
M01_convo.gat_interrogate2.handle = audio_conversation_load(M01_convo.gat_interrogate2.name)
-- -- start interrogation with 4 dudes left
-- while (Num_enemies_alive > 4) do
-- --while not M01_lobby_cleared do
-- thread_yield()
-- end
-- start right away
-- if you think you should be doing something, you are wrong
set_ignore_ai_flag(M01_group.start_homies.gat, true)
-- let go so we don't have any animation fighting
local instant_release = true
character_set_only_scripted_grabs(M01_group.start_homies.captive) -- make sure Shaundi doesn't grab him
if M01_thread.gat_hostage ~= INVALID_THREAD_HANDLE then -- make sure Gat doesn't try again
thread_kill(M01_thread.gat_hostage)
end
-- roll into the interrogation
-- pop to nav
teleport(M01_group.start_homies.gat, M01_group.start_homies.captive_nav)
thread_yield()
-- start the state
-- pop to nav
--teleport(M01_group.start_homies.gat, M01_group.start_homies.captive_nav)
action_play_synced_state(M01_group.start_homies.gat, M01_group.start_homies.captive, "Gat Interrogation State")
action_play_synced(M01_group.start_homies.gat, M01_group.start_homies.captive, "Gat Interrogation Entry")
delay(1.5)
-- do interrogation
-- Gat is going to interrogate
M01_conversation_playing = true
-- Gat just says one line now
--audio_play_persona_line(M01_group.start_homies.gat, "M01_Interrogate_Guard_05")
audio_conversation_play(M01_convo.gat_interrogate.handle)
-- set up our horse trigger
m01_set_trigger(M01_trigger.horse.name, "m01_trigger_horse_cb")
-- wait until the player gets done with his animation
while not M01_player_over_desk do
thread_yield()
end
-- When the conversation is done, Gat kills him
audio_conversation_wait_for_end(M01_convo.gat_interrogate.handle)
M01_convo.gat_interrogate.handle = INVALID_CONVERSATION_HANDLE
M01_conversation_playing = false
-- launch him
character_allow_ragdoll(M01_group.start_homies.captive, true)
-- pop to nav
--teleport(M01_group.start_homies.gat, M01_group.start_homies.captive_nav)
character_release_human_shield(M01_group.start_homies.gat, instant_release)
action_play_synced(M01_group.start_homies.gat, M01_group.start_homies.captive, "Gat Interrogation Exit")
-- wait until Gat is done. Horse should blow up on trigger
while not action_play_is_finished(M01_group.start_homies.gat) do
thread_yield()
end
-- kill him
set_ignore_ai_flag(M01_group.start_homies.gat, false)
action_stop_synced_state(M01_group.start_homies.gat)
if not M01_trigger.horse.hit then
-- we didn't break the horse yet? Crappy!
m01_break_horsie()
end
-- free up Gat
character_allow_ragdoll(M01_group.start_homies.gat, true)
character_prevent_flinching(M01_group.start_homies.gat, false)
follower_make_independent(M01_group.start_homies.gat, true)
-- larger leash, but still leashed (makes slide over counter go smoother)
npc_leash_to_nav( M01_group.start_homies.gat, M01_group.start_homies.captive_nav, 5.0 )
-- move to close to the door
local should_run = true
local should_fire = false
--ai_do_scripted_move(M01_group.start_homies.gat, "lobby_mark 001", should_run, should_fire)
-- after guard killed conversation
M01_conversation_playing = true
audio_conversation_play(M01_convo.gat_interrogate2.handle)
thread_yield()
-- signal the main thread that guard has been killed
M01_guard_killed = true
M01_convo.look_for_vault.handle = audio_conversation_load(M01_convo.look_for_vault.name)
while not M01_lobby_cleared do
thread_yield()
end
npc_leash_remove( M01_group.start_homies.gat )
-- Gat slide (hahaha)
-- start by telling Gat to go to the navpoint
ai_do_scripted_move(M01_group.start_homies.gat, "Gat_slide_nav", should_run, should_fire)
-- when he gets close, play the animation
while not ai_scripted_action_is_complete(M01_group.start_homies.gat) and (get_dist(M01_group.start_homies.gat, "Gat_slide_nav") > 0.5) do
thread_yield()
end
-- this should look great
--ai_clear_scripted_action(M01_group.start_homies.gat)
-- turn AI off while we do the action
--set_ignore_ai_flag( M01_group.start_homies.gat, true )
-- tell npc to play action at navpoint (sliding into place as necessary)
local anim_name = "Gat Sounter Slide"
local morph_name = "Gat Sounter Slide"
local force_play = false
local percentage = 1.0
local stand_still = true
local zero_movement = true
action_play(M01_group.start_homies.gat, anim_name, morph_name, force_play, percentage, stand_still, zero_movement, "Gat_slide_nav")
-- Gat takes a position by the door
m01_have_to_get_there_thread(M01_group.start_homies.gat, M01_cover.lobby2.gat)
-- don't move
npc_leash_to_nav(M01_group.start_homies.gat, M01_cover.lobby2.gat, 0.0)
audio_conversation_wait_for_end(M01_convo.gat_interrogate2.handle)
M01_convo.gat_interrogate2.handle = INVALID_CONVERSATION_HANDLE
M01_conversation_playing = false
M01_gat_at_door = true
-- wait for Josh's grandstanding
while not M01_josh_grandstanded do
thread_yield()
end
-- Shaundi: Oh Jesus..
--audio_play_persona_line(M01_shaundi, "M01_Berating_Josh_03")
delay(6.5)
while M01_conversation_playing do
thread_yield()
end
-- talk about going to vault
M01_conversation_playing = true
audio_conversation_play(M01_convo.look_for_vault.handle)
thread_yield()
M01_convo.morningstar.handle = audio_conversation_load(M01_convo.morningstar.name)
audio_conversation_wait_for_end(M01_convo.look_for_vault.handle)
M01_convo.look_for_vault.handle = INVALID_CONVERSATION_HANDLE
M01_conversation_playing = false
-- wait a smidge
delay(2.0)
-- talk about the morningstar
M01_conversation_playing = true
audio_conversation_play(M01_convo.morningstar.handle)
thread_yield()
audio_conversation_wait_for_end(M01_convo.morningstar.handle)
M01_convo.morningstar.handle = INVALID_CONVERSATION_HANDLE
M01_conversation_playing = false
end
-- Josh and Shaundi talk when going to set the bomb
function m01_bomb_convo_thread()
-- we should put this above the vault
audio_play_persona_line(LOCAL_PLAYER, "M01_Head_Above_Vault_01")
delay(3.5)
M01_convo.more_guys.handle = audio_conversation_load_direct(M01_convo.more_guys.name)
thread_yield()
-- More guards from elevator
M01_conversation_playing = true
audio_conversation_play(M01_convo.more_guys.handle)
thread_yield()
audio_conversation_wait_for_end(M01_convo.more_guys.handle)
M01_convo.more_guys.handle = INVALID_CONVERSATION_HANDLE
M01_conversation_playing = false
-- break
delay(2.3)
M01_convo.josh_and_shaundi.handle = audio_conversation_load_direct(M01_convo.josh_and_shaundi.name)
thread_yield()
-- Don't play if autograph thing is currently happening
while M01_doing_autograph do
thread_yield()
end
-- Josh professes his love to Shaundi
M01_conversation_playing = true
audio_conversation_play(M01_convo.josh_and_shaundi.handle)
thread_yield()
audio_conversation_wait_for_end(M01_convo.josh_and_shaundi.handle)
M01_convo.josh_and_shaundi.handle = INVALID_CONVERSATION_HANDLE
M01_conversation_playing = false
end
-- spawn the bad-guys in the elevator, open doors and send them out
function m01_elevator_guards_thread()
-- spawn and go
group_create(M01_group.bomb_security2.name, true)
for i,rocket_man in pairs(M01_group.bomb_security2.members) do
-- no rocket for you!!
npc_dont_drop_weapon_on_death(rocket_man, true)
end
local should_run = true
local should_fire = false
ai_do_scripted_move(M01_shaundi, "Shaundi_leash", should_run, should_fire)
ai_do_scripted_move(M01_gat, "Gat_leash<001>", should_run, true)
thread_kill(M01_thread.josh_ai)
ai_do_scripted_move(M01_josh, "Josh_leash", should_run, should_fire)
m01_setup_see_saints(M01_group.bomb_security2.members)
local locked = false
door_lock(M01_ELEVATOR_DOOR, locked)
door_open(M01_ELEVATOR_DOOR)
-- need to leash Shaundi so she doesn't run away and hide
npc_leash_to_nav(M01_shaundi, "Shaundi_leash", 3.0)
npc_leash_to_nav(M01_gat, "Gat_leash<001>", 5.0)
delay(2.0)
local nav1 = "Start_player_nav<001>"
local nav2 = "Start_player_nav<002>"
local move_to = nav1
for i, guard in pairs(M01_group.bomb_security2.members) do
npc_leash_to_nav(guard, move_to, 12)
ai_do_scripted_take_cover(guard, move_to)
ai_add_enemy_target(M01_shaundi, guard, ATTACK_NOW, false)
delay(0.1)
if move_to == nav1 then
move_to = nav2
else
move_to = nav1
end
end
end
-- setup the Saints Fan wanting an autograph from player
function m01_setup_autograph_thread()
M01_doing_autograph = false
-- spawn the group of 1
local block = true
group_create(M01_group.autograph.name, block)
while not character_is_ready(M01_group.autograph.guy) do
thread_yield()
end
-- don't cower
set_cant_cower_flag(M01_group.autograph.guy, true)
-- don't fight me
npc_combat_enable(M01_group.autograph.guy, false)
-- don't flinch
character_prevent_flinching(M01_group.autograph.guy, true)
-- setup voice
persona_override_persona_start(M01_group.autograph.guy, "Interrogation")
-- setup fallback in case he is killed
on_death("m01_autograph_death_cb", M01_group.autograph.guy)
on_take_damage("m01_autograph_death_cb", M01_group.autograph.guy)
-- put him in his animation
set_animation_state(M01_group.autograph.guy, "AutoGraph Stand")
-- setup his trigger
m01_set_trigger(M01_group.autograph.trigger, "m01_sign_autograph_cb")
M01_group.autograph.effect_handle = effect_play_finisher(M01_group.autograph.guy, 2.4)
-- just stay in this state unless you die or sign something
while true do
if not check_animation_state(M01_group.autograph.guy, "AutoGraph Stand") then
set_animation_state(M01_group.autograph.guy, "AutoGraph Stand")
end
thread_yield()
end
-- add special effect for photo-op
--marker_add_trigger(M01_group.autograph.trigger, MINIMAP_ICON_USE, INGAME_EFFECT_LOCATION)--"VFX_PhotoOpIcon")
end
-- handle conversations while on the vault
function m01_vault_convo_thread()
-- init all of our triggers
M01_convo.heli_rising.start = false
M01_convo.heli_jerk_back.start = false
M01_convo.heli_not_leaving.start = false
M01_convo.heli_drag_vault.start = false
M01_convo.heli_near_collision.start = false
M01_convo.vault_tipped.start = false
M01_convo.hooked_up.handle = audio_conversation_load(M01_convo.hooked_up.name)
-- wait until signaled
while not M01_convo.hooked_up.start do
thread_yield()
end
delay(M01_convo.hooked_up.delay)
audio_conversation_play(M01_convo.hooked_up.handle)
thread_yield()
audio_conversation_wait_for_end(M01_convo.hooked_up.handle)
M01_convo.hooked_up.handle = INVALID_CONVERSATION_HANDLE
-- load the first 3 conversations
M01_convo.heli_rising.handle = audio_conversation_load(M01_convo.heli_rising.name)
--M01_convo.heli_jerk_back.handle = audio_conversation_load(M01_convo.heli_jerk_back.name)
-- wait until signaled
while not M01_convo.heli_rising.start do
thread_yield()
end
delay(M01_convo.heli_rising.delay)
audio_conversation_play(M01_convo.heli_rising.handle)
thread_yield()
audio_conversation_wait_for_end(M01_convo.heli_rising.handle)
M01_convo.heli_rising.handle = INVALID_CONVERSATION_HANDLE
M01_convo.heli_not_leaving.handle = audio_conversation_load(M01_convo.heli_not_leaving.name)
-- wait until signaled
while not M01_convo.heli_jerk_back.start do
thread_yield()
end
delay(M01_convo.heli_jerk_back.delay)
audio_play_persona_line(M01_group.vault_heli.pilot, "M01_Helicopter_Jerks_Back_01")
M01_convo.heli_drag_vault.handle = audio_conversation_load(M01_convo.heli_drag_vault.name)
-- wait until signaled
while not M01_convo.heli_not_leaving.start do
thread_yield()
end
delay(M01_convo.heli_not_leaving.delay)
audio_conversation_play(M01_convo.heli_not_leaving.handle)
thread_yield()
audio_conversation_wait_for_end(M01_convo.heli_not_leaving.handle)
M01_convo.heli_not_leaving.handle = INVALID_CONVERSATION_HANDLE
M01_convo.heli_near_collision.handle = audio_conversation_load(M01_convo.heli_near_collision.name)
-- wait until signaled
while not M01_convo.heli_drag_vault.start do
thread_yield()
end
delay(M01_convo.heli_drag_vault.delay)
audio_conversation_play(M01_convo.heli_drag_vault.handle)
thread_yield()
audio_conversation_wait_for_end(M01_convo.heli_drag_vault.handle)
M01_convo.heli_drag_vault.handle = INVALID_CONVERSATION_HANDLE
M01_convo.vault_tipped.handle = audio_conversation_load(M01_convo.vault_tipped.name)
-- wait until signaled
while not M01_convo.heli_near_collision.start do
thread_yield()
end
delay(M01_convo.heli_near_collision.delay)
audio_conversation_play(M01_convo.heli_near_collision.handle)
thread_yield()
audio_conversation_wait_for_end(M01_convo.heli_near_collision.handle)
M01_convo.heli_near_collision.handle = INVALID_CONVERSATION_HANDLE
-- wait until signaled
while not M01_convo.vault_tipped.start do
thread_yield()
end
delay(M01_convo.vault_tipped.delay)
audio_conversation_play(M01_convo.vault_tipped.handle)
thread_yield()
audio_conversation_wait_for_end(M01_convo.vault_tipped.handle)
M01_convo.vault_tipped.handle = INVALID_CONVERSATION_HANDLE
end
-- These lines play at a critical time and we don't want to blow it if they play late/don't play
function m01_same_chopper2_thread()
audio_play_persona_line(LOCAL_PLAYER, "M01_Same_Attack_Chopper_02")
thread_yield()
while audio_persona_line_playing(LOCAL_PLAYER) do
thread_yield()
end
audio_play_persona_line(M01_group.heli_fighter1.members[1], "M01_Bullhorn_Attack_Heli_Strafe_01")
end
-- Show Gat and Shaundi prepping for SWAT attack
function m01_homies_prep_thread()
group_show(M01_group.swat_homies.name)
m01_setup_crew(M01_group.swat_homies)
-- make sure we are ready before we start playing animations
while not character_is_ready(M01_shaundi) do
thread_yield()
end
npc_unholster_best_weapon(M01_gat)
npc_unholster_best_weapon(M01_shaundi)
follower_make_independent(M01_gat, true)
follower_make_independent(M01_shaundi, true)
local anim_name = "Shaundi M01 Prep"
local morph_name = "Shaundi M01 Prep"
local force_play = false
local percentage = 0.1
local stand_still = true
local zero_movement = true
action_play(M01_shaundi, anim_name, morph_name, force_play, percentage, stand_still, zero_movement)
anim_name = "Gat M01 Prep"
morph_name = "Gat M01 Prep"
action_play(M01_gat, anim_name, morph_name, force_play, percentage, stand_still, zero_movement)
end
-- kill all of the helicopter movement threads if active
function m01_kill_heli_move_threads()
for i, group in pairs(M01_heli_police_groups) do
if group.thread ~= INVALID_THREAD_HANDLE then
thread_kill(group.thread)
end
end
end
-- Monitor the m01 vault's animation
function m01_path_complete_thread()
-- wait for transition to complete
while (vehicle_anim_playing(M01_group.vault_heli.vehicle)) do
thread_yield()
end
end
-- fly a helicopter to a specified point
--
-- heli: (string) name of the helicotper to move
-- nav: (string) name of the navpoint to move to
-- speed: (float) speed to move
--
function m01_fly_direct_thread(heli, nav, speed)
-- fly direct because we are very close to buildings
helicopter_fly_to_direct(heli, speed, nav)
end
function m01_fineaim_tutorial()
-- Fine aim tutorial
tutorial_start("combat_fineaim", 1000, true)
-- Wait for the fine aim tutorial to actally start displaying
while not tutorial_active("combat_fineaim") do
if not tutorial_queued("combat_fineaim") then
-- The tutorial died for some reason. Just give up.
M01_TUTORIAL_FINEAIM = INVALID_THREAD_HANDLE
return
end
thread_yield()
end
-- Show the first message for at least 2 seconds
delay(2.0)
-- Wait for the player to hold the shoulder button
while not inv_item_is_firearm_equipped() or not player_action_is_pressed("CBA_OFC_SHOULDER_CAMERA") do
thread_yield()
end
-- Advance to case 1
tutorial_advance("combat_fineaim")
-- Tutorial should clean up it's self after this point
M01_TUTORIAL_FINEAIM = INVALID_THREAD_HANDLE
end
-- Weapon changing tutorial. Waits until the palyer changed his weapon.
function m01_change_weapons_tutorial()
M01_weapon_changed = false
on_weapon_equip("m01_weapon_was_equiped", LOCAL_PLAYER)
tutorial_start("combat_weapons", 1000, true)
-- Wait for the fine aim tutorial to actally start displaying
while not tutorial_active("combat_weapons") do
if not tutorial_queued("combat_weapons") then
-- The tutorial died for some reason. Just give up.
M01_TUTORIAL_SWITCH_WEAPON = INVALID_THREAD_HANDLE
return
end
thread_yield()
end
-- Show the first message for at least 2 seconds
delay(2.0)
-- Wait for the player to switch weapons
while not M01_weapon_changed do
if not tutorial_active("combat_weapons") then
-- The tutorial died for some reason. Just give up.
M01_TUTORIAL_SWITCH_WEAPON = INVALID_THREAD_HANDLE
return
end
thread_yield()
end
tutorial_advance("combat_weapons")
M01_TUTORIAL_SWITCH_WEAPON = INVALID_THREAD_HANDLE
end
-- Thread to get helicopters loaded and off the ground
--
-- group_table: (table) information about the heli group
-- float_nav: (string) name of navpoint to float the heli at
--
function m01_spawn_and_float_heli_thread(group_table, float_nav)
group_create(group_table.name, true)
vehicle_enter_group_teleport(group_table.members, group_table.vehicle)
vehicle_enter_teleport(group_table.shooter, group_table.vehicle, group_table.shooter_seat)
m01_float_heli(group_table, float_nav)
end
-- handle news heli stuff (spotlights)
--
-- group_table: (table) everything I need to make news heli work
--
function m01_news_heli_thread(group_table)
-- news_heli1
local current_location = 0 -- always start at float nav
-- spawn it, load it and get it in the air
group_create(group_table.name, true)
vehicle_enter_group_teleport(group_table.members, group_table.vehicle)
m01_float_heli(group_table, group_table.float_nav)
local current_nav = group_table.float_nav
while true do
if current_location ~= M01_news_location then
if M01_news_location <= group_table.max_locations then
current_location = M01_news_location
else
current_location = group_table.max_locations
end
end
if vehicle_is_destroyed(group_table.vehicle) then
return
end
local location_info = group_table.location[current_location]
if current_nav ~= location_info.hover_nav then
-- go to where I need to be
current_nav = location_info.hover_nav
if location_info.looping_path then
helicopter_fly_to_direct_loop(group_table.vehicle, 20, current_nav)
else
-- direct call waits for completion before continuing
helicopter_fly_to_direct(group_table.vehicle, -1, current_nav)
end
else
-- make sure we haven't strayed too far from our hover nav
if not location_info.looping_path and get_dist(group_table.vehicle, current_nav) > 5.0 then
-- get back over there
helicopter_fly_to_direct(group_table.vehicle, -1, current_nav)
end
end
thread_yield()
-- art no like spotlights
-- -- make my spotlight look at stuff
-- for i,point in pairs(location_info.interest) do
-- if vehicle_is_destroyed(group_table.vehicle) or character_is_dead(group_table.members[1]) then
-- return
-- end
-- vehicle_spotlight_is_target_spotted(group_table.members[1], point)
-- delay(location_info.delay_time)
-- end
end
end
-- Thread to handle a respawning pair
--
-- pair_table: (table) group information about the pair
function m01_respawn_pair_thread(pair_table)
-- start disabled
pair_table.active = false
-- run until killed
while true do
-- see if we should spawn/respawn
while not pair_table.active do
thread_yield()
end
while (not thread_check_done(M01_thread.respawn_timer)) do
thread_yield()
end
-- claim it
M01_thread.respawn_timer = thread_new("delay", 1.5)
-- spawn the group
group_create(pair_table.name, true)
-- keep a count
M01_pairs_spawned = M01_pairs_spawned + 1
if (pair_table.window_entry) then
-- play swat animation
pair_table.entry_thread = thread_new("m01_swat_entry", pair_table.members[1], pair_table.navs[pair_table.set][1], pair_table.ropes[1])
delay(0.3)
pair_table.entry_thread = thread_new("m01_swat_entry", pair_table.members[2], pair_table.navs[pair_table.set][2], pair_table.ropes[2])
else
-- tell them to go to their navpoints
local should_run = true
local should_fire = false
ai_do_scripted_move(pair_table.members[1], pair_table.navs[pair_table.set][1], should_run, should_fire)
ai_do_scripted_move(pair_table.members[2], pair_table.navs[pair_table.set][2], should_run, should_fire)
-- target player, not the pilot
ai_add_enemy_target(pair_table.members[1], LOCAL_PLAYER, ATTACK_NOW_NEVER_LOSE, true)
if (coop_is_active() == true) then
ai_add_enemy_target(pair_table.members[2], REMOTE_PLAYER, ATTACK_NOW_NEVER_LOSE, true)
else
ai_add_enemy_target(pair_table.members[2], LOCAL_PLAYER, ATTACK_NOW_NEVER_LOSE, true)
end
end
-- wait until they are dead
while not character_is_dead(pair_table.members[1]) do
thread_yield()
end
while not character_is_dead(pair_table.members[2]) do
thread_yield()
end
-- clear callback
on_attack_performed("", pair_table.members[1])
on_attack_performed("", pair_table.members[2])
-- release so we can respawn
release_to_world(pair_table.name)
-- keep a count
M01_pairs_spawned = M01_pairs_spawned - 1
-- change where we send them to
if pair_table.set == 1 then
pair_table.set = 2
else
pair_table.set = 1
end
-- delay before respawn
delay(2.3)
end
end
-- Spawn a transport, load passengers and float at navpoint
--
-- transport_table: (table) transport information
--
function m01_setup_transport_thread(transport_table)
group_create(transport_table.name, true)
transport_table.complete = false
-- pilots first
local seat_idx = 0
for i, char in pairs(transport_table.pilots) do
-- Put the pilots into the vehicle
vehicle_enter_teleport(char, transport_table.vehicle, seat_idx, true)
follower_remain_in_car(char, true)
-- no floating weapons when vehicle is destroyed
npc_combat_enable(char, false)
while(not character_is_in_vehicle(char, transport_table.vehicle)) do
thread_yield()
end
seat_idx = seat_idx + 1
end
for i, char in pairs(transport_table.soldiers) do
-- Put the soldiers into the vehicle
vehicle_enter_teleport(char, transport_table.vehicle, seat_idx, true)
follower_remain_in_car(char, true)
while(not character_is_in_vehicle(char, transport_table.vehicle)) do
thread_yield()
end
seat_idx = seat_idx + 1
end
m01_float_heli(transport_table, transport_table.float_nav)
end
-- tell a transport to do a flyby and teleport back to float nav
--
-- transport_table: (table) Information about our transport heli
--
function m01_transport_flyby_thread(transport_table)
-- make heli invulnerable for flyby
turn_invulnerable(transport_table.vehicle)
-- float at the start
m01_float_heli(transport_table, transport_table.flyby_float)
-- pause for effect
delay(2.0)
-- fly the path
m01_fly_direct_thread(transport_table.vehicle, transport_table.flyby_path, 30.0)
-- move back to starting float area
m01_float_heli(transport_table, transport_table.float_nav)
turn_vulnerable(transport_table.vehicle)
end
-- Hide or show a transport helicopter and crew
--
-- transport_table: (table) Information about our transport heli
-- show: (boolean) true to show, false to hide
--
function m01_transport_show(transport_table, show)
if show then
vehicle_show(transport_table.vehicle)
for i,char in pairs(transport_table.soldiers) do
character_show(char)
end
for j,pilots in pairs(transport_table.pilots) do
character_show(pilots)
end
else
vehicle_hide(transport_table.vehicle)
for i,char in pairs(transport_table.soldiers) do
character_hide(char)
end
for j,pilots in pairs(transport_table.pilots) do
character_hide(pilots)
end
end
end
-- Emergency destroy in case the transport does not land properly (flips upsidedown or gets caught on something)
--
-- vehicle: (string) name of the transport helicopter
--
function m01_transport_emergency_destroy_thread(vehicle)
-- simple delay to determine how long we have (extra long)
delay(45.0)
-- times up, you are now vulnerable
turn_vulnerable(vehicle)
-- so blow up (callback will clean the rest up
vehicle_detonate(vehicle)
end
-- Drop off some troops and get out (weak helicopter drop-off) (script stolen from m10)
--
-- transport_table: (table) Information about our drop-off group
--
function m01_transport_drop_off_thread(transport_table)
if (transport_table.persona_line ~= "") then
persona_override_persona_start(transport_table.pilots[1], transport_table.pilot_persona)
end
turn_invulnerable(transport_table.vehicle)
-- mark transport as complete if the heli is destroyed
on_vehicle_destroyed("m01_transport_destroyed_cb", transport_table.vehicle)
-- reuse setup thread as emergency timer
transport_table.setup_thread = thread_new("m01_transport_emergency_destroy_thread", transport_table.vehicle)
-- get close
transport_table.thread = thread_new("m01_fly_direct_thread", transport_table.vehicle, transport_table.path, 45.0)
while get_dist(transport_table.vehicle, transport_table.path) > 70.0 do
thread_yield()
end
thread_kill(transport_table.thread)
-- get closer slower
transport_table.thread = thread_new("m01_fly_direct_thread", transport_table.vehicle, transport_table.path, 10.0)
while get_dist(transport_table.vehicle, transport_table.path) > 6.0 do
thread_yield()
end
thread_kill(transport_table.thread)
-- get closer slower
transport_table.thread = thread_new("m01_fly_direct_thread", transport_table.vehicle, transport_table.path, 3.0)
while get_dist(transport_table.vehicle, transport_table.path) > 2.0 do
thread_yield()
end
thread_kill(transport_table.thread)
-- get closer slower
transport_table.thread = thread_new("m01_fly_direct_thread", transport_table.vehicle, transport_table.path, 1.5)
while get_dist(transport_table.vehicle, transport_table.path) > 2.2 do
thread_yield()
end
thread_kill(transport_table.thread)
-- lets play a line
if (transport_table.persona_line ~= "") then
audio_play_persona_line(transport_table.pilots[1], transport_table.persona_line)
end
delay(0.5)
turn_vulnerable(transport_table.vehicle)
-- don't auto-destroy from here on
thread_kill(transport_table.setup_thread)
for i, char in pairs(transport_table.soldiers) do
follower_remain_in_car(char, false)
end
vehicle_exit_group(transport_table.soldiers, true) -- unenterable to make sure the soldiers don't try to get back in the transport
local should_run = true
local should_fire = false
-- close enough
for j, char in pairs(transport_table.soldiers) do
if (character_is_dead(char) == false) then
ai_add_enemy_target(char, LOCAL_PLAYER, ATTACK_ON_SIGHT, true)
if (coop_is_active() == true) then
ai_add_enemy_target(char, REMOTE_PLAYER, ATTACK_ON_SIGHT, true)
end
--ai_do_scripted_take_cover(char)
ai_do_scripted_move(char, transport_table.soldier_dest, should_run, should_fire)
end
end
delay(transport_table.ground_delay)
persona_override_persona_stop(transport_table.pilots[1])
transport_table.thread = thread_new("m01_fly_direct_thread", transport_table.vehicle, transport_table.exit_nav, 25.0)
while get_dist(transport_table.vehicle, transport_table.path) < 20.0 do
thread_yield()
end
-- if we make it out, consider it complete
transport_table.complete = true
end
-- Attack heli AI while the player is in the building
--
-- group_table: (table) information about the attack heli
function m01_attack_heli_building_battle_thread( group_table )
while not M01_group.heli_fighter1.permission_to_fire do
thread_yield()
end
npc_combat_enable(group_table.members[1], true)
npc_combat_enable(group_table.members[2], true)
local path_orient = HELI_PF_FACE_TARGET -- front face target
helicopter_set_path_orientation( group_table.vehicle, path_orient, LOCAL_PLAYER)
local missle_delay = 1.0
local attack_delay = 2.5
-- shoot warning missiles at back wall
local alt_fire = true
helicopter_shoot_navpoint(group_table.vehicle, "battle_rocket_target<004>", alt_fire)
delay(missle_delay)
helicopter_shoot_navpoint(group_table.vehicle, "battle_rocket_target<004>", alt_fire)
M01_group.heli_fighter1.thread = thread_new("m01_fly_direct_thread", group_table.vehicle, "battle_retreat_point", 8.0)
while get_dist(group_table.vehicle, "battle_retreat_point") > 5.0 do
thread_yield()
end
delay(attack_delay)
local do_sweep = true
while M01_group.heli_fighter1.permission_to_fire do
if M01_group.heli_fighter1.permission_to_fire then
M01_group.heli_fighter1.thread = thread_new("m01_fly_direct_thread", group_table.vehicle, "battle_attack_point<002>", 7.0)
end
while get_dist(group_table.vehicle, "battle_attack_point<002>") > 5.0 do
thread_yield()
end
if M01_group.heli_fighter1.permission_to_fire then
M01_group.heli_fighter1.thread = thread_new("m01_fly_direct_thread", group_table.vehicle, "battle_attack_point<003>", 1.0)
end
if do_sweep then
-- sweep the gun
local seconds = 0.4
if M01_group.heli_fighter1.permission_to_fire then
m01_heli_shoot_gun_at_nav(group_table.vehicle, "battle_target<001>", seconds)
end
if M01_group.heli_fighter1.permission_to_fire then
m01_heli_shoot_gun_at_nav(group_table.vehicle, "battle_target<002>", seconds)
end
if M01_group.heli_fighter1.permission_to_fire then
m01_heli_shoot_gun_at_nav(group_table.vehicle, "battle_target<003>", seconds)
end
if M01_group.heli_fighter1.permission_to_fire then
m01_heli_shoot_gun_at_nav(group_table.vehicle, "battle_target<004>", seconds)
end
if M01_group.heli_fighter1.permission_to_fire then
m01_heli_shoot_gun_at_nav(group_table.vehicle, "battle_target<005>", seconds)
end
if M01_group.heli_fighter1.permission_to_fire then
m01_heli_shoot_gun_at_nav(group_table.vehicle, "battle_target<006>", seconds)
end
if M01_group.heli_fighter1.permission_to_fire then
m01_heli_shoot_gun_at_nav(group_table.vehicle, "battle_target<007>", seconds)
end
if M01_group.heli_fighter1.permission_to_fire then
m01_heli_shoot_gun_at_nav(group_table.vehicle, "battle_target<008>", seconds)
end
if M01_group.heli_fighter1.permission_to_fire then
m01_heli_shoot_gun_at_nav(group_table.vehicle, "battle_target<007>", seconds)
end
if M01_group.heli_fighter1.permission_to_fire then
m01_heli_shoot_gun_at_nav(group_table.vehicle, "battle_target<006>", seconds)
end
if M01_group.heli_fighter1.permission_to_fire then
m01_heli_shoot_gun_at_nav(group_table.vehicle, "battle_target<005>", seconds)
end
if M01_group.heli_fighter1.permission_to_fire then
m01_heli_shoot_gun_at_nav(group_table.vehicle, "battle_target<004>", seconds)
end
if M01_group.heli_fighter1.permission_to_fire then
m01_heli_shoot_gun_at_nav(group_table.vehicle, "battle_target<003>", seconds)
end
if M01_group.heli_fighter1.permission_to_fire then
m01_heli_shoot_gun_at_nav(group_table.vehicle, "battle_target<002>", seconds)
end
if M01_group.heli_fighter1.permission_to_fire then
m01_heli_shoot_gun_at_nav(group_table.vehicle, "battle_target<001>", seconds)
end
--do_sweep = false
else
-- shoot player or another target
local shoot_human_seconds = 6.0
m01_heli_shoot_gun_at_human(group_table.vehicle, LOCAL_PLAYER, shoot_human_seconds)
--do_sweep = true
end
if M01_group.heli_fighter1.permission_to_fire then
M01_group.heli_fighter1.thread = thread_new("m01_fly_direct_thread", group_table.vehicle, "battle_retreat_point", 8.0)
while get_dist(group_table.vehicle, "battle_retreat_point") > 5.0 do
thread_yield()
end
end
if M01_group.heli_fighter1.permission_to_fire then
delay(attack_delay)
end
if M01_group.heli_fighter1.permission_to_fire then
M01_group.heli_fighter1.thread = thread_new("m01_fly_direct_thread", group_table.vehicle, "battle_attack_point<001>", 10.0)
while get_dist(group_table.vehicle, "battle_attack_point<001>") > 5.0 do
thread_yield()
end
end
-- Rockets in center
if M01_group.heli_fighter1.permission_to_fire then
helicopter_shoot_navpoint(group_table.vehicle, "battle_rocket_target<001>", alt_fire)
delay(missle_delay)
helicopter_shoot_navpoint(group_table.vehicle, "battle_rocket_target<002>", alt_fire)
delay(missle_delay)
helicopter_shoot_navpoint(group_table.vehicle, "battle_rocket_target<004>", alt_fire)
delay(missle_delay)
helicopter_shoot_navpoint(group_table.vehicle, "battle_rocket_target<003>", alt_fire)
delay(attack_delay)
end
if M01_group.heli_fighter1.permission_to_fire then
M01_group.heli_fighter1.thread = thread_new("m01_fly_direct_thread", group_table.vehicle, "battle_retreat_point", 8.0)
while get_dist(group_table.vehicle, "battle_retreat_point") > 5.0 do
thread_yield()
end
delay(attack_delay)
end
end
end
-- Send the heli fighter on an attack run
--
-- group_table: (table) information about the attack heli
-- attack_run: (table) information about the attack run
--
function m01_fighter_attack_run_thread( group_table, attack_run )
M01_fighter_run_complete = false
-- fly this path
group_table.thread = thread_new("m01_fly_direct_thread", group_table.vehicle, attack_run.enter_path, 30.0)
-- get kinda close
while get_dist(group_table.vehicle, attack_run.float_from_nav) > 15.0 do
thread_yield()
end
-- target the fighter and tell the player
marker_add(group_table.vehicle, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL)
objective_text( 0, "M01_KILL_CHOPPER", "", "", SYNC_ALL, OI_ASSET_KILL )
-- focus on the player
local path_orient = HELI_PF_FACE_TARGET -- front face target
helicopter_set_path_orientation( group_table.vehicle, path_orient, LOCAL_PLAYER)
-- until you are close to this navpoint or thread complete
while (not thread_check_done(group_table.thread)) or get_dist(group_table.vehicle, attack_run.float_from_nav) > 5.0 do
thread_yield()
end
-- move to this navpoint
group_table.thread = thread_new("m01_fly_direct_thread", group_table.vehicle, attack_run.float_to_nav, attack_run.float_speed)
-- short pause
delay(0.5)
npc_combat_enable(group_table.members[1], true)
npc_combat_enable(group_table.members[2], true)
-- shoot here
m01_heli_shoot_gun_at_nav(group_table.vehicle, attack_run.gun_target, attack_run.gun_time)
delay(0.2)
audio_play_persona_line(M01_group.heli_fighter1.members[1], attack_run.persona_line)
npc_combat_enable(group_table.members[1], false)
npc_combat_enable(group_table.members[2], false)
-- get this close
while get_dist(group_table.vehicle, attack_run.float_to_nav) > 1.0 do
thread_yield()
end
-- fire some missles at the pilot
m01_fighter_shoot_vault(attack_run.hit_delay)
-- take the exit path
M01_fighter_run_complete = true
-- back to old objective
marker_remove(group_table.vehicle)
turn_invulnerable(group_table.vehicle)
objective_text( 0, "m01_survive", "", "", SYNC_ALL, OI_ASSET_DEFEND )
-- get out of here
path_orient = HELI_PF_FACE_ALONG_PATH -- back to normal
helicopter_set_path_orientation(group_table.vehicle, path_orient)
group_table.thread = thread_new("m01_fly_direct_thread", group_table.vehicle, attack_run.exit_path, 30.0)
end
-- Let the attack heli attack in little chunks
--
-- group_table: (table) information about the attack heli
--
function m01_attack_heli_gunner_thread( group_table )
-- nobody in the heli attacks...yet
npc_combat_enable(group_table.members[1], false)
npc_combat_enable(group_table.members[2], false)
while true do
while not group_table.permission_to_fire do
thread_yield()
end
while get_dist(group_table.vehicle, group_table.final_nav[2]) > 5.0 do
thread_yield()
end
local path_orient = HELI_PF_FACE_TARGET -- front face target
helicopter_set_path_orientation( group_table.vehicle, path_orient, LOCAL_PLAYER)
if group_table.permission_to_fire then
-- as soon as we are released, take a few shots
npc_combat_enable(group_table.members[1], true)
npc_combat_enable(group_table.members[2], true)
-- target the player
ai_add_enemy_target(group_table.members[1], LOCAL_PLAYER, ATTACK_NOW_NEVER_LOSE, true)
ai_add_enemy_target(group_table.members[2], LOCAL_PLAYER, ATTACK_NOW_NEVER_LOSE, true)
end
if group_table.permission_to_fire then
-- fire for a few seconds
delay(1.0)
end
-- stop
npc_combat_enable(group_table.members[1], false)
npc_combat_enable(group_table.members[2], false)
if group_table.permission_to_fire then
-- move here
group_table.thread = thread_new("m01_fly_direct_thread", group_table.vehicle, group_table.final_nav[1], 2.0 )
end
if group_table.permission_to_fire then
-- shoot a bit more
npc_combat_enable(group_table.members[1], true)
npc_combat_enable(group_table.members[2], true)
-- target the player
ai_add_enemy_target(group_table.members[1], LOCAL_PLAYER, ATTACK_NOW_NEVER_LOSE, true)
ai_add_enemy_target(group_table.members[2], LOCAL_PLAYER, ATTACK_NOW_NEVER_LOSE, true)
end
if group_table.permission_to_fire then
-- fire for a few seconds
delay(1.5)
end
-- stop
npc_combat_enable(group_table.members[1], false)
npc_combat_enable(group_table.members[2], false)
delay(2.0)
if group_table.permission_to_fire then
-- go back
group_table.thread = thread_new("m01_fly_direct_thread", group_table.vehicle, group_table.final_nav[2], 1.0 )
end
-- cooldown
delay(3.0)
end
end
-- Handle Shanundi getting attacked
--
function m01_shaundi_attacked_thread()
-- we are not ready
M01_shaundi_attack.in_place = false
-- setup trigger
M01_trigger.shaundi_attack.hit = false
m01_set_trigger(M01_trigger.shaundi_attack.name, "m01_attack_shaundi_cb")
-- wait for freerun trigger hit
while not M01_trigger.freerun.hit do
thread_yield()
end
-- tell shaundi to get to her location
local should_run = true
local should_fire = false
ai_do_scripted_move(M01_shaundi, M01_shaundi_attack.shuandi_nav, should_run, should_fire)
while not ai_scripted_action_is_complete(M01_shaundi) do
thread_yield()
end
-- did we beat the player upstairs?
if M01_trigger.shaundi_attack.hit then
return -- missed it
end
set_ignore_ai_flag(M01_shaundi, true)
-- exactly in place (out of sight)
teleport(M01_shaundi, M01_shaundi_attack.shuandi_nav, false)
M01_shaundi_attack.in_place = true
-- spin until trigger is hit
while not M01_trigger.shaundi_attack.hit do
thread_yield()
end
-- double make sure Shaundi is in place (grr)
teleport(M01_shaundi, M01_shaundi_attack.shuandi_attack, false)
-- make dude invulnerable because we don't want Shaundi playing half an animation
turn_invulnerable(M01_shaundi_attack.attacker)
-- play animation at the navpoint
action_play_synced(M01_shaundi, M01_shaundi_attack.attacker, "Shaundi Attacked", M01_shaundi_attack.shuandi_attack)
turn_vulnerable(M01_shaundi_attack.attacker)
character_kill(M01_shaundi_attack.attacker)
-- free to do stuff again
set_ignore_ai_flag(M01_shaundi, false)
-- clear me out
M01_shaundi_attack.thread = INVALID_THREAD_HANDLE
end
-- retry pathfind until you get close
--
-- name: (string) name of npc to move
-- navpoint: (string) name of navpoint to go to
--
function m01_have_to_get_there_thread(name, navpoint)
local close = false
local should_run = true
local should_fire = false
while not close do
-- call scripted move
ai_do_scripted_move(name, navpoint, should_run, should_fire)
thread_yield()
while not ai_scripted_action_is_complete(name) do
thread_yield()
end
-- are we close?
close = (get_dist(name, navpoint) < 2.0)
end
end
-- Josh runs upstairs and is out of breath
--
function m01_josh_run_upstairs()
follower_make_independent(M01_josh, true)
ai_clear_scripted_action(M01_josh)
character_prevent_flinching(M01_josh, true)
set_always_cower_flag(M01_josh, false)
-- Josh runs upstairs and Shaundi will go after him?
override_npc_run_and_cower_run(M01_josh, "Cower Run", "Cower Run")
m01_have_to_get_there_thread(M01_josh, M01_shaundi_attack.josh_nav)
-- turn off AI and do out of breath thing
set_ignore_ai_flag( M01_josh, true )
delay(0.5)
set_animation_state(M01_josh, "Josh Winded")
character_prevent_flinching(M01_josh, false)
end
-- Josh goes to a navpoint by saints fan and waits
--
function m01_josh_to_autograph()
follower_make_independent(M01_josh, true)
ai_clear_scripted_action(M01_josh)
clear_animation_state(M01_josh)
set_always_cower_flag(M01_josh, false)
m01_have_to_get_there_thread(M01_josh, M01_group.autograph.josh_nav)
-- er...do something
npc_leash_to_nav( M01_josh, M01_group.autograph.josh_nav, 2.0 )
end
-- Josh moves up to offer his autograph
function m01_josh_to_autograph2()
-- make sure
follower_make_independent(M01_josh, true)
ai_clear_scripted_action(M01_josh)
clear_animation_state(M01_josh)
set_always_cower_flag(M01_josh, false)
-- Josh wants to sign some breasts
if get_dist(M01_josh, M01_group.autograph.josh_nav) < 3.0 then
delay(3.0)
end
ai_clear_scripted_action(M01_josh)
npc_leash_remove(M01_josh)
-- walk a little closer
local should_run = false
local should_fire = false
-- if he's not close, book it!
if get_dist(M01_josh, M01_group.autograph.josh_close_nav) > 3.0 then
m01_have_to_get_there_thread(M01_josh, M01_group.autograph.josh_close_nav)
else
ai_do_scripted_move(M01_josh, M01_group.autograph.josh_close_nav, should_run, should_fire)
thread_yield()
--inv_item_equip(nil, M01_josh)
while not ai_scripted_action_is_complete(M01_josh) do
thread_yield()
end
end
-- do talking state
--while true do
if not check_animation_state(M01_josh, "talk stand") then
set_animation_state(M01_josh, "talk stand")
end
thread_yield()
--end
local anim_name = "Insult M"
local morph_name = "Insult M"
local force_play = false
local percentage = 1.0
local stand_still = true
local zero_movement = true
action_play(M01_josh, anim_name, morph_name, force_play, percentage, stand_still, zero_movement)
-- react Avoid Person
while M01_doing_autograph do
thread_yield()
end
-- exit
clear_animation_state(M01_josh)
character_prevent_flinching(M01_josh, false)
character_prevent_flinching(M01_shaundi, false)
end
-- Josh in an endless cower
function m01_josh_just_cower_thread()
-- cower until this thread is killed
while true do
if not check_animation_state(M01_josh, "Cower Stand") then
set_animation_state(M01_josh, "Cower Stand")
end
thread_yield()
end
end
-- Josh is a dumbass. This thread says so.
--
function m01_josh_is_dumbass_thread()
M01_josh_grandstanded = false
-- don't do anything while we don't have Josh
while M01_josh == "" do
thread_yield()
end
set_cant_cower_flag(M01_josh, false)
set_cant_flee_flag(M01_josh, true)
-- don't exactly follow the player
follower_make_independent(M01_josh, true)
-- start Josh in a cower
ai_clear_scripted_action(M01_josh)
--set_always_cower_flag(M01_josh, true)
set_ignore_ai_flag( M01_josh, true )
-- need to make sure he's active before doing the next parts
while not character_is_ready(M01_josh) do
thread_yield()
end
set_animation_state(M01_josh, "Cower Stand")
-- make sure targets are set
while (Num_enemies_alive < 2) do
thread_yield()
if not check_animation_state(M01_josh, "Cower Stand") then
set_animation_state(M01_josh, "Cower Stand")
end
end
-- wait until Gat starts interrogation
while (Num_enemies_alive > 1) do
thread_yield()
if not check_animation_state(M01_josh, "Cower Stand") then
set_animation_state(M01_josh, "Cower Stand")
end
end
set_ignore_ai_flag( M01_josh, false )
clear_animation_state(M01_josh)
set_always_cower_flag(M01_josh, false)
ai_clear_scripted_action(M01_josh)
ai_set_personality(M01_josh, "gang offensive")
thread_yield()
-- get by the door
local should_run = true
local should_fire = false
ai_do_scripted_move(M01_josh, "lobby_mark 001", should_run, should_fire)
-- wait until Gat kills the guard
while not M01_guard_killed do
thread_yield()
end
-- "oh my god"...move along
-- Get into door bashing position
m01_have_to_get_there_thread(M01_josh, M01_grandstand_nav)
-- wait for Gat to get into his position
while not M01_gat_at_door do
thread_yield()
end
-- show awesome
--audio_play_persona_line(M01_josh, "M01_Josh_Grandstanding_01")
M01_convo.berate_josh.handle = audio_conversation_load(M01_convo.berate_josh.name)
M01_conversation_playing = true
audio_conversation_play(M01_convo.berate_josh.handle)
delay(2.5)
-- turn AI off while we do the action
set_ignore_ai_flag( M01_josh, true )
-- tell npc to play action at navpoint (sliding into place as necessary)
local anim_name = "Josh Door Fail"
local morph_name = "Josh Door Fail"
local force_play = false
local percentage = 0.2
local stand_still = true
local zero_movement = true
action_play(M01_josh, anim_name, morph_name, force_play, percentage, stand_still, zero_movement, M01_grandstand_nav)
-- cue guards to open the door
M01_josh_grandstanded = true
audio_conversation_wait_for_end(M01_convo.berate_josh.handle)
M01_convo.berate_josh.handle = INVALID_CONVERSATION_HANDLE
M01_conversation_playing = false
-- finish animation
percentage = 1.0
repeat
thread_yield()
until action_play_is_finished(M01_josh, percentage)
set_ignore_ai_flag( M01_josh, false )
-- get out of the way
ai_do_scripted_move(M01_josh, "josh_lobby2", should_run, should_fire)
while not ai_scripted_action_is_complete(M01_josh) do
thread_yield()
end
m01_josh_just_cower_thread()
end
-- Start setting up the player for the vault sequence
function m01_vault_setup_part1_thread()
-- need these guys
group_create_hidden(M01_group.vault_attackers2.name)
-- piss some of them off (don't waste time for all of them)
ai_add_enemy_target(M01_group.vault_attackers2.members[1], M01_group.vault_attackers2.gat, ATTACK_NOW_NEVER_LOSE, true)
ai_add_enemy_target(M01_group.vault_attackers2.members[2], M01_group.vault_attackers2.shaundi, ATTACK_NOW_NEVER_LOSE, true)
ai_add_enemy_target(M01_group.vault_attackers2.gat, M01_group.vault_attackers2.members[1], ATTACK_NOW_NEVER_LOSE, true)
ai_add_enemy_target(M01_group.vault_attackers2.shaundi, M01_group.vault_attackers2.members[2], ATTACK_NOW_NEVER_LOSE, true)
-- please don't get thrown on the vault...please don't get thrown on the vault...
character_prevent_explosion_fling(M01_group.vault_attackers2.gat, true)
character_prevent_explosion_fling(M01_group.vault_attackers2.shaundi, true)
character_allow_ragdoll(M01_group.vault_attackers2.gat, false)
character_allow_ragdoll(M01_group.vault_attackers2.shaundi, false)
-- remove the old loadout (if valid)
m01_clear_player_loadout()
-- start with a hidden vault
group_create_hidden(M01_group.vault_heli.name, true)
-- disable physics (wait until it works)
while not vehicle_enable_physics(M01_group.vault_heli.vehicle, false) do
thread_yield()
end
-- add one pilot
vehicle_enter_group_teleport(M01_group.vault_heli.pilot, M01_group.vault_heli.vehicle)
-- prep conversations for the vault
persona_override_persona_start(M01_group.vault_heli.pilot, "Interrogation")
end
-- Finish setup for the player on the vault
function m01_vault_setup_part2_thread()
group_show(M01_group.vault_attackers2.name)
group_show(M01_group.vault_heli.name)
m01_players_start_vault_health()
-- hide the static vault
mesh_mover_hide(M01_vault_mover)
-- restrict camera before fading back
-- limit to what we want you to look at only
local look_here_pitch = 20.0 -- will remove this restriction when player has control
camera_restrict_set_limits( look_here_pitch, look_here_pitch, 0.0, 0.0 )
camera_restrict_target_object(CAMERA_TARGET3) -- target we will rise to
camera_restrict_set_active(ENABLE)
-- put it in position
teleport_vehicle(M01_group.vault_heli.vehicle, M01_group.vault_heli.nav)
-- disable physics...again
while not vehicle_enable_physics(M01_group.vault_heli.vehicle, false) do
thread_yield()
end
-- put the player in
local block = true
local local_seat = 1
local remote_seat = 2
if M01_swap_vault_seats then
local_seat = 2
remote_seat = 1
end
while not vehicle_enter_teleport(LOCAL_PLAYER, M01_group.vault_heli.vehicle, local_seat, block) do
thread_yield()
end
set_player_can_enter_exit_vehicles(LOCAL_PLAYER, false)
if ( coop_is_active() ) then
while not vehicle_enter_teleport(REMOTE_PLAYER, M01_group.vault_heli.vehicle, remote_seat, block) do
thread_yield()
end
set_player_can_enter_exit_vehicles(REMOTE_PLAYER, false)
-- make sure the player gets in
while(not character_is_in_vehicle(REMOTE_PLAYER, M01_group.vault_heli.vehicle)) do
thread_yield()
end
end
-- make sure the player gets in
while(not character_is_in_vehicle(LOCAL_PLAYER, M01_group.vault_heli.vehicle)) do
thread_yield()
end
-- make sure we know what loadout we have
m01_set_player_loadout()
-- only smg for this ride
inv_weapon_disable_all_but_this_slot( WEAPON_SLOT_RIFLE )
action_sequence_setup(VAULT_SEQUENCE, M01_group.vault_heli.vehicle)
-- hook in special sounds
vault_heli_hack_for_m01(M01_group.vault_heli.vehicle)
-- attackers move out
local should_run = true
local should_fire = false
for i,attacker in pairs(M01_group.vault_attackers2.members) do
ai_do_scripted_move(attacker, M01_group.vault_attackers2.navs[i], should_run, should_fire)
ai_add_enemy_target(M01_group.vault_attackers2.gat, attacker, ATTACK_NOW_NEVER_LOSE, false)
ai_add_enemy_target(M01_group.vault_attackers2.shaundi, attacker, ATTACK_NOW_NEVER_LOSE, false)
end
thread_yield() -- wait at least 1 frame
M01_thread.conversation = thread_new("m01_vault_convo_thread")
end
-- Prep everything for the vault sequence that is not directly involving the player
--
function m01_vault_environ_setup_thread()
m01_start_respawn_pairs()
-- helicopters
M01_group.heli_police1.setup_thread = thread_new("m01_spawn_and_float_heli_thread", M01_group.heli_police1, POLICE_HELI_WAIT_LOCATION2)
M01_group.heli_police2.setup_thread = thread_new("m01_spawn_and_float_heli_thread", M01_group.heli_police2, POLICE_HELI2_START)
-- we may have already created this
if not group_is_loaded(M01_group.heli_fighter1.name) then
group_create(M01_group.heli_fighter1.name, true)
-- don't take explosion damage
vehicle_set_explosion_damage_multiplier(M01_group.heli_fighter1.vehicle, 0.0)
vehicle_prevent_explosion_fling(M01_group.heli_fighter1.vehicle, true)
vehicle_enter_group_teleport(M01_group.heli_fighter1.members, M01_group.heli_fighter1.vehicle)
vehicle_suppress_npc_exit(M01_group.heli_fighter1.vehicle, true)
-- should be damaged
local total_hitpoints = get_max_hit_points(M01_group.heli_fighter1.vehicle)
set_current_hit_points(M01_group.heli_fighter1.vehicle, total_hitpoints * M01_group.heli_fighter1.damage1)
-- set hard limit on how much damage can be taken
set_min_hit_points(M01_group.heli_fighter1.vehicle, total_hitpoints * M01_group.heli_fighter1.damage2)
end
-- set a persona for bullhorn lines
persona_override_persona_start(M01_group.heli_fighter1.members[1], "Interrogation")
-- just in case
vehicle_show(M01_group.heli_fighter1.vehicle)
-- don't fire rockets into the back of the building
npc_combat_enable(M01_group.heli_fighter1.members[1], false)
npc_combat_enable(M01_group.heli_fighter1.members[2], false)
m01_float_heli(M01_group.heli_fighter1, M01_group.heli_fighter1.first_float)
M01_group.transport1.setup_thread = thread_new("m01_setup_transport_thread", M01_group.transport1)
M01_group.transport2.setup_thread = thread_new("m01_setup_transport_thread", M01_group.transport2)
M01_group.transport3.setup_thread = thread_new("m01_setup_transport_thread", M01_group.transport3)
-- let's not see that
m01_transport_show(M01_group.transport1, false)
end