--[[
m19.lua
SR3 Mission Script
DATE: 08-17-2010
AUTHOR: Neil Ryan and Craig Williams
]]--
-- Debug flags --
M19_enable_binks = true
M19_chem_moved_distance = 1.0
-- Tweakable Parameters --
M19_ped_density = .50
M19_ped_density_in_truck = 0.8
M19_ped_density_fix_mask = 0.35
M19_ped_density_at_rimjobs = 0.15
M19_player_sprint_ms = 3500 -- Amount of time a full sprint bar will last
M19_player_sprint_recharge_ms = 10000 -- Amount of time it takes to fully recharge the sprint bar
M19_player_sprint_recharge_delay_ms = 2500 -- Amount of time to wait before starting to recharge the sprint bar
-- Groups --
M19_group = {
start_car = {
name = "start_car"
},
stag_guard = {
name = "stag_guard",
members = { "npc_stag_guard 001", "npc_stag_guard 002" },
},
chem_01 = {
name = "chem_01_group"
},
chem_02 = {
name = "chem_02_group"
},
chem_02_brute = {
name = "chem_02_brute_group",
brute = "chem_02_brute",
detection_callback = "m19_brute_02_cb",
death_callback = "m19_first_brute_dead_cb",
},
chem_03 = {
name = "chem_03_group"
},
chem_03_brute = {
name = "chem_03_brute_group",
brute = "chem_03_brute",
detection_callback = "m19_brute_03_cb",
death_callback = "m19_first_brute_dead_cb",
},
chem_final = {
name = "chem_final_group"
},
chem_truck = {
name = "chem_truck_group",
vehicle = "chem_truck",
},
spawn_small_a = {
name = "continuous_small_a"
},
spawn_small_b = {
name = "continuous_small_b"
},
spawn_small_c = {
name = "continuous_small_c"
},
spawn_small_d = {
name = "continuous_small_d"
},
spawn_small_e = {
name = "continuous_small_e"
},
start_homies = {
name = "start_homies",
suko = "Suko_start"
},
inside_homies = {
name = "inside_homies",
suko = "Suko_inside"
},
checkpoint_homies = {
name = "checkpoint_homies",
suko = "Suko_checkpoint"
},
viola_attack_zombies = {
name = "attack_zombies",
-- car = "m19_viola_car",
members = { "m19_viola_zombie 001", "m19_viola_zombie 002", "m19_viola_zombie 003", "m19_viola_zombie 004" },
},
rim_jobs_spawns_01 = {
spawns = {"mask_spawn_a", "mask_spawn_b"},
},
rim_jobs_spawns_02 = {
spawns = {"mask_spawn_c"},
},
rim_jobs_spawns_03 = {
spawns = {"mask_spawn_d"},
},
rim_jobs_spawns_all = {
spawns = {"mask_spawn_a", "mask_spawn_b", "mask_spawn_c", "mask_spawn_d"},
},
flaming_brute = {
name = "flaming_brute_group",
brute = "m19_flaming_brute",
},
cte_zombie_group = {
name = "m19_cte_zombies_01",
},
cte_suko_group = {
name = "m19_cte_suko_01",
},
}
M19_cte = {
name = "m19_cte_01",
}
--we need to not stop and start the same spawns at each level or we get extra spawns
M19_c_spawn = {
level_1 = { M19_group.spawn_small_a.name, M19_group.spawn_small_b.name },
stop_level2 = { M19_group.spawn_small_a.name },
start_level2 = { M19_group.spawn_small_c.name },
stop_level3 = { M19_group.spawn_small_b.name },
start_level3 = { M19_group.spawn_small_d.name, M19_group.spawn_small_e.name },
}
-- Spawn Regions --
M19_spawn_regions = {
"Script_Spawn_Region 001",
"Script_Spawn_Region 002",
"Script_Spawn_Region 003",
"Script_Spawn_Region 004",
"Script_Spawn_Region 005",
"Script_Spawn_Region 006",
"Script_Spawn_Region 007",
"Script_Spawn_Region 008",
"Script_Spawn_Region 009",
"Script_Spawn_Region 010"
}
M19_mask_spawn_regions = {
"Mask_Spawn_Region 01",
"Mask_Spawn_Region 02",
"Mask_Spawn_Region 03",
"Mask_Spawn_Region 04",
}
-- Navpoints --
M19_nav = {
escape_here1 = {
name = "Escape_here_nav 001"
},
neutralize_here = {
name = "neutralize_chem_truck_nav"
},
mission_end = { "m19_end_nav_local", "m19_end_nav_coop" },
zombie_attack_leash_point = {
name = "zombie_attack_nav1"
},
mask_fix_point = {
name = "Mask_fix_navpoint"
},
rimjobs_door_open_point = {
name = "M19_OpenDoor_Offset"
},
mask_search_point = {
name = "viola_mask_search_nav"
},
}
-- Triggers --
M19_trigger = {
doors = {
name = "doors_trigger",
hit = false,
},
freeze = {
name = "m19_trigger_vehicle_freeze",
hit = false,
},
escape1 = {
name = "Escape_trigger 001",
hit = false,
},
escape2 = {
name = "Neutralize_audio_trigger",
hit = false,
},
dumpster = {
name = "m19_trigger_dumpster",
hit = false,
},
roof = {
name = "m19_trigger_roof",
hit = false,
},
rim_jobs = {
name = "mask_fix_trigger",
hit = false,
inside = 0,
},
rim_jobs_door = {
name = "m19_trigger_rimjobs_door",
},
traffic = {
name = "m19_disable_traffic",
},
island = {
name = "Trigger_island_area",
hit = false,
},
}
-- Characters --
-- Vehicles --
-- Mesh Movers --
M19_chemical = {
container1 = {
name = "Chemicalcontainer B 001",
script_mover_name = "Chem 001",
start_nav = "Chem_start 001", -- navpoint under the chem container used to see if the container has been moved
end_nav = "Chem_end 001",
vfx = { nav = "vfx_zombie_fog 001", handle = -1 },
zombies = M19_group.chem_01.name,
brute_group = "",
moved = false,
complete = false,
setup = false,
spawn_trigger = "Chem_01_spawn_trigger",
spawn_callback = "m19_chem_01_spawn_cb",
},
container2 = {
name = "Chemicalcontainer B 002",
script_mover_name = "Chem 002",
start_nav = "Chem_start 002", -- navpoint under the chem container used to see if the container has been moved
end_nav = "Chem_end 002",
vfx = { nav = "vfx_zombie_fog 002", handle = -1 },
zombies = M19_group.chem_02.name,
brute_group = M19_group.chem_02_brute,
moved = false,
complete = false,
setup = false,
spawn_trigger = "Chem_02_spawn_trigger",
spawn_callback = "m19_chem_02_spawn_cb",
},
container3 = {
name = "Chemicalcontainer B 003",
script_mover_name = "Chem 003",
start_nav = "Chem_start 003", -- navpoint under the chem container used to see if the container has been moved
end_nav = "Chem_end 003",
vfx = { nav = "vfx_zombie_fog 003", handle = -1 },
zombies = M19_group.chem_03.name,
brute_group = M19_group.chem_03_brute,
moved = false,
complete = false,
setup = false,
spawn_trigger = "Chem_03_spawn_trigger",
spawn_callback = "m19_chem_03_spawn_cb",
},
}
-- Text --
-- Threads --
M19_closest_container_thread = INVALID_THREAD_HANDLE
M19_moved_or_found_thread = INVALID_THREAD_HANDLE
M19_out_of_mask_trigger_thread = INVALID_THREAD_HANDLE
M19_brute_flame_thread = INVALID_THREAD_HANDLE
M19_local_player_health_thread = INVALID_THREAD_HANDLE
M19_remote_player_health_thread = INVALID_THREAD_HANDLE
-- Checkpoints --
M19_INSIDE_DOOR1 = "doors_start_nav 001"
M19_warp_points = {
bridge = {
player1 = "player1_bridge_nav",
player2 = "player2_bridge_nav",
viola = "viola_bridge_nav",
},
rimjobs = {
player1 = "player1_rimjobs_nav",
player2 = "player2_rimjobs_nav",
viola = "viola_rimjobs_nav",
},
}
M19_checkpoint = {
start = {
name = MISSION_START_CHECKPOINT,
nav = { "start_nav 001", "start_nav 002" },
},
doors = {
name = "m19_doors",
nav1 = "doors_start_nav 001",
nav2 = "doors_start_nav 002",
},
-- checkpoints for any 1 container
chem_01 = { name = "m19_chem_01" },
chem_02 = { name = "m19_chem_02" },
chem_03 = { name = "m19_chem_03" },
-- checkpoints for 1 container and viola rescued
chem_01_rescue = { name = "m19_chem_01_rescue" },
chem_02_rescue = { name = "m19_chem_02_rescue" },
chem_03_rescue = { name = "m19_chem_03_rescue" },
-- checkpoints for any 2 containers
chem_12 = { name = "m19_chem_12" },
chem_23 = { name = "m19_chem_23" },
chem_13 = { name = "m19_chem_13" },
-- checkpoints for any 2 containers and mask fixed
chem_12_fixed = { name = "m19_chem_12_fixed" },
chem_23_fixed = { name = "m19_chem_23_fixed" },
chem_13_fixed = { name = "m19_chem_13_fixed" },
all_no_mask = { name = "m19_no_mask" },
final = {
name = "m19_final",
nav1 = "doors_start_nav 001",
nav2 = "doors_start_nav 002",
}
}
-- Cutscenes --
CUTSCENE_MISSION_INTRO = "19_in"
CUTSCENE_MISSION_OUTRO = "19_out"
-- Conversations --
M19_convo = {
mission_start = {--
files = {
{name = "M19_Mission_Start", delay = 2.0, phonecall = false},
{name = "M19_Drive_01", delay = 0.0, phonecall = false},
},
thread = INVALID_THREAD_HANDLE,
},
help_me_call = {--
files = {
{name = "M19_Help_Me_Call", delay = 0.0, phonecall = true, recieveing = false},
},
thread = INVALID_THREAD_HANDLE,
},
viola_rescued = {--
files = {
{name = "M19_viola_Rescued", delay = 0.0, phonecall = false},
},
thread = INVALID_THREAD_HANDLE,
},
zombie_killing_01 = {--
files = {
{name = "", delay = 15.0, phonecall = false},
{name = "M19_Zombie_Killing_01", delay = 8.0, phonecall = false},
{name = "M19_More_Zombie_Killing", delay = 10.0, phonecall = false},
{name = "M19_More_Zombie_Killing_2", delay = 0.0, phonecall = false},
},
thread = INVALID_THREAD_HANDLE,
},
broken_mask = {--
files = {
{name = "M19_Broken_Mask", delay = 0.0, phonecall = false},
},
thread = INVALID_THREAD_HANDLE,
},
rim_jobs_start = {--
files = {
{name = "M19_Hold_Off_Zombies_RJ", delay = 10.0, phonecall = false},
{name = "M19_Hurry_Up_in_Rim_Jobs", delay = 10.0, phonecall = false},
{name = "M19_Hurry_Up_in_Rim_Jobs_2", delay = 9.0, phonecall = false},
{name = "M19_Found_Hose_In_Rim_Jobs", delay = 0.0, phonecall = false},
},
thread = INVALID_THREAD_HANDLE,
},
-- zombie_killing_02 = {
-- files = {
-- {name = "", delay = 15.0},
-- {name = "M19_Zombie_Killing_02", delay = 0.0},
-- },
-- thread = INVALID_THREAD_HANDLE,
-- },
zombie_killing_03 = {--
files = {
{name = "", delay = 15.0, phonecall = false},
{name = "M19_Zombie_Killing_03", delay = 10.0, phonecall = false},
{name = "M19_Zombie_Killing_04", delay = 0.0, phonecall = false},
},
thread = INVALID_THREAD_HANDLE,
},
take_sample = {--
files = {
{name = "M19_Finish_The_Job_Call", delay = 5.0, phonecall = true, recieveing = true},
{name = "M19_Take_Sample_Call", delay = 0.0, phonecall = true, recieveing = true},
},
thread = INVALID_THREAD_HANDLE,
},
left_with_truck = {--
files = {
{name = "M19_Flatbed_Truck", delay = 0.0, phonecall = false},
},
thread = INVALID_THREAD_HANDLE,
},
jump_truck = {--
files = {
{name = "M19_Jump_Truck", delay = 0.0, phonecall = false},
},
thread = INVALID_THREAD_HANDLE,
},
}
M19_personas = {
{ name = "Oleg", handle = INVALID_PERSONA_HANDLE },
{ name = "Suko", handle = INVALID_PERSONA_HANDLE },
{ name = "Burt", handle = INVALID_PERSONA_HANDLE },
}
M19_persona_line = {
easy_enough = { name = "M19_First_Container_Done_01", character = LOCAL_PLAYER, play_2d = false},--
blasting_containers = { name = "M19_Blasting_Containers", character = LOCAL_PLAYER, play_2d = false},--
see_zombie = { name = "M19_More_Zombie_Brute_01", character = LOCAL_PLAYER, play_2d = false},
-- Character set by m19_setup_crew()
one_more = { name = "M19_Third_Container_Done", character = "", play_2d = false},--
brute_on_fire = { name = "M19_Brute_On_Fire", character = LOCAL_PLAYER, play_2d = false},
brute_on_fire_dead = { name = "M19_Brute_On_Fire_Dead", character = LOCAL_PLAYER, play_2d = false},
}
M19_island_emitter = "M19_amb_zombie_island"
M19_emitters = {
"M19_em_crashed_plane_groans",
}
-- Other --
M19_SONIC_GUN = "Special-SonicGun"
M19_PLAYER_LOADOUT = { M19_SONIC_GUN }
M19_containers_disturbed = 0
M19_containers_found = 0
M19_spawn_level = 0
M19_doors_started = false
-- record decision
M19_decision = {
took_chem_truck = false,
chem_truck_in_water = false,
}
M19_NOT_CLOSE_DISTANCE = 5000.0
M19_waypoint_target = ""
M19_active_convo = ""
M19_rim_jobs_old_door = "m19_rimjobs_door_mover"
M19_rim_jobs_new_door = "rim_jobs_zombie_door_mover"
M19_container_splash_effect = "Wtr Splash Zombie"
M19_mask_finished = false
M19_initial_brute_down = false
Current_Suko = ""
M19_phonecall_finished = false
M19_first_brute_dead = false
-- *************************
--
-- Standard functions
--
-- *************************
-- This is the primary entry point for the mission, and is responsible for starting up the mission
-- at the specified checkpoint.
-- CALLED FROM CODE
--
-- m19_checkpoint: The checkpoint the mission should begin at
-- is_restart: TRUE if the mission is restarting, FALSE otherwise
--
function m19_start(m19_checkpoint, is_restart)
-- Check if this mission starting from the beginning
if (m19_checkpoint == M19_checkpoint.start.name) then
if (is_restart == false) then
-- First time playing mission
-- Play an intro cutscene???
if (CUTSCENE_MISSION_INTRO ~= "") then
cutscene_play(CUTSCENE_MISSION_INTRO, nil, M19_checkpoint.start.nav, false)
elseif M19_enable_binks then
bink_play("19_IN_v2")
end
end
fade_out(0)
end
-- Handle mission initialization for the current checkpoint
m19_initialize(m19_checkpoint)
-- Run the mission from the current checkpoint
m19_run(m19_checkpoint)
end
-- This is the primary function responsible for running the entire mission from start to finish.
--
-- first_checkpoint: The first checkpoint to begin running the mission at
--
function m19_run(first_checkpoint)
local current_checkpoint = first_checkpoint
local ignore_vehicles = true
local ignore_notoriety = true
spawn_override_change_hood_alternate_spawning("HOOD_ZOMBIE", true)
-- post voice event to mute non-modulated voice
audio_object_post_event("Mission_VO_Override")
--set the cancel navpoints
mission_set_cancel_warp_location(M19_checkpoint.start.nav[1], M19_checkpoint.start.nav[2])
-- Run the mission from the beginning
if current_checkpoint == M19_checkpoint.start.name then
objective_text( 0, "M19_OBJ_GO_TO_ENTRANCE", "", "", SYNC_ALL, OI_ASSET_LOCATION )
m19_go_to_entrance()
m19_guards_scene()
tutorial_start("weap_charge_weapon", 0, true, true)
current_checkpoint = M19_checkpoint.doors.name
mission_set_checkpoint(M19_checkpoint.doors.name, ignore_vehicles, ignore_notoriety)
end
spawn_region_max_spawn_dist(150.0)
notoriety_force_no_spawn("morningstar", true)
notoriety_set_min("morningstar", 0)
notoriety_set_max("morningstar", 0)
notoriety_force_no_spawn("luchadores", true)
notoriety_set_min("luchadores", 0)
notoriety_set_max("luchadores", 0)
notoriety_force_no_spawn("deckers", true)
notoriety_set_min("deckers", 0)
notoriety_set_max("deckers", 0)
notoriety_force_no_spawn("police", true)
notoriety_force_no_spawn("stag", true)
--start audio emitters
for i, emitter in pairs(M19_emitters) do
audio_ambient_emitter_start(emitter)
end
--start health monitoring
M19_local_player_health_thread = thread_new("m19_player_health_thread", LOCAL_PLAYER)
if (coop_is_active()) then
M19_remote_player_health_thread = thread_new("m19_player_health_thread", REMOTE_PLAYER)
end
m19_setup_containers_for_checkpoint(current_checkpoint)
-- determine which checkpoint is hit
if(m19_get_num_destroyed_containers() < 1) then
current_checkpoint = m19_do_containers_checkpoints(current_checkpoint, 1)
mission_set_checkpoint(current_checkpoint, ignore_vehicles, ignore_notoriety)
end
if (current_checkpoint == M19_checkpoint.chem_01.name or current_checkpoint == M19_checkpoint.chem_02.name or current_checkpoint == M19_checkpoint.chem_03.name) then
current_checkpoint = m19_do_rescue()
m19_start_convo_thread(M19_convo.zombie_killing_01)
end
-- from this poitn on viola should be invulnerable
--mute viola's normal persona lines
npc_suppress_persona(Current_Suko, true)
if(m19_get_num_destroyed_containers() < 2) then
current_checkpoint = m19_do_containers_checkpoints(current_checkpoint, 2)
mission_set_checkpoint(current_checkpoint, ignore_vehicles, ignore_notoriety)
end
if (current_checkpoint == M19_checkpoint.chem_12.name or current_checkpoint == M19_checkpoint.chem_13.name or current_checkpoint == M19_checkpoint.chem_23.name or current_checkpoint == M19_checkpoint.all_no_mask.name) then
current_checkpoint = m19_do_mask()
m19_start_convo_thread(M19_convo.zombie_killing_03)
end
if(m19_get_num_destroyed_containers() < 3) then
current_checkpoint = m19_do_containers_checkpoints(current_checkpoint, 3)
mission_set_checkpoint(current_checkpoint, ignore_vehicles, ignore_notoriety)
end
if current_checkpoint == M19_checkpoint.final.name then
m19_take_or_destroy_chem_truck()
end
-- if (CUTSCENE_MISSION_OUTRO ~= "") then
-- cutscene_play(CUTSCENE_MISSION_OUTRO)
-- elseif M19_enable_binks then
-- bink_play("19_Out_v2")
-- end
-- fade_out(0.5)
-- fade_out_block()
-- teleport_coop(M19_nav.mission_end_local.name, M19_nav.mission_end_coop.name, true)
-- fade_in(0.5)
-- fade_in_block()
mission_end_success("m19", CUTSCENE_MISSION_OUTRO, M19_nav.mission_end)
end
-- This is the primary function responsible for cleaning up the entire mission
-- CALLED FROM CODE (+++MUST RETURN IMMEDIATLY+++)
--
function m19_cleanup()
-- stop muting voice
audio_object_post_event("Mission_VO_Override_Stop")
audio_object_post_event("M19_Music_STOP", nil, nil, LOCAL_PLAYER)
-- Unload any audio
m19_unload_all_convos()
m19_unload_personas()
-- re-enable traffic
traffic_disable_lanes(M19_trigger.traffic.name, false)
sidewalk_disable_nodes(M19_trigger.island.name, true)
--fix rimjobs door
mesh_mover_hide(M19_rim_jobs_new_door)
mesh_mover_show(M19_rim_jobs_old_door)
spawn_region_max_spawn_dist_reset()
-- shut down continuous spawns
m19_stop_continuous_spawns()
for i,spawn in pairs(M19_group.rim_jobs_spawns_all.spawns) do
continuous_spawn_stop(spawn)
end
continuous_spawn_regions_enable(M19_spawn_regions, false)
continuous_spawn_regions_enable(M19_mask_spawn_regions, false)
-- clear tod settings
m19_clear_tod()
-- remove temp weapons
inv_remove_temp_loadout(M19_PLAYER_LOADOUT)
-- kill the water check
if M19_moved_or_found_thread ~= INVALID_THREAD_HANDLE then
thread_kill(M19_moved_or_found_thread)
M19_moved_or_found_thread = INVALID_THREAD_HANDLE
end
if M19_closest_container_thread ~= INVALID_THREAD_HANDLE then
thread_kill(M19_closest_container_thread)
M19_closest_container_thread = INVALID_THREAD_HANDLE
end
if M19_brute_flame_thread ~= INVALID_THREAD_HANDLE then
thread_kill(M19_brute_flame_thread)
M19_brute_flame_thread = INVALID_THREAD_HANDLE
end
if M19_local_player_health_thread ~= INVALID_THREAD_HANDLE then
thread_kill(M19_local_player_health_thread)
M19_local_player_health_thread = INVALID_THREAD_HANDLE
end
if M19_remote_player_health_thread ~= INVALID_THREAD_HANDLE then
thread_kill(M19_remote_player_health_thread)
M19_remote_player_health_thread = INVALID_THREAD_HANDLE
end
if M19_out_of_mask_trigger_thread ~= INVALID_THREAD_HANDLE then
thread_kill(M19_out_of_mask_trigger_thread)
M19_out_of_mask_trigger_thread = INVALID_THREAD_HANDLE
end
-- clear container markers
m19_clear_container(M19_chemical.container1)
m19_clear_container(M19_chemical.container2)
m19_clear_container(M19_chemical.container3)
-- cleanup truck
on_vehicle_destroyed("", M19_group.chem_truck.vehicle)
--cleanup zombies
for i, zombie in pairs(M19_group.viola_attack_zombies.members) do
on_death("", zombie)
end
--cleanup first brutes
on_detection("", M19_group.chem_02_brute.brute)
on_detection("", M19_group.chem_03_brute.brute)
on_death("", M19_group.chem_02_brute.brute)
on_death("", M19_group.chem_03_brute.brute)
-- Cleanup the decision scene
m19_cleanup_decision()
-- clear triggers
for key, trigger in pairs(M19_trigger) do
m19_clear_trigger(trigger.name)
end
-- cleanup groups
m19_cleanup_groups()
m19_cleanup_crew(M19_group.start_homies)
m19_cleanup_crew(M19_group.inside_homies)
m19_cleanup_crew(M19_group.checkpoint_homies)
notoriety_set_max("luchadores", 5)
notoriety_set_max("deckers", 5)
notoriety_set_max("morningstar", 5)
notoriety_force_no_spawn("luchadores", false)
notoriety_force_no_spawn("deckers", false)
notoriety_force_no_spawn("morningstar", false)
notoriety_force_no_spawn("police", false)
notoriety_force_no_spawn("stag", false)
-- Remove any sprint restrictions
player_override_clear_sprint()
player_override_clear_sprint_delay()
player_override_clear_sprint_recharge()
-- cleanup timer callback
hud_timer_set(1, 0, "")
hud_timer_stop(1)
hud_timer_hide(1, true)
-- do spawning again
spawning_vehicles(true)
-- takeoff player mask
customization_item_revert()
audio_object_post_event("m19_sfx_gas_mask_STOP", nil, nil, LOCAL_PLAYER)
if (coop_is_active()) then
audio_object_post_event("m19_sfx_gas_mask_STOP", nil, nil, REMOTE_PLAYER)
end
audio_object_post_event("m19_amb_PC_poisoned_STOP")
--stop audio emitters
for i, emitter in pairs(M19_emitters) do
audio_ambient_emitter_stop(emitter)
end
audio_ambient_emitter_stop(M19_island_emitter)
--kill any phonecalls that may be occuring
audio_remove_mission_cellphone("M19_Help_Me_Call")
audio_remove_mission_cellphone("M19_Finish_The_Job_Call")
audio_remove_mission_cellphone("M19_Take_Sample_Call")
--kill all other mission audio
audio_play("M19_unload")
--clear drug effects
drug_effect_clear_override_values()
refraction_situation_clear()
end
-- Called when the mission has ended with success
-- CALLED FROM CODE (+++MUST RETURN IMMEDIATLY+++)
--
function m19_success()
end
-- *************************
--
-- Local functions
--
-- *************************
-- Initialize the mission for the specified checkpoint
--
-- checkpoint: Checkpoint to initialize the mission to
--
function m19_initialize(checkpoint)
-- Zone swap
-- city_zone_swap("chemcrash")
city_zone_swap("zombies")
city_zone_swap("mayoroff")
mesh_mover_hide(M19_rim_jobs_old_door)
mesh_mover_show(M19_rim_jobs_new_door)
-- city_zone_swap("burn")
traffic_disable_lanes(M19_trigger.traffic.name, true)
sidewalk_disable_nodes(M19_trigger.island.name, false)
-- Make sure the screen is completly faded out
mission_start_fade_out(0.0)
-- Set the mission author
set_mission_author("Neil Ryan")
-- Common initialization
m19_initialize_common()
-- Checkpoint specific initialization
m19_initialize_checkpoint(checkpoint)
-- Start fading in
mission_start_fade_in()
end
-- Go to the entrance of the zombie area
--
function m19_go_to_entrance()
m19_setup_crew(M19_group.start_homies)
group_create(M19_group.stag_guard)
for i, npc in pairs(M19_group.stag_guard.members) do
npc_detection_enable(npc, false)
end
m19_set_trigger(M19_trigger.island.name, "m19_island_entrance_cb", false)
m19_set_trigger(M19_trigger.doors.name, "m19_doors_cb")
mission_waypoint_add(M19_trigger.doors.name, SYNC_ALL)
marker_add(M19_trigger.doors.name, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
m19_start_convo_thread(M19_convo.mission_start)
m19_set_trigger(M19_trigger.freeze.name, "m19_doors_freeze_cb", false)
set_ped_density(M19_ped_density)
while not M19_trigger.doors.hit do
thread_yield()
end
if character_is_in_vehicle(LOCAL_PLAYER) then
vehicle_speed_override(LOCAL_PLAYER, 0)
end
if character_is_in_vehicle(REMOTE_PLAYER) then
vehicle_speed_override(REMOTE_PLAYER, 0)
end
--start the zombie island emitter
audio_ambient_emitter_start(M19_island_emitter)
end
-- Z-scene of guards letting you into the infected area
function m19_guards_scene()
if M19_trigger.island.hit == true then
for i, container in pairs(M19_chemical) do
mesh_mover_show(container.script_mover_name)
end
end
m19_clear_trigger(M19_trigger.island.name)
--fade_out(0.5)
--fade_out_block()
cutscene_in()
group_create_hidden( M19_group.cte_suko_group.name, true )
group_create_hidden( M19_group.cte_zombie_group.name, true )
customization_item_wear("cm_gasmask", "cm_mask_gasmask.cmeshx", "cm_mask_gasmask", true, SYNC_ALL, true)
character_add_prop("m19_cte_suko", "gasmask")
cutscene_play( M19_cte.name, nil, {M19_checkpoint.doors.nav1, M19_checkpoint.doors.nav2} )
--cutscene_play( M19_cte.name)
group_destroy( M19_group.cte_zombie_group.name )
group_destroy( M19_group.cte_suko_group.name )
M19_doors_started = true
-- teleport players into the bad area
--local exit_vehicle = true
--teleport_coop(M19_checkpoint.doors.nav1, M19_checkpoint.doors.nav2, exit_vehicle)
--delay(5)
m19_cleanup_crew(M19_group.start_homies)
-- if group_is_loaded(M19_group.start_car.name) then
-- group_destroy(M19_group.start_car.name)
-- end
if group_is_loaded(M19_group.stag_guard.name) then
group_destroy(M19_group.stag_guard.name)
end
--m19_setup_crew(M19_group.inside_homies)
spawning_vehicles(false)
m19_restrict_players_sprint()
inv_item_equip("Special-SonicGun", LOCAL_PLAYER)
if (coop_is_active()) then
inv_item_equip("Special-SonicGun", REMOTE_PLAYER)
end
customization_item_wear("cm_gasmask", "cm_mask_gasmask.cmeshx", "cm_mask_gasmask", true, SYNC_ALL, true)
--play gasmask sounds
audio_object_post_event("m19_sfx_gas_mask_normal", nil, nil, LOCAL_PLAYER)
if (coop_is_active()) then
audio_object_post_event("m19_sfx_gas_mask_normal", nil, nil, REMOTE_PLAYER)
end
--setup the exit truck here while we can be sure the players aren't in a custom car
m19_setup_chemical_truck()
cutscene_out()
--fade_in(0.5)
--fade_in_block()
end
function m19_setup_containers_for_checkpoint(current_checkpoint)
local do_1 = false
local do_2 = false
local do_3 = false
local checkpoint_found = true
-- figure out which containers we have left for the checkpoint
if current_checkpoint == M19_checkpoint.doors.name then
-- just got here, still need to do all of the containers
do_1 = true
do_2 = true
do_3 = true
elseif (current_checkpoint == M19_checkpoint.chem_01_rescue.name or
current_checkpoint == M19_checkpoint.chem_01.name) then
do_2 = true
do_3 = true
elseif (current_checkpoint == M19_checkpoint.chem_02_rescue.name or
current_checkpoint == M19_checkpoint.chem_02.name) then
do_1 = true
do_3 = true
elseif (current_checkpoint == M19_checkpoint.chem_03_rescue.name or
current_checkpoint == M19_checkpoint.chem_03.name) then
do_1 = true
do_2 = true
elseif (current_checkpoint == M19_checkpoint.chem_12_fixed.name or
current_checkpoint == M19_checkpoint.chem_12.name) then
do_3 = true
elseif (current_checkpoint == M19_checkpoint.chem_23_fixed.name or
current_checkpoint == M19_checkpoint.chem_23.name) then
do_1 = true
elseif (current_checkpoint == M19_checkpoint.chem_13_fixed.name or
current_checkpoint == M19_checkpoint.chem_13.name) then
do_2 = true
end
continuous_spawn_regions_enable(M19_spawn_regions, true)
-- setup or destroy container
if do_1 then
m19_setup_container(M19_chemical.container1)
else
m19_checkpoint_complete_container(M19_chemical.container1)
end
if do_2 then
m19_setup_container(M19_chemical.container2)
else
m19_checkpoint_complete_container(M19_chemical.container2)
end
if do_3 then
m19_setup_container(M19_chemical.container3)
else
m19_checkpoint_complete_container(M19_chemical.container3)
end
end
-- determine what we have done and what needs to be done
--
-- current_checkpoint: (string) name of the current checkpoint
--
function m19_do_containers_checkpoints(current_checkpoint, size)
--had to setup containers, but we've already finished this goal, don't mess with the rest
if (m19_get_num_destroyed_containers() >= size) then
return current_checkpoint
end
-- set objective text to whatever it needs to be
m19_set_3_way_objective_text()
-- check to see if containers have been moved or found
M19_moved_or_found_thread = thread_new("m19_container_moved_or_found_thread")
if (size == 1) then
--this should happen just after we get inside or if we restart at the doors checkpoint
audio_object_post_event("M19_music_mission_start", nil, nil, LOCAL_PLAYER)
end
--check all current containers and possibly re-add their OIs
m19_update_container_markers()
-- keep waypoint on the closest container
M19_closest_container_thread = thread_new("m19_nav_to_closest_thread")
while (m19_get_num_destroyed_containers() < size) do
thread_yield()
end
-- potentially clean up threads
if M19_moved_or_found_thread ~= INVALID_THREAD_HANDLE then
thread_kill(M19_moved_or_found_thread)
M19_moved_or_found_thread = INVALID_THREAD_HANDLE
end
if M19_closest_container_thread ~= INVALID_THREAD_HANDLE then
thread_kill(M19_closest_container_thread)
M19_closest_container_thread = INVALID_THREAD_HANDLE
end
m19_clear_container_markers()
-- keep track of where we're currently at
return m19_get_container_checkpoint()
end
function m19_update_container_markers()
for i, container in pairs(M19_chemical) do
if(container.moved and not container.complete) then
marker_remove(container.script_mover_name)
marker_add(container.script_mover_name, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_ALL)
waypoint_add(container.end_nav)
marker_add(container.end_nav, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_FULL, SYNC_ALL)
end
end
end
function m19_clear_container_markers()
for i, container in pairs(M19_chemical) do
marker_remove(container.script_mover_name, SYNC_ALL)
marker_remove(container.end_nav, SYNC_ALL)
end
end
-- after one container is destroyed, rescue viola
function m19_do_rescue()
local current_checkpoint_name
waypoint_remove()
-- set objective text to whatever it needs to be
m19_set_3_way_objective_text()
m19_start_convo_thread(M19_convo.help_me_call)
--spawn viola and zombies
m19_setup_crew(M19_group.inside_homies)
Current_Suko = M19_group.inside_homies.suko
character_add_prop(Current_Suko, "gasmask")
npc_leash_to_nav(Current_Suko, M19_nav.zombie_attack_leash_point.name, 1)
character_prevent_flinching(Current_Suko, true)
character_prevent_bumping(Current_Suko, true)
--mute viola's normal persona lines
npc_suppress_persona(Current_Suko, true)
--set_ignore_ai_flag(Current_Suko, true)
group_create(M19_group.viola_attack_zombies.name, true)
for i, zombie in pairs(M19_group.viola_attack_zombies.members) do
turn_invulnerable(zombie)
end
--wait on conversation
while M19_convo.help_me_call.thread ~= INVALID_THREAD_HANDLE do
thread_yield()
end
--guide the player to viola
m19_set_trigger(M19_trigger.dumpster.name, "m19_dumpster_cb", true)
objective_text( 0, "M19_OBJ_RESCUE_VIOLA", "", "", SYNC_ALL, OI_ASSET_LOCATION )
repeat
--seriously stay the hell there. wtf. stop it.
if (get_dist(Current_Suko, M19_nav.zombie_attack_leash_point.name) > 2.0) then
teleport(Current_Suko, M19_nav.zombie_attack_leash_point.name)
npc_leash_to_nav(Current_Suko, M19_nav.zombie_attack_leash_point.name, 1)
end
thread_yield()
until (M19_trigger.dumpster.hit)
m19_set_trigger(M19_trigger.roof.name, "m19_roof_cb", true)
repeat
thread_yield()
until (M19_trigger.roof.hit)
--set waypoint to viola
marker_add(Current_Suko, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_LOCATION)
--objective_text(0, "get to viola")
--set_ignore_ai_flag(Current_Suko, false)
--wait till you're close
while (get_dist_closest_player_to_object(Current_Suko) > 25) do
thread_yield()
end
-- once you're there, set goal to kill zombies, make viola not invulnerable
--objective_text(0, "kill zombies!")
objective_text( 0, "M19_OBJ_KILL_ZOMBiES", "", "", SYNC_ALL, OI_ASSET_KILL )
marker_remove(Current_Suko)
--follower_set_can_abandon( Current_Suko, true)
turn_vulnerable(Current_Suko)
npc_leash_remove(Current_Suko)
character_prevent_flinching(Current_Suko, false)
character_prevent_bumping(Current_Suko, false)
for i, zombie in pairs(M19_group.viola_attack_zombies.members) do
turn_vulnerable(zombie)
marker_add(zombie, MINIMAP_ICON_KILL, OI_ASSET_KILL, OI_FLAGS_DEFAULT, SYNC_ALL)
on_death("m19_viola_zombie_death_cb", zombie)
end
--while any zombies left wait
while ( group_members_alive(M19_group.viola_attack_zombies.name) > 0) do
thread_yield()
end
m19_start_convo_thread(M19_convo.viola_rescued)
npc_leash_remove(Current_Suko)
marker_remove(Current_Suko)
set_dont_attack_me_on_sight_flag(Current_Suko, true)
turn_invulnerable(Current_Suko)
current_checkpoint_name = m19_get_container_checkpoint(true, false)
mission_set_checkpoint(current_checkpoint_name, true, true)
delay(10)
return current_checkpoint_name
end
function m19_viola_zombie_death_cb(zombie, attacker)
marker_remove(zombie, SYNC_ALL)
on_death("", zombie)
end
-- after two containers are destroyed, fix your mask
function m19_do_mask()
local current_checkpoint_name
waypoint_remove()
-- set objective text to whatever it needs to be
m19_set_3_way_objective_text()
--change gasmask sounds
audio_object_post_event("m19_sfx_gas_mask_panic", nil, nil, LOCAL_PLAYER)
if (coop_is_active()) then
audio_object_post_event("m19_sfx_gas_mask_panic", nil, nil, REMOTE_PLAYER)
end
audio_object_post_event("m19_amb_PC_poisoned", nil, nil, LOCAL_PLAYER)
audio_object_post_event( "M19_music_PC_poisoned", nil, nil, LOCAL_PLAYER)
drug_effect_set_override_values(0.15,0)
refraction_situation_set("drug weak")
m19_start_convo_thread(M19_convo.broken_mask)
--wait on conversation
while M19_convo.broken_mask.thread ~= INVALID_THREAD_HANDLE do
thread_yield()
end
-- Turn down peds
set_ped_density(M19_ped_density_fix_mask)
-- Set waypoint to rim_jobs
trigger_enable(M19_trigger.rim_jobs.name, true)
marker_add_trigger(M19_trigger.rim_jobs.name, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
on_trigger("m19_mask_trigger_enter_cb", M19_trigger.rim_jobs.name)
on_trigger_exit("m19_mask_trigger_exit_cb", M19_trigger.rim_jobs.name)
continuous_spawn_regions_enable(M19_spawn_regions, false)
continuous_spawn_regions_enable(M19_mask_spawn_regions, true)
objective_text( 0, "M19_OBJ_GO_TO_RIMJOBS", "", "", SYNC_ALL, OI_ASSET_LOCATION )
-- Wait till the player gets there
hud_timer_set(1, 120000, "get_to_rimjobs_cb")
local num_players = 1
if (coop_is_active()) then
num_players = 2
end
repeat
thread_yield()
until (M19_trigger.rim_jobs.inside == num_players)
hud_timer_set(1, 0, "")
hud_timer_stop(1)
hud_timer_hide(1, true)
marker_remove_trigger(M19_trigger.rim_jobs.name, SYNC_ALL)
-- Open the door to rimjobs
--door_open(M19_rim_jobs_door)
door_lock(M19_rim_jobs_new_door, true)
objective_text( 0, "M19_OBJ_OPEN_DOOR", "", "", SYNC_ALL, OI_ASSET_USE )
marker_add(M19_rim_jobs_new_door, MINIMAP_ICON_USE, OI_ASSET_USE, OI_FLAGS_DEFAULT, SYNC_ALL)
trigger_enable(M19_trigger.rim_jobs_door.name, true)
on_trigger("m19_open_rimjobs_cb", M19_trigger.rim_jobs_door.name)
repeat
thread_yield()
until (door_is_open(M19_rim_jobs_new_door))
--make sure this trigger is cleared
m19_clear_trigger(M19_trigger.rim_jobs_door.name)
--up the drugged effects
marker_remove(M19_rim_jobs_new_door, SYNC_ALL)
drug_effect_set_override_values(0.25,0)
-- refraction_situation_set("drug medium")
-- Turn down peds
set_ped_density(M19_ped_density_at_rimjobs)
-- Start spawns/setup fight
objective_text( 0, "M19_OBJ_PROTECT_VIOLA", "", "", SYNC_ALL, OI_ASSET_DEFEND )
marker_add(Current_Suko, MINIMAP_ICON_PROTECT_ACQUIRE, OI_ASSET_DEFEND, OI_FLAGS_FULL, SYNC_ALL)
--
-- marker_add_trigger(M19_trigger.rim_jobs.name, MINIMAP_ICON_USE, INGAME_EFFECT_LOCATION, OI_ASSET_USE, OI_FLAGS_LOCATION)
-- Make viola go to her spot
local should_run = true
local should_fire = false
while (get_dist(Current_Suko, M19_nav.mask_search_point.name) > 2.0) do
ai_do_scripted_move(Current_Suko, M19_nav.mask_search_point.name, should_run, should_fire)
npc_combat_enable(Current_Suko, false)
while not ai_scripted_action_is_complete(Current_Suko) do
thread_yield()
end
end
-- Start area monitoring thread
M19_out_of_mask_trigger_thread = thread_new("m19_handle_mask_trigger_thread")
m19_start_convo_thread(M19_convo.rim_jobs_start)
hud_timer_set(1, 45000, "")
-- Put her into searching state
npc_leash_to_nav(Current_Suko, M19_nav.mask_search_point.name, 10)
set_animation_state(Current_Suko, "walk investigate")
for i,spawn in pairs(M19_group.rim_jobs_spawns_01.spawns) do
continuous_spawn_start(spawn, 0, 15)
continuous_spawn_set_orders(spawn, "attack", "", -1)
end
-- Spawn a flaming brute
group_create(M19_group.flaming_brute.name, true)
character_ignite(M19_group.flaming_brute.brute)
-- Voice line about zombie brutes being weak to fire
M19_brute_flame_thread = thread_new("m19_flaming_brute_thread")
--up the drugged effects
drug_effect_set_override_values(0.25,0)
-- Wait on timer, spawn new groups of zombies after intervals
delay(15.0)
-- for i,spawn in pairs(M19_group.rim_jobs_spawns_02.spawns) do
-- continuous_spawn_start(spawn)
-- continuous_spawn_set_orders(spawn, "attack", "", -1)
-- end
--up the drugged effects
--drug_effect_set_override_values(0.35,0)
refraction_situation_set("drug medium")
delay(15.0)
for i,spawn in pairs(M19_group.rim_jobs_spawns_03.spawns) do
continuous_spawn_start(spawn, 0, 15)
continuous_spawn_set_orders(spawn, "attack", "", -1)
end
--up the drugged effects
drug_effect_set_override_values(0.45,0)
--refraction_situation_set("drug strongest")
delay(15.0)
while(M19_trigger.rim_jobs.inside == false) do
thread_yield()
end
hud_timer_set(1, 0, "")
hud_timer_stop(1)
hud_timer_hide(1, true)
-- Success!
if (M19_brute_flame_thread ~= INVALID_THREAD_HANDLE) then
thread_kill(M19_brute_flame_thread)
M19_brute_flame_thread = INVALID_THREAD_HANDLE
end
--go to viola to fix your mask
marker_remove(Current_Suko)
m19_clear_trigger(M19_trigger.rim_jobs.name)
marker_add(Current_Suko, MINIMAP_ICON_USE, OI_ASSET_LOCATION, OI_FLAGS_DEFAULT, SYNC_ALL)
objective_text( 0, "M19_OBJ_GO_TO_VIOLA", "", "", SYNC_ALL, OI_ASSET_LOCATION )
while(get_dist_closest_player_to_object(Current_Suko) > 5.0 or human_is_downed(Current_Suko)) do
thread_yield()
end
-- kill the monitoring thread
if M19_out_of_mask_trigger_thread ~= INVALID_THREAD_HANDLE then
thread_kill(M19_out_of_mask_trigger_thread)
hud_critical_timer_stop()
M19_out_of_mask_trigger_thread = INVALID_THREAD_HANDLE
end
m19_clear_trigger(M19_trigger.rim_jobs.name)
--message("your mask has been fixed!")
npc_combat_enable(Current_Suko, true)
npc_leash_remove(Current_Suko)
clear_animation_state(Current_Suko)
audio_object_post_event("m19_sfx_gas_mask_normal", nil, nil, LOCAL_PLAYER)
if (coop_is_active()) then
audio_object_post_event("m19_sfx_gas_mask_normal", nil, nil, REMOTE_PLAYER)
end
audio_object_post_event("m19_amb_PC_poisoned_STOP", nil, nil, LOCAL_PLAYER)
audio_object_post_event( "M19_music_zombie_island", nil, nil, LOCAL_PLAYER )
marker_remove(Current_Suko)
-- minimap_icon_remove_radius(M19_trigger.rim_jobs.name, SYNC_ALL)
for i,spawn in pairs(M19_group.rim_jobs_spawns_all.spawns) do
continuous_spawn_stop(spawn)
end
drug_effect_set_override_values(0.35,0)
refraction_situation_set("drug medium")
delay(1.0)
drug_effect_set_override_values(0.25,0)
--refraction_situation_set("drug medium")
delay(1.0)
drug_effect_set_override_values(0.15,0)
refraction_situation_set("drug weak")
delay(1.0)
drug_effect_clear_override_values()
refraction_situation_clear()
-- Restore ped density
set_ped_density(M19_ped_density)
continuous_spawn_regions_enable(M19_mask_spawn_regions, false)
continuous_spawn_regions_enable(M19_spawn_regions, true)
current_checkpoint_name = m19_get_container_checkpoint(false, true)
mission_set_checkpoint(current_checkpoint_name, true, true)
M19_mask_finished = true
return current_checkpoint_name
end
-- Take the chemical truck or destroy it
--
function m19_take_or_destroy_chem_truck()
waypoint_remove()
group_create(M19_group.chem_final.name)
zscene_prep(CUTSCENE_MISSION_OUTRO)
vehicle_show(M19_group.chem_truck.vehicle)
objective_text( 0, "M19_OBJ_GET_IN_TRUCK", "", "", SYNC_ALL, OI_ASSET_USE )
-- Allow the player to enter the chemical truck again
set_unjackable_flag(M19_group.chem_truck.vehicle, false)
-- Register some callbacks to detect what the player has done to the vehicle
on_vehicle_enter("m19_player_in_chem_truck_cb", M19_group.chem_truck.vehicle)
on_vehicle_enter_water("m19_chem_truck_in_water", M19_group.chem_truck.vehicle)
-- Point out where the vehicle is
mission_waypoint_add(M19_group.chem_truck.vehicle)
marker_add(M19_group.chem_truck.vehicle, MINIMAP_ICON_USE, OI_ASSET_USE, OI_FLAGS_FULL, SYNC_ALL)
while M19_convo.zombie_killing_03.thread ~= INVALID_THREAD_HANDLE do
thread_yield()
end
m19_start_convo_thread(M19_convo.take_sample)
while not M19_decision.took_chem_truck and not M19_decision.chem_truck_in_water do
thread_yield()
end
marker_remove(M19_group.chem_truck.vehicle)
mission_waypoint_remove()
while M19_convo.take_sample.thread ~= INVALID_THREAD_HANDLE do
thread_yield()
end
--player_choice_tut_open("m19")
-- Increase the ped count to give the player some extra stuff to run over
set_ped_density(M19_ped_density_in_truck)
objective_text( 0, "M19_OBJ_CHOICE", "", "", SYNC_ALL, OI_ASSET_INVALID )
vehicle_infinite_mass(M19_group.chem_truck.vehicle, false)
vehicle_prevent_explosion_fling(M19_group.chem_truck.vehicle, false)
vehicle_speed_override(M19_group.chem_truck.vehicle, 45.0)
marker_add(M19_trigger.escape1.name, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_DEFAULT, SYNC_ALL)
marker_add(M19_nav.neutralize_here.name, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_ALL)
m19_set_trigger(M19_trigger.escape1.name, "m19_escape1_cb")
m19_set_trigger(M19_trigger.escape2.name, "m19_escape2_cb", false)
object_indicator_add_objective_text(M19_trigger.escape1.name, "PLAYER_CHOICE_M19_OPTION1_TITLE", "PLAYER_CHOICE_M19_OPTION1_BODY")
object_indicator_add_objective_text(M19_nav.neutralize_here.name, "PLAYER_CHOICE_M19_OPTION2_TITLE", "PLAYER_CHOICE_M19_OPTION2_BODY")
while true do
if M19_trigger.escape1.hit or M19_decision.chem_truck_in_water then
break
end
-- Nag the player to get back into the truck if they are no longer in it
local player_in_vehicle = character_is_in_vehicle(LOCAL_PLAYER, M19_group.chem_truck.vehicle)
if (player_in_vehicle == false) then
player_in_vehicle = character_is_in_vehicle(REMOTE_PLAYER, M19_group.chem_truck.vehicle)
end
if not player_in_vehicle then
m19_clear_trigger(M19_trigger.escape1.name)
m19_clear_trigger(M19_trigger.escape2.name)
marker_remove(M19_trigger.escape1.name)
marker_remove(M19_nav.neutralize_here.name)
M19_decision.took_chem_truck = false
objective_text( 0, "M19_OBJ_GET_IN_TRUCK", "", "", SYNC_ALL, OI_ASSET_USE )
marker_add(M19_group.chem_truck.vehicle, MINIMAP_ICON_USE, OI_ASSET_USE, OI_FLAGS_DEFAULT, SYNC_ALL)
while not M19_decision.took_chem_truck and not M19_decision.chem_truck_in_water do
thread_yield()
end
marker_remove(M19_group.chem_truck.vehicle)
objective_text( 0, "M19_OBJ_CHOICE", "", "", SYNC_ALL, OI_ASSET_INVALID )
marker_add(M19_trigger.escape1.name, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_DEFAULT, SYNC_ALL)
marker_add(M19_nav.neutralize_here.name, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_ALL)
m19_set_trigger(M19_trigger.escape1.name, "m19_escape1_cb")
m19_set_trigger(M19_trigger.escape2.name, "m19_escape2_cb", false)
end
thread_yield()
end
if M19_decision.chem_truck_in_water then
-- If the chem truck is in the water, we get SWAT instead of zombies.
-- Exclude the zombie reward
mission_set_excluded_reward("Homie_Zombie_Backup")
else
m19_play_convo_set(M19_convo.left_with_truck)
mission_set_excluded_reward("Homie_Mayor_Reynolds")
mission_set_excluded_reward("Homie_SWAT_Backup")
end
audio_object_post_event( "M19_music_zombie_island_end", nil, nil, LOCAL_PLAYER )
m19_cleanup_decision()
end
-- Cleanup anything setup for the decision scene
function m19_cleanup_decision()
on_vehicle_enter("", M19_group.chem_truck.vehicle)
on_vehicle_enter_water("", M19_group.chem_truck.vehicle)
marker_remove(M19_group.chem_truck.vehicle)
marker_remove(M19_trigger.escape1.name)
marker_remove(M19_nav.neutralize_here.name)
m19_clear_trigger(M19_trigger.escape1.name)
end
-- ***************************************************
-- m19_run Helper Functions
-- ***************************************************
-- ***************************************************
-- m19_initialize Helper Functions
-- ***************************************************
-- Handle any common initialization
--
function m19_initialize_common()
-- We only use fake notoriety, so make sure checkpoint system doesn't screw this up for us
notoriety_reset("luchadores")
notoriety_reset("deckers")
notoriety_reset("morningstar")
inv_add_temp_loadout(M19_PLAYER_LOADOUT)
for i, container in pairs(M19_chemical) do
container.setup = false
end
M19_mask_finished = false
M19_initial_brute_down = false
m19_set_tod()
m19_load_personas()
end
-- set the time of day for the mission
function m19_set_tod()
-- make it blood red night
set_time_of_day(20, 00) -- evening
end
-- clear the time of day for the mission
function m19_clear_tod()
end
-- Checkpoint specific initialization
--
-- checkpoint: The checkpoint to be initialized
--
function m19_initialize_checkpoint(checkpoint)
if (checkpoint == M19_checkpoint.start.name) then
teleport_coop(M19_checkpoint.start.nav[1], M19_checkpoint.start.nav[2], true)
group_create(M19_group.start_car.name, true)
else
--equip the sonic gun
inv_item_equip("Special-SonicGun", LOCAL_PLAYER)
if (coop_is_active()) then
inv_item_equip("Special-SonicGun", REMOTE_PLAYER)
end
customization_item_wear("cm_gasmask", "cm_mask_gasmask.cmeshx", "cm_mask_gasmask", true, SYNC_ALL, true)
audio_object_post_event("m19_sfx_gas_mask_normal", nil, nil, LOCAL_PLAYER)
audio_ambient_emitter_start(M19_island_emitter)
if (coop_is_active()) then
audio_object_post_event("m19_sfx_gas_mask_normal", nil, nil, REMOTE_PLAYER)
end
if (checkpoint ~= M19_checkpoint.doors.name) then
--only play this if we're starting after the doors checkpoint
audio_object_post_event( "M19_music_regular_checkpoint", nil, nil, LOCAL_PLAYER )
end
if (checkpoint ~= M19_checkpoint.doors.name and
checkpoint ~= M19_checkpoint.chem_01.name and
checkpoint ~= M19_checkpoint.chem_02.name and
checkpoint ~= M19_checkpoint.chem_03.name) then
--m19_setup_crew(M19_group.inside_homies)
--Current_Suko = M19_group.inside_homies.suko
m19_setup_crew(M19_group.checkpoint_homies)
Current_Suko = M19_group.checkpoint_homies.suko
character_add_prop(Current_Suko, "gasmask")
end
--possibly teleport
if (checkpoint == M19_checkpoint.chem_12.name or
checkpoint == M19_checkpoint.chem_23.name or
checkpoint == M19_checkpoint.chem_13.name or
checkpoint == M19_checkpoint.all_no_mask.name) then
teleport_coop(M19_warp_points.bridge.player1, M19_warp_points.bridge.player2, true)
teleport(Current_Suko, M19_warp_points.bridge.viola, true)
M19_initial_brute_down = true
elseif (checkpoint == M19_checkpoint.chem_12_fixed.name or
checkpoint == M19_checkpoint.chem_13_fixed.name or
checkpoint == M19_checkpoint.chem_23_fixed.name or
checkpoint == M19_checkpoint.final.name) then
teleport_coop(M19_warp_points.rimjobs.player1, M19_warp_points.rimjobs.viola, true)
-- teleport(Current_Suko, M19_warp_points.rimjobs.viola, true)
M19_mask_finished = true
M19_initial_brute_down = true
else
-- default is teleporting inside the door
teleport_coop(M19_checkpoint.doors.nav1, M19_checkpoint.doors.nav2, true)
end
--setup the end truck
m19_setup_chemical_truck()
spawning_vehicles(false)
set_ped_density(M19_ped_density)
m19_restrict_players_sprint()
end
end
-- Sets up the mission critical chemical truck for the final decision scene
--
function m19_setup_chemical_truck()
group_create(M19_group.chem_truck.name)
vehicle_infinite_mass(M19_group.chem_truck.vehicle, true)
vehicle_prevent_explosion_fling(M19_group.chem_truck.vehicle, true)
set_unjackable_flag(M19_group.chem_truck.vehicle, true)
on_vehicle_destroyed("m19_mover_destroyed_cb", M19_group.chem_truck.vehicle)
vehicle_hide(M19_group.chem_truck.vehicle)
end
-- Add the radius thing to the chem container and setup callbacks and flags.
--
-- setup_container: (table) container information
--
function m19_setup_container(setup_container)
if (setup_container.setup == false) then
while (mesh_mover_ready(setup_container.script_mover_name) == false) do
thread_yield()
end
mesh_mover_reset(setup_container.script_mover_name)
on_mover_enter_water("m19_container_in_water_cb", setup_container.script_mover_name)
on_mover_destroyed("m19_mover_destroyed_cb", setup_container.script_mover_name)
m19_set_trigger(setup_container.spawn_trigger, setup_container.spawn_callback, false)
-- setup_container.hiss_id = audio_object_post_event("m19_sfx_virus_tank_beep_hiss", nil, nil, setup_container.script_mover_name)
setup_container.complete = false
setup_container.moved = false
setup_container.vfx.handle = effect_play(setup_container.vfx.nav, true, SYNC_ALL)
setup_container.setup = true
end
end
-- Mark container as completed and destroy it.
-- This function is for loading from a checkpoint.
-- The normal clearing of a container is handled in the checkpoint.
--
-- complete_container: (table) container information
--
function m19_checkpoint_complete_container(complete_container)
mesh_mover_hide(complete_container.script_mover_name)
if (complete_container.moved ~= true) then
complete_container.moved = true
M19_containers_disturbed = M19_containers_disturbed + 1
M19_containers_found = M19_containers_found + 1
end
complete_container.complete = true
m19_adjust_spawning()
end
-- Remove markers/callbacks for a container
--
-- container: (table) container information
--
function m19_clear_container(container)
marker_remove(container.script_mover_name, SYNC_ALL)
marker_remove(container.end_nav, SYNC_ALL)
on_mover_enter_water("", container.script_mover_name)
on_mover_destroyed("", container.script_mover_name)
m19_clear_trigger(container.spawn_trigger)
end
-- ***************************************************
-- Miscellaneous m19 Helper Funcrtions
-- ***************************************************
-- Reduce the player's ability to sprint
--
function m19_restrict_players_sprint()
-- Change how long a full sprint bar will last. Unlimited sprint is ignored if once this value is set.
player_override_set_sprint(M19_player_sprint_ms)
-- Change how long it takes to recharge the full sprint bar
player_override_set_sprint_recharge(M19_player_sprint_recharge_ms)
-- Change the delay before the sprint bar starts to regenerate
player_override_set_sprint_delay(M19_player_sprint_recharge_delay_ms)
end
-- Spawn and setup homies
--
-- homie_setup: (table) homie information
--
function m19_setup_crew(homie_setup)
group_create(homie_setup.name, true)
party_add( homie_setup.suko, LOCAL_PLAYER )
follower_set_can_abandon( homie_setup.suko, false)
on_death("m19_failure_suko_died_cb", homie_setup.suko)
on_dismiss("m19_failure_suko_abandon_cb", homie_setup.suko)
set_behavior_set(homie_setup.suko, "Viola Zombie Fight")
M19_persona_line.one_more.character = homie_setup.suko
turn_invulnerable(homie_setup.suko)
inv_item_remove_all(homie_setup.suko)
inv_item_add("Shotgun-Police", 1, homie_setup.suko, true)
inv_item_equip(WEAPON_SLOT_SHOTGUN, homie_setup.suko)
npc_weapon_pickup_override(homie_setup.suko, false)
end
-- Cleanup homies
--
-- homie_cleanup: (table) homie information
--
function m19_cleanup_crew(homie_cleanup)
if group_is_loaded(homie_cleanup.name) then
on_death("", homie_cleanup.suko)
on_dismiss("", homie_cleanup.suko)
group_destroy(homie_cleanup.name)
end
end
-- Set a trigger enabled with a mission marker
--
-- trigger: (string) Name of the trigger
-- trigger_callback: (string) Function name to call when trigger is activated
--
function m19_set_trigger(trigger, trigger_callback, add_marker)
trigger_enable(trigger, true)
if add_marker ~= false then
marker_add_trigger(trigger, MINIMAP_ICON_LOCATION, INGAME_EFFECT_CHECKPOINT, OI_ASSET_LOCATION, OI_FLAGS_LOCATION, SYNC_ALL)
end
on_trigger(trigger_callback, trigger)
end
-- Disable trigger
--
-- trigger: (string) Name of the trigger
--
function m19_clear_trigger(trigger)
on_trigger("", trigger)
on_trigger_exit("", trigger)
trigger_enable(trigger, false)
marker_remove_trigger(trigger, SYNC_ALL)
mission_waypoint_remove()
end
-- Cleanup all mission groups
--
function m19_cleanup_groups()
if group_is_loaded(M19_group.start_car.name) then
group_destroy(M19_group.start_car.name)
end
if group_is_loaded(M19_group.stag_guard.name) then
group_destroy(M19_group.stag_guard.name)
end
if group_is_loaded(M19_group.chem_01.name) then
group_destroy(M19_group.chem_01.name)
end
if group_is_loaded(M19_group.chem_02.name) then
group_destroy(M19_group.chem_02.name)
end
if group_is_loaded(M19_group.chem_03.name) then
group_destroy(M19_group.chem_03.name)
end
if group_is_loaded(M19_group.chem_final.name) then
group_destroy(M19_group.chem_final.name)
end
if group_is_loaded(M19_group.chem_truck.name) then
group_destroy(M19_group.chem_truck.name)
end
end
-- start a group of continuous spawns
--
-- spawn_table: (table) continuous spawns to start
--
function m19_start_continuous_spawns(spawn_table)
for i,spawn in pairs(spawn_table) do
continuous_spawn_start(spawn, 0, 15)
end
end
function m19_stop_continuous_spawn_table(spawn_table)
for i,spawn in pairs(spawn_table) do
continuous_spawn_stop(spawn)
end
end
function m19_stop_continuous_spawns()
continuous_spawn_stop(M19_group.spawn_small_a.name)
continuous_spawn_stop(M19_group.spawn_small_b.name)
continuous_spawn_stop(M19_group.spawn_small_c.name)
continuous_spawn_stop(M19_group.spawn_small_d.name)
continuous_spawn_stop(M19_group.spawn_small_e.name)
end
-- adjust the continuous spawning based on the number of containers found
--
function m19_adjust_spawning()
if (M19_containers_disturbed <= M19_spawn_level) then
return -- spawn rate only goes up
end
if (M19_spawn_level == 0 and M19_containers_disturbed >= 1) then
m19_start_continuous_spawns(M19_c_spawn.level_1)
M19_spawn_level = 1
end
if (M19_spawn_level == 1 and M19_containers_disturbed >= 2 and M19_first_brute_dead == true )then
m19_stop_continuous_spawn_table(M19_c_spawn.stop_level2)
m19_start_continuous_spawns(M19_c_spawn.start_level2)
M19_spawn_level = 2
end
if (M19_spawn_level == 2 and M19_containers_disturbed == 3) then
m19_stop_continuous_spawn_table(M19_c_spawn.stop_level3)
m19_start_continuous_spawns(M19_c_spawn.start_level3)
M19_spawn_level = 3
end
end
-- Determine how many containers have been destroyed and play appropriate line
function m19_play_container_destroyed_audio()
local destroyed_count = 0
if M19_chemical.container1.complete then
destroyed_count = destroyed_count + 1
end
if M19_chemical.container2.complete then
destroyed_count = destroyed_count + 1
end
if M19_chemical.container3.complete then
destroyed_count = destroyed_count + 1
end
if destroyed_count == 1 then
m19_play_persona_line(M19_persona_line.easy_enough)
elseif destroyed_count == 2 then
-- m19_start_convo_thread(M19_convo.zombie_killing_02)
elseif destroyed_count == 3 then
m19_play_persona_line(M19_persona_line.one_more)
end
end
-- set the objective text based on how many containers are taken care of
function m19_set_3_way_objective_text()
local destroyed_count = 0
if M19_chemical.container1.complete then
destroyed_count = destroyed_count + 1
end
if M19_chemical.container2.complete then
destroyed_count = destroyed_count + 1
end
if M19_chemical.container3.complete then
destroyed_count = destroyed_count + 1
end
if destroyed_count < 3 then
objective_text( 0, "M19_OBJ_NEUTRALIZE_CONTAINERS", destroyed_count, 3, SYNC_ALL, OI_ASSET_KILL )
else
objective_text( 0, "M19_OBJ_GET_IN_TRUCK", "", "", SYNC_ALL, OI_ASSET_USE )
end
end
-- Determine which checkpoint we just completed
-- rescue and mask are set to true only if we *just* did one of them
function m19_get_container_checkpoint( rescue, mask )
local did1 = M19_chemical.container1.complete
local did2 = M19_chemical.container2.complete
local did3 = M19_chemical.container3.complete
local current_checkpoint
if (rescue) then
if did1 and did2 and did3 then
current_checkpoint = M19_checkpoint.all_no_mask.name
elseif did1 and did2 then
current_checkpoint = M19_checkpoint.chem_12.name
elseif did2 and did3 then
current_checkpoint = M19_checkpoint.chem_23.name
elseif did1 and did3 then
current_checkpoint = M19_checkpoint.chem_13.name
elseif did3 then
current_checkpoint = M19_checkpoint.chem_03_rescue.name
elseif did2 then
current_checkpoint = M19_checkpoint.chem_02_rescue.name
elseif did1 then
current_checkpoint = M19_checkpoint.chem_01_rescue.name
end
elseif (mask) then
if did1 and did2 and did3 then
current_checkpoint = M19_checkpoint.final.name
elseif did1 and did2 then
current_checkpoint = M19_checkpoint.chem_12_fixed.name
elseif did2 and did3 then
current_checkpoint = M19_checkpoint.chem_23_fixed.name
elseif did1 and did3 then
current_checkpoint = M19_checkpoint.chem_13_fixed.name
end
else
if did1 and did2 and did3 and M19_mask_finished then
current_checkpoint = M19_checkpoint.final.name
elseif did1 and did2 and did3 then
current_checkpoint = M19_checkpoint.all_no_mask.name
elseif did1 and did2 then
current_checkpoint = M19_checkpoint.chem_12.name
elseif did2 and did3 then
current_checkpoint = M19_checkpoint.chem_23.name
elseif did1 and did3 then
current_checkpoint = M19_checkpoint.chem_13.name
elseif did3 then
current_checkpoint = M19_checkpoint.chem_03.name
elseif did2 then
current_checkpoint = M19_checkpoint.chem_02.name
elseif did1 then
current_checkpoint = M19_checkpoint.chem_01.name
end
end
return current_checkpoint
end
-- check container to see if the has moved
-- separated from found becasue moved == attack
--
-- container_table: (table) container to test
--
function m19_moved_container_test(container_table)
if (M19_chem_moved_distance < get_dist(container_table.start_nav, container_table.script_mover_name)) then
container_table.moved = true
m19_clear_waypoint_target()
-- Ensure there are no makers on the container beforehand
marker_remove(container_table.script_mover_name)
marker_add(container_table.script_mover_name, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_ALL)
waypoint_add(container_table.end_nav)
marker_add(container_table.end_nav, MINIMAP_ICON_LOCATION, OI_ASSET_LOCATION, OI_FLAGS_FULL, SYNC_ALL)
M19_containers_found = M19_containers_found + 1
if (container_table.brute_group ~= "" and M19_initial_brute_down == false) then
--make sure the brute if alive sees you
if (character_is_dead(container_table.brute_group.brute) == false) then
set_always_sees_player_flag(container_table.brute_group.brute, true)
end
end
--Stop the VFX for this container
if (container_table.vfx.handle ~= -1) then
effect_stop(container_table.vfx.handle)
container_table.vfx.handle = -1
end
-- if (container_table.hiss_id ~= nil) then
-- audio_stop(container_table.hiss_id)
-- end
--play an audio line
m19_play_persona_line(M19_persona_line.blasting_containers)
-- bump up the continuous spawn
M19_containers_disturbed = M19_containers_disturbed + 1
m19_adjust_spawning()
end
end
-- Clear any previously set waypoint markers, and then add a marker to the specified container
--
-- container: (table) container to add a marker to
--
function m19_set_waypoint_target(container)
-- Ignore the container if we already have a marker on it
if M19_waypoint_target ~= "" and M19_waypoint_target.script_mover_name == container.script_mover_name then
return
end
-- Clear any old markers
m19_clear_waypoint_target()
-- Add the new marker
M19_waypoint_target = container
marker_add(container.script_mover_name, MINIMAP_ICON_KILL, OI_ASSET_KILL_FULL, OI_FLAGS_FULL, SYNC_ALL)
end
-- Remove any previously set waypoint markers.
--
function m19_clear_waypoint_target()
if M19_waypoint_target == "" then
return
end
-- Only remove the marker if the container hasn't been touched. Otherwise, we want to leave the marker
-- on the container.
if not M19_waypoint_target.moved then
marker_remove(M19_waypoint_target.script_mover_name)
end
M19_waypoint_target = ""
end
function m19_get_num_destroyed_containers()
local destroyed_count = 0
if M19_chemical.container1.complete then
destroyed_count = destroyed_count + 1
end
if M19_chemical.container2.complete then
destroyed_count = destroyed_count + 1
end
if M19_chemical.container3.complete then
destroyed_count = destroyed_count + 1
end
return destroyed_count
end
-- *************************
--
-- Callback functions
--
-- *************************
-- Suko died, you lose
function m19_failure_suko_died_cb()
mission_end_failure("m19", "m19_failure_suko_died")
end
-- Suko abandoned, you lose
function m19_failure_suko_abandon_cb()
hud_critical_timer_stop()
mission_end_failure("m19", "m19_failure_suko_abandoned")
end
function m19_island_entrance_cb()
for i, container in pairs(M19_chemical) do
mesh_mover_hide(container.script_mover_name)
end
M19_trigger.island.hit = true
end
function m19_doors_freeze_cb()
while M19_doors_started == false do
if character_is_in_vehicle(LOCAL_PLAYER) then
vehicle_freeze(LOCAL_PLAYER, true)
end
if character_is_in_vehicle(REMOTE_PLAYER) then
vehicle_freeze(REMOTE_PLAYER, true)
end
thread_yield()
end
m19_clear_trigger(M19_trigger.freeze.name)
end
-- a player has activiated the doors trigger region
function m19_doors_cb()
M19_trigger.doors.hit = true
m19_clear_trigger(M19_trigger.doors.name)
end
-- a player has hit the escape trigger
function m19_escape1_cb()
M19_trigger.escape1.hit = true
m19_clear_trigger(M19_trigger.escape1.name)
end
function m19_escape2_cb()
m19_start_convo_thread(M19_convo.jump_truck)
m19_clear_trigger(M19_trigger.escape2.name)
end
--spawn the dudes around a specific container
function m19_chem_01_spawn_cb(player, trigger)
local setup_container = M19_chemical.container1
if (setup_container.complete == false ) then
group_create(setup_container.zombies)
if (setup_container.brute_group ~= "" and M19_initial_brute_down == false) then
group_create(setup_container.brute_group.name)
on_detection(setup_container.brute_group.detection_callback, setup_container.brute_group.brute)
on_death(setup_container.brute_group.death_callback, setup_container.brute_group.brute)
end
end
m19_clear_trigger(trigger)
end
function m19_chem_02_spawn_cb(player, trigger)
local setup_container = M19_chemical.container2
if (setup_container.complete == false) then
group_create(setup_container.zombies)
if (setup_container.brute_group ~= "" and M19_initial_brute_down == false) then
group_create(setup_container.brute_group.name)
on_detection(setup_container.brute_group.detection_callback, setup_container.brute_group.brute)
on_death(setup_container.brute_group.death_callback, setup_container.brute_group.brute)
end
end
m19_clear_trigger(trigger)
end
function m19_chem_03_spawn_cb(player, trigger)
local setup_container = M19_chemical.container3
if (setup_container.complete == false) then
group_create(setup_container.zombies)
if (setup_container.brute_group ~= "" and M19_initial_brute_down == false) then
group_create(setup_container.brute_group.name)
on_detection(setup_container.brute_group.detection_callback, setup_container.brute_group.brute)
on_death(setup_container.brute_group.death_callback, setup_container.brute_group.brute)
end
end
m19_clear_trigger(trigger)
end
-- determine a chemical container is in the water
function m19_container_in_water_cb(mover_name)
-- find the container
for i, container in pairs(M19_chemical) do
if container.script_mover_name == mover_name then
--message("Container neutralized", 10.0)
container.complete = true
container.moved = true
--play sound
--audio_object_post_event("m19_sfx_virus_tank_splash", nil, nil, container.script_mover_name)
effect_play_on_script_object(M19_container_splash_effect, container.script_mover_name)
-- clean up any container stuff
m19_clear_container(container)
-- play amusing audio line
m19_play_container_destroyed_audio()
-- Remove the callback so m19_mover_destroyed_cb() doesn't get called
on_mover_destroyed("", container.script_mover_name)
marker_remove(container.end_nav, SYNC_ALL)
delay(1)
-- destroy the container mesh
mesh_mover_set_damaged_by_player_only(container.script_mover_name, false)
mesh_mover_kill(container.script_mover_name)
end
end
end
function m19_mover_destroyed_cb(mover_name)
mission_end_failure("m19", "m19_failure_container_destroyed")
end
-- Someone has entered the chemical truck
function m19_player_in_chem_truck_cb(player, vehicle)
-- if player == LOCAL_PLAYER then
M19_decision.took_chem_truck = true
-- end
end
-- The chemical truck fell into the water
function m19_chem_truck_in_water()
M19_decision.chem_truck_in_water = true
on_vehicle_destroyed("", M19_group.chem_truck.vehicle)
end
--viola rescue callbacks
function m19_dumpster_cb()
-- Clear the trigger
m19_clear_trigger(M19_trigger.dumpster.name)
-- Notify script that we reached the trigger
M19_trigger.dumpster.hit = true
end
function m19_roof_cb()
-- Clear the trigger
m19_clear_trigger(M19_trigger.roof.name)
-- Notify script that we reached the trigger
M19_trigger.roof.hit = true
end
function m19_mask_trigger_enter_cb(player)
M19_trigger.rim_jobs.inside = M19_trigger.rim_jobs.inside + 1
end
function m19_mask_trigger_exit_cb(player)
M19_trigger.rim_jobs.inside = M19_trigger.rim_jobs.inside - 1
end
function get_to_rimjobs_cb()
mission_end_failure("m19", "m19_failure_rimjobs_timer")
end
function m19_open_rimjobs_cb(player)
--ai_do_scripted_move(LOCAL_PLAYER, M19_nav.rimjobs_door_open_point, true)
door_lock(M19_rim_jobs_new_door, false)
door_open(M19_rim_jobs_new_door, false, true, player, "M19 Open Garage Door", M19_nav.rimjobs_door_open_point.name)
--action_play(player, "M19 Open Garage Door")
m19_clear_trigger(M19_trigger.rim_jobs_door.name)
end
function m19_brute_02_cb()
--play a line
delay(5)
m19_play_persona_line(M19_persona_line.see_zombie)
--kill other brute
on_death("", M19_group.chem_03_brute.brute)
if (character_exists(M19_group.chem_03_brute.brute)) then
character_kill(M19_group.chem_03_brute.brute)
end
--remove callbacks
on_detection("", M19_group.chem_02_brute.brute)
on_detection("", M19_group.chem_03_brute.brute)
M19_initial_brute_down = true
end
function m19_brute_03_cb()
--play a line
delay(5)
m19_play_persona_line(M19_persona_line.see_zombie)
--kill other brute
on_death("", M19_group.chem_02_brute.brute)
if (character_exists(M19_group.chem_02_brute.brute)) then
character_kill(M19_group.chem_02_brute.brute)
end
--remove callbacks
on_detection("", M19_group.chem_02_brute.brute)
on_detection("", M19_group.chem_03_brute.brute)
M19_initial_brute_down = true
end
function m19_first_brute_dead_cb(char)
m19_adjust_spawning()
on_death("", char)
end
function m19_finish_phonecall_cb()
M19_phonecall_finished = true
end
-- *************************
--
-- Thread functions
--
-- *************************
-- Find the closest container or container area and set a waypoint to it
function m19_nav_to_closest_thread()
while true do
-- If a container has been moved, but it still hasn't been pushed into the water, the container will have
-- a marker on it. Wait until the container is neutralized before we point out another container.
local player_moving_container = true
while player_moving_container do
player_moving_container = false
for i, container in pairs(M19_chemical) do
while not container.complete and container.moved do
thread_yield()
player_moving_container = true
end
end
end
-- Find the closest non-moved container
local closest = ""
local closest_dist = M19_NOT_CLOSE_DISTANCE
for i, container in pairs(M19_chemical) do
if not container.moved then
local dist = get_dist(LOCAL_PLAYER, container.script_mover_name)
if dist < closest_dist then
closest_dist = dist
closest = container
end
end
end
-- If we did not find a near by container, they have all been found.
if closest == "" then
break
end
-- Set the waypoint target to the closest container. This will clear the old marker for us as well.
m19_set_waypoint_target(closest)
-- don't update this so often
delay(1.0)
end
M19_closest_container_thread = INVALID_THREAD_HANDLE
end
-- determine if a container has been moved or found
--
function m19_container_moved_or_found_thread()
local all_complete = false
while not all_complete do
all_complete = true
for i, container in pairs(M19_chemical) do
if not container.complete and not container.moved then
all_complete = false
thread_yield() -- test over multiple frames
m19_moved_container_test(container)
end
end
thread_yield()
end
M19_moved_or_found_thread = INVALID_THREAD_HANDLE
end
--keep track of players being out of the trigger area and abandoning viola
function m19_handle_mask_trigger_thread()
local num_players = 1
if (coop_is_active()) then
num_players = 2
end
local players_inside = true
while (true) do
if (players_inside == true) then
if(M19_trigger.rim_jobs.inside < num_players) then
players_inside = false
--start a warning and fail chance
hud_critical_timer_set(10000, "m19_obj_protect_viola", "m19_failure_suko_abandon_cb")
end
else
if(M19_trigger.rim_jobs.inside == num_players) then
players_inside = true
--kill the warning and fail chance
hud_critical_timer_stop()
end
end
thread_yield()
end
end
--handle the player being out of the trigger area during the fix the mask section
function m19_out_of_mask_trigger_thread()
--objective_text(0, "get to back to Viola!")
m19_set_trigger(M19_trigger.rim_jobs.name, "m19_mask_trigger_return_cb", true)
--message("Get back to rim jobs!")
hud_critical_timer_set(10000, "m19_obj_protect_viola")
delay(10.0)
hud_critical_timer_stop()
--mission_end_failure("m19", "m19_failure_suko_abandoned")
end
function m19_flaming_brute_thread()
delay(1)
m19_play_persona_line(M19_persona_line.brute_on_fire)
while (get_dist_closest_player_to_object(M19_group.flaming_brute.brute) > 5.0) do
thread_yield()
end
--kill the brute
character_kill(M19_group.flaming_brute.brute)
m19_play_persona_line(M19_persona_line.brute_on_fire_dead)
M19_brute_flame_thread = INVALID_THREAD_HANDLE
end
function m19_player_health_thread(player)
local over_half = true
local over_quarter = true
local max_health = get_max_hit_points(player)
while (true) do
local current_health = get_current_hit_points(player)
local ratio = current_health / max_health
if (ratio > 0.5) then
--over half health
if(over_half == false) then
over_half = true
over_quarter = true
audio_object_post_event("m19_sfx_gas_mask_normal", nil, nil, player)
end
elseif (ratio > 0.25) then
if(over_quarter == false or over_half == true) then
over_half = false
over_quarter = true
audio_object_post_event("m19_sfx_gas_mask_sprint", nil, nil, LOCAL_PLAYER)
end
else
if(over_quarter == true or over_half == true) then
over_half = false
over_quarter = false
audio_object_post_event("m19_sfx_gas_mask_panic", nil, nil, LOCAL_PLAYER)
end
end
delay(2)
end
end
-- Plays a conversation
--
-- convo: Conversation to play
function m19_play_convo(convo)
if convo.name ~= "" and convo.name ~= nil then
--local msg_handle = message("Playing Convo: " .. convo.name, 99999999.0)
if(convo.phonecall == true) then
M19_phonecall_finished = false
convo.handle = INVALID_CONVERSATION_HANDLE
audio_play_for_mission_cellphone(convo.name , convo.recieveing , true, "", "m19_finish_phonecall_cb")
while (M19_phonecall_finished == false) do
thread_yield()
end
convo.handle = nil
else
convo.handle = audio_conversation_load(convo.name)
audio_conversation_play(convo.handle)
audio_conversation_wait_for_end(convo.handle)
convo.handle = nil
end
--message_remove(msg_handle)
end
if convo.delay ~= nil and convo.delay > 0.01 then
delay(convo.delay)
end
end
-- Unloads a conversation
--
-- convo: Conversation to unload
function m19_unload_convo(convo)
if convo.handle == nil then
return
end
audio_conversation_end(convo.handle)
convo.handle = nil
end
-- Unloads all conversations from the convo table
--
function m19_unload_all_convos()
for convo_key, convo_set in pairs(M19_convo) do
m19_unload_convo_set(convo_set)
if convo_set.thread ~= INVALID_THREAD_HANDLE then
thread_kill(convo_set.thread)
end
end
end
-- Iterates through a table of conversations and plays them.
--
-- convo_set: Table of conversations
--
function m19_play_convo_set(convo_set)
for key, convo in pairs(convo_set.files) do
m19_play_convo(convo)
end
end
-- Unloads a convo table (array)
--
-- convo_set Table of conversations to unload
--
function m19_unload_convo_set(convo_set)
for key, convo in pairs(convo_set.files) do
m19_unload_convo(convo)
end
end
-- Starts an audio conversation as a thread
--
-- convo_table: Conversation to play
--
function m19_start_convo_thread(convo_table)
if M19_active_convo ~= "" then
m19_unload_convo_set(M19_active_convo)
M19_active_convo = ""
end
convo_table.thread = thread_new("m19_audio_thread", convo_table)
end
-- Loads the necessary 2D personas for the heli rail sequence
--
function m19_load_personas()
for key, persona in pairs(M19_personas) do
persona.handle = audio_persona_load_2d(persona.name)
end
end
-- Unloads all 2d personas
--
function m19_unload_personas()
for key, persona in pairs(M19_personas) do
if persona.handle ~= INVALID_PERSONA_HANDLE then
audio_persona_remove_2d(persona.handle)
persona.handle = INVALID_PERSONA_HANDLE
end
end
end
-- Gets the 2d persona handle from a character name
--
function m19_get_persona_handle(line)
for key, persona in pairs(M19_personas) do
if persona.name == line.character then
return persona.handle
end
end
return nil
end
-- Plays a persona line.
--
function m19_play_persona_line(line)
local convo_active = true
while(M19_active_convo ~= "" and convo_active == true) do
convo_active = false
for key, convo in pairs(M19_active_convo.files) do
if (convo.handle ~= nil) then
convo_active = true
end
end
thread_yield()
end
if line.play_2d then
audio_play_persona_line_2d(m19_get_persona_handle(line), line.name)
else
audio_play_persona_line(line.character, line.name)
end
end
-- Play a audio conversation
--
-- convo_table: Table of the audio conversation files to play
--
function m19_audio_thread(convo_table)
M19_active_convo = convo_table
m19_play_convo_set(convo_table)
convo_table.thread = INVALID_THREAD_HANDLE
M19_active_convo = ""
end