mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-06 09:03:52 +00:00
feat(rendering): implement spell visual effects with bone-tracked ribbons and particles
Add complete spell visual pipeline resolving the DBC chain (Spell → SpellVisual → SpellVisualKit → SpellVisualEffectName → M2) with precast/cast/impact phases, bone-attached positioning, and automatic dual-hand mirroring. Ribbon rendering fixes: - Parse visibility track as uint8 (was read as float, suppressing all ribbon edges due to ~1.4e-45 failing the >0.5 check) - Filter garbage emitters with bone=UINT_MAX unconditionally - Guard against NaN spine positions from corrupt bone data - Resolve ribbon textures via direct index, not textureLookup table - Fall back to bone 0 when ribbon bone index is out of range Particle rendering fixes: - Reduce spell particle scale from 5x to 1.5x (was oversized) - Exempt spell effect instances from position-based deduplication Spell handler integration: - Trigger precast visuals on SMSG_SPELL_START with server castTimeMs - Trigger cast/impact visuals on SMSG_SPELL_GO - Cancel precast visuals on cast interrupt/failure/movement M2 classifier expansion: - Add AmbientEmitterType enum for sound system integration - Add 20+ foliage tokens, 4 spell effect tokens, isSmallFoliage flag - Add markModelAsSpellEffect() to override disableAnimation DBC layouts: - Add SpellVisualID field to Spell.dbc for all expansion configs Signed-off-by: Pavel Okhlopkov <pavel.okhlopkov@flant.com>
This commit is contained in:
parent
0a33e3081c
commit
b79d9b8fea
18 changed files with 803 additions and 90 deletions
|
|
@ -3,6 +3,7 @@
|
|||
#include "rendering/vk_context.hpp"
|
||||
#include "rendering/water_renderer.hpp"
|
||||
#include "rendering/m2_renderer.hpp"
|
||||
#include "rendering/m2_model_classifier.hpp"
|
||||
#include "rendering/wmo_renderer.hpp"
|
||||
#include "rendering/camera.hpp"
|
||||
#include "audio/ambient_sound_manager.hpp"
|
||||
|
|
@ -691,36 +692,21 @@ std::shared_ptr<PendingTile> TerrainManager::prepareTile(int x, int y) {
|
|||
doodadLogCount++;
|
||||
}
|
||||
|
||||
if (m2PathLower.find("fire") != std::string::npos ||
|
||||
m2PathLower.find("brazier") != std::string::npos ||
|
||||
m2PathLower.find("campfire") != std::string::npos) {
|
||||
// Fireplace/brazier emitter
|
||||
auto emitterType = rendering::classifyAmbientEmitter(m2PathLower);
|
||||
if (emitterType != rendering::AmbientEmitterType::None) {
|
||||
PendingTile::AmbientEmitter emitter;
|
||||
emitter.position = worldPos;
|
||||
if (m2PathLower.find("small") != std::string::npos || m2PathLower.find("campfire") != std::string::npos) {
|
||||
emitter.type = 0; // FIREPLACE_SMALL
|
||||
} else {
|
||||
emitter.type = 1; // FIREPLACE_LARGE
|
||||
// Map classifier enum to AmbientSoundManager type codes
|
||||
switch (emitterType) {
|
||||
case rendering::AmbientEmitterType::FireplaceSmall: emitter.type = 0; break;
|
||||
case rendering::AmbientEmitterType::FireplaceLarge: emitter.type = 1; break;
|
||||
case rendering::AmbientEmitterType::Torch: emitter.type = 2; break;
|
||||
case rendering::AmbientEmitterType::Fountain: emitter.type = 3; break;
|
||||
case rendering::AmbientEmitterType::Waterfall: emitter.type = 6; break;
|
||||
case rendering::AmbientEmitterType::Forge: emitter.type = 1; break; // Forge → large fire
|
||||
default: emitter.type = 0; break;
|
||||
}
|
||||
pending->ambientEmitters.push_back(emitter);
|
||||
} else if (m2PathLower.find("torch") != std::string::npos) {
|
||||
// Torch emitter
|
||||
PendingTile::AmbientEmitter emitter;
|
||||
emitter.position = worldPos;
|
||||
emitter.type = 2; // TORCH
|
||||
pending->ambientEmitters.push_back(emitter);
|
||||
} else if (m2PathLower.find("fountain") != std::string::npos) {
|
||||
// Fountain emitter
|
||||
PendingTile::AmbientEmitter emitter;
|
||||
emitter.position = worldPos;
|
||||
emitter.type = 3; // FOUNTAIN
|
||||
pending->ambientEmitters.push_back(emitter);
|
||||
} else if (m2PathLower.find("waterfall") != std::string::npos) {
|
||||
// Waterfall emitter
|
||||
PendingTile::AmbientEmitter emitter;
|
||||
emitter.position = worldPos;
|
||||
emitter.type = 6; // WATERFALL
|
||||
pending->ambientEmitters.push_back(emitter);
|
||||
}
|
||||
|
||||
PendingTile::WMODoodadReady doodadReady;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue