Scripts/AhnKahet: Update Herald Volazj to current coding standards

* convert to BossAI
* no functional changes

(cherry picked from commit 90543fd41d)
This commit is contained in:
Carbenium
2020-08-01 15:49:37 +02:00
committed by Shauren
parent 18e5e1ef43
commit 7e0fb710ad

View File

@@ -60,242 +60,251 @@ enum Achievements
ACHIEV_QUICK_DEMISE_START_EVENT = 20382,
};
class boss_volazj : public CreatureScript
struct boss_volazj : public BossAI
{
public:
boss_volazj() : CreatureScript("boss_volazj") { }
struct boss_volazjAI : public ScriptedAI
boss_volazj(Creature* creature) : BossAI(creature, DATA_HERALD_VOLAZJ), _insanityHandled(0)
{
boss_volazjAI(Creature* creature) : ScriptedAI(creature), Summons(me)
{
Initialize();
instance = creature->GetInstanceScript();
}
Initialize();
_instance = creature->GetInstanceScript();
}
void Initialize()
{
uiMindFlayTimer = 8 * IN_MILLISECONDS;
uiShadowBoltVolleyTimer = 5 * IN_MILLISECONDS;
uiShiverTimer = 15 * IN_MILLISECONDS;
// Used for Insanity handling
insanityHandled = 0;
}
void Reset() override
{
BossAI::Reset();
InstanceScript* instance;
Initialize();
uint32 uiMindFlayTimer;
uint32 uiShadowBoltVolleyTimer;
uint32 uiShiverTimer;
uint32 insanityHandled;
SummonList Summons;
_instance->DoStopCriteriaTimer(CriteriaStartEvent::SendEvent, ACHIEV_QUICK_DEMISE_START_EVENT);
// returns the percentage of health after taking the given damage.
uint32 GetHealthPct(uint32 damage)
{
if (damage > me->GetHealth())
return 0;
return 100*(me->GetHealth()-damage)/me->GetMaxHealth();
}
// Visible for all players in insanity
for (uint32 i = 173; i <= 177; ++i)
PhasingHandler::AddPhase(me, i, false);
PhasingHandler::AddPhase(me, 169, true);
void DamageTaken(Unit* /*pAttacker*/, uint32 &damage) override
{
if (me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE))
damage = 0;
ResetPlayersPhaseMask();
if ((GetHealthPct(0) >= 66 && GetHealthPct(damage) < 66)||
(GetHealthPct(0) >= 33 && GetHealthPct(damage) < 33))
// Cleanup
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetControlled(false, UNIT_STATE_STUNNED);
}
void Initialize()
{
// Used for Insanity handling
_insanityHandled = 0;
}
void ScheduleTasks() override
{
scheduler.Schedule(8s, [this](TaskContext task)
{
me->InterruptNonMeleeSpells(false);
DoCast(me, SPELL_INSANITY, false);
}
}
void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_INSANITY)
DoCastVictim(SPELL_MIND_FLAY);
task.Repeat(20s);
})
.Schedule(5s, [this](TaskContext task)
{
// Not good target or too many players
if (target->GetTypeId() != TYPEID_PLAYER || insanityHandled > 4)
return;
// First target - start channel visual and set self as unnattackable
if (!insanityHandled)
{
// Channel visual
DoCast(me, INSANITY_VISUAL, true);
// Unattackable
me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetControlled(true, UNIT_STATE_STUNNED);
}
DoCastVictim(SPELL_SHADOW_BOLT_VOLLEY);
task.Repeat();
})
.Schedule(15s, [this](TaskContext task)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
DoCast(target, SPELL_SHIVER);
task.Repeat();
});
}
// phase the player
target->CastSpell(target, SPELL_INSANITY_TARGET + insanityHandled, true);
// returns the percentage of health after taking the given damage.
uint32 GetHealthPct(uint32 damage)
{
if (damage > me->GetHealth())
return 0;
return 100*(me->GetHealth()-damage)/me->GetMaxHealth();
}
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_INSANITY_TARGET + insanityHandled, GetDifficulty());
if (!spellInfo)
return;
void DamageTaken(Unit* /*pAttacker*/, uint32 &damage) override
{
if (me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE))
damage = 0;
// summon twisted party members for this target
Map::PlayerList const& players = me->GetMap()->GetPlayers();
for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i)
{
Player* player = i->GetSource();
if (!player || !player->IsAlive())
continue;
// Summon clone
if (Unit* summon = me->SummonCreature(NPC_TWISTED_VISAGE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_CORPSE_DESPAWN))
{
// clone
player->CastSpell(summon, SPELL_CLONE_PLAYER, true);
// phase the summon
PhasingHandler::AddPhase(summon, spellInfo->GetEffect(EFFECT_0).MiscValueB, true);
}
}
++insanityHandled;
}
}
void ResetPlayersPhase()
if ((GetHealthPct(0) >= 66 && GetHealthPct(damage) < 66)||
(GetHealthPct(0) >= 33 && GetHealthPct(damage) < 33))
{
me->InterruptNonMeleeSpells(false);
DoCast(me, SPELL_INSANITY, false);
}
}
void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_INSANITY)
{
// Not good target or too many players
if (target->GetTypeId() != TYPEID_PLAYER || _insanityHandled > 4)
return;
// First target - start channel visual and set self as unnattackable
if (!_insanityHandled)
{
// Channel visual
DoCast(me, INSANITY_VISUAL, true);
// Unattackable
me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetControlled(true, UNIT_STATE_STUNNED);
}
// phase mask
target->CastSpell(target, SPELL_INSANITY_TARGET + _insanityHandled, true);
// summon twisted party members for this target
Map::PlayerList const& players = me->GetMap()->GetPlayers();
for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i)
{
Player* player = i->GetSource();
for (uint32 index = 0; index <= 4; ++index)
player->RemoveAurasDueToSpell(SPELL_INSANITY_TARGET + index);
}
}
void Reset() override
{
Initialize();
instance->SetBossState(DATA_HERALD_VOLAZJ, NOT_STARTED);
instance->DoStopCriteriaTimer(CriteriaStartEvent::SendEvent, ACHIEV_QUICK_DEMISE_START_EVENT);
// Visible for all players in insanity
for (uint32 i = 173; i <= 177; ++i)
PhasingHandler::AddPhase(me, i, false);
PhasingHandler::AddPhase(me, 169, true);
ResetPlayersPhase();
// Cleanup
Summons.DespawnAll();
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetControlled(false, UNIT_STATE_STUNNED);
}
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
instance->SetBossState(DATA_HERALD_VOLAZJ, IN_PROGRESS);
instance->DoStartCriteriaTimer(CriteriaStartEvent::SendEvent, ACHIEV_QUICK_DEMISE_START_EVENT);
}
void JustSummoned(Creature* summon) override
{
Summons.Summon(summon);
}
void SummonedCreatureDespawn(Creature* summon) override
{
uint32 nextPhase = 0;
Summons.Despawn(summon);
// Check if all summons in this phase killed
for (SummonList::const_iterator iter = Summons.begin(); iter != Summons.end(); ++iter)
{
if (Creature* visage = ObjectAccessor::GetCreature(*me, *iter))
if (!player || !player->IsAlive())
continue;
// Summon clone
if (Unit* summon = me->SummonCreature(NPC_TWISTED_VISAGE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_CORPSE_DESPAWN))
{
// Not all are dead
if (visage->IsInPhase(summon))
return;
else
{
nextPhase = visage->GetPhaseShift().GetPhases().begin()->Id;
break;
}
// clone
player->CastSpell(summon, SPELL_CLONE_PLAYER, true);
// set phase
PhasingHandler::AddPhase(summon, 173 + _insanityHandled, true);
}
}
++_insanityHandled;
}
}
// Roll Insanity
Map::PlayerList const& players = me->GetMap()->GetPlayers();
for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i)
void ResetPlayersPhaseMask()
{
Map::PlayerList const& players = me->GetMap()->GetPlayers();
for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i)
{
Player* player = i->GetSource();
for (uint32 index = 0; index <= 4; ++index)
player->RemoveAurasDueToSpell(SPELL_INSANITY_TARGET + index);
}
}
void JustEngagedWith(Unit* who) override
{
BossAI::JustEngagedWith(who);
Talk(SAY_AGGRO);
_instance->DoStartCriteriaTimer(CriteriaStartEvent::SendEvent, ACHIEV_QUICK_DEMISE_START_EVENT);
}
uint32 GetSpellForPhaseMask(uint32 phase)
{
uint32 spell = 0;
switch (phase)
{
case 173:
spell = SPELL_INSANITY_PHASING_1;
break;
case 174:
spell = SPELL_INSANITY_PHASING_2;
break;
case 175:
spell = SPELL_INSANITY_PHASING_3;
break;
case 176:
spell = SPELL_INSANITY_PHASING_4;
break;
case 177:
spell = SPELL_INSANITY_PHASING_5;
break;
}
return spell;
}
void SummonedCreatureDespawn(Creature* summon) override
{
BossAI::SummonedCreatureDespawn(summon);
uint32 phase = !summon->GetPhaseShift().GetPhases().empty() ? summon->GetPhaseShift().GetPhases().begin()->Id : 0;
uint32 nextPhase = 0;
// Check if all summons in this phase killed
for (SummonList::const_iterator iter = summons.begin(); iter != summons.end(); ++iter)
{
if (Creature* visage = ObjectAccessor::GetCreature(*me, *iter))
{
// Not all are dead
if (visage->IsInPhase(summon))
return;
else if (!visage->GetPhaseShift().GetPhases().empty())
{
nextPhase = visage->GetPhaseShift().GetPhases().begin()->Id;
break;
}
}
}
// Roll Insanity
uint32 spell = GetSpellForPhaseMask(phase);
uint32 spell2 = GetSpellForPhaseMask(nextPhase);
Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers();
if (!PlayerList.isEmpty())
{
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
if (Player* player = i->GetSource())
{
for (uint32 index = 0; index <= 4; ++index)
player->RemoveAurasDueToSpell(SPELL_INSANITY_TARGET + index);
player->CastSpell(player, SPELL_INSANITY_TARGET + nextPhase - 173, true);
if (player->HasAura(spell))
{
player->RemoveAurasDueToSpell(spell);
if (spell2) // if there is still some different mask cast spell for it
player->CastSpell(player, spell2, true);
}
}
}
}
}
void UpdateAI(uint32 diff) override
void UpdateAI(uint32 diff) override
{
//Return since we have no target
if (!UpdateVictim())
return;
if (_insanityHandled)
{
//Return since we have no target
if (!UpdateVictim())
if (!summons.empty())
return;
if (insanityHandled)
{
if (!Summons.empty())
return;
insanityHandled = 0;
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetControlled(false, UNIT_STATE_STUNNED);
me->RemoveAurasDueToSpell(INSANITY_VISUAL);
}
if (uiMindFlayTimer <= diff)
{
DoCastVictim(SPELL_MIND_FLAY);
uiMindFlayTimer = 20*IN_MILLISECONDS;
} else uiMindFlayTimer -= diff;
if (uiShadowBoltVolleyTimer <= diff)
{
DoCastVictim(SPELL_SHADOW_BOLT_VOLLEY);
uiShadowBoltVolleyTimer = 5*IN_MILLISECONDS;
} else uiShadowBoltVolleyTimer -= diff;
if (uiShiverTimer <= diff)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
DoCast(target, SPELL_SHIVER);
uiShiverTimer = 15*IN_MILLISECONDS;
} else uiShiverTimer -= diff;
_insanityHandled = 0;
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetControlled(false, UNIT_STATE_STUNNED);
me->RemoveAurasDueToSpell(INSANITY_VISUAL);
}
scheduler.Update(diff, [this]
{
DoMeleeAttackIfReady();
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
instance->SetBossState(DATA_HERALD_VOLAZJ, DONE);
Summons.DespawnAll();
ResetPlayersPhase();
}
void KilledUnit(Unit* who) override
{
if (who->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetAhnKahetAI<boss_volazjAI>(creature);
});
}
void JustDied(Unit* killer) override
{
BossAI::JustDied(killer);
Talk(SAY_DEATH);
ResetPlayersPhaseMask();
}
void KilledUnit(Unit* who) override
{
if (who->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
private:
InstanceScript* _instance;
uint32 _insanityHandled;
};
void AddSC_boss_volazj()
{
new boss_volazj();
RegisterAhnKahetCreatureAI(boss_volazj);
}