TrinityCore
SpellHistory.h
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef TRINITYCORE_SPELL_HISTORY_H
19#define TRINITYCORE_SPELL_HISTORY_H
20
21#include "Concepts.h"
22#include "DatabaseEnvFwd.h"
23#include "Duration.h"
24#include "GameTime.h"
25#include "Optional.h"
26#include "SharedDefines.h"
27#include <deque>
28#include <unordered_map>
29#include <vector>
30
31class Item;
32class Player;
33class Spell;
34class SpellInfo;
35class Unit;
36
37namespace WorldPackets::Pet
38{
39class PetSpells;
40}
41
43{
44class SendSpellHistory;
45class SendSpellCharges;
46}
47
50{
56};
57
59{
60public:
61 using Clock = std::chrono::system_clock;
62 using Duration = Milliseconds; // Cooldowns are stored only with millisecond precision, not whatever Clock's precision is
63 using TimePoint = std::chrono::time_point<Clock, Duration>;
64
66 {
67 uint32 SpellId = 0;
68 TimePoint CooldownEnd = TimePoint::min();
70 uint32 CategoryId = 0;
71 TimePoint CategoryEnd = TimePoint::min();
72 bool OnHold = false;
73 };
74
76 {
77 ChargeEntry() = default;
78 ChargeEntry(TimePoint startTime, Duration rechargeTime) : RechargeStart(startTime), RechargeEnd(startTime + rechargeTime) { }
79 ChargeEntry(TimePoint startTime, TimePoint endTime) : RechargeStart(startTime), RechargeEnd(endTime) { }
80
83 };
84
85 using ChargeEntryCollection = std::deque<ChargeEntry>;
86 using CooldownStorageType = std::unordered_map<uint32 /*spellId*/, CooldownEntry>;
87 using CategoryCooldownStorageType = std::unordered_map<uint32 /*categoryId*/, CooldownEntry*>;
88 using ChargeStorageType = std::unordered_map<uint32 /*categoryId*/, ChargeEntryCollection>;
89 using GlobalCooldownStorageType = std::unordered_map<uint32 /*categoryId*/, TimePoint>;
90
91 explicit SpellHistory(Unit* owner);
93
94 SpellHistory(SpellHistory const&) = delete;
96
99
100 template<class OwnerType>
101 void LoadFromDB(PreparedQueryResult cooldownsResult, PreparedQueryResult chargesResult);
102
103 template<class OwnerType>
105
106 void Update();
107
108 void HandleCooldowns(SpellInfo const* spellInfo, Item const* item, Spell* spell = nullptr);
109 void HandleCooldowns(SpellInfo const* spellInfo, uint32 itemId, Spell* spell = nullptr);
110 bool IsReady(SpellInfo const* spellInfo, uint32 itemId = 0) const;
111 void WritePacket(WorldPackets::Spells::SendSpellHistory* sendSpellHistory) const;
112 void WritePacket(WorldPackets::Spells::SendSpellCharges* sendSpellCharges) const;
113 void WritePacket(WorldPackets::Pet::PetSpells* petSpells) const;
114
115 // Cooldowns
116 static Duration const InfinityCooldownDelay; // used for set "infinity cooldowns" for spells and check
117
118 void StartCooldown(SpellInfo const* spellInfo, uint32 itemId, Spell* spell = nullptr, bool onHold = false, Optional<Duration> forcedCooldown = {});
119 void SendCooldownEvent(SpellInfo const* spellInfo, uint32 itemId = 0, Spell* spell = nullptr, bool startCooldown = true);
120
121 void AddCooldown(uint32 spellId, uint32 itemId, Duration cooldownDuration)
122 {
123 TimePoint now = time_point_cast<Duration>(GameTime::GetTime<Clock>());
124 AddCooldown(spellId, itemId, now + cooldownDuration, 0, now);
125 }
126
127 void AddCooldown(uint32 spellId, uint32 itemId, TimePoint cooldownEnd, uint32 categoryId, TimePoint categoryEnd, bool onHold = false);
128 void ModifyCooldown(uint32 spellId, Duration cooldownMod, bool withoutCategoryCooldown = false);
129 void ModifyCooldown(SpellInfo const* spellInfo, Duration cooldownMod, bool withoutCategoryCooldown = false);
130 template <Trinity::invocable_r<bool, CooldownEntry const&> Predicate>
131 void ModifyCoooldowns(Predicate&& predicate, Duration cooldownMod, bool withoutCategoryCooldown = false)
132 {
133 for (auto itr = _spellCooldowns.begin(); itr != _spellCooldowns.end();)
134 {
135 if (std::forward<Predicate>(predicate)(itr->second))
136 ModifySpellCooldown(itr, cooldownMod, withoutCategoryCooldown);
137 else
138 ++itr;
139 }
140 }
141
142 template <Trinity::invocable_r<bool, CooldownEntry const&> Predicate>
143 void UpdateCooldownRecoveryRate(Predicate&& predicate, float modChange, bool apply)
144 {
145 for (auto itr = _spellCooldowns.begin(); itr != _spellCooldowns.end(); ++itr)
146 {
147 if (std::forward<Predicate>(predicate)(itr->second))
148 UpdateCooldownRecoveryRate(itr, modChange, apply);
149 }
150 }
151
152 void ResetCooldown(uint32 spellId, bool update = false);
153 template <Trinity::invocable_r<bool, CooldownEntry const&> Predicate>
154 void ResetCooldowns(Predicate&& predicate, bool update = false)
155 {
156 std::vector<int32> resetCooldowns;
157 resetCooldowns.reserve(_spellCooldowns.size());
158 for (auto itr = _spellCooldowns.begin(); itr != _spellCooldowns.end();)
159 {
160 if (std::forward<Predicate>(predicate)(itr->second))
161 {
162 resetCooldowns.push_back(int32(itr->first));
163 ResetCooldown(itr, false);
164 }
165 else
166 ++itr;
167 }
168
169 if (update && !resetCooldowns.empty())
170 SendClearCooldowns(resetCooldowns);
171 }
172
173 void ResetAllCooldowns();
174 bool HasCooldown(SpellInfo const* spellInfo, uint32 itemId = 0) const;
175 bool HasCooldown(uint32 spellId, uint32 itemId = 0) const;
176 Duration GetRemainingCooldown(SpellInfo const* spellInfo) const;
177 Duration GetRemainingCategoryCooldown(uint32 categoryId) const;
178 Duration GetRemainingCategoryCooldown(SpellInfo const* spellInfo) const;
179
180 // School lockouts
181 void LockSpellSchool(SpellSchoolMask schoolMask, Duration lockoutTime);
182 bool IsSchoolLocked(SpellSchoolMask schoolMask) const;
183
184 // Charges
185 bool ConsumeCharge(uint32 chargeCategoryId);
186 void ModifyChargeRecoveryTime(uint32 chargeCategoryId, Duration cooldownMod);
187 void UpdateChargeRecoveryRate(uint32 chargeCategoryId, float modChange, bool apply);
188 void RestoreCharge(uint32 chargeCategoryId);
189 void ResetCharges(uint32 chargeCategoryId);
190 void ResetAllCharges();
191 bool HasCharge(uint32 chargeCategoryId) const;
192 int32 GetMaxCharges(uint32 chargeCategoryId) const;
193 int32 GetChargeRecoveryTime(uint32 chargeCategoryId) const;
194
195 // Global cooldown
196 bool HasGlobalCooldown(SpellInfo const* spellInfo) const;
197 void AddGlobalCooldown(SpellInfo const* spellInfo, Duration duration);
198 void CancelGlobalCooldown(SpellInfo const* spellInfo);
199 Duration GetRemainingGlobalCooldown(SpellInfo const* spellInfo) const;
200
201 bool IsPaused() const { return _pauseTime.has_value(); }
202 void PauseCooldowns();
203 void ResumeCooldowns();
204
205 static void GetCooldownDurations(SpellInfo const* spellInfo, uint32 itemId, Duration* cooldown, uint32* categoryId, Duration* categoryCooldown);
206
207 void SaveCooldownStateBeforeDuel();
208 void RestoreCooldownStateAfterDuel();
209
210private:
211 Player* GetPlayerOwner() const;
212 void ModifySpellCooldown(uint32 spellId, Duration cooldownMod, bool withoutCategoryCooldown);
213 void ModifySpellCooldown(CooldownStorageType::iterator& itr, Duration cooldownMod, bool withoutCategoryCooldown);
214 void UpdateCooldownRecoveryRate(CooldownStorageType::iterator& itr, float modChange, bool apply);
215 void ResetCooldown(CooldownStorageType::iterator& itr, bool update = false);
216 void SendClearCooldowns(std::vector<int32> const& cooldowns) const;
217 CooldownStorageType::iterator EraseCooldown(CooldownStorageType::iterator itr)
218 {
219 _categoryCooldowns.erase(itr->second.CategoryId);
220 return _spellCooldowns.erase(itr);
221 }
222
223 void SendSetSpellCharges(uint32 chargeCategoryId, ChargeEntryCollection const& chargeCollection) const;
224
229 TimePoint _schoolLockouts[MAX_SPELL_SCHOOL];
233
234 template<class T>
236};
237
238#endif // TRINITYCORE_SPELL_HISTORY_H
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
std::shared_ptr< PreparedResultSet > PreparedQueryResult
#define TC_GAME_API
Definition: Define.h:129
int32_t int32
Definition: Define.h:144
uint32_t uint32
Definition: Define.h:148
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition: Duration.h:24
std::chrono::steady_clock::time_point TimePoint
time_point shorthand typedefs
Definition: Duration.h:40
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
static void SaveToDB(QuestPool const &pool, CharacterDatabaseTransaction trans)
Definition: QuestPools.cpp:50
SpellSchoolMask
@ MAX_SPELL_SCHOOL
SpellCooldownFlags
Spell cooldown flags sent in SMSG_SPELL_COOLDOWN.
Definition: SpellHistory.h:50
@ SPELL_COOLDOWN_FLAG_INCLUDE_EVENT_COOLDOWNS
Starts GCD for spells that should start their cooldown on events, requires SPELL_COOLDOWN_FLAG_INCLUD...
Definition: SpellHistory.h:53
@ SPELL_COOLDOWN_FLAG_INCLUDE_GCD
Starts GCD in addition to normal cooldown specified in the packet.
Definition: SpellHistory.h:52
@ SPELL_COOLDOWN_FLAG_LOSS_OF_CONTROL_UI
Shows interrupt cooldown in loss of control ui.
Definition: SpellHistory.h:54
@ SPELL_COOLDOWN_FLAG_NONE
Definition: SpellHistory.h:51
@ SPELL_COOLDOWN_FLAG_ON_HOLD
Forces cooldown to behave as if SpellInfo::IsCooldownStartedOnEvent was true.
Definition: SpellHistory.h:55
PetSpells
Definition: Item.h:170
void AddCooldown(uint32 spellId, uint32 itemId, Duration cooldownDuration)
Definition: SpellHistory.h:121
void UpdateCooldownRecoveryRate(Predicate &&predicate, float modChange, bool apply)
Definition: SpellHistory.h:143
SpellHistory & operator=(SpellHistory const &)=delete
GlobalCooldownStorageType _globalCooldowns
Definition: SpellHistory.h:231
std::unordered_map< uint32, CooldownEntry * > CategoryCooldownStorageType
Definition: SpellHistory.h:87
std::chrono::system_clock Clock
Definition: SpellHistory.h:61
std::unordered_map< uint32, TimePoint > GlobalCooldownStorageType
Definition: SpellHistory.h:89
static Duration const InfinityCooldownDelay
Definition: SpellHistory.h:116
Optional< TimePoint > _pauseTime
Definition: SpellHistory.h:232
std::deque< ChargeEntry > ChargeEntryCollection
Definition: SpellHistory.h:85
SpellHistory(SpellHistory const &)=delete
CooldownStorageType _spellCooldowns
Definition: SpellHistory.h:226
void ModifyCoooldowns(Predicate &&predicate, Duration cooldownMod, bool withoutCategoryCooldown=false)
Definition: SpellHistory.h:131
std::unordered_map< uint32, CooldownEntry > CooldownStorageType
Definition: SpellHistory.h:86
bool IsPaused() const
Definition: SpellHistory.h:201
CooldownStorageType _spellCooldownsBeforeDuel
Definition: SpellHistory.h:227
Milliseconds Duration
Definition: SpellHistory.h:62
std::chrono::time_point< Clock, Duration > TimePoint
Definition: SpellHistory.h:63
CooldownStorageType::iterator EraseCooldown(CooldownStorageType::iterator itr)
Definition: SpellHistory.h:217
std::unordered_map< uint32, ChargeEntryCollection > ChargeStorageType
Definition: SpellHistory.h:88
void ResetCooldowns(Predicate &&predicate, bool update=false)
Definition: SpellHistory.h:154
SpellHistory(SpellHistory &&)=delete
SpellHistory & operator=(SpellHistory &&)=delete
ChargeStorageType _categoryCharges
Definition: SpellHistory.h:230
CategoryCooldownStorageType _categoryCooldowns
Definition: SpellHistory.h:228
Definition: Spell.h:262
Definition: Unit.h:631
void apply(T *val)
Definition: ByteConverter.h:41
void Update(VignetteData &vignette, WorldObject const *owner)
Definition: Vignette.cpp:101
ChargeEntry(TimePoint startTime, Duration rechargeTime)
Definition: SpellHistory.h:78
ChargeEntry(TimePoint startTime, TimePoint endTime)
Definition: SpellHistory.h:79