TrinityCore
Loading...
Searching...
No Matches
boss_gluth.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 "InstanceScript.h"
20#include "MotionMaster.h"
21#include "naxxramas.h"
22#include "ObjectAccessor.h"
23#include "ScriptedCreature.h"
24#include "SpellScript.h"
25
34
36{
37 // Gluth
38 SPELL_MORTAL_WOUND = 54378, // spell effect dummy unused. what its supposed to do is unkown.
39 SPELL_ENRAGE = 28371, // 54427 in 25 man.
40 SPELL_DECIMATE = 28374, // 54426 in 25 man. Effect0 is handled by SpellScript (see below) and 2 rows in conditions table. Effect2 is handled by SpellScript (see below).
43 SPELL_ZOMBIE_CHOW_SEARCH_SINGLE = 28239, // Insta kill spell. Single target. See spell script below.
44 SPELL_ZOMBIE_CHOW_SEARCH_MULTI = 28404, // Insta kill spell. Affect all zombies 10 yards around Gluth's center. See one row conditions table + spell script below.
45
46 // Zombies
47 SPELL_INFECTED_WOUND = 29307 // Used by the zombies on self.
48};
49
51{
52 { 3270.132f, -3169.948f, 297.5891f, 5.88176f },
53 { 3307.298f, -3183.449f, 297.5891f, 5.742133f },
54 { 3255.708f, -3135.677f, 297.5891f, 1.867502f }
55};
56
68
78
84
85enum Misc
86{
87 EVENT_GLUTH_ZOMBIE_BEHAVIOR = 10495, // unused. event handled by spell_gluth_decimate_SpellScript::HandleEvent
90};
91
92struct boss_gluth : public BossAI
93{
94
96
105
116
117 void SummonedCreatureDies(Creature* summoned, Unit* /* who */) override
118 {
119 summons.Despawn(summoned); // needed or else dead zombies not despawned yet will still be in the list
120 }
121
122 void UpdateAI(uint32 diff) override
123 {
124 if (!UpdateVictim() || !CheckInRoom())
125 return;
126
127 events.Update(diff);
128
130 return;
131
132 while (uint32 eventId = events.ExecuteEvent())
133 {
134 switch (eventId)
135 {
136 case EVENT_WOUND:
138 {
140 break;
141 }
142
144 events.Repeat(Seconds(10));
145 break;
146 case EVENT_ENRAGE:
148 {
150 break;
151 }
152
156 break;
157 case EVENT_DECIMATE:
159 {
161 break;
162 }
163
166 for (int i = 1; i <= 20; i++)
169 break;
170 case EVENT_BERSERK:
173 events.Repeat(Minutes(5)); //refresh the hard enrage buff
174 break;
175 case EVENT_SUMMON:
176 if (Is25ManRaid()) // one wave each 10s. one wave=1 zombie in 10man and 2 zombies in 25man.
178 else
180 events.Repeat(Seconds(10));
181 break;
183 {
184 Creature* zombie = nullptr;
185 for (SummonList::const_iterator itr = summons.begin(); !zombie && itr != summons.end(); ++itr)
186 {
187 zombie = ObjectAccessor::GetCreature(*me, *itr);
188 if (!zombie || !zombie->IsAlive() || !zombie->IsWithinDistInMap(me, 10.0))
189 zombie = nullptr;
190 }
191
192 if (zombie)
193 {
194 zombieToBeEatenGUID = zombie->GetGUID(); // save for later use
195
196 // the soon-to-be-eaten zombie should stop moving and stop attacking
198
199 // gluth should stop AAs on his primary target and turn toward the zombie (2 yards away). He then pauses for a few seconds.
200 me->SetSpeed(MOVE_RUN, 36.0f);
201
203 me->AttackStop();
204
206
207 //me->SetTarget(ObjectGuid::Empty);
208
209 me->GetMotionMaster()->MoveCloserAndStop(1, zombie, 2.0f);
210
212 }
213
215 break;
216 }
218 {
220 if (zombieToBeEaten && zombieToBeEaten->IsAlive() && zombieToBeEaten->IsWithinDistInMap(me, 10.0))
221 DoCast(zombieToBeEaten, SPELL_ZOMBIE_CHOW_SEARCH_SINGLE); // do the killing + healing in done inside by spell script see below.
222
226
227 // and then return on primary target
229
230 break;
231 }
233 {
234 if (state == STATE_GLUTH_EATING) // skip and simply wait for the next occurence
235 break;
236
237 Creature* zombie = nullptr;
238 for (SummonList::const_iterator itr = summons.begin(); !zombie && itr != summons.end(); ++itr)
239 {
240 zombie = ObjectAccessor::GetCreature(*me, *itr);
241 if (zombie && zombie->IsAlive() && zombie->GetExactDist2d(me) > 18.0)
242 zombie = nullptr;
243 }
244
245 if (zombie) // cast the aoe spell only if at least one zombie is found nearby
246 {
249 }
250 break;
251 }
252 }
253
255 return;
256 }
257
259 }
260
261 void MovementInform(uint32 /*type*/, uint32 id) override
262 {
263 if (id == 1){
266 }
267
268 }
269
270 void DoAction(int32 action) override
271 {
272 switch (action)
273 {
275 for (ObjectGuid zombieGuid : summons)
276 {
277 Creature* zombie = ObjectAccessor::GetCreature(*me, zombieGuid);
278 if (zombie && zombie->IsAlive())
280 }
281 break;
282 }
283 }
284
285private:
288};
289
290// 28374, 54426 - Decimate
292{
294
295 // handles the damaging effect of the decimate spell.
297 {
298 if (Unit *unit = GetHitUnit())
299 {
300 int32 damage = int32(unit->GetHealth()) - int32(unit->CountPctFromMaxHealth(5));
301 if (damage > 0)
302 {
304 args.AddSpellBP0(damage);
305 GetCaster()->CastSpell(unit, SPELL_DECIMATE_DMG, args);
306 }
307 }
308 }
309
310 // handles the change of zombies behavior after the decimate spell
311 void HandleEvent(SpellEffIndex /* index */)
312 {
314 }
315
316 bool Validate(SpellInfo const* /*spellInfo*/) override
317 {
319 }
320
326
327 bool Load() override
328 {
329 return GetCaster() && GetCaster()->GetEntry() == NPC_GLUTH;
330 }
331};
332
333// 28239, 28404 - Zombie Chow Search (single target and aoe zombie-kill spell) to heal Gluth on each target hit
335{
337
339 {
340 GetCaster()->ModifyHealth(int32(GetCaster()->CountPctFromMaxHealth(5)));
341 }
342
347
348 bool Load() override
349 {
350 return GetCaster() && GetCaster()->GetEntry() == NPC_GLUTH;
351 }
352};
353
354// creature 16360 (10man) / 30303 (25man)
356{
357 npc_zombie_chow(Creature* creature) : ScriptedAI(creature)
358 {
360
362 timer = 0;
364 }
365
366 void UpdateAI(uint32 diff) override
367 {
368 if (!UpdateVictim())
369 return;
370
372 {
373 timer += diff;
375 {
376 // Putting this in the UpdateAI loop fixes an issue where death gripping a decimated zombie would make the zombie stand still until the rest of the fight.
377 // Also fix the issue where if one or more zombie is rooted when decimates hits (and MovePoint() is called), the zombie teleport to the boss. pretty weird behavior.
378 if (timer > 1600 && me->GetExactDist2d(gluth) > 10.0f && me->CanFreeMove()) // it takes about 1600 ms for the animation to cycle. This way, the animation looks relatively smooth.
379 {
380 me->GetMotionMaster()->MovePoint(0, gluth->GetPosition()); // isn't dynamic. So, to take into account Gluth's movement, it must be called periodicly.
381 timer = 0;
382 }
383
384 if (me->GetExactDist2d(gluth) <= 10.0f)
385 me->StopMoving();
386 }
387 }
388 else if (state == STATE_ZOMBIE_NORMAL)
390 }
391
392 void SetData(uint32 id, uint32 value) override
393 {
394 if (id == DATA_ZOMBIE_STATE) // change of state
395 {
396 state = value;
397 if (value == STATE_ZOMBIE_DECIMATED)
398 {
400 me->AttackStop();
402 // at this point, the zombie should be non attacking and non moving.
403
404 me->SetWalk(true); // it doesnt seem to work with MoveFollow() (but it does work with MovePoint()).
405
406 timer = 1000;
407 }
408 else if (value == STATE_ZOMBIE_TOBE_EATEN)
409 {
410 // forced to stand still
412 me->StopMoving();
413
414 // and loose aggro behavior
416 me->AttackStop();
418
419 me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_GRIP, true); // not sure if this is blizz-like but this is very convenient
420 }
421 }
422 }
423
424 uint32 GetData(uint32 index) const override
425 {
426 if (index == DATA_ZOMBIE_STATE)
427 return state;
428 return 0;
429 }
430
431private:
435};
436
uint8_t uint8
Definition Define.h:135
int32_t int32
Definition Define.h:129
uint32_t uint32
Definition Define.h:133
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition Duration.h:27
std::chrono::minutes Minutes
Minutes shorthand typedef.
Definition Duration.h:30
Spells
Definition PlayerAI.cpp:32
Milliseconds randtime(Milliseconds min, Milliseconds max)
Definition Random.cpp:62
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1128
SpellEffIndex
@ EFFECT_0
@ EFFECT_2
@ SPELL_EFFECT_SCRIPT_EFFECT
@ SPELL_EFFECT_SEND_EVENT
@ MECHANIC_GRIP
@ IMMUNITY_MECHANIC
@ TRIGGERED_FULL_MASK
Will return SPELL_FAILED_DONT_REPORT in CheckCast functions.
#define SpellEffectFn(F, I, N)
#define SpellHitFn(F)
@ REACT_PASSIVE
@ REACT_AGGRESSIVE
@ MOVE_RUN
@ UNIT_STATE_CASTING
Definition Unit.h:235
SummonGroups
@ SUMMON_GROUP_CHOW_25MAN
@ SUMMON_GROUP_CHOW_10MAN
Position const PosSummon[3]
@ DATA_ZOMBIE_STATE
@ ACTION_DECIMATE_EVENT
@ EVENT_GLUTH_ZOMBIE_BEHAVIOR
@ SPELL_ENRAGE
@ SPELL_ZOMBIE_CHOW_SEARCH_MULTI
@ SPELL_ZOMBIE_CHOW_SEARCH_SINGLE
@ SPELL_DECIMATE
@ SPELL_DECIMATE_DMG
@ SPELL_BERSERK
@ SPELL_MORTAL_WOUND
@ SPELL_INFECTED_WOUND
States
@ STATE_GLUTH_NORMAL
@ STATE_ZOMBIE_TOBE_EATEN
@ STATE_ZOMBIE_DECIMATED
@ STATE_GLUTH_EATING
@ STATE_ZOMBIE_NORMAL
@ EMOTE_SPOTS_ONE
@ EMOTE_BERSERKER
@ EMOTE_ENRAGE
@ EMOTE_DECIMATE
@ EMOTE_DEVOURS_ALL
void AddSC_boss_gluth()
@ EVENT_SEARCH_ZOMBIE_SINGLE
@ EVENT_ENRAGE
@ EVENT_SEARCH_ZOMBIE_MULTI
@ EVENT_WOUND
@ EVENT_KILL_ZOMBIE_SINGLE
@ EVENT_BERSERK
@ EVENT_SUMMON
@ EVENT_DECIMATE
void JustEngagedWith(Unit *who) override
SummonList summons
EventMap events
virtual bool CheckInRoom()
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:82
void SetReactState(ReactStates st)
Definition Creature.h:119
void SetTarget(ObjectGuid guid) override
CreatureAI * AI() const
Definition Creature.h:154
void Update(uint32 time)
Definition EventMap.h:67
void Repeat(Milliseconds time)
Definition EventMap.cpp:63
EventId ExecuteEvent()
Definition EventMap.cpp:73
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:36
virtual ObjectGuid GetGuidData(uint32 type) const override
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={})
void MoveCloserAndStop(uint32 id, Unit *target, float distance)
static ObjectGuid const Empty
Definition ObjectGuid.h:140
void Clear()
Definition ObjectGuid.h:150
uint32 GetEntry() const
Definition Object.h:81
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
Unit * GetCaster() const
HookList< HitHandler > AfterHit
HookList< EffectHandler > OnEffectHit
Unit * GetHitUnit() const
HookList< EffectHandler > OnEffectHitTarget
void Despawn(Creature const *summon)
iterator begin()
StorageType::const_iterator const_iterator
iterator end()
virtual void SetData(uint32, uint32)
Definition UnitAI.h:156
virtual void DoAction(int32)
Definition UnitAI.h:154
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:54
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:166
SpellCastResult DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:243
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:106
Definition Unit.h:769
int32 ModifyHealth(int32 val)
Definition Unit.cpp:8381
void StopMoving(bool force=false)
Definition Unit.cpp:10312
void SetSpeed(UnitMoveType mtype, float newValue)
Definition Unit.cpp:8673
MotionMaster * GetMotionMaster()
Definition Unit.h:1667
bool CanFreeMove() const
Definition Unit.cpp:9338
bool IsAlive() const
Definition Unit.h:1234
UnitAI * GetAI() const
Definition Unit.h:800
bool SetWalk(bool enable)
Definition Unit.cpp:13268
bool HasUnitState(const uint32 f) const
Definition Unit.h:876
void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply)
Definition Unit.cpp:8142
bool AttackStop()
Definition Unit.cpp:5645
InstanceScript * GetInstanceScript() const
Definition Object.cpp:1087
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2832
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:1192
void SummonCreatureGroup(uint8 group, std::list< TempSummon * > *list=nullptr)
Definition Object.cpp:2082
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
PrepareSpellScript(spell_gluth_decimate)
bool Validate(SpellInfo const *) override
bool Load() override
void HandleEvent(SpellEffIndex)
void Register() override
void HandleScriptEffect(SpellEffIndex)
PrepareSpellScript(spell_gluth_zombiechow_search)
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
@ NPC_GLUTH
Definition naxxramas.h:96
@ BOSS_GLUTH
Definition naxxramas.h:38
@ DATA_GLUTH
Definition naxxramas.h:71
#define RegisterNaxxramasCreatureAI(ai_name)
Definition naxxramas.h:221
CastSpellExtraArgs & AddSpellBP0(int32 val)
float GetExactDist2d(const float x, const float y) const
Definition Position.h:109
T const & RAID_MODE(T const &normal10, T const &normal25) const
bool Is25ManRaid() const
void UpdateAI(uint32 diff) override
boss_gluth(Creature *creature)
void Reset() override
void JustEngagedWith(Unit *who) override
ObjectGuid zombieToBeEatenGUID
void DoAction(int32 action) override
void SummonedCreatureDies(Creature *summoned, Unit *) override
void MovementInform(uint32, uint32 id) override
npc_zombie_chow(Creature *creature)
void UpdateAI(uint32 diff) override
ObjectGuid GluthGUID
void SetData(uint32 id, uint32 value) override
uint32 GetData(uint32 index) const override