fix(vendor): re-gate residuals — MaxStackSize is the stack operand, wire-authored use radius, purse summaries
Some checks are pending
Headless portability / portable-headless (ubuntu-latest) (push) Waiting to run
Headless portability / portable-headless (windows-latest) (push) Waiting to run
Headless portability / linux-graphical (push) Waiting to run
Headless portability / linux-vulkan (push) Waiting to run
Some checks are pending
Headless portability / portable-headless (ubuntu-latest) (push) Waiting to run
Headless portability / portable-headless (windows-latest) (push) Waiting to run
Headless portability / linux-graphical (push) Waiting to run
Headless portability / linux-vulkan (push) Waiting to run
R1 the split bar's operand is the item's authored MaxStackSize —
three retail sites read pwd._maxStackSize directly (InqListSlotCount
pc:200052, buy-button cases pc:203996/204086) where ACE never fills
the desc stack and standard stock is unlimited. Threaded StackSizeMax
end to end with one shared resolver; the two literal _maxStackSize
sites are now byte-exact; AP-165 retired, AP-169 corrected.
R2 walk-to-vendor never opened because GetUseRadius used an UNCITED
3m Creature heuristic as the local stop distance while ACE's poll
demands the authored radius (default 0.6 m) — the walk stopped and
the Use fired far outside acceptance. Now reads the wire-authored
spawn UseRadius with ACE's exact fallback; heuristic constants
deleted. A first sabotage attempt was non-discriminating
(coincidental 0.6) and was corrected — the discriminating version is
what landed.
R3 the Buying/Selling purse summaries ("Buying %d %s worth %hsp" /
"You have %hsp") recovered from the binary data segment where BN
mis-attributes the Buy-side literal; wired to staging and money
changes on the four authored text elements; AP-166 narrowed to the
pending-sell highlight.
Clean-room complete solution: 11,528 passed / 4 skipped / 0 failed.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
68568a3a59
commit
d003449bb4
11 changed files with 680 additions and 103 deletions
|
|
@ -226,9 +226,9 @@ public sealed class VendorShopItemMaterializer : IDisposable
|
|||
/// the wire-shaped merge patch <see cref="ClientObjectTable.Ingest"/>
|
||||
/// expects.
|
||||
/// <para>
|
||||
/// G2 gate-finding fix (2026-08-08, register AP-169): retail's own
|
||||
/// client (<c>gmToolbarUI::HandleSelectionChanged</c>, <c>pc:198688</c>/
|
||||
/// <c>198744</c>/<c>198774</c>/<c>198791</c>) reads
|
||||
/// R1 gate-finding fix (2026-08-08, register AP-169 correction): retail's
|
||||
/// own client (<c>gmToolbarUI::HandleSelectionChanged</c>,
|
||||
/// <c>pc:198688</c>/<c>198744</c>/<c>198774</c>/<c>198791</c>) reads
|
||||
/// <c>eax_5->pwd._stackSize</c> — our <see cref="VendorShopItem.DescStackSize"/>
|
||||
/// — uniformly for BOTH owned-inventory and vendor-owned selections to
|
||||
/// decide whether the toolbar split slider shows and what it caps at.
|
||||
|
|
@ -246,18 +246,28 @@ public sealed class VendorShopItemMaterializer : IDisposable
|
|||
/// for every vendor listing. Reading only <c>DescStackSize</c> here
|
||||
/// therefore left <see cref="ClientObject.StackSize"/> at its default
|
||||
/// for every materialized shop item, so the toolbar split slider never
|
||||
/// appeared for ANY vendor stack, matching the live report exactly (it
|
||||
/// DID appear for owned-inventory stacks, which ACE populates normally
|
||||
/// via ordinary pickup/loot <c>SetStackSize</c> calls). This now prefers
|
||||
/// <c>DescStackSize</c> when present (retail-faithful first, and
|
||||
/// forward-compatible with any server that DOES populate it), falling
|
||||
/// back to the packed <c>StackSize</c> supply-count field clamped to a
|
||||
/// sane positive bound — the field that IS reliably populated against
|
||||
/// ACE. The <c>StackSize == -1</c> (unlimited-supply) sentinel has no
|
||||
/// bounded per-row purchase cap in <see cref="VendorShopItem"/>'s wire
|
||||
/// shape today (no <c>_maxStackSize</c> field carried), so it falls
|
||||
/// through to the conservative "1" default rather than inventing an
|
||||
/// arbitrary ceiling — see the register.
|
||||
/// appeared for ANY vendor stack.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// <b>The G2 packed-supply-count fallback (retired 2026-08-08).</b> An
|
||||
/// earlier fix fell back to <see cref="VendorShopItem.StackSize"/> (the
|
||||
/// packed ItemProfile "how many for sale" dword) when
|
||||
/// <c>DescStackSize</c> was absent. That did not survive live testing —
|
||||
/// a standard vendor listing (e.g. a Prismatic Taper) has UNLIMITED
|
||||
/// stock (<c>StackSize == -1</c>), so the fallback produced nothing
|
||||
/// usable and the bar stayed hidden, matching the live report exactly
|
||||
/// (bare "Prismatic Taper", no bar, no count). The live retail
|
||||
/// screenshot showed "1000 Prismatic Tapers" with the bar visible and a
|
||||
/// ceiling of 1000 — 1000 being the taper's authored MAX STACK SIZE, not
|
||||
/// any bounded supply count. This now prefers <c>DescStackSize</c> when
|
||||
/// present (retail-faithful first, forward-compatible with any server
|
||||
/// that DOES populate it), falling back to
|
||||
/// <see cref="VendorShopItem.MaxStackSize"/> — the item TYPE's authored
|
||||
/// stack ceiling, which ACE DOES populate (an ordinary weenie property)
|
||||
/// and which a real retail server evidently uses AS <c>_stackSize</c>
|
||||
/// for an unlimited-supply "one full stack" browse listing. See
|
||||
/// <see cref="VendorSplitPolicy.ResolveAuthoredStackSize"/> and the
|
||||
/// register, AP-169.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Every other field <see cref="VendorShopItem"/> doesn't carry
|
||||
|
|
@ -276,8 +286,8 @@ public sealed class VendorShopItemMaterializer : IDisposable
|
|||
IconUnderlayId: item.IconUnderlayId,
|
||||
Effects: item.Effects,
|
||||
Value: item.Value,
|
||||
StackSize: ResolveDisplayStackSize(item),
|
||||
StackSizeMax: null,
|
||||
StackSize: VendorSplitPolicy.ResolveAuthoredStackSize(item.DescStackSize, item.MaxStackSize),
|
||||
StackSizeMax: item.MaxStackSize,
|
||||
Burden: null,
|
||||
ContainerId: vendorId,
|
||||
WielderId: 0u,
|
||||
|
|
@ -291,23 +301,6 @@ public sealed class VendorShopItemMaterializer : IDisposable
|
|||
Workmanship: null,
|
||||
PluralName: item.PluralName);
|
||||
|
||||
/// <summary>
|
||||
/// G2 fix: <see cref="VendorShopItem.DescStackSize"/> when the wire
|
||||
/// actually carried it (nonzero — a genuinely retail-faithful server),
|
||||
/// else the packed <see cref="VendorShopItem.StackSize"/> supply count
|
||||
/// (what ACE reliably sends) when it names a real bounded quantity,
|
||||
/// else 1 (non-splittable — the safe default for the unlimited-supply
|
||||
/// sentinel or a genuinely single-unit listing).
|
||||
/// </summary>
|
||||
private static int? ResolveDisplayStackSize(VendorShopItem item)
|
||||
{
|
||||
if (item.DescStackSize is { } desc && desc > 0)
|
||||
return desc;
|
||||
if (item.StackSize > 0)
|
||||
return item.StackSize;
|
||||
return 1;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue