mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-16 02:20:27 +00:00
refactor(Scripts/AhnKahet): new script system (#9040)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user