diff --git a/src/client/animator.cpp b/src/client/animator.cpp index 4a1d2c6..8ce98f6 100644 --- a/src/client/animator.cpp +++ b/src/client/animator.cpp @@ -125,14 +125,21 @@ int Animator::getPhase() return m_phase; } -int Animator::getPhaseAt(Timer& timer, int lastPhase) +static uint32 getRandomVal(uint32_t seed, int iterations) +{ + for (int i = 0; i < iterations; i++) { + seed = seed * 17 + 3; + } + return seed; +} + +int Animator::getPhaseAt(Timer& timer, uint32_t randomSeed, int lastPhase) { - static int rand_val = 6; ticks_t time = timer.ticksElapsed(); for (int i = lastPhase; i < m_animationPhases; ++i) { int phaseDuration = m_phaseDurations[i].second == 0 ? - m_phaseDurations[i].first : m_phaseDurations[i].first + rand_val % (m_phaseDurations[i].second); - rand_val = rand_val * 7 + 11; + m_phaseDurations[i].first : m_phaseDurations[i].first + getRandomVal(randomSeed, i) % (m_phaseDurations[i].second); + if (time < phaseDuration) { timer.restart(); timer.adjust(-time); @@ -233,11 +240,14 @@ void Animator::calculateSynchronous() m_lastPhaseTicks = ticks; } -ticks_t Animator::getTotalDuration() +ticks_t Animator::getTotalDuration(uint32_t randomSeed) { ticks_t time = 0; + int i = 0; for (const auto &pair: m_phaseDurations) { - time += pair.first + pair.second; + int phaseDuration = pair.second == 0 ? + pair.first : pair.first + getRandomVal(randomSeed, i++) % (pair.second); + time += phaseDuration; } return time; diff --git a/src/client/animator.h b/src/client/animator.h index aebe865..5d5d65f 100644 --- a/src/client/animator.h +++ b/src/client/animator.h @@ -51,14 +51,14 @@ class Animator : public std::enable_shared_from_this void setPhase(int phase); int getPhase(); - int getPhaseAt(Timer& timer, int lastPhase = 0); + int getPhaseAt(Timer& timer, uint32_t randomSeed, int lastPhase = 0); int getStartPhase(); int getAnimationPhases() { return m_animationPhases; } bool isAsync() { return m_async; } bool isComplete() { return m_isComplete; } - ticks_t getTotalDuration(); + ticks_t getTotalDuration(uint32_t randomSeed); void resetAnimation(); diff --git a/src/client/effect.cpp b/src/client/effect.cpp index bbab428..b974ccb 100644 --- a/src/client/effect.cpp +++ b/src/client/effect.cpp @@ -25,6 +25,7 @@ #include "game.h" #include #include +#include void Effect::draw(const Point& dest, int offsetX, int offsetY, bool animate, LightView* lightView) { @@ -34,7 +35,7 @@ void Effect::draw(const Point& dest, int offsetX, int offsetY, bool animate, Lig if(animate) { if(g_game.getFeature(Otc::GameEnhancedAnimations) && rawGetThingType()->getAnimator()) { // This requires a separate getPhaseAt method as using getPhase would make all magic effects use the same phase regardless of their appearance time - m_animationPhase = std::max(0, rawGetThingType()->getAnimator()->getPhaseAt(m_animationTimer, m_animationPhase)); + m_animationPhase = std::max(0, rawGetThingType()->getAnimator()->getPhaseAt(m_animationTimer, m_randomSeed, m_animationPhase)); } else { // hack to fix some animation phases duration, currently there is no better solution int ticks = EFFECT_TICKS_PER_FRAME; @@ -63,7 +64,8 @@ void Effect::onAppear() int duration = 0; if(g_game.getFeature(Otc::GameEnhancedAnimations)) { - duration = getThingType()->getAnimator() ? getThingType()->getAnimator()->getTotalDuration() : 1000; + m_randomSeed = (uint32_t)stdext::fastrand(); + duration = getThingType()->getAnimator() ? getThingType()->getAnimator()->getTotalDuration(m_randomSeed) : 1000; } else { duration = EFFECT_TICKS_PER_FRAME; diff --git a/src/client/effect.h b/src/client/effect.h index 3a0d6e8..9103fa1 100644 --- a/src/client/effect.h +++ b/src/client/effect.h @@ -54,6 +54,7 @@ class Effect : public Thing uint16 m_id; Timer m_animationTimer; int m_animationPhase = 0; + uint32 m_randomSeed; }; #endif