v1.0.0
Rune Reminder Reforged
v1.0.0 (2026-08-05)
Full Changelog Previous Releases
- Add X-Curse-Project-ID for the new CurseForge listing
Project 1640798 -- a distinct, newly-created CurseForge project for
this addon, not the old fork's 1639190. - Fix Back slot showing "Ranged" (and picker/tooltip wrong-category bugs)
Paperdoll slot positions (INVSLOT_*, used by GetRuneForEquipmentSlot /
GetInventoryItemCooldown) and item equip-location types
(Enum.InventoryType, used by GetRunesForCategory and
C_Item.GetItemInventorySlotInfo) are two different numbering schemes.
They share values 1-11 (Head..Finger) but diverge after that:
INVSLOT_BACK=15 while Enum.InventoryType.IndexCloakType=16, and
Enum.InventoryType.IndexRangedType happens to equal 15 -- so passing
the paperdoll Back slot into a function expecting InventoryType
returned "Ranged" for its category/name instead of "Back". Confirmed
against Blizzard_APIDocumentationGenerated/ItemConstantsDocumentation.lua.
Added an explicit PAPERDOLL_TO_INVTYPE mapping (Finger1 and Finger2
both collapse to the single IndexFingerType category -- rings aren't
distinguished by which of the two slots they're in for this purpose)
and a shared RRR:GetSlotDisplayName(slot) helper, used by:- GetRunesForSlot (was passing the raw paperdoll slot into
GetRunesForCategory -- the picker's rune list itself) - Core/Notify.lua's RuneMismatch chat message
- UI/Widget.lua's slot-button tooltip (this is what showed "Ranged"
for the Back button)
Also simplified RUNE_UPDATED to always do a full RefreshAllRunes():
rune.equipmentSlot is likewise an InventoryType, not a paperdoll slot,
and since Finger1/Finger2 share one category there's no reliable way
to map it back to which specific tracked slot changed.
- GetRunesForSlot (was passing the raw paperdoll slot into
- Fix all-empty widget: call C_Engraving.RefreshRunesList before querying
GetRuneForEquipmentSlot returned nil for every tracked slot, even ones
with a real engraved rune equipped. Blizzard's own EngravingFrame_OnShow
(Blizzard_EngravingUI.lua) always calls C_Engraving.RefreshRunesList()
before querying any rune data or calling EngravingFrame_UpdateRuneList --
added the same call in InitEngraving (login) and RefreshAllRunes
(PLAYER_ENTERING_WORLD/RUNE_UPDATED with nil rune), matching Blizzard's
usage pattern rather than calling it on every event (their own
PLAYER_EQUIPMENT_CHANGED handler doesn't re-call it either). - Show a fixed set of slots instead of gating on IsEquipmentSlotEngravable
C_Engraving.IsEquipmentSlotEngravable reflects whether the CURRENTLY
EQUIPPED ITEM in a slot is engravable, not whether the slot category
is part of the system in general (Blizzard's own paperdoll code uses
it exactly that way). Gating which widget buttons exist on that call
meant the whole widget could show nothing at all whenever none of the
player's current gear happened to test as engravable at that instant
-- which is exactly what happened after a full client restart.
Since the 9 valid SoD engraving categories are already researched and
fixed (see the comment in Core/Engraving.lua), just always show those
10 slot IDs and use the API only for the rune data itself (which is
correctly nilable for "no rune"/nothing equipped), not for deciding
which buttons exist. A reminder widget should have a stable set of
slots rather than buttons appearing and disappearing with gear swaps.
Removed the now-dead slot-set-change-detection machinery this enabled
cutting: RefreshSlotList's "changed" bool, RebuildWidgetSlots, and the
rebuild-vs-refresh branching in PLAYER_EQUIPMENT_CHANGED. Replaced with
a simpler RefreshAllRunes() used by PLAYER_ENTERING_WORLD/RUNE_UPDATED
(nil rune) to force a full cache/UI refresh after a loading screen. - Fix slot discovery list against confirmed SoD engraving categories
C_Engraving.IsEquipmentSlotEngravable isn't reliable enough on its own
to decide which slot categories to probe -- it returned true for
INVSLOT_RANGED despite ranged weapons not being part of SoD's
engraving system. Researched the actual slot list (Icy Veins' SoD rune
overview, cross-checked against a Wowhead datamining article): exactly
9 categories -- chest, gloves, legs, waist, feet, head, wrist, back,
and ring -- explicitly excluding shoulder, neck, trinkets, and weapons.
Narrowed ALL_SLOTS to Head/Back/Chest/Wrist/Hand/Waist/Legs/Feet/
Finger1/Finger2 (10 slot IDs covering the 9 categories, since Ring
spans both physical finger slots). Previously included Neck and
Shoulder, which are explicitly NOT part of the system per this source
-- corrects an earlier over-inclusive guess from this same session. - Combine Alignment + Flyout direction into one Layout dropdown
Replaces the two separate dropdowns with a single "Layout" control
offering exactly the 4 sensible combinations: Vertical widget with
flyout left/right, or Horizontal widget with flyout up/down --
eliminating the nonsensical pairings (e.g. horizontal widget with a
left/right flyout) the two independent dropdowns allowed.
Underlying storage unchanged (widget.alignment / widget.flyoutDirection
are still two separate fields, encoded as one "ALIGNMENT_DIRECTION"
string for the dropdown's get/set); Widget.lua and Picker.lua need no
changes since they already read those two fields independently. - Add explicit Flyout direction option (Up/Down/Left/Right)
Replaces the automatic perpendicular-to-widget-alignment flyout
orientation with a single user-facing dropdown offering all 4
directions directly, independent of widget alignment. Added
widget.flyoutDirection to defaults (default "UP", matching prior
behavior for the default horizontal widget) and a matching Options
dropdown next to Alignment. - Flyout orientation now perpendicular to widget alignment
Horizontal widget -> vertical flyout (stacked above the clicked slot,
growing upward). Vertical widget -> horizontal flyout. Avoids the
flyout running parallel to and blending into the slot-button row/column
it's anchored next to. - Replace dropdown-menu picker with a bare icon-row flyout
The Blizzard UIDropDownMenuTemplate picker rendered as a large boxed
text list, visually inconsistent with the widget's own bare-icon row
style. Replaced with a small flyout of plain icon buttons (same visual
construction as the widget's slot buttons: per-icon dark background
square, no outer panel/box), anchored above the clicked slot button.
Each icon shows the rune's name on hover via GameTooltip. Clicking the
same slot again toggles the flyout closed; clicking a different slot
repopulates and repositions it. No more UIDropDownMenu dependency in
the picker (Options.lua's small Alignment dropdown is unrelated and
unchanged). - Fix invisible widget on login: re-scan slots on PLAYER_ENTERING_WORLD
PLAYER_LOGIN can fire before equipment/engraving data is fully synced
from the server, so InitEngraving's initial scan could find zero
engravable slots -- an empty, invisible widget (no visible chrome on
the container itself, only child slot buttons render anything).
Force a full slot re-scan and rune re-fetch on PLAYER_ENTERING_WORLD
and rebuild the widget unconditionally, so it's guaranteed to reflect
reality once the world is actually entered, regardless of what the
early PLAYER_LOGIN scan found. - Fix crash on login: guard picker init against no slot selected yet
UIDropDownMenu_Initialize calls initFunction(frame, level, menuList)
immediately during setup, not just lazily when the menu is opened
(confirmed at Blizzard_SharedXML/Classic/UIDropDownMenu.lua:84). At
that point no slot has ever been clicked, so currentSlot was nil,
and C_Engraving.GetRunesForCategory(nil, true) errored with "bad
argument #1" on every login. - Initial commit: Rune Reminder Reforged v1.0.0
A from-scratch, original addon for WoW Classic Season of Discovery that
tracks engraved runes per equipment slot, provides a one-click picker to
engrave a different rune, and prints a chat reminder when a gear swap
changes or clears a tracked slot's rune.
This is a clean-room rewrite, not a fork: written directly against
Blizzard's C_Engraving API (researched fresh from a local wow-ui-source
client-source checkout, cross-checked against Blizzard_EngravingUI.lua
and PaperDollFrame.lua) rather than any existing addon. It replaces an
earlier fork of a third-party "All Rights Reserved" addon that CurseForge
declined to host on licensing grounds (that fork is now private and
undistributed).
Deliberately smaller in scope than what it replaces: no saved rune-set
loadouts, no profiles, no Masque support, no popups (chat notification
only), no custom font/color/texture/glow customization -- just live
per-slot tracking, a simple native-dropdown picker, cooldown display,
and a draggable minimal widget. English only for v1.
Structure mirrors this workspace's other from-scratch addons
(EasyMount's Core/+UI/ split, HoneyLock's zero-dependency native
Settings-API options pattern, RaidNamesCopy's click+drag button
convention) rather than the addon it replaces.