promotional bannermobile promotional banner

Slotcast

Click-cast from your action bar: bind a mouse click to an action bar slot, and whatever spell you drag into that slot becomes the click
Back to Files

2.8.7

File nameSlotCast-2.8.7.zip
Uploader
terrafirma91terrafirma91
Uploaded
Oct 6, 2026
Downloads
7
Size
70.8 KB
Flavors
RetailForever
File ID
9080187
Type
R
Release
Supported game versions
  • 12.1.0
  • 12.0.0
  • 11.2.0
  • 1.60.1

What's new

SlotCast

2.8.7 (2026-10-04)

Full Changelog Previous Releases

  • Add CurseForge project ID to the TOC
    Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
  • Add project logo; keep art/ out of the packaged addon
    Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
  • Add tag-triggered packager workflow for CurseForge releases
    Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
  • Restore the Author line
    Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
  • Ignore dist/
    Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
  • Drop the Author line from the TOC for public release
    Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
  • Add WoW Forever's interface version (16001) to the TOC
    A Forever beta update started rejecting SlotCast as incompatible, even with
    "Load out of date AddOns" on: the TOC listed only retail versions newer than
    the client. 2.8.7.
    Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
  • Switch to the spellbook tab after opening Click Bindings
    WoW Forever's beta opens the spells window on Talents whichever way Click
    Bindings is opened, leaving nothing to drag spells from. Calling
    PlayerSpellsUtil.OpenToSpellBookTab() afterwards was confirmed in game to
    fix it, and is a no-op where the bug is absent. 2.8.6.
    Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
  • Open Click Bindings via ToggleClickBindingFrame first
    Blizzard's own opener load-on-demands the UI and needs no chat-box
    borrowing. It toggles, so an already-open window is detected first rather
    than closed. /clickcasting and the frame pokes remain as fallbacks. 2.8.5.
    Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
  • Offer rank/max for the top rank too; re-check ranks when a spell is learned
    A slot holding your best rank now gets the same R3/max toggle as a lower
    rank: identical today, but R3 stays on Rank 3 and max moves to Rank 4 once
    it is learned. The rank verdict cache was never wiped, so learning a rank
    would not have been noticed until /reload. Bump to 2.8.4.
    Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
  • Show the highest rank on the rank button instead of "-"
    A slot holding your best rank greyed out with a "no ranks" tooltip, which
    read as broken. It now shows the rank (e.g. R3), still disabled, and says
    it's the same spell as max until a higher rank is learned. Bump to 2.8.3.
    Also corrects the backstop comment: the Forever probe (1.60.1) shows the
    name test works there; Rank 2 resolved to its own id.
    Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
  • probe: trace the rank decision for each bar spell
    Prints SpellRank, what the bare name resolves to and its subtext, and the
    running version, so a greyed-out rank button points at the test that failed.
    Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
  • Bump version to 2.8.2
    Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
  • Detect lower ranks by the slot's spell id, not just the name parser
    WoW Forever resolves "Healing Wave(Rank 3)" to the top rank's id, so the
    name test called every rank flavour text and a Rank 3 slot cast max rank
    with the rank toggle hidden. A slot holding a different spell than the bare
    name resolves to, with a different rank subtext, is now a real rank.
    Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
  • Only defer, and only warn, when something actually changed
    "binding change held until you leave combat" fired on any refresh that
    happened during combat, and plenty of events land there for reasons
    unrelated to bindings: roster updates, spell overrides, macro edits. The
    message was accurate about the deferral and wrong about the cause.
    DoRefresh now builds the plan first -- building only reads, so it is safe
    in combat -- and compares a sorted signature of it, plus the settings
    that affect frame writes, against what was last applied. Identical means
    return silently. Nothing is deferred and nothing is announced unless the
    result would genuinely differ.
    Also skips the secure writes entirely out of combat when nothing changed,
    and adds /slotcast quiet for anyone who wants the notice gone regardless.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Add bar click labels, enemy-frame skipping, and a stop-casting option
    Three opt-in behaviours:
    • Labels.lua draws each slot's click on the action button itself, so the
      bar documents its own grid. Decorative only -- no attributes, no
      secure code -- and the font falls back if the narrow one is missing.
    • Enemy-ish frames (target, focus, boss, arena) can be left alone, since
      a heal aimed at a boss frame burns a click and sometimes a global.
      Excluded frames are actively restored, so the toggle takes effect at
      once rather than at the next reload.
    • /stopcasting can be prepended so a click-cast interrupts the cast in
      progress instead of being swallowed by it.
      Clique ships eight per-group frame toggles; one switch covers the case
      people actually have and costs a fraction of the panel space.
      Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Stop the recommendation callout clipping its own text
    The box was sized for two lines and the text ran to three, so it cut off
    mid-word. Box and label are taller, everything below shifts to match,
    and the copy is trimmed to two lines -- the reasoning already sits in
    the alignment line directly beneath it and in the Map button's tooltip,
    so the callout only needs to be the nudge.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Make the vertical-bar recommendation read as one
    A tip set in the same grey as the surrounding explanation is not a tip.
    The horizontal-bar nudge and the reshaped-bar warning now sit in a
    tinted callout with a coloured edge -- amber for the recommendation, red
    for the warning -- and lead with the problem before the fix.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Give the panel room, and lead the grid with what it means
    The two blocks that grow -- the warning list and the conflict list --
    were spaced for their empty state, so a couple of messages ran into the
    section below. Both now have room to grow into and a fixed height so
    they clip rather than overlap. Wrapped text gets line spacing, and the
    hints are shortened, with the detail left in the tooltips where it
    already was.
    The line describing what the grid means sat below the grid, which is the
    wrong order: it now reads "Current grid alignment: 3 wide x 4 tall.
    Columns are Left / Middle / Right; rows are none / Shift / Ctrl / Alt"
    directly above the picture it describes, under the vertical-bar tip.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Open Edit Mode rather than rewriting the user's layout
    Adds an Open Edit Mode button next to the grid controls, and a probe
    section reporting which Edit Mode APIs exist so the question of whether
    orientation is settable from code can be answered with evidence.
    Opening rather than setting is a deliberate choice independent of what
    the API allows: a bar's orientation lives in the player's saved UI
    layout, which is shared across characters and often carefully arranged.
    Rewriting that to suit one addon's preferred grid is not a trade an
    addon gets to make on someone's behalf.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Recommend a vertical bar for the grid mapping
    Both orientations work, but only one reads well: a vertical bar three
    columns wide puts Left / Middle / Right across the top and the modifiers
    down the side, matching how a mouse is laid out. A wide bar puts the
    mouse buttons on the rows, so left and right run downwards -- correct,
    and confusing to look at.
    Say so where it is useful: in the slot hint, in the Map button tooltip,
    and as a prompt on the preview itself when the bar is wider than it is
    tall. The README leads with it.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Draw the click mapping, and warn when the bar was reshaped
    Reported symptom: switching a bar from vertical to horizontal swaps
    left and right clicks. That is the mapping working as designed and being
    impossible to reason about -- the shape change moves every slot to a
    different cell AND flips which axis carries the mouse buttons, so the
    same spell lands on a different click.
    Explaining that in prose did not land twice, so draw it: a grid of cells
    under the slot list showing the click each position gets, read from the
    live bindings rather than recomputed so the picture cannot disagree with
    the behaviour. Flip the bar and the picture flips with it.
    Also remember the shape a mapping was made for, and say plainly when the
    bar no longer matches it, instead of leaving it looking like the
    bindings scrambled themselves.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • State the whole grid mapping, not just which axis wins
    Two different Edit Mode settings can produce the same shape with the
    slots filled in differently inside it: horizontal with 4 rows and
    vertical with 3 rows are both 3x4. The mapping is positional, measured
    from where buttons actually sit, so both map correctly -- but "columns
    are buttons" does not tell anyone what a click will do.
    The panel now spells it out: "3 wide x 4 tall - columns are Left /
    Middle / Right, rows are none / Shift / Ctrl / Alt", following the
    L/M/R order setting. The probe prints the click each slot ended up with
    alongside its cell, so the result can be read off rather than inferred.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Open Click Bindings through the chat parser as a last resort
    /clickcasting works when typed but is not a SLASH_ global on Forever, so
    the SlashCmdList lookup found nothing and the button did nothing.
    Try SlashCmdList, then SecureCmdList, then hand the text to
    ChatEdit_SendText exactly as if it had been typed. The parser knows
    about commands that are not exposed as globals at all, which is why
    typing it works when looking it up does not.
    The probe now reports which route a command was found on.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Work out grid orientation instead of asking about it
    The columns/rows toggle asked the user to answer something the addon
    already had the data for: GridLayout returns the shape, so orientation
    was there all along.
    Mouse buttons are scarce (three comfortable, five at most) and modifier
    combinations are plentiful (eight), so the shorter axis carries the
    buttons. That reads a 3-wide and a 3-tall bar correctly with no setting.
    The toggle becomes a label that states what was picked, and
    /slotcast grid cols|rows forces it.
    Shapes with no usable axis -- a single line of twelve, or a grid too big
    on both sides -- now map in reading order rather than being skipped,
    which is a case the old axis-only logic handled badly.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Explain the Click Bindings handoff with a dialog
    Clicking the Target or Unit menu row now opens WoW's Click Bindings and
    puts a dialog in front of it saying what to do there: bind ONLY Target
    Unit Frame and Open Context Menu, then Save. Without that, landing in an
    unfamiliar window with no explanation is its own kind of broken.
    The warning against binding spells there matters as much as the
    instruction -- two systems on one click is the failure this whole area
    has been about.
    Dialog is hand-rolled rather than StaticPopup, for the same reason as
    the rest of the UI, and remembers being dismissed. /slotcast blizz
    manual brings it back, since asking for it is an explicit request.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Open Blizzard's click bindings via /clickcasting
    Guessing at frame names was the wrong approach: that UI has been rebuilt
    more than once, while the slash command has not. Look the command up in
    SlashCmdList by its text and invoke whatever handler the client filed it
    under, falling back to the frame candidates only if that fails.
    The printed steps now name /clickcasting too, so the manual route works
    even when nothing can be opened programmatically.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Show Blizzard's Target/Unit menu bindings instead of offering our own
    Those two actions belong to the game's click-binding system now. Binding
    them in SlotCast silently did nothing AND blocked the binding that would
    have worked, which is the worst of both.
    So SlotCast stops competing: on a client with that system, the Target
    and Unit menu rows become read-only, showing what is actually bound
    there, and clicking one opens Blizzard's UI and prints the steps.
    "/slotcast blizz off" takes them back for a client where that system
    does not exist.
    Removes the profile-writing path entirely -- 103 lines that never took
    on 12.1 -- along with the modifier-bitfield capture that only existed to
    feed it. A read-only mirror of the real setting is both honest and
    simpler than trying to own someone else's config.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Add a manual route for the unit menu, and verify the automatic one
    Writing Blizzard's profile is the convenient path, not the reliable one,
    and it is still not taking on 12.1. So make the route that always works
    easy to reach: a button that opens Blizzard's Click Bindings UI and
    prints the steps, plus /slotcast blizz manual.
    SyncDelegated now reads the profile back after writing and reports
    failure if the entry did not survive. SetProfileByInfo returning without
    error was never evidence that it took, which is why this looked like
    silence rather than a refusal.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Hand Target and Unit menu to Blizzard's click bindings
    Unit menus moved to C_ClickBindings, which an addon cannot drive from a
    secure attribute -- but can write to. So for the actions that system now
    owns, write the binding into its profile and stop binding the click
    ourselves: our specific attribute would otherwise override the wildcard
    one their binding produces, which is the whole reason it looked broken.
    • The modifier bitfield's encoding is undocumented, so it is captured
      from the client via MakeModifiers() at the moment the user holds the
      keys rather than reconstructed.
    • SetProfileByInfo replaces the whole profile, so the current one is
      read first and everything that is not ours is preserved. Entries we
      wrote are tracked by button+modifiers so they can be removed when a
      binding changes.
    • The sync is idempotent and skips the write entirely when the profile
      already matches, so it can run on every refresh without churning
      someone else's settings.
      /slotcast blizz off|menu|both, or the button in the panel.
      Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Say plainly when the unit menu cannot be bound
    togglemenu fails on 12.1 as well as menu, so there is no secure action
    type left that opens a unit menu: it moved to C_ClickBindings, which an
    addon cannot invoke from an attribute.
    Detect that and say so in the panel, pointing at Blizzard's own Click
    Bindings -- which does support modifiers, and which works on a click
    SlotCast leaves unbound. A binding that silently does nothing is worse
    than an absent one, and it also blocks the binding that would have
    worked.
    check now lists the surviving menu APIs so a real fix can be based on
    what exists rather than on another guess.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Fix Target and Unit menu on 12.1
    check on PlayerFrame showed the attributes landing perfectly while the
    clicks did nothing, and frame.menu = nil was the giveaway.
    "menu" is not a generic action type: SecureUnitButton_OnClick
    special-cases it and calls frame.menu(). On 12.1 the frames still carry
    "*type2 = menu" but have no menu function -- the real right-click menu
    comes from C_ClickBindings -- so the attribute advertises a handler that
    no longer exists and the click falls through to a generic handler that
    has never heard of "menu". Detection now requires the function, not the
    attribute, and falls back to togglemenu. /slotcast menuverb overrides it.
    target, focus and assist now always use their macro forms rather than
    only on the press stroke. Those built-in action types are vestigial in
    the same way -- 12.1 advertises "*type1 = target" while targeting
    actually comes from C_ClickBindings -- whereas a macro is plain script
    execution and cannot quietly stop being supported. @mouseover is exactly
    right for a click binding, since the cursor is over the frame.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • check: report the click handler and Blizzard's click bindings
    Attribute readback on 12.1 shows alt-type1/alt-type2 landing correctly
    while the clicks still do nothing, so the remaining suspects are
    downstream of the write.
    "menu" is not a generic action type -- SecureUnitButton_OnClick
    special-cases it and calls frame.menu() -- so report which handler a
    frame actually uses and whether it has a menu function. Also dump
    Blizzard's click-binding profile, which runs on its own path and could
    be claiming a combo before ours is consulted.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • check: allow aiming at a named frame
    PlayerFrame and the compact party frames come from different templates,
    so "works here, not there" is worth being able to point at directly
    instead of inspecting whichever frame happens to be sampled first.
    Frame names are case-sensitive globals but the slash handler lowercased
    the whole message, so the raw argument text is now carried alongside the
    lowercased one.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Register arena frames; list managed frames in check
    Clique's default frame list has an arena group that ours lacked, so
    arena enemy frames were never picked up. The naming has changed across
    versions, so try each candidate; absent names cost nothing.
    check now lists every managed frame by name and calls out PlayerFrame,
    TargetFrame or FocusFrame if they are missing. A binding that works on
    party frames but not the player frame is a discovery problem rather
    than a binding problem, and the two were indistinguishable from the
    symptom.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Show /slotcast check in the copy window too
    Both reports now share one window and one display path, retitled per
    report and stashed separately (lastProbe, lastCheck) so either survives
    a /reload. "chat" as an argument to either still prints inline.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • check: dump raw frame attributes and the config, not just our bookkeeping
    Comparing the plan against the frame only proves our writes match our
    intent. It cannot show a binding that never reached the config, or a
    Blizzard attribute shadowing ours. Dump every type/unit attribute on the
    frame for buttons 1 and 2 across all modifier prefixes, plus the raw
    binds table, so the failure can be located instead of theorised about.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Keep casts on the press stroke; only the unit menu forces release
    Defaulting the whole frame to AnyUp fixed target and menu by giving up
    cast-on-press everywhere, which is the wrong trade: those milliseconds
    are the reason the cvar exists.
    RegisterForClicks is per frame, so the stroke cannot be chosen per
    binding -- but target, focus and assist have macro equivalents that run
    on either stroke. Emitting those as /target [@mouseover] and friends
    when firing on press leaves the unit menu as the only action with no
    press-stroke form.
    So "auto" (the new default) fires on press unless the unit menu is
    actually bound. clicks up/down/both remain as explicit overrides, and a
    binding stranded by the current mode is named in the panel, on status,
    and by /slotcast check rather than just failing quietly.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Register unit frames for AnyUp, not AnyDown
    Click registration followed the ActionButtonUseKeyDown cvar, which
    governs ACTION BUTTONS -- not unit frames. Blizzard's unit frames stay
    on the up-stroke and so does Clique.
    Casting works on the down-stroke, but "target" and "menu" run on the
    up-stroke, so registering unit frames for AnyDown left spell bindings
    working while silently killing Target unit and Unit menu. Two thirds of
    the addon working is what made this hard to see.
    Up is now the default. /slotcast clicks down opts back in for anyone who
    binds nothing but spells and wants them a few milliseconds earlier; it
    warns about the cost.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Add /slotcast check, and detect modified-click hijacks
    "The binding does nothing" has two very different causes with identical
    symptoms: the attribute never landed, or it landed and something ate the
    click. /slotcast check reads every planned attribute back off a live
    frame and says which happened.
    It also reports the client's own modified-click settings, because those
    hijack the unit before any binding runs. SELFCAST defaults to ALT --
    exactly the modifier people reach for when they run out of plain clicks
    -- and an Alt-bound Target then targets the player instead of the frame,
    which reads as "Alt-click doesn't work".
    Collisions are surfaced in the options panel too, not just on demand.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Fix Target unit / Unit menu: learn the verbs, and stop the auto-map
    overwriting them
    Two separate faults, both reported as "target and menu don't work".
    The menu verb was wrong. SecureActionButtonTemplate documents
    "togglemenu", but real unit frames carry "*type2 = menu" -- handled by
    SecureUnitButton_OnClick, not the generic action handler -- so setting
    togglemenu produced a click that silently did nothing. Both verbs are
    now read off a live frame instead of assumed, so whatever this client
    uses to open its own menus is what SlotCast uses.
    The auto-map also overwrote them. It clears slot bindings and then
    assigns row 1 / column 1 to plain Left and column 3 to plain Right,
    which is exactly where Target and Unit menu sit. It now leaves any
    combo already holding a unit-frame action alone and names what it
    skipped: a deliberate choice outranks a bulk mapping.
    Both verbs are reported by /slotcast status and the probe.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Don't bake one person's grid scheme into the auto-map
    The auto-map had three assumptions in it that are preferences, not
    facts: that columns carry the mouse button, that middle-click sits
    between left and right, and that a cell label is worth showing at all.
    • Which axis carries the button is now a toggle, disabled on a
      single-row bar where there is no choice to make. A 3-tall grid wants
      the opposite of a 3-wide one.
    • Mouse button order toggles between L/M/R and L/R/M, since middle-click
      is awkward on plenty of mice.
    • Slot rows show their index again, with the grid cell appended only
      when the grid is genuinely two-dimensional. On a plain row of twelve
      the cell label was strictly worse than the number it replaced.
      Modifier rows keep the canonical none/Shift/Ctrl/Alt order, matching
      every keybinding UI in the game.
      Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Measure the bar's visual grid and map it onto clicks
    Edit Mode bar shapes fill in a different order on different clients, so
    a hard-coded fold order would be both unknowable for an unreleased
    client and wrong the moment the bar is reshaped.
    Instead, read where the buttons actually sit on screen and cluster them
    into rows and columns. "Map grid to clicks" then assigns columns to
    Left/Middle/Right and rows to none/Shift/Ctrl/Alt, so a 3x4 bar reads
    exactly as it looks. Panel rows are labelled with their cell and the
    header shows the detected shape; the probe prints the grid as a picture,
    which makes a client's fold order obvious at a glance.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • /slotcast opens a standalone window instead of Blizzard's Settings
    Settings.OpenToCategory depends on category-id plumbing that has been
    rewritten more than once, and it was not opening the panel on 12.1. A
    config panel you tweak while watching your unit frames is better off as
    a draggable window anyway -- the same reasoning that made the widgets
    hand-rolled in the first place.
    The panel is now a pure content frame reparented into whichever host is
    showing it, so the standalone window and the Settings canvas share one
    layout with no duplicate construction. The Settings entry stays
    registered for discoverability in the AddOns tab.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Fix the rank guard: compare spell ids, not mere resolution
    The previous guard asked whether "Name(Subtext)" resolved to a spell.
    Probe output from 12.1 shows C_Spell.GetSpellInfo strips the
    parenthetical and resolves the base name, so every flavour subtext on
    the client passed -- "Revive Battle Pets(Battle Pets)" included. The
    guard failed open on all 8 test cases.
    A parenthetical cannot fake changing which spell is named. Both forms
    are now resolved and their spell ids compared: different ids mean the
    suffix selected a rank, identical ids mean it was ignored.
    The only false negative is a slot holding the highest rank, where both
    forms name the same spell -- casting rankless there is identical in
    effect, so it costs nothing. That asymmetry is what makes id comparison
    safe to be wrong about in a way "does it resolve" never was.
    Probe prints both ids so the verdict can be checked rather than trusted.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Probe: exercise the rank guard against real subtexts
    The rank feature rests entirely on "Name(Subtext)" failing to resolve
    for non-ranks, and that assumption was untested. The spellbook walk now
    calls the shipping RankedFormResolves on every subtext it finds and
    flags a YES loudly: on a rankless client every line must read "no", and
    anything else means the guard fails open.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Stop claiming plain left and right click by default
    Binding them overrode any Blizzard click binding on those two buttons
    while only reproducing behaviour the frame already had: current clients
    ship "*type1 = target" / "*type2 = menu" of their own, and a specific
    attribute beats a wildcard. Defaults are now empty, so the two systems
    coexist until the user deliberately binds a click.
    Existing profiles are migrated once, and only if those two entries are
    still at the old default values.
    Also fixes CopyDefaults resurrecting deleted entries: merging defaults
    key-by-key into binds meant clearing a binding came back on next login.
    User-edited tables are now seeded only when absent entirely.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Fix four bugs found by the 12.1.0 probe
    Probe output from retail 12.1.0 (build 69933) settled several things
    that had been read defensively or guessed:
    1. Bars 6-8 are at slots 145-180 on 12.1, not 73-108. The hard-coded
      fallback was wrong for this client; the runtime probe is what saved
      it. Those three fallbacks are removed rather than corrected -- there
      is no safe value to guess -- and an unprobeable bar now reports as
      unavailable, since binding the wrong slot is worse than binding none.
    2. "Battle for Azeroth Pathfinder" has the subtext "Rank 2" on retail,
      so the digit heuristic alone would have cast a nonexistent
      "Name(Rank 2)". A subtext now only counts as a rank if the client can
      actually resolve the parenthesised form, which is the real test and
      works on rankless and ranked clients alike.
    3. Blizzard's click bindings are wildcard attributes ("*type1 = target"),
      which a specific attribute beats -- so SlotCast overrides them rather
      than colliding, and nothing double-fires. The old warning was wrong.
      Worse, every character ships two Interaction entries for ordinary
      target/menu, so it would have cried conflict on every single login.
    4. GetSpellInfo and GetSpellSubtext globals are gone in 12.1; the
      C_Spell paths were already the primary and held up.
      Confirmed and now documented: ClickBindingInfo fields are actionID /
      button ("LeftButton") / modifiers / type, with PetAction=4 added to the
      enum handling. TOC interface set to 120100.
      Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Fix: LEARNED_SPELL_IN_TAB aborted Core.lua, killing all slash commands
    RegisterEvent raises on an unknown event name, and that event was
    removed in 11.0 (renamed LEARNED_SPELL_IN_SKILL_LINE). It was added in
    the spell-ranks commit, where it took out the registration loop at the
    bottom of Core.lua -- and with it the SlashCmdList assignment below.
    Every /slotcast command has silently done nothing since.
    • Events register one at a time under pcall; an absent event costs that
      event, not the rest of the file. Both spellbook event names are now
      registered and whichever does not exist is dropped.
    • Slash commands move to the top of Core.lua behind a forward-declared
      Dispatch, so diagnostics do not depend on the file they diagnose, and
      say so explicitly if Core.lua stopped partway.
    • /slotcast status reports skipped events.
      Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Make slash command failures visible instead of silent
    Retail swallows Lua errors unless scriptErrors is on, so a module that
    did not load looked identical to a command that did nothing: /slotcast
    probe nil-indexed ns.Probe and died quietly.
    • Dispatch runs under pcall and reports its own errors to chat.
    • Module access goes through Need(), which names the missing file and
      says to recopy the folder.
    • /slotcast status lists which modules loaded.
    • Probe falls back to chat if the copy window cannot be built, and
      "/slotcast probe chat" forces that path.
    • Copy window gets a sized scroll child, SetToplevel and UISpecialFrames.
      Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Add /slotcast probe: copyable client capability report
    Collects the things that cannot be determined outside the game, and
    reports absences as loudly as presences: build and WOW_PROJECT_*
    constants (scanned, not listed, so an unknown project id still shows),
    which bars exist and which slots they drive, every spell API's view of
    the spells on the bar, a spellbook walk for rank subtext, whether
    ClickCastFrames exists and what is in it, a real unit frame's secure
    attributes, and the click-binding profile if there is one.
    Copy window is built from plain frames rather than templates, since it
    has to work on a client where templates may be missing -- which is the
    reason it is being run. Report is also stashed in saved variables so it
    survives a /reload. Nothing identifying is collected.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Support Classic-style spell ranks, per slot
    Every action slot holds one specific rank, so the binding has to choose
    between casting "Renew(Rank 2)" and "Renew". That is a per-slot choice,
    not a global one: downranking means wanting Flash Heal at max and
    Greater Heal at Rank 3 bound at the same time.
    • Rank read from the client (C_Spell.GetSpellSubtext, then GetSpellSubtext,
      then Classic's two-return GetSpellInfo), never rebuilt -- the word is
      localised and the cast parser wants the local one.
    • A subtext only counts as a rank if it contains a digit, so retail's
      non-rank subtexts ("Fire", "Holy") fall back to the rankless cast.
    • Per-slot toggle in the panel, global default above it, /slotcast rank.
    • /slotcast castmode macro switches to "/cast [@mouseover] Name(Rank N)"
      if a client's CastSpellByName will not take the parenthesised form.
      Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • Discover the bar->slot mapping at runtime instead of hard-coding it
    Action slot ranges differ between clients, so asking each bar's first
    button which slot it drives is the only mapping that ports. Bars the
    client lacks are greyed out, and the default source bar falls back to
    the highest one that exists.
    Also drops "## AllowLoadGameType: mainline" from the TOC, which would
    have blocked loading outright on any client reporting a different game
    type.
    Co-Authored-By: Claude Opus 5 noreply@anthropic.com
  • SlotCast: action-bar-driven click casting for retail WoW
    Binds mouse clicks on unit frames to action bar SLOTS rather than to
    spells, so whatever is dragged into the slot becomes the binding.
    • Slots.lua builds a flat {attribute, value} plan for the whole binding
      set; Secure.lua hands the same plan to every frame and remembers each
      attribute's prior value so removing a binding restores the frame's
      original behaviour (plain left-click targeting survives).
    • Frame discovery via the shared ClickCastFrames registry plus a named
      sweep for Blizzard's non-compact frames.
    • Combat lockdown handled by queueing refreshes for PLAYER_REGEN_ENABLED.
    • Conflicts.lua detects overlapping bindings in Blizzard's built-in
      Click Bindings, which fire on their own secure path.
      Co-Authored-By: Claude Opus 5 noreply@anthropic.com

This mod has no additional files