A capture seats a player record, because the interface it loads is a player's

A capture never logs in, so `record_from_roster` answers `None` and the record stayed
empty — and the interface a capture loads is the one a player sees, where there is always
a player. That is the harness diverging from the client, not the other way round:
`Turtle_TransmogUI.lua:17` is `strlower(class)` over `local _, class = UnitClass("player")`
at main-chunk scope, so the nil killed the file and raised an error popup over the middle
of **every UI capture** — visible in the Interface options shot, and in nothing a player
has ever seen (his own session logs nine `Turtle_TransmogUI` lines and no such error).

Minimal and presence-only, the same record `manifest.rs` already seats for the offline
loader and for the same stated reason. Where `$WOW_CAPTURE_SAVED` names a character it is
that name, since the saved variables the capture just loaded are keyed on it.

Verified: `WOW_CAPTURE=ui-options` goes from one raised chain file to 0 runtime errors, and
the shot is a clean Interface page.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
This commit is contained in:
2026-11-05 10:50:43 -07:00
co-authored by Claude Opus 5
parent 167d4721e7
commit 6306fed1ca
+23 -13
View File
@@ -817,19 +817,29 @@ pub(crate) fn load_ingame_ui_on_world_entry(world: &mut World) {
.get_resource::<crate::char_select::Roster>()
.and_then(record_from_roster)
.or_else(|| {
// The other half of the realm above, and for the same reason: `$WOW_CAPTURE_SAVED`
// names the **character** whose saved variables this capture has just loaded, so
// `UnitName("player")` has to answer that name or an addon's `[realm][player]` key
// looks up rows it was not handed. Race, class and sex are presence-only here, as
// `manifest.rs`'s own offline record documents; a fixture that seats a real one
// later overwrites this, and the addon walk has already run by then.
crate::local_state::capture_saved_identity().map(|(_, name)| {
benilla_ui::script::PlayerRecord {
name,
race: Some(("Human".into(), "Human".into())),
class: Some(("Warrior".into(), "WARRIOR".into())),
sex: 2,
}
// A capture never logs in, so it has no roster and no record — and the interface it
// loads is the one a player sees, where there is always a player. Leaving the record
// empty is the harness diverging from the client, not the other way round: a chain
// file reading `UnitClass("player")` at main-chunk scope then takes a nil into
// `strlower` and the whole file dies, which is a popup on every UI capture and
// nothing a player ever meets (`Turtle_TransmogUI.lua:17`). `manifest.rs` makes the
// same argument for its offline loader and seats the same minimal record.
//
// `$WOW_CAPTURE_SAVED` names the **character** whose saved variables this capture has
// just loaded, so where it is given it is the name: an addon's `[realm][player]` key
// has to find the rows it was handed (the realm above is the other half). Race, class
// and sex are presence-only, and a fixture that seats a real one later overwrites
// this — the addon walk has already run by then.
let name = match crate::local_state::capture_saved_identity() {
Some((_, character)) => character,
None if std::env::var_os("WOW_CAPTURE").is_some() => "Benilla".to_owned(),
None => return None,
};
Some(benilla_ui::script::PlayerRecord {
name,
race: Some(("Human".into(), "Human".into())),
class: Some(("Warrior".into(), "WARRIOR".into())),
sex: 2,
})
})
{