superwow: CanLootUnit, GetSpeed and UnitNameplate

Three of the DLL's own manifest, and two of them needed no new feed at
all — which is the point worth recording, because the row that called
this family "todo, blocked: each needs new app-side state" was wrong
about two of the three.

`CanLootUnit` is the loot sparkle's test read through the token map:
`UnitState` already carries `dead` and raw `dynamic_flags`, so a corpse
that sparkles answers 1 and there is one source of truth for "has loot
for me". The bit is per-viewer on the server, so "can" means can.

`UnitNameplate` goes through the SAME `plate_frame` wrapper as
ClassicAPI's `C_NamePlate.GetNamePlateForUnit`, welded by a test that
asserts both names hand back one object — an addon may feature-detect
either, and two different frames for one plate is the kind of bug that
only shows up as an anchor in the wrong place.

`GetSpeed` is the one that needed a field: the posture snapshot gained
`speed`, filled from `net::current_speed`, the reference's own
`CMovement::GetCurrentSpeed 0x7c4c90`. What could not be settled is
written down rather than guessed over — upstream publishes no prose and
nothing in the corpus calls it, so "current" is a reading, taken because
it is the more informative of the two and because it is the only function
in the client named after speed that a hook would return. Standing still
it is 0, as that getter is.

`SelfMovement` loses its `Eq` (an f32 field); nothing compared two
snapshots — the feed assigns a fresh one each tick.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
This commit is contained in:
2026-10-25 12:43:08 -06:00
co-authored by Claude Opus 5
parent 3b6e91be35
commit ac857ada36
8 changed files with 189 additions and 8 deletions
+3 -2
View File
@@ -80,10 +80,11 @@ The usage strings, verbatim, for what is left:
| `TrackUnit("unit")` / `UntrackUnit("unit")` | todo — pfUI calls `TrackUnit` for every party and raid member under `C.unitframes.track_group` (`modules/superwow.lua:96-127`, inside `pcall`), to put the group on the minimap |
| `UnitPosition("unit")` | done |
| `GetPlayerBuffID(buffIndex)` | done |
| `UnitNameplate("unit")` | todo — the plate frame for a unit; `NamePlates::guid_for_frame` already keys the other direction |
| `CanlootUnit("unit")` | todo. **Note the lowercase `l`**: the *usage* string says `CanlootUnit` where the registered name is `CanLootUnit`. The registered name is what an addon calls; the typo is in the error message only |
| `UnitNameplate("unit")` | **done** — `compat/superwow.rs`, over `NamePlates::frame_for_guid`, through the **same** `plate_frame` wrapper ClassicAPI's `C_NamePlate.GetNamePlateForUnit` uses, so the two names cannot hand back different objects for one plate. Welded by a test that asserts exactly that, because an addon may feature-detect either |
| `CanlootUnit("unit")` | **done** — needed no new feed: `UnitState` already carries `dead` and raw `dynamic_flags`, so it is the loot sparkle's own two-part test (`shows_loot_sparkle`: `unit_is_dead() && unit_lootable()`) read through the token map instead of the ECS, and a corpse that sparkles answers 1. Bit `0x1` is **per viewer** on the server — vmangos raises it only for players who may loot — so "can" really means can. **Note the lowercase `l`**: the *usage* string says `CanlootUnit` where the registered name is `CanLootUnit`; the registered name is what an addon calls, and the typo is in the error message only |
| `GetMapPositionWorldLoc(continentIndex, zoneIndex, mapX, mapY)` | todo — map fraction to world XY, which `benilla-world`'s own map maths already does for the world map |
| `GetMapBoundaries(continentIndex, zoneIndex)` | todo — the zone's world extent, the same table that conversion reads |
| `GetSpeed()` (no usage string: it takes no argument) | **done** — one new field on the posture snapshot, filled by `ui_unit.rs`'s `feed_self_movement` from `net.rs`'s `current_speed`, the reference's own `CMovement::GetCurrentSpeed 0x7c4c90` walk over our speed block and the same move flags every other field of that snapshot reads. **What could not be settled**: upstream publishes no prose and no addon in the corpus calls it, so whether its number is the *current* speed or the unit's *run* speed is unknowable from here. Current is the reading taken — it is the one client function named after speed that a hook would return, and the strictly more informative of the two (a snare or a mount shows in it). The consequence to know: standing still it is 0, exactly as that getter is |
| `GetInboxItemLink(messageIndex)` | done (built for ClassicAPI's `Mail`) |
| `GetSoundDriverName(driverIndex)` | todo — with `GetSoundDevices`, `GetNumSoundDrivers`, `GetLoadedSoundDriver`: four getters over the audio backend. benilla has one backend and no enumeration, so these answer a one-row list honestly or not at all; no addon in the corpus calls any of them |
| `GetQuestIDForLogIndex(questIndex)` / `GetQuestLinkForLogIndex(questIndex)` | done |