diff --git a/Source/Game/BattleGrounds/Zones/ArathiBasin.cs b/Source/Game/BattleGrounds/Zones/ArathiBasin.cs index 0a79df4b8..d86f63fea 100644 --- a/Source/Game/BattleGrounds/Zones/ArathiBasin.cs +++ b/Source/Game/BattleGrounds/Zones/ArathiBasin.cs @@ -14,7 +14,6 @@ namespace Game.BattleGrounds.Zones public BgArathiBasin(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { m_IsInformedNearVictory = false; - m_BuffChange = true; BgObjects = new ObjectGuid[ABObjectTypes.Max]; BgCreatures = new ObjectGuid[ABBattlegroundNodes.AllCount + 5];//+5 for aura triggers diff --git a/Source/Game/BattleGrounds/Zones/EyeofStorm.cs b/Source/Game/BattleGrounds/Zones/EyeofStorm.cs index f203a8fee..a2d4dc81f 100644 --- a/Source/Game/BattleGrounds/Zones/EyeofStorm.cs +++ b/Source/Game/BattleGrounds/Zones/EyeofStorm.cs @@ -27,7 +27,6 @@ namespace Game.BattleGrounds.Zones { public BgEyeofStorm(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { - m_BuffChange = true; BgObjects = new ObjectGuid[EotSObjectTypes.Max]; BgCreatures= new ObjectGuid[EotSCreaturesTypes.Max]; m_Points_Trigger[EotSPoints.FelReaver] = EotSPointsTrigger.FelReaverBuff; diff --git a/Source/Game/Entities/Object/WorldObject.cs b/Source/Game/Entities/Object/WorldObject.cs index 74265517e..74fd14899 100644 --- a/Source/Game/Entities/Object/WorldObject.cs +++ b/Source/Game/Entities/Object/WorldObject.cs @@ -15,6 +15,7 @@ using Game.Scenarios; using Game.Spells; using System; using System.Collections.Generic; +using System.Linq; using System.Numerics; namespace Game.Entities @@ -1874,27 +1875,39 @@ namespace Game.Entities return value; } - public int CalcSpellDuration(SpellInfo spellInfo) + public int CalcSpellDuration(SpellInfo spellInfo, List powerCosts) { - int comboPoints = 0; - int maxComboPoints = 5; - Unit unit = ToUnit(); - if (unit != null) - { - comboPoints = unit.GetPower(PowerType.ComboPoints); - maxComboPoints = unit.GetMaxPower(PowerType.ComboPoints); - } - int minduration = spellInfo.GetDuration(); + if (minduration <= 0) + return minduration; + int maxduration = spellInfo.GetMaxDuration(); + if (minduration == maxduration) + return minduration; - int duration; - if (comboPoints != 0 && minduration != -1 && minduration != maxduration) - duration = minduration + ((maxduration - minduration) * comboPoints / maxComboPoints); - else - duration = minduration; + Unit unit = ToUnit(); + if (unit == null) + return minduration; - return duration; + if (powerCosts == null) + return minduration; + + // we want only baseline cost here + var powerCostRecord = spellInfo.PowerCosts.FirstOrDefault(powerEntry => powerEntry != null && powerEntry.PowerType == PowerType.ComboPoints && (powerEntry.RequiredAuraSpellID == 0 || unit.HasAura(powerEntry.RequiredAuraSpellID))); + if (powerCostRecord == null) + return minduration; + + var consumedCost = powerCosts.Find(consumed => consumed.Power == PowerType.ComboPoints); + if (consumedCost == null) + return minduration; + + int baseComboCost = powerCostRecord.ManaCost + (int)powerCostRecord.OptionalCost; + var powerTypeEntry = Global.DB2Mgr.GetPowerTypeEntry(PowerType.ComboPoints); + if (powerTypeEntry != null) + baseComboCost += MathFunctions.CalculatePct(powerTypeEntry.MaxBasePower, powerCostRecord.PowerCostPct + powerCostRecord.OptionalCostPct); + + float durationPerComboPoint = (float)(maxduration - minduration) / baseComboCost; + return minduration + (int)(durationPerComboPoint * consumedCost.Amount); } public int ModSpellDuration(SpellInfo spellInfo, WorldObject target, int duration, bool positive, uint effectMask) diff --git a/Source/Game/Spells/Auras/Aura.cs b/Source/Game/Spells/Auras/Aura.cs index 26b94210c..5b5d5a540 100644 --- a/Source/Game/Spells/Auras/Aura.cs +++ b/Source/Game/Spells/Auras/Aura.cs @@ -742,10 +742,10 @@ namespace Game.Spells public int CalcMaxDuration(Unit caster) { - return CalcMaxDuration(GetSpellInfo(), caster); + return CalcMaxDuration(GetSpellInfo(), caster, null); } - public static int CalcMaxDuration(SpellInfo spellInfo, WorldObject caster) + public static int CalcMaxDuration(SpellInfo spellInfo, WorldObject caster, List powerCosts) { Player modOwner = null; int maxDuration; @@ -753,7 +753,7 @@ namespace Game.Spells if (caster != null) { modOwner = caster.GetSpellModOwner(); - maxDuration = caster.CalcSpellDuration(spellInfo); + maxDuration = caster.CalcSpellDuration(spellInfo, powerCosts); } else maxDuration = spellInfo.GetDuration(); diff --git a/Source/Game/Spells/Auras/AuraEffect.cs b/Source/Game/Spells/Auras/AuraEffect.cs index 875be64fd..da97fc48d 100644 --- a/Source/Game/Spells/Auras/AuraEffect.cs +++ b/Source/Game/Spells/Auras/AuraEffect.cs @@ -152,7 +152,7 @@ namespace Game.Spells public static float CalculateEstimatedfTotalPeriodicAmount(Unit caster, Unit target, SpellInfo spellInfo, SpellEffectInfo spellEffectInfo, float amount, byte stack) { - int maxDuration = Aura.CalcMaxDuration(spellInfo, caster); + int maxDuration = Aura.CalcMaxDuration(spellInfo, caster, null); if (maxDuration <= 0) return 0.0f; diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index 02dc8e717..01a3c1fb0 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -2239,7 +2239,7 @@ namespace Game.Spells } } - hitInfo.AuraDuration = Aura.CalcMaxDuration(m_spellInfo, origCaster); + hitInfo.AuraDuration = Aura.CalcMaxDuration(m_spellInfo, origCaster, m_powerCost); // unit is immune to aura if it was diminished to 0 duration if (!hitInfo.Positive && !unit.ApplyDiminishingToDuration(m_spellInfo, ref hitInfo.AuraDuration, origCaster, diminishLevel)) diff --git a/Source/Game/Spells/SpellInfo.cs b/Source/Game/Spells/SpellInfo.cs index a92b2b1a8..a3d7e4b28 100644 --- a/Source/Game/Spells/SpellInfo.cs +++ b/Source/Game/Spells/SpellInfo.cs @@ -2792,25 +2792,19 @@ namespace Game.Spells if (power.RequiredAuraSpellID != 0 && !unitCaster.HasAura(power.RequiredAuraSpellID)) return null; - SpellPowerCost cost = new(); - // Spell drain all exist power on cast (Only paladin lay of Hands) if (HasAttribute(SpellAttr1.UseAllMana)) { + if (optionalCost) + return null; + // If power type - health drain all if (power.PowerType == PowerType.Health) - { - cost.Power = PowerType.Health; - cost.Amount = (int)unitCaster.GetHealth(); - return cost; - } + return new SpellPowerCost() { Power = PowerType.Health, Amount = (int)unitCaster.GetHealth() }; + // Else drain all power if (power.PowerType < PowerType.Max) - { - cost.Power = power.PowerType; - cost.Amount = unitCaster.GetPower(cost.Power); - return cost; - } + return new SpellPowerCost() { Power = power.PowerType, Amount = unitCaster.GetPower(power.PowerType) }; Log.outError(LogFilter.Spells, $"SpellInfo.CalcPowerCost: Unknown power type '{power.PowerType}' in spell {Id}"); return default; @@ -2997,9 +2991,7 @@ namespace Game.Spells if (initiallyNegative != (powerCost < 0)) powerCost = 0; - cost.Power = power.PowerType; - cost.Amount = powerCost; - return cost; + return new SpellPowerCost() { Power = power.PowerType, Amount = powerCost }; } public List CalcPowerCost(WorldObject caster, SpellSchoolMask schoolMask, Spell spell = null) @@ -3013,11 +3005,8 @@ namespace Game.Spells if (itr != null) return itr; - SpellPowerCost cost = new(); - cost.Power = powerType; - cost.Amount = 0; - costs.Add(cost); - return costs.Last(); + costs.Add(new SpellPowerCost() { Power = powerType, Amount = 0 }); + return costs.Last(); } foreach (SpellPowerRecord power in PowerCosts)