Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
UnitAI.h
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#ifndef SKYFIRE_UNITAI_H
7#define SKYFIRE_UNITAI_H
8
9#include "Containers.h"
10#include "Define.h"
11#include "UnaryFunction.h"
12#include "Unit.h"
13#include <list>
14
15class Player;
16class Quest;
17class Unit;
18struct AISpellInfoType;
19
20//Selection method used by SelectTarget
22{
23 SELECT_TARGET_RANDOM = 0, //Just selects a random target
24 SELECT_TARGET_TOPAGGRO, //Selects targes from top aggro to bottom
25 SELECT_TARGET_BOTTOMAGGRO, //Selects targets from bottom aggro to top
28};
29
30// default predicate function to select target based on distance, player and/or aura criteria
31struct DefaultTargetSelector : public SF_UNARY_FUNCTION<Unit*, bool>
32{
33 const Unit* me;
34 float m_dist;
37
38 // unit: the reference unit
39 // dist: if 0: ignored, if > 0: maximum distance to the reference unit, if < 0: minimum distance to the reference unit
40 // playerOnly: self explaining
41 // aura: if 0: ignored, if > 0: the target shall have the aura, if < 0, the target shall NOT have the aura
42 DefaultTargetSelector(Unit const* unit, float dist, bool playerOnly, int32 aura) : me(unit), m_dist(dist), m_playerOnly(playerOnly), m_aura(aura) { }
43
44 bool operator()(Unit const* target) const
45 {
46 if (!me)
47 return false;
48
49 if (!target)
50 return false;
51
52 if (m_playerOnly && (target->GetTypeId() != TypeID::TYPEID_PLAYER))
53 return false;
54
55 if (m_dist > 0.0f && !me->IsWithinCombatRange(target, m_dist))
56 return false;
57
58 if (m_dist < 0.0f && me->IsWithinCombatRange(target, -m_dist))
59 return false;
60
61 if (m_aura)
62 {
63 if (m_aura > 0)
64 {
65 if (!target->HasAura(m_aura))
66 return false;
67 }
68 else
69 {
70 if (target->HasAura(-m_aura))
71 return false;
72 }
73 }
74
75 return true;
76 }
77};
78
79// Target selector for spell casts checking range, auras and attributes
81struct SpellTargetSelector : public SF_UNARY_FUNCTION<Unit*, bool>
82{
83public:
84 SpellTargetSelector(Unit* caster, uint32 spellId);
85 bool operator()(Unit const* target) const;
86
87private:
88 Unit const* _caster;
90};
91
92// Very simple target selector, will just skip main target
93// NOTE: When passing to UnitAI::SelectTarget remember to use 0 as position for random selection
94// because tank will not be in the temporary list
95struct NonTankTargetSelector : public SF_UNARY_FUNCTION<Unit*, bool>
96{
97public:
98 NonTankTargetSelector(Creature* source, bool playerOnly = true) : _source(source), _playerOnly(playerOnly) { }
99 bool operator()(Unit const* target) const;
100
101private:
104};
105
107{
108protected:
109 Unit* const me;
110public:
111 explicit UnitAI(Unit* unit) : me(unit) { }
112 virtual ~UnitAI() { }
113
114 virtual bool CanAIAttack(Unit const* /*target*/) const { return true; }
115 virtual void AttackStart(Unit* /*target*/);
116 virtual void UpdateAI(uint32 diff) = 0;
117
118 virtual void InitializeAI() { if (!me->isDead()) Reset(); }
119
120 virtual void Reset() { };
121
122 // Called when unit is charmed
123 virtual void OnCharmed(bool apply) = 0;
124
125 // Pass parameters between AI
126 virtual void DoAction(int32 /*param*/) { }
127 virtual uint32 GetData(uint32 /*id = 0*/) const { return 0; }
128 virtual void SetData(uint32 /*id*/, uint32 /*value*/) { }
129 virtual void SetGUID(uint64 /*guid*/, int32 /*id*/ = 0) { }
130 virtual uint64 GetGUID(int32 /*id*/ = 0) const { return 0; }
131
132 Unit* SelectTarget(SelectAggroTarget targetType, uint32 position = 0, float dist = 0.0f, bool playerOnly = false, int32 aura = 0);
133 // Select the targets satifying the predicate.
134 // predicate shall extend std::unary_function<Unit*, bool>
135 template <class PREDICATE> Unit* SelectTarget(SelectAggroTarget targetType, uint32 position, PREDICATE const& predicate)
136 {
137 ThreatContainer::StorageType const& threatlist = me->getThreatManager().getThreatList();
138 if (position >= threatlist.size())
139 return NULL;
140
141 std::list<Unit*> targetList;
142 for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
143 if (predicate((*itr)->getTarget()))
144 targetList.push_back((*itr)->getTarget());
145
146 if (position >= targetList.size())
147 return NULL;
148
149 if (targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST)
150 targetList.sort(Skyfire::ObjectDistanceOrderPred(me));
151
152 switch (targetType)
153 {
156 {
157 std::list<Unit*>::iterator itr = targetList.begin();
158 std::advance(itr, position);
159 return *itr;
160 }
163 {
164 std::list<Unit*>::reverse_iterator ritr = targetList.rbegin();
165 std::advance(ritr, position);
166 return *ritr;
167 }
169 {
170 std::list<Unit*>::iterator itr = targetList.begin();
171 std::advance(itr, (std::rand() % targetList.size()) + position);
172 return *itr;
173 }
174 default:
175 break;
176 }
177
178 return NULL;
179 }
180
181 void SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectAggroTarget targetType, float dist = 0.0f, bool playerOnly = false, int32 aura = 0);
182
183 // Select the targets satifying the predicate.
184 // predicate shall extend std::unary_function<Unit*, bool>
185 template <class PREDICATE> void SelectTargetList(std::list<Unit*>& targetList, PREDICATE const& predicate, uint32 maxTargets, SelectAggroTarget targetType)
186 {
187 ThreatContainer::StorageType const& threatlist = me->getThreatManager().getThreatList();
188 if (threatlist.empty())
189 return;
190
191 for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
192 if (predicate((*itr)->getTarget()))
193 targetList.push_back((*itr)->getTarget());
194
195 if (targetList.size() < maxTargets)
196 return;
197
198 if (targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST)
199 targetList.sort(Skyfire::ObjectDistanceOrderPred(me));
200
201 if (targetType == SELECT_TARGET_FARTHEST || targetType == SELECT_TARGET_BOTTOMAGGRO)
202 targetList.reverse();
203
204 if (targetType == SELECT_TARGET_RANDOM)
205 Skyfire::Containers::RandomResizeList(targetList, maxTargets);
206 else
207 targetList.resize(maxTargets);
208 }
209
210 // Called at any Damage to any victim (before damage apply)
211 virtual void DamageDealt(Unit* /*victim*/, uint32& /*damage*/, DamageEffectType /*damageType*/) { }
212
213 // Called at any Damage from any attacker (before damage apply)
214 // Note: it for recalculation damage or special reaction at damage
215 // for attack reaction use AttackedBy called for not DOT damage in Unit::DealDamage also
216 virtual void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) { }
217
218 // Called when the creature receives heal
219 virtual void HealReceived(Unit* /*done_by*/, uint32& /*addhealth*/) { }
220
221 // Called when the unit heals
222 virtual void HealDone(Unit* /*done_to*/, uint32& /*addhealth*/) { }
223
226 virtual void SpellInterrupted(uint32 /*spellId*/, uint32 /*unTimeMs*/) { }
227
228 void AttackStartCaster(Unit* victim, float dist);
229
231 void DoCast(uint32 spellId);
232 void DoCast(Unit* victim, uint32 spellId, bool triggered = false);
233 void DoCastToAllHostilePlayers(uint32 spellid, bool triggered = false);
234 void DoCastVictim(uint32 spellId, bool triggered = false);
235 void DoCastAOE(uint32 spellId, bool triggered = false);
236
237 float DoGetSpellMaxRange(uint32 spellId, bool positive = false);
238
240 bool DoSpellAttackIfReady(uint32 spell);
241
243 static void FillAISpellInfo();
244
245 virtual bool OnGossipHello(Player* player) { sGossipHello(player); return false; }
246 virtual void sGossipHello(Player* /*player*/) { }
247 virtual void sGossipSelect(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/) { }
248 virtual void sGossipSelectCode(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/, char const* /*code*/) { }
249 virtual void sQuestAccept(Player* /*player*/, Quest const* /*quest*/) { }
250 virtual void sQuestSelect(Player* /*player*/, Quest const* /*quest*/) { }
251 virtual void sQuestComplete(Player* /*player*/, Quest const* /*quest*/) { }
252 virtual void sQuestReward(Player* /*player*/, Quest const* /*quest*/, uint32 /*opt*/) { }
253 virtual bool sOnDummyEffect(Unit* /*caster*/, uint32 /*spellId*/, SpellEffIndex /*effIndex*/) { return false; }
254 virtual void sOnGameEvent(bool /*start*/, uint16 /*eventId*/) { }
255private:
256 UnitAI(UnitAI const& right) = delete;
257 UnitAI& operator=(UnitAI const& right) = delete;
258};
259
260class PlayerAI : public UnitAI
261{
262protected:
263 Player* const me;
264public:
265 explicit PlayerAI(Player* player) : UnitAI((Unit*)player), me(player) { }
266
267 void OnCharmed(bool apply) OVERRIDE;
268};
269
271{
272public:
273 void UpdateAI(uint32 diff) OVERRIDE;
274 SimpleCharmedAI(Player* player) : PlayerAI(player) { }
275};
276
277#endif
std::int32_t int32
Definition Define.h:73
std::uint32_t uint32
Definition Define.h:77
#define OVERRIDE
Definition Define.h:60
std::uint64_t uint64
Definition Define.h:76
std::uint16_t uint16
Definition Define.h:78
@ TYPEID_PLAYER
Definition Object.h:55
SpellEffIndex
#define SF_UNARY_FUNCTION
DamageEffectType
Definition Unit.h:613
SelectAggroTarget
Definition UnitAI.h:22
@ SELECT_TARGET_BOTTOMAGGRO
Definition UnitAI.h:25
@ SELECT_TARGET_FARTHEST
Definition UnitAI.h:27
@ SELECT_TARGET_TOPAGGRO
Definition UnitAI.h:24
@ SELECT_TARGET_NEAREST
Definition UnitAI.h:26
@ SELECT_TARGET_RANDOM
Definition UnitAI.h:23
TypeID GetTypeId() const
Definition Object.h:131
void OnCharmed(bool apply) OVERRIDE
Definition UnitAI.cpp:241
Player *const me
Definition UnitAI.h:263
PlayerAI(Player *player)
Definition UnitAI.h:265
void UpdateAI(uint32 diff) OVERRIDE
Definition UnitAI.cpp:246
SimpleCharmedAI(Player *player)
Definition UnitAI.h:274
std::list< HostileReference * > StorageType
virtual void sQuestAccept(Player *, Quest const *)
Definition UnitAI.h:249
virtual void HealReceived(Unit *, uint32 &)
Definition UnitAI.h:219
virtual uint64 GetGUID(int32=0) const
Definition UnitAI.h:130
virtual void SetData(uint32, uint32)
Definition UnitAI.h:128
virtual void DoAction(int32)
Definition UnitAI.h:126
void AttackStartCaster(Unit *victim, float dist)
Definition UnitAI.cpp:22
virtual void SetGUID(uint64, int32=0)
Definition UnitAI.h:129
static void FillAISpellInfo()
Definition UnitAI.cpp:186
void SelectTargetList(std::list< Unit * > &targetList, PREDICATE const &predicate, uint32 maxTargets, SelectAggroTarget targetType)
Definition UnitAI.h:185
void SelectTargetList(std::list< Unit * > &targetList, uint32 num, SelectAggroTarget targetType, float dist=0.0f, bool playerOnly=false, int32 aura=0)
Definition UnitAI.cpp:71
virtual void SpellInterrupted(uint32, uint32)
Definition UnitAI.h:226
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:28
virtual ~UnitAI()
Definition UnitAI.h:112
void DoCast(uint32 spellId)
Definition UnitAI.cpp:110
virtual void sGossipSelectCode(Player *, uint32, uint32, char const *)
Definition UnitAI.h:248
virtual void Reset()
Definition UnitAI.h:120
UnitAI(Unit *unit)
Definition UnitAI.h:111
virtual void sQuestComplete(Player *, Quest const *)
Definition UnitAI.h:251
virtual bool CanAIAttack(Unit const *) const
Definition UnitAI.h:114
virtual bool OnGossipHello(Player *player)
Definition UnitAI.h:245
virtual void sQuestReward(Player *, Quest const *, uint32)
Definition UnitAI.h:252
virtual uint32 GetData(uint32) const
Definition UnitAI.h:127
Unit * SelectTarget(SelectAggroTarget targetType, uint32 position=0, float dist=0.0f, bool playerOnly=false, int32 aura=0)
Definition UnitAI.cpp:66
virtual bool sOnDummyEffect(Unit *, uint32, SpellEffIndex)
Definition UnitAI.h:253
Unit * SelectTarget(SelectAggroTarget targetType, uint32 position, PREDICATE const &predicate)
Definition UnitAI.h:135
UnitAI & operator=(UnitAI const &right)=delete
virtual void sGossipHello(Player *)
Definition UnitAI.h:246
void DoCastToAllHostilePlayers(uint32 spellid, bool triggered=false)
Definition UnitAI.cpp:96
float DoGetSpellMaxRange(uint32 spellId, bool positive=false)
Definition UnitAI.cpp:76
void DoAddAuraToAllHostilePlayers(uint32 spellid)
Definition UnitAI.cpp:82
virtual void InitializeAI()
Definition UnitAI.h:118
virtual void DamageTaken(Unit *, uint32 &)
Definition UnitAI.h:216
virtual void sGossipSelect(Player *, uint32, uint32)
Definition UnitAI.h:247
bool DoSpellAttackIfReady(uint32 spell)
Definition UnitAI.cpp:48
Unit *const me
Definition UnitAI.h:109
void DoCastVictim(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:168
virtual void HealDone(Unit *, uint32 &)
Definition UnitAI.h:222
virtual void DamageDealt(Unit *, uint32 &, DamageEffectType)
Definition UnitAI.h:211
virtual void UpdateAI(uint32 diff)=0
virtual void sQuestSelect(Player *, Quest const *)
Definition UnitAI.h:250
UnitAI(UnitAI const &right)=delete
void DoCastAOE(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:176
static AISpellInfoType * AISpellInfo
Definition UnitAI.h:242
virtual void AttackStart(Unit *)
Definition UnitAI.cpp:16
virtual void OnCharmed(bool apply)=0
virtual void sOnGameEvent(bool, uint16)
Definition UnitAI.h:254
Definition Unit.h:1367
bool HasAura(uint32 spellId, uint64 casterGUID=0, uint64 itemCasterGUID=0, uint32 reqEffMask=0) const
void RandomResizeList(std::list< T > &list, uint32 size)
Definition Containers.h:19
DefaultTargetSelector(Unit const *unit, float dist, bool playerOnly, int32 aura)
Definition UnitAI.h:42
bool operator()(Unit const *target) const
Definition UnitAI.h:44
const Unit * me
Definition UnitAI.h:33
Creature const * _source
Definition UnitAI.h:102
bool operator()(Unit const *target) const
Definition UnitAI.cpp:313
NonTankTargetSelector(Creature *source, bool playerOnly=true)
Definition UnitAI.h:98
SpellInfo const * _spellInfo
Definition UnitAI.h:89
bool operator()(Unit const *target) const
Definition UnitAI.cpp:276
SpellTargetSelector(Unit *caster, uint32 spellId)
Definition UnitAI.cpp:270
Unit const * _caster
Definition UnitAI.h:88