fix(Scripts/Karazhan): Use actual spell interruption timers to handle… (#17709)

fix(Scripts/Karazhan): Use actual spell interruption timers to handle basic ability cast
This commit is contained in:
Andrew
2023-11-14 18:50:45 -03:00
committed by GitHub
parent 1227e69600
commit a19613df86
@@ -44,7 +44,7 @@ enum Spells
{ {
SPELL_FROSTBOLT = 29954, SPELL_FROSTBOLT = 29954,
SPELL_FIREBALL = 29953, SPELL_FIREBALL = 29953,
SPELL_ARCMISSLE = 29955, SPELL_ARCANE_MISSILE = 29955,
SPELL_CHAINSOFICE = 29991, SPELL_CHAINSOFICE = 29991,
SPELL_DRAGONSBREATH = 29964, SPELL_DRAGONSBREATH = 29964,
SPELL_MASSSLOW = 30035, SPELL_MASSSLOW = 30035,
@@ -106,13 +106,9 @@ struct boss_shade_of_aran : public BossAI
{ {
BossAI::Reset(); BossAI::Reset();
_drinkScheduler.CancelAll(); _drinkScheduler.CancelAll();
_lastSuperSpell = rand() % 3; _lastSuperSpell = 0;
CurrentNormalSpell = 0; _currentNormalSpell = 0;
_arcaneCooledDown = true;
_fireCooledDown = true;
_frostCooledDown = true;
_drinking = false; _drinking = false;
_hasDrunk = false; _hasDrunk = false;
@@ -171,30 +167,6 @@ struct boss_shade_of_aran : public BossAI
Talk(SAY_KILL); Talk(SAY_KILL);
} }
void TriggerArcaneCooldown()
{
scheduler.Schedule(5s, [this](TaskContext)
{
_arcaneCooledDown = true;
});
}
void TriggerFireCooldown()
{
scheduler.Schedule(5s, [this](TaskContext)
{
_fireCooledDown = true;
});
}
void TriggerFrostCooldown()
{
scheduler.Schedule(5s, [this](TaskContext)
{
_frostCooledDown = true;
});
}
void JustDied(Unit* /*killer*/) override void JustDied(Unit* /*killer*/) override
{ {
Talk(SAY_DEATH); Talk(SAY_DEATH);
@@ -234,12 +206,15 @@ struct boss_shade_of_aran : public BossAI
_drinking = true; _drinking = true;
_hasDrunk = true; _hasDrunk = true;
me->InterruptNonMeleeSpells(true); me->InterruptNonMeleeSpells(true);
me->RemoveAurasDueToSpell(SPELL_ARCANE_MISSILE);
Talk(SAY_DRINK); Talk(SAY_DRINK);
DoCastAOE(SPELL_MASS_POLY);
me->SetReactState(REACT_PASSIVE); me->SetReactState(REACT_PASSIVE);
// Start drinking after conjuring drinks // Start drinking after conjuring drinks
_drinkScheduler.Schedule(2s, GROUP_DRINKING, [this](TaskContext) _drinkScheduler.Schedule(1s, GROUP_DRINKING, [this](TaskContext)
{
DoCastAOE(SPELL_MASS_POLY);
}).Schedule(2s, GROUP_DRINKING, [this](TaskContext)
{ {
DoCastSelf(SPELL_CONJURE); DoCastSelf(SPELL_CONJURE);
}).Schedule(4s, GROUP_DRINKING, [this](TaskContext) }).Schedule(4s, GROUP_DRINKING, [this](TaskContext)
@@ -280,53 +255,32 @@ struct boss_shade_of_aran : public BossAI
return; return;
} }
uint32 Spells[3]; std::list<uint32> normalSpells = { SPELL_ARCANE_MISSILE, SPELL_FIREBALL, SPELL_FROSTBOLT };
uint8 AvailableSpells = 0; normalSpells.remove_if([&](uint32 spell) -> bool { return !me->CanCastSpell(spell); });
//Check for what spells are not on cooldown if (!normalSpells.empty())
if (_arcaneCooledDown)
{ {
Spells[AvailableSpells] = SPELL_ARCMISSLE; // If we are able to cast spells, cast them.
++AvailableSpells; _currentNormalSpell = Acore::Containers::SelectRandomContainerElement(normalSpells);
}
if (_fireCooledDown)
{
Spells[AvailableSpells] = SPELL_FIREBALL;
++AvailableSpells;
}
if (_frostCooledDown)
{
Spells[AvailableSpells] = SPELL_FROSTBOLT;
++AvailableSpells;
}
//If no available spells wait 1 second and try again DoCastRandomTarget(_currentNormalSpell, 0, 100.0f);
if (AvailableSpells) if (me->GetVictim())
{
me->GetMotionMaster()->MoveChase(me->GetVictim(), 45.0f);
}
}
else
{ {
CurrentNormalSpell = Spells[rand() % AvailableSpells]; // Otherwise, chase in melee range for auto attacks (and drink mana potion, if needed).
me->SetWalk(false);
me->ResumeChasingVictim();
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(CurrentNormalSpell)) if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(_currentNormalSpell))
{ {
if (int32(me->GetPower(POWER_MANA)) < spellInfo->CalcPowerCost(me, (SpellSchoolMask)spellInfo->SchoolMask)) if (int32(me->GetPower(POWER_MANA)) < spellInfo->CalcPowerCost(me, (SpellSchoolMask)spellInfo->SchoolMask))
{ {
DoCastSelf(SPELL_POTION); 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);
}
}
}
} }
} }
} }
@@ -346,44 +300,25 @@ struct boss_shade_of_aran : public BossAI
DoCastSelf(SPELL_BLINK_CENTER, true); DoCastSelf(SPELL_BLINK_CENTER, true);
uint8 Available[2]; std::vector<uint32> superSpells = { SPELL_SUMMON_BLIZZARD, SPELL_AEXPLOSION, SPELL_FLAME_WREATH };
_lastSuperSpell = Acore::Containers::SelectRandomContainerElementIf(superSpells, [&](uint32 superSpell) -> bool { return superSpell != _lastSuperSpell; });
switch (_lastSuperSpell) switch (_lastSuperSpell)
{ {
case SUPER_AE: case SPELL_AEXPLOSION:
Available[0] = SUPER_FLAME;
Available[1] = SUPER_BLIZZARD;
break;
case SUPER_FLAME:
Available[0] = SUPER_AE;
Available[1] = SUPER_BLIZZARD;
break;
case SUPER_BLIZZARD:
Available[0] = SUPER_FLAME;
Available[1] = SUPER_AE;
break;
}
_lastSuperSpell = Available[urand(0, 1)];
switch (_lastSuperSpell)
{
case SUPER_AE:
Talk(SAY_EXPLOSION); Talk(SAY_EXPLOSION);
Talk(EMOTE_ARCANE_EXPLOSION); Talk(EMOTE_ARCANE_EXPLOSION);
DoCastSelf(SPELL_PLAYERPULL, true); DoCastSelf(SPELL_PLAYERPULL, true);
DoCastSelf(SPELL_MASSSLOW, true); DoCastSelf(SPELL_MASSSLOW, true);
DoCastSelf(SPELL_AEXPLOSION, false);
break; break;
case SUPER_FLAME: case SPELL_FLAME_WREATH:
Talk(SAY_FLAMEWREATH); Talk(SAY_FLAMEWREATH);
DoCastAOE(SPELL_FLAME_WREATH);
break; break;
case SUPER_BLIZZARD: case SPELL_SUMMON_BLIZZARD:
Talk(SAY_BLIZZARD); Talk(SAY_BLIZZARD);
DoCastAOE(SPELL_SUMMON_BLIZZARD);
break; break;
} }
DoCastAOE(_lastSuperSpell);
} }
context.Repeat(35s, 40s); context.Repeat(35s, 40s);
}).Schedule(12min, [this](TaskContext context) }).Schedule(12min, [this](TaskContext context)
@@ -417,44 +352,16 @@ struct boss_shade_of_aran : public BossAI
return; return;
} }
if (_arcaneCooledDown && _fireCooledDown && _frostCooledDown && !_drinking) if (!_drinking)
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
void SpellHit(Unit* /*pAttacker*/, SpellInfo const* Spell) override
{
//We only care about interrupt effects and only if they are durring a spell currently being cast
if ((Spell->Effects[0].Effect != SPELL_EFFECT_INTERRUPT_CAST &&
Spell->Effects[1].Effect != SPELL_EFFECT_INTERRUPT_CAST &&
Spell->Effects[2].Effect != SPELL_EFFECT_INTERRUPT_CAST) || !me->IsNonMeleeSpellCast(false))
return;
//Normally we would set the cooldown equal to the spell duration
//but we do not have access to the DurationStore
switch (CurrentNormalSpell)
{
case SPELL_ARCMISSLE:
TriggerArcaneCooldown();
break;
case SPELL_FIREBALL:
TriggerFireCooldown();
break;
case SPELL_FROSTBOLT:
TriggerFrostCooldown();
break;
}
}
private: private:
TaskScheduler _drinkScheduler; TaskScheduler _drinkScheduler;
uint32 _currentNormalSpell;
uint32 _lastSuperSpell; uint32 _lastSuperSpell;
uint32 CurrentNormalSpell;
bool _arcaneCooledDown;
bool _fireCooledDown;
bool _frostCooledDown;
bool _drinking; bool _drinking;
bool _hasDrunk; bool _hasDrunk;
bool _atieshReaction; bool _atieshReaction;