From 4764e4fb2ddae95993ca10234a609cdc2945ebda Mon Sep 17 00:00:00 2001 From: grom Date: Sun, 18 Oct 2026 07:52:12 -0600 Subject: [PATCH] framexml: the twenty-one rows of the chain's own toc the manifest still lacked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit benilla loads `assets/ui/benilla.toc`, not the player's `Interface\FrameXML\FrameXML.toc`, so a row the chain carries and the manifest omits is silently absent — no read attempt, no warning. Six went in with the arena templates; this is the rest of the diff but one, each with a comment on what it is for and in the chain's own order. The six baked Octo extensions are the player-visible half. `/pvp` now asks before a War Mode character spends its permanent, persisted opt-out. The exhaustion tooltip reads this realm's 175% instead of 1.12's baked 150%, and `/rested` answers. A player's hover shows the realm's own two challenges, Samurai and Together Forever: the server was already setting bits 10 and 11, and `TargetFrame_UpdateChallenges` walks a list that stopped at 10. The one-shot War Mode offer on arrival from the hardcore realm renders instead of being dropped. `/bug` and `/suggest` exist again — Turtle's FrameXML dropped the BugReport frame, and this rebuilds the dialog over chunked `.bug` SAY commands. And on C'Thun the Ghost debuff's tooltip carries the hardcore afterlife line, which is why the realm reverted that string in Spell.dbc. With them: `OctoToolReqTip`, the realm's own 40 KB recipe-to-tool table wrapping `GetTradeSkillTools`, so a recipe whose tool OctoWoW changed names its real one; six `OctoLocale` rows, each gated on `GetLocale()` and inert here; and the three Turtle windows the manifest said needed verbs built first — arena (4 rows), barbershop, guild bank (2). They need exactly one, `CameraZoomOut`, now built. All three publish their frames and open only on an exact gossip trigger string, so answering nil for `GetGossipText` cannot hide ordinary gossip. `StatsFrame.xml` is the row left out, and the manifest says so where it would sit: the debug-build overlay whose OnUpdate is the only reader of `GetDebugStats`, a binding we do not have, so the row would publish a `ToggleStats` that raises twice a second once pressed. `UNLEARNED_SPELL` joins `UNPRODUCED` rather than getting a producer. It is the only entry there that is not a 1.12 event at all: 5875's event-name pool carries `LEARNED_SPELL_IN_TAB` and `SPELLS_CHANGED` and no unlearn sibling, so the reference ignores that registration exactly as we do, and the War Mode re-scan rides PLAYER_LOGIN and LEARNED_SPELL_IN_TAB, which both fire. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn --- crates/benilla-app/assets/ui/benilla.toc | 91 ++++++++++++++++--- .../benilla-app/src/ui_script/reference_ui.rs | 9 ++ 2 files changed, 88 insertions(+), 12 deletions(-) diff --git a/crates/benilla-app/assets/ui/benilla.toc b/crates/benilla-app/assets/ui/benilla.toc index 402d8b3e..2ca20dac 100644 --- a/crates/benilla-app/assets/ui/benilla.toc +++ b/crates/benilla-app/assets/ui/benilla.toc @@ -17,6 +17,22 @@ Interface\FrameXML\Fonts.xml # Second, not first as in the reference, because entry 0 must be Fonts.xml. Interface\FrameXML\GlobalStrings.lua +# OctoWoW's own seven rows between GlobalStrings and Globals (its `FrameXML.toc` 4-10). Each +# `OctoLocale_*` file is one `if GetLocale() == "xxXX"` block of GlobalStrings overrides and is +# inert on an enUS chain, but they load as the reference loads them, so a client started in +# another locale reads the realm's own strings rather than ours. `OctoToolReqData.lua` is the +# realm's 40 KB recipe -> required-tool-item table and `OctoToolReqTip.lua` wraps +# `GetTradeSkillTools` over it: a recipe whose tool OctoWoW changed (the jeweler's kits, the +# Whittle) reads its real tool in the trade-skill window, and the universal knife (item 50006) +# satisfies any of them. The wrap is engine-level (`GetTradeSkillTools` is a binding, not +# FrameXML), so its place this early is the reference's and costs nothing. +Interface\FrameXML\OctoLocale\OctoLocale_deDE.lua +Interface\FrameXML\OctoLocale\OctoLocale_esES.lua +Interface\FrameXML\OctoLocale\OctoLocale_ptBR.lua +Interface\FrameXML\OctoLocale\OctoLocale_ruRU.lua +Interface\FrameXML\OctoLocale\OctoLocale_zhCN.lua +Interface\FrameXML\OctoToolReqTip\OctoToolReqData.lua +Interface\FrameXML\OctoToolReqTip\OctoToolReqTip.lua # TurtleWoW's own two rows after GlobalStrings (its `FrameXML.toc` 11-12), both the client half of # server-side systems. `Globals.lua` publishes `print`, `TURTLE_WOW_VERSION`, `TW_CLASS_TOKEN`, # `Turtle_AvailableChallenges`, `GAME_YELLOW` and the three `ADDON_MSG_*_DELIMITER`s that every @@ -27,6 +43,11 @@ Interface\FrameXML\GlobalStrings.lua # row the chain's `WorldMapContinent.dbc` carries. Interface\FrameXML\Globals.lua Interface\FrameXML\Overrides.lua +# The chain's row 14, immediately after its own Fonts.xml (our entry 0): it repoints the ~50 +# FrameXML font objects at `Fonts\FZLBJW.TTF` for ruRU and zhCN only, so on an enUS client every +# `GetFont`/`SetFont` pair it runs is a no-op. Faithful and inert, and the one row that makes a +# Cyrillic or CJK login legible. +Interface\FrameXML\OctoLocale\OctoLocale_Fonts.lua # `Localize()` runs at load and overwrites GlobalStrings keys, so this follows them. Interface\FrameXML\Localization.xml # `GetText` is a Lua global, not an engine binding: the client's `0x703bf0` calls it. @@ -137,6 +158,12 @@ Interface\FrameXML\HonorFrame.xml # Ours: the sixth tab page TurtleWoW's `CharacterFrame.lua` lists and 1.12 never shipped. CharacterFrameAdapters.xml Interface\FrameXML\DressUpFrame.xml +# Deliberately absent, the chain's `StatsFrame.xml` would sit here (its `FrameXML.toc` 60): the +# debug-build frame-stat overlay, `hidden="true"` with an OnUpdate that is the only reader of +# `GetDebugStats()` — a binding 5875 has and benilla does not, and whose readout is a debug +# build's own, not something a player sees. Loading the row would publish a `ToggleStats` that +# raises twice a second once pressed; leaving it out leaves `ToggleStats` nil, which is what an +# unbound key already does. Build `GetDebugStats` and this row costs nothing. Interface\FrameXML\SpellBookFrame.xml # Ours: the pet page's autocast widgets in the pet action button's proportions. SpellBookAdapters.xml @@ -179,7 +206,29 @@ Interface\FrameXML\LFT\LFT_Data.lua Interface\FrameXML\LFT\LFT.lua Interface\FrameXML\LFT\LFTTemplates.xml Interface\FrameXML\LFT\LFT.xml +# OctoWoW's six baked single-file extensions (its `FrameXML.toc` 139-148), all Lua over verbs that +# already exist, and baked into the chain rather than shipped as AddOns precisely so a player +# cannot switch them off. In the reference's order, which puts the first of them above +# OctoLFTBlinkPause. +# `OctoWowWarModeConfirm` wraps `SlashCmdList["PVP"]`: on the War Mode challenge (spell named +# "War Mode" in the spellbook) /pvp raises a confirm popup first, because the server reads a +# /pvp from such a character as a permanent, persisted opt-out. +Interface\FrameXML\OctoWowWarModeConfirm\OctoWowWarModeConfirm.lua Interface\FrameXML\OctoLFTBlinkPause\OctoLFTBlinkPause.lua +# `OctoRestedTooltip` wraps `GetRestState` so the exhaustion tooltip reads the realm's 175% rather +# than 1.12's baked 150%, and adds `/rested`; the multiplier is display-only in 1.12, the XP bar +# itself reads the state id. +Interface\FrameXML\OctoRestedTooltip\OctoRestedTooltip.lua +# `OctoChallengeTip` appends entries 11 and 12 to `Turtle_AvailableChallenges` (Globals.lua above), +# which is what `TargetFrame_UpdateChallenges` walks bit by bit — so the realm's own two +# challenges, Samurai and Together Forever, stop being dropped from a player's hover. +Interface\FrameXML\OctoChallengeTip\OctoChallengeTip.lua +# `OctoWarModeOffer` renders the one-shot War Mode offer the server sends as a `TW_WARMODE` +# `S2C_OFFER` addon message on arrival from the hardcore realm, and answers C2S_ACCEPT/C2S_DECLINE. +Interface\FrameXML\OctoWarModeOffer\OctoWarModeOffer.lua +# `RestoreBugCommand` rebuilds `/bug` and `/suggest`: Turtle's FrameXML dropped the BugReport frame +# altogether, so this builds its own dialog and sends the report as chunked `.bug` SAY commands. +Interface\FrameXML\RestoreBugCommand\RestoreBugCommand.lua # TurtleWoW's own three loose rows (its `FrameXML.toc` 103-105), all Lua over verbs that already # exist. `Hooks.lua` is the realm's tooltip layer: the guild line under a player's name (gated on # its own `TOOLTIP_GUILD_NAMES` CVar), the shift-click hint while a trade, auction or mail window @@ -191,14 +240,30 @@ Interface\FrameXML\OctoLFTBlinkPause\OctoLFTBlinkPause.lua Interface\FrameXML\Hooks.lua Interface\FrameXML\ChronoboonTimers.lua Interface\FrameXML\SpellChatLinks.lua +# Turtle's `# Arena` block (its `FrameXML.toc` 108-112), in its own order. `Turtle_ArenaUI.lua` +# is the whole client half of the realm's arena: the `TW_ARENA` addon-message protocol, the team +# roster and the queue. `Turtle_ArenaUITemplates.xml` carries `ArenaTeamTemplate`, which +# `Blizzard_InspectUI`'s own `InspectArenaFrame.xml` inherits for its three team buttons before +# reading `$parentText`, `$parentDetails` and nine `$parentDetails*` children by name — without +# that row the inspect window raised four times per inspect, three OnLoads and +# `InspectArenaFrame_OnShow`. +Interface\FrameXML\Turtle_ArenaUI\Turtle_ArenaUI.lua +Interface\FrameXML\Turtle_ArenaUI\Turtle_ArenaUITemplates.xml +Interface\FrameXML\Turtle_ArenaUI\Turtle_ArenaFrame.xml +Interface\FrameXML\Turtle_ArenaUI\Turtle_ArenaQueueFrame.xml +Interface\FrameXML\Turtle_ArenaUI\Turtle_ArenaRegistrarFrame.xml +# Turtle's barbershop, one row that scripts its own `Turtle_Barbershop.lua`: the window opens on a +# `TW_BARBERSHOP` addon message (no gossip hook — it watches CHAT_MSG_ADDON, PLAYER_MONEY and +# UNIT_MODEL_CHANGED) and drives a live 3-D preview, zooming the world camera out two yards at the +# open (`Turtle_Barbershop.lua:211`). `CameraZoomOut` was the one verb these three windows call +# that we did not have; it is built now, with `CameraZoomIn`. +Interface\FrameXML\Turtle_BarbershopUI\Turtle_Barbershop.xml # TurtleWoW's own FrameXML additions, in the reference `FrameXML.toc` order (patch-3.mpq). These # are the client half of Turtle's custom systems: `Turtle_TransmogUI` hooks `GOSSIP_SHOW`, hides # the stock gossip frame for its NPCs and drives the transmog window over `TW_TRANSMOG` addon # messages; `Turtle_ShopUI` (prefix `TW_SHOP`) is the custom merchant/shop. Without these rows the # server's trigger gossip text (`TRANSMOG_TRIGGER`, `CUSTOM_MERCHANT_TRIGGER`) is what the stock -# gossip window shows, and neither custom window exists. Turtle's Inspect-Talents and Guild-Bank -# UIs are the same pattern but need `ToggleInspect`/`SetTalentButtonLocation` and the GuildBank -# globals built first, so they are not loaded here yet. +# gossip window shows, and neither custom window exists. Interface\FrameXML\Turtle_TransmogUI\Turtle_TransmogSets.lua # The slot buttons in Turtle_TransmogUI.xml inherit TransmogPlayerSlotTemplate, and the look grid # and new-transmog alert inherit TransmogFrameLookTemplate/TransmogWonItemTemplate; without this @@ -207,15 +272,12 @@ Interface\FrameXML\Turtle_TransmogUI\Turtle_TransmogUITemplates.xml Interface\FrameXML\Turtle_TransmogUI\Turtle_TransmogUI.xml Interface\FrameXML\Turtle_ShopUI\Turtle_ShopUITemplates.xml Interface\FrameXML\Turtle_ShopUI\Turtle_ShopUI.xml -# Turtle's arena templates, the one row of its `# Arena` block (its `FrameXML.toc` 108-112) that -# stands alone: it inherits nothing but stock fonts and declares no handler of its own at load. -# `Blizzard_InspectUI`'s own `InspectArenaFrame.xml` inherits `ArenaTeamTemplate` for its three -# team buttons and then reads `$parentText`, `$parentDetails` and nine `$parentDetails*` children -# by name, so without this row the inspect window raised four times per inspect — three OnLoads -# and `InspectArenaFrame_OnShow`. The other four rows (`Turtle_ArenaUI.lua` and the arena, queue -# and registrar windows) are the same pattern as the Inspect-Talents and Guild-Bank UIs above: -# they need the arena verbs built first, so they are not loaded here yet. -Interface\FrameXML\Turtle_ArenaUI\Turtle_ArenaUITemplates.xml +# Turtle's guild bank (its `FrameXML.toc` 126-127): the templates first, then the window, which +# scripts its own 60 KB `Turtle_GuildBankUI.lua` — a `GOSSIP_SHOW` hook for the banker NPCs over +# `TW_GUILDBANK` messages, with the tab rights read off `GuildControlGetNumRanks`/`GetRankName` +# and so a `GUILD_ROSTER_UPDATE`/`PLAYER_GUILD_UPDATE` listener too. +Interface\FrameXML\Turtle_GuildBankUI\Turtle_GuildBankUITemplates.xml +Interface\FrameXML\Turtle_GuildBankUI\Turtle_GuildBankUI.xml # Turtle's honour/arena merchant (Stormwind armoury PvP gear, the Custom_Merchant NPCs): it hooks # `GOSSIP_SHOW`, hides the gossip frame for an NPC whose greeting is `CUSTOM_MERCHANT_TRIGGER` and # fills over `TW_Merchant` addon messages. Without it that trigger text is what the stock gossip @@ -231,6 +293,11 @@ Interface\FrameXML\Custom_Merchant\CustomMerchantFrame.xml # `SMSG_PLAY_MUSIC` naming a `SoundEntries.dbc` row whose file is a live HTTP stream URL. Interface\FrameXML\EverlookBroadcastingCo\EverlookBroadcastingCo.xml Interface\FrameXML\OctoRadioPlaceholder\OctoRadioPlaceholder.lua +# `OctoGhostGate`, last of the realm's six baked extensions: it post-hooks +# `GameTooltip:SetUnitDebuff` and, when the hovered debuff is titled exactly "Ghost", rewrites +# line 2 with the hardcore afterlife line — gated at PLAYER_LOGIN on `GetRealmName() == "C'Thun"`, +# because Spell.dbc loads before a realm is chosen and the realm wants the line on C'Thun only. +Interface\FrameXML\OctoGhostGate\OctoGhostGate.lua # AIO, the realm's client<->server transport (its FrameXML.toc bakes it so no AddOn is needed). # Before OctoCalendar, which feeds from it: the calendar registers an AIO handler at load and # queues its guild-permission request until AIO is up (`OctoCalendar.lua:919-920`). diff --git a/crates/benilla-app/src/ui_script/reference_ui.rs b/crates/benilla-app/src/ui_script/reference_ui.rs index 56149076..a9f8be3d 100644 --- a/crates/benilla-app/src/ui_script/reference_ui.rs +++ b/crates/benilla-app/src/ui_script/reference_ui.rs @@ -1895,6 +1895,15 @@ mod tests { "four files — the paperdoll model refresh", ), ("UNIT_PORTRAIT_UPDATE", "three files — the portrait refresh"), + ( + "UNLEARNED_SPELL", + "OctoWowWarModeConfirm.lua — and the only entry here that is not a 1.12 event at \ + all: `UNLEARNED_SPELL` is absent from 5875's own event-name pool (which carries \ + `LEARNED_SPELL_IN_TAB` and `SPELLS_CHANGED` right beside where it would sit), so \ + the reference ignores the registration exactly as we do. The addon re-scans the \ + spellbook for the \"War Mode\" spell on PLAYER_LOGIN and LEARNED_SPELL_IN_TAB \ + too, and both of those fire, so its /pvp guard is live either way", + ), ( "ZONE_UNDER_ATTACK", "ChatFrame.lua — the reference's `SMSG_ZONE_UNDER_ATTACK` line (\"%s is under \