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 "Creature.h"
21#include "CreatureAIImpl.h"
22#include "CreatureTextMgr.h"
23#include "DB2Structure.h"
24#include "Errors.h"
25#include "Language.h"
26#include "Log.h"
27#include "Map.h"
28#include "MapReference.h"
29#include "MapUtils.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
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;
176 return true;
177 switch (SummonTitle(properties->Title))
178 {
179 case SummonTitle::Pet:
184 return true;
185 default:
186 return false;
187 }
188 default:
189 return false;
190 }
191}
192
194{
195 if (!IsEngaged())
196 {
197 if (TempSummon* summon = me->ToTempSummon())
198 {
199 // Only apply this to specific types of summons
200 if (!summon->GetVehicle() && ShouldFollowOnSpawn(summon->m_Properties) && summon->CanFollowOwner())
201 {
202 if (Unit* owner = summon->GetCharmerOrOwner())
203 {
204 summon->GetMotionMaster()->Clear();
205 summon->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, summon->GetFollowAngle());
206 }
207 }
208 }
209 }
210}
211
213{
214 if (!IsEngaged() && !me->CanHaveThreatList())
215 EngagementStart(who);
216}
217
219{
220 if (!_EnterEvadeMode(why))
221 return;
222
223 TC_LOG_DEBUG("scripts.ai", "CreatureAI::EnterEvadeMode: entering evade mode (why: {}) ({})", EnumUtils::ToConstant(why), me->GetGUID().ToString());
224
225 if (!me->GetVehicle()) // otherwise me will be in evade mode forever
226 {
227 if (Unit* owner = me->GetCharmerOrOwner())
228 {
231 }
232 else
233 {
234 // Required to prevent attacking creatures that are evading and cause them to reenter combat
235 // Does not apply to MoveFollow
238 }
239 }
240
241 Reset();
242}
243
245{
246 if (!IsEngaged())
247 return false;
248
249 if (!me->IsAlive())
250 {
252 return false;
253 }
254
256 {
257 if (Unit* victim = me->SelectVictim())
258 if (victim != me->GetVictim())
259 AttackStart(victim);
260
261 return me->GetVictim() != nullptr;
262 }
263 else if (!me->IsInCombat())
264 {
266 return false;
267 }
268 else if (me->GetVictim())
269 me->AttackStop();
270
271 return true;
272}
273
275{
276 if (_isEngaged)
277 {
278 TC_LOG_ERROR("scripts.ai", "CreatureAI::EngagementStart called even though creature is already engaged. Creature debug info:\n{}", me->GetDebugInfo());
279 return;
280 }
281 _isEngaged = true;
282
283 me->AtEngage(who);
284}
285
287{
288 if (!_isEngaged)
289 {
290 TC_LOG_DEBUG("scripts.ai", "CreatureAI::EngagementOver called even though creature is not currently engaged. Creature debug info:\n{}", me->GetDebugInfo());
291 return;
292 }
293 _isEngaged = false;
294
295 me->AtDisengage();
296}
297
299{
300 if (me->IsInEvadeMode())
301 return false;
302
303 if (!me->IsAlive())
304 {
306 return false;
307 }
308
311
312 me->CombatStop(true);
314 me->SetTappedBy(nullptr);
315
318 me->SetCannotReachTarget(false);
323
324 return true;
325}
326
328{
329 if (victim && me->Attack(victim, true))
330 {
331 // Clear distracted state on attacking
333 {
336 }
337
339 }
340}
341
343{
344 return {};
345}
346
352int32 CreatureAI::VisualizeBoundary(Seconds duration, Unit* owner, bool fill) const
353{
354 typedef std::pair<int32, int32> coordinate;
355
356 if (!owner)
357 return -1;
358
359 if (!_boundary || _boundary->empty())
361
362 std::queue<coordinate> Q;
363 std::unordered_set<coordinate> alreadyChecked;
364 std::unordered_set<coordinate> outOfBounds;
365
366 Position startPosition = owner->GetPosition();
367 if (!IsInBoundary(&startPosition)) // fall back to creature position
368 {
369 startPosition = me->GetPosition();
370 if (!IsInBoundary(&startPosition)) // fall back to creature home position
371 {
372 startPosition = me->GetHomePosition();
373 if (!IsInBoundary(&startPosition))
375 }
376 }
377 float spawnZ = startPosition.GetPositionZ() + BOUNDARY_VISUALIZE_SPAWN_HEIGHT;
378
379 bool boundsWarning = false;
380 Q.push({ 0,0 });
381 while (!Q.empty())
382 {
383 coordinate front = Q.front();
384 bool hasOutOfBoundsNeighbor = false;
385 for (coordinate const& off : std::list<coordinate>{ {1, 0}, {0, 1}, {-1, 0}, {0, -1} })
386 {
387 coordinate next(front.first + off.first, front.second + off.second);
389 {
390 boundsWarning = true;
391 continue;
392 }
393 if (alreadyChecked.find(next) == alreadyChecked.end()) // never check a coordinate twice
394 {
395 Position nextPos(startPosition.GetPositionX() + next.first*BOUNDARY_VISUALIZE_STEP_SIZE, startPosition.GetPositionY() + next.second*BOUNDARY_VISUALIZE_STEP_SIZE, startPosition.GetPositionZ());
396 if (IsInBoundary(&nextPos))
397 Q.push(next);
398 else
399 {
400 outOfBounds.insert(next);
401 hasOutOfBoundsNeighbor = true;
402 }
403 alreadyChecked.insert(next);
404 }
405 else if (outOfBounds.find(next) != outOfBounds.end())
406 hasOutOfBoundsNeighbor = true;
407 }
408 if (fill || hasOutOfBoundsNeighbor)
409 {
410 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))
411 {
412 point->SetObjectScale(BOUNDARY_VISUALIZE_CREATURE_SCALE);
413 point->SetUnitFlag(UNIT_FLAG_STUNNED);
414 point->SetImmuneToAll(true);
415 if (!hasOutOfBoundsNeighbor)
416 point->SetUninteractible(true);
417 }
418 }
419
420 Q.pop();
421 }
422 return boundsWarning ? LANG_CREATURE_MOVEMENT_MAYBE_UNBOUNDED : 0;
423}
424
425bool CreatureAI::IsInBoundary(Position const* who) const
426{
427 if (!_boundary)
428 return true;
429
430 if (!who)
431 who = me;
432
434}
435
436bool CreatureAI::IsInBounds(CreatureBoundary const& boundary, Position const* pos)
437{
438 for (AreaBoundary const* areaBoundary : boundary)
439 if (!areaBoundary->IsWithinBoundary(pos))
440 return false;
441
442 return true;
443}
444
445void CreatureAI::SetBoundary(CreatureBoundary const* boundary, bool negateBoundaries /*= false*/)
446{
447 _boundary = boundary;
448 _negateBoundary = negateBoundaries;
450}
451
453{
454 if (IsInBoundary())
455 return true;
456 else
457 {
459 return false;
460 }
461}
462
463Creature* CreatureAI::DoSummon(uint32 entry, Position const& pos, Milliseconds despawnTime, TempSummonType summonType)
464{
465 return me->SummonCreature(entry, pos, summonType, despawnTime);
466}
467
468Creature* CreatureAI::DoSummon(uint32 entry, WorldObject* obj, float radius, Milliseconds despawnTime, TempSummonType summonType)
469{
470 Position pos = obj->GetRandomNearPosition(radius);
471 return me->SummonCreature(entry, pos, summonType, despawnTime);
472}
473
474Creature* CreatureAI::DoSummonFlyer(uint32 entry, WorldObject* obj, float flightZ, float radius, Milliseconds despawnTime, TempSummonType summonType)
475{
476 Position pos = obj->GetRandomNearPosition(radius);
477 pos.m_positionZ += flightZ;
478 return me->SummonCreature(entry, pos, summonType, despawnTime);
479}
@ IN_MILLISECONDS
Definition: Common.h:35
const float BOUNDARY_VISUALIZE_SPAWN_HEIGHT
Definition: CreatureAI.cpp:351
const uint32 BOUNDARY_VISUALIZE_CREATURE
Definition: CreatureAI.cpp:347
AISpellInfoType * GetAISpellInfo(uint32 spellId, Difficulty difficulty)
Definition: CreatureAI.cpp:40
const int32 BOUNDARY_VISUALIZE_FAILSAFE_LIMIT
Definition: CreatureAI.cpp:350
const int8 BOUNDARY_VISUALIZE_STEP_SIZE
Definition: CreatureAI.cpp:349
const float BOUNDARY_VISUALIZE_CREATURE_SCALE
Definition: CreatureAI.cpp:348
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:918
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::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition: Duration.h:24
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition: Duration.h:28
#define ASSERT
Definition: Errors.h:68
@ LANG_CREATURE_MOVEMENT_MAYBE_UNBOUNDED
Definition: Language.h:1242
@ LANG_CREATURE_MOVEMENT_NOT_BOUNDED
Definition: Language.h:1241
@ LANG_CREATURE_NO_INTERIOR_POINT_FOUND
Definition: Language.h:1240
#define TC_LOG_DEBUG(filterType__, message__,...)
Definition: Log.h:179
#define TC_LOG_ERROR(filterType__, message__,...)
Definition: Log.h:188
TempSummonType
Definition: ObjectDefines.h:62
@ TEMPSUMMON_TIMED_DESPAWN
Definition: ObjectDefines.h:65
@ TYPEID_UNIT
Definition: ObjectGuid.h:42
@ TYPEID_PLAYER
Definition: ObjectGuid.h:43
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
#define PET_FOLLOW_DIST
Definition: PetDefines.h:98
SummonTitle
@ AI_REACTION_ALERT
@ SUMMON_CATEGORY_PET
@ SUMMON_CATEGORY_ALLY
@ SUMMON_CATEGORY_WILD
EvadeReason
Definition: UnitAICommon.h:30
@ REACT_PASSIVE
Definition: UnitDefines.h:540
@ REACT_AGGRESSIVE
Definition: UnitDefines.h:542
@ UNIT_FLAG_STUNNED
Definition: UnitDefines.h:185
@ UNIT_STATE_DISTRACTED
Definition: Unit.h:270
@ UNIT_STATE_EVADE
Definition: Unit.h:280
@ UNIT_STATE_CONFUSED
Definition: Unit.h:269
@ UNIT_STATE_FLEEING
Definition: Unit.h:265
@ UNIT_STATE_STUNNED
Definition: Unit.h:261
static bool CanBeginCombat(Unit const *a, Unit const *b)
int32 VisualizeBoundary(Seconds duration, Unit *owner=nullptr, bool fill=false) const
Definition: CreatureAI.cpp:352
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:436
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:474
bool _isEngaged
Definition: CreatureAI.h:256
bool _negateBoundary
Definition: CreatureAI.h:250
void JustEnteredCombat(Unit *) override
Definition: CreatureAI.cpp:212
virtual void EnterEvadeMode(EvadeReason why=EvadeReason::Other)
Definition: CreatureAI.cpp:218
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:298
void OnCharmed(bool isNew) override
Definition: CreatureAI.cpp:62
CreatureAI(Creature *creature, uint32 scriptId={})
Definition: CreatureAI.cpp:45
virtual void JustAppeared()
Definition: CreatureAI.cpp:193
virtual bool CheckInRoom()
Definition: CreatureAI.cpp:452
virtual Optional< QuestGiverStatus > GetDialogStatus(Player const *player)
== Gossip system ================================
Definition: CreatureAI.cpp:342
bool IsInBoundary(Position const *who=nullptr) const
Definition: CreatureAI.cpp:425
bool UpdateVictim()
Definition: CreatureAI.cpp:244
virtual ~CreatureAI()
Definition: CreatureAI.cpp:52
void SetBoundary(CreatureBoundary const *boundary, bool negativeBoundaries=false)
Definition: CreatureAI.cpp:445
void AttackStart(Unit *victim) override
== Triggered Actions Requested ==================
Definition: CreatureAI.cpp:327
void EngagementStart(Unit *who)
Definition: CreatureAI.cpp:274
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:463
void EngagementOver()
Definition: CreatureAI.cpp:286
bool _moveInLOSLocked
Definition: CreatureAI.h:257
void MoveInLineOfSight_Safe(Unit *who)
== Reactions At =================================
Definition: CreatureAI.cpp:113
bool IsTapListNotClearedOnEvade() const
Definition: Creature.h:307
void DoImmediateBoundaryCheck()
Definition: Creature.h:365
void StartDefaultCombatMovement(Unit *victim, Optional< float > range={}, Optional< float > angle={})
Definition: Creature.cpp:2865
bool IsAggroGracePeriodExpired()
Definition: Creature.h:460
bool _IsTargetAcceptable(Unit const *target) const
Definition: Creature.cpp:2644
bool IsCivilian() const
Definition: Creature.h:126
void GetHomePosition(float &x, float &y, float &z, float &ori) const
Definition: Creature.h:388
void SetLastDamagedTime(time_t val)
Definition: Creature.h:442
bool HasReactState(ReactStates state) const
Definition: Creature.h:176
void DoNotReacquireSpellFocusTarget()
Definition: Creature.cpp:3637
bool IsEngaged() const override
Definition: Creature.cpp:3693
void ResetPlayerDamageReq()
Definition: Creature.h:415
void SetCannotReachTarget(bool cannotReach)
Definition: Creature.cpp:3395
void SetTappedBy(Unit const *unit, bool withGroup=true)
Definition: Creature.cpp:1366
void AtEngage(Unit *target) override
Definition: Creature.cpp:3700
void AtDisengage() override
Definition: Creature.cpp:3743
void SetTarget(ObjectGuid const &guid) override
Definition: Creature.cpp:3511
bool IsStateRestoredOnEvade() const
Definition: Creature.h:220
Unit * SelectVictim()
Definition: Creature.cpp:1238
void SendAIReaction(AiReaction reactionType)
Definition: Creature.cpp:2526
bool IsInEvadeMode() const
Definition: Creature.h:217
std::string GetDebugInfo() const override
Definition: Creature.cpp:3798
bool CanStartAttack(Unit const *u, bool force) const
Definition: Creature.cpp:2096
static char const * ToConstant(Enum value)
Definition: SmartEnum.h:120
Definition: Map.h:223
bool IsDungeon() const
Definition: Map.cpp:3216
bool HavePlayers() const
Definition: Map.h:391
bool Instanceable() const
Definition: Map.cpp:3211
PlayerList const & GetPlayers() const
Definition: Map.h:401
void MoveFollow(Unit *target, float dist, Optional< ChaseAngle > angle={}, Optional< Milliseconds > duration={}, bool ignoreTargetWalk=false, MovementSlot slot=MOTION_SLOT_ACTIVE, Optional< Scripting::v2::ActionResultSetter< MovementStopReason > > &&scriptResult={})
void MoveTargetedHome()
void MoveDistract(uint32 time, float orientation)
static ObjectGuid const Empty
Definition: ObjectGuid.h:274
bool IsEmpty() const
Definition: ObjectGuid.h:322
std::string ToString() const
Definition: ObjectGuid.cpp:757
void Clear()
Definition: ObjectGuid.h:289
TypeID GetTypeId() const
Definition: Object.h:209
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:195
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:631
void ClearUnitState(uint32 f)
Definition: Unit.h:740
bool IsCharmed() const
Definition: Unit.h:1227
Vehicle * GetVehicle() const
Definition: Unit.h:1756
void CombatStop(bool includingCast=false, bool mutualPvP=true, bool(*unitFilter)(Unit const *otherUnit)=nullptr)
Definition: Unit.cpp:5918
bool CanHaveThreatList() const
====================== THREAT & COMBAT ====================
Definition: Unit.h:1025
Unit * GetVehicleBase() const
Definition: Unit.cpp:11864
MotionMaster * GetMotionMaster()
Definition: Unit.h:1695
bool IsAlive() const
Definition: Unit.h:1176
TempSummon * ToTempSummon()
Definition: Unit.h:1800
ControlList m_Controlled
Definition: Unit.h:1223
void AddUnitState(uint32 f)
Definition: Unit.h:738
Unit * GetCharmerOrOwner() const
Definition: Unit.h:1212
bool Attack(Unit *victim, bool meleeAttack)
Definition: Unit.cpp:5761
void EngageWithTarget(Unit *who)
Definition: Unit.cpp:8281
virtual float GetFollowAngle() const
Definition: Unit.h:1788
Unit * GetVictim() const
Definition: Unit.h:722
bool HasUnitState(const uint32 f) const
Definition: Unit.h:739
SpellHistory * GetSpellHistory()
Definition: Unit.h:1488
ObjectGuid LastCharmerGUID
Definition: Unit.h:1751
bool AttackStop()
Definition: Unit.cpp:5872
void RemoveAurasOnEvade()
Definition: Unit.cpp:4372
bool IsInCombat() const
Definition: Unit.h:1053
Map * GetMap() const
Definition: Object.h:762
bool IsHostileTo(WorldObject const *target) const
Definition: Object.cpp:2957
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:2124
Position GetRandomNearPosition(float radius)
Definition: Object.cpp:3537
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
auto MapGetValuePtr(M &map, typename M::key_type const &key)
Definition: MapUtils.h:37
constexpr float GetPositionX() const
Definition: Position.h:86
float m_positionZ
Definition: Position.h:65
constexpr float GetPositionY() const
Definition: Position.h:87
float GetAbsoluteAngle(float x, float y) const
Definition: Position.h:135
constexpr void GetPosition(float &x, float &y) const
Definition: Position.h:91
constexpr float GetPositionZ() const
Definition: Position.h:88
EnumFlag< SummonPropertiesFlags > GetFlags() const