Files
moonwell-client/docs/prototype.md
T

5.0 KiB

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/<name>/.
  • 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:

.\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 <client>.
  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.