- 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>
- 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>
- 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>
- party members appear on the world map at their position and hovering names them — the party wire has carried each member's zone and coordinates since the group arc; the blip and the minimap dot read one shared position so they can never disagree, and the member's zone picks which continent the position belongs to
- the player's own frame wears the leader crown and the master-looter icon, with the reference's own asymmetry (the crown asks IsPartyLeader, the member frames compare a leader index)
- a party member outside your local area gets the generic race/sex portrait instead of an empty circle — their race and sex ride the name query, and nothing had asked for a member we never see; the roster now warms that cache, which also fills the raid grid's class column
- right-clicking a member who is nowhere near grays Trade, Inspect, Duel and Follow: the reference's bindings answer nil for a unit the object manager does not hold (carved this session), where ours defaulted "absent = in range" for exactly the farthest member; and the group-invite popup's background is measured faithful — the plate draws at the BLP's own 60% alpha
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the mix is bounded the way the reference's is: FMOD gave 1.12 exactly twelve software channels and nothing else limits a priest buffing five people — ported as a 12-voice ceiling (a probe capture read 42 live voices at +13 dBFS, the limiter pumping 13 dB to hold it), plus same-kit copies started in one frame capped at two, since five sample-aligned Fortitudes are one sound +14 dB; `$WOW_SOUND_PROBE` records the mix before and after the limiter with a timeline, F9 stamps the moment
- the raid tab draws its window art again — its four corner textures were written with single backslashes, which Lua drops silently, and a sweep now reads every archive path a shipped Lua chunk names; a drag whose release never arrives (pointer left the window, a second press) ends instead of gluing the frame to the cursor for the rest of the session, and `WOW_PROBE_DRAG` drives any UI drag headlessly in a live client
- the item tooltip fits its set bonuses again: an emptied line kept its last measured height forever (a pooled cell with no way to say "empty"), and the two blank rows above the set block are the reference's own literal (a space and a newline) — a whole row each, not the empty string
- an equipped BoE or BoP piece reads Soulbound: the bind line reads the item's own flags through the client's bound predicate instead of the template's bonding, one predicate shared with the enchant cursor's bind confirm
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the auction house end to end: right-clicking an auctioneer opens Browse/Bids/Auctions on the server's reply — search, the category tree from your own DBCs, the reference's 50-a-page pager, multi-key sorting (directions corrected at the bytes), bid/buyout, the sell slot with deposit and duration, cancel with its fee popup; prices sit on the reference's own money-frame kit in lined-up columns, the twenty auction messages split refusals-red / outcomes-to-chat, and a won or sold auction reads as a proper mail receipt — the window's Lua re-worded in our own terms after the overlap ratchet caught the first cut leaning on the reference's text
- the PvP honor system whole: the Honor tab and the inspect page over a real wire model, with current rank and highest-ever rank correctly two different fields
- a day of reported fixes: WASD survives a /logout re-entry, addon settings save on a window close and Cmd+Q (exactly once — a mac close could fire the tail twice), clams open again, random-enchant items name themselves on every surface, the loot window's rows hold their seats with legible counts, idle players stop sinking through building floors, the shooter re-pulls between Auto Shots, portraits loosen ~19% to the client's own aspect-1.0 matrix, and big creatures thump the camera off the CameraShakes table
- character select clicks like 1.12 — captions whiten on hover, buttons fire on release, Humans face straight ahead off the stage bone's real yaw, the facing is per-character, and hunter/warlock pets stand beside you at their family-ramp size with their own emitters (the imp's flames), the Voidwalker's sequence-hidden shackles culled
- the smaller player-facing set: nameplate on/off rows in Options with the CanAttack category gate (emissaries stop plating), the bonus bar slides up with igBonusBarOpen, the camera's framing height glides on a shapeshift, the open letter evicts the centre seat, the far-band fog hull stops printing a pale horizon stripe at low view distance, the guide arrow is gold with per-source rim art, error text fades through its shadow too, and /convertraid converts the party
- README: the auction house and PvP honor move out of "not built yet"
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the four extra action bars become per-character options, off by default, on a new Action Bars options page — the toggles ride the server's own byte (`CMSG_SET_ACTIONBAR_TOGGLES` into `PLAYER_FIELD_BYTES`), so a fresh character's zero is the default for free; turning the bottom-left bar off gives the stance bar its previously unbuilt unraised look, end-caps and 64×64 rings
- bag windows stop drawing straight through a raised bottom bar: the bottom band has ONE owner — the manage pass — the bag stack joins it through a listener seam, and a guard test walks all eight raisable-bar combinations across 24 bar/tenant pairs and refuses overlap
- the item-push card takes the reference's real geometry, closing the gap 0887 measured
- resizable addon windows stop at their bounds instead of pinning and walking across the screen: four per-frame f32s with 0.0 the disable sentinel, the clamp on the interactive drag only with the residual rebated out of the drag delta, `<ResizeBounds>` in XML honoured — and `SetFontString`'s three raises land exactly as the bytes have them
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Quiver works end to end (the reported nil-field error): 1.12's widget method tables are flat, so the 19 Region methods are ONE function per name — a frame's `GetHeight` IS the texture's — where we had two implementations behind two disjoint registries; `Button:SetFontString` and the Set/GetMin/MaxResize quad land with it, and the 219-addon survey moves loads-without-error 150 → 151 with every other addon byte-identical
- a teleport stops dropping you into a bare city: the reveal gate now waits on geometry that can actually draw (14 regions had sat undrawn for 630 ms with the cover already down), a relocating snap ≥100 yd raises the cover, and the pipeline warm pass runs once per process — a far same-map teleport's cover drops 3.8 s → 0.8 s
- the empty-world flash on a fully-resident teleport dies with it: the camera's world pose publishes before anything in Update reads it, so the visibility verdict stops being computed up to 644 yd from the eye — the lag reads 0 yd on every snap frame of every arm
- the camera follow becomes the engine's own curve — an edge-armed cosine smoothstep clamped to 0.1–2 s behind a 7-state input classifier, the enum 0/1/2 with Smart staying the default — and overlapping chat bubbles stack as whole cards, one frame level per bubble, nearest to the camera on top
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the eight heaviest UI feeds — spellbook, party, character, bags, talents, units, pet, player — rebuild only when an input moved instead of every frame: 216 → 12 µs a frame parked
- the character window's cost settles once it closes: enchant countdowns feed by the second instead of firing an inventory event into all 20 slots every frame, the paper-doll booth parks with its camera, and a window hidden under the cursor fires OnLeave so its tooltip goes with it — the reference's hover-hide law
- the walk stops paying for finished work: the loading-screen tally's per-placement walk latches off once the world is ready, the settled placement spawner is one integer compare, and billboards stop dirtying every card's transform
- never-rendering hierarchy nodes — rig anchors, joints, doodad hosts — keep the hide chain but leave the per-camera visibility sweep: 25,198 → 18,026 swept entities at Goldshire
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- a text write names its own label, so the per-frame measure sweep drains a short ledger instead of hashing every font string twice — ~0.3 ms a frame at the Stormwind gates, gone
- the idle interface tick stops re-writing settled state: buff durations and the weapon-enchant frame write only on change, and the fade and unit-popup drivers park until woken
- the interface extract skips a hidden region before cloning its row, not after
- WOW_UPLOAD_BUDGET=<MB> brackets the arrival burst's upload pacing — a lever for measuring world entry, not a fix yet
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- VSync is a player setting on the Graphics page now — 1.12's own gxVSync, persisted like every other CVar — instead of a dev-HUD checkbox
- the perf HUD collapses to one surface that says everything once, at a deliberate, governed width; the badge stops crying wolf
- the idle chat dock stops repainting itself every frame — the fade applier gets the gate the reference carries twice over, and hovering still reveals the hidden tabs
- the tick can name who spent it: per-handler self/total attribution at the one seam where every handler fires
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the pet bar's autocast shine cost +4.25 ms a frame for one button: its 92 script-side SetPoints forced two whole-roster anchor solves every frame — the shine now draws from a native lane, re-measured at +0.03 ms with what is drawn bit-faithful to before
- an NPC that spawned under its own floor — a cellar wolf, a pet at login — now measures its ground clamp from the server's seat instead of its own last answer, and climbs out
- a running cast cost ~4 ms a frame in layout gate walks; a mutated frame now takes one walk, not three, and the settled interface is pinned at zero
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- a teleport between cities on one continent could release you before the destination had streamed in and drop you under the map — the residency publish now waits for the snap and names the tile its facts are about, so the loading screen provably holds until the ground is real
- nameplates stop jittering: plates of units you cannot see no longer shove the visible ones around, and the snap rides the correct pixel grid
- unit-name text takes its first fix — a string fits the width its own measure reported, and a re-bake reaches the screen
- books and plaques render through a real SimpleHTML widget inside a real ScrollFrame — strict parse, per-element fonts, block layout, and a scroll range measured from the whole subtree
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the social window's third tab is live — the roster in both its views, the member card with its promote/demote/remove verbs, the rank editor's thirteen permissions, the guild information board, and the invite, leave, kick and note dialogs behind them
- setting your hearthstone at an innkeeper now asks before it takes and says so afterwards, and the innkeeper's gossip lines get their own icons back
- unavailable talents grey out, and every greyed icon in the client now goes through the same luminance fold the original used
- the buff tooltip's remaining-time line reads gold with the client's own hour/minute ladder, the macro editor takes a shift-click to paste a spell, trainer rows repaint after a purchase, and a long book page stops flickering its ellipsis
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- an addon's own texture files resolve from its folder, TGA included, and SetTexture answers 1 or nil the way the client does — custom icons and skins draw
- runtime SetParent re-levels a frame by the client's strata law, and the raise survives hide-and-show round-trips — AtlasLoot layers right
- an addon that unregisters an event mid-fire no longer robs the next addon of the same event — Bagnon's per-character database fills again
- the Model widget's clock truncates milliseconds like the client's, and the no-text cast-bar law is confirmed at the bytes and narrowed to the cast bar alone
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- dialogs carry the reference's toplevel bit, so the stack-split window opens above Bagnon instead of behind it
- the failure line fills its blank — "Requires Blacksmith Hammer", not "Requires" — and Opening casts stop printing a label the spell itself marks "no text"
- the pet bar's Attack/Follow/Stay tooltips name their keybinding, and typed text reaches the focused frame through the client's own delivery walk
- AtlasLoot parses again: our Lua keeps 5.0's compatibility semicolon
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- a real skill-up prints its line; the lines the client keeps silent — class specs, racials, mounts — stay silent, off the game's own flag
- the stack-split dialog draws whole: its plate fills the window
- the four bag-bar buttons speak the reference's names all the way down, so Bagnon's overrides catch them and the backpack button lights while its window is open
- regions anchor at creation — the client's implicit-anchor law replaces a pile of draw-time fallbacks
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- an addon error shows the red script-error dialog the reference shows, and a runaway load loop can no longer freeze world entry
- food and drink show stack counts from the first login, and a paladin's aura bar lights the aura that is actually on
- logging out no longer erases the character from saved-bag addons: the player's absence is no data
- MPQ patches are discovered the way the client discovers them, and a slow arrival holds in place instead of falling through the world
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- SetBinding accepts the mouse wheel — the refusal was ours, not the client's — so wheel-bound action buttons press and release like the real thing
- one addon load law: a single arbiter for "can this addon load, and why not", with the out-of-date version gate live
- one AddOns screen — the character-select list, wearing the authored reference layout: roster dropdown, per-character tri-state checkboxes, force-load; the ESC-menu panel is retired, since 1.12's own menu has no AddOns row
- the glyph atlas follows the window scale, so maximised text stops washing out and a title stops measuring wider than it draws; an unpositioned frame positions nothing, instead of landing at the screen origin
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- GetStringWidth answers the moment the text is set — the client's width law is a per-glyph table, no shaping pass — so Bagnon's character dropdown stops collapsing to 40 pixels
- a chat channel keeps its number when another channel leaves: Trade stays /2 through a teleport
- the login splash, the zone music and the minimap label wait for the world under the player instead of announcing whatever tile happened to be loaded
- ending a session empties the chat window and the input box's history
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- `--surface` re-runs the comparison against the captured in-world global table on demand, and `--surface-dump` writes our raw side for any tool to join — a one-shot measurement stops drifting
- CreateFrame with an unresolvable template raises exactly as the client does, instead of handing back a bare frame; `inherits=` is one name, matched case-insensitively
- CreateFontString and CreateTexture honour their third argument — 49 corpus call sites were passing an inherit into the void
- the addon-message inbound byte map is corrected (a test had agreed with the wrong constants), and the group-loot roll template publishes under the reference's own name
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the one shared region table splits into the client's own maps: a Texture no longer answers SetText, a FontString no longer answers SetTexture, and feature-detecting addons see the true surface
- CreateTitleRegion lands whole — object and drag — so an options window that is its own drag handle actually moves
- font-object names resolve whatever their case, and the CursorUpdate/CursorOnUpdate pair arrives for the container-item templates
- GetStringHeight is pruned (1.12 has no such method) and SetPortraitToTexture moves to the global it really is
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- every addon VM runs under an instruction bound, so a non-terminating loop becomes a report — and the bound promptly caught a landed fix that had been left switched off
- an unrecognised unit token raises the client's own "Unknown unit name" error instead of answering nil
- GetBindLocation answers from a real bind point, and RequestTimePlayed round-trips with TIME_PLAYED_MSG — both halves or neither
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- GetObjectType and IsObjectType land from the binary's own carve, with the client's exact inheritance answers
- the survey seats money and a quest log — sixteen addons call GetMoney, five walk the quest log, and none of those paths had ever run
- `date("*t")` returns its table form; the missing shape was an infinite loop for any addon walking days backwards
- unit tokens fold case like the client's resolver, and a FontString template carries the font object it inherits through the whole chain
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- every ranked list now states what it dropped and `--deep` reads the whole tail — a silent top-16 over 1,946 rows had already produced one wrong "nothing left" conclusion
- the backpack and equipped gear take their seats beside the spellbook, and a rankless spell's rank comes back "" rather than nil
- a FontString answers the full Region method map as one set — a text region's GetParent works — and RaidWarningFrame and PanelTemplates_Tab_OnClick arrive for the addons that name them
- SetRaidTargetIconTexture lands: the half of a raid mark an addon draws with
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- GetInventorySlotInfo folds case the way the client does, and gains the twelve bag-slot rows the shipped data really carries
- ChatTypeGroup exists for addons that register their own chat types at file scope — one missing table was taking five addons down
- GetChannelList answers in join order, shaped by the addons that consume it, and the harness's `--why` can now open any demand count
- the survey seats a spellbook, and the shapeshift bar's shelf art exists hidden, both exposing paths an empty fixture could never reach
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the main bar's page arrows page for real, with the reference's own rule that a page a shown multibar displays is not also reachable by paging
- `<Include file="X.lua">` executes the file the way the client does — dispatch on the extension — so an addon pulling its libraries through XML stops losing them
- UIParentLoadAddOn lands, the on-demand loader behind every "open the panel" path
- nine constants take the reference's names back (NUM_GROUP_LOOT_FRAMES and friends — an addon reads the real name, not our prefix), and UnitCreatureType answers through the client's own three-stage resolver
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the justify verbs had been written three times and drifted three ways; one implementation now serves the region, font-object and message-frame tables, and a cleared axis paints centre, as the client's draw path really does
- MessageFrame and ScrollingMessageFrame gain the ten-verb font block they were missing entirely, so font calls on message frames stop raising
- EnableKeyboard and IsKeyboardEnabled land as real Frame methods — eight addons were dying on their absence
- the harness's METHODS ranking states its own limits instead of reading as a build queue
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the corpus harness now seats a buff, a target and a ticking cooldown instead of an empty world, so "nothing to draw" and "failed to draw" stop sharing a row — and the richer seat immediately exposed two real gaps
- an addon button inheriting our action-button template now works even when it replaces the template's OnLoad: the handlers resolve their regions by name, the way the reference does on every access
- more of the reference's hidden-by-default frames exist by name — ReputationWatchBar, MiniMapBattlefieldFrame, MiniMapMeetingStoneFrame — for the addons that reposition them
- StartSizing lands beside its stop verb, and the sourced bag-anchor code runs against windows we actually build
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Lua 5.0's generic-for and nested long strings are restored in a forked VM — 60 corpus addons stopped dying on one deleted opcode
- a day of demand-driven carving takes the 218-addon corpus from 24 addons surviving a session start to 114, with 144 loading without a single error
- Bagnon draws a real bag and answers real gestures — hover tooltip, pickup, use, drag — because our frames wear the reference's names, and the reference's own ContainerFrame.lua runs off the player's install instead of being transcribed
- the physics broad phase leaves: nothing in the client reads a contact, and it was measured at up to 41% of main-thread samples in real sessions
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- benilla loads real 1.12 addons from Interface/AddOns — TOC, XML and Lua through one loader, with per-addon saved variables, Bindings.xml and the lifecycle events addons expect
- both AddOns screens are in: the character-select list with per-addon enable state, and the ESC menu's in-game list
- the API surface is measured, not guessed — a corpus harness runs hundreds of real 1.12 addons and ranks exactly which globals, templates and verbs they demand
- the Lua dialect is the client's own, read off the binary — 5.0 semantics with the 1.12 additions, and UI source files are bytes, not UTF-8
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- minimap zoom and the camera's distance and pitch persist across sessions
- the trainer's point-filter is a saved variable now and survives a relog, resetting per packet like the reference
- the options window gains its Combat page, over rows that can write the UI's own saved globals
- the step-up is a rise, not a jump forward — and the descent cone's cap belongs to the body, on every leg
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the step-up and step-down budgets are the client's own verified numbers, and the step regime is chosen by the blocking edge
- walking off a kerb follows the surface down instead of diving past the edge; steep ground supports you only while you are descending onto it
- a ride on a moving platform survives the ground snap, and a vertical wall no longer depends on a float's sign
- trainer and craft rows sort with the real client's own comparators, one per window — Beast Training lists a skill's ranks in ascending order again
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the Great Forge's lava stays drawn from every angle, and the chasm catwalk reads as a connected grate again
- music decoding and shader-compile bursts stop crowding the audio's lane, and the output buffer follows the device's real deadline
- the audio path grows its instruments: a mix tap to WAV, a starvation meter, a hardware overload listener
- trainer detail icons carry the reference's own tooltip
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- clicking a book in the world opens it and turns its pages: letters and world books share one reader
- the cursor's object rules are the client's own 31-row strategy table now, so decorative objects stop pretending to be usable
- trainer and tradeskill windows draw each row's icon by the reference's own law, and the trainer's filter dropdown toggles again
- water color follows the zone's light blend, so lakes stop snapping between area tints
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the whole loop plays: the line arcs rod tip to bobber, the bite splashes with its own sound, and clicking the bobber reels in
- the verdicts read like 1.12: yellow "your fish got away" lines, the reel-in sound, the fishing loot window
- "You feel rested." prints on the transition, rest states come from the client's own Exhaustion table, and level 60 trades the XP strip for the max-level rail
- the Skills pane lists what the real client lists: the hidden rows, the sort, gray numberless single-rank lines
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the spellbook's pet tab lists what the pet knows, with autocast toggled right on the page
- pet ability cooldowns sweep on the pet bar, and the bar binds to 1.12's Secondary Action Button keys
- the options window scrolls its pages in a real trough with seated arrows, nothing overflows the frame anymore
- Esc un-queues a queued strike, and a hostile unit's frame stops showing buffs the real client hides
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- feign death plays dead for real: the body collapses and stays down, both bars read 0 and DEAD, the nameplate drops, the combat hum goes quiet
- melee and Auto Shot are exclusive now: starting one stops the other, even mid-swing
- another client's addon chatter no longer prints as party chat
- right-click presses look pressed, rage and happiness read on their real scale, and the login boxes blink their caret
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the pet gets its own unit frame beside yours, and an Attack order no longer latches as the standing command
- five rooms that always read bone dry hold their water now, the Deeprun Tram's flooded stretches among them
- macros fire through the client's own chat door, and the macro window fits its tabs and scrolls its icon chooser
- the options window grows a Nameplates page and its first dropdown, and the name-display switches apply live in the world
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- a hunter's or warlock's pet has its action bar now: attack, follow, stay, the pet's own spells with cooldowns and autocast sparkles
- the macro system lands: the macro window, the icon chooser, /cast and /macro, and macros dragged onto the action bar
- hunter shots look right at last: the bow draws and releases on the shot, and the arrow lays a spark trail its whole flight
- the options window re-dresses in 1.12's own art with the classic dialog look, and gets a working search box and clickable steppers
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- one era-style Options window: window chrome, category list, search box and its own ESC rung, with the game menu reshaped to match
- settings are real CVars now: GetCVar/SetCVar reach Lua, and your changes persist as a diff in benilla/config.toml
- all local state lives in one visible benilla/ folder beside your Data/ — nothing hides in platform config dirs
- UI text stays crisp at any scale and survives a mid-session resolution change: glyphs measure in the environment they raster in
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the mount transition re-seats the rider instead of rebuilding them: shield glows, weapon enchants and worn visuals stay lit through mount and dismount
- an enchanted item's tooltip carries its enchant line, coloured per slot, with a temporary enchant's countdown
- a server refusal with nothing to say now says nothing: the raw "Inventory error" debug line is gone, real refusals still print
- the mail icon clears when you close the mailbox, and translucent models classify against the water plane
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- follow a player and the screen names who you're following, the right-click menu grows its Follow row, and your own movement is what cancels it — creatures are refused like the real client
- a locked lockbox click asks the server instead of refusing silently, a quest-starter chest offers its quest before opening, and an item on cooldown hides its green "open" line
- a parried swing plays its clang like the real client keys it
- the README's What works / Not built yet caught up on a week of shipping
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- /target and /assist find units by name like the original, and /follow walks you behind your target
- right click opens clams and lockboxes, and the tooltip promises it
- the freeze thaws clean, poses release instead of sticking, and you drop to neutral standing before it grips
- unit frame art layers over the bars like the original
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- The keyring is built. Your first key makes the keyring button appear by
the bags, opening the window the original keeps its dungeon keys in — the
server had been sending the keys all along; nothing had ever shown them.
- Keys open their doors now. The client used to cast the open as a bare
spell, which the server rightly refuses; it now sends the item-use the
original sends, carrying which key from which slot. The tooltip plays
along: "Locked" turns the soft green when something you carry opens it,
and a key stops inventing a "Use: Opening" line it never had.
- A building can own the sky: a WMO can name its own painted skybox, and
Stratholme's burning city now draws its near-black-to-red dome instead of
the zone's khaki gradient. The exact rule for when it applies settles in
the next snapshot.
- Signpost tooltips follow the cursor again — the tooltip anchor forks per
object class, corner for doors, cursor for signs — and the Blasted Lands
lightning stops striking the same spot for ever: a placed doodad re-rolls
its animation variation every play-window, like the original.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- The UI stopped paying to discover that nothing changed. Layout used to hash
~1,900 frames' worth of inputs every frame just to decide "quiet"; it now
tracks a mutation epoch and answers with one integer compare, and a settled
frame reuses last frame's rendered quads instead of re-rasterizing every
glyph. ~0.9 ms off every idle frame — with a verify mode, forced on across
all 489 UI tests, that re-runs every skipped resolve in full and asserts it
would have produced identical results.
- Across this run of snapshots, the one number everything is graded by: CPU
work per frame at the crowded dungeon spot went from ~29 ms to ~16.5 ms.
- A lighting question got the full treatment and an honest answer. Units
briefly took a different day/night lighting law; it read wrong on screen the
same evening, and a build-by-build hunt a full week back confirmed the
world's look never regressed in the first place — the change is reverted,
nothing about the look changes in this snapshot, and the question stays
parked until the one remaining unknown in the reference client is pinned.
- The character pane's model booth grew a headless eye — a dump of exactly
what it draws, no live session needed — built for that hunt, kept for the
next one.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Particles, ribbon trails, blob shadows, the selection ring, ground decals,
water foam and the weather all push their quads into one shared vertex
stream now — one buffer, batched draws, indices built per frame in draw
order. ~1,100 emitters at the crowded dungeon spot stopped being ~1,100 mesh
assets the engine reallocated every frame, no material asset is ever mutated
for an effect again, and adjacent draws merge like the original's own batches
(its measured shape: 793 quads in 23 draws). Vertices went camera-relative on
the way — the fix for streaks and flakes vanishing in far zones, where the
raw coordinates get big.
- Hovering an item in your bags cost +14 CPU ms for as long as the tooltip sat
open. The tooltip's refresh loop is faithful 1.12 behaviour (the bag button
re-runs its hover every frame, unthrottled, so a late-arriving item fills in
without a re-hover) — but each rebuild dropped the text measuring cache, so
every frame re-shaped every line. One line keeps the cache: +14 → +0.1 ms,
and the paperdoll, inspect and merchant tooltips stop paying the same tax as
spikes.
- "Which room is this creature in" walks one anchor per model instead of every
lit part — ~13,700 part visits a frame became ~1,700 anchor rows. The
frame-time win was honestly flat (the cost had already moved elsewhere); it
lands for the structure, and the old sweep's repair duties became
event-driven with it.
- The perf probe defends its own window now — always-on-top from the first
tick, occlusion counted on the measurement line — after two long overnight
runs were silently destroyed by the display going to sleep.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- The social window: friends, ignore and `/who`, in the reference's own two-level
arrangement with its inner tabs and per-row right-click menus. The lists ride the
real wire — guid-keyed with no names, resolved through the name cache, and capped
at 50 friends / 25 ignores because those are the client's own caps — and the
ignore list does its actual job: an ignored speaker's chat is dropped silently, a
whisper additionally tells the sender, and a duel challenge is auto-declined.
Guild ships as a disabled tab, which is what a guildless character sees.
- The escape menu: ESC's last rung finally opens something. The game menu lands at
the reference's own size and ladder, and leaving works — logout and quit with the
server owning the clock (instant at an inn, refused in combat, or the 20-second
countdown), narrated by the real camp/quit dialogs. While the menu holds the
center nothing else opens, and the bag bar greys out under it.
- Items on the action bar act like items. An equipped trinket was a dead button;
the reference's use law is two stages — not equippable means use, equippable and
already worn means use in place — over its exact search order (equipment first,
then the bags, then the backpack, then the keyring; never the bank). What can go
on the bar is now the reference's own two filters, byte-read: an item with an
on-use spell or one you can equip, and no passive spells — and dropping a passive
there speaks the real client's own line, "You can't put a passive ability in the
action bar."
- A quest-starter item opens its quest instead of "The item was not found." The
question goes to the item's own guid, never through item-use — which the server
refuses for every one of the 215 quest-starter items — and refusing the quest
says what the client says, then closes the window.
- For the toolbox: a pixel pick that reports everything under the cursor all the
way back, a lens that says which render phase a draw landed in, and switches that
separate "discarded" from "lost depth" from "never drawn" — built while cornering
a flickering tent, whose fix ships in the next snapshot.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- The main menu bar's two empty recesses fill. The micro menu — the eight arched
buttons: character, spellbook, talents, quest log, socials, world map, main menu,
help — sits in the dark panel between the page arrows and the bags, transcribed
from the reference's own layout: the character button wears your portrait, a button
holds itself down while its panel is up, and the talent button appears at level 10.
The latency meter fills the one slot the bar art leaves transparent for exactly it,
tinted green/yellow/red on the reference's 300/600 ms thresholds and drawn UNDER
the bar art, seen through its window, the way 1.12 actually does it. The socials
and main-menu buttons find their panels one snapshot later; help still waits.
- The UI explains itself on hover: 1.12 ships its detailed two-line tooltips ON — a
FrameXML default, not the opt-in extra it is often remembered as — so the micro
buttons, your own portrait, the XP bar, the five bag buttons and the ping meter
all answer a hover with the reference's own explanations.
- The PvP flag, end to end: crossed swords on the player, target and party frames,
driven by the two descriptor bits the wire actually carries, and `/pvp` speaks —
the yellow toast plus the system chat line, the OFF sentence being the one that
warns the flag lingers for five minutes. It really does linger: turning it off
waits out the server's timer, which looks like a bug and is the reference.
- Quest markers stopped freezing. The grey `!` over a questgiver above your level
goes gold the moment you ding, an NPC re-entering view is asked afresh instead of
wearing a session-old answer, and the marker drops when the questgiver bit goes
off — the re-ask triggers mirror the reference's own set, plus one named addition
(your own level changing).
- Water and heights: swimming downhill no longer bounces between swim and fall ten
times a second — the surface line is a two-sided constraint, so the swimmer
settles with the river instead of being left behind by it. And collision height
is per-unit now, read from the unit's own model: a gnome used to swim with a
third of a yard of water over her head because five depth lines were quoting a
human's number.
- A round of pixel honesty in text and chat: the newest chat line no longer wears a
wider drop shadow than every line above it (shadows move in whole pixels now),
keeps its descenders, and hover boxes stop painting over the chat body. The chat
input's history browse survives programmatic edits, a failed script chunk warns
instead of vanishing, and recall deepens to 64 lines. Idle animation got honest
too: a model's idle is Stand resolved through its own lookup table — never
file order, which had the duel flag bobbing on its spawn clip — and an armed idle
is culled on the box its animation authors, not the bind pose, so the flag stops
vanishing at most camera angles.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Other players walk the world. A watched player's motion between server updates now runs through
the same grounded movement resolve as your own character — same capsule, same colliders, same
step-up and ground election — so they follow terrain every frame instead of every packet, and
stop at a wall instead of walking into it and being snapped back. Their jumps are swept against
the world too, and a standstill jump steered mid-air reports that steer, the one mid-air press
the reference client broadcasts rather than defers.
- The move relay rebuilt: relayed moves ride a per-unit chain on real time, a due move never jumps
ahead of its unit's queue, and SMSG_COMPRESSED_MOVES — the batched carrier the server sends under
load — is decoded rather than skipped. Our own send path now matches the reference client's:
facing streams while moving, Nagle is off so each packet is one write, and the strafe axis nets so
left and right can never ride the same packet.
- NPC and quest text speaks the whole $-macro grammar, carved from the reference bytes — your name,
class and race, the gendered forms, and the server's live world states — and the same
substitution feeds gossip, quest text, the quest log and unit frames. Greetings are a weighted
draw, rolled per NPC per open, and a quest giver with no quest to give is no longer clickable,
where it used to open a dialog holding nothing but a placeholder greeting.
- Spell tooltips finish the reference's line law: cast time and cooldown behind the real passive
gate, the required tool or form, the reagents block, the chance-to-X line, a multi-bit
equipped-item requirement named properly instead of by raw bits, and a buff's dispel class.
- The UI layout engine got a dense, reusable anchor solver, and a change gate that skips the resolve
entirely on frames where no layout input moved — in practice, almost every idle frame. Pets are
named by their pet number rather than a creature-template entry, so the client asks the query the
server can actually answer. And the asset extractor grew a stray-geometry census for tracking
down geometry that renders where it should not.
This snapshot replaces the six dated `sync` commits that stood here before it, whose subjects said
nothing but the date. If you cloned before now: `git fetch && git reset --hard origin/main`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>