Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- From 3000e53cb260ff0fe2734628b897c96b7fe824fe Mon Sep 17 00:00:00 2001
- From: Skuallo <[email protected]>
- Date: Thu, 6 Nov 2025 14:58:14 +0100
- Subject: [PATCH] =?UTF-8?q?Prueba=20del=20Campe=C3=B3n?=
- MIME-Version: 1.0
- Content-Type: text/plain; charset=UTF-8
- Content-Transfer-Encoding: 8bit
- ---
- .../boss_argent_challenge.cpp | 1977 ++++++++----
- .../TrialOfTheChampion/boss_black_knight.cpp | 1203 ++++---
- .../boss_grand_champions.cpp | 2839 +++++++++++------
- .../instance_trial_of_the_champion.cpp | 682 ++--
- .../trial_of_the_champion.cpp | 1881 ++++++++---
- .../trial_of_the_champion.h | 436 ++-
- 6 files changed, 5912 insertions(+), 3106 deletions(-)
- rewrite src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp (73%)
- rewrite src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp (73%)
- rewrite src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp (75%)
- rewrite src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp (75%)
- rewrite src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp (66%)
- rewrite src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.h (74%)
- diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp
- dissimilarity index 73%
- index 8f2aa82f27..9c9169ec39 100644
- --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp
- +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp
- @@ -1,697 +1,1280 @@
- -/*
- - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
- - *
- - * 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, see <http://www.gnu.org/licenses/>.
- - */
- -
- -/* ScriptData
- -SDName: Argent Challenge Encounter.
- -SD%Complete: 50 %
- -SDComment: AI for Argent Soldiers are not implemented. AI from bosses need more improvements.
- -SDCategory: Trial of the Champion
- -EndScriptData */
- -
- -#include "ScriptMgr.h"
- -#include "Containers.h"
- -#include "InstanceScript.h"
- -#include "MotionMaster.h"
- -#include "ObjectAccessor.h"
- -#include "ScriptedEscortAI.h"
- -#include "SpellScript.h"
- -#include "TemporarySummon.h"
- -#include "trial_of_the_champion.h"
- -/*
- -enum Yells
- -{
- - // Eadric the Pure
- - SAY_INTRO = 0,
- - SAY_AGGRO = 1,
- - EMOTE_RADIANCE = 2,
- - EMOTE_HAMMER_RIGHTEOUS = 3,
- - SAY_HAMMER_RIGHTEOUS = 4,
- - SAY_KILL_PLAYER = 5,
- - SAY_DEFEATED = 6,
- -
- - // Argent Confessor Paletress
- - SAY_INTRO_1 = 0,
- - SAY_INTRO_2 = 1,
- - SAY_AGGRO = 2,
- - SAY_MEMORY_SUMMON = 3,
- - SAY_MEMORY_DEATH = 4,
- - SAY_KILL_PLAYER = 5,
- - SAY_DEFEATED = 6,
- -
- - // Memory of X
- - EMOTE_WAKING_NIGHTMARE = 0
- -};
- -*/
- -enum Spells
- -{
- - // Eadric the Pure
- - SPELL_EADRIC_ACHIEVEMENT = 68197,
- - SPELL_HAMMER_JUSTICE = 66863,
- - SPELL_HAMMER_RIGHTEOUS = 66867,
- - SPELL_RADIANCE = 66935,
- - SPELL_VENGEANCE = 66865,
- -
- - // Paletress
- - SPELL_SMITE = 66536,
- - SPELL_SMITE_H = 67674,
- - SPELL_HOLY_FIRE = 66538,
- - SPELL_HOLY_FIRE_H = 67676,
- - SPELL_RENEW = 66537,
- - SPELL_RENEW_H = 67675,
- - SPELL_HOLY_NOVA = 66546,
- - SPELL_SHIELD = 66515,
- - SPELL_CONFESS = 66680,
- - SPELL_SUMMON_MEMORY = 66545,
- -
- - // Memory of X (Summon)
- - SPELL_MEMORY_ALGALON = 66715,
- - SPELL_MEMORY_ARCHIMONDE = 66704,
- - SPELL_MEMORY_CHROMAGGUS = 66697,
- - SPELL_MEMORY_CYANIGOSA = 66709,
- - SPELL_MEMORY_DELRISSA = 66706,
- - SPELL_MEMORY_ECK = 66710,
- - SPELL_MEMORY_ENTROPIUS = 66707,
- - SPELL_MEMORY_GRUUL = 66702,
- - SPELL_MEMORY_HAKKAR = 66698,
- - SPELL_MEMORY_HEIGAN = 66712,
- - SPELL_MEMORY_HEROD = 66694,
- - SPELL_MEMORY_HOGGER = 66543,
- - SPELL_MEMORY_IGNIS = 66713,
- - SPELL_MEMORY_ILLIDAN = 66705,
- - SPELL_MEMORY_INGVAR = 66708,
- - SPELL_MEMORY_KALITHRESH = 66700,
- - SPELL_MEMORY_LUCIFRON = 66695,
- - SPELL_MEMORY_MALCHEZAAR = 66701,
- - SPELL_MEMORY_MUTANUS = 66692,
- - SPELL_MEMORY_ONYXIA = 66711,
- - SPELL_MEMORY_THUNDERAAN = 66696,
- - SPELL_MEMORY_VANCLEEF = 66691,
- - SPELL_MEMORY_VASHJ = 66703,
- - SPELL_MEMORY_VEKNILASH = 66699,
- - SPELL_MEMORY_VEZAX = 66714,
- -
- - // Memory
- - SPELL_OLD_WOUNDS = 66620,
- - SPELL_OLD_WOUNDS_H = 67679,
- - SPELL_SHADOWS_PAST = 66619,
- - SPELL_SHADOWS_PAST_H = 67678,
- - SPELL_WAKING_NIGHTMARE = 66552,
- - SPELL_WAKING_NIGHTMARE_H = 67677
- -};
- -
- -class OrientationCheck
- -{
- - public:
- - explicit OrientationCheck(Unit* _caster) : caster(_caster) { }
- - bool operator()(WorldObject* object)
- - {
- - return !object->isInFront(caster, 2.5f) || !object->IsWithinDist(caster, 40.0f);
- - }
- -
- - private:
- - Unit* caster;
- -};
- -
- -// 66862, 67681 - Radiance
- -class spell_eadric_radiance : public SpellScriptLoader
- -{
- - public:
- - spell_eadric_radiance() : SpellScriptLoader("spell_eadric_radiance") { }
- - class spell_eadric_radiance_SpellScript : public SpellScript
- - {
- - PrepareSpellScript(spell_eadric_radiance_SpellScript);
- -
- - void FilterTargets(std::list<WorldObject*>& unitList)
- - {
- - unitList.remove_if(OrientationCheck(GetCaster()));
- - }
- -
- - void Register() override
- - {
- - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_eadric_radiance_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
- - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_eadric_radiance_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY);
- - }
- - };
- -
- - SpellScript* GetSpellScript() const override
- - {
- - return new spell_eadric_radiance_SpellScript();
- - }
- -};
- -
- -class boss_eadric : public CreatureScript
- -{
- -public:
- - boss_eadric() : CreatureScript("boss_eadric") { }
- - struct boss_eadricAI : public ScriptedAI
- - {
- - boss_eadricAI(Creature* creature) : ScriptedAI(creature)
- - {
- - Initialize();
- - instance = creature->GetInstanceScript();
- - creature->SetReactState(REACT_PASSIVE);
- - creature->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- - }
- -
- - void Initialize()
- - {
- - uiVenganceTimer = 10000;
- - uiRadianceTimer = 16000;
- - uiHammerJusticeTimer = 25000;
- - uiResetTimer = 5000;
- -
- - bDone = false;
- - }
- -
- - InstanceScript* instance;
- -
- - uint32 uiVenganceTimer;
- - uint32 uiRadianceTimer;
- - uint32 uiHammerJusticeTimer;
- - uint32 uiResetTimer;
- -
- - bool bDone;
- -
- - void Reset() override
- - {
- - Initialize();
- - }
- -
- - void DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
- - {
- - if (damage >= me->GetHealth())
- - {
- - damage = 0;
- - EnterEvadeMode();
- - me->SetFaction(FACTION_FRIENDLY);
- - bDone = true;
- - }
- - }
- -
- - void MovementInform(uint32 MovementType, uint32 /*Data*/) override
- - {
- - if (MovementType != POINT_MOTION_TYPE)
- - return;
- -
- - instance->SetBossState(BOSS_ARGENT_CHALLENGE_E, DONE);
- -
- - me->DisappearAndDie();
- - }
- -
- - void UpdateAI(uint32 uiDiff) override
- - {
- - if (bDone && uiResetTimer <= uiDiff)
- - {
- - me->GetMotionMaster()->MovePoint(0, 746.87f, 665.87f, 411.75f);
- - bDone = false;
- - } else uiResetTimer -= uiDiff;
- -
- - if (!UpdateVictim())
- - return;
- -
- - if (uiHammerJusticeTimer <= uiDiff)
- - {
- - me->InterruptNonMeleeSpells(true);
- -
- - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 250, true))
- - {
- - if (target->IsAlive())
- - {
- - DoCast(target, SPELL_HAMMER_JUSTICE);
- - DoCast(target, SPELL_HAMMER_RIGHTEOUS);
- - }
- - }
- - uiHammerJusticeTimer = 25000;
- - } else uiHammerJusticeTimer -= uiDiff;
- -
- - if (uiVenganceTimer <= uiDiff)
- - {
- - DoCast(me, SPELL_VENGEANCE);
- -
- - uiVenganceTimer = 10000;
- - } else uiVenganceTimer -= uiDiff;
- -
- - if (uiRadianceTimer <= uiDiff)
- - {
- - DoCastAOE(SPELL_RADIANCE);
- -
- - uiRadianceTimer = 16000;
- - } else uiRadianceTimer -= uiDiff;
- -
- - DoMeleeAttackIfReady();
- - }
- - };
- -
- - CreatureAI* GetAI(Creature* creature) const override
- - {
- - return GetTrialOfTheChampionAI<boss_eadricAI>(creature);
- - }
- -};
- -
- -class boss_paletress : public CreatureScript
- -{
- -public:
- - boss_paletress() : CreatureScript("boss_paletress") { }
- -
- - struct boss_paletressAI : public ScriptedAI
- - {
- - boss_paletressAI(Creature* creature) : ScriptedAI(creature)
- - {
- - Initialize();
- - instance = creature->GetInstanceScript();
- -
- - creature->SetReactState(REACT_PASSIVE);
- - creature->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- - creature->RestoreFaction();
- - }
- -
- - void Initialize()
- - {
- - uiHolyFireTimer = urand(9000, 12000);
- - uiHolySmiteTimer = urand(5000, 7000);
- - uiRenewTimer = urand(2000, 5000);
- -
- - uiResetTimer = 7000;
- -
- - bHealth = false;
- - bDone = false;
- - }
- -
- - InstanceScript* instance;
- - ObjectGuid MemoryGUID;
- -
- - bool bHealth;
- - bool bDone;
- -
- - uint32 uiHolyFireTimer;
- - uint32 uiHolySmiteTimer;
- - uint32 uiRenewTimer;
- - uint32 uiResetTimer;
- -
- - void Reset() override
- - {
- - me->RemoveAllAuras();
- -
- - Initialize();
- -
- - if (Creature* pMemory = ObjectAccessor::GetCreature(*me, MemoryGUID))
- - if (pMemory->IsAlive())
- - pMemory->RemoveFromWorld();
- - }
- -
- - void SetData(uint32 uiId, uint32 /*uiValue*/) override
- - {
- - if (uiId == 1)
- - me->RemoveAura(SPELL_SHIELD);
- - }
- -
- - void DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
- - {
- - if (damage >= me->GetHealth())
- - {
- - damage = 0;
- - EnterEvadeMode();
- - me->SetFaction(FACTION_FRIENDLY);
- - bDone = true;
- - }
- - }
- -
- - void MovementInform(uint32 MovementType, uint32 Point) override
- - {
- - if (MovementType != POINT_MOTION_TYPE || Point != 0)
- - return;
- -
- - instance->SetBossState(BOSS_ARGENT_CHALLENGE_P, DONE);
- -
- - me->DisappearAndDie();
- - }
- -
- - void UpdateAI(uint32 uiDiff) override
- - {
- - if (bDone && uiResetTimer <= uiDiff)
- - {
- - me->GetMotionMaster()->MovePoint(0, 746.87f, 665.87f, 411.75f);
- - bDone = false;
- - } else uiResetTimer -= uiDiff;
- -
- - if (!UpdateVictim())
- - return;
- -
- - if (uiHolyFireTimer <= uiDiff)
- - {
- - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 250, true))
- - {
- - if (target->IsAlive())
- - DoCast(target, SPELL_HOLY_FIRE);
- - }
- - if (me->HasAura(SPELL_SHIELD))
- - uiHolyFireTimer = 13000;
- - else
- - uiHolyFireTimer = urand(9000, 12000);
- - } else uiHolyFireTimer -= uiDiff;
- -
- - if (uiHolySmiteTimer <= uiDiff)
- - {
- - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 250, true))
- - {
- - if (target->IsAlive())
- - DoCast(target, SPELL_SMITE);
- - }
- - if (me->HasAura(SPELL_SHIELD))
- - uiHolySmiteTimer = 9000;
- - else
- - uiHolySmiteTimer = urand(5000, 7000);
- - } else uiHolySmiteTimer -= uiDiff;
- -
- - if (me->HasAura(SPELL_SHIELD))
- - {
- - if (uiRenewTimer <= uiDiff)
- - {
- - me->InterruptNonMeleeSpells(true);
- - uint8 uiTarget = urand(0, 1);
- - switch (uiTarget)
- - {
- - case 0:
- - DoCast(me, SPELL_RENEW);
- - break;
- - case 1:
- - if (Creature* pMemory = ObjectAccessor::GetCreature(*me, MemoryGUID))
- - if (pMemory->IsAlive())
- - DoCast(pMemory, SPELL_RENEW);
- - break;
- - }
- - uiRenewTimer = urand(15000, 17000);
- - } else uiRenewTimer -= uiDiff;
- - }
- -
- - if (!bHealth && !HealthAbovePct(25))
- - {
- - me->InterruptNonMeleeSpells(true);
- - DoCastAOE(SPELL_HOLY_NOVA, false);
- - DoCast(me, SPELL_SHIELD);
- - DoCastAOE(SPELL_SUMMON_MEMORY, false);
- - DoCastAOE(SPELL_CONFESS, false);
- -
- - bHealth = true;
- - }
- -
- - DoMeleeAttackIfReady();
- - }
- -
- - void JustSummoned(Creature* summon) override
- - {
- - MemoryGUID = summon->GetGUID();
- - }
- - };
- -
- - CreatureAI* GetAI(Creature* creature) const override
- - {
- - return GetTrialOfTheChampionAI<boss_paletressAI>(creature);
- - }
- -};
- -
- -class npc_memory : public CreatureScript
- -{
- -public:
- - npc_memory() : CreatureScript("npc_memory") { }
- -
- - struct npc_memoryAI : public ScriptedAI
- - {
- - npc_memoryAI(Creature* creature) : ScriptedAI(creature)
- - {
- - Initialize();
- - }
- -
- - void Initialize()
- - {
- - uiOldWoundsTimer = 12000;
- - uiShadowPastTimer = 5000;
- - uiWakingNightmare = 7000;
- - }
- -
- - uint32 uiOldWoundsTimer;
- - uint32 uiShadowPastTimer;
- - uint32 uiWakingNightmare;
- -
- - void Reset() override
- - {
- - Initialize();
- - }
- -
- - void UpdateAI(uint32 uiDiff) override
- - {
- - if (!UpdateVictim())
- - return;
- -
- - if (uiOldWoundsTimer <= uiDiff)
- - {
- - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
- - {
- - if (target->IsAlive())
- - DoCast(target, SPELL_OLD_WOUNDS);
- - }
- - uiOldWoundsTimer = 12000;
- - }else uiOldWoundsTimer -= uiDiff;
- -
- - if (uiWakingNightmare <= uiDiff)
- - {
- - DoCast(me, SPELL_WAKING_NIGHTMARE);
- - uiWakingNightmare = 7000;
- - }else uiWakingNightmare -= uiDiff;
- -
- - if (uiShadowPastTimer <= uiDiff)
- - {
- - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1))
- - {
- - if (target->IsAlive())
- - DoCast(target, SPELL_SHADOWS_PAST);
- - }
- - uiShadowPastTimer = 5000;
- - }else uiShadowPastTimer -= uiDiff;
- -
- - DoMeleeAttackIfReady();
- - }
- -
- - void JustDied(Unit* /*killer*/) override
- - {
- - if (TempSummon* summ = me->ToTempSummon())
- - if (Unit* summoner = summ->GetSummonerUnit())
- - if (summoner->IsAlive())
- - summoner->GetAI()->SetData(1, 0);
- - }
- - };
- -
- - CreatureAI* GetAI(Creature* creature) const override
- - {
- - return GetTrialOfTheChampionAI<npc_memoryAI>(creature);
- - }
- -};
- -
- -class npc_argent_soldier : public CreatureScript
- -{
- -public:
- - npc_argent_soldier() : CreatureScript("npc_argent_soldier") { }
- -
- - // THIS AI NEEDS MORE IMPROVEMENTS
- - struct npc_argent_soldierAI : public EscortAI
- - {
- - npc_argent_soldierAI(Creature* creature) : EscortAI(creature)
- - {
- - instance = creature->GetInstanceScript();
- - me->SetReactState(REACT_DEFENSIVE);
- - SetDespawnAtEnd(false);
- - uiWaypoint = 0;
- - }
- -
- - InstanceScript* instance;
- -
- - uint8 uiWaypoint;
- -
- - void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
- - {
- - if (waypointId == 0)
- - {
- - switch (uiWaypoint)
- - {
- - case 0:
- - me->SetFacingTo(5.81f);
- - break;
- - case 1:
- - me->SetFacingTo(4.60f);
- - break;
- - case 2:
- - me->SetFacingTo(2.79f);
- - break;
- - }
- - }
- - }
- -
- - void SetData(uint32 uiType, uint32 /*uiData*/) override
- - {
- - switch (me->GetEntry())
- - {
- - case NPC_ARGENT_LIGHWIELDER:
- - switch (uiType)
- - {
- - case 0:
- - AddWaypoint(0, 712.14f, 628.42f, 411.88f);
- - break;
- - case 1:
- - AddWaypoint(0, 742.44f, 650.29f, 411.79f);
- - break;
- - case 2:
- - AddWaypoint(0, 783.33f, 615.29f, 411.84f);
- - break;
- - }
- - break;
- - case NPC_ARGENT_MONK:
- - switch (uiType)
- - {
- - case 0:
- - AddWaypoint(0, 713.12f, 632.97f, 411.90f);
- - break;
- - case 1:
- - AddWaypoint(0, 746.73f, 650.24f, 411.56f);
- - break;
- - case 2:
- - AddWaypoint(0, 781.32f, 610.54f, 411.82f);
- - break;
- - }
- - break;
- - case NPC_PRIESTESS:
- - switch (uiType)
- - {
- - case 0:
- - AddWaypoint(0, 715.06f, 637.07f, 411.91f);
- - break;
- - case 1:
- - AddWaypoint(0, 750.72f, 650.20f, 411.77f);
- - break;
- - case 2:
- - AddWaypoint(0, 779.77f, 607.03f, 411.81f);
- - break;
- - }
- - break;
- - }
- -
- - Start(false, true);
- - uiWaypoint = uiType;
- - }
- -
- - void UpdateAI(uint32 uiDiff) override
- - {
- - EscortAI::UpdateAI(uiDiff);
- -
- - if (!UpdateVictim())
- - return;
- -
- - DoMeleeAttackIfReady();
- - }
- -
- - void JustDied(Unit* /*killer*/) override
- - {
- - instance->SetData(DATA_ARGENT_SOLDIER_DEFEATED, instance->GetData(DATA_ARGENT_SOLDIER_DEFEATED) + 1);
- - }
- - };
- -
- - CreatureAI* GetAI(Creature* creature) const override
- - {
- - return GetTrialOfTheChampionAI<npc_argent_soldierAI>(creature);
- - }
- -};
- -
- -uint32 const memorySpellId[25] =
- -{
- - SPELL_MEMORY_ALGALON,
- - SPELL_MEMORY_ARCHIMONDE,
- - SPELL_MEMORY_CHROMAGGUS,
- - SPELL_MEMORY_CYANIGOSA,
- - SPELL_MEMORY_DELRISSA,
- - SPELL_MEMORY_ECK,
- - SPELL_MEMORY_ENTROPIUS,
- - SPELL_MEMORY_GRUUL,
- - SPELL_MEMORY_HAKKAR,
- - SPELL_MEMORY_HEIGAN,
- - SPELL_MEMORY_HEROD,
- - SPELL_MEMORY_HOGGER,
- - SPELL_MEMORY_IGNIS,
- - SPELL_MEMORY_ILLIDAN,
- - SPELL_MEMORY_INGVAR,
- - SPELL_MEMORY_KALITHRESH,
- - SPELL_MEMORY_LUCIFRON,
- - SPELL_MEMORY_MALCHEZAAR,
- - SPELL_MEMORY_MUTANUS,
- - SPELL_MEMORY_ONYXIA,
- - SPELL_MEMORY_THUNDERAAN,
- - SPELL_MEMORY_VANCLEEF,
- - SPELL_MEMORY_VASHJ,
- - SPELL_MEMORY_VEKNILASH,
- - SPELL_MEMORY_VEZAX
- -};
- -
- -// 66545 - Summon Memory
- -class spell_paletress_summon_memory : public SpellScriptLoader
- -{
- - public:
- - spell_paletress_summon_memory() : SpellScriptLoader("spell_paletress_summon_memory") { }
- -
- - class spell_paletress_summon_memory_SpellScript : public SpellScript
- - {
- - PrepareSpellScript(spell_paletress_summon_memory_SpellScript);
- -
- - bool Validate(SpellInfo const* /*spellInfo*/) override
- - {
- - return ValidateSpellInfo(memorySpellId);
- - }
- -
- - void FilterTargets(std::list<WorldObject*>& targets)
- - {
- - if (targets.empty())
- - return;
- -
- - WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
- - targets.clear();
- - targets.push_back(target);
- - }
- -
- - void HandleScript(SpellEffIndex /*effIndex*/)
- - {
- - GetHitUnit()->CastSpell(GetHitUnit(), memorySpellId[urand(0, 24)], GetCaster()->GetGUID());
- - }
- -
- - void Register() override
- - {
- - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_paletress_summon_memory_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
- - OnEffectHitTarget += SpellEffectFn(spell_paletress_summon_memory_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- - }
- - };
- -
- - SpellScript* GetSpellScript() const override
- - {
- - return new spell_paletress_summon_memory_SpellScript();
- - }
- -};
- -
- -void AddSC_boss_argent_challenge()
- -{
- - new boss_eadric();
- - new spell_eadric_radiance();
- - new boss_paletress();
- - new npc_memory();
- - new npc_argent_soldier();
- - new spell_paletress_summon_memory();
- -}
- +/*
- + * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
- + *
- + * This program is free software; you can redistribute it and/or modify it
- + * under the terms of the GNU General Public License as published by the
- + * Free Software Foundation; either version 2 of the License, or (at your
- + * option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- + * more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program. If not, see <http://www.gnu.org/licenses/>.
- + */
- +
- + /* ScriptData
- + SDName: Argent Challenge Encounter.
- + SD%Complete: 100%
- + SDComment:
- + SDCategory: Trial of the Champion
- + EndScriptData */
- +
- +#include "Player.h"
- +#include "ScriptMgr.h"
- +#include "ScriptedCreature.h"
- +#include "SpellAuraEffects.h"
- +#include "SpellScript.h"
- +#include "SpellMgr.h"
- +#include "trial_of_the_champion.h"
- +#include "TemporarySummon.h"
- +
- +uint32 SelectRandomMemorySpell()
- +{
- + static uint32 const memorySpellIds[] = {
- + 66715, // SPELL_MEMORY_ALGALON
- + 66704, // SPELL_MEMORY_ARCHIMONDE
- + 66697, // SPELL_MEMORY_CHROMAGGUS
- + 66709, // SPELL_MEMORY_CYANIGOSA
- + 66706, // SPELL_MEMORY_DELRISSA
- + 66710, // SPELL_MEMORY_ECK
- + 66707, // SPELL_MEMORY_ENTROPIUS
- + 66702, // SPELL_MEMORY_GRUUL
- + 66698, // SPELL_MEMORY_HAKKAR
- + 66712, // SPELL_MEMORY_HEIGAN
- + 66694, // SPELL_MEMORY_HEROD
- + 66543, // SPELL_MEMORY_HOGGER
- + 66713, // SPELL_MEMORY_IGNIS
- + 66705, // SPELL_MEMORY_ILLIDAN
- + 66708, // SPELL_MEMORY_INGVAR
- + 66700, // SPELL_MEMORY_KALITHRESH
- + 66695, // SPELL_MEMORY_LUCIFRON
- + 66701, // SPELL_MEMORY_MALCHEZAAR
- + 66692, // SPELL_MEMORY_MUTANUS
- + 66711, // SPELL_MEMORY_ONYXIA
- + 66696, // SPELL_MEMORY_THUNDERAAN
- + 66691, // SPELL_MEMORY_VANCLEEF
- + 66703, // SPELL_MEMORY_VASHJ
- + 66699, // SPELL_MEMORY_VEKNILASH
- + 66714 // SPELL_MEMORY_VEZAX
- + };
- +
- + return memorySpellIds[urand(0, 24)];
- +}
- +
- +enum Yells
- +{
- + // Eadric the Pure
- + SAY_AGGRO_E = 1,
- + EMOTE_RADIANCE = 2,
- + EMOTE_HAMMER_RIGHTEOUS = 3,
- + SAY_HAMMER_RIGHTEOUS = 4,
- + SAY_KILL_UNIT_E = 5,
- + SAY_DEFEATED_E = 6,
- +
- + // Argent Confessor Paletress
- + SAY_AGGRO_P = 2,
- + SAY_MEMORY_SUMMON = 3,
- + SAY_MEMORY_DEATH = 4,
- + SAY_KILL_UNIT_P = 5,
- + SAY_DEFEATED_P = 6,
- +
- + // Memory of X
- + EMOTE_WAKING_NIGHTMARE = 0
- +};
- +
- +enum Events
- +{
- + // Argent Lightwielder
- + EVENT_BLAZING_LIGHT = 1,
- + EVENT_CLEAVE,
- + EVENT_UNBALANCING_STRIKE,
- +
- + // Argent Monk
- + EVENT_FLURRY_OF_BLOWS,
- + EVENT_PUMMEL,
- +
- + // Argent Priestess
- + EVENT_HOLY_SMITE,
- + EVENT_SHADOW_WORD_PAIN,
- + EVENT_FOUNTAIN,
- + EVENT_MIND_CONTROL,
- +
- + // Argent Confessor Paletress
- + EVENT_HOLY_FIRE,
- + EVENT_HOLY_SMITE_E,
- + EVENT_RENEW,
- + EVENT_SUMMON_MEMORY,
- +
- + // Memory
- + EVENT_ENTER_AGGRESSIVE,
- + EVENT_OLD_WOUNDS,
- + EVENT_SHADOWS_PAST,
- + EVENT_WAKING_NIGHTMARE,
- +
- + // Eadric the Pure
- + EVENT_RADIANCE,
- + EVENT_HAMMER_OF_JUSTICE,
- +
- + // Shared
- + EVENT_CHALLENGE_DONE
- +};
- +
- +enum Spells
- +{
- + // Argent Lightwielder
- + SPELL_BLAZING_LIGHT = 67247,
- + SPELL_CLEAVE = 15284,
- + SPELL_UNBALANCING_STRIKE = 67237,
- +
- + // Argent Monk
- + SPELL_FLURRY_OF_BLOWS = 67233,
- + SPELL_PUMMEL = 67235,
- + SPELL_DIVINE_SHIELD = 67251,
- + SPELL_FINAL_MEDITATION = 67255,
- +
- + // Argent Priestess
- + SPELL_HOLY_SMITE = 36176,
- + SPELL_SHADOW_WORD_PAIN = 34941,
- + SPELL_MIND_CONTROL = 67229,
- + SPELL_SUMMON_FOUNTAIN = 67194,
- +
- + // Eadric the Pure
- + SPELL_EADRIC_FACEROLLER = 68197,
- + SPELL_HAMMER_JUSTICE = 66863,
- + SPELL_HAMMER_JUSTICE_STUN = 66940,
- + SPELL_HAMMER_RIGHTEOUS = 66867,
- + SPELL_HAMMER_RIGHT_DUMMY = 66904,
- + SPELL_HAMMER_RIGHTEOUS_PLR = 66905,
- + SPELL_RADIANCE = 66935,
- + SPELL_VENGEANCE = 66865,
- + SPELL_EADRIC_ACH = 68575, // dummy spell for achievement credit (IDs 4297, 4298, 3778, 4296)
- +
- + // Paletress
- + SPELL_PALETRESS_CONFESSOR = 68206, // achievement id 3802
- + SPELL_SMITE = 66536,
- + SPELL_HOLY_FIRE = 66538,
- + SPELL_RENEW = 66537,
- + SPELL_HOLY_NOVA = 66546,
- + SPELL_SHIELD = 66515,
- + SPELL_SHIELD_REFLECT = 33619,
- + SPELL_CONFESS = 66680,
- + SPELL_SUMMON_MEMORY = 66545,
- + SPELL_PALETRESS_ACH = 68574, // dummy spell for achievement credit (IDs 4297, 4298, 3778, 4296)
- +
- + // Memory of X (Summon)
- + SPELL_MEMORY_ALGALON = 66715,
- + SPELL_MEMORY_ARCHIMONDE = 66704,
- + SPELL_MEMORY_CHROMAGGUS = 66697,
- + SPELL_MEMORY_CYANIGOSA = 66709,
- + SPELL_MEMORY_DELRISSA = 66706,
- + SPELL_MEMORY_ECK = 66710,
- + SPELL_MEMORY_ENTROPIUS = 66707,
- + SPELL_MEMORY_GRUUL = 66702,
- + SPELL_MEMORY_HAKKAR = 66698,
- + SPELL_MEMORY_HEIGAN = 66712,
- + SPELL_MEMORY_HEROD = 66694,
- + SPELL_MEMORY_HOGGER = 66543,
- + SPELL_MEMORY_IGNIS = 66713,
- + SPELL_MEMORY_ILLIDAN = 66705,
- + SPELL_MEMORY_INGVAR = 66708,
- + SPELL_MEMORY_KALITHRESH = 66700,
- + SPELL_MEMORY_LUCIFRON = 66695,
- + SPELL_MEMORY_MALCHEZAAR = 66701,
- + SPELL_MEMORY_MUTANUS = 66692,
- + SPELL_MEMORY_ONYXIA = 66711,
- + SPELL_MEMORY_THUNDERAAN = 66696,
- + SPELL_MEMORY_VANCLEEF = 66691,
- + SPELL_MEMORY_VASHJ = 66703,
- + SPELL_MEMORY_VEKNILASH = 66699,
- + SPELL_MEMORY_VEZAX = 66714,
- +
- + // Memory
- + SPELL_SHADOWFORM = 41408,
- + SPELL_SPAWN_VISUAL = 66675,
- + SPELL_OLD_WOUNDS = 66620,
- + SPELL_SHADOWS_PAST = 66619,
- + SPELL_WAKING_NIGHTMARE = 66552
- +};
- +
- +enum PointMovement
- +{
- + POINT_PREFIGHT = 0,
- + POINT_PREPARE,
- + POINT_DESPAWN
- +};
- +
- +struct argent_challenge_baseAI : public BossAI
- +{
- + argent_challenge_baseAI(Creature* creature) : BossAI(creature, DATA_ARGENT_CHALLENGE)
- + {
- + Initialize();
- + creature->SetReactState(REACT_DEFENSIVE);
- + }
- +
- + virtual void Initialize() {}
- +
- + virtual void OnReset()
- + {
- + _Reset();
- + }
- +
- + void EnterEvadeMode(EvadeReason /*why*/) final override
- + {
- + if (instance->GetBossState(DATA_ARGENT_CHALLENGE) != SPECIAL &&
- + instance->GetBossState(DATA_ARGENT_CHALLENGE) != DONE)
- + BossAI::EnterEvadeMode();
- + }
- +
- + void JustReachedHome() final override
- + {
- + if (instance->GetBossState(DATA_ARGENT_CHALLENGE) == SPECIAL)
- + events.ScheduleEvent(EVENT_CHALLENGE_DONE, 4s);
- + else
- + me->SetEmoteState(EMOTE_STATE_READY1H);
- + }
- +
- + void Reset() final override
- + {
- + if (instance->GetBossState(DATA_ARGENT_CHALLENGE) != SPECIAL)
- + OnReset();
- + }
- +
- + void AttackStart(Unit* who) final override
- + {
- + if (!me->HasAura(SPELL_SHIELD) && instance->GetBossState(DATA_ARGENT_CHALLENGE) != SPECIAL)
- + BossAI::AttackStart(who);
- + }
- +
- + void MovementInform(uint32 type, uint32 id) final override
- + {
- + if (type != POINT_MOTION_TYPE)
- + return;
- +
- + switch (id)
- + {
- + case POINT_PREFIGHT:
- + if (Creature* announcer = instance->GetCreature(DATA_ANNOUNCER))
- + announcer->AI()->SetData(DATA_ARGENT_CHAMPION_PREPARE, 0);
- + break;
- + case POINT_PREPARE:
- + me->SetWalk(false);
- + me->SetEmoteState(EMOTE_STATE_READY1H);
- + break;
- + case POINT_DESPAWN:
- + me->DisappearAndDie();
- + break;
- + default:
- + break;
- + }
- + }
- +};
- +
- +enum EadricData
- +{
- + DATA_FACEROLLER_ACHIEVEMENT = 1
- +};
- +
- +class boss_eadric : public CreatureScript
- +{
- +public:
- + boss_eadric() : CreatureScript("boss_eadric") {}
- +
- + struct boss_eadricAI : public argent_challenge_baseAI
- + {
- + boss_eadricAI(Creature* creature) : argent_challenge_baseAI(creature) {}
- +
- + void Initialize() override
- + {
- + _faceroller = false;
- + }
- +
- + void SetData(uint32 type, uint32 data) override
- + {
- + if (type != DATA_FACEROLLER_ACHIEVEMENT)
- + return;
- +
- + _faceroller = (data == 1);
- + }
- +
- + uint32 GetData(uint32 type) const override
- + {
- + if (type != DATA_FACEROLLER_ACHIEVEMENT)
- + return 0;
- +
- + return _faceroller ? 1 : 0;
- + }
- +
- + void OnReset() override
- + {
- + Initialize();
- + argent_challenge_baseAI::OnReset();
- + }
- +
- + void DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
- + {
- + if (instance->GetBossState(DATA_ARGENT_CHALLENGE) == DONE)
- + {
- + damage = 0;
- + return;
- + }
- +
- + if (damage >= me->GetHealth())
- + {
- + damage = me->GetHealth() - 1;
- + if (instance->GetBossState(DATA_ARGENT_CHALLENGE) != SPECIAL)
- + {
- + instance->SetBossState(DATA_ARGENT_CHALLENGE, SPECIAL);
- + events.Reset();
- + Talk(SAY_DEFEATED_E);
- + }
- + }
- + }
- +
- + void JustEngagedWith(Unit* who) override
- + {
- + if (instance->GetBossState(DATA_ARGENT_CHALLENGE) == SPECIAL)
- + return;
- +
- + DoCastAOE(SPELL_VENGEANCE);
- + events.ScheduleEvent(EVENT_RADIANCE, 7s, 15s);
- + Talk(SAY_AGGRO_E, who);
- + _JustEngagedWith(who);
- + }
- +
- + void KilledUnit(Unit* who) override
- + {
- + if (who->GetTypeId() == TYPEID_PLAYER)
- + Talk(SAY_KILL_UNIT_E, who);
- + }
- +
- + void UpdateAI(uint32 diff) override
- + {
- + events.Update(diff);
- +
- + if (me->HasUnitState(UNIT_STATE_CASTING))
- + return;
- +
- + while (uint32 eventId = events.ExecuteEvent())
- + {
- + switch (eventId)
- + {
- + case EVENT_RADIANCE:
- + DoCastAOE(SPELL_RADIANCE);
- + Talk(EMOTE_RADIANCE);
- + events.ScheduleEvent(EVENT_HAMMER_OF_JUSTICE, 20s, 30s);
- + break;
- + case EVENT_HAMMER_OF_JUSTICE:
- + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
- + {
- + DoCast(target, SPELL_HAMMER_JUSTICE, true);
- + DoCast(target, SPELL_HAMMER_RIGHTEOUS);
- + Talk(EMOTE_HAMMER_RIGHTEOUS, target);
- + Talk(SAY_HAMMER_RIGHTEOUS);
- + }
- + events.ScheduleEvent(EVENT_RADIANCE, 7s, 15s);
- + break;
- + case EVENT_CHALLENGE_DONE:
- + me->RemoveAllAuras();
- + me->GetThreatManager().ClearAllThreat();
- + me->SetFullHealth();
- + me->RestoreFaction();
- + DoCastAOE(SPELL_EADRIC_ACH, true);
- + DoCastAOE(SPELL_EADRIC_FACEROLLER, true);
- +
- + _JustDied();
- + me->SetWalk(true);
- + me->GetMotionMaster()->MovePoint(POINT_DESPAWN, bossExitPos);
- + break;
- + default:
- + break;
- + }
- + }
- +
- + if (!UpdateVictim())
- + return;
- +
- + DoMeleeAttackIfReady();
- + }
- +
- + private:
- + bool _faceroller;
- + };
- +
- + CreatureAI* GetAI(Creature* creature) const override
- + {
- + return GetTrialOfChampionAI<boss_eadricAI>(creature);
- + }
- +};
- +
- +enum PaletressData
- +{
- + DATA_MEMORY_ENTRY = 1,
- +
- + ACTION_MEMORY_DEATH
- +};
- +
- +class boss_paletress : public CreatureScript
- +{
- +public:
- + boss_paletress() : CreatureScript("boss_paletress") {}
- +
- + struct boss_paletressAI : public argent_challenge_baseAI
- + {
- + boss_paletressAI(Creature* creature) : argent_challenge_baseAI(creature) {}
- +
- + void Initialize() override
- + {
- + argent_challenge_baseAI::Initialize();
- + _memorySummoned = false;
- + }
- +
- + void OnReset() override
- + {
- + me->RemoveAura(SPELL_SHIELD);
- + Initialize();
- + argent_challenge_baseAI::OnReset();
- + }
- +
- + void DoAction(int32 action) override
- + {
- + if (action != ACTION_MEMORY_DEATH)
- + return;
- +
- + me->InterruptNonMeleeSpells(true);
- + Talk(SAY_MEMORY_DEATH);
- + me->GetMotionMaster()->Clear();
- + me->RemoveAura(SPELL_SHIELD);
- + }
- +
- + uint32 GetData(uint32 type) const override
- + {
- + if (type != DATA_MEMORY_ENTRY || _memoryGuid.IsEmpty())
- + return 0;
- +
- + return _memoryGuid.GetEntry();
- + }
- +
- + void DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
- + {
- + if (instance->GetBossState(DATA_ARGENT_CHALLENGE) == DONE)
- + {
- + damage = 0;
- + return;
- + }
- +
- + if (!_memorySummoned && !HealthAbovePct(25))
- + {
- + _memorySummoned = true;
- +
- + me->InterruptNonMeleeSpells(true);
- + DoCastAOE(SPELL_HOLY_NOVA);
- + Talk(SAY_MEMORY_SUMMON);
- + DoCastAOE(SPELL_SHIELD);
- + DoCastAOE(SPELL_CONFESS);
- + me->AttackStop();
- + events.ScheduleEvent(EVENT_SUMMON_MEMORY, 2s);
- + }
- +
- + if (damage >= me->GetHealth())
- + {
- + damage = me->GetHealth() - 1;
- + if (instance->GetBossState(DATA_ARGENT_CHALLENGE) != SPECIAL)
- + {
- + instance->SetBossState(DATA_ARGENT_CHALLENGE, SPECIAL);
- + events.Reset();
- + Talk(SAY_DEFEATED_P);
- + }
- + }
- + }
- +
- + void JustSummoned(Creature* summon) override
- + {
- + argent_challenge_baseAI::JustSummoned(summon);
- +
- + _memoryGuid = summon->GetGUID();
- + me->GetMotionMaster()->MoveFollow(summon, 30.0f, 0.0f);
- + }
- +
- + void JustEngagedWith(Unit* who) override
- + {
- + if (instance->GetBossState(DATA_ARGENT_CHALLENGE) == SPECIAL)
- + return;
- +
- + events.ScheduleEvent(EVENT_HOLY_SMITE_E, 2s);
- + events.ScheduleEvent(EVENT_HOLY_FIRE, 9s, 12s);
- + events.ScheduleEvent(EVENT_RENEW, 15s, 17s);
- + Talk(SAY_AGGRO_P, who);
- + _JustEngagedWith(who);
- + }
- +
- + void KilledUnit(Unit* who) override
- + {
- + if (who->GetTypeId() == TYPEID_PLAYER)
- + Talk(SAY_KILL_UNIT_P, who);
- + }
- +
- + void UpdateAI(uint32 diff) override
- + {
- + events.Update(diff);
- +
- + while (uint32 eventId = events.ExecuteEvent())
- + {
- + switch (eventId)
- + {
- + case EVENT_HOLY_SMITE_E:
- + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true))
- + DoCast(target, SPELL_SMITE);
- + events.Repeat(2s, 3s);
- + break;
- + case EVENT_HOLY_FIRE:
- + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 30.0f, true))
- + DoCast(target, SPELL_HOLY_FIRE);
- + events.Repeat(9s, 12s);
- + break;
- + case EVENT_RENEW:
- + me->InterruptNonMeleeSpells(true);
- + if ((rand32() % 2) > 0 && me->GetHealthPct() < 100)
- + DoCastSelf(SPELL_RENEW);
- + else
- + {
- + Creature* memory = ObjectAccessor::GetCreature(*me, _memoryGuid);
- + if (memory && memory->GetHealth() > 1)
- + DoCast(memory, SPELL_RENEW);
- + else
- + DoCastSelf(SPELL_RENEW);
- + }
- +
- + events.Repeat(15s, 17s);
- + break;
- + case EVENT_SUMMON_MEMORY:
- + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true))
- + DoCast(target, SPELL_SUMMON_MEMORY, true);
- + break;
- + case EVENT_CHALLENGE_DONE:
- + me->RemoveAllAuras();
- + me->GetThreatManager().ClearAllThreat();
- + me->SetFullHealth();
- + DoCastAOE(SPELL_PALETRESS_ACH, true);
- + me->RestoreFaction();
- +
- + if (IsHeroic())
- + DoCastAOE(SPELL_PALETRESS_CONFESSOR, true);
- +
- + _JustDied();
- + me->SetWalk(true);
- + me->GetMotionMaster()->MovePoint(POINT_DESPAWN, bossExitPos);
- + break;
- + default:
- + break;
- + }
- + }
- +
- + if (!UpdateVictim())
- + return;
- +
- + DoMeleeAttackIfReady();
- + }
- +
- + private:
- + bool _memorySummoned;
- + ObjectGuid _memoryGuid;
- + };
- +
- + CreatureAI* GetAI(Creature* creature) const override
- + {
- + return GetTrialOfChampionAI<boss_paletressAI>(creature);
- + }
- +};
- +
- +class npc_argent_soldier : public CreatureScript
- +{
- +public:
- + npc_argent_soldier() : CreatureScript("npc_argent_soldier") {}
- +
- + struct npc_argent_soldierAI : public ScriptedAI
- + {
- + npc_argent_soldierAI(Creature* creature) : ScriptedAI(creature)
- + {
- + _instance = creature->GetInstanceScript();
- + Initialize();
- + _waypointId = 0;
- + }
- +
- + void Initialize()
- + {
- + _shielded = false;
- + }
- +
- + InstanceScript* _instance;
- + EventMap _events;
- +
- + ObjectGuid _fountainGuid;
- +
- + uint8 _waypointId;
- + bool _shielded;
- +
- + void Reset() override
- + {
- + _events.Reset();
- + Initialize();
- +
- + if (me->GetEntry() == NPC_PRIESTESS)
- + if (Creature* fountain = ObjectAccessor::GetCreature(*me, _fountainGuid))
- + fountain->DisappearAndDie();
- + }
- +
- + void GenerateFinalPosition(Position& finalPos) const
- + {
- + switch (me->GetEntry())
- + {
- + case NPC_ARGENT_LIGHWIELDER:
- + switch (_waypointId)
- + {
- + case 0:
- + finalPos = { 712.14f, 628.42f, 411.88f, 5.81f };
- + break;
- + case 1:
- + finalPos = { 742.44f, 650.29f, 411.79f, 4.60f };
- + break;
- + case 2:
- + finalPos = { 774.94f, 636.64f, 411.89f, 3.78f };
- + break;
- + }
- + break;
- + case NPC_ARGENT_MONK:
- + switch (_waypointId)
- + {
- + case 0:
- + finalPos = { 713.12f, 632.97f, 411.90f, 5.81f };
- + break;
- + case 1:
- + finalPos = { 746.73f, 650.24f, 411.56f, 4.60f };
- + break;
- + case 2:
- + finalPos = { 777.33f, 633.08f, 411.89f, 3.78f };
- + break;
- + }
- + break;
- + case NPC_PRIESTESS:
- + switch (_waypointId)
- + {
- + case 0:
- + finalPos = { 715.06f, 637.07f, 411.91f, 5.81f };
- + break;
- + case 1:
- + finalPos = { 750.72f, 650.20f, 411.77f, 4.60f };
- + break;
- + case 2:
- + finalPos = { 780.13f, 629.18f, 411.89f, 3.78f };
- + break;
- + }
- + break;
- + default:
- + break;
- + }
- + }
- +
- + void JustReachedHome() override
- + {
- + me->SetEmoteState(EMOTE_STATE_READY1H);
- + }
- +
- + void MovementInform(uint32 type, uint32 id) override
- + {
- + if (type != POINT_MOTION_TYPE)
- + return;
- +
- + if (id == POINT_PREFIGHT)
- + {
- + me->SetWalk(false);
- + me->GetMotionMaster()->MoveTargetedHome();
- + if (me->GetEntry() == NPC_ARGENT_MONK)
- + {
- + if (Creature* lightWielder = me->FindNearestCreature(NPC_ARGENT_LIGHWIELDER, 15.0f))
- + {
- + if (lightWielder->GetFollowAngle() != 0.f)
- + {
- + lightWielder->GetMotionMaster()->Clear();
- + lightWielder->GetMotionMaster()->MovePoint(0, lightWielder->GetHomePosition());
- + }
- + }
- +
- + if (Creature* priestess = me->FindNearestCreature(NPC_PRIESTESS, 15.0f))
- + {
- + if (priestess->GetFollowAngle() != 0.f)
- + {
- + priestess->GetMotionMaster()->Clear();
- + priestess->GetMotionMaster()->MovePoint(0, priestess->GetHomePosition());
- + }
- + }
- + }
- + }
- + }
- +
- + void JustSummoned(Creature* summon) override
- + {
- + if (me->GetEntry() == NPC_PRIESTESS)
- + _fountainGuid = summon->GetGUID();
- + }
- +
- + void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
- + {
- + if (me->GetEntry() == NPC_ARGENT_MONK && damage >= me->GetHealth() && !_shielded)
- + {
- + _shielded = true;
- + damage = me->GetHealth() - 1;
- + me->AttackStop();
- +
- + DoCast(SPELL_DIVINE_SHIELD);
- + DoCast(SPELL_FINAL_MEDITATION);
- + }
- + }
- +
- + void JustDied(Unit* /*killer*/) override
- + {
- + _instance->SetData(DATA_ARGENT_SOLDIER_DEFEATED, _instance->GetData(DATA_ARGENT_SOLDIER_DEFEATED) + 1);
- + if (me->GetEntry() == NPC_PRIESTESS)
- + {
- + if (Creature* fountain = ObjectAccessor::GetCreature(*me, _fountainGuid))
- + fountain->DisappearAndDie();
- + }
- + }
- +
- + void SetData(uint32 type, uint32 /*data*/) override
- + {
- + _waypointId = type;
- + Position homePos;
- + GenerateFinalPosition(homePos);
- +
- + if (homePos.IsPositionValid())
- + {
- + me->SetHomePosition(homePos);
- + me->SetWalk(true);
- + if (me->GetEntry() == NPC_ARGENT_MONK)
- + me->GetMotionMaster()->MovePoint(POINT_PREFIGHT, homePos);
- + }
- + }
- +
- + void JustEngagedWith(Unit* /*who*/) override
- + {
- + switch (me->GetEntry())
- + {
- + case NPC_ARGENT_LIGHWIELDER:
- + _events.ScheduleEvent(EVENT_BLAZING_LIGHT, 10s);
- + _events.ScheduleEvent(EVENT_CLEAVE, 4s, 6s);
- + if (IsHeroic())
- + _events.ScheduleEvent(EVENT_UNBALANCING_STRIKE, 8s);
- + break;
- + case NPC_ARGENT_MONK:
- + _events.ScheduleEvent(EVENT_FLURRY_OF_BLOWS, 2s);
- + _events.ScheduleEvent(EVENT_PUMMEL, 12s);
- + break;
- + case NPC_PRIESTESS:
- + _events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 500ms);
- + _events.ScheduleEvent(EVENT_HOLY_SMITE, 2500ms);
- + _events.ScheduleEvent(EVENT_FOUNTAIN, 10s);
- + if (IsHeroic())
- + _events.ScheduleEvent(EVENT_MIND_CONTROL, 15s);
- + break;
- + default:
- + break;
- + }
- + }
- +
- + void AttackStart(Unit* who) override
- + {
- + if (!(me->GetEntry() == NPC_ARGENT_MONK && me->HasAura(SPELL_DIVINE_SHIELD)))
- + ScriptedAI::AttackStart(who);
- + }
- +
- + void UpdateAI(uint32 diff) override
- + {
- + _events.Update(diff);
- +
- + if (me->HasUnitState(UNIT_STATE_CASTING))
- + return;
- +
- + if (!UpdateVictim())
- + return;
- +
- + while (uint32 eventId = _events.ExecuteEvent())
- + {
- + switch (eventId)
- + {
- + case EVENT_BLAZING_LIGHT:
- + if (Unit* friendly = DoSelectLowestHpFriendly(40.0f))
- + {
- + if (friendly->GetHealthPct() > me->GetHealthPct())
- + DoCastSelf(SPELL_BLAZING_LIGHT);
- + else
- + DoCast(friendly, SPELL_BLAZING_LIGHT);
- + }
- + _events.Repeat(10s);
- + break;
- + case EVENT_CLEAVE:
- + DoCastVictim(SPELL_CLEAVE);
- + _events.Repeat(4s, 6s);
- + break;
- + case EVENT_UNBALANCING_STRIKE:
- + DoCastVictim(SPELL_UNBALANCING_STRIKE);
- + _events.Repeat(15s);
- + break;
- + case EVENT_FLURRY_OF_BLOWS:
- + DoCast(SPELL_FLURRY_OF_BLOWS);
- + _events.Repeat(15s);
- + break;
- + case EVENT_PUMMEL:
- + {
- + Unit* target = nullptr;
- + for (auto* threatTarget : me->GetThreatManager().GetUnsortedThreatList())
- + {
- + if (threatTarget->GetVictim() && threatTarget->GetVictim()->IsWithinDist(me, 5.0f) &&
- + threatTarget->GetVictim()->IsNonMeleeSpellCast(true))
- + {
- + target = threatTarget->GetVictim();
- + break;
- + }
- + }
- +
- + if (target)
- + DoCast(target, SPELL_PUMMEL);
- +
- + _events.Repeat(12s);
- + break;
- + }
- + case EVENT_SHADOW_WORD_PAIN:
- + DoCastVictim(SPELL_SHADOW_WORD_PAIN);
- + _events.Repeat(15s);
- + break;
- + case EVENT_HOLY_SMITE:
- + DoCastVictim(SPELL_HOLY_SMITE);
- + _events.Repeat(4s, 7s);
- + break;
- + case EVENT_FOUNTAIN:
- + DoCastAOE(SPELL_SUMMON_FOUNTAIN);
- + _events.Repeat(50s);
- + break;
- + case EVENT_MIND_CONTROL:
- + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 30.0f, true))
- + DoCast(target, SPELL_MIND_CONTROL);
- + _events.Repeat(15s);
- + break;
- + default:
- + break;
- + }
- + }
- +
- + DoMeleeAttackIfReady();
- + }
- + };
- +
- + CreatureAI* GetAI(Creature* creature) const override
- + {
- + return GetTrialOfChampionAI<npc_argent_soldierAI>(creature);
- + }
- +};
- +
- +class npc_fountain_of_light : public CreatureScript
- +{
- +public:
- + npc_fountain_of_light() : CreatureScript("npc_fountain_of_light") {}
- +
- + struct npc_fountain_of_lightAI : public ScriptedAI
- + {
- + npc_fountain_of_lightAI(Creature* creature) : ScriptedAI(creature)
- + {
- + me->SetReactState(REACT_PASSIVE);
- + SetCombatMovement(false);
- + }
- +
- + void JustDied(Unit* /*killer*/) override
- + {
- + me->DespawnOrUnsummon();
- + }
- +
- + void AttackStart(Unit* /*who*/) override {}
- +
- + void UpdateAI(uint32 /*diff*/) override {}
- + };
- +
- + CreatureAI* GetAI(Creature* creature) const override
- + {
- + return GetTrialOfChampionAI<npc_fountain_of_lightAI>(creature);
- + }
- +};
- +
- +class npc_memory : public CreatureScript
- +{
- +public:
- + npc_memory() : CreatureScript("npc_memory") {}
- +
- + struct npc_memoryAI : public ScriptedAI
- + {
- + npc_memoryAI(Creature* creature) : ScriptedAI(creature)
- + {
- + Initialize();
- + me->SetReactState(REACT_PASSIVE);
- + }
- +
- + void Initialize()
- + {
- + DoCastAOE(SPELL_SHADOWFORM);
- + DoCastAOE(SPELL_SPAWN_VISUAL);
- + _events.ScheduleEvent(EVENT_ENTER_AGGRESSIVE, 3s);
- + }
- +
- + void Reset() override
- + {
- + _events.Reset();
- + Initialize();
- + }
- +
- + void JustDied(Unit* /*killer*/) override
- + {
- + if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit())
- + summoner->GetAI()->DoAction(ACTION_MEMORY_DEATH);
- +
- + me->DespawnOrUnsummon();
- + }
- +
- + void JustEngagedWith(Unit* /*who*/) override
- + {
- + DoZoneInCombat();
- + }
- +
- + void UpdateAI(uint32 diff) override
- + {
- + _events.Update(diff);
- +
- + if (me->HasUnitState(UNIT_STATE_CASTING))
- + return;
- +
- + while (uint32 eventId = _events.ExecuteEvent())
- + {
- + switch (eventId)
- + {
- + case EVENT_ENTER_AGGRESSIVE:
- + me->SetReactState(REACT_AGGRESSIVE);
- + _events.ScheduleEvent(EVENT_OLD_WOUNDS, 11s, 13s);
- + _events.ScheduleEvent(EVENT_SHADOWS_PAST, 5s);
- + _events.ScheduleEvent(EVENT_WAKING_NIGHTMARE, 7s, 10s);
- + break;
- + case EVENT_OLD_WOUNDS:
- + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 5.0f, true))
- + DoCast(target, SPELL_OLD_WOUNDS);
- + _events.Repeat(11s, 13s);
- + break;
- + case EVENT_SHADOWS_PAST:
- + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f, true))
- + DoCast(target, SPELL_SHADOWS_PAST);
- + _events.Repeat(5s, 7s);
- + break;
- + case EVENT_WAKING_NIGHTMARE:
- + Talk(EMOTE_WAKING_NIGHTMARE);
- + DoCastAOE(SPELL_WAKING_NIGHTMARE);
- + _events.Repeat(20s, 40s);
- + break;
- + default:
- + break;
- + }
- + }
- +
- + if (!UpdateVictim())
- + return;
- +
- + DoMeleeAttackIfReady();
- + }
- +
- + private:
- + EventMap _events;
- + };
- +
- + CreatureAI* GetAI(Creature* creature) const override
- + {
- + return GetTrialOfChampionAI<npc_memoryAI>(creature);
- + }
- +};
- +
- +class spell_eadric_hammer_of_righteous : public SpellScriptLoader
- +{
- +public:
- + spell_eadric_hammer_of_righteous() : SpellScriptLoader("spell_eadric_hammer_of_righteous") {}
- +
- + class spell_eadric_hammer_of_righteous_SpellScript : public SpellScript
- + {
- + PrepareSpellScript(spell_eadric_hammer_of_righteous_SpellScript);
- +
- + bool Validate(SpellInfo const* /*spellInfo*/) override
- + {
- + if (!sSpellMgr->GetSpellInfo(SPELL_HAMMER_RIGHT_DUMMY) ||
- + !sSpellMgr->GetSpellInfo(SPELL_HAMMER_JUSTICE_STUN))
- + return false;
- + return true;
- + }
- +
- + void HandleOnHit()
- + {
- + if (Unit* target = GetHitUnit())
- + {
- + if (!target->HasAura(SPELL_HAMMER_JUSTICE_STUN))
- + {
- + PreventHitDefaultEffect(EFFECT_0);
- + PreventHitDamage();
- + GetCaster()->CastSpell(target, SPELL_HAMMER_RIGHT_DUMMY, true);
- + }
- + }
- + }
- +
- + void Register() override
- + {
- + OnHit += SpellHitFn(spell_eadric_hammer_of_righteous_SpellScript::HandleOnHit);
- + }
- + };
- +
- + SpellScript* GetSpellScript() const override
- + {
- + return new spell_eadric_hammer_of_righteous_SpellScript();
- + }
- +};
- +
- +class spell_eadric_hammer_of_righteous_faceroller : public SpellScriptLoader
- +{
- +public:
- + spell_eadric_hammer_of_righteous_faceroller() : SpellScriptLoader("spell_eadric_hammer_of_righteous_faceroller") {}
- +
- + class spell_eadric_hammer_of_righteous_faceroller_SpellScript : public SpellScript
- + {
- + PrepareSpellScript(spell_eadric_hammer_of_righteous_faceroller_SpellScript);
- +
- + bool Load() override
- + {
- + Unit* caster = GetCaster();
- + return caster->GetTypeId() == TYPEID_PLAYER && caster->GetMap()->IsHeroic();
- + }
- +
- + void CheckHealth(SpellEffIndex /*effIndex*/)
- + {
- + Creature* creature = GetHitCreature();
- + if (!creature || creature->GetEntry() != NPC_EADRIC)
- + return;
- +
- + if (GetHitDamage() >= static_cast<int32>(GetHitUnit()->GetHealth()))
- + creature->AI()->SetData(DATA_FACEROLLER_ACHIEVEMENT, 1);
- + }
- +
- + void Register() override
- + {
- + OnEffectHitTarget += SpellEffectFn(spell_eadric_hammer_of_righteous_faceroller_SpellScript::CheckHealth, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
- + }
- + };
- +
- + SpellScript* GetSpellScript() const override
- + {
- + return new spell_eadric_hammer_of_righteous_faceroller_SpellScript();
- + }
- +};
- +
- +class spell_eadric_radiance : public SpellScriptLoader
- +{
- +public:
- + spell_eadric_radiance() : SpellScriptLoader("spell_eadric_radiance") {}
- +
- + class spell_eadric_radiance_SpellScript : public SpellScript
- + {
- + PrepareSpellScript(spell_eadric_radiance_SpellScript);
- +
- + void FilterTargets(std::list<WorldObject*>& targets)
- + {
- + Unit* caster = GetCaster();
- +
- + // CORRECCIÓN: Lambda simplificada y corregida
- + targets.remove_if([caster](WorldObject* target) -> bool
- + {
- + if (!target->IsWithinDist(caster, 40.0f))
- + return true;
- +
- + return !target->isInFront(caster, 2.5f);
- + });
- + }
- +
- + void Register() override
- + {
- + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_eadric_radiance_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
- + }
- + };
- +
- + SpellScript* GetSpellScript() const override
- + {
- + return new spell_eadric_radiance_SpellScript();
- + }
- +};
- +
- +// 66545 - Summon Memory
- +class spell_paletress_summon_memory : public SpellScriptLoader
- +{
- +public:
- + spell_paletress_summon_memory() : SpellScriptLoader("spell_paletress_summon_memory") {}
- +
- + class spell_paletress_summon_memory_SpellScript : public SpellScript
- + {
- + PrepareSpellScript(spell_paletress_summon_memory_SpellScript);
- +
- + bool Validate(SpellInfo const* /*spellInfo*/) override
- + {
- + return sSpellMgr->GetSpellInfo(SPELL_MEMORY_HOGGER) &&
- + sSpellMgr->GetSpellInfo(SPELL_MEMORY_VANCLEEF);
- + }
- +
- + void FilterTargets(std::list<WorldObject*>& targets)
- + {
- + if (!targets.empty())
- + {
- + auto it = targets.begin();
- + std::advance(it, urand(0, targets.size() - 1));
- + WorldObject* target = *it;
- + targets.clear();
- + targets.push_back(target);
- + }
- + }
- +
- + void HandleScript(SpellEffIndex /*effIndex*/)
- + {
- + uint32 randMemorySpellId = SelectRandomMemorySpell();
- + GetHitUnit()->CastSpell(GetHitUnit(), randMemorySpellId, true);
- + }
- +
- + void Register() override
- + {
- + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_paletress_summon_memory_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
- + OnEffectHitTarget += SpellEffectFn(spell_paletress_summon_memory_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- + }
- + };
- +
- + SpellScript* GetSpellScript() const override
- + {
- + return new spell_paletress_summon_memory_SpellScript();
- + }
- +};
- +
- +class spell_paletress_reflective_shield : public SpellScriptLoader
- +{
- +public:
- + spell_paletress_reflective_shield() : SpellScriptLoader("spell_paletress_reflective_shield") {}
- +
- + class spell_paletress_reflective_shield_AuraScript : public AuraScript
- + {
- + PrepareAuraScript(spell_paletress_reflective_shield_AuraScript);
- +
- + bool Validate(SpellInfo const* /*spellInfo*/) override
- + {
- + if (!sSpellMgr->GetSpellInfo(SPELL_SHIELD_REFLECT))
- + return false;
- + return true;
- + }
- +
- + void HandleScript(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount)
- + {
- + if (dmgInfo.GetAttacker() == GetTarget())
- + return;
- +
- + int32 bp = CalculatePct(absorbAmount, aurEff->GetSpellEffectInfo().CalcValue());
- + GetTarget()->CastSpell(dmgInfo.GetAttacker(), SPELL_SHIELD_REFLECT, CastSpellExtraArgs(aurEff).AddSpellBP0(bp));
- + }
- +
- + void Register() override
- + {
- + AfterEffectAbsorb += AuraEffectAbsorbFn(spell_paletress_reflective_shield_AuraScript::HandleScript, EFFECT_0);
- + }
- + };
- +
- + AuraScript* GetAuraScript() const override
- + {
- + return new spell_paletress_reflective_shield_AuraScript();
- + }
- +};
- +
- +template <uint32 MemoryEntry>
- +class achievement_argent_confessor : public AchievementCriteriaScript
- +{
- +public:
- + achievement_argent_confessor(char const* name) : AchievementCriteriaScript(name) {}
- +
- + bool OnCheck(Player* /*source*/, Unit* target) override
- + {
- + if (!target || !target->IsAIEnabled())
- + return false;
- +
- + return target->GetAI()->GetData(DATA_MEMORY_ENTRY) == MemoryEntry;
- + }
- +};
- +
- +class achievement_eadric_faceroller : public AchievementCriteriaScript
- +{
- +public:
- + achievement_eadric_faceroller() : AchievementCriteriaScript("achievement_eadric_faceroller") {}
- +
- + bool OnCheck(Player* /*source*/, Unit* target) override
- + {
- + if (!target)
- + return false;
- +
- + if (!target->IsAIEnabled())
- + return false;
- +
- + UnitAI* ai = target->GetAI();
- + if (!ai)
- + return false;
- +
- + uint32 achievementData = ai->GetData(DATA_FACEROLLER_ACHIEVEMENT);
- + return (achievementData == 1);
- + }
- +};
- +
- +void AddSC_boss_argent_challenge()
- +{
- + new boss_eadric();
- + new boss_paletress();
- +
- + new npc_argent_soldier();
- + new npc_fountain_of_light();
- + new npc_memory();
- +
- + new spell_eadric_hammer_of_righteous();
- + new spell_eadric_hammer_of_righteous_faceroller();
- + new spell_eadric_radiance();
- +
- + new spell_paletress_summon_memory();
- + new spell_paletress_reflective_shield();
- +
- + // Achievement scripts for each memory type
- + new achievement_argent_confessor<NPC_MEMORY_HOGGER>("achievement_argent_confessor_hogger");
- + new achievement_argent_confessor<NPC_MEMORY_VANCLEEF>("achievement_argent_confessor_vancleef");
- + new achievement_argent_confessor<NPC_MEMORY_MUTANUS>("achievement_argent_confessor_mutanus");
- + new achievement_argent_confessor<NPC_MEMORY_HEROD>("achievement_argent_confessor_herod");
- + new achievement_argent_confessor<NPC_MEMORY_LUCIFRON>("achievement_argent_confessor_lucifron");
- + new achievement_argent_confessor<NPC_MEMORY_THUNDERAAN>("achievement_argent_confessor_thunderaan");
- + new achievement_argent_confessor<NPC_MEMORY_CHROMAGGUS>("achievement_argent_confessor_chromaggus");
- + new achievement_argent_confessor<NPC_MEMORY_HAKKAR>("achievement_argent_confessor_hakkar");
- + new achievement_argent_confessor<NPC_MEMORY_VEKNILASH>("achievement_argent_confessor_veknilash");
- + new achievement_argent_confessor<NPC_MEMORY_KALITHRESH>("achievement_argent_confessor_kalithresh");
- + new achievement_argent_confessor<NPC_MEMORY_MALCHEZAAR>("achievement_argent_confessor_malchezaar");
- + new achievement_argent_confessor<NPC_MEMORY_GRUUL>("achievement_argent_confessor_gruul");
- + new achievement_argent_confessor<NPC_MEMORY_VASHJ>("achievement_argent_confessor_vashj");
- + new achievement_argent_confessor<NPC_MEMORY_ARCHIMONDE>("achievement_argent_confessor_archimonde");
- + new achievement_argent_confessor<NPC_MEMORY_ILLIDAN>("achievement_argent_confessor_illidan");
- + new achievement_argent_confessor<NPC_MEMORY_DELRISSA>("achievement_argent_confessor_delrissa");
- + new achievement_argent_confessor<NPC_MEMORY_MURU>("achievement_argent_confessor_muru");
- + new achievement_argent_confessor<NPC_MEMORY_INGVAR>("achievement_argent_confessor_ingvar");
- + new achievement_argent_confessor<NPC_MEMORY_CYANIGOSA>("achievement_argent_confessor_cyanigosa");
- + new achievement_argent_confessor<NPC_MEMORY_ECK>("achievement_argent_confessor_eck");
- + new achievement_argent_confessor<NPC_MEMORY_ONYXIA>("achievement_argent_confessor_onyxia");
- + new achievement_argent_confessor<NPC_MEMORY_HEIGAN>("achievement_argent_confessor_heigan");
- + new achievement_argent_confessor<NPC_MEMORY_IGNIS>("achievement_argent_confessor_ignis");
- + new achievement_argent_confessor<NPC_MEMORY_VEZAX>("achievement_argent_confessor_vezax");
- + new achievement_argent_confessor<NPC_MEMORY_ALGALON>("achievement_argent_confessor_algalon");
- +
- + new achievement_eadric_faceroller();
- +}
- diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp
- dissimilarity index 73%
- index 7ca324bdd8..0bd578810b 100644
- --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp
- +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp
- @@ -1,431 +1,772 @@
- -/*
- - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
- - *
- - * 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, see <http://www.gnu.org/licenses/>.
- - */
- -
- -/* ScriptData
- -SDName: Boss Black Knight
- -SD%Complete: 80%
- -SDComment: missing yells. not sure about timers.
- -SDCategory: Trial of the Champion
- -EndScriptData */
- -
- -#include "ScriptMgr.h"
- -#include "InstanceScript.h"
- -#include "ScriptedEscortAI.h"
- -#include "SpellInfo.h"
- -#include "SpellScript.h"
- -#include "trial_of_the_champion.h"
- -
- -enum Spells
- -{
- - //phase 1
- - SPELL_PLAGUE_STRIKE = 67884,
- - SPELL_PLAGUE_STRIKE_2 = 67724,
- - SPELL_ICY_TOUCH_H = 67881,
- - SPELL_ICY_TOUCH = 67718,
- - SPELL_DEATH_RESPITE = 67745,
- - SPELL_DEATH_RESPITE_2 = 68306,
- - SPELL_DEATH_RESPITE_3 = 66798,
- - SPELL_OBLITERATE_H = 67883,
- - SPELL_OBLITERATE = 67725,
- - //in this phase should rise herald (the spell is missing)
- -
- - //phase 2 - During this phase, the Black Knight will use the same abilities as in phase 1, except for Death's Respite
- - SPELL_ARMY_DEAD = 67761,
- - SPELL_DESECRATION = 67778,
- - SPELL_DESECRATION_2 = 67778,
- - SPELL_GHOUL_EXPLODE = 67751,
- -
- - //phase 3
- - SPELL_DEATH_BITE_H = 67875,
- - SPELL_DEATH_BITE = 67808,
- - SPELL_MARKED_DEATH = 67882,
- - SPELL_MARKED_DEATH_2 = 67823,
- -
- - SPELL_BLACK_KNIGHT_RES = 67693,
- -
- - SPELL_LEAP = 67749,
- - SPELL_LEAP_H = 67880,
- -
- - SPELL_KILL_CREDIT = 68663
- -};
- -
- -enum Models
- -{
- - MODEL_SKELETON = 29846,
- - MODEL_GHOST = 21300
- -};
- -
- -enum Phases
- -{
- - PHASE_UNDEAD = 1,
- - PHASE_SKELETON = 2,
- - PHASE_GHOST = 3
- -};
- -
- -class boss_black_knight : public CreatureScript
- -{
- -public:
- - boss_black_knight() : CreatureScript("boss_black_knight") { }
- -
- - struct boss_black_knightAI : public ScriptedAI
- - {
- - boss_black_knightAI(Creature* creature) : ScriptedAI(creature), summons(creature)
- - {
- - Initialize();
- - instance = creature->GetInstanceScript();
- - }
- -
- - void Initialize()
- - {
- - bEventInProgress = false;
- - bEvent = false;
- - bSummonArmy = false;
- - bDeathArmyDone = false;
- -
- - uiPhase = PHASE_UNDEAD;
- -
- - uiIcyTouchTimer = urand(5000, 9000);
- - uiPlagueStrikeTimer = urand(10000, 13000);
- - uiDeathRespiteTimer = urand(15000, 16000);
- - uiObliterateTimer = urand(17000, 19000);
- - uiDesecration = urand(15000, 16000);
- - uiDeathArmyCheckTimer = 7000;
- - uiResurrectTimer = 4000;
- - uiGhoulExplodeTimer = 8000;
- - uiDeathBiteTimer = urand(2000, 4000);
- - uiMarkedDeathTimer = urand(5000, 7000);
- - }
- -
- - InstanceScript* instance;
- -
- - SummonList summons;
- -
- - bool bEventInProgress;
- - bool bEvent;
- - bool bSummonArmy;
- - bool bDeathArmyDone;
- -
- - uint8 uiPhase;
- -
- - uint32 uiPlagueStrikeTimer;
- - uint32 uiIcyTouchTimer;
- - uint32 uiDeathRespiteTimer;
- - uint32 uiObliterateTimer;
- - uint32 uiDesecration;
- - uint32 uiResurrectTimer;
- - uint32 uiDeathArmyCheckTimer;
- - uint32 uiGhoulExplodeTimer;
- - uint32 uiDeathBiteTimer;
- - uint32 uiMarkedDeathTimer;
- -
- - void Reset() override
- - {
- - summons.DespawnAll();
- - me->SetDisplayId(me->GetNativeDisplayId());
- - me->ClearUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED);
- -
- - Initialize();
- - }
- -
- - void JustSummoned(Creature* summon) override
- - {
- - summons.Summon(summon);
- - summon->AI()->AttackStart(me->GetVictim());
- - }
- -
- - void SummonedCreatureDespawn(Creature* summon) override
- - {
- - summons.Despawn(summon);
- - }
- -
- - void UpdateAI(uint32 uiDiff) override
- - {
- - //Return since we have no target
- - if (!UpdateVictim())
- - return;
- -
- - if (bEventInProgress)
- - {
- - if (uiResurrectTimer <= uiDiff)
- - {
- - me->SetFullHealth();
- - DoCast(me, SPELL_BLACK_KNIGHT_RES, true);
- - uiPhase++;
- - uiResurrectTimer = 4000;
- - bEventInProgress = false;
- - me->ClearUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED);
- - } else uiResurrectTimer -= uiDiff;
- - }
- -
- - switch (uiPhase)
- - {
- - case PHASE_UNDEAD:
- - case PHASE_SKELETON:
- - {
- - if (uiIcyTouchTimer <= uiDiff)
- - {
- - DoCastVictim(SPELL_ICY_TOUCH);
- - uiIcyTouchTimer = urand(5000, 7000);
- - } else uiIcyTouchTimer -= uiDiff;
- - if (uiPlagueStrikeTimer <= uiDiff)
- - {
- - DoCastVictim(SPELL_ICY_TOUCH);
- - uiPlagueStrikeTimer = urand(12000, 15000);
- - } else uiPlagueStrikeTimer -= uiDiff;
- - if (uiObliterateTimer <= uiDiff)
- - {
- - DoCastVictim(SPELL_OBLITERATE);
- - uiObliterateTimer = urand(17000, 19000);
- - } else uiObliterateTimer -= uiDiff;
- - switch (uiPhase)
- - {
- - case PHASE_UNDEAD:
- - {
- - if (uiDeathRespiteTimer <= uiDiff)
- - {
- - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
- - {
- - if (target->IsAlive())
- - DoCast(target, SPELL_DEATH_RESPITE);
- - }
- - uiDeathRespiteTimer = urand(15000, 16000);
- - } else uiDeathRespiteTimer -= uiDiff;
- - break;
- - }
- - case PHASE_SKELETON:
- - {
- - if (!bSummonArmy)
- - {
- - bSummonArmy = true;
- - me->AddUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED);
- - DoCast(me, SPELL_ARMY_DEAD);
- - }
- - if (!bDeathArmyDone)
- - {
- - if (uiDeathArmyCheckTimer <= uiDiff)
- - {
- - me->ClearUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED);
- - uiDeathArmyCheckTimer = 0;
- - bDeathArmyDone = true;
- - } else uiDeathArmyCheckTimer -= uiDiff;
- - }
- - if (uiDesecration <= uiDiff)
- - {
- - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
- - {
- - if (target->IsAlive())
- - DoCast(target, SPELL_DESECRATION);
- - }
- - uiDesecration = urand(15000, 16000);
- - } else uiDesecration -= uiDiff;
- - if (uiGhoulExplodeTimer <= uiDiff)
- - {
- - DoCast(me, SPELL_GHOUL_EXPLODE);
- - uiGhoulExplodeTimer = 8000;
- - } else uiGhoulExplodeTimer -= uiDiff;
- - break;
- - }
- - break;
- - }
- - break;
- - }
- - case PHASE_GHOST:
- - {
- - if (uiDeathBiteTimer <= uiDiff)
- - {
- - DoCastAOE(SPELL_DEATH_BITE);
- - uiDeathBiteTimer = urand(2000, 4000);
- - } else uiDeathBiteTimer -= uiDiff;
- - if (uiMarkedDeathTimer <= uiDiff)
- - {
- - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
- - {
- - if (target->IsAlive())
- - DoCast(target, SPELL_MARKED_DEATH);
- - }
- - uiMarkedDeathTimer = urand(5000, 7000);
- - } else uiMarkedDeathTimer -= uiDiff;
- - break;
- - }
- - }
- -
- - if (!me->HasUnitState(UNIT_STATE_ROOT) && !me->HealthBelowPct(1))
- - DoMeleeAttackIfReady();
- - }
- -
- - void DamageTaken(Unit* /*pDoneBy*/, uint32& uiDamage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
- - {
- - if (uiDamage > me->GetHealth() && uiPhase <= PHASE_SKELETON)
- - {
- - uiDamage = 0;
- - me->SetHealth(0);
- - me->AddUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED);
- - summons.DespawnAll();
- - switch (uiPhase)
- - {
- - case PHASE_UNDEAD:
- - me->SetDisplayId(MODEL_SKELETON);
- - break;
- - case PHASE_SKELETON:
- - me->SetDisplayId(MODEL_GHOST);
- - break;
- - }
- - bEventInProgress = true;
- - }
- - }
- -
- - void JustDied(Unit* /*killer*/) override
- - {
- - DoCast(me, SPELL_KILL_CREDIT);
- -
- - instance->SetBossState(BOSS_BLACK_KNIGHT, DONE);
- - }
- - };
- -
- - CreatureAI* GetAI(Creature* creature) const override
- - {
- - return GetTrialOfTheChampionAI<boss_black_knightAI>(creature);
- - }
- -};
- -
- -class npc_risen_ghoul : public CreatureScript
- -{
- -public:
- - npc_risen_ghoul() : CreatureScript("npc_risen_ghoul") { }
- -
- - struct npc_risen_ghoulAI : public ScriptedAI
- - {
- - npc_risen_ghoulAI(Creature* creature) : ScriptedAI(creature)
- - {
- - Initialize();
- - }
- -
- - void Initialize()
- - {
- - uiAttackTimer = 3500;
- - }
- -
- - uint32 uiAttackTimer;
- -
- - void Reset() override
- - {
- - Initialize();
- - }
- -
- - void UpdateAI(uint32 uiDiff) override
- - {
- - if (!UpdateVictim())
- - return;
- -
- - if (uiAttackTimer <= uiDiff)
- - {
- - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100, true))
- - {
- - if (target->IsAlive())
- - DoCast(target, (SPELL_LEAP));
- - }
- - uiAttackTimer = 3500;
- - } else uiAttackTimer -= uiDiff;
- -
- - DoMeleeAttackIfReady();
- - }
- - };
- -
- - CreatureAI* GetAI(Creature* creature) const override
- - {
- - return GetTrialOfTheChampionAI<npc_risen_ghoulAI>(creature);
- - }
- -};
- -
- -class npc_black_knight_skeletal_gryphon : public CreatureScript
- -{
- -public:
- - npc_black_knight_skeletal_gryphon() : CreatureScript("npc_black_knight_skeletal_gryphon") { }
- -
- - struct npc_black_knight_skeletal_gryphonAI : public EscortAI
- - {
- - npc_black_knight_skeletal_gryphonAI(Creature* creature) : EscortAI(creature)
- - {
- - Start(false, true);
- - }
- -
- - void UpdateAI(uint32 uiDiff) override
- - {
- - EscortAI::UpdateAI(uiDiff);
- -
- - UpdateVictim();
- - }
- -
- - };
- -
- - CreatureAI* GetAI(Creature* creature) const override
- - {
- - return GetTrialOfTheChampionAI<npc_black_knight_skeletal_gryphonAI>(creature);
- - }
- -};
- -
- -// 67751 - Ghoul Explode
- -class spell_black_knight_ghoul_explode : public SpellScript
- -{
- - PrepareSpellScript(spell_black_knight_ghoul_explode);
- -
- - bool Validate(SpellInfo const* spellInfo) override
- - {
- - return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()) });
- - }
- -
- - void HandleScript(SpellEffIndex /*effIndex*/)
- - {
- - GetHitUnit()->CastSpell(GetHitUnit(), uint32(GetEffectInfo(EFFECT_0).CalcValue()));
- - }
- -
- - void Register() override
- - {
- - OnEffectHitTarget += SpellEffectFn(spell_black_knight_ghoul_explode::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
- - }
- -};
- -
- -// 67754 - Ghoul Explode
- -// 67889 - Ghoul Explode
- -class spell_black_knight_ghoul_explode_risen_ghoul : public SpellScript
- -{
- - PrepareSpellScript(spell_black_knight_ghoul_explode_risen_ghoul);
- -
- - bool Validate(SpellInfo const* spellInfo) override
- - {
- - return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_1).CalcValue()) });
- - }
- -
- - void HandleScript(SpellEffIndex /*effIndex*/)
- - {
- - GetCaster()->CastSpell(GetCaster(), uint32(GetEffectValue()));
- - }
- -
- - void Register() override
- - {
- - OnEffectHit += SpellEffectFn(spell_black_knight_ghoul_explode_risen_ghoul::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
- - }
- -};
- -
- -void AddSC_boss_black_knight()
- -{
- - new boss_black_knight();
- - new npc_risen_ghoul();
- - new npc_black_knight_skeletal_gryphon();
- - RegisterSpellScript(spell_black_knight_ghoul_explode);
- - RegisterSpellScript(spell_black_knight_ghoul_explode_risen_ghoul);
- -}
- +/*
- + * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
- + *
- + * This program is free software; you can redistribute it and/or modify it
- + * under the terms of the GNU General Public License as published by the
- + * Free Software Foundation; either version 2 of the License, or (at your
- + * option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- + * more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program. If not, see <http://www.gnu.org/licenses/>.
- + */
- +
- + /* ScriptData
- + SDName: Boss Black Knight
- + SD%Complete: 100%
- + SDComment:
- + SDCategory: Trial of the Champion
- + EndScriptData */
- +
- +#include "Player.h"
- +#include "ScriptMgr.h"
- +#include "ScriptedCreature.h"
- +#include "ScriptedEscortAI.h"
- +#include "SpellAuraEffects.h"
- +#include "SpellScript.h"
- +#include "SpellMgr.h"
- +#include "trial_of_the_champion.h"
- +
- +enum Yells
- +{
- + SAY_AGGRO = 3,
- + SAY_PHASE_2 = 4,
- + SAY_PHASE_3 = 5,
- + SAY_KILL = 6,
- + SAY_DEATH = 7
- +};
- +
- +enum Events
- +{
- + // The Black Knight
- + EVENT_ICY_TOUCH = 1,
- + EVENT_PLAGUE_STRIKE,
- + EVENT_DEATH_RESPITE,
- + EVENT_OBLITERATE,
- + EVENT_DESECRATION,
- + EVENT_GHOUL_EXPLODE,
- + EVENT_DEATH_BITE,
- + EVENT_MARKED_DEATH,
- + EVENT_RESURRECT,
- + // Ghouls
- + EVENT_CLAW,
- + EVENT_LEAP
- +};
- +
- +enum Spells
- +{
- + // Phase 1
- + SPELL_PLAGUE_STRIKE = 67724,
- + SPELL_ICY_TOUCH = 67718,
- + SPELL_DEATH_RESPITE = 67745,
- + SPELL_OBLITERATE = 67725,
- + SPELL_RAISE_ARELAS = 67705,
- + SPELL_RAISE_JAEREN = 67715,
- +
- + // Phase 2
- + SPELL_ARMY_DEAD = 67761,
- + SPELL_DESECRATION = 67778,
- + SPELL_GHOUL_EXPLODE = 67751,
- +
- + // Phase 3
- + SPELL_DEATH_BITE = 67808,
- + SPELL_MARKED_DEATH = 67882,
- +
- + // Ghouls
- + SPELL_CLAW = 67774,
- + SPELL_LEAP = 67749,
- +
- + SPELL_DEATH_RESPITE_DND = 66798, // casted on announcer
- + SPELL_FEIGN_DEATH = 66804,
- + SPELL_BLACK_KNIGHT_DIE = 67691,
- + SPELL_BLACK_KNIGHT_RES = 67693,
- + SPELL_FROST_FEVER = 67719,
- + SPELL_BLOOD_PLAGUE = 67722,
- + SPELL_EXPLODE = 67729,
- + SPELL_DESECRATION_DND = 67782,
- + SPELL_DESECRATION_ARM = 67803,
- + SPELL_FROST_FEVER_H = 67878,
- + SPELL_BLOOD_PLAGUE_H = 67885,
- + SPELL_EXPLODE_H = 67886,
- + SPELL_KILL_CREDIT = 68663
- +};
- +
- +enum Models
- +{
- + MODEL_SKELETON = 29846,
- + MODEL_GHOST = 21300
- +};
- +
- +enum Equipment
- +{
- + EQUIP_SWORD = 40343
- +};
- +
- +enum Phases
- +{
- + PHASE_UNDEAD = 1,
- + PHASE_SKELETON = 2,
- + PHASE_GHOST = 3
- +};
- +
- +class npc_risen_ghoul : public CreatureScript
- +{
- +public:
- + npc_risen_ghoul() : CreatureScript("npc_risen_ghoul") {}
- +
- + struct npc_risen_ghoulAI : public ScriptedAI
- + {
- + npc_risen_ghoulAI(Creature* creature) : ScriptedAI(creature)
- + {
- + Initialize();
- + instance = creature->GetInstanceScript();
- + }
- +
- + void Initialize()
- + {
- + doExplode = false;
- + }
- +
- + InstanceScript* instance;
- +
- + EventMap events;
- +
- + bool doExplode;
- +
- + void Reset() override
- + {
- + events.Reset();
- + Initialize();
- + }
- +
- + // CORRECCIÓN: SpellHitTarget actualizada
- + void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override
- + {
- + if (!target->IsPlayer())
- + return;
- +
- + if (spellInfo->Id == SPELL_EXPLODE || spellInfo->Id == SPELL_EXPLODE_H)
- + {
- + if (Creature* knight = instance->GetCreature(DATA_BLACK_KNIGHT))
- + // If corpse explosion hits any player during encounter
- + // we cannot give achievement id 3804
- + knight->AI()->SetData(1, 0);
- + }
- + }
- +
- + void DoExplode()
- + {
- + // We trigger the ghoul explode spell casted on us by Black Knight
- + // to get immunity to crowd control forms and we get correct growth aura
- + // the spell script of Ghoul Explode functions normally from here on
- + if (me->HasAura(SPELL_GHOUL_EXPLODE))
- + return;
- + DoCast(me, SPELL_GHOUL_EXPLODE, true);
- + // wtf?
- + if (me->GetEntry() == NPC_RISEN_ARELAS || me->GetEntry() == NPC_RISEN_JAEREN)
- + Talk(urand(0, 2));
- + }
- +
- + // CORRECCIÓN: DamageTaken actualizada
- + void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
- + {
- + if (HealthBelowPct(31) && !doExplode)
- + {
- + // Ghouls cast explode when they reach 30% health or if Black Knight dies
- + // or if Black Knight forces them to explode
- + doExplode = true;
- + DoExplode();
- + }
- + }
- +
- + // CORRECCIÓN: EnterCombat ? JustEngagedWith
- + void JustEngagedWith(Unit* /*who*/) override
- + {
- + events.ScheduleEvent(EVENT_CLAW, 3s);
- + events.ScheduleEvent(EVENT_LEAP, 2s);
- + DoZoneInCombat();
- + }
- +
- + void JustDied(Unit* /*killer*/) override
- + {
- + me->DespawnOrUnsummon(1s); // CORRECCIÓN: Usar 1s
- + }
- +
- + void KilledUnit(Unit* who) override
- + {
- + if (who == me)
- + return;
- + if (Creature* knight = instance->GetCreature(DATA_BLACK_KNIGHT))
- + {
- + if (!knight->HasAura(SPELL_BLACK_KNIGHT_DIE))
- + knight->AI()->KilledUnit(who);
- + }
- + }
- +
- + void UpdateAI(uint32 uiDiff) override
- + {
- + events.Update(uiDiff);
- +
- + if (me->HasUnitState(UNIT_STATE_CASTING))
- + return;
- +
- + if (!UpdateVictim())
- + return;
- +
- + while (uint32 eventId = events.ExecuteEvent())
- + {
- + switch (eventId)
- + {
- + case EVENT_CLAW:
- + DoCastVictim(SPELL_CLAW);
- + // CORRECCIÓN: Cambiar SELECT_TARGET_RANDOM por SelectTargetMethod::Random
- + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 50.0f, true))
- + {
- + ResetThreatList();
- + AddThreat(target, 10.0f);
- + me->AI()->AttackStart(target);
- + }
- + events.ScheduleEvent(EVENT_CLAW, 12s, 15s);
- + break;
- + case EVENT_LEAP:
- + if (me->GetEntry() == NPC_RISEN_ARELAS || me->GetEntry() == NPC_RISEN_JAEREN)
- + {
- + // CORRECCIÓN: Cambiar SELECT_TARGET_RANDOM por SelectTargetMethod::Random
- + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 30.0f, true))
- + DoCast(target, SPELL_LEAP);
- + events.ScheduleEvent(EVENT_LEAP, 8s, 10s);
- + }
- + break;
- + default:
- + break;
- + }
- + }
- + DoMeleeAttackIfReady();
- + }
- + };
- +
- + CreatureAI* GetAI(Creature* creature) const override
- + {
- + return GetTrialOfChampionAI<npc_risen_ghoulAI>(creature);
- + }
- +};
- +
- +class boss_black_knight : public CreatureScript
- +{
- +public:
- + boss_black_knight() : CreatureScript("boss_black_knight") {}
- +
- + struct boss_black_knightAI : public BossAI
- + {
- + boss_black_knightAI(Creature* creature) : BossAI(creature, DATA_BLACK_KNIGHT)
- + {
- + Initialize();
- + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- + me->SetReactState(REACT_PASSIVE);
- + }
- +
- + void Initialize()
- + {
- + uiPhase = PHASE_UNDEAD;
- + achievementCredit = true;
- + }
- +
- + uint8 uiPhase;
- + bool achievementCredit;
- +
- + void Reset() override
- + {
- + me->SetDisplayId(me->GetNativeDisplayId());
- + SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
- + _Reset();
- + Initialize();
- + }
- +
- + void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER) override
- + {
- + BossAI::EnterEvadeMode(why);
- + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC);
- + }
- +
- + // Events are not resetted in this function
- + void LoadEvents()
- + {
- + if (uiPhase == PHASE_GHOST)
- + {
- + // Phase 3
- + events.ScheduleEvent(EVENT_DEATH_BITE, 5s);
- + events.ScheduleEvent(EVENT_MARKED_DEATH, 20s);
- + }
- + else
- + {
- + // Phase 1 and 2
- + events.ScheduleEvent(EVENT_ICY_TOUCH, 6s);
- + if (uiPhase == PHASE_UNDEAD)
- + {
- + // Phase 1 only
- + events.ScheduleEvent(EVENT_DEATH_RESPITE, 8s);
- +
- + // Raising announcer as a ghoul
- + if (Creature* announcer = instance->GetCreature(DATA_ANNOUNCER))
- + {
- + // CORRECCIÓN: Simplificar CastSpell
- + if (announcer->GetEntry() == NPC_JAEREN)
- + announcer->CastSpell(me->GetVictim(), SPELL_RAISE_JAEREN, false);
- + else
- + announcer->CastSpell(me->GetVictim(), SPELL_RAISE_ARELAS, false);
- + }
- + }
- + else
- + {
- + // Phase 2 only
- + events.ScheduleEvent(EVENT_DESECRATION, 5s);
- + events.ScheduleEvent(EVENT_GHOUL_EXPLODE, 8s);
- +
- + // Army of the Dead
- + // disabling movement temporarily so the spell wont get interrupted
- + me->SetControlled(true, UNIT_STATE_ROOT);
- + DoCast(SPELL_ARMY_DEAD);
- + }
- + }
- + }
- +
- + void SetData(uint32 type, uint32 /*data*/) override
- + {
- + if (type == 1)
- + achievementCredit = false;
- + }
- +
- + void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
- + {
- + if (spellInfo->Id == SPELL_BLACK_KNIGHT_RES)
- + {
- + // TODO: According to sniffs, The Black Knight should update
- + // creature template to another entry, not just change his display id
- + // But the other templates are missing correct damage modifiers
- + me->SetFullHealth();
- + me->SetStandState(UNIT_STAND_STATE_STAND);
- + if (uiPhase == PHASE_UNDEAD)
- + {
- + me->SetDisplayId(MODEL_SKELETON);
- + Talk(SAY_PHASE_2);
- + }
- + else if (uiPhase == PHASE_SKELETON)
- + {
- + me->SetDisplayId(MODEL_GHOST);
- + SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
- + Talk(SAY_PHASE_3);
- + }
- + ++uiPhase;
- + LoadEvents();
- + }
- + }
- +
- + void MovementInform(uint32 type, uint32 id) override
- + {
- + if (type != POINT_MOTION_TYPE)
- + return;
- +
- + if (id == 0)
- + {
- + if (Creature* announcer = instance->GetCreature(DATA_ANNOUNCER))
- + announcer->AI()->SetData(DATA_BLACK_KNIGHT_PRECAST, 0);
- + }
- + }
- +
- + void JustSummoned(Creature* summon) override
- + {
- + if (summon->GetEntry() == NPC_DESECRATION_STALKER)
- + {
- + summon->CastSpell(summon, SPELL_DESECRATION_DND, true);
- + summon->CastSpell(summon, SPELL_DESECRATION_ARM, true);
- + return;
- + }
- + summons.Summon(summon);
- + summon->AI()->AttackStart(me->GetVictim());
- + }
- +
- + void SummonedCreatureDespawn(Creature* summon) override
- + {
- + summons.Despawn(summon);
- + }
- +
- + void DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
- + {
- + if (damage >= me->GetHealth() && uiPhase < PHASE_GHOST)
- + {
- + damage = 0;
- + events.Reset();
- + me->RemoveAllAuras();
- + me->SetHealth(0);
- + me->SetStandState(UNIT_STAND_STATE_DEAD);
- + DoCast(me, SPELL_BLACK_KNIGHT_DIE);
- + for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
- + {
- + Creature* ghoul = ObjectAccessor::GetCreature(*me, *itr);
- + if (ghoul && ghoul->IsAlive() && !ghoul->HasAura(SPELL_GHOUL_EXPLODE))
- + ENSURE_AI(npc_risen_ghoul::npc_risen_ghoulAI, ghoul->AI())->DoExplode();
- + }
- + }
- + }
- +
- + void JustDied(Unit* /*killer*/) override
- + {
- + Talk(SAY_DEATH);
- + instance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_KILL_CREDIT, 0, me);
- + _JustDied();
- + }
- +
- + void JustEngagedWith(Unit* who) override
- + {
- + LoadEvents();
- + Talk(SAY_AGGRO, who);
- + _JustEngagedWith(who); // CORRECCIÓN: Agregar parámetro
- + }
- +
- + void KilledUnit(Unit* who) override
- + {
- + Talk(SAY_KILL, who);
- + }
- +
- + void UpdateAI(uint32 uiDiff) override
- + {
- + events.Update(uiDiff);
- +
- + if (me->HasUnitState(UNIT_STATE_CASTING))
- + return;
- +
- + if (!UpdateVictim())
- + return;
- +
- + while (uint32 eventId = events.ExecuteEvent())
- + {
- + switch (eventId)
- + {
- + case EVENT_ICY_TOUCH:
- + DoCastVictim(SPELL_ICY_TOUCH);
- + events.ScheduleEvent(EVENT_PLAGUE_STRIKE, 1s);
- + break;
- + case EVENT_PLAGUE_STRIKE:
- + DoCastVictim(SPELL_PLAGUE_STRIKE);
- + events.ScheduleEvent(EVENT_OBLITERATE, 5s);
- + break;
- + case EVENT_OBLITERATE:
- + DoCastVictim(SPELL_OBLITERATE);
- + events.ScheduleEvent(EVENT_ICY_TOUCH, 5s, 8s);
- + break;
- + case EVENT_DEATH_RESPITE:
- + // TODO: fixing this later
- + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 50.0f, true))
- + DoCast(target, SPELL_DEATH_RESPITE);
- + events.ScheduleEvent(EVENT_DEATH_RESPITE, 15s, 16s);
- + break;
- + case EVENT_DESECRATION:
- + DoCastVictim(SPELL_DESECRATION);
- + events.ScheduleEvent(EVENT_DESECRATION, 15s, 16s);
- + break;
- + case EVENT_GHOUL_EXPLODE:
- + DoCastAOE(SPELL_GHOUL_EXPLODE);
- + events.ScheduleEvent(EVENT_GHOUL_EXPLODE, 15s, 16s);
- + break;
- + case EVENT_DEATH_BITE:
- + DoCastAOE(SPELL_DEATH_BITE);
- + events.ScheduleEvent(EVENT_DEATH_BITE, 3s);
- + break;
- + case EVENT_MARKED_DEATH:
- + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50.0f))
- + DoCast(target, SPELL_MARKED_DEATH);
- + events.ScheduleEvent(EVENT_MARKED_DEATH, 13s, 15s);
- + break;
- + default:
- + break;
- + }
- + }
- + DoMeleeAttackIfReady();
- + }
- + };
- +
- + CreatureAI* GetAI(Creature* creature) const override
- + {
- + return GetTrialOfChampionAI<boss_black_knightAI>(creature);
- + }
- +};
- +
- +class npc_black_knight_skeletal_gryphon : public CreatureScript
- +{
- +public:
- + npc_black_knight_skeletal_gryphon() : CreatureScript("npc_black_knight_skeletal_gryphon") {}
- +
- + struct npc_black_knight_skeletal_gryphonAI : public EscortAI
- + {
- + npc_black_knight_skeletal_gryphonAI(Creature* creature) : EscortAI(creature)
- + {
- + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- + me->SetReactState(REACT_PASSIVE);
- + me->SetCanFly(true);
- + me->SetDisableGravity(true);
- + SetDespawnAtEnd(true);
- +
- + uiWaypointPath = 0;
- + instance = creature->GetInstanceScript();
- + }
- +
- + InstanceScript* instance;
- + uint32 uiWaypointPath;
- +
- + void SetData(uint32 uiType, uint32 /*uiData*/) override
- + {
- + if (uiType == 1)
- + {
- + // Black Knight is flying towards arena
- + AddWaypoint(0, 766.99f, 657.16f, 457.43f);
- + AddWaypoint(1, 747.28f, 659.71f, 440.49f);
- + AddWaypoint(2, 730.03f, 639.59f, 428.16f);
- + AddWaypoint(3, 721.13f, 621.49f, 423.16f);
- + AddWaypoint(4, 731.72f, 599.81f, 421.99f);
- + AddWaypoint(5, 753.71f, 591.09f, 420.63f);
- + AddWaypoint(6, 776.53f, 597.52f, 418.05f);
- + AddWaypoint(7, 787.38f, 617.07f, 417.49f);
- + AddWaypoint(8, 777.06f, 636.98f, 416.57f);
- + AddWaypoint(9, 760.6f, 642.12f, 414.71f);
- + AddWaypoint(10, 752.58f, 632.35f, 411.63f);
- + // The vehicle starts flying away
- + AddWaypoint(11, 748.89f, 633.61f, 415.24f);
- + AddWaypoint(12, 740.42f, 636.31f, 418.32f);
- + AddWaypoint(13, 727.49f, 637.4f, 422.24f);
- + AddWaypoint(14, 716.59f, 617.99f, 422.24f);
- + AddWaypoint(15, 727.18f, 599.29f, 422.24f);
- + AddWaypoint(16, 746.63f, 587.77f, 422.24f);
- + AddWaypoint(17, 765.6f, 599.52f, 422.24f);
- + AddWaypoint(18, 777.01f, 618.79f, 422.24f);
- + AddWaypoint(19, 761.84f, 642.18f, 422.24f);
- + AddWaypoint(20, 746.09f, 670.33f, 429.68f);
- + AddWaypoint(21, 748.02f, 728.22f, 466.68f);
- + AddWaypoint(22, 779.44f, 797.49f, 477.79f);
- + AddWaypoint(23, 859.14f, 807.98f, 477.79f);
- + Start(false, true);
- + }
- + else if (uiType == 2)
- + {
- + me->SetCanFly(true);
- + me->SetDisableGravity(true);
- + SetEscortPaused(false);
- + }
- + }
- +
- + void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
- + {
- + if (waypointId == 10)
- + {
- + // Reached to arena
- + SetEscortPaused(true);
- + me->SetCanFly(false);
- + me->SetDisableGravity(false);
- + if (Creature* announcer = instance->GetCreature(DATA_ANNOUNCER))
- + {
- + me->SetFacingToObject(announcer);
- + announcer->AI()->SetData(DATA_BLACK_KNIGHT_PREPARE, 0);
- + }
- + }
- + }
- +
- + void UpdateAI(uint32 uiDiff) override
- + {
- + EscortAI::UpdateAI(uiDiff);
- +
- + UpdateVictim();
- + }
- +
- + };
- +
- + CreatureAI* GetAI(Creature* creature) const override
- + {
- + return GetTrialOfChampionAI<npc_black_knight_skeletal_gryphonAI>(creature);
- + }
- +};
- +
- +class spell_black_knight_deaths_push : public SpellScriptLoader
- +{
- +public:
- + spell_black_knight_deaths_push() : SpellScriptLoader("spell_black_knight_deaths_push") {}
- +
- + class spell_black_knight_deaths_push_AuraScript : public AuraScript
- + {
- + PrepareAuraScript(spell_black_knight_deaths_push_AuraScript);
- +
- + bool Validate(SpellInfo const* /*spellInfo*/) override
- + {
- + if (!sSpellMgr->GetSpellInfo(SPELL_DEATH_RESPITE_DND) ||
- + !sSpellMgr->GetSpellInfo(SPELL_FEIGN_DEATH))
- + return false;
- + return true;
- + }
- +
- + void HandleScript(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- + {
- + // The spell applies a dummy aura with short duration
- + // when the dummy aura is removed, announcer 'dies'
- + GetTarget()->RemoveAura(SPELL_DEATH_RESPITE_DND);
- + GetTarget()->CastSpell(GetTarget(), SPELL_FEIGN_DEATH, true);
- + // CORRECCIÓN: Cambiar UNIT_FLAG_NOT_SELECTABLE por UNIT_FLAG_UNINTERACTIBLE
- + GetTarget()->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
- + }
- +
- + void Register() override
- + {
- + AfterEffectRemove += AuraEffectRemoveFn(spell_black_knight_deaths_push_AuraScript::HandleScript, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
- + }
- + };
- +
- + AuraScript* GetAuraScript() const override
- + {
- + return new spell_black_knight_deaths_push_AuraScript();
- + }
- +};
- +
- +class spell_black_knight_obliterate : public SpellScriptLoader
- +{
- +public:
- + spell_black_knight_obliterate() : SpellScriptLoader("spell_black_knight_obliterate") {}
- +
- + class spell_black_knight_obliterate_SpellScript : public SpellScript
- + {
- + PrepareSpellScript(spell_black_knight_obliterate_SpellScript);
- +
- + bool Validate(SpellInfo const* /*spellInfo*/) override
- + {
- + if (!sSpellMgr->GetSpellInfo(SPELL_BLOOD_PLAGUE) ||
- + !sSpellMgr->GetSpellInfo(SPELL_FROST_FEVER) ||
- + !sSpellMgr->GetSpellInfo(SPELL_BLOOD_PLAGUE_H) ||
- + !sSpellMgr->GetSpellInfo(SPELL_FROST_FEVER_H))
- + return false;
- + return true;
- + }
- +
- + void CalculateDamage()
- + {
- + if (!GetHitUnit())
- + return;
- + uint32 bloodPlague = GetCaster()->GetMap()->IsHeroic() ? SPELL_BLOOD_PLAGUE_H : SPELL_BLOOD_PLAGUE;
- + uint32 frostFever = GetCaster()->GetMap()->IsHeroic() ? SPELL_FROST_FEVER_H : SPELL_FROST_FEVER;
- +
- + int32 damage = GetHitDamage();
- + int32 bonus = 0;
- + if (GetHitUnit()->HasAura(frostFever))
- + {
- + bonus += int32(damage * 0.3f);
- + GetHitUnit()->RemoveAurasDueToSpell(frostFever);
- + }
- + if (GetHitUnit()->HasAura(bloodPlague))
- + {
- + bonus += int32(damage * 0.3f);
- + GetHitUnit()->RemoveAurasDueToSpell(bloodPlague);
- + }
- + SetHitDamage(damage + bonus);
- + }
- +
- + void Register() override
- + {
- + OnHit += SpellHitFn(spell_black_knight_obliterate_SpellScript::CalculateDamage);
- + }
- + };
- +
- + SpellScript* GetSpellScript() const override
- + {
- + return new spell_black_knight_obliterate_SpellScript();
- + }
- +};
- +
- +class spell_black_knight_army_of_the_dead : public SpellScriptLoader
- +{
- +public:
- + spell_black_knight_army_of_the_dead() : SpellScriptLoader("spell_black_knight_army_of_the_dead") {}
- +
- + class spell_black_knight_army_of_the_dead_AuraScript : public AuraScript
- + {
- + PrepareAuraScript(spell_black_knight_army_of_the_dead_AuraScript);
- +
- + void RemoveFlag(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- + {
- + // that is wrong, movement disabled by spell (channel)
- + // On aura remove we must remove disable movement flag
- + if (Unit* caster = GetCaster())
- + caster->SetControlled(false, UNIT_STATE_ROOT);
- + }
- +
- + void Register() override
- + {
- + AfterEffectRemove += AuraEffectRemoveFn(spell_black_knight_army_of_the_dead_AuraScript::RemoveFlag, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
- + }
- + };
- +
- + AuraScript* GetAuraScript() const override
- + {
- + return new spell_black_knight_army_of_the_dead_AuraScript();
- + }
- +};
- +
- +class spell_black_knight_ghoul_explode : public SpellScriptLoader
- +{
- +public:
- + spell_black_knight_ghoul_explode() : SpellScriptLoader("spell_black_knight_ghoul_explode") {}
- +
- + class spell_black_knight_ghoul_explode_AuraScript : public AuraScript
- + {
- + PrepareAuraScript(spell_black_knight_ghoul_explode_AuraScript);
- +
- + bool Validate(SpellInfo const* /*spellInfo*/) override
- + {
- + if (!sSpellMgr->GetSpellInfo(SPELL_EXPLODE))
- + return false;
- + return true;
- + }
- +
- + void CastExplode(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- + {
- + // On Ghoul Explode aura apply, start casting Explode
- + GetTarget()->CastSpell(GetTarget(), SPELL_EXPLODE);
- + }
- +
- + void Register() override
- + {
- + AfterEffectApply += AuraEffectApplyFn(spell_black_knight_ghoul_explode_AuraScript::CastExplode, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
- + }
- + };
- +
- + AuraScript* GetAuraScript() const override
- + {
- + return new spell_black_knight_ghoul_explode_AuraScript();
- + }
- +};
- +
- +// Achievement id 3804 - I've Had Worse
- +class achievement_ive_had_worse : public AchievementCriteriaScript
- +{
- +public:
- + achievement_ive_had_worse() : AchievementCriteriaScript("achievement_ive_had_worse") {}
- +
- + bool OnCheck(Player* /*player*/, Unit* target) override
- + {
- + if (target->GetEntry() != NPC_BLACK_KNIGHT)
- + return false;
- + if (!ENSURE_AI(boss_black_knight::boss_black_knightAI, target->GetAI())->achievementCredit)
- + return false;
- + return true;
- + }
- +};
- +
- +void AddSC_boss_black_knight()
- +{
- + new boss_black_knight();
- + new npc_risen_ghoul();
- + new npc_black_knight_skeletal_gryphon();
- + new spell_black_knight_deaths_push();
- + new spell_black_knight_obliterate();
- + new spell_black_knight_army_of_the_dead();
- + new spell_black_knight_ghoul_explode();
- + new achievement_ive_had_worse();
- +}
- diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp
- dissimilarity index 75%
- index 3a789907f5..f0179d0e97 100644
- --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp
- +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp
- @@ -1,1039 +1,1800 @@
- -/*
- - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
- - *
- - * 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, see <http://www.gnu.org/licenses/>.
- - */
- -
- -/* ScriptData
- -SDName: boss_grand_champions
- -SD%Complete: 50 %
- -SDComment: Is missing the ai to make the npcs look for a new mount and use it.
- -SDCategory: Trial Of the Champion
- -EndScriptData */
- -
- -#include "ScriptMgr.h"
- -#include "InstanceScript.h"
- -#include "Map.h"
- -#include "ObjectAccessor.h"
- -#include "Player.h"
- -#include "ScriptedEscortAI.h"
- -#include "trial_of_the_champion.h"
- -#include "Vehicle.h"
- -
- -enum Spells
- -{
- - //Vehicle
- - SPELL_CHARGE = 63010,
- - SPELL_SHIELD_BREAKER = 68504,
- - SPELL_SHIELD = 66482,
- -
- - // Marshal Jacob Alerius && Mokra the Skullcrusher || Warrior
- - SPELL_MORTAL_STRIKE = 68783,
- - SPELL_MORTAL_STRIKE_H = 68784,
- - SPELL_BLADESTORM = 63784,
- - SPELL_INTERCEPT = 67540,
- - SPELL_ROLLING_THROW = 47115, //not implemented in the AI yet...
- -
- - // Ambrose Boltspark && Eressea Dawnsinger || Mage
- - SPELL_FIREBALL = 66042,
- - SPELL_FIREBALL_H = 68310,
- - SPELL_BLAST_WAVE = 66044,
- - SPELL_BLAST_WAVE_H = 68312,
- - SPELL_HASTE = 66045,
- - SPELL_POLYMORPH = 66043,
- - SPELL_POLYMORPH_H = 68311,
- -
- - // Colosos && Runok Wildmane || Shaman
- - SPELL_CHAIN_LIGHTNING = 67529,
- - SPELL_CHAIN_LIGHTNING_H = 68319,
- - SPELL_EARTH_SHIELD = 67530,
- - SPELL_HEALING_WAVE = 67528,
- - SPELL_HEALING_WAVE_H = 68318,
- - SPELL_HEX_OF_MENDING = 67534,
- -
- - // Jaelyne Evensong && Zul'tore || Hunter
- - SPELL_DISENGAGE = 68340, //not implemented in the AI yet...
- - SPELL_LIGHTNING_ARROWS = 66083,
- - SPELL_MULTI_SHOT = 66081,
- - SPELL_SHOOT = 65868,
- - SPELL_SHOOT_H = 67988,
- -
- - // Lana Stouthammer Evensong && Deathstalker Visceri || Rouge
- - SPELL_EVISCERATE = 67709,
- - SPELL_EVISCERATE_H = 68317,
- - SPELL_FAN_OF_KNIVES = 67706,
- - SPELL_POISON_BOTTLE = 67701
- -};
- -
- -enum Seats
- -{
- - SEAT_ID_0 = 0
- -};
- -
- -/*
- -struct Point
- -{
- - float x, y, z;
- -};
- -
- -const Point MovementPoint[] =
- -{
- - {746.84f, 623.15f, 411.41f},
- - {747.96f, 620.29f, 411.09f},
- - {750.23f, 618.35f, 411.09f}
- -};
- -*/
- -void AggroAllPlayers(Creature* temp)
- -{
- - Map::PlayerList const& PlList = temp->GetMap()->GetPlayers();
- -
- - if (PlList.isEmpty())
- - return;
- -
- - for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i)
- - {
- - if (Player* player = i->GetSource())
- - {
- - if (player->IsGameMaster())
- - continue;
- -
- - if (player->IsAlive())
- - {
- - temp->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- - temp->SetImmuneToPC(true);
- - temp->SetReactState(REACT_AGGRESSIVE);
- - temp->EngageWithTarget(player);
- - }
- - }
- - }
- -}
- -
- -bool GrandChampionsOutVehicle(Creature* me)
- -{
- - InstanceScript* instance = me->GetInstanceScript();
- -
- - if (!instance)
- - return false;
- -
- - Creature* pGrandChampion1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GRAND_CHAMPION_1));
- - Creature* pGrandChampion2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GRAND_CHAMPION_2));
- - Creature* pGrandChampion3 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GRAND_CHAMPION_3));
- -
- - if (pGrandChampion1 && pGrandChampion2 && pGrandChampion3)
- - {
- - if (!pGrandChampion1->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) &&
- - !pGrandChampion2->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) &&
- - !pGrandChampion3->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
- - return true;
- - }
- -
- - return false;
- -}
- -
- -/*
- -* Generic AI for vehicles used by npcs in ToC, it needs more improvements. *
- -* Script Complete: 25%. *
- -*/
- -
- -class generic_vehicleAI_toc5 : public CreatureScript
- -{
- -public:
- - generic_vehicleAI_toc5() : CreatureScript("generic_vehicleAI_toc5") { }
- -
- - struct generic_vehicleAI_toc5AI : public EscortAI
- - {
- - generic_vehicleAI_toc5AI(Creature* creature) : EscortAI(creature)
- - {
- - Initialize();
- - SetDespawnAtEnd(false);
- - uiWaypointPath = 0;
- -
- - instance = creature->GetInstanceScript();
- - }
- -
- - void Initialize()
- - {
- - uiChargeTimer = 5000;
- - uiShieldBreakerTimer = 8000;
- - uiBuffTimer = urand(30000, 60000);
- - }
- -
- - InstanceScript* instance;
- -
- - uint32 uiChargeTimer;
- - uint32 uiShieldBreakerTimer;
- - uint32 uiBuffTimer;
- -
- - uint32 uiWaypointPath;
- -
- - void Reset() override
- - {
- - Initialize();
- - }
- -
- - void SetData(uint32 uiType, uint32 /*uiData*/) override
- - {
- - switch (uiType)
- - {
- - case 1:
- - AddWaypoint(0, 747.36f, 634.07f, 411.572f);
- - AddWaypoint(1, 780.43f, 607.15f, 411.82f);
- - AddWaypoint(2, 785.99f, 599.41f, 411.92f);
- - AddWaypoint(3, 778.44f, 601.64f, 411.79f);
- - uiWaypointPath = 1;
- - break;
- - case 2:
- - AddWaypoint(0, 747.35f, 634.07f, 411.57f);
- - AddWaypoint(1, 768.72f, 581.01f, 411.92f);
- - AddWaypoint(2, 763.55f, 590.52f, 411.71f);
- - uiWaypointPath = 2;
- - break;
- - case 3:
- - AddWaypoint(0, 747.35f, 634.07f, 411.57f);
- - AddWaypoint(1, 784.02f, 645.33f, 412.39f);
- - AddWaypoint(2, 775.67f, 641.91f, 411.91f);
- - uiWaypointPath = 3;
- - break;
- - }
- -
- - if (uiType <= 3)
- - Start(false, true);
- - }
- -
- - void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
- - {
- - switch (waypointId)
- - {
- - case 2:
- - if (uiWaypointPath == 3 || uiWaypointPath == 2)
- - instance->SetData(DATA_MOVEMENT_DONE, instance->GetData(DATA_MOVEMENT_DONE)+1);
- - break;
- - case 3:
- - instance->SetData(DATA_MOVEMENT_DONE, instance->GetData(DATA_MOVEMENT_DONE)+1);
- - break;
- - }
- - }
- -
- - void JustEngagedWith(Unit* /*who*/) override
- - {
- - DoCastSpellShield();
- - }
- -
- - void DoCastSpellShield()
- - {
- - for (uint8 i = 0; i < 3; ++i)
- - DoCast(me, SPELL_SHIELD, true);
- - }
- -
- - void UpdateAI(uint32 uiDiff) override
- - {
- - EscortAI::UpdateAI(uiDiff);
- -
- - if (!UpdateVictim())
- - return;
- -
- - if (uiBuffTimer <= uiDiff)
- - {
- - if (!me->HasAura(SPELL_SHIELD))
- - DoCastSpellShield();
- -
- - uiBuffTimer = urand(30000, 45000);
- - }else uiBuffTimer -= uiDiff;
- -
- - if (uiChargeTimer <= uiDiff)
- - {
- - Map::PlayerList const& players = me->GetMap()->GetPlayers();
- - if (!players.isEmpty())
- - {
- - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
- - {
- - Player* player = itr->GetSource();
- - if (player && !player->IsGameMaster() && me->IsInRange(player, 8.0f, 25.0f, false))
- - {
- - ResetThreatList();
- - AddThreat(player, 1.0f);
- - DoCast(player, SPELL_CHARGE);
- - break;
- - }
- - }
- - }
- - uiChargeTimer = 5000;
- - }else uiChargeTimer -= uiDiff;
- -
- - //dosen't work at all
- - if (uiShieldBreakerTimer <= uiDiff)
- - {
- - Vehicle* pVehicle = me->GetVehicleKit();
- - if (!pVehicle)
- - return;
- -
- - if (Unit* pPassenger = pVehicle->GetPassenger(SEAT_ID_0))
- - {
- - Map::PlayerList const& players = me->GetMap()->GetPlayers();
- - if (!players.isEmpty())
- - {
- - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
- - {
- - Player* player = itr->GetSource();
- - if (player && !player->IsGameMaster() && me->IsInRange(player, 10.0f, 30.0f, false))
- - {
- - pPassenger->CastSpell(player, SPELL_SHIELD_BREAKER, true);
- - break;
- - }
- - }
- - }
- - }
- - uiShieldBreakerTimer = 7000;
- - }else uiShieldBreakerTimer -= uiDiff;
- -
- - DoMeleeAttackIfReady();
- - }
- - };
- -
- - CreatureAI* GetAI(Creature* creature) const override
- - {
- - return GetTrialOfTheChampionAI<generic_vehicleAI_toc5AI>(creature);
- - }
- -};
- -
- -class boss_warrior_toc5 : public CreatureScript
- -{
- -public:
- - boss_warrior_toc5() : CreatureScript("boss_warrior_toc5") { }
- -
- - // Marshal Jacob Alerius && Mokra the Skullcrusher || Warrior
- - struct boss_warrior_toc5AI : public ScriptedAI
- - {
- - boss_warrior_toc5AI(Creature* creature) : ScriptedAI(creature)
- - {
- - Initialize();
- - instance = creature->GetInstanceScript();
- -
- - bDone = false;
- - bHome = false;
- -
- - uiPhase = 0;
- - uiPhaseTimer = 0;
- -
- - me->SetReactState(REACT_PASSIVE);
- - // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED
- - me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- - me->SetImmuneToPC(true);
- - }
- -
- - void Initialize()
- - {
- - uiBladeStormTimer = urand(15000, 20000);
- - uiInterceptTimer = 7000;
- - uiMortalStrikeTimer = urand(8000, 12000);
- - }
- -
- - InstanceScript* instance;
- -
- - uint8 uiPhase;
- - uint32 uiPhaseTimer;
- -
- - uint32 uiBladeStormTimer;
- - uint32 uiInterceptTimer;
- - uint32 uiMortalStrikeTimer;
- -
- - bool bDone;
- - bool bHome;
- -
- - void Reset() override
- - {
- - Initialize();
- - }
- -
- - void JustReachedHome() override
- - {
- - ScriptedAI::JustReachedHome();
- -
- - if (!bHome)
- - return;
- -
- - uiPhaseTimer = 15000;
- - uiPhase = 1;
- -
- - bHome = false;
- - }
- -
- - void UpdateAI(uint32 uiDiff) override
- - {
- - if (!bDone && GrandChampionsOutVehicle(me))
- - {
- - bDone = true;
- -
- - if (me->GetGUID() == instance->GetGuidData(DATA_GRAND_CHAMPION_1))
- - me->SetHomePosition(739.678f, 662.541f, 412.393f, 4.49f);
- - else if (me->GetGUID() == instance->GetGuidData(DATA_GRAND_CHAMPION_2))
- - me->SetHomePosition(746.71f, 661.02f, 411.69f, 4.6f);
- - else if (me->GetGUID() == instance->GetGuidData(DATA_GRAND_CHAMPION_3))
- - me->SetHomePosition(754.34f, 660.70f, 412.39f, 4.79f);
- -
- - EnterEvadeMode();
- - bHome = true;
- - }
- -
- - if (uiPhaseTimer <= uiDiff)
- - {
- - if (uiPhase == 1)
- - {
- - AggroAllPlayers(me);
- - uiPhase = 0;
- - }
- - }else uiPhaseTimer -= uiDiff;
- -
- - if (!UpdateVictim() || !me->m_movementInfo.transport.guid.IsEmpty())
- - return;
- -
- - if (uiInterceptTimer <= uiDiff)
- - {
- - Map::PlayerList const& players = me->GetMap()->GetPlayers();
- - if (!players.isEmpty())
- - {
- - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
- - {
- - Player* player = itr->GetSource();
- - if (player && !player->IsGameMaster() && me->IsInRange(player, 8.0f, 25.0f, false))
- - {
- - ResetThreatList();
- - AddThreat(player, 5.0f);
- - DoCast(player, SPELL_INTERCEPT);
- - break;
- - }
- - }
- - }
- - uiInterceptTimer = 7000;
- - } else uiInterceptTimer -= uiDiff;
- -
- - if (uiBladeStormTimer <= uiDiff)
- - {
- - DoCastVictim(SPELL_BLADESTORM);
- - uiBladeStormTimer = urand(15000, 20000);
- - } else uiBladeStormTimer -= uiDiff;
- -
- - if (uiMortalStrikeTimer <= uiDiff)
- - {
- - DoCastVictim(SPELL_MORTAL_STRIKE);
- - uiMortalStrikeTimer = urand(8000, 12000);
- - } else uiMortalStrikeTimer -= uiDiff;
- -
- - DoMeleeAttackIfReady();
- - }
- -
- - void JustDied(Unit* /*killer*/) override
- - {
- - instance->SetBossState(BOSS_GRAND_CHAMPIONS, DONE);
- - }
- - };
- -
- - CreatureAI* GetAI(Creature* creature) const override
- - {
- - return GetTrialOfTheChampionAI<boss_warrior_toc5AI>(creature);
- - }
- -};
- -
- -class boss_mage_toc5 : public CreatureScript
- -{
- -public:
- - boss_mage_toc5() : CreatureScript("boss_mage_toc5") { }
- -
- - // Ambrose Boltspark && Eressea Dawnsinger || Mage
- - struct boss_mage_toc5AI : public ScriptedAI
- - {
- - boss_mage_toc5AI(Creature* creature) : ScriptedAI(creature)
- - {
- - Initialize();
- - instance = creature->GetInstanceScript();
- -
- - bDone = false;
- - bHome = false;
- -
- - uiPhase = 0;
- - uiPhaseTimer = 0;
- -
- - me->SetReactState(REACT_PASSIVE);
- - // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED
- - me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- - me->SetImmuneToPC(true);
- - }
- -
- - void Initialize()
- - {
- - uiFireBallTimer = 5000;
- - uiPolymorphTimer = 8000;
- - uiBlastWaveTimer = 12000;
- - uiHasteTimer = 22000;
- - }
- -
- - InstanceScript* instance;
- -
- - uint8 uiPhase;
- - uint32 uiPhaseTimer;
- -
- - uint32 uiFireBallTimer;
- - uint32 uiBlastWaveTimer;
- - uint32 uiHasteTimer;
- - uint32 uiPolymorphTimer;
- -
- - bool bDone;
- - bool bHome;
- -
- - void Reset() override
- - {
- - Initialize();
- - }
- -
- - void JustReachedHome() override
- - {
- - ScriptedAI::JustReachedHome();
- -
- - if (!bHome)
- - return;
- -
- - uiPhaseTimer = 15000;
- - uiPhase = 1;
- -
- - bHome = false;
- - }
- -
- - void UpdateAI(uint32 uiDiff) override
- - {
- - if (!bDone && GrandChampionsOutVehicle(me))
- - {
- - bDone = true;
- -
- - if (me->GetGUID() == instance->GetGuidData(DATA_GRAND_CHAMPION_1))
- - me->SetHomePosition(739.678f, 662.541f, 412.393f, 4.49f);
- - else if (me->GetGUID() == instance->GetGuidData(DATA_GRAND_CHAMPION_2))
- - me->SetHomePosition(746.71f, 661.02f, 411.69f, 4.6f);
- - else if (me->GetGUID() == instance->GetGuidData(DATA_GRAND_CHAMPION_3))
- - me->SetHomePosition(754.34f, 660.70f, 412.39f, 4.79f);
- -
- - instance->SetBossState(BOSS_GRAND_CHAMPIONS, IN_PROGRESS);
- -
- - EnterEvadeMode();
- - bHome = true;
- - }
- -
- - if (uiPhaseTimer <= uiDiff)
- - {
- - if (uiPhase == 1)
- - {
- - AggroAllPlayers(me);
- - uiPhase = 0;
- - }
- - }else uiPhaseTimer -= uiDiff;
- -
- - if (uiFireBallTimer <= uiDiff)
- - {
- - if (me->GetVictim())
- - DoCastVictim(SPELL_FIREBALL);
- - uiFireBallTimer = 5000;
- - } else uiFireBallTimer -= uiDiff;
- -
- - if (!UpdateVictim() || !me->m_movementInfo.transport.guid.IsEmpty())
- - return;
- -
- - if (uiFireBallTimer <= uiDiff)
- - {
- - DoCastVictim(SPELL_FIREBALL);
- - uiFireBallTimer = 5000;
- - } else uiFireBallTimer -= uiDiff;
- -
- - if (uiPolymorphTimer <= uiDiff)
- - {
- - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
- - DoCast(target, SPELL_POLYMORPH);
- - uiPolymorphTimer = 8000;
- - } else uiPolymorphTimer -= uiDiff;
- -
- - if (uiBlastWaveTimer <= uiDiff)
- - {
- - DoCastAOE(SPELL_BLAST_WAVE, false);
- - uiBlastWaveTimer = 13000;
- - } else uiBlastWaveTimer -= uiDiff;
- -
- - if (uiHasteTimer <= uiDiff)
- - {
- - me->InterruptNonMeleeSpells(true);
- -
- - DoCast(me, SPELL_HASTE);
- - uiHasteTimer = 22000;
- - } else uiHasteTimer -= uiDiff;
- -
- - DoMeleeAttackIfReady();
- - }
- -
- - void JustDied(Unit* /*killer*/) override
- - {
- - instance->SetBossState(BOSS_GRAND_CHAMPIONS, DONE);
- - }
- - };
- -
- - CreatureAI* GetAI(Creature* creature) const override
- - {
- - return GetTrialOfTheChampionAI<boss_mage_toc5AI>(creature);
- - }
- -};
- -
- -class boss_shaman_toc5 : public CreatureScript
- -{
- -public:
- - boss_shaman_toc5() : CreatureScript("boss_shaman_toc5") { }
- -
- - // Colosos && Runok Wildmane || Shaman
- - struct boss_shaman_toc5AI : public ScriptedAI
- - {
- - boss_shaman_toc5AI(Creature* creature) : ScriptedAI(creature)
- - {
- - Initialize();
- - instance = creature->GetInstanceScript();
- -
- - bDone = false;
- - bHome = false;
- -
- - uiPhase = 0;
- - uiPhaseTimer = 0;
- -
- - me->SetReactState(REACT_PASSIVE);
- - // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED
- - me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- - me->SetImmuneToPC(true);
- - }
- -
- - void Initialize()
- - {
- - uiChainLightningTimer = 16000;
- - uiHealingWaveTimer = 12000;
- - uiEartShieldTimer = urand(30000, 35000);
- - uiHexMendingTimer = urand(20000, 25000);
- - }
- -
- - InstanceScript* instance;
- -
- - uint8 uiPhase;
- - uint32 uiPhaseTimer;
- -
- - uint32 uiChainLightningTimer;
- - uint32 uiEartShieldTimer;
- - uint32 uiHealingWaveTimer;
- - uint32 uiHexMendingTimer;
- -
- - bool bDone;
- - bool bHome;
- -
- - void Reset() override
- - {
- - Initialize();
- - }
- -
- - void JustEngagedWith(Unit* who) override
- - {
- - DoCast(me, SPELL_EARTH_SHIELD);
- - DoCast(who, SPELL_HEX_OF_MENDING);
- - };
- -
- - void JustReachedHome() override
- - {
- - ScriptedAI::JustReachedHome();
- -
- - if (!bHome)
- - return;
- -
- - uiPhaseTimer = 15000;
- - uiPhase = 1;
- -
- - bHome = false;
- - }
- -
- - void UpdateAI(uint32 uiDiff) override
- - {
- - if (!bDone && GrandChampionsOutVehicle(me))
- - {
- - bDone = true;
- -
- - if (me->GetGUID() == instance->GetGuidData(DATA_GRAND_CHAMPION_1))
- - me->SetHomePosition(739.678f, 662.541f, 412.393f, 4.49f);
- - else if (me->GetGUID() == instance->GetGuidData(DATA_GRAND_CHAMPION_2))
- - me->SetHomePosition(746.71f, 661.02f, 411.69f, 4.6f);
- - else if (me->GetGUID() == instance->GetGuidData(DATA_GRAND_CHAMPION_3))
- - me->SetHomePosition(754.34f, 660.70f, 412.39f, 4.79f);
- -
- - instance->SetBossState(BOSS_GRAND_CHAMPIONS, IN_PROGRESS);
- -
- - EnterEvadeMode();
- - bHome = true;
- - }
- -
- - if (uiPhaseTimer <= uiDiff)
- - {
- - if (uiPhase == 1)
- - {
- - AggroAllPlayers(me);
- - uiPhase = 0;
- - }
- - }else uiPhaseTimer -= uiDiff;
- -
- - if (!UpdateVictim() || !me->m_movementInfo.transport.guid.IsEmpty())
- - return;
- -
- - if (uiChainLightningTimer <= uiDiff)
- - {
- - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
- - DoCast(target, SPELL_CHAIN_LIGHTNING);
- -
- - uiChainLightningTimer = 16000;
- - } else uiChainLightningTimer -= uiDiff;
- -
- - if (uiHealingWaveTimer <= uiDiff)
- - {
- - bool bChance = roll_chance_i(50);
- -
- - if (!bChance)
- - {
- - if (Unit* pFriend = DoSelectLowestHpFriendly(40))
- - DoCast(pFriend, SPELL_HEALING_WAVE);
- - } else
- - DoCast(me, SPELL_HEALING_WAVE);
- -
- - uiHealingWaveTimer = 12000;
- - } else uiHealingWaveTimer -= uiDiff;
- -
- - if (uiEartShieldTimer <= uiDiff)
- - {
- - DoCast(me, SPELL_EARTH_SHIELD);
- -
- - uiEartShieldTimer = urand(30000, 35000);
- - } else uiEartShieldTimer -= uiDiff;
- -
- - if (uiHexMendingTimer <= uiDiff)
- - {
- - DoCastVictim(SPELL_HEX_OF_MENDING, true);
- -
- - uiHexMendingTimer = urand(20000, 25000);
- - } else uiHexMendingTimer -= uiDiff;
- -
- - DoMeleeAttackIfReady();
- - }
- -
- - void JustDied(Unit* /*killer*/) override
- - {
- - instance->SetBossState(BOSS_GRAND_CHAMPIONS, DONE);
- - }
- - };
- -
- - CreatureAI* GetAI(Creature* creature) const override
- - {
- - return GetTrialOfTheChampionAI<boss_shaman_toc5AI>(creature);
- - }
- -};
- -
- -class boss_hunter_toc5 : public CreatureScript
- -{
- -public:
- - boss_hunter_toc5() : CreatureScript("boss_hunter_toc5") { }
- -
- - // Jaelyne Evensong && Zul'tore || Hunter
- - struct boss_hunter_toc5AI : public ScriptedAI
- - {
- - boss_hunter_toc5AI(Creature* creature) : ScriptedAI(creature)
- - {
- - Initialize();
- - instance = creature->GetInstanceScript();
- -
- - bDone = false;
- - bHome = false;
- -
- - uiPhase = 0;
- - uiPhaseTimer = 0;
- -
- - me->SetReactState(REACT_PASSIVE);
- - // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED
- - me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- - me->SetImmuneToPC(true);
- - }
- -
- - void Initialize()
- - {
- - uiShootTimer = 12000;
- - uiMultiShotTimer = 0;
- - uiLightningArrowsTimer = 7000;
- -
- - uiTargetGUID.Clear();
- -
- - bShoot = false;
- - }
- -
- - InstanceScript* instance;
- -
- - uint8 uiPhase;
- - uint32 uiPhaseTimer;
- -
- - uint32 uiShootTimer;
- - uint32 uiMultiShotTimer;
- - uint32 uiLightningArrowsTimer;
- -
- - ObjectGuid uiTargetGUID;
- -
- - bool bShoot;
- - bool bDone;
- - bool bHome;
- -
- - void Reset() override
- - {
- - Initialize();
- - }
- -
- - void JustReachedHome() override
- - {
- - ScriptedAI::JustReachedHome();
- -
- - if (!bHome)
- - return;
- -
- - uiPhaseTimer = 15000;
- - uiPhase = 1;
- -
- - bHome = false;
- - }
- -
- - void UpdateAI(uint32 uiDiff) override
- - {
- - if (!bDone && GrandChampionsOutVehicle(me))
- - {
- - bDone = true;
- -
- - if (me->GetGUID() == instance->GetGuidData(DATA_GRAND_CHAMPION_1))
- - me->SetHomePosition(739.678f, 662.541f, 412.393f, 4.49f);
- - else if (me->GetGUID() == instance->GetGuidData(DATA_GRAND_CHAMPION_2))
- - me->SetHomePosition(746.71f, 661.02f, 411.69f, 4.6f);
- - else if (me->GetGUID() == instance->GetGuidData(DATA_GRAND_CHAMPION_3))
- - me->SetHomePosition(754.34f, 660.70f, 412.39f, 4.79f);
- -
- - instance->SetBossState(BOSS_GRAND_CHAMPIONS, IN_PROGRESS);
- -
- - EnterEvadeMode();
- - bHome = true;
- - }
- -
- - if (uiPhaseTimer <= uiDiff)
- - {
- - if (uiPhase == 1)
- - {
- - AggroAllPlayers(me);
- - uiPhase = 0;
- - }
- - }else uiPhaseTimer -= uiDiff;
- -
- - if (!UpdateVictim() || !me->m_movementInfo.transport.guid.IsEmpty())
- - return;
- -
- - if (uiLightningArrowsTimer <= uiDiff)
- - {
- - DoCastAOE(SPELL_LIGHTNING_ARROWS, false);
- - uiLightningArrowsTimer = 7000;
- - } else uiLightningArrowsTimer -= uiDiff;
- -
- - if (uiShootTimer <= uiDiff)
- - {
- - if (Unit* target = SelectTarget(SelectTargetMethod::MaxDistance, 0, 30.0f))
- - {
- - uiTargetGUID = target->GetGUID();
- - DoCast(target, SPELL_SHOOT);
- - }
- - uiShootTimer = 12000;
- - uiMultiShotTimer = 3000;
- - bShoot = true;
- - } else uiShootTimer -= uiDiff;
- -
- - if (bShoot && uiMultiShotTimer <= uiDiff)
- - {
- - me->InterruptNonMeleeSpells(true);
- - Unit* target = ObjectAccessor::GetUnit(*me, uiTargetGUID);
- -
- - if (target && me->IsInRange(target, 5.0f, 30.0f, false))
- - {
- - DoCast(target, SPELL_MULTI_SHOT);
- - }
- - else
- - {
- - Map::PlayerList const& players = me->GetMap()->GetPlayers();
- - if (!players.isEmpty())
- - {
- - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
- - {
- - Player* player = itr->GetSource();
- - if (player && !player->IsGameMaster() && me->IsInRange(player, 5.0f, 30.0f, false))
- - {
- - DoCast(player, SPELL_MULTI_SHOT);
- - break;
- - }
- - }
- - }
- - }
- - bShoot = false;
- - } else uiMultiShotTimer -= uiDiff;
- -
- - DoMeleeAttackIfReady();
- - }
- -
- - void JustDied(Unit* /*killer*/) override
- - {
- - instance->SetBossState(BOSS_GRAND_CHAMPIONS, DONE);
- - }
- - };
- -
- - CreatureAI* GetAI(Creature* creature) const override
- - {
- - return GetTrialOfTheChampionAI<boss_hunter_toc5AI>(creature);
- - }
- -};
- -
- -class boss_rouge_toc5 : public CreatureScript
- -{
- -public:
- - boss_rouge_toc5() : CreatureScript("boss_rouge_toc5") { }
- -
- - // Lana Stouthammer Evensong && Deathstalker Visceri || Rouge
- - struct boss_rouge_toc5AI : public ScriptedAI
- - {
- - boss_rouge_toc5AI(Creature* creature) : ScriptedAI(creature)
- - {
- - Initialize();
- - instance = creature->GetInstanceScript();
- -
- - bDone = false;
- - bHome = false;
- -
- - uiPhase = 0;
- - uiPhaseTimer = 0;
- -
- - me->SetReactState(REACT_PASSIVE);
- - // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED
- - me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- - me->SetImmuneToPC(true);
- - }
- -
- - void Initialize()
- - {
- - uiEviscerateTimer = 8000;
- - uiFanKivesTimer = 14000;
- - uiPosionBottleTimer = 19000;
- - }
- -
- - InstanceScript* instance;
- -
- - uint8 uiPhase;
- - uint32 uiPhaseTimer;
- - uint32 uiEviscerateTimer;
- - uint32 uiFanKivesTimer;
- - uint32 uiPosionBottleTimer;
- -
- - bool bDone;
- - bool bHome;
- -
- - void Reset() override
- - {
- - Initialize();
- - }
- -
- - void JustReachedHome() override
- - {
- - ScriptedAI::JustReachedHome();
- -
- - if (!bHome)
- - return;
- -
- - uiPhaseTimer = 15000;
- - uiPhase = 1;
- -
- - bHome = false;
- - }
- -
- - void UpdateAI(uint32 uiDiff) override
- - {
- - if (!bDone && GrandChampionsOutVehicle(me))
- - {
- - bDone = true;
- -
- - if (me->GetGUID() == instance->GetGuidData(DATA_GRAND_CHAMPION_1))
- - me->SetHomePosition(739.678f, 662.541f, 412.393f, 4.49f);
- - else if (me->GetGUID() == instance->GetGuidData(DATA_GRAND_CHAMPION_2))
- - me->SetHomePosition(746.71f, 661.02f, 411.69f, 4.6f);
- - else if (me->GetGUID() == instance->GetGuidData(DATA_GRAND_CHAMPION_3))
- - me->SetHomePosition(754.34f, 660.70f, 412.39f, 4.79f);
- -
- - instance->SetBossState(BOSS_GRAND_CHAMPIONS, IN_PROGRESS);
- -
- - EnterEvadeMode();
- - bHome = true;
- - }
- -
- - if (uiPhaseTimer <= uiDiff)
- - {
- - if (uiPhase == 1)
- - {
- - AggroAllPlayers(me);
- - uiPhase = 0;
- - }
- - } else uiPhaseTimer -= uiDiff;
- -
- - if (!UpdateVictim() || !me->m_movementInfo.transport.guid.IsEmpty())
- - return;
- -
- - if (uiEviscerateTimer <= uiDiff)
- - {
- - DoCastVictim(SPELL_EVISCERATE);
- - uiEviscerateTimer = 8000;
- - } else uiEviscerateTimer -= uiDiff;
- -
- - if (uiFanKivesTimer <= uiDiff)
- - {
- - DoCastAOE(SPELL_FAN_OF_KNIVES, false);
- - uiFanKivesTimer = 14000;
- - } else uiFanKivesTimer -= uiDiff;
- -
- - if (uiPosionBottleTimer <= uiDiff)
- - {
- - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
- - DoCast(target, SPELL_POISON_BOTTLE);
- - uiPosionBottleTimer = 19000;
- - } else uiPosionBottleTimer -= uiDiff;
- -
- - DoMeleeAttackIfReady();
- - }
- -
- - void JustDied(Unit* /*killer*/) override
- - {
- - instance->SetBossState(BOSS_GRAND_CHAMPIONS, DONE);
- - }
- - };
- -
- - CreatureAI* GetAI(Creature* creature) const override
- - {
- - return GetTrialOfTheChampionAI<boss_rouge_toc5AI>(creature);
- - }
- -};
- -
- -void AddSC_boss_grand_champions()
- -{
- - new generic_vehicleAI_toc5();
- - new boss_warrior_toc5();
- - new boss_mage_toc5();
- - new boss_shaman_toc5();
- - new boss_hunter_toc5();
- - new boss_rouge_toc5();
- -}
- +/*
- + * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
- + * 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, see <http://www.gnu.org/licenses/>.
- + */
- +
- + /* ScriptData
- + SDName: boss_grand_champions
- + SD%Complete: 99%
- + SDComment: Cosmetic things missing
- + SDCategory: Trial Of the Champion
- + EndScriptData */
- +
- +#include "GridNotifiers.h"
- +#include "Player.h"
- +#include "ScriptedCreature.h"
- +#include "ScriptedEscortAI.h"
- +#include "ScriptMgr.h"
- +#include "SpellAuraEffects.h"
- +#include "SpellScript.h"
- +#include "SpellMgr.h"
- +#include "Vehicle.h"
- +#include "trial_of_the_champion.h"
- +
- +enum Events
- +{
- + // Grand Champion
- + EVENT_WALK_TO_MOUNT = 1,
- + EVENT_START_ATTACK_JOUST,
- + EVENT_TRAMPLE,
- + EVENT_EVADE_MODE,
- + EVENT_START_ATTACK_REAL,
- + EVENT_DESPAWN,
- + // General vehicle AI
- + EVENT_BUFF_SHIELD,
- + EVENT_BUFF_FLAG,
- + EVENT_MOUNT_CHARGE,
- + EVENT_SHIELD_BREAKER,
- + // Warrior - Grand Champion
- + EVENT_BLADESTORM,
- + EVENT_INTERCEPT,
- + EVENT_MORTAL_STRIKE,
- + EVENT_ROLLING_THROW,
- + // Mage - Grand Champion
- + EVENT_FIREBALL,
- + EVENT_BLASTWAVE,
- + EVENT_HASTE,
- + EVENT_POLYMORPH,
- + // Shaman - Grand Champion
- + EVENT_DEF_CHECK,
- + EVENT_CHAIN_LIGHTNING,
- + EVENT_HEALING_WAVE,
- + EVENT_EARTH_SHIELD,
- + EVENT_HEX_MENDING,
- + // Hunter - Grand Champion
- + EVENT_MULTI_SHOT,
- + EVENT_LIGHTNING_ARROWS,
- + EVENT_DISENGAGE,
- + // Rogue - Grand Champion
- + EVENT_DEADLY_POISON,
- + EVENT_EVISCERATE,
- + EVENT_FAN_OF_KNIVES,
- + EVENT_POISON_BOTTLE
- +};
- +
- +enum Spells
- +{
- + // Vehicle
- + SPELL_CHARGE_GRAND_CHAMP = 68321,
- + SPELL_CHARGE_LESSER_CHAMP = 63010,
- + SPELL_SHIELD_BREAKER = 68504,
- + SPELL_SHIELD_GRAND_CHAMP = 62719,
- + SPELL_SHIELD_LESSER_CHAMP = 64100,
- + SPELL_TRAMPLE_DUMMY_AURA = 67870, // triggers trample aura every 1 second, used by all vehicles
- + SPELL_TRAMPLE_AURA = 67868, // actual trample stun
- +
- + // General
- + SPELL_ACHIEVEMENT_CREDIT = 68572, // dummy spell for achievement credit (IDs 4297, 4298, 3778, 4296)
- + SPELL_KNEEL = 68442,
- +
- + // Marshal Jacob Alerius && Mokra the Skullcrusher || Warrior
- + SPELL_MORTAL_STRIKE = 68783,
- + SPELL_BLADESTORM = 67541,
- + SPELL_INTERCEPT = 67540,
- + SPELL_ROLLING_THROW = 67546,
- +
- + // Ambrose Boltspark && Eressea Dawnsinger || Mage
- + SPELL_FIREBALL = 66042,
- + SPELL_BLAST_WAVE = 66044,
- + SPELL_HASTE = 66045,
- + SPELL_POLYMORPH = 66043,
- +
- + // Colosos && Runok Wildmane || Shaman
- + SPELL_CHAIN_LIGHTNING = 67529,
- + SPELL_EARTH_SHIELD = 67530,
- + SPELL_HEALING_WAVE = 67528,
- + SPELL_HEX_OF_MENDING = 67534,
- +
- + // Jaelyne Evensong && Zul'tore || Hunter
- + SPELL_DISENGAGE = 68339, // 68340 is correct disengage but spell needs to be scripted
- + SPELL_LIGHTNING_ARROWS = 66083,
- + SPELL_LIGHTNING_ARROWS_AURA = 66085,
- + SPELL_MULTI_SHOT = 66081,
- + SPELL_SHOOT = 66079,
- +
- + // Lana Stouthammer && Deathstalker Visceri || Rouge
- + SPELL_EVISCERATE = 67709,
- + SPELL_FAN_OF_KNIVES = 67706,
- + SPELL_POISON_BOTTLE = 67701,
- + SPELL_DEADLY_POISON = 67711
- +};
- +
- +enum Texts
- +{
- + EMOTE_TRAMPLE = 0
- +};
- +
- +enum PointMovement
- +{
- + POINT_REMOUNT = 0,
- + POINT_DESPAWN
- +};
- +
- +void EnterAggressiveMode(Creature* temp)
- +{
- + temp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC);
- + temp->SetReactState(REACT_AGGRESSIVE);
- +}
- +
- +void DoCastPennant(Creature* me)
- +{
- + switch (me->GetEntry())
- + {
- + case NPC_MOKRA:
- + me->CastSpell(me, SPELL_PENNANT_ORGRIMMAR);
- + break;
- + case NPC_ERESSEA:
- + me->CastSpell(me, SPELL_PENNANT_SILVERMOON);
- + break;
- + case NPC_RUNOK:
- + me->CastSpell(me, SPELL_PENNANT_THUNDER_BLUFF);
- + break;
- + case NPC_ZULTORE:
- + me->CastSpell(me, SPELL_PENNANT_SEN_JIN);
- + break;
- + case NPC_VISCERI:
- + me->CastSpell(me, SPELL_PENNANT_UNDERCITY);
- + break;
- + case NPC_JACOB:
- + me->CastSpell(me, SPELL_PENNANT_STORMWIND);
- + break;
- + case NPC_AMBROSE:
- + me->CastSpell(me, SPELL_PENNANT_GNOMEREGAN);
- + break;
- + case NPC_COLOSOS:
- + me->CastSpell(me, SPELL_PENNANT_EXODAR);
- + break;
- + case NPC_JAELYNE:
- + me->CastSpell(me, SPELL_PENNANT_DARNASSUS);
- + break;
- + case NPC_LANA:
- + me->CastSpell(me, SPELL_PENNANT_IRONFORGE);
- + break;
- + default:
- + break;
- + }
- + if (me->GetVehicleBase())
- + me->CastSpell(me->GetVehicleBase(), SPELL_TRAMPLE_DUMMY_AURA, true);
- +}
- +
- +Creature* FindMyMount(Creature* me, bool newMount = false)
- +{
- + InstanceScript* instance = me->GetInstanceScript();
- + if (newMount)
- + {
- + // Summoning a new vehicle if all others are used
- + // can but should not occur
- + uint32 tmpEntry = instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE ? VEHICLE_ARGENT_BATTLEWORG_COSMETIC : VEHICLE_ARGENT_WARHORSE_COSMETIC;
- + if (Creature* mount = me->SummonCreature(tmpEntry, bossExitPos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10s))
- + {
- + if (instance->GetGuidData(DATA_GRAND_CHAMPION_1) == me->GetGUID())
- + instance->SetGuidData(DATA_GRAND_CHAMPION_VEHICLE_1, mount->GetGUID());
- + else if (instance->GetGuidData(DATA_GRAND_CHAMPION_2) == me->GetGUID())
- + instance->SetGuidData(DATA_GRAND_CHAMPION_VEHICLE_2, mount->GetGUID());
- + else if (instance->GetGuidData(DATA_GRAND_CHAMPION_3) == me->GetGUID())
- + instance->SetGuidData(DATA_GRAND_CHAMPION_VEHICLE_3, mount->GetGUID());
- + mount->SetOrientation(centerOrientation);
- + mount->SetHomePosition(me->GetHomePosition());
- + return mount;
- + }
- + }
- + if (me->GetGUID() == instance->GetGuidData(DATA_GRAND_CHAMPION_1))
- + return ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GRAND_CHAMPION_VEHICLE_1));
- + else if (me->GetGUID() == instance->GetGuidData(DATA_GRAND_CHAMPION_2))
- + return ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GRAND_CHAMPION_VEHICLE_2));
- + else if (me->GetGUID() == instance->GetGuidData(DATA_GRAND_CHAMPION_3))
- + return ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GRAND_CHAMPION_VEHICLE_3));
- +
- + // should not happen
- + return nullptr;
- +}
- +
- +// called on rider
- +void SetGrandChampionToEvadeMode(Creature* me)
- +{
- + me->RemoveAllAuras();
- + me->ApplySpellImmune(SPELL_TRAMPLE_AURA, IMMUNITY_ID, SPELL_TRAMPLE_AURA, false);
- + me->GetThreatManager().ClearAllThreat();
- + me->CombatStop(true);
- + me->SetLootRecipient(nullptr);
- + me->AI()->Reset();
- + if (Creature* mount = FindMyMount(me))
- + {
- + mount->AI()->Reset();
- + EnterAggressiveMode(mount);
- + mount->GetMotionMaster()->Clear();
- + mount->GetMotionMaster()->MoveTargetedHome();
- + }
- + DoCastPennant(me);
- + // On reset Grand Champions' flags are restored to DB values and we don't want that
- + EnterAggressiveMode(me);
- +}
- +
- +/*
- +* Generic AI for Grand Champions in ToC. *
- +* Script Complete: 100% *
- +*/
- +
- +struct boss_grand_championAI : BossAI
- +{
- + boss_grand_championAI(Creature* creature) : BossAI(creature, DATA_GRAND_CHAMPIONS)
- + {
- + LookingForMount = false;
- + MountedPhaseDone = false;
- + IsChampionDown = false;
- + bDone = false;
- + bHome = false;
- +
- + uiPhase = 0;
- + }
- + uint8 uiPhase;
- +
- + bool LookingForMount; // if is in looking for mount phase
- + bool MountedPhaseDone; // if jousting phase is done
- + bool IsChampionDown; // if champion is defeated
- + bool bDone; // if all champions have been downed
- + bool bHome; // if champion has reached home after jousing phase
- +
- + void Reset() override
- + {
- + if (MountedPhaseDone)
- + DoCastPennant(me);
- + if (IsChampionDown)
- + IsChampionDown = false;
- + _Reset();
- + }
- +
- + bool GrandChampionsOutOfVehicles()
- + {
- + for (int i = 0; i < 3; i++)
- + {
- + if (Creature* pGrandChampion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GRAND_CHAMPION_1 + i)))
- + {
- + if (pGrandChampion->GetVehicleBase())
- + return false;
- + }
- + }
- + return true;
- + }
- +
- + bool GrandChampionsDefeated()
- + {
- + for (int i = 0; i < 3; i++)
- + {
- + if (Creature* pGrandChampion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GRAND_CHAMPION_1 + i)))
- + {
- + if (!pGrandChampion->HasAura(SPELL_KNEEL))
- + return false;
- + }
- + }
- + return true;
- + }
- +
- + void AttackRandomPlayer()
- + {
- + Map::PlayerList const& players = me->GetMap()->GetPlayers();
- + if (players.isEmpty())
- + return;
- +
- + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
- + {
- + Player* plr = itr->GetSource();
- + if (plr && !plr->IsGameMaster() && plr->IsAlive())
- + {
- + for (int i = 0; i < 3; i++)
- + {
- + if (Creature* pGrandChampion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GRAND_CHAMPION_1 + i)))
- + {
- + EnterAggressiveMode(pGrandChampion);
- + if (!pGrandChampion->IsInCombat())
- + pGrandChampion->AI()->AttackStart(plr);
- + }
- + }
- + break;
- + }
- + }
- + }
- +
- + bool CanUseNormalAI()
- + {
- + // must check for unattackable flag to prevent crash in certain situations
- + return !UpdateVictim() || me->GetVehicleBase() || LookingForMount || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE) || !MountedPhaseDone;
- + }
- +
- + void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER) override
- + {
- + if (LookingForMount || !MountedPhaseDone)
- + return;
- +
- + // we must check if other champions have been downed and call evade for them
- + // for example, if players wipe during killing the last champion
- + for (int i = 0; i < 3; ++i)
- + {
- + if (Creature* pGrandChampion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GRAND_CHAMPION_1 + i)))
- + {
- + if (pGrandChampion->HasAura(SPELL_KNEEL))
- + {
- + pGrandChampion->RemoveAllAuras();
- + pGrandChampion->GetThreatManager().ClearAllThreat();
- + pGrandChampion->SetLootRecipient(nullptr);
- + pGrandChampion->SetRegenerateHealth(true);
- + pGrandChampion->GetMotionMaster()->MoveTargetedHome();
- + pGrandChampion->AI()->Reset();
- + }
- + }
- + }
- + BossAI::EnterEvadeMode(why);
- + }
- +
- + void JustReachedHome() override
- + {
- + if (bHome)
- + {
- + // Champions will be unattackable for 15 seconds when reached their homepositions for first time after jousting event
- + // After that time, they will start attacking a random player
- + // if group wipes during actual fight, grand champions will be attackable immediately when reached home position
- + uiPhase = 4;
- + events.ScheduleEvent(EVENT_START_ATTACK_REAL, 15s);
- + bHome = false;
- + }
- + else if (MountedPhaseDone && !bHome)
- + EnterAggressiveMode(me);
- + _JustReachedHome();
- + }
- +
- + void SpellHit(WorldObject* caster, SpellInfo const* spellInfo) override
- + {
- + if (spellInfo->Id == SPELL_TRAMPLE_AURA && LookingForMount && uiPhase == 0 && !me->IsImmunedToSpell(spellInfo, caster))
- + {
- + uiPhase = 3;
- + me->GetMotionMaster()->Clear();
- + me->GetMotionMaster()->MoveIdle();
- + Talk(EMOTE_TRAMPLE, me);
- + events.ScheduleEvent(EVENT_TRAMPLE, Milliseconds(spellInfo->GetDuration()));
- + }
- + }
- +
- + void MovementInform(uint32 type, uint32 id) override
- + {
- + if (type != POINT_MOTION_TYPE)
- + return;
- +
- + if (id == POINT_REMOUNT && LookingForMount)
- + {
- + // Reached point, mounting again
- + if (Creature* mount = FindMyMount(me))
- + {
- + if (!me->IsWithinDist(mount, INTERACTION_DISTANCE))
- + return;
- +
- + LookingForMount = false;
- + uiPhase = 2;
- + me->ApplySpellImmune(SPELL_TRAMPLE_AURA, IMMUNITY_ID, SPELL_TRAMPLE_AURA, true); // Champion should be immune to trample here
- + me->GetMotionMaster()->Clear();
- + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); // to prevent boss from bugging out
- + me->SetHealth(me->GetMaxHealth());
- + me->SetRegenerateHealth(true);
- + me->SetWalk(false);
- + mount->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNINTERACTIBLE);
- + // sometimes a player can trample champion right when he is about to enter in vehicle
- + // it will bug the boss and you can kill him without the need to kill others as well
- + // so we remove the stun aura just incase
- + me->RemoveAura(SPELL_TRAMPLE_AURA);
- + me->EnterVehicle(mount, SEAT_ID_0);
- +
- + // In rare scenario all players can die meanwhile one of the champions is going for new mount, and then the champion ends in a bugged state
- + // so we must check do we have alive players in the map first, else we call evade
- + bool foundPlr = false;
- + Map::PlayerList const& players = me->GetMap()->GetPlayers();
- + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
- + {
- + Player* player = itr->GetSource();
- + if (player && !player->IsGameMaster() && player->IsAlive())
- + {
- + foundPlr = true;
- + break;
- + }
- + }
- + if (foundPlr)
- + events.ScheduleEvent(EVENT_START_ATTACK_JOUST, 2s); // slight delay before attacking
- + else
- + SetGrandChampionToEvadeMode(me);
- + }
- + }
- + else if (id == POINT_DESPAWN)
- + me->DisappearAndDie();
- + }
- +
- + void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
- + {
- + if (damage >= me->GetHealth() && me->GetVehicleBase())
- + {
- + damage = 0;
- + LookingForMount = true;
- + uiPhase = 1;
- + me->ApplySpellImmune(SPELL_TRAMPLE_AURA, IMMUNITY_ID, SPELL_TRAMPLE_AURA, true); // Champion should be immune to trample here
- + me->ExitVehicle();
- + me->RemoveAllAuras();
- + DoCastPennant(me);
- + me->SetReactState(REACT_PASSIVE);
- + me->SetHealth(1);
- + me->CombatStop(true);
- + me->SetRegenerateHealth(false); // we don't regen health yet
- + me->GetMotionMaster()->MoveIdle();
- + me->SetWalk(true);
- + // Champion's current vehicle runs to the gates and despawns
- + // Champion will search for new mount
- + if (Creature* mount = FindMyMount(me))
- + {
- + mount->GetMotionMaster()->Clear();
- + mount->SetWalk(false);
- + mount->SetReactState(REACT_PASSIVE);
- + mount->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- +
- + uint32 newMountEntry = instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE ? VEHICLE_ARGENT_BATTLEWORG_COSMETIC : VEHICLE_ARGENT_WARHORSE_COSMETIC;
- + Creature* newMount = nullptr;
- + float dist = 0.0f;
- + std::list<Creature*> tempList;
- +
- + Trinity::AllCreaturesOfEntryInRange check(me, newMountEntry, 100);
- + Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(me, tempList, check);
- + Cell::VisitGridObjects(me, searcher, me->GetGridActivationRange());
- +
- + for (std::list<Creature*>::const_iterator itr = tempList.begin(); itr != tempList.end(); ++itr)
- + {
- + Creature* tmpMount = *itr;
- +
- + if (instance->GetGuidData(DATA_GRAND_CHAMPION_VEHICLE_1) == tmpMount->GetGUID() ||
- + instance->GetGuidData(DATA_GRAND_CHAMPION_VEHICLE_2) == tmpMount->GetGUID() ||
- + instance->GetGuidData(DATA_GRAND_CHAMPION_VEHICLE_3) == tmpMount->GetGUID())
- + continue;
- +
- + if (!tmpMount->IsAlive())
- + continue;
- +
- + if (dist == 0)
- + {
- + dist = me->GetDistance(tmpMount);
- + newMount = tmpMount;
- + }
- +
- + if (me->GetDistance(tmpMount) < dist)
- + {
- + dist = me->GetDistance(tmpMount);
- + newMount = tmpMount;
- + }
- + }
- + if (newMount)
- + {
- + if (instance->GetGuidData(DATA_GRAND_CHAMPION_1) == me->GetGUID())
- + instance->SetGuidData(DATA_GRAND_CHAMPION_VEHICLE_1, newMount->GetGUID());
- + else if (instance->GetGuidData(DATA_GRAND_CHAMPION_2) == me->GetGUID())
- + instance->SetGuidData(DATA_GRAND_CHAMPION_VEHICLE_2, newMount->GetGUID());
- + else if (instance->GetGuidData(DATA_GRAND_CHAMPION_3) == me->GetGUID())
- + instance->SetGuidData(DATA_GRAND_CHAMPION_VEHICLE_3, newMount->GetGUID());
- + newMount->SetHomePosition(mount->GetHomePosition());
- + }
- + else
- + {
- + // Summoning a new mount for Grand Champion if every other mount have been used
- + (void)FindMyMount(me, true);
- + }
- +
- + // Defeated mount runs towards the center of arena and disappears
- + if (Creature* announcer = instance->GetCreature(DATA_ANNOUNCER))
- + {
- + mount->GetMotionMaster()->Clear();
- + mount->GetMotionMaster()->MovePoint(1, announcer->GetHomePosition());
- + }
- + }
- + events.ScheduleEvent(EVENT_WALK_TO_MOUNT, 3s); // slight delay before we go for new mount
- + return;
- + }
- + else if (damage >= me->GetHealth() && LookingForMount)
- + {
- + damage = 0;
- + return;
- + }
- + else if (damage >= me->GetHealth() && MountedPhaseDone)
- + {
- + damage = 0;
- + if (!IsChampionDown)
- + {
- + IsChampionDown = true;
- + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- + me->SetReactState(REACT_PASSIVE);
- + me->SetHealth(1);
- + me->CombatStop(true);
- + me->SetRegenerateHealth(false);
- + me->GetMotionMaster()->MoveIdle();
- + me->RemoveAura(SPELL_EARTH_SHIELD);
- + me->RemoveAura(SPELL_HASTE);
- + me->RemoveAura(SPELL_LIGHTNING_ARROWS_AURA);
- + me->RemoveAura(SPELL_BLADESTORM);
- + me->CastSpell(me, SPELL_KNEEL, true);
- + }
- + return;
- + }
- + else if (bDone)
- + {
- + damage = 0;
- + return;
- + }
- + }
- +
- + void JustEngagedWith(Unit* who) override
- + {
- + //if (MountedPhaseDone)
- + //{
- + // All champions should attack together
- + for (int i = 0; i < 3; i++)
- + {
- + Creature* pGrandChampion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GRAND_CHAMPION_1 + i));
- + if (pGrandChampion && !pGrandChampion->HasAura(SPELL_KNEEL) && !pGrandChampion->IsInCombat())
- + pGrandChampion->AI()->AttackStart(who);
- + }
- + _JustEngagedWith(who);
- + //}
- + }
- +
- + void AttackStart(Unit* who) override
- + {
- + if (LookingForMount || uiPhase != 0)
- + return;
- + if (Creature* mount = FindMyMount(me))
- + mount->AI()->AttackStart(who);
- + BossAI::AttackStart(who);
- + }
- +
- + void UpdateAI(uint32 diff) override
- + {
- + events.Update(diff);
- +
- + while (uint32 eventId = events.ExecuteEvent())
- + {
- + switch (eventId)
- + {
- + case EVENT_WALK_TO_MOUNT:
- + // Starts walking for mount
- + if (!LookingForMount)
- + break;
- + me->ApplySpellImmune(SPELL_TRAMPLE_AURA, IMMUNITY_ID, SPELL_TRAMPLE_AURA, false);
- + // Sometimes boss can bug out after being thrown down from mount and reset flags to DB values
- + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC);
- + me->GetMotionMaster()->Clear();
- + if (Creature* mount = FindMyMount(me))
- + me->GetMotionMaster()->MovePoint(POINT_REMOUNT, mount->GetPosition());
- + break;
- + case EVENT_START_ATTACK_JOUST:
- + {
- + // We're mounted and preparing to attack
- + if (Creature* mount = FindMyMount(me))
- + {
- + me->ApplySpellImmune(SPELL_TRAMPLE_AURA, IMMUNITY_ID, SPELL_TRAMPLE_AURA, false);
- + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNINTERACTIBLE);
- + DoCastPennant(me);
- + EnterAggressiveMode(me);
- + EnterAggressiveMode(mount);
- + bool foundPlr = false;
- + Map::PlayerList const& players = me->GetMap()->GetPlayers();
- + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
- + {
- + Player* player = itr->GetSource();
- + if (player && !player->IsGameMaster() && player->IsAlive())
- + {
- + if (player->GetVehicleBase())
- + mount->AI()->AttackStart(player->GetVehicleBase());
- + else
- + mount->AI()->AttackStart(player);
- + foundPlr = true;
- + break;
- + }
- + }
- + if (!foundPlr)
- + SetGrandChampionToEvadeMode(me);
- + }
- + break;
- + }
- + case EVENT_TRAMPLE:
- + // Got trampled and continuing walking
- + me->GetMotionMaster()->Clear();
- + if (Creature* mount = FindMyMount(me))
- + me->GetMotionMaster()->MovePoint(0, mount->GetPosition());
- + break;
- + case EVENT_EVADE_MODE:
- + // Entering to evade mode after jousting event is done
- + bHome = true;
- + EnterEvadeMode();
- + break;
- + case EVENT_START_ATTACK_REAL:
- + // Searches an enemy to attack after waited a while after jousting event
- + AttackRandomPlayer();
- + break;
- + case EVENT_DESPAWN:
- + // Despawning
- + _JustDied();
- + me->RemoveAura(SPELL_KNEEL);
- + instance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_ACHIEVEMENT_CREDIT, 0, me);
- + me->SetWalk(true);
- + me->GetMotionMaster()->MovePoint(POINT_DESPAWN, bossExitPos);
- + break;
- + default:
- + break;
- + }
- + uiPhase = 0;
- + }
- +
- + if (!MountedPhaseDone && GrandChampionsOutOfVehicles())
- + {
- + // Champions have been defeated in jousting event
- + MountedPhaseDone = true;
- + if (me->GetGUID() == instance->GetGuidData(DATA_GRAND_CHAMPION_1))
- + me->SetHomePosition(739.678f, 660.975f, 412.393f, 4.49f);
- + else if (me->GetGUID() == instance->GetGuidData(DATA_GRAND_CHAMPION_2))
- + me->SetHomePosition(746.71f, 661.02f, 411.69f, 4.6f);
- + else if (me->GetGUID() == instance->GetGuidData(DATA_GRAND_CHAMPION_3))
- + me->SetHomePosition(754.34f, 660.70f, 412.39f, 4.79f);
- +
- + if (Creature* mount = FindMyMount(me))
- + mount->DisappearAndDie();
- +
- + LookingForMount = false;
- + me->ApplySpellImmune(SPELL_TRAMPLE_AURA, IMMUNITY_ID, SPELL_TRAMPLE_AURA, false);
- + me->GetMotionMaster()->MoveIdle();
- + me->GetMotionMaster()->Clear();
- + me->SetRegenerateHealth(true);
- + instance->SetData(DATA_REMOVE_VEHICLES, 0);
- + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- + uiPhase = 5;
- + events.ScheduleEvent(EVENT_EVADE_MODE, 2s); // minor delay before entering to evade mode to correct movement
- + }
- +
- + if (!bDone && GrandChampionsDefeated())
- + {
- + // Grand Champions encounter is now over
- + bDone = true;
- + uiPhase = 6;
- + events.ScheduleEvent(EVENT_DESPAWN, 2s); // minor delay before giving loot chest
- + }
- + }
- +};
- +
- +/*
- +* Generic AI for vehicles used by npcs in ToC. *
- +* Code requires cleanup and vehicles some improvement *
- +* Script Complete: 95%. *
- +*/
- +
- +class generic_vehicleAI_toc5 : public CreatureScript
- +{
- +public:
- + generic_vehicleAI_toc5() : CreatureScript("generic_vehicleAI_toc5") {}
- +
- + struct generic_vehicleAI_toc5AI : public EscortAI
- + {
- + generic_vehicleAI_toc5AI(Creature* creature) : EscortAI(creature)
- + {
- + Initialize();
- + SetDespawnAtEnd(false);
- + uiWaypointPath = 0;
- +
- + instance = creature->GetInstanceScript();
- + }
- +
- + void Initialize()
- + {
- + castedPennant = false;
- + events.ScheduleEvent(EVENT_BUFF_FLAG, 2s);
- + events.ScheduleEvent(EVENT_BUFF_SHIELD, 5s);
- + events.ScheduleEvent(EVENT_MOUNT_CHARGE, 5s);
- + events.ScheduleEvent(EVENT_SHIELD_BREAKER, 8s);
- + }
- +
- + InstanceScript* instance;
- +
- + EventMap events;
- +
- + bool castedPennant;
- + uint32 uiWaypointPath;
- +
- + void Reset() override
- + {
- + events.Reset();
- + Initialize();
- + }
- +
- + bool IsGrandChampionVehicle()
- + {
- + if (instance->GetGuidData(DATA_GRAND_CHAMPION_VEHICLE_1) == me->GetGUID() ||
- + instance->GetGuidData(DATA_GRAND_CHAMPION_VEHICLE_2) == me->GetGUID() ||
- + instance->GetGuidData(DATA_GRAND_CHAMPION_VEHICLE_3) == me->GetGUID())
- + return true;
- + return false;
- + }
- +
- + bool IsLesserChampion()
- + {
- + switch (me->GetEntry())
- + {
- + case NPC_DARNASSUS_CHAMPION:
- + case NPC_EXODAR_CHAMPION:
- + case NPC_STORMWIND_CHAMPION:
- + case NPC_GNOMEREGAN_CHAMPION:
- + case NPC_IRONFORGE_CHAMPION:
- + case NPC_UNDERCITY_CHAMPION:
- + case NPC_THUNDER_BLUFF_CHAMPION:
- + case NPC_ORGRIMMAR_CHAMPION:
- + case NPC_SILVERMOON_CHAMPION:
- + case NPC_SEN_JIN_CHAMPION:
- + return true;
- + }
- + return false;
- + }
- +
- + void SetData(uint32 uiType, uint32 uiData) override
- + {
- + switch (uiType)
- + {
- + case DATA_GENERATE_WAYPOINTS_FOR_BOSS_1:
- + if (uiData == HORDE)
- + {
- + AddWaypoint(0, 747.35f, 634.07f, 411.57f);
- + AddWaypoint(1, 780.43f, 607.15f, 411.82f);
- + AddWaypoint(2, 785.99f, 599.41f, 411.92f);
- + AddWaypoint(3, GrandChampFinalLoc[3].GetPositionX(), GrandChampFinalLoc[3].GetPositionY(), GrandChampFinalLoc[3].GetPositionZ());
- + }
- + else if (uiData == ALLIANCE)
- + {
- + AddWaypoint(0, 747.35f, 634.07f, 411.57f);
- + AddWaypoint(1, 700.39f, 618.73f, 412.39f);
- + AddWaypoint(2, 703.59f, 618.48f, 411.92f);
- + AddWaypoint(3, GrandChampFinalLoc[0].GetPositionX(), GrandChampFinalLoc[0].GetPositionY(), GrandChampFinalLoc[0].GetPositionZ());
- + }
- + uiWaypointPath = WAYPOINT_MAP_BOSS_1;
- + break;
- + case DATA_GENERATE_WAYPOINTS_FOR_BOSS_2:
- + if (uiData == HORDE)
- + {
- + AddWaypoint(0, 747.35f, 634.07f, 411.57f);
- + AddWaypoint(1, 792.36f, 614.47f, 412.39f);
- + AddWaypoint(2, GrandChampFinalLoc[4].GetPositionX(), GrandChampFinalLoc[4].GetPositionY(), GrandChampFinalLoc[4].GetPositionZ());
- + }
- + else if (uiData == ALLIANCE)
- + {
- + AddWaypoint(0, 747.35f, 634.07f, 411.57f);
- + AddWaypoint(1, 708.31f, 635.07f, 411.93f);
- + AddWaypoint(2, GrandChampFinalLoc[1].GetPositionX(), GrandChampFinalLoc[1].GetPositionY(), GrandChampFinalLoc[1].GetPositionZ());
- + }
- + uiWaypointPath = WAYPOINT_MAP_BOSS_2;
- + break;
- + case DATA_GENERATE_WAYPOINTS_FOR_BOSS_3:
- + if (uiData == HORDE)
- + {
- + AddWaypoint(0, 747.35f, 634.07f, 411.57f);
- + AddWaypoint(1, 793.00f, 624.40f, 412.39f);
- + AddWaypoint(2, GrandChampFinalLoc[5].GetPositionX(), GrandChampFinalLoc[5].GetPositionY(), GrandChampFinalLoc[5].GetPositionZ());
- + }
- + else if (uiData == ALLIANCE)
- + {
- + AddWaypoint(0, 747.35f, 634.07f, 411.57f);
- + AddWaypoint(1, 716.67f, 651.1f, 411.93f);
- + AddWaypoint(2, GrandChampFinalLoc[2].GetPositionX(), GrandChampFinalLoc[2].GetPositionY(), GrandChampFinalLoc[2].GetPositionZ());
- + }
- + uiWaypointPath = WAYPOINT_MAP_BOSS_3;
- + break;
- + case DATA_GENERATE_WAYPOINTS_FOR_ADDS:
- + me->SetWalk(true);
- + me->GetMotionMaster()->MovePoint(1, LesserChampLoc[uiData]);
- + uiWaypointPath = WAYPOINT_MAP_ADDS;
- + break;
- + }
- +
- + if (uiType <= DATA_GENERATE_WAYPOINTS_FOR_BOSS_3)
- + Start(false, true); // Grand Champions run to their positions
- + }
- +
- + void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER) override
- + {
- + // Evade is handled in UpdateAI for Grand Champions' vehicles
- + // "Cosmetic" vehicles are no longer grand champions' vehicles when champions are
- + // already walking to new mount, therefore they enter into evade mode instead of despawning
- + if (IsGrandChampionVehicle() ||
- + me->GetEntry() == VEHICLE_ARGENT_BATTLEWORG_COSMETIC ||
- + me->GetEntry() == VEHICLE_ARGENT_WARHORSE_COSMETIC)
- + return;
- +
- + EscortAI::EnterEvadeMode(why);
- + }
- +
- + void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
- + {
- + uint32 TeamInInstance = instance->GetData(DATA_TEAM_IN_INSTANCE);
- + // Grand Champions reached their final positions in the jousting event
- + // and Lesser Champions begin to correct their positions
- + if ((uiWaypointPath == WAYPOINT_MAP_BOSS_1 && waypointId == 3) || ((uiWaypointPath == WAYPOINT_MAP_BOSS_2 || uiWaypointPath == WAYPOINT_MAP_BOSS_3) && waypointId == 2))
- + {
- + if (Creature* herald = instance->GetCreature(DATA_ANNOUNCER))
- + {
- + if (TeamInInstance == ALLIANCE)
- + me->SetFacingTo(hordeOrientation);
- + else
- + me->SetFacingTo(allianceOrientation);
- + me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), TeamInInstance == ALLIANCE ? hordeOrientation : allianceOrientation);
- + if (me->GetVehicleKit() && me->GetVehicleKit()->GetPassenger(SEAT_ID_0) && me->GetVehicleKit()->GetPassenger(SEAT_ID_0)->ToCreature())
- + me->GetVehicleKit()->GetPassenger(SEAT_ID_0)->ToCreature()->SetHomePosition(me->GetPosition());
- + herald->AI()->SetData(DATA_LESSER_CHAMPIONS_PREPARE, uiWaypointPath);
- + }
- + }
- + // Grand Champions run from gates into the arena and then walk towards their waiting positions
- + else if (uiWaypointPath < WAYPOINT_MAP_ADDS && waypointId == 0)
- + me->SetWalk(true);
- + }
- +
- + void MovementInform(uint32 type, uint32 pointId) override
- + {
- + EscortAI::MovementInform(type, pointId);
- +
- + if (type != POINT_MOTION_TYPE)
- + return;
- +
- + // Lesser Champions correct their orientation
- + if (pointId == 1 && uiWaypointPath == WAYPOINT_MAP_ADDS)
- + {
- + uint32 TeamInInstance = instance->GetData(DATA_TEAM_IN_INSTANCE);
- + if (TeamInInstance == ALLIANCE)
- + me->SetFacingTo(hordeOrientation);
- + else
- + me->SetFacingTo(allianceOrientation);
- + me->SetWalk(false);
- + me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), TeamInInstance == ALLIANCE ? hordeOrientation : allianceOrientation);
- + }
- +
- + // Grand Champions' old mount will despawn when it has run to the center of arena
- + if (pointId == 1 && me->GetVehicleKit() && !me->GetVehicleKit()->GetPassenger(SEAT_ID_0))
- + me->DisappearAndDie();
- + }
- +
- + void JustDied(Unit* /*killer*/) override
- + {
- + if (IsLesserChampion())
- + {
- + me->Dismount();
- + if (Creature* herald = instance->GetCreature(DATA_ANNOUNCER))
- + herald->AI()->SetData(DATA_LESSER_CHAMPIONS_DEFEATED, 0);
- + }
- + }
- +
- + void DoCastShield()
- + {
- + if (IsGrandChampionVehicle())
- + {
- + if (me->GetVehicleKit())
- + if (Unit* rider = me->GetVehicleKit()->GetPassenger(SEAT_ID_0))
- + rider->CastSpell(rider, SPELL_SHIELD_GRAND_CHAMP, true);
- + }
- + else if (IsLesserChampion())
- + DoCast(me, SPELL_SHIELD_LESSER_CHAMP, true);
- + }
- +
- + void AttackStart(Unit* target) override
- + {
- + if (IsGrandChampionVehicle())
- + {
- + if (!(me->GetVehicleKit() && me->GetVehicleKit()->GetPassenger(SEAT_ID_0)))
- + return;
- +
- + if (me->HasUnitState(UNIT_STATE_MELEE_ATTACKING))
- + me->AttackStop();
- +
- + me->GetMotionMaster()->MoveFollow(target, 0, 0);
- + }
- + else if (IsLesserChampion())
- + ScriptedAI::AttackStart(target);
- + }
- +
- + // returns true if we are in combat and we have a victim
- + // returns false if we have no victim, and enters grand champion to evade mode
- + bool CheckCombat()
- + {
- + if (IsGrandChampionVehicle())
- + {
- + if (!me->GetVehicleKit())
- + return false;
- +
- + Unit* rider = me->GetVehicleKit()->GetPassenger(SEAT_ID_0);
- + if (!rider)
- + return false;
- +
- + if (!rider->IsInCombat())
- + return false;
- +
- + if ((rider->ToCreature() && !rider->ToCreature()->HasReactState(REACT_PASSIVE)) && !me->HasReactState(REACT_PASSIVE))
- + {
- + if (rider->GetVictim() == nullptr)
- + {
- + SetGrandChampionToEvadeMode(rider->ToCreature());
- + return false;
- + }
- + }
- + else if (rider->GetThreatManager().IsThreatListEmpty())
- + {
- + SetGrandChampionToEvadeMode(rider->ToCreature());
- + return false;
- + }
- + }
- + else if (!UpdateVictim())
- + return false;
- + return true;
- + }
- +
- + void UpdateAI(uint32 uiDiff) override
- + {
- + EscortAI::UpdateAI(uiDiff);
- + events.Update(uiDiff);
- +
- + while (uint32 eventId = events.ExecuteEvent())
- + {
- + switch (eventId)
- + {
- + case EVENT_BUFF_SHIELD:
- + DoCastShield();
- + events.ScheduleEvent(EVENT_BUFF_SHIELD, 7s);
- + break;
- + case EVENT_BUFF_FLAG:
- + if (IsGrandChampionVehicle())
- + {
- + if (!castedPennant)
- + {
- + if (me->GetVehicleKit() && me->GetVehicleKit()->GetPassenger(SEAT_ID_0) && me->GetVehicleKit()->GetPassenger(SEAT_ID_0)->ToCreature())
- + DoCastPennant(me->GetVehicleKit()->GetPassenger(SEAT_ID_0)->ToCreature());
- + castedPennant = true;
- + }
- + }
- + break;
- + case EVENT_MOUNT_CHARGE:
- + {
- + if (CheckCombat())
- + {
- + // Charge is casted on random player
- + // Champions' threatlist is reseted when using charge
- + Map::PlayerList const& pList = me->GetMap()->GetPlayers();
- + // Player list is always in the same order so we must "randomize" it
- + if (!pList.isEmpty())
- + {
- + uint32 rand = urand(0, pList.getSize() - 1);
- + for (Map::PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr)
- + {
- + if (rand == 0)
- + {
- + Player* plr = itr->GetSource();
- + if (plr && !plr->IsGameMaster() && plr->IsAlive() && me->IsInRange(plr, 8.0f, 25.0f, false))
- + {
- + uint32 spell_charge = IsGrandChampionVehicle() ? SPELL_CHARGE_GRAND_CHAMP : SPELL_CHARGE_LESSER_CHAMP;
- + if (IsGrandChampionVehicle())
- + {
- + if (me->GetVehicleKit() && me->GetVehicleKit()->GetPassenger(SEAT_ID_0))
- + {
- + if (Creature* rider = me->GetVehicleKit()->GetPassenger(SEAT_ID_0)->ToCreature())
- + {
- + // Grand Champion
- + // Resetting rider's threat (DoResetThreat() cannot be used on external unit)
- + rider->GetThreatManager().ResetAllThreat();
- + // Setting gaze on the new player
- + if (plr->GetVehicleBase())
- + AddThreat(plr->GetVehicleBase(), 100000.0f);
- + else
- + AddThreat(plr, 100000.0f);
- + // Casting actual charge
- + if (plr->GetVehicleBase())
- + rider->CastSpell(plr->GetVehicleBase(), spell_charge);
- + else
- + rider->CastSpell(plr, spell_charge);
- + me->GetMotionMaster()->MoveCharge(plr->GetPositionX(), plr->GetPositionY(), plr->GetPositionZ());
- + }
- + }
- + }
- + else
- + {
- + // Lesser Champion
- + // Resetting threat
- + ResetThreatList();
- + // Setting gaze on the new player
- + if (plr->GetVehicleBase())
- + AddThreat(plr->GetVehicleBase(), 100000.0f);
- + else
- + AddThreat(plr, 100000.0f);
- + // Casting actual charge
- + if (plr->GetVehicleBase())
- + DoCast(plr->GetVehicleBase(), spell_charge);
- + else
- + DoCast(plr, spell_charge);
- + }
- + break;
- + }
- + else
- + continue;
- + }
- + else
- + --rand;
- + }
- + }
- + }
- + events.ScheduleEvent(EVENT_MOUNT_CHARGE, 7s);
- + break;
- + }
- + case EVENT_SHIELD_BREAKER:
- + // Lesser Champions don't use Shield Breaker
- + if (IsGrandChampionVehicle() && me->GetVehicleKit())
- + {
- + if (CheckCombat())
- + {
- + if (Unit* rider = me->GetVehicleKit()->GetPassenger(SEAT_ID_0))
- + {
- + if (Unit* victim = rider->GetVictim())
- + {
- + if (rider->IsInRange(victim, 5.0f, 30.0f, false))
- + rider->CastSpell(victim, SPELL_SHIELD_BREAKER);
- + }
- + }
- + }
- + events.ScheduleEvent(EVENT_SHIELD_BREAKER, 4s);
- + }
- + break;
- + default:
- + break;
- + }
- + }
- +
- + if (!CheckCombat())
- + return;
- +
- + DoMeleeAttackIfReady();
- + }
- + };
- +
- + CreatureAI* GetAI(Creature* creature) const override
- + {
- + return GetTrialOfChampionAI<generic_vehicleAI_toc5AI>(creature);
- + }
- +};
- +
- +class boss_warrior_toc5 : public CreatureScript
- +{
- +public:
- + boss_warrior_toc5() : CreatureScript("boss_warrior_toc5") {}
- +
- + // Marshal Jacob Alerius && Mokra the Skullcrusher || Warrior
- + struct boss_warrior_toc5AI : public boss_grand_championAI
- + {
- + boss_warrior_toc5AI(Creature* creature) : boss_grand_championAI(creature) {}
- +
- + void Reset() override
- + {
- + boss_grand_championAI::Reset();
- + }
- +
- + void JustEngagedWith(Unit* who) override
- + {
- + events.ScheduleEvent(EVENT_BLADESTORM, randtime(15s, 20s));
- + events.ScheduleEvent(EVENT_INTERCEPT, 7s);
- + events.ScheduleEvent(EVENT_MORTAL_STRIKE, randtime(8s, 12s));
- + events.ScheduleEvent(EVENT_ROLLING_THROW, 30s);
- + boss_grand_championAI::JustEngagedWith(who);
- + }
- +
- + void UpdateAI(uint32 uiDiff) override
- + {
- + boss_grand_championAI::UpdateAI(uiDiff);
- +
- + if (CanUseNormalAI())
- + {
- + if (UpdateVictim())
- + DoMeleeAttackIfReady();
- + return;
- + }
- +
- + if (me->HasUnitState(UNIT_STATE_CASTING))
- + return;
- +
- + while (uint32 eventId = events.ExecuteEvent())
- + {
- + switch (eventId)
- + {
- + case EVENT_INTERCEPT:
- + {
- + if (!me->HasAura(SPELL_BLADESTORM))
- + {
- + Map::PlayerList const& pList = me->GetMap()->GetPlayers();
- + // Player list is always in the same order so we must "randomize" it
- + if (!pList.isEmpty())
- + {
- + uint32 rand = urand(0, pList.getSize() - 1);
- + for (Map::PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr)
- + {
- + if (rand == 0)
- + {
- + Player* plr = itr->GetSource();
- + if (plr && !plr->IsGameMaster() && plr->IsAlive() && me->IsInRange(plr, 8.0f, 25.0f, false))
- + {
- + ResetThreatList();
- + DoCast(plr, SPELL_INTERCEPT);
- + AddThreat(plr, 5.0f);
- + break;
- + }
- + else
- + continue;
- + }
- + else
- + --rand;
- + }
- + }
- + }
- + events.ScheduleEvent(EVENT_INTERCEPT, 7s);
- + break;
- + }
- + case EVENT_BLADESTORM:
- + DoCastVictim(SPELL_BLADESTORM);
- + events.ScheduleEvent(EVENT_BLADESTORM, randtime(15s, 20s));
- + break;
- + case EVENT_MORTAL_STRIKE:
- + if (!me->HasAura(SPELL_BLADESTORM))
- + DoCastVictim(SPELL_MORTAL_STRIKE);
- + events.ScheduleEvent(EVENT_MORTAL_STRIKE, randtime(8s, 12s));
- + break;
- + case EVENT_ROLLING_THROW:
- + // TODO: FIXME
- + // currently hackfixed at Spell::EffectLeapBack in SpellEffects.cpp
- + // without hackfix caster jumps forward, when caster should jump backwards and player jump forwards
- + if (!me->HasAura(SPELL_BLADESTORM))
- + DoCastVictim(SPELL_ROLLING_THROW);
- + events.ScheduleEvent(EVENT_ROLLING_THROW, 30s);
- + break;
- + default:
- + break;
- + }
- + }
- + DoMeleeAttackIfReady();
- + }
- + };
- +
- + CreatureAI* GetAI(Creature* creature) const override
- + {
- + return GetTrialOfChampionAI<boss_warrior_toc5AI>(creature);
- + }
- +};
- +
- +class boss_mage_toc5 : public CreatureScript
- +{
- +public:
- + boss_mage_toc5() : CreatureScript("boss_mage_toc5") {}
- +
- + // Ambrose Boltspark && Eressea Dawnsinger || Mage
- + struct boss_mage_toc5AI : public boss_grand_championAI
- + {
- + boss_mage_toc5AI(Creature* creature) : boss_grand_championAI(creature) {}
- +
- + void Reset() override
- + {
- + boss_grand_championAI::Reset();
- + }
- +
- + void JustEngagedWith(Unit* who) override
- + {
- + events.ScheduleEvent(EVENT_FIREBALL, 2s);
- + events.ScheduleEvent(EVENT_POLYMORPH, 8s);
- + events.ScheduleEvent(EVENT_BLASTWAVE, 12s);
- + events.ScheduleEvent(EVENT_HASTE, 22s);
- + boss_grand_championAI::JustEngagedWith(who);
- + }
- +
- + void AttackStart(Unit* who) override
- + {
- + me->GetMotionMaster()->MoveChase(who, 20.0f);
- + boss_grand_championAI::AttackStart(who);
- + }
- +
- + void UpdateAI(uint32 uiDiff) override
- + {
- + boss_grand_championAI::UpdateAI(uiDiff);
- +
- + if (CanUseNormalAI())
- + {
- + if (UpdateVictim())
- + DoMeleeAttackIfReady();
- + return;
- + }
- +
- + while (uint32 eventId = events.ExecuteEvent())
- + {
- + switch (eventId)
- + {
- + case EVENT_POLYMORPH:
- + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 30.0f, true))
- + {
- + DoCast(target, SPELL_POLYMORPH);
- + if (me->HasAura(SPELL_HASTE))
- + events.ScheduleEvent(EVENT_FIREBALL, 2s);
- + else
- + events.ScheduleEvent(EVENT_FIREBALL, 3s);
- + }
- + events.ScheduleEvent(EVENT_POLYMORPH, 8s);
- + break;
- + case EVENT_BLASTWAVE:
- + if (Unit* target = SelectTarget(SelectTargetMethod::MinDistance, 0))
- + {
- + if (me->IsWithinDist(target, 5.0f, false))
- + {
- + me->InterruptNonMeleeSpells(true);
- + DoCastAOE(SPELL_BLAST_WAVE);
- + events.ScheduleEvent(EVENT_FIREBALL, 1500ms);
- + }
- + }
- + events.ScheduleEvent(EVENT_BLASTWAVE, 13s);
- + break;
- + case EVENT_HASTE:
- + me->InterruptNonMeleeSpells(true);
- + DoCast(me, SPELL_HASTE);
- + events.ScheduleEvent(EVENT_FIREBALL, 1500ms);
- + events.ScheduleEvent(EVENT_HASTE, 22s);
- + break;
- + case EVENT_FIREBALL:
- + DoCastVictim(SPELL_FIREBALL);
- + if (me->HasAura(SPELL_HASTE))
- + events.ScheduleEvent(EVENT_FIREBALL, 3s);
- + else
- + events.ScheduleEvent(EVENT_FIREBALL, 4s);
- + break;
- + default:
- + break;
- + }
- + }
- + if ((100.f * me->GetPower(POWER_MANA) / me->GetMaxPower(POWER_MANA)) <= 1)
- + DoMeleeAttackIfReady();
- + }
- + };
- +
- + CreatureAI* GetAI(Creature* creature) const override
- + {
- + return GetTrialOfChampionAI<boss_mage_toc5AI>(creature);
- + }
- +};
- +
- +class boss_shaman_toc5 : public CreatureScript
- +{
- +public:
- + boss_shaman_toc5() : CreatureScript("boss_shaman_toc5") {}
- +
- + // Colosos && Runok Wildmane || Shaman
- + struct boss_shaman_toc5AI : public boss_grand_championAI
- + {
- + boss_shaman_toc5AI(Creature* creature) : boss_grand_championAI(creature)
- + {
- + Initialize();
- + }
- +
- + void Initialize()
- + {
- + earthShieldTarget.Clear();
- + isDefensive = false;
- + }
- + ObjectGuid earthShieldTarget;
- + // If shaman's friend or himself goes below 25% HP, he will go into defensive mode,
- + // casting healing spells only
- + bool isDefensive;
- +
- + void Reset() override
- + {
- + Initialize();
- + boss_grand_championAI::Reset();
- + }
- +
- + void JustEngagedWith(Unit* who) override
- + {
- + events.ScheduleEvent(EVENT_DEF_CHECK, 5s);
- + events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 16s);
- + events.ScheduleEvent(EVENT_HEALING_WAVE, 12s);
- + events.ScheduleEvent(EVENT_EARTH_SHIELD, 5s);
- + events.ScheduleEvent(EVENT_HEX_MENDING, 7s);
- + boss_grand_championAI::JustEngagedWith(who);
- + }
- +
- + void EnterCombatMode(bool interrupt)
- + {
- + if (interrupt)
- + me->InterruptNonMeleeSpells(true);
- + isDefensive = false;
- + events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 1s);
- + }
- +
- + void EnterDefensiveMode()
- + {
- + me->InterruptNonMeleeSpells(true);
- + isDefensive = true;
- + events.ScheduleEvent(EVENT_EARTH_SHIELD, 1s);
- + events.ScheduleEvent(EVENT_HEALING_WAVE, 1500ms);
- + }
- +
- + Unit* FindChampionWithLowestHp(float range)
- + {
- + // DoSelectLowestHpFriendly does not work correctly in this fight
- + // We look for champion with the lowest percentage health left
- + // ignoring champions with full hp or with kneel state (= defeated)
- + // and champions who are more than 40 yards away from me (max range of healing spells)
- + Unit* lowChampion = nullptr;
- + Creature* pGrandChampion1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GRAND_CHAMPION_1));
- + Creature* pGrandChampion2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GRAND_CHAMPION_2));
- + Creature* pGrandChampion3 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GRAND_CHAMPION_3));
- + if (pGrandChampion1 && pGrandChampion2 && pGrandChampion3)
- + {
- + if (!pGrandChampion1->HasAura(SPELL_KNEEL) && pGrandChampion1->GetHealthPct() < 100 && me->IsWithinDist(pGrandChampion1, range))
- + lowChampion = pGrandChampion1;
- + if (!pGrandChampion2->HasAura(SPELL_KNEEL) && pGrandChampion2->GetHealthPct() < 100 && me->IsWithinDist(pGrandChampion2, range))
- + {
- + if (lowChampion)
- + {
- + if (lowChampion->GetHealthPct() > pGrandChampion2->GetHealthPct())
- + lowChampion = pGrandChampion2;
- + }
- + else
- + lowChampion = pGrandChampion2;
- + }
- + if (!pGrandChampion3->HasAura(SPELL_KNEEL) && pGrandChampion3->GetHealthPct() < 100 && me->IsWithinDist(pGrandChampion3, range))
- + {
- + if (lowChampion)
- + {
- + if (lowChampion->GetHealthPct() > pGrandChampion3->GetHealthPct())
- + lowChampion = pGrandChampion3;
- + }
- + else
- + lowChampion = pGrandChampion3;
- + }
- + }
- + // can return NULL if other champions are over 40 yards away and we're in full hp
- + // or if one champion has been defeated and two are in full hp
- + // or we are last man standing with full hp
- + return lowChampion;
- + }
- +
- + void UpdateAI(uint32 uiDiff) override
- + {
- + boss_grand_championAI::UpdateAI(uiDiff);
- +
- + if (CanUseNormalAI())
- + {
- + if (UpdateVictim())
- + DoMeleeAttackIfReady();
- + return;
- + }
- +
- + while (uint32 eventId = events.ExecuteEvent())
- + {
- + switch (eventId)
- + {
- + case EVENT_DEF_CHECK:
- + if (!isDefensive)
- + {
- + Unit* pFriend = FindChampionWithLowestHp(40.0f);
- + if (pFriend && pFriend->GetHealthPct() <= 25)
- + EnterDefensiveMode();
- + }
- + else
- + {
- + Unit* pFriend = FindChampionWithLowestHp(40.0f);
- + if (pFriend && pFriend->GetHealthPct() > 25)
- + EnterCombatMode(false);
- + else
- + EnterCombatMode(true);
- + }
- + events.ScheduleEvent(EVENT_DEF_CHECK, 5s);
- + break;
- + case EVENT_CHAIN_LIGHTNING:
- + if (!isDefensive)
- + {
- + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 30.0f, true))
- + DoCast(target, SPELL_CHAIN_LIGHTNING);
- + events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 16s);
- + }
- + break;
- + case EVENT_HEALING_WAVE:
- + if (Unit* pFriend = FindChampionWithLowestHp(40.0f))
- + {
- + // double check to interrupt heal on defeated champion
- + if (pFriend->HasAura(SPELL_KNEEL))
- + EnterCombatMode(true);
- + else
- + DoCast(pFriend, SPELL_HEALING_WAVE);
- + }
- + if (isDefensive)
- + events.ScheduleEvent(EVENT_HEALING_WAVE, 4s);
- + else
- + events.ScheduleEvent(EVENT_HEALING_WAVE, 12s);
- + break;
- + case EVENT_EARTH_SHIELD:
- + if (Unit* pFriend = FindChampionWithLowestHp(40.0f))
- + {
- + // double check to interrupt shield on defeated champion
- + if (pFriend->HasAura(SPELL_KNEEL))
- + EnterCombatMode(true);
- + else
- + {
- + // Earth Shield is single target spell, we must remove it from previous target
- + if (Creature* target = ObjectAccessor::GetCreature(*me, earthShieldTarget))
- + {
- + if (target->HasAura(SPELL_EARTH_SHIELD))
- + target->RemoveAura(SPELL_EARTH_SHIELD);
- + }
- + DoCast(pFriend, SPELL_EARTH_SHIELD);
- + earthShieldTarget = pFriend->GetGUID();
- + }
- + }
- + events.ScheduleEvent(EVENT_EARTH_SHIELD, randtime(30s, 35s));
- + break;
- + case EVENT_HEX_MENDING:
- + DoCastVictim(SPELL_HEX_OF_MENDING);
- + events.ScheduleEvent(EVENT_HEX_MENDING, randtime(20s, 25s));
- + break;
- + default:
- + break;
- + }
- + }
- + if (!isDefensive)
- + DoMeleeAttackIfReady();
- + }
- + };
- +
- + CreatureAI* GetAI(Creature* creature) const override
- + {
- + return GetTrialOfChampionAI<boss_shaman_toc5AI>(creature);
- + }
- +};
- +
- +class boss_hunter_toc5 : public CreatureScript
- +{
- +public:
- + boss_hunter_toc5() : CreatureScript("boss_hunter_toc5") {}
- +
- + // Jaelyne Evensong && Zul'tore || Hunter
- + struct boss_hunter_toc5AI : public boss_grand_championAI
- + {
- + boss_hunter_toc5AI(Creature* creature) : boss_grand_championAI(creature) {}
- +
- + void Reset() override
- + {
- + boss_grand_championAI::Reset();
- + }
- +
- + void JustEngagedWith(Unit* who) override
- + {
- + events.ScheduleEvent(EVENT_MULTI_SHOT, 7500ms);
- + events.ScheduleEvent(EVENT_LIGHTNING_ARROWS, 15s);
- + events.ScheduleEvent(EVENT_DISENGAGE, randtime(25s, 35s));
- + boss_grand_championAI::JustEngagedWith(who);
- + }
- +
- + void AttackStart(Unit* who) override
- + {
- + me->GetMotionMaster()->MoveChase(who, 25.0f);
- + boss_grand_championAI::AttackStart(who);
- + }
- +
- + void UpdateAI(uint32 uiDiff) override
- + {
- + boss_grand_championAI::UpdateAI(uiDiff);
- +
- + if (CanUseNormalAI())
- + {
- + if (UpdateVictim())
- + DoMeleeAttackIfReady();
- + return;
- + }
- +
- + while (uint32 eventId = events.ExecuteEvent())
- + {
- + switch (eventId)
- + {
- + case EVENT_DISENGAGE:
- + if (Unit* target = SelectTarget(SelectTargetMethod::MinDistance, 0))
- + {
- + if (me->IsWithinDist(target, 5.0f, false))
- + {
- + me->InterruptNonMeleeSpells(true);
- + DoCast(me, SPELL_DISENGAGE);
- + }
- + }
- + events.ScheduleEvent(EVENT_DISENGAGE, randtime(25s, 35s));
- + break;
- + case EVENT_LIGHTNING_ARROWS:
- + if (!me->HasAura(SPELL_LIGHTNING_ARROWS_AURA) && !me->IsWithinDist(me->GetVictim(), 2.0f))
- + {
- + me->InterruptNonMeleeSpells(true);
- + DoCastAOE(SPELL_LIGHTNING_ARROWS);
- + }
- + events.ScheduleEvent(EVENT_LIGHTNING_ARROWS, randtime(20s, 30s));
- + break;
- + case EVENT_MULTI_SHOT:
- + if (me->IsInRange(me->GetVictim(), 5.0f, 30.0f, false) && !me->HasAura(SPELL_LIGHTNING_ARROWS))
- + {
- + me->InterruptNonMeleeSpells(true);
- + DoCastVictim(SPELL_MULTI_SHOT);
- + }
- + events.ScheduleEvent(EVENT_MULTI_SHOT, 8s);
- + break;
- + default:
- + break;
- + }
- + }
- +
- + if (me->IsWithinDist(me->GetVictim(), 2.0f))
- + DoMeleeAttackIfReady();
- + else
- + DoSpellAttackIfReady(SPELL_SHOOT);
- + }
- + };
- +
- + CreatureAI* GetAI(Creature* creature) const override
- + {
- + return GetTrialOfChampionAI<boss_hunter_toc5AI>(creature);
- + }
- +};
- +
- +class boss_rogue_toc5 : public CreatureScript
- +{
- +public:
- + boss_rogue_toc5() : CreatureScript("boss_rouge_toc5") {}
- +
- + // Lana Stouthammer Evensong && Deathstalker Visceri || Rogue
- + struct boss_rogue_toc5AI : public boss_grand_championAI
- + {
- + boss_rogue_toc5AI(Creature* creature) : boss_grand_championAI(creature) {}
- +
- + void Reset() override
- + {
- + boss_grand_championAI::Reset();
- + }
- +
- + void JustEngagedWith(Unit* who) override
- + {
- + events.ScheduleEvent(EVENT_DEADLY_POISON, 500ms);
- + events.ScheduleEvent(EVENT_EVISCERATE, 8s);
- + events.ScheduleEvent(EVENT_FAN_OF_KNIVES, 14s);
- + events.ScheduleEvent(EVENT_POISON_BOTTLE, 19s);
- + boss_grand_championAI::JustEngagedWith(who);
- + }
- +
- + void UpdateAI(uint32 diff) override
- + {
- + boss_grand_championAI::UpdateAI(diff);
- +
- + if (CanUseNormalAI())
- + {
- + if (UpdateVictim())
- + DoMeleeAttackIfReady();
- + return;
- + }
- +
- + if (me->HasUnitState(UNIT_STATE_CASTING))
- + return;
- +
- + while (uint32 eventId = events.ExecuteEvent())
- + {
- + switch (eventId)
- + {
- + case EVENT_DEADLY_POISON:
- + if (!me->HasAura(SPELL_DEADLY_POISON))
- + DoCast(me, SPELL_DEADLY_POISON);
- + events.ScheduleEvent(EVENT_DEADLY_POISON, 30s);
- + case EVENT_EVISCERATE:
- + DoCastVictim(SPELL_EVISCERATE);
- + events.ScheduleEvent(EVENT_EVISCERATE, 8s);
- + break;
- + case EVENT_FAN_OF_KNIVES:
- + if (Unit* target = SelectTarget(SelectTargetMethod::MinDistance, 0))
- + {
- + if (me->IsWithinDist(target, 8.0f, false)) // 8 yards is minimum range
- + DoCastAOE(SPELL_FAN_OF_KNIVES);
- + }
- + events.ScheduleEvent(EVENT_FAN_OF_KNIVES, 14s);
- + break;
- + case EVENT_POISON_BOTTLE:
- + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 30.0f, true))
- + DoCast(target, SPELL_POISON_BOTTLE);
- + events.ScheduleEvent(EVENT_POISON_BOTTLE, 19s);
- + break;
- + default:
- + break;
- + }
- + }
- + DoMeleeAttackIfReady();
- + }
- + };
- +
- + CreatureAI* GetAI(Creature* creature) const override
- + {
- + return GetTrialOfChampionAI<boss_rogue_toc5AI>(creature);
- + }
- +};
- +
- +class spell_toc5_trample_aura : public SpellScriptLoader
- +{
- +public:
- + spell_toc5_trample_aura() : SpellScriptLoader("spell_toc5_trample_aura") {}
- +
- + class spell_toc5_trample_aura_SpellScript : public SpellScript
- + {
- + PrepareSpellScript(spell_toc5_trample_aura_SpellScript);
- +
- + void RemoveInvalidTargets(std::list<WorldObject*>& targets)
- + {
- + // The aura should not be applied if there is already a trample aura on target
- + targets.remove_if(Trinity::UnitAuraCheck(true, GetSpellInfo()->Id));
- + }
- +
- + void HandleStun()
- + {
- + if (Unit* target = GetHitUnit())
- + {
- + // If target is mounted, do not apply
- + if (target->GetVehicleKit() // Grand Champions
- + || target->GetVehicleBase() // Players
- + || target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT)) // Lesser Champions
- + {
- + PreventHitEffect(EFFECT_0);
- + _removed = true;
- + }
- + }
- + }
- +
- + void RemoveAura()
- + {
- + if (_removed)
- + PreventHitAura();
- + }
- +
- + void Register() override
- + {
- + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_toc5_trample_aura_SpellScript::RemoveInvalidTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
- + OnHit += SpellHitFn(spell_toc5_trample_aura_SpellScript::HandleStun);
- + AfterHit += SpellHitFn(spell_toc5_trample_aura_SpellScript::RemoveAura);
- + }
- +
- + bool _removed = false;
- + };
- +
- + SpellScript* GetSpellScript() const override
- + {
- + return new spell_toc5_trample_aura_SpellScript();
- + }
- +};
- +
- +class spell_toc5_lightning_arrows : public SpellScriptLoader
- +{
- +public:
- + spell_toc5_lightning_arrows() : SpellScriptLoader("spell_toc5_lightning_arrows") {}
- +
- + class spell_toc5_lightning_arrows_AuraScript : public AuraScript
- + {
- + PrepareAuraScript(spell_toc5_lightning_arrows_AuraScript);
- +
- + bool Validate(SpellInfo const* /*spellInfo*/) override
- + {
- + if (!sSpellMgr->GetSpellInfo(SPELL_LIGHTNING_ARROWS_AURA))
- + return false;
- + return true;
- + }
- +
- + void HandleScript(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- + {
- + GetCaster()->CastSpell(GetCaster(), SPELL_LIGHTNING_ARROWS_AURA, true);
- + }
- +
- + void Register() override
- + {
- + AfterEffectRemove += AuraEffectRemoveFn(spell_toc5_lightning_arrows_AuraScript::HandleScript, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
- + }
- + };
- +
- + AuraScript* GetAuraScript() const override
- + {
- + return new spell_toc5_lightning_arrows_AuraScript();
- + }
- +};
- +
- +enum CriteriaIds
- +{
- + CRITERIA_WARRIOR = 12538,
- + CRITERIA_HUNTER = 12540,
- + CRITERIA_MAGE = 12542,
- + CRITERIA_ROGUE = 12544,
- + CRITERIA_SHAMAN = 12546,
- + CRITERIA_WARRIOR_H = 12539,
- + CRITERIA_HUNTER_H = 12541,
- + CRITERIA_MAGE_H = 12543,
- + CRITERIA_ROGUE_H = 12545,
- + CRITERIA_SHAMAN_H = 12547
- +};
- +
- +// Statistics achievements "Victories over X champion" both normal and heroic
- +class achievement_victories_over_champion : public AchievementCriteriaScript
- +{
- +public:
- + achievement_victories_over_champion(char const* name, uint32 criteriaId) : AchievementCriteriaScript(name),
- + _criteriaId(criteriaId)
- + {
- + }
- +
- + bool OnCheck(Player* /*player*/, Unit* target) override
- + {
- + if (target)
- + {
- + switch (_criteriaId)
- + {
- + case CRITERIA_WARRIOR:
- + case CRITERIA_WARRIOR_H:
- + return target->GetEntry() == NPC_JACOB || target->GetEntry() == NPC_MOKRA;
- + case CRITERIA_HUNTER:
- + case CRITERIA_HUNTER_H:
- + return target->GetEntry() == NPC_JAELYNE || target->GetEntry() == NPC_ZULTORE;
- + case CRITERIA_MAGE:
- + case CRITERIA_MAGE_H:
- + return target->GetEntry() == NPC_AMBROSE || target->GetEntry() == NPC_ERESSEA;
- + case CRITERIA_ROGUE:
- + case CRITERIA_ROGUE_H:
- + return target->GetEntry() == NPC_LANA || target->GetEntry() == NPC_VISCERI;
- + case CRITERIA_SHAMAN:
- + case CRITERIA_SHAMAN_H:
- + return target->GetEntry() == NPC_COLOSOS || target->GetEntry() == NPC_RUNOK;
- + default:
- + break;
- + }
- + }
- + return false;
- + }
- +
- +private:
- + uint32 const _criteriaId;
- +};
- +
- +void AddSC_boss_grand_champions()
- +{
- + new generic_vehicleAI_toc5();
- + new boss_warrior_toc5();
- + new boss_mage_toc5();
- + new boss_shaman_toc5();
- + new boss_hunter_toc5();
- + new boss_rogue_toc5();
- + new spell_toc5_trample_aura();
- + new spell_toc5_lightning_arrows();
- + new achievement_victories_over_champion("achievement_victories_over_war_champion", CRITERIA_WARRIOR);
- + new achievement_victories_over_champion("achievement_victories_over_hun_champion", CRITERIA_HUNTER);
- + new achievement_victories_over_champion("achievement_victories_over_mag_champion", CRITERIA_MAGE);
- + new achievement_victories_over_champion("achievement_victories_over_rog_champion", CRITERIA_ROGUE);
- + new achievement_victories_over_champion("achievement_victories_over_sha_champion", CRITERIA_SHAMAN);
- + new achievement_victories_over_champion("achievement_victories_over_war_champion_h", CRITERIA_WARRIOR_H);
- + new achievement_victories_over_champion("achievement_victories_over_hun_champion_h", CRITERIA_HUNTER_H);
- + new achievement_victories_over_champion("achievement_victories_over_mag_champion_h", CRITERIA_MAGE_H);
- + new achievement_victories_over_champion("achievement_victories_over_rog_champion_h", CRITERIA_ROGUE_H);
- + new achievement_victories_over_champion("achievement_victories_over_sha_champion_h", CRITERIA_SHAMAN_H);
- +}
- diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp
- dissimilarity index 75%
- index 8a19f8d8d1..e0424e42ba 100644
- --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp
- +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp
- @@ -1,293 +1,389 @@
- -/*
- - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
- - *
- - * 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, see <http://www.gnu.org/licenses/>.
- - */
- -
- -/* ScriptData
- -SDName: Instance Trial of the Champion
- -SDComment:
- -SDCategory: Trial Of the Champion
- -EndScriptData */
- -
- -#include "ScriptMgr.h"
- -#include "Creature.h"
- -#include "CreatureAI.h"
- -#include "GameObject.h"
- -#include "InstanceScript.h"
- -#include "Log.h"
- -#include "Map.h"
- -#include "MotionMaster.h"
- -#include "Player.h"
- -#include "trial_of_the_champion.h"
- -
- -constexpr uint32 ToCEncounterCount = 4;
- -
- -class instance_trial_of_the_champion : public InstanceMapScript
- -{
- -public:
- - instance_trial_of_the_champion() : InstanceMapScript(ToCScriptName, 650) { }
- -
- - InstanceScript* GetInstanceScript(InstanceMap* map) const override
- - {
- - return new instance_trial_of_the_champion_InstanceMapScript(map);
- - }
- -
- - struct instance_trial_of_the_champion_InstanceMapScript : public InstanceScript
- - {
- - instance_trial_of_the_champion_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
- - {
- - SetHeaders(DataHeader);
- - SetBossNumber(ToCEncounterCount);
- - uiMovementDone = 0;
- - uiGrandChampionsDeaths = 0;
- - uiArgentSoldierDeaths = 0;
- - teamInInstance = 0;
- -
- - bDone = false;
- - }
- -
- - uint32 teamInInstance;
- - uint16 uiMovementDone;
- - uint16 uiGrandChampionsDeaths;
- - uint8 uiArgentSoldierDeaths;
- -
- - ObjectGuid uiAnnouncerGUID;
- - ObjectGuid uiMainGateGUID;
- - ObjectGuid uiGrandChampionVehicle1GUID;
- - ObjectGuid uiGrandChampionVehicle2GUID;
- - ObjectGuid uiGrandChampionVehicle3GUID;
- - ObjectGuid uiGrandChampion1GUID;
- - ObjectGuid uiGrandChampion2GUID;
- - ObjectGuid uiGrandChampion3GUID;
- - ObjectGuid uiChampionLootGUID;
- - ObjectGuid uiArgentChampionGUID;
- -
- - GuidList VehicleList;
- -
- - bool bDone;
- -
- - void OnPlayerEnter(Player* player) override
- - {
- - if (!teamInInstance)
- - teamInInstance = player->GetTeam();
- - }
- -
- - void OnCreatureCreate(Creature* creature) override
- - {
- - switch (creature->GetEntry())
- - {
- - case VEHICLE_ARGENT_WARHORSE:
- - case VEHICLE_ARGENT_BATTLEWORG:
- - VehicleList.push_back(creature->GetGUID());
- - break;
- - case NPC_EADRIC:
- - case NPC_PALETRESS:
- - uiArgentChampionGUID = creature->GetGUID();
- - break;
- - case NPC_JAEREN:
- - case NPC_ARELAS:
- - uiAnnouncerGUID = creature->GetGUID();
- - break;
- - default:
- - break;
- - }
- - }
- -
- - uint32 GetCreatureEntry(ObjectGuid::LowType /*guidLow*/, CreatureData const* data) override
- - {
- - if (!teamInInstance)
- - {
- - Map::PlayerList const& players = instance->GetPlayers();
- - if (!players.isEmpty())
- - if (Player* player = players.begin()->GetSource())
- - teamInInstance = player->GetTeam();
- - }
- -
- - uint32 entry = data->id;
- - switch (entry)
- - {
- - case VEHICLE_MOKRA_SKILLCRUSHER_MOUNT:
- - return teamInInstance == HORDE ? VEHICLE_MARSHAL_JACOB_ALERIUS_MOUNT : VEHICLE_MOKRA_SKILLCRUSHER_MOUNT;
- - case VEHICLE_ERESSEA_DAWNSINGER_MOUNT:
- - return teamInInstance == HORDE ? VEHICLE_AMBROSE_BOLTSPARK_MOUNT : VEHICLE_ERESSEA_DAWNSINGER_MOUNT;
- - case VEHICLE_RUNOK_WILDMANE_MOUNT:
- - return teamInInstance == HORDE ? VEHICLE_COLOSOS_MOUNT : VEHICLE_RUNOK_WILDMANE_MOUNT;
- - case VEHICLE_ZUL_TORE_MOUNT:
- - return teamInInstance == HORDE ? VEHICLE_EVENSONG_MOUNT : VEHICLE_ZUL_TORE_MOUNT;
- - case VEHICLE_DEATHSTALKER_VESCERI_MOUNT:
- - return teamInInstance == HORDE ? VEHICLE_LANA_STOUTHAMMER_MOUNT : VEHICLE_DEATHSTALKER_VESCERI_MOUNT;
- - case NPC_JAEREN:
- - return teamInInstance == HORDE ? NPC_ARELAS : NPC_JAEREN;
- - default:
- - return entry;
- - }
- - }
- -
- - void OnGameObjectCreate(GameObject* go) override
- - {
- - switch (go->GetEntry())
- - {
- - case GO_MAIN_GATE:
- - uiMainGateGUID = go->GetGUID();
- - break;
- - case GO_CHAMPIONS_LOOT:
- - case GO_CHAMPIONS_LOOT_H:
- - uiChampionLootGUID = go->GetGUID();
- - break;
- - }
- - }
- -
- - bool SetBossState(uint32 id, EncounterState state) override
- - {
- - if (!InstanceScript::SetBossState(id, state))
- - return false;
- -
- - switch (id)
- - {
- - case BOSS_GRAND_CHAMPIONS:
- - if (state == IN_PROGRESS)
- - {
- - for (ObjectGuid guid : VehicleList)
- - if (Creature* summon = instance->GetCreature(guid))
- - summon->RemoveFromWorld();
- - }
- - else if (state == DONE)
- - {
- - ++uiGrandChampionsDeaths;
- - if (uiGrandChampionsDeaths == 3)
- - {
- - if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID))
- - {
- - pAnnouncer->GetMotionMaster()->MovePoint(0, 748.309f, 619.487f, 411.171f);
- - pAnnouncer->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
- - pAnnouncer->SummonGameObject(instance->IsHeroic() ? GO_CHAMPIONS_LOOT_H : GO_CHAMPIONS_LOOT, 746.59f, 618.49f, 411.09f, 1.42f, QuaternionData(), 25h);
- - }
- - }
- - }
- - break;
- - case BOSS_ARGENT_CHALLENGE_E:
- - if (state == DONE)
- - {
- - if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID))
- - {
- - pAnnouncer->GetMotionMaster()->MovePoint(0, 748.309f, 619.487f, 411.171f);
- - pAnnouncer->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
- - pAnnouncer->SummonGameObject(instance->IsHeroic() ? GO_EADRIC_LOOT_H : GO_EADRIC_LOOT, 746.59f, 618.49f, 411.09f, 1.42f, QuaternionData(), 25h);
- - }
- - }
- - break;
- - case BOSS_ARGENT_CHALLENGE_P:
- - if (state == DONE)
- - {
- - if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID))
- - {
- - pAnnouncer->GetMotionMaster()->MovePoint(0, 748.309f, 619.487f, 411.171f);
- - pAnnouncer->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
- - pAnnouncer->SummonGameObject(instance->IsHeroic() ? GO_PALETRESS_LOOT_H : GO_PALETRESS_LOOT, 746.59f, 618.49f, 411.09f, 1.42f, QuaternionData(), 25h);
- - }
- - }
- - break;
- - }
- - return true;
- - }
- -
- - void SetData(uint32 uiType, uint32 uiData) override
- - {
- - switch (uiType)
- - {
- - case DATA_MOVEMENT_DONE:
- - uiMovementDone = uiData;
- - if (uiMovementDone == 3)
- - {
- - if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID))
- - pAnnouncer->AI()->SetData(DATA_IN_POSITION, 0);
- - }
- - break;
- - case DATA_ARGENT_SOLDIER_DEFEATED:
- - uiArgentSoldierDeaths = uiData;
- - if (uiArgentSoldierDeaths == 9)
- - {
- - if (Creature* pBoss = instance->GetCreature(uiArgentChampionGUID))
- - {
- - pBoss->GetMotionMaster()->MovePoint(0, 746.88f, 618.74f, 411.06f);
- - pBoss->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- - pBoss->SetReactState(REACT_AGGRESSIVE);
- - }
- - }
- - break;
- - }
- -
- - if (uiData == DONE)
- - SaveToDB();
- - }
- -
- - uint32 GetData(uint32 uiData) const override
- - {
- - switch (uiData)
- - {
- - case DATA_MOVEMENT_DONE: return uiMovementDone;
- - case DATA_ARGENT_SOLDIER_DEFEATED: return uiArgentSoldierDeaths;
- - }
- -
- - return 0;
- - }
- -
- - ObjectGuid GetGuidData(uint32 uiData) const override
- - {
- - switch (uiData)
- - {
- - case DATA_ANNOUNCER: return uiAnnouncerGUID;
- - case DATA_MAIN_GATE: return uiMainGateGUID;
- -
- - case DATA_GRAND_CHAMPION_1: return uiGrandChampion1GUID;
- - case DATA_GRAND_CHAMPION_2: return uiGrandChampion2GUID;
- - case DATA_GRAND_CHAMPION_3: return uiGrandChampion3GUID;
- - }
- -
- - return ObjectGuid::Empty;
- - }
- -
- - void SetGuidData(uint32 uiType, ObjectGuid uiData) override
- - {
- - switch (uiType)
- - {
- - case DATA_GRAND_CHAMPION_1:
- - uiGrandChampion1GUID = uiData;
- - break;
- - case DATA_GRAND_CHAMPION_2:
- - uiGrandChampion2GUID = uiData;
- - break;
- - case DATA_GRAND_CHAMPION_3:
- - uiGrandChampion3GUID = uiData;
- - break;
- - }
- - }
- -
- - void WriteSaveDataMore(std::ostringstream& stream) override
- - {
- - stream << uiGrandChampionsDeaths << ' ' << uiMovementDone;
- - }
- -
- - void ReadSaveDataMore(std::istringstream& stream) override
- - {
- - stream >> uiGrandChampionsDeaths >> uiMovementDone;
- - }
- - };
- -};
- -
- -void AddSC_instance_trial_of_the_champion()
- -{
- - new instance_trial_of_the_champion();
- -}
- +/*
- + * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
- + *
- + * This program is free software; you can redistribute it and/or modify it
- + * under the terms of the GNU General Public License as published by the
- + * Free Software Foundation; either version 2 of the License, or (at your
- + * option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- + * more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program. If not, see <http://www.gnu.org/licenses/>.
- + */
- +
- + /* ScriptData
- + SDName: Instance Trial of the Champion
- + SDComment: missing fireworks when boss encounter is set to done
- + SDCategory: Trial Of the Champion
- + EndScriptData */
- +
- +#include "GameObject.h"
- +#include "InstanceScript.h"
- +#include "Player.h"
- +#include "ScriptedCreature.h"
- +#include "ScriptMgr.h"
- +#include "trial_of_the_champion.h"
- +
- +ObjectData const creatureData[] =
- +{
- + { NPC_ARELAS, DATA_ANNOUNCER },
- + { NPC_JAEREN, DATA_ANNOUNCER },
- + { NPC_TIRION, DATA_TIRION },
- + { NPC_VARIAN, DATA_VARIAN },
- + { NPC_JAINA, DATA_JAINA },
- + { NPC_GARROSH, DATA_GARROSH },
- + { NPC_THRALL, DATA_THRALL },
- + { NPC_BLACK_KNIGHT, DATA_BLACK_KNIGHT },
- + { 0, 0 } // END
- +};
- +
- +ObjectData const gameObjectData[] =
- +{
- + { GO_MAIN_GATE, DATA_MAIN_GATE },
- + { GO_CHAMPION_S_CACHE, DATA_CHAMPION_S_CACHE },
- + { GO_CHAMPION_S_CACHE_H, DATA_CHAMPION_S_CACHE },
- + { GO_EADRIC_S_CACHE, DATA_EADRIC_S_CACHE },
- + { GO_EADRIC_S_CACHE_H, DATA_EADRIC_S_CACHE },
- + { GO_CONFESSOR_S_CACHE, DATA_CONFESSOR_S_CACHE },
- + { GO_CONFESSOR_S_CACHE_H, DATA_CONFESSOR_S_CACHE },
- + { 0, 0 } // END
- +};
- +
- +DoorData const doorData[] =
- +{
- + { GO_NORTH_PORTCULLIS, DATA_GRAND_CHAMPIONS, DOOR_TYPE_ROOM },
- + { GO_NORTH_PORTCULLIS, DATA_ARGENT_CHALLENGE, DOOR_TYPE_ROOM },
- + { GO_NORTH_PORTCULLIS, DATA_BLACK_KNIGHT, DOOR_TYPE_ROOM },
- + { 0, 0, DOOR_TYPE_ROOM } // END
- +};
- +
- +uint8 const GrandChampionsCount = 3;
- +
- +class instance_trial_of_the_champion : public InstanceMapScript
- +{
- +public:
- + instance_trial_of_the_champion() : InstanceMapScript(ToCScriptName, 650) {}
- +
- + struct instance_trial_of_the_champion_InstanceMapScript : public InstanceScript
- + {
- + // CORRECCIÓN 1: Cambiar Map* por InstanceMap*
- + instance_trial_of_the_champion_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
- + {
- + SetHeaders(DataHeader);
- + SetBossNumber(MAX_ENCOUNTER);
- + LoadObjectData(creatureData, gameObjectData);
- + LoadDoorData(doorData);
- +
- + _teamInInstance = 0;
- + _argentSoldierDeaths = 0;
- + }
- +
- + uint32 GetCreatureEntry(uint32 /*guidLow*/, CreatureData const* data) override
- + {
- + uint32 entry = data->id;
- + switch (entry)
- + {
- + case NPC_JAEREN:
- + if (_teamInInstance == ALLIANCE)
- + return NPC_ARELAS;
- + break;
- + case VEHICLE_ARGENT_WARHORSE_COSMETIC:
- + if (_teamInInstance == ALLIANCE)
- + return VEHICLE_ARGENT_WARHORSE_A;
- + break;
- + case VEHICLE_ARGENT_BATTLEWORG_H:
- + if (_teamInInstance == ALLIANCE)
- + return VEHICLE_ARGENT_BATTLEWORG_COSMETIC;
- + break;
- + default:
- + break;
- + }
- +
- + return entry;
- + }
- +
- + void OnCreatureCreate(Creature* creature) override
- + {
- + if (!_teamInInstance)
- + {
- + Map::PlayerList const& players = instance->GetPlayers();
- + if (!players.isEmpty())
- + if (Player* player = players.begin()->GetSource())
- + _teamInInstance = player->GetTeam();
- + }
- +
- + switch (creature->GetEntry())
- + {
- + case NPC_MOKRA:
- + case NPC_ERESSEA:
- + case NPC_RUNOK:
- + case NPC_ZULTORE:
- + case NPC_VISCERI:
- + case NPC_JACOB:
- + case NPC_AMBROSE:
- + case NPC_COLOSOS:
- + case NPC_JAELYNE:
- + case NPC_LANA:
- + SetGrandChampionData(creature);
- + break;
- + case VEHICLE_ARGENT_WARHORSE_COSMETIC:
- + case VEHICLE_ARGENT_WARHORSE_A:
- + case VEHICLE_ARGENT_BATTLEWORG_COSMETIC:
- + case VEHICLE_ARGENT_BATTLEWORG_H:
- + _vehicles.push_back(creature->GetGUID());
- + break;
- +
- + case NPC_EADRIC:
- + case NPC_PALETRESS:
- + _argentChampionGUID = creature->GetGUID();
- + break;
- + case VEHICLE_BLACK_KNIGHT:
- + _blackKnightVehicleGUID = creature->GetGUID();
- + break;
- + // Setting passive and unattackable flags to Lesser Champions and Grand Champions' vehicles
- + case NPC_DARNASSUS_CHAMPION:
- + case NPC_EXODAR_CHAMPION:
- + case NPC_STORMWIND_CHAMPION:
- + case NPC_GNOMEREGAN_CHAMPION:
- + case NPC_IRONFORGE_CHAMPION:
- + case NPC_UNDERCITY_CHAMPION:
- + case NPC_THUNDER_BLUFF_CHAMPION:
- + case NPC_ORGRIMMAR_CHAMPION:
- + case NPC_SILVERMOON_CHAMPION:
- + case NPC_SEN_JIN_CHAMPION:
- + case VEHICLE_AMBROSE_BOLTSPARK_MOUNT:
- + case VEHICLE_COLOSOS_MOUNT:
- + case VEHICLE_MARSHAL_JACOB_ALERIUS_MOUNT:
- + case VEHICLE_MOKRA_SKULLCRUSHER_MOUNT:
- + case VEHICLE_ERESSEA_DAWNSINGER_MOUNT:
- + case VEHICLE_RUNOK_WILDMANE_MOUNT:
- + case VEHICLE_ZUL_TORE_MOUNT:
- + case VEHICLE_EVENSONG_MOUNT:
- + case VEHICLE_DEATHSTALKER_VESCERI_MOUNT:
- + case VEHICLE_LANA_STOUTHAMMER_MOUNT:
- + creature->SetReactState(REACT_PASSIVE);
- + creature->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); // CORRECCIÓN: Usar SetUnitFlag en lugar de SetFlag
- + break;
- + default:
- + break;
- + }
- +
- + InstanceScript::OnCreatureCreate(creature);
- + }
- +
- + void SetGrandChampionData(Creature* creature)
- + {
- + for (uint8 i = 0; i < GrandChampionsCount; ++i)
- + {
- + if (!_grandChampionGUIDs[i])
- + {
- + _grandChampionGUIDs[i] = creature->GetGUID();
- + break;
- + }
- + }
- + }
- +
- + bool SetBossState(uint32 id, EncounterState state) override
- + {
- + if (!InstanceScript::SetBossState(id, state))
- + return false;
- +
- + switch (id)
- + {
- + case DATA_GRAND_CHAMPIONS:
- + if (state == DONE)
- + {
- + if (Creature* announcer = GetCreature(DATA_ANNOUNCER))
- + {
- + // On heroic mode we must bind players to the instance
- + if (instance->IsHeroic())
- + instance->ToInstanceMap()->PermBindAllPlayers();
- +
- + announcer->GetMotionMaster()->MovePoint(1, announcerWaitPos);
- + announcer->AI()->SetData(DATA_GRAND_CHAMPIONS_DONE, 0);
- +
- + // CORRECCIÓN 2: Usar Seconds con sufijo 's'
- + DoRespawnGameObject(GetObjectGuid(DATA_CHAMPION_S_CACHE), Seconds(1 * DAY));
- + if (GameObject* cache = GetGameObject(DATA_CHAMPION_S_CACHE))
- + cache->RemoveFlag(GO_FLAG_NOT_SELECTABLE); // CORRECCIÓN 3: Solo el flag
- + }
- + }
- + break;
- + case DATA_ARGENT_CHALLENGE:
- + if (state == SPECIAL)
- + {
- + if (Creature* champion = instance->GetCreature(_argentChampionGUID))
- + {
- + champion->InterruptNonMeleeSpells(true);
- + champion->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); // CORRECCIÓN
- + champion->SetReactState(REACT_PASSIVE);
- + champion->SetHealth(1);
- + champion->CombatStop(true);
- + champion->SetRegenerateHealth(false);
- + champion->SetEmoteState(EMOTE_ONESHOT_NONE); // CORRECCIÓN: Usar SetEmoteState
- + champion->SetHomePosition(745.87f, 625.88f, 411.17f, champion->GetHomePosition().GetOrientation());
- + champion->GetMotionMaster()->MoveTargetedHome();
- + }
- + }
- + else if (state == DONE)
- + {
- + if (Creature* announcer = GetCreature(DATA_ANNOUNCER))
- + {
- + // On heroic mode we must bind players to the instance
- + if (instance->IsHeroic())
- + instance->ToInstanceMap()->PermBindAllPlayers();
- +
- + announcer->GetMotionMaster()->MovePoint(1, announcerWaitPos);
- +
- + uint32 dataType;
- + switch (_argentChampionGUID.GetEntry())
- + {
- + case NPC_EADRIC:
- + dataType = DATA_EADRIC_S_CACHE;
- + break;
- + case NPC_PALETRESS:
- + dataType = DATA_CONFESSOR_S_CACHE;
- + break;
- + default:
- + ABORT();
- + break;
- + }
- +
- + // CORRECCIÓN 4: Usar Seconds con sufijo 's'
- + DoRespawnGameObject(GetObjectGuid(dataType), Seconds(1 * DAY));
- + if (GameObject* cache = GetGameObject(dataType))
- + cache->RemoveFlag(GO_FLAG_NOT_SELECTABLE); // CORRECCIÓN 5: Solo el flag
- + }
- + }
- + break;
- + case DATA_BLACK_KNIGHT:
- + if (state == DONE)
- + {
- + if (Creature* announcer = GetCreature(DATA_ANNOUNCER))
- + announcer->AI()->SetData(DATA_BLACK_KNIGHT_DONE, 0);
- + }
- + break;
- + default:
- + break;
- + }
- + return true;
- + }
- +
- + void SetData(uint32 type, uint32 data) override
- + {
- + switch (type)
- + {
- + case DATA_REMOVE_VEHICLES:
- + {
- + for (ObjectGuid const& guid : _vehicles)
- + if (Creature* vehicle = instance->GetCreature(guid))
- + vehicle->DespawnOrUnsummon();
- +
- + // We must remove defense spells from players
- + Map::PlayerList const& players = instance->GetPlayers();
- + for (auto itr = players.begin(); itr != players.end(); ++itr)
- + {
- + Player* plr = itr->GetSource();
- + plr->RemoveAurasDueToSpell(62552); // Actual defense spell
- + plr->RemoveAurasDueToSpell(63130); // Shield Level 1 (visual only)
- + plr->RemoveAurasDueToSpell(63131); // Shield Level 2 (visual only)
- + plr->RemoveAurasDueToSpell(63132); // Shield Level 3 (visual only)
- + }
- + break;
- + }
- + case DATA_ARGENT_SOLDIER_DEFEATED:
- + _argentSoldierDeaths = data;
- + if (_argentSoldierDeaths == 9)
- + {
- + if (Creature* boss = instance->GetCreature(_argentChampionGUID))
- + {
- + boss->SetFaction(FACTION_MONSTER_2);
- + boss->SetHomePosition(747.02f, 637.65f, 411.57f, centerOrientation);
- + boss->GetMotionMaster()->MovePoint(1, boss->GetHomePosition());
- + }
- + }
- + break;
- + default:
- + break;
- + }
- + }
- +
- + uint32 GetData(uint32 type) const override
- + {
- + switch (type)
- + {
- + case DATA_TEAM_IN_INSTANCE:
- + return _teamInInstance;
- + case DATA_ARGENT_SOLDIER_DEFEATED:
- + return _argentSoldierDeaths;
- + default:
- + break;
- + }
- +
- + return 0;
- + }
- +
- + ObjectGuid GetGuidData(uint32 type) const override
- + {
- + switch (type)
- + {
- + case DATA_GRAND_CHAMPION_1:
- + case DATA_GRAND_CHAMPION_2:
- + case DATA_GRAND_CHAMPION_3:
- + return _grandChampionGUIDs[type - DATA_GRAND_CHAMPION_1];
- + case DATA_GRAND_CHAMPION_VEHICLE_1:
- + case DATA_GRAND_CHAMPION_VEHICLE_2:
- + case DATA_GRAND_CHAMPION_VEHICLE_3:
- + return _grandChampionVehicleGUIDs[type - DATA_GRAND_CHAMPION_VEHICLE_1];
- + case DATA_ARGENT_CHAMPION:
- + return _argentChampionGUID;
- + case DATA_BLACK_KNIGHT_VEHICLE:
- + return _blackKnightVehicleGUID;
- + default:
- + break;
- + }
- +
- + return InstanceScript::GetGuidData(type);
- + }
- +
- + void SetGuidData(uint32 type, ObjectGuid data) override
- + {
- + switch (type)
- + {
- + case DATA_GRAND_CHAMPION_VEHICLE_1:
- + case DATA_GRAND_CHAMPION_VEHICLE_2:
- + case DATA_GRAND_CHAMPION_VEHICLE_3:
- + _grandChampionVehicleGUIDs[type - DATA_GRAND_CHAMPION_VEHICLE_1] = data;
- + break;
- + default:
- + break;
- + }
- + }
- +
- + private:
- + ObjectGuid _grandChampionVehicleGUIDs[GrandChampionsCount];
- + ObjectGuid _grandChampionGUIDs[GrandChampionsCount];
- +
- + ObjectGuid _argentChampionGUID;
- + ObjectGuid _blackKnightVehicleGUID;
- +
- + GuidVector _vehicles;
- +
- + uint32 _teamInInstance;
- + uint8 _argentSoldierDeaths;
- + };
- +
- + InstanceScript* GetInstanceScript(InstanceMap* map) const override
- + {
- + return new instance_trial_of_the_champion_InstanceMapScript(map);
- + }
- +};
- +
- +void AddSC_instance_trial_of_the_champion()
- +{
- + new instance_trial_of_the_champion();
- +}
- diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp
- dissimilarity index 66%
- index e3c4e1e6c6..f909cb9ef4 100644
- --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp
- +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp
- @@ -1,507 +1,1374 @@
- -/*
- - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
- - *
- - * 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, see <http://www.gnu.org/licenses/>.
- - */
- -
- -/* ScriptData
- -SDName: Trial Of the Champion
- -SD%Complete:
- -SDComment:
- -SDCategory: trial_of_the_champion
- -EndScriptData */
- -
- -/* ContentData
- -npc_announcer_toc5
- -EndContentData */
- -
- -#include "ScriptMgr.h"
- -#include "GameObject.h"
- -#include "InstanceScript.h"
- -#include "Map.h"
- -#include "MotionMaster.h"
- -#include "ObjectAccessor.h"
- -#include "Player.h"
- -#include "ScriptedCreature.h"
- -#include "ScriptedGossip.h"
- -#include "TemporarySummon.h"
- -#include "trial_of_the_champion.h"
- -#include "Vehicle.h"
- -
- -enum Yells
- -{
- - SAY_INTRO_1 = 0,
- - SAY_INTRO_2 = 1,
- - SAY_INTRO_3 = 2,
- - SAY_AGGRO = 3,
- - SAY_PHASE_2 = 4,
- - SAY_PHASE_3 = 5,
- - SAY_KILL_PLAYER = 6,
- - SAY_DEATH = 7
- -};
- -
- -enum Gossip
- -{
- - GOSSIP_START_EVENT1_MID = 10614, // I'm ready to start challenge.
- - GOSSIP_START_EVENT1_OID = 0,
- - GOSSIP_START_EVENT2_MID = 10614, // I'm ready for the next challenge.
- - GOSSIP_START_EVENT2_OID = 1
- -};
- -
- -#define ORIENTATION 4.714f
- -
- -/*######
- -## npc_announcer_toc5
- -######*/
- -
- -const Position SpawnPosition = {746.261f, 657.401f, 411.681f, 4.65f};
- -
- -class npc_announcer_toc5 : public CreatureScript
- -{
- -public:
- - npc_announcer_toc5() : CreatureScript("npc_announcer_toc5") { }
- -
- - struct npc_announcer_toc5AI : public ScriptedAI
- - {
- - npc_announcer_toc5AI(Creature* creature) : ScriptedAI(creature)
- - {
- - instance = creature->GetInstanceScript();
- -
- - uiSummonTimes = 0;
- - uiPosition = 0;
- - uiLesserChampions = 0;
- -
- - uiFirstBoss = 0;
- - uiSecondBoss = 0;
- - uiThirdBoss = 0;
- -
- - uiArgentChampion = 0;
- -
- - uiPhase = 0;
- - uiTimer = 0;
- -
- - me->SetReactState(REACT_PASSIVE);
- - me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- - me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
- -
- - SetGrandChampionsForEncounter();
- - SetArgentChampion();
- - }
- -
- - InstanceScript* instance;
- -
- - uint8 uiSummonTimes;
- - uint8 uiPosition;
- - uint8 uiLesserChampions;
- -
- - uint32 uiArgentChampion;
- -
- - uint32 uiFirstBoss;
- - uint32 uiSecondBoss;
- - uint32 uiThirdBoss;
- -
- - uint32 uiPhase;
- - uint32 uiTimer;
- -
- - ObjectGuid uiVehicle1GUID;
- - ObjectGuid uiVehicle2GUID;
- - ObjectGuid uiVehicle3GUID;
- -
- - GuidList Champion1List;
- - GuidList Champion2List;
- - GuidList Champion3List;
- -
- - void NextStep(uint32 uiTimerStep, bool bNextStep = true, uint8 uiPhaseStep = 0)
- - {
- - uiTimer = uiTimerStep;
- - if (bNextStep)
- - ++uiPhase;
- - else
- - uiPhase = uiPhaseStep;
- - }
- -
- - void SetData(uint32 uiType, uint32 /*uiData*/) override
- - {
- - switch (uiType)
- - {
- - case DATA_START:
- - DoSummonGrandChampion(uiFirstBoss);
- - NextStep(10000, false, 1);
- - break;
- - case DATA_IN_POSITION: //movement done.
- - me->GetMotionMaster()->MovePoint(1, 735.81f, 661.92f, 412.39f);
- - if (GameObject* go = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_MAIN_GATE)))
- - instance->HandleGameObject(go->GetGUID(), false);
- - NextStep(10000, false, 3);
- - break;
- - case DATA_LESSER_CHAMPIONS_DEFEATED:
- - {
- - ++uiLesserChampions;
- - GuidList TempList;
- - if (uiLesserChampions == 3 || uiLesserChampions == 6)
- - {
- - switch (uiLesserChampions)
- - {
- - case 3:
- - TempList = Champion2List;
- - break;
- - case 6:
- - TempList = Champion3List;
- - break;
- - }
- -
- - for (GuidList::const_iterator itr = TempList.begin(); itr != TempList.end(); ++itr)
- - if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr))
- - AggroAllPlayers(summon);
- - }else if (uiLesserChampions == 9)
- - StartGrandChampionsAttack();
- -
- - break;
- - }
- - }
- - }
- -
- - void StartGrandChampionsAttack()
- - {
- - Creature* pGrandChampion1 = ObjectAccessor::GetCreature(*me, uiVehicle1GUID);
- - Creature* pGrandChampion2 = ObjectAccessor::GetCreature(*me, uiVehicle2GUID);
- - Creature* pGrandChampion3 = ObjectAccessor::GetCreature(*me, uiVehicle3GUID);
- -
- - if (pGrandChampion1 && pGrandChampion2 && pGrandChampion3)
- - {
- - AggroAllPlayers(pGrandChampion1);
- - AggroAllPlayers(pGrandChampion2);
- - AggroAllPlayers(pGrandChampion3);
- - }
- - }
- -
- - void MovementInform(uint32 uiType, uint32 uiPointId) override
- - {
- - if (uiType != POINT_MOTION_TYPE)
- - return;
- -
- - if (uiPointId == 1)
- - me->SetFacingTo(ORIENTATION);
- - }
- -
- - void DoSummonGrandChampion(uint32 uiBoss)
- - {
- - ++uiSummonTimes;
- - uint32 VEHICLE_TO_SUMMON1 = 0;
- - uint32 VEHICLE_TO_SUMMON2 = 0;
- - switch (uiBoss)
- - {
- - case 0:
- - VEHICLE_TO_SUMMON1 = VEHICLE_MOKRA_SKILLCRUSHER_MOUNT;
- - VEHICLE_TO_SUMMON2 = VEHICLE_ORGRIMMAR_WOLF;
- - break;
- - case 1:
- - VEHICLE_TO_SUMMON1 = VEHICLE_ERESSEA_DAWNSINGER_MOUNT;
- - VEHICLE_TO_SUMMON2 = VEHICLE_SILVERMOON_HAWKSTRIDER;
- - break;
- - case 2:
- - VEHICLE_TO_SUMMON1 = VEHICLE_RUNOK_WILDMANE_MOUNT;
- - VEHICLE_TO_SUMMON2 = VEHICLE_THUNDER_BLUFF_KODO;
- - break;
- - case 3:
- - VEHICLE_TO_SUMMON1 = VEHICLE_ZUL_TORE_MOUNT;
- - VEHICLE_TO_SUMMON2 = VEHICLE_DARKSPEAR_RAPTOR;
- - break;
- - case 4:
- - VEHICLE_TO_SUMMON1 = VEHICLE_DEATHSTALKER_VESCERI_MOUNT;
- - VEHICLE_TO_SUMMON2 = VEHICLE_FORSAKE_WARHORSE;
- - break;
- - default:
- - return;
- - }
- -
- - if (Creature* pBoss = me->SummonCreature(VEHICLE_TO_SUMMON1, SpawnPosition))
- - {
- - switch (uiSummonTimes)
- - {
- - case 1:
- - {
- - uiVehicle1GUID = pBoss->GetGUID();
- - ObjectGuid uiGrandChampionBoss1;
- - if (Vehicle* pVehicle = pBoss->GetVehicleKit())
- - if (Unit* unit = pVehicle->GetPassenger(0))
- - uiGrandChampionBoss1 = unit->GetGUID();
- - instance->SetGuidData(DATA_GRAND_CHAMPION_VEHICLE_1, uiVehicle1GUID);
- - instance->SetGuidData(DATA_GRAND_CHAMPION_1, uiGrandChampionBoss1);
- - pBoss->AI()->SetData(1, 0);
- - break;
- - }
- - case 2:
- - {
- - uiVehicle2GUID = pBoss->GetGUID();
- - ObjectGuid uiGrandChampionBoss2;
- - if (Vehicle* pVehicle = pBoss->GetVehicleKit())
- - if (Unit* unit = pVehicle->GetPassenger(0))
- - uiGrandChampionBoss2 = unit->GetGUID();
- - instance->SetGuidData(DATA_GRAND_CHAMPION_VEHICLE_2, uiVehicle2GUID);
- - instance->SetGuidData(DATA_GRAND_CHAMPION_2, uiGrandChampionBoss2);
- - pBoss->AI()->SetData(2, 0);
- - break;
- - }
- - case 3:
- - {
- - uiVehicle3GUID = pBoss->GetGUID();
- - ObjectGuid uiGrandChampionBoss3;
- - if (Vehicle* pVehicle = pBoss->GetVehicleKit())
- - if (Unit* unit = pVehicle->GetPassenger(0))
- - uiGrandChampionBoss3 = unit->GetGUID();
- - instance->SetGuidData(DATA_GRAND_CHAMPION_VEHICLE_3, uiVehicle3GUID);
- - instance->SetGuidData(DATA_GRAND_CHAMPION_3, uiGrandChampionBoss3);
- - pBoss->AI()->SetData(3, 0);
- - break;
- - }
- - default:
- - return;
- - }
- -
- - for (uint8 i = 0; i < 3; ++i)
- - {
- - if (Creature* pAdd = me->SummonCreature(VEHICLE_TO_SUMMON2, SpawnPosition, TEMPSUMMON_CORPSE_DESPAWN))
- - {
- - switch (uiSummonTimes)
- - {
- - case 1:
- - Champion1List.push_back(pAdd->GetGUID());
- - break;
- - case 2:
- - Champion2List.push_back(pAdd->GetGUID());
- - break;
- - case 3:
- - Champion3List.push_back(pAdd->GetGUID());
- - break;
- - }
- -
- - switch (i)
- - {
- - case 0:
- - pAdd->GetMotionMaster()->MoveFollow(pBoss, 2.0f, float(M_PI));
- - break;
- - case 1:
- - pAdd->GetMotionMaster()->MoveFollow(pBoss, 2.0f, float(M_PI) / 2);
- - break;
- - case 2:
- - pAdd->GetMotionMaster()->MoveFollow(pBoss, 2.0f, float(M_PI) / 2 + float(M_PI));
- - break;
- - }
- - }
- -
- - }
- - }
- - }
- -
- - void DoStartArgentChampionEncounter()
- - {
- - me->GetMotionMaster()->MovePoint(1, 735.81f, 661.92f, 412.39f);
- -
- - if (me->SummonCreature(uiArgentChampion, SpawnPosition))
- - {
- - for (uint8 i = 0; i < 3; ++i)
- - {
- - if (Creature* pTrash = me->SummonCreature(NPC_ARGENT_LIGHWIELDER, SpawnPosition))
- - pTrash->AI()->SetData(i, 0);
- - if (Creature* pTrash = me->SummonCreature(NPC_ARGENT_MONK, SpawnPosition))
- - pTrash->AI()->SetData(i, 0);
- - if (Creature* pTrash = me->SummonCreature(NPC_PRIESTESS, SpawnPosition))
- - pTrash->AI()->SetData(i, 0);
- - }
- - }
- - }
- -
- - void SetGrandChampionsForEncounter()
- - {
- - uiFirstBoss = urand(0, 4);
- -
- - while (uiSecondBoss == uiFirstBoss || uiThirdBoss == uiFirstBoss || uiThirdBoss == uiSecondBoss)
- - {
- - uiSecondBoss = urand(0, 4);
- - uiThirdBoss = urand(0, 4);
- - }
- - }
- -
- - void SetArgentChampion()
- - {
- - uint8 uiTempBoss = urand(0, 1);
- -
- - switch (uiTempBoss)
- - {
- - case 0:
- - uiArgentChampion = NPC_EADRIC;
- - break;
- - case 1:
- - uiArgentChampion = NPC_PALETRESS;
- - break;
- - }
- - }
- -
- - void StartEncounter()
- - {
- - me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
- -
- - if (instance->GetBossState(BOSS_BLACK_KNIGHT) == NOT_STARTED)
- - {
- - if (instance->GetBossState(BOSS_ARGENT_CHALLENGE_E) == NOT_STARTED && instance->GetBossState(BOSS_ARGENT_CHALLENGE_P) == NOT_STARTED)
- - {
- - if (instance->GetBossState(BOSS_GRAND_CHAMPIONS) == NOT_STARTED)
- - SetData(DATA_START, 0);
- -
- - if (instance->GetBossState(BOSS_GRAND_CHAMPIONS) == DONE)
- - DoStartArgentChampionEncounter();
- - }
- -
- - if ((instance->GetBossState(BOSS_GRAND_CHAMPIONS) == DONE &&
- - instance->GetBossState(BOSS_ARGENT_CHALLENGE_E) == DONE) ||
- - instance->GetBossState(BOSS_ARGENT_CHALLENGE_P) == DONE)
- - me->SummonCreature(VEHICLE_BLACK_KNIGHT, 769.834f, 651.915f, 447.035f, 0);
- - }
- - }
- -
- - void AggroAllPlayers(Creature* temp)
- - {
- - Map::PlayerList const& PlList = me->GetMap()->GetPlayers();
- - if (PlList.isEmpty())
- - return;
- -
- - for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i)
- - {
- - if (Player* player = i->GetSource())
- - {
- - if (player->IsGameMaster())
- - continue;
- -
- - if (player->IsAlive())
- - {
- - temp->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation());
- - temp->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- - temp->SetReactState(REACT_AGGRESSIVE);
- - AddThreat(player, 0.0f, temp);
- - }
- - }
- - }
- - }
- -
- - void UpdateAI(uint32 uiDiff) override
- - {
- - ScriptedAI::UpdateAI(uiDiff);
- -
- - if (uiTimer <= uiDiff)
- - {
- - switch (uiPhase)
- - {
- - case 1:
- - DoSummonGrandChampion(uiSecondBoss);
- - NextStep(10000, true);
- - break;
- - case 2:
- - DoSummonGrandChampion(uiThirdBoss);
- - NextStep(0, false);
- - break;
- - case 3:
- - if (!Champion1List.empty())
- - {
- - for (GuidList::const_iterator itr = Champion1List.begin(); itr != Champion1List.end(); ++itr)
- - if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr))
- - AggroAllPlayers(summon);
- - NextStep(0, false);
- - }
- - break;
- - }
- - } else uiTimer -= uiDiff;
- -
- - if (!UpdateVictim())
- - return;
- - }
- -
- - void JustSummoned(Creature* summon) override
- - {
- - if (instance->GetBossState(BOSS_GRAND_CHAMPIONS) == NOT_STARTED)
- - {
- - summon->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- - summon->SetReactState(REACT_PASSIVE);
- - }
- - }
- -
- - void SummonedCreatureDespawn(Creature* summon) override
- - {
- - switch (summon->GetEntry())
- - {
- - case VEHICLE_DARNASSIA_NIGHTSABER:
- - case VEHICLE_EXODAR_ELEKK:
- - case VEHICLE_STORMWIND_STEED:
- - case VEHICLE_GNOMEREGAN_MECHANOSTRIDER:
- - case VEHICLE_IRONFORGE_RAM:
- - case VEHICLE_FORSAKE_WARHORSE:
- - case VEHICLE_THUNDER_BLUFF_KODO:
- - case VEHICLE_ORGRIMMAR_WOLF:
- - case VEHICLE_SILVERMOON_HAWKSTRIDER:
- - case VEHICLE_DARKSPEAR_RAPTOR:
- - SetData(DATA_LESSER_CHAMPIONS_DEFEATED, 0);
- - break;
- - }
- - }
- -
- - bool OnGossipHello(Player* player) override
- - {
- - if (((instance->GetBossState(BOSS_GRAND_CHAMPIONS) == DONE &&
- - instance->GetBossState(BOSS_BLACK_KNIGHT) == DONE &&
- - instance->GetBossState(BOSS_ARGENT_CHALLENGE_E) == DONE) ||
- - instance->GetBossState(BOSS_ARGENT_CHALLENGE_P) == DONE))
- - return false;
- -
- - if (instance->GetBossState(BOSS_GRAND_CHAMPIONS) == NOT_STARTED &&
- - instance->GetBossState(BOSS_ARGENT_CHALLENGE_E) == NOT_STARTED &&
- - instance->GetBossState(BOSS_ARGENT_CHALLENGE_P) == NOT_STARTED &&
- - instance->GetBossState(BOSS_BLACK_KNIGHT) == NOT_STARTED)
- - {
- - InitGossipMenuFor(player, GOSSIP_START_EVENT1_MID);
- - AddGossipItemFor(player, GOSSIP_START_EVENT1_MID, GOSSIP_START_EVENT1_OID, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- - SendGossipMenuFor(player, player->GetGossipTextId(GOSSIP_START_EVENT1_MID, me), me->GetGUID());
- - }
- - else
- - {
- - InitGossipMenuFor(player, GOSSIP_START_EVENT2_MID);
- - AddGossipItemFor(player, GOSSIP_START_EVENT2_MID, GOSSIP_START_EVENT2_OID, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- - SendGossipMenuFor(player, player->GetGossipTextId(GOSSIP_START_EVENT2_MID, me), me->GetGUID());
- - }
- -
- - return true;
- - }
- -
- - bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
- - {
- - uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
- - ClearGossipMenuFor(player);
- - if (action == GOSSIP_ACTION_INFO_DEF + 1)
- - {
- - CloseGossipMenuFor(player);
- - StartEncounter();
- - }
- - return true;
- - }
- - };
- -
- - CreatureAI* GetAI(Creature* creature) const override
- - {
- - return GetTrialOfTheChampionAI<npc_announcer_toc5AI>(creature);
- - }
- -};
- -
- -void AddSC_trial_of_the_champion()
- -{
- - new npc_announcer_toc5();
- -}
- +/*
- + * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
- + *
- + * This program is free software; you can redistribute it and/or modify it
- + * under the terms of the GNU General Public License as published by the
- + * Free Software Foundation; either version 2 of the License, or (at your
- + * option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- + * more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program. If not, see <http://www.gnu.org/licenses/>.
- + */
- +
- +#include "GameObject.h"
- +#include "ScriptMgr.h"
- +#include "ScriptedCreature.h"
- +#include "ScriptedGossip.h"
- +#include "trial_of_the_champion.h"
- +#include "Vehicle.h"
- +#include "Player.h"
- +
- +#define GOSSIP_START_EVENT1 "I am ready."
- +#define GOSSIP_START_EVENT2 "I am ready for the next challenge."
- +#define GOSSIP_START_EVENT_SKIP "I am ready. However I'd like to skip the pageantry."
- +
- + // Agregar esta definición
- +const Position SpawnPosition = { 746.261f, 687.0f, 412.374f, 4.65f };
- +
- +enum Texts
- +{
- + // Used by announcers
- + SAY_INTRO_2_E = 0,
- + SAY_INTRO_2_P = 1,
- + SAY_INTRO_1 = 2,
- + SAY_INTRO_SHAM_A = 3,
- + SAY_INTRO_MAGE_H = 3,
- + SAY_INTRO_HUN = 4,
- + SAY_INTRO_MAGE_A = 5,
- + SAY_INTRO_WARR_H = 5,
- + SAY_INTRO_WARR_A = 6,
- + SAY_INTRO_ROG_H = 6,
- + SAY_INTRO_ROG_A = 7,
- + SAY_INTRO_SHAM_H = 7,
- + SAY_INTRO_3 = 8,
- + SAY_INTRODUCE_PLR_0 = 9,
- + SAY_INTRODUCE_PLR_1 = 10,
- + SAY_INTRODUCE_PLR_2 = 11,
- + SAY_INTRODUCE_PLR_3 = 12,
- + SAY_INTRODUCE_PLR_4 = 13,
- +
- + // Used by Tirion
- + SAY_TIRION_INTRO_1 = 50,
- + SAY_TIRION_INTRO_2 = 51,
- + SAY_TIRION_INTRO_3 = 52,
- + SAY_TIRION_OUTRO_1 = 53,
- + SAY_TIRION_INTRO_4 = 54,
- + SAY_TIRION_INTRO_5 = 55,
- + SAY_TIRION_INTRO_6 = 56,
- + SAY_TIRION_OUTRO_2 = 57,
- + SAY_TIRION_OUTRO_3 = 58,
- +
- + // Used by Varian
- + SAY_VARIAN_INTRO_1 = 50,
- + SAY_VARIAN_INTRO_2 = 52,
- + SAY_VARIAN_INTRO_3 = 51,
- + SAY_VARIAN_OUTRO_1 = 53,
- +
- + // Used by Garrosh
- + SAY_GARROSH_INTRO_1 = 50,
- + SAY_GARROSH_INTRO_2 = 52,
- + SAY_GARROSH_INTRO_3 = 51,
- +
- + // Used by Jaina
- + SAY_JAINA_INTRO_1 = 0,
- + SAY_JAINA_INTRO_2 = 1,
- +
- + // Used by Thrall
- + SAY_THRALL_INTRO_1 = 0,
- + SAY_THRALL_INTRO_2 = 2,
- + SAY_THRALL_OUTRO_1 = 1,
- +
- + // Used by Argent Confessor Paletress
- + SAY_PALETRESS_INTRO_1 = 0,
- + SAY_PALETRESS_INTRO_2 = 1,
- +
- + // Used by Eadric the Pure
- + SAY_EADRIC_INTRO_1 = 0,
- +
- + // Used by The Black Knight
- + SAY_KNIGHT_INTRO_1 = 0,
- + SAY_KNIGHT_INTRO_2 = 1,
- + SAY_KNIGHT_INTRO_3 = 2,
- +
- + // Used by spectators (same id for every spectator)
- + EMOTE_SPECTATOR_CHEER = 0
- +};
- +
- +enum BossData
- +{
- + BOSS_WARRIOR,
- + BOSS_MAGE,
- + BOSS_SHAMAN,
- + BOSS_HUNTER,
- + BOSS_ROGUE,
- + BOSS_EADRIC,
- + BOSS_PALETRESS
- +};
- +
- +enum GossipTexts
- +{
- + GOSSIP_TEXT_UNMOUNTED_A = 14757,
- + GOSSIP_TEXT_UNMOUNTED_H = 15043,
- + GOSSIP_TEXT_FIRST_BOSS = 14688,
- + GOSSIP_TEXT_SECOND_BOSS = 14737,
- + GOSSIP_TEXT_THIRD_BOSS = 14738
- +};
- +
- +enum Events
- +{
- + EVENT_CHEER_RND = 1,
- + // Grand Champion - roleplaying intro
- + EVENT_INTRODUCE,
- + EVENT_CHAT_1,
- + EVENT_CHAT_2,
- + EVENT_CHAT_3,
- + EVENT_CHAT_4,
- + EVENT_CHAT_5,
- + EVENT_CHAT_6,
- + EVENT_SUMMON_1,
- + EVENT_OPEN_DOOR_1,
- + EVENT_INTRODUCE_BOSS_1,
- + EVENT_CLOSE_DOOR_1,
- + EVENT_SUMMON_2,
- + EVENT_OPEN_DOOR_2,
- + EVENT_INTRODUCE_BOSS_2,
- + EVENT_CLOSE_DOOR_2,
- + EVENT_SUMMON_3,
- + EVENT_OPEN_DOOR_3,
- + EVENT_INTRODUCE_BOSS_3,
- + EVENT_CLOSE_DOOR_3,
- + EVENT_WAIT_1,
- + EVENT_FACING,
- + EVENT_CHAT_7,
- + EVENT_AGGRO_1,
- + EVENT_CHAT_8,
- + // Grand Champion - roleplaying skipped
- + EVENT_CHAT_9 = 30,
- + EVENT_SUMMON_1_SKIP,
- + EVENT_SUMMON_2_SKIP,
- + EVENT_SUMMON_3_SKIP,
- + // Argent Champion
- + EVENT_MOVE_MIDDLE = 40,
- + EVENT_SPAWN_ALL,
- + EVENT_OPEN_DOOR_4,
- + EVENT_INTRODUCE_BOSS_4,
- + EVENT_ARGENT_BOSS_WALK,
- + EVENT_GO_TO_ARGENT_BOSS,
- + EVENT_CHAT_10,
- + EVENT_CHAT_11,
- + EVENT_WAIT_2,
- + EVENT_CHAT_12,
- + // The Black Knight
- + EVENT_STEP_FORWARD = 50,
- + EVENT_CHAT_13,
- + EVENT_FACING_1,
- + EVENT_CHAT_14,
- + EVENT_START_PATH,
- + EVENT_CHAT_15,
- + EVENT_FACING_2,
- + EVENT_STUN_ANNOUNCER,
- + EVENT_CHAT_16,
- + EVENT_KNOCK_ANNOUNCER,
- + EVENT_CHAT_17,
- + EVENT_CHAT_18,
- + EVENT_AGGRO_2,
- + EVENT_CHAT_19,
- + EVENT_CHAT_20,
- + EVENT_CHAT_21,
- + EVENT_CHAT_22
- +};
- +
- +enum Spells
- +{
- + // Both casted by The Black Knight to announcer
- + SPELL_DEATHS_RESPITE = 66798,
- + SPELL_DEATHS_PUSH = 66797
- +};
- +
- +enum PointMovement
- +{
- + POINT_ENCOUNTER_1_WAIT = 0,
- + POINT_RETURN_TO_CENTER,
- + POINT_START_ARGENT_CHAMP,
- + POINT_ENCOUNTER_2_WAIT_1,
- + POINT_ENCOUNTER_2_WAIT_2,
- + POINT_ENCOUNTER_3_WAIT
- +};
- +
- +/*######
- +## npc_announcer_toc5
- +######*/
- +uint32 const IntroducePlrTxt[5] = { SAY_INTRODUCE_PLR_0, SAY_INTRODUCE_PLR_1, SAY_INTRODUCE_PLR_2, SAY_INTRODUCE_PLR_3, SAY_INTRODUCE_PLR_4 };
- +uint32 const SpectatorData[12] =
- +{
- + 0,
- + NPC_SPECTATOR_HUMAN,
- + NPC_SPECTATOR_ORC,
- + NPC_SPECTATOR_DWARF,
- + NPC_SPECTATOR_NELF,
- + NPC_SPECTATOR_UNDEAD,
- + NPC_SPECTATOR_TAUREN,
- + NPC_SPECTATOR_GNOME,
- + NPC_SPECTATOR_TROLL,
- + 0,
- + NPC_SPECTATOR_BELF,
- + NPC_SPECTATOR_DRAENEI
- +};
- +
- +// Bases mostly on Joshiwald's work (big thanks)
- +struct GrandChampionInfo
- +{
- + uint32 GrandChampionEntry[2];
- + uint32 FactionChampionEntry[2];
- + uint8 AnnounceText[2];
- + uint32 GrandChampionRealEntry[2]; // used only for cheering at correct champion if event is skipped
- + uint32 SpecatatorEntry[2];
- +};
- +
- +GrandChampionInfo const GrandChampionData[5] =
- +{
- + {
- + { VEHICLE_MOKRA_SKULLCRUSHER_MOUNT, VEHICLE_MARSHAL_JACOB_ALERIUS_MOUNT },
- + { NPC_ORGRIMMAR_CHAMPION, NPC_STORMWIND_CHAMPION },
- + { SAY_INTRO_WARR_H, SAY_INTRO_WARR_A },
- + { NPC_MOKRA, NPC_JACOB },
- + { SpectatorData[RACE_ORC], SpectatorData[RACE_HUMAN] },
- + },
- + {
- + { VEHICLE_ERESSEA_DAWNSINGER_MOUNT, VEHICLE_AMBROSE_BOLTSPARK_MOUNT },
- + { NPC_SILVERMOON_CHAMPION, NPC_GNOMEREGAN_CHAMPION },
- + { SAY_INTRO_MAGE_H, SAY_INTRO_MAGE_A },
- + { NPC_ERESSEA, NPC_AMBROSE },
- + { SpectatorData[RACE_BLOODELF], SpectatorData[RACE_GNOME] },
- + },
- + {
- + { VEHICLE_RUNOK_WILDMANE_MOUNT, VEHICLE_COLOSOS_MOUNT },
- + { NPC_THUNDER_BLUFF_CHAMPION, NPC_EXODAR_CHAMPION },
- + { SAY_INTRO_SHAM_H, SAY_INTRO_SHAM_A },
- + { NPC_RUNOK, NPC_COLOSOS },
- + { SpectatorData[RACE_TAUREN], SpectatorData[RACE_DRAENEI] },
- + },
- + {
- + { VEHICLE_ZUL_TORE_MOUNT, VEHICLE_EVENSONG_MOUNT },
- + { NPC_SEN_JIN_CHAMPION, NPC_DARNASSUS_CHAMPION },
- + { SAY_INTRO_HUN, SAY_INTRO_HUN },
- + { NPC_ZULTORE, NPC_JAELYNE },
- + { SpectatorData[RACE_TROLL], SpectatorData[RACE_NIGHTELF] },
- + },
- + {
- + { VEHICLE_DEATHSTALKER_VESCERI_MOUNT, VEHICLE_LANA_STOUTHAMMER_MOUNT },
- + { NPC_UNDERCITY_CHAMPION, NPC_IRONFORGE_CHAMPION },
- + { SAY_INTRO_ROG_H, SAY_INTRO_ROG_A },
- + { NPC_VISCERI, NPC_LANA },
- + { SpectatorData[RACE_UNDEAD_PLAYER], SpectatorData[RACE_DWARF] },
- + }
- +};
- +
- +class npc_announcer_toc5 : public CreatureScript
- +{
- +public:
- + npc_announcer_toc5() : CreatureScript("npc_announcer_toc5") {}
- +
- + struct npc_announcer_toc5AI : public ScriptedAI
- + {
- + npc_announcer_toc5AI(Creature* creature) : ScriptedAI(creature)
- + {
- + instance = creature->GetInstanceScript();
- +
- + uiSummonTimes = 0;
- + uiLesserChampions = 0;
- +
- + uiFirstBoss = 0;
- + uiSecondBoss = 0;
- + uiThirdBoss = 0;
- + uiArgentChampion = 0;
- +
- + SetCombatMovement(false);
- +
- + me->SetReactState(REACT_PASSIVE);
- + me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- + me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
- + me->SetWalk(true);
- +
- + SetGrandChampionsForEncounter();
- + SetArgentChampion();
- + }
- +
- + InstanceScript* instance;
- +
- + uint8 uiSummonTimes;
- + uint8 uiLesserChampions;
- +
- + uint32 uiFirstBoss;
- + uint32 uiSecondBoss;
- + uint32 uiThirdBoss;
- + uint32 uiArgentChampion;
- +
- + EventMap events;
- +
- + GuidList Champion1List;
- + GuidList Champion2List;
- + GuidList Champion3List;
- + GuidList PlayerEventList;
- +
- + void NextStep(uint32 uiTimerStep, bool bNextStep, uint32 currentEvent, uint8 uiPhaseStep = 0)
- + {
- + if (bNextStep)
- + events.ScheduleEvent(currentEvent + 1, Milliseconds(uiTimerStep));
- + else
- + {
- + if (uiPhaseStep > 0)
- + events.ScheduleEvent(uiPhaseStep, Milliseconds(uiTimerStep));
- + }
- + }
- +
- + void Reset() override
- + {
- + events.Reset();
- + events.ScheduleEvent(EVENT_CHEER_RND, 120s);
- + }
- +
- + void SetData(uint32 uiType, uint32 uiData) override
- + {
- + switch (uiType)
- + {
- + case DATA_START:
- + if (Creature* tirion = instance->GetCreature(DATA_TIRION))
- + tirion->AI()->Talk(SAY_TIRION_INTRO_1);
- + me->GetMotionMaster()->MovePoint(POINT_ENCOUNTER_1_WAIT, announcerEncounterPos);
- + NextStep(6000, false, 0, EVENT_CHAT_9);
- + break;
- + case DATA_LESSER_CHAMPIONS_PREPARE:
- + {
- + // Moving lesser champions to right position
- + uint32 TeamInInstance = instance->GetData(DATA_TEAM_IN_INSTANCE);
- + GuidList* TempList = nullptr;
- + uint8 x = 0;
- + switch (uiData)
- + {
- + case 1: // WAYPOINT_MAP_BOSS_1
- + TempList = &Champion1List;
- + if (TeamInInstance == HORDE)
- + x = 9;
- + else
- + x = 0;
- + break;
- + case 2: // WAYPOINT_MAP_BOSS_2
- + TempList = &Champion2List;
- + if (TeamInInstance == HORDE)
- + x = 12;
- + else
- + x = 3;
- + break;
- + case 3: // WAYPOINT_MAP_BOSS_3
- + TempList = &Champion3List;
- + if (TeamInInstance == HORDE)
- + x = 15;
- + else
- + x = 6;
- + break;
- + default:
- + break;
- + }
- +
- + if (TempList)
- + {
- + for (ObjectGuid const& guid : *TempList)
- + {
- + if (Creature* add = ObjectAccessor::GetCreature(*me, guid))
- + add->AI()->SetData(1, x); // DATA_GENERATE_WAYPOINTS_FOR_ADDS
- + x++;
- + }
- + }
- + break;
- + }
- + case DATA_LESSER_CHAMPIONS_DEFEATED:
- + {
- + ++uiLesserChampions;
- + GuidList TempList;
- + if (uiLesserChampions == 3 || uiLesserChampions == 6)
- + {
- + switch (uiLesserChampions)
- + {
- + case 3:
- + TempList = Champion2List;
- + break;
- + case 6:
- + TempList = Champion3List;
- + break;
- + }
- +
- + for (GuidList::const_iterator itr = TempList.begin(); itr != TempList.end(); ++itr)
- + if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr))
- + EnterAggressiveMode(summon);
- + }
- + else if (uiLesserChampions == 9)
- + StartGrandChampionsAttack();
- +
- + break;
- + }
- + case DATA_GRAND_CHAMPIONS_DONE:
- + NextStep(3000, false, 0, EVENT_CHAT_8);
- + break;
- + case DATA_ARGENT_CHAMPION_PREPARE:
- + NextStep(500, false, 0, EVENT_GO_TO_ARGENT_BOSS);
- + break;
- + case DATA_BLACK_KNIGHT_PREPARE:
- + NextStep(2000, false, 0, EVENT_CHAT_15);
- + break;
- + case DATA_BLACK_KNIGHT_PRECAST:
- + NextStep(500, false, 0, EVENT_FACING_2);
- + break;
- + case DATA_BLACK_KNIGHT_DONE:
- + NextStep(7000, false, 0, EVENT_CHAT_20);
- + break;
- + default:
- + break;
- + }
- + }
- +
- + void StartGrandChampionsAttack()
- + {
- + Creature* pGrandChampion1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GRAND_CHAMPION_VEHICLE_1));
- + Creature* pGrandChampion2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GRAND_CHAMPION_VEHICLE_2));
- + Creature* pGrandChampion3 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GRAND_CHAMPION_VEHICLE_3));
- + if (pGrandChampion1 && pGrandChampion2 && pGrandChampion3)
- + {
- + EnterAggressiveMode(pGrandChampion1, true);
- + EnterAggressiveMode(pGrandChampion2, true);
- + EnterAggressiveMode(pGrandChampion3, true);
- + }
- + }
- +
- + void MovementInform(uint32 uiType, uint32 uiPointId) override
- + {
- + if (uiType != POINT_MOTION_TYPE)
- + return;
- +
- + switch (uiPointId)
- + {
- + case POINT_ENCOUNTER_1_WAIT:
- + NextStep(500, false, 0, EVENT_WAIT_1);
- + break;
- + case POINT_RETURN_TO_CENTER:
- + me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
- + break;
- + case POINT_START_ARGENT_CHAMP:
- + me->SetFacingTo(me->GetHomePosition().GetOrientation());
- + NextStep(500, false, 0, EVENT_SPAWN_ALL);
- + break;
- + case POINT_ENCOUNTER_2_WAIT_1:
- + NextStep(500, false, 0, EVENT_WAIT_2);
- + break;
- + case POINT_ENCOUNTER_2_WAIT_2:
- + me->SetFacingTo(centerOrientation);
- + NextStep(1000, false, 0, EVENT_CHAT_12);
- + break;
- + case POINT_ENCOUNTER_3_WAIT:
- + me->SetFacingTo(centerOrientation);
- + NextStep(1000, false, 0, EVENT_CHAT_13);
- + break;
- + default:
- + break;
- + }
- + }
- +
- + void DoSummonNextGrandChampion(bool skipEvent = false)
- + {
- + ++uiSummonTimes;
- + uint32 bossId;
- + switch (uiSummonTimes)
- + {
- + case 1:
- + bossId = uiFirstBoss;
- + break;
- + case 2:
- + bossId = uiSecondBoss;
- + break;
- + case 3:
- + bossId = uiThirdBoss;
- + break;
- + default:
- + return;
- + }
- +
- + if (bossId >= 5)
- + return;
- +
- + GrandChampionInfo const* info = &GrandChampionData[bossId];
- + uint32 TeamInInstance = instance->GetData(DATA_TEAM_IN_INSTANCE);
- + uint32 teamIndex = TeamInInstance == HORDE ? 1 : 0;
- +
- + // Calculating spawn position for grand champion if event is skipped
- + int x = uiSummonTimes - 1;
- + if (TeamInInstance == HORDE)
- + x += 3;
- +
- + // Grand Champions
- + Position const spawnPos = skipEvent ? GrandChampFinalLoc[x] : SpawnPosition;
- + if (Creature* pBoss = me->SummonCreature(info->GrandChampionEntry[teamIndex], spawnPos))
- + {
- + instance->SetGuidData(DATA_GRAND_CHAMPION_VEHICLE_1 + uiSummonTimes - 1, pBoss->GetGUID());
- +
- + if (!skipEvent)
- + pBoss->AI()->SetData(uiSummonTimes, TeamInInstance);
- + else
- + {
- + if (TeamInInstance == ALLIANCE)
- + pBoss->SetFacingTo(hordeOrientation);
- + else
- + pBoss->SetFacingTo(allianceOrientation);
- + pBoss->SetHomePosition(pBoss->GetPositionX(), pBoss->GetPositionY(), pBoss->GetPositionZ(), TeamInInstance == ALLIANCE ? hordeOrientation : allianceOrientation);
- +
- + // Specatators cheer for champions even if event is skipped
- + if (Creature* spectator = me->FindNearestCreature(info->SpecatatorEntry[teamIndex], 200.0f))
- + {
- + if (Creature* rider = me->FindNearestCreature(info->GrandChampionRealEntry[teamIndex], 200.0f))
- + spectator->AI()->Talk(EMOTE_SPECTATOR_CHEER, rider);
- + }
- + }
- +
- + // Lesser Champions
- + for (uint8 i = 0; i < 3; ++i)
- + {
- + // Calculating waiting positions for lesser champions if event is skipped
- + int m = (uiSummonTimes - 1) * 3 + i;
- + if (TeamInInstance == HORDE)
- + m += 9;
- +
- + if (Creature* pAdd = me->SummonCreature(info->FactionChampionEntry[teamIndex], spawnPos, TEMPSUMMON_DEAD_DESPAWN))
- + {
- + switch (uiSummonTimes)
- + {
- + case 1:
- + Champion1List.push_back(pAdd->GetGUID());
- + break;
- + case 2:
- + Champion2List.push_back(pAdd->GetGUID());
- + break;
- + case 3:
- + Champion3List.push_back(pAdd->GetGUID());
- + break;
- + default:
- + break;
- + }
- +
- + if (!skipEvent)
- + {
- + // Following grand champion
- + switch (i)
- + {
- + case 0:
- + pAdd->GetMotionMaster()->MoveFollow(pBoss, 2.0f, float(M_PI));
- + break;
- + case 1:
- + pAdd->GetMotionMaster()->MoveFollow(pBoss, 2.0f, float(M_PI) / 2);
- + break;
- + case 2:
- + pAdd->GetMotionMaster()->MoveFollow(pBoss, 2.0f, float(M_PI) / 2 + float(M_PI));
- + break;
- + default:
- + break;
- + }
- + }
- + else
- + // Lesser Champions walk to their final positions
- + pAdd->AI()->SetData(1, m); // DATA_GENERATE_WAYPOINTS_FOR_ADDS
- + }
- + }
- + }
- + }
- +
- + void DoStartArgentChampionEncounter()
- + {
- + // Removing vehicles (if not already been removed)
- + instance->SetData(DATA_REMOVE_VEHICLES, 0);
- + // Cleaning chest from arena
- + if (GameObject* cache = instance->GetGameObject(DATA_CHAMPION_S_CACHE))
- + cache->Delete();
- + NextStep(1000, false, 0, EVENT_MOVE_MIDDLE);
- + }
- +
- + void DoStartBlackKnight()
- + {
- + // Removing vehicles (if not already been removed)
- + instance->SetData(DATA_REMOVE_VEHICLES, 0);
- + // Cleaning chest from arena
- + if (GameObject* cache = instance->GetGameObject(DATA_EADRIC_S_CACHE))
- + cache->Delete();
- + else if (GameObject* cache = instance->GetGameObject(DATA_CONFESSOR_S_CACHE))
- + cache->Delete();
- +
- + NextStep(1000, false, 0, EVENT_STEP_FORWARD);
- + }
- +
- + void SetGrandChampionsForEncounter()
- + {
- + uiFirstBoss = urand(BOSS_WARRIOR, BOSS_ROGUE);
- + do
- + {
- + uiSecondBoss = urand(BOSS_WARRIOR, BOSS_ROGUE);
- + uiThirdBoss = urand(BOSS_WARRIOR, BOSS_ROGUE);
- + } while (uiSecondBoss == uiFirstBoss || uiThirdBoss == uiFirstBoss || uiThirdBoss == uiSecondBoss);
- + }
- +
- + void SetArgentChampion()
- + {
- + switch (urand(BOSS_EADRIC, BOSS_PALETRESS))
- + {
- + case BOSS_EADRIC:
- + uiArgentChampion = NPC_EADRIC;
- + break;
- + case BOSS_PALETRESS:
- + uiArgentChampion = NPC_PALETRESS;
- + break;
- + default:
- + break;
- + }
- + }
- +
- + void StartEncounter(bool startRp = false)
- + {
- + me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
- +
- + if (instance->GetBossState(DATA_BLACK_KNIGHT) == NOT_STARTED)
- + {
- + if (instance->GetBossState(DATA_ARGENT_CHALLENGE) == NOT_STARTED)
- + {
- + // Starting Grand Champion event (with roleplaying)
- + if (startRp && instance->GetBossState(DATA_GRAND_CHAMPIONS) == NOT_STARTED)
- + {
- + Talk(SAY_INTRO_1);
- + NextStep(7000, false, 0, EVENT_INTRODUCE);
- + }
- +
- + // Starting Grand Champion event (skipped roleplaying)
- + if (!startRp && instance->GetBossState(DATA_GRAND_CHAMPIONS) == NOT_STARTED)
- + SetData(DATA_START, 0);
- +
- + // Starting Argent Champion event
- + if (instance->GetBossState(DATA_GRAND_CHAMPIONS) == DONE)
- + DoStartArgentChampionEncounter();
- + }
- +
- + // Starting Black Knight event
- + if (instance->GetBossState(DATA_GRAND_CHAMPIONS) == DONE && instance->GetBossState(DATA_ARGENT_CHALLENGE) == DONE)
- + DoStartBlackKnight();
- + }
- + }
- +
- + void IntroduceChampion()
- + {
- + uint32 bossId;
- + switch (uiSummonTimes)
- + {
- + case 1:
- + bossId = uiFirstBoss;
- + break;
- + case 2:
- + bossId = uiSecondBoss;
- + break;
- + case 3:
- + bossId = uiThirdBoss;
- + break;
- + default:
- + return;
- + }
- +
- + if (bossId >= 5)
- + return;
- +
- + GrandChampionInfo const* info = &GrandChampionData[bossId];
- + uint32 teamIndex = instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? 1 : 0;
- +
- + // Introduces champion
- + Talk(info->AnnounceText[teamIndex]);
- + // Spectators cheer for the champion
- + if (Creature* spectator = me->FindNearestCreature(info->SpecatatorEntry[teamIndex], 200.0f))
- + {
- + if (Creature* boss = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GRAND_CHAMPION_1 + uiSummonTimes - 1)))
- + spectator->AI()->Talk(EMOTE_SPECTATOR_CHEER, boss);
- + }
- + }
- +
- + void EnterAggressiveMode(Creature* temp, bool riderAlso = false)
- + {
- + temp->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC);
- + temp->SetReactState(REACT_AGGRESSIVE);
- + temp->SetWalk(false);
- +
- + Map::PlayerList const& players = me->GetMap()->GetPlayers();
- + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
- + {
- + Player* player = itr->GetSource();
- + if (player && !player->IsGameMaster() && player->IsAlive())
- + {
- + if (player->GetVehicleBase())
- + {
- + // Reemplazar AddThreat por el sistema moderno de amenaza
- + temp->EngageWithTarget(player->GetVehicleBase());
- + temp->AI()->AttackStart(player->GetVehicleBase());
- + }
- + else
- + {
- + temp->EngageWithTarget(player);
- + temp->AI()->AttackStart(player);
- + }
- + break;
- + }
- + }
- +
- + if (riderAlso)
- + {
- + if (temp->GetVehicleKit() && temp->GetVehicleKit()->GetPassenger(SEAT_ID_0))
- + {
- + if (Creature* rider = temp->GetVehicleKit()->GetPassenger(SEAT_ID_0)->ToCreature())
- + {
- + rider->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC);
- + rider->SetWalk(false);
- + rider->SetReactState(REACT_AGGRESSIVE);
- + }
- + }
- + }
- + }
- +
- + void AttackStart(Unit* who) override
- + {
- + ScriptedAI::AttackStart(who);
- + if (me->HasUnitState(UNIT_STATE_MELEE_ATTACKING))
- + {
- + me->ClearUnitState(UNIT_STATE_MELEE_ATTACKING);
- + me->SendMeleeAttackStop(who);
- + }
- + }
- +
- + void UpdateAI(uint32 uiDiff) override
- + {
- + events.Update(uiDiff);
- +
- + while (uint32 eventId = events.ExecuteEvent())
- + {
- + switch (eventId)
- + {
- + case EVENT_CHEER_RND:
- + if (!me->HasNpcFlag(UNIT_NPC_FLAG_GOSSIP) && !me->HasUnitState(UNIT_STATE_MOVING) && !me->HasAura(66804))
- + {
- + // Every 2 minutes a random player is being cheered by his/her race's spectators
- + // cheer should only occur during fights
- + Map::PlayerList const& pList = me->GetMap()->GetPlayers();
- + // Player list is always in the same order so we must "randomize" it
- + if (!pList.isEmpty())
- + {
- + uint32 rand = urand(0, pList.getSize() - 1);
- + for (Map::PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr)
- + {
- + if (rand == 0)
- + {
- + Player* plr = itr->GetSource();
- + if (plr && !plr->IsGameMaster() && plr->IsAlive())
- + {
- + // 50% chance for race cheering at you or faction cheering at you
- + uint32 raceId = plr->GetRace();
- + uint32 factionEntry = (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) ? NPC_SPECTATOR_ALLIANCE : NPC_SPECTATOR_HORDE;
- + uint32 spectatorEntry = urand(0, 1) ? SpectatorData[raceId] : factionEntry;
- +
- + if (Creature* spectator = me->FindNearestCreature(spectatorEntry, 200.0f))
- + spectator->AI()->Talk(EMOTE_SPECTATOR_CHEER, plr);
- + break;
- + }
- + else
- + continue;
- + }
- + else
- + --rand;
- + }
- + }
- + }
- + events.ScheduleEvent(EVENT_CHEER_RND, 120s);
- + break;
- + // Phases below happen in Grand Champions encounter
- + case EVENT_INTRODUCE:
- + {
- + // Introducing players to spectators
- + bool foundPlr = false;
- + Map::PlayerList const& players = me->GetMap()->GetPlayers();
- + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
- + {
- + Player* player = itr->GetSource();
- +
- + if (player->IsGameMaster() || !player->IsAlive())
- + continue;
- +
- + GuidList::iterator i = std::find(PlayerEventList.begin(), PlayerEventList.end(), player->GetGUID());
- + if (i != PlayerEventList.end())
- + continue;
- +
- + // player has not been yet introduced
- + uint32 x = PlayerEventList.size();
- + if (x < 5 && IntroducePlrTxt[x])
- + Talk(IntroducePlrTxt[x], player);
- + else
- + continue; // no text found, too many players?
- +
- + uint32 raceId = player->GetRace();
- + if (Creature* spectator = me->FindNearestCreature(SpectatorData[raceId], 200.0f))
- + spectator->AI()->Talk(EMOTE_SPECTATOR_CHEER, player);
- +
- + foundPlr = true;
- + PlayerEventList.push_back(player->GetGUID());
- + NextStep(7000, false, 0, EVENT_INTRODUCE);
- + break;
- + }
- + // All players introduced, moving on
- + if (!foundPlr)
- + NextStep(16000, true, eventId);
- + break;
- + }
- + case EVENT_CHAT_1:
- + if (Creature* tirion = instance->GetCreature(DATA_TIRION))
- + tirion->AI()->Talk(SAY_TIRION_INTRO_1);
- + NextStep(8000, true, eventId);
- + break;
- + case EVENT_CHAT_2:
- + // Tirion gets interrupted by Varian Wrynn or Garrosh Hellscream
- + if (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- + {
- + if (Creature* varian = instance->GetCreature(DATA_VARIAN))
- + varian->AI()->Talk(SAY_VARIAN_INTRO_1);
- + }
- + else
- + {
- + if (Creature* garrosh = instance->GetCreature(DATA_GARROSH))
- + garrosh->AI()->Talk(SAY_GARROSH_INTRO_1);
- + }
- + NextStep(6000, true, eventId);
- + break;
- + case EVENT_CHAT_3:
- + if (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- + {
- + if (Creature* jaina = instance->GetCreature(DATA_JAINA))
- + jaina->AI()->Talk(SAY_JAINA_INTRO_1);
- + }
- + else
- + {
- + if (Creature* thrall = instance->GetCreature(DATA_THRALL))
- + thrall->AI()->Talk(SAY_THRALL_INTRO_1);
- + }
- + NextStep(5000, true, eventId);
- + break;
- + case EVENT_CHAT_4:
- + if (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- + {
- + if (Creature* garrosh = instance->GetCreature(DATA_GARROSH))
- + garrosh->AI()->Talk(SAY_GARROSH_INTRO_2);
- + }
- + else
- + {
- + if (Creature* varian = instance->GetCreature(DATA_VARIAN))
- + varian->AI()->Talk(SAY_VARIAN_INTRO_2);
- + }
- + NextStep(8000, true, eventId);
- + break;
- + case EVENT_CHAT_5:
- + if (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- + {
- + if (Creature* thrall = instance->GetCreature(DATA_THRALL))
- + thrall->AI()->Talk(SAY_THRALL_INTRO_2);
- + }
- + else
- + {
- + if (Creature* jaina = instance->GetCreature(DATA_JAINA))
- + jaina->AI()->Talk(SAY_JAINA_INTRO_2);
- + }
- + NextStep(5000, true, eventId);
- + break;
- + case EVENT_CHAT_6:
- + if (Creature* tirion = instance->GetCreature(DATA_TIRION))
- + tirion->AI()->Talk(SAY_TIRION_INTRO_2);
- + NextStep(6000, true, eventId);
- + break;
- + case EVENT_SUMMON_1:
- + // Summoning first champion
- + DoSummonNextGrandChampion();
- + me->SetFacingTo(gateOrientation);
- + NextStep(2000, true, eventId);
- + break;
- + case EVENT_OPEN_DOOR_1:
- + // Opening doors
- + instance->HandleGameObject(instance->GetGuidData(DATA_MAIN_GATE), true);
- + NextStep(500, true, eventId);
- + break;
- + case EVENT_INTRODUCE_BOSS_1:
- + // Introducing first champion
- + IntroduceChampion();
- + NextStep(7500, true, eventId);
- + break;
- + case EVENT_CLOSE_DOOR_1:
- + // Closing door
- + instance->HandleGameObject(instance->GetGuidData(DATA_MAIN_GATE), false);
- + NextStep(8000, true, eventId);
- + break;
- + case EVENT_SUMMON_2:
- + // Summoning second champion
- + DoSummonNextGrandChampion();
- + NextStep(2000, true, eventId);
- + break;
- + case EVENT_OPEN_DOOR_2:
- + // Opening doors
- + instance->HandleGameObject(instance->GetGuidData(DATA_MAIN_GATE), true);
- + NextStep(500, true, eventId);
- + break;
- + case EVENT_INTRODUCE_BOSS_2:
- + // Introducing second champion
- + IntroduceChampion();
- + NextStep(7500, true, eventId);
- + break;
- + case EVENT_CLOSE_DOOR_2:
- + // Closing door
- + instance->HandleGameObject(instance->GetGuidData(DATA_MAIN_GATE), false);
- + NextStep(8000, true, eventId);
- + break;
- + case EVENT_SUMMON_3:
- + // Summoning third and final champion
- + DoSummonNextGrandChampion();
- + NextStep(2000, true, eventId);
- + break;
- + case EVENT_OPEN_DOOR_3:
- + // Opening doors
- + instance->HandleGameObject(instance->GetGuidData(DATA_MAIN_GATE), true);
- + NextStep(500, true, eventId);
- + break;
- + case EVENT_INTRODUCE_BOSS_3:
- + // Introducing third champion
- + IntroduceChampion();
- + NextStep(9500, true, eventId);
- + break;
- + case EVENT_CLOSE_DOOR_3:
- + // Closing door and announcer walks to the gate
- + instance->HandleGameObject(instance->GetGuidData(DATA_MAIN_GATE), false);
- + me->GetMotionMaster()->MovePoint(POINT_ENCOUNTER_1_WAIT, announcerEncounterPos);
- + break;
- + case EVENT_WAIT_1:
- + // Lesser champions are moving to their respective positions
- + NextStep(500, true, eventId);
- + break;
- + case EVENT_FACING:
- + // Correcting facing
- + me->SetFacingTo(centerOrientation);
- + NextStep(5000, true, eventId);
- + break;
- + case EVENT_CHAT_7:
- + if (Creature* tirion = instance->GetCreature(DATA_TIRION))
- + tirion->AI()->Talk(SAY_TIRION_INTRO_3);
- + NextStep(2000, true, eventId);
- + break;
- + case EVENT_AGGRO_1:
- + // First wave of lesser champions aggroes
- + for (GuidList::const_iterator itr = Champion1List.begin(); itr != Champion1List.end(); ++itr)
- + {
- + if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr))
- + EnterAggressiveMode(summon);
- + }
- + break;
- + case EVENT_CHAT_8:
- + // Tirion congratulates players
- + if (Creature* tirion = instance->GetCreature(DATA_TIRION))
- + tirion->AI()->Talk(SAY_TIRION_OUTRO_1);
- + break;
- + // Phases below happen only if roleplaying event is skipped
- + case EVENT_CHAT_9:
- + if (Creature* tirion = instance->GetCreature(DATA_TIRION))
- + tirion->AI()->Talk(SAY_TIRION_INTRO_2);
- + NextStep(3000, true, eventId);
- + break;
- + case EVENT_SUMMON_1_SKIP:
- + // Summoning first champion
- + DoSummonNextGrandChampion(true);
- + NextStep(2000, true, eventId);
- + break;
- + case EVENT_SUMMON_2_SKIP:
- + // Summoning second champion
- + DoSummonNextGrandChampion(true);
- + NextStep(2000, true, eventId);
- + break;
- + case EVENT_SUMMON_3_SKIP:
- + // Summoning third champion
- + DoSummonNextGrandChampion(true);
- + break;
- + // Phases below happen in Argent Champion encounter
- + case EVENT_MOVE_MIDDLE:
- + // Moves into middle of arena
- + me->GetMotionMaster()->MovePoint(POINT_START_ARGENT_CHAMP, me->GetHomePosition());
- + break;
- + case EVENT_SPAWN_ALL:
- + // Spawns 9 adds and boss
- + // Generating final positions for monks and other 2 adds follow the monk
- + // when monk is in final position, then final positions are generated for other adds
- + if (me->SummonCreature(uiArgentChampion, SpawnPosition))
- + {
- + for (uint8 i = 0; i < 3; ++i)
- + {
- + if (Creature* pMonk = me->SummonCreature(NPC_ARGENT_MONK, SpawnPosition))
- + {
- + pMonk->AI()->SetData(i, 0);
- + if (Creature* pLightwielder = me->SummonCreature(NPC_ARGENT_LIGHWIELDER, SpawnPosition))
- + {
- + pLightwielder->AI()->SetData(i, 0);
- + pLightwielder->GetMotionMaster()->MoveFollow(pMonk, 2.0f, float(M_PI));
- + }
- + if (Creature* pPriestess = me->SummonCreature(NPC_PRIESTESS, SpawnPosition))
- + {
- + pPriestess->AI()->SetData(i, 0);
- + pPriestess->GetMotionMaster()->MoveFollow(pMonk, 2.0f, float(M_PI) / 2);
- + }
- + }
- + }
- + }
- + NextStep(2000, true, eventId);
- + break;
- + case EVENT_OPEN_DOOR_4:
- + // Opening doors
- + instance->HandleGameObject(instance->GetGuidData(DATA_MAIN_GATE), true);
- + NextStep(2000, true, eventId);
- + break;
- + case EVENT_INTRODUCE_BOSS_4:
- + // Introducing Argent Champion to spectators
- + // Horde and alliance spectators cheer for Argent Champion
- + if (Creature* pBoss = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_ARGENT_CHAMPION)))
- + {
- + if (pBoss->GetEntry() == NPC_EADRIC)
- + Talk(SAY_INTRO_2_E, pBoss);
- + else
- + Talk(SAY_INTRO_2_P, pBoss);
- + if (Creature* aSpectator = me->FindNearestCreature(NPC_SPECTATOR_ALLIANCE, 200.0f))
- + aSpectator->AI()->Talk(EMOTE_SPECTATOR_CHEER, pBoss);
- + if (Creature* hSpectator = me->FindNearestCreature(NPC_SPECTATOR_HORDE, 200.0f))
- + hSpectator->AI()->Talk(EMOTE_SPECTATOR_CHEER, pBoss);
- + }
- + NextStep(10000, true, eventId);
- + break;
- + case EVENT_ARGENT_BOSS_WALK:
- + // Argent Champion starts walking to arena
- + if (Creature* pBoss = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_ARGENT_CHAMPION)))
- + {
- + pBoss->SetWalk(true);
- + pBoss->GetMotionMaster()->MovePoint(0, 746.71f, 661.4f, 411.7f);
- + }
- + break;
- + case EVENT_GO_TO_ARGENT_BOSS:
- + // Announcer starts walking to Argent Champion
- + instance->HandleGameObject(instance->GetGuidData(DATA_MAIN_GATE), false);
- + me->GetMotionMaster()->MovePoint(POINT_ENCOUNTER_2_WAIT_1, 746.73f, 653.93f, 411.6f);
- + NextStep(2000, true, eventId);
- + break;
- + case EVENT_CHAT_10:
- + // Argent Champion talks
- + if (Creature* pBoss = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_ARGENT_CHAMPION)))
- + {
- + if (pBoss->GetEntry() == NPC_EADRIC)
- + {
- + pBoss->AI()->Talk(SAY_EADRIC_INTRO_1, me);
- + }
- + else
- + {
- + pBoss->AI()->Talk(SAY_PALETRESS_INTRO_1, me);
- + NextStep(6000, true, eventId);
- + }
- + }
- + break;
- + case EVENT_CHAT_11:
- + // Paletress talks twice
- + if (Creature* pBoss = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_ARGENT_CHAMPION)))
- + {
- + if (pBoss->GetEntry() == NPC_PALETRESS)
- + pBoss->AI()->Talk(SAY_PALETRESS_INTRO_2, me);
- + }
- + break;
- + case EVENT_WAIT_2:
- + // After announcer reached position in front of Champion,
- + // he goes to encounter position
- + me->GetMotionMaster()->MovePoint(POINT_ENCOUNTER_2_WAIT_2, announcerEncounterPos);
- + break;
- + case EVENT_CHAT_12:
- + if (Creature* tirion = instance->GetCreature(DATA_TIRION))
- + tirion->AI()->Talk(SAY_TIRION_INTRO_4);
- + break;
- + // Phases below happen in The Black Knight encounter
- + case EVENT_STEP_FORWARD:
- + // Stepping forward
- + me->GetMotionMaster()->MovePoint(POINT_ENCOUNTER_3_WAIT, 743.65f, 627.6f, 411.17f);
- + break;
- + case EVENT_CHAT_13:
- + // Tirion congratulates champions and meanwhile Black Knight appears
- + if (Creature* tirion = instance->GetCreature(DATA_TIRION))
- + tirion->AI()->Talk(SAY_TIRION_INTRO_5);
- + me->SummonCreature(VEHICLE_BLACK_KNIGHT, 780.69f, 669.61f, 463.66f, 3.77f);
- + NextStep(6000, true, eventId);
- + break;
- + case EVENT_FACING_1:
- + // Announcer turns towards Black Knight
- + if (Creature* knight = instance->GetCreature(DATA_BLACK_KNIGHT))
- + me->SetFacingToObject(knight);
- + NextStep(2000, true, eventId);
- + break;
- + case EVENT_CHAT_14:
- + // Announcer notifies everyone that something is near the rafters
- + if (Creature* knight = instance->GetCreature(DATA_BLACK_KNIGHT))
- + Talk(SAY_INTRO_3, knight);
- + NextStep(1000, true, eventId);
- + break;
- + case EVENT_START_PATH:
- + // Black Knight starts to fly down
- + if (Creature* knightVehicle = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BLACK_KNIGHT_VEHICLE)))
- + {
- + knightVehicle->AI()->SetData(1, 0);
- + // We start attacking Black Knight without combat movement
- + // so we keep facing him all the time
- + if (knightVehicle->GetVehicleKit() && knightVehicle->GetVehicleKit()->GetPassenger(SEAT_ID_0))
- + AttackStart(knightVehicle->GetVehicleKit()->GetPassenger(SEAT_ID_0));
- + }
- + break;
- + case EVENT_CHAT_15:
- + // Black Knight exits his vehicle and talks
- + if (Creature* knight = instance->GetCreature(DATA_BLACK_KNIGHT))
- + {
- + knight->AI()->Talk(SAY_KNIGHT_INTRO_1, me);
- + knight->ExitVehicle();
- + knight->SetWalk(true);
- + knight->GetMotionMaster()->MovePoint(0, 747.79f, 632.49f, 411.41f);
- + }
- + break;
- + case EVENT_FACING_2:
- + // Black Knight corrects facing and we're stopping attacking
- + if (Creature* knight = instance->GetCreature(DATA_BLACK_KNIGHT))
- + knight->SetFacingToObject(me);
- + me->AttackStop();
- + me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- + NextStep(1500, true, eventId);
- + break;
- + case EVENT_STUN_ANNOUNCER:
- + // Announcer gets strangulated
- + if (Creature* knight = instance->GetCreature(DATA_BLACK_KNIGHT))
- + knight->CastSpell(me, SPELL_DEATHS_RESPITE);
- + NextStep(3000, true, eventId);
- + break;
- + case EVENT_CHAT_16:
- + if (Creature* tirion = instance->GetCreature(DATA_TIRION))
- + tirion->AI()->Talk(SAY_TIRION_INTRO_6, me);
- + NextStep(1000, true, eventId);
- + break;
- + case EVENT_KNOCK_ANNOUNCER:
- + // Announcer gets pushed to death and Black Knight's vehicle flies away
- + if (Creature* knight = instance->GetCreature(DATA_BLACK_KNIGHT))
- + knight->CastSpell(me, SPELL_DEATHS_PUSH);
- + if (Creature* knightVehicle = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BLACK_KNIGHT_VEHICLE)))
- + knightVehicle->AI()->SetData(2, 0);
- + NextStep(3000, true, eventId);
- + break;
- + case EVENT_CHAT_17:
- + // Black Knight moves to center
- + me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- + if (Creature* knight = instance->GetCreature(DATA_BLACK_KNIGHT))
- + {
- + knight->AI()->Talk(SAY_KNIGHT_INTRO_2, me);
- + knight->GetMotionMaster()->MovePoint(1, 747.21f, 622.75f, 411.42f);
- + }
- + NextStep(14000, true, eventId);
- + break;
- + case EVENT_CHAT_18:
- + if (Creature* knight = instance->GetCreature(DATA_BLACK_KNIGHT))
- + knight->AI()->Talk(SAY_KNIGHT_INTRO_3, me);
- + NextStep(3000, true, eventId);
- + break;
- + case EVENT_AGGRO_2:
- + // Entering aggressive
- + if (Creature* knight = instance->GetCreature(DATA_BLACK_KNIGHT))
- + {
- + knight->SetWalk(false);
- + knight->SetHomePosition(knight->GetPosition());
- + knight->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC);
- + knight->SetReactState(REACT_AGGRESSIVE);
- + }
- + NextStep(1000, true, eventId);
- + break;
- + case EVENT_CHAT_19:
- + // Varian or Garrosh tells players to kill him
- + if (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- + {
- + if (Creature* varian = instance->GetCreature(DATA_VARIAN))
- + varian->AI()->Talk(SAY_VARIAN_INTRO_3, me);
- + }
- + else
- + {
- + if (Creature* garrosh = instance->GetCreature(DATA_GARROSH))
- + garrosh->AI()->Talk(SAY_GARROSH_INTRO_3, me);
- + }
- + break;
- + case EVENT_CHAT_20:
- + // After Black Knight is dead, a small outro event happens
- + if (Creature* tirion = instance->GetCreature(DATA_TIRION))
- + tirion->AI()->Talk(SAY_TIRION_OUTRO_2, me);
- + NextStep(6000, true, eventId);
- + break;
- + case EVENT_CHAT_21:
- + if (Creature* tirion = instance->GetCreature(DATA_TIRION))
- + tirion->AI()->Talk(SAY_TIRION_OUTRO_3, me);
- + NextStep(7000, true, eventId);
- + break;
- + case EVENT_CHAT_22:
- + if (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- + {
- + if (Creature* varian = instance->GetCreature(DATA_VARIAN))
- + varian->AI()->Talk(SAY_VARIAN_OUTRO_1, me);
- + }
- + else
- + {
- + if (Creature* thrall = instance->GetCreature(DATA_THRALL))
- + thrall->AI()->Talk(SAY_THRALL_OUTRO_1, me);
- + }
- + break;
- + default:
- + break;
- + }
- + }
- +
- + if (!UpdateVictim())
- + return;
- +
- + // No combat for announcer
- + }
- +
- + bool OnGossipHello(Player* player) override
- + {
- + InstanceScript* instance = me->GetInstanceScript();
- + if (instance)
- + {
- + if (player->IsGameMaster())
- + {
- + // Gamemaster mode on you can choose which encounter you start
- + // you can't though do Grand Champions encounter more than once per instance ID
- + // other encounters you can do as many times as you like
- + if ((instance->GetBossState(DATA_GRAND_CHAMPIONS) == NOT_STARTED) &&
- + (instance->GetBossState(DATA_ARGENT_CHALLENGE) == NOT_STARTED) &&
- + (instance->GetBossState(DATA_BLACK_KNIGHT) == NOT_STARTED))
- + {
- + AddGossipItemFor(player, GOSSIP_ICON_CHAT, "[GM] Start Grand Champions encounter, unskipped roleplaying", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
- + AddGossipItemFor(player, GOSSIP_ICON_CHAT, "[GM] Start Grand Champions encounter, skipped roleplaying", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- + }
- + if (instance->GetBossState(DATA_ARGENT_CHALLENGE) == NOT_STARTED)
- + {
- + AddGossipItemFor(player, GOSSIP_ICON_CHAT, "[GM] Start Eadric the Pure encounter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
- + AddGossipItemFor(player, GOSSIP_ICON_CHAT, "[GM] Start Argent Confessor Paletress encounter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
- + }
- + if (instance->GetBossState(DATA_BLACK_KNIGHT) == NOT_STARTED)
- + AddGossipItemFor(player, GOSSIP_ICON_CHAT, "[GM] Start The Black Knight encounter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
- + SendGossipMenuFor(player, 1, me->GetGUID());
- + }
- + else if ((instance->GetBossState(DATA_GRAND_CHAMPIONS) == NOT_STARTED) && player->GetVehicleBase())
- + {
- + // If Grand Champions encounter hasn't been started and the player is mounted
- + AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_START_EVENT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
- + // Patch 3.2.2: "There is now an option in the herald's dialogue to skip the introductory scripted scene if everyone in the party has already seen it."
- + if (HasAllSeenEvent(player))
- + AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_START_EVENT_SKIP, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- + SendGossipMenuFor(player, GOSSIP_TEXT_FIRST_BOSS, me->GetGUID());
- + }
- + else if ((instance->GetBossState(DATA_GRAND_CHAMPIONS) == NOT_STARTED) && !player->GetVehicleBase())
- + {
- + // If Grand Champions encounter hasn't been started and the player is not mounted
- + if (player->GetTeam() == HORDE)
- + SendGossipMenuFor(player, GOSSIP_TEXT_UNMOUNTED_H, me->GetGUID());
- + else
- + SendGossipMenuFor(player, GOSSIP_TEXT_UNMOUNTED_A, me->GetGUID());
- + }
- + else if (instance->GetBossState(DATA_GRAND_CHAMPIONS) == DONE && (instance->GetBossState(DATA_ARGENT_CHALLENGE) == NOT_STARTED))
- + {
- + // If Grand Champions encounter is done and Eadric the Pure nor Argent Confessor Paletress encounters have been started
- + AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_START_EVENT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- + SendGossipMenuFor(player, GOSSIP_TEXT_SECOND_BOSS, me->GetGUID());
- + }
- + else if (instance->GetBossState(DATA_ARGENT_CHALLENGE) == DONE && (instance->GetBossState(DATA_BLACK_KNIGHT) == NOT_STARTED))
- + {
- + // If Grand Champions, Eadric the Pure and Argent Confessor Paletress encounters are all done but Black Knight encounter has not been started
- + AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_START_EVENT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- + SendGossipMenuFor(player, GOSSIP_TEXT_THIRD_BOSS, me->GetGUID());
- + }
- + }
- + return true;
- + }
- +
- + bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
- + {
- + uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
- + ClearGossipMenuFor(player);
- + CloseGossipMenuFor(player);
- + switch (action)
- + {
- + case GOSSIP_ACTION_INFO_DEF + 1:
- + StartEncounter();
- + break;
- + case GOSSIP_ACTION_INFO_DEF + 2:
- + StartEncounter(true);
- + break;
- + case GOSSIP_ACTION_INFO_DEF + 3:
- + me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
- + uiArgentChampion = NPC_EADRIC;
- + DoStartArgentChampionEncounter();
- + break;
- + case GOSSIP_ACTION_INFO_DEF + 4:
- + me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
- + uiArgentChampion = NPC_PALETRESS;
- + DoStartArgentChampionEncounter();
- + break;
- + case GOSSIP_ACTION_INFO_DEF + 5:
- + me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
- + DoStartBlackKnight();
- + break;
- + default:
- + break;
- + }
- + return true;
- + }
- +
- + bool HasAllSeenEvent(Player* player)
- + {
- + if (!player)
- + return false;
- +
- + if (player->IsGameMaster())
- + return true;
- +
- + bool seen = true;
- + Map::PlayerList const& players = player->GetMap()->GetPlayers();
- + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
- + {
- + if (Player const* plr = itr->GetSource())
- + {
- + // if everyone from your group have completed one of the Trial of the Champion achievements, you have option to skip the event
- + // maybe not the correct way to do it but I couldn't figure out better
- + if (!plr->HasAchieved(4298) /* Heroic ToC (alliance) */ && !plr->HasAchieved(3778) /* Normal ToC (horde) */ && !plr->HasAchieved(4297) /* Heroic ToC (horde) */ && !plr->HasAchieved(4296) /* Normal ToC (alliance) */)
- + {
- + seen = false;
- + break;
- + }
- + }
- + }
- + return seen;
- + }
- + };
- +
- + CreatureAI* GetAI(Creature* creature) const override
- + {
- + return new npc_announcer_toc5AI(creature);
- + }
- +};
- +
- +void AddSC_trial_of_the_champion()
- +{
- + new npc_announcer_toc5();
- +}
- diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.h b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.h
- dissimilarity index 74%
- index 2da7435e32..0b50d18fac 100644
- --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.h
- +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.h
- @@ -1,139 +1,297 @@
- -/*
- - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
- - *
- - * 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, see <http://www.gnu.org/licenses/>.
- - */
- -
- -#ifndef DEF_TOC_H
- -#define DEF_TOC_H
- -
- -#include "CreatureAIImpl.h"
- -
- -#define ToCScriptName "instance_trial_of_the_champion"
- -#define DataHeader "TC"
- -
- -enum TCData
- -{
- - BOSS_GRAND_CHAMPIONS = 0,
- - BOSS_ARGENT_CHALLENGE_E = 1,
- - BOSS_ARGENT_CHALLENGE_P = 2,
- - BOSS_BLACK_KNIGHT = 3,
- -
- - DATA_MOVEMENT_DONE,
- - DATA_LESSER_CHAMPIONS_DEFEATED,
- - DATA_START,
- - DATA_IN_POSITION,
- - DATA_ARGENT_SOLDIER_DEFEATED
- -};
- -
- -enum TCData64
- -{
- - DATA_ANNOUNCER,
- - DATA_MAIN_GATE,
- -
- - DATA_GRAND_CHAMPION_VEHICLE_1,
- - DATA_GRAND_CHAMPION_VEHICLE_2,
- - DATA_GRAND_CHAMPION_VEHICLE_3,
- -
- - DATA_GRAND_CHAMPION_1,
- - DATA_GRAND_CHAMPION_2,
- - DATA_GRAND_CHAMPION_3
- -};
- -
- -enum TCCreatureIds
- -{
- - // Horde Champions
- - NPC_MOKRA = 35572,
- - NPC_ERESSEA = 35569,
- - NPC_RUNOK = 35571,
- - NPC_ZULTORE = 35570,
- - NPC_VISCERI = 35617,
- -
- - // Alliance Champions
- - NPC_JACOB = 34705,
- - NPC_AMBROSE = 34702,
- - NPC_COLOSOS = 34701,
- - NPC_JAELYNE = 34657,
- - NPC_LANA = 34703,
- -
- - NPC_EADRIC = 35119,
- - NPC_PALETRESS = 34928,
- -
- - NPC_ARGENT_LIGHWIELDER = 35309,
- - NPC_ARGENT_MONK = 35305,
- - NPC_PRIESTESS = 35307,
- -
- - NPC_BLACK_KNIGHT = 35451,
- -
- - NPC_RISEN_JAEREN = 35545,
- - NPC_RISEN_ARELAS = 35564,
- -
- - NPC_JAEREN = 35004,
- - NPC_ARELAS = 35005
- -};
- -
- -enum TCGameObjects
- -{
- - GO_MAIN_GATE = 195647,
- -
- - GO_CHAMPIONS_LOOT = 195709,
- - GO_CHAMPIONS_LOOT_H = 195710,
- -
- - GO_EADRIC_LOOT = 195374,
- - GO_EADRIC_LOOT_H = 195375,
- -
- - GO_PALETRESS_LOOT = 195323,
- - GO_PALETRESS_LOOT_H = 195324
- -};
- -
- -enum TCVehicles
- -{
- - //Grand Champions Alliance Vehicles
- - VEHICLE_MARSHAL_JACOB_ALERIUS_MOUNT = 35637,
- - VEHICLE_AMBROSE_BOLTSPARK_MOUNT = 35633,
- - VEHICLE_COLOSOS_MOUNT = 35768,
- - VEHICLE_EVENSONG_MOUNT = 34658,
- - VEHICLE_LANA_STOUTHAMMER_MOUNT = 35636,
- - //Faction Champions (ALLIANCE)
- - VEHICLE_DARNASSIA_NIGHTSABER = 33319,
- - VEHICLE_EXODAR_ELEKK = 33318,
- - VEHICLE_STORMWIND_STEED = 33217,
- - VEHICLE_GNOMEREGAN_MECHANOSTRIDER = 33317,
- - VEHICLE_IRONFORGE_RAM = 33316,
- - //Grand Champions Horde Vehicles
- - VEHICLE_MOKRA_SKILLCRUSHER_MOUNT = 35638,
- - VEHICLE_ERESSEA_DAWNSINGER_MOUNT = 35635,
- - VEHICLE_RUNOK_WILDMANE_MOUNT = 35640,
- - VEHICLE_ZUL_TORE_MOUNT = 35641,
- - VEHICLE_DEATHSTALKER_VESCERI_MOUNT = 35634,
- - //Faction Champions (HORDE)
- - VEHICLE_FORSAKE_WARHORSE = 33324,
- - VEHICLE_THUNDER_BLUFF_KODO = 33322,
- - VEHICLE_ORGRIMMAR_WOLF = 33320,
- - VEHICLE_SILVERMOON_HAWKSTRIDER = 33323,
- - VEHICLE_DARKSPEAR_RAPTOR = 33321,
- -
- - VEHICLE_ARGENT_WARHORSE = 35644,
- - VEHICLE_ARGENT_BATTLEWORG = 36558,
- -
- - VEHICLE_BLACK_KNIGHT = 35491
- -};
- -
- -template <class AI, class T>
- -inline AI* GetTrialOfTheChampionAI(T* obj)
- -{
- - return GetInstanceAI<AI>(obj, ToCScriptName);
- -}
- -
- -#endif
- +/*
- + * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
- + * 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, see <http://www.gnu.org/licenses/>.
- + */
- +
- +#ifndef TRIAL_OF_CHAMPION_H_
- +#define TRIAL_OF_CHAMPION_H_
- +
- +#define ToCScriptName "instance_trial_of_the_champion"
- +#define DataHeader "TC"
- +
- +Position const LesserChampLoc[18] =
- +{
- + // Horde Lesser Champions
- + { 715.12f, 612.69f, 411.77f },
- + { 715.97f, 618.20f, 411.56f },
- + { 716.55f, 623.53f, 411.79f },
- + { 717.10f, 627.32f, 411.83f },
- + { 717.91f, 632.39f, 411.87f },
- + { 718.54f, 636.32f, 411.89f },
- + { 718.82f, 641.95f, 411.90f },
- + { 719.28f, 645.82f, 411.91f },
- + { 719.86f, 650.74f, 411.92f },
- + // Alliance Lesser Champions
- + { 774.66f, 600.71f, 411.71f },
- + { 775.31f, 604.16f, 411.75f },
- + { 775.96f, 607.60f, 411.76f },
- + { 776.95f, 612.87f, 411.76f },
- + { 777.60f, 616.31f, 411.76f },
- + { 778.22f, 619.64f, 411.71f },
- + { 779.11f, 624.34f, 411.83f },
- + { 779.69f, 627.44f, 411.87f },
- + { 780.34f, 630.89f, 411.89f }
- +};
- +
- +Position const GrandChampFinalLoc[6] =
- +{
- + // Horde Grand Champions
- + { 706.49f, 618.48f, 411.88f },
- + { 709.00f, 633.73f, 411.92f },
- + { 709.17f, 646.25f, 412.39f },
- + // Alliance Grand Champions
- + { 780.96f, 603.13f, 411.84f },
- + { 783.76f, 615.98f, 411.84f },
- + { 785.75f, 625.89f, 411.89f }
- +};
- +
- +Position const announcerEncounterPos = { 732.5243f, 663.007f, 412.3932f };
- +Position const announcerWaitPos = { 742.7739f, 629.849f, 411.1722f };
- +Position const bossExitPos = { 746.776f, 665.221f, 411.743f, 4.82f };
- +
- +float const hordeOrientation = 6.175f; // Facing towards alliance spectators
- +float const allianceOrientation = 3.114f; // Facing towards horde spectators
- +float const gateOrientation = 1.582f; // Facing towards main gate
- +float const centerOrientation = 4.714f; // Facing towards the center of arena
- +
- +enum DataTypes
- +{
- + // Encounter States/Boss GUIDs
- + DATA_GRAND_CHAMPIONS,
- + DATA_ARGENT_CHALLENGE,
- + DATA_BLACK_KNIGHT,
- +
- + MAX_ENCOUNTER,
- +
- + // Additional Data
- + DATA_ANNOUNCER,
- + DATA_MAIN_GATE,
- + DATA_TIRION,
- + DATA_VARIAN,
- + DATA_JAINA,
- + DATA_GARROSH,
- + DATA_THRALL,
- +
- + DATA_CHAMPION_S_CACHE,
- + DATA_EADRIC_S_CACHE,
- + DATA_CONFESSOR_S_CACHE,
- +
- + DATA_TEAM_IN_INSTANCE,
- +
- + DATA_LESSER_CHAMPIONS_PREPARE,
- + DATA_LESSER_CHAMPIONS_DEFEATED,
- + DATA_START,
- + DATA_REMOVE_VEHICLES,
- + DATA_GRAND_CHAMPIONS_DONE,
- + DATA_ARGENT_CHAMPION_PREPARE,
- + DATA_ARGENT_SOLDIER_DEFEATED,
- + DATA_BLACK_KNIGHT_PREPARE,
- + DATA_BLACK_KNIGHT_PRECAST,
- + DATA_BLACK_KNIGHT_DONE,
- +
- + DATA_GRAND_CHAMPION_VEHICLE_1,
- + DATA_GRAND_CHAMPION_VEHICLE_2,
- + DATA_GRAND_CHAMPION_VEHICLE_3,
- +
- + DATA_GRAND_CHAMPION_1,
- + DATA_GRAND_CHAMPION_2,
- + DATA_GRAND_CHAMPION_3,
- +
- + DATA_ARGENT_CHAMPION,
- +
- + DATA_BLACK_KNIGHT_VEHICLE
- +};
- +
- +enum Creatures
- +{
- + // Horde Champions
- + NPC_MOKRA = 35572,
- + NPC_ERESSEA = 35569,
- + NPC_RUNOK = 35571,
- + NPC_ZULTORE = 35570,
- + NPC_VISCERI = 35617,
- +
- + // Alliance Champions
- + NPC_JACOB = 34705,
- + NPC_AMBROSE = 34702,
- + NPC_COLOSOS = 34701,
- + NPC_JAELYNE = 34657,
- + NPC_LANA = 34703,
- +
- + // Horde Lesser Champions
- + NPC_ORGRIMMAR_CHAMPION = 35314,
- + NPC_SILVERMOON_CHAMPION = 35326,
- + NPC_THUNDER_BLUFF_CHAMPION = 35325,
- + NPC_SEN_JIN_CHAMPION = 35323,
- + NPC_UNDERCITY_CHAMPION = 35327,
- +
- + // Alliance Lesser Champions
- + NPC_STORMWIND_CHAMPION = 35328,
- + NPC_GNOMEREGAN_CHAMPION = 35331,
- + NPC_EXODAR_CHAMPION = 35330,
- + NPC_DARNASSUS_CHAMPION = 35332,
- + NPC_IRONFORGE_CHAMPION = 35329,
- +
- + // Argent Champions
- + NPC_EADRIC = 35119,
- + NPC_PALETRESS = 34928,
- +
- + NPC_ARGENT_LIGHWIELDER = 35309,
- + NPC_ARGENT_MONK = 35305,
- + NPC_PRIESTESS = 35307,
- +
- + // Memories
- + NPC_MEMORY_HOGGER = 34942,
- + NPC_MEMORY_VANCLEEF = 35028,
- + NPC_MEMORY_MUTANUS = 35029,
- + NPC_MEMORY_HEROD = 35030,
- + NPC_MEMORY_LUCIFRON = 35031,
- + NPC_MEMORY_THUNDERAAN = 35032,
- + NPC_MEMORY_CHROMAGGUS = 35033,
- + NPC_MEMORY_HAKKAR = 35034,
- + NPC_MEMORY_VEKNILASH = 35036,
- + NPC_MEMORY_KALITHRESH = 35037,
- + NPC_MEMORY_MALCHEZAAR = 35038,
- + NPC_MEMORY_GRUUL = 35039,
- + NPC_MEMORY_VASHJ = 35040,
- + NPC_MEMORY_ARCHIMONDE = 35041,
- + NPC_MEMORY_ILLIDAN = 35042,
- + NPC_MEMORY_DELRISSA = 35043,
- + NPC_MEMORY_MURU = 35044,
- + NPC_MEMORY_INGVAR = 35045,
- + NPC_MEMORY_CYANIGOSA = 35046,
- + NPC_MEMORY_ECK = 35047,
- + NPC_MEMORY_ONYXIA = 35048,
- + NPC_MEMORY_HEIGAN = 35049,
- + NPC_MEMORY_IGNIS = 35050,
- + NPC_MEMORY_VEZAX = 35051,
- + NPC_MEMORY_ALGALON = 35052,
- +
- + // The Black Knight
- + NPC_BLACK_KNIGHT = 35451,
- +
- + NPC_RISEN_GHOUL = 35590,
- + NPC_RISEN_JAEREN = 35545,
- + NPC_RISEN_ARELAS = 35564,
- + NPC_DESECRATION_STALKER = 35614,
- +
- + // Announcers
- + NPC_JAEREN = 35004,
- + NPC_ARELAS = 35005,
- +
- + // Spectators
- + NPC_TIRION = 34996,
- + NPC_JAINA = 34992,
- + NPC_VARIAN = 34990,
- + NPC_THRALL = 34994,
- + NPC_GARROSH = 34995,
- + NPC_SPECTATOR_HORDE = 34883,
- + NPC_SPECTATOR_ALLIANCE = 34887,
- + NPC_SPECTATOR_HUMAN = 34900,
- + NPC_SPECTATOR_ORC = 34901,
- + NPC_SPECTATOR_TROLL = 34902,
- + NPC_SPECTATOR_TAUREN = 34903,
- + NPC_SPECTATOR_BELF = 34904,
- + NPC_SPECTATOR_UNDEAD = 34905,
- + NPC_SPECTATOR_DWARF = 34906,
- + NPC_SPECTATOR_DRAENEI = 34908,
- + NPC_SPECTATOR_NELF = 34909,
- + NPC_SPECTATOR_GNOME = 34910
- +};
- +
- +enum GameObjects
- +{
- + GO_MAIN_GATE = 195647,
- + GO_NORTH_PORTCULLIS = 195650,
- +
- + GO_CHAMPION_S_CACHE = 195709,
- + GO_CHAMPION_S_CACHE_H = 195710,
- +
- + GO_EADRIC_S_CACHE = 195374,
- + GO_EADRIC_S_CACHE_H = 195375,
- +
- + GO_CONFESSOR_S_CACHE = 195323,
- + GO_CONFESSOR_S_CACHE_H = 195324
- +};
- +
- +enum Vehicles
- +{
- + // Grand Champions Alliance Vehicles
- + VEHICLE_MARSHAL_JACOB_ALERIUS_MOUNT = 35637,
- + VEHICLE_AMBROSE_BOLTSPARK_MOUNT = 35633,
- + VEHICLE_COLOSOS_MOUNT = 35768,
- + VEHICLE_EVENSONG_MOUNT = 34658,
- + VEHICLE_LANA_STOUTHAMMER_MOUNT = 35636,
- +
- + // Grand Champions Horde Vehicles
- + VEHICLE_MOKRA_SKULLCRUSHER_MOUNT = 35638,
- + VEHICLE_ERESSEA_DAWNSINGER_MOUNT = 35635,
- + VEHICLE_RUNOK_WILDMANE_MOUNT = 35640,
- + VEHICLE_ZUL_TORE_MOUNT = 35641,
- + VEHICLE_DEATHSTALKER_VESCERI_MOUNT = 35634,
- +
- + // Player vehicles
- + VEHICLE_ARGENT_WARHORSE_COSMETIC = 35644,
- + VEHICLE_ARGENT_WARHORSE_A = 36557,
- + VEHICLE_ARGENT_BATTLEWORG_H = 36558,
- + VEHICLE_ARGENT_BATTLEWORG_COSMETIC = 36559,
- +
- + // The Black Knight's vehicle
- + VEHICLE_BLACK_KNIGHT = 35491
- +};
- +
- +enum WaypointData
- +{
- + DATA_GENERATE_WAYPOINTS_FOR_BOSS_1 = 1,
- + DATA_GENERATE_WAYPOINTS_FOR_BOSS_2,
- + DATA_GENERATE_WAYPOINTS_FOR_BOSS_3,
- + DATA_GENERATE_WAYPOINTS_FOR_ADDS
- +};
- +
- +enum WaypointPaths
- +{
- + WAYPOINT_MAP_BOSS_1 = 1,
- + WAYPOINT_MAP_BOSS_2,
- + WAYPOINT_MAP_BOSS_3,
- + WAYPOINT_MAP_ADDS
- +};
- +
- +enum Seats
- +{
- + SEAT_ID_0 = 0
- +};
- +
- +enum PennantSpells
- +{
- + SPELL_PENNANT_DARNASSUS = 63406,
- + SPELL_PENNANT_EXODAR = 63423,
- + SPELL_PENNANT_GNOMEREGAN = 63396,
- + SPELL_PENNANT_IRONFORGE = 63427,
- + SPELL_PENNANT_ORGRIMMAR = 63433,
- + SPELL_PENNANT_SEN_JIN = 63399,
- + SPELL_PENNANT_SILVERMOON = 63403,
- + SPELL_PENNANT_STORMWIND = 62594,
- + SPELL_PENNANT_THUNDER_BLUFF = 63436,
- + SPELL_PENNANT_UNDERCITY = 63430
- +};
- +
- +template<class AI>
- +AI* GetTrialOfChampionAI(Creature* creature)
- +{
- + return GetInstanceAI<AI>(creature, ToCScriptName);
- +}
- +
- +#endif // TRIAL_OF_CHAMPION_H_
- --
- 2.30.0.windows.2
Add Comment
Please, Sign In to add comment