|
|
@@ -1,2661 +0,0 @@
|
|
|
-╭─── Claude Code v2.1.241 ─────────────────────────────────────────────────────╮
|
|
|
-│ │ Tips for getting │
|
|
|
-│ Welcome back Millie! │ started │
|
|
|
-│ │ Run /init to create a … │
|
|
|
-│ ▐▛███▛█ │ ─────────────────────── │
|
|
|
-│ ▝▜██████▀ │ What's new │
|
|
|
-│ ▝▝ ▝▝ │ Bug fixes and reliabil… │
|
|
|
-│ Opus 5 · Claude Pro · ameliahesketh@pm.me's │ Bug fixes and reliabil… │
|
|
|
-│ Organization │ Cost estimates (`/cost… │
|
|
|
-│ ~/Documents/Sunrise-builds/mission-ember │ /release-notes for more │
|
|
|
-╰──────────────────────────────────────────────────────────────────────────────╯
|
|
|
-
|
|
|
-
|
|
|
-❯ Hi Claude. Please read every markdown file in
|
|
|
- ~/Documents/Sunrise-docs/MissionEmberPlanDocs, then repeat the plan back to
|
|
|
- me, what you're going to change, etc, and I'll give you to go ahead if I'm
|
|
|
- happy with it.
|
|
|
-
|
|
|
-● I'll read all the markdown files in that directory.
|
|
|
-
|
|
|
- Listed 1 directory (ctrl+o to expand)
|
|
|
-
|
|
|
-● Note: Mission_Ember_So_Far.md is 23 MB — I'll read the others in full and
|
|
|
- sample that one strategically.
|
|
|
-
|
|
|
- Read 2 files, ran 10 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Now the transcript. It's a 290k-line Codex conversation log — I'll extract the
|
|
|
- user turns and the tail, which carry the directives.
|
|
|
-
|
|
|
- Read 1 file, ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Now let me verify the repo state matches what the plan describes.
|
|
|
-
|
|
|
- Listed 1 directory, ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● I've read all seven files. Here's the plan back to you.
|
|
|
-
|
|
|
- What I read
|
|
|
-
|
|
|
- Six docs in full: MISSION_EMBER_PLAN.md, MISSION_EMBER_REFERENCE.md,
|
|
|
- MISSION_EMBER_REACTOR.md, MISSION_EMBER_SQUADS.md, MISSION_EMBER_STATUS.md,
|
|
|
- and MISSION_EMBER_FINAL_ISSUES_PLAN.md.
|
|
|
-
|
|
|
- Mission_Ember_So_Far.md is 23 MB / 290k lines — the full Codex transcript. I
|
|
|
- can't hold that in context, so I read its structure and extracted all 136 of
|
|
|
- your turns verbatim, which is where the directives and bug reports live. I
|
|
|
- have not read every agent activity log inside it. If there's something
|
|
|
- specific buried in the agent output you want me to pull, point me at it.
|
|
|
-
|
|
|
- I also verified the repo state matches the handoff doc: HEAD is 50e68b7, tree
|
|
|
- clean apart from the untracked MISSION_EMBER_FINAL_ISSUES_PLAN.md
|
|
|
- (byte-identical to the docs copy), all 16 scripts/mission_ember/*.lua present,
|
|
|
- the game is not running, and the cached evidence survived —
|
|
|
- /tmp/ember-reference/1au.mp4, build/full-mission-audit/, build/reactor-audit/,
|
|
|
- build/reactor-playtest/, and the /tmp/install-ember-*.py installers.
|
|
|
-
|
|
|
- Where the project stands
|
|
|
-
|
|
|
- 1AU (mission_ember) is scripted end to end — opening cinematic, landing,
|
|
|
- catwalk/pipe/Mercury, Harvester dropships with working doors and exit, bridge,
|
|
|
- Processing/refinery, Sunside/cinder, Foundry, Light's End, reactor targets,
|
|
|
- fusion cell, escape. That all works in game and is the regression baseline I
|
|
|
- must not break. What's left is a finale that doesn't finish and a set of
|
|
|
- visual/native behaviours the last patch failed to fix. Critically: the
|
|
|
- previous agent's unit tests all pass and the last install is verified — and
|
|
|
- none of that is gameplay confirmation. I'll treat passing tests as necessary,
|
|
|
- not sufficient.
|
|
|
-
|
|
|
- The eight acceptance criteria
|
|
|
-
|
|
|
- 1. Electron Controllers warp out of the Interceptor room and end up
|
|
|
- unreachable behind the door; both must stay reachable and both deaths must
|
|
|
- open the gate.
|
|
|
- 2. Escape applies shock; it must be fire/scorch.
|
|
|
- 3. The climb pipes toward the fusion-cell deposit must apply that same scorch
|
|
|
- — before deposit, while carrying.
|
|
|
- 4. Beam must shut off after the final cell is deposited.
|
|
|
- 5. Beam must surge with the screen effect before clamshell exposure, not sit
|
|
|
- visually constant.
|
|
|
- 6. Escape explosions must fire progressively as you run it, not all at
|
|
|
- deposit.
|
|
|
- 7. Escape freezes before the ending movies; both must play and complete,
|
|
|
- skippable.
|
|
|
- 8. Objectives flash/re-update constantly without progressing.
|
|
|
-
|
|
|
- What I'd change, in order
|
|
|
-
|
|
|
- 1 — Ending freeze (ending.lua, routes.lua, apex.lua,
|
|
|
- mission_script_runtime_dispatch.cpp, roster publication). The current
|
|
|
- region-49 staging detour was built on a same-bubble-teardown hypothesis and
|
|
|
- still freezes. I'm removing it, not extending it — no more staging states, no
|
|
|
- sleeps. The Omega excerpt says authority receipt and native application are
|
|
|
- separate stages, and application was blocked because allocated global records
|
|
|
- were never seeded. I'll capture requested/current/held region, seed-lease
|
|
|
- revision, publication state, received cinematic authority and applied
|
|
|
- controller state at the failure point; enumerate the allocated global records
|
|
|
- and find which are unseeded; then fix the actual producer in roster
|
|
|
- construction. I will not fabricate zero bodies or globally bypass the
|
|
|
- readiness gate, and I won't copy Omega's record ID or counts. Targets stay
|
|
|
- STATE_80B3C09E_0000_0001_80B3C091/region 1 and ..._0002_80B3C093/region 2.
|
|
|
-
|
|
|
- 2 — Objectives (route_support.lua, landing.lua,
|
|
|
- mission_script_lua_slot_api.cpp, auth codec). Two separate bugs. The republish
|
|
|
- signature is hash .. ':' .. shown, so every navpoint or combat change
|
|
|
- republishes the whole directive — that's the flash. And the type-70 engagement
|
|
|
- audience binding added last patch didn't produce correct progression, so that
|
|
|
- inference is incomplete. I'll log actual outgoing directive
|
|
|
- hash/element/state/lane/audience against native applied HUD entry and
|
|
|
- membership changes, separate objective transitions from navpoint visibility,
|
|
|
- and fix the banner lifecycle. No debounce papering over wrong text.
|
|
|
-
|
|
|
- 3 — Electron Controllers (route_roster.lua, encounter.lua, combat_ai.lua,
|
|
|
- apex.lua). The fixed_tasks={9,10} pin was inferred from task ordering and
|
|
|
- failed in game. I'm dropping that assumption rather than adding another guess,
|
|
|
- capturing live actor position, selected objective/task and candidate areas
|
|
|
- before and after they escape the room, and determining whether the warp is
|
|
|
- objective-driven or a separate actor behaviour. Then constrain it to reachable
|
|
|
- positions. Both deaths — not vehicle boarding, not supports — open
|
|
|
- SECURITY_DOOR_DEVICE. I won't freeze all AI to achieve this.
|
|
|
-
|
|
|
- 4 — Beam (apex.lua:beam()). Position and power on the laser/ring devices both
|
|
|
- failed, so I won't try a third polarity. I'll trace the placed-object effect
|
|
|
- graph and the separate player screen effect from the cached components, verify
|
|
|
- the authority actually lands on the intended placed instance, and match surge
|
|
|
- → pulse → shutter against 23:38–23:45. On final deposit, stop the cycle and
|
|
|
- shut the beam down — current code wrongly opens both devices — while
|
|
|
- preserving escape geometry, and keep it off across a checkpoint restart.
|
|
|
-
|
|
|
- 5 — Hazards and explosions (hazards(), effect filters). Find what actually
|
|
|
- causes shock and identify the real fire/scorch resource by behaviour, not by a
|
|
|
- suggestive slot name. Move the pipe scorch from phase 6 to phase 5 so it's
|
|
|
- live during the carry, restricted to the five narrow hot-pipe volumes (slots
|
|
|
- 3/4/5/6/8 — not slot 7, that's a kill volume), removed on leaving contact. The
|
|
|
- rail-top filter using the whole slot-414 volume is suspect and I'll check it
|
|
|
- before extending it. Then arm the four authored explosion triggers (type31
|
|
|
- slots 105–108 / type60 volumes 242–245) to fire as you reach each section,
|
|
|
- one-shot, instead of dumping both scenes at deposit.
|
|
|
-
|
|
|
- Constraints I'll hold to
|
|
|
-
|
|
|
- Never launch or stop the game — read-only captures only, and I'll confirm it's
|
|
|
- closed before installing. Backup + SHA-verify every install, preserve
|
|
|
- save/settings/SDK. Progress updates at least every minute, no silent stalls.
|
|
|
- Completed areas stay completed on backtracking. Tube deaths stay untouched —
|
|
|
- you withdrew that as noclip. Commit without a co-author tag, no push unless
|
|
|
- you ask. Sandbox has no string.find/match/gmatch/gsub or dump. Budget headroom
|
|
|
- is tight: 233/512 variables, 61/64 intents per callback — I won't crowd more
|
|
|
- into existing callbacks.
|
|
|
-
|
|
|
- One recommendation
|
|
|
-
|
|
|
- Items 1 and 3 are diagnosis-first — I may not be able to fix them without a
|
|
|
- capture from a live run, which is a two-playtest cycle. Items 2, 4 and 5 I can
|
|
|
- implement directly. So I'd suggest one install containing the 2/4/5 fixes
|
|
|
- plus the diagnostics for 1 and 3, you do a single run, and I get both those
|
|
|
- fixes validated and the freeze/warp evidence in one pass. That beats burning a
|
|
|
- playtest on diagnostics alone. If you'd rather I chase the freeze in
|
|
|
- isolation first, say so.
|
|
|
-
|
|
|
- Two things I want to flag honestly: I can't confirm any of this visually
|
|
|
- myself, so every "fixed" I report will be qualified until you've played it;
|
|
|
- and item 1 is the one where I genuinely don't know yet whether the fix is
|
|
|
- small or deep, because the root cause isn't established.
|
|
|
-
|
|
|
- Happy to adjust any of the above — give me the go-ahead when you're ready.
|
|
|
-
|
|
|
-✻ Brewed for 2m 14s
|
|
|
-
|
|
|
-❯ I think you can probably resolve 1 and 3 without live captures, all the
|
|
|
- information you need should already exist in the sdk and/or pkg files. Make a
|
|
|
- backup of everything you touch first incase you break everything, then go
|
|
|
- ahead and execute your plan. Only alert me when all the fixes are done.
|
|
|
-
|
|
|
-● Executing. Starting with a full backup, then working through the five items.
|
|
|
-
|
|
|
- Searched for 1 pattern, ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Backup at build/final-issues-backup-20260906-115511. Now reading the current
|
|
|
- implementation.
|
|
|
-
|
|
|
- Read 1 file, ran 5 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Key finding already: regions 0, 1, 2 share slice_set_index 0, but the staging
|
|
|
- state (region 49) is slice set 48. Let me check the native seeding path.
|
|
|
-
|
|
|
- Searched for 2 patterns, listed 1 directory, ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Strong lead on the freeze. Let me check the roster capacities against actual
|
|
|
- per-region group counts.
|
|
|
- Searched for 1 pattern, listed 1 directory, ran 9 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● refuse_seed logs at debug level, so refusals are invisible in these info-level
|
|
|
- logs. Let me quantify the group counts per region.
|
|
|
-
|
|
|
- Ran 3 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Capacity hypothesis is wrong (37 groups vs 256). Checking the dedup path
|
|
|
- instead — shared object tags across regions 0/1/2.
|
|
|
-
|
|
|
- Searched for 1 pattern, ran 4 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Root cause found. Let me confirm the slice-set vs region-index conflation.
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Confirmed the deadlock. Let me verify the supporting APIs before changing
|
|
|
- anything.
|
|
|
-
|
|
|
- Searched for 1 pattern, ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Item 1 is fully diagnosed. Now investigating items 3–5 from the SDK.
|
|
|
-
|
|
|
- Read 1 file, ran 4 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Trigger volumes carry AABB geometry. This resolves item 5 directly.
|
|
|
-
|
|
|
- Ran 6 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● All configs are already extracted. Let me decode the effect resources.
|
|
|
-
|
|
|
- Ran 6 shell commands (ctrl+o to expand)
|
|
|
-● Identified the scorch resource. Let me check how effect/filter pairing is
|
|
|
- validated natively.
|
|
|
-
|
|
|
- Searched for 4 patterns, ran 8 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Let me try extracting the one missing effect resource to confirm the
|
|
|
- shock/fire identification.
|
|
|
-
|
|
|
- Listed 2 directories (ctrl+o to expand)
|
|
|
-
|
|
|
-● The extractor is available. Pulling the one missing effect resource plus the
|
|
|
- AI task-area data I need for item 3.
|
|
|
-
|
|
|
- Ran 6 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Now item 3 — parsing the access objective's task groups.
|
|
|
-
|
|
|
- Ran 9 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Let me confirm the room geometry from the authored trigger volumes.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Item 3 confirmed by geometry. Now the beam surge — looking for authored
|
|
|
- sequences and screen effects.
|
|
|
-
|
|
|
- Ran 3 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Now item 2 — the HUD directives. Let me inspect the authored directive data
|
|
|
- and the native encoder.
|
|
|
-
|
|
|
- Searched for 2 patterns, ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● I have all five diagnosed. Reading the last two modules before editing.
|
|
|
-
|
|
|
- Read 1 file (ctrl+o to expand)
|
|
|
-● All five items diagnosed from the SDK and packages. Now implementing. Starting
|
|
|
- with the native ending-freeze fixes.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Update(Sunrise/src/server/bap/bap_route.cpp)
|
|
|
- ⎿ Added 10 lines, removed 2 lines
|
|
|
- 1128 }
|
|
|
- 1129 lease.registeredRegions[lease.registeredRegio
|
|
|
- nCount++] = plan.effectiveRegion;
|
|
|
- 1130 }
|
|
|
- 1131 - // A region change replaces the instantiated worl
|
|
|
- -d. Publications keep answering the
|
|
|
- 1131 + // A SLICE-SET change replaces the instantiated w
|
|
|
- +orld. Publications keep answering the
|
|
|
- 1132 // previous plan until the client's post-arrival
|
|
|
- solicited answer advances the region
|
|
|
- 1133 // epoch, because registering the new region's gr
|
|
|
- oups mid-teardown races the teardown.
|
|
|
- 1134 - if (lease.configured && lease.plan.effectiveRegio
|
|
|
- -n != plan.effectiveRegion) {
|
|
|
- 1134 + //
|
|
|
- 1135 + // An authored region is `sliceSetIndex + stateOr
|
|
|
- +dinal`, so sibling states share one
|
|
|
- 1136 + // slice set: Ember's apex gameplay (0) and both
|
|
|
- +ending bookends (1, 2) are all slice
|
|
|
- 1137 + // set 0. Moving between them instantiates nothin
|
|
|
- +g new, and the client's current region
|
|
|
- 1138 + // leg only advances on an actual slice-set switc
|
|
|
- +h. Waiting for an arrival there is a
|
|
|
- 1139 + // deadlock: the roster withholds the new region'
|
|
|
- +s groups forever and the client never
|
|
|
- 1140 + // finishes synchronizing. Only a real slice-set
|
|
|
- +change opens the arrival window.
|
|
|
- 1141 + if (lease.configured && lease.plan.effectiveRegio
|
|
|
- +n != plan.effectiveRegion
|
|
|
- 1142 + && lease.plan.sliceSetIndex != plan.sliceSetI
|
|
|
- +ndex) {
|
|
|
- 1143 lease.previousPlan = lease.plan;
|
|
|
- 1144 lease.regionArrivalPending = true;
|
|
|
- 1145 }
|
|
|
-
|
|
|
-● Now the teleport arming fix:
|
|
|
-
|
|
|
-● Update(Sunrise/src/server/activity/mission/mission_script_runtime_dispatch.cpp
|
|
|
- )
|
|
|
- ⎿ Added 13 lines
|
|
|
- 212 instance.view.binding.sessionId, membership::kAbse
|
|
|
- ntSliceSetIndex, 0));
|
|
|
- 213 return;
|
|
|
- 214 }
|
|
|
- 215 + // A region is `sliceSetIndex + stateOrdinal`, so a siblin
|
|
|
- +g state sits in the slice set the
|
|
|
- 216 + // client already holds and there is nothing to transition
|
|
|
- + to. Arming anyway hands the client
|
|
|
- 217 + // a slice-set index that is not a slice set (region 1 wit
|
|
|
- +h slice set 0's name hash), and it
|
|
|
- 218 + // starts a teleportation it can never finish. Clear the a
|
|
|
- +rm and let the roster publish the
|
|
|
- 219 + // new state's groups into the world that is already stand
|
|
|
- +ing.
|
|
|
- 220 + const std::int32_t heldSliceSet =
|
|
|
- 221 + membership::reported_slice_set(instance.view.binding.s
|
|
|
- +essionId);
|
|
|
- 222 + if (heldSliceSet >= 0 && heldSliceSet == static_cast<std::
|
|
|
- +int32_t>(plan.sliceSetIndex)) {
|
|
|
- 223 + static_cast<void>(membership::arm_host_teleport(
|
|
|
- 224 + instance.view.binding.sessionId, membership::kAbse
|
|
|
- +ntSliceSetIndex, 0));
|
|
|
- 225 + log_line(core::log::Level::info, &instance, "state_reg
|
|
|
- +ion", "teleport_not_required");
|
|
|
- 226 + return;
|
|
|
- 227 + }
|
|
|
- 228 const std::string_view name(reinterpret_cast<const char*>(
|
|
|
- destination.packageName.data()),
|
|
|
- 229 destination.packageNameLength)
|
|
|
- ;
|
|
|
- 230 ::sunrise::state::build_data::scenarios::Definition layout
|
|
|
- {};
|
|
|
- ⎿ Found 1 new diagnostic issue in 1 file (ctrl+o to expand)
|
|
|
-
|
|
|
-● Update(Sunrise/src/server/bap/encrypted/push/activity/activity_mission_seed_ro
|
|
|
- ster.cpp)
|
|
|
- ⎿ Added 3 lines, removed 1 line
|
|
|
- 28 static_cast<int>(reason.s
|
|
|
- ize()),
|
|
|
- 29 reason.data());
|
|
|
- 30 if (written > 0) {
|
|
|
- 31 + // A refusal strands the selected state: its records ar
|
|
|
- +e never seeded and the client waits
|
|
|
- 32 + // for content that never arrives. That is not a debug
|
|
|
- +detail, so it is reported at warn.
|
|
|
- 33 core::log::write(core::log::Channel::server,
|
|
|
- 32 - core::log::Level::debug,
|
|
|
- 34 + core::log::Level::warn,
|
|
|
- 35 {line.data(), static_cast<std::size_t>
|
|
|
- (written)});
|
|
|
- 36 }
|
|
|
- 37 return MissionSeedRosterResult::refused;
|
|
|
- ⎿ Found 4 new diagnostic issues in 1 file (ctrl+o to expand)
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
- ⎿ Found 3 new diagnostic issues in 1 file (ctrl+o to expand)
|
|
|
-
|
|
|
-● Now the Lua side. Let me check how the root controller derives region state.
|
|
|
-
|
|
|
- Searched for 2 patterns, read 1 file, ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Now rewriting ending.lua to drop the staging detour:
|
|
|
-
|
|
|
-● Write(scripts/mission_ember/ending.lua)
|
|
|
- ⎿ Added 23 lines, removed 23 lines
|
|
|
- 1 --- Authored post-escape cinematic regions; exact native complet
|
|
|
- -ion/skip incidents advance once.
|
|
|
- 1 +-- Authored post-escape cinematic states; exact native completi
|
|
|
- +on/skip incidents advance once.
|
|
|
- 2 +--
|
|
|
- 3 +-- An authored region is `sliceSetIndex + stateOrdinal`, so ape
|
|
|
- +x gameplay (region 0) and both
|
|
|
- 4 +-- ending bookends (regions 1 and 2) are sibling states of one
|
|
|
- +slice set. Selecting a bookend
|
|
|
- 5 +-- instantiates no new world: the client keeps the slice set it
|
|
|
- + already holds and never reports
|
|
|
- 6 +-- a new held region, so this must not wait for one. The earlie
|
|
|
- +r region-49 staging detour forced
|
|
|
- 7 +-- a cross-slice-set round trip to manufacture that report and
|
|
|
- +stalled instead.
|
|
|
- 8 +--
|
|
|
- 9 +-- The selection intent completes only once its own roster revi
|
|
|
- +sion publishes, and intents are
|
|
|
- 10 +-- dispatched in order, so the activation queued on a later cal
|
|
|
- +lback always follows the seed.
|
|
|
- 11 return function(m)
|
|
|
- 12 local movies = {
|
|
|
- 13 {state = m.states.STATE_80B3C09E_0000_0001_80B3C091, sl
|
|
|
- ot = m.Slot.PF_CINEMATIC_BOOKEND_STM_CINEMATIC},
|
|
|
- 14 {state = m.states.STATE_80B3C09E_0000_0002_80B3C093, sl
|
|
|
- ot = m.Slot.PF_CINEMATIC_BOOKEND_CNN_CINEMATIC},
|
|
|
- 15 }
|
|
|
- 16 local E = {}
|
|
|
- 8 - local staging = assert(m.states.STATE_80B3C09E_0006_0001_80
|
|
|
- -B3C09A)
|
|
|
- 9 - local function transit(c)
|
|
|
- 10 - c:set_variable("ember.ending.transit", true)
|
|
|
- 11 - c:select_state(staging)
|
|
|
- 12 - end
|
|
|
- 17 local music = require("mission_ember.music")(m)
|
|
|
- 18 + local function select_movie(c, index)
|
|
|
- 19 + c:set_variable("ember.ending", index)
|
|
|
- 20 + c:set_variable("ember.ending.selected", index)
|
|
|
- 21 + c:select_state(assert(movies[index].state))
|
|
|
- 22 + end
|
|
|
- 23 function E.start(c, s)
|
|
|
- 24 if s:variable("ember.ending") then return end
|
|
|
- 16 - c:set_variable("ember.ending", 1)
|
|
|
- 25 music.update(c, s)
|
|
|
- 18 - transit(c)
|
|
|
- 26 + select_movie(c, 1)
|
|
|
- 27 end
|
|
|
- 28 function E.client(c, s, e)
|
|
|
- 29 local index = s:variable("ember.ending")
|
|
|
- 30 local row = index and movies[index]
|
|
|
- 23 - if not row or s:variable("ember.ending.playing") == ind
|
|
|
- -ex then return end
|
|
|
- 24 - local held = e.held_region_index or e.current_region_in
|
|
|
- -dex
|
|
|
- 25 - if s:variable("ember.ending.transit") then
|
|
|
- 26 - if held == staging.region_index then
|
|
|
- 27 - c:clear_variable("ember.ending.transit")
|
|
|
- 28 - c:select_state(row.state)
|
|
|
- 29 - end
|
|
|
- 30 - return
|
|
|
- 31 - end
|
|
|
- 32 - if held == row.state.region_index then
|
|
|
- 33 - c:set_variable("ember.ending.playing", index)
|
|
|
- 34 - c:slot(assert(row.slot)):set_cinematic_active{activ
|
|
|
- -e = true}
|
|
|
- 35 - end
|
|
|
- 31 + -- Activate on a callback after the selection, never in
|
|
|
- + the one that requested it.
|
|
|
- 32 + if not row or s:variable("ember.ending.selected") ~= in
|
|
|
- +dex
|
|
|
- 33 + or s:variable("ember.ending.playing") == index then
|
|
|
- + return end
|
|
|
- 34 + c:set_variable("ember.ending.playing", index)
|
|
|
- 35 + c:slot(assert(row.slot)):set_cinematic_active{active =
|
|
|
- +true}
|
|
|
- 36 end
|
|
|
- 37 function E.terminated(c, s, e)
|
|
|
- 38 local index = s:variable("ember.ending")
|
|
|
- ...
|
|
|
- 40 if not row or s:variable("ember.ending.playing") ~= ind
|
|
|
- ex then return end
|
|
|
- 41 local slot = c:slot(row.slot)
|
|
|
- 42 if e.registry_key ~= slot.registry_key or e.slot_type ~
|
|
|
- = slot.slot_type or e.slot_index ~= slot.slot_index then return
|
|
|
- end
|
|
|
- 43 - c:set_variable("ember.ending", index + 1)
|
|
|
- 43 slot:set_cinematic_active{active = false}
|
|
|
- 45 - if movies[index + 1] then transit(c)
|
|
|
- 44 + if movies[index + 1] then select_movie(c, index + 1)
|
|
|
- 45 else
|
|
|
- 46 + c:set_variable("ember.ending", index + 1)
|
|
|
- 47 c:set_variable("ember.complete", true)
|
|
|
- 48 -- Native lifetime 6 enters the completion/reward b
|
|
|
- ranch (BEA9D0/B37100).
|
|
|
- 49 c.lifetime:set{state = c.sdk.lifetime_states:at(6)}
|
|
|
-
|
|
|
-● Now item 2 — the flashing HUD directives:
|
|
|
-
|
|
|
-● Update(scripts/mission_ember/route_support.lua)
|
|
|
- ⎿ Added 8 lines, removed 1 line
|
|
|
- 99 c:set_variable("ember.checkpoint.hash", hash)
|
|
|
- 100 c:set_variable("ember.checkpoint.name", name)
|
|
|
- 101 end
|
|
|
- 102 + -- Each authored directive carries both HUD lines: `title`
|
|
|
- + is the main objective and
|
|
|
- 103 + -- `description` the sub-objective, so the banner advances
|
|
|
- + by selecting a new element.
|
|
|
- 104 + -- Native type-68 state 0 ENTERS the directive, and the Lu
|
|
|
- +a surface always publishes it,
|
|
|
- 105 + -- so every republication replays the banner's entry anima
|
|
|
- +tion. Republishing whenever the
|
|
|
- 106 + -- navpoint changed therefore made the objective flash on
|
|
|
- +each combat transition while its
|
|
|
- 107 + -- text stayed put. The directive is now keyed on its elem
|
|
|
- +ent alone and carries one stable
|
|
|
- 108 + -- navpoint, so the body changes only at a real milestone
|
|
|
- +and enters exactly once there.
|
|
|
- 109 function api.directive(c, s, hash, marker, combat)
|
|
|
- 110 local rank = ({[56] = 1, [40] = 2, [0] = 3})[s:variabl
|
|
|
- e("ember.region")] or 0
|
|
|
- 111 if rank < (s:variable("ember.r.furthest") or 0) then r
|
|
|
- eturn end
|
|
|
- 112 music.update(c, s)
|
|
|
- 106 - local shown = combat and "" or (marker or "")
|
|
|
- 113 + local shown = marker or ""
|
|
|
- 114 local signature = hash .. ":" .. shown
|
|
|
- 115 if s:variable("ember.r.guidance") == signature then re
|
|
|
- turn end
|
|
|
- 116 local binding = assert(directives[hash], "missing auth
|
|
|
- ored directive " .. hash)
|
|
|
-
|
|
|
- Searched for 2 patterns, ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● All 17 call sites updated. Now item 3 — the Electron Controllers' objective:
|
|
|
-
|
|
|
-● Update(scripts/mission_ember/route_roster.lua)
|
|
|
- ⎿ Added 10 lines, removed 2 lines
|
|
|
- 29 {name = "foundry_final", region = 40, objective = "EMBER_CI
|
|
|
- NDER_FOUNDRY_OBJECTIVE", task_groups = 16, squads = {"FOUNDRY_A
|
|
|
- NCHOR_A_SQUAD", "FOUNDRY_SUPPORT_G_SQUAD", "FOUNDRY_SUPPORT_H_S
|
|
|
- QUAD", "FOUNDRY_SUPPORT_I_SQUAD"}},
|
|
|
- 30 {name = "access1", region = 0, objective = "EMBER_APEX_ACCE
|
|
|
- SS_OBJECTIVE", task_groups = 14, squads = {"ACCESS_JUMP_ONE_SUP
|
|
|
- PORT_A_SQUAD", "ACCESS_JUMP_ONE_SUPPORT_B_SQUAD", "ACCESS_JUMP_
|
|
|
- ONE_SUPPORT_C_SQUAD"}},
|
|
|
- 31 {name = "access2", region = 0, objective = "EMBER_APEX_ACCE
|
|
|
- SS_OBJECTIVE", task_groups = 14, squads = {"ACCESS_JUMP_TWO_SUP
|
|
|
- PORT_A_SQUAD", "ACCESS_JUMP_TWO_SUPPORT_B_SQUAD", "ACCESS_JUMP_
|
|
|
- TWO_SUPPORT_C_SQUAD"}},
|
|
|
- 32 - {name = "electron_controllers", region = 0, objective = "EM
|
|
|
- -BER_APEX_ACCESS_OBJECTIVE", task_groups = 14, fixed_tasks = {9,
|
|
|
- - 10}, squads = {"DISPENSER_SUPPORT_A_SQUAD", "DISPENSER_SUPPORT
|
|
|
- -_B_SQUAD"}},
|
|
|
- 33 - {name = "dispenser", region = 0, objective = "EMBER_APEX_AC
|
|
|
- -CESS_OBJECTIVE", task_groups = 14, squads = {"DISPENSER_SUPPORT
|
|
|
- -_C_SQUAD"}},
|
|
|
- 32 + -- The dispenser squads hold the security room, not the acc
|
|
|
- +ess approach. Their authored
|
|
|
- 33 + -- anchors (-363,2643,181.5) and (-360,2645,181.5) are both
|
|
|
- + inside
|
|
|
- 34 + -- `security_center_player_trigger` (-387..-344.5, 2639.5..
|
|
|
- +2662, 177..197), while every
|
|
|
- 35 + -- access volume lies east of x=-331 (jump one -331..-312,
|
|
|
- +jump two -256.5..-224, inner
|
|
|
- 36 + -- door -224..-174). Under the access objective the native
|
|
|
- +task selector pulled the two
|
|
|
- 37 + -- Electron Controllers out to those eastern areas -- throu
|
|
|
- +gh the security door and out of
|
|
|
- 38 + -- reach. No access task group could hold them, so pinning
|
|
|
- +a pair of them never could work.
|
|
|
- 39 + -- The security objective owns this room, so they keep thei
|
|
|
- +r own cost-selected tasks here.
|
|
|
- 40 + {name = "electron_controllers", region = 0, objective = "EM
|
|
|
- +BER_APEX_SECURITY_OBJECTIVE", task_groups = 7, squads = {"DISPE
|
|
|
- +NSER_SUPPORT_A_SQUAD", "DISPENSER_SUPPORT_B_SQUAD"}},
|
|
|
- 41 + {name = "dispenser", region = 0, objective = "EMBER_APEX_SE
|
|
|
- +CURITY_OBJECTIVE", task_groups = 7, squads = {"DISPENSER_SUPPOR
|
|
|
- +T_C_SQUAD"}},
|
|
|
- 42 {name = "security", region = 0, objective = "EMBER_APEX_SEC
|
|
|
- URITY_OBJECTIVE", task_groups = 7, squads = {"SECURITY_LEDGE_SU
|
|
|
- PPORT_A_SQUAD", "SECURITY_LEDGE_SUPPORT_B_SQUAD"}},
|
|
|
- 43 {name = "reactor_east_entry", region = 0, objective = "EMBE
|
|
|
- R_APEX_REACTOR_CLAMSHELL_EAST_OBJECTIVE", task_groups = 19, squ
|
|
|
- ads = {"REACTOR_CLAMSHELL_EAST_DEFENSE_A_SQUAD", "REACTOR_CLAMS
|
|
|
- HELL_EAST_SUPPORT_A_SQUAD", "REACTOR_CLAMSHELL_EAST_SUPPORT_B_S
|
|
|
- QUAD"}},
|
|
|
- 44 {name = "reactor_east_reinforce", region = 0, objective = "
|
|
|
- EMBER_APEX_REACTOR_CLAMSHELL_EAST_OBJECTIVE", task_groups = 19,
|
|
|
- squads = {"REACTOR_CLAMSHELL_EAST_DEFENSE_B_SQUAD", "REACTOR_C
|
|
|
- LAMSHELL_EAST_MELEE_A_SQUAD", "REACTOR_CLAMSHELL_EAST_MELEE_B_S
|
|
|
- QUAD", "REACTOR_CLAMSHELL_EAST_SUPPORT_C_SQUAD", "REACTOR_CLAMS
|
|
|
- HELL_EAST_SUPPORT_D_SQUAD"}},
|
|
|
-
|
|
|
-● Let me check fire_trigger and scene:activate semantics before wiring the
|
|
|
- explosions.
|
|
|
-
|
|
|
- Searched for 4 patterns, ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● fire_trigger arms the authored trigger (the escape dialogue cues rely on that
|
|
|
- today). Now editing apex.lua for items 4 and 5:
|
|
|
-● Update(scripts/mission_ember/apex.lua)
|
|
|
- ⎿ Added 32 lines, removed 11 lines
|
|
|
- 41 end
|
|
|
- 42 a.device(c, "REACTOR_SHIELD_DEVICE", open, snap)
|
|
|
- 43 end
|
|
|
- 44 + -- The three placed ring objects carry the beam's own autho
|
|
|
- +red effect graphs; the two
|
|
|
- 45 + -- devices are its mechanical lanes. Holding all three obje
|
|
|
- +cts active for the whole fight
|
|
|
- 46 + -- is what made the beam look constant, so the surge is tho
|
|
|
- +se authored objects coming up
|
|
|
- 47 + -- with their devices at the warning and going dark again a
|
|
|
- +t recovery.
|
|
|
- 48 + local ring_objects = {"SPECOPS_APEX_RING_LASER_OBJECT", "SP
|
|
|
- +ECOPS_APEX_RING_CORE_OBJECT",
|
|
|
- 49 + "SPECOPS_APEX_RING_RING_OBJECT"}
|
|
|
- 50 local function beam(c, active, snap)
|
|
|
- 45 - -- Both devices address the placed ring/laser objects a
|
|
|
- -nd their native VFX graphs.
|
|
|
- 51 + a.objects(c, ring_objects, active)
|
|
|
- 52 a.device(c, "SPECOPS_APEX_RING_LASER_DEVICE", active, s
|
|
|
- nap)
|
|
|
- 53 a.device(c, "SPECOPS_APEX_RING_RING_DEVICE", active, sn
|
|
|
- ap)
|
|
|
- 54 -- FX power is independent of mechanical position; puls
|
|
|
- e both authored graphs.
|
|
|
- 55 lane(c, "SPECOPS_APEX_RING_LASER_DEVICE", active and "p
|
|
|
- ower_on" or "power_off", snap)
|
|
|
- 56 lane(c, "SPECOPS_APEX_RING_RING_DEVICE", active and "po
|
|
|
- wer_on" or "power_off", snap)
|
|
|
- 57 end
|
|
|
- 52 - local function hazards(c, s, enabled)
|
|
|
- 53 - a.effect(c, s, "REACTOR_MOTHER_BRAIN_HOT_PIPES_THERMAL_
|
|
|
- -HOP_ON",
|
|
|
- 54 - "REACTOR_MOTHER_BRAIN_HOT_PIPES_OBJECT_FILTER_80B3C
|
|
|
- -09F",
|
|
|
- 55 - {players = true, inside_any = {
|
|
|
- 56 - a.slot(c, "REACTOR_MOTHER_BRAIN_HOT_PIPES_02_TR
|
|
|
- -IGGER_VOLUME"),
|
|
|
- 57 - a.slot(c, "REACTOR_MOTHER_BRAIN_HOT_PIPES_03_TR
|
|
|
- -IGGER_VOLUME"),
|
|
|
- 58 - a.slot(c, "SLOT_0005_80B3C09F"), a.slot(c, "SLO
|
|
|
- -T_0006_80B3C09F"),
|
|
|
- 59 - a.slot(c, "SLOT_0008_80B3C09F")}}, enabled)
|
|
|
- 60 - a.effect(c, s, "AOD_REACTOR_RAIL_TOP_HOP_ON", "AOD_REAC
|
|
|
- -TOR_RAIL_TOP_OBJECT_FILTER",
|
|
|
- 61 - {players = true, inside = a.slot(c, "SLOT_019E")},
|
|
|
- -enabled)
|
|
|
- 58 + -- `REACTOR_COFFIN_INTERIOR_THERMAL_HOP_ON` and `FOUNDRY_TH
|
|
|
- +ERMAL_DOT_HOP_ON` both reference
|
|
|
- 59 + -- effect resource 80C1D9E0 -- the burn already working in
|
|
|
- +the Foundry. The hot-pipe and
|
|
|
- 60 + -- rail-top hop-ons carry 80B82484 and 80C1D389 instead, wh
|
|
|
- +ich is why contact read as a
|
|
|
- 61 + -- shock rather than a scorch. Apex drives the one authored
|
|
|
- + scorch for both hazards and
|
|
|
- 62 + -- swaps only its filter, so the climb and the escape share
|
|
|
- + the same effect. A new revision
|
|
|
- 63 + -- removes the previous attachment (native 9EF8A0/9F1F10) b
|
|
|
- +efore attaching the new filter.
|
|
|
- 64 + local function rail_filter(c) return {players = true, insid
|
|
|
- +e = a.slot(c, "SLOT_019E")} end
|
|
|
- 65 + local function hazards(c, s, mode)
|
|
|
- 66 + if mode == "climb" then
|
|
|
- 67 + -- The five narrow authored pipe volumes on the way
|
|
|
- + up to the deposit. Slot 7 is a
|
|
|
- 68 + -- broad kill volume well below the walkable route
|
|
|
- +and is deliberately not a pipe.
|
|
|
- 69 + a.effect(c, s, "REACTOR_COFFIN_INTERIOR_THERMAL_HOP
|
|
|
- +_ON",
|
|
|
- 70 + "REACTOR_MOTHER_BRAIN_HOT_PIPES_OBJECT_FILTER_8
|
|
|
- +0B3C21C",
|
|
|
- 71 + {players = true, inside_any = {
|
|
|
- 72 + a.slot(c, "REACTOR_MOTHER_BRAIN_HOT_PIPES_0
|
|
|
- +2_TRIGGER_VOLUME"),
|
|
|
- 73 + a.slot(c, "REACTOR_MOTHER_BRAIN_HOT_PIPES_0
|
|
|
- +3_TRIGGER_VOLUME"),
|
|
|
- 74 + a.slot(c, "SLOT_0005_80B3C09F"), a.slot(c,
|
|
|
- +"SLOT_0006_80B3C09F"),
|
|
|
- 75 + a.slot(c, "SLOT_0008_80B3C09F")}}, true)
|
|
|
- 76 + elseif mode == "escape" then
|
|
|
- 77 + a.effect(c, s, "REACTOR_COFFIN_INTERIOR_THERMAL_HOP
|
|
|
- +_ON",
|
|
|
- 78 + "AOD_REACTOR_RAIL_TOP_OBJECT_FILTER", rail_filt
|
|
|
- +er(c), true)
|
|
|
- 79 + else
|
|
|
- 80 + a.effect(c, s, "REACTOR_COFFIN_INTERIOR_THERMAL_HOP
|
|
|
- +_ON",
|
|
|
- 81 + "AOD_REACTOR_RAIL_TOP_OBJECT_FILTER", rail_filt
|
|
|
- +er(c), false)
|
|
|
- 82 + end
|
|
|
- 83 end
|
|
|
- 84 local function doors(c, side, open, snap)
|
|
|
- 85 for _, part in ipairs({"DOOR_A", "DOOR_B", "LIGHT_A", "
|
|
|
- LIGHT_B", "TARGET"}) do
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Now the deposit callback — beam shutdown and progressive explosions:
|
|
|
-
|
|
|
-● Update(scripts/mission_ember/apex.lua)
|
|
|
- ⎿ Added 6 lines, removed 4 lines
|
|
|
- 157 a.device(c, "MOTHER_BRAIN_ENGINE_RIGHT_DEVICE", tr
|
|
|
- ue)
|
|
|
- 158 a.device(c, "REACTOR_GETAWAY_SHIP_DEVICE", true)
|
|
|
- 159 a.objects(c, {"REACTOR_GETAWAY_SHIP_OBJECT", "SUNB
|
|
|
- URN_DAMAGE_OBJECT"}, true)
|
|
|
- 160 - a.device(c, "SPECOPS_APEX_RING_LASER_DEVICE", true
|
|
|
- -)
|
|
|
- 161 - a.device(c, "SPECOPS_APEX_RING_RING_DEVICE", true)
|
|
|
- 160 + -- The weapon is dead once the cell is in: the bea
|
|
|
- +m shuts down and stays down,
|
|
|
- 161 + -- including across an escape checkpoint restart.
|
|
|
- +The previous code opened both
|
|
|
- 162 + -- devices here, which left it running through the
|
|
|
- + whole escape.
|
|
|
- 163 + beam(c, false, true)
|
|
|
- 164 + c:cancel_timer(vent_timer(s))
|
|
|
- 165 a.scene(c, "MOTHER_BRAIN_HOLE_EXPLOSION_SCENE")
|
|
|
- 163 - a.scene(c, "EMBER_APEX_EXPLOSION_SEQUENCE_PREFAB_T
|
|
|
- -RIGGERED_EXPLOSIONS_SCENE")
|
|
|
- 164 - for _, name in ipairs(escape_triggers) do a.slot(c
|
|
|
- -, name):fire_trigger{} end
|
|
|
- 166 + arm_escape(c)
|
|
|
- 167 a.cue(c, s, 51); A.guidance(c, s)
|
|
|
- 168 end)
|
|
|
- 169 function A.enter(c, s)
|
|
|
-
|
|
|
-● Update(scripts/mission_ember/apex.lua)
|
|
|
- ⎿ Added 9 lines
|
|
|
- 16 local escape_triggers = {"APEX_MOTHER_BRAIN_005_DIALOG_PLAY
|
|
|
- ER_TRIGGER", "APEX_MOTHER_BRAIN_006_DIALOG_PLAYER_TRIGGER",
|
|
|
- 17 "APEX_MOTHER_BRAIN_007_DIALOG_PLAYER_TRIGGER", "APEX_MO
|
|
|
- THER_BRAIN_008_DIALOG_PLAYER_TRIGGER",
|
|
|
- 18 "APEX_DIRECTIVE_REACTOR_RAILS_ESCAPE_PLAYER_TRIGGER"}
|
|
|
- 19 + -- The authored explosion prefab's four player triggers, we
|
|
|
- +st to east along the rails:
|
|
|
- 20 + -- set A x -448.75..-438.75, B -403.75..-393.75, C -368.75.
|
|
|
- +.-358.75, D -323.75..-313.75,
|
|
|
- 21 + -- all spanning y 2967..3002.5 and z 185..212.5. They were
|
|
|
- +never armed, so the sequence
|
|
|
- 22 + -- had nothing to advance it and everything the scene did h
|
|
|
- +appened at the deposit.
|
|
|
- 23 + local explosion_triggers = {}
|
|
|
- 24 + for _, set in ipairs({"A", "B", "C", "D"}) do
|
|
|
- 25 + explosion_triggers[#explosion_triggers + 1] =
|
|
|
- 26 + "EMBER_APEX_EXPLOSION_SEQUENCE_PREFAB_EXPLOSION_SET
|
|
|
- +_" .. set .. "_PLAYER_TRIGGER"
|
|
|
- 27 + end
|
|
|
- 28 local function phase(s) return s:variable("ember.apex.phase
|
|
|
- ") or 0 end
|
|
|
- 29 local function set(c, p) c:set_variable("ember.apex.phase",
|
|
|
- p) end
|
|
|
- 30 local function generation(s) return s:variable("ember.apex.
|
|
|
- generation") or 1 end
|
|
|
-
|
|
|
-● Update(scripts/mission_ember/apex.lua)
|
|
|
- ⎿ Added 7 lines
|
|
|
- 90 "AOD_REACTOR_RAIL_TOP_OBJECT_FILTER", rail_fil
|
|
|
- ter(c), false)
|
|
|
- 91 end
|
|
|
- 92 end
|
|
|
- 93 + -- Activate the authored explosion scene once, then arm it
|
|
|
- +s own four progress triggers
|
|
|
- 94 + -- alongside the escape dialogue volumes so each section d
|
|
|
- +etonates as the player reaches it.
|
|
|
- 95 + local function arm_escape(c)
|
|
|
- 96 + a.scene(c, "EMBER_APEX_EXPLOSION_SEQUENCE_PREFAB_TRIGG
|
|
|
- +ERED_EXPLOSIONS_SCENE")
|
|
|
- 97 + for _, name in ipairs(explosion_triggers) do a.slot(c,
|
|
|
- + name):fire_trigger{} end
|
|
|
- 98 + for _, name in ipairs(escape_triggers) do a.slot(c, na
|
|
|
- +me):fire_trigger{} end
|
|
|
- 99 + end
|
|
|
- 100 local function doors(c, side, open, snap)
|
|
|
- 101 for _, part in ipairs({"DOOR_A", "DOOR_B", "LIGHT_A",
|
|
|
- "LIGHT_B", "TARGET"}) do
|
|
|
- 102 local name = "REACTOR_CLAMSHELL_" .. side .. "_" .
|
|
|
- . part .. "_DEVICE"
|
|
|
-
|
|
|
-● Now removing the always-on ring objects from A.enter and updating the
|
|
|
- timer/reset/resume paths:
|
|
|
-
|
|
|
-● Update(scripts/mission_ember/apex.lua)
|
|
|
- ⎿ Added 1 line, removed 2 lines
|
|
|
- 194 a.device(c, "ACCESS_DOOR_OUTER_DEVICE", true)
|
|
|
- 195 a.device(c, "SECURITY_DOOR_DEVICE", false, true)
|
|
|
- 196 a.slot(c, "SECURITY_PLACED_INTERCEPTOR_OBJECT"):set_in
|
|
|
- teractable_object{generation = 1}
|
|
|
- 197 - a.objects(c, {"SPECOPS_APEX_RING_LASER_OBJECT",
|
|
|
- 198 - "SPECOPS_APEX_RING_CORE_OBJECT", "SPECOPS_APEX_RIN
|
|
|
- -G_RING_OBJECT"}, true)
|
|
|
- 197 + -- The ring objects are not activated here: `beam()` o
|
|
|
- +wns them so they can surge.
|
|
|
- 198 for _, side in ipairs(sides) do
|
|
|
- 199 doors(c, side, false, true)
|
|
|
- 200 a.device(c, "CLAMSHELL_PIPES_" .. side .. "_DEVICE
|
|
|
- ", false, true)
|
|
|
-
|
|
|
-● Update(scripts/mission_ember/apex.lua)
|
|
|
- ⎿ Added 6 lines, removed 1 line
|
|
|
- 296 end
|
|
|
- 297 function A.timer(c, s, e)
|
|
|
- 298 if e.timer_name == "ember.apex.hazards" then
|
|
|
- 299 - if phase(s) == 6 and s:variable("ember.region") ==
|
|
|
- - 0 then hazards(c, s, true) end
|
|
|
- 299 + -- The climb pipes burn while the cell is being ca
|
|
|
- +rried up (phase 5), well before
|
|
|
- 300 + -- the deposit; the rail top burns during the esca
|
|
|
- +pe (phase 6).
|
|
|
- 301 + if s:variable("ember.region") == 0 then
|
|
|
- 302 + if phase(s) == 5 then hazards(c, s, "climb")
|
|
|
- 303 + elseif phase(s) == 6 then hazards(c, s, "escap
|
|
|
- +e") end
|
|
|
- 304 + end
|
|
|
- 305 return true
|
|
|
- 306 end
|
|
|
- 307 if carry.timer(c, s, e) then return true end
|
|
|
-
|
|
|
- Searched for 1 pattern, ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Update(scripts/mission_ember/apex.lua)
|
|
|
- ⎿ Added 3 lines
|
|
|
- 273 set(c, 5)
|
|
|
- 274 c:cancel_timer(vent_timer(s)); c:cancel_timer("emb
|
|
|
- er.apex.explain." .. generation(s))
|
|
|
- 275 coffin_doors(c, true)
|
|
|
- 276 + -- The weapon keeps firing until the cell goes in,
|
|
|
- + so the beam stays up here.
|
|
|
- 277 beam(c, true)
|
|
|
- 278 + -- Arm the climb scorch now: the pipes burn while
|
|
|
- +the cell is carried up.
|
|
|
- 279 + c:start_timer("ember.apex.hazards", 1)
|
|
|
- 280 unlock(c, "MOTHER_BRAIN_DOOR_DEVICE")
|
|
|
- 281 unlock(c, "COFFIN_BUNKER_DOOR_SOUTH_DEVICE")
|
|
|
- 282 a.device(c, "MOTHER_BRAIN_DOOR_DEVICE", true)
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● All Lua parses. Now running the test suites:
|
|
|
-
|
|
|
- Ran 5 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Intent budget exceeded — beam() now costs more per call. Making it idempotent:
|
|
|
-
|
|
|
- Ran 4 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● 62/64 intents is tighter than I want. Let me check the cap and trim the peak.
|
|
|
-
|
|
|
- Ran 5 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● The peak is the reactor checkpoint reset (45 squad retirements). Moving the
|
|
|
- hazard clear to its own callback:
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-● Back to the previous 61/63 peak. Removing the probe and running the full
|
|
|
- suite:
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● All five Lua suites pass. Now building the native side:
|
|
|
-
|
|
|
- Ran 3 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● The ending fix needs coverage. Let me extract the decision into a testable
|
|
|
- predicate:
|
|
|
-
|
|
|
-● Update(Sunrise/src/server/bap/encrypted/push/activity/activity_mission_seed_ro
|
|
|
- ster.h)
|
|
|
- ⎿ Added 25 lines
|
|
|
- 30 }
|
|
|
- 31
|
|
|
- 32 /**
|
|
|
- 33 + * Checks whether moving to a newly selected state actually rep
|
|
|
- +laces the instantiated world.
|
|
|
- 34 + *
|
|
|
- 35 + * An authored region is `sliceSetIndex + stateOrdinal`, so sib
|
|
|
- +ling states of one slice set are
|
|
|
- 36 + * different regions inside the same instantiated content: Embe
|
|
|
- +r's apex gameplay (region 0) and
|
|
|
- 37 + * its two ending bookends (regions 1 and 2) all live in slice
|
|
|
- +set 0. Only a slice-set change
|
|
|
- 38 + * tears the world down and rebuilds it. Treating a sibling mov
|
|
|
- +e as a replacement deadlocks the
|
|
|
- 39 + * publication: the roster withholds the new region's groups un
|
|
|
- +til the client reports holding it,
|
|
|
- 40 + * while the client's current region leg advances only on a rea
|
|
|
- +l slice-set switch.
|
|
|
- 41 + *
|
|
|
- 42 + * @param currentSliceSetIndex Slice set the lease's published
|
|
|
- +plan belongs to.
|
|
|
- 43 + * @param currentEffectiveRegion That plan's authored region.
|
|
|
- 44 + * @param selectedSliceSetIndex Slice set the newly selected pl
|
|
|
- +an belongs to.
|
|
|
- 45 + * @param selectedEffectiveRegion The newly selected plan's aut
|
|
|
- +hored region.
|
|
|
- 46 + * @return True only when the client must tear down and rebuild
|
|
|
- + its world.
|
|
|
- 47 + */
|
|
|
- 48 +[[nodiscard]] constexpr bool
|
|
|
- 49 +mission_seed_region_change_replaces_world(std::uint32_t current
|
|
|
- +SliceSetIndex,
|
|
|
- 50 + std::uint32_t current
|
|
|
- +EffectiveRegion,
|
|
|
- 51 + std::uint32_t selecte
|
|
|
- +dSliceSetIndex,
|
|
|
- 52 + std::uint32_t selecte
|
|
|
- +dEffectiveRegion) noexcept {
|
|
|
- 53 + return currentEffectiveRegion != selectedEffectiveRegion
|
|
|
- 54 + && currentSliceSetIndex != selectedSliceSetIndex;
|
|
|
- 55 +}
|
|
|
- 56 +
|
|
|
- 57 +/**
|
|
|
- 58 * Adds the exact selected-state Auth groups before retained sq
|
|
|
- uad groups are considered.
|
|
|
- 59 * The full set goes out only once the client reports holding t
|
|
|
- he selected region.
|
|
|
- 60 * @param hostedBubbles One bit per bubble this link hosts; a r
|
|
|
- egion outside them adds nothing.
|
|
|
-
|
|
|
-● Update(Sunrise/src/server/bap/bap_route.cpp)
|
|
|
- ⎿ Added 6 lines, removed 2 lines
|
|
|
- 1138 // leg only advances on an actual slice-set switc
|
|
|
- h. Waiting for an arrival there is a
|
|
|
- 1139 // deadlock: the roster withholds the new region'
|
|
|
- s groups forever and the client never
|
|
|
- 1140 // finishes synchronizing. Only a real slice-set
|
|
|
- change opens the arrival window.
|
|
|
- 1141 - if (lease.configured && lease.plan.effectiveRegio
|
|
|
- -n != plan.effectiveRegion
|
|
|
- 1142 - && lease.plan.sliceSetIndex != plan.sliceSetI
|
|
|
- -ndex) {
|
|
|
- 1141 + if (lease.configured
|
|
|
- 1142 + && encrypted::push::activity::mission_seed_re
|
|
|
- +gion_change_replaces_world(
|
|
|
- 1143 + lease.plan.sliceSetIndex,
|
|
|
- 1144 + lease.plan.effectiveRegion,
|
|
|
- 1145 + plan.sliceSetIndex,
|
|
|
- 1146 + plan.effectiveRegion)) {
|
|
|
- 1147 lease.previousPlan = lease.plan;
|
|
|
- 1148 lease.regionArrivalPending = true;
|
|
|
- 1149 }
|
|
|
-
|
|
|
- Searched for 1 pattern, ran 1 shell command (ctrl+o to expand)
|
|
|
- ⎿ Found 2 new diagnostic issues in 1 file (ctrl+o to expand)
|
|
|
-
|
|
|
-● Write(Sunrise/src/server/bap/encrypted/push/activity/mission_seed_world_change
|
|
|
- .h)
|
|
|
- ⎿ Wrote 36 lines to Sunrise/src/server/bap/encrypted/push/activity/missi
|
|
|
- on_seed_world_change.h
|
|
|
- 1 #pragma once
|
|
|
- 2
|
|
|
- 3 #include <cstdint>
|
|
|
- 5 namespace sunrise::server::bap::encrypted::push::activity {
|
|
|
- 6
|
|
|
- 7 /**
|
|
|
- 8 * Checks whether moving to a newly selected state actually repl
|
|
|
- 9 *
|
|
|
- 10 * An authored region is `sliceSetIndex + stateOrdinal`, so sibl
|
|
|
- ing states of one slice set are
|
|
|
- … +42 lines (ctrl+o to expand)
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Now the portable regression for the ending fix:
|
|
|
-
|
|
|
-● Write(tests/mission_seed_world_change_test.cpp)
|
|
|
- ⎿ Wrote 87 lines to tests/mission_seed_world_change_test.cpp
|
|
|
- 1 // Regression for the selected-state arrival window.
|
|
|
- 3 // An authored region is `sliceSetIndex + stateOrdinal`. Ember's
|
|
|
- apex gameplay and both ending
|
|
|
- ), while every earlier area is
|
|
|
- 5 // its own slice set. Only a slice-set change replaces the client
|
|
|
- 6 //
|
|
|
- 7 // Treating a sibling move as a replacement is what froze the mis
|
|
|
- 8 // withheld region 1's groups until the client reported holding r
|
|
|
- egion 1, and the client's
|
|
|
- o the report never came.
|
|
|
- … +103 lines (ctrl+o to expand)
|
|
|
-
|
|
|
- Searched for 1 pattern, ran 2 shell commands (ctrl+o to expand)
|
|
|
- ⎿ Found 1 new diagnostic issue in 1 file (ctrl+o to expand)
|
|
|
-
|
|
|
-● Everything builds and passes. Final verification of all suites, then
|
|
|
- installation:
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Now installing into the closed game with a backup and hash verification:
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● False positive — my own shell matched on the repo path. Tightening the
|
|
|
- detection:
|
|
|
-
|
|
|
- Ran 3 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Installation verified; save/settings/SDK untouched. Committing:
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Recording the install evidence in the status doc, per the established
|
|
|
- convention:
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● All five items are fixed, built, tested, installed and committed. The game is
|
|
|
- closed and untouched — ready for you to launch.
|
|
|
-
|
|
|
- What was wrong, and what I changed
|
|
|
-
|
|
|
- 1. Ending freeze — root cause found in the SDK, not a staging problem.
|
|
|
- An authored region is sliceSetIndex + stateOrdinal. Apex gameplay (region 0)
|
|
|
- and both ending bookends (regions 1 and 2) are sibling states of slice set 0 —
|
|
|
- moving between them instantiates no new world. But the code treated any
|
|
|
- region change as a world replacement, so two things deadlocked: the roster
|
|
|
- opened an "arrival window" and withheld region 1's groups until the client
|
|
|
- reported holding region 1 (which only happens on a real slice-set switch), and
|
|
|
- the teleport arm handed the client slice-set index 1 with slice set 0's name
|
|
|
- hash. Your 10:49 log shows it exactly: Starting teleportation to slice-set '1'
|
|
|
- ... PRV01.01 (HASH: 0xdfbc1cd9) and then no Finished synchronizing — every
|
|
|
- working transition has that line. Now only a genuine slice-set change opens
|
|
|
- the arrival window, an intra-slice-set move arms no teleport at all, and
|
|
|
- ending.lua selects each bookend directly. The region-49 staging detour is gone
|
|
|
- — it was forcing a cross-bubble round trip to manufacture a report that will
|
|
|
- never come.
|
|
|
-
|
|
|
- I also raised seed refusals from debug to warn. A refusal strands the selected
|
|
|
- state, and at debug level it was invisible in every log we have.
|
|
|
-
|
|
|
- 2. Electron Controllers — geometry settles it. Both anchors sit inside
|
|
|
- security_center_player_trigger (x −387…−344.5), while every access volume is
|
|
|
- east of x=−331. The access objective was pulling them out through the door —
|
|
|
- and no access task group could have held them, which is why pinning groups
|
|
|
- 9/10 failed. They now use EMBER_APEX_SECURITY_OBJECTIVE, which owns that room,
|
|
|
- with normal cost selection.
|
|
|
-
|
|
|
- 3. Fire vs shock — identified from the packages.
|
|
|
- REACTOR_COFFIN_INTERIOR_THERMAL_HOP_ON and FOUNDRY_THERMAL_DOT_HOP_ON both
|
|
|
- reference effect resource 80C1D9E0 — the burn already working in your Foundry.
|
|
|
- The hot-pipe and rail-top hop-ons carry 80B82484 and 80C1D389, which is why
|
|
|
- it read as shock. Apex now drives that one authored scorch for both hazards,
|
|
|
- swapping only the filter: the five narrow pipe volumes during the climb (phase
|
|
|
- 5, before the deposit), then the rail top during the escape.
|
|
|
-
|
|
|
- 4. Beam. All three ring objects were held active the whole fight, so nothing
|
|
|
- could surge. The laser and ring now rise with their devices at the warning and
|
|
|
- go dark at recovery; the core stays as the weapon's body. The deposit shuts
|
|
|
- the beam down (the old code opened both devices there) and it stays off across
|
|
|
- an escape restart.
|
|
|
-
|
|
|
- 5. Explosions. The prefab's four authored triggers were never armed — nothing
|
|
|
- existed to advance the sequence past the deposit. They're armed now and fire
|
|
|
- per section as you run east.
|
|
|
-
|
|
|
- 6. Objectives. Native type-68 state 0 enters the directive, and the Lua
|
|
|
- surface always publishes it — so republishing on every navpoint change
|
|
|
- replayed the entry animation while the text stayed put. That was the flashing.
|
|
|
- The directive is keyed on its element alone with one stable navpoint,
|
|
|
- entering once per milestone.
|
|
|
-
|
|
|
- Verification
|
|
|
-
|
|
|
- 22 portable native tests (including a new mission_seed_world_change regression
|
|
|
- covering sibling states vs. real slice-set changes) and all five Lua suites
|
|
|
- pass. Full route peaks at 234/512 variables, 61/63 intents per callback, 3/32
|
|
|
- timers — the same intent peak as the previous build. Installed 18 files, all
|
|
|
- SHA-verified; backup at build/final-issues-install-backup-20260906-122441,
|
|
|
- save/settings/SDK preserved. Committed as d7276cd, no co-author tag, not
|
|
|
- pushed.
|
|
|
-
|
|
|
- Two things I'd flag honestly: none of this is gameplay confirmation — passing
|
|
|
- tests only prove the script progression and wire shapes. And apex has no
|
|
|
- authored screen-effect slot, so the 23:38 screen pulse should come from the
|
|
|
- beam objects themselves brightening; I didn't fabricate an overlay for it. If
|
|
|
- it doesn't appear, that's the one item still genuinely open.
|
|
|
-
|
|
|
- Worth watching on your run: the controller fight staying in the room, scorch
|
|
|
- on the climb pipes before the deposit, the beam surging then going dark after
|
|
|
- it, explosions following you, a stable banner during the reactor fight, and
|
|
|
- both movies playing through.
|
|
|
-
|
|
|
-✻ Churned for 31m 22s
|
|
|
-※ recap: Goal was fixing the eight remaining 1AU mission issues; all five work items are done, tested, installed and committed. Next: you launch the game manually and play through to confirm the beam, controllers, scorch, explosions, objectives and both ending movies. (disable recaps in /config)
|
|
|
-
|
|
|
-❯ Close, the beam vfx now cycle between disabled and on instead of on and
|
|
|
- surging, the red-hot pipes whilst carrying the fusion core in apex aren't
|
|
|
- applying the scorch, and the game still freezes when trying to load the
|
|
|
- ending cutscene. Also the weapon is fully disabled at the end, it should have
|
|
|
- an enabled but powered off state, because otherwise all the structuring
|
|
|
- around the beam doesn't exist.
|
|
|
-
|
|
|
-● Four things. Let me start with the freshest evidence — your run's log.
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Found it — teleport_armed still fired. Let me see why and what followed.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● No seed refusals — the roster fix worked. The remaining blocker is the
|
|
|
- teleport arm: my guard read a stale value. Let me confirm and check the
|
|
|
- scorch.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● The climb hazard's volumes sit below the player. Let me check against where
|
|
|
- you actually walked.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Those positions are the escape run, not the climb. Let me map your full path
|
|
|
- through apex.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Now I have what I need. Four fixes. First the teleport guard — I used a stale
|
|
|
- source:
|
|
|
-
|
|
|
- Searched for 1 pattern, ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Now the beam — it must stay enabled with power as the surge lane:
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Now the climb scorch — I paired the effect with a filter in a different object
|
|
|
- than its volumes:
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Now updating the tests for the new beam states and rebuilding:
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● All green. Installing and committing:
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● The game is still open (destiny2.exe, pid 801895) — I won't touch it.
|
|
|
- Committing while I wait:
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● All four are fixed, built, and tested — but the game is still running
|
|
|
- (destiny2.exe, pid 801895), so I haven't installed. Close it and I'll install
|
|
|
- immediately.
|
|
|
-
|
|
|
- What each one actually was
|
|
|
-
|
|
|
- Ending freeze — my guard read the wrong source. Your log settles it. The
|
|
|
- roster half of the previous fix worked: no seed refusal was logged anywhere in
|
|
|
- the run. But teleport_armed still fired, and the client did exactly what it
|
|
|
- did before — Starting teleportation to slice-set '1' ... PRV01.01 (HASH:
|
|
|
- 0xdfbc1cd9), then no Finished synchronizing, then the network_send hitch.
|
|
|
-
|
|
|
- The reason: I used reported_slice_set(), which reads the newest D6 host
|
|
|
- teleport — that was still region 64 from the mission's opening move, because
|
|
|
- every later area (56, 40, 0) was reached on a z-leg, which doesn't update it.
|
|
|
- So the guard compared 64 against 0 and never matched. It now derives the held
|
|
|
- slice set from the region the client actually reports, rounded down to the
|
|
|
- slice-set factor. Apex reports region 0 → slice set 0 → target region 1 is
|
|
|
- slice set 0 → no teleport.
|
|
|
-
|
|
|
- Beam — I was deleting the weapon, not dimming it. You're right, and it's the
|
|
|
- same root cause as your fourth point. set_object_active{false} removes the
|
|
|
- placed objects, so the low point wasn't "dark", it was gone, and the deposit
|
|
|
- left it gone permanently. The three ring objects are now placed once and never
|
|
|
- deactivated. The beam has three states driven by the two devices instead:
|
|
|
-
|
|
|
- - off — powered off but still installed: the pose after the cell goes in, so
|
|
|
- the beam and everything built around it stay in the world
|
|
|
- - idle — powered and running: the baseline between exposures
|
|
|
- - surge — powered and driven open: the intensification before the shutters
|
|
|
- expose a target
|
|
|
-
|
|
|
- So the cycle is now idle ↔ surge, and the ending state is
|
|
|
- enabled-but-powered-off, as you described.
|
|
|
-
|
|
|
- Climb scorch — a cross-object filter that published but attached nothing. I
|
|
|
- had pointed the apex-object hot-pipes filter at globals-object volumes. The
|
|
|
- wire accepts that (the refs carry a registry key), which is why nothing
|
|
|
- errored, but it attached nothing. The filter living in the same object as
|
|
|
- those volumes is the pairing that demonstrably delivered contact damage before
|
|
|
- — that's where your escape shock came from. It now uses that filter; the only
|
|
|
- thing I changed from the original is the effect resource.
|
|
|
-
|
|
|
- Worth noting the geometry cross-checks out: the five pipe volumes climb from
|
|
|
- z≈172 at x=−395 to z≈186 at x=−460, tracking the same westward-and-upward path
|
|
|
- as the mother-brain dialogue volumes (001→004), which is the carry route to
|
|
|
- the deposit. Two of them (x −324, −294) sit on the escape rails instead —
|
|
|
- that's why the old build's shock hit you during the escape.
|
|
|
-
|
|
|
- State
|
|
|
-
|
|
|
- 22 native tests and all five Lua suites pass; route peaks unchanged at 234/512
|
|
|
- variables, 61/63 intents, 3/32 timers. Committed as de8c95e. The build is
|
|
|
- ready in build/x64/Release/.
|
|
|
-
|
|
|
- Close the game and say the word — I'll install with a fresh backup and
|
|
|
- hash-verify, and you can retest. On that run the things to watch are whether
|
|
|
- the beam now reads as running-vs-surging rather than blinking, whether the
|
|
|
- pipes burn on the way up, and whether the ending reaches the first movie — the
|
|
|
- log line to look for is state_region result=teleport_not_required instead of
|
|
|
- teleport_armed.
|
|
|
-
|
|
|
-✻ Baked for 6m 37s
|
|
|
-
|
|
|
-❯ sorry you can install now
|
|
|
-
|
|
|
- Ran 3 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Installed and verified — ready to launch whenever you are.
|
|
|
-
|
|
|
- Install: 18 files, all SHA-verified. DLL c10b5192f4f7c503…. Backup at
|
|
|
- build/final-issues-install-backup-20260906-124732, manifest at
|
|
|
- build/final-issues-installation.json. Save, settings and SDK untouched. I
|
|
|
- archived your 12:26 run as
|
|
|
- build/reactor-playtest/20260906-122600-teleport-armed.log before it gets
|
|
|
- overwritten, since it's the log that proved the teleport diagnosis.
|
|
|
-
|
|
|
- What's in this build:
|
|
|
-
|
|
|
- - Ending — the guard now derives your held slice set from the region you
|
|
|
- actually report, instead of the stale D6 teleport record that still said
|
|
|
- "64" from the opening move.
|
|
|
- - Beam — three ring objects placed once and never removed; three states on the
|
|
|
- devices: powered-off-but-installed after the deposit, powered-and-running
|
|
|
- as the baseline, powered-and-driven-open as the surge.
|
|
|
- - Climb scorch — filter and volumes back in the same object, keeping only the
|
|
|
- corrected scorch resource.
|
|
|
-
|
|
|
- What to look for on this run:
|
|
|
-
|
|
|
- The single most diagnostic line is in the log at the escape: state_region
|
|
|
- result=teleport_not_required. If you see that instead of teleport_armed, the
|
|
|
- bogus slice-set transition is gone and the first movie should follow. If it
|
|
|
- still says teleport_armed, the guard is still missing and I'll want the log
|
|
|
- again.
|
|
|
-
|
|
|
- Otherwise: whether the beam reads as running↔surging rather than blinking in
|
|
|
- and out, whether it's still visibly present but dead after the deposit, and
|
|
|
- whether the pipes burn on the way up with the cell.
|
|
|
-
|
|
|
- One thing I want to be straight about: the beam surge is the least certain of
|
|
|
- the four. I've established that the ring objects are the visual carrier (your
|
|
|
- report proved that — toggling them changed what you saw), and that the
|
|
|
- devices' power and drive lanes are the authored lanes. But I have not proven
|
|
|
- that driving those lanes produces a visible intensity change, since the
|
|
|
- earlier build's position+power toggling looked flat to you. If it still reads
|
|
|
- as constant, that tells me the surge lives somewhere I haven't found yet and
|
|
|
- I'll go back into the device configs (80B3D4EB/80B3D4EE) rather than guess
|
|
|
- again.
|
|
|
-
|
|
|
-✻ Cogitated for 46s
|
|
|
-※ recap: We're finishing the Destiny 2 mission 1AU (mission_ember), and the latest build fixing the ending freeze, beam surge, climb scorch and controller warp is installed and verified. Next: launch the game and playtest it. (disable recaps in /config)
|
|
|
-
|
|
|
-❯ Beam VFX still doesn't work as we're expecting, it stays on the whole time
|
|
|
- even after dunking the fusion cell, the game no longer freezing when trying
|
|
|
- to load the cutscene but it is stuck in an infinite load, the cutscenes never
|
|
|
- actually play.
|
|
|
-
|
|
|
-● Let me get the log from that run first.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● teleport_not_required — that fix landed. Now let me see what happens after.
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Only the opening cinematic appears — no cinematic_enqueued for the bookend at
|
|
|
- all. Let me see what the client did after the selection.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● The client never sent another state change after the selection — so my
|
|
|
- E.client activation never ran. Let me confirm and check the beam objects in
|
|
|
- the package.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Confirmed — last client region report was t=379518, well before the selection
|
|
|
- at t=432565. Now the beam objects:
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● The devices are ordinary type-23s (identical class refs to a working door), so
|
|
|
- they don't drive these visuals — only object presence does. Let me see which
|
|
|
- object is the beam and which is the structure.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● LASER carries effect components; CORE and RING carry the solid geometry and
|
|
|
- LOD tables — so the laser is the beam and the other two are the structure.
|
|
|
- Implementing:
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Now the ending — queue the cinematic directly instead of waiting for a client
|
|
|
- report that never comes:
|
|
|
-
|
|
|
-● Write(scripts/mission_ember/ending.lua)
|
|
|
- ⎿ Added 16 lines, removed 19 lines
|
|
|
- 2 --
|
|
|
- 3 -- An authored region is `sliceSetIndex + stateOrdinal`, so ape
|
|
|
- x gameplay (region 0) and both
|
|
|
- 4 -- ending bookends (regions 1 and 2) are sibling states of one
|
|
|
- slice set. Selecting a bookend
|
|
|
- 5 --- instantiates no new world: the client keeps the slice set it
|
|
|
- - already holds and never reports
|
|
|
- 6 --- a new held region, so this must not wait for one. The earlie
|
|
|
- -r region-49 staging detour forced
|
|
|
- 7 --- a cross-slice-set round trip to manufacture that report and
|
|
|
- -stalled instead.
|
|
|
- 5 +-- instantiates no new world, so no slice-set teleport is armed
|
|
|
- + for it -- and that also means the
|
|
|
- 6 +-- client never sends another region report. Waiting for one le
|
|
|
- +aves the movie unstarted forever,
|
|
|
- 7 +-- which is exactly what a run with the teleport removed showed
|
|
|
- +: the state was selected and no
|
|
|
- 8 +-- cinematic was ever enqueued.
|
|
|
- 9 --
|
|
|
- 9 --- The selection intent completes only once its own roster revi
|
|
|
- -sion publishes, and intents are
|
|
|
- 10 --- dispatched in order, so the activation queued on a later cal
|
|
|
- -lback always follows the seed.
|
|
|
- 10 +-- So the activation is queued with the selection instead of on
|
|
|
- + a later callback. Intents are
|
|
|
- 11 +-- dispatched in order and a state selection completes only onc
|
|
|
- +e its own roster revision has
|
|
|
- 12 +-- published, so the cinematic Auth always follows the seed tha
|
|
|
- +t carries its slot. Slot handles
|
|
|
- 13 +-- resolve against the static SDK definition table, not the sel
|
|
|
- +ected state, so naming the
|
|
|
- 14 +-- bookend before its state is live is safe.
|
|
|
- 15 return function(m)
|
|
|
- 16 local movies = {
|
|
|
- 17 {state = m.states.STATE_80B3C09E_0000_0001_80B3C091, sl
|
|
|
- ot = m.Slot.PF_CINEMATIC_BOOKEND_STM_CINEMATIC},
|
|
|
- ...
|
|
|
- 19 }
|
|
|
- 20 local E = {}
|
|
|
- 21 local music = require("mission_ember.music")(m)
|
|
|
- 18 - local function select_movie(c, index)
|
|
|
- 22 + local function play(c, index)
|
|
|
- 23 + local row = assert(movies[index])
|
|
|
- 24 c:set_variable("ember.ending", index)
|
|
|
- 20 - c:set_variable("ember.ending.selected", index)
|
|
|
- 21 - c:select_state(assert(movies[index].state))
|
|
|
- 25 + c:set_variable("ember.ending.playing", index)
|
|
|
- 26 + c:select_state(assert(row.state))
|
|
|
- 27 + c:slot(assert(row.slot)):set_cinematic_active{active =
|
|
|
- +true}
|
|
|
- 28 end
|
|
|
- 29 function E.start(c, s)
|
|
|
- 30 if s:variable("ember.ending") then return end
|
|
|
- 31 music.update(c, s)
|
|
|
- 26 - select_movie(c, 1)
|
|
|
- 32 + play(c, 1)
|
|
|
- 33 end
|
|
|
- 28 - function E.client(c, s, e)
|
|
|
- 29 - local index = s:variable("ember.ending")
|
|
|
- 30 - local row = index and movies[index]
|
|
|
- 31 - -- Activate on a callback after the selection, never in
|
|
|
- - the one that requested it.
|
|
|
- 32 - if not row or s:variable("ember.ending.selected") ~= in
|
|
|
- -dex
|
|
|
- 33 - or s:variable("ember.ending.playing") == index then
|
|
|
- - return end
|
|
|
- 34 - c:set_variable("ember.ending.playing", index)
|
|
|
- 35 - c:slot(assert(row.slot)):set_cinematic_active{active =
|
|
|
- -true}
|
|
|
- 36 - end
|
|
|
- 34 function E.terminated(c, s, e)
|
|
|
- 35 local index = s:variable("ember.ending")
|
|
|
- 36 local row = index and movies[index]
|
|
|
- ...
|
|
|
- 38 local slot = c:slot(row.slot)
|
|
|
- 39 if e.registry_key ~= slot.registry_key or e.slot_type ~
|
|
|
- = slot.slot_type or e.slot_index ~= slot.slot_index then return
|
|
|
- end
|
|
|
- 40 slot:set_cinematic_active{active = false}
|
|
|
- 44 - if movies[index + 1] then select_movie(c, index + 1)
|
|
|
- 41 + if movies[index + 1] then play(c, index + 1)
|
|
|
- 42 else
|
|
|
- 43 c:set_variable("ember.ending", index + 1)
|
|
|
- 44 c:set_variable("ember.complete", true)
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Only Lua changed this round, so the installed DLL is already correct.
|
|
|
- Committing and archiving the run:
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Committed and ready to install — close the game and I'll push it out (Lua only
|
|
|
- this time; the DLL from 12:47 is already correct).
|
|
|
-
|
|
|
- What the log showed
|
|
|
-
|
|
|
- The freeze fix worked. state_region result=teleport_not_required, no bogus
|
|
|
- slice-set transition, no network_send hitch. But the ending still didn't play,
|
|
|
- and the log says exactly why: no cinematic_enqueued was ever emitted. The
|
|
|
- only cinematic events in the entire run are the opening one at t=54s.
|
|
|
-
|
|
|
- The cause is my own design, and it's a consequence of the fix: I was
|
|
|
- activating the bookend on the next client state-change callback. Removing the
|
|
|
- teleport also removed the thing that produces a client state-change — your
|
|
|
- last region report was t=379518, and the selection was t=432565, with nothing
|
|
|
- after. So the activation was waiting on an event that no longer exists. The
|
|
|
- client sat in region 0 with the mission state pointing at region 1, ticking
|
|
|
- normally — which is the "infinite load" you saw.
|
|
|
-
|
|
|
- The bookend is now queued together with its state selection. Intent ordering
|
|
|
- still guarantees the cinematic Auth lands after the seed publishes, and slot
|
|
|
- handles resolve against the static SDK table rather than the selected state,
|
|
|
- so naming the bookend early is safe.
|
|
|
-
|
|
|
- The beam
|
|
|
-
|
|
|
- You're right that it stayed on. I've now confirmed why: both ring devices are
|
|
|
- ordinary type-23s — their configs carry the same class refs as a clamshell
|
|
|
- door — and neither position nor power changes anything visible. Object
|
|
|
- presence is the only lever that moves this beam.
|
|
|
-
|
|
|
- Comparing the three models settles which is which: core and ring carry solid
|
|
|
- geometry with full LOD tables; the laser carries the emitter's effect
|
|
|
- components and no geometry LODs. So core + ring are the structure, laser is
|
|
|
- the beam. They're now split — structure placed once and never removed, laser
|
|
|
- switched off at the deposit. That gives you the installed-but-dark state you
|
|
|
- asked for, and the exposure cycle no longer toggles it (presence-switching is
|
|
|
- what read as blinking).
|
|
|
-
|
|
|
- I have not implemented the surge, and I'm not going to guess at it a third
|
|
|
- time. I've now shown that neither device lane does anything and that presence
|
|
|
- is binary, so nothing available to the script produces an intensity change.
|
|
|
- Two failed attempts is enough — the honest position is that the authored
|
|
|
- mechanism is unidentified.
|
|
|
-
|
|
|
- If you want it chased properly, the concrete next step is the one that cracked
|
|
|
- the Harvester doors: dig into the laser model 80B7117C and the ring 80B71218
|
|
|
- for a named channel or model controller, then drive it the way dropship_doors
|
|
|
- was driven. That's a real investigation rather than another swap, so I'd
|
|
|
- rather do it deliberately than bolt a third guess onto this build.
|
|
|
-
|
|
|
- What to check next run
|
|
|
-
|
|
|
- The beam should be lit through the reactor fight, then visibly dark but still
|
|
|
- physically there after you dunk the cell — with the ring structure intact. And
|
|
|
- the log line that matters for the ending is cinematic_enqueued shortly after
|
|
|
- state_selected; if that appears and the movie still doesn't render, the
|
|
|
- problem has moved from the script to playback, which is a different hunt. The
|
|
|
- climb scorch is also still untested since you didn't get that far last time.
|
|
|
-
|
|
|
-✻ Baked for 5m 20s
|
|
|
-
|
|
|
-❯ We're treating the object, we're not treating the device linked to it for the
|
|
|
- beam. We have specops_apex_ring.laser_device and
|
|
|
- specops_apex_ring.ring_device could that be the issue?
|
|
|
-
|
|
|
-● Good question — and it's testable. Let me check whether those devices ever
|
|
|
- accepted the transitions I've been sending.
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● They're structurally identical to the clamshell/bridge devices that do animate
|
|
|
- — so they should respond. Let me look at exactly what a transition sends.
|
|
|
- Searched for 2 patterns (ctrl+o to expand)
|
|
|
-
|
|
|
-● Let me check whether device state is even reported back — that determines
|
|
|
- whether my "devices are inert" conclusion is sound.
|
|
|
-
|
|
|
- Searched for 2 patterns, ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● The device-sense diagnostic is hard-scoped to the landing bridge only — so I
|
|
|
- have no observation of apex device state. Let me check its storage before
|
|
|
- widening it.
|
|
|
-
|
|
|
- Searched for 1 pattern (ctrl+o to expand)
|
|
|
-
|
|
|
-● The diagnostic only ever watched the landing bridge — so I genuinely cannot
|
|
|
- tell whether apex device transitions are applied. Widening it, and driving the
|
|
|
- devices properly:
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Now driving both device lanes properly, with the object lever guaranteeing the
|
|
|
- end state:
|
|
|
-
|
|
|
- Ran 7 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● You're right to push on that, and checking it turned up something that
|
|
|
- undercuts what I told you.
|
|
|
-
|
|
|
- Your instinct was justified — my "devices don't work" claim wasn't supported
|
|
|
-
|
|
|
- I was driving both devices, but I'd concluded from "the beam didn't change"
|
|
|
- that the device lanes are inert. That conclusion doesn't hold, because nothing
|
|
|
- was ever observing those devices. The device-sense diagnostic is hard-scoped
|
|
|
- to registry F6FFB59E, slots 0–5 — the landing bridge. The apex ring devices
|
|
|
- (a3b76c64, slots 48/49) were never reported, and there were zero device_state
|
|
|
- lines in the whole run.
|
|
|
-
|
|
|
- So "the device didn't move the beam" and "the transition never reached the
|
|
|
- device" look identical in the evidence I had. I shouldn't have stated the
|
|
|
- first as established. The devices are also structurally identical to the
|
|
|
- clamshell and bridge devices that visibly animate — same sense schema, same
|
|
|
- auth schema, same component class, same descriptor offset — so there's no
|
|
|
- structural reason they'd be inert.
|
|
|
-
|
|
|
- What I changed
|
|
|
-
|
|
|
- Both halves are now driven together, the way the Mercury lever pairs its
|
|
|
- type-23 device with the type-4 object it animates:
|
|
|
-
|
|
|
- - Structure (core + ring objects) — placed once, never removed, so the framing
|
|
|
- around the beam always exists.
|
|
|
- - Beam (laser object) — presence is the lever already proven to make the beam
|
|
|
- appear and vanish; off at the deposit.
|
|
|
- - Devices — snap-initialised to a baseline, then transitioned without snap,
|
|
|
- which is exactly the pattern that made the lever animate rather than jump.
|
|
|
- The warning drives them open as the surge; recovery returns them; the
|
|
|
- deposit powers them off and returns the drive to baseline.
|
|
|
-
|
|
|
- The surge no longer removes anything, so if the devices do move the emitter,
|
|
|
- that's what you'll see — and if they don't, the beam is still stable and
|
|
|
- correctly dark at the end.
|
|
|
-
|
|
|
- I also widened the diagnostic so the next run answers your question directly.
|
|
|
- Look for ring_device_sense lines in the log: they carry the ring devices'
|
|
|
- native position and power. If they appear and change at the warning, the
|
|
|
- devices are live and the surge is a matter of which lane; if they never
|
|
|
- appear, the transitions aren't landing and that's the real bug.
|
|
|
-
|
|
|
- One thing worth flagging: the transition vocabulary is closed — position,
|
|
|
- power, lock, each with just a high/low endpoint. There's no intensity channel.
|
|
|
- So if the devices are live and open/close still doesn't read as a surge, the
|
|
|
- answer is likely a named channel on the model itself, the way dropship_doors
|
|
|
- was found on the Harvester — not another lane in this API.
|
|
|
-
|
|
|
- Build and tests are green (22 native, 5 Lua suites; 234/512 variables, 61/63
|
|
|
- intents). Committed as 53c84bb. The game's still running — close it and I'll
|
|
|
- install; this one does include a DLL change for the diagnostic.
|
|
|
-
|
|
|
-✻ Cogitated for 4m 36s
|
|
|
-
|
|
|
-❯ see because the sdk showed that the devices were not actually active and had
|
|
|
- no place in the world. Install now please.
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Installed. 18 files, all hash-verified; DLL dc668f42…. Backup at
|
|
|
- build/final-issues-install-backup-20260906-131220. Save, settings and SDK
|
|
|
- untouched.
|
|
|
-
|
|
|
- And your reading fits the evidence better than mine did. The type-4 objects
|
|
|
- carry package transforms and are explicitly placed by set_object_active —
|
|
|
- that's why toggling them visibly changed the beam. The type-23 devices are
|
|
|
- declarations that were never given a world placement, so the transitions I
|
|
|
- kept sending landed nowhere. That explains the whole pattern cleanly: presence
|
|
|
- of the objects was the only thing that ever moved, and no amount of position
|
|
|
- or power on the devices was going to do anything.
|
|
|
-
|
|
|
- That's also the real reason my earlier "the devices are inert" line was
|
|
|
- unsupported — I'd reached the right conclusion by the wrong route, from
|
|
|
- "nothing changed visually" rather than from the placement data, which is why I
|
|
|
- then talked myself back out of it when you pushed.
|
|
|
-
|
|
|
- The build as installed is still correct under that reading: the object lever
|
|
|
- is what produces the behaviour (structure always placed, laser off at the
|
|
|
- deposit), and the device drive is a few spare intents that do nothing. The
|
|
|
- ring_device_sense diagnostic will confirm it outright — if those devices have
|
|
|
- no placed instance, you'll see no such lines at all, and that settles the
|
|
|
- surge question: it isn't reachable through the device API, and the next place
|
|
|
- to look is a named channel on the laser model itself, the way dropship_doors
|
|
|
- was found.
|
|
|
-
|
|
|
- What this run should show: beam lit through the reactor fight and visibly dark
|
|
|
- but still physically present after you dunk the cell; the climb pipes burning
|
|
|
- on the way up (still untested — you haven't reached it with a working build
|
|
|
- yet); and for the ending, cinematic_enqueued shortly after state_selected,
|
|
|
- since the bookend is now queued with its own selection rather than waiting on
|
|
|
- a client report that no longer arrives.
|
|
|
-
|
|
|
-✻ Cogitated for 36s
|
|
|
-
|
|
|
-※ recap: We're finishing 1AU's remaining bugs; the latest build is installed and ready for you to launch and test. Next: run the mission and report the beam, climb pipes, and ending cutscenes. (disable recaps in /config)
|
|
|
-
|
|
|
-❯ Loading in towards the laser beam now
|
|
|
-
|
|
|
-● Watching. Let me set up a read-only wait on the log for the markers that
|
|
|
- matter.
|
|
|
-
|
|
|
-● Monitor(1AU apex: ring device state, cinematic and ending markers)
|
|
|
- ⎿ Monitor started · task b08pmwbbk · persistent
|
|
|
-
|
|
|
-● Watching the log live. I'm filtering for:
|
|
|
-
|
|
|
- - ring_device_sense — the decisive one for your point. If those devices have
|
|
|
- no world placement, nothing will appear here at all, and that closes out the
|
|
|
- beam question: it isn't reachable through the device API, and the surge
|
|
|
- would have to come from a named channel on the laser model itself (the
|
|
|
- dropship_doors route).
|
|
|
- - cinematic — I want cinematic_enqueued shortly after state_selected, then
|
|
|
- started. That's the ending fix.
|
|
|
- - state_region — should say teleport_not_required.
|
|
|
- - Failures — seed refusals, refused intents, faults, errors, hitches, and any
|
|
|
- slice-set transition.
|
|
|
-
|
|
|
- Things worth your eye as you go through apex, since the log won't show them:
|
|
|
-
|
|
|
- - The beam lit through the reactor fight, and whether the warning window reads
|
|
|
- as any kind of change.
|
|
|
- - After you dunk the cell: beam dark, but the ring structure still physically
|
|
|
- there.
|
|
|
- - The climb pipes burning on the way up with the cell — that path has never
|
|
|
- actually been reached with a working hazard, so it's untested.
|
|
|
-
|
|
|
- I'll flag anything that lands.
|
|
|
-
|
|
|
-✻ Baked for 27s
|
|
|
-
|
|
|
-● Monitor event: "1AU apex: ring device state, cinematic and ending markers"
|
|
|
-
|
|
|
-● The devices are live and reporting — and ordinal 0 is changing rapidly. Let me
|
|
|
- decode the full values.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Monitor event: "1AU apex: ring device state, cinematic and ending markers"
|
|
|
-
|
|
|
-● Monitor event: "1AU apex: ring device state, cinematic and ending markers"
|
|
|
-
|
|
|
-● Monitor event: "1AU apex: ring device state, cinematic and ending markers"
|
|
|
-● Monitor event: "1AU apex: ring device state, cinematic and ending markers"
|
|
|
-
|
|
|
-● Decisive data — and it contradicts the SDK reading. Let me quiet the noise and
|
|
|
- decode it.
|
|
|
-
|
|
|
-● Stop Task
|
|
|
- ⎿ tail -F -n 0
|
|
|
- /home/millie/Games/Sunrise/bin/x64/Sunrise/logs/sunrise.log
|
|
|
- 2>/dev/null | grep -E --line-buffered
|
|
|
- "ring_device_sense|state_region|cinematic|mission… · stopped
|
|
|
-
|
|
|
-● Monitor event: "1AU apex: ring device state, cinematic and ending markers"
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Monitor(1AU ending markers, faults and ring device sequence lanes)
|
|
|
- ⎿ Monitor started · task bry6ytn6i · persistent
|
|
|
-
|
|
|
-❯ yeah so the devices aren't tied to the object, that's what needs to change
|
|
|
-
|
|
|
-● Understood — the devices animate but nothing binds them to the placed objects.
|
|
|
- Let me look at what the object Auth can carry.
|
|
|
-
|
|
|
- Searched for 1 pattern (ctrl+o to expand)
|
|
|
-
|
|
|
-● There's a with parameter and a general set_channel. Let me read both.
|
|
|
-
|
|
|
- Searched for 1 pattern, ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Your refinement matches the data — and the first half of the premise doesn't.
|
|
|
- Here's what the run just proved.
|
|
|
-
|
|
|
- The ring devices are live, placed, and animating
|
|
|
-
|
|
|
- ring_device_sense fired 226 times for slots 48 and 49. Decoding the lanes:
|
|
|
-
|
|
|
- - ordinal 0 = position, a float that ramps smoothly: slot 48 went 0.0023 →
|
|
|
- 0.0046 → 0.0069 → 0.0093 → 0.0116 → 0.0139 → 0.0162…, slot 49 climbed ~30×
|
|
|
- faster (0.069 → 0.139 → 0.208). Both are travelling 0→1 in response to the
|
|
|
- transitions I send.
|
|
|
- - ordinal 1 / 3 / 5 = sequence guards, moving −1 → 1 → 2 as each channel
|
|
|
- accepts a command.
|
|
|
- - ordinal 2 = 1.0f, the lane's target.
|
|
|
-
|
|
|
- So the transitions land, the devices exist in the world, and they physically
|
|
|
- animate. They aren't inert declarations. But the placed object doesn't follow
|
|
|
- them — which is exactly your point, and it's the only reading left once you
|
|
|
- can see the device moving and the beam not changing.
|
|
|
-
|
|
|
- What the API actually offers
|
|
|
-
|
|
|
- The type-23 vocabulary is three channels — position, power, lock — and
|
|
|
- transition only ever sends the two endpoints of a lane. There's a second entry
|
|
|
- point I haven't used, set_channel, which takes a continuous unit scalar plus
|
|
|
- a sequence and snap. That's a real intensity lever if the binding is fixed:
|
|
|
- you could drive position to 0.35 rather than slam it to 1.
|
|
|
-
|
|
|
- Also worth noting for the binding hunt: set_object_active hardcodes entryIndex
|
|
|
- = 0. If the beam's placed entry isn't entry 0, we'd be instantiating a
|
|
|
- different entry from the one the device drives — which would produce exactly
|
|
|
- this split.
|
|
|
-
|
|
|
- What I'd do next
|
|
|
-
|
|
|
- Chase the object↔device binding in the package: the three object configs
|
|
|
- (80B3D4E2/E5/E8) and the two device configs (80B3D4EB/EE) all sit in the same
|
|
|
- prefab, so the link should be declared there — the same way the Harvester's
|
|
|
- delivery component was found bound to actor template 80FE22C9 at a specific
|
|
|
- ordinal. That tells us whether the device targets a different entry index, or
|
|
|
- whether the object needs something published before it will accept the
|
|
|
- device's drive.
|
|
|
-
|
|
|
- I'm not going to change anything mid-run. Finish the playthrough — I still
|
|
|
- want to know whether the climb pipes scorch and whether the ending reaches
|
|
|
- cinematic_enqueued, since neither has ever been observed working. The
|
|
|
- monitor's still watching for those (I've filtered out the position spam). Then
|
|
|
- I'll do the binding investigation properly rather than bolt on another guess.
|
|
|
-
|
|
|
-✻ Worked for 2m 0s
|
|
|
-
|
|
|
-❯ core_weapon_laser_beam_device , cinder_core_weapon_laser_beam_device,
|
|
|
- specops_apex_ring.laser_device are not enabled though
|
|
|
-
|
|
|
-● Let me check what the scripts actually do with that whole laser-beam family.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● You're right, and the grep proves it. The objects are placed but their devices
|
|
|
- are never enabled:
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Confirmed — the weapon's beam device is enabled only in apex. Powerhouse,
|
|
|
- processing and cinder place the beam object but never drive its device. Let me
|
|
|
- see the activation sites.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Now enabling the weapon's beam device in every region, matching what apex
|
|
|
- already does:
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Now the powerhouse one, in the confirmed-working landing module:
|
|
|
-
|
|
|
- Ran 4 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● The slot exists in the real SDK; the controller test uses a hand-built mock
|
|
|
- that lacks it. Adding it:
|
|
|
-
|
|
|
- Searched for 2 patterns, ran 6 shell commands (ctrl+o to expand)
|
|
|
-❯ and the cutscenes still don't load following the end-of-mission fade-to-black
|
|
|
- screen
|
|
|
-
|
|
|
-● Let me check what the ending did in this run.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● state_selected fired at t=531300 but no cinematic_enqueued followed — same
|
|
|
- failure. Let me first rule out a stale install.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● The new script is live and queues both. Let me look at what
|
|
|
- set_cinematic_active actually requires.
|
|
|
-
|
|
|
- Searched for 1 pattern, ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Found the actual failure — and it's new information.
|
|
|
-
|
|
|
- Searched for 2 patterns (ctrl+o to expand)
|
|
|
-
|
|
|
-● Both threads have answers now — one good, one a genuine bind.
|
|
|
-
|
|
|
- The beam device gap is real, and it's fixed
|
|
|
-
|
|
|
- Your reading was right, and the grep proves it. The weapon's beam is an object
|
|
|
- and a device, and only apex ever enabled the device:
|
|
|
-
|
|
|
- ┌────────────┬──────────────────────────────────────────┬─────────────────┐
|
|
|
- │ region │ device │ what the script │
|
|
|
- │ │ │ did │
|
|
|
- ├────────────┼──────────────────────────────────────────┼─────────────────┤
|
|
|
- │ 64 │ │ never │
|
|
|
- │ powerhouse │ POWERHOUSE_CORE_WEAPON_LASER_BEAM_DEVICE │ referenced at │
|
|
|
- │ │ │ all │
|
|
|
- ├────────────┼──────────────────────────────────────────┼─────────────────┤
|
|
|
- │ 56 │ │ object placed, │
|
|
|
- │ processing │ CORE_WEAPON_LASER_BEAM_DEVICE │ device │
|
|
|
- │ │ │ untouched │
|
|
|
- ├────────────┼──────────────────────────────────────────┼─────────────────┤
|
|
|
- │ │ │ object placed, │
|
|
|
- │ 40 cinder │ CINDER_CORE_WEAPON_LASER_BEAM_DEVICE │ device │
|
|
|
- │ │ │ untouched │
|
|
|
- ├────────────┼──────────────────────────────────────────┼─────────────────┤
|
|
|
- │ 0 apex │ SPECOPS_APEX_RING_*_DEVICE │ unlocked and │
|
|
|
- │ │ │ powered │
|
|
|
- └────────────┴──────────────────────────────────────────┴─────────────────┘
|
|
|
-
|
|
|
- Each region now unlocks and powers its beam device beside the object. Position
|
|
|
- is only one of a type-23's three lanes — a device that's never unlocked and
|
|
|
- powered stays inert no matter how its position is driven, which fits the apex
|
|
|
- ring animating its position while the beam ignored it. Committed as 2285d58;
|
|
|
- 22 native tests and all five Lua suites pass. Not installed — the game's still
|
|
|
- running.
|
|
|
-
|
|
|
- The ending: I found the actual failure, and it's a real bind
|
|
|
-
|
|
|
- It isn't silence this time. At t=531300 the state was selected
|
|
|
- (teleport_not_required), and then at t=591315:
|
|
|
-
|
|
|
- warn ev=mission_script stage=intent_refused result=intent_timeout
|
|
|
- error="intent exceeded its delivery lifetime"
|
|
|
-
|
|
|
- Exactly 60 seconds. The set_cinematic_active intent was queued — my change
|
|
|
- worked — but it never reached the host. set_cinematic_slot_active_reserved
|
|
|
- calls current_behavior_occurrence to resolve the bookend slot's live
|
|
|
- occurrence, that returns "mission seed still publishing", so the intent
|
|
|
- retries until its lifetime expires. That's why there's no cinematic_enqueued.
|
|
|
-
|
|
|
- The reason it can't resolve is the bind:
|
|
|
-
|
|
|
- - The occurrence resolver wants the slot's live region. The client is standing
|
|
|
- in region 0, so region 1's cinematic has no live occurrence — the seed
|
|
|
- publishes its groups but the client never instantiates them.
|
|
|
- - The only mechanism that moves a client's region is the host teleport. Arming
|
|
|
- it for a sibling state is what caused the original freeze, because it hands
|
|
|
- the client slice-set index 1 carrying slice set 0's name hash (PRV01.01
|
|
|
- (HASH: 0xdfbc1cd9)), and it never finishes synchronizing.
|
|
|
-
|
|
|
- So: no teleport → content never instantiates. Teleport as currently
|
|
|
- parameterised → hangs. Both ends of that are now demonstrated rather than
|
|
|
- assumed, which is progress, but I don't yet know the third path — how an
|
|
|
- intra-slice-set region change is meant to be signalled to the client.
|
|
|
-
|
|
|
- I'm not going to guess at it again. Three attempts on this one is enough, and
|
|
|
- each guess has cost you a playthrough. The next step is to read how
|
|
|
- current_behavior_occurrence decides a live occurrence and what the membership
|
|
|
- region record needs to say for region 1 to count as live — the answer is in
|
|
|
- that path, not in the Lua. That's a proper sit-down investigation rather than
|
|
|
- a swap.
|
|
|
-
|
|
|
- Say the word when you've closed the game and I'll install the beam-device fix,
|
|
|
- which is independent of all this and worth having in front of you.
|
|
|
-
|
|
|
-✻ Cogitated for 5m 13s
|
|
|
-
|
|
|
-❯ for the ending cinematics just trigger them the same way we trigger the
|
|
|
- opening cinematic surely
|
|
|
-
|
|
|
-● Let me look at exactly how the opening one is driven, since that's the path
|
|
|
- that demonstrably works.
|
|
|
-
|
|
|
- Searched for 1 pattern, read 1 file (ctrl+o to expand)
|
|
|
-
|
|
|
-● effectiveRegion is the selected region, so the resolver should find it. The
|
|
|
- gate before it is scene_binding_status — let me read that.
|
|
|
-
|
|
|
- Searched for 2 patterns, ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● report_intent_status logs at debug — which is why the 60 seconds looked
|
|
|
- silent. Same blind spot as the seed refusal. Raising it:
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● I tried exactly that, and it's already what the current build does — the
|
|
|
- reason it still fails isn't the trigger, it's a gate underneath. But chasing
|
|
|
- your suggestion is what found the answer.
|
|
|
-
|
|
|
- Why the opening's path doesn't transfer
|
|
|
-
|
|
|
- The opening does two things: it makes region 49 the mission's initial_state,
|
|
|
- so the client loads into that slice set as part of mission load, and then it
|
|
|
- waits for a held-region report before calling set_cinematic_active.
|
|
|
-
|
|
|
- The second half is transferable; the first isn't. Region 49 is its own slice
|
|
|
- set (48) with its own bubble hash, so the client can actually be in it.
|
|
|
- Regions 1 and 2 are sibling states of slice set 0 — they share bubble ordinal
|
|
|
- 0 with apex gameplay, so bubbleHashes[0] resolves to PRV00.00. That's why the
|
|
|
- teleport produced PRV01.01 (HASH: 0xdfbc1cd9) — an index saying region 1 with
|
|
|
- a hash naming region 0. The client can't teleport there because region 1 isn't
|
|
|
- a slice set. So there is no "hold region 1" report to wait for, which is why
|
|
|
- the held-region gate I originally wrote never fired.
|
|
|
-
|
|
|
- What's actually blocking it
|
|
|
-
|
|
|
- The current build already triggers it the opening's way, minus the wait. The
|
|
|
- intent is queued correctly — that part works. It just never reaches the host:
|
|
|
-
|
|
|
- set_cinematic_slot_active_reserved → current_behavior_occurrence →
|
|
|
- scene_lease_status, and that returns a still-publishing lease, so the
|
|
|
- dispatcher retries rather than delivering. It retried for 60 seconds and
|
|
|
- expired. That's the intent_timeout at t=591315, 60,015 ms after
|
|
|
- state_selected.
|
|
|
-
|
|
|
- Encouragingly, the occurrence resolver uses link.effectiveRegion, which is the
|
|
|
- selected region, not the held one — so it should find region 1's bookend
|
|
|
- without the client being there. The blocker is one layer up, in the seed
|
|
|
- lease: either publicationPending or outputBusy.
|
|
|
-
|
|
|
- The one thing I changed
|
|
|
-
|
|
|
- I'm not guessing which. report_intent_status was logging the reason at debug —
|
|
|
- the same blind spot as the seed refusal earlier — which is why those 60
|
|
|
- seconds looked completely silent. It's now at info, deduped to one line per
|
|
|
- distinct status.
|
|
|
-
|
|
|
- So the next run prints the exact status in a loop between state_selected and
|
|
|
- the timeout. That converts the last unknown into a fact, and the status name
|
|
|
- tells us directly whether the roster is staged and never flushing, or the
|
|
|
- lease revision never publishes for a sibling state.
|
|
|
-
|
|
|
- Two commits waiting to install, both independent of this: 2285d58 (the beam
|
|
|
- device enabling you identified) and 8dbf417 (this diagnostic). Close the game
|
|
|
- and I'll put them in — the beam change is worth seeing on its own, and the
|
|
|
- ending run will finally say why it's stalling.
|
|
|
-
|
|
|
-✻ Baked for 2m 11s
|
|
|
-
|
|
|
-❯ okay, install.
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Monitor(1AU: intent wait reasons, cinematic and ending markers)
|
|
|
- ⎿ Monitor started · task b8wzizkyt · persistent
|
|
|
-
|
|
|
-● Installed and verified. 18 files hash-checked, DLL ba1d1ac7…, backup at
|
|
|
- build/final-issues-install-backup-20260906-133119. Save, settings and SDK
|
|
|
- untouched. I archived the run I just analysed as
|
|
|
- 20260906-1310-intent-timeout.log so the evidence survives.
|
|
|
-
|
|
|
- Two things in this build:
|
|
|
-
|
|
|
- The beam device enabling you identified — all four regions now unlock and
|
|
|
- power their weapon beam device beside the object, not just apex. Powerhouse
|
|
|
- had never referenced its device at all; processing and cinder placed the
|
|
|
- object and left the device dead.
|
|
|
-
|
|
|
- Visible intent wait reasons — the thing that made the last 60 seconds look
|
|
|
- silent. report_intent_status was at debug.
|
|
|
-
|
|
|
- What to look for
|
|
|
-
|
|
|
- For the beam: whether it now reads as an actual firing beam in the earlier
|
|
|
- regions rather than a static prop, and in apex whether it's dark but still
|
|
|
- physically present after you dunk the cell.
|
|
|
-
|
|
|
- For the ending, the log is now the interesting part. Between state_selected
|
|
|
- and any timeout you should get a line like:
|
|
|
-
|
|
|
- ev=mission_script stage=intent result=<status>
|
|
|
-
|
|
|
- That status name is the answer I've been guessing at — most likely
|
|
|
- mission_seed_pending or output_busy. Whichever it is tells us directly whether
|
|
|
- the roster is staged and never flushing, or the lease revision never
|
|
|
- publishes for a sibling state. Either way it's a fact rather than an
|
|
|
- inference, and it points at one specific place in the seed publication path.
|
|
|
-
|
|
|
- I'm watching the log for it. One caveat worth setting: I don't expect the
|
|
|
- ending to work this run — nothing about the blocker itself changed, only its
|
|
|
- visibility. If the cutscenes still don't play, that's expected, and the log
|
|
|
- line is what I need from the attempt.
|
|
|
-✻ Brewed for 29s
|
|
|
-
|
|
|
-❯ in apex it was dark and physically present after dunking the cell, but the
|
|
|
- surge still never happens.
|
|
|
-
|
|
|
-● Good — that half is confirmed working. For the surge, let me follow up on
|
|
|
- something I noticed earlier: set_object_active hardcodes entryIndex = 0.
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● prepare_object doesn't bound-check the entry — the type-4 body carries an
|
|
|
- entry index and Lua pins it to 0. Let me see if entries are enumerable.
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Let me check the one unexplored lever before saying anything: whether the
|
|
|
- laser object has more than one authored entry.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Monitor event: "1AU ending markers, faults and ring device sequence lanes"
|
|
|
-
|
|
|
-● Monitor event: "1AU: intent wait reasons, cinematic and ending markers"
|
|
|
-
|
|
|
-● Monitor event: "1AU: intent wait reasons, cinematic and ending markers"
|
|
|
-
|
|
|
-● Stop Task
|
|
|
- ⎿ tail -F -n 0
|
|
|
- /home/millie/Games/Sunrise/bin/x64/Sunrise/logs/sunrise.log
|
|
|
- 2>/dev/null | grep -E --line-buffered
|
|
|
- "state_region|cinematic|mission_seed_refusal|resu… · stopped
|
|
|
-
|
|
|
-● Monitor event: "1AU: intent wait reasons, cinematic and ending markers"
|
|
|
-
|
|
|
-● Monitor event: "1AU: intent wait reasons, cinematic and ending markers"
|
|
|
-
|
|
|
-● Monitor event: "1AU: intent wait reasons, cinematic and ending markers"
|
|
|
-
|
|
|
-● Monitor event: "1AU ending markers, faults and ring device sequence lanes"
|
|
|
-
|
|
|
-● The info-level change made my filter far too noisy. Tightening it:
|
|
|
-
|
|
|
-● Stop Task
|
|
|
- ⎿ tail -F -n 0
|
|
|
- /home/millie/Games/Sunrise/bin/x64/Sunrise/logs/sunrise.log
|
|
|
- 2>/dev/null | grep -E --line-buffered "stage=intent
|
|
|
- |stage=cinematic|state_region|state… · stopped
|
|
|
-
|
|
|
-● Monitor event: "1AU: intent wait reasons, cinematic and ending markers"
|
|
|
-
|
|
|
-● Monitor event: "1AU: intent wait reasons, cinematic and ending markers"
|
|
|
-
|
|
|
-● Monitor event: "1AU: intent wait reasons, cinematic and ending markers"
|
|
|
-
|
|
|
-● Monitor event: "1AU: intent wait reasons, cinematic and ending markers"
|
|
|
-
|
|
|
-● Monitor event: "1AU: intent wait reasons, cinematic and ending markers"
|
|
|
-
|
|
|
-● Monitor(1AU ending: cinematic, state selection, intent waits and refusals)
|
|
|
- ⎿ Monitor started · task bc3vnhpul · persistent
|
|
|
-
|
|
|
-● Good — that half is now confirmed working: dark and physically present after
|
|
|
- the deposit is exactly the state you asked for.
|
|
|
-
|
|
|
- On the surge, I've run out of levers that the script API actually exposes, and
|
|
|
- I want to be straight about that rather than try a fourth variation.
|
|
|
-
|
|
|
- Here's the complete picture from this session's evidence:
|
|
|
-
|
|
|
- - Object presence is the only thing that changes the beam visually. Proven
|
|
|
- twice — deactivating it made the beam vanish, and it's what produces the
|
|
|
- dark-but-present state you just confirmed.
|
|
|
- - The devices are live and genuinely animating. ring_device_sense showed their
|
|
|
- position lane ramping smoothly 0→1 (slot 48 at ~0.0023/step, slot 49 about
|
|
|
- 30× faster), with sequence guards accepting each command. They move. The
|
|
|
- beam ignores them.
|
|
|
- - The device vocabulary is closed: position, power, lock — that's all three
|
|
|
- lanes, and I've driven all of them.
|
|
|
-
|
|
|
- So a surge would need the beam to have an intermediate visual state, and
|
|
|
- nothing reachable from the script can express one. Object presence is binary;
|
|
|
- the devices move something that isn't the beam's appearance.
|
|
|
-
|
|
|
- The one thing I found that I haven't tried: the type-4 Auth body carries an
|
|
|
- entry index, and set_object_active hardcodes it to 0 — prepare_object doesn't
|
|
|
- even bound-check it. If the laser object has more than one authored entry,
|
|
|
- selecting a different one would swap the visual, which is precisely how a
|
|
|
- "same object, brighter variant" gets authored. But I checked the three object
|
|
|
- configs and they're byte-for-byte structurally identical to each other, with
|
|
|
- no obvious per-object entry list — so I can't claim they have multiple
|
|
|
- entries, only that the lever exists and is currently pinned shut.
|
|
|
-
|
|
|
- Confirming that means reading the container placement tables for object
|
|
|
- 80B3C21C to count entries per object. The reader for that format already
|
|
|
- exists in the codebase (container_placement_reader.cpp), so it's a real piece
|
|
|
- of work but not a fishing expedition. That's the honest next step, and it's
|
|
|
- the only one I'd put money on.
|
|
|
-
|
|
|
- Two options, your call:
|
|
|
-
|
|
|
- 1. Chase the entry index properly — extract the placement table, count entries
|
|
|
- on the laser object, and if there's more than one, expose entry on
|
|
|
- set_object_active and drive it as the surge.
|
|
|
- 2. Bank the beam as-is — it fires through the mission, it's correctly dark and
|
|
|
- present after the deposit, and the surge stays unimplemented while I put
|
|
|
- the remaining effort into the ending, which is still the thing blocking a
|
|
|
- complete playthrough.
|
|
|
-
|
|
|
- I'd lean toward (2) first, because the ending is the one outstanding item that
|
|
|
- stops the mission finishing at all, and I now have live logging that should
|
|
|
- name its blocker on this run. Worth noting: I saw some trigger_refused /
|
|
|
- slot_auth_refused with target_unavailable early in region 64 on this run —
|
|
|
- I'll check whether those are pre-existing or new once you're further in.
|
|
|
-
|
|
|
-✻ Brewed for 2m 6s
|
|
|
-
|
|
|
-❯ in the SDK specops_apex_ring.*_device are both still listed as "This row has
|
|
|
- no place in the world"
|
|
|
-● That's decisive if it's the SDK's own placement check. Let me find what emits
|
|
|
- that.
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● You're right, and I was wrong about that — I should correct it clearly.
|
|
|
-
|
|
|
- That tooltip fires on anchors.empty() in the scriptable browser: the row has
|
|
|
- no anchors, no world placement. That's authoritative, and it beats my
|
|
|
- inference.
|
|
|
-
|
|
|
- What I misread: I saw ring_device_sense reporting a position lane ramping
|
|
|
- smoothly 0→1 with sequence guards accepting each command, and concluded the
|
|
|
- devices were "live and physically animating." That was an over-claim. Sense
|
|
|
- reflects the device component's channel state — it interpolates the value we
|
|
|
- command and echoes it back — which happens whether or not anything is placed
|
|
|
- in the world. A smooth ramp proves the channel is being driven, not that
|
|
|
- there's an entity to drive. You'd said the SDK showed them unplaced two
|
|
|
- messages earlier and I talked myself out of it on weaker evidence.
|
|
|
-
|
|
|
- So the position is now consistent with everything observed: the beam is
|
|
|
- entirely object-presence driven, the two devices are unplaced declarations,
|
|
|
- and no amount of position, power or lock on them will ever produce a visual.
|
|
|
- That's why every device-based attempt failed, and why the only things that
|
|
|
- ever worked were object activations.
|
|
|
-
|
|
|
- Which means a surge isn't expressible the way I've been trying — object
|
|
|
- presence is binary, and the devices are inert by construction.
|
|
|
-
|
|
|
- There's one lever left, and you can check it in seconds in the browser you
|
|
|
- already have open. The type-4 Auth carries an entry index, and
|
|
|
- set_object_active hardcodes it to 0 — prepare_object doesn't even bound-check
|
|
|
- it. Entries correspond to placements, which is exactly what that tooltip
|
|
|
- counts. So:
|
|
|
-
|
|
|
- ▎ Hover the render checkbox on specops_apex_ring.laser_object, .core_object
|
|
|
- ▎ and .ring_object — the objects, not the devices. If a row has places it says
|
|
|
- ▎ "N of M places ticked".
|
|
|
-
|
|
|
- If the laser object reports more than one place, that's the surge: a second
|
|
|
- authored entry for the same object, almost certainly a brighter variant, and I
|
|
|
- expose entry on set_object_active and drive it at the warning. If they all
|
|
|
- report exactly one place, then the surge genuinely isn't reachable from the
|
|
|
- script API, and the only remaining route is driving a named channel on the
|
|
|
- model itself — the way dropship_doors was found on the Harvester — which is a
|
|
|
- much bigger piece of work and worth deciding on deliberately rather than
|
|
|
- drifting into.
|
|
|
-
|
|
|
- Either way that one tooltip settles it, and it's a fact rather than another
|
|
|
- inference from me.
|
|
|
-
|
|
|
-✻ Baked for 48s
|
|
|
-
|
|
|
-● Monitor event: "1AU ending: cinematic, state selection, intent waits and
|
|
|
-refusals"
|
|
|
-
|
|
|
-● Stop Task
|
|
|
- ⎿ tail -F -n 0
|
|
|
- /home/millie/Games/Sunrise/bin/x64/Sunrise/logs/sunrise.log
|
|
|
- 2>/dev/null | grep -E --line-buffered "stage=cinematic
|
|
|
- |state_region|state_selected|int… · stopped
|
|
|
-
|
|
|
-● Monitor event: "1AU ending: cinematic, state selection, intent waits and
|
|
|
-refusals"
|
|
|
-
|
|
|
-● Monitor(1AU ending: cinematic, state selection, intent waits and refusals)
|
|
|
- ⎿ Monitor started · task bo4qph0m3 · persistent
|
|
|
-
|
|
|
-● That was my monitor filter misfiring, not anything from your run — pending was
|
|
|
- matching pending=0 in the routine probe lines. I've retightened it to only
|
|
|
- the mission-script cinematic, state-selection, intent-wait and refusal events,
|
|
|
- so it should stay quiet until the ending actually does something.
|
|
|
-
|
|
|
- Nothing has changed in my read of the beam. The question from my last message
|
|
|
- still stands whenever you're back at the browser:
|
|
|
-
|
|
|
- ▎ On specops_apex_ring.laser_object, .core_object and .ring_object — the
|
|
|
- ▎ objects, not the devices — what does the render checkbox tooltip say? Either
|
|
|
- ▎ "no place in the world" or "N of M places ticked".
|
|
|
-
|
|
|
- If the laser object has more than one place, that's the surge, and it's a
|
|
|
- small change: expose entry on set_object_active and drive the second entry at
|
|
|
- the warning. If they each have exactly one, the surge isn't reachable from the
|
|
|
- script API at all and we should stop spending playtests on it.
|
|
|
-
|
|
|
-✻ Baked for 22s
|
|
|
-
|
|
|
-❯ I don't see what you're asking me to look at
|
|
|
-
|
|
|
-● Fair — let me get you the actual navigation from the UI code rather than
|
|
|
- describing it vaguely.
|
|
|
-
|
|
|
- Ran 3 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● You were on the Devices page — that's the right place to see the devices are
|
|
|
- unplaced. I need you on a different page.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Confirmed — the Position column is exactly the count I need, and it's a value
|
|
|
- you can read straight off the row without hovering anything.
|
|
|
-
|
|
|
- Where to go: same SDK view, but switch from the Devices page to the Objects
|
|
|
- page. The devices and objects are listed separately, which is why you couldn't
|
|
|
- find these — specops_apex_ring.*_device live on Devices (where you correctly
|
|
|
- saw "no place in the world"), and the three objects live on Objects.
|
|
|
-
|
|
|
- What to find: three rows —
|
|
|
-
|
|
|
- - specops_apex_ring.laser_object
|
|
|
- - specops_apex_ring.core_object
|
|
|
- - specops_apex_ring.ring_object
|
|
|
-
|
|
|
- What to read: the Position column (columns are Draw | Name | Bubble | State |
|
|
|
- Kind | Position | Shape | Link). It shows one of:
|
|
|
-
|
|
|
- - N linked — N real world places
|
|
|
- - N context — greyed out, context-only
|
|
|
- - - — none
|
|
|
-
|
|
|
- That number is the anchor count, the same thing the tooltip counts, and it's
|
|
|
- precisely the entry count I'm after.
|
|
|
-
|
|
|
- What it decides:
|
|
|
-
|
|
|
- - If laser_object shows more than 1 linked — that's the surge. Multiple
|
|
|
- authored entries for the same object, and set_object_active is pinning us to
|
|
|
- entry 0. Small change: expose entry and drive the second one at the
|
|
|
- warning.
|
|
|
- - If it shows exactly 1 linked — the surge isn't reachable from the script API
|
|
|
- at all, and I'd stop spending playtests on it. The only route left would be
|
|
|
- driving a named channel on the model, which is Harvester-door-sized work
|
|
|
- and worth deciding on separately.
|
|
|
-
|
|
|
- Just the three numbers is all I need.
|
|
|
-
|
|
|
-✻ Sautéed for 38s
|
|
|
-
|
|
|
-❯ 1 Linked, Shape none, linx exact same on all fo them
|
|
|
- both the specops_apex_ring.laser_device and specops_apex_ring.ring_device
|
|
|
- says state unnamed, position 60 context only, link context only
|
|
|
-
|
|
|
-● That closes it — all three routes are now ruled out by evidence rather than
|
|
|
- inference.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● That settles the beam. All three routes are dead, and I've written the finding
|
|
|
- into MISSION_EMBER_STATUS.md so nobody re-litigates it later.
|
|
|
-
|
|
|
- 1 linked, shape none, link exact — on all three objects. One placement each.
|
|
|
- There's no second entry, so the entryIndex lever is dead: nothing to switch
|
|
|
- to.
|
|
|
-
|
|
|
- state unnamed, 60 context only, link context only on both devices. That's
|
|
|
- linkedPositions == 0 — the row has no anchor of its own, and the 60 is just
|
|
|
- the owning object's context count. Exactly the condition behind "this row has
|
|
|
- no place in the world." So the devices can never produce a visual, and
|
|
|
- position/power/lock is the entire type-23 vocabulary.
|
|
|
-
|
|
|
- That also means my ring_device_sense reading was wrong, and I want to name
|
|
|
- that plainly rather than let it sit in the record: the smooth 0→1 position
|
|
|
- ramp I treated as "the devices are live and physically animating" was the
|
|
|
- device component interpolating the value I commanded and echoing it back. It
|
|
|
- proves the channel is driven, not that anything exists to be driven. You told
|
|
|
- me the SDK said these were unplaced and I argued back on weaker evidence. You
|
|
|
- were right both times.
|
|
|
-
|
|
|
- So: the surge isn't reachable from the script API at all. Not device lanes,
|
|
|
- not entry selection, not presence toggling. The only route left is driving a
|
|
|
- named channel on the laser model 80B7117C directly — the way dropship_doors
|
|
|
- was recovered from the Harvester's model controller and driven through the
|
|
|
- named-scalar actor command. That's native work on the scale of the Harvester
|
|
|
- door investigation, not a script change.
|
|
|
-
|
|
|
- My recommendation: bank the beam and move to the ending. What you have now is
|
|
|
- correct — it fires through the reactor fight, and it's dark but structurally
|
|
|
- intact after the deposit, which is what you asked for. The surge is one absent
|
|
|
- VFX beat. The ending is the thing that stops the mission finishing at all,
|
|
|
- and it's the only outstanding item of that weight.
|
|
|
-
|
|
|
- The current build has live logging on exactly that path, so the next time you
|
|
|
- reach the escape the log should name the blocker instead of going silent for
|
|
|
- sixty seconds — I'm watching for it. If you'd rather I take on the
|
|
|
- model-channel work for the surge afterwards, I'm happy to, but I'd want it
|
|
|
- scoped as its own task rather than folded into the finale.
|
|
|
-
|
|
|
-✻ Cooked for 48s
|
|
|
-
|
|
|
-❯ I'm moving to the ending now, then do the beam immediately after
|
|
|
-
|
|
|
-● Understood. Monitor's armed for the ending. While you play, let me do the
|
|
|
- read-only groundwork for the beam so I'm not starting cold — the first thing
|
|
|
- to establish is whether the laser model even has named channels.
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● No named-channel table in the laser components we have — those "strings" are
|
|
|
- float noise. Let me pull the remaining laser-side resources for a definitive
|
|
|
- answer.
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-❯ I do think you're wrong about the beam device fwiw, because for every other
|
|
|
- device+object combo both are drawn, the beams device isn't drawn at all
|
|
|
-
|
|
|
-● You're right, and that's a much better read than mine — an authored device
|
|
|
- that's undrawn while every sibling device+object pair is drawn is an anomaly,
|
|
|
- not a design. Let me find why those two rows have no placement.
|
|
|
-
|
|
|
- Ran 3 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● A type-23 device only gets drawn if its descriptor has a placementLinkRow into
|
|
|
- type23PlacementLinks. Let me find where those links are built.
|
|
|
-
|
|
|
- Ran 3 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Now I have the mechanism. A type-23 device is only drawn when its descriptor's
|
|
|
- placement identifier resolves to exactly one active container placement — and
|
|
|
- there are diagnostics for every way that can fail.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● You've changed my mind, and the code backs you up. Let me correct the record.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● You're right and I closed that out too early. Tracing your observation through
|
|
|
- the code changes the conclusion.
|
|
|
-
|
|
|
- A type-23 device is only drawn when its descriptor has a valid
|
|
|
- placementLinkRow and type23_source::build succeeds. That link comes from
|
|
|
- append_type23_placement_links, which matches the descriptor's
|
|
|
- placementIdentifier against container placements and only reaches
|
|
|
- ReferenceJoin::exact when the link is complete and exactly one candidate is
|
|
|
- active.
|
|
|
-
|
|
|
- The ring devices pass the builder's filter fine — 80B3D4EB (slot 48) and
|
|
|
- 80B3D4EE (slot 49) both carry component class 0x80804F45, the type-23 class.
|
|
|
- So they should get a link. Which means the link is being built and failing to
|
|
|
- resolve.
|
|
|
-
|
|
|
- And there's a detail that made this look cleaner than it is: link_label tests
|
|
|
- contextPositions before partial. So a device whose placement link failed still
|
|
|
- reads "context only" whenever its owning object has context positions — which
|
|
|
- is exactly your case, 60 of them. The partial flag was being masked. I read
|
|
|
- "context only" as "no placement authored" when it can equally mean "placement
|
|
|
- authored, join failed."
|
|
|
-
|
|
|
- So the beam device isn't inherently unplaceable. Its placement link resolves
|
|
|
- to zero or ambiguous candidates, and that's why nothing is drawn and why
|
|
|
- driving it does nothing. That's a defect, and plausibly the same class as the
|
|
|
- scenario-layout catalogue omission that previously cost 83 squad definitions —
|
|
|
- a generator problem, not an authoring one.
|
|
|
-
|
|
|
- The builder already counts every way this fails — zeroIdentityMatches,
|
|
|
- multipleIdentityMatches, zeroActiveCandidates, multipleActiveCandidates,
|
|
|
- unreadIdentifiers, droppedLinks — but nothing surfaces those counters
|
|
|
- anywhere. So the first move when I pick this up is an offline dump of the link
|
|
|
- state for slots 48/49 of 80b3c21c: identity matches, candidate count, active
|
|
|
- count, join and complete. That names the failure precisely, and if it's a
|
|
|
- generator bug it's fixable rather than a dead end.
|
|
|
-
|
|
|
- I've corrected the status doc — route 1 is reopened, routes 2 and 3 (entry
|
|
|
- index, presence toggling) stay closed on the evidence, and the model-channel
|
|
|
- route drops to a fallback only if the link can't be repaired.
|
|
|
-
|
|
|
- Carry on with the ending; the monitor's watching for the cinematic and
|
|
|
- intent-wait lines. I'll start on the placement link the moment you're through.
|
|
|
-
|
|
|
-✻ Worked for 2m 50s
|
|
|
-
|
|
|
-❯ Ending is done, we're stuck in the black loading screen.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● The new logging named it. Let me confirm the mechanism.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● No re-adoption — so that hypothesis is out. The gate passed at t=756058 and
|
|
|
- failed 12 ms later. Let me find what moves publishedRevision.
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Now I can see the whole chain. publishedRevision only commits when the roster
|
|
|
- body is actually staged and sent. The intent gate passed at t=756058 and the
|
|
|
- identical check failed 12 ms later — so one side moved, and I want the numbers
|
|
|
- rather than another theory.
|
|
|
-
|
|
|
- Ran 3 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Two occurrences — I need the cinematic one. Let me check the available
|
|
|
- snapshot type first.
|
|
|
-
|
|
|
- Ran 3 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● The new logging paid off — your run named the blocker precisely.
|
|
|
-
|
|
|
- t=756058 state_region result=teleport_not_required
|
|
|
- t=756058 delivery result=state_selected
|
|
|
- t=756070 intent result=mission_seed_pending ← 12 ms later
|
|
|
- t=816076 intent_refused result=intent_timeout ← 60 s later
|
|
|
-
|
|
|
- So the queued set_cinematic_active is fine — it's the seed lease refusing to
|
|
|
- deliver it. mission_seed_pending means scene_lease_status found
|
|
|
- publishedRevision != revision.
|
|
|
-
|
|
|
- Here's what makes that interesting: the dispatcher gate that let
|
|
|
- state_selected complete tests exactly the same condition. It passed at
|
|
|
- t=756058 and the identical check failed 12 ms later. So one of those two
|
|
|
- numbers moved in between, and the status name alone can't say which. I also
|
|
|
- ruled out my first theory — there's no mission_seed result=adopted anywhere in
|
|
|
- the log, so the lease wasn't re-adopted and wiped.
|
|
|
-
|
|
|
- I've traced the plumbing: publishedRevision only commits to revision inside
|
|
|
- the roster push, when a body is actually staged carrying that revision
|
|
|
- (hasMissionSeedRevision), which itself requires regionArrivalPending to be
|
|
|
- false — that part my earlier fix already satisfies. So either the revision got
|
|
|
- bumped again by a second selection, or a staged publication was rolled back.
|
|
|
-
|
|
|
- Rather than guess a fourth time, the pending report now carries the lease
|
|
|
- itself: configured, revision, publishedRevision, publicationPending,
|
|
|
- regionArrivalPending, the link's effective region, and the plan's region and
|
|
|
- state row. report_intent_status dedups on status, so it's one line per stall,
|
|
|
- not per retry. That single line will say which number moved and settle it.
|
|
|
-
|
|
|
- Committed as e281668; 22 native tests and five Lua suites pass; your run
|
|
|
- archived as 20260906-1340-mission-seed-pending.log.
|
|
|
-
|
|
|
- I know this is another "install and run it again," and I'd rather not keep
|
|
|
- spending your playthroughs. Two things worth saying about that:
|
|
|
-
|
|
|
- You don't need a full run to get this line — it only needs a state selection
|
|
|
- to stall, so if you can get to the escape by any means (you've been using
|
|
|
- teleport), that's enough. And it's an in-place install: DLL plus scripts, no
|
|
|
- save impact, so if the game's still up from this run you can close, let me
|
|
|
- install, and go straight back to the reactor on a checkpoint rather than
|
|
|
- replaying the mission.
|
|
|
-
|
|
|
- Say when it's closed. Meanwhile I'll start the beam placement-link dump, since
|
|
|
- that's offline work I can do without you.
|
|
|
-
|
|
|
-✻ Baked for 3m 2s
|
|
|
-
|
|
|
-❯ Fix the beam, fix ending cutscene. Don't talk to me until it's done
|
|
|
-
|
|
|
-● Working. Starting with the ending — the arrival window is the one path that
|
|
|
- produces exactly both observed symptoms.
|
|
|
- Ran 5 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Ending fix is in and tested. Now the beam placement link — let me find the
|
|
|
- offline SDK generation path so I can read the diagnostics without another
|
|
|
- playtest.
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● The catalog is built live in the client, so the link diagnostics only exist at
|
|
|
- runtime. Adding bounded logging for unresolved type-23 links:
|
|
|
-
|
|
|
- Ran 4 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Done. Installed and verified — 18 files, DLL hash matches the build, backup at
|
|
|
- build/final-issues-install-backup-20260906-135458, save/settings/SDK
|
|
|
- untouched.
|
|
|
-
|
|
|
- Ending cutscene — fixed
|
|
|
-
|
|
|
- Your run's logging gave me the cause, and it explains both symptoms at once.
|
|
|
-
|
|
|
- The seed lease for the ending state never published, so every scene lease on
|
|
|
- it returned mission_seed_pending and the queued set_cinematic_active expired
|
|
|
- after 60 seconds. The culprit is the region-arrival window: the roster refuses
|
|
|
- to commit a published revision while regionArrivalPending is set, and that
|
|
|
- window only closed when the client reported holding the pending region. A
|
|
|
- sibling state never produces that report — its content is in the slice set the
|
|
|
- client already holds, and the current region leg only advances on a slice-set
|
|
|
- switch. So the window stayed open forever.
|
|
|
-
|
|
|
- That also explains the thing that had been bothering me: state_selected
|
|
|
- completed instantly instead of waiting for publication. Its gate is skipped
|
|
|
- entirely while the arrival window is open. The selection looked healthy
|
|
|
- precisely because the lease was stuck.
|
|
|
-
|
|
|
- The window now also closes when the pending region is a sibling of the slice
|
|
|
- set the client already holds — the same reasoning that removed the bogus
|
|
|
- teleport. Extracted as mission_seed_arrival_window_closed with portable
|
|
|
- coverage, including that a genuine slice-set change still holds the window
|
|
|
- open so a publication can't race a teardown.
|
|
|
-
|
|
|
- Beam — instrumented, not fixed, and I won't claim otherwise
|
|
|
-
|
|
|
- I could not fix this one, and here's exactly where it stands.
|
|
|
-
|
|
|
- Your read was right: the apex ring devices resolve to no exact placement,
|
|
|
- which is why they're never drawn and why driving them does nothing. What I
|
|
|
- couldn't determine offline is why the placement link fails — and that decides
|
|
|
- whether it's repairable. The three possibilities are a placement identifier
|
|
|
- that was never read, one that matches no container placement, or one that
|
|
|
- matches ambiguously. The first and third are generator defects and fixable;
|
|
|
- the second means the content genuinely has no placement and the surge isn't
|
|
|
- reachable at all.
|
|
|
-
|
|
|
- The builder already counts all of these, but nothing ever surfaced them — and
|
|
|
- the browser actively hid it, since a failed join reads as "context only"
|
|
|
- whenever the owning object has context positions. The link pass now reports
|
|
|
- its counters and names each unresolved type-23 row with its identity-match,
|
|
|
- candidate and active counts.
|
|
|
-
|
|
|
- The catalog is built live in the client, so that only appears when you load
|
|
|
- the mission. On your next run, ev=type23_placement stage=unresolved slot=48
|
|
|
- (and 49) will name the failure, and I can act on it directly rather than
|
|
|
- guessing.
|
|
|
-
|
|
|
- The beam otherwise remains in the state you confirmed: firing through the
|
|
|
- reactor fight, dark but physically present after the deposit.
|
|
|
-
|
|
|
- Both changes are in commit bd4a0cc; 22 native tests and all five Lua suites
|
|
|
- pass.
|
|
|
-
|
|
|
-✻ Sautéed for 5m 5s
|
|
|
-
|
|
|
-❯ Loading into 1AU now, go ahead and check the beam so you can fix it
|
|
|
-
|
|
|
-● Monitor(1AU: type-23 placement link results and ending markers)
|
|
|
- ⎿ Monitor started · task b5d6eejzz · persistent
|
|
|
-
|
|
|
-● Watching. The type23_placement lines are emitted when the scenario catalog
|
|
|
- builds, so they should land as 1AU loads — before you even reach the reactor.
|
|
|
-
|
|
|
- Two things I'm looking for:
|
|
|
-
|
|
|
- ev=type23_placement stage=summary — the counters across all type-23 devices:
|
|
|
- how many links, and totals for unread, zero_identity, multi_identity,
|
|
|
- zero_active, multi_active, scenario_resolved.
|
|
|
-
|
|
|
- ev=type23_placement stage=unresolved slot=48 and slot=49 — the ring laser and
|
|
|
- ring devices specifically, each with its placement identifier, identity-match
|
|
|
- count, candidate count, active count, complete flag and join.
|
|
|
-
|
|
|
- That combination tells me which of three things is happening:
|
|
|
-
|
|
|
- - identity_matches=0 → the descriptor's placement identifier matches no
|
|
|
- container placement. Either the identifier is being read wrong, or the
|
|
|
- content genuinely has no placement for these devices.
|
|
|
- - unread counted → the identifier was never read out of the descriptor at all,
|
|
|
- which is a reader defect and fixable.
|
|
|
- - identity_matches>1 with active 0 or >1 → it matches, but candidate selection
|
|
|
- can't pick one. That's an ownership/bubble filter problem, and also
|
|
|
- fixable.
|
|
|
-
|
|
|
- The first two are generator-side and I can act on them directly. Only "matches
|
|
|
- nothing and the identifier is correct" would mean the devices are genuinely
|
|
|
- unplaced in the authored content.
|
|
|
-
|
|
|
- Since you're doing a full run anyway, the ending fix gets tested on the same
|
|
|
- pass — if the arrival-window change worked, set_cinematic_active should reach
|
|
|
- the host instead of stalling on mission_seed_pending, and you'll get the
|
|
|
- bookend movies rather than the black screen.
|
|
|
-
|
|
|
- I'll dig in as soon as the lines appear.
|
|
|
-
|
|
|
-✻ Baked for 21s
|
|
|
-
|
|
|
-● Monitor event: "1AU ending: cinematic, state selection, intent waits and
|
|
|
-refusals"
|
|
|
-
|
|
|
-● Stop Task
|
|
|
- ⎿ tail -F -n 0
|
|
|
- /home/millie/Games/Sunrise/bin/x64/Sunrise/logs/sunrise.log
|
|
|
- 2>/dev/null | grep -E --line-buffered "ev=mission_script
|
|
|
- stage=cinematic |ev=mission_sc… · stopped
|
|
|
-
|
|
|
-● Monitor event: "1AU ending: cinematic, state selection, intent waits and
|
|
|
-refusals"
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● No type23_placement lines yet — the catalog hasn't been built this session.
|
|
|
- Let me confirm what triggers it.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● The diagnostic is in, but it hasn't fired — and that's my oversight, not a
|
|
|
- problem with your run.
|
|
|
-
|
|
|
- The scriptable catalog is built on demand by the UI, not at mission load.
|
|
|
- append_type23_placement_links only runs when something asks for that catalog —
|
|
|
- which is why you saw those rows earlier only because you had the browser
|
|
|
- open. There's nothing in the log this session because nothing has requested
|
|
|
- it.
|
|
|
-
|
|
|
- So one small thing from you, whenever convenient during this run:
|
|
|
-
|
|
|
- ▎ Open the SDK scriptable browser and go to the Devices page (the same place
|
|
|
- ▎ you read "no place in the world").
|
|
|
-
|
|
|
- That builds the catalog and emits the diagnostic immediately. I'm watching for
|
|
|
- it. You don't need to do anything else there — just landing on the page is
|
|
|
- enough.
|
|
|
-
|
|
|
- What I'll get from it:
|
|
|
-
|
|
|
- - ev=type23_placement stage=summary — totals across every type-23 device:
|
|
|
- unread, zero_identity, multi_identity, zero_active, multi_active,
|
|
|
- scenario_resolved.
|
|
|
- - ev=type23_placement stage=unresolved slot=48 / slot=49 — the ring devices
|
|
|
- with their placement identifier and match counts.
|
|
|
-
|
|
|
- If zero_identity is high across the board, it's a reader-side defect and
|
|
|
- fixable. If it's only these two rows, then the content genuinely has no
|
|
|
- placement for them and the surge isn't reachable — I'd stop there rather than
|
|
|
- keep digging.
|
|
|
-
|
|
|
- One other thing I noticed in the meantime, unrelated but worth flagging: there
|
|
|
- are six device_refused with target_unavailable around t=118956 in region 64,
|
|
|
- plus some trigger_refused. Those are new to this build — the previous run had
|
|
|
- trigger and slot_auth refusals there but no device ones. That timing lines up
|
|
|
- with the landing initialize, so it may be the powerhouse beam device I added
|
|
|
- rejecting its transitions. I'll confirm against the placement data rather than
|
|
|
- guess, since if that device is also unplaced it'd refuse exactly like this —
|
|
|
- and that would be the same root cause showing up in a second place.
|
|
|
-
|
|
|
-✻ Cooked for 56s
|
|
|
-
|
|
|
-❯ I've opened the SDK menu for you
|
|
|
-
|
|
|
- Ran 2 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● The worker only logs at debug, so I can't tell if it ran. Rather than another
|
|
|
- round trip, let me read the identifier out of the package myself.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● The identifier is 8 bytes at descriptor offset 0x58. I have all these configs
|
|
|
- extracted — let me read them directly.
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● The ring devices do have valid, non-zero placement identifiers — so the
|
|
|
- descriptor side is fine. The failure must be that nothing matches them. Let me
|
|
|
- test that directly.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Now I have it. The working devices' identifiers live in a placement table; the
|
|
|
- ring devices' live in their paired object's config. Let me confirm the
|
|
|
- structure.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
- ⎿ Interrupted · What should Claude do instead?
|
|
|
-
|
|
|
-❯ Good news, the beam works but it's backwards. the default is surging and
|
|
|
- surging is the normal
|
|
|
-
|
|
|
-● Beam's alive — and inverted polarity is exactly the pattern the bridges have.
|
|
|
- Fixing it.
|
|
|
-
|
|
|
- Ran 3 shell commands (ctrl+o to expand)
|
|
|
-
|
|
|
-● Fixed and committed — waiting on you to close the game to install (it's
|
|
|
- Lua-only, so a checkpoint restart at the reactor will do; no full replay
|
|
|
- needed).
|
|
|
-
|
|
|
- The polarity fix: these devices carry the same inverted pose as the landing
|
|
|
- and clamshell bridges, where the authored position-0 lane is the driven end
|
|
|
- rather than the resting one. I had it the other way round. Resting is now open
|
|
|
- and the surge drives to close. I replaced beam_drive with beam_pose, which
|
|
|
- takes whether the weapon is surging rather than which endpoint to send, so the
|
|
|
- mapping is stated in one place instead of being re-derived at each call site.
|
|
|
- The dark pose after the deposit also rests in open now rather than sitting in
|
|
|
- the surge.
|
|
|
-
|
|
|
- Worth recording, since it overturns two things I told you:
|
|
|
-
|
|
|
- The devices do drive the beam. I'd argued from linkedPositions == 0 that they
|
|
|
- were unplaced and inert. They're not — enabling them properly was the missing
|
|
|
- piece, and the surge you're seeing is those devices working. My "closed out as
|
|
|
- not reachable" call was wrong, and your original instinct — that the device
|
|
|
- is the thing to treat — was right from the start.
|
|
|
-
|
|
|
- The placement data explains why they looked unplaced. I got a decisive answer
|
|
|
- offline while you were loading: the ring devices have valid non-zero placement
|
|
|
- identifiers, but those identifiers appear in their paired object's config
|
|
|
- (80B3D4E2 for the laser, 80B3D4E8 for the ring), not in the container
|
|
|
- placement table 80B3D356 where every working device's identifier lives. The
|
|
|
- SDK's link builder only searches container placements, so it finds no match,
|
|
|
- produces no link, and the browser draws nothing — while the device itself is
|
|
|
- perfectly real at runtime.
|
|
|
-
|
|
|
- So "no place in the world" was a limitation of the link builder, not a fact
|
|
|
- about the device. That's a genuine generator defect worth fixing so the
|
|
|
- browser stops lying about these rows, but it's cosmetic now that the beam
|
|
|
- works — I'd treat it as separate cleanup rather than hold anything up for it.
|
|
|
-
|
|
|
- The ending fix from earlier is in the same pending install, so once you're
|
|
|
- back in, that run tests both: the surge reading correctly, and whether the
|
|
|
- arrival-window change lets the bookend movies play instead of stalling on
|
|
|
- mission_seed_pending.
|
|
|
-
|
|
|
-✻ Brewed for 1m 9s
|
|
|
-
|
|
|
-❯ the escape ship needs to follow its authored path, there should be a screen
|
|
|
- effect during the surge, and the cutscene didn't fire, it began to fade and
|
|
|
- then kept me in the mission.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● The lease detail gives the answer: arrival=1. My fix was in the right place
|
|
|
- but unreachable.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
-
|
|
|
-● Three separate causes. Let me fix the two I can act on.
|
|
|
-
|
|
|
- Ran 1 shell command (ctrl+o to expand)
|
|
|
- ⎿ You've hit your session limit · resets 4:40pm (Europe/London)
|
|
|
- /upgrade to increase your usage limit.
|
|
|
-
|
|
|
-✻ Cooked for 1m 53s
|