# MoonwellCustomization vertical slice ## Scope `MoonwellCustomization.dll` is a runtime-only WarcraftXL 1.1 extension for WoW 3.3.5a build 12340. It changes only an active Blood Elf Female player. State is kept in memory and is deliberately separate from rendering; there are no server packets, database changes, AzerothCore changes, or new Wow.exe offsets. The data flow is: `CustomizationOption (126) -> CustomizationChoice -> CustomizationElement (Geoset) -> collection M2` The explicit prototype state is None plus three retail choices. The renderer owns one independent collection render context at a time. Reapplying the same choice is a no-op; replacing a choice releases the old context first. The overlay copies the active character's placement and bone palette without joining the stock attachment readiness chain. `OnWorldLeave` always releases it and drops all borrowed player pointers. ## Verified WarcraftXL API The repository pins `vendor/warcraftxl` to `v1.1.220` (`4895cef`) on the `v1.1` branch. Source code, not README assumptions, establishes the following behavior: - `WXL_Query`/`WXL_Load` are the extension entry points; the runtime loads DLLs found below `Extensions//`. - `WXL_Api::UiAddPanel` registers an immediate-mode overlay panel. WarcraftXL v1.1 hard-codes `F9` as its overlay toggle; press it and select **MoonWell Customization**. - `world::ActivePlayerGuid` and `world::ResolveObject(..., kTypeMaskPlayer)` find the active player; `unit::Model` returns its body-model/scene-node binding. - The upstream typed `SceneNode` and `CharModelObject` views provide owner, race, gender, and root scene node. The extension adds no offsets. - `m2::GetRenderCtx` always creates a new scene model; `AttachToScene(..., slot 19, true)` attaches a collection M2. Core explicitly documents 19 as the collection-M2 attachment point. - `OnM2SkinFinalize` is the safe pre-finalize window to filter collection geosets. Runtime changes call `FinalizeSkin` once; a recursion guard prevents its event from re-entering the filter. - `OnBuildBonePalette` is post-engine and therefore the safe point to copy the parent character bone palette into the collection model immediately before upload. - `OnItemSlotChange` and `OnItemSlotClear` schedule a replacement on the next logic tick, after native equipment work. Native equipment is never overridden. - `OnWorldLeave` is the cleanup event. Events and UI run on WarcraftXL's main/render paths; no worker thread calls client model bindings. ## Build From a Visual Studio 2022 developer environment or PowerShell: ```powershell .\build-warcraftxl.ps1 -Configuration Release ``` The required artifact is: `build\warcraftxl-win32\Release\MoonwellCustomization.dll` The target is Win32. The top-level CMake build compiles the extension together with the existing WarcraftXL SDK sources; there is no second CMake project. ## Install and run 1. Install the asset files described in `docs/wow-export-assets.md` into a client MPQ. 2. Copy the DLL to `Extensions\MoonwellCustomization\MoonwellCustomization.dll` under the client directory. The build script does this automatically when invoked with `-Deploy -ClientPath `. 3. Start the stock build-12340 client through the installed WarcraftXL `d3d9.dll` proxy. 4. Press `F9` to open the WarcraftXL overlay and select **MoonWell Customization**. 5. On Blood Elf Female, press None / Betrayer / Beast / Dreadlord. None must remove the collection; repeated selections must not stack it. Equip and remove a helmet, then log out and back in. 6. On every other race or gender, the panel reports that the prototype is unsupported and exposes no choice controls. Expected log lines are tagged `[MoonwellCustomization]`: `loaded`, `player detected`, race/gender, apply, model load, attach, detach, unsupported player, and actionable failure text. ## Known limits - The repository intentionally excludes Blizzard assets. Without the collection M2 and sibling skin, the client loader can fall back to its placeholder model; that is an asset-install failure, not a successful visual test. - Retail collection model 7760202 is a modern MD21 asset. It requires the existing `wxl-modern-m2`, `wxl-modern-blp`, `wxl-db2`, and FDID extensions in this repository. - Bone copying assumes the retail Blood Elf Female collection uses the same ordered skeleton as its parent model. The code clamps to the smaller palette, but a retail build changing bone order would need an explicit bone map. - `FinalizeSkin` in WXL 1.1 has small internal re-finalize leaks. The implementation therefore performs it only on an actual choice change/equipment refresh, never per frame. - This source-level build proves compilation and packaging. A successful visual result and crash-free logout still require an interactive client session with the external assets installed. The next minimal step toward a broader retail-like system is to move the static option table to an external, versioned catalog and add renderers for Texture and independent M2Attachment elements while keeping the same `optionID -> choiceID` state boundary.