promotional bannermobile promotional banner

WhoDoesWhat

A raid-assigments panel for TBC with hassle-free paladin assignments, syncs to pallypower and raid members.
Back to Files

1.1.0

File nameWhoDoesWhat-1.1.0.zip
Uploader
WallhackjackWallhackjack
Uploaded
Aug 20, 2026
Downloads
26
Size
609.9 KB
Flavors
Classic TBCClassic
File ID
8694393
Type
R
Release
Supported game versions
  • 2.5.5
  • 1.15.9

What's new

lightweight tag 87e3b0feae73b6b06a5b43e7850fd9fd7948285b 1.1.0
Author:    jackfranzen <4414665+WallHackJack@users.noreply.github.com>
Date:    Thu Aug 20 16:55:13 2026 -0400

commit 87e3b0feae73b6b06a5b43e7850fd9fd7948285b
Author: jackfranzen <4414665+WallHackJack@users.noreply.github.com>
Date:   Thu Aug 20 16:55:13 2026 -0400

    Release 1.1.0

    Six lines in the About window for twenty-eight commits: the chat announce
    on the status bars, Action Items folded into Members, scoped blessing
    ignores, a PallyPower-less paladin announcing itself, group roles by hand
    for assistants, and the large-raid performance pass as one line.

    TOC debug literal bumped to match the tag, per AGENTS.md.

    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

commit 8464d1a3a2f69e7bafacac14c481fd23514b6065
Author: jackfranzen <4414665+WallHackJack@users.noreply.github.com>
Date:   Thu Aug 20 16:48:57 2026 -0400

    Announce missing buffs to chat, and move the edit shortcut to Alt

    Shift-right-click was the edit shortcut; it becomes the announce, and edit
    moves to alt-right-click. Alt now means "do something to this window" --
    drag, resize, settings, edit -- and shift means "tell me about the raid".

    One line per bar: "[14/25] Food Buff: Bob, Zed, Rexxar (pet) and 7 more".
    Paladins get a line each, naming which blessings they carry but not which
    one each raider is missing -- the paladin knows their own assignment, and
    spelling it out per raider turns one line into five. On the title strip it
    announces every visible bar, staggered so the burst clears the chat
    throttle. Names truncate to the tooltip's own name setting, then again to a
    byte budget, so a 40-name setting can't produce an over-length message.

    Nothing announces a finished bar or a debuff. "Everyone has it" is what the
    green bar already says, and "here is everyone who is NOT poisoned" is not a
    list anyone needs read out.

    Also: the PallyPower and Action Items rows were the only two you couldn't
    alt-drag the window by. They are mouse-enabled, so they swallow the drag the
    window behind them would have handled, but unlike the bar rows they never
    called AttachAltDrag.

    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

commit 5d39f4a8ee29c9b8ccd713616dc3cfc270629f55
Author: jackfranzen <4414665+WallHackJack@users.noreply.github.com>
Date:   Thu Aug 20 16:03:41 2026 -0400

    Let status bar tooltips name 10 raiders, and make that a setting

    The list rule was two constants pulling opposite ways: under six names show
    everyone, past that show three. So the moment a gap grew past five people --
    exactly when the list starts being useful -- it collapsed to three names.

    One number now. Default 10, picked from a Tooltip names dropdown on the
    Status Bars settings page (3 / 5 / 10 / 20 / 40). Global rather than
    per-check: it says how much tooltip you want to read, not anything about a
    particular buff. 40 is a full raid, so it stands in for "everyone" without
    needing a sentinel value.

    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

commit e12f9c8f6bd9efb83f4f9f28ebe19f15ba07bccc
Author: jackfranzen <4414665+WallHackJack@users.noreply.github.com>
Date:   Thu Aug 20 15:48:58 2026 -0400

    Track Enlightened as a food buff, and glow when it's yours to fix

    Skullfish Soup buffs Enlightened rather than Well Fed, so holy paladins
    drinking it read as unfed. The food check now accepts either aura name.

    "Glow when responsible" was gated behind a Requires Class, which food has
    none of -- the option never appeared on that row. Food is self-supplied:
    the question isn't which class casts it but whether you are still on the
    missing list yourself, or your pet is, since the owner feeds it.

    The tooltip's missing list now leads with your own row (you above your
    pet) on every core check. A list that truncates at a threshold couldn't
    answer "am I on it", which is the only thing the food row is asking.

    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

commit 69465289ff53d691eb7abbd8b5c7ddf64e8eedbb
Author: jackfranzen <4414665+WallHackJack@users.noreply.github.com>
Date:   Thu Aug 20 15:27:53 2026 -0400

    Ignore a blessing for only part of the raid

    An ignore rule may now name a scope the way a guarantee does, plus an
    `except` flag that inverts the match. "Sanctuary except for Tanks" is the
    shape this exists for: sanc stays in the plan for the tanks and leaves it
    for everyone else, in one rule rather than one per non-tank role -- and
    inverting the match also covers raiders with no role assigned, who two
    positive rules would miss.

    CompileBuffRules now returns the per-member rules (scoped ignores and
    guarantees) as one list in rule order, so nothing new had to be threaded
    through the ladder, the plan key, or the solver. A scoped ignore is
    applied before promotions, so an ignore beats a guarantee on the same
    blessing. Hunter pets follow the same matching: they are roleless and
    Sanctuary sits second in their buff order, so without that a rule that
    took sanc off every non-tank would still have left it on every pet.

    In the menu, the two flat ignore items become an "Ignore a Blessing"
    branch sharing the guarantee branch's blessing/target/role levels. All
    six blessings can be ignored for a group; "Everyone" -- the raid-wide
    ignore -- is still offered for Salvation and Light only.

    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

commit b2b948b5de5b206a5f0952e680a0a08a8cfd199b
Author: jackfranzen <4414665+WallHackJack@users.noreply.github.com>
Date:   Wed Aug 19 17:15:49 2026 -0400

    Let raid assistants set group roles by hand

    Splits Blizzard flag writes into manual and automatic, and fixes three
    defects in the merged Members page.

    Manual vs automatic permission. Writing another player's group-role flag
    took the single-writer election, which returns the raid leader whenever
    the leader also runs WhoDoesWhat -- the normal case -- so every
    assistant's Group role dropdown was dead and setting a WDW role never
    pushed their flag. The election exists to stop several clients writing
    the same flag on their own initiative; a person clicking one dropdown
    once is not a race. Manual writes now take CanSetOthersBlizzardRoleManually
    (the WoW rank the server itself demands: raid assist / party lead).
    Talent auto-detection and the reconcile sweep still take the election.
    ApplyBlizzardRole carries a `manual` flag, SyncBlizzardRoleState and
    SetAssignedRole thread it, and the human-click call sites pass it.
    Manual writes also skip the lastWritten loop-breaker: standing down is
    for automatic re-assertion races, and re-picking a role someone else
    overrode is deliberate.

    Unit token was required where it should have been optional.
    CanEditGroupRoleOf refused outright without a resolved raidN token, which
    greyed the column and dropped the unit SetAssignedRole needs. WoW accepts
    a group member's name as a unit and ApplyBlizzardRole already relies on
    that fallback, so the token is a convenience again. It now returns
    ok, reason, and the reason is what the greyed dropdown's tooltip shows.

    One wrong role counted as two issues. A two-way disagreement with no
    third answer to break the tie emitted a line per accused answer, so the
    tooltip said the same thing forwards and backwards and the badge read
    "2 issues" for one problem. Correct while each line lit its own column
    gutter; wrong once they share a tooltip. RowDisagreements now returns one
    entry per disagreement: a majority names the odd one out, no majority
    states it once and names the parties.

    The overview counts line hides the roleless bucket at zero. It wears the
    warning icon, and a warning over a 0 announces the good outcome as an
    alarm. The three role buckets keep their zeros, since the grid below
    hides itself when empty.

    Verified outside the client: all first-party files parse, TOC matches the
    file list, git diff --check is clean, and a stubbed harness drives the
    real GetRosterIssues over five disagreement cases -- reproducing the
    double count against the previous commit and passing on this one.

    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

commit 8036f9ac1aee61386f6866cf621b26176f4355e6
Author: jackfranzen <4414665+WallHackJack@users.noreply.github.com>
Date:   Wed Aug 19 02:27:42 2026 -0400

    Stop dismissed pets from becoming bogus PallyPower targets

    BuildDesired resolved a pet's wire name with `owner and
    ShortName(petRealName[owner]) or ShortName(raider)`. A dismissed pet has
    no live name, so ShortName returned nil and the and/or chain fell through
    to the plan key "<Hunter>'s Pet" -- a name PallyPower has never heard of.
    That became an active target with a wanted Normal exception nothing could
    ever satisfy: a permanent red row in the Differences window whose Fix
    button refused with "That target cannot be represented in PallyPower",
    and a garbage NASSIGN on the wire during a full sync. Resummoning the pet
    resolved the real name and the row vanished.

    No wire name now means no target, so the pet's cells count as skipped
    until it is summoned again.

    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

commit c6c4b4759bc9a19c4592489d3a297ce2f7b5b4a6
Author: jackfranzen <4414665+WallHackJack@users.noreply.github.com>
Date:   Wed Aug 19 02:06:07 2026 -0400

    Combined Actions + Members page into mega page

commit b360eaafc756f23a7f6f8795109fc69b72631377
Author: jackfranzen <4414665+WallHackJack@users.noreply.github.com>
Date:   Sun Aug 16 20:41:03 2026 -0400

    Little status bars cleanups

    Don't show all druids with 0/5 for example, and also hide paladin bars for players with 0 assignments

commit 4a3b3baf89545371ba5509175536a309a789aa69
Author: jackfranzen <4414665+WallHackJack@users.noreply.github.com>
Date:   Fri Aug 14 14:35:20 2026 -0400

    Report a PallyPower-less paladin to PallyPower

    PallyPower only draws a column for a paladin it has heard SELF from, so a
    paladin running WDW alone was invisible in every PallyPower window and
    nobody could aim an assignment at them.

    When PallyPower is absent and the player is a paladin, WDW now sends that
    announcement itself: SELF, FREEASSIGN YES with the real symbol count, then
    its mirrored exception rows as NASSIGN batches -- PallyPower's own SendSelf
    sequence. The rank/talent field is encoded from WDW's native talent scan
    plus the spellbook; the class row comes from the wire mirror rather than
    the computed plan, since SELF replaces the sender's row everywhere with no
    authority check.

    Announcing is reactive so an all-WDW group stays silent: nothing is sent on
    a timer or a push, and a REQ is answered only from a requester WDW cannot
    account for as a sync peer, or once a real PallyPower client is known to be
    listening. Answers are debounced into one broadcast rather than
    PallyPower's whisper per requester.

    PallyPower peers are now recognised from ASELF/PPLEADER instead of SELF --
    the two messages WDW never sends -- so its own announcement cannot count it
    as a PallyPower user, and that table now clears on leaving the group. The
    raider tooltip drops the PallyPower line entirely for anyone running WDW.

    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

commit 2b916c1df0721339bbef99e101450541c1306501
Author: jackfranzen <4414665+WallHackJack@users.noreply.github.com>
Date:   Thu Aug 13 17:37:03 2026 -0400

    Renamed Members page, and cleaned up styling

    No more double-warnings, cleaner columns, better scrolling / window size, and a header

commit b8227d747f5601728a794e46c2d991fb5f64c2cd
Author: jackfranzen <4414665+WallHackJack@users.noreply.github.com>
Date:   Thu Aug 13 16:53:15 2026 -0400

    Clarified actions page with additional warnings

    Attempts to find the outlier of all 3 categories (blizzard role / wdw role / talents) and flag an inconsistency

commit 40ccd2f6c93657bdfec58113a5607f4bb96f9a7e
Author: jackfranzen <4414665+WallHackJack@users.noreply.github.com>
Date:   Thu Aug 13 15:32:26 2026 -0400

    Option to ignore Light

    Highlighted when no Hpal

commit 92e2313d12eb20b6a02cb5490a492b3c0a68d0bd
Author: jackfranzen <4414665+WallHackJack@users.noreply.github.com>
Date:   Wed Aug 12 16:08:32 2026 -0400

    Use HasMemberOfClass for the last two emptiness tests

    Same shape already fixed in WDW Status: #MembersOfClass(x) > 0 builds and
    discards a filtered roster list to ask whether one exists.

    The grid's is the one that mattered -- it sat inside the core-header loop,
    which runs per block per column, so up to sixteen throwaway roster filters
    per grid repaint.

    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

commit 92e2313d12eb20b6a02cb5490a492b3c0a68d0bd
Author: jackfranzen <4414665+WallHackJack@users.noreply.github.com>
Date:   Wed Aug 12 16:08:32 2026 -0400

    Use HasMemberOfClass for the last two emptiness tests

    Same shape already fixed in WDW Status: #MembersOfClass(x) > 0 builds and
    discards a filtered roster list to ask whether one exists.

    The grid's is the one that mattered -- it sat inside the core-header loop,
    which runs per block per column, so up to sixteen throwaway roster filters
    per grid repaint.

    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

commit 33a0239df3647604e0c03b393b64f08cbd6c36ba
Author: jackfranzen <4414665+WallHackJack@users.noreply.github.com>
Date:   Wed Aug 12 15:07:38 2026 -0400

    Break talents.ready down into its parts

    talents.ready is inclusive and still reads up to 14ms, but its max cannot
    distinguish a slow scan from the leading-edge repaint RequestFullRefresh
    performs inside the first OnTalentsReady of a sweep.

    Worth noting for whoever reads the next dump: the three native talent reads
    all early-return unless isInspect, and SyncRosterTalents replays the cache
    with isInspect=false -- so on a roster sweep they do nothing at all, and the
    cost has to be elsewhere. Guessing at which "elsewhere" is what these
    sections remove.

    Adds talents.scan.paladin/warlock/core, talents.autoassign, talents.pushpp
    and talents.autorows. Instrumentation only, no behaviour change.

    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

commit e8e4e6f040d1961c9d93717df74dfc7d6777768a
Author: jackfranzen <4414665+WallHackJack@users.noreply.github.com>
Date:   Wed Aug 12 15:04:08 2026 -0400

    Coalesce the per-player talent repaints

    OnTalentsReady runs once PER PLAYER and repainted everything directly.
    SyncRosterTalents calls it for all 40 group members in a single loop, so a
    roster sweep did forty full repaints in one frame -- which is the ~250ms
    stall on AV start and on zoning into a raid after a wipe. The same thing made
    crowds stutter: LibClassicInspector delivers TALENTS_READY one player at a
    time as people come into range, each forcing its own repaint, including for
    players already scanned once (the sweep replays cached entries).

    So the 250ms was real, not an unclosed profiling section: talents.ready is
    inclusive, and it contained a whole board repaint per player.

    Adds RequestFullRefresh to ViewRefresh.lua -- leading edge like the
    buff-tracking notify, so a single inspect still repaints instantly, while
    anything arriving inside the interval collapses into one catch-up. Covers the
    two big windows as well as the board, since a talent arrival can settle a
    role and move the roster lists; that is what these callers each did
    individually.

    OnTalentsReady and AutoAssignDetectedRole now request instead of forcing.
    The user-initiated rescans stay immediate -- they fire once per click, not
    per player.

    Modelled in a scratch harness: a 40-player sweep in one frame goes from 40
    repaints to 2, twenty inspects over two seconds from 20 to 5, a lone inspect
    still repaints immediately, and a request during the cooldown still gets its
    catch-up.

    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

commit 05c65a7190bbe017035e074c7530cbb4ae4530d1
Author: jackfranzen <4414665+WallHackJack@users.noreply.github.com>
Date:   Wed Aug 12 14:31:48 2026 -0400

    Throttle board repaints to once a second

    The buff-tracking notify was a 0.1s trailing debounce, sized to collapse one
    burst of UNIT_AURA into a single repaint. A debounce only collapses a BURST
    though -- against a steady stream it just becomes a clock, and in a 40-man
    battleground the changes never stop (deaths and rezzes flip a raider's state
    as much as buffs do), so the gap between them stays under 0.1s and it settled
    into repainting the whole board 10 times a second. The buffs it reports last
    tens of minutes.

    Throttled to 1s rather than simply debounced at 1s, because a plain 1s
    debounce would make the first change after a quiet spell wait the full second
    -- exactly when promptness matters, like watching a blessing you just cast
    land. A change arriving after the interval repaints immediately; one arriving
    inside it schedules a single catch-up for the remainder.

    Modelled against change streams in a scratch harness:
      - lone change after a quiet spell: repaints immediately
      - a change every 10ms for 10s: 11 repaints, 1.00/s (was up to 10/s)
      - a 40-event burst: one catch-up repaint, last change not dropped
      - a change every 5s: all immediate, none delayed -- so the cadence actually
        observed in AV is unaffected, and this only bites during churn
      - worst-case latency for any change is bounded by the interval

    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

commit 933234003fbb7ea5914627fdcddaa5cb8b5daa85
Author: jackfranzen <4414665+WallHackJack@users.noreply.github.com>
Date:   Wed Aug 12 14:13:51 2026 -0400

    Move the Action Items model out of its view

    GetActionItems and CountActionItems derive what still needs tidying from the
    roster, the board and the last talent scan. No frames involved, and the main
    window's toolbar button and the WDW Status row both read the count -- so the
    header comment justifying their place in the view ("used by nothing else,
    splitting it would cost more than it explains") had stopped being true.

    Now ActionItems.lua, alongside the other models.

    Two things the view still needs stay shared rather than copied: the Blizzard
    role token map, now WhoDoesWhat.BLIZZ_ROLE_TO_WOW_ROLE, and the class-token
    lookup. The latter existed twice already -- Assignments.lua had the same
    function as a local -- so the view's copy is gone and Assignments exports its
    one as Assign.GetClassInfoByToken.

    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

This mod has no additional files