48 cooldownEntry->
SpellId = *spellId;
49 cooldownEntry->
CooldownEnd = Clock::from_time_t(time_t(fields[2].GetUInt32()));
52 cooldownEntry->
CategoryEnd = Clock::from_time_t(time_t(fields[4].GetUInt32()));
59 stmt->
setUInt32(index++, cooldown.second.ItemId);
60 stmt->
setUInt32(index++,
uint32(Clock::to_time_t(cooldown.second.CooldownEnd)));
61 stmt->
setUInt32(index++, cooldown.second.CategoryId);
62 stmt->
setUInt32(index++,
uint32(Clock::to_time_t(cooldown.second.CategoryEnd)));
80 cooldownEntry->
SpellId = *spellId;
81 cooldownEntry->
CooldownEnd = Clock::from_time_t(time_t(fields[1].GetUInt32()));
84 cooldownEntry->
CategoryEnd = Clock::from_time_t(time_t(fields[3].GetUInt32()));
91 stmt->
setUInt32(index++,
uint32(Clock::to_time_t(cooldown.second.CooldownEnd)));
92 stmt->
setUInt32(index++, cooldown.second.CategoryId);
93 stmt->
setUInt32(index++,
uint32(Clock::to_time_t(cooldown.second.CategoryEnd)));
97template<
class OwnerType>
108 if (StatementInfo::ReadCooldown(cooldownsResult->Fetch(), &spellId, &cooldown))
115 }
while (cooldownsResult->NextRow());
119template<
class OwnerType>
126 StatementInfo::SetIdentifier(stmt, index++,
_owner);
131 if (!p.second.OnHold)
134 stmt =
CharacterDatabase.GetPreparedStatement(StatementInfo::CooldownsInsertStatement);
135 StatementInfo::SetIdentifier(stmt, index++,
_owner);
136 StatementInfo::WriteCooldown(stmt, index, p);
147 if (itr->second->CategoryEnd < now)
155 if (itr->second.CooldownEnd < now)
179 player->SetLastPotionId(itemID);
197 if (
HasCooldown(spellInfo->
Id, itemId, ignoreCategoryCooldown))
209 packet <<
uint8(cooldownsCount);
213 packet <<
uint32(spellCooldown.first);
214 packet <<
uint16(spellCooldown.second.CategoryId);
215 if (!spellCooldown.second.OnHold)
217 std::chrono::milliseconds cooldownDuration = std::chrono::duration_cast<std::chrono::milliseconds>(spellCooldown.second.CooldownEnd - now);
218 if (cooldownDuration.count() <= 0)
225 std::chrono::milliseconds categoryDuration = std::chrono::duration_cast<std::chrono::milliseconds>(spellCooldown.second.CategoryEnd - now);
226 if (categoryDuration.count() > 0)
229 packet <<
uint32(categoryDuration.count());
233 packet <<
uint32(cooldownDuration.count());
247 historyEntry.
SpellID = spellCooldown.first;
248 historyEntry.
ItemID = spellCooldown.second.ItemId;
249 historyEntry.
Category = spellCooldown.second.CategoryId;
251 if (spellCooldown.second.OnHold)
252 historyEntry.
OnHold =
true;
255 Milliseconds cooldownDuration = duration_cast<Milliseconds>(spellCooldown.second.CooldownEnd - now);
256 if (cooldownDuration <= 0ms)
259 Milliseconds categoryDuration = duration_cast<Milliseconds>(spellCooldown.second.CategoryEnd - now);
260 if (categoryDuration >= 0ms)
263 if (cooldownDuration > categoryDuration)
276 int32 categoryCooldown = -1;
281 Clock::time_point catrecTime;
282 Clock::time_point recTime;
283 bool needsCooldownPacket =
false;
296 if (cooldown <= 0 && categoryCooldown <= 0 && (categoryId == 76 || (spellInfo->
IsAutoRepeatRangedSpell() && spellInfo->
Id != 75)))
313 if (!playerOwner || playerOwner->
HasSpell(spellInfo->
Id))
315 needsCooldownPacket =
true;
324 if (categoryCooldown < 0)
325 categoryCooldown = 0;
328 if (cooldown == 0 && categoryCooldown == 0)
331 catrecTime = categoryCooldown ? curTime + std::chrono::duration_cast<Clock::duration>(std::chrono::milliseconds(categoryCooldown)) : curTime;
332 recTime = cooldown ? curTime + std::chrono::duration_cast<Clock::duration>(std::chrono::milliseconds(cooldown)) : catrecTime;
336 if (recTime != curTime)
338 AddCooldown(spellInfo->
Id, itemId, recTime, categoryId, catrecTime, onHold);
340 if (needsCooldownPacket)
346 playerOwner->SendDirectMessage(&spellCooldown);
364 data <<
uint32(categoryItr->second->SpellId);
366 player->SendDirectMessage(&data);
375 player->SendDirectMessage(&data);
386 cooldownEntry.
SpellId = spellId;
388 cooldownEntry.
ItemId = itemId;
391 cooldownEntry.
OnHold = onHold;
404 Clock::duration offset = std::chrono::duration_cast<Clock::duration>(std::chrono::milliseconds(cooldownModMs));
405 if (itr->second.CooldownEnd + offset > now)
406 itr->second.CooldownEnd += offset;
413 modifyCooldown <<
uint32(spellId);
415 modifyCooldown <<
int32(cooldownModMs);
416 playerOwner->SendDirectMessage(&modifyCooldown);
436 data <<
uint32(itr->first);
438 playerOwner->SendDirectMessage(&data);
449 std::vector<int32> cooldowns;
452 cooldowns.push_back(p.first);
466 if (ignoreCategoryCooldown)
484 Clock::time_point end;
487 end = itr->second.CooldownEnd;
494 end = catItr->second->CategoryEnd;
501 Clock::duration remaining = end - now;
502 return uint32(std::chrono::duration_cast<std::chrono::milliseconds>(remaining).count());
508 Clock::time_point lockoutEnd = now + std::chrono::duration_cast<Clock::duration>(std::chrono::milliseconds(lockoutTime));
513 std::set<uint32> knownSpells;
516 for (
auto const& p : plrOwner->GetSpellMap())
518 knownSpells.insert(p.first);
522 for (
auto const& p : petOwner->m_spells)
524 knownSpells.insert(p.first);
531 knownSpells.insert(creatureOwner->
m_spells[i]);
536 for (
uint32 spellId : knownSpells)
547 cooldowns[spellId] = lockoutTime;
554 if (!cooldowns.empty())
557 player->SendDirectMessage(&spellCooldowns);
598 for (
int32 spell : cooldowns)
603 playerOwner->SendDirectMessage(&data);
622 for (
auto const& cooldown : cooldowns)
624 data << cooldown.first;
625 data << cooldown.second;
631 ASSERT(cooldown || categoryId || categoryCooldown);
632 int32 tmpCooldown = -1;
634 int32 tmpCategoryCooldown = -1;
642 for (
ItemEffect const& itemEffect : proto->Effects)
644 if (
uint32(itemEffect.SpellID) == spellInfo->
Id)
646 tmpCooldown = itemEffect.CoolDownMSec;
647 tmpCategoryId = itemEffect.SpellCategoryID;
648 tmpCategoryCooldown = itemEffect.CategoryCoolDownMSec;
656 if (tmpCooldown < 0 && tmpCategoryCooldown < 0)
664 *cooldown = tmpCooldown;
666 *categoryId = tmpCategoryId;
667 if (categoryCooldown)
668 *categoryCooldown = tmpCategoryCooldown;
704 uint32 cooldownDuration = itr->second.CooldownEnd > now ? std::chrono::duration_cast<std::chrono::milliseconds>(itr->second.CooldownEnd - now).count() : 0;
710 cooldowns[itr->first] = cooldownDuration;
715 player->SendDirectMessage(&data);
CharacterDatabaseStatements
@ CHAR_INS_PET_SPELL_COOLDOWN
@ CHAR_DEL_CHAR_SPELL_COOLDOWNS
@ CHAR_INS_CHAR_SPELL_COOLDOWN
@ CHAR_DEL_PET_SPELL_COOLDOWNS
static const uint32 MAX_CREATURE_SPELLS
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
@ SPELL_PREVENTION_TYPE_SILENCE
@ SPELL_ATTR6_IGNORE_CATEGORY_COOLDOWN_MODS
@ SPELL_AURA_MOD_COOLDOWN
@ SPELL_COOLDOWN_FLAG_INCLUDE_EVENT_COOLDOWNS
Starts GCD for spells that should start their cooldown on events, requires SPELL_COOLDOWN_FLAG_INCLUD...
@ SPELL_COOLDOWN_FLAG_NONE
uint32 m_spells[MAX_CREATURE_SPELLS]
Class used to access individual fields of database query result.
LowType GetCounter() const
static Creature * ToCreature(Object *o)
static ObjectGuid GetGUID(Object const *o)
static Player * ToPlayer(Object *o)
bool HasSpell(uint32 spell) const override
void setUInt32(uint8 index, uint32 value)
static Clock::duration const InfinityCooldownDelay
void LoadFromDB(PreparedQueryResult cooldownsResult)
GlobalCooldownStorageType _globalCooldowns
bool IsReady(SpellInfo const *spellInfo, uint32 itemId=0, bool ignoreCategoryCooldown=false) const
bool HasGlobalCooldown(SpellInfo const *spellInfo) const
void SendCooldownEvent(SpellInfo const *spellInfo, uint32 itemId=0, Spell *spell=nullptr, bool startCooldown=true)
void ResetCooldown(uint32 spellId, bool update=false)
void SaveToDB(CharacterDatabaseTransaction trans)
void SendClearCooldowns(std::vector< int32 > const &cooldowns) const
static Clock::duration const InfinityCooldownDelayCheck
void AddCooldown(uint32 spellId, uint32 itemId, std::chrono::duration< Type, Period > cooldownDuration)
CooldownStorageType _spellCooldowns
uint32 GetRemainingCooldown(SpellInfo const *spellInfo) const
void AddGlobalCooldown(SpellInfo const *spellInfo, uint32 duration)
void CancelGlobalCooldown(SpellInfo const *spellInfo)
void WritePacket(WorldPacket &packet) const
void RestoreCooldownStateAfterDuel()
static void GetCooldownDurations(SpellInfo const *spellInfo, uint32 itemId, int32 *cooldown, uint32 *categoryId, int32 *categoryCooldown)
CooldownStorageType _spellCooldownsBeforeDuel
void SaveCooldownStateBeforeDuel()
Clock::time_point _schoolLockouts[MAX_SPELL_SCHOOL]
std::unordered_map< uint32, uint32 > PacketCooldowns
void ModifyCooldown(uint32 spellId, int32 cooldownModMs)
CooldownStorageType::iterator EraseCooldown(CooldownStorageType::iterator itr)
void HandleCooldowns(SpellInfo const *spellInfo, Item const *item, Spell *spell=nullptr)
bool HasCooldown(SpellInfo const *spellInfo, uint32 itemId=0, bool ignoreCategoryCooldown=false) const
void LockSpellSchool(SpellSchoolMask schoolMask, uint32 lockoutTime)
void StartCooldown(SpellInfo const *spellInfo, uint32 itemId, Spell *spell=nullptr, bool onHold=false)
Player * GetPlayerOwner() const
void BuildCooldownPacket(WorldPacket &data, uint8 flags, uint32 spellId, uint32 cooldown) const
bool IsSchoolLocked(SpellSchoolMask schoolMask) const
CategoryCooldownStorageType _categoryCooldowns
uint32 GetCategory() const
bool IsCooldownStartedOnEvent() const
uint32 CategoryRecoveryTime
SpellSchoolMask GetSchoolMask() const
bool HasAttribute(SpellAttr0 attribute) const
bool IsAutoRepeatRangedSpell() const
uint32 StartRecoveryCategory
bool IsIgnoringCooldowns() const
CharmInfo * GetCharmInfo()
uint32 GetAttackTime(WeaponAttackType att) const
int32 GetTotalAuraModifier(AuraType auraType) const
Player * GetSpellModOwner() const
Player * GetCharmerOrOwnerPlayerOrPlayerItself() const
void Initialize(uint16 opcode, size_t newres=200)
std::vector< SpellHistoryEntry > SpellHistory
SystemTimePoint GetSystemTime()
Current chrono system_clock time point.
uint32 GetPetNumber() const
Clock::time_point CooldownEnd
Clock::time_point CategoryEnd
static void WriteCooldown(PreparedStatementBase *stmt, uint8 &index, CooldownStorageType::value_type const &cooldown)
static void SetIdentifier(PreparedStatementBase *stmt, uint8 index, Unit *owner)
static bool ReadCooldown(Field *fields, uint32 *spellId, CooldownEntry *cooldownEntry)
static bool ReadCooldown(Field *fields, uint32 *spellId, CooldownEntry *cooldownEntry)
static void WriteCooldown(PreparedStatementBase *stmt, uint8 &index, CooldownStorageType::value_type const &cooldown)
static void SetIdentifier(PreparedStatementBase *stmt, uint8 index, Unit *owner)
int32 CategoryRecoveryTime