TrinityCore
Loading...
Searching...
No Matches
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
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, uint32 itemId, Spell* spell = nullptr);
109 bool IsReady(SpellInfo const* spellInfo, uint32 itemId = 0) const;
110 void WritePacket(WorldPackets::Spells::SendSpellHistory* sendSpellHistory) const;
111 void WritePacket(WorldPackets::Spells::SendSpellCharges* sendSpellCharges) const;
112 void WritePacket(WorldPackets::Pet::PetSpells* petSpells) const;
113
114 // Cooldowns
115 void StartCooldown(SpellInfo const* spellInfo, uint32 itemId, Spell* spell = nullptr, bool onHold = false, Optional<Duration> forcedCooldown = {});
116 void SendCooldownEvent(SpellInfo const* spellInfo, uint32 itemId = 0, Spell* spell = nullptr, bool startCooldown = true);
117
118 void AddCooldown(uint32 spellId, uint32 itemId, Duration cooldownDuration)
119 {
120 TimePoint now = time_point_cast<Duration>(GameTime::GetTime<Clock>());
121 AddCooldown(spellId, itemId, now + cooldownDuration, 0, now);
122 }
123
124 void AddCooldown(uint32 spellId, uint32 itemId, TimePoint cooldownEnd, uint32 categoryId, TimePoint categoryEnd, bool onHold = false);
125 void ModifyCooldown(uint32 spellId, Duration cooldownMod, bool withoutCategoryCooldown = false);
126 void ModifyCooldown(SpellInfo const* spellInfo, Duration cooldownMod, bool withoutCategoryCooldown = false);
127 template <Trinity::invocable_r<bool, CooldownEntry const&> Predicate>
128 void ModifyCoooldowns(Predicate&& predicate, Duration cooldownMod, bool withoutCategoryCooldown = false)
129 {
130 for (auto itr = _spellCooldowns.begin(); itr != _spellCooldowns.end();)
131 {
132 if (!itr->second.OnHold && std::forward<Predicate>(predicate)(itr->second))
133 ModifySpellCooldown(itr, cooldownMod, withoutCategoryCooldown);
134 else
135 ++itr;
136 }
137 }
138
139 template <Trinity::invocable_r<bool, CooldownEntry const&> Predicate>
140 void UpdateCooldownRecoveryRate(Predicate&& predicate, float modChange, bool apply)
141 {
142 for (auto itr = _spellCooldowns.begin(); itr != _spellCooldowns.end(); ++itr)
143 {
144 if (!itr->second.OnHold && std::forward<Predicate>(predicate)(itr->second))
145 UpdateCooldownRecoveryRate(itr, modChange, apply);
146 }
147 }
148
149 void ResetCooldown(uint32 spellId, bool update = false);
150 template <Trinity::invocable_r<bool, CooldownEntry const&> Predicate>
151 void ResetCooldowns(Predicate&& predicate, bool update = false)
152 {
153 std::vector<int32> resetCooldowns;
154 resetCooldowns.reserve(_spellCooldowns.size());
155 for (auto itr = _spellCooldowns.begin(); itr != _spellCooldowns.end();)
156 {
157 if (!itr->second.OnHold && std::forward<Predicate>(predicate)(itr->second))
158 {
159 resetCooldowns.push_back(int32(itr->first));
160 ResetCooldown(itr, false);
161 }
162 else
163 ++itr;
164 }
165
166 if (update && !resetCooldowns.empty())
167 SendClearCooldowns(std::move(resetCooldowns));
168 }
169
170 void ResetAllCooldowns();
171 bool HasCooldown(SpellInfo const* spellInfo, uint32 itemId = 0) const;
172 bool HasCooldown(uint32 spellId, uint32 itemId = 0) const;
173 bool HasCooldownOnHold(uint32 spellId) const;
174 Duration GetRemainingCooldown(SpellInfo const* spellInfo) const;
175 Duration GetRemainingCategoryCooldown(uint32 categoryId) const;
176 Duration GetRemainingCategoryCooldown(SpellInfo const* spellInfo) const;
177
178 // School lockouts
179 void LockSpellSchool(SpellSchoolMask schoolMask, Duration lockoutTime);
180 bool IsSchoolLocked(SpellSchoolMask schoolMask) const;
181
182 // Charges
183 void ConsumeCharge(uint32 chargeCategoryId);
184 void ModifyChargeRecoveryTime(uint32 chargeCategoryId, Duration cooldownMod);
185 void UpdateChargeRecoveryRate(uint32 chargeCategoryId, float modChange, bool apply);
186 void RestoreCharge(uint32 chargeCategoryId);
187 void ResetCharges(uint32 chargeCategoryId);
188 void ResetAllCharges();
189 bool HasCharge(uint32 chargeCategoryId) const;
190 int32 GetMaxCharges(uint32 chargeCategoryId) const;
191 int32 GetChargeRecoveryTime(uint32 chargeCategoryId) const;
192
193 // Global cooldown
194 bool HasGlobalCooldown(SpellInfo const* spellInfo) const;
195 void AddGlobalCooldown(SpellInfo const* spellInfo, Duration duration);
196 void CancelGlobalCooldown(SpellInfo const* spellInfo);
197 Duration GetRemainingGlobalCooldown(SpellInfo const* spellInfo) const;
198
199 bool IsPaused() const { return _pauseTime.has_value(); }
200 void PauseCooldowns();
201 void ResumeCooldowns();
202
203 static void GetCooldownDurations(SpellInfo const* spellInfo, uint32 itemId, Duration* cooldown, uint32* categoryId, Duration* categoryCooldown);
204
205 void AtExitCombat();
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>&& cooldowns) const;
217 CooldownStorageType::iterator EraseCooldown(CooldownStorageType::iterator itr);
218
219 void SendSetSpellCharges(uint32 chargeCategoryId, ChargeEntryCollection const& chargeCollection) const;
220
225 TimePoint _schoolLockouts[MAX_SPELL_SCHOOL];
229
230 template<class T>
232};
233
234#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:150
uint32_t uint32
Definition Define.h:154
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)
SpellSchoolMask
@ MAX_SPELL_SCHOOL
SpellCooldownFlags
Spell cooldown flags sent in SMSG_SPELL_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_INCLUDE_GCD
Starts GCD in addition to normal cooldown specified in the packet.
@ SPELL_COOLDOWN_FLAG_LOSS_OF_CONTROL_UI
Shows interrupt cooldown in loss of control ui.
@ SPELL_COOLDOWN_FLAG_NONE
@ SPELL_COOLDOWN_FLAG_ON_HOLD
Forces cooldown to behave as if SpellInfo::IsCooldownStartedOnEvent was true.
PetSpells
Definition Item.h:185
void AddCooldown(uint32 spellId, uint32 itemId, Duration cooldownDuration)
void UpdateCooldownRecoveryRate(Predicate &&predicate, float modChange, bool apply)
SpellHistory & operator=(SpellHistory const &)=delete
GlobalCooldownStorageType _globalCooldowns
std::unordered_map< uint32, CooldownEntry * > CategoryCooldownStorageType
std::chrono::system_clock Clock
std::unordered_map< uint32, TimePoint > GlobalCooldownStorageType
Optional< TimePoint > _pauseTime
std::deque< ChargeEntry > ChargeEntryCollection
SpellHistory(SpellHistory const &)=delete
CooldownStorageType _spellCooldowns
void ModifyCoooldowns(Predicate &&predicate, Duration cooldownMod, bool withoutCategoryCooldown=false)
std::unordered_map< uint32, CooldownEntry > CooldownStorageType
bool IsPaused() const
CooldownStorageType _spellCooldownsBeforeDuel
Milliseconds Duration
std::chrono::time_point< Clock, Duration > TimePoint
std::unordered_map< uint32, ChargeEntryCollection > ChargeStorageType
void ResetCooldowns(Predicate &&predicate, bool update=false)
SpellHistory(SpellHistory &&)=delete
SpellHistory & operator=(SpellHistory &&)=delete
ChargeStorageType _categoryCharges
CategoryCooldownStorageType _categoryCooldowns
Definition Spell.h:277
Definition Unit.h:647
ChargeEntry(TimePoint startTime, Duration rechargeTime)
ChargeEntry(TimePoint startTime, TimePoint endTime)