TrinityCore
Loading...
Searching...
No Matches
UnitAI.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 TRINITY_UNITAI_H
19#define TRINITY_UNITAI_H
20
21#include "Errors.h"
22#include "EventMap.h"
23#include "ObjectGuid.h"
24#include "SharedDefines.h"
25#include "SpellDefines.h"
26
27#define CAST_AI(a, b) (dynamic_cast<a*>(b))
28#define ENSURE_AI(a,b) (EnsureAI<a>(b))
29
30template<class T, class U>
31T* EnsureAI(U* ai)
32{
33 T* cast_ai = dynamic_cast<T*>(ai);
34 ASSERT(cast_ai);
35 return cast_ai;
36}
37
38class Player;
39class Quest;
40class SpellInfo;
41class Unit;
42struct AISpellInfoType;
45enum SpellEffIndex : uint8;
46
47// Selection method used by SelectTarget
49{
50 Random, // just pick a random target
51 MaxThreat, // prefer targets higher in the threat list
52 MinThreat, // prefer targets lower in the threat list
53 MaxDistance, // prefer targets further from us
54 MinDistance // prefer targets closer to us
55};
56
57// default predicate function to select target based on distance, player and/or aura criteria
59{
60 public:
61 // unit: the reference unit
62 // dist: if 0: ignored, if > 0: maximum distance to the reference unit, if < 0: minimum distance to the reference unit
63 // playerOnly: self explaining
64 // withMainTank: allow current tank to be selected
65 // aura: if 0: ignored, if > 0: the target shall have the aura, if < 0, the target shall NOT have the aura
66 DefaultTargetSelector(Unit const* unit, float dist, bool playerOnly, bool withMainTank, int32 aura);
67 bool operator()(Unit const* target) const;
68
69 private:
70 Unit const* _me;
71 float _dist;
75};
76
77// Target selector for spell casts checking range, auras and attributes
80{
81 public:
82 SpellTargetSelector(Unit* caster, uint32 spellId);
83 bool operator()(Unit const* target) const;
84
85 private:
86 Unit const* _caster;
88};
89
90// Very simple target selector, will just skip main target
91// NOTE: When passing to UnitAI::SelectTarget remember to use 0 as position for random selection
92// because tank will not be in the temporary list
94{
95 public:
96 NonTankTargetSelector(Unit* source, bool playerOnly = true) : _source(source), _playerOnly(playerOnly) { }
97 bool operator()(Unit const* target) const;
98
99 private:
102};
103
104// Simple selector for units using mana
106{
107 public:
108 PowerUsersSelector(Unit const* unit, Powers power, float dist, bool playerOnly) : _me(unit), _power(power), _dist(dist), _playerOnly(playerOnly) { }
109 bool operator()(Unit const* target) const;
110
111 private:
112 Unit const* _me;
114 float const _dist;
115 bool const _playerOnly;
116};
117
119{
120 public:
121 FarthestTargetSelector(Unit const* unit, float dist, bool playerOnly, bool inLos) : _me(unit), _dist(dist), _playerOnly(playerOnly), _inLos(inLos) {}
122 bool operator()(Unit const* target) const;
123
124 private:
125 Unit const* _me;
126 float _dist;
128 bool _inLos;
129};
130
132{
133 protected:
134 Unit* const me;
135 public:
136 explicit UnitAI(Unit* unit) : me(unit) { }
137 virtual ~UnitAI() { }
138
139 virtual bool CanAIAttack(Unit const* /*target*/) const { return true; }
140 virtual void AttackStart(Unit* /*target*/);
141 virtual void UpdateAI(uint32 diff) = 0;
142
143 virtual void InitializeAI();
144
145 virtual void Reset() { }
146
147 // Called when unit's charm state changes with isNew = false
148 // Implementation should call me->ScheduleAIChange() if AI replacement is desired
149 // If this call is made, AI will be replaced on the next tick
150 // When replacement is made, OnCharmed is called with isNew = true
151 virtual void OnCharmed(bool isNew);
152
153 // Pass parameters between AI
154 virtual void DoAction(int32 /*param*/) { }
155 virtual uint32 GetData(uint32 /*id = 0*/) const { return 0; }
156 virtual void SetData(uint32 /*id*/, uint32 /*value*/) { }
157 virtual void SetGUID(ObjectGuid const& /*guid*/, int32 /*id*/ = 0) { }
158 virtual ObjectGuid GetGUID(int32 /*id*/ = 0) const { return ObjectGuid::Empty; }
159
160 // Select the best target (in <targetType> order) from the threat list that fulfill the following:
161 // - Not among the first <offset> entries in <targetType> order (or SelectTargetMethod::MaxThreat order,
162 // if <targetType> is SelectTargetMethod::Random).
163 // - Within at most <dist> yards (if dist > 0.0f)
164 // - At least -<dist> yards away (if dist < 0.0f)
165 // - Is a player (if playerOnly = true)
166 // - Not the current tank (if withTank = false)
167 // - Has aura with ID <aura> (if aura > 0)
168 // - Does not have aura with ID -<aura> (if aura < 0)
169 Unit* SelectTarget(SelectTargetMethod targetType, uint32 offset = 0, float dist = 0.0f, bool playerOnly = false, bool withTank = true, int32 aura = 0);
170
171 // Select the best target (in <targetType> order) satisfying <predicate> from the threat list.
172 // If <offset> is nonzero, the first <offset> entries in <targetType> order (or SelectTargetMethod::MaxThreat
173 // order, if <targetType> is SelectTargetMethod::Random) are skipped.
174 template<class PREDICATE>
175 Unit* SelectTarget(SelectTargetMethod targetType, uint32 offset, PREDICATE const& predicate)
176 {
177 std::list<Unit*> targetList;
178 SelectTargetList(targetList, std::numeric_limits<uint32>::max(), targetType, offset, predicate);
179
180 return FinalizeTargetSelection(targetList, targetType);
181 }
182
183 // Select the best (up to) <num> targets (in <targetType> order) from the threat list that fulfill the following:
184 // - Not among the first <offset> entries in <targetType> order (or SelectTargetMethod::MaxThreat order,
185 // if <targetType> is SelectTargetMethod::Random).
186 // - Within at most <dist> yards (if dist > 0.0f)
187 // - At least -<dist> yards away (if dist < 0.0f)
188 // - Is a player (if playerOnly = true)
189 // - Not the current tank (if withTank = false)
190 // - Has aura with ID <aura> (if aura > 0)
191 // - Does not have aura with ID -<aura> (if aura < 0)
192 // The resulting targets are stored in <targetList> (which is cleared first).
193 void SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectTargetMethod targetType, uint32 offset = 0, float dist = 0.0f, bool playerOnly = false, bool withTank = true, int32 aura = 0);
194
195 // Select the best (up to) <num> targets (in <targetType> order) satisfying <predicate> from the threat list and stores them in <targetList> (which is cleared first).
196 // If <offset> is nonzero, the first <offset> entries in <targetType> order (or SelectTargetMethod::MaxThreat
197 // order, if <targetType> is SelectTargetMethod::Random) are skipped.
198 template <class PREDICATE>
199 void SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectTargetMethod targetType, uint32 offset, PREDICATE const& predicate)
200 {
201 if (!PrepareTargetListSelection(targetList, targetType, offset))
202 return;
203
204 // then finally filter by predicate
205 targetList.remove_if([&predicate](Unit* target) { return !predicate(target); });
206
207 FinalizeTargetListSelection(targetList, num, targetType);
208 }
209
210 // Called when the unit enters combat
211 // (NOTE: Creature engage logic should NOT be here, but in JustEngagedWith, which happens once threat is established!)
212 virtual void JustEnteredCombat(Unit* /*who*/) { }
213
214 // Called when the unit leaves combat
215 virtual void JustExitedCombat() { }
216
217 // Called when the unit is about to be removed from the world (despawn, grid unload, corpse disappearing, player logging out etc.)
218 virtual void OnDespawn() { }
219
220 // Called at any Damage to any victim (before damage apply)
221 virtual void DamageDealt(Unit* /*victim*/, uint32& /*damage*/, DamageEffectType /*damageType*/) { }
222
223 // Called at any Damage from any attacker (before damage apply)
224 // Note: it for recalculation damage or special reaction at damage
225 virtual void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) { }
226
227 // Called when the creature receives heal
228 virtual void HealReceived(Unit* /*done_by*/, uint32& /*addhealth*/) { }
229
230 // Called when the unit heals
231 virtual void HealDone(Unit* /*done_to*/, uint32& /*addhealth*/) { }
232
235 virtual void SpellInterrupted(uint32 /*spellId*/, uint32 /*unTimeMs*/) { }
236
237 void AttackStartCaster(Unit* victim, float dist);
238
239 SpellCastResult DoCast(uint32 spellId);
240 SpellCastResult DoCast(Unit* victim, uint32 spellId, CastSpellExtraArgs const& args = {});
241 SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const& args = {}) { return DoCast(me, spellId, args); }
242 SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const& args = {});
243 SpellCastResult DoCastAOE(uint32 spellId, CastSpellExtraArgs const& args = {}) { return DoCast(nullptr, spellId, args); }
244
245 float DoGetSpellMaxRange(uint32 spellId, bool positive = false);
246
247 virtual bool ShouldSparWith(Unit const* /*target*/) const { return false; }
248
249 void DoMeleeAttackIfReady();
250 bool DoSpellAttackIfReady(uint32 spell);
251
253 static void FillAISpellInfo();
254
255 // Called when a game event starts or ends
256 virtual void OnGameEvent(bool /*start*/, uint16 /*eventId*/) { }
257
258 virtual std::string GetDebugInfo() const;
259
260 private:
261 UnitAI(UnitAI const& right) = delete;
262 UnitAI& operator=(UnitAI const& right) = delete;
263
264 Unit* FinalizeTargetSelection(std::list<Unit*>& targetList, SelectTargetMethod targetType);
265 bool PrepareTargetListSelection(std::list<Unit*>& targetList, SelectTargetMethod targetType, uint32 offset);
266 void FinalizeTargetListSelection(std::list<Unit*>& targetList, uint32 num, SelectTargetMethod targetType);
267};
268
269#endif
#define TC_GAME_API
Definition Define.h:114
uint8_t uint8
Definition Define.h:135
int32_t int32
Definition Define.h:129
uint16_t uint16
Definition Define.h:134
uint32_t uint32
Definition Define.h:133
std::string GetDebugInfo()
Definition Errors.cpp:155
#define ASSERT
Definition Errors.h:68
MovementGeneratorType
SpellEffIndex
Powers
SpellCastResult
T * EnsureAI(U *ai)
Definition UnitAI.h:31
SelectTargetMethod
Definition UnitAI.h:49
DamageEffectType
Definition Unit.h:352
static ObjectGuid const Empty
Definition ObjectGuid.h:140
virtual void HealReceived(Unit *, uint32 &)
Definition UnitAI.h:228
virtual void SetData(uint32, uint32)
Definition UnitAI.h:156
virtual void DoAction(int32)
Definition UnitAI.h:154
virtual void JustEnteredCombat(Unit *)
Definition UnitAI.h:212
virtual void SpellInterrupted(uint32, uint32)
Definition UnitAI.h:235
virtual ~UnitAI()
Definition UnitAI.h:137
virtual void Reset()
Definition UnitAI.h:145
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:241
UnitAI(Unit *unit)
Definition UnitAI.h:136
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset, PREDICATE const &predicate)
Definition UnitAI.h:175
virtual bool CanAIAttack(Unit const *) const
Definition UnitAI.h:139
virtual uint32 GetData(uint32) const
Definition UnitAI.h:155
void SelectTargetList(std::list< Unit * > &targetList, uint32 num, SelectTargetMethod targetType, uint32 offset, PREDICATE const &predicate)
Definition UnitAI.h:199
UnitAI & operator=(UnitAI const &right)=delete
virtual ObjectGuid GetGUID(int32=0) const
Definition UnitAI.h:158
virtual void DamageTaken(Unit *, uint32 &, DamageEffectType, SpellInfo const *)
Definition UnitAI.h:225
virtual void OnGameEvent(bool, uint16)
Definition UnitAI.h:256
virtual void OnDespawn()
Definition UnitAI.h:218
virtual void JustExitedCombat()
Definition UnitAI.h:215
Unit *const me
Definition UnitAI.h:134
virtual void HealDone(Unit *, uint32 &)
Definition UnitAI.h:231
virtual void DamageDealt(Unit *, uint32 &, DamageEffectType)
Definition UnitAI.h:221
virtual void UpdateAI(uint32 diff)=0
UnitAI(UnitAI const &right)=delete
static AISpellInfoType * AISpellInfo
Definition UnitAI.h:252
virtual void SetGUID(ObjectGuid const &, int32=0)
Definition UnitAI.h:157
SpellCastResult DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:243
virtual bool ShouldSparWith(Unit const *) const
Definition UnitAI.h:247
Definition Unit.h:769
Unit const * _me
Definition UnitAI.h:70
Unit const * _exception
Definition UnitAI.h:73
FarthestTargetSelector(Unit const *unit, float dist, bool playerOnly, bool inLos)
Definition UnitAI.h:121
Unit const * _me
Definition UnitAI.h:125
NonTankTargetSelector(Unit *source, bool playerOnly=true)
Definition UnitAI.h:96
float const _dist
Definition UnitAI.h:114
Unit const * _me
Definition UnitAI.h:112
Powers const _power
Definition UnitAI.h:113
PowerUsersSelector(Unit const *unit, Powers power, float dist, bool playerOnly)
Definition UnitAI.h:108
bool const _playerOnly
Definition UnitAI.h:115
SpellInfo const * _spellInfo
Definition UnitAI.h:87
Unit const * _caster
Definition UnitAI.h:86