Dibs-v0.4.5
What's new
Changelog
[v0.4.5] -- Advantage counts for everyone, Dibs learns your raid, and the standings say more
Added -- two new standings columns: WL lost and SR lost
Requested: "we SHOULD have a column for lost rolls on wishlisted items" and "we SHOULD have a column for rolls lost on SR items", alongside the plain Lost that counts every roll.
The point is that Lost on its own is a weak argument. A raider with forty lost rolls may simply have rolled on everything; a raider with twelve losses on items they had actually wishlisted has a case. The two new columns sit immediately right of Lost on the Attendance tab's Standings, and each is a subset of it.
The two overlap on purpose, and neither is a share of the other. An item can be on your wishlist and soft-reserved by you -- reserving something you want is the whole point -- so a loss on an item that is both is counted by both columns. Adding the columns together will therefore over-count, and that is the honest answer rather than forcing a choice between two true statements.
They only count from this version onwards, and the header tooltips say so. Whether a loss was wishlisted or reserved is a fact about that item and that player at the moment of the roll: the item rolled for is not recorded on the entry, and both the wishlist and the reserve list change afterwards. Nothing already in the history can be worked out after the fact, so both columns start at zero on existing data. Lost is unaffected and keeps its full history.
Internally this is one ledger entry per loss, with the category carried on the entry's reason rather than in a second entry -- Lost is a sum of amounts, so a second entry would have made one lost roll count as two and the column everybody already reads would have started lying. It is also per loser, not per item: one drop can be on Ana's wishlist, reserved by Bob and neither to Cid, and all three losing the same roll are filed separately. No change to what goes over the wire; an older client shows the unfamiliar reason as-is rather than breaking.
One known asymmetry, handled rather than hidden: an officer Reset is a compensating entry that carries no category, so it drives Lost to zero while the historical categorised entries remain. Each category column is clamped at that player's own Lost, so the table can never show "0 lost, 7 lost on wishlisted items".
Eighteen new tests across Tests/attendance_spec.lua and Tests/tracker_spec.lua -- the four reason tokens
and that they stay four distinct tokens, the per-loser routing, one-entry-per-loss, the reset asymmetry, the
clamp in both directions, the account-view fold, and that both columns are built with real header tooltips
rather than a missing locale key.
Fixed -- a raid you had not run yet could not be configured, and a per-raid setting did nothing
Reported: "the loot system per raid is missing RFC, ony, aq20 and aq40", and separately "we need to ensure RFC is being tracked as a raid, for raid attendance." Same subject underneath, so they are fixed together.
The list only ever showed raids you had already been to. Every source behind it was a record of something already done -- raids you had configured, raids attendance had tracked, raids with soft-reserve data -- so a raid could not be set up until after you had run it. Backwards for a screen whose whole job is deciding how a raid will run. It now starts from the raids your client actually ships, so Onyxia, both Ahn'Qiraj raids and Ragefire Chasm are there from the first time you open it. Still not a hard-coded list: the instances come from the item library and each is included only if Dibs itself calls it a raid, so a TBC client lists TBC raids and nothing has to be maintained by hand.
Ragefire Chasm and Wailing Caverns now count for attendance too. Both are deliberately treated as raids so the whole loot flow can be tested without assembling forty people -- but the game answers to the server, which calls them 5-mans whatever Dibs says, and raid attendance was still asking the game. A night in either was filed under the unidentified ? bucket. Attendance now asks Dibs' own question, exactly as the loot side already did. An ordinary dungeon is still not a raid, and reverting the two test declarations before a player release reverts this with them.
And a per-raid loot system was not being applied at all. A raid has two spellings -- the key
(MoltenCore) and the display name (Molten Core) -- and the settings screen saved under one while a lookup
made from inside the instance used the other, compared with an exact match. So setting Molten Core to DKP,
walking into Molten Core, and getting the guild-wide default was the actual behaviour, with the setting still
showing as set on screen. Both ends now agree on one spelling, and an override saved before this keeps working.
Fourteen tests in Tests/raidkeyspelling_spec.lua covering all three, including that one raid cannot end up
with two rows under two spellings and that clearing an override works whichever spelling you clear it by.
Fixed -- the Below-threshold loot tooltip pointed at a button that no longer exists
The Leave alone option told you to "use the Distribute mats button when you want it". That button was removed when the two masterlooter button rows were merged into one, so the tooltip was sending people to a control that is not on any window -- which reads as the addon being broken rather than as a stale sentence. This dropdown is that button's replacement: what used to be a press per corpse is now a standing answer.
Fixed -- an Advantage player's second roll was thrown away if they were from another realm
Reported live, with the chat log: "you can see one player who had Advantage rolled twice, their second roll was 98 but the item was awarded to the 65 roll."
1000 (OS)
Advantage -- Heafstaag-Myzrael: roll ONE range twice (/roll 100 or /roll 1000, not one of each).
Heafstaag rolls 59 (1-100)
Heafstaag rolls 98 (1-100)
Shockira rolls 65 (1-100)
Inevitabull rolls 331 (1-1000)
Mageificent rolls 2 (1-100)
Winner: Shockira (65)
The cause: Dibs was asking two different questions about who "Heafstaag" is, and only one of them had the
right answer. When it flags somebody for Advantage it identifies them from the raid -- which knows each
character's real realm, so the flag was stored under Heafstaag-Myzrael, exactly as the announce printed it.
But when their /roll scrolled past in chat, the name arrives with no realm attached, and Dibs asked the
guild roster to fill one in. That never looked anybody up: it simply stapled on the master looter's own
realm. For anyone raiding from another realm the two names then disagreed, the flag was not found, and the
second roll was rejected as a duplicate -- so the 59 stood, and 65 beat it.
It only ever hit cross-realm raiders, which is why it looked random. For someone on the master looter's
own realm both routes produce the same name and Advantage worked perfectly. This is the second time this
family of bug has taken an item off the wrong person (the first was Thorium rolling 41 then 59), and it is
the worst shape a loot bug has: the advantage was announced to the whole raid, the player took both rolls in
public, and the higher one was discarded in silence. Nothing errored, and the result read as an ordinary roll.
The fix is that there is now only one question. A /roll is matched against the raid roster -- the
same list the flags were keyed from in the first place -- so the two cannot disagree about who somebody is.
Guild membership never enters into it, and a pug resolves exactly the same way a guildmate does. The guild
library is still consulted afterwards, for a roll arriving from somebody who has just left the group.
A refused roll now says so. Dibs always had a line naming the reason in one word, and it was switched off
unless you were running /dibs debug -- so the single fact that would have settled this in seconds had never
once been printed. It is on by default now for the two refusals that change who can win, in the masterlooter's
own chat and not the raid's.
And the announce can no longer promise something the roll will not honour. The "rolls twice" line was sent whenever names were flagged, without checking that the roll it was describing actually grants a second die -- so a mismatch there would have told the raid one set of rules while running another.
Tests/advantagelog_spec.lua replays the chat above line by line through the real parsing, name-matching and
resolution code: it reproduces the wrong winner with the old behaviour and gets the right one with the new.
Tests/advantagerealm_spec.lua pins the name handling underneath it. They are separate files because the
existing session tests do not load the name-matching module at all, so every one of them used the same
spelling on both sides of that lookup -- which is how a defect in exactly that lookup survived a suite that
already had Advantage coverage.
Changed -- only one piece of code can add a realm to a name now
Housekeeping on the same machinery as the Advantage fix above, and not a second cause of that report -- see the note at the end.
Dibs had two pieces of code that appended your realm to a bare name. The flag set is keyed through
Names.Full, which uses the client's normalized realm name. The roller's last-resort fallback had its own
version: the client's display realm name with the spaces taken out. Two expressions for one value, sitting
on opposite sides of the comparison that decides whether your second roll counts.
Squashing spaces is not normalising. It handles a two-word realm and leaves every other kind of punctuation where it is. Wherever the two spellings differ, the flag goes in under one and the roll arrives under the other -- both carrying a realm, so Dibs compares them strictly, decides they are two different people, and refuses the second die.
There is now one function that can add a realm to a name, and both sides of that comparison go through it. The fallback is still the last resort it was and still honest about being a guess; it just spells the guess the way everything else does.
Whether any live realm actually triggers it is not established, and the first version of this entry claimed it was. It named three realms as examples, from memory, none of them checked -- and one was a two-word name, which by this entry's own argument would not have triggered anything. So this is a correctness fix rather than a reported bug, and it is not the cause of the Advantage report above: those realms all squash and normalise identically.
Three tests in Tests/advantagerealm_spec.lua, driven red first.
Internal -- the Advantage loss is now recreated from the shipped code, not from a description of it
Tests/advantagelog_spec.lua claimed to reproduce the reported loss. It did not: it ran oldNormalizer, a
hand-written stand-in somebody wrote to behave the way they believed v0.4.4 behaved. If the belief is wrong
the test proves nothing, and this is the file whose own header warns that hand-fed name spellings are how
three wrong diagnoses each looked confirmed.
It now drives the actual shipped function, transcribed verbatim from Dibs-v0.4.4, against the real
LibGuildRoster rather than a stub, with the raid's real names and realms and the master looter's own realm
installed. That combination reproduces the raid's outcome exactly -- Heafstaag resolved to the master looter's
realm, his second die refused, Shockira taking the item on 65 -- and the same replay through the current
resolver gives Heafstaag the item on 98. Driven red to confirm the assertions bite.
The shipped source settled something no summary of it had. The guild lookup was the first branch and returned immediately, with no roster consulted before it and no membership gate on it -- so for every bare chat name in that raid the answer was the master looter's realm, appended without looking anyone up.
Internal -- the Advantage replay was testing against realms the raid did not have
Tests/advantagelog_spec.lua replays the real chat log from the reported raid. Its roster fixture put all six
players on one realm -- while its own comment, twelve lines further down, recorded the realms measured from a
/who and a group-loot screenshot: the master looter on Azuresong, the flagged player on Myzrael, and two
others on OldBlanchy and Atiesh.
A fixture where everybody shares a realm is the exact condition under which a realm bug cannot appear. Every roller resolved to the same realm as every flag key, so the comparison the whole file is about was never actually made, and three sessions read a green replay while reasoning about realms from it.
The fixture now uses the measured names and realms, and the replay installs the master looter's own realm so the pipeline runs on the client that was in the screenshot rather than on the harness default. Same twenty tests, same outcomes -- but they now assert against the raid that happened.
Fixed -- the roll window no longer pops up with nothing in it
Reported with a screenshot, on Augment Blizzard's frame: "dibs roll window still appears just without the buttons."
In Augment mode Dibs deliberately draws no roll buttons -- Blizzard's own window does the rolling, and the Dibs companion beside it exists to tell you one of three things: that you called dibs on the drop, who else did, or that it is an upgrade for you. On a Runecloth it knows none of those, so the companion drew an item name and a timer that Blizzard's frame was already showing a few pixels away. A window with no controls reads as a window whose controls have broken.
It now stays shut unless it has something to say, which on trade goods and greys is most of the time. When there is a dib, another raider's dib, or an upgrade to report, it appears exactly as before. Replace mode is untouched -- there the window carries the buttons, so it always has a job.
Fixed -- the loot table could take itself away from the master looter, again
The previous release stopped this happening when the game could not say who holds master loot. It turns out that check had two halves and only one of them was covered: the same collapse survived on the question "and am I that person?". If your client momentarily could not work out its own name -- the churn around a reload, someone zoning, a member joining -- the answer came back no, which reads as "somebody else is the master looter", and the action bars, roster and title vanished mid-boss with the table still live.
That question now has a third answer: yes, no, or I cannot tell. Only yes and no move the table between players; "I cannot tell" changes nothing and waits for the next event, which is the rule the other half already followed.
The test suite was asserting the broken behaviour was correct, which is why this survived a release. Its fixture treated "the game says I am not the master looter" and "I could not work out who I am" as the same thing, so a genuine handover and this bug looked identical to it -- and the test that pinned handovers as correct was pinning both. That fixture is fixed too.
Fixed -- a record could be filed under a character with no name
Found by peer review, not in play. During the moment between logging in and your character existing, Dibs
could build its identity key as -YourRealm -- a realm with nobody attached to it. Every guard in the
addon checks that the key is not empty, and that string is not empty, so it went through: DKP entries, soft
reserves and Main/Alt declarations could all be filed under it, saved, and then synced to everyone else.
Nothing errors, and no later fix undoes it, because by then the record has travelled.
One condition, at the single place the key is built, and every one of those guards starts working. The same function's other branch -- the one used when GuildRoster is loaded -- had always got this right, which is why it went unnoticed for so long: on most clients the correct branch runs and the broken one never does.
Changed -- the priority picker and the roll it opens now agree on which method is running
Also from review. Three places read the Priority method setting and one of them assumed a different default from the other two, so an unconfigured guild could get a picker explaining Advantage rules over a roll that ran as Standard. All three now read it the same way.
That trail led somewhere worse: the "rolls twice" announcement was sent whenever names were flagged, without checking that the roll it was describing actually grants a second roll. So the raid could be told a player rolls twice by a roll that would refuse their second one and then keep the lower -- which is exactly the Advantage report above, reachable by a second route. The announcement is now tied to the roll it describes.
Added -- Dibs now remembers who is in your raid, and which realm they are really on
Requested, and asked for twice before it was built: "I TOLD YOU to create a RAID TABLE for LOOKUPS to support PUGS. you can use the guildroster lib as a source, but it's not going to work for PUGs."
A /roll line in chat gives you a bare name with no realm on it -- and on a connected-realm cluster that
is not enough to tell two characters apart. Every version of Dibs until now filled in the gap by guessing,
which was right for people on your own realm and wrong for everybody else. That is the Advantage bug above,
and it was never going to be the last one: the same guess sits under the loot log, soft reserves and
attendance.
Dibs now builds a table of everyone in the raid as they join, and keeps it for the whole night. Anyone who was in the group at any point is remembered, so a roll that arrives after somebody has dropped still lands on the right character. It is per raid, because a guild can run two at once and they must not answer for each other -- "we need to be able to have more than one, as there may be more than one raid in a guild at one time".
Three sources, none of which invents anything:
- The group itself, which knows each character's real realm. Free, and it covers everyone standing there -- a pug exactly as well as a guildmate, which is the whole point.
- The guild roster, for a guildmate who has already left the group.
- A player's GUID, which arrives free on any chat message they send and can be turned straight into a realm.
What it does NOT do is send /who queries, and that is worth saying because the first version of this did.
The player asked the right question -- "is there another way to get the realm from a player other than a /who
through the api? it would be cheaper and require less software" -- and there is. Once the group, the guild
roster and a chat GUID are all in play there is nobody left for a query to find, so the throttle, the retries
and the timeouts that went with it were deleted rather than shipped.
Fixed -- anyone who whispered you was enrolled in your raid's roster, and the per-raid lookup was never used
Both from peer review, and they are one fix because each of them was hiding the other.
Dibs keeps a table of who is in the raid so a /roll can be matched to the right character. It learns realms
from three places, and one of them is any chat message a player sends -- their identifier arrives free on
the event, and that is what made the whole /who machinery unnecessary. But the addon listens on say, yell
and whisper as well as the raid channels, and recording somebody's realm also recorded them as being in
this raid. So anyone who whispered you, and any stranger who spoke within range, was enrolled in your raid's
roster: a friend in a different raid, somebody standing in a city, a gold spammer.
That was invisible, because the other half of the feature was never switched on. The lookup can be narrowed to one raid -- which is what lets a guild run two at once without one answering for the other -- and the one place that asks was not passing the raid. So the membership list was written by four separate paths and read by nothing.
Fixing either one alone would have been wrong, and the order matters: switching on the narrowing while whispers could still enrol strangers would have taken a feature that was inert and made it confidently wrong -- answering for people who were never in the raid, with the narrowing's authority behind the answer.
So, in order: learning a realm and asserting raid membership are now two separate claims. A chat message teaches Dibs a character's realm and vouches for nothing else; only the group roster -- which reads the actual raid -- puts somebody in a raid. Then the narrowing was wired up, and the multi-raid half of this feature does what it has always said it does.
Internal -- the chat identifier's position is verified rather than asserted, and can no longer fail silently
Review flagged that the addon read a player's identifier from a fixed position in the chat event on the
strength of a comment saying so, and that the whole /who-is-unnecessary argument rests on that position
being right. It is right -- confirmed against Blizzard's own code in the Classic Era client, which unpacks
and names all fourteen values of that event in one line, and the identifier is the twelfth.
The check was kept anyway, because verified today is not true forever and the failure mode is the worst kind: hand that lookup something that is not a player identifier and it does not error -- it quietly answers "nobody", for ever. Since everyone currently in the group is still resolved from the group roster, the table would go on looking healthy while silently covering nobody else. It now refuses with a named reason instead of an unexplained blank.
Fixed -- a pug's roll could be credited to the wrong character
If someone in your raid was not in your guild, and they left the group before their roll was counted, Dibs asked the guild roster who they were. The guild roster has never heard of them -- but it answers anyway, stamping your realm onto their name. For a cross-realm pug that is the wrong character, and it is the same failure as the Advantage bug above, in the one corner that fix does not reach.
Dibs now only takes the guild roster's answer for somebody it actually has on file. A pug still in your raid was never affected: they are identified from the raid itself, where guild membership does not enter into it.
Fixed -- a re-roll under a second spelling of your name could take an item off someone
Found while tracing the above, and it is a different bug with the same root: when Dibs checked whether you had already used your roll, it compared names exactly, while every check around it compared them realm-tolerantly. If the same raider's two rolls came in under two spellings, the second one looked like a different person -- so "your first roll is binding" quietly stopped applying, both rolls competed, and the higher one could take the item off somebody who rolled once. A pass could be followed by a roll the same way.
Changed -- the ? column is gone, and the standings show how many raids you actually attended
Requested: "this ? column is useless information" and "we should get rid of the ? column and track actual raids attended".
The ? column was the bucket for a night whose raid instance Dibs could not identify -- old data from before attendance was tracked per raid, or a raid committed while not standing in an instance. As a column it could not be read: it has no name, so there is no way to tell which nights are in it.
In its place, an Attended column, sitting immediately left of the percentage it produces. That number has been carried on every row for a long time and was displayed nowhere, so an officer got 60% with no way to see whether it was 3 of 5 or 12 of 20 -- and those are not the same raider.
The unidentified nights are not deleted and still count as attendance. They were really raided, and the records are the only place they exist; dropping them from the totals would quietly reduce people's attendance, which is not what was asked for. The visible consequence, which the Attended tooltip states rather than leaving to be discovered: Attended can be higher than the per-raid columns added together, by exactly the number of nights with no identified raid.
The part that is easy to get wrong here is not the column -- the per-raid counts are keyed by position against the raid list, so removing ? from the columns while still numbering through it would have left every raid to its right showing the neighbouring raid's counts. A wrong number that looks entirely plausible. The bucket is filtered out of the raid list itself, and a test asserts the raid after the dropped one still reads its own counts.
Fixed -- the Lost column's description said something the column does not do
Reported: "i think the description for lost is wrong, in game it's just 'how many rolls you lost', not how many SR rolls you lost. check the code." Correct, and the code agrees -- every roll a player is in and does not win is a loss, with no wishlist or reserve test anywhere on that path.
The tooltip claimed it counted losses on wishlisted items, which makes a large number read as evidence of bad luck on the things a raider actually wanted. The identical wrong claim was also sitting on the Show lost rolls setting's description, where nobody had reported it; both are fixed.
[v0.4.4] -- loot moves only while you are watching, and the greys are yours to hand out
Fixed -- the masterlooter lost their own controls in the middle of a boss
Reported live, with a screenshot: "whatever you just did, makes the ML buttons across the bottom disappear for the ML." The loot table still had its rows and a running clock, but both action bars were gone, the roster column was gone, and the title had gone back to plain Loot.
That is not a layout fault, and the three symptoms together are what say so. The bars, the roster column and the title are all drawn from one fact -- whether this client is the masterlooter -- so all three vanishing at once means the addon had quietly decided it was not. The table stayed; the authority over it did not.
The cause is a question that had no way to answer "I don't know". Dibs asks the game who holds master loot. That answer is genuinely unavailable for a moment now and then -- while group state is still landing after a reload, or when a raid member's details are not resolvable at the instant an event fires. All of those came back as a flat no, which is indistinguishable from "somebody else has it", and Dibs acted on it: it stood the real masterlooter down and kept the table open in front of them.
And the event that triggers it fires exactly when the answer is least available -- when the loot method changes, when somebody joins, when a player zones. That is why it looked random.
Dibs now moves loot authority only on a definite answer naming somebody. If the game cannot say, nothing changes and it waits for the next event -- what it already knows is the last thing the game actually told it. This is deliberately symmetric: a client that cannot resolve the masterlooter will not seize a table either. A real handover is unaffected, because that comes with a name.
Also fixed alongside it: the status line at the bottom of the loot table only ever repainted for the masterlooter, so a client in this state carried on announcing "Selection open -- 0 of 2 have finished" long after it had stopped being their window. That is what made this look like missing buttons rather than a change of role, and it now clears.
Four tests in Tests/loottablehandover_spec.lua, driven red first: with the fix defeated, exactly the two
tests describing this symptom fail and the two genuine-handover tests stay green.
Added -- an Unstick button, so a stuck answer is not a reload
Reported live: "i did rolls a few times, it just 'stopped working'", and then "/reloading on both characters fixed it, but i shouldn't have to do that".
WoW quietly discards addon messages when there is too much traffic, and a message whose delivery is never confirmed can leave that channel blocked for the rest of the session. Everything queued behind it waits on something that will never arrive -- which, on a raider's screen, is an answer stuck on Sending your answer... that no amount of pressing Resend can shift.
Both loot windows now carry an Unstick button, bottom right. It releases the blocked queue and re-sends whatever was waiting. Safe to press at any time: a message that is merely waiting its turn is left alone, so nothing is ever sent twice, and it tells you which of the two happened.
It is on the window rather than only behind a command because the person it happens to is a raider who has no
reason to know a command exists. /dibscomms status is there as well for anyone who wants the detail --
which channel, how deep the backlog, how long it has been stuck.
Fixed -- a pick that never arrived, and nobody was told
Reported live: "i tried to pick MS on a recipe drop, and it's not being sent across." The raider's row sat on Sending your answer... while the masterlooter's window still listed them as not having answered.
Two checks on the masterlooter's side could discard an incoming pick and reply nothing at all -- both of them for transient reasons, like a handover in progress or the loot table not being open at that instant. The raider was left with a receipt that never resolved, and Resend could not help, because every retry met the same check and vanished the same way.
Both now answer, with a reason the raider's window shows, and the masterlooter gets a line in chat naming whoever was turned away. A refusal takes somebody out of the running for an item, and the person running the loot is the one who can do something about it.
Fixed -- the bottom of the Loot & Rolls settings could not be reached
Reported live: "the bottom of the rolls settings where the push to raid sync button is, isn't showing."
The tab's scrollable height was a number kept by hand next to the code that draws it, and a setting had been added without the number being grown to match. A short scroll height does not clip visibly and does not give you a scrollbar -- the panel simply ends, which is why this reads as a missing button rather than a mis-sized panel. It is the second time: the General tab did the same thing two days ago.
So the number is gone. Each settings tab now reports the height it actually drew, and the panel is sized from that -- it cannot fall behind what is on it. Five tests assert every control lands inside the scroll range, including on a guild with a dozen raids on the list.
Changed -- "N picked" moved to the roster column
Asked for repeatedly, and it took several attempts: "the count should just be in the column with the other data. why are you making this so hard?"
The count of how many people have picked an item now sits with Raid, Waiting and Done in the roster column, instead of on the item row beside the buttons. It is the same kind of number as those two -- how much of the raid has answered -- and reading it off a single item's row was what made it look out of place no matter where it was put.
One thing is lost and it is worth saying: the count is now for the whole table rather than per item, so the masterlooter no longer sees at a glance how many picked one specific drop.
Fixed -- a roll resolved itself, and gave the item away, with the loot window closed
Reported live: "when the ML looted an item and the popup happened and i pushed roll, and for some reason the ML closes the window, the addon randomly hands out the loot. it shouln't. nothing should happen until the ML opens the loot window again, and starts the roll process to completion. the only time loot should be handed out is during the complete process."
This is the cost of AUDIT 148's fix arriving, and 148 was right. Before it, closing the game's loot window
tore the roll down: every raider's prompt vanished mid-roll, anyone who had not clicked could not roll, and
nothing was announced. LOOT_CLOSED is not a decision -- it fires on Escape, on stepping out of range, on a
knockback, on closing the window to read a whisper, on the corpse despawning -- so a routine event was ending
the raid's roll. 148 made the roll survive it. What it did not do was stop the roll RESOLVING while nobody
was watching, and that is what the report is: the countdown ran out, or the last raider answered, and Dibs
announced a winner, wrote the loot log, spent the points and pushed the item at whoever was a candidate on
whatever loot window happened to be open by then.
A closed loot window now HOLDS the roll. The clock stops. ResolveRoll refuses outright -- that is the
first statement in the function, so the countdown timer, the everyone-has-answered shortcut and the loot
table's row sequencer all hit the same wall. Everything 148 wanted is kept: the session, the rolls already
collected, the raid's open prompts and the item are all still there. Opening a loot window again resumes
it, with a fresh countdown and a line on the window saying so.
- The clock restarts from full rather than from where it stopped. Resuming a twenty-second roll with two seconds left hands the raid a roll they cannot answer.
- The raid is told nothing at either end. A hold is not an ending, and their prompts never closed.
- The X on the Master Loot window still abandons, still announces, and still means what it always meant.
That is the deliberate close;
LOOT_CLOSEDis not. - KNOWN COST, said plainly: a master looter who closes the loot window mid-roll and never opens another one leaves the roll held, and the Roll button refuses a new one with "A roll is already running" until they do. Opening any corpse resumes it -- which is not the same as clearing it: the roll then runs its countdown and resolves normally, so the block lifts a countdown later rather than immediately. The Roll button's refusal names the Master Loot window's X as the way to abandon, and on a corpse the loot table carried, that window is hidden -- so the on-screen advice is incomplete in exactly the state it appears in. Traced rather than assumed, and raised for review rather than patched blind. That is the trade the rule asks for -- loot that waits is recoverable and loot handed to the wrong person is not.
Guarding the handover instead would have been the wrong half. The announce, the loot-log row, the SR+ reset and the DKP charge all run before the item moves, so stopping only the last step leaves the raid told who won, the log claiming an award, points spent, and nothing in anybody's bags.
Added -- the officer decides what happens to greys, whites and mats
Requested: "we need to add the settings from bijouRR that enable us to 'handle' grey/white items in the addon for the ML to roll out. we can expose those as officer only settings in the rolls tab in settings."
The BijouRR model has been in the addon since v0.1 -- protection, the below-threshold test, the random pick, all unit-tested -- and the only way to reach it was the Distribute mats button. There was no way to say "we roll for cloth in this guild". Below-threshold loot is now an officer-owned setting on the Rolls tab, pushed to the raid with the rest:
- Leave alone (default, and what every existing install already does) -- no rows, no window, Dibs does not touch below-threshold loot at all.
- Roll for them -- greys and whites get rows on the loot table, so a stack of Mageweave is rolled out like a boss drop.
- Hand out at random -- BijouRR proper. Opening the corpse gives each one to a random eligible raider immediately.
The protected-mats list is the exception to all three, and it earns its keep hardest under Hand out at
random: Distribute mats skips a protected item, so a protected mat is given a row there instead of
being randomised. Without that it would be unreachable by every route at once -- not randomised, not rollable,
and not mentioned on any window.
The boundary is the game's own master-loot threshold, not a second one inside Dibs. Two thresholds that can disagree is a disagreement about who gets handed what.
Fixed -- clicking Roll on a second row silently killed the first row's roll
Found by being asked what the abandon function was for. The honest answer was "because startRoll
refuses while a roll is live" -- and checking that turned up the fact that the loot table's Roll never
did. RunTableRow assigned the session unconditionally, so clicking Roll on a second row while the first
was still running replaced it in silence: the first row's raiders keep a prompt for a roll that no longer
exists, nothing is announced, and the tally the master looter is watching belongs to a different item.
That is exactly the defect the guard on the old single-item path was added to prevent, sitting on the path that guard never covered -- and since the window merge, the loot table is the path a master looter actually uses. So the protection existed only on the button that is going away.
It refuses rather than abandoning, which is the same call the single-item path makes: ending somebody's
roll without saying so is the bug this addon has already fixed once, and doing it silently on a click is worse
than doing it loudly. The first roll keeps running, and the reason lands on the loot table's status line
naming /dibs abandon -- which is what that command turned out to be for.
- Both Roll buttons are covered by one guard. The Master Loot window's Roll routes through the table's row when a live table holds the drop, so it gets the same refusal on the same line instead of failing silently on a window that may not even be open.
- The row sequencer is untouched. Rows advance from the resolve callback, which fires after the session has been cleared, so the next row always arrives at an empty session. Only a human clicking a second row mid-roll is refused.
- The status line moved to after the call. Written before it, a refused row left "Rolling for [item]" on screen for a roll that never started -- worse than no message, because the clock beside it is counting down somebody else's item.
Added -- /dibs abandon, because closing the loot window stopped being a way out
Found tracing the roll hold above, not reported by anyone. ML:Abandon is the deliberate cancel -- it
tells the raid and closes every raider's prompt -- and its only control was the Master Loot window's X.
Since the one-window merge that window is hidden whenever a loot table carried the corpse, which is the
ordinary case; and since a shut loot window now holds a roll rather than resolving it, the state "a roll
is live and I want out" became reachable with no abandon control anywhere on screen. Closing the game's loot
window used to be the way out. It stopped being one the moment closing it became a pause.
A command rather than a button, deliberately. A button needs a window and the whole problem is that the
window may not be there -- adding one to the loot table would fix the case where a table is up and leave the
case where nothing is. A command works in every state, needs no layout decision, and cannot be clicked by
accident, which matters for a control that ends a roll for the entire raid. /dibs cancel does the same.
It tells you which of the two things happened. Typed blind, "nothing was running" and "a live roll was just cancelled" are the same silence otherwise, and they are very different facts to the person typing.
The refusal message was naming that hidden window too, and now names this instead: "A roll is already running -- wait for it to finish, or type /dibs abandon to cancel it." Same correction in the in-game manual, which also told you to use the X.
Fixed -- an item could be handed to nobody, one boss after the loot window closed
Peer-review finding 178, and the fix is the reviewer's corrected remedy rather than my first one.
A flag with four write sites and no clear on any resolution path. When the loot window closes under a live roll or auction, Dibs records it, because the window open later may belong to a different corpse and there is no API on this client that says which -- so the item lookup must not go searching. That is right, and it is what AUDIT 151 exists for. What was missing is the other end: nothing ever cleared it when the award finished. So the suppression rode into the next row, where the window was open and the search should have run, and an item whose slot had shifted was handed to nobody at all. No error, nothing in chat, and the two events a boss apart.
One function, not a clear copied into each branch -- the reviewer's own words, and the distinction is the finding: "give the roll/auction lifetime ONE teardown both resolutions call, so a third resolution path added later cannot miss it." Their first version of the remedy fixed the roll path and left the auction broken in exactly the same way, because those two bodies have different control flow.
The ending is defined as a state rather than as a branch, which is what makes the auction fall out for free: the lifetime is "this client is still going to hand this item over from this slot". It ends when a roll is decided, when an auction is charged and handed over, and when a no-bid outcome disenchants or banks the item. It does not end on an auction TIE or a refused charge -- both leave the same item up for the same award, the master looter is expected to press Award again, and clearing there would re-arm the search under the one item it was suppressed for.
Red-driven: deleting the clear turns the new two-row test red with the item handed to nobody, which is the finding's failure exactly. A third test asserts the suppression still holds within a row whose window closed, so the fix cannot quietly become "delete AUDIT 151".
Fixed -- a /roll typed in chat could vanish without trace
Two cases, both from live raids:
- "if a person with dibs is an idiot and does a /roll 100/1000 we need to be able to use that"
- "if a person OUTSIDE of dibs does a /roll that is in the raid/party, we need to include them on that item"
A roll whose range did not match the session EXACTLY was discarded. Rolls.Classify compared (min, max)
against the configured ranges and answered nil for anything else, so AddRoll refused it as "untracked".
Nothing was counted, nothing appeared on any window, and nobody was told -- not the raider, not the master
looter. A raider without the addon has one chat line to work from and no window at all: they type a bare
/roll against a row called for /roll 1000, or fat-finger the number, and they are silently out of the
running for an item they were invited to roll on.
An unmatched range is now folded into the LOWEST-priority tracked category instead of being thrown away, and the master looter is told in their own chat frame -- who rolled, what they rolled, and on what range.
- The bottom of the order, not the top, and that is the half that protects everybody else. Main-spec exists to outrank off-spec; a roll we could not attribute has no claim on the top of that order. It wins only when nobody rolled above it -- so a mistyped 99 can never take an item off a correct main-spec 2.
- It is not a licence to roll anything. Every other gate is untouched: a soft-reserve row still admits only its reservers, a tie-break only the tied players, a pass is still final, and the roll cap still holds. This widens exactly one thing -- the ungated open roll, which is the case both reports are about.
- Telling the master looter is half the fix. Quietly reinterpreting somebody's roll is worse than
quietly dropping it: the raider believes they rolled main-spec and the session has them at the bottom. The
line is deliberately not behind
/dibs debug, unlike the refusal line beside it, because a salvage changed an outcome and a refusal did not. Fix tiers is the correction if the guess was wrong. "untracked"survives as a real refusal for the one case that is a broken session rather than a stray roll: no ranges to fall back to at all.
Found while writing the test, and left alone deliberately: LootSession's own DEFAULT_RANGES puts
off-spec at 1-99 while Settings.DEFAULTS.osMax is 1000. Nothing in the addon hits it -- every
production caller passes real ranges built from the settings -- but a caller that passed none would announce
one number to the raid and classify against another. Recorded in Tests/strayroll_spec.lua at the fixture
that tripped over it rather than changed, because changing a shared default to fix a case nothing reaches is
how the next bug gets in.
Removed -- the Distribute mats button
"do we need the distrubute mats button, or can we remove that button? it was always confusing and it's better to have it as a setting". Gone from the loot table's corpse row.
It was confusing for a reason worth writing down, because that reason is what makes removing it correct
rather than merely tidier: it was a button that encoded a POLICY. Pressing it meant "greys are handed out
at random in this guild" -- a standing rule about how the raid runs, being re-decided per corpse by whoever
happened to be looting, with nothing anywhere recording the answer. matsAction is that rule stated once, by
an officer, pushed to the raid, and applied to every corpse without anybody having to find a button on one.
The engine is not deleted. ML:DistributeMats still exists and still does the loot-slot walk; what went
is the manual caller. ML:AutoDistributeMats is now its only route in, and it prints the count to your chat
frame -- the status line it used to write to lives on the Master Loot window, which is stood down on this
path, so items would otherwise have left the corpse with no acknowledgement anywhere.
Knock-on tidying, all of it because the button was the stated reason for the thing:
UI:ShowNoticeno longer draws the corpse button row. Its own comment read "THE CORPSE BAR IS THE POINT, not the text" -- that was true when the bar carried the button, and with it gone the row would be an empty strip under a sentence.f.bar2now carries Fix tiers alone.- The
ml_no_itemsnotice survives as an answer to a deliberate press and nothing more./dibs looton an open corpse survives too, on its other two reasons: putting a corpse up on demand, and getting back in after finishing a table too early. - Both locale strings (
ml_distribute_mats,ml_distribute_mats_tip) are deleted, and the protected-list tooltip no longer names a button that does not exist. A spec now asserts the button andUI:DistributeMatsstay gone -- the obvious future mistake is to see a one-caller function and give it a button back.
KNOWN COST: Hand out at random is the only thing in Dibs that moves loot with nobody pressing anything, which is the exact opposite of the rule the roll fix above just established. That is deliberate and the two are consistent: a roll is a decision with a winner, a countdown and a record; scattering greys is the officer having decided once, in Settings, that greys are not worth a decision. It is off by default.
Fixed -- the loot window stopped opening on every trash mob
Reported from a live raid: "ML window appears every time looting a corpse, even if corpse is blank."
v0.4.3 fixed half of this and the half it fixed was the rarer one. That release taught LOOT_OPENED to
tell two corpses apart: one holding items below the loot threshold -- greys, cloth, a stack of Linen --
and one holding no items at all (money only, or already looted). The second got no window. The first kept
the No tradeable loot on the corpse. notice, on the reasoning that Distribute mats acts on exactly that
corpse and lives on that notice.
That reasoning is true and it is beside the point. A raid pulls dozens of trash mobs an hour and nearly every one of them drops something below threshold, so "greys get a notice" is a window on nearly every corpse in the instance -- which is the report, word for word. From the master looter's seat the two corpses are the same corpse: neither has anything the raid can roll for.
The rule, stated once so the next change can be measured against it: a button you pressed deserves an
answer, an event you did not ask for does not deserve a window. LOOT_OPENED now opens nothing at all when
the drop has no above-threshold item in it -- no loot table, no notice, and no Master Loot window.
The notice is not gone, it is on demand. Two entry points still produce it, and both are things the master looter did deliberately:
- the
Loot tablebutton on the Master Loot window, unchanged; /dibs loot, which previously only re-opened a live table and now falls back to building one for the corpse you are standing on. That is the master looter's route to Distribute mats on a mats corpse.
/dibs loot is gated on the same check the event handler makes (ML.BlockedNow), which is not
housekeeping: OpenLootTable runs StartTable and BroadcastTable, so a raider typing the command out of
habit would put a second loot authority on the wire. The command can do nothing the corpse could not have
done by itself. When the loot table refuses the notice outright, the reason lands on the Master Loot window's
status line and the command shows that window -- it is built hidden, so otherwise the explanation goes to
a frame nobody can see and the command looks like it did nothing.
Internal
scanLootItemslost its second return value. It counted loot slots holding an item at any quality, and existed purely to tell those two corpses apart; with both answered the same way it was dead weight carrying a comment that claimed to be load-bearing.- The guard sits in the
LOOT_OPENEDhandler and deliberately not inML:OpenLootTable. A guard put insideOpenLootTablewould satisfy every "no window on a blank corpse" test and take Distribute mats away permanently, since both deliberate entry points go through it.Tests\loottableautopop_spec.luanow asserts that corner directly, so the shortcut turns the suite red. - Two specs that pinned the auto-notice were rewritten onto the button path rather than re-baselined away, and two were added: a corpse of greys is silent on the event, and walking over one does not force-close a forgotten table on the previous corpse.
- Suite: 3572 passed, 0 failed, run this session.
[v0.4.3] -- rolls wait for the raid, empty corpses stay quiet, and the drop tells you if it is an upgrade
Added -- the roll window tells you whether it is an upgrade, without a hover
Requested 2026-08-20: "show the +/- ep of the item against what you're currently wearing in the roll window next to the gear item, so you can see if it's an upgrade for your current role/class by just looking at the roll window. this shouldn't be a tooltip, you need to add an EP column and show the + in green or the - in red just like we do in the planner".
The roll popup now carries the same vs. yours column the Loots browser, the Planner, the Master Loot
window and the loot table already had: a green +40 or a red -15 against what you are wearing in that
slot, drawn beside the item name. Both prompts get it -- the master looter's roll call and Blizzard's own
group-loot roll.
It refuses to answer rather than guess, in two cases, because a raider under a countdown will believe a green number:
- A random-suffix drop ("of the Owl"). The stats live in the suffix, so scoring the base item is a
confident answer about a different item. Blank instead.
Declaration.TierForItemwithholds its stat axes for the same reason. - An item this character cannot use. Without that gate the scorer still reads the stats, so a wand's DPS lands on a hunter's ranged weight and prints confident nonsense.
One implementation, not a fifth. Both refusals moved out of GUI\LootTable.lua, where they were a local,
into Loadout.DropDeltaText -- the roll window would otherwise have been the second copy of both, and a guard
that lives in three places is a guard that will be correct in two. The loot table now calls the same helper,
and its spec loads the real module rather than a stub, so deleting the production guard turns those tests red
instead of leaving them green.
Tests/rollepcol_spec.lua, 11 tests. The one it exists for is the pooled frame: these popups are recycled
between rolls, so a show path that stays silent inherits the previous item's number -- and the case that must
say nothing is exactly the case that would inherit a green +40.
Fixed -- the same low-level crash again, from two more directions
The level-2 script ran too long report carried four tracebacks, not two, and they had two
independent causes. The talent-cache fix below covers two of them. These are the other two, raised by
ItemDB as IDBREQ-DIBS-001 after it benchmarked its own library and found the remaining cost was on Dibs'
side:
ItemDB/LibItemDB-1.0.lua:259 -- via GetStats, under attackOpts <- Loots browser, per row
ItemDB/LibItemDB-1.0.lua:2308 -- under Loadout:BuffEP <- Planner summary
Neither named line was the cause, and ItemDB said so rather than fixing the line it landed on: script ran too long is the client's watchdog and it fires wherever the interpreter happens to be when the budget
for the whole click runs out. The time had already been spent in the loop above.
Dibs was re-reading what you are wearing on every row. Scoring one item asked what is in your main hand
and your ranged slot, and looked up both -- and that answer cannot change between two rows of one refresh.
The Loots browser under "All sources" emits a row for every item in the loot graph and did the whole lookup
for each, then Loadout:EquippedEP re-scored your equipped piece on top of it, once more per row, when
there are at most seventeen distinct answers in a whole refresh.
Both are now read once and remembered until you change gear.
A fresh character pays the most, which is why this surfaced at level 2. ItemDB looked for a level-dependent path in its own library and found none. What a new character has is a starter thrown weapon in the ranged slot, so the ranged lookup does real work on every row instead of returning immediately -- a threshold on top of an already-too-expensive loop rather than a cause of its own.
Not fixed, and said rather than left to be found: the Loots browser still has no upper bound on how many rows it builds. Capping or paging what you can see changes the browser, which is your call and not something to decide inside a performance fix.
Fixed -- "script ran too long" on a low-level character, from the Planner
Reported from Classic Hardcore on a level 2 character:
1x ...Specialization/Deprecated_Specialization_Vanilla.lua:50: script ran too long
[Blizzard_DeprecatedSpecialization/...]:50: in function 'GetTalentInfo'
[Dibs/Data/ItemSources.lua]:1050: in function 'PlayerClassSpec'
[Dibs/Modules/Weights.lua]:163: in function '?'
[Dibs/Data/ItemSources.lua]:1746: in function 'GetSetBonusEP'
[Dibs/GUI/Planner.lua]:1757 ... :515 ... :254
Spec detection has a cache, and it was keyed on the wrong thing. PlayerClassSpec walks the three talent
trees and takes the one with the most points spent, then remembers the answer. It stored that answer only
when it found points spent, on the reasoning that zero points meant the talent data had not loaded yet.
That reasoning is wrong, and a level 2 character is the proof. Nobody below level 10 has a point to spend,
so the cache could never fill and the result was re-derived from scratch on every single call. That would
be harmless if it were called once -- but Weights:Source asks it per item, and the Planner scores
hundreds of items in one frame. Each answer walked all three trees, and each talent went through the client's
deprecation shim. Tens of thousands of engine calls in a single frame is exactly what the watchdog stops.
The two states are distinguishable and now are: GetNumTalents reports the size of the tree, which is
populated before anyone has spent anything, so it says whether the data is there while the points say what
the player has done. A character with no points now caches "default" once, and spending the first point
invalidates it through the same CHARACTER_POINTS_CHANGED handler a respec already used.
Also fixed on the way, and it was silent: Dibs called the bare GetTalentInfo, which in this client is
only a deprecation fallback -- it exists solely when the loadDeprecationFallbacks CVar is on, and its
whole body forwards to C_SpecializationInfo.GetTalentInfo. Anyone running with that CVar off had no such
global, so spec detection silently failed and scored them as "default" for ever. Dibs now calls the real API
and keeps the old global only as a fallback.
Pinned by nine tests that count the talent reads rather than checking the answer -- the returned spec was correct throughout, so a test asserting it passes perfectly against the bug. Red-tested: with the old cache condition restored, fifty-one calls make 765 reads instead of 15.
Fixed -- a winner was declared before the raid had finished rolling
Reported from a live raid, and it is the worst thing this addon can get wrong -- an item handed to the wrong person:
Galdof rolls 70 (1-100)
[Galdof]: Roll on [Battle Chain Pants] -- /roll 100 (MS), /roll 1000 (OS)
[Galdof]: Winner: Galdof (70)
Toglowweap rolls 12 (1-100)
"and now it chose a winner before all the rolls were in".
The chat announce and the early-end roster disagreed. A loot-table row ends its roll as soon as everyone
it is waiting on has rolled, and that list was built from who had picked the row on the table -- on the
documented grounds that a blank row carries no claim. But the announce RunTableRow sends invites the
whole raid to /roll, blank-row players and non-Dibs players alike. So a row one person had picked
resolved the instant that person's dice landed, while everybody else was still reading the line telling them
to roll.
Modules/LootTable.lua grows RowAnswered(t, key): has every player who may act on this row actually
answered it, counting a Pass as an answer and ignoring anyone a gated row does not admit. GUI/LootTable.lua
now hands the roll an early-end roster only when that is true; otherwise it hands over nothing, which is the
documented "no roster to measure against" and leaves the countdown as the only end.
The cost, stated rather than hidden: a row somebody left blank now runs its full countdown, which is the other half of an earlier report ("it waits like 15-20s after all the rolls are in"). That complaint is still answered whenever the raid actually answers the table, and Pass is a button on every row. Waiting costs seconds. Resolving early costs somebody the item.
Fixed -- an empty corpse popped a window saying there was nothing on it
"and now i'm getting this on an empty corpse", with a screenshot of the loot table window holding nothing
but No tradeable loot on the corpse. and a Distribute mats button.
Two corpses looked identical to the code and want opposite answers. The auto-open asked only whether anything above the loot threshold had dropped. That is empty for a corpse of greys and mats -- which is exactly what that notice and that button exist for -- and equally empty for a corpse with nothing lootable on it at all, money-only or already looted. Both got the notice.
scanLootItems now also reports how many loot slots held an item at any quality, which is the half that
tells them apart. A corpse with none gets no window; the mats corpse keeps its notice and its button. The
Loot table button still answers on both, deliberately: a button you pressed deserves an answer, an event you
did not ask for does not deserve a window.
The corpse is now read before anything else in the handler runs, which matters more than it reads: restarting a forgotten table force-closes the previous corpse's table past its confirmation, and doing that on the way to opening nothing would have thrown the raid's selections away for a blank screen. Still exactly one read of the corpse per event.
Fixed -- 12px of dead space between the row list and the roster column
"why can't you get the 0 picked row in the same column as the waiting and done column? why is it to the left?"
Two insets were adding up: the row list left an 8px gutter before the sidebar, and the roster text was inset
another 4px inside it. Both are gone, so the count now ends about 4px short of where Waiting and Done
begin instead of 16px.
It still cannot share their left edge, and this is the reason rather than another restatement. A scroll
frame clips its children, so the count can never be drawn right of the row list's edge; the sidebar begins at
that edge, so its text can never be drawn left of it. The count is right-aligned to the list edge, which puts
its left edge one label-width -- about 74px -- earlier. Moving the list edge left moves the count left by the
same amount. The gap is the width of the words 0 picked, and no anchoring shrinks it. The remedies left
are structural -- take the roster out of a right-hand sidebar, or make the count a bare number -- and both are
your call, not a layout tweak.
Fixed -- the loot table was too narrow to show an item name on the masterlooter's side
Reported with a screenshot: "the item name is completely truncated on the ML side, the window needs to be
wider. it's fine on the normal raider side." The name read [Anc....
The two faces need different widths and had one number. The masterlooter's face spends 150px on the roster sidebar and about another 110 on the per-row Unlock and Roll controls -- neither of which the raider's face draws. At the shared width that left the name roughly 60px. The raider's face keeps the full width, which is exactly why the same number looked fine on one side and broken on the other.
The masterlooter's face now opens wider, applied as a floor: a window you have dragged wider keeps its width, and only one too narrow to show an item name is pushed out.
Added -- the loot table resizes, and remembers the size
"we need the grabber to make the window resize." There is a grip in the bottom-right corner. Drag it to resize; the size is saved and comes back with the window.
The grip resizes and the window body moves, deliberately kept apart -- one mouse button cannot mean both on the same surface, and a window that stretches when you meant to shove it out of the way mid-pull is worse than one that does not resize at all. The rows re-lay-out as you drag rather than after you let go.
It uses the shared widget library's resize framework, which landed in the library the same day, rather than a private copy. That framework is also what the suite's own windows use, so resizing behaves the same everywhere instead of being a property of one widget type. A hand-rolled grip stays behind a feature-detect for anyone running an older copy of the library, and a test asserts the shared path is the one taken -- otherwise "we use the library now" is a claim nothing checks.
The size is saved on its own rather than through the library's combined position-and-size store: this window already remembers its position separately, and one fact with two homes is how the two come to disagree.
Fixed -- "N picked" floated on its own, three times, for three different reasons
"the 2 picked wording needs to be in the same column alignment as the waiting and done. it shouldn't be out on its own like it is."
Anchoring to a hidden control still positions it, and that one fact caused all three. A hidden button keeps its slot, so the chain of controls along the row's right-hand side developed holes -- and everything to the left of a hole was dragged further left with it. Fixing one anchor moved the hole rather than closing it: the count went out on its own, then under the buttons where a 42px row has no vertical space, then adrift again when the auto-tier feature started hiding one of Main-spec / Off-spec.
Nothing is anchored to a sibling that might be hidden any more. The row's right-hand side is laid out in one ordered walk, right to left, and each control hangs off the last visible thing placed. The count is placed first and takes the row's right edge, so it is the fixed point rather than the thing that drifts, and a control added later joins the list instead of being threaded into a chain.
The remaining gap to Waiting and Done is dealt with in its own entry at the top of this release, where the reason it cannot be closed is derived rather than asserted.
Changed -- the main window's contents keep up while you resize it
Asked for directly: "you should add the resizing to the main dibs UI too."
The main window has always been resizable -- it has drag grips on the bottom and right edges, and a minimum size that stops it being shrunk under the Planner. What it did not do was re-lay-out while you drag: the frame grew and everything inside it stayed put until you let go of the mouse. That reads as resizing being broken even though the window is resizing perfectly.
The contents now reflow continuously as you drag, on the main window and the settings window both. It is rate-limited to once per frame drawn rather than once per pixel of mouse movement, which is what makes a full re-layout affordable to do live at all.
Known limit, measured honestly: I have not profiled this on the heaviest surface (the Planner paperdoll). Once-per-frame is cheap in principle and the throttle is the reason it is safe to attempt, but "cheap enough on a 40-slot paperdoll" is an assumption until somebody drags one on a real client.
Fixed -- your own characters are one account without anybody declaring it
Reported with a screenshot of four of the reporter's own characters listed as four separate rows: "the main/alt sync between characters is still not working. it's also not showing the same account relationship yet."
Sync was not the problem, and saying so matters because it sends the next person to the wrong place. The saved data was read directly: not one declaration carried a main-character link. The picker that writes it ("Points go to", inside My Main / Alt) had never been used, so there was nothing to group on, and every character correctly fell back to being its own account.
The defect is that the addon could already prove those characters are one account and was not using it. The declarations it holds locally are, by definition, this WoW account's own characters -- other people's copies arrive by a separate route. Membership of that list is proof of a shared account and needs no declaration at all. The Accounts tab now groups on it.
It groups, and it refuses to invent a main. The account is real; which character heads it is not something a sort order can answer. So when nobody has declared, the head carries a dim "(main not set -- use My Main / Alt)" rather than being rendered as though somebody chose it. A declared main always wins and is never overridden, a character outside your own account is never folded in, and a single character on its own is left alone and not nagged. None of this writes the linkage field, which also moves DKP totals -- guessing into that would move points on the strength of an alphabetical sort.
Fixed -- the Accounts tab had a column called "Main / Alt" that was not about mains and alts
On a tab whose whole subject is which characters are the same person, the third column was headed
Main / Alt and showed fury / protection -- your main spec and your off spec. Reading that as an answer
about main and alt characters is the obvious reading, and it is wrong.
It is now headed Specs, and its tooltip says where the real answer is: the main/alt relationship is the indenting in the Character column, where an alt sits underneath its main.
Fixed -- the masterlooter's own answer was filed under a name their own roster did not contain
Peer review finding 174. The loot table's roster and the table's selections were written by two different pieces of code through two different name normalizers, and only one of them had been canonicalised. A raider's answer arrived through the sync layer and was cleaned up at the boundary; the masterlooter's own click went in raw.
When those two spellings differ for the masterlooter, their selection is stored under a key that is not on
the roster it gets measured against. So they are counted as still waiting on their own answer, for ever:
the "everyone has answered" check can never come true, and the clock goes back to being the only thing that
can end selection -- which is precisely the "why is the timer still counting? the rolls are in" report that
the check was built to remove. The tell is distinctive: Waiting (1) naming the masterlooter, with their
choices visibly made on the rows in front of them.
Fixed at the writer. The masterlooter's click now goes through the same canonical spelling every raider's already did, so one table holds one spelling. A sibling module solved the same collision with tolerant readers instead; that was right for it and wrong here, because this table is compared by index and a tolerant read is not available to it.
And fixing only the writer broke five readers, which is the second half of the same entry. Peer review finding 175, raised against the fix above. Five other places read that table back under the old spelling, and before the fix they had all been wrong together -- which is why reading your own answer worked at all. Canonicalising the write alone split that agreement. The expensive one is the handover: when a masterlooter drops and someone else takes over, every raider re-sends their own answers by looking them up under their own name, and that lookup started finding nothing. It silently re-sent nothing at all, so the new masterlooter never learned that raider had answered -- a total loss of one player's selections at the exact moment the resume exists to preserve them. Also affected: a row you had answered could redraw as unanswered, and an unlock the masterlooter granted could be refused on your window.
There is now one function that spells your own name the way this window files things under, and all six places call it. A helper rather than six edits on purpose: six call sites is six chances to miss one, and the seventh has something to ask.
Both halves are now pinned by tests, and the premise behind them was measured rather than assumed. The first version of this entry said reproducing it needed two clients whose normalizers disagree. That was wrong: it needs one client whose two spellings of itself differ, which is what happens when the name library hands back a bare name and the other path expands it. Five new tests drive exactly that, and the handover one was confirmed by putting the bug back and watching it report zero answers re-sent instead of two. What is still unverified is whether any particular live client has the divergence at all -- the fix is correct either way, because one table with two writers and a raw comparison is a bug waiting on a library update.
Changed -- one window on the corpse, not two
Reported from a live raid with a screenshot of both windows up at once: "i'm still getting the other window." Looting a boss opened the loot table and the old Master Loot window, side by side, listing the same drop twice.
The loot table is now the window. Open a boss with real loot and you get one window.
The refusals land on the loot table too, as a notice rather than a table: an auction raid, and a corpse
with nothing above the loot threshold. That is what closed the limit this section originally shipped with --
Distribute mats moved onto the loot table, so a corpse of greys had to have a window carrying it, and the
notice is that window. The Master Loot window is now the fallback only when the notice itself cannot be
shown -- no widget library, or a live table that must not be painted over -- because a refusal nobody can read
is worse than an extra window.
A corpse with nothing lootable on it at all gets no window, which is a different corpse from the one above and is covered in its own entry at the top of this release.
Changed -- the roll timer is a bar again, under the item it belongs to
The countdown used to sit in the Master Loot window's title corner, which said how long was left and never what it was left on. On a boss with twelve drops that is the more useful half of the question.
It is now a thin orange bar across the row being rolled, draining smoothly until it is gone -- the same bar the old single-item roll prompt used. It appears on the row the master looter called and on no other, so the clock names its own item.
It was briefly a number instead, which was wrong twice over: a text line does not fit in a row that already carries an item name and a soft-reserve line, so it was drawn under the buttons, and a bar reads faster anyway.
Fixed -- forgetting to press Finish no longer costs you the next corpse
Reported live: "if i forget to finish, and start looting again, it should go ahead and finish and pull up the new loot window. it doesn't right now. i have to close and reloot."
Opening a corpse while an old loot table was still up did nothing at all, because the check was only "is a table already live". That check exists for a real reason -- re-opening the loot window on a boss you are part-way through fires the same event, and starting over there would throw away every selection the raid had already made -- but it could not tell that case from the next boss, and it answered both by leaving the stale table up.
Dibs now compares the drop against the table's rows. Everything on the corpse already on the table means the same corpse, and your selections are kept. Anything new means a new corpse: the old table is finished for you and this one opens. Items are matched including their random suffix, so two different "of the ..." versions of one item are two different drops.
A table you did not start -- one you are receiving as the raid's master loot changes hands -- is never closed out from under the raid.
Changed -- Fix tiers and Distribute mats moved onto the loot table
Both now sit on a second row of buttons at the bottom of the loot table, beside the clock controls rather than on a separate window. The two rows are split by what they act on: the top row is the table (start, pause, lock, begin, finish) and the bottom row is the corpse. The window is slightly taller to hold it.
Fixed -- "Decide main/alt for me" now tells you when it could not decide
Reported as a regression: "i have it set to auto and it's giving me the choice." It was not one. The setting had declined to answer for that particular drop, which is deliberate -- most often because the item has a random suffix, and a suffixed drop's stats are not on the base item, so scoring it would be scoring a different item. Dibs would rather ask than guess wrong.
The defect was that it never said so. Two buttons with the setting on looked exactly like two buttons with the setting off, so a correct refusal and a broken setting were the same picture -- and there was no way to tell which you had.
Such a row now carries a quiet "Auto tier could not decide -- pick one", and hovering either button names the actual cause: a random suffix, a Main/Alt declaration that is not finished, no declaration at all, or two bundles that score the item too closely to separate.
Fixed -- your main and off-spec choices never reached anybody after the first time
Reported from a live two-account test: "the sync problem is with syncing the main spec and alt spec choices." Rolling was "kinda working"; the declaration was not.
Saving a declaration never wrote a version number. It stamped when the declaration was locked and
stored it, and updatedAt -- the one field the declaration sync sorts on -- was left unset. So every
declaration this addon has ever saved travelled as version zero, and the receiving client's merge refuses
anything that is not strictly newer than what it already holds. Zero is never newer than zero.
The consequence is exact: a raider accepted the first declaration they ever saw from you, and silently discarded every change after it. Re-spec, re-declare, relog, whatever -- their copy of you was frozen at whatever you happened to be the first time your two clients met.
It failed in the direction that hides it. The change-detection hash does cover both spec choices, so the two clients correctly noticed they disagreed, correctly negotiated, and the record really was sent. It was thrown away on arrival, with no error and nothing in chat. From the outside that is indistinguishable from the message never being sent -- which is where four separate rounds of investigation went, including the three fixes already shipped in this version for the sync not running. Those were real and this is a different fault sitting behind them.
Declarations already saved are healed without anyone doing anything, and that mattered more than it looks: saving a declaration locks it, so "just save it again" would have meant every raider in a guild asking an officer to unlock them before their spec could ever sync. The lock stamp has always been written on every save, so it is used as the version when the newer field is missing. Nothing to migrate, nobody to ask.
Why the test suite was green through all of it, which is the part worth carrying. There is a passing test called "updates a declaration that has moved on, and converges". Its fixture wrote the version number straight into the store and never called the save path at all -- so it proved the transport works given an input that nothing in the addon produces. That is the fifth time a test in this project has honoured a precondition the real caller breaks. The new tests drive the actual save function, twice, across two clients.
Internal -- the first test that runs TWO clients, because that is where the last three bugs lived
Twenty-one spec files drive the loot modules and every one of them tests one client. The last three defects reported out of a live raid were not broken functions -- the loot table never reaching the raid, the masterlooter getting no roll prompt, and a raider being asked twice for an answer they had already given. All three were wires, all three passed a full green suite, and a unit test cannot ask the question that catches them: does anything trigger this, on every client that runs the path?
Tests/lootworkflow_spec.lua builds two real clients -- each with its own copy of the loot table model, its
wire module and its window -- and a bus that routes one client's broadcast into the other's registered
handler. It drives the boss's table from the masterlooter to a raider who never touched the masterlooter's
window, the raider's answer back as a whisper, the receipt back again, and the phase change that ends
selection. Driven red by cutting the bus: seven of the eight tests fail. The eighth is a negative and
stays green, which is stated in the file rather than left to be discovered.
What made this worth doing is what was in the way of it. Tests/loottablesync_spec.lua's header said
"the transport needs two clients and is not testable offline". That was false -- specs load into a
namespace they are handed, and the window keeps its state in a file-local, so two loads are two clients. It
is the same shape as the claim that frames could not be tested offline, which held a defect open for months:
a claim about what the tools cannot do has nothing pointed at it, and is believed precisely because it
reads as settled. The header is corrected and names the file that disproves it.
The bus is deliberately not a transport: no throttle, no queue, no loss. It proves a message is sent and acted on, and nothing about ordering under load or a client that misses one.
Fixed -- the roll popup asked you again for a choice you had already made on the loot table
Reported live: you tick MS, OS or Pass on the loot table, the masterlooter presses Roll, and a roll picker opens asking the same question. The first fix for this only fixed one person. The suppression was written into the code that starts a roll, which runs on the masterlooter's client and nowhere else -- so the masterlooter stopped being asked twice and every other raider in the group carried on being asked twice, down the path their prompt has always come from.
Both faces of the exchange now ask the same question through one shared check: do I already hold this player's answer for this item? By item, because that is the only identity the two windows share -- a second drop off the same corpse still gets its own prompt, and a drop the table has no answer for still prompts, because there is otherwise no way to ask you at all.
It suppresses the question, never the roll. The answer the table already holds is the one the row acts on; nothing about the session, the tally or the countdown is touched.
Fixed -- an advantage announced the lower of the two rolls
From a raid chat log, and it is the sharpest defect found this round:
Reported live: "Advantage -- roll ONE range twice ... Your higher roll counts", then rolls 41, then
rolls 59, then "Winner: 41". Best-of-two announced the lower roll.
The cause is a name spelling. Every lookup in the roll session is realm-tolerant except the one that decides
how many rolls you are allowed, which used the name as a raw key. The eligible list is built from the
group roster and is realm-qualified (Thorium-Azuresong); a /roll arrives from the game as a bare name
(Thorium). They did not match, the cap fell back to one, the second roll was refused as a duplicate, and
best-of-two had only one roll to choose from. The player was publicly promised two rolls, took them, and
had one silently discarded.
The test that should have caught it honoured a precondition the real caller breaks -- it flagged and rolled under the same spelling. The new tests drive the mismatched pair with the raid's own numbers, plus the negative: an unflagged player still gets exactly one roll, so a too-eager match cannot hand the whole raid an advantage.
Fixed -- the loot table kept counting down after everybody had answered
Screenshot: "Waiting (0) -- Everyone has answered", "Done (2)", "2 of 2 have finished" -- and the clock still running from 114 seconds. Nothing ever consulted the waiting list emptying; only the clock could end a selection.
Selection now closes as soon as nobody is outstanding, from both routes into it -- the masterlooter's own click and a raider's whispered answer. Masterlooter only: a raider must never be able to close selection for the raid. It runs through the same code the clock expiry runs through, so an early close and a timed one are identical downstream. An empty roster counts as "not everyone", not as "everyone" -- otherwise a table built before the roster resolved would lock itself the instant it opened.
Fixed -- a roll could be opened for the whole raid and answerable by only some of it
Peer review finding 163. Whether a roll is restricted to reserve holders was computed twice -- once when the session opened and once when it was broadcast -- and the name picker opens between the two reads. That setting is officer-pushed, so it can change in that gap. Open unrestricted plus broadcast restricted means the session waits on the entire raid while only the competitors are ever prompted, so the "everyone has answered" check can never come out true and the roll burns its full countdown.
That is the same symptom as the masterlooter's missing prompt, arriving by a completely independent route -- which is why fixing the prompt did not fully fix the timer. It is computed once now and passed along.
Fixed -- the Main / Alt window drew its status message through its own buttons
Reported with a screenshot. The status line was inset far enough to clear the Save button and nothing else, and the Request unlock button is wider -- and exists only in the locked state, which is the one state with the longest message to show.
Third instance of this exact shape (the masterlooter status line and the priority picker were the other two), so this one is pinned by a test that measures where things actually land on screen rather than what they are anchored to. An anchor test would have passed on all three. The status line now has a full-width row to itself and the window grew to fit it.
Fixed -- Dibs now speaks again when the group changes, not only at login
A guildmate who logs in ten minutes after you would never receive your declarations, because the exchange is one-directional -- the client that speaks learns what the other holds, and the one that listens does not -- and Dibs only ever spoke at login plus a handful of button presses. The first person online broadcast into an empty room and was then finished broadcasting for the session.
Dibs now re-broadcasts when the group roster changes, debounced so an invite storm costs one pass.
The bug this nearly introduced is worth recording: the login handler used to unregister all of its events once login was done. Adding a second event to that same frame would have killed it on the first login before it ever fired. It now unregisters only the one it is finished with.
Internal -- three claims in the code that were not true
Peer review findings 164, 165 and 166, all documentation-shaped and all wrong in the direction that invites a bad change later.
164: a comment asserted that the masterlooter does not receive their own raid broadcast, and other reasoning was built on top of it. They do receive it -- the client echoes, the comms library applies no self-filter, DeltaSync filters its own echo in eight separate handlers and another addon in this suite is built on the loopback. The comment is corrected. This also means the original missing prompt report has a cause still unidentified, and the comment now names the three places to look.
165: a call I had described as dead code stopped being dead the moment the "Fix tiers" repair landed, and what was preventing a second award was an unrelated nil-check rather than unreachability -- one line away from a post-award correction handing over an item that has already gone, logging it twice and charging for it twice. The call is deleted outright and replaced by a refusal that names all four non-idempotent effects.
166: the loot-table sync header said five message types, listed six and registered eight.
Fixed -- "Fix tiers" did nothing, and it was the moment it is most wanted that broke it
Reported live: "fix tiers does nothing." The button was drawn, its tooltip worked, and clicking it opened nothing at all.
Reading the path found it correct, four times over, which is why it survived: the button is wired, its handler exists, the picker frame is built, and the last line of that builder shows it. Every piece was fine. What none of the readings noticed is that two correct decisions cancelled each other out.
The Fix-tiers button deliberately stays on screen after the roll resolves -- that is the whole point of it, because a wrong tier is noticed when the winner is announced, and a button that vanished at resolution would disappear at the exact moment it is wanted. Separately, and just as deliberately, resolving a roll clears the roll's state, because a finished roll left lying around reads as a live one and other things branch on that. So from the instant the winner was announced the button was live, visible, and pointed at nothing. Its handler's first line asks for the roll it is correcting, does not find one, and returns. No error, no message, nothing on screen -- which in game is indistinguishable from a dead button.
The last finished roll is now kept for exactly as long as the button offers to correct it: until the next item is rolled, or the loot window closes. That is the lifetime the button was always documented as having.
It deliberately does NOT re-award the item. Restoring the whole roll would send a post-award correction back through the award path -- handing over an item that has already gone out, logging it twice and charging for it twice. A correction made after the winner was announced changes the record and is announced to the raid, as it always was; it does not move loot that has already moved.
Found offline, in a test, rather than in another raid. The picker had never been driven by the suite at
all, so a new spec builds it, clicks its rows and applies a correction -- and then drives the real thing:
a real roll, real /roll messages arriving through chat, a real resolution, and then the button. That last
part fails with "Fix tiers did nothing after the winner was announced" against the old code, which is the
report in the reporter's own words.
Fixed -- the masterlooter got no roll prompt, and that is also why the countdown never ended early
Reported live, three times, with a screenshot each time: "the ML needs the 3rd popup everyone else on the raid gets so they can chose to roll or pass."
The masterlooter had the loot table and the Master Loot window and no way to want the item themselves. They now get the same roll prompt every other raider gets, on every roll they start.
The second symptom is the one worth reading, because nothing about it looks related. Reported separately: "with auto-roll on, the roll timer does not end when everyone has rolled." A Dibs roll ends early once everyone has answered -- and "everyone" is the group roster, which includes the masterlooter. With no window to answer in, they were permanently outstanding, so the check could never come out true and every roll burned its full countdown however fast the raid answered. The screenshot said it in as many words: "Waiting (2) Galdof, Togcloth ... 0 of 2 have finished", with Galdof holding master loot. One missing window, two bugs.
The prompt is drawn locally rather than waiting for the broadcast to come back round. Whether an addon message sent to the raid returns to its own sender is the game's business, and the return trip also passes a gate written for other people's messages. None of that belongs on the path to your own client drawing your own window. If a copy does arrive, the prompt already refuses a duplicate for an item it is showing.
The loot table is untouched by this: the table runs its rows through a path that deliberately does not send that message, precisely so a second prompt never lands on top of it.
Fixed -- changing the loot table's countdown did nothing until the next boss
Reported live: "i also updated the time from 120s to 20s for the timer, and it didn't 'take'."
It had taken -- the setting saved correctly. Nothing on an open table ever read it again. The length is sampled once, when the table is built, so pressing Restart replayed the length the table was born with and the new number would not have appeared until the next corpse. From the outside that is indistinguishable from a setting that failed to save, which is exactly how it was reported.
Restart now re-reads the setting, and tells the raid the new number so nobody's clock disagrees with the masterlooter's. It is the right place and the only place: a running clock must never change length under a raid that is already answering against it, and Restart is the one control whose whole meaning is "start this again, properly this time". A setting that cannot be read leaves the current length alone and still restarts, and zero or negative is refused rather than locking the table the instant it starts.
Fixed -- the masterlooter was the one person who could not answer their own loot table
Reported with a screenshot: the table's roster read "Waiting (1) Galdof" against a status line saying "Selection open -- 1 of 2 have finished", and there was no control anywhere on screen that could make it 2 of 2. Galdof was the masterlooter.
The masterlooter's view of the table drew its own controls -- call this row, correct that one -- and hid the Main / Off-spec / Pass buttons outright. So the person standing on the corpse, who has a main and an alt like everybody else and whose own upgrade value the Master Loot window is already showing them, was structurally unable to want anything.
They get the same three buttons as the raid now, on the same rows, beside the controls they already had. "the ML needs the 3rd popup everyone else on the raid gets so they can chose to roll or pass." Not a separate window: a second copy of the same table is exactly what was rejected when the loot table's design was settled, and the row already had the space.
Changed -- with "Decide main/alt for me" on, the loot table asks Roll or Pass, not MS or OS
"when i have the auto select on, shouldn't it just be roll/pass, and the ms/os is done by the auto bit? it's set up right for ms/os when the autoroll is OFF."
The roll prompt has collapsed its two tier buttons into one since the setting shipped. The loot table never did -- so a player who had switched on the one option whose entire purpose is to stop asking which tier they are rolling was still being asked, on every row of every boss. That is many more times than the prompt asks it, which made the setting look broken rather than partial.
A row the setup can decide now shows one Roll and a Pass. Pass is never collapsed away, because the setting removes the main-versus-alt choice and never the choice of whether you want the item at all. A row it cannot decide keeps both buttons -- random-suffix drops in particular, which cannot be scored from the base item at all and must never be guessed.
The label changed and the choice did not. The button still sends the tier your setup picked, with that tier's roll range, and the tooltip names which one it was and how to switch the setting off. A test pins the sent tier specifically, because the failure that matters here is silent: a Roll button that quietly sent the wrong range would cost somebody an item with nothing on screen to say so.
Added -- the loot table now tells you who won each item, and on what roll
Reported live: "we need to update this on the users side with the roll info somehow. show the rolls and who won."
A raider picked their items, the window said "Selection is closed. Wait for the master looter to call each item", and then nothing on it ever changed again. It showed your own receipt -- your answer arrived -- and never the outcome, so the only record of who actually got the drop was raid chat scrolling past.
The reason was structural rather than an oversight in the window: the table's messages describe it being built, clocked, called and closed, and not one of them carried a result. The masterlooter's own copy had the winner and the winning roll the whole time; nothing sent it.
Each row now shows the winner and their roll as soon as the masterlooter resolves it, in the same words their window uses, so the two cannot describe one result differently. A row nobody won says so -- that is a real outcome and the difference between being beaten and the item going nowhere. The receipt is replaced rather than kept beside it, since a green "Received" on an item that has already gone to somebody else reads as though you still have something pending.
Only the winning roll travels, not the whole tally: every roll was already public in chat when it happened.
What chat does not carry is which item a given /roll belonged to, and that is exactly the winner line.
Fixed -- the loot table is the raid's window, and it only ever arrived if the masterlooter fetched it
Reported from a live run in Ragefire Chasm: a raider only saw the loot table when the masterlooter opened it by hand from the Master Loot window. "that's the wrong behaviour."
It is the raid's window, not the masterlooter's. "the loot table is for the rest of the raid, not the ML ... it should popup for every use like the ML one does for the ML ... the ML should get both." The whole point of it is that every raider sees the boss's drops as one list and marks what they want before anything is rolled -- so a table that arrives only when one person remembers to send it is a table the raid mostly never sees.
Every piece of this already worked, which is why it lasted. The masterlooter's snapshot of the corpse was correct. The broadcast was correct. A raider receiving one already popped their window open on its own. The only thing missing was the trigger: nothing started the table except a button. It now starts on the same event the masterlooter's own window opens on -- looting the boss -- so both windows arrive together, for everyone, with no one having to remember anything.
It will not restart a table that is already running. Re-opening the same corpse would otherwise mint a fresh table and throw away every selection the raid had already made, and nothing would have reported it -- the window would simply be blank again. The two refusals the button always had are unchanged and now apply automatically: nothing opens in an auction raid, and nothing opens on a corpse with no items above the loot threshold.
Fixed -- whoever logged in first stopped talking, and never started again
This is the second half of the Accounts-tab report, and it is the half that explains why the tab was still wrong after the first fix and a reload. The view was reading the wrong list; that is fixed above. But there was nothing in the peer list to read, because Dibs announced itself once at login and then never again for the rest of the session.
Dibs sends its content hashes when you log in, and after that only when you actually change something -- edit a wishlist, save a Main / Alt. Everything else was supposed to be covered by the sync library's catch-up: if a broadcast finds nobody, it tries again a few times over the next few minutes, which is exactly what happens when your guildmate loads in three minutes after you do.
Dibs had that switched off. hasMissingItems is the sync library's question "do you still need anything
from a peer?", and Dibs answered a flat no -- which the library reads as "I am complete, do not retry"
and abandons catch-up permanently, for the life of the session. So the first person online broadcast into an
empty room and was finished broadcasting forever. Nobody was dropping the data; nobody was ever asked for it
a second time.
It now answers yes, which is the honest answer: Dibs has no way to know whether somebody out there holds a declaration it has never seen. The cost is bounded by the sync library itself -- at most five retries about 45 seconds apart, then it stops on its own -- and Dibs keeps no state for it.
Worth recording how it hid for so long. The line carried a confident comment: "DeltaSync's hash compare drives offers; no extra hint". That sentence is true, and it is about a completely different mechanism -- offers, not catch-up. A sound rationale attached to the wrong subsystem reads as a considered decision, so the flag looked deliberate every time anyone passed it. Nothing in the test suite reached it either: the whole sync configuration block had never been driven offline even once. It is now, and the retry answer is pinned by a test that goes red if it is ever set back to no.
Fixed -- an automatic roll's button then claimed the drop was not for that tier
When Dibs rolls for you, the button it pressed stays on screen with its tooltip. That tooltip was reporting the opposite of the decision that had just been acted on -- telling you the drop was not for the tier it had this second rolled you into.
Nothing was rolled wrongly; the roll was right and the explanation beside it was wrong, which is arguably worse on an option whose whole job is to be trusted without being watched.
Internal -- one weapon-type lookup instead of three
The mapping from an item's weapon subclass to a weapon-skill token existed in the item module and was also
re-derived, slightly differently, at two of its call sites. Both duplicates are gone and both callers now go
through Items.WeaponTypeToken, which also refuses armour and non-weapon item classes outright rather than
trusting the caller to have checked -- the same class of defect as the cloth-read-as-a-two-hander bug below,
where a contract nothing enforced was quietly broken by its only caller.
Fixed -- the Accounts tab could only ever show you
Reported with a screenshot from each of two clients: two guildmates, in the same guild, in the same party, both with a saved Main/Alt -- and each one's Accounts tab listed only itself.
The sync was not the problem, and that is the part worth saying. Everyone's declarations were arriving correctly and had been all along. The tab was reading the wrong list: the one holding your own account's characters, rather than the one holding everyone's. So the single tab whose entire purpose is showing other people's mains and alts was the one place that could never show them.
It now reads both, with your own copy of your own character winning -- a copy of you that came back from somebody else can only be older than the one you are looking at.
Two more things were reading that same local-only list, and either would have kept the tab wrong after the rows appeared: the account grouping (so a guildmate's alt showed as a separate person instead of folding into their main) and the Locked column (which reported everybody else's declaration as open, whatever it actually was -- and "whose declaration is open right now" is the one thing an officer opens that list for).
Fixed -- an advantage rolled once instead of twice
Reported from a live raid: the group saw "Advantage -- Togcloth: roll ONE range twice ... Your higher roll counts" and then a single roll from Togcloth.
The second roll of an advantage is a second press of the button, which becomes Roll again after the first. Rolling automatically pressed it once and stopped -- so a player who had just been told in raid chat that they get two rolls quietly got one, with the window closing behind them so they could not even tell.
It takes both rolls now, in the same range as the first, exactly as pressing the button twice would. Players who were not given an advantage still roll once -- that half is pinned by its own test, because a fix that simply rolled twice would have had the whole raid double-rolling.
New -- Dibs can send the roll for you, not just pick which button to press
"i was hoping the addon would just do the roll automatically for each plyaer." Fair, and it is the original ask: "then the rolls just know if an item is for role a or b, it rolls 100 or 1000 automatically." Only the choosing half had shipped, so you were still clicking.
Roll for me automatically is a new per-player option on Loot & Rolls, directly beneath Decide main/alt for me. With both on, the roll goes out the moment the window opens and you never touch it.
It only ever fires when the other option picked a tier outright. It presses the button that decision left standing -- so when your Main / Alt setup cannot tell which tier a drop is for, both buttons are still there and you are still asked. The automatic roll can never be more confident than the decision behind it.
It is a separate switch on purpose. Wanting the tier chosen for you is not the same as wanting the roll sent for you, and only one of those cannot be taken back. Turning off Decide main/alt for me turns this off with it, since there is no single button left to press.
Off by default, and the reason is worth stating. With it on you roll on every drop your setup can classify -- including ones you did not want -- and you can win them. Your roll is public and cannot be withdrawn. It also leans toward main spec by design, which is the more socially expensive way to be wrong. Leave it off if you would rather look at the item first; the tooltip says all of this on the switch itself.
Under the hood it fires the kept button's own handler rather than rolling on its own, so it goes through the same roll, the same message to the master looter and the same receipt as a click. Anything that fixes the manual path fixes this one too, and the two cannot drift apart.
Fixed -- a hunter was being told to roll main spec on cloth
Reported live: "on a hunter i should not have MS roll for a cloth item."
Every check Dibs had asked which of your two setups a drop was for. None of them asked whether the drop was gear for your class at all. Cloth bracers on a hunter passed all three -- no weapon type to read, no spell school, and two gear scores that were identical because both of that player's setups named the same spec -- so the main-spec default answered, and answered main.
There is now a check ahead of the others: body armour lighter than the armour your class actually gears in is never a main-spec roll. It sits first and overrides the rest, because "this is not your armour type" outranks anything your two setups have to say about it.
It is not the same as "can you equip it". A hunter can put on cloth bracers -- nothing stops them, and Dibs already knew that. Being allowed to wear something is not the same as gearing in it, and the roll tier was reading the first as if it meant the second.
It knows about levelling, which is where this was reported from. Hunters and shamans do not train Mail until 40, and warriors and paladins do not train Plate until 40. Below that they gear one tier down, so a level 13 hunter's leather is still a main-spec drop and only cloth is demoted. If Dibs cannot read your level it assumes the trained armour rather than demoting everything.
It stays out of the way of everything that is not body armour. Cloaks, rings, necks and trinkets are worn by every class whatever their armour type, and weapons are not armour at all -- none of them are touched.
New -- the Master Loot window shows what a drop is worth against what you are wearing
Asked for looking at that window: "show the +/- ep of the item against what you're currently wearing ... so you can see if it's an upgrade for your current role/class by just looking", and explicitly not as a tooltip.
There is now a column beside each item, green for an upgrade and red for a downgrade, the same colours
and the same number the Loot browser's vs. yours column has always used. It is blank rather than zero when
the item is one you cannot use or one Dibs has no scores for, because a confident 0 on a drop that was
never scored is worse than saying nothing.
The value and its colours are now computed in one place shared by both windows, so the same drop cannot read as an upgrade in one and a downgrade in the other.
Fixed -- every cloth drop was being read as a two-handed weapon, and every plate drop as a one-hander
This is the actual cause of the automatic main/alt misfires, and it is not the one diagnosed earlier in this
version. /dibs tier on Crystalline Cuffs said it in one line:
axis 1 WEAPON: equipLoc=INVTYPE_WRIST subclass=1 -> two_hand
A pair of wrist bracers was classified as a two-handed weapon, matched the player's two-hand off-spec setup, and settled the tier before anything else was consulted.
WoW's subClassID is a different numbering for each kind of item, and the low numbers collide. As a
weapon, 1 is a two-handed axe; as armour, 1 is Cloth. 4 is a one-handed mace, or Plate. 0 is a one-handed axe,
or the Miscellaneous bucket that holds rings, necks and trinkets. Dibs was handing the classifier that number
for every item, weapon or not.
So the weapon check was not occasionally wrong, it was systematically wrong on armour: cloth read as
two_hand, plate as one_hand, and rings, necks and trinkets as one_hand. If your Main/Alt setup splits on
weapon type at all, whole armour classes were being sorted into a tier by nothing more than a number
collision. It now ignores the subclass unless the item is genuinely in a weapon slot.
Changed -- /dibs tier now names the axis that actually decided
The report listed all three checks and then the answer, leaving you to work out which one spoke. In the case above the EP numbers printed last, closest to the verdict, and looked like the cause -- while the real culprit sat two lines higher, correctly printed and easy to skim past. Each check now marks itself when it is the one that decides, notes when an earlier check already settled it, and points out when both your setups name the same spec (which makes their scores identical by construction and the EP check permanently silent).
Internal -- the test harness moved forward 25 commits, and the pin move found a guard nothing had ever run
Adopted the WoWAPITesting harness at 769c043 (from e4bbb3c, 25 commits). Every adoption-log entry in
between says "adopt: nothing" for Dibs, but two warn that installing new APIs can turn a suite red, which is
the fix working rather than a regression.
b8b9422 adds UnitGUID / UnitLevel / UnitExists / UnitIsPlayer to the offline environment. Dibs has
one feature-tested call among them -- Modules/BossTooltip.lua's "other players aren't loot sources" skip,
if unit and UnitIsPlayer and UnitIsPlayer(unit). With the global absent that guard fell through the and,
so it had never once executed in a test. I predicted the suite would go red on the pin move. It did not, and
that is the actual finding: no spec drove BossTooltip:Augment at all, so the branch was untested for two
independent reasons stacked on each other and fixing the harness half only revealed the gap.
New Tests/bosstooltip_spec.lua -- five tests over the function's guards: a player's tooltip is left alone, a
mob's is written to, a tooltip with a name but no unit token still matches, nothing is written when nothing of
yours drops there, and a blank or malformed tooltip does not raise. Driven red by deleting the guard.
UnitIsPlayer was also missing from both global lists, so luacheck reported it as undefined. Adding it to
.luacheckrc alone turned Tests/luaglobals_spec.lua red -- the guard that pins the two lists against each
other, catching exactly the drift the harness documents. Both lists now carry it.
The submodule pointer is not committed, so the checked-out harness is ahead of the recorded pin until it is.
Changed -- "Decide main/alt for me" now asks whether you are rolling for your MAIN, not which spec likes the item more
Reported live: "i'm getting OS on a clothie and this item is MS for a clothie." The drop was Crystalline Cuffs (+1 Intellect, +2 Spirit) and the player was a holy priest with a shadow off-spec.
The item was not a random-suffix item, so the fix above does not cover it. The setup was read correctly and the gear scores were right. The question being asked of them was the wrong question.
The old rule compared the two setups against each other: whichever one scored the item decisively higher won, and a close pair was refused. That answers "which of my two specs is this better for". Main-spec versus off-spec does not mean that. It means "am I rolling for my main?" -- and a holy priest rolling on intellect and spirit cloth is rolling for their main, whether or not the shadow set happens to want it too.
So the rule is no longer even-handed between your two setups, on purpose:
- Your main setup is the default. It keeps the item on ties, near-ties and anything it leads.
- Your off-spec only takes a drop when it decisively out-scores your main on it -- the same margin the old rule used, kept exactly rather than re-tuned, so nothing about a genuinely off-spec drop changes.
- An item neither of your setups can use is still refused, and you are asked. That test runs first, so a drop your class cannot use never falls into the main tier by default.
What this changes in practice: far fewer drops come back as "cannot tell, you pick". Two setups that want the same gear -- marksmanship and beast mastery, holy and discipline -- used to be unanswerable and now answer main, which is what you would have clicked. Weapons and spell schools are untouched: a dagger for a dagger off-spec is still a dagger, and that was never the comparison that went wrong.
Random-suffix drops are still asked, not guessed. That guard is about the item information being wrong at the source, and this change does not rescue it.
Changed -- "Decide main/alt for me" now actually decides it
Reported live: "i have it checked, but the ML window is still asking me to chose ms/os." It was. The setting greyed out the tier your declaration did not pick and left both buttons on screen -- so you were still looking at a main-spec button and an off-spec button and still had to pick one. A choice you still have to make is not a choice that was made for you.
When your Main/Alt setup can tell which tier a drop belongs to, only that tier's button is shown now. It rolls the range you would have rolled, and hovering it says the Main/Alt setup chose it and how to switch that off.
Pass is untouched, and there is always a roll button beside it. The setting takes away the main-vs-alt question, never the decision about whether you want the item -- and never leaves Pass as the only thing you can click, which is a mis-click nobody can take back.
When the drop cannot be told apart, both buttons stay and you are asked, exactly as before. That covers every random-suffix item (see above), any drop your class cannot use, and anything Dibs has no gear information for. (This paragraph originally also called two specs wanting the same gear the common case for being asked. The entry above, landed later in the same version, is what changed that: a near-tie now answers main rather than asking.)
Fixed -- the countdown kept running after everybody had already rolled
Reported live: "the timer is still counting down after all the rolls are in."
Dibs has always been able to end a roll the moment the last person answers -- that is what the game's own Need/Greed does, and it was built and wired. It could just never tell that the last person had answered.
The list of who a roll is waiting on is built from one source, and the answers coming back are filed under a name produced by a different one. Most of the time the two agree. When they don't -- and they don't for anyone the guild roster cannot identify, which includes pugs -- the two spellings of one player were compared letter by letter, didn't match, and that player stayed on the outstanding list for ever. They had rolled, the master looter could see the roll in the window, and the roll still sat there until the clock ran out.
Both spellings now count as the same person, through the same realm-tolerant comparison Dibs already uses everywhere else. A roll ends when the last answer is in.
It is still deliberately careful about who it is waiting on. Two characters with the same name on different realms stay two people, and a roll that includes anyone Dibs cannot hear from -- someone without the addon -- still runs its full countdown rather than finishing without them.
Fixed -- auto main/alt put a random-suffix drop in the wrong tier
Reported live: a holy priest was auto-tiered to alt on Aboriginal Footwraps of the Owl.
"of the Owl" is a random suffix, and every stat it grants lives there -- the base Aboriginal Footwraps
carries none of it. The tier resolver was handed the base item id, so it scored both of that player's
declared specs against a boot with essentially no stats. The gap between the two numbers was noise, and the
gap is all this test looks at: it needs the two scores to differ, not to mean anything. Noise cleared the
decisive-fit bar and picked a tier.
Dibs now recognises a random suffix on the link and withholds the two axes that read the item's stats, which drops the roll back to asking you -- the same thing it did before the setting existed. Being asked on a suffix drop is fine; being told the wrong tier is not.
The weapon axis still answers on those items, deliberately: a sword is a sword whatever suffix it rolled, because the slot and weapon type belong to the base item.
Expect this to decline more often than it used to, and that is the fix working. Random-suffix armour is a common drop class -- the Aboriginal / Owl / Eagle / Wolf families come off ordinary dungeon bosses constantly -- so every one of those now asks you instead of answering. It was answering before; it was just as likely to be wrong as right, because it was reading an item that does not exist. Said here rather than left to be noticed on a raid night.
Known limit, stated rather than left to be found: this is the narrow fix. Scoring the suffixed link properly -- so a holy priest's spirit boots actually resolve to main -- is the complete one and is a wider change; for now those drops ask instead of guessing.
The oldest v0.4.3 entries, all of v0.4.2 and v0.4.1, and every version from v0.4.0 back, have moved to
CHANGELOG_ARCHIVE.md -- this file has to stay under GitHub's 125,000-character
release-body limit, which Tests/pkgmetaclaims_spec.lua now asserts at 120,000 rather than leaving to
whoever happens to remember it. v0.4.3 passed that cap on its own, so once v0.4.2 was moved there was no
version boundary left to split at; the archive's own header records the three earlier times v0.4.1 needed
the same treatment.
All Relations
- All Relations
- Embedded Library
- Optional Dependency
- Required Dependency
- Tool
- Incompatible
- Include

