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
61
71
77
78enum Misc
79{
80 EVENT_GLUTH_ZOMBIE_BEHAVIOR = 10495, // unused. event handled by spell_gluth_decimate_SpellScript::HandleEvent
83};
84
85struct boss_gluth : public BossAI
86{
87
89
98
109
110 void SummonedCreatureDies(Creature* summoned, Unit* /* who */) override
111 {
112 summons.Despawn(summoned); // needed or else dead zombies not despawned yet will still be in the list
113 }
114
115 void UpdateAI(uint32 diff) override
116 {
117 if (!UpdateVictim() || !CheckInRoom())
118 return;
119
120 events.Update(diff);
121
123 return;
124
125 while (uint32 eventId = events.ExecuteEvent())
126 {
127 switch (eventId)
128 {
129 case EVENT_WOUND:
131 {
133 break;
134 }
135
137 events.Repeat(Seconds(10));
138 break;
139 case EVENT_ENRAGE:
141 {
143 break;
144 }
145
149 break;
150 case EVENT_DECIMATE:
152 {
154 break;
155 }
156
159 for (int i = 1; i <= 20; i++)
162 break;
163 case EVENT_BERSERK:
166 events.Repeat(Minutes(5)); //refresh the hard enrage buff
167 break;
168 case EVENT_SUMMON:
169 if (Is25ManRaid()) // one wave each 10s. one wave=1 zombie in 10man and 2 zombies in 25man.
171 else
173 events.Repeat(Seconds(10));
174 break;
176 {
177 Creature* zombie = nullptr;
178 for (SummonList::const_iterator itr = summons.begin(); !zombie && itr != summons.end(); ++itr)
179 {
180 zombie = ObjectAccessor::GetCreature(*me, *itr);
181 if (!zombie || !zombie->IsAlive() || !zombie->IsWithinDistInMap(me, 10.0))
182 zombie = nullptr;
183 }
184
185 if (zombie)
186 {
187 zombieToBeEatenGUID = zombie->GetGUID(); // save for later use
188
189 // the soon-to-be-eaten zombie should stop moving and stop attacking
191
192 // gluth should stop AAs on his primary target and turn toward the zombie (2 yards away). He then pauses for a few seconds.
193 me->SetSpeed(MOVE_RUN, 36.0f);
194
196 me->AttackStop();
197
199
200 //me->SetTarget(ObjectGuid::Empty);
201
202 me->GetMotionMaster()->MoveCloserAndStop(1, zombie, 2.0f);
203
205 }
206
208 break;
209 }
211 {
213 if (zombieToBeEaten && zombieToBeEaten->IsAlive() && zombieToBeEaten->IsWithinDistInMap(me, 10.0))
214 DoCast(zombieToBeEaten, SPELL_ZOMBIE_CHOW_SEARCH_SINGLE); // do the killing + healing in done inside by spell script see below.
215
219
220 // and then return on primary target
222
223 break;
224 }
226 {
227 if (state == STATE_GLUTH_EATING) // skip and simply wait for the next occurence
228 break;
229
230 Creature* zombie = nullptr;
231 for (SummonList::const_iterator itr = summons.begin(); !zombie && itr != summons.end(); ++itr)
232 {
233 zombie = ObjectAccessor::GetCreature(*me, *itr);
234 if (zombie && zombie->IsAlive() && zombie->GetExactDist2d(me) > 18.0)
235 zombie = nullptr;
236 }
237
238 if (zombie) // cast the aoe spell only if at least one zombie is found nearby
239 {
242 }
243 break;
244 }
245 }
246
248 return;
249 }
250 }
251
252 void MovementInform(uint32 /*type*/, uint32 id) override
253 {
254 if (id == 1){
257 }
258
259 }
260
261 void DoAction(int32 action) override
262 {
263 switch (action)
264 {
266 for (ObjectGuid zombieGuid : summons)
267 {
268 Creature* zombie = ObjectAccessor::GetCreature(*me, zombieGuid);
269 if (zombie && zombie->IsAlive())
271 }
272 break;
273 }
274 }
275
276private:
279};
280
281// 28374, 54426 - Decimate
283{
284 // handles the damaging effect of the decimate spell.
286 {
287 if (Unit *unit = GetHitUnit())
288 {
289 int32 damage = int32(unit->GetHealth()) - int32(unit->CountPctFromMaxHealth(5));
290 if (damage > 0)
291 {
293 args.AddSpellBP0(damage);
294 GetCaster()->CastSpell(unit, SPELL_DECIMATE_DMG, args);
295 }
296 }
297 }
298
299 // handles the change of zombies behavior after the decimate spell
300 void HandleEvent(SpellEffIndex /* index */)
301 {
303 }
304
305 bool Validate(SpellInfo const* /*spellInfo*/) override
306 {
308 }
309
315
316 bool Load() override
317 {
318 return GetCaster() && GetCaster()->GetEntry() == NPC_GLUTH;
319 }
320};
321
322// 28239, 28404 - Zombie Chow Search (single target and aoe zombie-kill spell) to heal Gluth on each target hit
324{
326 {
327 GetCaster()->ModifyHealth(int32(GetCaster()->CountPctFromMaxHealth(5)));
328 }
329
334
335 bool Load() override
336 {
337 return GetCaster() && GetCaster()->GetEntry() == NPC_GLUTH;
338 }
339};
340
341// creature 16360 (10man) / 30303 (25man)
343{
344 npc_zombie_chow(Creature* creature) : ScriptedAI(creature)
345 {
347
349 timer = 0;
351 }
352
353 void UpdateAI(uint32 diff) override
354 {
355 if (!UpdateVictim())
356 return;
357
359 {
360 timer += diff;
362 {
363 // 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.
364 // 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.
365 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.
366 {
367 me->GetMotionMaster()->MovePoint(0, gluth->GetPosition()); // isn't dynamic. So, to take into account Gluth's movement, it must be called periodicly.
368 timer = 0;
369 }
370
371 if (me->GetExactDist2d(gluth) <= 10.0f)
372 me->StopMoving();
373 }
374 }
375 }
376
377 void SetData(uint32 id, uint32 value) override
378 {
379 if (id == DATA_ZOMBIE_STATE) // change of state
380 {
381 state = value;
382 if (value == STATE_ZOMBIE_DECIMATED)
383 {
385 me->AttackStop();
386 me->SetCanMelee(false);
388 // at this point, the zombie should be non attacking and non moving.
389
390 me->SetWalk(true); // it doesnt seem to work with MoveFollow() (but it does work with MovePoint()).
391
392 timer = 1000;
393 }
394 else if (value == STATE_ZOMBIE_TOBE_EATEN)
395 {
396 // forced to stand still
398 me->StopMoving();
399
400 // and loose aggro behavior
402 me->AttackStop();
403 me->SetCanMelee(false);
405
406 me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_GRIP, true); // not sure if this is blizz-like but this is very convenient
407 }
408 }
409 }
410
411 uint32 GetData(uint32 index) const override
412 {
413 if (index == DATA_ZOMBIE_STATE)
414 return state;
415 return 0;
416 }
417
418private:
422};
423
uint8_t uint8
Definition Define.h:156
int32_t int32
Definition Define.h:150
uint32_t uint32
Definition Define.h:154
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition Duration.h:28
std::chrono::minutes Minutes
Minutes shorthand typedef.
Definition Duration.h:32
Spells
Definition PlayerAI.cpp:32
Milliseconds randtime(Milliseconds min, Milliseconds max)
Definition Random.cpp:62
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1383
SpellEffIndex
@ EFFECT_0
@ EFFECT_2
@ SPELL_EFFECT_SCRIPT_EFFECT
@ SPELL_EFFECT_SEND_EVENT
@ MECHANIC_GRIP
@ IMMUNITY_MECHANIC
@ TRIGGERED_FULL_MASK
Used when doing CastSpell with triggered == true.
#define SpellEffectFn(F, I, N)
#define SpellHitFn(F)
@ MOVE_RUN
@ REACT_PASSIVE
@ REACT_AGGRESSIVE
@ UNIT_STATE_CASTING
Definition Unit.h:276
@ SUMMON_GROUP_CHOW_25MAN
@ SUMMON_GROUP_CHOW_10MAN
@ 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
SummonGroups
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
void JustEngagedWith(Unit *who) override
SummonList summons
EventMap events
virtual bool CheckInRoom()
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:63
void SetCanMelee(bool canMelee, bool fleeFromMelee=false)
void SetReactState(ReactStates st)
Definition Creature.h:174
void SetTarget(ObjectGuid const &guid) override
CreatureAI * AI() const
Definition Creature.h:228
uint32 ExecuteEvent()
Definition EventMap.cpp:77
void Update(uint32 time)
Definition EventMap.h:61
void Repeat(Milliseconds time)
Definition EventMap.cpp:67
void ScheduleEvent(uint32 eventId, Milliseconds time, uint32 group=0, uint8 phase=0)
Definition EventMap.cpp:40
virtual ObjectGuid GetGuidData(uint32 type) const override
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={}, Optional< float > speed={}, MovementWalkRunSpeedSelectionMode speedSelectionMode=MovementWalkRunSpeedSelectionMode::Default, Optional< float > closeEnoughDistance={}, Optional< MovementFadeObject > fadeObject={}, Scripting::v2::ActionResultSetter< MovementStopReason > &&scriptResult={})
void MoveCloserAndStop(uint32 id, Unit *target, float distance)
static ObjectGuid const Empty
Definition ObjectGuid.h:314
void Clear()
Definition ObjectGuid.h:329
uint32 GetEntry() const
Definition Object.h:89
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
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 id, uint32 value)
Definition UnitAI.h:75
virtual void DoAction(int32 param)
Definition UnitAI.h:73
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:180
SpellCastResult DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:162
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:89
Definition Unit.h:635
void ApplySpellImmune(uint32 spellId, SpellImmunity op, uint32 type, bool apply)
Definition Unit.cpp:8242
int64 ModifyHealth(int64 val)
Definition Unit.cpp:8599
void SetSpeed(UnitMoveType mtype, float newValue)
Definition Unit.cpp:8937
MotionMaster * GetMotionMaster()
Definition Unit.h:1723
bool CanFreeMove() const
Definition Unit.cpp:9950
bool IsAlive() const
Definition Unit.h:1185
void StopMoving()
Definition Unit.cpp:10680
UnitAI * GetAI() const
Definition Unit.h:668
bool SetWalk(bool enable)
Definition Unit.cpp:13343
bool HasUnitState(const uint32 f) const
Definition Unit.h:743
bool AttackStop()
Definition Unit.cpp:5965
InstanceScript * GetInstanceScript() const
Definition Object.cpp:396
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2217
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:501
void SummonCreatureGroup(uint8 group, std::list< TempSummon * > *list=nullptr)
Definition Object.cpp:1507
bool Validate(SpellInfo const *) override
bool Load() override
void HandleEvent(SpellEffIndex)
void Register() override
void HandleScriptEffect(SpellEffIndex)
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(SpellEffectValue val)
float GetExactDist2d(const float x, const float y) const
Definition Position.h:117
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