- The main menu bar's two empty recesses fill. The micro menu — the eight arched buttons: character, spellbook, talents, quest log, socials, world map, main menu, help — sits in the dark panel between the page arrows and the bags, transcribed from the reference's own layout: the character button wears your portrait, a button holds itself down while its panel is up, and the talent button appears at level 10. The latency meter fills the one slot the bar art leaves transparent for exactly it, tinted green/yellow/red on the reference's 300/600 ms thresholds and drawn UNDER the bar art, seen through its window, the way 1.12 actually does it. The socials and main-menu buttons find their panels one snapshot later; help still waits. - The UI explains itself on hover: 1.12 ships its detailed two-line tooltips ON — a FrameXML default, not the opt-in extra it is often remembered as — so the micro buttons, your own portrait, the XP bar, the five bag buttons and the ping meter all answer a hover with the reference's own explanations. - The PvP flag, end to end: crossed swords on the player, target and party frames, driven by the two descriptor bits the wire actually carries, and `/pvp` speaks — the yellow toast plus the system chat line, the OFF sentence being the one that warns the flag lingers for five minutes. It really does linger: turning it off waits out the server's timer, which looks like a bug and is the reference. - Quest markers stopped freezing. The grey `!` over a questgiver above your level goes gold the moment you ding, an NPC re-entering view is asked afresh instead of wearing a session-old answer, and the marker drops when the questgiver bit goes off — the re-ask triggers mirror the reference's own set, plus one named addition (your own level changing). - Water and heights: swimming downhill no longer bounces between swim and fall ten times a second — the surface line is a two-sided constraint, so the swimmer settles with the river instead of being left behind by it. And collision height is per-unit now, read from the unit's own model: a gnome used to swim with a third of a yard of water over her head because five depth lines were quoting a human's number. - A round of pixel honesty in text and chat: the newest chat line no longer wears a wider drop shadow than every line above it (shadows move in whole pixels now), keeps its descenders, and hover boxes stop painting over the chat body. The chat input's history browse survives programmatic edits, a failed script chunk warns instead of vanishing, and recall deepens to 64 lines. Idle animation got honest too: a model's idle is Stand resolved through its own lookup table — never file order, which had the duel flag bobbing on its spawn clip — and an armed idle is culled on the box its animation authors, not the bind pose, so the flag stops vanishing at most camera angles. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1805 lines
123 KiB
XML
1805 lines
123 KiB
XML
<Ui>
|
||
<!--
|
||
benilla's character window (decision 0208, phase 1a display + phase 1b equip interactions
|
||
— the C-key window, paper doll first):
|
||
the round player portrait + name + level line + close button + the five-tab row, dressed
|
||
from the real 1.12 `CharacterFrame.xml`/`.lua` + `PaperDollFrame.xml`/`.lua` +
|
||
`CharacterFrameTemplates.xml` + the `Model_*` rotate helpers (`UIParent.lua:1421-1462`) —
|
||
extracted from the MPQ chain to session scratch this session (director-local reference
|
||
artifacts, never committed — the 0068/0138 pattern; line cites below are into that
|
||
extraction's own `ref-CharacterFrame.xml`/`.lua`, `ref-PaperDollFrame.xml`/`.lua`,
|
||
`ref-UIParent.lua`, `ref-GlobalStrings.lua`). `CharacterFrameTabButtonTemplate` is ALREADY
|
||
transcribed in `UiPanels.xml:507-563` (battle-tested by Merchant/QuestLog, 0138) — reused
|
||
here, not redefined.
|
||
|
||
Docks the left UIPanel slot exactly like Gossip/Merchant/Quest/QuestLog (`UiPanels.xml`
|
||
`UIPanelWindows["BenillaCharacterFrame"] = { area = "left", pushable = 0 }`, mirroring the
|
||
ref's own `CharacterFrame` row, `UIParent.lua` pin cited in `UiPanels.xml`'s header) — so it
|
||
competes for/replaces those windows, never stacks with them. `ToggleCharacter(tab)` (ref
|
||
`CharacterFrame.lua:3-23`, kept BARE — not Benilla-prefixed — matching this codebase's own
|
||
`ToggleQuestLog()` precedent: the addon-facing entry point keeps the real global name even
|
||
though the frames it drives are Benilla-prefixed) is the show/hide/tab-switch entry point;
|
||
the app's 'C' binding calls it (`ui_script/mod.rs`).
|
||
|
||
ONE deliberate naming deviation from the ref, applied consistently: every frame this file
|
||
defines is Benilla-prefixed (`BenillaCharacterFrame`, `BenillaPaperDollFrame`, …) — including
|
||
the string `ToggleCharacter`/`CharacterFrame_ShowSubFrame` pass around internally
|
||
(`BENILLA_CHARACTERFRAME_SUBFRAMES` lists `"BenillaPaperDollFrame"`, not the ref's bare
|
||
`"PaperDollFrame"`) — matching the same-prefix convention every other window in this codebase
|
||
already follows (Merchant/Bag/QuestLog never leave a sub-piece unprefixed).
|
||
|
||
Phase 1a shipped the window, display-only. Phase 1b (THIS pass) adds the equip
|
||
interactions over the SAME display — `PickupInventoryItem`/`UseInventoryItem`/
|
||
`AutoEquipCursorItem`/`CursorCanGoInSlot`/`IsInventoryItemLocked`, joining the paper doll
|
||
onto the ONE cursor-payload space via its sentinel `EQUIPMENT_BAG` bag id (decision 0216
|
||
§1, extended by decision 0208's own phasing, §"Phasing"/"1a"/"1b", and 0216/0218's
|
||
cursor-arc design). Tabs 2-5 (Pet/Reputation/Skills/Honor) are still OMITTED, the 0138
|
||
merchant-tab precedent ("tabs arrive with their pages") — `BENILLA_CHARACTERFRAME_SUBFRAMES`
|
||
only lists the one page that exists.
|
||
|
||
Named deferrals/OMITs (each re-cited at its own site below):
|
||
- Guild line (`CharacterGuildText`) and the PVP rank name (`UnitPVPName` — plain `UnitName`
|
||
ships instead): both decision 0208's own named deferrals (guild needs `CMSG_GUILD_QUERY`;
|
||
rank needs the honor arc). `CharacterTitleText` (also PVP-rank-driven) is dropped with it.
|
||
- Shift-click chat-link insert and ctrl-click `DressUpItemLink` (the dressing room): both
|
||
named deferrals this phase too — the left-click fork recognizes the modifiers and does
|
||
nothing, rather than silently falling through to a pickup a real shift/ctrl-click
|
||
would never have triggered.
|
||
- The ammo slot (id 0) LOADS ammo by entry (`CMSG_SET_AMMO`) — it does NOT swap into an
|
||
equip slot (decision 0526; wow-re `cursor-dragdrop-slots.md`: the client's auto-equip
|
||
sender forks ammo-class → SET_AMMO). So it can't share the 19 named slots'
|
||
`PickupInventoryItem` path — its click/drop route to `BenillaCharacterAmmoSlot_OnClick`
|
||
→ `AutoEquipCursorItem` (the app's autoequip drain resolves the held entry and forks to
|
||
SET_AMMO), gated by `CursorCanGoInSlot(0)` so only an ammo payload fits. It carries no
|
||
ring, so the `CURSOR_UPDATE` highlight / `ITEM_LOCK` dim legs no-op, and there is no
|
||
drag-OUT of loaded ammo; it keeps sharing `BenillaPaperDollSlot_OnLoad`/`_Update`/
|
||
`_OnEvent` for its DISPLAY. (The four equipped-bag icons, ids 20-23, joined the
|
||
`EQUIPMENT_BAG` payload space in decision 0216/0218 — no longer out of the drag space.)
|
||
- Cooldowns (`GetInventoryItemCooldown`/`CooldownFrameTemplate`), the broken-red tint
|
||
(`GetInventoryItemBroken`), and the shift-compare tooltip (`SHOW_COMPARE_TOOLTIP`):
|
||
none of their backing feeds/engine affordances exist yet — the item stats feed has no
|
||
durability/cooldown channel (the same named gap as 0138's damaged-sell-price).
|
||
- The `CURSOR_UPDATE` slot highlight is an EMULATION, not the reference's true
|
||
`LockHighlight`/`UnlockHighlight` (grepped `benilla-ui/src/script/button.rs` this
|
||
session — no such Button methods exist; a Button's highlight texture only ever shows
|
||
on REAL mouse hover, `ButtonState::region_visible`'s hardwired `enabled && hovered`, no
|
||
forced-show path). A real forced-highlight affordance is a `benilla-ui` follow-up, not
|
||
blocking this slice — `BenillaPaperDollSlot_LockHighlight`/`_UnlockHighlight` below
|
||
tint the slot's Quickslot2 ring instead, flagged at their own definition.
|
||
- The relic slot: `UnitHasRelicSlot` is vanilla-always-false (there is no relic slot in
|
||
1.12), so the ref's `CharacterAmmoSlot:Hide()`/relic-texture branches are DEAD CODE even
|
||
in the real client — omitted outright rather than transcribing unreachable branches; the
|
||
ammo slot always shows.
|
||
- Class-specific stat-tooltip flavor text (`WARRIOR_STRENGTH_TOOLTIP` and its ~20 siblings):
|
||
only the 5 `DEFAULT_*_TOOLTIP` fallbacks ship. `BenillaPaperDollStatTooltip` still looks
|
||
the class-specific global up FIRST exactly like the ref, so dropping in the per-class
|
||
table later is pure string data, no logic change — the numeric stat lines (the
|
||
load-bearing content) are complete either way.
|
||
- The model pane ships as a booth-texture stand-in, not a live `<Model>`/`<PlayerModel>`
|
||
widget (decision 0208 §5): our engine's `FrameKind::Model` parses but has no
|
||
`SetUnit`/`RefreshUnit` surface (verified this session — grepped `benilla-ui/src/script`),
|
||
so `CharacterModelFrame` materializes here as a plain `<Frame>` sampling the paper-doll
|
||
booth bake via `BenillaSetBoothTexture(region, "paperdoll")` (the `SetPortraitTexture`
|
||
plumbing's sibling, per this session's parallel-build contract) — `DISPLAY_SIZE_CHANGED`/
|
||
`RefreshUnit` don't apply and are dropped. `OnMouseUp`-to-equip DOES apply, though (1b):
|
||
it needs no live 3D — just `EnableMouse(true)` + the two script hooks, added below. The
|
||
held-button continuous spin (`Model_OnUpdate`, ref `UIParent.lua:1444-1462`) needs
|
||
`GetButtonState()=="PUSHED"` — grepped, no such method exists on our `Button` — so this
|
||
ships CLICK-ONLY (±0.03 rad/click); the held-spin is a follow-up once/if `GetButtonState`
|
||
lands.
|
||
- The ammo slot's data path (verified this session, not the speculative framing in decision
|
||
0208 §4): the ref's `CharacterAmmoSlot` is NOT driven by a separate `PLAYER_AMMO_ID`
|
||
Lua global — it shares the exact same `PaperDollItemSlotButton_OnLoad`/`_Update` functions
|
||
the 19 named slots use (ref `ref-PaperDollFrame.xml:999-1028`, byte-identical to the
|
||
shared template's own Scripts block at l.8-37), just keyed off `GetInventorySlotInfo(
|
||
"AmmoSlot")` instead of e.g. `"HeadSlot"`. Whatever `PLAYER_AMMO_ID`/bag-summing happens
|
||
for that particular slot id is the parallel binding's own implementation detail, invisible
|
||
to this Lua — transcribed here exactly as the ref wires it.
|
||
- `$parentStock` (the ammo slot's yellow "in bags" count, ref `ref-PaperDollFrame.xml:
|
||
970-978`): no Lua in this session's extraction ever populates it (likely an ammo-picker-
|
||
addon-only overlay outside this pull) — dropped rather than guessed at.
|
||
|
||
Engine-gap notes (transcribed anyway per this file's own instructions, or worked around) —
|
||
the first two are CLOSED, kept only because the workarounds below still read as if they held:
|
||
- `HitRectInsets` (both `BenillaCharacterFrame` and `BenillaPaperDollFrame`, ref's identical
|
||
0/30/0/45 on both) was a loader no-op when this file was written; it landed with the
|
||
micro menu (decision 0655) and now really insets the mouse rect.
|
||
- `enableMouse`/`setAllPoints` (frame-level) were no-ops on `<Frame>` too; both are wired
|
||
now (`loader/geometry.rs`'s `apply_attrs`/`apply_anchors`, and
|
||
`loader/tests.rs::frame_set_all_points_pins_to_parent`). `BenillaPaperDollFrame` still
|
||
carries an explicit `Size`+`TOPLEFT` anchor rather than the ref's `setAllPoints="true"`
|
||
— exactly equivalent for a child sized to fill its parent, so it is left alone rather
|
||
than churned.
|
||
- A plain `<Frame>` isn't mouse-enabled by construction in this engine (only Button/
|
||
CheckButton/EditBox/ScrollingMessageFrame are — `widget/mod.rs`'s ctor comment, already
|
||
the reason `UnitFrames.xml` calls `EnableMouse(true)` on its own root frame) — every
|
||
hover-tooltip `<Frame>` below (the 5 attribute rows, armor/attack/damage/ranged rows, the
|
||
5 resistance frames — none of them Buttons) gets its own `self:EnableMouse(true)` in
|
||
`OnLoad` for this reason; the 19 item slots are Buttons and need no such call.
|
||
- `TEXT(x)` (the ref's localization-tooling identity macro) has no engine equivalent and
|
||
needs none — it's a build-time no-op wrapper in the real client, so every `TEXT(FOO)` call
|
||
below is transcribed as the bare `FOO` global.
|
||
- The font color codes (`HIGHLIGHT_FONT_COLOR_CODE`/`GREEN_FONT_COLOR_CODE`/
|
||
`RED_FONT_COLOR_CODE`/`FONT_COLOR_CODE_CLOSE`, `NORMAL_FONT_COLOR`/`HIGHLIGHT_FONT_COLOR`)
|
||
are defined by the real `Fonts.xml`'s own <Script> block (ref l.8-19 — extracted and
|
||
verified this session), so ours live in our `Fonts.xml` (loaded first), not here.
|
||
|
||
Sounds (decision 0090): `igCharacterInfoOpen`/`Close` on Show/Hide (ref `CharacterFrame.lua:
|
||
83/96`), `igCharacterInfoTab` on the tab click (ref `CharacterFrameTab_OnClick`, l.47),
|
||
`igInventoryRotateCharacter` on each rotate click (ref `UIParent.lua:1432/1441`).
|
||
-->
|
||
<Script><![CDATA[
|
||
-- ── GlobalStrings values this window uses (ref-GlobalStrings.lua, cited per line — the
|
||
-- `X = X or "..."` idiom matches CastingBar.xml's own convention: a real GlobalStrings.lua,
|
||
-- if one ever loads, wins over this fallback) ──────────────────────────────────────────────
|
||
CHARACTER = CHARACTER or "Character" -- :481
|
||
SKILLS = SKILLS or "Skills" -- :3477 (decision 0437 phase 4, the Skills tab label)
|
||
PLAYER_LEVEL = PLAYER_LEVEL or "Level %d %s %s" -- :3075
|
||
ARMOR = ARMOR or "Armor" -- :62
|
||
ARMOR_COLON = ARMOR_COLON or "Armor:" -- :63
|
||
ARMOR_TOOLTIP = ARMOR_TOOLTIP or
|
||
"Decreases the amount of damage taken from physical attacks. The amount of reduction is influenced by the level of the attacker.\nDamage reduction against a level %d attacker: %.1f%%" -- :65
|
||
ATTACK_POWER_COLON = ATTACK_POWER_COLON or "Power:" -- :71
|
||
ATTACK_SPEED_COLON = ATTACK_SPEED_COLON or "Attack Speed (seconds):" -- :73
|
||
ATTACK_TOOLTIP = ATTACK_TOOLTIP or "Attack Rating" -- :75
|
||
ATTACK_TOOLTIP_SUBTEXT = ATTACK_TOOLTIP_SUBTEXT or
|
||
"Your attack rating affects your chance to hit a target, and is based on the weapon skill of the weapon you are currently wielding." -- :76
|
||
DAMAGE_COLON = DAMAGE_COLON or "Damage:" -- :888
|
||
DAMAGE_PER_SECOND = DAMAGE_PER_SECOND or "Damage per Second:" -- :889
|
||
DPS_TEMPLATE = DPS_TEMPLATE or "(%.1f damage per second)" -- :942
|
||
MELEE_ATTACK = MELEE_ATTACK or "Melee Attack" -- :2680
|
||
MELEE_ATTACK_POWER = MELEE_ATTACK_POWER or "Melee Attack Power" -- :2681
|
||
MELEE_ATTACK_POWER_TOOLTIP = MELEE_ATTACK_POWER_TOOLTIP or
|
||
"Increases damage with melee weapons by %.1f damage per second." -- :2682
|
||
NOT_APPLICABLE = NOT_APPLICABLE or "N/A" -- :2802
|
||
RANGED_ATTACK = RANGED_ATTACK or "Ranged Attack" -- :3292
|
||
RANGED_ATTACK_POWER = RANGED_ATTACK_POWER or "Ranged Attack Power" -- :3293
|
||
RANGED_ATTACK_POWER_TOOLTIP = RANGED_ATTACK_POWER_TOOLTIP or
|
||
"Increases damage with ranged weapons by %.1f damage per second." -- :3294
|
||
RANGED_ATTACK_TOOLTIP = RANGED_ATTACK_TOOLTIP or "Ranged Attack Rating" -- :3295
|
||
INVTYPE_WEAPONMAINHAND = INVTYPE_WEAPONMAINHAND or "Main Hand" -- :2375
|
||
INVTYPE_WEAPONOFFHAND = INVTYPE_WEAPONOFFHAND or "Off Hand" -- :2376
|
||
INVTYPE_RANGED = INVTYPE_RANGED or "Ranged" -- :2366
|
||
|
||
SPELL_STAT0_NAME = SPELL_STAT0_NAME or "Strength" -- :4118
|
||
SPELL_STAT1_NAME = SPELL_STAT1_NAME or "Agility" -- :4119
|
||
SPELL_STAT2_NAME = SPELL_STAT2_NAME or "Stamina" -- :4120
|
||
SPELL_STAT3_NAME = SPELL_STAT3_NAME or "Intellect" -- :4121
|
||
SPELL_STAT4_NAME = SPELL_STAT4_NAME or "Spirit" -- :4122
|
||
|
||
RESISTANCE1_NAME = RESISTANCE1_NAME or "Holy Resistance" -- :3347 (unused: Holy never rides the paper doll)
|
||
RESISTANCE2_NAME = RESISTANCE2_NAME or "Fire Resistance" -- :3348
|
||
RESISTANCE3_NAME = RESISTANCE3_NAME or "Nature Resistance" -- :3349
|
||
RESISTANCE4_NAME = RESISTANCE4_NAME or "Frost Resistance" -- :3350
|
||
RESISTANCE5_NAME = RESISTANCE5_NAME or "Shadow Resistance" -- :3351
|
||
RESISTANCE6_NAME = RESISTANCE6_NAME or "Arcane Resistance" -- :3352
|
||
RESISTANCE_TYPE1 = RESISTANCE_TYPE1 or "holy" -- :3362
|
||
RESISTANCE_TYPE2 = RESISTANCE_TYPE2 or "fire" -- :3363
|
||
RESISTANCE_TYPE3 = RESISTANCE_TYPE3 or "nature" -- :3364
|
||
RESISTANCE_TYPE4 = RESISTANCE_TYPE4 or "frost" -- :3365
|
||
RESISTANCE_TYPE5 = RESISTANCE_TYPE5 or "shadow" -- :3366
|
||
RESISTANCE_TYPE6 = RESISTANCE_TYPE6 or "arcane" -- :3367
|
||
RESISTANCE_EXCELLENT = RESISTANCE_EXCELLENT or "Excellent" -- :3353
|
||
RESISTANCE_VERYGOOD = RESISTANCE_VERYGOOD or "Very Good" -- :3368
|
||
RESISTANCE_GOOD = RESISTANCE_GOOD or "Good" -- :3355
|
||
RESISTANCE_FAIR = RESISTANCE_FAIR or "Fair" -- :3354
|
||
RESISTANCE_POOR = RESISTANCE_POOR or "Poor" -- :3358
|
||
RESISTANCE_NONE = RESISTANCE_NONE or "None" -- :3357
|
||
RESISTANCE_TOOLTIP_SUBTEXT = RESISTANCE_TOOLTIP_SUBTEXT or
|
||
"Increases the ability to resist %s-based attacks, spells and abilities.\nResistance against level %d: |cffffffff%s|r" -- :3360
|
||
|
||
-- Default (class-agnostic) stat tooltips only — see this file's header comment on the
|
||
-- class-specific (WARRIOR_STRENGTH_TOOLTIP, …) omission.
|
||
DEFAULT_STRENGTH_TOOLTIP = DEFAULT_STRENGTH_TOOLTIP or "Increases attack power with melee weapons." -- :916
|
||
DEFAULT_AGILITY_TOOLTIP = DEFAULT_AGILITY_TOOLTIP or
|
||
"Increases attack power with ranged weapons.\nImproves chance to score a critical hit with all weapons.\nIncreases armor and chance to dodge attacks." -- :911
|
||
DEFAULT_STAMINA_TOOLTIP = DEFAULT_STAMINA_TOOLTIP or "Increases health points." -- :915
|
||
DEFAULT_INTELLECT_TOOLTIP = DEFAULT_INTELLECT_TOOLTIP or "Increases the rate at which weapon skills improve." -- :913
|
||
DEFAULT_SPIRIT_TOOLTIP = DEFAULT_SPIRIT_TOOLTIP or "Increases health and mana regeneration rates." -- :914
|
||
|
||
HEADSLOT = HEADSLOT or "Head" -- :2123
|
||
NECKSLOT = NECKSLOT or "Neck" -- :2713
|
||
SHOULDERSLOT = SHOULDERSLOT or "Shoulders" -- :3428
|
||
BACKSLOT = BACKSLOT or "Back" -- :133
|
||
CHESTSLOT = CHESTSLOT or "Chest" -- :746
|
||
SHIRTSLOT = SHIRTSLOT or "Shirt" -- :3427
|
||
TABARDSLOT = TABARDSLOT or "Tabard" -- :4217
|
||
WRISTSLOT = WRISTSLOT or "Wrist" -- :5458
|
||
HANDSSLOT = HANDSSLOT or "Hands" -- :2115
|
||
WAISTSLOT = WAISTSLOT or "Waist" -- :5428
|
||
LEGSSLOT = LEGSSLOT or "Legs" -- :2565
|
||
FEETSLOT = FEETSLOT or "Feet" -- :1967
|
||
FINGER0SLOT = FINGER0SLOT or "Finger" -- :1971
|
||
FINGER1SLOT = FINGER1SLOT or "Finger" -- :1972
|
||
TRINKET0SLOT = TRINKET0SLOT or "Trinket" -- :4313
|
||
TRINKET1SLOT = TRINKET1SLOT or "Trinket" -- :4314
|
||
MAINHANDSLOT = MAINHANDSLOT or "Main Hand" -- :2658
|
||
SECONDARYHANDSLOT = SECONDARYHANDSLOT or "Off Hand" -- :3400
|
||
RANGEDSLOT = RANGEDSLOT or "Ranged" -- :3291
|
||
AMMOSLOT = AMMOSLOT or "Ammo" -- :53
|
||
|
||
-- The font color codes/tables live in our Fonts.xml (the ref's own home for them, l.8-19 —
|
||
-- verified this session), loaded before every window.
|
||
|
||
-- ── This window's own constants (ref-PaperDollFrame.lua:1-4, Benilla-prefixed) ────────────
|
||
BENILLA_NUM_STATS = 5 -- NUM_STATS
|
||
BENILLA_NUM_RESISTANCE_TYPES = 5 -- NUM_RESISTANCE_TYPES
|
||
BENILLA_ATTACK_POWER_MAGIC_NUMBER = 14 -- ATTACK_POWER_MAGIC_NUMBER
|
||
-- MagicResFrame1..5's ref `id=` attrs (ref-PaperDollFrame.xml:654-759) — arcane/fire/nature/
|
||
-- frost/shadow; Holy(1) never rides the paper doll (only 5 of the 6 schools show here).
|
||
BENILLA_MAGICRES_IDS = { 6, 2, 3, 4, 5 }
|
||
-- The pages that exist so far (this file's header comment; the 0138 merchant-tab
|
||
-- precedent — tabs arrive with their pages). Benilla-prefixed, unlike the ref's bare
|
||
-- "PaperDollFrame"/"SkillFrame". 1:1 with the tab row below (index N is tab N's page) —
|
||
-- decision 0437 phase 4 adds "BenillaSkillFrame" as tab 2; Pet/Reputation/Honor (the
|
||
-- real client's tabs 2/3/5) are still OMITTED.
|
||
BENILLA_CHARACTERFRAME_SUBFRAMES = { "BenillaPaperDollFrame", "BenillaSkillFrame" }
|
||
|
||
-- ── The window: toggle / tab dispatch (ref CharacterFrame.lua:1-48) ─────────────────────
|
||
-- Kept BARE (not Benilla-prefixed) — the addon-facing entry point, matching this codebase's
|
||
-- own ToggleQuestLog() precedent (QuestLogFrame.xml).
|
||
function CharacterFrame_ShowSubFrame(frameName)
|
||
for _, value in ipairs(BENILLA_CHARACTERFRAME_SUBFRAMES) do
|
||
-- Nil-guarded: a page's file may not be loaded (a test subset, a later
|
||
-- load-on-demand page) — a missing sibling must never break the switch.
|
||
local page = getglobal(value)
|
||
if page then
|
||
if value == frameName then page:Show() else page:Hide() end
|
||
end
|
||
end
|
||
end
|
||
|
||
function ToggleCharacter(tab)
|
||
local subFrame = getglobal(tab)
|
||
if not subFrame then return end
|
||
local frame = getglobal("BenillaCharacterFrame")
|
||
if frame:IsVisible() then
|
||
if subFrame:IsVisible() then
|
||
HideUIPanel(frame)
|
||
else
|
||
PlaySound("igCharacterInfoTab")
|
||
CharacterFrame_ShowSubFrame(tab)
|
||
end
|
||
else
|
||
ShowUIPanel(frame)
|
||
CharacterFrame_ShowSubFrame(tab)
|
||
end
|
||
end
|
||
|
||
-- The tab row's own OnClick (ref CharacterFrameTab_OnClick, l.35-48), now id-based (decision
|
||
-- 0437 phase 4 grows the row to 2) — the MerchantFrame.xml Merchant/Buyback pair's own shape
|
||
-- for a >1-tab window: `id` indexes BOTH the tab button and BENILLA_CHARACTERFRAME_SUBFRAMES
|
||
-- 1:1. PanelTemplates_SetTab visually selects the clicked tab (the ref's own
|
||
-- PanelTemplates_SetTab(this, subFrame:GetID()) call, dropped by the original phase-1a
|
||
-- single-tab comment above — restored now that a second tab exists to disagree with the
|
||
-- first). l.47's trailing PlaySound is the ref's OWN redundant second igCharacterInfoTab —
|
||
-- ToggleCharacter already plays it on the "switch to this tab" path, so this second call only
|
||
-- matters when the window is ALREADY open on this same tab, i.e. the HideUIPanel branch —
|
||
-- transcribed verbatim rather than "fixed" since it's the ref's own behavior, not a bug of ours.
|
||
function BenillaCharacterFrameTab_OnClick(id)
|
||
PanelTemplates_SetTab(getglobal("BenillaCharacterFrame"), id)
|
||
ToggleCharacter(BENILLA_CHARACTERFRAME_SUBFRAMES[id])
|
||
PlaySound("igCharacterInfoTab")
|
||
end
|
||
|
||
function BenillaCharacterFrame_OnLoad(frame)
|
||
-- GetID()/SetID() DO exist (landed with slice 2's BagFrame, which relies on them for
|
||
-- its own per-window bag id) — the STALE claim this comment used to make is corrected
|
||
-- here (0208 phase 1b touched this function anyway). 2 tabs ship as of decision 0437
|
||
-- phase 4 (Character + Skills); the window opens on tab 1 by default, matching the
|
||
-- real client.
|
||
PanelTemplates_SetNumTabs(frame, 2)
|
||
PanelTemplates_SetTab(frame, 1)
|
||
end
|
||
|
||
-- ref CharacterFrame_OnShow (l.82-93): Show*TextStatusBarText/ShowWatchedReputationBarText
|
||
-- OMITTED — no unit-frame bar-text-mode toggle or reputation-bar-text mechanism exists in
|
||
-- this engine. UpdateMicroButtons is LIVE as of the micro-menu slice (MicroMenu.xml); it was
|
||
-- omitted only for want of a micro bar. UnitPVPName -> plain UnitName (this file's header
|
||
-- comment: PVP rank is a named deferral).
|
||
function BenillaCharacterFrame_OnShow()
|
||
if UpdateMicroButtons then UpdateMicroButtons() end
|
||
PlaySound("igCharacterInfoOpen")
|
||
SetPortraitTexture(getglobal("BenillaCharacterFramePortrait"), "player")
|
||
getglobal("BenillaCharacterNameText"):SetText(UnitName("player"))
|
||
end
|
||
|
||
-- ref CharacterFrame_OnHide (l.95-104): everything past the PlaySound is the OnShow list's
|
||
-- Hide-twin — UpdateMicroButtons live (MicroMenu.xml), the bar-text pair still OMITTED for
|
||
-- the same reason as above. The subframe hide-loop is OUR OWN addition
|
||
-- (decision 0437 phase 4): BenillaPaperDollFrame is a true engine child of this frame (its
|
||
-- own header comment) so it hides for free on the parent's Hide-cascade, but
|
||
-- BenillaSkillFrame is a SEPARATE top-level file — this engine has no cross-file `parent=`
|
||
-- attachment (grepped `benilla-ui/src/loader`: the XML `parent=` attribute is read nowhere,
|
||
-- unlike `relativeTo`, which resolves by name regardless of tree position — see
|
||
-- SkillFrame.xml's own header comment) — so nothing else would hide it when the WHOLE
|
||
-- character window closes (ESC, the close X, or another left-slot window bumping it via
|
||
-- UIPanel exclusivity). Looping every BENILLA_CHARACTERFRAME_SUBFRAMES entry here, once,
|
||
-- keeps this correct as more non-nested tabs (Pet/Reputation/Honor) land the same way.
|
||
function BenillaCharacterFrame_OnHide()
|
||
if UpdateMicroButtons then UpdateMicroButtons() end
|
||
PlaySound("igCharacterInfoClose")
|
||
for _, name in ipairs(BENILLA_CHARACTERFRAME_SUBFRAMES) do
|
||
local subFrame = getglobal(name)
|
||
if subFrame then subFrame:Hide() end
|
||
end
|
||
end
|
||
|
||
-- ── The paper-doll page (ref PaperDollFrame.lua) ────────────────────────────────────────
|
||
-- ref PaperDollFrame_OnLoad (l.6-29), the label lines (l.7-13) transcribed verbatim: the
|
||
-- labels live ONLY in the row template's $parentLabel (gold GameFontNormalSmall, LEFT) and
|
||
-- Lua fills them — never a re-declared region in an instance (the ref's instances carry no
|
||
-- <Layers> at all, and this engine's template expansion appends children, so a re-declared
|
||
-- $parentLabel creates a SECOND anchorless default-font FontString instead of merging — the
|
||
-- white/overlapping-label bug this line-set replaces). CHARACTER_POINTS_CHANGED/
|
||
-- UNIT_MODEL_CHANGED/PLAYER_DAMAGE_DONE_MODS/UNIT_RANGEDDAMAGE/PLAYER_GUILD_UPDATE/
|
||
-- SKILL_LINES_CHANGED are OMITTED (talents/guild/skills are out of this phase's event
|
||
-- contract; UNIT_RANGEDDAMAGE isn't in it either — UNIT_DAMAGE/UNIT_ATTACK_SPEED alone
|
||
-- trigger the ranged refresh below, same as the ref's own first branch already does).
|
||
function BenillaPaperDollFrame_OnLoad(frame)
|
||
getglobal("BenillaCharacterAttackFrameLabel"):SetText(MELEE_ATTACK)
|
||
getglobal("BenillaCharacterDamageFrameLabel"):SetText(DAMAGE_COLON)
|
||
getglobal("BenillaCharacterAttackPowerFrameLabel"):SetText(ATTACK_POWER_COLON)
|
||
getglobal("BenillaCharacterRangedAttackFrameLabel"):SetText(RANGED_ATTACK)
|
||
getglobal("BenillaCharacterRangedDamageFrameLabel"):SetText(DAMAGE_COLON)
|
||
getglobal("BenillaCharacterRangedAttackPowerFrameLabel"):SetText(ATTACK_POWER_COLON)
|
||
getglobal("BenillaCharacterArmorFrameLabel"):SetText(ARMOR_COLON)
|
||
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||
frame:RegisterEvent("UNIT_LEVEL")
|
||
frame:RegisterEvent("UNIT_RESISTANCES")
|
||
frame:RegisterEvent("UNIT_STATS")
|
||
frame:RegisterEvent("UNIT_DAMAGE")
|
||
frame:RegisterEvent("UNIT_ATTACK_SPEED")
|
||
frame:RegisterEvent("UNIT_ATTACK_POWER")
|
||
frame:RegisterEvent("UNIT_RANGED_ATTACK_POWER")
|
||
frame:RegisterEvent("UNIT_ATTACK")
|
||
end
|
||
|
||
-- ref PaperDollFrame_OnEvent (l.37-76), the unit-token branch only (unit == "player" always
|
||
-- true here — no pet/other-unit reuse in phase 1a) and this file's registered subset only.
|
||
function BenillaPaperDollFrame_OnEvent(frame)
|
||
if event == "PLAYER_ENTERING_WORLD" then
|
||
return
|
||
end
|
||
if not frame:IsVisible() then return end
|
||
if arg1 ~= "player" then return end
|
||
if event == "UNIT_LEVEL" then
|
||
BenillaPaperDollFrame_SetLevel()
|
||
elseif event == "UNIT_DAMAGE" or event == "UNIT_ATTACK_SPEED" then
|
||
BenillaPaperDollFrame_SetDamage()
|
||
BenillaPaperDollFrame_SetRangedAttack()
|
||
BenillaPaperDollFrame_SetRangedDamage()
|
||
BenillaPaperDollFrame_SetAttackBothHands()
|
||
elseif event == "UNIT_ATTACK" then
|
||
BenillaPaperDollFrame_SetAttackBothHands()
|
||
elseif event == "UNIT_RESISTANCES" then
|
||
BenillaPaperDollFrame_SetResistances()
|
||
BenillaPaperDollFrame_SetArmor()
|
||
elseif event == "UNIT_STATS" then
|
||
BenillaPaperDollFrame_SetStats()
|
||
elseif event == "UNIT_ATTACK_POWER" then
|
||
BenillaPaperDollFrame_SetAttackPower()
|
||
elseif event == "UNIT_RANGED_ATTACK_POWER" then
|
||
BenillaPaperDollFrame_SetRangedAttack()
|
||
BenillaPaperDollFrame_SetRangedAttackPower()
|
||
end
|
||
end
|
||
|
||
-- ref PaperDollFrame_OnShow (l.568-585): SetGuild OMITTED (named deferral, this file's
|
||
-- header). The relic Hide/Show branch is DROPPED outright — UnitHasRelicSlot is
|
||
-- vanilla-always-false, so CharacterAmmoSlot simply never has a reason to hide; it ships
|
||
-- with no hidden="true" at all (see its own Button below).
|
||
function BenillaPaperDollFrame_OnShow()
|
||
BenillaPaperDollFrame_SetLevel()
|
||
BenillaPaperDollFrame_SetStats()
|
||
BenillaPaperDollFrame_SetResistances()
|
||
BenillaPaperDollFrame_SetArmor()
|
||
BenillaPaperDollFrame_SetDamage()
|
||
BenillaPaperDollFrame_SetAttackPower()
|
||
BenillaPaperDollFrame_SetAttackBothHands()
|
||
BenillaPaperDollFrame_SetRangedAttack()
|
||
BenillaPaperDollFrame_SetRangedDamage()
|
||
BenillaPaperDollFrame_SetRangedAttackPower()
|
||
end
|
||
-- ref PaperDollFrame_OnHide (l.587-592) is entirely commented-out in the ref itself (the
|
||
-- ShoppingTooltip/compare-tooltip lines, OMIT) — nothing to transcribe, no OnHide wired.
|
||
|
||
-- UnitRace/UnitClass return nil,nil until the app's first player snapshot lands (unlike the
|
||
-- real client, whose race/class are synchronous local data, never network-raced) — "?" is a
|
||
-- harmless placeholder for that one-tick window, not a fidelity change (verified live: an
|
||
-- unguarded format() errors "string expected, got nil" the instant this fires before the
|
||
-- first snapshot).
|
||
function BenillaPaperDollFrame_SetLevel()
|
||
getglobal("BenillaCharacterLevelText"):SetText(
|
||
format(PLAYER_LEVEL, UnitLevel("player"), UnitRace("player") or "?", UnitClass("player") or "?"))
|
||
end
|
||
|
||
-- ref PaperDollFrame_SetStats (l.131-174), including its per-refresh label SetText (l.140)
|
||
-- — the labels' one source of text (see BenillaPaperDollFrame_OnLoad's header comment).
|
||
function BenillaPaperDollFrame_SetStats()
|
||
for i = 1, BENILLA_NUM_STATS do
|
||
local label = getglobal("BenillaCharacterStatFrame" .. i .. "Label")
|
||
local text = getglobal("BenillaCharacterStatFrame" .. i .. "StatText")
|
||
local frame = getglobal("BenillaCharacterStatFrame" .. i)
|
||
local statName = getglobal("SPELL_STAT" .. (i - 1) .. "_NAME")
|
||
label:SetText(statName .. ":")
|
||
local stat, effectiveStat, posBuff, negBuff = UnitStat("player", i)
|
||
local tooltipText = HIGHLIGHT_FONT_COLOR_CODE .. statName .. " "
|
||
if posBuff == 0 and negBuff == 0 then
|
||
text:SetText(effectiveStat)
|
||
frame.tooltip = tooltipText .. effectiveStat .. FONT_COLOR_CODE_CLOSE
|
||
else
|
||
tooltipText = tooltipText .. effectiveStat
|
||
if posBuff > 0 or negBuff < 0 then
|
||
tooltipText = tooltipText .. " (" .. (stat - posBuff - negBuff) .. FONT_COLOR_CODE_CLOSE
|
||
end
|
||
if posBuff > 0 then
|
||
tooltipText = tooltipText .. FONT_COLOR_CODE_CLOSE .. GREEN_FONT_COLOR_CODE .. "+" .. posBuff .. FONT_COLOR_CODE_CLOSE
|
||
end
|
||
if negBuff < 0 then
|
||
tooltipText = tooltipText .. RED_FONT_COLOR_CODE .. " " .. negBuff .. FONT_COLOR_CODE_CLOSE
|
||
end
|
||
if posBuff > 0 or negBuff < 0 then
|
||
tooltipText = tooltipText .. HIGHLIGHT_FONT_COLOR_CODE .. ")" .. FONT_COLOR_CODE_CLOSE
|
||
end
|
||
frame.tooltip = tooltipText
|
||
if negBuff < 0 then
|
||
text:SetText(RED_FONT_COLOR_CODE .. effectiveStat .. FONT_COLOR_CODE_CLOSE)
|
||
else
|
||
text:SetText(GREEN_FONT_COLOR_CODE .. effectiveStat .. FONT_COLOR_CODE_CLOSE)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
-- ref PaperDollFrame_SetResistances (l.176-228). `resistanceLevel` is a proper `local` here
|
||
-- (the ref leaks it as an implicit global, harmless there — Lua 5.0's default — but our
|
||
-- sandboxed globals table is worth not littering).
|
||
function BenillaPaperDollFrame_SetResistances()
|
||
for i = 1, BENILLA_NUM_RESISTANCE_TYPES do
|
||
local resistId = BENILLA_MAGICRES_IDS[i]
|
||
local text = getglobal("BenillaMagicResText" .. i)
|
||
local frame = getglobal("BenillaMagicResFrame" .. i)
|
||
local base, resistance, positive, negative = UnitResistance("player", resistId)
|
||
local resistanceName = getglobal("RESISTANCE" .. resistId .. "_NAME")
|
||
frame.tooltip = resistanceName .. " " .. resistance
|
||
if math.abs(negative) > positive then
|
||
text:SetText(RED_FONT_COLOR_CODE .. resistance .. FONT_COLOR_CODE_CLOSE)
|
||
elseif math.abs(negative) == positive then
|
||
text:SetText(resistance)
|
||
else
|
||
text:SetText(GREEN_FONT_COLOR_CODE .. resistance .. FONT_COLOR_CODE_CLOSE)
|
||
end
|
||
if positive ~= 0 or negative ~= 0 then
|
||
frame.tooltip = frame.tooltip .. " ( " .. HIGHLIGHT_FONT_COLOR_CODE .. base
|
||
if positive > 0 then
|
||
frame.tooltip = frame.tooltip .. GREEN_FONT_COLOR_CODE .. " +" .. positive
|
||
end
|
||
if negative < 0 then
|
||
frame.tooltip = frame.tooltip .. " " .. RED_FONT_COLOR_CODE .. negative
|
||
end
|
||
frame.tooltip = frame.tooltip .. FONT_COLOR_CODE_CLOSE .. " )"
|
||
end
|
||
local unitLevel = math.max(UnitLevel("player") or 1, 20)
|
||
local magicResistanceNumber = resistance / unitLevel
|
||
local resistanceLevel
|
||
if magicResistanceNumber > 5 then
|
||
resistanceLevel = RESISTANCE_EXCELLENT
|
||
elseif magicResistanceNumber > 3.75 then
|
||
resistanceLevel = RESISTANCE_VERYGOOD
|
||
elseif magicResistanceNumber > 2.5 then
|
||
resistanceLevel = RESISTANCE_GOOD
|
||
elseif magicResistanceNumber > 1.25 then
|
||
resistanceLevel = RESISTANCE_FAIR
|
||
elseif magicResistanceNumber > 0 then
|
||
resistanceLevel = RESISTANCE_POOR
|
||
else
|
||
resistanceLevel = RESISTANCE_NONE
|
||
end
|
||
frame.tooltipSubtext = format(RESISTANCE_TOOLTIP_SUBTEXT,
|
||
getglobal("RESISTANCE_TYPE" .. resistId), unitLevel, resistanceLevel)
|
||
end
|
||
end
|
||
|
||
-- ref PaperDollFrame_SetArmor (l.230-250). NOTE the ref's own third UnitArmor return
|
||
-- (`armor`) is unused here too — PaperDollFormatStat gets `base`, not `armor`; transcribed
|
||
-- verbatim, not "fixed".
|
||
function BenillaPaperDollFrame_SetArmor(unit, prefix)
|
||
unit = unit or "player"
|
||
prefix = prefix or "BenillaCharacter"
|
||
local base, effectiveArmor, armor, posBuff, negBuff = UnitArmor(unit)
|
||
local frame = getglobal(prefix .. "ArmorFrame")
|
||
local text = getglobal(prefix .. "ArmorFrameStatText")
|
||
BenillaPaperDollFormatStat(ARMOR, base, posBuff, negBuff, frame, text)
|
||
local playerLevel = UnitLevel(unit)
|
||
local armorReduction = effectiveArmor / ((85 * playerLevel) + 400)
|
||
armorReduction = 100 * (armorReduction / (armorReduction + 1))
|
||
frame.tooltipSubtext = format(ARMOR_TOOLTIP, playerLevel, armorReduction)
|
||
end
|
||
|
||
-- ref PaperDollFrame_SetDamage (l.274-372).
|
||
function BenillaPaperDollFrame_SetDamage(unit, prefix)
|
||
unit = unit or "player"
|
||
prefix = prefix or "BenillaCharacter"
|
||
local damageText = getglobal(prefix .. "DamageFrameStatText")
|
||
local damageFrame = getglobal(prefix .. "DamageFrame")
|
||
local speed, offhandSpeed = UnitAttackSpeed(unit)
|
||
local minDamage, maxDamage, minOffHandDamage, maxOffHandDamage, physicalBonusPos, physicalBonusNeg, percent =
|
||
UnitDamage(unit)
|
||
local displayMin = math.max(math.floor(minDamage), 1)
|
||
local displayMax = math.max(math.ceil(maxDamage), 1)
|
||
minDamage = (minDamage / percent) - physicalBonusPos - physicalBonusNeg
|
||
maxDamage = (maxDamage / percent) - physicalBonusPos - physicalBonusNeg
|
||
local baseDamage = (minDamage + maxDamage) * 0.5
|
||
local fullDamage = (baseDamage + physicalBonusPos + physicalBonusNeg) * percent
|
||
local totalBonus = fullDamage - baseDamage
|
||
local damagePerSecond = math.max(fullDamage, 1) / speed
|
||
local damageTooltip = math.max(math.floor(minDamage), 1) .. " - " .. math.max(math.ceil(maxDamage), 1)
|
||
local colorPos = "|cff20ff20"
|
||
local colorNeg = "|cffff2020"
|
||
if totalBonus == 0 then
|
||
if displayMin < 100 and displayMax < 100 then
|
||
damageText:SetText(displayMin .. " - " .. displayMax)
|
||
else
|
||
damageText:SetText(displayMin .. "-" .. displayMax)
|
||
end
|
||
else
|
||
local color
|
||
if totalBonus > 0 then color = colorPos else color = colorNeg end
|
||
if displayMin < 100 and displayMax < 100 then
|
||
damageText:SetText(color .. displayMin .. " - " .. displayMax .. "|r")
|
||
else
|
||
damageText:SetText(color .. displayMin .. "-" .. displayMax .. "|r")
|
||
end
|
||
if physicalBonusPos > 0 then
|
||
damageTooltip = damageTooltip .. colorPos .. " +" .. physicalBonusPos .. "|r"
|
||
end
|
||
if physicalBonusNeg < 0 then
|
||
damageTooltip = damageTooltip .. colorNeg .. " " .. physicalBonusNeg .. "|r"
|
||
end
|
||
if percent > 1 then
|
||
damageTooltip = damageTooltip .. colorPos .. " x" .. math.floor(percent * 100 + 0.5) .. "%|r"
|
||
elseif percent < 1 then
|
||
damageTooltip = damageTooltip .. colorNeg .. " x" .. math.floor(percent * 100 + 0.5) .. "%|r"
|
||
end
|
||
end
|
||
damageFrame.damage = damageTooltip
|
||
damageFrame.attackSpeed = speed
|
||
damageFrame.dps = damagePerSecond
|
||
if offhandSpeed then
|
||
minOffHandDamage = (minOffHandDamage / percent) - physicalBonusPos - physicalBonusNeg
|
||
maxOffHandDamage = (maxOffHandDamage / percent) - physicalBonusPos - physicalBonusNeg
|
||
local offhandBaseDamage = (minOffHandDamage + maxOffHandDamage) * 0.5
|
||
local offhandFullDamage = (offhandBaseDamage + physicalBonusPos + physicalBonusNeg) * percent
|
||
local offhandDamagePerSecond = math.max(offhandFullDamage, 1) / offhandSpeed
|
||
local offhandDamageTooltip =
|
||
math.max(math.floor(minOffHandDamage), 1) .. " - " .. math.max(math.ceil(maxOffHandDamage), 1)
|
||
if physicalBonusPos > 0 then
|
||
offhandDamageTooltip = offhandDamageTooltip .. colorPos .. " +" .. physicalBonusPos .. "|r"
|
||
end
|
||
if physicalBonusNeg < 0 then
|
||
offhandDamageTooltip = offhandDamageTooltip .. colorNeg .. " " .. physicalBonusNeg .. "|r"
|
||
end
|
||
if percent > 1 then
|
||
offhandDamageTooltip = offhandDamageTooltip .. colorPos .. " x" .. math.floor(percent * 100 + 0.5) .. "%|r"
|
||
elseif percent < 1 then
|
||
offhandDamageTooltip = offhandDamageTooltip .. colorNeg .. " x" .. math.floor(percent * 100 + 0.5) .. "%|r"
|
||
end
|
||
damageFrame.offhandDamage = offhandDamageTooltip
|
||
damageFrame.offhandAttackSpeed = offhandSpeed
|
||
damageFrame.offhandDps = offhandDamagePerSecond
|
||
else
|
||
damageFrame.offhandAttackSpeed = nil
|
||
end
|
||
end
|
||
|
||
-- ref PaperDollFrame_SetAttackPower (l.374-389).
|
||
function BenillaPaperDollFrame_SetAttackPower(unit, prefix)
|
||
unit = unit or "player"
|
||
prefix = prefix or "BenillaCharacter"
|
||
local base, posBuff, negBuff = UnitAttackPower(unit)
|
||
local frame = getglobal(prefix .. "AttackPowerFrame")
|
||
local text = getglobal(prefix .. "AttackPowerFrameStatText")
|
||
BenillaPaperDollFormatStat(MELEE_ATTACK_POWER, base, posBuff, negBuff, frame, text)
|
||
frame.tooltipSubtext = format(MELEE_ATTACK_POWER_TOOLTIP,
|
||
math.max(base + posBuff + negBuff, 0) / BENILLA_ATTACK_POWER_MAGIC_NUMBER)
|
||
end
|
||
|
||
-- ref PaperDollFrame_SetAttackBothHands (l.391-417) — the weapon-skill line (decision 0208's
|
||
-- own "to confirm": the equipped-weapon subclass -> skill-id table is UnitAttackBothHands's
|
||
-- own concern, not this file's).
|
||
function BenillaPaperDollFrame_SetAttackBothHands(unit, prefix)
|
||
unit = unit or "player"
|
||
prefix = prefix or "BenillaCharacter"
|
||
local mainHandAttackBase, mainHandAttackMod = UnitAttackBothHands(unit)
|
||
local frame = getglobal(prefix .. "AttackFrame")
|
||
local text = getglobal(prefix .. "AttackFrameStatText")
|
||
if mainHandAttackMod == 0 then
|
||
text:SetText(mainHandAttackBase)
|
||
frame.tooltip = nil
|
||
else
|
||
local color = RED_FONT_COLOR_CODE
|
||
if mainHandAttackMod > 0 then
|
||
color = GREEN_FONT_COLOR_CODE
|
||
frame.tooltip = mainHandAttackBase .. color .. " +" .. mainHandAttackMod .. FONT_COLOR_CODE_CLOSE
|
||
else
|
||
frame.tooltip = mainHandAttackBase .. color .. " " .. mainHandAttackMod .. FONT_COLOR_CODE_CLOSE
|
||
end
|
||
text:SetText(color .. (mainHandAttackBase + mainHandAttackMod) .. FONT_COLOR_CODE_CLOSE)
|
||
end
|
||
end
|
||
|
||
-- ref PaperDollFrame_SetRangedAttack (l.419-466). `hasRelic`/UnitHasRelicSlot DROPPED
|
||
-- outright (this file's header comment: vanilla-always-false, dead code in the ref itself).
|
||
-- The literal slot id 18 is the ref's OWN hardcoded value (l.435) — quoted verbatim; what
|
||
-- GetInventoryItemTexture resolves id 18 to is the parallel binding's call, not re-derived
|
||
-- here.
|
||
function BenillaPaperDollFrame_SetRangedAttack(unit, prefix)
|
||
if unit == "pet" then return end
|
||
unit = unit or "player"
|
||
prefix = prefix or "BenillaCharacter"
|
||
local frame = getglobal(prefix .. "RangedAttackFrame")
|
||
local text = getglobal(prefix .. "RangedAttackFrameStatText")
|
||
local paperDoll = getglobal("BenillaPaperDollFrame")
|
||
local rangedAttackBase, rangedAttackMod = UnitRangedAttack(unit)
|
||
local rangedTexture = GetInventoryItemTexture("player", 18)
|
||
local oldValue = paperDoll.noRanged
|
||
if rangedTexture then
|
||
paperDoll.noRanged = nil
|
||
else
|
||
text:SetText(NOT_APPLICABLE)
|
||
paperDoll.noRanged = true
|
||
frame.tooltip = nil
|
||
end
|
||
if oldValue ~= paperDoll.noRanged then
|
||
BenillaPaperDollFrame_SetRangedAttackPower()
|
||
BenillaPaperDollFrame_SetRangedDamage()
|
||
end
|
||
if not rangedTexture then return end
|
||
if rangedAttackMod == 0 then
|
||
text:SetText(rangedAttackBase)
|
||
frame.tooltip = nil
|
||
else
|
||
local color = RED_FONT_COLOR_CODE
|
||
if rangedAttackMod > 0 then
|
||
color = GREEN_FONT_COLOR_CODE
|
||
frame.tooltip = rangedAttackBase .. color .. " +" .. rangedAttackMod .. FONT_COLOR_CODE_CLOSE
|
||
else
|
||
frame.tooltip = rangedAttackBase .. color .. " " .. rangedAttackMod .. FONT_COLOR_CODE_CLOSE
|
||
end
|
||
text:SetText(color .. (rangedAttackBase + rangedAttackMod) .. FONT_COLOR_CODE_CLOSE)
|
||
end
|
||
end
|
||
|
||
-- ref PaperDollFrame_SetRangedDamage (l.468-537).
|
||
function BenillaPaperDollFrame_SetRangedDamage(unit, prefix)
|
||
if unit == "pet" then return end
|
||
unit = unit or "player"
|
||
prefix = prefix or "BenillaCharacter"
|
||
local damageText = getglobal(prefix .. "RangedDamageFrameStatText")
|
||
local damageFrame = getglobal(prefix .. "RangedDamageFrame")
|
||
local paperDoll = getglobal("BenillaPaperDollFrame")
|
||
if paperDoll.noRanged then
|
||
damageText:SetText(NOT_APPLICABLE)
|
||
damageFrame.damage = nil
|
||
return
|
||
end
|
||
local rangedAttackSpeed, minDamage, maxDamage, physicalBonusPos, physicalBonusNeg, percent =
|
||
UnitRangedDamage(unit)
|
||
local displayMin = math.max(math.floor(minDamage), 1)
|
||
local displayMax = math.max(math.ceil(maxDamage), 1)
|
||
minDamage = (minDamage / percent) - physicalBonusPos - physicalBonusNeg
|
||
maxDamage = (maxDamage / percent) - physicalBonusPos - physicalBonusNeg
|
||
local baseDamage = (minDamage + maxDamage) * 0.5
|
||
local fullDamage = (baseDamage + physicalBonusPos + physicalBonusNeg) * percent
|
||
local totalBonus = fullDamage - baseDamage
|
||
local damagePerSecond = math.max(fullDamage, 1) / rangedAttackSpeed
|
||
local tooltip = math.max(math.floor(minDamage), 1) .. " - " .. math.max(math.ceil(maxDamage), 1)
|
||
if totalBonus == 0 then
|
||
if displayMin < 100 and displayMax < 100 then
|
||
damageText:SetText(displayMin .. " - " .. displayMax)
|
||
else
|
||
damageText:SetText(displayMin .. "-" .. displayMax)
|
||
end
|
||
else
|
||
local colorPos = "|cff20ff20"
|
||
local colorNeg = "|cffff2020"
|
||
local color
|
||
if totalBonus > 0 then color = colorPos else color = colorNeg end
|
||
if displayMin < 100 and displayMax < 100 then
|
||
damageText:SetText(color .. displayMin .. " - " .. displayMax .. "|r")
|
||
else
|
||
damageText:SetText(color .. displayMin .. "-" .. displayMax .. "|r")
|
||
end
|
||
if physicalBonusPos > 0 then
|
||
tooltip = tooltip .. colorPos .. " +" .. physicalBonusPos .. "|r"
|
||
end
|
||
if physicalBonusNeg < 0 then
|
||
tooltip = tooltip .. colorNeg .. " " .. physicalBonusNeg .. "|r"
|
||
end
|
||
if percent > 1 then
|
||
tooltip = tooltip .. colorPos .. " x" .. math.floor(percent * 100 + 0.5) .. "%|r"
|
||
elseif percent < 1 then
|
||
tooltip = tooltip .. colorNeg .. " x" .. math.floor(percent * 100 + 0.5) .. "%|r"
|
||
end
|
||
damageFrame.tooltip = tooltip .. " " .. format(DPS_TEMPLATE, damagePerSecond)
|
||
end
|
||
damageFrame.attackSpeed = rangedAttackSpeed
|
||
damageFrame.damage = tooltip
|
||
damageFrame.dps = damagePerSecond
|
||
end
|
||
|
||
-- ref PaperDollFrame_SetRangedAttackPower (l.539-566).
|
||
function BenillaPaperDollFrame_SetRangedAttackPower(unit, prefix)
|
||
if unit == "pet" then return end
|
||
unit = unit or "player"
|
||
prefix = prefix or "BenillaCharacter"
|
||
local frame = getglobal(prefix .. "RangedAttackPowerFrame")
|
||
local text = getglobal(prefix .. "RangedAttackPowerFrameStatText")
|
||
local paperDoll = getglobal("BenillaPaperDollFrame")
|
||
if paperDoll.noRanged then
|
||
text:SetText(NOT_APPLICABLE)
|
||
frame.tooltip = nil
|
||
return
|
||
end
|
||
if HasWandEquipped() then
|
||
text:SetText("--")
|
||
frame.tooltip = nil
|
||
return
|
||
end
|
||
local base, posBuff, negBuff = UnitRangedAttackPower(unit)
|
||
BenillaPaperDollFormatStat(RANGED_ATTACK_POWER, base, posBuff, negBuff, frame, text)
|
||
frame.tooltipSubtext = format(RANGED_ATTACK_POWER_TOOLTIP,
|
||
math.max(base + posBuff + negBuff, 0) / BENILLA_ATTACK_POWER_MAGIC_NUMBER)
|
||
end
|
||
|
||
-- ref PaperDollFormatStat (l.804-833).
|
||
function BenillaPaperDollFormatStat(name, base, posBuff, negBuff, frame, textString)
|
||
local effective = math.max(0, base + posBuff + negBuff)
|
||
local text = HIGHLIGHT_FONT_COLOR_CODE .. name .. " " .. effective
|
||
if posBuff == 0 and negBuff == 0 then
|
||
text = text .. FONT_COLOR_CODE_CLOSE
|
||
textString:SetText(effective)
|
||
else
|
||
if posBuff > 0 or negBuff < 0 then
|
||
text = text .. " (" .. base .. FONT_COLOR_CODE_CLOSE
|
||
end
|
||
if posBuff > 0 then
|
||
text = text .. FONT_COLOR_CODE_CLOSE .. GREEN_FONT_COLOR_CODE .. "+" .. posBuff .. FONT_COLOR_CODE_CLOSE
|
||
end
|
||
if negBuff < 0 then
|
||
text = text .. RED_FONT_COLOR_CODE .. " " .. negBuff .. FONT_COLOR_CODE_CLOSE
|
||
end
|
||
if posBuff > 0 or negBuff < 0 then
|
||
text = text .. HIGHLIGHT_FONT_COLOR_CODE .. ")" .. FONT_COLOR_CODE_CLOSE
|
||
end
|
||
if negBuff < 0 then
|
||
textString:SetText(RED_FONT_COLOR_CODE .. effective .. FONT_COLOR_CODE_CLOSE)
|
||
else
|
||
textString:SetText(GREEN_FONT_COLOR_CODE .. effective .. FONT_COLOR_CODE_CLOSE)
|
||
end
|
||
end
|
||
frame.tooltip = text
|
||
end
|
||
|
||
-- ref PaperDollStatTooltip (l.786-802) — `this` (the ref's ambient global) becomes an
|
||
-- explicit `button` param here, matching this codebase's own house convention (Merchant/
|
||
-- Bag/QuestLog all thread `self` explicitly rather than lean on the engine's `this`
|
||
-- global, which DOES exist — `benilla-ui/src/script/event.rs` — but isn't this codebase's
|
||
-- idiom).
|
||
function BenillaPaperDollStatTooltip(button, stat)
|
||
-- classFileName nil until the first player snapshot lands (this file's SetLevel comment
|
||
-- on the same engine timing gap) — "" just misses every class lookup, falling through to
|
||
-- DEFAULT_*_TOOLTIP below exactly like an unrecognized class would.
|
||
local _, classFileName = UnitClass("player")
|
||
classFileName = classFileName or ""
|
||
local classStatText = getglobal(strupper(classFileName) .. "_" .. stat .. "_TOOLTIP")
|
||
if not classStatText then
|
||
classStatText = getglobal("DEFAULT_" .. stat .. "_TOOLTIP")
|
||
end
|
||
GameTooltip:SetOwner(button, "ANCHOR_RIGHT")
|
||
GameTooltip:SetText(button.tooltip)
|
||
GameTooltip:AddLine(classStatText, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1)
|
||
GameTooltip:Show()
|
||
end
|
||
|
||
-- ref CharacterDamageFrame_OnEnter (l.835-851).
|
||
function BenillaCharacterDamageFrame_OnEnter(button)
|
||
GameTooltip:SetOwner(button, "ANCHOR_RIGHT")
|
||
GameTooltip:SetText(INVTYPE_WEAPONMAINHAND, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
|
||
GameTooltip:AddDoubleLine(ATTACK_SPEED_COLON, string.format("%.2f", button.attackSpeed),
|
||
NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
|
||
GameTooltip:AddDoubleLine(DAMAGE_COLON, button.damage,
|
||
NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
|
||
GameTooltip:AddDoubleLine(DAMAGE_PER_SECOND, string.format("%.1f", button.dps),
|
||
NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
|
||
if button.offhandAttackSpeed then
|
||
GameTooltip:AddLine(" ")
|
||
GameTooltip:AddLine(INVTYPE_WEAPONOFFHAND, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
|
||
GameTooltip:AddDoubleLine(ATTACK_SPEED_COLON, string.format("%.2f", button.offhandAttackSpeed),
|
||
NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
|
||
GameTooltip:AddDoubleLine(DAMAGE_COLON, button.offhandDamage,
|
||
NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
|
||
GameTooltip:AddDoubleLine(DAMAGE_PER_SECOND, string.format("%.1f", button.offhandDps),
|
||
NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
|
||
end
|
||
GameTooltip:Show()
|
||
end
|
||
|
||
-- ref CharacterRangedDamageFrame_OnEnter (l.853-863).
|
||
function BenillaCharacterRangedDamageFrame_OnEnter(button)
|
||
if not button.damage then return end
|
||
GameTooltip:SetOwner(button, "ANCHOR_RIGHT")
|
||
GameTooltip:SetText(INVTYPE_RANGED, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
|
||
GameTooltip:AddDoubleLine(ATTACK_SPEED_COLON, string.format("%.2f", button.attackSpeed),
|
||
NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
|
||
GameTooltip:AddDoubleLine(DAMAGE_COLON, button.damage,
|
||
NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
|
||
GameTooltip:AddDoubleLine(DAMAGE_PER_SECOND, string.format("%.1f", button.dps),
|
||
NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
|
||
GameTooltip:Show()
|
||
end
|
||
|
||
-- ── The 19 equipment slots + ammo (ref PaperDollItemSlotButton_*, l.78-98/594-784) ──────
|
||
-- Cooldowns, the broken-red tint, and SHOW_COMPARE_TOOLTIP are still OMITTED this phase —
|
||
-- this file's header comment. What ships now (1b): the icon/count fill, the empty-slot
|
||
-- art, the hover tooltip, click-to-equip/-use (l.647-662, ctrl/shift named deferrals),
|
||
-- the drag trio, lock dimming, and the CURSOR_UPDATE ring highlight (emulated — header
|
||
-- comment).
|
||
function BenillaPaperDollSlot_OnLoad(button, slotName)
|
||
button:RegisterEvent("UNIT_INVENTORY_CHANGED")
|
||
local id, texture, checkRelic = GetInventorySlotInfo(slotName)
|
||
button.invSlotId = id
|
||
button.slotName = slotName
|
||
button.emptyTexture = texture
|
||
button.checkRelic = checkRelic -- UnitHasRelicSlot is vanilla-always-false (header OMIT): never read
|
||
button.icon = getglobal(button:GetName() .. "IconTexture")
|
||
button.count = getglobal(button:GetName() .. "Count")
|
||
-- Equip interactions on the 19 named slots use the equip-swap wire (PickupInventoryItem
|
||
-- pick/place/swap). The ammo slot (id 0) is different: it LOADS ammo by entry via
|
||
-- CMSG_SET_AMMO (decision 0526; wow-re cursor-dragdrop-slots.md — the client's auto-equip
|
||
-- sender forks ammo-class → SET_AMMO), so it only wants click-to-place + drag-drop, both
|
||
-- routed to BenillaCharacterAmmoSlot_OnClick (its own Scripts block below). It carries no
|
||
-- ring, so the CURSOR_UPDATE highlight / ITEM_LOCK dim legs would no-op anyway, and there
|
||
-- is no drag-OUT (you can't pick the loaded ammo off the slot).
|
||
if slotName ~= "AmmoSlot" then
|
||
button:RegisterEvent("ITEM_LOCK_CHANGED")
|
||
button:RegisterEvent("CURSOR_UPDATE")
|
||
-- The shift-compare listener (ref PaperDollFrame.lua l.83): the ENGINE fires
|
||
-- SHOW_COMPARE_TOOLTIP(slot, n) for an equippable item hover while shift is held;
|
||
-- only the matching visible doll slot answers (the OnEvent branch below).
|
||
button:RegisterEvent("SHOW_COMPARE_TOOLTIP")
|
||
button:RegisterForClicks("LeftButtonUp", "RightButtonUp")
|
||
-- The drag trio (decision 0216 §3): click-carry and drag are ONE code path in the
|
||
-- reference (PaperDollFrame.xml:20-25 routes OnDragStart/OnReceiveDrag to the same
|
||
-- OnClick("LeftButton", ignoreModifiers=1) the plain click uses) — see
|
||
-- BenillaPaperDollSlot_OnClick below for the identical routing, the bag slots' own
|
||
-- precedent (BagFrame.xml's BenillaBagSlot_OnClick).
|
||
button:RegisterForDrag("LeftButton")
|
||
else
|
||
button:RegisterForClicks("LeftButtonUp")
|
||
end
|
||
BenillaPaperDollSlot_Update(button)
|
||
end
|
||
|
||
-- Left: shift/ctrl are named deferrals (chat-link insert / DressUpItemLink, header
|
||
-- comment) — recognized and done, not fallen through to a pickup a real modified click
|
||
-- would never trigger. Plain click: PickupInventoryItem (pick up / place / swap / cancel,
|
||
-- ref l.656). Right: UseInventoryItem (ref l.659). `ignoreModifiers` is the drag-route
|
||
-- calls' own suppression, the bag slots' precedent.
|
||
function BenillaPaperDollSlot_OnClick(button, mouseButton, ignoreModifiers)
|
||
if mouseButton == "LeftButton" then
|
||
if IsControlKeyDown() and not ignoreModifiers then
|
||
return -- DressUpItemLink: named deferral, no dressing room yet
|
||
elseif IsShiftKeyDown() and not ignoreModifiers then
|
||
return -- chat-link insert: named deferral
|
||
end
|
||
PickupInventoryItem(button.invSlotId)
|
||
GameTooltip:Hide() -- the item just left the slot for the cursor
|
||
BenillaPaperDollSlot_Update(button)
|
||
elseif mouseButton == "RightButton" then
|
||
UseInventoryItem(button.invSlotId)
|
||
end
|
||
end
|
||
|
||
-- The ammo slot's own click/drop (decision 0526): ammo LOADS by entry (CMSG_SET_AMMO), it
|
||
-- doesn't swap into an equip slot, so it can't share BenillaPaperDollSlot_OnClick's
|
||
-- PickupInventoryItem path. Only an ammo payload fits (CursorCanGoInSlot(0) — ammo's
|
||
-- find_equip_slot is [0]); the drop funnels through AutoEquipCursorItem, whose app-side drain
|
||
-- resolves the held item's entry and forks to SET_AMMO — the reference's own shared auto-equip
|
||
-- sender (wow-re cursor-dragdrop-slots.md). An empty cursor or a non-ammo payload is inert
|
||
-- (nothing fits), and there is no unload-via-slot in 1.12.
|
||
function BenillaCharacterAmmoSlot_OnClick(button)
|
||
if CursorCanGoInSlot(button.invSlotId) then
|
||
AutoEquipCursorItem()
|
||
GameTooltip:Hide()
|
||
BenillaPaperDollSlot_Update(button)
|
||
end
|
||
end
|
||
|
||
function BenillaPaperDollSlot_Update(button)
|
||
local textureName = GetInventoryItemTexture("player", button.invSlotId)
|
||
if textureName then
|
||
button.icon:SetTexture(textureName)
|
||
local count = GetInventoryItemCount("player", button.invSlotId)
|
||
if (count or 0) > 1 then
|
||
button.count:SetText(count)
|
||
else
|
||
button.count:SetText("")
|
||
end
|
||
else
|
||
button.icon:SetTexture(button.emptyTexture)
|
||
button.count:SetText("")
|
||
end
|
||
-- A BROKEN item (durability 0) tints icon + slot ring red — ref
|
||
-- PaperDollItemSlotButton_Update (l.670-676: SetItemButtonTextureVertexColor +
|
||
-- SetItemButtonNormalTextureVertexColor, both 0.9, 0, 0). The bags carry no broken
|
||
-- tint in 1.12 (ContainerFrame.lua has none) — equipped only. Kept as a flag for
|
||
-- the cursor highlight's restore (Unlock below shares the ring).
|
||
button.broken = textureName and GetInventoryItemBroken("player", button.invSlotId)
|
||
-- A locked slot (its item is up on the cursor, or a send is still pending
|
||
-- server-side, decision 0216 §4/0218 §3) dims — the bag slots' own vertex-dim
|
||
-- convention (BagFrame.xml's BenillaBagSlot_Update), applied here instead of the
|
||
-- ref's separate SetItemButtonDesaturated call (no engine equivalent — header
|
||
-- comment). The transient drag-dim outranks the broken red on the icon.
|
||
if IsInventoryItemLocked(button.invSlotId) then
|
||
button.icon:SetVertexColor(0.4, 0.4, 0.4)
|
||
elseif button.broken then
|
||
button.icon:SetVertexColor(0.9, 0, 0)
|
||
else
|
||
button.icon:SetVertexColor(1, 1, 1)
|
||
end
|
||
BenillaPaperDollSlot_UnlockHighlight(button)
|
||
if GameTooltip:IsOwned(button) then
|
||
BenillaPaperDollSlot_OnEnter(button)
|
||
end
|
||
end
|
||
|
||
-- ref PaperDollItemSlotButton_OnEnter (l.739-748): the equipped hover is the INSTANCE
|
||
-- render — SetInventoryItem, never an id/template render. That carries the live
|
||
-- durability pair (an earlier SetItemById here read the template's full max/max), and
|
||
-- an instance hover never arms a shift-compare — the engine's SetInventoryItem doesn't
|
||
-- arm (a worn item compared with itself is no comparison; director-caught: shift over
|
||
-- the doll popped a "Currently Equipped" 0/XX beside a template-full main tooltip).
|
||
-- The ref's repair-mode branch (l.757-762) is INTERIM-omitted with the binding's
|
||
-- repairCost. checkRelic (l.744-746) is TBC-flagged dead weight in 1.12 — omitted.
|
||
function BenillaPaperDollSlot_OnEnter(button)
|
||
GameTooltip:SetOwner(button, "ANCHOR_RIGHT")
|
||
local hasItem = GameTooltip:SetInventoryItem("player", button.invSlotId)
|
||
if not hasItem then
|
||
-- Empty slot: the slot-name tooltip (ref strupper(strsub(name,10)) -> the matching
|
||
-- GlobalStrings key, e.g. "HeadSlot" -> HEADSLOT -> "Head").
|
||
GameTooltip:SetText(getglobal(strupper(button.slotName)) or button.slotName)
|
||
end
|
||
GameTooltip:Show()
|
||
end
|
||
|
||
-- CURSOR_UPDATE's LockHighlight/UnlockHighlight emulation (this file's header comment: no
|
||
-- true forced-highlight affordance exists — no benilla-ui Button method shows a state
|
||
-- texture off real hover). A vertex tint on the slot's own Quickslot2 ring
|
||
-- (`NormalTexture`, the template below) stands in: green while `CursorCanGoInSlot` says
|
||
-- the held payload fits here, white otherwise.
|
||
-- Both legs no-op on a ringless slot (the ammo slot carries no NormalTexture).
|
||
function BenillaPaperDollSlot_LockHighlight(button)
|
||
local ring = button:GetNormalTexture()
|
||
if ring then
|
||
ring:SetVertexColor(0, 1, 0)
|
||
end
|
||
end
|
||
|
||
-- The restore leg: back to the ring's resting color — broken red (ref l.672) or white.
|
||
function BenillaPaperDollSlot_UnlockHighlight(button)
|
||
local ring = button:GetNormalTexture()
|
||
if not ring then
|
||
return
|
||
end
|
||
if button.broken then
|
||
ring:SetVertexColor(0.9, 0, 0)
|
||
else
|
||
ring:SetVertexColor(1, 1, 1)
|
||
end
|
||
end
|
||
|
||
function BenillaPaperDollSlot_OnEvent(button)
|
||
if event == "UNIT_INVENTORY_CHANGED" and arg1 == "player" then
|
||
BenillaPaperDollSlot_Update(button)
|
||
elseif event == "ITEM_LOCK_CHANGED" then
|
||
-- Ref PaperDollItemSlotButton_OnEvent (l.601-604): no arg filtering — every doll
|
||
-- slot just repaints on any lock transition (cheap, idempotent; it's this SLOT's
|
||
-- own dim that's actually changing, if anything is).
|
||
BenillaPaperDollSlot_Update(button)
|
||
elseif event == "CURSOR_UPDATE" then
|
||
if CursorCanGoInSlot(button.invSlotId) then
|
||
BenillaPaperDollSlot_LockHighlight(button)
|
||
else
|
||
BenillaPaperDollSlot_UnlockHighlight(button)
|
||
end
|
||
elseif event == "SHOW_COMPARE_TOOLTIP" then
|
||
-- ref PaperDollItemSlotButton_OnEvent (l.621-640, quoted; button.invSlotId for the
|
||
-- ref's this:GetID()): arg1 = the doll slot the hovered item would equip into,
|
||
-- arg2 = which shopping tooltip. Both anchor to THIS doll slot (1 to its right,
|
||
-- 2 hanging below-right) — so compares appear only with the character window
|
||
-- open, the 1.12 behavior.
|
||
if arg1 ~= button.invSlotId or not button:IsVisible() or arg2 > NUM_SHOPPING_TOOLTIPS then
|
||
return
|
||
end
|
||
local tooltip = getglobal("ShoppingTooltip" .. arg2)
|
||
local anchor = "ANCHOR_RIGHT"
|
||
if arg2 > 1 then
|
||
anchor = "ANCHOR_BOTTOMRIGHT"
|
||
end
|
||
tooltip:SetOwner(button, anchor)
|
||
local hasItem = tooltip:SetInventoryItem("player", button.invSlotId)
|
||
if not hasItem then
|
||
tooltip:Hide()
|
||
end
|
||
end
|
||
end
|
||
|
||
-- ref PaperDollItemSlotButton_OnUpdate (l.766-784), the un-throttled BagFrame-style
|
||
-- re-enter loop (BagFrame.xml's own comment on why this ships unthrottled).
|
||
function BenillaPaperDollSlot_OnUpdate(button)
|
||
if GameTooltip:IsOwned(button) then
|
||
BenillaPaperDollSlot_OnEnter(button)
|
||
end
|
||
end
|
||
|
||
-- ── The model pane (ref UIParent.lua:1420-1462) ─────────────────────────────────────────
|
||
-- This file's header comment: a booth-texture stand-in, not a live widget. `frame` here is
|
||
-- BenillaCharacterModelFrame; `frame.facing` stands in for the ref's `model.rotation`.
|
||
function BenillaPaperDollModel_OnLoad(frame)
|
||
frame.facing = 0.61 -- ref UIParent.lua:1422, the literal default facing
|
||
BenillaPaperDollModel_SetFacing(frame.facing)
|
||
end
|
||
|
||
-- ref Model_RotateLeft/Right (UIParent.lua:1426-1442) — the ref's OWN left/right sign
|
||
-- convention is preserved verbatim (rotate-left SUBTRACTS, rotate-right ADDS); not
|
||
-- re-derived, just quoted.
|
||
function BenillaPaperDollModel_RotateLeft(frame)
|
||
frame.facing = frame.facing - 0.03
|
||
BenillaPaperDollModel_SetFacing(frame.facing)
|
||
PlaySound("igInventoryRotateCharacter")
|
||
end
|
||
|
||
function BenillaPaperDollModel_RotateRight(frame)
|
||
frame.facing = frame.facing + 0.03
|
||
BenillaPaperDollModel_SetFacing(frame.facing)
|
||
PlaySound("igInventoryRotateCharacter")
|
||
end
|
||
|
||
-- ref Model_OnUpdate (UIParent.lua:1444-1462) — the HELD-button continuous spin, which is
|
||
-- where a rotate button's actual feel lives: half a turn per second (ROTATIONS_PER_SECOND,
|
||
-- UIParent.lua:2), against which the 0.03 click nudge above is a ~1.7° tap. Every 1.12 model
|
||
-- pane wires it (PaperDollFrame l.222-224, DressUpFrame.xml:202-204, TabardFrame.xml:406-408).
|
||
-- It used to be omitted here for want of `GetButtonState` — that method now answers "PUSHED"
|
||
-- for a LIVE mouse-held button (decision 0288 P3), so the ref's own loop ships verbatim.
|
||
-- Verbatim INCLUDES the ref's sign quirk: the held branches run OPPOSITE to the click helpers
|
||
-- (held-LEFT adds, held-RIGHT subtracts). Not a transcription slip — quoted, not re-derived.
|
||
function BenillaPaperDollModel_OnUpdate(frame, elapsed)
|
||
local step = elapsed * 2 * PI * ROTATIONS_PER_SECOND
|
||
if getglobal(frame:GetName() .. "RotateLeftButton"):GetButtonState() == "PUSHED" then
|
||
frame.facing = frame.facing + step
|
||
if frame.facing < 0 then
|
||
frame.facing = frame.facing + (2 * PI)
|
||
end
|
||
BenillaPaperDollModel_SetFacing(frame.facing)
|
||
end
|
||
if getglobal(frame:GetName() .. "RotateRightButton"):GetButtonState() == "PUSHED" then
|
||
frame.facing = frame.facing - step
|
||
if frame.facing > (2 * PI) then
|
||
frame.facing = frame.facing - (2 * PI)
|
||
end
|
||
BenillaPaperDollModel_SetFacing(frame.facing)
|
||
end
|
||
end
|
||
|
||
-- ref CharacterModelFrame_OnMouseUp (l.31-35): a plain left-click-up on the model pane
|
||
-- also auto-equips a held container item — the model pane doubles as a drop target even
|
||
-- without a drag, not just via OnReceiveDrag. AutoEquipCursorItem is already a no-op for
|
||
-- every non-fitting/non-container payload (cursor.rs's own contract), so no CursorHasItem
|
||
-- guard is needed here.
|
||
function BenillaPaperDollModel_OnMouseUp(frame, button)
|
||
if button == "LeftButton" then
|
||
AutoEquipCursorItem()
|
||
end
|
||
end
|
||
]]></Script>
|
||
|
||
<!--
|
||
The shared equipment-slot button (ref PaperDollItemSlotButtonTemplate inherits
|
||
ItemButtonTemplate, ref-PaperDollFrame.xml:4-38 — ItemButtonTemplate's own XML isn't part of
|
||
this session's extraction, so its shape is taken from this codebase's own prior
|
||
reconstruction of it, BagFrame.xml's BenillaBagSlotTemplate: 37x37, a BACKGROUND icon fill,
|
||
an OVERLAY count, the 64x64 UI-Quickslot2 ring centered (0,-1), UI-Quickslot-Depress pushed,
|
||
ButtonHilight-Square ADD highlight — duplicated here rather than cross-file inherited so this
|
||
window's slot behavior (UNIT_INVENTORY_CHANGED refresh, tooltip) stays self-contained in one
|
||
file, the same posture Merchant's own item-row template takes vs. reusing Bag's).
|
||
Cooldown ($parentCooldown, CooldownFrameTemplate) OMITTED — no cooldown feed/engine
|
||
affordance exists yet. OnClick + the drag trio land THIS phase (1b) — the NormalTexture
|
||
ring below doubles as the CURSOR_UPDATE highlight's vertex-tint target (this file's header
|
||
comment: an emulation, no true LockHighlight/UnlockHighlight exists).
|
||
-->
|
||
<Button name="BenillaPaperDollItemSlotTemplate" virtual="true">
|
||
<Size><AbsDimension x="37" y="37"/></Size>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="$parentIconTexture"/>
|
||
</Layer>
|
||
<Layer level="OVERLAY">
|
||
<FontString name="$parentCount" inherits="NumberFontNormal" justifyH="RIGHT">
|
||
<Anchors>
|
||
<Anchor point="BOTTOMRIGHT" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="-5" y="2"/></Offset></Anchor>
|
||
</Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<NormalTexture file="Interface\Buttons\UI-Quickslot2">
|
||
<Size><AbsDimension x="64" y="64"/></Size>
|
||
<Anchors>
|
||
<Anchor point="CENTER" relativePoint="CENTER"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor>
|
||
</Anchors>
|
||
</NormalTexture>
|
||
<PushedTexture file="Interface\Buttons\UI-Quickslot-Depress"/>
|
||
<HighlightTexture file="Interface\Buttons\ButtonHilight-Square" alphaMode="ADD"/>
|
||
<Scripts>
|
||
<OnClick>BenillaPaperDollSlot_OnClick(self, arg1)</OnClick>
|
||
<OnEnter>BenillaPaperDollSlot_OnEnter(self)</OnEnter>
|
||
<OnLeave>GameTooltip:Hide()</OnLeave>
|
||
<OnEvent>BenillaPaperDollSlot_OnEvent(self)</OnEvent>
|
||
<OnUpdate>BenillaPaperDollSlot_OnUpdate(self)</OnUpdate>
|
||
<!-- The reference routes both drag entries to the plain click path with modifiers
|
||
suppressed (PaperDollFrame.xml:20-25 — PickupInventoryItem, ignoring
|
||
shift/ctrl) — the bag slots' own precedent (BagFrame.xml). -->
|
||
<OnDragStart>BenillaPaperDollSlot_OnClick(self, "LeftButton", true)</OnDragStart>
|
||
<OnReceiveDrag>BenillaPaperDollSlot_OnClick(self, "LeftButton", true)</OnReceiveDrag>
|
||
</Scripts>
|
||
</Button>
|
||
|
||
<!--
|
||
The ref defines TWO byte-identical templates for the attribute/stat rows — StatFrameTemplate
|
||
(ref-PaperDollFrame.xml:39-71) and AttributeFrameTemplate (l.72-105): same 104x13 size, same
|
||
Label(GameFontNormalSmall,LEFT) + $parentStat(30x13,RIGHT)/$parentText(GameFontHighlightSmall,
|
||
RIGHT) shape — a semantic-only distinction in the real client (armor/attack rows "are stats",
|
||
the 5 primaries "are attributes"). Collapsed to ONE template here (a legitimate reuse — no
|
||
behavior differs). `self:EnableMouse(true)` in OnLoad: a plain Frame isn't mouse-enabled by
|
||
construction in this engine (this file's header comment) — every instance below needs it to
|
||
receive its own OnEnter/OnLeave hover.
|
||
-->
|
||
<Frame name="BenillaStatRowTemplate" virtual="true">
|
||
<Size><AbsDimension x="104" y="13"/></Size>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<FontString name="$parentLabel" inherits="GameFontNormalSmall">
|
||
<Anchors><Anchor point="LEFT"/></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<Frame name="$parentStat">
|
||
<Size><AbsDimension x="30" y="13"/></Size>
|
||
<Anchors><Anchor point="RIGHT"/></Anchors>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<FontString name="$parentText" inherits="GameFontHighlightSmall" justifyH="RIGHT">
|
||
<Anchors><Anchor point="RIGHT"/></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
</Frame>
|
||
</Frames>
|
||
</Frame>
|
||
|
||
<!--
|
||
The magic-resistance icon frame (ref MagicResistanceFrameTemplate, ref-PaperDollFrame.xml:
|
||
106-123): 32x29, a generic tooltip OnEnter reading self.tooltip/self.tooltipSubtext (both
|
||
filled by BenillaPaperDollFrame_SetResistances) — no per-instance OnEnter override needed
|
||
(the ref's own MagicResFrame1-5 instances carry none either).
|
||
-->
|
||
<Frame name="BenillaMagicResistanceFrameTemplate" virtual="true">
|
||
<Size><AbsDimension x="32" y="29"/></Size>
|
||
<Scripts>
|
||
<OnLoad>self:EnableMouse(true)</OnLoad>
|
||
<OnEnter>
|
||
if self.tooltip then
|
||
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
|
||
GameTooltip:SetText(self.tooltip)
|
||
GameTooltip:AddLine(self.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1)
|
||
GameTooltip:Show()
|
||
end
|
||
</OnEnter>
|
||
<OnLeave>GameTooltip:Hide()</OnLeave>
|
||
</Scripts>
|
||
</Frame>
|
||
|
||
<Frame name="BenillaCharacterFrame" hidden="true">
|
||
<!-- The real 384x512 window (ref-CharacterFrame.xml:5-7). No <Anchors> — ShowUIPanel/
|
||
SetLeftFrame SetPoints this to the left slot on open (UiPanels.xml's own convention). -->
|
||
<Size><AbsDimension x="384" y="512"/></Size>
|
||
<!-- HitRectInsets: transcribed for fidelity; no loader wiring exists yet (this file's header
|
||
comment) — a harmless no-op today. -->
|
||
<HitRectInsets><AbsInset left="0" right="30" top="0" bottom="45"/></HitRectInsets>
|
||
<Layers>
|
||
<!-- Portrait 60x60 TOPLEFT (7,-6) (ref l.19-31). Set in OnShow via SetPortraitTexture
|
||
(the live model-bake binding, UnitFrames.xml's own precedent) — "player" is a fixed
|
||
token here (unlike a unit frame, this window only ever shows the local player). -->
|
||
<Layer level="ARTWORK">
|
||
<Texture name="BenillaCharacterFramePortrait">
|
||
<Size><AbsDimension x="60" y="60"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="7" y="-6"/></Offset></Anchor></Anchors>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- Name: CENTER (6,232) wrapper, GameFontNormal 300x12 centered inside it, white (ref
|
||
l.35-64). UnitPVPName -> plain UnitName (this file's header comment: PVP rank is a
|
||
named deferral) — CharacterTitleText/CharacterGuildText (both PVP-rank/guild-driven)
|
||
are dropped with it. -->
|
||
<Frame name="BenillaCharacterNameFrame">
|
||
<Size><AbsDimension x="109" y="12"/></Size>
|
||
<Anchors><Anchor point="CENTER"><Offset><AbsDimension x="6" y="232"/></Offset></Anchor></Anchors>
|
||
<Layers>
|
||
<Layer>
|
||
<FontString name="BenillaCharacterNameText" inherits="GameFontNormal" text="NAME">
|
||
<Size><AbsDimension x="300" y="12"/></Size>
|
||
<Anchors><Anchor point="CENTER"/></Anchors>
|
||
<Color r="1.0" g="1.0" b="1.0"/>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Scripts>
|
||
<OnLoad>self:SetFrameLevel(self:GetFrameLevel() + 1)</OnLoad>
|
||
</Scripts>
|
||
</Frame>
|
||
<!-- Close: the ref's own UIPanelCloseButton position (CENTER of TOPRIGHT, -44,-25 — ref
|
||
l.65-78), on the minimize-button art this codebase's close buttons all use (no
|
||
UIPanelCloseButton template ships — Gossip/Bag/Merchant's own header comments).
|
||
OnLoad raises the frame level +1 (the same idiom BenillaCharacterNameFrame above uses,
|
||
transcribed from the ref): the window's own art is BenillaPaperDollFrame's BACKGROUND
|
||
layer — a full-window sibling created AFTER this button — so at the shared default
|
||
level 0 the page's art paints over the button by creation order (order.rs). The ref's
|
||
close button rides the client's show-time bucket-tail re-insertion instead; benilla
|
||
proxies that with creation order, so the explicit raise is the faithful compensation. -->
|
||
<Button name="BenillaCharacterFrameCloseButton">
|
||
<Size><AbsDimension x="32" y="32"/></Size>
|
||
<Anchors><Anchor point="CENTER" relativePoint="TOPRIGHT"><Offset><AbsDimension x="-44" y="-25"/></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>
|
||
<OnLoad>self:SetFrameLevel(self:GetFrameLevel() + 1)</OnLoad>
|
||
<OnClick>HideUIPanel(getglobal("BenillaCharacterFrame"))</OnClick>
|
||
</Scripts>
|
||
</Button>
|
||
<!-- The tab row (ref l.79-96 — CENTER of BOTTOMLEFT +60,+62 — tab 2 chained off tab 1,
|
||
MerchantFrame.xml's own Merchant/Buyback LEFT-of-RIGHT -16 offset). DEVIATION
|
||
flagged (decision 0437 phase 4): the real client's Skills tab is 4th of five
|
||
(Character/Pet/Reputation/Skills/Honor, ref l.79-168); ours renders 2nd until
|
||
Pet/Reputation/Honor land (the "tabs arrive with their pages" precedent, 0138/0208).
|
||
No hover tooltip (MicroButtonTooltipText/TOGGLECHARACTER0 have no engine surface,
|
||
and each tab's own visible label already says what it does — Merchant's own tab
|
||
pair carries no hover tooltip either). -->
|
||
<Button name="BenillaCharacterFrameTab1" inherits="CharacterFrameTabButtonTemplate" text="Character">
|
||
<Anchors><Anchor point="CENTER" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="60" y="62"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnClick>BenillaCharacterFrameTab_OnClick(1)</OnClick></Scripts>
|
||
</Button>
|
||
<Button name="BenillaCharacterFrameTab2" inherits="CharacterFrameTabButtonTemplate" text="Skills">
|
||
<Anchors><Anchor point="LEFT" relativeTo="BenillaCharacterFrameTab1" relativePoint="RIGHT"><Offset><AbsDimension x="-16" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnClick>BenillaCharacterFrameTab_OnClick(2)</OnClick></Scripts>
|
||
</Button>
|
||
|
||
<!-- The paper-doll page (ref PaperDollFrame, ref-PaperDollFrame.xml:124-1059). Sized to
|
||
exactly fill the parent instead of the ref's setAllPoints="true" — the same effect
|
||
(see this file's header: frame-level setAllPoints was a no-op when this was written
|
||
and is wired now; the explicit size is equivalent, so it stays). -->
|
||
<Frame name="BenillaPaperDollFrame">
|
||
<Size><AbsDimension x="384" y="512"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"/></Anchors>
|
||
<HitRectInsets><AbsInset left="0" right="30" top="0" bottom="45"/></HitRectInsets>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<!-- The four quadrant slabs that ARE this page's art (ref l.129-173): 256-wide
|
||
left halves, 128-wide right halves, each 256 tall, pinned per corner. -->
|
||
<Texture file="Interface\PaperDollInfoFrame\UI-Character-CharacterTab-L1">
|
||
<Size><AbsDimension x="256" y="256"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT"/></Anchors>
|
||
</Texture>
|
||
<Texture file="Interface\PaperDollInfoFrame\UI-Character-CharacterTab-R1">
|
||
<Size><AbsDimension x="128" y="256"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="256" y="0"/></Offset></Anchor></Anchors>
|
||
</Texture>
|
||
<Texture file="Interface\PaperDollInfoFrame\UI-Character-CharacterTab-BottomLeft">
|
||
<Size><AbsDimension x="256" y="256"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="0" y="-256"/></Offset></Anchor></Anchors>
|
||
</Texture>
|
||
<Texture file="Interface\PaperDollInfoFrame\UI-Character-CharacterTab-BottomRight">
|
||
<Size><AbsDimension x="128" y="256"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="256" y="-256"/></Offset></Anchor></Anchors>
|
||
</Texture>
|
||
<!-- "Level %d %s %s" under the name (ref l.174-182). -->
|
||
<FontString name="BenillaCharacterLevelText" inherits="GameFontNormalSmall">
|
||
<Anchors>
|
||
<Anchor point="TOP" relativeTo="BenillaCharacterNameText" relativePoint="BOTTOM"><Offset><AbsDimension x="0" y="-6"/></Offset></Anchor>
|
||
</Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- The model pane (ref PlayerModel CharacterModelFrame, l.204-273): 233x224 at
|
||
TOPLEFT (65,-78). This file's header comment: a plain Frame sampling the
|
||
paper-doll booth bake, not a live <Model>/<PlayerModel> widget. -->
|
||
<Frame name="BenillaCharacterModelFrame">
|
||
<Size><AbsDimension x="233" y="224"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="65" y="-78"/></Offset></Anchor></Anchors>
|
||
<Layers>
|
||
<Layer level="ARTWORK">
|
||
<Texture name="$parentTexture">
|
||
<Size><AbsDimension x="233" y="224"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT"/></Anchors>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- Rotate buttons (ref l.234-271): 35x35, left then right chained off its
|
||
TOPRIGHT, both at the model pane's own TOPLEFT.
|
||
`RegisterForClicks("LeftButtonDown","LeftButtonUp")` is the ref's own
|
||
(l.241-243/l.263-265): OnClick fires on BOTH edges, so one tap nudges
|
||
twice (2 × 0.03), and holding hands the spin to the pane's OnUpdate. -->
|
||
<Button name="BenillaCharacterModelFrameRotateLeftButton">
|
||
<Size><AbsDimension x="35" y="35"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"/></Anchors>
|
||
<NormalTexture file="Interface\Buttons\UI-RotationLeft-Button-Up"/>
|
||
<PushedTexture file="Interface\Buttons\UI-RotationLeft-Button-Down"/>
|
||
<HighlightTexture file="Interface\Buttons\ButtonHilight-Round" alphaMode="ADD"/>
|
||
<Scripts>
|
||
<OnLoad>self:RegisterForClicks("LeftButtonDown", "LeftButtonUp")</OnLoad>
|
||
<OnClick>BenillaPaperDollModel_RotateLeft(getglobal("BenillaCharacterModelFrame"))</OnClick>
|
||
</Scripts>
|
||
</Button>
|
||
<Button name="BenillaCharacterModelFrameRotateRightButton">
|
||
<Size><AbsDimension x="35" y="35"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterModelFrameRotateLeftButton" relativePoint="TOPRIGHT"/></Anchors>
|
||
<NormalTexture file="Interface\Buttons\UI-RotationRight-Button-Up"/>
|
||
<PushedTexture file="Interface\Buttons\UI-RotationRight-Button-Down"/>
|
||
<HighlightTexture file="Interface\Buttons\ButtonHilight-Round" alphaMode="ADD"/>
|
||
<Scripts>
|
||
<OnLoad>self:RegisterForClicks("LeftButtonDown", "LeftButtonUp")</OnLoad>
|
||
<OnClick>BenillaPaperDollModel_RotateRight(getglobal("BenillaCharacterModelFrame"))</OnClick>
|
||
</Scripts>
|
||
</Button>
|
||
</Frames>
|
||
<Scripts>
|
||
<OnLoad>
|
||
-- A plain Frame isn't mouse-enabled by construction (this file's
|
||
-- header comment) — needed THIS phase (1b) so the pane hit-tests
|
||
-- as an OnMouseUp/OnReceiveDrag drop target (ref l.226-231).
|
||
self:EnableMouse(true)
|
||
BenillaPaperDollModel_OnLoad(self)
|
||
BenillaSetBoothTexture(getglobal(self:GetName() .. "Texture"), "paperdoll")
|
||
</OnLoad>
|
||
<!-- ref l.221-224: the pane drives the held-button spin every frame. -->
|
||
<OnUpdate>BenillaPaperDollModel_OnUpdate(self, arg1)</OnUpdate>
|
||
<OnMouseUp>BenillaPaperDollModel_OnMouseUp(self, arg1)</OnMouseUp>
|
||
<OnReceiveDrag>AutoEquipCursorItem()</OnReceiveDrag>
|
||
</Scripts>
|
||
</Frame>
|
||
|
||
<!-- The attributes block (ref CharacterAttributesFrame, l.274-405): 230x78 at
|
||
TOPLEFT (67,-291), the 9-piece UI-Character-StatBackground plate (3 stacked
|
||
3-piece columns: player-stat / melee / ranged) behind the rows. -->
|
||
<Frame name="BenillaCharacterAttributesFrame">
|
||
<Size><AbsDimension x="230" y="78"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="67" y="-291"/></Offset></Anchor></Anchors>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="BenillaPlayerStatBackgroundTop" file="Interface\PaperDollInfoFrame\UI-Character-StatBackground">
|
||
<Size><AbsDimension x="115" y="16"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT"/></Anchors>
|
||
<TexCoords left="0" right="0.8984375" top="0" bottom="0.125"/>
|
||
</Texture>
|
||
<Texture name="BenillaPlayerStatBackgroundMiddle" file="Interface\PaperDollInfoFrame\UI-Character-StatBackground">
|
||
<Size><AbsDimension x="115" y="53"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaPlayerStatBackgroundTop" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
<TexCoords left="0" right="0.8984375" top="0.125" bottom="0.1953125"/>
|
||
</Texture>
|
||
<Texture name="BenillaPlayerStatBackgroundBottom" file="Interface\PaperDollInfoFrame\UI-Character-StatBackground">
|
||
<Size><AbsDimension x="115" y="16"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaPlayerStatBackgroundMiddle" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
<TexCoords left="0" right="0.8984375" top="0.484375" bottom="0.609375"/>
|
||
</Texture>
|
||
<Texture name="BenillaMeleeAttackBackgroundTop" file="Interface\PaperDollInfoFrame\UI-Character-StatBackground">
|
||
<Size><AbsDimension x="115" y="16"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="115" y="0"/></Offset></Anchor></Anchors>
|
||
<TexCoords left="0" right="0.8984375" top="0" bottom="0.125"/>
|
||
</Texture>
|
||
<Texture name="BenillaMeleeAttackBackgroundMiddle" file="Interface\PaperDollInfoFrame\UI-Character-StatBackground">
|
||
<Size><AbsDimension x="115" y="12"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaMeleeAttackBackgroundTop" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
<TexCoords left="0" right="0.8984375" top="0.125" bottom="0.1953125"/>
|
||
</Texture>
|
||
<Texture name="BenillaMeleeAttackBackgroundBottom" file="Interface\PaperDollInfoFrame\UI-Character-StatBackground">
|
||
<Size><AbsDimension x="115" y="16"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaMeleeAttackBackgroundMiddle" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
<TexCoords left="0" right="0.8984375" top="0.484375" bottom="0.609375"/>
|
||
</Texture>
|
||
<Texture name="BenillaRangedAttackBackgroundTop" file="Interface\PaperDollInfoFrame\UI-Character-StatBackground">
|
||
<Size><AbsDimension x="115" y="16"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaMeleeAttackBackgroundBottom" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="2"/></Offset></Anchor></Anchors>
|
||
<TexCoords left="0" right="0.8984375" top="0" bottom="0.125"/>
|
||
</Texture>
|
||
<Texture name="BenillaRangedAttackBackgroundMiddle" file="Interface\PaperDollInfoFrame\UI-Character-StatBackground">
|
||
<Size><AbsDimension x="115" y="11"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaRangedAttackBackgroundTop" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
<TexCoords left="0" right="0.8984375" top="0.125" bottom="0.1953125"/>
|
||
</Texture>
|
||
<Texture name="BenillaRangedAttackBackgroundBottom" file="Interface\PaperDollInfoFrame\UI-Character-StatBackground">
|
||
<Size><AbsDimension x="115" y="16"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaRangedAttackBackgroundMiddle" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
<TexCoords left="0" right="0.8984375" top="0.484375" bottom="0.609375"/>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- The 5 primary attributes (ref l.407-491): TOPLEFT (6,-3), chained
|
||
BOTTOMLEFT-to-BOTTOMLEFT. Labels are the TEMPLATE's $parentLabel,
|
||
filled from Lua exactly like the ref (BenillaPaperDollFrame_OnLoad /
|
||
_SetStats — see the former's header comment); instances declare no
|
||
regions of their own, same as the ref's. -->
|
||
<Frame name="BenillaCharacterStatFrame1" inherits="BenillaStatRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="6" y="-3"/></Offset></Anchor></Anchors>
|
||
<Scripts>
|
||
<OnLoad>self:EnableMouse(true)</OnLoad>
|
||
<OnEnter>BenillaPaperDollStatTooltip(self, "STRENGTH")</OnEnter>
|
||
<OnLeave>GameTooltip:Hide()</OnLeave>
|
||
</Scripts>
|
||
</Frame>
|
||
<Frame name="BenillaCharacterStatFrame2" inherits="BenillaStatRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterStatFrame1" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
<Scripts>
|
||
<OnLoad>self:EnableMouse(true)</OnLoad>
|
||
<OnEnter>BenillaPaperDollStatTooltip(self, "AGILITY")</OnEnter>
|
||
<OnLeave>GameTooltip:Hide()</OnLeave>
|
||
</Scripts>
|
||
</Frame>
|
||
<Frame name="BenillaCharacterStatFrame3" inherits="BenillaStatRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterStatFrame2" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
<Scripts>
|
||
<OnLoad>self:EnableMouse(true)</OnLoad>
|
||
<OnEnter>BenillaPaperDollStatTooltip(self, "STAMINA")</OnEnter>
|
||
<OnLeave>GameTooltip:Hide()</OnLeave>
|
||
</Scripts>
|
||
</Frame>
|
||
<Frame name="BenillaCharacterStatFrame4" inherits="BenillaStatRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterStatFrame3" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
<Scripts>
|
||
<OnLoad>self:EnableMouse(true)</OnLoad>
|
||
<OnEnter>BenillaPaperDollStatTooltip(self, "INTELLECT")</OnEnter>
|
||
<OnLeave>GameTooltip:Hide()</OnLeave>
|
||
</Scripts>
|
||
</Frame>
|
||
<Frame name="BenillaCharacterStatFrame5" inherits="BenillaStatRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterStatFrame4" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
<Scripts>
|
||
<OnLoad>self:EnableMouse(true)</OnLoad>
|
||
<OnEnter>BenillaPaperDollStatTooltip(self, "SPIRIT")</OnEnter>
|
||
<OnLeave>GameTooltip:Hide()</OnLeave>
|
||
</Scripts>
|
||
</Frame>
|
||
<!-- Armor (ref l.492-511), chained off Stat5's BOTTOMLEFT. -->
|
||
<Frame name="BenillaCharacterArmorFrame" inherits="BenillaStatRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterStatFrame5" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
<Scripts>
|
||
<OnLoad>self:EnableMouse(true)</OnLoad>
|
||
<OnEnter>
|
||
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
|
||
GameTooltip:SetText(self.tooltip)
|
||
GameTooltip:AddLine(self.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1)
|
||
GameTooltip:Show()
|
||
</OnEnter>
|
||
<OnLeave>GameTooltip:Hide()</OnLeave>
|
||
</Scripts>
|
||
</Frame>
|
||
<!-- Melee attack rating (ref l.512-531), TOPLEFT of the attributes frame
|
||
itself (122,-2) — the second column's own chain root. -->
|
||
<Frame name="BenillaCharacterAttackFrame" inherits="BenillaStatRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterAttributesFrame" relativePoint="TOPLEFT"><Offset><AbsDimension x="122" y="-2"/></Offset></Anchor></Anchors>
|
||
<Scripts>
|
||
<OnLoad>self:EnableMouse(true)</OnLoad>
|
||
<OnEnter>
|
||
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
|
||
GameTooltip:SetText(ATTACK_TOOLTIP)
|
||
GameTooltip:AddLine(ATTACK_TOOLTIP_SUBTEXT, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1)
|
||
GameTooltip:Show()
|
||
</OnEnter>
|
||
<OnLeave>GameTooltip:Hide()</OnLeave>
|
||
</Scripts>
|
||
</Frame>
|
||
<!-- Melee attack power (ref l.532-554), 99px-wide override (OnLoad). -->
|
||
<Frame name="BenillaCharacterAttackPowerFrame" inherits="BenillaStatRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterAttackFrame" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="5" y="1"/></Offset></Anchor></Anchors>
|
||
<Scripts>
|
||
<OnLoad>self:EnableMouse(true); self:SetWidth(99)</OnLoad>
|
||
<OnEnter>
|
||
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
|
||
GameTooltip:SetText(self.tooltip)
|
||
GameTooltip:AddLine(self.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1)
|
||
GameTooltip:Show()
|
||
</OnEnter>
|
||
<OnLeave>GameTooltip:Hide()</OnLeave>
|
||
</Scripts>
|
||
</Frame>
|
||
<!-- Melee damage (ref l.555-574), 99px-wide override, dedicated OnEnter. -->
|
||
<Frame name="BenillaCharacterDamageFrame" inherits="BenillaStatRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterAttackPowerFrame" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="1"/></Offset></Anchor></Anchors>
|
||
<Scripts>
|
||
<OnLoad>self:EnableMouse(true); self:SetWidth(99)</OnLoad>
|
||
<OnEnter>BenillaCharacterDamageFrame_OnEnter(self)</OnEnter>
|
||
<OnLeave>GameTooltip:Hide()</OnLeave>
|
||
</Scripts>
|
||
</Frame>
|
||
<!-- Ranged attack rating (ref l.575-594). -->
|
||
<Frame name="BenillaCharacterRangedAttackFrame" inherits="BenillaStatRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterDamageFrame" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="-6"/></Offset></Anchor></Anchors>
|
||
<Scripts>
|
||
<OnLoad>self:EnableMouse(true)</OnLoad>
|
||
<OnEnter>
|
||
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
|
||
GameTooltip:SetText(RANGED_ATTACK_TOOLTIP)
|
||
GameTooltip:AddLine(ATTACK_TOOLTIP_SUBTEXT, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1)
|
||
GameTooltip:Show()
|
||
</OnEnter>
|
||
<OnLeave>GameTooltip:Hide()</OnLeave>
|
||
</Scripts>
|
||
</Frame>
|
||
<!-- Ranged attack power (ref l.595-619), 99px-wide, conditional tooltip
|
||
(the N/A / wand-equipped states leave self.tooltip nil). -->
|
||
<Frame name="BenillaCharacterRangedAttackPowerFrame" inherits="BenillaStatRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterRangedAttackFrame" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="5" y="1"/></Offset></Anchor></Anchors>
|
||
<Scripts>
|
||
<OnLoad>self:EnableMouse(true); self:SetWidth(99)</OnLoad>
|
||
<OnEnter>
|
||
if self.tooltip then
|
||
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
|
||
GameTooltip:SetText(self.tooltip)
|
||
GameTooltip:AddLine(self.tooltipSubtext, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1)
|
||
GameTooltip:Show()
|
||
end
|
||
</OnEnter>
|
||
<OnLeave>GameTooltip:Hide()</OnLeave>
|
||
</Scripts>
|
||
</Frame>
|
||
<!-- Ranged damage (ref l.620-639), 99px-wide, dedicated OnEnter (no-ops
|
||
while self.damage is nil, e.g. no ranged weapon equipped). -->
|
||
<Frame name="BenillaCharacterRangedDamageFrame" inherits="BenillaStatRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterRangedAttackPowerFrame" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="1"/></Offset></Anchor></Anchors>
|
||
<Scripts>
|
||
<OnLoad>self:EnableMouse(true); self:SetWidth(99)</OnLoad>
|
||
<OnEnter>BenillaCharacterRangedDamageFrame_OnEnter(self)</OnEnter>
|
||
<OnLeave>GameTooltip:Hide()</OnLeave>
|
||
</Scripts>
|
||
</Frame>
|
||
</Frames>
|
||
</Frame>
|
||
|
||
<!-- The 5 magic-resistance frames (ref CharacterResistanceFrame, l.642-760):
|
||
32x160 wrapper, TOPRIGHT of PaperDollFrame's own TOPLEFT (297,-77); each
|
||
32x29 icon TOP-chained off the previous, ids 6/2/3/4/5 (arcane/fire/nature/
|
||
frost/shadow — Holy(1) never rides the paper doll). -->
|
||
<Frame name="BenillaCharacterResistanceFrame">
|
||
<Size><AbsDimension x="32" y="160"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPRIGHT" relativeTo="BenillaPaperDollFrame" relativePoint="TOPLEFT"><Offset><AbsDimension x="297" y="-77"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Frames>
|
||
<Frame name="BenillaMagicResFrame1" inherits="BenillaMagicResistanceFrameTemplate">
|
||
<Anchors><Anchor point="TOP" relativeTo="BenillaCharacterResistanceFrame" relativePoint="TOP"/></Anchors>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture file="Interface\PaperDollInfoFrame\UI-Character-ResistanceIcons">
|
||
<TexCoords left="0" right="1.0" top="0.2265625" bottom="0.33984375"/>
|
||
</Texture>
|
||
<FontString name="BenillaMagicResText1" inherits="GameFontHighlightSmall" text="X">
|
||
<Anchors><Anchor point="BOTTOM"><Offset><AbsDimension x="0" y="3"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
</Frame>
|
||
<Frame name="BenillaMagicResFrame2" inherits="BenillaMagicResistanceFrameTemplate">
|
||
<Anchors><Anchor point="TOP" relativeTo="BenillaMagicResFrame1" relativePoint="BOTTOM"/></Anchors>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture file="Interface\PaperDollInfoFrame\UI-Character-ResistanceIcons">
|
||
<TexCoords left="0" right="1.0" top="0" bottom="0.11328125"/>
|
||
</Texture>
|
||
<FontString name="BenillaMagicResText2" inherits="GameFontHighlightSmall" text="X">
|
||
<Anchors><Anchor point="BOTTOM"><Offset><AbsDimension x="0" y="3"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
</Frame>
|
||
<Frame name="BenillaMagicResFrame3" inherits="BenillaMagicResistanceFrameTemplate">
|
||
<Anchors><Anchor point="TOP" relativeTo="BenillaMagicResFrame2" relativePoint="BOTTOM"/></Anchors>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture file="Interface\PaperDollInfoFrame\UI-Character-ResistanceIcons">
|
||
<TexCoords left="0" right="1.0" top="0.11328125" bottom="0.2265625"/>
|
||
</Texture>
|
||
<FontString name="BenillaMagicResText3" inherits="GameFontHighlightSmall" text="X">
|
||
<Anchors><Anchor point="BOTTOM"><Offset><AbsDimension x="0" y="3"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
</Frame>
|
||
<Frame name="BenillaMagicResFrame4" inherits="BenillaMagicResistanceFrameTemplate">
|
||
<Anchors><Anchor point="TOP" relativeTo="BenillaMagicResFrame3" relativePoint="BOTTOM"/></Anchors>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture file="Interface\PaperDollInfoFrame\UI-Character-ResistanceIcons">
|
||
<TexCoords left="0" right="1.0" top="0.33984375" bottom="0.453125"/>
|
||
</Texture>
|
||
<FontString name="BenillaMagicResText4" inherits="GameFontHighlightSmall" text="X">
|
||
<Anchors><Anchor point="BOTTOM"><Offset><AbsDimension x="0" y="3"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
</Frame>
|
||
<Frame name="BenillaMagicResFrame5" inherits="BenillaMagicResistanceFrameTemplate">
|
||
<Anchors><Anchor point="TOP" relativeTo="BenillaMagicResFrame4" relativePoint="BOTTOM"/></Anchors>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture file="Interface\PaperDollInfoFrame\UI-Character-ResistanceIcons">
|
||
<TexCoords left="0" right="1.0" top="0.453125" bottom="0.56640625"/>
|
||
</Texture>
|
||
<FontString name="BenillaMagicResText5" inherits="GameFontHighlightSmall" text="X">
|
||
<Anchors><Anchor point="BOTTOM"><Offset><AbsDimension x="0" y="3"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
</Frame>
|
||
</Frames>
|
||
</Frame>
|
||
|
||
<!-- The 19 equipment slots (ref l.761-931): left column TOPLEFT (21,-74) chained
|
||
BOTTOMLEFT -4, right column TOPLEFT (305,-74) chained the same way, the
|
||
weapon row off the page's own BOTTOMLEFT (122,127) then chained TOPRIGHT +5. -->
|
||
<Button name="BenillaCharacterHeadSlot" inherits="BenillaPaperDollItemSlotTemplate">
|
||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="21" y="-74"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaPaperDollSlot_OnLoad(self, "HeadSlot")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaCharacterNeckSlot" inherits="BenillaPaperDollItemSlotTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterHeadSlot" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaPaperDollSlot_OnLoad(self, "NeckSlot")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaCharacterShoulderSlot" inherits="BenillaPaperDollItemSlotTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterNeckSlot" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaPaperDollSlot_OnLoad(self, "ShoulderSlot")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaCharacterBackSlot" inherits="BenillaPaperDollItemSlotTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterShoulderSlot" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaPaperDollSlot_OnLoad(self, "BackSlot")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaCharacterChestSlot" inherits="BenillaPaperDollItemSlotTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterBackSlot" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaPaperDollSlot_OnLoad(self, "ChestSlot")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaCharacterShirtSlot" inherits="BenillaPaperDollItemSlotTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterChestSlot" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaPaperDollSlot_OnLoad(self, "ShirtSlot")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaCharacterTabardSlot" inherits="BenillaPaperDollItemSlotTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterShirtSlot" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaPaperDollSlot_OnLoad(self, "TabardSlot")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaCharacterWristSlot" inherits="BenillaPaperDollItemSlotTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterTabardSlot" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaPaperDollSlot_OnLoad(self, "WristSlot")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaCharacterHandsSlot" inherits="BenillaPaperDollItemSlotTemplate">
|
||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="305" y="-74"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaPaperDollSlot_OnLoad(self, "HandsSlot")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaCharacterWaistSlot" inherits="BenillaPaperDollItemSlotTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterHandsSlot" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaPaperDollSlot_OnLoad(self, "WaistSlot")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaCharacterLegsSlot" inherits="BenillaPaperDollItemSlotTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterWaistSlot" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaPaperDollSlot_OnLoad(self, "LegsSlot")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaCharacterFeetSlot" inherits="BenillaPaperDollItemSlotTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterLegsSlot" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaPaperDollSlot_OnLoad(self, "FeetSlot")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaCharacterFinger0Slot" inherits="BenillaPaperDollItemSlotTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterFeetSlot" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaPaperDollSlot_OnLoad(self, "Finger0Slot")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaCharacterFinger1Slot" inherits="BenillaPaperDollItemSlotTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterFinger0Slot" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaPaperDollSlot_OnLoad(self, "Finger1Slot")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaCharacterTrinket0Slot" inherits="BenillaPaperDollItemSlotTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterFinger1Slot" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaPaperDollSlot_OnLoad(self, "Trinket0Slot")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaCharacterTrinket1Slot" inherits="BenillaPaperDollItemSlotTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterTrinket0Slot" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaPaperDollSlot_OnLoad(self, "Trinket1Slot")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaCharacterMainHandSlot" inherits="BenillaPaperDollItemSlotTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="122" y="127"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaPaperDollSlot_OnLoad(self, "MainHandSlot")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaCharacterSecondaryHandSlot" inherits="BenillaPaperDollItemSlotTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterMainHandSlot" relativePoint="TOPRIGHT"><Offset><AbsDimension x="5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaPaperDollSlot_OnLoad(self, "SecondaryHandSlot")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaCharacterRangedSlot" inherits="BenillaPaperDollItemSlotTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaCharacterSecondaryHandSlot" relativePoint="TOPRIGHT"><Offset><AbsDimension x="5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaPaperDollSlot_OnLoad(self, "RangedSlot")</OnLoad></Scripts>
|
||
</Button>
|
||
|
||
<!-- The ammo slot (ref CharacterAmmoSlot, l.932-1043): 27x27, LEFT of the ranged
|
||
slot's RIGHT (+15,0). NOT built from the shared slot template — its own
|
||
hand-authored art (a pouch background + a corner-accent overlay cut from the
|
||
same sheet, no Quickslot2 ring) — but reuses the SAME Lua as the 19 named
|
||
slots (this file's header comment: the ref shares PaperDollItemSlotButton_*
|
||
verbatim here too, keyed off "AmmoSlot"). $parentCount's hidden="true" (ref
|
||
default) is DROPPED — every other count fontstring in this codebase (Bag/
|
||
Merchant/this file's own template) uses the same "blank text = invisible"
|
||
idiom with no Show/Hide dance, applied here too for consistency.
|
||
$parentStock OMITTED (this file's header comment: no ref Lua populates it). -->
|
||
<Button name="BenillaCharacterAmmoSlot">
|
||
<Size><AbsDimension x="27" y="27"/></Size>
|
||
<Anchors>
|
||
<Anchor point="LEFT" relativeTo="BenillaCharacterRangedSlot" relativePoint="RIGHT"><Offset><AbsDimension x="15" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture file="Interface\PaperdollInfoFrame\UI-Character-AmmoSlot">
|
||
<Size><AbsDimension x="41" y="41"/></Size>
|
||
<Anchors><Anchor point="CENTER"/></Anchors>
|
||
<TexCoords left="0" right="0.640625" top="0" bottom="0.640625"/>
|
||
</Texture>
|
||
</Layer>
|
||
<Layer level="BORDER">
|
||
<Texture name="$parentIconTexture"/>
|
||
<FontString name="$parentCount" inherits="NumberFontNormal" justifyH="RIGHT">
|
||
<Anchors><Anchor point="BOTTOMRIGHT"><Offset><AbsDimension x="-1" y="2"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
<Layer level="OVERLAY">
|
||
<Texture file="Interface\PaperdollInfoFrame\UI-Character-AmmoSlot">
|
||
<Size><AbsDimension x="23" y="41"/></Size>
|
||
<Anchors><Anchor point="CENTER"><Offset><AbsDimension x="-22" y="0"/></Offset></Anchor></Anchors>
|
||
<TexCoords left="0.640625" right="1.0" top="0" bottom="0.640625"/>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<Scripts>
|
||
<OnLoad>BenillaPaperDollSlot_OnLoad(self, "AmmoSlot")</OnLoad>
|
||
<OnEnter>BenillaPaperDollSlot_OnEnter(self)</OnEnter>
|
||
<OnLeave>GameTooltip:Hide()</OnLeave>
|
||
<OnEvent>BenillaPaperDollSlot_OnEvent(self)</OnEvent>
|
||
<OnUpdate>BenillaPaperDollSlot_OnUpdate(self)</OnUpdate>
|
||
<!-- Ammo loads by SET_AMMO, not the equip-swap wire (decision 0526):
|
||
click-to-place and drag-drop both route to the ammo handler. -->
|
||
<OnClick>BenillaCharacterAmmoSlot_OnClick(self)</OnClick>
|
||
<OnReceiveDrag>BenillaCharacterAmmoSlot_OnClick(self)</OnReceiveDrag>
|
||
</Scripts>
|
||
</Button>
|
||
</Frames>
|
||
<Scripts>
|
||
<OnLoad>BenillaPaperDollFrame_OnLoad(self)</OnLoad>
|
||
<OnEvent>BenillaPaperDollFrame_OnEvent(self)</OnEvent>
|
||
<OnShow>BenillaPaperDollFrame_OnShow()</OnShow>
|
||
</Scripts>
|
||
</Frame>
|
||
</Frames>
|
||
<Scripts>
|
||
<OnLoad>BenillaCharacterFrame_OnLoad(self)</OnLoad>
|
||
<OnShow>BenillaCharacterFrame_OnShow()</OnShow>
|
||
<OnHide>BenillaCharacterFrame_OnHide()</OnHide>
|
||
</Scripts>
|
||
</Frame>
|
||
</Ui>
|