Commit graph

403 commits

Author SHA1 Message Date
Paul
9b38e64f84 "Fix and refine app initialization flow
- Update core application startup paths and cleanup logic
- Adjust renderer & input subsystem integration for stability
- Address recent staging source updates with robust error handling"
2026-04-01 20:06:26 +03:00
Paul
afeaa13562 chore(application): extract entity spawner + composer, apply app and UI updates
- add include/core/appearance_composer.hpp + src/core/appearance_composer.cpp
- update include/core/application.hpp + src/core/application.cpp
- update src/ui/game_screen.cpp
- adjust CMakeLists.txt and README.md for new composer module
2026-04-01 13:31:48 +03:00
Kelsi
b10a2c28d6 fix(core): guard entity spawner callbacks in asset-failure mode
Some checks are pending
Build / Build (arm64) (push) Waiting to run
Build / Build (x86-64) (push) Waiting to run
Build / Build (macOS arm64) (push) Waiting to run
Build / Build (windows-arm64) (push) Waiting to run
Build / Build (windows-x86-64) (push) Waiting to run
Security / CodeQL (C/C++) (push) Waiting to run
Security / Semgrep (push) Waiting to run
Security / Sanitizer Build (ASan/UBSan) (push) Waiting to run
2026-03-31 22:10:20 -07:00
Paul
cf3ae3bbfe chore(application): refactor app lifecycle and add entity spawner module
- updated CMakeLists.txt to include new module targets
- refactored application.hpp + application.cpp
- added new `entity_spawner` headers + sources:
  - entity_spawner.hpp
  - entity_spawner.cpp
2026-03-31 22:01:55 +03:00
Paul
b6e4e405b6 Merge commit 'ea8b0d9305' into chore/game-screen-extract 2026-03-31 20:17:21 +03:00
Paul
43aecab1ef Merge commit '32bb0becc8' into chore/game-screen-extract 2026-03-31 19:51:37 +03:00
Kelsi
ea8b0d9305 fix: reduce warmup ground-check timeout from 20s to 5s
Some checks are pending
Build / Build (arm64) (push) Waiting to run
Build / Build (x86-64) (push) Waiting to run
Build / Build (macOS arm64) (push) Waiting to run
Build / Build (windows-arm64) (push) Waiting to run
Build / Build (windows-x86-64) (push) Waiting to run
Security / CodeQL (C/C++) (push) Waiting to run
Security / Semgrep (push) Waiting to run
Security / Sanitizer Build (ASan/UBSan) (push) Waiting to run
The warmup loop waited up to 20 seconds for getHeightAt() to return a
terrain height within 15 units of spawn Z before accepting the ground
as ready. In practice, the terrain was loaded and the character was
visibly standing on it, but the height sample didn't match closely
enough (terrain LOD, chunk boundary, or server Z vs client height
mismatch).

Reduce the tile-count fallback timeout from 20s to 5s: if at least 4
tiles are loaded after 5 seconds, accept the ground as ready. The
exact height check still runs in the first 5 seconds for fast-path
cases where it does match.
2026-03-31 01:27:32 -07:00
Paul
9764286cae chore(game-screen): extract toast manager from game screen
- refactor: move toast UI logic into new `ToastManager` component
- add toast_manager.hpp + toast_manager.cpp
- update game_screen.hpp + game_screen.cpp to use `ToastManager`
- adjust app initialization in application.cpp
- keep root CMake target in CMakeLists.txt updated
2026-03-31 09:18:17 +03:00
Kelsi
7cfaf2c7e9 refactor: complete OpenGL→Vulkan migration (Phase 7)
Some checks are pending
Build / Build (arm64) (push) Waiting to run
Build / Build (x86-64) (push) Waiting to run
Build / Build (macOS arm64) (push) Waiting to run
Build / Build (windows-arm64) (push) Waiting to run
Build / Build (windows-x86-64) (push) Waiting to run
Security / CodeQL (C/C++) (push) Waiting to run
Security / Semgrep (push) Waiting to run
Security / Sanitizer Build (ASan/UBSan) (push) Waiting to run
Remove all OpenGL/GLEW code and dependencies. The Vulkan renderer has
been the sole active backend for months; these files were dead code.

Deleted (8 files, 641 lines):
- rendering/mesh.cpp+hpp: OpenGL VAO/VBO/EBO wrapper (never instantiated)
- rendering/shader.cpp+hpp: OpenGL GLSL compiler (replaced by VkShaderModule)
- rendering/scene.cpp+hpp: Scene graph holding Mesh objects (created but
  never populated — all rendering uses Vulkan sub-renderers directly)
- rendering/video_player.cpp+hpp: FFmpeg+GL texture uploader (never
  included by any other file — login video feature can be re-implemented
  with VkTexture when needed)

Cleaned up:
- renderer.hpp: remove Scene forward-decl, getScene() accessor, scene member
- renderer.cpp: remove scene.hpp/shader.hpp includes, Scene create/destroy
- application.cpp: remove stale "GL/glew.h removed" comment
- CMakeLists.txt: remove find_package(OpenGL/GLEW), source/header entries,
  and target_link_libraries for OpenGL::GL and GLEW::GLEW
- PKGBUILD: remove glew dependency
- BUILD_INSTRUCTIONS.md: remove glew from all platform install commands
2026-03-30 19:22:36 -07:00
Kelsi
76d29ad669 fix: address PR #31 and #32 review findings
- Dockerfile: fix LLVM apt repo codename (jammy → noble) for ubuntu:24.04
- build-linux.sh: add missing mkdir -p /wowee-build-src before tar extraction
- Dockerfile: remove dead ENV OSXCROSS_VERSION=1.5 and its unset
- CMakeLists: scope -undefined dynamic_lookup to wowee target only
- GameServices: remove redundant game:: qualifier inside namespace game
- application.cpp: zero out gameServices_ after gameHandler reset in shutdown
2026-03-30 13:40:40 -07:00
Paul
a86efaaa18 [refactor] Break Application::getInstance() from GameHandler
Introduce `GameServices` struct — an explicit dependency bundle that
`Application` populates and passes to `GameHandler` at construction time.
Eliminates all 47 hidden `Application::getInstance()` calls in
`src/game/*.cpp`, completing SOLID-D (dependency-inversion) cleanup.

Changes:
- New `include/game/game_services.hpp` — `struct GameServices` carrying
  pointers to `Renderer`, `AssetManager`, `ExpansionRegistry`, and two
  taxi-mount display IDs
- `GameHandler(GameServices&)` replaces default constructor; exposes
  `services() const` accessor for domain handlers
- `Application` holds `game::GameServices gameServices_`; populates it
  after all subsystems are created, then constructs `GameHandler`
  (fixes latent init-order bug: `GameHandler` was previously created
  before `AssetManager` / `ExpansionRegistry`)
- `game_handler.cpp`: duplicate `isActiveExpansion` / `isClassicLikeExpansion` /
  `isPreWotlk` anonymous-namespace helpers removed; `game_utils.hpp`
  included instead
- All domain handlers (`InventoryHandler`, `SpellHandler`, `MovementHandler`,
  `CombatHandler`, `QuestHandler`, `SocialHandler`, `WardenHandler`) replace
  `Application::getInstance().getXxx()` with `owner_.services().xxx`
2026-03-30 09:17:42 +03:00
Kelsi
74cc048767 fix: watchdog thread called SDL video functions from non-main thread
SDL2 requires video/window functions to be called from the main thread
(the one that called SDL_Init). The watchdog thread was calling
SDL_SetRelativeMouseMode, SDL_ShowCursor, and SDL_SetWindowGrab directly
on stall detection — undefined behavior on macOS (Cocoa requires main-
thread UI calls) and unsafe on other platforms.

Now the watchdog sets an atomic flag, and the main loop checks it at the
top of each iteration, executing the SDL calls on the correct thread.
2026-03-29 21:15:49 -07:00
Kelsi
f02be1ffac fix: tolower/toupper UB on signed char at 10 remaining call sites
Final sweep across mpq_manager, application, auth_screen, wmo_renderer,
character_renderer, and terrain_manager. All now use the unsigned char
cast pattern. No remaining bare ::tolower/::toupper or std::tolower(c)
calls on signed char in the codebase.
2026-03-29 20:27:16 -07:00
Kelsi
d731e0112e fix: std::tolower(char) UB on signed char at 3 call sites
std::tolower(int) has undefined behavior when passed a negative value,
which signed char produces for bytes > 127. The rest of the codebase
correctly casts to unsigned char first; these 3 sites were missed.
2026-03-29 19:43:46 -07:00
Kelsi
e72cb4d380 fix: async creature upload budget blocked cache hits and failures
The per-tick GPU upload budget check ran before consuming async futures,
so after 1 upload ALL remaining ready results were deferred — including
permanent failures and cache hits that need zero GPU work. Moved the
budget gate after failure/cache-hit processing so only actual uploads
count. Re-queues over-budget results as pending spawns for next frame.
2026-03-29 19:16:27 -07:00
Kelsi
5fcb30be1a cleanup: remove dead debug loop in buildCreatureDisplayLookups
Loop iterated 20 hair geoset lookups for Human Male but the if-body
was empty — the LOG statement that was presumably there was removed
but the loop skeleton was left behind.
2026-03-29 19:01:41 -07:00
Kelsi
91c6eef967 fix: suspend gravity for 10s after world entry to prevent WMO fall-through
Stormwind WMO collision takes 25+ seconds to fully load. The warmup
ground check couldn't detect the WMO floor because collision data
wasn't finalized yet. Player spawned and immediately fell through
the unloaded WMO floor into the terrain below (Dun Morogh).

New approach: suspendGravityFor(10s) after world entry. Gravity is
disabled (Z position frozen) until either:
1. A floor is detected by the collision system (gravity resumes instantly)
2. The 10-second timer expires (gravity resumes as fallback)

This handles the case where WMO collision loads during the first few
seconds of gameplay — the player hovers at spawn Z until the floor
appears, then lands normally.

Also fixes faction language for chat (ORCISH for Horde, COMMON for
Alliance) and adds SMSG_MESSAGECHAT diagnostic logging.
2026-03-28 15:50:13 -07:00
Kelsi
2f96bda6fa fix: far same-map teleport blocked packet handler for 41 seconds
loadOnlineWorldTerrain() was called directly from the worldEntryCallback
inside the packet handler, running the 20s warmup loop synchronously.
This blocked ALL packet processing and froze the game for 20-41 seconds.

Now defers the world reload to pendingWorldEntry_ which is processed on
the next frame, outside the packet handler. Position and camera snap
immediately so the player doesn't drift at the old location.

The /y respawn report was actually a server-initiated teleport (possibly
anti-spam or area trigger) that hit this 41-second blocking path.
2026-03-28 15:38:44 -07:00
Kelsi
615db79819 fix: skip all-zero equipment emit, broaden BG announcer filter
Equipment: the first emitOtherPlayerEquipment call fired before any item
queries returned, sending all-zero displayIds that stripped players naked.
Now skips the callback when resolved=0 (waiting for queries). Equipment
only applies once at least one item resolves, preventing the naked flash.

BG announcer: broadened filter to match ALL chat types (not just SYSTEM),
and added more patterns: "BGAnnouncer", "[H: N, A: N]" with spaces.

Also added diagnostic logging in setOnlinePlayerEquipment to trace
displayId counts reaching the renderer.
2026-03-28 15:09:52 -07:00
Kelsi
11571c582b fix: hearthstone from action bar, far teleport loading screen
Action bar hearthstone: the slot was type SPELL (spell 8690) not ITEM.
castSpell sends CMSG_CAST_SPELL which the server rejects for item-use
spells. Now detects item-use spells via getItemIdForSpell() and routes
through useItemById() instead, sending CMSG_USE_ITEM correctly.

Far same-map teleport: hearthstone on the same continent (e.g., Westfall
→ Stormwind on Azeroth) skipped the loading screen, so the player fell
through unloaded terrain. Now triggers a full world reload with loading
screen for teleports > 500 units, with the warmup ground check ensuring
WMO floors are loaded before spawning.
2026-03-28 14:55:58 -07:00
Kelsi
d6b387ae35 fix: increase tile-count fallback from 10s to 20s to prevent premature spawn 2026-03-28 12:04:54 -07:00
Kelsi
5a8ab87a78 fix: warmup checks WMO floor proximity, not just terrain existence
Stormwind players stand on WMO floors ~95m above terrain. The previous
check only tested if terrain existed at the spawn XY (it did — far below).
Now checks WMO floor first, then terrain, requiring the ground to be within
15 units of spawn Z. Falls back to tile count after 10s.

Also adds diagnostic logging for useItemBySlot (hearthstone debug).
2026-03-28 11:34:07 -07:00
Kelsi
8aaa2e7ff3 fix: warmup checks WMO floor + terrain + tile count before spawning
Stormwind players stand on WMO floors, not terrain. The terrain-only
check passed immediately (terrain exists below the city) but the WMO
floor hadn't loaded yet, so the player fell through.

Now checks three ground sources in order:
1. Terrain height at spawn point
2. WMO floor height at spawn point (for cities/buildings)
3. After 8s, accepts if 4+ terrain tiles are loaded (fallback)

Won't exit warmup until at least one ground source returns valid height,
or the 25s hard cap is reached.
2026-03-28 11:23:18 -07:00
Kelsi
7b26938e45 fix: warmup terrain check uses server spawn coords, not character position
The terrain readiness check was using getCharacterPosition() which is
(0,0,0) during warmup — always returned a valid height and exited
immediately, causing the player to spawn before terrain loaded.

Now uses the server-provided spawn coordinates (x,y,z from world entry)
converted to render coords for the terrain query. Also logs when terrain
isn't ready after 5 seconds to show warmup progress.

Player spawn callbacks and equipment re-emit chain confirmed working.
2026-03-28 11:18:36 -07:00
Kelsi
ada95756ce fix: don't exit warmup until terrain under player is loaded
Added terrain readiness check to the warmup exit condition: the loading
screen won't drop until getHeightAt(playerPos) returns a valid height,
ensuring the ground exists under the player's feet before spawning.

Also increased warmup hard cap from 15s to 25s to give terrain more time
to load in cities like Stormwind with dense WMO/M2 assets.

Equipment re-emit chain confirmed working: items resolve 3-4 seconds
after spawn and equipment is re-applied with valid displayIds.
2026-03-28 11:09:36 -07:00
Kelsi
e2383725f0 security: path traversal rejection, packet length validation; code quality
Security:
- Asset loader rejects paths containing ".." sequences (path traversal)
- Chat message parser validates length against remaining packet bytes
  before resize(), preventing memory exhaustion from malformed packets

Code quality:
- Extract 11 named geoset constants (kGeosetBareForearms, kGeosetWithCape,
  etc.) replacing ~40 magic number sites across 4 code paths
- Add build-debug/ and .claude/ to .gitignore
- Remove .claude/scheduled_tasks.lock from tracking
2026-03-27 18:42:48 -07:00
Kelsi
dee90d2951 fix: NPC/player attack animation uses weapon-appropriate anim ID
NPC and other-player melee swing callback was hardcoded to animation 16
(unarmed attack). Now tries 17 (1H weapon), 18 (2H weapon) first with
hasAnimation() check, falling back to 16 if neither exists on the model.
2026-03-27 18:14:29 -07:00
Kelsi
b366773f29 fix: inspect (packed GUID), follow (client-side auto-walk); add loot/raid commands
Inspect: CMSG_INSPECT was writing full uint64 GUID instead of packed GUID.
Server silently rejected the malformed packet. Fixed both InspectPacket and
QueryInspectAchievementsPacket to use writePackedGuid().

Follow: was a no-op (only stored GUID). Added client-side auto-follow system:
camera controller walks toward followed entity, faces target, cancels on
WASD/mouse input, stops within 3 units, cancels at 40+ units distance.

Party commands:
- /lootmethod (ffa/roundrobin/master/group/nbg) sends CMSG_LOOT_METHOD
- /lootthreshold (0-5 or quality name) sets minimum loot quality
- /raidconvert converts party to raid (leader only)

Equipment diagnostic logging still active for debugging naked players.
2026-03-27 17:54:56 -07:00
Kelsi
a20f46f0b6 feat: render shoulder armor M2 models on other players and NPCs
Shoulder pieces are M2 model attachments (like helmets), not body geosets.
Load left shoulder at attachment point 5, right shoulder at point 6.
Models resolved from ItemDisplayInfo.dbc LeftModel/RightModel fields,
with race/gender suffix variants tried first. Applied to both online
player and NPC equipment paths.
2026-03-27 17:35:42 -07:00
Kelsi
0396a42beb feat: render equipment on other players (helmets, weapons, belts, wrists)
Other players previously appeared partially naked — only chest, legs, feet,
hands, cape, and tabard rendered. Now renders full equipment:

- Helmet M2 model: loads from ItemDisplayInfo.dbc with race/gender suffix,
  attaches at head bone (point 0/11), hides hair geoset under helm
- Weapons: mainhand (attachment 1) and offhand (attachment 2) M2 models
  loaded from ItemDisplayInfo, with Weapon/Shield path fallback
- Wrist/bracer geoset (group 8): applies when no chest sleeve overrides
- Belt/waist geoset (group 18): reads GeosetGroup1 from ItemDisplayInfo
- Shoulder M2 attachments deferred (separate bone attachment system)

Also applied same wrist/waist geosets to NPC and character preview paths.

Minimap: batch 9 individual vkUpdateDescriptorSets into single call.
2026-03-27 17:30:35 -07:00
Kelsi
50a3eb7f07 fix: mail money uint64, other-player cape textures, zone toast dedup, TCP_NODELAY
Mail: change money/COD fields from uint32 to uint64 in CMSG_SEND_MAIL and
SMSG_MAIL_LIST_RESULT for WotLK 3.3.5a. Classic keeps uint32 on the wire.
Fixes money truncation and packet misalignment causing mail failures.

Other-player capes: add cape texture loading to setOnlinePlayerEquipment().
The cape geoset was enabled but no texture was loaded, leaving capes blank.
Now mirrors the local-player path: looks up ItemDisplayInfo.dbc, finds cape
texture candidates, applies via setGroupTextureOverride/setTextureSlotOverride.

Zone toasts: suppress duplicate zone toast when the zone text overlay is
already showing the same zone name. Fixes double "Entering: Stormwind City".

Network: enable TCP_NODELAY on both auth and world sockets after connect(),
disabling Nagle's algorithm to eliminate up to 200ms buffering delay on
small packets (movement, spell casts, chat).

Rendering: track material and bone descriptor sets in M2 renderer to skip
redundant vkCmdBindDescriptorSets calls between batches sharing same textures.
2026-03-27 17:20:31 -07:00
Kelsi
6b1c728377 perf: eliminate double map lookups, dynamic_cast in render loops, div by 255
- Replace count()+operator[] double lookups with find() or try_emplace()
  in gameObjectInstances_, playerTextureSlotsByModelId_, onlinePlayerAppearance_
- Add Entity::isUnit() helper; replace 5 dynamic_cast<Unit*> in per-frame
  UI rendering (nameplates, combat text, pet frame) with isUnit()+static_cast
- Add constexpr kInv255 reciprocal for per-pixel normal map generation loops
  in character_renderer and wmo_renderer
2026-03-27 17:04:13 -07:00
Kelsi
b0466e9029 perf: eliminate ~70 unnecessary sqrt ops per frame, optimize caches and threading
Squared distance optimizations across 30 files:
- Convert glm::length() comparisons to glm::dot() (no sqrt)
- Use glm::inversesqrt() for check-then-normalize patterns (1 rsqrt vs 2 sqrt)
- Defer sqrt to after early-out checks in collision/movement code
- Hottest paths: camera_controller (21), weather particles, WMO collision,
  transport movement, creature interpolation, nameplate culling

Container and algorithm improvements:
- std::map<string> → std::unordered_map for asset/DBC/MPQ/warden caches
- std::mutex → std::shared_mutex for asset_manager and mpq_manager caches
- std::sort → std::partial_sort in lighting_manager (top-2 of N volumes)
- Double-lookup find()+operator[] → insert_or_assign in game_handler
- Add reserve() for per-frame vectors: weather, swim_effects, WMO/M2 collision

Threading and synchronization:
- Replace 1ms busy-wait polling with condition_variable in character_renderer
- Move timestamp capture before mutex in logger
- Use memory_order_acquire/release for normal map completion signaling

API additions:
- DBC getStringView()/getStringViewByOffset() for zero-copy string access
- Parse creature display IDs from SMSG_CREATURE_QUERY_SINGLE_RESPONSE
2026-03-27 16:33:16 -07:00
Kelsi
c762688202 refactor: promote static const arrays to constexpr across audio/core/rendering
audio: birdPaths, cricketPaths, races
core/application: componentDirs (4 instances), compDirs
rendering/character_preview: componentDirs
rendering/character_renderer: regionCoords256, regionSizes256
2026-03-27 15:31:21 -07:00
Kelsi
ff77febb36 fix: guard std::stoi/stof calls at input boundaries against exceptions
Wrap string-to-number conversions in try-catch where input comes from
external sources (realm address port, last_world.cfg, keybinding config,
ADT tile filenames) to prevent crashes on malformed data.
2026-03-27 10:14:49 -07:00
Kelsi
56f8f5c592 refactor: extract loadWeaponM2() to deduplicate weapon model loading
Extract shared M2+skin loading logic into Application::loadWeaponM2(),
replacing duplicate 15-line blocks in loadEquippedWeapons() and
tryAttachCreatureVirtualWeapons(). Future weapon loading changes only
need to update one place.
2026-03-25 14:17:19 -07:00
Kelsi
05f2bedf88 refactor: replace C-style casts with static_cast and extract toLowerInPlace
Replace ~300 C-style casts ((int), (float), (uint32_t), etc.) with
static_cast across 15 source files. Extract toLowerInPlace() helper in
lua_engine.cpp to replace 72 identical tolower loop patterns.
2026-03-25 11:40:49 -07:00
Kelsi
7a5d80e801 fix: flush GPU before first render frame after world load
Add vkDeviceWaitIdle after world loading completes to ensure all async
texture uploads and resource creation are fully flushed before the
first render frame. Mitigates intermittent NVIDIA driver crashes at
vkCmdBeginRenderPass during initial world entry.
2026-03-24 13:34:52 -07:00
Kelsi
891b9e5822 fix: show friendly map names on loading screen (Outland not Expansion01)
Add mapDisplayName() with friendly names for continents: "Eastern
Kingdoms", "Kalimdor", "Outland", "Northrend". The loading screen
previously showed WDT directory names like "Expansion01" when
Map.dbc's localized name field was empty or matched the internal name.
2026-03-24 13:20:06 -07:00
Kelsi
d44411c304 fix: convert PLAY_OBJECT_SOUND positions to render coords for 3D audio
Entity positions are in canonical WoW coords (X=north, Y=west) but the
audio listener uses render coords (X=west, Y=north) from the camera.
Without conversion, distance attenuation was computed on swapped axes,
making NPC ambient sounds (peasant voices, etc.) play at wrong volumes
regardless of actual distance.
2026-03-24 10:17:47 -07:00
Kelsi
c09a443b18 cleanup: remove temporary PLAY_SOUND diagnostic logging 2026-03-24 10:13:31 -07:00
Kelsi
d2a396df11 feat: log GPU vendor/name at init, add PLAY_SOUND diagnostics
Log GPU name and vendor ID during VkContext initialization for easier
debugging of GPU-specific issues (FSR3, driver compat, etc.). Add
isAmdGpu()/isNvidiaGpu() accessors.

Temporarily log SMSG_PLAY_SOUND and SMSG_PLAY_OBJECT_SOUND at WARN
level (sound ID, name, file path) to diagnose unidentified ambient
NPC sounds reported by the user.
2026-03-24 09:56:54 -07:00
Kelsi
503f9ed650 fix: auto-detect CharSections.dbc layout and add Blood Elf/Draenei NPC voices
CharSections.dbc has different field layouts between stock WotLK (textures
at field 4-6) and Classic/TBC/Turtle/HD-textured WotLK (VariationIndex at
field 4). Add detectCharSectionsFields() that probes field-4 values at
runtime to determine the correct layout, so both stock and modded clients
work without JSON changes.

Also add BLOODELF_MALE/FEMALE and DRAENEI_MALE/FEMALE voice types to the
NPC voice system — previously all Blood Elf and Draenei NPCs fell through
to GENERIC (random dwarf/gnome/night elf/orc mix).
2026-03-23 11:00:49 -07:00
Kelsi
aa164478e1 feat: fire DISPLAY_SIZE_CHANGED and UNIT_QUEST_LOG_CHANGED events
DISPLAY_SIZE_CHANGED fires when the window is resized via
SDL_WINDOWEVENT_RESIZED, allowing UI addons to adapt their layout
to the new screen dimensions (5 FrameXML registrations).

UNIT_QUEST_LOG_CHANGED("player") fires alongside QUEST_LOG_UPDATE
at all 6 quest log modification points, for addons that register
for this variant instead (4 FrameXML registrations).
2026-03-22 19:29:06 -07:00
Kelsi
e9ce062112 fix: restore correct CharSections.dbc field indices for character textures
PR #19 (572bb4ef) swapped CharSections.dbc field indices, placing
Texture1-3 at fields 4-6 and VariationIndex/ColorIndex at 8-9. Binary
analysis of the actual DBC files (Classic, TBC, Turtle — all identical
layout, no WotLK-specific override) confirms the correct order is:

  Field 4 = VariationIndex
  Field 5 = ColorIndex
  Field 6 = Texture1 (string)
  Field 7 = Texture2 (string)
  Field 8 = Texture3 (string)
  Field 9 = Flags

With the wrong indices, VariationIndex/ColorIndex reads returned string
offsets (garbage values that never matched), so all CharSections lookups
failed silently — producing white untextured character models at the
login screen and in-world.

Fixes all 4 expansion JSON layouts, hardcoded fallbacks in
character_preview.cpp, application.cpp, and character_create_screen.cpp.
Also handles the single-layer edge case (body skin only, no face/underwear)
by loading the texture directly instead of skipping compositing.
2026-03-22 15:22:25 -07:00
Paul
027640189a make start on ubuntu intel video cards 2026-03-22 21:47:12 +03:00
Kelsi
a4c8fd621d fix: use geoset 503 for bare shins to reduce knee width discontinuity
Change the bare shin (no boots) default from geoset 502 to 503 across
all four code paths (character creation, character preview, equipment
update, NPC rendering).

Geoset 503 has Y width ~0.44 which better matches the thigh mesh
width (~0.42) than 502's width (~0.39), reducing the visible gap at
the knee joint where lower and upper leg meshes meet.
2026-03-21 13:53:02 -07:00
Kelsi
19b8d31da2 feat: display Lua addon errors as in-game UI errors
Previously Lua addon errors only logged to the log file. Now they
display as red UI error text to the player (same as spell errors and
game warnings), helping addon developers debug issues in real-time.

Add LuaErrorCallback to LuaEngine, fire it from event handler and
frame OnEvent pcall error paths. Wire the callback to GameHandler's
addUIError in application.cpp.
2026-03-21 06:00:06 -07:00
Kelsi
494175e2a7 feat: add remaining CHAT_MSG_* event mappings
Map 5 previously unmapped chat types to addon events:
- CHAT_MSG_MONSTER_PARTY (NPC party chat in dungeons/scripted events)
- CHAT_MSG_AFK (player AFK auto-reply messages)
- CHAT_MSG_DND (player DND auto-reply messages)
- CHAT_MSG_LOOT (loot roll/distribution messages)
- CHAT_MSG_SKILL (skill-up messages)

All WoW chat types in the ChatType enum are now mapped to addon events.
2026-03-21 04:57:19 -07:00
Kelsi
70a5d3240c feat: add ACHIEVEMENT_EARNED event and 15 missing CHAT_MSG_* events
Fire ACHIEVEMENT_EARNED event when a player earns an achievement,
enabling achievement tracking addons.

Add 15 previously unmapped chat type → addon event mappings:
- CHAT_MSG_ACHIEVEMENT, CHAT_MSG_GUILD_ACHIEVEMENT
- CHAT_MSG_WHISPER_INFORM (echo of sent whispers)
- CHAT_MSG_RAID_LEADER, CHAT_MSG_BATTLEGROUND_LEADER
- CHAT_MSG_MONSTER_SAY/YELL/EMOTE/WHISPER
- CHAT_MSG_RAID_BOSS_EMOTE/WHISPER
- CHAT_MSG_BG_SYSTEM_NEUTRAL/ALLIANCE/HORDE

These events are needed by boss mod addons (DBM, BigWigs) to detect
boss emotes, by achievement trackers, and by chat filter addons that
process all message types.
2026-03-21 04:28:15 -07:00