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 "Cell.h"
21#include "CellImpl.h"
22#include "Containers.h"
23#include "CommonHelpers.h"
24#include "CreatureAIImpl.h"
25#include "DB2Stores.h"
26#include "GridNotifiers.h"
27#include "GridNotifiersImpl.h"
28#include "InstanceScript.h"
29#include "Log.h"
30#include "Loot.h"
31#include "MotionMaster.h"
32#include "ObjectAccessor.h"
33#include "PhasingHandler.h"
34#include "Spell.h"
35#include "SpellMgr.h"
36#include "TemporarySummon.h"
37
38void SummonList::Summon(Creature const* summon)
39{
40 _storage.push_back(summon->GetGUID());
41}
42
43void SummonList::Despawn(Creature const* summon)
44{
45 _storage.remove(summon->GetGUID());
46}
47
49{
50 for (StorageType::iterator i = _storage.begin(); i != _storage.end();)
51 {
53 ++i;
54 if (summon && summon->IsAIEnabled()
55 && (!entry || summon->GetEntry() == entry))
56 {
57 summon->AI()->DoZoneInCombat();
58 }
59 }
60}
61
63{
64 for (StorageType::iterator i = _storage.begin(); i != _storage.end();)
65 {
67 if (!summon)
68 i = _storage.erase(i);
69 else if (summon->GetEntry() == entry)
70 {
71 i = _storage.erase(i);
72 summon->DespawnOrUnsummon();
73 }
74 else
75 ++i;
76 }
77}
78
80{
81 while (!_storage.empty())
82 {
84 _storage.pop_front();
85 if (summon)
86 summon->DespawnOrUnsummon();
87 }
88}
89
91{
92 for (StorageType::iterator i = _storage.begin(); i != _storage.end();)
93 {
95 ++i;
96 else
97 i = _storage.erase(i);
98 }
99}
100
102{
103 for (ObjectGuid const& guid : _storage)
104 {
105 Creature* summon = ObjectAccessor::GetCreature(*_me, guid);
106 if (summon && summon->GetEntry() == entry)
107 return true;
108 }
109
110 return false;
111}
112
114{
115 if (max)
117
118 for (ObjectGuid const& guid : summons)
119 {
120 Creature* summon = ObjectAccessor::GetCreature(*_me, guid);
121 if (summon && summon->IsAIEnabled())
122 summon->AI()->DoAction(action);
123 }
124}
125
126ScriptedAI::ScriptedAI(Creature* creature, uint32 scriptId) noexcept : CreatureAI(creature, scriptId), _isCombatMovementAllowed(true)
127{
128 _difficulty = me->GetMap()->GetDifficultyID();
129}
130
132{
133 if (!who)
134 return;
135
136 if (me->Attack(who, true))
138}
139
141{
144 else
146}
147
149{
150 // Check if we have a current target
151 UpdateVictim();
152}
153
154void ScriptedAI::DoStartMovement(Unit* victim, float distance, float angle)
155{
156 if (victim)
157 me->StartDefaultCombatMovement(victim, distance, angle);
158}
159
161{
162 if (!victim)
163 return;
164
166}
167
169{
170 if (me->GetVictim())
171 me->AttackStop();
172}
173
174void ScriptedAI::DoCastSpell(Unit* target, SpellInfo const* spellInfo, bool triggered)
175{
176 if (!target || me->IsNonMeleeSpellCast(false))
177 return;
178
179 me->StopMoving();
180 me->CastSpell(target, spellInfo->Id, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE);
181}
182
184{
185 if (!source)
186 return;
187
188 if (!sSoundKitStore.LookupEntry(soundId))
189 {
190 TC_LOG_ERROR("scripts.ai", "ScriptedAI::DoPlaySoundToSet: Invalid soundId {} used in DoPlaySoundToSet (Source: {})", soundId, source->GetGUID().ToString());
191 return;
192 }
193
194 source->PlayDirectSound(soundId);
195}
196
197void ScriptedAI::AddThreat(Unit* victim, float amount, Unit* who)
198{
199 if (!victim)
200 return;
201 if (!who)
202 who = me;
203 who->GetThreatManager().AddThreat(victim, amount, nullptr, true, true);
204}
205
207{
208 if (!victim)
209 return;
210 if (!who)
211 who = me;
212 who->GetThreatManager().ModifyThreatByPercent(victim, pct);
213}
214
216{
217 if (!victim)
218 return;
219 if (!who)
220 who = me;
221 who->GetThreatManager().ResetThreat(victim);
222}
223
225{
226 if (!who)
227 who = me;
229}
230
231float ScriptedAI::GetThreat(Unit const* victim, Unit const* who)
232{
233 if (!victim)
234 return 0.0f;
235 if (!who)
236 who = me;
237 return who->GetThreatManager().GetThreat(victim);
238}
239
240void ScriptedAI::ForceCombatStop(Creature* who, bool reset /*= true*/)
241{
242 if (!who || !who->IsInCombat())
243 return;
244
245 who->CombatStop(true);
248
249 if (reset)
250 {
251 who->LoadCreaturesAddon();
253 who->SetTappedBy(nullptr);
254
256 who->SetLastDamagedTime(0);
257 who->SetCannotReachTarget(false);
258 }
259}
260
261void ScriptedAI::ForceCombatStopForCreatureEntry(uint32 entry, float maxSearchRange /*= 250.0f*/, bool samePhase /*= true*/, bool reset /*= true*/)
262{
263 TC_LOG_DEBUG("scripts.ai", "ScriptedAI::ForceCombatStopForCreatureEntry: called on '{}'. Debug info: {}", me->GetGUID().ToString(), me->GetDebugInfo());
264
265 std::list<Creature*> creatures;
266 Trinity::AllCreaturesOfEntryInRange check(me, entry, maxSearchRange);
268
269 if (!samePhase)
271
272 Cell::VisitGridObjects(me, searcher, maxSearchRange);
273
274 if (!samePhase)
276
277 for (Creature* creature : creatures)
278 ForceCombatStop(creature, reset);
279}
280
281void ScriptedAI::ForceCombatStopForCreatureEntry(std::vector<uint32> creatureEntries, float maxSearchRange /*= 250.0f*/, bool samePhase /*= true*/, bool reset /*= true*/)
282{
283 for (uint32 const entry : creatureEntries)
284 ForceCombatStopForCreatureEntry(entry, maxSearchRange, samePhase, reset);
285}
286
287Creature* ScriptedAI::DoSpawnCreature(uint32 entry, float offsetX, float offsetY, float offsetZ, float angle, uint32 type, Milliseconds despawntime)
288{
289 return me->SummonCreature(entry, me->GetPositionX() + offsetX, me->GetPositionY() + offsetY, me->GetPositionZ() + offsetZ, angle, TempSummonType(type), despawntime);
290}
291
293{
294 return me->HealthBelowPct(pct);
295}
296
298{
299 return me->HealthAbovePct(pct);
300}
301
303{
304 return me->GetMap()->IsLFR();
305}
306
308{
309 return me->GetMap()->IsNormal();
310}
311
313{
314 return me->GetMap()->IsHeroic();
315}
316
318{
319 return me->GetMap()->IsMythic();
320}
321
323{
324 return me->GetMap()->IsMythicPlus();
325}
326
328{
329 return me->GetMap()->IsHeroicOrHigher();
330}
331
333{
334 return me->GetMap()->IsTimewalking();
335}
336
337SpellInfo const* ScriptedAI::SelectSpell(Unit* target, uint32 school, uint32 mechanic, SelectTargetType targets, float rangeMin, float rangeMax, SelectEffect effect)
338{
339 // No target so we can't cast
340 if (!target)
341 return nullptr;
342
343 // Silenced so we can't cast
344 if (me->IsSilenced(school ? SpellSchoolMask(school) : SPELL_SCHOOL_MASK_MAGIC))
345 return nullptr;
346
347 // Using the extended script system we first create a list of viable spells
348 SpellInfo const* apSpell[MAX_CREATURE_SPELLS];
349 memset(apSpell, 0, MAX_CREATURE_SPELLS * sizeof(SpellInfo*));
350
351 uint32 spellCount = 0;
352
353 SpellInfo const* tempSpell = nullptr;
354 AISpellInfoType const* aiSpell = nullptr;
355
356 // Check if each spell is viable(set it to null if not)
357 for (uint32 spell : me->m_spells)
358 {
359 tempSpell = sSpellMgr->GetSpellInfo(spell, me->GetMap()->GetDifficultyID());
360 aiSpell = GetAISpellInfo(spell, me->GetMap()->GetDifficultyID());
361
362 // This spell doesn't exist
363 if (!tempSpell || !aiSpell)
364 continue;
365
366 // Targets and Effects checked first as most used restrictions
367 // Check the spell targets if specified
368 if (targets && !(aiSpell->Targets & (1 << (targets-1))))
369 continue;
370
371 // Check the type of spell if we are looking for a specific spell type
372 if (effect && !(aiSpell->Effects & (1 << (effect-1))))
373 continue;
374
375 // Check for school if specified
376 if (school && (tempSpell->SchoolMask & school) == 0)
377 continue;
378
379 // Check for spell mechanic if specified
380 if (mechanic && tempSpell->Mechanic != mechanic)
381 continue;
382
383 // Continue if we don't have the mana to actually cast this spell
384 bool hasPower = true;
385 for (SpellPowerCost const& cost : tempSpell->CalcPowerCost(me, tempSpell->GetSchoolMask()))
386 {
387 if (cost.Amount > me->GetPower(cost.Power))
388 {
389 hasPower = false;
390 break;
391 }
392 }
393
394 if (!hasPower)
395 continue;
396
397 // Check if the spell meets our range requirements
398 SpellRange spellRange = me->GetSpellMinMaxRangeForTarget(target, tempSpell);
399 if (rangeMin && spellRange.Min < rangeMin)
400 continue;
401 if (rangeMax && spellRange.Max > rangeMax)
402 continue;
403
404 // Check if our target is in range
405 if (me->IsWithinDistInMap(target, spellRange.Min) || !me->IsWithinDistInMap(target, spellRange.Max))
406 continue;
407
408 // All good so lets add it to the spell list
409 apSpell[spellCount] = tempSpell;
410 ++spellCount;
411 }
412
413 // We got our usable spells so now lets randomly pick one
414 if (!spellCount)
415 return nullptr;
416
417 return apSpell[urand(0, spellCount - 1)];
418}
419
420void ScriptedAI::DoTeleportTo(float x, float y, float z, uint32 time)
421{
422 me->Relocate(x, y, z);
423 float speed = me->GetDistance(x, y, z) / ((float)time * 0.001f);
424 me->MonsterMoveWithSpeed(x, y, z, speed);
425}
426
427void ScriptedAI::DoTeleportTo(const float position[4])
428{
429 me->NearTeleportTo(position[0], position[1], position[2], position[3]);
430}
431
432void ScriptedAI::DoTeleportPlayer(Unit* unit, float x, float y, float z, float o)
433{
434 if (!unit)
435 return;
436
437 if (Player* player = unit->ToPlayer())
438 player->TeleportTo(unit->GetMapId(), x, y, z, o, TELE_TO_NOT_LEAVE_COMBAT);
439 else
440 TC_LOG_ERROR("scripts.ai", "ScriptedAI::DoTeleportPlayer: Creature {} Tried to teleport non-player unit ({}) to x: {} y:{} z: {} o: {}. Aborted.",
441 me->GetGUID().ToString(), unit->GetGUID().ToString(), x, y, z, o);
442}
443
444void ScriptedAI::DoTeleportAll(float x, float y, float z, float o)
445{
446 Map* map = me->GetMap();
447 if (!map->IsDungeon())
448 return;
449
450 for (MapReference const& mapref : map->GetPlayers())
451 if (Player* player = mapref.GetSource())
452 if (player->IsAlive())
453 player->TeleportTo(me->GetMapId(), x, y, z, o, TELE_TO_NOT_LEAVE_COMBAT);
454}
455
457{
458 Unit* unit = nullptr;
459 Trinity::MostHPMissingInRange u_check(me, range, minHPDiff);
461 Cell::VisitAllObjects(me, searcher, range);
462
463 return unit;
464}
465
466Unit* ScriptedAI::DoSelectBelowHpPctFriendlyWithEntry(uint32 entry, float range, uint8 minHPDiff, bool excludeSelf)
467{
468 Unit* unit = nullptr;
469 Trinity::FriendlyBelowHpPctEntryInRange u_check(me, entry, range, minHPDiff, excludeSelf);
471 Cell::VisitAllObjects(me, searcher, range);
472
473 return unit;
474}
475
476std::list<Creature*> ScriptedAI::DoFindFriendlyCC(float range)
477{
478 std::list<Creature*> list;
479 Trinity::FriendlyCCedInRange u_check(me, range);
481 Cell::VisitAllObjects(me, searcher, range);
482
483 return list;
484}
485
486std::list<Creature*> ScriptedAI::DoFindFriendlyMissingBuff(float range, uint32 uiSpellid)
487{
488 std::list<Creature*> list;
489 Trinity::FriendlyMissingBuffInRange u_check(me, range, uiSpellid);
491 Cell::VisitAllObjects(me, searcher, range);
492
493 return list;
494}
495
497{
498 Player* player = nullptr;
499
500 Trinity::PlayerAtMinimumRangeAway check(me, minimumRange);
502 Cell::VisitWorldObjects(me, searcher, minimumRange);
503
504 return player;
505}
506
507void ScriptedAI::SetEquipmentSlots(bool loadDefault, int32 mainHand /*= EQUIP_NO_CHANGE*/, int32 offHand /*= EQUIP_NO_CHANGE*/, int32 ranged /*= EQUIP_NO_CHANGE*/)
508{
509 if (loadDefault)
510 {
512 return;
513 }
514
515 if (mainHand >= 0)
516 me->SetVirtualItem(0, uint32(mainHand));
517
518 if (offHand >= 0)
519 me->SetVirtualItem(1, uint32(offHand));
520
521 if (ranged >= 0)
522 me->SetVirtualItem(2, uint32(ranged));
523}
524
525void ScriptedAI::SetCombatMovement(bool allowMovement)
526{
527 _isCombatMovementAllowed = allowMovement;
528}
529
530void ScriptedAI::SetAggressiveStateAfter(Milliseconds timer, Creature* who/* = nullptr*/, bool startCombat/* = true*/, Creature* summoner/* = nullptr*/, StartCombatArgs const& combatArgs/* = { }*/)
531{
532 if (!who)
533 who = me;
534 who->m_Events.AddEvent(new Trinity::Helpers::Events::SetAggresiveStateEvent(who, startCombat, summoner ? summoner->GetGUID() : ObjectGuid::Empty, combatArgs), who->m_Events.CalculateTime(timer));
535}
536
537void ScriptedAI::DoAddEvent(Milliseconds timer, BasicEvent* event, WorldObject* who/* = nullptr*/)
538{
539 if (!who)
540 who = me;
541 who->m_Events.AddEvent(event, who->m_Events.CalculateTime(timer));
542}
543
544// BossAI - for instanced bosses
545BossAI::BossAI(Creature* creature, uint32 bossId) noexcept : ScriptedAI(creature), instance(creature->GetInstanceScript()), summons(creature), _bossId(bossId)
546{
547 if (instance)
548 SetBoundary(instance->GetBossBoundary(bossId));
549 scheduler.SetValidator([this]
550 {
551 return !me->HasUnitState(UNIT_STATE_CASTING);
552 });
553}
554
555BossAI::~BossAI() = default;
556
558{
559 if (!me->IsAlive())
560 return;
561
562 me->ResetLootMode();
563 events.Reset();
568}
569
578
580{
581 me->setActive(false);
582}
583
585{
586 if (instance)
587 {
588 // bosses do not respawn, check only on enter combat
590 {
592 return;
593 }
595 }
596
597 me->setActive(true);
599}
600
602{
603 float x, y, z;
604 me->GetPosition(x, y, z);
605
606 for (auto const& pair : me->GetCombatManager().GetPvECombatRefs())
607 {
608 Unit* target = pair.second->GetOther(me);
609 if (target->IsControlledByPlayer() && !IsInBoundary(target))
610 target->NearTeleportTo(x, y, z, 0);
611 }
612}
613
615{
616 summons.Summon(summon);
617 if (me->IsEngaged())
618 DoZoneInCombat(summon);
619}
620
622{
623 summons.Despawn(summon);
624}
625
627{
628 if (!UpdateVictim())
629 return;
630
631 events.Update(diff);
632
634 return;
635
636 while (uint32 eventId = events.ExecuteEvent())
637 {
638 ExecuteEvent(eventId);
640 return;
641 }
642}
643
644bool BossAI::CanAIAttack(Unit const* target) const
645{
646 return IsInBoundary(target);
647}
648
649void BossAI::_DespawnAtEvade(Seconds delayToRespawn /*= 30s*/, Creature* who /*= nullptr*/)
650{
651 if (delayToRespawn < 2s)
652 {
653 TC_LOG_ERROR("scripts.ai", "BossAI::_DespawnAtEvade: called with delay of {} seconds, defaulting to 2 (me: {})", delayToRespawn.count(), me->GetGUID().ToString());
654 delayToRespawn = 2s;
655 }
656
657 if (!who)
658 who = me;
659
660 if (TempSummon* whoSummon = who->ToTempSummon())
661 {
662 TC_LOG_WARN("scripts.ai", "BossAI::_DespawnAtEvade: called on a temporary summon (who: {})", who->GetGUID().ToString());
663 whoSummon->UnSummon();
664 return;
665 }
666
667 who->DespawnOrUnsummon(0s, delayToRespawn);
668
669 if (instance && who == me)
671}
672
673// WorldBossAI - for non-instanced bosses
674WorldBossAI::WorldBossAI(Creature* creature) noexcept : ScriptedAI(creature), summons(creature) { }
675
676WorldBossAI::~WorldBossAI() = default;
677
679{
680 if (!me->IsAlive())
681 return;
682
683 events.Reset();
685}
686
688{
689 events.Reset();
691}
692
694{
695 Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true);
696 if (target)
697 AttackStart(target);
698}
699
701{
702 summons.Summon(summon);
703 Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true);
704 if (target)
705 summon->AI()->AttackStart(target);
706}
707
712
714{
715 if (!UpdateVictim())
716 return;
717
718 events.Update(diff);
719
721 return;
722
723 while (uint32 eventId = events.ExecuteEvent())
724 {
725 ExecuteEvent(eventId);
727 return;
728 }
729}
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:173
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:182
#define TC_LOG_WARN(filterType__, message__,...)
Definition Log.h:179
@ MOTION_PRIORITY_NORMAL
TempSummonType
@ TELE_TO_NOT_LEAVE_COMBAT
Definition Player.h:911
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:43
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:290
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:315
int8 GetOriginalEquipmentId() const
Definition Creature.h:262
void ResetLootMode()
Definition Creature.h:330
void StartDefaultCombatMovement(Unit *victim, Optional< float > range={}, Optional< float > angle={})
uint32 m_spells[MAX_CREATURE_SPELLS]
Definition Creature.h:332
void SetLastDamagedTime(time_t val)
Definition Creature.h:450
void LoadEquipment(int8 id=1, bool force=false)
void DoNotReacquireSpellFocusTarget()
bool IsEngaged() const override
void ResetPlayerDamageReq()
Definition Creature.h:423
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:235
std::string GetDebugInfo() const override
void Update(uint32 time)
Definition EventMap.h:77
EventId ExecuteEvent()
Definition EventMap.cpp:77
void Reset()
Definition EventMap.cpp:25
void AddEvent(BasicEvent *event, Milliseconds e_time, bool set_addtime=true)
Milliseconds CalculateTime(Milliseconds t_offset) const
virtual bool SetBossState(uint32 id, EncounterState state)
EncounterState GetBossState(uint32 id) const
virtual bool CheckRequiredBosses(uint32, Player const *=nullptr) const
Definition Map.h:227
bool IsDungeon() const
Definition Map.cpp:3303
bool IsNormal() const
Definition Map.cpp:3331
bool IsLFR() const
Definition Map.cpp:3318
bool IsMythicPlus() const
Definition Map.cpp:3375
bool IsTimewalking() const
Definition Map.cpp:3390
bool IsHeroicOrHigher() const
Definition Map.cpp:3380
Difficulty GetDifficultyID() const
Definition Map.h:363
bool IsHeroic() const
Definition Map.cpp:3347
PlayerList const & GetPlayers() const
Definition Map.h:408
bool IsMythic() const
Definition Map.cpp:3368
static ObjectGuid const Empty
Definition ObjectGuid.h:314
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)
uint32 const Id
Definition SpellInfo.h:328
uint32 Mechanic
Definition SpellInfo.h:332
uint32 SchoolMask
Definition SpellInfo.h:419
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:71
Definition Unit.h:647
bool IsNonMeleeSpellCast(bool withDelayed, bool skipChanneled=false, bool skipAutorepeat=false, bool isAutoshoot=false, bool skipInstant=true, bool skipChanneledAllowingActions=false) const
Definition Unit.cpp:3219
void CombatStop(bool includingCast=false, bool mutualPvP=true, bool(*unitFilter)(Unit const *otherUnit)=nullptr)
Definition Unit.cpp:6031
void SetVirtualItem(uint32 slot, uint32 itemId, uint16 appearanceModId=0, uint16 itemVisual=0)
Definition Unit.cpp:14521
ThreatManager & GetThreatManager()
Definition Unit.h:1093
void StopMoving(bool force=false)
Definition Unit.cpp:10753
MotionMaster * GetMotionMaster()
Definition Unit.h:1750
bool IsAlive() const
Definition Unit.h:1205
bool IsSilenced(SpellSchoolMask schoolMask) const
Definition Unit.h:1517
TempSummon * ToTempSummon()
Definition Unit.h:1844
bool IsAIEnabled() const
Definition Unit.h:678
bool Attack(Unit *victim, bool meleeAttack)
Definition Unit.cpp:5872
Unit * GetVictim() const
Definition Unit.h:738
int32 GetPower(Powers power) const
Definition Unit.cpp:10096
bool HealthAbovePct(float pct) const
Definition Unit.h:806
bool HealthBelowPct(float pct) const
Definition Unit.h:804
void NearTeleportTo(TeleportLocation const &target, bool casting=false)
Definition Unit.cpp:13054
bool HasUnitState(const uint32 f) const
Definition Unit.h:755
bool IsControlledByPlayer() const
Definition Unit.h:1234
CombatManager & GetCombatManager()
Definition Unit.h:1053
bool AttackStop()
Definition Unit.cpp:5984
bool IsInCombat() const
Definition Unit.h:1073
void MonsterMoveWithSpeed(float x, float y, float z, float speed, bool generatePath=false, bool forceDestination=false)
Definition Unit.cpp:538
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:2941
Map * GetMap() const
Definition Object.h:411
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2222
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:1403
void setActive(bool isActiveObject)
Definition Object.cpp:274
SpellRange GetSpellMinMaxRangeForTarget(Unit const *target, SpellInfo const *spellInfo) const
Definition Object.cpp:1670
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:499
EventProcessor m_Events
Definition Object.h:561
float GetDistance(WorldObject const *obj) const
Definition Object.cpp:430
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 VisitWorldObjects(WorldObject const *obj, T &visitor, float radius)
Definition CellImpl.h:150
static void VisitAllObjects(WorldObject const *obj, T &visitor, float radius)
Definition CellImpl.h:160
static void VisitGridObjects(WorldObject const *obj, T &visitor, float radius)
Definition CellImpl.h:140
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 DoAddEvent(Milliseconds timer, BasicEvent *event, WorldObject *who=nullptr)
void ResetThreatList(Unit *who=nullptr)
void DoPlaySoundToSet(WorldObject *source, uint32 soundId)
void SetAggressiveStateAfter(Milliseconds timer, Creature *who=nullptr, bool startCombat=true, Creature *summoner=nullptr, StartCombatArgs const &combatArgs={ })
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