diff --git a/docs/ADDON_COMPAT.md b/docs/ADDON_COMPAT.md index 1b5c37d8..45d1ac15 100644 --- a/docs/ADDON_COMPAT.md +++ b/docs/ADDON_COMPAT.md @@ -1761,3 +1761,78 @@ already had this case for EllesmereUI's drawer; pfUI's is the same shape, so the there a drawer" rather than "is it EllesmereUI", and `ns.UpdateMinimapButton` hands the button over on Core's scan if a drawer appeared after it was built (pfUI builds its panel a frame after login). Measured offline: `CinematicMinimapButton`'s parent is now `pfMinimapButtons`. + +## `namePlateUnitToken`, and the nameplate an addon can see but cannot identify + +Second round of grom's 2026-11-02 session: **friendly nameplates switched themselves on whenever +CineMode started**, on a profile whose every friendly-plate box is unticked. Measured in the +harness, straight off his saved variables: + +``` +before Cinematic_Toggle(): nameplateShowFriends = 0 +after: nameplateShowFriends = 1 +``` + +That write is Cinematic's and it is deliberate (`Effects.lua`'s `FORCED_PLATE_CVARS`): outside +instances it switches **every** plate kind on so that visibility is decided by *fading* instead — +"fades can change in fights, plate settings can't". The design only works if the addon can then +look at a plate and say which kind it is, and that is where this client failed it. + +**`plate.namePlateUnitToken` was not set on anything.** It is how every later-era plate addon gets +from a frame back to its unit — `plate.namePlateUnitToken or (plate.UnitFrame and +plate.UnitFrame.unit)` is the idiom, at six sites in `Cinematic/Effects.lua` and `PlateParts.lua` +alone. Without it an addon walking `C_NamePlate.GetNamePlates()` has a frame's rect and nothing +about its unit, so it cannot tell a friendly plate from a hostile one — and Cinematic, having just +switched them all on, faded none of them. + +The token itself already existed: `script/nameplate.rs` has had the slot-bound `nameplate` unit +tokens and the three plate events since the plate pool was built. The only missing piece was +publishing the slot's token **on the frame**, which `set_plate_unit_token` now does — set before +`NAME_PLATE_UNIT_ADDED` and cleared after `NAME_PLATE_UNIT_REMOVED`, so a handler for either event +reads the field the event is about, and a pooled frame reused for the next unit cannot answer the +departed one's token. Measured: a walked plate answers `nameplate1`, and `UnitName` of it answers +the unit. + +The eight verbs the classification then uses — `UnitIsFriend`, `UnitIsEnemy`, `UnitReaction`, +`UnitIsPlayer`, `UnitCanAttack`, `UnitPlayerControlled`, `UnitIsUnit`, `UnitClassification` — are +all present, so the chain is whole. (The probe harness's synthetic plate units carry no reaction, +so the fade itself is not something the offline run can show; what it can show, and does, is that +the token is there and resolves.) + +## Cinematic's own settings window: when nothing will host an addon's pages + +1.12 has no Interface Options panel, so Cinematic's registration (`Options.lua:1012`) finds neither +`Settings.RegisterCanvasLayoutCategory` nor `InterfaceOptions_AddCategory` and registers **nothing** +— at 8.206 s, before any addon has loaded. A second later, two addons' bundled AceConfigDialog +copies define both globals with a 1.12 rewrite of their own, whose `InterfaceOptions_AddCategory` +wants an AceGUI widget and whose `InterfaceOptionsFrame_OpenToCategory` wants a path of strings +where the game's wants a frame. So by the time the player clicks, the globals exist, Cinematic's +`elseif` branch takes them, and the call raises on `tconcat` with a frame — with its pages in no +tree anyway. + +Shipping an Interface Options system of our own does not resolve that on this install: the +registration half would work (ours would exist at 8.206 s) but the open half is replaced +afterwards, by load order, and nothing an engine does can stop an addon reassigning a global. + +So the port grew the thing a 1.12 addon needs when no host exists: **a window of Cinematic's own**, +holding the same canvases the Settings panel would be handed, with their names down the left. The +switch is not "does the global exist" — by click time it does — but **"did a registration actually +happen"**, a `hosted` flag set in whichever branch ran at build time. With it false, `ns.OpenOptions` +opens Cinematic's window instead, in combat too (nothing here is a protected panel). Measured: +`/cine config` opens it with the ten top-level pages listed and the main page shown, 0 errors. + +The general lesson for this client, which is not specific to Cinematic: **an addon that registers +options with a host and has no fallback is one stomped global away from having no settings UI at +all.** Shipping `InterfaceOptions_*` is still worth doing for the addons that have no window of +their own — it is on the list — but it cannot be the whole answer while any addon may redefine it. + +## Two more addons' frames CineMode was leaving up + +- **pfUI LocationPlus** (`Support/pfUI-locplus.lua`): the zone/coordinate panel by the minimap and + the two data panels beside it. Everything hangs off `CentralZoneFrame` + (`pfUI-locplus.lua:59`). Its own Advanced Frames row rather than a line in the pfUI file — it is + a separate addon, and its panel is the kind of thing a player may want kept up. +- **pfQuest** (`Support/pfQuest.lua`): `pfQuestMapTracker` and `pfDatabaseQuestItemTracker`, on the + Quest tracker row, exactly as the Questie file does it. No `own`/`hook`: pfQuest fades the + *regions* inside its tracker (`tracker.lua:178`, `:373`) and never the tracker frame, so there is + no second owner of the thing Cinematic writes.