fff48cd75caba0c40ef78225a55bd013bd7e61ba
1685
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
6a8df87219 |
edit boxes take focus the way 1.12 does, and the stable shows its pets
- the caret was a wedge in the line: it sat in flow, four units wide, so focusing a login box shoved its text right by one caret and a caret parked mid-word opened a gap; it is a zero-width seam now with the bar drawn as an overlay (a 0×26 seam and a 5×26 bar at the same x, off a node probe), the way the reference anchors its caret quad over the FontString; a blurred box collapses its selection so only the box holding the keyboard shows one; and a dialog answers only keys pressed while it was already on screen — ENTER on an empty form used to open the error dialog and close it in the same frame - `autoFocus` defaults ON in the reference (the ctor leaves flags = 1, and every one of the ten `autoFocus` attributes in the shipped chain is an opt-out), showing an autoFocus box focuses it after its `OnShow`, and hiding the focused box releases the keyboard — the "never focuses on show" note we had transcribed came from a `call`-only census that missed a tail `jmp`; the loader's flag loop could only ever turn a flag on, so `autoFocus="false"` was a no-op, fixed before the default flipped or it would have grabbed exactly the ten boxes the reference exempts; and the EditBox does fire generic `OnChar` with the spliced string, on every typed or pasted character and never on `SetText` - the stable master's portrait was a black disc (its session was missing from the `"npc"` token chain — the third window to ship that way, so the test is now exhaustive over every `impl NpcSession` and names the one you forgot) and its model pane draws the selected pet: a stabled pet is a database row with no world entity, so a `PortraitStandIn(display_id)` — an entity that exists only to be mirrored — feeds the existing booth code unchanged; plus the registrar's two service rows were hidden by an inherited attribute, a charter's tooltip carries the guild name and master on line 3, and the Help window drops three strings pointing at a company that stopped answering Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
dbf9d8057b |
a full realm is a queue to wait in, and the login dialog is centred
- a full realm answers with `AUTH_WAIT_QUEUE`, and it used to be read as a refusal; the grammar is length-branching exactly as the reference's handler has it, so both mangos body shapes parse; the estimate is the reference's own 8-sample ring — divide before multiply, signed, no timer — whose displayed figure climbs while the queue is silent, pinned by a test so nobody "fixes" it; the dialog is the ordinary status dialog relabelled `CHANGE_REALM` (which cancels back to the login screen: no realm list exists yet), and cancelling actually leaves the queue — the IO thread used to keep its place and walk on into character select on admission - the stable master, corrected against the binary: a stabled-pet drag rides the shared cursor at payload mode 10 (the mode census had that row's label wrong), a plain click always returns 1 and a drop always nil, the summoned pet dropped on an occupied stable slot swaps (STABLE was refused whenever both bought slots were full, silently), an unpurchased slot takes nothing, the stabled→summoned fork reads the live pet guid not the row, the client itself sends `MSG_LIST_STABLED_PETS` on the interact leg, `PET_STABLE_SHOW` fires on every list, the selection is a petNumber and every list clears it, and result codes 2–7 do nothing at all - the login dialog's text is centred (a FontString with no `justifyH` is CENTER, and `GlueDialogText` has none), the fifteen-year-dead "see www.worldofwarcraft.com" clauses are cut at the clause, the Login click sound is unconditional (the reference plays `gsLogin` before it checks the boxes), dialog buttons play `gsTitleOptionOK`, the realmlist button's `gsClick` never existed and is `gsLoginNewAccount`, and focusing a login box selects it — a stated divergence Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
77ca6915bc |
a full realm is a queue to wait in, and the login dialog is centred
- a full realm answers with `AUTH_WAIT_QUEUE`, and it used to be read as a refusal; the grammar is length-branching exactly as the reference's handler has it, so both mangos body shapes parse; the estimate is the reference's own 8-sample ring — divide before multiply, signed, no timer — whose displayed figure climbs while the queue is silent, pinned by a test so nobody "fixes" it; the dialog is the ordinary status dialog relabelled `CHANGE_REALM` (which cancels back to the login screen: no realm list exists yet), and cancelling actually leaves the queue — the IO thread used to keep its place and walk on into character select on admission - the stable master, corrected against the binary: a stabled-pet drag rides the shared cursor at payload mode 10 (the mode census had that row's label wrong), a plain click always returns 1 and a drop always nil, the summoned pet dropped on an occupied stable slot swaps (STABLE was refused whenever both bought slots were full, silently), an unpurchased slot takes nothing, the stabled→summoned fork reads the live pet guid not the row, the client itself sends `MSG_LIST_STABLED_PETS` on the interact leg, `PET_STABLE_SHOW` fires on every list, the selection is a petNumber and every list clears it, and result codes 2–7 do nothing at all - the login dialog's text is centred (a FontString with no `justifyH` is CENTER, and `GlueDialogText` has none), the fifteen-year-dead "see www.worldofwarcraft.com" clauses are cut at the clause, the Login click sound is unconditional (the reference plays `gsLogin` before it checks the boxes), dialog buttons play `gsTitleOptionOK`, the realmlist button's `gsClick` never existed and is `gsLoginNewAccount`, and focusing a login box selects it — a stated divergence Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
1fd736759e |
guild charters: the registrar, the charter, and the twelve verbs
- founding a guild: fourteen opcodes, eight goldens (four mutation-checked), twelve engine globals, `GuildRegistrarFrame` and `PetitionFrame` — `CMSG_PETITION_BUY` is a 72-byte frame the server reads two fields of and drops in silence if short, `allowedGender` is the family's one u16, a signature is a 12-byte stride not 8, and `MSG_PETITION_DECLINE` writes the charter guid and reads the decliner's — same width, opposite meaning
- two sessions, not one: the registrar is an NPC session (closed by walking away — its show event is one of the fourteen callers of the interact latch, so the registrar turns to face you) and the charter is bound to an item guid you carry across the city; right-clicking a charter in your bags opens it, keyed on template flag `0x2000` (item 5863 has no on-use spell and no quest, so every existing item-use arm declined it)
- the byte carve came back and rescored six named guesses — three confirmed, two corrected, one refuted: `PETITION_SHOW` is deferred until every signer name has resolved (the window never paints blank rows), `ClosePetition` on somebody else's charter sends `MSG_PETITION_DECLINE` ("sends nothing" had been chosen on principle and was wrong half the time), and founding a guild is silent — no `ERR_GUILD_FOUNDER_S`, the reference emits no text at all; the four success ids go to chat and the five refusals to the red error frame, three paraphrased strings are now the shipped ones (a sweep asserts all fifteen), and the `npc` unit token had never been fed — the registrar's name banner was blank; `WOW_PROBE_CHARTER=1` drives gossip → buy → open → rename → destroy live, 10/10
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
a5cb3cf746 |
guild charters: the registrar, the charter, and the twelve verbs
- founding a guild: fourteen opcodes, eight goldens (four mutation-checked), twelve engine globals, `GuildRegistrarFrame` and `PetitionFrame` — `CMSG_PETITION_BUY` is a 72-byte frame the server reads two fields of and drops in silence if short, `allowedGender` is the family's one u16, a signature is a 12-byte stride not 8, and `MSG_PETITION_DECLINE` writes the charter guid and reads the decliner's — same width, opposite meaning
- two sessions, not one: the registrar is an NPC session (closed by walking away — its show event is one of the fourteen callers of the interact latch, so the registrar turns to face you) and the charter is bound to an item guid you carry across the city; right-clicking a charter in your bags opens it, keyed on template flag `0x2000` (item 5863 has no on-use spell and no quest, so every existing item-use arm declined it)
- the byte carve came back and rescored six named guesses — three confirmed, two corrected, one refuted: `PETITION_SHOW` is deferred until every signer name has resolved (the window never paints blank rows), `ClosePetition` on somebody else's charter sends `MSG_PETITION_DECLINE` ("sends nothing" had been chosen on principle and was wrong half the time), and founding a guild is silent — no `ERR_GUILD_FOUNDER_S`, the reference emits no text at all; the four success ids go to chat and the five refusals to the red error frame, three paraphrased strings are now the shipped ones (a sweep asserts all fifteen), and the `npc` unit token had never been fed — the registrar's name banner was blank; `WOW_PROBE_CHARTER=1` drives gossip → buy → open → rename → destroy live, 10/10
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
57b61de04b |
GM tickets are in, and a login failure shows the string 1.12 shows
- GM tickets, end to end: five request/answer pairs, the seven Help-window bindings, three events and `GMTicketCategory.dbc` — the ten categories `HelpFrame.lua` keys 1..10 live in a DBC nothing here had ever opened (the four `TICKET_TYPE` strings feed a dropdown 1.12 never gave a frame); the category is one byte on the wire (a u32 would shift the map id and position and file every ticket at a garbage spot), and `UPDATETEXT` carries it too, which vmangos stores and cmangos swallows as the first character of the text — faithful to the client, the divergence recorded - the engine re-asks for the ticket after a create or update succeeds and on a status push (the ask opcode has three callers in the reference, two of them engine legs with no idempotence guard) — which is why the shipped FrameXML registers no handler for the three response opcodes and still repaints; without that leg the form stays a form for ten minutes; `UPDATE_GM_STATUS` is a signed passthrough (`0xFFFFFFFF` → −1), the five ticket verbs drain through one ordered queue because call order is wire order, and the Help micro button — drawn, hovering and a no-op since the micro menu landed — is live - a typed wrong password reads the reference's long "check the spelling of the account name and password" (0x04 and 0x05 share one jump-table arm — the client cannot say "wrong password", and the lockout cmangos's header describes does not exist in the binary), unknown codes read "Disconnected from server" rather than "Authentication failed", and every realmd row of the old map was in the wrong one: the two login-status enums have two key tables and two dialog paths, and a server source can only ever verify the codes, never which string the client draws for them Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
1c4cc147f5 |
GM tickets are in, and a login failure shows the string 1.12 shows
- GM tickets, end to end: five request/answer pairs, the seven Help-window bindings, three events and `GMTicketCategory.dbc` — the ten categories `HelpFrame.lua` keys 1..10 live in a DBC nothing here had ever opened (the four `TICKET_TYPE` strings feed a dropdown 1.12 never gave a frame); the category is one byte on the wire (a u32 would shift the map id and position and file every ticket at a garbage spot), and `UPDATETEXT` carries it too, which vmangos stores and cmangos swallows as the first character of the text — faithful to the client, the divergence recorded - the engine re-asks for the ticket after a create or update succeeds and on a status push (the ask opcode has three callers in the reference, two of them engine legs with no idempotence guard) — which is why the shipped FrameXML registers no handler for the three response opcodes and still repaints; without that leg the form stays a form for ten minutes; `UPDATE_GM_STATUS` is a signed passthrough (`0xFFFFFFFF` → −1), the five ticket verbs drain through one ordered queue because call order is wire order, and the Help micro button — drawn, hovering and a no-op since the micro menu landed — is live - a typed wrong password reads the reference's long "check the spelling of the account name and password" (0x04 and 0x05 share one jump-table arm — the client cannot say "wrong password", and the lockout cmangos's header describes does not exist in the binary), unknown codes read "Disconnected from server" rather than "Authentication failed", and every realmd row of the old map was in the wrong one: the two login-status enums have two key tables and two dialog paths, and a server source can only ever verify the codes, never which string the client draws for them Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
c0b7a613a9 |
the stable master is in, and master loot hands drops to the raid
- the stable master: `MSG_LIST_STABLED_PETS` both ways, the four mutations answered by one result byte, two slots priced from `StableSlotPrices.dbc` (500 and 50000 copper — the cap falls out of the data, corroborated by vmangos's `MAX_PET_STABLES` and the reference's `NUM_PET_STABLE_SLOTS`), rows seated by slot never by position (a petless hunter's list starts at a stabled row), slot 0 read from the wire because a dismissed pet has a row and no live unit, a re-list after every success because no result carries one, and `GetPetIcon` reading `CreatureFamily.dbc`'s icon column — which ships `Ability_Druid_CatForm` for both warlock families, asserted as shipped - master loot: `CMSG_LOOT_MASTER_GIVE` (the slot is a byte here where the roll family's is a u32) and `SMSG_LOOT_MASTER_LIST`; the click gate is the wire's slot-type byte and nothing else — the reference never asks who the master looter is — so a MASTER row fires `OPEN_MASTER_LOOT_LIST` instead of a take and auto-loot skips every non-ALLOW row; the candidate array is bucketed by raid subgroup into blocks of five (a dense list would have filed every candidate under the wrong "Group N"), an unresolved name is nil so `UPDATE_MASTER_LOOT_LIST` has something to repaint, and a give re-checks the row is still MASTER before sending; found on the way: a master looter in another raid subgroup lit the crown on your own portrait - `SetLootMethod` takes its third (threshold) argument; the reference's silent reset to Uncommon when it is absent is flagged and not adopted; the stable's model pane draws nothing yet — a stabled pet is a database row with no world entity, and a booth that renders from a bare display id is the next arc Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
78e958ef4f |
the stable master is in, and master loot hands drops to the raid
- the stable master: `MSG_LIST_STABLED_PETS` both ways, the four mutations answered by one result byte, two slots priced from `StableSlotPrices.dbc` (500 and 50000 copper — the cap falls out of the data, corroborated by vmangos's `MAX_PET_STABLES` and the reference's `NUM_PET_STABLE_SLOTS`), rows seated by slot never by position (a petless hunter's list starts at a stabled row), slot 0 read from the wire because a dismissed pet has a row and no live unit, a re-list after every success because no result carries one, and `GetPetIcon` reading `CreatureFamily.dbc`'s icon column — which ships `Ability_Druid_CatForm` for both warlock families, asserted as shipped - master loot: `CMSG_LOOT_MASTER_GIVE` (the slot is a byte here where the roll family's is a u32) and `SMSG_LOOT_MASTER_LIST`; the click gate is the wire's slot-type byte and nothing else — the reference never asks who the master looter is — so a MASTER row fires `OPEN_MASTER_LOOT_LIST` instead of a take and auto-loot skips every non-ALLOW row; the candidate array is bucketed by raid subgroup into blocks of five (a dense list would have filed every candidate under the wrong "Group N"), an unresolved name is nil so `UPDATE_MASTER_LOOT_LIST` has something to repaint, and a give re-checks the row is still MASTER before sending; found on the way: a master looter in another raid subgroup lit the crown on your own portrait - `SetLootMethod` takes its third (threshold) argument; the reference's silent reset to Uncommon when it is absent is flagged and not adopted; the stable's model pane draws nothing yet — a stabled pet is a database row with no world entity, and a booth that renders from a bare display id is the next arc Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
86ecbca9f7 |
a failed dial says which failure, and the sword reads the at-war bit
- "Unable to connect" now says which: an address that does not resolve reads the reference's "Invalid Login Server", a resolved address nothing answers on reads "Login Server Down", and each names the `host:port` actually dialed — resolution and connection are two operations now (a DNS failure surfaces as `Uncategorized` on macOS, so no error kind could tell them apart), and every address a name carries is tried, `localhost` → `::1` then `127.0.0.1` included - a typed wrong password shows the login dialog instead of exiting the client, and the two auth-result enums — realmd's and the world server's — are split so a code is read against the family that sent it, with the world server's own refusal text shown for its codes - the world cursor's fork is `CanInteract` and `CanAttack`, not a reaction-rank threshold: a Cenarion Circle NPC with no gossip showed the sword at neutral (and TAB acquired it, and right-click attacked it) because one predicate implemented twice read the standing where the binary reads the at-war bit in the player→unit direction; one byte-verified `CanAttack` is shared by the cursor, TAB, pet attack orders, `UnitCanAttack` and the action-button usable gate, the service ladder falls out to a plain pointer instead of the attack leg, and `/reaction` prints the at-war bit and the branch verdict Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
dc779b3017 |
a failed dial says which failure, and the sword reads the at-war bit
- "Unable to connect" now says which: an address that does not resolve reads the reference's "Invalid Login Server", a resolved address nothing answers on reads "Login Server Down", and each names the `host:port` actually dialed — resolution and connection are two operations now (a DNS failure surfaces as `Uncategorized` on macOS, so no error kind could tell them apart), and every address a name carries is tried, `localhost` → `::1` then `127.0.0.1` included - a typed wrong password shows the login dialog instead of exiting the client, and the two auth-result enums — realmd's and the world server's — are split so a code is read against the family that sent it, with the world server's own refusal text shown for its codes - the world cursor's fork is `CanInteract` and `CanAttack`, not a reaction-rank threshold: a Cenarion Circle NPC with no gossip showed the sword at neutral (and TAB acquired it, and right-click attacked it) because one predicate implemented twice read the standing where the binary reads the at-war bit in the player→unit direction; one byte-verified `CanAttack` is shared by the cursor, TAB, pet attack orders, `UnitCanAttack` and the action-button usable gate, the service ladder falls out to a plain pointer instead of the attack leg, and `/reaction` prints the at-war bit and the branch verdict Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
1a051806ad |
a realmlist button on the login screen, and a roadmap in the README
- the logon address is the reference's own `realmList` CVar — name, `host[:port]` form and the "Address of realm list server" prompt read straight out of `WoW.exe`'s string table — persisted in `benilla-config/config.toml` and edited on the login screen: a Realmlist button in the slot `AccountLogin.xml` already reserves under the Quit stack, the current address in grey beneath it, opening the reference's own `hasEditBox` glue dialog; before this the address was `$WOW_HOST` read once at process start with no way to change it; one text field and no saved list (every client at this scale ships one field), a pasted `SET realmlist "…"` line is accepted, and the default is `localhost` because the retail host has not resolved since 2019 - the README's "Not built yet" becomes "Where it's going": what done means, no dates, and one list in probable order — the remaining basics (battlegrounds, guild charters, the stable master, meeting stones, GM tickets, master loot, cinematics), addons / options / performance as ongoing, the no-brainer VanillaFixes- and SuperWoW-class fixes, playable downloads with Linux first; not planned: other expansions, Warden - a UI region's span comes from its content and the owner-edge fallback is deleted: the reference's resolver core has no parent pointer at all, a FontString floors at one unit on both axes, a texture takes its texel span, and a region resolves from its own anchors and span or not at all — a live census over 8772 rects: 0 stopped resolving, 923 FontStrings shrank (842 to exactly 1×1 — empty labels that had been the whole screen, or an inverted rect), 0 textures moved; and `Region:GetWidth`/`GetHeight` are the same virtual getters the resolver calls (authored value wins per axis, natural width, wrapped height, texel span for art), so a script reads the number its rect was built from Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
0d7b984304 |
a realmlist button on the login screen, and a roadmap in the README
- the logon address is the reference's own `realmList` CVar — name, `host[:port]` form and the "Address of realm list server" prompt read straight out of `WoW.exe`'s string table — persisted in `benilla-config/config.toml` and edited on the login screen: a Realmlist button in the slot `AccountLogin.xml` already reserves under the Quit stack, the current address in grey beneath it, opening the reference's own `hasEditBox` glue dialog; before this the address was `$WOW_HOST` read once at process start with no way to change it; one text field and no saved list (every client at this scale ships one field), a pasted `SET realmlist "…"` line is accepted, and the default is `localhost` because the retail host has not resolved since 2019 - the README's "Not built yet" becomes "Where it's going": what done means, no dates, and one list in probable order — the remaining basics (battlegrounds, guild charters, the stable master, meeting stones, GM tickets, master loot, cinematics), addons / options / performance as ongoing, the no-brainer VanillaFixes- and SuperWoW-class fixes, playable downloads with Linux first; not planned: other expansions, Warden - a UI region's span comes from its content and the owner-edge fallback is deleted: the reference's resolver core has no parent pointer at all, a FontString floors at one unit on both axes, a texture takes its texel span, and a region resolves from its own anchors and span or not at all — a live census over 8772 rects: 0 stopped resolving, 923 FontStrings shrank (842 to exactly 1×1 — empty labels that had been the whole screen, or an inverted rect), 0 textures moved; and `Region:GetWidth`/`GetHeight` are the same virtual getters the resolver calls (authored value wins per axis, natural width, wrapped height, texel span for art), so a script reads the number its rect was built from Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
66747179a1 |
effects ride the lift with you, and a long frame keeps you on the deck
- a rider's effects are stored in the deck's frame: standing still on the Thunder Bluff lift, a weapon enchant's streak hung four yards below the blade and through the floor, because its edges were laid down in world space while the car climbed out from under them — the reference folds the transport matrix (translate · Rz(facing), NULL on the ground) into the emitter at birth and back out at draw, so committed content rides the deck and only a boundary re-expresses it; a `RideFrame` on the rider's model, inherited down the parent-model chain the way the reference copies the transport pointer to every child each frame, one fold at birth, one at draw, one at the boundary — ribbons take it unconditionally, world-mode particle clouds take it, model-mode clouds never see it; measured on the car: streak 4.2 yd → 0.00 over a 49 yd climb, while the same rider thrown off the top streaks 0.9 → 24.8 yd on the way down - switching away from the window while riding a lift dropped you through it: a collider moved in `Update` is invisible to `Update`'s own spatial queries until the next physics step, so on a 1 s frame the deck descended 7 yd with its broad-phase box left behind, the ground probe found nothing under the feet, and the second long frame's clamped 250 ms of gravity put them under the deck; avian's own `update_moved_collider_aabbs` now runs inside the transport chain right after the deck moves (0.03 ms p50, flat across scene density), and `WOW_STALL` injects long frames on demand, since a probe window is never throttled by the OS - `WOW_TRAIL_CENSUS` prints each live ribbon trail's world-space spread beside its spread on the deck — the pair that separates "not riding" from "riding but not folded"; it first matched zero trails in every scene by requiring a component trails deliberately never carry, recorded rather than quietly fixed, because an instrument answering a confident zero cost an afternoon Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
1fb4d75acd |
effects ride the lift with you, and a long frame keeps you on the deck
- a rider's effects are stored in the deck's frame: standing still on the Thunder Bluff lift, a weapon enchant's streak hung four yards below the blade and through the floor, because its edges were laid down in world space while the car climbed out from under them — the reference folds the transport matrix (translate · Rz(facing), NULL on the ground) into the emitter at birth and back out at draw, so committed content rides the deck and only a boundary re-expresses it; a `RideFrame` on the rider's model, inherited down the parent-model chain the way the reference copies the transport pointer to every child each frame, one fold at birth, one at draw, one at the boundary — ribbons take it unconditionally, world-mode particle clouds take it, model-mode clouds never see it; measured on the car: streak 4.2 yd → 0.00 over a 49 yd climb, while the same rider thrown off the top streaks 0.9 → 24.8 yd on the way down - switching away from the window while riding a lift dropped you through it: a collider moved in `Update` is invisible to `Update`'s own spatial queries until the next physics step, so on a 1 s frame the deck descended 7 yd with its broad-phase box left behind, the ground probe found nothing under the feet, and the second long frame's clamped 250 ms of gravity put them under the deck; avian's own `update_moved_collider_aabbs` now runs inside the transport chain right after the deck moves (0.03 ms p50, flat across scene density), and `WOW_STALL` injects long frames on demand, since a probe window is never throttled by the OS - `WOW_TRAIL_CENSUS` prints each live ribbon trail's world-space spread beside its spread on the deck — the pair that separates "not riding" from "riding but not folded"; it first matched zero trails in every scene by requiring a component trails deliberately never carry, recorded rather than quietly fixed, because an instrument answering a confident zero cost an afternoon Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
693c26d9c4 |
held weapons pick, book images size to their art, the panel opens again
- a unit's pick geometry is every model chained to it — body, held items, mount — one candidate per root resolving to the same unit, which is how the reference registers its pick (it walks the attachment tree and registers each model); Naxxramas' floating weapons could only be selected by their name plate before (no body, no candidate), and every armed unit gains its gear as clickable surface (our own body 12 → 21 tested parts); the broad phase stays the body's sphere, so a very long polearm on a small body is the named residual - the selection ring's writer has two branches and we had transcribed one: a model whose stand box is degenerate (zero extent in x and y) rings at the literal 1.2 × scale — 2.7 yd under a trigger creature — instead of `sqrt(0.5·sqrt(dx²+dy²))` = 0 clamped to an invented 0.05 floor; both invented fallbacks are gone - an HTML book image with no width/height is its art's texel square (one texel = one FrameXML unit, bit-for-bit the `<AbsDimension>` converter), not the rest of the page — *A Treatise on Military Ranks* drew its crest twice too big and stretched to the page's aspect; a texture-size oracle answers off the same decoder the renderer draws with, and an unfloated height-less `<IMG>` reserves its art's height in the flow; 797 shipped textures swept, exactly two zero-size axes move and neither is visible - the dev debug panel killed the client on open with "Attachments have differing sample counts": Bevy's 2-D depth texture is keyed on the render target alone, so two Camera2ds on one window at different MSAA counts cannot both be valid, and the egui overlay camera had silently kept the default 4× after the player-UI camera went to Off; it now says `Msaa::Off`, and a preflight check reports any two 2-D cameras that disagree on a shared target, every run Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
18858046f9 |
held weapons pick, book images size to their art, the panel opens again
- a unit's pick geometry is every model chained to it — body, held items, mount — one candidate per root resolving to the same unit, which is how the reference registers its pick (it walks the attachment tree and registers each model); Naxxramas' floating weapons could only be selected by their name plate before (no body, no candidate), and every armed unit gains its gear as clickable surface (our own body 12 → 21 tested parts); the broad phase stays the body's sphere, so a very long polearm on a small body is the named residual - the selection ring's writer has two branches and we had transcribed one: a model whose stand box is degenerate (zero extent in x and y) rings at the literal 1.2 × scale — 2.7 yd under a trigger creature — instead of `sqrt(0.5·sqrt(dx²+dy²))` = 0 clamped to an invented 0.05 floor; both invented fallbacks are gone - an HTML book image with no width/height is its art's texel square (one texel = one FrameXML unit, bit-for-bit the `<AbsDimension>` converter), not the rest of the page — *A Treatise on Military Ranks* drew its crest twice too big and stretched to the page's aspect; a texture-size oracle answers off the same decoder the renderer draws with, and an unfloated height-less `<IMG>` reserves its art's height in the flow; 797 shipped textures swept, exactly two zero-size axes move and neither is visible - the dev debug panel killed the client on open with "Attachments have differing sample counts": Bevy's 2-D depth texture is keyed on the render target alone, so two Camera2ds on one window at different MSAA counts cannot both be valid, and the egui overlay camera had silently kept the default 4× after the player-UI camera went to Off; it now says `Msaa::Off`, and a preflight check reports any two 2-D cameras that disagree on a shared target, every run Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
cbf77812d7 |
the cave hides the lake, the lifts come back, the bolt gets its width
- from inside a building the open-world water outside draws only through a doorway you can see, as terrain and trees already did — the Caverns of Time lake is gone from the cavern's ceiling: there was never a second visibility lane for open-world liquid (the old deferral said "it already has an authority"; a sweep of every visibility writer found none, so Bevy's frustum test was the lake's only gate), an ADT liquid layer is tagged exterior scene at spawn and the existing window cull owns it, one 33 yd chunk layer at a time — which the reference's bytes then confirmed is its unit too (`CChunkLiquid`, reachable only from the per-window walk, a sealed room's supply discarded not deferred); a building's own pool also rides the Map Objects toggle now, so switching buildings off no longer leaves the canals hanging in the air - the Thunder Bluff elevators and every other Kalimdor lift were invisible for the whole session whenever you logged in on that continent: the lift arm snapshotted the current map one stage before the login frame had written it, so every lift compared itself against map 0 and hid as off-map — a lift carries no map at all now (it is only ever streamed to players standing on its own map), the off-map term stays for the boats it was written for, and `WOW_LIFT_CENSUS` prints each transport's arm state, cycle and visibility (13 transports, 11 hidden → 0) - the lightning across Razorgore's room and Chain Lightning's mob-to-mob hop drew as hairlines: the chain renderer took each hop's cross-section as the world-horizontal perpendicular, where the reference takes `(−d.y, d.x, 0)` in eye space — the ribbon is view-plane aligned and keeps its authored 2 × halfWidth yards at every angle, so a long level beam watched from its own plane no longer thins to a line (the "a hop seen end-on genuinely collapses" note was wrong and is gone) - a display that names a model builds even when it draws no batch — Naxxramas' Unholy Axe / Swords / Staff are an invisible stalker holding a Monster weapon, and the held weapon had nowhere to hang; the same gate was keeping 43 emitter-only GameObjects dark (house and blacksmith smoke, Ironforge's lava steam, Stratholme's embers, every firework), and a name sits at the authored PlayerName attachment instead of at the feet; and a vendor's foot-shuffle on turning to you now blends the whole way in and runs to its own clip window — a 500 ms step on 1100 of 1130 shipped shuffle records — where the latch had tested the gap left against a band sixty times too wide, and nothing ever ended the step Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
80551cab5e |
the cave hides the lake, the lifts come back, the bolt gets its width
- from inside a building the open-world water outside draws only through a doorway you can see, as terrain and trees already did — the Caverns of Time lake is gone from the cavern's ceiling: there was never a second visibility lane for open-world liquid (the old deferral said "it already has an authority"; a sweep of every visibility writer found none, so Bevy's frustum test was the lake's only gate), an ADT liquid layer is tagged exterior scene at spawn and the existing window cull owns it, one 33 yd chunk layer at a time — which the reference's bytes then confirmed is its unit too (`CChunkLiquid`, reachable only from the per-window walk, a sealed room's supply discarded not deferred); a building's own pool also rides the Map Objects toggle now, so switching buildings off no longer leaves the canals hanging in the air - the Thunder Bluff elevators and every other Kalimdor lift were invisible for the whole session whenever you logged in on that continent: the lift arm snapshotted the current map one stage before the login frame had written it, so every lift compared itself against map 0 and hid as off-map — a lift carries no map at all now (it is only ever streamed to players standing on its own map), the off-map term stays for the boats it was written for, and `WOW_LIFT_CENSUS` prints each transport's arm state, cycle and visibility (13 transports, 11 hidden → 0) - the lightning across Razorgore's room and Chain Lightning's mob-to-mob hop drew as hairlines: the chain renderer took each hop's cross-section as the world-horizontal perpendicular, where the reference takes `(−d.y, d.x, 0)` in eye space — the ribbon is view-plane aligned and keeps its authored 2 × halfWidth yards at every angle, so a long level beam watched from its own plane no longer thins to a line (the "a hop seen end-on genuinely collapses" note was wrong and is gone) - a display that names a model builds even when it draws no batch — Naxxramas' Unholy Axe / Swords / Staff are an invisible stalker holding a Monster weapon, and the held weapon had nowhere to hang; the same gate was keeping 43 emitter-only GameObjects dark (house and blacksmith smoke, Ironforge's lava steam, Stratholme's embers, every firework), and a name sits at the authored PlayerName attachment instead of at the feet; and a vendor's foot-shuffle on turning to you now blends the whole way in and runs to its own clip window — a 500 ms step on 1100 of 1130 shipped shuffle records — where the latch had tested the gap left against a band sixty times too wide, and nothing ever ended the step Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
67c0c000fb |
the world redraws on resize, and terrain takes its DXT blocks
- the world froze on every resize or graphics change: the backdrop was resized by writing a fresh image through the existing handle, and a mutated `Image` is a whole new GPU texture while a material's bind group is captured once and never re-captured — so the camera drew into a texture the UI never sampled, and the last frame stretched over the window forever; a resized world target is now a NEW asset (publish, retire the old one, and the UI pass forgets materials for removed images so a window drag does not leak a 46 MB target per frame), and a resized capture now matches the native render bit for bit - terrain tile layer arrays take the DXT blocks when the tile's whole layer set allows it — one array has one format, so eligibility is the tile's, not a texture's — and the install's own census says narrow is enough: 87 % of Azeroth's tiles and 92 % of Kalimdor's pass, layer bytes 1.57 GB → 0.63 and 2.23 → 0.76; the decode-tax comment is corrected on the way past — decoding costs 8x DXT1's bytes and 4x DXT3/DXT5's, not 4x and 2x - Environment Detail is the reference's slider, not a dropdown — row 27 of 1.12's own slider table, with the readout keeping the stop names because a bare "1" means nothing to a player — and the shipped ground cover comes off High to Medium: the x3 clutter density had been matched to a configured install, and Medium is the nearest stop no sparser than what a fresh install draws on capable hardware - Display Mode is modern Classic's two-entry dropdown — Windowed (Fullscreen) / Windowed, a boolean at Blizzard's own source, where the three-mode list is pre-8.0.1 folklore — riding `gxWindow` so saved configs keep meaning, with the label-against-value polarity pinned by the row's first test; the Multisampling row comes off the Graphics page for now (the CVar, the device clamp and the bindings all stay): with alpha-to-coverage set nowhere, MSAA touches polygon silhouettes only, and render scale on the same page measures four times the visual change Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
1a1d7e50dc |
the world redraws on resize, and terrain takes its DXT blocks
- the world froze on every resize or graphics change: the backdrop was resized by writing a fresh image through the existing handle, and a mutated `Image` is a whole new GPU texture while a material's bind group is captured once and never re-captured — so the camera drew into a texture the UI never sampled, and the last frame stretched over the window forever; a resized world target is now a NEW asset (publish, retire the old one, and the UI pass forgets materials for removed images so a window drag does not leak a 46 MB target per frame), and a resized capture now matches the native render bit for bit - terrain tile layer arrays take the DXT blocks when the tile's whole layer set allows it — one array has one format, so eligibility is the tile's, not a texture's — and the install's own census says narrow is enough: 87 % of Azeroth's tiles and 92 % of Kalimdor's pass, layer bytes 1.57 GB → 0.63 and 2.23 → 0.76; the decode-tax comment is corrected on the way past — decoding costs 8x DXT1's bytes and 4x DXT3/DXT5's, not 4x and 2x - Environment Detail is the reference's slider, not a dropdown — row 27 of 1.12's own slider table, with the readout keeping the stop names because a bare "1" means nothing to a player — and the shipped ground cover comes off High to Medium: the x3 clutter density had been matched to a configured install, and Medium is the nearest stop no sparser than what a fresh install draws on capable hardware - Display Mode is modern Classic's two-entry dropdown — Windowed (Fullscreen) / Windowed, a boolean at Blizzard's own source, where the three-mode list is pre-8.0.1 folklore — riding `gxWindow` so saved configs keep meaning, with the label-against-value polarity pinned by the row's first test; the Multisampling row comes off the Graphics page for now (the CVar, the device clamp and the bindings all stay): with alpha-to-coverage set nowhere, MSAA touches polygon silhouettes only, and render scale on the same page measures four times the visual change Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
5b62b89320 |
trilinear ships on, and every line of text rounds once
- the texture filter is the reference's policy — two globals, one process-wide mode, no per-texture override — registered as real CVars every sampler reads: the hardcoded trilinear + aniso 8 at five sampler sites had been read off an apitrace of an install whose `Config.wtf` set `anisotropic "16"`, a configured value taken for a default; and `trilinear` ships ON, because the registrar's `"0"` is not what a fresh install renders at — first-launch hardware detection overwrites sixteen video CVars from its hardware table, both rows a real GPU can reach set trilinear, and the reference's own `gx.log` on this machine names that row — while `anisotropic` is not among the sixteen, so anisotropy stays off - the MSAA device clamp ran before the config was read, so a saved `gxMultisample = 8` carried from a machine that offers it still killed the render thread on one that stops at 4; the ceiling is now a property of the write itself, covering the config file, `SetCVar`, the dropdown and any writer added later — and an empty device list is no opinion, so headless runs pass through - one line, one rounding: at a fractional display scale the per-glyph snap's f32 round-trip moved half-pixel ties by an ulp, so caps and ascenders rounded up while x-height letters stayed — the letters left the baseline, the thing the reporter photographed; the line's two anchors now round once and each glyph adds integer device-pixel offsets, so a line cannot be anything but flat at any scale, proven over 15,680 layouts — and `$WOW_DPI`'s size guard, which compared a physical request against the logical size and refused every non-1x run, now reads the unit it is denominated in - a test that panics while holding `ENV_LOCK` no longer poisons the tests behind it — one missing knob resource had reported as twelve red tests, eleven naming the mutex and none naming the bug; there is nothing for the poison to protect, since the guard's `Drop` restores the environment during the panicking test's own unwind Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a48441bca8 |
trilinear ships on, and every line of text rounds once
- the texture filter is the reference's policy — two globals, one process-wide mode, no per-texture override — registered as real CVars every sampler reads: the hardcoded trilinear + aniso 8 at five sampler sites had been read off an apitrace of an install whose `Config.wtf` set `anisotropic "16"`, a configured value taken for a default; and `trilinear` ships ON, because the registrar's `"0"` is not what a fresh install renders at — first-launch hardware detection overwrites sixteen video CVars from its hardware table, both rows a real GPU can reach set trilinear, and the reference's own `gx.log` on this machine names that row — while `anisotropic` is not among the sixteen, so anisotropy stays off - the MSAA device clamp ran before the config was read, so a saved `gxMultisample = 8` carried from a machine that offers it still killed the render thread on one that stops at 4; the ceiling is now a property of the write itself, covering the config file, `SetCVar`, the dropdown and any writer added later — and an empty device list is no opinion, so headless runs pass through - one line, one rounding: at a fractional display scale the per-glyph snap's f32 round-trip moved half-pixel ties by an ulp, so caps and ascenders rounded up while x-height letters stayed — the letters left the baseline, the thing the reporter photographed; the line's two anchors now round once and each glyph adds integer device-pixel offsets, so a line cannot be anything but flat at any scale, proven over 15,680 layouts — and `$WOW_DPI`'s size guard, which compared a physical request against the logical size and refused every non-1x run, now reads the unit it is denominated in - a test that panics while holding `ENV_LOCK` no longer poisons the tests behind it — one missing knob resource had reported as twelve red tests, eleven naming the mutex and none naming the bug; there is nothing for the poison to protect, since the guard's `Drop` restores the environment during the panicking test's own unwind Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
3cc24f14be |
the world shrinks without the UI, and a party member keeps their face
- `renderScale`: the world renders into its off-screen target at a fraction — or a multiple — of the window while text, icons and frame art stay native; the logical viewport comes out arithmetically unchanged, so picking cannot see the scale at all, and every hand-written sampler takes the `log2(scale)` mip bias below 100 % and none above it, where the sharper mip is what makes supersampling work — measured here at 26x the world pixels for +0.02 ms, and reachable as a Render Scale row on the Graphics page (50–200 %), staged to Apply so a dragged slider rebuilds the world target once instead of thirty times a sweep - a party member who walks out of range keeps their numbers and their face (B334): the client asks — `CMSG_REQUEST_PARTY_MEMBER_STATS` goes out on the despawn edge and for a roster member gained unseen, the same two edges the reference sends from — the record is snapshotted whole from the live descriptor at the moment the object deactivates, a never-seen member seats at the reference's 1/1 placeholder rather than an empty bar, and the raw-to-display divide happens at the read, so an out-of-range warrior stops reading ten times the rage; the portrait binds a guid-keyed bake cache built as a handover — the booth's own target image moves into the cache as its member streams out, so the face freezes with no copy and no flicker — and the self-review adds that a changed occupant is a re-bake and the record's dead/ghost bits are read - a slider row's number sits on its label's line (B232): the readout hung off the control frame and inherited a +3 art nudge that exists to seat the groove texture — four pixels off on an eleven-pixel cap height at the reporter's geometry — so the nudge moves onto the two frames that draw the art, across eight rows on three pages, and the bar itself does not move a pixel; `$WOW_DPI` renders on a player's pixel grid, so a 1x reporter's screenshot and a capture from this 2x machine compare pixel-for-pixel Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
72ca69ef5d |
the world shrinks without the UI, and a party member keeps their face
- `renderScale`: the world renders into its off-screen target at a fraction — or a multiple — of the window while text, icons and frame art stay native; the logical viewport comes out arithmetically unchanged, so picking cannot see the scale at all, and every hand-written sampler takes the `log2(scale)` mip bias below 100 % and none above it, where the sharper mip is what makes supersampling work — measured here at 26x the world pixels for +0.02 ms, and reachable as a Render Scale row on the Graphics page (50–200 %), staged to Apply so a dragged slider rebuilds the world target once instead of thirty times a sweep - a party member who walks out of range keeps their numbers and their face (B334): the client asks — `CMSG_REQUEST_PARTY_MEMBER_STATS` goes out on the despawn edge and for a roster member gained unseen, the same two edges the reference sends from — the record is snapshotted whole from the live descriptor at the moment the object deactivates, a never-seen member seats at the reference's 1/1 placeholder rather than an empty bar, and the raw-to-display divide happens at the read, so an out-of-range warrior stops reading ten times the rage; the portrait binds a guid-keyed bake cache built as a handover — the booth's own target image moves into the cache as its member streams out, so the face freezes with no copy and no flicker — and the self-review adds that a changed occupant is a re-bake and the record's dead/ghost bits are read - a slider row's number sits on its label's line (B232): the readout hung off the control frame and inherited a +3 art nudge that exists to seat the groove texture — four pixels off on an eleven-pixel cap height at the reporter's geometry — so the nudge moves onto the two frames that draw the art, across eight rows on three pages, and the bar itself does not move a pixel; `$WOW_DPI` renders on a player's pixel grid, so a 1x reporter's screenshot and a capture from this 2x machine compare pixel-for-pixel Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
d1931eed1d |
instruments for motion at the glass, and a macro hovers to its name
- the jitter meter measures the palette and the pixels, not just the pose: `pal` probes the rows the vertex stage actually blends (the old bone columns read a matrix the GPU never sees), `SCREEN` carries them to viewport pixels by the shader's own arithmetic, `camrot` watches the camera's rotation where only its translation had been vouching for "bit-stable", and `WOW_JITTER_RAW` dumps one bone's series unaggregated — rotations too, since a translation can be smooth while its frames are not - `WOW_FIXED_DT=<ms>` pins the animation advance so a screenshot burst measures the render rather than its own stall — arming on the wall clock, because during load the app runs ~385 updates a second and a pinned clock reached "90 seconds" in 14 s, photographing an empty world - `benilla-visual flow` estimates the whole window's motion by least squares over every pixel (noise floor 0.0000 px on static regions, and its brightness-constancy limit is measured and stated: invalid on a lit deforming body), `edge` reads a silhouette's sub-pixel crossing renormalised against the lighting with an honest ±0.5 px floor, `WOW_TWIST_GAP` pins a yaw gap so the body counter-twist is exercised at all — every earlier "removing it changed nothing" had measured a pass that never ran — and `WOW_DITHER` adds the dither the frame's 8-bit output has never had, off by default because the reference's framebuffer was undithered - hovering a MACRO action slot shows one white line, its name — the reference's macro leg renders exactly that and no more, in its "normal" white, where ours was a `_ => Ok(())` from before macros shipped; and `WOW_MSAA=8` is refused with a loud warning instead of panicking the render thread, through one parser both world-camera spawners now share Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
6b2a75e8a0 |
instruments for motion at the glass, and a macro hovers to its name
- the jitter meter measures the palette and the pixels, not just the pose: `pal` probes the rows the vertex stage actually blends (the old bone columns read a matrix the GPU never sees), `SCREEN` carries them to viewport pixels by the shader's own arithmetic, `camrot` watches the camera's rotation where only its translation had been vouching for "bit-stable", and `WOW_JITTER_RAW` dumps one bone's series unaggregated — rotations too, since a translation can be smooth while its frames are not - `WOW_FIXED_DT=<ms>` pins the animation advance so a screenshot burst measures the render rather than its own stall — arming on the wall clock, because during load the app runs ~385 updates a second and a pinned clock reached "90 seconds" in 14 s, photographing an empty world - `benilla-visual flow` estimates the whole window's motion by least squares over every pixel (noise floor 0.0000 px on static regions, and its brightness-constancy limit is measured and stated: invalid on a lit deforming body), `edge` reads a silhouette's sub-pixel crossing renormalised against the lighting with an honest ±0.5 px floor, `WOW_TWIST_GAP` pins a yaw gap so the body counter-twist is exercised at all — every earlier "removing it changed nothing" had measured a pass that never ran — and `WOW_DITHER` adds the dither the frame's 8-bit output has never had, off by default because the reference's framebuffer was undithered - hovering a MACRO action slot shows one white line, its name — the reference's macro leg renders exactly that and no more, in its "normal" white, where ours was a `_ => Ok(())` from before macros shipped; and `WOW_MSAA=8` is refused with a loud warning instead of panicking the render thread, through one parser both world-camera spawners now share Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
45f001bbc5 |
the hover tax is pinned and cut, and a spell-less macro is a button
- a tooltip change costs ~1.3 ms — five whole-interface recomputes, each working as designed: the quad re-convert at 474 µs, the Lua tick at 287, the layout resolve at 200, bevy's `Assets<Mesh>` tax at ~270 and the mesh rebuild at 146 — pinned with new hover probes (a jitter dial, a `WOW_PROBE_HOVER_DUTY` duty cycle so run drift cancels, an `AssetChanged` tax meter), and the layout preamble's two whole-roster scans become lists maintained at the writer (52–83 µs → 1–11) - the splice compared this frame's entries against last frame's by index, so one inserted highlight shifted the 160 entries behind it and read as "everything changed"; it now aligns on `z` — an identity, not a position — and a `Text` entry that writes only quads became spliceable, so a tooltip change re-converts 22 entries instead of 520 (`convert` +439 µs → +107), with `WOW_UI_SPLICE_VERIFY` running the full conversion behind every spliced frame: 0 mismatches over 1,078 - a spell-less macro is a usable action button, not the 0.4 grey — the reference's usable compute has a dedicated leg answering usable for the bound-spell zero, cross-checked at the bytes in the reference's disassembly — and the button's Name line is written unconditionally from `GetActionText` as the reference does, so the macro's name sits under its icon and a `/cast` of a spell the character does not know now greys, which is also 1.12's behaviour (B340) - a capture bounds its run in wall-clock seconds, because a frame cap is no cap at the ~1 fps a starved `nextDrawable` leaves — 1800 frames is thirty minutes there — and the teardown backstop runs on every run as a liveness guarantee, carrying the exit code the run asked for; the Multisampling row reads Off / 2x / 4x, since "1x" contradicts the no-multisampling byte both of the reference's enumerators normalise to and the bit-depth prefix was identical on every row Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a40cc4a905 |
the hover tax is pinned and cut, and a spell-less macro is a button
- a tooltip change costs ~1.3 ms — five whole-interface recomputes, each working as designed: the quad re-convert at 474 µs, the Lua tick at 287, the layout resolve at 200, bevy's `Assets<Mesh>` tax at ~270 and the mesh rebuild at 146 — pinned with new hover probes (a jitter dial, a `WOW_PROBE_HOVER_DUTY` duty cycle so run drift cancels, an `AssetChanged` tax meter), and the layout preamble's two whole-roster scans become lists maintained at the writer (52–83 µs → 1–11) - the splice compared this frame's entries against last frame's by index, so one inserted highlight shifted the 160 entries behind it and read as "everything changed"; it now aligns on `z` — an identity, not a position — and a `Text` entry that writes only quads became spliceable, so a tooltip change re-converts 22 entries instead of 520 (`convert` +439 µs → +107), with `WOW_UI_SPLICE_VERIFY` running the full conversion behind every spliced frame: 0 mismatches over 1,078 - a spell-less macro is a usable action button, not the 0.4 grey — the reference's usable compute has a dedicated leg answering usable for the bound-spell zero, cross-checked at the bytes in the reference's disassembly — and the button's Name line is written unconditionally from `GetActionText` as the reference does, so the macro's name sits under its icon and a `/cast` of a spell the character does not know now greys, which is also 1.12's behaviour (B340) - a capture bounds its run in wall-clock seconds, because a frame cap is no cap at the ~1 fps a starved `nextDrawable` leaves — 1800 frames is thirty minutes there — and the teardown backstop runs on every run as a liveness guarantee, carrying the exit code the run asked for; the Multisampling row reads Off / 2x / 4x, since "1x" contradicts the no-multisampling byte both of the reference's enumerators normalise to and the bit-depth prefix was identical on every row Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a0447c171d |
action-bar hover stops re-deriving, and multisampling asks the GPU
- hovering the action bars re-derived the whole layout graph and hovering bags did not: `GameTooltip:SetOwner(owner, "ANCHOR_NONE")` dropped the tooltip's anchors through the conservative whole-graph derive, and with `UberTooltips` at its shipped default every action-bar button routes through that arm while a bag slot anchors `ANCHOR_RIGHT` and never does — the arm now retargets to the empty target set, and derive frames fall from 15.9 % of hovered frames to 0.2 % - `gxMultisample` clamps to what the GPU actually offers: Apple GPUs stop at 4x, so a typed 8 was a wgpu validation panic on frame one — the clamp intersects the supported counts of every format the client multisamples into and steps the request down the way the reference's device-init retry loop does, with a warning that says so - the Multisampling dropdown lands on the Graphics page with the device's own stops, built from the same enumeration that clamps a typed value on the reference's three bindings (`GetMultisampleFormats`, `GetCurrentMultisampleFormat`, `SetMultisampleFormat`) — a fixed Off/2x/4x/8x ladder would put a crash on the menu of every GPU that stops at 4 - capture hardening: a run whose `$WOW_WIN` the display clamped is refused in ~2 s instead of producing a wrong-sized shot to diff, a capture never reads the OS pointer (a cursor resting over the window arms a hover and a tooltip that a cursor an inch to the left does not), and the stall sampler writes into `benilla-config` instead of a hand-built `~/Library/Logs` path Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
bf7201f4d3 |
action-bar hover stops re-deriving, and multisampling asks the GPU
- hovering the action bars re-derived the whole layout graph and hovering bags did not: `GameTooltip:SetOwner(owner, "ANCHOR_NONE")` dropped the tooltip's anchors through the conservative whole-graph derive, and with `UberTooltips` at its shipped default every action-bar button routes through that arm while a bag slot anchors `ANCHOR_RIGHT` and never does — the arm now retargets to the empty target set, and derive frames fall from 15.9 % of hovered frames to 0.2 % - `gxMultisample` clamps to what the GPU actually offers: Apple GPUs stop at 4x, so a typed 8 was a wgpu validation panic on frame one — the clamp intersects the supported counts of every format the client multisamples into and steps the request down the way the reference's device-init retry loop does, with a warning that says so - the Multisampling dropdown lands on the Graphics page with the device's own stops, built from the same enumeration that clamps a typed value on the reference's three bindings (`GetMultisampleFormats`, `GetCurrentMultisampleFormat`, `SetMultisampleFormat`) — a fixed Off/2x/4x/8x ladder would put a crash on the menu of every GPU that stops at 4 - capture hardening: a run whose `$WOW_WIN` the display clamped is refused in ~2 s instead of producing a wrong-sized shot to diff, a capture never reads the OS pointer (a cursor resting over the window arms a hover and a tooltip that a cursor an inch to the left does not), and the stall sampler writes into `benilla-config` instead of a hand-built `~/Library/Logs` path Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a60f723ad4 |
borderless fullscreen ships, and the 4x MSAA nobody chose is off
- the display mode is borderless fullscreen by default, and there is no exclusive mode at all — winit ignores exclusive on Wayland, X11's path cannot restore the desktop after a crash, macOS has none, and WoW itself dropped it in 8.0.1; 1.12's `gxWindow` row keeps its name, polarity and default with "0" redefined as borderless, read before the window exists so it is born in the player's mode (a window that does not fill gamescope's nested output is a documented input break, and the recorded workaround is "set the game to fullscreen"), `gxResolution` remembers the windowed size, and the Graphics page grows 1.12's own Windowed Mode checkbox - the UI camera says `Msaa::Off` out loud, because silence there meant Bevy's default 4×: the world arrives on this camera as an already-resolved quad and everything it draws itself is axis-aligned rects, so four samples bought a 4× colour target, a 4× depth texture nothing ever writes, 4× the fill on every quad and a resolve — for a measured difference of MAE ≤ 0.024, all of it quad borders now drawn at their authored crispness, which is also the reference's hard-edged 8-bit direction - `gxMultisample` is a real player setting, and it ships off — the reference's own default: the reference registers no literal, it formats field 21 of the `VideoHardware.dbc` row the GPU matched, a 193-row table that holds nothing above 2 anywhere and whose every 2004-era id misses a modern card, so the fallback rows answer and all of them hold 1; the setting persists, all three world-lane cameras read it on the reference's [1,16] scale rounded down the way its own retry loop steps, and `$WOW_MSAA` survives session-only - two instruments for the tooltip hunt: `rebuild_ui_mesh` — which sorts, clips and re-splits every quad in the interface on any dirty frame — gets a meter carrying total/sort/split/write beside the script phases whose flat reading had stood as an alibi, and `WOW_PROBE_HOVER` sweeps the real cursor across named frames through the real pointer path, pressing nothing: the hover recorder records what a hand does, and this supplies the hand Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
17a47acd71 |
borderless fullscreen ships, and the 4x MSAA nobody chose is off
- the display mode is borderless fullscreen by default, and there is no exclusive mode at all — winit ignores exclusive on Wayland, X11's path cannot restore the desktop after a crash, macOS has none, and WoW itself dropped it in 8.0.1; 1.12's `gxWindow` row keeps its name, polarity and default with "0" redefined as borderless, read before the window exists so it is born in the player's mode (a window that does not fill gamescope's nested output is a documented input break, and the recorded workaround is "set the game to fullscreen"), `gxResolution` remembers the windowed size, and the Graphics page grows 1.12's own Windowed Mode checkbox - the UI camera says `Msaa::Off` out loud, because silence there meant Bevy's default 4×: the world arrives on this camera as an already-resolved quad and everything it draws itself is axis-aligned rects, so four samples bought a 4× colour target, a 4× depth texture nothing ever writes, 4× the fill on every quad and a resolve — for a measured difference of MAE ≤ 0.024, all of it quad borders now drawn at their authored crispness, which is also the reference's hard-edged 8-bit direction - `gxMultisample` is a real player setting, and it ships off — the reference's own default: the reference registers no literal, it formats field 21 of the `VideoHardware.dbc` row the GPU matched, a 193-row table that holds nothing above 2 anywhere and whose every 2004-era id misses a modern card, so the fallback rows answer and all of them hold 1; the setting persists, all three world-lane cameras read it on the reference's [1,16] scale rounded down the way its own retry loop steps, and `$WOW_MSAA` survives session-only - two instruments for the tooltip hunt: `rebuild_ui_mesh` — which sorts, clips and re-splits every quad in the interface on any dirty frame — gets a meter carrying total/sort/split/write beside the script phases whose flat reading had stood as an alibi, and `WOW_PROBE_HOVER` sweeps the real cursor across named frames through the real pointer path, pressing nothing: the hover recorder records what a hand does, and this supplies the hand Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
ee8f9ddfa0 |
the login scene frames its art, char select remembers, DXT stays DXT
- the glue scene widens only as far as its art goes: none of the seven login dioramas is drawn wider than about 3:2 — measured per texel by `benilla-extract glueextent`, which rasterises every batch into the camera's own tan-space, painting where the reference's alpha-key test passes — so the frame zooms down to the reference's own 16:9 opening (never tighter) and pillarboxes past the aspect the art cannot fill, instead of showing the clear colour past the backdrop's slanted edges; 4:3 stays byte-identical - the character screen opens on whoever you last logged in as: the reference's `lastCharacterIndex` CVar, written at Enter World and only there — clicks and arrow keys never touch it, which is what makes the value mean "last logged in" rather than "last clicked" — restored on every character-list rebuild and clamped into range - spam-hovering tooltips stops costing 2 ms: two write sites gave up naming their node and re-derived the whole layout graph (1,812 µs against the ledger's 44, on 919 of 1,262 resolves) — the wrap pin now touches the one region it wrote, and re-pointing a tooltip at the button under the cursor retargets the node's edges in place instead of throwing the cached graph away - two corrections off the project's first GPU-bound report (a Steam Deck at 94% GPU busy on 8.4 W of a 15 W budget, the memory-stall signature): `farclip` ships the reference's registered 350 instead of the clamp's 777 — the value also sizes terrain residency, so 777 streamed, held and drew 4.8× the area — and BLP textures upload WoW's own DXT blocks verbatim the way the reference does, instead of decoding to RGBA8 at 8× the bytes of DXT1; the terrain slider still reaches 777, and the lanes that read texels on the CPU (terrain arrays, the character-skin compositor) stay decoded and say why Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
7146bc91f0 |
the login scene frames its art, char select remembers, DXT stays DXT
- the glue scene widens only as far as its art goes: none of the seven login dioramas is drawn wider than about 3:2 — measured per texel by `benilla-extract glueextent`, which rasterises every batch into the camera's own tan-space, painting where the reference's alpha-key test passes — so the frame zooms down to the reference's own 16:9 opening (never tighter) and pillarboxes past the aspect the art cannot fill, instead of showing the clear colour past the backdrop's slanted edges; 4:3 stays byte-identical - the character screen opens on whoever you last logged in as: the reference's `lastCharacterIndex` CVar, written at Enter World and only there — clicks and arrow keys never touch it, which is what makes the value mean "last logged in" rather than "last clicked" — restored on every character-list rebuild and clamped into range - spam-hovering tooltips stops costing 2 ms: two write sites gave up naming their node and re-derived the whole layout graph (1,812 µs against the ledger's 44, on 919 of 1,262 resolves) — the wrap pin now touches the one region it wrote, and re-pointing a tooltip at the button under the cursor retargets the node's edges in place instead of throwing the cached graph away - two corrections off the project's first GPU-bound report (a Steam Deck at 94% GPU busy on 8.4 W of a 15 W budget, the memory-stall signature): `farclip` ships the reference's registered 350 instead of the clamp's 777 — the value also sizes terrain residency, so 777 streamed, held and drew 4.8× the area — and BLP textures upload WoW's own DXT blocks verbatim the way the reference does, instead of decoding to RGBA8 at 8× the bytes of DXT1; the terrain slider still reaches 777, and the lanes that read texels on the CPU (terrain arrays, the character-skin compositor) stay decoded and say why Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
b344fc4938 |
Levitate walks on water, the doll takes a snapshot, the pose keeps time
- Levitate over water, whole: hover stacks on the water-walk surface, so the body rests exactly a yard above the waterline — the reference's own arm undoes the ground snap and descends by max(L−1.0, 0); casting it while swimming launches you clear of the water, because `SetHover(true)`'s handler calls `CMovement::Jump` before it ever sets the flag — a jump that, unlike Space's, is not refused for a hovering body; and aiming below −37° drops the liquid layers out of the walk mask, which is the reference's own way back into the water and the piece whose absence made the mode a one-way door - walking no longer sinks a Levitator: the step-down snap's no-hit leg — right on land, where it is the frame that leaves a ledge — could not see water, since liquid is queried rather than swept, so every walking frame stepped down a cone's worth while the hover climb hauled it back; the arithmetic closes with no free parameters (descent 0.24355 yd a frame, climb 0.11667, net −0.12688 against a measured −0.12687), settling 0.88 yd under the hover line until the keys were released - the pose advances on the PRESENTATION cadence, not the CPU loop: under vsync a frame reaches the eye only on a refresh boundary, but the measured delta absorbs the render thread's back-pressure wait, so two frames shown 16.67 ms apart get advanced 26.4 and 8.0 — the whole skeleton lurching at once, up to 91 of 117 bones past a quarter pixel in one frame; `Time<Virtual>` is re-split to a delta snapped to the estimated refresh with the remainder carried, engaging only while the stream looks vsync'd so a real stall stays visible — found once the jitter meter probed a point at each bone's flesh radius and logged the animation clock beside the wall clock, the two channels it had been blind in - the character doll is a snapshot you edit, not a mirror you follow: the reference re-takes a model widget's copy on becoming visible, a change of dress, a manual sheath toggle or a resize — the combat auto-draw is not one of them, so a bow drawn in combat stays off the character sheet; and a portrait bake now waits for its PIPELINES too, not just its textures — off macOS a cold pipeline variant skips its batch silently, a one-shot still keeps the hole for the session, and which piece goes missing is which variants lost the race: the hair's alpha-key, the body's opaque, a glow card Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
88f036206e |
Levitate walks on water, the doll takes a snapshot, the pose keeps time
- Levitate over water, whole: hover stacks on the water-walk surface, so the body rests exactly a yard above the waterline — the reference's own arm undoes the ground snap and descends by max(L−1.0, 0); casting it while swimming launches you clear of the water, because `SetHover(true)`'s handler calls `CMovement::Jump` before it ever sets the flag — a jump that, unlike Space's, is not refused for a hovering body; and aiming below −37° drops the liquid layers out of the walk mask, which is the reference's own way back into the water and the piece whose absence made the mode a one-way door - walking no longer sinks a Levitator: the step-down snap's no-hit leg — right on land, where it is the frame that leaves a ledge — could not see water, since liquid is queried rather than swept, so every walking frame stepped down a cone's worth while the hover climb hauled it back; the arithmetic closes with no free parameters (descent 0.24355 yd a frame, climb 0.11667, net −0.12688 against a measured −0.12687), settling 0.88 yd under the hover line until the keys were released - the pose advances on the PRESENTATION cadence, not the CPU loop: under vsync a frame reaches the eye only on a refresh boundary, but the measured delta absorbs the render thread's back-pressure wait, so two frames shown 16.67 ms apart get advanced 26.4 and 8.0 — the whole skeleton lurching at once, up to 91 of 117 bones past a quarter pixel in one frame; `Time<Virtual>` is re-split to a delta snapped to the estimated refresh with the remainder carried, engaging only while the stream looks vsync'd so a real stall stays visible — found once the jitter meter probed a point at each bone's flesh radius and logged the animation clock beside the wall clock, the two channels it had been blind in - the character doll is a snapshot you edit, not a mirror you follow: the reference re-takes a model widget's copy on becoming visible, a change of dress, a manual sheath toggle or a resize — the combat auto-draw is not one of them, so a bow drawn in combat stays off the character sheet; and a portrait bake now waits for its PIPELINES too, not just its textures — off macOS a cold pipeline variant skips its batch silently, a one-shot still keeps the hole for the session, and which piece goes missing is which variants lost the race: the hair's alpha-key, the body's opaque, a glow card Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
d6953c936f |
the missing bra, the robe's hem, and a doll that puts its arrow down
- the missing bra: the underwear section's CharSections row spends BOTH of its texture columns and the body compositor read only the first — the pelvis — so a bare-chested female composited panties and then bare skin above them; the second column is torso art authored on all eight female race rows and no male row, which is how the male-only regression test stayed green over the missing half, and the new test is byte-exact — the composite's torso tile must equal the shipped BLP's mip 0 verbatim - underwear is the tile's FALLBACK, not an under-layer: the reference tests a prefix of a tile's equipment cells and skips the underwear blit entirely when any is occupied, while cells past the prefix stack on top of an underwear that was allowed to draw — so a shirt or chest suppresses the bra, trousers the panties, but a belt never hides the panties and a plain tabard never hides the bra; benilla blitted underwear first and equipment over it, which coincides on most gear and is still the wrong law - a robe outranks footwear on the lower-leg tile: the equipment stacking table is a DEFAULT that two of the eight layer choosers overrule, and the robe bit lifts a chest to cell 4 over a boot's 3, so sandals stop repainting a robe's hem; and `_U` outranks the gendered file — the reference probes the universal name first and patches the gender letter in only on a miss (43 of 7944 shipped basenames carry both, and on those the gendered art is dead), which closes the bare-skin ring a shorter `_F` pant file left below the knee; `benilla-extract charatlas` prints the blits in order with the file each region resolved to, reading the same `equip_blits` law the compositor walks - a model widget edits its copy the way the reference does: fifteen attach ids reset off every duplicate — blood, breath, the nameplates, the spell hands, and the nocked arrow — and the hand grips arm from attachment occupancy, where ours sat hardcoded open under a comment claiming the pane sheaths its weapons (it never did); the character doll stops drawing a hunter's arrow and closes the hand around the bow, and the booth bake log now names its attach ids (`at=[2,35] grip=[false,true]`), which is also the reset's retest readout Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
e29cb90ebd |
the missing bra, the robe's hem, and a doll that puts its arrow down
- the missing bra: the underwear section's CharSections row spends BOTH of its texture columns and the body compositor read only the first — the pelvis — so a bare-chested female composited panties and then bare skin above them; the second column is torso art authored on all eight female race rows and no male row, which is how the male-only regression test stayed green over the missing half, and the new test is byte-exact — the composite's torso tile must equal the shipped BLP's mip 0 verbatim - underwear is the tile's FALLBACK, not an under-layer: the reference tests a prefix of a tile's equipment cells and skips the underwear blit entirely when any is occupied, while cells past the prefix stack on top of an underwear that was allowed to draw — so a shirt or chest suppresses the bra, trousers the panties, but a belt never hides the panties and a plain tabard never hides the bra; benilla blitted underwear first and equipment over it, which coincides on most gear and is still the wrong law - a robe outranks footwear on the lower-leg tile: the equipment stacking table is a DEFAULT that two of the eight layer choosers overrule, and the robe bit lifts a chest to cell 4 over a boot's 3, so sandals stop repainting a robe's hem; and `_U` outranks the gendered file — the reference probes the universal name first and patches the gender letter in only on a miss (43 of 7944 shipped basenames carry both, and on those the gendered art is dead), which closes the bare-skin ring a shorter `_F` pant file left below the knee; `benilla-extract charatlas` prints the blits in order with the file each region resolved to, reading the same `equip_blits` law the compositor walks - a model widget edits its copy the way the reference does: fifteen attach ids reset off every duplicate — blood, breath, the nameplates, the spell hands, and the nocked arrow — and the hand grips arm from attachment occupancy, where ours sat hardcoded open under a comment claiming the pane sheaths its weapons (it never did); the character doll stops drawing a hunter's arrow and closes the hand around the bow, and the booth bake log now names its attach ids (`at=[2,35] grip=[false,true]`), which is also the reset's retest readout Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
69bcd3bb6b |
gear rides the rig, water walking answers the keys, and a jitter meter
- an attached model's frame rides its wearer's rig: composed as bone-offset-plus-world-root every frame, a helm at Elwynn's ~9500-yard coordinates lands on a 0.98 mm f32 grid (exactly 2^-10 yd) and snaps whole steps against a body that moves exactly — the plumed helm, both pauldrons, the sword and the shield, 0.83 px of hop at a fully zoomed-in close-up; each attachment now holds one rigid palette frame composed in the rig's own space, the world position added back camera-relative in the vertex stage, so nothing on the path is ever a big-plus-small sum — the property the reference keeps by injecting its view matrix once, at the root of the attachment tree - a rider composes through the rig's own frame, not the unit's: `joints_root` re-points at the saddle's seat anchor the moment a character mounts, so reading the host entity's transform would have placed a mounted rider's helm and weapon by the gap between its feet and its saddle — pinned by a test whose seat is offset far enough that the wrong frame misses by 6 yards - the water-walk surface is GROUND, not a post-step clamp: stepping onto water with Levitate up froze the last land velocity in — the mover classified every over-water frame airborne (liquid is queried, never swept) while the clamp reported grounded, so the body ran on at full speed through every key release; the reference has no water-walking code path at all — the flag just ORs the liquid layers into the same swept query that finds terrain — so the surface now feeds the same grounded classification the colliders do, and the clamp stays as the resolve half - `WOW_JITTER`, a motion-jitter meter: the camera, the unit root and the pose sampled every frame as first AND second differences — Δ² tells a slow idle from per-frame noise at two orders' distance — with every reading also in pixels at the subject's own distance, because the same millimetre is 0.03 px across a courtyard and 0.8 px pressed against the camera Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
de004383ce |
gear rides the rig, water walking answers the keys, and a jitter meter
- an attached model's frame rides its wearer's rig: composed as bone-offset-plus-world-root every frame, a helm at Elwynn's ~9500-yard coordinates lands on a 0.98 mm f32 grid (exactly 2^-10 yd) and snaps whole steps against a body that moves exactly — the plumed helm, both pauldrons, the sword and the shield, 0.83 px of hop at a fully zoomed-in close-up; each attachment now holds one rigid palette frame composed in the rig's own space, the world position added back camera-relative in the vertex stage, so nothing on the path is ever a big-plus-small sum — the property the reference keeps by injecting its view matrix once, at the root of the attachment tree - a rider composes through the rig's own frame, not the unit's: `joints_root` re-points at the saddle's seat anchor the moment a character mounts, so reading the host entity's transform would have placed a mounted rider's helm and weapon by the gap between its feet and its saddle — pinned by a test whose seat is offset far enough that the wrong frame misses by 6 yards - the water-walk surface is GROUND, not a post-step clamp: stepping onto water with Levitate up froze the last land velocity in — the mover classified every over-water frame airborne (liquid is queried, never swept) while the clamp reported grounded, so the body ran on at full speed through every key release; the reference has no water-walking code path at all — the flag just ORs the liquid layers into the same swept query that finds terrain — so the surface now feeds the same grounded classification the colliders do, and the clamp stays as the resolve half - `WOW_JITTER`, a motion-jitter meter: the camera, the unit root and the pose sampled every frame as first AND second differences — Δ² tells a slow idle from per-frame noise at two orders' distance — with every reading also in pixels at the subject's own distance, because the same millimetre is 0.03 px across a courtyard and 0.8 px pressed against the camera Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
10874da37f |
clicks find their target, the booth eases off, and the map's lines go
- the world camera's pick regression: its off-screen render target carried `scale_factor: 1.0`, so on a Retina display the camera reported physical pixels as logical and a centred cursor cast its pick ray into the upper-left quadrant — unit and GameObject picks, the occlusion ray, chat bubbles and `world_to_viewport` all broke at once; the target now carries the window's real scale factor, re-stamped when dragging between displays changes it mid-session — and the perf pill's overlap dodge had the same disease in miniature (`GetBottom()` answers in WoW UI units, the pill lays out in window px), so it now answers a fraction of the screen and works at any window height - `boothHalfRate` defaults back to half-rate: a body pane's off-screen booth pass rendered every frame reads +7.6 ms of GPU at 4K (~1.6 ms at 1600×900), on exactly the weak GPUs that felt the last snapshot — the doll's item effects keep full speed, since they key on the pacing regime rather than the camera's active bit, so only the 30 fps animation cadence returns, and full-rate stays one `SetCVar` away - a spell cast by a GameObject arrives with caster guid 0 — vmangos writes the caster slot from a `Unit*` its GameObject constructor never sets — and the whole visual body was dropped at the guid lookup; the decode now reads an empty caster slot as the packet's first guid, which with no cast item IS the caster, so the Lightwell's click plays its impact kit (sound 3155 and the head flash) instead of only the aura glow that hid the miss, and the object stops being mislabelled a cast item - the world map's black hairlines: a `SetTexCoord` crop is not a texture, and a POI icon magnified to 2.08 px per texel sampled half a texel past its crop into the neighbouring atlas cell — an opaque black row bleeding over a cell that is fully transparent (the empty cell is the reference's own zone-level substitution); `UiQuad::uv_clamp` now insets the sampling window half a texel per axis, so a crop renders as if its sub-rect were its own clamped texture, and `WOW_UI_PICK=x,y` names every quad under a pixel — it found this one in a single run Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
027a2a14b4 |
clicks find their target, the booth eases off, and the map's lines go
- the world camera's pick regression: its off-screen render target carried `scale_factor: 1.0`, so on a Retina display the camera reported physical pixels as logical and a centred cursor cast its pick ray into the upper-left quadrant — unit and GameObject picks, the occlusion ray, chat bubbles and `world_to_viewport` all broke at once; the target now carries the window's real scale factor, re-stamped when dragging between displays changes it mid-session — and the perf pill's overlap dodge had the same disease in miniature (`GetBottom()` answers in WoW UI units, the pill lays out in window px), so it now answers a fraction of the screen and works at any window height - `boothHalfRate` defaults back to half-rate: a body pane's off-screen booth pass rendered every frame reads +7.6 ms of GPU at 4K (~1.6 ms at 1600×900), on exactly the weak GPUs that felt the last snapshot — the doll's item effects keep full speed, since they key on the pacing regime rather than the camera's active bit, so only the 30 fps animation cadence returns, and full-rate stays one `SetCVar` away - a spell cast by a GameObject arrives with caster guid 0 — vmangos writes the caster slot from a `Unit*` its GameObject constructor never sets — and the whole visual body was dropped at the guid lookup; the decode now reads an empty caster slot as the packet's first guid, which with no cast item IS the caster, so the Lightwell's click plays its impact kit (sound 3155 and the head flash) instead of only the aura glow that hid the miss, and the object stops being mislabelled a cast item - the world map's black hairlines: a `SetTexCoord` crop is not a texture, and a POI icon magnified to 2.08 px per texel sampled half a texel past its crop into the neighbouring atlas cell — an opaque black row bleeding over a cell that is fully transparent (the empty cell is the reference's own zone-level substitution); `UiQuad::uv_clamp` now insets the sampling window half a texel per axis, so a crop renders as if its sub-rect were its own clamped texture, and `WOW_UI_PICK=x,y` names every quad under a pixel — it found this one in a single run Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
db86a9c7ad |
the zone counters line up, and the ballista shine holds still
- the world-state readout — the top-centre counters a battleground or Silithus keeps up — takes the reference's real geometry: every icon those rows name is a sprite authored into the upper-left corner of a power-of-two canvas (`AllianceTower` is 16×16 of ink at (3,2) in a 32×32 file), nothing anywhere crops it, and the reference compensates geometrically — a 42×42 slot hung 6 units off the row's left edge with the label seated 10 above its centreline, taken as one system; our snug 20×20 box stripped exactly that compensation, so the art drew at half size floating away from its own `0/200` label — and an empty icon column now reserves its rect instead of sliding the text left, which straightens the readout's left edge - the dynamic icon is a second slot, not a swap: `Icon` and `DynamicIcon` feed two different regions and shipped content never mixes them, so the flag is a 32×32 button off the row's right edge with an ADD-blend flash overlay pulsing 0.5 s in / 0.5 s out, lit only at `uiState == 2` — the flag-taken value; before, any non-zero state replaced the static art, which fires on the ordinary state 1 and hid a faction shield that should never have moved, and the pulse's alpha ramp is now pinned by a test, not just its art - the dev cost pill yields the band: the readout is the game, the pill is scaffolding, and a stock 1.12 UI has no free corner to move house to — so it steps below whatever the readout draws, reading `WorldStateAlwaysUpFrame:GetBottom()` on its own 4 Hz cadence and only while it is drawing, rather than mirroring the frame's row pitch in Rust; the probe's cost is stated at the site (an edge read settles the layout — up to one graph solve, ~47 µs, four times a second) - the Hearthglen ballista's bolt heads and shields stop flickering: a shine layer is a second batch over its base's own triangles, and ours split the pair across lanes — the base rode the retained lane's f64 CPU bake while the env-mapped, additive, no-depth-write shine stayed on the entity path's f32 GPU rotate, and a few ULPs between coplanar surfaces turns the depth test into a per-pixel coin flip re-rolled by every camera move; a batch now names the M2 skin section it draws, neither member of a shared section diverts into a consolidator (depths equal by construction), and a corpus census bounds the cost — 1,080 of 9,691 models draw a section more than once, 264 such sections across 221 `World\` doodads — with toggling pixels at the pin dropping 0.26% to 0.14%, matching the consolidators-off arm bit-for-bit Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
3697e85525 |
the zone counters line up, and the ballista shine holds still
- the world-state readout — the top-centre counters a battleground or Silithus keeps up — takes the reference's real geometry: every icon those rows name is a sprite authored into the upper-left corner of a power-of-two canvas (`AllianceTower` is 16×16 of ink at (3,2) in a 32×32 file), nothing anywhere crops it, and the reference compensates geometrically — a 42×42 slot hung 6 units off the row's left edge with the label seated 10 above its centreline, taken as one system; our snug 20×20 box stripped exactly that compensation, so the art drew at half size floating away from its own `0/200` label — and an empty icon column now reserves its rect instead of sliding the text left, which straightens the readout's left edge - the dynamic icon is a second slot, not a swap: `Icon` and `DynamicIcon` feed two different regions and shipped content never mixes them, so the flag is a 32×32 button off the row's right edge with an ADD-blend flash overlay pulsing 0.5 s in / 0.5 s out, lit only at `uiState == 2` — the flag-taken value; before, any non-zero state replaced the static art, which fires on the ordinary state 1 and hid a faction shield that should never have moved, and the pulse's alpha ramp is now pinned by a test, not just its art - the dev cost pill yields the band: the readout is the game, the pill is scaffolding, and a stock 1.12 UI has no free corner to move house to — so it steps below whatever the readout draws, reading `WorldStateAlwaysUpFrame:GetBottom()` on its own 4 Hz cadence and only while it is drawing, rather than mirroring the frame's row pitch in Rust; the probe's cost is stated at the site (an edge read settles the layout — up to one graph solve, ~47 µs, four times a second) - the Hearthglen ballista's bolt heads and shields stop flickering: a shine layer is a second batch over its base's own triangles, and ours split the pair across lanes — the base rode the retained lane's f64 CPU bake while the env-mapped, additive, no-depth-write shine stayed on the entity path's f32 GPU rotate, and a few ULPs between coplanar surfaces turns the depth test into a per-pixel coin flip re-rolled by every camera move; a batch now names the M2 skin section it draws, neither member of a shared section diverts into a consolidator (depths equal by construction), and a corpus census bounds the cost — 1,080 of 9,691 models draw a section more than once, 264 such sections across 221 `World\` doodads — with toggling pixels at the pin dropping 0.26% to 0.14%, matching the consolidators-off arm bit-for-bit Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
462602c44b |
the world becomes the UI's backdrop, and recipe rows go white on hover
- every translucent UI pixel over the 3D world composited in the wrong space: the world lane and the UI lane each blend in gamma bytes the way the reference's fixed-function device does, but the one blend that mixes them — the UI camera's finished image onto the sRGB swapchain — ran in linear, so a chat tab whose body is black at alpha 102/255 left the scene at 77.5% of its brightness instead of 60%, and the dock's hover glow (an ADD with no plate under it) read as a lozenge floating on grass; the world camera now renders to an off-screen image drawn as the first quad of the UI pass, so every UI blend over the world is the same blend as every UI blend over UI — after, the selected tab plate lands at 0.593–0.600 of the bare scene against 0.60 predicted, and bare-world pixels move at most 1 LSB - the backdrop image is un-encoded `Rgba16Float`, because the UI arc composites in gamma and takes its one decode at the end — pre-encoding would land a second encode in that chain, and quantizing un-encoded values to 8 bits is the banding collapse measured long ago; and hiding the UI keeps the world: the toggle used to retire every batch in the pass, which would now be a black screen — hidden means the two UI lanes draw nothing while the backdrop, which is the world, still draws, with the no-world glue screens pinned on the old behaviour - a button's highlighted label is its own font instance: the client swaps which of three embedded instances the label reads — it never merges colour across states — so the `highlight_color.or(normal_color)` fallback is gone, and `LockHighlight()` now enters the label, not just the highlight texture (the reference blanks a recipe row's highlight texture to "" and then locks the row it selected — with nothing left to pin, the lock's only possible effect is the label, and that is the white text on a selected recipe) - tradeskill, craft and class-trainer rows read white on hover and on select: all three windows carried the row name as a child FontString no per-state font can reach, behind a "no engine method" note that was true when written and stale ever since — the name is now the button's own `<ButtonText>` under the base template's `<NormalFont>`/`<HighlightFont>`/`<DisabledFont>` trio, and the windows call `SetTextColor`/`LockHighlight`/`UnlockHighlight` where the reference calls them Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
1da3fb044f |
the world becomes the UI's backdrop, and recipe rows go white on hover
- every translucent UI pixel over the 3D world composited in the wrong space: the world lane and the UI lane each blend in gamma bytes the way the reference's fixed-function device does, but the one blend that mixes them — the UI camera's finished image onto the sRGB swapchain — ran in linear, so a chat tab whose body is black at alpha 102/255 left the scene at 77.5% of its brightness instead of 60%, and the dock's hover glow (an ADD with no plate under it) read as a lozenge floating on grass; the world camera now renders to an off-screen image drawn as the first quad of the UI pass, so every UI blend over the world is the same blend as every UI blend over UI — after, the selected tab plate lands at 0.593–0.600 of the bare scene against 0.60 predicted, and bare-world pixels move at most 1 LSB - the backdrop image is un-encoded `Rgba16Float`, because the UI arc composites in gamma and takes its one decode at the end — pre-encoding would land a second encode in that chain, and quantizing un-encoded values to 8 bits is the banding collapse measured long ago; and hiding the UI keeps the world: the toggle used to retire every batch in the pass, which would now be a black screen — hidden means the two UI lanes draw nothing while the backdrop, which is the world, still draws, with the no-world glue screens pinned on the old behaviour - a button's highlighted label is its own font instance: the client swaps which of three embedded instances the label reads — it never merges colour across states — so the `highlight_color.or(normal_color)` fallback is gone, and `LockHighlight()` now enters the label, not just the highlight texture (the reference blanks a recipe row's highlight texture to "" and then locks the row it selected — with nothing left to pin, the lock's only possible effect is the label, and that is the white text on a selected recipe) - tradeskill, craft and class-trainer rows read white on hover and on select: all three windows carried the row name as a child FontString no per-state font can reach, behind a "no engine method" note that was true when written and stale ever since — the name is now the button's own `<ButtonText>` under the base template's `<NormalFont>`/`<HighlightFont>`/`<DisabledFont>` trio, and the windows call `SetTextColor`/`LockHighlight`/`UnlockHighlight` where the reference calls them Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
73826ca3d7 |
casting a hunter shot starts Auto Shot, and the ping wears its real art
- Serpent Sting starts Auto Shot in play: the chain built earlier the same day never fired because the in-flight record was armed only for the cast classes it refuses on, and every hunter shot is a ranged attack — the reference records every commit and discriminates at the gate; two tests now run the real ladder and reproduce the shipped symptom - the minimap ping is MinimapPing.mdx, measured: three additive quads — a 12 px spinner on the model's global clock, a static core, and a ring expanding 3→32 px on an 833 ms loop — the interim art was ~3× too big and missing the ring the eye actually reads - a mouse release goes to the frame that took the press and nothing else — the reference's up handler reads the capture alone and never the hover frame, so a press over open space delivers no release to whatever the cursor wandered onto (corrects the morning's fallback) - `WOW_MOVE_TRACE_TAGS=use` traces a right-click end to end (the cursor decision, the use packet, the spell-go answer), and the first headless hover capture parks the cursor on a chat tab so the reveal can be measured against the bare scene Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
d0b06578e9 |
casting a hunter shot starts Auto Shot, and the ping wears its real art
- Serpent Sting starts Auto Shot in play: the chain built earlier the same day never fired because the in-flight record was armed only for the cast classes it refuses on, and every hunter shot is a ranged attack — the reference records every commit and discriminates at the gate; two tests now run the real ladder and reproduce the shipped symptom - the minimap ping is MinimapPing.mdx, measured: three additive quads — a 12 px spinner on the model's global clock, a static core, and a ring expanding 3→32 px on an 833 ms loop — the interim art was ~3× too big and missing the ring the eye actually reads - a mouse release goes to the frame that took the press and nothing else — the reference's up handler reads the capture alone and never the hover frame, so a press over open space delivers no release to whatever the cursor wandered onto (corrects the morning's fallback) - `WOW_MOVE_TRACE_TAGS=use` traces a right-click end to end (the cursor decision, the use packet, the spell-go answer), and the first headless hover capture parks the cursor on a chat tab so the reveal can be measured against the bare scene Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
f8421c1545 |
the colour wheel draws, chat windows move, and the minimap ping returns
- the colour picker can pick a colour: the hue disc and the value strip are engine-generated pixels (no BLP in the chain is a wheel), reproduced from the reference's own lattice — a hard-cut circle at a literal V = 1.0, the brightness marker moving over a disc that never dims - chat windows move and resize once unlocked (Lock/Unlock Window on the tab menu; the reference's own 296×75 to 608×400 bounds), the border textures doubling as the grips, and the placement is remembered per character in benilla-config/layout; both windows ship locked, as 1.12's reset leaves them - the minimap ping is back and pinned: one world point the engine draws, the click converted in the right unit (the old path was ~27% off at 1080p), and no 10-yard auto-clear — that was the gossip marker's rule, and walking to your own ping was deleting it - the Lightwell can be clicked: a billboard card is a world root with no parent hop, so the hit resolved to nothing and the whole shaft published a null mouseover; casting a hunter shot chains Auto Shot through `Spell.dbc`'s modalNextSpell column (the mechanism nobody had read — the next snapshot carries the seam that makes it fire in play); tradeskill list rows stop tooltipping (that hover was ours, not Blizzard's), and OnMouseUp goes to the frame that took the press Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |