2026-04-02 00:21:21 +03:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <unordered_map>
|
|
|
|
|
#include <unordered_set>
|
|
|
|
|
#include <glm/glm.hpp>
|
|
|
|
|
|
|
|
|
|
namespace wowee {
|
|
|
|
|
namespace pipeline { class AssetManager; }
|
|
|
|
|
namespace rendering {
|
|
|
|
|
|
|
|
|
|
class M2Renderer;
|
2026-04-07 11:27:59 +03:00
|
|
|
class Renderer;
|
|
|
|
|
class CharacterRenderer;
|
2026-04-02 00:21:21 +03:00
|
|
|
|
|
|
|
|
class SpellVisualSystem {
|
|
|
|
|
public:
|
|
|
|
|
SpellVisualSystem() = default;
|
|
|
|
|
~SpellVisualSystem() = default;
|
|
|
|
|
|
2026-04-07 11:27:59 +03:00
|
|
|
// Initialize with references to the M2 renderer and parent renderer
|
|
|
|
|
void initialize(M2Renderer* m2Renderer, Renderer* renderer);
|
2026-04-02 00:21:21 +03:00
|
|
|
void shutdown();
|
|
|
|
|
|
|
|
|
|
// Spawn a spell visual at a world position.
|
|
|
|
|
// useImpactKit=false → CastKit path; useImpactKit=true → ImpactKit path
|
|
|
|
|
void playSpellVisual(uint32_t visualId, const glm::vec3& worldPosition,
|
|
|
|
|
bool useImpactKit = false);
|
|
|
|
|
|
2026-04-07 11:27:59 +03:00
|
|
|
// Spawn a precast visual effect at a world position.
|
|
|
|
|
// castTimeMs: server cast time in milliseconds (0 = use anim duration).
|
|
|
|
|
void playSpellVisualPrecast(uint32_t visualId, const glm::vec3& worldPosition,
|
|
|
|
|
uint32_t castTimeMs = 0);
|
|
|
|
|
|
2026-04-02 00:21:21 +03:00
|
|
|
// Advance lifetime timers and remove expired instances.
|
|
|
|
|
void update(float deltaTime);
|
|
|
|
|
|
2026-04-07 11:27:59 +03:00
|
|
|
// Remove all active precast visual instances (cast canceled/interrupted).
|
|
|
|
|
void cancelAllPrecastVisuals();
|
|
|
|
|
|
2026-04-02 00:21:21 +03:00
|
|
|
// Remove all active spell visual instances and reset caches.
|
|
|
|
|
// Called on map change / combat reset.
|
|
|
|
|
void reset();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// Spell visual effects — transient M2 instances spawned by SMSG_PLAY_SPELL_VISUAL/IMPACT
|
|
|
|
|
struct SpellVisualInstance {
|
|
|
|
|
uint32_t instanceId;
|
|
|
|
|
float elapsed;
|
|
|
|
|
float duration; // per-instance lifetime in seconds (from M2 anim or default)
|
2026-04-07 11:27:59 +03:00
|
|
|
bool isPrecast; // true for precast effects (removed on cancel/interrupt)
|
|
|
|
|
uint32_t attachmentId; // character attachment point to track (0=none/static)
|
2026-04-02 00:21:21 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void loadSpellVisualDbc();
|
|
|
|
|
|
|
|
|
|
M2Renderer* m2Renderer_ = nullptr;
|
2026-04-07 11:27:59 +03:00
|
|
|
Renderer* renderer_ = nullptr;
|
2026-04-02 00:21:21 +03:00
|
|
|
pipeline::AssetManager* cachedAssetManager_ = nullptr;
|
|
|
|
|
|
|
|
|
|
std::vector<SpellVisualInstance> activeSpellVisuals_;
|
2026-04-07 11:27:59 +03:00
|
|
|
std::unordered_map<uint32_t, std::string> spellVisualPrecastPath_; // visualId → precast M2 path
|
2026-04-02 00:21:21 +03:00
|
|
|
std::unordered_map<uint32_t, std::string> spellVisualCastPath_; // visualId → cast M2 path
|
|
|
|
|
std::unordered_map<uint32_t, std::string> spellVisualImpactPath_; // visualId → impact M2 path
|
|
|
|
|
std::unordered_map<std::string, uint32_t> spellVisualModelIds_; // M2 path → M2Renderer modelId
|
|
|
|
|
std::unordered_set<uint32_t> spellVisualFailedModels_; // modelIds that failed to load (negative cache)
|
|
|
|
|
uint32_t nextSpellVisualModelId_ = 999000; // Reserved range 999000-999799
|
|
|
|
|
bool spellVisualDbcLoaded_ = false;
|
|
|
|
|
static constexpr float SPELL_VISUAL_MAX_DURATION = 5.0f;
|
|
|
|
|
static constexpr float SPELL_VISUAL_DEFAULT_DURATION = 2.0f;
|
2026-04-07 11:27:59 +03:00
|
|
|
|
|
|
|
|
// Determine character attachment point from model path keywords
|
|
|
|
|
static uint32_t classifyAttachmentId(const std::string& modelPath);
|
|
|
|
|
|
|
|
|
|
// Apply height offset based on model path keywords (Hand → hands, Chest → chest, Base → ground)
|
|
|
|
|
static glm::vec3 applyEffectHeightOffset(const glm::vec3& basePos, const std::string& modelPath);
|
2026-04-02 00:21:21 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // namespace rendering
|
|
|
|
|
} // namespace wowee
|