Merge pull request #1002 from diath/fix_magic_effects

Fix magic effect animations in newer client versions
This commit is contained in:
Konrad Kuśnierz 2019-01-16 13:50:51 +01:00 committed by GitHub
commit 74d328206b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 62 additions and 10 deletions

View File

@ -123,6 +123,24 @@ int Animator::getPhase()
return m_phase; 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<int>(index, m_animationPhases - 1);
}
int Animator::getStartPhase() int Animator::getStartPhase()
{ {
if(m_startPhase > -1) if(m_startPhase > -1)
@ -157,7 +175,7 @@ int Animator::getLoopPhase()
if(m_loopCount == 0) if(m_loopCount == 0)
return 0; return 0;
if(m_currentLoop < (m_loopCount - 1)) { if(m_currentLoop < (m_loopCount - 1)) {
m_currentLoop++; m_currentLoop++;
return 0; return 0;
@ -182,7 +200,7 @@ void Animator::calculateSynchronous()
int totalDuration = 0; int totalDuration = 0;
for(int i = 0; i < m_animationPhases; i++) for(int i = 0; i < m_animationPhases; i++)
totalDuration += getPhaseDuration(i); totalDuration += getPhaseDuration(i);
ticks_t ticks = g_clock.millis(); ticks_t ticks = g_clock.millis();
int elapsedTicks = (int)(ticks % totalDuration); int elapsedTicks = (int)(ticks % totalDuration);
int totalTime = 0; int totalTime = 0;
@ -197,3 +215,13 @@ void Animator::calculateSynchronous()
} }
m_lastPhaseTicks = ticks; m_lastPhaseTicks = ticks;
} }
ticks_t Animator::getTotalDuration()
{
ticks_t time = 0;
for (const auto &pair: m_phaseDurations) {
time += std::get<1>(pair);
}
return time;
}

View File

@ -50,12 +50,15 @@ public:
void setPhase(int phase); void setPhase(int phase);
int getPhase(); int getPhase();
int getPhaseAt(ticks_t time);
int getStartPhase(); int getStartPhase();
int getAnimationPhases() { return m_animationPhases; } int getAnimationPhases() { return m_animationPhases; }
bool isAsync() { return m_async; } bool isAsync() { return m_async; }
bool isComplete() { return m_isComplete; } bool isComplete() { return m_isComplete; }
ticks_t getTotalDuration();
void resetAnimation(); void resetAnimation();
private: private:

View File

@ -22,6 +22,7 @@
#include "effect.h" #include "effect.h"
#include "map.h" #include "map.h"
#include "game.h"
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
void Effect::drawEffect(const Point& dest, float scaleFactor, bool animate, int offsetX, int offsetY, LightView *lightView) 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; return;
int animationPhase = 0; int animationPhase = 0;
if(animate) if(animate) {
animationPhase = std::min<int>((int)(m_animationTimer.ticksElapsed() / m_phaseDuration), getAnimationPhases() - 1); 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>((int)(m_animationTimer.ticksElapsed() / ticks), getAnimationPhases() - 1);
}
}
int xPattern = offsetX % getNumPatternX(); int xPattern = offsetX % getNumPatternX();
if(xPattern < 0) if(xPattern < 0)
@ -47,15 +60,24 @@ void Effect::drawEffect(const Point& dest, float scaleFactor, bool animate, int
void Effect::onAppear() void Effect::onAppear()
{ {
m_animationTimer.restart(); m_animationTimer.restart();
m_phaseDuration = EFFECT_TICKS_PER_FRAME;
// hack to fix some animation phases duration, currently there is no better solution int duration = 0;
if(m_id == 33) if(g_game.getFeature(Otc::GameEnhancedAnimations)) {
m_phaseDuration <<= 2; 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 // schedule removal
auto self = asEffect(); 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) void Effect::setId(uint32 id)

View File

@ -51,7 +51,6 @@ protected:
private: private:
Timer m_animationTimer; Timer m_animationTimer;
uint m_phaseDuration;
uint16 m_id; uint16 m_id;
}; };