- BLP: blp_convert takes one arg, not two; was passing an output path
that caused conversion failures
- M2: vertex header offsets were wrong (used 80/100 instead of 60/68),
producing garbage vertex counts that failed the sanity check
- Add "Hide .anim/.skin" checkbox (on by default) to filter ~30k
companion files from the directory tree
Manifest keys use backslashes but tree splitting used forward slashes,
causing all 241k entries to land at root level. Combined with O(N)
any(startswith) checks per entry, this produced an O(N^2) hang. Re-key
manifest by the forward-slash 'p' field and build a directory index in
a single O(N) pass so tree operations are O(1) lookups.
When M2Renderer's descriptor pool was exhausted, batch.materialSet
would be VK_NULL_HANDLE and the bind was skipped, but the draw call
still executed using the previously bound descriptor set from
CharacterRenderer — causing game objects to render with the player's
skin/armor textures. Skip the entire batch instead.
New tab lets users explore extracted assets visually: BLP textures
rendered via blp_convert+Pillow, M2/WMO wireframes with mouse-drag
rotation and zoom, DBC/CSV tables with named columns from
dbc_layouts.json, ADT heightmap grids, text file viewer, audio
metadata, and hex dumps. Directory tree lazy-loads from manifest.json
with search and file-type filtering.
Cover all new features: cancel extraction, background override rebuild,
zip-slip protection, extractor auto-detection order, readonly dropdowns,
and selection preservation. Reorganize into per-tab sections with tables.
- Fix zip slip vulnerability: validate extracted paths stay within target
- Fix redundant mkdir before rmtree in rebuild_override()
- Add build/asset_extract and Windows .ps1 fallback to extractor search
- Preserve pack list selection across refreshes
- Add Cancel Extraction button with process.terminate()
- Run override rebuild in background thread to avoid UI freeze
- Fix locale combobox state to readonly
- Add asset_pipeline/ to .gitignore
- Make script executable
- Add -Wno-missing-field-initializers for GCC (Vulkan designated
initializer patterns in valid C++20 trigger this)
- Mark extern/ and vk-bootstrap as SYSTEM includes to suppress
warnings from vendored headers (VMA, stb, miniaudio, nlohmann)
- vk_utils.hpp: mark unused 'msg' parameter with [[maybe_unused]]
- world_packets.cpp: write exactMatch field to auction list packet
(was accepted as parameter but never serialized)
- game_screen.cpp: remove unused bagIcons array and unused info variable
- talent_screen.cpp: remove unused nextRank and pMin variables
The CLANGARM64 runner's cached MSYS2 install has outdated PGP keys,
causing "signature is unknown trust" errors. Setting update: true
refreshes the keyring before installing packages.
vk_mem_alloc.h was in extern/ but gitignored, causing macOS CI to fail
with 'vk_mem_alloc.h' file not found. Whitelist it alongside the other
vendored headers.
Latest vk-bootstrap HEAD uses Vulkan 1.4 types
(VkPhysicalDeviceVertexAttributeDivisorFeatures) that don't exist in
the Vulkan 1.3.275 headers shipped by Ubuntu 24.04. Pin to v1.3.302,
the latest release compatible with Vulkan 1.3 headers.
Some distros and CMake versions fail to find Vulkan via FindVulkan.cmake
even when libvulkan-dev is installed. Fall back to pkg-config (vulkan.pc)
and create the Vulkan::Vulkan imported target manually if needed.
- Add vk-bootstrap as a git submodule (was in extern/ but not tracked,
causing "vk-bootstrap not found" on all CI jobs)
- Whitelist extern/vk-bootstrap in .gitignore
- Move stormlib to a separate optional install step on both Windows CI
jobs (mingw-w64-x86_64-stormlib doesn't exist in MSYS2 repos)
Linux CI was missing libvulkan-dev, vulkan-tools, and glslc, causing
find_package(Vulkan REQUIRED) to fail. Also update BUILD_INSTRUCTIONS
Ubuntu and Arch sections to include Vulkan/shaderc packages.
- extract_assets.sh: detect Homebrew and pass CMAKE_PREFIX_PATH,
OPENSSL_ROOT_DIR, and PKG_CONFIG_PATH when auto-building on macOS
(bare cmake couldn't find Homebrew deps)
- README.md: fix macOS brew command that had comments after line
continuations (breaks shell execution)
- BUILD_INSTRUCTIONS.md: expand macOS asset extraction section with
auto-build note and expansion targets
- Add missing MSYS2 packages to CI: vulkan-loader, vulkan-headers,
shaderc, stormlib (both x86-64 and arm64), unicorn (arm64)
- Make vulkan-1.dll copy conditional via find_file (fixes MSYS2 builds)
- Use find_library for wininet/bz2 in asset_extract (graceful fallback)
- Add extract_assets.ps1 and extract_assets.bat for Windows users
- Expand BUILD_INSTRUCTIONS.md with MSYS2, vcpkg, and macOS sections
- Update README.md to reference Windows scripts and platforms
Character was facing stage-left (yaw 180) instead of toward camera;
corrected default yaw to 90. Added MSAA support to VkRenderTarget with
automatic resolve attachment, and enabled 4x MSAA for the character
preview off-screen pass.
Remove freeze-while-moving and idle smoothing logic from shadow
center computation. Texel snapping already prevents shimmer, so
the shadow projection can track the player directly each frame.
Add hard discard at radius 0.35 so no fragment beyond that point
reaches the additive blend stage. Tighten disc, glow, and edge
fade to fit within the cutoff boundary.
Remove isInterior restriction from WMO shadow sampling so city
buildings (flagged as interior groups) correctly receive shadows.
Apply shadow to interior-lit surfaces. Enable shadows by default
and persist the setting across sessions.
Zoom speed now scales with distance for fine control near the character.
Default max zoom out reduced from 50 to 33 units. New "Extended Camera
Zoom" toggle in Gameplay settings restores the full 50-unit range.
- Tighten celestial glow falloff and edge fade to eliminate visible quad boundary
- Add opacity support to minimap display shader, synced with UI opacity setting
- Fix audio double/triple-scaling by removing redundant master volume multiplications
- Rename "Original Soundtrack" toggle to "Enable WoWee Music"
- Add About tab with developer info and GitHub link
Audio was being scaled by master volume multiple times: once via
ma_engine_set_volume, again per-sound in AudioEngine, and again
via pre-multiplication in the UI. Removed redundant master volume
multiplications so each channel volume is independent and master
applies once through the engine. Added About tab to settings with
developer info and GitHub link.
Alpha blending caused faint quad edges to be visible against the sky
gradient. Additive blending correctly adds glow light without the
outline artifact. Edge fade starts earlier and discard threshold raised.
Ripples were cleared every frame the player wasn't swimming, which
destroyed foot splash particles the same frame they were spawned.
Now particles expire naturally via their lifetime.
- Replace dark edge RGB on alpha-tested foliage with mip-4 average color
proportional to alpha (low alpha = low trust in original RGB)
- Raise foliage alpha cutoff to 0.4 and remove dither band for cleaner edges
- Disable depth test on insect particles so they don't vanish behind foliage
- Exempt dragonflies/butterflies/moths from foliage animation freeze
Fireflies, dragonflies, butterflies, and moths no longer get
disableAnimation/foliage classification so their bone animation
and particles run normally.
- Spawn dark point-sprite insects buzzing around cattails/reeds/kelp/seaweed
- Fix firefly M2 particles: exempt from alpha dampening and forced gravity
- Make water shoreline/crest foam more irregular with UV warping and bluer tint
- Play WaterFootstep splash sounds when wading in shallow water
- Spawn foot splash particles at water surface on each water footstep
- Reduce inland water wave amplitude from 0.18 to 0.08 for calmer lakes
Remove negative cache for transient load failures in M2, terrain, and
character renderers. Failed textures return white and will be retried
on next model/tile load when assets may have finished streaming.
- Fix HeightMap::getHeight() to use interleaved 17-wide row layout
matching MCVT storage (was using wrong 9-wide contiguous indexing)
- Guard terrain bump mapping normalize against zero-length vectors
to prevent NaN propagation and GPU faults
- Add aura icons below target frame with buff/debuff color coding
- Show spell icons with hover tooltips and duration countdowns
- Change SPELL_FAILED_ONLY_SHAPESHIFT message to cover warrior stances
- Use authoritative playerRace/playerGender at spawn for voice profiles
instead of unreliable model name parsing
- Support nonbinary gender with useFemaleModel body type fallback
- Move voice setup into spawnPlayerCharacter() for all spawn paths
- Remove legacy single-player default Human Male clip preloading
- Make loading screen text black and move progress bar to top
- Cache material UBO mapped pointers at creation time, eliminating
per-batch vmaGetAllocationInfo() calls in the hot render path
- Precompute foliage/elven/lantern/kobold model name classifications
at load time instead of per-instance string operations every frame
- Remove redundant descriptor set and push constant rebinds on WMO
pipeline switches (preserved across compatible layouts)
- Pre-allocate glow sprite descriptor set once at init instead of
allocating from the pool every frame
Shadow casting: foliage batches now bind their actual texture in the shadow
pass with alpha testing, producing leaf-shaped shadows instead of solid cards.
Uses a per-frame resettable descriptor pool for texture sets.
Shadow receiving: foliage fragments now sample the shadow map with PCF
instead of using a flat constant darkening.
Gameobject M2 instances (books, crates, chests) were continuously
cycling their animations because M2Renderer unconditionally loops
all sequences. Added setInstanceAnimationFrozen() and freeze all
gameobject instances at creation time so they stay in their bind pose.
The legacy spline parser successfully read points but then unconditionally
rewound and re-parsed as compact format. When the data was actually legacy
format, the compact parser would read garbage and fail, causing the entire
update block (and all subsequent blocks in the packet) to be dropped.
This made creatures invisible when their spawn packet contained a spline.