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
36enum Say
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
223{
230
250
277
285
286 void KilledUnit(Unit* victim) override
287 {
288 if (victim->GetTypeId() == TYPEID_PLAYER)
289 Talk(SAY_KILL);
290 }
291
292 void JustDied(Unit* /*killer*/) override
293 {
294 _JustDied();
296
299
301 }
302
303 void JustSummoned(Creature* summon) override
304 {
305 summons.Summon(summon);
306 switch (summon->GetEntry())
307 {
310 return;
312 summon->CastSpell(summon, SPELL_GROW_STACKER, true);
313 summon->CastSpell(summon, SPELL_SLIME_PUDDLE_AURA, true);
314 // blizzard casts this spell 7 times initially (confirmed in sniff)
315 for (uint8 i = 0; i < 7; ++i)
316 summon->CastSpell(summon, SPELL_GROW, true);
317 break;
318 case NPC_GAS_CLOUD:
319 // no possible aura seen in sniff adding the aurastate
322 break;
324 // no possible aura seen in sniff adding the aurastate
327 break;
329 summon->CastSpell(summon, SPELL_CHOKING_GAS_BOMB_PERIODIC, true);
330 summon->CastSpell(summon, SPELL_CHOKING_GAS_EXPLOSION_TRIGGER, true);
331 return;
334 return;
335 default:
336 break;
337 }
338
339 if (me->IsInCombat())
340 DoZoneInCombat(summon);
341 }
342
343 void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
344 {
346 return;
347
348 switch (_phase)
349 {
350 case PHASE_COMBAT_1:
351 if (HealthAbovePct(80))
352 return;
355 break;
356 case PHASE_COMBAT_2:
357 if (HealthAbovePct(35))
358 return;
361 break;
362 default:
363 break;
364 }
365 }
366
367 void MovementInform(uint32 type, uint32 id) override
368 {
369 if (type != POINT_MOTION_TYPE)
370 return;
371 switch (id)
372 {
373 case POINT_FESTERGUT:
374 instance->SetBossState(DATA_FESTERGUT, IN_PROGRESS); // needed here for delayed gate close
378 festergut->CastSpell(festergut, SPELL_GASEOUS_BLIGHT_LARGE, CastSpellExtraArgs().SetOriginalCaster(festergut->GetGUID()));
379 break;
380 case POINT_ROTFACE:
381 instance->SetBossState(DATA_ROTFACE, IN_PROGRESS); // needed here for delayed gate close
385 break;
386 case POINT_TABLE:
387 // stop attack
391 me->SetFacingToObject(table);
392 // operating on new phase already
393 switch (_phase)
394 {
395 case PHASE_COMBAT_2:
396 {
397 SpellInfo const* spell = sSpellMgr->GetSpellInfo(SPELL_CREATE_CONCOCTION, GetDifficulty());
400 break;
401 }
402 case PHASE_COMBAT_3:
403 {
404 SpellInfo const* spell = sSpellMgr->GetSpellInfo(SPELL_GUZZLE_POTIONS, GetDifficulty());
407 break;
408 }
409 default:
410 break;
411 }
412 break;
413 default:
414 break;
415 }
416 }
417
418 void DoAction(int32 action) override
419 {
420 switch (action)
421 {
427 EngagementStart(nullptr);
428 if (IsHeroic())
430 break;
434 break;
437 break;
443 EngagementStart(nullptr);
444 _oozeFloodStage = 0;
445 // init random sequence of floods
447 {
448 std::list<Creature*> list;
450 list.remove_if(RotfaceHeightCheck(rotface));
451 if (list.size() > 4)
452 {
453 list.sort(Trinity::ObjectDistanceOrderPred(rotface));
454 do
455 {
456 list.pop_back();
457 } while (list.size() > 4);
458 }
459
460 uint8 i = 0;
461 while (!list.empty())
462 {
463 std::list<Creature*>::iterator itr = list.begin();
464 std::advance(itr, urand(0, list.size()-1));
465 _oozeFloodDummyGUIDs[i++] = (*itr)->GetGUID();
466 list.erase(itr);
467 }
468 }
469 break;
474 .SetOriginalCaster(me->GetGUID())); // cast from self for LoS (with prof's GUID for logs)
475 if (++_oozeFloodStage == 4)
476 _oozeFloodStage = 0;
477 break;
480 break;
483 events.DelayEvents(30s);
484 me->AttackStop();
485 if (!IsHeroic())
486 {
489 }
490 else
491 {
495 // cast variables
496 if (Is25ManRaid())
497 {
498 std::list<Unit*> targetList;
499 {
501 if (Player* target = ref->GetVictim()->ToPlayer())
502 targetList.push_back(target);
503 }
504
505 size_t half = targetList.size()/2;
506 // half gets ooze variable
507 while (half < targetList.size())
508 {
509 std::list<Unit*>::iterator itr = targetList.begin();
510 advance(itr, urand(0, targetList.size() - 1));
511 (*itr)->CastSpell(*itr, SPELL_OOZE_VARIABLE, true);
512 targetList.erase(itr);
513 }
514 // and half gets gas
515 for (std::list<Unit*>::iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
516 (*itr)->CastSpell(*itr, SPELL_GAS_VARIABLE, true);
517 }
519 }
520 switch (_phase)
521 {
522 case PHASE_COMBAT_1:
526 break;
527 case PHASE_COMBAT_2:
531 break;
532 default:
533 break;
534 }
535 break;
536 default:
537 break;
538 }
539 }
540
541 uint32 GetData(uint32 type) const override
542 {
543 switch (type)
544 {
546 return _experimentState;
547 case DATA_PHASE:
548 return _phase;
549 case DATA_ABOMINATION:
551 default:
552 break;
553 }
554
555 return 0;
556 }
557
558 void SetData(uint32 id, uint32 data) override
559 {
560 if (id == DATA_EXPERIMENT_STAGE)
561 _experimentState = data != 0;
562 }
563
564 void UpdateAI(uint32 diff) override
565 {
567 return;
568
569 events.Update(diff);
570
572 return;
573
574 while (uint32 eventId = events.ExecuteEvent())
575 {
576 switch (eventId)
577 {
581 break;
584 if (Is25ManRaid())
586 else
588 break;
592 break;
596 break;
597 case EVENT_BERSERK:
600 break;
602 {
603 std::list<Unit*> targets;
604 SelectTargetList(targets, 2, SelectTargetMethod::Random, 0, 0.0f, true);
605 if (!targets.empty())
606 for (std::list<Unit*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
609 break;
610 }
615 break;
616 case EVENT_TEAR_GAS:
619 break;
623 // remove Tear Gas
628 break;
630 if (Is25ManRaid())
631 {
632 std::list<Unit*> targets;
633 SelectTargetList(targets, 2, SelectTargetMethod::Random, 0, -7.0f, true);
634 if (!targets.empty())
635 {
637 for (std::list<Unit*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
639 }
640 }
641 else
642 {
643 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, -7.0f, true))
644 {
647 }
648 }
650 break;
655 break;
658 {
661 }
663 break;
667 break;
669 {
670 switch (_phase)
671 {
672 case PHASE_COMBAT_2:
674 me->SetFacingToObject(face);
678 break;
679 case PHASE_COMBAT_3:
681 me->SetFacingToObject(face);
686 break;
687 default:
688 break;
689 }
690 break;
691 }
692 default:
693 break;
694 }
695
697 return;
698 }
699 }
700
701private:
702 void SetPhase(Phases newPhase)
703 {
704 _phase = newPhase;
705 events.SetPhase(newPhase);
706 }
707
709 Phases _phase; // external of EventMap because event phase gets reset on evade
710 float const _baseSpeed;
713};
714
716{
717 public:
718 npc_putricide_oozeAI(Creature* creature, uint32 auraSpellId, uint32 hitTargetSpellId) : ScriptedAI(creature),
719 _auraSpellId(auraSpellId), _hitTargetSpellId(hitTargetSpellId), _newTargetSelectTimer(0), _instance(creature->GetInstanceScript()) { }
720
721 void SpellHitTarget(WorldObject* /*target*/, SpellInfo const* spellInfo) override
722 {
723 if (!_newTargetSelectTimer && spellInfo->Id == _hitTargetSpellId)
724 {
726 // go passive until next target selection
728 }
729 }
730
731 void Reset() override
732 {
735
737 DoCastAOE(_auraSpellId, true);
738 }
739
740 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
741 {
742 if (spellInfo->Id == SPELL_TEAR_GAS_CREATURE)
744 }
745
746 void UpdateAI(uint32 diff) override
747 {
749 return;
750
751 if (!_newTargetSelectTimer && !me->IsNonMeleeSpellCast(false, false, true, false, true))
753
755 return;
756
758 return;
759
760 if (_newTargetSelectTimer <= diff)
761 {
764 }
765 else
766 _newTargetSelectTimer -= diff;
767 }
768
769 virtual void CastMainSpell() = 0;
770
771 private:
776};
777
787
805
806// 70672, 72455, 72832, 72833 - Gaseous Bloat
808{
809 void HandleExtraEffect(AuraEffect const* /*aurEff*/)
810 {
811 Unit* target = GetTarget();
812 if (Unit* caster = GetCaster())
813 {
815 if (!target->HasAura(GetId()))
816 {
819 caster->CastSpell(caster, SPELL_GASEOUS_BLOAT, args);
820 }
821 }
822 }
823
824 void HandleProc(ProcEventInfo& eventInfo)
825 {
826 uint32 stack = GetStackAmount();
827 Unit* caster = eventInfo.GetActor();
828
829 int32 const mod = caster->GetMap()->Is25ManRaid() ? 1500 : 1250;
830 int32 dmg = 0;
831 for (uint8 i = 1; i <= stack; ++i)
832 dmg += mod * i;
833
835 args.AddSpellBP0(dmg);
836 caster->CastSpell(nullptr, SPELL_EXPUNGED_GAS, args);
837 }
838
844};
845
846// 70447, 72836, 72837, 72838 - Volatile Ooze Adhesive
847// 70672, 72455, 72832, 72833 - Gaseous Bloat
849{
850 bool Validate(SpellInfo const* spell) override
851 {
852 return ValidateSpellInfo({ spell->ExcludeTargetAuraSpell });
853 }
854
855 // set up initial variables and check if caster is creature
856 // this will let use safely use ToCreature() casts in entire script
857 bool Load() override
858 {
859 return GetCaster()->GetTypeId() == TYPEID_UNIT;
860 }
861
862 void SelectTarget(std::list<WorldObject*>& targets)
863 {
864 if (targets.empty())
865 {
867 GetCaster()->ToCreature()->DespawnOrUnsummon(1ms); // despawn next update
868 return;
869 }
870
872 targets.clear();
873 targets.push_back(target);
874 _target = target;
875 }
876
877 void SetTarget(std::list<WorldObject*>& targets)
878 {
879 targets.clear();
880 if (_target)
881 targets.push_back(_target);
882 }
883
893
901
903};
904
906{
907 public:
908 ExactDistanceCheck(Unit* source, float dist) : _source(source), _dist(dist) { }
909
910 bool operator()(WorldObject* unit) const
911 {
912 return _source->GetExactDist2d(unit) > _dist;
913 }
914
915 private:
917 float _dist;
918};
919
920// 70346, 72456, 72868, 72869 - Slime Puddle
934
935// this is here only because on retail you dont actually enter HEROIC mode for ICC
936// 72868, 72869 - Slime Puddle
938{
940 {
941 if (Unit* target = GetHitUnit())
942 GetCaster()->AddAura(GetCaster()->GetMap()->Is25ManRaid() ? 72456 : 70346, target);
943 }
944
949};
950
951// 70351, 71966, 71967, 71968 - Unstable Experiment
953{
955 {
956 PreventHitDefaultEffect(effIndex);
957 if (GetCaster()->GetTypeId() != TYPEID_UNIT)
958 return;
959
960 Creature* creature = GetCaster()->ToCreature();
961
962 uint32 stage = creature->AI()->GetData(DATA_EXPERIMENT_STAGE);
963 creature->AI()->SetData(DATA_EXPERIMENT_STAGE, stage ^ true);
964
965 Creature* target = nullptr;
966 std::list<Creature*> creList;
968 // 2 of them are spawned at green place - weird trick blizz
969 for (std::list<Creature*>::iterator itr = creList.begin(); itr != creList.end(); ++itr)
970 {
971 target = *itr;
972 std::list<Creature*> tmp;
974 if ((!stage && tmp.size() > 1) || (stage && tmp.size() == 1))
975 break;
976 }
977
978 GetCaster()->CastSpell(target, uint32(GetEffectInfo(SpellEffIndex(stage)).CalcValueAsInt()), true);
979 }
980
985};
986
987// 70459 - Ooze Eruption Search Effect
1004
1005// 71770 - Ooze Spell Tank Protection
1007{
1008 bool Validate(SpellInfo const* spellInfo) override
1009 {
1010 return ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 } })
1011 && ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0).TriggerSpell, spellInfo->GetEffect(EFFECT_1).TriggerSpell });
1012 }
1013
1014 void HandleProc(AuraEffect* aurEff, ProcEventInfo& eventInfo)
1015 {
1017
1018 Unit* actionTarget = eventInfo.GetActionTarget();
1019 actionTarget->CastSpell(nullptr, aurEff->GetSpellEffectInfo().TriggerSpell, aurEff);
1020 }
1021
1027};
1028
1029// 71255 - Choking Gas Bomb
1031{
1032 void HandleScript(SpellEffIndex /*effIndex*/)
1033 {
1034 uint32 skipIndex = urand(0, 2);
1035 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
1036 {
1037 if (spellEffectInfo.EffectIndex == skipIndex)
1038 continue;
1039
1040 uint32 spellId = uint32(spellEffectInfo.CalcValueAsInt());
1042 .SetOriginalCaster(GetCaster()->GetGUID()));
1043 }
1044 }
1045
1050};
1051
1052// 70920 - Unbound Plague Search Effect
1054{
1055 bool Validate(SpellInfo const* /*spell*/) override
1056 {
1058 }
1059
1060 void FilterTargets(std::list<WorldObject*>& targets)
1061 {
1062 if (AuraEffect const* eff = GetCaster()->GetAuraEffect(SPELL_UNBOUND_PLAGUE_SEARCHER, EFFECT_0))
1063 {
1064 if (eff->GetTickNumber() < 2)
1065 {
1066 targets.clear();
1067 return;
1068 }
1069 }
1070
1071 targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_UNBOUND_PLAGUE));
1073 }
1074
1075 void HandleScript(SpellEffIndex /*effIndex*/)
1076 {
1077 if (!GetHitUnit())
1078 return;
1079
1081 if (!instance)
1082 return;
1083
1085 {
1087 {
1088 if (Aura* oldPlague = GetCaster()->GetAura(SPELL_UNBOUND_PLAGUE, professor->GetGUID()))
1089 {
1090 if (Aura* newPlague = professor->AddAura(SPELL_UNBOUND_PLAGUE, GetHitUnit()))
1091 {
1092 newPlague->SetMaxDuration(oldPlague->GetMaxDuration());
1093 newPlague->SetDuration(oldPlague->GetDuration());
1094 oldPlague->Remove();
1098 professor->CastSpell(GetHitUnit(), SPELL_UNBOUND_PLAGUE_SEARCHER, true);
1099 }
1100 }
1101 }
1102 }
1103 }
1104
1110};
1111
1112// 70360, 72527 - Eat Ooze
1114{
1115 void SelectTarget(std::list<WorldObject*>& targets)
1116 {
1117 if (targets.empty())
1118 return;
1119
1121 WorldObject* target = targets.front();
1122 targets.clear();
1123 targets.push_back(target);
1124 }
1125
1126 void HandleScript(SpellEffIndex /*effIndex*/)
1127 {
1128 Creature* target = GetHitCreature();
1129 if (!target)
1130 return;
1131
1132 if (Aura* grow = target->GetAura(uint32(GetEffectValueAsInt())))
1133 {
1134 if (grow->GetStackAmount() < 3)
1135 {
1137 target->RemoveAura(grow);
1138 target->DespawnOrUnsummon(1ms);
1139 }
1140 else
1141 grow->ModStackAmount(-3);
1142 }
1143 }
1144
1150};
1151
1152// 72451, 72463, 72671, 72672 - Mutated Plague
1154{
1155 void HandleTriggerSpell(AuraEffect const* aurEff)
1156 {
1158 Unit* caster = GetCaster();
1159 if (!caster)
1160 return;
1161
1162 uint32 triggerSpell = aurEff->GetSpellEffectInfo().TriggerSpell;
1163 SpellInfo const* spell = sSpellMgr->AssertSpellInfo(triggerSpell, GetCastDifficulty());
1164
1165 SpellEffectValue damage = spell->GetEffect(EFFECT_0).CalcValue(caster);
1166 float multiplier = 2.0f;
1167 if (GetTarget()->GetMap()->Is25ManRaid())
1168 multiplier = 3.0f;
1169
1170 damage *= std::pow(multiplier, GetStackAmount());
1171 damage = damage * 1.5f;
1172
1173 CastSpellExtraArgs args(aurEff);
1175 args.AddSpellBP0(damage);
1176 GetTarget()->CastSpell(GetTarget(), triggerSpell, args);
1177 }
1178
1179 void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
1180 {
1181 uint32 healSpell = uint32(aurEff->GetSpellEffectInfo().CalcValueAsInt());
1182 SpellInfo const* healSpellInfo = sSpellMgr->GetSpellInfo(healSpell, GetCastDifficulty());
1183
1184 if (!healSpellInfo)
1185 return;
1186
1187 SpellEffectValue heal = healSpellInfo->GetEffect(EFFECT_0).CalcValue() * GetStackAmount();
1190 args.AddSpellBP0(heal);
1191 GetTarget()->CastSpell(GetTarget(), healSpell, args);
1192 }
1193
1199};
1200
1201// 70308 - Mutated Transformation (Init)
1203{
1205 {
1207 if (!instance)
1209
1211 if (!professor)
1213
1214 if (professor->AI()->GetData(DATA_PHASE) == PHASE_COMBAT_3 || !professor->IsAlive())
1215 {
1218 }
1219
1220 if (professor->AI()->GetData(DATA_ABOMINATION))
1221 {
1224 }
1225
1226 return SPELL_CAST_OK;
1227 }
1228
1230 {
1231 if (!GetExplTargetUnit())
1233
1234 if (GetExplTargetUnit()->GetTypeId() != TYPEID_PLAYER)
1236
1238 SpellCastResult result = CheckRequirementInternal(extension);
1239 if (result != SPELL_CAST_OK)
1240 {
1241 Spell::SendCastResult(GetExplTargetUnit()->ToPlayer(), GetSpellInfo(), GetSpell()->m_SpellVisual, GetSpell()->m_castId, result, extension);
1242 return result;
1243 }
1244
1245 return SPELL_CAST_OK;
1246 }
1247
1252};
1253
1255{
1256 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
1257 {
1258 uint32 spellId = 70311;
1259 if (GetTarget()->GetMap()->Is25ManRaid())
1260 spellId = 71503;
1261
1262 GetTarget()->CastSpell(GetTarget(), spellId, true);
1263 }
1264
1269};
1270
1271// 70405, 72508, 72509, 72510 - Mutated Transformation (Dismiss)
1273{
1274 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
1275 {
1276 if (Vehicle* veh = GetTarget()->GetVehicleKit())
1277 veh->RemoveAllPassengers();
1278 }
1279
1284};
1285
1286// 70311, 71503 - Mutated Transformation
1288{
1290 {
1291 PreventHitDefaultEffect(effIndex);
1292 Unit* caster = GetOriginalCaster();
1293 if (!caster)
1294 return;
1295
1296 InstanceScript* instance = caster->GetInstanceScript();
1297 if (!instance)
1298 return;
1299
1301 if (!putricide)
1302 return;
1303
1304 if (putricide->AI()->GetData(DATA_ABOMINATION))
1305 {
1306 if (Player* player = caster->ToPlayer())
1308 return;
1309 }
1310
1311 uint32 entry = uint32(GetEffectInfo().MiscValue);
1312 SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(uint32(GetEffectInfo().MiscValueB));
1313 Milliseconds duration = Milliseconds(GetSpellInfo()->GetDuration());
1314
1315 Position pos = caster->GetPosition();
1316 TempSummon* summon = caster->GetMap()->SummonCreature(entry, pos, properties, duration, caster, GetSpellInfo()->Id);
1317 if (!summon || !summon->IsVehicle())
1318 return;
1319
1320 summon->CastSpell(summon, SPELL_ABOMINATION_VEHICLE_POWER_DRAIN, true);
1321 summon->CastSpell(summon, SPELL_MUTATED_TRANSFORMATION_DAMAGE, true);
1322 caster->CastSpell(summon, SPELL_MUTATED_TRANSFORMATION_NAME, true);
1323
1324 caster->EnterVehicle(summon, 0); // VEHICLE_SPELL_RIDE_HARDCODED is used according to sniff, this is ok
1325 summon->SetCreatorGUID(caster->GetGUID());
1326 putricide->AI()->JustSummoned(summon);
1327 }
1328
1333};
1334
1335// 70402, 72511, 72512, 72513 - Mutated Transformation (Damage)
1337{
1338 void FilterTargetsInitial(std::list<WorldObject*>& targets)
1339 {
1340 if (Unit* owner = ObjectAccessor::GetUnit(*GetCaster(), GetCaster()->GetCreatorGUID()))
1341 targets.remove(owner);
1342 }
1343
1348};
1349
1350// 70539, 72457, 72875, 72876 - Regurgitated Ooze
1352{
1353 // the only purpose of this hook is to fail the achievement
1354 void ExtraEffect(SpellEffIndex /*effIndex*/)
1355 {
1356 if (InstanceScript* instance = GetCaster()->GetInstanceScript())
1357 instance->SetData(DATA_NAUSEA_ACHIEVEMENT, uint32(false));
1358 }
1359
1364};
1365
1366// Removes aura with id stored in effect value
1367// 71620 - Tear Gas Cancel
1368// 72618 - Mutated Plague Clear
1370{
1372 {
1373 PreventHitDefaultEffect(effIndex);
1374 Unit* target = GetHitUnit();
1375 uint32 auraId = GetEffectValueAsInt();
1376 target->RemoveAurasDueToSpell(auraId);
1377 if (m_scriptSpellId == SPELL_TEAR_GAS_CANCEL && GetSpellInfo()->GetEffects().size() >= EFFECT_1)
1378 {
1380 target->RemoveAurasDueToSpell(auraId2);
1381 }
1382 }
1383
1388};
1389
1390// Stinky and Precious spell, it's here because its used for both (Festergut and Rotface "pets")
1391// 71123 - Decimate
1393{
1394 void HandleScript(SpellEffIndex /*effIndex*/)
1395 {
1396 if (GetHitUnit()->GetHealthPct() > GetEffectValue())
1397 {
1399 GetHitUnit()->SetHealth(newHealth);
1400 }
1401 }
1402
1407};
1408
1409// 70402, 72511, 72512, 72513 - Mutated Transformation
1411{
1412 void HandleResistance(DamageInfo const& damageInfo, uint32& resistAmount, int32& /*absorbAmount*/)
1413 {
1414 Unit* caster = damageInfo.GetAttacker();;
1415 Unit* target = damageInfo.GetVictim();
1416 uint32 damage = damageInfo.GetDamage();
1417 uint32 resistedDamage = Unit::CalcSpellResistedDamage(caster, target, damage, SPELL_SCHOOL_MASK_SHADOW, nullptr);
1418 resistedDamage += Unit::CalcSpellResistedDamage(caster, target, damage, SPELL_SCHOOL_MASK_NATURE, nullptr);
1419 resistAmount = resistedDamage;
1420 }
1421
1426};
1427
1428// 71278, 72460, 72619, 72620 - Choking Gas
1429// 71279, 72459, 72621, 72622 - Choking Gas Explosion
1431{
1432 bool Validate(SpellInfo const* /*spell*/) override
1433 {
1435 }
1436
1437 void FilterTargets(std::list<WorldObject*>& targets)
1438 {
1439 targets.remove_if([](WorldObject* obj)
1440 {
1441 return obj->ToUnit() && obj->ToUnit()->GetVehicle();
1442 });
1443 }
1444
1445 void HandleDispel(SpellEffIndex /*effIndex*/)
1446 {
1447 Unit* target = GetHitUnit();
1450 }
1451
1457};
1458
1460{
1461 // Creatures
1465
1466 // Spells
1487}
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
Spells
Definition PlayerAI.cpp:32
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:42
#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
@ 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
@ SPELL_EFFECT_DUMMY
@ SPELL_EFFECT_SCRIPT_EFFECT
@ SPELL_EFFECT_SUMMON
@ SPELL_EFFECT_APPLY_AURA
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:276
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
Position const rotfaceWatchPos
Position const tablePos
@ SAY_PHASE_TRANSITION_HEROIC
@ SAY_FESTERGUT_GASEOUS_BLIGHT
@ EMOTE_UNSTABLE_EXPERIMENT
uint32 const oozeFloodSpells[4]
void AddSC_boss_professor_putricide()
#define EXPERIMENT_STATE_OOZE
@ EVENT_UNSTABLE_EXPERIMENT
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:184
void SetReactState(ReactStates st)
Definition Creature.h:174
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
CreatureAI * AI() const
Definition Creature.h:228
Unit * GetVictim() const
Definition Unit.h:447
Unit * GetAttacker() const
Definition Unit.h:446
uint32 GetDamage() const
Definition Unit.h:452
uint32 ExecuteEvent()
Definition EventMap.cpp:77
void Update(uint32 time)
Definition EventMap.h:61
void DelayEvents(Milliseconds delay)
Definition EventMap.cpp:100
void ScheduleEvent(uint32 eventId, Milliseconds time, uint32 group=0, uint8 phase=0)
Definition EventMap.cpp:40
bool IsInPhase(uint8 phase) const
Definition EventMap.h:222
void CancelEvent(uint32 eventId)
Definition EventMap.cpp:135
void SetPhase(uint8 phase)
Definition EventMap.cpp:32
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:1186
bool Is25ManRaid() const
Definition Map.cpp:3349
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:500
Unit * GetActor() const
Definition Unit.h:499
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:588
std::vector< SpellEffectInfo > const & GetEffects() const
Definition SpellInfo.h:587
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 *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:4699
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: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
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:79
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:89
Definition Unit.h:635
void EnterVehicle(Unit *base, int8 seatId=-1)
Definition Unit.cpp:12749
void ClearUnitState(uint32 f)
Definition Unit.h:744
bool IsVehicle() const
Definition Unit.h:754
Vehicle * GetVehicle() const
Definition Unit.h:1784
void SetHealth(uint64 val)
Definition Unit.cpp:9973
uint64 CountPctFromMaxHealth(float pct) const
Definition Unit.h:797
void RemoveAura(AuraApplicationMap::iterator &i, AuraRemoveMode mode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3828
ThreatManager & GetThreatManager()
Definition Unit.h:1078
MotionMaster * GetMotionMaster()
Definition Unit.h:1723
bool IsNonMeleeSpellCast(bool withDelayed, bool skipChanneled=false, bool skipAutorepeat=false, bool isAutoshoot=false, bool skipInstant=true) const
Definition Unit.cpp:3201
void SetFacingToObject(WorldObject const *object, bool force=true)
Definition Unit.cpp:13307
Aura * AddAura(uint32 spellId, Unit *target)
Definition Unit.cpp:12249
bool IsAlive() const
Definition Unit.h:1185
static uint32 CalcSpellResistedDamage(Unit const *attacker, Unit *victim, uint32 damage, SpellSchoolMask schoolMask, SpellInfo const *spellInfo)
Definition Unit.cpp:1775
void SetUninteractible(bool apply)
Definition Unit.cpp:8564
void ModifyAuraState(AuraStateType flag, bool apply)
Definition Unit.cpp:6079
Aura * GetAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4700
bool SetWalk(bool enable)
Definition Unit.cpp:13343
void RemoveAuraFromStack(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT, uint16 num=1)
Definition Unit.cpp:3990
Unit * GetVictim() const
Definition Unit.h:726
void SetSpeedRate(UnitMoveType mtype, float rate)
Definition Unit.cpp:8942
bool HasUnitState(const uint32 f) const
Definition Unit.h:743
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4804
void HandleEmoteCommand(Emote emoteId, Player *target=nullptr, Trinity::IteratorPair< int32 const * > spellVisualKitIds={}, int32 sequenceVariation=0)
Definition Unit.cpp:1657
void SetCreatorGUID(ObjectGuid creator)
Definition Unit.h:1194
bool AttackStop()
Definition Unit.cpp:5965
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3974
bool IsInCombat() const
Definition Unit.h:1058
Map * GetMap() const
Definition Object.h:411
InstanceScript * GetInstanceScript() const
Definition Object.cpp:396
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2217
void setActive(bool isActiveObject)
Definition Object.cpp:276
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition Object.cpp:1517
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 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)