aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoroffl <11556157+offl@users.noreply.github.com>2021-12-01 18:49:44 +0200
committerGitHub <noreply@github.com>2021-12-01 18:49:44 +0200
commit35b55b3f21cf11a673c4b4afacf45e77ec98db38 (patch)
tree03e91e542286539cbb1da8935c8bdb3d6f6235f2 /src
parent251304b19c2fc42ee330b9a533b54f7b80df5d4a (diff)
Scripts/Crypts: Rework Exarch Maladaar (#27313)
Diffstat (limited to 'src')
-rw-r--r--src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/auchenai_crypts.h2
-rw-r--r--src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp520
2 files changed, 292 insertions, 230 deletions
diff --git a/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/auchenai_crypts.h b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/auchenai_crypts.h
index 5ea113cc547..bf424d24538 100644
--- a/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/auchenai_crypts.h
+++ b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/auchenai_crypts.h
@@ -38,4 +38,6 @@ inline AI* GetAuchenaiCryptsAI(T* obj)
return GetInstanceAI<AI>(obj, ACScriptName);
}
+#define RegisterAuchenaiCryptsCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetAuchenaiCryptsAI)
+
#endif // AUCHENAI_CRYPTS_H_
diff --git a/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp
index 178afbe09dd..a0a120b46f3 100644
--- a/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp
+++ b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp
@@ -15,305 +15,365 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Boss_Exarch_Maladaar
-SD%Complete: 95
-SDComment: Most of event implemented, some adjustments to timers remain and possibly make some better code for switching his dark side in to better "images" of player.
-SDCategory: Auchindoun, Auchenai Crypts
-EndScriptData */
-
-/* ContentData
-npc_stolen_soul
-boss_exarch_maladaar
-EndContentData */
-
#include "ScriptMgr.h"
#include "auchenai_crypts.h"
#include "ObjectAccessor.h"
+#include "Player.h"
#include "ScriptedCreature.h"
+#include "Spell.h"
+#include "SpellInfo.h"
+#include "SpellScript.h"
+
+enum Texts
+{
+ SAY_ROAR = 0,
+ SAY_SOUL_CLEAVE = 1,
+ SAY_SUMMON = 2,
+ SAY_AGGRO = 3,
+ SAY_SLAY = 4,
+ SAY_DEATH = 5
+};
enum Spells
{
+ SPELL_SOUL_SCREAM = 32421,
+ SPELL_RIBBON_OF_SOULS = 32422,
+ SPELL_STOLEN_SOUL = 32346,
+ SPELL_SUMMON_STOLEN_SOUL = 32360,
+ SPELL_SUMMON_AVATAR = 32424,
+
+ // Stolen Soul
+ SPELL_STOLEN_SOUL_VISUAL = 32395,
+ SPELL_STOLEN_SOUL_DISPEL = 33326,
+
SPELL_MOONFIRE = 37328,
SPELL_FIREBALL = 37329,
SPELL_MIND_FLAY = 37330,
SPELL_HEMORRHAGE = 37331,
- SPELL_FROSTSHOCK = 37332,
+ SPELL_FROST_SHOCK = 37332,
SPELL_CURSE_OF_AGONY = 37334,
SPELL_MORTAL_STRIKE = 37335,
SPELL_FREEZING_TRAP = 37368,
SPELL_HAMMER_OF_JUSTICE = 37369,
-
- // Avatar of Martyred
- SPELL_AV_MORTAL_STRIKE = 16856,
- SPELL_AV_SUNDER_ARMOR = 16145
+ SPELL_PLAGUE_STRIKE = 58839
};
-class npc_stolen_soul : public CreatureScript
+enum Events
{
-public:
- npc_stolen_soul() : CreatureScript("npc_stolen_soul") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetAuchenaiCryptsAI<npc_stolen_soulAI>(creature);
- }
-
- struct npc_stolen_soulAI : public ScriptedAI
- {
- npc_stolen_soulAI(Creature* creature) : ScriptedAI(creature)
- {
- myClass = CLASS_NONE;
- Class_Timer = 1000;
- }
-
- uint8 myClass;
- uint32 Class_Timer;
-
- void Reset() override
- {
- myClass = CLASS_NONE;
- Class_Timer = 1000;
- }
-
- void JustEngagedWith(Unit* /*who*/) override
- { }
-
- void SetMyClass(uint8 myclass)
- {
- myClass = myclass;
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
-
- if (Class_Timer <= diff)
- {
- switch (myClass)
- {
- case CLASS_WARRIOR:
- DoCastVictim(SPELL_MORTAL_STRIKE);
- Class_Timer = 6000;
- break;
- case CLASS_PALADIN:
- DoCastVictim(SPELL_HAMMER_OF_JUSTICE);
- Class_Timer = 6000;
- break;
- case CLASS_HUNTER:
- DoCastVictim(SPELL_FREEZING_TRAP);
- Class_Timer = 20000;
- break;
- case CLASS_ROGUE:
- DoCastVictim(SPELL_HEMORRHAGE);
- Class_Timer = 10000;
- break;
- case CLASS_PRIEST:
- DoCastVictim(SPELL_MIND_FLAY);
- Class_Timer = 5000;
- break;
- case CLASS_SHAMAN:
- DoCastVictim(SPELL_FROSTSHOCK);
- Class_Timer = 8000;
- break;
- case CLASS_MAGE:
- DoCastVictim(SPELL_FIREBALL);
- Class_Timer = 5000;
- break;
- case CLASS_WARLOCK:
- DoCastVictim(SPELL_CURSE_OF_AGONY);
- Class_Timer = 20000;
- break;
- case CLASS_DRUID:
- DoCastVictim(SPELL_MOONFIRE);
- Class_Timer = 10000;
- break;
- }
- } else Class_Timer -= diff;
-
- DoMeleeAttackIfReady();
- }
- };
-
+ EVENT_SOUL_SCREAM = 1,
+ EVENT_RIBBON_OF_SOULS,
+ EVENT_STOLEN_SOUL,
+ EVENT_SUMMON_AVATAR
};
-enum ExarchMaladaar
+enum Misc
{
- SAY_INTRO = 0,
- SAY_SUMMON = 1,
- SAY_AGGRO = 2,
- SAY_ROAR = 3,
- SAY_SLAY = 4,
- SAY_DEATH = 5,
-
- SPELL_RIBBON_OF_SOULS = 32422,
- SPELL_SOUL_SCREAM = 32421,
- SPELL_STOLEN_SOUL = 32346,
- SPELL_STOLEN_SOUL_VISUAL = 32395,
- SPELL_SUMMON_AVATAR = 32424,
-
- ENTRY_STOLEN_SOUL = 18441
+ NPC_DORE = 19412,
+
+ MODEL_UNDEAD_MALE = 1027, // guessed
+ MODEL_UNDEAD_FEMALE = 1029, // guessed
+ MODEL_NIGHTELF_MALE = 2572, // guessed
+ MODEL_NIGHTELF_FEMALE = 2575, // guessed
+ MODEL_ORC_MALE = 2576, // guessed
+ MODEL_ORC_FEMALE = 2577, // guessed
+ MODEL_TAUREN_MALE = 2578, // sniff
+ MODEL_TAUREN_FEMALE = 2579, // guessed
+ MODEL_GNOME_MALE = 2581, // guessed
+ MODEL_GNOME_FEMALE = 2590, // guessed
+ MODEL_HUMAN_MALE = 2582, // sniff
+ MODEL_HUMAN_FEMALE = 2583, // sniff
+ MODEL_DWARF_MALE = 2584, // sniff
+ MODEL_DWARF_FEMALE = 2585, // guessed
+ MODEL_TROLL_MALE = 2588, // guessed
+ MODEL_TROLL_FEMALE = 2589, // guessed
+ MODEL_BLOODELF_MALE = 17267, // completely guessed
+ MODEL_BLOODELF_FEMALE = 17268, // completely guessed
+ MODEL_DRAENEI_MALE = 16721, // completely guessed
+ MODEL_DRAENEI_FEMALE = 17004 // completely guessed
};
-class boss_exarch_maladaar : public CreatureScript
+Position const DoreSpawnPos = { -4.40722f, -387.277f, 40.6294f, 6.26573f };
+
+struct boss_exarch_maladaar : public BossAI
{
-public:
- boss_exarch_maladaar() : CreatureScript("boss_exarch_maladaar") { }
+ boss_exarch_maladaar(Creature* creature) : BossAI(creature, DATA_EXARCH_MALADAAR), _avatarSummoned(false) { }
- CreatureAI* GetAI(Creature* creature) const override
+ void Reset() override
{
- return GetAuchenaiCryptsAI<boss_exarch_maladaarAI>(creature);
+ _Reset();
+ _avatarSummoned = false;
}
- struct boss_exarch_maladaarAI : public ScriptedAI
+ void JustEngagedWith(Unit* who) override
{
- boss_exarch_maladaarAI(Creature* creature) : ScriptedAI(creature)
+ BossAI::JustEngagedWith(who);
+ Talk(SAY_AGGRO);
+ events.ScheduleEvent(EVENT_SOUL_SCREAM, RAND(10s, 15s, 20s, 25s));
+ events.ScheduleEvent(EVENT_RIBBON_OF_SOULS, 1s, 4s);
+ events.ScheduleEvent(EVENT_STOLEN_SOUL, RAND(10s, 15s, 20s, 25s));
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
+ {
+ if (!_avatarSummoned && me->HealthBelowPctDamaged(25, damage))
{
- Initialize();
- HasTaunted = false;
+ _avatarSummoned = true;
+ events.ScheduleEvent(EVENT_SUMMON_AVATAR, 0s);
}
+ }
- void Initialize()
- {
- soulmodel = 0;
- soulholder.Clear();
- soulclass = 0;
+ void OnSpellCastFinished(SpellInfo const* spell, SpellFinishReason reason) override
+ {
+ if (reason == SPELL_FINISHED_SUCCESSFUL_CAST && spell->Id == SPELL_STOLEN_SOUL)
+ if (roll_chance_i(25))
+ Talk(SAY_SOUL_CLEAVE);
+ }
- Fear_timer = 15000 + rand32() % 5000;
- Ribbon_of_Souls_timer = 5000;
- StolenSoul_Timer = 25000 + rand32() % 10000;
+ void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override
+ {
+ if (spellInfo->Id == SPELL_STOLEN_SOUL)
+ target->CastSpell(target, SPELL_SUMMON_STOLEN_SOUL, true);
+ }
- Avatar_summoned = false;
- }
+ // Do not despawn avatar
+ void JustSummoned(Creature* /*summon*/) override { }
- uint32 soulmodel;
- ObjectGuid soulholder;
- uint8 soulclass;
+ void KilledUnit(Unit* /*victim*/) override
+ {
+ Talk(SAY_SLAY);
+ }
- uint32 Fear_timer;
- uint32 Ribbon_of_Souls_timer;
- uint32 StolenSoul_Timer;
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ Talk(SAY_DEATH);
+ me->SummonCreature(NPC_DORE, DoreSpawnPos, TEMPSUMMON_MANUAL_DESPAWN);
+ }
- bool HasTaunted;
- bool Avatar_summoned;
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- void Reset() override
- {
- Initialize();
- }
+ events.Update(diff);
- void MoveInLineOfSight(Unit* who) override
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ while (uint32 eventId = events.ExecuteEvent())
{
- if (!HasTaunted && me->IsWithinDistInMap(who, 150.0f))
+ switch (eventId)
{
- Talk(SAY_INTRO);
- HasTaunted = true;
+ case EVENT_SOUL_SCREAM:
+ if (roll_chance_i(25))
+ Talk(SAY_ROAR);
+ DoCastSelf(SPELL_SOUL_SCREAM);
+ events.Repeat(RAND(15s, 20s));
+ break;
+ case EVENT_RIBBON_OF_SOULS:
+ DoCastVictim(SPELL_RIBBON_OF_SOULS);
+ events.Repeat(4s, 20s); // Usually just 4
+ break;
+ case EVENT_STOLEN_SOUL:
+ if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f, true, true, -SPELL_STOLEN_SOUL))
+ DoCast(target, SPELL_STOLEN_SOUL);
+ events.Repeat(RAND(20s, 25s));
+ break;
+ case EVENT_SUMMON_AVATAR:
+ Talk(SAY_SUMMON);
+ DoCastSelf(SPELL_SUMMON_AVATAR);
+ break;
+ default:
+ break;
}
- ScriptedAI::MoveInLineOfSight(who);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
- void JustEngagedWith(Unit* /*who*/) override
- {
- Talk(SAY_AGGRO);
- }
+ DoMeleeAttackIfReady();
+ }
- void JustSummoned(Creature* summoned) override
- {
- if (summoned->GetEntry() == ENTRY_STOLEN_SOUL)
- {
- //SPELL_STOLEN_SOUL_VISUAL has shapeshift effect, but not implemented feature in Trinity for this spell.
- summoned->CastSpell(summoned, SPELL_STOLEN_SOUL_VISUAL, false);
- summoned->SetDisplayId(soulmodel);
- summoned->SetFaction(me->GetFaction());
+private:
+ bool _avatarSummoned;
+};
- if (Unit* target = ObjectAccessor::GetUnit(*me, soulholder))
- {
- ENSURE_AI(npc_stolen_soul::npc_stolen_soulAI, summoned->AI())->SetMyClass(soulclass);
- summoned->AI()->AttackStart(target);
- }
- }
- }
+struct npc_stolen_soul : public ScriptedAI
+{
+ npc_stolen_soul(Creature* creature) : ScriptedAI(creature), _summonerClass(CLASS_NONE) { }
- void KilledUnit(Unit* /*victim*/) override
- {
- if (rand32() % 2)
- return;
+ void IsSummonedBy(WorldObject* summonerWO) override
+ {
+ Player* summoner = summonerWO->ToPlayer();
+ if (!summoner)
+ return;
- Talk(SAY_SLAY);
- }
+ _summonerGUID = summoner->GetGUID();
+ _summonerClass = summoner->GetClass();
+
+ // Apparently this is the first time they tried to "clone" player
+ uint32 model = 0;
+ uint8 gender = summoner->GetNativeGender();
- void JustDied(Unit* /*killer*/) override
+ switch (summoner->GetRace())
{
- Talk(SAY_DEATH);
- //When Exarch Maladar is defeated D'ore appear.
- me->SummonCreature(19412, -4.40722f, -387.277f, 40.6294f, 6.26573f, TEMPSUMMON_MANUAL_DESPAWN);
+ case RACE_UNDEAD_PLAYER: model = gender ? MODEL_UNDEAD_FEMALE : MODEL_UNDEAD_MALE; break;
+ case RACE_NIGHTELF: model = gender ? MODEL_NIGHTELF_FEMALE : MODEL_NIGHTELF_MALE; break;
+ case RACE_ORC: model = gender ? MODEL_ORC_FEMALE : MODEL_ORC_MALE; break;
+ case RACE_TAUREN: model = gender ? MODEL_TAUREN_FEMALE : MODEL_TAUREN_MALE; break;
+ case RACE_GNOME: model = gender ? MODEL_GNOME_FEMALE : MODEL_GNOME_MALE; break;
+ case RACE_HUMAN: model = gender ? MODEL_HUMAN_FEMALE : MODEL_HUMAN_MALE; break;
+ case RACE_DWARF: model = gender ? MODEL_DWARF_FEMALE : MODEL_DWARF_MALE; break;
+ case RACE_TROLL: model = gender ? MODEL_TROLL_FEMALE : MODEL_TROLL_MALE; break;
+ case RACE_BLOODELF: model = gender ? MODEL_BLOODELF_FEMALE : MODEL_BLOODELF_MALE; break;
+ case RACE_DRAENEI: model = gender ? MODEL_DRAENEI_FEMALE : MODEL_DRAENEI_MALE; break;
+ default: break;
}
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ if (model)
+ me->SetDisplayId(model);
- if (!Avatar_summoned && HealthBelowPct(25))
- {
- if (me->IsNonMeleeSpellCast(false))
- me->InterruptNonMeleeSpells(true);
+ me->SetCorpseDelay(3, true);
+ DoCastSelf(SPELL_STOLEN_SOUL_VISUAL);
- Talk(SAY_SUMMON);
+ DoZoneInCombat();
+ }
- DoCast(me, SPELL_SUMMON_AVATAR);
- Avatar_summoned = true;
- StolenSoul_Timer = 15000 + rand32() % 15000;
- }
+ void Reset() override
+ {
+ _scheduler.CancelAll();
+ }
- if (StolenSoul_Timer <= diff)
- {
- if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
+ void JustEngagedWith(Unit* /*who*/) override
+ {
+ switch (_summonerClass)
+ {
+ case CLASS_WARRIOR: //
+ _scheduler.Schedule(5s, 10s, [this](TaskContext task)
{
- if (target->GetTypeId() == TYPEID_PLAYER)
- {
- if (me->IsNonMeleeSpellCast(false))
- me->InterruptNonMeleeSpells(true);
-
- Talk(SAY_ROAR);
+ DoCastVictim(SPELL_MORTAL_STRIKE);
+ task.Repeat(5s, 10s);
+ });
+ break;
+ case CLASS_PALADIN: // video & sniff
+ _scheduler.Schedule(2s, 7s, [this](TaskContext task)
+ {
+ DoCastVictim(SPELL_HAMMER_OF_JUSTICE);
+ task.Repeat(8s, 15s);
+ });
+ break;
+ case CLASS_HUNTER: // video
+ _scheduler.Schedule(5s, [this](TaskContext task)
+ {
+ DoCastSelf(SPELL_FREEZING_TRAP);
+ task.Repeat(20s);
+ });
+ break;
+ case CLASS_ROGUE: //
+ _scheduler.Schedule(5s, [this](TaskContext task)
+ {
+ DoCastVictim(SPELL_HEMORRHAGE);
+ task.Repeat(10s);
+ });
+ break;
+ case CLASS_PRIEST: //
+ _scheduler.Schedule(2s, [this](TaskContext task)
+ {
+ DoCastVictim(SPELL_MIND_FLAY);
+ task.Repeat(3s, 5s);
+ });
+ break;
+ case CLASS_SHAMAN: // video
+ _scheduler.Schedule(0s, [this](TaskContext task)
+ {
+ if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 20.0f, true, true, -SPELL_FROST_SHOCK))
+ DoCast(target, SPELL_FROST_SHOCK);
+ task.Repeat(3s, 8s);
+ });
+ break;
+ case CLASS_MAGE: // video
+ _scheduler.Schedule(0s, [this](TaskContext task)
+ {
+ DoCastVictim(SPELL_FIREBALL);
+ task.Repeat(3s);
+ });
+ break;
+ case CLASS_WARLOCK: // video
+ _scheduler.Schedule(10s, [this](TaskContext task)
+ {
+ if (Unit* victim = me->GetVictim())
+ if (!victim->HasAura(SPELL_CURSE_OF_AGONY))
+ DoCast(victim, SPELL_CURSE_OF_AGONY);
+
+ task.Repeat(7s);
+ });
+ break;
+ case CLASS_DRUID: //
+ _scheduler.Schedule(5s, [this](TaskContext task)
+ {
+ DoCastVictim(SPELL_MOONFIRE);
+ task.Repeat(10s);
+ });
+ break;
+ case CLASS_DEATH_KNIGHT: //
+ _scheduler.Schedule(3s, 6s, [this](TaskContext task)
+ {
+ DoCastVictim(SPELL_PLAGUE_STRIKE);
+ task.Repeat(6s, 12s);
+ });
+ break;
+ default:
+ break;
+ }
+ }
- soulmodel = target->GetDisplayId();
- soulholder = target->GetGUID();
- soulclass = target->GetClass();
+ void JustDied(Unit* /*killer*/) override
+ {
+ if (Unit* target = ObjectAccessor::GetUnit(*me, _summonerGUID))
+ DoCast(target, SPELL_STOLEN_SOUL_DISPEL, true);
+ }
- DoCast(target, SPELL_STOLEN_SOUL);
- me->SummonCreature(ENTRY_STOLEN_SOUL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10s);
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- StolenSoul_Timer = 20000 + rand32() % 10000;
- } else StolenSoul_Timer = 1000;
- }
- } else StolenSoul_Timer -= diff;
+ _scheduler.Update(diff, [this]
+ {
+ DoMeleeAttackIfReady();
+ });
+ }
- if (Ribbon_of_Souls_timer <= diff)
- {
- if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
- DoCast(target, SPELL_RIBBON_OF_SOULS);
+private:
+ TaskScheduler _scheduler;
+ ObjectGuid _summonerGUID;
+ uint8 _summonerClass;
+};
- Ribbon_of_Souls_timer = 5000 + (rand32() % 20 * 1000);
- } else Ribbon_of_Souls_timer -= diff;
+// 33326 - Stolen Soul Dispel
+class spell_exarch_maladaar_stolen_soul_dispel : public AuraScript
+{
+ PrepareAuraScript(spell_exarch_maladaar_stolen_soul_dispel);
- if (Fear_timer <= diff)
- {
- DoCast(me, SPELL_SOUL_SCREAM);
- Fear_timer = 15000 + rand32() % 15000;
- } else Fear_timer -= diff;
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_STOLEN_SOUL });
+ }
- DoMeleeAttackIfReady();
- }
- };
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->RemoveAurasDueToSpell(SPELL_STOLEN_SOUL);
+ }
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_exarch_maladaar_stolen_soul_dispel::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
};
void AddSC_boss_exarch_maladaar()
{
- new boss_exarch_maladaar();
- new npc_stolen_soul();
+ RegisterAuchenaiCryptsCreatureAI(boss_exarch_maladaar);
+ RegisterAuchenaiCryptsCreatureAI(npc_stolen_soul);
+ RegisterSpellScript(spell_exarch_maladaar_stolen_soul_dispel);
}