druids get their relic slot, and the loot window is the reference's own
- `UnitHasRelicSlot` is real in 1.12 and benilla had no binding for it: `0x519e50` reads `ChrClasses.dbc` field 16 — set for Paladin, Shaman and Druid in `patch.MPQ`'s 17-column copy (the base `dbc.MPQ` copy has 16 columns and no such field, which is how the "always false in vanilla" belief survived twice in decisions and seven times in code) — and stock `PaperDollFrame.lua` calls it unconditionally, so the character sheet would have raised for EVERY class; a druid, paladin or shaman's sheet now hides the ammo slot, shows the relic plate where the bow was, tooltips "Relic", and reports ranged Attack/Damage/Power as N/A, all four branches transcribed from the reference - the loot window is the reference's own `LootFrame.xml`: `LootButton` is built as a real widget type rather than aliased (a Button plus one slot dword and one overridden OnClick — right-click loots exactly like left, no shift/ctrl/alt takes, a row whose Lua handler errored still loots, a fast double-click takes two slots), `LOOT_SLOT_CLEARED` fires per row again because the stock file hangs hide-in-place AND the emptied-page auto-advance off it, `EditBox:Insert(nil)` is a no-op as `lua_tostring` makes it, and an alias `GameTooltip.xml` had quietly become a reader of would have turned every item tooltip white, silently, had it just gone nil - the vendor cursor: `PickupMerchantItem` is two verbs behind one name, decided by what the cursor holds and never by the caller — a held bag item SELLS (index ignored, no merchant-open gate), otherwise the vendor row is grabbed as cursor mode 5, which is invisible to `CursorHasItem` (modes 1 and 9 only) so all thirteen stock gates stay closed while it is held; the drop is the buy, `CMSG_BUY_ITEM_IN_SLOT`, count 1, into a bag or an equipment slot, and every refusal is silent and clears the cursor; the four `Model_*` rotation handlers land in UIParent where the reference keeps them - the gap report reads `:Method(` sites now — it found `SetMerchantCompareItem`, which would have raised on the first vendor-row hover with every check green, and `LootButton:SetSlot`, and 28 "free" windows became 25; the shared coin kit moved out of the merchant window into `MoneyFrame.xml` so the eight windows that draw coins through it can reach it without loading a vendor Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -126,6 +126,10 @@ pub(crate) fn place_action(model: &mut Model, id: u32) -> bool {
|
||||
// Mode 10 (decision 1677) — a stabled pet has no `CMSG_SET_ACTION_BUTTON` encoding either,
|
||||
// so the action bar refuses it and it goes back on the cursor.
|
||||
CursorPayload::StablePet(_) => None,
|
||||
// Mode 5 — a vendor row is not a bar action. `PlaceAction`'s payload table takes modes
|
||||
// 1, 2 and 8 only, and the merchant grab is none of them, so it goes back on the cursor
|
||||
// where the vendor window can still take it.
|
||||
CursorPayload::Merchant(_) => None,
|
||||
};
|
||||
let Some((kind, action, texture)) = placeable else {
|
||||
model.cursor = Some(held);
|
||||
|
||||
@@ -105,6 +105,27 @@ pub(super) fn pickup_inventory_item(model: &mut Model, id: u32) -> bool {
|
||||
queue_lock_changed(model, held.bag, held.slot);
|
||||
true
|
||||
}
|
||||
// Mode 5 — the buy, aimed at an equipment slot. `0x4c78fd` tests `[0xb4d900] == 5` inside
|
||||
// the paper-doll click and sends the same `CMSG_BUY_ITEM_IN_SLOT 0x1a3` the bag drop does;
|
||||
// the server equips it or refuses. Reported in the ONE bag space ([`EQUIPMENT_BAG`] + the
|
||||
// 1-based inventory slot), the seam this file already uses for every other doll intent.
|
||||
//
|
||||
// Of the reference's three drop consumers this is the one that handles a stale vendor row
|
||||
// correctly — the other two dereference it (`0x4f9f35`, `0x4c7ea5`) — so its refusal is
|
||||
// what we reproduce in all three.
|
||||
Some(CursorPayload::Merchant(held)) => {
|
||||
let entry = model
|
||||
.merchant
|
||||
.as_ref()
|
||||
.and_then(|m| m.items.get(held.row as usize))
|
||||
.filter(|it| it.item_id == held.item_id)
|
||||
.map(|it| it.item_id);
|
||||
if let Some(entry) = entry {
|
||||
model.merchant_slot_buys.push((EQUIPMENT_BAG, id, entry));
|
||||
}
|
||||
queue_cursor_update(model);
|
||||
true
|
||||
}
|
||||
Some(
|
||||
other @ (CursorPayload::Spell(_)
|
||||
| CursorPayload::Action(_)
|
||||
|
||||
Reference in New Issue
Block a user