Commit Graph
11 Commits
Author SHA1 Message Date
SamandClaude Fable 5.1 0535fe9097 a body lands with a thud, and twelve lists scroll again
- a dying body lands with a sound: the `$DTH` marker makes three calls in the reference (`0x624a94`) and benilla had built only the middle one, so the screen shook and nothing landed; the thud is a two-axis join — size class against terrain sound, through `DeathThudLookups.dbc` to a land or water kit — behind exactly three gates: more than 2.0 yd of liquid over the feet is complete silence, a size class outside 0..=4, and no terrain, no row or a kit of 0; it plays on bus 0, uncapped, so a battlefield's worth of bodies all land — the shake is the rare thing (49 of 430 models name a preset), the thud the universal one (329 key a `$DTH`, players included); the size axis had sat in our `CreatureDisplayInfo` schema labelled a string column 5875 does not have, and `StringLookups` stays unparsed on purpose — 9 rows benilla already resolves (1866)
- twelve faux-scroll lists showed their bar, moved their thumb and never moved their list: the reference's kit writes `frame.offset` from one handler the OWNER declares, and ours were wired to a `frame.updateFunc` field the reference does not have — Skill, Craft, TradeSkill, ScriptLog, the auction and the social panes are rewired, and a gate fails any faux frame without a handler of its own, because a list only scrolls when something drives it (1868); and the macro window's "Change Name/Icon" raised on a nil offset: `MacroPopupScrollFrame` inherits a template the manifest never loaded, and a missing template is a warning, so the frame was built BARE — no scroll bar, no scripts, no `offset = 0` — and the reference's offset read has no `or 0` cushion; the line is in the manifest, and a static gate fails any `inherits=` the manifest declares nowhere (1862)
- the character geoset selector's missing eighth branch is the tabard designer: B6 of `0x477520` is gated on "the guild registrar's tabard designer is open", not an ItemDisplayInfo column, and wears the tabard flap with an EMPTY tabard slot; dormant until `TabardFrame` migrates, but reading the whole function turned up three branches wrong since their first pass: B4-short never disabled [501,599], so the bare foot — a real submesh on 11 of the 18 character models — rendered inside every boot; B3 asked "is a chest equipped?" where the reference asks whether anything but the shirt paints the ArmLower tile, wrong more often than right (533 of 637 chest displays leave it empty, 566 of 570 wrist displays fill it); and B7 had no tabard guard, an ungated doublet arm, and a leg arm read off chest-or-legs where the reference reads the chest's bit alone (1864)
- a GameObject's display sounds have one trigger and two lanes: `GameObjectDisplayInfo.Sound[0..9]` has one reader (`0x5f4010`), reached only from the anim-event dispatcher, so benilla's state-transition arm — 19 Open and 4 Close rows the reference leaves silent, 80 Open and 38 Close doubled against the clip's own `$GO1`/`$GO3` — is deleted; and the kit's `0x200` flag is a LANE SELECT, not a loop flag: set means the ambient pool, which every campfire, brazier, torch and fountain names (37 live slots), and which had been starting untracked forever-channels (1867); and `WOW_PROBE_SERVICE=1` reads the NPC-service ladder back off a live server — four real NPCs, reporting the arm taken, the opcode sent and the window opened — with every hop inside the reference's own service reach, after a first run parked ~29 yd from Deputy Willem and blamed the client for a dropped packet (1865)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 20:48:52 +07:00
SamandClaude Fable 5.1 b45bce8184 bindings answer the reference's shapes, and the panel kit goes stock
- four return shapes were wrong — `UnitPowerType` returns ONE value in 5875 (the Era `(type, "RAGE")` pair does not exist, and its miss arm pushes the NUMBER 0, which `UnitFrame.lua:122` indexes `ManaBarColor` with), `UnitName` returns `(name, server)`, `GetTexCoord` returns EIGHT (ours four — a shape that exists nowhere, with zero call sites in FrameXML, so only the binary could have caught it), `GetLootMethod` answers `freeforall` ungrouped — the fifth right-name-wrong-arity finding in two days, so wow-re's `binding-shapes.tsv` (1722 rows over all 82 registrar tables) is vendored and a gate probes every binding's arity against it: 313 probes, eight divergences (seven global, one widget); `GetBuildInfo` pushed a fourth value no 1.12 client does (458 corpus sites take one, the four that destructure a fourth read nil on the real client), `GetAddOnInfo` RAISES on a numeric index, `Model:GetFogColor` is a packed `0xAARRGGBB` dword with no unset state, and the five miss branches are the reference's exact tuples
- the panel-template kit is the reference's own `UIPanelTemplates` pair (our 18 templates were a strict subset — `TabButtonTemplate` and the `ScrollingEdit_*` family arrive, which unblocks the macro window and HelpFrame), and the swap found two structural facts: `FauxScrollFrameTemplate` is a `<ScrollFrame>` while every instance we declared was a `<Frame>` (fifteen elements across twelve files), and an instance `<OnLoad>` REPLACES the template's — four FriendsFrame lists set `updateFunc` in their own OnLoad, so `ScrollFrame_OnLoad` never ran and guild/friends/ignore/who had been silently painting nothing behind a `frame.offset or 0`
- the options widget kit (`OptionFrameBoxTemplate`, `OptionsButtonTemplate`, `OptionsCheckButtonTemplate`, `OptionsSliderTemplate`) comes off the chain too, giving back the reference's own per-widget hover; one template of ours stays because `UIOptionsFrame.xml` is not built here, and the lesson is general — when a file SHRINKS rather than dies, every harness that named it gains the chain entry beside it, not instead of it

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 17:06:36 +07:00
SamandClaude Fable 5.1 6bafea0919 your character speaks its refusals, and clicks land on the right frame
- your character speaks its refusals: `VocalUISounds.dbc` gets an adapter, `sound::vocal` transcribes `0x4580f0`'s per-race table and `0x458250`'s play cycle — four plays of one line arm the annoyed variations, and the bus cap of one keeps the annoyed and ordinary lines from playing at once; a displayed message now carries its catalog RECORD, so its sound comes off the same row (tag 0x44 plays the named cue, anything else speaks the line), and 36 of the keys benilla raises have a voice — cast failures, inventory refusals, the quest/auction/petition lines, taxi, bank, stable, mail, the talent wipe; `EnableErrorSpeech` joins the CVars at the registrar's own default and the Audio page grows 1.12's fourth Sound checkbox with the dependency ours was missing (the master greys Ambience AND Error Speech, not Music); seven of the twelve taxi refusals turn out to be the YELLOW info line, not the red one they all took
- at equal (strata, level) the hit sweep takes the EARLIER-linked frame: `0x764aa0` inserts with a strict `ja`, so equal keys are appended, and `0x7660d0` sweeps each bucket from index 0 upward — the reverse of the reverse-draw-order walk we had, so draw order is unchanged and only the hit sweep reorders within a plane; the wheel becomes its own index, and the five full-area wheel-catcher Buttons (Craft, QuestLog, Skill, TradeSkill, Trainer) are deleted, since under the true tie law each would have swallowed its whole window's clicks — a bug the Skill window's own comment had already recorded once
- one rasterizer settle for the whole ground-decal family, and it is the measured one: the shipped client constructs `CGxDeviceD3d`, so the OpenGL arm holding the −4.0 slope factor is never executed (factor 0 on 2485 of 2485 captured `glPolygonOffset` calls), and every number derived from it was 256× too small; the reference groups the blob shadow with the selection RING and the footprints on their own at 10×, the reverse of ours — but ours is reversed-Z float where the bake residual is millimetre-scale and constant with distance, so `DECAL_RASTER` collapses to one value (32768: the ring and the reticle had been under their own conflict at 8192 and simply never walked on a slope)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 17:03:50 +07:00
SamandClaude Fable 5 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>
2026-08-27 15:06:05 +07:00
SamandClaude Fable 5 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>
2026-08-25 18:49:16 +07:00
SamandClaude Fable 5 eaabe372f7 the Lightwell stands up, and stealth openers start your swing
- the Lightwell has its shaft: a billboard card kept only the x of its bone's scale, so a bone animated non-uniformly (the well's 8.8 × 8.8 × 37.6 light column) collapsed into a squat blob drowning the bowl — 32 models and 49 bones in the corpus were losing their stretch the same way, mage Teleport's six bones at ×11 among them; `bbscan` grew the column that finds them
- Backstab, Garrote, Ambush, Cheap Shot, Shred, Ravage, Pounce and one Judgement start your auto-attack on the spell's hit, as the reference does — the "no spell carries that bit" the deferral rested on was a proof by absence over ten rows; the census now covers the shipped file's 36
- Quiver's range rung reads right: the interact-distance map held players only, so a mob "target" answered a constant at every distance; it holds every unit now, with the inspect refusal riding the entry
- the craft and tradeskill reagent slot is the reference's QuestItemTemplate (147×41, the name plate, the count on the icon) — its base template lives in the Blizzard addons, not FrameXML, which is why the first cut was hand-rolled

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 18:47:48 +07:00
SamandClaude Fable 5 cf581aa2ac the auction house opens, the Honor tab lands, and a day of fixes
- 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>
2026-08-22 19:04:27 +07:00
SamandClaude Fable 5 d1140829d7 the interface code is ours: the transcription debt is paid
- forty files that carried the reference's literal Lua are rewritten as our own expression of the behaviour — worst identical run 61 lines down to 7 — and the README now says exactly that
- the overlap gate measures the code itself across all four reference corpora, and ratchets: the number may only go down
- a lost session ends at the login screen instead of silently re-authenticating and stealing the account back
- a building's skybox is a real model: Caverns of Time's white ceiling becomes its painted nebula and additive stars

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-14 19:21:03 +07:00
SamandClaude Fable 5 b5bc569156 the addon arc: the AddOns folder opens
- 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>
2026-08-11 18:18:31 +07:00
SamandClaude Fable 5 ba9a333aeb the Ironforge lava returns, and the sound crackle is cornered
- 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>
2026-08-07 16:03:52 +07:00
SamandClaude Fable 5 3b6975fdef the pet gets its frame, flooded rooms fill, and macros really fire
- 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>
2026-08-05 19:03:43 +07:00