| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- -- Route policy reconstructed from the video and authored volume positions.
- return function(m, a)
- local C = {region = 40}
- local steps = {
- {trigger = "READY_ROOM_01_SPAWN_SET_02_PLAYER_TRIGGER_80B3C618", groups = {"ready1_reinforce"}, phase = 1},
- {trigger = "READY_ROOM_01_SPAWN_SET_03_PLAYER_TRIGGER", groups = {"ready1_reinforce"}, phase = 1},
- {trigger = "TUMBLER_ENTRY_PLAYER_TRIGGER", groups = {"tumbler"}, phase = 2},
- {trigger = "DECK_EAST_ENTRY_PLAYER_TRIGGER_80B3C6E8", groups = {"sunburn_east"}, phase = 3, cue = 26},
- {trigger = "DECK_BRIDGE_025_PERCENT_PLAYER_TRIGGER_80B3C6E8", groups = {"sunburn_bridge"}, phase = 4, cue = 27},
- {trigger = "DECK_BRIDGE_100_PERCENT_PLAYER_TRIGGER", groups = {"sunburn_west"}, phase = 5},
- -- The deck exit volume is still outdoors. Preload defenders there, but
- -- begin the indoor checkpoint/dialogue only beyond the far Sunside door.
- {trigger = "DECK_WEST_EXIT_PLAYER_TRIGGER_80B3C6E8", groups = {"ready2_entry"}, phase = 5},
- {trigger = "DIALOG_CINDER_READY_ROOM_02_001_PLAYER_TRIGGER", groups = {"ready2_entry"}, phase = 6, cue = 28},
- {trigger = "READY_ROOM_02_SPAWN_SET_01_PLAYER_TRIGGER", groups = {"ready2_entry"}, phase = 6},
- {trigger = "READY_ROOM_02_SPAWN_SET_02_PLAYER_TRIGGER", groups = {"ready2_reinforce"}, phase = 6},
- {trigger = "READY_ROOM_02_SPAWN_SET_03_PLAYER_TRIGGER", groups = {"ready2_reinforce"}, phase = 6},
- {trigger = "READY_ROOM_02_TO_CHAMBER_PLAYER_TRIGGER_80B3C67D", groups = {"chamber"}, phase = 7, cue = 30},
- {trigger = "CHAMBER_SPAWN_SET_01_PLAYER_TRIGGER", groups = {"chamber"}, phase = 7},
- {trigger = "MEAT_GRINDER_SPAWN_SET_01_PLAYER_TRIGGER", groups = {"meat1"}, phase = 8},
- {trigger = "MEAT_GRINDER_SPAWN_SET_02_PLAYER_TRIGGER", groups = {"meat2"}, phase = 9},
- {trigger = "ASCENT_SPAWN_SET_01_PLAYER_TRIGGER", groups = {"ascent"}, phase = 10, cue = 31},
- {trigger = "OVERLOOK_TO_FOUNDRY_PLAYER_TRIGGER", groups = {"foundry_entry"}, phase = 11, cue = 33},
- {trigger = "FOUNDRY_SPAWN_SET_02_PLAYER_TRIGGER", groups = {"foundry_mid"}, phase = 12},
- {trigger = "FOUNDRY_SPAWN_SET_03_PLAYER_TRIGGER", groups = {"foundry_final"}, phase = 13},
- }
- local extras = {"DECK_EAST_SECRET_PLAYER_TRIGGER", "ASCENT_SPAWN_SET_02_PLAYER_TRIGGER",
- "ASCENT_SPAWN_SET_03_PLAYER_TRIGGER", "ASCENT_SPAWN_SET_04_PLAYER_TRIGGER",
- "CHUTE_FIRST_WINDOW_PLAYER_TRIGGER", "APEX_GOTO_001_DIALOG_PLAYER_TRIGGER",
- "DIALOG_CINDER_SUNBURN_001_PLAYER_TRIGGER", "DIALOG_CINDER_READY_ROOM_02_002_PLAYER_TRIGGER",
- "CINDER_FOUNDRY_001_DIALOG_PLAYER_TRIGGER"}
- local current_groups = {{"ready1_entry", "ready1_reinforce"}, {"tumbler"}, {"sunburn_east"},
- {"sunburn_bridge"}, {"sunburn_west"}, {"ready2_entry", "ready2_reinforce"}, {"chamber"},
- {"meat1"}, {"meat2"}, {"ascent"}, {"foundry_entry", "foundry_mid", "foundry_final"}}
- local function phase(s) return s:variable("ember.cinder.phase") or 0 end
- local function set(c, p) c:set_variable("ember.cinder.phase", p) end
- local function retreat(c, s, area, letter)
- local group = area:lower() .. "_retreat_" .. letter:lower()
- if a.groups[group]:enter(c, s) then a.scene(c, area .. "_SQUAD_RETREAT_INSTANCE_" .. letter .. "_PREFAB_RETREAT_SCENE") end
- end
- local function arm(c, minimum)
- for _, row in ipairs(steps) do if row.phase >= (minimum or 0) then a.slot(c, row.trigger):fire_trigger{} end end
- for _, name in ipairs(extras) do a.slot(c, name):fire_trigger{} end
- end
- local function foundry_doors(c, open, snap)
- for _, name in ipairs({"FOUNDRY_HATCH_DOOR_LEFT_DEVICE", "FOUNDRY_HATCH_DOOR_RIGHT_DEVICE",
- "FOUNDRY_RAMROD_LEFT_DEVICE", "FOUNDRY_RAMROD_RIGHT_DEVICE", "FOUNDRY_WARNING_LIGHT_DEVICE"}) do
- a.device(c, name, open, snap)
- end
- end
- function C.enter(c, s)
- if phase(s) > 0 then return end
- set(c, 1)
- a.objects(c, {"CORE_WEAPON_LASER_BEAM_OBJECT_80B3C22D"}, true)
- a.enable_device(c, "CINDER_CORE_WEAPON_LASER_BEAM_DEVICE")
- -- This is the entrance to Ready Room 1; its defenders are beyond the hatch.
- a.device(c, "TUMBLER_HATCH_DOOR_DEVICE", true)
- a.slot(c, "TUMBLER_HATCH_DOOR_KLAXON_AUDIO_SEQUENCE"):play_sequence{}
- a.device(c, "READY_ROOM_01_WINDOW_CONSOLE_DEVICE", false, true)
- foundry_doors(c, false, true)
- arm(c)
- -- Exact 60/118 volume backing DECK_WHOLE_PLAYER_TRIGGER in 80B3C6E8.
- a.effect(c, s, "DECK_HEAT_SHIMMER_HOP_ON", "FOUNDRY_THERMAL_DOT_OBJECT_FILTER",
- {players = true, inside = a.slot(c, "SLOT_0076_80B3C6E8")}, true)
- for _, name in ipairs({"WEAPON_DOWN", "NO_COMBAT_ABILITIES"}) do
- a.effect(c, s, name .. "_HOP_ON", name .. "_OBJECT_FILTER",
- {players = true, inside = a.slot(c, "TV_CHUTE_MOTION_BLUR_TRIGGER_VOLUME")}, true)
- end
- a.spawn(c, s, {"ready1_entry"})
- a.cue(c, s, 19)
- C.guidance(c, s)
- end
- local function advance(c, s, row)
- local previous = phase(s)
- if row.phase < previous then return end
- -- Spatial fallback catches a skipped narrow volume within this room, never a completed room.
- if row.phase > previous then
- set(c, row.phase)
- if row.phase == 6 then a.checkpoint(c, 40, 0x82328D63, "ready2") end
- if row.phase >= 11 and previous < 11 then a.checkpoint(c, 40, 0x782CAF4C, "foundry") end
- end
- if row.phase == 6 then a.spawn(c, s, {"ready2_entry"}) end
- if row.phase >= 11 and row.phase <= 13 then
- a.spawn(c, s, {"foundry_entry"})
- if row.phase >= 12 then a.spawn(c, s, {"foundry_mid"}) end
- end
- a.spawn(c, s, row.groups)
- if row.phase == 6 then a.darkness(c, s, not a.clear(s, current_groups[6]))
- elseif row.phase >= 11 and row.phase <= 13 then a.darkness(c, s, not a.clear(s, current_groups[11])) end
- if row.cue then a.cue(c, s, row.cue) end
- if row.phase == 3 then
- retreat(c, s, "SUNBURN", "A"); retreat(c, s, "SUNBURN", "B"); retreat(c, s, "SUNBURN", "C")
- end
- end
- function C.trigger(c, s, e)
- for _, row in ipairs(steps) do
- if a.matches(c, e, row.trigger) then
- advance(c, s, row); C.guidance(c, s); return
- end
- end
- if a.matches(c, e, "DECK_EAST_SECRET_PLAYER_TRIGGER") and phase(s) <= 5 then a.spawn(c, s, {"sunburn_secret"}) end
- for index, letter in ipairs({"A", "B", "C"}) do
- if a.matches(c, e, "ASCENT_SPAWN_SET_0" .. (index + 1) .. "_PLAYER_TRIGGER") and phase(s) <= 10 then
- retreat(c, s, "ASCENT", letter)
- end
- end
- if a.matches(c, e, "DIALOG_CINDER_SUNBURN_001_PLAYER_TRIGGER") then a.cue(c, s, 23) end
- if a.matches(c, e, "DIALOG_CINDER_READY_ROOM_02_002_PLAYER_TRIGGER") and phase(s) == 6 then a.cue(c, s, 20) end
- if a.matches(c, e, "CHUTE_FIRST_WINDOW_PLAYER_TRIGGER") and phase(s) >= 14 then a.cue(c, s, 35) end
- if a.matches(c, e, "APEX_GOTO_001_DIALOG_PLAYER_TRIGGER") and phase(s) >= 14 then a.cue(c, s, 36) end
- C.guidance(c, s)
- end
- function C.cleared(c, s, name)
- if name == "ready1_entry" then a.spawn(c, s, {"ready1_reinforce"}) end
- if (name == "ready1_entry" or name == "ready1_reinforce") and a.clear(s, current_groups[1]) then
- a.device(c, "READY_ROOM_01_WINDOW_CONSOLE_DEVICE", true)
- a.spawn(c, s, {"tumbler"})
- end
- if name == "ready2_entry" then a.spawn(c, s, {"ready2_reinforce"}) end
- if (name == "ready2_entry" or name == "ready2_reinforce") and phase(s) == 6 and a.clear(s, current_groups[6]) then a.darkness(c, s, false) end
- if name == "foundry_entry" then a.spawn(c, s, {"foundry_mid"}) end
- if name == "foundry_mid" then a.spawn(c, s, {"foundry_final"}) end
- if phase(s) >= 11 and phase(s) <= 13
- and (name == "foundry_entry" or name == "foundry_mid" or name == "foundry_final")
- and a.clear(s, current_groups[11]) then
- set(c, 14)
- foundry_doors(c, true)
- a.slot(c, "FOUNDRY_HATCH_DOOR_CENTER_KLAXON_AUDIO_SEQUENCE"):play_sequence{}
- a.darkness(c, s, false)
- a.cue(c, s, 34)
- end
- C.guidance(c, s)
- end
- function C.guidance(c, s)
- if s:variable("ember.region") ~= 40 then return end
- local p = phase(s)
- local combat = a.combat(s, current_groups[math.min(p, 11)] or {})
- if p <= 2 then a.directive(c, s, "ECECF63D", "CINDER_DIRECTIVE_SUNBURN_GOTO_NAV_POINT")
- elseif p <= 5 then a.directive(c, s, "D496059B", "CINDER_DIRECTIVE_READY_ROOM_02_GOTO_NAV_POINT")
- elseif p == 6 then a.directive(c, s, combat and "7FF69D75" or "DF93A91C", "CINDER_DIRECTIVE_MEAT_GRINDER_GOTO_NAV_POINT")
- elseif p == 7 then a.directive(c, s, "62E3AEFB", "CINDER_DIRECTIVE_MEAT_GRINDER_GOTO_NAV_POINT")
- elseif p <= 10 then a.directive(c, s, "BAD7D583", "CINDER_DIRECTIVE_FOUNDRY_GOTO_NAV_POINT")
- elseif p <= 13 then a.directive(c, s, "7FF69D75", "FOUNDRY_HATCH_DOOR_CENTER_NAV_POINT")
- else a.directive(c, s, "FF7AB219", "CINDER_DIRECTIVE_CHUTE_GOTO_NAV_POINT") end
- end
- function C.resume(c, s)
- if (s:variable("ember.r.furthest") or 0) > 2 then return end
- local p = phase(s)
- a.darkness(c, s, (p == 6 and not a.clear(s, current_groups[6]))
- or (p >= 11 and p <= 13 and not a.clear(s, current_groups[11])))
- end
- function C.reset(c, s, name)
- local first = name == "ready2" and 6 or 11
- a.reset(c, current_groups[first])
- if first == 11 then foundry_doors(c, false, true) end
- a.slot(c, first == 6 and "EMBER_CINDER_READY_ROOM_02_OBJECTIVE" or "EMBER_CINDER_FOUNDRY_OBJECTIVE"):reset_objectives{}
- set(c, first); arm(c, first)
- a.spawn(c, s, {first == 6 and "ready2_entry" or "foundry_entry"})
- a.darkness(c, s, true)
- c:clear_variable("ember.r.guidance"); C.guidance(c, s)
- end
- return C
- end
|