TrinityCore
Loading...
Searching...
No Matches
ScriptedCreature.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 "ScriptedCreature.h"
19#include "AreaBoundary.h"
20#include "DB2Stores.h"
21#include "Cell.h"
22#include "CellImpl.h"
23#include "Containers.h"
24#include "CreatureAIImpl.h"
25#include "GridNotifiers.h"
26#include "GridNotifiersImpl.h"
27#include "InstanceScript.h"
28#include "Log.h"
29#include "Loot.h"
30#include "MotionMaster.h"
31#include "ObjectAccessor.h"
32#include "PhasingHandler.h"
33#include "Spell.h"
34#include "SpellMgr.h"
35#include "TemporarySummon.h"
36
37void SummonList::Summon(Creature const* summon)
38{
39 _storage.push_back(summon->GetGUID());
40}
41
42void SummonList::Despawn(Creature const* summon)
43{
44 _storage.remove(summon->GetGUID());
45}
46
48{
49 for (StorageType::iterator i = _storage.begin(); i != _storage.end();)
50 {
52 ++i;
53 if (summon && summon->IsAIEnabled()
54 && (!entry || summon->GetEntry() == entry))
55 {
56 summon->AI()->DoZoneInCombat();
57 }
58 }
59}
60
62{
63 for (StorageType::iterator i = _storage.begin(); i != _storage.end();)
64 {
66 if (!summon)
67 i = _storage.erase(i);
68 else if (summon->GetEntry() == entry)
69 {
70 i = _storage.erase(i);
71 summon->DespawnOrUnsummon();
72 }
73 else
74 ++i;
75 }
76}
77
79{
80 while (!_storage.empty())
81 {
83 _storage.pop_front();
84 if (summon)
85 summon->DespawnOrUnsummon();
86 }
87}
88
90{
91 for (StorageType::iterator i = _storage.begin(); i != _storage.end();)
92 {
94 ++i;
95 else
96 i = _storage.erase(i);
97 }
98}
99
101{
102 for (ObjectGuid const& guid : _storage)
103 {
104 Creature* summon = ObjectAccessor::GetCreature(*_me, guid);
105 if (summon && summon->GetEntry() == entry)
106 return true;
107 }
108
109 return false;
110}
111
113{
114 if (max)
116
117 for (ObjectGuid const& guid : summons)
118 {
119 Creature* summon = ObjectAccessor::GetCreature(*_me, guid);
120 if (summon && summon->IsAIEnabled())
121 summon->AI()->DoAction(action);
122 }
123}
124
125ScriptedAI::ScriptedAI(Creature* creature, uint32 scriptId) noexcept : CreatureAI(creature, scriptId), _isCombatMovementAllowed(true)
126{
127 _difficulty = me->GetMap()->GetDifficultyID();
128}
129
131{
132 if (!who)
133 return;
134
135 if (me->Attack(who, true))
137}
138
140{
143 else
145}
146
148{
149 // Check if we have a current target
150 UpdateVictim();
151}
152
153void ScriptedAI::DoStartMovement(Unit* victim, float distance, float angle)
154{
155 if (victim)
156 me->StartDefaultCombatMovement(victim, distance, angle);
157}
158
160{
161 if (!victim)
162 return;
163
165}
166
168{
169 if (me->GetVictim())
170 me->AttackStop();
171}
172
173void ScriptedAI::DoCastSpell(Unit* target, SpellInfo const* spellInfo, bool triggered)
174{
175 if (!target || me->IsNonMeleeSpellCast(false))
176 return;
177
178 me->StopMoving();
179 me->CastSpell(target, spellInfo->Id, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE);
180}
181
183{
184 if (!source)
185 return;
186
187 if (!sSoundKitStore.LookupEntry(soundId))
188 {
189 TC_LOG_ERROR("scripts.ai", "ScriptedAI::DoPlaySoundToSet: Invalid soundId {} used in DoPlaySoundToSet (Source: {})", soundId, source->GetGUID().ToString());
190 return;
191 }
192
193 source->PlayDirectSound(soundId);
194}
195
196void ScriptedAI::AddThreat(Unit* victim, float amount, Unit* who)
197{
198 if (!victim)
199 return;
200 if (!who)
201 who = me;
202 who->GetThreatManager().AddThreat(victim, amount, nullptr, true, true);
203}
204
206{
207 if (!victim)
208 return;
209 if (!who)
210 who = me;
211 who->GetThreatManager().ModifyThreatByPercent(victim, pct);
212}
213
215{
216 if (!victim)
217 return;
218 if (!who)
219 who = me;
220 who->GetThreatManager().ResetThreat(victim);
221}
222
224{
225 if (!who)
226 who = me;
228}
229
230float ScriptedAI::GetThreat(Unit const* victim, Unit const* who)
231{
232 if (!victim)
233 return 0.0f;
234 if (!who)
235 who = me;
236 return who->GetThreatManager().GetThreat(victim);
237}
238
239void ScriptedAI::ForceCombatStop(Creature* who, bool reset /*= true*/)
240{
241 if (!who || !who->IsInCombat())
242 return;
243
244 who->CombatStop(true);
247
248 if (reset)
249 {
250 who->LoadCreaturesAddon();
252 who->SetTappedBy(nullptr);
253
255 who->SetLastDamagedTime(0);
256 who->SetCannotReachTarget(false);
257 }
258}
259
260void ScriptedAI::ForceCombatStopForCreatureEntry(uint32 entry, float maxSearchRange /*= 250.0f*/, bool samePhase /*= true*/, bool reset /*= true*/)
261{
262 TC_LOG_DEBUG("scripts.ai", "ScriptedAI::ForceCombatStopForCreatureEntry: called on '{}'. Debug info: {}", me->GetGUID().ToString(), me->GetDebugInfo());
263
264 std::list<Creature*> creatures;
265 Trinity::AllCreaturesOfEntryInRange check(me, entry, maxSearchRange);
267
268 if (!samePhase)
270
271 Cell::VisitGridObjects(me, searcher, maxSearchRange);
272
273 if (!samePhase)
275
276 for (Creature* creature : creatures)
277 ForceCombatStop(creature, reset);
278}
279
280void ScriptedAI::ForceCombatStopForCreatureEntry(std::vector<uint32> creatureEntries, float maxSearchRange /*= 250.0f*/, bool samePhase /*= true*/, bool reset /*= true*/)
281{
282 for (uint32 const entry : creatureEntries)
283 ForceCombatStopForCreatureEntry(entry, maxSearchRange, samePhase, reset);
284}
285
286Creature* ScriptedAI::DoSpawnCreature(uint32 entry, float offsetX, float offsetY, float offsetZ, float angle, uint32 type, Milliseconds despawntime)
287{
288 return me->SummonCreature(entry, me->GetPositionX() + offsetX, me->GetPositionY() + offsetY, me->GetPositionZ() + offsetZ, angle, TempSummonType(type), despawntime);
289}
290
292{
293 return me->HealthBelowPct(pct);
294}
295
297{
298 return me->HealthAbovePct(pct);
299}
300
302{
303 return me->GetMap()->IsLFR();
304}
305
307{
308 return me->GetMap()->IsNormal();
309}
310
312{
313 return me->GetMap()->IsHeroic();
314}
315
317{
318 return me->GetMap()->IsMythic();
319}
320
322{
323 return me->GetMap()->IsMythicPlus();
324}
325
327{
328 return me->GetMap()->IsHeroicOrHigher();
329}
330
332{
333 return me->GetMap()->IsTimewalking();
334}
335
336SpellInfo const* ScriptedAI::SelectSpell(Unit* target, uint32 school, uint32 mechanic, SelectTargetType targets, float rangeMin, float rangeMax, SelectEffect effect)
337{
338 // No target so we can't cast
339 if (!target)
340 return nullptr;
341
342 // Silenced so we can't cast
343 if (me->IsSilenced(school ? SpellSchoolMask(school) : SPELL_SCHOOL_MASK_MAGIC))
344 return nullptr;
345
346 // Using the extended script system we first create a list of viable spells
347 SpellInfo const* apSpell[MAX_CREATURE_SPELLS];
348 memset(apSpell, 0, MAX_CREATURE_SPELLS * sizeof(SpellInfo*));
349
350 uint32 spellCount = 0;
351
352 SpellInfo const* tempSpell = nullptr;
353 AISpellInfoType const* aiSpell = nullptr;
354
355 // Check if each spell is viable(set it to null if not)
356 for (uint32 spell : me->m_spells)
358 tempSpell = sSpellMgr->GetSpellInfo(spell, me->GetMap()->GetDifficultyID());
359 aiSpell = GetAISpellInfo(spell, me->GetMap()->GetDifficultyID());
360
361 // This spell doesn't exist
362 if (!tempSpell || !aiSpell)
363 continue;
364
365 // Targets and Effects checked first as most used restrictions
366 // Check the spell targets if specified
367 if (targets && !(aiSpell->Targets & (1 << (targets-1))))
368 continue;
369
370 // Check the type of spell if we are looking for a specific spell type
371 if (effect && !(aiSpell->Effects & (1 << (effect-1))))
372 continue;
373
374 // Check for school if specified
375 if (school && (tempSpell->SchoolMask & school) == 0)
376 continue;
377
378 // Check for spell mechanic if specified
379 if (mechanic && tempSpell->Mechanic != mechanic)
380 continue;
381
382 // Continue if we don't have the mana to actually cast this spell
383 bool hasPower = true;
384 for (SpellPowerCost const& cost : tempSpell->CalcPowerCost(me, tempSpell->GetSchoolMask()))
385 {
386 if (cost.Amount > me->GetPower(cost.Power))
387 {
388 hasPower = false;
389 break;
390 }
391 }
392
393 if (!hasPower)
394 continue;
395
396 // Check if the spell meets our range requirements
397 SpellRange spellRange = me->GetSpellMinMaxRangeForTarget(target, tempSpell);
398 if (rangeMin && spellRange.Min < rangeMin)
399 continue;
400 if (rangeMax && spellRange.Max > rangeMax)
401 continue;
402
403 // Check if our target is in range
404 if (me->IsWithinDistInMap(target, spellRange.Min) || !me->IsWithinDistInMap(target, spellRange.Max))
405 continue;
406
407 // All good so lets add it to the spell list
408 apSpell[spellCount] = tempSpell;
409 ++spellCount;
410 }
411
412 // We got our usable spells so now lets randomly pick one
413 if (!spellCount)
414 return nullptr;
415
416 return apSpell[urand(0, spellCount - 1)];
417}
418
419void ScriptedAI::DoTeleportTo(float x, float y, float z, uint32 time)
420{
421 me->Relocate(x, y, z);
422 float speed = me->GetDistance(x, y, z) / ((float)time * 0.001f);
423 me->MonsterMoveWithSpeed(x, y, z, speed);
424}
425
426void ScriptedAI::DoTeleportTo(const float position[4])
427{
428 me->NearTeleportTo(position[0], position[1], position[2], position[3]);
429}
430
431void ScriptedAI::DoTeleportPlayer(Unit* unit, float x, float y, float z, float o)
432{
433 if (!unit)
434 return;
435
436 if (Player* player = unit->ToPlayer())
437 player->TeleportTo(unit->GetMapId(), x, y, z, o, TELE_TO_NOT_LEAVE_COMBAT);
438 else
439 TC_LOG_ERROR("scripts.ai", "ScriptedAI::DoTeleportPlayer: Creature {} Tried to teleport non-player unit ({}) to x: {} y:{} z: {} o: {}. Aborted.",
440 me->GetGUID().ToString(), unit->GetGUID().ToString(), x, y, z, o);
441}
442
443void ScriptedAI::DoTeleportAll(float x, float y, float z, float o)
444{
445 Map* map = me->GetMap();
446 if (!map->IsDungeon())
447 return;
448
449 for (MapReference const& mapref : map->GetPlayers())
450 if (Player* player = mapref.GetSource())
451 if (player->IsAlive())
452 player->TeleportTo(me->GetMapId(), x, y, z, o, TELE_TO_NOT_LEAVE_COMBAT);
453}
454
456{
457 Unit* unit = nullptr;
458 Trinity::MostHPMissingInRange u_check(me, range, minHPDiff);
460 Cell::VisitAllObjects(me, searcher, range);
461
462 return unit;
463}
464
465Unit* ScriptedAI::DoSelectBelowHpPctFriendlyWithEntry(uint32 entry, float range, uint8 minHPDiff, bool excludeSelf)
466{
467 Unit* unit = nullptr;
468 Trinity::FriendlyBelowHpPctEntryInRange u_check(me, entry, range, minHPDiff, excludeSelf);
470 Cell::VisitAllObjects(me, searcher, range);
471
472 return unit;
473}
474
475std::list<Creature*> ScriptedAI::DoFindFriendlyCC(float range)
476{
477 std::list<Creature*> list;
478 Trinity::FriendlyCCedInRange u_check(me, range);
480 Cell::VisitAllObjects(me, searcher, range);
481
482 return list;
483}
484
485std::list<Creature*> ScriptedAI::DoFindFriendlyMissingBuff(float range, uint32 uiSpellid)
486{
487 std::list<Creature*> list;
488 Trinity::FriendlyMissingBuffInRange u_check(me, range, uiSpellid);
490 Cell::VisitAllObjects(me, searcher, range);
491
492 return list;
493}
494
496{
497 Player* player = nullptr;
498
499 Trinity::PlayerAtMinimumRangeAway check(me, minimumRange);
501 Cell::VisitWorldObjects(me, searcher, minimumRange);
502
503 return player;
504}
505
506void ScriptedAI::SetEquipmentSlots(bool loadDefault, int32 mainHand /*= EQUIP_NO_CHANGE*/, int32 offHand /*= EQUIP_NO_CHANGE*/, int32 ranged /*= EQUIP_NO_CHANGE*/)
507{
508 if (loadDefault)
509 {
511 return;
512 }
513
514 if (mainHand >= 0)
515 me->SetVirtualItem(0, uint32(mainHand));
516
517 if (offHand >= 0)
518 me->SetVirtualItem(1, uint32(offHand));
519
520 if (ranged >= 0)
521 me->SetVirtualItem(2, uint32(ranged));
522}
523
524void ScriptedAI::SetCombatMovement(bool allowMovement)
525{
526 _isCombatMovementAllowed = allowMovement;
527}
528
529// BossAI - for instanced bosses
530BossAI::BossAI(Creature* creature, uint32 bossId) noexcept : ScriptedAI(creature), instance(creature->GetInstanceScript()), summons(creature), _bossId(bossId)
531{
532 if (instance)
533 SetBoundary(instance->GetBossBoundary(bossId));
534 scheduler.SetValidator([this]
535 {
536 return !me->HasUnitState(UNIT_STATE_CASTING);
537 });
538}
539
540BossAI::~BossAI() = default;
541
543{
544 if (!me->IsAlive())
545 return;
546
547 me->ResetLootMode();
548 events.Reset();
553}
554
563
565{
566 me->setActive(false);
567}
568
570{
571 if (instance)
572 {
573 // bosses do not respawn, check only on enter combat
575 {
577 return;
578 }
580 }
581
582 me->setActive(true);
584}
585
587{
588 float x, y, z;
589 me->GetPosition(x, y, z);
590
591 for (auto const& pair : me->GetCombatManager().GetPvECombatRefs())
592 {
593 Unit* target = pair.second->GetOther(me);
594 if (target->IsControlledByPlayer() && !IsInBoundary(target))
595 target->NearTeleportTo(x, y, z, 0);
596 }
597}
598
600{
601 summons.Summon(summon);
602 if (me->IsEngaged())
603 DoZoneInCombat(summon);
604}
605
607{
608 summons.Despawn(summon);
609}
610
612{
613 if (!UpdateVictim())
614 return;
615
616 events.Update(diff);
617
619 return;
620
621 while (uint32 eventId = events.ExecuteEvent())
622 {
623 ExecuteEvent(eventId);
625 return;
626 }
627}
628
629bool BossAI::CanAIAttack(Unit const* target) const
630{
631 return IsInBoundary(target);
632}
633
634void BossAI::_DespawnAtEvade(Seconds delayToRespawn /*= 30s*/, Creature* who /*= nullptr*/)
635{
636 if (delayToRespawn < 2s)
637 {
638 TC_LOG_ERROR("scripts.ai", "BossAI::_DespawnAtEvade: called with delay of {} seconds, defaulting to 2 (me: {})", delayToRespawn.count(), me->GetGUID().ToString());
639 delayToRespawn = 2s;
640 }
641
642 if (!who)
643 who = me;
644
645 if (TempSummon* whoSummon = who->ToTempSummon())
646 {
647 TC_LOG_WARN("scripts.ai", "BossAI::_DespawnAtEvade: called on a temporary summon (who: {})", who->GetGUID().ToString());
648 whoSummon->UnSummon();
649 return;
650 }
651
652 who->DespawnOrUnsummon(0s, delayToRespawn);
653
654 if (instance && who == me)
656}
657
658// WorldBossAI - for non-instanced bosses
659WorldBossAI::WorldBossAI(Creature* creature) noexcept : ScriptedAI(creature), summons(creature) { }
660
661WorldBossAI::~WorldBossAI() = default;
662
664{
665 if (!me->IsAlive())
666 return;
667
668 events.Reset();
670}
671
673{
674 events.Reset();
676}
677
679{
680 Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true);
681 if (target)
682 AttackStart(target);
683}
684
686{
687 summons.Summon(summon);
688 Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true);
689 if (target)
690 summon->AI()->AttackStart(target);
691}
692
697
699{
700 if (!UpdateVictim())
701 return;
702
703 events.Update(diff);
704
706 return;
707
708 while (uint32 eventId = events.ExecuteEvent())
709 {
710 ExecuteEvent(eventId);
712 return;
713 }
714}
SelectEffect
SelectTargetType
AISpellInfoType * GetAISpellInfo(uint32 spellId, Difficulty difficulty)
const uint32 MAX_CREATURE_SPELLS
DB2Storage< SoundKitEntry > sSoundKitStore("SoundKit.db2", &SoundKitLoadInfo::Instance)
uint8_t uint8
Definition Define.h:156
int32_t int32
Definition Define.h:150
uint16_t uint16
Definition Define.h:155
uint32_t uint32
Definition Define.h:154
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition Duration.h:24
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition Duration.h:28
@ IN_PROGRESS
@ FAIL
@ DONE
@ NOT_STARTED
#define TC_LOG_DEBUG(filterType__, message__,...)
Definition Log.h:181
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:190
#define TC_LOG_WARN(filterType__, message__,...)
Definition Log.h:187
@ MOTION_PRIORITY_NORMAL
TempSummonType
@ TELE_TO_NOT_LEAVE_COMBAT
Definition Player.h:925
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:42
SpellSchoolMask
@ SPELL_SCHOOL_MASK_MAGIC
@ TRIGGERED_FULL_MASK
Used when doing CastSpell with triggered == true.
@ TRIGGERED_NONE
Not triggered.
#define sSpellMgr
Definition SpellMgr.h:812
@ UNIT_STATE_CASTING
Definition Unit.h:276
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
InstanceScript *const instance
void _JustReachedHome()
void _JustEngagedWith(Unit *who)
void TeleportCheaters()
BossAI(Creature *creature, uint32 bossId) noexcept
void JustSummoned(Creature *summon) override
void _DespawnAtEvade(Seconds delayToRespawn=30s, Creature *who=nullptr)
bool CanAIAttack(Unit const *target) const override
uint32 const _bossId
virtual void UpdateAI(uint32 diff) override
virtual void ExecuteEvent(uint32)
TaskScheduler scheduler
SummonList summons
EventMap events
void SummonedCreatureDespawn(Creature *summon) override
virtual void ScheduleTasks()
virtual ~BossAI()
std::unordered_map< ObjectGuid, CombatReference * > const & GetPvECombatRefs() const
void DoZoneInCombat()
Definition CreatureAI.h:169
virtual void EnterEvadeMode(EvadeReason why=EvadeReason::Other)
bool IsInBoundary(Position const *who=nullptr) const
bool UpdateVictim()
void AttackStart(Unit *victim) override
== Triggered Actions Requested ==================
Creature *const me
Definition CreatureAI.h:63
bool LoadCreaturesAddon()
bool IsTapListNotClearedOnEvade() const
Definition Creature.h:307
int8 GetOriginalEquipmentId() const
Definition Creature.h:254
void ResetLootMode()
Definition Creature.h:322
void StartDefaultCombatMovement(Unit *victim, Optional< float > range={}, Optional< float > angle={})
uint32 m_spells[MAX_CREATURE_SPELLS]
Definition Creature.h:324
void SetLastDamagedTime(time_t val)
Definition Creature.h:442
void LoadEquipment(int8 id=1, bool force=false)
void DoNotReacquireSpellFocusTarget()
bool IsEngaged() const override
void ResetPlayerDamageReq()
Definition Creature.h:415
void SetCannotReachTarget(bool cannotReach)
void SetTappedBy(Unit const *unit, bool withGroup=true)
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
CreatureAI * AI() const
Definition Creature.h:228
std::string GetDebugInfo() const override
uint32 ExecuteEvent()
Definition EventMap.cpp:77
void Update(uint32 time)
Definition EventMap.h:61
void Reset()
Definition EventMap.cpp:25
virtual bool SetBossState(uint32 id, EncounterState state)
EncounterState GetBossState(uint32 id) const
virtual bool CheckRequiredBosses(uint32, Player const *=nullptr) const
Definition Map.h:225
bool IsDungeon() const
Definition Map.cpp:3267
bool IsNormal() const
Definition Map.cpp:3295
bool IsLFR() const
Definition Map.cpp:3282
bool IsMythicPlus() const
Definition Map.cpp:3339
bool IsTimewalking() const
Definition Map.cpp:3354
bool IsHeroicOrHigher() const
Definition Map.cpp:3344
Difficulty GetDifficultyID() const
Definition Map.h:360
bool IsHeroic() const
Definition Map.cpp:3311
PlayerList const & GetPlayers() const
Definition Map.h:403
bool IsMythic() const
Definition Map.cpp:3332
std::string ToString() const
Player * ToPlayer()
Definition Object.h:126
uint32 GetEntry() const
Definition Object.h:89
static void SetAlwaysVisible(WorldObject *object, bool apply, bool updateVisibility)
Optional< SpellPowerCost > CalcPowerCost(Powers powerType, bool optionalCost, WorldObject const *caster, SpellSchoolMask schoolMask, Spell *spell=nullptr) const
uint32 const Id
Definition SpellInfo.h:328
uint32 Mechanic
Definition SpellInfo.h:332
uint32 SchoolMask
Definition SpellInfo.h:419
SpellSchoolMask GetSchoolMask() const
Creature * _me
bool HasEntry(uint32 entry) const
void Despawn(Creature const *summon)
void DespawnEntry(uint32 entry)
void RemoveNotExisting()
void Summon(Creature const *summon)
void DoZoneInCombat(uint32 entry=0)
GuidList StorageType
void DoActionImpl(int32 action, StorageType &summons, uint16 max)
StorageType _storage
TaskScheduler & CancelAll()
void ResetThreat(Unit *target)
void ModifyThreatByPercent(Unit *target, float percent)
void AddThreat(Unit *target, float amount, SpellInfo const *spell=nullptr, bool ignoreModifiers=false, bool ignoreRedirects=false)
== AFFECT MY THREAT LIST ==
float GetThreat(Unit const *who, bool includeOffline=false) const
virtual void DoAction(int32 param)
Definition UnitAI.h:73
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:79
Definition Unit.h:635
void CombatStop(bool includingCast=false, bool mutualPvP=true, bool(*unitFilter)(Unit const *otherUnit)=nullptr)
Definition Unit.cpp:6012
void SetVirtualItem(uint32 slot, uint32 itemId, uint16 appearanceModId=0, uint16 itemVisual=0)
Definition Unit.cpp:14374
ThreatManager & GetThreatManager()
Definition Unit.h:1078
MotionMaster * GetMotionMaster()
Definition Unit.h:1723
bool IsNonMeleeSpellCast(bool withDelayed, bool skipChanneled=false, bool skipAutorepeat=false, bool isAutoshoot=false, bool skipInstant=true) const
Definition Unit.cpp:3201
bool IsAlive() const
Definition Unit.h:1185
void StopMoving()
Definition Unit.cpp:10680
bool IsSilenced(SpellSchoolMask schoolMask) const
Definition Unit.h:1494
TempSummon * ToTempSummon()
Definition Unit.h:1828
bool IsAIEnabled() const
Definition Unit.h:666
bool Attack(Unit *victim, bool meleeAttack)
Definition Unit.cpp:5853
Unit * GetVictim() const
Definition Unit.h:726
int32 GetPower(Powers power) const
Definition Unit.cpp:10028
bool HealthAbovePct(float pct) const
Definition Unit.h:794
bool HealthBelowPct(float pct) const
Definition Unit.h:792
void NearTeleportTo(TeleportLocation const &target, bool casting=false)
Definition Unit.cpp:12958
bool HasUnitState(const uint32 f) const
Definition Unit.h:743
bool IsControlledByPlayer() const
Definition Unit.h:1214
CombatManager & GetCombatManager()
Definition Unit.h:1038
bool AttackStop()
Definition Unit.cpp:5965
bool IsInCombat() const
Definition Unit.h:1058
void MonsterMoveWithSpeed(float x, float y, float z, float speed, bool generatePath=false, bool forceDestination=false)
Definition Unit.cpp:533
virtual ~WorldBossAI()
virtual void UpdateAI(uint32 diff) override
virtual void ExecuteEvent(uint32)
void JustSummoned(Creature *summon) override
WorldBossAI(Creature *creature) noexcept
SummonList summons
void SummonedCreatureDespawn(Creature *summon) override
constexpr uint32 GetMapId() const
Definition Position.h:216
void PlayDirectSound(uint32 soundId, Player const *target=nullptr, uint32 broadcastTextId=0) const
Definition Object.cpp:2938
Map * GetMap() const
Definition Object.h:411
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2217
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:1398
void setActive(bool isActiveObject)
Definition Object.cpp:276
SpellRange GetSpellMinMaxRangeForTarget(Unit const *target, SpellInfo const *spellInfo) const
Definition Object.cpp:1665
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:501
float GetDistance(WorldObject const *obj) const
Definition Object.cpp:432
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
void RandomResize(C &container, std::size_t requestedSize)
Definition Containers.h:67
static void VisitAllObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition CellImpl.h:203
static void VisitGridObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition CellImpl.h:179
static void VisitWorldObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition CellImpl.h:191
constexpr float GetPositionX() const
Definition Position.h:87
constexpr float GetPositionY() const
Definition Position.h:88
constexpr void GetPosition(float &x, float &y) const
Definition Position.h:92
constexpr void Relocate(float x, float y)
Definition Position.h:74
constexpr float GetPositionZ() const
Definition Position.h:89
bool IsHeroic() const
bool IsNormal() const
void DoStartNoMovement(Unit *target)
bool IsMythic() const
void SetEquipmentSlots(bool loadDefault, int32 mainHand=EQUIP_NO_CHANGE, int32 offHand=EQUIP_NO_CHANGE, int32 ranged=EQUIP_NO_CHANGE)
void ForceCombatStop(Creature *who, bool reset=true)
void AttackStart(Unit *) override
== Triggered Actions Requested ==================
void SetCombatMovement(bool allowMovement)
bool IsCombatMovementAllowed() const
bool HealthAbovePct(uint32 pct) const
Unit * DoSelectLowestHpFriendly(float range, uint32 minHPDiff=1)
bool IsTimewalking() const
ScriptedAI(Creature *creature, uint32 scriptId=0) noexcept
void DoTeleportTo(float x, float y, float z, uint32 time=0)
float GetThreat(Unit const *victim, Unit const *who=nullptr)
Player * GetPlayerAtMinimumRange(float minRange)
bool IsLFR() const
bool _isCombatMovementAllowed
bool IsMythicPlus() const
void DoTeleportPlayer(Unit *unit, float x, float y, float z, float o)
void DoTeleportAll(float x, float y, float z, float o)
bool HealthBelowPct(uint32 pct) const
SpellInfo const * SelectSpell(Unit *target, uint32 school, uint32 mechanic, SelectTargetType targets, float rangeMin, float rangeMax, SelectEffect effect)
void DoCastSpell(Unit *target, SpellInfo const *spellInfo, bool triggered=false)
void ModifyThreatByPercent(Unit *victim, int32 pct, Unit *who=nullptr)
void AttackStartNoMove(Unit *target)
Creature * DoSpawnCreature(uint32 entry, float offsetX, float offsetY, float offsetZ, float angle, uint32 type, Milliseconds despawntime)
std::list< Creature * > DoFindFriendlyMissingBuff(float range, uint32 spellId)
void ResetThreat(Unit *victim, Unit *who=nullptr)
bool IsHeroicOrHigher() const
void ForceCombatStopForCreatureEntry(uint32 entry, float maxSearchRange=250.0f, bool samePhase=true, bool reset=true)
std::list< Creature * > DoFindFriendlyCC(float range)
Unit * DoSelectBelowHpPctFriendlyWithEntry(uint32 entry, float range, uint8 hpPct=1, bool excludeSelf=true)
void ResetThreatList(Unit *who=nullptr)
void DoPlaySoundToSet(WorldObject *source, uint32 soundId)
void AddThreat(Unit *victim, float amount, Unit *who=nullptr)
void DoStartMovement(Unit *target, float distance=0.0f, float angle=0.0f)
virtual void UpdateAI(uint32 diff) override