TrinityCore
Loading...
Searching...
No Matches
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
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
78
83
84// 36626 - Festergut
85struct boss_festergut : public BossAI
86{
88 {
91 }
92
93 void Reset() override
94 {
95 _Reset();
101 _inhaleCounter = 0;
103 if (Creature* gasDummy = me->FindNearestCreature(NPC_GAS_DUMMY, 100.0f, true))
104 {
105 _gasDummyGUID = gasDummy->GetGUID();
106 for (uint8 i = 0; i < 3; ++i)
107 {
109 gasDummy->RemoveAurasDueToSpell(gaseousBlightVisual[i]);
110 }
111 }
112 }
113
114 void JustEngagedWith(Unit* who) override
115 {
117 {
120 return;
121 }
122
123 me->setActive(true);
125 if (Creature* gasDummy = me->FindNearestCreature(NPC_GAS_DUMMY, 100.0f, true))
126 _gasDummyGUID = gasDummy->GetGUID();
128 professor->AI()->DoAction(ACTION_FESTERGUT_COMBAT);
130 }
131
132 void JustDied(Unit* /*killer*/) override
133 {
134 _JustDied();
137 professor->AI()->DoAction(ACTION_FESTERGUT_DEATH);
138
139 RemoveBlight();
140 }
141
142 void JustReachedHome() override
143 {
146 }
147
148 void EnterEvadeMode(EvadeReason why) override
149 {
152 professor->AI()->EnterEvadeMode();
153 }
154
155 void KilledUnit(Unit* victim) override
156 {
157 if (victim->GetTypeId() == TYPEID_PLAYER)
158 Talk(SAY_KILL);
159 }
160
161 void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override
162 {
163 Unit* unitTarget = target->ToUnit();
164 if (!unitTarget)
165 return;
166
167 if (spellInfo->Id == PUNGENT_BLIGHT_HELPER)
169 }
170
171 void UpdateAI(uint32 diff) override
172 {
173 if (!UpdateVictim())
174 return;
175
176 events.Update(diff);
177
179 return;
180
181 while (uint32 eventId = events.ExecuteEvent())
182 {
183 switch (eventId)
184 {
186 {
187 RemoveBlight();
188 if (_inhaleCounter == 3)
189 {
193 _inhaleCounter = 0;
195 professor->AI()->DoAction(ACTION_FESTERGUT_GAS);
197 }
198 else
199 {
201 // just cast and dont bother with target, conditions will handle it
203 if (_inhaleCounter < 3)
205 .SetOriginalCaster(me->GetGUID()));
206 }
207
209 break;
210 }
211 case EVENT_VILE_GAS:
212 {
213 std::list<Unit*> ranged, melee;
214 uint32 minTargets = RAID_MODE<uint32>(3, 8, 3, 8);
215 SelectTargetList(ranged, 25, SelectTargetMethod::Random, 0, -5.0f, true);
216 SelectTargetList(melee, 25, SelectTargetMethod::Random, 0, 5.0f, true);
217 while (ranged.size() < minTargets)
218 {
219 if (melee.empty())
220 break;
221
223 ranged.push_back(target);
224 melee.remove(target);
225 }
226
227 if (!ranged.empty())
228 {
229 Trinity::Containers::RandomResize(ranged, RAID_MODE<uint32>(1, 3, 1, 3));
230 for (std::list<Unit*>::iterator itr = ranged.begin(); itr != ranged.end(); ++itr)
231 DoCast(*itr, SPELL_VILE_GAS);
232 }
233
235 break;
236 }
237 case EVENT_GAS_SPORE:
240 me->CastSpell(me, SPELL_GAS_SPORE, CastSpellExtraArgs().AddSpellMod(SPELLVALUE_MAX_TARGETS, RAID_MODE<int32>(2, 3, 2, 3)));
243 break;
247 break;
248 case EVENT_BERSERK:
251 break;
252 default:
253 break;
254 }
255
257 return;
258 }
259 }
260
261 void SetData(uint32 type, uint32 data) override
262 {
263 if (type == DATA_INOCULATED_STACK && data > _maxInoculatedStack)
264 _maxInoculatedStack = data;
265 }
266
267 uint32 GetData(uint32 type) const override
268 {
269 if (type == DATA_INOCULATED_STACK)
271
272 return 0;
273 }
274
276 {
278 for (uint8 i = 0; i < 3; ++i)
279 {
281 gasDummy->RemoveAurasDueToSpell(gaseousBlightVisual[i]);
282 }
283 }
284
285private:
289};
290
291// 37025 - Stinky
293{
294 npc_stinky_icc(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
295
296 void Reset() override
297 {
298 _events.Reset();
301 }
302
303 void JustEngagedWith(Unit* /*target*/) override
304 {
306 }
307
308 void UpdateAI(uint32 diff) override
309 {
310 if (!UpdateVictim())
311 return;
312
313 _events.Update(diff);
314
316 return;
317
318 while (uint32 eventId = _events.ExecuteEvent())
319 {
320 switch (eventId)
321 {
322 case EVENT_DECIMATE:
325 break;
329 break;
330 default:
331 break;
332 }
333 }
334 }
335
336 void JustDied(Unit* /*killer*/) override
337 {
339 if (festergut->IsAlive())
340 festergut->AI()->Talk(SAY_STINKY_DEAD);
341 }
342
343private:
346};
347
348// 69195, 71219, 73031, 73032 - Pungent Blight
367
368// 72219, 72551, 72552, 72553 - Gastric Bloat
370{
371 bool Validate(SpellInfo const* /*spell*/) override
372 {
374 }
375
376 void HandleScript(SpellEffIndex /*effIndex*/)
377 {
378 Aura const* aura = GetHitUnit()->GetAura(GetSpellInfo()->Id);
379 if (!(aura && aura->GetStackAmount() == 10))
380 return;
381
384 }
385
390};
391
392// 69290, 71222, 73033, 73034 - Blighted Spores
394{
395 bool Validate(SpellInfo const* /*spell*/) override
396 {
398 }
399
400 void ExtraEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
401 {
403 if (InstanceScript* instance = GetTarget()->GetInstanceScript())
404 if (Creature* festergut = ObjectAccessor::GetCreature(*GetTarget(), instance->GetGuidData(DATA_FESTERGUT)))
405 festergut->AI()->SetData(DATA_INOCULATED_STACK, GetStackAmount());
406
408 }
409
411 {
412 Player* target = GetUnitOwner()->ToPlayer();
413 if (!target)
414 return;
415
417 return;
418
420 if (target->GetQuestStatus(questId) != QUEST_STATUS_INCOMPLETE)
421 return;
422
424 }
425
430};
431
433{
434 public:
435 achievement_flu_shot_shortage() : AchievementCriteriaScript("achievement_flu_shot_shortage") { }
436
437 bool OnCheck(Player* /*source*/, Unit* target) override
438 {
439 if (target && target->GetTypeId() == TYPEID_UNIT)
440 return target->ToCreature()->AI()->GetData(DATA_INOCULATED_STACK) < 3;
441
442 return false;
443 }
444};
445
uint8_t uint8
Definition Define.h:156
uint32_t uint32
Definition Define.h:154
@ FAIL
@ TYPEID_UNIT
Definition ObjectGuid.h:43
@ TYPEID_PLAYER
Definition ObjectGuid.h:44
@ QUEST_STATUS_INCOMPLETE
Definition QuestDef.h:146
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1383
SpellEffIndex
@ EFFECT_1
@ EFFECT_0
@ EFFECT_2
@ SPELL_EFFECT_SCRIPT_EFFECT
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
@ SPELL_AURA_PERIODIC_DAMAGE
@ SPELLVALUE_MAX_TARGETS
@ TRIGGERED_FULL_MASK
Used when doing CastSpell with triggered == true.
#define SpellEffectFn(F, I, N)
#define AuraEffectRemoveFn(F, I, N, M)
EvadeReason
@ UNIT_STATE_CASTING
Definition Unit.h:290
FestergutSpells
@ 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
uint32 const gaseousBlight[3]
#define INOCULATED_HELPER
#define PUNGENT_BLIGHT_HELPER
FestergutTexts
@ 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
FestergutEvents
@ EVENT_VILE_GAS
@ EVENT_MORTAL_WOUND
@ EVENT_GASTRIC_BLOAT
@ EVENT_BERSERK
@ EVENT_GAS_SPORE
@ EVENT_INHALE_BLIGHT
@ EVENT_DECIMATE
FestergutMisc
@ DATA_INOCULATED_STACK
void AddSC_boss_festergut()
uint32 const gaseousBlightVisual[3]
Unit * GetTarget() const
HookList< EffectApplyHandler > OnEffectRemove
Unit * GetUnitOwner() const
uint8 GetStackAmount() const
uint8 GetStackAmount() const
Definition SpellAuras.h:238
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
TypeID GetTypeId() const
Definition BaseEntity.h:166
InstanceScript *const instance
void _JustReachedHome()
EventMap events
void DoZoneInCombat()
Definition CreatureAI.h:169
virtual void EnterEvadeMode(EvadeReason why=EvadeReason::Other)
void Talk(uint8 id, WorldObject const *whisperTarget=nullptr)
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:63
CreatureAI * AI() const
Definition Creature.h:235
void Update(uint32 time)
Definition EventMap.h:77
EventId ExecuteEvent()
Definition EventMap.cpp:77
void RescheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:56
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:40
void Reset()
Definition EventMap.cpp:25
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:3385
Player * ToPlayer()
Definition Object.h:126
Creature * ToCreature()
Definition Object.h:121
Unit * ToUnit()
Definition Object.h:116
QuestStatus GetQuestStatus(uint32 quest_id) const
Definition Player.cpp:15929
uint32 const Id
Definition SpellInfo.h:328
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
Unit * GetCaster() const
int32 GetEffectValueAsInt() const
Unit * GetHitUnit() const
HookList< EffectHandler > OnEffectHitTarget
SpellInfo const * GetSpellInfo() const
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:160
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:172
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:76
virtual uint32 GetData(uint32 id) const
Definition UnitAI.h:74
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:81
Definition Unit.h:647
Aura * GetAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4718
bool HasUnitState(const uint32 f) const
Definition Unit.h:755
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4822
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3992
Map * GetMap() const
Definition Object.h:411
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2222
void setActive(bool isActiveObject)
Definition Object.cpp:274
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition Object.cpp:1522
bool OnCheck(Player *, Unit *target) override
void ExtraEffect(AuraEffect const *, AuraEffectHandleModes)
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
@ 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) -> std::add_const_t< decltype(*std::ranges::begin(container))> &
Definition Containers.h:110
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
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