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:
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user