TrinityCore
boss_anubarak.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 "ScriptMgr.h"
19#include "AreaBoundary.h"
20#include "azjol_nerub.h"
21#include "Containers.h"
22#include "GameObject.h"
23#include "InstanceScript.h"
24#include "MotionMaster.h"
25#include "ObjectAccessor.h"
26#include "PassiveAI.h"
27#include "ScriptedCreature.h"
28#include "SpellInfo.h"
29#include "SpellScript.h"
30#include "TemporarySummon.h"
31
33{
34 SPELL_EMERGE = 53500,
40 SPELL_POUND = 59433,
44
49
50 SPELL_DART = 59349,
54 SPELL_POISON_BOLT = 53617
55};
56
58{
60};
61
63{
69 SAY_INTRO = 5
70};
71
73{
78 EVENT_SUBMERGE, // use event for this so we don't submerge mid-cast
84};
85
87{
90};
91
92enum Misc
93{
95};
96
98{
102
104{
108
110{
113
114struct boss_anub_arak : public BossAI
115{
117
118 void Reset() override
119 {
122 me->SetUninteractible(false);
123 _nextSubmerge = 75;
124 _petCount = 0;
125 }
126
127 bool CanAIAttack(Unit const* /*who*/) const override { return true; } // do not check boundary here
128
129 void JustEngagedWith(Unit* who) override
130 {
132
134 door->SetGoState(GO_STATE_ACTIVE); // open door for now
136 door2->SetGoState(GO_STATE_ACTIVE);
137
140
146
147 // set up world triggers
148 std::list<TempSummon*> summoned;
150 if (summoned.empty()) // something went wrong
151 {
153 return;
154 }
155 _guardianTrigger = (*summoned.begin())->GetGUID();
156
158 _assassinTrigger = trigger->GetGUID();
159 else
160 {
162 return;
163 }
164 }
165
166 void EnterEvadeMode(EvadeReason /*why*/) override
167 {
170 }
171
172 void UpdateAI(uint32 diff) override
173 {
174 if (!UpdateVictim())
175 return;
176
177 events.Update(diff);
178
180 return;
181
182 while (uint32 eventId = events.ExecuteEvent())
183 {
184 switch (eventId)
185 {
186 case EVENT_CLOSE_DOOR:
188 door->SetGoState(GO_STATE_READY);
190 door2->SetGoState(GO_STATE_READY);
191 break;
192 case EVENT_POUND:
194 events.Repeat(26s, 32s);
195 break;
199 events.Repeat(25s, 28s);
200 break;
203 events.Repeat(24s, 27s);
204 break;
205 case EVENT_IMPALE:
207 DoCast(impaleTarget, SPELL_IMPALE_DAMAGE, true);
208 break;
209 case EVENT_SUBMERGE:
212 break;
213 case EVENT_DARTER:
214 {
215 std::list<Creature*> triggers;
217 if (!triggers.empty())
218 {
220 trigger->CastSpell(trigger, SPELL_SUMMON_DARTER, true);
221
222 events.Repeat(11s);
223 }
224 else
226 break;
227 }
228 case EVENT_ASSASSIN:
230 {
231 trigger->CastSpell(trigger, SPELL_SUMMON_ASSASSIN, true);
232 trigger->CastSpell(trigger, SPELL_SUMMON_ASSASSIN, true);
233 if (_assassinCount > 2)
234 {
235 _assassinCount -= 2;
236 events.Repeat(20s);
237 }
238 else
239 _assassinCount = 0;
240 }
241 else // something went wrong
243 break;
244 case EVENT_GUARDIAN:
246 {
247 trigger->CastSpell(trigger, SPELL_SUMMON_GUARDIAN, true);
248 trigger->CastSpell(trigger, SPELL_SUMMON_GUARDIAN, true);
249 if (_guardianCount > 2)
250 {
251 _guardianCount -= 2;
252 events.Repeat(20s);
253 }
254 else
255 _guardianCount = 0;
256 }
257 else
259 break;
260 case EVENT_VENOMANCER:
262 {
263 trigger->CastSpell(trigger, SPELL_SUMMON_VENOMANCER, true);
264 trigger->CastSpell(trigger, SPELL_SUMMON_VENOMANCER, true);
265 if (_venomancerCount > 2)
266 {
267 _venomancerCount -= 2;
268 events.Repeat(20s);
269 }
270 else
272 }
273 else
275 break;
276 default:
277 break;
278 }
279
281 return;
282 }
283 }
284
285 void JustDied(Unit* /*killer*/) override
286 {
287 _JustDied();
289 }
290
291 void KilledUnit(Unit* victim) override
292 {
293 if (victim->GetTypeId() == TYPEID_PLAYER)
294 Talk(SAY_SLAY);
295 }
296
297 void SetGUID(ObjectGuid const& guid, int32 id) override
298 {
299 switch (id)
300 {
301 case GUID_TYPE_PET:
302 {
303 if (Creature* creature = ObjectAccessor::GetCreature(*me, guid))
304 JustSummoned(creature);
305 else // something has gone horribly wrong
307 break;
308 }
309 case GUID_TYPE_IMPALE:
310 _impaleTarget = guid;
312 break;
313 }
314 }
315
316 void DoAction(int32 action) override
317 {
318 switch (action)
319 {
320 case ACTION_PET_DIED:
321 if (!_petCount) // underflow check - something has gone horribly wrong
322 {
324 return;
325 }
326 if (!--_petCount) // last pet died, emerge
327 {
331 me->SetUninteractible(false);
337 }
338 break;
339 case ACTION_PET_EVADE:
341 break;
342 }
343 }
344
345 void DamageTaken(Unit* /*source*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
346 {
348 damage = 0;
349 else
351 {
354 }
355 }
356
357 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
358 {
359 if (spellInfo->Id == SPELL_SUBMERGE)
360 {
362 me->SetUninteractible(true);
365
367 switch (_nextSubmerge)
368 {
369 case 50: // first submerge phase
370 _assassinCount = 4;
371 _guardianCount = 2;
373 break;
374 case 25: // second submerge phase
375 _assassinCount = 6;
376 _guardianCount = 2;
378 break;
379 case 0: // third submerge phase
380 _assassinCount = 6;
381 _guardianCount = 2;
384 break;
385 }
387 if (_assassinCount)
389 if (_guardianCount)
393 }
394 }
395
396 private:
405};
406
408{
409 public:
410 npc_anubarak_pet_template(Creature* creature, bool isLarge) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _isLarge(isLarge) { }
411
412 void InitializeAI() override
413 {
416 anubarak->AI()->SetGUID(me->GetGUID(), GUID_TYPE_PET);
417 else
419 }
420
421 void JustDied(Unit* killer) override
422 {
423 ScriptedAI::JustDied(killer);
424 if (_isLarge)
426 anubarak->AI()->DoAction(ACTION_PET_DIED);
427 }
428
429 void EnterEvadeMode(EvadeReason /*why*/) override
430 {
432 anubarak->AI()->DoAction(ACTION_PET_EVADE);
433 else
435 }
436
437 protected:
439 private:
440 bool const _isLarge;
441};
442
444{
446
447 void InitializeAI() override
448 {
451 }
452};
453
455{
457
459 {
460 static float DISTANCE_MIN = 10.0f;
461 static float DISTANCE_MAX = 30.0f;
462 double angle = rand_norm() * 2.0 * M_PI;
463 return { anubarak->GetPositionX() + (float)(frand(DISTANCE_MIN, DISTANCE_MAX)*std::sin(angle)), anubarak->GetPositionY() + (float)(frand(DISTANCE_MIN, DISTANCE_MAX)*std::cos(angle)), anubarak->GetPositionZ() };
464 }
465
466 void InitializeAI() override
467 {
471 {
472 Position jumpTo;
473 do
474 jumpTo = GetRandomPositionAround(anubarak);
475 while (!CreatureAI::IsInBounds(*boundary, &jumpTo));
476 me->GetMotionMaster()->MoveJump(jumpTo, 40.0f, 40.0f);
478 }
479 }
480
481 void Reset() override
482 {
484 }
485
486 void JustEngagedWith(Unit* /*who*/) override
487 {
488 _scheduler.Schedule(6s, [this](TaskContext task)
489 {
490 if (me->GetVictim() && me->GetVictim()->isInBack(me))
492
493 task.Repeat();
494 });
495 }
496
497 void UpdateAI(uint32 diff) override
498 {
499 if (!UpdateVictim())
500 return;
501
502 _scheduler.Update(diff);
503 }
504
505 void MovementInform(uint32 /*type*/, uint32 id) override
506 {
507 if (id == EVENT_JUMP)
508 {
511 }
512 }
513
514private:
516};
517
519{
521
522 void Reset() override
523 {
525 }
526
527 void JustEngagedWith(Unit* /*who*/) override
528 {
529 _scheduler.Schedule(6s, [this](TaskContext task)
530 {
532 task.Repeat(12s);
533 });
534 }
535
536 void UpdateAI(uint32 diff) override
537 {
538 if (!UpdateVictim())
539 return;
540
541 _scheduler.Update(diff);
542 }
543
544private:
546};
547
549{
551
552 void Reset() override
553 {
555 }
556
557 void JustEngagedWith(Unit* /*who*/) override
558 {
559 _scheduler.Schedule(5s, [this](TaskContext task)
560 {
562 task.Repeat(2s, 3s);
563 });
564 }
565
566 void UpdateAI(uint32 diff) override
567 {
568 if (!UpdateVictim())
569 return;
570
571 _scheduler.Update(diff);
572 }
573
574private:
576};
577
579{
581
582 void InitializeAI() override
583 {
585 {
588 anubarak->AI()->SetGUID(me->GetGUID(), GUID_TYPE_IMPALE);
589 }
590 else
592 }
593};
594
595// 53472, 59433 - Pound
597{
598 bool Validate(SpellInfo const* /*spell*/) override
599 {
601 }
602
603 void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
604 {
605 if (Unit* target = GetTarget())
606 GetCaster()->CastSpell(target, SPELL_POUND_DAMAGE, true);
607 }
608
609 void Register() override
610 {
612 }
613};
614
615// 53520 - Carrion Beetles
617{
618 bool Validate(SpellInfo const* /*spell*/) override
619 {
621 }
622
623 void HandlePeriodic(AuraEffect const* /*eff*/)
624 {
627 }
628
629 void Register() override
630 {
632 }
633};
634
636{
638
644
647}
Actions
#define M_PI
Definition: Common.h:115
std::vector< AreaBoundary const * > CreatureBoundary
Definition: CreatureAI.h:37
uint8_t uint8
Definition: Define.h:144
int32_t int32
Definition: Define.h:138
uint32_t uint32
Definition: Define.h:142
@ TEMPSUMMON_MANUAL_DESPAWN
Definition: ObjectDefines.h:70
@ TYPEID_PLAYER
Definition: ObjectGuid.h:41
Spells
Definition: PlayerAI.cpp:32
float frand(float min, float max)
Definition: Random.cpp:55
float rand_norm()
Definition: Random.cpp:75
#define RegisterSpellScript(spell_script)
Definition: ScriptMgr.h:1369
@ EFFECT_0
Definition: SharedDefines.h:30
@ EFFECT_2
Definition: SharedDefines.h:32
@ EVENT_JUMP
@ GO_STATE_READY
@ GO_STATE_ACTIVE
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
@ SPELL_AURA_FLY
@ SPELL_AURA_PERIODIC_DUMMY
#define AuraEffectPeriodicFn(F, I, N)
Definition: SpellScript.h:2046
#define AuraEffectApplyFn(F, I, N, M)
Definition: SpellScript.h:2029
EvadeReason
Definition: UnitAICommon.h:30
DamageEffectType
Definition: UnitDefines.h:131
@ UNIT_FLAG_NON_ATTACKABLE
Definition: UnitDefines.h:145
@ UNIT_STATE_CASTING
Definition: Unit.h:270
@ DATA_ANUBARAK
Definition: azjol_nerub.h:33
@ DATA_ANUBARAK_WALL_2
Definition: azjol_nerub.h:40
@ DATA_ANUBARAK_WALL
Definition: azjol_nerub.h:39
#define RegisterAzjolNerubCreatureAI(ai_name)
Definition: azjol_nerub.h:75
@ SUMMON_GROUP_WORLD_TRIGGER_GUARDIAN
@ ACTION_PET_DIED
@ ACTION_PET_EVADE
@ NPC_WORLD_TRIGGER
@ ACHIEV_GOTTA_GO_START_EVENT
@ SAY_DEATH
@ SAY_AGGRO
@ SAY_SLAY
@ SAY_SUBMERGE
@ SAY_LOCUST
@ SAY_INTRO
@ SPELL_DART
@ SPELL_LEECHING_SWARM
@ SPELL_SUMMON_GUARDIAN
@ SPELL_EMERGE
@ SPELL_IMPALE_AURA
@ SPELL_SUMMON_ASSASSIN
@ SPELL_BACKSTAB
@ SPELL_POISON_BOLT
@ SPELL_SUMMON_VENOMANCER
@ SPELL_CARRION_BEETLE
@ SPELL_POUND_DAMAGE
@ SPELL_CARRION_BEETLES
@ SPELL_SUNDER_ARMOR
@ SPELL_IMPALE_VISUAL
@ SPELL_ASSASSIN_VISUAL
@ SPELL_SUBMERGE
@ SPELL_POUND
@ SPELL_IMPALE_DAMAGE
@ SPELL_SUMMON_DARTER
@ PHASE_EMERGE
@ PHASE_SUBMERGE
void AddSC_boss_anub_arak()
GUIDTypes
@ GUID_TYPE_PET
@ GUID_TYPE_IMPALE
@ EVENT_CARRION_BEETLES
@ EVENT_ASSASSIN
@ EVENT_DARTER
@ EVENT_GUARDIAN
@ EVENT_CLOSE_DOOR
@ EVENT_VENOMANCER
@ EVENT_SUBMERGE
@ EVENT_IMPALE
@ EVENT_LEECHING_SWARM
@ EVENT_POUND
SummonGroups
Yells
HookList< EffectPeriodicHandler > OnEffectPeriodic
Definition: SpellScript.h:2045
HookList< EffectApplyHandler > AfterEffectApply
Definition: SpellScript.h:2028
Unit * GetCaster() const
Unit * GetTarget() const
InstanceScript *const instance
void JustEngagedWith(Unit *who) override
void JustSummoned(Creature *summon) override
void _DespawnAtEvade(Seconds delayToRespawn=30s, Creature *who=nullptr)
SummonList summons
EventMap events
void Reset() override
void _JustDied()
void DoZoneInCombat()
Definition: CreatureAI.h:161
static bool IsInBounds(CreatureBoundary const &boundary, Position const *who)
Definition: CreatureAI.cpp:437
virtual void JustDied(Unit *)
Definition: CreatureAI.h:105
void Talk(uint8 id, WorldObject const *whisperTarget=nullptr)
Definition: CreatureAI.cpp:56
bool UpdateVictim()
Definition: CreatureAI.cpp:245
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 DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
Definition: Creature.cpp:2415
uint32 ExecuteEvent()
Definition: EventMap.cpp:73
void Update(uint32 time)
Definition: EventMap.h:56
void Repeat(Milliseconds time)
Definition: EventMap.cpp:63
void ScheduleEvent(uint32 eventId, Milliseconds time, uint32 group=0, uint8 phase=0)
Definition: EventMap.cpp:36
void SetPhase(uint8 phase)
Definition: EventMap.cpp:28
void RescheduleEvent(uint32 eventId, Milliseconds time, uint32 group=0, uint8 phase=0)
Definition: EventMap.cpp:52
Creature * GetCreature(uint32 type)
CreatureBoundary const * GetBossBoundary(uint32 id) const
void TriggerGameEvent(uint32 gameEventId, WorldObject *source=nullptr, WorldObject *target=nullptr) override
GameObject * GetGameObject(uint32 type)
void MoveJump(Position const &pos, float speedXY, float speedZ, uint32 id=EVENT_JUMP, bool hasOrientation=false, JumpArrivalCastArgs const *arrivalCast=nullptr, Movement::SpellEffectExtraData const *spellEffectExtraData=nullptr)
TypeID GetTypeId() const
Definition: Object.h:173
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
uint32 const Id
Definition: SpellInfo.h:325
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
Definition: SpellScript.h:162
TaskContext & Repeat(std::chrono::duration< Rep, Period > duration)
TaskScheduler & CancelAll()
TaskScheduler & Schedule(std::chrono::duration< Rep, Period > time, task_handler_t task)
TaskScheduler & Update(success_t const &callback=nullptr)
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.h:159
virtual void InitializeAI()
Definition: UnitAI.cpp:43
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.cpp:180
virtual ObjectGuid GetGUID(int32=0) const
Definition: UnitAI.h:76
SpellCastResult DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.h:161
SpellCastResult DoCast(uint32 spellId)
Definition: UnitAI.cpp:89
Definition: Unit.h:627
MotionMaster * GetMotionMaster()
Definition: Unit.h:1652
void SetUninteractible(bool apply)
Definition: Unit.cpp:8147
Unit * GetVictim() const
Definition: Unit.h:715
bool HasUnitState(const uint32 f) const
Definition: Unit.h:732
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition: Unit.cpp:4664
bool HealthBelowPctDamaged(int32 pct, uint32 damage) const
Definition: Unit.h:781
void SetUnitFlag(UnitFlags flags)
Definition: Unit.h:833
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3831
void RemoveUnitFlag(UnitFlags flags)
Definition: Unit.h:834
InstanceScript * GetInstanceScript() const
Definition: Object.cpp:1042
void GetCreatureListWithEntryInGrid(Container &creatureContainer, uint32 entry, float maxSearchRange=250.0f) const
Definition: Object.cpp:3312
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition: Object.cpp:2896
bool isInBack(WorldObject const *target, float arc=float(M_PI)) const
Definition: Object.cpp:1326
void SummonCreatureGroup(uint8 group, std::list< TempSummon * > *list=nullptr)
Definition: Object.cpp:2131
void JustDied(Unit *killer) override
void InitializeAI() override
npc_anubarak_pet_template(Creature *creature, bool isLarge)
InstanceScript * _instance
void EnterEvadeMode(EvadeReason) override
bool Validate(SpellInfo const *) override
void HandlePeriodic(AuraEffect const *)
bool Validate(SpellInfo const *) override
void Register() override
void AfterApply(AuraEffect const *, AuraEffectHandleModes)
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
auto SelectRandomContainerElement(C const &container) -> typename std::add_const< decltype(*std::begin(container))>::type &
Definition: Containers.h:109
constexpr float GetPositionX() const
Definition: Position.h:76
constexpr float GetPositionY() const
Definition: Position.h:77
constexpr void GetPosition(float &x, float &y) const
Definition: Position.h:81
constexpr float GetPositionZ() const
Definition: Position.h:78
void UpdateAI(uint32 diff) override
void SetGUID(ObjectGuid const &guid, int32 id) override
boss_anub_arak(Creature *creature)
void Reset() override
ObjectGuid _assassinTrigger
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
void KilledUnit(Unit *victim) override
bool CanAIAttack(Unit const *) const override
void DoAction(int32 action) override
ObjectGuid _impaleTarget
void EnterEvadeMode(EvadeReason) override
ObjectGuid _guardianTrigger
void JustDied(Unit *) override
void JustEngagedWith(Unit *who) override
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
npc_anubarak_anub_ar_assassin(Creature *creature)
void MovementInform(uint32, uint32 id) override
Position GetRandomPositionAround(Creature *anubarak)
void JustEngagedWith(Unit *) override
void UpdateAI(uint32 diff) override
npc_anubarak_anub_ar_darter(Creature *creature)
void JustEngagedWith(Unit *) override
void UpdateAI(uint32 diff) override
npc_anubarak_anub_ar_guardian(Creature *creature)
npc_anubarak_anub_ar_venomancer(Creature *creature)
void UpdateAI(uint32 diff) override
void JustEngagedWith(Unit *) override
npc_anubarak_impale_target(Creature *creature)