refactor(Scripts/AhnKahet): new script system (#9040)

This commit is contained in:
Kitzunu
2021-11-28 08:23:19 +01:00
committed by GitHub
parent 801a20fce2
commit 05a2d5baa8
7 changed files with 1619 additions and 1819 deletions

View File

@@ -71,4 +71,7 @@ inline AI* GetAhnKahetAI(T* obj)
return GetInstanceAI<AI>(obj, AhnKahetScriptName);
}
#define RegisterAhnKahetCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetAhnKahetAI)
#define RegisterAhnKahetGameObjectAI(ai_name) RegisterGameObjectAIWithFactory(ai_name, GetAhnKahetAI)
#endif // DEF_AHNKAHET_H

View File

@@ -99,288 +99,253 @@ Position const MushroomPositions[MAX_MUSHROOMS_COUNT] =
{ 398.2797f, -851.8694f, -68.84419f, 0.5759587f }
};
class boss_amanitar : public CreatureScript
struct boss_amanitar : public BossAI
{
public:
boss_amanitar() : CreatureScript("boss_amanitar")
boss_amanitar(Creature* creature) : BossAI(creature, DATA_AMANITAR), mushroomsSummoned(false)
{
creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true);
creature->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE);
}
struct boss_amanitarAI : public BossAI
void Reset() override
{
boss_amanitarAI(Creature* creature) : BossAI(creature, DATA_AMANITAR), mushroomsSummoned(false)
_Reset();
_mushroomsDeque.clear();
mushroomsSummoned = false;
}
void EnterCombat(Unit* /*attacker*/) override
{
events.ScheduleEvent(EVENT_ROOTS, urand(5000, 9000));
events.ScheduleEvent(EVENT_BASH, urand(10000, 14000));
events.ScheduleEvent(EVENT_BOLT, urand(15000, 20000));
events.ScheduleEvent(EVENT_MINI, 1000);
events.ScheduleEvent(EVENT_RESPAWN, 40000, 60000);
}
void JustDied(Unit* /*Killer*/) override
{
_JustDied();
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI);
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
}
void SummonedCreatureDies(Creature* summon, Unit* killer) override
{
_mushroomsDeque.push_back(summon->GetPosition());
BossAI::SummonedCreatureDies(summon, killer);
}
void EnterEvadeMode() override
{
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI);
BossAI::EnterEvadeMode();
}
void ExecuteEvent(uint32 eventId) override
{
switch (eventId)
{
creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true);
creature->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE);
case EVENT_RESPAWN:
{
while (!_mushroomsDeque.empty())
{
SummonMushroom(_mushroomsDeque.front());
_mushroomsDeque.pop_front();
}
events.RepeatEvent(urand(40000, 60000));
break;
}
case EVENT_ROOTS:
{
if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
{
DoCast(pTarget, SPELL_ENTANGLING_ROOTS, false);
}
events.RepeatEvent(urand(10000, 15000));
break;
}
case EVENT_BASH:
{
DoCastVictim(SPELL_BASH, false);
events.RepeatEvent(urand(15000, 20000));
break;
}
case EVENT_BOLT:
{
if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
{
DoCast(pTarget, SPELL_VENOM_BOLT_VOLLEY, false);
}
events.RepeatEvent(urand(15000, 20000));
break;
}
case EVENT_REMOVE_MUSHROOM_POWER:
{
DoCastAOE(SPELL_REMOVE_MUSHROOM_POWER, true);
events.RescheduleEvent(EVENT_MINI, 1000);
break;
}
case EVENT_MINI:
{
if (!mushroomsSummoned)
{
mushroomsSummoned = true;
for (uint8 i = 0; i < MAX_MUSHROOMS_COUNT; ++i)
{
SummonMushroom(MushroomPositions[i]);
}
}
if (SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_MINI))
{
DoCastSelf(SPELL_REMOVE_MUSHROOM_POWER, true);
DoCastAOE(SPELL_MINI);
events.RescheduleEvent(EVENT_REMOVE_MUSHROOM_POWER, 29000);
}
else
{
events.RepeatEvent(1000);
}
break;
}
}
}
private:
std::deque<Position> _mushroomsDeque;
bool mushroomsSummoned;
void SummonMushroom(Position const& pos)
{
me->SummonCreature(roll_chance_i(40) ? NPC_HEALTHY_MUSHROOM : NPC_POISONOUS_MUSHROOM, pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 4000);
}
};
struct npc_amanitar_mushrooms : public ScriptedAI
{
npc_amanitar_mushrooms(Creature* pCreature) : ScriptedAI(pCreature)
{
SetCombatMovement(false);
//TODO: this prolly needs to be done in database
pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
pCreature->SetRegeneratingHealth(false);
}
// Disabled events
void EnterCombat(Unit* /*who*/) override {}
void AttackStart(Unit* /*victim*/) override {}
void EnterEvadeMode() override {}
void Reset() override
{
me->SetReactState(REACT_PASSIVE);
DoCastSelf(SPELL_PUTRID_MUSHROOM);
if (me->GetEntry() == NPC_POISONOUS_MUSHROOM)
{
DoCastSelf(SPELL_POISONOUS_MUSHROOM_VISUAL_AURA, true);
}
else
{
DoCastSelf(SPELL_HEALTHY_MUSHROOM_VISUAL_AURA, true);
}
void Reset() override
{
_Reset();
_mushroomsDeque.clear();
mushroomsSummoned = false;
}
events.ScheduleEvent(EVENT_GROW, 800);
void EnterCombat(Unit* /*attacker*/) override
if (me->GetEntry() == NPC_POISONOUS_MUSHROOM)
{
events.ScheduleEvent(EVENT_ROOTS, urand(5000, 9000));
events.ScheduleEvent(EVENT_BASH, urand(10000, 14000));
events.ScheduleEvent(EVENT_BOLT, urand(15000, 20000));
events.ScheduleEvent(EVENT_MINI, 1000);
events.ScheduleEvent(EVENT_RESPAWN, 40000, 60000);
events.ScheduleEvent(EVENT_CHECK_PLAYER, 250);
}
}
void JustDied(Unit* /*Killer*/) override
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
{
if (me->GetEntry() == NPC_HEALTHY_MUSHROOM && damage >= me->GetHealth())
{
_JustDied();
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI);
DoCastSelf(SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS, true);
}
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
}
void UpdateAI(uint32 diff) override
{
if (events.Empty())
return;
void SummonedCreatureDies(Creature* summon, Unit* killer) override
{
_mushroomsDeque.push_back(summon->GetPosition());
BossAI::SummonedCreatureDies(summon, killer);
}
void EnterEvadeMode() override
{
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI);
BossAI::EnterEvadeMode();
}
void ExecuteEvent(uint32 eventId) override
events.Update(diff);
while (uint32 const eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_RESPAWN:
case EVENT_GROW:
{
while (!_mushroomsDeque.empty())
{
SummonMushroom(_mushroomsDeque.front());
_mushroomsDeque.pop_front();
}
events.RepeatEvent(urand(40000, 60000));
DoCastSelf(SPELL_GROW);
break;
}
case EVENT_ROOTS:
case EVENT_CHECK_PLAYER:
{
if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
if (Player* plr = me->SelectNearestPlayer(2.0f))
{
DoCast(pTarget, SPELL_ENTANGLING_ROOTS, false);
}
events.RepeatEvent(urand(10000, 15000));
break;
}
case EVENT_BASH:
{
DoCastVictim(SPELL_BASH, false);
events.RepeatEvent(urand(15000, 20000));
break;
}
case EVENT_BOLT:
{
if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
{
DoCast(pTarget, SPELL_VENOM_BOLT_VOLLEY, false);
}
events.RepeatEvent(urand(15000, 20000));
break;
}
case EVENT_REMOVE_MUSHROOM_POWER:
{
DoCastAOE(SPELL_REMOVE_MUSHROOM_POWER, true);
events.RescheduleEvent(EVENT_MINI, 1000);
break;
}
case EVENT_MINI:
{
if (!mushroomsSummoned)
{
mushroomsSummoned = true;
for (uint8 i = 0; i < MAX_MUSHROOMS_COUNT; ++i)
{
SummonMushroom(MushroomPositions[i]);
}
}
if (SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_MINI))
{
DoCastSelf(SPELL_REMOVE_MUSHROOM_POWER, true);
DoCastAOE(SPELL_MINI);
events.RescheduleEvent(EVENT_REMOVE_MUSHROOM_POWER, 29000);
plr->RemoveAurasDueToSpell(SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS);
DoCastSelf(SPELL_POISONOUS_MUSHROOM_VISUAL_AREA);
DoCastSelf(SPELL_POISONOUS_MUSHROOM_POISON_CLOUD);
DoCastSelf(SPELL_SHRINK);
events.ScheduleEvent(EVENT_KILLSELF, 4000);
}
else
{
events.RepeatEvent(1000);
events.RepeatEvent(250);
}
break;
}
}
}
private:
std::deque<Position> _mushroomsDeque;
bool mushroomsSummoned;
void SummonMushroom(Position const& pos)
{
me->SummonCreature(roll_chance_i(40) ? NPC_HEALTHY_MUSHROOM : NPC_POISONOUS_MUSHROOM, pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 4000);
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetAhnKahetAI<boss_amanitarAI>(creature);
}
};
class npc_amanitar_mushrooms : public CreatureScript
{
public:
npc_amanitar_mushrooms() : CreatureScript("npc_amanitar_mushrooms") { }
struct npc_amanitar_mushroomsAI : public ScriptedAI
{
npc_amanitar_mushroomsAI(Creature* pCreature) : ScriptedAI(pCreature)
{
SetCombatMovement(false);
//TODO: this prolly needs to be done in database
pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
pCreature->SetRegeneratingHealth(false);
}
// Disabled events
void EnterCombat(Unit* /*who*/) override {}
void AttackStart(Unit* /*victim*/) override {}
void EnterEvadeMode() override {}
void Reset() override
{
me->SetReactState(REACT_PASSIVE);
DoCastSelf(SPELL_PUTRID_MUSHROOM);
if (me->GetEntry() == NPC_POISONOUS_MUSHROOM)
{
DoCastSelf(SPELL_POISONOUS_MUSHROOM_VISUAL_AURA, true);
}
else
{
DoCastSelf(SPELL_HEALTHY_MUSHROOM_VISUAL_AURA, true);
}
events.ScheduleEvent(EVENT_GROW, 800);
if (me->GetEntry() == NPC_POISONOUS_MUSHROOM)
{
events.ScheduleEvent(EVENT_CHECK_PLAYER, 250);
}
}
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
{
if (me->GetEntry() == NPC_HEALTHY_MUSHROOM && damage >= me->GetHealth())
{
DoCastSelf(SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS, true);
}
}
void UpdateAI(uint32 diff) override
{
if (events.Empty())
return;
events.Update(diff);
while (uint32 const eventId = events.ExecuteEvent())
{
switch (eventId)
case EVENT_KILLSELF:
{
case EVENT_GROW:
{
DoCastSelf(SPELL_GROW);
break;
}
case EVENT_CHECK_PLAYER:
{
if (Player* plr = me->SelectNearestPlayer(2.0f))
{
plr->RemoveAurasDueToSpell(SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS);
DoCastSelf(SPELL_POISONOUS_MUSHROOM_VISUAL_AREA);
DoCastSelf(SPELL_POISONOUS_MUSHROOM_POISON_CLOUD);
DoCastSelf(SPELL_SHRINK);
events.ScheduleEvent(EVENT_KILLSELF, 4000);
}
else
{
events.RepeatEvent(250);
}
break;
}
case EVENT_KILLSELF:
{
me->DisappearAndDie();
break;
}
me->DisappearAndDie();
break;
}
}
}
private:
EventMap events;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetAhnKahetAI<npc_amanitar_mushroomsAI>(creature);
}
private:
EventMap events;
};
// 57283 Remove Mushroom Power
class spell_amanitar_remove_mushroom_power : public SpellScriptLoader
class spell_amanitar_remove_mushroom_power : public AuraScript
{
public:
spell_amanitar_remove_mushroom_power() : SpellScriptLoader("spell_amanitar_remove_mushroom_power") { }
PrepareAuraScript(spell_amanitar_remove_mushroom_power);
class spell_amanitar_remove_mushroom_power_AuraScript : public AuraScript
void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
PrepareAuraScript(spell_amanitar_remove_mushroom_power_AuraScript);
void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
if (Unit* target = GetTarget())
{
if (Unit* target = GetTarget())
{
target->RemoveAurasDueToSpell(SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS);
}
target->RemoveAurasDueToSpell(SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS);
}
}
void Register() override
{
OnEffectApply += AuraEffectApplyFn(spell_amanitar_remove_mushroom_power_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const
void Register() override
{
return new spell_amanitar_remove_mushroom_power_AuraScript();
OnEffectApply += AuraEffectApplyFn(spell_amanitar_remove_mushroom_power::HandleApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
void AddSC_boss_amanitar()
{
new boss_amanitar();
new npc_amanitar_mushrooms();
RegisterAhnKahetCreatureAI(boss_amanitar);
RegisterAhnKahetCreatureAI(npc_amanitar_mushrooms);
// Spells
new spell_amanitar_remove_mushroom_power();
RegisterSpellScript(spell_amanitar_remove_mushroom_power);
}

View File

@@ -69,336 +69,303 @@ enum Yells
EMOTE_HATCHES = 4
};
class boss_elder_nadox : public CreatureScript
struct boss_elder_nadox : public BossAI
{
public:
boss_elder_nadox() : CreatureScript("boss_elder_nadox") { }
struct boss_elder_nadoxAI : public BossAI
boss_elder_nadox(Creature* creature) : BossAI(creature, DATA_PRINCE_TALDARAM),
guardianSummoned(false),
respectYourElders(true)
{
boss_elder_nadoxAI(Creature* creature) : BossAI(creature, DATA_PRINCE_TALDARAM),
guardianSummoned(false),
respectYourElders(true)
}
void Reset() override
{
_Reset();
// Clear eggs data
swarmEggs.clear();
guardianEggs.clear();
previousSwarmEgg_GUID.Clear();
guardianSummoned = false;
respectYourElders = true;
}
void EnterCombat(Unit * /*who*/) override
{
_EnterCombat();
Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_SWARMER, 10000);
events.ScheduleEvent(EVENT_CHECK_HOME, 2000);
events.ScheduleEvent(EVENT_PLAGUE, urand(5000, 8000));
if (IsHeroic())
{
events.ScheduleEvent(EVENT_BROOD_RAGE, 5000);
}
void Reset() override
// Cache eggs
std::list<Creature*> eggs;
// Swarm eggs
me->GetCreatureListWithEntryInGrid(eggs, NPC_AHNKAHAR_SWARM_EGG, 250.0f);
if (!eggs.empty())
{
_Reset();
// Clear eggs data
swarmEggs.clear();
guardianEggs.clear();
previousSwarmEgg_GUID.Clear();
guardianSummoned = false;
respectYourElders = true;
}
void EnterCombat(Unit * /*who*/) override
{
_EnterCombat();
Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_SWARMER, 10000);
events.ScheduleEvent(EVENT_CHECK_HOME, 2000);
events.ScheduleEvent(EVENT_PLAGUE, urand(5000, 8000));
if (IsHeroic())
for (Creature* const egg : eggs)
{
events.ScheduleEvent(EVENT_BROOD_RAGE, 5000);
}
// Cache eggs
std::list<Creature*> eggs;
// Swarm eggs
me->GetCreatureListWithEntryInGrid(eggs, NPC_AHNKAHAR_SWARM_EGG, 250.0f);
if (!eggs.empty())
{
for (Creature* const egg : eggs)
if (egg)
{
if (egg)
{
swarmEggs.push_back(egg->GetGUID());
}
}
}
eggs.clear();
// Guardian eggs
me->GetCreatureListWithEntryInGrid(eggs, NPC_AHNKAHAR_GUARDIAN_EGG, 250.0f);
if (!eggs.empty())
{
for (Creature* const egg : eggs)
{
if (egg)
{
guardianEggs.push_back(egg->GetGUID());
}
swarmEggs.push_back(egg->GetGUID());
}
}
}
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
eggs.clear();
// Guardian eggs
me->GetCreatureListWithEntryInGrid(eggs, NPC_AHNKAHAR_GUARDIAN_EGG, 250.0f);
if (!eggs.empty())
{
if (summon->GetEntry() == NPC_AHNKAHAR_GUARDIAN)
for (Creature* const egg : eggs)
{
respectYourElders = false;
if (egg)
{
guardianEggs.push_back(egg->GetGUID());
}
}
}
}
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
{
if (summon->GetEntry() == NPC_AHNKAHAR_GUARDIAN)
{
respectYourElders = false;
}
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
{
Talk(SAY_SLAY);
}
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
}
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*school*/) override
{
if (!guardianSummoned && me->HealthBelowPctDamaged(55, damage))
{
SummonHelpers(false);
guardianSummoned = true;
}
}
uint32 GetData(uint32 type) const override
{
if (type == DATA_RESPECT_YOUR_ELDERS)
{
return respectYourElders ? 1 : 0;
}
return 0;
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
{
return;
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
{
return;
}
while (uint32 const eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_BROOD_RAGE:
{
if (Creature* pSwarmer = me->FindNearestCreature(NPC_AHNKAHAR_SWARMER, 40, true))
DoCast(pSwarmer, SPELL_BROOD_RAGE_H, true);
events.RepeatEvent(10000);
break;
}
case EVENT_PLAGUE:
{
DoCastVictim(SPELL_BROOD_PLAGUE, false);
events.RepeatEvent(urand(12000, 17000));
break;
}
case EVENT_SWARMER:
{
SummonHelpers(true);
events.RepeatEvent(10000);
break;
}
case EVENT_CHECK_HOME:
{
if (!me->HasAura(SPELL_ENRAGE) && (me->GetPositionZ() < 24.0f || !me->GetHomePosition().IsInDist(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 110.0f)))
{
DoCastSelf(SPELL_ENRAGE, true);
}
break;
}
}
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
{
Talk(SAY_SLAY);
}
}
DoMeleeAttackIfReady();
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
}
private:
GuidList swarmEggs;
GuidList guardianEggs;
ObjectGuid previousSwarmEgg_GUID; // This will prevent casting summoning spells on same egg twice
bool guardianSummoned;
bool respectYourElders;
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*school*/) override
void SummonHelpers(bool swarm)
{
if (swarm)
{
if (!guardianSummoned && me->HealthBelowPctDamaged(55, damage))
{
SummonHelpers(false);
guardianSummoned = true;
}
}
uint32 GetData(uint32 type) const override
{
if (type == DATA_RESPECT_YOUR_ELDERS)
{
return respectYourElders ? 1 : 0;
}
return 0;
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
if (swarmEggs.empty())
{
return;
}
events.Update(diff);
// Make a copy of guid list
GuidList swarmEggs2 = swarmEggs;
if (me->HasUnitState(UNIT_STATE_CASTING))
// Remove previous egg
if (previousSwarmEgg_GUID)
{
std::list<ObjectGuid>::iterator itr = std::find(swarmEggs2.begin(), swarmEggs2.end(), previousSwarmEgg_GUID);
if (itr != swarmEggs2.end())
{
swarmEggs2.erase(itr);
}
}
if (swarmEggs2.empty())
{
return;
}
while (uint32 const eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_BROOD_RAGE:
{
if (Creature* pSwarmer = me->FindNearestCreature(NPC_AHNKAHAR_SWARMER, 40, true))
DoCast(pSwarmer, SPELL_BROOD_RAGE_H, true);
previousSwarmEgg_GUID = Acore::Containers::SelectRandomContainerElement(swarmEggs2);
events.RepeatEvent(10000);
break;
}
case EVENT_PLAGUE:
{
DoCastVictim(SPELL_BROOD_PLAGUE, false);
events.RepeatEvent(urand(12000, 17000));
break;
}
case EVENT_SWARMER:
{
SummonHelpers(true);
events.RepeatEvent(10000);
break;
}
case EVENT_CHECK_HOME:
{
if (!me->HasAura(SPELL_ENRAGE) && (me->GetPositionZ() < 24.0f || !me->GetHomePosition().IsInDist(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 110.0f)))
{
DoCastSelf(SPELL_ENRAGE, true);
}
break;
}
}
if (Creature* egg = ObjectAccessor::GetCreature(*me, previousSwarmEgg_GUID))
{
egg->CastSpell(egg, SPELL_SUMMON_SWARMERS, true, nullptr, nullptr, me->GetGUID());
}
DoMeleeAttackIfReady();
if (roll_chance_f(33))
{
Talk(SAY_EGG_SAC);
}
}
private:
GuidList swarmEggs;
GuidList guardianEggs;
ObjectGuid previousSwarmEgg_GUID; // This will prevent casting summoning spells on same egg twice
bool guardianSummoned;
bool respectYourElders;
void SummonHelpers(bool swarm)
else
{
if (swarm)
if (guardianEggs.empty())
{
if (swarmEggs.empty())
{
return;
}
// Make a copy of guid list
GuidList swarmEggs2 = swarmEggs;
// Remove previous egg
if (previousSwarmEgg_GUID)
{
std::list<ObjectGuid>::iterator itr = std::find(swarmEggs2.begin(), swarmEggs2.end(), previousSwarmEgg_GUID);
if (itr != swarmEggs2.end())
{
swarmEggs2.erase(itr);
}
}
if (swarmEggs2.empty())
{
return;
}
previousSwarmEgg_GUID = Acore::Containers::SelectRandomContainerElement(swarmEggs2);
if (Creature* egg = ObjectAccessor::GetCreature(*me, previousSwarmEgg_GUID))
{
egg->CastSpell(egg, SPELL_SUMMON_SWARMERS, true, nullptr, nullptr, me->GetGUID());
}
if (roll_chance_f(33))
{
Talk(SAY_EGG_SAC);
}
return;
}
else
ObjectGuid const& guardianEggGUID = Acore::Containers::SelectRandomContainerElement(guardianEggs);
if (Creature* egg = ObjectAccessor::GetCreature(*me, guardianEggGUID))
{
if (guardianEggs.empty())
{
return;
}
egg->CastSpell(egg, SPELL_SUMMON_SWARM_GUARD, true, nullptr, nullptr, me->GetGUID());
}
ObjectGuid const& guardianEggGUID = Acore::Containers::SelectRandomContainerElement(guardianEggs);
if (Creature* egg = ObjectAccessor::GetCreature(*me, guardianEggGUID))
{
egg->CastSpell(egg, SPELL_SUMMON_SWARM_GUARD, true, nullptr, nullptr, me->GetGUID());
}
Talk(EMOTE_HATCHES, me);
Talk(EMOTE_HATCHES, me);
if (roll_chance_f(33))
{
Talk(SAY_EGG_SAC);
}
if (roll_chance_f(33))
{
Talk(SAY_EGG_SAC);
}
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetAhnKahetAI<boss_elder_nadoxAI>(creature);
}
};
class npc_ahnkahar_nerubian : public CreatureScript
struct npc_ahnkahar_nerubian : public ScriptedAI
{
public:
npc_ahnkahar_nerubian() : CreatureScript("npc_ahnkahar_nerubian") { }
npc_ahnkahar_nerubian(Creature* c) : ScriptedAI(c) { }
struct npc_ahnkahar_nerubianAI : public ScriptedAI
void Reset() override
{
npc_ahnkahar_nerubianAI(Creature* c) : ScriptedAI(c) { }
void Reset() override
{
DoCastSelf(me->GetEntry() == NPC_AHNKAHAR_GUARDIAN ? SPELL_GUARDIAN_AURA : SPELL_SWARMER_AURA, true);
uiSprintTimer = 10000;
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (uiSprintTimer <= diff)
{
DoCastSelf(SPELL_SPRINT, false);
uiSprintTimer = 15000;
}
else
uiSprintTimer -= diff;
DoMeleeAttackIfReady();
}
private:
uint32 uiSprintTimer;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetAhnKahetAI<npc_ahnkahar_nerubianAI>(creature);
DoCastSelf(me->GetEntry() == NPC_AHNKAHAR_GUARDIAN ? SPELL_GUARDIAN_AURA : SPELL_SWARMER_AURA, true);
uiSprintTimer = 10000;
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (uiSprintTimer <= diff)
{
DoCastSelf(SPELL_SPRINT, false);
uiSprintTimer = 15000;
}
else
uiSprintTimer -= diff;
DoMeleeAttackIfReady();
}
private:
uint32 uiSprintTimer;
};
class spell_ahn_kahet_swarmer_aura : public SpellScriptLoader
class spell_ahn_kahet_swarmer_aura : public SpellScript
{
public:
spell_ahn_kahet_swarmer_aura() : SpellScriptLoader("spell_ahn_kahet_swarmer_aura") { }
PrepareSpellScript(spell_ahn_kahet_swarmer_aura)
class spell_ahn_kahet_swarmer_aura_SpellScript : public SpellScript
void CountTargets(std::list<WorldObject*>& targets)
{
PrepareSpellScript(spell_ahn_kahet_swarmer_aura_SpellScript)
_targetCount = static_cast<uint32>(targets.size());
}
void CountTargets(std::list<WorldObject*>& targets)
void HandleDummy(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
if (_targetCount)
{
_targetCount = static_cast<uint32>(targets.size());
}
void HandleDummy(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
if (_targetCount)
if (Aura *aur = caster->GetAura(SPELL_SWARM))
{
aur->SetStackAmount(static_cast<uint8>(_targetCount));
}
else if (_targetCount)
{
// TODO: move spell id to enum
caster->CastCustomSpell(SPELL_SWARM, SPELLVALUE_AURA_STACK, _targetCount, caster, true);
if (Aura *aur = caster->GetAura(SPELL_SWARM))
{
aur->SetStackAmount(static_cast<uint8>(_targetCount));
}
else if (_targetCount)
{
// TODO: move spell id to enum
caster->CastCustomSpell(SPELL_SWARM, SPELLVALUE_AURA_STACK, _targetCount, caster, true);
if (Aura *aur = caster->GetAura(SPELL_SWARM))
{
aur->SetStackAmount(static_cast<uint8>(_targetCount));
}
}
}
else
{
caster->RemoveAurasDueToSpell(SPELL_SWARM);
}
}
uint32 _targetCount;
void Register() override
else
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ahn_kahet_swarmer_aura_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY);
OnEffectHitTarget += SpellEffectFn(spell_ahn_kahet_swarmer_aura_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
caster->RemoveAurasDueToSpell(SPELL_SWARM);
}
};
}
SpellScript* GetSpellScript() const override
uint32 _targetCount;
void Register() override
{
return new spell_ahn_kahet_swarmer_aura_SpellScript();
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ahn_kahet_swarmer_aura::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY);
OnEffectHitTarget += SpellEffectFn(spell_ahn_kahet_swarmer_aura::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
@@ -417,11 +384,11 @@ class achievement_respect_your_elders : public AchievementCriteriaScript
void AddSC_boss_elder_nadox()
{
// Creatures
new boss_elder_nadox();
new npc_ahnkahar_nerubian();
RegisterAhnKahetCreatureAI(boss_elder_nadox);
RegisterAhnKahetCreatureAI(npc_ahnkahar_nerubian);
// Spells
new spell_ahn_kahet_swarmer_aura();
RegisterSpellScript(spell_ahn_kahet_swarmer_aura);
// Achievements
new achievement_respect_your_elders();

View File

@@ -86,380 +86,357 @@ enum Events
const std::array<uint32, MAX_INSANITY_TARGETS> InsanitySpells = { SPELL_INSANITY_PHASING_1, SPELL_INSANITY_PHASING_2, SPELL_INSANITY_PHASING_3, SPELL_INSANITY_PHASING_4, SPELL_INSANITY_PHASING_5 };
class boss_volazj : public CreatureScript
struct boss_volazj : public BossAI
{
public:
boss_volazj() : CreatureScript("boss_volazj") { }
boss_volazj(Creature* pCreature) : BossAI(pCreature, DATA_HERALD_VOLAZJ),
insanityTimes(0),
insanityPhase(false)
{ }
struct boss_volazjAI : public BossAI
void InitializeAI() override
{
boss_volazjAI(Creature* pCreature) : BossAI(pCreature, DATA_HERALD_VOLAZJ),
insanityTimes(0),
insanityPhase(false)
BossAI::InitializeAI();
// Visible for all players in insanity
me->SetPhaseMask((1 | 16 | 32 | 64 | 128 | 256), true);
}
void Reset() override
{
_Reset();
insanityTimes = 0;
insanityPhase = false;
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
me->SetControlled(false, UNIT_STATE_STUNNED);
ResetPlayersPhaseMask();
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT);
}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
events.ScheduleEvent(EVENT_HERALD_MIND_FLAY, 8000);
events.ScheduleEvent(EVENT_HERALD_SHADOW, 5000);
events.ScheduleEvent(EVENT_HERALD_SHIVER, 15000);
Talk(SAY_AGGRO);
DoCastSelf(SPELL_WHISPER_AGGRO);
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT);
me->SetInCombatWithZone();
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
me->SetControlled(false, UNIT_STATE_STUNNED);
ResetPlayersPhaseMask();
switch (urand(0, 1))
{
case 0:
{
Talk(SAY_DEATH_1);
DoCastSelf(SPELL_WHISPER_DEATH_1, true);
break;
}
case 1:
{
Talk(SAY_DEATH_2);
DoCastSelf(SPELL_WHISPER_DEATH_2, true);
break;
}
}
}
void InitializeAI() override
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
{
BossAI::InitializeAI();
// Visible for all players in insanity
me->SetPhaseMask((1 | 16 | 32 | 64 | 128 | 256), true);
}
void Reset() override
{
_Reset();
insanityTimes = 0;
insanityPhase = false;
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
me->SetControlled(false, UNIT_STATE_STUNNED);
ResetPlayersPhaseMask();
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT);
}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
events.ScheduleEvent(EVENT_HERALD_MIND_FLAY, 8000);
events.ScheduleEvent(EVENT_HERALD_SHADOW, 5000);
events.ScheduleEvent(EVENT_HERALD_SHIVER, 15000);
Talk(SAY_AGGRO);
DoCastSelf(SPELL_WHISPER_AGGRO);
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT);
me->SetInCombatWithZone();
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
me->SetControlled(false, UNIT_STATE_STUNNED);
ResetPlayersPhaseMask();
switch (urand(0, 1))
switch (urand(0, 2))
{
case 0:
{
Talk(SAY_DEATH_1);
DoCastSelf(SPELL_WHISPER_DEATH_1, true);
Talk(SAY_SLAY_1);
DoCastSelf(SPELL_WHISPER_SLAY_1);
break;
}
case 1:
{
Talk(SAY_DEATH_2);
DoCastSelf(SPELL_WHISPER_DEATH_2, true);
Talk(SAY_SLAY_2);
DoCastSelf(SPELL_WHISPER_SLAY_2);
break;
}
case 2:
{
Talk(SAY_SLAY_3);
DoCastSelf(SPELL_WHISPER_SLAY_3);
break;
}
}
}
}
void KilledUnit(Unit* victim) override
void SetData(uint32 type, uint32 value) override
{
if (type == DATA_SET_INSANITY_PHASE)
{
if (victim->GetTypeId() == TYPEID_PLAYER)
{
switch (urand(0, 2))
{
case 0:
{
Talk(SAY_SLAY_1);
DoCastSelf(SPELL_WHISPER_SLAY_1);
break;
}
case 1:
{
Talk(SAY_SLAY_2);
DoCastSelf(SPELL_WHISPER_SLAY_2);
break;
}
case 2:
{
Talk(SAY_SLAY_3);
DoCastSelf(SPELL_WHISPER_SLAY_3);
break;
}
}
}
insanityPhase = (value != 0);
}
}
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
{
// Do not perform insanity recast if boss is casting Insanity already
if (me->FindCurrentSpellBySpellId(SPELL_INSANITY))
{
return;
}
void SetData(uint32 type, uint32 value) override
// First insanity
if (insanityTimes == 0 && me->HealthBelowPctDamaged(66, damage))
{
if (type == DATA_SET_INSANITY_PHASE)
{
insanityPhase = (value != 0);
}
DoCastSelf(SPELL_INSANITY, false);
++insanityTimes;
}
// Second insanity
else if (insanityTimes == 1 && me->HealthBelowPctDamaged(33, damage))
{
me->InterruptNonMeleeSpells(false);
DoCastSelf(SPELL_INSANITY, false);
++insanityTimes;
}
}
void UpdateAI(uint32 diff) override
{
//Return since we have no target
if (!UpdateVictim())
{
return;
}
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
if (insanityPhase)
{
// Do not perform insanity recast if boss is casting Insanity already
if (me->FindCurrentSpellBySpellId(SPELL_INSANITY))
if (!CheckPhaseMinions())
{
return;
}
// First insanity
if (insanityTimes == 0 && me->HealthBelowPctDamaged(66, damage))
{
DoCastSelf(SPELL_INSANITY, false);
++insanityTimes;
}
// Second insanity
else if (insanityTimes == 1 && me->HealthBelowPctDamaged(33, damage))
{
me->InterruptNonMeleeSpells(false);
DoCastSelf(SPELL_INSANITY, false);
++insanityTimes;
}
insanityPhase = false;
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
me->SetControlled(false, UNIT_STATE_STUNNED);
me->RemoveAurasDueToSpell(INSANITY_VISUAL);
}
void UpdateAI(uint32 diff) override
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
{
//Return since we have no target
if (!UpdateVictim())
{
return;
}
return;
}
if (insanityPhase)
while (uint32 const eventId = events.ExecuteEvent())
{
switch (eventId)
{
if (!CheckPhaseMinions())
case EVENT_HERALD_MIND_FLAY:
{
return;
DoCastVictim(SPELL_MIND_FLAY, false);
events.RepeatEvent(20000);
break;
}
case EVENT_HERALD_SHADOW:
{
DoCastVictim(SPELL_SHADOW_BOLT_VOLLEY, false);
events.RepeatEvent(5000);
break;
}
case EVENT_HERALD_SHIVER:
{
if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
{
DoCast(pTarget, SPELL_SHIVER, false);
}
insanityPhase = false;
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
me->SetControlled(false, UNIT_STATE_STUNNED);
me->RemoveAurasDueToSpell(INSANITY_VISUAL);
events.RepeatEvent(15000);
break;
}
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
{
return;
}
while (uint32 const eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_HERALD_MIND_FLAY:
{
DoCastVictim(SPELL_MIND_FLAY, false);
events.RepeatEvent(20000);
break;
}
case EVENT_HERALD_SHADOW:
{
DoCastVictim(SPELL_SHADOW_BOLT_VOLLEY, false);
events.RepeatEvent(5000);
break;
}
case EVENT_HERALD_SHIVER:
{
if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
{
DoCast(pTarget, SPELL_SHIVER, false);
}
events.RepeatEvent(15000);
break;
}
}
if (me->HasUnitState(UNIT_STATE_CASTING))
{
return;
}
}
DoMeleeAttackIfReady();
}
private:
uint8 insanityTimes;
bool insanityPhase; // Indicates if boss enter to insanity phase
DoMeleeAttackIfReady();
}
uint32 GetPlrInsanityAuraId(uint32 phaseMask) const
{
switch (phaseMask)
{
case 16:
return SPELL_INSANITY_PHASING_1;
case 32:
return SPELL_INSANITY_PHASING_2;
case 64:
return SPELL_INSANITY_PHASING_3;
case 128:
return SPELL_INSANITY_PHASING_4;
case 256:
return SPELL_INSANITY_PHASING_5;
}
private:
uint8 insanityTimes;
bool insanityPhase; // Indicates if boss enter to insanity phase
return 0;
}
void ResetPlayersPhaseMask()
{
Map::PlayerList const& players = me->GetMap()->GetPlayers();
for (auto const& i : players)
{
if (Player* pPlayer = i.GetSource())
{
if (uint32 const insanityAura = GetPlrInsanityAuraId(pPlayer->GetPhaseMask()))
{
pPlayer->RemoveAurasDueToSpell(insanityAura);
}
}
}
}
bool CheckPhaseMinions()
{
summons.RemoveNotExisting();
if (summons.empty())
{
ResetPlayersPhaseMask();
return true;
}
uint32 phase = 1;
for (ObjectGuid const& summonGUID : summons)
{
if (Creature* summon = ObjectAccessor::GetCreature(*me, summonGUID))
{
phase |= summon->GetPhaseMask();
}
}
Map::PlayerList const& players = me->GetMap()->GetPlayers();
for (auto const& i : players)
{
Player* pPlayer = i.GetSource();
if (pPlayer && !(pPlayer->GetPhaseMask() & phase))
{
pPlayer->RemoveAurasDueToSpell(GetPlrInsanityAuraId(pPlayer->GetPhaseMask()));
}
}
return false;
}
};
CreatureAI* GetAI(Creature* creature) const override
uint32 GetPlrInsanityAuraId(uint32 phaseMask) const
{
return GetAhnKahetAI<boss_volazjAI>(creature);
switch (phaseMask)
{
case 16:
return SPELL_INSANITY_PHASING_1;
case 32:
return SPELL_INSANITY_PHASING_2;
case 64:
return SPELL_INSANITY_PHASING_3;
case 128:
return SPELL_INSANITY_PHASING_4;
case 256:
return SPELL_INSANITY_PHASING_5;
}
return 0;
}
void ResetPlayersPhaseMask()
{
Map::PlayerList const& players = me->GetMap()->GetPlayers();
for (auto const& i : players)
{
if (Player* pPlayer = i.GetSource())
{
if (uint32 const insanityAura = GetPlrInsanityAuraId(pPlayer->GetPhaseMask()))
{
pPlayer->RemoveAurasDueToSpell(insanityAura);
}
}
}
}
bool CheckPhaseMinions()
{
summons.RemoveNotExisting();
if (summons.empty())
{
ResetPlayersPhaseMask();
return true;
}
uint32 phase = 1;
for (ObjectGuid const& summonGUID : summons)
{
if (Creature* summon = ObjectAccessor::GetCreature(*me, summonGUID))
{
phase |= summon->GetPhaseMask();
}
}
Map::PlayerList const& players = me->GetMap()->GetPlayers();
for (auto const& i : players)
{
Player* pPlayer = i.GetSource();
if (pPlayer && !(pPlayer->GetPhaseMask() & phase))
{
pPlayer->RemoveAurasDueToSpell(GetPlrInsanityAuraId(pPlayer->GetPhaseMask()));
}
}
return false;
}
};
// 57496 Insanity
class spell_herald_volzaj_insanity : public SpellScriptLoader
class spell_herald_volzaj_insanity : public SpellScript
{
public:
spell_herald_volzaj_insanity() : SpellScriptLoader("spell_herald_volzaj_insanity") { }
PrepareSpellScript(spell_herald_volzaj_insanity);
class spell_herald_volzaj_insanity_SpellScript : public SpellScript
bool Load() override { return GetCaster()->GetTypeId() == TYPEID_UNIT; }
void HandleDummyEffect(std::list<WorldObject*>& targets)
{
PrepareSpellScript(spell_herald_volzaj_insanity_SpellScript);
bool Load() override { return GetCaster()->GetTypeId() == TYPEID_UNIT; }
void HandleDummyEffect(std::list<WorldObject*>& targets)
Unit* caster = GetCaster();
if (!caster)
{
Unit* caster = GetCaster();
if (!caster)
targets.clear();
return;
}
if (!targets.empty())
{
targets.remove_if([this](WorldObject* targetObj) -> bool
{
targets.clear();
return;
return !targetObj || targetObj->GetTypeId() != TYPEID_PLAYER || !targetObj->ToPlayer()->IsInCombatWith(GetCaster()) ||
targetObj->GetDistance(GetCaster()) >= (MAX_VISIBILITY_DISTANCE * 2);
});
}
if (targets.empty())
{
return;
}
// Start channel visual and set self as unnattackable
caster->ToCreature()->AI()->Talk(SAY_INSANITY);
caster->CastSpell(caster, SPELL_WHISPER_INSANITY, true);
caster->RemoveAllAuras();
caster->CastSpell(caster, INSANITY_VISUAL, true);
caster->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
caster->SetControlled(true, UNIT_STATE_STUNNED);
// Handle phase effect
uint32 insanityCounter = 0;
std::list<WorldObject*>::const_iterator itr = targets.begin();
while (itr != targets.end() && insanityCounter < MAX_INSANITY_TARGETS)
{
WorldObject* targetObj = *itr;
if (!targetObj)
{
continue;
}
if (!targets.empty())
Player* plrTarget = targetObj->ToPlayer();
// This should never happen, spell has attribute SPELL_ATTR3_ONLY_TARGET_PLAYERS
if (!plrTarget)
{
targets.remove_if([this](WorldObject* targetObj) -> bool
{
return !targetObj || targetObj->GetTypeId() != TYPEID_PLAYER || !targetObj->ToPlayer()->IsInCombatWith(GetCaster()) ||
targetObj->GetDistance(GetCaster()) >= (MAX_VISIBILITY_DISTANCE * 2);
});
continue;
}
if (targets.empty())
{
return;
}
// phase mask
plrTarget->CastSpell(plrTarget, InsanitySpells.at(insanityCounter), true);
// Start channel visual and set self as unnattackable
caster->ToCreature()->AI()->Talk(SAY_INSANITY);
caster->CastSpell(caster, SPELL_WHISPER_INSANITY, true);
caster->RemoveAllAuras();
caster->CastSpell(caster, INSANITY_VISUAL, true);
caster->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
caster->SetControlled(true, UNIT_STATE_STUNNED);
// Handle phase effect
uint32 insanityCounter = 0;
std::list<WorldObject*>::const_iterator itr = targets.begin();
while (itr != targets.end() && insanityCounter < MAX_INSANITY_TARGETS)
// Summon clone
for (std::list<WorldObject*>::const_iterator itr2 = targets.begin(); itr2 != targets.end(); ++itr2)
{
WorldObject* targetObj = *itr;
if (!targetObj)
// Should not make clone of current player target
Player const* plrClone = *itr2 ? (*itr2)->ToPlayer() : nullptr;
if (!plrClone || plrClone == plrTarget)
{
continue;
}
Player* plrTarget = targetObj->ToPlayer();
// This should never happen, spell has attribute SPELL_ATTR3_ONLY_TARGET_PLAYERS
if (!plrTarget)
if (Unit* summon = caster->SummonCreature(NPC_TWISTED_VISAGE, plrClone->GetPosition(), TEMPSUMMON_CORPSE_DESPAWN, 0))
{
continue;
summon->AddThreat(plrTarget, 0.0f);
summon->SetInCombatWith(plrTarget);
plrTarget->SetInCombatWith(summon);
plrTarget->CastSpell(summon, SPELL_CLONE_PLAYER, true);
summon->SetPhaseMask(1 | (1 << (4 + insanityCounter)), true);
summon->SetUInt32Value(UNIT_FIELD_MINDAMAGE, plrClone->GetUInt32Value(UNIT_FIELD_MINDAMAGE));
summon->SetUInt32Value(UNIT_FIELD_MAXDAMAGE, plrClone->GetUInt32Value(UNIT_FIELD_MAXDAMAGE));
}
// phase mask
plrTarget->CastSpell(plrTarget, InsanitySpells.at(insanityCounter), true);
// Summon clone
for (std::list<WorldObject*>::const_iterator itr2 = targets.begin(); itr2 != targets.end(); ++itr2)
{
// Should not make clone of current player target
Player const* plrClone = *itr2 ? (*itr2)->ToPlayer() : nullptr;
if (!plrClone || plrClone == plrTarget)
{
continue;
}
if (Unit* summon = caster->SummonCreature(NPC_TWISTED_VISAGE, plrClone->GetPosition(), TEMPSUMMON_CORPSE_DESPAWN, 0))
{
summon->AddThreat(plrTarget, 0.0f);
summon->SetInCombatWith(plrTarget);
plrTarget->SetInCombatWith(summon);
plrTarget->CastSpell(summon, SPELL_CLONE_PLAYER, true);
summon->SetPhaseMask(1 | (1 << (4 + insanityCounter)), true);
summon->SetUInt32Value(UNIT_FIELD_MINDAMAGE, plrClone->GetUInt32Value(UNIT_FIELD_MINDAMAGE));
summon->SetUInt32Value(UNIT_FIELD_MAXDAMAGE, plrClone->GetUInt32Value(UNIT_FIELD_MAXDAMAGE));
}
}
++insanityCounter;
++itr;
}
}
void HandleAfterCast()
{
GetCaster()->ToCreature()->AI()->SetData(DATA_SET_INSANITY_PHASE, 1);
++insanityCounter;
++itr;
}
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_herald_volzaj_insanity_SpellScript::HandleDummyEffect, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
AfterCast += SpellCastFn(spell_herald_volzaj_insanity_SpellScript::HandleAfterCast);
}
};
SpellScript* GetSpellScript() const override
void HandleAfterCast()
{
return new spell_herald_volzaj_insanity_SpellScript();
GetCaster()->ToCreature()->AI()->SetData(DATA_SET_INSANITY_PHASE, 1);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_herald_volzaj_insanity::HandleDummyEffect, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
AfterCast += SpellCastFn(spell_herald_volzaj_insanity::HandleAfterCast);
}
};
@@ -470,70 +447,59 @@ public:
// 60295 Volazj Whisper: Slay 03
// 60296 Volazj Whisper: Death 01
// 60297 Volazj Whisper: Death 02
class spell_volazj_whisper : public SpellScriptLoader
class spell_volazj_whisper : public SpellScript
{
public:
spell_volazj_whisper() : SpellScriptLoader("spell_volazj_whisper") { }
PrepareSpellScript(spell_volazj_whisper);
class spell_volazj_whisper_SpellScript : public SpellScript
bool Validate(SpellInfo const* /*spell*/) override
{
PrepareSpellScript(spell_volazj_whisper_SpellScript);
bool Validate(SpellInfo const* /*spell*/) override
return ValidateSpellInfo(
{
return ValidateSpellInfo(
{
SPELL_WHISPER_AGGRO,
SPELL_WHISPER_INSANITY,
SPELL_WHISPER_SLAY_1,
SPELL_WHISPER_SLAY_2,
SPELL_WHISPER_SLAY_3,
SPELL_WHISPER_DEATH_1,
SPELL_WHISPER_DEATH_2
});
}
SPELL_WHISPER_AGGRO,
SPELL_WHISPER_INSANITY,
SPELL_WHISPER_SLAY_1,
SPELL_WHISPER_SLAY_2,
SPELL_WHISPER_SLAY_3,
SPELL_WHISPER_DEATH_1,
SPELL_WHISPER_DEATH_2
});
}
bool Load() override { return GetCaster()->GetTypeId() == TYPEID_UNIT; }
bool Load() override { return GetCaster()->GetTypeId() == TYPEID_UNIT; }
void HandleScriptEffect(SpellEffIndex /* effIndex */)
{
Unit* target = GetHitPlayer();
Creature* caster = GetCaster()->ToCreature();
if (!target || !caster)
{
return;
}
uint32 text = 0;
switch (GetSpellInfo()->Id)
{
case SPELL_WHISPER_AGGRO: text = WHISPER_AGGRO; break;
case SPELL_WHISPER_INSANITY: text = WHISPER_INSANITY; break;
case SPELL_WHISPER_SLAY_1: text = WHISPER_SLAY_1; break;
case SPELL_WHISPER_SLAY_2: text = WHISPER_SLAY_2; break;
case SPELL_WHISPER_SLAY_3: text = WHISPER_SLAY_3; break;
case SPELL_WHISPER_DEATH_1: text = WHISPER_DEATH_1; break;
case SPELL_WHISPER_DEATH_2: text = WHISPER_DEATH_2; break;
default: return;
}
caster->AI()->Talk(text, target);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_volazj_whisper_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
SpellScript* GetSpellScript() const override
void HandleScriptEffect(SpellEffIndex /* effIndex */)
{
return new spell_volazj_whisper_SpellScript();
Unit* target = GetHitPlayer();
Creature* caster = GetCaster()->ToCreature();
if (!target || !caster)
{
return;
}
uint32 text = 0;
switch (GetSpellInfo()->Id)
{
case SPELL_WHISPER_AGGRO: text = WHISPER_AGGRO; break;
case SPELL_WHISPER_INSANITY: text = WHISPER_INSANITY; break;
case SPELL_WHISPER_SLAY_1: text = WHISPER_SLAY_1; break;
case SPELL_WHISPER_SLAY_2: text = WHISPER_SLAY_2; break;
case SPELL_WHISPER_SLAY_3: text = WHISPER_SLAY_3; break;
case SPELL_WHISPER_DEATH_1: text = WHISPER_DEATH_1; break;
case SPELL_WHISPER_DEATH_2: text = WHISPER_DEATH_2; break;
default: return;
}
caster->AI()->Talk(text, target);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_volazj_whisper::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
void AddSC_boss_volazj()
{
new boss_volazj();
new spell_herald_volzaj_insanity();
new spell_volazj_whisper();
RegisterAhnKahetCreatureAI(boss_volazj);
RegisterSpellScript(spell_herald_volzaj_insanity);
RegisterSpellScript(spell_volazj_whisper);
}

View File

@@ -93,438 +93,415 @@ constexpr float DATA_GROUND_POSITION_Z = 11.308135f;
constexpr float DATA_SPHERE_DISTANCE = 25.0f;
#define DATA_SPHERE_ANGLE_OFFSET float(M_PI) / 2.0f
class npc_taldaram_flamesphere : public CreatureScript
struct npc_taldaram_flamesphere : public NullCreatureAI
{
public:
npc_taldaram_flamesphere() : CreatureScript("npc_taldaram_flamesphere") { }
struct npc_taldaram_flamesphereAI : public NullCreatureAI
npc_taldaram_flamesphere(Creature *pCreature) : NullCreatureAI(pCreature),
instance(pCreature->GetInstanceScript()),
uiDespawnTimer(13000),
moveTimer(0)
{
npc_taldaram_flamesphereAI(Creature *pCreature) : NullCreatureAI(pCreature),
instance(pCreature->GetInstanceScript()),
uiDespawnTimer(13000),
moveTimer(0)
pCreature->SetReactState(REACT_PASSIVE);
}
void DoAction(int32 action) override
{
if (action == ACTION_SPHERE)
{
pCreature->SetReactState(REACT_PASSIVE);
moveTimer = 3000;
}
}
void MovementInform(uint32 type, uint32 id) override
{
if (type == POINT_MOTION_TYPE && id == POINT_ORB)
{
me->DisappearAndDie();
}
}
void IsSummonedBy(Unit* /*summoner*/) override
{
// Replace sphere instantly if sphere is summoned after prince death
if (instance->GetBossState(DATA_PRINCE_TALDARAM) != IN_PROGRESS)
{
me->DespawnOrUnsummon();
return;
}
void DoAction(int32 action) override
DoCastSelf(SPELL_FLAME_SPHERE_SPAWN_EFFECT);
DoCastSelf(SPELL_FLAME_SPHERE_VISUAL);
// TODO: replace with DespawnOrUnsummon
uiDespawnTimer = 13000;
}
void JustDied(Unit* /*who*/) override
{
DoCastSelf(SPELL_FLAME_SPHERE_DEATH_EFFECT);
}
void UpdateAI(uint32 diff) override
{
if (moveTimer)
{
if (action == ACTION_SPHERE)
if (moveTimer <= diff)
{
moveTimer = 3000;
DoCastSelf(SPELL_FLAME_SPHERE_PERIODIC);
float angleOffset = 0.0f;
switch (me->GetEntry())
{
case NPC_FLAME_SPHERE_1:
break;
case NPC_FLAME_SPHERE_2:
angleOffset = DATA_SPHERE_ANGLE_OFFSET;
break;
case NPC_FLAME_SPHERE_3:
angleOffset = -DATA_SPHERE_ANGLE_OFFSET;
break;
default:
return;
}
float angle = me->GetAngle(&victimPos) + angleOffset;
float x = me->GetPositionX() + DATA_SPHERE_DISTANCE * cos(angle);
float y = me->GetPositionY() + DATA_SPHERE_DISTANCE * sin(angle);
me->GetMotionMaster()->MovePoint(POINT_ORB, x, y, me->GetPositionZ());
moveTimer = 0;
}
else
{
moveTimer -= diff;
}
}
void MovementInform(uint32 type, uint32 id) override
if (uiDespawnTimer)
{
if (type == POINT_MOTION_TYPE && id == POINT_ORB)
if (uiDespawnTimer <= diff)
{
me->DisappearAndDie();
uiDespawnTimer = 0;
}
else
uiDespawnTimer -= diff;
}
void IsSummonedBy(Unit* /*summoner*/) override
{
// Replace sphere instantly if sphere is summoned after prince death
if (instance->GetBossState(DATA_PRINCE_TALDARAM) != IN_PROGRESS)
{
me->DespawnOrUnsummon();
return;
}
DoCastSelf(SPELL_FLAME_SPHERE_SPAWN_EFFECT);
DoCastSelf(SPELL_FLAME_SPHERE_VISUAL);
// TODO: replace with DespawnOrUnsummon
uiDespawnTimer = 13000;
}
void JustDied(Unit* /*who*/) override
{
DoCastSelf(SPELL_FLAME_SPHERE_DEATH_EFFECT);
}
void UpdateAI(uint32 diff) override
{
if (moveTimer)
{
if (moveTimer <= diff)
{
DoCastSelf(SPELL_FLAME_SPHERE_PERIODIC);
float angleOffset = 0.0f;
switch (me->GetEntry())
{
case NPC_FLAME_SPHERE_1:
break;
case NPC_FLAME_SPHERE_2:
angleOffset = DATA_SPHERE_ANGLE_OFFSET;
break;
case NPC_FLAME_SPHERE_3:
angleOffset = -DATA_SPHERE_ANGLE_OFFSET;
break;
default:
return;
}
float angle = me->GetAngle(&victimPos) + angleOffset;
float x = me->GetPositionX() + DATA_SPHERE_DISTANCE * cos(angle);
float y = me->GetPositionY() + DATA_SPHERE_DISTANCE * sin(angle);
me->GetMotionMaster()->MovePoint(POINT_ORB, x, y, me->GetPositionZ());
moveTimer = 0;
}
else
{
moveTimer -= diff;
}
}
if (uiDespawnTimer)
{
if (uiDespawnTimer <= diff)
{
me->DisappearAndDie();
uiDespawnTimer = 0;
}
else
uiDespawnTimer -= diff;
}
}
void SetVictimPos(Position const& pos)
{
victimPos.Relocate(pos);
}
private:
Position victimPos;
InstanceScript* instance;
uint32 uiDespawnTimer;
uint32 moveTimer;
};
CreatureAI *GetAI(Creature *creature) const override
{
return GetAhnKahetAI<npc_taldaram_flamesphereAI>(creature);
}
void SetVictimPos(Position const& pos)
{
victimPos.Relocate(pos);
}
private:
Position victimPos;
InstanceScript* instance;
uint32 uiDespawnTimer;
uint32 moveTimer;
};
class boss_taldaram : public CreatureScript
struct boss_taldaram : public BossAI
{
public:
boss_taldaram() : CreatureScript("boss_taldaram")
boss_taldaram(Creature* pCreature) : BossAI(pCreature, DATA_PRINCE_TALDARAM),
vanishDamage(0)
{
}
struct boss_taldaramAI : public BossAI
void InitializeAI() override
{
boss_taldaramAI(Creature* pCreature) : BossAI(pCreature, DATA_PRINCE_TALDARAM),
vanishDamage(0)
{
}
BossAI::InitializeAI();
void InitializeAI() override
// Event not started
if (instance->GetData(DATA_TELDRAM_SPHERE1) != DONE || instance->GetData(DATA_TELDRAM_SPHERE2) != DONE)
{
BossAI::InitializeAI();
// Event not started
if (instance->GetData(DATA_TELDRAM_SPHERE1) != DONE || instance->GetData(DATA_TELDRAM_SPHERE2) != DONE)
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
me->SetDisableGravity(true);
me->SetHover(true);
if (!me->HasAura(SPELL_BEAM_VISUAL))
{
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
me->SetDisableGravity(true);
me->SetHover(true);
if (!me->HasAura(SPELL_BEAM_VISUAL))
{
DoCastSelf(SPELL_BEAM_VISUAL, true);
}
me->SummonCreatureGroup(SUMMON_GROUP_TRIGGERS);
return;
DoCastSelf(SPELL_BEAM_VISUAL, true);
}
if (instance->GetData(DATA_TELDRAM_SPHERE1) == DONE && instance->GetData(DATA_TELDRAM_SPHERE2) == DONE)
me->SummonCreatureGroup(SUMMON_GROUP_TRIGGERS);
return;
}
if (instance->GetData(DATA_TELDRAM_SPHERE1) == DONE && instance->GetData(DATA_TELDRAM_SPHERE2) == DONE)
{
DoAction(ACTION_REMOVE_PRISON_AT_RESET);
}
}
void Reset() override
{
_Reset();
vanishDamage = 0;
vanishTarget_GUID.Clear();
}
void DoAction(int32 action) override
{
if (action == ACTION_REMOVE_PRISON || action == ACTION_REMOVE_PRISON_AT_RESET)
{
me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), DATA_GROUND_POSITION_Z, me->GetOrientation());
instance->HandleGameObject(instance->GetGuidData(DATA_PRINCE_TALDARAM_PLATFORM), true);
if (action == ACTION_REMOVE_PRISON)
{
DoAction(ACTION_REMOVE_PRISON_AT_RESET);
DoCastSelf(SPELL_HOVER_FALL);
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveLand(POINT_LAND, me->GetHomePosition(), 8.0f);
Talk(SAY_REMOVE_PRISON);
}
}
void Reset() override
{
_Reset();
vanishDamage = 0;
vanishTarget_GUID.Clear();
}
void DoAction(int32 action) override
{
if (action == ACTION_REMOVE_PRISON || action == ACTION_REMOVE_PRISON_AT_RESET)
{
me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), DATA_GROUND_POSITION_Z, me->GetOrientation());
instance->HandleGameObject(instance->GetGuidData(DATA_PRINCE_TALDARAM_PLATFORM), true);
if (action == ACTION_REMOVE_PRISON)
{
DoCastSelf(SPELL_HOVER_FALL);
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveLand(POINT_LAND, me->GetHomePosition(), 8.0f);
Talk(SAY_REMOVE_PRISON);
}
// Teleport instantly
else
{
me->SetDisableGravity(false);
me->SetHover(false);
me->RemoveAllAuras();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_NOT_SELECTABLE);
me->UpdatePosition(me->GetHomePosition(), true);
}
summons.DespawnEntry(NPC_JEDOGA_CONTROLLER);
}
}
void MovementInform(uint32 type, uint32 id) override
{
if (type == EFFECT_MOTION_TYPE && id == POINT_LAND)
// Teleport instantly
else
{
me->SetDisableGravity(false);
me->SetHover(false);
me->RemoveAllAuras();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_NOT_SELECTABLE);
me->UpdatePosition(me->GetHomePosition(), true);
}
summons.DespawnEntry(NPC_JEDOGA_CONTROLLER);
}
}
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*school*/) override
void MovementInform(uint32 type, uint32 id) override
{
if (type == EFFECT_MOTION_TYPE && id == POINT_LAND)
{
if (vanishTarget_GUID)
{
if (me->FindCurrentSpellBySpellId(SPELL_EMBRACE_OF_THE_VAMPYR))
{
vanishDamage += damage;
if (vanishDamage >= DUNGEON_MODE<uint32>(MAX_EMBRACE_DMG, MAX_EMBRACE_DMG_H))
{
ScheduleCombatEvents();
me->CastStop();
vanishTarget_GUID.Clear();
vanishDamage = 0;
}
}
}
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() != TYPEID_PLAYER)
{
return;
}
Talk(SAY_SLAY);
if (vanishTarget_GUID && victim->GetGUID() == vanishTarget_GUID)
{
vanishTarget_GUID.Clear();
vanishDamage = 0;
}
}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
Talk(SAY_AGGRO);
ScheduleCombatEvents();
me->SetDisableGravity(false);
me->SetHover(false);
me->RemoveAllAuras();
me->InterruptNonMeleeSpells(true);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_NOT_SELECTABLE);
}
}
void SpellHitTarget(Unit* /*target*/, const SpellInfo *spellInfo) override
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*school*/) override
{
if (vanishTarget_GUID)
{
if (spellInfo->Id == SPELL_CONJURE_FLAME_SPHERE)
if (me->FindCurrentSpellBySpellId(SPELL_EMBRACE_OF_THE_VAMPYR))
{
summons.DoAction(ACTION_SPHERE);
vanishDamage += damage;
if (vanishDamage >= DUNGEON_MODE<uint32>(MAX_EMBRACE_DMG, MAX_EMBRACE_DMG_H))
{
ScheduleCombatEvents();
me->CastStop();
vanishTarget_GUID.Clear();
vanishDamage = 0;
}
}
}
}
void JustSummoned(Creature* summon) override
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() != TYPEID_PLAYER)
{
summons.Summon(summon);
switch (summon->GetEntry())
return;
}
Talk(SAY_SLAY);
if (vanishTarget_GUID && victim->GetGUID() == vanishTarget_GUID)
{
vanishTarget_GUID.Clear();
vanishDamage = 0;
}
}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
Talk(SAY_AGGRO);
ScheduleCombatEvents();
me->RemoveAllAuras();
me->InterruptNonMeleeSpells(true);
}
void SpellHitTarget(Unit* /*target*/, const SpellInfo *spellInfo) override
{
if (spellInfo->Id == SPELL_CONJURE_FLAME_SPHERE)
{
summons.DoAction(ACTION_SPHERE);
}
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
switch (summon->GetEntry())
{
case NPC_FLAME_SPHERE_1:
case NPC_FLAME_SPHERE_2:
case NPC_FLAME_SPHERE_3:
{
case NPC_FLAME_SPHERE_1:
case NPC_FLAME_SPHERE_2:
case NPC_FLAME_SPHERE_3:
if (npc_taldaram_flamesphere* summonAI = dynamic_cast<npc_taldaram_flamesphere*>(summon->AI()))
{
if (npc_taldaram_flamesphere::npc_taldaram_flamesphereAI* summonAI = dynamic_cast<npc_taldaram_flamesphere::npc_taldaram_flamesphereAI*>(summon->AI()))
summonAI->SetVictimPos(victimSperePos);
}
break;
}
case NPC_JEDOGA_CONTROLLER:
{
summon->CastSpell(nullptr, SPELL_BEAM_VISUAL);
break;
}
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
{
return;
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
{
return;
}
while (uint32 const eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_PRINCE_BLOODTHIRST:
{
DoCastSelf(SPELL_BLOODTHIRST);
events.RepeatEvent(10000);
break;
}
case EVENT_PRINCE_FLAME_SPHERES:
{
if (Unit* victim = me->GetVictim())
{
summonAI->SetVictimPos(victimSperePos);
DoCast(victim, SPELL_CONJURE_FLAME_SPHERE);
victimSperePos = *victim;
}
if (!events.GetNextEventTime(EVENT_PRINCE_VANISH))
{
events.RescheduleEvent(EVENT_PRINCE_VANISH, 14000);
}
else
{
// Make sure that Vanish won't get triggered at same time as sphere summon
events.DelayEvents(4000);
}
events.RepeatEvent(15000);
break;
}
case NPC_JEDOGA_CONTROLLER:
case EVENT_PRINCE_VANISH:
{
summon->CastSpell(nullptr, SPELL_BEAM_VISUAL);
//Count alive players
uint8 count = 0;
std::list<HostileReference*> const t_list = me->getThreatMgr().getThreatList();
if (!t_list.empty())
{
for (HostileReference const* reference : t_list)
{
if (reference)
{
Unit const* pTarget = ObjectAccessor::GetUnit(*me, reference->getUnitGuid());
if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->IsAlive())
{
++count;
}
}
}
}
// He only vanishes if there are 3 or more alive players
if (count > 2)
{
Talk(SAY_VANISH);
DoCastSelf(SPELL_VANISH, false);
if (Unit* pEmbraceTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
{
vanishTarget_GUID = pEmbraceTarget->GetGUID();
}
events.CancelEvent(EVENT_PRINCE_FLAME_SPHERES);
events.CancelEvent(EVENT_PRINCE_BLOODTHIRST);
events.ScheduleEvent(EVENT_PRINCE_VANISH_RUN, 2499);
}
break;
}
case EVENT_PRINCE_VANISH_RUN:
{
if (Unit* _vanishTarget = ObjectAccessor::GetUnit(*me, vanishTarget_GUID))
{
vanishDamage = 0;
DoCast(_vanishTarget, SPELL_SHADOWSTEP);
me->CastSpell(_vanishTarget, SPELL_EMBRACE_OF_THE_VAMPYR, false);
me->RemoveAura(SPELL_VANISH);
}
events.ScheduleEvent(EVENT_PRINCE_RESCHEDULE, 20000);
break;
}
case EVENT_PRINCE_RESCHEDULE:
{
ScheduleCombatEvents();
break;
}
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
{
return;
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
{
return;
}
while (uint32 const eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_PRINCE_BLOODTHIRST:
{
DoCastSelf(SPELL_BLOODTHIRST);
events.RepeatEvent(10000);
break;
}
case EVENT_PRINCE_FLAME_SPHERES:
{
if (Unit* victim = me->GetVictim())
{
DoCast(victim, SPELL_CONJURE_FLAME_SPHERE);
victimSperePos = *victim;
}
if (!events.GetNextEventTime(EVENT_PRINCE_VANISH))
{
events.RescheduleEvent(EVENT_PRINCE_VANISH, 14000);
}
else
{
// Make sure that Vanish won't get triggered at same time as sphere summon
events.DelayEvents(4000);
}
events.RepeatEvent(15000);
break;
}
case EVENT_PRINCE_VANISH:
{
//Count alive players
uint8 count = 0;
std::list<HostileReference*> const t_list = me->getThreatMgr().getThreatList();
if (!t_list.empty())
{
for (HostileReference const* reference : t_list)
{
if (reference)
{
Unit const* pTarget = ObjectAccessor::GetUnit(*me, reference->getUnitGuid());
if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->IsAlive())
{
++count;
}
}
}
}
// He only vanishes if there are 3 or more alive players
if (count > 2)
{
Talk(SAY_VANISH);
DoCastSelf(SPELL_VANISH, false);
if (Unit* pEmbraceTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
{
vanishTarget_GUID = pEmbraceTarget->GetGUID();
}
events.CancelEvent(EVENT_PRINCE_FLAME_SPHERES);
events.CancelEvent(EVENT_PRINCE_BLOODTHIRST);
events.ScheduleEvent(EVENT_PRINCE_VANISH_RUN, 2499);
}
break;
}
case EVENT_PRINCE_VANISH_RUN:
{
if (Unit* _vanishTarget = ObjectAccessor::GetUnit(*me, vanishTarget_GUID))
{
vanishDamage = 0;
DoCast(_vanishTarget, SPELL_SHADOWSTEP);
me->CastSpell(_vanishTarget, SPELL_EMBRACE_OF_THE_VAMPYR, false);
me->RemoveAura(SPELL_VANISH);
}
events.ScheduleEvent(EVENT_PRINCE_RESCHEDULE, 20000);
break;
}
case EVENT_PRINCE_RESCHEDULE:
{
ScheduleCombatEvents();
break;
}
}
if (me->HasUnitState(UNIT_STATE_CASTING))
{
return;
}
}
if (me->IsVisible())
{
DoMeleeAttackIfReady();
}
}
private:
Position victimSperePos;
ObjectGuid vanishTarget_GUID;
uint32 vanishDamage;
void ScheduleCombatEvents()
if (me->IsVisible())
{
events.Reset();
events.RescheduleEvent(EVENT_PRINCE_FLAME_SPHERES, 10000);
events.RescheduleEvent(EVENT_PRINCE_BLOODTHIRST, 10000);
vanishTarget_GUID.Clear();
vanishDamage = 0;
DoMeleeAttackIfReady();
}
};
}
CreatureAI* GetAI(Creature* creature) const override
private:
Position victimSperePos;
ObjectGuid vanishTarget_GUID;
uint32 vanishDamage;
void ScheduleCombatEvents()
{
return GetAhnKahetAI<boss_taldaramAI>(creature);
events.Reset();
events.RescheduleEvent(EVENT_PRINCE_FLAME_SPHERES, 10000);
events.RescheduleEvent(EVENT_PRINCE_BLOODTHIRST, 10000);
vanishTarget_GUID.Clear();
vanishDamage = 0;
}
};
// TODO: Turn into new script type when Gossips have been updated
class go_prince_taldaram_sphere : public GameObjectScript
{
public:
go_prince_taldaram_sphere() : GameObjectScript("go_prince_taldaram_sphere") { }
go_prince_taldaram_sphere() : GameObjectScript("go_prince_taldaram_sphere") {}
bool OnGossipHello(Player* pPlayer, GameObject *go) override
bool OnGossipHello(Player* pPlayer, GameObject* go) override
{
if (pPlayer && pPlayer->IsInCombat())
{
return true;
}
InstanceScript *pInstance = go->GetInstanceScript();
InstanceScript* pInstance = go->GetInstanceScript();
if (!pInstance)
{
return true;
@@ -550,83 +527,61 @@ public:
};
// 55931 - Conjure Flame Sphere
class spell_prince_taldaram_conjure_flame_sphere : public SpellScriptLoader
class spell_prince_taldaram_conjure_flame_sphere : public SpellScript
{
public:
spell_prince_taldaram_conjure_flame_sphere() : SpellScriptLoader("spell_prince_taldaram_conjure_flame_sphere") { }
PrepareSpellScript(spell_prince_taldaram_conjure_flame_sphere);
class spell_prince_taldaram_conjure_flame_sphere_SpellScript : public SpellScript
bool Validate(SpellInfo const* /*spellInfo*/) override
{
PrepareSpellScript(spell_prince_taldaram_conjure_flame_sphere_SpellScript);
return ValidateSpellInfo({SPELL_FLAME_SPHERE_SUMMON_1, SPELL_FLAME_SPHERE_SUMMON_2, SPELL_FLAME_SPHERE_SUMMON_3});
}
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({SPELL_FLAME_SPHERE_SUMMON_1, SPELL_FLAME_SPHERE_SUMMON_2, SPELL_FLAME_SPHERE_SUMMON_3});
}
void HandleScript(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
if (!caster || caster->isDead())
{
return;
}
caster->CastSpell(caster, SPELL_FLAME_SPHERE_SUMMON_1, false, nullptr, nullptr, caster->GetGUID());
if (caster->GetMap()->IsHeroic())
{
caster->CastSpell(caster, SPELL_FLAME_SPHERE_SUMMON_2, false, nullptr, nullptr, caster->GetGUID());
caster->CastSpell(caster, SPELL_FLAME_SPHERE_SUMMON_3, false, nullptr, nullptr, caster->GetGUID());
}
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_prince_taldaram_conjure_flame_sphere_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
SpellScript* GetSpellScript() const override
void HandleScript(SpellEffIndex /*effIndex*/)
{
return new spell_prince_taldaram_conjure_flame_sphere_SpellScript();
Unit* caster = GetCaster();
if (!caster || caster->isDead())
{
return;
}
caster->CastSpell(caster, SPELL_FLAME_SPHERE_SUMMON_1, false, nullptr, nullptr, caster->GetGUID());
if (caster->GetMap()->IsHeroic())
{
caster->CastSpell(caster, SPELL_FLAME_SPHERE_SUMMON_2, false, nullptr, nullptr, caster->GetGUID());
caster->CastSpell(caster, SPELL_FLAME_SPHERE_SUMMON_3, false, nullptr, nullptr, caster->GetGUID());
}
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_prince_taldaram_conjure_flame_sphere::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 55895, 59511, 59512 - Flame Sphere Summon
class spell_prince_taldaram_flame_sphere_summon : public SpellScriptLoader
class spell_prince_taldaram_flame_sphere_summon : public SpellScript
{
public:
spell_prince_taldaram_flame_sphere_summon() : SpellScriptLoader("spell_prince_taldaram_flame_sphere_summon") { }
PrepareSpellScript(spell_prince_taldaram_flame_sphere_summon);
class spell_prince_taldaram_flame_sphere_summon_SpellScript : public SpellScript
{
PrepareSpellScript(spell_prince_taldaram_flame_sphere_summon_SpellScript);
void SetDest(SpellDestination& dest)
{
dest._position.m_positionZ = DATA_GROUND_POSITION_Z + 5.5f;
}
void SetDest(SpellDestination& dest)
{
dest._position.m_positionZ = DATA_GROUND_POSITION_Z + 5.5f;
}
void Register() override
{
OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_prince_taldaram_flame_sphere_summon_SpellScript::SetDest, EFFECT_0, TARGET_DEST_CASTER);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_prince_taldaram_flame_sphere_summon_SpellScript();
}
void Register() override
{
OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_prince_taldaram_flame_sphere_summon::SetDest, EFFECT_0, TARGET_DEST_CASTER);
}
};
void AddSC_boss_taldaram()
{
new npc_taldaram_flamesphere();
new boss_taldaram();
RegisterAhnKahetCreatureAI(npc_taldaram_flamesphere);
RegisterAhnKahetCreatureAI(boss_taldaram);
new go_prince_taldaram_sphere();
// Spells
new spell_prince_taldaram_conjure_flame_sphere();
new spell_prince_taldaram_flame_sphere_summon();
RegisterSpellScript(spell_prince_taldaram_conjure_flame_sphere);
RegisterSpellScript(spell_prince_taldaram_flame_sphere_summon);
}

View File

@@ -257,34 +257,23 @@ public:
// 56702 Shadow Sickle
// 59103 Shadow Sickle
class spell_shadow_sickle_periodic_damage : public SpellScriptLoader
class spell_shadow_sickle_periodic_damage : public AuraScript
{
public:
spell_shadow_sickle_periodic_damage() : SpellScriptLoader("spell_shadow_sickle_periodic_damage") { }
PrepareAuraScript(spell_shadow_sickle_periodic_damage);
class spell_shadow_sickle_periodic_damage_AuraScript : public AuraScript
void HandlePeriodic(AuraEffect const* /*aurEff*/)
{
PrepareAuraScript(spell_shadow_sickle_periodic_damage_AuraScript);
GetCaster()->CastSpell(nullptr, SPELL_SHADOW_SICKLE);
}
void HandlePeriodic(AuraEffect const* /*aurEff*/)
{
GetCaster()->CastSpell(nullptr, SPELL_SHADOW_SICKLE);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_shadow_sickle_periodic_damage_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
AuraScript* GetAuraScript() const override
void Register() override
{
return new spell_shadow_sickle_periodic_damage_AuraScript();
OnEffectPeriodic += AuraEffectPeriodicFn(spell_shadow_sickle_periodic_damage::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
void AddSC_instance_ahnkahet()
{
new instance_ahnkahet;
new spell_shadow_sickle_periodic_damage();
RegisterSpellScript(spell_shadow_sickle_periodic_damage);
}