- forty files that carried the reference's literal Lua are rewritten as our own expression of the behaviour — worst identical run 61 lines down to 7 — and the README now says exactly that - the overlap gate measures the code itself across all four reference corpora, and ratchets: the number may only go down - a lost session ends at the login screen instead of silently re-authenticating and stealing the account back - a building's skybox is a real model: Caverns of Time's white ceiling becomes its painted nebula and additive stars Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
95 lines
5.2 KiB
XML
95 lines
5.2 KiB
XML
<Ui xmlns="http://www.blizzard.com/wow/ui/">
|
|
<!--
|
|
The duel UI (decision 0633): the two duel dialogs on our shared StaticPopup engine
|
|
(UiPanels.xml) plus the duel-event driver. The patch-chain FrameXML (mpqx extraction,
|
|
decision 0246) is the SPECIFICATION — StaticPopup.lua l.1103-1120 (DUEL_REQUESTED +
|
|
DUEL_OUTOFBOUNDS), UIParent.lua l.98-101 (the registrations) + l.378-393 (the event arms)
|
|
— and what it fixes is contract: the two dialog keys, the StaticPopupDialogs field names,
|
|
the sound kit and the two timeouts are all addressed by name, so they are reproduced
|
|
exactly while the entries around them are written here in our own shape. The strings are
|
|
the shipped enUS values from GlobalStrings.lua, quoted as data.
|
|
|
|
Duels have no window of their own — these two dialogs ARE the whole duel UI. Everything
|
|
else is engine-side: the "Duel starting: N" countdown and the outcome line are
|
|
CHAT_MSG_SYSTEM lines `crate::ui_duel` composes (byte-verified: WoW.exe's own duel TU emits
|
|
both through the chat path with type 0x0A, not through any frame), and the four events
|
|
below are fired from that module's state edges.
|
|
|
|
The DUEL_OUTOFBOUNDS dialog is text-only — no buttons, timeout 10 — and its text is filled
|
|
by the StaticPopup engine's per-tick countdown branch, which already names it in both of
|
|
its special-case lists (UiPanels.xml: the show-time " " seeding and the OnUpdate re-format).
|
|
The 10 s is the client's dialog timeout, and it coincides with the server's own forfeit
|
|
window (`Player::CheckDuelDistance`) rather than driving it: the popup expiring is cosmetic,
|
|
the forfeit is the server's.
|
|
-->
|
|
<Script><![CDATA[
|
|
-- ── Strings (the shipped enUS GlobalStrings.lua values, quoted as data) ─────────────────
|
|
local DUEL_REQUESTED = "%s has challenged you to a duel." -- l.957
|
|
local DUEL_OUTOFBOUNDS_TIMER = "Exiting duel area, you will forfeit in %d %s." -- l.956
|
|
local ACCEPT = "Accept"
|
|
local DECLINE = "Decline"
|
|
|
|
-- ── The challenge dialog (spec: StaticPopup.lua l.1103-1116) ────────────────────────────
|
|
-- Written scalars-first, handlers-last: what the dialog IS, then what answering it does.
|
|
--
|
|
-- No accept-guard flag (unlike PARTY_INVITE): the entry declines only on an explicit
|
|
-- OnCancel, so a timeout or an override hides it WITHOUT sending anything. That is not an
|
|
-- oversight to "fix" — the server's own 60 s is not a thing either; an unanswered challenge
|
|
-- simply sits until one side acts.
|
|
StaticPopupDialogs["DUEL_REQUESTED"] = {
|
|
text = DUEL_REQUESTED,
|
|
button1 = ACCEPT,
|
|
button2 = DECLINE,
|
|
sound = "igPlayerInvite",
|
|
timeout = 60,
|
|
hideOnEscape = 1,
|
|
-- The two buttons are the two replies. ESC arrives here as well — hideOnEscape routes
|
|
-- an escape through OnCancel — so backing out and declining are deliberately one path.
|
|
OnAccept = function()
|
|
AcceptDuel()
|
|
end,
|
|
OnCancel = function()
|
|
CancelDuel()
|
|
end,
|
|
}
|
|
|
|
-- ── The out-of-bounds warning (spec: StaticPopup.lua l.1117-1120) ───────────────────────
|
|
-- Two fields and nothing else: no buttons, because there is nothing to answer, and no
|
|
-- text of its own — the engine's countdown branch writes it every tick.
|
|
StaticPopupDialogs["DUEL_OUTOFBOUNDS"] = {
|
|
text = DUEL_OUTOFBOUNDS_TIMER,
|
|
timeout = 10,
|
|
}
|
|
|
|
-- ── The duel event arms (spec: UIParent.lua l.378-393) ──────────────────────────────────
|
|
function BenillaDuelDriver_OnEvent()
|
|
if event == "DUEL_REQUESTED" then
|
|
StaticPopup_Show("DUEL_REQUESTED", arg1)
|
|
elseif event == "DUEL_OUTOFBOUNDS" then
|
|
StaticPopup_Show("DUEL_OUTOFBOUNDS")
|
|
elseif event == "DUEL_INBOUNDS" then
|
|
StaticPopup_Hide("DUEL_OUTOFBOUNDS")
|
|
elseif event == "DUEL_FINISHED" then
|
|
-- Both, unconditionally: a duel that ends while the challenge popup is still up
|
|
-- (the other side cancelled first) must not leave it there.
|
|
StaticPopup_Hide("DUEL_REQUESTED")
|
|
StaticPopup_Hide("DUEL_OUTOFBOUNDS")
|
|
end
|
|
end
|
|
]]></Script>
|
|
|
|
<Frame name="BenillaDuelDriver" hidden="true">
|
|
<Size><AbsDimension x="1" y="1"/></Size>
|
|
<Anchors><Anchor point="TOPLEFT"/></Anchors>
|
|
<Scripts>
|
|
<OnLoad>
|
|
self:RegisterEvent("DUEL_REQUESTED")
|
|
self:RegisterEvent("DUEL_OUTOFBOUNDS")
|
|
self:RegisterEvent("DUEL_INBOUNDS")
|
|
self:RegisterEvent("DUEL_FINISHED")
|
|
</OnLoad>
|
|
<OnEvent>BenillaDuelDriver_OnEvent()</OnEvent>
|
|
</Scripts>
|
|
</Frame>
|
|
</Ui>
|