fix(D.5.2): always run effect recolor (effects==0 -> black) to match retail
Visual verification caught it: a no-mana scroll's icon edges are BLACK in retail but rendered WHITE in acdream. Cause = the effects!=0 gate (registered AP-44) that skipped retail's effects==0 recolor. Retail's effect tile is non-null even for effects==0 (the 0x21 SOLID-BLACK fallback 0x060011C5), so RenderIcons recolors pure-white pixels to black on mundane items and to the effect hue on magical ones. Remove the gate (always recolor); retire AP-44 (now faithful). TryGetEffectColor made internal + a golden test pins effects==0 -> ~black. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
702d6e1e90
commit
40c97a53ac
3 changed files with 30 additions and 10 deletions
|
|
@ -150,7 +150,7 @@ public sealed class IconComposer
|
|||
/// decompiler-ambiguous SurfaceWindow-header read; the tile IS the per-effect color, so
|
||||
/// its representative color is the faithful equivalent (divergence DR-2). Cached per DID.
|
||||
/// </summary>
|
||||
private bool TryGetEffectColor(uint effects, out (byte r, byte g, byte b, byte a) color)
|
||||
internal bool TryGetEffectColor(uint effects, out (byte r, byte g, byte b, byte a) color)
|
||||
{
|
||||
color = default;
|
||||
uint did = ResolveEffectDid(effects);
|
||||
|
|
@ -214,9 +214,9 @@ public sealed class IconComposer
|
|||
/// Returns 0 if no base icon. Mirrors retail IconData::RenderIcons (0x0058d180):
|
||||
/// a DRAG composite (base + custom overlay + effect recolor) blitted over the
|
||||
/// type-default underlay + custom underlay. The effect tile (enum 0x10000005) is a
|
||||
/// ReplaceColor tint SOURCE, not a blit layer (DR-1). The 2-stage form is
|
||||
/// associative-equivalent to a single Compose when effects==0, so D.5.1 visuals are
|
||||
/// unchanged for non-effect items.
|
||||
/// ReplaceColor tint SOURCE, not a blit layer (DR-1). The recolor runs for ALL items:
|
||||
/// effects==0 resolves to the 0x21 solid-black fallback tile, so pure-white pixels become
|
||||
/// black (matching retail); magical items take the per-effect hue instead.
|
||||
/// </summary>
|
||||
public uint GetIcon(ItemType itemType, uint iconId, uint underlayId, uint overlayId, uint effects)
|
||||
{
|
||||
|
|
@ -233,10 +233,13 @@ public sealed class IconComposer
|
|||
if (dragLayers.Count > 0)
|
||||
{
|
||||
var composed = Compose(dragLayers);
|
||||
// Effect recolor only when an effect bit is set. Retail nominally also runs the
|
||||
// effects==0 black-fallback recolor; we skip it (DR-3: white→black on every item
|
||||
// is a likely no-op but a regression risk, pending visual/cdb confirmation).
|
||||
if (effects != 0 && TryGetEffectColor(effects, out var ec))
|
||||
// Effect recolor — ALWAYS, matching retail IconData::RenderIcons (0x0058d180):
|
||||
// the effect tile (enum 0x10000005, lsb(effects)+1, fallback 0x21) is non-null
|
||||
// even for effects==0 (the 0x21 SOLID-BLACK tile 0x060011C5), so retail recolors
|
||||
// pure-white pixels to BLACK on mundane items and to the effect hue on magical
|
||||
// ones. Visually confirmed against retail 2026-06-17: the no-mana scroll's edges
|
||||
// are BLACK, not white — the earlier `effects != 0` gate (AP-44) was wrong.
|
||||
if (TryGetEffectColor(effects, out var ec))
|
||||
ReplaceColorWhite(composed.rgba, composed.w, composed.h, ec);
|
||||
drag = composed;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue