Scripts/Icecrown Citadel: Added Festergut script, thx Cromash for providing the base and Cyrax for sniffs
Scripts/Icecrown Citadel: Added Professor Putricide script handling ONLY Festergut related events --HG-- branch : trunk
This commit is contained in:
@@ -428,6 +428,8 @@ void AddSC_boss_marwyn();
|
||||
void AddSC_boss_lord_marrowgar(); // Icecrown Citadel
|
||||
void AddSC_boss_lady_deathwhisper();
|
||||
void AddSC_boss_deathbringer_saurfang();
|
||||
void AddSC_boss_festergut();
|
||||
void AddSC_boss_professor_putricide();
|
||||
void AddSC_icecrown_citadel_teleport();
|
||||
void AddSC_instance_icecrown_citadel();
|
||||
|
||||
@@ -1105,6 +1107,8 @@ void AddNorthrendScripts()
|
||||
AddSC_boss_lord_marrowgar(); // Icecrown Citadel
|
||||
AddSC_boss_lady_deathwhisper();
|
||||
AddSC_boss_deathbringer_saurfang();
|
||||
AddSC_boss_festergut();
|
||||
AddSC_boss_professor_putricide();
|
||||
AddSC_icecrown_citadel_teleport();
|
||||
AddSC_instance_icecrown_citadel();
|
||||
|
||||
|
||||
@@ -0,0 +1,452 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "ScriptPCH.h"
|
||||
#include "icecrown_citadel.h"
|
||||
|
||||
enum eScriptTexts
|
||||
{
|
||||
SAY_STINKY_DEAD = -1631078,
|
||||
SAY_AGGRO = -1631079,
|
||||
EMOTE_GAS_SPORE = -1631081,
|
||||
EMOTE_WARN_GAS_SPORE = -1631082,
|
||||
SAY_PUNGENT_BLIGHT = -1631083,
|
||||
EMOTE_WARN_PUNGENT_BLIGHT = -1631084,
|
||||
EMOTE_PUNGENT_BLIGHT = -1631085,
|
||||
SAY_KILL_1 = -1631086,
|
||||
SAY_KILL_2 = -1631087,
|
||||
SAY_BERSERK = -1631088,
|
||||
SAY_DEATH = -1631089
|
||||
};
|
||||
|
||||
enum eSpells
|
||||
{
|
||||
// Festergut
|
||||
SPELL_INHALE_BLIGHT = 69165,
|
||||
SPELL_PUNGENT_BLIGHT = 69195,
|
||||
SPELL_GASTRIC_BLOAT = 72219, // 72214 is the proper way (with proc) but atm procs can't have cooldown for creatures
|
||||
SPELL_GASTRIC_EXPLOSION = 72227,
|
||||
SPELL_GAS_SPORE = 69278,
|
||||
SPELL_VILE_GAS = 69240,
|
||||
SPELL_INOCULATED = 69291,
|
||||
|
||||
// Stinky
|
||||
SPELL_MORTAL_WOUND = 71127,
|
||||
SPELL_DECIMATE = 71123,
|
||||
SPELL_PLAGUE_STENCH = 71805
|
||||
};
|
||||
|
||||
// Used for HasAura checks
|
||||
#define PUNGENT_BLIGHT_HELPER RAID_MODE(69195,71219,73031,73032)
|
||||
#define INOCULATED_HELPER RAID_MODE(69291,72101,72102,72103)
|
||||
|
||||
static const uint32 gaseousBlight[3] = {69157, 69162, 69164};
|
||||
static const uint32 gaseousBlightVisual[3] = {69126, 69152, 69154};
|
||||
|
||||
enum eEvents
|
||||
{
|
||||
EVENT_BERSERK = 1,
|
||||
EVENT_INHALE_BLIGHT = 2,
|
||||
EVENT_VILE_GAS = 3,
|
||||
EVENT_GAS_SPORE = 4,
|
||||
EVENT_GASTRIC_BLOAT = 5,
|
||||
|
||||
EVENT_DECIMATE = 6,
|
||||
EVENT_MORTAL_WOUND = 7
|
||||
};
|
||||
|
||||
#define DATA_INOCULATED_STACK 69291
|
||||
|
||||
class boss_festergut : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_festergut() : CreatureScript("boss_festergut") { }
|
||||
|
||||
struct boss_festergutAI : public BossAI
|
||||
{
|
||||
boss_festergutAI(Creature* pCreature) : BossAI(pCreature, DATA_FESTERGUT)
|
||||
{
|
||||
ASSERT(instance);
|
||||
uiMaxInoculatedStack = 0;
|
||||
uiInhaleCounter = 0;
|
||||
gasDummyGUID = 0;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
events.Reset();
|
||||
events.ScheduleEvent(EVENT_BERSERK, 300000);
|
||||
events.ScheduleEvent(EVENT_INHALE_BLIGHT, urand(25000, 30000));
|
||||
events.ScheduleEvent(EVENT_VILE_GAS, urand(30000, 32500));
|
||||
events.ScheduleEvent(EVENT_GAS_SPORE, urand(20000, 25000));
|
||||
events.ScheduleEvent(EVENT_GASTRIC_BLOAT, urand(12500, 15000));
|
||||
uiMaxInoculatedStack = 0;
|
||||
uiInhaleCounter = 0;
|
||||
me->RemoveAurasDueToSpell(SPELL_BERSERK2);
|
||||
if (Creature* gasDummy = GetClosestCreatureWithEntry(me, NPC_GAS_DUMMY, 100.0f, true))
|
||||
{
|
||||
gasDummyGUID = gasDummy->GetGUID();
|
||||
for (uint8 i = 0; i < 3; ++i)
|
||||
{
|
||||
gasDummy->RemoveAurasDueToSpell(gaseousBlight[i]);
|
||||
gasDummy->RemoveAurasDueToSpell(gaseousBlightVisual[i]);
|
||||
}
|
||||
}
|
||||
|
||||
instance->SetBossState(DATA_FESTERGUT, NOT_STARTED);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/)
|
||||
{
|
||||
DoScriptText(SAY_AGGRO, me);
|
||||
if (Creature* gasDummy = GetClosestCreatureWithEntry(me, NPC_GAS_DUMMY, 100.0f, true))
|
||||
gasDummyGUID = gasDummy->GetGUID();
|
||||
instance->SetBossState(DATA_FESTERGUT, IN_PROGRESS);
|
||||
if (Creature* professor = Unit::GetCreature(*me, instance->GetData64(DATA_PROFESSOR_PUTRICIDE)))
|
||||
professor->AI()->DoAction(ACTION_FESTERGUT_COMBAT);
|
||||
|
||||
DoZoneInCombat(me);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/)
|
||||
{
|
||||
DoScriptText(SAY_DEATH, me);
|
||||
instance->SetBossState(DATA_FESTERGUT, DONE);
|
||||
if (Creature* professor = Unit::GetCreature(*me, instance->GetData64(DATA_PROFESSOR_PUTRICIDE)))
|
||||
professor->AI()->DoAction(ACTION_FESTERGUT_DEATH);
|
||||
}
|
||||
|
||||
void JustReachedHome()
|
||||
{
|
||||
instance->SetBossState(DATA_FESTERGUT, FAIL);
|
||||
}
|
||||
|
||||
void EnterEvadeMode()
|
||||
{
|
||||
ScriptedAI::EnterEvadeMode();
|
||||
if (Creature* professor = Unit::GetCreature(*me, instance->GetData64(DATA_PROFESSOR_PUTRICIDE)))
|
||||
professor->AI()->EnterEvadeMode();
|
||||
}
|
||||
|
||||
void KilledUnit(Unit *victim)
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
DoScriptText(RAND(SAY_KILL_1, SAY_KILL_2), me);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/)
|
||||
{
|
||||
// don't enter combat
|
||||
}
|
||||
|
||||
void SpellHitTarget(Unit* target, const SpellEntry* spell)
|
||||
{
|
||||
if (spell->Id == PUNGENT_BLIGHT_HELPER)
|
||||
target->RemoveAurasDueToSpell(INOCULATED_HELPER);
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim() || !CheckInRoom())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->hasUnitState(UNIT_STAT_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_INHALE_BLIGHT:
|
||||
{
|
||||
if (Creature* gasDummy = Unit::GetCreature(*me, gasDummyGUID))
|
||||
for (uint8 i = 0; i < 3; ++i)
|
||||
{
|
||||
gasDummy->RemoveAurasDueToSpell(gaseousBlight[i]);
|
||||
gasDummy->RemoveAurasDueToSpell(gaseousBlightVisual[i]);
|
||||
}
|
||||
if (uiInhaleCounter == 3)
|
||||
{
|
||||
DoScriptText(EMOTE_WARN_PUNGENT_BLIGHT, me);
|
||||
DoScriptText(SAY_PUNGENT_BLIGHT, me);
|
||||
DoCast(me, SPELL_PUNGENT_BLIGHT);
|
||||
uiInhaleCounter = 0;
|
||||
if (Creature* professor = Unit::GetCreature(*me, instance->GetData64(DATA_PROFESSOR_PUTRICIDE)))
|
||||
professor->AI()->DoAction(ACTION_FESTERGUT_GAS);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoCast(me, SPELL_INHALE_BLIGHT);
|
||||
// just cast and dont bother with target, conditions will handle it
|
||||
++uiInhaleCounter;
|
||||
if (uiInhaleCounter < 3)
|
||||
me->CastSpell(me, gaseousBlight[uiInhaleCounter], true, NULL, NULL, me->GetGUID());
|
||||
}
|
||||
events.ScheduleEvent(EVENT_INHALE_BLIGHT, urand(33500, 35000));
|
||||
return;
|
||||
}
|
||||
case EVENT_VILE_GAS:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
|
||||
DoCast(target, SPELL_VILE_GAS);
|
||||
events.ScheduleEvent(EVENT_VILE_GAS, urand(28000, 35000));
|
||||
break;
|
||||
case EVENT_GAS_SPORE:
|
||||
DoScriptText(EMOTE_WARN_GAS_SPORE, me);
|
||||
me->CastCustomSpell(SPELL_GAS_SPORE, SPELLVALUE_MAX_TARGETS, RAID_MODE<int32>(2,3,2,3), me);
|
||||
DoScriptText(EMOTE_GAS_SPORE, me);
|
||||
events.ScheduleEvent(EVENT_GAS_SPORE, urand(40000, 45000));
|
||||
case EVENT_GASTRIC_BLOAT:
|
||||
DoCastVictim(SPELL_GASTRIC_BLOAT);
|
||||
events.ScheduleEvent(EVENT_GASTRIC_BLOAT, urand(15000, 17500));
|
||||
break;
|
||||
case EVENT_BERSERK:
|
||||
DoCast(me, SPELL_BERSERK2);
|
||||
DoScriptText(SAY_BERSERK, me);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data)
|
||||
{
|
||||
if (type == DATA_INOCULATED_STACK && data > uiMaxInoculatedStack)
|
||||
uiMaxInoculatedStack = data;
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 type)
|
||||
{
|
||||
if (type == DATA_INOCULATED_STACK)
|
||||
return uint32(uiMaxInoculatedStack);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 uiMaxInoculatedStack;
|
||||
uint8 uiInhaleCounter;
|
||||
uint64 gasDummyGUID;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* pCreature) const
|
||||
{
|
||||
return new boss_festergutAI(pCreature);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_stinky_icc : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_stinky_icc() : CreatureScript("npc_stinky_icc") { }
|
||||
|
||||
struct npc_stinky_iccAI : public ScriptedAI
|
||||
{
|
||||
npc_stinky_iccAI(Creature* pCreature) : ScriptedAI(pCreature)
|
||||
{
|
||||
pInstance = pCreature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
events.Reset();
|
||||
events.ScheduleEvent(EVENT_DECIMATE, urand(20000, 25000));
|
||||
events.ScheduleEvent(EVENT_MORTAL_WOUND, urand(3000, 7000));
|
||||
DoCast(me, SPELL_PLAGUE_STENCH);
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->hasUnitState(UNIT_STAT_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_DECIMATE:
|
||||
DoCastVictim(SPELL_DECIMATE);
|
||||
events.ScheduleEvent(EVENT_DECIMATE, urand(20000, 25000));
|
||||
break;
|
||||
case EVENT_MORTAL_WOUND:
|
||||
DoCastVictim(SPELL_MORTAL_WOUND);
|
||||
events.ScheduleEvent(EVENT_MORTAL_WOUND, urand(10000, 12500));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void JustDied(Unit* who)
|
||||
{
|
||||
uint64 festergutGUID = pInstance ? pInstance->GetData64(DATA_FESTERGUT) : 0;
|
||||
if (Creature *festergut = me->GetCreature(*me, festergutGUID))
|
||||
DoScriptText(SAY_STINKY_DEAD, festergut);
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap events;
|
||||
InstanceScript* pInstance;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* pCreature) const
|
||||
{
|
||||
return new npc_stinky_iccAI(pCreature);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_festergut_pungent_blight : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_festergut_pungent_blight() : SpellScriptLoader("spell_festergut_pungent_blight") { }
|
||||
|
||||
class spell_festergut_pungent_blight_SpellScript : public SpellScript
|
||||
{
|
||||
void HandleScript(SpellEffIndex effIndex)
|
||||
{
|
||||
SpellEntry const* spellInfo = sSpellStore.LookupEntry(GetEffectValue());
|
||||
if (!spellInfo)
|
||||
return;
|
||||
|
||||
// Get Inhaled Blight id for our difficulty
|
||||
spellInfo = sSpellMgr.GetSpellForDifficultyFromSpell(spellInfo, GetCaster());
|
||||
|
||||
// ...and remove it
|
||||
GetCaster()->RemoveAurasDueToSpell(spellInfo->Id);
|
||||
DoScriptText(EMOTE_PUNGENT_BLIGHT, GetCaster());
|
||||
}
|
||||
|
||||
void Register()
|
||||
{
|
||||
OnEffect += SpellEffectFn(spell_festergut_pungent_blight_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const
|
||||
{
|
||||
return new spell_festergut_pungent_blight_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_festergut_gastric_bloat : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_festergut_gastric_bloat() : SpellScriptLoader("spell_festergut_gastric_bloat") { }
|
||||
|
||||
class spell_festergut_gastric_bloat_SpellScript : public SpellScript
|
||||
{
|
||||
void HandleScript(SpellEffIndex effIndex)
|
||||
{
|
||||
Aura const* aura = GetHitUnit()->GetAura(GetSpellInfo()->Id);
|
||||
if (!(aura && aura->GetStackAmount() == 10))
|
||||
return;
|
||||
|
||||
//PreventHitAura();
|
||||
|
||||
SpellEntry const* spellInfo = sSpellStore.LookupEntry(SPELL_GASTRIC_EXPLOSION);
|
||||
if (!spellInfo)
|
||||
return;
|
||||
|
||||
// Get Gastric Explosion id for our difficulty
|
||||
spellInfo = sSpellMgr.GetSpellForDifficultyFromSpell(spellInfo, GetCaster());
|
||||
GetHitUnit()->RemoveAurasDueToSpell(GetSpellInfo()->Id);
|
||||
GetHitUnit()->CastSpell(GetHitUnit(), spellInfo, true);
|
||||
}
|
||||
|
||||
void Register()
|
||||
{
|
||||
OnEffect += SpellEffectFn(spell_festergut_gastric_bloat_SpellScript::HandleScript, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const
|
||||
{
|
||||
return new spell_festergut_gastric_bloat_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_festergut_blighted_spores : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_festergut_blighted_spores() : SpellScriptLoader("spell_festergut_blighted_spores") { }
|
||||
|
||||
class spell_festergut_blighted_spores_AuraScript : public AuraScript
|
||||
{
|
||||
void ExtraEffect(AuraEffect const* /*aurEff*/, AuraApplication const* aurApp, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (!GetCaster()->IsAIEnabled || GetCaster()->GetTypeId() != TYPEID_UNIT)
|
||||
return;
|
||||
|
||||
uint32 inoculateId = CAST_AI(ScriptedAI, GetCaster()->ToCreature()->AI())->INOCULATED_HELPER;
|
||||
uint32 currStack = 0;
|
||||
if (Aura const* inoculate = aurApp->GetTarget()->GetAura(inoculateId))
|
||||
currStack = inoculate->GetStackAmount();
|
||||
|
||||
aurApp->GetTarget()->CastSpell(aurApp->GetTarget(), SPELL_INOCULATED, true);
|
||||
++currStack;
|
||||
if (GetCaster())
|
||||
GetCaster()->ToCreature()->AI()->SetData(DATA_INOCULATED_STACK, currStack);
|
||||
}
|
||||
|
||||
void Register()
|
||||
{
|
||||
OnEffectApply += AuraEffectApplyFn(spell_festergut_blighted_spores_AuraScript::ExtraEffect, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const
|
||||
{
|
||||
return new spell_festergut_blighted_spores_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
class achievement_flu_shot_shortage : public AchievementCriteriaScript
|
||||
{
|
||||
public:
|
||||
achievement_flu_shot_shortage() : AchievementCriteriaScript("achievement_flu_shot_shortage") { }
|
||||
|
||||
bool OnCheck(Player* /*source*/, Unit* target)
|
||||
{
|
||||
if (target && target->GetTypeId() == TYPEID_UNIT)
|
||||
return target->ToCreature()->AI()->GetData(DATA_INOCULATED_STACK) < 3;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_festergut()
|
||||
{
|
||||
new boss_festergut();
|
||||
new npc_stinky_icc();
|
||||
new spell_festergut_pungent_blight();
|
||||
new spell_festergut_gastric_bloat();
|
||||
new spell_festergut_blighted_spores();
|
||||
new achievement_flu_shot_shortage();
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "ScriptPCH.h"
|
||||
#include "icecrown_citadel.h"
|
||||
|
||||
enum eScriptTexts
|
||||
{
|
||||
// Festergut
|
||||
SAY_FESTERGUT_GASEOUS_BLIGHT = -1631080,
|
||||
SAY_FESTERGUT_DEATH = -1631090,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
enum eEvents
|
||||
{
|
||||
// Festergut
|
||||
EVENT_FESTERGUT_DIES = 1,
|
||||
EVENT_FESTERGUT_GOO = 2,
|
||||
};
|
||||
|
||||
enum ePhases
|
||||
{
|
||||
PHASE_FESTERGUT = 1,
|
||||
PHASE_ROTFACE = 2,
|
||||
PHASE_COMBAT = 3,
|
||||
|
||||
PHASE_MASK_NOT_SELF = (1 << PHASE_FESTERGUT) | (1 << PHASE_ROTFACE)
|
||||
};
|
||||
|
||||
enum ePoints
|
||||
{
|
||||
POINT_FESTERGUT = -366260,
|
||||
};
|
||||
|
||||
static const Position festergutWatchPos = {4324.82f, 3166.03f, 389.3831f, 3.316126f}; //emote 432 (release gas)
|
||||
|
||||
class boss_professor_putricide : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_professor_putricide() : CreatureScript("boss_professor_putricide") { }
|
||||
|
||||
struct boss_professor_putricideAI : public BossAI
|
||||
{
|
||||
boss_professor_putricideAI(Creature* pCreature) : BossAI(pCreature, DATA_PROFESSOR_PUTRICIDE),
|
||||
fBaseSpeed(pCreature->GetSpeedRate(MOVE_RUN))
|
||||
{
|
||||
ASSERT(instance);
|
||||
phase = ePhases(0);
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
events.Reset();
|
||||
summons.DespawnAll();
|
||||
_SetPhase(PHASE_COMBAT);
|
||||
me->SetReactState(REACT_DEFENSIVE);
|
||||
me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE)
|
||||
me->GetMotionMaster()->MovementExpired();
|
||||
}
|
||||
|
||||
void DoAction(const int32 action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case ACTION_FESTERGUT_COMBAT:
|
||||
_SetPhase(PHASE_FESTERGUT);
|
||||
me->SetSpeed(MOVE_RUN, fBaseSpeed*2.0f, true);
|
||||
me->GetMotionMaster()->MovePoint(POINT_FESTERGUT, festergutWatchPos);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
if (IsHeroic())
|
||||
{
|
||||
DoZoneInCombat(me);
|
||||
events.ScheduleEvent(EVENT_FESTERGUT_GOO, urand(15000, 20000), 0, PHASE_FESTERGUT);
|
||||
}
|
||||
break;
|
||||
case ACTION_FESTERGUT_GAS:
|
||||
DoScriptText(SAY_FESTERGUT_GASEOUS_BLIGHT, me);
|
||||
if (Creature* festergut = Unit::GetCreature(*me, instance->GetData64(DATA_FESTERGUT)))
|
||||
festergut->CastSpell(festergut, SPELL_RELEASE_GAS_VISUAL, false, NULL, NULL, me->GetGUID()); // cast from festergut for LoS (with prof's GUID for logs)
|
||||
break;
|
||||
case ACTION_FESTERGUT_DEATH:
|
||||
events.ScheduleEvent(EVENT_FESTERGUT_DIES, 4000, 0, PHASE_FESTERGUT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void JustReachedHome()
|
||||
{
|
||||
if (phase == PHASE_COMBAT)
|
||||
instance->SetBossState(DATA_PROFESSOR_PUTRICIDE, FAIL);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id)
|
||||
{
|
||||
if (type == POINT_MOTION_TYPE && id == 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());
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if ((!UpdateVictim() && !(events.GetPhaseMask() & PHASE_MASK_NOT_SELF)) || !CheckInRoom())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->hasUnitState(UNIT_STAT_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_FESTERGUT_DIES:
|
||||
DoScriptText(SAY_FESTERGUT_DEATH, me);
|
||||
EnterEvadeMode();
|
||||
break;
|
||||
case EVENT_FESTERGUT_GOO:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
|
||||
DoCast(target, SPELL_MALLABLE_GOO_H, true); // triggered, to skip LoS check
|
||||
events.ScheduleEvent(EVENT_FESTERGUT_GOO, urand(15000, 20000), 0, PHASE_FESTERGUT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _SetPhase(ePhases newPhase)
|
||||
{
|
||||
phase = newPhase;
|
||||
events.SetPhase(newPhase);
|
||||
}
|
||||
|
||||
private:
|
||||
ePhases phase; // external of EventMap because event phase gets reset on evade
|
||||
const float fBaseSpeed;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* pCreature) const
|
||||
{
|
||||
return new boss_professor_putricideAI(pCreature);
|
||||
}
|
||||
};
|
||||
|
||||
// Stinky and Precious spell, it's here because its used for both (Festergut and Rotface "pet")
|
||||
class spell_stinky_precious_decimate : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_stinky_precious_decimate() : SpellScriptLoader("spell_stinky_precious_decimate") { }
|
||||
|
||||
class spell_stinky_precious_decimate_SpellScript : public SpellScript
|
||||
{
|
||||
void HandleScript(SpellEffIndex effIndex)
|
||||
{
|
||||
if (GetHitUnit()->GetHealthPct() > float(GetEffectValue()))
|
||||
{
|
||||
uint32 newHealth = GetHitUnit()->GetMaxHealth() * uint32(GetEffectValue()) / 100;
|
||||
if (GetHitUnit()->GetMaxHealth() >= newHealth)
|
||||
GetHitUnit()->SetHealth(newHealth);
|
||||
}
|
||||
}
|
||||
|
||||
void Register()
|
||||
{
|
||||
OnEffect += SpellEffectFn(spell_stinky_precious_decimate_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const
|
||||
{
|
||||
return new spell_stinky_precious_decimate_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_professor_putricide()
|
||||
{
|
||||
new boss_professor_putricide();
|
||||
new spell_stinky_precious_decimate();
|
||||
}
|
||||
@@ -21,7 +21,8 @@
|
||||
|
||||
enum eSharedSpells
|
||||
{
|
||||
SPELL_BERSERK = 26662
|
||||
SPELL_BERSERK = 26662,
|
||||
SPELL_BERSERK2 = 47008
|
||||
};
|
||||
|
||||
enum eData
|
||||
@@ -69,6 +70,13 @@ enum eCreatures
|
||||
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_PROFESSOR_PUTRICIDE = 36678,
|
||||
};
|
||||
|
||||
enum eGameobjects
|
||||
@@ -84,6 +92,14 @@ enum eGameobjects
|
||||
GO_DEATHBRINGER_S_CACHE_10H = 202238,
|
||||
GO_DEATHBRINGER_S_CACHE_25H = 202241,
|
||||
GO_SCOURGE_TRANSPORTER_SAURFANG = 202244,
|
||||
GO_ORANGE_PLAGUE_MONSTER_ENTRANCE = 201371,
|
||||
GO_GREEN_PLAGUE_MONSTER_ENTRANCE = 201370,
|
||||
GO_SCIENTIST_AIRLOCK_DOOR_COLLISION = 201612,
|
||||
GO_SCIENTIST_AIRLOCK_DOOR_ORANGE = 201613,
|
||||
GO_SCIENTIST_AIRLOCK_DOOR_GREEN = 201614,
|
||||
GO_DOODAD_ICECROWN_ORANGETUBES02 = 201617,
|
||||
GO_DOODAD_ICECROWN_GREENTUBES02 = 201618,
|
||||
GO_SCIENTIST_ENTRANCE = 201372,
|
||||
};
|
||||
|
||||
enum eAchievementCriteria
|
||||
@@ -94,4 +110,11 @@ enum eAchievementCriteria
|
||||
CRITERIA_BONED_25H = 13394,
|
||||
};
|
||||
|
||||
enum ePutricideActions
|
||||
{
|
||||
ACTION_FESTERGUT_COMBAT = -366260,
|
||||
ACTION_FESTERGUT_GAS = -366261,
|
||||
ACTION_FESTERGUT_DEATH = -366262,
|
||||
};
|
||||
|
||||
#endif // DEF_ICECROWN_CITADEL_H
|
||||
|
||||
@@ -25,6 +25,9 @@ static const DoorData doorData[8] =
|
||||
{GO_ICEWALL, DATA_LORD_MARROWGAR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
|
||||
{GO_DOODAD_ICECROWN_ICEWALL02, DATA_LORD_MARROWGAR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
|
||||
{GO_ORATORY_OF_THE_DAMNED_ENTRANCE, DATA_LADY_DEATHWHISPER, DOOR_TYPE_ROOM, BOUNDARY_N },
|
||||
{GO_ORANGE_PLAGUE_MONSTER_ENTRANCE, DATA_FESTERGUT, DOOR_TYPE_ROOM, BOUNDARY_E },
|
||||
{GO_GREEN_PLAGUE_MONSTER_ENTRANCE, DATA_ROTFACE, DOOR_TYPE_ROOM, BOUNDARY_E },
|
||||
{GO_SCIENTIST_ENTRANCE, DATA_PROFESSOR_PUTRICIDE, DOOR_TYPE_ROOM, BOUNDARY_E },
|
||||
{0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE} // END
|
||||
};
|
||||
|
||||
@@ -45,6 +48,12 @@ class instance_icecrown_citadel : public InstanceMapScript
|
||||
uiSaurfangEventNPC = 0;
|
||||
uiDeathbringersCache = 0;
|
||||
uiSaurfangTeleport = 0;
|
||||
memset(uiPutricidePipes, 0, 2*sizeof(uint32));
|
||||
memset(uiPutricideGates, 0, 2*sizeof(uint32));
|
||||
uiPutricideCollision;
|
||||
uiFestergut = 0;
|
||||
uiRotface = 0;
|
||||
uiProfessorPutricide = 0;
|
||||
isBonedEligible = false;
|
||||
}
|
||||
|
||||
@@ -75,6 +84,15 @@ class instance_icecrown_citadel : public InstanceMapScript
|
||||
if (TeamInInstance == ALLIANCE)
|
||||
creature->UpdateEntry(NPC_SE_SKYBREAKER_MARINE, ALLIANCE);
|
||||
break;
|
||||
case NPC_FESTERGUT:
|
||||
uiFestergut = creature->GetGUID();
|
||||
break;
|
||||
case NPC_ROTFACE:
|
||||
uiRotface = creature->GetGUID();
|
||||
break;
|
||||
case NPC_PROFESSOR_PUTRICIDE:
|
||||
uiProfessorPutricide = creature->GetGUID();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -88,6 +106,9 @@ class instance_icecrown_citadel : public InstanceMapScript
|
||||
case GO_ICEWALL:
|
||||
case GO_LORD_MARROWGAR_S_ENTRANCE:
|
||||
case GO_ORATORY_OF_THE_DAMNED_ENTRANCE:
|
||||
case GO_ORANGE_PLAGUE_MONSTER_ENTRANCE:
|
||||
case GO_GREEN_PLAGUE_MONSTER_ENTRANCE:
|
||||
case GO_SCIENTIST_ENTRANCE:
|
||||
AddDoor(pGo, add);
|
||||
break;
|
||||
case GO_LADY_DEATHWHISPER_ELEVATOR:
|
||||
@@ -110,6 +131,35 @@ class instance_icecrown_citadel : public InstanceMapScript
|
||||
case GO_SCOURGE_TRANSPORTER_SAURFANG:
|
||||
uiSaurfangTeleport = pGo->GetGUID();
|
||||
break;
|
||||
case GO_SCIENTIST_AIRLOCK_DOOR_COLLISION:
|
||||
uiPutricideCollision = pGo->GetGUID();
|
||||
if (GetBossState(DATA_FESTERGUT) == DONE && GetBossState(DATA_ROTFACE) == DONE)
|
||||
HandleGameObject(uiPutricideCollision, true, pGo);
|
||||
break;
|
||||
case GO_SCIENTIST_AIRLOCK_DOOR_ORANGE:
|
||||
uiPutricideGates[0] = pGo->GetGUID();
|
||||
if (GetBossState(DATA_FESTERGUT) == DONE && GetBossState(DATA_ROTFACE) == DONE)
|
||||
pGo->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
|
||||
else if (GetBossState(DATA_FESTERGUT) == DONE)
|
||||
HandleGameObject(uiPutricideGates[1], false, pGo);
|
||||
break;
|
||||
case GO_SCIENTIST_AIRLOCK_DOOR_GREEN:
|
||||
uiPutricideGates[1] = pGo->GetGUID();
|
||||
if (GetBossState(DATA_ROTFACE) == DONE && GetBossState(DATA_FESTERGUT) == DONE)
|
||||
pGo->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
|
||||
else if (GetBossState(DATA_ROTFACE) == DONE)
|
||||
HandleGameObject(uiPutricideGates[1], false, pGo);
|
||||
break;
|
||||
case GO_DOODAD_ICECROWN_ORANGETUBES02:
|
||||
uiPutricidePipes[0] = pGo->GetGUID();
|
||||
if (GetBossState(DATA_FESTERGUT) == DONE)
|
||||
HandleGameObject(uiPutricidePipes[0], true, pGo);
|
||||
break;
|
||||
case GO_DOODAD_ICECROWN_GREENTUBES02:
|
||||
uiPutricidePipes[1] = pGo->GetGUID();
|
||||
if (GetBossState(DATA_ROTFACE) == DONE)
|
||||
HandleGameObject(uiPutricidePipes[1], true, pGo);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -127,6 +177,10 @@ class instance_icecrown_citadel : public InstanceMapScript
|
||||
return uiSaurfangDoor;
|
||||
case GO_SCOURGE_TRANSPORTER_SAURFANG:
|
||||
return uiSaurfangTeleport;
|
||||
case DATA_FESTERGUT:
|
||||
return uiFestergut;
|
||||
case DATA_PROFESSOR_PUTRICIDE:
|
||||
return uiProfessorPutricide;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -167,7 +221,35 @@ class instance_icecrown_citadel : public InstanceMapScript
|
||||
}
|
||||
break;
|
||||
case DATA_FESTERGUT:
|
||||
if (state == DONE)
|
||||
{
|
||||
if (GetBossState(DATA_ROTFACE) == DONE)
|
||||
HandleGameObject(uiPutricideCollision, true);
|
||||
if (GetBossState(DATA_ROTFACE) == DONE)
|
||||
{
|
||||
if (GameObject* pGo = instance->GetGameObject(uiPutricideGates[0]))
|
||||
pGo->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
|
||||
}
|
||||
else
|
||||
HandleGameObject(uiPutricideGates[0], false);
|
||||
HandleGameObject(uiPutricidePipes[0], true);
|
||||
}
|
||||
break;
|
||||
case DATA_ROTFACE:
|
||||
if (state == DONE)
|
||||
{
|
||||
if (GetBossState(DATA_FESTERGUT) == DONE)
|
||||
HandleGameObject(uiPutricideCollision, true);
|
||||
if (GetBossState(DATA_FESTERGUT) == DONE)
|
||||
{
|
||||
if (GameObject* pGo = instance->GetGameObject(uiPutricideGates[1]))
|
||||
pGo->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
|
||||
}
|
||||
else
|
||||
HandleGameObject(uiPutricideGates[1], false);
|
||||
HandleGameObject(uiPutricidePipes[1], true);
|
||||
}
|
||||
break;
|
||||
case DATA_PROFESSOR_PUTRICIDE:
|
||||
case DATA_BLOOD_PRINCE_COUNCIL:
|
||||
case DATA_BLOOD_QUEEN_LANA_THEL:
|
||||
@@ -256,6 +338,12 @@ class instance_icecrown_citadel : public InstanceMapScript
|
||||
uint64 uiSaurfangEventNPC; // Muradin Bronzebeard or High Overlord Saurfang
|
||||
uint64 uiDeathbringersCache;
|
||||
uint64 uiSaurfangTeleport;
|
||||
uint64 uiPutricidePipes[2];
|
||||
uint64 uiPutricideGates[2];
|
||||
uint64 uiPutricideCollision;
|
||||
uint64 uiFestergut;
|
||||
uint64 uiRotface;
|
||||
uint64 uiProfessorPutricide;
|
||||
bool isBonedEligible;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user