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;
}
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()
{
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;
}

View File

@ -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:

View File

@ -22,6 +22,7 @@
#include "effect.h"
#include "map.h"
#include "game.h"
#include <framework/core/eventdispatcher.h>
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>((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>((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)

View File

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