TrinityCore
boss_festergut.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 "icecrown_citadel.h"
19#include "Containers.h"
20#include "InstanceScript.h"
21#include "Map.h"
22#include "ObjectAccessor.h"
23#include "Player.h"
24#include "ScriptedCreature.h"
25#include "ScriptMgr.h"
26#include "SpellAuras.h"
27#include "SpellScript.h"
28
30{
41};
42
44{
45 // Festergut
48 SPELL_GASTRIC_BLOAT = 72219, // 72214 is the proper way (with proc) but atm procs can't have cooldown for creatures
53
54 // Stinky
58};
59
60// Used for HasAura checks
61#define PUNGENT_BLIGHT_HELPER RAID_MODE<uint32>(69195, 71219, 73031, 73032)
62#define INOCULATED_HELPER RAID_MODE<uint32>(69291, 72101, 72102, 72103)
63
64uint32 const gaseousBlight[3] = {69157, 69162, 69164};
65uint32 const gaseousBlightVisual[3] = {69126, 69152, 69154};
66
68{
74
77};
78
79enum Misc
80{
82};
83
84struct boss_festergut : public BossAI
85{
87 {
90 }
91
92 void Reset() override
93 {
94 _Reset();
100 _inhaleCounter = 0;
102 if (Creature* gasDummy = me->FindNearestCreature(NPC_GAS_DUMMY, 100.0f, true))
103 {
104 _gasDummyGUID = gasDummy->GetGUID();
105 for (uint8 i = 0; i < 3; ++i)
106 {
108 gasDummy->RemoveAurasDueToSpell(gaseousBlightVisual[i]);
109 }
110 }
111 }
112
113 void JustEngagedWith(Unit* who) override
114 {
116 {
119 return;
120 }
121
122 me->setActive(true);
124 if (Creature* gasDummy = me->FindNearestCreature(NPC_GAS_DUMMY, 100.0f, true))
125 _gasDummyGUID = gasDummy->GetGUID();
127 professor->AI()->DoAction(ACTION_FESTERGUT_COMBAT);
129 }
130
131 void JustDied(Unit* /*killer*/) override
132 {
133 _JustDied();
136 professor->AI()->DoAction(ACTION_FESTERGUT_DEATH);
137
138 RemoveBlight();
139 }
140
141 void JustReachedHome() override
142 {
145 }
146
147 void EnterEvadeMode(EvadeReason why) override
148 {
151 professor->AI()->EnterEvadeMode();
152 }
153
154 void KilledUnit(Unit* victim) override
155 {
156 if (victim->GetTypeId() == TYPEID_PLAYER)
157 Talk(SAY_KILL);
158 }
159
160 void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override
161 {
162 Unit* unitTarget = target->ToUnit();
163 if (!unitTarget)
164 return;
165
166 if (spellInfo->Id == PUNGENT_BLIGHT_HELPER)
168 }
169
170 void UpdateAI(uint32 diff) override
171 {
172 if (!UpdateVictim())
173 return;
174
175 events.Update(diff);
176
178 return;
179
180 while (uint32 eventId = events.ExecuteEvent())
181 {
182 switch (eventId)
183 {
185 {
186 RemoveBlight();
187 if (_inhaleCounter == 3)
188 {
192 _inhaleCounter = 0;
194 professor->AI()->DoAction(ACTION_FESTERGUT_GAS);
196 }
197 else
198 {
200 // just cast and dont bother with target, conditions will handle it
202 if (_inhaleCounter < 3)
204 .SetOriginalCaster(me->GetGUID()));
205 }
206
208 break;
209 }
210 case EVENT_VILE_GAS:
211 {
212 std::list<Unit*> ranged, melee;
213 uint32 minTargets = RAID_MODE<uint32>(3, 8, 3, 8);
214 SelectTargetList(ranged, 25, SelectTargetMethod::Random, 0, -5.0f, true);
215 SelectTargetList(melee, 25, SelectTargetMethod::Random, 0, 5.0f, true);
216 while (ranged.size() < minTargets)
217 {
218 if (melee.empty())
219 break;
220
222 ranged.push_back(target);
223 melee.remove(target);
224 }
225
226 if (!ranged.empty())
227 {
228 Trinity::Containers::RandomResize(ranged, RAID_MODE<uint32>(1, 3, 1, 3));
229 for (std::list<Unit*>::iterator itr = ranged.begin(); itr != ranged.end(); ++itr)
230 DoCast(*itr, SPELL_VILE_GAS);
231 }
232
234 break;
235 }
236 case EVENT_GAS_SPORE:
239 me->CastSpell(me, SPELL_GAS_SPORE, CastSpellExtraArgs().AddSpellMod(SPELLVALUE_MAX_TARGETS, RAID_MODE<int32>(2, 3, 2, 3)));
242 break;
246 break;
247 case EVENT_BERSERK:
250 break;
251 default:
252 break;
253 }
254
256 return;
257 }
258 }
259
260 void SetData(uint32 type, uint32 data) override
261 {
262 if (type == DATA_INOCULATED_STACK && data > _maxInoculatedStack)
263 _maxInoculatedStack = data;
264 }
265
266 uint32 GetData(uint32 type) const override
267 {
268 if (type == DATA_INOCULATED_STACK)
270
271 return 0;
272 }
273
275 {
277 for (uint8 i = 0; i < 3; ++i)
278 {
280 gasDummy->RemoveAurasDueToSpell(gaseousBlightVisual[i]);
281 }
282 }
283
284private:
288};
289
291{
292 npc_stinky_icc(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
293
294 void Reset() override
295 {
296 _events.Reset();
299 }
300
301 void JustEngagedWith(Unit* /*target*/) override
302 {
304 }
305
306 void UpdateAI(uint32 diff) override
307 {
308 if (!UpdateVictim())
309 return;
310
311 _events.Update(diff);
312
314 return;
315
316 while (uint32 eventId = _events.ExecuteEvent())
317 {
318 switch (eventId)
319 {
320 case EVENT_DECIMATE:
323 break;
327 break;
328 default:
329 break;
330 }
331 }
332 }
333
334 void JustDied(Unit* /*killer*/) override
335 {
337 if (festergut->IsAlive())
338 festergut->AI()->Talk(SAY_STINKY_DEAD);
339 }
340
341private:
344};
345
346// 69195, 71219, 73031, 73032 - Pungent Blight
348{
349 bool Load() override
350 {
351 return GetCaster()->GetTypeId() == TYPEID_UNIT;
352 }
353
354 void HandleScript(SpellEffIndex /*effIndex*/)
355 {
358 }
359
360 void Register() override
361 {
363 }
364};
365
366// 72219, 72551, 72552, 72553 - Gastric Bloat
368{
369 bool Validate(SpellInfo const* /*spell*/) override
370 {
372 }
373
374 void HandleScript(SpellEffIndex /*effIndex*/)
375 {
376 Aura const* aura = GetHitUnit()->GetAura(GetSpellInfo()->Id);
377 if (!(aura && aura->GetStackAmount() == 10))
378 return;
379
382 }
383
384 void Register() override
385 {
387 }
388};
389
390// 69290, 71222, 73033, 73034 - Blighted Spores
392{
393 bool Validate(SpellInfo const* /*spell*/) override
394 {
396 }
397
398 void ExtraEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
399 {
401 if (InstanceScript* instance = GetTarget()->GetInstanceScript())
402 if (Creature* festergut = ObjectAccessor::GetCreature(*GetTarget(), instance->GetGuidData(DATA_FESTERGUT)))
403 festergut->AI()->SetData(DATA_INOCULATED_STACK, GetStackAmount());
404
406 }
407
409 {
410 Player* target = GetUnitOwner()->ToPlayer();
411 if (!target)
412 return;
413
415 return;
416
418 if (target->GetQuestStatus(questId) != QUEST_STATUS_INCOMPLETE)
419 return;
420
422 }
423
424 void Register() override
425 {
427 }
428};
429
431{
432 public:
433 achievement_flu_shot_shortage() : AchievementCriteriaScript("achievement_flu_shot_shortage") { }
434
435 bool OnCheck(Player* /*source*/, Unit* target) override
436 {
437 if (target && target->GetTypeId() == TYPEID_UNIT)
438 return target->ToCreature()->AI()->GetData(DATA_INOCULATED_STACK) < 3;
439
440 return false;
441 }
442};
443
445{
446 // Creatures
449
450 // Spells
454
455 // Achievements
457}
uint8_t uint8
Definition: Define.h:144
uint32_t uint32
Definition: Define.h:142
@ FAIL
@ TYPEID_UNIT
Definition: ObjectGuid.h:40
@ TYPEID_PLAYER
Definition: ObjectGuid.h:41
Spells
Definition: PlayerAI.cpp:32
@ QUEST_STATUS_INCOMPLETE
Definition: QuestDef.h:145
#define RegisterSpellScript(spell_script)
Definition: ScriptMgr.h:1369
SpellEffIndex
Definition: SharedDefines.h:29
@ EFFECT_1
Definition: SharedDefines.h:31
@ EFFECT_0
Definition: SharedDefines.h:30
@ EFFECT_2
Definition: SharedDefines.h:32
@ SPELL_EFFECT_SCRIPT_EFFECT
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
@ SPELL_AURA_PERIODIC_DAMAGE
@ TRIGGERED_FULL_MASK
Used when doing CastSpell with triggered == true.
Definition: SpellDefines.h:266
@ SPELLVALUE_MAX_TARGETS
Definition: SpellDefines.h:230
#define SpellEffectFn(F, I, N)
Definition: SpellScript.h:842
#define AuraEffectRemoveFn(F, I, N, M)
Definition: SpellScript.h:2040
EvadeReason
Definition: UnitAICommon.h:30
@ UNIT_STATE_CASTING
Definition: Unit.h:270
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
Unit * GetTarget() const
HookList< EffectApplyHandler > OnEffectRemove
Definition: SpellScript.h:2035
Unit * GetUnitOwner() const
uint8 GetStackAmount() const
uint8 GetStackAmount() const
Definition: SpellAuras.h:189
InstanceScript *const instance
void _JustReachedHome()
EventMap events
void _JustDied()
void DoZoneInCombat()
Definition: CreatureAI.h:161
virtual void EnterEvadeMode(EvadeReason why=EvadeReason::Other)
Definition: CreatureAI.cpp:219
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
CreatureAI * AI() const
Definition: Creature.h:214
uint32 ExecuteEvent()
Definition: EventMap.cpp:73
void Update(uint32 time)
Definition: EventMap.h:56
void ScheduleEvent(uint32 eventId, Milliseconds time, uint32 group=0, uint8 phase=0)
Definition: EventMap.cpp:36
void RescheduleEvent(uint32 eventId, Milliseconds time, uint32 group=0, uint8 phase=0)
Definition: EventMap.cpp:52
void Reset()
Definition: EventMap.cpp:21
virtual bool SetBossState(uint32 id, EncounterState state)
void DoCastSpellOnPlayers(uint32 spell, bool includePets=false, bool includeControlled=false)
virtual ObjectGuid GetGuidData(uint32 type) const override
virtual bool CheckRequiredBosses(uint32, Player const *=nullptr) const
bool Is25ManRaid() const
Definition: Map.cpp:3320
static Creature * ToCreature(Object *o)
Definition: Object.h:219
static Unit * ToUnit(Object *o)
Definition: Object.h:225
TypeID GetTypeId() const
Definition: Object.h:173
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
static Player * ToPlayer(Object *o)
Definition: Object.h:213
QuestStatus GetQuestStatus(uint32 quest_id) const
Definition: Player.cpp:16050
uint32 const Id
Definition: SpellInfo.h:325
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
Definition: SpellScript.h:162
Unit * GetCaster() const
Unit * GetHitUnit() const
int32 GetEffectValue() const
HookList< EffectHandler > OnEffectHitTarget
Definition: SpellScript.h:840
SpellInfo const * GetSpellInfo() const
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.h:159
virtual uint32 GetData(uint32) const
Definition: UnitAI.h:73
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.cpp:180
void SelectTargetList(std::list< Unit * > &targetList, uint32 num, SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition: UnitAI.cpp:84
SpellCastResult DoCast(uint32 spellId)
Definition: UnitAI.cpp:89
Definition: Unit.h:627
Aura * GetAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition: Unit.cpp:4560
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
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3831
Map * GetMap() const
Definition: Object.h:624
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition: Object.cpp:2896
void setActive(bool isActiveObject)
Definition: Object.cpp:922
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition: Object.cpp:2148
bool OnCheck(Player *, Unit *target) override
void ExtraEffect(AuraEffect const *, AuraEffectHandleModes)
bool Validate(SpellInfo const *) override
void HandleScript(SpellEffIndex)
bool Validate(SpellInfo const *) override
void HandleScript(SpellEffIndex)
@ SPELL_ORANGE_BLIGHT_RESIDUE
@ SPELL_BERSERK2
@ LIGHT_S_HAMMER_TELEPORT
#define RegisterIcecrownCitadelCreatureAI(ai_name)
@ ACTION_FESTERGUT_DEATH
@ ACTION_FESTERGUT_GAS
@ ACTION_FESTERGUT_COMBAT
@ DATA_PROFESSOR_PUTRICIDE
@ DATA_FESTERGUT
@ NPC_GAS_DUMMY
@ QUEST_RESIDUE_RENDEZVOUS_10
@ QUEST_RESIDUE_RENDEZVOUS_25
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
void RandomResize(C &container, std::size_t requestedSize)
Definition: Containers.h:67
void SpellHitTarget(WorldObject *target, SpellInfo const *spellInfo) override
void UpdateAI(uint32 diff) override
void JustReachedHome() override
uint32 _maxInoculatedStack
void KilledUnit(Unit *victim) override
uint32 GetData(uint32 type) const override
void SetData(uint32 type, uint32 data) override
void Reset() override
ObjectGuid _gasDummyGUID
void JustDied(Unit *) override
void EnterEvadeMode(EvadeReason why) override
void JustEngagedWith(Unit *who) override
boss_festergut(Creature *creature)
void Reset() override
void JustEngagedWith(Unit *) override
npc_stinky_icc(Creature *creature)
void JustDied(Unit *) override
void UpdateAI(uint32 diff) override
InstanceScript * _instance