the auction house opens, the Honor tab lands, and a day of fixes
- the auction house end to end: right-clicking an auctioneer opens Browse/Bids/Auctions on the server's reply — search, the category tree from your own DBCs, the reference's 50-a-page pager, multi-key sorting (directions corrected at the bytes), bid/buyout, the sell slot with deposit and duration, cancel with its fee popup; prices sit on the reference's own money-frame kit in lined-up columns, the twenty auction messages split refusals-red / outcomes-to-chat, and a won or sold auction reads as a proper mail receipt — the window's Lua re-worded in our own terms after the overlap ratchet caught the first cut leaning on the reference's text - the PvP honor system whole: the Honor tab and the inspect page over a real wire model, with current rank and highest-ever rank correctly two different fields - a day of reported fixes: WASD survives a /logout re-entry, addon settings save on a window close and Cmd+Q (exactly once — a mac close could fire the tail twice), clams open again, random-enchant items name themselves on every surface, the loot window's rows hold their seats with legible counts, idle players stop sinking through building floors, the shooter re-pulls between Auto Shots, portraits loosen ~19% to the client's own aspect-1.0 matrix, and big creatures thump the camera off the CameraShakes table - character select clicks like 1.12 — captions whiten on hover, buttons fire on release, Humans face straight ahead off the stage bone's real yaw, the facing is per-character, and hunter/warlock pets stand beside you at their family-ramp size with their own emitters (the imp's flames), the Voidwalker's sequence-hidden shackles culled - the smaller player-facing set: nameplate on/off rows in Options with the CanAttack category gate (emissaries stop plating), the bonus bar slides up with igBonusBarOpen, the camera's framing height glides on a shapeshift, the open letter evicts the centre seat, the far-band fog hull stops printing a pale horizon stripe at low view distance, the guide arrow is gold with per-source rim art, error text fades through its shadow too, and /convertraid converts the party - README: the auction house and PvP honor move out of "not built yet" Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -615,6 +615,204 @@ fn temporary_enchant_line_carries_its_countdown_and_charges() {
|
||||
);
|
||||
}
|
||||
|
||||
/// **The loot hover shows the ROLL, never the placeholder** (decision 1547; wow-re §E6-LOOT).
|
||||
/// `SetLootItem 0x533470` writes an instance block (p6=1) whose `+0x424` is the wire's
|
||||
/// randomPropertyId and whose seven enchant slots are zeroed, and passes an all-zero item GUID —
|
||||
/// so there is never an object, the builder takes §E5's suffix-row copy into slots 2..6, and the
|
||||
/// `ITEM_RANDOM_ENCHANT` arm is unreachable (§E1's fork). The row's name is the suffix-joined one
|
||||
/// (`0x5d8b00`, the same string `GetLootSlotInfo` returns), so the plate reads "… of the Monkey".
|
||||
///
|
||||
/// This is the reported bug's exact shape: through the template path (`SetItemById`) the same
|
||||
/// hover printed `<Random enchantment>` until the item reached a bag.
|
||||
#[test]
|
||||
fn a_looted_roll_shows_its_lines_and_never_the_placeholder() {
|
||||
let mut s = script();
|
||||
s.set_item_template(
|
||||
8888,
|
||||
ItemTemplateView {
|
||||
name: "Bloodrazor".into(),
|
||||
quality: 2,
|
||||
class: 2,
|
||||
// The template CAN roll — the placeholder's own gate, so its absence below is the law
|
||||
// and not an accident of the fixture.
|
||||
random_property: 42,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
s.set_loot(Some(LootState {
|
||||
rows: vec![Some(LootRow {
|
||||
name: Some("Bloodrazor of the Monkey".into()),
|
||||
texture: None,
|
||||
quantity: 1,
|
||||
quality: Some(2),
|
||||
is_coin: false,
|
||||
item_id: 8888,
|
||||
link: Some("|cff1eff00|Hitem:8888:0:584:0|h[Bloodrazor of the Monkey]|h|r".into()),
|
||||
// The row carries the ROLL, not resolved lines — the engine resolves it, like the
|
||||
// reference reading its own DBC store off the block's `+0x424`.
|
||||
random_property_id: 584,
|
||||
})],
|
||||
fishing: false,
|
||||
}));
|
||||
s.set_random_properties(
|
||||
[(
|
||||
584,
|
||||
RandomPropertyView {
|
||||
suffix: "of the Monkey".into(),
|
||||
enchants: vec![
|
||||
EnchantView {
|
||||
slot: 2,
|
||||
name: "Agility +7".into(),
|
||||
..Default::default()
|
||||
},
|
||||
EnchantView {
|
||||
slot: 3,
|
||||
name: "Stamina +7".into(),
|
||||
..Default::default()
|
||||
},
|
||||
],
|
||||
},
|
||||
)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
);
|
||||
s.run(
|
||||
r#"
|
||||
local a = CreateFrame("Button", "Slot"); a:SetPoint("CENTER", 0, 0); a:SetSize(10, 10)
|
||||
local tt = CreateFrame("GameTooltip", "TT")
|
||||
tt:SetOwner(Slot, "ANCHOR_RIGHT")
|
||||
tt:SetLootItem(1)
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
let lines = super::lines_of(&mut s);
|
||||
let texts: Vec<&str> = lines.iter().map(|(t, _)| t.as_str()).collect();
|
||||
assert!(
|
||||
!texts.contains(&"<Random enchantment>"),
|
||||
"a block source never reaches the placeholder arm — got {texts:?}"
|
||||
);
|
||||
assert_eq!(
|
||||
texts.first(),
|
||||
Some(&"Bloodrazor of the Monkey"),
|
||||
"the plate takes the roll's suffixed name — got {texts:?}"
|
||||
);
|
||||
for line in ["Agility +7", "Stamina +7"] {
|
||||
let l = lines
|
||||
.iter()
|
||||
.find(|(t, _)| t == line)
|
||||
.unwrap_or_else(|| panic!("the roll's slot line {line} — got {texts:?}"));
|
||||
// Slots 2..6 are always WHITE, whatever the sign (§E3).
|
||||
assert_eq!(l.1, [1.0, 1.0, 1.0, 1.0], "{line} is white");
|
||||
}
|
||||
}
|
||||
|
||||
/// The other half of the same law: a loot row with **no** roll shows no enchant line AND no
|
||||
/// placeholder, even though the template can roll. The fork tests the block's presence, not its
|
||||
/// contents (§E1) — which is why this cannot be expressed as "print the placeholder when the
|
||||
/// slots are empty".
|
||||
#[test]
|
||||
fn a_looted_item_with_no_roll_shows_neither_line_nor_placeholder() {
|
||||
let mut s = script();
|
||||
s.set_item_template(
|
||||
8888,
|
||||
ItemTemplateView {
|
||||
name: "Bloodrazor".into(),
|
||||
quality: 2,
|
||||
class: 2,
|
||||
random_property: 42,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
s.set_loot(Some(LootState {
|
||||
rows: vec![Some(LootRow {
|
||||
name: Some("Bloodrazor".into()),
|
||||
quantity: 1,
|
||||
quality: Some(2),
|
||||
item_id: 8888,
|
||||
..Default::default()
|
||||
})],
|
||||
fishing: false,
|
||||
}));
|
||||
s.run(
|
||||
r#"
|
||||
local a = CreateFrame("Button", "Slot"); a:SetPoint("CENTER", 0, 0); a:SetSize(10, 10)
|
||||
local tt = CreateFrame("GameTooltip", "TT")
|
||||
tt:SetOwner(Slot, "ANCHOR_RIGHT")
|
||||
tt:SetLootItem(1)
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
let texts: Vec<String> = super::lines_of(&mut s)
|
||||
.into_iter()
|
||||
.map(|(t, _)| t)
|
||||
.collect();
|
||||
assert!(
|
||||
!texts.iter().any(|t| t == "<Random enchantment>"),
|
||||
"no placeholder on a block source — got {texts:?}"
|
||||
);
|
||||
}
|
||||
|
||||
/// A **chat link** is a block source too (`SetHyperlink 0x532181`, p6=1): its `|Hitem:` token 2 is
|
||||
/// the roll, which §E5 expands into slots 2..6, and the placeholder arm is unreachable. Decision
|
||||
/// 0920's prose said a hyperlink hover shows the placeholder; §E1's fork says otherwise, and this
|
||||
/// is the case that proves it — the same drop, linked in chat instead of hovered in the loot
|
||||
/// window, must read identically.
|
||||
#[test]
|
||||
fn a_linked_roll_shows_its_lines_and_never_the_placeholder() {
|
||||
let mut s = script();
|
||||
s.set_item_template(
|
||||
8888,
|
||||
ItemTemplateView {
|
||||
name: "Bloodrazor".into(),
|
||||
quality: 2,
|
||||
class: 2,
|
||||
random_property: 42,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
s.set_random_properties(
|
||||
[(
|
||||
584,
|
||||
RandomPropertyView {
|
||||
suffix: "of the Monkey".into(),
|
||||
enchants: vec![EnchantView {
|
||||
slot: 2,
|
||||
name: "Agility +7".into(),
|
||||
..Default::default()
|
||||
}],
|
||||
},
|
||||
)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
);
|
||||
s.run(
|
||||
r#"
|
||||
local a = CreateFrame("Button", "Slot"); a:SetPoint("CENTER", 0, 0); a:SetSize(10, 10)
|
||||
local tt = CreateFrame("GameTooltip", "TT")
|
||||
tt:SetOwner(Slot, "ANCHOR_RIGHT")
|
||||
tt:SetHyperlink("|cff1eff00|Hitem:8888:0:584:0|h[Bloodrazor of the Monkey]|h|r")
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
let texts: Vec<String> = super::lines_of(&mut s)
|
||||
.into_iter()
|
||||
.map(|(t, _)| t)
|
||||
.collect();
|
||||
assert!(
|
||||
!texts.iter().any(|t| t == "<Random enchantment>"),
|
||||
"a link never reaches the placeholder arm — got {texts:?}"
|
||||
);
|
||||
assert_eq!(
|
||||
texts.first().map(String::as_str),
|
||||
Some("Bloodrazor of the Monkey"),
|
||||
"the plate takes the link's own suffixed name — got {texts:?}"
|
||||
);
|
||||
assert!(
|
||||
texts.iter().any(|t| t == "Agility +7"),
|
||||
"the roll's slot line — got {texts:?}"
|
||||
);
|
||||
}
|
||||
|
||||
/// `<Random enchantment>` (§E5) — the template-only placeholder: a random-property item with NO
|
||||
/// instance to read a roll from prints it, green, and the per-slot lines and this one are mutually
|
||||
/// exclusive by construction. The control is the same template hovered as a real enchanted
|
||||
|
||||
Reference in New Issue
Block a user