diff options
Diffstat (limited to 'src')
11 files changed, 117 insertions, 53 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index e39c596c60a..30e04dbd629 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -13367,11 +13367,11 @@ uint32 Unit::GetRemainingPeriodicAmount(ObjectGuid caster, uint32 spellId, AuraT  {      uint32 amount = 0;      AuraEffectList const& periodicAuras = GetAuraEffectsByType(auraType); -    for (AuraEffectList::const_iterator i = periodicAuras.begin(); i != periodicAuras.end(); ++i) +    for (AuraEffect const* aurEff : periodicAuras)      { -        if ((*i)->GetCasterGUID() != caster || (*i)->GetId() != spellId || (*i)->GetEffIndex() != effectIndex || !(*i)->GetTotalTicks()) +        if (aurEff->GetCasterGUID() != caster || aurEff->GetId() != spellId || aurEff->GetEffIndex() != effectIndex || !aurEff->GetTotalTicks())              continue; -        amount += uint32(((*i)->GetAmount() * std::max<int32>((*i)->GetTotalTicks() - int32((*i)->GetTickNumber()), 0)) / (*i)->GetTotalTicks()); +        amount += uint32((aurEff->GetAmount() * static_cast<int32>(aurEff->GetRemainingTicks())) / aurEff->GetTotalTicks());          break;      } diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 89aaa7db4c6..eef239d13b5 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -578,7 +578,7 @@ AuraEffect::AuraEffect(Aura* base, SpellEffectInfo const* spellEfffectInfo, int3  m_base(base), m_spellInfo(base->GetSpellInfo()), m_effectInfo(spellEfffectInfo), m_spellmod(nullptr),  m_baseAmount(baseAmount ? *baseAmount : spellEfffectInfo->CalcBaseValue(caster, base->GetType() == UNIT_AURA_TYPE ? base->GetOwner()->ToUnit() : nullptr, base->GetCastItemId(), base->GetCastItemLevel())),  m_damage(0), m_critChance(0.0f), m_donePct(1.0f), -m_periodicTimer(0), m_tickNumber(0), +_periodicTimer(0), _period(0), _ticksDone(0),  m_canBeRecalculated(true), m_isPeriodic(false)  {      CalculatePeriodic(caster, true, false); @@ -673,18 +673,26 @@ int32 AuraEffect::CalculateAmount(Unit* caster)      return amount;  } +void AuraEffect::ResetPeriodic(bool resetPeriodicTimer /*= false*/) +{ +    _ticksDone = 0; +    if (resetPeriodicTimer) +    { +        _periodicTimer = _period; +        // Start periodic on next tick or at aura apply +        if (!m_spellInfo->HasAttribute(SPELL_ATTR5_START_PERIODIC_AT_APPLY)) +            _periodicTimer = 0; +    } +} +  void AuraEffect::CalculatePeriodic(Unit* caster, bool resetPeriodicTimer /*= true*/, bool load /*= false*/)  { -    m_period = GetSpellEffectInfo()->ApplyAuraPeriod; +    _period = GetSpellEffectInfo()->ApplyAuraPeriod;      // prepare periodics      switch (GetAuraType())      {          case SPELL_AURA_OBS_MOD_POWER: -            // 3 spells have no amplitude set -            if (!m_period) -                m_period = 1 * IN_MILLISECONDS; -            /* fallthrough */          case SPELL_AURA_PERIODIC_DAMAGE:          case SPELL_AURA_PERIODIC_HEAL:          case SPELL_AURA_OBS_MOD_HEALTH: @@ -703,49 +711,48 @@ void AuraEffect::CalculatePeriodic(Unit* caster, bool resetPeriodicTimer /*= tru              break;      } -    GetBase()->CallScriptEffectCalcPeriodicHandlers(this, m_isPeriodic, m_period); +    GetBase()->CallScriptEffectCalcPeriodicHandlers(this, m_isPeriodic, _period);      if (!m_isPeriodic)          return;      Player* modOwner = caster ? caster->GetSpellModOwner() : nullptr;      // Apply casting time mods -    if (m_period) +    if (_period)      {          // Apply periodic time mod          if (modOwner) -            modOwner->ApplySpellMod(GetSpellInfo(), SPELLMOD_ACTIVATION_TIME, m_period); +            modOwner->ApplySpellMod(GetSpellInfo(), SPELLMOD_ACTIVATION_TIME, _period);          if (caster)          {              // Haste modifies periodic time of channeled spells              if (m_spellInfo->IsChanneled()) -                caster->ModSpellDurationTime(m_spellInfo, m_period); +                caster->ModSpellDurationTime(m_spellInfo, _period);              else if (m_spellInfo->HasAttribute(SPELL_ATTR5_HASTE_AFFECT_DURATION)) -                m_period = int32(m_period * caster->m_unitData->ModCastingSpeed); +                _period = int32(_period * caster->m_unitData->ModCastingSpeed);          }      } +    else // prevent infinite loop on Update +        m_isPeriodic = false;      if (load) // aura loaded from db      { -        m_tickNumber = m_period ? GetBase()->GetDuration() / m_period : 0; -        m_periodicTimer = m_period ? GetBase()->GetDuration() % m_period : 0; +        if (_period && !GetBase()->IsPermanent()) +        { +            uint32 elapsedTime = GetBase()->GetMaxDuration() - GetBase()->GetDuration(); +            _ticksDone = elapsedTime / uint32(_period); +            _periodicTimer = elapsedTime % uint32(_period); +        } +          if (m_spellInfo->HasAttribute(SPELL_ATTR5_START_PERIODIC_AT_APPLY)) -            ++m_tickNumber; +            ++_ticksDone;      }      else // aura just created or reapplied      { -        m_tickNumber = 0; -          // reset periodic timer on aura create or reapply          // we don't reset periodic timers when aura is triggered by proc -        if (resetPeriodicTimer) -        { -            m_periodicTimer = 0; -            // Start periodic on next tick or at aura apply -            if (m_period && !m_spellInfo->HasAttribute(SPELL_ATTR5_START_PERIODIC_AT_APPLY)) -                m_periodicTimer += m_period; -        } +        ResetPeriodic(resetPeriodicTimer);      }  } @@ -908,12 +915,12 @@ void AuraEffect::ApplySpellMod(Unit* target, bool apply)                      }                      else if (GetMiscValue() == SPELLMOD_EFFECT1)                      { -                       if (AuraEffect* aurEff = aura->GetEffect(0)) +                        if (AuraEffect* aurEff = aura->GetEffect(0))                              aurEff->RecalculateAmount();                      }                      else if (GetMiscValue() == SPELLMOD_EFFECT2)                      { -                       if (AuraEffect* aurEff = aura->GetEffect(1)) +                        if (AuraEffect* aurEff = aura->GetEffect(1))                              aurEff->RecalculateAmount();                      }                      else if (GetMiscValue() == SPELLMOD_EFFECT3) @@ -941,16 +948,18 @@ void AuraEffect::ApplySpellMod(Unit* target, bool apply)  void AuraEffect::Update(uint32 diff, Unit* caster)  { -    if (m_isPeriodic && (GetBase()->GetDuration() >=0 || GetBase()->IsPassive() || GetBase()->IsPermanent())) +    if (m_isPeriodic && (GetBase()->GetDuration() >= 0 || GetBase()->IsPassive() || GetBase()->IsPermanent()))      { -        if (m_periodicTimer > int32(diff)) -            m_periodicTimer -= diff; -        else // tick also at m_periodicTimer == 0 to prevent lost last tick in case max m_duration == (max m_periodicTimer)*N +        _periodicTimer += diff; +        while (_periodicTimer >= _period)          { -            ++m_tickNumber; +            _periodicTimer -= _period; + +            if (!GetBase()->IsPermanent() && (_ticksDone + 1) > GetTotalTicks()) +                break; + +            ++_ticksDone; -            // update before tick (aura can be removed in TriggerSpell or PeriodicTick calls) -            m_periodicTimer += m_period - diff;              UpdatePeriodic(caster);              std::vector<AuraApplication*> effectApplications; @@ -1029,7 +1038,7 @@ void AuraEffect::UpdatePeriodic(Unit* caster)                                          // on 2 tick - 133% (handled in 6 second)                                          // Apply bonus for 1 - 4 tick -                                        switch (m_tickNumber) +                                        switch (_ticksDone)                                          {                                              case 1:   // 0%                                                  aurEff->ChangeAmount(0); @@ -1067,7 +1076,7 @@ void AuraEffect::UpdatePeriodic(Unit* caster)                      if (GetSpellInfo()->SpellFamilyFlags[1] & 0x00004000)                      {                          // Get 0 effect aura -                        if (AuraEffect* slow = GetBase()->GetEffect(0)) +                        if (AuraEffect* slow = GetBase()->GetEffect(EFFECT_0))                          {                              int32 newAmount = slow->GetAmount() + GetAmount();                              if (newAmount > 0) @@ -1104,7 +1113,7 @@ void AuraEffect::SendTickImmune(Unit* target, Unit* caster) const          caster->SendSpellDamageImmune(target, m_spellInfo->Id, true);  } -void AuraEffect::PeriodicTick(AuraApplication * aurApp, Unit* caster) const +void AuraEffect::PeriodicTick(AuraApplication* aurApp, Unit* caster) const  {      bool prevented = GetBase()->CallScriptEffectPeriodicHandlers(this, aurApp);      if (prevented) @@ -5525,11 +5534,11 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster)                  return;              // Negative Energy Periodic              case 46284: -                target->CastCustomSpell(triggerSpellId, SPELLVALUE_MAX_TARGETS, m_tickNumber / 10 + 1, nullptr, true, nullptr, this); +                target->CastCustomSpell(triggerSpellId, SPELLVALUE_MAX_TARGETS, _ticksDone / 10 + 1, nullptr, true, nullptr, this);                  return;              // Slime Pool (Dreadscale & Acidmaw)              case 66882: -                target->CastCustomSpell(triggerSpellId, SPELLVALUE_RADIUS_MOD, (int32)((((float)m_tickNumber / 60) * 0.9f + 0.1f) * 10000 * 2 / 3), nullptr, true, nullptr, this); +                target->CastCustomSpell(triggerSpellId, SPELLVALUE_RADIUS_MOD, static_cast<int32>(((_ticksDone / 60.f) * 0.9f + 0.1f) * 10000.f * 2.f / 3.f), nullptr, true, nullptr, this);                  return;              // Slime Spray - temporary here until preventing default effect works again              // added on 9.10.2010 @@ -5681,7 +5690,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const                      case 72854: // Unbound Plague                      case 72855: // Unbound Plague                      case 72856: // Unbound Plague -                        damage *= uint32(pow(1.25f, int32(m_tickNumber))); +                        damage *= uint32(pow(1.25f, int32(_ticksDone)));                          break;                      default:                          break; diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index e2a9c1608de..b2aba79de95 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -49,7 +49,7 @@ class TC_GAME_API AuraEffect          uint32 GetId() const { return m_spellInfo->Id; }          uint32 GetEffIndex() const { return m_effectInfo->EffectIndex; }          int32 GetBaseAmount() const { return m_baseAmount; } -        int32 GetPeriod() const { return m_period; } +        int32 GetPeriod() const { return _period; }          int32 GetMiscValueB() const { return GetSpellEffectInfo()->MiscValueB; }          int32 GetMiscValue() const { return GetSpellEffectInfo()->MiscValue; } @@ -57,8 +57,8 @@ class TC_GAME_API AuraEffect          int32 GetAmount() const { return m_amount; }          void SetAmount(int32 amount) { m_amount = amount; m_canBeRecalculated = false;} -        int32 GetPeriodicTimer() const { return m_periodicTimer; } -        void SetPeriodicTimer(int32 periodicTimer) { m_periodicTimer = periodicTimer; } +        int32 GetPeriodicTimer() const { return _periodicTimer; } +        void SetPeriodicTimer(int32 periodicTimer) { _periodicTimer = periodicTimer; }          int32 CalculateAmount(Unit* caster);          void CalculatePeriodic(Unit* caster, bool resetPeriodicTimer = true, bool load = false); @@ -82,9 +82,11 @@ class TC_GAME_API AuraEffect          void Update(uint32 diff, Unit* caster);          void UpdatePeriodic(Unit* caster); -        uint32 GetTickNumber() const { return m_tickNumber; } -        int32 GetTotalTicks() const { return m_period ? (GetBase()->GetMaxDuration() / m_period) : 1;} -        void ResetPeriodic(bool resetPeriodicTimer = false) { if (resetPeriodicTimer) m_periodicTimer = m_period; m_tickNumber = 0;} +        void ResetTicks() { _ticksDone = 0; } +        uint32 GetTickNumber() const { return _ticksDone; } +        uint32 GetRemainingTicks() const { return GetTotalTicks() - _ticksDone; } +        uint32 GetTotalTicks() const { return (_period && !GetBase()->IsPermanent()) ? uint32(GetBase()->GetMaxDuration() / _period) : uint32(0); } +        void ResetPeriodic(bool resetPeriodicTimer = false);          bool IsPeriodic() const { return m_isPeriodic; }          void SetPeriodic(bool isPeriodic) { m_isPeriodic = isPeriodic; } @@ -120,9 +122,10 @@ class TC_GAME_API AuraEffect          float m_critChance;          float m_donePct; -        int32 m_periodicTimer; -        int32 m_period; -        uint32 m_tickNumber; +        // periodic stuff +        int32 _periodicTimer; +        int32 _period;          // time between consecutive ticks +        uint32 _ticksDone;      // ticks counter          bool m_canBeRecalculated;          bool m_isPeriodic; diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 1d55107b1b1..bbabf96b85e 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -799,6 +799,11 @@ void Aura::RefreshDuration(bool withMods)      if (!m_periodicCosts.empty())          m_timeCla = 1 * IN_MILLISECONDS; + +    // also reset periodic counters +    for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) +        if (AuraEffect* aurEff = GetEffect(i)) +            aurEff->ResetTicks();  }  void Aura::RefreshTimers(bool resetPeriodicTimer) diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 8e4de205301..8c2c1f69853 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3207,6 +3207,43 @@ void SpellMgr::LoadSpellInfoCorrections()  {      uint32 oldMSTime = getMSTime(); +    // Some spells have no amplitude set +    { +        ApplySpellFix({ +            6727,  // Poison Mushroom +            7331,  // Healing Aura (TEST) (Rank 1) +            /* +            30400, // Nether Beam - Perseverance +                Blizzlike to have it disabled? DBC says: +                "This is currently turned off to increase performance. Enable this to make it fire more frequently." +            */ +            34589, // Dangerous Water +            52562, // Arthas Zombie Catcher +            57550, // Tirion Aggro +            65755 +        }, [](SpellInfo* spellInfo) +        { +            const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->ApplyAuraPeriod = 1 * IN_MILLISECONDS; +        }); + +        ApplySpellFix({ +            24707, // Food +            26263, // Dim Sum +            29055, // Refreshing Red Apple +            37504  // Karazhan - Chess NPC AI, action timer +        }, [](SpellInfo* spellInfo) +        { +            // first effect has correct amplitude +            const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->ApplyAuraPeriod = const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->ApplyAuraPeriod; +        }); + +        // Vomit +        ApplySpellFix({ 43327 }, [](SpellInfo* spellInfo) +        { +            const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->ApplyAuraPeriod = 1 * IN_MILLISECONDS; +        }); +    } +      ApplySpellFix({          63026, // Summon Aspirant Test NPC (HACK: Target shouldn't be changed)          63137  // Summon Valiant Test (HACK: Target shouldn't be changed; summon position should be untied from spell destination) diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp index 8528aba9fb7..511c0e17893 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp @@ -149,7 +149,7 @@ class spell_marwyn_shared_suffering : public SpellScriptLoader                  if (Unit* caster = GetCaster())                  { -                    int32 remainingDamage = aurEff->GetAmount() * (aurEff->GetTotalTicks() - aurEff->GetTickNumber()); +                    int32 remainingDamage = aurEff->GetAmount() * aurEff->GetRemainingTicks();                      if (remainingDamage > 0)                          caster->CastCustomSpell(SPELL_SHARED_SUFFERING_DISPEL, SPELLVALUE_BASE_POINT1, remainingDamage, GetTarget(), TRIGGERED_FULL_MASK);                  } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp index cb7beeafb42..73dcd478546 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp @@ -200,6 +200,8 @@ class spell_grobbulus_poison_cloud : public SpellScriptLoader              void PeriodicTick(AuraEffect const* aurEff)              {                  PreventDefaultAction(); +                if (!aurEff->GetTotalTicks()) +                    return;                  uint32 triggerSpell = aurEff->GetSpellEffectInfo()->TriggerSpell;                  int32 mod = int32(((float(aurEff->GetTickNumber()) / aurEff->GetTotalTicks()) * 0.9f + 0.1f) * 10000 * 2 / 3); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp index df299a03c50..41c5b3c68d6 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp @@ -976,7 +976,7 @@ struct npc_thorim_trashAI : public ScriptedAI              uint32 heal = 0;              Unit::AuraEffectList const& auras = target->GetAuraEffectsByType(SPELL_AURA_PERIODIC_HEAL);              for (AuraEffect const* aurEff : auras) -                heal += aurEff->GetAmount() * (aurEff->GetTotalTicks() - aurEff->GetTickNumber()); +                heal += aurEff->GetAmount() * aurEff->GetRemainingTicks();              return heal;          } diff --git a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp index a1737fc4e11..f8ae540f12e 100644 --- a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp @@ -178,6 +178,8 @@ class spell_broggok_poison_cloud : public SpellScriptLoader              void PeriodicTick(AuraEffect const* aurEff)              {                  PreventDefaultAction(); +                if (!aurEff->GetTotalTicks()) +                    return;                  uint32 triggerSpell = aurEff->GetSpellEffectInfo()->TriggerSpell;                  int32 mod = int32(((float(aurEff->GetTickNumber()) / aurEff->GetTotalTicks()) * 0.9f + 0.1f) * 10000 * 2 / 3); diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp index 80cee09da89..5719b684ccd 100644 --- a/src/server/scripts/Spells/spell_druid.cpp +++ b/src/server/scripts/Spells/spell_druid.cpp @@ -555,6 +555,12 @@ public:          void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/)          { +            if (!aurEff->GetTotalTicks()) +            { +                amount = 0; +                return; +            } +              if (Unit* caster = GetCaster())                  amount = int32(CalculatePct(caster->GetCreatePowers(POWER_MANA), amount) / aurEff->GetTotalTicks());              else diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 0d39c1181ad..496c7da3676 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -1319,7 +1319,7 @@ class spell_gen_gift_of_naaru : public AuraScript      void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/)      { -        if (!GetCaster()) +        if (!GetCaster() || !aurEff->GetTotalTicks())              return;          float heal = 0.0f;  | 
