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

Port From (https://github.com/TrinityCore/TrinityCore/commit/b2de3efb4b3e023874b6e28dd3a0a82b2c735ca8)
This commit is contained in:
hondacrx
2021-09-09 10:23:51 -04:00
parent ed98f4a2a4
commit 4573123717
2 changed files with 76 additions and 65 deletions
+11 -5
View File
@@ -721,7 +721,12 @@ namespace Game.Spells
}
}
int CalcMaxDuration(Unit caster)
public int CalcMaxDuration(Unit caster)
{
return CalcMaxDuration(GetSpellInfo(), caster);
}
public static int CalcMaxDuration(SpellInfo spellInfo, WorldObject caster)
{
Player modOwner = null;
int maxDuration;
@@ -729,17 +734,18 @@ namespace Game.Spells
if (caster != null)
{
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 == null)
if (spellInfo.IsPassive() && spellInfo.DurationEntry == null)
maxDuration = -1;
// IsPermanent() checks max duration (which we are supposed to calculate here)
if (maxDuration != -1 && modOwner != null)
modOwner.ApplySpellMod(GetSpellInfo(), SpellModOp.Duration, ref maxDuration);
modOwner.ApplySpellMod(spellInfo, SpellModOp.Duration, ref maxDuration);
return maxDuration;
}
+65 -60
View File
@@ -1987,7 +1987,7 @@ namespace Game.Spells
}
}
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, ref hitInfo.AuraDuration, origCaster, diminishLevel))
@@ -2009,14 +2009,21 @@ namespace Game.Spells
if (caster != null)
{
AuraCreateInfo createInfo = null;
// delayed spells with multiple targets need to create a new aura object, otherwise we'll access a deleted aura
if (m_spellInfo.HasHitDelay() && !m_spellInfo.IsChanneled())
{
spellAura = null;
Aura aura = unit.GetAura(m_spellInfo.Id, caster.GetGUID(), m_CastItem ? m_CastItem.GetGUID() : ObjectGuid.Empty, aura_effmask);
if (aura != null)
spellAura = aura.ToUnitAura();
}
if (spellAura == null)
{
bool resetPeriodicTimer = !_triggeredCastFlags.HasFlag(TriggerCastFlags.DontResetPeriodicTimer);
uint allAuraEffectMask = Aura.BuildEffectMaskForOwner(m_spellInfo, SpellConst.MaxEffectMask, unit);
createInfo = new(m_castId, m_spellInfo, GetCastDifficulty(), allAuraEffectMask, unit);
AuraCreateInfo createInfo = new(m_castId, m_spellInfo, GetCastDifficulty(), allAuraEffectMask, unit);
createInfo.SetCasterGUID(caster.GetGUID());
createInfo.SetBaseAmount(hitInfo.AuraBasePoints);
createInfo.SetCastItem(m_castItemGUID, m_castItemEntry, m_castItemLevel);
@@ -2025,63 +2032,59 @@ namespace Game.Spells
Aura aura = Aura.TryRefreshStackOrCreate(createInfo);
if (aura != null)
{
spellAura = aura.ToUnitAura();
// Set aura stack amount to desired value
if (m_spellValue.AuraStackAmount > 1)
{
if (!createInfo.IsRefresh)
spellAura.SetStackAmount((byte)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 *= (int)m_spellValue.DurationMul;
// Haste modifies duration of channeled spells
if (m_spellInfo.IsChanneled())
caster.ModSpellDurationTime(m_spellInfo, ref hitInfo.AuraDuration, this);
else if (m_spellInfo.HasAttribute(SpellAttr5.HasteAffectDuration))
{
int origDuration = hitInfo.AuraDuration;
hitInfo.AuraDuration = 0;
foreach (AuraEffect auraEff in spellAura.GetAuraEffects())
{
if (auraEff != null)
{
int period = auraEff.GetPeriod();
if (period != 0) // period is hastened by UNIT_MOD_CAST_SPEED
hitInfo.AuraDuration = Math.Max(Math.Max(origDuration / period, 1) * period, hitInfo.AuraDuration);
}
}
// if there is no periodic effect
if (hitInfo.AuraDuration == 0)
hitInfo.AuraDuration = (int)(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);
bool refresh = false;
if (createInfo != null)
refresh = createInfo.IsRefresh;
if (spellAura != null)
{
// Set aura stack amount to desired value
if (m_spellValue.AuraStackAmount > 1)
{
if (!refresh)
spellAura.SetStackAmount((byte)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 *= (int)m_spellValue.DurationMul;
// Haste modifies duration of channeled spells
if (m_spellInfo.IsChanneled())
caster.ModSpellDurationTime(m_spellInfo, ref hitInfo.AuraDuration, this);
else if (m_spellInfo.HasAttribute(SpellAttr5.HasteAffectDuration))
{
int origDuration = hitInfo.AuraDuration;
hitInfo.AuraDuration = 0;
foreach (AuraEffect auraEff in spellAura.GetAuraEffects())
{
if (auraEff != null)
{
int period = auraEff.GetPeriod();
if (period != 0) // period is hastened by UNIT_MOD_CAST_SPEED
hitInfo.AuraDuration = Math.Max(Math.Max(origDuration / period, 1) * period, hitInfo.AuraDuration);
}
}
// if there is no periodic effect
if (hitInfo.AuraDuration == 0)
hitInfo.AuraDuration = (int)(origDuration * m_originalCaster.m_unitData.ModCastingSpeed);
}
}
if (hitInfo.AuraDuration != spellAura.GetMaxDuration())
{
spellAura.SetMaxDuration(hitInfo.AuraDuration);
spellAura.SetDuration(hitInfo.AuraDuration);
}
}
}
}
@@ -2809,10 +2812,12 @@ namespace Game.Spells
else if (duration == -1)
SendChannelStart((uint)duration);
m_spellState = SpellState.Casting;
// GameObjects shouldn't cast channeled spells
m_caster.ToUnit().AddInterruptMask(m_spellInfo.ChannelInterruptFlags, m_spellInfo.ChannelInterruptFlags2);
if (duration != 0)
{
m_spellState = SpellState.Casting;
// GameObjects shouldn't cast channeled spells
m_caster.ToUnit().AddInterruptMask(m_spellInfo.ChannelInterruptFlags, m_spellInfo.ChannelInterruptFlags2);
}
}
PrepareTargetProcessing();