Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_festergut.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "ObjectMgr.h"
7#include "ScriptMgr.h"
8#include "ScriptedCreature.h"
9#include "SpellAuras.h"
10#include "icecrown_citadel.h"
11
25
27{
28 // Festergut
31 SPELL_GASTRIC_BLOAT = 72219, // 72214 is the proper way (with proc) but atm procs can't have cooldown for creatures
36
37 // Stinky
41};
42
43// Used for HasAura checks
44#define PUNGENT_BLIGHT_HELPER RAID_MODE<uint32>(69195, 71219, 73031, 73032)
45#define INOCULATED_HELPER RAID_MODE<uint32>(69291, 72101, 72102, 72103)
46
47uint32 const gaseousBlight[3] = {69157, 69162, 69164};
48uint32 const gaseousBlightVisual[3] = {69126, 69152, 69154};
49
61
62enum Misc
63{
65};
66
68{
69 public:
70 boss_festergut() : CreatureScript("boss_festergut") { }
71
72 struct boss_festergutAI : public BossAI
73 {
75 {
78 _gasDummyGUID = 0;
79 }
80
82 {
83 _Reset();
84 me->SetReactState(REACT_DEFENSIVE);
85 events.ScheduleEvent(EVENT_BERSERK, 300000);
86 events.ScheduleEvent(EVENT_INHALE_BLIGHT, std::rand() % 30000 + 25000);
87 events.ScheduleEvent(EVENT_GAS_SPORE, std::rand() % 25000 + 20000);
88 events.ScheduleEvent(EVENT_GASTRIC_BLOAT, std::rand() % 15000 + 12500);
91 me->RemoveAurasDueToSpell(SPELL_BERSERK2);
92 if (Creature* gasDummy = me->FindNearestCreature(NPC_GAS_DUMMY, 100.0f, true))
93 {
94 _gasDummyGUID = gasDummy->GetGUID();
95 for (uint8 i = 0; i < 3; ++i)
96 {
97 me->RemoveAurasDueToSpell(gaseousBlight[i]);
98 gasDummy->RemoveAurasDueToSpell(gaseousBlightVisual[i]);
99 }
100 }
101 }
102
104 {
105 if (!instance->CheckRequiredBosses(DATA_FESTERGUT, who->ToPlayer()))
106 {
108 instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT);
109 return;
110 }
111
112 me->setActive(true);
114 if (Creature* gasDummy = me->FindNearestCreature(NPC_GAS_DUMMY, 100.0f, true))
115 _gasDummyGUID = gasDummy->GetGUID();
117 professor->AI()->DoAction(ACTION_FESTERGUT_COMBAT);
119 }
120
121 void JustDied(Unit* /*killer*/) OVERRIDE
122 {
123 _JustDied();
126 professor->AI()->DoAction(ACTION_FESTERGUT_DEATH);
127
128 RemoveBlight();
129 }
130
132 {
134 instance->SetBossState(DATA_FESTERGUT, FAIL);
135 }
136
138 {
141 professor->AI()->EnterEvadeMode();
142 }
143
145 {
146 if (victim->GetTypeId() == TypeID::TYPEID_PLAYER)
147 Talk(SAY_KILL);
148 }
149
150 void SpellHitTarget(Unit* target, SpellInfo const* spell) OVERRIDE
151 {
152 if (spell->Id == PUNGENT_BLIGHT_HELPER)
153 target->RemoveAurasDueToSpell(INOCULATED_HELPER);
154 }
155
157 {
158 if (!UpdateVictim() || !CheckInRoom())
159 return;
160
161 events.Update(diff);
162
163 if (me->HasUnitState(UNIT_STATE_CASTING))
164 return;
165
166 while (uint32 eventId = events.ExecuteEvent())
167 {
168 switch (eventId)
169 {
171 {
172 RemoveBlight();
173 if (_inhaleCounter == 3)
174 {
178 _inhaleCounter = 0;
180 professor->AI()->DoAction(ACTION_FESTERGUT_GAS);
181 events.RescheduleEvent(EVENT_GAS_SPORE, std::rand() % 25000 + 20000);
182 }
183 else
184 {
186 // just cast and dont bother with target, conditions will handle it
188 if (_inhaleCounter < 3)
189 me->CastSpell(me, gaseousBlight[_inhaleCounter], true, NULL, NULL, me->GetGUID());
190 }
191
192 events.ScheduleEvent(EVENT_INHALE_BLIGHT, std::rand() % 35000 + 33500);
193 break;
194 }
195 case EVENT_VILE_GAS:
196 {
197 std::list<Unit*> ranged, melee;
198 uint32 minTargets = RAID_MODE<uint32>(3, 8, 3, 8);
199 SelectTargetList(ranged, 25, SELECT_TARGET_RANDOM, -5.0f, true);
200 SelectTargetList(melee, 25, SELECT_TARGET_RANDOM, 5.0f, true);
201 while (ranged.size() < minTargets)
202 {
203 if (melee.empty())
204 break;
205
207 ranged.push_back(target);
208 melee.remove(target);
209 }
210
211 if (!ranged.empty())
212 {
214 for (std::list<Unit*>::iterator itr = ranged.begin(); itr != ranged.end(); ++itr)
215 DoCast(*itr, SPELL_VILE_GAS);
216 }
217
218 events.ScheduleEvent(EVENT_VILE_GAS, std::rand() % 35000 + 28000);
219 break;
220 }
221 case EVENT_GAS_SPORE:
224 me->CastCustomSpell(SPELL_GAS_SPORE, SPELLVALUE_MAX_TARGETS, RAID_MODE<int32>(2, 3, 2, 3), me);
225 events.ScheduleEvent(EVENT_GAS_SPORE, std::rand() % 45000 + 40000);
226 events.RescheduleEvent(EVENT_VILE_GAS, std::rand() % 35000 + 28000);
227 break;
230 events.ScheduleEvent(EVENT_GASTRIC_BLOAT, std::rand() % 17500 + 15000);
231 break;
232 case EVENT_BERSERK:
235 break;
236 default:
237 break;
238 }
239 }
240
242 }
243
244 void SetData(uint32 type, uint32 data) OVERRIDE
245 {
246 if (type == DATA_INOCULATED_STACK && data > _maxInoculatedStack)
247 _maxInoculatedStack = data;
248 }
249
251 {
252 if (type == DATA_INOCULATED_STACK)
254
255 return 0;
256 }
257
259 {
261 for (uint8 i = 0; i < 3; ++i)
262 {
263 me->RemoveAurasDueToSpell(gaseousBlight[i]);
264 gasDummy->RemoveAurasDueToSpell(gaseousBlightVisual[i]);
265 }
266 }
267
268 private:
272 };
273
275 {
277 }
278};
279
281{
282 public:
283 npc_stinky_icc() : CreatureScript("npc_stinky_icc") { }
284
286 {
287 npc_stinky_iccAI(Creature* creature) : ScriptedAI(creature)
288 {
289 _instance = creature->GetInstanceScript();
290 }
291
293 {
294 _events.Reset();
295 _events.ScheduleEvent(EVENT_DECIMATE, std::rand() % 25000 + 20000);
296 _events.ScheduleEvent(EVENT_MORTAL_WOUND, std::rand() % 7000 + 3000);
297 }
298
299 void EnterCombat(Unit* /*target*/) OVERRIDE
300 {
302 }
303
305 {
306 if (!UpdateVictim())
307 return;
308
309 _events.Update(diff);
310
311 if (me->HasUnitState(UNIT_STATE_CASTING))
312 return;
313
314 while (uint32 eventId = _events.ExecuteEvent())
315 {
316 switch (eventId)
317 {
318 case EVENT_DECIMATE:
320 _events.ScheduleEvent(EVENT_DECIMATE, std::rand() % 25000 + 20000);
321 break;
324 _events.ScheduleEvent(EVENT_MORTAL_WOUND, std::rand() % 12500 + 10000);
325 break;
326 default:
327 break;
328 }
329 }
330
332 }
333
334 void JustDied(Unit* /*killer*/) OVERRIDE
335 {
336 if (Creature* festergut = me->GetCreature(*me, _instance->GetData64(DATA_FESTERGUT)))
337 if (festergut->IsAlive())
338 festergut->AI()->Talk(SAY_STINKY_DEAD);
339 }
340
341 private:
344 };
345
347 {
349 }
350};
351
353{
354 public:
355 spell_festergut_pungent_blight() : SpellScriptLoader("spell_festergut_pungent_blight") { }
356
358 {
360
362 {
364 }
365
366 void HandleScript(SpellEffIndex /*effIndex*/)
367 {
368 // Get Inhaled Blight id for our difficulty
369 uint32 blightId = sSpellMgr->GetSpellIdForDifficulty(uint32(GetEffectValue()), GetCaster());
370
371 // ...and remove it
372 GetCaster()->RemoveAurasDueToSpell(blightId);
374 }
375
380 };
381
386};
387
389{
390 public:
391 spell_festergut_gastric_bloat() : SpellScriptLoader("spell_festergut_gastric_bloat") { }
392
394 {
396
397 bool Validate(SpellInfo const* /*spell*/) OVERRIDE
398 {
399 if (!sSpellMgr->GetSpellInfo(SPELL_GASTRIC_EXPLOSION))
400 return false;
401 return true;
402 }
403
404 void HandleScript(SpellEffIndex /*effIndex*/)
405 {
406 Aura const* aura = GetHitUnit()->GetAura(GetSpellInfo()->Id);
407 if (!(aura && aura->GetStackAmount() == 10))
408 return;
409
412 }
413
418 };
419
424};
425
427{
428 public:
429 spell_festergut_blighted_spores() : SpellScriptLoader("spell_festergut_blighted_spores") { }
430
432 {
434
435 bool Validate(SpellInfo const* /*spell*/) OVERRIDE
436 {
437 if (!sSpellMgr->GetSpellInfo(SPELL_INOCULATED))
438 return false;
439 return true;
440 }
441
442 void ExtraEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
443 {
445 if (InstanceScript* instance = GetTarget()->GetInstanceScript())
446 if (Creature* festergut = ObjectAccessor::GetCreature(*GetTarget(), instance->GetData64(DATA_FESTERGUT)))
447 festergut->AI()->SetData(DATA_INOCULATED_STACK, GetStackAmount());
448 }
449
454 };
455
460};
461
463{
464 public:
465 achievement_flu_shot_shortage() : AchievementCriteriaScript("achievement_flu_shot_shortage") { }
466
467 bool OnCheck(Player* /*source*/, Unit* target) OVERRIDE
468 {
469 if (target && target->GetTypeId() == TypeID::TYPEID_UNIT)
470 return target->ToCreature()->AI()->GetData(DATA_INOCULATED_STACK) < 3;
471
472 return false;
473 }
474};
475
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
#define OVERRIDE
Definition Define.h:60
std::uint64_t uint64
Definition Define.h:76
@ FAIL
@ TYPEID_PLAYER
Definition Object.h:55
@ TYPEID_UNIT
Definition Object.h:54
SpellEffIndex
@ EFFECT_1
@ EFFECT_0
@ EFFECT_2
@ SPELL_EFFECT_SCRIPT_EFFECT
@ SPELL_AURA_PERIODIC_DAMAGE
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK
#define sSpellMgr
Definition SpellMgr.h:744
#define SpellEffectFn(F, I, N)
#define AuraEffectApplyFn(F, I, N, M)
@ SPELLVALUE_MAX_TARGETS
Definition Unit.h:118
@ UNIT_STATE_CASTING
Definition Unit.h:527
@ REACT_DEFENSIVE
Definition Unit.h:1157
@ SELECT_TARGET_RANDOM
Definition UnitAI.h:23
@ SAY_BERSERK
#define SAY_DEATH
#define SAY_AGGRO
#define SAY_KILL
uint32 const gaseousBlight[3]
#define INOCULATED_HELPER
@ DATA_INOCULATED_STACK
#define PUNGENT_BLIGHT_HELPER
@ SPELL_VILE_GAS
@ SPELL_PLAGUE_STENCH
@ SPELL_GASTRIC_EXPLOSION
@ SPELL_INHALE_BLIGHT
@ SPELL_GAS_SPORE
@ SPELL_GASTRIC_BLOAT
@ SPELL_INOCULATED
@ SPELL_DECIMATE
@ SPELL_MORTAL_WOUND
@ SPELL_PUNGENT_BLIGHT
@ SAY_DEATH
@ EMOTE_PUNGENT_BLIGHT
@ SAY_AGGRO
@ EMOTE_GAS_SPORE
@ SAY_PUNGENT_BLIGHT
@ EMOTE_WARN_GAS_SPORE
@ SAY_KILL
@ EMOTE_WARN_PUNGENT_BLIGHT
@ SAY_STINKY_DEAD
@ SAY_BERSERK
void AddSC_boss_festergut()
uint32 const gaseousBlightVisual[3]
@ EVENT_VILE_GAS
@ EVENT_MORTAL_WOUND
@ EVENT_GASTRIC_BLOAT
@ EVENT_BERSERK
@ EVENT_GAS_SPORE
@ EVENT_INHALE_BLIGHT
@ EVENT_DECIMATE
@ EVENT_BERSERK
@ SPELL_MORTAL_WOUND
@ EVENT_MORTAL_WOUND
AchievementCriteriaScript(const char *name)
uint8 GetStackAmount() const
Definition SpellAuras.h:133
HookList< EffectApplyHandler > AfterEffectApply
Unit * GetTarget() const
uint8 GetStackAmount() const
InstanceScript *const instance
void _JustReachedHome()
bool CheckInRoom()
EventMap events
BossAI(Creature *creature, uint32 bossId)
void DoZoneInCombat(Creature *creature=NULL, float maxRangeToNearestTarget=50.0f)
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
bool UpdateVictim()
virtual void EnterEvadeMode()
CreatureAI * AI() const
Definition Creature.h:483
CreatureScript(const char *name)
static Creature * GetCreature(WorldObject const &u, uint64 guid)
TypeID GetTypeId() const
Definition Object.h:131
Creature * ToCreature()
Definition Object.h:207
SpellInfo const * GetSpellInfo()
HookList< EffectHandler > OnEffectHitTarget
Unit * GetHitUnit()
int32 GetEffectValue()
Unit * GetCaster()
SpellScriptLoader(const char *name)
void SelectTargetList(std::list< Unit * > &targetList, uint32 num, SelectAggroTarget targetType, float dist=0.0f, bool playerOnly=false, int32 aura=0)
Definition UnitAI.cpp:71
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:28
void DoCast(uint32 spellId)
Definition UnitAI.cpp:110
void DoCastVictim(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:168
Definition Unit.h:1367
void CastSpell(SpellCastTargets const &targets, SpellInfo const *spellInfo, CustomSpellValues const *value, TriggerCastFlags triggerFlags=TRIGGERED_NONE, Item *castItem=NULL, AuraEffect const *triggeredByAura=NULL, uint64 originalCaster=0)
void RemoveAurasDueToSpell(uint32 spellId, uint64 casterGUID=0, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Aura * GetAura(uint32 spellId, uint64 casterGUID=0, uint64 itemCasterGUID=0, uint32 reqEffMask=0) const
InstanceScript * GetInstanceScript()
Definition Object.cpp:1612
bool OnCheck(Player *, Unit *target) OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
AuraScript * GetAuraScript() const OVERRIDE
SpellScript * GetSpellScript() const OVERRIDE
SpellScript * GetSpellScript() const OVERRIDE
@ NPC_GAS_DUMMY
CreatureAI * GetIcecrownCitadelAI(Creature *creature)
@ ACTION_FESTERGUT_DEATH
@ ACTION_FESTERGUT_GAS
@ ACTION_FESTERGUT_COMBAT
@ LIGHT_S_HAMMER_TELEPORT
@ SPELL_BERSERK2
@ DATA_PROFESSOR_PUTRICIDE
@ DATA_FESTERGUT
void RandomResizeList(std::list< T > &list, uint32 size)
Definition Containers.h:19
C::value_type const & SelectRandomContainerElement(C const &container)
Definition Containers.h:48
Creature * me
const T & RAID_MODE(const T &normal10, const T &normal25) const
ScriptedAI(Creature *creature)
void SetData(uint32 type, uint32 data) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void KilledUnit(Unit *victim) OVERRIDE
void EnterCombat(Unit *who) OVERRIDE
void SpellHitTarget(Unit *target, SpellInfo const *spell) OVERRIDE
uint32 GetData(uint32 type) const OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================