diff options
Diffstat (limited to 'src')
10 files changed, 6734 insertions, 5 deletions
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index 92b5840bdb7..2a4a313a8ab 100644 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -329,6 +329,13 @@ void AddSC_boss_black_knight(); void AddSC_boss_grand_champions(); void AddSC_instance_trial_of_the_champion(); void AddSC_trial_of_the_champion(); +void AddSC_boss_anubarak_trial(); //Trial of the Crusader +void AddSC_boss_faction_champions(); +void AddSC_boss_jaraxxus(); +void AddSC_boss_northrend_beasts(); +void AddSC_boss_twin_valkyr(); +void AddSC_trial_of_the_crusader(); +void AddSC_instance_trial_of_the_crusader(); void AddSC_boss_anubrekhan(); //Naxxramas void AddSC_boss_maexxna(); void AddSC_boss_patchwerk(); @@ -990,6 +997,13 @@ void AddNorthrendScripts() AddSC_boss_grand_champions(); AddSC_instance_trial_of_the_champion(); AddSC_trial_of_the_champion(); + AddSC_boss_anubarak_trial(); //Trial of the Crusader + AddSC_boss_faction_champions(); + AddSC_boss_jaraxxus(); + AddSC_trial_of_the_crusader(); + AddSC_boss_twin_valkyr(); + AddSC_boss_northrend_beasts(); + AddSC_instance_trial_of_the_crusader(); AddSC_boss_krik_thir(); //Azjol-Nerub Azjol-Nerub AddSC_boss_hadronox(); AddSC_boss_anub_arak(); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 97539d262ce..a5819f2925f 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -2342,9 +2342,6 @@ void AuraEffect::TriggerSpell(Unit * target, Unit * caster) const default: break; } - - // Reget trigger spell proto - triggeredSpellInfo = sSpellStore.LookupEntry(triggerSpellId); } else { @@ -2359,8 +2356,21 @@ void AuraEffect::TriggerSpell(Unit * target, Unit * caster) const case RAID_DIFFICULTY_25MAN_NORMAL: triggerSpellId = 67622; break; case RAID_DIFFICULTY_25MAN_HEROIC: triggerSpellId = 67623; break; } - // Reget trigger spell proto - triggeredSpellInfo = sSpellStore.LookupEntry(triggerSpellId); + break; + // Pursuing Spikes (Anub'arak) + case 65920: + case 65922: + case 65923: + if (caster->HasAura(66193)) + { + if (Unit* permafrostCaster = caster->GetAura(66193)->GetCaster()) + if (permafrostCaster->ToCreature()) + permafrostCaster->ToCreature()->ForcedDespawn(3000); + caster->CastSpell(caster,66181,false); + caster->RemoveAllAuras(); + if (caster->ToCreature()) + caster->ToCreature()->DisappearAndDie(); + } break; // Mana Tide case 16191: @@ -2387,6 +2397,9 @@ void AuraEffect::TriggerSpell(Unit * target, Unit * caster) const } } + // Reget trigger spell proto + triggeredSpellInfo = sSpellStore.LookupEntry(triggerSpellId); + if (triggeredSpellInfo) { Unit * triggerCaster = GetTriggeredSpellCaster(triggeredSpellInfo, caster, triggerTarget); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp new file mode 100644 index 00000000000..87467b261ac --- /dev/null +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp @@ -0,0 +1,716 @@ +/* Copyright (C) 2006 - 2010 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> + * 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 + */ + +/* ScriptData +SDName: boss_anubarak_trial +SD%Complete: ??% +SDComment: based on /dev/rsa +SDCategory: +EndScriptData */ + +// Known bugs: +// Anubarak - underground phase partially not worked +// - tele after impale hit a permafrost doesn't work (the entire tele spell should be better) +// Burrow - visual is vanishing +// Burrower - Spider Frenzy not working as it should (frenzy not stacking) +// Scarab - Kill credit isn't crediting? +// FrostSph - often they are casting Permafrost a little above the ground + +#include "ScriptPCH.h" +#include "trial_of_the_crusader.h" + +enum Yells +{ + SAY_INTRO = -1649055, + SAY_AGGRO = -1649056, + SAY_KILL1 = -1649057, + SAY_KILL2 = -1649058, + SAY_DEATH = -1649059, + EMOTE_SPIKE = -1649060, + SAY_BURROWER = -1649061, + EMOTE_LEECHING_SWARM = -1649062, + SAY_LEECHING_SWARM = -1649063, +}; + +enum Summons +{ + NPC_FROST_SPHERE = 34606, + NPC_BURROW = 34862, + NPC_BURROWER = 34607, + NPC_SCARAB = 34605, + NPC_SPIKE = 34660, +}; + +enum BossSpells +{ + SPELL_FREEZE_SLASH = 66012, + SPELL_PENETRATING_COLD = 66013, + SPELL_LEECHING_SWARM = 66118, + SPELL_LEECHING_HEAL = 66125, + SPELL_LEECHING_DAMAGE = 66240, + SPELL_MARK = 67574, + SPELL_SPIKE_CALL = 66169, + SPELL_SUBMERGE_ANUBARAK = 65981, + SPELL_CLEAR_ALL_DEBUFFS = 34098, + SPELL_EMERGE_ANUBARAK = 65982, + SPELL_SUMMON_BEATLES = 66339, + SPELL_SUMMON_BURROWER = 66332, + + // Burrow + SPELL_CHURNING_GROUND = 66969, + + // Scarab + SPELL_DETERMINATION = 66092, + SPELL_ACID_MANDIBLE = 65774, //Passive - Triggered + + // Burrower + SPELL_SPIDER_FRENZY = 66128, + SPELL_EXPOSE_WEAKNESS = 67720, //Passive - Triggered + SPELL_SHADOW_STRIKE = 66134, + SPELL_SUBMERGE_EFFECT = 53421, + SPELL_EMERGE_EFFECT = 66947, + + SUMMON_SCARAB = NPC_SCARAB, + SUMMON_FROSTSPHERE = NPC_FROST_SPHERE, + SPELL_BERSERK = 26662, + + //Frost Sphere + SPELL_FROST_SPHERE = 67539, + SPELL_PERMAFROST = 66193, + SPELL_PERMAFROST_VISUAL = 65882, + + //Spike + SPELL_SUMMON_SPIKE = 66169, + SPELL_SPIKE_SPEED1 = 65920, + SPELL_SPIKE_TRAIL = 65921, + SPELL_SPIKE_SPEED2 = 65922, + SPELL_SPIKE_SPEED3 = 65923, + SPELL_SPIKE_FAIL = 66181, + SPELL_SPIKE_TELE = 66170, +}; + +enum SummonActions +{ + ACTION_SHADOW_STRIKE, + ACTION_SCARAB_SUBMERGE, +}; +
const Position SphereSpawn[6] = +{ + { 786.6439, 108.2498, 155.6701 }, + { 806.8429, 150.5902, 155.6701 }, + { 759.1386, 163.9654, 155.6701 }, + { 744.3701, 119.5211, 155.6701 }, + { 710.0211, 120.8152, 155.6701 }, + { 706.6383, 161.5266, 155.6701 }, +};
class boss_anubarak_trial : public CreatureScript +{ +public: + boss_anubarak_trial() : CreatureScript("boss_anubarak_trial") { } + + CreatureAI* GetAI(Creature* pCreature) const + { + return new boss_anubarak_trialAI(pCreature); + }; + + struct boss_anubarak_trialAI : public ScriptedAI + { + boss_anubarak_trialAI(Creature* pCreature) : ScriptedAI(pCreature), Summons(me) + { + m_pInstance = (InstanceScript*)pCreature->GetInstanceScript(); + } + + InstanceScript* m_pInstance; + + SummonList Summons; + std::list<uint64> m_vBurrowGUID; + uint64 m_aSphereGUID[6]; + + uint32 m_uiFreezeSlashTimer; + uint32 m_uiPenetratingColdTimer; + uint32 m_uiSummonNerubianTimer; + uint32 m_uiNerubianShadowStrikeTimer; + uint32 m_uiSubmergeTimer; + uint32 m_uiPursuingSpikeTimer; + uint32 m_uiSummonScarabTimer; + uint32 m_uiSummonFrostSphereTimer; + uint32 m_uiBerserkTimer; + + uint8 m_uiStage; + bool m_bIntro; + bool m_bReachedPhase3; + uint64 m_uiTargetGUID; + uint8 m_uiScarabSummoned; + + void Reset() + { + m_uiFreezeSlashTimer = 15*IN_MILLISECONDS; + m_uiPenetratingColdTimer = 20*IN_MILLISECONDS; + m_uiNerubianShadowStrikeTimer = 30*IN_MILLISECONDS; + m_uiSummonNerubianTimer = 10*IN_MILLISECONDS; + m_uiSubmergeTimer = 80*IN_MILLISECONDS; + + m_uiPursuingSpikeTimer = 2*IN_MILLISECONDS; + m_uiSummonScarabTimer = 2*IN_MILLISECONDS; + + m_uiSummonFrostSphereTimer = 20*IN_MILLISECONDS; + + m_uiBerserkTimer = 15*MINUTE*IN_MILLISECONDS; + m_uiStage = 0; + m_uiScarabSummoned = 0; + m_bIntro = true; + m_bReachedPhase3 = false; + m_uiTargetGUID = 0; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + Summons.DespawnAll(); + m_vBurrowGUID.clear(); + } + + void KilledUnit(Unit* pWho) + { + if (pWho->GetTypeId() == TYPEID_PLAYER) + { + DoScriptText(urand(0,1) ? SAY_KILL1 : SAY_KILL2,me); + if (m_pInstance) + m_pInstance->SetData(DATA_TRIBUTE_TO_IMMORTALITY_ELEGIBLE, 0); + } + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!m_bIntro) + { + DoScriptText(SAY_INTRO,me); + m_bIntro = false; + } + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_ANUBARAK, FAIL); + //Summon Scarab Swarms neutral at random places + for (int i=0; i < 10; i++) + if (Creature* pTemp = me->SummonCreature(NPC_SCARAB,AnubarakLoc[1].GetPositionX()+urand(0,50)-25,AnubarakLoc[1].GetPositionY()+urand(0,50)-25,AnubarakLoc[1].GetPositionZ())) + pTemp->setFaction(31); + } + + void JustDied(Unit* pKiller) + { + Summons.DespawnAll(); + DoScriptText(SAY_DEATH,me); + if (m_pInstance) + m_pInstance->SetData(TYPE_ANUBARAK, DONE); + } + + void JustSummoned(Creature* pSummoned) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM); + switch(pSummoned->GetEntry()) + { + case NPC_BURROW: + m_vBurrowGUID.push_back(pSummoned->GetGUID()); + pSummoned->SetReactState(REACT_PASSIVE); + pSummoned->CastSpell(pSummoned,SPELL_CHURNING_GROUND,false); + break; + case NPC_SPIKE: + pSummoned->CombatStart(pTarget); + DoScriptText(EMOTE_SPIKE,me,pTarget); + break; + } + Summons.Summon(pSummoned); + } + + void SummonedCreatureDespawn(Creature* pSummoned) + { + switch(pSummoned->GetEntry()) + { + case NPC_SPIKE: + m_uiPursuingSpikeTimer = 2*IN_MILLISECONDS; + break; + } + } + + void EnterCombat(Unit* pWho) + { + DoScriptText(SAY_AGGRO,me); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + me->SetInCombatWithZone(); + if (m_pInstance) + m_pInstance->SetData(TYPE_ANUBARAK, IN_PROGRESS); + //Despawn Scarab Swarms neutral + Summons.DoAction(NPC_SCARAB,ACTION_SCARAB_SUBMERGE); + //Spawn Burrow + for (int i=0; i < 4; i++) + me->SummonCreature(NPC_BURROW,AnubarakLoc[i+2]); + //Spawn Frost Spheres + for (int i=0; i < 6; i++) + if (Unit *pSummoned = me->SummonCreature(NPC_FROST_SPHERE,SphereSpawn[i])) + m_aSphereGUID[i] = pSummoned->GetGUID(); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + switch(m_uiStage) + { + case 0: + if (m_uiFreezeSlashTimer <= uiDiff) + { + DoCastVictim(SPELL_FREEZE_SLASH); + m_uiFreezeSlashTimer = 15*IN_MILLISECONDS; + } else m_uiFreezeSlashTimer -= uiDiff; + + if (m_uiPenetratingColdTimer <= uiDiff) + { + me->CastCustomSpell(SPELL_PENETRATING_COLD, SPELLVALUE_MAX_TARGETS, RAID_MODE(2,5)); + m_uiPenetratingColdTimer = 20*IN_MILLISECONDS; + } else m_uiPenetratingColdTimer -= uiDiff; + + if (m_uiSummonNerubianTimer <= uiDiff && (IsHeroic() || !m_bReachedPhase3)) + { + me->CastCustomSpell(SPELL_SUMMON_BURROWER, SPELLVALUE_MAX_TARGETS, RAID_MODE(1,2,2,4)); + m_uiSummonNerubianTimer = 45*IN_MILLISECONDS; + } else m_uiSummonNerubianTimer -= uiDiff; + + if (IsHeroic() && m_uiNerubianShadowStrikeTimer <= uiDiff) + { + Summons.DoAction(NPC_BURROWER,ACTION_SHADOW_STRIKE); + m_uiNerubianShadowStrikeTimer = 30*IN_MILLISECONDS; + } else m_uiNerubianShadowStrikeTimer -= uiDiff; + + if (m_uiSubmergeTimer <= uiDiff && !m_bReachedPhase3 && !me->HasAura(SPELL_BERSERK)) + { + m_uiStage = 1; + m_uiSubmergeTimer = 60*IN_MILLISECONDS; + } else m_uiSubmergeTimer -= uiDiff; + break; + case 1: + DoCast(me,SPELL_SUBMERGE_ANUBARAK); + DoCast(me,SPELL_CLEAR_ALL_DEBUFFS); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + DoScriptText(SAY_BURROWER,me); + m_uiScarabSummoned = 0; + m_uiSummonScarabTimer = 4*IN_MILLISECONDS; + m_uiStage = 2; + break; + case 2: + if (m_uiPursuingSpikeTimer <= uiDiff) + { + DoCast(SPELL_SPIKE_CALL); + // Just to make sure it won't happen again in this phase + m_uiPursuingSpikeTimer = 90*IN_MILLISECONDS; + } else m_uiPursuingSpikeTimer -= uiDiff; + + if (m_uiSummonScarabTimer <= uiDiff) + { + /* WORKAROUND + * - The correct implementation is more likely the comment below but it needs spell knowledge + */ + std::list<uint64>::iterator i = m_vBurrowGUID.begin(); + uint32 at = urand(0,m_vBurrowGUID.size()-1); + for (uint32 k = 0; k < at; k++) + ++i; + if (Creature *pBurrow = Unit::GetCreature(*me, *i)) + pBurrow->CastSpell(pBurrow,66340,false); + m_uiScarabSummoned++; + m_uiSummonScarabTimer = 4*IN_MILLISECONDS; + if (m_uiScarabSummoned == 4) m_uiSummonScarabTimer = RAID_MODE(4,20)*IN_MILLISECONDS; + + /*It seems that this spell have something more that needs to be taken into account + //Need more sniff info + DoCast(SPELL_SUMMON_BEATLES); + // Just to make sure it won't happen again in this phase + m_uiSummonScarabTimer = 90*IN_MILLISECONDS;*/ + } else m_uiSummonScarabTimer -= uiDiff; + + if (m_uiSubmergeTimer <= uiDiff) + { + m_uiStage = 3; + m_uiSubmergeTimer = 80*IN_MILLISECONDS; + } else m_uiSubmergeTimer -= uiDiff; + break; + case 3: + m_uiStage = 0; + DoCast(SPELL_SPIKE_TELE); + Summons.DespawnEntry(NPC_SPIKE); + me->RemoveAurasDueToSpell(SPELL_SUBMERGE_ANUBARAK); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + DoCast(me,SPELL_EMERGE_ANUBARAK); + me->GetMotionMaster()->MoveChase(me->getVictim()); + m_uiSummonNerubianTimer = 10*IN_MILLISECONDS; + m_uiNerubianShadowStrikeTimer = 30*IN_MILLISECONDS; + m_uiSummonScarabTimer = 2*IN_MILLISECONDS; + break; + } + + if (!IsHeroic()) + { + if (m_uiSummonFrostSphereTimer <= uiDiff) + { + uint8 startAt = urand(0,5); + uint8 i = startAt; + do + { + if (Unit *pSphere = Unit::GetCreature(*me,m_aSphereGUID[i])) + { + if (!pSphere->HasAura(SPELL_FROST_SPHERE)) + { + if (Creature *pSummon = me->SummonCreature(NPC_FROST_SPHERE,SphereSpawn[i])) + m_aSphereGUID[i] = pSummon->GetGUID(); + break; + } + } + i = (i+1)%6; + } while (i != startAt); + m_uiSummonFrostSphereTimer = urand(20,30)*IN_MILLISECONDS; + } else m_uiSummonFrostSphereTimer -= uiDiff; + } + + if (HealthBelowPct(30) && m_uiStage == 0 && !m_bReachedPhase3) + { + m_bReachedPhase3 = true; + DoCastAOE(SPELL_LEECHING_SWARM); + DoScriptText(EMOTE_LEECHING_SWARM,me); + DoScriptText(SAY_LEECHING_SWARM,me); + } + + if (m_uiBerserkTimer <= uiDiff && !me->HasAura(SPELL_BERSERK)) + { + DoCast(me,SPELL_BERSERK); + } else m_uiBerserkTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + }; + +}; + +
class mob_swarm_scarab : public CreatureScript +{ +public: + mob_swarm_scarab() : CreatureScript("mob_swarm_scarab") { } + + CreatureAI* GetAI(Creature* pCreature) const + { + return new mob_swarm_scarabAI(pCreature); + }; + + struct mob_swarm_scarabAI : public ScriptedAI + { + mob_swarm_scarabAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (InstanceScript*)pCreature->GetInstanceScript(); + } + + InstanceScript* m_pInstance; + + uint32 m_uiDeterminationTimer; + + void Reset() + { + me->SetCorpseDelay(0); + m_uiDeterminationTimer = urand(5*IN_MILLISECONDS,60*IN_MILLISECONDS); + DoCast(me,SPELL_ACID_MANDIBLE); + me->SetInCombatWithZone(); + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + me->AddThreat(pTarget,20000.0f); + if (!me->isInCombat()) + me->DisappearAndDie(); + } + + void DoAction(const int32 actionId) + { + switch(actionId) + { + case ACTION_SCARAB_SUBMERGE: + DoCast(SPELL_SUBMERGE_EFFECT); + me->ForcedDespawn(1000); + break; + } + } + + void JustDied(Unit* pKiller) + { + DoCast(pKiller,RAID_MODE(SPELL_TRAITOR_KING_10,SPELL_TRAITOR_KING_25)); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + /* Bosskillers don't recognize */ + if (m_uiDeterminationTimer <= uiDiff) + { + DoCast(me,SPELL_DETERMINATION); + m_uiDeterminationTimer = urand(10*IN_MILLISECONDS,60*IN_MILLISECONDS); + } else m_uiDeterminationTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + }; + +}; + +
class mob_nerubian_burrower : public CreatureScript +{ +public: + mob_nerubian_burrower() : CreatureScript("mob_nerubian_burrower") { } + + CreatureAI* GetAI(Creature* pCreature) const + { + return new mob_nerubian_burrowerAI(pCreature); + }; + + struct mob_nerubian_burrowerAI : public ScriptedAI + { + mob_nerubian_burrowerAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (InstanceScript*)pCreature->GetInstanceScript(); + } + + InstanceScript* m_pInstance; + + uint32 m_uiSpiderFrenzyTimer; + uint32 m_uiSubmergeTimer; + + void Reset() + { + me->SetCorpseDelay(0); + m_uiSpiderFrenzyTimer = urand(10*IN_MILLISECONDS,20*IN_MILLISECONDS); + m_uiSubmergeTimer = 30*IN_MILLISECONDS; + DoCast(me,SPELL_EXPOSE_WEAKNESS); + DoCast(me,SPELL_SPIDER_FRENZY); + me->SetInCombatWithZone(); + if (!me->isInCombat()) + me->DisappearAndDie(); + } + + void DoAction(const int32 actionId) + { + switch(actionId) + { + case ACTION_SHADOW_STRIKE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_SHADOW_STRIKE); + break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if ((m_uiSubmergeTimer <= uiDiff) && HealthBelowPct(80)) + { + if (me->HasAura(SPELL_SUBMERGE_EFFECT)) + { + me->RemoveAurasDueToSpell(SPELL_SUBMERGE_EFFECT); + DoCast(me,SPELL_EMERGE_EFFECT); + me->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->CombatStart(me->SelectNearestTarget()); + } + else + { + if (!me->HasAura(SPELL_PERMAFROST)) + { + DoCast(me,SPELL_SUBMERGE_EFFECT); + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->CombatStop(); + } + } + m_uiSubmergeTimer = 20*IN_MILLISECONDS; + } else m_uiSubmergeTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + }; + +}; + +
class mob_frost_sphere : public CreatureScript +{ +public: + mob_frost_sphere() : CreatureScript("mob_frost_sphere") { } + + CreatureAI* GetAI(Creature* pCreature) const + { + return new mob_frost_sphereAI(pCreature); + }; + + struct mob_frost_sphereAI : public ScriptedAI + { + mob_frost_sphereAI(Creature* pCreature) : ScriptedAI(pCreature) + { + } + + bool m_bFall; + uint32 m_uiPermafrostTimer; + + void Reset() + { + m_bFall = false; + m_uiPermafrostTimer = 0; + me->SetReactState(REACT_PASSIVE); + me->SetFlying(true); + me->SetDisplayId(25144); + me->SetSpeed(MOVE_RUN, 0.5, false); + me->GetMotionMaster()->MoveRandom(20.0f); + DoCast(SPELL_FROST_SPHERE); + } + + void DamageTaken(Unit* pWho, uint32& uiDamage) + { + if (me->GetHealth() < uiDamage) + { + uiDamage = 0; + if (!m_bFall) + { + m_bFall = true; + me->SetFlying(false); + me->GetMotionMaster()->MoveIdle(); + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NOT_SELECTABLE); + //At hit the ground + me->GetMotionMaster()->MoveFall(142.2f, 0); + //me->FallGround(); //need correct vmap use (i believe it isn't working properly right now) + } + } + } + + void MovementInform(uint32 uiType, uint32 uiId) + { + if(uiType != POINT_MOTION_TYPE) return; + + switch (uiId) + { + case 0: + m_uiPermafrostTimer = IN_MILLISECONDS; + break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_uiPermafrostTimer) + { + if (m_uiPermafrostTimer <= uiDiff) + { + m_uiPermafrostTimer = 0; + me->RemoveAurasDueToSpell(SPELL_FROST_SPHERE); + me->SetDisplayId(11686); + me->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.0f); + DoCast(SPELL_PERMAFROST_VISUAL); + DoCast(SPELL_PERMAFROST); + } else m_uiPermafrostTimer -= uiDiff; + } + } + }; + +}; + +
class mob_anubarak_spike : public CreatureScript +{ +public: + mob_anubarak_spike() : CreatureScript("mob_anubarak_spike") { } + + CreatureAI* GetAI(Creature* pCreature) const + { + return new mob_anubarak_spikeAI(pCreature); + }; + + struct mob_anubarak_spikeAI : public ScriptedAI + { + mob_anubarak_spikeAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (InstanceScript*)pCreature->GetInstanceScript(); + } + + InstanceScript* m_pInstance; + uint32 m_uiIncreaseSpeedTimer; + uint8 m_uiSpeed; + uint64 m_uiTargetGUID; + + void Reset() + { + // For an unknown reason this npc isn't recognize the Aura of Permafrost with this flags =/ + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); + m_uiTargetGUID = 0; + } + + void EnterCombat(Unit *pWho) + { + m_uiTargetGUID = pWho->GetGUID(); + DoCast(pWho,SPELL_MARK); + me->SetSpeed(MOVE_RUN, 0.5f); + m_uiSpeed = 0; + m_uiIncreaseSpeedTimer = 1*IN_MILLISECONDS; + me->TauntApply(pWho); + } + + void DamageTaken(Unit* pWho, uint32& uiDamage) + { + uiDamage = 0; + } + + void UpdateAI(const uint32 uiDiff) + { + Unit* pTarget = Unit::GetPlayer(*me, m_uiTargetGUID); + if (!pTarget || !pTarget->isAlive() || !pTarget->HasAura(SPELL_MARK)) + { + if (Creature* pAnubarak = Unit::GetCreature((*me),m_pInstance->GetData64(NPC_ANUBARAK))) + pAnubarak->CastSpell(pAnubarak,SPELL_SPIKE_TELE,false); + me->DisappearAndDie(); + return; + } + + if (m_uiIncreaseSpeedTimer) + if (m_uiIncreaseSpeedTimer <= uiDiff) + { + switch (m_uiSpeed) + { + case 0: + DoCast(me,SPELL_SPIKE_SPEED1); + DoCast(me,SPELL_SPIKE_TRAIL); + m_uiSpeed = 1; + m_uiIncreaseSpeedTimer = 7*IN_MILLISECONDS; + break; + case 1: + DoCast(me,SPELL_SPIKE_SPEED2); + m_uiSpeed = 2; + m_uiIncreaseSpeedTimer = 7*IN_MILLISECONDS; + break; + case 2: + DoCast(me,SPELL_SPIKE_SPEED3); + m_uiIncreaseSpeedTimer = 0; + break; + } + } else m_uiIncreaseSpeedTimer -= uiDiff; + } + }; + +}; + +void AddSC_boss_anubarak_trial() +{ + new boss_anubarak_trial(); + new mob_swarm_scarab(); + new mob_nerubian_burrower(); + new mob_anubarak_spike(); + new mob_frost_sphere(); +} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp new file mode 100644 index 00000000000..007d0e27304 --- /dev/null +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp @@ -0,0 +1,1953 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> + * 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 + */ + +/* ScriptData +SDName: faction_champions +SD%Complete: ??% +SDComment: Scripts by Selector, modified by /dev/rsa +SDCategory: Crusader Coliseum +EndScriptData */ + +// Known bugs: +// All - untested +// Pets aren't being summoned by their masters + +#include "ScriptPCH.h" +#include "trial_of_the_crusader.h" + +enum eYell +{ + SAY_GARROSH_KILL_ALLIANCE_PLAYER4 = -1649118, + SAY_VARIAN_KILL_HORDE_PLAYER4 = -1649123, +}; + +enum eAIs +{ + AI_MELEE = 0, + AI_RANGED = 1, + AI_HEALER = 2, + AI_PET = 3, +}; + +#define SPELL_ANTI_AOE 68595 +#define SPELL_PVP_TRINKET 65547 +
class boss_toc_champion_controller : public CreatureScript +{ +public: + boss_toc_champion_controller() : CreatureScript("boss_toc_champion_controller") { } + + CreatureAI* GetAI(Creature *pCreature) const + { + return new boss_toc_champion_controllerAI (pCreature); + } + + struct boss_toc_champion_controllerAI : public ScriptedAI + { + boss_toc_champion_controllerAI(Creature* pCreature) : ScriptedAI(pCreature), Summons(me) + { + m_pInstance = (InstanceScript *) pCreature->GetInstanceScript(); + } + + InstanceScript* m_pInstance; + SummonList Summons; + uint32 m_uiChampionsNotStarted; + uint32 m_uiChampionsFailed; + uint32 m_uiChampionsKilled; + bool m_bInProgress; + + void Reset() + { + m_uiChampionsNotStarted = 0; + m_uiChampionsFailed = 0; + m_uiChampionsKilled = 0; + m_bInProgress = false; + } + + std::vector<uint32> SelectChampions(Team playerTeam) + { + std::vector<uint32> vHealersEntries; + vHealersEntries.clear(); + vHealersEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_DRUID_RESTORATION : NPC_ALLIANCE_DRUID_RESTORATION); + vHealersEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_PALADIN_HOLY : NPC_ALLIANCE_PALADIN_HOLY); + vHealersEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_PRIEST_DISCIPLINE : NPC_ALLIANCE_PRIEST_DISCIPLINE); + vHealersEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_SHAMAN_RESTORATION : NPC_ALLIANCE_SHAMAN_RESTORATION); + + std::vector<uint32> vOtherEntries; + vOtherEntries.clear(); + vOtherEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_DEATH_KNIGHT : NPC_ALLIANCE_DEATH_KNIGHT); + vOtherEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_HUNTER : NPC_ALLIANCE_HUNTER); + vOtherEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_MAGE : NPC_ALLIANCE_MAGE); + vOtherEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_ROGUE : NPC_ALLIANCE_ROGUE); + vOtherEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_WARLOCK : NPC_ALLIANCE_WARLOCK); + vOtherEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_WARRIOR : NPC_ALLIANCE_WARRIOR); + + uint8 healersSubtracted = 2; + if (m_pInstance->instance->GetSpawnMode() == RAID_DIFFICULTY_25MAN_NORMAL || m_pInstance->instance->GetSpawnMode() == RAID_DIFFICULTY_25MAN_HEROIC) + healersSubtracted = 1; + for (uint8 i = 0; i < healersSubtracted; ++i) + { + uint8 pos = urand(0, vHealersEntries.size()-1); + switch (vHealersEntries[pos]) + { + case NPC_ALLIANCE_DRUID_RESTORATION: vOtherEntries.push_back(NPC_ALLIANCE_DRUID_BALANCE); break; + case NPC_HORDE_DRUID_RESTORATION: vOtherEntries.push_back(NPC_HORDE_DRUID_BALANCE); break; + case NPC_ALLIANCE_PALADIN_HOLY: vOtherEntries.push_back(NPC_ALLIANCE_PALADIN_RETRIBUTION); break; + case NPC_HORDE_PALADIN_HOLY: vOtherEntries.push_back(NPC_HORDE_PALADIN_RETRIBUTION); break; + case NPC_ALLIANCE_PRIEST_DISCIPLINE: vOtherEntries.push_back(NPC_ALLIANCE_PRIEST_SHADOW); break; + case NPC_HORDE_PRIEST_DISCIPLINE: vOtherEntries.push_back(NPC_HORDE_PRIEST_SHADOW); break; + case NPC_ALLIANCE_SHAMAN_RESTORATION: vOtherEntries.push_back(NPC_ALLIANCE_SHAMAN_ENHANCEMENT); break; + case NPC_HORDE_SHAMAN_RESTORATION: vOtherEntries.push_back(NPC_HORDE_SHAMAN_ENHANCEMENT); break; + } + vHealersEntries.erase(vHealersEntries.begin()+pos); + } + + if (m_pInstance->instance->GetSpawnMode() == RAID_DIFFICULTY_10MAN_NORMAL || m_pInstance->instance->GetSpawnMode() == RAID_DIFFICULTY_10MAN_HEROIC) + for (uint8 i = 0; i < 4; ++i) + vOtherEntries.erase(vOtherEntries.begin()+urand(0, vOtherEntries.size()-1)); + + std::vector<uint32> vChampionEntries; + vChampionEntries.clear(); + for (uint8 i = 0; i < vHealersEntries.size(); ++i) + vChampionEntries.push_back(vHealersEntries[i]); + for (uint8 i = 0; i < vOtherEntries.size(); ++i) + vChampionEntries.push_back(vOtherEntries[i]); + + return vChampionEntries; + } + + void SummonChampions(Team playerTeam) + { + std::vector<Position> vChampionJumpOrigin; + if (playerTeam == ALLIANCE) + for (uint8 i = 0; i < 5; i++) + vChampionJumpOrigin.push_back(FactionChampionLoc[i]); + else + for (uint8 i = 5; i < 10; i++) + vChampionJumpOrigin.push_back(FactionChampionLoc[i]); + + std::vector<Position> vChampionJumpTarget; + for (uint8 i = 10; i < 20; i++) + vChampionJumpTarget.push_back(FactionChampionLoc[i]); + std::vector<uint32> vChampionEntries = SelectChampions(playerTeam); + + for (uint8 i = 0; i < vChampionEntries.size(); ++i) + { + uint8 pos = urand(0, vChampionJumpTarget.size()-1); + if (Creature* pTemp = me->SummonCreature(vChampionEntries[i], vChampionJumpOrigin[urand(0,vChampionJumpOrigin.size()-1)], TEMPSUMMON_MANUAL_DESPAWN)) + { + Summons.Summon(pTemp); + pTemp->SetReactState(REACT_PASSIVE); + pTemp->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_OOC_NOT_ATTACKABLE); + if (playerTeam == ALLIANCE) + { + pTemp->SetHomePosition(vChampionJumpTarget[pos].GetPositionX(), vChampionJumpTarget[pos].GetPositionY(), vChampionJumpTarget[pos].GetPositionZ(),0); + pTemp->GetMotionMaster()->MoveJump(vChampionJumpTarget[pos].GetPositionX(), vChampionJumpTarget[pos].GetPositionY(), vChampionJumpTarget[pos].GetPositionZ(), 20.0f, 20.0f); + pTemp->SetOrientation(0); + } + else + { + pTemp->SetHomePosition((ToCCommonLoc[1].GetPositionX()*2)-vChampionJumpTarget[pos].GetPositionX(), vChampionJumpTarget[pos].GetPositionY(), vChampionJumpTarget[pos].GetPositionZ(),3); + pTemp->GetMotionMaster()->MoveJump((ToCCommonLoc[1].GetPositionX()*2)-vChampionJumpTarget[pos].GetPositionX(), vChampionJumpTarget[pos].GetPositionY(), vChampionJumpTarget[pos].GetPositionZ(), 20.0f, 20.0f); + pTemp->SetOrientation(3); + } + } + vChampionJumpTarget.erase(vChampionJumpTarget.begin()+pos); + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + switch(uiType) + { + case 0: + SummonChampions((Team)uiData); + break; + case 1: + for (std::list<uint64>::iterator i = Summons.begin(); i != Summons.end(); ++i) + { + if (Creature* pTemp = Unit::GetCreature(*me, *i)) + { + pTemp->SetReactState(REACT_AGGRESSIVE); + pTemp->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + } + break; + case 2: + switch(uiData) + { + case FAIL: + m_uiChampionsFailed++; + if (m_uiChampionsFailed + m_uiChampionsKilled >= Summons.size()) + { + m_pInstance->SetData(TYPE_CRUSADERS, FAIL); + Summons.DespawnAll(); + me->ForcedDespawn(); + } + break; + case IN_PROGRESS: + if (!m_bInProgress) + { + m_uiChampionsNotStarted = 0; + m_uiChampionsFailed = 0; + m_uiChampionsKilled = 0; + m_bInProgress = true; + Summons.DoZoneInCombat(); + m_pInstance->SetData(TYPE_CRUSADERS, IN_PROGRESS); + } + break; + case DONE: + m_uiChampionsKilled++; + if (m_uiChampionsKilled == 1) + m_pInstance->SetData(TYPE_CRUSADERS, SPECIAL); + else if (m_uiChampionsKilled >= Summons.size()) + { + m_pInstance->SetData(TYPE_CRUSADERS, DONE); + Summons.DespawnAll(); + me->ForcedDespawn(); + } + break; + } + break; + } + } + }; + +}; + + +struct boss_faction_championsAI : public ScriptedAI +{ + boss_faction_championsAI(Creature* pCreature, uint32 aitype) : ScriptedAI(pCreature) + { + m_pInstance = (InstanceScript *) pCreature->GetInstanceScript(); + mAIType = aitype; + } + + InstanceScript* m_pInstance; + + uint64 championControllerGUID; + uint32 mAIType; + uint32 ThreatTimer; + uint32 CCTimer; + + void Reset() + { + championControllerGUID = 0; + CCTimer = rand()%10000; + ThreatTimer = 5000; + } + + void JustReachedHome() + { + if(m_pInstance) + if (Creature* pChampionController = Unit::GetCreature((*me),m_pInstance->GetData64(NPC_CHAMPIONS_CONTROLLER))) + pChampionController->AI()->SetData(2, FAIL); + me->ForcedDespawn(); + } + + float CalculateThreat(float distance, float armor, uint32 health) + { + float dist_mod = (mAIType == AI_MELEE || mAIType == AI_PET) ? 15.0f/(15.0f + distance) : 1.0f; + float armor_mod = (mAIType == AI_MELEE || mAIType == AI_PET) ? armor / 16635.0f : 0.0f; + float eh = (health+1) * (1.0f + armor_mod); + return dist_mod * 30000.0f / eh; + } + + void UpdateThreat() + { + std::list<HostileReference*> const& tList = me->getThreatManager().getThreatList(); + std::list<HostileReference*>::const_iterator itr; + bool empty = true; + for(itr = tList.begin(); itr!=tList.end(); ++itr) + { + Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); + if (pUnit && me->getThreatManager().getThreat(pUnit)) + { + if(pUnit->GetTypeId()==TYPEID_PLAYER) + { + float threat = CalculateThreat(me->GetDistance2d(pUnit), (float)pUnit->GetArmor(), pUnit->GetHealth()); + me->getThreatManager().modifyThreatPercent(pUnit, -100); + me->AddThreat(pUnit, 1000000.0f * threat); + empty = false; + } + } + } + } + + void UpdatePower() + { + if(me->getPowerType() == POWER_MANA) + me->ModifyPower(POWER_MANA, me->GetMaxPower(POWER_MANA) / 3); + //else if(me->getPowerType() == POWER_ENERGY) + // me->ModifyPower(POWER_ENERGY, 100); + } + + void RemoveCC() + { + me->RemoveAurasByType(SPELL_AURA_MOD_STUN); + me->RemoveAurasByType(SPELL_AURA_MOD_FEAR); + me->RemoveAurasByType(SPELL_AURA_MOD_ROOT); + me->RemoveAurasByType(SPELL_AURA_MOD_PACIFY); + me->RemoveAurasByType(SPELL_AURA_MOD_CONFUSE); + //DoCast(me, SPELL_PVP_TRINKET); + } + + void JustDied(Unit *killer) + { + if(mAIType != AI_PET) + if(m_pInstance) + if (Creature* pChampionController = Unit::GetCreature((*me),m_pInstance->GetData64(NPC_CHAMPIONS_CONTROLLER))) + pChampionController->AI()->SetData(2, DONE); + } + + void EnterCombat(Unit *who) + { + DoCast(me, SPELL_ANTI_AOE, true); + me->SetInCombatWithZone(); + if(m_pInstance) + if (Creature* pChampionController = Unit::GetCreature((*me),m_pInstance->GetData64(NPC_CHAMPIONS_CONTROLLER))) + pChampionController->AI()->SetData(2, IN_PROGRESS); + } + + void KilledUnit(Unit* who) + { + if (who->GetTypeId() == TYPEID_PLAYER) + { + Map::PlayerList const &players = me->GetMap()->GetPlayers(); + uint32 TeamInInstance = 0; + + if (!players.isEmpty()) + if (Player* pPlayer = players.begin()->getSource()) + TeamInInstance = pPlayer->GetTeam(); + + if (m_pInstance) + { + if (TeamInInstance == ALLIANCE) + if (Creature* pTemp = Unit::GetCreature(*me,m_pInstance->GetData64(NPC_VARIAN))) + DoScriptText(SAY_VARIAN_KILL_HORDE_PLAYER4+urand(0,3), pTemp); // + cause we are on negative + else + if (Creature* pTemp = me->FindNearestCreature(NPC_GARROSH, 300.f)) + DoScriptText(SAY_GARROSH_KILL_ALLIANCE_PLAYER4+urand(0,3), pTemp); // + cause we are on negative + + m_pInstance->SetData(DATA_TRIBUTE_TO_IMMORTALITY_ELEGIBLE, 0); + } + } + } + + Creature* SelectRandomFriendlyMissingBuff(uint32 spell) + { + std::list<Creature *> lst = DoFindFriendlyMissingBuff(40.0f, spell); + std::list<Creature *>::const_iterator itr = lst.begin(); + if(lst.empty()) + return NULL; + advance(itr, rand()%lst.size()); + return (*itr); + } + + Unit* SelectEnemyCaster(bool casting) + { + std::list<HostileReference*> const& tList = me->getThreatManager().getThreatList(); + std::list<HostileReference*>::const_iterator iter; + for(iter = tList.begin(); iter!=tList.end(); ++iter) + { + Unit *target; + if(target = Unit::GetUnit((*me),(*iter)->getUnitGuid())) + if(target->getPowerType() == POWER_MANA) + return target; + } + return NULL; + } + + uint32 EnemiesInRange(float distance) + { + std::list<HostileReference*> const& tList = me->getThreatManager().getThreatList(); + std::list<HostileReference*>::const_iterator iter; + uint32 count = 0; + for(iter = tList.begin(); iter!=tList.end(); ++iter) + { + Unit *target; + if(target = Unit::GetUnit((*me),(*iter)->getUnitGuid())) + if(me->GetDistance2d(target) < distance) + ++count; + } + return count; + } + + void AttackStart(Unit* pWho) + { + if (!pWho) return; + + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 10.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + + if(mAIType == AI_MELEE || mAIType == AI_PET) + DoStartMovement(pWho); + else + DoStartMovement(pWho, 20.0f); + SetCombatMovement(true); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if(ThreatTimer < uiDiff) + { + UpdatePower(); + UpdateThreat(); + ThreatTimer = 4000; + } + else ThreatTimer -= uiDiff; + + if(mAIType != AI_PET) + if(CCTimer < uiDiff) + { + RemoveCC(); + CCTimer = 8000+rand()%2000; + } + else CCTimer -= uiDiff; + + if(mAIType == AI_MELEE || mAIType == AI_PET) DoMeleeAttackIfReady(); + } +}; + +/******************************************************************** + HEALERS +********************************************************************/ + +#define SPELL_LIFEBLOOM 66093 +#define SPELL_NOURISH 66066 +#define SPELL_REGROWTH 66067 +#define SPELL_REJUVENATION 66065 +#define SPELL_TRANQUILITY 66086 +#define SPELL_BARKSKIN 65860 //1 min cd +#define SPELL_THORNS 66068 +#define SPELL_NATURE_GRASP 66071 //1 min cd, self buff +
class mob_toc_druid : public CreatureScript +{ +public: + mob_toc_druid() : CreatureScript("mob_toc_druid") { } + + CreatureAI* GetAI(Creature *pCreature) const + { + return new mob_toc_druidAI (pCreature); + } + + struct mob_toc_druidAI : public boss_faction_championsAI + { + mob_toc_druidAI(Creature* pCreature) : boss_faction_championsAI(pCreature, AI_HEALER) {} + + uint32 m_uiNatureGraspTimer; + uint32 m_uiTranquilityTimer; + uint32 m_uiBarkskinTimer; + uint32 m_uiCommonTimer; + + void Reset() + { + boss_faction_championsAI::Reset(); + m_uiNatureGraspTimer = IN_MILLISECONDS; + m_uiTranquilityTimer = IN_MILLISECONDS; + m_uiBarkskinTimer = IN_MILLISECONDS; + m_uiCommonTimer = IN_MILLISECONDS; + SetEquipmentSlots(false, 51799, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) return; + + if (m_uiNatureGraspTimer <= uiDiff) + { + DoCast(me,SPELL_NATURE_GRASP); + m_uiNatureGraspTimer = urand(40*IN_MILLISECONDS,80*IN_MILLISECONDS); + } else m_uiNatureGraspTimer -= uiDiff; + + if (m_uiTranquilityTimer <= uiDiff) + { + DoCastAOE(SPELL_TRANQUILITY); + m_uiTranquilityTimer = urand(40*IN_MILLISECONDS,90*IN_MILLISECONDS); + } else m_uiTranquilityTimer -= uiDiff; + + if (m_uiBarkskinTimer <= uiDiff) + { + if (HealthBelowPct(50)) + DoCast(me,SPELL_BARKSKIN); + m_uiBarkskinTimer = urand(45*IN_MILLISECONDS,90*IN_MILLISECONDS); + } else m_uiBarkskinTimer -= uiDiff; + + if (m_uiCommonTimer <= uiDiff) + { + switch(urand(0,4)) + { + case 0: + DoCast(me,SPELL_LIFEBLOOM); + break; + case 1: + DoCast(me,SPELL_NOURISH); + break; + case 2: + DoCast(me,SPELL_REGROWTH); + break; + case 3: + DoCast(me,SPELL_REJUVENATION); + break; + case 4: + if(Creature* pTarget = SelectRandomFriendlyMissingBuff(SPELL_THORNS)) + DoCast(pTarget,SPELL_THORNS); + break; + } + m_uiCommonTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiCommonTimer -= uiDiff; + + boss_faction_championsAI::UpdateAI(uiDiff); + } + }; + +}; + +#define SPELL_HEALING_WAVE 66055 +#define SPELL_RIPTIDE 66053 +#define SPELL_SPIRIT_CLEANSE 66056 //friendly only +#define SPELL_HEROISM 65983 +#define SPELL_BLOODLUST 65980 +#define SPELL_HEX 66054 +#define SPELL_EARTH_SHIELD 66063 +#define SPELL_EARTH_SHOCK 65973 +#define AURA_EXHAUSTION 57723 +#define AURA_SATED 57724 +
class mob_toc_shaman : public CreatureScript +{ +public: + mob_toc_shaman() : CreatureScript("mob_toc_shaman") { } + + CreatureAI* GetAI(Creature *pCreature) const + { + return new mob_toc_shamanAI (pCreature); + } + + struct mob_toc_shamanAI : public boss_faction_championsAI + { + mob_toc_shamanAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_HEALER) {} + + uint32 m_uiHeroismOrBloodlustTimer; + uint32 m_uiHexTimer; + uint32 m_uiCommonTimer; + + void Reset() + { + boss_faction_championsAI::Reset(); + m_uiHeroismOrBloodlustTimer = IN_MILLISECONDS; + m_uiHexTimer = IN_MILLISECONDS; + m_uiCommonTimer = IN_MILLISECONDS; + SetEquipmentSlots(false, 49992, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) return; + + if (m_uiHeroismOrBloodlustTimer <= uiDiff) + { + if (me->getFaction()) //Am i alliance? + if (!me->HasAura(AURA_EXHAUSTION)) + DoCastAOE(SPELL_HEROISM); + else + if (!me->HasAura(AURA_SATED)) + DoCastAOE(SPELL_BLOODLUST); + m_uiHeroismOrBloodlustTimer = urand(30*IN_MILLISECONDS,60*IN_MILLISECONDS); + } else m_uiHeroismOrBloodlustTimer -= uiDiff; + + if (m_uiHexTimer <= uiDiff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_HEX); + m_uiHexTimer = urand(10*IN_MILLISECONDS,40*IN_MILLISECONDS); + } else m_uiHexTimer -= uiDiff; + + if (m_uiCommonTimer <= uiDiff) + { + switch(urand(0,5)) + { + case 0: case 1: + DoCast(me,SPELL_HEALING_WAVE); + break; + case 2: + DoCast(me,SPELL_RIPTIDE); + break; + case 3: + DoCast(me,SPELL_EARTH_SHOCK); + break; + case 4: + DoCast(me,SPELL_SPIRIT_CLEANSE); + break; + case 5: + if(Unit *pTarget = SelectRandomFriendlyMissingBuff(SPELL_EARTH_SHIELD)) + DoCast(pTarget,SPELL_EARTH_SHIELD); + break; + } + m_uiCommonTimer = urand(5*IN_MILLISECONDS,15*IN_MILLISECONDS); + } else m_uiCommonTimer -= uiDiff; + + boss_faction_championsAI::UpdateAI(uiDiff); + } + }; + +}; + +#define SPELL_HAND_OF_FREEDOM 68757 //25 sec cd +#define SPELL_BUBBLE 66010 //5 min cd +#define SPELL_CLEANSE 66116 +#define SPELL_FLASH_OF_LIGHT 66113 +#define SPELL_HOLY_LIGHT 66112 +#define SPELL_HOLY_SHOCK 66114 +#define SPELL_HAND_OF_PROTECTION 66009 +#define SPELL_HAMMER_OF_JUSTICE 66613 +
class mob_toc_paladin : public CreatureScript +{ +public: + mob_toc_paladin() : CreatureScript("mob_toc_paladin") { } + + CreatureAI* GetAI(Creature *pCreature) const + { + return new mob_toc_paladinAI (pCreature); + } + + struct mob_toc_paladinAI : public boss_faction_championsAI + { + mob_toc_paladinAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_HEALER) {} + + uint32 m_uiBubbleTimer; + uint32 m_uiHandOfProtectionTimer; + uint32 m_uiHolyShockTimer; + uint32 m_uiHandOfFreedomTimer; + uint32 m_uiHammerOfJusticeTimer; + uint32 m_uiCommonTimer; + + void Reset() + { + boss_faction_championsAI::Reset(); + m_uiBubbleTimer = urand(0*IN_MILLISECONDS,360*IN_MILLISECONDS); + m_uiHandOfProtectionTimer = urand(0*IN_MILLISECONDS,360*IN_MILLISECONDS); + m_uiHolyShockTimer = urand(6*IN_MILLISECONDS,15*IN_MILLISECONDS); + m_uiHandOfFreedomTimer = urand(25*IN_MILLISECONDS,40*IN_MILLISECONDS); + m_uiHammerOfJusticeTimer = urand(5*IN_MILLISECONDS,15*IN_MILLISECONDS); + m_uiCommonTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + SetEquipmentSlots(false, 50771, 47079, EQUIP_NO_CHANGE); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) return; + + if (m_uiBubbleTimer <= uiDiff) + { + //cast bubble at 20% hp + if(HealthBelowPct(20)) + DoCast(me,SPELL_BUBBLE); + m_uiBubbleTimer = urand(0*IN_MILLISECONDS,360*IN_MILLISECONDS); + } else m_uiBubbleTimer -= uiDiff; + + if (m_uiHandOfProtectionTimer <= uiDiff) + { + if(Unit *pTarget = DoSelectLowestHpFriendly(40.0f)) + if(pTarget->GetHealth() * 100 < pTarget->GetMaxHealth() * 15) // HealthBelowPct(15) + DoCast(pTarget,SPELL_HAND_OF_PROTECTION); + m_uiHandOfProtectionTimer = urand(0*IN_MILLISECONDS,360*IN_MILLISECONDS); + } else m_uiHandOfProtectionTimer -= uiDiff; + + if (m_uiHolyShockTimer <= uiDiff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_HOLY_SHOCK); + m_uiHolyShockTimer = urand(6*IN_MILLISECONDS,15*IN_MILLISECONDS); + } else m_uiHolyShockTimer -= uiDiff; + + if (m_uiHandOfFreedomTimer <= uiDiff) + { + if(Unit *pTarget = SelectRandomFriendlyMissingBuff(SPELL_HAND_OF_FREEDOM)) + DoCast(pTarget,SPELL_HAND_OF_FREEDOM); + m_uiHandOfFreedomTimer = urand(25*IN_MILLISECONDS,40*IN_MILLISECONDS); + } else m_uiHandOfFreedomTimer -= uiDiff; + + if (m_uiHammerOfJusticeTimer <= uiDiff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_HAMMER_OF_JUSTICE); + m_uiHammerOfJusticeTimer = urand(5*IN_MILLISECONDS,15*IN_MILLISECONDS); + } else m_uiHammerOfJusticeTimer -= uiDiff; + + if (m_uiCommonTimer <= uiDiff) + { + switch(urand(0,4)) + { + case 0: case 1: + DoCast(me,SPELL_FLASH_OF_LIGHT); + break; + case 2: case 3: + DoCast(me,SPELL_HOLY_LIGHT); + break; + case 4: + DoCast(me,SPELL_CLEANSE); + break; + } + m_uiCommonTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiCommonTimer -= uiDiff; + + boss_faction_championsAI::UpdateAI(uiDiff); + } + }; + +}; + +#define SPELL_RENEW 66177 +#define SPELL_SHIELD 66099 +#define SPELL_FLASH_HEAL 66104 +#define SPELL_DISPEL 65546 +#define SPELL_PSYCHIC_SCREAM 65543 +#define SPELL_MANA_BURN 66100 +
class mob_toc_priest : public CreatureScript +{ +public: + mob_toc_priest() : CreatureScript("mob_toc_priest") { } + + CreatureAI* GetAI(Creature *pCreature) const + { + return new mob_toc_priestAI (pCreature); + } + + struct mob_toc_priestAI : public boss_faction_championsAI + { + mob_toc_priestAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_HEALER) {} + + uint32 m_uiPsychicScreamTimer; + uint32 m_uiCommonTimer; + + void Reset() + { + boss_faction_championsAI::Reset(); + m_uiPsychicScreamTimer = IN_MILLISECONDS; + m_uiCommonTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + SetEquipmentSlots(false, 49992, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) return; + + if (m_uiPsychicScreamTimer <= uiDiff) + { + if(EnemiesInRange(10.0f) > 2) + DoCastAOE(SPELL_PSYCHIC_SCREAM); + m_uiPsychicScreamTimer = urand(5*IN_MILLISECONDS,25*IN_MILLISECONDS); + } else m_uiPsychicScreamTimer -= uiDiff; + + if (m_uiCommonTimer <= uiDiff) + { + switch(urand(0,5)) + { + case 0: + DoCast(me,SPELL_RENEW); + break; + case 1: + DoCast(me,SPELL_SHIELD); + break; + case 2: case 3: + DoCast(me,SPELL_FLASH_HEAL); + break; + case 4: + if(Unit *pTarget = urand(0,1) ? SelectUnit(SELECT_TARGET_RANDOM,0) : DoSelectLowestHpFriendly(40.0f)) + DoCast(pTarget, SPELL_DISPEL); + break; + case 5: + DoCast(me,SPELL_MANA_BURN); + break; + } + m_uiCommonTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiCommonTimer -= uiDiff; + + boss_faction_championsAI::UpdateAI(uiDiff); + } + }; + +}; + +/******************************************************************** + RANGED +********************************************************************/ + +#define SPELL_SILENCE 65542 +#define SPELL_VAMPIRIC_TOUCH 65490 +#define SPELL_SW_PAIN 65541 +#define SPELL_MIND_FLAY 65488 +#define SPELL_MIND_BLAST 65492 +#define SPELL_HORROR 65545 +#define SPELL_DISPERSION 65544 +#define SPELL_SHADOWFORM 16592 +
class mob_toc_shadow_priest : public CreatureScript +{ +public: + mob_toc_shadow_priest() : CreatureScript("mob_toc_shadow_priest") { } + + CreatureAI* GetAI(Creature *pCreature) const + { + return new mob_toc_shadow_priestAI (pCreature); + } + + struct mob_toc_shadow_priestAI : public boss_faction_championsAI + { + mob_toc_shadow_priestAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_RANGED) {} + + uint32 m_uiPsychicScreamTimer; + uint32 m_uiDispersionTimer; + uint32 m_uiSilenceTimer; + uint32 m_uiMindBlastTimer; + uint32 m_uiCommonTimer; + + void Reset() + { + boss_faction_championsAI::Reset(); + m_uiPsychicScreamTimer = urand(5*IN_MILLISECONDS,25*IN_MILLISECONDS); + m_uiDispersionTimer = urand(1*IN_MILLISECONDS,180*IN_MILLISECONDS); + m_uiSilenceTimer = urand(8*IN_MILLISECONDS,15*IN_MILLISECONDS); + m_uiMindBlastTimer = urand(3*IN_MILLISECONDS,8*IN_MILLISECONDS); + m_uiCommonTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + SetEquipmentSlots(false, 50040, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + DoCast(me,SPELL_SHADOWFORM); + } + + void EnterCombat(Unit *pWho) + { + boss_faction_championsAI::EnterCombat(pWho); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) return; + + if (m_uiPsychicScreamTimer <= uiDiff) + { + if(EnemiesInRange(10.0f) > 2) + DoCastAOE(SPELL_PSYCHIC_SCREAM); + m_uiPsychicScreamTimer = urand(5*IN_MILLISECONDS,25*IN_MILLISECONDS); + } else m_uiPsychicScreamTimer -= uiDiff; + + if (m_uiDispersionTimer <= uiDiff) + { + if(HealthBelowPct(20)) + DoCast(me,SPELL_DISPERSION); + m_uiDispersionTimer = urand(1*IN_MILLISECONDS,180*IN_MILLISECONDS); + } else m_uiDispersionTimer -= uiDiff; + + if (m_uiSilenceTimer <= uiDiff) + { + if(Unit *pTarget = SelectEnemyCaster(false)) + DoCast(pTarget,SPELL_SILENCE); + m_uiSilenceTimer = urand(8*IN_MILLISECONDS,15*IN_MILLISECONDS); + } else m_uiSilenceTimer -= uiDiff; + + if (m_uiMindBlastTimer <= uiDiff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_MIND_BLAST); + m_uiMindBlastTimer = urand(3*IN_MILLISECONDS,8*IN_MILLISECONDS); + } else m_uiMindBlastTimer -= uiDiff; + + if (m_uiCommonTimer <= uiDiff) + { + switch(urand(0,4)) + { + case 0: case 1: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_MIND_FLAY); + break; + case 2: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_VAMPIRIC_TOUCH); + break; + case 3: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_SW_PAIN); + break; + case 4: + if(Unit *pTarget = urand(0,1) ? SelectUnit(SELECT_TARGET_RANDOM,0) : DoSelectLowestHpFriendly(40.0f)) + DoCast(pTarget, SPELL_DISPEL); + break; + } + m_uiCommonTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiCommonTimer -= uiDiff; + + boss_faction_championsAI::UpdateAI(uiDiff); + } + }; + +}; + +#define SPELL_HELLFIRE 65816 +#define SPELL_CORRUPTION 65810 +#define SPELL_CURSE_OF_AGONY 65814 +#define SPELL_CURSE_OF_EXHAUSTION 65815 +#define SPELL_FEAR 65809 //8s +#define SPELL_SEARING_PAIN 65819 +#define SPELL_SHADOW_BOLT 65821 +#define SPELL_UNSTABLE_AFFLICTION 65812 +#define SPELL_SUMMON_FELHUNTER 67514 +#define H_SPELL_UNSTABLE_AFFLICTION 68155 //15s +
class mob_toc_warlock : public CreatureScript +{ +public: + mob_toc_warlock() : CreatureScript("mob_toc_warlock") { } + + CreatureAI* GetAI(Creature *pCreature) const + { + return new mob_toc_warlockAI (pCreature); + } + + struct mob_toc_warlockAI : public boss_faction_championsAI + { + mob_toc_warlockAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_RANGED), Summons(me) {} + + SummonList Summons; + + uint32 m_uiFearTimer; + uint32 m_uiHellfireTimer; + uint32 m_uiUnstableAfflictionTimer; + uint32 m_uiCommonTimer; + uint32 m_uiSummonPetTimer; + + void Reset() + { + boss_faction_championsAI::Reset(); + m_uiFearTimer = urand(4*IN_MILLISECONDS,15*IN_MILLISECONDS); + m_uiHellfireTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + m_uiUnstableAfflictionTimer = urand(2*IN_MILLISECONDS,10*IN_MILLISECONDS); + m_uiCommonTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + SetEquipmentSlots(false, 49992, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + + m_uiSummonPetTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + DoCast(SPELL_SUMMON_FELHUNTER); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) return; + + if (m_uiFearTimer <= uiDiff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_FEAR); + m_uiFearTimer = urand(4*IN_MILLISECONDS,15*IN_MILLISECONDS); + } else m_uiFearTimer -= uiDiff; + + if (m_uiHellfireTimer <= uiDiff) + { + if (EnemiesInRange(10.0f) > 2) + DoCastAOE(SPELL_HELLFIRE); + m_uiHellfireTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiHellfireTimer -= uiDiff; + + if (m_uiUnstableAfflictionTimer <= uiDiff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_UNSTABLE_AFFLICTION); + m_uiUnstableAfflictionTimer = urand(2*IN_MILLISECONDS,10*IN_MILLISECONDS); + } else m_uiUnstableAfflictionTimer -= uiDiff; + + if (m_uiSummonPetTimer <= uiDiff) + { + m_uiSummonPetTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiSummonPetTimer -= uiDiff; + + if (m_uiCommonTimer <= uiDiff) + { + switch(urand(0,5)) + { + case 0: case 1: + DoCastVictim(SPELL_SHADOW_BOLT); + break; + case 2: + DoCastVictim(SPELL_SEARING_PAIN); + break; + case 3: + DoCastVictim(SPELL_CORRUPTION); + break; + case 4: + DoCastVictim(SPELL_CURSE_OF_AGONY); + break; + case 5: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_CURSE_OF_EXHAUSTION); + break; + } + m_uiCommonTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiCommonTimer -= uiDiff; + boss_faction_championsAI::UpdateAI(uiDiff); + } + }; + +}; + +#define SPELL_ARCANE_BARRAGE 65799 //3s +#define SPELL_ARCANE_BLAST 65791 +#define SPELL_ARCANE_EXPLOSION 65800 +#define SPELL_BLINK 65793 //15s +#define SPELL_COUNTERSPELL 65790 //24s +#define SPELL_FROST_NOVA 65792 //25s +#define SPELL_FROSTBOLT 65807 +#define SPELL_ICE_BLOCK 65802 //5min +#define SPELL_POLYMORPH 65801 //15s +
class mob_toc_mage : public CreatureScript +{ +public: + mob_toc_mage() : CreatureScript("mob_toc_mage") { } + + CreatureAI* GetAI(Creature *pCreature) const + { + return new mob_toc_mageAI (pCreature); + } + + struct mob_toc_mageAI : public boss_faction_championsAI + { + mob_toc_mageAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_RANGED) {} + + uint32 m_uiCounterspellTimer; + uint32 m_uiBlinkTimer; + uint32 m_uiIceBlockTimer; + uint32 m_uiPolymorphTimer; + uint32 m_uiCommonTimer; + + void Reset() + { + boss_faction_championsAI::Reset(); + m_uiCounterspellTimer = urand(5*IN_MILLISECONDS,15*IN_MILLISECONDS); + m_uiBlinkTimer = urand(7*IN_MILLISECONDS,25*IN_MILLISECONDS); + m_uiIceBlockTimer = urand(0*IN_MILLISECONDS,360*IN_MILLISECONDS); + m_uiPolymorphTimer = urand(15*IN_MILLISECONDS,40*IN_MILLISECONDS); + m_uiCommonTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + SetEquipmentSlots(false, 47524, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) return; + + if (m_uiCounterspellTimer <= uiDiff) + { + if (Unit *pTarget = SelectEnemyCaster(false)) + DoCast(pTarget,SPELL_COUNTERSPELL); + m_uiCounterspellTimer = urand(5*IN_MILLISECONDS,15*IN_MILLISECONDS); + } else m_uiCounterspellTimer -= uiDiff; + + if (m_uiBlinkTimer <= uiDiff) + { + if (HealthBelowPct(50) && EnemiesInRange(10.0f) > 3) + { + DoCastAOE(SPELL_FROST_NOVA); + DoCast(SPELL_BLINK); + } + m_uiBlinkTimer = urand(7*IN_MILLISECONDS,25*IN_MILLISECONDS); + } else m_uiBlinkTimer -= uiDiff; + + if (m_uiIceBlockTimer <= uiDiff) + { + if (HealthBelowPct(20)) + DoCast(me,SPELL_ICE_BLOCK); + m_uiIceBlockTimer = urand(0*IN_MILLISECONDS,360*IN_MILLISECONDS); + } else m_uiIceBlockTimer -= uiDiff; + + if (m_uiPolymorphTimer <= uiDiff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_POLYMORPH); + m_uiPolymorphTimer = urand(15*IN_MILLISECONDS,40*IN_MILLISECONDS); + } else m_uiPolymorphTimer -= uiDiff; + + if (m_uiCommonTimer <= uiDiff) + { + switch(urand(0,2)) + { + case 0: + DoCast(me,SPELL_ARCANE_BARRAGE); + break; + case 1: + DoCastVictim(SPELL_ARCANE_BLAST); + break; + case 2: + DoCastVictim(SPELL_FROSTBOLT); + break; + } + m_uiCommonTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiCommonTimer -= uiDiff; + + boss_faction_championsAI::UpdateAI(uiDiff); + } + }; + +}; + + +#define SPELL_AIMED_SHOT 65883 +#define SPELL_DETERRENCE 65871 //90s +#define SPELL_DISENGAGE 65869 //30s +#define SPELL_EXPLOSIVE_SHOT 65866 +#define SPELL_FROST_TRAP 65880 //30s +#define SPELL_SHOOT 65868 //1.7s +#define SPELL_STEADY_SHOT 65867 //3s +#define SPELL_WING_CLIP 66207 //6s +#define SPELL_WYVERN_STING 65877 //60s +#define SPELL_CALL_PET 67777 +
class mob_toc_hunter : public CreatureScript +{ +public: + mob_toc_hunter() : CreatureScript("mob_toc_hunter") { } + + CreatureAI* GetAI(Creature *pCreature) const + { + return new mob_toc_hunterAI (pCreature); + } + + struct mob_toc_hunterAI : public boss_faction_championsAI + { + mob_toc_hunterAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_RANGED), Summons(me) {} + + SummonList Summons; + + uint32 m_uiDisengageTimer; + uint32 m_uiDeterrenceTimer; + uint32 m_uiWyvernStingTimer; + uint32 m_uiFrostTrapTimer; + uint32 m_uiWingClipTimer; + uint32 m_uiCommonTimer; + uint32 m_uiSummonPetTimer; + + void Reset() + { + boss_faction_championsAI::Reset(); + m_uiDisengageTimer = urand(12*IN_MILLISECONDS,20*IN_MILLISECONDS); + m_uiDeterrenceTimer = urand(20*IN_MILLISECONDS,120*IN_MILLISECONDS); + m_uiWyvernStingTimer = urand(7*IN_MILLISECONDS,60*IN_MILLISECONDS); + m_uiFrostTrapTimer = urand(12*IN_MILLISECONDS,30*IN_MILLISECONDS); + m_uiWingClipTimer = urand(4*IN_MILLISECONDS,8*IN_MILLISECONDS); + m_uiCommonTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + SetEquipmentSlots(false, 47156, EQUIP_NO_CHANGE, 48711); + + m_uiSummonPetTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + DoCast(SPELL_CALL_PET); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) return; + + if (m_uiDisengageTimer <= uiDiff) + { + if(EnemiesInRange(10.0f) > 3) + DoCast(SPELL_DISENGAGE); + m_uiDisengageTimer = urand(12*IN_MILLISECONDS,20*IN_MILLISECONDS); + } else m_uiDisengageTimer -= uiDiff; + + if (m_uiDeterrenceTimer <= uiDiff) + { + if(HealthBelowPct(20)) + DoCast(SPELL_DETERRENCE); + m_uiDeterrenceTimer = urand(20*IN_MILLISECONDS,120*IN_MILLISECONDS); + } else m_uiDeterrenceTimer -= uiDiff; + + if (m_uiWyvernStingTimer <= uiDiff) + { + DoCastVictim(SPELL_WYVERN_STING); + m_uiWyvernStingTimer = urand(7*IN_MILLISECONDS,60*IN_MILLISECONDS); + } else m_uiWyvernStingTimer -= uiDiff; + + if (m_uiFrostTrapTimer <= uiDiff) + { + DoCast(SPELL_FROST_TRAP); + m_uiFrostTrapTimer = urand(12*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiFrostTrapTimer -= uiDiff; + + if (m_uiWingClipTimer <= uiDiff) + { + if (me->GetDistance2d(me->getVictim()) < 5.0f) + DoCastVictim(SPELL_WING_CLIP); + m_uiWingClipTimer = urand(4*IN_MILLISECONDS,8*IN_MILLISECONDS); + } else m_uiWingClipTimer -= uiDiff; + + if (m_uiSummonPetTimer <= uiDiff) + { + m_uiSummonPetTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiSummonPetTimer -= uiDiff; + + if (m_uiCommonTimer <= uiDiff) + { + switch(urand(0,3)) + { + case 0: case 1: + DoCastVictim(SPELL_SHOOT); + break; + case 2: + DoCastVictim(SPELL_EXPLOSIVE_SHOT); + break; + case 3: + DoCastVictim(SPELL_AIMED_SHOT); + break; + } + m_uiCommonTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiCommonTimer -= uiDiff; + + boss_faction_championsAI::UpdateAI(uiDiff); + } + }; + +}; + +#define SPELL_CYCLONE 65859 //6s +#define SPELL_ENTANGLING_ROOTS 65857 //10s +#define SPELL_FAERIE_FIRE 65863 +#define SPELL_FORCE_OF_NATURE 65861 //180s +#define SPELL_INSECT_SWARM 65855 +#define SPELL_MOONFIRE 65856 //5s +#define SPELL_STARFIRE 65854 +#define SPELL_WRATH 65862 +
class mob_toc_boomkin : public CreatureScript +{ +public: + mob_toc_boomkin() : CreatureScript("mob_toc_boomkin") { } + + CreatureAI* GetAI(Creature *pCreature) const + { + return new mob_toc_boomkinAI (pCreature); + } + + struct mob_toc_boomkinAI : public boss_faction_championsAI + { + mob_toc_boomkinAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_RANGED) {} + + uint32 m_uiBarkskinTimer; + uint32 m_uiCycloneTimer; + uint32 m_uiEntanglingRootsTimer; + uint32 m_uiFaerieFireTimer; + uint32 m_uiCommonTimer; + + void Reset() + { + boss_faction_championsAI::Reset(); + m_uiBarkskinTimer = urand(5*IN_MILLISECONDS,120*IN_MILLISECONDS); + m_uiCycloneTimer = urand(5*IN_MILLISECONDS,40*IN_MILLISECONDS); + m_uiEntanglingRootsTimer = urand(5*IN_MILLISECONDS,40*IN_MILLISECONDS); + m_uiFaerieFireTimer = urand(10*IN_MILLISECONDS,40*IN_MILLISECONDS); + m_uiCommonTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + SetEquipmentSlots(false, 50966, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) return; + + if (m_uiBarkskinTimer <= uiDiff) + { + if (HealthBelowPct(50)) + DoCast(me,SPELL_BARKSKIN); + m_uiBarkskinTimer = urand(5*IN_MILLISECONDS,120*IN_MILLISECONDS); + } else m_uiBarkskinTimer -= uiDiff; + + if (m_uiCycloneTimer <= uiDiff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_CYCLONE); + m_uiCycloneTimer = urand(5*IN_MILLISECONDS,40*IN_MILLISECONDS); + } else m_uiCycloneTimer -= uiDiff; + + if (m_uiEntanglingRootsTimer <= uiDiff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_ENTANGLING_ROOTS); + m_uiEntanglingRootsTimer = urand(5*IN_MILLISECONDS,40*IN_MILLISECONDS); + } else m_uiEntanglingRootsTimer -= uiDiff; + + if (m_uiFaerieFireTimer <= uiDiff) + { + DoCastVictim(SPELL_FAERIE_FIRE); + m_uiFaerieFireTimer = urand(10*IN_MILLISECONDS,40*IN_MILLISECONDS); + } else m_uiFaerieFireTimer -= uiDiff; + + if (m_uiCommonTimer <= uiDiff) + { + switch(urand(0,6)) + { + case 0: case 1: + DoCastVictim(SPELL_MOONFIRE); + break; + case 2: + DoCastVictim(SPELL_INSECT_SWARM); + break; + case 3: + DoCastVictim(SPELL_STARFIRE); + break; + case 4: case 5: case 6: + DoCastVictim(SPELL_WRATH); + break; + } + m_uiCommonTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiCommonTimer -= uiDiff; + + boss_faction_championsAI::UpdateAI(uiDiff); + } + }; + +}; + +/******************************************************************** + MELEE +********************************************************************/ + +#define SPELL_BLADESTORM 65947 +#define SPELL_INTIMIDATING_SHOUT 65930 +#define SPELL_MORTAL_STRIKE 65926 +#define SPELL_CHARGE 68764 +#define SPELL_DISARM 65935 +#define SPELL_OVERPOWER 65924 +#define SPELL_SUNDER_ARMOR 65936 +#define SPELL_SHATTERING_THROW 65940 +#define SPELL_RETALIATION 65932 +
class mob_toc_warrior : public CreatureScript +{ +public: + mob_toc_warrior() : CreatureScript("mob_toc_warrior") { } + + CreatureAI* GetAI(Creature *pCreature) const + { + return new mob_toc_warriorAI (pCreature); + } + + struct mob_toc_warriorAI : public boss_faction_championsAI + { + mob_toc_warriorAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) {} + + uint32 m_uiBladestormTimer; + uint32 m_uiIntimidatingShoutTimer; + uint32 m_uiMortalStrikeTimer; + uint32 m_uiSunderArmorTimer; + uint32 m_uiChargeTimer; + uint32 m_uiRetaliationTimer; + uint32 m_uiOverpowerTimer; + uint32 m_uiShatteringThrowTimer; + uint32 m_uiDisarmTimer; + + void Reset() + { + boss_faction_championsAI::Reset(); + m_uiBladestormTimer = urand(20*IN_MILLISECONDS,30*IN_MILLISECONDS); + m_uiIntimidatingShoutTimer = urand(10*IN_MILLISECONDS,60*IN_MILLISECONDS); + m_uiMortalStrikeTimer = urand(6*IN_MILLISECONDS,25*IN_MILLISECONDS); + m_uiSunderArmorTimer = urand(5*IN_MILLISECONDS,25*IN_MILLISECONDS); + m_uiChargeTimer = urand(3*IN_MILLISECONDS,25*IN_MILLISECONDS); + m_uiRetaliationTimer = urand(30*IN_MILLISECONDS,60*IN_MILLISECONDS); + m_uiOverpowerTimer = urand(30*IN_MILLISECONDS,90*IN_MILLISECONDS); + m_uiShatteringThrowTimer = urand(10*IN_MILLISECONDS,25*IN_MILLISECONDS); + m_uiDisarmTimer = urand(20*IN_MILLISECONDS,80*IN_MILLISECONDS); + SetEquipmentSlots(false, 47427, 46964, EQUIP_NO_CHANGE); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) return; + + if (m_uiBladestormTimer <= uiDiff) + { + DoCastVictim(SPELL_BLADESTORM); + m_uiBladestormTimer = urand(20*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiBladestormTimer -= uiDiff; + + if (m_uiIntimidatingShoutTimer <= uiDiff) + { + DoCast(me,SPELL_INTIMIDATING_SHOUT); + m_uiIntimidatingShoutTimer = urand(10*IN_MILLISECONDS,60*IN_MILLISECONDS); + } else m_uiIntimidatingShoutTimer -= uiDiff; + + if (m_uiMortalStrikeTimer <= uiDiff) + { + DoCastVictim(SPELL_MORTAL_STRIKE); + m_uiMortalStrikeTimer = urand(6*IN_MILLISECONDS,25*IN_MILLISECONDS); + } else m_uiMortalStrikeTimer -= uiDiff; + + if (m_uiSunderArmorTimer <= uiDiff) + { + DoCastVictim(SPELL_SUNDER_ARMOR); + m_uiSunderArmorTimer = urand(5*IN_MILLISECONDS,25*IN_MILLISECONDS); + } else m_uiSunderArmorTimer -= uiDiff; + + if (m_uiChargeTimer <= uiDiff) + { + DoCastVictim(SPELL_CHARGE); + m_uiChargeTimer = urand(3*IN_MILLISECONDS,25*IN_MILLISECONDS); + } else m_uiChargeTimer -= uiDiff; + + if (m_uiRetaliationTimer <= uiDiff) + { + DoCastVictim(SPELL_RETALIATION); + m_uiRetaliationTimer = urand(30*IN_MILLISECONDS,60*IN_MILLISECONDS); + } else m_uiRetaliationTimer -= uiDiff; + + if (m_uiOverpowerTimer <= uiDiff) + { + DoCastVictim(SPELL_OVERPOWER); + m_uiOverpowerTimer = urand(30*IN_MILLISECONDS,90*IN_MILLISECONDS); + } else m_uiOverpowerTimer -= uiDiff; + + if (m_uiShatteringThrowTimer <= uiDiff) + { + DoCastVictim(SPELL_SHATTERING_THROW); + m_uiShatteringThrowTimer = urand(10*IN_MILLISECONDS,25*IN_MILLISECONDS); + } else m_uiShatteringThrowTimer -= uiDiff; + + if (m_uiDisarmTimer <= uiDiff) + { + DoCastVictim(SPELL_DISARM); + m_uiDisarmTimer = urand(20*IN_MILLISECONDS,80*IN_MILLISECONDS); + } else m_uiDisarmTimer -= uiDiff; + + boss_faction_championsAI::UpdateAI(uiDiff); + } + }; + +}; + +#define SPELL_CHAINS_OF_ICE 66020 //8sec +#define SPELL_DEATH_COIL 66019 //5sec +#define SPELL_DEATH_GRIP 66017 //35sec +#define SPELL_FROST_STRIKE 66047 //6sec +#define SPELL_ICEBOUND_FORTITUDE 66023 //1min +#define SPELL_ICY_TOUCH 66021 //8sec +#define SPELL_STRANGULATE 66018 //2min +
class mob_toc_dk : public CreatureScript +{ +public: + mob_toc_dk() : CreatureScript("mob_toc_dk") { } + + CreatureAI* GetAI(Creature *pCreature) const + { + return new mob_toc_dkAI (pCreature); + } + + struct mob_toc_dkAI : public boss_faction_championsAI + { + mob_toc_dkAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) {} + + uint32 m_uiIceboundFortitudeTimer; + uint32 m_uiChainsOfIceTimer; + uint32 m_uiDeathCoilTimer; + uint32 m_uiStrangulateTimer; + uint32 m_uiFrostStrikeTimer; + uint32 m_uiIcyTouchTimer; + uint32 m_uiDeathGripTimer; + + void Reset() + { + boss_faction_championsAI::Reset(); + m_uiIceboundFortitudeTimer = urand(5*IN_MILLISECONDS,90*IN_MILLISECONDS); + m_uiChainsOfIceTimer = urand(5*IN_MILLISECONDS,15*IN_MILLISECONDS); + m_uiDeathCoilTimer = urand(5*IN_MILLISECONDS,15*IN_MILLISECONDS); + m_uiStrangulateTimer = urand(10*IN_MILLISECONDS,90*IN_MILLISECONDS); + m_uiFrostStrikeTimer = urand(5*IN_MILLISECONDS,15*IN_MILLISECONDS); + m_uiIcyTouchTimer = urand(8*IN_MILLISECONDS,12*IN_MILLISECONDS); + m_uiDeathGripTimer = urand(5*IN_MILLISECONDS,15*IN_MILLISECONDS); + SetEquipmentSlots(false, 47518, 51021, EQUIP_NO_CHANGE); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) return; + + if (m_uiIceboundFortitudeTimer <= uiDiff) + { + if(HealthBelowPct(50)) + DoCast(me,SPELL_ICEBOUND_FORTITUDE); + m_uiIceboundFortitudeTimer = urand(5*IN_MILLISECONDS,90*IN_MILLISECONDS); + } else m_uiIceboundFortitudeTimer -= uiDiff; + + if (m_uiChainsOfIceTimer <= uiDiff) + { + if(Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_CHAINS_OF_ICE); + m_uiChainsOfIceTimer = urand(5*IN_MILLISECONDS,15*IN_MILLISECONDS); + } else m_uiChainsOfIceTimer -= uiDiff; + + if (m_uiDeathCoilTimer <= uiDiff) + { + DoCastVictim(SPELL_DEATH_COIL); + m_uiDeathCoilTimer = urand(5*IN_MILLISECONDS,15*IN_MILLISECONDS); + } else m_uiDeathCoilTimer -= uiDiff; + + if (m_uiStrangulateTimer <= uiDiff) + { + if(Unit *pTarget = SelectEnemyCaster(false)) + DoCast(pTarget,SPELL_STRANGULATE); + m_uiStrangulateTimer = urand(10*IN_MILLISECONDS,90*IN_MILLISECONDS); + } else m_uiStrangulateTimer -= uiDiff; + + if (m_uiFrostStrikeTimer <= uiDiff) + { + DoCastVictim(SPELL_FROST_STRIKE); + m_uiFrostStrikeTimer = urand(5*IN_MILLISECONDS,15*IN_MILLISECONDS); + } else m_uiFrostStrikeTimer -= uiDiff; + + if (m_uiIcyTouchTimer <= uiDiff) + { + DoCastVictim(SPELL_ICY_TOUCH); + m_uiIcyTouchTimer = urand(8*IN_MILLISECONDS,12*IN_MILLISECONDS); + } else m_uiIcyTouchTimer -= uiDiff; + + if (m_uiDeathGripTimer <= uiDiff) + { + if(me->IsInRange(me->getVictim(), 10.0f, 30.0f, false)) + DoCastVictim(SPELL_DEATH_GRIP); + m_uiDeathGripTimer = urand(5*IN_MILLISECONDS,15*IN_MILLISECONDS); + } else m_uiDeathGripTimer -= uiDiff; + + boss_faction_championsAI::UpdateAI(uiDiff); + } + }; + +}; + +#define SPELL_FAN_OF_KNIVES 65955 //2sec +#define SPELL_BLIND 65960 //2min +#define SPELL_CLOAK 65961 //90sec +#define SPELL_BLADE_FLURRY 65956 //2min +#define SPELL_SHADOWSTEP 66178 //30sec +#define SPELL_HEMORRHAGE 65954 +#define SPELL_EVISCERATE 65957 +
class mob_toc_rogue : public CreatureScript +{ +public: + mob_toc_rogue() : CreatureScript("mob_toc_rogue") { } + + CreatureAI* GetAI(Creature *pCreature) const + { + return new mob_toc_rogueAI (pCreature); + } + + struct mob_toc_rogueAI : public boss_faction_championsAI + { + mob_toc_rogueAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) {} + + uint32 m_uiFanOfKnivesTimer; + uint32 m_uiHemorrhageTimer; + uint32 m_uiEviscerateTimer; + uint32 m_uiShadowstepTimer; + uint32 m_uiBlindTimer; + uint32 m_uiCloakTimer; + uint32 m_uiBladeFlurryTimer; + + void Reset() + { + boss_faction_championsAI::Reset(); + m_uiFanOfKnivesTimer = urand(8*IN_MILLISECONDS,10*IN_MILLISECONDS); + m_uiHemorrhageTimer = urand(5*IN_MILLISECONDS,8*IN_MILLISECONDS); + m_uiEviscerateTimer = urand(15*IN_MILLISECONDS,20*IN_MILLISECONDS); + m_uiShadowstepTimer = urand(10*IN_MILLISECONDS,80*IN_MILLISECONDS); + m_uiBlindTimer = urand(7*IN_MILLISECONDS,8*IN_MILLISECONDS); + m_uiCloakTimer = urand(20*IN_MILLISECONDS,120*IN_MILLISECONDS); + m_uiBladeFlurryTimer = urand(12*IN_MILLISECONDS,120*IN_MILLISECONDS); + SetEquipmentSlots(false, 47422, 49982, EQUIP_NO_CHANGE); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) return; + + if (m_uiFanOfKnivesTimer <= uiDiff) + { + if(EnemiesInRange(15.0f) > 2) + DoCastAOE(SPELL_FAN_OF_KNIVES); + m_uiFanOfKnivesTimer = urand(8*IN_MILLISECONDS,10*IN_MILLISECONDS); + } else m_uiFanOfKnivesTimer -= uiDiff; + + if (m_uiHemorrhageTimer <= uiDiff) + { + DoCastVictim(SPELL_HEMORRHAGE); + m_uiHemorrhageTimer = urand(5*IN_MILLISECONDS,8*IN_MILLISECONDS); + } else m_uiHemorrhageTimer -= uiDiff; + + if (m_uiEviscerateTimer <= uiDiff) + { + DoCastVictim(SPELL_EVISCERATE); + m_uiEviscerateTimer = urand(15*IN_MILLISECONDS,20*IN_MILLISECONDS); + } else m_uiEviscerateTimer -= uiDiff; + + if (m_uiShadowstepTimer <= uiDiff) + { + if(me->IsInRange(me->getVictim(), 10.0f, 40.0f)) + DoCastVictim(SPELL_SHADOWSTEP); + m_uiShadowstepTimer = urand(10*IN_MILLISECONDS,80*IN_MILLISECONDS); + } else m_uiShadowstepTimer -= uiDiff; + + if (m_uiBlindTimer <= uiDiff) + { + if(Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + if(me->IsInRange(pTarget, 0.0f, 15.0f, false)) + DoCast(pTarget,SPELL_BLIND); + m_uiBlindTimer = urand(7*IN_MILLISECONDS,8*IN_MILLISECONDS); + } else m_uiBlindTimer -= uiDiff; + + if (m_uiCloakTimer <= uiDiff) + { + if(HealthBelowPct(50)) + DoCast(me,SPELL_CLOAK); + m_uiCloakTimer = urand(20*IN_MILLISECONDS,120*IN_MILLISECONDS); + } else m_uiCloakTimer -= uiDiff; + + if (m_uiBladeFlurryTimer <= uiDiff) + { + DoCastVictim(SPELL_BLADE_FLURRY); + m_uiBladeFlurryTimer = urand(12*IN_MILLISECONDS,120*IN_MILLISECONDS); + } else m_uiBladeFlurryTimer -= uiDiff; + + boss_faction_championsAI::UpdateAI(uiDiff); + } + }; + +}; + +#define SPELL_EARTH_SHOCK 65973 +#define SPELL_LAVA_LASH 65974 +#define SPELL_STORMSTRIKE 65970 +
class mob_toc_enh_shaman : public CreatureScript +{ +public: + mob_toc_enh_shaman() : CreatureScript("mob_toc_enh_shaman") { } + + CreatureAI* GetAI(Creature *pCreature) const + { + return new mob_toc_enh_shamanAI (pCreature); + } + + struct mob_toc_enh_shamanAI : public boss_faction_championsAI + { + mob_toc_enh_shamanAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_MELEE), Summons(me) {} + + SummonList Summons; + + uint32 m_uiHeroismOrBloodlustTimer; + uint32 m_uiEarthShockTimer; + uint32 m_uiStormstrikeTimer; + uint32 m_uiLavaLashTimer; + uint32 m_uiDeployTotemTimer; + uint8 m_uiTotemCount; + float m_fTotemOldCenterX, m_fTotemOldCenterY; + + void Reset() + { + boss_faction_championsAI::Reset(); + m_uiHeroismOrBloodlustTimer = urand(25*IN_MILLISECONDS,60*IN_MILLISECONDS); + m_uiEarthShockTimer = urand(5*IN_MILLISECONDS,8*IN_MILLISECONDS); + m_uiStormstrikeTimer = urand(5*IN_MILLISECONDS,90*IN_MILLISECONDS); + m_uiLavaLashTimer = urand(5*IN_MILLISECONDS,8*IN_MILLISECONDS); + m_uiDeployTotemTimer = urand(1*IN_MILLISECONDS,3*IN_MILLISECONDS); + m_uiTotemCount = 0; + m_fTotemOldCenterX = me->GetPositionX(); + m_fTotemOldCenterY = me->GetPositionY(); + SetEquipmentSlots(false, 51803, 48013, EQUIP_NO_CHANGE); + Summons.DespawnAll(); + } + + void JustSummoned(Creature* pSummoned) + { + Summons.Summon(pSummoned); + } + + void SummonedCreatureDespawn(Creature* pSummoned) + { + --m_uiTotemCount; + } + + void DeployTotem() + { + m_uiTotemCount = 4; + m_fTotemOldCenterX = me->GetPositionX(); + m_fTotemOldCenterY = me->GetPositionY(); + /* + -Windfury (16% melee haste) + -Grounding (redirects one harmful magic spell to the totem) + + -Healing Stream (unable to find amount of healing in our logs) + + -Tremor (prevents fear effects) + -Strength of Earth (155 strength and agil for the opposing team) + + -Searing (average ~3500 damage on a random target every ~3.5 seconds) + */ + } + + void JustDied(Unit *pKiller) + { + boss_faction_championsAI::JustDied(pKiller); + Summons.DespawnAll(); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) return; + + if (m_uiHeroismOrBloodlustTimer <= uiDiff) + { + if (me->getFaction()) //Am i alliance? + if (!me->HasAura(AURA_EXHAUSTION)) + DoCastAOE(SPELL_HEROISM); + else + if (!me->HasAura(AURA_SATED)) + DoCastAOE(SPELL_BLOODLUST); + m_uiHeroismOrBloodlustTimer = urand(25*IN_MILLISECONDS,60*IN_MILLISECONDS); + } else m_uiHeroismOrBloodlustTimer -= uiDiff; + + if (m_uiEarthShockTimer <= uiDiff) + { + DoCastVictim(SPELL_EARTH_SHOCK); + m_uiEarthShockTimer = urand(5*IN_MILLISECONDS,8*IN_MILLISECONDS); + } else m_uiEarthShockTimer -= uiDiff; + + if (m_uiStormstrikeTimer <= uiDiff) + { + DoCastVictim(SPELL_STORMSTRIKE); + m_uiStormstrikeTimer = urand(5*IN_MILLISECONDS,90*IN_MILLISECONDS); + } else m_uiStormstrikeTimer -= uiDiff; + + if (m_uiLavaLashTimer <= uiDiff) + { + DoCastVictim(SPELL_LAVA_LASH); + m_uiLavaLashTimer = urand(5*IN_MILLISECONDS,8*IN_MILLISECONDS); + } else m_uiLavaLashTimer -= uiDiff; + + if (m_uiDeployTotemTimer <= uiDiff) + { + if (m_uiTotemCount < 4 || me->GetDistance2d(m_fTotemOldCenterX,m_fTotemOldCenterY) > 20.0f) + DeployTotem(); + m_uiDeployTotemTimer = urand(1*IN_MILLISECONDS,3*IN_MILLISECONDS); + } else m_uiDeployTotemTimer -= uiDiff; + + boss_faction_championsAI::UpdateAI(uiDiff); + } + }; + +}; + +#define SPELL_AVENGING_WRATH 66011 //3min cd +#define SPELL_CRUSADER_STRIKE 66003 //6sec cd +#define SPELL_DIVINE_SHIELD 66010 //5min cd +#define SPELL_DIVINE_STORM 66006 //10sec cd +#define SPELL_HAMMER_OF_JUSTICE 66007 //40sec cd +#define SPELL_HAND_OF_PROTECTION 66009 //5min cd +#define SPELL_JUDGEMENT_OF_COMMAND 66005 //8sec cd +#define SPELL_REPENTANCE 66008 //60sec cd +#define SPELL_SEAL_OF_COMMAND 66004 //no cd +
class mob_toc_retro_paladin : public CreatureScript +{ +public: + mob_toc_retro_paladin() : CreatureScript("mob_toc_retro_paladin") { } + + CreatureAI* GetAI(Creature *pCreature) const + { + return new mob_toc_retro_paladinAI (pCreature); + } + + struct mob_toc_retro_paladinAI : public boss_faction_championsAI + { + mob_toc_retro_paladinAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) {} + + uint32 m_uiRepeteanceTimer; + uint32 m_uiCrusaderStrikeTimer; + uint32 m_uiAvengingWrathTimer; + uint32 m_uiDivineShieldTimer; + uint32 m_uiDivineStormTimer; + uint32 m_uiJudgementOfCommandTimer; + + void Reset() + { + boss_faction_championsAI::Reset(); + m_uiRepeteanceTimer = 60*IN_MILLISECONDS; + m_uiCrusaderStrikeTimer = urand(6*IN_MILLISECONDS,18*IN_MILLISECONDS); + m_uiAvengingWrathTimer = 180*IN_MILLISECONDS; + m_uiDivineShieldTimer = urand(0*IN_MILLISECONDS,360*IN_MILLISECONDS); + m_uiDivineStormTimer = 10*IN_MILLISECONDS; + m_uiJudgementOfCommandTimer = urand(8*IN_MILLISECONDS,15*IN_MILLISECONDS); + SetEquipmentSlots(false, 47519, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + } + + void EnterCombat(Unit *pWho) + { + boss_faction_championsAI::EnterCombat(pWho); + DoCast(SPELL_SEAL_OF_COMMAND); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) return; + + if (m_uiRepeteanceTimer <= uiDiff) + { + if(Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_REPENTANCE); + m_uiRepeteanceTimer = 60*IN_MILLISECONDS; + } else m_uiRepeteanceTimer -= uiDiff; + + if (m_uiCrusaderStrikeTimer <= uiDiff) + { + DoCastVictim(SPELL_CRUSADER_STRIKE); + m_uiCrusaderStrikeTimer = urand(6*IN_MILLISECONDS,18*IN_MILLISECONDS); + } else m_uiCrusaderStrikeTimer -= uiDiff; + + if (m_uiAvengingWrathTimer <= uiDiff) + { + DoCastVictim(SPELL_AVENGING_WRATH); + m_uiAvengingWrathTimer = 180*IN_MILLISECONDS; + } else m_uiAvengingWrathTimer -= uiDiff; + + if (m_uiDivineShieldTimer <= uiDiff) + { + if(HealthBelowPct(20)) + DoCast(me,SPELL_DIVINE_SHIELD); + m_uiDivineShieldTimer = urand(0*IN_MILLISECONDS,360*IN_MILLISECONDS); + } else m_uiDivineShieldTimer -= uiDiff; + + if (m_uiDivineStormTimer <= uiDiff) + { + DoCastVictim(SPELL_DIVINE_STORM); + m_uiDivineStormTimer = 10*IN_MILLISECONDS; + } else m_uiDivineStormTimer -= uiDiff; + + if (m_uiJudgementOfCommandTimer <= uiDiff) + { + DoCastVictim(SPELL_JUDGEMENT_OF_COMMAND); + m_uiJudgementOfCommandTimer = urand(8*IN_MILLISECONDS,15*IN_MILLISECONDS); + } else m_uiJudgementOfCommandTimer -= uiDiff; + + boss_faction_championsAI::UpdateAI(uiDiff); + } + }; + +}; + +#define SPELL_DEVOUR_MAGIC 67518 +#define SPELL_SPELL_LOCK 67519 + +class mob_toc_pet_warlock : public CreatureScript +{ +public: + mob_toc_pet_warlock() : CreatureScript("mob_toc_pet_warlock") { } + + CreatureAI* GetAI(Creature *pCreature) const + { + return new mob_toc_pet_warlockAI (pCreature); + } + + struct mob_toc_pet_warlockAI : public boss_faction_championsAI + { + mob_toc_pet_warlockAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_PET) {} + + uint32 m_uiDevourMagicTimer; + uint32 m_uiSpellLockTimer; + + void Reset() + { + boss_faction_championsAI::Reset(); + m_uiDevourMagicTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + m_uiSpellLockTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) return; + + if (m_uiDevourMagicTimer <= uiDiff) + { + DoCastVictim(SPELL_DEVOUR_MAGIC); + m_uiDevourMagicTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiDevourMagicTimer -= uiDiff; + + if (m_uiSpellLockTimer <= uiDiff) + { + DoCastVictim(SPELL_SPELL_LOCK); + m_uiSpellLockTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiSpellLockTimer -= uiDiff; + + boss_faction_championsAI::UpdateAI(uiDiff); + } + }; + +}; + +#define SPELL_CLAW 67793 +class mob_toc_pet_hunter : public CreatureScript +{ +public: + mob_toc_pet_hunter() : CreatureScript("mob_toc_pet_hunter") { } + + CreatureAI* GetAI(Creature *pCreature) const + { + return new mob_toc_pet_hunterAI (pCreature); + } + + struct mob_toc_pet_hunterAI : public boss_faction_championsAI + { + mob_toc_pet_hunterAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_PET) {} + + uint32 m_uiClawTimer; + + void Reset() + { + boss_faction_championsAI::Reset(); + m_uiClawTimer = urand(5*IN_MILLISECONDS,10*IN_MILLISECONDS); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) return; + + if (m_uiClawTimer <= uiDiff) + { + DoCastVictim(SPELL_CLAW); + m_uiClawTimer = urand(5*IN_MILLISECONDS,10*IN_MILLISECONDS); + } else m_uiClawTimer -= uiDiff; + + boss_faction_championsAI::UpdateAI(uiDiff); + } + }; + +}; + +/*========================================================*/ + +void AddSC_boss_faction_champions() +{ + new boss_toc_champion_controller(); + new mob_toc_druid(); + new mob_toc_shaman(); + new mob_toc_paladin(); + new mob_toc_priest(); + new mob_toc_shadow_priest(); + new mob_toc_mage(); + new mob_toc_warlock(); + new mob_toc_hunter(); + new mob_toc_boomkin(); + new mob_toc_warrior(); + new mob_toc_dk(); + new mob_toc_rogue(); + new mob_toc_enh_shaman(); + new mob_toc_retro_paladin(); + new mob_toc_pet_warlock(); + new mob_toc_pet_hunter(); +} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp new file mode 100644 index 00000000000..2746e5b277a --- /dev/null +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp @@ -0,0 +1,566 @@ +/* Copyright (C) 2006 - 2010 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> + * 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 + */ + +/* ScriptData +SDName: trial_of_the_crusader +SD%Complete: ??% +SDComment: based on /dev/rsa +SDCategory: Crusader Coliseum +EndScriptData */ + +// Known bugs: +// Some visuals aren't appearing right sometimes +// Mistress of Pain - Isn't working as a vehicle yet +// - SPELL_SPINNING_STRIKE not working + +#include "ScriptPCH.h" +#include "trial_of_the_crusader.h" + +enum Yells +{ + SAY_INTRO = -1649030, + SAY_AGGRO = -1649031, + SAY_DEATH = -1649032, + EMOTE_INCINERATE = -1649033, + SAY_INCINERATE = -1649034, + EMOTE_LEGION_FLAME = -1649035, + EMOTE_NETHER_PORTAL = -1649036, + SAY_NETHER_PORTAL = -1649037, + EMOTE_INFERNAL_ERUPTION = -1649038, + SAY_INFERNAL_ERUPTION = -1649039, +}; + +enum Equipment +{ + EQUIP_MAIN = 47266, + EQUIP_OFFHAND = 46996, + EQUIP_RANGED = 47267, + EQUIP_DONE = EQUIP_NO_CHANGE, +}; + +enum Summons +{ + NPC_LEGION_FLAME = 34784, + NPC_INFERNAL_VOLCANO = 34813, + NPC_FEL_INFERNAL = 34815, + NPC_NETHER_PORTAL = 34825, + NPC_MISTRESS_OF_PAIN = 34826, +}; + +enum BossSpells +{ + SPELL_NETHER_POWER = 67108, + SPELL_INFERNAL = 66258, + SPELL_INFERNAL_ERUPTION = 66255, + SPELL_FEL_FIREBALL = 66532, + SPELL_FEL_LIGHTING = 66528, + SPELL_INCINERATE_FLESH = 66237, + SPELL_TOUCH_OF_JARAXXUS = 66209, + SPELL_BURNING_INFERNO = 66242, + SPELL_NETHER_PORTAL = 66263, + SPELL_LEGION_FLAME = 66197, + SPELL_LEGION_FLAME_EFFECT = 66201, + SPELL_SHIVAN_SLASH = 67098, + SPELL_SPINNING_STRIKE = 66316, + SPELL_MISTRESS_KISS = 67077, + SPELL_FEL_INFERNO = 67047, + SPELL_FEL_STREAK = 66494, + SPELL_BERSERK = 64238, +}; + +/*###### +## boss_jaraxxus +######*/ +
class boss_jaraxxus : public CreatureScript +{ +public: + boss_jaraxxus() : CreatureScript("boss_jaraxxus") { } + + CreatureAI* GetAI(Creature* pCreature) const + { + return new boss_jaraxxusAI(pCreature); + } + + struct boss_jaraxxusAI : public ScriptedAI + { + boss_jaraxxusAI(Creature* pCreature) : ScriptedAI(pCreature), Summons(me) + { + m_pInstance = (InstanceScript*)pCreature->GetInstanceScript(); + Reset(); + } + + InstanceScript* m_pInstance; + + SummonList Summons; + + uint32 m_uiFelFireballTimer; + uint32 m_uiFelLightningTimer; + uint32 m_uiIncinerateFleshTimer; + uint32 m_uiNetherPowerTimer; + uint32 m_uiLegionFlameTimer; + uint32 m_uiTouchOfJaraxxusTimer; + uint32 m_uiSummonNetherPortalTimer; + uint32 m_uiSummonInfernalEruptionTimer; + + void Reset() + { + if(m_pInstance) + m_pInstance->SetData(TYPE_JARAXXUS, NOT_STARTED); + SetEquipmentSlots(false, EQUIP_MAIN, EQUIP_OFFHAND, EQUIP_RANGED); + m_uiFelFireballTimer = 5*IN_MILLISECONDS; + m_uiFelLightningTimer = urand(10*IN_MILLISECONDS,15*IN_MILLISECONDS); + m_uiIncinerateFleshTimer = urand(20*IN_MILLISECONDS,25*IN_MILLISECONDS); + m_uiNetherPowerTimer = 40*IN_MILLISECONDS; + m_uiLegionFlameTimer = 30*IN_MILLISECONDS; + m_uiTouchOfJaraxxusTimer = urand(10*IN_MILLISECONDS,15*IN_MILLISECONDS); + m_uiSummonNetherPortalTimer = 1*MINUTE*IN_MILLISECONDS; + m_uiSummonInfernalEruptionTimer = 2*MINUTE*IN_MILLISECONDS; + Summons.DespawnAll(); + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_JARAXXUS, FAIL); + DoCast(me,SPELL_JARAXXUS_CHAINS); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetReactState(REACT_PASSIVE); + } + + void KilledUnit(Unit *pWho) + { + if (pWho->GetTypeId() == TYPEID_PLAYER) + { + if (m_pInstance) + m_pInstance->SetData(DATA_TRIBUTE_TO_IMMORTALITY_ELEGIBLE, 0); + } + } + + void JustDied(Unit* pKiller) + { + Summons.DespawnAll(); + DoScriptText(SAY_DEATH,me); + if (m_pInstance) + m_pInstance->SetData(TYPE_JARAXXUS, DONE); + } + + void JustSummoned(Creature* pSummoned) + { + Summons.Summon(pSummoned); + } + + void EnterCombat(Unit* pWho) + { + me->SetInCombatWithZone(); + if (m_pInstance) + m_pInstance->SetData(TYPE_JARAXXUS, IN_PROGRESS); + DoScriptText(SAY_AGGRO,me); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (m_uiSummonInfernalEruptionTimer <= uiDiff) + { + DoScriptText(EMOTE_INFERNAL_ERUPTION,me); + DoScriptText(SAY_INFERNAL_ERUPTION,me); + uint8 i = urand(2,3); + me->SummonCreature(NPC_INFERNAL_VOLCANO,JaraxxusLoc[i].GetPositionX(),JaraxxusLoc[i].GetPositionY(),JaraxxusLoc[i].GetPositionZ(),TEMPSUMMON_CORPSE_DESPAWN); + m_uiSummonInfernalEruptionTimer = 2*MINUTE*IN_MILLISECONDS; + } else m_uiSummonInfernalEruptionTimer -= uiDiff; + + if (m_uiSummonNetherPortalTimer <= uiDiff) + { + DoScriptText(EMOTE_NETHER_PORTAL,me); + DoScriptText(SAY_NETHER_PORTAL,me); + uint8 i = urand(2,3); + me->SummonCreature(NPC_NETHER_PORTAL,JaraxxusLoc[i].GetPositionX(),JaraxxusLoc[i].GetPositionY(),JaraxxusLoc[i].GetPositionZ(),TEMPSUMMON_CORPSE_DESPAWN); + m_uiSummonNetherPortalTimer = 2*MINUTE*IN_MILLISECONDS; + } else m_uiSummonNetherPortalTimer -= uiDiff; + + if (m_uiFelFireballTimer <= uiDiff) + { + DoCastVictim(SPELL_FEL_FIREBALL); + m_uiFelFireballTimer = urand(10*IN_MILLISECONDS,15*IN_MILLISECONDS); + } else m_uiFelFireballTimer -= uiDiff; + + if (m_uiFelLightningTimer <= uiDiff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget,SPELL_FEL_LIGHTING); + m_uiFelLightningTimer = urand(10*IN_MILLISECONDS,15*IN_MILLISECONDS); + } else m_uiFelLightningTimer -= uiDiff; + + if (m_uiIncinerateFleshTimer <= uiDiff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,1)) + { + DoScriptText(EMOTE_INCINERATE,me,pTarget); + DoScriptText(SAY_INCINERATE,me); + DoCast(pTarget,SPELL_INCINERATE_FLESH); + } + m_uiIncinerateFleshTimer = urand(20*IN_MILLISECONDS,25*IN_MILLISECONDS); + } else m_uiIncinerateFleshTimer -= uiDiff; + + if (m_uiNetherPowerTimer <= uiDiff) + { + DoCast(me,SPELL_NETHER_POWER); + m_uiNetherPowerTimer = 40*IN_MILLISECONDS; + } else m_uiNetherPowerTimer -= uiDiff; + + if (m_uiLegionFlameTimer <= uiDiff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,1)) + { + DoScriptText(EMOTE_LEGION_FLAME,me,pTarget); + DoCast(pTarget,SPELL_LEGION_FLAME); + } + m_uiLegionFlameTimer = 30*IN_MILLISECONDS; + } else m_uiLegionFlameTimer -= uiDiff; + + if (getDifficulty() == RAID_DIFFICULTY_25MAN_HEROIC && m_uiTouchOfJaraxxusTimer <= uiDiff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_TOUCH_OF_JARAXXUS); + m_uiTouchOfJaraxxusTimer = urand(10*IN_MILLISECONDS,15*IN_MILLISECONDS); + } else m_uiTouchOfJaraxxusTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + }; + +}; + +
class mob_legion_flame : public CreatureScript +{ +public: + mob_legion_flame() : CreatureScript("mob_legion_flame") { } + + CreatureAI* GetAI(Creature* pCreature) const + { + return new mob_legion_flameAI(pCreature); + } + + struct mob_legion_flameAI : public Scripted_NoMovementAI + { + mob_legion_flameAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) + { + Reset(); + } + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->SetInCombatWithZone(); + DoCast(SPELL_LEGION_FLAME_EFFECT); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + } + }; + +}; + +
class mob_infernal_volcano : public CreatureScript +{ +public: + mob_infernal_volcano() : CreatureScript("mob_infernal_volcano") { } + + CreatureAI* GetAI(Creature* pCreature) const + { + return new mob_infernal_volcanoAI(pCreature); + } + + struct mob_infernal_volcanoAI : public Scripted_NoMovementAI + { + mob_infernal_volcanoAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature), Summons(me) + { + m_pInstance = (InstanceScript*)pCreature->GetInstanceScript(); + Reset(); + } + + InstanceScript* m_pInstance; + + SummonList Summons; + + uint8 m_Count; + uint8 m_CountMax; + uint32 m_Timer; + + void Reset() + { + me->SetReactState(REACT_PASSIVE); + m_Count = 0; + if (!IsHeroic()) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED); + m_CountMax = 3; + m_Timer = 15*IN_MILLISECONDS; + } + else + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED); + m_CountMax = 0; + m_Timer = 0; + } + Summons.DespawnAll(); + } + + void JustSummoned(Creature* pSummoned) + { + Summons.Summon(pSummoned); + pSummoned->SetCorpseDelay(0); + } + + void JustDied(Unit* pKiller) + { + me->ForcedDespawn(); + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_Timer <= uiDiff) + { + if (m_CountMax && m_CountMax == m_Count) + me->ForcedDespawn(); + else + { + DoCast(SPELL_INFERNAL_ERUPTION); + ++m_Count; + } + m_Timer = 5*IN_MILLISECONDS; + } else m_Timer -= uiDiff; + + if (!UpdateVictim()) + return; + } + }; + +}; + +
class mob_fel_infernal : public CreatureScript +{ +public: + mob_fel_infernal() : CreatureScript("mob_fel_infernal") { } + + CreatureAI* GetAI(Creature* pCreature) const + { + return new mob_fel_infernalAI(pCreature); + } + + struct mob_fel_infernalAI : public ScriptedAI + { + mob_fel_infernalAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (InstanceScript*)pCreature->GetInstanceScript(); + Reset(); + } + + InstanceScript* m_pInstance; + uint32 m_uiFelStreakTimer; + + void Reset() + { + m_uiFelStreakTimer = 30*IN_MILLISECONDS; + me->SetInCombatWithZone(); + } + + /*void SpellHitTarget(Unit *pTarget, const SpellEntry *pSpell) + { + if (pSpell->Id == SPELL_FEL_STREAK) + DoCastAOE(SPELL_FEL_INFERNO); //66517 + }*/ + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (m_pInstance && m_pInstance->GetData(TYPE_JARAXXUS) != IN_PROGRESS) + me->ForcedDespawn(); + + if (m_uiFelStreakTimer <= uiDiff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_FEL_STREAK); + m_uiFelStreakTimer = 30*IN_MILLISECONDS; + } else m_uiFelStreakTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + }; + +}; + +
class mob_nether_portal : public CreatureScript +{ +public: + mob_nether_portal() : CreatureScript("mob_nether_portal") { } + + CreatureAI* GetAI(Creature* pCreature) const + { + return new mob_nether_portalAI(pCreature); + } + + struct mob_nether_portalAI : public ScriptedAI + { + mob_nether_portalAI(Creature* pCreature) : ScriptedAI(pCreature), Summons(me) + { + m_pInstance = (InstanceScript*)pCreature->GetInstanceScript(); + Reset(); + } + + InstanceScript* m_pInstance; + + SummonList Summons; + + uint32 m_Timer; + uint8 m_Count; + uint8 m_CountMax; + + void Reset() + { + me->SetReactState(REACT_PASSIVE); + m_Timer = 10*IN_MILLISECONDS; + m_Count = 0; + if (!IsHeroic()) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED); + m_CountMax = 1; + } + else + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED); + m_CountMax = 0; + } + Summons.DespawnAll(); + } + + void JustSummoned(Creature* pSummoned) + { + Summons.Summon(pSummoned); + pSummoned->SetCorpseDelay(0); + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_Timer <= uiDiff) + { + if (m_CountMax && m_CountMax == m_Count) + me->ForcedDespawn(); + else + { + DoCast(SPELL_NETHER_PORTAL); + ++m_Count; + } + m_Timer = 15*IN_MILLISECONDS; + } else m_Timer -= uiDiff; + + if (!UpdateVictim()) + return; + } + }; + +}; + +
class mob_mistress_of_pain : public CreatureScript +{ +public: + mob_mistress_of_pain() : CreatureScript("mob_mistress_of_pain") { } + + CreatureAI* GetAI(Creature* pCreature) const + { + return new mob_mistress_of_painAI(pCreature); + } + + struct mob_mistress_of_painAI : public ScriptedAI + { + mob_mistress_of_painAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (InstanceScript*)pCreature->GetInstanceScript(); + if (m_pInstance) + m_pInstance->SetData(DATA_MISTRESS_OF_PAIN_COUNT, INCREASE); + Reset(); + } + + InstanceScript* m_pInstance; + uint32 m_uiShivanSlashTimer; + uint32 m_uiSpinningStrikeTimer; + uint32 m_uiMistressKissTimer; + + void Reset() + { + m_uiShivanSlashTimer = 30*IN_MILLISECONDS; + m_uiSpinningStrikeTimer = 30*IN_MILLISECONDS; + m_uiMistressKissTimer = 15*IN_MILLISECONDS; + me->SetInCombatWithZone(); + } + + void JustDied(Unit* pKiller) + { + if (m_pInstance) + m_pInstance->SetData(DATA_MISTRESS_OF_PAIN_COUNT, DECREASE); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (m_pInstance && m_pInstance->GetData(TYPE_JARAXXUS) != IN_PROGRESS) + me->ForcedDespawn(); + + if (m_uiShivanSlashTimer <= uiDiff) + { + DoCastVictim(SPELL_SHIVAN_SLASH); + m_uiShivanSlashTimer = 30*IN_MILLISECONDS; + } else m_uiShivanSlashTimer -= uiDiff; + + if (m_uiSpinningStrikeTimer <= uiDiff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_SPINNING_STRIKE); + m_uiSpinningStrikeTimer = 30*IN_MILLISECONDS; + } else m_uiSpinningStrikeTimer -= uiDiff; + + if (IsHeroic() && m_uiMistressKissTimer <= uiDiff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_MISTRESS_KISS); + m_uiMistressKissTimer = 30*IN_MILLISECONDS; + } else m_uiMistressKissTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + }; + +}; + + +void AddSC_boss_jaraxxus() +{ + new boss_jaraxxus(); + new mob_legion_flame(); + new mob_infernal_volcano(); + new mob_fel_infernal(); + new mob_nether_portal(); + new mob_mistress_of_pain(); +} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp new file mode 100644 index 00000000000..9bbe93f3aa7 --- /dev/null +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp @@ -0,0 +1,906 @@ +/* Copyright (C) 2006 - 2010 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> + * 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 + */ +/* ScriptData +SDName: northrend_beasts +SD%Complete: 90% +SDComment: based on /dev/rsa +SDCategory: +EndScriptData */ + +// Known bugs: +// Gormok - Not implemented as a vehicle +// - Snobold Firebomb +// - Snobolled (creature at back) +// Snakes - miss the 1-hitkill from emerging +// - visual changes between mobile and stationary models seems not to work sometimes + +#include "ScriptPCH.h" +#include "trial_of_the_crusader.h" + +enum Yells +{ + //Gormok + SAY_SNOBOLLED = -1649000, + //Acidmaw & Dreadscale + SAY_SUBMERGE = -1649010, + SAY_EMERGE = -1649011, + SAY_BERSERK = -1649012, + //Icehowl + SAY_TRAMPLE_STARE = -1649020, + SAY_TRAMPLE_FAIL = -1649021, + SAY_TRAMPLE_START = -1649022, +}; + +enum Equipment +{ + EQUIP_MAIN = 50760, + EQUIP_OFFHAND = 48040, + EQUIP_RANGED = 47267, + EQUIP_DONE = EQUIP_NO_CHANGE, +}; + +enum Model +{ + MODEL_ACIDMAW_STATIONARY = 29815, + MODEL_ACIDMAW_MOBILE = 29816, + MODEL_DREADSCALE_STATIONARY = 26935, + MODEL_DREADSCALE_MOBILE = 24564, +}; + +enum Summons +{ + NPC_SNOBOLD_VASSAL = 34800, + NPC_SLIME_POOL = 35176, +}; + +enum BossSpells +{ + //Gormok + SPELL_IMPALE = 66331, + SPELL_STAGGERING_STOMP = 67648, + SPELL_RISING_ANGER = 66636, + //Snobold + SPELL_SNOBOLLED = 66406, + SPELL_BATTER = 66408, + SPELL_FIRE_BOMB = 66313, + SPELL_FIRE_BOMB_1 = 66317, + SPELL_FIRE_BOMB_DOT = 66318, + SPELL_HEAD_CRACK = 66407, + + //Acidmaw & Dreadscale + SPELL_ACID_SPIT = 66880, + SPELL_PARALYTIC_SPRAY = 66901, + SPELL_ACID_SPEW = 66819, + SPELL_PARALYTIC_BITE = 66824, + SPELL_SWEEP_0 = 66794, + SUMMON_SLIME_POOL = 66883, + SPELL_FIRE_SPIT = 66796, + SPELL_MOLTEN_SPEW = 66821, + SPELL_BURNING_BITE = 66879, + SPELL_BURNING_SPRAY = 66902, + SPELL_SWEEP_1 = 67646, + SPELL_EMERGE_0 = 66947, + SPELL_SUBMERGE_0 = 53421, + SPELL_ENRAGE = 68335, + SPELL_SLIME_POOL_EFFECT = 66882, //In 60s it diameter grows from 10y to 40y (r=r+0.25 per second) + + //Icehowl + SPELL_FEROCIOUS_BUTT = 66770, + SPELL_MASSIVE_CRASH = 66683, + SPELL_WHIRL = 67345, + SPELL_ARCTIC_BREATH = 66689, + SPELL_TRAMPLE = 66734, + SPELL_FROTHING_RAGE = 66759, + SPELL_STAGGERED_DAZE = 66758, +}; +
class boss_gormok : public CreatureScript +{ +public: + boss_gormok() : CreatureScript("boss_gormok") { } + + CreatureAI* GetAI(Creature* pCreature) const + { + return new boss_gormokAI(pCreature); + } + + struct boss_gormokAI : public ScriptedAI + { + boss_gormokAI(Creature* pCreature) : ScriptedAI(pCreature), Summons(me) + { + m_pInstance = (InstanceScript*)pCreature->GetInstanceScript(); + } + + InstanceScript* m_pInstance; + + uint32 m_uiImpaleTimer; + uint32 m_uiStaggeringStompTimer; + SummonList Summons; + uint32 m_uiSummonTimer; + uint32 m_uiSummonCount; + + void Reset() + { + m_uiImpaleTimer = urand(8*IN_MILLISECONDS,10*IN_MILLISECONDS); + m_uiStaggeringStompTimer = 15*IN_MILLISECONDS; + m_uiSummonTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS);; + + if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL || + getDifficulty() == RAID_DIFFICULTY_25MAN_HEROIC) + m_uiSummonCount = 5; + else + m_uiSummonCount = 4; + + Summons.DespawnAll(); + } + + void JustDied(Unit* pKiller) + { + if (m_pInstance) + m_pInstance->SetData(TYPE_NORTHREND_BEASTS,GORMOK_DONE); + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_NORTHREND_BEASTS,FAIL); + me->ForcedDespawn(); + } + + void EnterCombat(Unit* pWho) + { + me->SetInCombatWithZone(); + m_pInstance->SetData(TYPE_NORTHREND_BEASTS,GORMOK_IN_PROGRESS); + } + + void JustSummoned(Creature* pSummoned) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + switch(pSummoned->GetEntry()) + { + case NPC_SNOBOLD_VASSAL: + pSummoned->GetMotionMaster()->MoveJump(pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),10.0f,20.0f); + DoCast(me, SPELL_RISING_ANGER); + --m_uiSummonCount; + break; + } + pSummoned->AI()->AttackStart(pTarget); + Summons.Summon(pSummoned); + } + + void SummonedCreatureDespawn(Creature* pSummoned) + { + switch(pSummoned->GetEntry()) + { + case NPC_SNOBOLD_VASSAL: + if (pSummoned->isAlive()) ++m_uiSummonCount; + break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (m_uiImpaleTimer <= uiDiff) + { + DoCast(me->getVictim(),SPELL_IMPALE); + m_uiImpaleTimer = urand(8*IN_MILLISECONDS,10*IN_MILLISECONDS); + } else m_uiImpaleTimer -= uiDiff; + + if (m_uiStaggeringStompTimer <= uiDiff) + { + DoCast(me->getVictim(),SPELL_STAGGERING_STOMP); + m_uiStaggeringStompTimer = urand(20*IN_MILLISECONDS,25*IN_MILLISECONDS); + } else m_uiStaggeringStompTimer -= uiDiff; + + if (m_uiSummonTimer <= uiDiff) + { + if (m_uiSummonCount > 0) + { + me->SummonCreature(NPC_SNOBOLD_VASSAL,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),0,TEMPSUMMON_CORPSE_DESPAWN); + DoScriptText(SAY_SNOBOLLED,me); + } + m_uiSummonTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiSummonTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + }; + +}; + +
class mob_snobold_vassal : public CreatureScript +{ +public: + mob_snobold_vassal() : CreatureScript("mob_snobold_vassal") { } + + CreatureAI* GetAI(Creature* pCreature) const + { + return new mob_snobold_vassalAI(pCreature); + } + + struct mob_snobold_vassalAI : public ScriptedAI + { + mob_snobold_vassalAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (InstanceScript*)pCreature->GetInstanceScript(); + if (m_pInstance) + m_pInstance->SetData(DATA_SNOBOLD_COUNT, INCREASE); + } + + InstanceScript* m_pInstance; + uint32 m_uiFireBombTimer; + uint32 m_uiBatterTimer; + uint32 m_uiHeadCrackTimer; + uint64 m_uiBossGUID; + uint64 m_uiTargetGUID; + bool m_bTargetDied; + + void Reset() + { + m_uiFireBombTimer = 15000; + m_uiBatterTimer = 5000; + m_uiHeadCrackTimer = 25000; + + m_uiTargetGUID = 0; + m_bTargetDied = false; + if (m_pInstance) + m_uiBossGUID = m_pInstance->GetData64(NPC_GORMOK); + //Workaround for Snobold + me->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + } + + void EnterCombat(Unit *pWho) + { + m_uiTargetGUID = pWho->GetGUID(); + me->TauntApply(pWho); + DoCast(pWho, SPELL_SNOBOLLED); + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (pDoneBy->GetGUID()==m_uiTargetGUID) + uiDamage = 0; + } + + void MovementInform(uint32 uiType, uint32 uiId) + { + if(uiType != POINT_MOTION_TYPE) return; + + switch (uiId) + { + case 0: // JUMP!? Fuck! THAT'S BEEZARR! Would someone PLEASE make MotionMaster->Move* work better? + if (m_bTargetDied) + me->ForcedDespawn(); + break; + } + } + + void JustDied(Unit* pKiller) + { + if (Unit *pTarget = Unit::GetPlayer(*me,m_uiTargetGUID)) + if (pTarget->isAlive()) + pTarget->RemoveAurasDueToSpell(SPELL_SNOBOLLED); + if (m_pInstance) + m_pInstance->SetData(DATA_SNOBOLD_COUNT, DECREASE); + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_bTargetDied || !UpdateVictim()) + return; + + if (Unit* pTarget = Unit::GetPlayer(*me,m_uiTargetGUID)) + if (!pTarget->isAlive()) + if (m_pInstance) + if (Unit* pGormok = Unit::GetCreature(*me,m_pInstance->GetData64(NPC_GORMOK))) + { + if (pGormok->isAlive()) + { + SetCombatMovement(false); + m_bTargetDied = true; + me->GetMotionMaster()->MoveJump(pGormok->GetPositionX(),pGormok->GetPositionY(),pGormok->GetPositionZ(),15.0f,15.0f); + } + else + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + m_uiTargetGUID = pTarget->GetGUID(); + me->GetMotionMaster()->MoveJump(pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),15.0f,15.0f); + } + } + } + + if (m_uiFireBombTimer < uiDiff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_FIRE_BOMB); + m_uiFireBombTimer = 20000; + } + else m_uiFireBombTimer -= uiDiff; + + if (m_uiBatterTimer < uiDiff) + { + if (Unit *pTarget = Unit::GetPlayer(*me,m_uiTargetGUID)) + DoCast(pTarget, SPELL_BATTER); + m_uiBatterTimer = 10000; + } + else m_uiBatterTimer -= uiDiff; + + if (m_uiHeadCrackTimer < uiDiff) + { + if (Unit *pTarget = Unit::GetPlayer(*me,m_uiTargetGUID)) + DoCast(pTarget, SPELL_HEAD_CRACK); + m_uiHeadCrackTimer = 35000; + } + else m_uiHeadCrackTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + }; + +}; + + +struct boss_jormungarAI : public ScriptedAI +{ + boss_jormungarAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (InstanceScript*)pCreature->GetInstanceScript(); + } + + InstanceScript* m_pInstance; + + uint32 m_uiSisterID; + + uint32 m_uiModelStationary; + uint32 m_uiModelMobile; + + uint32 m_uiBiteSpell; + uint32 m_uiSpewSpell; + uint32 m_uiSpitSpell; + uint32 m_uiSpraySpell; + + uint32 m_uiBiteTimer; + uint32 m_uiSpewTimer; + uint32 m_uiSlimePoolTimer; + uint32 m_uiSpitTimer; + uint32 m_uiSprayTimer; + uint32 m_uiSweepTimer; + uint32 m_uiSubmergeTimer; + uint8 m_uiStage; + bool m_bEnraged; + + void Reset() + { + m_bEnraged = false; + m_uiBiteTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + m_uiSpewTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + m_uiSlimePoolTimer = 15*IN_MILLISECONDS; + m_uiSpitTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + m_uiSprayTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + m_uiSweepTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } + + void JustDied(Unit* pKiller) + { + if (m_pInstance) + if (Creature* pSister = Unit::GetCreature((*me),m_pInstance->GetData64(m_uiSisterID))) + if (!pSister->isAlive()) + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, SNAKES_DONE); + else + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, SNAKES_SPECIAL); + } + + void JustReachedHome() + { + if (m_pInstance && m_pInstance->GetData(TYPE_NORTHREND_BEASTS) != FAIL) + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, FAIL); + me->ForcedDespawn(); + } + + void KilledUnit(Unit *pWho) + { + if (pWho->GetTypeId() == TYPEID_PLAYER) + { + if (m_pInstance) + m_pInstance->SetData(DATA_TRIBUTE_TO_IMMORTALITY_ELEGIBLE, 0); + } + } + + void EnterCombat(Unit* pWho) + { + me->SetInCombatWithZone(); + if (m_pInstance) + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, SNAKES_IN_PROGRESS); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) return; + + if (m_pInstance && m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == SNAKES_SPECIAL && !m_bEnraged) + { + DoScriptText(SAY_EMERGE,me); + me->RemoveAurasDueToSpell(SPELL_SUBMERGE_0); + me->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + DoCast(SPELL_ENRAGE); + m_bEnraged = true; + DoScriptText(SAY_BERSERK,me); + switch (m_uiStage) + { + case 0: break; + case 4: + m_uiStage = 5; + m_uiSubmergeTimer = 5*IN_MILLISECONDS; + default: + m_uiStage = 7; + } + } + + switch (m_uiStage) + { + case 0: // Mobile + if (m_uiBiteTimer <= uiDiff) + { + DoCastVictim(m_uiBiteSpell); + m_uiBiteTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiBiteTimer -= uiDiff; + + if (m_uiSpewTimer <= uiDiff) + { + DoCastAOE(m_uiSpewSpell); + m_uiSpewTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiSpewTimer -= uiDiff; + + if (m_uiSlimePoolTimer <= uiDiff) + { + /* Spell summon has only 30s duration */ + //DoCast(SUMMON_SLIME_POOL); + me->SummonCreature(NPC_SLIME_POOL,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),0); + m_uiSlimePoolTimer = 30*IN_MILLISECONDS; + } else m_uiSlimePoolTimer -= uiDiff; + + if (m_uiSubmergeTimer <= uiDiff && !m_bEnraged) + { + m_uiStage = 1; + m_uiSubmergeTimer = 5*IN_MILLISECONDS; + } else m_uiSubmergeTimer -= uiDiff; + + DoMeleeAttackIfReady(); + break; + case 1: // Submerge + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + DoCast(me,SPELL_SUBMERGE_0); + DoScriptText(SAY_SUBMERGE,me); + me->GetMotionMaster()->MovePoint(0,ToCCommonLoc[1].GetPositionX()+urand(0,80)-40,ToCCommonLoc[1].GetPositionY()+urand(0,80)-40,ToCCommonLoc[1].GetPositionZ()); + m_uiStage = 2; + case 2: // Wait til emerge + if (m_uiSubmergeTimer <= uiDiff) + { + m_uiStage = 3; + m_uiSubmergeTimer = 50*IN_MILLISECONDS; + } else m_uiSubmergeTimer -= uiDiff; + break; + case 3: // Emerge + me->SetDisplayId(m_uiModelStationary); + DoScriptText(SAY_EMERGE,me); + me->RemoveAurasDueToSpell(SPELL_SUBMERGE_0); + DoCast(me,SPELL_EMERGE_0); + me->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE); + SetCombatMovement(false); + me->GetMotionMaster()->MoveIdle(); + m_uiStage = 4; + break; + case 4: // Stationary + if (m_uiSprayTimer <= uiDiff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,m_uiSpraySpell); + m_uiSprayTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiSprayTimer -= uiDiff; + + if (m_uiSweepTimer <= uiDiff) + { + DoCastAOE(SPELL_SWEEP_0); + m_uiSweepTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiSweepTimer -= uiDiff; + + if (m_uiSubmergeTimer <= uiDiff) + { + m_uiStage = 5; + m_uiSubmergeTimer = 10*IN_MILLISECONDS; + } else m_uiSubmergeTimer -= uiDiff; + + DoSpellAttackIfReady(m_uiSpitSpell); + break; + case 5: // Submerge + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + DoCast(me,SPELL_SUBMERGE_0); + DoScriptText(SAY_SUBMERGE,me); + me->GetMotionMaster()->MovePoint(0,ToCCommonLoc[1].GetPositionX()+urand(0,80)-40,ToCCommonLoc[1].GetPositionY()+urand(0,80)-40,ToCCommonLoc[1].GetPositionZ()); + m_uiStage = 6; + case 6: // Wait til emerge + if (m_uiSubmergeTimer <= uiDiff) + { + m_uiStage = 7; + m_uiSubmergeTimer = 45*IN_MILLISECONDS; + } else m_uiSubmergeTimer -= uiDiff; + break; + case 7: // Emerge + me->SetDisplayId(m_uiModelMobile); + DoScriptText(SAY_EMERGE,me); + me->RemoveAurasDueToSpell(SPELL_SUBMERGE_0); + DoCast(me,SPELL_EMERGE_0); + me->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE); + SetCombatMovement(true); + me->GetMotionMaster()->MoveChase(me->getVictim()); + m_uiStage = 0; + break; + } + } +}; + +
class boss_acidmaw : public CreatureScript +{ + public: + boss_acidmaw() : CreatureScript("boss_acidmaw") { } + + CreatureAI* GetAI(Creature* pCreature) const + { + return new boss_acidmawAI(pCreature); + } + + struct boss_acidmawAI : public boss_jormungarAI + { + boss_acidmawAI(Creature* pCreature) : boss_jormungarAI(pCreature) { } + + void Reset() + { + boss_jormungarAI::Reset(); + m_uiBiteSpell = SPELL_PARALYTIC_BITE; + m_uiSpewSpell = SPELL_ACID_SPEW; + m_uiSpitSpell = SPELL_ACID_SPIT; + m_uiSpraySpell = SPELL_PARALYTIC_SPRAY; + m_uiModelStationary = MODEL_ACIDMAW_STATIONARY; + m_uiModelMobile = MODEL_ACIDMAW_MOBILE; + m_uiSisterID = NPC_DREADSCALE; + + m_uiSubmergeTimer = 500; + DoCast(me,SPELL_SUBMERGE_0); + m_uiStage = 2; + } + }; + +}; + +
class boss_dreadscale : public CreatureScript +{ +public: + boss_dreadscale() : CreatureScript("boss_dreadscale") { } + + CreatureAI* GetAI(Creature* pCreature) const + { + return new boss_dreadscaleAI(pCreature); + } + + struct boss_dreadscaleAI : public boss_jormungarAI + { + boss_dreadscaleAI(Creature* pCreature) : boss_jormungarAI(pCreature) { } + + void Reset() + { + boss_jormungarAI::Reset(); + m_uiBiteSpell = SPELL_BURNING_BITE; + m_uiSpewSpell = SPELL_MOLTEN_SPEW; + m_uiSpitSpell = SPELL_FIRE_SPIT; + m_uiSpraySpell = SPELL_BURNING_SPRAY; + m_uiModelStationary = MODEL_DREADSCALE_STATIONARY; + m_uiModelMobile = MODEL_DREADSCALE_MOBILE; + m_uiSisterID = NPC_ACIDMAW; + + m_uiSubmergeTimer = 45*IN_MILLISECONDS; + m_uiStage = 0; + } + }; + +}; + +
class mob_slime_pool : public CreatureScript +{ +public: + mob_slime_pool() : CreatureScript("mob_slime_pool") { } + + CreatureAI* GetAI(Creature* pCreature) const + { + return new mob_slime_poolAI(pCreature); + } + + struct mob_slime_poolAI : public ScriptedAI + { + mob_slime_poolAI(Creature *pCreature) : ScriptedAI(pCreature) + { + } + + bool casted; + void Reset() + { + casted = false; + me->SetReactState(REACT_PASSIVE); + me->ForcedDespawn(60*IN_MILLISECONDS); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!casted) + { + casted = true; + DoCast(me,SPELL_SLIME_POOL_EFFECT); + } + } + }; + +}; +
class boss_icehowl : public CreatureScript +{ +public: + boss_icehowl() : CreatureScript("boss_icehowl") { } + + CreatureAI* GetAI(Creature* pCreature) const + { + return new boss_icehowlAI(pCreature); + } + + struct boss_icehowlAI : public ScriptedAI + { + boss_icehowlAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (InstanceScript*)pCreature->GetInstanceScript(); + } + + InstanceScript* m_pInstance; + + uint32 m_uiFerociousButtTimer; + uint32 m_uiArticBreathTimer; + uint32 m_uiWhirlTimer; + uint32 m_uiMassiveCrashTimer; + uint32 m_uiTrampleTimer; + float m_fTrampleTargetX,m_fTrampleTargetY,m_fTrampleTargetZ; + uint64 m_uiTrampleTargetGUID; + bool m_bMovementStarted; + bool m_bMovementFinish; + bool m_bTrampleCasted; + uint8 m_uiStage; + Unit* pTarget; + + void Reset() + { + m_uiFerociousButtTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + m_uiArticBreathTimer = urand(25*IN_MILLISECONDS,40*IN_MILLISECONDS); + m_uiWhirlTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + m_uiMassiveCrashTimer = 30*IN_MILLISECONDS; + m_uiTrampleTimer = IN_MILLISECONDS; + m_bMovementStarted = false; + m_bMovementFinish = false; + m_bTrampleCasted = false; + m_uiTrampleTargetGUID = 0; + m_fTrampleTargetX = 0; + m_fTrampleTargetY = 0; + m_fTrampleTargetZ = 0; + m_uiStage = 0; + } + + void JustDied(Unit* pKiller) + { + if (m_pInstance) + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, ICEHOWL_DONE); + } + + void MovementInform(uint32 uiType, uint32 uiId) + { + if(uiType != POINT_MOTION_TYPE) return; + + switch (uiId) + { + case 0: // JUMP!? Fuck! THAT'S BEEZARR! Would someone PLEASE make MotionMaster->Move* work better? + if (me->GetDistance2d(ToCCommonLoc[1].GetPositionX(),ToCCommonLoc[1].GetPositionY()) < 6.0f) + { + // Middle of the room + m_uiStage = 1; + } + else + { + // Landed from Hop backwards (start trample) + if(Unit* pTarget = Unit::GetPlayer(*me,m_uiTrampleTargetGUID)) + { + m_uiStage = 4; + } else m_uiStage = 6; + } + break; + case 1: // Finish trample + m_bMovementFinish = true; + break; + } + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, FAIL); + me->ForcedDespawn(); + } + + void KilledUnit(Unit *pWho) + { + if (pWho->GetTypeId() == TYPEID_PLAYER) + { + if (m_pInstance) + m_pInstance->SetData(DATA_TRIBUTE_TO_IMMORTALITY_ELEGIBLE, 0); + } + } + + void EnterCombat(Unit* pWho) + { + if (m_pInstance) + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, ICEHOWL_IN_PROGRESS); + me->SetInCombatWithZone(); + } + + void SpellHitTarget(Unit* target, const SpellEntry* spell) + { + if(spell->Id == SPELL_TRAMPLE && target->GetTypeId() == TYPEID_PLAYER) + { + if (!m_bTrampleCasted) + { + DoCast(me, SPELL_FROTHING_RAGE, true); + m_bTrampleCasted = true; + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + switch (m_uiStage) + { + case 0: + if (m_uiFerociousButtTimer <= uiDiff) + { + DoCastVictim(SPELL_FEROCIOUS_BUTT); + m_uiFerociousButtTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiFerociousButtTimer -= uiDiff; + + if (m_uiArticBreathTimer <= uiDiff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_ARCTIC_BREATH); + m_uiArticBreathTimer = urand(25*IN_MILLISECONDS,40*IN_MILLISECONDS); + } else m_uiArticBreathTimer -= uiDiff; + + if (m_uiWhirlTimer <= uiDiff) + { + DoCastAOE(SPELL_WHIRL); + m_uiWhirlTimer = urand(15*IN_MILLISECONDS,30*IN_MILLISECONDS); + } else m_uiWhirlTimer -= uiDiff; + + if (m_uiMassiveCrashTimer <= uiDiff) + { + me->GetMotionMaster()->MoveJump(ToCCommonLoc[1].GetPositionX(),ToCCommonLoc[1].GetPositionY(),ToCCommonLoc[1].GetPositionZ(),10.0f,20.0f); // 1: Middle of the room + m_uiStage = 7; //Invalid (Do nothing more than move) + m_uiMassiveCrashTimer = 30*IN_MILLISECONDS; + } else m_uiMassiveCrashTimer -= uiDiff; + + DoMeleeAttackIfReady(); + break; + case 1: + DoCastAOE(SPELL_MASSIVE_CRASH); + m_uiStage = 2; + break; + case 2: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + m_uiTrampleTargetGUID = pTarget->GetGUID(); + me->SetUInt64Value(UNIT_FIELD_TARGET, m_uiTrampleTargetGUID); + DoScriptText(SAY_TRAMPLE_STARE,me,pTarget); + m_bTrampleCasted = false; + SetCombatMovement(false); + me->GetMotionMaster()->MoveIdle(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_uiTrampleTimer = 4*IN_MILLISECONDS; + m_uiStage = 3; + } else m_uiStage = 6; + break; + case 3: + if (m_uiTrampleTimer <= uiDiff) + { + if(Unit* pTarget = Unit::GetPlayer(*me,m_uiTrampleTargetGUID)) + { + m_bTrampleCasted = false; + m_bMovementStarted = true; + m_fTrampleTargetX = pTarget->GetPositionX(); + m_fTrampleTargetY = pTarget->GetPositionY(); + m_fTrampleTargetZ = pTarget->GetPositionZ(); + me->GetMotionMaster()->MoveJump(2*me->GetPositionX()-m_fTrampleTargetX, + 2*me->GetPositionY()-m_fTrampleTargetY, + me->GetPositionZ(), + 10.0f,20.0f); // 2: Hop Backwards + m_uiStage = 7; //Invalid (Do nothing more than move) + } else m_uiStage = 6; + } else m_uiTrampleTimer -= uiDiff; + break; + case 4: + DoScriptText(SAY_TRAMPLE_START,me); + me->GetMotionMaster()->MoveCharge(m_fTrampleTargetX,m_fTrampleTargetY,m_fTrampleTargetZ+2, 42, 1); + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + m_uiStage = 5; + break; + case 5: + if (m_bMovementFinish) + { + if (m_uiTrampleTimer <= uiDiff) DoCastAOE(SPELL_TRAMPLE); + m_bMovementFinish = false; + m_uiStage = 6; + return; + } + if (m_uiTrampleTimer <= uiDiff) + { + Map::PlayerList const &lPlayers = me->GetMap()->GetPlayers(); + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + if (Unit* pPlayer = itr->getSource()) + if (pPlayer->isAlive() && pPlayer->IsWithinDistInMap(me, 6.0f)) + { + DoCastAOE(SPELL_TRAMPLE); + m_uiTrampleTimer = IN_MILLISECONDS; + break; + } + } + } else m_uiTrampleTimer -= uiDiff; + break; + case 6: + if (!m_bTrampleCasted) + { + DoCast(me,SPELL_STAGGERED_DAZE); + DoScriptText(SAY_TRAMPLE_FAIL,me); + } + m_bMovementStarted = false; + me->GetMotionMaster()->MovementExpired(); + me->GetMotionMaster()->MoveChase(me->getVictim()); + SetCombatMovement(true); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_uiStage = 0; + break; + } + } + }; + +}; + + +void AddSC_boss_northrend_beasts() +{ + new boss_gormok(); + new mob_snobold_vassal(); + new boss_acidmaw(); + new boss_dreadscale(); + new mob_slime_pool(); + new boss_icehowl(); +} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp new file mode 100644 index 00000000000..d755aa821bc --- /dev/null +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp @@ -0,0 +1,669 @@ +/* Copyright (C) 2006 - 2010 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> + * 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 + */ + +/* ScriptData +SDName: trial_of_the_crusader +SD%Complete: ??% +SDComment: based on /dev/rsa +SDCategory: Crusader Coliseum +EndScriptData */ + +// Known bugs: +// - They should be floating but they aren't respecting the floor =( +// - Lacks the powering up effect that leads to Empowering +// - There's a workaround for the shared life effect + +#include "ScriptPCH.h" +#include "trial_of_the_crusader.h" + +enum Yells +{ + SAY_AGGRO = -1649040, + SAY_DEATH = -1649041, + SAY_BERSERK = -1649042, + EMOTE_SHIELD = -1649043, + SAY_SHIELD = -1649044, + SAY_KILL1 = -1649045, + SAY_KILL2 = -1649046, + EMOTE_LIGHT_VORTEX = -1649047, + SAY_LIGHT_VORTEX = -1649048, + EMOTE_DARK_VORTEX = -1649049, + SAY_DARK_VORTEX = -1649050, +}; + +enum Equipment +{ + EQUIP_MAIN_1 = 49303, + EQUIP_OFFHAND_1 = 47146, + EQUIP_RANGED_1 = 47267, + EQUIP_MAIN_2 = 45990, + EQUIP_OFFHAND_2 = 47470, + EQUIP_RANGED_2 = 47267, + EQUIP_DONE = EQUIP_NO_CHANGE, +}; + +enum Summons +{ + NPC_DARK_ESSENCE = 34567, + NPC_LIGHT_ESSENCE = 34568, + + NPC_UNLEASHED_DARK = 34628, + NPC_UNLEASHED_LIGHT = 34630, +}; + +enum BossSpells +{ + SPELL_LIGHT_TWIN_SPIKE = 66075, + SPELL_LIGHT_SURGE = 65766, + SPELL_LIGHT_SHIELD = 65858, + SPELL_LIGHT_TWIN_PACT = 65876, + SPELL_LIGHT_VORTEX = 66046, + SPELL_LIGHT_TOUCH = 67297, + + SPELL_DARK_TWIN_SPIKE = 66069, + SPELL_DARK_SURGE = 65768, + SPELL_DARK_SHIELD = 65874, + SPELL_DARK_TWIN_PACT = 65875, + SPELL_DARK_VORTEX = 66058, + SPELL_DARK_TOUCH = 67282, + + SPELL_TWIN_POWER = 65916, + SPELL_LIGHT_ESSENCE = 65686, + SPELL_DARK_ESSENCE = 65684, + SPELL_BERSERK = 64238, + SPELL_NONE = 0, + + SPELL_EMPOWERED_DARK = 67215, + SPELL_EMPOWERED_LIGHT = 67218, + + SPELL_UNLEASHED_DARK = 65808, + SPELL_UNLEASHED_LIGHT = 65795, + //PowerUp 67604 +}; + +enum Actions +{ + ACTION_VORTEX, + ACTION_PACT +}; + + +/*###### +## boss_twin_base +######*/ + +struct boss_twin_baseAI : public ScriptedAI +{ + boss_twin_baseAI(Creature* pCreature) : ScriptedAI(pCreature), Summons(me) + { + m_pInstance = (InstanceScript*)pCreature->GetInstanceScript(); + } + + InstanceScript* m_pInstance; + SummonList Summons; + + uint8 m_uiStage; + bool m_bIsBerserk; + uint8 m_uiWaveCount; + uint32 m_uiColorballsTimer; + uint32 m_uiSpecialAbilityTimer; + uint32 m_uiSpikeTimer; + uint32 m_uiTouchTimer; + uint32 m_uiBerserkTimer; + + uint32 m_uiVortexSay; + uint32 m_uiVortexEmote; + uint32 m_uiSisterNpcId; + uint32 m_uiColorballNpcId; + uint32 m_uiEssenceNpcId; + uint32 m_uiMyEssenceSpellId; + uint32 m_uiOtherEssenceSpellId; + uint32 m_uiEmpoweredWeaknessSpellId; + uint32 m_uiSurgeSpellId; + uint32 m_uiVortexSpellId; + uint32 m_uiShieldSpellId; + uint32 m_uiTwinPactSpellId; + uint32 m_uiSpikeSpellId; + uint32 m_uiTouchSpellId; + + Position HomeLocation; + Position EssenceLocation[2]; + + void Reset() { + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_PASSIVE); + /* Uncomment this once that they are flying above the ground + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SetFlying(true); */ + m_bIsBerserk = false; + + m_uiWaveCount = 1; + m_uiColorballsTimer = 15*IN_MILLISECONDS; + m_uiSpecialAbilityTimer = MINUTE*IN_MILLISECONDS; + m_uiSpikeTimer = 20*IN_MILLISECONDS; + m_uiTouchTimer = urand(10,15)*IN_MILLISECONDS; + m_uiBerserkTimer = IsHeroic() ? 6*MINUTE*IN_MILLISECONDS : 10*MINUTE*IN_MILLISECONDS; + + Summons.DespawnAll(); + } + + void JustReachedHome() + { + if (m_pInstance) + { + m_pInstance->SetData(TYPE_VALKIRIES, FAIL); + m_pInstance->SetData(DATA_HEALTH_TWIN_SHARED, me->GetMaxHealth()); + } + me->ForcedDespawn(); + } + + void MovementInform(uint32 uiType, uint32 uiId) + { + if(uiType != POINT_MOTION_TYPE) return; + + switch (uiId) + { + case 0: + me->GetMotionMaster()->MovePoint(1, HomeLocation.GetPositionX(), HomeLocation.GetPositionY(), HomeLocation.GetPositionZ()); + me->SetHomePosition(HomeLocation); + break; + case 1: + me->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_AGGRESSIVE); + me->SetInCombatWithZone(); + break; + } + } + + void KilledUnit(Unit* pWho) + { + if (pWho->GetTypeId() == TYPEID_PLAYER) + { + DoScriptText(urand(0,1) ? SAY_KILL1 : SAY_KILL2,me); + if (m_pInstance) + m_pInstance->SetData(DATA_TRIBUTE_TO_IMMORTALITY_ELEGIBLE, 0); + } + } + + void JustSummoned(Creature* pSummoned) + { + switch(pSummoned->GetEntry()) + { + case NPC_UNLEASHED_DARK: + case NPC_UNLEASHED_LIGHT: + pSummoned->SetCorpseDelay(0); + break; + } + Summons.Summon(pSummoned); + } + + void SummonedCreatureDespawn(Creature* pSummoned) + { + switch(pSummoned->GetEntry()) + { + case NPC_LIGHT_ESSENCE: + case NPC_DARK_ESSENCE: + Map* pMap = me->GetMap(); + Map::PlayerList const &lPlayers = pMap->GetPlayers(); + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + Unit* pPlayer = itr->getSource(); + if (!pPlayer) continue; + if (pPlayer->isAlive()) + if (pSummoned->GetEntry() == NPC_LIGHT_ESSENCE) + pPlayer->RemoveAurasDueToSpell(SPELL_LIGHT_ESSENCE); + if (pSummoned->GetEntry() == NPC_DARK_ESSENCE) + pPlayer->RemoveAurasDueToSpell(SPELL_DARK_ESSENCE); + } + break; + } + Summons.Despawn(pSummoned); + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (!me || !me->isAlive()) + return; + + if (pDoneBy->GetGUID() == me->GetGUID()) + return; + + if (pDoneBy->GetTypeId() == TYPEID_PLAYER) + { + if(pDoneBy->HasAura(m_uiOtherEssenceSpellId)) + uiDamage += uiDamage/2; + if(pDoneBy->HasAura(m_uiEmpoweredWeaknessSpellId)) + uiDamage += uiDamage; + else + if(pDoneBy->HasAura(m_uiMyEssenceSpellId)) + uiDamage /= 2; + } + + if (m_pInstance) + m_pInstance->SetData(DATA_HEALTH_TWIN_SHARED, me->GetHealth() >= uiDamage ? me->GetHealth() - uiDamage : 0); + } + + void SpellHit(Unit* caster, const SpellEntry* spell) + { + if (caster->ToCreature() == me) + if (spell->Effect[0] == 136) //Effect Heal + if (m_pInstance) + m_pInstance->SetData(DATA_HEALTH_TWIN_SHARED, me->GetHealth() + me->GetMaxHealth()*spell->EffectBasePoints[0]/100); + } + + void SummonColorballs(uint8 quantity) + { + float x0 = ToCCommonLoc[1].GetPositionX(), y0 = ToCCommonLoc[1].GetPositionY(), r = 47.0f; + float y = y0; + for (uint8 i = 0; i < quantity; i++) + { + float x = urand(x0-r,x0+r); + if (urand(0,1)) + y = y0 + sqrt(pow(r,2) - pow((x-x0),2)); + else + y = y0 - sqrt(pow(r,2) - pow((x-x0),2)); + me->SummonCreature(m_uiColorballNpcId,x,y,me->GetPositionZ(),TEMPSUMMON_CORPSE_DESPAWN); + } + } + + void JustDied(Unit* pKiller) + { + DoScriptText(SAY_DEATH,me); + if (m_pInstance) + { + m_pInstance->SetData(DATA_HEALTH_TWIN_SHARED, 0); + if (Creature* pSister = GetSister()) + if (!pSister->isAlive()) + { + m_pInstance->SetData(TYPE_VALKIRIES, DONE); + Summons.DespawnAll(); + } + else m_pInstance->SetData(TYPE_VALKIRIES, SPECIAL); + } + Summons.DespawnAll(); + } + + // Called when sister pointer needed + Creature* GetSister() + { + return Unit::GetCreature((*me),m_pInstance->GetData64(m_uiSisterNpcId)); + } + + void EnterCombat(Unit* pWho) + { + me->SetInCombatWithZone(); + if (m_pInstance) + { + m_pInstance->SetData(TYPE_VALKIRIES, IN_PROGRESS); + m_pInstance->SetData(DATA_HEALTH_TWIN_SHARED, me->GetMaxHealth()); + } + if (me->isAlive()) + { + me->SummonCreature(m_uiEssenceNpcId, EssenceLocation[0].GetPositionX(), EssenceLocation[0].GetPositionY(), EssenceLocation[0].GetPositionZ()); + me->SummonCreature(m_uiEssenceNpcId, EssenceLocation[1].GetPositionX(), EssenceLocation[1].GetPositionY(), EssenceLocation[1].GetPositionZ()); + } + DoScriptText(SAY_AGGRO,me); + DoCast(me,m_uiSurgeSpellId); + } + + void DoAction(const int32 action) + { + switch(action) + { + case ACTION_VORTEX: + m_uiStage = me->GetEntry() == NPC_LIGHTBANE ? 2 : 1; + break; + case ACTION_PACT: + m_uiStage = me->GetEntry() == NPC_LIGHTBANE ? 1 : 2; + DoCast(me,SPELL_TWIN_POWER); + break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance || !UpdateVictim()) + return; + + if (m_pInstance->GetData(DATA_HEALTH_TWIN_SHARED) != 0) + me->SetHealth(m_pInstance->GetData(DATA_HEALTH_TWIN_SHARED)); + else + me->SetHealth(1); + + switch (m_uiStage) + { + case 0: + break; + case 1: // Vortex + if (m_uiSpecialAbilityTimer <= uiDiff) + { + if (Creature* pSister = GetSister()) + pSister->AI()->DoAction(ACTION_VORTEX); + DoScriptText(m_uiVortexEmote,me); + DoScriptText(m_uiVortexSay,me); + DoCastAOE(m_uiVortexSpellId); + m_uiStage = 0; + m_uiSpecialAbilityTimer = MINUTE*IN_MILLISECONDS; + } else m_uiSpecialAbilityTimer -= uiDiff; + break; + case 2: // Shield+Pact + if (m_uiSpecialAbilityTimer <= uiDiff) + { + if (Creature* pSister = GetSister()) + pSister->AI()->DoAction(ACTION_PACT); + DoScriptText(EMOTE_SHIELD,me); + DoScriptText(SAY_SHIELD,me); + DoCast(me,m_uiShieldSpellId); + DoCast(me,m_uiTwinPactSpellId); + m_uiStage = 0; + m_uiSpecialAbilityTimer = MINUTE*IN_MILLISECONDS; + } m_uiSpecialAbilityTimer -= uiDiff; + break; + default: + break; + } + + if (m_uiSpikeTimer <= uiDiff) + { + DoCastVictim(m_uiSpikeSpellId); + m_uiSpikeTimer = 20*IN_MILLISECONDS; + } m_uiSpikeTimer -= uiDiff; + + if (IsHeroic() && m_uiTouchTimer <= uiDiff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,200,true,m_uiOtherEssenceSpellId)) + DoCast(pTarget,m_uiTouchSpellId); + m_uiTouchTimer = urand(10,15)*IN_MILLISECONDS; + } m_uiTouchTimer -= uiDiff; + + if (m_uiColorballsTimer <= uiDiff) + { + if (m_uiWaveCount >= 2) + { + SummonColorballs(12); + m_uiWaveCount = 0; + } + else + { + SummonColorballs(2); + m_uiWaveCount++; + } + m_uiColorballsTimer = 15*IN_MILLISECONDS; + } else m_uiColorballsTimer -= uiDiff; + + if (!m_bIsBerserk && m_uiBerserkTimer <= uiDiff) + { + DoCast(me,SPELL_BERSERK); + DoScriptText(SAY_BERSERK,me); + m_bIsBerserk = true; + } else m_uiBerserkTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +/*###### +## boss_fjola +######*/ +
class boss_fjola : public CreatureScript +{ +public: + boss_fjola() : CreatureScript("boss_fjola") { } + + CreatureAI* GetAI(Creature* pCreature) const + { + return new boss_fjolaAI(pCreature); + } + + struct boss_fjolaAI : public boss_twin_baseAI + { + boss_fjolaAI(Creature* pCreature) : boss_twin_baseAI(pCreature) {} + + void Reset() { + boss_twin_baseAI::Reset(); + SetEquipmentSlots(false, EQUIP_MAIN_1, EQUIP_OFFHAND_1, EQUIP_RANGED_1); + m_uiStage = 0; + m_uiVortexEmote = EMOTE_LIGHT_VORTEX; + m_uiVortexSay = SAY_LIGHT_VORTEX; + m_uiSisterNpcId = NPC_DARKBANE; + m_uiColorballNpcId = NPC_UNLEASHED_LIGHT; + m_uiEssenceNpcId = NPC_LIGHT_ESSENCE; + m_uiMyEssenceSpellId = SPELL_LIGHT_ESSENCE; + m_uiOtherEssenceSpellId = SPELL_DARK_ESSENCE; + m_uiEmpoweredWeaknessSpellId = SPELL_EMPOWERED_DARK; + m_uiSurgeSpellId = SPELL_LIGHT_SURGE; + m_uiVortexSpellId = SPELL_LIGHT_VORTEX; + m_uiShieldSpellId = SPELL_LIGHT_SHIELD; + m_uiTwinPactSpellId = SPELL_LIGHT_TWIN_PACT; + m_uiTouchSpellId = SPELL_LIGHT_TOUCH; + m_uiSpikeSpellId = SPELL_LIGHT_TWIN_SPIKE; + + HomeLocation = ToCCommonLoc[8]; + EssenceLocation[0] = TwinValkyrsLoc[2]; + EssenceLocation[1] = TwinValkyrsLoc[3]; + + if (m_pInstance) + { + m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, EVENT_START_TWINS_FIGHT); + } + } + + void EnterCombat(Unit* pWho) + { + boss_twin_baseAI::EnterCombat(pWho); + if (m_pInstance) + { + m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, EVENT_START_TWINS_FIGHT); + } + } + }; + +}; + + +/*###### +## boss_eydis +######*/ +
class boss_eydis : public CreatureScript +{ +public: + boss_eydis() : CreatureScript("boss_eydis") { } + + CreatureAI* GetAI(Creature* pCreature) const + { + return new boss_eydisAI(pCreature); + } + + struct boss_eydisAI : public boss_twin_baseAI + { + boss_eydisAI(Creature* pCreature) : boss_twin_baseAI(pCreature) {} + + void Reset() { + boss_twin_baseAI::Reset(); + SetEquipmentSlots(false, EQUIP_MAIN_2, EQUIP_OFFHAND_2, EQUIP_RANGED_2); + m_uiStage = 1; + m_uiVortexEmote = EMOTE_DARK_VORTEX; + m_uiVortexSay = SAY_DARK_VORTEX; + m_uiSisterNpcId = NPC_LIGHTBANE; + m_uiColorballNpcId = NPC_UNLEASHED_DARK; + m_uiEssenceNpcId = NPC_DARK_ESSENCE; + m_uiMyEssenceSpellId = SPELL_DARK_ESSENCE; + m_uiOtherEssenceSpellId = SPELL_LIGHT_ESSENCE; + m_uiEmpoweredWeaknessSpellId = SPELL_EMPOWERED_LIGHT; + m_uiSurgeSpellId = SPELL_DARK_SURGE; + m_uiVortexSpellId = SPELL_DARK_VORTEX; + m_uiShieldSpellId = SPELL_DARK_SHIELD; + m_uiTwinPactSpellId = SPELL_DARK_TWIN_PACT; + m_uiTouchSpellId = SPELL_DARK_TOUCH; + m_uiSpikeSpellId = SPELL_DARK_TWIN_SPIKE; + + HomeLocation = ToCCommonLoc[9]; + EssenceLocation[0] = TwinValkyrsLoc[0]; + EssenceLocation[1] = TwinValkyrsLoc[1]; + } + }; + +}; + +
class mob_essence_of_twin : public CreatureScript +{ +public: + mob_essence_of_twin() : CreatureScript("mob_essence_of_twin") { } + + bool OnGossipHello(Player* pPlayer, Creature* pCreature) + { + switch(pCreature->GetEntry()) + { + case NPC_LIGHT_ESSENCE: + if (pPlayer || pPlayer->HasAura(SPELL_DARK_ESSENCE)) + pPlayer->RemoveAura(SPELL_DARK_ESSENCE); + pPlayer->CastSpell(pPlayer,SPELL_LIGHT_ESSENCE,true); + break; + case NPC_DARK_ESSENCE: + if (pPlayer || pPlayer->HasAura(SPELL_LIGHT_ESSENCE)) + pPlayer->RemoveAura(SPELL_LIGHT_ESSENCE); + pPlayer->CastSpell(pPlayer,SPELL_DARK_ESSENCE,true); + break; + } + pPlayer->CLOSE_GOSSIP_MENU(); + return true; + } +}; + + +struct mob_unleashed_ballAI : public ScriptedAI +{ + mob_unleashed_ballAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (InstanceScript*)pCreature->GetInstanceScript(); + } + + InstanceScript* m_pInstance; + uint32 m_uiRangeCheckTimer; + + void MoveToNextPoint() + { + float x0 = ToCCommonLoc[1].GetPositionX(), y0 = ToCCommonLoc[1].GetPositionY(), r = 47.0f; + float y = y0; + float x = urand(x0-r,x0+r); + if (urand(0,1)) + y = y0 + sqrt(pow(r,2) - pow((x-x0),2)); + else + y = y0 - sqrt(pow(r,2) - pow((x-x0),2)); + me->GetMotionMaster()->MovePoint(0,x,y,me->GetPositionZ()); + } + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_PASSIVE); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SetFlying(true); + SetCombatMovement(false); + MoveToNextPoint(); + m_uiRangeCheckTimer = IN_MILLISECONDS; + } + + void MovementInform(uint32 uiType, uint32 uiId) + { + if(uiType != POINT_MOTION_TYPE) return; + + switch (uiId) + { + case 0: + if (urand(0,3) == 0) + MoveToNextPoint(); + else + me->DisappearAndDie(); + break; + } + } +}; +
class mob_unleashed_dark : public CreatureScript +{ +public: + mob_unleashed_dark() : CreatureScript("mob_unleashed_dark") { } + + CreatureAI* GetAI(Creature *pCreature) const + { + return new mob_unleashed_darkAI(pCreature); + } + + struct mob_unleashed_darkAI : public mob_unleashed_ballAI + { + mob_unleashed_darkAI(Creature *pCreature) : mob_unleashed_ballAI(pCreature) {} + + void UpdateAI(const uint32 uiDiff) + { + if (m_uiRangeCheckTimer < uiDiff) + { + if (Unit *pTarget = me->SelectNearestTarget(2.0f)) + if (pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive()) + { + DoCastAOE(SPELL_UNLEASHED_DARK); + me->GetMotionMaster()->MoveIdle(); + me->ForcedDespawn(500); + } + m_uiRangeCheckTimer = IN_MILLISECONDS; + } + else m_uiRangeCheckTimer -= uiDiff; + } + }; + +}; + +
class mob_unleashed_light : public CreatureScript +{ +public: + mob_unleashed_light() : CreatureScript("mob_unleashed_light") { } + + CreatureAI* GetAI(Creature *pCreature) const + { + return new mob_unleashed_lightAI(pCreature); + } + + struct mob_unleashed_lightAI : public mob_unleashed_ballAI + { + mob_unleashed_lightAI(Creature *pCreature) : mob_unleashed_ballAI(pCreature) {} + + void UpdateAI(const uint32 uiDiff) + { + if (m_uiRangeCheckTimer < uiDiff) + { + if (Unit *pTarget = me->SelectNearestTarget(2.0f)) + if (pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive()) + { + DoCastAOE(SPELL_UNLEASHED_LIGHT); + me->GetMotionMaster()->MoveIdle(); + me->ForcedDespawn(500); + } + m_uiRangeCheckTimer = IN_MILLISECONDS; + } + else m_uiRangeCheckTimer -= uiDiff; + } + }; + +}; + + +void AddSC_boss_twin_valkyr() +{ + new boss_fjola(); + new boss_eydis(); + new mob_unleashed_light(); + new mob_unleashed_dark(); + new mob_essence_of_twin(); +} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp new file mode 100644 index 00000000000..0419ec380d7 --- /dev/null +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp @@ -0,0 +1,629 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> +* 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 +*/ + +/* ScriptData +SDName: instance_trial_of_the_crusader +SD%Complete: 80% +SDComment: by /dev/rsa +SDCategory: Trial of the Crusader +EndScriptData */ + +#include "ScriptPCH.h" +#include "trial_of_the_crusader.h" +
class instance_trial_of_the_crusader : public InstanceMapScript +{ +public: + instance_trial_of_the_crusader() : InstanceMapScript("instance_trial_of_the_crusader", 649) { } + + InstanceScript* GetInstanceScript(InstanceMap* pMap) const + { + return new instance_trial_of_the_crusader_InstanceMapScript(pMap); + } + + struct instance_trial_of_the_crusader_InstanceMapScript : public InstanceScript + { + instance_trial_of_the_crusader_InstanceMapScript(Map* pMap) : InstanceScript(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTERS]; + uint32 m_uiTrialCounter; + uint32 m_uiEvent; + uint32 m_uiEventTimer; + uint32 m_uiEventNPCId; + uint32 m_uiNorthrendBeasts; + std::string m_strInstData; + bool m_bNeedSave; + + uint32 m_uiDataDamageTwin; + uint32 m_uiFjolaCasting; + uint32 m_uiEydisCasting; + + uint64 m_uiBarrentGUID; + uint64 m_uiTirionGUID; + uint64 m_uiFizzlebangGUID; + uint64 m_uiGarroshGUID; + uint64 m_uiVarianGUID; + + uint64 m_uiGormokGUID; + uint64 m_uiAcidmawGUID; + uint64 m_uiDreadscaleGUID; + uint64 m_uiIcehowlGUID; + uint64 m_uiJaraxxusGUID; + uint64 m_uiChampionsControllerGUID; + uint64 m_uiDarkbaneGUID; + uint64 m_uiLightbaneGUID; + uint64 m_uiAnubarakGUID; + + uint64 m_uiCrusadersCacheGUID; + uint64 m_uiFloorGUID; + + uint64 m_uiTributeChestGUID; + + uint64 m_uiMainGateDoorGUID; + uint64 m_uiEastPortcullisGUID; + uint64 m_uiWebDoorGUID; + + // Achievement stuff + uint32 m_uiNotOneButTwoJormungarsTimer; + uint32 m_uiResilienceWillFixItTimer; + uint8 m_uiSnoboldCount; + uint8 m_uiMistressOfPainCount; + bool m_bTributeToImmortalityElegible; + std::list<uint32> m_vScarabTimeOfDeath; + + void Initialize() + { + for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + m_auiEncounter[i] = NOT_STARTED; + + m_uiTrialCounter = 50; + m_uiEvent = 0; + + m_uiTributeChestGUID = 0; + m_uiDataDamageTwin = 0; + + m_uiMainGateDoorGUID = 0; + m_uiEastPortcullisGUID = 0; + m_uiWebDoorGUID = 0; + + m_uiNorthrendBeasts = NOT_STARTED; + + m_uiEventTimer = 1000; + + m_uiNotOneButTwoJormungarsTimer = 0; + m_uiResilienceWillFixItTimer = 0; + m_uiSnoboldCount = 0; + m_uiMistressOfPainCount = 0; + m_bTributeToImmortalityElegible = true; + + m_bNeedSave = false; + } + + bool IsEncounterInProgress() const + { + for(uint8 i = 0; i < MAX_ENCOUNTERS ; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + return true; + return false; + } + + void OnPlayerEnter(Player *m_player) + { + if (instance->IsHeroic()) + { + m_player->SendUpdateWorldState(UPDATE_STATE_UI_SHOW,1); + m_player->SendUpdateWorldState(UPDATE_STATE_UI_COUNT, GetData(TYPE_COUNTER)); + } + } + + bool IsRaidWiped() + { + Map::PlayerList const &players = instance->GetPlayers(); + + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + { + if(Player* pPlayer = i->getSource()) + { + if(pPlayer->isAlive()) + return false; + } + } + return true; + } + + void OpenDoor(uint64 guid) + { + if(!guid) return; + GameObject* pGo = instance->GetGameObject(guid); + if(pGo) pGo->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + } + + void CloseDoor(uint64 guid) + { + if(!guid) return; + GameObject* pGo = instance->GetGameObject(guid); + if(pGo) pGo->SetGoState(GO_STATE_READY); + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case NPC_BARRENT: m_uiBarrentGUID = pCreature->GetGUID(); break; + case NPC_TIRION: m_uiTirionGUID = pCreature->GetGUID(); break; + case NPC_FIZZLEBANG: m_uiFizzlebangGUID = pCreature->GetGUID(); break; + case NPC_GARROSH: m_uiGarroshGUID = pCreature->GetGUID(); break; + case NPC_VARIAN: m_uiVarianGUID = pCreature->GetGUID(); break; + + case NPC_GORMOK: m_uiGormokGUID = pCreature->GetGUID(); break; + case NPC_ACIDMAW: m_uiAcidmawGUID = pCreature->GetGUID(); break; + case NPC_DREADSCALE: m_uiDreadscaleGUID = pCreature->GetGUID(); break; + case NPC_ICEHOWL: m_uiIcehowlGUID = pCreature->GetGUID(); break; + case NPC_JARAXXUS: m_uiJaraxxusGUID = pCreature->GetGUID(); break; + case NPC_CHAMPIONS_CONTROLLER: m_uiChampionsControllerGUID = pCreature->GetGUID(); break; + case NPC_DARKBANE: m_uiDarkbaneGUID = pCreature->GetGUID(); break; + case NPC_LIGHTBANE: m_uiLightbaneGUID = pCreature->GetGUID(); break; + case NPC_ANUBARAK: m_uiAnubarakGUID = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGO, bool bAdd) + { + switch(pGO->GetEntry()) + { + case GO_CRUSADERS_CACHE_10: + if(instance->GetSpawnMode() == RAID_DIFFICULTY_10MAN_NORMAL) + m_uiCrusadersCacheGUID = pGO->GetGUID(); + break; + case GO_CRUSADERS_CACHE_25: + if(instance->GetSpawnMode() == RAID_DIFFICULTY_25MAN_NORMAL) + m_uiCrusadersCacheGUID = pGO->GetGUID(); + break; + case GO_CRUSADERS_CACHE_10_H: + if(instance->GetSpawnMode() == RAID_DIFFICULTY_10MAN_HEROIC) + m_uiCrusadersCacheGUID = pGO->GetGUID(); + break; + case GO_CRUSADERS_CACHE_25_H: + if(instance->GetSpawnMode() == RAID_DIFFICULTY_25MAN_HEROIC) + m_uiCrusadersCacheGUID = pGO->GetGUID(); + break; + case GO_ARGENT_COLISEUM_FLOOR: m_uiFloorGUID = pGO->GetGUID(); break; + case GO_MAIN_GATE_DOOR: m_uiMainGateDoorGUID = pGO->GetGUID(); break; + case GO_EAST_PORTCULLIS: m_uiEastPortcullisGUID = pGO->GetGUID(); break; + case GO_WEB_DOOR: m_uiWebDoorGUID = pGO->GetGUID(); break; + + case GO_TRIBUTE_CHEST_10H_25: + case GO_TRIBUTE_CHEST_10H_45: + case GO_TRIBUTE_CHEST_10H_50: + case GO_TRIBUTE_CHEST_10H_99: + case GO_TRIBUTE_CHEST_25H_25: + case GO_TRIBUTE_CHEST_25H_45: + case GO_TRIBUTE_CHEST_25H_50: + case GO_TRIBUTE_CHEST_25H_99: + m_uiTributeChestGUID = pGO->GetGUID(); break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + switch(uiType) + { + case TYPE_JARAXXUS: + if (uiData == DONE) m_uiEvent = 2000; + break; + case TYPE_CRUSADERS: + switch (uiData) + { + case IN_PROGRESS: m_uiResilienceWillFixItTimer = 0; break; + case SPECIAL: //Means the first blood + m_uiResilienceWillFixItTimer = 60*IN_MILLISECONDS; + uiData = IN_PROGRESS; + break; + case DONE: + DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_DEFEAT_FACTION_CHAMPIONS); + if (m_uiResilienceWillFixItTimer > 0) + DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_CHAMPIONS_KILLED_IN_MINUTE); + if (GameObject* pChest = instance->GetGameObject(m_uiCrusadersCacheGUID)) + if (pChest && !pChest->isSpawned()) + pChest->SetRespawnTime(7*DAY); + m_uiEvent = 3100; + break; + } + break; + case TYPE_VALKIRIES: + switch (uiData) + { + case FAIL: + if (m_auiEncounter[TYPE_VALKIRIES] == NOT_STARTED) uiData = NOT_STARTED; + break; + case SPECIAL: + if (m_auiEncounter[TYPE_VALKIRIES] == SPECIAL) uiData = DONE; + break; + case DONE: + if (instance->GetPlayers().getFirst()->getSource()->GetTeam() == ALLIANCE) + m_uiEvent = 4020; + else + m_uiEvent = 4030; + break; + } + break; + case TYPE_ANUBARAK: + switch (uiData) + { + case DONE: + m_uiEvent = 6000; + break; + case SPECIAL: + uint32 tributeChest = 0; + if (instance->GetSpawnMode() == RAID_DIFFICULTY_10MAN_HEROIC) + { + if (m_uiTrialCounter >= 50) + tributeChest = GO_TRIBUTE_CHEST_10H_99; + else + if (m_uiTrialCounter >= 45) + tributeChest = GO_TRIBUTE_CHEST_10H_50; + else + if (m_uiTrialCounter >= 25) + tributeChest = GO_TRIBUTE_CHEST_10H_45; + else + tributeChest = GO_TRIBUTE_CHEST_10H_25; + } + else if (instance->GetSpawnMode() == RAID_DIFFICULTY_25MAN_HEROIC) + { + if (m_uiTrialCounter >= 50) + tributeChest = GO_TRIBUTE_CHEST_25H_99; + else + if (m_uiTrialCounter >= 45) + tributeChest = GO_TRIBUTE_CHEST_25H_50; + else + if (m_uiTrialCounter >= 25) + tributeChest = GO_TRIBUTE_CHEST_25H_45; + else + tributeChest = GO_TRIBUTE_CHEST_25H_25; + } + if (tributeChest) + if (Creature* pTirion = instance->GetCreature(m_uiTirionGUID)) + if (GameObject* pChest = pTirion->SummonGameObject(tributeChest,805.62,134.87,142.16,3.27,0,0,0,0,90000000)) + pChest->SetRespawnTime(pChest->GetRespawnDelay()); + break; + } + break; + case TYPE_COUNTER: m_uiTrialCounter = uiData; uiData = DONE; break; + case TYPE_EVENT: m_uiEvent = uiData; uiData = NOT_STARTED; break; + case TYPE_EVENT_TIMER: m_uiEventTimer = uiData; uiData = NOT_STARTED; break; + case TYPE_NORTHREND_BEASTS: + m_uiNorthrendBeasts = uiData; + switch (uiData) + { + case GORMOK_DONE: + m_uiEvent = 200; + SetData(TYPE_NORTHREND_BEASTS,IN_PROGRESS); + SetData(TYPE_BEASTS,IN_PROGRESS); + break; + case SNAKES_IN_PROGRESS: m_uiNotOneButTwoJormungarsTimer = 0; break; + case SNAKES_SPECIAL: m_uiNotOneButTwoJormungarsTimer = 10*IN_MILLISECONDS; break; + case SNAKES_DONE: + if (m_uiNotOneButTwoJormungarsTimer > 0) + DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_WORMS_KILLED_IN_10_SECONDS); + m_uiEvent = 300; + SetData(TYPE_NORTHREND_BEASTS,IN_PROGRESS); + SetData(TYPE_BEASTS,IN_PROGRESS); + break; + case ICEHOWL_DONE: + m_uiEvent = 400; + SetData(TYPE_NORTHREND_BEASTS,DONE); + SetData(TYPE_BEASTS,DONE); + break; + case FAIL: + SetData(TYPE_BEASTS,FAIL); + break; + } + break; + case DATA_HEALTH_TWIN_SHARED: m_uiDataDamageTwin = uiData; uiData = NOT_STARTED; break; + + //Achievements + case DATA_SNOBOLD_COUNT: + if (uiData == INCREASE) + ++m_uiSnoboldCount; + else if (uiData == DECREASE) + --m_uiSnoboldCount; + break; + case DATA_MISTRESS_OF_PAIN_COUNT: + if (uiData == INCREASE) + ++m_uiMistressOfPainCount; + else if (uiData == DECREASE) + --m_uiMistressOfPainCount; + break; + case DATA_TRIBUTE_TO_IMMORTALITY_ELEGIBLE: + m_bTributeToImmortalityElegible = false; + break; + } + if (IsEncounterInProgress()) + { + CloseDoor(GetData64(GO_EAST_PORTCULLIS)); + CloseDoor(GetData64(GO_WEB_DOOR)); + } else { + OpenDoor(GetData64(GO_EAST_PORTCULLIS)); + OpenDoor(GetData64(GO_WEB_DOOR)); + } + + if (uiType < MAX_ENCOUNTERS) + { + sLog.outBasic("[ToCr] m_auiEncounter[uiType %u] %u = uiData %u;",uiType,m_auiEncounter[uiType],uiData); + if (uiData == FAIL) + { + if (IsRaidWiped()) + { + --m_uiTrialCounter; + m_bNeedSave = true; + m_uiEvent = (uiType == TYPE_BEASTS? 666 : 0); + } + uiData = NOT_STARTED; + } + m_auiEncounter[uiType] = uiData; + + if (uiData == DONE || m_bNeedSave == true) + { + if (Unit* pAnnouncer = instance->GetCreature(GetData64(NPC_BARRENT))) + pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + Save(); + } + } + } + + uint64 GetData64(uint32 uiData) + { + switch(uiData) + { + case NPC_BARRENT: return m_uiBarrentGUID; + case NPC_TIRION: return m_uiTirionGUID; + case NPC_FIZZLEBANG: return m_uiFizzlebangGUID; + case NPC_GARROSH: return m_uiGarroshGUID; + case NPC_VARIAN: return m_uiVarianGUID; + + case NPC_GORMOK: return m_uiGormokGUID; + case NPC_ACIDMAW: return m_uiAcidmawGUID; + case NPC_DREADSCALE: return m_uiDreadscaleGUID; + case NPC_ICEHOWL: return m_uiIcehowlGUID; + case NPC_JARAXXUS: return m_uiJaraxxusGUID; + case NPC_CHAMPIONS_CONTROLLER: return m_uiChampionsControllerGUID; + case NPC_DARKBANE: return m_uiDarkbaneGUID; + case NPC_LIGHTBANE: return m_uiLightbaneGUID; + case NPC_ANUBARAK: return m_uiAnubarakGUID; + + case GO_ARGENT_COLISEUM_FLOOR: return m_uiFloorGUID; + case GO_MAIN_GATE_DOOR: return m_uiMainGateDoorGUID; + case GO_EAST_PORTCULLIS: return m_uiEastPortcullisGUID; + case GO_WEB_DOOR: return m_uiWebDoorGUID; + } + return 0; + } + + uint32 GetData(uint32 uiType) + { + switch(uiType) + { + case TYPE_BEASTS: return m_auiEncounter[TYPE_BEASTS]; + case TYPE_JARAXXUS: return m_auiEncounter[TYPE_JARAXXUS]; + case TYPE_CRUSADERS: return m_auiEncounter[TYPE_CRUSADERS]; + case TYPE_VALKIRIES: return m_auiEncounter[TYPE_VALKIRIES]; + case TYPE_LICH_KING: return m_auiEncounter[TYPE_LICH_KING]; + case TYPE_ANUBARAK: return m_auiEncounter[TYPE_ANUBARAK]; + case TYPE_COUNTER: return m_uiTrialCounter; + case TYPE_EVENT: return m_uiEvent; + case TYPE_NORTHREND_BEASTS: return m_uiNorthrendBeasts; + case TYPE_EVENT_TIMER: return m_uiEventTimer; + case TYPE_EVENT_NPC: + switch (m_uiEvent) + { + case 110: + case 140: + case 150: + case 155: + case 200: + case 205: + case 210: + case 220: + case 300: + case 305: + case 310: + case 315: + case 400: + case 666: + case 1010: + case 1180: + case 2000: + case 2030: + case 3000: + case 3001: + case 3060: + case 3061: + case 3090: + case 3091: + case 3092: + case 3100: + case 3110: + case 4000: + case 4010: + case 4015: + case 4016: + case 4040: + case 4050: + case 5000: + case 5005: + case 5020: + case 6000: + case 6005: + case 6010: + m_uiEventNPCId = NPC_TIRION; + break; + case 5010: + case 5030: + case 5040: + case 5050: + case 5060: + case 5070: + case 5080: + m_uiEventNPCId = NPC_LICH_KING_1; + break; + case 120: + case 122: + case 2020: + case 3080: + case 3051: + case 3071: + case 4020: + m_uiEventNPCId = NPC_VARIAN; + break; + case 130: + case 132: + case 2010: + case 3050: + case 3070: + case 3081: + case 4030: + m_uiEventNPCId = NPC_GARROSH; + break; + case 1110: + case 1120: + case 1130: + case 1132: + case 1134: + case 1135: + case 1140: + case 1142: + case 1144: + case 1150: + m_uiEventNPCId = NPC_FIZZLEBANG; + break; + default: + m_uiEventNPCId = NPC_TIRION; + break; + }; + return m_uiEventNPCId; + case DATA_HEALTH_TWIN_SHARED: return m_uiDataDamageTwin; + } + return 0; + } + + void Update(uint32 uiDiff) + { + if (GetData(TYPE_NORTHREND_BEASTS) == SNAKES_SPECIAL) + { + if (m_uiNotOneButTwoJormungarsTimer) + if (m_uiNotOneButTwoJormungarsTimer <= uiDiff) + m_uiNotOneButTwoJormungarsTimer = 0; + else m_uiNotOneButTwoJormungarsTimer -= uiDiff; + } + + if (GetData(TYPE_CRUSADERS) == IN_PROGRESS) + { + if (m_uiResilienceWillFixItTimer) + if (m_uiResilienceWillFixItTimer <= uiDiff) + m_uiResilienceWillFixItTimer = 0; + else m_uiResilienceWillFixItTimer -= uiDiff; + } + } + + void Save() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + + for(uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + saveStream << m_auiEncounter[i] << " "; + + saveStream << m_uiTrialCounter; + m_strInstData = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + m_bNeedSave = false; + } + + std::string GetSaveData() + { + return m_strInstData; + } + + void Load(const char* strIn) + { + if (!strIn) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(strIn); + + std::istringstream loadStream(strIn); + + for(uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + { + loadStream >> m_auiEncounter[i]; + + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + } + loadStream >> m_uiTrialCounter; + m_uiEvent = 0; + + OUT_LOAD_INST_DATA_COMPLETE; + } + + bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target*/, uint32 /*miscvalue1*/) + { + switch (criteria_id) + { + case UPPER_BACK_PAIN_10_PLAYER: + case UPPER_BACK_PAIN_10_PLAYER_HEROIC: + return m_uiSnoboldCount >= 2; + case UPPER_BACK_PAIN_25_PLAYER: + case UPPER_BACK_PAIN_25_PLAYER_HEROIC: + return m_uiSnoboldCount >= 4; + case THREE_SIXTY_PAIN_SPIKE_10_PLAYER: + case THREE_SIXTY_PAIN_SPIKE_10_PLAYER_HEROIC: + case THREE_SIXTY_PAIN_SPIKE_25_PLAYER: + case THREE_SIXTY_PAIN_SPIKE_25_PLAYER_HEROIC: + return m_uiMistressOfPainCount >= 2; + case A_TRIBUTE_TO_SKILL_10_PLAYER: + case A_TRIBUTE_TO_SKILL_25_PLAYER: + return m_uiTrialCounter >= 25; + case A_TRIBUTE_TO_MAD_SKILL_10_PLAYER: + case A_TRIBUTE_TO_MAD_SKILL_25_PLAYER: + return m_uiTrialCounter >= 45; + case A_TRIBUTE_TO_INSANITY_10_PLAYER: + case A_TRIBUTE_TO_INSANITY_25_PLAYER: + case REALM_FIRST_GRAND_CRUSADER: + return m_uiTrialCounter == 50; + case A_TRIBUTE_TO_IMMORTALITY_HORDE: + case A_TRIBUTE_TO_IMMORTALITY_ALLIANCE: + return m_uiTrialCounter == 50 && m_bTributeToImmortalityElegible; + case A_TRIBUTE_TO_DEDICATED_INSANITY: + return false/*uiGrandCrusaderAttemptsLeft == 50 && !bHasAtAnyStagePlayerEquippedTooGoodItem*/; + } + + return false; + } + }; + +}; + + +void AddSC_instance_trial_of_the_crusader() +{ + new instance_trial_of_the_crusader(); +} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp new file mode 100644 index 00000000000..9d187ead517 --- /dev/null +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp @@ -0,0 +1,987 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> + * 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 + */ + +/* ScriptData +SDName: Trial Of the crusader +SD%Complete: ??% +SDComment: event script based on /dev/rsa +SDCategory: trial_of_the_crusader +EndScriptData */ + +//Known Bugs: +// - Need better implementation of Gossip and correct gossip text and option +// - Misses Dalaran Teleport at the end. + +#include "ScriptPCH.h" +#include "trial_of_the_crusader.h" + +enum eYells +{ + SAY_STAGE_0_01 = -1649070, + SAY_STAGE_0_02 = -1649071, + SAY_STAGE_0_03a = -1649072, + SAY_STAGE_0_03h = -1649073, + SAY_STAGE_0_04 = -1649074, + SAY_STAGE_0_05 = -1649075, + SAY_STAGE_0_06 = -1649076, + SAY_STAGE_0_WIPE = -1649077, + SAY_STAGE_1_01 = -1649080, + SAY_STAGE_1_02 = -1649081, + SAY_STAGE_1_03 = -1649082, + SAY_STAGE_1_04 = -1649083, + SAY_STAGE_1_05 = -1649030, //INTRO Jaraxxus + SAY_STAGE_1_06 = -1649084, + SAY_STAGE_1_07 = -1649086, + SAY_STAGE_1_08 = -1649087, + SAY_STAGE_1_09 = -1649088, + SAY_STAGE_1_10 = -1649089, + SAY_STAGE_1_11 = -1649090, + SAY_STAGE_2_01 = -1649091, + SAY_STAGE_2_02a = -1649092, + SAY_STAGE_2_02h = -1649093, + SAY_STAGE_2_03 = -1649094, + SAY_STAGE_2_04a = -1649095, + SAY_STAGE_2_04h = -1649096, + SAY_STAGE_2_05a = -1649097, + SAY_STAGE_2_05h = -1649098, + SAY_STAGE_2_06 = -1649099, + SAY_STAGE_3_01 = -1649100, + SAY_STAGE_3_02 = -1649101, + SAY_STAGE_3_03a = -1649102, + SAY_STAGE_3_03h = -1649103, + SAY_STAGE_4_01 = -1649104, + SAY_STAGE_4_02 = -1649105, + SAY_STAGE_4_03 = -1649106, + SAY_STAGE_4_04 = -1649107, + SAY_STAGE_4_05 = -1649108, + SAY_STAGE_4_06 = -1649109, + SAY_STAGE_4_07 = -1649110, +}; + +struct _Messages +{ + eAnnouncerMessages msgnum; + uint32 id; + bool state; + uint32 encounter; +}; + +static _Messages _GossipMessage[]= +{ + {MSG_BEASTS,GOSSIP_ACTION_INFO_DEF+1,false,TYPE_BEASTS}, + {MSG_JARAXXUS,GOSSIP_ACTION_INFO_DEF+2,false,TYPE_JARAXXUS}, + {MSG_CRUSADERS,GOSSIP_ACTION_INFO_DEF+3,false,TYPE_CRUSADERS}, + {MSG_VALKIRIES,GOSSIP_ACTION_INFO_DEF+4,false,TYPE_VALKIRIES}, + {MSG_LICH_KING,GOSSIP_ACTION_INFO_DEF+5,false,TYPE_ANUBARAK}, + {MSG_ANUBARAK,GOSSIP_ACTION_INFO_DEF+6,true,TYPE_ANUBARAK} +}; + +enum +{ + NUM_MESSAGES = 6, +}; + +class npc_announcer_toc10 : public CreatureScript +{ + public: + + npc_announcer_toc10() : CreatureScript("npc_announcer_toc10") { } + + struct npc_announcer_toc10AI : public ScriptedAI + { + npc_announcer_toc10AI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (InstanceScript*)pCreature->GetInstanceScript(); + } + + InstanceScript* m_pInstance; + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if(Creature *pAlly = GetClosestCreatureWithEntry(me, NPC_THRALL, 300.0f)) + pAlly->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if(Creature *pAlly = GetClosestCreatureWithEntry(me, NPC_PROUDMOORE, 300.0f)) + pAlly->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void AttackStart(Unit* pWho) {} + }; + + bool OnGossipHello(Player* pPlayer, Creature* pCreature) + { + InstanceScript* m_pInstance; + m_pInstance = (InstanceScript*)pCreature->GetInstanceScript(); + if (!m_pInstance) return false; + + char const* _message = "We are ready!"; + + if (!pPlayer->getAttackers().empty() || m_pInstance->IsEncounterInProgress() || m_pInstance->GetData(TYPE_EVENT)) + return true; + + uint8 i; + for(i = 0; i < NUM_MESSAGES; i++) + { + if ((!_GossipMessage[i].state && m_pInstance->GetData(_GossipMessage[i].encounter) != DONE) + || (_GossipMessage[i].state && m_pInstance->GetData(_GossipMessage[i].encounter) == DONE)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, _message, GOSSIP_SENDER_MAIN,_GossipMessage[i].id); + break; + } + } + + pPlayer->SEND_GOSSIP_MENU(_GossipMessage[i].msgnum, pCreature->GetGUID()); + return true; + } + + bool OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) + { + InstanceScript* m_pInstance; + m_pInstance = (InstanceScript*)pCreature->GetInstanceScript(); + if (!m_pInstance) return false; + + pPlayer->CLOSE_GOSSIP_MENU(); + + switch(uiAction) { + case GOSSIP_ACTION_INFO_DEF+1: + if (m_pInstance->GetData(TYPE_BEASTS) != DONE) + { + m_pInstance->SetData(TYPE_EVENT,110); + m_pInstance->SetData(TYPE_NORTHREND_BEASTS,NOT_STARTED); + m_pInstance->SetData(TYPE_BEASTS,NOT_STARTED); + } + break; + case GOSSIP_ACTION_INFO_DEF+2: + if (Creature* pJaraxxus = Unit::GetCreature(*pCreature,m_pInstance->GetData64(NPC_JARAXXUS))) + { + pJaraxxus->RemoveAurasDueToSpell(SPELL_JARAXXUS_CHAINS); + pJaraxxus->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pJaraxxus->SetReactState(REACT_AGGRESSIVE); + pJaraxxus->SetInCombatWithZone(); + } + else + { + if (m_pInstance->GetData(TYPE_JARAXXUS) != DONE) + { + m_pInstance->SetData(TYPE_EVENT,1010); + m_pInstance->SetData(TYPE_JARAXXUS,NOT_STARTED); + } + } + break; + case GOSSIP_ACTION_INFO_DEF+3: + if (m_pInstance->GetData(TYPE_CRUSADERS) != DONE) + { + if (pPlayer->GetTeam() == ALLIANCE) m_pInstance->SetData(TYPE_EVENT,3000); + else m_pInstance->SetData(TYPE_EVENT,3001); + m_pInstance->SetData(TYPE_CRUSADERS,NOT_STARTED); + } + break; + case GOSSIP_ACTION_INFO_DEF+4: + if (m_pInstance->GetData(TYPE_VALKIRIES) != DONE) + { + m_pInstance->SetData(TYPE_EVENT,4000); + m_pInstance->SetData(TYPE_VALKIRIES,NOT_STARTED); + } + break; + case GOSSIP_ACTION_INFO_DEF+5: + { + if (m_pInstance->GetData(TYPE_LICH_KING) != DONE && !pPlayer->isGameMaster()) + return false; + + if (GameObject* pGoFloor = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(GO_ARGENT_COLISEUM_FLOOR))) + pGoFloor->TakenDamage(1000000); + + pCreature->CastSpell(pCreature,69016,false); + + Creature* pTemp = Unit::GetCreature((*pCreature),m_pInstance->GetData64(NPC_ANUBARAK)); + if (!pTemp || !pTemp->isAlive()) + pTemp = pCreature->SummonCreature(NPC_ANUBARAK, AnubarakLoc[0].GetPositionX(), AnubarakLoc[0].GetPositionY(), AnubarakLoc[0].GetPositionZ(), 3, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + + m_pInstance->SetData(TYPE_ANUBARAK,NOT_STARTED); + + if (pCreature->GetVisibility() == VISIBILITY_ON) + pCreature->SetVisibility(VISIBILITY_OFF); + break; + } + } + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + return true; + } + + CreatureAI* GetAI(Creature* pCreature) const + { + return new npc_announcer_toc10AI(pCreature); + } +}; + +class boss_lich_king_toc : public CreatureScript +{ + public: + + boss_lich_king_toc() : CreatureScript("boss_lich_king_toc") { } + + struct boss_lich_king_tocAI : public ScriptedAI + { + boss_lich_king_tocAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (InstanceScript*)pCreature->GetInstanceScript(); + } + + InstanceScript* m_pInstance; + uint32 m_uiUpdateTimer; + + void Reset() + { + m_uiUpdateTimer = 0; + me->SetReactState(REACT_PASSIVE); + if (Creature* pSummoned = me->SummonCreature(NPC_TRIGGER, ToCCommonLoc[2].GetPositionX(), ToCCommonLoc[2].GetPositionY(), ToCCommonLoc[2].GetPositionZ(), 5, TEMPSUMMON_TIMED_DESPAWN, 60000)) + { + pSummoned->CastSpell(pSummoned, 51807, false); + pSummoned->SetDisplayId(11686); + } + if (m_pInstance) m_pInstance->SetData(TYPE_LICH_KING,IN_PROGRESS); + me->AddUnitMovementFlag(MOVEMENTFLAG_WALKING); + } + + void MovementInform(uint32 uiType, uint32 uiId) + { + if (uiType != POINT_MOTION_TYPE) + return; + switch (uiId) + { + case 0: + m_pInstance->SetData(TYPE_EVENT,5030); + break; + case 1: + m_pInstance->SetData(TYPE_EVENT,5050); + break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance) return; + if (m_pInstance->GetData(TYPE_EVENT_NPC) != NPC_LICH_KING_1) return; + + m_uiUpdateTimer = m_pInstance->GetData(TYPE_EVENT_TIMER); + if (m_uiUpdateTimer <= uiDiff) + { + switch (m_pInstance->GetData(TYPE_EVENT)) + { + case 5010: + DoScriptText(SAY_STAGE_4_02,me); + m_uiUpdateTimer = 3000; + me->GetMotionMaster()->MovePoint(0,LichKingLoc[0]); + m_pInstance->SetData(TYPE_EVENT,5020); + break; + case 5030: + DoScriptText(SAY_STAGE_4_04,me); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_TALK); + m_uiUpdateTimer = 10000; + m_pInstance->SetData(TYPE_EVENT,5040); + break; + case 5040: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + me->GetMotionMaster()->MovePoint(1,LichKingLoc[1]); + m_uiUpdateTimer = 1000; + m_pInstance->SetData(TYPE_EVENT,0); + break; + case 5050: + me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); + m_uiUpdateTimer = 3000; + m_pInstance->SetData(TYPE_EVENT,5060); + break; + case 5060: + DoScriptText(SAY_STAGE_4_05,me); + me->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL); + m_uiUpdateTimer = 2500; + m_pInstance->SetData(TYPE_EVENT,5070); + break; + case 5070: + me->CastSpell(me,68198,false); + m_uiUpdateTimer = 1500; + m_pInstance->SetData(TYPE_EVENT,5080); + break; + case 5080: + if (GameObject* pGoFloor = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(GO_ARGENT_COLISEUM_FLOOR))) + pGoFloor->TakenDamage(1000000); + me->CastSpell(me,69016,false); + if(m_pInstance) m_pInstance->SetData(TYPE_LICH_KING,DONE); + Creature* pTemp = Unit::GetCreature((*me),m_pInstance->GetData64(NPC_ANUBARAK)); + if (!pTemp || !pTemp->isAlive()) + pTemp = me->SummonCreature(NPC_ANUBARAK, AnubarakLoc[0].GetPositionX(), AnubarakLoc[0].GetPositionY(), AnubarakLoc[0].GetPositionZ(), 3, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + me->ForcedDespawn(); + m_pInstance->SetData(TYPE_EVENT,0); + m_uiUpdateTimer = 20000; + break; + } + } else m_uiUpdateTimer -= uiDiff; + m_pInstance->SetData(TYPE_EVENT_TIMER, m_uiUpdateTimer); + } + }; + + CreatureAI* GetAI(Creature* pCreature) const + { + return new boss_lich_king_tocAI(pCreature); + } +}; + +class npc_fizzlebang_toc : public CreatureScript +{ + public: + + npc_fizzlebang_toc() : CreatureScript("npc_fizzlebang_toc") { } + + struct npc_fizzlebang_tocAI : public ScriptedAI + { + npc_fizzlebang_tocAI(Creature* pCreature) : ScriptedAI(pCreature), Summons(me) + { + m_pInstance = (InstanceScript*)me->GetInstanceScript(); + } + + InstanceScript* m_pInstance; + SummonList Summons; + uint32 m_uiUpdateTimer; + uint64 m_uiPortalGUID; + uint64 m_uiTriggerGUID; + + void JustDied(Unit* pKiller) + { + DoScriptText(SAY_STAGE_1_06, me, pKiller); + m_pInstance->SetData(TYPE_EVENT, 1180); + if (Creature* pTemp = Unit::GetCreature(*me,m_pInstance->GetData64(NPC_JARAXXUS))) + { + pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTemp->SetReactState(REACT_AGGRESSIVE); + pTemp->SetInCombatWithZone(); + } + } + + void Reset() + { + me->AddUnitMovementFlag(MOVEMENTFLAG_WALKING); + m_uiPortalGUID = 0; + me->GetMotionMaster()->MovePoint(1, ToCCommonLoc[10].GetPositionX(), ToCCommonLoc[10].GetPositionY()-60, ToCCommonLoc[10].GetPositionZ()); + } + + void MovementInform(uint32 uiType, uint32 uiId) + { + if(uiType != POINT_MOTION_TYPE) return; + + switch (uiId) + { + case 1: + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); + if (m_pInstance) + { + m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(GO_MAIN_GATE_DOOR)); + m_pInstance->SetData(TYPE_EVENT, 1120); + m_pInstance->SetData(TYPE_EVENT_TIMER, 1000); + } + break; + } + } + + void JustSummoned(Creature* pSummoned) + { + Summons.Summon(pSummoned); + } + + void UpdateAI(const uint32 uiDiff) + { + if(!m_pInstance) return; + + if (m_pInstance->GetData(TYPE_EVENT_NPC) != NPC_FIZZLEBANG) return; + + m_uiUpdateTimer = m_pInstance->GetData(TYPE_EVENT_TIMER); + if (m_uiUpdateTimer <= uiDiff) + { + switch (m_pInstance->GetData(TYPE_EVENT)) + { + case 1110: + m_pInstance->SetData(TYPE_EVENT, 1120); + m_uiUpdateTimer = 4000; + break; + case 1120: + DoScriptText(SAY_STAGE_1_02, me); + m_pInstance->SetData(TYPE_EVENT, 1130); + m_uiUpdateTimer = 12000; + break; + case 1130: + me->GetMotionMaster()->MovementExpired(); + DoScriptText(SAY_STAGE_1_03, me); + me->HandleEmoteCommand(EMOTE_ONESHOT_SPELLCAST_OMNI); + if (Unit* pTrigger = me->SummonCreature(NPC_TRIGGER, ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY(), ToCCommonLoc[1].GetPositionZ(), 4.69494f, TEMPSUMMON_MANUAL_DESPAWN)) + { + m_uiTriggerGUID = pTrigger->GetGUID(); + pTrigger->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.0f); + pTrigger->SetDisplayId(22862); + pTrigger->CastSpell(pTrigger, SPELL_WILFRED_PORTAL, false); + } + m_pInstance->SetData(TYPE_EVENT, 1132); + m_uiUpdateTimer = 4000; + break; + case 1132: + me->GetMotionMaster()->MovementExpired(); + m_pInstance->SetData(TYPE_EVENT, 1134); + m_uiUpdateTimer = 4000; + break; + case 1134: + me->HandleEmoteCommand(EMOTE_ONESHOT_SPELLCAST_OMNI); + if (Creature* pPortal = me->SummonCreature(NPC_WILFRED_PORTAL, ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY(), ToCCommonLoc[1].GetPositionZ(), 4.71239f, TEMPSUMMON_MANUAL_DESPAWN)) + { + pPortal->SetReactState(REACT_PASSIVE); + pPortal->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.0f); + pPortal->CastSpell(pPortal,SPELL_WILFRED_PORTAL,false); + m_uiPortalGUID = pPortal->GetGUID(); + } + m_uiUpdateTimer = 4000; + m_pInstance->SetData(TYPE_EVENT, 1135); + break; + case 1135: + m_pInstance->SetData(TYPE_EVENT, 1140); + m_uiUpdateTimer = 3000; + break; + case 1140: + DoScriptText(SAY_STAGE_1_04, me); + if (Creature* pTemp = me->SummonCreature(NPC_JARAXXUS, ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY(), ToCCommonLoc[1].GetPositionZ(), 5.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME)) + { + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTemp->SetReactState(REACT_PASSIVE); + pTemp->GetMotionMaster()->MovePoint(0,ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY()-10, ToCCommonLoc[1].GetPositionZ()); + } + m_pInstance->SetData(TYPE_EVENT, 1142); + m_uiUpdateTimer = 5000; + break; + case 1142: + if (Creature* pTemp = Unit::GetCreature(*me,m_pInstance->GetData64(NPC_JARAXXUS))) + pTemp->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + if (Creature* pTrigger = Unit::GetCreature(*me,m_uiTriggerGUID)) + pTrigger->ForcedDespawn(); + if (Creature* pPortal = Unit::GetCreature(*me,m_uiPortalGUID)) + pPortal->ForcedDespawn(); + m_pInstance->SetData(TYPE_EVENT, 1144); + m_uiUpdateTimer = 10000; + break; + case 1144: + if (Creature* pTemp = Unit::GetCreature(*me,m_pInstance->GetData64(NPC_JARAXXUS))) + DoScriptText(SAY_STAGE_1_05,pTemp); + m_pInstance->SetData(TYPE_EVENT, 1150); + m_uiUpdateTimer = 5000; + break; + case 1150: + if (Creature* pTemp = Unit::GetCreature(*me,m_pInstance->GetData64(NPC_JARAXXUS))) + { + //1-shot Fizzlebang + pTemp->CastSpell(me,67888,false); + me->SetInCombatWith(pTemp); + pTemp->AddThreat(me, 1000.0f); + pTemp->AI()->AttackStart(me); + } + m_pInstance->SetData(TYPE_EVENT, 1160); + m_uiUpdateTimer = 3000; + break; + } + } else m_uiUpdateTimer -= uiDiff; + m_pInstance->SetData(TYPE_EVENT_TIMER, m_uiUpdateTimer); + } + }; + + CreatureAI* GetAI(Creature* pCreature) const + { + return new npc_fizzlebang_tocAI(pCreature); + } +}; + +class npc_tirion_toc : public CreatureScript +{ + public: + + npc_tirion_toc() : CreatureScript("npc_tirion_toc") { } + + struct npc_tirion_tocAI : public ScriptedAI + { + npc_tirion_tocAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (InstanceScript*)me->GetInstanceScript(); + } + + InstanceScript* m_pInstance; + uint32 m_uiUpdateTimer; + + void Reset() {} + + void AttackStart(Unit* pWho) {} + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance) return; + if (m_pInstance->GetData(TYPE_EVENT_NPC) != NPC_TIRION) return; + + m_uiUpdateTimer = m_pInstance->GetData(TYPE_EVENT_TIMER); + if (m_uiUpdateTimer <= uiDiff) + { + switch (m_pInstance->GetData(TYPE_EVENT)) + { + case 110: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_TALK); + DoScriptText(SAY_STAGE_0_01, me); + m_uiUpdateTimer = 22000; + m_pInstance->SetData(TYPE_EVENT,120); + break; + case 140: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_TALK); + DoScriptText(SAY_STAGE_0_02, me); + m_uiUpdateTimer = 5000; + m_pInstance->SetData(TYPE_EVENT,150); + m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(GO_MAIN_GATE_DOOR)); + break; + case 150: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + if (m_pInstance->GetData(TYPE_BEASTS) != DONE) + { + me->SummonCreature(NPC_GORMOK, ToCCommonLoc[10].GetPositionX(), ToCCommonLoc[10].GetPositionY(), ToCCommonLoc[10].GetPositionZ(), 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30*IN_MILLISECONDS); + if (Creature* pTemp = Unit::GetCreature((*me),m_pInstance->GetData64(NPC_GORMOK))) + { + pTemp->GetMotionMaster()->MovePoint(0, ToCCommonLoc[5].GetPositionX(), ToCCommonLoc[5].GetPositionY(), ToCCommonLoc[5].GetPositionZ()); + pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALKING); + pTemp->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + pTemp->SetReactState(REACT_PASSIVE); + } + } + m_uiUpdateTimer = 3000; + m_pInstance->SetData(TYPE_EVENT,155); + break; + case 155: + if (Creature* pTemp = Unit::GetCreature((*me),m_pInstance->GetData64(NPC_GORMOK))) + { + pTemp->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + pTemp->SetReactState(REACT_AGGRESSIVE); + pTemp->SetInCombatWithZone(); + } + m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(GO_MAIN_GATE_DOOR)); + m_pInstance->SetData(TYPE_BEASTS,IN_PROGRESS); + m_uiUpdateTimer = 5000; + m_pInstance->SetData(TYPE_EVENT,160); + break; + case 200: + DoScriptText(SAY_STAGE_0_04, me); + m_uiUpdateTimer = 8000; + m_pInstance->SetData(TYPE_EVENT,205); + break; + case 205: + m_uiUpdateTimer = 3000; + m_pInstance->SetData(TYPE_EVENT,210); + m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(GO_MAIN_GATE_DOOR)); + break; + case 210: + if (m_pInstance->GetData(TYPE_BEASTS) != DONE) + { + me->SummonCreature(NPC_DREADSCALE, ToCCommonLoc[3].GetPositionX(), ToCCommonLoc[3].GetPositionY(), ToCCommonLoc[3].GetPositionZ(), 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30*IN_MILLISECONDS); + me->SummonCreature(NPC_ACIDMAW, ToCCommonLoc[4].GetPositionX(), ToCCommonLoc[4].GetPositionY(), ToCCommonLoc[4].GetPositionZ(), 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30*IN_MILLISECONDS); + if (Creature* pTemp = Unit::GetCreature((*me),m_pInstance->GetData64(NPC_DREADSCALE))) + { + pTemp->GetMotionMaster()->MovePoint(0, ToCCommonLoc[8].GetPositionX(), ToCCommonLoc[8].GetPositionY(), ToCCommonLoc[8].GetPositionZ()); + pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALKING); + pTemp->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + pTemp->SetReactState(REACT_PASSIVE); + } + if (Creature* pTemp = Unit::GetCreature((*me),m_pInstance->GetData64(NPC_ACIDMAW))) + { + pTemp->GetMotionMaster()->MovePoint(0, ToCCommonLoc[9].GetPositionX(), ToCCommonLoc[9].GetPositionY(), ToCCommonLoc[9].GetPositionZ()); + pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALKING); + pTemp->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + pTemp->SetReactState(REACT_PASSIVE); + } + } + m_uiUpdateTimer = 5000; + m_pInstance->SetData(TYPE_EVENT,220); + break; + case 220: + if (Creature* pTemp = Unit::GetCreature((*me),m_pInstance->GetData64(NPC_DREADSCALE))) + { + pTemp->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + pTemp->SetReactState(REACT_AGGRESSIVE); + pTemp->SetInCombatWithZone(); + } + if (Creature* pTemp = Unit::GetCreature((*me),m_pInstance->GetData64(NPC_ACIDMAW))) + { + pTemp->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + pTemp->SetReactState(REACT_AGGRESSIVE); + pTemp->SetInCombatWithZone(); + } + m_pInstance->SetData(TYPE_EVENT,230); + m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(GO_MAIN_GATE_DOOR)); + break; + case 300: + DoScriptText(SAY_STAGE_0_05, me); + m_uiUpdateTimer = 8000; + m_pInstance->SetData(TYPE_EVENT,305); + break; + case 305: + m_uiUpdateTimer = 3000; + m_pInstance->SetData(TYPE_EVENT,310); + m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(GO_MAIN_GATE_DOOR)); + break; + case 310: + if (m_pInstance->GetData(TYPE_BEASTS) != DONE) + { + me->SummonCreature(NPC_ICEHOWL, ToCCommonLoc[10].GetPositionX(), ToCCommonLoc[10].GetPositionY(), ToCCommonLoc[10].GetPositionZ(), 5, TEMPSUMMON_DEAD_DESPAWN); + if (Creature* pTemp = Unit::GetCreature((*me),m_pInstance->GetData64(NPC_ICEHOWL))) + { + pTemp->GetMotionMaster()->MovePoint(0, ToCCommonLoc[5].GetPositionX(), ToCCommonLoc[5].GetPositionY(), ToCCommonLoc[5].GetPositionZ()); + pTemp->SetInCombatWithZone(); + } + } + m_uiUpdateTimer = 5000; + m_pInstance->SetData(TYPE_EVENT,315); + break; + case 315: + m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(GO_MAIN_GATE_DOOR)); + m_pInstance->SetData(TYPE_EVENT,320); + break; + case 400: + DoScriptText(SAY_STAGE_0_06, me); + m_uiUpdateTimer = 5000; + m_pInstance->SetData(TYPE_EVENT,0); + break; + case 666: + DoScriptText(SAY_STAGE_0_WIPE, me); + m_uiUpdateTimer = 5000; + m_pInstance->SetData(TYPE_EVENT,0); + break; + case 1010: + DoScriptText(SAY_STAGE_1_01, me); + m_uiUpdateTimer = 7000; + m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(GO_MAIN_GATE_DOOR)); + me->SummonCreature(NPC_FIZZLEBANG, ToCCommonLoc[10].GetPositionX(), ToCCommonLoc[10].GetPositionY(), ToCCommonLoc[10].GetPositionZ(), 2, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + m_pInstance->SetData(TYPE_EVENT,0); + break; + case 1180: + DoScriptText(SAY_STAGE_1_07, me); + m_uiUpdateTimer = 3000; + m_pInstance->SetData(TYPE_EVENT,0); + break; + case 2000: + DoScriptText(SAY_STAGE_1_08, me); + m_uiUpdateTimer = 18000; + m_pInstance->SetData(TYPE_EVENT,2010); + break; + case 2030: + DoScriptText(SAY_STAGE_1_11, me); + m_uiUpdateTimer = 5000; + m_pInstance->SetData(TYPE_EVENT,0); + break; + case 3000: + DoScriptText(SAY_STAGE_2_01, me); + m_uiUpdateTimer = 12000; + m_pInstance->SetData(TYPE_EVENT,3050); + break; + case 3001: + DoScriptText(SAY_STAGE_2_01, me); + m_uiUpdateTimer = 12000; + m_pInstance->SetData(TYPE_EVENT,3051); + break; + case 3060: + DoScriptText(SAY_STAGE_2_03, me); + m_uiUpdateTimer = 5000; + m_pInstance->SetData(TYPE_EVENT,3070); + break; + case 3061: + DoScriptText(SAY_STAGE_2_03, me); + m_uiUpdateTimer = 5000; + m_pInstance->SetData(TYPE_EVENT,3071); + break; + //Summoning crusaders + case 3091: + me->SummonCreature(NPC_CHAMPIONS_CONTROLLER, ToCCommonLoc[1]); + if (Creature* pChampionController = Unit::GetCreature((*me),m_pInstance->GetData64(NPC_CHAMPIONS_CONTROLLER))) + pChampionController->AI()->SetData(0,HORDE); + m_uiUpdateTimer = 3000; + m_pInstance->SetData(TYPE_EVENT,3092); + break; + //Summoning crusaders + case 3090: + me->SummonCreature(NPC_CHAMPIONS_CONTROLLER, ToCCommonLoc[1]); + if (Creature* pChampionController = Unit::GetCreature((*me),m_pInstance->GetData64(NPC_CHAMPIONS_CONTROLLER))) + pChampionController->AI()->SetData(0,ALLIANCE); + m_uiUpdateTimer = 3000; + m_pInstance->SetData(TYPE_EVENT,3092); + break; + case 3092: + if (Creature* pChampionController = Unit::GetCreature((*me),m_pInstance->GetData64(NPC_CHAMPIONS_CONTROLLER))) + pChampionController->AI()->SetData(1,NOT_STARTED); + m_pInstance->SetData(TYPE_EVENT,3095); + break; + //Crusaders battle end + case 3100: + DoScriptText(SAY_STAGE_2_06, me); + m_uiUpdateTimer = 5000; + m_pInstance->SetData(TYPE_EVENT,0); + break; + case 4000: + DoScriptText(SAY_STAGE_3_01, me); + m_uiUpdateTimer = 13000; + m_pInstance->SetData(TYPE_EVENT,4010); + break; + case 4010: + DoScriptText(SAY_STAGE_3_02, me); + m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(GO_MAIN_GATE_DOOR)); + m_uiUpdateTimer = 3000; + m_pInstance->SetData(TYPE_EVENT,4015); + break; + case 4015: + me->SummonCreature(NPC_LIGHTBANE, ToCCommonLoc[3].GetPositionX(), ToCCommonLoc[3].GetPositionY(), ToCCommonLoc[3].GetPositionZ(), 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + if (Creature* pTemp = Unit::GetCreature((*me),m_pInstance->GetData64(NPC_LIGHTBANE))) + { + pTemp->GetMotionMaster()->MovePoint(0, ToCCommonLoc[6].GetPositionX(), ToCCommonLoc[6].GetPositionY(), ToCCommonLoc[6].GetPositionZ()); + pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALKING); + me->SetReactState(REACT_PASSIVE); + } + me->SummonCreature(NPC_DARKBANE, ToCCommonLoc[4].GetPositionX(), ToCCommonLoc[4].GetPositionY(), ToCCommonLoc[4].GetPositionZ(), 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + if (Creature* pTemp = Unit::GetCreature((*me),m_pInstance->GetData64(NPC_DARKBANE))) + { + pTemp->GetMotionMaster()->MovePoint(0, ToCCommonLoc[7].GetPositionX(), ToCCommonLoc[7].GetPositionY(), ToCCommonLoc[7].GetPositionZ()); + pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALKING); + me->SetReactState(REACT_PASSIVE); + } + m_uiUpdateTimer = 5000; + m_pInstance->SetData(TYPE_EVENT,4016); + break; + case 4016: + m_pInstance->SetData(TYPE_EVENT,4017); + m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(GO_MAIN_GATE_DOOR)); + break; + case 4040: + m_uiUpdateTimer = 60000; + m_pInstance->SetData(TYPE_EVENT,5000); + break; + case 5000: + DoScriptText(SAY_STAGE_4_01, me); + m_uiUpdateTimer = 10000; + m_pInstance->SetData(TYPE_EVENT,5005); + break; + case 5005: + m_uiUpdateTimer = 8000; + m_pInstance->SetData(TYPE_EVENT,5010); + me->SummonCreature(NPC_LICH_KING_1, ToCCommonLoc[2].GetPositionX(), ToCCommonLoc[2].GetPositionY(), ToCCommonLoc[2].GetPositionZ(), 5); + break; + case 5020: + DoScriptText(SAY_STAGE_4_03, me); + m_uiUpdateTimer = 1000; + m_pInstance->SetData(TYPE_EVENT,0); + break; + case 6000: + me->NearTeleportTo(AnubarakLoc[0].GetPositionX(), AnubarakLoc[0].GetPositionY(), AnubarakLoc[0].GetPositionZ(), 4.0f); + m_uiUpdateTimer = 20000; + m_pInstance->SetData(TYPE_EVENT,6005); + break; + case 6005: + DoScriptText(SAY_STAGE_4_06, me); + m_uiUpdateTimer = 20000; + m_pInstance->SetData(TYPE_EVENT,6010); + break; + case 6010: + if (IsHeroic()) + { + DoScriptText(SAY_STAGE_4_07, me); + m_uiUpdateTimer = 60000; + m_pInstance->SetData(TYPE_ANUBARAK,SPECIAL); + m_pInstance->SetData(TYPE_EVENT,6020); + } else m_pInstance->SetData(TYPE_EVENT,6030); + break; + case 6020: + me->ForcedDespawn(); + m_uiUpdateTimer = 5000; + m_pInstance->SetData(TYPE_EVENT,6030); + break; + } + } else m_uiUpdateTimer -= uiDiff; + m_pInstance->SetData(TYPE_EVENT_TIMER, m_uiUpdateTimer); + } + }; + + CreatureAI* GetAI(Creature* pCreature) const + { + return new npc_tirion_tocAI(pCreature); + } +}; + +class npc_garrosh_toc : public CreatureScript +{ + public: + + npc_garrosh_toc() : CreatureScript("npc_garrosh_toc") { } + + struct npc_garrosh_tocAI : public ScriptedAI + { + npc_garrosh_tocAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (InstanceScript*)me->GetInstanceScript(); + } + + InstanceScript* m_pInstance; + uint32 m_uiUpdateTimer; + + void Reset() {} + + void AttackStart(Unit* pWho) {} + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance) return; + if (m_pInstance->GetData(TYPE_EVENT_NPC) != NPC_GARROSH) return; + + m_uiUpdateTimer = m_pInstance->GetData(TYPE_EVENT_TIMER); + if (m_uiUpdateTimer <= uiDiff) + { + switch (m_pInstance->GetData(TYPE_EVENT)) + { + case 130: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_TALK); + DoScriptText(SAY_STAGE_0_03h, me); + m_uiUpdateTimer = 3000; + m_pInstance->SetData(TYPE_EVENT,132); + break; + case 132: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + m_uiUpdateTimer = 5000; + m_pInstance->SetData(TYPE_EVENT,140); + break; + case 2010: + DoScriptText(SAY_STAGE_1_09, me); + m_uiUpdateTimer = 9000; + m_pInstance->SetData(TYPE_EVENT,2020); + break; + case 3050: + DoScriptText(SAY_STAGE_2_02h, me); + m_uiUpdateTimer = 15000; + m_pInstance->SetData(TYPE_EVENT,3060); + break; + case 3070: + DoScriptText(SAY_STAGE_2_04h, me); + m_uiUpdateTimer = 6000; + m_pInstance->SetData(TYPE_EVENT,3080); + break; + case 3081: + DoScriptText(SAY_STAGE_2_05h, me); + m_uiUpdateTimer = 3000; + m_pInstance->SetData(TYPE_EVENT,3091); + break; + case 4030: + DoScriptText(SAY_STAGE_3_03h, me); + m_uiUpdateTimer = 5000; + m_pInstance->SetData(TYPE_EVENT,4040); + break; + } + } else m_uiUpdateTimer -= uiDiff; + m_pInstance->SetData(TYPE_EVENT_TIMER, m_uiUpdateTimer); + } + }; + + CreatureAI* GetAI(Creature* pCreature) const + { + return new npc_garrosh_tocAI(pCreature); + } +}; + +class npc_varian_toc : public CreatureScript +{ + public: + + npc_varian_toc() : CreatureScript("npc_varian_toc") { } + + struct npc_varian_tocAI : public ScriptedAI + { + npc_varian_tocAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (InstanceScript*)me->GetInstanceScript(); + } + + InstanceScript* m_pInstance; + uint32 m_uiUpdateTimer; + + void Reset() {} + + void AttackStart(Unit* pWho) {} + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance) return; + if (m_pInstance->GetData(TYPE_EVENT_NPC) != NPC_VARIAN) return; + + m_uiUpdateTimer = m_pInstance->GetData(TYPE_EVENT_TIMER); + if (m_uiUpdateTimer <= uiDiff) + { + switch (m_pInstance->GetData(TYPE_EVENT)) + { + case 120: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_TALK); + DoScriptText(SAY_STAGE_0_03a, me); + m_uiUpdateTimer = 2000; + m_pInstance->SetData(TYPE_EVENT,122); + break; + case 122: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + m_uiUpdateTimer = 3000; + m_pInstance->SetData(TYPE_EVENT,130); + break; + case 2020: + DoScriptText(SAY_STAGE_1_10, me); + m_uiUpdateTimer = 5000; + m_pInstance->SetData(TYPE_EVENT,2030); + break; + case 3051: + DoScriptText(SAY_STAGE_2_02a, me); + m_uiUpdateTimer = 10000; + m_pInstance->SetData(TYPE_EVENT,3061); + break; + case 3071: + DoScriptText(SAY_STAGE_2_04a, me); + m_uiUpdateTimer = 5000; + m_pInstance->SetData(TYPE_EVENT,3081); + break; + case 3080: + DoScriptText(SAY_STAGE_2_05a, me); + m_uiUpdateTimer = 3000; + m_pInstance->SetData(TYPE_EVENT,3090); + break; + case 4020: + DoScriptText(SAY_STAGE_3_03a, me); + m_uiUpdateTimer = 5000; + m_pInstance->SetData(TYPE_EVENT,4040); + break; + } + } else m_uiUpdateTimer -= uiDiff; + m_pInstance->SetData(TYPE_EVENT_TIMER,m_uiUpdateTimer); + } + }; + + CreatureAI* GetAI(Creature* pCreature) const + { + return new npc_varian_tocAI(pCreature); + } +}; + +void AddSC_trial_of_the_crusader() +{ + new npc_announcer_toc10(); + new boss_lich_king_toc(); + new npc_fizzlebang_toc(); + new npc_tirion_toc(); + new npc_garrosh_toc(); + new npc_varian_toc(); +} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h new file mode 100644 index 00000000000..3704331ddb1 --- /dev/null +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h @@ -0,0 +1,276 @@ +/* Copyright (C) 2009 - 2010 by /dev/rsa for ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_CRUSADER_H +#define DEF_CRUSADER_H + +enum +{ + TYPE_BEASTS = 0, + TYPE_JARAXXUS = 1, + TYPE_CRUSADERS = 2, + TYPE_VALKIRIES = 3, + TYPE_LICH_KING = 4, + TYPE_ANUBARAK = 5, + MAX_ENCOUNTERS = 6, + + TYPE_COUNTER = 8, + TYPE_EVENT = 9, + + TYPE_EVENT_TIMER = 101, + TYPE_EVENT_NPC = 102, + TYPE_NORTHREND_BEASTS = 103, + + DATA_HEALTH_TWIN_SHARED = 201, + + DATA_SNOBOLD_COUNT = 301, + DATA_MISTRESS_OF_PAIN_COUNT = 302, + DATA_TRIBUTE_TO_IMMORTALITY_ELEGIBLE = 303, + + INCREASE = 501, + DECREASE = 502, + + SPELL_WILFRED_PORTAL = 68424, + SPELL_JARAXXUS_CHAINS = 67924, + + DESPAWN_TIME = 300000, +}; + +static Position ToCCommonLoc[]= +{ + {559.257996f, 90.266197f, 395.122986f}, // 0 Barrent + + {563.672974f, 139.571f, 393.837006f}, // 1 Center + {563.833008f, 187.244995f, 394.5f}, // 2 Backdoor + {577.347839f, 195.338888f, 395.14f}, // 3 - Right + {550.955933f, 195.338888f, 395.14f}, // 4 - Left + {563.833008f, 195.244995f, 394.585561f}, // 5 - Center + {573.5f, 180.5f, 395.14f}, // 6 Move 0 Right + {553.5f, 180.5f, 395.14f}, // 7 Move 0 Left + {585.5f, 170.0f, 395.14f}, // 8 Move 1 Right + {545.5f, 170.0f, 395.14f}, // 9 Move 1 Left + {563.8f, 216.1f, 395.1f}, // 10 Behind the door + + {575.042358f, 195.260727f, 395.137146f}, // 5 + {552.248901f, 195.331955f, 395.132658f}, // 6 + {573.342285f, 195.515823f, 395.135956f}, // 7 + {554.239929f, 195.825577f, 395.137909f}, // 8 + {571.042358f, 195.260727f, 395.137146f}, // 9 + {556.720581f, 195.015472f, 395.132658f}, // 10 + {569.534119f, 195.214478f, 395.139526f}, // 11 + {569.231201f, 195.941071f, 395.139526f}, // 12 + {558.811610f, 195.985779f, 394.671661f}, // 13 + {567.641724f, 195.351501f, 394.659943f}, // 14 + {560.633972f, 195.391708f, 395.137543f}, // 15 + {565.816956f, 195.477921f, 395.136810f}, // 16 +}; + +static Position JaraxxusLoc[]= +{ + {508.104767f, 138.247345f, 395.128052f}, // 0 - Fizzlebang start location + {548.610596f, 139.807800f, 394.321838f}, // 1 - fizzlebang end + {581.854187f, 138.0f, 394.319f}, // 2 - Portal Right + {550.558838f, 138.0f, 394.319f}, // 3 - Portal Left +}; + +static Position FactionChampionLoc[]= +{ + {514.231,105.569,418.234}, // 0 - Horde Initial Pos 0 + {508.334,115.377,418.234}, // 1 - Horde Initial Pos 1 + {506.454,126.291,418.234}, // 2 - Horde Initial Pos 2 + {506.243,106.596,421.592}, // 3 - Horde Initial Pos 3 + {499.885,117.717,421.557}, // 4 - Horde Initial Pos 4 + + {613.127,100.443,419.74}, // 5 - Ally Initial Pos 0 + {621.126,128.042,418.231}, // 6 - Ally Initial Pos 1 + {618.829,113.606,418.232}, // 7 - Ally Initial Pos 2 + {625.845,112.914,421.575}, // 8 - Ally Initial Pos 3 + {615.566,109.653,418.234}, // 9 - Ally Initial Pos 4 + + {535.469,113.012,394.66}, // 10 - Horde Final Pos 0 + {526.417,137.465,394.749}, // 11 - Horde Final Pos 1 + {528.108,111.057,395.289}, // 12 - Horde Final Pos 2 + {519.92,134.285,395.289}, // 13 - Horde Final Pos 3 + {533.648,119.148,394.646}, // 14 - Horde Final Pos 4 + {531.399,125.63,394.708}, // 15 - Horde Final Pos 5 + {528.958,131.47,394.73}, // 16 - Horde Final Pos 6 + {526.309,116.667,394.833}, // 17 - Horde Final Pos 7 + {524.238,122.411,394.819}, // 18 - Horde Final Pos 8 + {521.901,128.488,394.832}, // 19 - Horde Final Pos 9 +}; + +static Position TwinValkyrsLoc[]= +{ + {586.060242f, 117.514809f, 394.314026f}, // 0 - Dark essence 1 + {541.602112f, 161.879837f, 394.587952f}, // 1 - Dark essence 2 + {541.021118f, 117.262932f, 395.314819f}, // 2 - Light essence 1 + {586.200562f, 162.145523f, 394.626129f}, // 3 - Light essence 2 +}; + +static Position LichKingLoc[]= +{ + {563.549f, 152.474f, 394.393f}, // 0 - Lich king start + {563.547f, 141.613f, 393.908f}, // 1 - Lich king end +}; + +static Position AnubarakLoc[]= +{ + {787.932556f, 133.289780f, 142.612152f}, // 0 - Anub'arak start location + {695.240051f, 137.834824f, 142.200000f}, // 1 - Anub'arak move point location + {694.886353f, 102.484665f, 142.119614f}, // 3 - Nerub Spawn + {694.500671f, 185.363968f, 142.117905f}, // 5 - Nerub Spawn + {731.987244f, 83.3824690f, 142.119614f}, // 2 - Nerub Spawn + {740.184509f, 193.443390f, 142.117584f}, // 4 - Nerub Spawn +}; + +enum euiWorldStates +{ + UPDATE_STATE_UI_SHOW = 4390, + UPDATE_STATE_UI_COUNT = 4389, +}; + +enum eNorthrendBeasts +{ + GORMOK_IN_PROGRESS = 1000, + GORMOK_DONE = 1001, + SNAKES_IN_PROGRESS = 2000, + DREADSCALE_SUBMERGED = 2001, + ACIDMAW_SUBMERGED = 2002, + SNAKES_SPECIAL = 2003, + SNAKES_DONE = 2004, + ICEHOWL_IN_PROGRESS = 3000, + ICEHOWL_DONE = 3001, +}; + +enum eAnnouncerMessages +{ + MSG_BEASTS = 724001, + MSG_JARAXXUS = 724002, + MSG_CRUSADERS = 724003, + MSG_VALKIRIES = 724004, + MSG_LICH_KING = 724005, + MSG_ANUBARAK = 724006, +}; + +enum eCreature +{ + NPC_BARRENT = 34816, + NPC_TIRION = 34996, + NPC_FIZZLEBANG = 35458, + NPC_GARROSH = 34995, + NPC_VARIAN = 34990, + NPC_LICH_KING_0 = 16980, + NPC_LICH_KING_1 = 35877, + + NPC_THRALL = 34994, + NPC_PROUDMOORE = 34992, + NPC_WILFRED_PORTAL = 17965, + NPC_TRIGGER = 35651, + + NPC_ICEHOWL = 34797, + NPC_GORMOK = 34796, + NPC_DREADSCALE = 34799, + NPC_ACIDMAW = 35144, + + NPC_JARAXXUS = 34780, + + NPC_CHAMPIONS_CONTROLLER = 34781, + + NPC_ALLIANCE_DEATH_KNIGHT = 34461, + NPC_ALLIANCE_DRUID_BALANCE = 34460, + NPC_ALLIANCE_DRUID_RESTORATION = 34469, + NPC_ALLIANCE_HUNTER = 34467, + NPC_ALLIANCE_MAGE = 34468, + NPC_ALLIANCE_PALADIN_HOLY = 34465, + NPC_ALLIANCE_PALADIN_RETRIBUTION = 34471, + NPC_ALLIANCE_PRIEST_DISCIPLINE = 34466, + NPC_ALLIANCE_PRIEST_SHADOW = 34473, + NPC_ALLIANCE_ROGUE = 34472, + NPC_ALLIANCE_SHAMAN_ENHANCEMENT = 34463, + NPC_ALLIANCE_SHAMAN_RESTORATION = 34470, + NPC_ALLIANCE_WARLOCK = 34474, + NPC_ALLIANCE_WARRIOR = 34475, + + NPC_HORDE_DEATH_KNIGHT = 34458, + NPC_HORDE_DRUID_BALANCE = 34451, + NPC_HORDE_DRUID_RESTORATION = 34459, + NPC_HORDE_HUNTER = 34448, + NPC_HORDE_MAGE = 34449, + NPC_HORDE_PALADIN_HOLY = 34445, + NPC_HORDE_PALADIN_RETRIBUTION = 34456, + NPC_HORDE_PRIEST_DISCIPLINE = 34447, + NPC_HORDE_PRIEST_SHADOW = 34441, + NPC_HORDE_ROGUE = 34454, + NPC_HORDE_SHAMAN_ENHANCEMENT = 34455, + NPC_HORDE_SHAMAN_RESTORATION = 34444, + NPC_HORDE_WARLOCK = 34450, + NPC_HORDE_WARRIOR = 34453, + + NPC_LIGHTBANE = 34497, + NPC_DARKBANE = 34496, + + NPC_ANUBARAK = 34564, +}; + +enum eGameObject +{ + GO_CRUSADERS_CACHE_10 = 195631, + GO_CRUSADERS_CACHE_25 = 195632, + GO_CRUSADERS_CACHE_10_H = 195633, + GO_CRUSADERS_CACHE_25_H = 195635, + + // Tribute Chest (heroic) + // 10-man modes + GO_TRIBUTE_CHEST_10H_25 = 195668, // 10man 01-24 attempts + GO_TRIBUTE_CHEST_10H_45 = 195667, // 10man 25-44 attempts + GO_TRIBUTE_CHEST_10H_50 = 195666, // 10man 45-49 attempts + GO_TRIBUTE_CHEST_10H_99 = 195665, // 10man 50 attempts + // 25-man modes + GO_TRIBUTE_CHEST_25H_25 = 195672, // 25man 01-24 attempts + GO_TRIBUTE_CHEST_25H_45 = 195671, // 25man 25-44 attempts + GO_TRIBUTE_CHEST_25H_50 = 195670, // 25man 45-49 attempts + GO_TRIBUTE_CHEST_25H_99 = 195669, // 25man 50 attempts + + GO_ARGENT_COLISEUM_FLOOR = 195527, //20943 + GO_MAIN_GATE_DOOR = 195647, + GO_EAST_PORTCULLIS = 195648, + GO_WEB_DOOR = 195485, +}; + +enum eAchievementData +{ + // Northrend Beasts + UPPER_BACK_PAIN_10_PLAYER = 11779, + UPPER_BACK_PAIN_10_PLAYER_HEROIC = 11802, + UPPER_BACK_PAIN_25_PLAYER = 11780, + UPPER_BACK_PAIN_25_PLAYER_HEROIC = 11801, + // Lord Jaraxxus + THREE_SIXTY_PAIN_SPIKE_10_PLAYER = 11838, + THREE_SIXTY_PAIN_SPIKE_10_PLAYER_HEROIC = 11861, + THREE_SIXTY_PAIN_SPIKE_25_PLAYER = 11839, + THREE_SIXTY_PAIN_SPIKE_25_PLAYER_HEROIC = 11862, + // Tribute + A_TRIBUTE_TO_SKILL_10_PLAYER = 12344, + A_TRIBUTE_TO_SKILL_25_PLAYER = 12338, + A_TRIBUTE_TO_MAD_SKILL_10_PLAYER = 12347, + A_TRIBUTE_TO_MAD_SKILL_25_PLAYER = 12341, + A_TRIBUTE_TO_INSANITY_10_PLAYER = 12349, + A_TRIBUTE_TO_INSANITY_25_PLAYER = 12343, + A_TRIBUTE_TO_IMMORTALITY_HORDE = 12358, + A_TRIBUTE_TO_IMMORTALITY_ALLIANCE = 12359, + A_TRIBUTE_TO_DEDICATED_INSANITY = 12360, + REALM_FIRST_GRAND_CRUSADER = 12350, + + // Dummy spells - not existing in dbc but we don't need that + SPELL_WORMS_KILLED_IN_10_SECONDS = 68523, + SPELL_CHAMPIONS_KILLED_IN_MINUTE = 68620, + SPELL_DEFEAT_FACTION_CHAMPIONS = 68184, + SPELL_TRAITOR_KING_10 = 68186, + SPELL_TRAITOR_KING_25 = 68515, + + // Timed events + EVENT_START_TWINS_FIGHT = 21853 +}; + +#endif |