unitscan's horn cut whatever SoftSpoken was reading, because the only stop 1.12 has stops everything
`SetCVar("MasterSoundEffects", 0)` then `..., 1)` is the only way a 1.12 addon
can stop a sound that is already playing, and the reference's stop is
indiscriminate: `0x7a67a0` walks the live instance list and stops every node in
it, whoever started them. That is fine while one addon at a time uses the toggle,
and this install has two that use it for opposite ends — SoftSpoken to stop its
own clip before replaying it and to duck the game's NPC bark, unitscan to make
sure of a channel for its alert (`unitscan.lua:55-59` is the pair, then
`PlaySoundFile`). It is not aimed at anybody.
grom: "unitscan sound will interupt softspoken reading something, this is really
annoying, I still want the unitscan sound but for softspoken to not be silenced."
Nothing in the toggle separates the two uses, so the caller does.
`PlaySoundFile` and the toggle each now carry the addon whose file made the call
— attribution by chunk name, since an addon's files load as
`@Interface\AddOns\<Name>\<file>`. A cut still stops every kit-played bark, which
is the game's own audio and what an addon ducking "the sound" means by it; among
`PlaySoundFile` audio it stops only the calling addon's own. Both of SoftSpoken's
uses survive intact: stopping its own clip is cutter == owner, and ducking NPC
dialogue is a kit.
A deviation from the reference, written down in `docs/ADDON_COMPAT.md` with the
two reports on either side of it, together with the Who-list font colours and the
73%-opaque tooltip art behind the unreadable map tooltip.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
This commit is contained in:
@@ -5133,3 +5133,100 @@ caller is not an addon at all — it is the realm's own FrameXML:
|
||||
`SetHyperlink`, to force each item into the cache. The tooltip is a hidden scanner that is never
|
||||
positioned for anyone to read, so the reference's own fallback to mode 0 / `ANCHOR_LEFT` is all
|
||||
that code ever got from it either. A true report of sloppy realm code, not a gap here.
|
||||
|
||||
## `NORMAL_FONT_COLOR:GetRGB()` — the `/who` list, and a global 1.12 never had
|
||||
|
||||
`ui_script/manifest.rs`'s `install_font_colour_objects`, beside the other load-time repairs.
|
||||
|
||||
1.12 ships its font colours as loose `{ r, g, b }` tables (`Fonts.xml`); every client from Legion
|
||||
on makes them `ColorMixin` objects, and addon code written in that dialect calls methods on them
|
||||
rather than reading the fields. pfUI does, in both directions at once:
|
||||
|
||||
| call | where | what it did here |
|
||||
| --- | --- | --- |
|
||||
| `NORMAL_FONT_COLOR:GetRGB()` | `modules/socialmod.lua:145`, `modules/loot.lua` ×5 | **26 raises in one of grom's sessions**, every one from opening the Who tab. The list drew uncoloured and each row cost a traceback; the master-loot menu has the same five lines waiting for a raid |
|
||||
| `WHITE_FONT_COLOR:GetRGB()` / `:GetRGBA()` | `modules/totems.lua:22-23`, `modules/minimap.lua:198` | indexes a nil: 1.12 has no such global at all |
|
||||
|
||||
The six `*_FONT_COLOR` tables 1.12 declares (`reference/1.12-globals.tsv`) get `ColorMixin` as a
|
||||
**metatable**, not a `Mixin` copy. Upstream copies the methods in as fields, which is right for an
|
||||
object it owns; these tables are FrameXML's, FrameXML reads them, and a 1.12 addon is free to walk
|
||||
one with `pairs`. `__index` leaves `pairs(NORMAL_FONT_COLOR)` answering exactly the keys it answers
|
||||
on the reference while the methods still resolve. `a` is the one field added, because `GetRGBA` has
|
||||
to answer something and modern WoW's own `NORMAL_FONT_COLOR` is opaque. A table that already
|
||||
carries a metatable is left exactly as found. `WHITE_FONT_COLOR` is created only if absent.
|
||||
|
||||
It lives in `manifest.rs` rather than beside `ColorMixin` in `compat/classic_api/color_mixin.rs`
|
||||
for the same mechanical reason as `/focus`: the tables do not exist until `Fonts.xml` has run, and
|
||||
the compat layer installs before FrameXML loads. Named one by one rather than swept out of `_G`,
|
||||
so an addon's own table of the same name never gets a metatable it did not ask for.
|
||||
|
||||
## `MasterSoundEffects`: whose sound a cut may stop
|
||||
|
||||
`script/sound.rs`'s `SoundRequest::CutEffects`, spent by `sound/kit.rs`'s `stopped_by_reenable`.
|
||||
**A deviation, and a deliberate one.**
|
||||
|
||||
`SetCVar("MasterSoundEffects", 0)` then `..., 1)` is the only way a 1.12 addon can stop a sound
|
||||
that is already playing, and the reference's stop is indiscriminate: `0x7a67a0` walks the live
|
||||
instance list and stops every node in it, whoever started them. That is fine while one addon at a
|
||||
time uses the toggle, and this install has two that use it for opposite ends:
|
||||
|
||||
* **SoftSpoken** spends it to stop *its own* clip before replaying it, and to duck the game's own
|
||||
NPC bark while it reads.
|
||||
* **unitscan** spends it to make sure of a channel for its alert — `unitscan.lua:55-59` is the
|
||||
pair, then `PlaySoundFile`. It is not aimed at anybody.
|
||||
|
||||
With the reference's rule, unitscan's horn cuts whatever SoftSpoken is in the middle of reading.
|
||||
grom, 2026-11-08: *"unitscan sound will interupt softspoken reading something, this is really
|
||||
annoying, I still want the unitscan sound but for softspoken to not be silenced."*
|
||||
|
||||
Nothing in the toggle separates the two uses, so the **caller** does. `PlaySoundFile` and the
|
||||
toggle each carry the addon whose file made the call (`script/mod.rs`'s `calling_addon`, attribution
|
||||
by chunk name: an addon's files load as `@Interface\AddOns\<Name>\<file>`). A cut still stops every
|
||||
kit-played bark — that is the game's own audio, which is what an addon ducking "the sound" means by
|
||||
it — and among `PlaySoundFile` audio it stops only the calling addon's own. Both of SoftSpoken's
|
||||
uses survive intact: stopping its own clip is cutter == owner, and ducking NPC dialogue is a kit.
|
||||
|
||||
## An item template nobody answered
|
||||
|
||||
`items.rs`'s `retry_unanswered_templates`, over `query_cache.rs`'s `sweep_pending`.
|
||||
|
||||
The ask-once rule is the reference's `DBCache` and it is right for everything it covers: one query
|
||||
per entry per connection, a negative cached as a negative. What it has no arm for is a query that
|
||||
goes out and is **never answered**, and the whole cost of that falls on the player —
|
||||
`GetItemInfo` keeps returning nil, so the item draws with no name, no icon and no tooltip, in the
|
||||
bag, in the quest frame's required-items box and in every addon that reads it, for the rest of the
|
||||
session, and nothing ever asks again.
|
||||
|
||||
grom, 2026-11-08: *"on the quest Deeprun Rat Roundup, I'm not recieving the flute item needed for
|
||||
the quest"*. He had it the whole time. Entry **17117**, Rat Catcher's Flute, bag 0 slot 2 — the
|
||||
only trace of it in a three-hour log is `GetNumJunkItems` reporting one carried slot *"with no
|
||||
item template yet"*, twice.
|
||||
|
||||
An unanswered ask is now re-sent after 5 s, three sends in all, and then reported once. Bounded on
|
||||
purpose: an entry the server genuinely does not know is answered with the high-bit miss and never
|
||||
reaches the sweep, so a key that survives three sends is one nothing is going to answer. The same
|
||||
gap exists for creature names and gameobject templates and is left alone until one of them is seen
|
||||
to drop an answer, since a nameless mob is at least self-correcting on the next
|
||||
`SMSG_UPDATE_OBJECT`.
|
||||
|
||||
## The map tooltip that read as invisible — 73% opaque art, not a draw order
|
||||
|
||||
Not a client change: `OpenMapClassic/Map/Extras.lua` (the port), `BackTooltip`.
|
||||
|
||||
grom sent two screenshots of a pfQuest quest-node tooltip he could not read on the world map, and
|
||||
it looks exactly like a strata fault — so that is what was measured first, and it is not one.
|
||||
`WorldMapTooltip` reports `strata=TOOLTIP lvl=1`, the stitched art is `FULLSCREEN` at levels 3..190,
|
||||
`ZKey` puts the stratum in its top four bits, alphas are 1.0 on both sides, and the frame trees of
|
||||
`WorldMapTooltip` and `ItemRefTooltip` are identical down to pfUI's backdrop child.
|
||||
|
||||
Four panels over the same stitched map settled it: `WorldMapTooltip` and a **fresh frame with a
|
||||
stock backdrop** both read through; the same frame with a flat `ARTWORK` texture instead of a
|
||||
backdrop is solid, on `WorldMapFrame` and on `UIParent` alike. So it is the backdrop art, and
|
||||
decoding it says so outright — every texel of `Interface\Tooltips\UI-Tooltip-Background.blp` is
|
||||
RGBA(142, 140, 142, **187**), 73% opaque.
|
||||
|
||||
Which is faithful. On Blizzard's muted parchment zone map the quarter that comes through is
|
||||
invisible; on OpenMap's bright, busy stitched map it is all you see. `GameTooltip` does not have
|
||||
the problem because pfUI puts a solid panel behind it, and nothing skins `WorldMapTooltip`. The
|
||||
port now does the same: one opaque texture on the tooltip's `BACKGROUND` layer, inset past the
|
||||
border so it still looks like a tooltip, shown only while the stitched map is what is underneath.
|
||||
|
||||
Reference in New Issue
Block a user