TrinityCore
Loading...
Searching...
No Matches
boss_professor_putricide.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 "DB2Stores.h"
21#include "GridNotifiers.h"
22#include "Group.h"
23#include "InstanceScript.h"
24#include "Map.h"
25#include "MotionMaster.h"
26#include "ObjectAccessor.h"
27#include "ScriptedCreature.h"
28#include "ScriptMgr.h"
29#include "Spell.h"
30#include "SpellAuraEffects.h"
31#include "SpellMgr.h"
32#include "SpellScript.h"
33#include "TemporarySummon.h"
34#include "Vehicle.h"
35
37{
38 // Festergut
41
42 // Rotface
45
46 // Professor Putricide
51 SAY_TRANSFORM_2 = 8, // always used for phase2 change, DO NOT GROUP WITH SAY_TRANSFORM_1
56 SAY_DEATH = 13
57};
58
60{
61 // Festergut
68
69 // Professor Putricide
73 SPELL_TEAR_GAS = 71617, // phase transition
80 SPELL_OOZE_TANK_PROTECTION = 71770, // protects the tank
90
91 // Slime Puddle
93 SPELL_GROW = 70347,
95
96 // Gas Cloud
101
102 // Volatile Ooze
107
108 // Choking Gas Bomb
111
112 // Mutated Abomination vehicle
117
118 // Unholy Infusion
121
123{
124 // Festergut
127
128 // Rotface
131
132 // Professor Putricide
133 EVENT_BERSERK = 6, // all phases
134 EVENT_SLIME_PUDDLE = 7, // all phases
136 EVENT_TEAR_GAS = 9, // phase transition not heroic
144
154
156{
159 POINT_TABLE = 366780
161
162Position const festergutWatchPos = {4324.820f, 3166.03f, 389.3831f, 3.316126f}; //emote 432 (release gas)
163Position const rotfaceWatchPos = {4390.371f, 3164.50f, 389.3890f, 5.497787f}; //emote 432 (release ooze)
164Position const tablePos = {4356.190f, 3262.90f, 389.4820f, 1.483530f};
165
166// used in Rotface encounter
167uint32 const oozeFloodSpells[4] = {69782, 69796, 69798, 69801};
168
175
176#define EXPERIMENT_STATE_OOZE false
177#define EXPERIMENT_STATE_GAS true
178
180{
181 public:
182 explicit AbominationDespawner(Unit* owner) : _owner(owner) { }
183
185 {
186 if (Unit* summon = ObjectAccessor::GetUnit(*_owner, guid))
187 {
188 if (summon->GetEntry() == NPC_MUTATED_ABOMINATION_10 || summon->GetEntry() == NPC_MUTATED_ABOMINATION_25)
189 {
190 if (Vehicle* veh = summon->GetVehicleKit())
191 veh->RemoveAllPassengers(); // also despawns the vehicle
192
193 // Found unit is Mutated Abomination, remove it
194 return true;
195 }
196
197 // Found unit is not Mutated Abomintaion, leave it
198 return false;
199 }
200
201 // No unit found, remove from SummonList
202 return true;
203 }
204
205 private:
207};
208
210{
211 RotfaceHeightCheck(Creature* rotface) : _rotface(rotface) { }
212
213 bool operator()(Creature* stalker) const
214 {
215 return stalker->GetPositionZ() < _rotface->GetPositionZ() + 5.0f;
216 }
217
218private:
220};
221
222// 36678 - Professor Putricide
224{
231
251
278
286
287 void KilledUnit(Unit* victim) override
288 {
289 if (victim->GetTypeId() == TYPEID_PLAYER)
290 Talk(SAY_KILL);
291 }
292
293 void JustDied(Unit* /*killer*/) override
294 {
295 _JustDied();
297
300
302 }
303
304 void JustSummoned(Creature* summon) override
305 {
306 summons.Summon(summon);
307 switch (summon->GetEntry())
308 {
311 return;
313 summon->CastSpell(summon, SPELL_GROW_STACKER, true);
314 summon->CastSpell(summon, SPELL_SLIME_PUDDLE_AURA, true);
315 // blizzard casts this spell 7 times initially (confirmed in sniff)
316 for (uint8 i = 0; i < 7; ++i)
317 summon->CastSpell(summon, SPELL_GROW, true);
318 break;
319 case NPC_GAS_CLOUD:
320 // no possible aura seen in sniff adding the aurastate
323 break;
325 // no possible aura seen in sniff adding the aurastate
328 break;
330 summon->CastSpell(summon, SPELL_CHOKING_GAS_BOMB_PERIODIC, true);
331 summon->CastSpell(summon, SPELL_CHOKING_GAS_EXPLOSION_TRIGGER, true);
332 return;
335 return;
336 default:
337 break;
338 }
339
340 if (me->IsInCombat())
341 DoZoneInCombat(summon);
342 }
343
344 void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
345 {
347 return;
348
349 switch (_phase)
350 {
351 case PHASE_COMBAT_1:
352 if (HealthAbovePct(80))
353 return;
356 break;
357 case PHASE_COMBAT_2:
358 if (HealthAbovePct(35))
359 return;
362 break;
363 default:
364 break;
365 }
366 }
367
368 void MovementInform(uint32 type, uint32 id) override
369 {
370 if (type != POINT_MOTION_TYPE)
371 return;
372 switch (id)
373 {
374 case POINT_FESTERGUT:
375 instance->SetBossState(DATA_FESTERGUT, IN_PROGRESS); // needed here for delayed gate close
379 festergut->CastSpell(festergut, SPELL_GASEOUS_BLIGHT_LARGE, CastSpellExtraArgs().SetOriginalCaster(festergut->GetGUID()));
380 break;
381 case POINT_ROTFACE:
382 instance->SetBossState(DATA_ROTFACE, IN_PROGRESS); // needed here for delayed gate close
386 break;
387 case POINT_TABLE:
388 // stop attack
392 me->SetFacingToObject(table);
393 // operating on new phase already
394 switch (_phase)
395 {
396 case PHASE_COMBAT_2:
397 {
398 SpellInfo const* spell = sSpellMgr->GetSpellInfo(SPELL_CREATE_CONCOCTION, GetDifficulty());
401 break;
402 }
403 case PHASE_COMBAT_3:
404 {
405 SpellInfo const* spell = sSpellMgr->GetSpellInfo(SPELL_GUZZLE_POTIONS, GetDifficulty());
408 break;
409 }
410 default:
411 break;
412 }
413 break;
414 default:
415 break;
416 }
417 }
418
419 void DoAction(int32 action) override
420 {
421 switch (action)
422 {
428 EngagementStart(nullptr);
429 if (IsHeroic())
431 break;
435 break;
438 break;
444 EngagementStart(nullptr);
445 _oozeFloodStage = 0;
446 // init random sequence of floods
448 {
449 std::list<Creature*> list;
451 list.remove_if(RotfaceHeightCheck(rotface));
452 if (list.size() > 4)
453 {
454 list.sort(Trinity::ObjectDistanceOrderPred(rotface));
455 do
456 {
457 list.pop_back();
458 } while (list.size() > 4);
459 }
460
461 uint8 i = 0;
462 while (!list.empty())
463 {
464 std::list<Creature*>::iterator itr = list.begin();
465 std::advance(itr, urand(0, list.size()-1));
466 _oozeFloodDummyGUIDs[i++] = (*itr)->GetGUID();
467 list.erase(itr);
468 }
469 }
470 break;
475 .SetOriginalCaster(me->GetGUID())); // cast from self for LoS (with prof's GUID for logs)
476 if (++_oozeFloodStage == 4)
477 _oozeFloodStage = 0;
478 break;
481 break;
484 events.DelayEvents(30s);
485 me->AttackStop();
486 if (!IsHeroic())
487 {
490 }
491 else
492 {
496 // cast variables
497 if (Is25ManRaid())
498 {
499 std::list<Unit*> targetList;
500 {
502 if (Player* target = ref->GetVictim()->ToPlayer())
503 targetList.push_back(target);
504 }
505
506 size_t half = targetList.size()/2;
507 // half gets ooze variable
508 while (half < targetList.size())
509 {
510 std::list<Unit*>::iterator itr = targetList.begin();
511 advance(itr, urand(0, targetList.size() - 1));
512 (*itr)->CastSpell(*itr, SPELL_OOZE_VARIABLE, true);
513 targetList.erase(itr);
514 }
515 // and half gets gas
516 for (std::list<Unit*>::iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
517 (*itr)->CastSpell(*itr, SPELL_GAS_VARIABLE, true);
518 }
520 }
521 switch (_phase)
522 {
523 case PHASE_COMBAT_1:
527 break;
528 case PHASE_COMBAT_2:
532 break;
533 default:
534 break;
535 }
536 break;
537 default:
538 break;
539 }
540 }
541
542 uint32 GetData(uint32 type) const override
543 {
544 switch (type)
545 {
547 return _experimentState;
548 case DATA_PHASE:
549 return _phase;
550 case DATA_ABOMINATION:
552 default:
553 break;
554 }
555
556 return 0;
557 }
558
559 void SetData(uint32 id, uint32 data) override
560 {
561 if (id == DATA_EXPERIMENT_STAGE)
562 _experimentState = data != 0;
563 }
564
565 void UpdateAI(uint32 diff) override
566 {
568 return;
569
570 events.Update(diff);
571
573 return;
574
575 while (uint32 eventId = events.ExecuteEvent())
576 {
577 switch (eventId)
578 {
582 break;
585 if (Is25ManRaid())
587 else
589 break;
593 break;
597 break;
598 case EVENT_BERSERK:
601 break;
603 {
604 std::list<Unit*> targets;
605 SelectTargetList(targets, 2, SelectTargetMethod::Random, 0, 0.0f, true);
606 if (!targets.empty())
607 for (std::list<Unit*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
610 break;
611 }
616 break;
617 case EVENT_TEAR_GAS:
620 break;
624 // remove Tear Gas
629 break;
631 if (Is25ManRaid())
632 {
633 std::list<Unit*> targets;
634 SelectTargetList(targets, 2, SelectTargetMethod::Random, 0, -7.0f, true);
635 if (!targets.empty())
636 {
638 for (std::list<Unit*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
640 }
641 }
642 else
643 {
644 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, -7.0f, true))
645 {
648 }
649 }
651 break;
656 break;
659 {
662 }
664 break;
668 break;
670 {
671 switch (_phase)
672 {
673 case PHASE_COMBAT_2:
675 me->SetFacingToObject(face);
679 break;
680 case PHASE_COMBAT_3:
682 me->SetFacingToObject(face);
687 break;
688 default:
689 break;
690 }
691 break;
692 }
693 default:
694 break;
695 }
696
698 return;
699 }
700 }
701
702private:
704 {
705 _phase = newPhase;
706 events.SetPhase(newPhase);
707 }
708
710 PutricidePhases _phase; // external of EventMap because event phase gets reset on evade
711 float const _baseSpeed;
714};
715
717{
718 public:
719 npc_putricide_oozeAI(Creature* creature, uint32 auraSpellId, uint32 hitTargetSpellId) : ScriptedAI(creature),
720 _auraSpellId(auraSpellId), _hitTargetSpellId(hitTargetSpellId), _newTargetSelectTimer(0), _instance(creature->GetInstanceScript()) { }
721
722 void SpellHitTarget(WorldObject* /*target*/, SpellInfo const* spellInfo) override
723 {
724 if (!_newTargetSelectTimer && spellInfo->Id == _hitTargetSpellId)
725 {
727 // go passive until next target selection
729 }
730 }
731
732 void Reset() override
733 {
736
738 DoCastAOE(_auraSpellId, true);
739 }
740
741 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
742 {
743 if (spellInfo->Id == SPELL_TEAR_GAS_CREATURE)
745 }
746
747 void UpdateAI(uint32 diff) override
748 {
750 return;
751
752 if (!_newTargetSelectTimer && !me->IsNonMeleeSpellCast(false, false, true, false, true))
754
756 return;
757
759 return;
760
761 if (_newTargetSelectTimer <= diff)
762 {
765 }
766 else
767 _newTargetSelectTimer -= diff;
768 }
769
770 virtual void CastMainSpell() = 0;
771
772 private:
777};
778
779// 37697 - Volatile Ooze
789
790// 37562 - Gas Cloud
808
809// 70672, 72455, 72832, 72833 - Gaseous Bloat
811{
812 void HandleExtraEffect(AuraEffect const* /*aurEff*/)
813 {
814 Unit* target = GetTarget();
815 if (Unit* caster = GetCaster())
816 {
818 if (!target->HasAura(GetId()))
819 {
822 caster->CastSpell(caster, SPELL_GASEOUS_BLOAT, args);
823 }
824 }
825 }
826
827 void HandleProc(ProcEventInfo& eventInfo)
828 {
829 uint32 stack = GetStackAmount();
830 Unit* caster = eventInfo.GetActor();
831
832 int32 const mod = caster->GetMap()->Is25ManRaid() ? 1500 : 1250;
833 int32 dmg = 0;
834 for (uint8 i = 1; i <= stack; ++i)
835 dmg += mod * i;
836
838 args.AddSpellBP0(dmg);
839 caster->CastSpell(nullptr, SPELL_EXPUNGED_GAS, args);
840 }
841
847};
848
849// 70447, 72836, 72837, 72838 - Volatile Ooze Adhesive
850// 70672, 72455, 72832, 72833 - Gaseous Bloat
852{
853 bool Validate(SpellInfo const* spell) override
854 {
855 return ValidateSpellInfo({ spell->ExcludeTargetAuraSpell });
856 }
857
858 // set up initial variables and check if caster is creature
859 // this will let use safely use ToCreature() casts in entire script
860 bool Load() override
861 {
862 return GetCaster()->GetTypeId() == TYPEID_UNIT;
863 }
864
865 void SelectTarget(std::list<WorldObject*>& targets)
866 {
867 if (targets.empty())
868 {
870 GetCaster()->ToCreature()->DespawnOrUnsummon(1ms); // despawn next update
871 return;
872 }
873
875 targets.clear();
876 targets.push_back(target);
877 _target = target;
878 }
879
880 void SetTarget(std::list<WorldObject*>& targets)
881 {
882 targets.clear();
883 if (_target)
884 targets.push_back(_target);
885 }
886
896
904
906};
907
909{
910 public:
911 ExactDistanceCheck(Unit* source, float dist) : _source(source), _dist(dist) { }
912
913 bool operator()(WorldObject* unit) const
914 {
915 return _source->GetExactDist2d(unit) > _dist;
916 }
917
918 private:
920 float _dist;
921};
922
923// 70346, 72456, 72868, 72869 - Slime Puddle
937
938// this is here only because on retail you dont actually enter HEROIC mode for ICC
939// 72868, 72869 - Slime Puddle
941{
943 {
944 if (Unit* target = GetHitUnit())
945 GetCaster()->AddAura(GetCaster()->GetMap()->Is25ManRaid() ? 72456 : 70346, target);
946 }
947
952};
953
954// 70351, 71966, 71967, 71968 - Unstable Experiment
956{
958 {
959 PreventHitDefaultEffect(effIndex);
960 if (GetCaster()->GetTypeId() != TYPEID_UNIT)
961 return;
962
963 Creature* creature = GetCaster()->ToCreature();
964
965 uint32 stage = creature->AI()->GetData(DATA_EXPERIMENT_STAGE);
966 creature->AI()->SetData(DATA_EXPERIMENT_STAGE, stage ^ true);
967
968 Creature* target = nullptr;
969 std::list<Creature*> creList;
971 // 2 of them are spawned at green place - weird trick blizz
972 for (std::list<Creature*>::iterator itr = creList.begin(); itr != creList.end(); ++itr)
973 {
974 target = *itr;
975 std::list<Creature*> tmp;
977 if ((!stage && tmp.size() > 1) || (stage && tmp.size() == 1))
978 break;
979 }
980
981 GetCaster()->CastSpell(target, uint32(GetEffectInfo(SpellEffIndex(stage)).CalcValueAsInt()), true);
982 }
983
988};
989
990// 70459 - Ooze Eruption Search Effect
1007
1008// 71770 - Ooze Spell Tank Protection
1010{
1011 bool Validate(SpellInfo const* spellInfo) override
1012 {
1013 return ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 } })
1014 && ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0).TriggerSpell, spellInfo->GetEffect(EFFECT_1).TriggerSpell });
1015 }
1016
1017 void HandleProc(AuraEffect* aurEff, ProcEventInfo& eventInfo)
1018 {
1020
1021 Unit* actionTarget = eventInfo.GetActionTarget();
1022 actionTarget->CastSpell(nullptr, aurEff->GetSpellEffectInfo().TriggerSpell, aurEff);
1023 }
1024
1030};
1031
1032// 71255 - Choking Gas Bomb
1034{
1035 void HandleScript(SpellEffIndex /*effIndex*/)
1036 {
1037 uint32 skipIndex = urand(0, 2);
1038 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
1039 {
1040 if (spellEffectInfo.EffectIndex == skipIndex)
1041 continue;
1042
1043 uint32 spellId = uint32(spellEffectInfo.CalcValueAsInt());
1045 .SetOriginalCaster(GetCaster()->GetGUID()));
1046 }
1047 }
1048
1053};
1054
1055// 70920 - Unbound Plague Search Effect
1057{
1058 bool Validate(SpellInfo const* /*spell*/) override
1059 {
1061 }
1062
1063 void FilterTargets(std::list<WorldObject*>& targets)
1064 {
1065 if (AuraEffect const* eff = GetCaster()->GetAuraEffect(SPELL_UNBOUND_PLAGUE_SEARCHER, EFFECT_0))
1066 {
1067 if (eff->GetTickNumber() < 2)
1068 {
1069 targets.clear();
1070 return;
1071 }
1072 }
1073
1074 targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_UNBOUND_PLAGUE));
1076 }
1077
1078 void HandleScript(SpellEffIndex /*effIndex*/)
1079 {
1080 if (!GetHitUnit())
1081 return;
1082
1084 if (!instance)
1085 return;
1086
1088 {
1090 {
1091 if (Aura* oldPlague = GetCaster()->GetAura(SPELL_UNBOUND_PLAGUE, professor->GetGUID()))
1092 {
1093 if (Aura* newPlague = professor->AddAura(SPELL_UNBOUND_PLAGUE, GetHitUnit()))
1094 {
1095 newPlague->SetMaxDuration(oldPlague->GetMaxDuration());
1096 newPlague->SetDuration(oldPlague->GetDuration());
1097 oldPlague->Remove();
1101 professor->CastSpell(GetHitUnit(), SPELL_UNBOUND_PLAGUE_SEARCHER, true);
1102 }
1103 }
1104 }
1105 }
1106 }
1107
1113};
1114
1115// 70360, 72527 - Eat Ooze
1117{
1118 void SelectTarget(std::list<WorldObject*>& targets)
1119 {
1120 if (targets.empty())
1121 return;
1122
1124 WorldObject* target = targets.front();
1125 targets.clear();
1126 targets.push_back(target);
1127 }
1128
1129 void HandleScript(SpellEffIndex /*effIndex*/)
1130 {
1131 Creature* target = GetHitCreature();
1132 if (!target)
1133 return;
1134
1135 if (Aura* grow = target->GetAura(uint32(GetEffectValueAsInt())))
1136 {
1137 if (grow->GetStackAmount() < 3)
1138 {
1140 target->RemoveAura(grow);
1141 target->DespawnOrUnsummon(1ms);
1142 }
1143 else
1144 grow->ModStackAmount(-3);
1145 }
1146 }
1147
1153};
1154
1155// 72451, 72463, 72671, 72672 - Mutated Plague
1157{
1158 void HandleTriggerSpell(AuraEffect const* aurEff)
1159 {
1161 Unit* caster = GetCaster();
1162 if (!caster)
1163 return;
1164
1165 uint32 triggerSpell = aurEff->GetSpellEffectInfo().TriggerSpell;
1166 SpellInfo const* spell = sSpellMgr->AssertSpellInfo(triggerSpell, GetCastDifficulty());
1167
1168 SpellEffectValue damage = spell->GetEffect(EFFECT_0).CalcValue(caster);
1169 float multiplier = 2.0f;
1170 if (GetTarget()->GetMap()->Is25ManRaid())
1171 multiplier = 3.0f;
1172
1173 damage *= std::pow(multiplier, GetStackAmount());
1174 damage = damage * 1.5f;
1175
1176 CastSpellExtraArgs args(aurEff);
1178 args.AddSpellBP0(damage);
1179 GetTarget()->CastSpell(GetTarget(), triggerSpell, args);
1180 }
1181
1182 void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
1183 {
1184 uint32 healSpell = uint32(aurEff->GetSpellEffectInfo().CalcValueAsInt());
1185 SpellInfo const* healSpellInfo = sSpellMgr->GetSpellInfo(healSpell, GetCastDifficulty());
1186
1187 if (!healSpellInfo)
1188 return;
1189
1190 SpellEffectValue heal = healSpellInfo->GetEffect(EFFECT_0).CalcValue() * GetStackAmount();
1193 args.AddSpellBP0(heal);
1194 GetTarget()->CastSpell(GetTarget(), healSpell, args);
1195 }
1196
1202};
1203
1204// 70308 - Mutated Transformation (Init)
1206{
1208 {
1210 if (!instance)
1212
1214 if (!professor)
1216
1217 if (professor->AI()->GetData(DATA_PHASE) == PHASE_COMBAT_3 || !professor->IsAlive())
1218 {
1221 }
1222
1223 if (professor->AI()->GetData(DATA_ABOMINATION))
1224 {
1227 }
1228
1229 return SPELL_CAST_OK;
1230 }
1231
1233 {
1234 if (!GetExplTargetUnit())
1236
1237 if (GetExplTargetUnit()->GetTypeId() != TYPEID_PLAYER)
1239
1241 SpellCastResult result = CheckRequirementInternal(extension);
1242 if (result != SPELL_CAST_OK)
1243 {
1244 Spell::SendCastResult(GetExplTargetUnit()->ToPlayer(), GetSpellInfo(), GetSpell()->m_SpellVisual, GetSpell()->m_castId, result, extension);
1245 return result;
1246 }
1247
1248 return SPELL_CAST_OK;
1249 }
1250
1255};
1256
1258{
1259 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
1260 {
1261 uint32 spellId = 70311;
1262 if (GetTarget()->GetMap()->Is25ManRaid())
1263 spellId = 71503;
1264
1265 GetTarget()->CastSpell(GetTarget(), spellId, true);
1266 }
1267
1272};
1273
1274// 70405, 72508, 72509, 72510 - Mutated Transformation (Dismiss)
1276{
1277 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
1278 {
1279 if (Vehicle* veh = GetTarget()->GetVehicleKit())
1280 veh->RemoveAllPassengers();
1281 }
1282
1287};
1288
1289// 70311, 71503 - Mutated Transformation
1291{
1293 {
1294 PreventHitDefaultEffect(effIndex);
1295 Unit* caster = GetOriginalCaster();
1296 if (!caster)
1297 return;
1298
1299 InstanceScript* instance = caster->GetInstanceScript();
1300 if (!instance)
1301 return;
1302
1304 if (!putricide)
1305 return;
1306
1307 if (putricide->AI()->GetData(DATA_ABOMINATION))
1308 {
1309 if (Player* player = caster->ToPlayer())
1311 return;
1312 }
1313
1314 uint32 entry = uint32(GetEffectInfo().MiscValue);
1315 SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(uint32(GetEffectInfo().MiscValueB));
1316 Milliseconds duration = Milliseconds(GetSpellInfo()->GetDuration());
1317
1318 Position pos = caster->GetPosition();
1319 TempSummon* summon = caster->GetMap()->SummonCreature(entry, pos, properties, duration, caster, GetSpellInfo()->Id);
1320 if (!summon || !summon->IsVehicle())
1321 return;
1322
1323 summon->CastSpell(summon, SPELL_ABOMINATION_VEHICLE_POWER_DRAIN, true);
1324 summon->CastSpell(summon, SPELL_MUTATED_TRANSFORMATION_DAMAGE, true);
1325 caster->CastSpell(summon, SPELL_MUTATED_TRANSFORMATION_NAME, true);
1326
1327 caster->EnterVehicle(summon, 0); // VEHICLE_SPELL_RIDE_HARDCODED is used according to sniff, this is ok
1328 summon->SetCreatorGUID(caster->GetGUID());
1329 putricide->AI()->JustSummoned(summon);
1330 }
1331
1336};
1337
1338// 70402, 72511, 72512, 72513 - Mutated Transformation (Damage)
1340{
1341 void FilterTargetsInitial(std::list<WorldObject*>& targets)
1342 {
1343 if (Unit* owner = ObjectAccessor::GetUnit(*GetCaster(), GetCaster()->GetCreatorGUID()))
1344 targets.remove(owner);
1345 }
1346
1351};
1352
1353// 70539, 72457, 72875, 72876 - Regurgitated Ooze
1355{
1356 // the only purpose of this hook is to fail the achievement
1357 void ExtraEffect(SpellEffIndex /*effIndex*/)
1358 {
1359 if (InstanceScript* instance = GetCaster()->GetInstanceScript())
1360 instance->SetData(DATA_NAUSEA_ACHIEVEMENT, uint32(false));
1361 }
1362
1367};
1368
1369// Removes aura with id stored in effect value
1370// 71620 - Tear Gas Cancel
1371// 72618 - Mutated Plague Clear
1373{
1375 {
1376 PreventHitDefaultEffect(effIndex);
1377 Unit* target = GetHitUnit();
1378 uint32 auraId = GetEffectValueAsInt();
1379 target->RemoveAurasDueToSpell(auraId);
1380 if (m_scriptSpellId == SPELL_TEAR_GAS_CANCEL && GetSpellInfo()->GetEffects().size() >= EFFECT_1)
1381 {
1383 target->RemoveAurasDueToSpell(auraId2);
1384 }
1385 }
1386
1391};
1392
1393// Stinky and Precious spell, it's here because its used for both (Festergut and Rotface "pets")
1394// 71123 - Decimate
1396{
1397 void HandleScript(SpellEffIndex /*effIndex*/)
1398 {
1399 if (GetHitUnit()->GetHealthPct() > GetEffectValue())
1400 {
1402 GetHitUnit()->SetHealth(newHealth);
1403 }
1404 }
1405
1410};
1411
1412// 70402, 72511, 72512, 72513 - Mutated Transformation
1414{
1415 void HandleResistance(DamageInfo const& damageInfo, uint32& resistAmount, int32& /*absorbAmount*/)
1416 {
1417 Unit* caster = damageInfo.GetAttacker();;
1418 Unit* target = damageInfo.GetVictim();
1419 uint32 damage = damageInfo.GetDamage();
1420 uint32 resistedDamage = Unit::CalcSpellResistedDamage(caster, target, damage, SPELL_SCHOOL_MASK_SHADOW, nullptr);
1421 resistedDamage += Unit::CalcSpellResistedDamage(caster, target, damage, SPELL_SCHOOL_MASK_NATURE, nullptr);
1422 resistAmount = resistedDamage;
1423 }
1424
1429};
1430
1431// 71278, 72460, 72619, 72620 - Choking Gas
1432// 71279, 72459, 72621, 72622 - Choking Gas Explosion
1434{
1435 bool Validate(SpellInfo const* /*spell*/) override
1436 {
1438 }
1439
1440 void FilterTargets(std::list<WorldObject*>& targets)
1441 {
1442 targets.remove_if([](WorldObject* obj)
1443 {
1444 return obj->ToUnit() && obj->ToUnit()->GetVehicle();
1445 });
1446 }
1447
1448 void HandleDispel(SpellEffIndex /*effIndex*/)
1449 {
1450 Unit* target = GetHitUnit();
1453 }
1454
1460};
1461
1463{
1464 // Creatures
1468
1469 // Spells
1490}
DB2Storage< SummonPropertiesEntry > sSummonPropertiesStore("SummonProperties.db2", &SummonPropertiesLoadInfo::Instance)
uint8_t uint8
Definition Define.h:156
int32_t int32
Definition Define.h:150
uint64_t uint64
Definition Define.h:153
uint32_t uint32
Definition Define.h:154
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition Duration.h:24
@ IN_PROGRESS
@ FAIL
@ DONE
@ NOT_STARTED
@ POINT_MOTION_TYPE
@ TYPEID_UNIT
Definition ObjectGuid.h:43
@ TYPEID_PLAYER
Definition ObjectGuid.h:44
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:43
#define RegisterSpellAndAuraScriptPair(script_1, script_2)
Definition ScriptMgr.h:1381
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1383
void GetCreatureListWithEntryInGrid(Container &container, WorldObject *source, uint32 entry, float maxSearchRange)
SpellEffIndex
@ EFFECT_1
@ EFFECT_0
@ EFFECT_2
@ SPELL_EFFECT_DUMMY
@ SPELL_EFFECT_SCRIPT_EFFECT
@ SPELL_EFFECT_SUMMON
@ SPELL_EFFECT_APPLY_AURA
@ TARGET_UNIT_SRC_AREA_ENTRY
@ TARGET_UNIT_DEST_AREA_ENEMY
@ TARGET_UNIT_SRC_AREA_ALLY
@ TARGET_UNIT_SRC_AREA_ENEMY
@ TARGET_UNIT_DEST_AREA_ENTRY
@ EMOTE_ONESHOT_KNEEL
@ SPELL_SCHOOL_MASK_SHADOW
@ SPELL_SCHOOL_MASK_NATURE
SpellCustomErrors
@ SPELL_CUSTOM_ERROR_NONE
@ SPELL_CUSTOM_ERROR_TOO_MANY_ABOMINATIONS
@ SPELL_CUSTOM_ERROR_ALL_POTIONS_USED
SpellCastResult
@ SPELL_FAILED_TARGET_NOT_PLAYER
@ SPELL_FAILED_CUSTOM_ERROR
@ SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW
@ SPELL_FAILED_BAD_TARGETS
@ SPELL_CAST_OK
@ SPELL_FAILED_NO_VALID_TARGETS
@ AURA_STATE_VULNERABLE
@ AURA_STATE_RAID_ENCOUNTER
#define EFFECT_ALL
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
@ AURA_REMOVE_BY_ENEMY_SPELL
@ SPELL_AURA_PERIODIC_DAMAGE
@ SPELL_AURA_PROC_TRIGGER_SPELL
@ SPELL_AURA_DUMMY
@ SPELL_AURA_PERIODIC_TRIGGER_SPELL
@ SPELLVALUE_AURA_STACK
@ SPELLVALUE_MAX_TARGETS
double SpellEffectValue
This is a double instead of float to be able to store full range of int32.
@ TRIGGERED_FULL_MASK
Used when doing CastSpell with triggered == true.
#define sSpellMgr
Definition SpellMgr.h:812
#define AuraProcFn(F)
#define SpellCheckCastFn(F)
#define AuraEffectProcFn(F, I, N)
#define SpellOnResistAbsorbCalculateFn(F)
#define SpellEffectFn(F, I, N)
#define SpellObjectAreaTargetSelectFn(F, I, N)
#define AuraEffectPeriodicFn(F, I, N)
#define SpellHitFn(F)
#define AuraEffectRemoveFn(F, I, N, M)
@ MOVE_RUN
@ REACT_DEFENSIVE
@ REACT_PASSIVE
@ REACT_AGGRESSIVE
DamageEffectType
@ UNIT_STATE_CASTING
Definition Unit.h:290
Position const festergutWatchPos
@ SPELL_UNBOUND_PLAGUE_PROTECTION
@ SPELL_UNBOUND_PLAGUE_SEARCHER
@ SPELL_OOZE_ERUPTION_SEARCH_PERIODIC
@ SPELL_CHOKING_GAS_BOMB_PERIODIC
@ SPELL_VOLATILE_OOZE_ADHESIVE
@ SPELL_SLIME_PUDDLE_AURA
@ SPELL_SLIME_PUDDLE_TRIGGER
@ SPELL_MUTATED_TRANSFORMATION
@ SPELL_GASEOUS_BLOAT_PROTECTION
@ SPELL_MUTATED_TRANSFORMATION_DAMAGE
@ SPELL_TEAR_GAS_CREATURE
@ SPELL_TEAR_GAS_PERIODIC_TRIGGER
@ SPELL_UNSTABLE_EXPERIMENT
@ SPELL_GASEOUS_BLOAT_PROC
@ SPELL_UNHOLY_INFUSION_CREDIT
@ SPELL_OOZE_TANK_PROTECTION
@ SPELL_ABOMINATION_VEHICLE_POWER_DRAIN
@ SPELL_VOLATILE_OOZE_PROTECTION
@ SPELL_CREATE_CONCOCTION
@ SPELL_MUTATED_TRANSFORMATION_NAME
@ SPELL_TEAR_GAS_TRIGGER_MISSILE
@ SPELL_RELEASE_GAS_VISUAL
@ SPELL_GASEOUS_BLIGHT_LARGE
@ SPELL_GASEOUS_BLIGHT_MEDIUM
@ SPELL_GASEOUS_BLIGHT_SMALL
@ SPELL_MALLEABLE_GOO_SUMMON
@ SPELL_CHOKING_GAS_EXPLOSION_TRIGGER
@ SPELL_MUTATED_PLAGUE_CLEAR
@ EVENT_UNSTABLE_EXPERIMENT
Position const rotfaceWatchPos
@ SAY_PHASE_TRANSITION_HEROIC
@ SAY_FESTERGUT_GASEOUS_BLIGHT
@ EMOTE_UNSTABLE_EXPERIMENT
Position const tablePos
uint32 const oozeFloodSpells[4]
void AddSC_boss_professor_putricide()
#define EXPERIMENT_STATE_OOZE
bool operator()(ObjectGuid guid)
SpellEffectInfo const & GetSpellEffectInfo() const
void PreventDefaultAction()
HookList< EffectApplyHandler > AfterEffectRemove
HookList< EffectPeriodicHandler > OnEffectPeriodic
SpellInfo const * GetSpellInfo() const
Unit * GetCaster() const
Unit * GetTarget() const
ObjectGuid GetCasterGUID() const
Difficulty GetCastDifficulty() const
HookList< EffectProcHandler > OnEffectProc
HookList< AuraProcHandler > OnProc
uint8 GetStackAmount() const
uint32 GetId() const
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
TypeID GetTypeId() const
Definition BaseEntity.h:166
InstanceScript *const instance
void _JustReachedHome()
SummonList summons
EventMap events
void DoZoneInCombat()
Definition CreatureAI.h:169
virtual void JustSummoned(Creature *)
Definition CreatureAI.h:113
virtual void EnterEvadeMode(EvadeReason why=EvadeReason::Other)
bool UpdateVictim()
void AttackStart(Unit *victim) override
== Triggered Actions Requested ==================
void EngagementStart(Unit *who)
Creature *const me
Definition CreatureAI.h:63
void SetImmuneToPC(bool apply) override
Definition Creature.h:190
void SetReactState(ReactStates st)
Definition Creature.h:180
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
CreatureAI * AI() const
Definition Creature.h:235
Unit * GetVictim() const
Definition Unit.h:461
Unit * GetAttacker() const
Definition Unit.h:460
uint32 GetDamage() const
Definition Unit.h:466
void Update(uint32 time)
Definition EventMap.h:77
void DelayEvents(Milliseconds delay)
Definition EventMap.cpp:100
EventId ExecuteEvent()
Definition EventMap.cpp:77
bool IsInPhase(PhaseIndex phase) const
Definition EventMap.h:246
void CancelEvent(EventId eventId)
Definition EventMap.cpp:156
void SetPhase(PhaseIndex phase)
Definition EventMap.cpp:32
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:40
void Reset()
Definition EventMap.cpp:25
ExactDistanceCheck(Unit *source, float dist)
bool operator()(WorldObject *unit) const
virtual bool SetBossState(uint32 id, EncounterState state)
void DoRemoveAurasDueToSpellOnPlayers(uint32 spell, bool includePets=false, bool includeControlled=false)
void DoCastSpellOnPlayers(uint32 spell, bool includePets=false, bool includeControlled=false)
virtual ObjectGuid GetGuidData(uint32 type) const override
EncounterState GetBossState(uint32 id) const
virtual bool CheckRequiredBosses(uint32, Player const *=nullptr) const
TempSummon * SummonCreature(uint32 entry, Position const &pos, SummonPropertiesEntry const *properties=nullptr, Milliseconds duration=0ms, WorldObject *summoner=nullptr, uint32 spellId=0, uint32 vehId=0, ObjectGuid privateObjectOwner=ObjectGuid::Empty, SmoothPhasingInfo const *smoothPhasingInfo=nullptr)
Definition Object.cpp:1191
bool Is25ManRaid() const
Definition Map.cpp:3385
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={})
Player * ToPlayer()
Definition Object.h:126
uint32 GetEntry() const
Definition Object.h:89
Creature * ToCreature()
Definition Object.h:121
Unit * ToUnit()
Definition Object.h:116
Unit * GetActionTarget() const
Definition Unit.h:514
Unit * GetActor() const
Definition Unit.h:513
SpellEffectValue CalcValue(WorldObject const *caster=nullptr, SpellEffectValue const *basePoints=nullptr, Unit const *target=nullptr, float *variance=nullptr, uint32 castItemId=0, int32 itemLevel=-1) const
uint32 TriggerSpell
Definition SpellInfo.h:234
int32 CalcValueAsInt(WorldObject const *caster=nullptr, SpellEffectValue const *basePoints=nullptr, Unit const *target=nullptr, float *variance=nullptr, uint32 castItemId=0, int32 itemLevel=-1) const
uint32 ExcludeTargetAuraSpell
Definition SpellInfo.h:365
uint32 const Id
Definition SpellInfo.h:328
uint32 CalcCastTime(Spell *spell=nullptr) const
SpellEffectInfo const & GetEffect(SpellEffIndex index) const
Definition SpellInfo.h:590
std::vector< SpellEffectInfo > const & GetEffects() const
Definition SpellInfo.h:589
uint32 m_scriptSpellId
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
static bool ValidateSpellEffect(std::initializer_list< std::pair< uint32, SpellEffIndex > > effects)
HookList< CheckCastHandler > OnCheckCast
Creature * GetHitCreature() const
Unit * GetCaster() const
HookList< HitHandler > AfterHit
SpellEffectValue GetEffectValue() const
int32 GetEffectValueAsInt() const
HookList< HitHandler > OnHit
void PreventHitDefaultEffect(SpellEffIndex effIndex)
Unit * GetHitUnit() const
SpellEffectInfo const & GetEffectInfo() const
HookList< EffectHandler > OnEffectHitTarget
HookList< OnCalculateResistAbsorbHandler > OnCalculateResistAbsorb
Spell * GetSpell() const
void FinishCast(SpellCastResult result, int32 *param1=nullptr, int32 *param2=nullptr)
HookList< EffectHandler > OnEffectLaunch
Unit * GetExplTargetUnit() const
SpellInfo const * GetSpellInfo() const
HookList< ObjectAreaTargetSelectHandler > OnObjectAreaTargetSelect
Unit * GetOriginalCaster() const
static void SendCastResult(Player const *caster, SpellInfo const *spellInfo, SpellCastVisual spellVisual, ObjectGuid cast_count, SpellCastResult result, SpellCustomErrors customError=SPELL_CUSTOM_ERROR_NONE, int32 *param1=nullptr, int32 *param2=nullptr)
Definition Spell.cpp:4641
bool HasEntry(uint32 entry) const
void DespawnIf(T const &predicate)
void Summon(Creature const *summon)
Trinity::IteratorPair< ThreatListIterator, std::nullptr_t > GetUnsortedThreatList() const
void FixateTarget(Unit *target)
void AddThreat(Unit *target, float amount, SpellInfo const *spell=nullptr, bool ignoreModifiers=false, bool ignoreRedirects=false)
== AFFECT MY THREAT LIST ==
virtual void SetData(uint32 id, uint32 value)
Definition UnitAI.h:75
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
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:71
SpellCastResult DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:162
virtual uint32 GetData(uint32 id) const
Definition UnitAI.h:74
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:81
Definition Unit.h:647
void EnterVehicle(Unit *base, int8 seatId=-1)
Definition Unit.cpp:12845
void ClearUnitState(uint32 f)
Definition Unit.h:756
bool IsVehicle() const
Definition Unit.h:766
Vehicle * GetVehicle() const
Definition Unit.h:1800
bool IsNonMeleeSpellCast(bool withDelayed, bool skipChanneled=false, bool skipAutorepeat=false, bool isAutoshoot=false, bool skipInstant=true, bool skipChanneledAllowingActions=false) const
Definition Unit.cpp:3219
void SetHealth(uint64 val)
Definition Unit.cpp:10041
uint64 CountPctFromMaxHealth(float pct) const
Definition Unit.h:809
void RemoveAura(AuraApplicationMap::iterator &i, AuraRemoveMode mode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3846
ThreatManager & GetThreatManager()
Definition Unit.h:1093
MotionMaster * GetMotionMaster()
Definition Unit.h:1750
Aura * AddAura(uint32 spellId, Unit *target)
Definition Unit.cpp:12344
bool IsAlive() const
Definition Unit.h:1205
static uint32 CalcSpellResistedDamage(Unit const *attacker, Unit *victim, uint32 damage, SpellSchoolMask schoolMask, SpellInfo const *spellInfo)
Definition Unit.cpp:1780
void SetUninteractible(bool apply)
Definition Unit.cpp:8583
void SetFacingToObject(WorldObject const *object, bool force=true, uint32 movementId=EVENT_FACE)
Definition Unit.cpp:13394
void ModifyAuraState(AuraStateType flag, bool apply)
Definition Unit.cpp:6098
Aura * GetAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4718
bool SetWalk(bool enable)
Definition Unit.cpp:13422
void RemoveAuraFromStack(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT, uint16 num=1)
Definition Unit.cpp:4008
Unit * GetVictim() const
Definition Unit.h:738
void SetSpeedRate(UnitMoveType mtype, float rate)
Definition Unit.cpp:8961
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 HandleEmoteCommand(Emote emoteId, Player *target=nullptr, Trinity::IteratorPair< int32 const * > spellVisualKitIds={}, int32 sequenceVariation=0)
Definition Unit.cpp:1662
void SetCreatorGUID(ObjectGuid creator)
Definition Unit.h:1214
bool AttackStop()
Definition Unit.cpp:5984
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3992
bool IsInCombat() const
Definition Unit.h:1073
Map * GetMap() const
Definition Object.h:411
InstanceScript * GetInstanceScript() const
Definition Object.cpp:394
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
virtual void SetData(uint32, uint32)
Definition ZoneScript.h:100
npc_putricide_oozeAI(Creature *creature, uint32 auraSpellId, uint32 hitTargetSpellId)
void UpdateAI(uint32 diff) override
void SpellHitTarget(WorldObject *, SpellInfo const *spellInfo) override
virtual void CastMainSpell()=0
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void HandleResistance(DamageInfo const &damageInfo, uint32 &resistAmount, int32 &)
void FilterTargets(std::list< WorldObject * > &targets)
bool Validate(SpellInfo const *) override
void SelectTarget(std::list< WorldObject * > &targets)
void HandleProc(ProcEventInfo &eventInfo)
void OnRemove(AuraEffect const *aurEff, AuraEffectHandleModes)
void HandleTriggerSpell(AuraEffect const *aurEff)
void OnRemove(AuraEffect const *, AuraEffectHandleModes)
void FilterTargetsInitial(std::list< WorldObject * > &targets)
void OnRemove(AuraEffect const *, AuraEffectHandleModes)
SpellCastResult CheckRequirementInternal(SpellCustomErrors &extendedError)
void SetTarget(std::list< WorldObject * > &targets)
void SelectTarget(std::list< WorldObject * > &targets)
bool Validate(SpellInfo const *spell) override
void HandleProc(AuraEffect *aurEff, ProcEventInfo &eventInfo)
bool Validate(SpellInfo const *spellInfo) override
void ScaleRange(std::list< WorldObject * > &targets)
void FilterTargets(std::list< WorldObject * > &targets)
bool Validate(SpellInfo const *) override
@ SPELL_SHADOWS_FATE
@ SPELL_BERSERK2
@ LIGHT_S_HAMMER_TELEPORT
#define RegisterIcecrownCitadelCreatureAI(ai_name)
@ ACTION_CHANGE_PHASE
@ ACTION_ROTFACE_COMBAT
@ ACTION_FESTERGUT_DEATH
@ ACTION_ROTFACE_DEATH
@ ACTION_ROTFACE_OOZE
@ ACTION_FESTERGUT_GAS
@ ACTION_FESTERGUT_COMBAT
@ DATA_NAUSEA_ACHIEVEMENT
@ DATA_ROTFACE
@ DATA_PROFESSOR_PUTRICIDE
@ DATA_PUTRICIDE_TABLE
@ DATA_FESTERGUT
@ NPC_TEAR_GAS_TARGET_STALKER
@ NPC_ABOMINATION_WING_MAD_SCIENTIST_STALKER
@ NPC_MUTATED_ABOMINATION_25
@ NPC_CHOKING_GAS_BOMB
@ NPC_MALLEABLE_OOZE_STALKER
@ NPC_VOLATILE_OOZE
@ NPC_PUDDLE_STALKER
@ NPC_GAS_CLOUD
@ NPC_MUTATED_ABOMINATION_10
@ NPC_GROWING_OOZE_PUDDLE
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
TC_GAME_API GameObject * GetGameObject(WorldObject const &u, ObjectGuid const &guid)
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
CastSpellExtraArgs & SetOriginalCaster(ObjectGuid const &guid)
CastSpellExtraArgs & AddSpellBP0(SpellEffectValue val)
CastSpellExtraArgs & AddSpellMod(SpellValueMod mod, int32 val)
float GetExactDist2d(const float x, const float y) const
Definition Position.h:117
constexpr void GetPosition(float &x, float &y) const
Definition Position.h:92
constexpr float GetPositionZ() const
Definition Position.h:89
bool operator()(Creature *stalker) const
RotfaceHeightCheck(Creature *rotface)
bool IsHeroic() const
void AttackStart(Unit *) override
== Triggered Actions Requested ==================
bool HealthAbovePct(uint32 pct) const
Difficulty GetDifficulty() const
bool Is25ManRaid() const
void SetPhase(PutricidePhases newPhase)
void DamageTaken(Unit *, uint32 &, DamageEffectType, SpellInfo const *) override
uint32 GetData(uint32 type) const override
void DoAction(int32 action) override
boss_professor_putricide(Creature *creature)
void JustSummoned(Creature *summon) override
void KilledUnit(Unit *victim) override
void MovementInform(uint32 type, uint32 id) override
void SetData(uint32 id, uint32 data) override
void UpdateAI(uint32 diff) override
void JustEngagedWith(Unit *who) override
void CastMainSpell() override
npc_gas_cloud(Creature *creature)
npc_volatile_ooze(Creature *creature)