--[[
m22.lua
SR3 Mission Script
DATE: 08-09-10
AUTHOR: John Karczewski
]]--
-- Debug flags --
-- Tweakable Parameters --
-- Battle Zones --
NUM_ZONES_TO_COMPLETE_TO_SUCCEED = 2
NOTORIETY_FAILSAFE_TIME = 1 * 60 -- Time before notoriety spawns are automatically re-enabled during battle zones.
NUM_ZONE_ENEMIES_TO_RELEASE = 20 -- Number of initial spawn enemies that will be released immediately when they are killed.
-- Stop Killbane --
NUM_HITS_TO_STOP_PLANE = 4
-- Save the Saints --
STATUE_EXPLOSION_TIME = 300 -- seconds
-- Boss Battle --
PLAYER_STARTING_FART_IN_JAR_AMMO = 0
FART_IN_JAR_RESPAWN_TIME = 15 -- seconds
-- Kia --
KIA_VTOL_RESPAWN_TIME = 5
VTOL_HOVER_TIME = 5
KIA_COOP_REINFORCEMENTS_TIME = 10
KIA_WEAPON_SPREAD_MULTIPLIER = 0.25
KIA_DESIRED_PLAYER_KEEP_DISTANCE = 10.0 -- distance from the player Kia will try to maintain
KIA_ATTACK_POSITION_LEASH_RADIUS = 5.0 -- leash radius while Kia is at an attack navpoint position
KIA_DEFENSIVE_POSITION_LEASH_RADIUS = 1.0 -- defensive leash radius (while in cover)
KIA_NUM_TIMES_TO_VOMIT = 2 -- number of times Kia should vomit when hit with a FIAJ
KIA_DAMAGE_MULTIPLIER_HUMAN_SHIELD = 0.5 -- damage multiplier for Kia when she has Shaundi as a human shield
KIA_DAMAGE_MULTIPLIER_VOMITING = 1.75 -- damage multiplier for Kia when she is vomiting from a FIAJ
KIA_ATTACK_VTOL_IDLE_TIME = 10.0
KIA_ATTACK_VTOL_PRE_ATTACK_TIME = 3.0
KIA_ATTACK_VTOL_POST_ATTACK_TIME = 2.0
KIA_ATTACK_VTOL_RESAPWN_TIME = 20.0
KIA_TEMPORARY_WEAPON = "Special-SonicGun"
KIA_TEMPORARY_GRENADE = "flashbang"
KIA_FIAJ_REACTION_SYNCED_ANIM = "M22_Human_Shield_FIAJ"
-- Groups --
M22_groups = {
---------------------------
----- ZONE ONE GROUPS -----
---------------------------
--[[
Zone_One_Initial = {
name = "Group_battle_zone 001",
members = { "NPC_sind_one 001", "NPC_sind_one 002", "NPC_sind_one 003", "NPC_sind_one 004", "NPC_sind_one 005",
"NPC_sind_one 006", "NPC_sind_one 007", "NPC_sind_one 008", "NPC_sind_one 009", "NPC_sind_one 010",
"NPC_sind_one 011", "NPC_sind_one 012", "NPC_sind_one 013", "NPC_sind_one 014", "NPC_sind_one 015",
"NPC_sind_one 016", "NPC_sind_one 017", "NPC_sind_one 018", "NPC_sind_one 019", "NPC_sind_one 020",
"NPC_sind_one 021", "NPC_sind_one 022", "NPC_sind_one 023", "NPC_sind_one 024",
"NPC_stag_one 001", "NPC_stag_one 002", "NPC_stag_one 003", "NPC_stag_one 004", "NPC_stag_one 005",
"NPC_stag_one 006", "NPC_stag_one 007", "NPC_stag_one 008", "NPC_stag_one 009", "NPC_stag_one 010",
"NPC_stag_one 011", "NPC_stag_one 012", "NPC_stag_one 013", "NPC_stag_one 014", "NPC_stag_one 015",
"NPC_stag_one 016", "NPC_stag_one 017", "NPC_stag_one 018", "NPC_stag_one 019", "NPC_stag_one 020",
"NPC_stag_one 021", "NPC_stag_one 022", "NPC_stag_one 023", "NPC_stag_one 024" },
vehicles = { "veh_Zone1_synd 001", "veh_Zone1_synd 002", "veh_Zone1_synd 003",
"veh_Zone1_synd 004", "veh_Zone1_synd 005", "veh_Zone1_synd 006", "veh_Zone1_stag 001", "veh_Zone1_stag 002",
"veh_Zone1_stag 003", "veh_Zone1_stag 004", "veh_Zone1_stag 005", "veh_Zone1_stag 006", "veh_Zone1_stag 007" },
},
Zone_One_Courtesy = {
name = "Group_battle_zone_courtesy 001",
vehicles = { "Vehicle_Zone1_Courtesy 001", "Vehicle_Zone1_Courtesy 002" },
},
--]]
---------------------------
----- ZONE TWO GROUPS -----
---------------------------
Zone_Two_Initial = {
name = "Group_battle_zone 002",
members = { "NPC_sind_two 001", "NPC_sind_two 002", "NPC_sind_two 003", "NPC_sind_two 004", "NPC_sind_two 005",
"NPC_sind_two 006", "NPC_sind_two 007", "NPC_sind_two 008", "NPC_sind_two 009", "NPC_sind_two 010",
"NPC_sind_two 011", "NPC_sind_two 012", "NPC_sind_two 013", "NPC_sind_two 014", "NPC_sind_two 015",
"NPC_sind_two 016", "NPC_sind_two 017", "NPC_sind_two 018", "NPC_sind_two 019", "NPC_sind_two 020",
"NPC_sind_two 021", "NPC_sind_two 022", "NPC_sind_two 023", "NPC_sind_two 024",
"NPC_stag_two 001", "NPC_stag_two 002", "NPC_stag_two 003", "NPC_stag_two 004", "NPC_stag_two 005",
"NPC_stag_two 006", "NPC_stag_two 007", "NPC_stag_two 008", "NPC_stag_two 009", "NPC_stag_two 010",
"NPC_stag_two 011", "NPC_stag_two 012", "NPC_stag_two 013", "NPC_stag_two 014", "NPC_stag_two 015",
"NPC_stag_two 016", "NPC_stag_two 017", "NPC_stag_two 022", "NPC_stag_two 023", "NPC_stag_two 024",
"NPC_stag_two 025", "NPC_stag_two 026", "NPC_stag_two 027", "NPC_stag_two 028" },
},
Zone_Two_Vehicles = {
name = "Group_battle_zone_vehicles 2",
spawned = false,
},
Zone_Two_Courtesy = {
name = "Group_battle_zone_courtesy 002",
vehicles = { "Vehicle_Zone2_Courtesy 001", "Vehicle_Zone2_Courtesy 002" },
},
Zone_Two_Saints = {
name = "Group_BZ2_Saints 001",
cars = {
{
vehicle = "veh_bz2_saint 001",
members = { "npc_bz2_saint 001", "npc_bz2_saint 002", "npc_bz2_saint 003" },
},
{
vehicle = "veh_bz2_saint 002",
members = { "npc_bz2_saint 004", "npc_bz2_saint 005", "npc_bz2_saint 006" },
},
},
start_positions = {
{
nav = "nav_BZ2_saints_start 001",
path = "path_bz2_saints 1",
},
{
nav = "nav_BZ2_saints_start 002",
path = "path_bz2_saints 2",
},
{
nav = "nav_BZ2_saints_start 003",
path = "path_bz2_saints 3",
},
},
},
---------------------------
----- ZONE Three GROUPS ---
---------------------------
Zone_Three_Initial = {
name = "Group_battle_zone 003",
members = { "NPC_sind_three 001", "NPC_sind_three 002", "NPC_sind_three 003", "NPC_sind_three 004", "NPC_sind_three 005",
"NPC_sind_three 006", "NPC_sind_three 007", "NPC_sind_three 008", "NPC_sind_three 009", "NPC_sind_three 010",
"NPC_sind_three 011", "NPC_sind_three 012", "NPC_sind_three 013", "NPC_sind_three 014", "NPC_sind_three 015",
"NPC_sind_three 016", "NPC_sind_three 017", "NPC_sind_three 018", "NPC_sind_three 019", "NPC_sind_three 020",
"NPC_sind_three 021", "NPC_sind_three 022", "NPC_sind_three 023", "NPC_sind_three 024",
"NPC_stag_three 001", "NPC_stag_three 002", "NPC_stag_three 003", "NPC_stag_three 004", "NPC_stag_three 005",
"NPC_stag_three 006", "NPC_stag_three 007", "NPC_stag_three 008", "NPC_stag_three 009", "NPC_stag_three 010",
"NPC_stag_three 011", "NPC_stag_three 012", "NPC_stag_three 013", "NPC_stag_three 014", "NPC_stag_three 015",
"NPC_stag_three 016", "NPC_stag_three 017", "NPC_stag_three 018", "NPC_stag_three 019", "NPC_stag_three 020",
"NPC_stag_three 021", "NPC_stag_three 022", "NPC_stag_three 023", "NPC_stag_three 024" },
},
Zone_Three_Vehicles = {
name = "Group_battle_zone_vehicles 3",
spawned = false,
},
Zone_Three_Courtesy = {
name = "Group_battle_zone_courtesy 003",
vehicles = { "Vehicle_Zone3_Courtesy 001", "Vehicle_Zone3_Courtesy 002" },
},
Zone_Three_Saints = {
name = "Group_BZ3_Saints 001",
cars = {
{
vehicle = "veh_bz3_saint 001",
members = { "npc_bz3_saint 001", "npc_bz3_saint 002", "npc_bz3_saint 003" },
},
{
vehicle = "veh_bz3_saint 002",
members = { "npc_bz3_saint 004", "npc_bz3_saint 005", "npc_bz3_saint 006" },
},
},
start_positions = {
{
nav = "nav_BZ3_saints_start 001",
path = "path_bz3_saints 1",
},
{
nav = "nav_BZ3_saints_start 002",
path = "path_bz3_saints 2",
},
{
nav = "nav_BZ3_saints_start 003",
path = "path_bz3_saints 3",
},
},
},
---------------------------
----- ZONE FOUR GROUPS ----
---------------------------
Zone_Four_Initial = {
name = "Group_battle_zone 004",
members = { "NPC_sind_four 001", "NPC_sind_four 002", "NPC_sind_four 003", "NPC_sind_four 004", "NPC_sind_four 005",
"NPC_sind_four 006", "NPC_sind_four 007", "NPC_sind_four 008", "NPC_sind_four 009", "NPC_sind_four 010",
"NPC_sind_four 011", "NPC_sind_four 015", "NPC_sind_four 016", "NPC_sind_four 017", "NPC_sind_four 018",
"NPC_sind_four 019", "NPC_sind_four 020", "NPC_sind_four 021", "NPC_sind_four 022", "NPC_sind_four 024",
"NPC_sind_four 025", "NPC_sind_four 026", "NPC_sind_four 029", "NPC_sind_four 030",
"NPC_stag_four 001", "NPC_stag_four 002", "NPC_stag_four 003", "NPC_stag_four 004", "NPC_stag_four 005",
"NPC_stag_four 006", "NPC_stag_four 007", "NPC_stag_four 008", "NPC_stag_four 009", "NPC_stag_four 010",
"NPC_stag_four 011", "NPC_stag_four 012", "NPC_stag_four 013", "NPC_stag_four 014", "NPC_stag_four 015",
"NPC_stag_four 016", "NPC_stag_four 017", "NPC_stag_four 018", "NPC_stag_four 019", "NPC_stag_four 020",
"NPC_stag_four 021", "NPC_stag_four 022", "NPC_stag_four 023", "NPC_stag_four 024" },
},
Zone_Four_Vehicles = {
name = "Group_battle_zone_vehicles 4",
spawned = false,
},
Zone_Four_Courtesy = {
name = "Group_battle_zone_courtesy 004",
vehicles = { "Vehicle_Zone4_Courtesy 001", "Vehicle_Zone4_Courtesy 002" },
},
Zone_Four_Saints = {
name = "Group_BZ4_Saints 001",
cars = {
{
vehicle = "veh_bz4_saint 001",
members = { "npc_bz4_saint 001", "npc_bz4_saint 002", "npc_bz4_saint 003" },
},
{
vehicle = "veh_bz4_saint 002",
members = { "npc_bz4_saint 004", "npc_bz4_saint 005", "npc_bz4_saint 006" },
}
},
start_positions = {
{
nav = "nav_BZ4_saints_start 001",
path = "path_bz4_saints 1",
},
{
nav = "nav_BZ4_saints_start 002",
path = "path_bz4_saints 2",
},
{
nav = "nav_BZ4_saints_start 003",
path = "path_bz4_saints 3",
},
},
},
---------------------------
----- ARMORY GROUPS -----
---------------------------
Armory_Initial = {
name = "Group_armory",
members = { "NPC_synd_armory 001", "NPC_synd_armory 002", "NPC_synd_armory 003", "NPC_synd_armory 005", "NPC_synd_armory 006",
"NPC_synd_armory 007", "NPC_synd_armory 008", "NPC_synd_armory 009", "NPC_synd_armory 010", "NPC_synd_armory 011",
"NPC_synd_armory 012", "NPC_synd_armory 013", "NPC_synd_armory 014", "NPC_synd_armory 015", "NPC_synd_armory 016",
"NPC_synd_armory 017", "NPC_synd_armory 018", "NPC_synd_armory 019", "NPC_synd_armory 020", "NPC_synd_armory 021",
"NPC_synd_armory 022", "NPC_synd_armory 023", "NPC_synd_armory 024", "NPC_synd_armory 025",
"NPC_stag_armory 001", "NPC_stag_armory 003", "NPC_stag_armory 004", "NPC_stag_armory 005", "NPC_stag_armory 006",
"NPC_stag_armory 007", "NPC_stag_armory 009", "NPC_stag_armory 010", "NPC_stag_armory 011", "NPC_stag_armory 012",
"NPC_stag_armory 013", "NPC_stag_armory 014", "NPC_stag_armory 015", "NPC_stag_armory 016", "NPC_stag_armory 017",
"NPC_stag_armory 018", "NPC_stag_armory 019", "NPC_stag_armory 020", "NPC_stag_armory 021", "NPC_stag_armory 022",
"NPC_stag_armory 023", "NPC_stag_armory 024", "NPC_stag_armory 025", "NPC_stag_armory 026" },
},
Armory_Vehicles = {
name = "Group_armory_vehicles",
spawned = false,
},
Armory_Courtesy = {
name = "Group_Courtesy_Armory",
vehicles = { "Vehicle_Armory_Courtesy 001", "Vehicle_Armory_Courtesy 002" },
},
Statue_Boats = {
name = "Group_heli",
members = { "veh_StatueHeli", "veh_StatueHeli<001>" },
},
---------------------------
----- MISC GROUPS -----
---------------------------
Start_Vehicle = {
name = "Group_Start_Vehicle",
vehicles = { "Vehicle_Courtesy 001", "Vehicle_Courtesy 002" },
},
Oleg_and_Pierce = {
name = "Group_Oleg_and_Pierce",
members = { "Oleg_gameplay", "Pierce_gameplay"},
oleg = "Oleg_gameplay",
pierce = "Pierce_gameplay"
},
Angel = {
name = "Group_Angel",
members = { "Angel_gameplay" },
vehicle = "Angel_Car",
npc = "Angel_gameplay"
},
Angels_Attackers = {
name = "Group_Angels_Attackers",
members = { "Angel_attacker_NPC 001", "Angel_attacker_NPC 002", "Angel_attacker_NPC 003",
"Angel_attacker_NPC 004", "Angel_attacker_NPC 005", "Angel_attacker_NPC 006",
"Angel_attacker_NPC 007", "Angel_attacker_NPC 008" },
vehicles = { "Angel_attacker_Car 001", "Angel_attacker_Car 002" }
},
Airport = {
name = "Group airport initial",
members = { "Killbane_gameplay" },
killbane = "Killbane_gameplay" -- The cutscene creates a dude named "Killbane" that conflicts...
},
Airport_Roadblock_one = {
name = "Group airport roadblock 001",
members = { "Roadblock_1_NPC 001", "Roadblock_1_NPC 002", "Roadblock_1_NPC 003", "Roadblock_1_NPC 004",
"Roadblock_1_NPC 005", "Roadblock_1_NPC 006", "Roadblock_1_NPC 007", "Roadblock_1_NPC 008" },
cars = { "Roadblock_1_Vehicle 001", "Roadblock_1_Vehicle 002", "Roadblock_1_Vehicle 003", "Roadblock_1_Vehicle 004",
"Roadblock_1_Vehicle 005", "Roadblock_1_Vehicle 006", "Roadblock_1_Vehicle 007", "Roadblock_1_Vehicle 008" }
},
Airport_Roadblock_two = {
name = "Group airport roadblock 002",
members = { "Roadblock_2_NPC 001", "Roadblock_2_NPC 002", "Roadblock_2_NPC 003", "Roadblock_2_NPC 004" },
cars = { "Roadblock_2_Vehicle 001", "Roadblock_2_Vehicle 002", "Roadblock_2_Vehicle 003", "Roadblock_2_Vehicle 004" }
},
Airport_Roadblock_three = {
name = "Group airport roadblock 003",
members = { "Roadblock_3_NPC 001", "Roadblock_3_NPC 002", "Roadblock_3_NPC 003", "Roadblock_3_NPC 004" },
cars = { "Roadblock_3_Vehicle 001", "Roadblock_3_Vehicle 002", "Roadblock_3_Vehicle 003", "Roadblock_3_Vehicle 004" }
},
Airport_Roadblock_four = {
name = "Group airport roadblock 004",
members = { "Roadblock_4_NPC 001", "Roadblock_4_NPC 002", "Roadblock_4_NPC 003", "Roadblock_4_NPC 004" },
cars = { "Roadblock_4_Vehicle 001", "Roadblock_4_Vehicle 002", "Roadblock_4_Vehicle 003", "Roadblock_4_Vehicle 004" }
},
Killbane_QTE = {
name = "Group_killbane_qte",
members = "Killbane_qte",
killbane = "Killbane_qte"
},
Killbane_QTE_Nomask = {
name = "Group_killbane_qte_nomask",
members = "Killbane_qte_nomask",
killbane = "Killbane_qte_nomask"
},
Kia = {
name = "Group_kia",
members = "Kia_gameplay",
kia = "Kia_gameplay",
},
Kia_Thugs = {
name = "Group_kia_thugs",
members = { "Kia_Thug 001", "Kia_Thug 002", "Kia_Thug 003", "Kia_Thug 004", "Kia_Thug 005", "Kia_Thug 006",
"Kia_Thug 007", "Kia_Thug 008", "Kia_Thug 009", "Kia_Thug 010", "Kia_Thug 011", "Kia_Thug 012" },
},
Kia_Vtol1 = {
name = "Group_kia_vtol 001",
vtols = {
{
vtol = "veh_kia_vtol 001",
members = { "char_kia_vtol_pilot 001" },
path_intro = "path_kia_vtol_intro 001",
path_looping = "path_kia_vtol_loop 001",
loop_speed = 130,
thread_id = INVALID_THREAD_HANDLE,
},
{
vtol = "veh_kia_vtol 002",
members = { "char_kia_vtol_pilot 002" },
path_intro = "path_kia_vtol_intro 002",
path_looping = "path_kia_vtol_loop 002",
loop_speed = 122,
thread_id = INVALID_THREAD_HANDLE,
},
{
vtol = "veh_kia_vtol 003",
members = { "char_kia_vtol_pilot 003" },
path_intro = "path_kia_vtol_intro 003",
path_looping = "path_kia_vtol_loop 003",
loop_speed = 135,
thread_id = INVALID_THREAD_HANDLE,
},
},
path_break_off = "path_kia_vtol_break_off 001",
path_east_west = "path_kia_vtol_east_west 001",
path_west_east = "path_kia_vtol_west_east 001",
},
vtol_reinforcement = {
name = "Group_vtol_reinforcement",
members = { "Kia_Thug 001", "Kia_Thug 002", "Kia_Thug 003", "Kia_Thug 004", "Kia_Thug 005", "Kia_Thug 006",
"Vtol_driver 002" },
vtol = "veh_reinforcement_vtol 001",
pilots = { "Vtol_driver 002" },
drop_offs = {
soldiers = { "Kia_Thug 001", "Kia_Thug 002", "Kia_Thug 003",
"Kia_Thug 004", "Kia_Thug 005", "Kia_Thug 006" },
path = "Vtol_landing_path 001",
},
thread_id = -1,
},
vtol_coop_reinforcement = {
name = "Group_vtol_coop_rein",
members = { "Kia_Thug_Coop 001", "Kia_Thug_Coop 002", "Kia_Thug_Coop 003", "Kia_Thug_Coop 004",
"Vtol_driver 003" },
vtol = "veh_reinforcement_vtol 002",
pilots = { "Vtol_driver 003" },
drop_offs = {
soldiers = { "Kia_Thug_Coop 001", "Kia_Thug_Coop 002", "Kia_Thug_Coop 003", "Kia_Thug_Coop 004" },
path = "Vtol_landing_path 002",
},
thread_id = -1,
},
Statue_Base = {
name = "Group_statue_base",
members = { "Synd_Statue_NPC 001", "Synd_Statue_NPC 002", "Synd_Statue_NPC 003", "Synd_Statue_NPC 004", "Synd_Statue_NPC 005",
"Synd_Statue_NPC 006", "Synd_Statue_NPC 007", "Synd_Statue_NPC 008", "Synd_Statue_NPC 009", "Synd_Statue_NPC 010",
"Synd_Statue_NPC 011", "Synd_Statue_NPC 012", "Synd_Statue_NPC 013", "Synd_Statue_NPC 014", "Synd_Statue_NPC 015",
"Synd_Statue_NPC 016", "Stag_Statue_NPC 001", "Stag_Statue_NPC 002", "Stag_Statue_NPC 003", "Stag_Statue_NPC 004",
"Stag_Statue_NPC 005", "Stag_Statue_NPC 006", "Stag_Statue_NPC 007", "Stag_Statue_NPC 008", "Stag_Statue_NPC 009",
"Stag_Statue_NPC 010", "Stag_Statue_NPC 011", "Stag_Statue_NPC 012", "Stag_Statue_NPC 013", "Stag_Statue_NPC 014",
"Stag_Statue_NPC 015", "Stag_Statue_NPC 016" }
},
Statue = {
name = "Group_statue",
members = { "Trapped_Saint 001", "Trapped_Saint 002", "Trapped_Saint 003", "Trapped_Saint 004" },
saints = { "Trapped_Saint 001", "Trapped_Saint 002", "Trapped_Saint 003", "Trapped_Saint 004" },
},
Statue_CTE = {
name = "Group_CTE_Statue_Stags",
},
Viola = {
name = "Group_Viola",
members = { "Viola_gameplay" },
viola = "Viola_gameplay"
},
Kinzie = {
name = "Group_Kinzie",
members = { "Kinzie" },
kinzie = "Kinzie",
},
Hostages = {
name = "Group_Hostages",
members = { "Mayor_Hostage", "Shaundi_Hostage" },
shaundi = "Shaundi_Hostage",
mayor = "Mayor_Hostage",
},
Kia_battle_props = {
name = "Group_kia_boss_battle_props",
fart_jars = { "Itm_fart_jar 001", "Itm_fart_jar 002", "Itm_fart_jar 003", "Itm_fart_jar 004" },
},
BattleZone_Finale1 = {
name = "Group_BZfinale1",
members = { "npc_BZFinale1 Brute1", },
},
BattleZone_Finale1v2 = {
name = "Group_BZfinale1v2",
members = { "npc_BZFinale1 Brute2", },
},
BattleZone_Finale2 = {
name = "Group_BZfinale2",
members = { "npc_BZFinale2 Stag 001", "npc_BZFinale2 Stag 002" },
vehicle = "veh_BZFinale2 Tank",
},
BattleZone_Finale3v1 = {
name = "Group_BZfinale3v1",
members = { "npc_BZFinale3 Brute" },
},
BattleZone_Finale3v2 = {
name = "Group_BZfinale3v2",
members = { "npc_BZFinale3 Stag 001", "npc_BZFinale3 Stag 002" },
vehicles = { "veh_BZFinale3 Tank" },
},
Armory_Finale1 = {
name = "Group_ARMFinale1",
members = { "npc_ARMFinale Brute1" },
},
Armory_Finale2 = {
name = "Group_ARMFinale2",
members = { "npc_ARMFinale Brute2" },
},
Armory_Finale3 = {
name = "Group_ARMFinale3",
members = { "npc_ARMFinale Stag 001", "npc_ARMFinale Stag 002" },
vehicles = { "veh_ARMFinale Tank" },
},
Statue_Spawn1 = {
name = "Group_Statue_Spawn1",
members = { "Statue_Stag 001", "Statue_Stag 002" },
},
Statue_Spawn2 = {
name = "Group_Statue_Spawn2",
members = { "Statue_Stag 003", "Statue_Stag 004" },
},
Statue_Spawn3 = {
name = "Group_Statue_Spawn3",
members = { "Statue_Stag 005", "Statue_Stag 006" },
},
Statue_Spawn4 = {
name = "Group_Statue_Spawn4",
members = { "Statue_Stag 007", "Statue_Stag 008" },
},
Statue_Spawn5 = {
name = "Group_Statue_Spawn5",
members = { "Statue_Stag 009", "Statue_Stag 010" },
},
}
Battle_Zone_Groups = {
-- MLG: Removing Battlezone area 1 since we wanted to reduce the number of battlezones
--[[
{
initial_spawn = M22_groups.Zone_One_Initial,
courtesy_vehicles = M22_groups.Zone_One_Courtesy,
boss_spawn_regions = { "sr_BZ1_region 001", "sr_BZ1_region 002", "sr_BZ1_region 003",
"sr_BZ1_region 004", "sr_BZ1_region 005", "sr_BZ1_region 006" },
center_pos = "Battle_Zone_Navpoint 001",
player_starts = { "nav_player_start_bz01_ 001", "nav_player_start_bz01_ 002" },
trigger = "BZ1_Spawn_Trigger",
battle_area = "BZ1_Battle_Area",
required_kills = 26,
cleared = false,
index = 1,
},
--]]
{
initial_spawn = M22_groups.Zone_Two_Initial,
initial_vehicles = M22_groups.Zone_Two_Vehicles,
courtesy_vehicles = M22_groups.Zone_Two_Courtesy,
saints_group = M22_groups.Zone_Two_Saints,
boss_spawn_regions = { "sr_BZ2_region 001", "sr_BZ2_region 002", "sr_BZ2_region 003",
"sr_BZ2_region 004", "sr_BZ2_region 005", "sr_BZ2_region 006" },
center_pos = "Battle_Zone_Navpoint 002",
player_starts = { "nav_player_start_bz02_ 001", "nav_player_start_bz02_ 002" },
trigger = "BZ2_Spawn_Trigger",
battle_area = "BZ2_Battle_Area",
required_kills = 26,
cleared = false,
index = 1,
},
{
initial_spawn = M22_groups.Zone_Three_Initial,
initial_vehicles = M22_groups.Zone_Three_Vehicles,
courtesy_vehicles = M22_groups.Zone_Three_Courtesy,
saints_group = M22_groups.Zone_Three_Saints,
boss_spawn_regions = { "sr_BZ3_region 001", "sr_BZ3_region 002", "sr_BZ3_region 003",
"sr_BZ3_region 004", "sr_BZ3_region 005", "sr_BZ3_region 006" },
center_pos = "Battle_Zone_Navpoint 003",
player_starts = { "nav_player_start_bz03_ 001", "nav_player_start_bz03_ 002" },
trigger = "BZ3_Spawn_Trigger",
battle_area = "BZ3_Battle_Area",
required_kills = 26,
cleared = false,
index = 2,
},
{
initial_spawn = M22_groups.Zone_Four_Initial,
initial_vehicles = M22_groups.Zone_Four_Vehicles,
courtesy_vehicles = M22_groups.Zone_Four_Courtesy,
boss_spawn_regions = { "sr_BZ4_region 001", "sr_BZ4_region 002", "sr_BZ4_region 003",
"sr_BZ4_region 004", "sr_BZ4_region 005", "sr_BZ4_region 006" },
saints_group = M22_groups.Zone_Four_Saints,
center_pos = "Battle_Zone_Navpoint 004",
player_starts = { "nav_player_start_bz04_ 001", "nav_player_start_bz04_ 002" },
trigger = "BZ4_Spawn_Trigger",
battle_area = "BZ4_Battle_Area",
required_kills = 26,
cleared = false,
index = 3,
},
}
Battle_Zone_Finales = {
{ M22_groups.BattleZone_Finale1, M22_groups.BattleZone_Finale1v2 },
{ M22_groups.BattleZone_Finale2 },
{ M22_groups.BattleZone_Finale3v1, M22_groups.BattleZone_Finale3v2 },
{ M22_groups.Armory_Finale1, M22_groups.Armory_Finale2, M22_groups.Armory_Finale3 },
}
Armory_battle_zone = {
initial_spawn = M22_groups.Armory_Initial,
initial_vehicles = M22_groups.Armory_Vehicles,
courtesy_vehicles = M22_groups.Armory_Courtesy,
boss_spawn_regions = { "sr_ARM_region 001", "sr_ARM_region 002", "sr_ARM_region 003",
"sr_ARM_region 004", "sr_ARM_region 005", "sr_ARM_region 006" },
center_pos = "Armory_Navpoint",
player_starts = { "nav_player_start_armory_ 001", "nav_player_start_armory_ 002" },
trigger = "Armory_Spawn_Trigger",
battle_area = "Armory_Battle_Area",
required_kills = 20,
cleared = false,
index = 5,
}
cte_plane_group = {
name = "m22_cte_plane_01"
}
cte_kia_group = {
name = "Group_CTE_Kia"
}
-- Navpoints --
M22_navpoints = {
local_start = "Local_Player_Start",
remote_start = "Remote_Player_Start",
rail_begin = "Airport_Rail_Begin",
roadblock_one_move_tos = { "Roadblock_1_Nav 001", "Roadblock_1_Nav 002", "Roadblock_1_Nav 003", "Roadblock_1_Nav 004",
"Roadblock_1_Nav 005", "Roadblock_1_Nav 006", "Roadblock_1_Nav 007", "Roadblock_1_Nav 008" },
roadblock_two_move_tos = { "Roadblock_2_Nav 001", "Roadblock_2_Nav 002", "Roadblock_2_Nav 003", "Roadblock_2_Nav 004" },
roadblock_three_move_tos = { "Roadblock_3_Nav 001", "Roadblock_3_Nav 002", "Roadblock_3_Nav 003", "Roadblock_3_Nav 004" },
roadblock_four_move_tos = { "Roadblock_4_Nav 001", "Roadblock_4_Nav 002", "Roadblock_4_Nav 003", "Roadblock_4_Nav 004" },
player_angel_start = { "nav_player_start_stop_kb 001", "nav_player_start_stop_kb 002" },
player_kbfight_start = { "Local_kbfight_start", "Remote_kbfight_start" },
player_kia_fight_start = { "Local_Kia_Fight_Start", "Remote_Kia_Fight_Start" },
player_dock_start = { "nav_player_start_dock 001", "nav_player_start_dock 002" },
statue_obs_deck = "Statue_Obs_Deck_Navpoint",
statue_boat_loc = "nav_statue_boat_location",
kia_attack_navs = { "Nav_kia_attack_pos 001", "Nav_kia_attack_pos 002", "Nav_kia_attack_pos 003", "Nav_kia_attack_pos 004" },
kia_defence_east_navs= { "Nav_kia_defense_pos_east 001", "Nav_kia_defense_pos_east 002", "Nav_kia_defense_pos_east 003",
"Nav_kia_defense_pos_east 004", "Nav_kia_defense_pos_east 005", "Nav_kia_defense_pos_east 006" },
kia_defence_west_navs= { "Nav_kia_defense_pos_west 001", "Nav_kia_defense_pos_west 002", "Nav_kia_defense_pos_west 003",
"Nav_kia_defense_pos_west 004", "Nav_kia_defense_pos_west 005", "Nav_kia_defense_pos_west 006" },
kia_vtol_east_attack = { "nav_kia_vtol_idle_east 001", "nav_kia_vtol_attack_east 001" },
kia_vtol_west_attack = { "nav_kia_vtol_idle_west 001", "nav_kia_vtol_attack_west 001" },
}
-- Triggers --
M22_triggers = {
kill_killbane_perimeter = "Kill_Killbane_Perimeter_Trigger",
kill_killbane = "Kill_Killbane_Trigger",
save_saints_perimeter = "Save_Saints_Perimeter_Trigger",
save_saints = "Save_Saints_Trigger",
roadblock_one = "Roadblock_Trigger 001",
roadblock_two = "Roadblock_Trigger 002",
roadblock_three = "Roadblock_Trigger 003",
roadblock_four = "Roadblock_Trigger 004",
statue_elevator = "Statue_Elevator_Trigger",
statue_explosion_region = "Explosion_Region",
untie = { "Untie_Saint_Trigger 001", "Untie_Saint_Trigger 002", "Untie_Saint_Trigger 003", "Untie_Saint_Trigger 004" },
First_Floor = "First_Floor_Trigger",
Second_Floor = "Second_Floor_Trigger",
Player_reached_top = "Player_reached_top_trigger",
Kia_Breadcrumb = "Kia_Breadcrumb_Trigger",
Kia_Boss_Area = "Trigger_Kia_Boss_Area 001",
fart_jars = { "Fart_jar_trigger 001", "Fart_jar_trigger 002", "Fart_jar_trigger 003", "Fart_jar_trigger 004" },
}
-- Characters --
M22_characters = {
Killbane = M22_groups.Airport.killbane,
Killbane_QTE = "", -- Initialized when we spawn Killbane, he may be masked or unmasked.
Kia = M22_groups.Kia.kia,
Oleg = M22_groups.Oleg_and_Pierce.oleg,
Pierce = M22_groups.Oleg_and_Pierce.pierce,
Angel = M22_groups.Angel.npc,
Viola = M22_groups.Viola.viola,
Mayor = M22_groups.Hostages.mayor,
Shaundi = M22_groups.Hostages.shaundi,
}
-- Vehicles --
M22_vehicles = {
Start = M22_groups.Start_Vehicle.vehicle,
Killbanes_Plane = "Killbane_Plane",
Angels_Car = M22_groups.Angel.vehicle,
Kia_Vtol1 = M22_groups.Kia_Vtol1.vtol,
}
-- Mesh Movers --
M22_movers = {
c4 = { "C4_Mover 001", "C4_Mover 002", "C4_Mover 003", "C4_Mover 004" },
first_floor = { "C4_Mover 005", "C4_Mover 006", "C4_Mover 007", "C4_Mover 008" },
}
-- Text --
-- Threads --
M22_threads = {
convo_handle = INVALID_THREAD_HANDLE,
drive_convo_handle = INVALID_THREAD_HANDLE,
battle_zone_gps = INVALID_THREAD_HANDLE,
battle_zone_instance = INVALID_THREAD_HANDLE,
battle_zone_followers = INVALID_THREAD_HANDLE,
battle_zone_saints = INVALID_THREAD_HANDLE,
battle_zone_notoriety_failsafe = INVALID_THREAD_HANDLE,
killbane_path_handle = INVALID_THREAD_HANDLE,
kill_killbane_dialog = INVALID_THREAD_HANDLE,
player_path_handle = INVALID_THREAD_HANDLE,
vtol_one_handle = INVALID_THREAD_HANDLE,
vtol_two_handle = INVALID_THREAD_HANDLE,
kill_kia_dialog = INVALID_THREAD_HANDLE,
burt_dialog = INVALID_THREAD_HANDLE,
kia_boss_handle = INVALID_THREAD_HANDLE,
kia_vomit_handle = INVALID_THREAD_HANDLE,
respawn_handles = { INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE,
INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE },
player_car_speed_handle = INVALID_THREAD_HANDLE,
roadblock_driveto_handles = { INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE,
INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE, INVALID_THREAD_HANDLE },
audio_failsafe = INVALID_THREAD_HANDLE,
}
-- Checkpoints --
M22_checkpoints = {
CHECKPOINT_START = MISSION_START_CHECKPOINT, -- defined in ug_lib.lua
BATTLE_ZONE_1 = "m22_checkpoint_text_battle_zone_1",
BATTLE_ZONE_2 = "m22_checkpoint_text_battle_zone_2",
BATTLE_ZONE_3 = "m22_checkpoint_text_battle_zone_3",
--BATTLE_ZONE_4 = "m22_checkpoint_text_battle_zone_4",
-- These checkpoint save when the player completes their 3rd battle zone
-- Depending on which zone we are, trigger a different checkpoint so that we can
-- warp them and their homies back to the correct zone if they die.
GOTO_ARMORY1 = "m22_checkpoint_text_get_to_the_armory1", -- DT
GOTO_ARMORY2 = "m22_checkpoint_text_get_to_the_armory2", -- NW
GOTO_ARMORY3 = "m22_checkpoint_text_get_to_the_armory3", -- SW
ARMORY_FIGHT = "m22_checkpoint_text_armory_fight",
MAKE_YOUR_CHOICE = "m22_checkpoint_text_make_your_choice",
HELP_ANGEL = "m22_checkpoint_text_help_angel",
STOP_KILLBANE = "m22_checkpoint_text_stop_killbane_from_escaping",
KILL_KILLBANE = "m22_checkpoint_text_kill_killbane",
GOTO_SAINTS = "m22_checkpoint_text_go_to_statue",
SAVE_SAINTS = "m22_checkpoint_text_save_saints",
KILL_KIA = "m22_checkpoint_text_kill_kia",
DEBUG_AIRPORT_CHOICE = "m22_debug_checkpoint_airport_choice",
DEBUG_STATUE_CHOICE = "m22_debug_checkpoint_statue_choice",
DEBUG_STATUE_CTE = "m22_debug_checkpoint_statue_cte",
}
-- Cutscenes --
M22_cutscenes = {
mission_intro = "22_in",
choice = "22_choice",
mission_killbane_outro = "22_out1",
mission_kia_outro = "22_out2",
plane_destroyed = "22_Z01"
}
-- Replaced by "22_choice" cutscene.
--[[
M22_cte_choice_01 = {
name = "m22_cte_01",
}
M22_cte_statue_01 = {
name = "m22_cte_02",
}
--]]
M22_cte_statue_02 = {
name = "m22_cte_03",
}
-- Conversations --
M22_conversations = {
mission_start = {
name = "M22_Mission_Start",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
--[[
drive_convos = {
{
name = "M22_Drive_01",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
{
name = "M22_Drive_02",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
{
name = "M22_Drive_03",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
},
]]--
boss_battle_intros = {
{
name = "M22_Gang_Fight_01",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
--[[
{
name = "M22_Gang_Fight_02",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
{
name = "M22_Gang_Fight_03",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
]]--
{
name = "M22_Second_Battle_Zone",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
},
--[[
boss_battle_middle = {
{
name = "M22_First_Battle_Zone",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
{
name = "M22_Second_Battle_Zone",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
{
name = "M22_Third_Battle_Zone",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
},
]]--
boss_battle_complete = {
--[[
{
name = "M22_End_First_Battle_Zone",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
]]--
{
name = "M22_End_Second_Battle_Zone",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
{
name = "M22_End_Third_Battle_Zone",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
},
armory = {
name = "M22_Armory",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
armory_fight = {
name = "M22_Armory_Fight",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
armory_middle = {
name = "M22_Armory_Battle_Zone",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
choice_phone_call = {
name = "M22_Choice_Call",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
convincing_call = {
name = "M22_Convincing",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
-- Save Shaundi
kinzie_phone_call = {
name = "M22_Kinzie_Phone_Call",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
kinzie_monument = {
name = "M22_Kinzie_Monument",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
-- CUT
--[[
viola_monument = {
name = "M22_Viola_Monument",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
--]]
kia_fight = {
name = "M22_Kia_Fight",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
-- Kill Killbane
angel_phone_call = {
name = "M22_Angel_Under_Fire",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
angel_car_chase = {
name = "M22_Angel_Car_Chase",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
angel_car_chase2 = {
name = "M22_More_Angel_Car_Case",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
angel_shoot_plane = {
name = "M22_Angel_Shoot_Plane",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
-- CUT
--[[
plane_shot_down = {
name = "M22_Plane_Shot_Down",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
--]]
-- CUT
--[[
killbane_fight_01 = {
name = "M22_Killbane_Fight_01",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
--]]
killbane_fight_04 = {
name = "M22_Killbane_Fight_04",
handle = INVALID_CONVERSATION_HANDLE, played = false, direct = false,
},
}
M22_dialog_lines = {
pierce_saints_arrive = { "M22_First_Battle_Saints_Arrive", "M22_Second_Battle_Saints_Arrive" },
pierce_leave_oleg = { "M22_Oleg_Fell_Behind_01", "M22_Oleg_Fell_Behind_02" },
player_armory_clear = "M22_End_Armory_Battle_Zone",
choice_call = { "M22_Choice_Call_01", "M22_Choice_Call_02" },
--kia_vs_vtol = "m22_vtol_attacking_kia",
oleg_convincing = "M22_Convincing_02",
pierce_convincing = "M22_Convincing_01",
kinzie_dock = "M22_Kinzie_Monument_01",
killbane_fight_02 = "M22_Killbane_Fight_02",
killbane_fight_03 = "M22_Killbane_Fight_03",
burt_encouragement = { "M22_Burt_Encouragement_01", "M22_Burt_Encouragement_02", "M22_Burt_Encouragement_03", "M22_Burt_Encouragement_04", "M22_Burt_Encouragement_05" },
burt_damaged = { "M22_Burt_Collateral_Damage_01", "M22_Burt_Collateral_Damage_02", "M22_Burt_Collateral_Damage_03", "M22_Burt_Collateral_Damage_04", "M22_Burt_Collateral_Damage_05" },
burt_fiaj = { "M22_Burt_React_FIAJ_01", "M22_Burt_React_FIAJ_02", "M22_Burt_React_FIAJ_03", "M22_Burt_React_FIAJ_04", "M22_Burt_React_FIAJ_05" },
shaundi_grab_fiaj = "M22_Pick_Up_Grenades",
shaundi_grab_fiaj_nag = "M22_Nag_About_Grenades",
player_grabbed_fiaj = "M22_Pick_Up_Grenades_02",
angel_attacked = { "M22_Angel_Being_Attacked_01", "M22_Angel_Being_Attacked_02", "M22_Angel_Being_Attacked_03" },
angel_chase = { "M22_More_Angel_Car_Chase_02_01", "M22_More_Angel_Car_Chase_03_01" },
angel_encourage_shoot = { "M22_Angel_Encourage_Plane_Shot_01", "M22_Angel_Encourage_Shot_02", "M22_Angel_Encourage_Shot_03" },
plane_down = "M22_Plane_Shot_Down",
}
M22_personas = {
kinzie = {
name = "Kinzie",
persona_id = INVALID_PERSONA_HANDLE,
},
oleg = {
name = "Oleg",
persona_id = INVALID_PERSONA_HANDLE,
},
pierce = {
name = "Pierce",
persona_id = INVALID_PERSONA_HANDLE,
},
kia = {
name = "Kia",
persona_id = INVALID_PERSONA_HANDLE,
},
angel = {
name = "Angel",
persona_id = INVALID_PERSONA_HANDLE,
},
}
M22_audio_events = {
music_start = "M22_Hero_Music_Start",
music_start_checkpoint = "M22_Hero_Music_Checkpoint",
music_fade_out = "M22_Hero_Music_Fade",
music_stop = "M22_Hero_Music_Stop",
music_kia_start = "M22_Kia_Music_Start",
music_kia_finish = "M22_Kia_Music_Finish",
music_kia_stop = "M22_Kia_Music_Stop",
battle_ambience_start = "M22_Battle_Ambience",
battle_anbience_stop = "M22_Battle_Ambience_Stop",
music_kb_zscene_fade = "M22_Hero_Fade_Zscene",
}
M22_roadblocks = {
-- Example
--{ layout = "police_lvl2_2lane", navpoint = "nav_roadblock", handle = -1 },
{layout = "m22_skirmish_4lane", navpoint = "nav_dt_roadblock 001", handle = -1},
{layout = "m22_skirmish_4lane", navpoint = "nav_dt_roadblock 002", handle = -1},
{layout = "m22_wreckage_2lane", navpoint = "nav_dt_roadblock 003", handle = -1},
{layout = "m22_skirmish_4lane", navpoint = "nav_dt_roadblock 004", handle = -1},
{layout = "m22_skirmish_4lane", navpoint = "nav_dt_roadblock 005", handle = -1},
{layout = "m22_wreckage_4lane", navpoint = "nav_dt_roadblock 006", handle = -1},
{layout = "m22_skirmish_2lane", navpoint = "nav_dt_roadblock 007", handle = -1},
{layout = "m22_skirmish_2lane", navpoint = "nav_dt_roadblock 008", handle = -1},
{layout = "m22_wreckage_2lane", navpoint = "nav_ne_roadblock 001", handle = -1},
{layout = "m22_skirmish_2lane", navpoint = "nav_ne_roadblock 002", handle = -1},
{layout = "m22_skirmish_4lane", navpoint = "nav_ne_roadblock 003", handle = -1},
{layout = "m22_wreckage_4lane", navpoint = "nav_ne_roadblock 004", handle = -1},
{layout = "m22_skirmish_4lane", navpoint = "nav_ne_roadblock 005", handle = -1},
{layout = "m22_skirmish_2lane", navpoint = "nav_ne_roadblock 006", handle = -1},
{layout = "m22_wreckage_2lane", navpoint = "nav_nw_roadblock 001", handle = -1},
{layout = "m22_skirmish_4lane", navpoint = "nav_nw_roadblock 002", handle = -1},
{layout = "m22_skirmish_2lane", navpoint = "nav_nw_roadblock 003", handle = -1},
{layout = "m22_wreckage_2lane", navpoint = "nav_nw_roadblock 004", handle = -1},
{layout = "m22_skirmish_2lane", navpoint = "nav_nw_roadblock 005", handle = -1},
{layout = "m22_skirmish_4lane", navpoint = "nav_nw_roadblock 006", handle = -1},
{layout = "m22_wreckage_4lane", navpoint = "nav_sw_roadblock 001", handle = -1},
{layout = "m22_skirmish_2lane", navpoint = "nav_sw_roadblock 002", handle = -1},
{layout = "m22_wreckage_2lane", navpoint = "nav_sw_roadblock 003", handle = -1},
{layout = "m22_skirmish_4lane", navpoint = "nav_sw_roadblock 004", handle = -1},
{layout = "m22_wreckage_2lane", navpoint = "nav_sw_roadblock 005", handle = -1},
{layout = "m22_skirmish_4lane", navpoint = "nav_sw_roadblock 006", handle = -1},
}
m22_statue_spawn_regions = {
"sr_statue_spawn_region 001", "sr_statue_spawn_region 002", "sr_statue_spawn_region 003", "sr_statue_spawn_region 004",
"sr_statue_spawn_region 005", "sr_statue_spawn_region 006", "sr_statue_spawn_region 007", "sr_statue_spawn_region 008",
}
M22_anims = {
fiaj_reactions = {
{ intro = "Stand_to_FIAJ_ReactA", outro = "FIAJ_ReactA_To_Stand" },
{ intro = "Stand_to_FIAJ_ReactB", outro = "FIAJ_ReactB_To_Stand" },
{ intro = "Stand_to_FIAJ_ReactC", outro = "FIAJ_ReactC_To_Stand" },
{ intro = "Stand_to_FIAJ_ReactD", outro = "FIAJ_ReactD_To_Stand" },
},
}
-- Other --
in_coop = false
Completed_m23 = false
Completed_m24 = false
NO_ZONE = 0
ZONE_ACTIVE = 1
STAG = true
SYND = false
Active_conversation = {
convo_table = nil
}
Current_bz = {
zone = NO_ZONE,
num_initial_stag_alive = 0,
num_initial_synd_alive = 0,
kills = 0,
num_bosses = 0,
bosses_killed = 0,
num_enemies_released = 0,
}
Nearest_bz_center = ""
Number_of_zones_cleared = 0
Latest_zone_cleared = 0
Local_player_zone = NO_ZONE -- These are either FIRST/SECOND
Remote_player_zone = NO_ZONE -- Tells us what zones the players are in.
Mission_23_name = "m23"
Mission_24_name = "m24"
-- Armory
Armory_reached = false
-- Player Choice
Player_choice = "none"
Next_mission = Mission_23_name -- default to mission 23 for mission_win
-- Airport
M22_ROCKET_LAUNCHER = "Explosive-RocketLauncher"
M22_SONICWAVE_GUN = "Special-SonicGun"
M22_RC_GUN = "Special-RCVehicleGun"
M22_PLAYER_KB_LOADOUT = { M22_ROCKET_LAUNCHER }
M22_PLAYER_SONIC_LOADOUT = { M22_SONICWAVE_GUN }
Airport_player_path = {
"Player Airport Spline 001",
"Player Airport Spline 001b",
"Player Airport Spline 002",
"Player Airport Spline 003",
"Player Airport Spline 004",
"Player Airport Spline 005",
"Player Airport Spline 006",
}
Airport_Killbane_Path1 = "Killbane Airport Spline 001"
Airport_Killbane_Path2 = "Killbane Airport Spline 002"
Airport_Killbane_Path3 = "Killbane Airport Spline 003"
Airport_Killbane_Path4 = "Killbane Airport Spline 004"
Airport_Killbane_Path5 = "Killbane Airport Spline 005"
Num_plane_hits = 0
Killbane_qte_finished = false
-- Statue
M22_statue_populated = false
Num_c4_left_to_destroy = 0
Total_c4_to_destroy = 0
Num_c4_left_first_floor = 0
Player_used_elevator = false
First_floor_cleared = false
Second_floor_reached = false
Player_reached_breadcrumb = false
Player_reached_top = false
Player_got_fiaj = false
M22_burt_can_play_damage_line = true
Vtol_path1 = "Vtol_path 001"
Vtol_path2 = "Vtol_path 002"
Battle_zone_boss_hud_bar_factor = 3
-- Kia Boss Battle
Kia_boss_ai = {
current_navpoint = nil,
attack_vtol_side = nil,
attack_vtol_attacking = false,
}
M22_cur_cell_call_name = ""
-- *************************
--
-- 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
--
-- m22_checkpoint: The checkpoint the mission should begin at
-- is_restart: TRUE if the mission is restarting, FALSE otherwise
--
function m22_start(m22_checkpoint, is_restart)
in_coop = coop_is_active()
--m22_checkpoint = M22_checkpoints.ARMORY_FIGHT
-- Check if this mission starting from the beginning
if (m22_checkpoint == M22_checkpoints.CHECKPOINT_START) then
if (is_restart == false) then
-- First time playing mission
local cutscene_navs = { "Local_Player_Start", "Remote_Player_Start" }
-- Play an intro cutscene???
if (M22_cutscenes.mission_intro ~= "") then
cutscene_play(M22_cutscenes.mission_intro, nil, cutscene_navs, false)
end
end
end
-- Handle mission initialization for the current checkpoint
m22_initialize(m22_checkpoint)
-- Run the mission from the current checkpoint
m22_run(m22_checkpoint)
end
-- This is the primary function responsible for cleaning up the entire mission
-- CALLED FROM CODE (+++MUST RETURN IMMEDIATLY+++)
--
function m22_cleanup()
hud_timer_stop(1)
-- Cleanup the QTE system
qte_cleanup()
-- Disable zone swaps
city_zone_swap("planecrash", DISABLE) -- Cleanup Killbane plane crash
city_zone_swap("burn", DISABLE) -- Turn off the city burning
-- If the player is replaying this mission, and the statue got blown
-- up previously, redo that.
if Completed_m23 == true and Completed_m24 == false then
city_zone_swap("rubble", true)
end
m22_cleanup_battle_zones()
m22_cleanup_goto_armory_sequence()
m22_cleanup_kill_kia()
m22_cleanup_triggers(M22_triggers)
m22_cleanup_threads(M22_threads)
m22_cleanup_movers(M22_movers)
m22_cleanup_conversations()
m22_cleanup_personas()
cleanup_groups(M22_groups)
mission_waypoint_remove()
shop_ignore_clerk(false)
--boss_battle_kia_active(false)
on_qte_animation_trigger("")
on_human_killed("")
on_projectile_hit("")
notoriety_force_no_spawn("police", DISABLE)
notoriety_force_no_spawn("stag", false) -- AC: Test
notoriety_force_no_spawn("luchadores", DISABLE)
notoriety_force_no_spawn_group("stag_tank", false)
notoriety_force_no_spawn_group("stag_attack_heli", false)
notoriety_force_no_spawn_group("stag_heli", false)
notoriety_force_no_spawn_group("stag_riot", false)
-- Remove Fake Notoriety
hud_set_fake_notoriety("police", false)
hud_set_fake_notoriety("luchadores", false)
set_stag_active(DISABLE)
notoriety_set_can_decay(ENABLE)
--notoriety_force_no_spawn("syndicate", false)
disable_specific_notoriety_group("stag", 2, "G_STAG_CopCar", false)
disable_specific_notoriety_group("stag", 3, "G_STAG_CopCar", false)
disable_specific_notoriety_group("stag", 4, "G_STAG_CopCar", false)
disable_specific_notoriety_group("stag", 5, "G_STAG_CopCar", false)
disable_specific_notoriety_group("stag", 2, "G_STAG_BikeCop", false)
disable_specific_notoriety_group("stag", 3, "G_STAG_BikeCop", false)
for i, spawn in pairs(m22_statue_spawn_regions) do
cleanup_spawn_regions(m22_statue_spawn_regions[i], false)
end
cleanup_spawn_groups(M22_groups.Statue_Spawn1.name)
cleanup_spawn_groups(M22_groups.Statue_Spawn2.name)
cleanup_spawn_groups(M22_groups.Statue_Spawn3.name)
cleanup_spawn_groups(M22_groups.Statue_Spawn4.name)
cleanup_spawn_groups(M22_groups.Statue_Spawn5.name)
-- turn roadblocks and ambient roadblocks back on
roadblocks_ambient_traffic_enable(true)
roadblocks_enable(true)
set_civilians_flee(DISABLE)
flashpoints_enable(ENABLE) -- reenable flashpoints
on_death("", M22_characters.Oleg)
on_death("", M22_characters.Pierce)
on_dismiss("", M22_characters.Pierce)
-- Cleanup on_death callback for the tied up saints
for i, saint in pairs(M22_groups.Statue.saints) do
on_death("", saint)
end
set_player_can_enter_exit_vehicles(LOCAL_PLAYER, true)
-- Make sure all the weapon slots are enabled again
inv_weapon_disable_all_slots(DISABLE)
if in_coop then
set_player_can_enter_exit_vehicles(REMOTE_PLAYER, true)
end
-- Destroy the roadblocks around the city
for i, roadblock in pairs(M22_roadblocks) do
roadblock_destroy(roadblock.handle)
end
-- Reset density of peds and traffic
set_ped_density(1)
set_traffic_density(1)
spawning_pedestrians(true)
-- Reset parked car spawning.
parking_spot_reset_max()
audio_object_post_event("M22_QTE_Music_Stop", nil, nil, LOCAL_PLAYER)
audio_object_post_event(M22_audio_events.music_kia_stop, nil, nil, LOCAL_PLAYER)
inv_remove_temp_loadout(M22_PLAYER_KB_LOADOUT)
player_movement_enable(LOCAL_PLAYER)
if coop_is_active() then
player_movement_enable(REMOTE_PLAYER)
end
end
-- Called when the mission has ended with success
-- CALLED FROM CODE (+++MUST RETURN IMMEDIATLY+++)
--
function m22_success()
--[[ INSERT ANY MISSION SPECIFIC SUCCESS STUFF ]]--
if (Next_mission == Mission_23_name) then
game_choice_set_state( MISSION_22_CHOICE, M22_CHOICE_KILLBANE_KILL )
else
game_choice_set_state( MISSION_22_CHOICE, M22_CHOICE_KILLBANE_ESCAPE )
end
local skip_teleport = true
m22_coop_skip(skip_teleport) -- do the stuff we'd do in the skip case
end
-- *************************
--
-- Local functions
--
-- *************************
-- Initialize the mission for the specified checkpoint
--
-- checkpoint: Checkpoint to initialize the mission to
--
function m22_initialize(checkpoint)
-- Make sure the screen is completly faded out
mission_start_fade_out(0.0)
-- Set the mission author
set_mission_author("John Karczewski")
-- Common initialization
m22_initialize_common()
-- Checkpoint specific initialization
m22_initialize_checkpoint(checkpoint)
-- Reduce density of peds and traffic
set_ped_density(0.25)
set_traffic_density(0.1)
-- Start fading in
mission_start_fade_in()
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 m22_run(first_checkpoint)
local current_checkpoint = first_checkpoint
-- Run the mission from the beginning or from a battle zone checkpoint
if (current_checkpoint == M22_checkpoints.CHECKPOINT_START or m22_checkpoint_is_battle_zone(current_checkpoint) == true) then
m22_process_battle_zone_sequence()
current_checkpoint = m22_set_post_battle_zone_checkpoint()
end
if (m22_checkpoint_is_get_to_armory(current_checkpoint) == true) then
m22_goto_armory_sequence()
current_checkpoint = M22_checkpoints.ARMORY_FIGHT
mission_set_checkpoint(M22_checkpoints.ARMORY_FIGHT, true)
end
if current_checkpoint == M22_checkpoints.ARMORY_FIGHT then
m22_process_armory_fight()
-- Play dialog lines prior to the cutscene
--[[
M22_threads.convo_handle = thread_new("m22_play_cell_convo", M22_conversations.mission_start.name, true)
local line_handle = audio_play_persona_line_2d(M22_personas.angel.persona_id, M22_dialog_lines.choice_call[1])
-- Wait for the line to finish
while (audio_is_playing(line_handle) == true)do
thread_yield()
end
audio_stop(line_handle)
]]--
m22_play_cell_convo(M22_dialog_lines.choice_call[1], true, M22_personas.angel.persona_id)
local line_handle = audio_play_persona_line(LOCAL_PLAYER, M22_dialog_lines.choice_call[2])
--delay(1.0)
-- Wait for the line to finish
m22_wait_for_foley_safe(line_handle, 60.0)
audio_stop(line_handle)
-- Play the cutscene
cutscene_play(M22_cutscenes.choice, nil, { Armory_battle_zone.center_pos, Armory_battle_zone.center_pos })
current_checkpoint = M22_checkpoints.MAKE_YOUR_CHOICE
mission_set_checkpoint(M22_checkpoints.MAKE_YOUR_CHOICE)
end
-- Replaced by "22_choice" cutscene.
--[[
if current_checkpoint == M22_checkpoints.DEBUG_AIRPORT_CHOICE then
m22_choice_airport_cutscene()
current_checkpoint = M22_checkpoints.DEBUG_STATUE_CHOICE
end
if current_checkpoint == M22_checkpoints.DEBUG_STATUE_CHOICE then
m22_choice_statue_cutscene()
current_checkpoint = M22_checkpoints.MAKE_YOUR_CHOICE
mission_set_checkpoint(M22_checkpoints.MAKE_YOUR_CHOICE)
end
--]]
if current_checkpoint == M22_checkpoints.MAKE_YOUR_CHOICE then
m22_process_player_choice_sequence()
if (Player_choice == "killbane") then
current_checkpoint = M22_checkpoints.STOP_KILLBANE
mission_set_checkpoint(M22_checkpoints.STOP_KILLBANE)
else
current_checkpoint = M22_checkpoints.DEBUG_STATUE_CTE
end
end
if current_checkpoint == M22_checkpoints.STOP_KILLBANE then
m22_protect_angel_sequence()
m22_in_transit_to_airport()
m22_setup_killbane_chase_sequence()
m22_process_killbane_chase_sequence()
audio_object_post_event(M22_audio_events.music_kb_zscene_fade, nil, nil, LOCAL_PLAYER)
-- Setup the killbane fight and cinematic (need a screen fade here since we need to apply the zone-swap)
mission_start_fade_out(0.0)
m22_setup_kill_killbane()
mission_start_fade_in()
current_checkpoint = M22_checkpoints.KILL_KILLBANE
mission_set_checkpoint(M22_checkpoints.KILL_KILLBANE, true) -- don't save out their vehicle
end
if current_checkpoint == M22_checkpoints.KILL_KILLBANE then
m22_killbane_plane_destroyed_scene()
m22_process_kill_killbane()
Player_choice = "killbane"
end
if current_checkpoint == M22_checkpoints.DEBUG_STATUE_CTE then
m22_arrived_at_dock_sequence()
m22_c4_objective_cte()
current_checkpoint = M22_checkpoints.GOTO_SAINTS
mission_set_checkpoint(M22_checkpoints.GOTO_SAINTS, false)
end
if current_checkpoint == M22_checkpoints.GOTO_SAINTS then
m22_go_to_statue_sequence()
m22_setup_save_the_saints()
fade_out(0.5)
fade_out_block()
teleport_coop(M22_navpoints.statue_obs_deck, M22_navpoints.statue_obs_deck, true)
-- Equip the sonic gun.
m22_equip_temp_weapons_for_save_saints()
fade_in(0.5)
fade_in_block()
m22_cleanup_statue_courtesy_boats()
current_checkpoint = M22_checkpoints.SAVE_SAINTS
mission_set_checkpoint(M22_checkpoints.SAVE_SAINTS, false)
end
if current_checkpoint == M22_checkpoints.SAVE_SAINTS then
m22_process_save_the_saints()
m22_cleanup_save_the_saints()
current_checkpoint = M22_checkpoints.KILL_KIA
mission_set_checkpoint(M22_checkpoints.KILL_KIA, true) -- don't save out their vehicle
end
if current_checkpoint == M22_checkpoints.KILL_KIA then
m22_process_kill_kia()
m22_cleanup_kill_kia()
Player_choice = "shaundi"
end
-- Call mission success??
if Player_choice == "killbane" then
mission_end_success("m22", M22_cutscenes.mission_killbane_outro, M22_navpoints.player_kbfight_start)
else
fade_out(0.5)
fade_out_block()
mission_set_completed( "m22" )
mission_unlock( "m24" )
mission_autosave()
mission_end_to_activity( "m22", "m24" )
end
end
-- Primary function to process all of the battlezones the player must clear before moving on in the mission
function m22_process_battle_zone_sequence()
-- Enable all the battlezone triggers
for i, battle_zone in pairs(Battle_Zone_Groups) do
on_trigger("m22_zone_triggered_cb", battle_zone.trigger)
on_trigger_exit("m22_zone_exited_cb", battle_zone.trigger)
trigger_enable(battle_zone.trigger, true)
end
if (Number_of_zones_cleared == 0) then
-- Play some dialog
M22_threads.convo_handle = thread_new("m22_play_cell_convo", M22_conversations.mission_start.name, true)
end
local oleg_tutorial_displayed = false
-- Loop until all the zones have been completed
while (Number_of_zones_cleared < NUM_ZONES_TO_COMPLETE_TO_SUCCEED) do
-- Update the object text to get to the battle zone
objective_text_clear(0)
objective_text_clear(1)
objective_text( 0, "m22_obj_goto_battlezone", "", "", SYNC_LOCAL, OI_ASSET_LOCATION)
objective_text( 1, "m22_obj_goto_battlezone", "", "", SYNC_REMOTE, OI_ASSET_LOCATION)
-- Initialize the current battle zone data
Current_bz.zone = NO_ZONE
-- Setup all the battle zones triggers (for any remaining battle zones)
m22_show_remaining_battle_zones()
-- Begin plotting GPS paths to the nearest battle zone.
M22_threads.battle_zone_gps = thread_new("m22_thread_neareast_battlezone_gps")
-- Set the notoriery respawn timers
notoriety_force_no_spawn("stag",false)
notoriety_force_no_spawn("luchadores", false)
notoriety_spawn_group_set_delay("luchadores", 80000)
notoriety_spawn_group_set_delay("stag", 80000)
-- Set the ped/traffic density for traveling between zones
set_ped_density(0.25)
set_traffic_density(0.1)
spawning_pedestrians(true)
-- Make Oleg invulnerable
turn_invulnerable(M22_characters.Oleg, true)
-- Start a thread to process when to play the driving conversation
-- M22_threads.drive_convo_handle = thread_new("m22_thread_process_drive_convo")
-- Start the ambient battle audio until the player reaches a battle area
audio_object_post_event(M22_audio_events.battle_ambience_start, nil, nil, LOCAL_PLAYER)
-- Display a tutorial telling the player that they can leave Oleg behind after completing
-- the first battle zone.
if Number_of_zones_cleared == 1 and oleg_tutorial_displayed == false then
oleg_tutorial_displayed = true
tutorial_start("mis_22_oleg_follow", 5000, true, true)
end
-- Wait until the player has reached one fo the battle zone areas
Current_bz.zone = NO_ZONE
while (Current_bz.zone == NO_ZONE) do
thread_yield()
end
-- Stop auto-updating the GPS.
mission_waypoint_remove()
thread_kill(M22_threads.battle_zone_gps)
M22_threads.battle_zone_gps = INVALID_THREAD_HANDLE
-- Turn notoriety off and disable peds and traffic while in the battle zone
m22_set_stag_synd_notoriety(0)
set_ped_density(0.01)
set_traffic_density(0.01)
spawning_pedestrians(false)
-- Stop the ambient battle audio while the player is in an active battle area
audio_object_post_event(M22_audio_events.battle_anbience_stop, nil, nil, LOCAL_PLAYER)
-- Make Oleg vulnerable again
turn_vulnerable(M22_characters.Oleg)
-- Kill the driving convo thread
thread_kill(M22_threads.drive_convo_handle)
-- Kick off a thread to process the battle zone instance (do this in a thread so it can be interrupted if the player leaves)
M22_threads.battle_zone_instance = thread_new("m22_process_active_battle_zone_thread")
-- Wait until the battle zone thread has finished (either completed, or the player left)
while(thread_check_done(M22_threads.battle_zone_instance) == false) do
thread_yield()
end
-- Clear the players' zone flags.
Local_player_zone = NO_ZONE
Remote_player_zone = NO_ZONE
-- Turn notoriety and traffic back on
m22_set_stag_synd_notoriety(3)
set_ped_density(0.25)
set_traffic_density(0.1)
spawning_pedestrians(true)
-- Clean-up the active battle zone
m22_cleanup_active_battle_zone()
end
m22_cleanup_battle_zones()
end
-- Primary thread to process a battle zone area from start to finish
function m22_process_active_battle_zone_thread()
-- Do the initial battlezone spawn
m22_spawn_battle_zone(Current_bz.zone)
-- Create a thread to process the follower leash behaviors
M22_threads.battle_zone_followers = thread_new("m22_thread_process_battle_zone_followers")
-- Play some dialog
M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.boss_battle_intros[Number_of_zones_cleared + 1], 0.0)
-- Process the battle zone sections
m22_process_battle_zone_kill_enemies()
-- Play some dialog
-- M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.boss_battle_middle[Number_of_zones_cleared + 1], 0.0)
-- Process the finale
m22_process_battle_zone_finale()
-- Play some dialog
M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.boss_battle_complete[Number_of_zones_cleared + 1], 0.0)
-- Kick of a new thread to process the Saints reinforcements
M22_threads.battle_zone_saints = thread_new("m22_thread_process_battle_zone_saint_reinforcements")
m22_cleanup_active_battle_zone()
-- Battle zone is complete, update our bookkeeping
Current_bz.zone.cleared = true
Number_of_zones_cleared = Number_of_zones_cleared + 1
Latest_zone_cleared = Current_bz.zone.index
Current_bz.zone = NO_ZONE
-- Set the new checkpoint
m22_set_battle_zone_complete_checkpoint()
end
-- Function to process the initial enemies the player must kill at a battle zone
function m22_process_battle_zone_kill_enemies()
-- Reduce density of peds and traffic
set_ped_density(0.01)
set_traffic_density(0.01)
on_human_killed("m22_battle_zone_initial_died_cb")
notoriety_force_no_spawn("stag", true)
notoriety_force_no_spawn("luchadores", true)
-- Set notoriety timer for when spawning starts up again
notoriety_set_override_timer("stag", true, 3000, 5000)
notoriety_set_override_timer("gang LD", true, 3000, 5000)
-- Start a failsafe thread that will re-enable notoriety spawns anyway if
-- something goes horribly wrong.
M22_threads.battle_zone_notoriety_failsafe = thread_new("m22_thread_notoriety_failsafe")
-- Wait until the player has almsot killed enough enemies
while (Current_bz.kills < (Current_bz.zone.required_kills - 5) ) do
thread_yield()
end
-- Wait until the player has killed enough enemies
while (Current_bz.kills < Current_bz.zone.required_kills) do
thread_yield()
end
m22_cleanup_battle_zone_kill_enemies()
end
-- Function to clean-up the initial enemies the player must kill at a battle zone
function m22_cleanup_battle_zone_kill_enemies()
-- Remove callbacks on enemy NPCs (we don't need to count kills anymore)
m22_remove_on_death_callbacks(Current_bz.zone)
-- Stop the notoriety failsafe thread if it's still running.
if M22_threads.battle_zone_notoriety_failsafe ~= INVALID_THREAD_HANDLE then
thread_kill(M22_threads.battle_zone_notoriety_failsafe)
M22_threads.battle_zone_notoriety_failsafe = INVALID_THREAD_HANDLE
end
on_human_killed("")
end
-- Function to process the battle zone finale (boss enemey spawns)
function m22_process_battle_zone_finale()
-- Set up spawn regions for finale boss(es)
for i, spawn_region in pairs(Current_bz.zone.boss_spawn_regions)do
spawn_region_enable(spawn_region, true)
end
-- Spawn a finale boss set
for i, spawn_group in pairs(Battle_Zone_Finales[Number_of_zones_cleared + 1]) do
-- Tell the group to attack the nearest player and spawn them.
continuous_spawn_set_orders(spawn_group.name, "attack", "", -1)
continuous_spawn_start(spawn_group.name, 1, 0, "m22_bz_boss_killed_cb", SRF_DEFAULT, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, MINIMAP_ICON_KILL)
end
-- Turn off override spawn times
notoriety_set_override_timer("stag", false, 10000, 15000)
notoriety_set_override_timer("gang LD", false, 10000, 15000)
notoriety_spawn_group_set_delay("luchadores", 60000)
notoriety_spawn_group_set_delay("stag", 60000)
notoriety_force_no_spawn("stag", false)
notoriety_force_no_spawn("luchadores", false)
notoriety_spawn_group_clear_destination("stag")
notoriety_spawn_group_clear_destination("luchadores")
-- Wait until all the bosses have been destroyed
while(Current_bz.bosses_killed < Current_bz.num_bosses) do
thread_yield()
end
m22_cleanup_battle_zone_finale()
end
-- Function to cleanup the battle zone finale
function m22_cleanup_battle_zone_finale()
-- Cleanup any battle zone finale continuous spawns
for i, finale_group in pairs(Battle_Zone_Finales[Number_of_zones_cleared + 1]) do
cleanup_spawn_groups(finale_group.name)
end
-- Cleanup any battle zone spawn regions
for i, spawn in pairs(Current_bz.zone.boss_spawn_regions) do
continuous_spawn_regions_enable(spawn, false)
end
end
-- Thread to process spawning a group of Saints reinforcements at a battle area
function m22_thread_process_battle_zone_saint_reinforcements()
local saints_group = Current_bz.zone.saints_group
local dest = Current_bz.zone.center_pos
local zones_cleared = Number_of_zones_cleared
-- Setup the vehicles
group_create_hidden(saints_group.name, true)
for i, car_group in pairs(saints_group.cars) do
vehicle_enter_group_teleport(car_group.members, car_group.vehicle)
end
-- Find a good navpoint set to use
local best_dist = 0
local best_start_pos = nil
for i, start_pos in pairs(saints_group.start_positions) do
local dist = get_dist_closest_player_to_object(start_pos.nav)
if (dist > best_dist) then
best_dist = dist
best_start_pos = start_pos
end
end
-- If we didn't find a nav greater than 50m away, then don't show the Saints
if (best_start_pos == nil or best_dist < 50.0) then
return
end
-- Teleport the cars into place, and send them towards the Battlezone
for i, car_group in pairs(saints_group.cars) do
-- Teleport the vehicle into place
teleport_vehicle(car_group.vehicle, best_start_pos.nav)
-- Show the car and Saints guys
vehicle_show(car_group.vehicle)
for j, member in pairs(car_group.members) do
character_show(member)
end
-- Follow the path associated with the start position.
vehicle_pathfind_navmesh_do(car_group.vehicle, best_start_pos.path, false, true, false, 1)
delay(3.0)
end
-- Wait until at least one vehicle has arrived
local arrived = false
while(arrived == false) do
for i, car_group in pairs(saints_group.cars) do
if (vehicle_pathfind_check_done(car_group.vehicle) == 1) then
arrived = true
end
end
thread_yield()
end
-- Play some dialog
audio_play_persona_line(M22_characters.Pierce, M22_dialog_lines.pierce_saints_arrive[zones_cleared + 1])
for i, car_group in pairs(saints_group.cars)do
vehicle_exit_group(car_group.members)
end
end
-- Thread to process leashing of followers at battle zones
function m22_thread_process_battle_zone_followers()
while(true) do
local dist = get_dist(LOCAL_PLAYER, M22_characters.Pierce)
if (dist > 25.0 or character_is_in_vehicle(LOCAL_PLAYER) == true) then
follower_make_independent(M22_characters.Pierce, false)
else
follower_make_independent(M22_characters.Pierce, true)
end
dist = get_dist(LOCAL_PLAYER, M22_characters.Oleg)
if (dist > 25.0 or character_is_in_vehicle(LOCAL_PLAYER) == true) then
follower_make_independent(M22_characters.Oleg, false)
else
follower_make_independent(M22_characters.Oleg, true)
end
thread_yield()
end
end
-- Cleanup saints reinforcements
function m22_cleanup_battle_zone_saint_reinforcements()
-- Kill the thread processing the Saints reinforcements
thread_kill(M22_threads.battle_zone_saints)
-- Clean-up the script group
if (group_is_loaded(Current_bz.zone.saints_group.name) == true) then
release_to_world(Current_bz.zone.saints_group.name)
group_destroy(Current_bz.zone.saints_group.name)
end
end
-- External clean-up function to clean-up the active battle zone (on completion, player exit, or mission cancel)
function m22_cleanup_active_battle_zone()
-- Clean-up an active battle
if (Current_bz.zone ~= NO_ZONE) then
m22_cleanup_battle_zone_kill_enemies()
m22_cleanup_battle_zone_finale()
-- Remove the battle area callback and radius from the minimap
m22_cleanup_trigger(Current_bz.zone.battle_area)
minimap_icon_remove_radius(Current_bz.zone.center_pos)
marker_remove(Current_bz.zone.center_pos)
-- Kill the thread processing the battle zone followers
thread_kill(M22_threads.battle_zone_followers)
follower_make_independent(M22_characters.Pierce, false)
follower_make_independent(M22_characters.Oleg, false)
end
-- Turn off the progress bar
hud_bar_off(0)
hud_bar_off(1)
end
-- Removes enter trigger and disables battle zones
function m22_cleanup_battle_zones()
m22_cleanup_active_battle_zone()
-- Clean up the zone triggers
for i, battle_zone in pairs(Battle_Zone_Groups) do
m22_cleanup_trigger(battle_zone.trigger)
m22_cleanup_trigger(battle_zone.battle_area)
m22_remove_on_death_callbacks(battle_zone)
end
-- Stop auto-updating the GPS.
mission_waypoint_remove()
thread_kill(M22_threads.battle_zone_gps)
M22_threads.battle_zone_gps = INVALID_THREAD_HANDLE
end
-- Set the appropriate battle zone complete checkpoint name
function m22_set_battle_zone_complete_checkpoint()
local checkpoint_name = "m22_checkpoint_text_battle_zone_" .. Latest_zone_cleared
--[[
for i, zone in pairs(Battle_Zone_Groups) do
if (zone.cleared == true and i~= Latest_zone_cleared) then
checkpoint_name = checkpoint_name .. "_" .. i
break
end
end
--]]
mission_set_checkpoint(checkpoint_name)
end
-- The player must goto the armory
function m22_goto_armory_sequence()
objective_text_clear(0)
objective_text_clear(1)
objective_text( 0, "m22_obj_goto_armory", "", "", SYNC_LOCAL, OI_ASSET_LOCATION)
objective_text( 1, "m22_obj_goto_armory", "", "", SYNC_REMOTE, OI_ASSET_LOCATION)
-- Enable the armory trigger
on_trigger("m22_armory_reached_cb", Armory_battle_zone.trigger)
trigger_enable(Armory_battle_zone.trigger)
marker_add_trigger(Armory_battle_zone.trigger, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
mission_waypoint_add(Armory_battle_zone.trigger)
-- Battle Zones are over, delay the spawning of some things
notoriety_spawn_group_set_delay("stag_tank", 80000)
notoriety_force_no_spawn_group("stag_tank", false)
notoriety_spawn_group_set_delay("stag_attack_heli", 80000)
notoriety_force_no_spawn_group("stag_attack_heli", false)
notoriety_spawn_group_set_delay("stag_heli", 80000)
notoriety_force_no_spawn_group("stag_heli", false)
notoriety_spawn_group_set_delay("stag_riot", 80000)
notoriety_force_no_spawn_group("stag_riot", false)
M22_threads.convo_handle = thread_new("m22_play_cell_convo", M22_conversations.armory.name, true)
-- Make Oleg invulnerable
turn_invulnerable(M22_characters.Oleg, true)
-- Start the ambient battle audio until the player reaches a battle area
audio_object_post_event(M22_audio_events.battle_ambience_start, nil, nil, LOCAL_PLAYER)
while not Armory_reached do
thread_yield()
end
-- Stop the ambient battle audio while the player is in an active battle area
audio_object_post_event(M22_audio_events.battle_anbience_stop, nil, nil, LOCAL_PLAYER)
-- Make Oleg vulnerable again
turn_vulnerable(M22_characters.Oleg)
m22_cleanup_goto_armory_sequence()
end
-- Cleanup the goto armory sequence
function m22_cleanup_goto_armory_sequence()
on_trigger("", Armory_battle_zone.trigger)
end
-- Spawns the initial forces of the armory fight
function m22_process_armory_fight()
-- Set the battle zone to the armory
Current_bz.zone = Armory_battle_zone
-- Add the battle area radius, and a marker to the center of the battle area
minimap_icon_add_radius(Current_bz.zone.center_pos, trigger_get_radius(Current_bz.zone.battle_area), SYNC_ALL)
marker_add(Current_bz.zone.center_pos, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL)
-- Enable the trigger for the battle area (so we can update the marker on the battle area)
on_trigger("m22_battle_area_triggered_cb", Current_bz.zone.battle_area)
on_trigger_exit("m22_battle_area_exited_cb", Current_bz.zone.battle_area)
trigger_enable(Current_bz.zone.battle_area, true)
-- Turn notoriety off and disable peds and traffic while in the armory battle area
m22_set_stag_synd_notoriety(0)
set_ped_density(0.1)
set_traffic_density(0.1)
spawning_pedestrians(false)
-- Do the initial battlezone spawn
m22_spawn_battle_zone(Current_bz.zone)
-- Update the GSI
objective_text_clear(0)
local hud_bar_size = Armory_battle_zone.required_kills + Battle_zone_boss_hud_bar_factor * #Battle_Zone_Finales[Number_of_zones_cleared + 1]
hud_bar_on(0, "Health", "m22_obj_clear_armory", hud_bar_size, SYNC_LOCAL, OI_ASSET_KILL)
hud_bar_set_value(0, hud_bar_size, SYNC_LOCAL)
if (coop_is_active() == true) then
objective_text_clear(1)
hud_bar_on(1, "Health", "m22_obj_clear_armory", hud_bar_size, SYNC_REMOTE, OI_ASSET_KILL)
hud_bar_set_value(1, hud_bar_size, SYNC_REMOTE)
end
-- Wait until one of the player's has reached the Armory area
while(object_is_in_trigger(Current_bz.zone.battle_area, LOCAL_PLAYER) == false and
(coop_is_active() == false or object_is_in_trigger(Current_bz.zone.battle_area, REMOTE_PLAYER) == false)) do
thread_yield()
end
-- Play some dialog
M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.armory_fight, 0.0)
-- Process the armory battle zone
m22_process_battle_zone_kill_enemies()
-- Play some dialog
M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.armory_middle, 0.0)
m22_process_battle_zone_finale()
-- Play some dialog
local line_handle = audio_play_persona_line(LOCAL_PLAYER, M22_dialog_lines.player_armory_clear)
m22_wait_for_foley_safe(line_handle, 60.0)
audio_stop(line_handle)
-- Oleg and Pierce are no longer part of the player's party
party_dismiss(M22_characters.Oleg)
party_dismiss(M22_characters.Pierce)
turn_invulnerable(M22_characters.Oleg, true) -- shouldn't die unless the player kills them
turn_invulnerable(M22_characters.Pierce, true) -- shouldn't die unless the player kills them
on_dismiss("", M22_characters.Pierce) -- Don't fail the mission on dismissal
on_death("", M22_characters.Oleg)
on_death("", M22_characters.Pierce)
-- Revive them if they are downed
npc_revive(M22_characters.Oleg)
npc_revive(M22_characters.Pierce)
m22_cleanup_active_battle_zone()
-- Destroy the guys we spawned
if group_is_loaded(Armory_battle_zone.initial_spawn.name) then
group_destroy(Armory_battle_zone.initial_spawn.name)
end
-- Turn peds and traffic back on
set_ped_density(0.25)
set_traffic_density(0.1)
spawning_pedestrians(true)
delay(0.5)
end
-- Depending on what the last battle zone cleared was, sets the appropriate checkpoint
--
-- returns: entry from M22_checkpoints
function m22_set_post_battle_zone_checkpoint()
if Latest_zone_cleared == 1 then
mission_set_checkpoint(M22_checkpoints.GOTO_ARMORY1, true)
return M22_checkpoints.GOTO_ARMORY1
elseif Latest_zone_cleared == 2 then
mission_set_checkpoint(M22_checkpoints.GOTO_ARMORY2, true)
return M22_checkpoints.GOTO_ARMORY2
elseif Latest_zone_cleared == 3 then
mission_set_checkpoint(M22_checkpoints.GOTO_ARMORY3, true)
return M22_checkpoints.GOTO_ARMORY3
end
end
function m22_setup_statue_courtesy_boats()
-- Create the courtesy helicoper
group_create(M22_groups.Statue_Boats, true)
-- Set it up so that the player can't change the radio station
radio_block(M22_groups.Statue_Boats.members[1])
radio_block(M22_groups.Statue_Boats.members[2])
end
-- Callback when the player enters the perimeter of the statue
function m22_save_saints_perimeter()
m22_cleanup_trigger(M22_triggers.save_saints_perimeter)
M22_threads.convo_handle = thread_new("m22_play_cell_convo", M22_conversations.kinzie_phone_call.name, true)
group_create(M22_groups.Kinzie, true)
end
-- Callback when the player enters the perimeter of the killbane boss area
function m22_kill_killbane_perimeter()
m22_cleanup_trigger(M22_triggers.kill_killbane_perimeter)
-- M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.angel_phone_call, 0.0)
M22_threads.convo_handle = thread_new("m22_play_cell_convo", M22_conversations.angel_phone_call.name, true)
end
-- Waits until the the player has hit a trigger and then determines what to do
function m22_process_player_choice_sequence()
-- Clear the objective text
objective_text_clear(0)
objective_text_clear(1)
-- Let's add some complications
-- If the player has completed the game as Host, mission 22 will become unlocked again
-- We want to give the player the opportunity to play the finale the other way, so we will force their choice
-- to be the one they did not select the last time
local block_m23 = false
local block_m24 = false
if Completed_m23 and not Completed_m24 then
block_m23 = true
end
if not Completed_m23 and Completed_m24 then
block_m24 = true
end
-- if both are competed, I don't know how you got here, so good luck!
-- maybe change objective if it is chosen for you
objective_text( 0, "m22_obj_killbane_or_shaundi", "", "", SYNC_ALL , OI_ASSET_LOCATION)
-- Setup the perimiter triggers for the two choice areas
if not block_m24 then
on_trigger("m22_save_saints_perimeter", M22_triggers.save_saints_perimeter)
trigger_enable(M22_triggers.save_saints_perimeter, true)
end
if not block_m23 then
on_trigger("m22_kill_killbane_perimeter", M22_triggers.kill_killbane_perimeter)
trigger_enable(M22_triggers.kill_killbane_perimeter, true)
end
-- Setup the player choice triggers
if not block_m24 then
on_trigger("m22_player_choice_cb", M22_triggers.save_saints)
trigger_enable(M22_triggers.save_saints)
marker_add_trigger(M22_triggers.save_saints, MINIMAP_ICON_PROTECT_ACQUIRE, INGAME_EFFECT_CHECKPOINT, OI_ASSET_DEFEND, OI_FLAGS_LOCATION, SYNC_ALL)
end
if not block_m23 then
on_trigger("m22_player_choice_cb", M22_triggers.kill_killbane)
trigger_enable(M22_triggers.kill_killbane)
marker_add_trigger(M22_triggers.kill_killbane, MINIMAP_ICON_KILL, INGAME_EFFECT_CHECKPOINT, OI_ASSET_KILL_FULL, OI_FLAGS_LOCATION, SYNC_ALL)
end
if not block_m24 then
object_indicator_add_objective_text(M22_triggers.save_saints, "PLAYER_CHOICE_M22_OPTION2_TITLE", "PLAYER_CHOICE_M22_OPTION2_BODY")
end
if not block_m23 then
object_indicator_add_objective_text(M22_triggers.kill_killbane, "PLAYER_CHOICE_M22_OPTION1_TITLE", "PLAYER_CHOICE_M22_OPTION1_BODY")
end
-- add waypoint if we are forcing you to go somewhere
if block_m24 then
mission_waypoint_add(M22_triggers.kill_killbane)
end
if block_m23 then
mission_waypoint_add(M22_triggers.save_saints)
end
-- Start playing the music "I need a Hero"
delay(1.0)
audio_object_post_event(M22_audio_events.music_start, nil, nil, LOCAL_PLAYER)
-- Wait until the player choice phone call has finished (or the player already made it to a choice trigger)
while(thread_check_done(M22_threads.convo_handle) == false and Player_choice == "none") do
thread_yield()
end
delay(1.0)
if group_is_loaded(M22_groups.Oleg_and_Pierce.name) then
-- Play Pierce's convincing phone call (if the player hasn't already made their choice)
if (Player_choice == "none") then
audio_play_persona_line(M22_groups.Oleg_and_Pierce.pierce, M22_dialog_lines.pierce_convincing)
delay(0.5)
-- Wait for the line to finish
while audio_persona_line_playing(M22_groups.Oleg_and_Pierce.pierce) do
thread_yield()
end
end
-- Play Oleg's convincing phone call (if the player hasn't already made their choice)
if (Player_choice == "none") then
audio_play_persona_line(M22_groups.Oleg_and_Pierce.oleg, M22_dialog_lines.oleg_convincing)
delay(0.5)
-- Wait for the line to finish
while audio_persona_line_playing(M22_groups.Oleg_and_Pierce.oleg) do
thread_yield()
end
end
end
while Player_choice == "none" do
thread_yield()
end
end
-- Clean up left over npcs from the armory
function m22_cleanup_statue_courtesy_boats()
if group_is_loaded(M22_groups.Statue_Boats) then
group_destroy(M22_groups.Statue_Boats)
end
end
-- The cutscene showing the player's choices
function m22_choice_airport_cutscene()
-- Kick off a thread for the player choice conversation, and wait for it to finish
-- M22_threads.convo_handle = thread_new("m22_play_cell_convo", M22_conversations.choice_phone_call.name, true)
local line_handle = audio_play_persona_line_2d(M22_personas.angel.persona_id, M22_dialog_lines.choice_call[1])
-- Wait for the line to finish
m22_wait_for_foley_safe(line_handle, 60.0)
audio_stop(line_handle)
line_handle = audio_play_persona_line(LOCAL_PLAYER, M22_dialog_lines.choice_call[2])
delay(1.0)
-- Wait for the line to finish
m22_wait_for_foley_safe(line_handle, 60.0)
audio_stop(line_handle)
-- Play the CTE showing the airport
cutscene_in()
group_create( cte_plane_group.name, true )
cutscene_play( M22_cte_choice_01.name )
while(cutscene_check_exiting() == true) do
thread_yield()
end
group_destroy( cte_plane_group.name )
cutscene_out()
end
function m22_choice_statue_cutscene()
-- Play the CTE showing the statue
cutscene_in()
group_create( M22_groups.Hostages.name, true )
group_create( cte_kia_group.name, true )
local teleport_navs = { Armory_battle_zone.center_pos, Armory_battle_zone.center_pos }
cutscene_play( M22_cte_statue_01.name, nil, teleport_navs )
group_destroy( M22_groups.Hostages.name )
group_destroy( cte_kia_group.name )
cutscene_out()
end
-- Cutscene for the airpot angel rail sequence
function m22_angel_rail_cutscene()
fade_out(0.5)
fade_out_block()
delay(1)
--message("After protecting Angel he will explain in a CTE cutscene that Killbane is getting on his personal jet and will be taking off in short order.", 5)
--delay(5)
--message("The player tells Angel to �get me there� and they both will then run to a nearby spawned vehicle (4-door, convertible if possible) and get into it. ", 5)
--message("Angel will drive.", 5)
--delay(5)
fade_in(0.5)
fade_in_block()
end
-- Handles the sequence where Angel drives the player to the airport
function m22_in_transit_to_airport()
objective_text_clear(0)
objective_text( 0, "m22_obj_stop_killbane", "", "", SYNC_ALL , OI_ASSET_KILL)
set_ignore_ai_flag(M22_characters.Angel)
-- Setup notoriety
notoriety_set("luchadores", 5) -- AC: Changed from 3 to 5
notoriety_set_can_decay(false)
notoriety_force_no_spawn("luchadores", false)
notoriety_force_no_spawn_group("stag_tank", true)
notoriety_force_no_spawn_group("stag_attack_heli", true)
notoriety_force_no_spawn_group("stag_heli", true)
notoriety_force_no_spawn_group("stag_riot", true)
-- Set up a delay so the transition is not jarring
delay(2.0)
fade_out(0.5)
fade_out_block()
teleport_coop(M22_navpoints.player_angel_start[1], M22_navpoints.player_angel_start[2], true)
inv_add_temp_loadout(M22_PLAYER_KB_LOADOUT)
set_unjackable_flag(M22_vehicles.Angels_Car, false)
vehicle_enter_teleport(M22_characters.Angel, M22_vehicles.Angels_Car, 0, true, true)
set_seatbelt_flag(M22_characters.Angel, ENABLE)
vehicle_enter_teleport(LOCAL_PLAYER, M22_vehicles.Angels_Car, 1, true, true)
set_player_can_enter_exit_vehicles(LOCAL_PLAYER, false)
if in_coop then
vehicle_enter_teleport(REMOTE_PLAYER, M22_vehicles.Angels_Car, 2, true, true)
set_player_can_enter_exit_vehicles(REMOTE_PLAYER, false)
end
fade_in(0.5)
fade_in_block()
vehicle_suppress_flipping(M22_vehicles.Angels_Car)
vehicle_suppress_npc_exit(M22_vehicles.Angels_Car)
vehicle_speed_override(M22_vehicles.Angels_Car, 45)
vehicle_set_allow_ram_ped(M22_vehicles.Angels_Car, ENABLE)
vehicle_set_ignore_rail_obstacles(M22_vehicles.Angels_Car, ENABLE)
vehicle_ignore_repulsors(M22_vehicles.Angels_Car, ENABLE)
vehicle_set_crazy(M22_vehicles.Angels_Car, ENABLE)
vehicle_prevent_transition_to_ambient(M22_vehicles.Angels_Car, true)
set_unjackable_flag(M22_vehicles.Angels_Car, true)
vehicle_set_script_hard_goto(M22_vehicles.Angels_Car, true)
-- Turn off roadblocks for this part
roadblocks_enable(false)
-- Infinite mass for car
vehicle_infinite_mass(M22_vehicles.Angels_Car, ENABLE)
M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.angel_car_chase, 5.0)
-- Don't allow this pathfind to fail. If it does, keep trying.
while get_dist(M22_vehicles.Angels_Car, "Airport_Rail_Begin") > 10.0 do
vehicle_pathfind_to(M22_vehicles.Angels_Car, "Airport_Rail_Begin", false, false)
thread_yield()
end
vehicle_set_crazy(M22_vehicles.Angels_Car, DISABLE)
end
-- Player meets up with angel and must protect him
function m22_protect_angel_sequence()
objective_text_clear(0)
objective_text( 0, "m22_obj_help_angel", "", "", SYNC_ALL , OI_ASSET_DEFEND)
if group_is_loaded(M22_groups.Angel.name) == false then
group_create(M22_groups.Angel.name, true)
end
if group_is_loaded(M22_groups.Angels_Attackers.name) == false then
group_create(M22_groups.Angels_Attackers.name, true)
end
-- Make sure the player can't enter Angel's car before he's supposed to.
set_unjackable_flag(M22_vehicles.Angels_Car, true)
marker_add(M22_groups.Angel.members[1], MINIMAP_ICON_PROTECT_ACQUIRE, OI_ASSET_DEFEND, OI_FLAGS_DEFAULT, SYNC_ALL)
process_enemy_set(M22_groups.Angels_Attackers.members)
notoriety_force_no_spawn("luchadores", true)
marker_remove(M22_groups.Angel.members[1])
-- Apparently this cutscene was cut; all it does is fade out and in... which is bad.
--m22_angel_rail_cutscene()
end
-- Performs all the necessary operations to set up the chase sequence
function m22_setup_killbane_chase_sequence()
notoriety_force_no_spawn("police", false) -- turn of stag notoriety spawns for this sequence - AC: turned back on for test
notoriety_force_no_spawn("luchadores", false) -- turn of notoriety spawns for now, makes rail sequence too hard - AC: turned back on for test
notoriety_set("luchadores", 5)
notoriety_set_can_decay(false)
Num_plane_hits = 0
group_create(M22_groups.Airport, true)
vehicle_enter_teleport(M22_characters.Killbane, M22_vehicles.Killbanes_Plane, 0, true)
marker_add(M22_vehicles.Killbanes_Plane, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL)
on_projectile_hit("m22_projectile_hit_cb")
vehicle_set_invulnerable_to_player_explosives(M22_vehicles.Killbanes_Plane, true)
vehicle_suppress_flipping(M22_vehicles.Killbanes_Plane)
-- Infinite mass for car
vehicle_infinite_mass(M22_vehicles.Angels_Car, ENABLE)
-- Infinite mass for Killbane's airplane
vehicle_infinite_mass(M22_vehicles.Killbanes_Plane, ENABLE)
vehicle_set_allow_ram_ped(M22_vehicles.Killbanes_Plane, ENABLE)
vehicle_set_ignore_rail_obstacles(M22_vehicles.Killbanes_Plane, ENABLE)
vehicle_ignore_repulsors(M22_vehicles.Killbanes_Plane, ENABLE)
vehicle_set_crazy(M22_vehicles.Killbanes_Plane, ENABLE)
vehicle_prevent_transition_to_ambient(M22_vehicles.Killbanes_Plane, true)
set_unjackable_flag(M22_vehicles.Killbanes_Plane, true)
vehicle_set_script_hard_goto(M22_vehicles.Killbanes_Plane, true)
M22_threads.killbane_path_handle = thread_new("m22_airport_killbane_path_thread")
M22_threads.player_path_handle = thread_new("m22_angel_car_path_thread")
M22_threads.player_car_speed_handle = thread_new("m22_manage_players_car_speed_thread")
on_trigger("m22_spawn_first_roadblock_cb", M22_triggers.roadblock_one)
on_trigger("m22_spawn_second_roadblock_cb", M22_triggers.roadblock_two)
on_trigger("m22_spawn_third_roadblock_cb", M22_triggers.roadblock_three)
on_trigger("m22_spawn_fourth_roadblock_cb", M22_triggers.roadblock_four)
trigger_enable(M22_triggers.roadblock_one)
trigger_enable(M22_triggers.roadblock_two)
trigger_enable(M22_triggers.roadblock_three)
trigger_enable(M22_triggers.roadblock_four)
end
-- Waits for Killbane's plane to be destroyed before continueing
function m22_process_killbane_chase_sequence()
while(not vehicle_is_destroyed(M22_vehicles.Killbanes_Plane)) do
thread_yield()
end
-- vehicle_max_speed(M22_vehicles.Angels_Car, 40)
-- delay(3)
-- vehicle_max_speed(M22_vehicles.Angels_Car, 20)
-- delay(3)
vehicle_max_speed(M22_vehicles.Angels_Car, 10)
delay(1)
vehicle_freeze(M22_vehicles.Angels_Car)
delay(1.0)
--[[ CONVERSATION CUT
while M22_threads.convo_handle ~= INVALID_THREAD_HANDLE do
-- wait for the conversation to finish
thread_yield()
end
--]]
-- remove temp weapons
inv_remove_temp_loadout(M22_PLAYER_KB_LOADOUT)
vehicle_exit(LOCAL_PLAYER)
set_player_can_enter_exit_vehicles(LOCAL_PLAYER, true)
if in_coop then
vehicle_exit(REMOTE_PLAYER)
set_player_can_enter_exit_vehicles(REMOTE_PLAYER, true)
end
-- Clean up the two remaining roadblocks
group_destroy(M22_groups.Angel)
group_destroy(M22_groups.Airport_Roadblock_three) -- cleanup the first roadblock
group_destroy(M22_groups.Airport_Roadblock_four) -- cleanup the first roadblock
end
-- Simple function that performs the necessary setup for the Killbane boss portion of M22
function m22_setup_kill_killbane()
-- Teleport the players first so that we can wait for Killbane to activate in group_create
teleport_coop(M22_navpoints.player_kbfight_start[1], M22_navpoints.player_kbfight_start[2])
if game_choice_get_state(MISSION_21_CHOICE) == M21_CHOICE_KILLBANE_UNMASKED then
group_create_hidden(M22_groups.Killbane_QTE_Nomask.name, true)
M22_characters.Killbane_QTE = M22_groups.Killbane_QTE_Nomask.killbane
else
group_create_hidden(M22_groups.Killbane_QTE.name, true)
M22_characters.Killbane_QTE = M22_groups.Killbane_QTE.killbane
end
zscene_prep(M22_cutscenes.plane_destroyed)
turn_vulnerable(M22_characters.Killbane_QTE)
character_set_never_catch_fire(M22_characters.Killbane_QTE, true)
set_ignore_ai_flag(M22_characters.Killbane_QTE, false)
-- Apply the plane crash zone swap
city_zone_swap("planecrash")
-- Disable all player's weapons
inv_weapon_disable_all_slots(true)
inv_item_equip(nil, LOCAL_PLAYER)
if in_coop then
inv_item_equip(nil, REMOTE_PLAYER)
end
-- AC: Turn off notoriety for this
notoriety_force_no_spawn("police", true) -- turn off stag notoriety spawns for this sequence
notoriety_force_no_spawn("stag", true) -- AC: Test - turn off stag notoriety spawns for this sequence
notoriety_force_no_spawn("luchadores", true) -- turn off notoriety spawns for now,
-- Make sure Killbane is ready to go.
--while (not character_is_ready(M22_characters.Killbane_QTE)) do
-- thread_yield()
--end
while(zscene_is_loaded() == false) do
thread_yield()
end
end
-- Waits for Killbane to die before continueing
function m22_process_kill_killbane()
audio_object_post_event("M22_QTE_Music_Start", nil, nil, LOCAL_PLAYER)
qte_start(LOCAL_PLAYER, "M22_BossFight", "m22_killbane_qte_completed_cb", M22_characters.Killbane_QTE)
objective_text_clear(0)
objective_text( 0, "m22_obj_kill_killbane", "", "", SYNC_ALL , OI_ASSET_KILL)
-- Kick off a thread to process the dialog for this sequence
-- M22_threads.kill_killbane_dialog = thread_new("m22_process_kill_killbane_dialog_thread")
-- Register a callback to stop the QTE and fade out before the QTE actually finishes and
-- Killbane goes all floppy on the ground.
on_qte_animation_trigger("on_killbane_qte_fade_out_trigger")
-- Wait until the QTE is finished
while(not Killbane_qte_finished) do
thread_yield()
end
-- Let the players move again.
player_movement_enable(LOCAL_PLAYER)
if coop_is_active() then
player_movement_enable(REMOTE_PLAYER)
end
-- Kill the thread processing the dialog
-- thread_kill(M22_threads.kill_killbane_dialog)
-- M22_threads.kill_killbane_dialog = INVALID_THREAD_HANDLE
Next_mission = Mission_23_name
end
function on_killbane_qte_fade_out_trigger()
on_qte_animation_trigger("")
qte_cleanup()
fade_out(0.5)
Killbane_qte_finished = true
end
-- Plays the bink of killbane emerging from the rubble
function m22_killbane_plane_destroyed_scene()
-- Prevent the players from moving, that can screw up the orientation of the QTE.
player_movement_disable(LOCAL_PLAYER)
if coop_is_active() then
player_movement_disable(REMOTE_PLAYER)
end
-- Play the bink
cutscene_play(M22_cutscenes.plane_destroyed, nil, M22_navpoints.player_kbfight_start, false)
-- Unhide Killbane, he should be in place
character_show(M22_characters.Killbane_QTE)
-- Wait for Killbane to be ready before fading in.
--while ( not character_is_ready(M22_characters.Killbane_QTE)) do
-- thread_yield()
--end
fade_in(0.5)
fade_in_block()
end
function m22_killbane_qte_completed_cb()
Killbane_qte_finished = true
end
-- Thread to process Killbane's dialog
function m22_process_kill_killbane_dialog_thread()
-- Play the second dialog line
m22_play_persona_line_and_wait(M22_characters.Killbane_QTE, M22_dialog_lines.killbane_fight_02)
delay(5.0)
-- Play the third dialog line
m22_play_persona_line_and_wait(M22_characters.Killbane_QTE, M22_dialog_lines.killbane_fight_03)
delay(3.0)
-- Play the 4th dialog line
M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.killbane_fight_04, 0.0)
while(thread_check_done(M22_threads.convo_handle) == false) do
thread_yield()
end
end
-- Process the sequence when the player arrives at the doc
function m22_arrived_at_dock_sequence()
objective_text_clear(0)
-- Play some dialog of the player talking to Kinzie
m22_play_persona_line_and_wait(LOCAL_PLAYER, M22_dialog_lines.kinzie_dock)
--delay(1.5)
end
-- Player arrived at the statue to find a battle going on
function m22_go_to_statue_sequence()
objective_text_clear(0)
objective_text( 0, "m22_obj_goto_statue", "", "", SYNC_ALL, OI_ASSET_LOCATION )
m22_helper_populate_statue()
group_create(M22_groups.Statue_Base.name)
on_trigger("m22_player_used_elevator_cb", M22_triggers.statue_elevator)
trigger_enable(M22_triggers.statue_elevator, true)
marker_add_trigger(M22_triggers.statue_elevator, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
while not Player_used_elevator do
thread_yield()
end
group_destroy(M22_groups.Statue_Base.name)
end
-- Helper to spawn the initial NPCs at the statue
function m22_helper_populate_statue()
if (M22_statue_populated == false) then
group_create(M22_groups.Statue.name)
for i, saint in pairs(M22_groups.Statue.saints) do
m22_setup_hostage(saint)
set_ignore_ai_flag(saint, true)
turn_invulnerable(saint)
-- Set the animation state
set_script_animation_state(saint, "hostage idle")
-- AC Test
inv_item_remove_all(M22_groups.Statue.saints[i])
-- Register some callbacks
on_trigger("m22_saint_untied_cb", M22_triggers.untie[i])
on_death("m22_saint_died_cb", saint)
trigger_enable(M22_triggers.untie[i], true)
end
-- Set up continuous spawn
for i, spawn in pairs(m22_statue_spawn_regions)do
spawn_region_enable(m22_statue_spawn_regions[i], true)
end
continuous_spawn_start(M22_groups.Statue_Spawn1.name, 0, 1)
continuous_spawn_start(M22_groups.Statue_Spawn2.name, 0, 1)
continuous_spawn_start(M22_groups.Statue_Spawn3.name, 0, 1)
continuous_spawn_start(M22_groups.Statue_Spawn4.name, 0, 1)
continuous_spawn_start(M22_groups.Statue_Spawn5.name, 0, 1)
end
M22_statue_populated = true
end
-- Sets up npcs, triggers and movers for the save the saints sequence
function m22_setup_save_the_saints()
group_create(M22_groups.Viola, true)
m22_setup_hostage(M22_characters.Viola)
m22_helper_populate_statue()
for i, mover in pairs(M22_movers.c4) do
on_mover_destroyed("m22_c4_destroyed_cb", mover)
on_take_damage("m22_c4_damaged_cb", mover)
on_mover_enter_water("m22_c4_entered_water_cb", mover)
mesh_mover_reset(mover)
mesh_mover_show(mover)
-- marker_add(mover, MINIMAP_ICON_USE, OI_ASSET_USE, OI_FLAGS_DEFAULT, SYNC_ALL)
Num_c4_left_to_destroy = Num_c4_left_to_destroy + 1
end
for i, mover in pairs(M22_movers.first_floor)do
on_mover_destroyed("m22_c41_destroyed_cb", mover)
on_take_damage("m22_c4_damaged_cb", mover)
on_mover_enter_water("m22_c41_entered_water_cb", mover)
mesh_mover_reset(mover)
mesh_mover_show(mover)
marker_add(mover, MINIMAP_ICON_USE, OI_ASSET_USE, OI_FLAGS_DEFAULT, SYNC_ALL)
Num_c4_left_to_destroy = Num_c4_left_to_destroy + 1
Num_c4_left_first_floor = Num_c4_left_first_floor + 1
end
trigger_enable(M22_triggers.statue_explosion_region, ENABLE)
on_trigger_exit("m22_human_left_statue_cb", M22_triggers.statue_explosion_region)
Total_c4_to_destroy = Num_c4_left_to_destroy
end
-- Processing function that waits until all the c4 has been destroyed
function m22_process_save_the_saints()
objective_text( 0, "m22_obj_remove_bombs", Total_c4_to_destroy - Num_c4_left_to_destroy, Total_c4_to_destroy .. " ", SYNC_ALL, OI_ASSET_USE )
local time_in_ms = STATUE_EXPLOSION_TIME * 1000
hud_timer_set(1, time_in_ms, "m22_statue_times_up_cb")
while(Num_c4_left_first_floor > 0)do
thread_yield()
end
-- Disable first floor spawn regions
spawn_region_enable(m22_statue_spawn_regions[1], false)
spawn_region_enable(m22_statue_spawn_regions[4], false)
spawn_region_enable(m22_statue_spawn_regions[5], false)
spawn_region_enable(m22_statue_spawn_regions[8], false)
objective_text( 0, "m22_obj_proceed_up_statue", "", "", SYNC_ALL, OI_ASSET_LOCATION )
on_trigger("m22_first_floor_cb", M22_triggers.First_Floor)
trigger_enable(M22_triggers.First_Floor, true)
marker_add_trigger(M22_triggers.First_Floor, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
while not Second_floor_reached do
thread_yield()
end
objective_text( 0, "m22_obj_remove_bombs", Total_c4_to_destroy - Num_c4_left_to_destroy, Total_c4_to_destroy .. " ", SYNC_ALL, OI_ASSET_USE )
--M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.viola_monument, 0.0)
local played_music_fade = false
while(Num_c4_left_to_destroy > 0) do
-- If there's only 5 seconds left, start fading out the music
if (played_music_fade == false and hud_timer_get_remainder(1) < 5000) then
audio_object_post_event(M22_audio_events.music_fade_out, nil, nil, LOCAL_PLAYER)
played_music_fade = true
end
thread_yield()
end
-- If the music isn't already fading, then stop it
if (played_music_fade == false) then
audio_object_post_event(M22_audio_events.music_fade_out, nil, nil, LOCAL_PLAYER)
end
end
-- Cleans everything up from save the saints sequence
function m22_cleanup_save_the_saints()
on_trigger("m22_player_reached_breadcrumb_cb", M22_triggers.Kia_Breadcrumb)
trigger_enable(M22_triggers.Kia_Breadcrumb, true)
marker_add_trigger(M22_triggers.Kia_Breadcrumb, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
party_dismiss_all()
hud_timer_stop(1) -- stop the clock
objective_text_clear(0)
objective_text( 0, "m22_obj_proceed_up_statue", "", "", SYNC_ALL, OI_ASSET_LOCATION )
delay(3)
while not Player_reached_breadcrumb do
thread_yield()
end
on_trigger("m22_player_reached_top_cb", M22_triggers.Player_reached_top)
trigger_enable(M22_triggers.Player_reached_top, true)
marker_add_trigger(M22_triggers.Player_reached_top, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
while not Player_reached_top do
thread_yield()
end
for i, saint in pairs(M22_groups.Statue.saints) do
on_death("", saint)
m22_cleanup_trigger(M22_triggers.untie[i])
end
-- Stop continuous spawn
for i, spawn in pairs(m22_statue_spawn_regions)do
spawn_region_enable(m22_statue_spawn_regions[i], false)
end
continuous_spawn_stop(M22_groups.Statue_Spawn1.name)
continuous_spawn_stop(M22_groups.Statue_Spawn2.name)
continuous_spawn_stop(M22_groups.Statue_Spawn3.name)
continuous_spawn_stop(M22_groups.Statue_Spawn4.name)
continuous_spawn_stop(M22_groups.Statue_Spawn5.name)
-- remove sonic gun
--inv_remove_temp_loadout(M22_PLAYER_SONIC_LOADOUT)
on_trigger_exit("", M22_triggers.statue_explosion_region)
trigger_enable(M22_triggers.statue_explosion_region, DISABLE)
group_destroy(M22_groups.Statue.name)
group_destroy(M22_groups.Viola)
m22_kia_fight_cte()
end
-- Performs all the needed setup for the Kia fight
function m22_setup_kill_kia()
objective_text_clear(0)
objective_text( 0, "m22_obj_kill_kia", "", "", SYNC_ALL , OI_ASSET_KILL)
group_create(M22_groups.Kia, true)
group_create(M22_groups.Hostages, true)
group_create(M22_groups.Viola, true)
group_create(M22_groups.Kia_battle_props, true)
-- Setup the hostages
m22_setup_hostage(M22_characters.Mayor)
m22_setup_hostage(M22_characters.Shaundi)
m22_setup_hostage(M22_characters.Viola)
-- Setup Kia
character_allow_ragdoll(M22_characters.Kia, false)
character_set_immune_to_explosion_vomit(M22_characters.Kia, true)
character_set_no_explosive_panic(M22_characters.Kia, true)
character_set_never_catch_fire(M22_characters.Kia, true)
npc_weapon_spread(M22_characters.Kia, KIA_WEAPON_SPREAD_MULTIPLIER)
on_take_damage("m22_kia_damaged_cb", M22_characters.Kia)
marker_add(M22_characters.Kia, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL)
-- Setup Shaundi
character_set_immune_to_explosion_vomit(M22_characters.Shaundi, true)
character_set_no_explosive_panic(M22_characters.Shaundi, true)
character_set_never_catch_fire(M22_characters.Shaundi, true)
turn_invulnerable(M22_characters.Shaundi, true) -- can still be hurt by the player
on_death("m22_shaundi_killed_cb", M22_characters.Shaundi)
-- Setup the Mayor (Burt)
on_take_damage("m22_burt_damaged_cb", M22_characters.Mayor)
set_script_animation_state(M22_characters.Mayor, "hostage idle")
set_script_animation_state(M22_characters.Viola, "hostage idle")
-- Setup the Fart in a Jar ammo triggers
for i, trigger in pairs(M22_triggers.fart_jars) do
trigger_enable(trigger, true)
marker_add_trigger(trigger, MINIMAP_ICON_USE, nil, OI_ASSET_USE, OI_FLAGS_DEFAULT, SYNC_ALL)
on_trigger("m22_give_fart_in_jar_ammo_cb", trigger)
end
-- Setup the player killed triggers
trigger_enable(M22_triggers.Kia_Boss_Area, ENABLE)
on_trigger_exit("m22_human_left_statue_cb", M22_triggers.Kia_Boss_Area)
end
-- Spins until Kia dies
function m22_process_kill_kia()
-- Start boss fight music.
audio_object_post_event(M22_audio_events.music_kia_start, nil, nil, LOCAL_PLAYER)
M22_threads.kia_boss_handle = thread_new("m22_kia_boss_ai_thread")
M22_threads.vtol_one_handle = thread_new("m22_process_kia_vtols_thread")
if in_coop then
M22_threads.vtol_two_handle = thread_new("m22_kia_coop_reinforcements_thread")
end
M22_threads.kill_kia_dialog = thread_new("m22_process_kill_kia_dialog_thread")
while not character_is_dead(M22_characters.Kia) do
thread_yield()
end
-- End boss fight music.
audio_object_post_event(M22_audio_events.music_kia_finish, nil, nil, LOCAL_PLAYER)
-- Delay so the end isn't so jarring.
delay(1.0)
thread_kill(M22_threads.kill_kia_dialog)
M22_threads.kill_kia_dialog = INVALID_THREAD_HANDLE
end
-- Thread to process Kia's dialog
function m22_process_kill_kia_dialog_thread()
M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.kia_fight, 0.0)
while(thread_check_done(M22_threads.convo_handle) == false) do
thread_yield()
end
delay(1.5)
-- Tell the player to grab the FIAJ
audio_play_persona_line(M22_characters.Shaundi, M22_dialog_lines.shaundi_grab_fiaj)
delay(2.0)
M22_threads.burt_dialog = thread_new("m22_process_burt_dialog_thread")
-- Process Shaundi FIAJ nags
delay(10.0)
while(true) do
-- Play the line
audio_play_persona_line(M22_characters.Shaundi, M22_dialog_lines.shaundi_grab_fiaj_nag)
-- Add a delay and then wait until Shaundi isn't actively vomitting
delay(rand_int(15, 25))
while(thread_check_done(M22_threads.kia_vomit_handle) == false) do
thread_yield()
end
-- If one of the players got a FIAJ, then stop processing the nags
if (Player_got_fiaj == true) then
break
end
end
end
-- Thread to process Burt's dialog
function m22_process_burt_dialog_thread()
while(true) do
audio_play_persona_line(M22_characters.Mayor, M22_dialog_lines.burt_encouragement[rand_int(1, #M22_dialog_lines.burt_encouragement)])
delay(rand_int(15, 25))
end
end
-- Cleans up the kia fight - kills of the vtol threads
function m22_cleanup_kill_kia()
Next_mission = Mission_24_name
on_take_damage("", M22_characters.Kia)
marker_remove(M22_characters.Kia)
on_death("", M22_characters.Shaundi)
on_take_damage("", M22_characters.Mayor)
m22_remove_temp_weapons_for_save_saints()
on_trigger_exit("", M22_triggers.Kia_Boss_Area)
trigger_enable(M22_triggers.Kia_Boss_Area, DISABLE)
-- Disable the Fart in a Jar ammo triggers
for i, trigger in pairs(M22_triggers.fart_jars) do
trigger_enable(trigger, false)
on_trigger("", trigger)
end
thread_kill(M22_threads.vtol_one_handle)
M22_threads.vtol_one_handle = INVALID_THREAD_HANDLE
thread_kill(M22_threads.vtol_two_handle)
M22_threads.vtol_two_handle = INVALID_THREAD_HANDLE
end
function m22_c4_objective_cte()
fade_out(0.5)
fade_out_block()
-- Unhide all the C4 at the statue
for i, mover in pairs(M22_movers.c4) do
mesh_mover_reset(mover)
mesh_mover_show(mover)
end
for i, mover in pairs(M22_movers.first_floor) do
mesh_mover_reset(mover)
mesh_mover_show(mover)
end
--group_create( M22_groups.Statue.name, true )
m22_setup_statue_courtesy_boats()
group_create( M22_groups.Statue_CTE.name, true )
cutscene_play( M22_cte_statue_02.name, nil, M22_navpoints.player_dock_start )
group_destroy( M22_groups.Statue_CTE.name )
--group_destroy( M22_groups.Statue.name )
-- Give the players sonic guns and farts in jars.
m22_give_temp_weapons_for_save_saints()
--Get rid of Kinzie
if group_is_loaded(M22_groups.Kinzie)then
group_destroy(M22_groups.Kinzie)
end
-- Hide all the C4 at the statue until it's time for that objective
for i, mover in pairs(M22_movers.c4) do
mesh_mover_hide(mover)
end
for i, mover in pairs(M22_movers.first_floor) do
mesh_mover_hide(mover)
end
fade_in(0.5)
fade_in_block()
end
function m22_kia_fight_cte()
fade_out(0.5)
fade_out_block()
message("-- CTE Plays Here --", 5)
message("Kia is shown on the girder of the statue and she curses her plans being foiled by those meddling kids", 5)
m22_setup_kill_kia()
delay(5)
fade_in(0.5)
fade_in_block()
end
-- ***************************************************
-- m22_run Helper Functions
-- ***************************************************
-- Waits for a script foley (persona line) to finish playing,
-- or stops the foley and continues on if a maximum wait time has
-- expired.
--
-- foley_id: (int) the ID of the foley to wait for.
-- max_wait: (float) the maximum time to wait for the foley.
--
function m22_wait_for_foley_safe(foley_id, max_wait)
-- Wait for anything else that was using the failsafe thread handle to finish.
while M22_threads.audio_failsafe ~= INVALID_THREAD_HANDLE do
thread_yield()
end
M22_threads.audio_failsafe = thread_new("delay", max_wait)
-- Wait until the line has ended or our maximum wait time has elapsed.
while audio_is_playing(foley_id) and thread_check_done(M22_threads.audio_failsafe) == false do
thread_yield()
end
-- Kill the voice line if it's still playing.
if audio_is_playing(foley_id) then
audio_stop(foley_id)
end
thread_kill(M22_threads.audio_failsafe)
M22_threads.audio_failsafe = INVALID_THREAD_HANDLE
end
-- This function adds a GPS path to the nearest battle zone.
--
function m22_gps_path_to_nearest_battle()
local nearest_dist = nil
local nearest_group_nav = nil
for i, group in pairs(Battle_Zone_Groups) do
if group.cleared == false then
local cur_dist = get_dist_closest_player_to_object(group.center_pos)
if nearest_dist == nil or cur_dist < nearest_dist then
nearest_dist = cur_dist
nearest_group_nav = group.center_pos
end
end
end
if nearest_group_nav ~= nil then
if Nearest_bz_center ~= nearest_group_nav then
Nearest_bz_center = nearest_group_nav
mission_waypoint_add(nearest_group_nav)
end
end
end
-- Plays a persona line on a character and waits for it to finish.
--
function m22_play_persona_line_and_wait(character, persona_line)
local play_success = audio_play_persona_line(character, persona_line)
if play_success then
delay(1.0)
while(audio_persona_line_playing(character) == true) do
thread_yield()
end
end
end
function m22_cell_convo_finished()
M22_cur_cell_call_name = ""
end
function m22_play_cell_convo(conv_name, receiving_call, persona_override_id)
while M22_cur_cell_call_name ~= "" do
thread_yield()
end
M22_cur_cell_call_name = conv_name
audio_play_for_mission_cellphone(conv_name, receiving_call, true, "", "m22_cell_convo_finished", persona_override_id)
while M22_cur_cell_call_name ~= "" do
thread_yield()
end
M22_cur_cell_call_name = ""
end
-- Spawns the initial npc group for a battle zone. It then sets each member's on_death callback
-- used for kill count management and reinforcemences.
--
-- battle_zone: (string) name of a table containing tables of the Stag and Syndicate groups
-- EX:
-- Battle_Zone_One = { Battle_Zone_One_Stag, Battle_Zone_One_Synd }
function m22_spawn_battle_zone(battle_zone)
Current_bz.num_initial_synd_alive = 0
Current_bz.num_initial_stag_alive = 0
Current_bz.kills = 0
Current_bz.num_bosses = 0
Current_bz.bosses_killed = 0
Current_bz.num_enemies_released = 0
-- Initialize the hud bar.
m22_helper_update_battle_zone_hud()
-- Spawn a finale boss set
for i, spawn_group in pairs(Battle_Zone_Finales[Number_of_zones_cleared + 1]) do
Current_bz.num_bosses = Current_bz.num_bosses + 1
end
-- Check if there are any old battle zone groups that need to be destroyed
for i, battle_zone_group in pairs(Battle_Zone_Groups) do
if (group_is_loaded(battle_zone_group.initial_spawn.name) == true) then
group_destroy(battle_zone_group.initial_spawn.name)
end
if (group_is_loaded(battle_zone_group.saints_group.name) == true) then
release_to_world(battle_zone_group.saints_group.name)
group_destroy(battle_zone_group.saints_group.name)
end
end
delay(1.0) -- arbitrary time to allow group to be cleaned up
-- Spawn the initial spawn group group
group_create(battle_zone.initial_spawn.name, true)
for i, member in pairs(battle_zone.initial_spawn.members) do
if (character_is_dead(member) == false) then
-- Set up the on death callback for all members of the initial Stag force
local team = get_team(member)
if (team == "STAG") then
on_death("m22_battle_zone_stag_initial_died_cb", member)
Current_bz.num_initial_stag_alive = Current_bz.num_initial_stag_alive + 1
elseif (team == "Luchadores" or team == "Morningstar" or team == "Deckers") then
on_death("m22_battle_zone_synd_initial_died_cb", member)
Current_bz.num_initial_synd_alive = Current_bz.num_initial_synd_alive + 1
end
end
end
-- Spawn and immediately release the vehicles for the battle zone.
if battle_zone.initial_vehicles.spawned == false then
battle_zone.initial_vehicles.spawned = true
group_create(battle_zone.initial_vehicles.name, true)
release_to_world(battle_zone.initial_vehicles.name)
group_destroy(battle_zone.initial_vehicles.name)
end
-- Spawn courtesy vehicle
m22_create_player_courtesy_vehicle(battle_zone.courtesy_vehicles)
end
-- Helper function to update the the battle zone HUD
function m22_helper_update_battle_zone_hud()
-- Update the progress bar
local kills_remaining = max((Current_bz.zone.required_kills - Current_bz.kills), 0)
local bosses_remaining = max((#Battle_Zone_Finales[Number_of_zones_cleared + 1] - Current_bz.bosses_killed), 0)
local bar_remaining = kills_remaining + bosses_remaining * Battle_zone_boss_hud_bar_factor
if (Local_player_zone == ZONE_ACTIVE) then
hud_bar_set_value(0, bar_remaining, SYNC_LOCAL)
end
if (Remote_player_zone == ZONE_ACTIVE) then
hud_bar_set_value(1, bar_remaining, SYNC_REMOTE)
end
end
-- Given a player, this checks the other player's current zone slot
--
-- player: (string) name of the player
--
-- returns: FIRST/SECOND
function m22_other_player_in_zone(player)
if player == LOCAL_PLAYER then
-- Need to see if the remote player is in zone
return (Remote_player_zone)
else
return (Local_player_zone)
end
end
-- Sets a player's zone slot
--
-- player: (string) name of a player
--
function m22_set_players_zone(player)
if LOCAL_PLAYER == player then
Local_player_zone = ZONE_ACTIVE
elseif REMOTE_PLAYER == player then
Remote_player_zone = ZONE_ACTIVE
end
end
-- Gets a player's zone slot
--
-- player: (string) name of a player
--
-- returns: FIRST/SECOND
function m22_get_players_zone(player)
if player == LOCAL_PLAYER then
return (Local_player_zone)
else
return (Remote_player_zone)
end
end
-- Removes all on_death callbacks for a given zone
--
-- zone_groups: group of the initial stag/synd
function m22_remove_on_death_callbacks(zone_groups)
for k, char_name in pairs(zone_groups.initial_spawn.members) do
on_death("", char_name)
end
end
-- Displays location markers for all unbeaten battle zones to the players
function m22_show_remaining_battle_zones()
for i, battle_zone in pairs(Battle_Zone_Groups) do
if (battle_zone.cleared == false) then
marker_add_trigger(battle_zone.trigger, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
end
end
end
-- Setup a STAG transport VTOL (assumes the group has already been created) *copied from M10, written by Matt G*
--
-- vtol_table: Lua table defining the STAG transport
function m22_setup_stag_transport(vtol_table)
local seat_idx = 0
for i, char in pairs(vtol_table.pilots) do
-- Put the pilots into the vehicle
vehicle_enter_teleport(char, vtol_table.vtol, seat_idx, true)
follower_remain_in_car(char, true)
seat_idx = seat_idx + 1
end
--for i, drop_off in pairs(vtol_table.drop_offs) do
for j, char in pairs(vtol_table.drop_offs.soldiers) do
-- Put the soldiers into the vehicle
vehicle_enter_teleport(char, vtol_table.vtol, seat_idx, true)
follower_remain_in_car(char, true)
seat_idx = seat_idx + 1
end
--end
end
-- Sets up a hostage character for the statue sequence. No ragdoll, flinching, or attacking this character.
--
-- hostage_name: (string) name of the hostage in question
--
function m22_setup_hostage(hostage_name)
character_allow_ragdoll(hostage_name, DISABLE)
character_prevent_flinching(hostage_name, ENABLE)
character_prevent_bumping(hostage_name, true)
set_dont_attack_me_on_sight_flag(hostage_name, true)
end
function m22_spawn_and_move_roadblock(group_name, dest_navpoint_set_name)
group_create(group_name, true)
for i, member in pairs(group_name.members) do
local car = group_name.cars[i]
vehicle_enter_teleport(member, car) -- teleport each driver in their car
M22_threads.roadblock_driveto_handles[i] = thread_new("m22_roadblock_drive_to_thread", member, car, dest_navpoint_set_name[i], i)
end
end
-- Create a player coutesy vehicle group
function m22_create_player_courtesy_vehicle(courtesy_vehicle_group)
group_create(courtesy_vehicle_group.name, true)
-- If this isn't coop, hide the second vehicle
if (coop_is_active() == false) then
vehicle_hide(courtesy_vehicle_group.vehicles[2])
end
end
-- Function to setup a player's courtesy vehicle by teleporting the player(s) and homies into the vehicle seats
function m22_setup_player_courtesy_vehicle(courtesy_vehicle_group)
-- Put the players into the vehicle
local seat_idx = 0
vehicle_enter_teleport(LOCAL_PLAYER, courtesy_vehicle_group.vehicles[1], seat_idx, true)
seat_idx = seat_idx + 1 -- increment to the next seat
if (coop_is_active() == true) then
vehicle_enter_teleport(REMOTE_PLAYER, courtesy_vehicle_group.vehicles[1], seat_idx, true)
seat_idx = seat_idx + 1 -- increment to the next seat
end
-- Put the homies into the vehicle
vehicle_enter_teleport(M22_characters.Pierce, courtesy_vehicle_group.vehicles[1], seat_idx, true)
vehicle_enter_teleport(M22_characters.Oleg, courtesy_vehicle_group.vehicles[1], 5, true) -- force Oleg into his "special" seat in the back
end
-- Simple function that enables/disables notoriety spawning of brutes. The ordering matters when enableing/disabling
--
-- enable: (bool) true - turns brutes on, false - turns brutes off
function m22_brute_enable(enable)
if enable then
-- Enable brutes
disable_specific_notoriety_group("luchadores", 4, "G_Luchadore_Brute_M", false)
disable_specific_notoriety_group("luchadores", 4, "G_Luchadore_Brute_F", false)
disable_specific_notoriety_group("luchadores", 4, "G_Luchadore_Brute_G", false)
disable_specific_notoriety_group("luchadores", 5, "G_Luchadore_Brute_M", false)
disable_specific_notoriety_group("luchadores", 5, "G_Luchadore_Brute_F", false)
disable_specific_notoriety_group("luchadores", 5, "G_Luchadore_Brute_G", false)
else
-- Disable brutes
disable_specific_notoriety_group("luchadores", 4, "G_Luchadore_Brute_M", true)
disable_specific_notoriety_group("luchadores", 4, "G_Luchadore_Brute_F", true)
disable_specific_notoriety_group("luchadores", 4, "G_Luchadore_Brute_G", true)
disable_specific_notoriety_group("luchadores", 5, "G_Luchadore_Brute_M", true)
disable_specific_notoriety_group("luchadores", 5, "G_Luchadore_Brute_F", true)
disable_specific_notoriety_group("luchadores", 5, "G_Luchadore_Brute_G", true)
end
end
-- Function that sets Stag and Syndacite min/max notorieties to a specific level.
--
-- level: (int) level to set notoriety to
function m22_set_stag_synd_notoriety(level)
notoriety_set_min_and_max("police", level, level)
notoriety_set("police", level)
notoriety_set_min_and_max("luchadores", level, level)
notoriety_set("luchadores", level)
end
-- Gives the sonic gun and farts in jars to both players.
--
function m22_give_temp_weapons_for_save_saints()
inv_weapon_add_temporary(LOCAL_PLAYER, KIA_TEMPORARY_WEAPON, 1, false, false, false, true)
-- Remove any normal flashbangs and replace them with farts in jars.
inv_item_remove(KIA_TEMPORARY_GRENADE, LOCAL_PLAYER)
inv_weapon_add_temporary(LOCAL_PLAYER, KIA_TEMPORARY_GRENADE, 2, false, false, false, true, WEAPON_LEVEL4)
if coop_is_active() then
inv_weapon_add_temporary(REMOTE_PLAYER, KIA_TEMPORARY_WEAPON, 1, false, false, false, true)
-- Remove any normal flashbangs and replace them with farts in jars.
inv_item_remove(KIA_TEMPORARY_GRENADE, REMOTE_PLAYER)
inv_weapon_add_temporary(REMOTE_PLAYER, KIA_TEMPORARY_GRENADE, 2, false, false, false, true, WEAPON_LEVEL4)
end
end
-- Removes the temporary sonic gun and farts in jars from both players.
--
function m22_remove_temp_weapons_for_save_saints()
inv_weapon_remove_temporary(LOCAL_PLAYER, KIA_TEMPORARY_WEAPON)
inv_weapon_remove_temporary(LOCAL_PLAYER, KIA_TEMPORARY_GRENADE)
if (coop_is_active() == true) then
inv_weapon_remove_temporary(REMOTE_PLAYER, KIA_TEMPORARY_WEAPON)
inv_weapon_remove_temporary(REMOTE_PLAYER, KIA_TEMPORARY_GRENADE)
end
end
-- Equips the sonic gun on both players when entering the statue.
--
function m22_equip_temp_weapons_for_save_saints()
inv_item_equip(KIA_TEMPORARY_WEAPON, LOCAL_PLAYER)
if coop_is_active() then
inv_item_equip(KIA_TEMPORARY_WEAPON, REMOTE_PLAYER)
end
end
-- ***************************************************
-- m22_initialize Helper Functions
-- ***************************************************
-- Handle any common initialization
--
function m22_initialize_common()
Completed_m23 = mission_is_complete("m23")
Completed_m24 = mission_is_complete("m24")
city_zone_swap("burn", ENABLE)
-- If the player is replaying this mission, and the statue got blown
-- up previously, undo that for the duration of the mission.
city_zone_swap("rubble", false)
-- Let people buy stuff even though there's notoriety.
shop_ignore_clerk(true)
--notoriety_force_no_spawn("police", true)
flashpoints_enable(DISABLE) -- no flashpoints for this mission
set_stag_active(ENABLE)
disable_specific_notoriety_group("stag", 2, "G_STAG_CopCar", true)
disable_specific_notoriety_group("stag", 3, "G_STAG_CopCar", true)
disable_specific_notoriety_group("stag", 4, "G_STAG_CopCar", true)
disable_specific_notoriety_group("stag", 5, "G_STAG_CopCar", true)
disable_specific_notoriety_group("stag", 2, "G_STAG_BikeCop", true)
disable_specific_notoriety_group("stag", 3, "G_STAG_BikeCop", true)
notoriety_set_can_decay(DISABLE)
notoriety_force_no_spawn_group("stag_tank", true)
notoriety_force_no_spawn_group("stag_attack_heli", true)
notoriety_force_no_spawn_group("stag_heli", true)
notoriety_force_no_spawn_group("stag_riot", true)
roadblocks_ambient_traffic_enable(false)
-- Show Fake Notoriety
hud_set_fake_notoriety("police", true, 5)
hud_set_fake_notoriety("luchadores", true, 5)
set_civilians_flee(ENABLE, ENABLE, LOCAL_PLAYER)
-- Create the roadblocks around the city
for i, roadblock in pairs(M22_roadblocks) do
roadblock.handle = roadblock_create(roadblock.layout, roadblock.navpoint)
end
-- Hide alll the C4 at the statue until it's time for that objective
for i, mover in pairs(M22_movers.c4) do
mesh_mover_hide(mover)
end
for i, mover in pairs(M22_movers.first_floor) do
mesh_mover_hide(mover)
end
-- Load up kinzie's persona
M22_personas.kinzie.persona_id = audio_persona_load_2d(M22_personas.kinzie.name)
M22_personas.kia.persona_id = audio_persona_load_2d(M22_personas.kia.name)
M22_personas.angel.persona_id = audio_persona_load_2d(M22_personas.angel.name)
-- Spawn fewer parked cars so we have room for all the vehicles at the battle zones.
parking_spot_set_max(4)
end
-- Check if the given checkpoint name is a battle zone checkpoint
--
-- checkpoint_name: Name of the checkpoint
--
-- returns:
-- is_battle_zone: True if the checkpoint is for a battle zone
-- last_zone_completed: Last battle zone that was completed
-- second_zone_complted: The second battle zone that was completed (or nil if only one battle zone has been completed)
function m22_checkpoint_is_battle_zone(checkpoint_name)
if (checkpoint_name == M22_checkpoints.BATTLE_ZONE_1) then
return true, 1
elseif (checkpoint_name == M22_checkpoints.BATTLE_ZONE_2) then
return true, 2
elseif (checkpoint_name == M22_checkpoints.BATTLE_ZONE_3) then
return true, 3
end
return false
end
-- Check if the given checkpoint name is an armory checkpoint
--
-- checkpoint_name: Name of the checkpoint
--
-- returns:
-- is_armory_checkpoint: True if the checkpoint is for a battle zone
-- last_zone_completed: Last battle zone that was completed
function m22_checkpoint_is_get_to_armory(checkpoint_name)
if (checkpoint_name == M22_checkpoints.GOTO_ARMORY1) then
return true, 1
elseif (checkpoint_name == M22_checkpoints.GOTO_ARMORY2) then
return true, 2
elseif (checkpoint_name == M22_checkpoints.GOTO_ARMORY3) then
return true, 3
end
return false
end
-- Checkpoint specific initialization
--
-- checkpoint: The checkpoint to be initialized
function m22_initialize_checkpoint(checkpoint)
if (checkpoint == M22_checkpoints.CHECKPOINT_START) then
Number_of_zones_cleared = 0
Latest_zone_cleared = 0
m22_create_player_courtesy_vehicle(M22_groups.Start_Vehicle)
m22_setup_oleg_and_pierce()
teleport_coop(M22_navpoints.local_start, M22_navpoints.remote_start, true)
-- Setup the courtesy vehicle
m22_setup_player_courtesy_vehicle(M22_groups.Start_Vehicle)
m22_brute_enable(DISABLE) -- turn off notoriety brute spawning
m22_set_stag_synd_notoriety(2)
end
local is_battle_zone, zone1, zone2 = m22_checkpoint_is_battle_zone(checkpoint)
if (is_battle_zone == true) then
Latest_zone_cleared = zone1
Battle_Zone_Groups[zone1].cleared = true
if (zone2 == nil) then
Number_of_zones_cleared = 1
else
Number_of_zones_cleared = 2
Battle_Zone_Groups[zone2].cleared = true
end
m22_setup_oleg_and_pierce()
m22_brute_enable(DISABLE) -- turn off notoriety brute spawning
m22_set_stag_synd_notoriety(2)
-- Create the courtesy vehicles
m22_create_player_courtesy_vehicle(Battle_Zone_Groups[Latest_zone_cleared].courtesy_vehicles)
-- Create the Saints groups
group_create(Battle_Zone_Groups[Latest_zone_cleared].saints_group.name, true)
teleport_coop(Battle_Zone_Groups[Latest_zone_cleared].player_starts[1], Battle_Zone_Groups[Latest_zone_cleared].player_starts[2], true)
-- Setup the courtesy vehicle
m22_setup_player_courtesy_vehicle(Battle_Zone_Groups[Latest_zone_cleared].courtesy_vehicles)
end
local is_go_to_armory, last_zone = m22_checkpoint_is_get_to_armory(checkpoint)
if (is_go_to_armory == true) then
Latest_zone_cleared = last_zone
Number_of_zones_cleared = 2
m22_setup_oleg_and_pierce()
m22_brute_enable(DISABLE) -- turn off notoriety brute spawning
m22_set_stag_synd_notoriety(4)
-- Create the courtesy vehicles
m22_create_player_courtesy_vehicle(Battle_Zone_Groups[Latest_zone_cleared].courtesy_vehicles)
teleport_coop(Battle_Zone_Groups[Latest_zone_cleared].player_starts[1], Battle_Zone_Groups[Latest_zone_cleared].player_starts[2], true)
-- Setup the courtesy vehicle
m22_setup_player_courtesy_vehicle(Battle_Zone_Groups[Latest_zone_cleared].courtesy_vehicles)
end
if (checkpoint == M22_checkpoints.ARMORY_FIGHT) then
Number_of_zones_cleared = 3
m22_setup_oleg_and_pierce()
Local_player_zone = ZONE_ACTIVE
Remote_player_zone = ZONE_ACTIVE
teleport_coop(Armory_battle_zone.player_starts[1], Armory_battle_zone.player_starts[2], true)
Armory_reached = true
m22_brute_enable(DISABLE) -- turn off notoriety brute spawning
end
if (checkpoint == M22_checkpoints.DEBUG_AIRPORT_CHOICE or checkpoint == M22_checkpoints.DEBUG_STATUE_CHOICE) then
-- NOTHING TO DO
end
if (checkpoint == M22_checkpoints.MAKE_YOUR_CHOICE) then
-- Spawn courtesy vehicle
m22_create_player_courtesy_vehicle(Armory_battle_zone.courtesy_vehicles)
teleport_coop(Armory_battle_zone.player_starts[1], Armory_battle_zone.player_starts[2], true)
end
if (checkpoint == M22_checkpoints.STOP_KILLBANE) then
group_create(M22_groups.Angel.name, true)
group_create(M22_groups.Angels_Attackers.name, true)
teleport_coop(M22_navpoints.player_angel_start[1], M22_navpoints.player_angel_start[2], true)
-- Play some music where we left off
audio_object_post_event(M22_audio_events.music_start_checkpoint, nil, nil, LOCAL_PLAYER)
end
if (checkpoint == M22_checkpoints.KILL_KILLBANE) then
m22_setup_kill_killbane()
end
if (checkpoint == M22_checkpoints.GOTO_SAINTS or checkpoint == M22_checkpoints.DEBUG_STATUE_CTE) then
-- Create the courtesy vehicles
m22_setup_statue_courtesy_boats()
teleport_coop(M22_navpoints.player_dock_start[1], M22_navpoints.player_dock_start[2])
-- Play some music where we left off
audio_object_post_event(M22_audio_events.music_start_checkpoint, nil, nil, LOCAL_PLAYER)
end
if (checkpoint == M22_checkpoints.SAVE_SAINTS) then
m22_setup_save_the_saints()
-- Give the player the sonic gun and farts in jars.
m22_give_temp_weapons_for_save_saints()
-- Equip the sonic gun.
m22_equip_temp_weapons_for_save_saints()
teleport_coop(M22_navpoints.statue_obs_deck, M22_navpoints.statue_obs_deck)
-- Play some music where we left off
audio_object_post_event(M22_audio_events.music_start_checkpoint, nil, nil, LOCAL_PLAYER)
end
if (checkpoint == M22_checkpoints.KILL_KIA) then
m22_setup_kill_kia()
-- Give the player the sonic gun and farts in jars.
m22_give_temp_weapons_for_save_saints()
teleport_coop(M22_navpoints.player_kia_fight_start[1] , M22_navpoints.player_kia_fight_start[2])
end
end
-- ***************************************************
-- Miscellaneous m22 Helper Funcrtions
-- ***************************************************
-- Create Oleg and Pierce and assigns them as homies
function m22_setup_oleg_and_pierce()
group_create(M22_groups.Oleg_and_Pierce.name, true)
party_add(M22_characters.Pierce, LOCAL_PLAYER)
if in_coop then
party_add(M22_characters.Oleg, REMOTE_PLAYER)
else
party_add(M22_characters.Oleg, LOCAL_PLAYER)
end
party_set_dismissable(false)
on_death("m22_oleg_died_cb", M22_characters.Oleg)
on_death("m22_pierce_died_cb", M22_characters.Pierce)
on_dismiss("m22_pierce_abandoned_cb", M22_characters.Pierce)
follower_set_can_abandon(M22_characters.Pierce, ENABLE)
end
-- Resets callbacks and disables a given trigger
--
-- trigger_name: (string) name of the trigger to clean up
--
function m22_cleanup_trigger(trigger_name)
on_trigger("", trigger_name)
on_trigger_exit("", trigger_name)
trigger_enable(trigger_name, false)
marker_remove_trigger(trigger_name)
end
-- Cleans up all triggers
--
function m22_cleanup_triggers(trigger_group)
for i, trigger in pairs(trigger_group) do
if (type(trigger) == "table") then
m22_cleanup_triggers(trigger)
else
m22_cleanup_trigger(trigger)
end
end
end
-- Cleans up all threads
--
function m22_cleanup_threads(thread_group)
for i, thread in pairs(thread_group) do
if (type(thread) == "table") then
m22_cleanup_threads(thread)
else
if thread ~= INVALID_THREAD_HANDLE then
thread_kill(thread)
thread = INVALID_THREAD_HANDLE
end
end
end
end
-- Resets the on_mover_destroyed callback for all movers
--
function m22_cleanup_movers(mover_group)
for i, mover in pairs(mover_group) do
if (type(mover) == "table") then
m22_cleanup_movers(mover)
else
on_mover_destroyed("", mover)
on_take_damage("", mover)
on_mover_enter_water("", mover)
end
end
end
-- Stops any active conversation and restores the handle to invalid
function m22_cleanup_conversations()
-- If we have a conversation thread active, kill it
if M22_threads.convo_handle ~= INVALID_THREAD_HANDLE then
if Active_conversation.convo_table ~= nil then
audio_conversation_end(Active_conversation.convo_table.handle)
Active_conversation.convo_table.handle = INVALID_CONVERSATION_HANDLE
Active_conversation.convo_table = nil
end
thread_kill(M22_threads.convo_handle)
M22_threads.convo_handle = INVALID_CONVERSATION_HANDLE
end
audio_remove_mission_cellphone(M22_cur_cell_call_name)
M22_cur_cell_call_name = ""
end
-- Unloads any 2d personas used in the mission
function m22_cleanup_personas()
for i, persona in pairs(M22_personas) do
if persona.persona_id ~= INVALID_PERSONA_HANDLE then
audio_persona_remove_2d(persona.persona_id)
persona.persona_id = INVALID_PERSONA_HANDLE
end
end
end
-- *************************
--
-- Callback functions
--
-- *************************
function m22_oleg_died_cb()
mission_end_failure("m22", "m22_failure_oleg_died")
end
function m22_pierce_died_cb()
mission_end_failure("m22", "m22_failure_pierce_died")
end
function m22_pierce_abandoned_cb()
mission_end_failure("m22", "m22_failure_pierce_abandoned")
end
-- On killed callback for all humanoids within a battle zone. Increments the player's kill count.
--
-- team: (string) Team that this particular humanoid belongs to
-- killer: (string) The name of the character/player that killed them
function m22_battle_zone_initial_died_cb(team, killer)
if (team == "Civilian") then
return
end
if (team == "Saints") then
return
end
if (killer == LOCAL_PLAYER or killer == REMOTE_PLAYER) then
if killer ~= nil then
if object_is_in_trigger(Current_bz.zone.trigger, killer) then
Current_bz.kills = Current_bz.kills + 1
m22_helper_update_battle_zone_hud()
end
end
end
end
-- Callback for a initial stag spawn within a battle zone. This function, will update kill credit and
-- spawn numbers, and then spawn reinforcements as necessary.
--
-- npc: (string) name of the npc who died
-- killer: (string) name of the character that killed them
function m22_battle_zone_stag_initial_died_cb(npc, killer)
-- MLG (07/06/11): We're running out of animation memory, so we need to be stricter with how we clean-up guys.
-- Don't release these NPCs into the world, since we're going to destroy their group before the next
-- battle location spawns
-- WillA (9/5/2011): We need to release some of these guys to free up NPC slots for notoriety, so we'll release the first
-- NUM_ZONE_ENEMIES_TO_RELEASE guys that die.
-- character is dead, release it if we need to
if Current_bz.num_enemies_released < NUM_ZONE_ENEMIES_TO_RELEASE then
Current_bz.num_enemies_released = Current_bz.num_enemies_released + 1
if not character_is_released(npc) then
release_to_world(npc)
thread_yield()
end
end
Current_bz.num_initial_stag_alive = Current_bz.num_initial_stag_alive - 1
-- Spawn the backup waves based on how many of the initial spawn remain.
if (Current_bz.num_initial_stag_alive <= 10) then
local level = 3
if (Number_of_zones_cleared == 2) then
level = 4
end
m22_set_stag_synd_notoriety(level)
notoriety_force_no_spawn("stag", false)
--notoriety_force_no_spawn("luchadores", false)
local stag_navpoint_name = Current_bz.zone.center_pos
--local luchadore_navpoint_name = Current_bz.zone.center_pos
notoriety_spawn_group_set_destination("stag", stag_navpoint_name)
--notoriety_spawn_group_set_destination("luchadores", luchadore_navpoint_name)
end
end
-- Callback for a initial synd spawn within a battle zone. This function, will update kill credit and
-- spawn numbers, and then spawn reinforcements as necessary.
--
-- npc: (string) name of the npc who died
-- killer: (string) name of the character that killed them
function m22_battle_zone_synd_initial_died_cb(npc, killer)
-- MLG (07/06/11): We're running out of animation memory, so we need to be stricter with how we clean-up guys.
-- Don't release these NPCs into the world, since we're going to destroy their group before the next
-- battle location spawns
-- WillA (9/5/2011): We need to release some of these guys to free up NPC slots for notoriety, so we'll release the first
-- NUM_ZONE_ENEMIES_TO_RELEASE guys that die.
-- character is dead, release it if we need to
if Current_bz.num_enemies_released < NUM_ZONE_ENEMIES_TO_RELEASE then
Current_bz.num_enemies_released = Current_bz.num_enemies_released + 1
if not character_is_released(npc) then
release_to_world(npc)
thread_yield()
end
end
Current_bz.num_initial_synd_alive = Current_bz.num_initial_synd_alive - 1
-- Spawn the backup waves based on how many of the initial spawn remain.
if (Current_bz.num_initial_synd_alive <= 10) then
local level = 3
if (Number_of_zones_cleared == 2) then
level = 4
end
m22_set_stag_synd_notoriety(level)
--notoriety_force_no_spawn("stag", false)
notoriety_force_no_spawn("luchadores", false)
--local stag_navpoint_name = Current_bz.zone.center_pos
local luchadore_navpoint_name = Current_bz.zone.center_pos
--notoriety_spawn_group_set_destination("stag", stag_navpoint_name)
notoriety_spawn_group_set_destination("luchadores", luchadore_navpoint_name)
end
end
-- On_trigger callback for battle zone triggers. Figures out which zone was triggered, associates the player
-- with that zone, spawns it if it hasn't already started, and then sets up the on_trigger_exit callback.
--
-- player: (string) name of the player who triggered the zone
-- trigger_name: (string) name of the trigger
--
function m22_zone_triggered_cb(player, trigger_name)
-- Find out which zone was triggered
local battle_zone = m22_helper_battle_zone_from_trigger(trigger_name)
-- We don't care if the battlezone is already cleared
if (battle_zone.cleared == true) then
return
end
-- If there's already a battle zone active, we only care if the player is entering that zone
if (Current_bz.zone ~= NO_ZONE and Current_bz.zone ~= battle_zone) then
return
end
-- Remove all the trigger markers
for i, battle_zone in pairs(Battle_Zone_Groups) do
marker_remove_trigger(battle_zone.trigger, SYNC_ALL)
end
-- Check to see if this is a new zone that needs to go active
if Current_bz.zone == NO_ZONE then
Current_bz.zone = battle_zone
-- Enable the battle area trigger
on_trigger("m22_battle_area_triggered_cb", Current_bz.zone.battle_area)
on_trigger_exit("m22_battle_area_exited_cb", Current_bz.zone.battle_area)
trigger_enable(Current_bz.zone.battle_area, true)
end
m22_set_players_zone(player)
local other_player_in_zone = m22_other_player_in_zone(player)
local hud_bar_size = Current_bz.zone.required_kills + Battle_zone_boss_hud_bar_factor * #Battle_Zone_Finales[Number_of_zones_cleared + 1]
if player == LOCAL_PLAYER then
objective_text_clear(0)
hud_bar_on(0, "Health", "m22_obj_clear_battlezone", hud_bar_size, SYNC_LOCAL, OI_ASSET_KILL)
-- Add the battle area radius, and a marker to the center of the battle area
minimap_icon_add_radius(Current_bz.zone.center_pos, trigger_get_radius(Current_bz.zone.battle_area), SYNC_LOCAL)
marker_add(Current_bz.zone.center_pos, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_LOCAL)
if m22_other_player_in_zone(player) ~= ZONE_ACTIVE then
-- remote player isnt in a zone
marker_add_trigger(trigger_name, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_REMOTE)
end
elseif player == REMOTE_PLAYER then
objective_text_clear(1)
hud_bar_on(1, "Health", "m22_obj_clear_battlezone", hud_bar_size, SYNC_REMOTE, OI_ASSET_KILL)
-- Add the battle area radius, and a marker to the center of the battle area
minimap_icon_add_radius(Current_bz.zone.center_pos, trigger_get_radius(Current_bz.zone.battle_area), SYNC_REMOTE)
marker_add(Current_bz.zone.center_pos, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_REMOTE)
if m22_other_player_in_zone(player) ~= ZONE_ACTIVE then
-- host player isnt in a zone
marker_add_trigger(trigger_name, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_LOCAL)
end
end
end
-- On_trigger_exit callback used for when a player exits a zone. Will shut down the battle zone if the player
-- is the last one to leave the zone
--
-- player: (string) name of the player who triggered the zone
-- trigger_name: (string) name of the trigger
--
function m22_zone_exited_cb(player, trigger_name)
local other_player_zone = m22_other_player_in_zone(player)
-- Don't care if there is no active zone
if (Current_bz.zone == NO_ZONE) then
return
end
--Check to see if the other player is still in the zone
if other_player_zone ~= ZONE_ACTIVE then
-- Kill the thread processing the battle zone
thread_kill(M22_threads.battle_zone_instance)
m22_cleanup_battle_zone_kill_enemies()
-- Destroy the guys we spawned
if (group_is_loaded(Current_bz.zone.initial_spawn.name) == true) then
group_destroy(Current_bz.zone.initial_spawn.name)
end
-- Release the courtesy vehicle to the world and destroy the group
if group_is_loaded(Current_bz.zone.courtesy_vehicles.name) then
release_to_world(Current_bz.zone.courtesy_vehicles.name)
group_destroy(Current_bz.zone.courtesy_vehicles.name)
end
m22_cleanup_battle_zone_saint_reinforcements()
else
-- We're in coop, and this player left the zone before their partner
if (Current_bz.zone.cleared == false) then
-- Was the zone cleared? If not, give them the icon to get back in to help their friend
marker_add_trigger(trigger_name, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, sync_from_player(player))
end
end
if LOCAL_PLAYER == player then
Local_player_zone = NO_ZONE
hud_bar_off(0)
objective_text( 0, "m22_obj_goto_battlezone", "", "", SYNC_LOCAL , OI_ASSET_LOCATION)
minimap_icon_remove_radius(Current_bz.zone.center_pos, SYNC_LOCAL)
marker_remove(Current_bz.zone.center_pos, SYNC_LOCAL)
else
Remote_player_zone = NO_ZONE
hud_bar_off(1)
objective_text( 1, "m22_obj_goto_battlezone", "", "", SYNC_REMOTE , OI_ASSET_LOCATION)
minimap_icon_remove_radius(Current_bz.zone.center_pos, SYNC_REMOTE)
marker_remove(Current_bz.zone.center_pos, SYNC_REMOTE)
end
end
-- Get a battle zone table from a trigger name (used for callbacks)
--
-- trigger_name: Name of the trigger
function m22_helper_battle_zone_from_trigger(trigger_name)
-- Find out which zone was triggered
for i, battle_zone in pairs(Battle_Zone_Groups) do
if (battle_zone.trigger == trigger_name or battle_zone.battle_area == trigger_name) then
return battle_zone
end
end
if (Armory_battle_zone.trigger == trigger_name or Armory_battle_zone.battle_area == trigger_name) then
return Armory_battle_zone
end
return NO_ZONE
end
-- Callback when the player enters the battle area for a batttle zone
function m22_battle_area_triggered_cb(player, trigger_name)
-- If a battle zone isn't active or this isn't the battle area for that zone, just return
local battle_zone = m22_helper_battle_zone_from_trigger(trigger_name)
if (Current_bz.zone == NO_ZONE or Current_bz.zone ~= battle_zone) then
return
end
-- Remove the marker leading the player to the battle area
if LOCAL_PLAYER == player then
marker_remove(battle_zone.center_pos, SYNC_LOCAL)
else
marker_remove(battle_zone.center_pos, SYNC_REMOTE)
end
end
-- Callback when the players leaves the battle area for a battle zone
function m22_battle_area_exited_cb(player, trigger_name)
-- If a battle zone isn't active or this isn't the battle area for that zone, just return
local battle_zone = m22_helper_battle_zone_from_trigger(trigger_name)
if (Current_bz.zone == NO_ZONE or Current_bz.zone ~= battle_zone) then
return
end
-- Add the marker leading the player to the battle area
if LOCAL_PLAYER == player then
marker_add(battle_zone.center_pos, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_LOCAL)
else
marker_add(battle_zone.center_pos, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_REMOTE)
end
end
-- On_trigger callback used to determine when a player reaches the armory
--
-- player: (string) name of the player that entered the trigger
-- trigger_name: (string) name of the trigger entered
--
function m22_armory_reached_cb(player, trigger_name)
m22_set_players_zone(LOCAL_PLAYER)
if (coop_is_active() == true) then
m22_set_players_zone(REMOTE_PLAYER)
end
Armory_reached = true
mission_waypoint_remove()
m22_cleanup_trigger(trigger_name)
end
-- On_trigger callback used to determine which area the player went to
--
-- player: (string) name of the player that entered the trigger
-- trigger_name: (string) name of the trigger entered
--
function m22_player_choice_cb(player, trigger_name)
if trigger_name == M22_triggers.kill_killbane then
Player_choice = "killbane"
elseif trigger_name == M22_triggers.save_saints then
Player_choice = "shaundi"
end
-- Cleanup the triggers
m22_cleanup_trigger(M22_triggers.kill_killbane_perimeter)
m22_cleanup_trigger(M22_triggers.save_saints_perimeter)
m22_cleanup_trigger(M22_triggers.kill_killbane)
m22_cleanup_trigger(M22_triggers.save_saints)
end
-- On_vehicle_enter callback used to determine when a player has entered a vehicle capable of reaching the statue
function m22_player_entered_vehicle_cb(player, vehicle_name)
local veh_type = get_vehicle_type(vehicle_name)
if (veh_type == VT_AIRPLANE or veh_type == VT_HELICOPTER or veh_type == VT_VTOL or veh_type == VT_WATERCRAFT) then
marker_remove(M22_navpoints.statue_boat_loc)
marker_add_trigger(M22_triggers.save_saints, MINIMAP_ICON_PROTECT_ACQUIRE, INGAME_EFFECT_CHECKPOINT, OI_ASSET_DEFEND, OI_FLAGS_LOCATION, SYNC_ALL)
end
end
-- On_projectile_hit callback that is used to monitor Killbanes plane for RPG hits
--
-- object_hit_type: (string) type of object that was hit by a projectile
-- object_hit_name: (string) name of the object that was hit
-- weapon: (string) name of the weapon type from which the projectile originated
--
function m22_projectile_hit_cb(object_hit_type, object_hit_name, weapon)
if object_hit_type == "vehicle" and object_hit_name == M22_vehicles.Killbanes_Plane then
Num_plane_hits = Num_plane_hits + 1
if Num_plane_hits == NUM_HITS_TO_STOP_PLANE then
on_projectile_hit("")
-- Clean up the pathing threads
thread_kill(M22_threads.killbane_path_handle)
thread_kill(M22_threads.player_path_handle)
thread_kill(M22_threads.player_car_speed_handle)
M22_threads.killbane_path_handle = INVALID_THREAD_HANDLE
M22_threads.player_path_handle = INVALID_THREAD_HANDLE
M22_threads.player_car_speed_handle = INVALID_THREAD_HANDLE
-- Destroy the Airplane
turn_vulnerable(M22_vehicles.Killbanes_Plane)
vehicle_detonate(M22_vehicles.Killbanes_Plane)
marker_remove(M22_vehicles.Killbanes_Plane)
vehicle_stop(M22_vehicles.Angels_Car)
else
-- Reduce the HP of the plan
local max = get_max_hit_points(M22_vehicles.Killbanes_Plane)
set_current_hit_points(M22_vehicles.Killbanes_Plane, max * ((NUM_HITS_TO_STOP_PLANE - Num_plane_hits) / NUM_HITS_TO_STOP_PLANE))
end
end
end
-- On_trigger callback that spawns and moves the first roadblock of the Killbane chase sequence
--
-- player: (string) name of the player that triggered the trigger
-- trigger_name: (string) name of the trigger
--
function m22_spawn_first_roadblock_cb(player, trigger_name)
m22_cleanup_trigger(trigger_name)
m22_spawn_and_move_roadblock(M22_groups.Airport_Roadblock_one, M22_navpoints.roadblock_one_move_tos)
end
-- On_trigger callback that spawns and moves the second roadblock of the Killbane chase sequence
--
-- player: (string) name of the player that triggered the trigger
-- trigger_name: (string) name of the trigger
--
function m22_spawn_second_roadblock_cb(player, trigger_name)
m22_cleanup_trigger(trigger_name)
M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.angel_shoot_plane, 5.0)
m22_spawn_and_move_roadblock(M22_groups.Airport_Roadblock_two, M22_navpoints.roadblock_two_move_tos)
end
-- On_trigger callback that spawns and moves the third roadblock of the Killbane chase sequence
--
-- player: (string) name of the player that triggered the trigger
-- trigger_name: (string) name of the trigger
--
function m22_spawn_third_roadblock_cb(player, trigger_name)
group_destroy(M22_groups.Airport_Roadblock_one) -- cleanup the first roadblock
m22_cleanup_trigger(trigger_name)
m22_spawn_and_move_roadblock(M22_groups.Airport_Roadblock_three, M22_navpoints.roadblock_three_move_tos)
end
-- On_trigger callback that spawns and moves the third roadblock of the Killbane chase sequence
--
-- player: (string) name of the player that triggered the trigger
-- trigger_name: (string) name of the trigger
--
function m22_spawn_fourth_roadblock_cb(player, trigger_name)
group_destroy(M22_groups.Airport_Roadblock_two) -- cleanup the second roadblock
m22_cleanup_trigger(trigger_name)
m22_spawn_and_move_roadblock(M22_groups.Airport_Roadblock_four, M22_navpoints.roadblock_four_move_tos)
end
-- On_mover_destroyed callback used to keep track of the C4
--
-- mover_name: (string) name of the script mover
-- attacker: (string) name of the character that destroyed the mover
--
function m22_c4_destroyed_cb(mover_name, attacker)
on_take_damage("", mover_name)
on_mover_destroyed("", mover_name)
on_mover_enter_water("", mover_name)
if object_is_in_trigger(M22_triggers.statue_explosion_region, mover_name) then
-- Bomb blew up on the statue.
character_kill(LOCAL_PLAYER)
if in_coop then
character_kill(REMOTE_PLAYER)
end
mission_end_failure("m22", "m22_failure_statue_blown_up")
for i, mover in pairs(M22_movers.c4) do
mesh_mover_kill (mover, LOCAL_PLAYER)
end
else
Num_c4_left_to_destroy = Num_c4_left_to_destroy - 1
marker_remove(mover_name)
objective_text( 0, "m22_obj_remove_bombs", Total_c4_to_destroy - Num_c4_left_to_destroy, Total_c4_to_destroy .. " ", SYNC_ALL, OI_ASSET_USE )
end
end
-- On_mover_destroyed callback used to keep track of the C4 on the first floor
--
-- mover_name: (string) name of the script mover
-- attacker: (string) name of the character that destroyed the mover
--
function m22_c41_destroyed_cb(mover_name, attacker)
on_take_damage("", mover_name)
on_mover_destroyed("", mover_name)
on_mover_enter_water("", mover_name)
if object_is_in_trigger(M22_triggers.statue_explosion_region, mover_name) then
-- Bomb blew up on the statue.
character_kill(LOCAL_PLAYER)
if in_coop then
character_kill(REMOTE_PLAYER)
end
mission_end_failure("m22", "m22_failure_statue_blown_up")
for i, mover in pairs(M22_movers.c4) do
mesh_mover_kill (mover, LOCAL_PLAYER)
end
else
Num_c4_left_to_destroy = Num_c4_left_to_destroy - 1
Num_c4_left_first_floor = Num_c4_left_first_floor - 1
marker_remove(mover_name)
objective_text( 0, "m22_obj_remove_bombs", Total_c4_to_destroy - Num_c4_left_to_destroy, Total_c4_to_destroy .. " ", SYNC_ALL, OI_ASSET_USE )
end
end
-- Callback for when a C4 mover is damaged
--
-- mover_name: (string) name of the script mover
-- attacker: (string) name of the character that damaged the mover
-- hitpoint_pct: (float) percent of hitpoints remaining
-- from_exp: (bool) true if the mover was damaged from an explosion
-- from_melee: (bool) true if the mover was damaged from melee
-- from_sonic: (bool) true if the mover was damaged from a sonic gun
--
function m22_c4_damaged_cb(mover_name, attacker, hitpoint_pct, from_exp, from_melee, from_sonic)
if (from_sonic == false) then
if (object_is_in_trigger(M22_triggers.statue_explosion_region, mover_name) == false) then
on_take_damage("", mover_name)
thread_yield()
mesh_mover_kill(mover_name, LOCAL_PLAYER)
end
end
end
-- on_mover_enter_water callback used to keep track of the C4
--
-- mover_name: (string) name of the script mover
--
function m22_c41_entered_water_cb(mover_name)
Num_c4_left_to_destroy = Num_c4_left_to_destroy - 1
Num_c4_left_first_floor = Num_c4_left_first_floor - 1
marker_remove(mover_name)
on_mover_enter_water("", mover_name)
on_mover_destroyed("", mover_name)
on_take_damage("", mover_name)
mesh_mover_kill(mover_name, LOCAL_PLAYER)
objective_text_clear(0)
objective_text( 0, "m22_obj_remove_bombs", Total_c4_to_destroy - Num_c4_left_to_destroy, Total_c4_to_destroy .. " ", SYNC_ALL, OI_ASSET_USE )
end
-- on_mover_enter_water callback used to keep track of the C4 on the first floor
--
-- mover_name: (string) name of the script mover
--
function m22_c4_entered_water_cb(mover_name)
Num_c4_left_to_destroy = Num_c4_left_to_destroy - 1
marker_remove(mover_name)
on_mover_enter_water("", mover_name)
on_mover_destroyed("", mover_name)
on_take_damage("", mover_name)
mesh_mover_kill(mover_name, LOCAL_PLAYER)
objective_text_clear(0)
objective_text( 0, "m22_obj_remove_bombs", Total_c4_to_destroy - Num_c4_left_to_destroy, Total_c4_to_destroy .. " ", SYNC_ALL, OI_ASSET_USE )
end
-- on_trigger_exit callback used to kill humans leaving the statue
function m22_human_left_statue_cb(character_name, trigger_name)
--if character_name ~= LOCAL_PLAYER and character_name ~= REMOTE_PLAYER then
if character_name ~= nil then
character_ragdoll(character_name)
character_kill(character_name, true)
end
--end
end
-- Callback for when the player takes the elevator up the statue
--
-- char_name: (string) name of the player that triggered the trigger
-- trigger_name: (string) name of the trigger
--
function m22_player_used_elevator_cb(char_name, trigger_name)
Player_used_elevator = true
m22_cleanup_trigger(trigger_name)
end
-- Callback for when the player reaches the breadcrumb
--
-- char_name: (string) name of the player that triggered the trigger
-- trigger_name: (string) name of the trigger
--
function m22_player_reached_breadcrumb_cb(char_name, trigger_name)
Player_reached_breadcrumb = true
m22_cleanup_trigger(trigger_name)
end
-- Callback for when the player reaches the top of the statue
--
-- char_name: (string) name of the player that triggered the trigger
-- trigger_name: (string) name of the trigger
--
function m22_player_reached_top_cb(char_name, trigger_name)
Player_reached_top = true
m22_cleanup_trigger(trigger_name)
end
-- Callback for when the player unties a saint
--
-- char_name: (string) name of the player that triggered the trigger
-- trigger_name: (string) name of the trigger
--
function m22_saint_untied_cb(char_name, trigger_name)
m22_cleanup_trigger(trigger_name)
for i, trigger in pairs(M22_triggers.untie) do
if trigger == trigger_name then
set_script_animation_state(M22_groups.Statue.saints[i], nil)
action_play_synced(char_name, M22_groups.Statue.saints[i], "Hostage Release")
turn_vulnerable(M22_groups.Statue.saints[i])
-- Clear their hostage state
if (character_is_dead(M22_groups.Statue.saints[i]) == false) then
set_ignore_ai_flag(M22_groups.Statue.saints[i], false)
set_dont_attack_me_on_sight_flag(M22_groups.Statue.saints[i], false)
character_allow_ragdoll(M22_groups.Statue.saints[i], ENABLE)
character_prevent_flinching(M22_groups.Statue.saints[i], DISABLE)
character_prevent_bumping(M22_groups.Statue.saints[i], DISABLE)
party_add(M22_groups.Statue.saints[i])
end
break
end
end
end
-- Callback called when a tied up saint is killed. Cleans up trigger and character callbacks.
--
-- char_name: (string) name of the saint that died
-- attacker_name: (string) name of the person that killed the saint or nil
--
function m22_saint_died_cb(char_name, attacker_name)
on_death("", char_name)
for i, saint in pairs(M22_groups.Statue.saints) do
if saint == char_name then
m22_cleanup_trigger(M22_triggers.untie[i])
break
end
end
end
-- Callback called when the player runs out of time during the statue sequence.
function m22_statue_times_up_cb()
-- Bomb blew up on the statue.
character_kill(LOCAL_PLAYER)
if in_coop then
character_kill(REMOTE_PLAYER)
end
mission_end_failure("m22", "m22_failure_statue_blown_up")
end
-- Callback for when Kia is damaged
function m22_kia_damaged_cb(victim, attacker, hitpoints, from_explosion, from_melee, causes_vomit)
-- Only care about the damage if it should cause her to vomit
if (causes_vomit == true) then
-- If we're not already processing a vomit, then kick off a new thread
if (thread_check_done(M22_threads.kia_vomit_handle) == true) then
M22_threads.kia_vomit_handle = thread_new("m22_kia_process_vomit_thread")
end
end
end
-- Callback when the Mayor Burt is damaged
function m22_burt_damaged_cb(victim, attacker, hitpoints, from_explosion, from_melee, causes_vomit)
if (M22_burt_can_play_damage_line == true) then
-- Play a situational line
if (causes_vomit == true) then
audio_play_persona_line(M22_characters.Mayor, M22_dialog_lines.burt_fiaj[rand_int(1, #M22_dialog_lines.burt_fiaj)])
else
audio_play_persona_line(M22_characters.Mayor, M22_dialog_lines.burt_damaged[rand_int(1, #M22_dialog_lines.burt_damaged)])
end
M22_burt_can_play_damage_line = false
delay(5.0)
M22_burt_can_play_damage_line = true
end
end
-- Callback when Shaundi is killed
function m22_shaundi_killed_cb()
mission_end_failure("m22", "m22_failure_shaundi_died")
end
-- Callback for when a player enters a trigger to get Fart in a Jar ammo
--
-- triggerer: Name of the player that entered the trigger region
-- trigger: Name of the trigger region that was entered
function m22_give_fart_in_jar_ammo_cb(triggerer, trigger)
-- Figure out which trigger volume was triggered
for i, fart_jar_trigger in pairs(M22_triggers.fart_jars) do
if (fart_jar_trigger == trigger) then
-- Disable the trigger, and hide the item
trigger_enable(trigger, false)
item_hide(M22_groups.Kia_battle_props.fart_jars[i])
marker_remove_trigger(trigger, SYNC_ALL)
-- Give them a FIAJ
if (inv_item_get_weapon_upgrades(KIA_TEMPORARY_GRENADE, triggerer) ~= WEAPON_LEVEL4) then
-- If the player doesn't already have the FIAJ flashbang upgrade then give it to them
inv_weapon_add_temporary(triggerer, KIA_TEMPORARY_GRENADE, 0, false, false, false, true, WEAPON_LEVEL4)
else
-- Otherwise just give them some ammo
inv_item_add_ammo(triggerer, KIA_TEMPORARY_GRENADE, 1)
end
Player_got_fiaj = true
-- Delay until the respawn time has elapsed
delay(FART_IN_JAR_RESPAWN_TIME)
-- Re-enable the trigger, and show the item
trigger_enable(trigger, true)
item_show(M22_groups.Kia_battle_props.fart_jars[i])
marker_add_trigger(trigger, MINIMAP_ICON_USE, nil, OI_ASSET_USE, OI_FLAGS_DEFAULT, SYNC_ALL)
break
end
end
end
-- Callback for when a battle zone boss dies
--
-- group_name: Name of the continuous spawn group that was killed
function m22_bz_boss_killed_cb(group_name)
Current_bz.bosses_killed = Current_bz.bosses_killed + 1
m22_helper_update_battle_zone_hud()
end
-- Callback for when the player reaches the first floor breadcrumb on the statue
--
-- char_name: (string) name of the player that triggered the trigger
-- trigger_name: (string) name of the trigger
function m22_first_floor_cb(char_name, trigger_name)
m22_cleanup_trigger(trigger_name)
-- Set up trigger for the second floor
on_trigger("m22_second_floor_cb", M22_triggers.Second_Floor)
trigger_enable(M22_triggers.Second_Floor, true)
marker_add_trigger(M22_triggers.Second_Floor, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
end
-- Callback for when the player reaches the second floor breadcrumb on the statue
--
-- char_name: (string) name of the player that triggered the trigger
-- trigger_name: (string) name of the trigger
function m22_second_floor_cb(char_name, trigger_name)
Second_floor_reached = true
m22_cleanup_trigger(trigger_name)
for i, mover in pairs(M22_movers.c4) do
if not (mesh_mover_destroyed(mover))then
marker_add(mover, MINIMAP_ICON_USE, OI_ASSET_USE, OI_FLAGS_DEFAULT, SYNC_ALL)
end
end
end
-- *************************
--
-- Thread functions
--
-- *************************
-- Failsafe thread that will re-enable notoriety after a certain amount of
-- time during the "kill some dudes" section of a battle zone.
--
function m22_thread_notoriety_failsafe()
delay(NOTORIETY_FAILSAFE_TIME)
local level = 3
if (Number_of_zones_cleared == 2) then
level = 4
end
m22_set_stag_synd_notoriety(level)
notoriety_force_no_spawn("stag", false)
notoriety_force_no_spawn("luchadores", false)
--notoriety_spawn_group_clear_destination("stag")
--notoriety_spawn_group_clear_destination("luchadores")
end
function m22_thread_neareast_battlezone_gps()
while true do
m22_gps_path_to_nearest_battle()
delay(1.0)
end
end
function m22_helper_play_conversation(conversation_table, delay_time)
if Active_conversation.convo_table ~= nil then
-- currently playing a conversation, kill it
audio_conversation_end(Active_conversation.convo_table.handle)
Active_conversation.convo_table.handle = INVALID_CONVERSATION_HANDLE
Active_conversation.convo_table = nil
end
-- Load the conversation
if conversation_table.direct then
conversation_table.handle = audio_conversation_load_direct(conversation_table.name)
else
conversation_table.handle = audio_conversation_load(conversation_table.name)
end
Active_conversation.convo_table = conversation_table
delay(delay_time)
-- Wait for anything else that was using the failsafe thread handle to finish.
while M22_threads.audio_failsafe ~= INVALID_THREAD_HANDLE do
thread_yield()
end
M22_threads.audio_failsafe = thread_new("delay", 120.0)
conversation_table.played = true
-- Play the conversation and wait for it to end or for the maximum wait time to elapse.
audio_conversation_play(conversation_table.handle)
while audio_conversation_playing(conversation_table.handle) and thread_check_done(M22_threads.audio_failsafe) == false do
thread_yield()
end
audio_conversation_end(conversation_table.handle)
thread_kill(M22_threads.audio_failsafe)
M22_threads.audio_failsafe = INVALID_THREAD_HANDLE
conversation_table.handle = INVALID_CONVERSATION_HANDLE
Active_conversation.convo_table = nil
M22_threads.convo_handle = INVALID_THREAD_HANDLE
end
-- Thread function responsible for controling Killbanes plane
function m22_airport_killbane_path_thread()
-- Stop notoriety spawning during the take off sequence.
notoriety_force_no_spawn("stag", true)
notoriety_force_no_spawn("luchadores", true)
delay(10)
vehicle_max_speed(M22_vehicles.Killbanes_Plane, 35) -- AC: Previously 20 turned it up to 30
vehicle_pathfind_to(M22_vehicles.Killbanes_Plane, Airport_Killbane_Path1, true, false)
vehicle_max_speed(M22_vehicles.Killbanes_Plane, 45)
vehicle_pathfind_to(M22_vehicles.Killbanes_Plane, Airport_Killbane_Path2, true, false)
vehicle_max_speed(M22_vehicles.Killbanes_Plane, 45)
vehicle_pathfind_to(M22_vehicles.Killbanes_Plane, Airport_Killbane_Path3, true, false)
vehicle_max_speed(M22_vehicles.Killbanes_Plane, 30)
vehicle_pathfind_to(M22_vehicles.Killbanes_Plane, Airport_Killbane_Path4, true, false)
--vehicle_max_speed(M22_vehicles.Killbanes_Plane, 35)
vehicle_max_speed(M22_vehicles.Killbanes_Plane, 55)
vehicle_pathfind_to(M22_vehicles.Killbanes_Plane, Airport_Killbane_Path5, true, false)
--airplane_takeoff(M22_vehicles.Killbanes_Plane)
mission_end_failure("m22", "m22_failure_killbane_escaped")
end
-- Thread function responsible for controling Angels car
function m22_angel_car_path_thread()
for i, segment_name in pairs(Airport_player_path) do
vehicle_pathfind_to(M22_vehicles.Angels_Car, segment_name, true, false)
end
mission_end_failure("m22", "m22_failure_killbane_escaped")
end
-- Thread function that will drive to a specific spot, used for roadblocks in the airplane chase sequence
--
-- driver_name: (string) name of the driver
-- car_name: (string) name of the car
-- nav_point_name: (string) name of the destination navpoint
-- thread_index: (int) index into M22_threads.roadblock_drive_to_handles, to clean up when this thread ends
--
function m22_roadblock_drive_to_thread(driver_name, car_name, nav_point_name, thread_index)
vehicle_max_speed(car_name, 65) -- AC: Test
vehicle_pathfind_to(car_name, nav_point_name, true, true)
vehicle_exit_group( { driver_name } )
-- Get the drivers to attack the player
npc_combat_enable(driver_name, true)
ai_add_enemy_target(driver_name, M22_groups.Angel.members[1], ATTACK_NOW, true)
M22_threads.roadblock_driveto_handles[thread_index] = INVALID_THREAD_HANDLE
end
-- Thread to process one of the attack VTOLs as it circles around the statue
--
-- vtol_table: Lua table defining the VTOL objects
function m22_process_kia_vtol_circling(vtol_table)
vehicle_max_speed(vtol_table.vtol, vtol_table.loop_speed)
helicopter_set_path_orientation(vtol_table.vtol, HELI_PF_PATH_PITCH)
helicopter_fly_to_direct_dont_stop(vtol_table.vtol, vtol_table.loop_speed, vtol_table.path_intro)
while(vehicle_is_destroyed(vtol_table.vtol) == false) do
-- MLG: This would have been nice, but the minimum follow distance is 20m, which is way to far to keep these VTOLs in formation
--[[
-- Find a potential follow target
local follow_target = nil
for i, vtol in pairs(M22_groups.Kia_Vtol1.vtols) do
if (vtol == vtol_table) then
-- We didn't find any VTOLs in front of us in the list, so break without a VTOL follow target
break
elseif (thread_check_done(vtol.thread_id) == false) then
-- The VTOL still has a looping thread, so it hasn't broken off yet. Follow this guy
follow_target = vtol.vtol
break
end
end
--]]
--[[
if (follow_target ~= nil) then
helicopter_fly_to_follow_dont_stop(vtol_table.vtol, 150.0, follow_target, vtol_table.path_looping, 20.0, false)
else
--]]
helicopter_fly_to_direct_dont_stop(vtol_table.vtol, vtol_table.loop_speed, vtol_table.path_looping)
--[[
end
--]]
thread_yield()
end
end
-- Thread to process the attack VTOLs that circle the status and attack the player during the Kia Boss Battle
function m22_process_kia_vtols_thread()
-- Loop forever
while (true) do
-- Create the script group for the VTOLs
group_create_hidden(M22_groups.Kia_Vtol1.name, true)
group_show(M22_groups.Kia_Vtol1.name)
-- Setup each VTOL in the group, and set them on the intor paths
for i, vtol in pairs(M22_groups.Kia_Vtol1.vtols) do
vehicle_enter_group_teleport(vtol.members, vtol.vtol)
vehicle_suppress_npc_exit(vtol.vtol)
vtol.thread_id = thread_new("m22_process_kia_vtol_circling", vtol)
end
-- Start a loop to break one VTOL off at a time and attack the player
while(true) do
-- Find the first VTOL that is still alive (search this last backwards, since we want to break of the following plane's first)
local attack_vtol_table = nil
for i=(#M22_groups.Kia_Vtol1.vtols), 1, -1 do
if (vehicle_is_destroyed(M22_groups.Kia_Vtol1.vtols[i].vtol) == false) then
attack_vtol_table = M22_groups.Kia_Vtol1.vtols[i]
break
end
end
-- If we didn't find an attack VTOL, they must all have died, break out of this loop so we can create another wave
if (attack_vtol_table == nil) then
break
end
-- Kill the circling path thread
thread_kill(attack_vtol_table.thread_id)
-- Wait until the attack VTOL has finished the current loop it's on
while(vehicle_pathfind_check_done(attack_vtol_table.vtol) == 0) do
thread_yield()
end
-- Fly the break-off path
helicopter_fly_to_direct(attack_vtol_table.vtol, -1, M22_groups.Kia_Vtol1.path_break_off)
-- Process this VTOL attacking until it dies
Kia_boss_ai.attack_vtol_side = "east"
local attack_navs = M22_navpoints.kia_vtol_east_attack
while(vehicle_is_destroyed(attack_vtol_table.vtol) == false) do
-- Move the VTOL to the idle attack position, and wait
helicopter_set_path_orientation(attack_vtol_table.vtol, HELI_PF_FACE_TARGET, LOCAL_PLAYER)
helicopter_fly_to_direct(attack_vtol_table.vtol, -1, attack_navs[1])
delay(KIA_ATTACK_VTOL_IDLE_TIME)
-- Start the attack, and move down to the attack navpoint
Kia_boss_ai.attack_vtol_attacking = true
delay(1.0) -- sneak a little delay in here, so Kia has time to get into cover
helicopter_fly_to_direct(attack_vtol_table.vtol, -1, attack_navs[2])
-- Fire on the player
set_ignore_ai_flag(attack_vtol_table.members[1], true) -- ignore AI so we don't fire while at the idle location
delay(KIA_ATTACK_VTOL_PRE_ATTACK_TIME)
set_ignore_ai_flag(attack_vtol_table.members[1], false) -- turn AI back on
helicopter_shoot_human(attack_vtol_table.vtol, LOCAL_PLAYER)
delay(KIA_ATTACK_VTOL_POST_ATTACK_TIME)
-- Stop attacking
Kia_boss_ai.attack_vtol_attacking = false
-- Select a random side to attack from next
local prev_attack_side = Kia_boss_ai.attack_vtol_side
if (rand_int(1, 2) == 1) then
Kia_boss_ai.attack_vtol_side = "east"
attack_navs = M22_navpoints.kia_vtol_east_attack
else
Kia_boss_ai.attack_vtol_side = "west"
attack_navs = M22_navpoints.kia_vtol_west_attack
end
-- Check if we're switching sides
if (Kia_boss_ai.attack_vtol_side ~= prev_attack_side) then
-- Switching sides, so do a transition pathfind depending on which side we're going to
helicopter_set_path_orientation(attack_vtol_table.vtol, HELI_PF_PATH_PITCH)
if (Kia_boss_ai.attack_vtol_side == "east") then
helicopter_fly_to_direct(attack_vtol_table.vtol, -1, M22_groups.Kia_Vtol1.path_west_east)
else
helicopter_fly_to_direct(attack_vtol_table.vtol, -1, M22_groups.Kia_Vtol1.path_east_west)
end
end
end
end
-- Release the now dead group to the world and destroy the group, so we can recreate them
release_to_world(M22_groups.Kia_Vtol1.name)
group_destroy(M22_groups.Kia_Vtol1.name)
delay(KIA_ATTACK_VTOL_RESAPWN_TIME)
end
end
-- Thread to process Kia's AI during the boss battle
function m22_kia_boss_ai_thread()
-- Make Kia grab Shaundi
character_take_human_shield(M22_characters.Kia, M22_characters.Shaundi, true) -- bypass AI to take the human shield immediately
npc_leash_remove(M22_characters.Kia)
-- Register both players as enemy targets
ai_add_enemy_target(M22_characters.Kia, LOCAL_PLAYER, ATTACK_NOW_NEVER_LOSE)
if (coop_is_active() == true) then
ai_add_enemy_target(M22_characters.Kia, REMOTE_PLAYER, ATTACK_NOW_NEVER_LOSE)
end
-- Do per-frame AI processing until Kia has died
while(character_is_dead(M22_characters.Kia) == false) do
-- Evaluate if Kia should move to a new position
m22_kia_boss_ai_evaluate_move()
thread_yield()
end
end
function m22_kia_boss_ai_evaluate_move()
-- Don't process move to AI if Kia is vomiting
if (thread_check_done(M22_threads.kia_vomit_handle) == false) then
return
end
-- Don't process move to AI if Kia doesn't have Shaundi as a human shield
if (character_has_human_shield(M22_characters.Kia) == false) then
return
end
if (Kia_boss_ai.attack_vtol_attacking == true) then
-- Attack VTOL is about to attack, take cover
m22_kia_do_take_cover_from_vtol()
else
-- No immediate thread, so just try and keep away from the player(s)
m22_kia_do_move_away_from_player()
end
end
-- Per frame processing for Kia to try and take cover from an attack VTOL
function m22_kia_do_take_cover_from_vtol()
-- Figure out which group of cover nodes to search through, based on which side the VTOL is attacking from
local search_navs = nil
if (Kia_boss_ai.attack_vtol_side == "east") then
-- VTOL is attacking from the east, so look for cover on the west
search_navs = M22_navpoints.kia_defence_west_navs
else
-- VTOL is attacking from the west, so look for cover on the east
search_navs = M22_navpoints.kia_defence_east_navs
end
-- Find the closest cover navpoint
local closest_nav_dist = 100000 -- big number
local closest_nav = nil
for i, nav in pairs(search_navs) do
local distance = get_dist(nav, M22_characters.Kia)
if (distance < closest_nav_dist) then
-- We have a new closest navpoint
closest_nav = nav
closest_nav_dist = distance
end
end
-- If this navpoint is different than Kia's current navpoint, then move there
if (closest_nav ~= Kia_boss_ai.current_navpoint) then
npc_leash_remove(M22_characters.Kia)
npc_leash_to_object(M22_characters.Kia, closest_nav, KIA_DEFENSIVE_POSITION_LEASH_RADIUS)
Kia_boss_ai.current_navpoint = closest_nav
end
end
-- Per frame processing for Kia to try and maintain a safe distance from the player
function m22_kia_do_move_away_from_player()
local dist_to_player, closest_player = get_dist_closest_player_to_object(M22_characters.Kia)
if (dist_to_player <= KIA_DESIRED_PLAYER_KEEP_DISTANCE) then
-- We're too close to a player, see if we should consider a new attack position
-- First, check to see if our destination position is too close to a player
if (Kia_boss_ai.current_navpoint ~= nil) then
local dest_dist_to_player, dest_closest_player = get_dist_closest_player_to_object(Kia_boss_ai.current_navpoint)
if (dest_dist_to_player >= KIA_DESIRED_PLAYER_KEEP_DISTANCE) then
-- Our current destination is far enough away, just stay the course
return
end
end
-- See if any of the other navpoints are a better pick
local best_nav = nil
local closest_nav_dist = 100000 -- big number
local furthest_from_player_dist = 0
local furthest_from_player_nav = nil
for i, nav in pairs(M22_navpoints.kia_attack_navs) do
local nav_dist_to_player = get_dist_closest_player_to_object(nav)
local dist_to_nav = get_dist(M22_characters.Kia, nav)
if (nav_dist_to_player > KIA_DESIRED_PLAYER_KEEP_DISTANCE) then
-- If the nav is outside of the desired keep distance, compare how close it is to other navs outside of the keep distance
if (dist_to_nav < closest_nav_dist) then
best_nav = nav
closest_nav_dist = dist_to_nav
end
else
-- Track the furthest navpoint away from the player that falls within the keep distance
if (nav_dist_to_player > furthest_from_player_dist) then
furthest_from_player_nav = nav
furthest_from_player_dist = nav_dist_to_player
end
end
end
-- If there was no suitable navpoint outside of the keep radius, then check if we should consider the furthest navpoint inside the keep radius
if (best_nav == nil and furthest_from_player_nav ~= nil) then
-- Is this at least 10% further away from the closest player?
if (furthest_from_player_dist > (dist_to_player * 1.1)) then
best_nav = furthest_from_player_nav
end
end
-- If there's a better navpoint, then move there
if (best_nav ~= nil) then
npc_leash_remove(M22_characters.Kia)
npc_leash_to_object(M22_characters.Kia, best_nav, KIA_ATTACK_POSITION_LEASH_RADIUS)
Kia_boss_ai.current_navpoint = best_nav
end
end
end
-- Thread to process character's custom FIAJ reaction for Mission22
--
-- character_name: Name of the character
-- loop: TRUE if the FIAJ should loop indefinitely, FALSE if it should play only once
function m22_do_character_fiaj_thread(character_name, loop)
repeat
-- Pick a random fiaj reaction
local fiaj_reaction = M22_anims.fiaj_reactions[rand_int(1, #M22_anims.fiaj_reactions)]
-- Play the FIAJ reaction animations
action_play(character_name, fiaj_reaction.intro)
action_play(character_name, fiaj_reaction.outro)
until (loop == false)
end
-- Process Kia vomitting
function m22_kia_process_vomit_thread()
-- Release Shaundi
--[[
character_release_human_shield(M22_characters.Kia)
while(character_has_human_shield(M22_characters.Kia) == true) do
thread_yield()
end
--]]
-- Apply the vomiting damage multiplier to Kia, and disable AI (so she won't attack the player between vomits - it looks bad)
character_set_damage_multiplier(M22_characters.Kia, KIA_DAMAGE_MULTIPLIER_VOMITING)
set_ignore_ai_flag(M22_characters.Kia, true)
set_ignore_ai_flag(M22_characters.Shaundi, true)
action_play_synced(M22_characters.Kia, M22_characters.Shaundi, KIA_FIAJ_REACTION_SYNCED_ANIM)
--[[
local shaundi_reaction_thread = thread_new("m22_do_character_fiaj_thread", M22_characters.Shaundi, true)
m22_do_character_fiaj_thread(M22_characters.Kia, false)
--]]
-- Apply the normal damage multiplyer on Kia, and re-enable AI processing
character_set_damage_multiplier(M22_characters.Kia, KIA_DAMAGE_MULTIPLIER_HUMAN_SHIELD)
set_ignore_ai_flag(M22_characters.Kia, false)
--[[
while character_is_ready(M22_characters.Kia) == false do
thread_yield()
end
-- Grab Shaundi again
character_take_human_shield(M22_characters.Kia, M22_characters.Shaundi, true)
while(character_has_human_shield(M22_characters.Kia) == false) do
thread_yield()
end
--]]
set_ignore_ai_flag(M22_characters.Shaundi, false)
--thread_kill(shaundi_reaction_thread)
-- Continue moving to the destination navpoint, if there is one
if (Kia_boss_ai.current_navpoint ~= nil) then
npc_leash_remove(M22_characters.Kia)
npc_leash_to_object(M22_characters.Kia, Kia_boss_ai.current_navpoint, KIA_ATTACK_POSITION_LEASH_RADIUS)
end
end
-- Thread function that spawns continuous heli reinforcements during the Kia boss battle
function m22_kia_coop_reinforcements_thread()
while true do
group_create(M22_groups.vtol_coop_reinforcement)
m22_setup_stag_transport(M22_groups.vtol_coop_reinforcement)
helicopter_fly_to_direct(M22_groups.vtol_coop_reinforcement.vtol, -1, M22_groups.vtol_coop_reinforcement.drop_offs.path)
-- Tell the soldiers to exit the transport VTOL
for i, soldier in pairs(M22_groups.vtol_coop_reinforcement.drop_offs.soldiers) do
teleport(soldier, "nav_vtol_dropoff_coop", true)
end
delay(1)
helicopter_fly_to_direct(M22_groups.vtol_coop_reinforcement.vtol, -1, "nav_vtol_dropoff_flee_coop")
helicopter_enter_retreat(M22_groups.vtol_coop_reinforcement.vtol)
release_to_world(M22_groups.vtol_coop_reinforcement.name)
delay(KIA_COOP_REINFORCEMENTS_TIME)
end
end
-- Thread function that maintains a certain speed on the player's vehicle based on it's distance from Killbane's plane
function m22_manage_players_car_speed_thread()
local distance_from_killbane
while true do
distance_from_killbane = get_dist(M22_vehicles.Angels_Car, M22_vehicles.Killbanes_Plane)
if distance_from_killbane < 30 then
vehicle_max_speed(M22_vehicles.Angels_Car, 35)
else
if distance_from_killbane < 100 then
vehicle_max_speed(M22_vehicles.Angels_Car, 75)
else
vehicle_max_speed(M22_vehicles.Angels_Car, 100)
end
end
delay(3)
end
end
-- Function to process when to trigger a driving conversation between battlezones
function m22_thread_process_drive_convo(convo_table)
if (Number_of_zones_cleared > 1) then
-- Wait until the player gets into a car
while(character_is_in_vehicle(LOCAL_PLAYER) == false) do
thread_yield()
end
audio_play_persona_line(M22_characters.Pierce, M22_dialog_lines.pierce_leave_oleg[Number_of_zones_cleared])
end
-- If the driving convo has already played, then just return
if (M22_conversations.drive_convos[Number_of_zones_cleared + 1].played == true) then
return
end
delay(10)
while(thread_check_done(M22_threads.convo_handle) == false or character_is_in_vehicle(LOCAL_PLAYER) == false) do
thread_yield()
end
M22_threads.convo_handle = thread_new("m22_helper_play_conversation", M22_conversations.drive_convos[Number_of_zones_cleared + 1], 0.0)
end