The lit air is eased toward a ceiling of 0.35 in luma (the faint dusk glow is as it was) and
laid over the frame as a screen, as are the sun shafts, so a bright pixel brightens little and
none clips; its forward lobe is gentler (g 0.5), and the bloom raises the stock glow less
(x(1 + 0.8 s), was 1.5). Checked at five places through seven hours.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The post pass takes from the dark and middle tones (eased off toward the bright, so a torch's
pool, a window or the moon keep theirs): post.shadow_depth at any hour, post.night_darkness
far further with the sun down, cooler and a little greyer. The lit air keeps 15% for the moon
(was 35%). The Forever preset sets both.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Light in the air through the sun's shadow cascades (rays through canopies, the air glowing
toward a low sun), secondary lighting off the screen, FXAA and a contrast-adaptive sharpen in
the post pass, bloom from the stock FFXGlow, dense far grass through ClutterConfig (the core
re-meshes on a fade change), wind waves on water without current (city canals included), and
a "WoW Forever look" button in the options window. Everything off still draws the stock image.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1.12 gives no quest id for a log row and no world position. benilla-ui
opens two reads (quest_log_row_quest, player_place) and the MoonWell
launcher adds MoonWell_GetQuestLogQuestID and MoonWell_GetPlayerPlace to
each in-game VM, for MoonWell UI's quest map. A dev build also adds
MoonWell_DevInteract(entry) for scripted runs.
Built and checked on Windows (release, and the player build without dev);
clippy clean for benilla-ui and moonwell; quest_log tests pass.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Since upstream b4d0987a startup recurses deeper than Windows' 1 MiB
default and MoonWell.exe overflowed its stack before the glue screen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Applies upstream c5fc904f..b4d0987a (34 commits): live loot, auction,
mail and trade getters; packet-ordered signals; world click records;
transport props. docs/MAP.md and DEVIATIONS.md regenerated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Project Reforged's helms (patch-G) key their root bone in Stand: a
constant translation of (-0.09, 0, -0.18) that seats the helm on the HD
head. benilla drew every resting item at its bind pose, as no stock item
keys its bones, so these helms floated above and in front of the head.
An item whose loader-idle clip poses a bone now gets a pose and a player
like a flexing bow, its palette rows F x model[b] x ibp[b]: the reference
animates every attached M2 (0x714260). Stock items, keyless, are
unchanged.
Verified with creature-sun-front captures of MoonWell.exe at 1600x900
on the install's Data (Reforged A + G), the fixture's display set to
Stormwind guards (5446 female, 1984 male, Helm_Plate_AllianceUprez_B_01):
the helm sat above the head before and sits on it after; display 1862
(stock Helm_Plate_B_01Stormwind) is unchanged. benilla-app's equipment
tests 26/26. The fixture's display override was a working-tree change
only. Built on Windows.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A restarted process cannot log in: the launcher's login ticket is spent.
The saved choice now just closes the client, and the confirmation (patch-F)
tells the player to start it again through the launcher.
Verified: builds and lints clean (release).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Publishing Project Reforged's patch-A.mpq (1.7 GB) failed four times at
a random part (27, 85, 5, 24), and each failure aborted the upload and
restarted the file from part 1. A part is now sent up to six times with
a doubling pause (4 s to 64 s) before the upload fails, and the failure
names the store's error instead of dropping it.
Verified: builds and lints clean; the release publish is running with it.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Upstream's #2424 holds 1.12.1's device gate on UI textures: a side
that is not a power of two, or is 1024 or more, leaves the solid 8x8
green (0x4484ae-0x4484d0). MoonWell UI (patch-F) draws Forever UI and
its login screens from atlas sheets of 1024² (74) and 2048² (2), all
power-of-two, so after the upstream sync its frames, previews and
glue art turned green.
Core seam (benilla-formats, a few lines): raise_ui_texture_side(side),
set once by the entry point, lifts makes_device_texture's upper bound
(at least 1024); the power-of-two and 8-minimum rules stay. The MoonWell
launcher raises it to 4096, as VanillaHelpers raises the client's limit.
Verified with MoonWell.exe captures at 1600x900 on the release package's
Data: the style chooser's previews and the create screen's vignettes,
banners and bronze frames draw again (green before); the Forever style
in game (a --test-style forever patch-F) draws its frames, bars and
minimap. benilla-formats 549/549 and benilla-assets' green-gate test
pass. Built on Windows.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
66 upstream commits since d3b5df3f, applied with the explicit base.
Conflicts: docs/MAP.md and docs/DEVIATIONS.md taken from upstream and
regenerated (scripts/genmap.sh); Cargo.lock taken from upstream and
refreshed for MoonWell's crates; crates/benilla-ui/tests/vm_parity.golden
taken from upstream, its `sweep cos` answer keyed cos@linux-x86_64, as
this fork lists cos among the per-platform cases.
Verified: MoonWell (release) builds; benilla-formats 549/549,
vm_parity, moonwell-gfx 46/46 (the shader anchors hold).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The tests that read the install assert the stock 1.12.1 data, so a
player's texture pack (Project Reforged's patch-A, -G, -T...) or an
interface mod (patch-F) in the same Data folder failed them. With
$BENILLA_STOCK_CHAIN set, Chain::open mounts a Data directory's base
set, patch.MPQ, patch-2.MPQ and speech2.MPQ, and leaves out every other
patch-?.MPQ; the language pack's folder is not filtered.
scripts/unit-tests.sh, the gates' test runner, exports it.
Verified: a chain test (stock mode keeps patch and patch-2, drops
patch-A.mpq and patch-F.MPQ; without it all mount); benilla-formats'
547 tests pass on the install with Reforged's A and G under
BENILLA_STOCK_CHAIN=1, where three character tests failed before. The
other crates' install tests were not run here. Built on Windows.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1.12 composites a character's body skin (base skin, face, hair,
underwear, worn armour) into a 256² atlas, and benilla copied each
overlay texel for texel into its 256²-space tile, so a pack's larger
textures landed misplaced or were cut. Project Reforged's patch-T (and
patch-U) ship skins and TextureComponents at 2x (4x) and say so with
VanillaHelpers' convention, VanillaHelpers\ResizeCharacterSkin.txt
holding 2 or 4.
CharSections reads that file at load. At scale 1 the composite is
unchanged. At 2 or 4 the atlas is 512² / 1024²: the base skin and every
overlay are resampled to their scaled tile when their size differs (a
pack texture at its scale fits as is, a stock one is enlarged), blended
at level 0, and the mip pyramid is built by 2x2 averages. A Deviation:
comment names the reference's 256².
Verified: a unit test (a stock 128x64 overlay fills its doubled g1 tile
and nothing else, 10 levels down to 1x1); the character tests pass on
the stock data (33/33; on the install with Reforged's patch-A, three of
them fail with or without this change, as they assert stock data);
benilla-extract charatlas for a human female naked and in plate (display
1184): 256² with patch-A alone, 512² with patch-A + patch-T, the layout
the same and the T one visibly sharper; glue-charcreate captures at
2560x1440 with A and with A + T, the T face sharper. The captures needed
upstream's e4bff386 in the working tree only. Built on Windows.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The install's HD archives (Project Reforged's character set: A
characters and NPCs, G gear, L female body, T and U high-resolution
character and gear textures) are mounted or left out of the chain. The
chain opens once, so a change restarts the client.
Core seam (benilla-formats, ~30 lines): leave_out_archives(names) set
by the entry point before anything opens the chain; Chain::open_client
and open_localized skip those archives of the install's Data folder by
name, in any case. The language pack's folder is not filtered.
The launcher (crates/moonwell/src/models.rs) reads the choice from
benilla-config/moonwell-models.toml (characters = "sd" | "hd", HD when
absent; $MOONWELL_MODELS overrides it for a run) and adds
MoonWell_GetCharacterModels / MoonWell_SetCharacterModels to every glue
and in-game VM; a different choice is saved and the client starts again
with its arguments. The interface for it lives in MoonWell UI (patch-F).
Verified: a chain test (a left-out archive does not mount, the rest keep
their order); glue-charcreate captures of MoonWell.exe at 2560x1440 on a
Data with Reforged's A, G and T, SD and HD showing the stock and the HD
human female; an in-game capture answers MoonWell_GetCharacterModels().
The restart itself was not run (captures save no state). Built on
Windows: release dev build and player build.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The FPS journal writes gpu-passes.log (every top-level GPU pass) and cpu-phases.csv (wall,
process and main-thread CPU per main schedule) beside fps-journal.csv, with a session marker
per recording. On Windows the phase clocks count thread cycles (QueryThreadCycleTime /
QueryProcessCycleTime at a TSC rate calibrated against Instant), since tick-sized process
times cannot split a frame. A crate on top labels recordings through FpsJournalTags; each tag
lands in all three files when recording starts and whenever it changes, and
scripts/journal-report.py summarises a recording per session and tag state side by side.
moonwell-gfx tags recordings with its settings (mwgfx) and gets cheaper at renderScale 2:
- the ambient occlusion reads a linear depth pyramid (ao_depth.wgsl, after McGuire's SAO),
far samples off coarse levels: 2.2-2.4 ms -> ~1.1 ms at 12 MP, image unchanged (max 9/255);
- the water's scene copy is skipped while no view sees a liquid;
- shadow casters take their own visibility class, so the world camera stops listing them.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Add the graphify knowledge graph of crates/ and the CLAUDE.md rules for using it. Only the graph, report, viz and manifest are tracked; caches and scratch files are ignored.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Import 48 upstream commits since 9a5f2a56 and retain the ruRU localization: Cyrillic names
keep the twelve-letter cap in upstream's reworked name check, the roster keeps its Unicode
name match beside upstream's new tests, and the spell cost cells take upstream's keyed
GlobalStrings templates, which supersede ours. The workspace stays at 0.3.0 (upstream went
back to 0.2.0 until its 0.3.0 ships); cos stays a per-platform VM parity case. Workspace
tests pass on Windows.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A graphics crate on top of benilla, added through `run_with` in the MoonWell launcher, with
small seams in the core: atmospheric fog, sun shadows (static, terrain and entity casters),
a post pass (SSAO, sun shafts, grading), wind in trees and grass, stylised water after
benilla-watershader (planar mirrors for two heights, SSR, shore foam, character wakes, river
current), light from fires and lamps with per-pixel point lights, halos and torch shadows,
and an in-game options window (/mwgfx, the game menu) with a defaults button. Everything is
off by default and then draws the stock image.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Import 25 commits through 9a5f2a56, retain Russian localization and agreement distribution. Windows locked player build, formatting and offline stock glue compatibility checks pass. Full suites not rerun. Production release requested by maintainer.
Import 32 upstream commits through a5cb73a8 and include original EULA/TOS in client packages. Windows player build, targeted packaging tests, clippy and offline stock agreement scrolling checks pass. Original data remain outside Git. Full workspace suites not rerun.
Accept Cyrillic confirmation case-insensitively in the ruRU glue layer. Offline stock GlueXML reproduction and focused verification passed; full suites not rerun per user instruction. Production release authorized.
Integrate 182 upstream commits through b2473e60 while retaining MoonWell packaging, branding and the community ruRU pack.
Upstream replaces the C Lua/mlua host with benilla-lua/benilla-mlua and the native glue screens with stock GlueXML. The update also includes the new locale/DBC/name rules, cache and interaction handling, rendering, quest log and chat behavior, including the latest quest completion and timed-quest failure fixes. Fork adaptations use the new APIs: stock Wow.ini locales remain intact, while the ruRU overlay reads column zero and retains its ruRU authentication tag and Lua identity. Russian names keep their twelve-letter policy and Unicode roster matching; fonts, spell costs, race/class labels and translated options retain real-pack regression coverage.
Windows regression fixes keep the locale-default test valid under instrumented window overrides and the shader assertion independent of checkout line endings. The original C Lua 5.1 host, rebuilt from c0630f3d in an isolated directory, reproduces the complete Windows cos-sweep answer byte for byte; cos now uses platform-specific goldens.
Validation on Windows: scripts/gates.sh passed all automatic gates, including real-data and no-install workspace tests, reference tables, documentation, message catalog, render-pass lint, player clippy/tests and engine boots with and without data. MoonWell player clippy also passed with -D warnings. The committed tree exactly matches the full green stamp; five vendored Kira files retain the tested checkout's line endings, with normalized contents unchanged. All three actual ruRU pack regressions passed in both builds. Fifteen test archives were restored read-only from the published client and SHA-256 checked.
Each real-data/player rung skipped 31 tests because the optional addon corpus is absent (24 general, 7 Quiver). Live smoke was not run: no declared probe account; no player-account login or character creation was performed. Linux/macOS changes were not locally built.
Integrate six upstream commits through c0630f3d (2026-10-11), preserving MoonWell branding, launcher integration and ruRU localization.
The update fixes OnUpdate ordering by strata/level/link order, bare Lua errors passed to the error handler, case-insensitive addon file lookup and UNIT_FACTION on faction-template changes. It also adds an optional Bevy dynamic-linking feature and lets test gates report all failing crates.
Merge conflicts retain localized spell costs, race/class display names, Cyrillic character-name input and the twelve-letter creation limit. UI error handling and update traversal follow upstream. docs/MAP.md was regenerated and has no delta.
Validation: full scripts/gates.sh passed on the exact source tree (1884 s) on Windows with the real 1.12.1 MPQ/DBC data and ruRU pack, including workspace tests with and without install data, player tests without dev, and engine boot checks. The 31 optional addon corpus tests are unavailable on this checkout. No live account login was attempted because no probe identity is configured. The optional dynamic-linking feature is retained but not enabled by the default gates.
Spell resource costs, UnitRace/UnitClass and the character-name field were still using English-only paths after enabling ruRU. Costs now fill the selected GlobalStrings templates, the player record and live unit feeds use ChrRaces/ChrClasses display names while retaining file tokens, and typed/pasted Unicode letters reach the UTF-8 create packet. CharacterCreateNameEdit now initializes its reference limit of 12 letters; a 12-letter Cyrillic name retains all 24 UTF-8 bytes. Roster selection also matches the server's recased Cyrillic name.
Reference: 1.12 PaperDollFrame_SetLevel reads UnitRace/UnitClass; ruRU GlobalStrings supplies MANA_COST/RAGE_COST/ENERGY_COST and their PER_TIME forms; the selected ChrRaces/ChrClasses DBCs supply display names. vmangos normalizePlayerName decodes UTF-8 and recases letters: https://github.com/vmangos/core/blob/development/src/game/ObjectMgr.cpp#L60.
Original symptoms reproduced by instruments with real client data: 30 Mana, Human/Warrior in CharacterLevelText, and Cyrillic keyboard text rejected. The same instruments check Russian and adjacent English text, Human/Warrior and Tauren/Druid, Unicode typing/paste/backspace and the 12-letter cap. The create packet and normalized roster spelling have separate checks.
Validation: the original three symptoms reproduced, then the same three instruments passed with real ruRU and adjacent enUS data. Full land gates passed on the final source tree (816 s): fmt, workspace clippy, workspace tests with data and without an install, doc links, render-pass lint, player tests without dev, and engine boot with/without data. Only the 31 absent addon-corpus tests skipped on each real-data test rung. The strengthened create-packet check verifies the actual reset field, its 12-letter cap and unmodified UTF-8. Built on Windows. No live character creation or player-account login (no declared probe account).
Bring the fork from its already integrated upstream c2fc3cf3 snapshot to 710eb8f531. The new upstream commit changes only development/play build profiles: dev ThinLTO is disabled and dependencies use one codegen unit. Production release and ship profiles are unchanged; MoonWell integration and Russian localization are retained.
Source: upstream commit 710eb8f5, PR samwhosung/benilla#857. The patch is applied unchanged. MAP was regenerated and has no delta.
Validation on Windows: formatting and locked workspace metadata pass. All automated land gates passed on the final tree (4100 seconds): clippy, workspace tests with and without installed data, documentation and render-pass checks, player-build tests and both engine boot checks. The only skipped tests are 31 optional vanilla-addon/Quiver corpus tests, because that corpus is unavailable. Parsed TOML confirms that all profiles match upstream and that release/ship profiles and workspace dependencies are unchanged. Russian roster labels, character creation names, deletion text and locale-aware NPC-cache tests passed against the real archives. No declared probe account is available for a live game login. Upstream performance figures were measured on macOS and are not claimed for Windows.
Russian character selection displays literal numbered placeholders, and character creation uses English race/class names even when its descriptions are translated. Resolve display names from the selected ChrRaces/ChrClasses DBCs and use the existing numbered-argument formatter for roster rows and deletion prompts.
Creature caches were always written and accepted as enUS. Write the selected client locale into the header and reject caches from another language, allowing the server to answer fresh NPC-name queries.
Reference: the supplied ruRU pack has CHARACTER_SELECT_INFO ordered as class then level, and its DBC name slots contain the Russian labels. The deployed server has 9,755 Russian NPC names; existing local caches contain 101 English-only NPC records. The reported quest giver is Guard Thomas (261), starting quest 37; its Russian name exists in the deployed database.
Validation: ten targeted Windows checks passed against the supplied archives with data required and no skips. All automated land gates passed: formatting, clippy, tests with and without installed data, player-build tests, documentation and enforcers. The 31 optional addon-corpus tests skip because the vanilla addon/Quiver corpus is unavailable. Tests cover real ruRU roster rows including ghosts, Human/Warrior and Tauren/Druid creation headers, changing class-button labels, deletion text without deleting, English fallback, and cache rejection across enUS/ruRU. Windows only. No unattended game login was performed because this checkout has no declared probe account.
The client selects an installed Data/ruRU pack for assets, DBCs, Lua GetLocale, Cyrillic fonts and realmd locale. WOW_LOCALE supports auto, enUS and ruRU. Localize MoonWell options, menu, bindings and script log; preserve English reference loading and fallback. The deployment tool stages and validates the supplied ruRU archives without changing the install.
Rebased on main 97a92194, which integrates approved GitHub upstream c2fc3cf3. No conflicts were required for localization.
Windows validation on the exact final tree: scripts/gates.sh ALL GATES GREEN (2671 seconds), workspace tests with and without reference data, player build tests and engine boot checks. Russian FrameXML, captions, settings/search, Cyrillic font glyphs and locale challenge tests are included. 31 tests skipped only because the addon corpus is absent. No declared account for a live login; other platforms were not built. Game assets remain outside Git.
Update the fork to the approved upstream/main snapshot c2fc3cf3, including UI scale, load/reload lifecycle and visibility fixes. Preserve MoonWell integration and live-player seating during ReloadUI. MAP was regenerated.
Windows validation: all scripts/gates.sh gates green (2963 seconds), with and without vanilla data, player build tests and engine boot checks. 31 tests skipped only for the absent addon corpus. No declared account for live login; other platforms were not built.
Integrate the MoonWell launcher and deployment tooling on the local upstream baseline d0d1b5de. Correct the shipped icon path, regenerate the code map, and make source/Lua gates portable to Windows. Classify launcher startup icon access as input plumbing.
Verified on Windows: scripts/gates.sh ALL GATES GREEN; MoonWell release build without dev; 12 deployment tests; deployment and packaging script syntax. Stock MPQ chain excludes the custom patch-3. Thirty-one addon tests skip per data-enabled rung because the corpus is absent. Native macOS/Linux and live login smoke were not run; no declared test account is available.
With Click to Move on, benilla walked only to things you interact with. In 1.12.1 a right-click on the ground walks to the point (`0x5e0378` → `0x6102b0`, 0.5 yd short, speed-scaled, no leash, held in a deck's frame). A right-click on the sky with an empty cursor walks along the ray (`0x492dca` → `0x610100`), pitching while swimming. An attack on an enemy out of melee walks to where it stood (`0x60c22b` → `0x60fcc0`, mode 10): the stop is about 1.9 yd because the arm names the player's own guid, the radii are unscaled, and the 80 yd leash says ERR_AUTOFOLLOW_TOO_FAR. Inside melee the player turns to face it.
Deviations, each written where it lives: the melee point keeps the enemy's height, does not snap to the reference's fixed arrival heading, and rides the deck it was armed on.
Tests: the router, the steering, the gates, the leash and the deck frames.
Fixes#758
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Mathih13 <15229325+Mathih13@users.noreply.github.com>
Co-Authored-By: Sam <samuv.eth@gmail.com>
In 1.12.1 the `SMSG_LOOT_RESPONSE` handler selects a looted unit before it opens the window (`0x5ebc35` → `0x48f3a0`, SetSelection at `0x48f3be`). benilla opened the window without selecting it. So a Tab pressed during a Click-to-Move walk to a corpse left the Tab target selected when the loot opened.
The handler now admits the response and arms the latch, then selects a unit through the one SetSelection path, then opens the window. A refusal, a chest or an item selects nothing. SetSelection's re-swing now uses StartAttack's target gate (alive, then CanAttack, `0x5ecc16`), so switching to a body mid-swing never swings at it.
Tests: the handler's select, dedup, refusals, teardown order and swing stop, a hostile body looted mid-swing, and the stock TargetFrame naming the looted body.
Fixes#763
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Use binding_abi::flag for SpellIsTargeting and SpellCanTargetUnit so addons
can compare their results with 1, as in 1.12.1. Keep nil for false.
Verified on Windows with Rust 1.98.1: three regression failures before
the fix, all 35 focused spell tests passing after it, formatting and
render-pass lint clean. The full UI run passed 1677 tests, with one
ignored and one traceback-name failure reproduced on untouched main.
Fixes#711
Three ways the one-shot emote player differed from 1.12.1.
- **LiftOff and Land were refused in combat.** `0x5fcd20` exempts AnimIDs 192 and 200 from its combat test only (`0x5fcd5f`-`0x5fcd92`), so a dragon's take-off and landing now play mid-fight.
- **An emote could restart a clip already armed.** The player skips an id already armed on the key bone or bone 0 (`0x5fcd56`, `0x5fdb50`). It compares the requested id, which op4 stores at `+0xf8` (`0x71252f`), not the fallback that plays.
- **Your own emote waited for the server.** `DoEmote` plays it locally while a direction key is held (`0x5fd680`, called at `0x5ef660`), so a moving `/wave` shows at once and its echo is skipped.
Tests cover the exemption, the armed test (including on a rider), each local-play gate, and the skipped echo.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Two ways the emote-state base pick differed from 1.12.1.
- A blacksmith kept hammering while you used his vendor window. The resolver `0x5fd770` passes over a state whose `Emotes.dbc` flags have `0x2000` (work, mining, ready, dance) while the unit is the interact NPC (`0x5fd7e2`-`0x5fd7fd`). `SetInteractNPC` re-picks on open (`0x493198`) and on close (`0x493219`, before the name clears at `0x49334b`), never for a player. So the NPC stands, and the loop resumes at its next re-pick.
- A set state outranks the idle fallbacks: `0x5fd770` runs before `0x5fd830`, and a row with AnimID 0 claims Stand. After `/stand` (state 26), a swimmer at rest shows Stand until it moves.
Tests cover the open, the close hold, players, a pose under a one-shot, and the precedence order.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Three ways `DoEmote` and the chat talk gesture differed from 1.12.1:
- `/wave Bob` ignored the name and targeted the selection. 1.12.1 resolves a name that does not start with `%` as a player, at any range (`0x49fdb1`-`0x49fdf0`, `0x493aa0`), and sends the emote untargeted on a miss. `DoEmote(token, name)` from Lua does the same.
- A polymorphed, stunned or sleeping speaker still played the talk gesture. `UNIT_FIELD_FLAGS 0x20000000` suppresses it when the sender's name is cached (`0x49d7f7`).
- `DoEmote` sent while our unit was possessed (`0x5ef57e`). A chat-only emote now reads `Emotes.dbc` row 0's flags, so it is refused while asleep or dead (`0x5ef5b1`, `0x47db8e`).
Tests cover the name, miss, `%t` and self cases, the gesture gate, and both `DoEmote` gates against the install's row 0.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
One-shot emotes were routed by a hand-made class table that wrongly let `/pray` (75), the `/beg` family (79), and 126, 127, 131, 132 and 135 play upper-body. A mounted rider played every id on its upper body.
1.12.1 reads two byte tables:
- CLASS_A (`0x5fed90`): the ids that may play on the key bone.
- The mount set (`0x5fec80`): what goes to the mount model while mounted (`0x5fe7b5`..`0x5fe803`). Anything else plays nowhere.
What changed:
- Both tables now match the bytes, and a mount-set id is forwarded to the mount child.
- Unmounted `/eat` (61) always plays upper-body (`0x5fe834`).
- A model with no split bone arms nothing for an upper-body play (`0x5fdcc4`).
Tests pin both tables for every id 0..300, plus the mounted, eat and no-bone driver cases.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Every text emote's voice played for every performer, so every `/cheer` in a city was heard. 1.12.1's composer tail (`0x623c80`) plays it only for you or a member of the four party slots (`0x623cc2`-`0x623cce`, `0x5efea0`), and drops an ignored sender before that (`0x49dc36`).
What changed:
- The voice plays at attachment `0x11` and stops the unit's previous emote voice once a new one opens (`0x623c10`).
- Race and sex come from the display override before the descriptor (`0x60c6a0`/`0x60c6c0`).
- `SMSG_EMOTE` no longer plays `EventSoundID`. The one-shot path never reads it (`0x5e66b0` → `0x5fcd20`); only the state emote's `$ESD` does.
Tests cover each relation class, an ignored performer and the per-unit voice slot.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>