`UpdateWorldMapArrowFrames` (`0x4a8d10`, `0x4a7c20`) copies the camera-tracked object's
facing to both arrows and leaves them alone when there is no such object. Ours tested "is
there a player" with `WorldMapState::player_uv.is_some()` — a different question, because
that field is `GetPlayerMapPosition` on the **displayed** map. A view sitting on a
continent, on another zone, or on an addon's stitched world answers `None` on every frame,
so the arrow kept the heading it had when the window last sat on the player's own zone: the
right place, pointing the wrong way.
`player_facing_seen` is the real test, set the first time the feed pushes a facing — the
feed runs only where there is a player, and the facing it pushes is unconditional. The
existing test asserted the old behaviour on its second leg; that leg now asserts the
heading following off the displayed map, and a new test holds the other half (before any
feed, the login and loading screens, the arrow is left alone).
`scripts/soften-zone-masks.py` is for the OpenMapClassic port rather than the client: its
per-zone land masks are binary, so every map sheet ends on a crisp line against a
differently-lit neighbour. It writes a softened copy — dilate, blur, times a rect ramp that
reaches zero inside the sheet's own torn parchment border, which is the half that is not
obvious.
`docs/ADDON_COMPAT.md` writes up this round's five: the flashing arrow (two writers on one
frame, measured `h h S h h S`), why correcting after 1.12 rather than suppressing it cost a
full UI conversion every frame, pfQuest's pins being both behind the map and only ever for
one zone, the softened masks, and the cities.
Gates: fmt 0, clippy 0, benilla-ui 2121 pass / 0 fail, benilla-app 4233 pass / 12 fail (the
recorded data-golden baseline). Corpus 86/87 load clean, 86/87 survive a session start and
a UI probe, 0 raised on hover, click or drag — unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn