Files
benilla-octo/crates/benilla-app/assets/ui/GameTooltip.xml
T
SamandClaude Fable 5 348f55e37e four extra action bars as options, and the bottom band gets one owner
- the four extra action bars become per-character options, off by default, on a new Action Bars options page — the toggles ride the server's own byte (`CMSG_SET_ACTIONBAR_TOGGLES` into `PLAYER_FIELD_BYTES`), so a fresh character's zero is the default for free; turning the bottom-left bar off gives the stance bar its previously unbuilt unraised look, end-caps and 64×64 rings
- bag windows stop drawing straight through a raised bottom bar: the bottom band has ONE owner — the manage pass — the bag stack joins it through a listener seam, and a guard test walks all eight raisable-bar combinations across 24 bar/tenant pairs and refuses overlap
- the item-push card takes the reference's real geometry, closing the gap 0887 measured
- resizable addon windows stop at their bounds instead of pinning and walking across the screen: four per-frame f32s with 0.0 the disable sentinel, the clamp on the interactive drag only with the residual rebated out of the drag delta, `<ResizeBounds>` in XML honoured — and `SetFontString`'s three raises land exactly as the bytes have them

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 18:12:19 +07:00

616 lines
42 KiB
XML

<Ui>
<!--
The GameTooltip (decision 0274): a real <GameTooltip> engine widget — the line stack,
SetOwner anchor law, auto-size + right-flush, IsOwned, FadeOut, and the OnTooltipCleared/
OnTooltipAddMoney script protocol all live engine-side (benilla-ui script/tooltip.rs); the
line pairs are engine-created named regions (GameTooltipTextLeftN/RightN — real globals,
like the template pairs reference Lua addresses by name). This file declares the two
TEMPLATES and their instances: the plate (backdrop art + colors QUOTED from
ref-GameTooltip.xml/.lua, line cites inline), the money coin trio, and the Lua that is
genuinely FrameXML's in the real client (GameTooltip_SetDefaultAnchor,
GameTooltip_AddNewbieTip, SetTooltipMoney) — plus the P0 item-stat renderer, which
moves engine-side in 0274 P1 with the full template feed.
The frame's global name is the real one — GameTooltip — so transcribed reference code
(MinimapCluster's zone hover, UnitFrame's TextLeft1 recolor) works verbatim.
The reference splits this across two files — Interface\FrameXML\GameTooltipTemplate.xml
holds the virtual GameTooltipTemplate (l.3-627) and ShoppingTooltipTemplate (l.628-1217);
GameTooltip.xml <Include>s it and declares only the instances. Both templates live here
instead, ABOVE their instances, because that is the whole of their reach: the tooltip file
already loads before every window that hovers, and keeping them in one file means the
template is registered by the time the instances (and, later, ItemRef.xml's) expand it
without a second manifest entry to keep in order. Same registry, same splice, one file.
-->
<Script><![CDATA[
-- Tooltip default colours (VERIFIED, ref-GameTooltip.lua l.3-4). The border is white, the
-- background the dark blue tint; applied to the Backdrop in OnLoad exactly as the real
-- GameTooltip_OnLoad does (ref-GameTooltip.lua l.79-82).
TOOLTIP_DEFAULT_COLOR = { r = 1, g = 1, b = 1 }
TOOLTIP_DEFAULT_BACKGROUND_COLOR = { r = 0.09, g = 0.09, b = 0.19 }
-- GameTooltip_SetDefaultAnchor's position math (ref-GameTooltip.lua l.6,73-77): the
-- bottom-right screen corner, -CONTAINER_OFFSET_X - 13 in x, CONTAINER_OFFSET_Y in y.
DEFAULT_TOOLTIP_POSITION = -13
-- The shopping-compare pair count (ref GameTooltip.lua l.7; PaperDollFrame's listener
-- bounds arg2 by it).
NUM_SHOPPING_TOOLTIPS = 2
-- "Show Detailed Tooltips" — ref UIOptionsFrame.lua l.100-101, inside UIOptionsFrame_Init:
-- SHOW_NEWBIE_TIPS = "1"; RegisterForSave("SHOW_NEWBIE_TIPS");
-- It is a FrameXML *uvar*, not a CVar, and 1.12 ships it ON — so the detailed second line
-- IS the default reference tooltip, not an opt-in. (An earlier note in this corpus had this
-- backwards; decision 0661.) The options window's Interface page drives it now
-- (decision 1136), and the assignment below is the ONLY statement of the default: the saved
-- chunk executes over it at load (1128) and the row captures it as its Defaults value at
-- OnLoad — which runs first — so "1" is written down in exactly one place, here.
SHOW_NEWBIE_TIPS = "1"
RegisterForSave("SHOW_NEWBIE_TIPS")
-- The bracketed name out of an item hyperlink "|cff…|Hitem:117|h[Tough Jerky]|h|r"; if the
-- string has no bracket it is already a plain name (the merchant/loot rows hand plain names).
function BenillaTooltip_ItemName(link)
if not link then return nil end
local _, _, name = strfind(link, "%[(.-)%]")
return name or link
end
-- Reuse the quality→colour source the loot window already ships (BENILLA_LOOT_QUALITY_COLORS,
-- LootFrame.xml — itself matching ui_items.rs quality_color / the client's GetItemQualityColor).
-- Unknown/nil quality falls back to common white. All FrameXML files load before any hover
-- fires, so the table is defined by the time this runs regardless of file order.
function BenillaTooltip_QualityColor(quality)
local t = BENILLA_LOOT_QUALITY_COLORS
local c = (t and (t[quality] or t[1])) or { r = 1, g = 1, b = 1 }
return c.r, c.g, c.b
end
-- Copper → "Ng Ms Kc" text for a price/value line (only the non-zero high coins, always the
-- copper). math.floor if present, else a truncation fallback.
function BenillaTooltip_MoneyString(copper)
copper = copper or 0
local mfloor = (math and math.floor) or function(x) return x - (x % 1) end
local g = mfloor(copper / 10000)
local s = mfloor((copper - g * 10000) / 100)
local c = copper - g * 10000 - s * 100
local out = ""
if g > 0 then out = g .. "g " end
if s > 0 or g > 0 then out = out .. s .. "s " end
return out .. c .. "c"
end
-- The default anchor (ref-GameTooltip.lua l.73-77, quoted): owner with no auto-anchor,
-- then the bottom-right screen corner, above the bag row - CONTAINER_OFFSET_X/Y are the
-- manage pass's live values (UIParent.xml). The engine's ANCHOR_NONE drops the previous
-- owner anchor (tooltip.rs SetOwner), so no ClearAllPoints - the ref has none either.
function GameTooltip_SetDefaultAnchor(tooltip, parent)
tooltip:SetOwner(parent, "ANCHOR_NONE")
-- Read the two managed globals FRESH, and fall back AT USE rather than assigning a
-- copy: this file used to open with `CONTAINER_OFFSET_X = CONTAINER_OFFSET_X or 0`,
-- which is a second written statement of numbers UIParent.xml owns. Harmless in the
-- shipped load order (UIParent.xml is manifest 42, this file later) but it is the same
-- shape as the shadow pair that froze the bag stack at the no-bars corner, so the law
-- of 1499 forbids it outright: nothing outside UIParent.xml assigns a managed offset.
-- The `or` defaults below cover the tooltip-only harnesses that load no UIParent.
local offsetX = CONTAINER_OFFSET_X or 0
local offsetY = CONTAINER_OFFSET_Y or 70
tooltip:SetPoint("BOTTOMRIGHT", "UIParent", "BOTTOMRIGHT",
-offsetX + DEFAULT_TOOLTIP_POSITION, offsetY)
tooltip.default = 1
end
-- The two-line UI-element tooltip (spec: ref-GameTooltip.lua l.107-123): a white label,
-- then the long explanation wrapped underneath in NORMAL_FONT_COLOR — the whole reason a
-- 1.12 hover over the ping meter or a micro button is a paragraph and not four words.
-- With detailed tips on it seats at the DEFAULT corner, not beside the owner; with them off
-- it collapses to the bare label at the owner's right. `noNormalText` says "the explanation
-- is the whole tooltip" (the XP bar) — with tips off such a hover shows nothing at all.
--
-- Signature note: the ref reads the firing frame from the `this` global; the corpus
-- convention is to keep the ref NAME and take that frame as a leading parameter
-- (GameTooltip_OnHide(self), GameTooltip_ClearMoney(frame) — same shift). Reference code
-- pasted in verbatim must therefore have the owner threaded in as arg 1.
-- **The reference's exact signature, because a signature IS api (1199).** Ours used to take
-- the owner as arg 1; the reference takes none and reads `this`. Outfitter calls it the
-- reference's way (`OutfitterMinimapButton:OnEnter` -> `GameTooltip_AddNewbieTip(text, ...)`),
-- so its TEXT landed in our owner slot and `SetOwner` raised
-- "bad argument #2: error converting Lua string to table". Found by the use-probe, not by
-- reading: it only fires when something hovers.
--
-- Our own callers mostly hold the owner in a local that is NOT the firing frame (`bar`,
-- `button`, `frame`), so they use the explicit-owner variant below rather than `this`.
function GameTooltip_AddNewbieTip(normalText, r, g, b, newbieText, noNormalText)
BenillaTooltip_AddNewbieTipFor(this, normalText, r, g, b, newbieText, noNormalText)
end
-- The explicit-owner form our FrameXML uses, and where the behaviour above actually lives:
-- the owner is threaded in rather than read off `this`. Kept under a Benilla name so it can
-- never be mistaken for a reference global an addon might call or replace.
function BenillaTooltip_AddNewbieTipFor(owner, normalText, r, g, b, newbieText, noNormalText)
-- Detailed tips OFF is the short shape: the label alone, beside whatever it labels.
-- A caller that says its label is worthless on its own then has nothing left to show.
if SHOW_NEWBIE_TIPS ~= "1" then
if not noNormalText then
GameTooltip:SetOwner(owner, "ANCHOR_RIGHT")
GameTooltip:SetText(normalText, r, g, b)
end
return
end
-- Detailed tips ON: a paragraph, and paragraphs go to the screen corner instead of
-- crowding the thing they explain.
GameTooltip_SetDefaultAnchor(GameTooltip, owner)
if normalText then
-- Label in the caller's colour; the explanation under it, wrapped, always in
-- NORMAL_FONT_COLOR — the two lines are deliberately not the same colour.
GameTooltip:SetText(normalText, r, g, b)
GameTooltip:AddLine(newbieText, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1)
else
-- No label, so the explanation IS the tooltip: it takes the caller's colour, plus
-- SetText's alpha and wrap flags (args 5 and 6) — the wrap the second line above
-- would otherwise have carried.
GameTooltip:SetText(newbieText, r, g, b, 1, 1)
end
GameTooltip:Show()
end
-- ref GameTooltip_OnHide (ref-GameTooltip.lua l.100-104, quoted): the plate colours
-- reset for the next owner and the default-corner flag drops. The ref's OnHide also
-- hides ShoppingTooltip1/2 - that pair lands with the compare-tooltip slice (0274 P4).
--
-- `self or this`: the corpus calls this the REFERENCE way, with no argument at all
-- (TipBuddy.xml l.1412, atsw.xml l.3420, and TipBuddy.lua l.2520 which REPLACES the global
-- and calls the saved original bare). The signature note above explains the corpus-wide
-- shift to a leading parameter; nothing lets us edit an addon, and `this` is exactly what
-- the reference reads here, so the two spellings mean the same thing.
function GameTooltip_OnHide(self)
self = self or this
self:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b)
self:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b)
self.default = nil
end
-- The embedded money row — the ref's SetTooltipMoney (ref-GameTooltip.lua l.84-92) over our
-- shared coin kit (BenillaMoney_Set, MerchantFrame.xml): a blank line, the coin trio seated
-- at the money line's LEFT +4, and the money's width as the tooltip's minimum width. The
-- engine fires OnTooltipAddMoney with the computed price (wow-re ui/scratch/tooltip-money.md
-- 0x52b650@0x52e376: the engine computes, FrameXML renders) and this is its handler; Lua
-- call sites (repair cost) call it directly, exactly like the ref's ContainerFrame does.
function SetTooltipMoney(frame, money)
frame:AddLine(" ", 1.0, 1.0, 1.0)
local numLines = frame:NumLines()
local line = getglobal(frame:GetName() .. "TextLeft" .. numLines)
local coin1 = getglobal(frame:GetName() .. "MoneyCoin1")
coin1:ClearAllPoints()
coin1:SetPoint("LEFT", line, "LEFT", 4, 0)
BenillaMoney_Set(frame:GetName() .. "Money", money, true)
local width = 4
for i = 1, 3 do
local c = getglobal(frame:GetName() .. "MoneyCoin" .. i)
if c:IsShown() then width = width + c:GetWidth() + 4 end
end
frame:SetMinimumWidth(width)
end
-- The money row clears whenever the content does (the ref wires GameTooltip_ClearMoney to
-- OnTooltipCleared; the engine fires it on ClearLines/SetOwner/Hide). BenillaMoney_Clear
-- ships in MerchantFrame.xml (the money kit's home) — guard for engine tests that load
-- this file alone; in the app every file is loaded.
function GameTooltip_ClearMoney(frame)
frame = frame or this
if BenillaMoney_Clear then
BenillaMoney_Clear(frame:GetName() .. "Money")
end
end
-- The item content channels (SetItemById/SetBagItem/SetMerchantItem/SetBuybackItem) are
-- ENGINE methods on the GameTooltip widget (benilla-ui script/tooltip_item.rs, decision
-- 0274 P1): one shared renderer — the real client's own shape (0x52b650 behind 8 of the
-- 9 Set*Item bindings, wow-re ui/scratch/tooltip-money.md; decision 0126's one-renderer
-- law) — over the full item-template store, with the red failed-requirement law and the
-- engine-fired sell-price money row (merchant open + real instance + repair off).
-- The reaction color table (ref ReputationFrame.lua l.3-12, quoted) — the unit-name
-- recolor's palette; guarded so a later reputation window's own definition wins.
FACTION_BAR_COLORS = FACTION_BAR_COLORS or {
[1] = { r = 0.8, g = 0.3, b = 0.22 },
[2] = { r = 0.8, g = 0.3, b = 0.22 },
[3] = { r = 0.75, g = 0.27, b = 0 },
[4] = { r = 0.9, g = 0.7, b = 0 },
[5] = { r = 0, g = 0.6, b = 0.1 },
[6] = { r = 0, g = 0.6, b = 0.1 },
[7] = { r = 0, g = 0.6, b = 0.1 },
[8] = { r = 0, g = 0.6, b = 0.1 },
}
-- GameTooltip_UnitColor (ref-GameTooltip.lua l.8-71): creatures color by reaction;
-- players read white (the ref's own shipping state — its hostile/PvP player branches
-- are the FACTION_BAR_COLORS reds/greens, kept for when PvP states stream). The engine
-- prints the name gold and fires UPDATE_MOUSEOVER_UNIT; this recolors line 1 (the
-- byte-verified split — the name COLOR is FrameXML's, decision 0276).
function GameTooltip_UnitColor(unit)
local reaction = UnitReaction(unit, "player")
if reaction and FACTION_BAR_COLORS[reaction] then
local c = FACTION_BAR_COLORS[reaction]
return c.r, c.g, c.b
end
return 1.0, 1.0, 1.0
end
-- The health bar's own fill colour (spec: ref-HealthBar.lua, the whole file).
--
-- Two colourings in one handler. `smooth` asks for the health RAMP — green at the top of
-- the range, red at the bottom, and between them a two-segment fade that pins one channel
-- at full and slides the other, so the halfway mark reads solid yellow. Without it the bar
-- is flat green whatever it reads. Blue is 0 either way, which is what keeps the fade
-- inside the red-yellow-green wedge and never lets it wash out.
--
-- **Nothing passes `smooth` — not us and not the reference.** Verified: our only caller is
-- the status bar's `<OnValueChanged>` below (one argument), and 1.12's own two callers are
-- ref-GameTooltipTemplate.xml l.593 and ref-UnitFrame.lua l.181, both of which forward
-- `value` alone. So the ramp has never coloured a bar in this game; it is kept because it
-- is the contract an addon replacing a unit frame may still call with two arguments.
--
-- A value outside the bar's own range leaves the colour untouched rather than being clamped
-- to an end of the ramp — the reference's own guard, kept as the reference has it.
function HealthBar_OnValueChanged(value, smooth)
if not value then return end
local bar = this
local min, max = bar:GetMinMaxValues()
if value < min or value > max then return end
local r, g = 0.0, 1.0
if smooth then
local filled = 0
if max > min then filled = (value - min) / (max - min) end
if filled > 0.5 then
r, g = (1.0 - filled) * 2, 1.0
else
r, g = 1.0, filled * 2
end
end
bar:SetStatusBarColor(r, g, 0.0)
end
-- `self or this` for the same reason as GameTooltip_OnHide: an addon inheriting
-- GameTooltipTemplate re-declares <OnLoad> to add its own line and opens it with the
-- reference's bare `GameTooltip_OnLoad();` (TipBuddy.xml l.1402, atsw.xml l.3417) — a nil
-- self there is a load ERROR, and the plate it was about to tint never gets its colours.
-- The body is the ref's two lines and NOTHING else. It used to end with a `self:Hide()` we
-- had added, which the reference (l.79-82, the whole function) does not have — inert for
-- our four tooltips, since every one of them carries `hidden="true"` and the loader's
-- attribute pass runs Hide() long before OnLoad fires, but NOT inert for an addon: two of
-- the 27 declare `hidden="false"` on purpose (PowerAuras.xml l.20, SimpleActionSets.xml
-- l.349) and never call Show(), so the extra line hid a tooltip the real client leaves up.
-- A helper that quietly does more than the reference's is exactly the kind of thing that
-- only shows up when someone else's code calls it.
function GameTooltip_OnLoad(self)
self = self or this
-- The plate colours (ref GameTooltip_OnLoad, ref-GameTooltip.lua l.79-82).
self:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b)
self:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b)
end
]]></Script>
<!--
GameTooltipTemplate (ref-GameTooltipTemplate.xml l.3-627) — the shared tooltip SHAPE, and
the single most-wanted template in the addon corpus: 27 addons name it in an XML
`inherits=` (TipBuddy, AtlasLoot, CT_BarMod, MikScrollingBattleText, TheoryCraft, …) and
two more reach it through CreateFrame("GameTooltip", name, nil, "GameTooltipTemplate").
Every one of those declarations is a <GameTooltip> element, so the template's job is to
hand them the PLATE and the STATUS BAR; the line pairs they then read
(`getglobal(tip:GetName().."TextLeft1")`) are engine-created per instance and can never
carry the template's name.
What is here is what the reference's template carries and all our instances shared, moved
verbatim from the GameTooltip instance below: the backdrop plate, the Thicken deviation
(its rationale note travels WITH it — this is the shared plate, not one window's), the
$parentStatusBar, and the OnLoad/OnHide pair (ref l.611-616).
What is deliberately NOT here, and stays on the GameTooltip instance:
- The money coin trio and the OnTooltipAddMoney/OnTooltipCleared pair. The reference's
template carries a $parentMoneyFrame (l.598-608, a SmallMoneyFrameTemplate), so its
handler is safe on every instance; ours is a bespoke three-coin row that only
GameTooltip declares, so a templated OnTooltipAddMoney would index a MoneyCoin1 that
does not exist. Moving the row up would give ItemRefTooltip and every addon tooltip a
coin line they render today without — a visible change, so it waits for the director.
- OnTooltipSetDefaultAnchor (ref l.617-619). The engine fires it by name on `GameTooltip`
alone (script/tooltip_unit.rs looks the frame up), so on any other instance it is dead
weight.
`clampedToScreen="true"` is the reference's own attribute and is a no-op for us: decision
0352 made the flag default-ON for every GameTooltip-kind frame, because the reference plate
observably clamps though its XML never sets it. Kept because it is what the reference says.
-->
<GameTooltip name="GameTooltipTemplate" frameStrata="TOOLTIP" clampedToScreen="true" hidden="true" virtual="true">
<!-- The tooltip plate (ref-GameTooltipTemplate.xml l.4-14 / ref-GameTooltip.xml l.33-43):
UI-Tooltip-Background tiled, UI-Tooltip-Border edge, EdgeSize 16, TileSize 16, insets
5/5/5/5. Colours are set in OnLoad (SetBackdropColor/BorderColor) — no <Color> here, so
the plate starts ctor-white and OnLoad tints it. -->
<Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
<EdgeSize><AbsValue val="16"/></EdgeSize>
<TileSize><AbsValue val="16"/></TileSize>
<BackgroundInsets><AbsInset left="5" right="5" top="5" bottom="5"/></BackgroundInsets>
</Backdrop>
<Layers>
<Layer level="BACKGROUND">
<!-- DELIBERATE deviation (director's call): the real plate is UI-Tooltip-Background's
baked 187/255 alpha (~73% opaque — measured from the BLP; the tint can only
lower it) and read too see-through here. This solid fill in the same navy,
inset to the backdrop's 5px background insets, thickens the plate to ~84%
against the world. The `a` is the knob; delete the region for the raw quote. -->
<Texture name="$parentThicken">
<Anchors>
<Anchor point="TOPLEFT"><Offset><AbsDimension x="5" y="-5"/></Offset></Anchor>
<Anchor point="BOTTOMRIGHT"><Offset><AbsDimension x="-5" y="5"/></Offset></Anchor>
</Anchors>
<Color r="0.09" g="0.09" b="0.19" a="0.4"/>
</Texture>
</Layer>
<Layer level="ARTWORK">
<!-- **The 30 pre-declared line pairs, exactly as ref-GameTooltipTemplate.xml l.17-627.**
They exist so `GameTooltipTextLeft1` is a REAL GLOBAL FROM LOAD, hidden, before any
line has been added. Ours were engine-created purely on demand, so cold they were
nil — and the corpus pattern that breaks on is a GUARD, not a read:
`Participant/Resurrection.lua:294` and `CT_RaidAssist/CT_RADetectSpells.lua:47` both
say `GameTooltipTextLeft1:IsVisible()` to ask whether the tooltip is showing
anything. On the reference that is safe and answers false; for us it raised on the
check itself. 7 corpus addons index the name (decision 1220).
The engine ADOPTS these (`script::tooltip::ensure_lines` — the same path
ShoppingTooltipTemplate's ladder already uses): their faces ride, the engine owns
justify, visibility and anchors, so no anchors are declared here. Faces match what
`ensure_lines` picks for a created line — header for pair 1, GameTooltipText after —
which is why this changes nothing on screen. `NumLines()` is `num_lines`, not the
pool size, and `layout_tooltips` sizes from `num_lines`, so a declared-but-unfilled
pair adds no height and no width. -->
<FontString name="$parentTextLeft1" inherits="GameTooltipHeaderText" hidden="true"/>
<FontString name="$parentTextRight1" inherits="GameTooltipHeaderText" hidden="true"/>
<FontString name="$parentTextLeft2" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight2" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft3" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight3" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft4" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight4" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft5" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight5" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft6" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight6" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft7" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight7" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft8" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight8" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft9" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight9" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft10" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight10" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft11" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight11" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft12" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight12" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft13" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight13" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft14" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight14" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft15" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight15" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft16" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight16" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft17" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight17" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft18" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight18" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft19" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight19" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft20" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight20" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft21" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight21" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft22" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight22" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft23" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight23" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft24" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight24" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft25" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight25" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft26" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight26" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft27" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight27" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft28" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight28" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft29" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight29" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextLeft30" inherits="GameTooltipText" hidden="true"/>
<FontString name="$parentTextRight30" inherits="GameTooltipText" hidden="true"/>
</Layer>
</Layers>
<Frames>
<!-- The mouseover health bar (ref-GameTooltipTemplate.xml l.575-597, quoted): 8px
tall, hanging below the plate, UI-TargetingFrame-BarFill, colored by
HealthBar_OnValueChanged. The ENGINE drives min/max/value from the live unit
snapshot (the byte law's HEALTH watcher — SetUnit + every set_unit push), finding
it by the `<name>StatusBar` global — so it has to be the TEMPLATE's, not one
instance's: TipBuddy replaces the whole unit tooltip and both `parent=` and
`relativeTo=` a `TipBuddyTooltipStatusBar` it never declares
(TipBuddy.xml l.2320, l.2591) — a name only this element can publish. -->
<StatusBar name="$parentStatusBar" hidden="true">
<Size><AbsDimension x="0" y="8"/></Size>
<Anchors>
<Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="2" y="-1"/></Offset></Anchor>
<Anchor point="TOPRIGHT" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="-2" y="-1"/></Offset></Anchor>
</Anchors>
<Scripts>
<OnValueChanged>HealthBar_OnValueChanged(arg1)</OnValueChanged>
</Scripts>
<BarTexture name="$parentTexture" file="Interface\TargetingFrame\UI-TargetingFrame-BarFill"/>
</StatusBar>
</Frames>
<Scripts>
<!-- ref-GameTooltipTemplate.xml l.611-616. An instance that needs more re-declares the
handler and calls the same helper first (the reference's own shape, and ours:
GameTooltip adds its event registration, ItemRefTooltip its padding) — the loader
walks every <Scripts> block in splice order, so the instance's SetScript lands
last and wins. -->
<OnLoad>GameTooltip_OnLoad(self)</OnLoad>
<OnHide>GameTooltip_OnHide(this)</OnHide>
</Scripts>
</GameTooltip>
<GameTooltip name="GameTooltip" inherits="GameTooltipTemplate" frameStrata="TOOLTIP" hidden="true">
<!-- A default size so the plate resolves the first frame it is shown; the engine's
auto-size pass takes over once the lines are measured (one frame's latency). NO
load-time anchor (the ref instance carries none): every show path seats the plate
first - SetOwner's anchor law for owned hovers, OnTooltipSetDefaultAnchor for world
hovers - and a leftover static anchor is exactly what parked the world tooltip at
screen center when the default-anchor script wasn't wired. -->
<Size><AbsDimension x="120" y="32"/></Size>
<Frames>
<!-- The money row's coin trio (the real $parentMoneyFrame — GameTooltipTemplate.xml,
patch.MPQ — as our shared coin-slot shape; MerchantFrame.xml's BenillaMoney_Set
fills them, left-to-right gold-first). Coin1 is re-anchored by SetTooltipMoney to
the money line's LEFT +4 (ref SetTooltipMoney's seat). -->
<Frame name="$parentMoneyCoin1" hidden="true">
<Size><AbsDimension x="13" y="13"/></Size>
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"/></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>
<TexCoords left="0.5" right="0.75" top="0" bottom="1"/>
</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="$parentMoneyCoin2" hidden="true">
<Size><AbsDimension x="13" y="13"/></Size>
<Anchors>
<Anchor point="LEFT" relativeTo="$parentMoneyCoin1" 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>
<TexCoords left="0.25" right="0.5" top="0" bottom="1"/>
</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="$parentMoneyCoin3" hidden="true">
<Size><AbsDimension x="13" y="13"/></Size>
<Anchors>
<Anchor point="LEFT" relativeTo="$parentMoneyCoin2" 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>
<TexCoords left="0" right="0.25" top="0" bottom="1"/>
</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>
<Scripts>
<OnLoad>
GameTooltip_OnLoad(self)
self:RegisterEvent("UPDATE_MOUSEOVER_UNIT")
</OnLoad>
<!-- The engine renders the mouseover unit's lines gold and fires this; the recolor by
reaction is FrameXML's half (ref-GameTooltip.xml l.12-16, quoted). -->
<OnEvent>
if event == "UPDATE_MOUSEOVER_UNIT" then
getglobal(this:GetName() .. "TextLeft1"):SetTextColor(GameTooltip_UnitColor("mouseover"))
end
</OnEvent>
<!-- The default corner for world hovers (ref-GameTooltipTemplate.xml l.617-619,
quoted): the engine fires this before rendering a mouseover unit/object, and
the handler seats the plate at the screen's bottom-right. THE wiring whose
absence parked the world tooltip on the character. -->
<OnTooltipSetDefaultAnchor>GameTooltip_SetDefaultAnchor(this, UIParent)</OnTooltipSetDefaultAnchor>
<!-- ref GameTooltip.xml OnHide (l.18-22, quoted): the color reset + the compare pair
drops with its anchor host. -->
<OnHide>
GameTooltip_OnHide(this)
ShoppingTooltip1:Hide()
ShoppingTooltip2:Hide()
</OnHide>
<!-- The engine-fired money protocol (ref-GameTooltipTemplate.xml l.620-625): the engine
computes a price and fires OnTooltipAddMoney(arg1 = copper); OnTooltipCleared fires
whenever the content clears (ClearLines/SetOwner/Hide) and drops the coin row. -->
<OnTooltipAddMoney>SetTooltipMoney(this, arg1)</OnTooltipAddMoney>
<OnTooltipCleared>GameTooltip_ClearMoney(this)</OnTooltipCleared>
</Scripts>
</GameTooltip>
<!--
ShoppingTooltipTemplate (ref-GameTooltipTemplate.xml l.628-1217) — the shopping-compare
pair's own template, a SEPARATE virtual from GameTooltipTemplate exactly as the reference
has it (its instances, ref-GameTooltip.xml l.24-25, inherit this and not the main one).
It repeats the plate rather than inheriting it because the reference's does, and because
inheriting GameTooltipTemplate would hand the compare plates its OnHide, its status bar and
(later) its money row — none of which the compare cut has.
The declared TextLeft/Right1-4 pairs are this template's own small-font ladder, faces
quoted verbatim (including its odd GameFontNormal cells) — the engine ADOPTS declared pairs
and clones the last pair's faces for lines it grows past them (tooltip.rs ensure_lines).
Same plate as the main tooltip, including the Thicken deviation (its rationale is on
GameTooltipTemplate above); no coin trio — the compare cut ends before money.
No addon in the corpus names this template (0 of 218, against GameTooltipTemplate's 27), so
it earns its keep as OUR de-duplication, not as an addon surface: the two instances below
were byte-identical apart from the name.
-->
<GameTooltip name="ShoppingTooltipTemplate" frameStrata="TOOLTIP" hidden="true" virtual="true">
<Size><AbsDimension x="120" y="32"/></Size>
<Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
<EdgeSize><AbsValue val="16"/></EdgeSize>
<TileSize><AbsValue val="16"/></TileSize>
<BackgroundInsets><AbsInset left="5" right="5" top="5" bottom="5"/></BackgroundInsets>
</Backdrop>
<Layers>
<Layer level="BACKGROUND">
<Texture name="$parentThicken">
<Anchors>
<Anchor point="TOPLEFT"><Offset><AbsDimension x="5" y="-5"/></Offset></Anchor>
<Anchor point="BOTTOMRIGHT"><Offset><AbsDimension x="-5" y="5"/></Offset></Anchor>
</Anchors>
<Color r="0.09" g="0.09" b="0.19" a="0.4"/>
</Texture>
</Layer>
<Layer level="ARTWORK">
<FontString name="$parentTextLeft1" inherits="GameFontNormalSmall" hidden="true"/>
<FontString name="$parentTextRight1" inherits="GameFontNormal" hidden="true"/>
<FontString name="$parentTextLeft2" inherits="GameFontNormal" hidden="true"/>
<FontString name="$parentTextRight2" inherits="GameFontHighlightSmall" hidden="true"/>
<FontString name="$parentTextLeft3" inherits="GameFontHighlightSmall" hidden="true"/>
<FontString name="$parentTextRight3" inherits="GameFontHighlightSmall" hidden="true"/>
<FontString name="$parentTextLeft4" inherits="GameTooltipTextSmall" hidden="true"/>
<FontString name="$parentTextRight4" inherits="GameFontHighlightSmall" hidden="true"/>
</Layer>
</Layers>
<Scripts>
<OnLoad>GameTooltip_OnLoad(self)</OnLoad>
</Scripts>
</GameTooltip>
<!-- The shopping-compare pair (ref GameTooltip.xml l.24-25, quoted down to the one-line shape):
two more GameTooltip widgets the engine seats on the paperdoll slot when
SHOW_COMPARE_TOOLTIP fires (CharacterFrame.xml's listener). -->
<GameTooltip name="ShoppingTooltip1" inherits="ShoppingTooltipTemplate" frameStrata="TOOLTIP" hidden="true"/>
<GameTooltip name="ShoppingTooltip2" inherits="ShoppingTooltipTemplate" frameStrata="TOOLTIP" hidden="true"/>
</Ui>