aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorariel- <ariel-@users.noreply.github.com>2017-12-14 11:42:42 -0300
committerfunjoker <funjoker109@gmail.com>2021-03-15 20:17:31 +0100
commit5f9e0d92d563c983c229db1569414916b3dce51e (patch)
tree79c906bdf9d526646c26f827db677a566460bf43 /src
parentfe362cf2c9d5c71db4698480ce26cb35dbc58f28 (diff)
Core/Auras: periodics refactor part 1:
- Don't skip ticks if diff is greater than amplitude - Fixed spells without ampltude in DBC (cherry picked from commit 5d91beb1dbc795382a12ec05f6e72c76b195b141)
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp6
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp85
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.h21
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp5
-rw-r--r--src/server/game/Spells/SpellMgr.cpp37
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp2
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp2
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp2
-rw-r--r--src/server/scripts/Spells/spell_druid.cpp6
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp2
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;