From a40130d79ba67cb052d8e5ee36d3fe3ba63d4b94 Mon Sep 17 00:00:00 2001 From: Kamil Chojnowski Date: Sat, 5 Jan 2019 22:14:36 +0100 Subject: [PATCH] Fix magic effect animations in newer client versions --- src/client/animator.cpp | 32 ++++++++++++++++++++++++++++++-- src/client/animator.h | 3 +++ src/client/effect.cpp | 36 +++++++++++++++++++++++++++++------- src/client/effect.h | 1 - 4 files changed, 62 insertions(+), 10 deletions(-) diff --git a/src/client/animator.cpp b/src/client/animator.cpp index c81077ba..0382f291 100644 --- a/src/client/animator.cpp +++ b/src/client/animator.cpp @@ -123,6 +123,24 @@ int Animator::getPhase() return m_phase; } +int Animator::getPhaseAt(ticks_t time) +{ + int index = 0; + ticks_t total = 0; + + for(const auto &pair: m_phaseDurations) { + total += std::get<1>(pair); + + if (time < total) { + return index; + } + + ++index; + } + + return std::min(index, m_animationPhases - 1); +} + int Animator::getStartPhase() { if(m_startPhase > -1) @@ -157,7 +175,7 @@ int Animator::getLoopPhase() if(m_loopCount == 0) return 0; - + if(m_currentLoop < (m_loopCount - 1)) { m_currentLoop++; return 0; @@ -182,7 +200,7 @@ void Animator::calculateSynchronous() int totalDuration = 0; for(int i = 0; i < m_animationPhases; i++) totalDuration += getPhaseDuration(i); - + ticks_t ticks = g_clock.millis(); int elapsedTicks = (int)(ticks % totalDuration); int totalTime = 0; @@ -197,3 +215,13 @@ void Animator::calculateSynchronous() } m_lastPhaseTicks = ticks; } + +ticks_t Animator::getTotalDuration() +{ + ticks_t time = 0; + for (const auto &pair: m_phaseDurations) { + time += std::get<1>(pair); + } + + return time; +} diff --git a/src/client/animator.h b/src/client/animator.h index 93d0e1ef..2bf7f845 100644 --- a/src/client/animator.h +++ b/src/client/animator.h @@ -50,12 +50,15 @@ public: void setPhase(int phase); int getPhase(); + int getPhaseAt(ticks_t time); int getStartPhase(); int getAnimationPhases() { return m_animationPhases; } bool isAsync() { return m_async; } bool isComplete() { return m_isComplete; } + ticks_t getTotalDuration(); + void resetAnimation(); private: diff --git a/src/client/effect.cpp b/src/client/effect.cpp index 0ea74a6a..60f254bd 100644 --- a/src/client/effect.cpp +++ b/src/client/effect.cpp @@ -22,6 +22,7 @@ #include "effect.h" #include "map.h" +#include "game.h" #include void Effect::drawEffect(const Point& dest, float scaleFactor, bool animate, int offsetX, int offsetY, LightView *lightView) @@ -30,8 +31,20 @@ void Effect::drawEffect(const Point& dest, float scaleFactor, bool animate, int return; int animationPhase = 0; - if(animate) - animationPhase = std::min((int)(m_animationTimer.ticksElapsed() / m_phaseDuration), getAnimationPhases() - 1); + if(animate) { + if(g_game.getFeature(Otc::GameEnhancedAnimations)) { + // This requires a separate getPhaseAt method as using getPhase would make all magic effects use the same phase regardless of their appearance time + animationPhase = rawGetThingType()->getAnimator()->getPhaseAt(m_animationTimer.ticksElapsed()); + } else { + // hack to fix some animation phases duration, currently there is no better solution + int ticks = EFFECT_TICKS_PER_FRAME; + if (m_id == 33) { + ticks <<= 2; + } + + animationPhase = std::min((int)(m_animationTimer.ticksElapsed() / ticks), getAnimationPhases() - 1); + } + } int xPattern = offsetX % getNumPatternX(); if(xPattern < 0) @@ -47,15 +60,24 @@ void Effect::drawEffect(const Point& dest, float scaleFactor, bool animate, int void Effect::onAppear() { m_animationTimer.restart(); - m_phaseDuration = EFFECT_TICKS_PER_FRAME; - // hack to fix some animation phases duration, currently there is no better solution - if(m_id == 33) - m_phaseDuration <<= 2; + int duration = 0; + if(g_game.getFeature(Otc::GameEnhancedAnimations)) { + duration = getThingType()->getAnimator()->getTotalDuration(); + } else { + duration = EFFECT_TICKS_PER_FRAME; + + // hack to fix some animation phases duration, currently there is no better solution + if(m_id == 33) { + duration <<= 2; + } + + duration *= getAnimationPhases(); + } // schedule removal auto self = asEffect(); - g_dispatcher.scheduleEvent([self]() { g_map.removeThing(self); }, m_phaseDuration * getAnimationPhases()); + g_dispatcher.scheduleEvent([self]() { g_map.removeThing(self); }, duration); } void Effect::setId(uint32 id) diff --git a/src/client/effect.h b/src/client/effect.h index 74e757cd..00a9cdfb 100644 --- a/src/client/effect.h +++ b/src/client/effect.h @@ -51,7 +51,6 @@ protected: private: Timer m_animationTimer; - uint m_phaseDuration; uint16 m_id; };