mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-18 16:38:42 +01:00
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:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user