mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-23 07:40:14 +00:00
Add Warrior Charge ability with ribbon trail visual effect
Implements charge rush-to-target for spell IDs 100/6178/11578 with smoothstep lerp movement, vertical red-orange ribbon trail, dust puffs, client-side range validation, and sound fallback chain.
This commit is contained in:
parent
da49593268
commit
e163813dee
9 changed files with 761 additions and 2 deletions
|
|
@ -16,6 +16,7 @@
|
|||
#include "rendering/sky_system.hpp"
|
||||
#include "rendering/swim_effects.hpp"
|
||||
#include "rendering/mount_dust.hpp"
|
||||
#include "rendering/charge_effect.hpp"
|
||||
#include "rendering/levelup_effect.hpp"
|
||||
#include "rendering/character_renderer.hpp"
|
||||
#include "rendering/wmo_renderer.hpp"
|
||||
|
|
@ -359,6 +360,13 @@ bool Renderer::initialize(core::Window* win) {
|
|||
// Create level-up effect (model loaded later via loadLevelUpEffect)
|
||||
levelUpEffect = std::make_unique<LevelUpEffect>();
|
||||
|
||||
// Create charge effect (point-sprite particles + optional M2 models)
|
||||
chargeEffect = std::make_unique<ChargeEffect>();
|
||||
if (!chargeEffect->initialize()) {
|
||||
LOG_WARNING("Failed to initialize charge effect");
|
||||
chargeEffect.reset();
|
||||
}
|
||||
|
||||
// Create character renderer
|
||||
characterRenderer = std::make_unique<CharacterRenderer>();
|
||||
if (!characterRenderer->initialize()) {
|
||||
|
|
@ -1509,12 +1517,20 @@ void Renderer::updateCharacterAnimation() {
|
|||
newState = CharAnimState::IDLE;
|
||||
}
|
||||
break;
|
||||
|
||||
case CharAnimState::CHARGE:
|
||||
// Stay in CHARGE until charging_ is cleared
|
||||
break;
|
||||
}
|
||||
|
||||
if (forceMelee) {
|
||||
newState = CharAnimState::MELEE_SWING;
|
||||
}
|
||||
|
||||
if (charging_) {
|
||||
newState = CharAnimState::CHARGE;
|
||||
}
|
||||
|
||||
if (newState != charAnimState) {
|
||||
charAnimState = newState;
|
||||
}
|
||||
|
|
@ -1573,6 +1589,10 @@ void Renderer::updateCharacterAnimation() {
|
|||
loop = false;
|
||||
break;
|
||||
case CharAnimState::MOUNT: animId = ANIM_MOUNT; loop = true; break;
|
||||
case CharAnimState::CHARGE:
|
||||
animId = ANIM_RUN;
|
||||
loop = true;
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t currentAnimId = 0;
|
||||
|
|
@ -1632,6 +1652,34 @@ void Renderer::triggerLevelUpEffect(const glm::vec3& position) {
|
|||
levelUpEffect->trigger(position);
|
||||
}
|
||||
|
||||
void Renderer::startChargeEffect(const glm::vec3& position, const glm::vec3& direction) {
|
||||
if (!chargeEffect) return;
|
||||
|
||||
// Lazy-load M2 models on first use
|
||||
if (!chargeEffect->isActive() && m2Renderer) {
|
||||
if (!cachedAssetManager) {
|
||||
cachedAssetManager = core::Application::getInstance().getAssetManager();
|
||||
}
|
||||
if (cachedAssetManager) {
|
||||
chargeEffect->tryLoadM2Models(m2Renderer.get(), cachedAssetManager);
|
||||
}
|
||||
}
|
||||
|
||||
chargeEffect->start(position, direction);
|
||||
}
|
||||
|
||||
void Renderer::emitChargeEffect(const glm::vec3& position, const glm::vec3& direction) {
|
||||
if (chargeEffect) {
|
||||
chargeEffect->emit(position, direction);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::stopChargeEffect() {
|
||||
if (chargeEffect) {
|
||||
chargeEffect->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::triggerMeleeSwing() {
|
||||
if (!characterRenderer || characterInstanceId == 0) return;
|
||||
if (meleeSwingCooldown > 0.0f) return;
|
||||
|
|
@ -2008,6 +2056,10 @@ void Renderer::update(float deltaTime) {
|
|||
if (levelUpEffect) {
|
||||
levelUpEffect->update(deltaTime);
|
||||
}
|
||||
// Update charge effect
|
||||
if (chargeEffect) {
|
||||
chargeEffect->update(deltaTime);
|
||||
}
|
||||
|
||||
auto sky2 = std::chrono::high_resolution_clock::now();
|
||||
skyTime += std::chrono::duration<float, std::milli>(sky2 - sky1).count();
|
||||
|
|
@ -2685,6 +2737,11 @@ void Renderer::renderWorld(game::World* world, game::GameHandler* gameHandler) {
|
|||
mountDust->render(*camera);
|
||||
}
|
||||
|
||||
// Render charge effect (red haze + dust)
|
||||
if (chargeEffect && camera) {
|
||||
chargeEffect->render(*camera);
|
||||
}
|
||||
|
||||
// Compute view/projection once for all sub-renderers
|
||||
const glm::mat4& view = camera ? camera->getViewMatrix() : glm::mat4(1.0f);
|
||||
const glm::mat4& projection = camera ? camera->getProjectionMatrix() : glm::mat4(1.0f);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue