From 7de2405604c0d9da2d76539696ecbab31f4165eb Mon Sep 17 00:00:00 2001 From: Skjalf <47818697+Nyeriah@users.noreply.github.com> Date: Sat, 30 Sep 2023 22:13:49 -0300 Subject: [PATCH] fix(Scripts/Karazhan): Several Aran fixes (#17394) - Fix drinking being interrupted by dots - Fix first super timer - Fix missing Arcane Explosion emote - Fix supers being locked by spell interrupt - Correct drinking to 10% mana down from 20% --- .../rev_1696108618524876800.sql | 4 + .../game/Entities/Creature/Creature.cpp | 8 + src/server/game/Entities/Creature/Creature.h | 1 + .../Karazhan/boss_shade_of_aran.cpp | 202 ++++++++++-------- 4 files changed, 121 insertions(+), 94 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1696108618524876800.sql diff --git a/data/sql/updates/pending_db_world/rev_1696108618524876800.sql b/data/sql/updates/pending_db_world/rev_1696108618524876800.sql new file mode 100644 index 000000000..088dea281 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1696108618524876800.sql @@ -0,0 +1,4 @@ +-- +DELETE FROM `creature_text` WHERE `CreatureId` = 16524 AND `GroupID` = 10; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(16524, 10, 0, '%s begins channelling his mana into a powerful arcane spell.', 16, 0, 100, 13515, 3, 'Shade of Aran EMOTE_ARCANE_EXPLOSION'); diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index f64bf3a3e..d86bc3b45 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -2748,6 +2748,14 @@ bool Creature::IsSpellProhibited(SpellSchoolMask idSchoolMask) const return false; } +void Creature::ClearProhibitedSpellTimers() +{ + for (uint8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i) + { + m_ProhibitSchoolTime[i] = 0; + } +} + void Creature::_AddCreatureSpellCooldown(uint32 spell_id, uint16 categoryId, uint32 end_time) { CreatureSpellCooldown spellCooldown; diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index d0a6b8b72..06debd25e 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -165,6 +165,7 @@ public: [[nodiscard]] uint32 GetSpellCooldown(uint32 spell_id) const; void ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs) override; [[nodiscard]] bool IsSpellProhibited(SpellSchoolMask idSchoolMask) const; + void ClearProhibitedSpellTimers(); [[nodiscard]] bool HasSpell(uint32 spellID) const override; diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp index e8413ef48..01a3c39b5 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp @@ -24,15 +24,17 @@ enum Texts { - SAY_AGGRO = 0, - SAY_FLAMEWREATH = 1, - SAY_BLIZZARD = 2, - SAY_EXPLOSION = 3, - SAY_DRINK = 4, - SAY_ELEMENTALS = 5, - SAY_KILL = 6, - SAY_TIMEOVER = 7, - SAY_DEATH = 8 + SAY_AGGRO = 0, + SAY_FLAMEWREATH = 1, + SAY_BLIZZARD = 2, + SAY_EXPLOSION = 3, + SAY_DRINK = 4, + SAY_ELEMENTALS = 5, + SAY_KILL = 6, + SAY_TIMEOVER = 7, + SAY_DEATH = 8, + SAY_ATIESH = 9, + EMOTE_ARCANE_EXPLOSION = 10 }; enum Spells @@ -103,19 +105,11 @@ struct boss_shade_of_aran : public BossAI }); } - uint8 LastSuperSpell; - - ObjectGuid FlameWreathTarget[3]; - float FWTargPosX[3]; - float FWTargPosY[3]; - - uint32 CurrentNormalSpell; - void Reset() override { BossAI::Reset(); _drinkScheduler.CancelAll(); - LastSuperSpell = rand() % 3; + _lastSuperSpell = rand() % 3; for (uint8 i = 0; i < 3; ++i) FlameWreathTarget[i].Clear(); @@ -127,9 +121,7 @@ struct boss_shade_of_aran : public BossAI _frostCooledDown = true; _drinking = false; - - // Not in progress - instance->SetData(DATA_ARAN, NOT_STARTED); + _hasDrunk = false; if (GameObject* libraryDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_GO_LIBRARY_DOOR))) { @@ -207,6 +199,25 @@ struct boss_shade_of_aran : public BossAI } } + void DamageTaken(Unit* doneBy, uint32& damage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask) override + { + BossAI::DamageTaken(doneBy, damage, damagetype, damageSchoolMask); + + if ((damagetype == DIRECT_DAMAGE || damagetype == SPELL_DIRECT_DAMAGE) && _drinking && me->GetReactState() == REACT_PASSIVE) + { + me->RemoveAurasDueToSpell(SPELL_DRINK); + me->SetStandState(UNIT_STAND_STATE_STAND); + me->SetReactState(REACT_AGGRESSIVE); + me->SetPower(POWER_MANA, me->GetMaxPower(POWER_MANA) - 32000); + _drinkScheduler.CancelGroup(GROUP_DRINKING); + _drinkScheduler.Schedule(1s, [this](TaskContext) + { + DoCastSelf(SPELL_AOE_PYROBLAST, false); + _drinking = false; + }); + } + } + void JustEngagedWith(Unit* /*who*/) override { _JustEngagedWith(); @@ -222,11 +233,14 @@ struct boss_shade_of_aran : public BossAI } }).Schedule(1s, [this](TaskContext context) { - if (!me->IsNonMeleeSpellCast(false) && !_drinking) + context.Repeat(2s); + + if (!_drinking) { - Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true); - if (!target) + if (me->IsNonMeleeSpellCast(false)) + { return; + } uint32 Spells[3]; uint8 AvailableSpells = 0; @@ -248,27 +262,69 @@ struct boss_shade_of_aran : public BossAI ++AvailableSpells; } + // Should drink at 10%, need 10% mana for mass polymorph + if (!_hasDrunk && me->GetMaxPower(POWER_MANA) && (me->GetPower(POWER_MANA) * 100 / me->GetMaxPower(POWER_MANA)) < 13) + { + _drinking = true; + _hasDrunk = true; + me->InterruptNonMeleeSpells(true); + Talk(SAY_DRINK); + DoCastAOE(SPELL_MASS_POLY); + me->SetReactState(REACT_PASSIVE); + + // Start drinking after conjuring drinks + _drinkScheduler.Schedule(2s, GROUP_DRINKING, [this](TaskContext) + { + DoCastSelf(SPELL_CONJURE); + }).Schedule(4s, GROUP_DRINKING, [this](TaskContext) + { + me->SetStandState(UNIT_STAND_STATE_SIT); + DoCastSelf(SPELL_DRINK); + }); + + _drinkScheduler.Schedule(10s, GROUP_DRINKING, [this](TaskContext) + { + me->SetStandState(UNIT_STAND_STATE_STAND); + me->SetReactState(REACT_AGGRESSIVE); + me->SetPower(POWER_MANA, me->GetMaxPower(POWER_MANA) - 32000); + DoCastSelf(SPELL_AOE_PYROBLAST); + _drinkScheduler.CancelGroup(GROUP_DRINKING); + _drinking = false; + }); + + return; + } + //If no available spells wait 1 second and try again if (AvailableSpells) { CurrentNormalSpell = Spells[rand() % AvailableSpells]; - if (!me->CanCastSpell(CurrentNormalSpell)) + if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(CurrentNormalSpell)) { - me->SetWalk(false); - me->ResumeChasingVictim(); - } - else - { - DoCast(target, CurrentNormalSpell); - if (me->GetVictim()) + if (int32(me->GetPower(POWER_MANA)) < spellInfo->CalcPowerCost(me, (SpellSchoolMask)spellInfo->SchoolMask)) { - me->GetMotionMaster()->MoveChase(me->GetVictim(), 45.0f); + DoCastSelf(SPELL_POTION); + } + else + { + if (!me->CanCastSpell(CurrentNormalSpell)) + { + me->SetWalk(false); + me->ResumeChasingVictim(); + } + else + { + DoCastRandomTarget(CurrentNormalSpell, 0, 100.0f); + if (me->GetVictim()) + { + me->GetMotionMaster()->MoveChase(me->GetVictim(), 45.0f); + } + } } } } } - context.Repeat(2s); }).Schedule(5s, [this](TaskContext context) { if (!_drinking) @@ -284,13 +340,17 @@ struct boss_shade_of_aran : public BossAI } } context.Repeat(5s, 20s); - }).Schedule(35s, [this](TaskContext context) + }).Schedule(6s, [this](TaskContext context) { if (!_drinking) { + me->ClearProhibitedSpellTimers(); + + DoCastSelf(SPELL_BLINK_CENTER, true); + uint8 Available[2]; - switch (LastSuperSpell) + switch (_lastSuperSpell) { case SUPER_AE: Available[0] = SUPER_FLAME; @@ -306,14 +366,13 @@ struct boss_shade_of_aran : public BossAI break; } - LastSuperSpell = Available[urand(0, 1)]; + _lastSuperSpell = Available[urand(0, 1)]; - switch (LastSuperSpell) + switch (_lastSuperSpell) { case SUPER_AE: Talk(SAY_EXPLOSION); - - DoCastSelf(SPELL_BLINK_CENTER, true); + Talk(EMOTE_ARCANE_EXPLOSION); DoCastSelf(SPELL_PLAYERPULL, true); DoCastSelf(SPELL_MASSSLOW, true); DoCastSelf(SPELL_AEXPLOSION, false); @@ -356,56 +415,6 @@ struct boss_shade_of_aran : public BossAI } } context.Repeat(35s, 40s); - }).Schedule(1s, [this](TaskContext context){ - if (me->GetMaxPower(POWER_MANA) && (me->GetPower(POWER_MANA) * 100 / me->GetMaxPower(POWER_MANA)) < 20) - { - _drinking = true; - me->InterruptNonMeleeSpells(true); - Talk(SAY_DRINK); - DoCastSelf(SPELL_MASS_POLY, true); - DoCastSelf(SPELL_CONJURE, false); - me->SetReactState(REACT_PASSIVE); - me->SetStandState(UNIT_STAND_STATE_SIT); - DoCastSelf(SPELL_DRINK, true); - _currentHealth = me->GetHealth(); - _drinkScheduler.Schedule(500ms, GROUP_DRINKING, [this](TaskContext context) - { - //check for damage to interrupt - if (me->GetHealth() < _currentHealth) - { - me->RemoveAurasDueToSpell(SPELL_DRINK); - me->SetStandState(UNIT_STAND_STATE_STAND); - me->SetReactState(REACT_AGGRESSIVE); - me->SetPower(POWER_MANA, me->GetMaxPower(POWER_MANA) - 32000); - DoCastSelf(SPELL_POTION, false); - _drinkScheduler.CancelGroup(GROUP_DRINKING); - _drinkScheduler.Schedule(1s, [this](TaskContext) - { - DoCastSelf(SPELL_AOE_PYROBLAST, false); - }).Schedule(3s, [this](TaskContext) - { - _drinking = false; - }); - } else - { - context.Repeat(500ms); - } - }).Schedule(10s, GROUP_DRINKING, [this](TaskContext) - { - me->SetStandState(UNIT_STAND_STATE_STAND); - me->SetReactState(REACT_AGGRESSIVE); - me->SetPower(POWER_MANA, me->GetMaxPower(POWER_MANA) - 32000); - DoCastSelf(SPELL_POTION, true); - DoCastSelf(SPELL_AOE_PYROBLAST, false); - _drinkScheduler.CancelGroup(GROUP_DRINKING); - _drinking = false; - }); - context.Repeat(12s); //semi-arbitrary duration to envelop drinking duration - } - else - { - context.Repeat(1s); - } }).Schedule(12min, [this](TaskContext context) { for (uint32 i = 0; i < 5; ++i) @@ -484,9 +493,6 @@ struct boss_shade_of_aran : public BossAI Spell->Effects[2].Effect != SPELL_EFFECT_INTERRUPT_CAST) || !me->IsNonMeleeSpellCast(false)) return; - //Interrupt effect - me->InterruptNonMeleeSpells(false); - //Normally we would set the cooldown equal to the spell duration //but we do not have access to the DurationStore @@ -506,11 +512,19 @@ struct boss_shade_of_aran : public BossAI private: TaskScheduler _drinkScheduler; + uint32 _lastSuperSpell; + + ObjectGuid FlameWreathTarget[3]; + float FWTargPosX[3]; + float FWTargPosY[3]; + + uint32 CurrentNormalSpell; + bool _arcaneCooledDown; bool _fireCooledDown; bool _frostCooledDown; bool _drinking; - uint32 _currentHealth; + bool _hasDrunk; }; void AddSC_boss_shade_of_aran()