Core/Spells: SpellHistory updates
Port From (https://github.com/TrinityCore/TrinityCore/commit/8cc6520b89583d4bf6549b28fa5b7390fc2b0b9d)
This commit is contained in:
@@ -1578,7 +1578,7 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
m_weaponChangeTimer = spellProto.StartRecoveryTime;
|
m_weaponChangeTimer = spellProto.StartRecoveryTime;
|
||||||
|
|
||||||
GetSpellHistory().AddGlobalCooldown(spellProto, m_weaponChangeTimer);
|
GetSpellHistory().AddGlobalCooldown(spellProto, TimeSpan.FromMilliseconds(m_weaponChangeTimer));
|
||||||
|
|
||||||
SpellCooldownPkt spellCooldown = new();
|
SpellCooldownPkt spellCooldown = new();
|
||||||
spellCooldown.Caster = GetGUID();
|
spellCooldown.Caster = GetGUID();
|
||||||
@@ -3912,7 +3912,7 @@ namespace Game.Entities
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Don't replace longer cooldowns by equip cooldown if we have any.
|
// 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;
|
continue;
|
||||||
|
|
||||||
GetSpellHistory().AddCooldown((uint)effectData.SpellID, pItem.GetEntry(), TimeSpan.FromSeconds(30));
|
GetSpellHistory().AddCooldown((uint)effectData.SpellID, pItem.GetEntry(), TimeSpan.FromSeconds(30));
|
||||||
|
|||||||
@@ -6388,7 +6388,7 @@ namespace Game.Entities
|
|||||||
BroadcastTextRecord bct = CliDB.BroadcastTextStorage.LookupByKey(textId);
|
BroadcastTextRecord bct = CliDB.BroadcastTextStorage.LookupByKey(textId);
|
||||||
if (bct == null)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -538,10 +538,12 @@ namespace Game.Networking.Packets
|
|||||||
_worldPacket.WriteUInt32(SpellID);
|
_worldPacket.WriteUInt32(SpellID);
|
||||||
_worldPacket.WriteInt32(DeltaTime);
|
_worldPacket.WriteInt32(DeltaTime);
|
||||||
_worldPacket.WriteBit(IsPet);
|
_worldPacket.WriteBit(IsPet);
|
||||||
|
_worldPacket.WriteBit(WithoutCategoryCooldown);
|
||||||
_worldPacket.FlushBits();
|
_worldPacket.FlushBits();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsPet;
|
public bool IsPet;
|
||||||
|
public bool WithoutCategoryCooldown;
|
||||||
public int DeltaTime;
|
public int DeltaTime;
|
||||||
public uint SpellID;
|
public uint SpellID;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1361,7 +1361,7 @@ namespace Game.Spells
|
|||||||
{
|
{
|
||||||
// This additional check is needed to add a minimal delay before cooldown in in effect
|
// 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
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
else // and add if needed
|
else // and add if needed
|
||||||
|
|||||||
+22
-11
@@ -7246,42 +7246,53 @@ namespace Game.Spells
|
|||||||
if (!CanHaveGlobalCooldown(m_caster))
|
if (!CanHaveGlobalCooldown(m_caster))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int gcd = (int)m_spellInfo.StartRecoveryTime;
|
TimeSpan gcd = TimeSpan.FromMilliseconds(m_spellInfo.StartRecoveryTime);
|
||||||
if (gcd == 0 || m_spellInfo.StartRecoveryCategory == 0)
|
if (gcd == TimeSpan.Zero || m_spellInfo.StartRecoveryCategory == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_caster.IsTypeId(TypeId.Player))
|
if (m_caster.IsTypeId(TypeId.Player))
|
||||||
if (m_caster.ToPlayer().GetCommandStatus(PlayerCommandStates.Cooldown))
|
if (m_caster.ToPlayer().GetCommandStatus(PlayerCommandStates.Cooldown))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
TimeSpan MinGCD = TimeSpan.FromMilliseconds(750);
|
||||||
|
TimeSpan MaxGCD = TimeSpan.FromMilliseconds(1500);
|
||||||
|
|
||||||
// Global cooldown can't leave range 1..1.5 secs
|
// 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
|
// 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.
|
// 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
|
// gcd modifier auras are applied only to own spells and only players have such mods
|
||||||
Player modOwner = m_caster.GetSpellModOwner();
|
Player modOwner = m_caster.GetSpellModOwner();
|
||||||
if (modOwner)
|
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 ||
|
bool isMeleeOrRangedSpell = m_spellInfo.DmgClass == SpellDmgClass.Melee || m_spellInfo.DmgClass == SpellDmgClass.Ranged ||
|
||||||
m_spellInfo.HasAttribute(SpellAttr0.ReqAmmo) || m_spellInfo.HasAttribute(SpellAttr0.Ability);
|
m_spellInfo.HasAttribute(SpellAttr0.ReqAmmo) || m_spellInfo.HasAttribute(SpellAttr0.Ability);
|
||||||
|
|
||||||
// Apply haste rating
|
// 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);
|
gcd = TimeSpan.FromMilliseconds(gcd.TotalMilliseconds * m_caster.ToUnit().m_unitData.ModSpellHaste);
|
||||||
MathFunctions.RoundToInterval(ref gcd, 750, 1500);
|
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);
|
gcd = TimeSpan.FromMilliseconds(gcd.TotalMilliseconds * m_caster.ToUnit().m_unitData.ModHasteRegen);
|
||||||
MathFunctions.RoundToInterval(ref gcd, 750, 1500);
|
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()
|
void CancelGlobalCooldown()
|
||||||
|
|||||||
@@ -2648,7 +2648,8 @@ namespace Game.Spells
|
|||||||
if (unitCaster != null)
|
if (unitCaster != null)
|
||||||
{
|
{
|
||||||
int duration = m_spellInfo.GetDuration();
|
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)
|
if (m_spellInfo.DmgClass == SpellDmgClass.Magic)
|
||||||
Unit.ProcSkillsAndAuras(unitCaster, unitTarget, ProcFlags.DoneSpellMagicDmgClassNeg, ProcFlags.TakenSpellMagicDmgClassNeg, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.Hit, ProcFlagsHit.Interrupt, null, null, null);
|
Unit.ProcSkillsAndAuras(unitCaster, unitTarget, ProcFlags.DoneSpellMagicDmgClassNeg, ProcFlags.TakenSpellMagicDmgClassNeg, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.Hit, ProcFlagsHit.Interrupt, null, null, null);
|
||||||
else if (m_spellInfo.DmgClass == SpellDmgClass.Melee)
|
else if (m_spellInfo.DmgClass == SpellDmgClass.Melee)
|
||||||
|
|||||||
@@ -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
|
// init cooldown values
|
||||||
uint categoryId = 0;
|
uint categoryId = 0;
|
||||||
int cooldown = -1;
|
TimeSpan cooldown = TimeSpan.Zero;
|
||||||
int categoryCooldown = -1;
|
TimeSpan categoryCooldown = TimeSpan.Zero;
|
||||||
|
|
||||||
GetCooldownDurations(spellInfo, itemId, ref cooldown, ref categoryId, ref categoryCooldown);
|
|
||||||
|
|
||||||
DateTime curTime = GameTime.GetGameTimeSystemPoint();
|
DateTime curTime = GameTime.GetGameTimeSystemPoint();
|
||||||
DateTime catrecTime;
|
DateTime catrecTime;
|
||||||
DateTime recTime;
|
DateTime recTime;
|
||||||
bool needsCooldownPacket = false;
|
bool needsCooldownPacket = false;
|
||||||
|
|
||||||
|
if (!forcedCooldown.HasValue)
|
||||||
|
GetCooldownDurations(spellInfo, itemId, ref cooldown, ref categoryId, ref categoryCooldown);
|
||||||
|
else
|
||||||
|
cooldown = forcedCooldown.Value;
|
||||||
|
|
||||||
// overwrite time for selected category
|
// overwrite time for selected category
|
||||||
if (onHold)
|
if (onHold)
|
||||||
{
|
{
|
||||||
// use +MONTH as infinite cooldown marker
|
// use +MONTH as infinite cooldown marker
|
||||||
catrecTime = categoryCooldown > 0 ? (curTime + PlayerConst.InfinityCooldownDelay) : curTime;
|
catrecTime = categoryCooldown > TimeSpan.Zero ? (curTime + PlayerConst.InfinityCooldownDelay) : curTime;
|
||||||
recTime = cooldown > 0 ? (curTime + PlayerConst.InfinityCooldownDelay) : catrecTime;
|
recTime = cooldown > TimeSpan.Zero ? (curTime + PlayerConst.InfinityCooldownDelay) : catrecTime;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// shoot spells used equipped item cooldown values already assigned in GetAttackTime(RANGED_ATTACK)
|
if (!forcedCooldown.HasValue)
|
||||||
// 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 (cooldown >= 0)
|
// shoot spells used equipped item cooldown values already assigned in SetBaseAttackTime(RANGED_ATTACK)
|
||||||
modOwner.ApplySpellMod(spellInfo, SpellModOp.Cooldown, ref cooldown, spell);
|
// 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))
|
// Now we have cooldown data (if found any), time to apply mods
|
||||||
modOwner.ApplySpellMod(spellInfo, SpellModOp.Cooldown, ref categoryCooldown, spell);
|
Player modOwner = _owner.GetSpellModOwner();
|
||||||
}
|
if (modOwner)
|
||||||
|
|
||||||
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))
|
|
||||||
{
|
{
|
||||||
needsCooldownPacket = true;
|
void applySpellMod(ref TimeSpan value)
|
||||||
cooldown += cooldownMod * Time.InMilliseconds; // SPELL_AURA_MOD_COOLDOWN does not affect category cooldows, verified with shaman shocks
|
{
|
||||||
}
|
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
|
if (cooldown >= TimeSpan.Zero)
|
||||||
// Note: This aura applies its modifiers to all cooldowns of spells with set category, not to category cooldown only
|
applySpellMod(ref cooldown);
|
||||||
if (categoryId != 0)
|
|
||||||
{
|
|
||||||
int categoryModifier = _owner.GetTotalAuraModifierByMiscValue(AuraType.ModSpellCategoryCooldown, (int)categoryId);
|
|
||||||
if (categoryModifier != 0)
|
|
||||||
{
|
|
||||||
if (cooldown > 0)
|
|
||||||
cooldown += categoryModifier;
|
|
||||||
|
|
||||||
if (categoryCooldown > 0)
|
if (categoryCooldown >= TimeSpan.Zero && !spellInfo.HasAttribute(SpellAttr6.IgnoreCategoryCooldownMods))
|
||||||
categoryCooldown += categoryModifier;
|
applySpellMod(ref categoryCooldown);
|
||||||
}
|
}
|
||||||
|
|
||||||
SpellCategoryRecord categoryEntry = CliDB.SpellCategoryStorage.LookupByKey(categoryId);
|
if (_owner.HasAuraTypeWithAffectMask(AuraType.ModSpellCooldownByHaste, spellInfo))
|
||||||
if (categoryEntry.Flags.HasAnyFlag(SpellCategoryFlags.CooldownExpiresAtDailyReset))
|
{
|
||||||
categoryCooldown = (int)(Time.UnixTimeToDateTime(Global.WorldMgr.GetNextDailyQuestsResetTime()) - GameTime.GetGameTimeSystemPoint()).TotalMilliseconds;
|
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
|
// replace negative cooldowns by 0
|
||||||
if (cooldown < 0)
|
if (cooldown < TimeSpan.Zero)
|
||||||
cooldown = 0;
|
cooldown = TimeSpan.Zero;
|
||||||
|
|
||||||
if (categoryCooldown < 0)
|
if (categoryCooldown < TimeSpan.Zero)
|
||||||
categoryCooldown = 0;
|
categoryCooldown = TimeSpan.Zero;
|
||||||
|
|
||||||
// no cooldown after applying spell mods
|
// no cooldown after applying spell mods
|
||||||
if (cooldown == 0 && categoryCooldown == 0)
|
if (cooldown == TimeSpan.Zero && categoryCooldown == TimeSpan.Zero)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
catrecTime = categoryCooldown != 0 ? curTime + TimeSpan.FromMilliseconds(categoryCooldown) : curTime;
|
catrecTime = categoryCooldown != TimeSpan.Zero ? curTime + categoryCooldown : curTime;
|
||||||
recTime = cooldown != 0 ? curTime + TimeSpan.FromMilliseconds(cooldown) : catrecTime;
|
recTime = cooldown != TimeSpan.Zero ? curTime + cooldown : catrecTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
// self spell cooldown
|
// self spell cooldown
|
||||||
@@ -445,7 +460,7 @@ namespace Game.Spells
|
|||||||
SpellCooldownPkt spellCooldown = new();
|
SpellCooldownPkt spellCooldown = new();
|
||||||
spellCooldown.Caster = _owner.GetGUID();
|
spellCooldown.Caster = _owner.GetGUID();
|
||||||
spellCooldown.Flags = SpellCooldownFlags.None;
|
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);
|
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)
|
public void AddCooldown(uint spellId, uint itemId, DateTime cooldownEnd, uint categoryId, DateTime categoryEnd, bool onHold = false)
|
||||||
{
|
{
|
||||||
CooldownEntry cooldownEntry = new();
|
CooldownEntry cooldownEntry = new();
|
||||||
cooldownEntry.SpellId = spellId;
|
// scripts can start multiple cooldowns for a given spell, only store the longest one
|
||||||
cooldownEntry.CooldownEnd = cooldownEnd;
|
if (cooldownEnd > cooldownEntry.CooldownEnd || categoryEnd > cooldownEntry.CategoryEnd || onHold)
|
||||||
cooldownEntry.ItemId = itemId;
|
{
|
||||||
cooldownEntry.CategoryId = categoryId;
|
cooldownEntry.SpellId = spellId;
|
||||||
cooldownEntry.CategoryEnd = categoryEnd;
|
cooldownEntry.CooldownEnd = cooldownEnd;
|
||||||
cooldownEntry.OnHold = onHold;
|
cooldownEntry.ItemId = itemId;
|
||||||
_spellCooldowns[spellId] = cooldownEntry;
|
cooldownEntry.CategoryId = categoryId;
|
||||||
|
cooldownEntry.CategoryEnd = categoryEnd;
|
||||||
|
cooldownEntry.OnHold = onHold;
|
||||||
|
_spellCooldowns[spellId] = cooldownEntry;
|
||||||
|
|
||||||
if (categoryId != 0)
|
if (categoryId != 0)
|
||||||
_categoryCooldowns[categoryId] = cooldownEntry;
|
_categoryCooldowns[categoryId] = cooldownEntry;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ModifySpellCooldown(uint spellId, TimeSpan offset)
|
public void ModifySpellCooldown(uint spellId, TimeSpan offset)
|
||||||
@@ -623,7 +642,7 @@ namespace Game.Spells
|
|||||||
return _categoryCooldowns.ContainsKey(category);
|
return _categoryCooldowns.ContainsKey(category);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint GetRemainingCooldown(SpellInfo spellInfo)
|
public TimeSpan GetRemainingCooldown(SpellInfo spellInfo)
|
||||||
{
|
{
|
||||||
DateTime end;
|
DateTime end;
|
||||||
var entry = _spellCooldowns.LookupByKey(spellInfo.Id);
|
var entry = _spellCooldowns.LookupByKey(spellInfo.Id);
|
||||||
@@ -633,23 +652,23 @@ namespace Game.Spells
|
|||||||
{
|
{
|
||||||
var cooldownEntry = _categoryCooldowns.LookupByKey(spellInfo.GetCategory());
|
var cooldownEntry = _categoryCooldowns.LookupByKey(spellInfo.GetCategory());
|
||||||
if (cooldownEntry == null)
|
if (cooldownEntry == null)
|
||||||
return 0;
|
return TimeSpan.Zero;
|
||||||
|
|
||||||
end = cooldownEntry.CategoryEnd;
|
end = cooldownEntry.CategoryEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
DateTime now = GameTime.GetGameTimeSystemPoint();
|
DateTime now = GameTime.GetGameTimeSystemPoint();
|
||||||
if (end < now)
|
if (end < now)
|
||||||
return 0;
|
return TimeSpan.Zero;
|
||||||
|
|
||||||
var remaining = end - now;
|
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 now = GameTime.GetGameTimeSystemPoint();
|
||||||
DateTime lockoutEnd = now + TimeSpan.FromMilliseconds(lockoutTime);
|
DateTime lockoutEnd = now + lockoutTime;
|
||||||
for (int i = 0; i < (int)SpellSchools.Max; ++i)
|
for (int i = 0; i < (int)SpellSchools.Max; ++i)
|
||||||
if (Convert.ToBoolean((SpellSchoolMask)(1 << i) & schoolMask))
|
if (Convert.ToBoolean((SpellSchoolMask)(1 << i) & schoolMask))
|
||||||
_schoolLockouts[i] = lockoutEnd;
|
_schoolLockouts[i] = lockoutEnd;
|
||||||
@@ -679,7 +698,7 @@ namespace Game.Spells
|
|||||||
|
|
||||||
SpellCooldownPkt spellCooldown = new();
|
SpellCooldownPkt spellCooldown = new();
|
||||||
spellCooldown.Caster = _owner.GetGUID();
|
spellCooldown.Caster = _owner.GetGUID();
|
||||||
spellCooldown.Flags = SpellCooldownFlags.None;
|
spellCooldown.Flags = SpellCooldownFlags.LossOfControlUi;
|
||||||
foreach (uint spellId in knownSpells)
|
foreach (uint spellId in knownSpells)
|
||||||
{
|
{
|
||||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(spellId, _owner.GetMap().GetDifficultyID());
|
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(spellId, _owner.GetMap().GetDifficultyID());
|
||||||
@@ -689,11 +708,14 @@ namespace Game.Spells
|
|||||||
if (!spellInfo.PreventionType.HasAnyFlag(SpellPreventionType.Silence))
|
if (!spellInfo.PreventionType.HasAnyFlag(SpellPreventionType.Silence))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (Convert.ToBoolean(schoolMask & spellInfo.GetSchoolMask()) && GetRemainingCooldown(spellInfo) < lockoutTime)
|
if ((schoolMask & spellInfo.GetSchoolMask()) == 0)
|
||||||
{
|
continue;
|
||||||
spellCooldown.SpellCooldowns.Add(new SpellCooldownStruct(spellId, lockoutTime));
|
|
||||||
|
if (GetRemainingCooldown(spellInfo) < lockoutTime)
|
||||||
AddCooldown(spellId, 0, lockoutEnd, 0, now);
|
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();
|
Player player = GetPlayerOwner();
|
||||||
@@ -856,9 +878,9 @@ namespace Game.Spells
|
|||||||
return _globalCooldowns.ContainsKey(spellInfo.StartRecoveryCategory) && _globalCooldowns[spellInfo.StartRecoveryCategory] > GameTime.GetGameTimeSystemPoint();
|
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)
|
public void CancelGlobalCooldown(SpellInfo spellInfo)
|
||||||
@@ -900,15 +922,15 @@ namespace Game.Spells
|
|||||||
|
|
||||||
void GetCooldownDurations(SpellInfo spellInfo, uint itemId, ref uint categoryId)
|
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);
|
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;
|
uint tmpCategoryId = 0;
|
||||||
int tmpCategoryCooldown = -1;
|
TimeSpan tmpCategoryCooldown = TimeSpan.MinValue;
|
||||||
|
|
||||||
// cooldown information stored in ItemEffect.db2, overriding normal cooldown and category
|
// cooldown information stored in ItemEffect.db2, overriding normal cooldown and category
|
||||||
if (itemId != 0)
|
if (itemId != 0)
|
||||||
@@ -920,9 +942,9 @@ namespace Game.Spells
|
|||||||
{
|
{
|
||||||
if (itemEffect.SpellID == spellInfo.Id)
|
if (itemEffect.SpellID == spellInfo.Id)
|
||||||
{
|
{
|
||||||
tmpCooldown = itemEffect.CoolDownMSec;
|
tmpCooldown = TimeSpan.FromMilliseconds(itemEffect.CoolDownMSec);
|
||||||
tmpCategoryId = itemEffect.SpellCategoryID;
|
tmpCategoryId = itemEffect.SpellCategoryID;
|
||||||
tmpCategoryCooldown = itemEffect.CategoryCoolDownMSec;
|
tmpCategoryCooldown = TimeSpan.FromMilliseconds(itemEffect.CategoryCoolDownMSec);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -930,11 +952,11 @@ namespace Game.Spells
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if no cooldown found above then base at DBC data
|
// 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();
|
tmpCategoryId = spellInfo.GetCategory();
|
||||||
tmpCategoryCooldown = (int)spellInfo.CategoryRecoveryTime;
|
tmpCategoryCooldown = TimeSpan.FromMilliseconds(spellInfo.CategoryRecoveryTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
cooldown = tmpCooldown;
|
cooldown = tmpCooldown;
|
||||||
|
|||||||
@@ -101,26 +101,33 @@ namespace Scripts.World.DuelReset
|
|||||||
player.GetSpellHistory().ResetCooldowns(pair =>
|
player.GetSpellHistory().ResetCooldowns(pair =>
|
||||||
{
|
{
|
||||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(pair.Key, Difficulty.None);
|
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(pair.Key, Difficulty.None);
|
||||||
uint remainingCooldown = player.GetSpellHistory().GetRemainingCooldown(spellInfo);
|
TimeSpan remainingCooldown = player.GetSpellHistory().GetRemainingCooldown(spellInfo);
|
||||||
uint totalCooldown = spellInfo.RecoveryTime;
|
TimeSpan totalCooldown = TimeSpan.FromMilliseconds(spellInfo.RecoveryTime);
|
||||||
uint categoryCooldown = spellInfo.CategoryRecoveryTime;
|
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);
|
int cooldownMod = player.GetTotalAuraModifier(AuraType.ModCooldown);
|
||||||
if (cooldownMod != 0)
|
if (cooldownMod != 0)
|
||||||
totalCooldown += (uint)(cooldownMod * Time.InMilliseconds);
|
totalCooldown += TimeSpan.FromMilliseconds(cooldownMod);
|
||||||
|
|
||||||
if (!spellInfo.HasAttribute(SpellAttr6.IgnoreCategoryCooldownMods))
|
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
|
&& !pair.Value.OnHold
|
||||||
&& TimeSpan.FromMilliseconds(totalCooldown) < TimeSpan.FromMinutes(10)
|
&& totalCooldown < TimeSpan.FromMinutes(10)
|
||||||
&& TimeSpan.FromMilliseconds(categoryCooldown) < TimeSpan.FromMinutes(10)
|
&& categoryCooldown < TimeSpan.FromMinutes(10)
|
||||||
&& TimeSpan.FromMilliseconds(remainingCooldown) < TimeSpan.FromMinutes(10)
|
&& remainingCooldown < TimeSpan.FromMinutes(10)
|
||||||
&& (onStartDuel ? TimeSpan.FromMilliseconds(totalCooldown - remainingCooldown) > TimeSpan.FromSeconds(30) : true)
|
&& (onStartDuel ? totalCooldown - remainingCooldown > TimeSpan.FromSeconds(30) : true)
|
||||||
&& (onStartDuel ? TimeSpan.FromMilliseconds(categoryCooldown - remainingCooldown) > TimeSpan.FromSeconds(30) : true);
|
&& (onStartDuel ? categoryCooldown - remainingCooldown > TimeSpan.FromSeconds(30) : true);
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
// pet cooldowns
|
// pet cooldowns
|
||||||
|
|||||||
Reference in New Issue
Block a user