TrinityCore
SpellHistory Class Reference

#include <SpellHistory.h>

Classes

struct  ChargeEntry
 
struct  CooldownEntry
 
struct  PersistenceHelper
 
struct  PersistenceHelper< Pet >
 
struct  PersistenceHelper< Player >
 

Public Types

using Clock = std::chrono::system_clock
 
using Duration = Milliseconds
 
using ChargeEntryCollection = std::deque< ChargeEntry >
 
using CooldownStorageType = std::unordered_map< uint32, CooldownEntry >
 
using CategoryCooldownStorageType = std::unordered_map< uint32, CooldownEntry * >
 
using ChargeStorageType = std::unordered_map< uint32, ChargeEntryCollection >
 
using GlobalCooldownStorageType = std::unordered_map< uint32, Clock::time_point >
 

Public Member Functions

 SpellHistory (Unit *owner)
 
 ~SpellHistory ()
 
 SpellHistory (SpellHistory const &)=delete
 
 SpellHistory (SpellHistory &&)=delete
 
SpellHistoryoperator= (SpellHistory const &)=delete
 
SpellHistoryoperator= (SpellHistory &&)=delete
 
template<class OwnerType >
void LoadFromDB (PreparedQueryResult cooldownsResult, PreparedQueryResult chargesResult)
 
template<class OwnerType >
void SaveToDB (CharacterDatabaseTransaction trans)
 
void Update ()
 
void HandleCooldowns (SpellInfo const *spellInfo, Item const *item, Spell *spell=nullptr)
 
void HandleCooldowns (SpellInfo const *spellInfo, uint32 itemId, Spell *spell=nullptr)
 
bool IsReady (SpellInfo const *spellInfo, uint32 itemId=0) const
 
template<class PacketType >
void WritePacket (PacketType *packet) const
 
void StartCooldown (SpellInfo const *spellInfo, uint32 itemId, Spell *spell=nullptr, bool onHold=false, Optional< Duration > forcedCooldown={})
 
void SendCooldownEvent (SpellInfo const *spellInfo, uint32 itemId=0, Spell *spell=nullptr, bool startCooldown=true)
 
void AddCooldown (uint32 spellId, uint32 itemId, Duration cooldownDuration)
 
void AddCooldown (uint32 spellId, uint32 itemId, Clock::time_point cooldownEnd, uint32 categoryId, Clock::time_point categoryEnd, bool onHold=false)
 
void ModifyCooldown (uint32 spellId, Duration cooldownMod, bool withoutCategoryCooldown=false)
 
void ModifyCooldown (SpellInfo const *spellInfo, Duration cooldownMod, bool withoutCategoryCooldown=false)
 
void ResetCooldown (uint32 spellId, bool update=false)
 
void ResetCooldown (CooldownStorageType::iterator &itr, bool update=false)
 
template<typename Predicate >
void ResetCooldowns (Predicate predicate, bool update=false)
 
void ResetAllCooldowns ()
 
bool HasCooldown (SpellInfo const *spellInfo, uint32 itemId=0) const
 
bool HasCooldown (uint32 spellId, uint32 itemId=0) const
 
Duration GetRemainingCooldown (SpellInfo const *spellInfo) const
 
Duration GetRemainingCategoryCooldown (uint32 categoryId) const
 
Duration GetRemainingCategoryCooldown (SpellInfo const *spellInfo) const
 
void LockSpellSchool (SpellSchoolMask schoolMask, Duration lockoutTime)
 
bool IsSchoolLocked (SpellSchoolMask schoolMask) const
 
bool ConsumeCharge (uint32 chargeCategoryId)
 
void ModifyChargeRecoveryTime (uint32 chargeCategoryId, Duration cooldownMod)
 
void RestoreCharge (uint32 chargeCategoryId)
 
void ResetCharges (uint32 chargeCategoryId)
 
void ResetAllCharges ()
 
bool HasCharge (uint32 chargeCategoryId) const
 
int32 GetMaxCharges (uint32 chargeCategoryId) const
 
int32 GetChargeRecoveryTime (uint32 chargeCategoryId) const
 
bool HasGlobalCooldown (SpellInfo const *spellInfo) const
 
void AddGlobalCooldown (SpellInfo const *spellInfo, Duration duration)
 
void CancelGlobalCooldown (SpellInfo const *spellInfo)
 
void SaveCooldownStateBeforeDuel ()
 
void RestoreCooldownStateAfterDuel ()
 
template<>
void WritePacket (WorldPackets::Spells::SendSpellHistory *sendSpellHistory) const
 
template<>
void WritePacket (WorldPackets::Spells::SendSpellCharges *sendSpellCharges) const
 
template<>
void WritePacket (WorldPackets::Pet::PetSpells *petSpells) const
 

Static Public Attributes

static Duration const InfinityCooldownDelay = Seconds(MONTH)
 

Private Member Functions

PlayerGetPlayerOwner () const
 
void ModifySpellCooldown (uint32 spellId, Duration cooldownMod, bool withoutCategoryCooldown=false)
 
void SendClearCooldowns (std::vector< int32 > const &cooldowns) const
 
CooldownStorageType::iterator EraseCooldown (CooldownStorageType::iterator itr)
 
void SendSetSpellCharges (uint32 chargeCategoryId, ChargeEntryCollection const &chargeCollection)
 

Static Private Member Functions

static void GetCooldownDurations (SpellInfo const *spellInfo, uint32 itemId, Duration *cooldown, uint32 *categoryId, Duration *categoryCooldown)
 

Private Attributes

Unit_owner
 
CooldownStorageType _spellCooldowns
 
CooldownStorageType _spellCooldownsBeforeDuel
 
CategoryCooldownStorageType _categoryCooldowns
 
Clock::time_point _schoolLockouts [MAX_SPELL_SCHOOL]
 
ChargeStorageType _categoryCharges
 
GlobalCooldownStorageType _globalCooldowns
 

Member Typedef Documentation

◆ CategoryCooldownStorageType

◆ ChargeEntryCollection

◆ ChargeStorageType

◆ Clock

using SpellHistory::Clock = std::chrono::system_clock

◆ CooldownStorageType

◆ Duration

◆ GlobalCooldownStorageType

using SpellHistory::GlobalCooldownStorageType = std::unordered_map<uint32 , Clock::time_point>

Constructor & Destructor Documentation

◆ SpellHistory() [1/3]

SpellHistory::SpellHistory ( Unit owner)
explicit
139  : _owner(owner), _schoolLockouts()
140 {
141 }
Unit * _owner
Definition: SpellHistory.h:181
Clock::time_point _schoolLockouts[MAX_SPELL_SCHOOL]
Definition: SpellHistory.h:185
+ Here is the call graph for this function:

◆ ~SpellHistory()

SpellHistory::~SpellHistory ( )
default
+ Here is the caller graph for this function:

◆ SpellHistory() [2/3]

SpellHistory::SpellHistory ( SpellHistory const &  )
delete

◆ SpellHistory() [3/3]

SpellHistory::SpellHistory ( SpellHistory &&  )
delete

Member Function Documentation

◆ AddCooldown() [1/2]

void SpellHistory::AddCooldown ( uint32  spellId,
uint32  itemId,
Duration  cooldownDuration 
)
inline
108  {
109  Clock::time_point now = GameTime::GetTime<Clock>();
110  AddCooldown(spellId, itemId, now + cooldownDuration, 0, now);
111  }
void AddCooldown(uint32 spellId, uint32 itemId, Duration cooldownDuration)
Definition: SpellHistory.h:107
+ Here is the caller graph for this function:

◆ AddCooldown() [2/2]

void SpellHistory::AddCooldown ( uint32  spellId,
uint32  itemId,
Clock::time_point  cooldownEnd,
uint32  categoryId,
Clock::time_point  categoryEnd,
bool  onHold = false 
)
554 {
555  CooldownEntry& cooldownEntry = _spellCooldowns[spellId];
556  // scripts can start multiple cooldowns for a given spell, only store the longest one
557  if (cooldownEnd > cooldownEntry.CooldownEnd || categoryEnd > cooldownEntry.CategoryEnd || onHold)
558  {
559  cooldownEntry.SpellId = spellId;
560  cooldownEntry.CooldownEnd = cooldownEnd;
561  cooldownEntry.ItemId = itemId;
562  cooldownEntry.CategoryId = categoryId;
563  cooldownEntry.CategoryEnd = categoryEnd;
564  cooldownEntry.OnHold = onHold;
565 
566  if (categoryId)
567  _categoryCooldowns[categoryId] = &cooldownEntry;
568  }
569 }
CategoryCooldownStorageType _categoryCooldowns
Definition: SpellHistory.h:184
CooldownStorageType _spellCooldowns
Definition: SpellHistory.h:182

◆ AddGlobalCooldown()

void SpellHistory::AddGlobalCooldown ( SpellInfo const *  spellInfo,
Duration  duration 
)
933 {
934  _globalCooldowns[spellInfo->StartRecoveryCategory] = Clock::now() + duration;
935 }
GlobalCooldownStorageType _globalCooldowns
Definition: SpellHistory.h:187
+ Here is the caller graph for this function:

◆ CancelGlobalCooldown()

void SpellHistory::CancelGlobalCooldown ( SpellInfo const *  spellInfo)
938 {
939  _globalCooldowns[spellInfo->StartRecoveryCategory] = Clock::time_point(Clock::duration(0));
940 }
GlobalCooldownStorageType _globalCooldowns
Definition: SpellHistory.h:187

◆ ConsumeCharge()

bool SpellHistory::ConsumeCharge ( uint32  chargeCategoryId)
795 {
796  if (!sSpellCategoryStore.LookupEntry(chargeCategoryId))
797  return false;
798 
799  int32 chargeRecovery = GetChargeRecoveryTime(chargeCategoryId);
800  if (chargeRecovery > 0 && GetMaxCharges(chargeCategoryId) > 0)
801  {
802  Clock::time_point recoveryStart;
803  std::deque<ChargeEntry>& charges = _categoryCharges[chargeCategoryId];
804  if (charges.empty())
805  recoveryStart = GameTime::GetTime<Clock>();
806  else
807  recoveryStart = charges.back().RechargeEnd;
808 
809  charges.emplace_back(recoveryStart, Milliseconds(chargeRecovery));
810  return true;
811  }
812 
813  return false;
814 }
ChargeStorageType _categoryCharges
Definition: SpellHistory.h:186
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition: Duration.h:24
int32_t int32
Definition: Define.h:139
DB2Storage< SpellCategoryEntry > sSpellCategoryStore("SpellCategory.db2", SpellCategoryLoadInfo::Instance())
int32 GetMaxCharges(uint32 chargeCategoryId) const
Definition: SpellHistory.cpp:894
int32 GetChargeRecoveryTime(uint32 chargeCategoryId) const
Definition: SpellHistory.cpp:905
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ EraseCooldown()

CooldownStorageType::iterator SpellHistory::EraseCooldown ( CooldownStorageType::iterator  itr)
inlineprivate
172  {
173  _categoryCooldowns.erase(itr->second.CategoryId);
174  return _spellCooldowns.erase(itr);
175  }
CategoryCooldownStorageType _categoryCooldowns
Definition: SpellHistory.h:184
CooldownStorageType _spellCooldowns
Definition: SpellHistory.h:182
+ Here is the caller graph for this function:

◆ GetChargeRecoveryTime()

int32 SpellHistory::GetChargeRecoveryTime ( uint32  chargeCategoryId) const
906 {
907  SpellCategoryEntry const* chargeCategoryEntry = sSpellCategoryStore.LookupEntry(chargeCategoryId);
908  if (!chargeCategoryEntry)
909  return 0;
910 
911  int32 recoveryTime = chargeCategoryEntry->ChargeRecoveryTime;
912  recoveryTime += _owner->GetTotalAuraModifierByMiscValue(SPELL_AURA_CHARGE_RECOVERY_MOD, chargeCategoryId);
913 
914  float recoveryTimeF = float(recoveryTime);
916 
918  recoveryTimeF *= _owner->m_unitData->ModSpellHaste;
919 
921  recoveryTimeF *= _owner->m_unitData->ModHasteRegen;
922 
923  return int32(std::floor(recoveryTimeF));
924 }
int32 GetTotalAuraModifierByMiscValue(AuraType auraType, int32 misc_value) const
Definition: Unit.cpp:4845
Unit * _owner
Definition: SpellHistory.h:181
float GetTotalAuraMultiplierByMiscValue(AuraType auraType, int32 misc_value) const
Definition: Unit.cpp:4855
int32 ChargeRecoveryTime
Definition: DB2Structure.h:3248
Definition: SpellAuraDefines.h:547
Definition: DB2Structure.h:3241
Definition: SpellAuraDefines.h:551
UF::UpdateField< UF::UnitData, 0, TYPEID_UNIT > m_unitData
Definition: Unit.h:1886
int32_t int32
Definition: Define.h:139
DB2Storage< SpellCategoryEntry > sSpellCategoryStore("SpellCategory.db2", SpellCategoryLoadInfo::Instance())
bool HasAuraType(AuraType auraType) const
Definition: Unit.cpp:4530
Definition: SpellAuraDefines.h:550
Definition: SpellAuraDefines.h:548
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ GetCooldownDurations()

void SpellHistory::GetCooldownDurations ( SpellInfo const *  spellInfo,
uint32  itemId,
Duration cooldown,
uint32 categoryId,
Duration categoryCooldown 
)
staticprivate
973 {
974  ASSERT(cooldown || categoryId || categoryCooldown);
975  Duration tmpCooldown = Duration::min();
976  uint32 tmpCategoryId = 0;
977  Duration tmpCategoryCooldown = Duration::min();
978 
979  // cooldown information stored in ItemEffect.db2, overriding normal cooldown and category
980  if (itemId)
981  {
982  if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId))
983  {
984  for (ItemEffectEntry const* itemEffect : proto->Effects)
985  {
986  if (uint32(itemEffect->SpellID) == spellInfo->Id)
987  {
988  tmpCooldown = Milliseconds(itemEffect->CoolDownMSec);
989  tmpCategoryId = itemEffect->SpellCategoryID;
990  tmpCategoryCooldown = Milliseconds(itemEffect->CategoryCoolDownMSec);
991  break;
992  }
993  }
994  }
995  }
996 
997  // if no cooldown found above then base at DBC data
998  if (tmpCooldown < Duration::zero() && tmpCategoryCooldown < Duration::zero())
999  {
1000  tmpCooldown = Milliseconds(spellInfo->RecoveryTime);
1001  tmpCategoryId = spellInfo->GetCategory();
1002  tmpCategoryCooldown = Milliseconds(spellInfo->CategoryRecoveryTime);
1003  }
1004 
1005  if (cooldown)
1006  *cooldown = tmpCooldown;
1007  if (categoryId)
1008  *categoryId = tmpCategoryId;
1009  if (categoryCooldown)
1010  *categoryCooldown = tmpCategoryCooldown;
1011 }
Definition: DB2Structure.h:2062
#define sObjectMgr
Definition: ObjectMgr.h:1967
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition: Duration.h:24
int32 SpellID
Definition: DB2Structure.h:2071
int32 CoolDownMSec
Definition: DB2Structure.h:2068
int32 CategoryCoolDownMSec
Definition: DB2Structure.h:2069
Milliseconds Duration
Definition: SpellHistory.h:50
uint32_t uint32
Definition: Define.h:143
Definition: ItemTemplate.h:735
#define ASSERT
Definition: Errors.h:68
uint16 SpellCategoryID
Definition: DB2Structure.h:2070
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ GetMaxCharges()

int32 SpellHistory::GetMaxCharges ( uint32  chargeCategoryId) const
895 {
896  SpellCategoryEntry const* chargeCategoryEntry = sSpellCategoryStore.LookupEntry(chargeCategoryId);
897  if (!chargeCategoryEntry)
898  return 0;
899 
900  uint32 charges = chargeCategoryEntry->MaxCharges;
902  return charges;
903 }
int32 GetTotalAuraModifierByMiscValue(AuraType auraType, int32 misc_value) const
Definition: Unit.cpp:4845
Definition: SpellAuraDefines.h:505
Unit * _owner
Definition: SpellHistory.h:181
Definition: DB2Structure.h:3241
uint32_t uint32
Definition: Define.h:143
DB2Storage< SpellCategoryEntry > sSpellCategoryStore("SpellCategory.db2", SpellCategoryLoadInfo::Instance())
int8 MaxCharges
Definition: DB2Structure.h:3247
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ GetPlayerOwner()

Player * SpellHistory::GetPlayerOwner ( ) const
private
943 {
945 }
Unit * _owner
Definition: SpellHistory.h:181
Player * GetCharmerOrOwnerPlayerOrPlayerItself() const
Definition: Object.cpp:2128
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ GetRemainingCategoryCooldown() [1/2]

SpellHistory::Duration SpellHistory::GetRemainingCategoryCooldown ( uint32  categoryId) const
706 {
707  Clock::time_point end;
708  auto catItr = _categoryCooldowns.find(categoryId);
709  if (catItr == _categoryCooldowns.end())
710  return Duration::zero();
711 
712  end = catItr->second->CategoryEnd;
713 
714  Clock::time_point now = GameTime::GetTime<Clock>();
715  if (end < now)
716  return Duration::zero();
717 
718  Clock::duration remaining = end - now;
719  return std::chrono::duration_cast<Milliseconds>(remaining);
720 }
CategoryCooldownStorageType _categoryCooldowns
Definition: SpellHistory.h:184
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition: Duration.h:24
+ Here is the caller graph for this function:

◆ GetRemainingCategoryCooldown() [2/2]

SpellHistory::Duration SpellHistory::GetRemainingCategoryCooldown ( SpellInfo const *  spellInfo) const
723 {
724  return GetRemainingCategoryCooldown(spellInfo->GetCategory());
725 }
Duration GetRemainingCategoryCooldown(uint32 categoryId) const
Definition: SpellHistory.cpp:705
+ Here is the call graph for this function:

◆ GetRemainingCooldown()

SpellHistory::Duration SpellHistory::GetRemainingCooldown ( SpellInfo const *  spellInfo) const
683 {
684  Clock::time_point end;
685  auto itr = _spellCooldowns.find(spellInfo->Id);
686  if (itr != _spellCooldowns.end())
687  end = itr->second.CooldownEnd;
688  else
689  {
690  auto catItr = _categoryCooldowns.find(spellInfo->GetCategory());
691  if (catItr == _categoryCooldowns.end())
692  return Duration::zero();
693 
694  end = catItr->second->CategoryEnd;
695  }
696 
697  Clock::time_point now = GameTime::GetTime<Clock>();
698  if (end < now)
699  return Duration::zero();
700 
701  Clock::duration remaining = end - now;
702  return std::chrono::duration_cast<Milliseconds>(remaining);
703 }
CategoryCooldownStorageType _categoryCooldowns
Definition: SpellHistory.h:184
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition: Duration.h:24
CooldownStorageType _spellCooldowns
Definition: SpellHistory.h:182
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ HandleCooldowns() [1/2]

void SpellHistory::HandleCooldowns ( SpellInfo const *  spellInfo,
Item const *  item,
Spell spell = nullptr 
)
247 {
248  HandleCooldowns(spellInfo, item ? item->GetEntry() : 0, spell);
249 }
void HandleCooldowns(SpellInfo const *spellInfo, Item const *item, Spell *spell=nullptr)
Definition: SpellHistory.cpp:246
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ HandleCooldowns() [2/2]

void SpellHistory::HandleCooldowns ( SpellInfo const *  spellInfo,
uint32  itemId,
Spell spell = nullptr 
)
252 {
253  if (spell && spell->IsIgnoringCooldowns())
254  return;
255 
256  if (ConsumeCharge(spellInfo->ChargeCategoryId))
257  return;
258 
259  if (Player* player = _owner->ToPlayer())
260  {
261  // potions start cooldown until exiting combat
262  if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId))
263  {
264  if (itemTemplate->IsPotion() || spellInfo->IsCooldownStartedOnEvent())
265  {
266  player->SetLastPotionId(itemId);
267  return;
268  }
269  }
270  }
271 
272  if (spellInfo->IsCooldownStartedOnEvent() || spellInfo->IsPassive())
273  return;
274 
275  StartCooldown(spellInfo, itemId, spell);
276 }
static Player * ToPlayer(Object *o)
Definition: Object.h:198
Unit * _owner
Definition: SpellHistory.h:181
#define sObjectMgr
Definition: ObjectMgr.h:1967
bool IsIgnoringCooldowns() const
Definition: Spell.cpp:7966
bool ConsumeCharge(uint32 chargeCategoryId)
Definition: SpellHistory.cpp:794
Definition: ItemTemplate.h:735
void StartCooldown(SpellInfo const *spellInfo, uint32 itemId, Spell *spell=nullptr, bool onHold=false, Optional< Duration > forcedCooldown={})
Definition: SpellHistory.cpp:405
Definition: Player.h:1131
+ Here is the call graph for this function:

◆ HasCharge()

bool SpellHistory::HasCharge ( uint32  chargeCategoryId) const
881 {
882  if (!sSpellCategoryStore.LookupEntry(chargeCategoryId))
883  return true;
884 
885  // Check if the spell is currently using charges (untalented warlock Dark Soul)
886  int32 maxCharges = GetMaxCharges(chargeCategoryId);
887  if (maxCharges <= 0)
888  return true;
889 
890  auto itr = _categoryCharges.find(chargeCategoryId);
891  return itr == _categoryCharges.end() || int32(itr->second.size()) < maxCharges;
892 }
ChargeStorageType _categoryCharges
Definition: SpellHistory.h:186
int32_t int32
Definition: Define.h:139
DB2Storage< SpellCategoryEntry > sSpellCategoryStore("SpellCategory.db2", SpellCategoryLoadInfo::Instance())
int32 GetMaxCharges(uint32 chargeCategoryId) const
Definition: SpellHistory.cpp:894
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ HasCooldown() [1/2]

bool SpellHistory::HasCooldown ( SpellInfo const *  spellInfo,
uint32  itemId = 0 
) const
665 {
666  if (_spellCooldowns.count(spellInfo->Id) != 0)
667  return true;
668 
669  uint32 category = 0;
670  GetCooldownDurations(spellInfo, itemId, nullptr, &category, nullptr);
671  if (!category)
672  return false;
673 
674  return _categoryCooldowns.count(category) != 0;
675 }
static void GetCooldownDurations(SpellInfo const *spellInfo, uint32 itemId, Duration *cooldown, uint32 *categoryId, Duration *categoryCooldown)
Definition: SpellHistory.cpp:972
CategoryCooldownStorageType _categoryCooldowns
Definition: SpellHistory.h:184
uint32_t uint32
Definition: Define.h:143
CooldownStorageType _spellCooldowns
Definition: SpellHistory.h:182
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ HasCooldown() [2/2]

bool SpellHistory::HasCooldown ( uint32  spellId,
uint32  itemId = 0 
) const
678 {
679  return HasCooldown(sSpellMgr->AssertSpellInfo(spellId, _owner->GetMap()->GetDifficultyID()), itemId);
680 }
Difficulty GetDifficultyID() const
Definition: Map.h:401
Unit * _owner
Definition: SpellHistory.h:181
bool HasCooldown(SpellInfo const *spellInfo, uint32 itemId=0) const
Definition: SpellHistory.cpp:664
Map * GetMap() const
Definition: Object.h:555
#define sSpellMgr
Definition: SpellMgr.h:825
+ Here is the call graph for this function:

◆ HasGlobalCooldown()

bool SpellHistory::HasGlobalCooldown ( SpellInfo const *  spellInfo) const
927 {
928  auto itr = _globalCooldowns.find(spellInfo->StartRecoveryCategory);
929  return itr != _globalCooldowns.end() && itr->second > Clock::now();
930 }
GlobalCooldownStorageType _globalCooldowns
Definition: SpellHistory.h:187
+ Here is the caller graph for this function:

◆ IsReady()

bool SpellHistory::IsReady ( SpellInfo const *  spellInfo,
uint32  itemId = 0 
) const
279 {
280  if (spellInfo->PreventionType & SPELL_PREVENTION_TYPE_SILENCE)
281  if (IsSchoolLocked(spellInfo->GetSchoolMask()))
282  return false;
283 
284  if (HasCooldown(spellInfo, itemId))
285  return false;
286 
287  if (!HasCharge(spellInfo->ChargeCategoryId))
288  return false;
289 
290  return true;
291 }
Definition: SharedDefines.h:2725
bool HasCooldown(SpellInfo const *spellInfo, uint32 itemId=0) const
Definition: SpellHistory.cpp:664
bool HasCharge(uint32 chargeCategoryId) const
Definition: SpellHistory.cpp:880
bool IsSchoolLocked(SpellSchoolMask schoolMask) const
Definition: SpellHistory.cpp:783
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ IsSchoolLocked()

bool SpellHistory::IsSchoolLocked ( SpellSchoolMask  schoolMask) const
784 {
785  Clock::time_point now = GameTime::GetTime<Clock>();
786  for (uint32 i = 0; i < MAX_SPELL_SCHOOL; ++i)
787  if (SpellSchoolMask(1 << i) & schoolMask)
788  if (_schoolLockouts[i] > now)
789  return true;
790 
791  return false;
792 }
Clock::time_point _schoolLockouts[MAX_SPELL_SCHOOL]
Definition: SpellHistory.h:185
SpellSchoolMask
Definition: SharedDefines.h:310
Definition: SharedDefines.h:307
uint32_t uint32
Definition: Define.h:143
+ Here is the caller graph for this function:

◆ LoadFromDB()

template<class OwnerType >
template void SpellHistory::LoadFromDB< Pet > ( PreparedQueryResult  cooldownsResult,
PreparedQueryResult  chargesResult 
)
147 {
148  using StatementInfo = PersistenceHelper<OwnerType>;
149 
150  if (cooldownsResult)
151  {
152  do
153  {
154  uint32 spellId;
155  CooldownEntry cooldown;
156  if (StatementInfo::ReadCooldown(cooldownsResult->Fetch(), &spellId, &cooldown))
157  {
158  _spellCooldowns[spellId] = cooldown;
159  if (cooldown.CategoryId)
160  _categoryCooldowns[cooldown.CategoryId] = &_spellCooldowns[spellId];
161  }
162 
163  } while (cooldownsResult->NextRow());
164  }
165 
166  if (chargesResult)
167  {
168  do
169  {
170  Field* fields = chargesResult->Fetch();
171  uint32 categoryId = 0;
172  ChargeEntry charges;
173  if (StatementInfo::ReadCharge(fields, &categoryId, &charges))
174  _categoryCharges[categoryId].push_back(charges);
175 
176  } while (chargesResult->NextRow());
177  }
178 }
ChargeStorageType _categoryCharges
Definition: SpellHistory.h:186
CategoryCooldownStorageType _categoryCooldowns
Definition: SpellHistory.h:184
Class used to access individual fields of database query result.
Definition: Field.h:83
uint32_t uint32
Definition: Define.h:143
CooldownStorageType _spellCooldowns
Definition: SpellHistory.h:182
+ Here is the caller graph for this function:

◆ LockSpellSchool()

void SpellHistory::LockSpellSchool ( SpellSchoolMask  schoolMask,
Duration  lockoutTime 
)
728 {
729  Clock::time_point now = GameTime::GetTime<Clock>();
730  Clock::time_point lockoutEnd = now + lockoutTime;
731  for (uint32 i = 0; i < MAX_SPELL_SCHOOL; ++i)
732  if (SpellSchoolMask(1 << i) & schoolMask)
733  _schoolLockouts[i] = lockoutEnd;
734 
735  std::set<uint32> knownSpells;
736  if (Player* plrOwner = _owner->ToPlayer())
737  {
738  for (auto const& p : plrOwner->GetSpellMap())
739  if (p.second.state != PLAYERSPELL_REMOVED)
740  knownSpells.insert(p.first);
741  }
742  else if (Pet* petOwner = _owner->ToPet())
743  {
744  for (auto const& p : petOwner->m_spells)
745  if (p.second.state != PETSPELL_REMOVED)
746  knownSpells.insert(p.first);
747  }
748  else
749  {
750  Creature* creatureOwner = _owner->ToCreature();
751  for (uint32 spell : creatureOwner->m_spells)
752  if (spell)
753  knownSpells.insert(spell);
754  }
755 
757  spellCooldown.Caster = _owner->GetGUID();
759  for (uint32 spellId : knownSpells)
760  {
761  SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(spellId, _owner->GetMap()->GetDifficultyID());
762  if (spellInfo->IsCooldownStartedOnEvent())
763  continue;
764 
765  if (!(spellInfo->PreventionType & SPELL_PREVENTION_TYPE_SILENCE))
766  continue;
767 
768  if (!(schoolMask & spellInfo->GetSchoolMask()))
769  continue;
770 
771  if (GetRemainingCooldown(spellInfo) < lockoutTime)
772  AddCooldown(spellId, 0, lockoutEnd, 0, now);
773 
774  // always send cooldown, even if it will be shorter than already existing cooldown for LossOfControl UI
775  spellCooldown.SpellCooldowns.emplace_back(spellId, lockoutTime.count());
776  }
777 
778  if (Player* player = GetPlayerOwner())
779  if (!spellCooldown.SpellCooldowns.empty())
780  player->SendDirectMessage(spellCooldown.Write());
781 }
static Player * ToPlayer(Object *o)
Definition: Object.h:198
std::vector< SpellCooldownStruct > SpellCooldowns
Definition: SpellPackets.h:610
Player * GetPlayerOwner() const
Definition: SpellHistory.cpp:942
ObjectGuid Caster
Definition: SpellPackets.h:611
Difficulty GetDifficultyID() const
Definition: Map.h:401
Definition: Player.h:180
Definition: SharedDefines.h:2725
Unit * _owner
Definition: SpellHistory.h:181
Definition: SpellInfo.h:342
Pet * ToPet()
Definition: Unit.h:1841
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:156
uint32 m_spells[MAX_CREATURE_SPELLS]
Definition: Creature.h:246
Definition: Creature.h:69
Duration GetRemainingCooldown(SpellInfo const *spellInfo) const
Definition: SpellHistory.cpp:682
Clock::time_point _schoolLockouts[MAX_SPELL_SCHOOL]
Definition: SpellHistory.h:185
void AddCooldown(uint32 spellId, uint32 itemId, Duration cooldownDuration)
Definition: SpellHistory.h:107
SpellSchoolMask
Definition: SharedDefines.h:310
Shows interrupt cooldown in loss of control ui.
Definition: SpellHistory.h:42
Map * GetMap() const
Definition: Object.h:555
Definition: SharedDefines.h:307
WorldPacket const * Write() override
Definition: SpellPackets.cpp:636
#define sSpellMgr
Definition: SpellMgr.h:825
uint32_t uint32
Definition: Define.h:143
SpellSchoolMask GetSchoolMask() const
Definition: SpellInfo.cpp:2362
static Creature * ToCreature(Object *o)
Definition: Object.h:204
Definition: PetDefines.h:66
uint32 PreventionType
Definition: SpellInfo.h:428
bool IsCooldownStartedOnEvent() const
Definition: SpellInfo.cpp:1576
Definition: SpellPackets.h:603
uint8 Flags
Definition: SpellPackets.h:612
Definition: Player.h:1131
Definition: Pet.h:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ModifyChargeRecoveryTime()

void SpellHistory::ModifyChargeRecoveryTime ( uint32  chargeCategoryId,
Duration  cooldownMod 
)
817 {
818  SpellCategoryEntry const* chargeCategoryEntry = sSpellCategoryStore.LookupEntry(chargeCategoryId);
819  if (!chargeCategoryEntry)
820  return;
821 
822  auto itr = _categoryCharges.find(chargeCategoryId);
823  if (itr == _categoryCharges.end() || itr->second.empty())
824  return;
825 
826  Clock::time_point now = GameTime::GetTime<Clock>();
827 
828  for (ChargeEntry& entry : itr->second)
829  {
830  entry.RechargeStart += cooldownMod;
831  entry.RechargeEnd += cooldownMod;
832  }
833 
834  while (!itr->second.empty() && itr->second.front().RechargeEnd < now)
835  itr->second.pop_front();
836 
837  SendSetSpellCharges(chargeCategoryId, itr->second);
838 }
ChargeStorageType _categoryCharges
Definition: SpellHistory.h:186
void SendSetSpellCharges(uint32 chargeCategoryId, ChargeEntryCollection const &chargeCollection)
Definition: SpellHistory.cpp:958
Definition: DB2Structure.h:3241
DB2Storage< SpellCategoryEntry > sSpellCategoryStore("SpellCategory.db2", SpellCategoryLoadInfo::Instance())
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ModifyCooldown() [1/2]

void SpellHistory::ModifyCooldown ( uint32  spellId,
Duration  cooldownMod,
bool  withoutCategoryCooldown = false 
)
606 {
607  if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, _owner->GetMap()->GetDifficultyID()))
608  ModifyCooldown(spellInfo, cooldownMod, withoutCategoryCooldown);
609 }
Difficulty GetDifficultyID() const
Definition: Map.h:401
Unit * _owner
Definition: SpellHistory.h:181
Definition: SpellInfo.h:342
Map * GetMap() const
Definition: Object.h:555
#define sSpellMgr
Definition: SpellMgr.h:825
void ModifyCooldown(uint32 spellId, Duration cooldownMod, bool withoutCategoryCooldown=false)
Definition: SpellHistory.cpp:605
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ModifyCooldown() [2/2]

void SpellHistory::ModifyCooldown ( SpellInfo const *  spellInfo,
Duration  cooldownMod,
bool  withoutCategoryCooldown = false 
)
612 {
613  if (!cooldownMod.count())
614  return;
615 
616  if (GetChargeRecoveryTime(spellInfo->ChargeCategoryId) > 0 && GetMaxCharges(spellInfo->ChargeCategoryId) > 0)
617  ModifyChargeRecoveryTime(spellInfo->ChargeCategoryId, cooldownMod);
618  else
619  ModifySpellCooldown(spellInfo->Id, cooldownMod, withoutCategoryCooldown);
620 }
void ModifySpellCooldown(uint32 spellId, Duration cooldownMod, bool withoutCategoryCooldown=false)
Definition: SpellHistory.cpp:571
int32 GetMaxCharges(uint32 chargeCategoryId) const
Definition: SpellHistory.cpp:894
int32 GetChargeRecoveryTime(uint32 chargeCategoryId) const
Definition: SpellHistory.cpp:905
void ModifyChargeRecoveryTime(uint32 chargeCategoryId, Duration cooldownMod)
Definition: SpellHistory.cpp:816
+ Here is the call graph for this function:

◆ ModifySpellCooldown()

void SpellHistory::ModifySpellCooldown ( uint32  spellId,
Duration  cooldownMod,
bool  withoutCategoryCooldown = false 
)
private
572 {
573  auto itr = _spellCooldowns.find(spellId);
574  if (!offset.count() || itr == _spellCooldowns.end())
575  return;
576 
577  Clock::time_point now = GameTime::GetTime<Clock>();
578 
579  itr->second.CooldownEnd += offset;
580 
581  if (itr->second.CategoryId)
582  {
583  if (!withoutCategoryCooldown)
584  itr->second.CategoryEnd += offset;
585 
586  // Because category cooldown existence is tied to regular cooldown, we cannot allow a situation where regular cooldown is shorter than category
587  if (itr->second.CooldownEnd < itr->second.CategoryEnd)
588  itr->second.CooldownEnd = itr->second.CategoryEnd;
589  }
590 
591  if (itr->second.CooldownEnd <= now)
592  EraseCooldown(itr);
593 
594  if (Player* playerOwner = GetPlayerOwner())
595  {
597  modifyCooldown.IsPet = _owner != playerOwner;
598  modifyCooldown.SpellID = spellId;
599  modifyCooldown.DeltaTime = std::chrono::duration_cast<Milliseconds>(offset).count();
600  modifyCooldown.WithoutCategoryCooldown = withoutCategoryCooldown;
601  playerOwner->SendDirectMessage(modifyCooldown.Write());
602  }
603 }
Player * GetPlayerOwner() const
Definition: SpellHistory.cpp:942
Unit * _owner
Definition: SpellHistory.h:181
int32 DeltaTime
Definition: SpellPackets.h:589
bool IsPet
Definition: SpellPackets.h:587
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition: Duration.h:24
Definition: SpellPackets.h:580
bool WithoutCategoryCooldown
Definition: SpellPackets.h:588
int32 SpellID
Definition: SpellPackets.h:590
CooldownStorageType _spellCooldowns
Definition: SpellHistory.h:182
Definition: Player.h:1131
CooldownStorageType::iterator EraseCooldown(CooldownStorageType::iterator itr)
Definition: SpellHistory.h:171
WorldPacket const * Write() override
Definition: SpellPackets.cpp:617
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ operator=() [1/2]

SpellHistory& SpellHistory::operator= ( SpellHistory const &  )
delete

◆ operator=() [2/2]

SpellHistory& SpellHistory::operator= ( SpellHistory &&  )
delete

◆ ResetAllCharges()

void SpellHistory::ResetAllCharges ( )
869 {
870  _categoryCharges.clear();
871 
872  if (Player* player = GetPlayerOwner())
873  {
874  WorldPackets::Spells::ClearAllSpellCharges clearAllSpellCharges;
875  clearAllSpellCharges.IsPet = _owner != player;
876  player->SendDirectMessage(clearAllSpellCharges.Write());
877  }
878 }
Player * GetPlayerOwner() const
Definition: SpellHistory.cpp:942
ChargeStorageType _categoryCharges
Definition: SpellHistory.h:186
Unit * _owner
Definition: SpellHistory.h:181
Definition: SpellPackets.h:638
bool IsPet
Definition: SpellPackets.h:645
WorldPacket const * Write() override
Definition: SpellPackets.cpp:676
Definition: Player.h:1131
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ResetAllCooldowns()

void SpellHistory::ResetAllCooldowns ( )
649 {
650  if (GetPlayerOwner())
651  {
652  std::vector<int32> cooldowns;
653  cooldowns.reserve(_spellCooldowns.size());
654  for (auto const& p : _spellCooldowns)
655  cooldowns.push_back(p.first);
656 
657  SendClearCooldowns(cooldowns);
658  }
659 
660  _categoryCooldowns.clear();
661  _spellCooldowns.clear();
662 }
Player * GetPlayerOwner() const
Definition: SpellHistory.cpp:942
CategoryCooldownStorageType _categoryCooldowns
Definition: SpellHistory.h:184
CooldownStorageType _spellCooldowns
Definition: SpellHistory.h:182
void SendClearCooldowns(std::vector< int32 > const &cooldowns) const
Definition: SpellHistory.cpp:947
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ResetCharges()

void SpellHistory::ResetCharges ( uint32  chargeCategoryId)
852 {
853  auto itr = _categoryCharges.find(chargeCategoryId);
854  if (itr != _categoryCharges.end())
855  {
856  _categoryCharges.erase(itr);
857 
858  if (Player* player = GetPlayerOwner())
859  {
860  WorldPackets::Spells::ClearSpellCharges clearSpellCharges;
861  clearSpellCharges.IsPet = _owner != player;
862  clearSpellCharges.Category = chargeCategoryId;
863  player->SendDirectMessage(clearSpellCharges.Write());
864  }
865  }
866 }
Player * GetPlayerOwner() const
Definition: SpellHistory.cpp:942
ChargeStorageType _categoryCharges
Definition: SpellHistory.h:186
Unit * _owner
Definition: SpellHistory.h:181
int32 Category
Definition: SpellPackets.h:656
bool IsPet
Definition: SpellPackets.h:655
WorldPacket const * Write() override
Definition: SpellPackets.cpp:684
Definition: SpellPackets.h:648
Definition: Player.h:1131
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ResetCooldown() [1/2]

void SpellHistory::ResetCooldown ( uint32  spellId,
bool  update = false 
)
623 {
624  auto itr = _spellCooldowns.find(spellId);
625  if (itr == _spellCooldowns.end())
626  return;
627 
628  ResetCooldown(itr, update);
629 }
CooldownStorageType _spellCooldowns
Definition: SpellHistory.h:182
void ResetCooldown(uint32 spellId, bool update=false)
Definition: SpellHistory.cpp:622
+ Here is the caller graph for this function:

◆ ResetCooldown() [2/2]

void SpellHistory::ResetCooldown ( CooldownStorageType::iterator &  itr,
bool  update = false 
)
632 {
633  if (update)
634  {
635  if (Player* playerOwner = GetPlayerOwner())
636  {
638  clearCooldown.IsPet = _owner != playerOwner;
639  clearCooldown.SpellID = itr->first;
640  clearCooldown.ClearOnHold = false;
641  playerOwner->SendDirectMessage(clearCooldown.Write());
642  }
643  }
644 
645  itr = EraseCooldown(itr);
646 }
Player * GetPlayerOwner() const
Definition: SpellHistory.cpp:942
bool IsPet
Definition: SpellPackets.h:575
Unit * _owner
Definition: SpellHistory.h:181
bool ClearOnHold
Definition: SpellPackets.h:577
WorldPacket const * Write() override
Definition: SpellPackets.cpp:607
Definition: SpellPackets.h:568
Definition: Player.h:1131
int32 SpellID
Definition: SpellPackets.h:576
CooldownStorageType::iterator EraseCooldown(CooldownStorageType::iterator itr)
Definition: SpellHistory.h:171
+ Here is the call graph for this function:

◆ ResetCooldowns()

template<typename Predicate >
void SpellHistory::ResetCooldowns ( Predicate  predicate,
bool  update = false 
)
inline
120  {
121  std::vector<int32> resetCooldowns;
122  resetCooldowns.reserve(_spellCooldowns.size());
123  for (auto itr = _spellCooldowns.begin(); itr != _spellCooldowns.end();)
124  {
125  if (predicate(itr))
126  {
127  resetCooldowns.push_back(int32(itr->first));
128  ResetCooldown(itr, false);
129  }
130  else
131  ++itr;
132  }
133 
134  if (update && !resetCooldowns.empty())
135  SendClearCooldowns(resetCooldowns);
136  }
int32_t int32
Definition: Define.h:139
CooldownStorageType _spellCooldowns
Definition: SpellHistory.h:182
void SendClearCooldowns(std::vector< int32 > const &cooldowns) const
Definition: SpellHistory.cpp:947
void ResetCooldown(uint32 spellId, bool update=false)
Definition: SpellHistory.cpp:622
+ Here is the caller graph for this function:

◆ RestoreCharge()

void SpellHistory::RestoreCharge ( uint32  chargeCategoryId)
841 {
842  auto itr = _categoryCharges.find(chargeCategoryId);
843  if (itr != _categoryCharges.end() && !itr->second.empty())
844  {
845  itr->second.pop_back();
846 
847  SendSetSpellCharges(chargeCategoryId, itr->second);
848  }
849 }
ChargeStorageType _categoryCharges
Definition: SpellHistory.h:186
void SendSetSpellCharges(uint32 chargeCategoryId, ChargeEntryCollection const &chargeCollection)
Definition: SpellHistory.cpp:958
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ RestoreCooldownStateAfterDuel()

void SpellHistory::RestoreCooldownStateAfterDuel ( )
1019 {
1020  if (Player* player = _owner->ToPlayer())
1021  {
1022  // add all profession CDs created while in duel (if any)
1023  for (auto const& c : _spellCooldowns)
1024  {
1025  SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(c.first, DIFFICULTY_NONE);
1026 
1027  if (spellInfo->RecoveryTime > 10 * MINUTE * IN_MILLISECONDS ||
1028  spellInfo->CategoryRecoveryTime > 10 * MINUTE * IN_MILLISECONDS)
1029  _spellCooldownsBeforeDuel[c.first] = _spellCooldowns[c.first];
1030  }
1031 
1032  // check for spell with onHold active before and during the duel
1033  for (CooldownStorageType::value_type const& pair : _spellCooldownsBeforeDuel)
1034  {
1035  if (!pair.second.OnHold &&
1036  _spellCooldowns.find(pair.first) != _spellCooldowns.end() &&
1037  !_spellCooldowns[pair.first].OnHold)
1038  _spellCooldowns[pair.first] = _spellCooldownsBeforeDuel[pair.first];
1039  }
1040 
1041  // update the client: restore old cooldowns
1043  spellCooldown.Caster = _owner->GetGUID();
1045 
1046  for (auto const& c : _spellCooldowns)
1047  {
1048  Clock::time_point now = GameTime::GetTime<Clock>();
1049  uint32 cooldownDuration = uint32(c.second.CooldownEnd > now ? std::chrono::duration_cast<Milliseconds>(c.second.CooldownEnd - now).count() : 0);
1050 
1051  // cooldownDuration must be between 0 and 10 minutes in order to avoid any visual bugs
1052  if (cooldownDuration <= 0 || cooldownDuration > 10 * MINUTE * IN_MILLISECONDS || c.second.OnHold)
1053  continue;
1054 
1055  spellCooldown.SpellCooldowns.emplace_back(c.first, cooldownDuration);
1056  }
1057 
1058  player->SendDirectMessage(spellCooldown.Write());
1059  }
1060 }
Definition: DBCEnums.h:666
static Player * ToPlayer(Object *o)
Definition: Object.h:198
std::vector< SpellCooldownStruct > SpellCooldowns
Definition: SpellPackets.h:610
ObjectGuid Caster
Definition: SpellPackets.h:611
Unit * _owner
Definition: SpellHistory.h:181
Definition: SpellInfo.h:342
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:156
Definition: Common.h:62
WorldPacket const * Write() override
Definition: SpellPackets.cpp:636
uint32 RecoveryTime
Definition: SpellInfo.h:384
Definition: Common.h:68
#define sSpellMgr
Definition: SpellMgr.h:825
uint32_t uint32
Definition: Define.h:143
Starts GCD for spells that should start their cooldown on events, requires SPELL_COOLDOWN_FLAG_INCLUD...
Definition: SpellHistory.h:41
CooldownStorageType _spellCooldowns
Definition: SpellHistory.h:182
CooldownStorageType _spellCooldownsBeforeDuel
Definition: SpellHistory.h:183
uint32 CategoryRecoveryTime
Definition: SpellInfo.h:385
Definition: SpellPackets.h:603
uint8 Flags
Definition: SpellPackets.h:612
Definition: Player.h:1131
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ SaveCooldownStateBeforeDuel()

void SpellHistory::SaveCooldownStateBeforeDuel ( )
1014 {
1016 }
CooldownStorageType _spellCooldowns
Definition: SpellHistory.h:182
CooldownStorageType _spellCooldownsBeforeDuel
Definition: SpellHistory.h:183
+ Here is the caller graph for this function:

◆ SaveToDB()

template<class OwnerType >
template void SpellHistory::SaveToDB< Pet > ( CharacterDatabaseTransaction  trans)
182 {
183  using StatementInfo = PersistenceHelper<OwnerType>;
184 
185  uint8 index = 0;
186  CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(StatementInfo::CooldownsDeleteStatement);
187  StatementInfo::SetIdentifier(stmt, index++, _owner);
188  trans->Append(stmt);
189 
190  for (auto const& p : _spellCooldowns)
191  {
192  if (!p.second.OnHold)
193  {
194  index = 0;
195  stmt = CharacterDatabase.GetPreparedStatement(StatementInfo::CooldownsInsertStatement);
196  StatementInfo::SetIdentifier(stmt, index++, _owner);
197  StatementInfo::WriteCooldown(stmt, index, p);
198  trans->Append(stmt);
199  }
200  }
201 
202  stmt = CharacterDatabase.GetPreparedStatement(StatementInfo::ChargesDeleteStatement);
203  StatementInfo::SetIdentifier(stmt, 0, _owner);
204  trans->Append(stmt);
205 
206  for (auto const& p : _categoryCharges)
207  {
208  for (ChargeEntry const& charge : p.second)
209  {
210  index = 0;
211  stmt = CharacterDatabase.GetPreparedStatement(StatementInfo::ChargesInsertStatement);
212  StatementInfo::SetIdentifier(stmt, index++, _owner);
213  StatementInfo::WriteCharge(stmt, index, p.first, charge);
214  trans->Append(stmt);
215  }
216  }
217 }
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
ChargeStorageType _categoryCharges
Definition: SpellHistory.h:186
Unit * _owner
Definition: SpellHistory.h:181
Definition: DatabaseEnvFwd.h:40
CooldownStorageType _spellCooldowns
Definition: SpellHistory.h:182
uint8_t uint8
Definition: Define.h:145
+ Here is the caller graph for this function:

◆ SendClearCooldowns()

void SpellHistory::SendClearCooldowns ( std::vector< int32 > const &  cooldowns) const
private
948 {
949  if (Player const* playerOwner = GetPlayerOwner())
950  {
952  clearCooldowns.IsPet = _owner != playerOwner;
953  clearCooldowns.SpellID = cooldowns;
954  playerOwner->SendDirectMessage(clearCooldowns.Write());
955  }
956 }
Player * GetPlayerOwner() const
Definition: SpellHistory.cpp:942
Unit * _owner
Definition: SpellHistory.h:181
std::vector< int32 > SpellID
Definition: SpellPackets.h:564
bool IsPet
Definition: SpellPackets.h:565
WorldPacket const * Write() override
Definition: SpellPackets.cpp:595
Definition: SpellPackets.h:557
Definition: Player.h:1131
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ SendCooldownEvent()

void SpellHistory::SendCooldownEvent ( SpellInfo const *  spellInfo,
uint32  itemId = 0,
Spell spell = nullptr,
bool  startCooldown = true 
)
529 {
530  // Send activate cooldown timer (possible 0) at client side
531  if (Player* player = GetPlayerOwner())
532  {
533  uint32 category = spellInfo->GetCategory();
534  GetCooldownDurations(spellInfo, itemId, nullptr, &category, nullptr);
535 
536  auto categoryItr = _categoryCooldowns.find(category);
537  if (categoryItr != _categoryCooldowns.end() && categoryItr->second->SpellId != spellInfo->Id)
538  {
539  player->SendDirectMessage(WorldPackets::Spells::CooldownEvent(player != _owner, categoryItr->second->SpellId).Write());
540 
541  if (startCooldown)
542  StartCooldown(sSpellMgr->AssertSpellInfo(categoryItr->second->SpellId, _owner->GetMap()->GetDifficultyID()), itemId, spell);
543  }
544 
545  player->SendDirectMessage(WorldPackets::Spells::CooldownEvent(player != _owner, spellInfo->Id).Write());
546  }
547 
548  // start cooldowns at server side, if any
549  if (startCooldown)
550  StartCooldown(spellInfo, itemId, spell);
551 }
Player * GetPlayerOwner() const
Definition: SpellHistory.cpp:942
Difficulty GetDifficultyID() const
Definition: Map.h:401
Unit * _owner
Definition: SpellHistory.h:181
static void GetCooldownDurations(SpellInfo const *spellInfo, uint32 itemId, Duration *cooldown, uint32 *categoryId, Duration *categoryCooldown)
Definition: SpellHistory.cpp:972
CategoryCooldownStorageType _categoryCooldowns
Definition: SpellHistory.h:184
Map * GetMap() const
Definition: Object.h:555
Definition: SpellPackets.h:545
#define sSpellMgr
Definition: SpellMgr.h:825
uint32_t uint32
Definition: Define.h:143
void StartCooldown(SpellInfo const *spellInfo, uint32 itemId, Spell *spell=nullptr, bool onHold=false, Optional< Duration > forcedCooldown={})
Definition: SpellHistory.cpp:405
Definition: Player.h:1131
WorldPacket const * Write() override
Definition: SpellPackets.cpp:586
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ SendSetSpellCharges()

void SpellHistory::SendSetSpellCharges ( uint32  chargeCategoryId,
ChargeEntryCollection const &  chargeCollection 
)
private
959 {
960  if (Player* player = GetPlayerOwner())
961  {
963  setSpellCharges.Category = chargeCategoryId;
964  if (!chargeCollection.empty())
965  setSpellCharges.NextRecoveryTime = uint32(std::chrono::duration_cast<Milliseconds>(chargeCollection.front().RechargeEnd - Clock::now()).count());
966  setSpellCharges.ConsumedCharges = uint8(chargeCollection.size());
967  setSpellCharges.IsPet = player != _owner;
968  player->SendDirectMessage(setSpellCharges.Write());
969  }
970 }
Player * GetPlayerOwner() const
Definition: SpellHistory.cpp:942
Unit * _owner
Definition: SpellHistory.h:181
Definition: SpellPackets.h:659
WorldPacket const * Write() override
Definition: SpellPackets.cpp:693
bool IsPet
Definition: SpellPackets.h:666
uint32_t uint32
Definition: Define.h:143
uint8 ConsumedCharges
Definition: SpellPackets.h:669
uint32 NextRecoveryTime
Definition: SpellPackets.h:668
uint8_t uint8
Definition: Define.h:145
Definition: Player.h:1131
uint32 Category
Definition: SpellPackets.h:667
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ StartCooldown()

void SpellHistory::StartCooldown ( SpellInfo const *  spellInfo,
uint32  itemId,
Spell spell = nullptr,
bool  onHold = false,
Optional< Duration forcedCooldown = {} 
)
406 {
407  // init cooldown values
408  uint32 categoryId = 0;
409  Duration cooldown = Duration::zero();
410  Duration categoryCooldown = Duration::zero();
411 
412  Clock::time_point curTime = GameTime::GetTime<Clock>();
413  Clock::time_point catrecTime;
414  Clock::time_point recTime;
415  bool needsCooldownPacket = false;
416 
417  if (!forcedCooldown)
418  GetCooldownDurations(spellInfo, itemId, &cooldown, &categoryId, &categoryCooldown);
419  else
420  cooldown = *forcedCooldown;
421 
422  // overwrite time for selected category
423  if (onHold)
424  {
425  // use +MONTH as infinite cooldown marker
426  catrecTime = categoryCooldown > Duration::zero() ? (curTime + InfinityCooldownDelay) : curTime;
427  recTime = cooldown > Duration::zero() ? (curTime + InfinityCooldownDelay) : catrecTime;
428  }
429  else
430  {
431  if (!forcedCooldown)
432  {
433  // Now we have cooldown data (if found any), time to apply mods
434  if (Player* modOwner = _owner->GetSpellModOwner())
435  {
436  auto applySpellMod = [&](Milliseconds& value)
437  {
438  int32 intValue = value.count();
439  modOwner->ApplySpellMod(spellInfo, SpellModOp::Cooldown, intValue, spell);
440  value = Milliseconds(intValue);
441  };
442 
443  if (cooldown >= Duration::zero())
444  applySpellMod(cooldown);
445 
446  if (categoryCooldown >= Clock::duration::zero() && !spellInfo->HasAttribute(SPELL_ATTR6_NO_CATEGORY_COOLDOWN_MODS))
447  applySpellMod(categoryCooldown);
448  }
449 
451  {
452  cooldown = Duration(int64(cooldown.count() * _owner->m_unitData->ModSpellHaste));
453  categoryCooldown = Duration(int64(categoryCooldown.count() * _owner->m_unitData->ModSpellHaste));
454  }
455 
457  {
458  cooldown = Duration(int64(cooldown.count() * _owner->m_unitData->ModHasteRegen));
459  categoryCooldown = Duration(int64(categoryCooldown.count() * _owner->m_unitData->ModHasteRegen));
460  }
461 
463  {
464  // Apply SPELL_AURA_MOD_COOLDOWN only to own spells
465  Player* playerOwner = GetPlayerOwner();
466  if (!playerOwner || playerOwner->HasSpell(spellInfo->Id))
467  {
468  needsCooldownPacket = true;
469  cooldown += Milliseconds(cooldownMod); // SPELL_AURA_MOD_COOLDOWN does not affect category cooldows, verified with shaman shocks
470  }
471  }
472 
473  // Apply SPELL_AURA_MOD_SPELL_CATEGORY_COOLDOWN modifiers
474  // Note: This aura applies its modifiers to all cooldowns of spells with set category, not to category cooldown only
475  if (categoryId)
476  {
478  {
479  if (cooldown > Duration::zero())
480  cooldown += Milliseconds(categoryModifier);
481 
482  if (categoryCooldown > Duration::zero())
483  categoryCooldown += Milliseconds(categoryModifier);
484  }
485 
486  SpellCategoryEntry const* categoryEntry = sSpellCategoryStore.AssertEntry(categoryId);
488  categoryCooldown = std::chrono::duration_cast<Milliseconds>(Clock::from_time_t(sWorld->GetNextDailyQuestsResetTime()) - Clock::now());
489  }
490  }
491  else
492  needsCooldownPacket = true;
493 
494  // replace negative cooldowns by 0
495  if (cooldown < Duration::zero())
496  cooldown = Duration::zero();
497 
498  if (categoryCooldown < Duration::zero())
499  categoryCooldown = Duration::zero();
500 
501  // no cooldown after applying spell mods
502  if (cooldown == Duration::zero() && categoryCooldown == Duration::zero())
503  return;
504 
505  catrecTime = categoryCooldown != Duration::zero() ? curTime + std::chrono::duration_cast<Clock::duration>(Milliseconds(categoryCooldown)) : curTime;
506  recTime = cooldown != Duration::zero() ? curTime + std::chrono::duration_cast<Clock::duration>(Milliseconds(cooldown)) : catrecTime;
507  }
508 
509  // self spell cooldown
510  if (recTime != curTime)
511  {
512  AddCooldown(spellInfo->Id, itemId, recTime, categoryId, catrecTime, onHold);
513 
514  if (needsCooldownPacket)
515  {
516  if (Player* playerOwner = GetPlayerOwner())
517  {
519  spellCooldown.Caster = _owner->GetGUID();
520  spellCooldown.Flags = SPELL_COOLDOWN_FLAG_NONE;
521  spellCooldown.SpellCooldowns.emplace_back(spellInfo->Id, uint32(cooldown.count()));
522  playerOwner->SendDirectMessage(spellCooldown.Write());
523  }
524  }
525  }
526 }
int32 GetTotalAuraModifierByMiscValue(AuraType auraType, int32 misc_value) const
Definition: Unit.cpp:4845
Definition: SpellAuraDefines.h:510
std::vector< SpellCooldownStruct > SpellCooldowns
Definition: SpellPackets.h:610
Player * GetPlayerOwner() const
Definition: SpellHistory.cpp:942
ObjectGuid Caster
Definition: SpellPackets.h:611
Unit * _owner
Definition: SpellHistory.h:181
static void GetCooldownDurations(SpellInfo const *spellInfo, uint32 itemId, Duration *cooldown, uint32 *categoryId, Duration *categoryCooldown)
Definition: SpellHistory.cpp:972
int64_t int64
Definition: Define.h:138
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:156
Definition: SpellAuraDefines.h:441
bool HasSpell(uint32 spell) const override
Definition: Player.cpp:3720
#define sWorld
Definition: World.h:946
void AddCooldown(uint32 spellId, uint32 itemId, Duration cooldownDuration)
Definition: SpellHistory.h:107
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition: Duration.h:24
WorldPacket const * Write() override
Definition: SpellPackets.cpp:636
bool HasAuraTypeWithAffectMask(AuraType auraType, SpellInfo const *affectedSpell) const
Definition: Unit.cpp:4552
void SendDirectMessage(WorldPacket const *data) const
Definition: Player.cpp:6174
Definition: DB2Structure.h:3241
int32 GetTotalAuraModifier(AuraType auraType) const
Definition: Unit.cpp:4785
UF::UpdateField< UF::UnitData, 0, TYPEID_UNIT > m_unitData
Definition: Unit.h:1886
int32_t int32
Definition: Define.h:139
Milliseconds Duration
Definition: SpellHistory.h:50
Definition: SharedDefines.h:660
uint32_t uint32
Definition: Define.h:143
DB2Storage< SpellCategoryEntry > sSpellCategoryStore("SpellCategory.db2", SpellCategoryLoadInfo::Instance())
Definition: SpellHistory.h:39
static Duration const InfinityCooldownDelay
Definition: SpellHistory.h:102
Definition: SpellAuraDefines.h:435
Player * GetSpellModOwner() const
Definition: Object.cpp:2148
Definition: SpellAuraDefines.h:290
int8 Flags
Definition: DB2Structure.h:3245
Definition: SpellPackets.h:603
uint8 Flags
Definition: SpellPackets.h:612
Definition: Player.h:1131
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Update()

void SpellHistory::Update ( )
220 {
221  Clock::time_point now = GameTime::GetTime<Clock>();
222  for (auto itr = _categoryCooldowns.begin(); itr != _categoryCooldowns.end();)
223  {
224  if (itr->second->CategoryEnd < now)
225  itr = _categoryCooldowns.erase(itr);
226  else
227  ++itr;
228  }
229 
230  for (auto itr = _spellCooldowns.begin(); itr != _spellCooldowns.end();)
231  {
232  if (itr->second.CooldownEnd < now)
233  itr = EraseCooldown(itr);
234  else
235  ++itr;
236  }
237 
238  for (auto& p : _categoryCharges)
239  {
240  std::deque<ChargeEntry>& chargeRefreshTimes = p.second;
241  while (!chargeRefreshTimes.empty() && chargeRefreshTimes.front().RechargeEnd <= now)
242  chargeRefreshTimes.pop_front();
243  }
244 }
ChargeStorageType _categoryCharges
Definition: SpellHistory.h:186
CategoryCooldownStorageType _categoryCooldowns
Definition: SpellHistory.h:184
CooldownStorageType _spellCooldowns
Definition: SpellHistory.h:182
CooldownStorageType::iterator EraseCooldown(CooldownStorageType::iterator itr)
Definition: SpellHistory.h:171
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ WritePacket() [1/4]

template<class PacketType >
void SpellHistory::WritePacket ( PacketType *  packet) const
295 {
296  static_assert(!std::is_same<PacketType, PacketType>::value /*static_assert(false)*/, "This packet is not supported.");
297 }
+ Here is the caller graph for this function:

◆ WritePacket() [2/4]

template<>
void SpellHistory::WritePacket ( WorldPackets::Spells::SendSpellHistory sendSpellHistory) const
301 {
302  sendSpellHistory->Entries.reserve(_spellCooldowns.size());
303 
304  Clock::time_point now = GameTime::GetTime<Clock>();
305  for (auto const& p : _spellCooldowns)
306  {
308  historyEntry.SpellID = p.first;
309  historyEntry.ItemID = p.second.ItemId;
310 
311  if (p.second.OnHold)
312  historyEntry.OnHold = true;
313  else
314  {
315  Milliseconds cooldownDuration = std::chrono::duration_cast<Milliseconds>(p.second.CooldownEnd - now);
316  if (cooldownDuration.count() <= 0)
317  continue;
318 
319  Milliseconds categoryDuration = std::chrono::duration_cast<Milliseconds>(p.second.CategoryEnd - now);
320  if (categoryDuration.count() > 0)
321  {
322  historyEntry.Category = p.second.CategoryId;
323  historyEntry.CategoryRecoveryTime = uint32(categoryDuration.count());
324  }
325 
326  if (cooldownDuration.count() > categoryDuration.count())
327  historyEntry.RecoveryTime = uint32(cooldownDuration.count());
328  }
329 
330  sendSpellHistory->Entries.push_back(historyEntry);
331  }
332 }
bool OnHold
Definition: SpellPackets.h:623
uint32 SpellID
Definition: SpellPackets.h:617
int32 CategoryRecoveryTime
Definition: SpellPackets.h:621
uint32 ItemID
Definition: SpellPackets.h:618
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition: Duration.h:24
Definition: SpellPackets.h:615
uint32_t uint32
Definition: Define.h:143
int32 RecoveryTime
Definition: SpellPackets.h:620
CooldownStorageType _spellCooldowns
Definition: SpellHistory.h:182
std::vector< SpellHistoryEntry > Entries
Definition: SpellPackets.h:635
uint32 Category
Definition: SpellPackets.h:619

◆ WritePacket() [3/4]

template<>
void SpellHistory::WritePacket ( WorldPackets::Spells::SendSpellCharges sendSpellCharges) const
336 {
337  sendSpellCharges->Entries.reserve(_categoryCharges.size());
338 
339  Clock::time_point now = GameTime::GetTime<Clock>();
340  for (auto const& p : _categoryCharges)
341  {
342  if (!p.second.empty())
343  {
344  Milliseconds cooldownDuration = std::chrono::duration_cast<Milliseconds>(p.second.front().RechargeEnd - now);
345  if (cooldownDuration.count() <= 0)
346  continue;
347 
349  chargeEntry.Category = p.first;
350  chargeEntry.NextRecoveryTime = uint32(cooldownDuration.count());
351  chargeEntry.ConsumedCharges = uint8(p.second.size());
352  sendSpellCharges->Entries.push_back(chargeEntry);
353  }
354  }
355 }
ChargeStorageType _categoryCharges
Definition: SpellHistory.h:186
uint32 Category
Definition: SpellPackets.h:675
Definition: SpellPackets.h:673
uint8 ConsumedCharges
Definition: SpellPackets.h:678
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition: Duration.h:24
uint32_t uint32
Definition: Define.h:143
std::vector< SpellChargeEntry > Entries
Definition: SpellPackets.h:688
uint32 NextRecoveryTime
Definition: SpellPackets.h:676
uint8_t uint8
Definition: Define.h:145

◆ WritePacket() [4/4]

template<>
void SpellHistory::WritePacket ( WorldPackets::Pet::PetSpells petSpells) const
359 {
360  Clock::time_point now = GameTime::GetTime<Clock>();
361 
362  petSpells->Cooldowns.reserve(_spellCooldowns.size());
363  for (auto const& p : _spellCooldowns)
364  {
365  WorldPackets::Pet::PetSpellCooldown petSpellCooldown;
366  petSpellCooldown.SpellID = p.first;
367  petSpellCooldown.Category = p.second.CategoryId;
368 
369  if (!p.second.OnHold)
370  {
371  Milliseconds cooldownDuration = std::chrono::duration_cast<Milliseconds>(p.second.CooldownEnd - now);
372  if (cooldownDuration.count() <= 0)
373  continue;
374 
375  petSpellCooldown.Duration = uint32(cooldownDuration.count());
376  Milliseconds categoryDuration = std::chrono::duration_cast<Milliseconds>(p.second.CategoryEnd - now);
377  if (categoryDuration.count() > 0)
378  petSpellCooldown.CategoryDuration = uint32(categoryDuration.count());
379  }
380  else
381  petSpellCooldown.CategoryDuration = 0x80000000;
382 
383  petSpells->Cooldowns.push_back(petSpellCooldown);
384  }
385 
386  petSpells->SpellHistory.reserve(_categoryCharges.size());
387  for (auto const& p : _categoryCharges)
388  {
389  if (!p.second.empty())
390  {
391  Milliseconds cooldownDuration = std::chrono::duration_cast<Milliseconds>(p.second.front().RechargeEnd - now);
392  if (cooldownDuration.count() <= 0)
393  continue;
394 
395  WorldPackets::Pet::PetSpellHistory petChargeEntry;
396  petChargeEntry.CategoryID = p.first;
397  petChargeEntry.RecoveryTime = uint32(cooldownDuration.count());
398  petChargeEntry.ConsumedCharges = int8(p.second.size());
399 
400  petSpells->SpellHistory.push_back(petChargeEntry);
401  }
402  }
403 }
Definition: PetPackets.h:92
int32 CategoryID
Definition: PetPackets.h:94
ChargeStorageType _categoryCharges
Definition: SpellHistory.h:186
int8_t int8
Definition: Define.h:141
int32 SpellID
Definition: PetPackets.h:85
int8 ConsumedCharges
Definition: PetPackets.h:97
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition: Duration.h:24
int32 Duration
Definition: PetPackets.h:86
int32 CategoryDuration
Definition: PetPackets.h:87
uint32_t uint32
Definition: Define.h:143
CooldownStorageType _spellCooldowns
Definition: SpellHistory.h:182
uint16 Category
Definition: PetPackets.h:89
int32 RecoveryTime
Definition: PetPackets.h:95
Definition: PetPackets.h:83
std::vector< PetSpellHistory > SpellHistory
Definition: PetPackets.h:119
std::vector< PetSpellCooldown > Cooldowns
Definition: PetPackets.h:118

Member Data Documentation

◆ _categoryCharges

ChargeStorageType SpellHistory::_categoryCharges
private

◆ _categoryCooldowns

CategoryCooldownStorageType SpellHistory::_categoryCooldowns
private

◆ _globalCooldowns

GlobalCooldownStorageType SpellHistory::_globalCooldowns
private

◆ _owner

Unit* SpellHistory::_owner
private

◆ _schoolLockouts

Clock::time_point SpellHistory::_schoolLockouts[MAX_SPELL_SCHOOL]
private

◆ _spellCooldowns

CooldownStorageType SpellHistory::_spellCooldowns
private

◆ _spellCooldownsBeforeDuel

CooldownStorageType SpellHistory::_spellCooldownsBeforeDuel
private

◆ InfinityCooldownDelay

SpellHistory::Duration const SpellHistory::InfinityCooldownDelay = Seconds(MONTH)
static

The documentation for this class was generated from the following files: