TrinityCore
CreatureAI.cpp
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#include "CreatureAI.h"
19#include "AreaBoundary.h"
20#include "Containers.h"
21#include "Creature.h"
22#include "CreatureAIImpl.h"
23#include "CreatureTextMgr.h"
24#include "DB2Structure.h"
25#include "Errors.h"
26#include "Language.h"
27#include "Log.h"
28#include "Map.h"
29#include "MapReference.h"
30#include "MotionMaster.h"
31#include "ObjectAccessor.h"
32#include "Player.h"
33#include "SmartEnum.h"
34#include "SpellHistory.h"
35#include "TemporarySummon.h"
36#include "Vehicle.h"
37#include <queue>
38
39std::unordered_map<std::pair<uint32, Difficulty>, AISpellInfoType> UnitAI::AISpellInfo;
41{
42 return Trinity::Containers::MapGetValuePtr(UnitAI::AISpellInfo, { spellId, difficulty });
43}
44
46 : UnitAI(creature), me(creature), _boundary(nullptr),
47 _negateBoundary(false), _scriptId(scriptId ? scriptId : creature->GetScriptId()), _isEngaged(false), _moveInLOSLocked(false)
48{
49 ASSERT(_scriptId, "A CreatureAI was initialized with an invalid scriptId!");
50}
51
53{
54}
55
56void CreatureAI::Talk(uint8 id, WorldObject const* whisperTarget /*= nullptr*/)
57{
58 sCreatureTextMgr->SendChat(me, id, whisperTarget);
59}
60
61// Disable CreatureAI when charmed
62void CreatureAI::OnCharmed(bool isNew)
63{
64 if (isNew && !me->IsCharmed() && !me->LastCharmerGUID.IsEmpty())
65 {
67 {
68 if (Unit* lastCharmer = ObjectAccessor::GetUnit(*me, me->LastCharmerGUID))
69 me->EngageWithTarget(lastCharmer);
70 }
71
73
74 if (!me->IsInCombat())
76 }
77
78 UnitAI::OnCharmed(isNew);
79}
80
82{
83 Map* map = creature->GetMap();
84 if (!map->IsDungeon()) // use IsDungeon instead of Instanceable, in case battlegrounds will be instantiated
85 {
86 TC_LOG_ERROR("scripts.ai", "CreatureAI::DoZoneInCombat: call for map that isn't an instance ({})", creature->GetGUID().ToString());
87 return;
88 }
89
90 if (!map->HavePlayers())
91 return;
92
93 for (MapReference const& ref : map->GetPlayers())
94 {
95 if (Player* player = ref.GetSource())
96 {
97 if (!player->IsAlive() || !CombatManager::CanBeginCombat(creature, player))
98 continue;
99
100 creature->EngageWithTarget(player);
101
102 for (Unit* pet : player->m_Controlled)
103 creature->EngageWithTarget(pet);
104
105 if (Unit* vehicle = player->GetVehicleBase())
106 creature->EngageWithTarget(vehicle);
107 }
108 }
109}
110
111// scripts does not take care about MoveInLineOfSight loops
112// MoveInLineOfSight can be called inside another MoveInLineOfSight and cause stack overflow
114{
115 if (_moveInLOSLocked == true)
116 return;
117 _moveInLOSLocked = true;
119 _moveInLOSLocked = false;
120}
121
123{
124 if (me->IsEngaged())
125 return;
126
127 if (me->HasReactState(REACT_AGGRESSIVE) && me->CanStartAttack(who, false))
128 me->EngageWithTarget(who);
129}
130
132{
133 if (!target || !me->IsAlive())
134 return;
135
136 if (!me->HasReactState(REACT_PASSIVE) && me->CanStartAttack(target, true))
137 me->EngageWithTarget(target);
138}
139
140// Distract creature, if player gets too close while stealthed/prowling
141void CreatureAI::TriggerAlert(Unit const* who) const
142{
143 // If there's no target, or target isn't a player do nothing
144 if (!who || who->GetTypeId() != TYPEID_PLAYER)
145 return;
146
147 // If this unit isn't an NPC, is already distracted, is fighting, is confused, stunned or fleeing, do nothing
149 return;
150
151 // Only alert for hostiles!
153 return;
154
155 // Send alert sound (if any) for this creature
157
158 // Face the unit (stealthed player) and set distracted state for 5 seconds
160}
161
162// adapted from logic in Spell:EffectSummonType before commit 8499434
163static bool ShouldFollowOnSpawn(SummonPropertiesEntry const* properties)
164{
165 // Summons without SummonProperties are generally scripted summons that don't belong to any owner
166 if (!properties)
167 return false;
168
169 switch (properties->Control)
170 {
172 return true;
177 return true;
178 switch (SummonTitle(properties->Title))
179 {
180 case SummonTitle::Pet:
185 return true;
186 default:
187 return false;
188 }
189 default:
190 return false;
191 }
192}
193
195{
196 if (!IsEngaged())
197 {
198 if (TempSummon* summon = me->ToTempSummon())
199 {
200 // Only apply this to specific types of summons
201 if (!summon->GetVehicle() && ShouldFollowOnSpawn(summon->m_Properties) && summon->CanFollowOwner())
202 {
203 if (Unit* owner = summon->GetCharmerOrOwner())
204 {
205 summon->GetMotionMaster()->Clear();
206 summon->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, summon->GetFollowAngle());
207 }
208 }
209 }
210 }
211}
212
214{
215 if (!IsEngaged() && !me->CanHaveThreatList())
216 EngagementStart(who);
217}
218
220{
221 if (!_EnterEvadeMode(why))
222 return;
223
224 TC_LOG_DEBUG("scripts.ai", "CreatureAI::EnterEvadeMode: entering evade mode (why: {}) ({})", EnumUtils::ToConstant(why), me->GetGUID().ToString());
225
226 if (!me->GetVehicle()) // otherwise me will be in evade mode forever
227 {
228 if (Unit* owner = me->GetCharmerOrOwner())
229 {
232 }
233 else
234 {
235 // Required to prevent attacking creatures that are evading and cause them to reenter combat
236 // Does not apply to MoveFollow
239 }
240 }
241
242 Reset();
243}
244
246{
247 if (!IsEngaged())
248 return false;
249
250 if (!me->IsAlive())
251 {
253 return false;
254 }
255
257 {
258 if (Unit* victim = me->SelectVictim())
259 if (victim != me->GetVictim())
260 AttackStart(victim);
261
262 return me->GetVictim() != nullptr;
263 }
264 else if (!me->IsInCombat())
265 {
267 return false;
268 }
269 else if (me->GetVictim())
270 me->AttackStop();
271
272 return true;
273}
274
276{
277 if (_isEngaged)
278 {
279 TC_LOG_ERROR("scripts.ai", "CreatureAI::EngagementStart called even though creature is already engaged. Creature debug info:\n{}", me->GetDebugInfo());
280 return;
281 }
282 _isEngaged = true;
283
284 me->AtEngage(who);
285}
286
288{
289 if (!_isEngaged)
290 {
291 TC_LOG_DEBUG("scripts.ai", "CreatureAI::EngagementOver called even though creature is not currently engaged. Creature debug info:\n{}", me->GetDebugInfo());
292 return;
293 }
294 _isEngaged = false;
295
296 me->AtDisengage();
297}
298
300{
301 if (me->IsInEvadeMode())
302 return false;
303
304 if (!me->IsAlive())
305 {
307 return false;
308 }
309
312
313 me->CombatStop(true);
315 me->SetTappedBy(nullptr);
316
319 me->SetCannotReachTarget(false);
324
325 return true;
326}
327
329{
330 if (victim && me->Attack(victim, true))
331 {
332 // Clear distracted state on attacking
334 {
337 }
338
340 }
341}
342
344{
345 return {};
346}
347
353int32 CreatureAI::VisualizeBoundary(Seconds duration, Unit* owner, bool fill) const
354{
355 typedef std::pair<int32, int32> coordinate;
356
357 if (!owner)
358 return -1;
359
360 if (!_boundary || _boundary->empty())
362
363 std::queue<coordinate> Q;
364 std::unordered_set<coordinate> alreadyChecked;
365 std::unordered_set<coordinate> outOfBounds;
366
367 Position startPosition = owner->GetPosition();
368 if (!IsInBoundary(&startPosition)) // fall back to creature position
369 {
370 startPosition = me->GetPosition();
371 if (!IsInBoundary(&startPosition)) // fall back to creature home position
372 {
373 startPosition = me->GetHomePosition();
374 if (!IsInBoundary(&startPosition))
376 }
377 }
378 float spawnZ = startPosition.GetPositionZ() + BOUNDARY_VISUALIZE_SPAWN_HEIGHT;
379
380 bool boundsWarning = false;
381 Q.push({ 0,0 });
382 while (!Q.empty())
383 {
384 coordinate front = Q.front();
385 bool hasOutOfBoundsNeighbor = false;
386 for (coordinate const& off : std::list<coordinate>{ {1, 0}, {0, 1}, {-1, 0}, {0, -1} })
387 {
388 coordinate next(front.first + off.first, front.second + off.second);
390 {
391 boundsWarning = true;
392 continue;
393 }
394 if (alreadyChecked.find(next) == alreadyChecked.end()) // never check a coordinate twice
395 {
396 Position nextPos(startPosition.GetPositionX() + next.first*BOUNDARY_VISUALIZE_STEP_SIZE, startPosition.GetPositionY() + next.second*BOUNDARY_VISUALIZE_STEP_SIZE, startPosition.GetPositionZ());
397 if (IsInBoundary(&nextPos))
398 Q.push(next);
399 else
400 {
401 outOfBounds.insert(next);
402 hasOutOfBoundsNeighbor = true;
403 }
404 alreadyChecked.insert(next);
405 }
406 else if (outOfBounds.find(next) != outOfBounds.end())
407 hasOutOfBoundsNeighbor = true;
408 }
409 if (fill || hasOutOfBoundsNeighbor)
410 {
411 if (TempSummon* point = owner->SummonCreature(BOUNDARY_VISUALIZE_CREATURE, Position(startPosition.GetPositionX() + front.first * BOUNDARY_VISUALIZE_STEP_SIZE, startPosition.GetPositionY() + front.second * BOUNDARY_VISUALIZE_STEP_SIZE, spawnZ), TEMPSUMMON_TIMED_DESPAWN, duration))
412 {
413 point->SetObjectScale(BOUNDARY_VISUALIZE_CREATURE_SCALE);
414 point->SetUnitFlag(UNIT_FLAG_STUNNED);
415 point->SetImmuneToAll(true);
416 if (!hasOutOfBoundsNeighbor)
417 point->SetUninteractible(true);
418 }
419 }
420
421 Q.pop();
422 }
423 return boundsWarning ? LANG_CREATURE_MOVEMENT_MAYBE_UNBOUNDED : 0;
424}
425
426bool CreatureAI::IsInBoundary(Position const* who) const
427{
428 if (!_boundary)
429 return true;
430
431 if (!who)
432 who = me;
433
435}
436
437bool CreatureAI::IsInBounds(CreatureBoundary const& boundary, Position const* pos)
438{
439 for (AreaBoundary const* areaBoundary : boundary)
440 if (!areaBoundary->IsWithinBoundary(pos))
441 return false;
442
443 return true;
444}
445
446void CreatureAI::SetBoundary(CreatureBoundary const* boundary, bool negateBoundaries /*= false*/)
447{
448 _boundary = boundary;
449 _negateBoundary = negateBoundaries;
451}
452
454{
455 if (IsInBoundary())
456 return true;
457 else
458 {
460 return false;
461 }
462}
463
464Creature* CreatureAI::DoSummon(uint32 entry, Position const& pos, Milliseconds despawnTime, TempSummonType summonType)
465{
466 return me->SummonCreature(entry, pos, summonType, despawnTime);
467}
468
469Creature* CreatureAI::DoSummon(uint32 entry, WorldObject* obj, float radius, Milliseconds despawnTime, TempSummonType summonType)
470{
471 Position pos = obj->GetRandomNearPosition(radius);
472 return me->SummonCreature(entry, pos, summonType, despawnTime);
473}
474
475Creature* CreatureAI::DoSummonFlyer(uint32 entry, WorldObject* obj, float flightZ, float radius, Milliseconds despawnTime, TempSummonType summonType)
476{
477 Position pos = obj->GetRandomNearPosition(radius);
478 pos.m_positionZ += flightZ;
479 return me->SummonCreature(entry, pos, summonType, despawnTime);
480}
@ IN_MILLISECONDS
Definition: Common.h:35
const float BOUNDARY_VISUALIZE_SPAWN_HEIGHT
Definition: CreatureAI.cpp:352
const uint32 BOUNDARY_VISUALIZE_CREATURE
Definition: CreatureAI.cpp:348
AISpellInfoType * GetAISpellInfo(uint32 spellId, Difficulty difficulty)
Definition: CreatureAI.cpp:40
const int32 BOUNDARY_VISUALIZE_FAILSAFE_LIMIT
Definition: CreatureAI.cpp:351
const int8 BOUNDARY_VISUALIZE_STEP_SIZE
Definition: CreatureAI.cpp:350
const float BOUNDARY_VISUALIZE_CREATURE_SCALE
Definition: CreatureAI.cpp:349
static bool ShouldFollowOnSpawn(SummonPropertiesEntry const *properties)
Definition: CreatureAI.cpp:163
std::vector< AreaBoundary const * > CreatureBoundary
Definition: CreatureAI.h:37
#define sCreatureTextMgr
Difficulty
Definition: DBCEnums.h:873
uint8_t uint8
Definition: Define.h:144
int8_t int8
Definition: Define.h:140
int32_t int32
Definition: Define.h:138
uint32_t uint32
Definition: Define.h:142
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition: Duration.h:32
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition: Duration.h:29
#define ASSERT
Definition: Errors.h:68
@ LANG_CREATURE_MOVEMENT_MAYBE_UNBOUNDED
Definition: Language.h:1235
@ LANG_CREATURE_MOVEMENT_NOT_BOUNDED
Definition: Language.h:1234
@ LANG_CREATURE_NO_INTERIOR_POINT_FOUND
Definition: Language.h:1233
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
TempSummonType
Definition: ObjectDefines.h:62
@ TEMPSUMMON_TIMED_DESPAWN
Definition: ObjectDefines.h:65
@ TYPEID_UNIT
Definition: ObjectGuid.h:40
@ TYPEID_PLAYER
Definition: ObjectGuid.h:41
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
#define PET_FOLLOW_DIST
Definition: PetDefines.h:97
SummonTitle
@ AI_REACTION_ALERT
@ SUMMON_CATEGORY_PET
@ SUMMON_CATEGORY_ALLY
@ SUMMON_CATEGORY_WILD
@ SUMMON_CATEGORY_UNK
EvadeReason
Definition: UnitAICommon.h:30
@ REACT_PASSIVE
Definition: UnitDefines.h:506
@ REACT_AGGRESSIVE
Definition: UnitDefines.h:508
@ UNIT_FLAG_STUNNED
Definition: UnitDefines.h:162
@ UNIT_STATE_DISTRACTED
Definition: Unit.h:267
@ UNIT_STATE_EVADE
Definition: Unit.h:277
@ UNIT_STATE_CONFUSED
Definition: Unit.h:266
@ UNIT_STATE_FLEEING
Definition: Unit.h:262
@ UNIT_STATE_STUNNED
Definition: Unit.h:258
static bool CanBeginCombat(Unit const *a, Unit const *b)
int32 VisualizeBoundary(Seconds duration, Unit *owner=nullptr, bool fill=false) const
Definition: CreatureAI.cpp:353
virtual void MoveInLineOfSight(Unit *)
Definition: CreatureAI.cpp:122
void DoZoneInCombat()
Definition: CreatureAI.h:161
bool IsEngaged() const
Definition: CreatureAI.h:77
static bool IsInBounds(CreatureBoundary const &boundary, Position const *who)
Definition: CreatureAI.cpp:437
void TriggerAlert(Unit const *who) const
Definition: CreatureAI.cpp:141
CreatureBoundary const * _boundary
Definition: CreatureAI.h:249
void OnOwnerCombatInteraction(Unit *target)
Definition: CreatureAI.cpp:131
Creature * DoSummonFlyer(uint32 entry, WorldObject *obj, float flightZ, float radius=5.0f, Milliseconds despawnTime=30s, TempSummonType summonType=TEMPSUMMON_CORPSE_TIMED_DESPAWN)
Definition: CreatureAI.cpp:475
bool _isEngaged
Definition: CreatureAI.h:256
bool _negateBoundary
Definition: CreatureAI.h:250
void JustEnteredCombat(Unit *) override
Definition: CreatureAI.cpp:213
virtual void EnterEvadeMode(EvadeReason why=EvadeReason::Other)
Definition: CreatureAI.cpp:219
void Talk(uint8 id, WorldObject const *whisperTarget=nullptr)
Definition: CreatureAI.cpp:56
uint32 const _scriptId
Definition: CreatureAI.h:255
bool _EnterEvadeMode(EvadeReason why=EvadeReason::Other)
Definition: CreatureAI.cpp:299
void OnCharmed(bool isNew) override
Definition: CreatureAI.cpp:62
CreatureAI(Creature *creature, uint32 scriptId={})
Definition: CreatureAI.cpp:45
virtual void JustAppeared()
Definition: CreatureAI.cpp:194
virtual bool CheckInRoom()
Definition: CreatureAI.cpp:453
virtual Optional< QuestGiverStatus > GetDialogStatus(Player const *player)
== Gossip system ================================
Definition: CreatureAI.cpp:343
bool IsInBoundary(Position const *who=nullptr) const
Definition: CreatureAI.cpp:426
bool UpdateVictim()
Definition: CreatureAI.cpp:245
virtual ~CreatureAI()
Definition: CreatureAI.cpp:52
void SetBoundary(CreatureBoundary const *boundary, bool negativeBoundaries=false)
Definition: CreatureAI.cpp:446
void AttackStart(Unit *victim) override
== Triggered Actions Requested ==================
Definition: CreatureAI.cpp:328
void EngagementStart(Unit *who)
Definition: CreatureAI.cpp:275
Creature *const me
Definition: CreatureAI.h:61
Creature * DoSummon(uint32 entry, Position const &pos, Milliseconds despawnTime=30s, TempSummonType summonType=TEMPSUMMON_CORPSE_TIMED_DESPAWN)
Definition: CreatureAI.cpp:464
void EngagementOver()
Definition: CreatureAI.cpp:287
bool _moveInLOSLocked
Definition: CreatureAI.h:257
void MoveInLineOfSight_Safe(Unit *who)
== Reactions At =================================
Definition: CreatureAI.cpp:113
bool IsTapListNotClearedOnEvade() const
Definition: Creature.h:285
void DoImmediateBoundaryCheck()
Definition: Creature.h:343
void StartDefaultCombatMovement(Unit *victim, Optional< float > range={}, Optional< float > angle={})
Definition: Creature.cpp:2855
bool _IsTargetAcceptable(Unit const *target) const
Definition: Creature.cpp:2639
bool IsCivilian() const
Definition: Creature.h:112
void GetHomePosition(float &x, float &y, float &z, float &ori) const
Definition: Creature.h:373
void SetLastDamagedTime(time_t val)
Definition: Creature.h:427
bool HasReactState(ReactStates state) const
Definition: Creature.h:162
void DoNotReacquireSpellFocusTarget()
Definition: Creature.cpp:3545
bool IsEngaged() const override
Definition: Creature.cpp:3601
void ResetPlayerDamageReq()
Definition: Creature.h:400
void SetCannotReachTarget(bool cannotReach)
Definition: Creature.cpp:3303
void SetTappedBy(Unit const *unit, bool withGroup=true)
Definition: Creature.cpp:1339
void AtEngage(Unit *target) override
Definition: Creature.cpp:3608
void AtDisengage() override
Definition: Creature.cpp:3644
void SetTarget(ObjectGuid const &guid) override
Definition: Creature.cpp:3419
bool IsStateRestoredOnEvade() const
Definition: Creature.h:206
Unit * SelectVictim()
Definition: Creature.cpp:1211
void SendAIReaction(AiReaction reactionType)
Definition: Creature.cpp:2521
bool IsInEvadeMode() const
Definition: Creature.h:203
std::string GetDebugInfo() const override
Definition: Creature.cpp:3667
bool CanStartAttack(Unit const *u, bool force) const
Definition: Creature.cpp:2099
static char const * ToConstant(Enum value)
Definition: SmartEnum.h:120
Definition: Map.h:189
bool IsDungeon() const
Definition: Map.cpp:3238
bool HavePlayers() const
Definition: Map.h:357
PlayerList const & GetPlayers() const
Definition: Map.h:367
void MoveFollow(Unit *target, float dist, ChaseAngle angle, Optional< Milliseconds > duration={}, MovementSlot slot=MOTION_SLOT_ACTIVE)
void MoveTargetedHome()
void MoveDistract(uint32 time, float orientation)
static ObjectGuid const Empty
Definition: ObjectGuid.h:274
bool IsEmpty() const
Definition: ObjectGuid.h:319
std::string ToString() const
Definition: ObjectGuid.cpp:554
void Clear()
Definition: ObjectGuid.h:286
TypeID GetTypeId() const
Definition: Object.h:173
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
void ResetAllCooldowns()
Definition: UnitAI.h:50
virtual void Reset()
Definition: UnitAI.h:63
static std::unordered_map< std::pair< uint32, Difficulty >, AISpellInfoType > AISpellInfo
Definition: UnitAI.h:165
virtual void OnCharmed(bool isNew)
Definition: UnitAI.cpp:49
Definition: Unit.h:627
void ClearUnitState(uint32 f)
Definition: Unit.h:733
bool IsCharmed() const
Definition: Unit.h:1215
Vehicle * GetVehicle() const
Definition: Unit.h:1713
void CombatStop(bool includingCast=false, bool mutualPvP=true, bool(*unitFilter)(Unit const *otherUnit)=nullptr)
Definition: Unit.cpp:5827
bool CanHaveThreatList() const
====================== THREAT & COMBAT ====================
Definition: Unit.h:1015
Unit * GetVehicleBase() const
Definition: Unit.cpp:11480
MotionMaster * GetMotionMaster()
Definition: Unit.h:1652
bool IsAlive() const
Definition: Unit.h:1164
TempSummon * ToTempSummon()
Definition: Unit.h:1756
ControlList m_Controlled
Definition: Unit.h:1211
void AddUnitState(uint32 f)
Definition: Unit.h:731
Unit * GetCharmerOrOwner() const
Definition: Unit.h:1200
bool Attack(Unit *victim, bool meleeAttack)
Definition: Unit.cpp:5670
void EngageWithTarget(Unit *who)
Definition: Unit.cpp:8077
virtual float GetFollowAngle() const
Definition: Unit.h:1744
Unit * GetVictim() const
Definition: Unit.h:715
bool HasUnitState(const uint32 f) const
Definition: Unit.h:732
SpellHistory * GetSpellHistory()
Definition: Unit.h:1457
ObjectGuid LastCharmerGUID
Definition: Unit.h:1708
bool AttackStop()
Definition: Unit.cpp:5781
void RemoveAurasOnEvade()
Definition: Unit.cpp:4303
bool IsInCombat() const
Definition: Unit.h:1043
Map * GetMap() const
Definition: Object.h:624
bool IsHostileTo(WorldObject const *target) const
Definition: Object.cpp:2860
TempSummon * SummonCreature(uint32 entry, Position const &pos, TempSummonType despawnType=TEMPSUMMON_MANUAL_DESPAWN, Milliseconds despawnTime=0s, uint32 vehId=0, uint32 spellId=0, ObjectGuid privateObjectOwner=ObjectGuid::Empty)
Definition: Object.cpp:2025
Position GetRandomNearPosition(float radius)
Definition: Object.cpp:3423
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
auto MapGetValuePtr(M &map, typename M::key_type const &key)
Definition: MapUtils.h:29
constexpr float GetPositionX() const
Definition: Position.h:76
float m_positionZ
Definition: Position.h:55
constexpr float GetPositionY() const
Definition: Position.h:77
float GetAbsoluteAngle(float x, float y) const
Definition: Position.h:125
constexpr void GetPosition(float &x, float &y) const
Definition: Position.h:81
constexpr float GetPositionZ() const
Definition: Position.h:78
EnumFlag< SummonPropertiesFlags > GetFlags() const