diff options
author | Shauren <none@none> | 2010-10-16 16:34:21 +0200 |
---|---|---|
committer | Shauren <none@none> | 2010-10-16 16:34:21 +0200 |
commit | 4ce274dbcdeba8b9647bc445efda4a211b730a8e (patch) | |
tree | 81e12625d17b3d64a4c5caac3a9c13ca1126c3a7 /src | |
parent | 8154f7243cfa6221662615993b2bd17b75f06c38 (diff) |
Scripts/Icecrown Citadel: Added Professor Putricide script
Scripts/Icecrown Citadel: Fixed Professor Putricide gate opening when both Rotface and Festergut are dead
Scripts/Icecrown Citadel: Added script updating entries of NPCs at Light's Hammer depending on faction
Scripts/Icecrown Citadel: Rotface should not pick main tank as target for Slime Spray (removed debugging code)
Core/Spells/Conditions : Spell script target condition now accepts ConditionValue3 as affecting effect mask (only search targets with matching mask)
--HG--
branch : trunk
Diffstat (limited to 'src')
-rwxr-xr-x | src/server/game/Conditions/ConditionMgr.cpp | 14 | ||||
-rwxr-xr-x | src/server/game/Entities/Unit/Unit.cpp | 10 | ||||
-rwxr-xr-x | src/server/game/Miscellaneous/SharedDefines.h | 4 | ||||
-rwxr-xr-x | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 14 | ||||
-rwxr-xr-x | src/server/game/Spells/Spell.cpp | 20 | ||||
-rwxr-xr-x | src/server/game/Spells/Spell.h | 2 | ||||
-rwxr-xr-x | src/server/game/Spells/SpellMgr.cpp | 40 | ||||
-rwxr-xr-x | src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp | 1124 | ||||
-rw-r--r-- | src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp | 10 | ||||
-rwxr-xr-x | src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h | 106 | ||||
-rwxr-xr-x | src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp | 57 |
11 files changed, 1299 insertions, 102 deletions
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index a6626ca62b2..155d73569f2 100755 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -828,10 +828,17 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) spellProto->EffectImplicitTargetB[i] == TARGET_UNIT_CONE_ENTRY) { targetfound = true; - break; + //break; + } + else if (cond->mConditionValue3 & (1 << i)) + { + cond->mConditionValue3 &= ~(1 << i); + sLog.outErrorDb("SourceEntry %u in `condition` table does not have any implicit target TARGET_UNIT_NEARBY_ENTRY(38) or TARGET_DST_NEARBY_ENTRY (46)" + ",TARGET_UNIT_AREA_ENTRY_SRC(7), TARGET_UNIT_AREA_ENTRY_DST(8), TARGET_UNIT_CONE_ENTRY(60), TARGET_GAMEOBJECT_NEARBY_ENTRY(40)" + "TARGET_GAMEOBJECT_AREA_SRC(51), TARGET_GAMEOBJECT_AREA_DST(52) in effect %u", cond->mSourceEntry, uint32(i)); } } - if (!targetfound) + if (!targetfound && !cond->mConditionValue3) // cond->mConditionValue3 already errored up there { sLog.outErrorDb("SourceEntry %u in `condition` table does not have any implicit target TARGET_UNIT_NEARBY_ENTRY(38) or TARGET_DST_NEARBY_ENTRY (46)" ",TARGET_UNIT_AREA_ENTRY_SRC(7), TARGET_UNIT_AREA_ENTRY_DST(8), TARGET_UNIT_CONE_ENTRY(60), TARGET_GAMEOBJECT_NEARBY_ENTRY(40)" @@ -1175,9 +1182,6 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) break; } } - - if (cond->mConditionValue3) - sLog.outErrorDb("SpellTarget condition has useless data in value3 (%u)!", cond->mConditionValue3); break; } case CONDITION_CREATURE_TARGET: diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 2e3737c6037..f4d3346145b 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -5701,6 +5701,16 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger target = triggeredByAura->GetCaster(); break; } + // Gaseous Bloat (Professor Putricide add) + case 70215: + case 72858: + case 72859: + case 72860: + { + target = getVictim(); + triggered_spell_id = 70701; + break; + } } break; } diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index bf2de3b0930..5f49e7e60a7 100755 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -1004,10 +1004,10 @@ enum AuraState AURA_STATE_DEADLY_POISON = 16, // T | AURA_STATE_ENRAGE = 17, // C | AURA_STATE_BLEEDING = 18, // T| - //AURA_STATE_UNKNOWN19 = 19, // | not used + AURA_STATE_UNKNOWN19 = 19, // | //AURA_STATE_UNKNOWN20 = 20, // c | only (45317 Suicide) //AURA_STATE_UNKNOWN21 = 21, // | not used - //AURA_STATE_UNKNOWN22 = 22, // C t| varius spells (63884, 50240) + AURA_STATE_UNKNOWN22 = 22, // C t| varius spells (63884, 50240) AURA_STATE_HEALTH_ABOVE_75_PERCENT = 23, // C | }; diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 629f9b9850f..87baad480a7 100755 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -1316,6 +1316,20 @@ void AuraEffect::PeriodicTick(Unit * target, Unit * caster) const } } } + if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_GENERIC) + { + switch (GetId()) + { + case 70911: // Unbound Plague + case 72854: // Unbound Plague + case 72855: // Unbound Plague + case 72856: // Unbound Plague + damage *= uint32(pow(1.25f, int32(m_tickNumber))); + break; + default: + break; + } + } } else damage = uint32(target->CountPctFromMaxHealth(damage)); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 0aed57b9c4e..819fe27606f 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -1877,7 +1877,7 @@ void Spell::SearchGOAreaTarget(std::list<GameObject*> &TagGOMap, float radius, S m_caster->GetMap()->VisitGrid(pos->m_positionX, pos->m_positionY, radius, searcher); } -WorldObject* Spell::SearchNearbyTarget(float range, SpellTargets TargetType) +WorldObject* Spell::SearchNearbyTarget(float range, SpellTargets TargetType, SpellEffIndex effIndex) { switch(TargetType) { @@ -1888,9 +1888,9 @@ WorldObject* Spell::SearchNearbyTarget(float range, SpellTargets TargetType) { sLog.outDebug("Spell (ID: %u) (caster Entry: %u) does not have record in `conditions` for spell script target (ConditionSourceType 14)", m_spellInfo->Id, m_caster->GetEntry()); if (IsPositiveSpell(m_spellInfo->Id)) - return SearchNearbyTarget(range, SPELL_TARGETS_ALLY); + return SearchNearbyTarget(range, SPELL_TARGETS_ALLY, effIndex); else - return SearchNearbyTarget(range, SPELL_TARGETS_ENEMY); + return SearchNearbyTarget(range, SPELL_TARGETS_ENEMY, effIndex); } Creature* creatureScriptTarget = NULL; @@ -1900,6 +1900,8 @@ WorldObject* Spell::SearchNearbyTarget(float range, SpellTargets TargetType) { if ((*i_spellST)->mConditionType != CONDITION_SPELL_SCRIPT_TARGET) continue; + if ((*i_spellST)->mConditionValue3 && !((*i_spellST)->mConditionValue3 & (1 << uint32(effIndex)))) + continue; switch((*i_spellST)->mConditionValue1) { case SPELL_TARGET_TYPE_CONTROLLED: @@ -2087,20 +2089,20 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur) case TARGET_UNIT_NEARBY_ENEMY: range = GetSpellMaxRange(m_spellInfo, false); if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); - target = SearchNearbyTarget(range, SPELL_TARGETS_ENEMY); + target = SearchNearbyTarget(range, SPELL_TARGETS_ENEMY, SpellEffIndex(i)); break; case TARGET_UNIT_NEARBY_ALLY: case TARGET_UNIT_NEARBY_ALLY_UNK: case TARGET_UNIT_NEARBY_RAID: range = GetSpellMaxRange(m_spellInfo, true); if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); - target = SearchNearbyTarget(range, SPELL_TARGETS_ALLY); + target = SearchNearbyTarget(range, SPELL_TARGETS_ALLY, SpellEffIndex(i)); break; case TARGET_UNIT_NEARBY_ENTRY: case TARGET_GAMEOBJECT_NEARBY_ENTRY: range = GetSpellMaxRange(m_spellInfo, IsPositiveSpell(m_spellInfo->Id)); if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); - target = SearchNearbyTarget(range, SPELL_TARGETS_ENTRY); + target = SearchNearbyTarget(range, SPELL_TARGETS_ENTRY, SpellEffIndex(i)); break; } @@ -2303,7 +2305,7 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur) float range = GetSpellMaxRange(m_spellInfo, IsPositiveSpell(m_spellInfo->Id)); if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); - if (WorldObject *target = SearchNearbyTarget(range, SPELL_TARGETS_ENTRY)) + if (WorldObject *target = SearchNearbyTarget(range, SPELL_TARGETS_ENTRY, SpellEffIndex(i))) m_targets.setDst(*target); break; } @@ -2473,6 +2475,8 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur) { if ((*i_spellST)->mConditionType != CONDITION_SPELL_SCRIPT_TARGET) continue; + if ((*i_spellST)->mConditionValue3 && !((*i_spellST)->mConditionValue3 & (1<<i))) + continue; if ((*i_spellST)->mConditionValue1 == SPELL_TARGET_TYPE_CREATURE) SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ENTRY, (*i_spellST)->mConditionValue2); else if ((*i_spellST)->mConditionValue1 == SPELL_TARGET_TYPE_CONTROLLED) @@ -2568,6 +2572,8 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur) { if ((*i_spellST)->mConditionType != CONDITION_SPELL_SCRIPT_TARGET) continue; + if ((*i_spellST)->mConditionValue3 && !((*i_spellST)->mConditionValue3 & (1<<i))) + continue; if ((*i_spellST)->mConditionValue1 == SPELL_TARGET_TYPE_GAMEOBJECT) SearchGOAreaTarget(gobjectList, radius, pushType, SPELL_TARGETS_GO, (*i_spellST)->mConditionValue2); } diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 3509f0bffac..2a74e21f817 100755 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -660,7 +660,7 @@ class Spell void SearchAreaTarget(std::list<Unit*> &unitList, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry = 0); void SearchGOAreaTarget(std::list<GameObject*> &gobjectList, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry = 0); void SearchChainTarget(std::list<Unit*> &unitList, float radius, uint32 unMaxTargets, SpellTargets TargetType); - WorldObject* SearchNearbyTarget(float range, SpellTargets TargetType); + WorldObject* SearchNearbyTarget(float range, SpellTargets TargetType, SpellEffIndex effIndex); bool IsValidSingleTargetEffect(Unit const* target, Targets type) const; bool IsValidSingleTargetSpell(Unit const* target) const; bool IsValidDeadOrAliveTarget(Unit const* target) const; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 48d8faa4369..f18d53bc893 100755 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3605,6 +3605,8 @@ void SpellMgr::LoadSpellCustomAttr() case 64422: case 64688: // Sonic Screech case 72373: // Shared Suffering case 71904: // Chaos Bane + case 70492: case 72505: // Ooze Eruption + case 72624: case 72625: // Ooze Eruption // ONLY SPELLS WITH SPELLFAMILY_GENERIC and EFFECT_SCHOOL_DAMAGE mSpellCustomAttr[i] |= SPELL_ATTR_CU_SHARE_DAMAGE; count++; @@ -3882,6 +3884,44 @@ void SpellMgr::LoadSpellCustomAttr() spellInfo->EffectSpellClassMask[0] = flag96(423937, 276955137, 2049); count++; break; + // this is here until targetAuraSpell and alike support SpellDifficulty.dbc + case 70459: // Ooze Eruption Search Effect + spellInfo->targetAuraSpell = 0; + count++; + break; + case 71413: // Green Ooze Summon + case 71414: // Orange Ooze Summon + spellInfo->EffectImplicitTargetA[0] = TARGET_DEST_DEST; + count++; + break; + // THIS IS HERE BECAUSE COOLDOWN ON CREATURE PROCS IS NOT IMPLEMENTED + case 71604: // Mutated Strength + case 72673: // Mutated Strength + case 72674: // Mutated Strength + case 72675: // Mutated Strength + spellInfo->Effect[1] = 0; + count++; + break; + case 70447: // Volatile Ooze Adhesive + case 72836: // Volatile Ooze Adhesive + case 72837: // Volatile Ooze Adhesive + case 72838: // Volatile Ooze Adhesive + case 70672: // Gaseous Bloat + case 72455: // Gaseous Bloat + case 72832: // Gaseous Bloat + case 72833: // Gaseous Bloat + spellInfo->EffectImplicitTargetB[0] = TARGET_UNIT_TARGET_ENEMY; + spellInfo->EffectImplicitTargetB[1] = TARGET_UNIT_TARGET_ENEMY; + spellInfo->EffectImplicitTargetB[2] = TARGET_UNIT_TARGET_ENEMY; + count++; + break; + case 70911: // Unbound Plague + case 72854: // Unbound Plague + case 72855: // Unbound Plague + case 72856: // Unbound Plague + spellInfo->EffectImplicitTargetB[0] = TARGET_UNIT_TARGET_ENEMY; + count++; + break; default: break; } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp index f8ab37813ab..0ef0504ca39 100755 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp @@ -15,32 +15,94 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "icecrown_citadel.h" enum eScriptTexts { // Festergut - SAY_FESTERGUT_GASEOUS_BLIGHT = -1631080, - SAY_FESTERGUT_DEATH = -1631090, - SAY_ROTFACE_OOZE_FLOOD1 = -1631091, - SAY_ROTFACE_OOZE_FLOOD2 = -1631092, - SAY_ROTFACE_DEATH = -1631093, + SAY_FESTERGUT_GASEOUS_BLIGHT = -1631080, + SAY_FESTERGUT_DEATH = -1631090, + + // Rotface + SAY_ROTFACE_OOZE_FLOOD1 = -1631091, + SAY_ROTFACE_OOZE_FLOOD2 = -1631092, + SAY_ROTFACE_DEATH = -1631093, + + // Professor Putricide + SAY_AGGRO = -1631104, + EMOTE_UNSTABLE_EXPERIMENT = -1631105, + SAY_PHASE_TRANSITION_HEROIC = -1631106, + SAY_TRANSFORM_1 = -1631107, + SAY_TRANSFORM_2 = -1631108, + EMOTE_MALLEABLE_GOO = -1631109, + EMOTE_CHOKING_GAS_BOMB = -1631110, + SAY_KILL_1 = -1631111, + SAY_KILL_2 = -1631112, + SAY_BERSERK = -1631113, + SAY_DEATH = -1631114 }; enum eSpells { // Festergut - SPELL_RELEASE_GAS_VISUAL = 69125, - SPELL_GASEOUS_BLIGHT_LARGE = 69157, - SPELL_GASEOUS_BLIGHT_MEDIUM = 69162, - SPELL_GASEOUS_BLIGHT_SMALL = 69164, - SPELL_MALLABLE_GOO_H = 70852, + SPELL_RELEASE_GAS_VISUAL = 69125, + SPELL_GASEOUS_BLIGHT_LARGE = 69157, + SPELL_GASEOUS_BLIGHT_MEDIUM = 69162, + SPELL_GASEOUS_BLIGHT_SMALL = 69164, + SPELL_MALLABLE_GOO_H = 70852, // Rotface - SPELL_VILE_GAS_H = 69240, + SPELL_VILE_GAS_H = 69240, + + // Professor Putricide + SPELL_SLIME_PUDDLE_TRIGGER = 70341, + SPELL_MALLEABLE_GOO = 70852, + SPELL_UNSTABLE_EXPERIMENT = 70351, + SPELL_TEAR_GAS = 71617, // phase transition + SPELL_CREATE_CONCOCTION = 71621, + SPELL_GUZZLE_POTIONS = 71893, + SPELL_OOZE_TANK_PROTECTION = 71770, // protects the tank + SPELL_CHOKING_GAS_BOMB = 71255, + SPELL_OOZE_VARIABLE = 70352, + SPELL_GAS_VARIABLE = 70353, + SPELL_UNBOUND_PLAGUE = 70911, + SPELL_UNBOUND_PLAGUE_SEARCHER = 70917, + SPELL_PLAGUE_SICKNESS = 70953, + SPELL_UNBOUND_PLAGUE_PROTECTION = 70955, + SPELL_MUTATED_PLAGUE = 72451, + + // Slime Puddle + SPELL_GROW_STACKER = 70345, + SPELL_SLIME_PUDDLE_AURA = 70343, + + // Gas Cloud + SPELL_GASEOUS_BLOAT_PROC = 70215, + SPELL_GASEOUS_BLOAT = 70672, + SPELL_GASEOUS_BLOAT_PROTECTION = 70812, + + // Volatile Ooze + SPELL_OOZE_ERUPTION = 70492, + SPELL_VOLATILE_OOZE_ADHESIVE = 70447, + SPELL_OOZE_ERUPTION_SEARCH_PERIODIC = 70457, + SPELL_VOLATILE_OOZE_PROTECTION = 70530, + + // Choking Gas Bomb + SPELL_CHOKING_GAS_BOMB_PERIODIC = 71259, + SPELL_CHOKING_GAS_EXPLOSION_TRIGGER = 71280, + + // Mutated Abomination vehicle + SPELL_ABOMINATION_VEHICLE_POWER_DRAIN = 70385, + SPELL_MUTATED_TRANSFORMATION = 70311, + SPELL_MUTATED_TRANSFORMATION_DAMAGE = 70405, + SPELL_MUTATED_TRANSFORMATION_NAME = 72401, }; +#define SPELL_GASEOUS_BLOAT_HELPER RAID_MODE<uint32>(70672,72455,72832,72833) + enum eEvents { // Festergut @@ -51,14 +113,29 @@ enum eEvents EVENT_ROTFACE_DIES = 3, EVENT_ROTFACE_VILE_GAS = 4, EVENT_ROTFACE_OOZE_FLOOD = 5, + + // Professor Putricide + EVENT_BERSERK = 6, // all phases + EVENT_SLIME_PUDDLE = 7, // all phases + EVENT_UNSTABLE_EXPERIMENT = 8, // P1 && P2 + EVENT_TEAR_GAS = 9, // phase transition not heroic + EVENT_RESUME_ATTACK = 10, + EVENT_MALLEABLE_GOO = 11, + EVENT_CHOKING_GAS_BOMB = 12, + EVENT_UNBOUND_PLAGUE = 13, + EVENT_MUTATED_PLAGUE = 14, + EVENT_PHASE_TRANSITION = 15, }; enum ePhases { PHASE_FESTERGUT = 1, PHASE_ROTFACE = 2, - PHASE_COMBAT = 3, + PHASE_COMBAT_1 = 4, + PHASE_COMBAT_2 = 5, + PHASE_COMBAT_3 = 6, + PHASE_MASK_COMBAT = (1 << PHASE_COMBAT_1) | (1 << PHASE_COMBAT_2) | (1 << PHASE_COMBAT_3), PHASE_MASK_NOT_SELF = (1 << PHASE_FESTERGUT) | (1 << PHASE_ROTFACE) }; @@ -66,13 +143,33 @@ enum ePoints { POINT_FESTERGUT = 366260, POINT_ROTFACE = 366270, + POINT_TABLE = 366780, }; static const Position festergutWatchPos = {4324.820f, 3166.03f, 389.3831f, 3.316126f}; //emote 432 (release gas) -static const Position rotfaceWatchPos = {4390.371f, 3164.50f, 389.3890f, 5.497787f}; //emote 432 (release gas) +static const Position rotfaceWatchPos = {4390.371f, 3164.50f, 389.3890f, 5.497787f}; //emote 432 (release ooze) +static const Position tablePos = {4356.190f, 3262.90f, 389.4820f, 1.483530f}; static const uint32 oozeFloodSpells[4] = {69782, 69796, 69798, 69801}; +#define DATA_EXPERIMENT_STAGE 0 +#define EXPERIMENT_STATE_OOZE false +#define EXPERIMENT_STATE_GAS true + +class StartMovementEvent : public BasicEvent +{ + public: + StartMovementEvent(Creature& owner) : BasicEvent(), m_owner(owner) { } + bool Execute(uint64 /*eventTime*/, uint32 /*diff*/) + { + m_owner.GetMotionMaster()->MoveChase(m_owner.getVictim()); + return true; + } + + private: + Creature& m_owner; +}; + class boss_professor_putricide : public CreatureScript { public: @@ -81,7 +178,7 @@ class boss_professor_putricide : public CreatureScript struct boss_professor_putricideAI : public BossAI { boss_professor_putricideAI(Creature* pCreature) : BossAI(pCreature, DATA_PROFESSOR_PUTRICIDE), - fBaseSpeed(pCreature->GetSpeedRate(MOVE_RUN)) + fBaseSpeed(pCreature->GetSpeedRate(MOVE_RUN)), bExperimentState(EXPERIMENT_STATE_OOZE) { ASSERT(instance); phase = ePhases(0); @@ -89,15 +186,184 @@ class boss_professor_putricide : public CreatureScript void Reset() { + if (!(events.GetPhaseMask() & PHASE_MASK_NOT_SELF)) + instance->SetBossState(DATA_PROFESSOR_PUTRICIDE, NOT_STARTED); + instance->SetData(DATA_NAUSEA___ACHIEVEMENT, uint32(true)); + events.Reset(); summons.DespawnAll(); - _SetPhase(PHASE_COMBAT); + _SetPhase(PHASE_COMBAT_1); + bExperimentState = EXPERIMENT_STATE_OOZE; me->SetReactState(REACT_DEFENSIVE); me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE) me->GetMotionMaster()->MovementExpired(); } + void EnterCombat(Unit* /*who*/) + { + if (events.GetPhaseMask() & PHASE_MASK_NOT_SELF) + return; + + _SetPhase(PHASE_COMBAT_1); + DoScriptText(SAY_AGGRO, me); + DoCast(me, SPELL_OOZE_TANK_PROTECTION, true); + DoZoneInCombat(me); + + events.Reset(); + events.ScheduleEvent(EVENT_BERSERK, 600000); + events.ScheduleEvent(EVENT_SLIME_PUDDLE, 10000); + events.ScheduleEvent(EVENT_UNSTABLE_EXPERIMENT, urand(25000, 30000)); + if (IsHeroic()) + events.ScheduleEvent(EVENT_UNBOUND_PLAGUE, 20000); + + instance->SetBossState(DATA_PROFESSOR_PUTRICIDE, IN_PROGRESS); + } + + void JustReachedHome() + { + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); + if (events.GetPhaseMask() & PHASE_MASK_COMBAT) + instance->SetBossState(DATA_PROFESSOR_PUTRICIDE, FAIL); + } + + void KilledUnit(Unit *victim) + { + if (victim->GetTypeId() == TYPEID_PLAYER) + DoScriptText(RAND(SAY_KILL_1, SAY_KILL_2), me); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + instance->SetBossState(DATA_PROFESSOR_PUTRICIDE, DONE); + } + + void JustSummoned(Creature* summon) + { + summons.Summon(summon); + switch (summon->GetEntry()) + { + case NPC_GROWING_OOZE_PUDDLE: + summon->CastSpell(summon, SPELL_GROW_STACKER, true); + summon->CastSpell(summon, SPELL_SLIME_PUDDLE_AURA, true); + break; + case NPC_GAS_CLOUD: + // no possible aura seen in sniff adding the aurastate + summon->SetFlag(UNIT_FIELD_AURASTATE, 1 << (AURA_STATE_UNKNOWN22-1)); + summon->CastSpell(summon, SPELL_GASEOUS_BLOAT_PROC, true); + // taunt immunity + summon->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + summon->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_GASEOUS_BLOAT_PROTECTION)) + { + summon->AI()->AttackStart(target); + summon->CastCustomSpell(SPELL_GASEOUS_BLOAT, SPELLVALUE_MAX_TARGETS, 1, target, false); + summon->clearUnitState(UNIT_STAT_CASTING); + summon->GetMotionMaster()->MoveIdle(); + summon->m_Events.AddEvent(new StartMovementEvent(*summon), summon->m_Events.CalculateTime(3500)); + } + return; + case NPC_VOLATILE_OOZE: + // no possible aura seen in sniff adding the aurastate + summon->SetFlag(UNIT_FIELD_AURASTATE, 1 << (AURA_STATE_UNKNOWN19-1)); + summon->CastSpell(summon, SPELL_OOZE_ERUPTION_SEARCH_PERIODIC, true); + // taunt immunity + summon->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + summon->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_VOLATILE_OOZE_PROTECTION)) + { + summon->AI()->AttackStart(target); + summon->CastCustomSpell(SPELL_VOLATILE_OOZE_ADHESIVE, SPELLVALUE_MAX_TARGETS, 1, target, false); + summon->clearUnitState(UNIT_STAT_CASTING); + summon->GetMotionMaster()->MoveIdle(); + summon->m_Events.AddEvent(new StartMovementEvent(*summon), summon->m_Events.CalculateTime(3500)); + } + return; + case NPC_CHOKING_GAS_BOMB: + summon->CastSpell(summon, SPELL_CHOKING_GAS_BOMB_PERIODIC, true); + summon->CastSpell(summon, SPELL_CHOKING_GAS_EXPLOSION_TRIGGER, true); + return; + default: + break; + } + if (me->isInCombat()) + DoZoneInCombat(summon); + } + + void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) + { + switch (phase) + { + case PHASE_COMBAT_1: + if (HealthAbovePct(80)) + return; + me->SetReactState(REACT_PASSIVE); + DoAction(ACTION_CHANGE_PHASE); + break; + case PHASE_COMBAT_2: + if (HealthAbovePct(35)) + return; + me->SetReactState(REACT_PASSIVE); + DoAction(ACTION_CHANGE_PHASE); + break; + default: + break; + } + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + switch (id) + { + case POINT_FESTERGUT: + me->SetSpeed(MOVE_RUN, fBaseSpeed, true); + DoAction(ACTION_FESTERGUT_GAS); + if (Creature* festergut = Unit::GetCreature(*me, instance->GetData64(DATA_FESTERGUT))) + festergut->CastSpell(festergut, SPELL_GASEOUS_BLIGHT_LARGE, false, NULL, NULL, festergut->GetGUID()); + break; + case POINT_ROTFACE: + me->SetSpeed(MOVE_RUN, fBaseSpeed, true); + DoAction(ACTION_ROTFACE_OOZE); + events.ScheduleEvent(EVENT_ROTFACE_OOZE_FLOOD, 25000, 0, PHASE_ROTFACE); + break; + case POINT_TABLE: + // stop attack + me->GetMotionMaster()->MoveIdle(); + me->Attack(me->getVictim(), false); + me->SetSpeed(MOVE_RUN, fBaseSpeed, true); + if (GameObject* table = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_PUTRICIDE_TABLE))) + me->SetFacingToObject(table); + // operating on new phase already + switch (phase) + { + case PHASE_COMBAT_2: + { + SpellEntry const* spell = sSpellStore.LookupEntry(SPELL_CREATE_CONCOCTION); + spell = sSpellMgr.GetSpellForDifficultyFromSpell(spell, me); + DoCast(me, SPELL_CREATE_CONCOCTION); + events.ScheduleEvent(EVENT_PHASE_TRANSITION, GetSpellCastTime(spell)+100); + break; + } + case PHASE_COMBAT_3: + { + SpellEntry const* spell = sSpellStore.LookupEntry(SPELL_GUZZLE_POTIONS); + spell = sSpellMgr.GetSpellForDifficultyFromSpell(spell, me); + DoCast(me, SPELL_GUZZLE_POTIONS); + events.ScheduleEvent(EVENT_PHASE_TRANSITION, GetSpellCastTime(spell)+100); + break; + } + default: + break; + } + break; + default: + break; + } + } + void DoAction(const int32 action) { switch (action) @@ -160,45 +426,87 @@ class boss_professor_putricide : public CreatureScript } case ACTION_ROTFACE_OOZE: DoScriptText(RAND(SAY_ROTFACE_OOZE_FLOOD1, SAY_ROTFACE_OOZE_FLOOD2), me); - if (Unit::GetCreature(*me, instance->GetData64(DATA_ROTFACE))) - if (Creature* dummy = Unit::GetCreature(*me, oozeFloodDummy[oozeFloodStage])) - dummy->CastSpell(dummy, oozeFloodSpells[oozeFloodStage], true, NULL, NULL, me->GetGUID()); // cast from self for LoS (with prof's GUID for logs) + if (Creature* dummy = Unit::GetCreature(*me, oozeFloodDummy[oozeFloodStage])) + dummy->CastSpell(dummy, oozeFloodSpells[oozeFloodStage], true, NULL, NULL, me->GetGUID()); // cast from self for LoS (with prof's GUID for logs) if (++oozeFloodStage == 4) oozeFloodStage = 0; break; case ACTION_ROTFACE_DEATH: events.ScheduleEvent(EVENT_ROTFACE_DIES, 4500, 0, PHASE_ROTFACE); break; + case ACTION_CHANGE_PHASE: + me->SetSpeed(MOVE_RUN, fBaseSpeed*2.0f, true); + events.DelayEvents(30000); + if (!IsHeroic()) + { + DoCast(me, SPELL_TEAR_GAS); + events.ScheduleEvent(EVENT_TEAR_GAS, 2500); + } + else + { + DoScriptText(SAY_PHASE_TRANSITION_HEROIC, me); + DoCast(me, SPELL_UNSTABLE_EXPERIMENT, true); + DoCast(me, SPELL_UNSTABLE_EXPERIMENT, true); + // cast variables + if (Is25ManRaid()) + { + std::list<Unit*> targetList; + { + const std::list<HostileReference*>& threatlist = me->getThreatManager().getThreatList(); + for (std::list<HostileReference*>::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) + if ((*itr)->getTarget()->GetTypeId() == TYPEID_PLAYER) + targetList.push_back((*itr)->getTarget()); + } + + size_t half = targetList.size()/2; + // half gets ooze variable + while (half < targetList.size()) + { + std::list<Unit*>::iterator itr = targetList.begin(); + advance(itr, urand(0, targetList.size()-1)); + DoCast(*itr, SPELL_OOZE_VARIABLE); + targetList.erase(itr); + } + // and half gets gas + for (std::list<Unit*>::iterator itr = targetList.begin(); itr != targetList.end(); ++itr) + DoCast(*itr, SPELL_GAS_VARIABLE); + } + me->GetMotionMaster()->MovePoint(POINT_TABLE, tablePos); + } + switch (phase) + { + case PHASE_COMBAT_1: + _SetPhase(PHASE_COMBAT_2); + events.ScheduleEvent(EVENT_MALLEABLE_GOO, urand(21000, 26000)); + events.ScheduleEvent(EVENT_CHOKING_GAS_BOMB, urand(35000, 40000)); + break; + case PHASE_COMBAT_2: + _SetPhase(PHASE_COMBAT_3); + events.ScheduleEvent(EVENT_MUTATED_PLAGUE, 25000); + events.CancelEvent(EVENT_UNSTABLE_EXPERIMENT); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MUTATED_TRANSFORMATION); + instance->DoRemoveAurasDueToSpellOnPlayers(71503); // SPELL_MUTATED_TRANSFORMATION2 + break; + default: + break; + } + break; default: break; } } - void JustReachedHome() + uint32 GetData(uint32 type) { - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); - if (phase == PHASE_COMBAT) - instance->SetBossState(DATA_PROFESSOR_PUTRICIDE, FAIL); - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - switch (id) + if (type == DATA_EXPERIMENT_STAGE) { - case POINT_FESTERGUT: - me->SetSpeed(MOVE_RUN, fBaseSpeed, true); - DoAction(ACTION_FESTERGUT_GAS); - if (Creature* festergut = Unit::GetCreature(*me, instance->GetData64(DATA_FESTERGUT))) - festergut->CastSpell(festergut, SPELL_GASEOUS_BLIGHT_LARGE, false, NULL, NULL, festergut->GetGUID()); - break; - case POINT_ROTFACE: - me->SetSpeed(MOVE_RUN, fBaseSpeed, true); - DoAction(ACTION_ROTFACE_OOZE); - events.ScheduleEvent(EVENT_ROTFACE_OOZE_FLOOD, 25000, 0, PHASE_ROTFACE); - break; + // ALSO MODIFIES! + uint32 ret = uint32(bExperimentState); + bExperimentState ^= true; + return ret; } + + return 0; } void UpdateAI(const uint32 diff) @@ -236,10 +544,103 @@ class boss_professor_putricide : public CreatureScript case EVENT_ROTFACE_OOZE_FLOOD: DoAction(ACTION_ROTFACE_OOZE); events.ScheduleEvent(EVENT_ROTFACE_OOZE_FLOOD, 25000, 0, PHASE_ROTFACE); + break; + case EVENT_BERSERK: + DoScriptText(SAY_BERSERK, me); + DoCast(me, SPELL_BERSERK2); + break; + case EVENT_SLIME_PUDDLE: + { + std::list<Unit*> targets; + SelectTargetList(targets, 2, SELECT_TARGET_RANDOM, 0.0f, true); + if (!targets.empty()) + for (std::list<Unit*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) + DoCast(*itr, SPELL_SLIME_PUDDLE_TRIGGER); + events.ScheduleEvent(EVENT_SLIME_PUDDLE, 35000); + break; + } + case EVENT_UNSTABLE_EXPERIMENT: + DoScriptText(EMOTE_UNSTABLE_EXPERIMENT, me); + DoCast(me, SPELL_UNSTABLE_EXPERIMENT); + events.ScheduleEvent(EVENT_UNSTABLE_EXPERIMENT, urand(35000, 40000)); + break; + case EVENT_TEAR_GAS: + me->GetMotionMaster()->MovePoint(POINT_TABLE, tablePos); + break; + case EVENT_RESUME_ATTACK: + me->SetReactState(REACT_DEFENSIVE); + AttackStart(me->getVictim()); + // remove Tear Gas + instance->DoRemoveAurasDueToSpellOnPlayers(71615); + instance->DoRemoveAurasDueToSpellOnPlayers(71618); + break; + case EVENT_MALLEABLE_GOO: + if (Is25ManRaid()) + { + std::list<Unit*> targets; + SelectTargetList(targets, 2, SELECT_TARGET_RANDOM, -7.0f, true); + if (!targets.empty()) + { + DoScriptText(EMOTE_MALLEABLE_GOO, me); + for (std::list<Unit*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) + DoCast(*itr, SPELL_MALLEABLE_GOO); + } + } + else + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, -7.0f, true)) + { + DoScriptText(EMOTE_MALLEABLE_GOO, me); + DoCast(target, SPELL_MALLEABLE_GOO); + } + } + events.ScheduleEvent(EVENT_MALLEABLE_GOO, urand(25000, 30000)); + break; + case EVENT_CHOKING_GAS_BOMB: + DoScriptText(EMOTE_CHOKING_GAS_BOMB, me); + DoCast(me, SPELL_CHOKING_GAS_BOMB); + events.ScheduleEvent(EVENT_CHOKING_GAS_BOMB, urand(35000, 40000)); + break; + case EVENT_UNBOUND_PLAGUE: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true)) + { + me->CastCustomSpell(SPELL_UNBOUND_PLAGUE, SPELLVALUE_BASE_POINT0, 775, target); + DoCast(target, SPELL_UNBOUND_PLAGUE_SEARCHER); + } + events.ScheduleEvent(EVENT_UNBOUND_PLAGUE, 90000); + break; + case EVENT_MUTATED_PLAGUE: + DoCastVictim(SPELL_MUTATED_PLAGUE); + events.ScheduleEvent(EVENT_MUTATED_PLAGUE, 10000); + break; + case EVENT_PHASE_TRANSITION: + { + switch (phase) + { + case PHASE_COMBAT_2: + if (Creature* face = me->FindNearestCreature(NPC_TEAR_GAS_TARGET_STALKER, 50.0f)) + me->SetFacingToObject(face); + me->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL); + DoScriptText(SAY_TRANSFORM_1, me); + events.ScheduleEvent(EVENT_RESUME_ATTACK, 5500, 0, PHASE_COMBAT_2); + break; + case PHASE_COMBAT_3: + if (Creature* face = me->FindNearestCreature(NPC_TEAR_GAS_TARGET_STALKER, 50.0f)) + me->SetFacingToObject(face); + me->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL); + DoScriptText(SAY_TRANSFORM_2, me); + events.ScheduleEvent(EVENT_RESUME_ATTACK, 8500, 0, PHASE_COMBAT_3); + break; + default: + break; + } + } default: break; } } + + DoMeleeAttackIfReady(); } private: @@ -250,9 +651,11 @@ class boss_professor_putricide : public CreatureScript } ePhases phase; // external of EventMap because event phase gets reset on evade + // Festergut & Rotface variables const float fBaseSpeed; uint64 oozeFloodDummy[4]; uint8 oozeFloodStage; + bool bExperimentState; }; CreatureAI* GetAI(Creature* pCreature) const @@ -261,6 +664,627 @@ class boss_professor_putricide : public CreatureScript } }; +class npc_volatile_ooze : public CreatureScript +{ + public: + npc_volatile_ooze() : CreatureScript("npc_volatile_ooze") { } + + struct npc_volatile_oozeAI : public ScriptedAI + { + npc_volatile_oozeAI(Creature* pCreature) : ScriptedAI(pCreature) + { + uiNewTargetSelectTimer = 0; + } + + void SpellHitTarget(Unit* /*pTarget*/, const SpellEntry* spell) + { + SpellEntry const* explode = sSpellStore.LookupEntry(SPELL_OOZE_ERUPTION); + explode = sSpellMgr.GetSpellForDifficultyFromSpell(explode, me); + if (explode->Id == spell->Id) + { + uiNewTargetSelectTimer = 5000; + DoStartNoMovement(me); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (!uiNewTargetSelectTimer) + return; + + if (uiNewTargetSelectTimer <= diff) + { + uiNewTargetSelectTimer = 0; + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_VOLATILE_OOZE_PROTECTION)) + { + AttackStart(target); + me->CastCustomSpell(SPELL_VOLATILE_OOZE_ADHESIVE, SPELLVALUE_MAX_TARGETS, 1, target, false); + } + else if (TempSummon* summ = me->ToTempSummon()) + summ->UnSummon(); + else + me->ForcedDespawn(); + } + else + uiNewTargetSelectTimer -= diff; + } + + private: + // no need to use EventMap for just one event + uint32 uiNewTargetSelectTimer; + }; + + CreatureAI* GetAI(Creature* pCreature) const + { + return new npc_volatile_oozeAI(pCreature); + } +}; + +class spell_putricide_gaseous_bloat : public SpellScriptLoader +{ + public: + spell_putricide_gaseous_bloat() : SpellScriptLoader("spell_putricide_gaseous_bloat") { } + + class spell_putricide_gaseous_bloat_SpellScript : public SpellScript + { + PrepareSpellScript(spell_putricide_gaseous_bloat_SpellScript); + + void ModAuraStack() + { + if (Aura* aur = GetHitAura()) + aur->SetStackAmount(10); + } + + void Register() + { + AfterHit += SpellHitFn(spell_putricide_gaseous_bloat_SpellScript::ModAuraStack); + } + }; + + class spell_putricide_gaseous_bloat_AuraScript : public AuraScript + { + PrepareAuraScript(spell_putricide_gaseous_bloat_AuraScript); + + void HandleExtraEffect(AuraEffect const* /*aurEff*/, AuraApplication const* aurApp) + { + if (aurApp->GetTarget()) + aurApp->GetTarget()->RemoveAuraFromStack(GetSpellProto()->Id, aurApp->GetBase()->GetCasterGUID()); + } + + void Register() + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_putricide_gaseous_bloat_AuraScript::HandleExtraEffect, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_putricide_gaseous_bloat_SpellScript(); + } + + AuraScript* GetAuraScript() const + { + return new spell_putricide_gaseous_bloat_AuraScript(); + } +}; + +class spell_putricide_expunged_gas : public SpellScriptLoader +{ + public: + spell_putricide_expunged_gas() : SpellScriptLoader("spell_putricide_expunged_gas") { } + + class spell_putricide_expunged_gas_SpellScript : public SpellScript + { + PrepareSpellScript(spell_putricide_expunged_gas_SpellScript); + + void CalcDamage(SpellEffIndex /*effIndex*/) + { + if (GetCaster()->GetTypeId() != TYPEID_UNIT) + return; + + InstanceScript* instance = GetCaster()->GetInstanceScript(); + if (!instance) + return; + + Creature* professor = Unit::GetCreature(*GetCaster(), instance->GetData64(DATA_PROFESSOR_PUTRICIDE)); + if (!professor) + return; + + int32 dmg = 0; + ScriptedAI* professorAI = CAST_AI(ScriptedAI, professor->AI()); + if (Aura* gasBloat = GetTargetUnit()->GetAura(professorAI->SPELL_GASEOUS_BLOAT_HELPER)) + { + uint32 stack = gasBloat->GetStackAmount(); + const int32 mod = professorAI->Is25ManRaid() ? 1500 : 1250; + for (uint8 i = 1; i < stack; ++i) + dmg += mod * stack; + } + else if (TempSummon* summ = GetCaster()->ToTempSummon()) + summ->UnSummon(); + else + GetCaster()->ToCreature()->ForcedDespawn(); + + SetHitDamage(dmg); + } + + void Register() + { + OnEffect += SpellEffectFn(spell_putricide_expunged_gas_SpellScript::CalcDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_putricide_expunged_gas_SpellScript(); + } +}; + +class spell_putricide_slime_puddle : public SpellScriptLoader +{ + public: + spell_putricide_slime_puddle() : SpellScriptLoader("spell_putricide_slime_puddle") { } + + class spell_putricide_slime_puddle_AuraScript : public AuraScript + { + PrepareAuraScript(spell_putricide_slime_puddle_AuraScript); + + void HandleTriggerSpell(AuraEffect const* aurEff, AuraApplication const* aurApp) + { + PreventDefaultAction(); + if (Unit* caster = aurApp->GetBase()->GetCaster()) + { + int32 radiusMod = 4; + if (Aura* size = caster->GetAura(70347)) + radiusMod += size->GetStackAmount(); + + uint32 triggerSpellId = GetSpellProto()->EffectTriggerSpell[aurEff->GetEffIndex()]; + caster->CastCustomSpell(triggerSpellId, SPELLVALUE_RADIUS_MOD, radiusMod*100, caster, true); + } + } + + void Register() + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_putricide_slime_puddle_AuraScript::HandleTriggerSpell, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_putricide_slime_puddle_AuraScript(); + } +}; + +class spell_putricide_unstable_experiment : public SpellScriptLoader +{ + public: + spell_putricide_unstable_experiment() : SpellScriptLoader("spell_putricide_unstable_experiment") { } + + class spell_putricide_unstable_experiment_SpellScript : public SpellScript + { + PrepareSpellScript(spell_putricide_unstable_experiment_SpellScript); + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + if (GetCaster()->GetTypeId() != TYPEID_UNIT) + return; + + uint32 stage = GetCaster()->ToCreature()->AI()->GetData(DATA_EXPERIMENT_STAGE); + Creature* target = NULL; + std::list<Creature*> creList; + GetCreatureListWithEntryInGrid(creList, GetCaster(), NPC_ABOMINATION_WING_MAD_SCIENTIST_STALKER, 100.0f); + // 2 of them are spawned at green place - weird trick blizz + for (std::list<Creature*>::iterator itr = creList.begin(); itr != creList.end(); ++itr) + { + target = *itr; + std::list<Creature*> tmp; + GetCreatureListWithEntryInGrid(tmp, target, NPC_ABOMINATION_WING_MAD_SCIENTIST_STALKER, 1.0f); + if ((!stage && tmp.size() > 1) || (stage && tmp.size() == 1)) + break; + } + + GetCaster()->CastSpell(target, GetSpellInfo()->EffectBasePoints[stage]+1, true, NULL, NULL, GetCaster()->GetGUID()); + } + + void Register() + { + OnEffect += SpellEffectFn(spell_putricide_unstable_experiment_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_putricide_unstable_experiment_SpellScript(); + } +}; + +class spell_putricide_ooze_summon : public SpellScriptLoader +{ + public: + spell_putricide_ooze_summon() : SpellScriptLoader("spell_putricide_ooze_summon") { } + + class spell_putricide_ooze_summon_AuraScript : public AuraScript + { + PrepareAuraScript(spell_putricide_ooze_summon_AuraScript); + + void HandleTriggerSpell(AuraEffect const* aurEff, AuraApplication const* aurApp) + { + PreventDefaultAction(); + if (Unit* caster = GetCaster()) + { + uint32 triggerSpellId = GetSpellProto()->EffectTriggerSpell[aurEff->GetEffIndex()]; + float x, y, z; + aurApp->GetTarget()->GetPosition(x, y, z); + z = aurApp->GetTarget()->GetMap()->GetHeight(x, y, z, true, 25.0f); + x += 10.0f * cosf(caster->GetOrientation()); + y += 10.0f * sinf(caster->GetOrientation()); + caster->CastSpell(x, y, z, triggerSpellId, true, NULL, NULL, GetCasterGUID(), caster); + } + } + + void Register() + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_putricide_ooze_summon_AuraScript::HandleTriggerSpell, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_putricide_ooze_summon_AuraScript(); + } +}; + +class spell_putricide_ooze_eruption_searcher : public SpellScriptLoader +{ + public: + spell_putricide_ooze_eruption_searcher() : SpellScriptLoader("spell_putricide_ooze_eruption_searcher") { } + + class spell_putricide_ooze_eruption_searcher_SpellScript : public SpellScript + { + PrepareSpellScript(spell_putricide_ooze_eruption_searcher_SpellScript); + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + SpellEntry const* adhesive = sSpellStore.LookupEntry(SPELL_VOLATILE_OOZE_ADHESIVE); + adhesive = sSpellMgr.GetSpellForDifficultyFromSpell(adhesive, GetCaster()); + if (GetHitUnit()->HasAura(adhesive->Id)) + { + GetCaster()->CastSpell(GetHitUnit(), SPELL_OOZE_ERUPTION, true); + GetHitUnit()->RemoveAurasDueToSpell(adhesive->Id, GetCaster()->GetGUID()); + } + } + + void Register() + { + OnEffect += SpellEffectFn(spell_putricide_ooze_eruption_searcher_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_putricide_ooze_eruption_searcher_SpellScript(); + } +}; + +class spell_putricide_choking_gas_bomb : public SpellScriptLoader +{ + public: + spell_putricide_choking_gas_bomb() : SpellScriptLoader("spell_putricide_choking_gas_bomb") { } + + class spell_putricide_choking_gas_bomb_SpellScript : public SpellScript + { + PrepareSpellScript(spell_putricide_choking_gas_bomb_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + uint32 skipIndex = urand(0, 2); + for (uint32 i = 0; i < 3; ++i) + { + if (i == skipIndex) + continue; + + uint32 spellId = SpellMgr::CalculateSpellEffectAmount(GetSpellInfo(), uint8(i)); + GetCaster()->CastSpell(GetCaster(), spellId, true, NULL, NULL, GetCaster()->GetGUID()); + } + } + + void Register() + { + OnEffect += SpellEffectFn(spell_putricide_choking_gas_bomb_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_putricide_choking_gas_bomb_SpellScript(); + } +}; + +class spell_putricide_unbound_plague : public SpellScriptLoader +{ + public: + spell_putricide_unbound_plague() : SpellScriptLoader("spell_putricide_unbound_plague") { } + + class spell_putricide_unbound_plague_SpellScript : public SpellScript + { + PrepareSpellScript(spell_putricide_unbound_plague_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (!GetHitUnit()) + return; + + SpellEntry const* plague = sSpellStore.LookupEntry(SPELL_UNBOUND_PLAGUE); + SpellEntry const* searcher = sSpellStore.LookupEntry(SPELL_UNBOUND_PLAGUE_SEARCHER); + Creature* professor = NULL; + if (InstanceScript* instance = GetCaster()->GetInstanceScript()) + { + professor = Unit::GetCreature(*GetCaster(), instance->GetData64(DATA_PROFESSOR_PUTRICIDE)); + if (professor) + { + plague = sSpellMgr.GetSpellForDifficultyFromSpell(plague, professor); + searcher = sSpellMgr.GetSpellForDifficultyFromSpell(searcher, professor); + } + } + + if (!GetHitUnit()->HasAura(plague->Id)) + { + if (professor) + if (Aura* oldPlague = GetCaster()->GetAura(plague->Id, professor->GetGUID())) + if (Aura* newPlague = professor->AddAura(plague->Id, GetHitUnit())) + { + newPlague->SetMaxDuration(oldPlague->GetDuration()); + newPlague->SetDuration(oldPlague->GetDuration()); + oldPlague->Remove(); + GetCaster()->RemoveAurasDueToSpell(searcher->Id); + GetCaster()->CastSpell(GetCaster(), SPELL_PLAGUE_SICKNESS, true); + GetCaster()->CastSpell(GetCaster(), SPELL_UNBOUND_PLAGUE_PROTECTION, true); + professor->CastSpell(GetHitUnit(), SPELL_UNBOUND_PLAGUE_SEARCHER, true); + } + } + } + + void Register() + { + OnEffect += SpellEffectFn(spell_putricide_unbound_plague_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_putricide_unbound_plague_SpellScript(); + } +}; + +class spell_putricide_eat_ooze : public SpellScriptLoader +{ + public: + spell_putricide_eat_ooze() : SpellScriptLoader("spell_putricide_eat_ooze") { } + + class spell_putricide_eat_ooze_SpellScript : public SpellScript + { + PrepareSpellScript(spell_putricide_eat_ooze_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Creature* target = GetCaster()->FindNearestCreature(NPC_GROWING_OOZE_PUDDLE, 15.0f)) + { + if (Aura* grow = target->GetAura(GetEffectValue())) + { + if (grow->GetStackAmount() < 4) + { + target->RemoveAurasDueToSpell(SPELL_GROW_STACKER); + target->RemoveAura(grow); + if (TempSummon* summ = target->ToTempSummon()) + summ->UnSummon(); + else + target->ForcedDespawn(); + } + else + grow->ModStackAmount(-4); + } + } + } + + void Register() + { + OnEffect += SpellEffectFn(spell_putricide_eat_ooze_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_putricide_eat_ooze_SpellScript(); + } +}; + +class spell_putricide_mutated_plague : public SpellScriptLoader +{ + public: + spell_putricide_mutated_plague() : SpellScriptLoader("spell_putricide_mutated_plague") { } + + class spell_putricide_mutated_plague_AuraScript : public AuraScript + { + PrepareAuraScript(spell_putricide_mutated_plague_AuraScript); + + void HandleTriggerSpell(AuraEffect const* aurEff, AuraApplication const* aurApp) + { + PreventDefaultAction(); + Unit* caster = GetCaster(); + if (!caster) + return; + + uint32 triggerSpell = GetSpellProto()->EffectTriggerSpell[aurEff->GetEffIndex()]; + SpellEntry const* spell = sSpellStore.LookupEntry(triggerSpell); + spell = sSpellMgr.GetSpellForDifficultyFromSpell(spell, caster); + + int32 damage = SpellMgr::CalculateSpellEffectAmount(spell, 0, caster); + float multiplier = 2.0f; + if (aurApp->GetTarget()->GetMap()->GetSpawnMode() & 1) + multiplier = 3.0f; + + damage *= int32(pow(multiplier, aurApp->GetBase()->GetStackAmount())); + damage *= 1.5; + + aurApp->GetTarget()->CastCustomSpell(triggerSpell, SPELLVALUE_BASE_POINT0, damage, aurApp->GetTarget(), true, NULL, aurEff, GetCasterGUID()); + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraApplication const* aurApp, AuraEffectHandleModes /*mode*/) + { + if (aurApp->GetRemoveMode() == AURA_REMOVE_BY_STACK) + return; + uint32 healSpell = SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), 0); + aurApp->GetTarget()->CastSpell(aurApp->GetTarget(), healSpell, true, NULL, NULL, GetCasterGUID()); + } + + void Register() + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_putricide_mutated_plague_AuraScript::HandleTriggerSpell, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + OnEffectRemove += AuraEffectRemoveFn(spell_putricide_mutated_plague_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_putricide_mutated_plague_AuraScript(); + } +}; + +class spell_putricide_mutation_init : public SpellScriptLoader +{ + public: + spell_putricide_mutation_init() : SpellScriptLoader("spell_putricide_mutation_init") { } + + class spell_putricide_mutation_init_AuraScript : public AuraScript + { + PrepareAuraScript(spell_putricide_mutation_init_AuraScript); + + void OnRemove(AuraEffect const* /*aurEff*/, AuraApplication const* aurApp, AuraEffectHandleModes /*mode*/) + { + uint32 spellId = 70311; + if (aurApp->GetTarget()->GetMap()->GetSpawnMode() & 1) + spellId = 71503; + + aurApp->GetTarget()->CastSpell(aurApp->GetTarget(), spellId, true); + } + + void Register() + { + OnEffectRemove += AuraEffectRemoveFn(spell_putricide_mutation_init_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_putricide_mutation_init_AuraScript(); + } +}; + +class spell_putricide_mutated_transformation_dismiss : public SpellScriptLoader +{ + public: + spell_putricide_mutated_transformation_dismiss() : SpellScriptLoader("spell_putricide_mutated_transformation_dismiss") { } + + class spell_putricide_mutated_transformation_dismiss_AuraScript : public AuraScript + { + PrepareAuraScript(spell_putricide_mutated_transformation_dismiss_AuraScript); + + void OnRemove(AuraEffect const* /*aurEff*/, AuraApplication const* aurApp, AuraEffectHandleModes /*mode*/) + { + if (Vehicle* veh = aurApp->GetTarget()->GetVehicleKit()) + veh->RemoveAllPassengers(); + } + + void Register() + { + OnEffectRemove += AuraEffectRemoveFn(spell_putricide_mutated_transformation_dismiss_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_putricide_mutated_transformation_dismiss_AuraScript(); + } +}; + +class spell_putricide_mutated_transformation : public SpellScriptLoader +{ + public: + spell_putricide_mutated_transformation() : SpellScriptLoader("spell_putricide_mutated_transformation") { } + + class spell_putricide_mutated_transformation_SpellScript : public SpellScript + { + PrepareSpellScript(spell_putricide_mutated_transformation_SpellScript); + + void HandleSummon(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + uint32 entry = GetSpellInfo()->EffectMiscValue[effIndex]; + SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(GetSpellInfo()->EffectMiscValueB[effIndex]); + Unit* caster = GetOriginalCaster(); + if (!caster) + return; + + int32 duration = GetSpellDuration(GetSpellInfo()); + + Position pos; + caster->GetPosition(&pos); + TempSummon* summon = caster->GetMap()->SummonCreature(entry, pos, properties, duration, caster); + if (!summon || !summon->IsVehicle()) + return; + + caster->CastSpell(summon, SPELL_MUTATED_TRANSFORMATION_NAME, true); + summon->CastSpell(summon, SPELL_ABOMINATION_VEHICLE_POWER_DRAIN, true); + summon->CastSpell(summon, SPELL_MUTATED_TRANSFORMATION_DAMAGE, true); + caster->EnterVehicle(summon->GetVehicleKit(), 0); + + summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, GetSpellInfo()->Id); + summon->SetCreatorGUID(caster->GetGUID()); + } + + void Register() + { + OnEffect += SpellEffectFn(spell_putricide_mutated_transformation_SpellScript::HandleSummon, EFFECT_0, SPELL_EFFECT_SUMMON); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_putricide_mutated_transformation_SpellScript(); + } +}; + +class spell_putricide_regurgitated_ooze : public SpellScriptLoader +{ + public: + spell_putricide_regurgitated_ooze() : SpellScriptLoader("spell_putricide_regurgitated_ooze") { } + + class spell_putricide_regurgitated_ooze_SpellScript : public SpellScript + { + PrepareSpellScript(spell_putricide_regurgitated_ooze_SpellScript); + + // the only purpose of this hook is to fail the achievement + void ExtraEffect(SpellEffIndex /*effIndex*/) + { + if (InstanceScript* instance = GetCaster()->GetInstanceScript()) + instance->SetData(DATA_NAUSEA___ACHIEVEMENT, uint32(false)); + } + + void Register() + { + OnEffect += SpellEffectFn(spell_putricide_regurgitated_ooze_SpellScript::ExtraEffect, EFFECT_0, SPELL_EFFECT_APPLY_AURA); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_putricide_regurgitated_ooze_SpellScript(); + } +}; + // Stinky and Precious spell, it's here because its used for both (Festergut and Rotface "pets") class spell_stinky_precious_decimate : public SpellScriptLoader { @@ -269,7 +1293,8 @@ class spell_stinky_precious_decimate : public SpellScriptLoader class spell_stinky_precious_decimate_SpellScript : public SpellScript { - PrepareSpellScript(spell_stinky_precious_decimate_SpellScript) + PrepareSpellScript(spell_stinky_precious_decimate_SpellScript); + void HandleScript(SpellEffIndex /*effIndex*/) { if (GetHitUnit()->GetHealthPct() > float(GetEffectValue())) @@ -295,5 +1320,20 @@ class spell_stinky_precious_decimate : public SpellScriptLoader void AddSC_boss_professor_putricide() { new boss_professor_putricide(); + new npc_volatile_ooze(); + new spell_putricide_gaseous_bloat(); + new spell_putricide_expunged_gas(); + new spell_putricide_slime_puddle(); + new spell_putricide_unstable_experiment(); + new spell_putricide_ooze_summon(); + new spell_putricide_ooze_eruption_searcher(); + new spell_putricide_choking_gas_bomb(); + new spell_putricide_unbound_plague(); + new spell_putricide_eat_ooze(); + new spell_putricide_mutated_plague(); + new spell_putricide_mutation_init(); + new spell_putricide_mutated_transformation_dismiss(); + new spell_putricide_mutated_transformation(); + new spell_putricide_regurgitated_ooze(); new spell_stinky_precious_decimate(); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp index ca7ec22bd8e..d7ef1978da3 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp @@ -186,15 +186,13 @@ class boss_rotface : public CreatureScript switch (eventId) { case EVENT_SLIME_SPRAY: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0/*1*/, 0.0f, true)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true)) { Position pos; target->GetPosition(&pos); - if (DoSummon(NPC_OOZE_SPRAY_STALKER, pos, 8000, TEMPSUMMON_TIMED_DESPAWN)) - { - DoScriptText(EMOTE_SLIME_SPRAY, me); - DoCastAOE(SPELL_SLIME_SPRAY); - } + DoSummon(NPC_OOZE_SPRAY_STALKER, pos, 8000, TEMPSUMMON_TIMED_DESPAWN); + DoScriptText(EMOTE_SLIME_SPRAY, me); + DoCastAOE(SPELL_SLIME_SPRAY); } events.ScheduleEvent(EVENT_SLIME_SPRAY, 20000); break; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h index 9b838b6e5ab..5d3eee1499f 100755 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h @@ -43,43 +43,73 @@ enum eData DATA_BONED_ACHIEVEMENT = 13, DATA_OOZE_DANCE_ACHIEVEMENT = 14, + DATA_PUTRICIDE_TABLE = 15, + DATA_NAUSEA___ACHIEVEMENT = 16, }; #define MAX_ENCOUNTER 12 enum eCreatures { - NPC_LORD_MARROWGAR = 36612, - NPC_COLDFLAME = 36672, - NPC_BONE_SPIKE = 36619, - - NPC_LADY_DEATHWHISPER = 36855, - NPC_CULT_FANATIC = 37890, - NPC_DEFORMED_FANATIC = 38135, - NPC_REANIMATED_FANATIC = 38009, - NPC_CULT_ADHERENT = 37949, - NPC_EMPOWERED_ADHERENT = 38136, - NPC_REANIMATED_ADHERENT = 38010, - NPC_VENGEFUL_SHADE = 38222, - - NPC_DEATHBRINGER_SAURFANG = 37813, - NPC_BLOOD_BEAST = 38508, - NPC_SE_JAINA_PROUDMOORE = 37188, // SE means Saurfang Event - NPC_SE_MURADIN_BRONZEBEARD = 37200, - NPC_SE_KING_VARIAN_WRYNN = 37879, - NPC_SE_HIGH_OVERLORD_SAURFANG = 37187, - NPC_SE_KOR_KRON_REAVER = 37920, - NPC_SE_SKYBREAKER_MARINE = 37830, - - NPC_FESTERGUT = 36626, - NPC_GAS_DUMMY = 36659, - - NPC_ROTFACE = 36627, - NPC_OOZE_SPRAY_STALKER = 37986, - NPC_PUDDLE_STALKER = 37013, - NPC_UNSTABLE_EXPLOSION_STALKER = 38107, - - NPC_PROFESSOR_PUTRICIDE = 36678, + // At Light's Hammer + NPC_KOR_KRON_GENERAL = 37189, + NPC_ALLIANCE_COMMANDER = 37190, + NPC_TORTUNOK = 37992, // Druid Armor H + NPC_ALANA_MOONSTRIKE = 37999, // Druid Armor A + NPC_GERARDO_THE_SUAVE = 37993, // Hunter Armor H + NPC_TALAN_MOONSTRIKE = 37998, // Hunter Armor A + NPC_UVLUS_BANEFIRE = 38284, // Mage Armor H + NPC_MALFUS_GRIMFROST = 38283, // Mage Armor A + NPC_IKFIRUS_THE_VILE = 37991, // Rogue Armor H + NPC_YILI = 37997, // Rogue Armor A + NPC_VOL_GUK = 38841, // Shaman Armor H + NPC_JEDEBIA = 38840, // Shaman Armor A + NPC_HARAGG_THE_UNSEEN = 38181, // Warlock Armor H + NPC_NIBY_THE_ALMIGHTY = 38182, // Warlock Armor N + + // Lord Marrowgar + NPC_LORD_MARROWGAR = 36612, + NPC_COLDFLAME = 36672, + NPC_BONE_SPIKE = 36619, + + // Lady Deathwhisper + NPC_LADY_DEATHWHISPER = 36855, + NPC_CULT_FANATIC = 37890, + NPC_DEFORMED_FANATIC = 38135, + NPC_REANIMATED_FANATIC = 38009, + NPC_CULT_ADHERENT = 37949, + NPC_EMPOWERED_ADHERENT = 38136, + NPC_REANIMATED_ADHERENT = 38010, + NPC_VENGEFUL_SHADE = 38222, + + // Deathbringer Saurfang + NPC_DEATHBRINGER_SAURFANG = 37813, + NPC_BLOOD_BEAST = 38508, + NPC_SE_JAINA_PROUDMOORE = 37188, // SE means Saurfang Event + NPC_SE_MURADIN_BRONZEBEARD = 37200, + NPC_SE_KING_VARIAN_WRYNN = 37879, + NPC_SE_HIGH_OVERLORD_SAURFANG = 37187, + NPC_SE_KOR_KRON_REAVER = 37920, + NPC_SE_SKYBREAKER_MARINE = 37830, + + // Festergut + NPC_FESTERGUT = 36626, + NPC_GAS_DUMMY = 36659, + + // Rotface + NPC_ROTFACE = 36627, + NPC_OOZE_SPRAY_STALKER = 37986, + NPC_PUDDLE_STALKER = 37013, + NPC_UNSTABLE_EXPLOSION_STALKER = 38107, + + // Professor Putricide + NPC_PROFESSOR_PUTRICIDE = 36678, + NPC_ABOMINATION_WING_MAD_SCIENTIST_STALKER = 37824, + NPC_GROWING_OOZE_PUDDLE = 37690, + NPC_GAS_CLOUD = 37562, + NPC_VOLATILE_OOZE = 37697, + NPC_CHOKING_GAS_BOMB = 38159, + NPC_TEAR_GAS_TARGET_STALKER = 38317, }; enum eGameobjects @@ -103,18 +133,23 @@ enum eGameobjects GO_DOODAD_ICECROWN_ORANGETUBES02 = 201617, GO_DOODAD_ICECROWN_GREENTUBES02 = 201618, GO_SCIENTIST_ENTRANCE = 201372, + GO_DRINK_ME = 201584, }; enum eAchievementCriteria { - CRITERIA_BONED_10N = 12775, - CRITERIA_BONED_25N = 12962, - CRITERIA_BONED_10H = 13393, - CRITERIA_BONED_25H = 13394, + CRITERIA_BONED_10N = 12775, + CRITERIA_BONED_25N = 12962, + CRITERIA_BONED_10H = 13393, + CRITERIA_BONED_25H = 13394, CRITERIA_DANCES_WITH_OOZES_10N = 12984, CRITERIA_DANCES_WITH_OOZES_25N = 12966, CRITERIA_DANCES_WITH_OOZES_10H = 12985, CRITERIA_DANCES_WITH_OOZES_25H = 12983, + CRITERIA_NAUSEA_10N = 12987, + CRITERIA_NAUSEA_25N = 12968, + CRITERIA_NAUSEA_10H = 12988, + CRITERIA_NAUSEA_25H = 12981, }; enum ePutricideActions @@ -125,6 +160,7 @@ enum ePutricideActions ACTION_ROTFACE_COMBAT = -366270, ACTION_ROTFACE_OOZE = -366271, ACTION_ROTFACE_DEATH = -366272, + ACTION_CHANGE_PHASE = -366780 }; #endif // DEF_ICECROWN_CITADEL_H diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index 41917b96b9d..673ef17ae59 100755 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -53,8 +53,10 @@ class instance_icecrown_citadel : public InstanceMapScript uiFestergut = 0; uiRotface = 0; uiProfessorPutricide = 0; + uiPutricideTable; isBonedEligible = true; isOozeDanceEligible = true; + isNauseaEligible = true; } void OnCreatureCreate(Creature* creature, bool /*add*/) @@ -70,6 +72,34 @@ class instance_icecrown_citadel : public InstanceMapScript switch (creature->GetEntry()) { + case NPC_KOR_KRON_GENERAL: + if (TeamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_ALLIANCE_COMMANDER, ALLIANCE); + break; + case NPC_TORTUNOK: + if (TeamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_ALANA_MOONSTRIKE, ALLIANCE); + break; + case NPC_GERARDO_THE_SUAVE: + if (TeamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_TALAN_MOONSTRIKE, ALLIANCE); + break; + case NPC_UVLUS_BANEFIRE: + if (TeamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_MALFUS_GRIMFROST, ALLIANCE); + break; + case NPC_IKFIRUS_THE_VILE: + if (TeamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_YILI, ALLIANCE); + break; + case NPC_VOL_GUK: + if (TeamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_JEDEBIA, ALLIANCE); + break; + case NPC_HARAGG_THE_UNSEEN: + if (TeamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_NIBY_THE_ALMIGHTY, ALLIANCE); + break; case NPC_DEATHBRINGER_SAURFANG: uiDeathbringerSaurfang = creature->GetGUID(); break; @@ -160,6 +190,9 @@ class instance_icecrown_citadel : public InstanceMapScript if (GetBossState(DATA_ROTFACE) == DONE) HandleGameObject(uiPutricidePipes[1], true, pGo); break; + case GO_DRINK_ME: + uiPutricideTable = pGo->GetGUID(); + break; default: break; } @@ -183,6 +216,9 @@ class instance_icecrown_citadel : public InstanceMapScript return uiRotface; case DATA_PROFESSOR_PUTRICIDE: return uiProfessorPutricide; + case DATA_PUTRICIDE_TABLE: + return uiPutricideTable; + break; default: break; } @@ -226,11 +262,12 @@ class instance_icecrown_citadel : public InstanceMapScript if (state == DONE) { if (GetBossState(DATA_ROTFACE) == DONE) - HandleGameObject(uiPutricideCollision, true); - if (GetBossState(DATA_ROTFACE) == DONE) { + HandleGameObject(uiPutricideCollision, true); if (GameObject* pGo = instance->GetGameObject(uiPutricideGates[0])) pGo->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + if (GameObject* pGo = instance->GetGameObject(uiPutricideGates[1])) + pGo->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); } else HandleGameObject(uiPutricideGates[0], false); @@ -241,9 +278,10 @@ class instance_icecrown_citadel : public InstanceMapScript if (state == DONE) { if (GetBossState(DATA_FESTERGUT) == DONE) - HandleGameObject(uiPutricideCollision, true); - if (GetBossState(DATA_FESTERGUT) == DONE) { + HandleGameObject(uiPutricideCollision, true); + if (GameObject* pGo = instance->GetGameObject(uiPutricideGates[0])) + pGo->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); if (GameObject* pGo = instance->GetGameObject(uiPutricideGates[1])) pGo->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); } @@ -273,6 +311,10 @@ class instance_icecrown_citadel : public InstanceMapScript break; case DATA_OOZE_DANCE_ACHIEVEMENT: isOozeDanceEligible = data ? true : false; + break; + case DATA_NAUSEA___ACHIEVEMENT: + isNauseaEligible = data ? true : false; + break; default: break; } @@ -292,6 +334,11 @@ class instance_icecrown_citadel : public InstanceMapScript case CRITERIA_DANCES_WITH_OOZES_10H: case CRITERIA_DANCES_WITH_OOZES_25H: return isOozeDanceEligible; + case CRITERIA_NAUSEA_10N: + case CRITERIA_NAUSEA_25N: + case CRITERIA_NAUSEA_10H: + case CRITERIA_NAUSEA_25H: + return isNauseaEligible; default: break; } @@ -353,8 +400,10 @@ class instance_icecrown_citadel : public InstanceMapScript uint64 uiFestergut; uint64 uiRotface; uint64 uiProfessorPutricide; + uint64 uiPutricideTable; bool isBonedEligible; bool isOozeDanceEligible; + bool isNauseaEligible; }; InstanceScript* GetInstanceScript(InstanceMap* pMap) const |