2026-02-02 12:24:50 -08:00
cmake_minimum_required(VERSION 3.15)
2026-03-20 11:12:07 -07:00
project(wowee VERSION 1.0.0 LANGUAGES C CXX)
2026-02-11 15:24:05 -08:00
include(GNUInstallDirs)
2026-02-02 12:24:50 -08:00
2026-02-07 11:43:37 -08:00
set(CMAKE_CXX_STANDARD 20)
2026-02-02 12:24:50 -08:00
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
2026-02-25 09:46:27 -08:00
# Explicitly tag optimized configs so runtime defaults can enforce low-noise logging.
add_compile_definitions(
$<$<CONFIG:Release>:WOWEE_RELEASE_LOGGING>
$<$<CONFIG:RelWithDebInfo>:WOWEE_RELEASE_LOGGING>
$<$<CONFIG:MinSizeRel>:WOWEE_RELEASE_LOGGING>
)
2026-02-02 12:24:50 -08:00
# Output directories
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
2026-03-09 04:24:24 -07:00
if(WIN32)
# Needed for Vulkan Win32 external memory/semaphore handle types used by FSR3 interop.
add_compile_definitions(VK_USE_PLATFORM_WIN32_KHR)
endif()
2026-02-02 12:24:50 -08:00
# Options
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
2026-04-03 09:41:34 +03:00
option(WOWEE_BUILD_TESTS "Build tests" ON)
2026-02-23 16:30:49 +01:00
option(WOWEE_ENABLE_ASAN "Enable AddressSanitizer (Debug builds)" OFF)
2026-04-03 09:41:34 +03:00
option(WOWEE_ENABLE_TRACY "Enable Tracy profiler instrumentation" OFF)
2026-03-08 19:33:07 -07:00
option(WOWEE_ENABLE_AMD_FSR2 "Enable AMD FidelityFX FSR2 backend when SDK is present" ON)
2026-03-08 22:47:46 -07:00
option(WOWEE_ENABLE_AMD_FSR3_FRAMEGEN "Enable AMD FidelityFX SDK FSR3 frame generation interface probe when SDK is present" ON)
2026-03-09 04:24:24 -07:00
option(WOWEE_BUILD_AMD_FSR3_RUNTIME "Build native AMD FidelityFX VK runtime (Path A) from extern/FidelityFX-SDK/Kits" ON)
2026-03-08 19:33:07 -07:00
# AMD FidelityFX FSR2 SDK detection (drop-in under extern/FidelityFX-FSR2)
set(WOWEE_AMD_FSR2_DIR ${CMAKE_SOURCE_DIR}/extern/FidelityFX-FSR2)
set(WOWEE_AMD_FSR2_HEADER ${WOWEE_AMD_FSR2_DIR}/src/ffx-fsr2-api/ffx_fsr2.h)
2026-03-08 19:56:52 -07:00
set(WOWEE_AMD_FSR2_VK_PERM_HEADER ${WOWEE_AMD_FSR2_DIR}/src/ffx-fsr2-api/vk/shaders/ffx_fsr2_accumulate_pass_permutations.h)
2026-03-08 21:45:25 -07:00
set(WOWEE_AMD_FSR2_VK_VENDOR_DIR ${CMAKE_SOURCE_DIR}/third_party/fsr2_vk_permutations)
# Upstream SDK checkouts may not ship generated Vulkan permutation headers.
# If we have a vendored snapshot, copy it into the SDK tree before detection.
if(WOWEE_ENABLE_AMD_FSR2 AND EXISTS ${WOWEE_AMD_FSR2_HEADER} AND NOT EXISTS ${WOWEE_AMD_FSR2_VK_PERM_HEADER} AND EXISTS ${WOWEE_AMD_FSR2_VK_VENDOR_DIR})
file(GLOB WOWEE_AMD_FSR2_VK_VENDOR_HEADERS "${WOWEE_AMD_FSR2_VK_VENDOR_DIR}/ffx_fsr2_*pass*.h")
list(LENGTH WOWEE_AMD_FSR2_VK_VENDOR_HEADERS WOWEE_AMD_FSR2_VK_VENDOR_COUNT)
if(WOWEE_AMD_FSR2_VK_VENDOR_COUNT GREATER 0)
file(MAKE_DIRECTORY ${WOWEE_AMD_FSR2_DIR}/src/ffx-fsr2-api/vk/shaders)
file(COPY ${WOWEE_AMD_FSR2_VK_VENDOR_HEADERS} DESTINATION ${WOWEE_AMD_FSR2_DIR}/src/ffx-fsr2-api/vk/shaders)
message(STATUS "AMD FSR2: bootstrapped ${WOWEE_AMD_FSR2_VK_VENDOR_COUNT} vendored Vulkan permutation headers")
endif()
endif()
2026-03-08 19:56:52 -07:00
if(WOWEE_ENABLE_AMD_FSR2 AND EXISTS ${WOWEE_AMD_FSR2_HEADER} AND EXISTS ${WOWEE_AMD_FSR2_VK_PERM_HEADER})
2026-03-08 19:33:07 -07:00
message(STATUS "AMD FSR2 SDK detected at ${WOWEE_AMD_FSR2_DIR}")
add_compile_definitions(WOWEE_HAS_AMD_FSR2=1)
2026-03-08 19:56:52 -07:00
add_compile_definitions(FFX_GCC=1)
# AMD FSR2 Vulkan backend sources (official SDK implementation)
set(WOWEE_AMD_FSR2_SOURCES
${WOWEE_AMD_FSR2_DIR}/src/ffx-fsr2-api/ffx_assert.cpp
${WOWEE_AMD_FSR2_DIR}/src/ffx-fsr2-api/ffx_fsr2.cpp
${WOWEE_AMD_FSR2_DIR}/src/ffx-fsr2-api/vk/ffx_fsr2_vk.cpp
${WOWEE_AMD_FSR2_DIR}/src/ffx-fsr2-api/vk/shaders/ffx_fsr2_shaders_vk.cpp
)
add_library(wowee_fsr2_amd_vk STATIC ${WOWEE_AMD_FSR2_SOURCES})
set_target_properties(wowee_fsr2_amd_vk PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
)
target_include_directories(wowee_fsr2_amd_vk PUBLIC
2026-03-08 19:33:07 -07:00
${WOWEE_AMD_FSR2_DIR}/src
${WOWEE_AMD_FSR2_DIR}/src/ffx-fsr2-api
${WOWEE_AMD_FSR2_DIR}/src/ffx-fsr2-api/vk
2026-03-08 19:56:52 -07:00
${WOWEE_AMD_FSR2_DIR}/src/ffx-fsr2-api/vk/shaders
2026-03-08 19:33:07 -07:00
)
2026-03-08 19:56:52 -07:00
set(WOWEE_FFX_COMPAT_HEADER ${CMAKE_SOURCE_DIR}/include/third_party/ffx_fsr2_compat.h)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
target_compile_options(wowee_fsr2_amd_vk PRIVATE
"-include${WOWEE_FFX_COMPAT_HEADER}"
)
elseif(MSVC)
target_compile_options(wowee_fsr2_amd_vk PRIVATE
"/FI${WOWEE_FFX_COMPAT_HEADER}"
)
endif()
target_link_libraries(wowee_fsr2_amd_vk PUBLIC Vulkan::Vulkan)
2026-03-08 19:33:07 -07:00
else()
add_compile_definitions(WOWEE_HAS_AMD_FSR2=0)
if(WOWEE_ENABLE_AMD_FSR2)
2026-03-08 19:56:52 -07:00
if(NOT EXISTS ${WOWEE_AMD_FSR2_HEADER})
message(WARNING "AMD FSR2 SDK not found at ${WOWEE_AMD_FSR2_DIR}; using internal fallback implementation.")
elseif(NOT EXISTS ${WOWEE_AMD_FSR2_VK_PERM_HEADER})
message(WARNING "AMD FSR2 SDK found, but generated Vulkan permutation headers are missing (e.g. ${WOWEE_AMD_FSR2_VK_PERM_HEADER}); using internal fallback implementation.")
endif()
2026-03-08 19:33:07 -07:00
endif()
endif()
2026-02-02 12:24:50 -08:00
2026-03-08 22:47:46 -07:00
# AMD FidelityFX SDK (FSR3 frame generation interfaces) detection under extern/FidelityFX-SDK
2026-03-09 01:09:37 -07:00
set(WOWEE_AMD_FFX_SDK_KITS_DIR ${CMAKE_SOURCE_DIR}/extern/FidelityFX-SDK/Kits/FidelityFX)
set(WOWEE_AMD_FFX_SDK_KITS_FG_HEADER ${WOWEE_AMD_FFX_SDK_KITS_DIR}/framegeneration/include/ffx_framegeneration.h)
2026-03-08 22:47:46 -07:00
2026-03-09 04:24:24 -07:00
set(WOWEE_AMD_FFX_SDK_KITS_READY FALSE)
if(EXISTS ${WOWEE_AMD_FFX_SDK_KITS_DIR}/upscalers/fsr3/include/ffx_fsr3upscaler.h
AND EXISTS ${WOWEE_AMD_FFX_SDK_KITS_DIR}/framegeneration/fsr3/include/ffx_frameinterpolation.h
AND EXISTS ${WOWEE_AMD_FFX_SDK_KITS_DIR}/framegeneration/fsr3/include/ffx_opticalflow.h
AND EXISTS ${WOWEE_AMD_FFX_SDK_KITS_DIR}/backend/vk/ffx_vk.h)
set(WOWEE_AMD_FFX_SDK_KITS_READY TRUE)
endif()
2026-03-09 05:00:51 -07:00
if(WOWEE_ENABLE_AMD_FSR3_FRAMEGEN AND WOWEE_AMD_FFX_SDK_KITS_READY)
message(STATUS "AMD FidelityFX-SDK framegen headers detected at ${WOWEE_AMD_FFX_SDK_KITS_DIR} (Kits layout)")
add_compile_definitions(WOWEE_AMD_FFX_SDK_KITS=1)
2026-03-08 22:47:46 -07:00
add_compile_definitions(WOWEE_HAS_AMD_FSR3_FRAMEGEN=1)
add_library(wowee_fsr3_framegen_amd_vk_probe STATIC
src/rendering/amd_fsr3_framegen_probe.cpp
)
set_target_properties(wowee_fsr3_framegen_amd_vk_probe PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
)
2026-03-09 05:00:51 -07:00
target_include_directories(wowee_fsr3_framegen_amd_vk_probe PUBLIC
Add FSR3 Generic API path and harden runtime diagnostics
- AmdFsr3Runtime now probes both the legacy ffxFsr3* API and the newer
generic ffxCreateContext/ffxDispatch API; selects whichever the loaded
runtime library exports (GenericApi takes priority fallback)
- Generic API path implements full upscale + frame-generation context
creation, configure, dispatch, and destroy lifecycle
- dlopen error captured and surfaced in lastError_ on Linux so runtime
initialization failures are actionable
- FSR3 runtime init failure log now includes path kind, error string,
and loaded library path for easier debugging
- tools/generate_ffx_sdk_vk_permutations.sh added: auto-bootstraps
missing VK permutation headers; DXC auto-downloaded on Linux/Windows
MSYS2; macOS reads from PATH (CI installs via brew dxc)
- CMakeLists: add upscalers/include to probe include dirs, invoke
permutation script before SDK build, scope FFX pragma/ODR warning
suppressions to affected TUs, add runtime-copy dependency on wowee
- UI labels updated from "FSR2" → "FSR3" in settings, tuning panel,
performance HUD, and combo boxes
- CI macOS job now installs dxc via Homebrew for permutation codegen
2026-03-09 12:51:59 -07:00
${WOWEE_AMD_FFX_SDK_KITS_DIR}/upscalers/include
2026-03-09 05:00:51 -07:00
${WOWEE_AMD_FFX_SDK_KITS_DIR}/upscalers/fsr3/include
${WOWEE_AMD_FFX_SDK_KITS_DIR}/framegeneration/fsr3/include
${WOWEE_AMD_FFX_SDK_KITS_DIR}/framegeneration/include
${WOWEE_AMD_FFX_SDK_KITS_DIR}/backend/vk
${WOWEE_AMD_FFX_SDK_KITS_DIR}/api/internal
${WOWEE_AMD_FFX_SDK_KITS_DIR}/api/include
)
2026-03-08 22:47:46 -07:00
target_link_libraries(wowee_fsr3_framegen_amd_vk_probe PUBLIC Vulkan::Vulkan)
2026-03-09 00:36:53 -07:00
2026-03-09 05:00:51 -07:00
if(WOWEE_BUILD_AMD_FSR3_RUNTIME)
2026-03-09 04:24:24 -07:00
message(STATUS "AMD FSR3 Path A runtime target enabled: build with target 'wowee_fsr3_official_runtime_copy'")
set(WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR ${CMAKE_BINARY_DIR}/ffx_sdk_runtime_build)
if(WIN32)
set(WOWEE_AMD_FSR3_RUNTIME_NAME amd_fidelityfx_vk.dll)
if(CMAKE_CONFIGURATION_TYPES)
set(WOWEE_AMD_FSR3_RUNTIME_SRC ${WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR}/$<CONFIG>/amd_fidelityfx_vk.dll)
else()
set(WOWEE_AMD_FSR3_RUNTIME_SRC ${WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR}/amd_fidelityfx_vk.dll)
endif()
elseif(APPLE)
set(WOWEE_AMD_FSR3_RUNTIME_NAME libamd_fidelityfx_vk.dylib)
if(CMAKE_CONFIGURATION_TYPES)
set(WOWEE_AMD_FSR3_RUNTIME_SRC ${WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR}/$<CONFIG>/libamd_fidelityfx_vk.dylib)
else()
set(WOWEE_AMD_FSR3_RUNTIME_SRC ${WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR}/libamd_fidelityfx_vk.dylib)
endif()
else()
set(WOWEE_AMD_FSR3_RUNTIME_NAME libamd_fidelityfx_vk.so)
set(WOWEE_AMD_FSR3_RUNTIME_SRC ${WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR}/libamd_fidelityfx_vk.so)
endif()
if(CMAKE_BUILD_TYPE)
set(WOWEE_AMD_FSR3_RUNTIME_BUILD_TYPE ${CMAKE_BUILD_TYPE})
else()
set(WOWEE_AMD_FSR3_RUNTIME_BUILD_TYPE Release)
endif()
2026-03-09 13:11:03 -07:00
# Locate bash at configure time so the build-time COMMAND works on Windows
# (cmake custom commands run via cmd.exe on Windows, so bare 'bash' is not found).
find_program(BASH_EXECUTABLE bash
HINTS
/usr/bin
/bin
"${MSYS2_PATH}/usr/bin"
"$ENV{MSYS2_PATH}/usr/bin"
"C:/msys64/usr/bin"
"D:/msys64/usr/bin"
2026-03-09 04:24:24 -07:00
)
2026-03-09 13:11:03 -07:00
if(BASH_EXECUTABLE)
add_custom_target(wowee_fsr3_official_runtime_build
COMMAND ${CMAKE_COMMAND}
-S ${WOWEE_AMD_FFX_SDK_KITS_DIR}
-B ${WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR}
-DCMAKE_BUILD_TYPE=${WOWEE_AMD_FSR3_RUNTIME_BUILD_TYPE}
-DFFX_BUILD_VK=ON
-DFFX_BUILD_FRAMEGENERATION=ON
-DFFX_BUILD_UPSCALER=ON
COMMAND ${BASH_EXECUTABLE} ${CMAKE_SOURCE_DIR}/tools/generate_ffx_sdk_vk_permutations.sh
${CMAKE_SOURCE_DIR}/extern/FidelityFX-SDK
COMMAND ${CMAKE_COMMAND}
--build ${WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR}
--config $<CONFIG>
--parallel
COMMENT "Building native AMD FSR3 runtime (Path A) from FidelityFX-SDK Kits"
VERBATIM
)
else()
message(STATUS "bash not found; VK permutation headers will not be auto-generated")
add_custom_target(wowee_fsr3_official_runtime_build
COMMAND ${CMAKE_COMMAND}
-S ${WOWEE_AMD_FFX_SDK_KITS_DIR}
-B ${WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR}
-DCMAKE_BUILD_TYPE=${WOWEE_AMD_FSR3_RUNTIME_BUILD_TYPE}
-DFFX_BUILD_VK=ON
-DFFX_BUILD_FRAMEGENERATION=ON
-DFFX_BUILD_UPSCALER=ON
COMMAND ${CMAKE_COMMAND}
--build ${WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR}
--config $<CONFIG>
--parallel
COMMENT "Building native AMD FSR3 runtime (Path A) from FidelityFX-SDK Kits (no permutation bootstrap)"
VERBATIM
)
endif()
2026-03-09 04:24:24 -07:00
add_custom_target(wowee_fsr3_official_runtime_copy
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${WOWEE_AMD_FSR3_RUNTIME_SRC}
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${WOWEE_AMD_FSR3_RUNTIME_NAME}
DEPENDS wowee_fsr3_official_runtime_build
COMMENT "Copying native AMD FSR3 runtime to ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
VERBATIM
)
endif()
2026-03-09 02:42:07 -07:00
2026-03-08 22:47:46 -07:00
else()
add_compile_definitions(WOWEE_HAS_AMD_FSR3_FRAMEGEN=0)
2026-03-09 04:24:24 -07:00
add_compile_definitions(WOWEE_AMD_FFX_SDK_KITS=0)
2026-03-08 22:47:46 -07:00
if(WOWEE_ENABLE_AMD_FSR3_FRAMEGEN)
2026-03-09 01:09:37 -07:00
if(EXISTS ${WOWEE_AMD_FFX_SDK_KITS_FG_HEADER})
2026-03-09 05:00:51 -07:00
message(STATUS "FidelityFX-SDK Kits layout detected at ${WOWEE_AMD_FFX_SDK_KITS_DIR}, but required FSR3 headers are incomplete. FSR3 framegen interface probe disabled.")
2026-03-09 01:09:37 -07:00
else()
2026-03-09 05:00:51 -07:00
message(WARNING "AMD FidelityFX-SDK Kits headers not found at ${WOWEE_AMD_FFX_SDK_KITS_DIR}; FSR3 framegen interface probe disabled.")
2026-03-09 01:09:37 -07:00
endif()
2026-03-08 22:47:46 -07:00
endif()
endif()
2026-02-20 03:02:31 -08:00
# Opcode registry generation/validation
find_package(Python3 COMPONENTS Interpreter QUIET)
if(Python3_Interpreter_FOUND)
add_custom_target(opcodes-generate
COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/tools/gen_opcode_registry.py
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Generating opcode registry include fragments"
)
add_custom_target(opcodes-validate
COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/tools/validate_opcode_maps.py --root ${CMAKE_SOURCE_DIR}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
DEPENDS opcodes-generate
COMMENT "Validating canonical opcode registry and expansion maps"
)
endif()
2026-02-02 12:24:50 -08:00
# Find required packages
find_package(SDL2 REQUIRED)
2026-02-23 18:47:42 -08:00
find_package(Vulkan QUIET)
if(NOT Vulkan_FOUND)
feat: add multi-platform Docker build system for Linux, macOS, and Windows
Replace the single Ubuntu-based container build with a dedicated
Dockerfile, build script, and launcher for each target platform.
Infrastructure:
- Add .dockerignore to minimize Docker build context
- Add container/builder-linux.Dockerfile (Ubuntu 24.04, GCC, native build)
- Add container/builder-macos.Dockerfile (multi-stage: SDK fetcher + osxcross/Clang 18)
- Add container/builder-windows.Dockerfile (LLVM-MinGW 20240619, vcpkg)
- Add container/macos/sdk-fetcher.py (auto-fetch macOS SDK from Apple catalog)
- Add container/macos/osxcross-toolchain.cmake (auto-detecting CMake toolchain)
- Add container/macos/triplets/arm64-osx-cross.cmake
- Add container/macos/triplets/x64-osx-cross.cmake
- Remove container/builder-ubuntu.Dockerfile (replaced by per-platform Dockerfiles)
- Remove container/build-in-container.sh and container/build-wowee.sh (replaced)
Build scripts (run inside containers):
- Add container/build-linux.sh (tar copy, FidelityFX clone, cmake/ninja)
- Add container/build-macos.sh (arch detection, vcpkg triplet, cross-compile)
- Add container/build-windows.sh (Vulkan import lib via dlltool, cross-compile)
Launcher scripts (run on host):
- Add container/run-linux.sh, run-macos.sh, run-windows.sh (bash)
- Add container/run-linux.ps1, run-macos.ps1, run-windows.ps1 (PowerShell)
Documentation:
- Add container/README.md (quick start, options, file structure, troubleshooting)
- Add container/FLOW.md (comprehensive build flow for each platform)
CMake changes:
- Add macOS cross-compile support (VulkanHeaders, -undefined dynamic_lookup)
- Add LLVM-MinGW/Windows cross-compile support
- Detect osxcross toolchain and vcpkg triplets
Other:
- Update vcpkg.json with ffmpeg feature flags
- Update resources/wowee.rc version string
2026-03-30 20:17:41 +03:00
# For Windows cross-compilation the host pkg-config finds the Linux libvulkan-dev
# and injects /usr/include as an INTERFACE_INCLUDE_DIRECTORY, which causes
# MinGW clang to pull in glibc headers (bits/libc-header-start.h) instead of
# the MinGW sysroot headers. Skip the host pkg-config path entirely and instead
# locate Vulkan via vcpkg-installed vulkan-headers or the MinGW toolchain.
if(CMAKE_CROSSCOMPILING AND WIN32)
# The cross-compile build script generates a Vulkan import library
# (libvulkan-1.a) in ${CMAKE_BINARY_DIR}/vulkan-import from the headers.
set(_VULKAN_IMPORT_DIR "${CMAKE_BINARY_DIR}/vulkan-import")
find_package(VulkanHeaders CONFIG QUIET)
if(VulkanHeaders_FOUND)
if(NOT TARGET Vulkan::Vulkan)
add_library(Vulkan::Vulkan INTERFACE IMPORTED)
endif()
# Vulkan::Headers is provided by vcpkg's vulkan-headers port and carries
# the correct MinGW include path — no Linux system headers involved.
set_property(TARGET Vulkan::Vulkan APPEND PROPERTY
INTERFACE_LINK_LIBRARIES Vulkan::Headers)
# Link against the Vulkan loader import library (vulkan-1.dll).
if(EXISTS "${_VULKAN_IMPORT_DIR}/libvulkan-1.a")
2026-02-23 18:47:42 -08:00
set_property(TARGET Vulkan::Vulkan APPEND PROPERTY
feat: add multi-platform Docker build system for Linux, macOS, and Windows
Replace the single Ubuntu-based container build with a dedicated
Dockerfile, build script, and launcher for each target platform.
Infrastructure:
- Add .dockerignore to minimize Docker build context
- Add container/builder-linux.Dockerfile (Ubuntu 24.04, GCC, native build)
- Add container/builder-macos.Dockerfile (multi-stage: SDK fetcher + osxcross/Clang 18)
- Add container/builder-windows.Dockerfile (LLVM-MinGW 20240619, vcpkg)
- Add container/macos/sdk-fetcher.py (auto-fetch macOS SDK from Apple catalog)
- Add container/macos/osxcross-toolchain.cmake (auto-detecting CMake toolchain)
- Add container/macos/triplets/arm64-osx-cross.cmake
- Add container/macos/triplets/x64-osx-cross.cmake
- Remove container/builder-ubuntu.Dockerfile (replaced by per-platform Dockerfiles)
- Remove container/build-in-container.sh and container/build-wowee.sh (replaced)
Build scripts (run inside containers):
- Add container/build-linux.sh (tar copy, FidelityFX clone, cmake/ninja)
- Add container/build-macos.sh (arch detection, vcpkg triplet, cross-compile)
- Add container/build-windows.sh (Vulkan import lib via dlltool, cross-compile)
Launcher scripts (run on host):
- Add container/run-linux.sh, run-macos.sh, run-windows.sh (bash)
- Add container/run-linux.ps1, run-macos.ps1, run-windows.ps1 (PowerShell)
Documentation:
- Add container/README.md (quick start, options, file structure, troubleshooting)
- Add container/FLOW.md (comprehensive build flow for each platform)
CMake changes:
- Add macOS cross-compile support (VulkanHeaders, -undefined dynamic_lookup)
- Add LLVM-MinGW/Windows cross-compile support
- Detect osxcross toolchain and vcpkg triplets
Other:
- Update vcpkg.json with ffmpeg feature flags
- Update resources/wowee.rc version string
2026-03-30 20:17:41 +03:00
INTERFACE_LINK_DIRECTORIES "${_VULKAN_IMPORT_DIR}")
2026-02-23 18:47:42 -08:00
set_property(TARGET Vulkan::Vulkan APPEND PROPERTY
feat: add multi-platform Docker build system for Linux, macOS, and Windows
Replace the single Ubuntu-based container build with a dedicated
Dockerfile, build script, and launcher for each target platform.
Infrastructure:
- Add .dockerignore to minimize Docker build context
- Add container/builder-linux.Dockerfile (Ubuntu 24.04, GCC, native build)
- Add container/builder-macos.Dockerfile (multi-stage: SDK fetcher + osxcross/Clang 18)
- Add container/builder-windows.Dockerfile (LLVM-MinGW 20240619, vcpkg)
- Add container/macos/sdk-fetcher.py (auto-fetch macOS SDK from Apple catalog)
- Add container/macos/osxcross-toolchain.cmake (auto-detecting CMake toolchain)
- Add container/macos/triplets/arm64-osx-cross.cmake
- Add container/macos/triplets/x64-osx-cross.cmake
- Remove container/builder-ubuntu.Dockerfile (replaced by per-platform Dockerfiles)
- Remove container/build-in-container.sh and container/build-wowee.sh (replaced)
Build scripts (run inside containers):
- Add container/build-linux.sh (tar copy, FidelityFX clone, cmake/ninja)
- Add container/build-macos.sh (arch detection, vcpkg triplet, cross-compile)
- Add container/build-windows.sh (Vulkan import lib via dlltool, cross-compile)
Launcher scripts (run on host):
- Add container/run-linux.sh, run-macos.sh, run-windows.sh (bash)
- Add container/run-linux.ps1, run-macos.ps1, run-windows.ps1 (PowerShell)
Documentation:
- Add container/README.md (quick start, options, file structure, troubleshooting)
- Add container/FLOW.md (comprehensive build flow for each platform)
CMake changes:
- Add macOS cross-compile support (VulkanHeaders, -undefined dynamic_lookup)
- Add LLVM-MinGW/Windows cross-compile support
- Detect osxcross toolchain and vcpkg triplets
Other:
- Update vcpkg.json with ffmpeg feature flags
- Update resources/wowee.rc version string
2026-03-30 20:17:41 +03:00
INTERFACE_LINK_LIBRARIES vulkan-1)
endif()
set(Vulkan_FOUND TRUE)
message(STATUS "Found Vulkan headers for Windows cross-compile via vcpkg VulkanHeaders")
else()
# Last-resort: check the LLVM-MinGW toolchain sysroot directly.
find_path(_VULKAN_MINGW_INCLUDE NAMES vulkan/vulkan.h
PATHS /opt/llvm-mingw/x86_64-w64-mingw32/include NO_DEFAULT_PATH)
if(_VULKAN_MINGW_INCLUDE)
if(NOT TARGET Vulkan::Vulkan)
add_library(Vulkan::Vulkan INTERFACE IMPORTED)
endif()
set_target_properties(Vulkan::Vulkan PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${_VULKAN_MINGW_INCLUDE}")
# Link against the Vulkan loader import library (vulkan-1.dll).
if(EXISTS "${_VULKAN_IMPORT_DIR}/libvulkan-1.a")
set_property(TARGET Vulkan::Vulkan APPEND PROPERTY
INTERFACE_LINK_DIRECTORIES "${_VULKAN_IMPORT_DIR}")
set_property(TARGET Vulkan::Vulkan APPEND PROPERTY
INTERFACE_LINK_LIBRARIES vulkan-1)
endif()
set(Vulkan_FOUND TRUE)
message(STATUS "Found Vulkan headers in LLVM-MinGW sysroot: ${_VULKAN_MINGW_INCLUDE}")
endif()
endif()
elseif(CMAKE_CROSSCOMPILING AND CMAKE_SYSTEM_NAME STREQUAL "Darwin")
# macOS cross-compilation: use vcpkg-installed vulkan-headers.
# The host pkg-config would find Linux libvulkan-dev headers which the
# macOS cross-compiler cannot use (different sysroot).
find_package(VulkanHeaders CONFIG QUIET)
if(VulkanHeaders_FOUND)
if(NOT TARGET Vulkan::Vulkan)
add_library(Vulkan::Vulkan INTERFACE IMPORTED)
2026-02-23 18:47:42 -08:00
endif()
feat: add multi-platform Docker build system for Linux, macOS, and Windows
Replace the single Ubuntu-based container build with a dedicated
Dockerfile, build script, and launcher for each target platform.
Infrastructure:
- Add .dockerignore to minimize Docker build context
- Add container/builder-linux.Dockerfile (Ubuntu 24.04, GCC, native build)
- Add container/builder-macos.Dockerfile (multi-stage: SDK fetcher + osxcross/Clang 18)
- Add container/builder-windows.Dockerfile (LLVM-MinGW 20240619, vcpkg)
- Add container/macos/sdk-fetcher.py (auto-fetch macOS SDK from Apple catalog)
- Add container/macos/osxcross-toolchain.cmake (auto-detecting CMake toolchain)
- Add container/macos/triplets/arm64-osx-cross.cmake
- Add container/macos/triplets/x64-osx-cross.cmake
- Remove container/builder-ubuntu.Dockerfile (replaced by per-platform Dockerfiles)
- Remove container/build-in-container.sh and container/build-wowee.sh (replaced)
Build scripts (run inside containers):
- Add container/build-linux.sh (tar copy, FidelityFX clone, cmake/ninja)
- Add container/build-macos.sh (arch detection, vcpkg triplet, cross-compile)
- Add container/build-windows.sh (Vulkan import lib via dlltool, cross-compile)
Launcher scripts (run on host):
- Add container/run-linux.sh, run-macos.sh, run-windows.sh (bash)
- Add container/run-linux.ps1, run-macos.ps1, run-windows.ps1 (PowerShell)
Documentation:
- Add container/README.md (quick start, options, file structure, troubleshooting)
- Add container/FLOW.md (comprehensive build flow for each platform)
CMake changes:
- Add macOS cross-compile support (VulkanHeaders, -undefined dynamic_lookup)
- Add LLVM-MinGW/Windows cross-compile support
- Detect osxcross toolchain and vcpkg triplets
Other:
- Update vcpkg.json with ffmpeg feature flags
- Update resources/wowee.rc version string
2026-03-30 20:17:41 +03:00
set_property(TARGET Vulkan::Vulkan APPEND PROPERTY
INTERFACE_LINK_LIBRARIES Vulkan::Headers)
2026-02-23 18:47:42 -08:00
set(Vulkan_FOUND TRUE)
feat: add multi-platform Docker build system for Linux, macOS, and Windows
Replace the single Ubuntu-based container build with a dedicated
Dockerfile, build script, and launcher for each target platform.
Infrastructure:
- Add .dockerignore to minimize Docker build context
- Add container/builder-linux.Dockerfile (Ubuntu 24.04, GCC, native build)
- Add container/builder-macos.Dockerfile (multi-stage: SDK fetcher + osxcross/Clang 18)
- Add container/builder-windows.Dockerfile (LLVM-MinGW 20240619, vcpkg)
- Add container/macos/sdk-fetcher.py (auto-fetch macOS SDK from Apple catalog)
- Add container/macos/osxcross-toolchain.cmake (auto-detecting CMake toolchain)
- Add container/macos/triplets/arm64-osx-cross.cmake
- Add container/macos/triplets/x64-osx-cross.cmake
- Remove container/builder-ubuntu.Dockerfile (replaced by per-platform Dockerfiles)
- Remove container/build-in-container.sh and container/build-wowee.sh (replaced)
Build scripts (run inside containers):
- Add container/build-linux.sh (tar copy, FidelityFX clone, cmake/ninja)
- Add container/build-macos.sh (arch detection, vcpkg triplet, cross-compile)
- Add container/build-windows.sh (Vulkan import lib via dlltool, cross-compile)
Launcher scripts (run on host):
- Add container/run-linux.sh, run-macos.sh, run-windows.sh (bash)
- Add container/run-linux.ps1, run-macos.ps1, run-windows.ps1 (PowerShell)
Documentation:
- Add container/README.md (quick start, options, file structure, troubleshooting)
- Add container/FLOW.md (comprehensive build flow for each platform)
CMake changes:
- Add macOS cross-compile support (VulkanHeaders, -undefined dynamic_lookup)
- Add LLVM-MinGW/Windows cross-compile support
- Detect osxcross toolchain and vcpkg triplets
Other:
- Update vcpkg.json with ffmpeg feature flags
- Update resources/wowee.rc version string
2026-03-30 20:17:41 +03:00
message(STATUS "Found Vulkan headers for macOS cross-compile via vcpkg VulkanHeaders")
endif()
else()
# Fallback: some distros / CMake versions need pkg-config to locate Vulkan.
find_package(PkgConfig QUIET)
if(PkgConfig_FOUND)
pkg_check_modules(VULKAN_PKG vulkan)
if(VULKAN_PKG_FOUND)
add_library(Vulkan::Vulkan INTERFACE IMPORTED)
set_target_properties(Vulkan::Vulkan PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${VULKAN_PKG_INCLUDE_DIRS}"
INTERFACE_LINK_LIBRARIES "${VULKAN_PKG_LIBRARIES}"
)
if(VULKAN_PKG_LIBRARY_DIRS)
set_property(TARGET Vulkan::Vulkan APPEND PROPERTY
INTERFACE_LINK_DIRECTORIES "${VULKAN_PKG_LIBRARY_DIRS}")
endif()
set(Vulkan_FOUND TRUE)
message(STATUS "Found Vulkan via pkg-config: ${VULKAN_PKG_LIBRARIES}")
endif()
2026-02-23 18:47:42 -08:00
endif()
endif()
if(NOT Vulkan_FOUND)
message(FATAL_ERROR "Could not find Vulkan. Install libvulkan-dev (Linux), vulkan-loader (macOS), or the Vulkan SDK (Windows).")
endif()
endif()
feat: add multi-platform Docker build system for Linux, macOS, and Windows
Replace the single Ubuntu-based container build with a dedicated
Dockerfile, build script, and launcher for each target platform.
Infrastructure:
- Add .dockerignore to minimize Docker build context
- Add container/builder-linux.Dockerfile (Ubuntu 24.04, GCC, native build)
- Add container/builder-macos.Dockerfile (multi-stage: SDK fetcher + osxcross/Clang 18)
- Add container/builder-windows.Dockerfile (LLVM-MinGW 20240619, vcpkg)
- Add container/macos/sdk-fetcher.py (auto-fetch macOS SDK from Apple catalog)
- Add container/macos/osxcross-toolchain.cmake (auto-detecting CMake toolchain)
- Add container/macos/triplets/arm64-osx-cross.cmake
- Add container/macos/triplets/x64-osx-cross.cmake
- Remove container/builder-ubuntu.Dockerfile (replaced by per-platform Dockerfiles)
- Remove container/build-in-container.sh and container/build-wowee.sh (replaced)
Build scripts (run inside containers):
- Add container/build-linux.sh (tar copy, FidelityFX clone, cmake/ninja)
- Add container/build-macos.sh (arch detection, vcpkg triplet, cross-compile)
- Add container/build-windows.sh (Vulkan import lib via dlltool, cross-compile)
Launcher scripts (run on host):
- Add container/run-linux.sh, run-macos.sh, run-windows.sh (bash)
- Add container/run-linux.ps1, run-macos.ps1, run-windows.ps1 (PowerShell)
Documentation:
- Add container/README.md (quick start, options, file structure, troubleshooting)
- Add container/FLOW.md (comprehensive build flow for each platform)
CMake changes:
- Add macOS cross-compile support (VulkanHeaders, -undefined dynamic_lookup)
- Add LLVM-MinGW/Windows cross-compile support
- Detect osxcross toolchain and vcpkg triplets
Other:
- Update vcpkg.json with ffmpeg feature flags
- Update resources/wowee.rc version string
2026-03-30 20:17:41 +03:00
# macOS cross-compilation: the Vulkan loader (MoltenVK) is not available at link
# time. Allow unresolved Vulkan symbols — they are resolved at runtime.
if(CMAKE_CROSSCOMPILING AND CMAKE_SYSTEM_NAME STREQUAL "Darwin")
2026-03-30 13:40:40 -07:00
set(WOWEE_MACOS_CROSS_COMPILE TRUE)
feat: add multi-platform Docker build system for Linux, macOS, and Windows
Replace the single Ubuntu-based container build with a dedicated
Dockerfile, build script, and launcher for each target platform.
Infrastructure:
- Add .dockerignore to minimize Docker build context
- Add container/builder-linux.Dockerfile (Ubuntu 24.04, GCC, native build)
- Add container/builder-macos.Dockerfile (multi-stage: SDK fetcher + osxcross/Clang 18)
- Add container/builder-windows.Dockerfile (LLVM-MinGW 20240619, vcpkg)
- Add container/macos/sdk-fetcher.py (auto-fetch macOS SDK from Apple catalog)
- Add container/macos/osxcross-toolchain.cmake (auto-detecting CMake toolchain)
- Add container/macos/triplets/arm64-osx-cross.cmake
- Add container/macos/triplets/x64-osx-cross.cmake
- Remove container/builder-ubuntu.Dockerfile (replaced by per-platform Dockerfiles)
- Remove container/build-in-container.sh and container/build-wowee.sh (replaced)
Build scripts (run inside containers):
- Add container/build-linux.sh (tar copy, FidelityFX clone, cmake/ninja)
- Add container/build-macos.sh (arch detection, vcpkg triplet, cross-compile)
- Add container/build-windows.sh (Vulkan import lib via dlltool, cross-compile)
Launcher scripts (run on host):
- Add container/run-linux.sh, run-macos.sh, run-windows.sh (bash)
- Add container/run-linux.ps1, run-macos.ps1, run-windows.ps1 (PowerShell)
Documentation:
- Add container/README.md (quick start, options, file structure, troubleshooting)
- Add container/FLOW.md (comprehensive build flow for each platform)
CMake changes:
- Add macOS cross-compile support (VulkanHeaders, -undefined dynamic_lookup)
- Add LLVM-MinGW/Windows cross-compile support
- Detect osxcross toolchain and vcpkg triplets
Other:
- Update vcpkg.json with ffmpeg feature flags
- Update resources/wowee.rc version string
2026-03-30 20:17:41 +03:00
endif()
2026-02-02 12:24:50 -08:00
find_package(OpenSSL REQUIRED)
find_package(Threads REQUIRED)
2026-02-05 21:03:27 -08:00
find_package(ZLIB REQUIRED)
2026-02-18 17:38:08 -08:00
if(WIN32)
find_package(PkgConfig QUIET)
else()
find_package(PkgConfig REQUIRED)
endif()
if(PkgConfig_FOUND)
2026-02-23 16:30:49 +01:00
pkg_check_modules(FFMPEG libavformat libavcodec libswscale libavutil)
2026-02-18 17:38:08 -08:00
else()
# Fallback for MSVC/vcpkg — find FFmpeg libraries manually
find_path(FFMPEG_INCLUDE_DIRS libavformat/avformat.h)
find_library(AVFORMAT_LIB NAMES avformat)
find_library(AVCODEC_LIB NAMES avcodec)
find_library(AVUTIL_LIB NAMES avutil)
find_library(SWSCALE_LIB NAMES swscale)
set(FFMPEG_LIBRARIES ${AVFORMAT_LIB} ${AVCODEC_LIB} ${AVUTIL_LIB} ${SWSCALE_LIB})
2026-02-23 16:30:49 +01:00
endif()
if(FFMPEG_INCLUDE_DIRS AND AVFORMAT_LIB)
set(HAVE_FFMPEG TRUE)
message(STATUS "Found FFmpeg: ${AVFORMAT_LIB}")
elseif(FFMPEG_FOUND)
set(HAVE_FFMPEG TRUE)
else()
set(HAVE_FFMPEG FALSE)
message(WARNING "FFmpeg not found — video_player will be disabled. Install via vcpkg: ffmpeg:x64-windows")
2026-02-18 17:38:08 -08:00
endif()
2026-02-02 12:24:50 -08:00
2026-02-12 03:01:36 -08:00
# Unicorn Engine (x86 emulator for cross-platform Warden module execution)
find_library(UNICORN_LIBRARY NAMES unicorn)
find_path(UNICORN_INCLUDE_DIR unicorn/unicorn.h)
if(NOT UNICORN_LIBRARY OR NOT UNICORN_INCLUDE_DIR)
message(WARNING "Unicorn Engine not found. Install with: sudo apt-get install libunicorn-dev")
message(WARNING "Warden emulation will be disabled")
set(HAVE_UNICORN FALSE)
else()
message(STATUS "Found Unicorn Engine: ${UNICORN_LIBRARY}")
set(HAVE_UNICORN TRUE)
endif()
2026-02-02 12:24:50 -08:00
# GLM (header-only math library)
find_package(glm QUIET)
if(NOT glm_FOUND)
message(STATUS "GLM not found, will use system includes or download")
endif()
2026-02-18 17:49:52 -08:00
# GLM GTX extensions (quaternion, norm, etc.) require this flag on newer GLM versions
2026-02-21 19:41:21 -08:00
add_compile_definitions(GLM_ENABLE_EXPERIMENTAL GLM_FORCE_DEPTH_ZERO_TO_ONE)
2026-02-23 16:30:49 +01:00
if(WIN32)
add_compile_definitions(NOMINMAX _CRT_SECURE_NO_WARNINGS)
endif()
2026-02-21 19:41:21 -08:00
# SPIR-V shader compilation via glslc
find_program(GLSLC glslc HINTS ${Vulkan_GLSLC_EXECUTABLE} "$ENV{VULKAN_SDK}/bin")
if(GLSLC)
message(STATUS "Found glslc: ${GLSLC}")
else()
message(WARNING "glslc not found. Install the Vulkan SDK or vulkan-tools package.")
message(WARNING "Shaders will not be compiled to SPIR-V.")
endif()
# Function to compile GLSL shaders to SPIR-V
function(compile_shaders TARGET_NAME)
set(SHADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/assets/shaders)
set(SPV_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/assets/shaders)
file(MAKE_DIRECTORY ${SPV_DIR})
file(GLOB GLSL_SOURCES "${SHADER_DIR}/*.glsl")
set(SPV_OUTPUTS)
foreach(GLSL_FILE ${GLSL_SOURCES})
get_filename_component(FILE_NAME ${GLSL_FILE} NAME)
# e.g. skybox.vert.glsl -> skybox.vert.spv
string(REGEX REPLACE "\\.glsl$" ".spv" SPV_NAME ${FILE_NAME})
set(SPV_FILE ${SPV_DIR}/${SPV_NAME})
# Determine shader stage from filename
if(FILE_NAME MATCHES "\\.vert\\.glsl$")
set(SHADER_STAGE vertex)
elseif(FILE_NAME MATCHES "\\.frag\\.glsl$")
set(SHADER_STAGE fragment)
elseif(FILE_NAME MATCHES "\\.comp\\.glsl$")
set(SHADER_STAGE compute)
elseif(FILE_NAME MATCHES "\\.geom\\.glsl$")
set(SHADER_STAGE geometry)
else()
message(WARNING "Cannot determine shader stage for: ${FILE_NAME}")
continue()
endif()
add_custom_command(
OUTPUT ${SPV_FILE}
COMMAND ${GLSLC} -fshader-stage=${SHADER_STAGE} -O ${GLSL_FILE} -o ${SPV_FILE}
DEPENDS ${GLSL_FILE}
COMMENT "Compiling SPIR-V: ${FILE_NAME} -> ${SPV_NAME}"
VERBATIM
)
list(APPEND SPV_OUTPUTS ${SPV_FILE})
endforeach()
add_custom_target(${TARGET_NAME}_shaders ALL DEPENDS ${SPV_OUTPUTS})
add_dependencies(${TARGET_NAME} ${TARGET_NAME}_shaders)
endfunction()
2026-02-02 12:24:50 -08:00
2026-02-12 20:32:14 -08:00
# StormLib for MPQ extraction tool (not needed for main executable)
2026-02-02 12:24:50 -08:00
find_library(STORMLIB_LIBRARY NAMES StormLib stormlib storm)
find_path(STORMLIB_INCLUDE_DIR StormLib.h PATH_SUFFIXES StormLib)
2026-02-21 19:41:21 -08:00
# Include ImGui as a static library (Vulkan backend)
2026-02-02 12:24:50 -08:00
set(IMGUI_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/imgui)
if(EXISTS ${IMGUI_DIR})
add_library(imgui STATIC
${IMGUI_DIR}/imgui.cpp
${IMGUI_DIR}/imgui_draw.cpp
${IMGUI_DIR}/imgui_tables.cpp
${IMGUI_DIR}/imgui_widgets.cpp
${IMGUI_DIR}/imgui_demo.cpp
${IMGUI_DIR}/backends/imgui_impl_sdl2.cpp
2026-02-21 19:41:21 -08:00
${IMGUI_DIR}/backends/imgui_impl_vulkan.cpp
2026-02-02 12:24:50 -08:00
)
target_include_directories(imgui PUBLIC
${IMGUI_DIR}
${IMGUI_DIR}/backends
)
2026-02-21 19:41:21 -08:00
target_link_libraries(imgui PUBLIC SDL2::SDL2 Vulkan::Vulkan ${CMAKE_DL_LIBS})
2026-02-02 12:24:50 -08:00
else()
message(WARNING "ImGui not found in extern/imgui. Clone it with:")
message(WARNING " git clone https://github.com/ocornut/imgui.git extern/imgui")
endif()
2026-02-21 19:41:21 -08:00
# vk-bootstrap (Vulkan device/instance setup)
set(VK_BOOTSTRAP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/vk-bootstrap)
if(EXISTS ${VK_BOOTSTRAP_DIR})
add_library(vk-bootstrap STATIC
${VK_BOOTSTRAP_DIR}/src/VkBootstrap.cpp
)
target_include_directories(vk-bootstrap PUBLIC ${VK_BOOTSTRAP_DIR}/src)
target_link_libraries(vk-bootstrap PUBLIC Vulkan::Vulkan)
else()
message(FATAL_ERROR "vk-bootstrap not found in extern/vk-bootstrap")
endif()
2026-02-02 12:24:50 -08:00
# Source files
set(WOWEE_SOURCES
# Core
src/core/application.cpp
2026-03-31 22:01:55 +03:00
src/core/entity_spawner.cpp
2026-04-05 19:30:44 +03:00
src/core/entity_spawner_player.cpp
src/core/entity_spawner_processing.cpp
2026-04-01 13:31:48 +03:00
src/core/appearance_composer.cpp
2026-04-01 20:06:26 +03:00
src/core/world_loader.cpp
refactor(core): decompose Application::setupUICallbacks() into 7 domain handlers
Extract ~1,700 lines / 60+ inline [this]-capturing lambdas from the monolithic
Application::setupUICallbacks() into 7 focused callback handler classes following
the ToastManager/ChatPanel::setupCallbacks() pattern already in the codebase.
New handlers (include/core/ + src/core/):
- NPCInteractionCallbackHandler NPC greeting/farewell/vendor/aggro voice
- AudioCallbackHandler Music, positional sound, level-up, achievement, LFG
- EntitySpawnCallbackHandler Creature/player/GO spawn, despawn, move, state
- AnimationCallbackHandler Death, respawn, combat, emotes, charge, sprint, vehicle
- TransportCallbackHandler Mount, taxi, transport spawn/move
- WorldEntryCallbackHandler World entry, unstuck, hearthstone, bind point
- UIScreenCallbackHandler Auth, realm selection, char selection/creation/deletion
application.cpp: 4,462 → 2,791 lines (−1,671)
setupUICallbacks: ~1,700 → ~50 lines (thin orchestrator)
Deduplication:
resolveSoundEntryPath() — was 3× copy-paste of SoundEntries.dbc lookup
resolveNpcVoiceType() — was 4× copy-paste of display-ID→voice detection
precacheNearbyTiles() — was 3× copy-paste of 17×17 tile loop
4 helper lambdas — promoted to private methods on WorldEntryCallbackHandler
State migration out of Application:
charge* (6 vars) → AnimationCallbackHandler
hearth*/worldEntry*/taxi* → WorldEntryCallbackHandler
pendingCreatedCharacterName_ → UIScreenCallbackHandler
Bug fixes:
- Duplicate `namespace core {` in application.hpp caused wowee::std pollution
- AppState forward decl in ui_screen_callback_handler.hpp was at wrong scope
- world_loader.cpp accessed moved member vars directly via friend; now uses handler API
2026-04-05 16:48:17 +03:00
src/core/npc_interaction_callback_handler.cpp
src/core/audio_callback_handler.cpp
src/core/entity_spawn_callback_handler.cpp
src/core/animation_callback_handler.cpp
src/core/transport_callback_handler.cpp
src/core/world_entry_callback_handler.cpp
src/core/ui_screen_callback_handler.cpp
2026-02-02 12:24:50 -08:00
src/core/window.cpp
src/core/input.cpp
src/core/logger.cpp
2026-02-08 23:15:26 -08:00
src/core/memory_monitor.cpp
2026-02-02 12:24:50 -08:00
refactor: extract spline math, consolidate packet parsing, decompose TransportManager
Extract CatmullRomSpline (include/math/spline.hpp, src/math/spline.cpp) as a
standalone, immutable, thread-safe spline module with O(log n) binary segment
search and fused position+tangent evaluation — replacing the duplicated O(n)
evalTimedCatmullRom/orientationFromTangent pair in TransportManager.
Consolidate 7 copies of spline packet parsing into shared functions in
game/spline_packet.{hpp,cpp}: parseMonsterMoveSplineBody (WotLK/TBC),
parseMonsterMoveSplineBodyVanilla, parseClassicMoveUpdateSpline,
parseWotlkMoveUpdateSpline, and decodePackedDelta. Named SplineFlag constants
replace magic hex literals throughout.
Extract TransportPathRepository (game/transport_path_repository.{hpp,cpp}) from
TransportManager — owns path data, DBC loading, and path inference. Paths stored
as PathEntry wrapping CatmullRomSpline + metadata (zOnly, fromDBC, worldCoords).
TransportManager reduced from ~1200 to ~500 lines, focused on transport lifecycle
and server sync.
Signed-off-by: Pavel Okhlopkov <pavel.okhlopkov@flant.com>
2026-04-11 08:30:28 +03:00
# Math
src/math/spline.cpp
2026-02-02 12:24:50 -08:00
# Network
src/network/socket.cpp
src/network/packet.cpp
src/network/tcp_socket.cpp
src/network/world_socket.cpp
# Auth
src/auth/auth_handler.cpp
src/auth/auth_opcodes.cpp
src/auth/auth_packets.cpp
2026-02-13 00:22:01 -08:00
src/auth/pin_auth.cpp
2026-02-13 01:32:15 -08:00
src/auth/integrity.cpp
2026-02-02 12:24:50 -08:00
src/auth/srp.cpp
src/auth/big_num.cpp
src/auth/crypto.cpp
src/auth/rc4.cpp
2026-02-13 16:53:28 -08:00
src/auth/vanilla_crypt.cpp
2026-02-02 12:24:50 -08:00
# Game
2026-02-12 22:56:36 -08:00
src/game/expansion_profile.cpp
src/game/opcode_table.cpp
src/game/update_field_table.cpp
2026-02-02 12:24:50 -08:00
src/game/game_handler.cpp
2026-04-05 19:30:44 +03:00
src/game/game_handler_packets.cpp
src/game/game_handler_callbacks.cpp
refactor(game): split GameHandler into domain handlers
Extract domain-specific logic from the monolithic GameHandler into
dedicated handler classes, each owning its own opcode registration,
state, and packet parsing:
- CombatHandler: combat, XP, kill, PvP, loot roll (~26 methods)
- SpellHandler: spells, auras, pet stable, talent (~3+ methods)
- SocialHandler: friends, guild, groups, BG, RAF, PvP AFK (~14+ methods)
- ChatHandler: chat messages, channels, GM tickets, server messages,
defense/area-trigger messages (~7+ methods)
- InventoryHandler: items, trade, loot, mail, vendor, equipment sets,
read item (~3+ methods)
- QuestHandler: gossip, quests, completed quest response (~5+ methods)
- MovementHandler: movement, follow, transport (~2 methods)
- WardenHandler: Warden anti-cheat module
Each handler registers its own dispatch table entries via
registerOpcodes(DispatchTable&), called from
GameHandler::registerOpcodeHandlers(). GameHandler retains core
orchestration: auth/session handshake, update-object parsing,
opcode routing, and cross-handler coordination.
game_handler.cpp reduced from ~10,188 to ~9,432 lines.
Also add a POST_BUILD CMake step to symlink Data/ next to the
executable so expansion profiles and opcode tables are found at
runtime when running from build/bin/.
2026-03-28 09:42:37 +03:00
src/game/chat_handler.cpp
src/game/movement_handler.cpp
src/game/combat_handler.cpp
src/game/spell_handler.cpp
src/game/inventory_handler.cpp
src/game/social_handler.cpp
src/game/quest_handler.cpp
refactor(game): extract EntityController from GameHandler (step 1.3)
Moves entity lifecycle, name/creature/game-object caches, transport GUID
tracking, and the entire update-object pipeline out of GameHandler into a
new EntityController class (friend-class pattern, same as CombatHandler
et al.).
What moved:
- applyUpdateObjectBlock() — 1,520-line core of all entity creation,
field updates, and movement application
- processOutOfRangeObjects() / finalizeUpdateObjectBatch()
- handleUpdateObject() / handleCompressedUpdateObject() / handleDestroyObject()
- handleNameQueryResponse() / handleCreatureQueryResponse()
- handleGameObjectQueryResponse() / handleGameObjectPageText()
- handlePageTextQueryResponse()
- enqueueUpdateObjectWork() / processPendingUpdateObjectWork()
- playerNameCache, playerClassRaceCache_, pendingNameQueries
- creatureInfoCache, pendingCreatureQueries
- gameObjectInfoCache_, pendingGameObjectQueries_
- transportGuids_, serverUpdatedTransportGuids_
- EntityManager (accessed by other handlers via getEntityManager())
8 opcodes re-registered by EntityController::registerOpcodes():
SMSG_UPDATE_OBJECT, SMSG_COMPRESSED_UPDATE_OBJECT, SMSG_DESTROY_OBJECT,
SMSG_NAME_QUERY_RESPONSE, SMSG_CREATURE_QUERY_RESPONSE,
SMSG_GAMEOBJECT_QUERY_RESPONSE, SMSG_GAMEOBJECT_PAGETEXT,
SMSG_PAGE_TEXT_QUERY_RESPONSE
Other handler files (combat, movement, social, spell, inventory, quest,
chat) updated to access EntityManager via getEntityManager() and the
name cache via getPlayerNameCache() — no logic changes.
Also included:
- .clang-tidy: add modernize-use-nodiscard,
modernize-use-designated-initializers; set -std=c++20 in ExtraArgs
- test.sh: prepend clang's own resource include dir before GCC's to
silence xmmintrin.h / ia32intrin.h conflicts during clang-tidy runs
Line counts:
entity_controller.hpp 147 lines (new)
entity_controller.cpp 2172 lines (new)
game_handler.cpp 8095 lines (was 10143, −2048)
Build: 0 errors, 0 warnings.
2026-03-29 08:21:27 +03:00
src/game/entity_controller.cpp
refactor(game): split GameHandler into domain handlers
Extract domain-specific logic from the monolithic GameHandler into
dedicated handler classes, each owning its own opcode registration,
state, and packet parsing:
- CombatHandler: combat, XP, kill, PvP, loot roll (~26 methods)
- SpellHandler: spells, auras, pet stable, talent (~3+ methods)
- SocialHandler: friends, guild, groups, BG, RAF, PvP AFK (~14+ methods)
- ChatHandler: chat messages, channels, GM tickets, server messages,
defense/area-trigger messages (~7+ methods)
- InventoryHandler: items, trade, loot, mail, vendor, equipment sets,
read item (~3+ methods)
- QuestHandler: gossip, quests, completed quest response (~5+ methods)
- MovementHandler: movement, follow, transport (~2 methods)
- WardenHandler: Warden anti-cheat module
Each handler registers its own dispatch table entries via
registerOpcodes(DispatchTable&), called from
GameHandler::registerOpcodeHandlers(). GameHandler retains core
orchestration: auth/session handshake, update-object parsing,
opcode routing, and cross-handler coordination.
game_handler.cpp reduced from ~10,188 to ~9,432 lines.
Also add a POST_BUILD CMake step to symlink Data/ next to the
executable so expansion profiles and opcode tables are found at
runtime when running from build/bin/.
2026-03-28 09:42:37 +03:00
src/game/warden_handler.cpp
2026-02-12 02:09:15 -08:00
src/game/warden_crypto.cpp
2026-02-12 02:43:20 -08:00
src/game/warden_module.cpp
2026-02-12 03:01:36 -08:00
src/game/warden_emulator.cpp
2026-02-14 02:00:15 -08:00
src/game/warden_memory.cpp
2026-02-10 21:29:10 -08:00
src/game/transport_manager.cpp
refactor: extract spline math, consolidate packet parsing, decompose TransportManager
Extract CatmullRomSpline (include/math/spline.hpp, src/math/spline.cpp) as a
standalone, immutable, thread-safe spline module with O(log n) binary segment
search and fused position+tangent evaluation — replacing the duplicated O(n)
evalTimedCatmullRom/orientationFromTangent pair in TransportManager.
Consolidate 7 copies of spline packet parsing into shared functions in
game/spline_packet.{hpp,cpp}: parseMonsterMoveSplineBody (WotLK/TBC),
parseMonsterMoveSplineBodyVanilla, parseClassicMoveUpdateSpline,
parseWotlkMoveUpdateSpline, and decodePackedDelta. Named SplineFlag constants
replace magic hex literals throughout.
Extract TransportPathRepository (game/transport_path_repository.{hpp,cpp}) from
TransportManager — owns path data, DBC loading, and path inference. Paths stored
as PathEntry wrapping CatmullRomSpline + metadata (zOnly, fromDBC, worldCoords).
TransportManager reduced from ~1200 to ~500 lines, focused on transport lifecycle
and server sync.
Signed-off-by: Pavel Okhlopkov <pavel.okhlopkov@flant.com>
2026-04-11 08:30:28 +03:00
src/game/transport_path_repository.cpp
2026-04-11 09:50:38 +03:00
src/game/transport_clock_sync.cpp
src/game/transport_animator.cpp
2026-02-02 12:24:50 -08:00
src/game/world.cpp
src/game/player.cpp
src/game/entity.cpp
src/game/opcodes.cpp
src/game/world_packets.cpp
2026-04-05 19:30:44 +03:00
src/game/world_packets_social.cpp
src/game/world_packets_entity.cpp
src/game/world_packets_world.cpp
src/game/world_packets_economy.cpp
refactor: extract spline math, consolidate packet parsing, decompose TransportManager
Extract CatmullRomSpline (include/math/spline.hpp, src/math/spline.cpp) as a
standalone, immutable, thread-safe spline module with O(log n) binary segment
search and fused position+tangent evaluation — replacing the duplicated O(n)
evalTimedCatmullRom/orientationFromTangent pair in TransportManager.
Consolidate 7 copies of spline packet parsing into shared functions in
game/spline_packet.{hpp,cpp}: parseMonsterMoveSplineBody (WotLK/TBC),
parseMonsterMoveSplineBodyVanilla, parseClassicMoveUpdateSpline,
parseWotlkMoveUpdateSpline, and decodePackedDelta. Named SplineFlag constants
replace magic hex literals throughout.
Extract TransportPathRepository (game/transport_path_repository.{hpp,cpp}) from
TransportManager — owns path data, DBC loading, and path inference. Paths stored
as PathEntry wrapping CatmullRomSpline + metadata (zOnly, fromDBC, worldCoords).
TransportManager reduced from ~1200 to ~500 lines, focused on transport lifecycle
and server sync.
Signed-off-by: Pavel Okhlopkov <pavel.okhlopkov@flant.com>
2026-04-11 08:30:28 +03:00
src/game/spline_packet.cpp
2026-02-12 22:56:36 -08:00
src/game/packet_parsers_tbc.cpp
src/game/packet_parsers_classic.cpp
2026-02-02 12:24:50 -08:00
src/game/character.cpp
src/game/zone_manager.cpp
src/game/inventory.cpp
# Audio
2026-02-09 00:40:50 -08:00
src/audio/audio_engine.cpp
2026-04-01 20:38:37 +03:00
src/audio/audio_coordinator.cpp
2026-02-02 12:24:50 -08:00
src/audio/music_manager.cpp
2026-02-03 14:55:32 -08:00
src/audio/footstep_manager.cpp
2026-02-03 19:49:56 -08:00
src/audio/activity_sound_manager.cpp
2026-02-09 01:04:53 -08:00
src/audio/mount_sound_manager.cpp
2026-02-09 01:29:44 -08:00
src/audio/npc_voice_manager.cpp
2026-02-09 14:50:14 -08:00
src/audio/ambient_sound_manager.cpp
2026-02-09 16:30:47 -08:00
src/audio/ui_sound_manager.cpp
2026-02-09 16:38:50 -08:00
src/audio/combat_sound_manager.cpp
Add comprehensive spell sound manager with 35+ magic sounds
Implemented complete spell casting audio system with all magic schools:
Magic schools supported:
- Fire: Precast (Low/Medium/High), Cast, Fireball impacts
- Frost: Precast (Low/Medium/High), Cast, Blizzard impacts
- Holy: Precast (Low/Medium/High), Cast, Holy impacts (4 levels)
- Nature: Precast (Low/Medium/High), Cast
- Shadow: Precast (Low/Medium/High), Cast
- Arcane: Precast, Arcane Missile impacts
- Physical: Non-magical abilities
Spell phases:
- Precast: Channeling/preparation sounds (before cast)
- Cast: Spell release sounds (when spell fires)
- Impact: Spell hit sounds (when spell hits target)
Power levels:
- Low: Weak spells, low level abilities
- Medium: Standard power spells
- High: Powerful high-level spells
Sound coverage (35+ sounds):
- 16 precast sounds (Fire/Frost/Holy/Nature/Shadow × Low/Med/High + Arcane)
- 5 cast sounds (one per school)
- 16 impact sounds (Fireball ×3, Blizzard ×6, Holy ×4, Arcane Missile ×3)
Technical details:
- Loads 35+ sound files from Sound\Spells directory
- Simple API: playPrecast(school, power), playCast(school), playImpact(school, power)
- Convenience methods: playFireball(), playFrostbolt(), playHeal(), etc.
- Random variation selection for impacts
- Volume at 0.75 with global scale control
- Ready for integration with spell casting system
Usage examples:
```cpp
// Full spell sequence
spellSoundManager->playPrecast(MagicSchool::FIRE, SpellPower::HIGH);
// ... cast time ...
spellSoundManager->playCast(MagicSchool::FIRE);
// ... projectile travel ...
spellSoundManager->playImpact(MagicSchool::FIRE, SpellPower::HIGH);
// Convenience methods
spellSoundManager->playFireball();
spellSoundManager->playHeal();
```
This adds essential magic feedback for spell casting gameplay!
2026-02-09 16:45:30 -08:00
src/audio/spell_sound_manager.cpp
2026-02-09 16:50:37 -08:00
src/audio/movement_sound_manager.cpp
2026-02-02 12:24:50 -08:00
# Pipeline (asset loaders)
src/pipeline/blp_loader.cpp
src/pipeline/dbc_loader.cpp
src/pipeline/asset_manager.cpp
2026-02-12 20:32:14 -08:00
src/pipeline/asset_manifest.cpp
src/pipeline/loose_file_reader.cpp
2026-02-02 12:24:50 -08:00
src/pipeline/m2_loader.cpp
src/pipeline/wmo_loader.cpp
src/pipeline/adt_loader.cpp
2026-02-26 17:56:11 -08:00
src/pipeline/wdt_loader.cpp
2026-05-05 09:56:24 -07:00
src/pipeline/wowee_terrain_loader.cpp
2026-05-05 10:24:46 -07:00
src/pipeline/wowee_model.cpp
2026-05-06 10:32:17 -07:00
src/pipeline/wowee_model_fromm2.cpp
2026-05-05 10:28:24 -07:00
src/pipeline/wowee_building.cpp
2026-05-05 15:23:58 -07:00
src/pipeline/wowee_collision.cpp
2026-05-09 13:52:07 -07:00
src/pipeline/wowee_light.cpp
feat(pipeline): add Wowee Open Weather (.wow) zone schedule
8th open-format addition to the Wowee pipeline. Replaces
WoW's WeatherTypes.dbc / WeatherEffect logic with a single
binary file holding a list of weather states for one zone,
each tagged with intensity bounds, a probability weight,
and duration bounds. The renderer / runtime samples one
entry at a time using weighted-random selection, drives
it for a uniform-random duration in [min, max] sec, then
re-rolls.
• Types: Clear / Rain / Snow / Storm / Sandstorm / Fog /
Blizzard (extensible enum).
• Binary format: magic "WOWA", version 1, name, N entries
each storing (typeId, minIntensity, maxIntensity, weight,
minDurationSec, maxDurationSec).
CLI:
• --info-wow <wow-base> [--json] — inspect a WOW
• --gen-weather-temperate — clear + rain + fog (forest)
• --gen-weather-arctic — snow + blizzard + fog (tundra)
• --gen-weather-desert — clear + sandstorm (dunes)
• --gen-weather-stormy — rain + storm + occasional clear
The 8th open format complementing the rest:
M2 → WOM | WMO → WOB | WMO collision → WOC | ADT → WOT
DBC → JsonDBC | BLP → PNG | Light.dbc → WOL | WeatherTypes.dbc → WOW
Smoke-tested all 4 presets + JSON output. Each preset reads
back identically with the expected entry count and weight
distribution.
2026-05-09 14:10:13 -07:00
src/pipeline/wowee_weather.cpp
2026-05-09 14:38:05 -07:00
src/pipeline/wowee_world_map.cpp
feat(pipeline): add WSND (Wowee Sound Catalog) format
Novel open replacement for Blizzard's SoundEntries.dbc +
SoundEntriesAdvanced.dbc. The 10th open format added to the
editor — covers the audio-metadata gap (the previous 9 cover
geometry, terrain, atmosphere, and world manifests, but no
sound metadata).
Format:
• magic "WSND", version 1, little-endian
• catalogName + entry count
• per entry: soundId / kind / flags / volume /
minDistance / maxDistance / filePath / label
Kind enum (7 categories):
sfx, music, ambient, ui, voice, spell, combat
Flags packed (3 bits used, rest reserved):
loop (0x01), 3d (0x02), stream (0x04)
API: WoweeSoundLoader::save / load / exists; presets
makeStarter (one entry per kind), makeAmbient (wilderness
loops + footsteps), makeTavern (fire + crowd + drink + door
+ lute).
CLI added (5 flags, 465 documented total now):
--gen-sound-catalog <base> [name]
--gen-sound-catalog-ambient <base> [name]
--gen-sound-catalog-tavern <base> [name]
--info-wsnd <base> [--json]
--validate-wsnd <base> [--json]
Validator catches: out-of-range kind, NaN/inf volume or
distances, 3D sounds with bad min/max, duplicate sound IDs,
empty filePaths.
All 3 presets verified: save / load / validate clean
on first run. Variable-length string fields use length-
prefixed encoding with a 1 MiB sanity cap on read to
prevent corrupted-file allocation blowups.
2026-05-09 14:47:16 -07:00
src/pipeline/wowee_sound.cpp
feat(pipeline): add WSPN (Wowee Spawn Point catalog) format
Novel open replacement for AzerothCore-style scattered
creature_template / gameobject SQL spawn tables PLUS the
ADT MDDF / MODF doodad-placement chunks. The 11th open
format, and the first that covers the live world-content
side (atmosphere + sounds + spawns now form the runtime
"what fills this zone" picture).
A WSPN file holds all spawn points for a zone in a single
table, with kind discriminating creature vs game object
vs static doodad. The same format powers:
• server runtime — knows what NPCs / objects to spawn
• editor — draws spawn markers
• renderer — reads the doodad subset directly to
draw static props without going
through a server roundtrip
Format:
• magic "WSPN", version 1, little-endian
• per entry: kind / entryId / position(3f) / rotation(3f)
/ scale / flags / respawnSec / factionId /
questIdRequired / wanderRadius / label
Flags packed: disabled (0x01), event-only (0x02),
quest-phased (0x04). Reserved bits for future per-entry
encoding extensions.
API: WoweeSpawnsLoader::save / load / exists; presets
makeStarter (1 each kind), makeCamp (4-bandit ring +
chest + 2 tents), makeVillage (6 NPCs + 2 signs + 4
corner trees).
CLI added (5 flags, 473 documented total now):
--gen-spawns / --gen-spawns-camp / --gen-spawns-village
--info-wspn / --validate-wspn
Validator catches: out-of-range kind, NaN/inf coords,
non-positive scale, doodad with non-zero respawn (static
prop misuse), creature with respawn=0 (won't respawn after
kill), entryId=0 (orphan reference).
All 3 presets save / load / re-validate clean. Doodad and
game-object entries explicitly set wanderRadius=0 so the
generated catalogs are noise-free.
2026-05-09 14:57:53 -07:00
src/pipeline/wowee_spawns.cpp
feat(pipeline): add WIT (Wowee Item Template) format
Novel open replacement for Blizzard's Item.dbc +
ItemDisplayInfo.dbc + the SQL item_template tables that
AzerothCore-style servers store item definitions in. The
12th open format added to the editor.
A WIT file holds the catalog of all items in a content
pack: weapons, armor, consumables, quest items, trade
goods. Each entry pairs gameplay metadata (stats, level
reqs, flags, weapon damage / speed) with display metadata
(displayId for icon / model, quality color), so the
runtime can render inventory tooltips and equip slots
from a single load.
Format:
• magic "WITM", version 1, little-endian
• per item: itemId / displayId / quality / itemClass /
itemSubClass / inventoryType / flags / requiredLevel /
itemLevel / sellPrice / buyPrice / maxStack / durability
/ damageMin / damageMax / attackSpeedMs /
statCount + stats[] / name / description
Enums:
• Quality: Poor..Heirloom (8 levels)
• Class: Consumable, Weapon, Armor, Quest, ... (13)
• InventoryType: Head..Cloak..Weapon2H (18 slots)
• Flags: Unique, BoP, BoE, QuestItem, Conjured, ...
• StatType: Stamina, Strength, Intellect, Defense, ...
API: WoweeItemLoader::save / load / exists / findById;
presets makeStarter (4-item demo), makeWeapons (5 items
common -> legendary), makeArmor (6-piece mail set with
BoE flag).
CLI added (5 flags, 480 documented total now):
--gen-items / --gen-items-weapons / --gen-items-armor
--info-wit / --validate-wit
Validator catches: itemId=0, duplicate itemIds, weapons
with 0 damage or attackSpeed, weapons with non-weapon
slot, equippables with durability=0 or maxStack>1, sell
price >= buy price (vendor would lose money), out-of-range
quality.
All 3 presets save / load / re-validate clean. Info-table
output includes a gold/silver/copper price formatter for
hand-readability.
2026-05-09 15:04:48 -07:00
src/pipeline/wowee_items.cpp
feat(pipeline): add WLOT (Wowee Loot Table) format
Novel open replacement for AzerothCore-style
creature_loot_template / gameobject_loot_template SQL
tables. The 13th open format added to the editor.
Pairs naturally with the WIT item catalog from the
preceding commit: each loot drop's itemId references an
entry in a WIT file, so a content pack ships both the
item definitions and the loot tables that reference them.
The runtime composes WIT + WLOT + WSPN to drive the full
"creature dies, drops items" flow without any SQL.
Format:
• magic "WLOT", version 1, little-endian
• per table: creatureId / flags / dropCount /
moneyMin..Max / itemDropCount + drops[]
• per drop: itemId / chancePercent (float, 0..100) /
minQty / maxQty / drop_flags
Table flags: QuestOnly, GroupOnly, Pickpocket
Drop flags: QuestRequired, GroupRollOnly, AlwaysDrop
dropCount is the slot budget — how many distinct drops
to roll per kill. Each item drop is rolled independently
against its chancePercent (so dropCount=2 with 4 candidate
drops at varying chances gives the classic "up to 2 distinct
items per kill" behavior). Drops with the AlwaysDrop flag
bypass the slot budget — used for guaranteed quest items.
API: WoweeLootLoader::save / load / exists /
findByCreatureId; presets makeStarter (1 table, 1 drop),
makeBandit (4 candidates, dropCount=2, matches the camp
spawns from WSPN at creatureId=1000), makeBoss (6 candidates
including guaranteed quest item via AlwaysDrop and a
group-only epic at 5%).
CLI added (5 flags, 486 documented total now):
--gen-loot / --gen-loot-bandit / --gen-loot-boss
--info-wlot / --validate-wlot
Validator catches: creatureId=0, duplicates, chance not in
0..100, NaN chance, money min > max, minQty > maxQty,
dropCount=0 with non-empty drops list (silent dead config).
All 3 presets save / load / re-validate clean. The bandit
table's creatureId=1000 deliberately matches WSPN's
makeCamp creatureId so the open-format demo content pack
already has working cross-references.
2026-05-09 15:11:08 -07:00
src/pipeline/wowee_loot.cpp
feat(pipeline): add WCRT (Wowee Creature Template) format
Novel open replacement for the AzerothCore-style
creature_template SQL table PLUS the Blizzard
CreatureTemplate / CreatureFamily / CreatureType.dbc trio.
The 14th open format added to the editor.
This is the canonical metadata side of creatures shared
across every spawn instance: HP, level range, faction,
behavior flags, NPC role bits (vendor / trainer /
quest-giver / innkeeper), base damage, equipped gear
references.
Cross-references with the previously-added formats:
WSPN.entry.entryId -> WCRT.entry.creatureId
WLOT.entry.creatureId -> WCRT.entry.creatureId
WCRT.entry.equipped* -> WIT.entry.itemId
The 4-format set (WIT + WLOT + WSPN + WCRT) now lets a
content pack define a complete RPG zone's creature
ecosystem: what creatures are, where they spawn, what they
drop, and what gear they carry — entirely in open formats
with no SQL dependencies.
Format:
• magic "WCRT", version 1, little-endian
• per entry: creatureId / displayId / name / subname /
minLevel..maxLevel / baseHealth + healthPerLevel /
baseMana + manaPerLevel / factionId / npcFlags /
typeId / familyId / damageMin..Max / attackSpeedMs /
baseArmor / walkSpeed + runSpeed / gossipId /
equippedMain + equippedOffhand + equippedRanged /
aiFlags
Enums:
• TypeId: Beast / Dragon / Demon / Elemental / Giant /
Undead / Humanoid / Critter / Mechanical
• FamilyId: Wolf / Cat / Bear / Boar / Raptor / Hyena /
Spider / Gorilla / Crab (for Beast types)
• NpcFlags: Vendor / QuestGiver / Trainer / Banker /
Innkeeper / FlightMaster / Auctioneer /
Repair / Stable
• Behavior: Passive / Aggressive / FleeLowHp / CallHelp /
NoLeash
API: WoweeCreatureLoader::save / load / exists /
findById; presets makeStarter (1 innkeeper),
makeBandit (creatureId=1000 matches WSPN/WLOT bandit
references, equips WIT itemId=1001 sword), makeMerchants
(creatureIds 4001/4002/4003 match WSPN village labels).
CLI added (5 flags, 493 documented total):
--gen-creatures / --gen-creatures-bandit / --gen-creatures-merchants
--info-wcrt / --validate-wcrt
Validator catches: creatureId=0, duplicates, level=0,
minLevel>maxLevel, baseHealth=0, damageMin>damageMax,
attackSpeed=0, non-positive walk/runSpeed, behavior flag
contradictions (passive+aggressive), vendor with
aggressive behavior (player can't trade).
2026-05-09 15:18:44 -07:00
src/pipeline/wowee_creatures.cpp
feat(pipeline): add WQT (Wowee Quest Template) format
Novel open replacement for AzerothCore-style quest_template
SQL tables PLUS the Blizzard Quest.dbc / QuestObjective.dbc
trio. The 15th open format added to the editor — and the
last gameplay-graph piece the catalog needed.
Cross-references with previously-added formats:
WQT.giverCreatureId -> WCRT.entry.creatureId
WQT.turninCreatureId -> WCRT.entry.creatureId
WQT.objective.targetId -> WCRT (kill) / WIT (collect) /
WOB (interact)
WQT.rewardItem.itemId -> WIT.entry.itemId
WQT.prevQuestId -> WQT.entry.questId (intra-format)
WQT.nextQuestId -> WQT.entry.questId
Together with WIT / WCRT / WLOT / WSPN / WOMX / WOL / WOW /
WSND, a content pack can now ship a complete RPG zone
(terrain + props + atmosphere + sounds + creatures + items
+ loot + spawns + quests) entirely in open formats with no
SQL or .dbc dependencies. 15 of 15 expected slots filled.
Format:
• magic "WQTM", version 1, little-endian
• per quest: questId / title / objective / description /
minLevel..maxLevel + questLevel / requiredClass+RaceMask /
prev+nextQuestId / giver+turninCreatureId /
objectives[] / xpReward + moneyCopperReward /
rewardItems[] / flags
Per-objective:
kind (kill/collect/interact/visit/escort/cast),
targetId, quantity
Per-reward:
itemId, qty, pickFlags (AutoGiven / PlayerChoice)
Quest flags: Daily / Weekly / Raid / Group / AutoComplete /
AutoAccept / Repeatable / ClassQuest / Pvp
API: WoweeQuestLoader::save / load / exists / findById;
presets makeStarter (1 simple kill quest, references the
bandit creatureId=1000), makeChain (3-quest chain with
prev/next links + AutoComplete bridge + player-choice
rewards), makeDaily (Daily+Repeatable+AutoAccept combo).
CLI added (5 flags, 500 documented total — round milestone):
--gen-quests / --gen-quests-chain / --gen-quests-daily
--info-wqt / --validate-wqt
Validator catches: questId=0+duplicates, level=0,
maxLevel<minLevel, empty title, no objectives without
AutoComplete (player can't finish), no rewards at all,
Daily without Repeatable (incoherent), targetId=0,
quantity=0, unknown objective kind, reward itemId=0 or qty=0.
The 3-quest chain demo exercises every major feature:
• multiple objective kinds (visit / collect / kill)
• prev/next chain links
• AutoComplete dialogue-bridge quest
• PlayerChoice reward (1 of 2 weapons)
2026-05-09 15:25:02 -07:00
src/pipeline/wowee_quests.cpp
feat(pipeline): add WGOT (Wowee Game Object Template) format
Novel open replacement for AzerothCore-style
gameobject_template SQL tables PLUS the Blizzard
GameObjectDisplayInfo.dbc / GameObject types metadata. The
16th open format added to the editor.
Game objects are the non-creature interactable scenery:
chests (with loot), doors, buttons, mailboxes, herb / ore
gathering nodes, fishing pools, signposts, mounts. Each
has a displayId for the model, a typeId driving its
interaction logic, and optional cross-references to a lock
(future WLCK) and loot table (existing WLOT).
Cross-references with previously-added formats:
WSPN.entry.entryId (kind=GameObject) -> WGOT.entry.objectId
WGOT.entry.lootTableId -> WLOT.entry.creatureId
(loot tables are
universal — chests
and creatures both
key by ID)
The dungeon preset's Bandit Strongbox uses lootTableId=2000
to match WLOT's bandit chest table id, so the demo content
stack already wires together: spawn (WSPN object kind 2000)
-> object template (WGOT 2000) -> loot table (WLOT 2000).
Format:
• magic "WGOT", version 1, little-endian
• per object: objectId / displayId / name / typeId /
size / castBarCaption / requiredSkill +
requiredSkillValue / lockId / lootTableId /
minOpenTimeMs..maxOpenTimeMs / flags
Enums:
• TypeId (16): Door / Button / Chest / Container /
QuestGiver / Text / Trap / Goober / Transport /
Mailbox / MineralNode / HerbNode / FishingNode /
Mount / Sign / Bonfire
• Flags: Disabled / ScriptOnly / UsableFromMount /
Despawn / Frozen / QuestGated
API: WoweeGameObjectLoader::save / load / exists /
findById; presets makeStarter (chest + mailbox + sign),
makeDungeon (door + button + 2 chests + trap with proper
WLOT cross-references), makeGather (Peacebloom herb +
Tin Vein ore + fishing pool with skill requirements).
CLI added (5 flags, 507 documented total now):
--gen-objects / --gen-objects-dungeon / --gen-objects-gather
--info-wgot / --validate-wgot
Validator catches: objectId=0 + duplicates, size<=0,
minOpenTime>maxOpenTime, gathering node without skill
requirement (anyone can harvest — usually a typo), chest
without loot table (script must populate), requiredSkillValue
set without requiredSkill (incoherent).
2026-05-09 15:31:49 -07:00
src/pipeline/wowee_objects.cpp
feat(pipeline): add WFAC (Wowee Faction Catalog) format
Novel open replacement for Blizzard's Faction.dbc +
FactionTemplate.dbc + the AzerothCore-style
reputation_reward / reputation_spillover SQL tables. The
17th open format added to the editor.
Combines the "displayable Faction" (player-facing name +
reputation thresholds for friendly/honored/revered/exalted)
with the "FactionTemplate matrix" (which factions are
hostile to which) into one entry. The runtime walks the
catalog to answer two questions:
• "Will faction A attack faction B on sight?" -> enemy list
• "What rep tier is the player with X?" -> thresholds
Cross-references with previously-added formats:
WCRT.entry.factionId -> WFAC.entry.factionId
WFAC.entry.parentFactionId -> WFAC.entry.factionId
WFAC.entry.enemies[] -> WFAC.entry.factionId
WFAC.entry.friends[] -> WFAC.entry.factionId
The starter preset's factionId 35 (Friendly) and 14
(Hostile) deliberately match the WCRT preset defaults, so
the demo content stack is consistent: WCRT.makeBandit's
factionId=14 has a real entry in WFAC.makeStarter that
declares it hostile to friendly NPCs (35) and players (1).
Format:
• magic "WFAC", version 1, little-endian
• per faction: factionId / parentFactionId / name /
description / reputationFlags / baseReputation /
7 ascending tier thresholds (hostile..exalted) /
enemies[] / friends[]
Enums:
• ReputationFlags: VisibleOnTab / AtWarDefault / Hidden /
NoReputation / IsHeader (group label)
• Tier (canonical): Hated / Hostile / Unfriendly /
Neutral / Friendly / Honored /
Revered / Exalted
API: WoweeFactionLoader::save / load / exists / findById +
WoweeFaction::isHostile(a, b); presets makeStarter (3-faction
demo matching WCRT defaults), makeAlliance (header +
Stormwind / Darnassus / Ironforge with reciprocal friend
lists + Defias enemy), makeWildlife (4 beast factions, each
hostile to player but ignoring other beasts).
CLI added (5 flags, 514 documented total now):
--gen-factions / --gen-factions-alliance / --gen-factions-wildlife
--info-wfac / --validate-wfac
Validator catches: factionId=0 + duplicates, empty name,
threshold ordering violations (hostile must be < unfriendly
< neutral < ... < exalted), self-listed as enemy or friend,
faction in both enemies and friends (incoherent).
2026-05-09 15:37:59 -07:00
src/pipeline/wowee_factions.cpp
feat(pipeline): add WLCK (Wowee Lock Template) format
Novel open replacement for Blizzard's Lock.dbc. The 18th
open format added to the editor. Closes the cross-reference
gap from WGOT.entry.lockId — until now that field pointed
to a format that didn't exist yet.
A lock is a multi-channel security check. Each lock has up
to 5 independent channels; a player can open the lock by
satisfying ANY ONE channel:
• Item — requires a specific key item (WIT cross-ref)
• Lockpick — requires the lockpicking skill at minimum rank
(rogue / engineering profession)
• Spell — requires casting a specific spell
• Damage — can be forced open with attack damage
Cross-references with previously-added formats:
WGOT.entry.lockId -> WLCK.entry.lockId
WLCK.channel.targetId (Item) -> WIT.entry.itemId
WLCK.channel.targetId (Lockpick) -> future WSKL skillId
WLCK.channel.targetId (Spell) -> future WSPL spellId
The starter and dungeon presets' lockIds (1 and 2)
deliberately match WGOT.makeDungeon's iron-door lockId=1
and bandit-strongbox lockId=2, so the demo content stack
already wires together: WSPN spawn -> WGOT object template
-> WLCK lock template -> WIT key items.
Format:
• magic "WLCK", version 1, little-endian
• per lock: lockId / name / flags / 5 fixed channel slots
• per channel: kind / skillRequired / targetId
• all 5 slots written even when unused (kind=None +
zeroed fields), keeping the per-entry size constant for
fast random access
Enums:
• ChannelKind: None / Item / Lockpick / Spell / Damage
• Flags: DestructOnOpen / RespawnOnKey / TrapOnFail
API: WoweeLockLoader::save / load / exists / findById;
presets makeStarter (Iron Door + Wooden Chest), makeDungeon
(matches WGOT cross-references; light/heavy lockpicks +
boss-key-only seal), makeProfessions (4-tier rogue lockpick
progression at ranks 1/100/175/250).
CLI added (5 flags, 521 documented total now):
--gen-locks / --gen-locks-dungeon / --gen-locks-professions
--info-wlck / --validate-wlck
Validator catches: lockId=0 + duplicates, all-None channels
(lock can never open), Item/Spell/Lockpick channels with
targetId=0 (no resource referenced), unknown channel kind,
skillRequired set on non-Lockpick channel (silently ignored
at runtime — flag as warning).
2026-05-09 15:44:26 -07:00
src/pipeline/wowee_locks.cpp
feat(pipeline): add WSKL (Wowee Skill Catalog) format
Novel open replacement for Blizzard's SkillLine.dbc +
SkillLineCategory.dbc + the AzerothCore-style player skill
base tables. The 19th open format added to the editor.
Defines every player-trackable skill: weapon proficiencies
(Swords, Axes, Bows), professions (Mining, Alchemy,
Cooking), languages (Common, Dwarvish), class
specializations (Fire, Frost, Holy, Protection), armor
proficiencies (Mail, Plate), and secondary skills (First
Aid, Lockpicking, Riding).
Cross-references with previously-added formats:
WLCK.channel.targetId (kind=Lockpick) -> WSKL.entry.skillId
WGOT.entry.requiredSkill -> WSKL.entry.skillId
The starter preset's skillIds 186 (Mining) and 633
(Lockpicking) deliberately match the canonical IDs already
referenced by WGOT.makeGather and WLCK.makeDungeon —
so the demo content stack now wires together end-to-end:
WGOT herb-node requires skill 186 -> WSKL Mining at rank 1+;
WLCK bandit-strongbox channel requires skill 633 -> WSKL
Lockpicking at rank 1+.
Format:
• magic "WSKL", version 1, little-endian
• per skill: skillId / name / description / categoryId /
canTrain / maxRank / rankPerLevel / iconPath
Enums:
• CategoryId (8): Weapon / Class / Profession /
SecondaryProfession / Language / ArmorProficiency /
Riding / WeaponSpec
API: WoweeSkillLoader::save / load / exists / findById;
presets makeStarter (5-skill demo with cross-referenced
canonical IDs), makeProfessions (12 classic professions:
9 primary + 3 secondary), makeWeapons (16 weapon skills
with canonical SkillLine IDs and rankPerLevel=5 auto-grow).
CLI added (5 flags, 528 documented total now):
--gen-skills / --gen-skills-professions / --gen-skills-weapons
--info-wskl / --validate-wskl
Validator catches: skillId=0 + duplicates, empty name,
maxRank=0, unknown categoryId, suspicious maxRank=1 on
non-Language skill (only languages cap at 1), weapon skill
with rankPerLevel=0 (won't auto-grow on use).
2026-05-09 15:50:25 -07:00
src/pipeline/wowee_skills.cpp
feat(pipeline): add WSPL (Wowee Spell Catalog) format
Novel open replacement for Blizzard's Spell.dbc +
SpellEffect.dbc + the AzerothCore-style spell_dbc /
spell_proc tables. The 20th open format added to the
editor — completes the canonical-data side of the gameplay
graph.
Each entry holds the metadata side of a spell: name,
description, school, range, mana / cast / cooldown times,
plus a single primary effect. The simplified effect model
(one effectKind + min/max value + misc field) covers the
common cases (damage / heal / buff / debuff / teleport /
summon / dispel) without needing to reproduce the full
multi-effect graph that classic Spell.dbc carries.
Cross-references with previously-added formats:
WLCK.channel.targetId (kind=Spell) -> WSPL.entry.spellId
WQT.objective.targetId (kind=SpellCast) -> WSPL.entry.spellId
WCRT.equippedMain (item with on-use) -> WIT -> WSPL
Format:
• magic "WSPL", version 1, little-endian
• per spell: spellId / name / description / iconPath /
school / targetType / effectKind / cast & cooldown &
GCD ms / manaCost / range min..max / minLevel /
maxStacks / durationMs / effectValueMin..Max /
effectMisc / flags
Enums:
• School (7): Physical / Holy / Fire / Nature / Frost /
Shadow / Arcane
• TargetType (6): Self / Single / Cone / AoeFromSelf /
Line / Ground
• EffectKind (7): Damage / Heal / Buff / Debuff / Teleport /
Summon / Dispel
• Flags: Passive / Hidden / Channeled / Ranged /
AreaOfEffect / Triggered / UnitTargetOnly /
FriendlyOnly / HostileOnly
API: WoweeSpellLoader::save / load / exists / findById;
presets makeStarter (Strike + Lesser Heal + Power Word:
Fortitude + Hearthstone, one per major effect kind),
makeMage (Frostbolt 116 + Fireball 133 + Arcane Intellect
1459 + Blink 1953, canonical Classic spellIds), makeWarrior
(Heroic Strike 78 + Thunder Clap 6343 + Battle Shout 6673 +
Mortal Strike 12294).
CLI added (5 flags, 535 documented total now):
--gen-spells / --gen-spells-mage / --gen-spells-warrior
--info-wspl / --validate-wspl
Validator catches: spellId=0 + duplicates, empty name,
school out of range, effectKind out of range, NaN range,
range/value min>max, FriendlyOnly+HostileOnly conflict
(incoherent), friendly-only with damage/debuff effect
(incoherent), hostile-only with heal/buff effect, buff/debuff
effect with durationMs=0 (instant fade — almost certainly
authoring oversight).
The validator caught a real preset-emitter authoring error
during initial smoke testing — buff spells were setting
effectValueMin without effectValueMax (validator's range
check immediately flagged it), prompting an in-batch fix
to set both fields. This is exactly the catch-the-typo
purpose validators serve.
2026-05-09 15:58:09 -07:00
src/pipeline/wowee_spells.cpp
feat(pipeline): add WACH (Wowee Achievement Catalog) format
Novel open replacement for Blizzard's Achievement.dbc +
AchievementCriteria.dbc + AchievementCategory.dbc + the
AzerothCore-style character_achievement /
character_achievement_progress SQL tables. The 21st open
format added to the editor.
Each achievement carries display metadata (name, description,
icon, points, faction restriction) plus a list of criteria
the player must satisfy. Criteria mirror the WQT objective
model (kind + targetId + quantity), so the runtime can
reuse the same progress-tracking machinery for both quests
and achievements.
Cross-references with previously-added formats — every
criterion kind has a real format target:
WACH.criteria.targetId (kind=KillCreature) -> WCRT.creatureId
WACH.criteria.targetId (kind=CompleteQuest) -> WQT.questId
WACH.criteria.targetId (kind=LootItem) -> WIT.itemId
WACH.criteria.targetId (kind=CastSpell) -> WSPL.spellId
WACH.criteria.targetId (kind=ReachSkillLevel) -> WSKL.skillId
WACH.criteria.targetId (kind=EarnReputation) -> WFAC.factionId
WACH.criteria.targetId (kind=CompleteAchievement) -> WACH.achievementId
(meta-achievements)
Format:
• magic "WACH", version 1, little-endian
• per achievement: id / categoryId / name / description /
iconPath / titleReward / points / minLevel / faction /
flags / criteria[]
• per criterion: criteriaId / kind / targetId / quantity /
description
Enums:
• CriteriaKind (9): KillCreature / CompleteQuest / LootItem /
ReachLevel / EarnReputation / CastSpell /
ReachSkillLevel / VisitArea /
CompleteAchievement
• Faction: Both / Alliance / Horde
• Flags: HiddenUntilEarned / ServerFirst / RealmFirst /
Tracking / Counter / Account
API: WoweeAchievementLoader::save / load / exists /
findById; presets makeStarter (3 simple kill/quest/level
demos), makeBandit (3 with WCRT/WGOT/WQT cross-refs),
makeMeta (3 base + 1 meta-achievement granting "the
Versatile" title, exercising CompleteAchievement criterion
kind that lets achievements depend on other achievements).
CLI added (5 flags, 542 documented total now):
--gen-achievements / --gen-achievements-bandit / --gen-achievements-meta
--info-wach / --validate-wach
Validator catches: achievementId=0 + duplicates, empty name,
faction out of range, no criteria (achievement can never
be earned), criterion quantity=0, unknown criterion kind,
targetId=0 on criterion kinds that need a real resource
reference (everything except ReachLevel which uses the
quantity field for the level number).
The bandit preset's cross-references close the gameplay
graph end-to-end: kill 50 creatureId=1000 (matches WCRT/
WSPN/WLOT bandit), loot objectId=2000 (matches WGOT bandit
strongbox), complete questId=1 (matches WQT Bandit Trouble).
The meta preset closes a separate loop: 3 sub-achievements
covering Mining (skillId=186), Lockpicking (skillId=633),
and Frostbolt cast count (spellId=116) — each pointing at
a real WSKL/WSPL entry that already exists in the demo
content stack.
2026-05-09 16:04:30 -07:00
src/pipeline/wowee_achievements.cpp
feat(pipeline): add WTRN (Wowee Trainer / Vendor catalog) format
Novel open replacement for AzerothCore-style npc_trainer +
npc_vendor SQL tables PLUS the Blizzard TrainerSpells.dbc
family. The 22nd open format added to the editor.
Unifies trainer spell lists and vendor item inventories
into one per-NPC entry. A creature flagged Trainer or
Vendor in WCRT references a WTRN entry that lists what they
teach / sell. The same NPC can be both — kindMask is a
bitmask covering the Trainer (0x01) and Vendor (0x02) kinds.
This format closes a major cross-format gap: WCRT.npcFlags
already had Vendor / Trainer bits, but until now there was
no format defining what a vendor sells or what a trainer
teaches. Now an NPC marked Vendor in WCRT has a real
inventory, and an NPC marked Trainer has a real spell list.
Cross-references — every WTRN field has a real format target:
WTRN.entry.npcId -> WCRT.entry.creatureId
WTRN.spell.spellId -> WSPL.entry.spellId
WTRN.spell.requiredSkillId -> WSKL.entry.skillId
WTRN.item.itemId -> WIT.entry.itemId
Format:
• magic "WTRN", version 1, little-endian
• per NPC: npcId / kindMask / greeting + spells[] + items[]
• per spell offer: spellId / moneyCostCopper /
requiredSkillId / requiredSkillRank / requiredLevel
• per item offer: itemId / stockCount (0xFFFFFFFF =
unlimited) / restockSec / extendedCost / moneyCostCopper
(0 = inherit from WIT.buyPrice)
API: WoweeTrainerLoader::save / load / exists / findByNpc;
presets makeStarter (innkeeper 4001 as both trainer +
vendor: teaches First Aid + sells starter items),
makeMageTrainer (NPC 4003 teaches the WSPL mage spells
at scaling cost), makeWeaponVendor (NPC 4002 sells WIT
weapons with mixed unlimited/finite stock + restock timers).
CLI added (5 flags, 551 documented total now):
--gen-trainers / --gen-trainers-mage / --gen-trainers-weapons
--info-wtrn / --validate-wtrn
Validator catches: npcId=0 + duplicates, kindMask=0 (NPC
offers nothing), Trainer flag without spells, Vendor flag
without items, spells/items present without the matching
kind bit (silently ignored at runtime), spellId=0 / itemId=0
in offers, finite stock with restockSec=0 (single-fill —
usually intentional but worth surfacing).
The 3 presets deliberately use npcIds matching WCRT village
merchants (4001/4002/4003) so the demo content stack is
self-consistent: WCRT 4001 has the Vendor + Trainer flag,
and WTRN 4001 actually defines what they sell and teach.
2026-05-09 16:12:58 -07:00
src/pipeline/wowee_trainers.cpp
feat(pipeline): add WGSP (Wowee Gossip Menu) format
Novel open replacement for AzerothCore-style gossip_menu +
gossip_menu_option + npc_text SQL tables PLUS the Blizzard
NpcText.dbc family. The 23rd open format added to the
editor.
An NPC's dialogue tree: a menu of options the player can
pick from when right-clicking the NPC. Each option may
bridge to another menu, trigger a vendor / trainer
interaction, offer a quest, etc. The simplified per-option
model (kind + actionTarget + flags + moneyCost) covers the
common cases without needing separate npc_text condition
tables.
Closes a major cross-format gap: WCRT.entry.gossipId has
existed since batch 116 (when WCRT was added) but pointed
to a format that didn't exist yet. The innkeeper preset's
menuId=4001 deliberately matches WCRT's Bartleby NPC so
the demo content stack can wire WCRT.gossipId = 4001 once
that field is plumbed through the runtime.
Cross-references:
WCRT.entry.gossipId -> WGSP.entry.menuId
WGSP.option.actionTarget (Submenu) -> WGSP.entry.menuId
WGSP.option.actionTarget (Vendor / Trainer)
-> WTRN.entry.npcId
WGSP.option.actionTarget (Quest) -> WQT.entry.questId
Format:
• magic "WGSP", version 1, little-endian
• per menu: menuId / titleText + options[]
• per option: optionId / text / kind / actionTarget /
requiredFlags / moneyCostCopper
Enums:
• OptionKind (13): Close / Submenu / Vendor / Trainer /
Quest / Tabard / Banker / Innkeeper /
FlightMaster / TextOnly / Script /
Battlemaster / Auctioneer
• OptionFlags: AllianceOnly / HordeOnly / Coinpouch /
QuestGated / Closes
API: WoweeGossipLoader::save / load / exists / findById;
presets makeStarter (1 menu with vendor + trainer + close),
makeInnkeeper (2-menu tree: main menu 4001 with hearth /
vendor / flight / submenu options + lore submenu 4002 that
links back), makeQuestGiver (1 menu with 2 quest options
referencing WQT 1 and 100, plus a paid respec script
exercising the Coinpouch flag with a 10g cost).
CLI added (5 flags, 558 documented total now):
--gen-gossip / --gen-gossip-innkeeper / --gen-gossip-questgiver
--info-wgsp / --validate-wgsp
Validator catches: menuId=0 + duplicates, empty title /
options, unknown option kind, empty option text, Submenu
options pointing at non-existent menuIds (intra-format
cross-reference resolution), Coinpouch flag without
moneyCost (misleading UI), AllianceOnly+HordeOnly conflict.
2026-05-09 16:20:07 -07:00
src/pipeline/wowee_gossip.cpp
2026-05-09 16:26:27 -07:00
src/pipeline/wowee_taxi.cpp
feat(pipeline): add WTAL (Wowee Talent catalog) format
Novel open replacement for Blizzard's TalentTab.dbc +
Talent.dbc + the AzerothCore-style talent_progression SQL
tables. The 25th open format added to the editor.
Defines class talent specialization trees: per-class set
of named tabs (Arms / Fury / Protection for warrior, Fire
/ Frost / Arcane for mage), each with talents arranged in
a row/column grid, each talent having up to 5 ranks and
an optional prerequisite chain.
Cross-references with previously-added formats:
WTAL.talent.prereqTalentId -> WTAL.talent.talentId
(intra-format chain)
WTAL.talent.rankSpellIds[] -> WSPL.entry.spellId
(spell granted at each rank)
Format:
• magic "WTAL", version 1, little-endian
• per tree: treeId / name / iconPath / requiredClassMask /
talents[] (row, col, maxRank, prereqTalentId+rank,
rankSpellIds[5] zero-padded for unused ranks)
Enums:
• ClassMask: bit positions match canonical CharClasses.dbc
classIds — Warrior / Paladin / Hunter / Rogue / Priest /
DK / Shaman / Mage / Warlock / Druid
API: WoweeTalentLoader::save / load / exists +
WoweeTalent::findTree / findTalent (global lookup across
all trees in the catalog).
Three preset emitters showcase tree shapes:
• makeStarter — 1 small tree (3-talent vertical chain)
• makeWarrior — 3 trees (Arms 4 / Fury 4 / Protection 3)
with WSPL cross-refs at capstones
(Mortal Strike -> WSPL 12294, Battle Shout
-> WSPL 6673, Thunder Clap -> WSPL 6343)
• makeMage — 3 trees (Arcane / Fire / Frost) with
capstones referencing Frostbolt 116 /
Fireball 133 / Blink 1953 from WSPL
CLI added (5 flags, 571 documented total now):
--gen-talents / --gen-talents-warrior / --gen-talents-mage
--info-wtal / --validate-wtal
Validator catches: tree+talent ids=0 or duplicates, empty
tree name, requiredClassMask=0 (every class would see this
tree — usually a typo), maxRank not in 1..5, talent listing
itself as prerequisite, prereqTalentId pointing at a
talent that doesn't exist in this catalog (intra-format
cross-reference resolution), prereqRank=0 or > the prereq
talent's maxRank (catches off-by-one references), gaps in
rankSpellIds progression (rank N has spell but rank N-1
doesn't — usually a typo).
The validator caught a real authoring bug in the makeMage /
makeWarrior presets during smoke testing — initial check
was comparing prereqRank against the WRONG talent's maxRank
(this talent's rather than the prereq's). Fixed in the same
commit by hoisting the check into the cross-reference
resolution pass where the prereq talent is in hand.
2026-05-09 16:33:45 -07:00
src/pipeline/wowee_talents.cpp
feat(pipeline): add WMS (Wowee Map / Area) catalog format
Novel open replacement for Blizzard's Map.dbc + AreaTable.dbc
+ the AzerothCore-style world_zone SQL tables. The 26th open
format added to the editor.
Defines two related kinds of locator in one catalog:
• Maps — top-level worlds (continents / instances / raids /
battlegrounds / arenas) with a friendly name,
type, expansion tag, and player-count cap.
• Areas — sub-zones within maps with friendly names, parent-
area chain, recommended level range, faction-
territory marker (alliance / horde / contested /
both), exploration XP, and an ambient-sound
cross-reference into WSND.
The runtime uses Areas for minimap labels, location strings
under the player frame, "Discover Sub-zone" XP gains, and
ambient-music selection on zone entry.
Cross-references with previously-added formats:
WMS.area.ambienceSoundId -> WSND.entry.soundId
WMS.area.parentAreaId -> WMS.area.areaId (intra-format
sub-zone hierarchy)
WSPN entries are tied to WMS.area boundaries by
world position (no direct ID — the runtime resolves
position -> area at lookup time)
Format:
• magic "WMSX", version 1, little-endian
• maps[] (each): mapId / name / shortName / mapType /
expansionId / maxPlayers
• areas[] (each): areaId / mapId / parentAreaId / name /
minLevel..maxLevel / factionGroup / explorationXP /
ambienceSoundId
Enums:
• MapType (5): Continent / Instance / Raid / Battleground / Arena
• ExpansionId (5): Classic / Tbc / Wotlk / Cata / Mop
• FactionGroup: Both / Alliance / Horde / Contested
(PvP-flagging zone)
API: WoweeMapsLoader::save / load / exists +
WoweeMaps::findMap / findArea.
Three preset emitters showcase the catalog shape:
• makeStarter — 1 continent + 3 areas with parent chain
(Goldshire is a sub-zone of Elwynn Forest)
• makeClassic — 2 continents + Deadmines instance + 6
areas (Stormwind/Elwynn/Goldshire/Westfall/
Duskwood/Teldrassil/Deadmines) with WSND
ambient-sound refs
• makeBgArena — Alterac Valley (40-player BG) + Nagrand
Arena (5v5 with maxPlayers=10)
CLI added (5 flags, 578 documented total now):
--gen-maps / --gen-maps-classic / --gen-maps-bgarena
--info-wms / --validate-wms
Validator catches: empty map name, unknown mapType / expansion,
BG/Arena with maxPlayers=0 (no participant cap), area ids=0
+ duplicates, empty area name, maxLevel < minLevel, areas
referencing non-existent maps, parentAreaId chains crossing
maps (sub-zones must be on the same world), self-parent.
2026-05-09 16:40:00 -07:00
src/pipeline/wowee_maps.cpp
feat(pipeline): add WCHC (Wowee Character Classes/Races) format
Novel open replacement for Blizzard's CharClasses.dbc +
CharRaces.dbc + CharStartOutfit.dbc trio. The 27th open
format added to the editor — completes the foundational
character-creation surface.
One file holds three flat arrays:
• classes — playable classes (Warrior / Mage / etc.) with
power type (mana/rage/focus/energy/runic),
base HP+power scaling, faction availability
• races — playable races with faction (Alliance/Horde/
Neutral), starting map+zone, default language
spell, base stats, racial mount spell
• outfits — starting gear loadout per (class, race, gender)
triple, listing item IDs and display slots
Cross-references with previously-added formats:
WCHC.race.startingMapId -> WMS.map.mapId
WCHC.race.startingZoneAreaId -> WMS.area.areaId
WCHC.race.defaultLanguageSpellId -> WSPL.entry.spellId
WCHC.race.mountSpellId -> WSPL.entry.spellId
WCHC.outfit.items.itemId -> WIT.entry.itemId
The starter preset's outfits use real WIT itemIds (1=Worn
Shortsword, 2=Linen Vest, 3=Healing Potion) so the demo
content stack is consistent: a freshly created Human Warrior
in WCHC starts with WIT items 1/2/3, drops them on death
into a WLOT-tracked corpse loot, and can be respawned via
WSPN, etc.
Format:
• magic "WCHC", version 1, little-endian
• classes[]: classId / name / icon / powerType / display /
baseHP+perLevel / basePower+perLevel / factionAvailability
• races[]: raceId / name / icon / factionId / male+female
displayId / 5 base stats / startingMap+zone /
defaultLanguage+mount spell IDs
• outfits[]: classId+raceId+gender + items[]
(each: itemId + displaySlot)
Enums:
• PowerType (6): Mana / Rage / Focus / Energy / RunicPower / Runes
• RaceFaction (3): Alliance / Horde / Neutral
• Gender: Male / Female
• FactionAvailability bitmask: AvailableAlliance, AvailableHorde
API: WoweeCharsLoader::save / load / exists +
WoweeChars::findClass / findRace / findOutfit (by class+race+gender).
CLI added (5 flags, 585 documented total now):
--gen-chars / --gen-chars-alliance / --gen-chars-allraces
--info-wchc / --validate-wchc
Validator catches: ids unique, baseHealth=0 (instant-death
character), factionAvailability=0 (no faction can pick),
empty names, factionId out of range, outfit references to
non-existent class/race ids (cross-format resolution),
gender > 1, outfit items with itemId=0, outfit with no
items (warning — naked character).
2026-05-09 16:47:04 -07:00
src/pipeline/wowee_chars.cpp
feat(pipeline): add WTKN (Wowee Token catalog) format
Novel open replacement for Blizzard's Currency.dbc +
CurrencyCategory.dbc + CurrencyTypes.dbc + the AzerothCore-
style player_currency SQL tables. The 28th open format
added to the editor.
Defines secondary currency tokens beyond gold: Honor Points
(PvP), Arena Points (rated PvP), Marks of Honor (per
battleground), faction reputation tokens, holiday-event
currencies. Each token has a balance cap, optional weekly
cap (regenerating earnings limit), and a category for
grouping in the player's currency tab.
Cross-references:
WTRN.item.extendedCost -> WTKN.entry.tokenId
(vendors can charge in tokens
instead of copper — when
extendedCost > 0 the runtime
looks up the matching token)
Format:
• magic "WTKN", version 1, little-endian
• per token: tokenId / name / description / iconPath /
category / maxBalance / weeklyCap / flags
Enums:
• Category (6): Misc / Pvp / Reputation / Crafting /
Seasonal / Holiday
• Flags: AccountWide / Tradeable / HiddenUntilEarned /
ResetsOnLogout / ConvertsToGold
API: WoweeTokenLoader::save / load / exists / findById.
Three preset emitters showcase typical token shapes:
• makeStarter — 3 tokens (Honor / Marks / Stormwind Guard
rep) covering Pvp + Reputation categories
• makePvp — full PvP set: Honor (75k) + Arena (5k +
weekly 1500) + 6 BG marks of honor for
classic + TBC + WotLK battlegrounds
• makeSeasonal — 4 holiday tokens (Tricky Treats /
Brewfest / Coin of Ancestry / Stranger's
Gift) all flagged ResetsOnLogout to make
them event-bound
CLI added (5 flags, 592 documented total now):
--gen-tokens / --gen-tokens-pvp / --gen-tokens-seasonal
--info-wtkn / --validate-wtkn
Validator catches: tokenId=0 + duplicates, empty name,
unknown category, weeklyCap > maxBalance (cap unreachable),
ResetsOnLogout + AccountWide combo (incoherent — account
state survives logout by definition).
2026-05-09 16:53:11 -07:00
src/pipeline/wowee_tokens.cpp
feat(pipeline): add WTRG (Wowee Area Trigger) format
Novel open replacement for Blizzard's AreaTrigger.dbc +
AreaTriggerTeleport.dbc + the AzerothCore-style
areatrigger_template / areatrigger_teleport SQL tables.
The 29th open format added to the editor.
Defines proximity-based event zones — when a player enters
a defined region (box or sphere), the runtime fires the
trigger's action: teleport to another map, award
exploration XP for a quest, run a server script, gate an
instance entrance behind a key item, mark a PvP boundary,
or simply display a "Discovered: {area name}" banner.
Cross-references with previously-added formats — every
trigger field has a real format target:
WTRG.entry.mapId / areaId -> WMS.map.mapId / WMS.area.areaId
WTRG.actionTarget (Teleport) -> WMS.mapId
WTRG.actionTarget (QuestExploration) -> WQT.questId
WTRG.requiredQuestId -> WQT.entry.questId
WTRG.requiredItemId -> WIT.entry.itemId (key)
Format:
• magic "WTRG", version 1, little-endian
• per trigger: triggerId / mapId / areaId / name /
center vec3 / shape / kind / boxDims vec3 / radius /
actionTarget / dest vec3 / destOrientation /
requiredQuestId / requiredItemId / minLevel
Enums:
• Shape (2): Box / Sphere
• Kind (7): Teleport / QuestExploration / Script /
InstanceEntrance / AreaName / CombatStartZone /
Waypoint
API: WoweeTriggerLoader::save / load / exists / findById.
Three preset emitters showcase common trigger shapes:
• makeStarter — area-name + quest-exploration with
cross-ref to WQT 100 ("Investigate the
Camp")
• makeDungeon — outdoor area-name + portal-style
InstanceEntrance with Deadmines key
gate (WIT itemId 5200, matches
WLCK.makeDungeon's Boss Vault Seal) +
interior exit teleport back outdoors
• makeFlightPath — 2 sphere waypoints near flight masters
so the runtime can auto-open the
flight UI on proximity (matches WTAX
starter node positions)
CLI added (5 flags, 601 documented total now):
--gen-triggers / --gen-triggers-dungeon / --gen-triggers-flightpath
--info-wtrg / --validate-wtrg
Validator catches: triggerId=0 + duplicates, unknown shape /
kind, non-finite center, sphere with radius<=0, box with
all-zero half-extents, teleport / instance with dest=(0,0,0)
(silently does nothing — usually a typo), QuestExploration
without an actionTarget questId.
2026-05-09 17:01:43 -07:00
src/pipeline/wowee_triggers.cpp
feat(pipeline): add WTIT (Wowee Title catalog) format
Novel open replacement for Blizzard's CharTitles.dbc + the
AzerothCore-style character_title SQL table. The 30th open
format added to the editor.
Defines the player-display titles awarded for completing
achievements ("the Versatile"), reaching PvP ranks
("Sergeant Major" / "Stone Guard"), participating in raids
("Champion of the Naaru"), levelling a profession ("Master
Locksmith"), or seasonal events ("Brewmaster", "the
Hallowed").
Closes a long-standing gap: WACH.entry.titleReward has been
a free-form string since batch 116 with no formal catalog
to resolve against. WTIT systematizes those strings into a
real catalog — the runtime resolves WACH.titleReward to a
WTIT entry by name, then displays the titleId in the player
title selector.
Cross-references:
WACH.entry.titleReward (string) ~= WTIT.entry.name
(string match — runtime
resolves achievement-
granted titles by
looking up matching WTIT
entry by name)
Format:
• magic "WTIT", version 1, little-endian
• per title: titleId / name / nameMale / nameFemale /
iconPath / prefix (suffix vs prefix display) /
category / sortOrder
Enums:
• Category (8): Achievement / Pvp / Raid / ClassTitle /
Event / Profession / Lore / Custom
API: WoweeTitleLoader::save / load / exists +
WoweeTitle::findById / findByName.
Three preset emitters showcase typical title catalogs:
• makeStarter — 4 titles (Versatile / Sergeant /
Champion / Hallowed) covering 4
categories
• makePvp — 28-title classic Honor System ladder
(14 Alliance ranks Private->Grand
Marshal + 14 Horde ranks Scout->High
Warlord)
• makeAchievement — 8 achievement titles including "the
Versatile" matching WACH.makeMeta's
achievement 250 titleReward + capstone
profession titles
CLI added (5 flags, 608 documented total now):
--gen-titles / --gen-titles-pvp / --gen-titles-achievement
--info-wtit / --validate-wtit
Validator catches: titleId=0 + duplicates, empty name,
unknown category, gender variants set on only one side
(causes mixed-gender display when the runtime falls back to
canonical for the unset side).
2026-05-09 17:07:56 -07:00
src/pipeline/wowee_titles.cpp
feat(pipeline): add WSEA (Wowee Seasonal Event) format
Novel open replacement for Blizzard's GameEvents.dbc + the
AzerothCore-style game_event / game_event_creature /
game_event_gameobject SQL tables. The 31st open format
added to the editor.
Calendar-based content: holidays (Hallow's End, Winter's
Veil), recurring promotional events (Children's Week,
Lunar Festival, Brewfest), one-time anniversaries, and
XP-bonus weekends. Each event has a start date, duration,
optional recurrence (yearly / monthly / weekly), faction
restriction, optional XP bonus, and a reward currency
cross-reference into WTKN.
Cross-references with previously-added formats:
WSEA.entry.tokenIdReward -> WTKN.entry.tokenId
(the seasonal currency the
event hands out — Tricky
Treats during Hallow's End,
Brewfest Tokens during
Brewfest, etc.)
The yearly preset's tokenIdReward values (200/201/202/203)
deliberately match WTKN.makeSeasonal's seasonal token ids
so the demo content stack already wires together: WSEA
yearly events grant WTKN tokens that vendors can charge in
via WTRN.item.extendedCost.
Format:
• magic "WSEA", version 1, little-endian
• per event: eventId / name / description / iconPath /
announceMessage / startDate (Unix epoch seconds) /
duration_seconds / recurrenceDays (0=one-shot, 365=yearly) /
holidayKind / factionGroup / bonusXpPercent / tokenIdReward
Enums:
• HolidayKind (7): Combat / Collection / Racial /
Anniversary / Fishing / Cosmetic /
WorldEvent
• FactionGroup (3): Both / Alliance / Horde
API: WoweeEventLoader::save / load / exists / findById.
Three preset emitters showcase typical event shapes:
• makeStarter — 3 events covering Combat /
Fishing / Anniversary kinds
• makeYearly — 4 yearly holidays with full WTKN
cross-refs (Hallow's End / Brewfest /
Lunar Festival / Winter's Veil)
• makeBonusWeekends — 3 monthly Fri-Sun bonus tiers
(50% / 100% / 200% RAF-style)
CLI added (5 flags, 614 documented total now):
--gen-events / --gen-events-yearly / --gen-events-weekends
--info-wsea / --validate-wsea
Validator catches: eventId=0 + duplicates, empty name,
unknown holidayKind / factionGroup, duration_seconds=0
(event never runs), duration > recurrence period (events
would overlap themselves on next iteration), bonusXpPercent
> 200 (very high — verify intentional).
2026-05-09 17:14:46 -07:00
src/pipeline/wowee_events.cpp
feat(pipeline): add WMOU (Wowee Mount catalog) format
Novel open replacement for Blizzard's Mount.dbc +
MountCapability.dbc + MountType.dbc + the mount-related
subsets of Spell.dbc / Item.dbc. The 32nd open format added
to the editor.
Defines all summonable steeds: ground mounts, flying mounts,
swimming mounts, racial mounts (Tauren Plainsrunner for
druids), and class mounts (Warlock dreadsteed, Paladin
charger). Each mount has a summon spell, optional teach
item, riding skill prerequisite, speed bonus, and faction
/ race availability mask.
Cross-references with previously-added formats:
WMOU.entry.summonSpellId -> WSPL.entry.spellId
WMOU.entry.itemIdToLearn -> WIT.entry.itemId
WMOU.entry.requiredSkillId -> WSKL.entry.skillId
(Riding skill ID 762)
WCHC.race.mountSpellId ~= WMOU.entry.summonSpellId
(loose match by spellId)
Format:
• magic "WMOU", version 1, little-endian
• per mount: mountId / name / description / icon /
displayId / summonSpellId / itemIdToLearn /
requiredSkillId+Rank / speedPercent / mountKind /
factionId / categoryId / raceMask
Enums:
• Kind (5): Ground / Flying / Swimming / Hybrid /
Aquatic
• Faction (3): Both / Alliance / Horde
• Category (8): Common / Epic / Racial / Event /
Achievement / Pvp / Quest / ClassMount
API: WoweeMountLoader::save / load / exists / findById.
Three preset emitters showcase typical mount catalogs:
• makeStarter — 3 mounts (ground horse + epic flying
gryphon + aquatic riding turtle)
• makeRacial — 6 racial mounts (4 Alliance: Pinto / Ram /
Frostsaber / Mechanostrider; 2 Horde:
Dire Wolf / Skeletal Horse) with raceMask
gating per WCHC race bit positions
• makeFlying — 4 flying mounts spanning Common (60%) ->
Epic (100%) -> Achievement (280%) -> Pvp
(310%) speed tiers
CLI added (5 flags, 621 documented total now):
--gen-mounts / --gen-mounts-racial / --gen-mounts-flying
--info-wmou / --validate-wmou
Validator catches: mountId=0 + duplicates, empty name,
summonSpellId=0 (mount cannot be cast), unknown enum values,
speedPercent=0 (no speed bonus), flying mount with
requiredSkillRank<150 (player can't fly), Racial category
without raceMask (any race could use — usually a typo).
2026-05-09 17:23:00 -07:00
src/pipeline/wowee_mounts.cpp
feat(pipeline): add WBGD (Wowee Battleground Definition) format
Novel open replacement for Blizzard's BattlemasterList.dbc +
PvpDifficulty.dbc + the AzerothCore-style
battleground_template SQL tables. The 33rd open format
added to the editor.
Defines per-BG gameplay rules: player count brackets,
score-to-win, time limit, objective type (annihilation /
capture flag / control nodes / king of hill / resource race
/ carry object), per-team start positions, respawn timer,
and the WTKN currency token awarded on win.
Cross-references with previously-added formats:
WBGD.entry.mapId -> WMS.map.mapId
(where mapType=Battleground)
WBGD.entry.markTokenId -> WTKN.entry.tokenId
(Mark of Honor for that BG)
The classic preset's markTokenId fields (102/103/104)
deliberately match WTKN.makePvp's "Mark of Honor: Warsong
Gulch / Arathi Basin / Alterac Valley" token ids — so the
demo content stack already wires together: WBGD.scoreToWin
reached → grant WTKN mark → which a vendor in WTRN can
charge in via item.extendedCost.
Format:
• magic "WBGD", version 1, little-endian
• per BG: battlegroundId / mapId / name / description /
objectiveKind / min+maxPlayersPerSide /
minLevel..maxLevel / scoreToWin / timeLimitSeconds /
bracketSize / allianceStart vec3 + facing /
hordeStart vec3 + facing / respawnTimeSeconds /
markTokenId
Enums:
• ObjectiveKind (6): Annihilation / CaptureFlag /
ControlNodes / KingOfHill /
ResourceRace / CarryObject
API: WoweeBattlegroundLoader::save / load / exists /
findById.
Three preset emitters showcase typical BG shapes:
• makeStarter — 1 king-of-hill BG (10v10, 3-cap to win)
• makeClassic — 3 classic BGs with authentic player
counts, level brackets, scoring, and
WTKN cross-refs (Warsong Gulch CTF /
Arathi Basin nodes / Alterac Valley
resource race)
• makeArena — 3 arena formats (Nagrand 2v2 / Blade's
Edge 3v3 / Lordaeron 5v5) — annihilation
objective + no respawn + 25 min cap
CLI added (5 flags, 628 documented total now):
--gen-bg / --gen-bg-classic / --gen-bg-arena
--info-wbgd / --validate-wbgd
Validator catches: bgId=0 + duplicates, empty name, unknown
objectiveKind, player count=0, min>max counts/levels,
scoreToWin=0 (no win condition), non-annihilation BG with
respawnTimeSeconds=0 (losing side cannot recover).
2026-05-09 17:30:59 -07:00
src/pipeline/wowee_battlegrounds.cpp
feat(pipeline): add WMAL (Wowee Mail Template) format
Novel open replacement for AzerothCore-style
mail_loot_template SQL + the in-game mail subset of the
inventory + currency systems. The 34th open format added
to the editor.
Defines templated mail messages with currency + item
attachments. Triggered by quest reward delivery (overflow
when bag is full), auction house bid wins / sales,
achievement reward attachments, GM correspondence, holiday
event mailings (Brewfest samples, Hallow's End candy), and
returned-mail-on-rejection.
Cross-references with previously-added formats:
WMAL.entry.senderNpcId -> WCRT.entry.creatureId
WMAL.entry.attachments.itemId -> WIT.entry.itemId
Format:
• magic "WMAL", version 1, little-endian
• per template: templateId / senderNpcId / subject / body /
senderName / moneyCopperAttached / categoryId / cod /
returnable / expiryDays / attachments[] (each: itemId +
quantity)
Enums:
• Category (8): QuestReward / Auction / GmCorrespondence /
AchievementReward / EventMailing / Raffle /
ScriptDelivery / ReturnedMail
API: WoweeMailLoader::save / load / exists / findById.
Three preset emitters showcase typical mail templates:
• makeStarter — 3 templates (quest overflow / auction won /
GM gift) covering the 3 most common
categories
• makeHoliday — 4 holiday samples that cross-reference the
WTKN seasonal token IDs (200=Tricky Treats,
201=Brewfest, 202=Coin of Ancestry,
203=Stranger's Gift) so the demo content
stack ships a full holiday onboarding
experience
• makeAuction — 5-template auction-house family (outbid /
won / sold / expired / cancelled) — runtime
fills in actual bid amounts / sold items
at send time
CLI added (5 flags, 635 documented total now):
--gen-mail / --gen-mail-holiday / --gen-mail-auction
--info-wmal / --validate-wmal
Validator catches: templateId=0 + duplicates, empty subject,
neither senderNpcId nor senderName set (no displayable
sender), unknown category, expiryDays=0 (mail expires
immediately), cod=1 with no money attached (free COD),
empty mail in categories where the runtime doesn't fill in
content (skips Auction / GmCorrespondence / ReturnedMail
where empty templates are intentional).
Two bugs caught + fixed during smoke-test on the auction
preset:
• print formatting glued the `0` from senderNpcId after
the senderName when no NPC was set (rendered as
"Postmaster0" instead of "Postmaster") — fixed with an
explicit if/else split
• validator's "no money + no items" warning was too
aggressive for the Auction category, where templates
are intentionally informational and the runtime fills
in the real values — added Auction + ReturnedMail to
the skip list
2026-05-09 17:41:03 -07:00
src/pipeline/wowee_mail.cpp
feat(pipeline): add WGEM (Wowee Gem / Enchantment) format
Novel open replacement for Blizzard's ItemEnchantment.dbc +
GemProperties.dbc + SpellItemEnchantment.dbc. The 35th
open format added to the editor.
Defines two related kinds of item enhancement in one
catalog:
• Gems — socketable jewelry pieces with color
(red / blue / yellow / meta) that fit
into gear sockets, granting stats or
triggering passive spells when socketed
• Enchantments — persistent buffs applied to weapon /
armor pieces, either by an enchanter
spell or by an item proc (Mongoose,
Crusader, Berserking)
Cross-references with previously-added formats:
WGEM.gem.itemIdToInsert -> WIT.entry.itemId
WGEM.gem.spellId -> WSPL.entry.spellId
WGEM.enchantment.spellId -> WSPL.entry.spellId
Format:
• magic "WGEM", version 1, little-endian
• gems[]: gemId / itemIdToInsert / name / color /
statType + statValue / requiredItemQuality / spellId
• enchantments[]: enchantId / name / description /
iconPath / enchantSlot / statType + statValue /
spellId / durationSeconds / chargeCount
Enums:
• Color (8): Meta / Red / Yellow / Blue / Purple /
Green / Orange / Prismatic
• EnchantSlot (5): Permanent / Temporary / SocketColor /
Ring / Cloak
API: WoweeGemLoader::save / load / exists +
WoweeGem::findGem / findEnchant.
Three preset emitters showcase common shapes:
• makeStarter — 3 gems (one per primary color) +
2 enchantments (proc + stat)
• makeGemSet — 6-gem full color palette covering
primary + secondary combinations
• makeEnchants — 5 enchant variants spanning slots
(Mongoose / Deadly Poison / stats ring /
cloak / Berserking)
CLI added (5 flags, 642 documented total now):
--gen-gems / --gen-gems-set / --gen-gems-enchants
--info-wgem / --validate-wgem
Validator catches: ids=0 + duplicates, empty name, color /
slot out of range, stat-only entries with statValue=0 (gem
provides nothing), chargeCount > 0 on non-Temporary
enchant slots (charges silently ignored at runtime).
The validator caught a real preset issue on first run —
the proc enchants (Mongoose / Deadly Poison / Berserking)
had spellId=0 and statValue=0, providing nothing. Fixed by
adding placeholder spellIds in the 28000-29000 range, with
a comment noting they resolve to real WSPL proc spells
when the spell catalog is extended.
2026-05-09 18:01:48 -07:00
src/pipeline/wowee_gems.cpp
feat(pipeline): add WGLD (Wowee Guild) catalog format
Novel open replacement for AzerothCore-style guild +
guild_member + guild_rank + guild_bank_tab + guild_perk
SQL tables. The 36th open format added to the editor.
Each guild entry holds the complete social-organization
state: header (name, leader, faction, MOTD, info,
creation date, level + experience, bank money, packed
emblem), rank ladder with permissions bitmask + daily
withdraw caps, member roster with rank + join date +
public/officer notes, bank tabs with per-tab and per-rank
deposit / withdraw / view permission masks, and purchased
guild perks referencing WSPL spell IDs.
Cross-references with previously-added formats:
WGLD.entry.factionId ~ WCHC.race.factionId
(guilds are faction-locked)
WGLD.entry.perks.spellId -> WSPL.entry.spellId
Format:
• magic "WGLD", version 1, little-endian
• per guild: header (12 scalar fields + 4 strings) +
ranks[] + members[] + bankTabs[] + perks[]
• per rank: rankIndex / name / permissionsMask /
moneyPerDayCopper
• per member: characterName / rankIndex / joinedDate /
publicNote / officerNote
• per bankTab: tabIndex / name / iconPath /
deposit+withdraw+view permission masks
• per perk: perkId / name / spellId / requiredGuildLevel
Enums:
• Faction (2): Alliance / Horde
• RankPermissionFlags (14): GuildChat / OfficerChat /
Invite / Remove / Promote /
Demote / SetMotd /
EditPublicNote /
EditOfficerNote / ViewBank /
Deposit / Withdraw / Disband /
RepairFromBank
API: WoweeGuildLoader::save / load / exists / findById +
shared addDefaultRanks helper used by both starter and
faction-pair presets.
Three preset emitters:
• makeStarter — 1 small guild, default 5-rank ladder
(GM/Officer/Veteran/Member/Initiate),
3 members borrowing names from WCRT
merchants for cross-format consistency
• makeFull — 1 fleshed-out guild: 6 ranks (with
Recruit added) + 8 members + 4 bank
tabs (officer-only withdraw on tabs
3+4) + 3 perks referencing WSPL
spell IDs (Heroic Strike / Battle
Shout / Thunder Clap as placeholder
perk procs)
• makeFactionPair — 2 parallel guilds, one Alliance + one
Horde, with identical rank structures
CLI added (5 flags, 649 documented total now):
--gen-guilds / --gen-guilds-full / --gen-guilds-pair
--info-wgld / --validate-wgld
Validator catches: guildId=0 + duplicates, empty name /
leaderName, factionId out of range, no ranks (members can't
exist without a rank ladder), member.rankIndex exceeding
the highest defined rank (intra-format cross-reference
resolution), duplicate bank tabIndices, perks with
spellId=0 (perk does nothing).
2026-05-09 18:10:45 -07:00
src/pipeline/wowee_guilds.cpp
feat(pipeline): add WPCD (Wowee Player Condition) format
Novel open replacement for Blizzard's PlayerCondition.dbc +
the AzerothCore-style condition_template SQL tables. The
37th open format added to the editor.
Defines reusable boolean conditions that other formats can
reference for gating: "player has quest X completed",
"player level >= N", "player class is mage", "player has
item Y in inventory", "WSEA event Z is active".
Conditions can be grouped and combined with AND/OR
aggregators on a per-group basis: a quest-giver gossip
option that says "show only to level 60 alliance mages
who completed quest 1234" composes 4 conditions sharing
the same groupId with AND aggregation. The runtime walks
each group, applies the group's aggregator, and returns
the boolean result to the caller.
Cross-references with previously-added formats — the
targetId field has a polymorphic interpretation by kind:
WPCD.targetId (kind=QuestCompleted/Active) -> WQT.questId
WPCD.targetId (kind=HasItem) -> WIT.itemId
WPCD.targetId (kind=HasSpell) -> WSPL.spellId
WPCD.targetId (kind=HasAchievement) -> WACH.achievementId
WPCD.targetId (kind=AreaId) -> WMS.areaId
WPCD.targetId (kind=EventActive) -> WSEA.eventId
WPCD.targetId (kind=HasTitle) -> WTIT.titleId
WPCD.targetId (kind=FactionRep) -> WFAC.factionId
WPCD.targetId (kind=Class/Race) -> WCHC class/race id
Future format extensions can reference WPCD.conditionId in
their own gating fields — WTRG triggers gated by player
state, WGSP options visible only when conditions are met,
WMOU summon spells condition-gated by quest progress, etc.
Format:
• magic "WPCD", version 1, little-endian
• per condition: conditionId / groupId (0 = standalone) /
name / description / kind / aggregator / negated /
targetId / minValue / maxValue
Enums:
• Kind (17): AlwaysTrue / AlwaysFalse / QuestCompleted /
QuestActive / HasItem / HasSpell / MinLevel /
MaxLevel / ClassMatch / RaceMatch /
FactionRep / HasAchievement / TeamSize /
GuildLevel / EventActive / AreaId / HasTitle
• Aggregator (2): And / Or
API: WoweeConditionLoader::save / load / exists / findById.
Three preset emitters showcase typical usage:
• makeStarter — 4 standalone conditions covering the most
common kinds (quest-done / has-item /
min-level / class)
• makeGated — 5 conditions in 2 groups demonstrating
AND-aggregation (alliance + mage + lvl 60)
and OR-aggregation (did quest 1 OR quest 100)
• makeEvent — 3 event-gated conditions cross-referencing
WSEA event IDs (Hallow's End / Brewfest /
Winter's Veil)
CLI added (5 flags, 656 documented total now):
--gen-conditions / --gen-conditions-gated / --gen-conditions-event
--info-wpcd / --validate-wpcd
Validator catches: conditionId=0 + duplicates, kind /
aggregator out of range, kinds requiring targetId having
target=0 (skips AlwaysTrue/False, MinLevel/MaxLevel,
TeamSize, GuildLevel which use min/max instead), TeamSize
with min > max.
2026-05-09 18:18:27 -07:00
src/pipeline/wowee_conditions.cpp
feat(pipeline): add WPET (Wowee Pet System) catalog
Novel open replacement for AzerothCore-style pet_template +
pet_levelstats SQL + the pet-related subsets of
CreatureFamily.dbc + SpellFamilyName.dbc. The 38th open
format added to the editor.
Defines two related kinds of player-controlled NPCs in
one catalog:
• Pet families — hunter pet families (Wolf / Cat / Bear /
Boar / Raptor / Spider / etc.) with
per-family ability sets, base stat
multipliers, and diet preferences
• Warlock minions — Imp / Voidwalker / Succubus /
Felhunter / Felguard, each with
their own summon spell, creature
template, and ability list
Cross-references with previously-added formats:
WPET.family.familyId -> WCRT.entry.familyId
(matches creature family)
WPET.family.abilities.spellId -> WSPL.entry.spellId
WPET.minion.summonSpellId -> WSPL.entry.spellId
WPET.minion.creatureId -> WCRT.entry.creatureId
(used for stat scaling)
WPET.minion.abilities.spellId -> WSPL.entry.spellId
The starter preset's familyIds (1=Wolf, 2=Cat) match
WCRT::FamilyId enum values, so a hunter taming a wolf via
WCRT links straight through to WPET ability sets.
Format:
• magic "WPET", version 1, little-endian
• families[]: familyId / name / description / icon /
petType / baseAttackSpeed / damageMultiplier /
armorMultiplier / dietMask / abilities[]
• minions[]: minionId / name / summonSpellId / creatureId /
abilities[] (each: spellId / rank / autocastDefault)
Enums:
• PetType (3): Cunning / Ferocity / Tenacity
(WotLK+ talent tree categorization)
• DietFlags: Meat / Fish / Bread / Cheese / Fruit / Fungus
API: WoweePetLoader::save / load / exists +
WoweePet::findFamily / findMinion + dietMaskName helper
that decodes a dietMask into a "meat+fish" string.
Three preset emitters showcase typical pet catalogs:
• makeStarter — 2 hunter families (Wolf + Cat) with full
3-ability sets + 1 warlock Imp
• makeHunter — 8 classic hunter families covering all
3 petType categories with appropriate
diet masks
• makeWarlock — 5 warlock minions each with summon spell
ID and creatureId pointing into WCRT
CLI added (5 flags, 663 documented total now):
--gen-pets / --gen-pets-hunter / --gen-pets-warlock
--info-wpet / --validate-wpet
Validator catches: ids=0 + duplicates, empty name, petType
out of range, baseAttackSpeed<=0 (would divide by zero in
DPS calc), dietMask=0 (pet cannot be fed for happiness),
minion missing summonSpellId / creatureId.
2026-05-09 18:27:02 -07:00
src/pipeline/wowee_pets.cpp
feat(pipeline): add WAUC (Wowee Auction House) catalog
Novel open replacement for Blizzard's AuctionHouse.dbc +
the AzerothCore-style auctionhouse / auctionhousebot SQL
tables. The 39th open format added to the editor.
Defines per-house rules for the auction system: faction
access, deposit rate (basis points of buyout price), house
cut on successful sale, three listing duration tiers with
per-tier deposit multipliers, disallowed item-class bitmask,
and the auctioneer NPC.
Cross-references with previously-added formats:
WAUC.entry.auctioneerNpcId -> WCRT.entry.creatureId
(Auctioneer-flagged NPC)
WAUC.entry.disallowedClassMask
bitmask of WIT.Class values
that may not be auctioned at
this house
The faction-pair preset captures the canonical asymmetry:
faction houses charge 5% on a successful sale while neutral
houses charge 15% — the cross-faction tax that makes
neutral AHs profitable for goblins.
Format:
• magic "WAUC", version 1, little-endian
• per house: houseId / auctioneerNpcId / name /
factionAccess / baseDepositRateBp / houseCutRateBp /
maxBidCopper / 3 duration hours + 3 deposit multipliers /
disallowedClassMask
Enums:
• FactionAccess (4): Alliance / Horde / Neutral / Both
• Rates use basis points: 10000 = 100%
API: WoweeAuctionLoader::save / load / exists / findById.
Three preset emitters showcase typical auction setups:
• makeStarter — 1 neutral house with default 12h /
24h / 48h tiers
• makeFactionPair — 3 houses (Stormwind / Orgrimmar /
Booty Bay) with auctioneer NPC IDs
+ canonical faction-vs-neutral cut
rates
• makeRestricted — 1 house disallowing Containers (1) +
Quest items (12) + Keys (13) with
tighter durations + 1000g bid cap
CLI added (5 flags, 670 documented total now):
--gen-auction / --gen-auction-pair / --gen-auction-restricted
--info-wauc / --validate-wauc
Validator catches: houseId=0 + duplicates, empty name,
factionAccess out of range, duration tier=0, durations not
in short<=medium<=long order, houseCutRateBp >= 100% (seller
loses money on a sale), warns on >50% cut.
2026-05-09 18:34:54 -07:00
src/pipeline/wowee_auction.cpp
feat(pipeline): add WCHN (Wowee Chat Channel) catalog
Novel open replacement for Blizzard's ChatChannels.dbc +
the AzerothCore-style chat_channel SQL tables. The 40th
open format added to the editor.
Defines the world chat channel system: General, Trade,
LookingForGroup, GuildRecruitment, LocalDefense, plus
per-zone area channels and custom user-created channels.
Each channel has access rules (faction / level), join
behavior (auto vs opt-in), broadcast policy (announce /
moderated), and optional area / map gating that auto-joins
or auto-leaves the channel as the player moves.
Cross-references with previously-added formats:
WCHN.entry.areaIdGate -> WMS.area.areaId
(channel auto-attaches in this area)
WCHN.entry.mapIdGate -> WMS.map.mapId
(channel auto-attaches on this map)
Format:
• magic "WCHN", version 1, little-endian
• per channel: channelId / name / description /
channelType / factionAccess / autoJoin / announce /
moderated / minLevel / areaIdGate / mapIdGate
Enums:
• ChannelType (10): AreaLocal / Zone / Continent / World /
Trade / LookingForGroup / GuildRecruit /
LocalDefense / Custom / Pvp
• FactionAccess (3): Alliance / Horde / Both
API: WoweeChannelLoader::save / load / exists / findById.
Three preset emitters:
• makeStarter — 4 stock channels (General Zone +
Trade + LFG + GuildRecruit) with
default autoJoin policies
• makeCity — 5 city-specific channels (3 Stormwind +
2 Orgrimmar) with mapId / areaId gates
so they auto-attach on entry
• makeModerated — 3 moderated / restricted channels
(LocalDefense level 10+, WorldDefense
moderated, RaidCoordination level 60+)
CLI added (5 flags, 677 documented total now):
--gen-channels / --gen-channels-city / --gen-channels-moderated
--info-wchn / --validate-wchn
Validator catches: channelId=0 + duplicates, empty name,
unknown channelType / factionAccess, world / continent
channel with area or map gate (gate is silently ignored at
runtime — usually a typo), minLevel=0 (no level gate at all).
2026-05-09 18:43:26 -07:00
src/pipeline/wowee_channels.cpp
feat(pipeline): add WCMS (Wowee Cinematic) catalog
41st open format — replaces Movie.dbc / CinematicCamera.dbc /
CinematicSequences.dbc plus the AzerothCore cinematic_camera SQL
table. Defines pre-rendered videos, in-engine camera flythroughs,
text crawls, and still images, each with a media path, duration,
skippable flag, and a polymorphic trigger that fires on quest
events / class first-login / zone entry / dungeon clear /
achievements / level milestones.
Cross-references with prior formats — triggerTargetId resolves
by triggerKind to WQT.questId / WMS.areaId / WMS.mapId /
WCHC.classId / WACH.achievementId, and soundtrackId points at
WSND.soundId.
CLI: --gen-cinematics (3-entry starter), --gen-cinematics-intros
(4 class intros), --gen-cinematics-quests (3 quest-bound
cinematics referencing demo questIds 1/100/102), --info-wcms,
--validate-wcms with --json variants. Validator catches
id=0/duplicates, empty name/mediaPath, kind/trigger out of
range, missing target id for non-Manual/Login/LevelUp triggers,
zero-duration entries, and non-skippable pre-rendered videos.
2026-05-09 18:50:43 -07:00
src/pipeline/wowee_cinematics.cpp
feat(pipeline): add WGLY (Wowee Glyph) catalog
42nd open format — replaces GlyphProperties.dbc + GlyphSlot.dbc
plus the AzerothCore-style glyph_properties SQL table. Defines
the WotLK glyph system: per-class inscribable glyphs that
modify spell behavior. Each entry pairs a glyph item (the
inscriber's craft output) with the spell aura that applies the
modification, tagged with a Major / Minor / Prime slot type and
a classMask of allowed classes.
Cross-references with prior formats — spellId points at
WSPL.spellId (the aura), itemId points at WIT.itemId (the
inscribed item), and classMask bit positions match the WCHC
classId enum (1=Warrior, 2=Paladin, 3=Hunter, etc).
CLI: --gen-glyphs (3-entry per-role starter), --gen-glyphs-warrior
(6-entry full warrior allotment), --gen-glyphs-universal (4
classMask=All utility glyphs), --info-wgly, --validate-wgly with
--json variants. Validator catches id=0/duplicates, empty name,
spellId=0 (glyph applies no aura), classMask=0 (no class can
inscribe), itemId=0 warning, requiredLevel<25 warning (below
WotLK glyph threshold), and glyphType out-of-range.
2026-05-09 18:55:22 -07:00
src/pipeline/wowee_glyphs.cpp
feat(pipeline): add WVHC (Wowee Vehicle) catalog
43rd open format — replaces Vehicle.dbc + VehicleSeat.dbc plus
the AzerothCore-style vehicle_template SQL tables. Defines
drivable vehicles: tanks, demolishers, motorcycles, gryphons,
choppers, siege weapons, multi-passenger transports. Each entry
pairs a creature template (the rendered model) with a fixed
seat layout — driver / passenger / gunner seats with their own
attachment points, control flags (kSeatDriver / kSeatGunner /
kSeatPassenger / kSeatHidesPlayer / kSeatNoEjectByCC), and
per-seat abilities mounted to the action bar.
Cross-references with prior formats — creatureId points at
WCRT.creatureId (the rendered model), flightCapabilityId points
at WMNT.mountId for shared fly-speed tables, and per-seat
controlSpellId / exitSpellId point at WSPL.spellId.
CLI: --gen-vehicles (3-vehicle starter chopper/wind-rider/tank),
--gen-vehicles-siege (3 siege weapons with control spellIds),
--gen-vehicles-flying (3 flying mounts cross-ref WMNT
flightCapabilityIds), --info-wvhc, --validate-wvhc with --json
variants. Validator catches id=0/duplicates, missing creature,
enum out-of-range, empty seat list, flying-vehicle on wrong
movement (would fall through world), driver-flag exclusivity
(0 or >1 drivers), and duplicate seatIndex within a vehicle.
2026-05-09 18:59:49 -07:00
src/pipeline/wowee_vehicles.cpp
feat(pipeline): add WHOL (Wowee Holiday) catalog
44th open format — replaces Holidays.dbc + HolidayDescriptions.dbc
+ HolidayNames.dbc plus the AzerothCore-style game_event SQL
tables. Defines time-gated world events: seasonal holidays
(Hallow's End / Brewfest / Winter Veil), weekly call-to-arms BG
bonuses, world-PvP windows (Wintergrasp), one-shot specials, and
recurring daily / weekly resets. Each holiday has a recurrence
rule (Annual / Monthly / WeeklyRecur / OneTime), a calendar
window (startMonth + startDay + durationHours), and optional
cross-refs to a feature creature, an intro quest, and a token /
item reward issued during the window.
Cross-references with prior formats — holidayQuestId points at
WQT.questId, bossCreatureId points at WCRT.creatureId,
itemRewardId points at WIT.itemId, and areaIdGate / mapIdGate
point at WMS.areaId / WMS.mapId.
CLI: --gen-holidays (3 seasonal starter), --gen-holidays-weekly
(3 weekly BG call-to-arms windows), --gen-holidays-special (3
world-PvP / lunar / children events), --info-whol, --validate-whol
with --json variants. Validator catches id=0/duplicates, kind /
recurrence out of range, durationHours=0, invalid month/day for
non-weekly recurrence, and calendar-only events (no quest +
boss + reward) as a warning.
2026-05-09 19:05:33 -07:00
src/pipeline/wowee_holidays.cpp
feat(pipeline): add WLIQ (Wowee Liquid Type) catalog
45th open format — replaces LiquidType.dbc plus the
AzerothCore-style terrain liquid descriptor data. Defines
liquid materials used by terrain MCNK liquid layers, WMO
interior pools, and procedurally generated fluid bodies in
custom zones. Each liquid pairs a render material (shader +
texture array + flow vectors + fog color) with gameplay data
(damage spell, raw DPS, ambient + splash audio cross-refs).
Cross-references with prior formats — ambientSoundId and
splashSoundId point at WSND.soundId, damageSpellId points at
WSPL.spellId.
10 liquid kinds (Water / Magma / Slime / OceanSalt / FelFire /
HolyLight / TarOil / AcidBog / FrozenWater / UnderworldGoo)
covering both natural and magical fluids. Per-liquid: viscosity
(0=water, 1=slime), flow direction+speed (radians+units/sec),
fog density+RGB, packed minimap RGBA color.
CLI: --gen-liquids (3-entry classic Water/Lava/Slime starter),
--gen-liquids-magical (4 magical pools incl. fel/holy/cosmic),
--gen-liquids-hazardous (3 high-damage liquids with WSPL DoT
cross-refs), --info-wliq, --validate-wliq with --json variants.
Validator catches id=0/duplicates, missing shader/material,
kind out of range, fog/viscosity outside 0..1, hazardous-kind-
without-damage warning, and Water/OceanSalt-with-damage warning
to flag accidental misconfiguration.
2026-05-09 19:10:03 -07:00
src/pipeline/wowee_liquids.cpp
feat(pipeline): add WANI (Wowee Animation) catalog
46th open format — replaces AnimationData.dbc plus the
hard-coded animation-id tables in M2 model loaders. Defines
named animations (Stand, Walk, Run, Cast, Death, MountIdle,
Fly, ...) with fallback chains, behavior tier (default /
mounted / sitting / aerial / swimming), and weapon-flag
bitmasks that select the correct animation variant when the
model wields 1H / 2H / dual / bow / rifle / wand / etc.
Cross-references with prior formats — fallbackId resolves
within the same WANI catalog (graceful degradation when the
requested animation is absent: Run falls back to Walk,
Attack2H falls back to Attack1H).
10 weapon-flag constants + 6 behavior flags (Looped,
BlendableCycle, Interruptable, MovementSync, OneShot,
PreserveAtEnd). 5 behavior tiers. CLI: --gen-animations
(5 essentials), --gen-animations-combat (8 weapon-typed
attacks + parry + channel), --gen-animations-movement (6
locomotion anims with tier transitions). Validator catches
id-uniqueness, fallback-self-loop, looped-without-duration,
mutually-exclusive Looped+OneShot flags, weaponFlags=0
warning, and unresolved fallback warnings.
Also extends --list-formats and --info-magic with WANI.
2026-05-09 19:19:13 -07:00
src/pipeline/wowee_animations.cpp
feat(pipeline): add WSVK (Wowee Spell Visual Kit) catalog
47th open format — replaces SpellVisualKit.dbc +
SpellVisualEffectName.dbc plus the AzerothCore-style spell
visual SQL data. Defines per-spell visual presentations:
cast-bar effect model, projectile model + travel speed +
arc gravity, impact effect model, hand effect on the caster,
and the animations + sounds that fire at cast / channel /
impact time.
Cross-references with prior formats — castAnimId / impactAnimId
/ precastAnimId point at WANI.animationId, castSoundId /
impactSoundId point at WSND.soundId. Spell catalogs (WSPL)
will reference visualKitId here to bind "what mechanically
happens" to "what plays visually."
CLI: --gen-svk (3-kit Frostbolt/Fireball/HealingTouch starter
showing projectile + AoE + heal patterns), --gen-svk-combat
(5 melee/ranged with WANI animation refs), --gen-svk-utility
(4 portal/hearth/mount/resurrect with no projectile),
--info-wsvk, --validate-wsvk with --json variants. Validator
catches id=0/duplicates, missing name, negative speeds/radii,
projectile-model + speed coherence (model without speed =
never travels; speed without model = invisible), and a
no-effect catch-all (no models + no anims + no sounds).
2026-05-09 19:23:36 -07:00
src/pipeline/wowee_spell_visuals.cpp
feat(pipeline): add WWUI (Wowee World-State UI) catalog
48th open format — replaces WorldStateUI.dbc plus the
AzerothCore-style world_state SQL data. Defines on-screen UI
elements that surface server-side world-state variables: BG
scoreboards (flag captures, base controls), Wintergrasp tank
counters, Eye of the Storm flag-carrier indicator, dungeon
boss progress, world-event collection trackers.
Each entry binds a server-side variableIndex to a UI panel
kind (counter / timer / flag-icon / progress-bar / two-sided
score / custom) gated by mapId+areaId, with optional
alwaysVisible and hideWhenZero flags and a chosen panel
position (top / bottom / top-left / top-right / center).
Cross-references with prior formats — mapId points at
WMS.mapId and areaId points at WMS.areaId.
CLI: --gen-wsui (3-entry BG scoreboard starter for WSG/AB/
EotS), --gen-wsui-wintergrasp (4-entry full Wintergrasp UI),
--gen-wsui-dungeon (3-entry boss/keys/treasure hunt UI),
--info-wwui, --validate-wwui with --json variants. Validator
catches id=0/duplicates, kind/position out of range,
variableIndex=0 warning, alwaysVisible+hideWhenZero conflict
warning, and (mapId, variableIndex) collision warning when
two entries would read the same server slot on the same map.
Also extends --list-formats and --info-magic with WWUI.
2026-05-09 19:32:15 -07:00
src/pipeline/wowee_world_state_ui.cpp
feat(pipeline): add WPCN (Wowee Player Condition) catalog
49th open format — replaces PlayerCondition.dbc plus the
AzerothCore-style condition resolver. Defines reusable
boolean checks that other catalogs reference by conditionId
to gate gossip options, vendor items, quest availability,
achievement criteria, spell trainer offerings.
16 condition kinds (Always, Race, Class, Level, Zone, Map,
Reputation, AchievementWon, QuestComplete, QuestActive,
SpellKnown, ItemEquipped, Faction, InCombat, Mounted,
Resting), 8 comparison ops (==, !=, >, >=, <, <=, in-set,
not-in-set), and 4 chain ops (none, and, or, not) — chain
multiple conditions via chainNextId to express arbitrary
boolean trees.
Cross-references with prior formats — targetIdA is
polymorphic by conditionKind: resolves to WCHC raceId/classId,
WMS areaId/mapId, WFAC factionId, WACH achievementId, WQT
questId, WSPL spellId, or WIT itemId. chainNextId resolves
within the same WPCN catalog.
CLI: --gen-pcn (3 single-check starters), --gen-pcn-quest-gates
(4 cross-format quest gates with real WQT/WFAC/WACH/WMS IDs),
--gen-pcn-composite (3 leaves + 3 chained roots showing AND/
OR/NOT). Validator catches id=0/duplicates, kind/op out of
range, chain self-loop (infinite recursion), chainOp set
without chainNextId (dangling chain), chainNextId set without
chainOp (dead pointer warning), and unresolved chainNextId
references.
2026-05-09 19:36:56 -07:00
src/pipeline/wowee_player_conditions.cpp
feat(pipeline): add WTSK (Wowee Trade Skill / Recipe) catalog
New open format — replaces SkillLineAbility.dbc plus the
recipe portions of SkillLine.dbc plus the AzerothCore
trade_skill SQL tables. Closes the crafting gap left by WSKL
(which carries skill lines but not the recipes that bind to
them).
14 professions (Blacksmithing, Tailoring, Engineering,
Alchemy, Enchanting, Leatherworking, Jewelcrafting,
Inscription, Mining, Skinning, Herbalism, Cooking, FirstAid,
Fishing). Each recipe has 4 skill-up bracket thresholds
(orange / yellow / green / gray) for skill-up probability,
a craft spell cross-ref (WSPL), produced item cross-ref
(WIT) with min/max quantity range, an optional tool item,
and up to 4 reagent slots (itemId + count).
Cross-references with prior formats — craftSpellId points at
WSPL.spellId, producedItemId / toolItemId / reagent[].itemId
all point at WIT.itemId, and skillId points at WSKL.skillId.
CLI: --gen-tsk (3-recipe entry-tier starter), --gen-tsk-
blacksmithing (5-recipe progression rough sharpening through
truesilver champion), --gen-tsk-alchemy (5-recipe progression
minor healing through flask of titans), --info-wtsk,
--validate-wtsk with --json variants. Validator catches
id=0/duplicates, profession out of range, missing craft spell
or produced item, monotonic-bracket check (must be orange <=
yellow <= green <= gray), reagent itemId-without-count
mismatch, and free-recipe warning (no reagents and no tool).
Format graph now exposes 49 distinct binary formats. CLI
flag count: 747 → 752.
2026-05-09 19:41:49 -07:00
src/pipeline/wowee_trade_skills.cpp
feat(pipeline): add WCEQ (Wowee Creature Equipment) — 50th open format
Replaces the AzerothCore-style creature_equip_template SQL
tables plus the visible-weapon / shield / ranged-slot data
that was traditionally embedded in creature templates. Closes
a long-standing gap in the creature subsystem: until now WCRT
defined a creature's stats, WSPN placed it in the world, and
WLOT defined what it drops — but nothing defined what items
it visibly equips.
Each entry binds a creatureId to up to three equipped items
(main hand / off hand / ranged) plus the visual kit that
fires when the main-hand weapon is brandished. equipFlags
bits encode hidden / dual-wield / shield-offhand /
thrown-ranged / 2H polearm to drive the renderer's
attachment-point selection.
Cross-references with prior formats — creatureId points at
WCRT.creatureId, mainHandItemId / offHandItemId / rangedItemId
all point at WIT.itemId, and mainHandVisualId points at
WSVK.visualKitId so brandished weapons can play their
signature glow / aura.
CLI: --gen-ceq (3 generic guard/hunter/rogue starters),
--gen-ceq-bosses (4 iconic loadouts incl. Frostmourne and
Illidan's warglaives, with WSVK visual cross-refs),
--gen-ceq-ranged (3 ranged-only rifle/bow/crossbow loadouts),
--info-wceq, --validate-wceq with --json variants. Validator
catches id=0/duplicates, missing creatureId, all-empty-slots
warning, kFlagDualWield without both hand items, kFlagShield
without offhand item, mutually-exclusive dual-wield + shield,
and 2H polearm with offhand item filled.
Format graph milestone: 50 distinct binary formats. CLI flag
count: 754 → 760.
2026-05-09 19:48:13 -07:00
src/pipeline/wowee_creature_equipment.cpp
feat(pipeline): add WSET (Wowee Item Set / Tier Bonus) catalog
51st open format — replaces ItemSet.dbc + ItemSetSpell.dbc
plus the AzerothCore-style item_set_spell SQL data. Closes
the tier-bonus gap left by WIT (which describes individual
items but not the set bonuses they grant when worn together).
Each entry binds up to 8 piece item IDs to up to 4 bonus
thresholds — at N pieces worn, the matching bonus spell
activates as an aura. Standard 2/4/6/8-piece tier set pattern
is the canonical case; 5-piece PvP sets with 2/4 bonuses are
also supported.
Cross-references with prior formats — itemIds[] point at
WIT.itemId, bonusSpellIds[] point at WSPL.spellId, and
requiredSkillId points at WSKL.skillId. requiredClassMask
is a 32-bit field (uint32_t) so bit positions match WCHC's
classId enum directly — Druid (bit 11 = 0x800) and Mage
(bit 8 = 0x100) wouldn't fit in a uint8_t.
CLI: --gen-itset (2 raid sets — Battlegear of Wrath +
Stormrage Raiment, real WoW item/spell IDs), --gen-itset-tier
(4 tier-1 progression sets covering plate / cloth / leather /
holy plate), --gen-itset-pvp (3 PvP gladiator 5-piece sets
with honor-rank skill thresholds), --info-wset, --validate-wset
with --json variants. Validator catches id+name+pieceCount
required, pieceCount/bonusCount within array bounds, piece-
slot drift (0 IDs within count or non-0 IDs past count),
bonus thresholds strictly ascending, no bonus threshold
exceeding pieceCount (would never trigger), and spellId=0
in any populated bonus slot.
Format graph: 50 → 51 binary formats. CLI flag count: 762
→ 767.
2026-05-09 19:54:36 -07:00
src/pipeline/wowee_item_sets.cpp
feat(pipeline): add WGTP (Wowee Game Tips) catalog
52nd open format — replaces GameTips.dbc plus loading-screen
tutorial hint tables. Defines the rotating tips shown during
world loads, the contextual tutorial hints that fire on first
gameplay events (first quest accept, first death, first
dungeon entry), and the persistent tooltip-help strings that
explain UI elements.
4 display kinds (LoadingScreen / Tutorial / TooltipHelp /
Hint), 7 audience-filter bits (Alliance / Horde / NewPlayer /
Hardcore / PvE / PvP / Roleplay) for pool selection, level
range gating (minLevel + maxLevel), displayWeight for
relative frequency within the pool, optional WPCN condition
cross-ref for further gating, and class-mask restriction
matching WCHC bit positions.
Cross-references with prior formats — conditionId points at
WPCN.conditionId for advanced gating; requiredClassMask uses
the same WCHC.classId bit layout as WGLY/WSET.
CLI: --gen-tips (3 generic loading-screen tips), --gen-tips-
new-player (5 onboarding Tutorial-kind tips for level 1-15,
weighted higher for new players), --gen-tips-advanced (4
endgame tips for level 70+ covering raid mechanics / arena /
daily professions / dungeon finder), --info-wgtp,
--validate-wgtp with --json variants. Validator catches
id/name/text required, kind 0..3, audienceFilter=0 (tip
never shown), invalid level range, displayWeight=0 (in pool
but never picked) warning, and brevity check (>280 chars)
on Tutorial / Hint kinds that need to fit on screen.
Format graph: 51 → 52 binary formats. CLI flag count: 770
→ 775.
2026-05-09 20:00:56 -07:00
src/pipeline/wowee_game_tips.cpp
feat(pipeline): add WCMP (Wowee Companion Pet) catalog
53rd open format — replaces the companion-pet portions of
CreatureFamily.dbc plus the AzerothCore-style critter / vanity-
pet SQL data. Distinct from WPET (which covers hunter combat
pets and warlock minions); WCMP covers non-combat "vanity" pets
that follow the player around for cosmetic reasons —
Mechanical Squirrel, Mini Diablo, Panda Cub, dragon hatchlings.
8 companion kinds (Critter, Mechanical, DragonHatchling,
Demonic, Spectral, Elemental, Plush, UndeadCritter), 4
rarity tiers (Common / Uncommon / Rare / Epic), and 3
faction restrictions (AnyFaction / AllianceOnly / HordeOnly).
Cross-references with prior formats — creatureId points at
WCRT.creatureId (the rendered model), learnSpellId at
WSPL.spellId (the spell that summons the pet), itemId at
WIT.itemId (the item that teaches the spell), and
idleSoundId at WSND.soundId (idle ambient noise).
CLI: --gen-cmp (3 common vendor pets), --gen-cmp-rare (4
promo / collector pets at Epic rarity — Mini Diablo,
Panda Cub, Zergling, Murky), --gen-cmp-faction (3 faction-
restricted Alliance Lion Cub / Horde Mottled Boar /
neutral Argent Squire), --info-wcmp, --validate-wcmp with
--json variants. Validator catches id+name+creatureId+
learnSpellId required, kind 0..7 / rarity 0..3 / faction
0..2 range, and Epic-rarity-no-itemId warning (most promo
pets need a redemption-code item).
Format graph: 52 → 53 binary formats. CLI flag count: 777
→ 782.
2026-05-09 20:05:06 -07:00
src/pipeline/wowee_companions.cpp
feat(pipeline): add WSMC (Wowee Spell Mechanic) catalog
54th open format — replaces SpellMechanic.dbc plus the
AzerothCore-style diminishing-returns (DR) tables. Defines
crowd-control mechanic categories that spells reference:
Stun, Silence, Polymorph, Sleep, Fear, Root, Snare, Slow,
Knockback, etc. Each mechanic carries gameplay metadata
(breaks-on-damage, can-be-dispelled, default duration, max
stacks) plus DR category and dispel type.
8 DR categories (DRNone / DRStun / DRDisorient / DRSilence
/ DRRoot / DRPolymorph / DRControlled / DRMisc) — the
runtime uses these to gate repeated CC on the same target.
7 dispel types (DispelNone / Magic / Curse / Disease /
Poison / Enrage / Stealth) bind which dispel spells can
remove the mechanic. conflictsMask is a bitmask of OTHER
mechanic IDs — only one mechanic from a conflict-group can
apply to a target simultaneously.
Cross-references with prior formats — mechanicId is
referenced by WSPL.spellId entries that apply this CC; this
catalog is referenced from spell tags rather than referencing
out.
CLI: --gen-smc (3 baseline Stun/Silence/Snare), --gen-smc-
hard (5 hard-CC: Stun/Polymorph/Sleep/Fear/Knockback with
conflictsMask wiring), --gen-smc-roots (4 movement-impair:
Root/Snare/Slow stacking 5x/GroundPin breaks-on-damage),
--info-wsmc, --validate-wsmc with --json variants. Validator
catches id+name required, DR category 0..7, dispel type
0..6, maxStacks=0 (mechanic could never apply),
canBeDispelled+DispelNone inconsistency, and self-conflict
bit set in conflictsMask (mechanic blocking itself).
Format graph: 53 → 54 binary formats. CLI flag count: 784
→ 789.
2026-05-09 20:09:44 -07:00
src/pipeline/wowee_spell_mechanics.cpp
feat(pipeline): add WKBD (Wowee Keybinding) catalog
55th open format — replaces KeyBinding.dbc plus the
AzerothCore-style default-keybind SQL data. Defines the key
bindings shipped with the game: movement (W/A/S/D),
targeting (Tab), action bars (1-9, 0, -, =), UI panels
(C/I/B/P/N/L), chat (Enter), camera (Insert/Delete).
Each binding has an internal action name (SCREAMING_SNAKE
convention — "MOVE_FORWARD"), a primary key, an optional
alternate key, a category for the keybindings UI grouping,
and a flag indicating whether the user can override it.
Hardcoded engine bindings (alt-F4, ESC) set
isUserOverridable=0 so the rebind dialog can't accidentally
break them.
9 categories (Movement / Combat / Targeting / Camera /
UIPanels / Chat / Macro / Bar / Other) for the rebind
dialog grouping.
CLI: --gen-kbd (3 essential WASD/Tab/C bindings), --gen-kbd-
movement (8 movement: WASD + arrow alternates + jump +
autorun), --gen-kbd-ui (10 UI panel bindings covering all
the standard interface windows), --info-wkbd, --validate-wkbd
with --json variants. Validator catches id+actionName+
defaultKey required, category 0..8, alternateKey ==
defaultKey (no point in alt), action-name lowercase warning
(should be SCREAMING_SNAKE), duplicate primary keys (would
silently shadow earlier binding), and duplicate action names.
Format graph: 54 → 55 binary formats. CLI flag count: 791
→ 796.
2026-05-09 20:13:37 -07:00
src/pipeline/wowee_keybindings.cpp
feat(pipeline): add WSCH (Wowee Spell School) catalog
56th open format — replaces SpellSchools.dbc plus the
Resistances.dbc resistance-cap tables. Defines damage
schools spells use: Physical, Holy, Fire, Nature, Frost,
Shadow, Arcane, plus combined / hybrid schools that count
as multiple types simultaneously (Spellfire, Spellshadow,
Spellfrost — relevant for resistance-bypass mechanics).
7 canonical schools with single-bit IDs (1, 2, 4, 8, 16,
32, 64) so combinedSchoolMask values line up directly with
the spell engine's school-bit enum. Hybrid schools use
high-bit IDs (0x80000001+) and their combinedSchoolMask
references the canonical bits they qualify as. Each school
carries visual identity (color tint, icon), gameplay rules
(canBeImmune / canBeAbsorbed / canBeReflected / canCrit),
resistance cap at max level, and cast / impact sound IDs.
Cross-references with prior formats — castSoundId and
impactSoundId point at WSND.soundId; combinedSchoolMask
is a bitmask of OTHER WSCH.schoolId values within the same
catalog.
CLI: --gen-sch (3 base — Physical / Fire / Holy showing
non-resistable Holy + non-reflectable Physical), --gen-sch-
magical (6 canonical magical schools with proper colors
+ 365 max-level resistance caps), --gen-sch-combined (3
hybrids — Spellfire / Spellshadow / Spellfrost with
multi-bit combinedSchoolMask), --info-wsch, --validate-wsch
with --json variants. Validator catches id+name required,
reflected-without-absorbed warning (reflected damage
should be absorbable), self-referential combinedSchoolMask
(school qualifying as itself), and combined-mask references
to bits not defined in the same catalog (resolved at runtime
across catalogs).
Format graph: 55 → 56 binary formats. CLI flag count: 798
→ 804.
2026-05-09 20:19:34 -07:00
src/pipeline/wowee_spell_schools.cpp
feat(pipeline): add WLFG (Wowee Looking-for-Group) catalog
57th open format — replaces LFGDungeons.dbc plus the
AzerothCore-style dungeon-finder reward tables. Defines the
dungeons / raids that the Dungeon Finder / Raid Browser
presents to players, with their level brackets, group-size
requirements, role requirements (tank / heal / DPS), and
queue-completion rewards.
4 difficulty levels (Normal / Heroic / Mythic / Hardmode —
the latter for Ulduar-style toggleable boss difficulty),
4 expansion gates (Classic / TBC / WotLK / TurtleWoW), and
3 role-requirement bits (Tank / Heal / DPS — typically all
three for queue-formed groups).
Cross-references with prior formats — mapId points at
WMS.mapId (the instance map), queueRewardItemId points at
WIT.itemId (the random reward bag), firstClearAchievement
points at WACH.achievementId.
CLI: --gen-lfg (3 classic 5-mans Ragefire/Wailing/Deadmines
with real WoW mapIds + level brackets), --gen-lfg-heroic
(5 WotLK 80-level heroic 5-mans with emblem rewards +
real first-clear achievement IDs from Halls of Lightning
through Old Kingdom), --gen-lfg-raid (3 raid entries —
Naxx-25, Ulduar-25 Hardmode, ToC-25 Mythic), --info-wlfg,
--validate-wlfg with --json variants. Validator catches
id+name+mapId required, difficulty 0..3, expansion 0..3,
minLevel<=maxLevel, recommended-level outside range
warning, unusual groupSize warning (5/10/25/40 are
canonical), and zero role mask (queue can't form a
balanced group).
Format graph: 56 → 57 binary formats. CLI flag count: 804
→ 811.
2026-05-09 20:24:21 -07:00
src/pipeline/wowee_lfg.cpp
feat(pipeline): add WMAC (Wowee Macro / Slash Command) catalog
58th open format — novel format with no direct DBC equivalent.
WoW historically stored player macros client-side in the user
profile and system slash commands as hardcoded engine handlers;
WMAC unifies both into a single structured catalog so default
macros, system slash commands, and shipped player presets can
be authored, validated, and shipped as content alongside the
rest of the open-format graph.
5 macro kinds (SystemSlash for engine /sit /dance handlers,
DefaultMacro for shipped presets, PlayerTemplate for user
templates, GuildMacro for guild-shared, SharedMacro for
account-wide). Multi-line macro bodies are stored verbatim
with literal '\n' separators — the client parses /cast /
/target / /run lines at runtime.
Cross-references with prior formats — requiredClassMask uses
WCHC.classId bit positions (Warrior=0x02, etc, same as WGLY/
WSET/WGTP).
CLI: --gen-mac (3 system slash — /sit, /dance, /target with
[@mouseover] modifier), --gen-mac-combat (4 warrior combat
templates — heroic strike spam, charge/intercept stance dance,
intercept stance switch, victory rush+bloodthirst fallback —
each with default key bindings), --gen-mac-utility (3 universal
utility — /follow target, mass /inv with %targetN tokens,
/releasecorpse via RepopMe()), --info-wmac, --validate-wmac
with --json variants. Validator catches id+name+body required,
kind 0..4, body within maxLength cap, body starting with '/'
or '#' (slash command or showtooltip annotation), and
SystemSlash + classMask warning (slash commands are class-
agnostic — restricting them to a class makes no sense).
Format graph: 57 → 58 binary formats. CLI flag count: 814
→ 819.
2026-05-09 20:30:17 -07:00
src/pipeline/wowee_macros.cpp
feat(pipeline): add WCHF (Wowee Character Customization Feature) catalog
59th open format — replaces CharHairGeosets.dbc +
CharFacialHairStyles.dbc plus the variation portions of
CharSections.dbc. Defines per-(race, sex) customization
options the character creation screen exposes: skin colors,
face variations, hair styles, hair colors, facial hair
(beards / mustaches), and race-specific markings (Tauren
horns, Draenei tendrils, Blood Elf ears).
9 feature kinds (SkinColor / FaceVariation / HairStyle /
HairColor / FacialHair / FacialColor / EarStyle / Horns /
Markings) cover the full canonical customization surface.
Each entry is one selectable carousel choice for one
(race, sex, kind) tuple — variationIndex disambiguates.
expansionGate enum gates Blood Elf / Draenei (TBC) and DK
features (WotLK) behind the right expansion unlock.
Cross-references with prior formats — raceId points at
WCHC.race.raceId. requiresExpansion bit positions match
the WLFG expansion enum (Classic=0, TBC=1, WotLK=2,
Turtle=3) for consistency.
CLI: --gen-chf (5 Human Male starter — skin / face / 2
hair styles / facial hair), --gen-chf-bloodelf (8 Blood
Elf Female hair styles, requiresExpansion=TBC — the
iconic TBC race feature), --gen-chf-tauren (6 Tauren Male
features using race-specific Horns kind + 3 facial hair
variations), --info-wchf, --validate-wchf with --json
variants. Validator catches id+name+raceId+texturePath
required, kind 0..8 / sex 0..1 / expansion 0..3, and the
critical (race, sex, kind, variation) tuple-uniqueness
check — duplicates would shadow each other in the create-
character carousel.
Format graph: 58 → 59 binary formats. CLI flag count: 819
→ 826.
2026-05-09 20:35:21 -07:00
src/pipeline/wowee_char_features.cpp
feat(pipeline): add WPVP (Wowee PvP Honor / Rank) — 60th open format
60th open format milestone — replaces the AzerothCore-style
PvP rank tables plus the vanilla honor-rank reward chains.
Defines PvP progression rungs: vanilla honor ranks (Private
through Grand Marshal / High Warlord), arena rating brackets
(Combatant / Challenger / Rival / Duelist / Gladiator), and
battleground rated tiers.
5 rank kinds (VanillaHonor / ArenaRating / BattlegroundRated /
WorldPvP / ConquestPoint) cover the canonical PvP progression
surface. Each entry carries an alliance-specific name and a
horde-specific name (Grand Marshal = High Warlord; arena tiers
share the same name on both factions), an honor or rating
threshold, and optional gear cross-refs (chest, gloves,
shoulders) into WIT.
Cross-references with prior formats — titleId points at
WTTL.titleId (the unlock title), chest/gloves/shoulders point
at WIT.itemId for the matching PvP set, bracketBgId points at
WBGD.bgId for battleground-bracket gating.
CLI: --gen-pvp (3 vanilla entry tiers Rank2-4 with alliance
vs horde alternate names), --gen-pvp-alliance (9 vanilla
ranks 6-14 with WTTL+WIT cross-refs and ramping honor
thresholds 50k → 260k), --gen-pvp-arena (5 arena rating
brackets 1500/1750/2000/2200/2400 with 10/20/40/80/160 emblem
rewards), --info-wpvp, --validate-wpvp with --json variants.
Validator catches id+name required, kind 0..4, level range
valid, faction-name pairing (one set without the other is a
typo), threshold monotonicity within a rankKind, arena rating
below 1500 floor, and VanillaHonor with minHonor=0 baseline
warning.
Format graph: 59 → 60 binary formats (milestone). CLI flag
count: 826 → 833.
2026-05-09 20:41:09 -07:00
src/pipeline/wowee_pvp.cpp
feat(pipeline): add WBNK (Wowee Bag / Bank Slot) catalog
61st open format — replaces ItemBag.dbc plus the bank-storage
and special-purpose container tables. Defines every slot the
player has access to: equipped bags, bank bags, keyring, soul
shard bag, quiver, reagent bag, hunter pet stable.
8 bag kinds (Inventory / Bank / Keyring / Quiver / SoulShard /
Stable / Reagent / Wallet) cover the canonical container
surface. Each entry has a fixed capacity (or 0 = variable,
size set by equipped bag), a display order in the inventory
UI, an unlock state with optional gold cost (bank bags ramp
through 10s / 1g / 10g / 25g / 50g / 100g matching canonical
WoW prices), and an accepts-bag-subclass mask gating which
container kinds may be equipped (generic / herb / enchanting
/ engineer / gem / mining / leather / inscription / quiver /
ammo pouch).
Cross-references with prior formats — fixedBagItemId points
at WIT.itemId for the bag item that always occupies a fixed
slot (0 = player-equipable variable slot).
CLI: --gen-bnk (5 inventory slots — 16-slot fixed main
backpack + 4 player-equippable bag slots accepting generic
containers + herb + enchanting bags), --gen-bnk-bank (8 bank
bag slots with the canonical WoW unlock cost ramp),
--gen-bnk-special (4 special-purpose: 32-slot Keyring fixed,
warlock SoulShardBag, hunter ArrowQuiver, hunter
HuntersStable for 5 pets), --info-wbnk, --validate-wbnk with
--json variants. Validator catches id+name required, kind
0..7, locked-with-zero-cost (slot can never be unlocked),
fixed-slot-with-non-zero-mask (equippable bag would be
ignored), variable slot with empty mask (no bag can fit),
and ambiguous (bagKind, displayOrder) tuples (UI sort would
flicker).
Format graph: 60 → 61 binary formats. CLI flag count: 833
→ 840.
2026-05-09 20:46:06 -07:00
src/pipeline/wowee_bags.cpp
feat(pipeline): add WRUN (Wowee DK Rune Cost) catalog
62nd open format — replaces RuneCost.dbc plus the DK-specific
portions of ChrPowerType. Defines per-spell rune costs (Blood
/ Frost / Unholy) and runic-power generation / consumption
for the Death Knight class.
4 spell tree branches (BloodTree / FrostTree / UnholyTree /
Generic) classify which spec uses each rune cost. Each entry
binds a spell to its rune cost (how many of each rune kind
the spell consumes), an optional anyDeathConvertCost (extra
Death-rune-acceptable cost for procced abilities), and a
runicPowerCost (negative = generator, positive = spender).
Cross-references with prior formats — spellId points at
WSPL.spellId (the spell that uses this rune cost).
CLI: --gen-rune (3 baseline DK abilities — Death Strike
1F+1U + 20RP gen, Frost Strike pure 40 RP spender, Heart
Strike 1B + 10RP gen), --gen-rune-blood (4 blood-tree DK
abilities — Heart Strike, Death and Decay AoE, Vampiric
Blood tank cooldown, Rune Tap self-heal), --gen-rune-frost
(4 frost-tree — Frost Strike, Howling Blast AoE, Obliterate
finisher, Icy Touch ranged opener applying Frost Fever),
--info-wrun, --validate-wrun with --json variants. Validator
catches id+name+spellId required, branch 0..3, no rune cost
> 2 (DK only has 2 of each rune type so a higher cost can
never be paid), runicPowerCost > 100 (DK RP cap), no-cost
warning (spell consumes nothing — verify it's a
passive/stance/form), and high-RP-generator warning (> 25
RP per cast is unusual).
Format graph: 61 → 62 binary formats. CLI flag count: 840
→ 847.
2026-05-09 20:52:19 -07:00
src/pipeline/wowee_runes.cpp
feat(pipeline): add WLDS (Wowee Loading Screen) catalog
63rd open format — replaces LoadingScreens.dbc plus the
per-zone background-image tables. Defines the loading-screen
images shown when the client crosses into a new map /
instance, with optional level-bracket gating and expansion
gating (TBC art only shown if expansion installed).
When multiple screens match the player's current map + level
+ expansion, displayWeight selects randomly between them — a
zone with 3 weighted variants gets a different image roughly
proportional to weight.
4 expansion gates (Classic / TBC / WotLK / TurtleWoW),
isAnimated flag for screens with subtle animation,
isWideAspect flag for 16:9 raid intro art (vs 4:3 standard).
Cross-references with prior formats — mapId points at
WMS.map.mapId (which map triggers this loading screen);
mapId=0 is the catch-all sentinel for screens shown when
no map-specific screen matches.
CLI: --gen-lds (3 base screens — Elwynn level 1-30, Orgrimmar,
GenericFallback level 31-80 catch-all), --gen-lds-instances
(5 WotLK dungeon screens with mapId+expansion cross-refs:
Halls of Lightning/Stone, Utgarde Pinnacle, Violet Hold,
Old Kingdom), --gen-lds-raid (3 raid intro screens —
Naxxramas/Ulduar/ToC at isWideAspect=1 with weight=3),
--info-wlds, --validate-wlds with --json variants. Validator
catches id+name+texture required, expansion 0..3, level range
valid, weight=0 (in pool but never picked), and the practical
catch-all overlap warning when multiple mapId=0 screens share
overlapping level brackets (random pick becomes
non-deterministic).
Format graph: 62 → 63 binary formats. CLI flag count: 847
→ 854.
2026-05-09 20:59:25 -07:00
src/pipeline/wowee_loading_screens.cpp
feat(pipeline): add WSUF (Wowee Item Random Suffix) catalog
64th open format — replaces ItemRandomProperties.dbc +
ItemRandomSuffix.dbc plus the AzerothCore-style suffix-roll
tables. Defines random "of the X" suffixes that roll on
green and blue items at world drop ("Sturdy Cloth Cap of
the Bear" = base item + STR + STA suffix).
5 suffix categories (Generic / Elemental / Defensive /
PvPSuffix / Crafted), per-suffix item-quality bracket gating
(only blue+ items can roll PvPSuffix), restricted-slot mask
that limits which equipment slots a suffix can apply to (15
slot bits matching WCEQ slot enum), and up to 5 stat bonus
slots per suffix matching WoW canonical max.
statValuePoints isn't an absolute number — it's a scaling
base that the runtime multiplies by an item-level
coefficient to compute the final per-item bonus, so "of the
Bear" gives proportionally more strength on a level-60 item
than on a level-20 item.
Cross-references with prior formats — statKind values match
WIT.statType enum (STR=4, AGI=3, INT=5, SPI=6, STA=7) so
item generators roll consistent stats with base items.
CLI: --gen-suf (3 generic stat triads — Bear STR+STA, Eagle
INT+SPI, Tiger STR+AGI), --gen-suf-magical (4 elemental
spell-power suffixes restricted to caster-eligible slots),
--gen-suf-pvp (3 PvPSuffix entries with resilience + offensive
stats, blue+ quality only), --info-wsuf, --validate-wsuf with
--json variants. Validator catches id+name required, category
0..4, quality range valid (0..7 covers heirloom), itemQuality
floor<=ceiling, stat-kind/value pairing (kind=0 with value!=0
is a typo, vice versa), and no-stats warning (suffix renames
item without changing it).
Format graph: 63 → 64 binary formats. CLI flag count: 854
→ 861.
2026-05-09 21:05:49 -07:00
src/pipeline/wowee_item_suffixes.cpp
feat(pipeline): add WCRR (Wowee Combat Rating Conversion) catalog
65th open format — replaces gtCombatRatings.dbc plus the
per-level rating-to-percentage tables in gtRegenHPPerSpt.dbc
and related stat-curve DBCs. Defines per-rating-type
conversion factors at canonical level breakpoints (1 / 60
/ 70 / 80) — the runtime linearly interpolates between
breakpoints for intermediate levels.
pointsAtLevelN is "how many rating points equal 1% of the
benefit at that level." Higher level = more rating needed
for the same %. Standard WoW WotLK example: 14 crit rating
= 1% crit at L60, but 45.91 = 1% at L80.
5 rating kinds (Combat / Defense / Spell / Resilience /
Other) classify what stat resolver category each rating
belongs to.
CLI: --gen-crr (3 essential combat ratings — Hit/Crit/Haste
at canonical WoW WotLK conversion values), --gen-crr-defensive
(4 defensive — Defense/Dodge/Parry/Block with diminishing-
returns soft-cap percentages), --gen-crr-spell (3 spell —
SpellPower direct 1:1, SpellPenetration flat, MP5 mana
regen), --info-wcrr, --validate-wcrr with --json variants.
Validator catches id+name required, kind 0..4, all
pointsAtLN > 0 (otherwise stat resolver would div-by-zero),
maxBenefitPercent > 0 (rating would never grant any
benefit), and non-monotonic conversion curve warning
(rating cost typically ascends with level for non-flat
ratings like SpellPower).
Format graph: 64 → 65 binary formats. CLI flag count: 861
→ 868.
2026-05-09 21:11:26 -07:00
src/pipeline/wowee_combat_ratings.cpp
feat(pipeline): add WUMV (Wowee Unit Movement Type) catalog
66th open format — replaces UnitMovement.dbc plus the
movement-modifier portions of CreatureModelData.dbc. Defines
movement speed types (walk / run / swim / flight / fly /
pitch) with their canonical baseline speeds in yards-per-
second, plus the temp speed buffs that stack on top
(Sprint, Aspect of the Cheetah, Travel Form).
12 movement categories cover the canonical surface (Walk /
Run / Backward / Swim / SwimBack / Turn / Flight /
FlightBack / Pitch / Fly / FlyBack / TempBuff). baseSpeed
is yards/second for baseline categories and ignored for
TempBuff entries (which use baseMultiplier instead).
maxMultiplier caps stacking — Sprint capped at 1.4 means
Sprint + Aspect of Cheetah doesn't exceed 1.4× run speed.
stackingPriority resolves conflicts when multiple buffs
of equal multiplier compete (higher wins).
CLI: --gen-umv (4 baseline at canonical WoW vanilla speeds:
Walk 2.5y/s, Run 7.0y/s, Swim 4.7y/s, Turn π rad/s),
--gen-umv-flight (5 flight entries — ground-rail Flight
7y/s, free Fly 14y/s, Pitch 1.5 rad/s, backward variants
at slower 4.5y/s), --gen-umv-buffs (5 temp speed buffs
matching real WoW spell auras with proper durations and
stacking priorities), --info-wumv, --validate-wumv with
--json variants. Validator catches id+name required,
category 0..11, baseMultiplier > 0 (otherwise unit freezes
in place), maxMultiplier >= baseMultiplier (cap below
floor would clamp the base down), baseline categories
need baseSpeed > 0, and Run < 3.0y/s warning (canonical
is 7.0y/s).
Format graph: 65 → 66 binary formats. CLI flag count: 870
→ 875.
2026-05-09 21:18:03 -07:00
src/pipeline/wowee_unit_movement.cpp
feat(pipeline): add WQSO (Wowee Quest Sort) catalog
67th open format — replaces QuestSort.dbc plus the quest-log
categorization fields in QuestInfo.dbc. Defines the
categories that quests fall into for the quest-log UI:
class quests (Warrior trial, etc), profession quests, daily
quests, holiday events, reputation grinds, dungeon /
heroic / raid quests, repeatables, PvP, tournament.
12 sort kinds (General / ClassQuest / Profession / Daily /
Holiday / Reputation / Dungeon / Raid / Heroic / Repeatable
/ PvP / Tournament). Each WQT (quest) entry can reference
a sortId here to be grouped under the right header in the
quest log. Sorts can be class-restricted (Warrior quests
only show for warriors), profession-restricted, or
faction-reputation-gated.
Cross-references with prior formats — targetClassMask uses
WCHC.classId bit positions (matches WGLY/WSET/WGTP
convention), targetProfessionId points at WTSK.profession
enum, targetFactionId points at WFAC.factionId.
CLI: --gen-qso (3 generic sorts — General catch-all, Daily
reset, Repeatable non-daily), --gen-qso-class (10 class-
specific sorts with proper bit masks for Warrior 0x02
through Druid 0x800), --gen-qso-profession (8 profession
sorts with WTSK profession enum cross-refs), --info-wqso,
--validate-wqso with --json variants. Validator catches
id+name+displayName required, kind 0..11, ClassQuest with
classMask=0 (not actually class-restricted), Profession
with profId=0 + non-Blacksmithing-name (likely typo since
0=Blacksmithing in WTSK), and Reputation with factionId=0
(no faction to grind).
Format graph: 66 → 67 binary formats. CLI flag count: 877
→ 882.
2026-05-09 21:23:38 -07:00
src/pipeline/wowee_quest_sorts.cpp
feat(editor): add WSRG (Spell Range Index) open catalog format
Open replacement for Blizzard's SpellRange.dbc plus the per-spell
range-bucket fields in Spell.dbc. Defines the categorical range
buckets that spells reference instead of carrying their own min/max
yards (every Frostbolt shares one 30y bucket; every Heal shares
one 40y friendly bucket). Each entry carries separate min/max for
hostile vs friendly targets so heals can reach further on allies
than nukes do on enemies, plus an icon color for HUD range
indicators.
Three preset emitters: --gen-srg (3 baseline buckets:
Self/Melee/Spell), --gen-srg-ranged (5 ranged spell buckets:
Short/Medium/Long/VeryLong/Unlimited), --gen-srg-friendly (3
friendly-only buckets where hostile range is 0). --info-wsrg and
--validate-wsrg round out the per-format surface; validation
catches negative ranges, min>max, duplicate ids, out-of-range
rangeKind, and warns on Self+nonzero range or Melee>8y.
Wired through the cross-format table so WSRG appears automatically
in --list-formats, --info-magic, --diff-headers, --summary-dir,
--rename-by-magic, --catalog-grep, --tree-summary-md, and
--touch-tree. Format count 67 -> 68; CLI flag count 885 -> 890.
2026-05-09 21:33:17 -07:00
src/pipeline/wowee_spell_ranges.cpp
2026-05-09 21:37:42 -07:00
src/pipeline/wowee_spell_cast_times.cpp
feat(editor): add WSDR (Spell Duration Index) — completes WSRG/WSCT/WSDR triplet
Open replacement for SpellDuration.dbc plus per-spell duration
fields in Spell.dbc. Defines the categorical duration buckets
that auras / DoTs / HoTs / buffs reference (5s / 30s / 5min / 1hr
/ UntilCancelled / UntilDeath).
Together with WSRG (range) and WSCT (cast time), this completes a
small triplet of spell-metadata catalogs: instead of every
Frostbolt rank embedding its own range, cast time, and
chill-debuff duration as duplicate fields, each spell holds three
small integer ids that resolve through these three tables. The
engine retunes thousands of spells at once by editing one bucket.
Duration scales with caster level via perLevelMs (a rank-1 Renew
at 9s grows to 12s at lvl 60), then is clamped to maxDurationMs.
Negative baseDurationMs is the canonical sentinel for "no timer"
(UntilCancelled / UntilDeath); resolveAtLevel returns -1 for
those so HUD code can render the indefinite-duration glyph.
Three preset emitters: --gen-sdr (5 baseline tiers from instant
to one-hour), --gen-sdr-buffs (4 long-duration buffs including
UntilDeath), --gen-sdr-dot (4 tick-based DoT/HoT buckets at 3s
ticks). Validation enforces base>0 for Timed/TickBased, base<0
for permanent kinds, max>=base, durationKind 0..4, no duplicate
ids, and warns on Instant+nonzero base.
Wired through the cross-format table; WSDR appears automatically
in all 9 cross-format utilities. Format count 69 -> 70; CLI flag
count 899 -> 904.
2026-05-09 21:41:55 -07:00
src/pipeline/wowee_spell_durations.cpp
2026-05-09 21:49:13 -07:00
src/pipeline/wowee_spell_cooldowns.cpp
feat(editor): add WCEF (Creature Family) open catalog format
Open replacement for CreatureFamily.dbc plus the per-creature
family fields in Creature.dbc. Defines the family categorization
that pet-able beasts share (Bear / Cat / Wolf / Boar / Crab /
Raptor / Devilsaur / etc), each with its own pet talent tree
(Ferocity / Tenacity / Cunning), food preferences as a bitmask
(Meat / Fish / Bread / Cheese / Fruit / Fungus / Raw), the skill
line that family-specific abilities reference, and the minimum
hunter level required to tame it.
Used by the hunter pet system to decide which talent tree a tamed
pet uses, validate that a hunter can tame a creature, match
feeding-table food items to pet preferences, and gate exotic-beast
families behind the Beast Master 51-point talent.
Cross-references back to WCRT (creature.familyId points here) and
WSPL (family-specific abilities reference WSPL spellId via the
skillLine field).
Three preset emitters: --gen-cef (5 baseline families covering
both major talent trees), --gen-cef-ferocity (4 DPS-tree pets
with bleed/howl/armor-shred mechanics), --gen-cef-exotic (4
exotic Beast Master families requiring 51-point talent).
Validation enforces id+name presence, familyKind 0..5, talent
tree 0..3, no duplicate ids, and warns on:
- NotPet families with a non-None talent tree (irrelevant)
- Exotic families with minLevelForTame > 80 (level-cap unreachable)
- Beast/Exotic families with no food types set (pet would starve)
Wired through the cross-format table; WCEF appears automatically
in all 10 cross-format utilities. Format count 71 -> 72; CLI flag
count 914 -> 919.
2026-05-09 21:54:00 -07:00
src/pipeline/wowee_creature_families.cpp
feat(editor): add WSPC (Spell Power Cost) — completes spell-bucket five-pack
Open replacement for the per-spell power-cost fields in Spell.dbc
plus SpellPowerCost-related side tables. Defines categorical
power-cost buckets that spells reference (LowMana 5% / MediumMana
15% / HighMana 30% of caster max mana; fixed Rage-30 /
Energy-40 / Runic-30 / etc), so spells share cost metadata across
ranks instead of embedding per-rank cost numbers.
Completes the small lookup-bucket five-pack:
WSRG — range bucket
WSCT — cast time bucket
WSDR — duration bucket
WSCD — cooldown bucket
WSPC — power cost bucket (this catalog)
Five small integer ids per spell (range / cast / dur / cd / cost)
replace the dozens of duplicate per-rank fields that Blizzard's
Spell.dbc carries. Editing one bucket here retunes every spell
that references it — change LowMana from 5% to 4% and every
rank-1 bolt across every caster class becomes cheaper.
Cost can be flat (baseCost), per-level scaled (perLevelCost), or
percentage-of-max-power (percentOfBase) — the engine sums
whichever fields are non-zero. resolveCost(id, level, maxPower)
does the math. Twelve power types covering every WoW resource
(Mana / Rage / Focus / Energy / Happiness / Runic Power / Runes /
Soul Shards / Holy Power / Eclipse / Health / NoCost).
Three preset emitters: --gen-spc (4 baseline mana tiers),
--gen-spc-rage (4 fixed warrior rage costs including stance-locked
Whirlwind), --gen-spc-mixed (5 cross-class costs covering every
non-mana power type with refund-on-miss flag for energy).
Validation enforces id+name presence, powerType 0..11, no
duplicate ids; warns on percentOfBase outside [0,1] (would
overflow), NoCost type with non-zero cost fields, and non-NoCost
types with no cost set (would cast for free — easy bug to ship).
Wired through the cross-format table; WSPC appears automatically
in all 11 cross-format utilities. Format count 72 -> 73; CLI flag
count 922 -> 927.
2026-05-09 22:00:55 -07:00
src/pipeline/wowee_spell_power_costs.cpp
feat(editor): add WGFS (Glyph Slot) open catalog format
Open replacement for Blizzard's GlyphSlot.dbc. Defines the
per-class glyph slot layout: which slots a class has (Major /
Minor / Prime), in which display order they appear in the
spellbook UI, and at which character level each slot becomes
available for use.
Distinct from WGLY (GlyphProperties) which defines the individual
glyphs themselves. WGLY says "Glyph of Polymorph exists, costs 1
inscription dust, modifies Polymorph"; WGFS says "the slot that
holds Glyph of Polymorph is the second Major Glyph Slot, unlocks
at level 25, and only Mages have it".
Layout grew across expansions, captured by the three presets:
- --gen-gfs — 6 slots: 3 Major + 3 Minor all-class
baseline (25/50/75 each)
- --gen-gfs-wotlk — 6 slots: 3 Major (15/30/50) + 3 Minor
(15/50/70) matching WotLK 3.3.5a
- --gen-gfs-cata — 9 slots: 3 Prime + 3 Major + 3 Minor
matching Cataclysm
Cross-references back to WGLY (glyphs reference slotKind to
constrain which glyph fits which slot) and WCHC (requiredClassMask
uses the same bit layout as WCHC class IDs).
Validation enforces id+name+classMask presence (classMask=0 means
no class can use the slot — usually a config bug), slotKind 0..2,
no duplicate ids; warns on minLevelToUnlock>80 (would never
unlock at WotLK cap), displayOrder>4 (UI typically shows 3-4),
and (kind+order) collisions for overlapping classMask (two slots
claiming the same UI position would render on top of each other).
isUnlockedFor(id, classBit, level) is the engine helper.
Wired through the cross-format table; WGFS appears automatically
in all 11 cross-format utilities. Format count 73 -> 74; CLI flag
count 929 -> 934.
2026-05-09 22:05:05 -07:00
src/pipeline/wowee_glyph_slots.cpp
feat(editor): add WCDF (Creature Difficulty) open catalog format
Open replacement for Blizzard's CreatureDifficulty.dbc. Maps a
base creature entry to its difficulty variants:
Normal-10 / Normal-25 / Heroic-10 / Heroic-25 in WotLK raid
format. Each variant is itself a separate WCRT creature entry
with its own stats, abilities, and loot.
When a 25-man party engages an instance, the engine looks up the
encounter base creature's difficultyId, reads the normal25Id
field, and spawns that variant instead. This is how Lord
Marrowgar in 25-Heroic ICC has 30M HP and hits for 80k while the
same encounter in 10-Normal has 5M HP and hits for 25k — same
spawn point, different WCRT entries.
5-man dungeons typically use only normal10Id + heroic10Id (the
25-man fields stay 0 — engine falls through to the 10-man
variant when 25-man is queried). World bosses don't scale at
all (all 4 variant fields stay 0, engine falls back to the base
entry).
Cross-references back to WCRT — every non-zero variant id field
points at a WCRT.creatureId entry; the base creature itself
lives in WCRT too.
Three preset emitters: --gen-cdf (4 example bosses with full
4-variant routing), --gen-cdf-wotlk-raid (4 ICC-style raid
bosses Marrowgar/Deathwhisper/Saurfang/LK with all 4 difficulty
variants), --gen-cdf-fiveman (4 5-man dungeon bosses with only
Normal+Heroic 10-man set). resolveVariant(id, mode) is the
engine helper.
Validation enforces id+name+baseCreatureId presence,
spawnGroupKind 0..5, no duplicate ids; warns on:
- WorldBoss kind with non-zero variant ids (world bosses don't scale)
- duplicate baseCreatureId across routes (only first honored)
- all-self-reference non-WorldBoss (creature doesn't actually scale)
- Boss with n25 but not n10 (raid sequencing typo — n10 always
comes with n25)
Wired through the cross-format table; WCDF appears automatically
in all 11 cross-format utilities. Format count 74 -> 75; CLI flag
count 936 -> 941.
2026-05-09 22:10:09 -07:00
src/pipeline/wowee_creature_difficulties.cpp
feat(editor): add WMAT (Item Material) open catalog format
Open replacement for Blizzard's Material.dbc plus the Material
and SheatheType fields in ItemDisplayInfo.dbc. Defines the
material categorization that items reference (Cloth / Leather /
Mail / Plate / Wood / Steel / Crystal / Ethereal / etc), each
with its own foley sound (played on item use), impact sound
(played on drop / hit), weight category, and material-property
flags (IsBreakable / IsMagical / IsFlammable / IsConductive /
IsHolyCharged / IsCursed).
The engine plays a sword's metallic clang from impactSoundId
when it hits a stone wall, but a cloth tabard makes no such
sound — the difference is exactly the material assigned by this
catalog. Every armor and weapon item in WIT references a
materialId here.
Twelve materialKind values cover the standard armor classes
(Cloth/Leather/Mail/Plate/Hide), structural materials (Wood /
Stone / Metal), and special categories (Liquid / Organic /
Crystal / Ethereal). Three weight tiers (Light / Medium / Heavy)
control encumbrance UI hints.
Cross-references back to WSND (foleySoundId / impactSoundId
reference WSND sound entries) and forward to WIT (item entries
reference materialId here).
Three preset emitters: --gen-mat (5 armor materials matching
WoW's armor classes), --gen-mat-weapon (5 weapon materials from
breakable+flammable Wood through enchanted endgame steel),
--gen-mat-magical (4 magical materials with special flags
including the IsHolyCharged anti-undead property).
Validation enforces id+name presence, materialKind 0..11,
weightCategory 0..2, no duplicate ids; warns on:
- IsHolyCharged + IsCursed both set (engine picks one,
typically IsCursed wins)
- Plate kind that's not Heavy weight (canonical violation)
- Cloth kind that's not Light weight (canonical violation)
Wired through the cross-format table; WMAT appears automatically
in all 11 cross-format utilities. Format count 75 -> 76; CLI flag
count 943 -> 948.
2026-05-09 22:14:44 -07:00
src/pipeline/wowee_item_materials.cpp
feat(editor): add WPSP (Player Spawn Profile) open catalog format
Open replacement for AzerothCore's playercreateinfo SQL table
plus the per-class/race starting fields in CharStartOutfit.dbc.
Defines the initial state for a newly created character: starting
map / zone / position / facing, bind point (Hearthstone
destination), up to 4 starting items with counts, and up to 4
starting spells.
One entry per (race, class) combination — a Human Warrior spawns
at Northshire Abbey with a Worn Shortsword and Heroic Strike
already learned, while an Orc Hunter spawns in Valley of Trials
with Aimed Shot and a starter rifle. Death Knights have their
own preset spawning at lvl 55 in Acherus, the Ebon Hold.
The race+class fields are bitmasks (mirroring WCHC layout) so
one profile entry can cover multiple class/race combinations
that share starting state. findByRaceClass(raceBit, classBit)
is the engine helper used by character creation.
Cross-references back to WCHC (race/class bit layouts), WMS (map
ids), WIT (starting item ids), and WSPL (starting spell ids).
Three preset emitters: --gen-psp (5 Alliance combos covering
each starting zone from Northshire to Ammen Vale), --gen-psp-horde
(5 Horde combos from Valley of Trials to Sunstrider Isle),
--gen-psp-dk (2 DK combos at lvl 55 in Acherus with Death Coil /
Plague Strike / Death Grip starter loadout).
Validation enforces id+name+race+class+startingLevel presence,
no duplicate ids; warns on (0,0,0) spawn (uninitialized entry),
item id/count mismatch (granted item without count or vice versa),
startingLevel > 80 (above WotLK cap), and Death Knight class
with startingLevel < 55 (DKs canonically start at 55).
Wired through the cross-format table; WPSP appears automatically
in all 12 cross-format utilities. Format count 76 -> 77; CLI flag
count 951 -> 956.
2026-05-09 22:22:57 -07:00
src/pipeline/wowee_player_spawn_profiles.cpp
feat(editor): add WTLE (Talent Tab) open catalog format
Open replacement for Blizzard's TalentTab.dbc plus the per-tab
fields in Spell.dbc / Talent.dbc. Defines the three talent trees
that each class has — Warrior: Arms / Fury / Protection;
Mage: Arcane / Fire / Frost; Paladin: Holy / Protection /
Retribution; etc.
Each tab carries its own name, role hint (DPS / Tank / Healer /
Hybrid / PetClass), display order in the talent UI, background
artwork path (e.g. "WarriorArms" for the parchment background),
icon path, and the class bitmask it belongs to.
Distinct from WTAL (which defines individual talent points) —
WTLE says "the Arms tree exists for Warriors, displays in tab 1,
is a DPS spec"; WTAL says "Mortal Strike is a 1-point talent in
the Arms tree, row 7, requires Improved Charge as a prerequisite".
Cross-references back to WCHC (classMask uses the same bit
layout) and forward to WTAL (talent entries reference tabId
here). findByClass(classBit) returns all tabs for a class
sorted by displayOrder — the talent UI uses this directly to
populate its tab buttons.
Three preset emitters: --gen-tle (Warrior 3 tabs with two DPS +
one Tank), --gen-tle-mage (Mage 3 DPS tabs), --gen-tle-paladin
(Paladin 3 tabs covering all three roles in one preset).
Validation enforces id+name+classMask presence (classMask=0
means no class can use the tab — usually a config bug),
roleHint 0..4, no duplicate ids; warns on empty iconPath
(missing-texture render), empty backgroundFile (no panel art),
displayOrder>3 (UI shows at most 4 tabs), and (classMask +
displayOrder) collisions for overlapping classes (two tabs
claiming the same UI slot for the same class).
Wired through the cross-format table; WTLE appears automatically
in all 12 cross-format utilities. Format count 77 -> 78; CLI flag
count 958 -> 963.
2026-05-09 22:27:18 -07:00
src/pipeline/wowee_talent_tabs.cpp
feat(editor): add WCTR (Currency Type) open catalog format
Open replacement for Blizzard's CurrencyTypes.dbc plus the
per-currency cap tables in CurrencyCategory.dbc. Defines the
in-game currencies that are NOT regular item stacks: Honor
Points, Arena Points, Justice Points, Valor Points, Conquest
Points, plus the various faction tokens (Champion's Seal,
Wintergrasp Mark of Honor, Emblem of Frost).
Distinct from regular items in WIT — currencies are tracked
per-character as scalar quantities with weekly + absolute caps,
not as stackable inventory slots. Some currencies are still
backed by a WIT item entry for the icon and tooltip text
(itemId field), while others (Honor, Arena) live entirely in
the currency system.
The cap model captures both shapes:
- maxQuantity = absolute lifetime cap (Honor Points 75k)
- maxQuantityWeekly = weekly earn cap, no absolute cap
(Conquest Points 1650/wk)
- both 0 = uncapped (faction tokens, Emblem of Frost)
earnableNow(id, current, weekly) is the engine helper that
returns the smaller of (remaining absolute, remaining weekly).
Cross-references back to WIT (itemId for tooltip art) and
WFAC (categoryId references factionId for FactionToken kind —
the rep gate that lets you spend the token).
Three preset emitters: --gen-ctr (4 PvP currencies covering
absolute, weekly-only, and uncapped tiers), --gen-ctr-pve (4
PvE raid currencies with same cap variety), --gen-ctr-faction
(4 faction tokens with their categoryId pointing at WFAC
faction ids).
Validation enforces id+name presence, currencyKind 0..5, no
duplicate ids; warns on:
- maxQuantityWeekly > maxQuantity (weekly cap will never be
reached, absolute cap blocks first)
- FactionToken kind with categoryId=0 (rep gate breaks)
- no caps + no itemId + no iconPath (currency has no display
data and unbounded earn rate)
Wired through the cross-format table; WCTR appears automatically
in all 12 cross-format utilities. Format count 78 -> 79; CLI flag
count 965 -> 970.
2026-05-09 22:31:42 -07:00
src/pipeline/wowee_currency_types.cpp
2026-05-09 22:38:36 -07:00
src/pipeline/wowee_spell_reagents.cpp
feat(editor): add WACR (Achievement Criteria) open catalog format
Open replacement for Blizzard's Achievement_Criteria.dbc. Defines
the individual progression criteria that a character must
complete to earn an achievement.
Each WACH achievement has a tree of WACR criteria — "Kill 100
boars" is one criteria entry with criteriaType=KillCreature,
targetId=boarCreatureId, requiredCount=100. Multi-criteria
achievements (e.g. "Visit all 3 capital cities") have one entry
per sub-objective, all referencing the same achievementId, with
progressOrder determining their display sequence in the
achievement UI.
Thirteen criteriaType values cover the full progression variety:
KillCreature / ReachLevel / CompleteQuest / EarnGold /
GainHonor / EarnReputation / ExploreZone / LootItem /
UseItem / CastSpell / PvPKill / DungeonRun / Misc
The targetId field is type-polymorphic — for KillCreature it
references WCRT.creatureId, for CompleteQuest it references
WQT.questId, for ExploreZone it's a WMS.zoneId, etc. The engine
interprets it based on criteriaType.
Cross-references back to WACH (achievementId), WCRT
(KillCreature.targetId), WQT (CompleteQuest.targetId), WIT
(LootItem/UseItem.targetId), WMS (ExploreZone.targetId), WSPL
(CastSpell.targetId). findByAchievement(achId) returns all
criteria for an achievement sorted by progressOrder — used
directly by the achievement UI to render the progress checklist.
Three preset emitters: --gen-acr (5 kill criteria under one
composite achievement showing different creature targets),
--gen-acr-quest (4-step quest progression), --gen-acr-mixed
(5 cross-type criteria demonstrating the full CriteriaType
variety).
Validation enforces id+name+achievementId presence,
criteriaType 0..12, no duplicate ids; warns on:
- missing targetId for type-specific kinds (KillCreature,
CompleteQuest, etc. — engine cannot track without it)
- ReachLevel with requiredCount > 80 (above WotLK cap)
- timeLimitMs set on non-time-sensitive types (engine
ignores it for ReachLevel / EarnGold)
- requiredCount=0 (criteria completes instantly on first
progress event — usually a misconfig)
Wired through the cross-format table; WACR appears automatically
in all 14 cross-format utilities. Format count 80 -> 81; CLI flag
count 981 -> 986.
2026-05-09 22:43:44 -07:00
src/pipeline/wowee_achievement_criteria.cpp
feat(editor): add WSEF (Spell Effect Type) open catalog format
Open replacement for the SpellEffect.Effect field meanings in
Spell.dbc plus the engine's hard-coded effect dispatch table.
Defines what each spell-effect integer value actually does —
SCHOOL_DAMAGE=2 deals magical damage, DUMMY=3 is a script hook,
HEAL=10 restores health, ENERGIZE=30 restores power,
APPLY_AURA=6 attaches a buff/debuff, etc.
WotLK's Spell.dbc has 192+ effect type integers, each with its
own resolver in the spell engine. This catalog lets the engine
look up "given effect=10, what resolution behavior do I run?"
via a single table lookup instead of a hard-coded switch
statement, and lets server-custom spells reference new effect
IDs without touching engine code.
Ten effectKind values capture the major behavior families
(Damage / Heal / Aura / Energize / Trigger / Movement / Summon /
Dispel / Dummy / Misc), and a 6-bit behaviorFlags field
captures targeting/gating semantics:
- RequiresTarget — must have a target
- RequiresLineOfSight — LoS check on target
- IsHostileEffect — hostile only (PvP gating)
- IsBeneficialEffect — friendly only
- IgnoresImmunities — bypasses Bubble / IBF / etc
- TriggersGCD — counts toward GCD
Distinct from WAUR (Spell Aura Type, future format) which is the
secondary classification used when effectType is APPLY_AURA. The
two together cover the full spell-effect classification space.
Three preset emitters: --gen-sef (5 damage effects covering
typical Spell.dbc damage IDs), --gen-sef-healing (4 heal
effects all flagged IsBeneficialEffect), --gen-sef-aura (5
aura-application effects covering single-target / pet /
party-wide / area variants).
Validation enforces name presence, effectKind 0..9, no duplicate
ids; warns on:
- both Hostile and Beneficial flags set (engine picks Hostile,
contradiction suggests config bug)
- Damage kind without TriggersGCD (most damage should be on GCD
— env damage is the canonical exception)
- Heal kind without IsBeneficialEffect (engine treats heal as
ungated, may damage enemies)
Wired through the cross-format table; WSEF appears automatically
in all 15 cross-format utilities. Format count 81 -> 82; CLI flag
count 989 -> 994.
2026-05-09 22:50:13 -07:00
src/pipeline/wowee_spell_effect_types.cpp
feat(editor): add WAUR (Spell Aura Type) — companion to WSEF, CLI flag count breaks 1000
Open replacement for the SpellEffect.EffectAuraType field
meanings used when SpellEffect.Effect=APPLY_AURA. Defines what
each aura-type integer value actually does once an aura is
attached to a unit — PERIODIC_DAMAGE ticks damage every N
seconds, MOD_STAT adds a stat bonus, MOD_INCREASE_SPEED scales
movement, MOD_DAMAGE_PERCENT_DONE scales spell power, etc.
Companion to WSEF — together they cover the full spell-effect
classification space:
WSEF: outer effect ID — what does the effect DO?
(APPLY_AURA, SCHOOL_DAMAGE, HEAL, etc)
WAUR: inner aura type — when WSEF=APPLY_AURA, what KIND
of aura is applied? (PERIODIC_DAMAGE, MOD_STAT,
STUN, ROOT, etc)
Nine auraKind values (Periodic / StatMod / DamageMod /
Movement / Visual / Trigger / Resource / Control / Misc)
classify the major behavior families. Periodic auras carry an
updateFrequencyMs (canonical 3s for DoT/HoT, 2s for energize,
1s for fast triggers). Stackable auras carry a maxStackCount.
Cross-references back to WSEF (this catalog is the secondary
classification that WSEF entry id 6 (APPLY_AURA) dispatches
into) and forward to WSPL (spell entries with effect=APPLY_AURA
reference an auraTypeId here).
Three preset emitters: --gen-aur (5 periodic auras with
canonical tick intervals), --gen-aur-stats (5 stat-modifier
auras instantly applied on attach), --gen-aur-movement (4
movement-impairing CC auras typical of crowd-control spells).
Validation enforces name presence, auraKind 0..8, targetingHint
0..3, no duplicate ids; errors on Periodic kind without
updateFrequencyMs (would never tick); warns on:
- non-Periodic/Trigger kinds with updateFrequencyMs > 0
(engine ignores tick interval)
- maxStackCount > 0 with isStackable=false (cap unreachable)
Wired through the cross-format table; WAUR appears automatically
in all 15 cross-format utilities. Format count 82 -> 83;
CLI flag count 996 -> 1001 — broke the 1000-flag mark.
2026-05-09 22:54:53 -07:00
src/pipeline/wowee_spell_aura_types.cpp
feat(editor): add WIQR (Item Quality) open catalog format
Open replacement for the hardcoded item quality tiers in the
WoW client (Poor / Common / Uncommon / Rare / Epic / Legendary
/ Artifact / Heirloom). Defines each tier's tooltip text color,
inventory slot border color, vendor price multiplier, drop-level
gating, and disenchant eligibility.
The hardcoded client uses a fixed color table (gray/white/green/
blue/purple/orange/red/gold). This catalog lets server admins:
- retune the colors (rename "Epic" to "Tier 1" with custom hex)
- add server-custom tiers above Heirloom
- change vendor markup per tier (legendary 50x base price)
- gate quality drops by character level (Heirlooms unlock 80)
The standard preset reproduces the canonical 8-tier scale with
exact hex values from the live client (#9d9d9d through #00ccff)
and standard disenchant rules (Common+ disenchantable, Legendary
and Artifact aren't). The server-custom preset shows 4 tiers
above the standard range with non-standard pricing (Junk 0.1x,
QuestLocked 0.0x unsellable). The raid preset gates 4
progression tiers behind minLevelToDrop=60 with escalating
vendor multipliers up to 50x for Legendary.
Cross-references back to WIT — item entries reference qualityId
here for tooltip color and sort order. canDropAtLevel(id, lvl)
is the engine helper used by loot generation.
Validation enforces name presence, no duplicate ids,
vendorPriceMultiplier >= 0, minLevelToDrop <= maxLevelToDrop;
warns on:
- minLevelToDrop > 80 (unreachable at WotLK cap)
- vendorPriceMultiplier > 100x (sanity check the economy)
- nameColorRGBA with alpha=0 (text would be invisible in
tooltips — common bug when copy-pasting RGB hex without
alpha byte)
Wired through the cross-format table; WIQR appears automatically
in all 15 cross-format utilities. Format count 83 -> 84; CLI
flag count 1003 -> 1008.
2026-05-09 22:59:27 -07:00
src/pipeline/wowee_item_qualities.cpp
feat(editor): add WSCS (Skill Cost) open catalog format
Open replacement for Blizzard's SkillCostsData.dbc plus the
per-rank training cost tables. Defines the tiered progression of
trainable skills: each rank unlocks a skill range, requires a
minimum character level, and costs a fixed amount of gold to
learn.
The canonical 6-tier profession progression captured by the
default preset:
Apprentice skill 0-75 lvl 5 1s
Journeyman skill 50-150 lvl 10 5s
Expert skill 125-225 lvl 20 1g
Artisan skill 200-300 lvl 35 5g
Master skill 275-375 lvl 50 10g
Grand Master skill 350-450 lvl 65 25g
Same shape applies to weapon skills (free, level-gated, capped at
5x char level) and riding skills (canonical Vanilla / TBC / WotLK
gold costs from 90g Apprentice through 5000g Artisan flying down
to 1000g Cold Weather Flying).
Five costKind values cover the full training-skill space
(Profession / WeaponSkill / RidingSkill / ClassSkill / Misc).
Each entry's copperCost stores the cost in copper (1g = 10000c)
which the info renderer pretty-prints as "25g 0s 0c".
Cross-references back to WSKL — skill entries reference costId
here for the tiered training schedule. nextTrainable(currentSkill,
characterLevel) is the engine helper that returns the lowest-rank
tier a character qualifies for and hasn't capped yet — used by
trainer NPCs to populate their offered-skill list.
Three preset emitters: --gen-scs (6 profession tiers), --gen-scs-
weapon (5 weapon skill tiers), --gen-scs-riding (5 riding tiers
with canonical gold costs).
Validation enforces id+name presence, costKind 0..4, no duplicate
ids, min<max range; warns on:
- requiredLevel > 80 (unreachable at WotLK cap)
- RidingSkill with requiredLevel < 20 (Apprentice canonically
unlocks at 20)
- Profession kind with copperCost=0 (every standard tier costs
at least a copper — usually a config bug)
Wired through the cross-format table; WSCS appears automatically
in all 15 cross-format utilities. Format count 84 -> 85; CLI
flag count 1010 -> 1015.
2026-05-09 23:04:02 -07:00
src/pipeline/wowee_skill_costs.cpp
2026-05-05 10:01:05 -07:00
src/pipeline/custom_zone_discovery.cpp
2026-02-12 22:56:36 -08:00
src/pipeline/dbc_layout.cpp
2026-02-15 04:18:34 -08:00
2026-02-02 12:24:50 -08:00
src/pipeline/terrain_mesh.cpp
2026-02-21 19:41:21 -08:00
# Rendering (Vulkan infrastructure)
src/rendering/vk_context.cpp
src/rendering/vk_utils.cpp
src/rendering/vk_shader.cpp
src/rendering/vk_texture.cpp
src/rendering/vk_buffer.cpp
src/rendering/vk_pipeline.cpp
src/rendering/vk_render_target.cpp
2026-02-02 12:24:50 -08:00
# Rendering
src/rendering/renderer.cpp
2026-03-08 23:13:08 -07:00
src/rendering/amd_fsr3_runtime.cpp
2026-02-02 12:24:50 -08:00
src/rendering/camera.cpp
src/rendering/camera_controller.cpp
src/rendering/material.cpp
src/rendering/terrain_renderer.cpp
src/rendering/terrain_manager.cpp
src/rendering/frustum.cpp
src/rendering/performance_hud.cpp
src/rendering/water_renderer.cpp
src/rendering/skybox.cpp
src/rendering/celestial.cpp
src/rendering/starfield.cpp
src/rendering/clouds.cpp
src/rendering/lens_flare.cpp
src/rendering/weather.cpp
src/rendering/lightning.cpp
2026-02-10 13:44:22 -08:00
src/rendering/lighting_manager.cpp
Implement WoW-accurate DBC-driven sky system with lore-faithful celestial bodies
Add SkySystem coordinator that follows WoW's actual architecture where skyboxes
are authoritative and procedural elements serve as fallbacks. Integrate lighting
system across all renderers (terrain, WMO, M2, character) with unified parameters.
Sky System:
- SkySystem coordinator manages skybox, celestial bodies, stars, clouds, lens flare
- Skybox is authoritative (baked stars from M2 models, procedural fallback only)
- skyboxHasStars flag gates procedural star rendering (prevents double-star bug)
Celestial Bodies (Lore-Accurate):
- Two moons: White Lady (30-day cycle, pale white) + Blue Child (27-day cycle, pale blue)
- Deterministic moon phases from server gameTime (not deltaTime toys)
- Sun positioning driven by LightingManager directionalDir (DBC-sourced)
- Camera-locked sky dome (translation ignored, rotation applied)
Lighting Integration:
- Apply LightingManager params to WMO, M2, character renderers
- Unified lighting: directional light, diffuse color, ambient color, fog
- Star occlusion by cloud density (70% weight) and fog density (30% weight)
Documentation:
- Add comprehensive SKY_SYSTEM.md technical guide
- Update MEMORY.md with sky system architecture and anti-patterns
- Update README.md with WoW-accurate descriptions
Critical design decisions:
- NO latitude-based star rotation (Azeroth not modeled as spherical planet)
- NO always-on procedural stars (skybox authority prevents zone identity loss)
- NO universal dual-moon setup (map-specific celestial configurations)
2026-02-10 14:36:17 -08:00
src/rendering/sky_system.cpp
2026-02-02 12:24:50 -08:00
src/rendering/character_renderer.cpp
2026-02-05 14:55:42 -08:00
src/rendering/character_preview.cpp
2026-02-02 12:24:50 -08:00
src/rendering/wmo_renderer.cpp
src/rendering/m2_renderer.cpp
2026-04-05 19:30:44 +03:00
src/rendering/m2_renderer_render.cpp
src/rendering/m2_renderer_particles.cpp
src/rendering/m2_renderer_instance.cpp
2026-03-24 19:55:24 +03:00
src/rendering/m2_model_classifier.cpp
feat(rendering): GPU architecture + visual quality fixes
M2 GPU instancing
- M2InstanceGPU SSBO (96 B/entry, double-buffered, 16384 max)
- Group opaque instances by (modelId, LOD); single vkCmdDrawIndexed per group
- boneBase field indexes into mega bone SSBO via gl_InstanceIndex
Indirect terrain drawing
- 24 MB mega index buffer (6M uint32) + 64 MB mega vertex buffer
- CPU builds VkDrawIndexedIndirectCommand per visible chunk
- Single VB/IB bind per frame; shadow pass reuses mega buffers
- Replaced vkCmdDrawIndexedIndirect with direct vkCmdDrawIndexed to fix
host-mapped buffer race condition that caused terrain flickering
GPU frustum culling (compute shader)
- m2_cull.comp.glsl: 64-thread workgroups, sphere-vs-6-planes + distance cull
- CullInstanceGPU SSBO input, uint visibility[] output, double-buffered
- dispatchCullCompute() runs before main pass via render graph node
Consolidated bone matrix SSBOs
- 16 MB double-buffered mega bone SSBO (2048 instances × 128 bones)
- Eliminated per-instance descriptor sets; one megaBoneSet_ per frame
- prepareRender() packs bone matrices consecutively into current frame slot
Render graph / frame graph
- RenderGraph: RGResource handles, RGPass nodes, Kahn topological sort
- Automatic VkImageMemoryBarrier/VkBufferMemoryBarrier between passes
- Passes: minimap_composite, worldmap_composite, preview_composite,
shadow_pass, reflection_pass, compute_cull
- beginFrame() uses buildFrameGraph() + renderGraph_->execute(cmd)
Pipeline derivatives
- PipelineBuilder::setFlags/setBasePipeline for VK_PIPELINE_CREATE_DERIVATIVE_BIT
- M2 opaque = base; alphaTest/alpha/additive are derivatives
- Applied to terrain (wireframe) and WMO (alpha-test) renderers
Rendering bug fixes:
- fix(shadow): compute lightSpaceMatrix before updatePerFrameUBO to eliminate
one-frame lag that caused shadow trails and flicker on moving objects
- fix(shadow): scale depth bias with shadowDistance_ instead of hardcoded 0.8f
to prevent acne at close range and gaps at far range
- fix(visibility): WMO group distance threshold 500u → 1200u to match terrain
view distance; buildings were disappearing on the horizon
- fix(precision): camera near plane 0.05 → 0.5 (ratio 600K:1 → 60K:1),
eliminating Z-fighting and improving frustum plane extraction stability
- fix(streaming): terrain load radius 4 → 6 tiles (~2133u → ~3200u) to exceed
M2 render distance (2800u) and eliminate pop-in when camera turns;
unload radius 7 → 9; spawn radius 3 → 4
- fix(visibility): ground-detail M2 distance multiplier 0.75 → 0.9 to reduce
early pop of grass and debris
2026-04-04 13:43:16 +03:00
src/rendering/render_graph.cpp
feat(rendering): add HiZ occlusion culling & fix WMO interior shadows
Implement GPU-driven Hierarchical-Z occlusion culling for M2 doodads
using a depth pyramid built from the previous frame's depth buffer.
The cull shader projects bounding spheres via prevViewProj (temporal
reprojection) and samples the HiZ pyramid to reject hidden objects
before the main render pass.
Key implementation details:
- Separate early compute submission (beginSingleTimeCommands + fence
wait) eliminates 2-frame visibility staleness
- Conservative safeguards prevent false culls: screen-edge guard,
full VP row-vector AABB projection (Cauchy-Schwarz), 50% sphere
inflation, depth bias, mip+1, min screen size threshold, camera
motion dampening (auto-disable on fast rotations), and per-instance
previouslyVisible flag tracking
- Graceful fallback to frustum-only culling if HiZ init fails
Fix dark WMO interiors by gating shadow map sampling on isInterior==0
in the WMO fragment shader. Interior groups (flag 0x2000) now rely
solely on pre-baked MOCV vertex-color lighting + MOHD ambient color.
Disable interiorDarken globally (was incorrectly darkening outdoor M2s
when camera was inside a WMO). Use isInsideInteriorWMO() instead of
isInsideWMO() for correct indoor detection.
New files:
- hiz_system.hpp/cpp: pyramid image management, compute pipeline,
descriptors, mip-chain build dispatch, resize handling
- hiz_build.comp.glsl: MAX-depth 2x2 reduction compute shader
- m2_cull_hiz.comp.glsl: frustum + HiZ occlusion cull compute shader
- test_indoor_shadows.cpp: 14 unit tests for shadow/interior contracts
Modified:
- CullUniformsGPU expanded 128->272 bytes (HiZ params, viewProj,
prevViewProj)
- Depth buffer images gain VK_IMAGE_USAGE_SAMPLED_BIT for HiZ reads
- wmo.frag.glsl: interior branch before unlit, shadow skip for 0x2000
- Render graph: hiz_build + compute_cull disabled (run in early compute)
- .gitignore: ignore compiled .spv binaries
- MEGA_BONE_MAX_INSTANCES: 2048 -> 4096
Signed-off-by: Pavel Okhlopkov <pavel.okhlopkov@flant.com>
2026-04-06 16:40:59 +03:00
src/rendering/hiz_system.cpp
2026-02-09 23:41:38 -08:00
src/rendering/quest_marker_renderer.cpp
2026-02-02 12:24:50 -08:00
src/rendering/minimap.cpp
refactor: decompose world map into modular component architecture
Break the monolithic 1360-line world_map.cpp into 16 focused modules
under src/rendering/world_map/:
Architecture:
- world_map_facade: public API composing all components (PIMPL)
- world_map_types: Vulkan-free domain types (Zone, ViewLevel, etc.)
- data_repository: DBC zone loading, ZMP pixel map, POI/overlay storage
- coordinate_projection: UV projection, zone/continent lookups
- composite_renderer: Vulkan tile pipeline + off-screen compositing
- exploration_state: server mask + local exploration tracking
- view_state_machine: COSMIC→WORLD→CONTINENT→ZONE navigation
- input_handler: keyboard/mouse input → InputAction mapping
- overlay_renderer: layer-based ImGui overlay system (OCP)
- map_resolver: cross-map navigation (Outland, Northrend, etc.)
- zone_metadata: level ranges and faction data
Overlay layers (each an IOverlayLayer):
- player_marker, party_dot, taxi_node, poi_marker, quest_poi,
corpse_marker, zone_highlight, coordinate_display, subzone_tooltip
Fixes:
- Player marker no longer bleeds across continents (only shown when
player is in a zone belonging to the displayed continent)
- Zone hover uses DBC-projected AABB rectangles (restored from
original working behavior)
- Exploration overlay rendering for zone view subzones
Tests:
- 6 new test files covering coordinate projection, exploration state,
map resolver, view state machine, zone metadata, and integration
Signed-off-by: Pavel Okhlopkov <pavel.okhlopkov@flant.com>
2026-04-12 09:52:51 +03:00
src/rendering/world_map/coordinate_projection.cpp
src/rendering/world_map/map_resolver.cpp
src/rendering/world_map/exploration_state.cpp
src/rendering/world_map/zone_metadata.cpp
src/rendering/world_map/data_repository.cpp
src/rendering/world_map/view_state_machine.cpp
src/rendering/world_map/composite_renderer.cpp
src/rendering/world_map/overlay_renderer.cpp
src/rendering/world_map/input_handler.cpp
src/rendering/world_map/world_map_facade.cpp
src/rendering/world_map/layers/player_marker_layer.cpp
src/rendering/world_map/layers/party_dot_layer.cpp
src/rendering/world_map/layers/taxi_node_layer.cpp
src/rendering/world_map/layers/poi_marker_layer.cpp
src/rendering/world_map/layers/quest_poi_layer.cpp
src/rendering/world_map/layers/corpse_marker_layer.cpp
src/rendering/world_map/layers/zone_highlight_layer.cpp
src/rendering/world_map/layers/coordinate_display.cpp
src/rendering/world_map/layers/subzone_tooltip_layer.cpp
2026-02-02 12:24:50 -08:00
src/rendering/swim_effects.cpp
2026-02-09 01:24:17 -08:00
src/rendering/mount_dust.cpp
2026-02-19 20:36:25 -08:00
src/rendering/levelup_effect.cpp
2026-02-19 21:13:13 -08:00
src/rendering/charge_effect.cpp
2026-04-02 00:21:21 +03:00
src/rendering/spell_visual_system.cpp
src/rendering/post_process_pipeline.cpp
2026-04-05 19:30:44 +03:00
src/rendering/overlay_system.cpp
chore(renderer): extract AnimationController and remove audio pass-throughs
Extract ~1,500 lines of character animation state from Renderer into a dedicated
AnimationController class, and complete the AudioCoordinator migration by removing
all 10 audio pass-through getters from Renderer.
AnimationController:
- New: include/rendering/animation_controller.hpp (182 lines)
- New: src/rendering/animation_controller.cpp (1,703 lines)
- Moves: locomotion state machine (50+ members), mount animation (40+ members),
emote system, footstep triggering, surface detection, melee combat animations
- Renderer holds std::unique_ptr<AnimationController> and delegates completely
- AnimationController accesses audio via renderer_->getAudioCoordinator()
Audio caller migration:
- Migrate ~60 external callers from renderer->getXManager() to AudioCoordinator
directly, grouped by access pattern:
- UIServices: settings_panel, game_screen, toast_manager, chat_panel,
combat_ui, window_manager
- GameServices: game_handler, spell_handler, inventory_handler, quest_handler,
social_handler, combat_handler
- Application singleton: application.cpp, auth_screen.cpp, lua_engine.cpp
- Remove 10 pass-through getter definitions from renderer.cpp
- Remove 10 pass-through getter declarations from renderer.hpp
- Remove individual audio manager forward declarations from renderer.hpp
- Redirect 69 internal renderer.cpp audio calls to audioCoordinator_ directly
- game_handler.cpp: withSoundManager template uses services_.audioCoordinator;
MFP changed from &Renderer::getUiSoundManager to &AudioCoordinator::getUiSoundManager
- GameServices struct: add AudioCoordinator* audioCoordinator member
- settings_panel: applyAudioVolumes(Renderer*) -> applyAudioVolumes(AudioCoordinator*)
2026-04-02 13:06:31 +03:00
src/rendering/animation_controller.cpp
2026-04-05 12:27:35 +03:00
src/rendering/animation/animation_ids.cpp
src/rendering/animation/emote_registry.cpp
src/rendering/animation/footstep_driver.cpp
src/rendering/animation/sfx_state_driver.cpp
src/rendering/animation/anim_capability_probe.cpp
src/rendering/animation/locomotion_fsm.cpp
src/rendering/animation/combat_fsm.cpp
src/rendering/animation/activity_fsm.cpp
src/rendering/animation/mount_fsm.cpp
src/rendering/animation/character_animator.cpp # Renamed from player_animator.cpp; npc_animator.cpp removed
src/rendering/animation/animation_manager.cpp
2026-02-03 13:33:31 -08:00
src/rendering/loading_screen.cpp
2026-02-02 12:24:50 -08:00
# UI
src/ui/ui_manager.cpp
src/ui/auth_screen.cpp
src/ui/realm_screen.cpp
2026-02-05 14:13:48 -08:00
src/ui/character_create_screen.cpp
2026-02-02 12:24:50 -08:00
src/ui/character_screen.cpp
src/ui/game_screen.cpp
2026-04-05 19:30:44 +03:00
src/ui/game_screen_frames.cpp
src/ui/game_screen_hud.cpp
src/ui/game_screen_minimap.cpp
2026-03-31 08:53:14 +03:00
src/ui/chat_panel.cpp
refactor(chat): decompose into modular architecture, add GM commands, fix protocol
- Extract ChatPanel monolith into 15+ focused modules under ui/chat/
(ChatInput, ChatTabManager, ChatTabCompleter, ChatMarkupParser,
ChatMarkupRenderer, ChatCommandRegistry, ChatBubbleManager,
ChatSettings, MacroEvaluator, GameStateAdapter, InputModifierAdapter)
- Split 2700-line chat_panel_commands.cpp into 11 command modules
- Add GM command handling: 190-command data table, dot-prefix interception,
tab-completion, /gmhelp with category filter
- Fix ChatType enum to match WoW wire protocol (SAY=0x01 not 0x00);
values 0x00-0x1B shared across Vanilla/TBC/WotLK
- Fix BG_SYSTEM_* values from 82-84 (UB in bitmask shifts) to 0x24-0x26
- Fix infinite Enter key loop after teleport (disable TOGGLE_CHAT repeat,
add 2-frame input cooldown)
- Add tests: chat_markup_parser, chat_tab_completer, gm_commands,
macro_evaluator
Signed-off-by: Pavel Okhlopkov <pavel.okhlopkov@flant.com>
2026-04-12 14:59:56 +03:00
src/ui/chat/chat_settings.cpp
src/ui/chat/chat_input.cpp
2026-04-12 15:46:03 +03:00
src/ui/chat/chat_utils.cpp
refactor(chat): decompose into modular architecture, add GM commands, fix protocol
- Extract ChatPanel monolith into 15+ focused modules under ui/chat/
(ChatInput, ChatTabManager, ChatTabCompleter, ChatMarkupParser,
ChatMarkupRenderer, ChatCommandRegistry, ChatBubbleManager,
ChatSettings, MacroEvaluator, GameStateAdapter, InputModifierAdapter)
- Split 2700-line chat_panel_commands.cpp into 11 command modules
- Add GM command handling: 190-command data table, dot-prefix interception,
tab-completion, /gmhelp with category filter
- Fix ChatType enum to match WoW wire protocol (SAY=0x01 not 0x00);
values 0x00-0x1B shared across Vanilla/TBC/WotLK
- Fix BG_SYSTEM_* values from 82-84 (UB in bitmask shifts) to 0x24-0x26
- Fix infinite Enter key loop after teleport (disable TOGGLE_CHAT repeat,
add 2-frame input cooldown)
- Add tests: chat_markup_parser, chat_tab_completer, gm_commands,
macro_evaluator
Signed-off-by: Pavel Okhlopkov <pavel.okhlopkov@flant.com>
2026-04-12 14:59:56 +03:00
src/ui/chat/chat_tab_manager.cpp
src/ui/chat/chat_bubble_manager.cpp
src/ui/chat/chat_markup_parser.cpp
src/ui/chat/chat_markup_renderer.cpp
2026-04-12 15:46:03 +03:00
src/ui/chat/item_tooltip_renderer.cpp
refactor(chat): decompose into modular architecture, add GM commands, fix protocol
- Extract ChatPanel monolith into 15+ focused modules under ui/chat/
(ChatInput, ChatTabManager, ChatTabCompleter, ChatMarkupParser,
ChatMarkupRenderer, ChatCommandRegistry, ChatBubbleManager,
ChatSettings, MacroEvaluator, GameStateAdapter, InputModifierAdapter)
- Split 2700-line chat_panel_commands.cpp into 11 command modules
- Add GM command handling: 190-command data table, dot-prefix interception,
tab-completion, /gmhelp with category filter
- Fix ChatType enum to match WoW wire protocol (SAY=0x01 not 0x00);
values 0x00-0x1B shared across Vanilla/TBC/WotLK
- Fix BG_SYSTEM_* values from 82-84 (UB in bitmask shifts) to 0x24-0x26
- Fix infinite Enter key loop after teleport (disable TOGGLE_CHAT repeat,
add 2-frame input cooldown)
- Add tests: chat_markup_parser, chat_tab_completer, gm_commands,
macro_evaluator
Signed-off-by: Pavel Okhlopkov <pavel.okhlopkov@flant.com>
2026-04-12 14:59:56 +03:00
src/ui/chat/chat_command_registry.cpp
src/ui/chat/chat_tab_completer.cpp
src/ui/chat/macro_evaluator.cpp
2026-04-12 15:46:03 +03:00
src/ui/chat/macro_eval_convenience.cpp
refactor(chat): decompose into modular architecture, add GM commands, fix protocol
- Extract ChatPanel monolith into 15+ focused modules under ui/chat/
(ChatInput, ChatTabManager, ChatTabCompleter, ChatMarkupParser,
ChatMarkupRenderer, ChatCommandRegistry, ChatBubbleManager,
ChatSettings, MacroEvaluator, GameStateAdapter, InputModifierAdapter)
- Split 2700-line chat_panel_commands.cpp into 11 command modules
- Add GM command handling: 190-command data table, dot-prefix interception,
tab-completion, /gmhelp with category filter
- Fix ChatType enum to match WoW wire protocol (SAY=0x01 not 0x00);
values 0x00-0x1B shared across Vanilla/TBC/WotLK
- Fix BG_SYSTEM_* values from 82-84 (UB in bitmask shifts) to 0x24-0x26
- Fix infinite Enter key loop after teleport (disable TOGGLE_CHAT repeat,
add 2-frame input cooldown)
- Add tests: chat_markup_parser, chat_tab_completer, gm_commands,
macro_evaluator
Signed-off-by: Pavel Okhlopkov <pavel.okhlopkov@flant.com>
2026-04-12 14:59:56 +03:00
src/ui/chat/game_state_adapter.cpp
src/ui/chat/input_modifier_adapter.cpp
src/ui/chat/commands/system_commands.cpp
src/ui/chat/commands/social_commands.cpp
src/ui/chat/commands/channel_commands.cpp
src/ui/chat/commands/combat_commands.cpp
src/ui/chat/commands/group_commands.cpp
src/ui/chat/commands/guild_commands.cpp
src/ui/chat/commands/target_commands.cpp
src/ui/chat/commands/emote_commands.cpp
src/ui/chat/commands/misc_commands.cpp
src/ui/chat/commands/help_commands.cpp
src/ui/chat/commands/gm_commands.cpp
2026-03-31 09:18:17 +03:00
src/ui/toast_manager.cpp
2026-03-31 10:07:58 +03:00
src/ui/dialog_manager.cpp
src/ui/settings_panel.cpp
2026-03-31 19:49:52 +03:00
src/ui/combat_ui.cpp
src/ui/social_panel.cpp
src/ui/action_bar_panel.cpp
src/ui/window_manager.cpp
2026-02-02 12:24:50 -08:00
src/ui/inventory_screen.cpp
2026-02-06 13:47:03 -08:00
src/ui/quest_log_screen.cpp
2026-02-04 11:31:08 -08:00
src/ui/spellbook_screen.cpp
2026-02-06 16:04:25 -08:00
src/ui/talent_screen.cpp
2026-03-11 06:26:57 -07:00
src/ui/keybinding_manager.cpp
2026-02-02 12:24:50 -08:00
2026-03-20 11:12:07 -07:00
# Addons
src/addons/addon_manager.cpp
src/addons/lua_engine.cpp
`chore(lua): refactor addon Lua engine API + progress docs`
- Refactor Lua addon integration:
- Update CMakeLists.txt for addon build paths
- Enhance addons API headers and Lua engine interface
- Add new Lua API addon modules (`lua_api_helpers`, `lua_api_registrations`, `lua_services`, `lua_action_api`, `lua_inventory_api`, `lua_quest_api`, `lua_social_api`, `lua_spell_api`, `lua_system_api`, `lua_unit_api`)
- Update implementation in addon_manager.cpp, lua_engine.cpp, application.cpp, game_handler.cpp
2026-04-03 07:31:06 +03:00
src/addons/lua_unit_api.cpp
src/addons/lua_spell_api.cpp
src/addons/lua_inventory_api.cpp
src/addons/lua_quest_api.cpp
src/addons/lua_social_api.cpp
src/addons/lua_system_api.cpp
src/addons/lua_action_api.cpp
2026-03-20 11:12:07 -07:00
src/addons/toc_parser.cpp
2026-02-02 12:24:50 -08:00
# Main
src/main.cpp
)
set(WOWEE_HEADERS
include/core/application.hpp
include/core/window.hpp
include/core/input.hpp
include/core/logger.hpp
include/network/socket.hpp
include/network/packet.hpp
include/network/tcp_socket.hpp
2026-02-03 22:24:17 -08:00
include/network/world_socket.hpp
include/network/net_platform.hpp
include/platform/process.hpp
2026-02-02 12:24:50 -08:00
include/auth/auth_handler.hpp
include/auth/auth_opcodes.hpp
include/auth/auth_packets.hpp
include/auth/srp.hpp
include/auth/big_num.hpp
include/auth/crypto.hpp
include/game/game_handler.hpp
include/game/world.hpp
include/game/player.hpp
include/game/entity.hpp
include/game/opcodes.hpp
include/game/zone_manager.hpp
include/game/inventory.hpp
Add gameplay systems: combat, spells, groups, loot, vendors, and UI
Implement ~70 new protocol opcodes across 5 phases while maintaining
full 3.3.5a private server compatibility:
- Phase 1: Server-aware targeting (CMSG_SET_SELECTION), player/creature
name queries, CMSG_SET_ACTIVE_MOVER after login
- Phase 2: Auto-attack, melee/spell damage parsing, health/mana/power
tracking from UPDATE_OBJECT fields, floating combat text
- Phase 3: Spell casting, action bar (12 slots, keys 1-=), cast bar,
cooldown tracking, aura/buff system with cancellation
- Phase 4: Group invite/accept/decline/leave, party frames UI,
/invite chat command
- Phase 5: Loot window, NPC gossip dialog, vendor buy/sell interface
Also: disable debug HUD/panels by default, gate 3D rendering to
IN_GAME state only, fix window resize not updating UI positions.
2026-02-04 10:30:52 -08:00
include/game/spell_defines.hpp
include/game/group_defines.hpp
include/game/world_packets.hpp
include/game/character.hpp
2026-02-02 12:24:50 -08:00
2026-02-09 00:40:50 -08:00
include/audio/audio_engine.hpp
2026-02-02 12:24:50 -08:00
include/audio/music_manager.hpp
2026-02-03 14:55:32 -08:00
include/audio/footstep_manager.hpp
2026-02-03 19:49:56 -08:00
include/audio/activity_sound_manager.hpp
2026-02-09 01:04:53 -08:00
include/audio/mount_sound_manager.hpp
Implement comprehensive audio control panel with tabbed settings interface
Adds complete audio volume controls for all 11 audio systems with master volume. Reorganizes settings window into Video, Audio, and Gameplay tabs for better UX.
Audio Features:
- Master volume control affecting all audio systems
- Individual volume sliders for: Music, Ambient, UI, Combat, Spell, Movement, Footsteps, NPC Voices, Mounts, Activity sounds
- Real-time volume adjustment with master volume multiplier
- Restore defaults button per tab
Technical Changes:
- Added getVolumeScale() getters to all audio managers
- Integrated all 10 audio managers into renderer (UI, Combat, Spell, Movement added)
- Expanded game_screen.hpp with 11 pending volume variables
- Reorganized settings window using ImGui tab bars (Video/Audio/Gameplay)
- Audio settings uses scrollable child window for 11 volume controls
- Settings window expanded to 520x720px to accommodate comprehensive controls
2026-02-09 17:07:22 -08:00
include/audio/npc_voice_manager.hpp
include/audio/ambient_sound_manager.hpp
include/audio/ui_sound_manager.hpp
include/audio/combat_sound_manager.hpp
include/audio/spell_sound_manager.hpp
include/audio/movement_sound_manager.hpp
2026-02-02 12:24:50 -08:00
include/pipeline/blp_loader.hpp
2026-02-12 20:32:14 -08:00
include/pipeline/asset_manifest.hpp
include/pipeline/loose_file_reader.hpp
2026-02-02 12:24:50 -08:00
include/pipeline/m2_loader.hpp
include/pipeline/wmo_loader.hpp
include/pipeline/adt_loader.hpp
2026-02-26 17:56:11 -08:00
include/pipeline/wdt_loader.hpp
2026-02-02 12:24:50 -08:00
include/pipeline/dbc_loader.hpp
include/pipeline/terrain_mesh.hpp
2026-02-21 19:41:21 -08:00
include/rendering/vk_context.hpp
include/rendering/vk_utils.hpp
include/rendering/vk_shader.hpp
include/rendering/vk_texture.hpp
include/rendering/vk_buffer.hpp
include/rendering/vk_pipeline.hpp
include/rendering/vk_render_target.hpp
2026-02-02 12:24:50 -08:00
include/rendering/renderer.hpp
include/rendering/camera.hpp
include/rendering/camera_controller.hpp
include/rendering/material.hpp
include/rendering/terrain_renderer.hpp
include/rendering/terrain_manager.hpp
include/rendering/frustum.hpp
include/rendering/performance_hud.hpp
include/rendering/water_renderer.hpp
include/rendering/skybox.hpp
include/rendering/celestial.hpp
include/rendering/starfield.hpp
include/rendering/clouds.hpp
include/rendering/lens_flare.hpp
include/rendering/weather.hpp
include/rendering/lightning.hpp
include/rendering/swim_effects.hpp
2026-02-04 22:27:45 -08:00
include/rendering/world_map.hpp
refactor: decompose world map into modular component architecture
Break the monolithic 1360-line world_map.cpp into 16 focused modules
under src/rendering/world_map/:
Architecture:
- world_map_facade: public API composing all components (PIMPL)
- world_map_types: Vulkan-free domain types (Zone, ViewLevel, etc.)
- data_repository: DBC zone loading, ZMP pixel map, POI/overlay storage
- coordinate_projection: UV projection, zone/continent lookups
- composite_renderer: Vulkan tile pipeline + off-screen compositing
- exploration_state: server mask + local exploration tracking
- view_state_machine: COSMIC→WORLD→CONTINENT→ZONE navigation
- input_handler: keyboard/mouse input → InputAction mapping
- overlay_renderer: layer-based ImGui overlay system (OCP)
- map_resolver: cross-map navigation (Outland, Northrend, etc.)
- zone_metadata: level ranges and faction data
Overlay layers (each an IOverlayLayer):
- player_marker, party_dot, taxi_node, poi_marker, quest_poi,
corpse_marker, zone_highlight, coordinate_display, subzone_tooltip
Fixes:
- Player marker no longer bleeds across continents (only shown when
player is in a zone belonging to the displayed continent)
- Zone hover uses DBC-projected AABB rectangles (restored from
original working behavior)
- Exploration overlay rendering for zone view subzones
Tests:
- 6 new test files covering coordinate projection, exploration state,
map resolver, view state machine, zone metadata, and integration
Signed-off-by: Pavel Okhlopkov <pavel.okhlopkov@flant.com>
2026-04-12 09:52:51 +03:00
include/rendering/world_map/world_map_types.hpp
include/rendering/world_map/coordinate_projection.hpp
include/rendering/world_map/map_resolver.hpp
include/rendering/world_map/exploration_state.hpp
include/rendering/world_map/zone_metadata.hpp
include/rendering/world_map/data_repository.hpp
include/rendering/world_map/view_state_machine.hpp
include/rendering/world_map/composite_renderer.hpp
include/rendering/world_map/overlay_renderer.hpp
include/rendering/world_map/input_handler.hpp
include/rendering/world_map/world_map_facade.hpp
include/rendering/world_map/layers/player_marker_layer.hpp
include/rendering/world_map/layers/party_dot_layer.hpp
include/rendering/world_map/layers/taxi_node_layer.hpp
include/rendering/world_map/layers/poi_marker_layer.hpp
include/rendering/world_map/layers/quest_poi_layer.hpp
include/rendering/world_map/layers/corpse_marker_layer.hpp
include/rendering/world_map/layers/zone_highlight_layer.hpp
include/rendering/world_map/layers/coordinate_display.hpp
include/rendering/world_map/layers/subzone_tooltip_layer.hpp
2026-02-02 12:24:50 -08:00
include/rendering/character_renderer.hpp
2026-02-05 14:55:42 -08:00
include/rendering/character_preview.hpp
2026-02-02 12:24:50 -08:00
include/rendering/wmo_renderer.hpp
2026-02-03 13:33:31 -08:00
include/rendering/loading_screen.hpp
2026-02-02 12:24:50 -08:00
include/ui/ui_manager.hpp
include/ui/auth_screen.hpp
include/ui/realm_screen.hpp
2026-02-05 14:13:48 -08:00
include/ui/character_create_screen.hpp
2026-02-02 12:24:50 -08:00
include/ui/character_screen.hpp
include/ui/game_screen.hpp
include/ui/inventory_screen.hpp
2026-02-04 11:31:08 -08:00
include/ui/spellbook_screen.hpp
2026-02-06 16:04:25 -08:00
include/ui/talent_screen.hpp
2026-03-11 06:26:57 -07:00
include/ui/keybinding_manager.hpp
2026-02-02 12:24:50 -08:00
)
2026-02-11 15:24:05 -08:00
set(WOWEE_PLATFORM_SOURCES)
if(WIN32)
feat: add multi-platform Docker build system for Linux, macOS, and Windows
Replace the single Ubuntu-based container build with a dedicated
Dockerfile, build script, and launcher for each target platform.
Infrastructure:
- Add .dockerignore to minimize Docker build context
- Add container/builder-linux.Dockerfile (Ubuntu 24.04, GCC, native build)
- Add container/builder-macos.Dockerfile (multi-stage: SDK fetcher + osxcross/Clang 18)
- Add container/builder-windows.Dockerfile (LLVM-MinGW 20240619, vcpkg)
- Add container/macos/sdk-fetcher.py (auto-fetch macOS SDK from Apple catalog)
- Add container/macos/osxcross-toolchain.cmake (auto-detecting CMake toolchain)
- Add container/macos/triplets/arm64-osx-cross.cmake
- Add container/macos/triplets/x64-osx-cross.cmake
- Remove container/builder-ubuntu.Dockerfile (replaced by per-platform Dockerfiles)
- Remove container/build-in-container.sh and container/build-wowee.sh (replaced)
Build scripts (run inside containers):
- Add container/build-linux.sh (tar copy, FidelityFX clone, cmake/ninja)
- Add container/build-macos.sh (arch detection, vcpkg triplet, cross-compile)
- Add container/build-windows.sh (Vulkan import lib via dlltool, cross-compile)
Launcher scripts (run on host):
- Add container/run-linux.sh, run-macos.sh, run-windows.sh (bash)
- Add container/run-linux.ps1, run-macos.ps1, run-windows.ps1 (PowerShell)
Documentation:
- Add container/README.md (quick start, options, file structure, troubleshooting)
- Add container/FLOW.md (comprehensive build flow for each platform)
CMake changes:
- Add macOS cross-compile support (VulkanHeaders, -undefined dynamic_lookup)
- Add LLVM-MinGW/Windows cross-compile support
- Detect osxcross toolchain and vcpkg triplets
Other:
- Update vcpkg.json with ffmpeg feature flags
- Update resources/wowee.rc version string
2026-03-30 20:17:41 +03:00
# Copy icon into build tree so windres can find it via the relative path
# in wowee.rc ("assets\\wowee.ico"). Tell the RC compiler to also search
# the build directory — GNU windres uses cwd (already the build dir) but
# llvm-windres resolves relative to the .rc file, so it needs the hint.
2026-02-18 19:05:47 -08:00
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/assets/Wowee.ico
${CMAKE_CURRENT_BINARY_DIR}/assets/wowee.ico
COPYONLY
)
feat: add multi-platform Docker build system for Linux, macOS, and Windows
Replace the single Ubuntu-based container build with a dedicated
Dockerfile, build script, and launcher for each target platform.
Infrastructure:
- Add .dockerignore to minimize Docker build context
- Add container/builder-linux.Dockerfile (Ubuntu 24.04, GCC, native build)
- Add container/builder-macos.Dockerfile (multi-stage: SDK fetcher + osxcross/Clang 18)
- Add container/builder-windows.Dockerfile (LLVM-MinGW 20240619, vcpkg)
- Add container/macos/sdk-fetcher.py (auto-fetch macOS SDK from Apple catalog)
- Add container/macos/osxcross-toolchain.cmake (auto-detecting CMake toolchain)
- Add container/macos/triplets/arm64-osx-cross.cmake
- Add container/macos/triplets/x64-osx-cross.cmake
- Remove container/builder-ubuntu.Dockerfile (replaced by per-platform Dockerfiles)
- Remove container/build-in-container.sh and container/build-wowee.sh (replaced)
Build scripts (run inside containers):
- Add container/build-linux.sh (tar copy, FidelityFX clone, cmake/ninja)
- Add container/build-macos.sh (arch detection, vcpkg triplet, cross-compile)
- Add container/build-windows.sh (Vulkan import lib via dlltool, cross-compile)
Launcher scripts (run on host):
- Add container/run-linux.sh, run-macos.sh, run-windows.sh (bash)
- Add container/run-linux.ps1, run-macos.ps1, run-windows.ps1 (PowerShell)
Documentation:
- Add container/README.md (quick start, options, file structure, troubleshooting)
- Add container/FLOW.md (comprehensive build flow for each platform)
CMake changes:
- Add macOS cross-compile support (VulkanHeaders, -undefined dynamic_lookup)
- Add LLVM-MinGW/Windows cross-compile support
- Detect osxcross toolchain and vcpkg triplets
Other:
- Update vcpkg.json with ffmpeg feature flags
- Update resources/wowee.rc version string
2026-03-30 20:17:41 +03:00
set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -I ${CMAKE_CURRENT_BINARY_DIR} -I ${CMAKE_CURRENT_SOURCE_DIR}")
2026-02-11 15:24:05 -08:00
list(APPEND WOWEE_PLATFORM_SOURCES resources/wowee.rc)
endif()
2026-03-20 11:12:07 -07:00
# ---- Lua 5.1.5 (vendored, static library) ----
set(LUA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/lua-5.1.5/src)
set(LUA_SOURCES
${LUA_DIR}/lapi.c ${LUA_DIR}/lcode.c ${LUA_DIR}/ldebug.c
${LUA_DIR}/ldo.c ${LUA_DIR}/ldump.c ${LUA_DIR}/lfunc.c
${LUA_DIR}/lgc.c ${LUA_DIR}/llex.c ${LUA_DIR}/lmem.c
${LUA_DIR}/lobject.c ${LUA_DIR}/lopcodes.c ${LUA_DIR}/lparser.c
${LUA_DIR}/lstate.c ${LUA_DIR}/lstring.c ${LUA_DIR}/ltable.c
${LUA_DIR}/ltm.c ${LUA_DIR}/lundump.c ${LUA_DIR}/lvm.c
${LUA_DIR}/lzio.c ${LUA_DIR}/lauxlib.c ${LUA_DIR}/lbaselib.c
${LUA_DIR}/ldblib.c ${LUA_DIR}/liolib.c ${LUA_DIR}/lmathlib.c
${LUA_DIR}/loslib.c ${LUA_DIR}/ltablib.c ${LUA_DIR}/lstrlib.c
${LUA_DIR}/linit.c
)
add_library(lua51 STATIC ${LUA_SOURCES})
set_target_properties(lua51 PROPERTIES LINKER_LANGUAGE C C_STANDARD 99 POSITION_INDEPENDENT_CODE ON)
target_include_directories(lua51 PUBLIC ${LUA_DIR})
if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
target_compile_options(lua51 PRIVATE -w)
endif()
2026-02-02 12:24:50 -08:00
# Create executable
2026-02-11 15:24:05 -08:00
add_executable(wowee ${WOWEE_SOURCES} ${WOWEE_HEADERS} ${WOWEE_PLATFORM_SOURCES})
2026-04-03 09:41:34 +03:00
# Tracy profiler — zero overhead when WOWEE_ENABLE_TRACY is OFF
if(WOWEE_ENABLE_TRACY)
target_sources(wowee PRIVATE ${CMAKE_SOURCE_DIR}/extern/tracy/public/TracyClient.cpp)
target_compile_definitions(wowee PRIVATE TRACY_ENABLE)
target_include_directories(wowee SYSTEM PRIVATE ${CMAKE_SOURCE_DIR}/extern/tracy/public)
message(STATUS "Tracy profiler: ENABLED")
endif()
2026-02-20 03:02:31 -08:00
if(TARGET opcodes-generate)
add_dependencies(wowee opcodes-generate)
endif()
2026-03-30 13:40:40 -07:00
# macOS cross-compilation: MoltenVK is not available at link time.
# Allow unresolved Vulkan symbols — resolved at runtime. Scoped to wowee only.
if(WOWEE_MACOS_CROSS_COMPILE)
target_link_options(wowee PRIVATE "-undefined" "dynamic_lookup")
endif()
2026-02-02 12:24:50 -08:00
Add FSR3 Generic API path and harden runtime diagnostics
- AmdFsr3Runtime now probes both the legacy ffxFsr3* API and the newer
generic ffxCreateContext/ffxDispatch API; selects whichever the loaded
runtime library exports (GenericApi takes priority fallback)
- Generic API path implements full upscale + frame-generation context
creation, configure, dispatch, and destroy lifecycle
- dlopen error captured and surfaced in lastError_ on Linux so runtime
initialization failures are actionable
- FSR3 runtime init failure log now includes path kind, error string,
and loaded library path for easier debugging
- tools/generate_ffx_sdk_vk_permutations.sh added: auto-bootstraps
missing VK permutation headers; DXC auto-downloaded on Linux/Windows
MSYS2; macOS reads from PATH (CI installs via brew dxc)
- CMakeLists: add upscalers/include to probe include dirs, invoke
permutation script before SDK build, scope FFX pragma/ODR warning
suppressions to affected TUs, add runtime-copy dependency on wowee
- UI labels updated from "FSR2" → "FSR3" in settings, tuning panel,
performance HUD, and combo boxes
- CI macOS job now installs dxc via Homebrew for permutation codegen
2026-03-09 12:51:59 -07:00
# FidelityFX-SDK headers can trigger compiler-specific pragma/unused-static noise
# when included through the runtime bridge; keep suppression scoped to that TU.
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
set_source_files_properties(src/rendering/amd_fsr3_runtime.cpp PROPERTIES
COMPILE_OPTIONS "-Wno-unknown-pragmas;-Wno-unused-variable"
)
endif()
2026-02-21 19:41:21 -08:00
# Compile GLSL shaders to SPIR-V
if(GLSLC)
compile_shaders(wowee)
endif()
2026-02-02 12:24:50 -08:00
# Include directories
target_include_directories(wowee PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src
2026-02-23 19:20:55 -08:00
)
# Vendored headers as SYSTEM to suppress third-party warnings
target_include_directories(wowee SYSTEM PRIVATE
2026-02-03 13:33:31 -08:00
${CMAKE_CURRENT_SOURCE_DIR}/extern
2026-02-21 19:41:21 -08:00
${CMAKE_CURRENT_SOURCE_DIR}/extern/vk-bootstrap/src
2026-02-02 12:24:50 -08:00
)
2026-02-23 16:30:49 +01:00
if(HAVE_FFMPEG)
target_include_directories(wowee PRIVATE ${FFMPEG_INCLUDE_DIRS})
endif()
2026-02-02 12:24:50 -08:00
# Link libraries
target_link_libraries(wowee PRIVATE
SDL2::SDL2
2026-02-21 19:41:21 -08:00
Vulkan::Vulkan
2026-02-02 12:24:50 -08:00
OpenSSL::SSL
OpenSSL::Crypto
Threads::Threads
2026-02-05 21:03:27 -08:00
ZLIB::ZLIB
2026-03-20 11:12:07 -07:00
lua51
2026-02-09 00:40:50 -08:00
${CMAKE_DL_LIBS}
2026-02-02 12:24:50 -08:00
)
2026-02-23 16:30:49 +01:00
if(HAVE_FFMPEG)
target_compile_definitions(wowee PRIVATE HAVE_FFMPEG)
target_link_libraries(wowee PRIVATE ${FFMPEG_LIBRARIES})
if(FFMPEG_LIBRARY_DIRS)
target_link_directories(wowee PRIVATE ${FFMPEG_LIBRARY_DIRS})
endif()
2026-02-05 15:34:29 -08:00
endif()
2026-02-03 22:24:17 -08:00
# Platform-specific libraries
2026-02-07 17:59:40 -08:00
if(UNIX AND NOT APPLE)
target_link_libraries(wowee PRIVATE X11)
endif()
2026-02-03 22:24:17 -08:00
if(WIN32)
target_link_libraries(wowee PRIVATE ws2_32)
# SDL2main provides WinMain entry point on Windows
if(TARGET SDL2::SDL2main)
target_link_libraries(wowee PRIVATE SDL2::SDL2main)
endif()
endif()
2026-02-02 12:24:50 -08:00
# Link ImGui if available
if(TARGET imgui)
target_link_libraries(wowee PRIVATE imgui)
endif()
2026-02-21 19:41:21 -08:00
# Link vk-bootstrap
if(TARGET vk-bootstrap)
target_link_libraries(wowee PRIVATE vk-bootstrap)
endif()
2026-03-08 19:56:52 -07:00
if(TARGET wowee_fsr2_amd_vk)
target_link_libraries(wowee PRIVATE wowee_fsr2_amd_vk)
endif()
2026-03-08 22:47:46 -07:00
if(TARGET wowee_fsr3_framegen_amd_vk_probe)
target_link_libraries(wowee PRIVATE wowee_fsr3_framegen_amd_vk_probe)
endif()
Add FSR3 Generic API path and harden runtime diagnostics
- AmdFsr3Runtime now probes both the legacy ffxFsr3* API and the newer
generic ffxCreateContext/ffxDispatch API; selects whichever the loaded
runtime library exports (GenericApi takes priority fallback)
- Generic API path implements full upscale + frame-generation context
creation, configure, dispatch, and destroy lifecycle
- dlopen error captured and surfaced in lastError_ on Linux so runtime
initialization failures are actionable
- FSR3 runtime init failure log now includes path kind, error string,
and loaded library path for easier debugging
- tools/generate_ffx_sdk_vk_permutations.sh added: auto-bootstraps
missing VK permutation headers; DXC auto-downloaded on Linux/Windows
MSYS2; macOS reads from PATH (CI installs via brew dxc)
- CMakeLists: add upscalers/include to probe include dirs, invoke
permutation script before SDK build, scope FFX pragma/ODR warning
suppressions to affected TUs, add runtime-copy dependency on wowee
- UI labels updated from "FSR2" → "FSR3" in settings, tuning panel,
performance HUD, and combo boxes
- CI macOS job now installs dxc via Homebrew for permutation codegen
2026-03-09 12:51:59 -07:00
if(TARGET wowee_fsr3_official_runtime_copy)
2026-03-09 13:23:39 -07:00
# FSR3 Path A runtime is an opt-in artifact; build explicitly with:
# cmake --build build --target wowee_fsr3_official_runtime_copy
# Do NOT add as a hard dependency of wowee — it would break arm64 and Windows CI
# (no DXC available on arm64; bash context issues on MSYS2 Windows).
Add FSR3 Generic API path and harden runtime diagnostics
- AmdFsr3Runtime now probes both the legacy ffxFsr3* API and the newer
generic ffxCreateContext/ffxDispatch API; selects whichever the loaded
runtime library exports (GenericApi takes priority fallback)
- Generic API path implements full upscale + frame-generation context
creation, configure, dispatch, and destroy lifecycle
- dlopen error captured and surfaced in lastError_ on Linux so runtime
initialization failures are actionable
- FSR3 runtime init failure log now includes path kind, error string,
and loaded library path for easier debugging
- tools/generate_ffx_sdk_vk_permutations.sh added: auto-bootstraps
missing VK permutation headers; DXC auto-downloaded on Linux/Windows
MSYS2; macOS reads from PATH (CI installs via brew dxc)
- CMakeLists: add upscalers/include to probe include dirs, invoke
permutation script before SDK build, scope FFX pragma/ODR warning
suppressions to affected TUs, add runtime-copy dependency on wowee
- UI labels updated from "FSR2" → "FSR3" in settings, tuning panel,
performance HUD, and combo boxes
- CI macOS job now installs dxc via Homebrew for permutation codegen
2026-03-09 12:51:59 -07:00
endif()
2026-03-08 19:56:52 -07:00
2026-02-12 03:01:36 -08:00
# Link Unicorn if available
if(HAVE_UNICORN)
target_link_libraries(wowee PRIVATE ${UNICORN_LIBRARY})
target_include_directories(wowee PRIVATE ${UNICORN_INCLUDE_DIR})
target_compile_definitions(wowee PRIVATE HAVE_UNICORN)
endif()
2026-02-02 12:24:50 -08:00
# Link GLM if found
if(TARGET glm::glm)
target_link_libraries(wowee PRIVATE glm::glm)
elseif(glm_FOUND)
target_include_directories(wowee PRIVATE ${GLM_INCLUDE_DIRS})
endif()
# Compiler warnings
if(MSVC)
target_compile_options(wowee PRIVATE /W4)
else()
2026-02-23 19:20:55 -08:00
target_compile_options(wowee PRIVATE -Wall -Wextra -Wpedantic -Wno-missing-field-initializers)
Add FSR3 Generic API path and harden runtime diagnostics
- AmdFsr3Runtime now probes both the legacy ffxFsr3* API and the newer
generic ffxCreateContext/ffxDispatch API; selects whichever the loaded
runtime library exports (GenericApi takes priority fallback)
- Generic API path implements full upscale + frame-generation context
creation, configure, dispatch, and destroy lifecycle
- dlopen error captured and surfaced in lastError_ on Linux so runtime
initialization failures are actionable
- FSR3 runtime init failure log now includes path kind, error string,
and loaded library path for easier debugging
- tools/generate_ffx_sdk_vk_permutations.sh added: auto-bootstraps
missing VK permutation headers; DXC auto-downloaded on Linux/Windows
MSYS2; macOS reads from PATH (CI installs via brew dxc)
- CMakeLists: add upscalers/include to probe include dirs, invoke
permutation script before SDK build, scope FFX pragma/ODR warning
suppressions to affected TUs, add runtime-copy dependency on wowee
- UI labels updated from "FSR2" → "FSR3" in settings, tuning panel,
performance HUD, and combo boxes
- CI macOS job now installs dxc via Homebrew for permutation codegen
2026-03-09 12:51:59 -07:00
# GCC LTO emits -Wodr for FFX enum-name mismatches across SDK generations.
# We intentionally keep FSR2+FSR3 integrations in separate TUs and suppress
# this linker-time diagnostic to avoid CI noise.
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_compile_options(wowee PRIVATE -Wno-odr)
target_link_options(wowee PRIVATE -Wno-odr)
endif()
2026-02-02 12:24:50 -08:00
endif()
2026-02-23 16:30:49 +01:00
# Debug build flags
if(MSVC)
# /ZI — Edit-and-Continue debug info (works with hot-reload in VS 2022)
# /RTC1 — stack-frame and uninitialised-variable runtime checks (Debug only)
# /sdl — additional SDL security checks
# /Od — disable optimisation so stepping matches source lines exactly
target_compile_options(wowee PRIVATE
$<$<CONFIG:Debug>:/ZI /RTC1 /sdl /Od>
)
# Ensure the linker emits a .pdb alongside the .exe for every config
target_link_options(wowee PRIVATE
$<$<CONFIG:Debug>:/DEBUG:FULL>
$<$<CONFIG:RelWithDebInfo>:/DEBUG:FASTLINK>
)
else()
# -g3 — maximum DWARF debug info (includes macro definitions)
# -Og — optimise for debugging (better than -O0, keeps most frames)
# -fno-omit-frame-pointer — preserve frame pointers so stack traces are clean
2026-04-03 20:19:33 -07:00
# Frame pointers in all configs (negligible perf cost, critical for crash backtraces)
2026-02-23 16:30:49 +01:00
target_compile_options(wowee PRIVATE
2026-04-03 20:19:33 -07:00
-fno-omit-frame-pointer
$<$<CONFIG:Debug>:-g3 -Og>
$<$<CONFIG:RelWithDebInfo>:-g>
2026-02-23 16:30:49 +01:00
)
endif()
2026-04-03 09:41:34 +03:00
# ── Unit tests (Catch2) ──────────────────────────────────────
if(WOWEE_BUILD_TESTS)
enable_testing()
add_subdirectory(tests)
endif()
2026-02-23 16:30:49 +01:00
# AddressSanitizer — catch buffer overflows, use-after-free, etc.
# Enable with: cmake ... -DWOWEE_ENABLE_ASAN=ON -DCMAKE_BUILD_TYPE=Debug
if(WOWEE_ENABLE_ASAN)
if(MSVC)
target_compile_options(wowee PRIVATE /fsanitize=address)
# ASAN on MSVC requires the dynamic CRT (/MD or /MDd)
target_compile_options(wowee PRIVATE
$<$<CONFIG:Debug>:/MDd>
$<$<CONFIG:Release>:/MD>
)
else()
2026-04-03 09:41:34 +03:00
target_compile_options(wowee PRIVATE -fsanitize=address,undefined -fno-omit-frame-pointer)
target_link_options(wowee PRIVATE -fsanitize=address,undefined)
2026-02-23 16:30:49 +01:00
endif()
2026-04-03 09:41:34 +03:00
message(STATUS "AddressSanitizer + UBSan: ENABLED")
2026-02-23 16:30:49 +01:00
endif()
2026-02-18 20:10:47 -08:00
# Release build optimizations
include(CheckIPOSupported)
check_ipo_supported(RESULT _ipo_supported OUTPUT _ipo_error)
if(_ipo_supported)
set_property(TARGET wowee PROPERTY INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE)
endif()
if(NOT MSVC)
# -O3: more aggressive inlining and auto-vectorization vs CMake's default -O2
target_compile_options(wowee PRIVATE $<$<CONFIG:Release>:-O3>)
# -fvisibility=hidden: keeps all symbols internal by default, shrinks binary
# and gives the linker and optimizer more freedom to dead-strip and inline
target_compile_options(wowee PRIVATE $<$<CONFIG:Release>:-fvisibility=hidden -fvisibility-inlines-hidden>)
endif()
2026-02-23 16:30:49 +01:00
# Copy assets next to the executable (runs every build, not just configure).
# Uses $<TARGET_FILE_DIR:wowee> so MSVC multi-config generators place assets
# in bin/Debug/ or bin/Release/ alongside the exe, not the common bin/ parent.
add_custom_command(TARGET wowee POST_BUILD
2026-02-22 02:59:24 -08:00
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_CURRENT_SOURCE_DIR}/assets
2026-02-23 16:30:49 +01:00
$<TARGET_FILE_DIR:wowee>/assets
COMMENT "Syncing assets to $<TARGET_FILE_DIR:wowee>/assets"
2026-02-22 02:59:24 -08:00
)
2026-02-23 16:30:49 +01:00
refactor(game): split GameHandler into domain handlers
Extract domain-specific logic from the monolithic GameHandler into
dedicated handler classes, each owning its own opcode registration,
state, and packet parsing:
- CombatHandler: combat, XP, kill, PvP, loot roll (~26 methods)
- SpellHandler: spells, auras, pet stable, talent (~3+ methods)
- SocialHandler: friends, guild, groups, BG, RAF, PvP AFK (~14+ methods)
- ChatHandler: chat messages, channels, GM tickets, server messages,
defense/area-trigger messages (~7+ methods)
- InventoryHandler: items, trade, loot, mail, vendor, equipment sets,
read item (~3+ methods)
- QuestHandler: gossip, quests, completed quest response (~5+ methods)
- MovementHandler: movement, follow, transport (~2 methods)
- WardenHandler: Warden anti-cheat module
Each handler registers its own dispatch table entries via
registerOpcodes(DispatchTable&), called from
GameHandler::registerOpcodeHandlers(). GameHandler retains core
orchestration: auth/session handshake, update-object parsing,
opcode routing, and cross-handler coordination.
game_handler.cpp reduced from ~10,188 to ~9,432 lines.
Also add a POST_BUILD CMake step to symlink Data/ next to the
executable so expansion profiles and opcode tables are found at
runtime when running from build/bin/.
2026-03-28 09:42:37 +03:00
# Symlink Data/ next to the executable so expansion profiles, opcode tables,
# and other runtime data files are found when running from the build directory.
if(NOT WIN32)
add_custom_command(TARGET wowee POST_BUILD
COMMAND ${CMAKE_COMMAND} -E create_symlink
${CMAKE_CURRENT_SOURCE_DIR}/Data
$<TARGET_FILE_DIR:wowee>/Data
COMMENT "Symlinking Data to $<TARGET_FILE_DIR:wowee>/Data"
)
endif()
2026-02-23 16:30:49 +01:00
# On Windows, SDL 2.28+ uses LoadLibraryExW with LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
# which does NOT include System32. Copy vulkan-1.dll into the output directory so
# SDL_Vulkan_LoadLibrary can locate it without needing a full system PATH search.
if(WIN32)
2026-02-23 18:32:47 -08:00
find_file(VULKAN_DLL vulkan-1.dll
PATHS "$ENV{SystemRoot}/System32" "$ENV{VULKAN_SDK}/Bin"
NO_DEFAULT_PATH)
if(VULKAN_DLL)
add_custom_command(TARGET wowee POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${VULKAN_DLL}" "$<TARGET_FILE_DIR:wowee>/vulkan-1.dll"
COMMENT "Copying vulkan-1.dll to output directory"
)
else()
message(STATUS " vulkan-1.dll not found — skipping copy (MSYS2 provides it via PATH)")
endif()
2026-02-23 16:30:49 +01:00
endif()
2026-02-02 12:24:50 -08:00
# Install targets
install(TARGETS wowee
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
2026-02-18 18:29:34 -08:00
# Note: tool install rules are placed next to each target definition below.
2026-02-18 18:18:30 -08:00
# Install built-in assets (exclude proprietary music)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/assets
DESTINATION bin
PATTERN "Original Music" EXCLUDE)
# On Windows, install any DLLs that were bundled into the build output dir
# (populated by the CI workflow's DLL-bundling step before cpack runs)
if(WIN32)
install(DIRECTORY "${CMAKE_BINARY_DIR}/bin/"
DESTINATION bin
FILES_MATCHING PATTERN "*.dll")
endif()
2026-02-11 15:24:05 -08:00
# Linux desktop integration (launcher + icon)
if(UNIX AND NOT APPLE)
set(WOWEE_LINUX_ICON_PATH "${CMAKE_INSTALL_FULL_DATAROOTDIR}/icons/hicolor/256x256/apps/wowee.png")
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/resources/wowee.desktop.in
${CMAKE_CURRENT_BINARY_DIR}/wowee.desktop
@ONLY
)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/wowee.desktop
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/assets/Wowee.png
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/256x256/apps
RENAME wowee.png)
endif()
2026-02-12 20:32:14 -08:00
# ---- Tool: asset_extract (MPQ → loose files) ----
if(STORMLIB_LIBRARY AND STORMLIB_INCLUDE_DIR)
add_executable(asset_extract
tools/asset_extract/main.cpp
tools/asset_extract/extractor.cpp
tools/asset_extract/path_mapper.cpp
tools/asset_extract/manifest_writer.cpp
2026-05-06 10:23:32 -07:00
tools/asset_extract/open_format_emitter.cpp
2026-02-13 00:10:01 -08:00
src/pipeline/dbc_loader.cpp
2026-05-06 10:23:32 -07:00
src/pipeline/blp_loader.cpp
2026-05-06 10:32:17 -07:00
src/pipeline/m2_loader.cpp
src/pipeline/wmo_loader.cpp
2026-05-06 10:36:14 -07:00
src/pipeline/adt_loader.cpp
2026-05-06 10:32:17 -07:00
src/pipeline/wowee_model.cpp
src/pipeline/wowee_building.cpp
2026-05-06 10:36:14 -07:00
src/pipeline/wowee_collision.cpp
2026-02-13 00:10:01 -08:00
src/core/logger.cpp
2026-02-12 20:32:14 -08:00
)
target_include_directories(asset_extract PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/tools/asset_extract
${STORMLIB_INCLUDE_DIR}
)
2026-05-06 02:30:04 -07:00
target_include_directories(asset_extract SYSTEM PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/extern
)
2026-02-12 20:32:14 -08:00
target_link_libraries(asset_extract PRIVATE
${STORMLIB_LIBRARY}
ZLIB::ZLIB
Threads::Threads
)
2026-02-23 14:09:51 +01:00
if(WIN32)
2026-02-23 18:32:47 -08:00
find_library(WININET_LIB wininet)
find_library(BZ2_LIB bz2)
if(WININET_LIB)
target_link_libraries(asset_extract PRIVATE ${WININET_LIB})
endif()
if(BZ2_LIB)
target_link_libraries(asset_extract PRIVATE ${BZ2_LIB})
endif()
2026-02-23 14:09:51 +01:00
endif()
2026-02-12 20:32:14 -08:00
set_target_properties(asset_extract PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)
2026-02-18 18:29:34 -08:00
install(TARGETS asset_extract RUNTIME DESTINATION bin)
2026-02-12 20:32:14 -08:00
message(STATUS " asset_extract tool: ENABLED")
else()
message(STATUS " asset_extract tool: DISABLED (requires StormLib)")
endif()
2026-02-13 00:10:01 -08:00
# ---- Tool: dbc_to_csv (DBC → CSV text) ----
add_executable(dbc_to_csv
tools/dbc_to_csv/main.cpp
src/pipeline/dbc_loader.cpp
src/core/logger.cpp
)
target_include_directories(dbc_to_csv PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
2026-05-05 15:12:19 -07:00
${CMAKE_CURRENT_SOURCE_DIR}/extern
2026-02-13 00:10:01 -08:00
)
target_link_libraries(dbc_to_csv PRIVATE Threads::Threads)
set_target_properties(dbc_to_csv PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)
2026-02-18 18:29:34 -08:00
install(TARGETS dbc_to_csv RUNTIME DESTINATION bin)
2026-02-13 00:10:01 -08:00
2026-02-13 00:55:36 -08:00
# ---- Tool: auth_probe (LOGON_CHALLENGE probe) ----
add_executable(auth_probe
tools/auth_probe/main.cpp
src/auth/auth_packets.cpp
src/auth/auth_opcodes.cpp
src/auth/crypto.cpp
src/network/packet.cpp
src/network/socket.cpp
src/network/tcp_socket.cpp
src/core/logger.cpp
)
target_include_directories(auth_probe PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
)
2026-02-18 19:12:16 -08:00
target_link_libraries(auth_probe PRIVATE Threads::Threads OpenSSL::Crypto
$<$<BOOL:${WIN32}>:ws2_32>)
2026-02-13 00:55:36 -08:00
set_target_properties(auth_probe PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)
2026-02-18 18:29:34 -08:00
install(TARGETS auth_probe RUNTIME DESTINATION bin)
2026-02-13 00:55:36 -08:00
2026-02-13 01:32:15 -08:00
# ---- Tool: auth_login_probe (challenge + proof probe) ----
add_executable(auth_login_probe
tools/auth_login_probe/main.cpp
src/auth/auth_packets.cpp
src/auth/auth_opcodes.cpp
src/auth/crypto.cpp
src/auth/integrity.cpp
src/auth/big_num.cpp
src/auth/srp.cpp
src/network/packet.cpp
src/network/socket.cpp
src/network/tcp_socket.cpp
src/core/logger.cpp
)
target_include_directories(auth_login_probe PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
)
2026-02-18 19:12:16 -08:00
target_link_libraries(auth_login_probe PRIVATE Threads::Threads OpenSSL::Crypto
$<$<BOOL:${WIN32}>:ws2_32>)
2026-02-13 01:32:15 -08:00
set_target_properties(auth_login_probe PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)
2026-02-18 18:29:34 -08:00
install(TARGETS auth_login_probe RUNTIME DESTINATION bin)
2026-02-13 01:32:15 -08:00
2026-02-12 20:32:14 -08:00
# ---- Tool: blp_convert (BLP ↔ PNG) ----
add_executable(blp_convert
tools/blp_convert/main.cpp
src/pipeline/blp_loader.cpp
src/core/logger.cpp
)
target_include_directories(blp_convert PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/extern
)
target_link_libraries(blp_convert PRIVATE Threads::Threads)
set_target_properties(blp_convert PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)
2026-02-18 18:29:34 -08:00
install(TARGETS blp_convert RUNTIME DESTINATION bin)
2026-02-12 20:32:14 -08:00
feat(editor): add standalone world editor (rough/WIP)
Standalone wowee_editor tool for creating custom WoW zones.
This is a rough initial implementation — many features work but
M2/WMO rendering still has issues (frame sync, texture layout
transitions) and needs further polish.
Terrain:
- Create new blank terrain with 10 biome types (Grassland, Forest,
Jungle, Desert, Barrens, Snow, Swamp, Rocky, Beach, Volcanic)
- Load existing ADT tiles from extracted game data
- Sculpt brushes: Raise, Lower, Smooth, Flatten, Level
- Chunk edge stitching prevents seams between tiles
- Undo/redo (100-deep stack, Ctrl+Z/Ctrl+Shift+Z)
- Save to WoW ADT/WDT format
Texture Painting:
- Paint/Erase/Replace Base modes
- Full tileset texture browser (1285 textures from manifest)
- Per-zone directory filtering and search
- Alpha map editing with 4-layer limit (auto-replaces weakest)
Object Placement:
- M2 and WMO model placement with full manifest browser (11k M2s, 2k WMOs)
- M2Renderer + WMORenderer integrated (loads .skin files for WotLK)
- Ghost preview follows cursor before placing
- Ctrl+click selection, right-click context menu
- Transform gizmo (Move/Rotate/Scale with axis constraints)
- Position/rotation/scale editing in properties panel
NPC/Monster System:
- 631 creature presets scanned from manifest, categorized
(Critters, Beasts, Humanoids, Undead, Demons, etc.)
- Stats editor: level, health, mana, damage, armor, faction
- Behavior: Stationary, Patrol, Wander, Scripted
- Aggro/leash radius, respawn time, flags (hostile/vendor/etc.)
- Save creature spawns to JSON
Water:
- Place water at configurable height per chunk
- Liquid types: Water, Ocean, Magma, Slime
- Rendered as translucent colored quads
- Saved in ADT MH2O format
Infrastructure:
- Free-fly camera (WASD/QE, right-drag look, scroll speed)
- 5-mode toolbar: Sculpt | Paint | Objects | Water | NPCs
- Asset browser indexes full manifest on startup
- Editor water/marker shaders (pos+color vertex format)
- forceNoCull added to M2Renderer for editor use
- AssetManifest::getEntries() and AssetManager::getManifest() exposed
Known issues:
- M2/WMO rendering may not display on first placement (frame index
sync between update/render was misaligned — now fixed but untested
end-to-end)
- Validation layer errors on shutdown (resource cleanup ordering)
- Object placement on steep terrain can miss raycast
- No undo for texture painting or object placement yet
2026-05-05 03:47:03 -07:00
# ---- Tool: wowee_editor (Standalone World Editor) ----
add_executable(wowee_editor
tools/editor/main.cpp
refactor(editor): extract gen-audio-* handlers into cli_gen_audio.cpp
main.cpp had grown past 28k lines, with each new procedural-
generation command adding 100-200 lines to the inline if/else
dispatch chain. This commit starts breaking that up by moving
the four audio-related handlers (--gen-audio-tone, -noise,
-sweep, --gen-zone-audio-pack) into their own translation unit.
Pattern established here for future family extractions:
- Family lives in cli_<family>.{hpp,cpp}
- Single dispatch entry point: bool handle<Family>(int& i, int argc,
char** argv, int& outRc) — true if matched (writes outRc), false
to fall through.
- main.cpp's argv loop calls each family's dispatcher first and
returns its outRc on match, before the legacy in-line chain.
Side-benefit: consolidated the duplicated 25-line WAV header
writer + 5ms attack/release envelope into shared helpers
(writeWavMono16, applyEdgeEnvelope) at the top of the new file.
main.cpp drops from 28,943 → 28,329 lines (-614). Audio family
is fully self-contained (~440 lines), behavior unchanged
(verified by re-running tone/noise/sweep + zone-audio-pack).
2026-05-08 16:19:30 -07:00
tools/editor/cli_gen_audio.cpp
2026-05-08 16:46:14 -07:00
tools/editor/cli_zone_packs.cpp
2026-05-08 17:12:10 -07:00
tools/editor/cli_audits.cpp
2026-05-08 17:36:10 -07:00
tools/editor/cli_readmes.cpp
2026-05-08 18:24:01 -07:00
tools/editor/cli_zone_inventory.cpp
2026-05-08 18:47:06 -07:00
tools/editor/cli_project_inventory.cpp
refactor(editor): extract printUsage into cli_help.cpp
Pulls the 597-line block of printf calls that emits the --help
text out of main.cpp into its own translation unit. printUsage
is the longest single function in main.cpp by far and was pure
boilerplate (no logic, just a flat list of help lines).
Function moved verbatim to wowee::editor::cli::printUsage; all
6 in-tree callers (--list-commands, --info-cli-stats,
--info-cli-categories, --info-cli-help, --validate-cli-help,
and the bare --help/-h handler) updated to the namespaced name.
The CLI-meta commands continue to capture printUsage's stdout
the same way, so behavior is identical (verified by re-running
--validate-cli-help, --info-cli-stats, --list-commands).
main.cpp drops 26,650 → 26,286 lines (-364 net; -597 from the
removal, +233 from the include and namespace-prefixing the
six call sites... wait, no, +6). Actually main.cpp net delta
matches the body extraction.
2026-05-08 20:12:15 -07:00
tools/editor/cli_help.cpp
2026-05-08 20:59:02 -07:00
tools/editor/cli_gen_texture.cpp
refactor(editor): extract 12 composite mesh primitives into cli_gen_mesh.cpp
Moves the recently-added composite-prop mesh handlers (rock,
pillar, bridge, tower, house, fountain, statue, altar, portal,
archway, barrel, chest) into their own translation unit. These
12 handlers were the most contiguous block of similar-shaped
mesh code in main.cpp.
Other mesh handlers (--gen-mesh dispatcher, fence, tree, grid,
stairs, disc, tube, capsule, arch, pyramid, from-heightmap,
textured) still live in main.cpp and may be migrated in
subsequent batches.
main.cpp drops 24,270 → 22,681 lines (-1,589). Behavior
verified by re-running rock/chest/archway/fountain.
2026-05-08 22:19:41 -07:00
tools/editor/cli_gen_mesh.cpp
2026-05-09 00:04:27 -07:00
tools/editor/cli_mesh_io.cpp
2026-05-09 00:36:51 -07:00
tools/editor/cli_mesh_edit.cpp
2026-05-09 01:18:09 -07:00
tools/editor/cli_wom_info.cpp
2026-05-09 01:57:37 -07:00
tools/editor/cli_format_validate.cpp
2026-05-09 02:25:05 -07:00
tools/editor/cli_convert.cpp
2026-05-09 02:48:58 -07:00
tools/editor/cli_format_info.cpp
2026-05-09 03:12:09 -07:00
tools/editor/cli_pack.cpp
2026-05-09 03:33:40 -07:00
tools/editor/cli_content_info.cpp
2026-05-09 03:52:44 -07:00
tools/editor/cli_zone_info.cpp
2026-05-09 04:14:32 -07:00
tools/editor/cli_data_tree.cpp
2026-05-09 04:35:08 -07:00
tools/editor/cli_diff.cpp
2026-05-09 05:05:22 -07:00
tools/editor/cli_spawn_audit.cpp
2026-05-09 05:19:04 -07:00
tools/editor/cli_items.cpp
2026-05-09 05:32:27 -07:00
tools/editor/cli_extract_info.cpp
2026-05-09 05:45:00 -07:00
tools/editor/cli_export.cpp
2026-05-09 05:57:25 -07:00
tools/editor/cli_bake.cpp
2026-05-09 06:13:41 -07:00
tools/editor/cli_migrate.cpp
2026-05-09 06:25:04 -07:00
tools/editor/cli_convert_single.cpp
refactor(editor): extract interop --validate-* into cli_validate_interop.cpp
Moves the four structural validators for INTEROP file formats
(--validate-stl, --validate-png, --validate-blp, --validate-jsondbc)
out of main.cpp into a new cli_validate_interop.{hpp,cpp} module.
These check files coming in/out of wowee from third-party tools,
distinct from cli_format_validate.cpp which validates the native
open formats (WOM, WOB, WOC, WHM).
main.cpp shrinks by 524 lines (10,644 to 10,121). Each validator
preserves its --json output mode for machine-readable reports.
2026-05-09 06:36:02 -07:00
tools/editor/cli_validate_interop.cpp
2026-05-09 06:46:02 -07:00
tools/editor/cli_glb_inspect.cpp
refactor(editor): extract WOM <-> OBJ/GLB/STL into cli_wom_io.cpp
Moves the four WOM interchange-format handlers (--export-obj,
--export-glb, --export-stl, --import-stl) out of main.cpp into
a new cli_wom_io.{hpp,cpp} module. WOM is our open M2
replacement; these are the bridge that lets it round-trip
through every external 3D tool — Blender, Three.js, slicers,
CAD packages — so the open format is actually useful.
main.cpp shrinks by 467 lines (9,464 to 8,997). The five WOB
and WHM exporters (--export-wob-glb, --export-whm-glb, etc.)
remain inline for a follow-up extraction.
2026-05-09 06:55:00 -07:00
tools/editor/cli_wom_io.cpp
refactor(editor): extract WOB/WHM/WOC IO into cli_world_io.cpp
Moves all six world-asset interchange handlers (--export-wob-glb,
--export-wob-obj, --import-wob-obj, --export-whm-glb,
--export-whm-obj, --export-woc-obj) out of main.cpp into a new
cli_world_io.{hpp,cpp} module. WOB / WHM / WOC are our open
replacements for proprietary WMO / ADT-heightmap / ADT-collision
data; these are the bridge that lets the open formats round-trip
through Blender, MeshLab, Three.js, and the rest of the standard
3D toolchain.
main.cpp shrinks by 858 lines (8,997 to 8,140). The single-mesh
--import-obj handler stays inline for now -- it shadow-mirrors
cli_wom_io's --import-stl semantics and will move there next.
2026-05-09 07:03:14 -07:00
tools/editor/cli_world_io.cpp
refactor(editor): extract --info-{zone,project}-tree into cli_info_tree.cpp
Moves the two tree-style content browser handlers
(--info-zone-tree, --info-project-tree) out of main.cpp into
a new cli_info_tree.{hpp,cpp} module. Both render
Unix-`tree`-style hierarchical views — one drilling into a
single zone (manifest, tiles, creatures, objects, quests,
files) and one giving a bird's-eye view of every zone in a
project with bake/viewer status.
main.cpp shrinks by 201 lines (8,140 to 7,939). The remaining
info-zone/-project-* pairs (bytes, extents, water, density,
audio) form the next natural extraction batch.
2026-05-09 07:10:12 -07:00
tools/editor/cli_info_tree.cpp
2026-05-09 07:16:27 -07:00
tools/editor/cli_info_bytes.cpp
2026-05-09 07:22:06 -07:00
tools/editor/cli_info_extents.cpp
2026-05-09 07:28:15 -07:00
tools/editor/cli_info_water.cpp
2026-05-09 07:33:40 -07:00
tools/editor/cli_info_density.cpp
2026-05-09 07:38:36 -07:00
tools/editor/cli_info_audio.cpp
2026-05-09 07:44:57 -07:00
tools/editor/cli_world_info.cpp
2026-05-09 14:38:05 -07:00
tools/editor/cli_world_map.cpp
feat(pipeline): add WSND (Wowee Sound Catalog) format
Novel open replacement for Blizzard's SoundEntries.dbc +
SoundEntriesAdvanced.dbc. The 10th open format added to the
editor — covers the audio-metadata gap (the previous 9 cover
geometry, terrain, atmosphere, and world manifests, but no
sound metadata).
Format:
• magic "WSND", version 1, little-endian
• catalogName + entry count
• per entry: soundId / kind / flags / volume /
minDistance / maxDistance / filePath / label
Kind enum (7 categories):
sfx, music, ambient, ui, voice, spell, combat
Flags packed (3 bits used, rest reserved):
loop (0x01), 3d (0x02), stream (0x04)
API: WoweeSoundLoader::save / load / exists; presets
makeStarter (one entry per kind), makeAmbient (wilderness
loops + footsteps), makeTavern (fire + crowd + drink + door
+ lute).
CLI added (5 flags, 465 documented total now):
--gen-sound-catalog <base> [name]
--gen-sound-catalog-ambient <base> [name]
--gen-sound-catalog-tavern <base> [name]
--info-wsnd <base> [--json]
--validate-wsnd <base> [--json]
Validator catches: out-of-range kind, NaN/inf volume or
distances, 3D sounds with bad min/max, duplicate sound IDs,
empty filePaths.
All 3 presets verified: save / load / validate clean
on first run. Variable-length string fields use length-
prefixed encoding with a 1 MiB sanity cap on read to
prevent corrupted-file allocation blowups.
2026-05-09 14:47:16 -07:00
tools/editor/cli_sound_catalog.cpp
feat(pipeline): add WSPN (Wowee Spawn Point catalog) format
Novel open replacement for AzerothCore-style scattered
creature_template / gameobject SQL spawn tables PLUS the
ADT MDDF / MODF doodad-placement chunks. The 11th open
format, and the first that covers the live world-content
side (atmosphere + sounds + spawns now form the runtime
"what fills this zone" picture).
A WSPN file holds all spawn points for a zone in a single
table, with kind discriminating creature vs game object
vs static doodad. The same format powers:
• server runtime — knows what NPCs / objects to spawn
• editor — draws spawn markers
• renderer — reads the doodad subset directly to
draw static props without going
through a server roundtrip
Format:
• magic "WSPN", version 1, little-endian
• per entry: kind / entryId / position(3f) / rotation(3f)
/ scale / flags / respawnSec / factionId /
questIdRequired / wanderRadius / label
Flags packed: disabled (0x01), event-only (0x02),
quest-phased (0x04). Reserved bits for future per-entry
encoding extensions.
API: WoweeSpawnsLoader::save / load / exists; presets
makeStarter (1 each kind), makeCamp (4-bandit ring +
chest + 2 tents), makeVillage (6 NPCs + 2 signs + 4
corner trees).
CLI added (5 flags, 473 documented total now):
--gen-spawns / --gen-spawns-camp / --gen-spawns-village
--info-wspn / --validate-wspn
Validator catches: out-of-range kind, NaN/inf coords,
non-positive scale, doodad with non-zero respawn (static
prop misuse), creature with respawn=0 (won't respawn after
kill), entryId=0 (orphan reference).
All 3 presets save / load / re-validate clean. Doodad and
game-object entries explicitly set wanderRadius=0 so the
generated catalogs are noise-free.
2026-05-09 14:57:53 -07:00
tools/editor/cli_spawns_catalog.cpp
feat(pipeline): add WIT (Wowee Item Template) format
Novel open replacement for Blizzard's Item.dbc +
ItemDisplayInfo.dbc + the SQL item_template tables that
AzerothCore-style servers store item definitions in. The
12th open format added to the editor.
A WIT file holds the catalog of all items in a content
pack: weapons, armor, consumables, quest items, trade
goods. Each entry pairs gameplay metadata (stats, level
reqs, flags, weapon damage / speed) with display metadata
(displayId for icon / model, quality color), so the
runtime can render inventory tooltips and equip slots
from a single load.
Format:
• magic "WITM", version 1, little-endian
• per item: itemId / displayId / quality / itemClass /
itemSubClass / inventoryType / flags / requiredLevel /
itemLevel / sellPrice / buyPrice / maxStack / durability
/ damageMin / damageMax / attackSpeedMs /
statCount + stats[] / name / description
Enums:
• Quality: Poor..Heirloom (8 levels)
• Class: Consumable, Weapon, Armor, Quest, ... (13)
• InventoryType: Head..Cloak..Weapon2H (18 slots)
• Flags: Unique, BoP, BoE, QuestItem, Conjured, ...
• StatType: Stamina, Strength, Intellect, Defense, ...
API: WoweeItemLoader::save / load / exists / findById;
presets makeStarter (4-item demo), makeWeapons (5 items
common -> legendary), makeArmor (6-piece mail set with
BoE flag).
CLI added (5 flags, 480 documented total now):
--gen-items / --gen-items-weapons / --gen-items-armor
--info-wit / --validate-wit
Validator catches: itemId=0, duplicate itemIds, weapons
with 0 damage or attackSpeed, weapons with non-weapon
slot, equippables with durability=0 or maxStack>1, sell
price >= buy price (vendor would lose money), out-of-range
quality.
All 3 presets save / load / re-validate clean. Info-table
output includes a gold/silver/copper price formatter for
hand-readability.
2026-05-09 15:04:48 -07:00
tools/editor/cli_items_catalog.cpp
feat(pipeline): add WLOT (Wowee Loot Table) format
Novel open replacement for AzerothCore-style
creature_loot_template / gameobject_loot_template SQL
tables. The 13th open format added to the editor.
Pairs naturally with the WIT item catalog from the
preceding commit: each loot drop's itemId references an
entry in a WIT file, so a content pack ships both the
item definitions and the loot tables that reference them.
The runtime composes WIT + WLOT + WSPN to drive the full
"creature dies, drops items" flow without any SQL.
Format:
• magic "WLOT", version 1, little-endian
• per table: creatureId / flags / dropCount /
moneyMin..Max / itemDropCount + drops[]
• per drop: itemId / chancePercent (float, 0..100) /
minQty / maxQty / drop_flags
Table flags: QuestOnly, GroupOnly, Pickpocket
Drop flags: QuestRequired, GroupRollOnly, AlwaysDrop
dropCount is the slot budget — how many distinct drops
to roll per kill. Each item drop is rolled independently
against its chancePercent (so dropCount=2 with 4 candidate
drops at varying chances gives the classic "up to 2 distinct
items per kill" behavior). Drops with the AlwaysDrop flag
bypass the slot budget — used for guaranteed quest items.
API: WoweeLootLoader::save / load / exists /
findByCreatureId; presets makeStarter (1 table, 1 drop),
makeBandit (4 candidates, dropCount=2, matches the camp
spawns from WSPN at creatureId=1000), makeBoss (6 candidates
including guaranteed quest item via AlwaysDrop and a
group-only epic at 5%).
CLI added (5 flags, 486 documented total now):
--gen-loot / --gen-loot-bandit / --gen-loot-boss
--info-wlot / --validate-wlot
Validator catches: creatureId=0, duplicates, chance not in
0..100, NaN chance, money min > max, minQty > maxQty,
dropCount=0 with non-empty drops list (silent dead config).
All 3 presets save / load / re-validate clean. The bandit
table's creatureId=1000 deliberately matches WSPN's
makeCamp creatureId so the open-format demo content pack
already has working cross-references.
2026-05-09 15:11:08 -07:00
tools/editor/cli_loot_catalog.cpp
feat(pipeline): add WCRT (Wowee Creature Template) format
Novel open replacement for the AzerothCore-style
creature_template SQL table PLUS the Blizzard
CreatureTemplate / CreatureFamily / CreatureType.dbc trio.
The 14th open format added to the editor.
This is the canonical metadata side of creatures shared
across every spawn instance: HP, level range, faction,
behavior flags, NPC role bits (vendor / trainer /
quest-giver / innkeeper), base damage, equipped gear
references.
Cross-references with the previously-added formats:
WSPN.entry.entryId -> WCRT.entry.creatureId
WLOT.entry.creatureId -> WCRT.entry.creatureId
WCRT.entry.equipped* -> WIT.entry.itemId
The 4-format set (WIT + WLOT + WSPN + WCRT) now lets a
content pack define a complete RPG zone's creature
ecosystem: what creatures are, where they spawn, what they
drop, and what gear they carry — entirely in open formats
with no SQL dependencies.
Format:
• magic "WCRT", version 1, little-endian
• per entry: creatureId / displayId / name / subname /
minLevel..maxLevel / baseHealth + healthPerLevel /
baseMana + manaPerLevel / factionId / npcFlags /
typeId / familyId / damageMin..Max / attackSpeedMs /
baseArmor / walkSpeed + runSpeed / gossipId /
equippedMain + equippedOffhand + equippedRanged /
aiFlags
Enums:
• TypeId: Beast / Dragon / Demon / Elemental / Giant /
Undead / Humanoid / Critter / Mechanical
• FamilyId: Wolf / Cat / Bear / Boar / Raptor / Hyena /
Spider / Gorilla / Crab (for Beast types)
• NpcFlags: Vendor / QuestGiver / Trainer / Banker /
Innkeeper / FlightMaster / Auctioneer /
Repair / Stable
• Behavior: Passive / Aggressive / FleeLowHp / CallHelp /
NoLeash
API: WoweeCreatureLoader::save / load / exists /
findById; presets makeStarter (1 innkeeper),
makeBandit (creatureId=1000 matches WSPN/WLOT bandit
references, equips WIT itemId=1001 sword), makeMerchants
(creatureIds 4001/4002/4003 match WSPN village labels).
CLI added (5 flags, 493 documented total):
--gen-creatures / --gen-creatures-bandit / --gen-creatures-merchants
--info-wcrt / --validate-wcrt
Validator catches: creatureId=0, duplicates, level=0,
minLevel>maxLevel, baseHealth=0, damageMin>damageMax,
attackSpeed=0, non-positive walk/runSpeed, behavior flag
contradictions (passive+aggressive), vendor with
aggressive behavior (player can't trade).
2026-05-09 15:18:44 -07:00
tools/editor/cli_creatures_catalog.cpp
feat(pipeline): add WQT (Wowee Quest Template) format
Novel open replacement for AzerothCore-style quest_template
SQL tables PLUS the Blizzard Quest.dbc / QuestObjective.dbc
trio. The 15th open format added to the editor — and the
last gameplay-graph piece the catalog needed.
Cross-references with previously-added formats:
WQT.giverCreatureId -> WCRT.entry.creatureId
WQT.turninCreatureId -> WCRT.entry.creatureId
WQT.objective.targetId -> WCRT (kill) / WIT (collect) /
WOB (interact)
WQT.rewardItem.itemId -> WIT.entry.itemId
WQT.prevQuestId -> WQT.entry.questId (intra-format)
WQT.nextQuestId -> WQT.entry.questId
Together with WIT / WCRT / WLOT / WSPN / WOMX / WOL / WOW /
WSND, a content pack can now ship a complete RPG zone
(terrain + props + atmosphere + sounds + creatures + items
+ loot + spawns + quests) entirely in open formats with no
SQL or .dbc dependencies. 15 of 15 expected slots filled.
Format:
• magic "WQTM", version 1, little-endian
• per quest: questId / title / objective / description /
minLevel..maxLevel + questLevel / requiredClass+RaceMask /
prev+nextQuestId / giver+turninCreatureId /
objectives[] / xpReward + moneyCopperReward /
rewardItems[] / flags
Per-objective:
kind (kill/collect/interact/visit/escort/cast),
targetId, quantity
Per-reward:
itemId, qty, pickFlags (AutoGiven / PlayerChoice)
Quest flags: Daily / Weekly / Raid / Group / AutoComplete /
AutoAccept / Repeatable / ClassQuest / Pvp
API: WoweeQuestLoader::save / load / exists / findById;
presets makeStarter (1 simple kill quest, references the
bandit creatureId=1000), makeChain (3-quest chain with
prev/next links + AutoComplete bridge + player-choice
rewards), makeDaily (Daily+Repeatable+AutoAccept combo).
CLI added (5 flags, 500 documented total — round milestone):
--gen-quests / --gen-quests-chain / --gen-quests-daily
--info-wqt / --validate-wqt
Validator catches: questId=0+duplicates, level=0,
maxLevel<minLevel, empty title, no objectives without
AutoComplete (player can't finish), no rewards at all,
Daily without Repeatable (incoherent), targetId=0,
quantity=0, unknown objective kind, reward itemId=0 or qty=0.
The 3-quest chain demo exercises every major feature:
• multiple objective kinds (visit / collect / kill)
• prev/next chain links
• AutoComplete dialogue-bridge quest
• PlayerChoice reward (1 of 2 weapons)
2026-05-09 15:25:02 -07:00
tools/editor/cli_quests_catalog.cpp
feat(pipeline): add WGOT (Wowee Game Object Template) format
Novel open replacement for AzerothCore-style
gameobject_template SQL tables PLUS the Blizzard
GameObjectDisplayInfo.dbc / GameObject types metadata. The
16th open format added to the editor.
Game objects are the non-creature interactable scenery:
chests (with loot), doors, buttons, mailboxes, herb / ore
gathering nodes, fishing pools, signposts, mounts. Each
has a displayId for the model, a typeId driving its
interaction logic, and optional cross-references to a lock
(future WLCK) and loot table (existing WLOT).
Cross-references with previously-added formats:
WSPN.entry.entryId (kind=GameObject) -> WGOT.entry.objectId
WGOT.entry.lootTableId -> WLOT.entry.creatureId
(loot tables are
universal — chests
and creatures both
key by ID)
The dungeon preset's Bandit Strongbox uses lootTableId=2000
to match WLOT's bandit chest table id, so the demo content
stack already wires together: spawn (WSPN object kind 2000)
-> object template (WGOT 2000) -> loot table (WLOT 2000).
Format:
• magic "WGOT", version 1, little-endian
• per object: objectId / displayId / name / typeId /
size / castBarCaption / requiredSkill +
requiredSkillValue / lockId / lootTableId /
minOpenTimeMs..maxOpenTimeMs / flags
Enums:
• TypeId (16): Door / Button / Chest / Container /
QuestGiver / Text / Trap / Goober / Transport /
Mailbox / MineralNode / HerbNode / FishingNode /
Mount / Sign / Bonfire
• Flags: Disabled / ScriptOnly / UsableFromMount /
Despawn / Frozen / QuestGated
API: WoweeGameObjectLoader::save / load / exists /
findById; presets makeStarter (chest + mailbox + sign),
makeDungeon (door + button + 2 chests + trap with proper
WLOT cross-references), makeGather (Peacebloom herb +
Tin Vein ore + fishing pool with skill requirements).
CLI added (5 flags, 507 documented total now):
--gen-objects / --gen-objects-dungeon / --gen-objects-gather
--info-wgot / --validate-wgot
Validator catches: objectId=0 + duplicates, size<=0,
minOpenTime>maxOpenTime, gathering node without skill
requirement (anyone can harvest — usually a typo), chest
without loot table (script must populate), requiredSkillValue
set without requiredSkill (incoherent).
2026-05-09 15:31:49 -07:00
tools/editor/cli_objects_catalog.cpp
feat(pipeline): add WFAC (Wowee Faction Catalog) format
Novel open replacement for Blizzard's Faction.dbc +
FactionTemplate.dbc + the AzerothCore-style
reputation_reward / reputation_spillover SQL tables. The
17th open format added to the editor.
Combines the "displayable Faction" (player-facing name +
reputation thresholds for friendly/honored/revered/exalted)
with the "FactionTemplate matrix" (which factions are
hostile to which) into one entry. The runtime walks the
catalog to answer two questions:
• "Will faction A attack faction B on sight?" -> enemy list
• "What rep tier is the player with X?" -> thresholds
Cross-references with previously-added formats:
WCRT.entry.factionId -> WFAC.entry.factionId
WFAC.entry.parentFactionId -> WFAC.entry.factionId
WFAC.entry.enemies[] -> WFAC.entry.factionId
WFAC.entry.friends[] -> WFAC.entry.factionId
The starter preset's factionId 35 (Friendly) and 14
(Hostile) deliberately match the WCRT preset defaults, so
the demo content stack is consistent: WCRT.makeBandit's
factionId=14 has a real entry in WFAC.makeStarter that
declares it hostile to friendly NPCs (35) and players (1).
Format:
• magic "WFAC", version 1, little-endian
• per faction: factionId / parentFactionId / name /
description / reputationFlags / baseReputation /
7 ascending tier thresholds (hostile..exalted) /
enemies[] / friends[]
Enums:
• ReputationFlags: VisibleOnTab / AtWarDefault / Hidden /
NoReputation / IsHeader (group label)
• Tier (canonical): Hated / Hostile / Unfriendly /
Neutral / Friendly / Honored /
Revered / Exalted
API: WoweeFactionLoader::save / load / exists / findById +
WoweeFaction::isHostile(a, b); presets makeStarter (3-faction
demo matching WCRT defaults), makeAlliance (header +
Stormwind / Darnassus / Ironforge with reciprocal friend
lists + Defias enemy), makeWildlife (4 beast factions, each
hostile to player but ignoring other beasts).
CLI added (5 flags, 514 documented total now):
--gen-factions / --gen-factions-alliance / --gen-factions-wildlife
--info-wfac / --validate-wfac
Validator catches: factionId=0 + duplicates, empty name,
threshold ordering violations (hostile must be < unfriendly
< neutral < ... < exalted), self-listed as enemy or friend,
faction in both enemies and friends (incoherent).
2026-05-09 15:37:59 -07:00
tools/editor/cli_factions_catalog.cpp
feat(pipeline): add WLCK (Wowee Lock Template) format
Novel open replacement for Blizzard's Lock.dbc. The 18th
open format added to the editor. Closes the cross-reference
gap from WGOT.entry.lockId — until now that field pointed
to a format that didn't exist yet.
A lock is a multi-channel security check. Each lock has up
to 5 independent channels; a player can open the lock by
satisfying ANY ONE channel:
• Item — requires a specific key item (WIT cross-ref)
• Lockpick — requires the lockpicking skill at minimum rank
(rogue / engineering profession)
• Spell — requires casting a specific spell
• Damage — can be forced open with attack damage
Cross-references with previously-added formats:
WGOT.entry.lockId -> WLCK.entry.lockId
WLCK.channel.targetId (Item) -> WIT.entry.itemId
WLCK.channel.targetId (Lockpick) -> future WSKL skillId
WLCK.channel.targetId (Spell) -> future WSPL spellId
The starter and dungeon presets' lockIds (1 and 2)
deliberately match WGOT.makeDungeon's iron-door lockId=1
and bandit-strongbox lockId=2, so the demo content stack
already wires together: WSPN spawn -> WGOT object template
-> WLCK lock template -> WIT key items.
Format:
• magic "WLCK", version 1, little-endian
• per lock: lockId / name / flags / 5 fixed channel slots
• per channel: kind / skillRequired / targetId
• all 5 slots written even when unused (kind=None +
zeroed fields), keeping the per-entry size constant for
fast random access
Enums:
• ChannelKind: None / Item / Lockpick / Spell / Damage
• Flags: DestructOnOpen / RespawnOnKey / TrapOnFail
API: WoweeLockLoader::save / load / exists / findById;
presets makeStarter (Iron Door + Wooden Chest), makeDungeon
(matches WGOT cross-references; light/heavy lockpicks +
boss-key-only seal), makeProfessions (4-tier rogue lockpick
progression at ranks 1/100/175/250).
CLI added (5 flags, 521 documented total now):
--gen-locks / --gen-locks-dungeon / --gen-locks-professions
--info-wlck / --validate-wlck
Validator catches: lockId=0 + duplicates, all-None channels
(lock can never open), Item/Spell/Lockpick channels with
targetId=0 (no resource referenced), unknown channel kind,
skillRequired set on non-Lockpick channel (silently ignored
at runtime — flag as warning).
2026-05-09 15:44:26 -07:00
tools/editor/cli_locks_catalog.cpp
feat(pipeline): add WSKL (Wowee Skill Catalog) format
Novel open replacement for Blizzard's SkillLine.dbc +
SkillLineCategory.dbc + the AzerothCore-style player skill
base tables. The 19th open format added to the editor.
Defines every player-trackable skill: weapon proficiencies
(Swords, Axes, Bows), professions (Mining, Alchemy,
Cooking), languages (Common, Dwarvish), class
specializations (Fire, Frost, Holy, Protection), armor
proficiencies (Mail, Plate), and secondary skills (First
Aid, Lockpicking, Riding).
Cross-references with previously-added formats:
WLCK.channel.targetId (kind=Lockpick) -> WSKL.entry.skillId
WGOT.entry.requiredSkill -> WSKL.entry.skillId
The starter preset's skillIds 186 (Mining) and 633
(Lockpicking) deliberately match the canonical IDs already
referenced by WGOT.makeGather and WLCK.makeDungeon —
so the demo content stack now wires together end-to-end:
WGOT herb-node requires skill 186 -> WSKL Mining at rank 1+;
WLCK bandit-strongbox channel requires skill 633 -> WSKL
Lockpicking at rank 1+.
Format:
• magic "WSKL", version 1, little-endian
• per skill: skillId / name / description / categoryId /
canTrain / maxRank / rankPerLevel / iconPath
Enums:
• CategoryId (8): Weapon / Class / Profession /
SecondaryProfession / Language / ArmorProficiency /
Riding / WeaponSpec
API: WoweeSkillLoader::save / load / exists / findById;
presets makeStarter (5-skill demo with cross-referenced
canonical IDs), makeProfessions (12 classic professions:
9 primary + 3 secondary), makeWeapons (16 weapon skills
with canonical SkillLine IDs and rankPerLevel=5 auto-grow).
CLI added (5 flags, 528 documented total now):
--gen-skills / --gen-skills-professions / --gen-skills-weapons
--info-wskl / --validate-wskl
Validator catches: skillId=0 + duplicates, empty name,
maxRank=0, unknown categoryId, suspicious maxRank=1 on
non-Language skill (only languages cap at 1), weapon skill
with rankPerLevel=0 (won't auto-grow on use).
2026-05-09 15:50:25 -07:00
tools/editor/cli_skills_catalog.cpp
feat(pipeline): add WSPL (Wowee Spell Catalog) format
Novel open replacement for Blizzard's Spell.dbc +
SpellEffect.dbc + the AzerothCore-style spell_dbc /
spell_proc tables. The 20th open format added to the
editor — completes the canonical-data side of the gameplay
graph.
Each entry holds the metadata side of a spell: name,
description, school, range, mana / cast / cooldown times,
plus a single primary effect. The simplified effect model
(one effectKind + min/max value + misc field) covers the
common cases (damage / heal / buff / debuff / teleport /
summon / dispel) without needing to reproduce the full
multi-effect graph that classic Spell.dbc carries.
Cross-references with previously-added formats:
WLCK.channel.targetId (kind=Spell) -> WSPL.entry.spellId
WQT.objective.targetId (kind=SpellCast) -> WSPL.entry.spellId
WCRT.equippedMain (item with on-use) -> WIT -> WSPL
Format:
• magic "WSPL", version 1, little-endian
• per spell: spellId / name / description / iconPath /
school / targetType / effectKind / cast & cooldown &
GCD ms / manaCost / range min..max / minLevel /
maxStacks / durationMs / effectValueMin..Max /
effectMisc / flags
Enums:
• School (7): Physical / Holy / Fire / Nature / Frost /
Shadow / Arcane
• TargetType (6): Self / Single / Cone / AoeFromSelf /
Line / Ground
• EffectKind (7): Damage / Heal / Buff / Debuff / Teleport /
Summon / Dispel
• Flags: Passive / Hidden / Channeled / Ranged /
AreaOfEffect / Triggered / UnitTargetOnly /
FriendlyOnly / HostileOnly
API: WoweeSpellLoader::save / load / exists / findById;
presets makeStarter (Strike + Lesser Heal + Power Word:
Fortitude + Hearthstone, one per major effect kind),
makeMage (Frostbolt 116 + Fireball 133 + Arcane Intellect
1459 + Blink 1953, canonical Classic spellIds), makeWarrior
(Heroic Strike 78 + Thunder Clap 6343 + Battle Shout 6673 +
Mortal Strike 12294).
CLI added (5 flags, 535 documented total now):
--gen-spells / --gen-spells-mage / --gen-spells-warrior
--info-wspl / --validate-wspl
Validator catches: spellId=0 + duplicates, empty name,
school out of range, effectKind out of range, NaN range,
range/value min>max, FriendlyOnly+HostileOnly conflict
(incoherent), friendly-only with damage/debuff effect
(incoherent), hostile-only with heal/buff effect, buff/debuff
effect with durationMs=0 (instant fade — almost certainly
authoring oversight).
The validator caught a real preset-emitter authoring error
during initial smoke testing — buff spells were setting
effectValueMin without effectValueMax (validator's range
check immediately flagged it), prompting an in-batch fix
to set both fields. This is exactly the catch-the-typo
purpose validators serve.
2026-05-09 15:58:09 -07:00
tools/editor/cli_spells_catalog.cpp
feat(pipeline): add WACH (Wowee Achievement Catalog) format
Novel open replacement for Blizzard's Achievement.dbc +
AchievementCriteria.dbc + AchievementCategory.dbc + the
AzerothCore-style character_achievement /
character_achievement_progress SQL tables. The 21st open
format added to the editor.
Each achievement carries display metadata (name, description,
icon, points, faction restriction) plus a list of criteria
the player must satisfy. Criteria mirror the WQT objective
model (kind + targetId + quantity), so the runtime can
reuse the same progress-tracking machinery for both quests
and achievements.
Cross-references with previously-added formats — every
criterion kind has a real format target:
WACH.criteria.targetId (kind=KillCreature) -> WCRT.creatureId
WACH.criteria.targetId (kind=CompleteQuest) -> WQT.questId
WACH.criteria.targetId (kind=LootItem) -> WIT.itemId
WACH.criteria.targetId (kind=CastSpell) -> WSPL.spellId
WACH.criteria.targetId (kind=ReachSkillLevel) -> WSKL.skillId
WACH.criteria.targetId (kind=EarnReputation) -> WFAC.factionId
WACH.criteria.targetId (kind=CompleteAchievement) -> WACH.achievementId
(meta-achievements)
Format:
• magic "WACH", version 1, little-endian
• per achievement: id / categoryId / name / description /
iconPath / titleReward / points / minLevel / faction /
flags / criteria[]
• per criterion: criteriaId / kind / targetId / quantity /
description
Enums:
• CriteriaKind (9): KillCreature / CompleteQuest / LootItem /
ReachLevel / EarnReputation / CastSpell /
ReachSkillLevel / VisitArea /
CompleteAchievement
• Faction: Both / Alliance / Horde
• Flags: HiddenUntilEarned / ServerFirst / RealmFirst /
Tracking / Counter / Account
API: WoweeAchievementLoader::save / load / exists /
findById; presets makeStarter (3 simple kill/quest/level
demos), makeBandit (3 with WCRT/WGOT/WQT cross-refs),
makeMeta (3 base + 1 meta-achievement granting "the
Versatile" title, exercising CompleteAchievement criterion
kind that lets achievements depend on other achievements).
CLI added (5 flags, 542 documented total now):
--gen-achievements / --gen-achievements-bandit / --gen-achievements-meta
--info-wach / --validate-wach
Validator catches: achievementId=0 + duplicates, empty name,
faction out of range, no criteria (achievement can never
be earned), criterion quantity=0, unknown criterion kind,
targetId=0 on criterion kinds that need a real resource
reference (everything except ReachLevel which uses the
quantity field for the level number).
The bandit preset's cross-references close the gameplay
graph end-to-end: kill 50 creatureId=1000 (matches WCRT/
WSPN/WLOT bandit), loot objectId=2000 (matches WGOT bandit
strongbox), complete questId=1 (matches WQT Bandit Trouble).
The meta preset closes a separate loop: 3 sub-achievements
covering Mining (skillId=186), Lockpicking (skillId=633),
and Frostbolt cast count (spellId=116) — each pointing at
a real WSKL/WSPL entry that already exists in the demo
content stack.
2026-05-09 16:04:30 -07:00
tools/editor/cli_achievements_catalog.cpp
feat(pipeline): add WTRN (Wowee Trainer / Vendor catalog) format
Novel open replacement for AzerothCore-style npc_trainer +
npc_vendor SQL tables PLUS the Blizzard TrainerSpells.dbc
family. The 22nd open format added to the editor.
Unifies trainer spell lists and vendor item inventories
into one per-NPC entry. A creature flagged Trainer or
Vendor in WCRT references a WTRN entry that lists what they
teach / sell. The same NPC can be both — kindMask is a
bitmask covering the Trainer (0x01) and Vendor (0x02) kinds.
This format closes a major cross-format gap: WCRT.npcFlags
already had Vendor / Trainer bits, but until now there was
no format defining what a vendor sells or what a trainer
teaches. Now an NPC marked Vendor in WCRT has a real
inventory, and an NPC marked Trainer has a real spell list.
Cross-references — every WTRN field has a real format target:
WTRN.entry.npcId -> WCRT.entry.creatureId
WTRN.spell.spellId -> WSPL.entry.spellId
WTRN.spell.requiredSkillId -> WSKL.entry.skillId
WTRN.item.itemId -> WIT.entry.itemId
Format:
• magic "WTRN", version 1, little-endian
• per NPC: npcId / kindMask / greeting + spells[] + items[]
• per spell offer: spellId / moneyCostCopper /
requiredSkillId / requiredSkillRank / requiredLevel
• per item offer: itemId / stockCount (0xFFFFFFFF =
unlimited) / restockSec / extendedCost / moneyCostCopper
(0 = inherit from WIT.buyPrice)
API: WoweeTrainerLoader::save / load / exists / findByNpc;
presets makeStarter (innkeeper 4001 as both trainer +
vendor: teaches First Aid + sells starter items),
makeMageTrainer (NPC 4003 teaches the WSPL mage spells
at scaling cost), makeWeaponVendor (NPC 4002 sells WIT
weapons with mixed unlimited/finite stock + restock timers).
CLI added (5 flags, 551 documented total now):
--gen-trainers / --gen-trainers-mage / --gen-trainers-weapons
--info-wtrn / --validate-wtrn
Validator catches: npcId=0 + duplicates, kindMask=0 (NPC
offers nothing), Trainer flag without spells, Vendor flag
without items, spells/items present without the matching
kind bit (silently ignored at runtime), spellId=0 / itemId=0
in offers, finite stock with restockSec=0 (single-fill —
usually intentional but worth surfacing).
The 3 presets deliberately use npcIds matching WCRT village
merchants (4001/4002/4003) so the demo content stack is
self-consistent: WCRT 4001 has the Vendor + Trainer flag,
and WTRN 4001 actually defines what they sell and teach.
2026-05-09 16:12:58 -07:00
tools/editor/cli_trainers_catalog.cpp
feat(pipeline): add WGSP (Wowee Gossip Menu) format
Novel open replacement for AzerothCore-style gossip_menu +
gossip_menu_option + npc_text SQL tables PLUS the Blizzard
NpcText.dbc family. The 23rd open format added to the
editor.
An NPC's dialogue tree: a menu of options the player can
pick from when right-clicking the NPC. Each option may
bridge to another menu, trigger a vendor / trainer
interaction, offer a quest, etc. The simplified per-option
model (kind + actionTarget + flags + moneyCost) covers the
common cases without needing separate npc_text condition
tables.
Closes a major cross-format gap: WCRT.entry.gossipId has
existed since batch 116 (when WCRT was added) but pointed
to a format that didn't exist yet. The innkeeper preset's
menuId=4001 deliberately matches WCRT's Bartleby NPC so
the demo content stack can wire WCRT.gossipId = 4001 once
that field is plumbed through the runtime.
Cross-references:
WCRT.entry.gossipId -> WGSP.entry.menuId
WGSP.option.actionTarget (Submenu) -> WGSP.entry.menuId
WGSP.option.actionTarget (Vendor / Trainer)
-> WTRN.entry.npcId
WGSP.option.actionTarget (Quest) -> WQT.entry.questId
Format:
• magic "WGSP", version 1, little-endian
• per menu: menuId / titleText + options[]
• per option: optionId / text / kind / actionTarget /
requiredFlags / moneyCostCopper
Enums:
• OptionKind (13): Close / Submenu / Vendor / Trainer /
Quest / Tabard / Banker / Innkeeper /
FlightMaster / TextOnly / Script /
Battlemaster / Auctioneer
• OptionFlags: AllianceOnly / HordeOnly / Coinpouch /
QuestGated / Closes
API: WoweeGossipLoader::save / load / exists / findById;
presets makeStarter (1 menu with vendor + trainer + close),
makeInnkeeper (2-menu tree: main menu 4001 with hearth /
vendor / flight / submenu options + lore submenu 4002 that
links back), makeQuestGiver (1 menu with 2 quest options
referencing WQT 1 and 100, plus a paid respec script
exercising the Coinpouch flag with a 10g cost).
CLI added (5 flags, 558 documented total now):
--gen-gossip / --gen-gossip-innkeeper / --gen-gossip-questgiver
--info-wgsp / --validate-wgsp
Validator catches: menuId=0 + duplicates, empty title /
options, unknown option kind, empty option text, Submenu
options pointing at non-existent menuIds (intra-format
cross-reference resolution), Coinpouch flag without
moneyCost (misleading UI), AllianceOnly+HordeOnly conflict.
2026-05-09 16:20:07 -07:00
tools/editor/cli_gossip_catalog.cpp
2026-05-09 16:26:27 -07:00
tools/editor/cli_taxi_catalog.cpp
feat(pipeline): add WTAL (Wowee Talent catalog) format
Novel open replacement for Blizzard's TalentTab.dbc +
Talent.dbc + the AzerothCore-style talent_progression SQL
tables. The 25th open format added to the editor.
Defines class talent specialization trees: per-class set
of named tabs (Arms / Fury / Protection for warrior, Fire
/ Frost / Arcane for mage), each with talents arranged in
a row/column grid, each talent having up to 5 ranks and
an optional prerequisite chain.
Cross-references with previously-added formats:
WTAL.talent.prereqTalentId -> WTAL.talent.talentId
(intra-format chain)
WTAL.talent.rankSpellIds[] -> WSPL.entry.spellId
(spell granted at each rank)
Format:
• magic "WTAL", version 1, little-endian
• per tree: treeId / name / iconPath / requiredClassMask /
talents[] (row, col, maxRank, prereqTalentId+rank,
rankSpellIds[5] zero-padded for unused ranks)
Enums:
• ClassMask: bit positions match canonical CharClasses.dbc
classIds — Warrior / Paladin / Hunter / Rogue / Priest /
DK / Shaman / Mage / Warlock / Druid
API: WoweeTalentLoader::save / load / exists +
WoweeTalent::findTree / findTalent (global lookup across
all trees in the catalog).
Three preset emitters showcase tree shapes:
• makeStarter — 1 small tree (3-talent vertical chain)
• makeWarrior — 3 trees (Arms 4 / Fury 4 / Protection 3)
with WSPL cross-refs at capstones
(Mortal Strike -> WSPL 12294, Battle Shout
-> WSPL 6673, Thunder Clap -> WSPL 6343)
• makeMage — 3 trees (Arcane / Fire / Frost) with
capstones referencing Frostbolt 116 /
Fireball 133 / Blink 1953 from WSPL
CLI added (5 flags, 571 documented total now):
--gen-talents / --gen-talents-warrior / --gen-talents-mage
--info-wtal / --validate-wtal
Validator catches: tree+talent ids=0 or duplicates, empty
tree name, requiredClassMask=0 (every class would see this
tree — usually a typo), maxRank not in 1..5, talent listing
itself as prerequisite, prereqTalentId pointing at a
talent that doesn't exist in this catalog (intra-format
cross-reference resolution), prereqRank=0 or > the prereq
talent's maxRank (catches off-by-one references), gaps in
rankSpellIds progression (rank N has spell but rank N-1
doesn't — usually a typo).
The validator caught a real authoring bug in the makeMage /
makeWarrior presets during smoke testing — initial check
was comparing prereqRank against the WRONG talent's maxRank
(this talent's rather than the prereq's). Fixed in the same
commit by hoisting the check into the cross-reference
resolution pass where the prereq talent is in hand.
2026-05-09 16:33:45 -07:00
tools/editor/cli_talents_catalog.cpp
feat(pipeline): add WMS (Wowee Map / Area) catalog format
Novel open replacement for Blizzard's Map.dbc + AreaTable.dbc
+ the AzerothCore-style world_zone SQL tables. The 26th open
format added to the editor.
Defines two related kinds of locator in one catalog:
• Maps — top-level worlds (continents / instances / raids /
battlegrounds / arenas) with a friendly name,
type, expansion tag, and player-count cap.
• Areas — sub-zones within maps with friendly names, parent-
area chain, recommended level range, faction-
territory marker (alliance / horde / contested /
both), exploration XP, and an ambient-sound
cross-reference into WSND.
The runtime uses Areas for minimap labels, location strings
under the player frame, "Discover Sub-zone" XP gains, and
ambient-music selection on zone entry.
Cross-references with previously-added formats:
WMS.area.ambienceSoundId -> WSND.entry.soundId
WMS.area.parentAreaId -> WMS.area.areaId (intra-format
sub-zone hierarchy)
WSPN entries are tied to WMS.area boundaries by
world position (no direct ID — the runtime resolves
position -> area at lookup time)
Format:
• magic "WMSX", version 1, little-endian
• maps[] (each): mapId / name / shortName / mapType /
expansionId / maxPlayers
• areas[] (each): areaId / mapId / parentAreaId / name /
minLevel..maxLevel / factionGroup / explorationXP /
ambienceSoundId
Enums:
• MapType (5): Continent / Instance / Raid / Battleground / Arena
• ExpansionId (5): Classic / Tbc / Wotlk / Cata / Mop
• FactionGroup: Both / Alliance / Horde / Contested
(PvP-flagging zone)
API: WoweeMapsLoader::save / load / exists +
WoweeMaps::findMap / findArea.
Three preset emitters showcase the catalog shape:
• makeStarter — 1 continent + 3 areas with parent chain
(Goldshire is a sub-zone of Elwynn Forest)
• makeClassic — 2 continents + Deadmines instance + 6
areas (Stormwind/Elwynn/Goldshire/Westfall/
Duskwood/Teldrassil/Deadmines) with WSND
ambient-sound refs
• makeBgArena — Alterac Valley (40-player BG) + Nagrand
Arena (5v5 with maxPlayers=10)
CLI added (5 flags, 578 documented total now):
--gen-maps / --gen-maps-classic / --gen-maps-bgarena
--info-wms / --validate-wms
Validator catches: empty map name, unknown mapType / expansion,
BG/Arena with maxPlayers=0 (no participant cap), area ids=0
+ duplicates, empty area name, maxLevel < minLevel, areas
referencing non-existent maps, parentAreaId chains crossing
maps (sub-zones must be on the same world), self-parent.
2026-05-09 16:40:00 -07:00
tools/editor/cli_maps_catalog.cpp
feat(pipeline): add WCHC (Wowee Character Classes/Races) format
Novel open replacement for Blizzard's CharClasses.dbc +
CharRaces.dbc + CharStartOutfit.dbc trio. The 27th open
format added to the editor — completes the foundational
character-creation surface.
One file holds three flat arrays:
• classes — playable classes (Warrior / Mage / etc.) with
power type (mana/rage/focus/energy/runic),
base HP+power scaling, faction availability
• races — playable races with faction (Alliance/Horde/
Neutral), starting map+zone, default language
spell, base stats, racial mount spell
• outfits — starting gear loadout per (class, race, gender)
triple, listing item IDs and display slots
Cross-references with previously-added formats:
WCHC.race.startingMapId -> WMS.map.mapId
WCHC.race.startingZoneAreaId -> WMS.area.areaId
WCHC.race.defaultLanguageSpellId -> WSPL.entry.spellId
WCHC.race.mountSpellId -> WSPL.entry.spellId
WCHC.outfit.items.itemId -> WIT.entry.itemId
The starter preset's outfits use real WIT itemIds (1=Worn
Shortsword, 2=Linen Vest, 3=Healing Potion) so the demo
content stack is consistent: a freshly created Human Warrior
in WCHC starts with WIT items 1/2/3, drops them on death
into a WLOT-tracked corpse loot, and can be respawned via
WSPN, etc.
Format:
• magic "WCHC", version 1, little-endian
• classes[]: classId / name / icon / powerType / display /
baseHP+perLevel / basePower+perLevel / factionAvailability
• races[]: raceId / name / icon / factionId / male+female
displayId / 5 base stats / startingMap+zone /
defaultLanguage+mount spell IDs
• outfits[]: classId+raceId+gender + items[]
(each: itemId + displaySlot)
Enums:
• PowerType (6): Mana / Rage / Focus / Energy / RunicPower / Runes
• RaceFaction (3): Alliance / Horde / Neutral
• Gender: Male / Female
• FactionAvailability bitmask: AvailableAlliance, AvailableHorde
API: WoweeCharsLoader::save / load / exists +
WoweeChars::findClass / findRace / findOutfit (by class+race+gender).
CLI added (5 flags, 585 documented total now):
--gen-chars / --gen-chars-alliance / --gen-chars-allraces
--info-wchc / --validate-wchc
Validator catches: ids unique, baseHealth=0 (instant-death
character), factionAvailability=0 (no faction can pick),
empty names, factionId out of range, outfit references to
non-existent class/race ids (cross-format resolution),
gender > 1, outfit items with itemId=0, outfit with no
items (warning — naked character).
2026-05-09 16:47:04 -07:00
tools/editor/cli_chars_catalog.cpp
feat(pipeline): add WTKN (Wowee Token catalog) format
Novel open replacement for Blizzard's Currency.dbc +
CurrencyCategory.dbc + CurrencyTypes.dbc + the AzerothCore-
style player_currency SQL tables. The 28th open format
added to the editor.
Defines secondary currency tokens beyond gold: Honor Points
(PvP), Arena Points (rated PvP), Marks of Honor (per
battleground), faction reputation tokens, holiday-event
currencies. Each token has a balance cap, optional weekly
cap (regenerating earnings limit), and a category for
grouping in the player's currency tab.
Cross-references:
WTRN.item.extendedCost -> WTKN.entry.tokenId
(vendors can charge in tokens
instead of copper — when
extendedCost > 0 the runtime
looks up the matching token)
Format:
• magic "WTKN", version 1, little-endian
• per token: tokenId / name / description / iconPath /
category / maxBalance / weeklyCap / flags
Enums:
• Category (6): Misc / Pvp / Reputation / Crafting /
Seasonal / Holiday
• Flags: AccountWide / Tradeable / HiddenUntilEarned /
ResetsOnLogout / ConvertsToGold
API: WoweeTokenLoader::save / load / exists / findById.
Three preset emitters showcase typical token shapes:
• makeStarter — 3 tokens (Honor / Marks / Stormwind Guard
rep) covering Pvp + Reputation categories
• makePvp — full PvP set: Honor (75k) + Arena (5k +
weekly 1500) + 6 BG marks of honor for
classic + TBC + WotLK battlegrounds
• makeSeasonal — 4 holiday tokens (Tricky Treats /
Brewfest / Coin of Ancestry / Stranger's
Gift) all flagged ResetsOnLogout to make
them event-bound
CLI added (5 flags, 592 documented total now):
--gen-tokens / --gen-tokens-pvp / --gen-tokens-seasonal
--info-wtkn / --validate-wtkn
Validator catches: tokenId=0 + duplicates, empty name,
unknown category, weeklyCap > maxBalance (cap unreachable),
ResetsOnLogout + AccountWide combo (incoherent — account
state survives logout by definition).
2026-05-09 16:53:11 -07:00
tools/editor/cli_tokens_catalog.cpp
feat(pipeline): add WTRG (Wowee Area Trigger) format
Novel open replacement for Blizzard's AreaTrigger.dbc +
AreaTriggerTeleport.dbc + the AzerothCore-style
areatrigger_template / areatrigger_teleport SQL tables.
The 29th open format added to the editor.
Defines proximity-based event zones — when a player enters
a defined region (box or sphere), the runtime fires the
trigger's action: teleport to another map, award
exploration XP for a quest, run a server script, gate an
instance entrance behind a key item, mark a PvP boundary,
or simply display a "Discovered: {area name}" banner.
Cross-references with previously-added formats — every
trigger field has a real format target:
WTRG.entry.mapId / areaId -> WMS.map.mapId / WMS.area.areaId
WTRG.actionTarget (Teleport) -> WMS.mapId
WTRG.actionTarget (QuestExploration) -> WQT.questId
WTRG.requiredQuestId -> WQT.entry.questId
WTRG.requiredItemId -> WIT.entry.itemId (key)
Format:
• magic "WTRG", version 1, little-endian
• per trigger: triggerId / mapId / areaId / name /
center vec3 / shape / kind / boxDims vec3 / radius /
actionTarget / dest vec3 / destOrientation /
requiredQuestId / requiredItemId / minLevel
Enums:
• Shape (2): Box / Sphere
• Kind (7): Teleport / QuestExploration / Script /
InstanceEntrance / AreaName / CombatStartZone /
Waypoint
API: WoweeTriggerLoader::save / load / exists / findById.
Three preset emitters showcase common trigger shapes:
• makeStarter — area-name + quest-exploration with
cross-ref to WQT 100 ("Investigate the
Camp")
• makeDungeon — outdoor area-name + portal-style
InstanceEntrance with Deadmines key
gate (WIT itemId 5200, matches
WLCK.makeDungeon's Boss Vault Seal) +
interior exit teleport back outdoors
• makeFlightPath — 2 sphere waypoints near flight masters
so the runtime can auto-open the
flight UI on proximity (matches WTAX
starter node positions)
CLI added (5 flags, 601 documented total now):
--gen-triggers / --gen-triggers-dungeon / --gen-triggers-flightpath
--info-wtrg / --validate-wtrg
Validator catches: triggerId=0 + duplicates, unknown shape /
kind, non-finite center, sphere with radius<=0, box with
all-zero half-extents, teleport / instance with dest=(0,0,0)
(silently does nothing — usually a typo), QuestExploration
without an actionTarget questId.
2026-05-09 17:01:43 -07:00
tools/editor/cli_triggers_catalog.cpp
feat(pipeline): add WTIT (Wowee Title catalog) format
Novel open replacement for Blizzard's CharTitles.dbc + the
AzerothCore-style character_title SQL table. The 30th open
format added to the editor.
Defines the player-display titles awarded for completing
achievements ("the Versatile"), reaching PvP ranks
("Sergeant Major" / "Stone Guard"), participating in raids
("Champion of the Naaru"), levelling a profession ("Master
Locksmith"), or seasonal events ("Brewmaster", "the
Hallowed").
Closes a long-standing gap: WACH.entry.titleReward has been
a free-form string since batch 116 with no formal catalog
to resolve against. WTIT systematizes those strings into a
real catalog — the runtime resolves WACH.titleReward to a
WTIT entry by name, then displays the titleId in the player
title selector.
Cross-references:
WACH.entry.titleReward (string) ~= WTIT.entry.name
(string match — runtime
resolves achievement-
granted titles by
looking up matching WTIT
entry by name)
Format:
• magic "WTIT", version 1, little-endian
• per title: titleId / name / nameMale / nameFemale /
iconPath / prefix (suffix vs prefix display) /
category / sortOrder
Enums:
• Category (8): Achievement / Pvp / Raid / ClassTitle /
Event / Profession / Lore / Custom
API: WoweeTitleLoader::save / load / exists +
WoweeTitle::findById / findByName.
Three preset emitters showcase typical title catalogs:
• makeStarter — 4 titles (Versatile / Sergeant /
Champion / Hallowed) covering 4
categories
• makePvp — 28-title classic Honor System ladder
(14 Alliance ranks Private->Grand
Marshal + 14 Horde ranks Scout->High
Warlord)
• makeAchievement — 8 achievement titles including "the
Versatile" matching WACH.makeMeta's
achievement 250 titleReward + capstone
profession titles
CLI added (5 flags, 608 documented total now):
--gen-titles / --gen-titles-pvp / --gen-titles-achievement
--info-wtit / --validate-wtit
Validator catches: titleId=0 + duplicates, empty name,
unknown category, gender variants set on only one side
(causes mixed-gender display when the runtime falls back to
canonical for the unset side).
2026-05-09 17:07:56 -07:00
tools/editor/cli_titles_catalog.cpp
feat(pipeline): add WSEA (Wowee Seasonal Event) format
Novel open replacement for Blizzard's GameEvents.dbc + the
AzerothCore-style game_event / game_event_creature /
game_event_gameobject SQL tables. The 31st open format
added to the editor.
Calendar-based content: holidays (Hallow's End, Winter's
Veil), recurring promotional events (Children's Week,
Lunar Festival, Brewfest), one-time anniversaries, and
XP-bonus weekends. Each event has a start date, duration,
optional recurrence (yearly / monthly / weekly), faction
restriction, optional XP bonus, and a reward currency
cross-reference into WTKN.
Cross-references with previously-added formats:
WSEA.entry.tokenIdReward -> WTKN.entry.tokenId
(the seasonal currency the
event hands out — Tricky
Treats during Hallow's End,
Brewfest Tokens during
Brewfest, etc.)
The yearly preset's tokenIdReward values (200/201/202/203)
deliberately match WTKN.makeSeasonal's seasonal token ids
so the demo content stack already wires together: WSEA
yearly events grant WTKN tokens that vendors can charge in
via WTRN.item.extendedCost.
Format:
• magic "WSEA", version 1, little-endian
• per event: eventId / name / description / iconPath /
announceMessage / startDate (Unix epoch seconds) /
duration_seconds / recurrenceDays (0=one-shot, 365=yearly) /
holidayKind / factionGroup / bonusXpPercent / tokenIdReward
Enums:
• HolidayKind (7): Combat / Collection / Racial /
Anniversary / Fishing / Cosmetic /
WorldEvent
• FactionGroup (3): Both / Alliance / Horde
API: WoweeEventLoader::save / load / exists / findById.
Three preset emitters showcase typical event shapes:
• makeStarter — 3 events covering Combat /
Fishing / Anniversary kinds
• makeYearly — 4 yearly holidays with full WTKN
cross-refs (Hallow's End / Brewfest /
Lunar Festival / Winter's Veil)
• makeBonusWeekends — 3 monthly Fri-Sun bonus tiers
(50% / 100% / 200% RAF-style)
CLI added (5 flags, 614 documented total now):
--gen-events / --gen-events-yearly / --gen-events-weekends
--info-wsea / --validate-wsea
Validator catches: eventId=0 + duplicates, empty name,
unknown holidayKind / factionGroup, duration_seconds=0
(event never runs), duration > recurrence period (events
would overlap themselves on next iteration), bonusXpPercent
> 200 (very high — verify intentional).
2026-05-09 17:14:46 -07:00
tools/editor/cli_events_catalog.cpp
feat(pipeline): add WMOU (Wowee Mount catalog) format
Novel open replacement for Blizzard's Mount.dbc +
MountCapability.dbc + MountType.dbc + the mount-related
subsets of Spell.dbc / Item.dbc. The 32nd open format added
to the editor.
Defines all summonable steeds: ground mounts, flying mounts,
swimming mounts, racial mounts (Tauren Plainsrunner for
druids), and class mounts (Warlock dreadsteed, Paladin
charger). Each mount has a summon spell, optional teach
item, riding skill prerequisite, speed bonus, and faction
/ race availability mask.
Cross-references with previously-added formats:
WMOU.entry.summonSpellId -> WSPL.entry.spellId
WMOU.entry.itemIdToLearn -> WIT.entry.itemId
WMOU.entry.requiredSkillId -> WSKL.entry.skillId
(Riding skill ID 762)
WCHC.race.mountSpellId ~= WMOU.entry.summonSpellId
(loose match by spellId)
Format:
• magic "WMOU", version 1, little-endian
• per mount: mountId / name / description / icon /
displayId / summonSpellId / itemIdToLearn /
requiredSkillId+Rank / speedPercent / mountKind /
factionId / categoryId / raceMask
Enums:
• Kind (5): Ground / Flying / Swimming / Hybrid /
Aquatic
• Faction (3): Both / Alliance / Horde
• Category (8): Common / Epic / Racial / Event /
Achievement / Pvp / Quest / ClassMount
API: WoweeMountLoader::save / load / exists / findById.
Three preset emitters showcase typical mount catalogs:
• makeStarter — 3 mounts (ground horse + epic flying
gryphon + aquatic riding turtle)
• makeRacial — 6 racial mounts (4 Alliance: Pinto / Ram /
Frostsaber / Mechanostrider; 2 Horde:
Dire Wolf / Skeletal Horse) with raceMask
gating per WCHC race bit positions
• makeFlying — 4 flying mounts spanning Common (60%) ->
Epic (100%) -> Achievement (280%) -> Pvp
(310%) speed tiers
CLI added (5 flags, 621 documented total now):
--gen-mounts / --gen-mounts-racial / --gen-mounts-flying
--info-wmou / --validate-wmou
Validator catches: mountId=0 + duplicates, empty name,
summonSpellId=0 (mount cannot be cast), unknown enum values,
speedPercent=0 (no speed bonus), flying mount with
requiredSkillRank<150 (player can't fly), Racial category
without raceMask (any race could use — usually a typo).
2026-05-09 17:23:00 -07:00
tools/editor/cli_mounts_catalog.cpp
feat(pipeline): add WBGD (Wowee Battleground Definition) format
Novel open replacement for Blizzard's BattlemasterList.dbc +
PvpDifficulty.dbc + the AzerothCore-style
battleground_template SQL tables. The 33rd open format
added to the editor.
Defines per-BG gameplay rules: player count brackets,
score-to-win, time limit, objective type (annihilation /
capture flag / control nodes / king of hill / resource race
/ carry object), per-team start positions, respawn timer,
and the WTKN currency token awarded on win.
Cross-references with previously-added formats:
WBGD.entry.mapId -> WMS.map.mapId
(where mapType=Battleground)
WBGD.entry.markTokenId -> WTKN.entry.tokenId
(Mark of Honor for that BG)
The classic preset's markTokenId fields (102/103/104)
deliberately match WTKN.makePvp's "Mark of Honor: Warsong
Gulch / Arathi Basin / Alterac Valley" token ids — so the
demo content stack already wires together: WBGD.scoreToWin
reached → grant WTKN mark → which a vendor in WTRN can
charge in via item.extendedCost.
Format:
• magic "WBGD", version 1, little-endian
• per BG: battlegroundId / mapId / name / description /
objectiveKind / min+maxPlayersPerSide /
minLevel..maxLevel / scoreToWin / timeLimitSeconds /
bracketSize / allianceStart vec3 + facing /
hordeStart vec3 + facing / respawnTimeSeconds /
markTokenId
Enums:
• ObjectiveKind (6): Annihilation / CaptureFlag /
ControlNodes / KingOfHill /
ResourceRace / CarryObject
API: WoweeBattlegroundLoader::save / load / exists /
findById.
Three preset emitters showcase typical BG shapes:
• makeStarter — 1 king-of-hill BG (10v10, 3-cap to win)
• makeClassic — 3 classic BGs with authentic player
counts, level brackets, scoring, and
WTKN cross-refs (Warsong Gulch CTF /
Arathi Basin nodes / Alterac Valley
resource race)
• makeArena — 3 arena formats (Nagrand 2v2 / Blade's
Edge 3v3 / Lordaeron 5v5) — annihilation
objective + no respawn + 25 min cap
CLI added (5 flags, 628 documented total now):
--gen-bg / --gen-bg-classic / --gen-bg-arena
--info-wbgd / --validate-wbgd
Validator catches: bgId=0 + duplicates, empty name, unknown
objectiveKind, player count=0, min>max counts/levels,
scoreToWin=0 (no win condition), non-annihilation BG with
respawnTimeSeconds=0 (losing side cannot recover).
2026-05-09 17:30:59 -07:00
tools/editor/cli_battlegrounds_catalog.cpp
feat(pipeline): add WMAL (Wowee Mail Template) format
Novel open replacement for AzerothCore-style
mail_loot_template SQL + the in-game mail subset of the
inventory + currency systems. The 34th open format added
to the editor.
Defines templated mail messages with currency + item
attachments. Triggered by quest reward delivery (overflow
when bag is full), auction house bid wins / sales,
achievement reward attachments, GM correspondence, holiday
event mailings (Brewfest samples, Hallow's End candy), and
returned-mail-on-rejection.
Cross-references with previously-added formats:
WMAL.entry.senderNpcId -> WCRT.entry.creatureId
WMAL.entry.attachments.itemId -> WIT.entry.itemId
Format:
• magic "WMAL", version 1, little-endian
• per template: templateId / senderNpcId / subject / body /
senderName / moneyCopperAttached / categoryId / cod /
returnable / expiryDays / attachments[] (each: itemId +
quantity)
Enums:
• Category (8): QuestReward / Auction / GmCorrespondence /
AchievementReward / EventMailing / Raffle /
ScriptDelivery / ReturnedMail
API: WoweeMailLoader::save / load / exists / findById.
Three preset emitters showcase typical mail templates:
• makeStarter — 3 templates (quest overflow / auction won /
GM gift) covering the 3 most common
categories
• makeHoliday — 4 holiday samples that cross-reference the
WTKN seasonal token IDs (200=Tricky Treats,
201=Brewfest, 202=Coin of Ancestry,
203=Stranger's Gift) so the demo content
stack ships a full holiday onboarding
experience
• makeAuction — 5-template auction-house family (outbid /
won / sold / expired / cancelled) — runtime
fills in actual bid amounts / sold items
at send time
CLI added (5 flags, 635 documented total now):
--gen-mail / --gen-mail-holiday / --gen-mail-auction
--info-wmal / --validate-wmal
Validator catches: templateId=0 + duplicates, empty subject,
neither senderNpcId nor senderName set (no displayable
sender), unknown category, expiryDays=0 (mail expires
immediately), cod=1 with no money attached (free COD),
empty mail in categories where the runtime doesn't fill in
content (skips Auction / GmCorrespondence / ReturnedMail
where empty templates are intentional).
Two bugs caught + fixed during smoke-test on the auction
preset:
• print formatting glued the `0` from senderNpcId after
the senderName when no NPC was set (rendered as
"Postmaster0" instead of "Postmaster") — fixed with an
explicit if/else split
• validator's "no money + no items" warning was too
aggressive for the Auction category, where templates
are intentionally informational and the runtime fills
in the real values — added Auction + ReturnedMail to
the skip list
2026-05-09 17:41:03 -07:00
tools/editor/cli_mail_catalog.cpp
feat(pipeline): add WGEM (Wowee Gem / Enchantment) format
Novel open replacement for Blizzard's ItemEnchantment.dbc +
GemProperties.dbc + SpellItemEnchantment.dbc. The 35th
open format added to the editor.
Defines two related kinds of item enhancement in one
catalog:
• Gems — socketable jewelry pieces with color
(red / blue / yellow / meta) that fit
into gear sockets, granting stats or
triggering passive spells when socketed
• Enchantments — persistent buffs applied to weapon /
armor pieces, either by an enchanter
spell or by an item proc (Mongoose,
Crusader, Berserking)
Cross-references with previously-added formats:
WGEM.gem.itemIdToInsert -> WIT.entry.itemId
WGEM.gem.spellId -> WSPL.entry.spellId
WGEM.enchantment.spellId -> WSPL.entry.spellId
Format:
• magic "WGEM", version 1, little-endian
• gems[]: gemId / itemIdToInsert / name / color /
statType + statValue / requiredItemQuality / spellId
• enchantments[]: enchantId / name / description /
iconPath / enchantSlot / statType + statValue /
spellId / durationSeconds / chargeCount
Enums:
• Color (8): Meta / Red / Yellow / Blue / Purple /
Green / Orange / Prismatic
• EnchantSlot (5): Permanent / Temporary / SocketColor /
Ring / Cloak
API: WoweeGemLoader::save / load / exists +
WoweeGem::findGem / findEnchant.
Three preset emitters showcase common shapes:
• makeStarter — 3 gems (one per primary color) +
2 enchantments (proc + stat)
• makeGemSet — 6-gem full color palette covering
primary + secondary combinations
• makeEnchants — 5 enchant variants spanning slots
(Mongoose / Deadly Poison / stats ring /
cloak / Berserking)
CLI added (5 flags, 642 documented total now):
--gen-gems / --gen-gems-set / --gen-gems-enchants
--info-wgem / --validate-wgem
Validator catches: ids=0 + duplicates, empty name, color /
slot out of range, stat-only entries with statValue=0 (gem
provides nothing), chargeCount > 0 on non-Temporary
enchant slots (charges silently ignored at runtime).
The validator caught a real preset issue on first run —
the proc enchants (Mongoose / Deadly Poison / Berserking)
had spellId=0 and statValue=0, providing nothing. Fixed by
adding placeholder spellIds in the 28000-29000 range, with
a comment noting they resolve to real WSPL proc spells
when the spell catalog is extended.
2026-05-09 18:01:48 -07:00
tools/editor/cli_gems_catalog.cpp
feat(pipeline): add WGLD (Wowee Guild) catalog format
Novel open replacement for AzerothCore-style guild +
guild_member + guild_rank + guild_bank_tab + guild_perk
SQL tables. The 36th open format added to the editor.
Each guild entry holds the complete social-organization
state: header (name, leader, faction, MOTD, info,
creation date, level + experience, bank money, packed
emblem), rank ladder with permissions bitmask + daily
withdraw caps, member roster with rank + join date +
public/officer notes, bank tabs with per-tab and per-rank
deposit / withdraw / view permission masks, and purchased
guild perks referencing WSPL spell IDs.
Cross-references with previously-added formats:
WGLD.entry.factionId ~ WCHC.race.factionId
(guilds are faction-locked)
WGLD.entry.perks.spellId -> WSPL.entry.spellId
Format:
• magic "WGLD", version 1, little-endian
• per guild: header (12 scalar fields + 4 strings) +
ranks[] + members[] + bankTabs[] + perks[]
• per rank: rankIndex / name / permissionsMask /
moneyPerDayCopper
• per member: characterName / rankIndex / joinedDate /
publicNote / officerNote
• per bankTab: tabIndex / name / iconPath /
deposit+withdraw+view permission masks
• per perk: perkId / name / spellId / requiredGuildLevel
Enums:
• Faction (2): Alliance / Horde
• RankPermissionFlags (14): GuildChat / OfficerChat /
Invite / Remove / Promote /
Demote / SetMotd /
EditPublicNote /
EditOfficerNote / ViewBank /
Deposit / Withdraw / Disband /
RepairFromBank
API: WoweeGuildLoader::save / load / exists / findById +
shared addDefaultRanks helper used by both starter and
faction-pair presets.
Three preset emitters:
• makeStarter — 1 small guild, default 5-rank ladder
(GM/Officer/Veteran/Member/Initiate),
3 members borrowing names from WCRT
merchants for cross-format consistency
• makeFull — 1 fleshed-out guild: 6 ranks (with
Recruit added) + 8 members + 4 bank
tabs (officer-only withdraw on tabs
3+4) + 3 perks referencing WSPL
spell IDs (Heroic Strike / Battle
Shout / Thunder Clap as placeholder
perk procs)
• makeFactionPair — 2 parallel guilds, one Alliance + one
Horde, with identical rank structures
CLI added (5 flags, 649 documented total now):
--gen-guilds / --gen-guilds-full / --gen-guilds-pair
--info-wgld / --validate-wgld
Validator catches: guildId=0 + duplicates, empty name /
leaderName, factionId out of range, no ranks (members can't
exist without a rank ladder), member.rankIndex exceeding
the highest defined rank (intra-format cross-reference
resolution), duplicate bank tabIndices, perks with
spellId=0 (perk does nothing).
2026-05-09 18:10:45 -07:00
tools/editor/cli_guilds_catalog.cpp
feat(pipeline): add WPCD (Wowee Player Condition) format
Novel open replacement for Blizzard's PlayerCondition.dbc +
the AzerothCore-style condition_template SQL tables. The
37th open format added to the editor.
Defines reusable boolean conditions that other formats can
reference for gating: "player has quest X completed",
"player level >= N", "player class is mage", "player has
item Y in inventory", "WSEA event Z is active".
Conditions can be grouped and combined with AND/OR
aggregators on a per-group basis: a quest-giver gossip
option that says "show only to level 60 alliance mages
who completed quest 1234" composes 4 conditions sharing
the same groupId with AND aggregation. The runtime walks
each group, applies the group's aggregator, and returns
the boolean result to the caller.
Cross-references with previously-added formats — the
targetId field has a polymorphic interpretation by kind:
WPCD.targetId (kind=QuestCompleted/Active) -> WQT.questId
WPCD.targetId (kind=HasItem) -> WIT.itemId
WPCD.targetId (kind=HasSpell) -> WSPL.spellId
WPCD.targetId (kind=HasAchievement) -> WACH.achievementId
WPCD.targetId (kind=AreaId) -> WMS.areaId
WPCD.targetId (kind=EventActive) -> WSEA.eventId
WPCD.targetId (kind=HasTitle) -> WTIT.titleId
WPCD.targetId (kind=FactionRep) -> WFAC.factionId
WPCD.targetId (kind=Class/Race) -> WCHC class/race id
Future format extensions can reference WPCD.conditionId in
their own gating fields — WTRG triggers gated by player
state, WGSP options visible only when conditions are met,
WMOU summon spells condition-gated by quest progress, etc.
Format:
• magic "WPCD", version 1, little-endian
• per condition: conditionId / groupId (0 = standalone) /
name / description / kind / aggregator / negated /
targetId / minValue / maxValue
Enums:
• Kind (17): AlwaysTrue / AlwaysFalse / QuestCompleted /
QuestActive / HasItem / HasSpell / MinLevel /
MaxLevel / ClassMatch / RaceMatch /
FactionRep / HasAchievement / TeamSize /
GuildLevel / EventActive / AreaId / HasTitle
• Aggregator (2): And / Or
API: WoweeConditionLoader::save / load / exists / findById.
Three preset emitters showcase typical usage:
• makeStarter — 4 standalone conditions covering the most
common kinds (quest-done / has-item /
min-level / class)
• makeGated — 5 conditions in 2 groups demonstrating
AND-aggregation (alliance + mage + lvl 60)
and OR-aggregation (did quest 1 OR quest 100)
• makeEvent — 3 event-gated conditions cross-referencing
WSEA event IDs (Hallow's End / Brewfest /
Winter's Veil)
CLI added (5 flags, 656 documented total now):
--gen-conditions / --gen-conditions-gated / --gen-conditions-event
--info-wpcd / --validate-wpcd
Validator catches: conditionId=0 + duplicates, kind /
aggregator out of range, kinds requiring targetId having
target=0 (skips AlwaysTrue/False, MinLevel/MaxLevel,
TeamSize, GuildLevel which use min/max instead), TeamSize
with min > max.
2026-05-09 18:18:27 -07:00
tools/editor/cli_conditions_catalog.cpp
feat(pipeline): add WPET (Wowee Pet System) catalog
Novel open replacement for AzerothCore-style pet_template +
pet_levelstats SQL + the pet-related subsets of
CreatureFamily.dbc + SpellFamilyName.dbc. The 38th open
format added to the editor.
Defines two related kinds of player-controlled NPCs in
one catalog:
• Pet families — hunter pet families (Wolf / Cat / Bear /
Boar / Raptor / Spider / etc.) with
per-family ability sets, base stat
multipliers, and diet preferences
• Warlock minions — Imp / Voidwalker / Succubus /
Felhunter / Felguard, each with
their own summon spell, creature
template, and ability list
Cross-references with previously-added formats:
WPET.family.familyId -> WCRT.entry.familyId
(matches creature family)
WPET.family.abilities.spellId -> WSPL.entry.spellId
WPET.minion.summonSpellId -> WSPL.entry.spellId
WPET.minion.creatureId -> WCRT.entry.creatureId
(used for stat scaling)
WPET.minion.abilities.spellId -> WSPL.entry.spellId
The starter preset's familyIds (1=Wolf, 2=Cat) match
WCRT::FamilyId enum values, so a hunter taming a wolf via
WCRT links straight through to WPET ability sets.
Format:
• magic "WPET", version 1, little-endian
• families[]: familyId / name / description / icon /
petType / baseAttackSpeed / damageMultiplier /
armorMultiplier / dietMask / abilities[]
• minions[]: minionId / name / summonSpellId / creatureId /
abilities[] (each: spellId / rank / autocastDefault)
Enums:
• PetType (3): Cunning / Ferocity / Tenacity
(WotLK+ talent tree categorization)
• DietFlags: Meat / Fish / Bread / Cheese / Fruit / Fungus
API: WoweePetLoader::save / load / exists +
WoweePet::findFamily / findMinion + dietMaskName helper
that decodes a dietMask into a "meat+fish" string.
Three preset emitters showcase typical pet catalogs:
• makeStarter — 2 hunter families (Wolf + Cat) with full
3-ability sets + 1 warlock Imp
• makeHunter — 8 classic hunter families covering all
3 petType categories with appropriate
diet masks
• makeWarlock — 5 warlock minions each with summon spell
ID and creatureId pointing into WCRT
CLI added (5 flags, 663 documented total now):
--gen-pets / --gen-pets-hunter / --gen-pets-warlock
--info-wpet / --validate-wpet
Validator catches: ids=0 + duplicates, empty name, petType
out of range, baseAttackSpeed<=0 (would divide by zero in
DPS calc), dietMask=0 (pet cannot be fed for happiness),
minion missing summonSpellId / creatureId.
2026-05-09 18:27:02 -07:00
tools/editor/cli_pets_catalog.cpp
feat(pipeline): add WAUC (Wowee Auction House) catalog
Novel open replacement for Blizzard's AuctionHouse.dbc +
the AzerothCore-style auctionhouse / auctionhousebot SQL
tables. The 39th open format added to the editor.
Defines per-house rules for the auction system: faction
access, deposit rate (basis points of buyout price), house
cut on successful sale, three listing duration tiers with
per-tier deposit multipliers, disallowed item-class bitmask,
and the auctioneer NPC.
Cross-references with previously-added formats:
WAUC.entry.auctioneerNpcId -> WCRT.entry.creatureId
(Auctioneer-flagged NPC)
WAUC.entry.disallowedClassMask
bitmask of WIT.Class values
that may not be auctioned at
this house
The faction-pair preset captures the canonical asymmetry:
faction houses charge 5% on a successful sale while neutral
houses charge 15% — the cross-faction tax that makes
neutral AHs profitable for goblins.
Format:
• magic "WAUC", version 1, little-endian
• per house: houseId / auctioneerNpcId / name /
factionAccess / baseDepositRateBp / houseCutRateBp /
maxBidCopper / 3 duration hours + 3 deposit multipliers /
disallowedClassMask
Enums:
• FactionAccess (4): Alliance / Horde / Neutral / Both
• Rates use basis points: 10000 = 100%
API: WoweeAuctionLoader::save / load / exists / findById.
Three preset emitters showcase typical auction setups:
• makeStarter — 1 neutral house with default 12h /
24h / 48h tiers
• makeFactionPair — 3 houses (Stormwind / Orgrimmar /
Booty Bay) with auctioneer NPC IDs
+ canonical faction-vs-neutral cut
rates
• makeRestricted — 1 house disallowing Containers (1) +
Quest items (12) + Keys (13) with
tighter durations + 1000g bid cap
CLI added (5 flags, 670 documented total now):
--gen-auction / --gen-auction-pair / --gen-auction-restricted
--info-wauc / --validate-wauc
Validator catches: houseId=0 + duplicates, empty name,
factionAccess out of range, duration tier=0, durations not
in short<=medium<=long order, houseCutRateBp >= 100% (seller
loses money on a sale), warns on >50% cut.
2026-05-09 18:34:54 -07:00
tools/editor/cli_auction_catalog.cpp
feat(pipeline): add WCHN (Wowee Chat Channel) catalog
Novel open replacement for Blizzard's ChatChannels.dbc +
the AzerothCore-style chat_channel SQL tables. The 40th
open format added to the editor.
Defines the world chat channel system: General, Trade,
LookingForGroup, GuildRecruitment, LocalDefense, plus
per-zone area channels and custom user-created channels.
Each channel has access rules (faction / level), join
behavior (auto vs opt-in), broadcast policy (announce /
moderated), and optional area / map gating that auto-joins
or auto-leaves the channel as the player moves.
Cross-references with previously-added formats:
WCHN.entry.areaIdGate -> WMS.area.areaId
(channel auto-attaches in this area)
WCHN.entry.mapIdGate -> WMS.map.mapId
(channel auto-attaches on this map)
Format:
• magic "WCHN", version 1, little-endian
• per channel: channelId / name / description /
channelType / factionAccess / autoJoin / announce /
moderated / minLevel / areaIdGate / mapIdGate
Enums:
• ChannelType (10): AreaLocal / Zone / Continent / World /
Trade / LookingForGroup / GuildRecruit /
LocalDefense / Custom / Pvp
• FactionAccess (3): Alliance / Horde / Both
API: WoweeChannelLoader::save / load / exists / findById.
Three preset emitters:
• makeStarter — 4 stock channels (General Zone +
Trade + LFG + GuildRecruit) with
default autoJoin policies
• makeCity — 5 city-specific channels (3 Stormwind +
2 Orgrimmar) with mapId / areaId gates
so they auto-attach on entry
• makeModerated — 3 moderated / restricted channels
(LocalDefense level 10+, WorldDefense
moderated, RaidCoordination level 60+)
CLI added (5 flags, 677 documented total now):
--gen-channels / --gen-channels-city / --gen-channels-moderated
--info-wchn / --validate-wchn
Validator catches: channelId=0 + duplicates, empty name,
unknown channelType / factionAccess, world / continent
channel with area or map gate (gate is silently ignored at
runtime — usually a typo), minLevel=0 (no level gate at all).
2026-05-09 18:43:26 -07:00
tools/editor/cli_channels_catalog.cpp
feat(pipeline): add WCMS (Wowee Cinematic) catalog
41st open format — replaces Movie.dbc / CinematicCamera.dbc /
CinematicSequences.dbc plus the AzerothCore cinematic_camera SQL
table. Defines pre-rendered videos, in-engine camera flythroughs,
text crawls, and still images, each with a media path, duration,
skippable flag, and a polymorphic trigger that fires on quest
events / class first-login / zone entry / dungeon clear /
achievements / level milestones.
Cross-references with prior formats — triggerTargetId resolves
by triggerKind to WQT.questId / WMS.areaId / WMS.mapId /
WCHC.classId / WACH.achievementId, and soundtrackId points at
WSND.soundId.
CLI: --gen-cinematics (3-entry starter), --gen-cinematics-intros
(4 class intros), --gen-cinematics-quests (3 quest-bound
cinematics referencing demo questIds 1/100/102), --info-wcms,
--validate-wcms with --json variants. Validator catches
id=0/duplicates, empty name/mediaPath, kind/trigger out of
range, missing target id for non-Manual/Login/LevelUp triggers,
zero-duration entries, and non-skippable pre-rendered videos.
2026-05-09 18:50:43 -07:00
tools/editor/cli_cinematics_catalog.cpp
feat(pipeline): add WGLY (Wowee Glyph) catalog
42nd open format — replaces GlyphProperties.dbc + GlyphSlot.dbc
plus the AzerothCore-style glyph_properties SQL table. Defines
the WotLK glyph system: per-class inscribable glyphs that
modify spell behavior. Each entry pairs a glyph item (the
inscriber's craft output) with the spell aura that applies the
modification, tagged with a Major / Minor / Prime slot type and
a classMask of allowed classes.
Cross-references with prior formats — spellId points at
WSPL.spellId (the aura), itemId points at WIT.itemId (the
inscribed item), and classMask bit positions match the WCHC
classId enum (1=Warrior, 2=Paladin, 3=Hunter, etc).
CLI: --gen-glyphs (3-entry per-role starter), --gen-glyphs-warrior
(6-entry full warrior allotment), --gen-glyphs-universal (4
classMask=All utility glyphs), --info-wgly, --validate-wgly with
--json variants. Validator catches id=0/duplicates, empty name,
spellId=0 (glyph applies no aura), classMask=0 (no class can
inscribe), itemId=0 warning, requiredLevel<25 warning (below
WotLK glyph threshold), and glyphType out-of-range.
2026-05-09 18:55:22 -07:00
tools/editor/cli_glyphs_catalog.cpp
feat(pipeline): add WVHC (Wowee Vehicle) catalog
43rd open format — replaces Vehicle.dbc + VehicleSeat.dbc plus
the AzerothCore-style vehicle_template SQL tables. Defines
drivable vehicles: tanks, demolishers, motorcycles, gryphons,
choppers, siege weapons, multi-passenger transports. Each entry
pairs a creature template (the rendered model) with a fixed
seat layout — driver / passenger / gunner seats with their own
attachment points, control flags (kSeatDriver / kSeatGunner /
kSeatPassenger / kSeatHidesPlayer / kSeatNoEjectByCC), and
per-seat abilities mounted to the action bar.
Cross-references with prior formats — creatureId points at
WCRT.creatureId (the rendered model), flightCapabilityId points
at WMNT.mountId for shared fly-speed tables, and per-seat
controlSpellId / exitSpellId point at WSPL.spellId.
CLI: --gen-vehicles (3-vehicle starter chopper/wind-rider/tank),
--gen-vehicles-siege (3 siege weapons with control spellIds),
--gen-vehicles-flying (3 flying mounts cross-ref WMNT
flightCapabilityIds), --info-wvhc, --validate-wvhc with --json
variants. Validator catches id=0/duplicates, missing creature,
enum out-of-range, empty seat list, flying-vehicle on wrong
movement (would fall through world), driver-flag exclusivity
(0 or >1 drivers), and duplicate seatIndex within a vehicle.
2026-05-09 18:59:49 -07:00
tools/editor/cli_vehicles_catalog.cpp
feat(pipeline): add WHOL (Wowee Holiday) catalog
44th open format — replaces Holidays.dbc + HolidayDescriptions.dbc
+ HolidayNames.dbc plus the AzerothCore-style game_event SQL
tables. Defines time-gated world events: seasonal holidays
(Hallow's End / Brewfest / Winter Veil), weekly call-to-arms BG
bonuses, world-PvP windows (Wintergrasp), one-shot specials, and
recurring daily / weekly resets. Each holiday has a recurrence
rule (Annual / Monthly / WeeklyRecur / OneTime), a calendar
window (startMonth + startDay + durationHours), and optional
cross-refs to a feature creature, an intro quest, and a token /
item reward issued during the window.
Cross-references with prior formats — holidayQuestId points at
WQT.questId, bossCreatureId points at WCRT.creatureId,
itemRewardId points at WIT.itemId, and areaIdGate / mapIdGate
point at WMS.areaId / WMS.mapId.
CLI: --gen-holidays (3 seasonal starter), --gen-holidays-weekly
(3 weekly BG call-to-arms windows), --gen-holidays-special (3
world-PvP / lunar / children events), --info-whol, --validate-whol
with --json variants. Validator catches id=0/duplicates, kind /
recurrence out of range, durationHours=0, invalid month/day for
non-weekly recurrence, and calendar-only events (no quest +
boss + reward) as a warning.
2026-05-09 19:05:33 -07:00
tools/editor/cli_holidays_catalog.cpp
feat(pipeline): add WLIQ (Wowee Liquid Type) catalog
45th open format — replaces LiquidType.dbc plus the
AzerothCore-style terrain liquid descriptor data. Defines
liquid materials used by terrain MCNK liquid layers, WMO
interior pools, and procedurally generated fluid bodies in
custom zones. Each liquid pairs a render material (shader +
texture array + flow vectors + fog color) with gameplay data
(damage spell, raw DPS, ambient + splash audio cross-refs).
Cross-references with prior formats — ambientSoundId and
splashSoundId point at WSND.soundId, damageSpellId points at
WSPL.spellId.
10 liquid kinds (Water / Magma / Slime / OceanSalt / FelFire /
HolyLight / TarOil / AcidBog / FrozenWater / UnderworldGoo)
covering both natural and magical fluids. Per-liquid: viscosity
(0=water, 1=slime), flow direction+speed (radians+units/sec),
fog density+RGB, packed minimap RGBA color.
CLI: --gen-liquids (3-entry classic Water/Lava/Slime starter),
--gen-liquids-magical (4 magical pools incl. fel/holy/cosmic),
--gen-liquids-hazardous (3 high-damage liquids with WSPL DoT
cross-refs), --info-wliq, --validate-wliq with --json variants.
Validator catches id=0/duplicates, missing shader/material,
kind out of range, fog/viscosity outside 0..1, hazardous-kind-
without-damage warning, and Water/OceanSalt-with-damage warning
to flag accidental misconfiguration.
2026-05-09 19:10:03 -07:00
tools/editor/cli_liquids_catalog.cpp
2026-05-09 19:14:55 -07:00
tools/editor/cli_list_formats.cpp
2026-05-09 19:16:26 -07:00
tools/editor/cli_info_magic.cpp
feat(pipeline): add WANI (Wowee Animation) catalog
46th open format — replaces AnimationData.dbc plus the
hard-coded animation-id tables in M2 model loaders. Defines
named animations (Stand, Walk, Run, Cast, Death, MountIdle,
Fly, ...) with fallback chains, behavior tier (default /
mounted / sitting / aerial / swimming), and weapon-flag
bitmasks that select the correct animation variant when the
model wields 1H / 2H / dual / bow / rifle / wand / etc.
Cross-references with prior formats — fallbackId resolves
within the same WANI catalog (graceful degradation when the
requested animation is absent: Run falls back to Walk,
Attack2H falls back to Attack1H).
10 weapon-flag constants + 6 behavior flags (Looped,
BlendableCycle, Interruptable, MovementSync, OneShot,
PreserveAtEnd). 5 behavior tiers. CLI: --gen-animations
(5 essentials), --gen-animations-combat (8 weapon-typed
attacks + parry + channel), --gen-animations-movement (6
locomotion anims with tier transitions). Validator catches
id-uniqueness, fallback-self-loop, looped-without-duration,
mutually-exclusive Looped+OneShot flags, weaponFlags=0
warning, and unresolved fallback warnings.
Also extends --list-formats and --info-magic with WANI.
2026-05-09 19:19:13 -07:00
tools/editor/cli_animations_catalog.cpp
feat(pipeline): add WSVK (Wowee Spell Visual Kit) catalog
47th open format — replaces SpellVisualKit.dbc +
SpellVisualEffectName.dbc plus the AzerothCore-style spell
visual SQL data. Defines per-spell visual presentations:
cast-bar effect model, projectile model + travel speed +
arc gravity, impact effect model, hand effect on the caster,
and the animations + sounds that fire at cast / channel /
impact time.
Cross-references with prior formats — castAnimId / impactAnimId
/ precastAnimId point at WANI.animationId, castSoundId /
impactSoundId point at WSND.soundId. Spell catalogs (WSPL)
will reference visualKitId here to bind "what mechanically
happens" to "what plays visually."
CLI: --gen-svk (3-kit Frostbolt/Fireball/HealingTouch starter
showing projectile + AoE + heal patterns), --gen-svk-combat
(5 melee/ranged with WANI animation refs), --gen-svk-utility
(4 portal/hearth/mount/resurrect with no projectile),
--info-wsvk, --validate-wsvk with --json variants. Validator
catches id=0/duplicates, missing name, negative speeds/radii,
projectile-model + speed coherence (model without speed =
never travels; speed without model = invisible), and a
no-effect catch-all (no models + no anims + no sounds).
2026-05-09 19:23:36 -07:00
tools/editor/cli_spell_visuals_catalog.cpp
2026-05-09 19:27:48 -07:00
tools/editor/cli_format_table.cpp
tools/editor/cli_summary_dir.cpp
2026-05-09 19:29:18 -07:00
tools/editor/cli_rename_magic.cpp
feat(pipeline): add WWUI (Wowee World-State UI) catalog
48th open format — replaces WorldStateUI.dbc plus the
AzerothCore-style world_state SQL data. Defines on-screen UI
elements that surface server-side world-state variables: BG
scoreboards (flag captures, base controls), Wintergrasp tank
counters, Eye of the Storm flag-carrier indicator, dungeon
boss progress, world-event collection trackers.
Each entry binds a server-side variableIndex to a UI panel
kind (counter / timer / flag-icon / progress-bar / two-sided
score / custom) gated by mapId+areaId, with optional
alwaysVisible and hideWhenZero flags and a chosen panel
position (top / bottom / top-left / top-right / center).
Cross-references with prior formats — mapId points at
WMS.mapId and areaId points at WMS.areaId.
CLI: --gen-wsui (3-entry BG scoreboard starter for WSG/AB/
EotS), --gen-wsui-wintergrasp (4-entry full Wintergrasp UI),
--gen-wsui-dungeon (3-entry boss/keys/treasure hunt UI),
--info-wwui, --validate-wwui with --json variants. Validator
catches id=0/duplicates, kind/position out of range,
variableIndex=0 warning, alwaysVisible+hideWhenZero conflict
warning, and (mapId, variableIndex) collision warning when
two entries would read the same server slot on the same map.
Also extends --list-formats and --info-magic with WWUI.
2026-05-09 19:32:15 -07:00
tools/editor/cli_world_state_ui_catalog.cpp
feat(pipeline): add WPCN (Wowee Player Condition) catalog
49th open format — replaces PlayerCondition.dbc plus the
AzerothCore-style condition resolver. Defines reusable
boolean checks that other catalogs reference by conditionId
to gate gossip options, vendor items, quest availability,
achievement criteria, spell trainer offerings.
16 condition kinds (Always, Race, Class, Level, Zone, Map,
Reputation, AchievementWon, QuestComplete, QuestActive,
SpellKnown, ItemEquipped, Faction, InCombat, Mounted,
Resting), 8 comparison ops (==, !=, >, >=, <, <=, in-set,
not-in-set), and 4 chain ops (none, and, or, not) — chain
multiple conditions via chainNextId to express arbitrary
boolean trees.
Cross-references with prior formats — targetIdA is
polymorphic by conditionKind: resolves to WCHC raceId/classId,
WMS areaId/mapId, WFAC factionId, WACH achievementId, WQT
questId, WSPL spellId, or WIT itemId. chainNextId resolves
within the same WPCN catalog.
CLI: --gen-pcn (3 single-check starters), --gen-pcn-quest-gates
(4 cross-format quest gates with real WQT/WFAC/WACH/WMS IDs),
--gen-pcn-composite (3 leaves + 3 chained roots showing AND/
OR/NOT). Validator catches id=0/duplicates, kind/op out of
range, chain self-loop (infinite recursion), chainOp set
without chainNextId (dangling chain), chainNextId set without
chainOp (dead pointer warning), and unresolved chainNextId
references.
2026-05-09 19:36:56 -07:00
tools/editor/cli_player_conditions_catalog.cpp
feat(pipeline): add WTSK (Wowee Trade Skill / Recipe) catalog
New open format — replaces SkillLineAbility.dbc plus the
recipe portions of SkillLine.dbc plus the AzerothCore
trade_skill SQL tables. Closes the crafting gap left by WSKL
(which carries skill lines but not the recipes that bind to
them).
14 professions (Blacksmithing, Tailoring, Engineering,
Alchemy, Enchanting, Leatherworking, Jewelcrafting,
Inscription, Mining, Skinning, Herbalism, Cooking, FirstAid,
Fishing). Each recipe has 4 skill-up bracket thresholds
(orange / yellow / green / gray) for skill-up probability,
a craft spell cross-ref (WSPL), produced item cross-ref
(WIT) with min/max quantity range, an optional tool item,
and up to 4 reagent slots (itemId + count).
Cross-references with prior formats — craftSpellId points at
WSPL.spellId, producedItemId / toolItemId / reagent[].itemId
all point at WIT.itemId, and skillId points at WSKL.skillId.
CLI: --gen-tsk (3-recipe entry-tier starter), --gen-tsk-
blacksmithing (5-recipe progression rough sharpening through
truesilver champion), --gen-tsk-alchemy (5-recipe progression
minor healing through flask of titans), --info-wtsk,
--validate-wtsk with --json variants. Validator catches
id=0/duplicates, profession out of range, missing craft spell
or produced item, monotonic-bracket check (must be orange <=
yellow <= green <= gray), reagent itemId-without-count
mismatch, and free-recipe warning (no reagents and no tool).
Format graph now exposes 49 distinct binary formats. CLI
flag count: 747 → 752.
2026-05-09 19:41:49 -07:00
tools/editor/cli_trade_skills_catalog.cpp
feat(pipeline): add WCEQ (Wowee Creature Equipment) — 50th open format
Replaces the AzerothCore-style creature_equip_template SQL
tables plus the visible-weapon / shield / ranged-slot data
that was traditionally embedded in creature templates. Closes
a long-standing gap in the creature subsystem: until now WCRT
defined a creature's stats, WSPN placed it in the world, and
WLOT defined what it drops — but nothing defined what items
it visibly equips.
Each entry binds a creatureId to up to three equipped items
(main hand / off hand / ranged) plus the visual kit that
fires when the main-hand weapon is brandished. equipFlags
bits encode hidden / dual-wield / shield-offhand /
thrown-ranged / 2H polearm to drive the renderer's
attachment-point selection.
Cross-references with prior formats — creatureId points at
WCRT.creatureId, mainHandItemId / offHandItemId / rangedItemId
all point at WIT.itemId, and mainHandVisualId points at
WSVK.visualKitId so brandished weapons can play their
signature glow / aura.
CLI: --gen-ceq (3 generic guard/hunter/rogue starters),
--gen-ceq-bosses (4 iconic loadouts incl. Frostmourne and
Illidan's warglaives, with WSVK visual cross-refs),
--gen-ceq-ranged (3 ranged-only rifle/bow/crossbow loadouts),
--info-wceq, --validate-wceq with --json variants. Validator
catches id=0/duplicates, missing creatureId, all-empty-slots
warning, kFlagDualWield without both hand items, kFlagShield
without offhand item, mutually-exclusive dual-wield + shield,
and 2H polearm with offhand item filled.
Format graph milestone: 50 distinct binary formats. CLI flag
count: 754 → 760.
2026-05-09 19:48:13 -07:00
tools/editor/cli_creature_equipment_catalog.cpp
feat(pipeline): add WSET (Wowee Item Set / Tier Bonus) catalog
51st open format — replaces ItemSet.dbc + ItemSetSpell.dbc
plus the AzerothCore-style item_set_spell SQL data. Closes
the tier-bonus gap left by WIT (which describes individual
items but not the set bonuses they grant when worn together).
Each entry binds up to 8 piece item IDs to up to 4 bonus
thresholds — at N pieces worn, the matching bonus spell
activates as an aura. Standard 2/4/6/8-piece tier set pattern
is the canonical case; 5-piece PvP sets with 2/4 bonuses are
also supported.
Cross-references with prior formats — itemIds[] point at
WIT.itemId, bonusSpellIds[] point at WSPL.spellId, and
requiredSkillId points at WSKL.skillId. requiredClassMask
is a 32-bit field (uint32_t) so bit positions match WCHC's
classId enum directly — Druid (bit 11 = 0x800) and Mage
(bit 8 = 0x100) wouldn't fit in a uint8_t.
CLI: --gen-itset (2 raid sets — Battlegear of Wrath +
Stormrage Raiment, real WoW item/spell IDs), --gen-itset-tier
(4 tier-1 progression sets covering plate / cloth / leather /
holy plate), --gen-itset-pvp (3 PvP gladiator 5-piece sets
with honor-rank skill thresholds), --info-wset, --validate-wset
with --json variants. Validator catches id+name+pieceCount
required, pieceCount/bonusCount within array bounds, piece-
slot drift (0 IDs within count or non-0 IDs past count),
bonus thresholds strictly ascending, no bonus threshold
exceeding pieceCount (would never trigger), and spellId=0
in any populated bonus slot.
Format graph: 50 → 51 binary formats. CLI flag count: 762
→ 767.
2026-05-09 19:54:36 -07:00
tools/editor/cli_item_sets_catalog.cpp
2026-05-09 19:58:01 -07:00
tools/editor/cli_touch_tree.cpp
feat(pipeline): add WGTP (Wowee Game Tips) catalog
52nd open format — replaces GameTips.dbc plus loading-screen
tutorial hint tables. Defines the rotating tips shown during
world loads, the contextual tutorial hints that fire on first
gameplay events (first quest accept, first death, first
dungeon entry), and the persistent tooltip-help strings that
explain UI elements.
4 display kinds (LoadingScreen / Tutorial / TooltipHelp /
Hint), 7 audience-filter bits (Alliance / Horde / NewPlayer /
Hardcore / PvE / PvP / Roleplay) for pool selection, level
range gating (minLevel + maxLevel), displayWeight for
relative frequency within the pool, optional WPCN condition
cross-ref for further gating, and class-mask restriction
matching WCHC bit positions.
Cross-references with prior formats — conditionId points at
WPCN.conditionId for advanced gating; requiredClassMask uses
the same WCHC.classId bit layout as WGLY/WSET.
CLI: --gen-tips (3 generic loading-screen tips), --gen-tips-
new-player (5 onboarding Tutorial-kind tips for level 1-15,
weighted higher for new players), --gen-tips-advanced (4
endgame tips for level 70+ covering raid mechanics / arena /
daily professions / dungeon finder), --info-wgtp,
--validate-wgtp with --json variants. Validator catches
id/name/text required, kind 0..3, audienceFilter=0 (tip
never shown), invalid level range, displayWeight=0 (in pool
but never picked) warning, and brevity check (>280 chars)
on Tutorial / Hint kinds that need to fit on screen.
Format graph: 51 → 52 binary formats. CLI flag count: 770
→ 775.
2026-05-09 20:00:56 -07:00
tools/editor/cli_game_tips_catalog.cpp
feat(pipeline): add WCMP (Wowee Companion Pet) catalog
53rd open format — replaces the companion-pet portions of
CreatureFamily.dbc plus the AzerothCore-style critter / vanity-
pet SQL data. Distinct from WPET (which covers hunter combat
pets and warlock minions); WCMP covers non-combat "vanity" pets
that follow the player around for cosmetic reasons —
Mechanical Squirrel, Mini Diablo, Panda Cub, dragon hatchlings.
8 companion kinds (Critter, Mechanical, DragonHatchling,
Demonic, Spectral, Elemental, Plush, UndeadCritter), 4
rarity tiers (Common / Uncommon / Rare / Epic), and 3
faction restrictions (AnyFaction / AllianceOnly / HordeOnly).
Cross-references with prior formats — creatureId points at
WCRT.creatureId (the rendered model), learnSpellId at
WSPL.spellId (the spell that summons the pet), itemId at
WIT.itemId (the item that teaches the spell), and
idleSoundId at WSND.soundId (idle ambient noise).
CLI: --gen-cmp (3 common vendor pets), --gen-cmp-rare (4
promo / collector pets at Epic rarity — Mini Diablo,
Panda Cub, Zergling, Murky), --gen-cmp-faction (3 faction-
restricted Alliance Lion Cub / Horde Mottled Boar /
neutral Argent Squire), --info-wcmp, --validate-wcmp with
--json variants. Validator catches id+name+creatureId+
learnSpellId required, kind 0..7 / rarity 0..3 / faction
0..2 range, and Epic-rarity-no-itemId warning (most promo
pets need a redemption-code item).
Format graph: 52 → 53 binary formats. CLI flag count: 777
→ 782.
2026-05-09 20:05:06 -07:00
tools/editor/cli_companions_catalog.cpp
feat(pipeline): add WSMC (Wowee Spell Mechanic) catalog
54th open format — replaces SpellMechanic.dbc plus the
AzerothCore-style diminishing-returns (DR) tables. Defines
crowd-control mechanic categories that spells reference:
Stun, Silence, Polymorph, Sleep, Fear, Root, Snare, Slow,
Knockback, etc. Each mechanic carries gameplay metadata
(breaks-on-damage, can-be-dispelled, default duration, max
stacks) plus DR category and dispel type.
8 DR categories (DRNone / DRStun / DRDisorient / DRSilence
/ DRRoot / DRPolymorph / DRControlled / DRMisc) — the
runtime uses these to gate repeated CC on the same target.
7 dispel types (DispelNone / Magic / Curse / Disease /
Poison / Enrage / Stealth) bind which dispel spells can
remove the mechanic. conflictsMask is a bitmask of OTHER
mechanic IDs — only one mechanic from a conflict-group can
apply to a target simultaneously.
Cross-references with prior formats — mechanicId is
referenced by WSPL.spellId entries that apply this CC; this
catalog is referenced from spell tags rather than referencing
out.
CLI: --gen-smc (3 baseline Stun/Silence/Snare), --gen-smc-
hard (5 hard-CC: Stun/Polymorph/Sleep/Fear/Knockback with
conflictsMask wiring), --gen-smc-roots (4 movement-impair:
Root/Snare/Slow stacking 5x/GroundPin breaks-on-damage),
--info-wsmc, --validate-wsmc with --json variants. Validator
catches id+name required, DR category 0..7, dispel type
0..6, maxStacks=0 (mechanic could never apply),
canBeDispelled+DispelNone inconsistency, and self-conflict
bit set in conflictsMask (mechanic blocking itself).
Format graph: 53 → 54 binary formats. CLI flag count: 784
→ 789.
2026-05-09 20:09:44 -07:00
tools/editor/cli_spell_mechanics_catalog.cpp
feat(pipeline): add WKBD (Wowee Keybinding) catalog
55th open format — replaces KeyBinding.dbc plus the
AzerothCore-style default-keybind SQL data. Defines the key
bindings shipped with the game: movement (W/A/S/D),
targeting (Tab), action bars (1-9, 0, -, =), UI panels
(C/I/B/P/N/L), chat (Enter), camera (Insert/Delete).
Each binding has an internal action name (SCREAMING_SNAKE
convention — "MOVE_FORWARD"), a primary key, an optional
alternate key, a category for the keybindings UI grouping,
and a flag indicating whether the user can override it.
Hardcoded engine bindings (alt-F4, ESC) set
isUserOverridable=0 so the rebind dialog can't accidentally
break them.
9 categories (Movement / Combat / Targeting / Camera /
UIPanels / Chat / Macro / Bar / Other) for the rebind
dialog grouping.
CLI: --gen-kbd (3 essential WASD/Tab/C bindings), --gen-kbd-
movement (8 movement: WASD + arrow alternates + jump +
autorun), --gen-kbd-ui (10 UI panel bindings covering all
the standard interface windows), --info-wkbd, --validate-wkbd
with --json variants. Validator catches id+actionName+
defaultKey required, category 0..8, alternateKey ==
defaultKey (no point in alt), action-name lowercase warning
(should be SCREAMING_SNAKE), duplicate primary keys (would
silently shadow earlier binding), and duplicate action names.
Format graph: 54 → 55 binary formats. CLI flag count: 791
→ 796.
2026-05-09 20:13:37 -07:00
tools/editor/cli_keybindings_catalog.cpp
2026-05-09 20:16:27 -07:00
tools/editor/cli_tree_summary_md.cpp
feat(pipeline): add WSCH (Wowee Spell School) catalog
56th open format — replaces SpellSchools.dbc plus the
Resistances.dbc resistance-cap tables. Defines damage
schools spells use: Physical, Holy, Fire, Nature, Frost,
Shadow, Arcane, plus combined / hybrid schools that count
as multiple types simultaneously (Spellfire, Spellshadow,
Spellfrost — relevant for resistance-bypass mechanics).
7 canonical schools with single-bit IDs (1, 2, 4, 8, 16,
32, 64) so combinedSchoolMask values line up directly with
the spell engine's school-bit enum. Hybrid schools use
high-bit IDs (0x80000001+) and their combinedSchoolMask
references the canonical bits they qualify as. Each school
carries visual identity (color tint, icon), gameplay rules
(canBeImmune / canBeAbsorbed / canBeReflected / canCrit),
resistance cap at max level, and cast / impact sound IDs.
Cross-references with prior formats — castSoundId and
impactSoundId point at WSND.soundId; combinedSchoolMask
is a bitmask of OTHER WSCH.schoolId values within the same
catalog.
CLI: --gen-sch (3 base — Physical / Fire / Holy showing
non-resistable Holy + non-reflectable Physical), --gen-sch-
magical (6 canonical magical schools with proper colors
+ 365 max-level resistance caps), --gen-sch-combined (3
hybrids — Spellfire / Spellshadow / Spellfrost with
multi-bit combinedSchoolMask), --info-wsch, --validate-wsch
with --json variants. Validator catches id+name required,
reflected-without-absorbed warning (reflected damage
should be absorbable), self-referential combinedSchoolMask
(school qualifying as itself), and combined-mask references
to bits not defined in the same catalog (resolved at runtime
across catalogs).
Format graph: 55 → 56 binary formats. CLI flag count: 798
→ 804.
2026-05-09 20:19:34 -07:00
tools/editor/cli_spell_schools_catalog.cpp
feat(pipeline): add WLFG (Wowee Looking-for-Group) catalog
57th open format — replaces LFGDungeons.dbc plus the
AzerothCore-style dungeon-finder reward tables. Defines the
dungeons / raids that the Dungeon Finder / Raid Browser
presents to players, with their level brackets, group-size
requirements, role requirements (tank / heal / DPS), and
queue-completion rewards.
4 difficulty levels (Normal / Heroic / Mythic / Hardmode —
the latter for Ulduar-style toggleable boss difficulty),
4 expansion gates (Classic / TBC / WotLK / TurtleWoW), and
3 role-requirement bits (Tank / Heal / DPS — typically all
three for queue-formed groups).
Cross-references with prior formats — mapId points at
WMS.mapId (the instance map), queueRewardItemId points at
WIT.itemId (the random reward bag), firstClearAchievement
points at WACH.achievementId.
CLI: --gen-lfg (3 classic 5-mans Ragefire/Wailing/Deadmines
with real WoW mapIds + level brackets), --gen-lfg-heroic
(5 WotLK 80-level heroic 5-mans with emblem rewards +
real first-clear achievement IDs from Halls of Lightning
through Old Kingdom), --gen-lfg-raid (3 raid entries —
Naxx-25, Ulduar-25 Hardmode, ToC-25 Mythic), --info-wlfg,
--validate-wlfg with --json variants. Validator catches
id+name+mapId required, difficulty 0..3, expansion 0..3,
minLevel<=maxLevel, recommended-level outside range
warning, unusual groupSize warning (5/10/25/40 are
canonical), and zero role mask (queue can't form a
balanced group).
Format graph: 56 → 57 binary formats. CLI flag count: 804
→ 811.
2026-05-09 20:24:21 -07:00
tools/editor/cli_lfg_catalog.cpp
2026-05-09 20:27:16 -07:00
tools/editor/cli_catalog_grep.cpp
feat(editor): add --diff-headers cross-file header comparison
Compares two .w* files at the standard catalog header level:
4-byte magic, version, catalog name, entry count, total file
bytes. Useful for confirming a JSON round-trip didn't drift,
checking whether two preset emissions produced equivalent
output, or quickly diagnosing when a content snapshot has
silently shifted (entry count up means content was added,
file bytes up but everything else same means entry payloads
got fatter).
Output uses = / ≠ markers per field so visual scanning is
fast. Three diagnostic summary cases: identical headers (and
same bytes — possibly byte-equal, run cmp(1) to confirm),
same shape but bytes differ (entry payloads diverged), and
different formats entirely (files are unrelated).
Returns exit 1 if any field differs, so the flag composes
into shell pipelines (`if diff-headers a.wcms b.wcms; then ...`).
World/asset formats stop after magic since their layouts
diverge from the standard catalog header.
Supports --json variant for tooling integration.
2026-05-09 21:27:26 -07:00
tools/editor/cli_diff_headers.cpp
2026-05-09 21:45:54 -07:00
tools/editor/cli_audit_tree.cpp
2026-05-09 21:57:26 -07:00
tools/editor/cli_magic_fix.cpp
2026-05-09 22:19:09 -07:00
tools/editor/cli_bulk_validate.cpp
2026-05-09 22:35:12 -07:00
tools/editor/cli_bulk_json.cpp
2026-05-09 22:46:52 -07:00
tools/editor/cli_diff_tree.cpp
feat(pipeline): add WMAC (Wowee Macro / Slash Command) catalog
58th open format — novel format with no direct DBC equivalent.
WoW historically stored player macros client-side in the user
profile and system slash commands as hardcoded engine handlers;
WMAC unifies both into a single structured catalog so default
macros, system slash commands, and shipped player presets can
be authored, validated, and shipped as content alongside the
rest of the open-format graph.
5 macro kinds (SystemSlash for engine /sit /dance handlers,
DefaultMacro for shipped presets, PlayerTemplate for user
templates, GuildMacro for guild-shared, SharedMacro for
account-wide). Multi-line macro bodies are stored verbatim
with literal '\n' separators — the client parses /cast /
/target / /run lines at runtime.
Cross-references with prior formats — requiredClassMask uses
WCHC.classId bit positions (Warrior=0x02, etc, same as WGLY/
WSET/WGTP).
CLI: --gen-mac (3 system slash — /sit, /dance, /target with
[@mouseover] modifier), --gen-mac-combat (4 warrior combat
templates — heroic strike spam, charge/intercept stance dance,
intercept stance switch, victory rush+bloodthirst fallback —
each with default key bindings), --gen-mac-utility (3 universal
utility — /follow target, mass /inv with %targetN tokens,
/releasecorpse via RepopMe()), --info-wmac, --validate-wmac
with --json variants. Validator catches id+name+body required,
kind 0..4, body within maxLength cap, body starting with '/'
or '#' (slash command or showtooltip annotation), and
SystemSlash + classMask warning (slash commands are class-
agnostic — restricting them to a class makes no sense).
Format graph: 57 → 58 binary formats. CLI flag count: 814
→ 819.
2026-05-09 20:30:17 -07:00
tools/editor/cli_macros_catalog.cpp
feat(pipeline): add WCHF (Wowee Character Customization Feature) catalog
59th open format — replaces CharHairGeosets.dbc +
CharFacialHairStyles.dbc plus the variation portions of
CharSections.dbc. Defines per-(race, sex) customization
options the character creation screen exposes: skin colors,
face variations, hair styles, hair colors, facial hair
(beards / mustaches), and race-specific markings (Tauren
horns, Draenei tendrils, Blood Elf ears).
9 feature kinds (SkinColor / FaceVariation / HairStyle /
HairColor / FacialHair / FacialColor / EarStyle / Horns /
Markings) cover the full canonical customization surface.
Each entry is one selectable carousel choice for one
(race, sex, kind) tuple — variationIndex disambiguates.
expansionGate enum gates Blood Elf / Draenei (TBC) and DK
features (WotLK) behind the right expansion unlock.
Cross-references with prior formats — raceId points at
WCHC.race.raceId. requiresExpansion bit positions match
the WLFG expansion enum (Classic=0, TBC=1, WotLK=2,
Turtle=3) for consistency.
CLI: --gen-chf (5 Human Male starter — skin / face / 2
hair styles / facial hair), --gen-chf-bloodelf (8 Blood
Elf Female hair styles, requiresExpansion=TBC — the
iconic TBC race feature), --gen-chf-tauren (6 Tauren Male
features using race-specific Horns kind + 3 facial hair
variations), --info-wchf, --validate-wchf with --json
variants. Validator catches id+name+raceId+texturePath
required, kind 0..8 / sex 0..1 / expansion 0..3, and the
critical (race, sex, kind, variation) tuple-uniqueness
check — duplicates would shadow each other in the create-
character carousel.
Format graph: 58 → 59 binary formats. CLI flag count: 819
→ 826.
2026-05-09 20:35:21 -07:00
tools/editor/cli_char_features_catalog.cpp
feat(pipeline): add WPVP (Wowee PvP Honor / Rank) — 60th open format
60th open format milestone — replaces the AzerothCore-style
PvP rank tables plus the vanilla honor-rank reward chains.
Defines PvP progression rungs: vanilla honor ranks (Private
through Grand Marshal / High Warlord), arena rating brackets
(Combatant / Challenger / Rival / Duelist / Gladiator), and
battleground rated tiers.
5 rank kinds (VanillaHonor / ArenaRating / BattlegroundRated /
WorldPvP / ConquestPoint) cover the canonical PvP progression
surface. Each entry carries an alliance-specific name and a
horde-specific name (Grand Marshal = High Warlord; arena tiers
share the same name on both factions), an honor or rating
threshold, and optional gear cross-refs (chest, gloves,
shoulders) into WIT.
Cross-references with prior formats — titleId points at
WTTL.titleId (the unlock title), chest/gloves/shoulders point
at WIT.itemId for the matching PvP set, bracketBgId points at
WBGD.bgId for battleground-bracket gating.
CLI: --gen-pvp (3 vanilla entry tiers Rank2-4 with alliance
vs horde alternate names), --gen-pvp-alliance (9 vanilla
ranks 6-14 with WTTL+WIT cross-refs and ramping honor
thresholds 50k → 260k), --gen-pvp-arena (5 arena rating
brackets 1500/1750/2000/2200/2400 with 10/20/40/80/160 emblem
rewards), --info-wpvp, --validate-wpvp with --json variants.
Validator catches id+name required, kind 0..4, level range
valid, faction-name pairing (one set without the other is a
typo), threshold monotonicity within a rankKind, arena rating
below 1500 floor, and VanillaHonor with minHonor=0 baseline
warning.
Format graph: 59 → 60 binary formats (milestone). CLI flag
count: 826 → 833.
2026-05-09 20:41:09 -07:00
tools/editor/cli_pvp_catalog.cpp
feat(pipeline): add WBNK (Wowee Bag / Bank Slot) catalog
61st open format — replaces ItemBag.dbc plus the bank-storage
and special-purpose container tables. Defines every slot the
player has access to: equipped bags, bank bags, keyring, soul
shard bag, quiver, reagent bag, hunter pet stable.
8 bag kinds (Inventory / Bank / Keyring / Quiver / SoulShard /
Stable / Reagent / Wallet) cover the canonical container
surface. Each entry has a fixed capacity (or 0 = variable,
size set by equipped bag), a display order in the inventory
UI, an unlock state with optional gold cost (bank bags ramp
through 10s / 1g / 10g / 25g / 50g / 100g matching canonical
WoW prices), and an accepts-bag-subclass mask gating which
container kinds may be equipped (generic / herb / enchanting
/ engineer / gem / mining / leather / inscription / quiver /
ammo pouch).
Cross-references with prior formats — fixedBagItemId points
at WIT.itemId for the bag item that always occupies a fixed
slot (0 = player-equipable variable slot).
CLI: --gen-bnk (5 inventory slots — 16-slot fixed main
backpack + 4 player-equippable bag slots accepting generic
containers + herb + enchanting bags), --gen-bnk-bank (8 bank
bag slots with the canonical WoW unlock cost ramp),
--gen-bnk-special (4 special-purpose: 32-slot Keyring fixed,
warlock SoulShardBag, hunter ArrowQuiver, hunter
HuntersStable for 5 pets), --info-wbnk, --validate-wbnk with
--json variants. Validator catches id+name required, kind
0..7, locked-with-zero-cost (slot can never be unlocked),
fixed-slot-with-non-zero-mask (equippable bag would be
ignored), variable slot with empty mask (no bag can fit),
and ambiguous (bagKind, displayOrder) tuples (UI sort would
flicker).
Format graph: 60 → 61 binary formats. CLI flag count: 833
→ 840.
2026-05-09 20:46:06 -07:00
tools/editor/cli_bags_catalog.cpp
feat(pipeline): add WRUN (Wowee DK Rune Cost) catalog
62nd open format — replaces RuneCost.dbc plus the DK-specific
portions of ChrPowerType. Defines per-spell rune costs (Blood
/ Frost / Unholy) and runic-power generation / consumption
for the Death Knight class.
4 spell tree branches (BloodTree / FrostTree / UnholyTree /
Generic) classify which spec uses each rune cost. Each entry
binds a spell to its rune cost (how many of each rune kind
the spell consumes), an optional anyDeathConvertCost (extra
Death-rune-acceptable cost for procced abilities), and a
runicPowerCost (negative = generator, positive = spender).
Cross-references with prior formats — spellId points at
WSPL.spellId (the spell that uses this rune cost).
CLI: --gen-rune (3 baseline DK abilities — Death Strike
1F+1U + 20RP gen, Frost Strike pure 40 RP spender, Heart
Strike 1B + 10RP gen), --gen-rune-blood (4 blood-tree DK
abilities — Heart Strike, Death and Decay AoE, Vampiric
Blood tank cooldown, Rune Tap self-heal), --gen-rune-frost
(4 frost-tree — Frost Strike, Howling Blast AoE, Obliterate
finisher, Icy Touch ranged opener applying Frost Fever),
--info-wrun, --validate-wrun with --json variants. Validator
catches id+name+spellId required, branch 0..3, no rune cost
> 2 (DK only has 2 of each rune type so a higher cost can
never be paid), runicPowerCost > 100 (DK RP cap), no-cost
warning (spell consumes nothing — verify it's a
passive/stance/form), and high-RP-generator warning (> 25
RP per cast is unusual).
Format graph: 61 → 62 binary formats. CLI flag count: 840
→ 847.
2026-05-09 20:52:19 -07:00
tools/editor/cli_runes_catalog.cpp
feat(pipeline): add WLDS (Wowee Loading Screen) catalog
63rd open format — replaces LoadingScreens.dbc plus the
per-zone background-image tables. Defines the loading-screen
images shown when the client crosses into a new map /
instance, with optional level-bracket gating and expansion
gating (TBC art only shown if expansion installed).
When multiple screens match the player's current map + level
+ expansion, displayWeight selects randomly between them — a
zone with 3 weighted variants gets a different image roughly
proportional to weight.
4 expansion gates (Classic / TBC / WotLK / TurtleWoW),
isAnimated flag for screens with subtle animation,
isWideAspect flag for 16:9 raid intro art (vs 4:3 standard).
Cross-references with prior formats — mapId points at
WMS.map.mapId (which map triggers this loading screen);
mapId=0 is the catch-all sentinel for screens shown when
no map-specific screen matches.
CLI: --gen-lds (3 base screens — Elwynn level 1-30, Orgrimmar,
GenericFallback level 31-80 catch-all), --gen-lds-instances
(5 WotLK dungeon screens with mapId+expansion cross-refs:
Halls of Lightning/Stone, Utgarde Pinnacle, Violet Hold,
Old Kingdom), --gen-lds-raid (3 raid intro screens —
Naxxramas/Ulduar/ToC at isWideAspect=1 with weight=3),
--info-wlds, --validate-wlds with --json variants. Validator
catches id+name+texture required, expansion 0..3, level range
valid, weight=0 (in pool but never picked), and the practical
catch-all overlap warning when multiple mapId=0 screens share
overlapping level brackets (random pick becomes
non-deterministic).
Format graph: 62 → 63 binary formats. CLI flag count: 847
→ 854.
2026-05-09 20:59:25 -07:00
tools/editor/cli_loading_screens_catalog.cpp
feat(pipeline): add WSUF (Wowee Item Random Suffix) catalog
64th open format — replaces ItemRandomProperties.dbc +
ItemRandomSuffix.dbc plus the AzerothCore-style suffix-roll
tables. Defines random "of the X" suffixes that roll on
green and blue items at world drop ("Sturdy Cloth Cap of
the Bear" = base item + STR + STA suffix).
5 suffix categories (Generic / Elemental / Defensive /
PvPSuffix / Crafted), per-suffix item-quality bracket gating
(only blue+ items can roll PvPSuffix), restricted-slot mask
that limits which equipment slots a suffix can apply to (15
slot bits matching WCEQ slot enum), and up to 5 stat bonus
slots per suffix matching WoW canonical max.
statValuePoints isn't an absolute number — it's a scaling
base that the runtime multiplies by an item-level
coefficient to compute the final per-item bonus, so "of the
Bear" gives proportionally more strength on a level-60 item
than on a level-20 item.
Cross-references with prior formats — statKind values match
WIT.statType enum (STR=4, AGI=3, INT=5, SPI=6, STA=7) so
item generators roll consistent stats with base items.
CLI: --gen-suf (3 generic stat triads — Bear STR+STA, Eagle
INT+SPI, Tiger STR+AGI), --gen-suf-magical (4 elemental
spell-power suffixes restricted to caster-eligible slots),
--gen-suf-pvp (3 PvPSuffix entries with resilience + offensive
stats, blue+ quality only), --info-wsuf, --validate-wsuf with
--json variants. Validator catches id+name required, category
0..4, quality range valid (0..7 covers heirloom), itemQuality
floor<=ceiling, stat-kind/value pairing (kind=0 with value!=0
is a typo, vice versa), and no-stats warning (suffix renames
item without changing it).
Format graph: 63 → 64 binary formats. CLI flag count: 854
→ 861.
2026-05-09 21:05:49 -07:00
tools/editor/cli_item_suffixes_catalog.cpp
feat(pipeline): add WCRR (Wowee Combat Rating Conversion) catalog
65th open format — replaces gtCombatRatings.dbc plus the
per-level rating-to-percentage tables in gtRegenHPPerSpt.dbc
and related stat-curve DBCs. Defines per-rating-type
conversion factors at canonical level breakpoints (1 / 60
/ 70 / 80) — the runtime linearly interpolates between
breakpoints for intermediate levels.
pointsAtLevelN is "how many rating points equal 1% of the
benefit at that level." Higher level = more rating needed
for the same %. Standard WoW WotLK example: 14 crit rating
= 1% crit at L60, but 45.91 = 1% at L80.
5 rating kinds (Combat / Defense / Spell / Resilience /
Other) classify what stat resolver category each rating
belongs to.
CLI: --gen-crr (3 essential combat ratings — Hit/Crit/Haste
at canonical WoW WotLK conversion values), --gen-crr-defensive
(4 defensive — Defense/Dodge/Parry/Block with diminishing-
returns soft-cap percentages), --gen-crr-spell (3 spell —
SpellPower direct 1:1, SpellPenetration flat, MP5 mana
regen), --info-wcrr, --validate-wcrr with --json variants.
Validator catches id+name required, kind 0..4, all
pointsAtLN > 0 (otherwise stat resolver would div-by-zero),
maxBenefitPercent > 0 (rating would never grant any
benefit), and non-monotonic conversion curve warning
(rating cost typically ascends with level for non-flat
ratings like SpellPower).
Format graph: 64 → 65 binary formats. CLI flag count: 861
→ 868.
2026-05-09 21:11:26 -07:00
tools/editor/cli_combat_ratings_catalog.cpp
feat(pipeline): add WUMV (Wowee Unit Movement Type) catalog
66th open format — replaces UnitMovement.dbc plus the
movement-modifier portions of CreatureModelData.dbc. Defines
movement speed types (walk / run / swim / flight / fly /
pitch) with their canonical baseline speeds in yards-per-
second, plus the temp speed buffs that stack on top
(Sprint, Aspect of the Cheetah, Travel Form).
12 movement categories cover the canonical surface (Walk /
Run / Backward / Swim / SwimBack / Turn / Flight /
FlightBack / Pitch / Fly / FlyBack / TempBuff). baseSpeed
is yards/second for baseline categories and ignored for
TempBuff entries (which use baseMultiplier instead).
maxMultiplier caps stacking — Sprint capped at 1.4 means
Sprint + Aspect of Cheetah doesn't exceed 1.4× run speed.
stackingPriority resolves conflicts when multiple buffs
of equal multiplier compete (higher wins).
CLI: --gen-umv (4 baseline at canonical WoW vanilla speeds:
Walk 2.5y/s, Run 7.0y/s, Swim 4.7y/s, Turn π rad/s),
--gen-umv-flight (5 flight entries — ground-rail Flight
7y/s, free Fly 14y/s, Pitch 1.5 rad/s, backward variants
at slower 4.5y/s), --gen-umv-buffs (5 temp speed buffs
matching real WoW spell auras with proper durations and
stacking priorities), --info-wumv, --validate-wumv with
--json variants. Validator catches id+name required,
category 0..11, baseMultiplier > 0 (otherwise unit freezes
in place), maxMultiplier >= baseMultiplier (cap below
floor would clamp the base down), baseline categories
need baseSpeed > 0, and Run < 3.0y/s warning (canonical
is 7.0y/s).
Format graph: 65 → 66 binary formats. CLI flag count: 870
→ 875.
2026-05-09 21:18:03 -07:00
tools/editor/cli_unit_movement_catalog.cpp
feat(pipeline): add WQSO (Wowee Quest Sort) catalog
67th open format — replaces QuestSort.dbc plus the quest-log
categorization fields in QuestInfo.dbc. Defines the
categories that quests fall into for the quest-log UI:
class quests (Warrior trial, etc), profession quests, daily
quests, holiday events, reputation grinds, dungeon /
heroic / raid quests, repeatables, PvP, tournament.
12 sort kinds (General / ClassQuest / Profession / Daily /
Holiday / Reputation / Dungeon / Raid / Heroic / Repeatable
/ PvP / Tournament). Each WQT (quest) entry can reference
a sortId here to be grouped under the right header in the
quest log. Sorts can be class-restricted (Warrior quests
only show for warriors), profession-restricted, or
faction-reputation-gated.
Cross-references with prior formats — targetClassMask uses
WCHC.classId bit positions (matches WGLY/WSET/WGTP
convention), targetProfessionId points at WTSK.profession
enum, targetFactionId points at WFAC.factionId.
CLI: --gen-qso (3 generic sorts — General catch-all, Daily
reset, Repeatable non-daily), --gen-qso-class (10 class-
specific sorts with proper bit masks for Warrior 0x02
through Druid 0x800), --gen-qso-profession (8 profession
sorts with WTSK profession enum cross-refs), --info-wqso,
--validate-wqso with --json variants. Validator catches
id+name+displayName required, kind 0..11, ClassQuest with
classMask=0 (not actually class-restricted), Profession
with profId=0 + non-Blacksmithing-name (likely typo since
0=Blacksmithing in WTSK), and Reputation with factionId=0
(no faction to grind).
Format graph: 66 → 67 binary formats. CLI flag count: 877
→ 882.
2026-05-09 21:23:38 -07:00
tools/editor/cli_quest_sorts_catalog.cpp
feat(editor): add WSRG (Spell Range Index) open catalog format
Open replacement for Blizzard's SpellRange.dbc plus the per-spell
range-bucket fields in Spell.dbc. Defines the categorical range
buckets that spells reference instead of carrying their own min/max
yards (every Frostbolt shares one 30y bucket; every Heal shares
one 40y friendly bucket). Each entry carries separate min/max for
hostile vs friendly targets so heals can reach further on allies
than nukes do on enemies, plus an icon color for HUD range
indicators.
Three preset emitters: --gen-srg (3 baseline buckets:
Self/Melee/Spell), --gen-srg-ranged (5 ranged spell buckets:
Short/Medium/Long/VeryLong/Unlimited), --gen-srg-friendly (3
friendly-only buckets where hostile range is 0). --info-wsrg and
--validate-wsrg round out the per-format surface; validation
catches negative ranges, min>max, duplicate ids, out-of-range
rangeKind, and warns on Self+nonzero range or Melee>8y.
Wired through the cross-format table so WSRG appears automatically
in --list-formats, --info-magic, --diff-headers, --summary-dir,
--rename-by-magic, --catalog-grep, --tree-summary-md, and
--touch-tree. Format count 67 -> 68; CLI flag count 885 -> 890.
2026-05-09 21:33:17 -07:00
tools/editor/cli_spell_ranges_catalog.cpp
2026-05-09 21:37:42 -07:00
tools/editor/cli_spell_cast_times_catalog.cpp
feat(editor): add WSDR (Spell Duration Index) — completes WSRG/WSCT/WSDR triplet
Open replacement for SpellDuration.dbc plus per-spell duration
fields in Spell.dbc. Defines the categorical duration buckets
that auras / DoTs / HoTs / buffs reference (5s / 30s / 5min / 1hr
/ UntilCancelled / UntilDeath).
Together with WSRG (range) and WSCT (cast time), this completes a
small triplet of spell-metadata catalogs: instead of every
Frostbolt rank embedding its own range, cast time, and
chill-debuff duration as duplicate fields, each spell holds three
small integer ids that resolve through these three tables. The
engine retunes thousands of spells at once by editing one bucket.
Duration scales with caster level via perLevelMs (a rank-1 Renew
at 9s grows to 12s at lvl 60), then is clamped to maxDurationMs.
Negative baseDurationMs is the canonical sentinel for "no timer"
(UntilCancelled / UntilDeath); resolveAtLevel returns -1 for
those so HUD code can render the indefinite-duration glyph.
Three preset emitters: --gen-sdr (5 baseline tiers from instant
to one-hour), --gen-sdr-buffs (4 long-duration buffs including
UntilDeath), --gen-sdr-dot (4 tick-based DoT/HoT buckets at 3s
ticks). Validation enforces base>0 for Timed/TickBased, base<0
for permanent kinds, max>=base, durationKind 0..4, no duplicate
ids, and warns on Instant+nonzero base.
Wired through the cross-format table; WSDR appears automatically
in all 9 cross-format utilities. Format count 69 -> 70; CLI flag
count 899 -> 904.
2026-05-09 21:41:55 -07:00
tools/editor/cli_spell_durations_catalog.cpp
2026-05-09 21:49:13 -07:00
tools/editor/cli_spell_cooldowns_catalog.cpp
feat(editor): add WCEF (Creature Family) open catalog format
Open replacement for CreatureFamily.dbc plus the per-creature
family fields in Creature.dbc. Defines the family categorization
that pet-able beasts share (Bear / Cat / Wolf / Boar / Crab /
Raptor / Devilsaur / etc), each with its own pet talent tree
(Ferocity / Tenacity / Cunning), food preferences as a bitmask
(Meat / Fish / Bread / Cheese / Fruit / Fungus / Raw), the skill
line that family-specific abilities reference, and the minimum
hunter level required to tame it.
Used by the hunter pet system to decide which talent tree a tamed
pet uses, validate that a hunter can tame a creature, match
feeding-table food items to pet preferences, and gate exotic-beast
families behind the Beast Master 51-point talent.
Cross-references back to WCRT (creature.familyId points here) and
WSPL (family-specific abilities reference WSPL spellId via the
skillLine field).
Three preset emitters: --gen-cef (5 baseline families covering
both major talent trees), --gen-cef-ferocity (4 DPS-tree pets
with bleed/howl/armor-shred mechanics), --gen-cef-exotic (4
exotic Beast Master families requiring 51-point talent).
Validation enforces id+name presence, familyKind 0..5, talent
tree 0..3, no duplicate ids, and warns on:
- NotPet families with a non-None talent tree (irrelevant)
- Exotic families with minLevelForTame > 80 (level-cap unreachable)
- Beast/Exotic families with no food types set (pet would starve)
Wired through the cross-format table; WCEF appears automatically
in all 10 cross-format utilities. Format count 71 -> 72; CLI flag
count 914 -> 919.
2026-05-09 21:54:00 -07:00
tools/editor/cli_creature_families_catalog.cpp
feat(editor): add WSPC (Spell Power Cost) — completes spell-bucket five-pack
Open replacement for the per-spell power-cost fields in Spell.dbc
plus SpellPowerCost-related side tables. Defines categorical
power-cost buckets that spells reference (LowMana 5% / MediumMana
15% / HighMana 30% of caster max mana; fixed Rage-30 /
Energy-40 / Runic-30 / etc), so spells share cost metadata across
ranks instead of embedding per-rank cost numbers.
Completes the small lookup-bucket five-pack:
WSRG — range bucket
WSCT — cast time bucket
WSDR — duration bucket
WSCD — cooldown bucket
WSPC — power cost bucket (this catalog)
Five small integer ids per spell (range / cast / dur / cd / cost)
replace the dozens of duplicate per-rank fields that Blizzard's
Spell.dbc carries. Editing one bucket here retunes every spell
that references it — change LowMana from 5% to 4% and every
rank-1 bolt across every caster class becomes cheaper.
Cost can be flat (baseCost), per-level scaled (perLevelCost), or
percentage-of-max-power (percentOfBase) — the engine sums
whichever fields are non-zero. resolveCost(id, level, maxPower)
does the math. Twelve power types covering every WoW resource
(Mana / Rage / Focus / Energy / Happiness / Runic Power / Runes /
Soul Shards / Holy Power / Eclipse / Health / NoCost).
Three preset emitters: --gen-spc (4 baseline mana tiers),
--gen-spc-rage (4 fixed warrior rage costs including stance-locked
Whirlwind), --gen-spc-mixed (5 cross-class costs covering every
non-mana power type with refund-on-miss flag for energy).
Validation enforces id+name presence, powerType 0..11, no
duplicate ids; warns on percentOfBase outside [0,1] (would
overflow), NoCost type with non-zero cost fields, and non-NoCost
types with no cost set (would cast for free — easy bug to ship).
Wired through the cross-format table; WSPC appears automatically
in all 11 cross-format utilities. Format count 72 -> 73; CLI flag
count 922 -> 927.
2026-05-09 22:00:55 -07:00
tools/editor/cli_spell_power_costs_catalog.cpp
feat(editor): add WGFS (Glyph Slot) open catalog format
Open replacement for Blizzard's GlyphSlot.dbc. Defines the
per-class glyph slot layout: which slots a class has (Major /
Minor / Prime), in which display order they appear in the
spellbook UI, and at which character level each slot becomes
available for use.
Distinct from WGLY (GlyphProperties) which defines the individual
glyphs themselves. WGLY says "Glyph of Polymorph exists, costs 1
inscription dust, modifies Polymorph"; WGFS says "the slot that
holds Glyph of Polymorph is the second Major Glyph Slot, unlocks
at level 25, and only Mages have it".
Layout grew across expansions, captured by the three presets:
- --gen-gfs — 6 slots: 3 Major + 3 Minor all-class
baseline (25/50/75 each)
- --gen-gfs-wotlk — 6 slots: 3 Major (15/30/50) + 3 Minor
(15/50/70) matching WotLK 3.3.5a
- --gen-gfs-cata — 9 slots: 3 Prime + 3 Major + 3 Minor
matching Cataclysm
Cross-references back to WGLY (glyphs reference slotKind to
constrain which glyph fits which slot) and WCHC (requiredClassMask
uses the same bit layout as WCHC class IDs).
Validation enforces id+name+classMask presence (classMask=0 means
no class can use the slot — usually a config bug), slotKind 0..2,
no duplicate ids; warns on minLevelToUnlock>80 (would never
unlock at WotLK cap), displayOrder>4 (UI typically shows 3-4),
and (kind+order) collisions for overlapping classMask (two slots
claiming the same UI position would render on top of each other).
isUnlockedFor(id, classBit, level) is the engine helper.
Wired through the cross-format table; WGFS appears automatically
in all 11 cross-format utilities. Format count 73 -> 74; CLI flag
count 929 -> 934.
2026-05-09 22:05:05 -07:00
tools/editor/cli_glyph_slots_catalog.cpp
feat(editor): add WCDF (Creature Difficulty) open catalog format
Open replacement for Blizzard's CreatureDifficulty.dbc. Maps a
base creature entry to its difficulty variants:
Normal-10 / Normal-25 / Heroic-10 / Heroic-25 in WotLK raid
format. Each variant is itself a separate WCRT creature entry
with its own stats, abilities, and loot.
When a 25-man party engages an instance, the engine looks up the
encounter base creature's difficultyId, reads the normal25Id
field, and spawns that variant instead. This is how Lord
Marrowgar in 25-Heroic ICC has 30M HP and hits for 80k while the
same encounter in 10-Normal has 5M HP and hits for 25k — same
spawn point, different WCRT entries.
5-man dungeons typically use only normal10Id + heroic10Id (the
25-man fields stay 0 — engine falls through to the 10-man
variant when 25-man is queried). World bosses don't scale at
all (all 4 variant fields stay 0, engine falls back to the base
entry).
Cross-references back to WCRT — every non-zero variant id field
points at a WCRT.creatureId entry; the base creature itself
lives in WCRT too.
Three preset emitters: --gen-cdf (4 example bosses with full
4-variant routing), --gen-cdf-wotlk-raid (4 ICC-style raid
bosses Marrowgar/Deathwhisper/Saurfang/LK with all 4 difficulty
variants), --gen-cdf-fiveman (4 5-man dungeon bosses with only
Normal+Heroic 10-man set). resolveVariant(id, mode) is the
engine helper.
Validation enforces id+name+baseCreatureId presence,
spawnGroupKind 0..5, no duplicate ids; warns on:
- WorldBoss kind with non-zero variant ids (world bosses don't scale)
- duplicate baseCreatureId across routes (only first honored)
- all-self-reference non-WorldBoss (creature doesn't actually scale)
- Boss with n25 but not n10 (raid sequencing typo — n10 always
comes with n25)
Wired through the cross-format table; WCDF appears automatically
in all 11 cross-format utilities. Format count 74 -> 75; CLI flag
count 936 -> 941.
2026-05-09 22:10:09 -07:00
tools/editor/cli_creature_difficulties_catalog.cpp
feat(editor): add WMAT (Item Material) open catalog format
Open replacement for Blizzard's Material.dbc plus the Material
and SheatheType fields in ItemDisplayInfo.dbc. Defines the
material categorization that items reference (Cloth / Leather /
Mail / Plate / Wood / Steel / Crystal / Ethereal / etc), each
with its own foley sound (played on item use), impact sound
(played on drop / hit), weight category, and material-property
flags (IsBreakable / IsMagical / IsFlammable / IsConductive /
IsHolyCharged / IsCursed).
The engine plays a sword's metallic clang from impactSoundId
when it hits a stone wall, but a cloth tabard makes no such
sound — the difference is exactly the material assigned by this
catalog. Every armor and weapon item in WIT references a
materialId here.
Twelve materialKind values cover the standard armor classes
(Cloth/Leather/Mail/Plate/Hide), structural materials (Wood /
Stone / Metal), and special categories (Liquid / Organic /
Crystal / Ethereal). Three weight tiers (Light / Medium / Heavy)
control encumbrance UI hints.
Cross-references back to WSND (foleySoundId / impactSoundId
reference WSND sound entries) and forward to WIT (item entries
reference materialId here).
Three preset emitters: --gen-mat (5 armor materials matching
WoW's armor classes), --gen-mat-weapon (5 weapon materials from
breakable+flammable Wood through enchanted endgame steel),
--gen-mat-magical (4 magical materials with special flags
including the IsHolyCharged anti-undead property).
Validation enforces id+name presence, materialKind 0..11,
weightCategory 0..2, no duplicate ids; warns on:
- IsHolyCharged + IsCursed both set (engine picks one,
typically IsCursed wins)
- Plate kind that's not Heavy weight (canonical violation)
- Cloth kind that's not Light weight (canonical violation)
Wired through the cross-format table; WMAT appears automatically
in all 11 cross-format utilities. Format count 75 -> 76; CLI flag
count 943 -> 948.
2026-05-09 22:14:44 -07:00
tools/editor/cli_item_materials_catalog.cpp
feat(editor): add WPSP (Player Spawn Profile) open catalog format
Open replacement for AzerothCore's playercreateinfo SQL table
plus the per-class/race starting fields in CharStartOutfit.dbc.
Defines the initial state for a newly created character: starting
map / zone / position / facing, bind point (Hearthstone
destination), up to 4 starting items with counts, and up to 4
starting spells.
One entry per (race, class) combination — a Human Warrior spawns
at Northshire Abbey with a Worn Shortsword and Heroic Strike
already learned, while an Orc Hunter spawns in Valley of Trials
with Aimed Shot and a starter rifle. Death Knights have their
own preset spawning at lvl 55 in Acherus, the Ebon Hold.
The race+class fields are bitmasks (mirroring WCHC layout) so
one profile entry can cover multiple class/race combinations
that share starting state. findByRaceClass(raceBit, classBit)
is the engine helper used by character creation.
Cross-references back to WCHC (race/class bit layouts), WMS (map
ids), WIT (starting item ids), and WSPL (starting spell ids).
Three preset emitters: --gen-psp (5 Alliance combos covering
each starting zone from Northshire to Ammen Vale), --gen-psp-horde
(5 Horde combos from Valley of Trials to Sunstrider Isle),
--gen-psp-dk (2 DK combos at lvl 55 in Acherus with Death Coil /
Plague Strike / Death Grip starter loadout).
Validation enforces id+name+race+class+startingLevel presence,
no duplicate ids; warns on (0,0,0) spawn (uninitialized entry),
item id/count mismatch (granted item without count or vice versa),
startingLevel > 80 (above WotLK cap), and Death Knight class
with startingLevel < 55 (DKs canonically start at 55).
Wired through the cross-format table; WPSP appears automatically
in all 12 cross-format utilities. Format count 76 -> 77; CLI flag
count 951 -> 956.
2026-05-09 22:22:57 -07:00
tools/editor/cli_player_spawn_profiles_catalog.cpp
feat(editor): add WTLE (Talent Tab) open catalog format
Open replacement for Blizzard's TalentTab.dbc plus the per-tab
fields in Spell.dbc / Talent.dbc. Defines the three talent trees
that each class has — Warrior: Arms / Fury / Protection;
Mage: Arcane / Fire / Frost; Paladin: Holy / Protection /
Retribution; etc.
Each tab carries its own name, role hint (DPS / Tank / Healer /
Hybrid / PetClass), display order in the talent UI, background
artwork path (e.g. "WarriorArms" for the parchment background),
icon path, and the class bitmask it belongs to.
Distinct from WTAL (which defines individual talent points) —
WTLE says "the Arms tree exists for Warriors, displays in tab 1,
is a DPS spec"; WTAL says "Mortal Strike is a 1-point talent in
the Arms tree, row 7, requires Improved Charge as a prerequisite".
Cross-references back to WCHC (classMask uses the same bit
layout) and forward to WTAL (talent entries reference tabId
here). findByClass(classBit) returns all tabs for a class
sorted by displayOrder — the talent UI uses this directly to
populate its tab buttons.
Three preset emitters: --gen-tle (Warrior 3 tabs with two DPS +
one Tank), --gen-tle-mage (Mage 3 DPS tabs), --gen-tle-paladin
(Paladin 3 tabs covering all three roles in one preset).
Validation enforces id+name+classMask presence (classMask=0
means no class can use the tab — usually a config bug),
roleHint 0..4, no duplicate ids; warns on empty iconPath
(missing-texture render), empty backgroundFile (no panel art),
displayOrder>3 (UI shows at most 4 tabs), and (classMask +
displayOrder) collisions for overlapping classes (two tabs
claiming the same UI slot for the same class).
Wired through the cross-format table; WTLE appears automatically
in all 12 cross-format utilities. Format count 77 -> 78; CLI flag
count 958 -> 963.
2026-05-09 22:27:18 -07:00
tools/editor/cli_talent_tabs_catalog.cpp
feat(editor): add WCTR (Currency Type) open catalog format
Open replacement for Blizzard's CurrencyTypes.dbc plus the
per-currency cap tables in CurrencyCategory.dbc. Defines the
in-game currencies that are NOT regular item stacks: Honor
Points, Arena Points, Justice Points, Valor Points, Conquest
Points, plus the various faction tokens (Champion's Seal,
Wintergrasp Mark of Honor, Emblem of Frost).
Distinct from regular items in WIT — currencies are tracked
per-character as scalar quantities with weekly + absolute caps,
not as stackable inventory slots. Some currencies are still
backed by a WIT item entry for the icon and tooltip text
(itemId field), while others (Honor, Arena) live entirely in
the currency system.
The cap model captures both shapes:
- maxQuantity = absolute lifetime cap (Honor Points 75k)
- maxQuantityWeekly = weekly earn cap, no absolute cap
(Conquest Points 1650/wk)
- both 0 = uncapped (faction tokens, Emblem of Frost)
earnableNow(id, current, weekly) is the engine helper that
returns the smaller of (remaining absolute, remaining weekly).
Cross-references back to WIT (itemId for tooltip art) and
WFAC (categoryId references factionId for FactionToken kind —
the rep gate that lets you spend the token).
Three preset emitters: --gen-ctr (4 PvP currencies covering
absolute, weekly-only, and uncapped tiers), --gen-ctr-pve (4
PvE raid currencies with same cap variety), --gen-ctr-faction
(4 faction tokens with their categoryId pointing at WFAC
faction ids).
Validation enforces id+name presence, currencyKind 0..5, no
duplicate ids; warns on:
- maxQuantityWeekly > maxQuantity (weekly cap will never be
reached, absolute cap blocks first)
- FactionToken kind with categoryId=0 (rep gate breaks)
- no caps + no itemId + no iconPath (currency has no display
data and unbounded earn rate)
Wired through the cross-format table; WCTR appears automatically
in all 12 cross-format utilities. Format count 78 -> 79; CLI flag
count 965 -> 970.
2026-05-09 22:31:42 -07:00
tools/editor/cli_currency_types_catalog.cpp
2026-05-09 22:38:36 -07:00
tools/editor/cli_spell_reagents_catalog.cpp
feat(editor): add WACR (Achievement Criteria) open catalog format
Open replacement for Blizzard's Achievement_Criteria.dbc. Defines
the individual progression criteria that a character must
complete to earn an achievement.
Each WACH achievement has a tree of WACR criteria — "Kill 100
boars" is one criteria entry with criteriaType=KillCreature,
targetId=boarCreatureId, requiredCount=100. Multi-criteria
achievements (e.g. "Visit all 3 capital cities") have one entry
per sub-objective, all referencing the same achievementId, with
progressOrder determining their display sequence in the
achievement UI.
Thirteen criteriaType values cover the full progression variety:
KillCreature / ReachLevel / CompleteQuest / EarnGold /
GainHonor / EarnReputation / ExploreZone / LootItem /
UseItem / CastSpell / PvPKill / DungeonRun / Misc
The targetId field is type-polymorphic — for KillCreature it
references WCRT.creatureId, for CompleteQuest it references
WQT.questId, for ExploreZone it's a WMS.zoneId, etc. The engine
interprets it based on criteriaType.
Cross-references back to WACH (achievementId), WCRT
(KillCreature.targetId), WQT (CompleteQuest.targetId), WIT
(LootItem/UseItem.targetId), WMS (ExploreZone.targetId), WSPL
(CastSpell.targetId). findByAchievement(achId) returns all
criteria for an achievement sorted by progressOrder — used
directly by the achievement UI to render the progress checklist.
Three preset emitters: --gen-acr (5 kill criteria under one
composite achievement showing different creature targets),
--gen-acr-quest (4-step quest progression), --gen-acr-mixed
(5 cross-type criteria demonstrating the full CriteriaType
variety).
Validation enforces id+name+achievementId presence,
criteriaType 0..12, no duplicate ids; warns on:
- missing targetId for type-specific kinds (KillCreature,
CompleteQuest, etc. — engine cannot track without it)
- ReachLevel with requiredCount > 80 (above WotLK cap)
- timeLimitMs set on non-time-sensitive types (engine
ignores it for ReachLevel / EarnGold)
- requiredCount=0 (criteria completes instantly on first
progress event — usually a misconfig)
Wired through the cross-format table; WACR appears automatically
in all 14 cross-format utilities. Format count 80 -> 81; CLI flag
count 981 -> 986.
2026-05-09 22:43:44 -07:00
tools/editor/cli_achievement_criteria_catalog.cpp
feat(editor): add WSEF (Spell Effect Type) open catalog format
Open replacement for the SpellEffect.Effect field meanings in
Spell.dbc plus the engine's hard-coded effect dispatch table.
Defines what each spell-effect integer value actually does —
SCHOOL_DAMAGE=2 deals magical damage, DUMMY=3 is a script hook,
HEAL=10 restores health, ENERGIZE=30 restores power,
APPLY_AURA=6 attaches a buff/debuff, etc.
WotLK's Spell.dbc has 192+ effect type integers, each with its
own resolver in the spell engine. This catalog lets the engine
look up "given effect=10, what resolution behavior do I run?"
via a single table lookup instead of a hard-coded switch
statement, and lets server-custom spells reference new effect
IDs without touching engine code.
Ten effectKind values capture the major behavior families
(Damage / Heal / Aura / Energize / Trigger / Movement / Summon /
Dispel / Dummy / Misc), and a 6-bit behaviorFlags field
captures targeting/gating semantics:
- RequiresTarget — must have a target
- RequiresLineOfSight — LoS check on target
- IsHostileEffect — hostile only (PvP gating)
- IsBeneficialEffect — friendly only
- IgnoresImmunities — bypasses Bubble / IBF / etc
- TriggersGCD — counts toward GCD
Distinct from WAUR (Spell Aura Type, future format) which is the
secondary classification used when effectType is APPLY_AURA. The
two together cover the full spell-effect classification space.
Three preset emitters: --gen-sef (5 damage effects covering
typical Spell.dbc damage IDs), --gen-sef-healing (4 heal
effects all flagged IsBeneficialEffect), --gen-sef-aura (5
aura-application effects covering single-target / pet /
party-wide / area variants).
Validation enforces name presence, effectKind 0..9, no duplicate
ids; warns on:
- both Hostile and Beneficial flags set (engine picks Hostile,
contradiction suggests config bug)
- Damage kind without TriggersGCD (most damage should be on GCD
— env damage is the canonical exception)
- Heal kind without IsBeneficialEffect (engine treats heal as
ungated, may damage enemies)
Wired through the cross-format table; WSEF appears automatically
in all 15 cross-format utilities. Format count 81 -> 82; CLI flag
count 989 -> 994.
2026-05-09 22:50:13 -07:00
tools/editor/cli_spell_effect_types_catalog.cpp
feat(editor): add WAUR (Spell Aura Type) — companion to WSEF, CLI flag count breaks 1000
Open replacement for the SpellEffect.EffectAuraType field
meanings used when SpellEffect.Effect=APPLY_AURA. Defines what
each aura-type integer value actually does once an aura is
attached to a unit — PERIODIC_DAMAGE ticks damage every N
seconds, MOD_STAT adds a stat bonus, MOD_INCREASE_SPEED scales
movement, MOD_DAMAGE_PERCENT_DONE scales spell power, etc.
Companion to WSEF — together they cover the full spell-effect
classification space:
WSEF: outer effect ID — what does the effect DO?
(APPLY_AURA, SCHOOL_DAMAGE, HEAL, etc)
WAUR: inner aura type — when WSEF=APPLY_AURA, what KIND
of aura is applied? (PERIODIC_DAMAGE, MOD_STAT,
STUN, ROOT, etc)
Nine auraKind values (Periodic / StatMod / DamageMod /
Movement / Visual / Trigger / Resource / Control / Misc)
classify the major behavior families. Periodic auras carry an
updateFrequencyMs (canonical 3s for DoT/HoT, 2s for energize,
1s for fast triggers). Stackable auras carry a maxStackCount.
Cross-references back to WSEF (this catalog is the secondary
classification that WSEF entry id 6 (APPLY_AURA) dispatches
into) and forward to WSPL (spell entries with effect=APPLY_AURA
reference an auraTypeId here).
Three preset emitters: --gen-aur (5 periodic auras with
canonical tick intervals), --gen-aur-stats (5 stat-modifier
auras instantly applied on attach), --gen-aur-movement (4
movement-impairing CC auras typical of crowd-control spells).
Validation enforces name presence, auraKind 0..8, targetingHint
0..3, no duplicate ids; errors on Periodic kind without
updateFrequencyMs (would never tick); warns on:
- non-Periodic/Trigger kinds with updateFrequencyMs > 0
(engine ignores tick interval)
- maxStackCount > 0 with isStackable=false (cap unreachable)
Wired through the cross-format table; WAUR appears automatically
in all 15 cross-format utilities. Format count 82 -> 83;
CLI flag count 996 -> 1001 — broke the 1000-flag mark.
2026-05-09 22:54:53 -07:00
tools/editor/cli_spell_aura_types_catalog.cpp
feat(editor): add WIQR (Item Quality) open catalog format
Open replacement for the hardcoded item quality tiers in the
WoW client (Poor / Common / Uncommon / Rare / Epic / Legendary
/ Artifact / Heirloom). Defines each tier's tooltip text color,
inventory slot border color, vendor price multiplier, drop-level
gating, and disenchant eligibility.
The hardcoded client uses a fixed color table (gray/white/green/
blue/purple/orange/red/gold). This catalog lets server admins:
- retune the colors (rename "Epic" to "Tier 1" with custom hex)
- add server-custom tiers above Heirloom
- change vendor markup per tier (legendary 50x base price)
- gate quality drops by character level (Heirlooms unlock 80)
The standard preset reproduces the canonical 8-tier scale with
exact hex values from the live client (#9d9d9d through #00ccff)
and standard disenchant rules (Common+ disenchantable, Legendary
and Artifact aren't). The server-custom preset shows 4 tiers
above the standard range with non-standard pricing (Junk 0.1x,
QuestLocked 0.0x unsellable). The raid preset gates 4
progression tiers behind minLevelToDrop=60 with escalating
vendor multipliers up to 50x for Legendary.
Cross-references back to WIT — item entries reference qualityId
here for tooltip color and sort order. canDropAtLevel(id, lvl)
is the engine helper used by loot generation.
Validation enforces name presence, no duplicate ids,
vendorPriceMultiplier >= 0, minLevelToDrop <= maxLevelToDrop;
warns on:
- minLevelToDrop > 80 (unreachable at WotLK cap)
- vendorPriceMultiplier > 100x (sanity check the economy)
- nameColorRGBA with alpha=0 (text would be invisible in
tooltips — common bug when copy-pasting RGB hex without
alpha byte)
Wired through the cross-format table; WIQR appears automatically
in all 15 cross-format utilities. Format count 83 -> 84; CLI
flag count 1003 -> 1008.
2026-05-09 22:59:27 -07:00
tools/editor/cli_item_qualities_catalog.cpp
feat(editor): add WSCS (Skill Cost) open catalog format
Open replacement for Blizzard's SkillCostsData.dbc plus the
per-rank training cost tables. Defines the tiered progression of
trainable skills: each rank unlocks a skill range, requires a
minimum character level, and costs a fixed amount of gold to
learn.
The canonical 6-tier profession progression captured by the
default preset:
Apprentice skill 0-75 lvl 5 1s
Journeyman skill 50-150 lvl 10 5s
Expert skill 125-225 lvl 20 1g
Artisan skill 200-300 lvl 35 5g
Master skill 275-375 lvl 50 10g
Grand Master skill 350-450 lvl 65 25g
Same shape applies to weapon skills (free, level-gated, capped at
5x char level) and riding skills (canonical Vanilla / TBC / WotLK
gold costs from 90g Apprentice through 5000g Artisan flying down
to 1000g Cold Weather Flying).
Five costKind values cover the full training-skill space
(Profession / WeaponSkill / RidingSkill / ClassSkill / Misc).
Each entry's copperCost stores the cost in copper (1g = 10000c)
which the info renderer pretty-prints as "25g 0s 0c".
Cross-references back to WSKL — skill entries reference costId
here for the tiered training schedule. nextTrainable(currentSkill,
characterLevel) is the engine helper that returns the lowest-rank
tier a character qualifies for and hasn't capped yet — used by
trainer NPCs to populate their offered-skill list.
Three preset emitters: --gen-scs (6 profession tiers), --gen-scs-
weapon (5 weapon skill tiers), --gen-scs-riding (5 riding tiers
with canonical gold costs).
Validation enforces id+name presence, costKind 0..4, no duplicate
ids, min<max range; warns on:
- requiredLevel > 80 (unreachable at WotLK cap)
- RidingSkill with requiredLevel < 20 (Apprentice canonically
unlocks at 20)
- Profession kind with copperCost=0 (every standard tier costs
at least a copper — usually a config bug)
Wired through the cross-format table; WSCS appears automatically
in all 15 cross-format utilities. Format count 84 -> 85; CLI
flag count 1010 -> 1015.
2026-05-09 23:04:02 -07:00
tools/editor/cli_skill_costs_catalog.cpp
2026-05-09 07:56:16 -07:00
tools/editor/cli_quest_objective.cpp
2026-05-09 08:01:28 -07:00
tools/editor/cli_quest_reward.cpp
2026-05-09 08:06:20 -07:00
tools/editor/cli_clone.cpp
2026-05-09 08:11:50 -07:00
tools/editor/cli_remove.cpp
2026-05-09 08:16:52 -07:00
tools/editor/cli_add.cpp
2026-05-09 08:22:06 -07:00
tools/editor/cli_random.cpp
2026-05-09 08:26:52 -07:00
tools/editor/cli_items_export.cpp
2026-05-09 08:33:59 -07:00
tools/editor/cli_items_mutate.cpp
2026-05-09 08:42:49 -07:00
tools/editor/cli_zone_create.cpp
2026-05-09 08:47:32 -07:00
tools/editor/cli_tiles.cpp
2026-05-09 08:52:19 -07:00
tools/editor/cli_zone_mgmt.cpp
2026-05-09 08:56:47 -07:00
tools/editor/cli_strip.cpp
2026-05-09 08:59:51 -07:00
tools/editor/cli_repair.cpp
2026-05-09 09:04:44 -07:00
tools/editor/cli_makefile.cpp
2026-05-09 09:09:06 -07:00
tools/editor/cli_zone_list.cpp
2026-05-09 09:14:01 -07:00
tools/editor/cli_tilemap.cpp
2026-05-09 09:16:26 -07:00
tools/editor/cli_deps.cpp
2026-05-09 09:23:23 -07:00
tools/editor/cli_for_each.cpp
2026-05-09 09:25:41 -07:00
tools/editor/cli_check.cpp
refactor(editor): extract CLI introspection handlers into cli_introspect.cpp
Moves five self-discovery handlers (--list-commands,
--info-cli-stats, --info-cli-categories, --info-cli-help,
--gen-completion) out of main.cpp into a new
cli_introspect.{hpp,cpp} module. All five auto-discover
commands by parsing printUsage's stdout via tmpfile capture,
so the surface stays self-describing as new flags are added.
Useful for shell completion scripts that re-exec the binary
at completion time, IDE plugins, and 'is there a flag for X?'
search workflows. main.cpp shrinks by 276 lines (2,298 to
2,022). --validate-cli-help stays inline because it needs
direct access to the static-local kArgRequired array.
2026-05-09 09:31:31 -07:00
tools/editor/cli_introspect.cpp
2026-05-09 09:34:19 -07:00
tools/editor/cli_texture_helpers.cpp
refactor(editor): extract WOM/WOB info handlers into cli_mesh_info.cpp
Moves three mesh-aggregate info handlers (--info-zone-models-total,
--list-zone-meshes-detail, --info-mesh) out of main.cpp into a
new cli_mesh_info.{hpp,cpp} module. The first aggregates
WOM/WOB stats across a zone; the second tabulates per-mesh
metrics sorted by triangle count; the third dumps single-WOM
detail (bounds, version, batches, bones, animations, textures).
main.cpp shrinks by 285 lines (1,826 to 1,541). All three
preserve --json output for capacity-planning pipelines.
2026-05-09 09:40:03 -07:00
tools/editor/cli_mesh_info.cpp
2026-05-09 09:44:52 -07:00
tools/editor/cli_zone_data.cpp
2026-05-09 09:54:17 -07:00
tools/editor/cli_project_actions.cpp
2026-05-09 10:01:33 -07:00
tools/editor/cli_zone_export.cpp
2026-05-09 10:08:14 -07:00
tools/editor/cli_arg_required.cpp
2026-05-09 10:22:36 -07:00
tools/editor/cli_multi_arg_required.cpp
2026-05-09 11:05:54 -07:00
tools/editor/cli_weld.cpp
refactor(editor): extract addBox into shared cli_box_emitter
36 procedural mesh primitives in cli_gen_mesh.cpp each open-
coded the same ~30-line lambda for emitting a flat-shaded
axis-aligned box (per-face vertices for unique normals,
6 faces × 4 verts × 2 tris). Hoist the implementation into
cli_box_emitter.{hpp,cpp} as addFlatBox(WoweeModel&, ...)
with two overloads:
• addFlatBox(wom, cx, cy, cz, hx, hy, hz)
center + half-extents form, used by 34 primitives
• addFlatBox(wom, glm::vec3 lo, glm::vec3 hi)
lo/hi corners form, used by --gen-mesh-archway and
--gen-mesh-fence which compute corners directly
Each lambda site collapses from ~30 lines to a 3-line thin
wrapper: cli_gen_mesh.cpp drops from 7374 to 6989 lines.
Output bytes verified identical via --info-mesh-stats
(firepit surface area 2.1100 m² unchanged, vertex/triangle
counts match across firepit/canopy/dock/archway/fence).
Future box-based primitives now opt in by including one
header instead of pasting the lambda again.
2026-05-09 11:24:35 -07:00
tools/editor/cli_box_emitter.cpp
2026-05-09 10:15:51 -07:00
tools/editor/cli_dispatch.cpp
feat(editor): add standalone world editor (rough/WIP)
Standalone wowee_editor tool for creating custom WoW zones.
This is a rough initial implementation — many features work but
M2/WMO rendering still has issues (frame sync, texture layout
transitions) and needs further polish.
Terrain:
- Create new blank terrain with 10 biome types (Grassland, Forest,
Jungle, Desert, Barrens, Snow, Swamp, Rocky, Beach, Volcanic)
- Load existing ADT tiles from extracted game data
- Sculpt brushes: Raise, Lower, Smooth, Flatten, Level
- Chunk edge stitching prevents seams between tiles
- Undo/redo (100-deep stack, Ctrl+Z/Ctrl+Shift+Z)
- Save to WoW ADT/WDT format
Texture Painting:
- Paint/Erase/Replace Base modes
- Full tileset texture browser (1285 textures from manifest)
- Per-zone directory filtering and search
- Alpha map editing with 4-layer limit (auto-replaces weakest)
Object Placement:
- M2 and WMO model placement with full manifest browser (11k M2s, 2k WMOs)
- M2Renderer + WMORenderer integrated (loads .skin files for WotLK)
- Ghost preview follows cursor before placing
- Ctrl+click selection, right-click context menu
- Transform gizmo (Move/Rotate/Scale with axis constraints)
- Position/rotation/scale editing in properties panel
NPC/Monster System:
- 631 creature presets scanned from manifest, categorized
(Critters, Beasts, Humanoids, Undead, Demons, etc.)
- Stats editor: level, health, mana, damage, armor, faction
- Behavior: Stationary, Patrol, Wander, Scripted
- Aggro/leash radius, respawn time, flags (hostile/vendor/etc.)
- Save creature spawns to JSON
Water:
- Place water at configurable height per chunk
- Liquid types: Water, Ocean, Magma, Slime
- Rendered as translucent colored quads
- Saved in ADT MH2O format
Infrastructure:
- Free-fly camera (WASD/QE, right-drag look, scroll speed)
- 5-mode toolbar: Sculpt | Paint | Objects | Water | NPCs
- Asset browser indexes full manifest on startup
- Editor water/marker shaders (pos+color vertex format)
- forceNoCull added to M2Renderer for editor use
- AssetManifest::getEntries() and AssetManager::getManifest() exposed
Known issues:
- M2/WMO rendering may not display on first placement (frame index
sync between update/render was misaligned — now fixed but untested
end-to-end)
- Validation layer errors on shutdown (resource cleanup ordering)
- Object placement on steep terrain can miss raycast
- No undo for texture painting or object placement yet
2026-05-05 03:47:03 -07:00
tools/editor/editor_app.cpp
tools/editor/editor_camera.cpp
tools/editor/editor_viewport.cpp
tools/editor/editor_ui.cpp
tools/editor/editor_brush.cpp
tools/editor/editor_history.cpp
tools/editor/terrain_editor.cpp
tools/editor/texture_painter.cpp
tools/editor/object_placer.cpp
tools/editor/npc_spawner.cpp
tools/editor/npc_presets.cpp
feat(editor): SQL spawn export for AzerothCore/TrinityCore
Private server integration: export creature spawns, patrol waypoints,
and quest definitions as ready-to-import SQL for AzerothCore/TrinityCore.
- creature_template: name, level, health, mana, damage, armor, faction,
npcflag (questgiver/vendor/flightmaster/innkeeper), displayId, scale
- creature: spawn position, orientation, respawn time, wander distance,
movement type (stationary/wander/patrol)
- creature_addon + waypoint_data: patrol path waypoints with delays
- quest_template: title, description, completion text, level, XP, money
- All use ON DUPLICATE KEY UPDATE for safe re-imports
- Auto-exported as spawns.sql alongside other assets on zone save
- File > Export Server SQL menu item for standalone export
- Map ID from zone metadata panel used in spawn table
2026-05-05 16:06:34 -07:00
tools/editor/sql_exporter.cpp
2026-05-05 16:31:13 -07:00
tools/editor/server_module_gen.cpp
feat(editor): quest editor with objectives, rewards, and quest chains
- New Quest mode (key 6) with full quest creation panel:
- Title, description, required level
- Quest giver / turn-in NPC ID linkage
- Up to 4 objectives: Kill, Collect, Talk, Explore, Escort, Use Object
- Rewards: XP and gold
- Quest chain support via nextQuestId linking
- Quest list showing all created quests with level and objective count
- Save quests to JSON (included in Export Zone package)
- Foundation for campaign system: create quest chains across NPCs,
link objectives to placed creatures, build storylines
2026-05-05 06:10:14 -07:00
tools/editor/quest_editor.cpp
feat(editor): add standalone world editor (rough/WIP)
Standalone wowee_editor tool for creating custom WoW zones.
This is a rough initial implementation — many features work but
M2/WMO rendering still has issues (frame sync, texture layout
transitions) and needs further polish.
Terrain:
- Create new blank terrain with 10 biome types (Grassland, Forest,
Jungle, Desert, Barrens, Snow, Swamp, Rocky, Beach, Volcanic)
- Load existing ADT tiles from extracted game data
- Sculpt brushes: Raise, Lower, Smooth, Flatten, Level
- Chunk edge stitching prevents seams between tiles
- Undo/redo (100-deep stack, Ctrl+Z/Ctrl+Shift+Z)
- Save to WoW ADT/WDT format
Texture Painting:
- Paint/Erase/Replace Base modes
- Full tileset texture browser (1285 textures from manifest)
- Per-zone directory filtering and search
- Alpha map editing with 4-layer limit (auto-replaces weakest)
Object Placement:
- M2 and WMO model placement with full manifest browser (11k M2s, 2k WMOs)
- M2Renderer + WMORenderer integrated (loads .skin files for WotLK)
- Ghost preview follows cursor before placing
- Ctrl+click selection, right-click context menu
- Transform gizmo (Move/Rotate/Scale with axis constraints)
- Position/rotation/scale editing in properties panel
NPC/Monster System:
- 631 creature presets scanned from manifest, categorized
(Critters, Beasts, Humanoids, Undead, Demons, etc.)
- Stats editor: level, health, mana, damage, armor, faction
- Behavior: Stationary, Patrol, Wander, Scripted
- Aggro/leash radius, respawn time, flags (hostile/vendor/etc.)
- Save creature spawns to JSON
Water:
- Place water at configurable height per chunk
- Liquid types: Water, Ocean, Magma, Slime
- Rendered as translucent colored quads
- Saved in ADT MH2O format
Infrastructure:
- Free-fly camera (WASD/QE, right-drag look, scroll speed)
- 5-mode toolbar: Sculpt | Paint | Objects | Water | NPCs
- Asset browser indexes full manifest on startup
- Editor water/marker shaders (pos+color vertex format)
- forceNoCull added to M2Renderer for editor use
- AssetManifest::getEntries() and AssetManager::getManifest() exposed
Known issues:
- M2/WMO rendering may not display on first placement (frame index
sync between update/render was misaligned — now fixed but untested
end-to-end)
- Validation layer errors on shutdown (resource cleanup ordering)
- Object placement on steep terrain can miss raycast
- No undo for texture painting or object placement yet
2026-05-05 03:47:03 -07:00
tools/editor/transform_gizmo.cpp
2026-05-05 05:06:41 -07:00
tools/editor/zone_manifest.cpp
2026-05-05 09:27:00 -07:00
tools/editor/content_pack.cpp
2026-05-05 09:32:13 -07:00
tools/editor/wowee_terrain.cpp
2026-05-05 09:36:44 -07:00
tools/editor/editor_project.cpp
2026-05-05 10:17:03 -07:00
tools/editor/texture_exporter.cpp
2026-05-05 10:21:14 -07:00
tools/editor/dbc_exporter.cpp
feat(editor): add standalone world editor (rough/WIP)
Standalone wowee_editor tool for creating custom WoW zones.
This is a rough initial implementation — many features work but
M2/WMO rendering still has issues (frame sync, texture layout
transitions) and needs further polish.
Terrain:
- Create new blank terrain with 10 biome types (Grassland, Forest,
Jungle, Desert, Barrens, Snow, Swamp, Rocky, Beach, Volcanic)
- Load existing ADT tiles from extracted game data
- Sculpt brushes: Raise, Lower, Smooth, Flatten, Level
- Chunk edge stitching prevents seams between tiles
- Undo/redo (100-deep stack, Ctrl+Z/Ctrl+Shift+Z)
- Save to WoW ADT/WDT format
Texture Painting:
- Paint/Erase/Replace Base modes
- Full tileset texture browser (1285 textures from manifest)
- Per-zone directory filtering and search
- Alpha map editing with 4-layer limit (auto-replaces weakest)
Object Placement:
- M2 and WMO model placement with full manifest browser (11k M2s, 2k WMOs)
- M2Renderer + WMORenderer integrated (loads .skin files for WotLK)
- Ghost preview follows cursor before placing
- Ctrl+click selection, right-click context menu
- Transform gizmo (Move/Rotate/Scale with axis constraints)
- Position/rotation/scale editing in properties panel
NPC/Monster System:
- 631 creature presets scanned from manifest, categorized
(Critters, Beasts, Humanoids, Undead, Demons, etc.)
- Stats editor: level, health, mana, damage, armor, faction
- Behavior: Stationary, Patrol, Wander, Scripted
- Aggro/leash radius, respawn time, flags (hostile/vendor/etc.)
- Save creature spawns to JSON
Water:
- Place water at configurable height per chunk
- Liquid types: Water, Ocean, Magma, Slime
- Rendered as translucent colored quads
- Saved in ADT MH2O format
Infrastructure:
- Free-fly camera (WASD/QE, right-drag look, scroll speed)
- 5-mode toolbar: Sculpt | Paint | Objects | Water | NPCs
- Asset browser indexes full manifest on startup
- Editor water/marker shaders (pos+color vertex format)
- forceNoCull added to M2Renderer for editor use
- AssetManifest::getEntries() and AssetManager::getManifest() exposed
Known issues:
- M2/WMO rendering may not display on first placement (frame index
sync between update/render was misaligned — now fixed but untested
end-to-end)
- Validation layer errors on shutdown (resource cleanup ordering)
- Object placement on steep terrain can miss raycast
- No undo for texture painting or object placement yet
2026-05-05 03:47:03 -07:00
tools/editor/asset_browser.cpp
tools/editor/editor_water.cpp
tools/editor/editor_markers.cpp
tools/editor/adt_writer.cpp
# Pipeline (asset loading)
src/pipeline/blp_loader.cpp
src/pipeline/dbc_loader.cpp
src/pipeline/dbc_layout.cpp
src/pipeline/asset_manager.cpp
src/pipeline/asset_manifest.cpp
src/pipeline/loose_file_reader.cpp
src/pipeline/m2_loader.cpp
src/pipeline/wmo_loader.cpp
src/pipeline/adt_loader.cpp
src/pipeline/wdt_loader.cpp
2026-05-05 09:56:24 -07:00
src/pipeline/wowee_terrain_loader.cpp
2026-05-05 10:24:46 -07:00
src/pipeline/wowee_model.cpp
2026-05-06 10:32:17 -07:00
src/pipeline/wowee_model_fromm2.cpp
2026-05-05 10:28:24 -07:00
src/pipeline/wowee_building.cpp
2026-05-05 15:23:58 -07:00
src/pipeline/wowee_collision.cpp
2026-05-09 13:52:07 -07:00
src/pipeline/wowee_light.cpp
feat(pipeline): add Wowee Open Weather (.wow) zone schedule
8th open-format addition to the Wowee pipeline. Replaces
WoW's WeatherTypes.dbc / WeatherEffect logic with a single
binary file holding a list of weather states for one zone,
each tagged with intensity bounds, a probability weight,
and duration bounds. The renderer / runtime samples one
entry at a time using weighted-random selection, drives
it for a uniform-random duration in [min, max] sec, then
re-rolls.
• Types: Clear / Rain / Snow / Storm / Sandstorm / Fog /
Blizzard (extensible enum).
• Binary format: magic "WOWA", version 1, name, N entries
each storing (typeId, minIntensity, maxIntensity, weight,
minDurationSec, maxDurationSec).
CLI:
• --info-wow <wow-base> [--json] — inspect a WOW
• --gen-weather-temperate — clear + rain + fog (forest)
• --gen-weather-arctic — snow + blizzard + fog (tundra)
• --gen-weather-desert — clear + sandstorm (dunes)
• --gen-weather-stormy — rain + storm + occasional clear
The 8th open format complementing the rest:
M2 → WOM | WMO → WOB | WMO collision → WOC | ADT → WOT
DBC → JsonDBC | BLP → PNG | Light.dbc → WOL | WeatherTypes.dbc → WOW
Smoke-tested all 4 presets + JSON output. Each preset reads
back identically with the expected entry count and weight
distribution.
2026-05-09 14:10:13 -07:00
src/pipeline/wowee_weather.cpp
2026-05-09 14:38:05 -07:00
src/pipeline/wowee_world_map.cpp
feat(pipeline): add WSND (Wowee Sound Catalog) format
Novel open replacement for Blizzard's SoundEntries.dbc +
SoundEntriesAdvanced.dbc. The 10th open format added to the
editor — covers the audio-metadata gap (the previous 9 cover
geometry, terrain, atmosphere, and world manifests, but no
sound metadata).
Format:
• magic "WSND", version 1, little-endian
• catalogName + entry count
• per entry: soundId / kind / flags / volume /
minDistance / maxDistance / filePath / label
Kind enum (7 categories):
sfx, music, ambient, ui, voice, spell, combat
Flags packed (3 bits used, rest reserved):
loop (0x01), 3d (0x02), stream (0x04)
API: WoweeSoundLoader::save / load / exists; presets
makeStarter (one entry per kind), makeAmbient (wilderness
loops + footsteps), makeTavern (fire + crowd + drink + door
+ lute).
CLI added (5 flags, 465 documented total now):
--gen-sound-catalog <base> [name]
--gen-sound-catalog-ambient <base> [name]
--gen-sound-catalog-tavern <base> [name]
--info-wsnd <base> [--json]
--validate-wsnd <base> [--json]
Validator catches: out-of-range kind, NaN/inf volume or
distances, 3D sounds with bad min/max, duplicate sound IDs,
empty filePaths.
All 3 presets verified: save / load / validate clean
on first run. Variable-length string fields use length-
prefixed encoding with a 1 MiB sanity cap on read to
prevent corrupted-file allocation blowups.
2026-05-09 14:47:16 -07:00
src/pipeline/wowee_sound.cpp
feat(pipeline): add WSPN (Wowee Spawn Point catalog) format
Novel open replacement for AzerothCore-style scattered
creature_template / gameobject SQL spawn tables PLUS the
ADT MDDF / MODF doodad-placement chunks. The 11th open
format, and the first that covers the live world-content
side (atmosphere + sounds + spawns now form the runtime
"what fills this zone" picture).
A WSPN file holds all spawn points for a zone in a single
table, with kind discriminating creature vs game object
vs static doodad. The same format powers:
• server runtime — knows what NPCs / objects to spawn
• editor — draws spawn markers
• renderer — reads the doodad subset directly to
draw static props without going
through a server roundtrip
Format:
• magic "WSPN", version 1, little-endian
• per entry: kind / entryId / position(3f) / rotation(3f)
/ scale / flags / respawnSec / factionId /
questIdRequired / wanderRadius / label
Flags packed: disabled (0x01), event-only (0x02),
quest-phased (0x04). Reserved bits for future per-entry
encoding extensions.
API: WoweeSpawnsLoader::save / load / exists; presets
makeStarter (1 each kind), makeCamp (4-bandit ring +
chest + 2 tents), makeVillage (6 NPCs + 2 signs + 4
corner trees).
CLI added (5 flags, 473 documented total now):
--gen-spawns / --gen-spawns-camp / --gen-spawns-village
--info-wspn / --validate-wspn
Validator catches: out-of-range kind, NaN/inf coords,
non-positive scale, doodad with non-zero respawn (static
prop misuse), creature with respawn=0 (won't respawn after
kill), entryId=0 (orphan reference).
All 3 presets save / load / re-validate clean. Doodad and
game-object entries explicitly set wanderRadius=0 so the
generated catalogs are noise-free.
2026-05-09 14:57:53 -07:00
src/pipeline/wowee_spawns.cpp
feat(pipeline): add WIT (Wowee Item Template) format
Novel open replacement for Blizzard's Item.dbc +
ItemDisplayInfo.dbc + the SQL item_template tables that
AzerothCore-style servers store item definitions in. The
12th open format added to the editor.
A WIT file holds the catalog of all items in a content
pack: weapons, armor, consumables, quest items, trade
goods. Each entry pairs gameplay metadata (stats, level
reqs, flags, weapon damage / speed) with display metadata
(displayId for icon / model, quality color), so the
runtime can render inventory tooltips and equip slots
from a single load.
Format:
• magic "WITM", version 1, little-endian
• per item: itemId / displayId / quality / itemClass /
itemSubClass / inventoryType / flags / requiredLevel /
itemLevel / sellPrice / buyPrice / maxStack / durability
/ damageMin / damageMax / attackSpeedMs /
statCount + stats[] / name / description
Enums:
• Quality: Poor..Heirloom (8 levels)
• Class: Consumable, Weapon, Armor, Quest, ... (13)
• InventoryType: Head..Cloak..Weapon2H (18 slots)
• Flags: Unique, BoP, BoE, QuestItem, Conjured, ...
• StatType: Stamina, Strength, Intellect, Defense, ...
API: WoweeItemLoader::save / load / exists / findById;
presets makeStarter (4-item demo), makeWeapons (5 items
common -> legendary), makeArmor (6-piece mail set with
BoE flag).
CLI added (5 flags, 480 documented total now):
--gen-items / --gen-items-weapons / --gen-items-armor
--info-wit / --validate-wit
Validator catches: itemId=0, duplicate itemIds, weapons
with 0 damage or attackSpeed, weapons with non-weapon
slot, equippables with durability=0 or maxStack>1, sell
price >= buy price (vendor would lose money), out-of-range
quality.
All 3 presets save / load / re-validate clean. Info-table
output includes a gold/silver/copper price formatter for
hand-readability.
2026-05-09 15:04:48 -07:00
src/pipeline/wowee_items.cpp
feat(pipeline): add WLOT (Wowee Loot Table) format
Novel open replacement for AzerothCore-style
creature_loot_template / gameobject_loot_template SQL
tables. The 13th open format added to the editor.
Pairs naturally with the WIT item catalog from the
preceding commit: each loot drop's itemId references an
entry in a WIT file, so a content pack ships both the
item definitions and the loot tables that reference them.
The runtime composes WIT + WLOT + WSPN to drive the full
"creature dies, drops items" flow without any SQL.
Format:
• magic "WLOT", version 1, little-endian
• per table: creatureId / flags / dropCount /
moneyMin..Max / itemDropCount + drops[]
• per drop: itemId / chancePercent (float, 0..100) /
minQty / maxQty / drop_flags
Table flags: QuestOnly, GroupOnly, Pickpocket
Drop flags: QuestRequired, GroupRollOnly, AlwaysDrop
dropCount is the slot budget — how many distinct drops
to roll per kill. Each item drop is rolled independently
against its chancePercent (so dropCount=2 with 4 candidate
drops at varying chances gives the classic "up to 2 distinct
items per kill" behavior). Drops with the AlwaysDrop flag
bypass the slot budget — used for guaranteed quest items.
API: WoweeLootLoader::save / load / exists /
findByCreatureId; presets makeStarter (1 table, 1 drop),
makeBandit (4 candidates, dropCount=2, matches the camp
spawns from WSPN at creatureId=1000), makeBoss (6 candidates
including guaranteed quest item via AlwaysDrop and a
group-only epic at 5%).
CLI added (5 flags, 486 documented total now):
--gen-loot / --gen-loot-bandit / --gen-loot-boss
--info-wlot / --validate-wlot
Validator catches: creatureId=0, duplicates, chance not in
0..100, NaN chance, money min > max, minQty > maxQty,
dropCount=0 with non-empty drops list (silent dead config).
All 3 presets save / load / re-validate clean. The bandit
table's creatureId=1000 deliberately matches WSPN's
makeCamp creatureId so the open-format demo content pack
already has working cross-references.
2026-05-09 15:11:08 -07:00
src/pipeline/wowee_loot.cpp
feat(pipeline): add WCRT (Wowee Creature Template) format
Novel open replacement for the AzerothCore-style
creature_template SQL table PLUS the Blizzard
CreatureTemplate / CreatureFamily / CreatureType.dbc trio.
The 14th open format added to the editor.
This is the canonical metadata side of creatures shared
across every spawn instance: HP, level range, faction,
behavior flags, NPC role bits (vendor / trainer /
quest-giver / innkeeper), base damage, equipped gear
references.
Cross-references with the previously-added formats:
WSPN.entry.entryId -> WCRT.entry.creatureId
WLOT.entry.creatureId -> WCRT.entry.creatureId
WCRT.entry.equipped* -> WIT.entry.itemId
The 4-format set (WIT + WLOT + WSPN + WCRT) now lets a
content pack define a complete RPG zone's creature
ecosystem: what creatures are, where they spawn, what they
drop, and what gear they carry — entirely in open formats
with no SQL dependencies.
Format:
• magic "WCRT", version 1, little-endian
• per entry: creatureId / displayId / name / subname /
minLevel..maxLevel / baseHealth + healthPerLevel /
baseMana + manaPerLevel / factionId / npcFlags /
typeId / familyId / damageMin..Max / attackSpeedMs /
baseArmor / walkSpeed + runSpeed / gossipId /
equippedMain + equippedOffhand + equippedRanged /
aiFlags
Enums:
• TypeId: Beast / Dragon / Demon / Elemental / Giant /
Undead / Humanoid / Critter / Mechanical
• FamilyId: Wolf / Cat / Bear / Boar / Raptor / Hyena /
Spider / Gorilla / Crab (for Beast types)
• NpcFlags: Vendor / QuestGiver / Trainer / Banker /
Innkeeper / FlightMaster / Auctioneer /
Repair / Stable
• Behavior: Passive / Aggressive / FleeLowHp / CallHelp /
NoLeash
API: WoweeCreatureLoader::save / load / exists /
findById; presets makeStarter (1 innkeeper),
makeBandit (creatureId=1000 matches WSPN/WLOT bandit
references, equips WIT itemId=1001 sword), makeMerchants
(creatureIds 4001/4002/4003 match WSPN village labels).
CLI added (5 flags, 493 documented total):
--gen-creatures / --gen-creatures-bandit / --gen-creatures-merchants
--info-wcrt / --validate-wcrt
Validator catches: creatureId=0, duplicates, level=0,
minLevel>maxLevel, baseHealth=0, damageMin>damageMax,
attackSpeed=0, non-positive walk/runSpeed, behavior flag
contradictions (passive+aggressive), vendor with
aggressive behavior (player can't trade).
2026-05-09 15:18:44 -07:00
src/pipeline/wowee_creatures.cpp
feat(pipeline): add WQT (Wowee Quest Template) format
Novel open replacement for AzerothCore-style quest_template
SQL tables PLUS the Blizzard Quest.dbc / QuestObjective.dbc
trio. The 15th open format added to the editor — and the
last gameplay-graph piece the catalog needed.
Cross-references with previously-added formats:
WQT.giverCreatureId -> WCRT.entry.creatureId
WQT.turninCreatureId -> WCRT.entry.creatureId
WQT.objective.targetId -> WCRT (kill) / WIT (collect) /
WOB (interact)
WQT.rewardItem.itemId -> WIT.entry.itemId
WQT.prevQuestId -> WQT.entry.questId (intra-format)
WQT.nextQuestId -> WQT.entry.questId
Together with WIT / WCRT / WLOT / WSPN / WOMX / WOL / WOW /
WSND, a content pack can now ship a complete RPG zone
(terrain + props + atmosphere + sounds + creatures + items
+ loot + spawns + quests) entirely in open formats with no
SQL or .dbc dependencies. 15 of 15 expected slots filled.
Format:
• magic "WQTM", version 1, little-endian
• per quest: questId / title / objective / description /
minLevel..maxLevel + questLevel / requiredClass+RaceMask /
prev+nextQuestId / giver+turninCreatureId /
objectives[] / xpReward + moneyCopperReward /
rewardItems[] / flags
Per-objective:
kind (kill/collect/interact/visit/escort/cast),
targetId, quantity
Per-reward:
itemId, qty, pickFlags (AutoGiven / PlayerChoice)
Quest flags: Daily / Weekly / Raid / Group / AutoComplete /
AutoAccept / Repeatable / ClassQuest / Pvp
API: WoweeQuestLoader::save / load / exists / findById;
presets makeStarter (1 simple kill quest, references the
bandit creatureId=1000), makeChain (3-quest chain with
prev/next links + AutoComplete bridge + player-choice
rewards), makeDaily (Daily+Repeatable+AutoAccept combo).
CLI added (5 flags, 500 documented total — round milestone):
--gen-quests / --gen-quests-chain / --gen-quests-daily
--info-wqt / --validate-wqt
Validator catches: questId=0+duplicates, level=0,
maxLevel<minLevel, empty title, no objectives without
AutoComplete (player can't finish), no rewards at all,
Daily without Repeatable (incoherent), targetId=0,
quantity=0, unknown objective kind, reward itemId=0 or qty=0.
The 3-quest chain demo exercises every major feature:
• multiple objective kinds (visit / collect / kill)
• prev/next chain links
• AutoComplete dialogue-bridge quest
• PlayerChoice reward (1 of 2 weapons)
2026-05-09 15:25:02 -07:00
src/pipeline/wowee_quests.cpp
feat(pipeline): add WGOT (Wowee Game Object Template) format
Novel open replacement for AzerothCore-style
gameobject_template SQL tables PLUS the Blizzard
GameObjectDisplayInfo.dbc / GameObject types metadata. The
16th open format added to the editor.
Game objects are the non-creature interactable scenery:
chests (with loot), doors, buttons, mailboxes, herb / ore
gathering nodes, fishing pools, signposts, mounts. Each
has a displayId for the model, a typeId driving its
interaction logic, and optional cross-references to a lock
(future WLCK) and loot table (existing WLOT).
Cross-references with previously-added formats:
WSPN.entry.entryId (kind=GameObject) -> WGOT.entry.objectId
WGOT.entry.lootTableId -> WLOT.entry.creatureId
(loot tables are
universal — chests
and creatures both
key by ID)
The dungeon preset's Bandit Strongbox uses lootTableId=2000
to match WLOT's bandit chest table id, so the demo content
stack already wires together: spawn (WSPN object kind 2000)
-> object template (WGOT 2000) -> loot table (WLOT 2000).
Format:
• magic "WGOT", version 1, little-endian
• per object: objectId / displayId / name / typeId /
size / castBarCaption / requiredSkill +
requiredSkillValue / lockId / lootTableId /
minOpenTimeMs..maxOpenTimeMs / flags
Enums:
• TypeId (16): Door / Button / Chest / Container /
QuestGiver / Text / Trap / Goober / Transport /
Mailbox / MineralNode / HerbNode / FishingNode /
Mount / Sign / Bonfire
• Flags: Disabled / ScriptOnly / UsableFromMount /
Despawn / Frozen / QuestGated
API: WoweeGameObjectLoader::save / load / exists /
findById; presets makeStarter (chest + mailbox + sign),
makeDungeon (door + button + 2 chests + trap with proper
WLOT cross-references), makeGather (Peacebloom herb +
Tin Vein ore + fishing pool with skill requirements).
CLI added (5 flags, 507 documented total now):
--gen-objects / --gen-objects-dungeon / --gen-objects-gather
--info-wgot / --validate-wgot
Validator catches: objectId=0 + duplicates, size<=0,
minOpenTime>maxOpenTime, gathering node without skill
requirement (anyone can harvest — usually a typo), chest
without loot table (script must populate), requiredSkillValue
set without requiredSkill (incoherent).
2026-05-09 15:31:49 -07:00
src/pipeline/wowee_objects.cpp
feat(pipeline): add WFAC (Wowee Faction Catalog) format
Novel open replacement for Blizzard's Faction.dbc +
FactionTemplate.dbc + the AzerothCore-style
reputation_reward / reputation_spillover SQL tables. The
17th open format added to the editor.
Combines the "displayable Faction" (player-facing name +
reputation thresholds for friendly/honored/revered/exalted)
with the "FactionTemplate matrix" (which factions are
hostile to which) into one entry. The runtime walks the
catalog to answer two questions:
• "Will faction A attack faction B on sight?" -> enemy list
• "What rep tier is the player with X?" -> thresholds
Cross-references with previously-added formats:
WCRT.entry.factionId -> WFAC.entry.factionId
WFAC.entry.parentFactionId -> WFAC.entry.factionId
WFAC.entry.enemies[] -> WFAC.entry.factionId
WFAC.entry.friends[] -> WFAC.entry.factionId
The starter preset's factionId 35 (Friendly) and 14
(Hostile) deliberately match the WCRT preset defaults, so
the demo content stack is consistent: WCRT.makeBandit's
factionId=14 has a real entry in WFAC.makeStarter that
declares it hostile to friendly NPCs (35) and players (1).
Format:
• magic "WFAC", version 1, little-endian
• per faction: factionId / parentFactionId / name /
description / reputationFlags / baseReputation /
7 ascending tier thresholds (hostile..exalted) /
enemies[] / friends[]
Enums:
• ReputationFlags: VisibleOnTab / AtWarDefault / Hidden /
NoReputation / IsHeader (group label)
• Tier (canonical): Hated / Hostile / Unfriendly /
Neutral / Friendly / Honored /
Revered / Exalted
API: WoweeFactionLoader::save / load / exists / findById +
WoweeFaction::isHostile(a, b); presets makeStarter (3-faction
demo matching WCRT defaults), makeAlliance (header +
Stormwind / Darnassus / Ironforge with reciprocal friend
lists + Defias enemy), makeWildlife (4 beast factions, each
hostile to player but ignoring other beasts).
CLI added (5 flags, 514 documented total now):
--gen-factions / --gen-factions-alliance / --gen-factions-wildlife
--info-wfac / --validate-wfac
Validator catches: factionId=0 + duplicates, empty name,
threshold ordering violations (hostile must be < unfriendly
< neutral < ... < exalted), self-listed as enemy or friend,
faction in both enemies and friends (incoherent).
2026-05-09 15:37:59 -07:00
src/pipeline/wowee_factions.cpp
feat(pipeline): add WLCK (Wowee Lock Template) format
Novel open replacement for Blizzard's Lock.dbc. The 18th
open format added to the editor. Closes the cross-reference
gap from WGOT.entry.lockId — until now that field pointed
to a format that didn't exist yet.
A lock is a multi-channel security check. Each lock has up
to 5 independent channels; a player can open the lock by
satisfying ANY ONE channel:
• Item — requires a specific key item (WIT cross-ref)
• Lockpick — requires the lockpicking skill at minimum rank
(rogue / engineering profession)
• Spell — requires casting a specific spell
• Damage — can be forced open with attack damage
Cross-references with previously-added formats:
WGOT.entry.lockId -> WLCK.entry.lockId
WLCK.channel.targetId (Item) -> WIT.entry.itemId
WLCK.channel.targetId (Lockpick) -> future WSKL skillId
WLCK.channel.targetId (Spell) -> future WSPL spellId
The starter and dungeon presets' lockIds (1 and 2)
deliberately match WGOT.makeDungeon's iron-door lockId=1
and bandit-strongbox lockId=2, so the demo content stack
already wires together: WSPN spawn -> WGOT object template
-> WLCK lock template -> WIT key items.
Format:
• magic "WLCK", version 1, little-endian
• per lock: lockId / name / flags / 5 fixed channel slots
• per channel: kind / skillRequired / targetId
• all 5 slots written even when unused (kind=None +
zeroed fields), keeping the per-entry size constant for
fast random access
Enums:
• ChannelKind: None / Item / Lockpick / Spell / Damage
• Flags: DestructOnOpen / RespawnOnKey / TrapOnFail
API: WoweeLockLoader::save / load / exists / findById;
presets makeStarter (Iron Door + Wooden Chest), makeDungeon
(matches WGOT cross-references; light/heavy lockpicks +
boss-key-only seal), makeProfessions (4-tier rogue lockpick
progression at ranks 1/100/175/250).
CLI added (5 flags, 521 documented total now):
--gen-locks / --gen-locks-dungeon / --gen-locks-professions
--info-wlck / --validate-wlck
Validator catches: lockId=0 + duplicates, all-None channels
(lock can never open), Item/Spell/Lockpick channels with
targetId=0 (no resource referenced), unknown channel kind,
skillRequired set on non-Lockpick channel (silently ignored
at runtime — flag as warning).
2026-05-09 15:44:26 -07:00
src/pipeline/wowee_locks.cpp
feat(pipeline): add WSKL (Wowee Skill Catalog) format
Novel open replacement for Blizzard's SkillLine.dbc +
SkillLineCategory.dbc + the AzerothCore-style player skill
base tables. The 19th open format added to the editor.
Defines every player-trackable skill: weapon proficiencies
(Swords, Axes, Bows), professions (Mining, Alchemy,
Cooking), languages (Common, Dwarvish), class
specializations (Fire, Frost, Holy, Protection), armor
proficiencies (Mail, Plate), and secondary skills (First
Aid, Lockpicking, Riding).
Cross-references with previously-added formats:
WLCK.channel.targetId (kind=Lockpick) -> WSKL.entry.skillId
WGOT.entry.requiredSkill -> WSKL.entry.skillId
The starter preset's skillIds 186 (Mining) and 633
(Lockpicking) deliberately match the canonical IDs already
referenced by WGOT.makeGather and WLCK.makeDungeon —
so the demo content stack now wires together end-to-end:
WGOT herb-node requires skill 186 -> WSKL Mining at rank 1+;
WLCK bandit-strongbox channel requires skill 633 -> WSKL
Lockpicking at rank 1+.
Format:
• magic "WSKL", version 1, little-endian
• per skill: skillId / name / description / categoryId /
canTrain / maxRank / rankPerLevel / iconPath
Enums:
• CategoryId (8): Weapon / Class / Profession /
SecondaryProfession / Language / ArmorProficiency /
Riding / WeaponSpec
API: WoweeSkillLoader::save / load / exists / findById;
presets makeStarter (5-skill demo with cross-referenced
canonical IDs), makeProfessions (12 classic professions:
9 primary + 3 secondary), makeWeapons (16 weapon skills
with canonical SkillLine IDs and rankPerLevel=5 auto-grow).
CLI added (5 flags, 528 documented total now):
--gen-skills / --gen-skills-professions / --gen-skills-weapons
--info-wskl / --validate-wskl
Validator catches: skillId=0 + duplicates, empty name,
maxRank=0, unknown categoryId, suspicious maxRank=1 on
non-Language skill (only languages cap at 1), weapon skill
with rankPerLevel=0 (won't auto-grow on use).
2026-05-09 15:50:25 -07:00
src/pipeline/wowee_skills.cpp
feat(pipeline): add WSPL (Wowee Spell Catalog) format
Novel open replacement for Blizzard's Spell.dbc +
SpellEffect.dbc + the AzerothCore-style spell_dbc /
spell_proc tables. The 20th open format added to the
editor — completes the canonical-data side of the gameplay
graph.
Each entry holds the metadata side of a spell: name,
description, school, range, mana / cast / cooldown times,
plus a single primary effect. The simplified effect model
(one effectKind + min/max value + misc field) covers the
common cases (damage / heal / buff / debuff / teleport /
summon / dispel) without needing to reproduce the full
multi-effect graph that classic Spell.dbc carries.
Cross-references with previously-added formats:
WLCK.channel.targetId (kind=Spell) -> WSPL.entry.spellId
WQT.objective.targetId (kind=SpellCast) -> WSPL.entry.spellId
WCRT.equippedMain (item with on-use) -> WIT -> WSPL
Format:
• magic "WSPL", version 1, little-endian
• per spell: spellId / name / description / iconPath /
school / targetType / effectKind / cast & cooldown &
GCD ms / manaCost / range min..max / minLevel /
maxStacks / durationMs / effectValueMin..Max /
effectMisc / flags
Enums:
• School (7): Physical / Holy / Fire / Nature / Frost /
Shadow / Arcane
• TargetType (6): Self / Single / Cone / AoeFromSelf /
Line / Ground
• EffectKind (7): Damage / Heal / Buff / Debuff / Teleport /
Summon / Dispel
• Flags: Passive / Hidden / Channeled / Ranged /
AreaOfEffect / Triggered / UnitTargetOnly /
FriendlyOnly / HostileOnly
API: WoweeSpellLoader::save / load / exists / findById;
presets makeStarter (Strike + Lesser Heal + Power Word:
Fortitude + Hearthstone, one per major effect kind),
makeMage (Frostbolt 116 + Fireball 133 + Arcane Intellect
1459 + Blink 1953, canonical Classic spellIds), makeWarrior
(Heroic Strike 78 + Thunder Clap 6343 + Battle Shout 6673 +
Mortal Strike 12294).
CLI added (5 flags, 535 documented total now):
--gen-spells / --gen-spells-mage / --gen-spells-warrior
--info-wspl / --validate-wspl
Validator catches: spellId=0 + duplicates, empty name,
school out of range, effectKind out of range, NaN range,
range/value min>max, FriendlyOnly+HostileOnly conflict
(incoherent), friendly-only with damage/debuff effect
(incoherent), hostile-only with heal/buff effect, buff/debuff
effect with durationMs=0 (instant fade — almost certainly
authoring oversight).
The validator caught a real preset-emitter authoring error
during initial smoke testing — buff spells were setting
effectValueMin without effectValueMax (validator's range
check immediately flagged it), prompting an in-batch fix
to set both fields. This is exactly the catch-the-typo
purpose validators serve.
2026-05-09 15:58:09 -07:00
src/pipeline/wowee_spells.cpp
feat(pipeline): add WACH (Wowee Achievement Catalog) format
Novel open replacement for Blizzard's Achievement.dbc +
AchievementCriteria.dbc + AchievementCategory.dbc + the
AzerothCore-style character_achievement /
character_achievement_progress SQL tables. The 21st open
format added to the editor.
Each achievement carries display metadata (name, description,
icon, points, faction restriction) plus a list of criteria
the player must satisfy. Criteria mirror the WQT objective
model (kind + targetId + quantity), so the runtime can
reuse the same progress-tracking machinery for both quests
and achievements.
Cross-references with previously-added formats — every
criterion kind has a real format target:
WACH.criteria.targetId (kind=KillCreature) -> WCRT.creatureId
WACH.criteria.targetId (kind=CompleteQuest) -> WQT.questId
WACH.criteria.targetId (kind=LootItem) -> WIT.itemId
WACH.criteria.targetId (kind=CastSpell) -> WSPL.spellId
WACH.criteria.targetId (kind=ReachSkillLevel) -> WSKL.skillId
WACH.criteria.targetId (kind=EarnReputation) -> WFAC.factionId
WACH.criteria.targetId (kind=CompleteAchievement) -> WACH.achievementId
(meta-achievements)
Format:
• magic "WACH", version 1, little-endian
• per achievement: id / categoryId / name / description /
iconPath / titleReward / points / minLevel / faction /
flags / criteria[]
• per criterion: criteriaId / kind / targetId / quantity /
description
Enums:
• CriteriaKind (9): KillCreature / CompleteQuest / LootItem /
ReachLevel / EarnReputation / CastSpell /
ReachSkillLevel / VisitArea /
CompleteAchievement
• Faction: Both / Alliance / Horde
• Flags: HiddenUntilEarned / ServerFirst / RealmFirst /
Tracking / Counter / Account
API: WoweeAchievementLoader::save / load / exists /
findById; presets makeStarter (3 simple kill/quest/level
demos), makeBandit (3 with WCRT/WGOT/WQT cross-refs),
makeMeta (3 base + 1 meta-achievement granting "the
Versatile" title, exercising CompleteAchievement criterion
kind that lets achievements depend on other achievements).
CLI added (5 flags, 542 documented total now):
--gen-achievements / --gen-achievements-bandit / --gen-achievements-meta
--info-wach / --validate-wach
Validator catches: achievementId=0 + duplicates, empty name,
faction out of range, no criteria (achievement can never
be earned), criterion quantity=0, unknown criterion kind,
targetId=0 on criterion kinds that need a real resource
reference (everything except ReachLevel which uses the
quantity field for the level number).
The bandit preset's cross-references close the gameplay
graph end-to-end: kill 50 creatureId=1000 (matches WCRT/
WSPN/WLOT bandit), loot objectId=2000 (matches WGOT bandit
strongbox), complete questId=1 (matches WQT Bandit Trouble).
The meta preset closes a separate loop: 3 sub-achievements
covering Mining (skillId=186), Lockpicking (skillId=633),
and Frostbolt cast count (spellId=116) — each pointing at
a real WSKL/WSPL entry that already exists in the demo
content stack.
2026-05-09 16:04:30 -07:00
src/pipeline/wowee_achievements.cpp
feat(pipeline): add WTRN (Wowee Trainer / Vendor catalog) format
Novel open replacement for AzerothCore-style npc_trainer +
npc_vendor SQL tables PLUS the Blizzard TrainerSpells.dbc
family. The 22nd open format added to the editor.
Unifies trainer spell lists and vendor item inventories
into one per-NPC entry. A creature flagged Trainer or
Vendor in WCRT references a WTRN entry that lists what they
teach / sell. The same NPC can be both — kindMask is a
bitmask covering the Trainer (0x01) and Vendor (0x02) kinds.
This format closes a major cross-format gap: WCRT.npcFlags
already had Vendor / Trainer bits, but until now there was
no format defining what a vendor sells or what a trainer
teaches. Now an NPC marked Vendor in WCRT has a real
inventory, and an NPC marked Trainer has a real spell list.
Cross-references — every WTRN field has a real format target:
WTRN.entry.npcId -> WCRT.entry.creatureId
WTRN.spell.spellId -> WSPL.entry.spellId
WTRN.spell.requiredSkillId -> WSKL.entry.skillId
WTRN.item.itemId -> WIT.entry.itemId
Format:
• magic "WTRN", version 1, little-endian
• per NPC: npcId / kindMask / greeting + spells[] + items[]
• per spell offer: spellId / moneyCostCopper /
requiredSkillId / requiredSkillRank / requiredLevel
• per item offer: itemId / stockCount (0xFFFFFFFF =
unlimited) / restockSec / extendedCost / moneyCostCopper
(0 = inherit from WIT.buyPrice)
API: WoweeTrainerLoader::save / load / exists / findByNpc;
presets makeStarter (innkeeper 4001 as both trainer +
vendor: teaches First Aid + sells starter items),
makeMageTrainer (NPC 4003 teaches the WSPL mage spells
at scaling cost), makeWeaponVendor (NPC 4002 sells WIT
weapons with mixed unlimited/finite stock + restock timers).
CLI added (5 flags, 551 documented total now):
--gen-trainers / --gen-trainers-mage / --gen-trainers-weapons
--info-wtrn / --validate-wtrn
Validator catches: npcId=0 + duplicates, kindMask=0 (NPC
offers nothing), Trainer flag without spells, Vendor flag
without items, spells/items present without the matching
kind bit (silently ignored at runtime), spellId=0 / itemId=0
in offers, finite stock with restockSec=0 (single-fill —
usually intentional but worth surfacing).
The 3 presets deliberately use npcIds matching WCRT village
merchants (4001/4002/4003) so the demo content stack is
self-consistent: WCRT 4001 has the Vendor + Trainer flag,
and WTRN 4001 actually defines what they sell and teach.
2026-05-09 16:12:58 -07:00
src/pipeline/wowee_trainers.cpp
feat(pipeline): add WGSP (Wowee Gossip Menu) format
Novel open replacement for AzerothCore-style gossip_menu +
gossip_menu_option + npc_text SQL tables PLUS the Blizzard
NpcText.dbc family. The 23rd open format added to the
editor.
An NPC's dialogue tree: a menu of options the player can
pick from when right-clicking the NPC. Each option may
bridge to another menu, trigger a vendor / trainer
interaction, offer a quest, etc. The simplified per-option
model (kind + actionTarget + flags + moneyCost) covers the
common cases without needing separate npc_text condition
tables.
Closes a major cross-format gap: WCRT.entry.gossipId has
existed since batch 116 (when WCRT was added) but pointed
to a format that didn't exist yet. The innkeeper preset's
menuId=4001 deliberately matches WCRT's Bartleby NPC so
the demo content stack can wire WCRT.gossipId = 4001 once
that field is plumbed through the runtime.
Cross-references:
WCRT.entry.gossipId -> WGSP.entry.menuId
WGSP.option.actionTarget (Submenu) -> WGSP.entry.menuId
WGSP.option.actionTarget (Vendor / Trainer)
-> WTRN.entry.npcId
WGSP.option.actionTarget (Quest) -> WQT.entry.questId
Format:
• magic "WGSP", version 1, little-endian
• per menu: menuId / titleText + options[]
• per option: optionId / text / kind / actionTarget /
requiredFlags / moneyCostCopper
Enums:
• OptionKind (13): Close / Submenu / Vendor / Trainer /
Quest / Tabard / Banker / Innkeeper /
FlightMaster / TextOnly / Script /
Battlemaster / Auctioneer
• OptionFlags: AllianceOnly / HordeOnly / Coinpouch /
QuestGated / Closes
API: WoweeGossipLoader::save / load / exists / findById;
presets makeStarter (1 menu with vendor + trainer + close),
makeInnkeeper (2-menu tree: main menu 4001 with hearth /
vendor / flight / submenu options + lore submenu 4002 that
links back), makeQuestGiver (1 menu with 2 quest options
referencing WQT 1 and 100, plus a paid respec script
exercising the Coinpouch flag with a 10g cost).
CLI added (5 flags, 558 documented total now):
--gen-gossip / --gen-gossip-innkeeper / --gen-gossip-questgiver
--info-wgsp / --validate-wgsp
Validator catches: menuId=0 + duplicates, empty title /
options, unknown option kind, empty option text, Submenu
options pointing at non-existent menuIds (intra-format
cross-reference resolution), Coinpouch flag without
moneyCost (misleading UI), AllianceOnly+HordeOnly conflict.
2026-05-09 16:20:07 -07:00
src/pipeline/wowee_gossip.cpp
2026-05-09 16:26:27 -07:00
src/pipeline/wowee_taxi.cpp
feat(pipeline): add WTAL (Wowee Talent catalog) format
Novel open replacement for Blizzard's TalentTab.dbc +
Talent.dbc + the AzerothCore-style talent_progression SQL
tables. The 25th open format added to the editor.
Defines class talent specialization trees: per-class set
of named tabs (Arms / Fury / Protection for warrior, Fire
/ Frost / Arcane for mage), each with talents arranged in
a row/column grid, each talent having up to 5 ranks and
an optional prerequisite chain.
Cross-references with previously-added formats:
WTAL.talent.prereqTalentId -> WTAL.talent.talentId
(intra-format chain)
WTAL.talent.rankSpellIds[] -> WSPL.entry.spellId
(spell granted at each rank)
Format:
• magic "WTAL", version 1, little-endian
• per tree: treeId / name / iconPath / requiredClassMask /
talents[] (row, col, maxRank, prereqTalentId+rank,
rankSpellIds[5] zero-padded for unused ranks)
Enums:
• ClassMask: bit positions match canonical CharClasses.dbc
classIds — Warrior / Paladin / Hunter / Rogue / Priest /
DK / Shaman / Mage / Warlock / Druid
API: WoweeTalentLoader::save / load / exists +
WoweeTalent::findTree / findTalent (global lookup across
all trees in the catalog).
Three preset emitters showcase tree shapes:
• makeStarter — 1 small tree (3-talent vertical chain)
• makeWarrior — 3 trees (Arms 4 / Fury 4 / Protection 3)
with WSPL cross-refs at capstones
(Mortal Strike -> WSPL 12294, Battle Shout
-> WSPL 6673, Thunder Clap -> WSPL 6343)
• makeMage — 3 trees (Arcane / Fire / Frost) with
capstones referencing Frostbolt 116 /
Fireball 133 / Blink 1953 from WSPL
CLI added (5 flags, 571 documented total now):
--gen-talents / --gen-talents-warrior / --gen-talents-mage
--info-wtal / --validate-wtal
Validator catches: tree+talent ids=0 or duplicates, empty
tree name, requiredClassMask=0 (every class would see this
tree — usually a typo), maxRank not in 1..5, talent listing
itself as prerequisite, prereqTalentId pointing at a
talent that doesn't exist in this catalog (intra-format
cross-reference resolution), prereqRank=0 or > the prereq
talent's maxRank (catches off-by-one references), gaps in
rankSpellIds progression (rank N has spell but rank N-1
doesn't — usually a typo).
The validator caught a real authoring bug in the makeMage /
makeWarrior presets during smoke testing — initial check
was comparing prereqRank against the WRONG talent's maxRank
(this talent's rather than the prereq's). Fixed in the same
commit by hoisting the check into the cross-reference
resolution pass where the prereq talent is in hand.
2026-05-09 16:33:45 -07:00
src/pipeline/wowee_talents.cpp
feat(pipeline): add WMS (Wowee Map / Area) catalog format
Novel open replacement for Blizzard's Map.dbc + AreaTable.dbc
+ the AzerothCore-style world_zone SQL tables. The 26th open
format added to the editor.
Defines two related kinds of locator in one catalog:
• Maps — top-level worlds (continents / instances / raids /
battlegrounds / arenas) with a friendly name,
type, expansion tag, and player-count cap.
• Areas — sub-zones within maps with friendly names, parent-
area chain, recommended level range, faction-
territory marker (alliance / horde / contested /
both), exploration XP, and an ambient-sound
cross-reference into WSND.
The runtime uses Areas for minimap labels, location strings
under the player frame, "Discover Sub-zone" XP gains, and
ambient-music selection on zone entry.
Cross-references with previously-added formats:
WMS.area.ambienceSoundId -> WSND.entry.soundId
WMS.area.parentAreaId -> WMS.area.areaId (intra-format
sub-zone hierarchy)
WSPN entries are tied to WMS.area boundaries by
world position (no direct ID — the runtime resolves
position -> area at lookup time)
Format:
• magic "WMSX", version 1, little-endian
• maps[] (each): mapId / name / shortName / mapType /
expansionId / maxPlayers
• areas[] (each): areaId / mapId / parentAreaId / name /
minLevel..maxLevel / factionGroup / explorationXP /
ambienceSoundId
Enums:
• MapType (5): Continent / Instance / Raid / Battleground / Arena
• ExpansionId (5): Classic / Tbc / Wotlk / Cata / Mop
• FactionGroup: Both / Alliance / Horde / Contested
(PvP-flagging zone)
API: WoweeMapsLoader::save / load / exists +
WoweeMaps::findMap / findArea.
Three preset emitters showcase the catalog shape:
• makeStarter — 1 continent + 3 areas with parent chain
(Goldshire is a sub-zone of Elwynn Forest)
• makeClassic — 2 continents + Deadmines instance + 6
areas (Stormwind/Elwynn/Goldshire/Westfall/
Duskwood/Teldrassil/Deadmines) with WSND
ambient-sound refs
• makeBgArena — Alterac Valley (40-player BG) + Nagrand
Arena (5v5 with maxPlayers=10)
CLI added (5 flags, 578 documented total now):
--gen-maps / --gen-maps-classic / --gen-maps-bgarena
--info-wms / --validate-wms
Validator catches: empty map name, unknown mapType / expansion,
BG/Arena with maxPlayers=0 (no participant cap), area ids=0
+ duplicates, empty area name, maxLevel < minLevel, areas
referencing non-existent maps, parentAreaId chains crossing
maps (sub-zones must be on the same world), self-parent.
2026-05-09 16:40:00 -07:00
src/pipeline/wowee_maps.cpp
feat(pipeline): add WCHC (Wowee Character Classes/Races) format
Novel open replacement for Blizzard's CharClasses.dbc +
CharRaces.dbc + CharStartOutfit.dbc trio. The 27th open
format added to the editor — completes the foundational
character-creation surface.
One file holds three flat arrays:
• classes — playable classes (Warrior / Mage / etc.) with
power type (mana/rage/focus/energy/runic),
base HP+power scaling, faction availability
• races — playable races with faction (Alliance/Horde/
Neutral), starting map+zone, default language
spell, base stats, racial mount spell
• outfits — starting gear loadout per (class, race, gender)
triple, listing item IDs and display slots
Cross-references with previously-added formats:
WCHC.race.startingMapId -> WMS.map.mapId
WCHC.race.startingZoneAreaId -> WMS.area.areaId
WCHC.race.defaultLanguageSpellId -> WSPL.entry.spellId
WCHC.race.mountSpellId -> WSPL.entry.spellId
WCHC.outfit.items.itemId -> WIT.entry.itemId
The starter preset's outfits use real WIT itemIds (1=Worn
Shortsword, 2=Linen Vest, 3=Healing Potion) so the demo
content stack is consistent: a freshly created Human Warrior
in WCHC starts with WIT items 1/2/3, drops them on death
into a WLOT-tracked corpse loot, and can be respawned via
WSPN, etc.
Format:
• magic "WCHC", version 1, little-endian
• classes[]: classId / name / icon / powerType / display /
baseHP+perLevel / basePower+perLevel / factionAvailability
• races[]: raceId / name / icon / factionId / male+female
displayId / 5 base stats / startingMap+zone /
defaultLanguage+mount spell IDs
• outfits[]: classId+raceId+gender + items[]
(each: itemId + displaySlot)
Enums:
• PowerType (6): Mana / Rage / Focus / Energy / RunicPower / Runes
• RaceFaction (3): Alliance / Horde / Neutral
• Gender: Male / Female
• FactionAvailability bitmask: AvailableAlliance, AvailableHorde
API: WoweeCharsLoader::save / load / exists +
WoweeChars::findClass / findRace / findOutfit (by class+race+gender).
CLI added (5 flags, 585 documented total now):
--gen-chars / --gen-chars-alliance / --gen-chars-allraces
--info-wchc / --validate-wchc
Validator catches: ids unique, baseHealth=0 (instant-death
character), factionAvailability=0 (no faction can pick),
empty names, factionId out of range, outfit references to
non-existent class/race ids (cross-format resolution),
gender > 1, outfit items with itemId=0, outfit with no
items (warning — naked character).
2026-05-09 16:47:04 -07:00
src/pipeline/wowee_chars.cpp
feat(pipeline): add WTKN (Wowee Token catalog) format
Novel open replacement for Blizzard's Currency.dbc +
CurrencyCategory.dbc + CurrencyTypes.dbc + the AzerothCore-
style player_currency SQL tables. The 28th open format
added to the editor.
Defines secondary currency tokens beyond gold: Honor Points
(PvP), Arena Points (rated PvP), Marks of Honor (per
battleground), faction reputation tokens, holiday-event
currencies. Each token has a balance cap, optional weekly
cap (regenerating earnings limit), and a category for
grouping in the player's currency tab.
Cross-references:
WTRN.item.extendedCost -> WTKN.entry.tokenId
(vendors can charge in tokens
instead of copper — when
extendedCost > 0 the runtime
looks up the matching token)
Format:
• magic "WTKN", version 1, little-endian
• per token: tokenId / name / description / iconPath /
category / maxBalance / weeklyCap / flags
Enums:
• Category (6): Misc / Pvp / Reputation / Crafting /
Seasonal / Holiday
• Flags: AccountWide / Tradeable / HiddenUntilEarned /
ResetsOnLogout / ConvertsToGold
API: WoweeTokenLoader::save / load / exists / findById.
Three preset emitters showcase typical token shapes:
• makeStarter — 3 tokens (Honor / Marks / Stormwind Guard
rep) covering Pvp + Reputation categories
• makePvp — full PvP set: Honor (75k) + Arena (5k +
weekly 1500) + 6 BG marks of honor for
classic + TBC + WotLK battlegrounds
• makeSeasonal — 4 holiday tokens (Tricky Treats /
Brewfest / Coin of Ancestry / Stranger's
Gift) all flagged ResetsOnLogout to make
them event-bound
CLI added (5 flags, 592 documented total now):
--gen-tokens / --gen-tokens-pvp / --gen-tokens-seasonal
--info-wtkn / --validate-wtkn
Validator catches: tokenId=0 + duplicates, empty name,
unknown category, weeklyCap > maxBalance (cap unreachable),
ResetsOnLogout + AccountWide combo (incoherent — account
state survives logout by definition).
2026-05-09 16:53:11 -07:00
src/pipeline/wowee_tokens.cpp
feat(pipeline): add WTRG (Wowee Area Trigger) format
Novel open replacement for Blizzard's AreaTrigger.dbc +
AreaTriggerTeleport.dbc + the AzerothCore-style
areatrigger_template / areatrigger_teleport SQL tables.
The 29th open format added to the editor.
Defines proximity-based event zones — when a player enters
a defined region (box or sphere), the runtime fires the
trigger's action: teleport to another map, award
exploration XP for a quest, run a server script, gate an
instance entrance behind a key item, mark a PvP boundary,
or simply display a "Discovered: {area name}" banner.
Cross-references with previously-added formats — every
trigger field has a real format target:
WTRG.entry.mapId / areaId -> WMS.map.mapId / WMS.area.areaId
WTRG.actionTarget (Teleport) -> WMS.mapId
WTRG.actionTarget (QuestExploration) -> WQT.questId
WTRG.requiredQuestId -> WQT.entry.questId
WTRG.requiredItemId -> WIT.entry.itemId (key)
Format:
• magic "WTRG", version 1, little-endian
• per trigger: triggerId / mapId / areaId / name /
center vec3 / shape / kind / boxDims vec3 / radius /
actionTarget / dest vec3 / destOrientation /
requiredQuestId / requiredItemId / minLevel
Enums:
• Shape (2): Box / Sphere
• Kind (7): Teleport / QuestExploration / Script /
InstanceEntrance / AreaName / CombatStartZone /
Waypoint
API: WoweeTriggerLoader::save / load / exists / findById.
Three preset emitters showcase common trigger shapes:
• makeStarter — area-name + quest-exploration with
cross-ref to WQT 100 ("Investigate the
Camp")
• makeDungeon — outdoor area-name + portal-style
InstanceEntrance with Deadmines key
gate (WIT itemId 5200, matches
WLCK.makeDungeon's Boss Vault Seal) +
interior exit teleport back outdoors
• makeFlightPath — 2 sphere waypoints near flight masters
so the runtime can auto-open the
flight UI on proximity (matches WTAX
starter node positions)
CLI added (5 flags, 601 documented total now):
--gen-triggers / --gen-triggers-dungeon / --gen-triggers-flightpath
--info-wtrg / --validate-wtrg
Validator catches: triggerId=0 + duplicates, unknown shape /
kind, non-finite center, sphere with radius<=0, box with
all-zero half-extents, teleport / instance with dest=(0,0,0)
(silently does nothing — usually a typo), QuestExploration
without an actionTarget questId.
2026-05-09 17:01:43 -07:00
src/pipeline/wowee_triggers.cpp
feat(pipeline): add WTIT (Wowee Title catalog) format
Novel open replacement for Blizzard's CharTitles.dbc + the
AzerothCore-style character_title SQL table. The 30th open
format added to the editor.
Defines the player-display titles awarded for completing
achievements ("the Versatile"), reaching PvP ranks
("Sergeant Major" / "Stone Guard"), participating in raids
("Champion of the Naaru"), levelling a profession ("Master
Locksmith"), or seasonal events ("Brewmaster", "the
Hallowed").
Closes a long-standing gap: WACH.entry.titleReward has been
a free-form string since batch 116 with no formal catalog
to resolve against. WTIT systematizes those strings into a
real catalog — the runtime resolves WACH.titleReward to a
WTIT entry by name, then displays the titleId in the player
title selector.
Cross-references:
WACH.entry.titleReward (string) ~= WTIT.entry.name
(string match — runtime
resolves achievement-
granted titles by
looking up matching WTIT
entry by name)
Format:
• magic "WTIT", version 1, little-endian
• per title: titleId / name / nameMale / nameFemale /
iconPath / prefix (suffix vs prefix display) /
category / sortOrder
Enums:
• Category (8): Achievement / Pvp / Raid / ClassTitle /
Event / Profession / Lore / Custom
API: WoweeTitleLoader::save / load / exists +
WoweeTitle::findById / findByName.
Three preset emitters showcase typical title catalogs:
• makeStarter — 4 titles (Versatile / Sergeant /
Champion / Hallowed) covering 4
categories
• makePvp — 28-title classic Honor System ladder
(14 Alliance ranks Private->Grand
Marshal + 14 Horde ranks Scout->High
Warlord)
• makeAchievement — 8 achievement titles including "the
Versatile" matching WACH.makeMeta's
achievement 250 titleReward + capstone
profession titles
CLI added (5 flags, 608 documented total now):
--gen-titles / --gen-titles-pvp / --gen-titles-achievement
--info-wtit / --validate-wtit
Validator catches: titleId=0 + duplicates, empty name,
unknown category, gender variants set on only one side
(causes mixed-gender display when the runtime falls back to
canonical for the unset side).
2026-05-09 17:07:56 -07:00
src/pipeline/wowee_titles.cpp
feat(pipeline): add WSEA (Wowee Seasonal Event) format
Novel open replacement for Blizzard's GameEvents.dbc + the
AzerothCore-style game_event / game_event_creature /
game_event_gameobject SQL tables. The 31st open format
added to the editor.
Calendar-based content: holidays (Hallow's End, Winter's
Veil), recurring promotional events (Children's Week,
Lunar Festival, Brewfest), one-time anniversaries, and
XP-bonus weekends. Each event has a start date, duration,
optional recurrence (yearly / monthly / weekly), faction
restriction, optional XP bonus, and a reward currency
cross-reference into WTKN.
Cross-references with previously-added formats:
WSEA.entry.tokenIdReward -> WTKN.entry.tokenId
(the seasonal currency the
event hands out — Tricky
Treats during Hallow's End,
Brewfest Tokens during
Brewfest, etc.)
The yearly preset's tokenIdReward values (200/201/202/203)
deliberately match WTKN.makeSeasonal's seasonal token ids
so the demo content stack already wires together: WSEA
yearly events grant WTKN tokens that vendors can charge in
via WTRN.item.extendedCost.
Format:
• magic "WSEA", version 1, little-endian
• per event: eventId / name / description / iconPath /
announceMessage / startDate (Unix epoch seconds) /
duration_seconds / recurrenceDays (0=one-shot, 365=yearly) /
holidayKind / factionGroup / bonusXpPercent / tokenIdReward
Enums:
• HolidayKind (7): Combat / Collection / Racial /
Anniversary / Fishing / Cosmetic /
WorldEvent
• FactionGroup (3): Both / Alliance / Horde
API: WoweeEventLoader::save / load / exists / findById.
Three preset emitters showcase typical event shapes:
• makeStarter — 3 events covering Combat /
Fishing / Anniversary kinds
• makeYearly — 4 yearly holidays with full WTKN
cross-refs (Hallow's End / Brewfest /
Lunar Festival / Winter's Veil)
• makeBonusWeekends — 3 monthly Fri-Sun bonus tiers
(50% / 100% / 200% RAF-style)
CLI added (5 flags, 614 documented total now):
--gen-events / --gen-events-yearly / --gen-events-weekends
--info-wsea / --validate-wsea
Validator catches: eventId=0 + duplicates, empty name,
unknown holidayKind / factionGroup, duration_seconds=0
(event never runs), duration > recurrence period (events
would overlap themselves on next iteration), bonusXpPercent
> 200 (very high — verify intentional).
2026-05-09 17:14:46 -07:00
src/pipeline/wowee_events.cpp
feat(pipeline): add WMOU (Wowee Mount catalog) format
Novel open replacement for Blizzard's Mount.dbc +
MountCapability.dbc + MountType.dbc + the mount-related
subsets of Spell.dbc / Item.dbc. The 32nd open format added
to the editor.
Defines all summonable steeds: ground mounts, flying mounts,
swimming mounts, racial mounts (Tauren Plainsrunner for
druids), and class mounts (Warlock dreadsteed, Paladin
charger). Each mount has a summon spell, optional teach
item, riding skill prerequisite, speed bonus, and faction
/ race availability mask.
Cross-references with previously-added formats:
WMOU.entry.summonSpellId -> WSPL.entry.spellId
WMOU.entry.itemIdToLearn -> WIT.entry.itemId
WMOU.entry.requiredSkillId -> WSKL.entry.skillId
(Riding skill ID 762)
WCHC.race.mountSpellId ~= WMOU.entry.summonSpellId
(loose match by spellId)
Format:
• magic "WMOU", version 1, little-endian
• per mount: mountId / name / description / icon /
displayId / summonSpellId / itemIdToLearn /
requiredSkillId+Rank / speedPercent / mountKind /
factionId / categoryId / raceMask
Enums:
• Kind (5): Ground / Flying / Swimming / Hybrid /
Aquatic
• Faction (3): Both / Alliance / Horde
• Category (8): Common / Epic / Racial / Event /
Achievement / Pvp / Quest / ClassMount
API: WoweeMountLoader::save / load / exists / findById.
Three preset emitters showcase typical mount catalogs:
• makeStarter — 3 mounts (ground horse + epic flying
gryphon + aquatic riding turtle)
• makeRacial — 6 racial mounts (4 Alliance: Pinto / Ram /
Frostsaber / Mechanostrider; 2 Horde:
Dire Wolf / Skeletal Horse) with raceMask
gating per WCHC race bit positions
• makeFlying — 4 flying mounts spanning Common (60%) ->
Epic (100%) -> Achievement (280%) -> Pvp
(310%) speed tiers
CLI added (5 flags, 621 documented total now):
--gen-mounts / --gen-mounts-racial / --gen-mounts-flying
--info-wmou / --validate-wmou
Validator catches: mountId=0 + duplicates, empty name,
summonSpellId=0 (mount cannot be cast), unknown enum values,
speedPercent=0 (no speed bonus), flying mount with
requiredSkillRank<150 (player can't fly), Racial category
without raceMask (any race could use — usually a typo).
2026-05-09 17:23:00 -07:00
src/pipeline/wowee_mounts.cpp
feat(pipeline): add WBGD (Wowee Battleground Definition) format
Novel open replacement for Blizzard's BattlemasterList.dbc +
PvpDifficulty.dbc + the AzerothCore-style
battleground_template SQL tables. The 33rd open format
added to the editor.
Defines per-BG gameplay rules: player count brackets,
score-to-win, time limit, objective type (annihilation /
capture flag / control nodes / king of hill / resource race
/ carry object), per-team start positions, respawn timer,
and the WTKN currency token awarded on win.
Cross-references with previously-added formats:
WBGD.entry.mapId -> WMS.map.mapId
(where mapType=Battleground)
WBGD.entry.markTokenId -> WTKN.entry.tokenId
(Mark of Honor for that BG)
The classic preset's markTokenId fields (102/103/104)
deliberately match WTKN.makePvp's "Mark of Honor: Warsong
Gulch / Arathi Basin / Alterac Valley" token ids — so the
demo content stack already wires together: WBGD.scoreToWin
reached → grant WTKN mark → which a vendor in WTRN can
charge in via item.extendedCost.
Format:
• magic "WBGD", version 1, little-endian
• per BG: battlegroundId / mapId / name / description /
objectiveKind / min+maxPlayersPerSide /
minLevel..maxLevel / scoreToWin / timeLimitSeconds /
bracketSize / allianceStart vec3 + facing /
hordeStart vec3 + facing / respawnTimeSeconds /
markTokenId
Enums:
• ObjectiveKind (6): Annihilation / CaptureFlag /
ControlNodes / KingOfHill /
ResourceRace / CarryObject
API: WoweeBattlegroundLoader::save / load / exists /
findById.
Three preset emitters showcase typical BG shapes:
• makeStarter — 1 king-of-hill BG (10v10, 3-cap to win)
• makeClassic — 3 classic BGs with authentic player
counts, level brackets, scoring, and
WTKN cross-refs (Warsong Gulch CTF /
Arathi Basin nodes / Alterac Valley
resource race)
• makeArena — 3 arena formats (Nagrand 2v2 / Blade's
Edge 3v3 / Lordaeron 5v5) — annihilation
objective + no respawn + 25 min cap
CLI added (5 flags, 628 documented total now):
--gen-bg / --gen-bg-classic / --gen-bg-arena
--info-wbgd / --validate-wbgd
Validator catches: bgId=0 + duplicates, empty name, unknown
objectiveKind, player count=0, min>max counts/levels,
scoreToWin=0 (no win condition), non-annihilation BG with
respawnTimeSeconds=0 (losing side cannot recover).
2026-05-09 17:30:59 -07:00
src/pipeline/wowee_battlegrounds.cpp
feat(pipeline): add WMAL (Wowee Mail Template) format
Novel open replacement for AzerothCore-style
mail_loot_template SQL + the in-game mail subset of the
inventory + currency systems. The 34th open format added
to the editor.
Defines templated mail messages with currency + item
attachments. Triggered by quest reward delivery (overflow
when bag is full), auction house bid wins / sales,
achievement reward attachments, GM correspondence, holiday
event mailings (Brewfest samples, Hallow's End candy), and
returned-mail-on-rejection.
Cross-references with previously-added formats:
WMAL.entry.senderNpcId -> WCRT.entry.creatureId
WMAL.entry.attachments.itemId -> WIT.entry.itemId
Format:
• magic "WMAL", version 1, little-endian
• per template: templateId / senderNpcId / subject / body /
senderName / moneyCopperAttached / categoryId / cod /
returnable / expiryDays / attachments[] (each: itemId +
quantity)
Enums:
• Category (8): QuestReward / Auction / GmCorrespondence /
AchievementReward / EventMailing / Raffle /
ScriptDelivery / ReturnedMail
API: WoweeMailLoader::save / load / exists / findById.
Three preset emitters showcase typical mail templates:
• makeStarter — 3 templates (quest overflow / auction won /
GM gift) covering the 3 most common
categories
• makeHoliday — 4 holiday samples that cross-reference the
WTKN seasonal token IDs (200=Tricky Treats,
201=Brewfest, 202=Coin of Ancestry,
203=Stranger's Gift) so the demo content
stack ships a full holiday onboarding
experience
• makeAuction — 5-template auction-house family (outbid /
won / sold / expired / cancelled) — runtime
fills in actual bid amounts / sold items
at send time
CLI added (5 flags, 635 documented total now):
--gen-mail / --gen-mail-holiday / --gen-mail-auction
--info-wmal / --validate-wmal
Validator catches: templateId=0 + duplicates, empty subject,
neither senderNpcId nor senderName set (no displayable
sender), unknown category, expiryDays=0 (mail expires
immediately), cod=1 with no money attached (free COD),
empty mail in categories where the runtime doesn't fill in
content (skips Auction / GmCorrespondence / ReturnedMail
where empty templates are intentional).
Two bugs caught + fixed during smoke-test on the auction
preset:
• print formatting glued the `0` from senderNpcId after
the senderName when no NPC was set (rendered as
"Postmaster0" instead of "Postmaster") — fixed with an
explicit if/else split
• validator's "no money + no items" warning was too
aggressive for the Auction category, where templates
are intentionally informational and the runtime fills
in the real values — added Auction + ReturnedMail to
the skip list
2026-05-09 17:41:03 -07:00
src/pipeline/wowee_mail.cpp
feat(pipeline): add WGEM (Wowee Gem / Enchantment) format
Novel open replacement for Blizzard's ItemEnchantment.dbc +
GemProperties.dbc + SpellItemEnchantment.dbc. The 35th
open format added to the editor.
Defines two related kinds of item enhancement in one
catalog:
• Gems — socketable jewelry pieces with color
(red / blue / yellow / meta) that fit
into gear sockets, granting stats or
triggering passive spells when socketed
• Enchantments — persistent buffs applied to weapon /
armor pieces, either by an enchanter
spell or by an item proc (Mongoose,
Crusader, Berserking)
Cross-references with previously-added formats:
WGEM.gem.itemIdToInsert -> WIT.entry.itemId
WGEM.gem.spellId -> WSPL.entry.spellId
WGEM.enchantment.spellId -> WSPL.entry.spellId
Format:
• magic "WGEM", version 1, little-endian
• gems[]: gemId / itemIdToInsert / name / color /
statType + statValue / requiredItemQuality / spellId
• enchantments[]: enchantId / name / description /
iconPath / enchantSlot / statType + statValue /
spellId / durationSeconds / chargeCount
Enums:
• Color (8): Meta / Red / Yellow / Blue / Purple /
Green / Orange / Prismatic
• EnchantSlot (5): Permanent / Temporary / SocketColor /
Ring / Cloak
API: WoweeGemLoader::save / load / exists +
WoweeGem::findGem / findEnchant.
Three preset emitters showcase common shapes:
• makeStarter — 3 gems (one per primary color) +
2 enchantments (proc + stat)
• makeGemSet — 6-gem full color palette covering
primary + secondary combinations
• makeEnchants — 5 enchant variants spanning slots
(Mongoose / Deadly Poison / stats ring /
cloak / Berserking)
CLI added (5 flags, 642 documented total now):
--gen-gems / --gen-gems-set / --gen-gems-enchants
--info-wgem / --validate-wgem
Validator catches: ids=0 + duplicates, empty name, color /
slot out of range, stat-only entries with statValue=0 (gem
provides nothing), chargeCount > 0 on non-Temporary
enchant slots (charges silently ignored at runtime).
The validator caught a real preset issue on first run —
the proc enchants (Mongoose / Deadly Poison / Berserking)
had spellId=0 and statValue=0, providing nothing. Fixed by
adding placeholder spellIds in the 28000-29000 range, with
a comment noting they resolve to real WSPL proc spells
when the spell catalog is extended.
2026-05-09 18:01:48 -07:00
src/pipeline/wowee_gems.cpp
feat(pipeline): add WGLD (Wowee Guild) catalog format
Novel open replacement for AzerothCore-style guild +
guild_member + guild_rank + guild_bank_tab + guild_perk
SQL tables. The 36th open format added to the editor.
Each guild entry holds the complete social-organization
state: header (name, leader, faction, MOTD, info,
creation date, level + experience, bank money, packed
emblem), rank ladder with permissions bitmask + daily
withdraw caps, member roster with rank + join date +
public/officer notes, bank tabs with per-tab and per-rank
deposit / withdraw / view permission masks, and purchased
guild perks referencing WSPL spell IDs.
Cross-references with previously-added formats:
WGLD.entry.factionId ~ WCHC.race.factionId
(guilds are faction-locked)
WGLD.entry.perks.spellId -> WSPL.entry.spellId
Format:
• magic "WGLD", version 1, little-endian
• per guild: header (12 scalar fields + 4 strings) +
ranks[] + members[] + bankTabs[] + perks[]
• per rank: rankIndex / name / permissionsMask /
moneyPerDayCopper
• per member: characterName / rankIndex / joinedDate /
publicNote / officerNote
• per bankTab: tabIndex / name / iconPath /
deposit+withdraw+view permission masks
• per perk: perkId / name / spellId / requiredGuildLevel
Enums:
• Faction (2): Alliance / Horde
• RankPermissionFlags (14): GuildChat / OfficerChat /
Invite / Remove / Promote /
Demote / SetMotd /
EditPublicNote /
EditOfficerNote / ViewBank /
Deposit / Withdraw / Disband /
RepairFromBank
API: WoweeGuildLoader::save / load / exists / findById +
shared addDefaultRanks helper used by both starter and
faction-pair presets.
Three preset emitters:
• makeStarter — 1 small guild, default 5-rank ladder
(GM/Officer/Veteran/Member/Initiate),
3 members borrowing names from WCRT
merchants for cross-format consistency
• makeFull — 1 fleshed-out guild: 6 ranks (with
Recruit added) + 8 members + 4 bank
tabs (officer-only withdraw on tabs
3+4) + 3 perks referencing WSPL
spell IDs (Heroic Strike / Battle
Shout / Thunder Clap as placeholder
perk procs)
• makeFactionPair — 2 parallel guilds, one Alliance + one
Horde, with identical rank structures
CLI added (5 flags, 649 documented total now):
--gen-guilds / --gen-guilds-full / --gen-guilds-pair
--info-wgld / --validate-wgld
Validator catches: guildId=0 + duplicates, empty name /
leaderName, factionId out of range, no ranks (members can't
exist without a rank ladder), member.rankIndex exceeding
the highest defined rank (intra-format cross-reference
resolution), duplicate bank tabIndices, perks with
spellId=0 (perk does nothing).
2026-05-09 18:10:45 -07:00
src/pipeline/wowee_guilds.cpp
feat(pipeline): add WPCD (Wowee Player Condition) format
Novel open replacement for Blizzard's PlayerCondition.dbc +
the AzerothCore-style condition_template SQL tables. The
37th open format added to the editor.
Defines reusable boolean conditions that other formats can
reference for gating: "player has quest X completed",
"player level >= N", "player class is mage", "player has
item Y in inventory", "WSEA event Z is active".
Conditions can be grouped and combined with AND/OR
aggregators on a per-group basis: a quest-giver gossip
option that says "show only to level 60 alliance mages
who completed quest 1234" composes 4 conditions sharing
the same groupId with AND aggregation. The runtime walks
each group, applies the group's aggregator, and returns
the boolean result to the caller.
Cross-references with previously-added formats — the
targetId field has a polymorphic interpretation by kind:
WPCD.targetId (kind=QuestCompleted/Active) -> WQT.questId
WPCD.targetId (kind=HasItem) -> WIT.itemId
WPCD.targetId (kind=HasSpell) -> WSPL.spellId
WPCD.targetId (kind=HasAchievement) -> WACH.achievementId
WPCD.targetId (kind=AreaId) -> WMS.areaId
WPCD.targetId (kind=EventActive) -> WSEA.eventId
WPCD.targetId (kind=HasTitle) -> WTIT.titleId
WPCD.targetId (kind=FactionRep) -> WFAC.factionId
WPCD.targetId (kind=Class/Race) -> WCHC class/race id
Future format extensions can reference WPCD.conditionId in
their own gating fields — WTRG triggers gated by player
state, WGSP options visible only when conditions are met,
WMOU summon spells condition-gated by quest progress, etc.
Format:
• magic "WPCD", version 1, little-endian
• per condition: conditionId / groupId (0 = standalone) /
name / description / kind / aggregator / negated /
targetId / minValue / maxValue
Enums:
• Kind (17): AlwaysTrue / AlwaysFalse / QuestCompleted /
QuestActive / HasItem / HasSpell / MinLevel /
MaxLevel / ClassMatch / RaceMatch /
FactionRep / HasAchievement / TeamSize /
GuildLevel / EventActive / AreaId / HasTitle
• Aggregator (2): And / Or
API: WoweeConditionLoader::save / load / exists / findById.
Three preset emitters showcase typical usage:
• makeStarter — 4 standalone conditions covering the most
common kinds (quest-done / has-item /
min-level / class)
• makeGated — 5 conditions in 2 groups demonstrating
AND-aggregation (alliance + mage + lvl 60)
and OR-aggregation (did quest 1 OR quest 100)
• makeEvent — 3 event-gated conditions cross-referencing
WSEA event IDs (Hallow's End / Brewfest /
Winter's Veil)
CLI added (5 flags, 656 documented total now):
--gen-conditions / --gen-conditions-gated / --gen-conditions-event
--info-wpcd / --validate-wpcd
Validator catches: conditionId=0 + duplicates, kind /
aggregator out of range, kinds requiring targetId having
target=0 (skips AlwaysTrue/False, MinLevel/MaxLevel,
TeamSize, GuildLevel which use min/max instead), TeamSize
with min > max.
2026-05-09 18:18:27 -07:00
src/pipeline/wowee_conditions.cpp
feat(pipeline): add WPET (Wowee Pet System) catalog
Novel open replacement for AzerothCore-style pet_template +
pet_levelstats SQL + the pet-related subsets of
CreatureFamily.dbc + SpellFamilyName.dbc. The 38th open
format added to the editor.
Defines two related kinds of player-controlled NPCs in
one catalog:
• Pet families — hunter pet families (Wolf / Cat / Bear /
Boar / Raptor / Spider / etc.) with
per-family ability sets, base stat
multipliers, and diet preferences
• Warlock minions — Imp / Voidwalker / Succubus /
Felhunter / Felguard, each with
their own summon spell, creature
template, and ability list
Cross-references with previously-added formats:
WPET.family.familyId -> WCRT.entry.familyId
(matches creature family)
WPET.family.abilities.spellId -> WSPL.entry.spellId
WPET.minion.summonSpellId -> WSPL.entry.spellId
WPET.minion.creatureId -> WCRT.entry.creatureId
(used for stat scaling)
WPET.minion.abilities.spellId -> WSPL.entry.spellId
The starter preset's familyIds (1=Wolf, 2=Cat) match
WCRT::FamilyId enum values, so a hunter taming a wolf via
WCRT links straight through to WPET ability sets.
Format:
• magic "WPET", version 1, little-endian
• families[]: familyId / name / description / icon /
petType / baseAttackSpeed / damageMultiplier /
armorMultiplier / dietMask / abilities[]
• minions[]: minionId / name / summonSpellId / creatureId /
abilities[] (each: spellId / rank / autocastDefault)
Enums:
• PetType (3): Cunning / Ferocity / Tenacity
(WotLK+ talent tree categorization)
• DietFlags: Meat / Fish / Bread / Cheese / Fruit / Fungus
API: WoweePetLoader::save / load / exists +
WoweePet::findFamily / findMinion + dietMaskName helper
that decodes a dietMask into a "meat+fish" string.
Three preset emitters showcase typical pet catalogs:
• makeStarter — 2 hunter families (Wolf + Cat) with full
3-ability sets + 1 warlock Imp
• makeHunter — 8 classic hunter families covering all
3 petType categories with appropriate
diet masks
• makeWarlock — 5 warlock minions each with summon spell
ID and creatureId pointing into WCRT
CLI added (5 flags, 663 documented total now):
--gen-pets / --gen-pets-hunter / --gen-pets-warlock
--info-wpet / --validate-wpet
Validator catches: ids=0 + duplicates, empty name, petType
out of range, baseAttackSpeed<=0 (would divide by zero in
DPS calc), dietMask=0 (pet cannot be fed for happiness),
minion missing summonSpellId / creatureId.
2026-05-09 18:27:02 -07:00
src/pipeline/wowee_pets.cpp
feat(pipeline): add WAUC (Wowee Auction House) catalog
Novel open replacement for Blizzard's AuctionHouse.dbc +
the AzerothCore-style auctionhouse / auctionhousebot SQL
tables. The 39th open format added to the editor.
Defines per-house rules for the auction system: faction
access, deposit rate (basis points of buyout price), house
cut on successful sale, three listing duration tiers with
per-tier deposit multipliers, disallowed item-class bitmask,
and the auctioneer NPC.
Cross-references with previously-added formats:
WAUC.entry.auctioneerNpcId -> WCRT.entry.creatureId
(Auctioneer-flagged NPC)
WAUC.entry.disallowedClassMask
bitmask of WIT.Class values
that may not be auctioned at
this house
The faction-pair preset captures the canonical asymmetry:
faction houses charge 5% on a successful sale while neutral
houses charge 15% — the cross-faction tax that makes
neutral AHs profitable for goblins.
Format:
• magic "WAUC", version 1, little-endian
• per house: houseId / auctioneerNpcId / name /
factionAccess / baseDepositRateBp / houseCutRateBp /
maxBidCopper / 3 duration hours + 3 deposit multipliers /
disallowedClassMask
Enums:
• FactionAccess (4): Alliance / Horde / Neutral / Both
• Rates use basis points: 10000 = 100%
API: WoweeAuctionLoader::save / load / exists / findById.
Three preset emitters showcase typical auction setups:
• makeStarter — 1 neutral house with default 12h /
24h / 48h tiers
• makeFactionPair — 3 houses (Stormwind / Orgrimmar /
Booty Bay) with auctioneer NPC IDs
+ canonical faction-vs-neutral cut
rates
• makeRestricted — 1 house disallowing Containers (1) +
Quest items (12) + Keys (13) with
tighter durations + 1000g bid cap
CLI added (5 flags, 670 documented total now):
--gen-auction / --gen-auction-pair / --gen-auction-restricted
--info-wauc / --validate-wauc
Validator catches: houseId=0 + duplicates, empty name,
factionAccess out of range, duration tier=0, durations not
in short<=medium<=long order, houseCutRateBp >= 100% (seller
loses money on a sale), warns on >50% cut.
2026-05-09 18:34:54 -07:00
src/pipeline/wowee_auction.cpp
feat(pipeline): add WCHN (Wowee Chat Channel) catalog
Novel open replacement for Blizzard's ChatChannels.dbc +
the AzerothCore-style chat_channel SQL tables. The 40th
open format added to the editor.
Defines the world chat channel system: General, Trade,
LookingForGroup, GuildRecruitment, LocalDefense, plus
per-zone area channels and custom user-created channels.
Each channel has access rules (faction / level), join
behavior (auto vs opt-in), broadcast policy (announce /
moderated), and optional area / map gating that auto-joins
or auto-leaves the channel as the player moves.
Cross-references with previously-added formats:
WCHN.entry.areaIdGate -> WMS.area.areaId
(channel auto-attaches in this area)
WCHN.entry.mapIdGate -> WMS.map.mapId
(channel auto-attaches on this map)
Format:
• magic "WCHN", version 1, little-endian
• per channel: channelId / name / description /
channelType / factionAccess / autoJoin / announce /
moderated / minLevel / areaIdGate / mapIdGate
Enums:
• ChannelType (10): AreaLocal / Zone / Continent / World /
Trade / LookingForGroup / GuildRecruit /
LocalDefense / Custom / Pvp
• FactionAccess (3): Alliance / Horde / Both
API: WoweeChannelLoader::save / load / exists / findById.
Three preset emitters:
• makeStarter — 4 stock channels (General Zone +
Trade + LFG + GuildRecruit) with
default autoJoin policies
• makeCity — 5 city-specific channels (3 Stormwind +
2 Orgrimmar) with mapId / areaId gates
so they auto-attach on entry
• makeModerated — 3 moderated / restricted channels
(LocalDefense level 10+, WorldDefense
moderated, RaidCoordination level 60+)
CLI added (5 flags, 677 documented total now):
--gen-channels / --gen-channels-city / --gen-channels-moderated
--info-wchn / --validate-wchn
Validator catches: channelId=0 + duplicates, empty name,
unknown channelType / factionAccess, world / continent
channel with area or map gate (gate is silently ignored at
runtime — usually a typo), minLevel=0 (no level gate at all).
2026-05-09 18:43:26 -07:00
src/pipeline/wowee_channels.cpp
feat(pipeline): add WCMS (Wowee Cinematic) catalog
41st open format — replaces Movie.dbc / CinematicCamera.dbc /
CinematicSequences.dbc plus the AzerothCore cinematic_camera SQL
table. Defines pre-rendered videos, in-engine camera flythroughs,
text crawls, and still images, each with a media path, duration,
skippable flag, and a polymorphic trigger that fires on quest
events / class first-login / zone entry / dungeon clear /
achievements / level milestones.
Cross-references with prior formats — triggerTargetId resolves
by triggerKind to WQT.questId / WMS.areaId / WMS.mapId /
WCHC.classId / WACH.achievementId, and soundtrackId points at
WSND.soundId.
CLI: --gen-cinematics (3-entry starter), --gen-cinematics-intros
(4 class intros), --gen-cinematics-quests (3 quest-bound
cinematics referencing demo questIds 1/100/102), --info-wcms,
--validate-wcms with --json variants. Validator catches
id=0/duplicates, empty name/mediaPath, kind/trigger out of
range, missing target id for non-Manual/Login/LevelUp triggers,
zero-duration entries, and non-skippable pre-rendered videos.
2026-05-09 18:50:43 -07:00
src/pipeline/wowee_cinematics.cpp
feat(pipeline): add WGLY (Wowee Glyph) catalog
42nd open format — replaces GlyphProperties.dbc + GlyphSlot.dbc
plus the AzerothCore-style glyph_properties SQL table. Defines
the WotLK glyph system: per-class inscribable glyphs that
modify spell behavior. Each entry pairs a glyph item (the
inscriber's craft output) with the spell aura that applies the
modification, tagged with a Major / Minor / Prime slot type and
a classMask of allowed classes.
Cross-references with prior formats — spellId points at
WSPL.spellId (the aura), itemId points at WIT.itemId (the
inscribed item), and classMask bit positions match the WCHC
classId enum (1=Warrior, 2=Paladin, 3=Hunter, etc).
CLI: --gen-glyphs (3-entry per-role starter), --gen-glyphs-warrior
(6-entry full warrior allotment), --gen-glyphs-universal (4
classMask=All utility glyphs), --info-wgly, --validate-wgly with
--json variants. Validator catches id=0/duplicates, empty name,
spellId=0 (glyph applies no aura), classMask=0 (no class can
inscribe), itemId=0 warning, requiredLevel<25 warning (below
WotLK glyph threshold), and glyphType out-of-range.
2026-05-09 18:55:22 -07:00
src/pipeline/wowee_glyphs.cpp
feat(pipeline): add WVHC (Wowee Vehicle) catalog
43rd open format — replaces Vehicle.dbc + VehicleSeat.dbc plus
the AzerothCore-style vehicle_template SQL tables. Defines
drivable vehicles: tanks, demolishers, motorcycles, gryphons,
choppers, siege weapons, multi-passenger transports. Each entry
pairs a creature template (the rendered model) with a fixed
seat layout — driver / passenger / gunner seats with their own
attachment points, control flags (kSeatDriver / kSeatGunner /
kSeatPassenger / kSeatHidesPlayer / kSeatNoEjectByCC), and
per-seat abilities mounted to the action bar.
Cross-references with prior formats — creatureId points at
WCRT.creatureId (the rendered model), flightCapabilityId points
at WMNT.mountId for shared fly-speed tables, and per-seat
controlSpellId / exitSpellId point at WSPL.spellId.
CLI: --gen-vehicles (3-vehicle starter chopper/wind-rider/tank),
--gen-vehicles-siege (3 siege weapons with control spellIds),
--gen-vehicles-flying (3 flying mounts cross-ref WMNT
flightCapabilityIds), --info-wvhc, --validate-wvhc with --json
variants. Validator catches id=0/duplicates, missing creature,
enum out-of-range, empty seat list, flying-vehicle on wrong
movement (would fall through world), driver-flag exclusivity
(0 or >1 drivers), and duplicate seatIndex within a vehicle.
2026-05-09 18:59:49 -07:00
src/pipeline/wowee_vehicles.cpp
feat(pipeline): add WHOL (Wowee Holiday) catalog
44th open format — replaces Holidays.dbc + HolidayDescriptions.dbc
+ HolidayNames.dbc plus the AzerothCore-style game_event SQL
tables. Defines time-gated world events: seasonal holidays
(Hallow's End / Brewfest / Winter Veil), weekly call-to-arms BG
bonuses, world-PvP windows (Wintergrasp), one-shot specials, and
recurring daily / weekly resets. Each holiday has a recurrence
rule (Annual / Monthly / WeeklyRecur / OneTime), a calendar
window (startMonth + startDay + durationHours), and optional
cross-refs to a feature creature, an intro quest, and a token /
item reward issued during the window.
Cross-references with prior formats — holidayQuestId points at
WQT.questId, bossCreatureId points at WCRT.creatureId,
itemRewardId points at WIT.itemId, and areaIdGate / mapIdGate
point at WMS.areaId / WMS.mapId.
CLI: --gen-holidays (3 seasonal starter), --gen-holidays-weekly
(3 weekly BG call-to-arms windows), --gen-holidays-special (3
world-PvP / lunar / children events), --info-whol, --validate-whol
with --json variants. Validator catches id=0/duplicates, kind /
recurrence out of range, durationHours=0, invalid month/day for
non-weekly recurrence, and calendar-only events (no quest +
boss + reward) as a warning.
2026-05-09 19:05:33 -07:00
src/pipeline/wowee_holidays.cpp
feat(pipeline): add WLIQ (Wowee Liquid Type) catalog
45th open format — replaces LiquidType.dbc plus the
AzerothCore-style terrain liquid descriptor data. Defines
liquid materials used by terrain MCNK liquid layers, WMO
interior pools, and procedurally generated fluid bodies in
custom zones. Each liquid pairs a render material (shader +
texture array + flow vectors + fog color) with gameplay data
(damage spell, raw DPS, ambient + splash audio cross-refs).
Cross-references with prior formats — ambientSoundId and
splashSoundId point at WSND.soundId, damageSpellId points at
WSPL.spellId.
10 liquid kinds (Water / Magma / Slime / OceanSalt / FelFire /
HolyLight / TarOil / AcidBog / FrozenWater / UnderworldGoo)
covering both natural and magical fluids. Per-liquid: viscosity
(0=water, 1=slime), flow direction+speed (radians+units/sec),
fog density+RGB, packed minimap RGBA color.
CLI: --gen-liquids (3-entry classic Water/Lava/Slime starter),
--gen-liquids-magical (4 magical pools incl. fel/holy/cosmic),
--gen-liquids-hazardous (3 high-damage liquids with WSPL DoT
cross-refs), --info-wliq, --validate-wliq with --json variants.
Validator catches id=0/duplicates, missing shader/material,
kind out of range, fog/viscosity outside 0..1, hazardous-kind-
without-damage warning, and Water/OceanSalt-with-damage warning
to flag accidental misconfiguration.
2026-05-09 19:10:03 -07:00
src/pipeline/wowee_liquids.cpp
feat(pipeline): add WANI (Wowee Animation) catalog
46th open format — replaces AnimationData.dbc plus the
hard-coded animation-id tables in M2 model loaders. Defines
named animations (Stand, Walk, Run, Cast, Death, MountIdle,
Fly, ...) with fallback chains, behavior tier (default /
mounted / sitting / aerial / swimming), and weapon-flag
bitmasks that select the correct animation variant when the
model wields 1H / 2H / dual / bow / rifle / wand / etc.
Cross-references with prior formats — fallbackId resolves
within the same WANI catalog (graceful degradation when the
requested animation is absent: Run falls back to Walk,
Attack2H falls back to Attack1H).
10 weapon-flag constants + 6 behavior flags (Looped,
BlendableCycle, Interruptable, MovementSync, OneShot,
PreserveAtEnd). 5 behavior tiers. CLI: --gen-animations
(5 essentials), --gen-animations-combat (8 weapon-typed
attacks + parry + channel), --gen-animations-movement (6
locomotion anims with tier transitions). Validator catches
id-uniqueness, fallback-self-loop, looped-without-duration,
mutually-exclusive Looped+OneShot flags, weaponFlags=0
warning, and unresolved fallback warnings.
Also extends --list-formats and --info-magic with WANI.
2026-05-09 19:19:13 -07:00
src/pipeline/wowee_animations.cpp
feat(pipeline): add WSVK (Wowee Spell Visual Kit) catalog
47th open format — replaces SpellVisualKit.dbc +
SpellVisualEffectName.dbc plus the AzerothCore-style spell
visual SQL data. Defines per-spell visual presentations:
cast-bar effect model, projectile model + travel speed +
arc gravity, impact effect model, hand effect on the caster,
and the animations + sounds that fire at cast / channel /
impact time.
Cross-references with prior formats — castAnimId / impactAnimId
/ precastAnimId point at WANI.animationId, castSoundId /
impactSoundId point at WSND.soundId. Spell catalogs (WSPL)
will reference visualKitId here to bind "what mechanically
happens" to "what plays visually."
CLI: --gen-svk (3-kit Frostbolt/Fireball/HealingTouch starter
showing projectile + AoE + heal patterns), --gen-svk-combat
(5 melee/ranged with WANI animation refs), --gen-svk-utility
(4 portal/hearth/mount/resurrect with no projectile),
--info-wsvk, --validate-wsvk with --json variants. Validator
catches id=0/duplicates, missing name, negative speeds/radii,
projectile-model + speed coherence (model without speed =
never travels; speed without model = invisible), and a
no-effect catch-all (no models + no anims + no sounds).
2026-05-09 19:23:36 -07:00
src/pipeline/wowee_spell_visuals.cpp
feat(pipeline): add WWUI (Wowee World-State UI) catalog
48th open format — replaces WorldStateUI.dbc plus the
AzerothCore-style world_state SQL data. Defines on-screen UI
elements that surface server-side world-state variables: BG
scoreboards (flag captures, base controls), Wintergrasp tank
counters, Eye of the Storm flag-carrier indicator, dungeon
boss progress, world-event collection trackers.
Each entry binds a server-side variableIndex to a UI panel
kind (counter / timer / flag-icon / progress-bar / two-sided
score / custom) gated by mapId+areaId, with optional
alwaysVisible and hideWhenZero flags and a chosen panel
position (top / bottom / top-left / top-right / center).
Cross-references with prior formats — mapId points at
WMS.mapId and areaId points at WMS.areaId.
CLI: --gen-wsui (3-entry BG scoreboard starter for WSG/AB/
EotS), --gen-wsui-wintergrasp (4-entry full Wintergrasp UI),
--gen-wsui-dungeon (3-entry boss/keys/treasure hunt UI),
--info-wwui, --validate-wwui with --json variants. Validator
catches id=0/duplicates, kind/position out of range,
variableIndex=0 warning, alwaysVisible+hideWhenZero conflict
warning, and (mapId, variableIndex) collision warning when
two entries would read the same server slot on the same map.
Also extends --list-formats and --info-magic with WWUI.
2026-05-09 19:32:15 -07:00
src/pipeline/wowee_world_state_ui.cpp
feat(pipeline): add WPCN (Wowee Player Condition) catalog
49th open format — replaces PlayerCondition.dbc plus the
AzerothCore-style condition resolver. Defines reusable
boolean checks that other catalogs reference by conditionId
to gate gossip options, vendor items, quest availability,
achievement criteria, spell trainer offerings.
16 condition kinds (Always, Race, Class, Level, Zone, Map,
Reputation, AchievementWon, QuestComplete, QuestActive,
SpellKnown, ItemEquipped, Faction, InCombat, Mounted,
Resting), 8 comparison ops (==, !=, >, >=, <, <=, in-set,
not-in-set), and 4 chain ops (none, and, or, not) — chain
multiple conditions via chainNextId to express arbitrary
boolean trees.
Cross-references with prior formats — targetIdA is
polymorphic by conditionKind: resolves to WCHC raceId/classId,
WMS areaId/mapId, WFAC factionId, WACH achievementId, WQT
questId, WSPL spellId, or WIT itemId. chainNextId resolves
within the same WPCN catalog.
CLI: --gen-pcn (3 single-check starters), --gen-pcn-quest-gates
(4 cross-format quest gates with real WQT/WFAC/WACH/WMS IDs),
--gen-pcn-composite (3 leaves + 3 chained roots showing AND/
OR/NOT). Validator catches id=0/duplicates, kind/op out of
range, chain self-loop (infinite recursion), chainOp set
without chainNextId (dangling chain), chainNextId set without
chainOp (dead pointer warning), and unresolved chainNextId
references.
2026-05-09 19:36:56 -07:00
src/pipeline/wowee_player_conditions.cpp
feat(pipeline): add WTSK (Wowee Trade Skill / Recipe) catalog
New open format — replaces SkillLineAbility.dbc plus the
recipe portions of SkillLine.dbc plus the AzerothCore
trade_skill SQL tables. Closes the crafting gap left by WSKL
(which carries skill lines but not the recipes that bind to
them).
14 professions (Blacksmithing, Tailoring, Engineering,
Alchemy, Enchanting, Leatherworking, Jewelcrafting,
Inscription, Mining, Skinning, Herbalism, Cooking, FirstAid,
Fishing). Each recipe has 4 skill-up bracket thresholds
(orange / yellow / green / gray) for skill-up probability,
a craft spell cross-ref (WSPL), produced item cross-ref
(WIT) with min/max quantity range, an optional tool item,
and up to 4 reagent slots (itemId + count).
Cross-references with prior formats — craftSpellId points at
WSPL.spellId, producedItemId / toolItemId / reagent[].itemId
all point at WIT.itemId, and skillId points at WSKL.skillId.
CLI: --gen-tsk (3-recipe entry-tier starter), --gen-tsk-
blacksmithing (5-recipe progression rough sharpening through
truesilver champion), --gen-tsk-alchemy (5-recipe progression
minor healing through flask of titans), --info-wtsk,
--validate-wtsk with --json variants. Validator catches
id=0/duplicates, profession out of range, missing craft spell
or produced item, monotonic-bracket check (must be orange <=
yellow <= green <= gray), reagent itemId-without-count
mismatch, and free-recipe warning (no reagents and no tool).
Format graph now exposes 49 distinct binary formats. CLI
flag count: 747 → 752.
2026-05-09 19:41:49 -07:00
src/pipeline/wowee_trade_skills.cpp
feat(pipeline): add WCEQ (Wowee Creature Equipment) — 50th open format
Replaces the AzerothCore-style creature_equip_template SQL
tables plus the visible-weapon / shield / ranged-slot data
that was traditionally embedded in creature templates. Closes
a long-standing gap in the creature subsystem: until now WCRT
defined a creature's stats, WSPN placed it in the world, and
WLOT defined what it drops — but nothing defined what items
it visibly equips.
Each entry binds a creatureId to up to three equipped items
(main hand / off hand / ranged) plus the visual kit that
fires when the main-hand weapon is brandished. equipFlags
bits encode hidden / dual-wield / shield-offhand /
thrown-ranged / 2H polearm to drive the renderer's
attachment-point selection.
Cross-references with prior formats — creatureId points at
WCRT.creatureId, mainHandItemId / offHandItemId / rangedItemId
all point at WIT.itemId, and mainHandVisualId points at
WSVK.visualKitId so brandished weapons can play their
signature glow / aura.
CLI: --gen-ceq (3 generic guard/hunter/rogue starters),
--gen-ceq-bosses (4 iconic loadouts incl. Frostmourne and
Illidan's warglaives, with WSVK visual cross-refs),
--gen-ceq-ranged (3 ranged-only rifle/bow/crossbow loadouts),
--info-wceq, --validate-wceq with --json variants. Validator
catches id=0/duplicates, missing creatureId, all-empty-slots
warning, kFlagDualWield without both hand items, kFlagShield
without offhand item, mutually-exclusive dual-wield + shield,
and 2H polearm with offhand item filled.
Format graph milestone: 50 distinct binary formats. CLI flag
count: 754 → 760.
2026-05-09 19:48:13 -07:00
src/pipeline/wowee_creature_equipment.cpp
feat(pipeline): add WSET (Wowee Item Set / Tier Bonus) catalog
51st open format — replaces ItemSet.dbc + ItemSetSpell.dbc
plus the AzerothCore-style item_set_spell SQL data. Closes
the tier-bonus gap left by WIT (which describes individual
items but not the set bonuses they grant when worn together).
Each entry binds up to 8 piece item IDs to up to 4 bonus
thresholds — at N pieces worn, the matching bonus spell
activates as an aura. Standard 2/4/6/8-piece tier set pattern
is the canonical case; 5-piece PvP sets with 2/4 bonuses are
also supported.
Cross-references with prior formats — itemIds[] point at
WIT.itemId, bonusSpellIds[] point at WSPL.spellId, and
requiredSkillId points at WSKL.skillId. requiredClassMask
is a 32-bit field (uint32_t) so bit positions match WCHC's
classId enum directly — Druid (bit 11 = 0x800) and Mage
(bit 8 = 0x100) wouldn't fit in a uint8_t.
CLI: --gen-itset (2 raid sets — Battlegear of Wrath +
Stormrage Raiment, real WoW item/spell IDs), --gen-itset-tier
(4 tier-1 progression sets covering plate / cloth / leather /
holy plate), --gen-itset-pvp (3 PvP gladiator 5-piece sets
with honor-rank skill thresholds), --info-wset, --validate-wset
with --json variants. Validator catches id+name+pieceCount
required, pieceCount/bonusCount within array bounds, piece-
slot drift (0 IDs within count or non-0 IDs past count),
bonus thresholds strictly ascending, no bonus threshold
exceeding pieceCount (would never trigger), and spellId=0
in any populated bonus slot.
Format graph: 50 → 51 binary formats. CLI flag count: 762
→ 767.
2026-05-09 19:54:36 -07:00
src/pipeline/wowee_item_sets.cpp
feat(pipeline): add WGTP (Wowee Game Tips) catalog
52nd open format — replaces GameTips.dbc plus loading-screen
tutorial hint tables. Defines the rotating tips shown during
world loads, the contextual tutorial hints that fire on first
gameplay events (first quest accept, first death, first
dungeon entry), and the persistent tooltip-help strings that
explain UI elements.
4 display kinds (LoadingScreen / Tutorial / TooltipHelp /
Hint), 7 audience-filter bits (Alliance / Horde / NewPlayer /
Hardcore / PvE / PvP / Roleplay) for pool selection, level
range gating (minLevel + maxLevel), displayWeight for
relative frequency within the pool, optional WPCN condition
cross-ref for further gating, and class-mask restriction
matching WCHC bit positions.
Cross-references with prior formats — conditionId points at
WPCN.conditionId for advanced gating; requiredClassMask uses
the same WCHC.classId bit layout as WGLY/WSET.
CLI: --gen-tips (3 generic loading-screen tips), --gen-tips-
new-player (5 onboarding Tutorial-kind tips for level 1-15,
weighted higher for new players), --gen-tips-advanced (4
endgame tips for level 70+ covering raid mechanics / arena /
daily professions / dungeon finder), --info-wgtp,
--validate-wgtp with --json variants. Validator catches
id/name/text required, kind 0..3, audienceFilter=0 (tip
never shown), invalid level range, displayWeight=0 (in pool
but never picked) warning, and brevity check (>280 chars)
on Tutorial / Hint kinds that need to fit on screen.
Format graph: 51 → 52 binary formats. CLI flag count: 770
→ 775.
2026-05-09 20:00:56 -07:00
src/pipeline/wowee_game_tips.cpp
feat(pipeline): add WCMP (Wowee Companion Pet) catalog
53rd open format — replaces the companion-pet portions of
CreatureFamily.dbc plus the AzerothCore-style critter / vanity-
pet SQL data. Distinct from WPET (which covers hunter combat
pets and warlock minions); WCMP covers non-combat "vanity" pets
that follow the player around for cosmetic reasons —
Mechanical Squirrel, Mini Diablo, Panda Cub, dragon hatchlings.
8 companion kinds (Critter, Mechanical, DragonHatchling,
Demonic, Spectral, Elemental, Plush, UndeadCritter), 4
rarity tiers (Common / Uncommon / Rare / Epic), and 3
faction restrictions (AnyFaction / AllianceOnly / HordeOnly).
Cross-references with prior formats — creatureId points at
WCRT.creatureId (the rendered model), learnSpellId at
WSPL.spellId (the spell that summons the pet), itemId at
WIT.itemId (the item that teaches the spell), and
idleSoundId at WSND.soundId (idle ambient noise).
CLI: --gen-cmp (3 common vendor pets), --gen-cmp-rare (4
promo / collector pets at Epic rarity — Mini Diablo,
Panda Cub, Zergling, Murky), --gen-cmp-faction (3 faction-
restricted Alliance Lion Cub / Horde Mottled Boar /
neutral Argent Squire), --info-wcmp, --validate-wcmp with
--json variants. Validator catches id+name+creatureId+
learnSpellId required, kind 0..7 / rarity 0..3 / faction
0..2 range, and Epic-rarity-no-itemId warning (most promo
pets need a redemption-code item).
Format graph: 52 → 53 binary formats. CLI flag count: 777
→ 782.
2026-05-09 20:05:06 -07:00
src/pipeline/wowee_companions.cpp
feat(pipeline): add WSMC (Wowee Spell Mechanic) catalog
54th open format — replaces SpellMechanic.dbc plus the
AzerothCore-style diminishing-returns (DR) tables. Defines
crowd-control mechanic categories that spells reference:
Stun, Silence, Polymorph, Sleep, Fear, Root, Snare, Slow,
Knockback, etc. Each mechanic carries gameplay metadata
(breaks-on-damage, can-be-dispelled, default duration, max
stacks) plus DR category and dispel type.
8 DR categories (DRNone / DRStun / DRDisorient / DRSilence
/ DRRoot / DRPolymorph / DRControlled / DRMisc) — the
runtime uses these to gate repeated CC on the same target.
7 dispel types (DispelNone / Magic / Curse / Disease /
Poison / Enrage / Stealth) bind which dispel spells can
remove the mechanic. conflictsMask is a bitmask of OTHER
mechanic IDs — only one mechanic from a conflict-group can
apply to a target simultaneously.
Cross-references with prior formats — mechanicId is
referenced by WSPL.spellId entries that apply this CC; this
catalog is referenced from spell tags rather than referencing
out.
CLI: --gen-smc (3 baseline Stun/Silence/Snare), --gen-smc-
hard (5 hard-CC: Stun/Polymorph/Sleep/Fear/Knockback with
conflictsMask wiring), --gen-smc-roots (4 movement-impair:
Root/Snare/Slow stacking 5x/GroundPin breaks-on-damage),
--info-wsmc, --validate-wsmc with --json variants. Validator
catches id+name required, DR category 0..7, dispel type
0..6, maxStacks=0 (mechanic could never apply),
canBeDispelled+DispelNone inconsistency, and self-conflict
bit set in conflictsMask (mechanic blocking itself).
Format graph: 53 → 54 binary formats. CLI flag count: 784
→ 789.
2026-05-09 20:09:44 -07:00
src/pipeline/wowee_spell_mechanics.cpp
feat(pipeline): add WKBD (Wowee Keybinding) catalog
55th open format — replaces KeyBinding.dbc plus the
AzerothCore-style default-keybind SQL data. Defines the key
bindings shipped with the game: movement (W/A/S/D),
targeting (Tab), action bars (1-9, 0, -, =), UI panels
(C/I/B/P/N/L), chat (Enter), camera (Insert/Delete).
Each binding has an internal action name (SCREAMING_SNAKE
convention — "MOVE_FORWARD"), a primary key, an optional
alternate key, a category for the keybindings UI grouping,
and a flag indicating whether the user can override it.
Hardcoded engine bindings (alt-F4, ESC) set
isUserOverridable=0 so the rebind dialog can't accidentally
break them.
9 categories (Movement / Combat / Targeting / Camera /
UIPanels / Chat / Macro / Bar / Other) for the rebind
dialog grouping.
CLI: --gen-kbd (3 essential WASD/Tab/C bindings), --gen-kbd-
movement (8 movement: WASD + arrow alternates + jump +
autorun), --gen-kbd-ui (10 UI panel bindings covering all
the standard interface windows), --info-wkbd, --validate-wkbd
with --json variants. Validator catches id+actionName+
defaultKey required, category 0..8, alternateKey ==
defaultKey (no point in alt), action-name lowercase warning
(should be SCREAMING_SNAKE), duplicate primary keys (would
silently shadow earlier binding), and duplicate action names.
Format graph: 54 → 55 binary formats. CLI flag count: 791
→ 796.
2026-05-09 20:13:37 -07:00
src/pipeline/wowee_keybindings.cpp
feat(pipeline): add WSCH (Wowee Spell School) catalog
56th open format — replaces SpellSchools.dbc plus the
Resistances.dbc resistance-cap tables. Defines damage
schools spells use: Physical, Holy, Fire, Nature, Frost,
Shadow, Arcane, plus combined / hybrid schools that count
as multiple types simultaneously (Spellfire, Spellshadow,
Spellfrost — relevant for resistance-bypass mechanics).
7 canonical schools with single-bit IDs (1, 2, 4, 8, 16,
32, 64) so combinedSchoolMask values line up directly with
the spell engine's school-bit enum. Hybrid schools use
high-bit IDs (0x80000001+) and their combinedSchoolMask
references the canonical bits they qualify as. Each school
carries visual identity (color tint, icon), gameplay rules
(canBeImmune / canBeAbsorbed / canBeReflected / canCrit),
resistance cap at max level, and cast / impact sound IDs.
Cross-references with prior formats — castSoundId and
impactSoundId point at WSND.soundId; combinedSchoolMask
is a bitmask of OTHER WSCH.schoolId values within the same
catalog.
CLI: --gen-sch (3 base — Physical / Fire / Holy showing
non-resistable Holy + non-reflectable Physical), --gen-sch-
magical (6 canonical magical schools with proper colors
+ 365 max-level resistance caps), --gen-sch-combined (3
hybrids — Spellfire / Spellshadow / Spellfrost with
multi-bit combinedSchoolMask), --info-wsch, --validate-wsch
with --json variants. Validator catches id+name required,
reflected-without-absorbed warning (reflected damage
should be absorbable), self-referential combinedSchoolMask
(school qualifying as itself), and combined-mask references
to bits not defined in the same catalog (resolved at runtime
across catalogs).
Format graph: 55 → 56 binary formats. CLI flag count: 798
→ 804.
2026-05-09 20:19:34 -07:00
src/pipeline/wowee_spell_schools.cpp
feat(pipeline): add WLFG (Wowee Looking-for-Group) catalog
57th open format — replaces LFGDungeons.dbc plus the
AzerothCore-style dungeon-finder reward tables. Defines the
dungeons / raids that the Dungeon Finder / Raid Browser
presents to players, with their level brackets, group-size
requirements, role requirements (tank / heal / DPS), and
queue-completion rewards.
4 difficulty levels (Normal / Heroic / Mythic / Hardmode —
the latter for Ulduar-style toggleable boss difficulty),
4 expansion gates (Classic / TBC / WotLK / TurtleWoW), and
3 role-requirement bits (Tank / Heal / DPS — typically all
three for queue-formed groups).
Cross-references with prior formats — mapId points at
WMS.mapId (the instance map), queueRewardItemId points at
WIT.itemId (the random reward bag), firstClearAchievement
points at WACH.achievementId.
CLI: --gen-lfg (3 classic 5-mans Ragefire/Wailing/Deadmines
with real WoW mapIds + level brackets), --gen-lfg-heroic
(5 WotLK 80-level heroic 5-mans with emblem rewards +
real first-clear achievement IDs from Halls of Lightning
through Old Kingdom), --gen-lfg-raid (3 raid entries —
Naxx-25, Ulduar-25 Hardmode, ToC-25 Mythic), --info-wlfg,
--validate-wlfg with --json variants. Validator catches
id+name+mapId required, difficulty 0..3, expansion 0..3,
minLevel<=maxLevel, recommended-level outside range
warning, unusual groupSize warning (5/10/25/40 are
canonical), and zero role mask (queue can't form a
balanced group).
Format graph: 56 → 57 binary formats. CLI flag count: 804
→ 811.
2026-05-09 20:24:21 -07:00
src/pipeline/wowee_lfg.cpp
feat(pipeline): add WMAC (Wowee Macro / Slash Command) catalog
58th open format — novel format with no direct DBC equivalent.
WoW historically stored player macros client-side in the user
profile and system slash commands as hardcoded engine handlers;
WMAC unifies both into a single structured catalog so default
macros, system slash commands, and shipped player presets can
be authored, validated, and shipped as content alongside the
rest of the open-format graph.
5 macro kinds (SystemSlash for engine /sit /dance handlers,
DefaultMacro for shipped presets, PlayerTemplate for user
templates, GuildMacro for guild-shared, SharedMacro for
account-wide). Multi-line macro bodies are stored verbatim
with literal '\n' separators — the client parses /cast /
/target / /run lines at runtime.
Cross-references with prior formats — requiredClassMask uses
WCHC.classId bit positions (Warrior=0x02, etc, same as WGLY/
WSET/WGTP).
CLI: --gen-mac (3 system slash — /sit, /dance, /target with
[@mouseover] modifier), --gen-mac-combat (4 warrior combat
templates — heroic strike spam, charge/intercept stance dance,
intercept stance switch, victory rush+bloodthirst fallback —
each with default key bindings), --gen-mac-utility (3 universal
utility — /follow target, mass /inv with %targetN tokens,
/releasecorpse via RepopMe()), --info-wmac, --validate-wmac
with --json variants. Validator catches id+name+body required,
kind 0..4, body within maxLength cap, body starting with '/'
or '#' (slash command or showtooltip annotation), and
SystemSlash + classMask warning (slash commands are class-
agnostic — restricting them to a class makes no sense).
Format graph: 57 → 58 binary formats. CLI flag count: 814
→ 819.
2026-05-09 20:30:17 -07:00
src/pipeline/wowee_macros.cpp
feat(pipeline): add WCHF (Wowee Character Customization Feature) catalog
59th open format — replaces CharHairGeosets.dbc +
CharFacialHairStyles.dbc plus the variation portions of
CharSections.dbc. Defines per-(race, sex) customization
options the character creation screen exposes: skin colors,
face variations, hair styles, hair colors, facial hair
(beards / mustaches), and race-specific markings (Tauren
horns, Draenei tendrils, Blood Elf ears).
9 feature kinds (SkinColor / FaceVariation / HairStyle /
HairColor / FacialHair / FacialColor / EarStyle / Horns /
Markings) cover the full canonical customization surface.
Each entry is one selectable carousel choice for one
(race, sex, kind) tuple — variationIndex disambiguates.
expansionGate enum gates Blood Elf / Draenei (TBC) and DK
features (WotLK) behind the right expansion unlock.
Cross-references with prior formats — raceId points at
WCHC.race.raceId. requiresExpansion bit positions match
the WLFG expansion enum (Classic=0, TBC=1, WotLK=2,
Turtle=3) for consistency.
CLI: --gen-chf (5 Human Male starter — skin / face / 2
hair styles / facial hair), --gen-chf-bloodelf (8 Blood
Elf Female hair styles, requiresExpansion=TBC — the
iconic TBC race feature), --gen-chf-tauren (6 Tauren Male
features using race-specific Horns kind + 3 facial hair
variations), --info-wchf, --validate-wchf with --json
variants. Validator catches id+name+raceId+texturePath
required, kind 0..8 / sex 0..1 / expansion 0..3, and the
critical (race, sex, kind, variation) tuple-uniqueness
check — duplicates would shadow each other in the create-
character carousel.
Format graph: 58 → 59 binary formats. CLI flag count: 819
→ 826.
2026-05-09 20:35:21 -07:00
src/pipeline/wowee_char_features.cpp
feat(pipeline): add WPVP (Wowee PvP Honor / Rank) — 60th open format
60th open format milestone — replaces the AzerothCore-style
PvP rank tables plus the vanilla honor-rank reward chains.
Defines PvP progression rungs: vanilla honor ranks (Private
through Grand Marshal / High Warlord), arena rating brackets
(Combatant / Challenger / Rival / Duelist / Gladiator), and
battleground rated tiers.
5 rank kinds (VanillaHonor / ArenaRating / BattlegroundRated /
WorldPvP / ConquestPoint) cover the canonical PvP progression
surface. Each entry carries an alliance-specific name and a
horde-specific name (Grand Marshal = High Warlord; arena tiers
share the same name on both factions), an honor or rating
threshold, and optional gear cross-refs (chest, gloves,
shoulders) into WIT.
Cross-references with prior formats — titleId points at
WTTL.titleId (the unlock title), chest/gloves/shoulders point
at WIT.itemId for the matching PvP set, bracketBgId points at
WBGD.bgId for battleground-bracket gating.
CLI: --gen-pvp (3 vanilla entry tiers Rank2-4 with alliance
vs horde alternate names), --gen-pvp-alliance (9 vanilla
ranks 6-14 with WTTL+WIT cross-refs and ramping honor
thresholds 50k → 260k), --gen-pvp-arena (5 arena rating
brackets 1500/1750/2000/2200/2400 with 10/20/40/80/160 emblem
rewards), --info-wpvp, --validate-wpvp with --json variants.
Validator catches id+name required, kind 0..4, level range
valid, faction-name pairing (one set without the other is a
typo), threshold monotonicity within a rankKind, arena rating
below 1500 floor, and VanillaHonor with minHonor=0 baseline
warning.
Format graph: 59 → 60 binary formats (milestone). CLI flag
count: 826 → 833.
2026-05-09 20:41:09 -07:00
src/pipeline/wowee_pvp.cpp
feat(pipeline): add WBNK (Wowee Bag / Bank Slot) catalog
61st open format — replaces ItemBag.dbc plus the bank-storage
and special-purpose container tables. Defines every slot the
player has access to: equipped bags, bank bags, keyring, soul
shard bag, quiver, reagent bag, hunter pet stable.
8 bag kinds (Inventory / Bank / Keyring / Quiver / SoulShard /
Stable / Reagent / Wallet) cover the canonical container
surface. Each entry has a fixed capacity (or 0 = variable,
size set by equipped bag), a display order in the inventory
UI, an unlock state with optional gold cost (bank bags ramp
through 10s / 1g / 10g / 25g / 50g / 100g matching canonical
WoW prices), and an accepts-bag-subclass mask gating which
container kinds may be equipped (generic / herb / enchanting
/ engineer / gem / mining / leather / inscription / quiver /
ammo pouch).
Cross-references with prior formats — fixedBagItemId points
at WIT.itemId for the bag item that always occupies a fixed
slot (0 = player-equipable variable slot).
CLI: --gen-bnk (5 inventory slots — 16-slot fixed main
backpack + 4 player-equippable bag slots accepting generic
containers + herb + enchanting bags), --gen-bnk-bank (8 bank
bag slots with the canonical WoW unlock cost ramp),
--gen-bnk-special (4 special-purpose: 32-slot Keyring fixed,
warlock SoulShardBag, hunter ArrowQuiver, hunter
HuntersStable for 5 pets), --info-wbnk, --validate-wbnk with
--json variants. Validator catches id+name required, kind
0..7, locked-with-zero-cost (slot can never be unlocked),
fixed-slot-with-non-zero-mask (equippable bag would be
ignored), variable slot with empty mask (no bag can fit),
and ambiguous (bagKind, displayOrder) tuples (UI sort would
flicker).
Format graph: 60 → 61 binary formats. CLI flag count: 833
→ 840.
2026-05-09 20:46:06 -07:00
src/pipeline/wowee_bags.cpp
feat(pipeline): add WRUN (Wowee DK Rune Cost) catalog
62nd open format — replaces RuneCost.dbc plus the DK-specific
portions of ChrPowerType. Defines per-spell rune costs (Blood
/ Frost / Unholy) and runic-power generation / consumption
for the Death Knight class.
4 spell tree branches (BloodTree / FrostTree / UnholyTree /
Generic) classify which spec uses each rune cost. Each entry
binds a spell to its rune cost (how many of each rune kind
the spell consumes), an optional anyDeathConvertCost (extra
Death-rune-acceptable cost for procced abilities), and a
runicPowerCost (negative = generator, positive = spender).
Cross-references with prior formats — spellId points at
WSPL.spellId (the spell that uses this rune cost).
CLI: --gen-rune (3 baseline DK abilities — Death Strike
1F+1U + 20RP gen, Frost Strike pure 40 RP spender, Heart
Strike 1B + 10RP gen), --gen-rune-blood (4 blood-tree DK
abilities — Heart Strike, Death and Decay AoE, Vampiric
Blood tank cooldown, Rune Tap self-heal), --gen-rune-frost
(4 frost-tree — Frost Strike, Howling Blast AoE, Obliterate
finisher, Icy Touch ranged opener applying Frost Fever),
--info-wrun, --validate-wrun with --json variants. Validator
catches id+name+spellId required, branch 0..3, no rune cost
> 2 (DK only has 2 of each rune type so a higher cost can
never be paid), runicPowerCost > 100 (DK RP cap), no-cost
warning (spell consumes nothing — verify it's a
passive/stance/form), and high-RP-generator warning (> 25
RP per cast is unusual).
Format graph: 61 → 62 binary formats. CLI flag count: 840
→ 847.
2026-05-09 20:52:19 -07:00
src/pipeline/wowee_runes.cpp
feat(pipeline): add WLDS (Wowee Loading Screen) catalog
63rd open format — replaces LoadingScreens.dbc plus the
per-zone background-image tables. Defines the loading-screen
images shown when the client crosses into a new map /
instance, with optional level-bracket gating and expansion
gating (TBC art only shown if expansion installed).
When multiple screens match the player's current map + level
+ expansion, displayWeight selects randomly between them — a
zone with 3 weighted variants gets a different image roughly
proportional to weight.
4 expansion gates (Classic / TBC / WotLK / TurtleWoW),
isAnimated flag for screens with subtle animation,
isWideAspect flag for 16:9 raid intro art (vs 4:3 standard).
Cross-references with prior formats — mapId points at
WMS.map.mapId (which map triggers this loading screen);
mapId=0 is the catch-all sentinel for screens shown when
no map-specific screen matches.
CLI: --gen-lds (3 base screens — Elwynn level 1-30, Orgrimmar,
GenericFallback level 31-80 catch-all), --gen-lds-instances
(5 WotLK dungeon screens with mapId+expansion cross-refs:
Halls of Lightning/Stone, Utgarde Pinnacle, Violet Hold,
Old Kingdom), --gen-lds-raid (3 raid intro screens —
Naxxramas/Ulduar/ToC at isWideAspect=1 with weight=3),
--info-wlds, --validate-wlds with --json variants. Validator
catches id+name+texture required, expansion 0..3, level range
valid, weight=0 (in pool but never picked), and the practical
catch-all overlap warning when multiple mapId=0 screens share
overlapping level brackets (random pick becomes
non-deterministic).
Format graph: 62 → 63 binary formats. CLI flag count: 847
→ 854.
2026-05-09 20:59:25 -07:00
src/pipeline/wowee_loading_screens.cpp
feat(pipeline): add WSUF (Wowee Item Random Suffix) catalog
64th open format — replaces ItemRandomProperties.dbc +
ItemRandomSuffix.dbc plus the AzerothCore-style suffix-roll
tables. Defines random "of the X" suffixes that roll on
green and blue items at world drop ("Sturdy Cloth Cap of
the Bear" = base item + STR + STA suffix).
5 suffix categories (Generic / Elemental / Defensive /
PvPSuffix / Crafted), per-suffix item-quality bracket gating
(only blue+ items can roll PvPSuffix), restricted-slot mask
that limits which equipment slots a suffix can apply to (15
slot bits matching WCEQ slot enum), and up to 5 stat bonus
slots per suffix matching WoW canonical max.
statValuePoints isn't an absolute number — it's a scaling
base that the runtime multiplies by an item-level
coefficient to compute the final per-item bonus, so "of the
Bear" gives proportionally more strength on a level-60 item
than on a level-20 item.
Cross-references with prior formats — statKind values match
WIT.statType enum (STR=4, AGI=3, INT=5, SPI=6, STA=7) so
item generators roll consistent stats with base items.
CLI: --gen-suf (3 generic stat triads — Bear STR+STA, Eagle
INT+SPI, Tiger STR+AGI), --gen-suf-magical (4 elemental
spell-power suffixes restricted to caster-eligible slots),
--gen-suf-pvp (3 PvPSuffix entries with resilience + offensive
stats, blue+ quality only), --info-wsuf, --validate-wsuf with
--json variants. Validator catches id+name required, category
0..4, quality range valid (0..7 covers heirloom), itemQuality
floor<=ceiling, stat-kind/value pairing (kind=0 with value!=0
is a typo, vice versa), and no-stats warning (suffix renames
item without changing it).
Format graph: 63 → 64 binary formats. CLI flag count: 854
→ 861.
2026-05-09 21:05:49 -07:00
src/pipeline/wowee_item_suffixes.cpp
feat(pipeline): add WCRR (Wowee Combat Rating Conversion) catalog
65th open format — replaces gtCombatRatings.dbc plus the
per-level rating-to-percentage tables in gtRegenHPPerSpt.dbc
and related stat-curve DBCs. Defines per-rating-type
conversion factors at canonical level breakpoints (1 / 60
/ 70 / 80) — the runtime linearly interpolates between
breakpoints for intermediate levels.
pointsAtLevelN is "how many rating points equal 1% of the
benefit at that level." Higher level = more rating needed
for the same %. Standard WoW WotLK example: 14 crit rating
= 1% crit at L60, but 45.91 = 1% at L80.
5 rating kinds (Combat / Defense / Spell / Resilience /
Other) classify what stat resolver category each rating
belongs to.
CLI: --gen-crr (3 essential combat ratings — Hit/Crit/Haste
at canonical WoW WotLK conversion values), --gen-crr-defensive
(4 defensive — Defense/Dodge/Parry/Block with diminishing-
returns soft-cap percentages), --gen-crr-spell (3 spell —
SpellPower direct 1:1, SpellPenetration flat, MP5 mana
regen), --info-wcrr, --validate-wcrr with --json variants.
Validator catches id+name required, kind 0..4, all
pointsAtLN > 0 (otherwise stat resolver would div-by-zero),
maxBenefitPercent > 0 (rating would never grant any
benefit), and non-monotonic conversion curve warning
(rating cost typically ascends with level for non-flat
ratings like SpellPower).
Format graph: 64 → 65 binary formats. CLI flag count: 861
→ 868.
2026-05-09 21:11:26 -07:00
src/pipeline/wowee_combat_ratings.cpp
feat(pipeline): add WUMV (Wowee Unit Movement Type) catalog
66th open format — replaces UnitMovement.dbc plus the
movement-modifier portions of CreatureModelData.dbc. Defines
movement speed types (walk / run / swim / flight / fly /
pitch) with their canonical baseline speeds in yards-per-
second, plus the temp speed buffs that stack on top
(Sprint, Aspect of the Cheetah, Travel Form).
12 movement categories cover the canonical surface (Walk /
Run / Backward / Swim / SwimBack / Turn / Flight /
FlightBack / Pitch / Fly / FlyBack / TempBuff). baseSpeed
is yards/second for baseline categories and ignored for
TempBuff entries (which use baseMultiplier instead).
maxMultiplier caps stacking — Sprint capped at 1.4 means
Sprint + Aspect of Cheetah doesn't exceed 1.4× run speed.
stackingPriority resolves conflicts when multiple buffs
of equal multiplier compete (higher wins).
CLI: --gen-umv (4 baseline at canonical WoW vanilla speeds:
Walk 2.5y/s, Run 7.0y/s, Swim 4.7y/s, Turn π rad/s),
--gen-umv-flight (5 flight entries — ground-rail Flight
7y/s, free Fly 14y/s, Pitch 1.5 rad/s, backward variants
at slower 4.5y/s), --gen-umv-buffs (5 temp speed buffs
matching real WoW spell auras with proper durations and
stacking priorities), --info-wumv, --validate-wumv with
--json variants. Validator catches id+name required,
category 0..11, baseMultiplier > 0 (otherwise unit freezes
in place), maxMultiplier >= baseMultiplier (cap below
floor would clamp the base down), baseline categories
need baseSpeed > 0, and Run < 3.0y/s warning (canonical
is 7.0y/s).
Format graph: 65 → 66 binary formats. CLI flag count: 870
→ 875.
2026-05-09 21:18:03 -07:00
src/pipeline/wowee_unit_movement.cpp
feat(pipeline): add WQSO (Wowee Quest Sort) catalog
67th open format — replaces QuestSort.dbc plus the quest-log
categorization fields in QuestInfo.dbc. Defines the
categories that quests fall into for the quest-log UI:
class quests (Warrior trial, etc), profession quests, daily
quests, holiday events, reputation grinds, dungeon /
heroic / raid quests, repeatables, PvP, tournament.
12 sort kinds (General / ClassQuest / Profession / Daily /
Holiday / Reputation / Dungeon / Raid / Heroic / Repeatable
/ PvP / Tournament). Each WQT (quest) entry can reference
a sortId here to be grouped under the right header in the
quest log. Sorts can be class-restricted (Warrior quests
only show for warriors), profession-restricted, or
faction-reputation-gated.
Cross-references with prior formats — targetClassMask uses
WCHC.classId bit positions (matches WGLY/WSET/WGTP
convention), targetProfessionId points at WTSK.profession
enum, targetFactionId points at WFAC.factionId.
CLI: --gen-qso (3 generic sorts — General catch-all, Daily
reset, Repeatable non-daily), --gen-qso-class (10 class-
specific sorts with proper bit masks for Warrior 0x02
through Druid 0x800), --gen-qso-profession (8 profession
sorts with WTSK profession enum cross-refs), --info-wqso,
--validate-wqso with --json variants. Validator catches
id+name+displayName required, kind 0..11, ClassQuest with
classMask=0 (not actually class-restricted), Profession
with profId=0 + non-Blacksmithing-name (likely typo since
0=Blacksmithing in WTSK), and Reputation with factionId=0
(no faction to grind).
Format graph: 66 → 67 binary formats. CLI flag count: 877
→ 882.
2026-05-09 21:23:38 -07:00
src/pipeline/wowee_quest_sorts.cpp
feat(editor): add WSRG (Spell Range Index) open catalog format
Open replacement for Blizzard's SpellRange.dbc plus the per-spell
range-bucket fields in Spell.dbc. Defines the categorical range
buckets that spells reference instead of carrying their own min/max
yards (every Frostbolt shares one 30y bucket; every Heal shares
one 40y friendly bucket). Each entry carries separate min/max for
hostile vs friendly targets so heals can reach further on allies
than nukes do on enemies, plus an icon color for HUD range
indicators.
Three preset emitters: --gen-srg (3 baseline buckets:
Self/Melee/Spell), --gen-srg-ranged (5 ranged spell buckets:
Short/Medium/Long/VeryLong/Unlimited), --gen-srg-friendly (3
friendly-only buckets where hostile range is 0). --info-wsrg and
--validate-wsrg round out the per-format surface; validation
catches negative ranges, min>max, duplicate ids, out-of-range
rangeKind, and warns on Self+nonzero range or Melee>8y.
Wired through the cross-format table so WSRG appears automatically
in --list-formats, --info-magic, --diff-headers, --summary-dir,
--rename-by-magic, --catalog-grep, --tree-summary-md, and
--touch-tree. Format count 67 -> 68; CLI flag count 885 -> 890.
2026-05-09 21:33:17 -07:00
src/pipeline/wowee_spell_ranges.cpp
2026-05-09 21:37:42 -07:00
src/pipeline/wowee_spell_cast_times.cpp
feat(editor): add WSDR (Spell Duration Index) — completes WSRG/WSCT/WSDR triplet
Open replacement for SpellDuration.dbc plus per-spell duration
fields in Spell.dbc. Defines the categorical duration buckets
that auras / DoTs / HoTs / buffs reference (5s / 30s / 5min / 1hr
/ UntilCancelled / UntilDeath).
Together with WSRG (range) and WSCT (cast time), this completes a
small triplet of spell-metadata catalogs: instead of every
Frostbolt rank embedding its own range, cast time, and
chill-debuff duration as duplicate fields, each spell holds three
small integer ids that resolve through these three tables. The
engine retunes thousands of spells at once by editing one bucket.
Duration scales with caster level via perLevelMs (a rank-1 Renew
at 9s grows to 12s at lvl 60), then is clamped to maxDurationMs.
Negative baseDurationMs is the canonical sentinel for "no timer"
(UntilCancelled / UntilDeath); resolveAtLevel returns -1 for
those so HUD code can render the indefinite-duration glyph.
Three preset emitters: --gen-sdr (5 baseline tiers from instant
to one-hour), --gen-sdr-buffs (4 long-duration buffs including
UntilDeath), --gen-sdr-dot (4 tick-based DoT/HoT buckets at 3s
ticks). Validation enforces base>0 for Timed/TickBased, base<0
for permanent kinds, max>=base, durationKind 0..4, no duplicate
ids, and warns on Instant+nonzero base.
Wired through the cross-format table; WSDR appears automatically
in all 9 cross-format utilities. Format count 69 -> 70; CLI flag
count 899 -> 904.
2026-05-09 21:41:55 -07:00
src/pipeline/wowee_spell_durations.cpp
2026-05-09 21:49:13 -07:00
src/pipeline/wowee_spell_cooldowns.cpp
feat(editor): add WCEF (Creature Family) open catalog format
Open replacement for CreatureFamily.dbc plus the per-creature
family fields in Creature.dbc. Defines the family categorization
that pet-able beasts share (Bear / Cat / Wolf / Boar / Crab /
Raptor / Devilsaur / etc), each with its own pet talent tree
(Ferocity / Tenacity / Cunning), food preferences as a bitmask
(Meat / Fish / Bread / Cheese / Fruit / Fungus / Raw), the skill
line that family-specific abilities reference, and the minimum
hunter level required to tame it.
Used by the hunter pet system to decide which talent tree a tamed
pet uses, validate that a hunter can tame a creature, match
feeding-table food items to pet preferences, and gate exotic-beast
families behind the Beast Master 51-point talent.
Cross-references back to WCRT (creature.familyId points here) and
WSPL (family-specific abilities reference WSPL spellId via the
skillLine field).
Three preset emitters: --gen-cef (5 baseline families covering
both major talent trees), --gen-cef-ferocity (4 DPS-tree pets
with bleed/howl/armor-shred mechanics), --gen-cef-exotic (4
exotic Beast Master families requiring 51-point talent).
Validation enforces id+name presence, familyKind 0..5, talent
tree 0..3, no duplicate ids, and warns on:
- NotPet families with a non-None talent tree (irrelevant)
- Exotic families with minLevelForTame > 80 (level-cap unreachable)
- Beast/Exotic families with no food types set (pet would starve)
Wired through the cross-format table; WCEF appears automatically
in all 10 cross-format utilities. Format count 71 -> 72; CLI flag
count 914 -> 919.
2026-05-09 21:54:00 -07:00
src/pipeline/wowee_creature_families.cpp
feat(editor): add WSPC (Spell Power Cost) — completes spell-bucket five-pack
Open replacement for the per-spell power-cost fields in Spell.dbc
plus SpellPowerCost-related side tables. Defines categorical
power-cost buckets that spells reference (LowMana 5% / MediumMana
15% / HighMana 30% of caster max mana; fixed Rage-30 /
Energy-40 / Runic-30 / etc), so spells share cost metadata across
ranks instead of embedding per-rank cost numbers.
Completes the small lookup-bucket five-pack:
WSRG — range bucket
WSCT — cast time bucket
WSDR — duration bucket
WSCD — cooldown bucket
WSPC — power cost bucket (this catalog)
Five small integer ids per spell (range / cast / dur / cd / cost)
replace the dozens of duplicate per-rank fields that Blizzard's
Spell.dbc carries. Editing one bucket here retunes every spell
that references it — change LowMana from 5% to 4% and every
rank-1 bolt across every caster class becomes cheaper.
Cost can be flat (baseCost), per-level scaled (perLevelCost), or
percentage-of-max-power (percentOfBase) — the engine sums
whichever fields are non-zero. resolveCost(id, level, maxPower)
does the math. Twelve power types covering every WoW resource
(Mana / Rage / Focus / Energy / Happiness / Runic Power / Runes /
Soul Shards / Holy Power / Eclipse / Health / NoCost).
Three preset emitters: --gen-spc (4 baseline mana tiers),
--gen-spc-rage (4 fixed warrior rage costs including stance-locked
Whirlwind), --gen-spc-mixed (5 cross-class costs covering every
non-mana power type with refund-on-miss flag for energy).
Validation enforces id+name presence, powerType 0..11, no
duplicate ids; warns on percentOfBase outside [0,1] (would
overflow), NoCost type with non-zero cost fields, and non-NoCost
types with no cost set (would cast for free — easy bug to ship).
Wired through the cross-format table; WSPC appears automatically
in all 11 cross-format utilities. Format count 72 -> 73; CLI flag
count 922 -> 927.
2026-05-09 22:00:55 -07:00
src/pipeline/wowee_spell_power_costs.cpp
feat(editor): add WGFS (Glyph Slot) open catalog format
Open replacement for Blizzard's GlyphSlot.dbc. Defines the
per-class glyph slot layout: which slots a class has (Major /
Minor / Prime), in which display order they appear in the
spellbook UI, and at which character level each slot becomes
available for use.
Distinct from WGLY (GlyphProperties) which defines the individual
glyphs themselves. WGLY says "Glyph of Polymorph exists, costs 1
inscription dust, modifies Polymorph"; WGFS says "the slot that
holds Glyph of Polymorph is the second Major Glyph Slot, unlocks
at level 25, and only Mages have it".
Layout grew across expansions, captured by the three presets:
- --gen-gfs — 6 slots: 3 Major + 3 Minor all-class
baseline (25/50/75 each)
- --gen-gfs-wotlk — 6 slots: 3 Major (15/30/50) + 3 Minor
(15/50/70) matching WotLK 3.3.5a
- --gen-gfs-cata — 9 slots: 3 Prime + 3 Major + 3 Minor
matching Cataclysm
Cross-references back to WGLY (glyphs reference slotKind to
constrain which glyph fits which slot) and WCHC (requiredClassMask
uses the same bit layout as WCHC class IDs).
Validation enforces id+name+classMask presence (classMask=0 means
no class can use the slot — usually a config bug), slotKind 0..2,
no duplicate ids; warns on minLevelToUnlock>80 (would never
unlock at WotLK cap), displayOrder>4 (UI typically shows 3-4),
and (kind+order) collisions for overlapping classMask (two slots
claiming the same UI position would render on top of each other).
isUnlockedFor(id, classBit, level) is the engine helper.
Wired through the cross-format table; WGFS appears automatically
in all 11 cross-format utilities. Format count 73 -> 74; CLI flag
count 929 -> 934.
2026-05-09 22:05:05 -07:00
src/pipeline/wowee_glyph_slots.cpp
feat(editor): add WCDF (Creature Difficulty) open catalog format
Open replacement for Blizzard's CreatureDifficulty.dbc. Maps a
base creature entry to its difficulty variants:
Normal-10 / Normal-25 / Heroic-10 / Heroic-25 in WotLK raid
format. Each variant is itself a separate WCRT creature entry
with its own stats, abilities, and loot.
When a 25-man party engages an instance, the engine looks up the
encounter base creature's difficultyId, reads the normal25Id
field, and spawns that variant instead. This is how Lord
Marrowgar in 25-Heroic ICC has 30M HP and hits for 80k while the
same encounter in 10-Normal has 5M HP and hits for 25k — same
spawn point, different WCRT entries.
5-man dungeons typically use only normal10Id + heroic10Id (the
25-man fields stay 0 — engine falls through to the 10-man
variant when 25-man is queried). World bosses don't scale at
all (all 4 variant fields stay 0, engine falls back to the base
entry).
Cross-references back to WCRT — every non-zero variant id field
points at a WCRT.creatureId entry; the base creature itself
lives in WCRT too.
Three preset emitters: --gen-cdf (4 example bosses with full
4-variant routing), --gen-cdf-wotlk-raid (4 ICC-style raid
bosses Marrowgar/Deathwhisper/Saurfang/LK with all 4 difficulty
variants), --gen-cdf-fiveman (4 5-man dungeon bosses with only
Normal+Heroic 10-man set). resolveVariant(id, mode) is the
engine helper.
Validation enforces id+name+baseCreatureId presence,
spawnGroupKind 0..5, no duplicate ids; warns on:
- WorldBoss kind with non-zero variant ids (world bosses don't scale)
- duplicate baseCreatureId across routes (only first honored)
- all-self-reference non-WorldBoss (creature doesn't actually scale)
- Boss with n25 but not n10 (raid sequencing typo — n10 always
comes with n25)
Wired through the cross-format table; WCDF appears automatically
in all 11 cross-format utilities. Format count 74 -> 75; CLI flag
count 936 -> 941.
2026-05-09 22:10:09 -07:00
src/pipeline/wowee_creature_difficulties.cpp
feat(editor): add WMAT (Item Material) open catalog format
Open replacement for Blizzard's Material.dbc plus the Material
and SheatheType fields in ItemDisplayInfo.dbc. Defines the
material categorization that items reference (Cloth / Leather /
Mail / Plate / Wood / Steel / Crystal / Ethereal / etc), each
with its own foley sound (played on item use), impact sound
(played on drop / hit), weight category, and material-property
flags (IsBreakable / IsMagical / IsFlammable / IsConductive /
IsHolyCharged / IsCursed).
The engine plays a sword's metallic clang from impactSoundId
when it hits a stone wall, but a cloth tabard makes no such
sound — the difference is exactly the material assigned by this
catalog. Every armor and weapon item in WIT references a
materialId here.
Twelve materialKind values cover the standard armor classes
(Cloth/Leather/Mail/Plate/Hide), structural materials (Wood /
Stone / Metal), and special categories (Liquid / Organic /
Crystal / Ethereal). Three weight tiers (Light / Medium / Heavy)
control encumbrance UI hints.
Cross-references back to WSND (foleySoundId / impactSoundId
reference WSND sound entries) and forward to WIT (item entries
reference materialId here).
Three preset emitters: --gen-mat (5 armor materials matching
WoW's armor classes), --gen-mat-weapon (5 weapon materials from
breakable+flammable Wood through enchanted endgame steel),
--gen-mat-magical (4 magical materials with special flags
including the IsHolyCharged anti-undead property).
Validation enforces id+name presence, materialKind 0..11,
weightCategory 0..2, no duplicate ids; warns on:
- IsHolyCharged + IsCursed both set (engine picks one,
typically IsCursed wins)
- Plate kind that's not Heavy weight (canonical violation)
- Cloth kind that's not Light weight (canonical violation)
Wired through the cross-format table; WMAT appears automatically
in all 11 cross-format utilities. Format count 75 -> 76; CLI flag
count 943 -> 948.
2026-05-09 22:14:44 -07:00
src/pipeline/wowee_item_materials.cpp
feat(editor): add WPSP (Player Spawn Profile) open catalog format
Open replacement for AzerothCore's playercreateinfo SQL table
plus the per-class/race starting fields in CharStartOutfit.dbc.
Defines the initial state for a newly created character: starting
map / zone / position / facing, bind point (Hearthstone
destination), up to 4 starting items with counts, and up to 4
starting spells.
One entry per (race, class) combination — a Human Warrior spawns
at Northshire Abbey with a Worn Shortsword and Heroic Strike
already learned, while an Orc Hunter spawns in Valley of Trials
with Aimed Shot and a starter rifle. Death Knights have their
own preset spawning at lvl 55 in Acherus, the Ebon Hold.
The race+class fields are bitmasks (mirroring WCHC layout) so
one profile entry can cover multiple class/race combinations
that share starting state. findByRaceClass(raceBit, classBit)
is the engine helper used by character creation.
Cross-references back to WCHC (race/class bit layouts), WMS (map
ids), WIT (starting item ids), and WSPL (starting spell ids).
Three preset emitters: --gen-psp (5 Alliance combos covering
each starting zone from Northshire to Ammen Vale), --gen-psp-horde
(5 Horde combos from Valley of Trials to Sunstrider Isle),
--gen-psp-dk (2 DK combos at lvl 55 in Acherus with Death Coil /
Plague Strike / Death Grip starter loadout).
Validation enforces id+name+race+class+startingLevel presence,
no duplicate ids; warns on (0,0,0) spawn (uninitialized entry),
item id/count mismatch (granted item without count or vice versa),
startingLevel > 80 (above WotLK cap), and Death Knight class
with startingLevel < 55 (DKs canonically start at 55).
Wired through the cross-format table; WPSP appears automatically
in all 12 cross-format utilities. Format count 76 -> 77; CLI flag
count 951 -> 956.
2026-05-09 22:22:57 -07:00
src/pipeline/wowee_player_spawn_profiles.cpp
feat(editor): add WTLE (Talent Tab) open catalog format
Open replacement for Blizzard's TalentTab.dbc plus the per-tab
fields in Spell.dbc / Talent.dbc. Defines the three talent trees
that each class has — Warrior: Arms / Fury / Protection;
Mage: Arcane / Fire / Frost; Paladin: Holy / Protection /
Retribution; etc.
Each tab carries its own name, role hint (DPS / Tank / Healer /
Hybrid / PetClass), display order in the talent UI, background
artwork path (e.g. "WarriorArms" for the parchment background),
icon path, and the class bitmask it belongs to.
Distinct from WTAL (which defines individual talent points) —
WTLE says "the Arms tree exists for Warriors, displays in tab 1,
is a DPS spec"; WTAL says "Mortal Strike is a 1-point talent in
the Arms tree, row 7, requires Improved Charge as a prerequisite".
Cross-references back to WCHC (classMask uses the same bit
layout) and forward to WTAL (talent entries reference tabId
here). findByClass(classBit) returns all tabs for a class
sorted by displayOrder — the talent UI uses this directly to
populate its tab buttons.
Three preset emitters: --gen-tle (Warrior 3 tabs with two DPS +
one Tank), --gen-tle-mage (Mage 3 DPS tabs), --gen-tle-paladin
(Paladin 3 tabs covering all three roles in one preset).
Validation enforces id+name+classMask presence (classMask=0
means no class can use the tab — usually a config bug),
roleHint 0..4, no duplicate ids; warns on empty iconPath
(missing-texture render), empty backgroundFile (no panel art),
displayOrder>3 (UI shows at most 4 tabs), and (classMask +
displayOrder) collisions for overlapping classes (two tabs
claiming the same UI slot for the same class).
Wired through the cross-format table; WTLE appears automatically
in all 12 cross-format utilities. Format count 77 -> 78; CLI flag
count 958 -> 963.
2026-05-09 22:27:18 -07:00
src/pipeline/wowee_talent_tabs.cpp
feat(editor): add WCTR (Currency Type) open catalog format
Open replacement for Blizzard's CurrencyTypes.dbc plus the
per-currency cap tables in CurrencyCategory.dbc. Defines the
in-game currencies that are NOT regular item stacks: Honor
Points, Arena Points, Justice Points, Valor Points, Conquest
Points, plus the various faction tokens (Champion's Seal,
Wintergrasp Mark of Honor, Emblem of Frost).
Distinct from regular items in WIT — currencies are tracked
per-character as scalar quantities with weekly + absolute caps,
not as stackable inventory slots. Some currencies are still
backed by a WIT item entry for the icon and tooltip text
(itemId field), while others (Honor, Arena) live entirely in
the currency system.
The cap model captures both shapes:
- maxQuantity = absolute lifetime cap (Honor Points 75k)
- maxQuantityWeekly = weekly earn cap, no absolute cap
(Conquest Points 1650/wk)
- both 0 = uncapped (faction tokens, Emblem of Frost)
earnableNow(id, current, weekly) is the engine helper that
returns the smaller of (remaining absolute, remaining weekly).
Cross-references back to WIT (itemId for tooltip art) and
WFAC (categoryId references factionId for FactionToken kind —
the rep gate that lets you spend the token).
Three preset emitters: --gen-ctr (4 PvP currencies covering
absolute, weekly-only, and uncapped tiers), --gen-ctr-pve (4
PvE raid currencies with same cap variety), --gen-ctr-faction
(4 faction tokens with their categoryId pointing at WFAC
faction ids).
Validation enforces id+name presence, currencyKind 0..5, no
duplicate ids; warns on:
- maxQuantityWeekly > maxQuantity (weekly cap will never be
reached, absolute cap blocks first)
- FactionToken kind with categoryId=0 (rep gate breaks)
- no caps + no itemId + no iconPath (currency has no display
data and unbounded earn rate)
Wired through the cross-format table; WCTR appears automatically
in all 12 cross-format utilities. Format count 78 -> 79; CLI flag
count 965 -> 970.
2026-05-09 22:31:42 -07:00
src/pipeline/wowee_currency_types.cpp
2026-05-09 22:38:36 -07:00
src/pipeline/wowee_spell_reagents.cpp
feat(editor): add WACR (Achievement Criteria) open catalog format
Open replacement for Blizzard's Achievement_Criteria.dbc. Defines
the individual progression criteria that a character must
complete to earn an achievement.
Each WACH achievement has a tree of WACR criteria — "Kill 100
boars" is one criteria entry with criteriaType=KillCreature,
targetId=boarCreatureId, requiredCount=100. Multi-criteria
achievements (e.g. "Visit all 3 capital cities") have one entry
per sub-objective, all referencing the same achievementId, with
progressOrder determining their display sequence in the
achievement UI.
Thirteen criteriaType values cover the full progression variety:
KillCreature / ReachLevel / CompleteQuest / EarnGold /
GainHonor / EarnReputation / ExploreZone / LootItem /
UseItem / CastSpell / PvPKill / DungeonRun / Misc
The targetId field is type-polymorphic — for KillCreature it
references WCRT.creatureId, for CompleteQuest it references
WQT.questId, for ExploreZone it's a WMS.zoneId, etc. The engine
interprets it based on criteriaType.
Cross-references back to WACH (achievementId), WCRT
(KillCreature.targetId), WQT (CompleteQuest.targetId), WIT
(LootItem/UseItem.targetId), WMS (ExploreZone.targetId), WSPL
(CastSpell.targetId). findByAchievement(achId) returns all
criteria for an achievement sorted by progressOrder — used
directly by the achievement UI to render the progress checklist.
Three preset emitters: --gen-acr (5 kill criteria under one
composite achievement showing different creature targets),
--gen-acr-quest (4-step quest progression), --gen-acr-mixed
(5 cross-type criteria demonstrating the full CriteriaType
variety).
Validation enforces id+name+achievementId presence,
criteriaType 0..12, no duplicate ids; warns on:
- missing targetId for type-specific kinds (KillCreature,
CompleteQuest, etc. — engine cannot track without it)
- ReachLevel with requiredCount > 80 (above WotLK cap)
- timeLimitMs set on non-time-sensitive types (engine
ignores it for ReachLevel / EarnGold)
- requiredCount=0 (criteria completes instantly on first
progress event — usually a misconfig)
Wired through the cross-format table; WACR appears automatically
in all 14 cross-format utilities. Format count 80 -> 81; CLI flag
count 981 -> 986.
2026-05-09 22:43:44 -07:00
src/pipeline/wowee_achievement_criteria.cpp
feat(editor): add WSEF (Spell Effect Type) open catalog format
Open replacement for the SpellEffect.Effect field meanings in
Spell.dbc plus the engine's hard-coded effect dispatch table.
Defines what each spell-effect integer value actually does —
SCHOOL_DAMAGE=2 deals magical damage, DUMMY=3 is a script hook,
HEAL=10 restores health, ENERGIZE=30 restores power,
APPLY_AURA=6 attaches a buff/debuff, etc.
WotLK's Spell.dbc has 192+ effect type integers, each with its
own resolver in the spell engine. This catalog lets the engine
look up "given effect=10, what resolution behavior do I run?"
via a single table lookup instead of a hard-coded switch
statement, and lets server-custom spells reference new effect
IDs without touching engine code.
Ten effectKind values capture the major behavior families
(Damage / Heal / Aura / Energize / Trigger / Movement / Summon /
Dispel / Dummy / Misc), and a 6-bit behaviorFlags field
captures targeting/gating semantics:
- RequiresTarget — must have a target
- RequiresLineOfSight — LoS check on target
- IsHostileEffect — hostile only (PvP gating)
- IsBeneficialEffect — friendly only
- IgnoresImmunities — bypasses Bubble / IBF / etc
- TriggersGCD — counts toward GCD
Distinct from WAUR (Spell Aura Type, future format) which is the
secondary classification used when effectType is APPLY_AURA. The
two together cover the full spell-effect classification space.
Three preset emitters: --gen-sef (5 damage effects covering
typical Spell.dbc damage IDs), --gen-sef-healing (4 heal
effects all flagged IsBeneficialEffect), --gen-sef-aura (5
aura-application effects covering single-target / pet /
party-wide / area variants).
Validation enforces name presence, effectKind 0..9, no duplicate
ids; warns on:
- both Hostile and Beneficial flags set (engine picks Hostile,
contradiction suggests config bug)
- Damage kind without TriggersGCD (most damage should be on GCD
— env damage is the canonical exception)
- Heal kind without IsBeneficialEffect (engine treats heal as
ungated, may damage enemies)
Wired through the cross-format table; WSEF appears automatically
in all 15 cross-format utilities. Format count 81 -> 82; CLI flag
count 989 -> 994.
2026-05-09 22:50:13 -07:00
src/pipeline/wowee_spell_effect_types.cpp
feat(editor): add WAUR (Spell Aura Type) — companion to WSEF, CLI flag count breaks 1000
Open replacement for the SpellEffect.EffectAuraType field
meanings used when SpellEffect.Effect=APPLY_AURA. Defines what
each aura-type integer value actually does once an aura is
attached to a unit — PERIODIC_DAMAGE ticks damage every N
seconds, MOD_STAT adds a stat bonus, MOD_INCREASE_SPEED scales
movement, MOD_DAMAGE_PERCENT_DONE scales spell power, etc.
Companion to WSEF — together they cover the full spell-effect
classification space:
WSEF: outer effect ID — what does the effect DO?
(APPLY_AURA, SCHOOL_DAMAGE, HEAL, etc)
WAUR: inner aura type — when WSEF=APPLY_AURA, what KIND
of aura is applied? (PERIODIC_DAMAGE, MOD_STAT,
STUN, ROOT, etc)
Nine auraKind values (Periodic / StatMod / DamageMod /
Movement / Visual / Trigger / Resource / Control / Misc)
classify the major behavior families. Periodic auras carry an
updateFrequencyMs (canonical 3s for DoT/HoT, 2s for energize,
1s for fast triggers). Stackable auras carry a maxStackCount.
Cross-references back to WSEF (this catalog is the secondary
classification that WSEF entry id 6 (APPLY_AURA) dispatches
into) and forward to WSPL (spell entries with effect=APPLY_AURA
reference an auraTypeId here).
Three preset emitters: --gen-aur (5 periodic auras with
canonical tick intervals), --gen-aur-stats (5 stat-modifier
auras instantly applied on attach), --gen-aur-movement (4
movement-impairing CC auras typical of crowd-control spells).
Validation enforces name presence, auraKind 0..8, targetingHint
0..3, no duplicate ids; errors on Periodic kind without
updateFrequencyMs (would never tick); warns on:
- non-Periodic/Trigger kinds with updateFrequencyMs > 0
(engine ignores tick interval)
- maxStackCount > 0 with isStackable=false (cap unreachable)
Wired through the cross-format table; WAUR appears automatically
in all 15 cross-format utilities. Format count 82 -> 83;
CLI flag count 996 -> 1001 — broke the 1000-flag mark.
2026-05-09 22:54:53 -07:00
src/pipeline/wowee_spell_aura_types.cpp
feat(editor): add WIQR (Item Quality) open catalog format
Open replacement for the hardcoded item quality tiers in the
WoW client (Poor / Common / Uncommon / Rare / Epic / Legendary
/ Artifact / Heirloom). Defines each tier's tooltip text color,
inventory slot border color, vendor price multiplier, drop-level
gating, and disenchant eligibility.
The hardcoded client uses a fixed color table (gray/white/green/
blue/purple/orange/red/gold). This catalog lets server admins:
- retune the colors (rename "Epic" to "Tier 1" with custom hex)
- add server-custom tiers above Heirloom
- change vendor markup per tier (legendary 50x base price)
- gate quality drops by character level (Heirlooms unlock 80)
The standard preset reproduces the canonical 8-tier scale with
exact hex values from the live client (#9d9d9d through #00ccff)
and standard disenchant rules (Common+ disenchantable, Legendary
and Artifact aren't). The server-custom preset shows 4 tiers
above the standard range with non-standard pricing (Junk 0.1x,
QuestLocked 0.0x unsellable). The raid preset gates 4
progression tiers behind minLevelToDrop=60 with escalating
vendor multipliers up to 50x for Legendary.
Cross-references back to WIT — item entries reference qualityId
here for tooltip color and sort order. canDropAtLevel(id, lvl)
is the engine helper used by loot generation.
Validation enforces name presence, no duplicate ids,
vendorPriceMultiplier >= 0, minLevelToDrop <= maxLevelToDrop;
warns on:
- minLevelToDrop > 80 (unreachable at WotLK cap)
- vendorPriceMultiplier > 100x (sanity check the economy)
- nameColorRGBA with alpha=0 (text would be invisible in
tooltips — common bug when copy-pasting RGB hex without
alpha byte)
Wired through the cross-format table; WIQR appears automatically
in all 15 cross-format utilities. Format count 83 -> 84; CLI
flag count 1003 -> 1008.
2026-05-09 22:59:27 -07:00
src/pipeline/wowee_item_qualities.cpp
feat(editor): add WSCS (Skill Cost) open catalog format
Open replacement for Blizzard's SkillCostsData.dbc plus the
per-rank training cost tables. Defines the tiered progression of
trainable skills: each rank unlocks a skill range, requires a
minimum character level, and costs a fixed amount of gold to
learn.
The canonical 6-tier profession progression captured by the
default preset:
Apprentice skill 0-75 lvl 5 1s
Journeyman skill 50-150 lvl 10 5s
Expert skill 125-225 lvl 20 1g
Artisan skill 200-300 lvl 35 5g
Master skill 275-375 lvl 50 10g
Grand Master skill 350-450 lvl 65 25g
Same shape applies to weapon skills (free, level-gated, capped at
5x char level) and riding skills (canonical Vanilla / TBC / WotLK
gold costs from 90g Apprentice through 5000g Artisan flying down
to 1000g Cold Weather Flying).
Five costKind values cover the full training-skill space
(Profession / WeaponSkill / RidingSkill / ClassSkill / Misc).
Each entry's copperCost stores the cost in copper (1g = 10000c)
which the info renderer pretty-prints as "25g 0s 0c".
Cross-references back to WSKL — skill entries reference costId
here for the tiered training schedule. nextTrainable(currentSkill,
characterLevel) is the engine helper that returns the lowest-rank
tier a character qualifies for and hasn't capped yet — used by
trainer NPCs to populate their offered-skill list.
Three preset emitters: --gen-scs (6 profession tiers), --gen-scs-
weapon (5 weapon skill tiers), --gen-scs-riding (5 riding tiers
with canonical gold costs).
Validation enforces id+name presence, costKind 0..4, no duplicate
ids, min<max range; warns on:
- requiredLevel > 80 (unreachable at WotLK cap)
- RidingSkill with requiredLevel < 20 (Apprentice canonically
unlocks at 20)
- Profession kind with copperCost=0 (every standard tier costs
at least a copper — usually a config bug)
Wired through the cross-format table; WSCS appears automatically
in all 15 cross-format utilities. Format count 84 -> 85; CLI
flag count 1010 -> 1015.
2026-05-09 23:04:02 -07:00
src/pipeline/wowee_skill_costs.cpp
2026-05-05 10:04:45 -07:00
src/pipeline/custom_zone_discovery.cpp
feat(editor): add standalone world editor (rough/WIP)
Standalone wowee_editor tool for creating custom WoW zones.
This is a rough initial implementation — many features work but
M2/WMO rendering still has issues (frame sync, texture layout
transitions) and needs further polish.
Terrain:
- Create new blank terrain with 10 biome types (Grassland, Forest,
Jungle, Desert, Barrens, Snow, Swamp, Rocky, Beach, Volcanic)
- Load existing ADT tiles from extracted game data
- Sculpt brushes: Raise, Lower, Smooth, Flatten, Level
- Chunk edge stitching prevents seams between tiles
- Undo/redo (100-deep stack, Ctrl+Z/Ctrl+Shift+Z)
- Save to WoW ADT/WDT format
Texture Painting:
- Paint/Erase/Replace Base modes
- Full tileset texture browser (1285 textures from manifest)
- Per-zone directory filtering and search
- Alpha map editing with 4-layer limit (auto-replaces weakest)
Object Placement:
- M2 and WMO model placement with full manifest browser (11k M2s, 2k WMOs)
- M2Renderer + WMORenderer integrated (loads .skin files for WotLK)
- Ghost preview follows cursor before placing
- Ctrl+click selection, right-click context menu
- Transform gizmo (Move/Rotate/Scale with axis constraints)
- Position/rotation/scale editing in properties panel
NPC/Monster System:
- 631 creature presets scanned from manifest, categorized
(Critters, Beasts, Humanoids, Undead, Demons, etc.)
- Stats editor: level, health, mana, damage, armor, faction
- Behavior: Stationary, Patrol, Wander, Scripted
- Aggro/leash radius, respawn time, flags (hostile/vendor/etc.)
- Save creature spawns to JSON
Water:
- Place water at configurable height per chunk
- Liquid types: Water, Ocean, Magma, Slime
- Rendered as translucent colored quads
- Saved in ADT MH2O format
Infrastructure:
- Free-fly camera (WASD/QE, right-drag look, scroll speed)
- 5-mode toolbar: Sculpt | Paint | Objects | Water | NPCs
- Asset browser indexes full manifest on startup
- Editor water/marker shaders (pos+color vertex format)
- forceNoCull added to M2Renderer for editor use
- AssetManifest::getEntries() and AssetManager::getManifest() exposed
Known issues:
- M2/WMO rendering may not display on first placement (frame index
sync between update/render was misaligned — now fixed but untested
end-to-end)
- Validation layer errors on shutdown (resource cleanup ordering)
- Object placement on steep terrain can miss raycast
- No undo for texture painting or object placement yet
2026-05-05 03:47:03 -07:00
src/pipeline/terrain_mesh.cpp
# Rendering core
src/rendering/vk_context.cpp
src/rendering/vk_utils.cpp
src/rendering/vk_shader.cpp
src/rendering/vk_texture.cpp
src/rendering/vk_buffer.cpp
src/rendering/vk_pipeline.cpp
src/rendering/camera.cpp
src/rendering/terrain_renderer.cpp
src/rendering/m2_renderer.cpp
src/rendering/m2_renderer_instance.cpp
src/rendering/m2_renderer_particles.cpp
src/rendering/m2_renderer_render.cpp
src/rendering/m2_model_classifier.cpp
src/rendering/wmo_renderer.cpp
src/rendering/frustum.cpp
# Core
src/core/window.cpp
src/core/logger.cpp
src/core/memory_monitor.cpp
# stb_image (needed by AssetManager for PNG overrides)
tools/editor/stb_image_impl.cpp
)
target_include_directories(wowee_editor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR}/tools/editor
)
target_include_directories(wowee_editor SYSTEM PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/extern
${CMAKE_CURRENT_SOURCE_DIR}/extern/vk-bootstrap/src
)
target_link_libraries(wowee_editor PRIVATE
SDL2::SDL2
Vulkan::Vulkan
Threads::Threads
ZLIB::ZLIB
${CMAKE_DL_LIBS}
imgui
vk-bootstrap
)
if(TARGET glm::glm)
target_link_libraries(wowee_editor PRIVATE glm::glm)
elseif(glm_FOUND)
target_include_directories(wowee_editor PRIVATE ${GLM_INCLUDE_DIRS})
endif()
if(UNIX AND NOT APPLE)
find_package(X11 QUIET)
if(X11_FOUND)
target_link_libraries(wowee_editor PRIVATE X11)
endif()
endif()
if(WIN32)
target_link_libraries(wowee_editor PRIVATE ws2_32)
if(TARGET SDL2::SDL2main)
target_link_libraries(wowee_editor PRIVATE SDL2::SDL2main)
endif()
endif()
if(NOT MSVC)
target_compile_options(wowee_editor PRIVATE -Wall -Wextra -Wpedantic -Wno-missing-field-initializers)
endif()
if(GLSLC)
add_dependencies(wowee_editor wowee_shaders)
endif()
set_target_properties(wowee_editor PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)
install(TARGETS wowee_editor RUNTIME DESTINATION bin)
message(STATUS " wowee_editor tool: ENABLED")
2026-02-02 12:24:50 -08:00
# Print configuration summary
message(STATUS "")
message(STATUS "Wowee Configuration:")
message(STATUS " C++ Standard: ${CMAKE_CXX_STANDARD}")
message(STATUS " Build Type: ${CMAKE_BUILD_TYPE}")
message(STATUS " SDL2: ${SDL2_VERSION}")
message(STATUS " OpenSSL: ${OPENSSL_VERSION}")
message(STATUS " ImGui: ${IMGUI_DIR}")
2026-02-23 16:30:49 +01:00
message(STATUS " ASAN: ${WOWEE_ENABLE_ASAN}")
2026-02-02 12:24:50 -08:00
message(STATUS "")
2026-02-18 18:18:30 -08:00
# ---- CPack packaging ----
set(CPACK_PACKAGE_NAME "wowee")
set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "World of Warcraft client emulator")
set(CPACK_PACKAGE_VENDOR "Wowee")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "Wowee")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
if(WIN32)
set(CPACK_GENERATOR "NSIS")
set(CPACK_NSIS_DISPLAY_NAME "Wowee")
set(CPACK_NSIS_PACKAGE_NAME "Wowee")
set(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES64")
set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
# Run wowee from bin/ so that ./assets/ resolves correctly.
# SetOutPath sets the shortcut's working directory in NSIS.
set(CPACK_NSIS_CREATE_ICONS_EXTRA
2026-02-18 19:21:14 -08:00
"SetOutPath '$INSTDIR\\\\bin'\nCreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Wowee.lnk' '$INSTDIR\\\\bin\\\\wowee.exe'")
2026-02-18 18:18:30 -08:00
set(CPACK_NSIS_DELETE_ICONS_EXTRA
2026-02-18 19:21:14 -08:00
"Delete '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Wowee.lnk'")
2026-02-18 18:18:30 -08:00
elseif(APPLE)
set(CPACK_GENERATOR "DragNDrop")
else()
# Linux — generate postinst/prerm wrapper scripts
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/packaging)
# postinst: write a wrapper script at /usr/local/bin/wowee that cd's to
# the install dir so ./assets/ resolves correctly.
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/packaging/postinst
[[#!/bin/sh
cat > /usr/local/bin/wowee << 'WOWEE_WRAPPER'
#!/bin/sh
cd /opt/wowee/bin
exec ./wowee "$@"
WOWEE_WRAPPER
chmod +x /usr/local/bin/wowee
]])
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/packaging/prerm
"#!/bin/sh\nrm -f /usr/local/bin/wowee\n")
file(CHMOD
${CMAKE_CURRENT_BINARY_DIR}/packaging/postinst
${CMAKE_CURRENT_BINARY_DIR}/packaging/prerm
PERMISSIONS
OWNER_EXECUTE OWNER_WRITE OWNER_READ
GROUP_EXECUTE GROUP_READ
WORLD_EXECUTE WORLD_READ)
set(CPACK_GENERATOR "DEB")
set(CPACK_PACKAGING_INSTALL_PREFIX "/opt/wowee")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Wowee")
set(CPACK_DEBIAN_PACKAGE_SECTION "games")
set(CPACK_DEBIAN_PACKAGE_DEPENDS
2026-02-21 19:41:21 -08:00
"libsdl2-2.0-0, libvulkan1, libssl3, zlib1g")
2026-02-18 18:18:30 -08:00
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
"${CMAKE_CURRENT_BINARY_DIR}/packaging/postinst;${CMAKE_CURRENT_BINARY_DIR}/packaging/prerm")
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64")
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|ARM64")
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64")
endif()
endif()
include(CPack)