- a cinematic holds the body while the camera flies: the streaming focus follows the eye — a Tauren's intro opens 1741 yards from the body — so the body's own ground unloaded under it and it fell (z=59.4 to −62 in four seconds, the server yanking it back); it now takes the same hold a teleport takes, released when the focus comes home to a resident tile, and the loading screen stops covering the fly-by, because "the player's ground is missing" is not a load while the eye is deliberately elsewhere; the letterbox measurement prints as an ordinary info line, and scripts/cine.sh plays any one cinematic and prints what the client did to the world while the camera was away
- a cinematic cuts the zone music: the reference asserts exactly what /console EnableMusic 0 asserts, through the same setter — a cut, not a fade, the music pump dead for the duration, resume at +3.000 s — and benilla asserts the runtime flag, never the CVar, or quitting during a 102-second intro would save your music off for good; ambience is deliberately untouched (it has the analogous flag and the cinematic never writes it); the narration has no category at all — its flags route it around every volume slider but not around the Enable Sound Effects gate, so unchecking that silences it — and the listener follows the cinematic camera for the duration
- addons can walk a UI they did not build: GetChildren/GetNumChildren/GetRegions/GetNumRegions land — the basis of the whole reskin genre, and the wall four of the twenty most-installed 1.12 addons died on: pfUI drew nothing before and now paints 495 quads, ShaguDPS 71 → 566, pfQuest 3 → 498 — with the reference's own quirks: the title region is NOT in the list (its creation path never reaches the region linker), hidden regions are returned and counted, oldest first; the Model widget gets its Lua surface (SetModel, SetSequence and siblings, read out of the shipped image, where SetRotation and SetFacing are two names for one slot); and the Minimap carries the nine engine-created Model children no XML declares, built before the frame descent, the ninth being the player arrow Questie indexes as ({Minimap:GetChildren()})[9]
- all seven chat windows come from one template, tabs and scroll buttons included — whether a window is shown has nothing to do with whether its globals resolve, and pfUI reads every piece of that furniture for all seven, unguarded; isDocked only on windows 1 and 2 (the chat-cache's own DOCKED byte), SELECTED_CHAT_FRAME seated beside DEFAULT_CHAT_FRAME (the window you last picked vs the one FrameXML prints to), and the four per-window fields ChatFrame_OnLoad seats; two more one-name walls fell — a Button's label answers to its second spelling NormalText, which KLHThreatMeter's column headers die without, and ABANDON_QUEST_WITH_ITEMS is declared because a dialog table is read at load whatever the client later shows, leaving Questie with zero errors of ours — and the addon harness gains --probe/--eval, one addon's VM answering a question in ~5 s instead of a 90 s corpus run
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1947 lines
144 KiB
XML
1947 lines
144 KiB
XML
<Ui>
|
||
<!--
|
||
benilla's quest log window (decision 0088 arc, the quest-log slice — the sibling of
|
||
`QuestFrame.xml`'s questgiver window, dressed from the real 1.12 `QuestLogFrame.xml`/
|
||
`QuestLogFrame.lua` (scratchpad `ref-framexml/QUESTLOG-PIN.md`; section cites below are into
|
||
that pin, `file:line` cites are into the pin's own extracted `QuestLogFrame.xml`/`.lua`). One
|
||
`QuestLogFrame` carries BOTH the list page and the detail page — FLAT layout (decision
|
||
0088 §2, quoted in `QuestFrame.xml`'s header): a child frame shown at runtime does not render
|
||
its own `<Layers>` FontStrings in this engine, so every FontString/Button here lives directly
|
||
on the one always-visible window, never on a nested sub-frame. `enableMouse`/`toplevel`/
|
||
`movable` are LoadXML no-ops in this engine (`loader.rs` warn-once gaps) — omitted here exactly
|
||
as `QuestFrame.xml` omits them; they cost nothing since Buttons are mouse-enabled by
|
||
construction regardless (`widget/mod.rs`'s ctor comment).
|
||
|
||
Docks the left UIPanel slot exactly like Gossip/Merchant/Quest (`UiPanels.xml`
|
||
`UIPanelWindows["QuestLogFrame"] = { area = "left", pushable = 0, whileDead = 1 }`
|
||
(whileDead carried since 1507), pin §8's
|
||
`UIParent.lua l.25` quote) — so it competes for/replaces those windows, never stacks with
|
||
them. UNLIKE those windows this is not an NPC session: no `CloseX()` on hide, no range guard;
|
||
it is durable player state the app can push at any time (`benilla-ui`'s `quest_log.rs` module
|
||
doc). `ToggleQuestLog()` (pin §8, `QuestLogFrame.lua:24-30`) is the show/hide entry point the
|
||
app's 'L' binding already calls (`ui_script/mod.rs`).
|
||
|
||
Faux-scroll (pin §2): 6 title rows (`QUESTS_DISPLAYED`), a Lua-side `questLogOffset` upvalue
|
||
standing in for the real `QuestLogListScrollFrame`/`FauxScrollFrame_Update` (no real
|
||
ScrollFrame/FauxScrollFrame engine exists yet) — `<OnMouseWheel>` adjusts it directly. The
|
||
wheel handler lives on the window Frame itself: the engine bubbles a spin UP the parent chain
|
||
(`script/pointer.rs` `mouse_wheel`), so a spin over a title row (no handler of its own) rises to
|
||
this window and scrolls. (A bare `<Frame>` is not a mouse HIT target — only
|
||
Button/CheckButton/EditBox/ScrollingMessageFrame are, `widget/mod.rs`'s ctor comment, and
|
||
`enableMouse` is a no-op stub — but it is still a valid bubble ANCESTOR: bubbling checks for the
|
||
handler, not mouse-enablement.) The `QuestLogWheelCatcher` BUTTON, declared FIRST so every
|
||
real row out-ranks it in hit-testing (`order::hit_test` walks the draw-order-descending list),
|
||
now only gives the list's EMPTY tail a hit-target whose spin also bubbles here.
|
||
|
||
v1 scope/deviations from the pin (each cited again at its own widget below):
|
||
- The LIST page still has no real ScrollFrame — `questLogOffset`'s faux-scroll stands in
|
||
(this comment's own "Faux-scroll" paragraph above); real real-estate accounting there
|
||
would need a genuine header/collapse model this v1 doesn't ship. The DETAIL page now
|
||
DOES sit on a real ScrollFrame (`QuestLogDetailScroll`, decision 0112's mechanism)
|
||
— a quest with many objectives/a long description/many rewards scrolls and clips at the
|
||
pane's own edge instead of running past the window's bottom (pin §3's doNotScroll
|
||
asymmetry is implemented — see `BenillaQuestLogDetail_Update`'s own comment).
|
||
- Difficulty coloring wears the reference's names and bands (`QuestDifficultyColor` +
|
||
`GetDifficultyColor`, specified at l.14-20 + l.584-599) over the real
|
||
`GetQuestGreenRange()` binding — see the function's own comment. (The old
|
||
`BenillaQuestDifficultyColor` INTERIM and its approximated thresholds are retired.)
|
||
- No headers ship (`benilla-ui`'s `quest_log.rs`: flat entries only, headers need the
|
||
QuestSort/AreaTable DBC join) — the header branch below is dead code today, kept for when
|
||
that join lands rather than re-derived then.
|
||
- No party share/push, no timed-quest countdown, no reward-spell row — still-named v1 stubs
|
||
in `benilla-ui`'s `quest_log.rs`. Quest-watch tracking (this comment's own arc) IS wired.
|
||
- `GetQuestLogRequiredMoney()` exists on the Lua surface (pin §3/§6) but is not wired to a
|
||
detail-pane line — rare in vanilla (ferry-style quests), a documented v1 gap.
|
||
- `EmptyQuestLogFrame` (pin §2, a whole separate book-art frame) is simplified to one
|
||
centered FontString + hidden rows on this same window.
|
||
- The abandon confirm is the ref's `ABANDON_QUEST` entry on the shared StaticPopup
|
||
engine (UiPanels.xml, decision 0308 §3).
|
||
- Quest-watch toggle is SHIFT+left-click, the ref's own fork (pin §5,
|
||
`QuestLogTitleButton_OnClick`, `QuestLogFrame.lua:469-505`). The modifier plumbing this
|
||
note once named as the missing engine slice (`IsShiftKeyDown` + the app's per-frame
|
||
mirror) landed with the cursor arc; the interim right-click substitute is retired.
|
||
- The two ref watch errors (`QUEST_WATCH_NO_OBJECTIVES`/`QUEST_WATCH_TOO_MANY`) go out
|
||
through the reference's own `UIErrorsFrame:AddMessage`. That was once impossible here —
|
||
`UIErrorsFrame` was a hand-rolled `<Frame>` reachable only by firing `UI_ERROR_MESSAGE`
|
||
from Rust — and the guards no-opped silently in the interim; the MessageFrame widget
|
||
(`script::messageframe::plain`) closed it, and the seam this note asked for turned out
|
||
to be the real widget method rather than a benilla global.
|
||
-->
|
||
<Script><![CDATA[
|
||
QUESTS_DISPLAYED = 6 -- QUESTS_DISPLAYED (pin §2, QuestLogFrame.lua:1)
|
||
MAX_QUESTLOG_QUESTS = 20 -- MAX_QUESTLOG_QUESTS (pin §2, :6) — display cap only
|
||
MAX_OBJECTIVES = 10 -- MAX_OBJECTIVES (pin §3, QuestLogFrame.lua:3)
|
||
-- Reward/choice row cap: the SAME v1 cap `QuestFrame.xml`'s BENILLA_QUEST_MAX_ITEMS uses (the
|
||
-- ref's own MAX_NUM_ITEMS is 10, QuestFrame.lua:2 — we halve it there too).
|
||
BENILLA_QUESTLOG_MAX_ITEMS = 6
|
||
-- MAX_WATCHABLE_QUESTS (pin §2/§5, QuestLogFrame.lua:8) — the SAME cap `quest_log.rs`'s
|
||
-- AddQuestWatch already enforces engine-side; this is just this file's own guard so the
|
||
-- right-click handler can skip the AddQuestWatch call (and its error) locally.
|
||
BENILLA_QUESTLOG_MAX_WATCHES = 5
|
||
-- The tracker HUD's flat line pool (ref MAX_QUESTWATCH_LINES, QuestLogFrame.lua:7):
|
||
-- one rolling pool across every watch, dynamically re-chained each paint — the ref's own
|
||
-- model (the old fixed 5×(1+4) per-slot grid predated region Show/Hide/SetPoint).
|
||
BENILLA_QUESTWATCH_LINES = 30
|
||
-- The timed-quest countdown row (decision 1150). UPDATE_DELAY is the ref's own
|
||
-- (QuestLogFrame.lua:5) — the throttle on the "Time Remaining:" repaint, not a benilla
|
||
-- dial. TIME_REMAINING is the shipped enUS GlobalString (GlobalStrings.lua:4248), inlined
|
||
-- like every other string in these files (we load no GlobalStrings.lua).
|
||
BENILLA_QUESTLOG_UPDATE_DELAY = 0.1
|
||
BENILLA_TIME_REMAINING = "Time Remaining:"
|
||
|
||
-- The detail pane's ScrollFrame child-resize sum (`BenillaQuestLogDetail_ResizeChild`'s own
|
||
-- comment) — fixed offsets/row heights transcribed from this chain's own FontString/SetPoint
|
||
-- comments below, gathered here with the file's other constants.
|
||
BENILLA_QUESTLOG_DETAIL_TOP = 5 -- child TOPLEFT -> QuestTitle (ref :624-635, offset 5,-5)
|
||
BENILLA_QUESTLOG_DETAIL_OBJ_GAP = 10 -- ObjectivesText->Objective1 AND last objective/
|
||
-- ObjectivesText->DescriptionTitle (both -10, XML/Lua)
|
||
BENILLA_QUESTLOG_DETAIL_OBJ_ROW = 12 -- one objective line (Objective1's own comment)
|
||
BENILLA_QUESTLOG_DETAIL_OBJ_STEP = 2 -- gap between objective lines
|
||
BENILLA_QUESTLOG_DETAIL_BOTTOM_PAD = 10 -- v1: a little breathing room past the last row
|
||
-- The detail pane's minimal scrollbar (`BenillaQuestLogDetailScroll_SyncBar`'s own comment).
|
||
BENILLA_QUESTLOG_SCROLL_STEP = 20 -- px per wheel notch / arrow click
|
||
BENILLA_QUESTLOG_SCROLL_TRACK_H = 229 -- ScrollFrame height 261 - 16 (up) - 16 (down)
|
||
BENILLA_QUESTLOG_SCROLL_THUMB_H = 16
|
||
|
||
-- The faux-scroll offset (pin §2's FauxScrollFrame stand-in) — a plain chunk-local upvalue
|
||
-- every function below closes over, the same pattern `UiPanels.xml`'s `slots` table uses.
|
||
local questLogOffset = 0
|
||
|
||
-- The detail pane's last-computed resize inputs (`BenillaQuestLogDetail_ResizeChild`'s own
|
||
-- comment on WHY a re-check is needed at all: `GetHeight()` on the auto-height FontStrings
|
||
-- is one tick stale on the FIRST populate of brand-new text — the host measures it only on
|
||
-- the NEXT `resolve()`/measure round-trip, which lands after this Lua tick already returned.
|
||
-- Detail_Update has no reason to run again once the quest log's data stops changing, so
|
||
-- nothing would ever ask for the now-correct height — these upvalues let the ScrollFrame's
|
||
-- own `<OnUpdate>` re-ask every frame (cheaply — see that handler's own comment) using the
|
||
-- SAME inputs the last full populate computed, until the measured heights catch up and the
|
||
-- resize stops changing.
|
||
local detailObjAnchorIndex = 0
|
||
local detailRewardHeight = 18
|
||
-- The last height actually applied via SetHeight — lets the OnUpdate re-check below skip
|
||
-- SetHeight/UpdateScrollChildRect (and the OnScrollRangeChanged repaint it fires) entirely
|
||
-- once the resize has converged and stopped changing, rather than redoing that work every
|
||
-- single frame forever while the window sits open.
|
||
local detailLastAppliedHeight = nil
|
||
|
||
-- ── Difficulty coloring ──────────────────────────────────────────────────────────────────
|
||
-- The six bands and their exact colors are the reference's contract, not a palette of ours:
|
||
-- ref-QuestLogFrame.lua's table (l.14-20) and GetDifficultyColor (l.584-599, "Used for
|
||
-- quests and enemy coloration" — the ref's own comment; the TARGET FRAME's level number
|
||
-- colors through this same function, TargetFrame_CheckLevel l.130), and `QuestDifficultyColor`
|
||
-- is a name addons read, so both the global and its six keys are fixed. The green→grey
|
||
-- boundary is the real GetQuestGreenRange() binding (benilla-ui unit.rs — the byte-verified
|
||
-- grey band the plate/tooltip share; the binding's own byte read is under the 2026-07-17
|
||
-- wow-re §5). This retires the BenillaQuestDifficultyColor INTERIM and its approximated
|
||
-- -2/-10 thresholds.
|
||
QuestDifficultyColor = {
|
||
impossible = { r = 1.00, g = 0.10, b = 0.10 },
|
||
verydifficult = { r = 1.00, g = 0.50, b = 0.25 },
|
||
difficult = { r = 1.00, g = 1.00, b = 0.00 },
|
||
standard = { r = 0.25, g = 0.75, b = 0.25 },
|
||
trivial = { r = 0.50, g = 0.50, b = 0.50 },
|
||
header = { r = 0.70, g = 0.70, b = 0.70 },
|
||
}
|
||
|
||
-- How far ABOVE the player the quest sits picks the band. Note the shape of the last two
|
||
-- tests: the three hard bands are fixed offsets, but the green/grey boundary is not a
|
||
-- constant at all — GetQuestGreenRange() widens as the player levels — which is why it is
|
||
-- asked rather than compared against a number, and why "trivial" is what is left over
|
||
-- rather than a band with an edge of its own.
|
||
function GetDifficultyColor(level)
|
||
local levelDiff = level - UnitLevel("player")
|
||
if levelDiff >= 5 then
|
||
return QuestDifficultyColor.impossible
|
||
elseif levelDiff >= 3 then
|
||
return QuestDifficultyColor.verydifficult
|
||
elseif levelDiff >= -2 then
|
||
return QuestDifficultyColor.difficult
|
||
elseif -levelDiff <= GetQuestGreenRange() then
|
||
return QuestDifficultyColor.standard
|
||
end
|
||
return QuestDifficultyColor.trivial
|
||
end
|
||
|
||
-- ── The list page ────────────────────────────────────────────────────────────────────────
|
||
-- `mouseButton` is arg1 off RegisterForClicks("LeftButtonUp", "RightButtonUp")
|
||
-- (BenillaQuestLogTitleTemplate's OnLoad). The watch toggle is SHIFT+left-click, the ref's
|
||
-- own fork (QuestLogFrame.lua:469-505) — the modifier plumbing this file's header once
|
||
-- named as the missing engine slice landed with the cursor arc (0216/0218 follow-up), so
|
||
-- the documented right-click substitute is retired.
|
||
function BenillaQuestLogTitle_OnClick(button, mouseButton)
|
||
local index = button.questIndex
|
||
if not index then return end
|
||
local _, _, _, isHeader, isCollapsed = GetQuestLogTitle(index)
|
||
if isHeader then
|
||
-- pin §5, QuestLog_SetSelection (QuestLogFrame.lua:321-329): a header never becomes
|
||
-- the selection, it only (un)collapses. No header ever ships in v1 (module doc,
|
||
-- `benilla-ui/src/script/quest_log.rs`) so Expand/CollapseQuestHeader don't exist yet
|
||
-- — guarded rather than assumed absent forever.
|
||
if isCollapsed and type(ExpandQuestHeader) == "function" then
|
||
ExpandQuestHeader(index)
|
||
elseif type(CollapseQuestHeader) == "function" then
|
||
CollapseQuestHeader(index)
|
||
end
|
||
return
|
||
end
|
||
-- pin §5, QuestLogTitleButton_OnClick (QuestLogFrame.lua:469-501): shift-click either
|
||
-- posts the quest's NAME into an open chat edit box (l.478-480) or, with chat closed,
|
||
-- toggles the watch (l.481-500 — the ref's own `else`). Chat wins; the watch is the
|
||
-- fallback, not the other way round (decision 1059).
|
||
--
|
||
-- The insert (l.480) is `gsub(this:GetText(), " *(.*)", "%1")` — the row LABEL with its
|
||
-- leading indent trimmed, i.e. the bare quest name; note it is plain text, NOT a
|
||
-- hyperlink (1.12 has no |Hquest: link). We read `GetQuestLogTitle(index)` instead of
|
||
-- the label, because our label is not the ref's: this window appends the Complete/Failed
|
||
-- tag onto the ONE title string (the v1 simplification in BenillaQuestLogList_Update,
|
||
-- where the ref keeps a separate right-justified $parentTag FontString), so the ref's
|
||
-- gsub over our label would post "Quest 1 (Complete)". The API title is exactly the
|
||
-- string the ref's own trim yields — same result, different expression. `ChatFrameEditBox
|
||
-- and` guards a window test that hasn't loaded ChatFrame.xml (BenillaPaperDollSlot_OnClick's
|
||
-- precedent).
|
||
--
|
||
-- Guard order inside the watch arm matches the ref exactly: already watched → unwatch,
|
||
-- unconditionally; else zero objectives (QUEST_WATCH_NO_OBJECTIVES) or the watch list
|
||
-- full (QUEST_WATCH_TOO_MANY) put the ref's red line on the errors frame
|
||
-- (UIErrorsFrame:AddMessage, the ref's own call — lua:490/495), else watch it. The ref calls QuestWatch_Update() itself
|
||
-- right after each Add/RemoveQuestWatch (same two call sites) — it does NOT lean on
|
||
-- the QUEST_LOG_UPDATE/QUEST_WATCH_UPDATE events alone for this, since neither engine
|
||
-- fires an event off a plain Add/RemoveQuestWatch call; we mirror that exactly.
|
||
if mouseButton == "LeftButton" and IsShiftKeyDown() then
|
||
local title = GetQuestLogTitle(index)
|
||
if ChatFrameEditBox and ChatFrameEditBox:IsVisible() then
|
||
-- The visibility test stays HERE, not in the helper: it is the ref's own fork
|
||
-- (l.474/478) — with chat open this click never watches, and the helper's
|
||
-- return would conflate "chat closed" with "nothing to post".
|
||
BenillaChatEdit_InsertLink(title)
|
||
elseif IsQuestWatched(index) then
|
||
-- Clearing the timer too: a lingering timed entry would later expire and
|
||
-- silently unwatch a re-added MANUAL watch.
|
||
if title then BENILLA_QUEST_WATCH_TIMERS[title] = nil end
|
||
RemoveQuestWatch(index)
|
||
QuestWatch_Update()
|
||
elseif GetNumQuestLeaderBoards(index) == 0 then
|
||
-- ref QUEST_WATCH_NO_OBJECTIVES, red, straight onto the errors frame.
|
||
UIErrorsFrame:AddMessage("This quest has no objectives to track", 1.0, 0.1, 0.1)
|
||
elseif GetNumQuestWatches() >= BENILLA_QUESTLOG_MAX_WATCHES then
|
||
-- ref QUEST_WATCH_TOO_MANY, red.
|
||
UIErrorsFrame:AddMessage("You may only watch " .. BENILLA_QUESTLOG_MAX_WATCHES .. " quests at a time", 1.0, 0.1, 0.1)
|
||
else
|
||
-- A manual watch is PERMANENT (ref: QUEST_WATCH_NO_EXPIRE) — drop any timed
|
||
-- entry the auto-watch may have armed for it.
|
||
if title then BENILLA_QUEST_WATCH_TIMERS[title] = nil end
|
||
AddQuestWatch(index)
|
||
QuestWatch_Update()
|
||
end
|
||
end
|
||
-- pin §5: every click (shifted/right-clicked or not) ends in select + a full repaint.
|
||
SelectQuestLogEntry(index)
|
||
BenillaQuestLogFrame_Update()
|
||
end
|
||
|
||
-- The fold-all tab (ref QuestLogCollapseAllButton_OnClick, QuestLogFrame.lua:554-563):
|
||
-- index 0 = every header; the tab's own +/- icon tracks the all-state.
|
||
function QuestLogCollapseAllButton_OnClick()
|
||
local b = getglobal("QuestLogCollapseAllButton")
|
||
if b.allCollapsed then
|
||
b.allCollapsed = nil
|
||
b:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-Up")
|
||
ExpandQuestHeader(0)
|
||
else
|
||
b.allCollapsed = 1
|
||
b:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-Up")
|
||
CollapseQuestHeader(0)
|
||
end
|
||
end
|
||
|
||
-- pin §2's QuestLog_SetFirstValidSelection/QuestLog_GetFirstSelectableQuest
|
||
-- (QuestLogFrame.lua:293-296, :565-582): if nothing is selected, pick the first non-header row.
|
||
function QuestLog_SetFirstValidSelection()
|
||
if GetQuestLogSelection() ~= 0 then return end
|
||
local numEntries = GetNumQuestLogEntries()
|
||
for i = 1, numEntries do
|
||
local _, _, _, isHeader = GetQuestLogTitle(i)
|
||
if not isHeader then
|
||
SelectQuestLogEntry(i)
|
||
return
|
||
end
|
||
end
|
||
end
|
||
|
||
function BenillaQuestLogList_Update()
|
||
local numEntries, numQuests = GetNumQuestLogEntries()
|
||
-- Ref QuestLogFrame.lua:123-124 with QUEST_LOG_COUNT_TEMPLATE inlined verbatim
|
||
-- (GlobalStrings.lua:3236): gold "Quests:" label, white count via the |cff markup; the
|
||
-- pill's middle piece then shrinks to the text (ref sizes it every update). The >10
|
||
-- guard skips the first-ever paint, where the host hasn't measured the string yet
|
||
-- (GetWidth 0 would collapse the pill; the next update — and every one after — sizes it).
|
||
getglobal("QuestLogCount"):SetText(string.format("Quests: |cffffffff%d/%d|r", numQuests, MAX_QUESTLOG_QUESTS))
|
||
local countWidth = getglobal("QuestLogCount"):GetWidth()
|
||
if countWidth and countWidth > 10 then
|
||
getglobal("QuestLogCountMiddle"):SetWidth(countWidth)
|
||
end
|
||
|
||
-- v1 empty state (pin §2 drives a whole separate EmptyQuestLogFrame; simplified here to
|
||
-- one message string + hidden rows, see this file's header comment). NOTE: throughout
|
||
-- this file "hiding" text is a blank SetText(""), never a Show/Hide call — exactly how
|
||
-- `QuestFrame.xml`'s BenillaQuest_HideAll blanks its texts instead of hiding them. That
|
||
-- convention predates region Show/Hide (`region.rs` has the real pair now, and the
|
||
-- loader honours hidden= on regions); an empty string draws nothing, so it is equivalent
|
||
-- either way and the idiom stays for consistency with the sibling windows.
|
||
local abandonButton = getglobal("QuestLogAbandonButton")
|
||
if numEntries == 0 then
|
||
getglobal("QuestLogEmptyText"):SetText("Your quest log is empty.")
|
||
abandonButton:Disable()
|
||
else
|
||
getglobal("QuestLogEmptyText"):SetText("")
|
||
abandonButton:Enable()
|
||
end
|
||
|
||
-- Clamp the faux-scroll offset (pin §2's FauxScrollFrame_Update clamp).
|
||
local maxOffset = numEntries - QUESTS_DISPLAYED
|
||
if maxOffset < 0 then maxOffset = 0 end
|
||
if questLogOffset > maxOffset then questLogOffset = maxOffset end
|
||
if questLogOffset < 0 then questLogOffset = 0 end
|
||
|
||
local selection = GetQuestLogSelection()
|
||
|
||
for i = 1, QUESTS_DISPLAYED do
|
||
local button = getglobal("QuestLogTitle" .. i)
|
||
local index = i + questLogOffset
|
||
if index <= numEntries then
|
||
local title, level, tag, isHeader, isCollapsed, isComplete = GetQuestLogTitle(index)
|
||
local text = title or ""
|
||
if isHeader then
|
||
-- Ref QuestLogFrame.lua:146-159: a header shows the plus/minus fold icon
|
||
-- (its NormalTexture — the row template declares the 16x16 LEFT+3 slot),
|
||
-- the plus-glow hover art, no indent, no tag, no watch check.
|
||
if isCollapsed then
|
||
button:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-Up")
|
||
else
|
||
button:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-Up")
|
||
end
|
||
button.foldHighlight:SetTexture("Interface\\Buttons\\UI-PlusButton-Hilight")
|
||
else
|
||
-- Ref l.161-166: quest rows clear both state slots and indent two spaces.
|
||
text = " " .. text
|
||
button:SetNormalTexture("")
|
||
button.foldHighlight:SetTexture("")
|
||
if isComplete == 1 then
|
||
text = text .. " (Complete)"
|
||
elseif isComplete == -1 then
|
||
text = text .. " (Failed)"
|
||
end
|
||
end
|
||
-- pin §2: the ref recolors via a SEPARATE right-side tag FontString; one combined
|
||
-- string (title + tag suffix, above) is our v1 simplification — see this widget's
|
||
-- own template comment.
|
||
button.text:SetText(text)
|
||
button.questIndex = index
|
||
if isHeader then
|
||
local c = QuestDifficultyColor["header"]
|
||
button.text:SetTextColor(c.r, c.g, c.b)
|
||
else
|
||
local c = GetDifficultyColor(level)
|
||
button.text:SetTextColor(c.r, c.g, c.b)
|
||
end
|
||
-- pin §2's $parentCheck: the per-row watch checkbox. SetTexture(path)/
|
||
-- SetTexture(nil) as the show/hide toggle — the icon-slot blanking pattern
|
||
-- (`BenillaBagSlot_Update` etc.). (Regions DO have Show/Hide these days —
|
||
-- region.rs; this site just predates it and the pattern is equivalent.)
|
||
if not isHeader and IsQuestWatched(index) then
|
||
button.check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
|
||
else
|
||
button.check:SetTexture(nil)
|
||
end
|
||
button:Show()
|
||
else
|
||
button.questIndex = nil
|
||
button:Hide()
|
||
end
|
||
end
|
||
|
||
-- The selection highlight follows the row only while it is inside the visible scroll
|
||
-- window (pin §5, QuestLog_SetSelection QuestLogFrame.lua:330-340) — a selection scrolled
|
||
-- off-screen still holds state, but the highlight itself doesn't show until the list
|
||
-- scrolls back to it. Ref l.337-339 verbatim: the glow rides at (5,0) on the row and is
|
||
-- vertex-colored to the row's own difficulty color (that green bar in the ref shot IS
|
||
-- this vertex color on the white ADD gradient).
|
||
local hl = getglobal("QuestLogSelectHighlight")
|
||
if selection > questLogOffset and selection <= questLogOffset + QUESTS_DISPLAYED
|
||
and selection <= numEntries then
|
||
local selButton = getglobal("QuestLogTitle" .. (selection - questLogOffset))
|
||
local _, selLevel, _, selIsHeader = GetQuestLogTitle(selection)
|
||
if selIsHeader then
|
||
local c = QuestDifficultyColor["header"]
|
||
getglobal("QuestLogSkillHighlight"):SetVertexColor(c.r, c.g, c.b)
|
||
else
|
||
local c = GetDifficultyColor(selLevel)
|
||
getglobal("QuestLogSkillHighlight"):SetVertexColor(c.r, c.g, c.b)
|
||
end
|
||
hl:SetPoint("TOPLEFT", selButton, "TOPLEFT", 5, 0)
|
||
hl:Show()
|
||
else
|
||
hl:Hide()
|
||
end
|
||
end
|
||
|
||
function BenillaQuestLogFrame_OnMouseWheel(delta)
|
||
-- WoW wheel convention: +1 per notch up, -1 down (ChatFrame.xml's own handler quotes the
|
||
-- same convention). Up = earlier entries (offset toward 0); down = later entries.
|
||
if delta > 0 then
|
||
questLogOffset = questLogOffset - 1
|
||
else
|
||
questLogOffset = questLogOffset + 1
|
||
end
|
||
BenillaQuestLogList_Update()
|
||
end
|
||
|
||
-- ── The detail page ──────────────────────────────────────────────────────────────────────
|
||
-- The detail pane's real ScrollFrame (decision 0112's mechanism, landed this session — this
|
||
-- window used to be a fixed layout that simply clipped past the window's bottom edge, this
|
||
-- file's header comment). `QuestLogDetailScroll`'s ScrollChild is
|
||
-- `QuestLogDetailChild`: every FontString/Button below that used to live flat on
|
||
-- `QuestLogFrame` now lives on that child instead (the 0088 §2 flat-frame constraint
|
||
-- this file's header comment quoted DIED with the 0112 resolver fixpoint — child frames
|
||
-- render their own `<Layers>` regions again), so its subtree clips at the ScrollFrame's own
|
||
-- rect and scrolls independent of the rest of the window.
|
||
--
|
||
-- The child has no *reported* height from the engine (a Frame's height is its own SetSize —
|
||
-- the resolver never grows a frame to fit content that overflows it, `script/mod.rs`'s
|
||
-- region-resolution comment), so `BenillaQuestLogDetail_ResizeChild` below sums one by hand
|
||
-- from the same fixed offsets/row heights this chain's own comments already cite, plus each
|
||
-- auto-height FontString's OWN `GetHeight()` (region.rs: measured from the host font atlas
|
||
-- once text is set — confirmed live, not a guess). That measurement is a FRAME LATE relative
|
||
-- to *this* call (Lua runs before `resolve()`/the measure round-trip each tick, `ui_script/
|
||
-- mod.rs`'s drive loop) — a BRAND-NEW selection's text sizes off zero (never yet measured)
|
||
-- on this very populate, understating the true height. Nothing guarantees a SECOND populate
|
||
-- ever runs for the same stable selection (`QUEST_LOG_UPDATE` only fires on an actual data
|
||
-- change — `ui_quest_log.rs`'s diffed feed — not every tick), so relying on "the next
|
||
-- update self-heals it" silently under-sizes the child forever once the log goes quiet
|
||
-- (caught on the ui-questlog capture: the reward text visibly clipped with the scrollbar
|
||
-- never appearing). The honest fix is `BenillaQuestLogDetail_OnUpdate` below: it re-sums
|
||
-- every frame the window is open (cheap — its own comment) until the measurement lands and
|
||
-- the sum stops changing, which converges within a couple of frames of any repaint. A
|
||
-- same-frame exact answer isn't available without an engine-side "resize to fit" primitive;
|
||
-- this converges honestly instead of asserting a fiction.
|
||
|
||
-- A FontString's content height for the resize sum: blank text is a TRUE 0 regardless of
|
||
-- what GetHeight() answers. Needed because `measured` (region.rs) is a one-way cache keyed
|
||
-- off the LAST non-blank text — SetText("") never clears it (this engine has no live "0,0"
|
||
-- the instant a string blanks, unlike the real client's font engine), so a freshly-blanked
|
||
-- FontString would otherwise still report its previous text's height. A NON-blank string
|
||
-- still reports last tick's measurement (this function's own header comment on the lag).
|
||
function BenillaQuestLogDetail_TextHeight(fontString)
|
||
local text = fontString:GetText()
|
||
if not text or text == "" then return 0 end
|
||
return fontString:GetHeight()
|
||
end
|
||
|
||
-- Sums the child's needed height from this ONE chain's own fixed offsets (cited per term,
|
||
-- each already documented at its own FontString/SetPoint above) + every auto-height
|
||
-- FontString's measured `GetHeight()` + `rewardSectionHeight` (BenillaQuestLogRewards_Update's
|
||
-- own return — its header-through-money layout has its own conditional branches, cheaper to
|
||
-- total right where those branches already live than to re-derive them here). Then
|
||
-- `UpdateScrollChildRect()` so the scrollbar (BenillaQuestLogDetailScroll_SyncBar) hears the
|
||
-- new range.
|
||
function BenillaQuestLogDetail_ResizeChild(objAnchorIndex, rewardSectionHeight)
|
||
detailObjAnchorIndex = objAnchorIndex
|
||
detailRewardHeight = rewardSectionHeight
|
||
local title = getglobal("QuestLogQuestTitle")
|
||
local objectivesText = getglobal("QuestLogObjectivesText")
|
||
local description = getglobal("QuestLogDescription")
|
||
|
||
local objSpan
|
||
if objAnchorIndex > 0 then
|
||
objSpan = BENILLA_QUESTLOG_DETAIL_OBJ_GAP
|
||
+ objAnchorIndex * BENILLA_QUESTLOG_DETAIL_OBJ_ROW
|
||
+ (objAnchorIndex - 1) * BENILLA_QUESTLOG_DETAIL_OBJ_STEP
|
||
+ BENILLA_QUESTLOG_DETAIL_OBJ_GAP
|
||
else
|
||
objSpan = BENILLA_QUESTLOG_DETAIL_OBJ_GAP
|
||
end
|
||
-- The countdown row, when the selection has one (decision 1150): one more -10 hop and
|
||
-- one more fixed 12px row ahead of the objectives, whether or not any objective follows
|
||
-- it — both branches above start at the same ObjectivesText→next -10, so the delta is
|
||
-- the same either way. Read off the ref's own hasTimer flag rather than a second
|
||
-- parameter, so the OnUpdate re-check below re-sums it without threading state.
|
||
if BenillaQuestLogHasTimer then
|
||
objSpan = objSpan + BENILLA_QUESTLOG_DETAIL_OBJ_GAP + BENILLA_QUESTLOG_DETAIL_OBJ_ROW
|
||
end
|
||
|
||
local height = BENILLA_QUESTLOG_DETAIL_TOP
|
||
+ BenillaQuestLogDetail_TextHeight(title)
|
||
+ 5 -- QuestTitle -> ObjectivesText
|
||
+ BenillaQuestLogDetail_TextHeight(objectivesText)
|
||
+ objSpan
|
||
+ 18 -- DescriptionTitle: fixed span regardless of text (its own comment)
|
||
+ 5 -- DescriptionTitle -> Description
|
||
+ BenillaQuestLogDetail_TextHeight(description)
|
||
+ 15 -- Description -> RewardTitleText
|
||
+ rewardSectionHeight
|
||
+ BENILLA_QUESTLOG_DETAIL_BOTTOM_PAD
|
||
|
||
if height ~= detailLastAppliedHeight then
|
||
detailLastAppliedHeight = height
|
||
getglobal("QuestLogDetailChild"):SetHeight(height)
|
||
getglobal("QuestLogDetailScroll"):UpdateScrollChildRect()
|
||
end
|
||
end
|
||
|
||
-- The re-check `QuestLogDetailScroll`'s own `<OnUpdate>` calls every frame the log
|
||
-- window is open (`UiScript::tick`'s OnUpdate gate gates it on effective-visibility, so this
|
||
-- costs nothing while the window is closed): re-sums the SAME inputs the last full populate
|
||
-- computed (`BenillaQuestLogDetail_ResizeChild`'s own header comment on why a single populate
|
||
-- isn't enough — the auto-height FontStrings' `GetHeight()` only reflects a NEW text's real
|
||
-- measurement one tick after this function first set it). `ResizeChild`'s own
|
||
-- detailLastAppliedHeight guard makes every one of these calls a no-op once the resize has
|
||
-- converged (no host measurement changed since the last check).
|
||
function BenillaQuestLogDetail_OnUpdate()
|
||
BenillaQuestLogDetail_ResizeChild(detailObjAnchorIndex, detailRewardHeight)
|
||
end
|
||
|
||
-- ref QuestLog_OnUpdate (QuestLogFrame.lua:96-105), re-expressed here including its
|
||
-- UPDATE_DELAY throttle: the countdown is repainted ten times a second, not every frame —
|
||
-- SecondsToTime's output only changes once a second, so anything faster is a re-measure of
|
||
-- an identical string. The flag/accumulator pair is the ref's own (its two fields on
|
||
-- QuestLogFrame; ours are file globals because our detail state already lives that way).
|
||
function QuestLog_OnUpdate(elapsed)
|
||
if not BenillaQuestLogHasTimer then
|
||
return
|
||
end
|
||
BenillaQuestLogTimePassed = (BenillaQuestLogTimePassed or 0) + (elapsed or 0)
|
||
if BenillaQuestLogTimePassed > BENILLA_QUESTLOG_UPDATE_DELAY then
|
||
local left = GetQuestLogTimeLeft()
|
||
getglobal("QuestLogTimerText"):SetText(
|
||
BENILLA_TIME_REMAINING .. " " .. SecondsToTime(left or 0))
|
||
BenillaQuestLogTimePassed = 0
|
||
end
|
||
end
|
||
|
||
-- Steps the detail ScrollFrame by `delta` px — the wheel handler and both scrollbar arrow
|
||
-- buttons share this one path; SetVerticalScroll's own clamp (benilla-ui's `scrollframe.rs`)
|
||
-- does the range-bounding, this function just supplies the signed step.
|
||
function BenillaQuestLogDetailScroll_Step(delta)
|
||
local sf = getglobal("QuestLogDetailScroll")
|
||
sf:SetVerticalScroll(sf:GetVerticalScroll() + delta)
|
||
end
|
||
|
||
-- Repaints the minimal scrollbar (this window's own scrollbar comment: VISUAL only, no
|
||
-- drag) from the CURRENT offset/range — wired to both OnVerticalScroll (the value changed)
|
||
-- and OnScrollRangeChanged (the content resized), the ref UIPanelScrollFrameTemplate's own
|
||
-- pair (UIPanelTemplates.xml). Hides the whole bar when nothing overflows (range 0); disables
|
||
-- either arrow at its own end, mirroring the ref's identical two Enable/Disable calls off a
|
||
-- real Slider's min/max (there's no Slider here — this window's own comment on why).
|
||
function BenillaQuestLogDetailScroll_SyncBar()
|
||
local sf = getglobal("QuestLogDetailScroll")
|
||
local value = sf:GetVerticalScroll()
|
||
local range = sf:GetVerticalScrollRange()
|
||
local bar = getglobal("QuestLogDetailScrollBar")
|
||
if range <= 0 then
|
||
bar:Hide()
|
||
return
|
||
end
|
||
bar:Show()
|
||
if value > 0 then
|
||
getglobal("QuestLogDetailScrollUp"):Enable()
|
||
else
|
||
getglobal("QuestLogDetailScrollUp"):Disable()
|
||
end
|
||
if value < range then
|
||
getglobal("QuestLogDetailScrollDown"):Enable()
|
||
else
|
||
getglobal("QuestLogDetailScrollDown"):Disable()
|
||
end
|
||
local travel = BENILLA_QUESTLOG_SCROLL_TRACK_H - BENILLA_QUESTLOG_SCROLL_THUMB_H
|
||
local frac = value / range
|
||
getglobal("QuestLogDetailScrollThumb"):SetPoint(
|
||
"TOPLEFT", getglobal("QuestLogDetailScrollTrack"), "TOPLEFT", 0, -(frac * travel))
|
||
end
|
||
|
||
function BenillaQuestLogDetail_Clear()
|
||
getglobal("QuestLogQuestTitle"):SetText("")
|
||
getglobal("QuestLogObjectivesText"):SetText("")
|
||
-- The ref clears hasTimer on the empty-log path too (QuestLog_Update, :108) — without
|
||
-- it the per-tick repaint keeps writing a countdown into a pane with no selection, and
|
||
-- the child height keeps paying for a row that isn't there.
|
||
BenillaQuestLogHasTimer = nil
|
||
getglobal("QuestLogTimerText"):SetText("")
|
||
getglobal("QuestLogDescriptionTitle"):SetText("")
|
||
getglobal("QuestLogDescription"):SetText("")
|
||
for i = 1, MAX_OBJECTIVES do
|
||
getglobal("QuestLogObjective" .. i):SetText("")
|
||
end
|
||
getglobal("QuestLogRewardTitleText"):SetText("")
|
||
getglobal("QuestLogItemChooseText"):SetText("")
|
||
getglobal("QuestLogItemReceiveText"):SetText("")
|
||
for i = 1, BENILLA_QUESTLOG_MAX_ITEMS do
|
||
getglobal("QuestLogChoice" .. i):Hide()
|
||
getglobal("QuestLogReward" .. i):Hide()
|
||
end
|
||
BenillaMoney_Clear("QuestLogMoney")
|
||
-- Nothing selected: the header-only span (BenillaQuestLogRewards_Update's own
|
||
-- haveAnyReward==false case, 18px) is the right resize input here too.
|
||
BenillaQuestLogDetail_ResizeChild(0, 18)
|
||
end
|
||
|
||
-- Fill + show one reward/choice row. `getter` is GetQuestLogChoiceInfo or
|
||
-- GetQuestLogRewardInfo (pin §6): both answer the shared 5-tuple `name, texture, count,
|
||
-- quality, usable` — the same shape QuestFrame.xml's GetQuestItemInfo(kind, index) answers
|
||
-- for the questgiver panels, just under quest-log-specific getter names instead of one
|
||
-- kind-dispatched function. `kind` ("choice"/"reward") rides alongside because the LINK
|
||
-- getter IS kind-dispatched — GetQuestLogItemLink(this.type, this:GetID()), ref
|
||
-- QuestLogFrame.lua:545/549 — and because it is the ref's own `questItem.type`
|
||
-- (QuestFrame.lua:369/476, the shared layout routine both windows run).
|
||
function BenillaQuestLogItem_Set(button, getter, index, kind)
|
||
local name, texture, count, quality, usable, itemId = getter(index)
|
||
button.index = index
|
||
button.kind = kind
|
||
button.itemId = itemId
|
||
-- ref QuestFrame.lua:388/490 ("-- For the tooltip"), the same stamp the giver window's
|
||
-- BenillaQuestItem_Set makes: only the reward-SPELL row ever reads "spell" (l.445), and
|
||
-- v1 builds none (GetQuestLogRewardSpell is nil — this file's header). The click arms
|
||
-- below guard on it exactly as the ref does, so the guard is live when that row lands.
|
||
button.rewardType = "item"
|
||
button.quality = quality
|
||
button.icon:SetTexture(texture or BENILLA_FALLBACK_ICON)
|
||
button.name:SetText(name or "...")
|
||
if (count or 1) > 1 then button.count:SetText(count) else button.count:SetText("") end
|
||
local r, g, b = 1, 1, 1
|
||
if quality and BenillaTooltip_QualityColor then r, g, b = BenillaTooltip_QualityColor(quality) end
|
||
button.name:SetTextColor(r, g, b)
|
||
button:Show()
|
||
end
|
||
|
||
-- ref QuestLogRewardItem_OnClick (QuestLogFrame.lua:542-552), the OnClick
|
||
-- QuestLogRewardItemTemplate carries (ref QuestLogFrame.xml:118-120): CTRL previews the
|
||
-- reward in the dressing room (decision 1060), SHIFT posts its link into an open chat edit
|
||
-- box (decision 1059). There is no third arm here — a quest-log reward row is never
|
||
-- selectable, so a plain click is inert, which is why these rows carried no OnClick before
|
||
-- this arc.
|
||
--
|
||
-- Guard-for-guard with the ref: ctrl is gated on `this.rewardType ~= "spell"` (l.544), and
|
||
-- so is shift — but on the ELSEIF line itself (l.547), where the giver window's twin puts it
|
||
-- inside (QuestFrame.lua:121). Same outcome, and kept where the ref puts it. Ours
|
||
-- adds `ChatFrameEditBox and` (ChatFrame.xml is a separate file a window test need not
|
||
-- load — BenillaPaperDollSlot_OnClick's precedent) and a nil-link guard: `link` is nil until
|
||
-- the ask-once item template lands, a state the reference's synchronous item cache never
|
||
-- has, and EditBox:Insert takes a string (DressUpItemLink carries the same guard itself —
|
||
-- ref DressUpFrame.lua:11-13).
|
||
function QuestLogRewardItem_OnClick()
|
||
local button = this
|
||
if IsControlKeyDown() then
|
||
if button.rewardType ~= "spell" then
|
||
DressUpItemLink(GetQuestLogItemLink(button.kind, button.index))
|
||
end
|
||
elseif IsShiftKeyDown() and button.rewardType ~= "spell" then
|
||
-- The visible/non-nil pair is the shared helper's (UIParent.xml).
|
||
BenillaChatEdit_InsertLink(GetQuestLogItemLink(button.kind, button.index))
|
||
end
|
||
end
|
||
|
||
-- The reward-panel layout, ported from the ref's shared `QuestFrameItems_Update`
|
||
-- (QuestFrame.lua:311-522, the same routine the live QuestFrame reward panel uses) — this
|
||
-- window's v1 subset of it: no spell-reward row (GetQuestLogRewardSpell has no v1 caller,
|
||
-- QuestLogFrame.xml's header comment), capped at BENILLA_QUESTLOG_MAX_ITEMS (6, half the ref's
|
||
-- MAX_NUM_ITEMS=10, same halving QuestFrame.xml's own BENILLA_QUEST_MAX_ITEMS does). Every
|
||
-- SetPoint below mirrors the ref's own line-for-line (cited per block) — this is the mechanism
|
||
-- the ref itself uses; a static XML band was never right, and now that a runtime SetPoint
|
||
-- re-propagates to dependents (commit d0c23c5) we don't need to fake it with fixed offsets.
|
||
--
|
||
-- RETURNS the section's own total height (RewardTitleText's top to the lowest visible row's
|
||
-- bottom) for `BenillaQuestLogDetail_ResizeChild` to add onto the rest of the chain — this is
|
||
-- the one place that already knows every conditional branch (choices-only / fixed-only /
|
||
-- money-only / any combination), cheaper to total right here than to re-derive elsewhere.
|
||
function BenillaQuestLogRewards_Update()
|
||
local numChoices = GetNumQuestLogChoices()
|
||
local numRewards = GetNumQuestLogRewards()
|
||
local money = GetQuestLogRewardMoney()
|
||
|
||
-- pin §3 / QuestFrame.lua:343-349: QuestLogRewardTitleText shown only if
|
||
-- numRewards+numChoices+money > 0. Text is toggled rather than Show/Hide — see
|
||
-- BenillaQuestLogList_Update's comment on this file's blank-text convention.
|
||
local header = getglobal("QuestLogRewardTitleText")
|
||
local haveAnyReward = numChoices > 0 or numRewards > 0 or (money and money > 0)
|
||
if haveAnyReward then
|
||
header:SetText("Rewards")
|
||
else
|
||
header:SetText("")
|
||
end
|
||
|
||
-- ── Choosable rewards (QuestFrame.lua:367-413): 2-per-row under ItemChooseText. Row 1
|
||
-- anchors below the header text (-3,-5); each following ODD index anchors BOTTOMLEFT of
|
||
-- the row two back (0,-2) — starts a new row; each EVEN index anchors TOPRIGHT of the
|
||
-- previous (1,0) — sits beside it. ──
|
||
local chooseText = getglobal("QuestLogItemChooseText")
|
||
local lastChoice = math.min(numChoices, BENILLA_QUESTLOG_MAX_ITEMS)
|
||
if numChoices > 0 then
|
||
chooseText:SetText("You may choose one of these rewards:")
|
||
else
|
||
chooseText:SetText("")
|
||
end
|
||
for i = 1, BENILLA_QUESTLOG_MAX_ITEMS do
|
||
local choice = getglobal("QuestLogChoice" .. i)
|
||
if i <= lastChoice then
|
||
BenillaQuestLogItem_Set(choice, GetQuestLogChoiceInfo, i, "choice")
|
||
if i == 1 then
|
||
choice:SetPoint("TOPLEFT", chooseText, "BOTTOMLEFT", -3, -5)
|
||
elseif i % 2 == 1 then
|
||
choice:SetPoint("TOPLEFT", getglobal("QuestLogChoice" .. (i - 2)), "BOTTOMLEFT", 0, -2)
|
||
else
|
||
choice:SetPoint("TOPLEFT", getglobal("QuestLogChoice" .. (i - 1)), "TOPRIGHT", 1, 0)
|
||
end
|
||
else
|
||
choice:Hide()
|
||
end
|
||
end
|
||
|
||
-- ── "You will receive:" / "You will also receive:" (QuestFrame.lua:454-473): shown
|
||
-- whenever there's a fixed reward OR money, even with zero fixed-reward rows (money-only).
|
||
-- Anchored below the LAST CHOICE ROW'S LEFT COLUMN (the shorter of the two columns) when
|
||
-- choices exist, else below the Rewards header directly. ──
|
||
local receiveText = getglobal("QuestLogItemReceiveText")
|
||
local haveFixed = numRewards > 0 or (money and money > 0)
|
||
if haveFixed then
|
||
if numChoices > 0 then
|
||
receiveText:SetText("You will also receive:")
|
||
local anchorIndex = lastChoice
|
||
if anchorIndex % 2 == 0 then anchorIndex = anchorIndex - 1 end
|
||
receiveText:SetPoint("TOPLEFT", getglobal("QuestLogChoice" .. anchorIndex), "BOTTOMLEFT", 3, -5)
|
||
else
|
||
receiveText:SetText("You will receive:")
|
||
receiveText:SetPoint("TOPLEFT", header, "BOTTOMLEFT", 3, -5)
|
||
end
|
||
else
|
||
receiveText:SetText("")
|
||
end
|
||
|
||
-- ── Fixed rewards (QuestFrame.lua:474-513): row 1 anchors below ItemReceiveText (-3,-5);
|
||
-- the same odd/even 2-per-row pattern as the choice rows above, chained off each other. ──
|
||
local lastReward = math.min(numRewards, BENILLA_QUESTLOG_MAX_ITEMS)
|
||
for i = 1, BENILLA_QUESTLOG_MAX_ITEMS do
|
||
local reward = getglobal("QuestLogReward" .. i)
|
||
if i <= lastReward then
|
||
BenillaQuestLogItem_Set(reward, GetQuestLogRewardInfo, i, "reward")
|
||
if i == 1 then
|
||
reward:SetPoint("TOPLEFT", receiveText, "BOTTOMLEFT", -3, -5)
|
||
elseif i % 2 == 1 then
|
||
reward:SetPoint("TOPLEFT", getglobal("QuestLogReward" .. (i - 2)), "BOTTOMLEFT", 0, -2)
|
||
else
|
||
reward:SetPoint("TOPLEFT", getglobal("QuestLogReward" .. (i - 1)), "TOPRIGHT", 1, 0)
|
||
end
|
||
else
|
||
reward:Hide()
|
||
end
|
||
end
|
||
|
||
-- Money: a STATIC XML anchor (LEFT of ItemReceiveText's RIGHT, +15,0 — ref
|
||
-- QuestLogFrame.xml:896-903) tracks receiveText's runtime SetPoint above via the resolver's
|
||
-- fixpoint re-propagation; only the coin fill/clear is Lua's job here.
|
||
if money and money > 0 then
|
||
BenillaMoney_Set("QuestLogMoney", money, true)
|
||
else
|
||
BenillaMoney_Clear("QuestLogMoney")
|
||
end
|
||
|
||
-- The section's total height, mirroring the branches above term-for-term (a money-only
|
||
-- coin row adds no height of its own — it rides receiveText's own row, LEFT of it, not
|
||
-- a new one — this window's own coin-anchor comment just above).
|
||
local height = 18 -- RewardTitleText: fixed span regardless of text (its own comment)
|
||
if haveAnyReward then
|
||
if numChoices > 0 then
|
||
local numChoiceRows = math.ceil(lastChoice / 2)
|
||
height = height
|
||
+ 5 -- header -> chooseText
|
||
+ BenillaQuestLogDetail_TextHeight(chooseText)
|
||
+ 5 -- chooseText -> choice row 1
|
||
+ numChoiceRows * 41 + (numChoiceRows - 1) * 2
|
||
end
|
||
if haveFixed then
|
||
height = height + 5 -- (last choice row, or the header) -> receiveText
|
||
+ BenillaQuestLogDetail_TextHeight(receiveText)
|
||
if numRewards > 0 then
|
||
local numRewardRows = math.ceil(lastReward / 2)
|
||
height = height + 5 -- receiveText -> reward row 1
|
||
+ numRewardRows * 41 + (numRewardRows - 1) * 2
|
||
end
|
||
end
|
||
end
|
||
return height
|
||
end
|
||
|
||
-- pin §3/§5's doNotScroll asymmetry (QuestLogFrame.lua:348/455-457, QUESTLOG-PIN.md's own
|
||
-- section on it): a MANUAL reselect (`BenillaQuestLogTitle_OnClick`, no arg here) always
|
||
-- snaps the detail pane's scroll back to the top; the QUEST_LOG_UPDATE data-refresh path
|
||
-- (`BenillaQuestLogFrame_OnEvent` below) passes `doNotScroll=true` so a quest updating while
|
||
-- already being read doesn't yank the player's scroll position out from under them.
|
||
function BenillaQuestLogDetail_Update(doNotScroll)
|
||
local selection = GetQuestLogSelection()
|
||
if selection == 0 or selection > GetNumQuestLogEntries() then
|
||
BenillaQuestLogDetail_Clear()
|
||
if not doNotScroll then
|
||
getglobal("QuestLogDetailScroll"):SetVerticalScroll(0)
|
||
end
|
||
return
|
||
end
|
||
|
||
-- pin §3, QuestLog_UpdateQuestDetails (QuestLogFrame.lua:349-356): title from
|
||
-- GetQuestLogTitle's FIRST return only; " - (Failed)" appended when failed.
|
||
local title = GetQuestLogTitle(selection)
|
||
if IsCurrentQuestFailed() then
|
||
title = (title or "") .. " - (Failed)"
|
||
end
|
||
getglobal("QuestLogQuestTitle"):SetText(title or "")
|
||
|
||
-- pin §3: description is GetQuestLogQuestText()'s FIRST return, the objectives FLAVOR
|
||
-- paragraph (not the leaderboard lines) is the second.
|
||
local description, objectivesText = GetQuestLogQuestText()
|
||
getglobal("QuestLogObjectivesText"):SetText(objectivesText or "")
|
||
|
||
-- pin §3, QuestLog_UpdateQuestDetails (QuestLogFrame.lua:364-374) followed, minus the
|
||
-- Show/Hide our region model has no verb for: a timed quest gets the "Time Remaining:"
|
||
-- row and pushes Objective1 below it; an untimed one blanks the row (our stand-in for
|
||
-- the ref's :Hide()) and anchors Objective1 straight onto ObjectivesText, so the row
|
||
-- costs an untimed quest no space at all. `hasTimer` is the ref's own flag and drives
|
||
-- both the per-tick repaint (QuestLog_OnUpdate) and the child-height sum.
|
||
local questTimer = GetQuestLogTimeLeft()
|
||
local timerText = getglobal("QuestLogTimerText")
|
||
local objective1 = getglobal("QuestLogObjective1")
|
||
if questTimer then
|
||
BenillaQuestLogHasTimer = 1
|
||
BenillaQuestLogTimePassed = 0
|
||
timerText:SetText(BENILLA_TIME_REMAINING .. " " .. SecondsToTime(questTimer))
|
||
objective1:SetPoint("TOPLEFT", timerText, "BOTTOMLEFT", 0, -10)
|
||
else
|
||
BenillaQuestLogHasTimer = nil
|
||
timerText:SetText("")
|
||
objective1:SetPoint("TOPLEFT", getglobal("QuestLogObjectivesText"), "BOTTOMLEFT", 0, -10)
|
||
end
|
||
getglobal("QuestLogDescription"):SetText(description or "")
|
||
-- Lua-managed header (ref text=QUEST_DESCRIPTION is static since the ref always has a real
|
||
-- selection whenever this pane is even visible; our flat window keeps the same FontString
|
||
-- alive with no selection, so THIS function — not a static `text=` — owns "Description",
|
||
-- blanked by BenillaQuestLogDetail_Clear on the empty-log path).
|
||
getglobal("QuestLogDescriptionTitle"):SetText("Description")
|
||
|
||
local numObjectives = GetNumQuestLeaderBoards()
|
||
for i = 1, MAX_OBJECTIVES do
|
||
local line = getglobal("QuestLogObjective" .. i)
|
||
if i <= numObjectives then
|
||
local text, kind, finished = GetQuestLogLeaderBoard(i)
|
||
local display = text
|
||
if not display or display == "" then display = kind or "" end
|
||
-- Ref QuestLogFrame.lua:389-394 verbatim: finished objectives go (0.2,0.2,0.2)
|
||
-- with the "(Complete)" suffix, unfinished stay (0,0,0) — both on the parchment.
|
||
if finished then
|
||
display = display .. " (Complete)"
|
||
line:SetTextColor(0.2, 0.2, 0.2)
|
||
else
|
||
line:SetTextColor(0, 0, 0)
|
||
end
|
||
line:SetText(display)
|
||
else
|
||
line:SetText("")
|
||
end
|
||
end
|
||
|
||
-- pin §3, QuestLog_UpdateQuestDetails (QuestLogFrame.lua:414-424): DescriptionTitle is
|
||
-- runtime-SetPoint'd off the LAST actually-used objective slot, not a static chain off
|
||
-- Objective10 — a quest with fewer than 10 objectives would otherwise drag this header
|
||
-- down by however much dead space the unused tail slots add (this window's own comment
|
||
-- on the FontString). No RequiredMoney branch here (this file's documented v1 gap: no
|
||
-- widget backs GetQuestLogRequiredMoney yet) — that ref branch collapses into the rest.
|
||
-- The objective-less TIMED branch (ref :432-437) is kept: a timed quest with no
|
||
-- leaderboard lines hangs the header off the countdown row, not off ObjectivesText.
|
||
local objAnchorIndex = math.min(numObjectives, MAX_OBJECTIVES)
|
||
local descTitle = getglobal("QuestLogDescriptionTitle")
|
||
if objAnchorIndex > 0 then
|
||
descTitle:SetPoint("TOPLEFT", getglobal("QuestLogObjective" .. objAnchorIndex), "BOTTOMLEFT", 0, -10)
|
||
elseif questTimer then
|
||
descTitle:SetPoint("TOPLEFT", getglobal("QuestLogTimerText"), "BOTTOMLEFT", 0, -10)
|
||
else
|
||
descTitle:SetPoint("TOPLEFT", getglobal("QuestLogObjectivesText"), "BOTTOMLEFT", 0, -10)
|
||
end
|
||
|
||
local rewardHeight = BenillaQuestLogRewards_Update()
|
||
BenillaQuestLogDetail_ResizeChild(objAnchorIndex, rewardHeight)
|
||
if not doNotScroll then
|
||
getglobal("QuestLogDetailScroll"):SetVerticalScroll(0)
|
||
end
|
||
end
|
||
|
||
-- ── The always-visible quest-watch tracker (QuestWatchFrame) ─────────────────────────
|
||
-- Ref QuestWatch_Update (QuestLogFrame.lua:602-663), re-expressed onto the flat 30-line pool
|
||
-- (the frame's own XML comment): every paint re-anchors each used line — a quest TITLE drops
|
||
-- -5 below the previous line (ref -4 under its 13px boxes; ours are measured 12s, same
|
||
-- pitch), an OBJECTIVE drops -1 (ref 0) — writes " - "-prefixed objective rows colored by
|
||
-- the ref law (finished WHITE, unfinished 0.8-gray; the title dark-gold 0.75/0.61/0 until
|
||
-- every objective completes, then full gold), sizes the frame to the content (width
|
||
-- maxW+10 growing LEFT off the TOPRIGHT anchor, height lines×13), recolors the log
|
||
-- window's Track dot, and hides the pool's trailing lines. `GetQuestIndexForWatch(w)`
|
||
-- answers each watch's CURRENT log index (it follows the quest across a log shuffle —
|
||
-- `quest_log.rs`'s id-keyed watch set), exactly like the ref.
|
||
function QuestWatch_Update()
|
||
local watchTextIndex = 1
|
||
local maxWidth = 0
|
||
for i = 1, GetNumQuestWatches() do
|
||
local questIndex = GetQuestIndexForWatch(i)
|
||
if questIndex then
|
||
local numObjectives = GetNumQuestLeaderBoards(questIndex)
|
||
if numObjectives > 0 then
|
||
local titleLine = getglobal("QuestWatchLine" .. watchTextIndex)
|
||
titleLine:SetText(GetQuestLogTitle(questIndex) or "")
|
||
if watchTextIndex > 1 then
|
||
titleLine:ClearAllPoints()
|
||
titleLine:SetPoint("TOPLEFT", getglobal("QuestWatchLine" .. (watchTextIndex - 1)), "BOTTOMLEFT", 0, -5)
|
||
end
|
||
titleLine:Show()
|
||
if titleLine:GetStringWidth() > maxWidth then maxWidth = titleLine:GetStringWidth() end
|
||
watchTextIndex = watchTextIndex + 1
|
||
local objectivesCompleted = 0
|
||
for j = 1, numObjectives do
|
||
local text, kind, finished = GetQuestLogLeaderBoard(j, questIndex)
|
||
if not text or text == "" then text = kind or "" end
|
||
local line = getglobal("QuestWatchLine" .. watchTextIndex)
|
||
line:SetText(" - " .. text)
|
||
if finished then
|
||
line:SetTextColor(1, 1, 1)
|
||
objectivesCompleted = objectivesCompleted + 1
|
||
else
|
||
line:SetTextColor(0.8, 0.8, 0.8)
|
||
end
|
||
line:ClearAllPoints()
|
||
line:SetPoint("TOPLEFT", getglobal("QuestWatchLine" .. (watchTextIndex - 1)), "BOTTOMLEFT", 0, -1)
|
||
line:Show()
|
||
if line:GetStringWidth() > maxWidth then maxWidth = line:GetStringWidth() end
|
||
watchTextIndex = watchTextIndex + 1
|
||
end
|
||
if objectivesCompleted == numObjectives then
|
||
titleLine:SetTextColor(1, 0.82, 0)
|
||
else
|
||
titleLine:SetTextColor(0.75, 0.61, 0)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
-- The log window's Track dot (the ref's tracking-indicator tail): green with ≥1
|
||
-- watch, red with none.
|
||
if GetNumQuestWatches() > 0 then
|
||
getglobal("QuestLogTrackTracking"):SetVertexColor(0, 1.0, 0)
|
||
else
|
||
getglobal("QuestLogTrackTracking"):SetVertexColor(1.0, 0, 0)
|
||
end
|
||
local frame = getglobal("QuestWatchFrame")
|
||
if watchTextIndex == 1 then
|
||
frame:Hide()
|
||
return
|
||
end
|
||
frame:Show()
|
||
frame:SetHeight(watchTextIndex * 13)
|
||
if maxWidth > 0 then frame:SetWidth(maxWidth + 10) end
|
||
-- The GetStringWidth reads above are extract-measured — a frame stale after a text
|
||
-- change — so the OnUpdate sizing tail re-reads them for two frames and converges.
|
||
frame.used_lines = watchTextIndex - 1
|
||
frame.resize_pending = 2
|
||
for i = watchTextIndex, BENILLA_QUESTWATCH_LINES do
|
||
getglobal("QuestWatchLine" .. i):Hide()
|
||
end
|
||
end
|
||
|
||
-- ── Auto quest watching (ref QuestLogFrame.lua:702-786; AUTO_QUEST_WATCH defaults "1" —
|
||
-- "Quests are automatically watched for 5 minutes when you achieve a quest objective.").
|
||
-- BENILLA_QUEST_PROGRESS(questLogIndex) — our own engine event — arms a 300 s timed
|
||
-- watch: a manual shift-click watch is permanent (no timer entry) and never downgraded,
|
||
-- fresh progress re-arms a timed one, expiry unwatches, and a full watch list evicts the
|
||
-- timed entry nearest expiry (never a manual one). Timers key by quest TITLE (stable
|
||
-- across log shuffles; the engine's watch set is id-keyed — the ref's index-keyed
|
||
-- QUEST_WATCH_LIST bookkeeping is transcribed to its observable law, not its
|
||
-- iterate-while-mutating quirks).
|
||
--
|
||
-- Why NOT the native QUEST_WATCH_UPDATE the ref Lua consumes: the §5-verified engine
|
||
-- (wow-re quest-update-ui-feedback-law.md, handler 0x5e5ad0) fires that event with the
|
||
-- quest's 1-based WATCH-LIST position — 0 when unwatched — while the ref's
|
||
-- AutoQuestWatch_Update(arg1) treats arg1 as a quest-LOG index: the shipped 1.12 chain
|
||
-- is broken at exactly that seam (an unwatched quest's progress arrives as 0, and
|
||
-- AddQuestWatch(0) no-ops), so the advertised auto-watch never actually adds a quest.
|
||
-- We keep the advertised behavior — the feature the option tooltip documents — off the
|
||
-- benilla event that carries what the Lua needed; a deliberate intent-over-letter
|
||
-- divergence (the fold-back decision record).
|
||
--
|
||
-- The FLAG is the ref's own uvar, under the ref's own name since decision 1136 — it was
|
||
-- BENILLA_AUTO_QUEST_WATCH (a boolean) while nothing could change it. It is a "1"/"0"
|
||
-- string now because that is what an options row writes and what the reference's own
|
||
-- consumers compare against; the Interface page's "Automatic Quest Tracking" row drives it.
|
||
--
|
||
-- Which is the SECOND break in this feature, independent of the event seam above and just
|
||
-- as fatal: 1.12 assigns `AUTO_QUEST_WATCH = 1` — the NUMBER — at UIOptionsFrame.lua:122,
|
||
-- while every consumer tests `AUTO_QUEST_WATCH == "1"` (QuestLogFrame.lua:64/68) and the
|
||
-- checkbox loads on the same string compare. In Lua 5.0 `1 ~= "1"`, so on a fresh install
|
||
-- the option paints UNCHECKED and the auto-watch is dead, despite the table declaring
|
||
-- `default = "1"`; it only comes alive once the player clicks the box, which writes the
|
||
-- string. We ship the string, so the advertised default is the real one.
|
||
AUTO_QUEST_WATCH = "1"
|
||
RegisterForSave("AUTO_QUEST_WATCH")
|
||
BENILLA_QUEST_WATCH_TIMER = 300
|
||
BENILLA_QUEST_WATCH_TIMERS = {}
|
||
|
||
function BenillaQuestWatch_RemoveByTitle(title)
|
||
for w = 1, GetNumQuestWatches() do
|
||
local questIndex = GetQuestIndexForWatch(w)
|
||
if questIndex and GetQuestLogTitle(questIndex) == title then
|
||
RemoveQuestWatch(questIndex)
|
||
return
|
||
end
|
||
end
|
||
end
|
||
|
||
function AutoQuestWatch_Update(questIndex)
|
||
if AUTO_QUEST_WATCH ~= "1" or not questIndex then return end
|
||
local title = GetQuestLogTitle(questIndex)
|
||
if not title then return end
|
||
if IsQuestWatched(questIndex) then
|
||
if BENILLA_QUEST_WATCH_TIMERS[title] then
|
||
BENILLA_QUEST_WATCH_TIMERS[title] = BENILLA_QUEST_WATCH_TIMER
|
||
end
|
||
return
|
||
end
|
||
if GetNumQuestLeaderBoards(questIndex) == 0 then return end
|
||
if GetNumQuestWatches() >= BENILLA_QUESTLOG_MAX_WATCHES then
|
||
local lowestTitle, lowestTimer = nil, BENILLA_QUEST_WATCH_TIMER + 1
|
||
for t, timer in pairs(BENILLA_QUEST_WATCH_TIMERS) do
|
||
if timer < lowestTimer then lowestTitle, lowestTimer = t, timer end
|
||
end
|
||
if not lowestTitle then return end -- every slot is a manual watch: no eviction
|
||
BENILLA_QUEST_WATCH_TIMERS[lowestTitle] = nil
|
||
BenillaQuestWatch_RemoveByTitle(lowestTitle)
|
||
end
|
||
AddQuestWatch(questIndex)
|
||
BENILLA_QUEST_WATCH_TIMERS[title] = BENILLA_QUEST_WATCH_TIMER
|
||
end
|
||
|
||
function AutoQuestWatch_OnUpdate(elapsed)
|
||
local expired = nil
|
||
for title, timer in pairs(BENILLA_QUEST_WATCH_TIMERS) do
|
||
if timer - elapsed <= 0 then
|
||
expired = expired or {}
|
||
table.insert(expired, title)
|
||
else
|
||
BENILLA_QUEST_WATCH_TIMERS[title] = timer - elapsed
|
||
end
|
||
end
|
||
if expired then
|
||
for _, title in ipairs(expired) do
|
||
BENILLA_QUEST_WATCH_TIMERS[title] = nil
|
||
BenillaQuestWatch_RemoveByTitle(title)
|
||
end
|
||
QuestWatch_Update()
|
||
BenillaQuestLogList_Update() -- the log's row ticks follow (ref: QuestLog_Update)
|
||
end
|
||
end
|
||
|
||
function BenillaQuestWatchFrame_OnLoad(frame)
|
||
-- Repaints on all three: QUEST_LOG_UPDATE (every log change — the ref's own
|
||
-- QuestLog_OnEvent repaints QuestWatch_Update() off it too, QuestLogFrame.lua:57-70),
|
||
-- the native QUEST_WATCH_UPDATE (arg1 = the WATCH-LIST index, 0 if unwatched — kept
|
||
-- for repaint + any future addon, never for auto-watch: the divergence comment
|
||
-- above), and BENILLA_QUEST_PROGRESS (arg1 = the quest-LOG index) which feeds the
|
||
-- auto-watch.
|
||
frame:RegisterEvent("QUEST_LOG_UPDATE")
|
||
frame:RegisterEvent("QUEST_WATCH_UPDATE")
|
||
frame:RegisterEvent("BENILLA_QUEST_PROGRESS")
|
||
QuestWatch_Update()
|
||
end
|
||
|
||
function BenillaQuestWatchFrame_OnEvent(frame)
|
||
if event == "BENILLA_QUEST_PROGRESS" then
|
||
AutoQuestWatch_Update(arg1)
|
||
QuestWatch_Update()
|
||
elseif event == "QUEST_WATCH_UPDATE" or event == "QUEST_LOG_UPDATE" then
|
||
QuestWatch_Update()
|
||
end
|
||
end
|
||
|
||
-- The watch frame's OnUpdate carries the ref's auto-watch timer decay (ref
|
||
-- QuestLogFrame.xml:1140-1144 — the ALWAYS-VISIBLE frame hosts it, so timers tick with
|
||
-- the log closed; hidden-with-no-watches is safe, an empty watch set has no timers) plus
|
||
-- our sizing-convergence tail (QuestWatch_Update's own comment).
|
||
function BenillaQuestWatchFrame_OnUpdate(frame, elapsed)
|
||
AutoQuestWatch_OnUpdate(elapsed or 0)
|
||
if frame.resize_pending and frame.resize_pending > 0 then
|
||
frame.resize_pending = frame.resize_pending - 1
|
||
local maxw = 0
|
||
for i = 1, (frame.used_lines or 0) do
|
||
local w = getglobal("QuestWatchLine" .. i):GetStringWidth()
|
||
if w > maxw then maxw = w end
|
||
end
|
||
if maxw > 0 then frame:SetWidth(maxw + 10) end
|
||
end
|
||
end
|
||
|
||
-- ── Window lifecycle ─────────────────────────────────────────────────────────────────────
|
||
-- `doNotScroll` (pin §5's asymmetry, threaded through to `BenillaQuestLogDetail_Update`):
|
||
-- absent/falsy for a manual call (a row click, the window's own OnShow); `true` from the
|
||
-- QUEST_LOG_UPDATE event handler below.
|
||
function BenillaQuestLogFrame_Update(doNotScroll)
|
||
QuestLog_SetFirstValidSelection()
|
||
BenillaQuestLogList_Update()
|
||
-- pin §5, QuestLog_OnEvent (QuestLogFrame.lua:57-63): the detail pane only repaints while
|
||
-- the window is visible — the list rebuild above runs unconditionally either way.
|
||
if getglobal("QuestLogFrame"):IsVisible() then
|
||
BenillaQuestLogDetail_Update(doNotScroll)
|
||
end
|
||
end
|
||
|
||
function BenillaQuestLogFrame_OnLoad(frame)
|
||
frame:RegisterEvent("QUEST_LOG_UPDATE")
|
||
end
|
||
|
||
function BenillaQuestLogFrame_OnEvent(frame)
|
||
if event == "QUEST_LOG_UPDATE" then
|
||
-- pin §5: the event-driven refresh path passes doNotScroll=true (QuestLogFrame.lua:62
|
||
-- passes `1`) — a quest updating while already being read must not yank the reader's
|
||
-- scroll position back to the top.
|
||
BenillaQuestLogFrame_Update(true)
|
||
end
|
||
end
|
||
|
||
-- pin §8, QuestLogFrame.lua:24-30 — the app's 'L' binding already calls this
|
||
-- (ui_script/mod.rs).
|
||
function ToggleQuestLog()
|
||
local frame = getglobal("QuestLogFrame")
|
||
if frame:IsVisible() then
|
||
HideUIPanel(frame)
|
||
else
|
||
ShowUIPanel(frame)
|
||
end
|
||
end
|
||
|
||
function BenillaQuestLogCloseButton_OnClick()
|
||
HideUIPanel(getglobal("QuestLogFrame"))
|
||
end
|
||
|
||
-- ── The abandon two-step (mark on click → confirm on Yes) — our `ABANDON_QUEST` entry on
|
||
-- the shared StaticPopup engine (UiPanels.xml, decision 0308 §3). Every field below is
|
||
-- StaticPopup's own vocabulary and every value is specified by StaticPopup.lua:749-761:
|
||
-- the ABANDON_QUEST_CONFIRM wording 'Abandon "%s"?' (GlobalStrings.lua:5), abandoning on
|
||
-- accept, and the igQuestLogAbandonQuest kit. There is no expression left to choose here,
|
||
-- which is why this reads the way the specification does. exclusive is v1-inert (engine
|
||
-- header note). ─────────────────────────────────────────────────────────────────────────
|
||
StaticPopupDialogs["ABANDON_QUEST"] = {
|
||
text = "Abandon \"%s\"?", -- ABANDON_QUEST_CONFIRM
|
||
button1 = "Yes", -- YES
|
||
button2 = "No", -- NO
|
||
OnAccept = function()
|
||
AbandonQuest()
|
||
PlaySound("igQuestLogAbandonQuest")
|
||
end,
|
||
timeout = 0,
|
||
whileDead = 1,
|
||
exclusive = 1,
|
||
hideOnEscape = 1,
|
||
}
|
||
|
||
-- ── ABANDON_QUEST_WITH_ITEMS — DECLARED, never shown ────────────────────────────────────
|
||
-- `GetAbandonQuestItems()` is always nil here (`quest_log.rs`), so nothing in this client
|
||
-- reaches `StaticPopup_Show("ABANDON_QUEST_WITH_ITEMS", …)`, and the click handler below
|
||
-- says so. That was taken as a reason to omit the *entry*, and it is not one: the
|
||
-- reference's StaticPopup.lua declares this table unconditionally at load
|
||
-- (StaticPopup.lua:762-775), whatever the client later shows, and an addon reading `_G`
|
||
-- reads declarations, not behaviour.
|
||
--
|
||
-- Questie is the measurement: `QuestieQuest.lua:55` is
|
||
-- `StaticPopupDialogs["ABANDON_QUEST_WITH_ITEMS"].OnAccept` at file scope, with no guard —
|
||
-- it wraps BOTH abandon dialogs to clear its own quest cache. Absent, that is
|
||
-- `attempt to index field 'ABANDON_QUEST_WITH_ITEMS' (a nil value)` and the addon's whole
|
||
-- quest module never loads. (#3 of the top-20 corpus; the same shape as `ChatFrame3..7`'s
|
||
-- "declared because addons read them", 1497.)
|
||
--
|
||
-- Byte-identical to ABANDON_QUEST above but for `text` — the reference's two entries differ
|
||
-- in exactly that one field. `%s` twice: the quest name, then the item list.
|
||
StaticPopupDialogs["ABANDON_QUEST_WITH_ITEMS"] = {
|
||
text = "Abandon \"%s\", destroying %s?", -- ABANDON_QUEST_CONFIRM_WITH_ITEMS
|
||
button1 = "Yes", -- YES
|
||
button2 = "No", -- NO
|
||
OnAccept = function()
|
||
AbandonQuest()
|
||
PlaySound("igQuestLogAbandonQuest")
|
||
end,
|
||
timeout = 0,
|
||
whileDead = 1,
|
||
exclusive = 1,
|
||
hideOnEscape = 1,
|
||
}
|
||
|
||
function BenillaQuestLogAbandonButton_OnClick()
|
||
if GetQuestLogSelection() == 0 then return end
|
||
-- pin §4, QuestLogFrame.xml:463-472: SetAbandonQuest() pins the click-time selection;
|
||
-- GetAbandonQuestItems() is always nil in v1 (`quest_log.rs`), so only the plain
|
||
-- ABANDON_QUEST popup path exists — never ABANDON_QUEST_WITH_ITEMS. (Ref
|
||
-- QuestLogFrame.lua's own click handler shows the same dialog with the name arg.)
|
||
SetAbandonQuest()
|
||
StaticPopup_Show("ABANDON_QUEST", GetAbandonQuestName() or "")
|
||
end
|
||
]]></Script>
|
||
|
||
<!--
|
||
One reward/choice item row — a byte-for-byte copy of `QuestFrame.xml`'s
|
||
`QuestItemTemplate` (ref `QuestItemTemplate`, QuestFrameTemplates.xml l.85-166),
|
||
DUPLICATED rather than inherited across files: this window's own tests load only its own
|
||
dependency list (Fonts/UiPanels/MerchantFrame — the money helpers), the same per-window
|
||
isolation this repo's other `*_tests.rs` already keep (e.g. `bag_tests.rs` loads
|
||
`MerchantFrame.xml` for its money helper only, never `QuestFrame.xml`). The real client also
|
||
keeps a SEPARATE `QuestLogRewardItemTemplate` from the live `QuestItemTemplate` (pin §3) — so
|
||
this mirrors the ref's own duplication, not just an engine workaround. Keep the two shapes in
|
||
sync by hand if either is revisited.
|
||
-->
|
||
<Button name="BenillaQuestLogItemTemplate" virtual="true" hidden="true">
|
||
<!-- Ref-verbatim geometry (QuestFrameTemplates.xml:85-138): a bare 39×39 icon at TOPLEFT
|
||
(no slot-well texture behind it — the earlier `UI-EmptySlot` here was our own addition
|
||
and read as a heavy black box on the parchment), the name plate overlapping the icon's
|
||
right edge by 10, and the name in GameFontHighlight (12px — not the Small variant). -->
|
||
<Size><AbsDimension x="147" y="41"/></Size>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="$parentIconTexture">
|
||
<Size><AbsDimension x="39" y="39"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"/></Anchors>
|
||
</Texture>
|
||
<Texture name="$parentNameFrame" file="Interface\QuestFrame\UI-QuestItemNameFrame">
|
||
<Size><AbsDimension x="128" y="64"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativeTo="$parentIconTexture" relativePoint="RIGHT"><Offset><AbsDimension x="-10" y="0"/></Offset></Anchor></Anchors>
|
||
</Texture>
|
||
<FontString name="$parentName" inherits="GameFontHighlight" justifyH="LEFT">
|
||
<Size><AbsDimension x="90" y="36"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativeTo="$parentNameFrame"><Offset><AbsDimension x="15" y="0"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
<Layer level="ARTWORK">
|
||
<FontString name="$parentCount" inherits="NumberFontNormal" justifyH="RIGHT">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="$parentIconTexture"><Offset><AbsDimension x="-4" y="1"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<!-- No HighlightTexture: the ref QuestLogRewardItemTemplate (QuestLogFrame.xml:108-123)
|
||
adds only tooltip/click scripts to QuestItemTemplate — reward rows never glow on
|
||
hover, exactly like the giver window's twin template. -->
|
||
<Scripts>
|
||
<OnLoad>
|
||
local n = self:GetName()
|
||
self.icon = getglobal(n .. "IconTexture")
|
||
self.name = getglobal(n .. "Name")
|
||
self.count = getglobal(n .. "Count")
|
||
</OnLoad>
|
||
<!-- The shared id-keyed item tooltip (ref QuestLogRewardItemTemplate OnEnter →
|
||
GameTooltip:SetQuestLogItem — the same C++ renderer every item hover uses). -->
|
||
<OnEnter>
|
||
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
|
||
GameTooltip:SetItemById(self.itemId, self.name:GetText(), self.quality)
|
||
GameTooltip:Show()
|
||
</OnEnter>
|
||
<OnLeave>GameTooltip:Hide()</OnLeave>
|
||
<!-- ref QuestLogRewardItemTemplate's own OnClick (ref QuestLogFrame.xml:118-120): the
|
||
CTRL dressing-room preview + the SHIFT chat-link post, and nothing else — a plain
|
||
click on a quest-log reward row is inert (decisions 1059/1060). -->
|
||
<OnClick>QuestLogRewardItem_OnClick()</OnClick>
|
||
</Scripts>
|
||
</Button>
|
||
|
||
<!--
|
||
One list row (pin §2's QuestLogTitleButtonTemplate, QuestLogFrame.xml:4-107, ~300×16). Text
|
||
lives on a NAMED `$parentText` FontString (not the auto ButtonText slot — same convention
|
||
`GossipFrame.xml`'s `BenillaGossipRowTemplate` uses for its `$parentLabel`), so it can carry
|
||
an explicit LEFT justify. v1 simplification: the ref's Complete/Failed tag rides a SEPARATE
|
||
right-justified `$parentTag` FontString the client shrinks the title to make room for; we
|
||
append the tag straight onto the one title string instead (`BenillaQuestLogList_Update`) —
|
||
simpler, no dynamic width math, costs only the tag not being right-flush.
|
||
State art is now ref-verbatim (QuestLogTitleButtonTemplate, ref QuestLogFrame.xml:68-107):
|
||
the 16x16 plus/minus fold icon slot at LEFT+3 is the button's NormalTexture (the Lua swaps
|
||
Plus/Minus per header fold state and CLEARS it on quest rows — SetNormalTexture("")), the
|
||
16x16 UI-PlusButton-Hilight at the same spot is the ONLY hover art (quest rows clear it
|
||
too — the ref has NO row-wide hover glow), and the text starts at LEFT+20 (the real
|
||
indent; quest rows add the ref's own two-space prefix on top). The PERSISTENT selection bar
|
||
is the separate `QuestLogSelectHighlight` frame `BenillaQuestLogList_Update` moves.
|
||
|
||
`$parentCheck` (pin §2, ref `QuestLogFrame.xml:34-45`) is the per-row watch checkbox — a 16×16
|
||
`UI-CheckBox-Check`, no `file=` here (where the ref uses `hidden="true"`): it starts with
|
||
NO texture bound and is entirely SetTexture-driven from first paint. That shape dates from
|
||
before Texture regions had Show/Hide; `region.rs` has the real pair now and the loader
|
||
honours `hidden=` on regions, so the ref's exact shape is available here if this ever wants
|
||
it — the bind-driven form works and is left alone. SEAT (the director's
|
||
ref A/B — the first build parked it in a left gutter): the ref places the check just past
|
||
the TITLE'S INK — `QuestLog.lua:211/224` computes `LEFT of the row + dummyTextWidth + 24`,
|
||
and with the ref's text inset of 20 that nets to `ink end + 4`. We get the same geometry
|
||
from the anchor graph instead of the Lua dummy-measure hack: the title FontString is
|
||
width-less (its resolved rect hugs its host-measured ink — the measure round-trip), and
|
||
the check anchors LEFT → the title's RIGHT at +4. Known deviation, unchanged: the ref
|
||
shrinks the title width to fit the right-justified tag (its `textWidth` cap); our combined
|
||
title+tag string means a "(Complete)" row seats the check after the tag, not between
|
||
title and tag.
|
||
-->
|
||
<Button name="BenillaQuestLogTitleTemplate" virtual="true" hidden="true">
|
||
<Size><AbsDimension x="300" y="16"/></Size>
|
||
<Layers>
|
||
<Layer level="ARTWORK">
|
||
<FontString name="$parentText" inherits="GameFontNormal" justifyH="LEFT">
|
||
<Anchors><Anchor point="LEFT" relativePoint="LEFT"><Offset><AbsDimension x="20" y="0"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
<Texture name="$parentCheck">
|
||
<Size><AbsDimension x="16" y="16"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativeTo="$parentText" relativePoint="RIGHT"><Offset><AbsDimension x="4" y="0"/></Offset></Anchor></Anchors>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<NormalTexture file="Interface\Buttons\UI-MinusButton-UP">
|
||
<Size><AbsDimension x="16" y="16"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativePoint="LEFT"><Offset><AbsDimension x="3" y="0"/></Offset></Anchor></Anchors>
|
||
</NormalTexture>
|
||
<HighlightTexture name="$parentHighlight" file="Interface\Buttons\UI-PlusButton-Hilight" alphaMode="ADD">
|
||
<Size><AbsDimension x="16" y="16"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativePoint="LEFT"><Offset><AbsDimension x="3" y="0"/></Offset></Anchor></Anchors>
|
||
</HighlightTexture>
|
||
<Scripts>
|
||
<OnLoad>
|
||
self.text = getglobal(self:GetName() .. "Text")
|
||
self.check = getglobal(self:GetName() .. "Check")
|
||
-- Via the state-texture getter (era API), not getglobal: the loader doesn't yet
|
||
-- publish a named state texture's `name=` as a global (known gap — Layers regions
|
||
-- publish, state slots don't).
|
||
self.foldHighlight = self:GetHighlightTexture()
|
||
-- Both buttons must reach OnClick (the default set is LeftButtonUp only) — the same
|
||
-- convention `BagFrame.xml`'s `BenillaBagSlot_OnLoad` uses for its own left/right split.
|
||
self:RegisterForClicks("LeftButtonUp", "RightButtonUp")
|
||
</OnLoad>
|
||
<OnClick>BenillaQuestLogTitle_OnClick(self, arg1)</OnClick>
|
||
</Scripts>
|
||
</Button>
|
||
|
||
<!-- A panel action button (Abandon/Exit/Yes/No) — the UIPanelButtonTemplate face from
|
||
`QuestFrame.xml`'s `BenillaQuestPanelButtonTemplate`, duplicated for the same per-window
|
||
test-isolation reason as `BenillaQuestLogItemTemplate` above. UNLIKE the giver window's
|
||
template this one is NOT hidden="true": the giver's panel-switch Lua re-Show()s each
|
||
panel's pair every switch, but this window's Abandon/Exit are always-visible chrome (ref
|
||
QuestLogFrame.xml:451/482) with no code path that would ever Show() them — inheriting
|
||
hidden left them invisible (0109 look fix; caught on the ui-questlog capture). -->
|
||
<Button name="BenillaQuestLogPanelButtonTemplate" virtual="true">
|
||
<Size><AbsDimension x="80" y="22"/></Size>
|
||
<NormalFont inherits="GameFontNormal"/>
|
||
<HighlightFont inherits="GameFontHighlight"/>
|
||
<DisabledFont inherits="GameFontDisable"/>
|
||
<NormalTexture file="Interface\Buttons\UI-Panel-Button-Up"><TexCoords left="0" right="0.625" top="0" bottom="0.6875"/></NormalTexture>
|
||
<PushedTexture file="Interface\Buttons\UI-Panel-Button-Down"><TexCoords left="0" right="0.625" top="0" bottom="0.6875"/></PushedTexture>
|
||
<DisabledTexture file="Interface\Buttons\UI-Panel-Button-Disabled"><TexCoords left="0" right="0.625" top="0" bottom="0.6875"/></DisabledTexture>
|
||
<HighlightTexture file="Interface\Buttons\UI-Panel-Button-Highlight" alphaMode="ADD"><TexCoords left="0" right="0.625" top="0" bottom="0.6875"/></HighlightTexture>
|
||
</Button>
|
||
|
||
<Frame name="QuestLogFrame" hidden="true">
|
||
<!-- The real 384×512 window (pin §1). No <Anchors> — ShowUIPanel/SetLeftFrame SetPoints this
|
||
to the left slot on open, exactly like Gossip/Merchant/Quest. -->
|
||
<Size><AbsDimension x="384" y="512"/></Size>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<!-- pin §1: 64×64 book icon, TOPLEFT (4,-4). -->
|
||
<Texture file="Interface\QuestFrame\UI-QuestLog-BookIcon">
|
||
<Size><AbsDimension x="64" y="64"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="4" y="-4"/></Offset></Anchor></Anchors>
|
||
</Texture>
|
||
</Layer>
|
||
<Layer level="ARTWORK">
|
||
<!-- pin §1: the four book-panel quadrants, each pinned to its corner, whole-texture. -->
|
||
<Texture file="Interface\QuestFrame\UI-QuestLog-TopLeft"><Size><AbsDimension x="256" y="256"/></Size><Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"/></Anchors></Texture>
|
||
<Texture file="Interface\QuestFrame\UI-QuestLog-TopRight"><Size><AbsDimension x="128" y="256"/></Size><Anchors><Anchor point="TOPRIGHT" relativePoint="TOPRIGHT"/></Anchors></Texture>
|
||
<Texture file="Interface\QuestFrame\UI-QuestLog-BotLeft"><Size><AbsDimension x="256" y="256"/></Size><Anchors><Anchor point="BOTTOMLEFT" relativePoint="BOTTOMLEFT"/></Anchors></Texture>
|
||
<Texture file="Interface\QuestFrame\UI-QuestLog-BotRight"><Size><AbsDimension x="128" y="256"/></Size><Anchors><Anchor point="BOTTOMRIGHT" relativePoint="BOTTOMRIGHT"/></Anchors></Texture>
|
||
|
||
<!-- pin §1: title, TOP (0,-15), GameFontHighlight, text token QUEST_LOG → "Quest Log". -->
|
||
<FontString name="QuestLogTitleText" inherits="GameFontHighlight" justifyH="CENTER" text="Quest Log">
|
||
<Anchors><Anchor point="TOP" relativePoint="TOP"><Offset><AbsDimension x="0" y="-15"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
<!-- pin §1, geometry/art byte-for-byte (ref QuestLogFrame.xml:204-243): the quest-count
|
||
pill is the Common-Input-Border 3-texture trio + a FontString RIGHT of the right
|
||
piece — REPLACING this window's old bare text at (-30,-16), which sat inside the
|
||
close X's hit area and visually collided with it. -->
|
||
<Texture name="QuestLogCountRight" file="Interface\Common\Common-Input-Border">
|
||
<Size><AbsDimension x="8" y="20"/></Size>
|
||
<Anchors><Anchor point="TOPRIGHT" relativePoint="TOPRIGHT"><Offset><AbsDimension x="-47" y="-41"/></Offset></Anchor></Anchors>
|
||
<TexCoords left="0.9375" right="1.0" top="0" bottom="0.625"/>
|
||
</Texture>
|
||
<Texture name="QuestLogCountMiddle" file="Interface\Common\Common-Input-Border">
|
||
<Size><AbsDimension x="100" y="20"/></Size>
|
||
<Anchors><Anchor point="RIGHT" relativeTo="QuestLogCountRight" relativePoint="LEFT"/></Anchors>
|
||
<TexCoords left="0.0625" right="0.9375" top="0" bottom="0.625"/>
|
||
</Texture>
|
||
<Texture name="QuestLogCountLeft" file="Interface\Common\Common-Input-Border">
|
||
<Size><AbsDimension x="8" y="20"/></Size>
|
||
<Anchors><Anchor point="RIGHT" relativeTo="QuestLogCountMiddle" relativePoint="LEFT"/></Anchors>
|
||
<TexCoords left="0" right="0.0625" top="0" bottom="0.625"/>
|
||
</Texture>
|
||
<FontString name="QuestLogCount" inherits="GameFontNormalSmall" justifyH="RIGHT">
|
||
<Anchors><Anchor point="RIGHT" relativeTo="QuestLogCountRight" relativePoint="RIGHT"><Offset><AbsDimension x="-6" y="0"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
<!-- v1 empty state (pin §2's EmptyQuestLogFrame, simplified — this file's header
|
||
comment): one centered message over the row area. No `text=`/`hidden=` here —
|
||
`BenillaQuestLogList_Update` owns this entirely via SetText(""), this file's
|
||
blank-text convention (see that function's comment). -->
|
||
<FontString name="QuestLogEmptyText" inherits="GameFontNormal" justifyH="CENTER">
|
||
<Size><AbsDimension x="300" y="0"/></Size>
|
||
<Anchors><Anchor point="TOP" relativePoint="TOP"><Offset><AbsDimension x="0" y="-90"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
|
||
<!-- Detail page (pin §3): NOW lives on `QuestLogDetailChild`, a real
|
||
ScrollFrame's scroll child (`QuestLogDetailScroll`, below in this window's
|
||
own `<Frames>`) — the 0088 §2 flat-frame constraint this file used to quote here
|
||
DIED with the 0112 resolver fixpoint (child frames render their own `<Layers>`
|
||
regions again), so the whole chain (QuestTitle → ItemReceiveText, the choice/
|
||
reward Buttons, the money coins) moved there verbatim; only the FIRST element's
|
||
anchor changed (the child's own TOPLEFT, ref :624-635's offset 5,-5 — see the
|
||
child's own comment). Nothing detail-page-shaped remains in this window's own
|
||
`<Layers>`. -->
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- The scroll-wheel catcher (this file's header comment) — MUST be first so every real
|
||
widget below out-ranks it in hit-testing. -->
|
||
<Button name="QuestLogWheelCatcher">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativePoint="TOPLEFT"/>
|
||
<Anchor point="BOTTOMRIGHT" relativePoint="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
<Scripts><OnMouseWheel>BenillaQuestLogFrame_OnMouseWheel(arg1)</OnMouseWheel></Scripts>
|
||
</Button>
|
||
|
||
<!-- pin §1: the top-right close X (UIPanelCloseButton in the ref; our engine ships no such
|
||
template — QuestFrame.xml/BagFrame.xml already draw it by hand on the same art). -->
|
||
<Button name="QuestLogCloseButton">
|
||
<Size><AbsDimension x="32" y="32"/></Size>
|
||
<Anchors><Anchor point="TOPRIGHT" relativePoint="TOPRIGHT"><Offset><AbsDimension x="-30" y="-8"/></Offset></Anchor></Anchors>
|
||
<NormalTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Up"/>
|
||
<PushedTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Down"/>
|
||
<HighlightTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Highlight" alphaMode="ADD"/>
|
||
<Scripts><OnClick>BenillaQuestLogCloseButton_OnClick()</OnClick></Scripts>
|
||
</Button>
|
||
|
||
<!-- The "All" fold-all tab (ref QuestLogExpandButtonFrame/QuestLogCollapseAllButton,
|
||
QuestLogFrame.xml:247-323): the sort-tab art trio behind a row-template button at
|
||
(70,-48) — its own +/- NormalTexture slot doubles as the all-state icon. The ref's
|
||
sibling "Track Quest" checkbox (QuestLogTrack) is a named deferral: our watch
|
||
toggle is the row right-click until the track-checkbox arc lands. -->
|
||
<Frame name="QuestLogExpandButtonFrame">
|
||
<Size><AbsDimension x="54" y="32"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="70" y="-48"/></Offset></Anchor></Anchors>
|
||
<Frames>
|
||
<Button name="QuestLogCollapseAllButton" inherits="BenillaQuestLogTitleTemplate" hidden="false" text="All">
|
||
<Size><AbsDimension x="40" y="22"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="0" y="-2"/></Offset></Anchor></Anchors>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="QuestLogExpandTabLeft" file="Interface\QuestFrame\UI-QuestLogSortTab-Left">
|
||
<Size><AbsDimension x="8" y="32"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="-6" y="8"/></Offset></Anchor></Anchors>
|
||
</Texture>
|
||
<Texture name="QuestLogExpandTabMiddle" file="Interface\QuestFrame\UI-QuestLogSortTab-Middle">
|
||
<Size><AbsDimension x="38" y="32"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativeTo="QuestLogExpandTabLeft" relativePoint="RIGHT"/></Anchors>
|
||
</Texture>
|
||
<Texture file="Interface\QuestFrame\UI-QuestLogSortTab-Right">
|
||
<Size><AbsDimension x="8" y="32"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativeTo="QuestLogExpandTabMiddle" relativePoint="RIGHT"/></Anchors>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<Scripts>
|
||
<OnClick>QuestLogCollapseAllButton_OnClick()</OnClick>
|
||
</Scripts>
|
||
<!-- The tab label sits beside its own +/- icon slot (the ref row template's
|
||
ButtonText geometry: LEFT+20 next to the 16px icon at LEFT+3), gold —
|
||
the engine's default label centered "All" OVER the icon (director's
|
||
img-12 misalignment). -->
|
||
<ButtonText>
|
||
<Size><AbsDimension x="0" y="10"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativePoint="LEFT"><Offset><AbsDimension x="20" y="0"/></Offset></Anchor></Anchors>
|
||
</ButtonText>
|
||
<NormalFont inherits="GameFontNormal" justifyH="LEFT"/>
|
||
<HighlightFont inherits="GameFontHighlight" justifyH="LEFT"/>
|
||
</Button>
|
||
</Frames>
|
||
</Frame>
|
||
|
||
<!-- The "Track Quest" watch indicator (ref QuestLogTrack, QuestLogFrame.xml:324-369):
|
||
an INDICATOR, not a button — the 20×20 UI-RadioButton pair (base = the left
|
||
quarter, the dot = the second quarter) with the dot vertex-colored by
|
||
`QuestWatch_Update`: red when nothing is watched, green when ≥1 is (ref
|
||
`QuestWatch_Update`'s tracking-indicator tail). Watching itself stays the row
|
||
shift-click (`QUEST_WATCH_TOOLTIP`, served on hover). Ref HitRectInsets
|
||
(right −80, stretching the hover over the label) is an engine gap — the hover
|
||
rect is the 20×20 dot only. -->
|
||
<Frame name="QuestLogTrack" enableMouse="true">
|
||
<Size><AbsDimension x="20" y="20"/></Size>
|
||
<Anchors>
|
||
<Anchor point="LEFT" relativeTo="QuestLogExpandButtonFrame" relativePoint="RIGHT">
|
||
<Offset><AbsDimension x="5" y="10"/></Offset>
|
||
</Anchor>
|
||
</Anchors>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<FontString name="$parentTitle" inherits="GameFontHighlightSmall" text="Track Quest">
|
||
<Anchors><Anchor point="LEFT" relativePoint="RIGHT"/></Anchors>
|
||
</FontString>
|
||
<Texture file="Interface\Buttons\UI-RadioButton">
|
||
<TexCoords left="0" right="0.25" top="0" bottom="1"/>
|
||
</Texture>
|
||
<Texture name="QuestLogTrackTracking" file="Interface\Buttons\UI-RadioButton">
|
||
<TexCoords left="0.25" right="0.5" top="0" bottom="1"/>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<Scripts>
|
||
<OnLoad>
|
||
getglobal("QuestLogTrackTracking"):SetVertexColor(1.0, 0, 0)
|
||
</OnLoad>
|
||
<OnEnter>
|
||
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
|
||
GameTooltip:SetText("Shift-click a quest to add or remove a quest from your quest watch list.", nil, nil, nil, nil, 1)
|
||
</OnEnter>
|
||
<OnLeave>
|
||
GameTooltip:Hide()
|
||
</OnLeave>
|
||
</Scripts>
|
||
</Frame>
|
||
|
||
<!-- The persistent selection highlight (ref QuestLogHighlightFrame, QuestLogFrame.xml:
|
||
522-534): 293×16, ARTWORK-layer ADD `UI-QuestLogTitleHighlight`, declared BEFORE the
|
||
title rows so the row text paints OVER the glow (same parent + same frameLevel ⇒
|
||
declaration order is the z-tiebreak; the old `frameLevel="8"` put the glow ON TOP of
|
||
the title text and washed it out — 0112's capture gate caught the wash, this scrub
|
||
found the cause). Moved onto the selected row (at the ref's (5,0)) and vertex-colored
|
||
to the row's difficulty color by `BenillaQuestLogList_Update` (ref lua l.337-339). -->
|
||
<Frame name="QuestLogSelectHighlight" hidden="true">
|
||
<Size><AbsDimension x="293" y="16"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"/></Anchors>
|
||
<Layers><Layer level="ARTWORK">
|
||
<Texture name="QuestLogSkillHighlight" file="Interface\QuestFrame\UI-QuestLogTitleHighlight" alphaMode="ADD">
|
||
<Anchors><Anchor point="TOPLEFT"/><Anchor point="BOTTOMRIGHT"/></Anchors>
|
||
</Texture>
|
||
</Layer></Layers>
|
||
</Frame>
|
||
|
||
<!-- pin §2, geometry byte-for-byte (ref QuestLogFrame.xml:535-588): 6 title rows,
|
||
300×16, row1 TOPLEFT of the frame at (19,-75); rows 2-6 chain TOPLEFT→prior BOTTOMLEFT
|
||
at (0,+1) — a TIGHT 1px OVERLAP, not a gap (the ref's own offset is positive). -->
|
||
<Button name="QuestLogTitle1" inherits="BenillaQuestLogTitleTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="19" y="-75"/></Offset></Anchor></Anchors>
|
||
</Button>
|
||
<Button name="QuestLogTitle2" inherits="BenillaQuestLogTitleTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogTitle1" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="1"/></Offset></Anchor></Anchors></Button>
|
||
<Button name="QuestLogTitle3" inherits="BenillaQuestLogTitleTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogTitle2" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="1"/></Offset></Anchor></Anchors></Button>
|
||
<Button name="QuestLogTitle4" inherits="BenillaQuestLogTitleTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogTitle3" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="1"/></Offset></Anchor></Anchors></Button>
|
||
<Button name="QuestLogTitle5" inherits="BenillaQuestLogTitleTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogTitle4" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="1"/></Offset></Anchor></Anchors></Button>
|
||
<Button name="QuestLogTitle6" inherits="BenillaQuestLogTitleTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogTitle5" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="1"/></Offset></Anchor></Anchors></Button>
|
||
|
||
<!-- The detail pane's real ScrollFrame (decision 0112's mechanism): 300×261, TOPLEFT of
|
||
this window at (19,-175) — the ref's own `QuestLogDetailScrollFrame` position, this
|
||
file's "Detail chain start" arithmetic that used to live above (list bottom-left
|
||
(19,-168) - 7 = (19,-175)). Mouse-wheel-interactive by construction (no wheel-catcher
|
||
needed — `widget/mod.rs`'s ScrollFrame ctor comment), and declared AFTER
|
||
`QuestLogWheelCatcher` in this `<Frames>` list so it out-ranks the catcher for
|
||
any wheel/click landing inside its own rect (this file's header comment on hit-test
|
||
z-order) — scrolling over the detail text no longer scrolls the LIST underneath it,
|
||
a latent mix-up the flat layout had no way to avoid. -->
|
||
<ScrollFrame name="QuestLogDetailScroll">
|
||
<Size><AbsDimension x="300" y="261"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="19" y="-175"/></Offset></Anchor></Anchors>
|
||
<Frames>
|
||
<!-- The scroll child (`SetScrollChild`'d in this ScrollFrame's own OnLoad below):
|
||
300 wide, matching the ref's `QuestLogDetailScrollChildFrame`; HEIGHT is
|
||
runtime-set by `BenillaQuestLogDetail_ResizeChild` (a Frame's height is only
|
||
ever its own SetSize — the resolver never grows one to fit overflowing
|
||
content, that function's own comment) — 261 here is just a sane starting size
|
||
before the first Detail_Update ever runs. Every widget below is the SAME
|
||
detail chain this window used to carry flat on itself (this window's own
|
||
"Detail page" comment) — only QuestTitle's own anchor changed, to the CHILD's
|
||
TOPLEFT (ref :624-635's offset 5,-5) now that it's the origin of its own
|
||
subtree; everything downstream still chains by NAME exactly as before (anchor
|
||
resolution is name-keyed, not parent-scoped — unaffected by which frame owns
|
||
which region). -->
|
||
<Frame name="QuestLogDetailChild">
|
||
<Size><AbsDimension x="300" y="261"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"/></Anchors>
|
||
<Layers>
|
||
<Layer level="ARTWORK">
|
||
<FontString name="QuestLogQuestTitle" inherits="QuestTitleFont" justifyH="LEFT">
|
||
<Size><AbsDimension x="285" y="0"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="5" y="-5"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
<FontString name="QuestLogObjectivesText" inherits="QuestFont" justifyH="LEFT">
|
||
<Size><AbsDimension x="275" y="0"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogQuestTitle" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-5"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
<!-- The timed-quest countdown row (decision 1150) — the ref's QuestLogTimerText,
|
||
QuestLogFrame.xml:648-659, at its own anchor and offset. Untimed quests are the
|
||
overwhelming majority, so the row must cost them NOTHING: the ref hides it and
|
||
re-SetPoints Objective1 straight onto ObjectivesText (QuestLogFrame.lua:370/374),
|
||
and `BenillaQuestLogDetail_Update` keeps exactly that pair of branches. Our
|
||
region model has no Show/Hide for a bare FontString (the recurring comment
|
||
below), so the untimed case leaves this string EMPTY — it draws nothing, and
|
||
nothing anchors through it, so its 12px sits harmlessly behind Objective1's row
|
||
rather than displacing anything. -->
|
||
<FontString name="QuestLogTimerText" inherits="QuestFontNormalSmall" justifyH="LEFT">
|
||
<Size><AbsDimension x="285" y="12"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogObjectivesText" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-10"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
<!-- No `hidden=` on these 10 (a no-op on a region anyway — same reasoning as the
|
||
empty-state text above): each starts textless (no `text=` attribute) and stays
|
||
that way until `BenillaQuestLogDetail_Update` fills the ones in use.
|
||
Objective1's XML anchor is the UNTIMED one (straight onto ObjectivesText) rather
|
||
than the ref's static hop through the timer row, because in this engine that
|
||
row cannot be hidden — the timed branch re-SetPoints it through
|
||
QuestLogTimerText, which is the ref's own runtime behaviour either way
|
||
(QuestLogFrame.lua:370/374; only the XML seed differs, and the ref re-points it
|
||
on every populate before anything is drawn).
|
||
|
||
Height is EXPLICIT 12 (GameFontNormalSmall is 10px, `Fonts.xml`), NOT the ref's
|
||
auto "y=0" — a deliberate v1 deviation: a FontString anchored by a single point
|
||
with an explicit height of exactly 0 and no text ever measured (this engine only
|
||
host-measures a FontString with non-empty text — `UiScript::fontstrings_needing_
|
||
measure`'s own doc) resolves its far edge to `combine_edge`'s span==0 branch,
|
||
which is UNSET, so `resolve()`'s region pass falls the WHOLE unconstrained edge
|
||
back to the OWNER FRAME's edge (`script/mod.rs`'s region-resolution comment) —
|
||
not "zero height", the owner's own far edge. The ref's own equivalent never sees
|
||
this: it :Hide()s unused objective strings entirely (pin §3, QuestLogFrame.lua:
|
||
400-402) — Show/Hide aside — and presumably never lets an anchored-through
|
||
FontString sit at a true zero measured height. This engine's region model has no
|
||
Show/Hide for a bare FontString (this file's own recurring comment on
|
||
`region.rs`), so hiding isn't an option; a fixed nonzero height is the narrowest
|
||
fix that keeps the WHOLE ref chain verbatim. Blank slots now occupy a small
|
||
fixed 12px instead of true 0 — an accepted, minor v1 footprint difference from
|
||
the ref, not a fidelity claim (and exactly why `BenillaQuestLogDetail_ResizeChild`
|
||
sums this fixed 12px per row rather than measuring these ten). -->
|
||
<FontString name="QuestLogObjective1" inherits="QuestFontNormalSmall" justifyH="LEFT">
|
||
<Size><AbsDimension x="285" y="12"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogObjectivesText" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-10"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
<FontString name="QuestLogObjective2" inherits="QuestFontNormalSmall" justifyH="LEFT"><Size><AbsDimension x="285" y="12"/></Size><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogObjective1" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-2"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestLogObjective3" inherits="QuestFontNormalSmall" justifyH="LEFT"><Size><AbsDimension x="285" y="12"/></Size><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogObjective2" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-2"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestLogObjective4" inherits="QuestFontNormalSmall" justifyH="LEFT"><Size><AbsDimension x="285" y="12"/></Size><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogObjective3" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-2"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestLogObjective5" inherits="QuestFontNormalSmall" justifyH="LEFT"><Size><AbsDimension x="285" y="12"/></Size><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogObjective4" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-2"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestLogObjective6" inherits="QuestFontNormalSmall" justifyH="LEFT"><Size><AbsDimension x="285" y="12"/></Size><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogObjective5" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-2"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestLogObjective7" inherits="QuestFontNormalSmall" justifyH="LEFT"><Size><AbsDimension x="285" y="12"/></Size><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogObjective6" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-2"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestLogObjective8" inherits="QuestFontNormalSmall" justifyH="LEFT"><Size><AbsDimension x="285" y="12"/></Size><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogObjective7" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-2"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestLogObjective9" inherits="QuestFontNormalSmall" justifyH="LEFT"><Size><AbsDimension x="285" y="12"/></Size><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogObjective8" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-2"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestLogObjective10" inherits="QuestFontNormalSmall" justifyH="LEFT"><Size><AbsDimension x="285" y="12"/></Size><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogObjective9" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-2"/></Offset></Anchor></Anchors></FontString>
|
||
|
||
<!-- Verbatim ref chain continues (QuestLogFrame.xml:785-833), EXCEPT
|
||
`QuestLogDescriptionTitle` itself: the ref does NOT anchor its
|
||
`QuestLogDescriptionTitle` to a static `QuestLogObjective10` — it re-`SetPoint`s
|
||
it at RUNTIME in `QuestLog_UpdateQuestDetails` off the LAST *actually used*
|
||
objective slot (`QuestLogFrame.lua:414-424`: `QuestLogObjective`..numObjectives,
|
||
or `QuestLogObjectivesText` when numObjectives is 0 — there's also a
|
||
RequiredMoney branch we don't model, this file's documented v1 gap).
|
||
`BenillaQuestLogDetail_Update` ports the ref's runtime SetPoint; the anchor
|
||
below is a load-bearing-free PLACEHOLDER (immediately overwritten whenever a
|
||
selection exists) — same convention the reward/choice Buttons use. Height
|
||
stays EXPLICIT 18 (QuestTitleFont, `Fonts.xml` — matching `RewardTitleText`'s
|
||
own explicit 18 below, which the ref ITSELF gives a nonzero height): the same
|
||
zero-height-owner-fallback rationale as the Objective slots above applies
|
||
whenever the log has zero rewards+choices+money (`RewardTitleText` blanks to ""
|
||
too) — this header must resolve a real span regardless of its own text (and is
|
||
why `BenillaQuestLogDetail_ResizeChild` sums a fixed 18 for it too, never
|
||
`GetHeight()`). -->
|
||
<FontString name="QuestLogDescriptionTitle" inherits="QuestTitleFont" justifyH="LEFT">
|
||
<Size><AbsDimension x="285" y="18"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogObjectivesText" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-10"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
<FontString name="QuestLogDescription" inherits="QuestFont" justifyH="LEFT">
|
||
<Size><AbsDimension x="270" y="0"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogDescriptionTitle" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-5"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
<!-- No `text=`/`hidden=` — `BenillaQuestLogRewards_Update` owns this text entirely
|
||
(toggles "Rewards" / "" — this file's blank-text convention). -->
|
||
<FontString name="QuestLogRewardTitleText" inherits="QuestTitleFont" justifyH="LEFT">
|
||
<Size><AbsDimension x="300" y="18"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogDescription" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-15"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
<!-- REWARD_CHOICES (ref QuestLogFrame.xml:821-832) — our literal transcription of the
|
||
token's string. Lua-managed (`BenillaQuestLogRewards_Update` toggles the text). -->
|
||
<FontString name="QuestLogItemChooseText" inherits="QuestFont" justifyH="LEFT">
|
||
<Size><AbsDimension x="295" y="0"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogRewardTitleText" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-5"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
<!-- QuestLogItemReceiveText (ref :833-837) — unlike the ref's own bare `<Anchor
|
||
point="TOPLEFT"/>` (it's entirely SetPoint-driven at runtime, QuestFrame.lua:
|
||
460/467/470), `BenillaQuestLogRewards_Update` re-SetPoints this one too — see that
|
||
function. No static `relativeTo` here is load-bearing, only a safe placeholder. -->
|
||
<FontString name="QuestLogItemReceiveText" inherits="QuestFont" justifyH="LEFT">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogRewardTitleText" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- Choice + fixed reward rows (pin §3/§6). Static XML anchors below are placeholders
|
||
ONLY (bare TOPLEFT-of-parent-ish, never read while hidden) —
|
||
`BenillaQuestLogRewards_Update` SetPoints every shown row every repaint, porting
|
||
`QuestFrameItems_Update`'s own SetPoint math verbatim (QuestFrame.lua:311-522,
|
||
cited per-line in that function). -->
|
||
<Button name="QuestLogChoice1" inherits="BenillaQuestLogItemTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogItemChooseText" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
</Button>
|
||
<Button name="QuestLogChoice2" inherits="BenillaQuestLogItemTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogChoice1" relativePoint="BOTTOMLEFT"/></Anchors></Button>
|
||
<Button name="QuestLogChoice3" inherits="BenillaQuestLogItemTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogChoice2" relativePoint="BOTTOMLEFT"/></Anchors></Button>
|
||
<Button name="QuestLogChoice4" inherits="BenillaQuestLogItemTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogChoice3" relativePoint="BOTTOMLEFT"/></Anchors></Button>
|
||
<Button name="QuestLogChoice5" inherits="BenillaQuestLogItemTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogChoice4" relativePoint="BOTTOMLEFT"/></Anchors></Button>
|
||
<Button name="QuestLogChoice6" inherits="BenillaQuestLogItemTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogChoice5" relativePoint="BOTTOMLEFT"/></Anchors></Button>
|
||
|
||
<Button name="QuestLogReward1" inherits="BenillaQuestLogItemTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogItemReceiveText" relativePoint="BOTTOMLEFT"/></Anchors></Button>
|
||
<Button name="QuestLogReward2" inherits="BenillaQuestLogItemTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogReward1" relativePoint="BOTTOMLEFT"/></Anchors></Button>
|
||
<Button name="QuestLogReward3" inherits="BenillaQuestLogItemTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogReward2" relativePoint="BOTTOMLEFT"/></Anchors></Button>
|
||
<Button name="QuestLogReward4" inherits="BenillaQuestLogItemTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogReward3" relativePoint="BOTTOMLEFT"/></Anchors></Button>
|
||
<Button name="QuestLogReward5" inherits="BenillaQuestLogItemTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogReward4" relativePoint="BOTTOMLEFT"/></Anchors></Button>
|
||
<Button name="QuestLogReward6" inherits="BenillaQuestLogItemTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogReward5" relativePoint="BOTTOMLEFT"/></Anchors></Button>
|
||
|
||
<!-- Reward money (pin §3, GetQuestLogRewardMoney) — ref QuestLogMoneyFrame anchors LEFT
|
||
to QuestLogItemReceiveText's RIGHT, offset (15,0) (QuestLogFrame.xml:896-903). -->
|
||
<Frame name="QuestLogMoneyCoin1">
|
||
<Size><AbsDimension x="13" y="13"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativeTo="QuestLogItemReceiveText" relativePoint="RIGHT"><Offset><AbsDimension x="15" y="0"/></Offset></Anchor></Anchors>
|
||
<Layers><Layer level="OVERLAY">
|
||
<Texture name="$parentIcon" file="Interface\MoneyFrame\UI-MoneyIcons"><Size><AbsDimension x="13" y="13"/></Size><Anchors><Anchor point="RIGHT" relativePoint="RIGHT"/></Anchors></Texture>
|
||
<FontString name="$parentNum" inherits="NumberFontNormal" justifyH="RIGHT"><Size><AbsDimension x="20" y="13"/></Size><Anchors><Anchor point="RIGHT" relativePoint="RIGHT"><Offset><AbsDimension x="-13" y="0"/></Offset></Anchor></Anchors></FontString>
|
||
</Layer></Layers>
|
||
</Frame>
|
||
<Frame name="QuestLogMoneyCoin2">
|
||
<Size><AbsDimension x="13" y="13"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativeTo="QuestLogMoneyCoin1" relativePoint="RIGHT"><Offset><AbsDimension x="4" y="0"/></Offset></Anchor></Anchors>
|
||
<Layers><Layer level="OVERLAY">
|
||
<Texture name="$parentIcon" file="Interface\MoneyFrame\UI-MoneyIcons"><Size><AbsDimension x="13" y="13"/></Size><Anchors><Anchor point="RIGHT" relativePoint="RIGHT"/></Anchors></Texture>
|
||
<FontString name="$parentNum" inherits="NumberFontNormal" justifyH="RIGHT"><Size><AbsDimension x="20" y="13"/></Size><Anchors><Anchor point="RIGHT" relativePoint="RIGHT"><Offset><AbsDimension x="-13" y="0"/></Offset></Anchor></Anchors></FontString>
|
||
</Layer></Layers>
|
||
</Frame>
|
||
<Frame name="QuestLogMoneyCoin3">
|
||
<Size><AbsDimension x="13" y="13"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativeTo="QuestLogMoneyCoin2" relativePoint="RIGHT"><Offset><AbsDimension x="4" y="0"/></Offset></Anchor></Anchors>
|
||
<Layers><Layer level="OVERLAY">
|
||
<Texture name="$parentIcon" file="Interface\MoneyFrame\UI-MoneyIcons"><Size><AbsDimension x="13" y="13"/></Size><Anchors><Anchor point="RIGHT" relativePoint="RIGHT"/></Anchors></Texture>
|
||
<FontString name="$parentNum" inherits="NumberFontNormal" justifyH="RIGHT"><Size><AbsDimension x="20" y="13"/></Size><Anchors><Anchor point="RIGHT" relativePoint="RIGHT"><Offset><AbsDimension x="-13" y="0"/></Offset></Anchor></Anchors></FontString>
|
||
</Layer></Layers>
|
||
</Frame>
|
||
</Frames>
|
||
</Frame>
|
||
|
||
<!-- A minimal ref-shaped scrollbar (ref UIPanelScrollFrameTemplate/
|
||
UIPanelScrollBarTemplate, UIPanelTemplates.xml): up/down step buttons + a
|
||
thumb texture positioned from GetVerticalScroll/GetVerticalScrollRange. VISUAL
|
||
only — no drag: this engine has no Slider widget (no drag-capture affordance
|
||
anywhere yet, the same class of gap this file's header comment already notes
|
||
for modifier keys), so the ref's real `Slider` track is a named DEFERRED
|
||
follow-up, not modeled here; the wheel + the two arrow buttons are the only
|
||
interactive paths to scroll, which is already the ENTIRE ask (the ref's own
|
||
mouse-drag-the-thumb affordance is the one piece missing). Hidden whenever
|
||
nothing overflows (`BenillaQuestLogDetailScroll_SyncBar`). -->
|
||
<Frame name="QuestLogDetailScrollBar" hidden="true">
|
||
<Size><AbsDimension x="16" y="261"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogDetailScroll" relativePoint="TOPRIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Frames>
|
||
<Button name="QuestLogDetailScrollUp">
|
||
<Size><AbsDimension x="16" y="16"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"/></Anchors>
|
||
<NormalTexture file="Interface\Buttons\UI-ScrollBar-ScrollUpButton-Up"><TexCoords left="0.25" right="0.75" top="0.25" bottom="0.75"/></NormalTexture>
|
||
<PushedTexture file="Interface\Buttons\UI-ScrollBar-ScrollUpButton-Down"><TexCoords left="0.25" right="0.75" top="0.25" bottom="0.75"/></PushedTexture>
|
||
<DisabledTexture file="Interface\Buttons\UI-ScrollBar-ScrollUpButton-Disabled"><TexCoords left="0.25" right="0.75" top="0.25" bottom="0.75"/></DisabledTexture>
|
||
<HighlightTexture file="Interface\Buttons\UI-ScrollBar-ScrollUpButton-Highlight" alphaMode="ADD"><TexCoords left="0.25" right="0.75" top="0.25" bottom="0.75"/></HighlightTexture>
|
||
<Scripts><OnClick>BenillaQuestLogDetailScroll_Step(-BENILLA_QUESTLOG_SCROLL_STEP)</OnClick></Scripts>
|
||
</Button>
|
||
<Button name="QuestLogDetailScrollDown">
|
||
<Size><AbsDimension x="16" y="16"/></Size>
|
||
<Anchors><Anchor point="BOTTOMLEFT" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
<NormalTexture file="Interface\Buttons\UI-ScrollBar-ScrollDownButton-Up"><TexCoords left="0.25" right="0.75" top="0.25" bottom="0.75"/></NormalTexture>
|
||
<PushedTexture file="Interface\Buttons\UI-ScrollBar-ScrollDownButton-Down"><TexCoords left="0.25" right="0.75" top="0.25" bottom="0.75"/></PushedTexture>
|
||
<DisabledTexture file="Interface\Buttons\UI-ScrollBar-ScrollDownButton-Disabled"><TexCoords left="0.25" right="0.75" top="0.25" bottom="0.75"/></DisabledTexture>
|
||
<HighlightTexture file="Interface\Buttons\UI-ScrollBar-ScrollDownButton-Highlight" alphaMode="ADD"><TexCoords left="0.25" right="0.75" top="0.25" bottom="0.75"/></HighlightTexture>
|
||
<Scripts><OnClick>BenillaQuestLogDetailScroll_Step(BENILLA_QUESTLOG_SCROLL_STEP)</OnClick></Scripts>
|
||
</Button>
|
||
<!-- The track: BENILLA_QUESTLOG_SCROLL_TRACK_H (229) tall, between the two
|
||
arrow buttons (261 - 16 - 16). The thumb texture is a plain child
|
||
region SetPoint'd by BenillaQuestLogDetailScroll_SyncBar off the
|
||
CURRENT GetVerticalScroll()/GetVerticalScrollRange() fraction. -->
|
||
<Frame name="QuestLogDetailScrollTrack">
|
||
<Size><AbsDimension x="16" y="229"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="QuestLogDetailScrollUp" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
<Layers><Layer level="OVERLAY">
|
||
<Texture name="QuestLogDetailScrollThumb" file="Interface\Buttons\UI-ScrollBar-Knob">
|
||
<Size><AbsDimension x="16" y="16"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"/></Anchors>
|
||
<!-- The ref thumb samples the knob art's CENTER quarter
|
||
(UIPanelScrollBarButton's TexCoords, UIPanelTemplates.xml
|
||
:104-106 + :160-164) — full UVs squash the 32px canvas
|
||
into 16px and the knob reads half-size (director's
|
||
"scroll cube is too small"). -->
|
||
<TexCoords left="0.25" right="0.75" top="0.25" bottom="0.75"/>
|
||
</Texture>
|
||
</Layer></Layers>
|
||
</Frame>
|
||
</Frames>
|
||
</Frame>
|
||
</Frames>
|
||
<Scripts>
|
||
<OnLoad>self:SetScrollChild(getglobal("QuestLogDetailChild"))</OnLoad>
|
||
<OnMouseWheel>
|
||
if arg1 > 0 then
|
||
BenillaQuestLogDetailScroll_Step(-BENILLA_QUESTLOG_SCROLL_STEP)
|
||
else
|
||
BenillaQuestLogDetailScroll_Step(BENILLA_QUESTLOG_SCROLL_STEP)
|
||
end
|
||
</OnMouseWheel>
|
||
<OnVerticalScroll>BenillaQuestLogDetailScroll_SyncBar()</OnVerticalScroll>
|
||
<OnScrollRangeChanged>BenillaQuestLogDetailScroll_SyncBar()</OnScrollRangeChanged>
|
||
<!-- BenillaQuestLogDetail_OnUpdate's own comment: the FIRST populate of a
|
||
freshly-selected quest's text sizes off a one-tick-stale (zero, brand-new
|
||
text) GetHeight() — nothing else re-asks once the quest log's data itself
|
||
stops changing, so this keeps re-checking every frame the window is open
|
||
until the real measurement lands and the resize stops changing (its own
|
||
guard makes every further call here a no-op). -->
|
||
<OnUpdate>BenillaQuestLogDetail_OnUpdate()</OnUpdate>
|
||
</Scripts>
|
||
</ScrollFrame>
|
||
|
||
<!-- pin §4, geometry byte-for-byte (ref QuestLogFrame.xml:451-498): Abandon 125×21 at
|
||
(17,54), Exit 77×21 at (-43,54). numEntries==0 disables Abandon. -->
|
||
<Button name="QuestLogAbandonButton" inherits="BenillaQuestLogPanelButtonTemplate" text="Abandon Quest">
|
||
<Size><AbsDimension x="125" y="21"/></Size>
|
||
<Anchors><Anchor point="BOTTOMLEFT" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="17" y="54"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnClick>BenillaQuestLogAbandonButton_OnClick()</OnClick></Scripts>
|
||
</Button>
|
||
<Button name="QuestLogExitButton" inherits="BenillaQuestLogPanelButtonTemplate" text="Exit">
|
||
<Size><AbsDimension x="77" y="21"/></Size>
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="-43" y="54"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnClick>HideUIPanel(getglobal("QuestLogFrame"))</OnClick></Scripts>
|
||
</Button>
|
||
<!-- Share Quest (ref QuestFramePushQuestButton, QuestLogFrame.xml:499-521): 123×21 flush
|
||
LEFT of Exit. Party quest-sharing is a named deferral (no QuestLogPushQuest wire yet),
|
||
so this ships permanently DISABLED — exactly how the ref presents it solo (its lua
|
||
disables it whenever the party can't receive the quest); the button existing is what
|
||
fills the bottom row's middle slot the frame art reserves for it. -->
|
||
<Button name="QuestLogPushQuestButton" inherits="BenillaQuestLogPanelButtonTemplate" text="Share Quest">
|
||
<Size><AbsDimension x="123" y="21"/></Size>
|
||
<Anchors><Anchor point="RIGHT" relativeTo="QuestLogExitButton" relativePoint="LEFT"/></Anchors>
|
||
<Scripts><OnLoad>self:Disable()</OnLoad></Scripts>
|
||
</Button>
|
||
</Frames>
|
||
<Scripts>
|
||
<OnLoad>BenillaQuestLogFrame_OnLoad(self)</OnLoad>
|
||
<OnEvent>BenillaQuestLogFrame_OnEvent(self)</OnEvent>
|
||
<!-- The countdown's own repaint (ref QuestLog_OnUpdate, QuestLogFrame.lua:96-105) —
|
||
the ONLY thing the ref's window OnUpdate does. Gated on hasTimer, so it costs an
|
||
untimed selection nothing, and gated on the window being effectively visible by
|
||
`UiScript::tick`'s own OnUpdate gate, so it costs a closed window nothing. -->
|
||
<OnUpdate>QuestLog_OnUpdate(arg1)</OnUpdate>
|
||
<!-- The list wheel lives on the WINDOW, not just the child catcher: the engine bubbles a
|
||
spin up the PARENT chain (script/pointer.rs mouse_wheel), so a spin over a quest-title
|
||
row (no OnMouseWheel of its own) must reach this window to scroll — a sibling catcher
|
||
never sees it (bubbling reaches ancestors, not siblings). The QuestLogWheelCatcher
|
||
button now only gives the list's empty tail a hit-target that also bubbles here. (The
|
||
detail ScrollFrame keeps its own OnMouseWheel and is unaffected.) -->
|
||
<OnMouseWheel>BenillaQuestLogFrame_OnMouseWheel(arg1)</OnMouseWheel>
|
||
<!-- pin §1, QuestLog_OnShow/OnHide (QuestLogFrame.lua:85-95), wired via the frame's
|
||
OnShow/OnHide (QuestLogFrame.xml:949-954) — the window-sound convention (decision
|
||
0090). Note the SoundKit-name vs on-disk-filename trap the pin calls out (§1): the
|
||
kit names below are `igQuestLog*`, the shipped waves are `iQuestLogOpenA`/
|
||
`iQuestLogCloseA` (no "g") — PlaySound takes the KIT name, so this is correct as
|
||
written, flagged only so a future filename-based lookup doesn't "fix" it wrongly.
|
||
Never fires at load (hidden="true"). UpdateMicroButtons leads both, as in the ref
|
||
(QuestLogFrame.lua:85-95's own first line) — live since the micro-menu slice
|
||
(MicroMenu.xml). -->
|
||
<OnShow>if UpdateMicroButtons then UpdateMicroButtons() end PlaySound("igQuestLogOpen") BenillaQuestLogFrame_Update()</OnShow>
|
||
<OnHide>if UpdateMicroButtons then UpdateMicroButtons() end PlaySound("igQuestLogClose")</OnHide>
|
||
</Scripts>
|
||
</Frame>
|
||
|
||
|
||
<!--
|
||
The quest-watch tracker HUD (pin's `QuestWatchFrame`, ref `QuestLogFrame.xml:968-1146`) — a
|
||
SEPARATE always-on-screen frame, not part of `QuestLogFrame` (this file's "The
|
||
always-visible quest-watch tracker" script comment): it's screen-anchored, never docks a
|
||
UIPanel slot, has no close button/ESC handling, and repaints off its own events whether or
|
||
not the log window is even open — a HUD element, exactly like the ref's. Kept in THIS file
|
||
rather than a separate `QuestWatchFrame.xml`: the ref itself defines it in `QuestLogFrame.xml`
|
||
too (it's the log's own on-screen echo, driven by the same Lua functions/getters as the log
|
||
window above), and this file's tests already load nothing else — a second file would need its
|
||
own duplicate test-harness load list for zero isolation benefit (contrast the
|
||
`BenillaQuestLogItemTemplate`/`BenillaQuestLogPanelButtonTemplate` duplication above, which
|
||
buys real per-window test isolation).
|
||
|
||
v1 placement: TOPRIGHT of the screen, offset (-10,-170) — no minimap frame exists in benilla
|
||
yet (the ref anchors 10px below `MinimapCluster`'s bottom edge), so this is a plain guess at
|
||
clearing where one would land (a classic-sized minimap runs roughly 140px tall from the
|
||
corner). FOR THE DIRECTOR'S EYE: revisit once a minimap ships, or sooner if this reads wrong
|
||
on screen.
|
||
|
||
280 wide (the ref's own `QuestWatchFrame` width) with NO Backdrop (the ref's tracker floats
|
||
bare text over the world, no border/background) — matches `UIErrorsFrame`'s bare-text
|
||
convention, not `BenillaQuestLogAbandonConfirm`'s dialog chrome. `BENILLA_QUESTLOG_MAX_WATCHES`
|
||
(5, `quest_log.rs`'s own `AddQuestWatch` cap) × `BENILLA_QUESTWATCH_MAX_OBJECTIVES` (4, this
|
||
file's v1 cap — see that constant's own comment) pre-declares a FIXED 5×(1+4) grid of
|
||
FontStrings — the flat-frame constraint (no dynamic creation at runtime), so every slot exists
|
||
up front and `QuestWatch_Update` only ever SetTexts/colors them, never creates one.
|
||
-->
|
||
<!-- The always-on quest-watch tracker HUD (ref QuestWatchFrame, QuestLogFrame.xml:963-1146
|
||
+ QuestWatch_Update, QuestLogFrame.lua:602-663), re-expressed: TOPRIGHT hangs off the
|
||
MinimapCluster's BOTTOMRIGHT (+10 up — the cluster art overhangs), an empty 13px
|
||
GameFontNormal spacer (the ref's never-written QuestWatchQuestName) seats the first line,
|
||
and ONE FLAT POOL of 30 lines (MAX_QUESTWATCH_LINES) carries titles and objectives alike —
|
||
the Lua re-anchors each line every paint (titles drop -4 extra; the pool squeezes, no
|
||
fixed per-quest slots). Lines are the ref's GameFontHighlight; the XML chain offset is -1
|
||
because our lines are measured (y=0 -> ink height 12) where the ref pins 13px boxes:
|
||
12 + 1 = the ref pitch. Width/height follow the content (SetWidth maxW+10 / SetHeight
|
||
lines*13) so the left-aligned column hugs the minimap's right edge like the ref; the
|
||
GetWidth reads are extract-measured (one frame stale), so the sizing tail re-runs from
|
||
OnUpdate for two frames after each repaint (`resize_pending`) and converges next frame. -->
|
||
<Frame name="QuestWatchFrame">
|
||
<Size><AbsDimension x="280" y="20"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPRIGHT" relativeTo="MinimapCluster" relativePoint="BOTTOMRIGHT">
|
||
<Offset><AbsDimension x="0" y="10"/></Offset>
|
||
</Anchor>
|
||
</Anchors>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<FontString name="QuestWatchQuestName" inherits="GameFontNormal" justifyH="LEFT">
|
||
<Size><AbsDimension x="0" y="13"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT"/></Anchors>
|
||
</FontString>
|
||
<FontString name="QuestWatchLine1" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchQuestName" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine2" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine1" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine3" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine2" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine4" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine3" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine5" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine4" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine6" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine5" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine7" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine6" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine8" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine7" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine9" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine8" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine10" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine9" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine11" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine10" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine12" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine11" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine13" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine12" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine14" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine13" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine15" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine14" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine16" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine15" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine17" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine16" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine18" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine17" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine19" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine18" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine20" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine19" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine21" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine20" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine22" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine21" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine23" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine22" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine24" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine23" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine25" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine24" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine26" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine25" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine27" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine26" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine28" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine27" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine29" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine28" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
<FontString name="QuestWatchLine30" inherits="GameFontHighlight" justifyH="LEFT"><Anchors><Anchor point="TOPLEFT" relativeTo="QuestWatchLine29" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor></Anchors></FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Scripts>
|
||
<OnLoad>BenillaQuestWatchFrame_OnLoad(self)</OnLoad>
|
||
<OnEvent>BenillaQuestWatchFrame_OnEvent(self)</OnEvent>
|
||
<OnUpdate>BenillaQuestWatchFrame_OnUpdate(self, arg1)</OnUpdate>
|
||
</Scripts>
|
||
</Frame>
|
||
</Ui>
|