diff --git a/Source/Game/Entities/Player/Player.Items.cs b/Source/Game/Entities/Player/Player.Items.cs index 4963eb554..f0a281aa6 100644 --- a/Source/Game/Entities/Player/Player.Items.cs +++ b/Source/Game/Entities/Player/Player.Items.cs @@ -1578,7 +1578,7 @@ namespace Game.Entities { m_weaponChangeTimer = spellProto.StartRecoveryTime; - GetSpellHistory().AddGlobalCooldown(spellProto, m_weaponChangeTimer); + GetSpellHistory().AddGlobalCooldown(spellProto, TimeSpan.FromMilliseconds(m_weaponChangeTimer)); SpellCooldownPkt spellCooldown = new(); spellCooldown.Caster = GetGUID(); @@ -3912,7 +3912,7 @@ namespace Game.Entities continue; // Don't replace longer cooldowns by equip cooldown if we have any. - if (GetSpellHistory().GetRemainingCooldown(effectSpellInfo) > 30 * Time.InMilliseconds) + if (GetSpellHistory().GetRemainingCooldown(effectSpellInfo) > TimeSpan.FromSeconds(30)) continue; GetSpellHistory().AddCooldown((uint)effectData.SpellID, pItem.GetEntry(), TimeSpan.FromSeconds(30)); diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index 028f18b98..068a5c18e 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -6388,7 +6388,7 @@ namespace Game.Entities BroadcastTextRecord bct = CliDB.BroadcastTextStorage.LookupByKey(textId); if (bct == null) { - Log.outError(LogFilter.Unit, "WorldObject.MonsterWhisper: `broadcast_text` was not {0} found", textId); + Log.outError(LogFilter.Unit, "WorldObject.Whisper: `broadcast_text` was not {0} found", textId); return; } diff --git a/Source/Game/Networking/Packets/SpellPackets.cs b/Source/Game/Networking/Packets/SpellPackets.cs index bdacbc28e..a8f1f14f8 100644 --- a/Source/Game/Networking/Packets/SpellPackets.cs +++ b/Source/Game/Networking/Packets/SpellPackets.cs @@ -538,10 +538,12 @@ namespace Game.Networking.Packets _worldPacket.WriteUInt32(SpellID); _worldPacket.WriteInt32(DeltaTime); _worldPacket.WriteBit(IsPet); + _worldPacket.WriteBit(WithoutCategoryCooldown); _worldPacket.FlushBits(); } public bool IsPet; + public bool WithoutCategoryCooldown; public int DeltaTime; public uint SpellID; } diff --git a/Source/Game/Spells/Auras/Aura.cs b/Source/Game/Spells/Auras/Aura.cs index 8283a4454..2957185e5 100644 --- a/Source/Game/Spells/Auras/Aura.cs +++ b/Source/Game/Spells/Auras/Aura.cs @@ -1361,7 +1361,7 @@ namespace Game.Spells { // This additional check is needed to add a minimal delay before cooldown in in effect // to allow all bubbles broken by a single damage source proc mana return - if (caster.GetSpellHistory().GetRemainingCooldown(aura.GetSpellInfo()) <= 11 * Time.InMilliseconds) + if (caster.GetSpellHistory().GetRemainingCooldown(aura.GetSpellInfo()) <= TimeSpan.FromSeconds(11)) break; } else // and add if needed diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index d4daf488e..b7647ba38 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -7246,42 +7246,53 @@ namespace Game.Spells if (!CanHaveGlobalCooldown(m_caster)) return; - int gcd = (int)m_spellInfo.StartRecoveryTime; - if (gcd == 0 || m_spellInfo.StartRecoveryCategory == 0) + TimeSpan gcd = TimeSpan.FromMilliseconds(m_spellInfo.StartRecoveryTime); + if (gcd == TimeSpan.Zero || m_spellInfo.StartRecoveryCategory == 0) return; if (m_caster.IsTypeId(TypeId.Player)) if (m_caster.ToPlayer().GetCommandStatus(PlayerCommandStates.Cooldown)) return; + TimeSpan MinGCD = TimeSpan.FromMilliseconds(750); + TimeSpan MaxGCD = TimeSpan.FromMilliseconds(1500); + // Global cooldown can't leave range 1..1.5 secs // There are some spells (mostly not casted directly by player) that have < 1 sec and > 1.5 sec global cooldowns // but as tests show are not affected by any spell mods. - if (m_spellInfo.StartRecoveryTime >= 750 && m_spellInfo.StartRecoveryTime <= 1500) + if (gcd >= MinGCD && gcd <= MaxGCD) { // gcd modifier auras are applied only to own spells and only players have such mods Player modOwner = m_caster.GetSpellModOwner(); if (modOwner) - modOwner.ApplySpellMod(m_spellInfo, SpellModOp.StartCooldown, ref gcd, this); + { + int intGcd = (int)gcd.TotalMilliseconds; + modOwner.ApplySpellMod(m_spellInfo, SpellModOp.StartCooldown, ref intGcd, this); + gcd = TimeSpan.FromMilliseconds(intGcd); + } bool isMeleeOrRangedSpell = m_spellInfo.DmgClass == SpellDmgClass.Melee || m_spellInfo.DmgClass == SpellDmgClass.Ranged || m_spellInfo.HasAttribute(SpellAttr0.ReqAmmo) || m_spellInfo.HasAttribute(SpellAttr0.Ability); // Apply haste rating - if (gcd > 750 && (m_spellInfo.StartRecoveryCategory == 133 && !isMeleeOrRangedSpell)) + if (gcd > MinGCD && (m_spellInfo.StartRecoveryCategory == 133 && !isMeleeOrRangedSpell)) { - gcd = (int)(gcd * m_caster.ToUnit().m_unitData.ModSpellHaste); - MathFunctions.RoundToInterval(ref gcd, 750, 1500); + gcd = TimeSpan.FromMilliseconds(gcd.TotalMilliseconds * m_caster.ToUnit().m_unitData.ModSpellHaste); + int intGcd = (int)gcd.TotalMilliseconds; + MathFunctions.RoundToInterval(ref intGcd, 750, 1500); + gcd = TimeSpan.FromMilliseconds(intGcd); } - if (gcd > 750 && m_caster.ToUnit().HasAuraTypeWithAffectMask(AuraType.ModGlobalCooldownByHasteRegen, m_spellInfo)) + if (gcd > MinGCD && m_caster.ToUnit().HasAuraTypeWithAffectMask(AuraType.ModGlobalCooldownByHasteRegen, m_spellInfo)) { - gcd = (int)(gcd * m_caster.ToUnit().m_unitData.ModHasteRegen); - MathFunctions.RoundToInterval(ref gcd, 750, 1500); + gcd = TimeSpan.FromMilliseconds(gcd.TotalMilliseconds * m_caster.ToUnit().m_unitData.ModHasteRegen); + int intGcd = (int)gcd.TotalMilliseconds; + MathFunctions.RoundToInterval(ref intGcd, 750, 1500); + gcd = TimeSpan.FromMilliseconds(intGcd); } } - m_caster.ToUnit().GetSpellHistory().AddGlobalCooldown(m_spellInfo, (uint)gcd); + m_caster.ToUnit().GetSpellHistory().AddGlobalCooldown(m_spellInfo, gcd); } void CancelGlobalCooldown() diff --git a/Source/Game/Spells/SpellEffects.cs b/Source/Game/Spells/SpellEffects.cs index c41f24751..ca2cf732c 100644 --- a/Source/Game/Spells/SpellEffects.cs +++ b/Source/Game/Spells/SpellEffects.cs @@ -2648,7 +2648,8 @@ namespace Game.Spells if (unitCaster != null) { int duration = m_spellInfo.GetDuration(); - unitTarget.GetSpellHistory().LockSpellSchool(curSpellInfo.GetSchoolMask(), (uint)unitTarget.ModSpellDuration(m_spellInfo, unitTarget, duration, false, (uint)(1 << (int)effectInfo.EffectIndex))); + duration = unitTarget.ModSpellDuration(m_spellInfo, unitTarget, duration, false, 1u << (int)effectInfo.EffectIndex); + unitTarget.GetSpellHistory().LockSpellSchool(curSpellInfo.GetSchoolMask(), TimeSpan.FromMilliseconds(duration)); if (m_spellInfo.DmgClass == SpellDmgClass.Magic) Unit.ProcSkillsAndAuras(unitCaster, unitTarget, ProcFlags.DoneSpellMagicDmgClassNeg, ProcFlags.TakenSpellMagicDmgClassNeg, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.Hit, ProcFlagsHit.Interrupt, null, null, null); else if (m_spellInfo.DmgClass == SpellDmgClass.Melee) diff --git a/Source/Game/Spells/SpellHistory.cs b/Source/Game/Spells/SpellHistory.cs index 42884f72d..f10c2c55d 100644 --- a/Source/Game/Spells/SpellHistory.cs +++ b/Source/Game/Spells/SpellHistory.cs @@ -335,101 +335,116 @@ namespace Game.Spells } } - public void StartCooldown(SpellInfo spellInfo, uint itemId, Spell spell = null, bool onHold = false) + public void StartCooldown(SpellInfo spellInfo, uint itemId, Spell spell = null, bool onHold = false, TimeSpan? forcedCooldown = null) { // init cooldown values uint categoryId = 0; - int cooldown = -1; - int categoryCooldown = -1; - - GetCooldownDurations(spellInfo, itemId, ref cooldown, ref categoryId, ref categoryCooldown); + TimeSpan cooldown = TimeSpan.Zero; + TimeSpan categoryCooldown = TimeSpan.Zero; DateTime curTime = GameTime.GetGameTimeSystemPoint(); DateTime catrecTime; DateTime recTime; bool needsCooldownPacket = false; + if (!forcedCooldown.HasValue) + GetCooldownDurations(spellInfo, itemId, ref cooldown, ref categoryId, ref categoryCooldown); + else + cooldown = forcedCooldown.Value; + // overwrite time for selected category if (onHold) { // use +MONTH as infinite cooldown marker - catrecTime = categoryCooldown > 0 ? (curTime + PlayerConst.InfinityCooldownDelay) : curTime; - recTime = cooldown > 0 ? (curTime + PlayerConst.InfinityCooldownDelay) : catrecTime; + catrecTime = categoryCooldown > TimeSpan.Zero ? (curTime + PlayerConst.InfinityCooldownDelay) : curTime; + recTime = cooldown > TimeSpan.Zero ? (curTime + PlayerConst.InfinityCooldownDelay) : catrecTime; } else { - // shoot spells used equipped item cooldown values already assigned in GetAttackTime(RANGED_ATTACK) - // prevent 0 cooldowns set by another way - if (cooldown <= 0 && categoryCooldown <= 0 && (categoryId == 76 || (spellInfo.IsAutoRepeatRangedSpell() && spellInfo.Id != 75))) - cooldown = (int)(uint)_owner.m_unitData.RangedAttackRoundBaseTime; - - // Now we have cooldown data (if found any), time to apply mods - Player modOwner = _owner.GetSpellModOwner(); - if (modOwner) + if (!forcedCooldown.HasValue) { - if (cooldown >= 0) - modOwner.ApplySpellMod(spellInfo, SpellModOp.Cooldown, ref cooldown, spell); + // shoot spells used equipped item cooldown values already assigned in SetBaseAttackTime(RANGED_ATTACK) + // prevent 0 cooldowns set by another way + if (cooldown <= TimeSpan.Zero && categoryCooldown <= TimeSpan.Zero && (categoryId == 76 || (spellInfo.IsAutoRepeatRangedSpell() && spellInfo.Id != 75))) + cooldown = TimeSpan.FromMilliseconds(_owner.m_unitData.RangedAttackRoundBaseTime); - if (categoryCooldown >= 0 && !spellInfo.HasAttribute(SpellAttr6.IgnoreCategoryCooldownMods)) - modOwner.ApplySpellMod(spellInfo, SpellModOp.Cooldown, ref categoryCooldown, spell); - } - - if (_owner.HasAuraTypeWithAffectMask(AuraType.ModSpellCooldownByHaste, spellInfo)) - { - cooldown = (int)(cooldown * _owner.m_unitData.ModSpellHaste); - categoryCooldown = (int)(categoryCooldown * _owner.m_unitData.ModSpellHaste); - } - - if (_owner.HasAuraTypeWithAffectMask(AuraType.ModCooldownByHasteRegen, spellInfo)) - { - cooldown = (int)(cooldown * _owner.m_unitData.ModHasteRegen); - categoryCooldown = (int)(categoryCooldown * _owner.m_unitData.ModHasteRegen); - } - - int cooldownMod = _owner.GetTotalAuraModifier(AuraType.ModCooldown); - if (cooldownMod != 0) - { - // Apply SPELL_AURA_MOD_COOLDOWN only to own spells - Player playerOwner = GetPlayerOwner(); - if (!playerOwner || playerOwner.HasSpell(spellInfo.Id)) + // Now we have cooldown data (if found any), time to apply mods + Player modOwner = _owner.GetSpellModOwner(); + if (modOwner) { - needsCooldownPacket = true; - cooldown += cooldownMod * Time.InMilliseconds; // SPELL_AURA_MOD_COOLDOWN does not affect category cooldows, verified with shaman shocks - } - } + void applySpellMod(ref TimeSpan value) + { + int intValue = (int)value.TotalMilliseconds; + modOwner.ApplySpellMod(spellInfo, SpellModOp.Cooldown, ref intValue, spell); + value = TimeSpan.FromMilliseconds(intValue); + } - // Apply SPELL_AURA_MOD_SPELL_CATEGORY_COOLDOWN modifiers - // Note: This aura applies its modifiers to all cooldowns of spells with set category, not to category cooldown only - if (categoryId != 0) - { - int categoryModifier = _owner.GetTotalAuraModifierByMiscValue(AuraType.ModSpellCategoryCooldown, (int)categoryId); - if (categoryModifier != 0) - { - if (cooldown > 0) - cooldown += categoryModifier; + if (cooldown >= TimeSpan.Zero) + applySpellMod(ref cooldown); - if (categoryCooldown > 0) - categoryCooldown += categoryModifier; + if (categoryCooldown >= TimeSpan.Zero && !spellInfo.HasAttribute(SpellAttr6.IgnoreCategoryCooldownMods)) + applySpellMod(ref categoryCooldown); } - SpellCategoryRecord categoryEntry = CliDB.SpellCategoryStorage.LookupByKey(categoryId); - if (categoryEntry.Flags.HasAnyFlag(SpellCategoryFlags.CooldownExpiresAtDailyReset)) - categoryCooldown = (int)(Time.UnixTimeToDateTime(Global.WorldMgr.GetNextDailyQuestsResetTime()) - GameTime.GetGameTimeSystemPoint()).TotalMilliseconds; + if (_owner.HasAuraTypeWithAffectMask(AuraType.ModSpellCooldownByHaste, spellInfo)) + { + cooldown = TimeSpan.FromMilliseconds(cooldown.TotalMilliseconds * _owner.m_unitData.ModSpellHaste); + categoryCooldown = TimeSpan.FromMilliseconds(categoryCooldown.TotalMilliseconds * _owner.m_unitData.ModSpellHaste); + } + + if (_owner.HasAuraTypeWithAffectMask(AuraType.ModCooldownByHasteRegen, spellInfo)) + { + cooldown = TimeSpan.FromMilliseconds(cooldown.TotalMilliseconds * _owner.m_unitData.ModHasteRegen); + categoryCooldown = TimeSpan.FromMilliseconds(categoryCooldown.TotalMilliseconds * _owner.m_unitData.ModHasteRegen); + } + + int cooldownMod = _owner.GetTotalAuraModifier(AuraType.ModCooldown); + if (cooldownMod != 0) + { + // Apply SPELL_AURA_MOD_COOLDOWN only to own spells + Player playerOwner = GetPlayerOwner(); + if (!playerOwner || playerOwner.HasSpell(spellInfo.Id)) + { + needsCooldownPacket = true; + cooldown += TimeSpan.FromMilliseconds(cooldownMod); // SPELL_AURA_MOD_COOLDOWN does not affect category cooldows, verified with shaman shocks + } + } + + // Apply SPELL_AURA_MOD_SPELL_CATEGORY_COOLDOWN modifiers + // Note: This aura applies its modifiers to all cooldowns of spells with set category, not to category cooldown only + if (categoryId != 0) + { + int categoryModifier = _owner.GetTotalAuraModifierByMiscValue(AuraType.ModSpellCategoryCooldown, (int)categoryId); + if (categoryModifier != 0) + { + if (cooldown > TimeSpan.Zero) + cooldown += TimeSpan.FromMilliseconds(categoryModifier); + + if (categoryCooldown > TimeSpan.Zero) + categoryCooldown += TimeSpan.FromMilliseconds(categoryModifier); + } + + SpellCategoryRecord categoryEntry = CliDB.SpellCategoryStorage.LookupByKey(categoryId); + if (categoryEntry.Flags.HasAnyFlag(SpellCategoryFlags.CooldownExpiresAtDailyReset)) + categoryCooldown = Time.UnixTimeToDateTime(Global.WorldMgr.GetNextDailyQuestsResetTime()) - GameTime.GetGameTimeSystemPoint(); + } } + else + needsCooldownPacket = true; // replace negative cooldowns by 0 - if (cooldown < 0) - cooldown = 0; + if (cooldown < TimeSpan.Zero) + cooldown = TimeSpan.Zero; - if (categoryCooldown < 0) - categoryCooldown = 0; + if (categoryCooldown < TimeSpan.Zero) + categoryCooldown = TimeSpan.Zero; // no cooldown after applying spell mods - if (cooldown == 0 && categoryCooldown == 0) + if (cooldown == TimeSpan.Zero && categoryCooldown == TimeSpan.Zero) return; - catrecTime = categoryCooldown != 0 ? curTime + TimeSpan.FromMilliseconds(categoryCooldown) : curTime; - recTime = cooldown != 0 ? curTime + TimeSpan.FromMilliseconds(cooldown) : catrecTime; + catrecTime = categoryCooldown != TimeSpan.Zero ? curTime + categoryCooldown : curTime; + recTime = cooldown != TimeSpan.Zero ? curTime + cooldown : catrecTime; } // self spell cooldown @@ -445,7 +460,7 @@ namespace Game.Spells SpellCooldownPkt spellCooldown = new(); spellCooldown.Caster = _owner.GetGUID(); spellCooldown.Flags = SpellCooldownFlags.None; - spellCooldown.SpellCooldowns.Add(new SpellCooldownStruct(spellInfo.Id, (uint)cooldown)); + spellCooldown.SpellCooldowns.Add(new SpellCooldownStruct(spellInfo.Id, (uint)cooldown.TotalMilliseconds)); playerOwner.SendPacket(spellCooldown); } } @@ -486,16 +501,20 @@ namespace Game.Spells public void AddCooldown(uint spellId, uint itemId, DateTime cooldownEnd, uint categoryId, DateTime categoryEnd, bool onHold = false) { CooldownEntry cooldownEntry = new(); - cooldownEntry.SpellId = spellId; - cooldownEntry.CooldownEnd = cooldownEnd; - cooldownEntry.ItemId = itemId; - cooldownEntry.CategoryId = categoryId; - cooldownEntry.CategoryEnd = categoryEnd; - cooldownEntry.OnHold = onHold; - _spellCooldowns[spellId] = cooldownEntry; + // scripts can start multiple cooldowns for a given spell, only store the longest one + if (cooldownEnd > cooldownEntry.CooldownEnd || categoryEnd > cooldownEntry.CategoryEnd || onHold) + { + cooldownEntry.SpellId = spellId; + cooldownEntry.CooldownEnd = cooldownEnd; + cooldownEntry.ItemId = itemId; + cooldownEntry.CategoryId = categoryId; + cooldownEntry.CategoryEnd = categoryEnd; + cooldownEntry.OnHold = onHold; + _spellCooldowns[spellId] = cooldownEntry; - if (categoryId != 0) - _categoryCooldowns[categoryId] = cooldownEntry; + if (categoryId != 0) + _categoryCooldowns[categoryId] = cooldownEntry; + } } public void ModifySpellCooldown(uint spellId, TimeSpan offset) @@ -623,7 +642,7 @@ namespace Game.Spells return _categoryCooldowns.ContainsKey(category); } - public uint GetRemainingCooldown(SpellInfo spellInfo) + public TimeSpan GetRemainingCooldown(SpellInfo spellInfo) { DateTime end; var entry = _spellCooldowns.LookupByKey(spellInfo.Id); @@ -633,23 +652,23 @@ namespace Game.Spells { var cooldownEntry = _categoryCooldowns.LookupByKey(spellInfo.GetCategory()); if (cooldownEntry == null) - return 0; + return TimeSpan.Zero; end = cooldownEntry.CategoryEnd; } DateTime now = GameTime.GetGameTimeSystemPoint(); if (end < now) - return 0; + return TimeSpan.Zero; var remaining = end - now; - return (uint)remaining.TotalMilliseconds; + return remaining; } - public void LockSpellSchool(SpellSchoolMask schoolMask, uint lockoutTime) + public void LockSpellSchool(SpellSchoolMask schoolMask, TimeSpan lockoutTime) { DateTime now = GameTime.GetGameTimeSystemPoint(); - DateTime lockoutEnd = now + TimeSpan.FromMilliseconds(lockoutTime); + DateTime lockoutEnd = now + lockoutTime; for (int i = 0; i < (int)SpellSchools.Max; ++i) if (Convert.ToBoolean((SpellSchoolMask)(1 << i) & schoolMask)) _schoolLockouts[i] = lockoutEnd; @@ -679,7 +698,7 @@ namespace Game.Spells SpellCooldownPkt spellCooldown = new(); spellCooldown.Caster = _owner.GetGUID(); - spellCooldown.Flags = SpellCooldownFlags.None; + spellCooldown.Flags = SpellCooldownFlags.LossOfControlUi; foreach (uint spellId in knownSpells) { SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(spellId, _owner.GetMap().GetDifficultyID()); @@ -689,11 +708,14 @@ namespace Game.Spells if (!spellInfo.PreventionType.HasAnyFlag(SpellPreventionType.Silence)) continue; - if (Convert.ToBoolean(schoolMask & spellInfo.GetSchoolMask()) && GetRemainingCooldown(spellInfo) < lockoutTime) - { - spellCooldown.SpellCooldowns.Add(new SpellCooldownStruct(spellId, lockoutTime)); + if ((schoolMask & spellInfo.GetSchoolMask()) == 0) + continue; + + if (GetRemainingCooldown(spellInfo) < lockoutTime) AddCooldown(spellId, 0, lockoutEnd, 0, now); - } + + // always send cooldown, even if it will be shorter than already existing cooldown for LossOfControl UI + spellCooldown.SpellCooldowns.Add(new SpellCooldownStruct(spellId, (uint)lockoutTime.TotalMilliseconds)); } Player player = GetPlayerOwner(); @@ -856,9 +878,9 @@ namespace Game.Spells return _globalCooldowns.ContainsKey(spellInfo.StartRecoveryCategory) && _globalCooldowns[spellInfo.StartRecoveryCategory] > GameTime.GetGameTimeSystemPoint(); } - public void AddGlobalCooldown(SpellInfo spellInfo, uint duration) + public void AddGlobalCooldown(SpellInfo spellInfo, TimeSpan durationMs) { - _globalCooldowns[spellInfo.StartRecoveryCategory] = GameTime.GetGameTimeSystemPoint() + TimeSpan.FromMilliseconds(duration); + _globalCooldowns[spellInfo.StartRecoveryCategory] = GameTime.GetGameTimeSystemPoint() + durationMs; } public void CancelGlobalCooldown(SpellInfo spellInfo) @@ -900,15 +922,15 @@ namespace Game.Spells void GetCooldownDurations(SpellInfo spellInfo, uint itemId, ref uint categoryId) { - int notUsed = 0; + TimeSpan notUsed = TimeSpan.Zero; GetCooldownDurations(spellInfo, itemId, ref notUsed, ref categoryId, ref notUsed); } - void GetCooldownDurations(SpellInfo spellInfo, uint itemId, ref int cooldown, ref uint categoryId, ref int categoryCooldown) + void GetCooldownDurations(SpellInfo spellInfo, uint itemId, ref TimeSpan cooldown, ref uint categoryId, ref TimeSpan categoryCooldown) { - int tmpCooldown = -1; + TimeSpan tmpCooldown = TimeSpan.MinValue; uint tmpCategoryId = 0; - int tmpCategoryCooldown = -1; + TimeSpan tmpCategoryCooldown = TimeSpan.MinValue; // cooldown information stored in ItemEffect.db2, overriding normal cooldown and category if (itemId != 0) @@ -920,9 +942,9 @@ namespace Game.Spells { if (itemEffect.SpellID == spellInfo.Id) { - tmpCooldown = itemEffect.CoolDownMSec; + tmpCooldown = TimeSpan.FromMilliseconds(itemEffect.CoolDownMSec); tmpCategoryId = itemEffect.SpellCategoryID; - tmpCategoryCooldown = itemEffect.CategoryCoolDownMSec; + tmpCategoryCooldown = TimeSpan.FromMilliseconds(itemEffect.CategoryCoolDownMSec); break; } } @@ -930,11 +952,11 @@ namespace Game.Spells } // if no cooldown found above then base at DBC data - if (tmpCooldown < 0 && tmpCategoryCooldown < 0) + if (tmpCooldown < TimeSpan.Zero && tmpCategoryCooldown < TimeSpan.Zero) { - tmpCooldown = (int)spellInfo.RecoveryTime; + tmpCooldown = TimeSpan.FromMilliseconds(spellInfo.RecoveryTime); tmpCategoryId = spellInfo.GetCategory(); - tmpCategoryCooldown = (int)spellInfo.CategoryRecoveryTime; + tmpCategoryCooldown = TimeSpan.FromMilliseconds(spellInfo.CategoryRecoveryTime); } cooldown = tmpCooldown; diff --git a/Source/Scripts/World/DuelReset.cs b/Source/Scripts/World/DuelReset.cs index a4b6395f6..91ae182ec 100644 --- a/Source/Scripts/World/DuelReset.cs +++ b/Source/Scripts/World/DuelReset.cs @@ -101,26 +101,33 @@ namespace Scripts.World.DuelReset player.GetSpellHistory().ResetCooldowns(pair => { SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(pair.Key, Difficulty.None); - uint remainingCooldown = player.GetSpellHistory().GetRemainingCooldown(spellInfo); - uint totalCooldown = spellInfo.RecoveryTime; - uint categoryCooldown = spellInfo.CategoryRecoveryTime; + TimeSpan remainingCooldown = player.GetSpellHistory().GetRemainingCooldown(spellInfo); + TimeSpan totalCooldown = TimeSpan.FromMilliseconds(spellInfo.RecoveryTime); + TimeSpan categoryCooldown = TimeSpan.FromMilliseconds(spellInfo.CategoryRecoveryTime); - player.ApplySpellMod(spellInfo, SpellModOp.Cooldown, ref totalCooldown, null); + void applySpellMod(ref TimeSpan value) + { + int intValue = (int)value.TotalMilliseconds; + player.ApplySpellMod(spellInfo, SpellModOp.Cooldown, ref intValue, null); + value = TimeSpan.FromMilliseconds(intValue); + }; + + applySpellMod(ref totalCooldown); int cooldownMod = player.GetTotalAuraModifier(AuraType.ModCooldown); if (cooldownMod != 0) - totalCooldown += (uint)(cooldownMod * Time.InMilliseconds); + totalCooldown += TimeSpan.FromMilliseconds(cooldownMod); if (!spellInfo.HasAttribute(SpellAttr6.IgnoreCategoryCooldownMods)) - player.ApplySpellMod(spellInfo, SpellModOp.Cooldown, ref categoryCooldown, null); + applySpellMod(ref categoryCooldown); - return remainingCooldown > 0 + return remainingCooldown > TimeSpan.Zero && !pair.Value.OnHold - && TimeSpan.FromMilliseconds(totalCooldown) < TimeSpan.FromMinutes(10) - && TimeSpan.FromMilliseconds(categoryCooldown) < TimeSpan.FromMinutes(10) - && TimeSpan.FromMilliseconds(remainingCooldown) < TimeSpan.FromMinutes(10) - && (onStartDuel ? TimeSpan.FromMilliseconds(totalCooldown - remainingCooldown) > TimeSpan.FromSeconds(30) : true) - && (onStartDuel ? TimeSpan.FromMilliseconds(categoryCooldown - remainingCooldown) > TimeSpan.FromSeconds(30) : true); + && totalCooldown < TimeSpan.FromMinutes(10) + && categoryCooldown < TimeSpan.FromMinutes(10) + && remainingCooldown < TimeSpan.FromMinutes(10) + && (onStartDuel ? totalCooldown - remainingCooldown > TimeSpan.FromSeconds(30) : true) + && (onStartDuel ? categoryCooldown - remainingCooldown > TimeSpan.FromSeconds(30) : true); }, true); // pet cooldowns