mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-09 08:17:56 +00:00
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%
This commit is contained in:
@@ -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');
|
||||||
@@ -2748,6 +2748,14 @@ bool Creature::IsSpellProhibited(SpellSchoolMask idSchoolMask) const
|
|||||||
return false;
|
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)
|
void Creature::_AddCreatureSpellCooldown(uint32 spell_id, uint16 categoryId, uint32 end_time)
|
||||||
{
|
{
|
||||||
CreatureSpellCooldown spellCooldown;
|
CreatureSpellCooldown spellCooldown;
|
||||||
|
|||||||
@@ -165,6 +165,7 @@ public:
|
|||||||
[[nodiscard]] uint32 GetSpellCooldown(uint32 spell_id) const;
|
[[nodiscard]] uint32 GetSpellCooldown(uint32 spell_id) const;
|
||||||
void ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs) override;
|
void ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs) override;
|
||||||
[[nodiscard]] bool IsSpellProhibited(SpellSchoolMask idSchoolMask) const;
|
[[nodiscard]] bool IsSpellProhibited(SpellSchoolMask idSchoolMask) const;
|
||||||
|
void ClearProhibitedSpellTimers();
|
||||||
|
|
||||||
[[nodiscard]] bool HasSpell(uint32 spellID) const override;
|
[[nodiscard]] bool HasSpell(uint32 spellID) const override;
|
||||||
|
|
||||||
|
|||||||
@@ -24,15 +24,17 @@
|
|||||||
|
|
||||||
enum Texts
|
enum Texts
|
||||||
{
|
{
|
||||||
SAY_AGGRO = 0,
|
SAY_AGGRO = 0,
|
||||||
SAY_FLAMEWREATH = 1,
|
SAY_FLAMEWREATH = 1,
|
||||||
SAY_BLIZZARD = 2,
|
SAY_BLIZZARD = 2,
|
||||||
SAY_EXPLOSION = 3,
|
SAY_EXPLOSION = 3,
|
||||||
SAY_DRINK = 4,
|
SAY_DRINK = 4,
|
||||||
SAY_ELEMENTALS = 5,
|
SAY_ELEMENTALS = 5,
|
||||||
SAY_KILL = 6,
|
SAY_KILL = 6,
|
||||||
SAY_TIMEOVER = 7,
|
SAY_TIMEOVER = 7,
|
||||||
SAY_DEATH = 8
|
SAY_DEATH = 8,
|
||||||
|
SAY_ATIESH = 9,
|
||||||
|
EMOTE_ARCANE_EXPLOSION = 10
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Spells
|
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
|
void Reset() override
|
||||||
{
|
{
|
||||||
BossAI::Reset();
|
BossAI::Reset();
|
||||||
_drinkScheduler.CancelAll();
|
_drinkScheduler.CancelAll();
|
||||||
LastSuperSpell = rand() % 3;
|
_lastSuperSpell = rand() % 3;
|
||||||
|
|
||||||
for (uint8 i = 0; i < 3; ++i)
|
for (uint8 i = 0; i < 3; ++i)
|
||||||
FlameWreathTarget[i].Clear();
|
FlameWreathTarget[i].Clear();
|
||||||
@@ -127,9 +121,7 @@ struct boss_shade_of_aran : public BossAI
|
|||||||
_frostCooledDown = true;
|
_frostCooledDown = true;
|
||||||
|
|
||||||
_drinking = false;
|
_drinking = false;
|
||||||
|
_hasDrunk = false;
|
||||||
// Not in progress
|
|
||||||
instance->SetData(DATA_ARAN, NOT_STARTED);
|
|
||||||
|
|
||||||
if (GameObject* libraryDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_GO_LIBRARY_DOOR)))
|
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
|
void JustEngagedWith(Unit* /*who*/) override
|
||||||
{
|
{
|
||||||
_JustEngagedWith();
|
_JustEngagedWith();
|
||||||
@@ -222,11 +233,14 @@ struct boss_shade_of_aran : public BossAI
|
|||||||
}
|
}
|
||||||
}).Schedule(1s, [this](TaskContext context)
|
}).Schedule(1s, [this](TaskContext context)
|
||||||
{
|
{
|
||||||
if (!me->IsNonMeleeSpellCast(false) && !_drinking)
|
context.Repeat(2s);
|
||||||
|
|
||||||
|
if (!_drinking)
|
||||||
{
|
{
|
||||||
Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true);
|
if (me->IsNonMeleeSpellCast(false))
|
||||||
if (!target)
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
uint32 Spells[3];
|
uint32 Spells[3];
|
||||||
uint8 AvailableSpells = 0;
|
uint8 AvailableSpells = 0;
|
||||||
@@ -248,27 +262,69 @@ struct boss_shade_of_aran : public BossAI
|
|||||||
++AvailableSpells;
|
++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 no available spells wait 1 second and try again
|
||||||
if (AvailableSpells)
|
if (AvailableSpells)
|
||||||
{
|
{
|
||||||
CurrentNormalSpell = Spells[rand() % AvailableSpells];
|
CurrentNormalSpell = Spells[rand() % AvailableSpells];
|
||||||
|
|
||||||
if (!me->CanCastSpell(CurrentNormalSpell))
|
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(CurrentNormalSpell))
|
||||||
{
|
{
|
||||||
me->SetWalk(false);
|
if (int32(me->GetPower(POWER_MANA)) < spellInfo->CalcPowerCost(me, (SpellSchoolMask)spellInfo->SchoolMask))
|
||||||
me->ResumeChasingVictim();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DoCast(target, CurrentNormalSpell);
|
|
||||||
if (me->GetVictim())
|
|
||||||
{
|
{
|
||||||
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)
|
}).Schedule(5s, [this](TaskContext context)
|
||||||
{
|
{
|
||||||
if (!_drinking)
|
if (!_drinking)
|
||||||
@@ -284,13 +340,17 @@ struct boss_shade_of_aran : public BossAI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
context.Repeat(5s, 20s);
|
context.Repeat(5s, 20s);
|
||||||
}).Schedule(35s, [this](TaskContext context)
|
}).Schedule(6s, [this](TaskContext context)
|
||||||
{
|
{
|
||||||
if (!_drinking)
|
if (!_drinking)
|
||||||
{
|
{
|
||||||
|
me->ClearProhibitedSpellTimers();
|
||||||
|
|
||||||
|
DoCastSelf(SPELL_BLINK_CENTER, true);
|
||||||
|
|
||||||
uint8 Available[2];
|
uint8 Available[2];
|
||||||
|
|
||||||
switch (LastSuperSpell)
|
switch (_lastSuperSpell)
|
||||||
{
|
{
|
||||||
case SUPER_AE:
|
case SUPER_AE:
|
||||||
Available[0] = SUPER_FLAME;
|
Available[0] = SUPER_FLAME;
|
||||||
@@ -306,14 +366,13 @@ struct boss_shade_of_aran : public BossAI
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
LastSuperSpell = Available[urand(0, 1)];
|
_lastSuperSpell = Available[urand(0, 1)];
|
||||||
|
|
||||||
switch (LastSuperSpell)
|
switch (_lastSuperSpell)
|
||||||
{
|
{
|
||||||
case SUPER_AE:
|
case SUPER_AE:
|
||||||
Talk(SAY_EXPLOSION);
|
Talk(SAY_EXPLOSION);
|
||||||
|
Talk(EMOTE_ARCANE_EXPLOSION);
|
||||||
DoCastSelf(SPELL_BLINK_CENTER, true);
|
|
||||||
DoCastSelf(SPELL_PLAYERPULL, true);
|
DoCastSelf(SPELL_PLAYERPULL, true);
|
||||||
DoCastSelf(SPELL_MASSSLOW, true);
|
DoCastSelf(SPELL_MASSSLOW, true);
|
||||||
DoCastSelf(SPELL_AEXPLOSION, false);
|
DoCastSelf(SPELL_AEXPLOSION, false);
|
||||||
@@ -356,56 +415,6 @@ struct boss_shade_of_aran : public BossAI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
context.Repeat(35s, 40s);
|
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)
|
}).Schedule(12min, [this](TaskContext context)
|
||||||
{
|
{
|
||||||
for (uint32 i = 0; i < 5; ++i)
|
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))
|
Spell->Effects[2].Effect != SPELL_EFFECT_INTERRUPT_CAST) || !me->IsNonMeleeSpellCast(false))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//Interrupt effect
|
|
||||||
me->InterruptNonMeleeSpells(false);
|
|
||||||
|
|
||||||
//Normally we would set the cooldown equal to the spell duration
|
//Normally we would set the cooldown equal to the spell duration
|
||||||
//but we do not have access to the DurationStore
|
//but we do not have access to the DurationStore
|
||||||
|
|
||||||
@@ -506,11 +512,19 @@ struct boss_shade_of_aran : public BossAI
|
|||||||
private:
|
private:
|
||||||
TaskScheduler _drinkScheduler;
|
TaskScheduler _drinkScheduler;
|
||||||
|
|
||||||
|
uint32 _lastSuperSpell;
|
||||||
|
|
||||||
|
ObjectGuid FlameWreathTarget[3];
|
||||||
|
float FWTargPosX[3];
|
||||||
|
float FWTargPosY[3];
|
||||||
|
|
||||||
|
uint32 CurrentNormalSpell;
|
||||||
|
|
||||||
bool _arcaneCooledDown;
|
bool _arcaneCooledDown;
|
||||||
bool _fireCooledDown;
|
bool _fireCooledDown;
|
||||||
bool _frostCooledDown;
|
bool _frostCooledDown;
|
||||||
bool _drinking;
|
bool _drinking;
|
||||||
uint32 _currentHealth;
|
bool _hasDrunk;
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_shade_of_aran()
|
void AddSC_boss_shade_of_aran()
|
||||||
|
|||||||
Reference in New Issue
Block a user