Core/Spells: Fix some issues with channeled spells and aura duration mods

Closes #21584

(cherry picked from commit ac97655063)
This commit is contained in:
ariel-
2018-03-12 02:31:17 -03:00
committed by Shauren
parent bb772416bf
commit b2de3efb4b
3 changed files with 60 additions and 53 deletions

View File

@@ -841,6 +841,11 @@ void Aura::Update(uint32 diff, Unit* caster)
}
int32 Aura::CalcMaxDuration(Unit* caster) const
{
return Aura::CalcMaxDuration(GetSpellInfo(), caster);
}
/*static*/ int32 Aura::CalcMaxDuration(SpellInfo const* spellInfo, WorldObject* caster)
{
Player* modOwner = nullptr;
int32 maxDuration;
@@ -848,17 +853,17 @@ int32 Aura::CalcMaxDuration(Unit* caster) const
if (caster)
{
modOwner = caster->GetSpellModOwner();
maxDuration = caster->CalcSpellDuration(m_spellInfo);
maxDuration = caster->CalcSpellDuration(spellInfo);
}
else
maxDuration = m_spellInfo->GetDuration();
maxDuration = spellInfo->GetDuration();
if (IsPassive() && !m_spellInfo->DurationEntry)
if (spellInfo->IsPassive() && !spellInfo->DurationEntry)
maxDuration = -1;
// IsPermanent() checks max duration (which we are supposed to calculate here)
if (maxDuration != -1 && modOwner)
modOwner->ApplySpellMod(GetSpellInfo(), SpellModOp::Duration, maxDuration);
modOwner->ApplySpellMod(spellInfo, SpellModOp::Duration, maxDuration);
return maxDuration;
}

View File

@@ -168,6 +168,7 @@ class TC_GAME_API Aura
void SetMaxDuration(int32 duration) { m_maxDuration = duration; }
int32 CalcMaxDuration() const { return CalcMaxDuration(GetCaster()); }
int32 CalcMaxDuration(Unit* caster) const;
static int32 CalcMaxDuration(SpellInfo const* spellInfo, WorldObject* caster);
int32 GetDuration() const { return m_duration; }
void SetDuration(int32 duration, bool withMods = false);
void RefreshDuration(bool withMods = false);

View File

@@ -2814,7 +2814,7 @@ SpellMissInfo Spell::PreprocessSpellHit(Unit* unit, TargetInfo& hitInfo)
}
}
hitInfo.AuraDuration = m_spellInfo->GetMaxDuration();
hitInfo.AuraDuration = Aura::CalcMaxDuration(m_spellInfo, origCaster);
// unit is immune to aura if it was diminished to 0 duration
if (!hitInfo.Positive && !unit->ApplyDiminishingToDuration(m_spellInfo, hitInfo.AuraDuration, origCaster, diminishLevel))
@@ -2852,54 +2852,53 @@ void Spell::DoSpellEffectHit(Unit* unit, SpellEffectInfo const& spellEffectInfo,
.IsRefresh = &refresh;
if (Aura* aura = Aura::TryRefreshStackOrCreate(createInfo))
{
_spellAura = aura->ToUnitAura();
// Set aura stack amount to desired value
if (m_spellValue->AuraStackAmount > 1)
{
if (!refresh)
_spellAura->SetStackAmount(m_spellValue->AuraStackAmount);
else
_spellAura->ModStackAmount(m_spellValue->AuraStackAmount);
}
_spellAura->SetDiminishGroup(hitInfo.DRGroup);
hitInfo.AuraDuration = caster->ModSpellDuration(m_spellInfo, unit, hitInfo.AuraDuration, hitInfo.Positive, _spellAura->GetEffectMask());
if (hitInfo.AuraDuration > 0)
{
hitInfo.AuraDuration *= m_spellValue->DurationMul;
// Haste modifies duration of channeled spells
if (m_spellInfo->IsChanneled())
caster->ModSpellDurationTime(m_spellInfo, hitInfo.AuraDuration, this);
else if (m_spellInfo->HasAttribute(SPELL_ATTR5_HASTE_AFFECT_DURATION))
{
int32 origDuration = hitInfo.AuraDuration;
hitInfo.AuraDuration = 0;
for (AuraEffect const* auraEff : _spellAura->GetAuraEffects())
if (auraEff)
if (int32 period = auraEff->GetPeriod()) // period is hastened by UNIT_MOD_CAST_SPEED
hitInfo.AuraDuration = std::max(std::max(origDuration / period, 1) * period, hitInfo.AuraDuration);
// if there is no periodic effect
if (!hitInfo.AuraDuration)
hitInfo.AuraDuration = int32(origDuration * m_originalCaster->m_unitData->ModCastingSpeed);
}
}
if (hitInfo.AuraDuration != _spellAura->GetMaxDuration())
{
_spellAura->SetMaxDuration(hitInfo.AuraDuration);
_spellAura->SetDuration(hitInfo.AuraDuration);
}
}
}
else
_spellAura->AddStaticApplication(unit, aura_effmask);
if (_spellAura)
{
// Set aura stack amount to desired value
if (m_spellValue->AuraStackAmount > 1)
{
if (!refresh)
_spellAura->SetStackAmount(m_spellValue->AuraStackAmount);
else
_spellAura->ModStackAmount(m_spellValue->AuraStackAmount);
}
_spellAura->SetDiminishGroup(hitInfo.DRGroup);
hitInfo.AuraDuration = caster->ModSpellDuration(m_spellInfo, unit, hitInfo.AuraDuration, hitInfo.Positive, _spellAura->GetEffectMask());
if (hitInfo.AuraDuration > 0)
{
hitInfo.AuraDuration *= m_spellValue->DurationMul;
// Haste modifies duration of channeled spells
if (m_spellInfo->IsChanneled())
caster->ModSpellDurationTime(m_spellInfo, hitInfo.AuraDuration, this);
else if (m_spellInfo->HasAttribute(SPELL_ATTR5_HASTE_AFFECT_DURATION))
{
int32 origDuration = hitInfo.AuraDuration;
hitInfo.AuraDuration = 0;
for (AuraEffect const* auraEff : _spellAura->GetAuraEffects())
if (auraEff)
if (int32 period = auraEff->GetPeriod()) // period is hastened by UNIT_MOD_CAST_SPEED
hitInfo.AuraDuration = std::max(std::max(origDuration / period, 1) * period, hitInfo.AuraDuration);
// if there is no periodic effect
if (!hitInfo.AuraDuration)
hitInfo.AuraDuration = int32(origDuration * m_originalCaster->m_unitData->ModCastingSpeed);
}
}
if (hitInfo.AuraDuration != _spellAura->GetMaxDuration())
{
_spellAura->SetMaxDuration(hitInfo.AuraDuration);
_spellAura->SetDuration(hitInfo.AuraDuration);
}
}
}
}
@@ -3582,10 +3581,12 @@ void Spell::handle_immediate()
else if (duration == -1)
SendChannelStart(duration);
m_spellState = SPELL_STATE_CASTING;
// GameObjects shouldn't cast channeled spells
ASSERT_NOTNULL(m_caster->ToUnit())->AddInterruptMask(m_spellInfo->ChannelInterruptFlags, m_spellInfo->ChannelInterruptFlags2);
if (duration != 0)
{
m_spellState = SPELL_STATE_CASTING;
// GameObjects shouldn't cast channeled spells
ASSERT_NOTNULL(m_caster->ToUnit())->AddInterruptMask(m_spellInfo->ChannelInterruptFlags, m_spellInfo->ChannelInterruptFlags2);
}
}
PrepareTargetProcessing();