public void RestoreCooldownStateAfterDuel() { Player player = _owner.ToPlayer(); if (player) { // add all profession CDs created while in duel (if any) foreach (var c in _spellCooldowns) { SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(c.Key); if (spellInfo.RecoveryTime > 10 * Time.Minute * Time.InMilliseconds || spellInfo.CategoryRecoveryTime > 10 * Time.Minute * Time.InMilliseconds) { _spellCooldownsBeforeDuel[c.Key] = _spellCooldowns[c.Key]; } } // check for spell with onHold active before and during the duel foreach (var pair in _spellCooldownsBeforeDuel) { if (!pair.Value.OnHold && _spellCooldowns.ContainsKey(pair.Key) && !_spellCooldowns[pair.Key].OnHold) { _spellCooldowns[pair.Key] = _spellCooldownsBeforeDuel[pair.Key]; } } // update the client: restore old cooldowns SpellCooldownPkt spellCooldown = new SpellCooldownPkt(); spellCooldown.Caster = _owner.GetGUID(); spellCooldown.Flags = SpellCooldownFlags.IncludeEventCooldowns; foreach (var c in _spellCooldowns) { DateTime now = DateTime.Now; uint cooldownDuration = c.Value.CooldownEnd > now ? (uint)(c.Value.CooldownEnd - now).TotalMilliseconds : 0; // cooldownDuration must be between 0 and 10 minutes in order to avoid any visual bugs if (cooldownDuration <= 0 || cooldownDuration > 10 * Time.Minute * Time.InMilliseconds || c.Value.OnHold) { continue; } spellCooldown.SpellCooldowns.Add(new SpellCooldownStruct(c.Key, cooldownDuration)); } player.SendPacket(spellCooldown); } }
public void LockSpellSchool(SpellSchoolMask schoolMask, uint lockoutTime) { DateTime now = DateTime.Now; DateTime lockoutEnd = now + TimeSpan.FromMilliseconds(lockoutTime); for (int i = 0; i < (int)SpellSchools.Max; ++i) { if (Convert.ToBoolean((SpellSchoolMask)(1 << i) & schoolMask)) { _schoolLockouts[i] = lockoutEnd; } } List <uint> knownSpells = new List <uint>(); Player plrOwner = _owner.ToPlayer(); if (plrOwner) { foreach (var p in plrOwner.GetSpellMap()) { if (p.Value.State != PlayerSpellState.Removed) { knownSpells.Add(p.Key); } } } else if (_owner.IsPet()) { Pet petOwner = _owner.ToPet(); foreach (var p in petOwner.m_spells) { if (p.Value.state != PetSpellState.Removed) { knownSpells.Add(p.Key); } } } else { Creature creatureOwner = _owner.ToCreature(); for (byte i = 0; i < SharedConst.MaxCreatureSpells; ++i) { if (creatureOwner.m_spells[i] != 0) { knownSpells.Add(creatureOwner.m_spells[i]); } } } SpellCooldownPkt spellCooldown = new SpellCooldownPkt(); spellCooldown.Caster = _owner.GetGUID(); spellCooldown.Flags = SpellCooldownFlags.None; foreach (uint spellId in knownSpells) { SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(spellId); if (spellInfo.IsCooldownStartedOnEvent()) { continue; } if (!spellInfo.PreventionType.HasAnyFlag(SpellPreventionType.Silence)) { continue; } if (Convert.ToBoolean(schoolMask & spellInfo.GetSchoolMask()) && GetRemainingCooldown(spellInfo) < lockoutTime) { spellCooldown.SpellCooldowns.Add(new SpellCooldownStruct(spellId, lockoutTime)); AddCooldown(spellId, 0, lockoutEnd, 0, now); } } Player player = GetPlayerOwner(); if (player) { if (!spellCooldown.SpellCooldowns.Empty()) { player.SendPacket(spellCooldown); } } }
public void StartCooldown(SpellInfo spellInfo, uint itemId, Spell spell = null, bool onHold = false) { // init cooldown values uint categoryId = 0; int cooldown = -1; int categoryCooldown = -1; GetCooldownDurations(spellInfo, itemId, ref cooldown, ref categoryId, ref categoryCooldown); DateTime curTime = DateTime.Now; DateTime catrecTime; DateTime recTime; bool needsCooldownPacket = false; // 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; } 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)_owner.GetUInt32Value(UnitFields.RangedAttackTime); } // Now we have cooldown data (if found any), time to apply mods Player modOwner = _owner.GetSpellModOwner(); if (modOwner) { if (cooldown > 0) { modOwner.ApplySpellMod(spellInfo.Id, SpellModOp.Cooldown, ref cooldown, spell); } if (categoryCooldown > 0 && !spellInfo.HasAttribute(SpellAttr6.IgnoreCategoryCooldownMods)) { modOwner.ApplySpellMod(spellInfo.Id, SpellModOp.Cooldown, ref categoryCooldown, spell); } } if (_owner.HasAuraTypeWithAffectMask(AuraType.ModSpellCooldownByHaste, spellInfo)) { cooldown = (int)(cooldown * _owner.GetFloatValue(UnitFields.ModCastHaste)); categoryCooldown = (int)(categoryCooldown * _owner.GetFloatValue(UnitFields.ModCastHaste)); } if (_owner.HasAuraTypeWithAffectMask(AuraType.ModCooldownByHasteRegen, spellInfo)) { cooldown = (int)(cooldown * _owner.GetFloatValue(UnitFields.ModHasteRegen)); categoryCooldown = (int)(categoryCooldown * _owner.GetFloatValue(UnitFields.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 += cooldownMod * Time.InMilliseconds; // 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 > 0) { cooldown += categoryModifier; } if (categoryCooldown > 0) { categoryCooldown += categoryModifier; } } SpellCategoryRecord categoryEntry = CliDB.SpellCategoryStorage.LookupByKey(categoryId); if (categoryEntry.Flags.HasAnyFlag(SpellCategoryFlags.CooldownExpiresAtDailyReset)) { categoryCooldown = (int)(Time.UnixTimeToDateTime(Global.WorldMgr.GetNextDailyQuestsResetTime()) - DateTime.Now).TotalMilliseconds; } } // replace negative cooldowns by 0 if (cooldown < 0) { cooldown = 0; } if (categoryCooldown < 0) { categoryCooldown = 0; } // no cooldown after applying spell mods if (cooldown == 0 && categoryCooldown == 0) { return; } catrecTime = categoryCooldown != 0 ? curTime + TimeSpan.FromMilliseconds(categoryCooldown) : curTime; recTime = cooldown != 0 ? curTime + TimeSpan.FromMilliseconds(cooldown) : catrecTime; } // self spell cooldown if (recTime != curTime) { AddCooldown(spellInfo.Id, itemId, recTime, categoryId, catrecTime, onHold); if (needsCooldownPacket) { Player playerOwner = GetPlayerOwner(); if (playerOwner) { SpellCooldownPkt spellCooldown = new SpellCooldownPkt(); spellCooldown.Caster = _owner.GetGUID(); spellCooldown.Flags = SpellCooldownFlags.None; spellCooldown.SpellCooldowns.Add(new SpellCooldownStruct(spellInfo.Id, (uint)cooldown)); playerOwner.SendPacket(spellCooldown); } } } }