--[[
m09.lua
SR3 Mission Script
DATE: 09-22-2010
AUTHOR: Neil Ryan and Craig Williams
]]--
-- Debug flags --
M09_enable_binks = true
M09_debug_skip_to_heli_scene = false
-- Tweakable Parameters --
M09_give_rocket_launcher = true
M09_continuous_respawn_delay = 10.0 -- time in seconds before a continuous spawn group respawns
M09_delay_between_boats = 2.0
M09_boat_is_close = 7.0
M09_max_player_dist_from_boat =140.0
M09_cargo_ship_camera_shake = "cargo_plane_interior"
M09_cargo_ship_camera_shake_amt = 0.4
M09_chase_boat_min_dist_to_player = 30.0
M09_chase_boat_slow_speed = 20.0
M09_dead_boat_release_delay = 5.0 -- How long after a ho boat attacker boat is destroyed should we wait before releasing it?
M09_min_notoriety = 3 -- Actual notoriety range to use when driving to the Saints HQ or Brothel
M09_max_notoriety = 3
-- Audio emitters --
M09_audio_emitters = {
girls_1 = "Container_Stripper<001>",
girls_2 = "Container_Stripper<002>",
girls_3 = "Container_Stripper<003>",
girls_4 = "Container_Stripper<004>",
brute_1 = "Container_Brute<001>",
brute_2 = "Container_Brute<002>",
}
-- Navpoints --
M09_nav = {
zimos_girls = {
"zimos_nav 1", "zimos_nav 2", "zimos_nav 3",
},
boat_advance_positions = { "boat_advance_pos 001", "boat_advance_pos 002", },
choice_saints_hq = {
host = "nav_hq_host",
client = "nav_hq_client",
},
choice_brothel = {
host = "nav_brothel_host",
client = "nav_brothel_client",
},
}
M09_boat_paths = {
north = {
boat_paths = {"north_boat_path 001", "north_boat_path 002", "north_boat_path 003", },
approach_path = "north_boat_approach",
boat_holding_path = "north_boat_holding_loop",
jetski_holding_path = "north_jetski_holding_loop",
drive_back = {"north_boat_drive_back_path 001", },
boat_stop = "north_boat_stairs_dest 001",
boat_abandon_stop = "north_boat_stairs_dest 002",
stairs_nav = "Boat_stairs_front 001",
upstairs = "Boat_front_upstairs",
},
south = {
boat_paths = {"south_boat_path 001", "south_boat_path 002", "south_boat_path 003", },
approach_path = "south_boat_approach",
boat_holding_path = "south_boat_holding_loop",
jetski_holding_path = "south_jetski_holding_loop",
drive_back = {"south_boat_drive_back_path 001" },
boat_stop = "south_boat_stairs_dest 001",
boat_abandon_stop = "south_boat_stairs_dest 002",
stairs_nav = "Boat_stairs_rear 001",
upstairs = "Boat_rear_upstairs",
},
}
-- Groups --
M09_group = {
local_start_vehicle = {
name = "local_start_vehicle_group",
members = {},
vehicle = "start_vehicle 001",
},
remote_start_vehicle = {
name = "remote_start_vehicle_group",
members = {},
vehicle = "start_vehicle 002",
},
girls1 = {
name = "girls_group 001",
members = { "girl 001", "girl 002",}
},
girls2 = {
name = "girls_group 002",
members = { "girl 003", "girl 004",}
},
girls3 = {
name = "girls_group 003",
members = { "girl 005", "girl 006",}
},
girls4 = {
name = "girls_group 004",
members = { "girl 007", "girl 008",}
},
girls_in_heli_crate = {
name = "girls_in_heli_crate_group",
members = { "girl_in_heli_crate 001", "girl_in_heli_crate 002", "girl_in_heli_crate 003", "girl_in_heli_crate 004",
"girl_in_heli_crate 005", "girl_in_heli_crate 006", "girl_in_heli_crate 007", "girl_in_heli_crate 008", }
},
brute1 = {
name = "Brute_group 001",
members = { "Brute 001" }
},
minigun_brute = {
name = "Minigun_Brute_group 001",
members = { "Minigun_Brute 001" }
},
weapons = {
name = "weapon_group",
},
ammo_crate_smg = {
name = "Weapon_Pickup_SMG",
},
ammo_crate_grenades = {
name = "Weapon_Pickup_Grenades",
},
ammo_crate_rpg = {
name = "Weapon_Pickup_RPG",
},
-- guards waiting on the boat
boat_guards = {
name = "boat_guards",
members = { "boat_guard 001", "boat_guard 002", "boat_guard 003", "boat_guard 004", "boat_guard 005", "boat_guard 006", }
},
-- Helicopters that orbit the ho boat.
attack_heli_01 = {
name = "attack_heli_group 001",
vehicle = "attack_heli <001>",
pilot = "attack_heli_pilot <001>",
gunner = "attack_heli_gunner <001>",
approach_path = "attack_heli_approach <001>",
orbit_path = "attack_heli_orbit <001>",
orbit_speed = 7,
thread = INVALID_THREAD_HANDLE,
},
attack_heli_02 = {
name = "attack_heli_group 002",
vehicle = "attack_heli <002>",
pilot = "attack_heli_pilot <002>",
gunner = "attack_heli_gunner <002>",
approach_path = "attack_heli_approach <002>",
orbit_path = "attack_heli_orbit <002>",
orbit_speed = 12,
thread = INVALID_THREAD_HANDLE,
},
-- Transport helicopters that attack the ho boat.
attack_transport_01 = {
name = "transport_heli_group 001",
vehicle = "transport_heli <001>",
pilot = "trans_heli_npc_1<1>",
approach_path = "trans_heli_north_path",
land_path = "trans_heli_north_land_path",
exit_path = "trans_heli_north_exit_path",
thread = INVALID_THREAD_HANDLE,
debug_done = false,
},
attack_transport_soldiers_01 = {
name = "transport_soldiers 001",
members = { "trans_heli_npc_1<2>", "trans_heli_npc_1<3>", "trans_heli_npc_1<4>", "trans_heli_npc_1<5>" },
},
attack_transport_02 = {
name = "transport_heli_group 002",
vehicle = "transport_heli <002>",
pilot = "trans_heli_npc_2<1>",
approach_path = "trans_heli_center_path",
land_path = "trans_heli_center_land_path",
exit_path = "trans_heli_center_exit_path",
thread = INVALID_THREAD_HANDLE,
debug_done = false,
},
attack_transport_soldiers_02 = {
name = "transport_soldiers 002",
members = { "trans_heli_npc_2<2>", "trans_heli_npc_2<3>", "trans_heli_npc_2<4>", "trans_heli_npc_2<5>" },
},
attack_transport_03 = {
name = "transport_heli_group 003",
vehicle = "transport_heli <003>",
pilot = "trans_heli_npc_3<1>",
approach_path = "trans_heli_south_path",
land_path = "trans_heli_south_land_path",
exit_path = "trans_heli_south_exit_path",
thread = INVALID_THREAD_HANDLE,
debug_done = false,
},
attack_transport_soldiers_03 = {
name = "transport_soldiers 003",
members = { "trans_heli_npc_3<2>", "trans_heli_npc_3<3>", "trans_heli_npc_3<4>", "trans_heli_npc_3<5>" },
},
-- four seater
boat1 = {
name = "Boat_group 001",
drive_boat_back = true,
is_jetski = false,
is_docking = false,
members = { "Boat1_attacker 001", "Boat1_attacker 002", "Boat1_attacker 003", "Boat1_attacker 004" },
vehicle = "Attack_boat 001",
thread = INVALID_THREAD_HANDLE,
pathfind_thread = INVALID_THREAD_HANDLE,
},
-- four seater
boat2 = {
name = "Boat_group 002",
drive_boat_back = true,
is_jetski = false,
is_docking = false,
members = { "Boat2_attacker 001", "Boat2_attacker 002", "Boat2_attacker 003", "Boat2_attacker 004" },
vehicle = "Attack_boat 002",
thread = INVALID_THREAD_HANDLE,
pathfind_thread = INVALID_THREAD_HANDLE,
},
-- two seater
boat3 = {
name = "Boat_group 003",
drive_boat_back = false,
is_jetski = true,
is_docking = false,
members = { "Boat3_attacker 001", "Boat3_attacker 002" },
vehicle = "Attack_boat 003",
thread = INVALID_THREAD_HANDLE,
pathfind_thread = INVALID_THREAD_HANDLE,
},
-- two seater
boat4 = {
name = "Boat_group 004",
drive_boat_back = false,
is_jetski = true,
is_docking = false,
members = { "Boat4_attacker 001", "Boat4_attacker 002" },
vehicle = "Attack_boat 004",
thread = INVALID_THREAD_HANDLE,
pathfind_thread = INVALID_THREAD_HANDLE,
},
-- four seater
boat5 = {
name = "Boat_group 005",
drive_boat_back = true,
is_jetski = false,
is_docking = false,
members = { "Boat5_attacker 001", "Boat5_attacker 002", "Boat5_attacker 003", "Boat5_attacker 004" },
vehicle = "Attack_boat 005",
thread = INVALID_THREAD_HANDLE,
pathfind_thread = INVALID_THREAD_HANDLE,
},
player_pickup = {
name = "Player_pickup_heli_group",
pilot = "Player_pickup_heli_pilot",
vehicle = "Player_pickup_heli",
float_nav = "Player_pickup_heli_start",
path = {{path = "Player_pickup_path", speed = 40.0},},
thread = INVALID_THREAD_HANDLE,
},
girls_pickup = {
name = "Girls_pickup_heli_group",
pilot = "Girls_pickup_heli_pilot",
vehicle = "Girls_pickup_heli",
float_nav = "Girls_pickup_heli_start",
path = {{path = "Girls_float_nav", speed = 40.0},},
thread = INVALID_THREAD_HANDLE,
},
player_rail = {
name = "heli_rail_group",
pilot = "player_pilot",
vehicle = "rail_heli",
path = "Player_heli_route",
start = "Player_pickup_heli_end",
pause_nav = "Player_heli_pause_nav",
},
girls_heli = {
name = "Girls_heli_group",
pilot = "Girls_heli_pilot",
vehicle = "Girls_heli",
float_nav = "Girls_float_nav",
pause_nav = "Girls_float_nav_2",
path = {
{path = "Girls_heli_route 001 a", speed = 15.5},
{path = "Girls_heli_route 001 b", speed = 11.0},
{path = "Girls_heli_route 001 c", speed = 12.0},
{path = "Girls_heli_route 001 d", speed = 19.0},
{path = "Girls_heli_route 002 a", speed = 16.0},
{path = "Girls_heli_route 002 a2", speed = 12.0},
{path = "Girls_heli_route 002 b", speed = 12.0},
{path = "Girls_heli_route 002 c", speed = 9.0},
{path = "Girls_heli_route 002 c2", speed = 6.0},
{path = "Girls_heli_route 002 c3", speed = 6.0},
{path = "Girls_heli_route 002 d", speed = 10.0},
{path = "Girls_heli_route 002 e", speed = 15.0},
{path = "Girls_heli_route 002 f", speed = 12.5},
--[[
{path = "Girls_heli_route 003 a", speed = 11.0},
{path = "Girls_heli_route 003 b", speed = 2.0},
{path = "Girls_heli_route 003 c", speed = 17.0},
{path = "Girls_heli_route 003 d", speed = 11.0},
{path = "Girls_heli_route 004", speed = 12.0},
--]]
},
thread = INVALID_THREAD_HANDLE,
},
girls_truck = {
name = "girls_truck_group",
vehicle = "girls_truck"
},
-- homies
start_homies = {
name = "homies_start",
zimos = "zimos_start"
},
gangway_homies = {
name = "homies_gangway",
zimos = "zimos_gangway"
},
-- Rail lookat groups
player_lookat_1 = {
name = "player_lookat_group_1",
spawned = false,
members = {"Player_route_lookat_1", }
},
-- Roof Groups
roof1 = {
name = "roof_group 001",
spawned = false,
members = { --[["roof_npc 001",--]] "roof_npc 001<001>", "roof_npc 001<002>", "roof_npc 001<003>", "roof_npc 001<004>", "roof_npc 001<005>", "roof_npc 001<067>", "roof_npc 001<068>",
"roof_npc 001<069>", "roof_npc 001<070>", "roof_npc 001<071>", "roof_npc 001<072>", "roof_npc 001<073>", "roof_npc 001<074>", "roof_npc 001<075>",
"roof_npc 001<076>", "roof_npc 001<077>", }
},
roof2 = {
name = "roof_group 002",
spawned = false,
members = { "roof_npc 001<006>", "roof_npc 001<007>", "roof_npc 001<008>", "roof_npc 001<009>", "roof_npc 001<010>", "roof_npc 001<011>", "roof_npc 001<012>", }
},
roof3 = {
name = "roof_group 003",
spawned = false,
members = { "roof_npc 001<013>", "roof_npc 001<014>", "roof_npc 001<015>", "roof_npc 001<016>", "roof_npc 001<017>", }
},
roof4 = {
name = "roof_group 004",
spawned = false,
members = { "roof_npc 001<018>", "roof_npc 001<019>", "roof_npc 001<020>", "roof_npc 001<021>", "roof_npc 001<022>", "roof_npc 001<023>", "roof_npc 001<060>", }
},
roof5 = {
name = "roof_group 005",
spawned = false,
members = { "roof_npc 001<024>", "roof_npc 001<025>", "roof_npc 001<026>", "roof_npc 001<027>", "roof_npc 001<028>", "roof_npc 001<029>",
"roof_npc 001<030>", "roof_npc 001<031>", "roof_npc 001<032>", "roof_npc 001<033>", }
},
roof6 = {
name = "roof_group 006",
spawned = false,
members = { "roof_npc 001<034>", "roof_npc 001<035>", "roof_npc 001<036>", "roof_npc 001<037>", "roof_npc 001<038>", "roof_npc 001<039>",
"roof_npc 001<040>", "roof_npc 001<041>", "roof_npc 001<042>", "roof_npc 001<043>", "roof_npc 001<044>", "roof_npc 001<045>",
"roof_npc 001<046>", "roof_npc 001<047>", "roof_npc 001<048>", "roof_npc 001<049>", "roof_npc 001<050>", }
},
roof7 = {
name = "roof_group 007",
spawned = false,
members = { "roof_npc 001<051>", "roof_npc 001<052>", "roof_npc 001<053>", "roof_npc 001<054>", "roof_npc 001<055>", "roof_npc 001<056>",
"roof_npc 001<057>", "roof_npc 001<058>", "roof_npc 001<059>", }
},
-- Murderbrawl roof
roof_mb = {
name = "roof_mb_group",
spawned = false,
members = { "roof_mb_npc <001>", "roof_mb_npc <002>", "roof_mb_npc <003>", "roof_mb_npc <004>", "roof_mb_npc <005>", "roof_mb_npc <006>",
"roof_mb_npc <007>", "roof_mb_npc <008>", "roof_mb_npc <009>", "roof_mb_npc <010>", "roof_mb_npc <011>", }
},
-- Rail sequence boats
heli_boats = {
name = "heli_boat_group",
spawned = false,
speed = 37.0,
start_ai_disabled = true,
vehicles = {
{
vehicle = "heli_boat <001>",
members = {"heli_boat_npc <002>", "heli_boat_npc <004>",},
path = {"heli_boat_path <001>", "river_chase_path 1", },
pathfind_thread = INVALID_THREAD_HANDLE,
},
{
vehicle = "heli_boat <002>",
members = {"heli_boat_npc <006>", "heli_boat_npc <008>",},
path = {"heli_boat_path <002>", "river_chase_path 2", },
pathfind_thread = INVALID_THREAD_HANDLE,
trailing_aim = true,
},--[[
{
vehicle = "heli_boat <003>",
members = {"heli_boat_npc <009>", "heli_boat_npc <010>", },
path = {"heli_boat_path <003>", "river_chase_path 2", },
pathfind_thread = INVALID_THREAD_HANDLE,
},--]]
{
vehicle = "heli_boat <004>",
members = {"heli_boat_npc <012>", "heli_boat_npc <014>",},
path = {"heli_boat_path <004>", "river_chase_path 2", },
pathfind_thread = INVALID_THREAD_HANDLE,
target_player = true,
},
{
vehicle = "heli_boat <005>",
members = {"heli_boat_npc <016>", "heli_boat_npc <018>",},
path = {"heli_boat_path <005>", "river_chase_path 1", },
pathfind_thread = INVALID_THREAD_HANDLE,
trailing_aim = true,
target_player = true,
},
},
},
heli_boats_2 = {
name = "heli_boat_group_2",
spawned = false,
speed = 37.0,
start_ai_disabled = true,
vehicles = {
{
vehicle = "heli_boat_2 1",
members = {"heli_boat_2_npc 02", "heli_boat_2_npc 04",},
path = {"heli_boat_2_path 1", "river_chase_path 1", },
pathfind_thread = INVALID_THREAD_HANDLE,
target_player = true,
},
{
vehicle = "heli_boat_2 2",
members = {"heli_boat_2_npc 06", "heli_boat_2_npc 08",},
path = {"heli_boat_2_path 2", "river_chase_path 3", },
pathfind_thread = INVALID_THREAD_HANDLE,
trailing_aim = true,
},
{
vehicle = "heli_boat_2 3",
members = {"heli_boat_2_npc 10", "heli_boat_2_npc 12",},
path = {"heli_boat_2_path 2", "river_chase_path 3", },
pathfind_thread = INVALID_THREAD_HANDLE,
trailing_aim = true,
target_player = true,
},
{
vehicle = "heli_boat_2 4",
members = {"heli_boat_2_npc 14", "heli_boat_2_npc 16",},
path = {"heli_boat_2_path 1", "river_chase_path 1", },
pathfind_thread = INVALID_THREAD_HANDLE,
target_player = true,
},
},
},
heli_boats_3 = {
name = "heli_boat_group_3",
spawned = false,
speed = 50.0,
start_ai_disabled = true,
thread_func = "m09_throttle_heli_boats",
thread = INVALID_THREAD_HANDLE,
vehicles = {
{
vehicle = "heli_boat_3 1",
members = {"heli_boat_3_npc 04", "heli_boat_3_npc 10",},
path = {"heli_boat_3_path 1", "river_chase_path 1", },
pathfind_thread = INVALID_THREAD_HANDLE,
target_player = true,
},
{
vehicle = "heli_boat_3 2",
members = {"heli_boat_3_npc 05", "heli_boat_3_npc 11",},
path = {"heli_boat_3_path 1", "river_chase_path 1", },
pathfind_thread = INVALID_THREAD_HANDLE,
trailing_aim = true,
target_player = true,
},
{
vehicle = "heli_boat_3 3",
members = {"heli_boat_3_npc 06", "heli_boat_3_npc 12",},
path = {"heli_boat_3_path 3", "river_chase_path 3", },
pathfind_thread = INVALID_THREAD_HANDLE,
},
{
vehicle = "heli_boat_3 4",
members = {"heli_boat_3_npc 16", "heli_boat_3_npc 22",},
path = {"heli_boat_3_path 2", "river_chase_path 2", },
pathfind_thread = INVALID_THREAD_HANDLE,
target_player = true,
},
{
vehicle = "heli_boat_3 5",
members = {"heli_boat_3_npc 17", "heli_boat_3_npc 23",},
path = {"heli_boat_3_path 2", "river_chase_path 2", },
pathfind_thread = INVALID_THREAD_HANDLE,
trailing_aim = true,
target_player = true,
},
{
vehicle = "heli_boat_3 6",
members = {"heli_boat_3_npc 18", "heli_boat_3_npc 24",},
path = {"heli_boat_3_path 3", "river_chase_path 3", },
pathfind_thread = INVALID_THREAD_HANDLE,
trailing_aim = true,
},
},
},
-- Rail sequence tank
heli_tank1 = {
name = "heli_tank_group 001",
spawned = false,
vehicles = {
{
vehicle = "heli_tank <001>",
members = {"heli_tank_npc <001>", "heli_tank_npc <002>",},
path = "tank_spline_1",
speed = 30,
pathfind_thread = INVALID_THREAD_HANDLE,
},
{
vehicle = "heli_tank <002>",
members = {"heli_tank_npc <003>", "heli_tank_npc <004>",},
path = "tank_spline_1",
speed = 30,
pathfind_thread = INVALID_THREAD_HANDLE,
},
{
vehicle = "heli_tank <003>",
members = {"heli_tank_npc <005>", "heli_tank_npc <006>",},
path = {"tank_spline_2", "tank_spline_1",},
speed = 30,
pathfind_thread = INVALID_THREAD_HANDLE,
},
{
vehicle = "heli_tank <006>",
--members = {"heli_tank_npc <009>", "heli_tank_npc <010>",},
gunner = "heli_tank_npc <009>",
path = "",
speed = 40,
pathfind_thread = INVALID_THREAD_HANDLE,
},
{
vehicle = "heli_tank <007>",
--members = {"heli_tank_npc <011>", "heli_tank_npc <012>",},
gunner = "heli_tank_npc <011>",
path = "",
speed = 40,
pathfind_thread = INVALID_THREAD_HANDLE,
},
{
vehicle = "heli_tank <008>",
--members = {"heli_tank_npc <013>", "heli_tank_npc <014>",},
gunner = "heli_tank_npc <013>",
path = "",
speed = 40,
pathfind_thread = INVALID_THREAD_HANDLE,
},
},
},
heli_tank2 = {
name = "heli_tank_group 002",
spawned = false,
vehicles = {
{
vehicle = "heli_tank <004>",
--members = {"heli_tank_npc <007>",},
gunner = "heli_tank_npc <007>",
path = "",
speed = 0,
pathfind_thread = INVALID_THREAD_HANDLE,
},
{
vehicle = "heli_tank <005>",
--members = {"heli_tank_npc <008>",},
gunner = "heli_tank_npc <008>",
path = "",
speed = 0,
pathfind_thread = INVALID_THREAD_HANDLE,
},
{
vehicle = "heli_tank <009>",
members = {"heli_tank_npc <015>", "heli_tank_npc <016>",},
path = "tank_spline_3",
speed = 15,
pathfind_thread = INVALID_THREAD_HANDLE,
},
},
},
cte_npc_group = {
name = "m09_cte_group",
},
}
M09_attack_helis = { M09_group.attack_heli_01, M09_group.attack_heli_02, }
M09_trans_attack_helis = {
{
heli_group = M09_group.attack_transport_01,
soldier_group = M09_group.attack_transport_soldiers_01,
},
{
heli_group = M09_group.attack_transport_02,
soldier_group = M09_group.attack_transport_soldiers_02,
},
{
heli_group = M09_group.attack_transport_03,
soldier_group = M09_group.attack_transport_soldiers_03
},
}
M09_boats = { M09_group.boat1, M09_group.boat2, M09_group.boat3, M09_group.boat4, M09_group.boat5 }
M09_boat_wave1 = { M09_group.boat5, M09_group.boat3, M09_group.boat4, M09_group.boat2, M09_group.boat1 }
M09_boat_wave2 = { M09_group.boat4, M09_group.boat5, M09_group.boat3, M09_group.boat2, M09_group.boat1 }
M09_boat_wave3 = { M09_group.boat2, M09_group.boat4, M09_group.boat1, M09_group.boat3, M09_group.boat5, }
M09_boat_wave4 = { M09_group.boat1, M09_group.boat5, M09_group.boat3, M09_group.boat2, M09_group.boat4, }
M09_spawn_regions = {
front = {"Front_Spawn_Region 001",},
}
M09_spawn_groups = {
normal = {"Continuous_spawn_group 001", "Continuous_spawn_group 002",},
snipers = {"Continuous_spawn_group 003",},
}
-- current homie
M09_Zimos = M09_group.start_homies.zimos
-- indexed table that gives order of segments to traverse
M09_player_rail_segments = {
{
path = "Player_route 001 a",
speed = 15.0,
stop_at_end = false,
end_callback = {
func = "m09_heli_face_target",
args = {
M09_group.player_rail.vehicle, M09_group.player_lookat_1.members[1]
},
},
},
{
path = "Player_route 001 b",
speed = 12.0,
stop_at_end = false,
end_callback = {
func = "m09_heli_stop_facing_target",
args = {
M09_group.player_rail.vehicle
},
},
},
{
path = "Player_route 002",
speed = 15.0,
stop_at_end = false,
},
{
path = "Player_route 003",
speed = 10.0,
stop_at_end = false,
end_callback = {
func = "m09_fire_scripted_rpg",
args = {
{
origin = "mb_script_rpg_1_origin",
target = "mb_script_rpg_1_target",
delay = 1.0,
},
{
origin = "mb_script_rpg_2_origin",
target = "mb_script_rpg_2_target",
delay = 0.2,
},
},
},
},
{
path = "Player_route 004",
speed = 16.0,
stop_at_end = false,
},
{
path = "Player_route 004 a",
speed = 6.5,
stop_at_end = false,
},
{
path = "Player_route 004 b",
speed = 13.0,
stop_at_end = false,
},
{
path = "Player_route 005",
speed = 23.0,
stop_at_end = false,
end_callback = {
func = "m09_wind_down_rail_music",
args = nil,
},
},
{
path = "Player_route 006",
speed = 12.0,
stop_at_end = true,
},
--[[
{
path = "Player_route 006 a",
speed = 08.0,
stop_at_end = false,
end_callback = {
func = "m09_fire_scripted_rpg",
args = {
{
origin = "pc_script_rpg_1_origin",
target = "pc_script_rpg_1_target",
delay = 0.0,
},
{
origin = "pc_script_rpg_2_origin",
target = "pc_script_rpg_2_target",
delay = 0.5,
},
{
origin = "pc_script_rpg_3_origin",
target = "pc_script_rpg_3_target",
delay = 1.0,
},
},
},
},
{
path = "Player_route 006 a<001>",
speed = 08.0,
stop_at_end = false,
},
{
path = "Player_route 006 b",
speed = 06.0,
stop_at_end = false,
},
{
path = "Player_route 007",
speed = 12.0,
stop_at_end = true,
},
{
path = "Player_route 008",
speed = 10.0,
stop_at_end = true,
},
{
path = "Player_route 009",
speed = 20.0,
stop_at_end = true,
},
--]]
}
-- Characters --
-- Vehicles --
-- Mesh Movers --
-- Text --
M09_objective = {
go_to_ship = {name = "M09_OBJ_GO_TO_SHIP", icon = OI_ASSET_LOCATION},
find_girls = {name = "M09_OBJ_FIND_THE_GIRLS", icon = OI_ASSET_USE},
wait_for_chopper = {name = "M09_OBJ_WAIT_FOR_CHOPPER", icon = OI_ASSET_INVALID},
jump_to_chopper = {name = "SH03_OBJ_ENTER_HELI", icon = OI_ASSET_LOCATION},
defend_heli = {name = "M09_OBJ_DEFEND_HELI", icon = OI_ASSET_DEFEND},
take_truck = {name = "M09_OBJ_GET_INTO_TRUCK", icon = OI_ASSET_USE},
choice = {name = "M09_OBJ_CHOICE", icon = OI_ASSET_LOCATION},
kill_guards = {name = "M09_OBJ_KILL_GUARDS", icon = OI_ASSET_KILL},
north_platform = {name = "M09_OBJ_NORTH_PLATFORM", icon = OI_ASSET_LOCATION},
clear_the_boat = {name = "M09_OBJ_KILL_ATTACKERS", icon = OI_ASSET_KILL},
south_platform = {name = "M09_OBJ_SOUTH_PLATFORM", icon = OI_ASSET_LOCATION},
to_hq = {name = "M09_OBJ_TO_SAINTS_HQ", icon = OI_ASSET_LOCATION},
to_brothel = {name = "M09_OBJ_TO_BROTHEL", icon = OI_ASSET_LOCATION},
}
-- Threads --
M09_zimos_girl_thread = INVALID_THREAD_HANDLE
M09_girls_follow_zimos_thread = INVALID_THREAD_HANDLE
M09_line_failsafe_thread = INVALID_THREAD_HANDLE
M09_get_to_south_platform_thread = INVALID_THREAD_HANDLE
M09_path_end_callback_thread = INVALID_THREAD_HANDLE
M09_delay_thread = INVALID_THREAD_HANDLE
M09_failsafe_thread = INVALID_THREAD_HANDLE
M09_zimos_comforting_hos_thread = INVALID_THREAD_HANDLE
-- Checkpoints --
M09_checkpoint = {
start = {
name = MISSION_START_CHECKPOINT,
nav1 = "start_nav 001",
nav2 = "start_nav 002"
},
gangway = {
name = "m09_checkpoint_gangway",
nav1 = "gangway_nav 001",
nav2 = "gangway_nav 002"
},
defend_girls = {
name = "m09_checkpoint_defend_girls",
nav1 = "Defend_girls_nav 001",
nav2 = "Defend_girls_nav 002",
},
heli_rail = {
name = "m09_checkpoint_heli_rail",
nav1 = "rail_heli_nav 001",
nav2 = "rail_heli_nav 002"
},
truck_route = {
name = "m09_checkpoint_truck_route",
nav1 = "truck_nav 001",
nav2 = "truck_nav 002",
},
}
-- Cutscenes --
CUTSCENE_MISSION_INTRO = "09_in"
CUTSCENE_CTE_BOATS = "m09_cte_01"
CUTSCENE_MISSION_OUTRO = "09_out"
-- Music --
M09_music = {
boat_begin = "M09_Boat_Music_Start",
boat_pierce_arrive = "M09_Boat_Music_Pierce",
boat_stop = "M09_Boat_Music_Stop",
rail_begin = "M09_Rail_Music_Start",
rail_wind_down = "M09_Rail_Music_Finish",
rail_stop = "M09_Rail_Music_Stop",
}
-- Audio events --
M09_audio_events = {
heli_walla = {
event = "M09_Heli_Walla",
switch_group = nil,
switch = nil,
},
heli_walla_stop = {
event = "M09_Heli_Walla_Stop",
switch_group = nil,
switch = nil,
},
stripper_cargo = {
event = "Mission_09",
switch_group = "Mission_09",
switch = "M09_Stripper_Cargo",
},
stripper_cargo_stop = {
event = "Mission_09_Stop",
switch_group = "Mission_09",
switch = "M09_Stripper_Cargo",
},
load_truck = {
event = "Mission_09",
switch_group = "Mission_09",
switch = "M09_Load_Truck",
},
}
-- Personas --
M09_personas = {
{name = "Pierce", handle = INVALID_PERSONA_HANDLE},
{name = "Zimos", handle = INVALID_PERSONA_HANDLE},
{name = "Paparazzi_WM", handle = INVALID_PERSONA_HANDLE},
{name = "Interrogation", handle = INVALID_PERSONA_HANDLE},
{name = "Matt", handle = INVALID_PERSONA_HANDLE},
}
M09_persona_line = {
take_a_boat = { character = LOCAL_PLAYER, name = "M09_Mission_Start_01", play_2d = false, },
goto_zimos = {
{ character = LOCAL_PLAYER, name = "M09_Go_To_Zimos_01", play_2d = false, },
{ character = LOCAL_PLAYER, name = "M09_Go_To_Zimos_02", play_2d = false, },
{ character = LOCAL_PLAYER, name = "M09_Go_To_Zimos_03", play_2d = false, },
{ character = LOCAL_PLAYER, name = "M09_Go_To_Zimos_04", play_2d = false, },
},
-- Character reference updated in m09_setup_crew()
follow_zimos = {
{ character = M09_Zimos, name = "M09_Follow_Zimos_01", play_2d = false, },
{ character = M09_Zimos, name = "M09_Follow_Zimos_02", play_2d = false, },
{ character = M09_Zimos, name = "M09_Follow_Zimos_03", play_2d = false, },
{ character = M09_Zimos, name = "M09_Follow_Zimos_04", play_2d = false, },
},
zimos_to_hos = { character = M09_Zimos, name = "M09_Zimos_Taking_Care_Of_Hoes", play_2d = false, },
find_ammo = {
{ character = LOCAL_PLAYER, name = "M09_Find_Ammo_03", play_2d = false, },
{ character = LOCAL_PLAYER, name = "M09_Find_Ammo_02", play_2d = false, },
{ character = LOCAL_PLAYER, name = "M11_Get_To_VTOL_02", play_2d = false, },
},
find_gag = {
{ character = LOCAL_PLAYER, name = "M09_Find_Gag_01", play_2d = false, },
{ character = LOCAL_PLAYER, name = "M09_Find_Gag_03", play_2d = false, },
{ character = LOCAL_PLAYER, name = "M09_Find_Gag_02", play_2d = false, },
{ character = LOCAL_PLAYER, name = "M09_Find_Ammo_01", play_2d = false, },
},
girl_thanks_1 = { character = "", name = "M09_Box_Thanks", play_2d = false, },
girl_thanks_2 = { character = "", name = "M09_Box_Thanks", play_2d = false, },
girl_complain_1 = { character = "", name = "M09_Back_In_Box", play_2d = false },
girl_complain_2 = { character = "", name = "M09_Back_In_Box", play_2d = false },
melee_brute = { character = LOCAL_PLAYER, name = "M09_Melee_Brute", play_2d = false, },
gat_brute = { character = LOCAL_PLAYER, name = "M09_Gat_Brute", play_2d = false, },
crates = { character = LOCAL_PLAYER, name = "M09_Many_Crates", play_2d = false, },
find_minigun = { character = LOCAL_PLAYER, name = "M09_Find_Minigun_01", play_2d = false },
heli_drop_off_02 = { character = M09_Zimos, name = "M09_Helis_Drop_Off_Guys_02", play_2d = false },
heli_drop_off_03 = { character = M09_Zimos, name = "M09_Helis_Drop_Off_Guys_03", play_2d = false },
clear_the_boat = { character = "Pierce", name = "M09_Clear_to_Land", play_2d = true, cell_receive = true, },
heli_at_platform = { character = M09_Zimos, name = "M09_Helicopter_At_Platform", play_2d = false, },
start_flying = { character = "Pierce", name = "M09_Flying_Start", play_2d = true, },
protect_pierce_1 = { character = "Pierce", name = "M09_Protect_Pierce_01", play_2d = true, },
protect_pierce_2 = { character = "Pierce", name = "M09_Protect_Pierce_02", play_2d = true, },
protect_pierce_3 = { character = "Pierce", name = "M09_Protect_Pierce_03", play_2d = true, },
protect_pierce_4 = { character = "Pierce", name = "M09_Protect_Pierce_04", play_2d = true, },
girls_in_truck_1 = { character = LOCAL_PLAYER, name = "M09_Girls_In_Truck_01", play_2d = false, },
girls_in_truck_2 = { character = LOCAL_PLAYER, name = "M09_Girls_In_Truck_02", play_2d = false, },
girls_in_truck_3 = { character = LOCAL_PLAYER, name = "M09_Girls_In_Truck_03", play_2d = false, },
choice_crib = { character = LOCAL_PLAYER, name = "M09_Choice_Crib_01", play_2d = false, },
choice_morningstar = { character = LOCAL_PLAYER, name = "M09_Choice_Morningstar_01", play_2d = false, },
}
-- Conversations --
M09_convo = {
-- Started as soon as the player gets on a boat
to_boat = {
files = {
--{name = M09_persona_line.take_a_boat, delay = 1.0},
{name = "m09_boat_ride_01", delay = 4.0},
{name = "m09_boat_ride_02", delay = 0.0},
},
thread = INVALID_THREAD_HANDLE,
},
-- Played after the player hits the gangway trigger
gangway = {
files = {
{name = "m09_arrive_boat", delay = 0.0},
},
thread = INVALID_THREAD_HANDLE,
},
-- Played as the player approaches a crate with a brute in it.
brute_crate = {
files = {
{name = "M09_Brute_Crate", delay = 0.0},
},
thread = INVALID_THREAD_HANDLE,
},
--[[
-- Played when the player hits a trigger partway through the deck of the boat.
banter_on_boat = {
files = {
{name = "M09_Banter_On_Boat", delay = 0.0},
},
thread = INVALID_THREAD_HANDLE,
},
--]]
zimos_01 = {
files = {
{name = M09_persona_line.girl_thanks_1, delay = 0.0},
{name = M09_persona_line.girl_thanks_2, delay = 0.0},
{name = M09_persona_line.goto_zimos[1], delay = 3.0},
{name = M09_persona_line.follow_zimos[1], delay = 1.0},
},
thread = INVALID_THREAD_HANDLE,
},
zimos_02 = {
files = {
{name = M09_persona_line.girl_thanks_1, delay = 0.0},
{name = M09_persona_line.girl_thanks_2, delay = 0.0},
{name = M09_persona_line.goto_zimos[2], delay = 2.0},
{name = M09_persona_line.follow_zimos[2], delay = 1.0},
},
thread = INVALID_THREAD_HANDLE,
},
zimos_03 = {
files = {
{name = M09_persona_line.girl_thanks_1, delay = 0.0},
{name = M09_persona_line.girl_thanks_2, delay = 0.0},
{name = M09_persona_line.goto_zimos[3], delay = 3.0},
{name = M09_persona_line.follow_zimos[3], delay = 1.0},
},
thread = INVALID_THREAD_HANDLE,
},
zimos_04 = {
files = {
{name = M09_persona_line.girl_thanks_1, delay = 0.0},
{name = M09_persona_line.girl_thanks_2, delay = 0.0},
{name = M09_persona_line.goto_zimos[4], delay = 2.0},
{name = M09_persona_line.follow_zimos[4], delay = 1.0},
},
thread = INVALID_THREAD_HANDLE,
},
crates = {
files = {
{name = M09_persona_line.crates, delay = 0.0},
},
thread = INVALID_THREAD_HANDLE,
},
-- Played shortly after the final crate has been found
load_girls = {
files = {
{name = "m09_get_in_crate", delay = 0.0},
{name = M09_persona_line.girl_complain_1, delay = 0.0},
{name = M09_persona_line.girl_complain_2, delay = 4.0},
},
thread = INVALID_THREAD_HANDLE,
},
defend_girls = {
files = {
{name = "M09_Enemies_On_Sides", delay = 5.0},
{name = M09_persona_line.clear_the_boat, delay = 1.0, cell_receive = true},
},
thread = INVALID_THREAD_HANDLE,
},
zimos_to_hos = {
files = {
{name = M09_persona_line.zimos_to_hos, delay = 1.0},
},
thread = INVALID_THREAD_HANDLE,
},
-- Played between waves of attackers while waiting for the chopper.
hold_off_attackers = {
files = {
{name = "m09_hold_off", delay = 2.0, cell_receive = true},
{name = "m09_combat", delay = 0.0},
},
thread = INVALID_THREAD_HANDLE,
},
heli_drop_off_01 = {
files = {
{name = "M09_Helis_Drop_Off_Guys_1", delay = 0.0},
},
thread = INVALID_THREAD_HANDLE,
},
heli_drop_off_02 = {
files = {
{name = M09_persona_line.heli_drop_off_02, delay = 0.0},
},
thread = INVALID_THREAD_HANDLE,
},
heli_drop_off_03 = {
files = {
{name = M09_persona_line.heli_drop_off_03, delay = 0.0},
},
thread = INVALID_THREAD_HANDLE,
},
-- Played when the ho boat is clear and Pierce should come in.
boat_clear_of_danger = {
files = {
{name = "M09_Clear_Of_Danger", delay = 4.0},
{name = "M09_Banter_On_Boat", delay = 0.0},
},
thread = INVALID_THREAD_HANDLE,
},
-- Played when the helicopter arrives.
get_to_the_chopper = {
files = {
{name = M09_persona_line.heli_at_platform, delay = 2.0},
},
thread = INVALID_THREAD_HANDLE,
},
boat_chase = {
files = {
{name = "M09_Tell_Pilot_To_Follow", delay = 0.0},
},
thread = INVALID_THREAD_HANDLE,
},
rockets = {
files = {
{name = "m09_roof_01", delay = 15.0},
{name = M09_persona_line.protect_pierce_1, delay = 1.0},
},
thread = INVALID_THREAD_HANDLE,
},
down_there = {
files = {
{name = "m09_roof_02", delay = 0.0},
},
thread = INVALID_THREAD_HANDLE,
},
all_over_roofs = {
files = {
{name = "M09_roof_3", delay = 10.0},
{name = M09_persona_line.protect_pierce_2, delay = 1.0},
},
thread = INVALID_THREAD_HANDLE,
},
why_shoot_at_us = {
files = {
{name = "M09_Pilot_Combat_1", delay = 0.0},
},
thread = INVALID_THREAD_HANDLE,
},
too_much_fire = {
files = {
{name = "M09_Pilot_Combat_2", delay = 0.0},
},
thread = INVALID_THREAD_HANDLE,
},
first_tank_attack = {
files = {
{name = "M09_First_Tank_Attack", delay = 0.0},
},
thread = INVALID_THREAD_HANDLE,
},
--[[ second_tank_attack = {
files = {
{name = "M09_Second_Tank_Attack", delay = 0.0},
},
thread = INVALID_THREAD_HANDLE,
},
--]]
choice_suggestion = {
files = {
{name = "M09_Choice_Suggestion", delay = 0.0, cell_receive = true, },
},
thread = INVALID_THREAD_HANDLE,
},
}
-- Triggers --
M09_trigger = {
gangway = {
name = "Gangway_trigger",
callback = "m09_gangway_trigger_cb",
on_exit = "",
hit = false
},
heli_entrance = {
name = "heli_entrance_trigger",
callback = "m09_heli_entrance_trigger_cb",
on_exit = "",
hit = false
},
to_saints_trigger = {
name = "to_saints_trigger",
callback = "m09_set_trigger_hit_cb",
on_exit = "",
hit = false,
},
to_brothel_trigger = {
name = "to_brothel_trigger",
callback = "m09_set_trigger_hit_cb",
on_exit = "",
hit = false,
},
on_boat_trigger = {
name = "on_boat_trigger",
callback = "m09_on_boat_enter_cb",
on_exit = "m09_on_boat_exit_cb",
hit = false
},
player_on_boat_trigger = {
name = "on_boat_trigger",
callback = "m09_player_on_boat_enter_cb",
on_exit = "m09_player_on_boat_exit_cb",
hit = false
},
disable_front_spawns = {
name = "disable_front_spawns_trigger",
callback = "m09_disable_front_spawns_cb",
on_exit = "",
hit = false
},
audio_how_many_crates = {
name = "audio_trigger_crates",
callback = "m09_audio_trigger_cb",
on_exit = "",
hit = false,
convo = M09_convo.crates,
},
ho_heli_crate = {
name = "Ho_Heli_Crate_Trigger",
callback = "m09_ho_heli_crate_trigger_cb",
on_exit = "",
hit = false,
hoes_run_to = "Ho_Heli_Crate_Nav",
},
dist_warn = {
name = "dist_warn_trigger",
callback = "m09_remove_warn_radius_cb",
on_exit = "m09_show_warn_radius_cb",
hit = false,
},
dist_fail = {
name = "dist_fail_trigger",
callback = "",
on_exit = "m09_fail_ship_abandoned_cb",
hit = false,
},
north_vantage = {
name = "North_vantage_point_trigger",
callback = "m09_north_vantage_cb",
on_exit = "",
hit = false,
},
south_vantage = {
name = "South_vantage_point_trigger",
callback = "m09_south_vantage_cb",
on_exit = "",
hit = false,
},
roof1 = {
name = "roof_prep_trigger 001",
callback = "m09_prep_roof_group_cb",
on_exit = "",
hit = false,
group = M09_group.roof1,
},
roof2 = {
name = "roof_prep_trigger 002",
callback = "m09_prep_roof_group_cb",
on_exit = "",
hit = false,
group = M09_group.roof2,
},
heli_boat = {
name = "boat_prep_trigger",
callback = "m09_setup_boats_cb",
on_exit = "",
hit = false,
group = M09_group.heli_boats,
},
mark_boats = {
name = "mark_boats_trigger",
callback = "m09_mark_rail_group_trigger",
on_exit = "",
hit = false,
groups = {M09_group.heli_boats},
},
heli_boat_2 = {
name = "boat_prep_trigger 2",
callback = "m09_setup_boats_cb",
on_exit = "",
hit = false,
group = M09_group.heli_boats_2,
},
mark_boats_2 = {
name = "mark_boats_2_trigger",
callback = "m09_mark_rail_group_trigger",
on_exit = "",
hit = false,
groups = {M09_group.heli_boats_2},
},
heli_boat_3 = {
name = "boat_prep_trigger 3",
callback = "m09_setup_boats_cb",
on_exit = "",
hit = false,
group = M09_group.heli_boats_3,
},
mark_boats_3 = {
name = "mark_boats_3_trigger",
callback = "m09_mark_rail_group_trigger",
on_exit = "",
hit = false,
groups = {M09_group.heli_boats_3},
},
cleanup_boats = {
name = "cleanup_boats_trigger",
callback = "m09_cleanup_rail_group_trigger",
on_exit = "",
hit = false,
groups = {M09_group.heli_boats, M09_group.heli_boats_2, M09_group.heli_boats_3},
},
tank1 = {
name = "tank_prep_trigger <001>",
callback = "m09_setup_boats_cb",
on_exit = "",
hit = false,
group = M09_group.heli_tank1,
},
mark_tanks = {
name = "mark_tanks_trigger_1",
callback = "m09_mark_rail_group_trigger",
on_exit = "",
hit = false,
groups = {M09_group.heli_tank1},
},
cleanup_tanks = {
name = "cleanup_tanks_trigger",
callback = "m09_cleanup_rail_group_trigger",
on_exit = "",
hit = false,
groups = {M09_group.heli_tank1},
},
tank2 = {
name = "tank_prep_trigger_2",
callback = "m09_setup_boats_cb",
on_exit = "",
hit = false,
group = M09_group.heli_tank2,
},
mark_tanks_2 = {
name = "mark_tanks_trigger_2",
callback = "m09_mark_rail_group_trigger",
on_exit = "",
hit = false,
groups = {M09_group.heli_tank2},
},
cleanup_tanks_2 = {
name = "cleanup_tanks_trigger_2",
callback = "m09_cleanup_rail_group_trigger",
on_exit = "",
hit = false,
groups = {M09_group.heli_tank2},
},
audio_rockets = {
name = "audio_trigger_rockets",
callback = "m09_audio_trigger_cb",
on_exit = "",
hit = false,
convo = M09_convo.rockets,
},
audio_down_there = {
name = "audio_trigger_down_there",
callback = "m09_audio_trigger_cb",
on_exit = "",
hit = false,
convo = M09_convo.down_there,
},
audio_all_over_roofs = {
name = "audio_trigger_all_over_roofs",
callback = "m09_audio_trigger_cb",
on_exit = "",
hit = false,
convo = M09_convo.all_over_roofs,
},
audio_why_shoot_at_us = {
name = "audio_trigger_why_shoot_at_us",
callback = "m09_audio_trigger_cb",
on_exit = "",
hit = false,
convo = M09_convo.why_shoot_at_us,
},
audio_apcs = {
name = "audio_trigger_apcs",
callback = "m09_audio_trigger_cb",
on_exit = "",
hit = false,
convo = M09_convo.first_tank_attack,
},
--[[ audio_apcs_2 = {
name = "audio_trigger_apcs_2",
callback = "m09_audio_trigger_cb",
on_exit = "",
hit = false,
convo = M09_convo.second_tank_attack,
},
--]]
audio_too_much_fire = {
name = "audio_trigger_too_much_fire",
callback = "m09_audio_trigger_cb",
on_exit = "",
hit = false,
convo = M09_convo.too_much_fire,
},
}
M09_rail_triggers = {
M09_trigger.heli_boat, M09_trigger.heli_boat_2, M09_trigger.heli_boat_3,
M09_trigger.mark_boats, M09_trigger.mark_boats_2, M09_trigger.mark_boats_3,
M09_trigger.cleanup_boats,
M09_trigger.tank1, M09_trigger.mark_tanks, M09_trigger.cleanup_tanks,
M09_trigger.tank2, M09_trigger.mark_tanks_2, M09_trigger.cleanup_tanks_2,
M09_trigger.roof1, M09_trigger.roof2,
--[[
M09_trigger.roof3,
M09_trigger.roof4, M09_trigger.roof5, M09_trigger.roof6,
M09_trigger.roof7, M09_trigger.roof_mb, M09_trigger.clear_roof7,
--]]
M09_trigger.audio_rockets, M09_trigger.audio_down_there, M09_trigger.audio_all_over_roofs,
M09_trigger.audio_why_shoot_at_us, M09_trigger.audio_apcs, M09_trigger.audio_apcs_2, M09_trigger.audio_too_much_fire,
}
-- Other --
-- Shipping Containers --
M09_CRATE_GIRLS = 1
M09_CRATE_BOMB = 2
M09_CRATE_GAG = 3
M09_CRATE_ENEMIES = 4
M09_CRATE_BRUTE = 5
M09_CRATE_BRUTE_GAT = 6
M09_CRATE_AMMO = 7
M09_crate_sets = {
[1] = {
crates = {
girls1 = {
trigger = "Girls_trigger 001", -- open_door trigger
door = "Girls_door_1", -- door script mover
player_anim = "M09 open container", -- animation to play on the player when they open the crate
anim_nav = "nav_crate_anim<011>", -- nav point to move the player to for the animation
emitter_to_stop = M09_audio_emitters.girls_1, -- audio emitter to stop when the crate is opened
door_open_event = nil, -- audio event to post when the door opens
door_open_switch_group = nil, -- switch group for the event to post when the door opens
door_open_switch = nil, -- switch for the event to post when the door opens
door_open_event_object = nil, -- the object to post an audio event on when the door opens
content = M09_CRATE_GIRLS, -- what's inside?
qte = "", --"m09_open_container", -- qte to open the door
group = M09_group.girls1, -- group if needed
run_to = "Girls_nav 001", -- nav to run to
just_opened = false,
opened = false,
zimos_nav = M09_nav.zimos_girls[1],
},
ammo1 = {
trigger = "Ammo_Trigger 001", -- open_door trigger
door = "Ammo_door_1", -- door script mover
player_anim = "M09 open container", -- animation to play on the player when they open the crate
anim_nav = "nav_crate_anim<009>", -- nav point to move the player to for the animation
emitter_to_stop = nil, -- audio emitter to stop when the crate is opened
door_open_event = nil, -- audio event to post when the door opens
door_open_switch_group = nil, -- switch group for the event to post when the door opens
door_open_switch = nil, -- switch for the event to post when the door opens
door_open_event_object = nil, -- the object to post an audio event on when the door opens
content = M09_CRATE_AMMO, -- what's inside?
qte = "", --"m09_open_container", -- qte to open the door
group = "", -- group if needed
run_to = "", -- nav to run to
opened = false,
ammo_group = M09_group.ammo_crate_grenades, -- Script group of weapons to spawn in this container.
},
ammo2 = {
trigger = "Ammo_Trigger 002", -- open_door trigger
door = "Ammo_door_2", -- door script mover
player_anim = "M09 open container", -- animation to play on the player when they open the crate
anim_nav = "nav_crate_anim<007>", -- nav point to move the player to for the animation
emitter_to_stop = nil, -- audio emitter to stop when the crate is opened
door_open_event = nil, -- audio event to post when the door opens
door_open_switch_group = nil, -- switch group for the event to post when the door opens
door_open_switch = nil, -- switch for the event to post when the door opens
door_open_event_object = nil, -- the object to post an audio event on when the door opens
content = M09_CRATE_AMMO, -- what's inside?
qte = "", --"m09_open_container", -- qte to open the door
group = "", -- group if needed
run_to = "", -- nav to run to
opened = false,
ammo_group = M09_group.ammo_crate_rpg, -- Script group of weapons to spawn in this container.
},
gag1 = {
trigger = "Gag_Trigger 001", -- open_door trigger
door = "Gag_door_1", -- door script mover
player_anim = "M09 open container", -- animation to play on the player when they open the crate
anim_nav = "nav_crate_anim<010>", -- nav point to move the player to for the animation
emitter_to_stop = nil, -- audio emitter to stop when the crate is opened
door_open_event = nil, -- audio event to post when the door opens
door_open_switch_group = nil, -- switch group for the event to post when the door opens
door_open_switch = nil, -- switch for the event to post when the door opens
door_open_event_object = nil, -- the object to post an audio event on when the door opens
content = M09_CRATE_GAG, -- what's inside?
qte = "", --"m09_open_container", -- qte to open the door
group = "", -- group if needed
run_to = "", -- nav to run to
opened = false,
},
},
},
[2] = {
zimos_nav = M09_nav.zimos_girls[2],
crates = {
brute1 = {
trigger = "Brute_Trigger 001", -- open_door trigger
door = "Brute_Mover 001", -- door script mover
player_anim = nil, -- animation to play on the player when they open the crate
anim_nav = nil, -- nav point to move the player to for the animation
emitter_to_stop = M09_audio_emitters.brute_1,-- audio emitter to stop when the crate is opened
door_open_event = "Mission_09", -- audio event to post when the door opens
door_open_switch_group = "Mission_09", -- switch group for the event to post when the door opens
door_open_switch = "M09_Brute_Crash", -- switch for the event to post when the door opens
door_open_event_object = M09_group.brute1.members[1], -- the object to post an audio event on when the door opens
content = M09_CRATE_BRUTE, -- what's inside?
qte = "", -- qte to open the door
group = M09_group.brute1, -- group if needed
run_to = "Brute_Nav 001", -- nav point to run to
opened = false,
},
gag2 = {
trigger = "Gag_Trigger 002", -- open_door trigger
door = "Gag_door_2", -- door script mover
player_anim = "M09 open container", -- animation to play on the player when they open the crate
anim_nav = "nav_crate_anim<004>", -- nav point to move the player to for the animation
emitter_to_stop = nil, -- audio emitter to stop when the crate is opened
door_open_event = nil, -- audio event to post when the door opens
door_open_switch_group = nil, -- switch group for the event to post when the door opens
door_open_switch = nil, -- switch for the event to post when the door opens
door_open_event_object = nil, -- the object to post an audio event on when the door opens
content = M09_CRATE_GAG, -- what's inside?
qte = "", --"m09_open_container", -- qte to open the door
group = "", -- group if needed
run_to = "", -- nav to run to
opened = false,
},
gag3 = {
trigger = "Gag_Trigger 003", -- open_door trigger
door = "Gag_door_3", -- door script mover
player_anim = "M09 open container", -- animation to play on the player when they open the crate
anim_nav = "nav_crate_anim<013>", -- nav point to move the player to for the animation
emitter_to_stop = nil, -- audio emitter to stop when the crate is opened
door_open_event = nil, -- audio event to post when the door opens
door_open_switch_group = nil, -- switch group for the event to post when the door opens
door_open_switch = nil, -- switch for the event to post when the door opens
door_open_event_object = nil, -- the object to post an audio event on when the door opens
content = M09_CRATE_GAG, -- what's inside?
qte = "", --"m09_open_container", -- qte to open the door
group = "", -- group if needed
run_to = "", -- nav to run to
opened = false,
},
girls2 = {
trigger = "Girls_trigger 002", -- open_door trigger
door = "Girls_door_2", -- door script mover
player_anim = "M09 open container", -- animation to play on the player when they open the crate
anim_nav = "nav_crate_anim<001>", -- nav point to move the player to for the animation
emitter_to_stop = M09_audio_emitters.girls_2, -- audio emitter to stop when the crate is opened
door_open_event = nil, -- audio event to post when the door opens
door_open_switch_group = nil, -- switch group for the event to post when the door opens
door_open_switch = nil, -- switch for the event to post when the door opens
door_open_event_object = nil, -- the object to post an audio event on when the door opens
content = M09_CRATE_GIRLS, -- what's inside?
qte = "", --"m09_open_container", -- qte to open the door
group = M09_group.girls2, -- group if needed
run_to = "Girls_nav 002", -- nav to run to
just_opened = false,
opened = false,
},
},
},
[3] = {
zimos_nav = M09_nav.zimos_girls[3],
crates = {
girls3 = {
trigger = "Girls_trigger 003", -- open_door trigger
door = "Girls_door_3", -- door script mover
player_anim = "M09 open container", -- animation to play on the player when they open the crate
anim_nav = "nav_crate_anim<014>", -- nav point to move the player to for the animation
emitter_to_stop = M09_audio_emitters.girls_3, -- audio emitter to stop when the crate is opened
door_open_event = nil, -- audio event to post when the door opens
door_open_switch_group = nil, -- switch group for the event to post when the door opens
door_open_switch = nil, -- switch for the event to post when the door opens
door_open_event_object = nil, -- the object to post an audio event on when the door opens
content = M09_CRATE_GIRLS, -- what's inside?
qte = "", --"m09_open_container", -- qte to open the door
group = M09_group.girls3, -- group if needed
run_to = "Girls_nav 003", -- nav to run to
just_opened = false,
opened = false,
},
girls4 = {
trigger = "Girls_trigger 004", -- open_door trigger
door = "Girls_door_4", -- door script mover
player_anim = "M09 open container", -- animation to play on the player when they open the crate
anim_nav = "nav_crate_anim<005>", -- nav point to move the player to for the animation
emitter_to_stop = M09_audio_emitters.girls_4, -- audio emitter to stop when the crate is opened
door_open_event = nil, -- audio event to post when the door opens
door_open_switch_group = nil, -- switch group for the event to post when the door opens
door_open_switch = nil, -- switch for the event to post when the door opens
door_open_event_object = nil, -- the object to post an audio event on when the door opens
content = M09_CRATE_GIRLS, -- what's inside?
qte = "", --"m09_open_container", -- qte to open the door
group = M09_group.girls4, -- group if needed
run_to = "Girls_nav 004", -- nav to run to
just_opened = false,
opened = false,
},
ammo3 = {
trigger = "Ammo_Trigger 003", -- open_door trigger
door = "Ammo_door_3", -- door script mover
player_anim = "M09 open container", -- animation to play on the player when they open the crate
anim_nav = "nav_crate_anim<008>", -- nav point to move the player to for the animation
emitter_to_stop = nil, -- audio emitter to stop when the crate is opened
door_open_event = nil, -- audio event to post when the door opens
door_open_switch_group = nil, -- switch group for the event to post when the door opens
door_open_switch = nil, -- switch for the event to post when the door opens
door_open_event_object = nil, -- the object to post an audio event on when the door opens
content = M09_CRATE_AMMO, -- what's inside?
qte = "", --"m09_open_container", -- qte to open the door
group = "", -- group if needed
run_to = "", -- nav to run to
opened = false,
ammo_group = M09_group.ammo_crate_smg, -- Script group of weapons to spawn in this container.
},
minigun_brute1 = {
trigger = "Minigun_Brute_Trigger 001", -- open_door trigger
door = "Minigun_Brute_Mover 001", -- door script mover
player_anim = nil, -- animation to play on the player when they open the crate
anim_nav = nil, -- nav point to move the player to for the animation
emitter_to_stop = M09_audio_emitters.brute_2,-- audio emitter to stop when the crate is opened
door_open_event = "Mission_09", -- audio event to post when the door opens
door_open_switch_group = "Mission_09", -- switch group for the event to post when the door opens
door_open_switch = "M09_Brute_Crash", -- switch for the event to post when the door opens
door_open_event_object = M09_group.minigun_brute.members[1], -- the object to post an audio event on when the door opens
content = M09_CRATE_BRUTE_GAT, -- what's inside?
qte = "", -- qte to open the door
group = M09_group.minigun_brute, -- group if needed
run_to = "Minigun_Brute_Nav 001", -- nav point to run to
opened = false,
},
gag4 = {
trigger = "Gag_Trigger 004", -- open_door trigger
door = "Gag_door_4", -- door script mover
player_anim = "M09 open container", -- animation to play on the player when they open the crate
anim_nav = "nav_crate_anim<003>", -- nav point to move the player to for the animation
emitter_to_stop = nil, -- audio emitter to stop when the crate is opened
door_open_event = nil, -- audio event to post when the door opens
door_open_switch_group = nil, -- switch group for the event to post when the door opens
door_open_switch = nil, -- switch for the event to post when the door opens
door_open_event_object = nil, -- the object to post an audio event on when the door opens
content = M09_CRATE_GAG, -- what's inside?
qte = "", --"m09_open_container", -- qte to open the door
group = "", -- group if needed
run_to = "", -- nav to run to
opened = false,
},
},
},
}
M09_girl_crate = {
M09_crate_sets[1].crates.girls1, M09_crate_sets[2].crates.girls2, M09_crate_sets[3].crates.girls3, M09_crate_sets[3].crates.girls4
}
-- These emitters get disabled when restarting from the "defend girls" checkpoint.
M09_temporary_emitters = {M09_audio_emitters.girls_1, M09_audio_emitters.girls_2, M09_audio_emitters.girls_3, M09_audio_emitters.girls_4, M09_audio_emitters.brute_1, M09_audio_emitters.brute_2}
M09_heli_weapon = "Rifle-Gang"
M09_local_crate = M09_crate_sets[1].crates.girls1
M09_remote_crate = M09_crate_sets[1].crates.girls1
M09_active_convo = ""
M09_goto_zimos_line = 1
M09_found_girl_crates = 0
M09_found_gag_line = 1
M09_found_ammo_line = 1
M09_girls_found = false
M09_zimos_drop_off_girls = false
M09_play_find_minigun_line = false
M09_just_opened_girls_crates = {}
M09_girls_following = {}
M09_girls_flee_nav = ""
M09_allow_attacker_docking = true
M09_enemies_on_the_boat = {}
M09_heli_drop_off_convo = 1
M09_local_on_boat = false
M09_remote_on_boat = false
M09_current_obj = ""
M09_obj_str1 = ""
M09_obj_str2 = ""
M09_secondary_obj = {} -- Need one for each player
M09_crates_disabled = false
M09_active_crate_set = ""
M09_brute_list = { }
M09_cur_cell_call = ""
M09_stripper_cower_variants = {
0, -- Hunched
2, -- Knee
3, -- Other knee
}
M09_player_chose_brothel = false
M09_mission_success = false
In_coop = 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
--
-- m09_checkpoint: The checkpoint the mission should begin at
-- is_restart: TRUE if the mission is restarting, FALSE otherwise
--
function m09_start(m09_checkpoint, is_restart)
In_coop = coop_is_active()
--if not is_restart then
--m09_checkpoint = M09_checkpoint.start.name
--m09_checkpoint = M09_checkpoint.gangway.name
--m09_checkpoint = M09_checkpoint.defend_girls.name
--m09_checkpoint = M09_checkpoint.heli_rail.name
--m09_checkpoint = M09_checkpoint.truck_route.name
--mission_set_checkpoint(m09_checkpoint, true, true)
--end
if M09_debug_skip_to_heli_scene then
m09_checkpoint = M09_checkpoint.heli_rail.name
mission_set_checkpoint(m09_checkpoint, true, true)
end
-- Check if this mission starting from the beginning
if (m09_checkpoint == M09_checkpoint.start.name) then
if (is_restart == false) then
-- First time playing mission
cutscene_play(CUTSCENE_MISSION_INTRO, nil, {M09_checkpoint.start.nav1, M09_checkpoint.start.nav2}, false)
end
end
-- Handle mission initialization for the current checkpoint
m09_initialize(m09_checkpoint, is_restart)
-- Run the mission from the current checkpoint
m09_run(m09_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 m09_run(first_checkpoint)
local current_checkpoint = first_checkpoint
mission_set_cancel_warp_location(M09_checkpoint.start.nav1, M09_checkpoint.start.nav2)
-- Make sure all crate doors are locked.
m09_lock_crate_doors()
-- Run the mission from the beginning
if current_checkpoint == M09_checkpoint.start.name then
m09_go_to_boat()
m09_setup_distance_check_triggers()
current_checkpoint = M09_checkpoint.gangway.name
mission_set_checkpoint(M09_checkpoint.gangway.name, true, true)
end
if current_checkpoint == M09_checkpoint.gangway.name then
character_ragdoll_set_last_resort_position(M09_checkpoint.gangway.nav1)
-- Begin camera shake when on the boat.
camera_shake_play_looping(M09_cargo_ship_camera_shake, M09_cargo_ship_camera_shake_amt)
m09_find_girls()
-- Zimos wil bring the girls to their final crate
m09_set_trigger(M09_trigger.on_boat_trigger, false, false)
delay(1.0)
--m09_clear_boat_guards()
current_checkpoint = M09_checkpoint.defend_girls.name
mission_set_checkpoint(M09_checkpoint.defend_girls.name, true, true)
end
if current_checkpoint == M09_checkpoint.defend_girls.name then
character_ragdoll_set_last_resort_position(M09_checkpoint.defend_girls.nav1)
m09_defend_girls()
m09_call_the_helis()
-- End the camera shake.
camera_shake_stop()
fade_out(0.5)
fade_out_block()
m09_cleanup_cargo_ship()
teleport_coop(M09_checkpoint.heli_rail.nav1, M09_checkpoint.heli_rail.nav2, true)
m09_setup_heli_rail()
current_checkpoint = M09_checkpoint.heli_rail.name
mission_set_checkpoint(M09_checkpoint.heli_rail.name, true, true)
m09_players_enter_rail_heli()
fade_in(0.5)
fade_in_block()
end
-- Stop using the mission specified ragdoll get up last resort.
character_ragdoll_clear_last_resort_position()
if current_checkpoint == M09_checkpoint.heli_rail.name then
m09_heli_rail()
current_checkpoint = M09_checkpoint.truck_route.name
mission_set_checkpoint(M09_checkpoint.truck_route.name, true, true)
end
if current_checkpoint == M09_checkpoint.truck_route.name then
m09_truck_route()
end
M09_mission_success = true
mission_end_success("m09", CUTSCENE_MISSION_OUTRO)
end
-- This is the primary function responsible for cleaning up the entire mission
-- CALLED FROM CODE (+++MUST RETURN IMMEDIATLY+++)
--
function m09_cleanup()
persona_suppress_ambient_lines(false)
In_coop = coop_is_active()
m09_kill_all_threads()
m09_cleanup_heli_rail()
-- Clear any QTE
qte_cleanup()
character_allow_ragdoll(LOCAL_PLAYER, true)
character_allow_ragdoll(REMOTE_PLAYER, true)
-- cleanup triggers
m09_clear_all_triggers()
-- make sure the crates are all cleaned up
m09_clear_all_crates()
-- cleanup any continuous spawn groups or regions
m09_cleanup_all_continuous_spawns()
-- cleanup any homies
m09_clear_all_crew()
m09_cleanup_roof()
-- cleanup groups
m09_cleanup_groups()
-- Cleanup any boat attackers.
for human in pairs(M09_enemies_on_the_boat) do
M09_enemies_on_the_boat[human] = nil
marker_remove(human)
on_death("", human)
end
minimap_icon_remove_radius("Cargo_Ship_Center", SYNC_ALL)
inv_weapon_disable_all_slots(false)
cleanup_temporary_weapons(M09_heli_weapon)
if M09_give_rocket_launcher then
cleanup_temporary_weapons("Explosive-RocketLauncher")
end
set_player_can_enter_exit_vehicles(LOCAL_PLAYER, true)
if In_coop then
set_player_can_enter_exit_vehicles(REMOTE_PLAYER, true)
end
if M09_mission_success then
-- Teleport the player to the location they chose.
if M09_player_chose_brothel then
teleport(LOCAL_PLAYER, M09_nav.choice_brothel.host, true)
if In_coop then
teleport(REMOTE_PLAYER, M09_nav.choice_brothel.client, true)
end
else
teleport(LOCAL_PLAYER, M09_nav.choice_saints_hq.host, true)
if In_coop then
teleport(REMOTE_PLAYER, M09_nav.choice_saints_hq.client, true)
end
end
end
-- reset notoriety
notoriety_set_min("morningstar", 0)
notoriety_set_max("morningstar", MAX_NOTORIETY_LEVEL)
notoriety_force_no_spawn("morningstar", false)
notoriety_set("morningstar", 0)
notoriety_reset("morningstar")
-- TODO: Remove once poper follower/water interaction is added
on_vehicle_enter("", LOCAL_PLAYER)
city_zone_swap("cargo", DISABLE) -- Remove Cargo ship zone swap
-- Cleanup any on going audio threads
m09_unload_all_convos()
m09_unload_personas()
-- End the camera shake.
camera_shake_stop()
-- Post any sudio stop events.
m09_post_audio_event(M09_audio_events.heli_walla_stop, LOCAL_PLAYER)
if group_is_loaded(M09_group.girls_truck) then
m09_post_audio_event(M09_audio_events.stripper_cargo_stop, M09_group.girls_truck.vehicle)
end
-- Enable warp to shore
player_warp_to_shore_enable(LOCAL_PLAYER)
if In_coop then
player_warp_to_shore_enable(REMOTE_PLAYER)
end
mission_waypoint_remove()
-- Stop any cell calls.
audio_remove_mission_cellphone(M09_cur_cell_call)
mission_cleanup_maybe_reenable_player_controls()
-- Stop using the mission specified ragdoll get up last resort.
character_ragdoll_clear_last_resort_position()
end
-- Called when the mission has ended with success
-- CALLED FROM CODE (+++MUST RETURN IMMEDIATLY+++)
--
function m09_success()
end
-- *************************
--
-- Local functions
--
-- *************************
-- Initialize the mission for the specified checkpoint
--
-- checkpoint: Checkpoint to initialize the mission to
-- is_restart: Whether or not the mission is restarting.
--
function m09_initialize(checkpoint, is_restart)
-- Make sure the screen is completly faded out
mission_start_fade_out(0.0)
-- Set the mission author
set_mission_author("Neil Ryan")
-- Common initialization
m09_initialize_common()
-- Checkpoint specific initialization
m09_initialize_checkpoint(checkpoint, is_restart)
-- Start fading in
mission_start_fade_in()
end
-- Go to the boat because it is cool
--
function m09_go_to_boat()
m09_set_objective(M09_objective.go_to_ship)
m09_set_trigger(M09_trigger.player_on_boat_trigger, false, false)
-- TODO: Remove once poper follower/water interaction is added
--on_vehicle_enter("m09_player_entered_boat", LOCAL_PLAYER)
trigger_enable(M09_trigger.gangway.name, true) -- Trigger needs to be enabled for the minimap icon.
marker_add_trigger(M09_trigger.gangway.name, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
-- GPS looks stupid going to the boat, so don't do it.
--mission_waypoint_add(M09_trigger.gangway.name)
if not In_coop then
M09_remote_on_boat = true
end
while not M09_local_on_boat or not M09_remote_on_boat do
thread_yield()
end
trigger_enable(M09_trigger.gangway.name, false)
marker_remove_trigger(M09_trigger.gangway.name, SYNC_ALL)
--mission_waypoint_remove()
m09_clear_trigger(M09_trigger.player_on_boat_trigger.name)
-- Start spawning guards on the deck.
m09_start_continuous_spawns(M09_spawn_groups.normal, M09_continuous_respawn_delay, M09_spawn_regions.front)
m09_start_convo_thread(M09_convo.gangway)
-- TODO: Remove once poper follower/water interaction is added
on_vehicle_enter("", LOCAL_PLAYER)
notoriety_force_no_spawn("morningstar", true)
notoriety_set_min("morningstar", M09_min_notoriety)
notoriety_set_max("morningstar", M09_max_notoriety)
end
function m09_spawn_ship_guards()
if group_is_loaded(M09_group.weapons.name) then
return
end
group_create(M09_group.weapons, true)
group_create(M09_group.boat_guards.name, true)
end
function m09_setup_distance_check_triggers()
m09_set_trigger(M09_trigger.dist_warn, false, false)
m09_set_trigger(M09_trigger.dist_fail, false, false)
M09_local_on_boat = true
M09_remote_on_boat = In_coop
-- Prevent the player from attempting to warp away from the ship
player_warp_to_shore_disable(LOCAL_PLAYER)
if In_coop then
player_warp_to_shore_disable(REMOTE_PLAYER)
end
end
function m09_cleanup_distance_check_triggers()
m09_clear_trigger(M09_trigger.dist_warn.name)
m09_clear_trigger(M09_trigger.dist_fail.name)
player_warp_to_shore_enable(LOCAL_PLAYER)
if In_coop then
player_warp_to_shore_enable(REMOTE_PLAYER)
end
end
-- find the crate with the girls
--
function m09_find_girls()
local num_girl_crates = sizeof_table(M09_girl_crate)
local found_crates = 0
M09_goto_zimos_line = 1
M09_found_gag_line = 1
M09_found_ammo_line = 1
M09_found_girl_crates = 0
m09_set_objective(M09_objective.find_girls, M09_found_girl_crates, num_girl_crates)
m09_set_trigger(M09_trigger.disable_front_spawns, false, false)
m09_set_trigger(M09_trigger.audio_how_many_crates, false, false)
-- Don't allow Zimos to die.
turn_invulnerable(M09_Zimos)
-- Zimos may lag behind the player, don't pop up the warning that you're abandoning him.
follower_set_can_abandon(M09_Zimos, false)
set_force_combat_ready_team("Playas")
M09_zimos_girl_thread = thread_new("m09_zimos_girl_behavior_thread")
M09_girls_follow_zimos_thread = thread_new("m09_girls_follow_zimos_thread")
for i, crate_set in pairs(M09_crate_sets) do
m09_setup_crate_set(crate_set)
while m09_num_crates_left(crate_set) ~= 0 and M09_found_girl_crates < num_girl_crates do
thread_yield()
end
if crate_set.zimos_nav ~= nil then
-- Move Zimos to the specified nav.
m09_move_zimos_and_girls(crate_set.zimos_nav)
end
end
m09_clear_trigger(M09_trigger.audio_how_many_crates.name)
m09_clear_all_crate_triggers()
m09_cleanup_all_continuous_spawns()
m09_start_convo_thread(M09_convo.load_girls)
m09_clear_objective()
-- Wait for the conversation to finish.
m09_wait_for_convo(30.0)
-- Start music for the boat segment.
m09_post_music_event(M09_music.boat_begin)
delay(1.0)
m09_start_convo_thread(M09_convo.defend_girls)
M09_zimos_drop_off_girls = true
M09_girls_found = true
delay(3.0)
end
-- defend against waves of attackers
--
function m09_defend_girls()
m09_set_objective(M09_objective.north_platform)
m09_set_trigger(M09_trigger.north_vantage, false, true)
while not M09_trigger.north_vantage.hit do
thread_yield()
end
set_force_combat_ready_team("Playas")
-- Only play the "find minigun" line the first time through, it'd
-- be weird to play it after restarting the checkpoint.
if (M09_play_find_minigun_line) then
m09_play_persona_line(M09_persona_line.find_minigun)
delay(2.0)
end
--m09_play_cte()
m09_set_objective(M09_objective.clear_the_boat)
local wave_data = {
-- Boats
{
thread_func = "m09_do_boat_wave_thread",
thread = INVALID_THREAD_HANDLE,
waves = {
{
boats = M09_boat_wave1,
paths = M09_boat_paths.north,
do_south_platform_breadcrumb = false,
},
{
boats = M09_boat_wave2,
paths = M09_boat_paths.north,
do_south_platform_breadcrumb = false,
play_convo = true,
},
},
num_waves = 2,
cur_wave = 1,
finished = false,
},
-- Sniper helis
{
thread_func = "m09_do_attack_heli_wave_thread",
thread = INVALID_THREAD_HANDLE,
waves = { nil, nil },
num_waves = 2,
cur_wave = 1,
finished = false,
},
-- Transport helis
{
thread_func = "m09_do_transport_heli_wave_thread",
thread = INVALID_THREAD_HANDLE,
waves = { nil, nil },
num_waves = 1,
cur_wave = 1,
finished = false,
},
}
M09_zimos_comforting_hos_thread = thread_new("m09_zimos_comforting_hos")
local waves_done = false
-- Keep spawning waves until all waves sets are finished.
while (waves_done == false) do
waves_done = true
for i, wave_set in pairs(wave_data) do
if (wave_set.finished == false) then
-- This wave set hasn't finished yet.
waves_done = false
if (wave_set.thread == INVALID_THREAD_HANDLE or thread_check_done(wave_set.thread)) then
if (wave_set.cur_wave <= wave_set.num_waves) then
--message(wave_set.thread_func, 2.0)
-- Spawn the next wave for this wave set.
wave_set.thread = thread_new(wave_set.thread_func, wave_set.waves[wave_set.cur_wave])
wave_set.cur_wave = wave_set.cur_wave + 1
else
-- This wave set has ended, everyone's dead.
wave_set.finished = true
end
end
end
end
thread_yield()
end
-- Wait for all straggling attackers to be taken care of.
while sizeof_table(M09_enemies_on_the_boat) ~= 0 do
thread_yield()
end
set_force_combat_ready_team("")
thread_kill(M09_zimos_comforting_hos_thread)
M09_zimos_comforting_hos_thread = INVALID_THREAD_HANDLE
-- All attackers are dead.
thread_kill(M09_get_to_south_platform_thread)
m09_clear_trigger(M09_trigger.south_vantage.name)
delay(3.0)
m09_start_convo_thread(M09_convo.boat_clear_of_danger)
end
-- Call the helis in to pickup the hoes and the player
--
function m09_call_the_helis()
-- set up the escape helis
m09_prep_heli(M09_group.player_pickup)
m09_prep_heli(M09_group.girls_pickup)
m09_set_objective(M09_objective.wait_for_chopper)
-- Switch up the music while we wait for Pierce.
m09_post_music_event(M09_music.boat_pierce_arrive)
-- launch the escape helis
m09_launch_heli(M09_group.player_pickup)
m09_launch_heli(M09_group.girls_pickup)
threads_wait_for_completion(M09_group.player_pickup.thread)
threads_wait_for_completion(M09_group.girls_pickup.thread)
m09_cleanup_distance_check_triggers()
m09_set_objective(M09_objective.jump_to_chopper)
m09_start_convo_thread(M09_convo.get_to_the_chopper)
-- Cleanup any markers
for human in pairs(M09_enemies_on_the_boat) do
M09_enemies_on_the_boat[human] = nil
marker_remove(human)
on_death("", human)
end
m09_clear_trigger(M09_trigger.on_boat_trigger.name)
m09_set_trigger(M09_trigger.heli_entrance, false, true)
while not M09_trigger.heli_entrance.hit do
thread_yield()
end
-- End boat segment music.
m09_post_music_event(M09_music.boat_stop)
end
function m09_cleanup_cargo_ship()
m09_cleanup_all_boat_wave_attackers()
m09_cleanup_all_heli_attackers()
m09_cleanup_all_transport_heli_wave_attackers()
m09_cleanup_all_helis()
m09_clear_all_crates()
m09_clear_all_crew()
if group_is_loaded(M09_group.local_start_vehicle.name) then
group_destroy(M09_group.local_start_vehicle.name)
end
if group_is_loaded(M09_group.remote_start_vehicle.name) then
group_destroy(M09_group.remote_start_vehicle.name)
end
if group_is_loaded(M09_group.weapons.name) then
group_destroy(M09_group.weapons.name)
end
end
-- Launch a wave of attack helicopters and wait until it is complete.
--
function m09_do_attack_heli_wave_thread()
for i, heli_group in pairs(M09_attack_helis) do
heli_group.thread = thread_new("m09_spawn_attack_heli_thread", heli_group)
delay(20.0)
end
-- wait for everything to get started
delay(2.0)
for i, heli_group in pairs(M09_attack_helis) do
threads_wait_for_completion(heli_group.thread)
end
m09_cleanup_all_heli_attackers()
end
-- Sets an objective to move to the south platform of the boat.
--
function m09_do_south_platform_breadcrumb_thread()
m09_set_objective(M09_objective.south_platform)
m09_set_trigger(M09_trigger.south_vantage)
while not M09_trigger.south_vantage.hit do
thread_yield()
end
m09_set_objective(M09_objective.clear_the_boat)
end
-- launch a boat wave and wait until it is complete
--
-- wave_info: (table) information about all of the attacking boats
--
function m09_do_boat_wave_thread(wave_info)
local boat_info = wave_info.boats
local paths = wave_info.paths
M09_allow_attacker_docking = true
if (wave_info.do_south_platform_breadcrumb) then
M09_get_to_south_platform_thread = thread_new("m09_do_south_platform_breadcrumb_thread")
end
for i, boat_group in pairs(boat_info) do
boat_group.thread = thread_new("m09_spawn_attacker_thread", boat_group, paths)
-- wait before launching next group
delay(M09_delay_between_boats)
end
-- wait for everything to get started
delay(2.0)
if wave_info.play_convo == true then
m09_start_convo_thread(M09_convo.hold_off_attackers)
end
-- wait until we are done (all are dead)
for i, boat_group in pairs(boat_info) do
threads_wait_for_completion(boat_group.thread)
end
-- Wait as long as we might wait to clean up a boat that was destroyed.
delay(M09_dead_boat_release_delay)
m09_cleanup_all_boat_wave_attackers()
end
-- launch a wave of transport helis to land on the ho boat.
--
function m09_do_transport_heli_wave_thread()
for i, group in pairs(M09_trans_attack_helis) do
group.heli_group.thread = thread_new("m09_spawn_transport_attack_heli_thread", group)
delay(20.0)
end
for i, group in pairs(M09_trans_attack_helis) do
threads_wait_for_completion(group.heli_group.thread)
end
m09_cleanup_all_transport_heli_wave_attackers()
end
-- setup heli rail stuff
--
function m09_setup_heli_rail()
-- turn off chatter, congrat lines, etc
persona_suppress_ambient_lines(true)
group_create_hidden(M09_group.player_rail.name, true)
-- create helicopter to defend as well
group_create_hidden(M09_group.girls_heli.name, true)
group_create_hidden(M09_group.player_lookat_1.name, true)
-- put the pilots in the helis
vehicle_suppress_npc_exit(M09_group.player_rail.vehicle, true)
vehicle_enter_group_teleport(M09_group.player_rail.pilot, M09_group.player_rail.vehicle)
vehicle_suppress_npc_exit(M09_group.girls_heli.vehicle, true)
vehicle_enter_group_teleport(M09_group.girls_heli.pilot, M09_group.girls_heli.vehicle)
-- Put the girls in the heli container, they go in seats 1-4 and 6-7, per Zach.
if group_is_loaded(M09_group.girls_in_heli_crate.name) == false then
group_create_hidden(M09_group.girls_in_heli_crate.name)
end
local num_girls = sizeof_table(M09_group.girls_in_heli_crate.members)
for i = 1,num_girls do
if i ~= 5 and i <= 7 then
vehicle_enter_teleport(M09_group.girls_in_heli_crate.members[i], M09_group.girls_heli.vehicle, i, true)
else
character_hide(M09_group.girls_in_heli_crate.members[i])
end
end
-- Prevent the radio from turning on in either heli.
radio_block(M09_group.player_rail.vehicle)
radio_block(M09_group.girls_heli.vehicle)
turn_invulnerable(M09_group.player_rail.vehicle)
on_vehicle_destroyed("m09_failure_heli_destroyed_cb", M09_group.girls_heli.vehicle)
marker_add(M09_group.girls_heli.vehicle, MINIMAP_ICON_PROTECT_ACQUIRE, OI_ASSET_DEFEND, OI_FLAGS_FULL)
teleport_vehicle(M09_group.girls_heli.vehicle, M09_group.girls_heli.float_nav)
thread_yield()
group_show(M09_group.girls_heli.name)
group_show(M09_group.girls_in_heli_crate.name)
-- Start the heli flying to a nav point to keep it from plumeting.
helicopter_fly_to_do(M09_group.girls_heli.vehicle, 1, true, "", false, M09_group.girls_heli.pause_nav, 0, false, false, false, false)
spawning_pedestrians(false)
spawning_vehicles(false)
end
-- Teleports the players into the rail heli
--
function m09_players_enter_rail_heli()
teleport_vehicle(M09_group.player_rail.vehicle, M09_group.player_rail.start)
group_show(M09_group.player_rail.name)
-- Start the heli flying to a nav point to keep it from plumeting.
helicopter_fly_to_do(M09_group.player_rail.vehicle, 1, true, "", false, M09_group.player_rail.pause_nav, 0, false, false, false, false)
vehicle_enter_teleport(LOCAL_PLAYER, M09_group.player_rail.vehicle, 2, true)
set_player_can_enter_exit_vehicles(LOCAL_PLAYER, false)
--inv_weapon_add_temporary(LOCAL_PLAYER, M09_heli_weapon, 1, true, true)
inv_weapon_disable_all_but_this_slot(WEAPON_SLOT_EXPLOSIVE, true, SYNC_ALL)
if M09_give_rocket_launcher then
inv_weapon_add_temporary(LOCAL_PLAYER, "Explosive-RocketLauncher", 1, true, true, false, true, WEAPON_LEVEL4)
inv_weapon_disable_slot(WEAPON_SLOT_EXPLOSIVE, false)
end
if In_coop then
vehicle_enter_teleport(REMOTE_PLAYER, M09_group.player_rail.vehicle, 3, true)
set_player_can_enter_exit_vehicles(REMOTE_PLAYER, false)
inv_weapon_add_temporary(REMOTE_PLAYER, M09_heli_weapon, 1, true, true)
if M09_give_rocket_launcher then
inv_weapon_add_temporary(REMOTE_PLAYER, "Explosive-RocketLauncher", 1, true, true, false, true, WEAPON_LEVEL4)
inv_weapon_disable_slot(WEAPON_SLOT_EXPLOSIVE, false)
end
end
end
-- handle all of the speed changes of the player on the rail sequence
--
function m09_do_player_rail()
-- start the girls heli going
M09_group.girls_heli.thread = thread_new("m09_fly_path_set_thread", M09_group.girls_heli.vehicle, M09_group.girls_heli.path)
-- maybe also setup next trigger
for key, trigger in pairs(M09_rail_triggers) do
m09_set_rail_trigger(trigger)
end
delay(0.75)
-- might want this still trigger based to keep things smooth
for i, segment in ipairs(M09_player_rail_segments) do
if segment.stop_at_end then
helicopter_fly_to_direct(M09_group.player_rail.vehicle, segment.speed, segment.path)
else
helicopter_fly_to_direct_dont_stop(M09_group.player_rail.vehicle, segment.speed, segment.path)
end
if (segment.end_callback ~= nil) then
thread_kill(M09_path_end_callback_thread)
M09_path_end_callback_thread = thread_new(segment.end_callback.func, segment.end_callback.args)
end
if vehicle_is_destroyed(M09_group.player_rail.vehicle) and not character_is_dead(LOCAL_PLAYER) then
character_kill(LOCAL_PLAYER)
end
end
end
-- protect the girls on a helicopter
--
function m09_heli_rail()
m09_set_objective(M09_objective.defend_heli)
-- Start the heli walla thingy.
m09_post_audio_event(M09_audio_events.heli_walla, LOCAL_PLAYER)
-- Kick off the music.
m09_post_music_event(M09_music.rail_begin)
delay (3.5)
m09_start_convo_thread(M09_convo.boat_chase)
m09_do_player_rail()
-- Wait for the conversation to finish.
m09_wait_for_convo(30.0)
-- get out
fade_out(0.5)
fade_out_block()
-- Play some audio for loading the truck.
m09_post_audio_event(M09_audio_events.load_truck, LOCAL_PLAYER)
-- Start a delay thread to keep the screen faded out at least as long as the sound plays.
M09_delay_thread = thread_new("delay", 7.5)
group_create(M09_group.girls_truck.name, true)
set_player_can_enter_exit_vehicles(LOCAL_PLAYER, true)
vehicle_exit_teleport(LOCAL_PLAYER)
if In_coop then
set_player_can_enter_exit_vehicles(REMOTE_PLAYER, true)
vehicle_exit_teleport(REMOTE_PLAYER)
end
m09_cleanup_heli_rail()
teleport_coop(M09_checkpoint.truck_route.nav1, M09_checkpoint.truck_route.nav2, true)
-- Get into the truck.
vehicle_enter_teleport(LOCAL_PLAYER, M09_group.girls_truck.vehicle)
if In_coop then
vehicle_enter_teleport(REMOTE_PLAYER, M09_group.girls_truck.vehicle)
end
threads_wait_for_completion(M09_delay_thread)
fade_in(0.5)
fade_in_block()
end
function m09_cleanup_heli_rail()
-- Stop the heli walla thingy.
m09_post_audio_event(M09_audio_events.heli_walla_stop, LOCAL_PLAYER)
-- Stop the rail music.
m09_post_music_event(M09_music.rail_stop)
set_player_can_enter_exit_vehicles(LOCAL_PLAYER, true)
if coop_is_active() then
set_player_can_enter_exit_vehicles(REMOTE_PLAYER, true)
end
-- kill the copter
if group_is_loaded(M09_group.player_rail.name) then
group_destroy(M09_group.player_rail.name)
end
-- kill girls copter
if group_is_loaded(M09_group.girls_heli.name) then
marker_remove(M09_group.girls_heli.vehicle)
on_vehicle_destroyed("", M09_group.girls_heli.vehicle)
group_destroy(M09_group.girls_heli.name)
end
-- Players' and girls' helis
m09_cleanup_all_helis()
-- Destroy the girl group.
if group_is_loaded(M09_group.girls_in_heli_crate.name) then
group_destroy(M09_group.girls_in_heli_crate.name)
end
-- Allow the player to use weapons again
inv_weapon_disable_all_slots(false, SYNC_ALL)
-- Cleanup any audio threads
m09_unload_all_convos()
-- Clean up all attacker groups.
local vehicle_groups = {
M09_group.heli_boats, M09_group.heli_boats_2, M09_group.heli_boats_3, M09_group.heli_tank1, M09_group.heli_tank2,
}
for group_key, group in pairs(vehicle_groups) do
m09_cleanup_rail_group(group)
if group_is_loaded(group.name) then
group_destroy(group.name)
end
end
-- Reset ambient ped and traffic spawning.
spawning_pedestrians(true)
spawning_vehicles(true)
-- allow ambient lines
persona_suppress_ambient_lines(false)
end
-- Check to see if any player is in the girls truck
--
function m09_player_in_truck()
if In_coop then
return get_char_vehicle_name(REMOTE_PLAYER) == M09_group.girls_truck.vehicle
end
return get_char_vehicle_name(LOCAL_PLAYER) == M09_group.girls_truck.vehicle
end
-- Block until a player enters the truck
--
function m09_get_into_truck()
if m09_player_in_truck() then
return
end
m09_set_secondary_objective(M09_objective.take_truck, SYNC_ALL)
marker_add(M09_group.girls_truck.vehicle, MINIMAP_ICON_USE, M09_objective.take_truck.icon)
while not m09_player_in_truck() do
thread_yield()
end
marker_remove(M09_group.girls_truck.vehicle)
m09_clear_seconodary_objective(SYNC_ALL)
end
-- Drive the truck to the specified location. If the player leaves the truck, they will be
-- told to enter it again
--
-- obj_text: (string) Objective text to display when taveling to the trigger
-- trigger: (table) triggr to tell the player to go to
--
function m09_truck_goto_trigger(obj_text, trigger)
m09_set_objective(obj_text)
m09_set_trigger(trigger)
while not trigger.hit do
if not m09_player_in_truck() then
m09_clear_trigger(trigger.name)
m09_get_into_truck()
m09_set_trigger(trigger)
end
thread_yield()
end
end
-- drive the truck to one of 2 destinations
--
function m09_truck_route()
on_vehicle_destroyed("m09_failure_truck_destroyed_cb", M09_group.girls_truck.vehicle)
on_vehicle_enter_water("m09_failure_truck_destroyed_cb", M09_group.girls_truck.vehicle)
--m09_get_into_truck()
--player_choice_tut_open("m09")
-- Post the event to start the girls whining/tumbling around in the truck.
m09_post_audio_event(M09_audio_events.stripper_cargo, M09_group.girls_truck.vehicle)
m09_set_objective(M09_objective.choice)
m09_set_trigger(M09_trigger.to_saints_trigger, false, false)
marker_add_trigger(M09_trigger.to_saints_trigger.name, MINIMAP_ICON_SAINTS, INGAME_EFFECT_CHECKPOINT, OI_ASSET_COOP, OI_FLAGS_LOCATION, SYNC_ALL)
m09_set_trigger(M09_trigger.to_brothel_trigger, false, false)
marker_add_trigger(M09_trigger.to_brothel_trigger.name, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
object_indicator_add_objective_text(M09_trigger.to_brothel_trigger.name, "PLAYER_CHOICE_M09_OPTION1_TITLE", "PLAYER_CHOICE_M09_OPTION1_BODY")
object_indicator_add_objective_text(M09_trigger.to_saints_trigger.name, "PLAYER_CHOICE_M09_OPTION2_TITLE", "PLAYER_CHOICE_M09_OPTION2_BODY")
while not M09_trigger.to_saints_trigger.hit and not M09_trigger.to_brothel_trigger.hit do
if not m09_player_in_truck() then
m09_clear_trigger(M09_trigger.to_saints_trigger.name)
m09_clear_trigger(M09_trigger.to_brothel_trigger.name)
m09_get_into_truck()
m09_set_trigger(M09_trigger.to_saints_trigger, false, false)
marker_add_trigger(M09_trigger.to_saints_trigger.name, MINIMAP_ICON_SAINTS, INGAME_EFFECT_CHECKPOINT, OI_ASSET_COOP, OI_FLAGS_LOCATION, SYNC_ALL)
m09_set_trigger(M09_trigger.to_brothel_trigger, false, false)
marker_add_trigger(M09_trigger.to_brothel_trigger.name, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
end
thread_yield()
end
-- we want notoriety spawns here
notoriety_force_no_spawn("morningstar", false)
m09_clear_trigger(M09_trigger.to_saints_trigger.name)
m09_clear_trigger(M09_trigger.to_brothel_trigger.name)
if M09_trigger.to_saints_trigger.hit then
--m09_start_convo_thread(M09_convo.choice_crib)
--m09_truck_goto_trigger(M09_objective.to_hq, M09_trigger.saints_hq)
mission_set_excluded_reward("Lump_Sum_of_Money")
m09_play_persona_line(M09_persona_line.choice_crib)
else
--m09_start_convo_thread(M09_convo.choice_morningstar)
--m09_truck_goto_trigger(M09_objective.to_brothel, M09_trigger.brothel)
mission_set_excluded_reward("Weekly_cash_for_hos")
M09_player_chose_brothel = true
m09_play_persona_line(M09_persona_line.choice_morningstar)
end
delay(1.0)
-- Wait for a maximum of 10 seconds in case things break horribly.
m09_wait_for_persona_line(LOCAL_PLAYER, 10.0)
delay(1.0)
end
-- ***************************************************
-- m09_run Helper Functions
-- ***************************************************
-- Waits for a conversation to finish, or a maximum wait time has elapsed in
-- the case that the conversation fails to play.
--
-- max_wait: (float) Max seconds to wait before we stop the conversation and continue.
--
function m09_wait_for_convo(max_wait)
-- Waits for anything else that's using the failsafe thread to finish.
if M09_failsafe_thread ~= INVALID_THREAD_HANDLE then
while thread_check_done(M09_failsafe_thread) == false do
thread_yield()
end
end
M09_failsafe_thread = thread_new("delay", max_wait)
-- Wait for the conversation to finish or for our max wait time to elapse.
while M09_active_convo ~= "" and thread_check_done(M09_failsafe_thread) == false do
thread_yield()
end
if M09_active_convo ~= "" then
-- End the conversation if it's still playing.
for key, convo in pairs(M09_active_convo.files) do
if convo.handle ~= nil then
audio_conversation_end(convo.handle)
convo.handle = nil
end
end
if M09_active_convo.thread ~= INVALID_THREAD_HANDLE then
thread_kill(M09_active_convo.thread)
M09_active_convo.thread = INVALID_THREAD_HANDLE
end
M09_active_convo = ""
end
thread_kill(M09_failsafe_thread)
M09_failsafe_thread = INVALID_THREAD_HANDLE
end
-- Waits for a character's voice line to finish, or until a maximum time has elapsed.
--
-- char: (string) character whose voice line we're waiting for.
-- max_wait: (float) maximum time to wait.
--
function m09_wait_for_persona_line(char, max_wait)
-- Waits for anything else that's using the failsafe thread to finish.
if M09_failsafe_thread ~= INVALID_THREAD_HANDLE then
while thread_check_done(M09_failsafe_thread) == false do
thread_yield()
end
end
M09_failsafe_thread = thread_new("delay", max_wait)
-- Wait for the line to finish or for our max wait time to elapse.
while audio_persona_line_playing(char) and thread_check_done(M09_failsafe_thread) == false do
thread_yield()
end
thread_kill(M09_failsafe_thread)
M09_failsafe_thread = INVALID_THREAD_HANDLE
end
-- Leashes Zimos to a new nav point. The girls following him will
-- in turn move there as well.
--
-- nav_point: Name of the nav point to move Zimos to.
--
function m09_move_zimos_and_girls(nav_point)
M09_girls_flee_nav = nav_point
end
-- Locks all the crate doors; cutscenes will unlock the script movers in reset_peer...
--
function m09_lock_crate_doors()
for i, set in pairs(M09_crate_sets) do
for j, crate in pairs(set.crates) do
door_lock(crate.door, true)
end
end
end
-- Plays the next heli drop off conversation in the progression.
--
function m09_play_heli_drop_off_convo()
if M09_heli_drop_off_convo == 1 then
m09_start_convo_thread(M09_convo.heli_drop_off_01)
elseif M09_heli_drop_off_convo == 2 then
m09_start_convo_thread(M09_convo.heli_drop_off_02)
elseif M09_heli_drop_off_convo == 3 then
m09_start_convo_thread(M09_convo.heli_drop_off_03)
end
M09_heli_drop_off_convo = M09_heli_drop_off_convo + 1
end
-- Posts a music event.
--
-- event_name: Name of the event to post.
--
function m09_post_music_event(event_name)
audio_object_post_event(event_name, nil, nil, LOCAL_PLAYER)
end
-- Posts an event on an object's audio object.
--
-- event_table: Table containing info for the event.
-- event_obj: The object to post the event on.
function m09_post_audio_event(event_table, event_obj)
audio_object_post_event(event_table.event, event_table.switch_group, event_table.switch, event_obj)
end
-- setup followers as necessary
--
-- homie_table: (table) homie information
--
function m09_setup_crew( homie_table )
group_create(homie_table.name, true)
party_add( homie_table.zimos, LOCAL_PLAYER )
on_death("m09_failure_zimos_died_cb", homie_table.zimos)
M09_Zimos = homie_table.zimos
for key, line in pairs(M09_persona_line.follow_zimos) do
line.character = M09_Zimos
end
M09_persona_line.zimos_to_hos.character = M09_Zimos
M09_persona_line.heli_at_platform.character = M09_Zimos
M09_persona_line.heli_drop_off_02.character = M09_Zimos
M09_persona_line.heli_drop_off_03.character = M09_Zimos
follower_set_can_abandon(M09_Zimos, true)
on_dismiss("m09_zimos_abandoned_cb", M09_Zimos)
end
-- setup and play cte
--
function m09_play_cte()
-- Fade out early to spawn CTE group
fade_out(0.5)
fade_out_block()
-- Spawn CTE group members
group_create( M09_group.cte_npc_group.name, true )
-- Stop the cargo ship camera shake.
camera_shake_stop()
-- Fade to black and set up widescreen bars
cutscene_in()
-- Play CTE
cutscene_play( CUTSCENE_CTE_BOATS )
-- Fade to black and take off widescreen bars
cutscene_out()
-- Destroy the CTE group
group_destroy( M09_group.cte_npc_group.name )
-- Start up the camera shake again.
camera_shake_play_looping(M09_cargo_ship_camera_shake, M09_cargo_ship_camera_shake_amt)
-- Fade back in
fade_in(0.5)
fade_in_block()
end
-- clear followers as necessary
--
-- homie_table: (table) homie information
--
function m09_clear_crew( homie_table )
if group_is_loaded(homie_table.name) then
on_death("", homie_table.zimos)
on_dismiss("", M09_Zimos)
group_destroy(homie_table.name)
end
end
-- clear all crew tables
--
function m09_clear_all_crew()
m09_clear_crew(M09_group.start_homies)
m09_clear_crew(M09_group.gangway_homies)
end
-- Set a trigger enabled with a mission marker
--
-- trigger_table: (table) trigger information
-- add_waypoint: (bool, optional) true to add a waypoint, else dont (default true)
-- add_marker: (bool, optional) true to add a marker, else dont (default true)
--
function m09_set_trigger(trigger_table, add_waypoint, add_marker)
trigger_table.hit = false
if add_waypoint == nil or add_waypoint == true then
mission_waypoint_add(trigger_table.name)
end
if add_marker == nil or add_marker == true then
marker_add_trigger(trigger_table.name, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
end
trigger_enable(trigger_table.name, true)
on_trigger(trigger_table.callback, trigger_table.name)
on_trigger_exit(trigger_table.on_exit, trigger_table.name)
end
-- Disable trigger/clear callback/remove markers
--
-- trigger: (string) name of the trigger
--
function m09_clear_trigger(trigger)
on_trigger("", trigger)
on_trigger_exit("", trigger)
trigger_enable(trigger, false)
marker_remove_trigger(trigger, SYNC_ALL)
mission_waypoint_remove()
end
-- Clear all of the triggers in this mission
--
function m09_clear_all_triggers()
for i, trigger in pairs(M09_trigger) do
m09_clear_trigger(trigger.name)
end
end
-- setup a trigger for the rail sequence (no indicator)
--
-- rail_trigger: (table) trigger information
--
function m09_set_rail_trigger(rail_trigger)
rail_trigger.hit = false
trigger_enable(rail_trigger.name, true)
on_trigger(rail_trigger.callback, rail_trigger.name)
end
-- Enables the specified spawn regions and loads the table of groups into the continuous spawn system
--
-- groups: (table) groups to enable
-- respawn_delay: (float) time, in seconds, to wait before respawing a group
-- regions: (table) spawn regions to enable
--
function m09_start_continuous_spawns(groups, respawn_delay, regions)
continuous_spawn_regions_enable(regions, true)
for key, group in pairs(groups) do
continuous_spawn_start(group, 0, respawn_delay)
end
end
-- Disables all continuous spawn groups and regions
--
function m09_cleanup_all_continuous_spawns()
cleanup_spawn_groups(M09_spawn_groups)
cleanup_spawn_regions(M09_spawn_regions)
end
local M09_active_roof_group = ""
function m09_find_trigger(trigger_name)
for key, trigger in pairs(M09_trigger) do
if trigger.name == trigger_name then
return trigger
end
end
return ""
end
function m09_heli_face_target(args)
helicopter_set_path_orientation(args[1], HELI_PF_RIGHT_SIDE_FACE_TARGT, args[2])
end
function m09_heli_stop_facing_target(args)
helicopter_set_path_orientation(args[1], HELI_PF_FACE_ALONG_PATH)
end
function m09_wind_down_rail_music()
m09_post_music_event(M09_music.rail_wind_down)
delay (2.0)
m09_start_convo_thread(M09_convo.choice_suggestion)
end
function m09_fire_scripted_rpg(rpgs)
--[[
local trigger = m09_find_trigger(trigger_name)
if trigger == "" then
--message("Missing Trigger: " .. trigger_name, 4.0)
return
end
--]]
for i, rpg in pairs(rpgs) do
delay(rpg.delay)
projectile_fire_from_navpoint(rpg.origin, rpg.target, "Explosive-RocketLauncher", 0.0)
end
--m09_clear_trigger(trigger_name)
end
function m09_prep_roof_group_cb(human, trigger_name)
local trigger = m09_find_trigger(trigger_name)
if trigger == "" then
--message("Missing Trigger: " .. trigger_name, 4.0)
return
end
if trigger.group.spawned == true then
return
end
trigger.group.spawned = true
m09_clear_trigger(trigger_name)
m09_cleanup_roof()
m09_setup_roof(trigger.group)
end
function m09_cleanup_roof()
if M09_active_roof_group == "" then
return
end
if group_is_loaded(M09_active_roof_group.name) then
for key, npc in pairs(M09_active_roof_group.members) do
marker_remove(npc)
on_death("", npc)
end
release_to_world(M09_active_roof_group.name)
group_destroy(M09_active_roof_group.name)
end
M09_active_roof_group = ""
end
function m09_setup_roof(group)
group_create(group.name, true)
--[[
for key, npc in pairs(group.members) do
marker_add(npc, MINIMAP_ICON_KILL, OI_ASSET_KILL, OI_FLAGS_DEFAULT, SYNC_ALL)
on_death("m09_attacker_killed_cb", npc)
end
]]
M09_active_roof_group = group
end
function m09_setup_boats_cb(human, trigger_name)
local trigger = m09_find_trigger(trigger_name)
local group = trigger.group
-- Make sure we only spawn this group once.
if trigger.spawned == true then
return
end
trigger.spawned = true
m09_clear_trigger(trigger_name)
group_create_hidden(group.name, true)
for key, boat in pairs(group.vehicles) do
vehicle_suppress_npc_exit(boat.vehicle, true)
if boat.gunner ~= nil then
vehicle_enter_teleport(boat.gunner, boat.vehicle, 1, true)
end
if boat.members ~= nil then
vehicle_enter_group_teleport(boat.members, boat.vehicle)
end
if boat.start_ai_disabled == true then
-- Disable all AI for the group until it is enabled later.
for i, member in pairs(group.members) do
set_ignore_ai_flag(member)
end
else
-- Make the driver ignore stuff so that they don't chase the player after they finish their path.
local driver_name = vehicle_get_driver(boat.vehicle)
if driver_name ~= nil then
set_ignore_ai_flag(driver_name)
end
end
if boat.speed ~= nil and boat.speed ~= "" then
vehicle_speed_override(boat.vehicle, boat.speed)
elseif group.speed ~= nil and group.speed ~= "" then
vehicle_speed_override(boat.vehicle, group.speed)
end
if boat.path ~= "" then
boat.pathfind_thread = thread_new("M09_vehicle_pathfind_thread", boat.vehicle, boat.path, boat)
else
while vehicle_exists(boat.vehicle) == false do
thread_yield()
end
vehicle_stop(boat.vehicle)
end
if boat.members ~= nil then
for key, member in pairs(boat.members) do
-- If the group is flagged with trailing aim, then set that on all NPCs in the group.
if boat.trailing_aim == true then
set_trailing_aim_flag(member, true)
end
-- Inform the dudes of the helicopter.
if boat.target_player == true then
ai_add_enemy_target(member, LOCAL_PLAYER, ATTACK_NOW_NEVER_LOSE, true)
else
ai_add_enemy_target(member, M09_group.girls_heli.pilot, ATTACK_NOW_NEVER_LOSE)
end
npc_refire_rate_override(member, 5000)
end
end
end
group_show(group.name)
-- If a thread function was specified for this group, start it up.
if group.thread_func ~= nil then
group.thread = thread_new(group.thread_func, group)
end
for key, boat in pairs(group.vehicles) do
if boat.pathfind_thread ~= INVALID_THREAD_HANDLE then
threads_wait_for_completion(boat.pathfind_thread)
end
end
delay(20.0)
m09_cleanup_rail_group(group)
group_destroy(group.name)
end
function m09_audio_trigger_cb(human, trigger_name)
local trigger = m09_find_trigger(trigger_name)
local audio_set= trigger.convo
m09_clear_trigger(trigger_name)
m09_start_convo_thread(audio_set)
end
-- ***************************************************
-- m09_initialize Helper Functions
-- ***************************************************
-- Handle any common initialization
--
function m09_initialize_common()
-- Perform any necessary zone swaps
city_zone_swap("cargo")
m09_load_heli_rail_personas()
-- Start all ambient emitters.
for i, emitter in pairs(M09_temporary_emitters) do
audio_ambient_emitter_start(emitter)
end
end
-- Checkpoint specific initialization
--
-- checkpoint: The checkpoint to be initialized
-- is_restart: Whether or not the mission is restarting.
--
function m09_initialize_checkpoint(checkpoint, is_restart)
if (checkpoint == M09_checkpoint.start.name) then
if is_restart == true then
teleport_coop(M09_checkpoint.start.nav1, M09_checkpoint.start.nav2, true)
end
m09_setup_crew(M09_group.start_homies)
group_create(M09_group.local_start_vehicle.name, true)
vehicle_enter_teleport(LOCAL_PLAYER, M09_group.local_start_vehicle.vehicle, 0, true)
vehicle_enter_teleport(M09_Zimos, M09_group.local_start_vehicle.vehicle, 1, true)
if In_coop then
group_create(M09_group.remote_start_vehicle.name, true)
vehicle_enter_teleport(REMOTE_PLAYER, M09_group.remote_start_vehicle.vehicle, 0, true)
end
m09_spawn_ship_guards()
delay(1.5)
m09_start_convo_thread(M09_convo.to_boat)
M09_play_find_minigun_line = true
-- Make sure morningstar notoriety is what we'd expect it to be.
notoriety_reset("morningstar")
else
-- any other checkpoint should be high notoriety
notoriety_force_no_spawn("morningstar", true)
notoriety_set_min("morningstar", M09_min_notoriety)
notoriety_set_max("morningstar", M09_max_notoriety)
end
if (checkpoint == M09_checkpoint.gangway.name) then
teleport_coop(M09_checkpoint.gangway.nav1, M09_checkpoint.gangway.nav2, true)
m09_setup_crew(M09_group.gangway_homies)
teleport(M09_Zimos, M09_checkpoint.gangway.nav1, true, false, 1.0)
m09_spawn_ship_guards()
m09_setup_distance_check_triggers()
M09_play_find_minigun_line = true
end
if (checkpoint == M09_checkpoint.defend_girls.name) then
teleport_coop(M09_checkpoint.defend_girls.nav1, M09_checkpoint.defend_girls.nav2, true)
-- Disable all audio emitters that were disabled by opening crates.
for i, emitter in pairs(M09_temporary_emitters) do
audio_ambient_emitter_stop(emitter)
end
-- Start music for the boat segment.
m09_post_music_event(M09_music.boat_begin)
group_create(M09_group.girls_in_heli_crate, true)
group_create(M09_group.weapons, true)
m09_setup_crew(M09_group.gangway_homies)
teleport(M09_Zimos, M09_nav.zimos_girls[3], true, false, 0.0, 0.0, -1.0)
m09_setup_distance_check_triggers()
M09_girls_found = true
m09_set_trigger(M09_trigger.on_boat_trigger, false, false)
-- Start the girls cowering.
for i, girl in pairs(M09_group.girls_in_heli_crate.members) do
set_always_cower_flag(girl, true)
end
-- Leash Zimos to a nav point near the girls
m09_move_zimos_and_girls(M09_nav.zimos_girls[3])
if M09_zimos_girl_thread == INVALID_THREAD_HANDLE then
M09_zimos_girl_thread = thread_new("m09_zimos_girl_behavior_thread")
end
-- Start the camera shake, must be done after the teleport.
camera_shake_play_looping(M09_cargo_ship_camera_shake, M09_cargo_ship_camera_shake_amt)
end
if (checkpoint == M09_checkpoint.heli_rail.name) then
teleport_coop(M09_checkpoint.heli_rail.nav1, M09_checkpoint.heli_rail.nav2, true)
-- Disable all audio emitters that were disabled by opening crates.
for i, emitter in pairs(M09_temporary_emitters) do
audio_ambient_emitter_stop(emitter)
end
group_create(M09_group.girls_in_heli_crate, true)
m09_setup_heli_rail()
m09_players_enter_rail_heli()
end
if (checkpoint == M09_checkpoint.truck_route.name) then
group_create(M09_group.girls_truck.name, true)
teleport_coop(M09_checkpoint.truck_route.nav1, M09_checkpoint.truck_route.nav2, true)
vehicle_enter_teleport(LOCAL_PLAYER, M09_group.girls_truck.vehicle)
if In_coop then
vehicle_enter_teleport(REMOTE_PLAYER, M09_group.girls_truck.vehicle)
end
end
end
-- ***************************************************
-- Miscellaneous m09 Helper Funcrtions
-- ***************************************************
-- Places small kill markers over guys in a rail group.
--
function m09_mark_rail_group_trigger(human, trigger_name)
local trigger = m09_find_trigger(trigger_name)
if trigger == "" then
--message("Missing Trigger: " .. trigger_name, 4.0)
return
end
m09_clear_trigger(trigger_name)
for i, group in pairs(trigger.groups) do
for key, vehicle_info in pairs(group.vehicles) do
if vehicle_is_destroyed(vehicle_info.vehicle) == false then
marker_add(vehicle_info.vehicle, MINIMAP_ICON_KILL, OI_ASSET_KILL, OI_FLAGS_DEFAULT, SYNC_ALL)
on_vehicle_destroyed("m09_remove_vehicle_marker_cb", vehicle_info.vehicle)
end
if group.start_ai_disabled == true then
-- Enable the AI for everyone but the driver.
local driver_name = vehicle_get_driver(vehicle_info.vehicle)
for i, member in pairs(vehicle_info.members) do
if member ~= driver_name then
set_ignore_ai_flag(member, false)
end
end
end
end
end
end
-- Cleans up a group's markers and stuff during the rail section.
--
-- human: The human that tripped the trigger.
-- trigger_name: The name of the trigger that was tripped.
--
function m09_cleanup_rail_group_trigger(human, trigger_name)
local trigger = m09_find_trigger(trigger_name)
if trigger == "" then
--message("Missing Trigger: " .. trigger_name, 4.0)
return
end
m09_clear_trigger(trigger_name)
for i, group in pairs(trigger.groups) do
m09_cleanup_rail_group(group)
end
end
-- Cleans up a rail group, removing the marker from the vehicles in the group.
--
-- group: (table) group info
--
function m09_cleanup_rail_group(group)
if group_is_loaded(group.name) == false then
return
end
if group.vehicles ~= nil then
for i, vehicle_info in pairs(group.vehicles) do
marker_remove(vehicle_info.vehicle)
on_vehicle_destroyed("", vehicle_info.vehicle)
if vehicle_info.pathfind_thread ~= INVALID_THREAD_HANDLE then
thread_kill(vehicle_info.pathfind_thread)
vehicle_info.pathfind_thread = INVALID_THREAD_HANDLE
end
end
end
if group.members ~= nil then
for i, member in pairs(group.members) do
on_death("", member)
marker_remove(member)
end
end
if group.thread ~= nil then
thread_kill(group.thread)
group.thread = INVALID_THREAD_HANDLE
end
end
-- common cleanup stuff
--
-- attacker: (table) attacker information
function m09_cleanup_attacker_common(attacker)
if group_is_loaded(attacker.name) then
marker_remove(attacker.vehicle)
on_vehicle_destroyed("", attacker.vehicle)
release_to_world(attacker.name)
group_destroy(attacker.name)
end
thread_kill(attacker.thread)
end
-- cleanup attacker
--
-- attacker: (table) attacker information
--
function m09_cleanup_boat_attacker(attacker)
-- remove on death callback and markers for members
if group_is_loaded(attacker.name) then
for i,baddie in pairs(attacker.members) do
on_death("", baddie)
on_ai_do_action_complete("", baddie)
marker_remove(baddie)
if not character_is_dead(baddie) then
set_ignore_ai_flag(baddie, false)
npc_hearing_enable(baddie, true)
npc_combat_enable(baddie, true)
end
M09_enemies_on_the_boat[baddie] = nil
end
end
m09_cleanup_attacker_common(attacker)
attacker.is_docking = false
thread_kill(attacker.pathfind_thread)
end
-- cleanup transport helicopter attacker
--
-- attacker: (table) attacker information
--
function m09_cleanup_transport_heli_attacker(attacker)
-- remove on death callback and markers for members
if group_is_loaded(attacker.heli_group.name) then
--[[
if (attacker.heli_group.debug_done == false) then
message("Cleaning up transport that isn't done", 4.0)
end
--]]
on_death("", attacker.heli_group.pilot)
on_ai_do_action_complete("", attacker.heli_group.pilot)
marker_remove(attacker.heli_group.pilot)
on_vehicle_destroyed("", attacker.heli_group.vehicle)
end
if group_is_loaded(attacker.soldier_group.name) then
for i,baddie in pairs(attacker.soldier_group.members) do
on_death("", baddie)
on_ai_do_action_complete("", baddie)
marker_remove(baddie)
end
release_to_world(attacker.soldier_group.name)
group_destroy(attacker.soldier_group.name)
end
m09_cleanup_attacker_common(attacker.heli_group)
end
-- Cleans up a helicopter attacker.
--
-- attacker: (table) attacker information
--
function m09_cleanup_heli_attacker(attacker)
if group_is_loaded(attacker.name) then
marker_remove(attacker.vehicle)
on_vehicle_destroyed("", attacker.vehicle)
release_to_world(attacker.name)
group_destroy(attacker.name)
end
end
-- Clean up all attack helicopters.
--
function m09_cleanup_all_heli_attackers()
for key, heli_group in pairs(M09_attack_helis) do
m09_cleanup_heli_attacker(heli_group)
end
end
-- do the cleanup dance for all boat wave attackers
--
function m09_cleanup_all_boat_wave_attackers()
for key, boat_group in pairs(M09_boats) do
m09_cleanup_boat_attacker(boat_group)
end
end
-- Clean up all transport attack helis.
--
function m09_cleanup_all_transport_heli_wave_attackers()
for i, heli_group in pairs(M09_trans_attack_helis) do
m09_cleanup_transport_heli_attacker(heli_group)
end
end
-- Create heli group, put pilot into heli and hold at initial navpoint
--
-- heli: (table) heli information
--
function m09_prep_heli(heli)
group_create(heli.name, true)
vehicle_enter_teleport(heli.pilot, heli.vehicle)
-- pop the chopper off the ground to get it going
teleport_vehicle(heli.vehicle, heli.float_nav)
-- stay there
heli.thread = thread_new("m09_fly_path_thread", heli.vehicle, 10.0, heli.float_nav)
end
-- send heli on his path
--
-- heli: (table) heli information
--
function m09_launch_heli(heli)
-- kill the float thread
thread_kill(heli.thread)
-- clean up any markers set on them
on_vehicle_destroyed("m09_remove_marker_cb", heli.vehicle)
-- send them on their way
heli.thread = thread_new("m09_fly_path_set_thread", heli.vehicle, heli.path)
end
-- cleanup the heli
--
-- heli: (table) heli information
--
function m09_cleanup_heli(heli)
if group_is_loaded(heli.name) then
on_vehicle_destroyed("", heli.vehicle)
marker_remove(heli.vehicle)
group_destroy(heli.name)
end
thread_kill(heli.thread)
end
-- do the cleanup dance for all generic helis
--
function m09_cleanup_all_helis()
m09_cleanup_heli(M09_group.player_pickup)
m09_cleanup_heli(M09_group.girls_pickup)
end
-- Sets the primary and secondary objectives for the players.
--
function m09_set_objectives_internal()
-- Clear objectives for both players.
objective_text_clear(0)
objective_text_clear(1)
if M09_secondary_obj[SYNC_LOCAL] == nil then
-- No secondary objective for the local player, set the primary objective.
if M09_current_obj ~= nil and M09_current_obj ~= "" then
objective_text(0, M09_current_obj.name, M09_obj_str1, M09_obj_str2, SYNC_LOCAL, M09_current_obj.icon)
end
else
-- Local player has a secondary objective, use that.
objective_text(0, M09_secondary_obj[SYNC_LOCAL].name, "", "", SYNC_LOCAL, M09_secondary_obj[SYNC_LOCAL].icon)
end
if M09_secondary_obj[SYNC_REMOTE] == nil then
-- No secondary objective for the remote player, set the primary objective.
if M09_current_obj ~= nil and M09_current_obj ~= "" then
objective_text(1, M09_current_obj.name, M09_obj_str1, M09_obj_str2, SYNC_REMOTE, M09_current_obj.icon)
end
else
-- Remote player has a secondary objective, use that.
objective_text(1, M09_secondary_obj[SYNC_REMOTE].name, "", "", SYNC_REMOTE, M09_secondary_obj[SYNC_REMOTE].icon)
end
end
function m09_set_objective(obj, str1, str2)
M09_current_obj = obj
if str1 == nil then
str1 = ""
end
if str2 == nil then
str2 = ""
end
M09_obj_str1 = str1
M09_obj_str2 = str2
m09_set_objectives_internal()
end
function m09_clear_objective()
M09_current_obj = ""
M09_obj_str1 = ""
M09_obj_str2 = ""
m09_set_objectives_internal()
end
function m09_set_secondary_objective(obj, sync)
M09_secondary_obj[sync] = obj
m09_set_objectives_internal()
-- Don't disable the crates anymore, since we're not displaying the "get
-- back to the boat" radius/message for both players in co-op.
--m09_disable_active_crates()
end
function m09_clear_seconodary_objective(sync)
M09_secondary_obj[sync] = nil
m09_set_objectives_internal()
m09_enable_active_crates()
end
-- *************** ***************
-- *************** Crate Stuff ***************
-- *************** ***************
-- Set a trigger enabled with a mission marker
--
-- trigger: (string) Name of the trigger
--
function m09_set_crate_trigger(crate)
if M09_crates_disabled then
return
end
trigger_enable(crate.trigger, true)
if crate.content ~= M09_CRATE_BRUTE and crate.content ~= M09_CRATE_BRUTE_GAT then
marker_add_trigger(crate.trigger, MINIMAP_ICON_USE, nil, OI_ASSET_USE, OI_FLAGS_DEFAULT + OI_FLAG_FADE, SYNC_ALL)
end
on_trigger("m09_trigger_crate_cb", crate.trigger)
end
-- Disable crate trigger
--
-- trigger: (string) trigger name
--
function m09_clear_crate_trigger(trigger)
on_trigger("", trigger)
trigger_enable(trigger, false)
marker_remove_trigger(trigger, SYNC_ALL)
end
-- Process a complete crate open QTE
--
-- crate: (table) crate information
-- successful: (boolean) true if QTE was successful
-- player: (string) player opening the crate
--
function m09_crate_door_open(crate, successful, player)
if successful then
-- Make sure we don't somehow open the same crate multiple times.
if crate.opened == true then
return
end
crate.opened = true
-- Stop the audio emitter if one is specified.
if crate.emitter_to_stop ~= nil then
audio_ambient_emitter_stop(crate.emitter_to_stop)
end
-- Post the audio event if one is specified.
if crate.door_open_event ~= nil then
audio_object_post_event(crate.door_open_event, crate.door_open_switch_group, crate.door_open_switch, crate.door_open_event_object)
end
-- Before opening a crate full of girls, set them up to cower 'n stuff.
if crate.content == M09_CRATE_GIRLS then
for i, girl in pairs(crate.group.members) do
set_ignore_ai_flag(girl, false)
npc_hearing_enable(girl, false)
npc_combat_enable(girl, false)
set_always_cower_flag(girl, true)
character_allow_ragdoll(girl, false)
set_dont_attack_me_on_sight_flag(girl, true)
set_team(girl, "Playas")
end
end
-- If the crate has a script group of weapons to spawn, do that now.
if crate.ammo_group ~= nil then
group_create(crate.ammo_group.name, true)
end
-- Play the animation to open the crate door.
door_open(crate.door)
if crate.player_anim ~= nil then
action_play(player, crate.player_anim, crate.player_anim, false, 0.8, false, true, crate.anim_nav)
end
if crate.content == M09_CRATE_BOMB then
delay(0.25)
explosion_create("Flashbang", crate.door, player)
elseif crate.content == M09_CRATE_ENEMIES or crate.content == M09_CRATE_BRUTE or crate.content == M09_CRATE_BRUTE_GAT then
for i, enemy in pairs(crate.group.members) do
set_ignore_ai_flag( enemy, false )
npc_hearing_enable(enemy, true)
turn_vulnerable(enemy)
ai_add_enemy_target(enemy, player, ATTACK_NOW_NEVER_LOSE)
if crate.run_to ~= "" then
local should_fire = true
local should_run = true
ai_do_scripted_move(enemy, crate.run_to, should_run, should_fire)
end
end
if crate.content == M09_CRATE_BRUTE then
delay(3.0)
m09_play_persona_line(M09_persona_line.melee_brute)
M09_brute_list[crate.group.members[1]] = true
elseif crate.content == M09_CRATE_BRUTE_GAT then
delay(3.0)
m09_play_persona_line(M09_persona_line.gat_brute)
M09_brute_list[crate.group.members[1]] = true
end
elseif crate.content == M09_CRATE_GIRLS then
M09_found_girl_crates = M09_found_girl_crates + 1
m09_set_objective(M09_objective.find_girls, M09_found_girl_crates, sizeof_table(M09_girl_crate))
for i, girl in pairs(crate.group.members) do
M09_girls_following[girl] = girl
end
crate.just_opened = true
-- Set characters for the girl thanks and complain lines.
M09_persona_line.girl_thanks_1.character = crate.group.members[1]
M09_persona_line.girl_thanks_2.character = crate.group.members[2]
M09_persona_line.girl_complain_1.character = crate.group.members[1]
M09_persona_line.girl_complain_2.character = crate.group.members[2]
if M09_goto_zimos_line == 1 then
M09_persona_line.goto_zimos[1].character = player
m09_start_convo_thread(M09_convo.zimos_01)
elseif M09_goto_zimos_line == 2 then
M09_persona_line.goto_zimos[2].character = player
m09_start_convo_thread(M09_convo.zimos_02)
elseif M09_goto_zimos_line == 3 then
M09_persona_line.goto_zimos[3].character = player
m09_start_convo_thread(M09_convo.zimos_03)
else
-- Does this line make sense to play? We're going to tell the hos to get into the crate immediately
-- following, so why tell them to follow Zimos?
--m09_start_convo_thread(M09_convo.zimos_04)
end
M09_goto_zimos_line = M09_goto_zimos_line + 1
elseif crate.content == M09_CRATE_GAG then
delay(1.0)
if M09_found_gag_line < 5 then
M09_persona_line.find_gag[M09_found_gag_line].character = player
m09_play_persona_line(M09_persona_line.find_gag[M09_found_gag_line])
end
M09_found_gag_line = M09_found_gag_line + 1
elseif crate.content == M09_CRATE_AMMO then
delay(1.0)
if M09_found_ammo_line < 4 then
M09_persona_line.find_ammo[M09_found_ammo_line].character = player
m09_play_persona_line(M09_persona_line.find_ammo[M09_found_ammo_line])
end
M09_found_ammo_line = M09_found_ammo_line + 1
end
if crate.zimos_nav ~= nil then
-- Move Zimos to the specified nav.
m09_move_zimos_and_girls(crate.zimos_nav)
end
else
-- fail, reset triggers
m09_setup_crate(crate)
end
end
-- setup the trigger on the crate and spawn any people inside if needed
--
-- crate: (table) crate information
--
function m09_setup_crate(crate)
crate.opened = false
m09_set_crate_trigger(crate)
if crate.group ~= "" and not group_is_loaded(crate.group.name) then
group_create(crate.group.name, true)
end
end
-- setup all crates in a set
--
function m09_setup_crate_set(crate_set)
M09_active_crate_set = crate_set
for key, crate in pairs(crate_set.crates) do
door_close(crate.door)
m09_setup_crate(crate)
end
end
function m09_disable_active_crates()
M09_crates_disabled = true
if M09_active_crate_set == "" then
return
end
for key, crate in pairs(M09_active_crate_set.crates) do
m09_clear_crate_trigger(crate.trigger)
end
end
function m09_enable_active_crates()
M09_crates_disabled = false
if M09_active_crate_set == "" then
return
end
for key, crate in pairs(M09_active_crate_set.crates) do
if not door_is_open(crate.door) then
m09_set_crate_trigger(crate)
end
end
end
function m09_num_crates_left(crate_set)
local left = 0
for key, crate in pairs(crate_set.crates) do
if crate.opened == false then
left = left + 1
end
end
return left
end
-- close the doors to all of the crates (WARNING: Don't trap a player inside)
--
function m09_close_all_crate_doors()
for i, crate_set in pairs(M09_crate_sets) do
for key, crate in pairs(crate_set.crates) do
door_close(crate.door)
end
end
end
-- Clear the trigger callback to all of the crates
--
function m09_clear_all_crates()
for i, crate_set in pairs(M09_crate_sets) do
for key, crate in pairs(crate_set.crates) do
m09_clear_crate_trigger(crate.trigger)
if crate.group ~= "" and group_is_loaded(crate.group.name) then
if crate.content == M09_CRATE_BRUTE or crate.content == M09_CRATE_BRUTE_GAT then
m09_remove_makers_and_callbacks(crate)
end
group_destroy(crate.group.name)
if crate.ammo_group ~= nil then
group_destroy(crate.ammo_group.name)
end
end
end
end
end
-- Disables the triggers on all the crates
--
function m09_clear_all_crate_triggers()
for i, crate_set in pairs(M09_crate_sets) do
for key, crate in pairs(crate_set.crates) do
m09_clear_crate_trigger(crate.trigger)
end
end
M09_active_crate_set = ""
end
-- Remove any markers and callbacks associated with a crates members
--
function m09_remove_makers_and_callbacks(crate)
if crate.group == "" or not group_is_loaded(crate.group.name) then
return
end
for i, enemy in pairs(crate.group.members) do
marker_remove(enemy)
on_death("", enemy)
end
end
-- clean up all mission groups
--
function m09_cleanup_groups()
-- defense stuff
m09_cleanup_all_boat_wave_attackers()
m09_cleanup_all_heli_attackers()
m09_cleanup_all_transport_heli_wave_attackers()
-- rail stuff
if group_is_loaded(M09_group.girls_heli.name) then
marker_remove(M09_group.girls_heli.vehicle)
on_vehicle_destroyed("", M09_group.girls_heli.vehicle)
end
m09_cleanup_all_helis()
-- driving stuff
if group_is_loaded(M09_group.girls_truck.name) then
marker_remove(M09_group.girls_truck.vehicle)
on_vehicle_destroyed("", M09_group.girls_truck.vehicle)
on_vehicle_enter_water("", M09_group.girls_truck.vehicle)
end
cleanup_groups(M09_group)
end
-- *************************
--
-- Callback functions
--
-- *************************
-- Called when a vehicle is destroyed and we need to remove the marker from it.
function m09_remove_vehicle_marker_cb(vehicle_name)
on_vehicle_destroyed("", vehicle_name)
marker_remove(vehicle_name)
end
-- Called when a cell call ends.
function m09_cell_call_ended()
M09_cur_cell_call = ""
end
-- Disable front spawns trigger has been hit
--
-- player: (string) player that activated trigger
-- trigger: (string) name of trigger hit
--
function m09_disable_front_spawns_cb(player, trigger)
m09_cleanup_all_continuous_spawns()
m09_clear_trigger(trigger)
end
-- Gangway trigger has been hit
--
-- player: (string) player that activated trigger
-- trigger: (string) name of trigger hit
--
function m09_gangway_trigger_cb(player, trigger)
M09_trigger.gangway.hit = true
m09_clear_trigger(trigger)
end
function m09_heli_entrance_trigger_cb(player, trigger)
M09_trigger.heli_entrance.hit = true
m09_clear_trigger(trigger)
end
function m09_north_vantage_cb(player, trigger)
M09_trigger.north_vantage.hit = true
m09_clear_trigger(trigger)
end
function m09_south_vantage_cb(player, trigger)
M09_trigger.south_vantage.hit = true
m09_clear_trigger(trigger)
end
-- Ho heli crate trigger has been hit
--
-- player: (string) player that activated trigger
-- trigger: (string) name of trigger hit
--
function m09_ho_heli_crate_trigger_cb(player, trigger)
M09_trigger.ho_heli_crate.hit = true
m09_clear_trigger(trigger)
end
-- Zimos death callback
function m09_failure_zimos_died_cb()
-- End the mission, Zimos died
mission_end_failure("m09", "m09_failure_zimos_died")
end
-- Zimos abandoned
function m09_zimos_abandoned_cb()
mission_end_failure("m09", "m09_failure_zimos_abandoned")
end
-- helicopter of girls is gone
function m09_failure_heli_destroyed_cb()
mission_end_failure("m09", "m09_failure_girls_heli")
end
-- truck of girls is gone
function m09_failure_truck_destroyed_cb()
mission_end_failure("m09", "m09_failure_girls_truck")
end
-- count another attacker
--
-- attacker: (string) name of attacker killed
--
function m09_attacker_killed_cb(attacker)
marker_remove(attacker)
release_to_world(attacker)
M09_enemies_on_the_boat[attacker] = nil
on_death("", attacker)
end
-- remove marker on killed object
--
-- killed: (string) name of npc or vehicle killed
--
function m09_remove_marker_cb(killed)
marker_remove(killed)
end
-- Handle an attack heli being blown up.
--
-- heli_name: (string) name of the heli destroyed
--
function m09_attack_heli_destroyed_cb(heli_name)
-- clear our callback
on_vehicle_destroyed("", heli_name)
-- find our boat
for i, heli in pairs(M09_attack_helis) do
if heli.vehicle == heli_name then
marker_remove(heli.vehicle)
thread_kill(heli.thread)
heli.thread = INVALID_THREAD_HANDLE
end
end
end
-- Attacker transport helicopter was destroyed.
--
-- heli_name: (string) name of the heli destroyed
--
function m09_transport_heli_destroyed_cb(heli_name)
for i, heli in pairs(M09_trans_attack_helis) do
if heli.heli_group.vehicle == heli_name then
m09_cleanup_transport_heli_attacker(heli)
end
end
end
-- handle a boat being blown up before arriving
--
-- boat_name: (string) name of vehicle destroyed
--
function m09_boat_destroyed_cb(boat_name)
-- clear our callback
on_vehicle_destroyed("", boat_name)
-- find our boat
for i,boat in pairs(M09_boats) do
if boat.vehicle == boat_name then
if (boat.is_docking) then
M09_allow_attacker_docking = true
end
-- don't need this marker anymore
marker_remove(boat.vehicle)
-- kill the threads
thread_kill(boat.pathfind_thread)
thread_kill(boat.thread)
-- Wait a little while before releasing the group.
-- The ambient spawn system is pretty aggressive at
-- destroying vehicles.
delay(M09_dead_boat_release_delay)
-- release the whole group
release_to_world(boat.name)
group_destroy(boat.name)
-- we're done here
return
end
end
end
-- Sets the hit flag of a trigger when its hit
--
-- human: (string) human that activated the trigger
-- tirgger: (string) trigger that was activated
function m09_set_trigger_hit_cb(human, trigger_name)
for key, trigger in pairs(M09_trigger) do
if trigger.name == trigger_name then
trigger.hit = true
return
end
end
--message("Error: Could not find the trigger " .. trigger_name, 4.0)
return
end
-- Keep track of when NPCs enter the boat
--
function m09_on_boat_enter_cb(human, trigger)
if human == nil or human == "" or get_team(human) ~= "Morningstar" or M09_enemies_on_the_boat[human] == true then
return
end
-- If the dude's in a helicopter, leave him alone.
if get_char_vehicle_type(human) == VT_HELICOPTER then
return
end
marker_remove(human)
if M09_brute_list[human] == true then
marker_add(human, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_DEFAULT, SYNC_ALL)
else
marker_add(human, MINIMAP_ICON_KILL, OI_ASSET_KILL, OI_FLAGS_DEFAULT, SYNC_ALL)
end
M09_enemies_on_the_boat[human] = true
on_death("m09_attacker_killed_cb", human)
end
-- Keep track of when NPCs leave the boat
--
function m09_on_boat_exit_cb(human, trigger)
if human == nil or human == "" or get_team(human) ~= "Morningstar" then
return
end
-- If the dude's in a helicopter, leave him alone.
if get_char_vehicle_type(human) == VT_HELICOPTER then
return
end
on_death("", human)
if not character_is_dead(human) then
character_kill(human)
end
marker_remove(human)
M09_enemies_on_the_boat[human] = nil
end
function m09_player_on_boat_enter_cb(human, trigger)
if human == LOCAL_PLAYER then
M09_local_on_boat = true
marker_remove_trigger(M09_trigger.gangway.name, SYNC_LOCAL)
elseif human == REMOTE_PLAYER then
M09_remote_on_boat = true
marker_remove_trigger(M09_trigger.gangway.name, SYNC_REMOTE)
end
end
function m09_player_on_boat_exit_cb(human, trigger)
if human == LOCAL_PLAYER then
M09_local_on_boat = false
marker_add_trigger(M09_trigger.gangway.name, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_LOCAL)
elseif human == REMOTE_PLAYER then
M09_remote_on_boat = false
marker_add_trigger(M09_trigger.gangway.name, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_REMOTE)
end
end
function m09_show_warn_radius_cb(human, trigger)
if human == LOCAL_PLAYER then
minimap_icon_add_radius("Cargo_Ship_Center", M09_max_player_dist_from_boat * 0.95, SYNC_LOCAL)
m09_set_secondary_objective(M09_objective.go_to_ship, SYNC_LOCAL)
elseif human == REMOTE_PLAYER then
minimap_icon_add_radius("Cargo_Ship_Center", M09_max_player_dist_from_boat * 0.95, SYNC_REMOTE)
m09_set_secondary_objective(M09_objective.go_to_ship, SYNC_REMOTE)
end
end
function m09_remove_warn_radius_cb(human, trigger)
if human == LOCAL_PLAYER then
minimap_icon_remove_radius("Cargo_Ship_Center", SYNC_LOCAL)
m09_clear_seconodary_objective(SYNC_LOCAL)
elseif human == REMOTE_PLAYER then
minimap_icon_remove_radius("Cargo_Ship_Center", SYNC_REMOTE)
m09_clear_seconodary_objective(SYNC_REMOTE)
end
end
function m09_fail_ship_abandoned_cb(human, trigger)
-- TOOD: End Mission Failure
mission_end_failure("m09", "m09_failure_ship_abandoned")
end
-- Returns a gril crate that was just opened, or "" if one isn't found
--
function m09_just_opened_girls_crate()
for key, crate in pairs(M09_girl_crate) do
if crate.just_opened == true then
return crate
end
end
return ""
end
-- Tells a group of NPCs to perform a scripted move and block until the path is complete.
--
-- npcs - Table of npcs to move
-- dest - Destination nav point
-- should_run - Should the NPCs run to the destination?
-- dist_tolerance - Distance the destination the NPC must be within for the path to be considered complete
-- max_sec - Max amount of time, in seconds, the npcs are allowed to pathfind for
--
function m09_do_scripted_move(npcs, dest, should_run, dist_tolerance, max_sec)
local active = {}
-- Tell all NPCs to move to the specified point
for key, npc in pairs(npcs) do
ai_do_scripted_move(npc, dest, should_run, false)
active[key] = npc
end
local sec = 0
while sizeof_table(active) > 0 do
thread_yield()
for key, npc in pairs(active) do
if not ai_scripted_action_is_processing(npc) or get_dist(npc, dest) <= dist_tolerance then
active[key] = nil
end
end
sec = sec + get_frame_time()
if sec > max_sec then
break
end
end
for key, npc in pairs(npcs) do
ai_clear_scripted_action(npc)
end
end
--[[
-- Tells Zimos to collect any girls from a crate that was just opened.
--
function m09_zimos_go_to_opened_crate()
local crate = m09_just_opened_girls_crate()
while crate ~= "" do
-- A crate was just opened. Tell Zimos to go pick up some hoes!
--m09_do_scripted_move({M09_Zimos}, crate.run_to, true, 1.0, 60.0)
-- Zimos should now be in range of the crate. Have them run to Zimos
--m09_do_scripted_move(crate.group.members, crate.run_to, true, 1.0, 6.0)
-- Have all of them follow zimos
for key, girl in pairs(crate.group.members) do
M09_girls_following[girl] = girl
set_team(girl, "Playas")
--npc_leash_to_object(girl, M09_Zimos, 2.0)
inv_item_remove_all(girl)
end
crate.just_opened = false
crate = m09_just_opened_girls_crate()
end
end
--]]
-- Tell Zimos to wander to a near by nav point
--
function m09_zimos_move_to_close_nav()
local dist_to_closest = 1000000.0
for key, nav in pairs(M09_nav.girls_flee_to) do
local dist = get_dist(LOCAL_PLAYER, nav)
if dist < dist_to_closest then
M09_girls_flee_nav = nav
dist_to_closest = dist
end
end
if dist_to_closest < 3.0 then
return
end
-- Is Zimos already there?
if get_dist(M09_Zimos, M09_girls_flee_nav) < 1.0 then
return
end
m09_do_scripted_move({M09_Zimos}, M09_girls_flee_nav, true, 1.0, 5.0)
end
function m09_girls_follow_zimos_thread()
local dist = 0.0
while true do
for girl in pairs(M09_girls_following) do
dist = get_dist(girl, M09_girls_flee_nav)
if dist > 5.0 then
if ai_scripted_action_is_processing(girl) == false then
set_ignore_ai_flag(girl, false)
set_always_cower_flag(girl, false)
ai_do_scripted_move(girl, M09_girls_flee_nav, true, false)
end
elseif dist < 3.0 then
if ai_scripted_action_is_processing(girl) then
ai_clear_scripted_action(girl)
set_cower_variant(girl, get_random_table_entry(M09_stripper_cower_variants))
--set_ignore_ai_flag(girl, true)
set_always_cower_flag(girl, true)
end
end
--ai_do_scripted_move(girl, closest_nav, true, false)
end
delay(0.2)
end
end
--[[
-- Checks to see if Zimos has all the girls. If he does, lead them to the heli crate.
--
function m09_zimos_maybe_drop_off_girls()
if M09_zimos_drop_off_girls == false then
return false
end
ai_do_scripted_move(M09_Zimos, M09_trigger.ho_heli_crate.hoes_run_to, true, false)
m09_start_convo_thread(M09_convo.defend_girls)
thread_kill(M09_girls_follow_zimos_thread)
M09_girls_follow_zimos_thread = INVALID_THREAD_HANDLE
for girl in pairs(M09_girls_following) do
npc_leash_remove(girl)
set_ignore_ai_flag(girl, true)
end
thread_yield()
for girl in pairs(M09_girls_following) do
local should_run = true
local should_fire = false
ai_do_scripted_move(girl, M09_trigger.ho_heli_crate.hoes_run_to, should_run, should_fire)
end
return true
end
--]]
function m09_play_cell_convo(convo)
M09_cur_cell_call = convo.name
audio_play_for_mission_cellphone(convo.name, convo.cell_receive == true, true, "", "m09_cell_call_ended", m09_get_persona_handle(convo))
while M09_cur_cell_call ~= "" do
thread_yield()
end
end
-- Plays a conversation
--
-- convo: Conversation to play
function m09_play_convo(convo)
if convo.name ~= "" and convo.name ~= nil then
if type(convo.name) == "table" then
if convo.cell_call == true or convo.cell_receive == true then
m09_play_cell_convo(convo.name)
else
local result = m09_play_persona_line(convo.name, true)
-- Proceed with the conversation if the line fails.
M09_line_failsafe_thread = thread_new("delay", 2.0)
-- Wait for the line to finish.
delay(0.25)
if (convo.name.play_2d == true) then
-- For 2D lines the result we got back is the play ID of the line.
while (audio_is_playing(result)) do
thread_yield()
end
else
-- For 3D lines, wait for the human we played it on to stop talking.
while audio_persona_line_playing(convo.name.character) and not thread_check_done(M09_line_failsafe_thread) do
thread_yield()
end
end
M09_line_failsafe_thread = INVALID_THREAD_HANDLE
end
else
if convo.cell_call == true or convo.cell_receive == true then
m09_play_cell_convo(convo)
else
--local msg_handle = message("Playing Convo: " .. convo.name, 99999999.0)
if convo.direct == true then
convo.handle = audio_conversation_load_direct(convo.name)
else
convo.handle = audio_conversation_load(convo.name)
end
audio_conversation_play(convo.handle)
audio_conversation_wait_for_end(convo.handle)
convo.handle = nil
--message_remove(msg_handle)
end
end
end
if convo.delay ~= nil and convo.delay > 0.01 then
delay(convo.delay)
end
end
-- Unloads a conversation
--
-- convo: Conversation to unload
function m09_unload_convo(convo)
if convo.handle == nil then
return
end
audio_conversation_end(convo.handle)
convo.handle = nil
end
-- Unloads all conversations from the convo table
--
function m09_unload_all_convos()
for convo_key, convo_set in pairs(M09_convo) do
m09_unload_convo_set(convo_set)
if convo_set.thread ~= INVALID_THREAD_HANDLE then
thread_kill(convo_set.thread)
end
end
end
-- Iterates through a table of conversations and plays them.
--
-- convo_set: Table of conversations
--
function m09_play_convo_set(convo_set)
for key, convo in pairs(convo_set.files) do
m09_play_convo(convo)
end
end
-- Unloads a convo table (array)
--
-- convo_set Table of conversations to unload
--
function m09_unload_convo_set(convo_set)
for key, convo in pairs(convo_set.files) do
m09_unload_convo(convo)
end
end
-- Starts an audio conversation as a thread
--
-- convo_table: Conversation to play
--
function m09_start_convo_thread(convo_table)
--[[
if M09_active_convo ~= "" then
m09_unload_convo_set(M09_active_convo)
M09_active_convo = ""
end
M09_active_convo = convo_table
--]]
convo_table.thread = thread_new("m09_audio_thread", convo_table)
end
-- Loads the necessary 2D personas for the heli rail sequence
--
function m09_load_heli_rail_personas()
for key, persona in pairs(M09_personas) do
persona.handle = audio_persona_load_2d(persona.name)
end
end
-- Unloads all 2d personas
--
function m09_unload_personas()
for key, persona in pairs(M09_personas) do
if persona.handle ~= INVALID_PERSONA_HANDLE then
audio_persona_remove_2d(persona.handle)
persona.handle = INVALID_PERSONA_HANDLE
end
end
end
-- Gets the 2d persona handle from a character name
--
function m09_get_persona_handle(line)
for key, persona in pairs(M09_personas) do
if persona.name == line.character then
return persona.handle
end
end
return nil
end
-- Plays a persona line.
--
-- line: (string) name of the line to play
-- during_conversations: (bool) indicates whether or not this line should play if a conversation is active
--
-- returns: For 2D lines, the play ID of the line is returned, for 3D lines, a boolean
-- indicating whether the line succeeded.
--
function m09_play_persona_line(line, during_conversations)
--message("Playing Persona Line: " .. line.name, 4.0)
-- If there's a conversation playing, then skip this line.
if M09_active_convo ~= "" then
if (during_conversations == nil or during_conversations == false) then
--message("Line aborted:" .. line.name, 2.0)
return nil
end
end
if line.play_2d then
return audio_play_persona_line_2d(m09_get_persona_handle(line), line.name)
else
return audio_play_persona_line(line.character, line.name)
end
end
-- *************** ***************
-- *************** Crate Callbacks ***************
-- *************** ***************
-- Start the QTE to open the crate
--
-- player: (string) player opening the crate
-- trigger: (string) trigger being used
--
function m09_trigger_crate_cb(player, trigger)
local is_local = (player == LOCAL_PLAYER)
for i, crate_set in pairs(M09_crate_sets) do
for key, crate in pairs(crate_set.crates) do
if trigger == crate.trigger then
if is_local then
M09_local_crate = crate
-- Clear the trigger first, so that the player can't trigger it again
-- during a delay in the crate door open function.
m09_clear_crate_trigger(trigger)
m09_crate_door_open(crate, true, LOCAL_PLAYER)
else
M09_remote_crate = crate
-- Clear the trigger first, so that the player can't trigger it again
-- during a delay in the crate door open function.
m09_clear_crate_trigger(trigger)
m09_crate_door_open(crate, true, REMOTE_PLAYER)
end
return
end
end
end
--message("ERROR: NO CRATE FOUND", 4.0)
end
-- local player completed the crate opening QTE
--
-- successful: (boolean) true if QTE was successful
--
function m09_crate_door_open_local_cb(successful)
character_allow_ragdoll(LOCAL_PLAYER, true)
m09_crate_door_open(M09_local_crate, successful, LOCAL_PLAYER)
end
-- remote player completed the crate opening QTE
--
-- successful: (boolean) true if QTE was successful
--
function m09_crate_door_open_remote_cb(successful)
character_allow_ragdoll(REMOTE_PLAYER, true)
m09_crate_door_open(M09_remote_crate, successful, REMOTE_PLAYER)
end
function m09_destroy_heli_cb(human, trigger)
if human == "" or human == nil or character_is_in_vehicle(human) == false then
return
end
local vehicle = get_char_vehicle_name(human)
if vehicle == "" or vehicle == nil then
return
end
if not vehicle_is_destroyed(vehicle) then
vehicle_detonate(vehicle)
end
end
--[[
-- TODO: Remove after proper homie water interaction is added
function m09_player_entered_boat(player, vehicle, seat)
if not character_is_in_vehicle(M09_Zimos) then
vehicle_enter_teleport(M09_Zimos, vehicle, 1, true)
end
on_vehicle_enter("", LOCAL_PLAYER)
delay(1.5)
m09_start_convo_thread(M09_convo.to_boat)
end
--]]
-- *************************
--
-- Thread functions
--
-- *************************
-- Plays Zimos lines comforting the hos.
--
function m09_zimos_comforting_hos()
while true do
delay(rand_float(10.0, 20.0))
if (M09_active_convo ~= "") then
m09_start_convo_thread(M09_convo.zimos_to_hos)
end
end
end
-- Kill any misc threads
--
function m09_kill_all_threads()
thread_kill(M09_group.girls_heli.thread)
thread_kill(M09_zimos_girl_thread)
thread_kill(M09_girls_follow_zimos_thread)
thread_kill(M09_line_failsafe_thread)
thread_kill(M09_get_to_south_platform_thread)
thread_kill(M09_path_end_callback_thread)
thread_kill(M09_delay_thread)
thread_kill(M09_failsafe_thread)
thread_kill(M09_zimos_comforting_hos_thread)
end
function m09_clear_boat_guards()
if sizeof_table(M09_enemies_on_the_boat) ~= 0 then
m09_set_objective(M09_objective.kill_guards)
while sizeof_table(M09_enemies_on_the_boat) ~= 0 do
thread_yield()
end
end
end
-- Slows down any boats chasing the helicopter if they get too close.
--
-- boat_group: Table with boat group info.
--
function m09_throttle_heli_boats(boat_group)
while true do
for i, boat_info in pairs(boat_group.vehicles) do
if get_dist(boat_info.vehicle, LOCAL_PLAYER, false, true) < M09_chase_boat_min_dist_to_player then
vehicle_speed_override(boat_info.vehicle, M09_chase_boat_slow_speed)
else
vehicle_speed_override(boat_info.vehicle, boat_group.speed)
end
end
delay(0.5)
end
end
-- Creates a helicopter to attack the ho boat after the player has captured it.
--
-- attacker: (table) attacker information
--
function m09_spawn_attack_heli_thread(attacker)
group_create(attacker.name, true)
-- make sure the heli exists
while (vehicle_exists(attacker.vehicle) == false) do
thread_yield()
end
-- Put the guys in the heli.
vehicle_suppress_npc_exit(attacker.vehicle, true)
vehicle_enter_teleport(attacker.gunner, attacker.vehicle, 4, true)
vehicle_enter_teleport(attacker.pilot, attacker.vehicle, 0, true)
-- Once everyone is in, set the vehicle as unjackable to prevent RC.
set_unjackable_flag(attacker.vehicle, true)
on_vehicle_destroyed("m09_attack_heli_destroyed_cb", attacker.vehicle)
-- Mark vehicle as a target.
marker_add(attacker.vehicle, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_ALL)
-- Fly the approach path.
helicopter_fly_to_direct_dont_stop(attacker.vehicle, 20, attacker.approach_path)
-- Have the gunners attack the player.
ai_add_enemy_target(attacker.gunner, LOCAL_PLAYER, ATTACK_NOW_NEVER_LOSE)
if In_coop then
ai_add_enemy_target(attacker.gunner, REMOTE_PLAYER, ATTACK_NOW_NEVER_LOSE)
end
-- Start the heli on its looping path.
helicopter_set_path_orientation(attacker.vehicle, HELI_PF_LEFT_SIDE_FACE_TARGET)
helicopter_fly_to_direct_loop(attacker.vehicle, attacker.orbit_speed, attacker.orbit_path)
-- Wait until the chopper is killed.
while (true) do
thread_yield()
end
end
-- Create attack group, put them in the vehicle (boat), send them to kill the player
--
-- attacker: (table) attacker information
-- entry: (table) entry navpoints
--
function m09_spawn_attacker_thread(attacker, entry)
group_create(attacker.name, true)
-- make sure the car exists
while not vehicle_exists(attacker.vehicle) do
thread_yield()
end
-- nobody leaves until I say so
vehicle_suppress_npc_exit(attacker.vehicle, true)
vehicle_enter_group_teleport(attacker.members, attacker.vehicle)
-- Once everyone is in, set the vehicle as unjackable to prevent RC.
set_unjackable_flag(attacker.vehicle, true)
for i, baddie in pairs(attacker.members) do
if character_is_in_a_driver_seat(baddie) then
set_ignore_ai_flag(baddie, false)
npc_hearing_enable(baddie, false)
npc_combat_enable(baddie, false)
else
-- Have the passengers attack the player.
ai_add_enemy_target(baddie, LOCAL_PLAYER, ATTACK_NOW_NEVER_LOSE)
if In_coop then
ai_add_enemy_target(baddie, REMOTE_PLAYER, ATTACK_NOW_NEVER_LOSE)
end
end
end
on_vehicle_destroyed("m09_boat_destroyed_cb", attacker.vehicle)
-- mark vehicle as a target
marker_add(attacker.vehicle, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_ALL)
-- Send them to a navpoint (this may need to change to a path when we get boats)
--vehicle_ignore_repulsors(attacker.vehicle, true)
-- Follow the approach path. The first guy gets to dock without stopping.
if (M09_allow_attacker_docking == true) then
M09_allow_attacker_docking = false
attacker.is_docking = true
end
--attacker.pathfind_thread = thread_new("M09_vehicle_pathfind_thread", attacker.vehicle, get_random_table_entry(paths), attacker)
-- Path to the boat, set a speed limit to avoid guys running over one another.
vehicle_speed_override(attacker.vehicle, 35)
vehicle_pathfind_to(attacker.vehicle, get_random_table_entry(entry.boat_paths), true, false)
-- Wait until we're free to dock.
if (attacker.is_docking == false and M09_allow_attacker_docking == false) then
-- Go into a holding loop until we can dock.
while (M09_allow_attacker_docking == false) do
if (attacker.is_jetski) then
vehicle_speed_override(attacker.vehicle, 30)
vehicle_pathfind_to(attacker.vehicle, entry.jetski_holding_path, true, false)
else
vehicle_speed_override(attacker.vehicle, 40)
vehicle_pathfind_to(attacker.vehicle, entry.boat_holding_path, true, false)
end
thread_yield()
end
end
M09_allow_attacker_docking = false
attacker.is_docking = true
vehicle_speed_cancel(attacker.vehicle)
-- Approach the dock
local destination = nil
if (attacker.drive_boat_back) then
-- Take the approach path to the destination so we don't end up in a position
-- where we have to awkwardly back around.
vehicle_pathfind_to(attacker.vehicle, entry.approach_path, true, true)
destination = entry.boat_stop
else
-- Just drive to the abandon point.
destination = entry.boat_abandon_stop
vehicle_pathfind_to(attacker.vehicle, destination, true, true)
end
-- Get close
while get_dist(attacker.vehicle, destination) > M09_boat_is_close do
if attacker.pathfind_thread == INVALID_THREAD_HANDLE then
m09_cleanup_boat_attacker(attacker)
M09_allow_attacker_docking = true
delay(10.0)
return
end
thread_yield()
end
thread_kill(attacker.pathfind_thread)
vehicle_stop(attacker.vehicle)
-- vehicle is no longer the problem
marker_remove(attacker.vehicle)
on_vehicle_destroyed("", attacker.vehicle)
-- Let's see what the AI can do for now
for i, baddie in pairs(attacker.members) do
if not character_is_dead(baddie) and character_is_in_vehicle(baddie) then
-- don't let the driver exit if we want to take the boat back
if not attacker.drive_boat_back or not character_is_in_a_driver_seat(baddie) then
on_death("m09_attacker_killed_cb", baddie)
-- target players
ai_add_enemy_target(baddie, LOCAL_PLAYER, ATTACK_NOW_NEVER_LOSE)
if In_coop then
ai_add_enemy_target(baddie, REMOTE_PLAYER, ATTACK_NOW_NEVER_LOSE)
end
-- out of the vehicle
vehicle_exit_teleport(baddie)
while character_is_in_vehicle(baddie) do
thread_yield()
end
-- on to the stairs
teleport(baddie, entry.stairs_nav)
-- Enable AI again
set_ignore_ai_flag(baddie, false)
npc_hearing_enable(baddie, true)
npc_combat_enable(baddie, true)
marker_add(baddie, MINIMAP_ICON_KILL, OI_ASSET_KILL, OI_FLAGS_DEFAULT, SYNC_ALL)
M09_enemies_on_the_boat[baddie] = true
-- go upstairs
ai_do_scripted_move(baddie, entry.upstairs, true, false)
on_ai_do_action_complete("m09_advance_on_player", baddie)
-- wait
delay(0.5)
end
else
if not character_is_dead(baddie) then
character_kill(baddie)
end
end
end
local driver = vehicle_get_driver(attacker.vehicle)
-- if we didn't tell the driver to get out of the boat, drive it back
if attacker.drive_boat_back and driver ~= nil and not character_is_dead(driver) and character_is_in_vehicle(driver) then
attacker.pathfind_thread = thread_new("M09_vehicle_pathfind_thread", attacker.vehicle, get_random_table_entry(entry.drive_back), attacker)
end
-- Allow the next dude to dock now.
M09_allow_attacker_docking = true
attacker.is_docking = false
-- keep this thread going until all of the guys have been released to the world and or killed
for i, baddie in pairs(attacker.members) do
if not character_is_in_a_driver_seat(baddie) then
while character_exists(baddie) and not character_is_dead(baddie) do
thread_yield()
end
end
end
-- nuke it so we can reuse it
m09_cleanup_boat_attacker(attacker)
end
-- Creates and controls a group to attack the boat with a transport helicopter.
--
-- attacker: (table) attacker information.
--
function m09_spawn_transport_attack_heli_thread(attacker)
group_create_hidden(attacker.heli_group.name, true)
group_create_hidden(attacker.soldier_group.name, true)
-- make sure the heli exists
while not vehicle_exists(attacker.heli_group.vehicle) do
thread_yield()
end
attacker.heli_group.debug_done = false
-- Get everyone in the heli.
vehicle_enter_teleport(attacker.heli_group.pilot, attacker.heli_group.vehicle, 0)
--turn_invulnerable(attacker.heli_group.pilot)
--vehicle_enter_group_teleport(attacker.soldiers, attacker.vehicle)
local seat_idx = 1
for i, soldier in pairs(attacker.soldier_group.members) do
vehicle_enter_teleport(soldier, attacker.heli_group.vehicle, seat_idx)
seat_idx = seat_idx + 1
end
-- Once everyone is in, set the vehicle as unjackable to prevent RC.
set_unjackable_flag(attacker.heli_group.vehicle, true)
group_show(attacker.heli_group.name)
group_show(attacker.soldier_group.name)
-- Add a merker to the heli.
marker_add(attacker.heli_group.vehicle, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_ALL)
-- Clean up the heli if it's destroyed.
on_vehicle_destroyed("m09_transport_heli_destroyed_cb", attacker.heli_group.vehicle)
-- Follow the approach path.
helicopter_fly_to_direct_dont_stop(attacker.heli_group.vehicle, -1, attacker.heli_group.approach_path)
-- Slow down and follow the landing path.
-- directly call to helicopter_fly_to_do because we don't want to wait for completion
helicopter_fly_to_do(attacker.heli_group.vehicle, 5, true, "", false, attacker.heli_group.land_path)
-- Wait until either the chopper comes to a stop or hits the deck.
while (get_char_vehicle_is_in_air(attacker.heli_group.pilot) == true and get_vehicle_speed(attacker.heli_group.vehicle) > 1.0) do
thread_yield()
end
-- If the helicopter didn't make it to the boat, clean them up.
if object_is_in_trigger(M09_trigger.on_boat_trigger.name, attacker.heli_group.vehicle) == false then
m09_cleanup_transport_heli_attacker(attacker)
return
end
-- Stop the pathfind.
helicopter_fly_to_stop(attacker.heli_group.vehicle)
-- Everybody out!
vehicle_exit_group(attacker.soldier_group.members)
-- Add markers to all the guys and tell them to attack the player(s).
for i, baddie in pairs(attacker.soldier_group.members) do
if character_exists(baddie) and not character_is_dead(baddie) then
marker_add(baddie, MINIMAP_ICON_KILL, OI_ASSET_KILL, OI_FLAGS_DEFAULT, SYNC_ALL)
ai_add_enemy_target(baddie, LOCAL_PLAYER, ATTACK_NOW_NEVER_LOSE)
if In_coop then
ai_add_enemy_target(baddie, REMOTE_PLAYER, ATTACK_NOW_NEVER_LOSE)
end
end
end
-- Remove the marker from the transport heli and remove it's callback, it's no longer a target.
marker_remove(attacker.heli_group.vehicle)
on_vehicle_destroyed("", attacker.heli_group.vehicle)
-- Wait for everyone to get out
for i, soldier in pairs(attacker.soldier_group.members) do
while (character_is_in_vehicle(soldier, attacker.heli_group.vehicle)) do
thread_yield()
end
end
delay(2.0)
m09_play_heli_drop_off_convo()
-- Fly the exit path.
helicopter_fly_to_direct_dont_stop(attacker.heli_group.vehicle, -1, attacker.heli_group.exit_path)
-- Run away!
helicopter_enter_retreat(attacker.heli_group.vehicle)
-- Release the guy so he can be destroyed when out of range.
release_to_world(attacker.heli_group.name)
-- Wait until all the attackers are dead.
for i, baddie in pairs(attacker.soldier_group.members) do
while character_exists(baddie) and not character_is_dead(baddie) do
thread_yield()
end
end
attacker.heli_group.debug_done = true
end
-- When a scripted action is completed, tell the AI to advance on the player
--
-- npc: (string) name of the NPC that completed their action.
--
function m09_advance_on_player(npc)
on_ai_do_action_complete("", (npc))
local target = LOCAL_PLAYER
if (In_coop and rand_int(1, 2) == 2) then
target = REMOTE_PLAYER
end
local closest_nav = nil
local closest_dist = 99999
for i, pos in pairs(M09_nav.boat_advance_positions) do
local dist = get_dist(target, pos)
if (dist < closest_dist) then
closest_dist = dist
closest_nav = pos
end
end
ai_attack_region(npc, closest_nav, 20.0)
end
-- pathfind to a destination
--
-- vehicle: (string) name of vehicle
-- navpoint: (string) name of navpoint to pathfind to
--
function M09_vehicle_pathfind_thread(vehicle, navpoint, handle_table)
local stop_at_goal = true
local nav_table = nil
-- If we passed in a single path, make a table out of it.
if type(navpoint) == "string" then
nav_table = {navpoint}
else
nav_table = navpoint
end
-- Pathfind along each path in the table.
for i, nav in pairs(nav_table) do
if i < sizeof_table(nav_table) then
stop_at_goal = false
else
stop_at_goal = true
end
local path_done = 0
if vehicle_pathfind_navmesh_do(vehicle,nav, false, stop_at_goal, true, 0) == false then
path_done = 1
end
while ( path_done == 0) do
thread_yield()
path_done = vehicle_is_destroyed(vehicle) or vehicle_pathfind_check_done(vehicle)
end
if vehicle_is_destroyed(vehicle) then
break
end
end
if handle_table ~= nil then
handle_table.pathfind_thread = INVALID_THREAD_HANDLE
end
end
-- fly a path
--
-- vehicle: (string) name of vehicle
-- speed: (float) speed to fly
-- path: (path or navpoint) path to fly
--
function m09_fly_path_thread( vehicle, speed, path )
helicopter_fly_to_direct(vehicle, speed, path)
end
-- fly through a set of path segments
--
-- vehicle: (string) name of the vehicle
-- path_set: (table) table with a speed and path member
--
function m09_fly_path_set_thread( vehicle, path_set )
local segments_left = sizeof_table(path_set)
for key, segment in pairs(path_set) do
--message("Path: " .. segment.path .. " Speed: " .. segment.speed, 2.0)
if segments_left > 1 then
helicopter_fly_to_direct_dont_stop(vehicle, segment.speed, segment.path)
segments_left = segments_left - 1
else
helicopter_fly_to_direct(vehicle, segment.speed, segment.path)
end
end
end
-- Have Zimos collect any girls and hang back out of the player's way
--
function m09_zimos_girl_behavior_thread()
-- Don't allow Zimos to die.
turn_invulnerable(M09_Zimos)
while true do
if M09_girls_flee_nav ~= "" then
local dist = get_dist(M09_Zimos, M09_girls_flee_nav)
if dist > 10.0 then
npc_leash_remove(M09_Zimos)
ai_do_scripted_move(M09_Zimos, M09_girls_flee_nav, true, false)
elseif dist < 5.0 then
npc_leash_to_nav(M09_Zimos, M09_girls_flee_nav, 3.0)
end
end
delay(0.5)
end
M09_zimos_girl_thread = INVALID_THREAD_HANDLE
end
-- Play a audio conversation
--
-- convo_table: Table of the audio conversation files to play
--
function m09_audio_thread(convo_table)
if (M09_active_convo ~= "") then
-- Wait for the current conversation to end.
while (M09_active_convo ~= "") do
thread_yield()
end
M09_active_convo = convo_table
-- Delay a moment before starting the next conversation.
delay(2.0)
end
M09_active_convo = convo_table
m09_play_convo_set(convo_table)
convo_table.thread = INVALID_THREAD_HANDLE
M09_active_convo = ""
end