refactor(Scripts/FoS): modernize Forge of Souls bosses to use BossAI (#25174)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b5da3363f1
commit
f63a93276e
4 changed files with 431 additions and 528 deletions
|
|
@ -32,7 +32,7 @@ enum Yells
|
|||
SAY_CORRUPT_SOUL = 4,
|
||||
};
|
||||
|
||||
enum eSpells
|
||||
enum Spells
|
||||
{
|
||||
SPELL_SOULSTORM_CHANNEL_OOC = 69008,
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ enum eSpells
|
|||
SPELL_SOULSTORM = 68872,
|
||||
};
|
||||
|
||||
enum eEvents
|
||||
enum Events
|
||||
{
|
||||
EVENT_SPELL_SHADOW_BOLT = 1,
|
||||
EVENT_SPELL_FEAR,
|
||||
|
|
@ -60,207 +60,171 @@ enum eEvents
|
|||
EVENT_START_SOULSTORM,
|
||||
};
|
||||
|
||||
class boss_bronjahm : public CreatureScript
|
||||
struct boss_bronjahm : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_bronjahm() : CreatureScript("boss_bronjahm") { }
|
||||
boss_bronjahm(Creature* creature) : BossAI(creature, DATA_BRONJAHM) { }
|
||||
|
||||
struct boss_bronjahmAI : public ScriptedAI
|
||||
void JustReachedHome() override
|
||||
{
|
||||
boss_bronjahmAI(Creature* creature) : ScriptedAI(creature), summons(me)
|
||||
{
|
||||
pInstance = creature->GetInstanceScript();
|
||||
}
|
||||
BossAI::JustReachedHome();
|
||||
DoCastSelf(SPELL_SOULSTORM_CHANNEL_OOC, true);
|
||||
}
|
||||
|
||||
InstanceScript* pInstance;
|
||||
EventMap events;
|
||||
SummonList summons;
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
me->CastSpell(me, SPELL_SOULSTORM_CHANNEL_OOC, true);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
me->RemoveUnitFlag(UNIT_FLAG_DISABLE_MOVE);
|
||||
me->CastSpell(me, SPELL_SOULSTORM_CHANNEL_OOC, true);
|
||||
events.Reset();
|
||||
summons.DespawnAll();
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_BRONJAHM, NOT_STARTED);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
me->RemoveAurasDueToSpell(SPELL_SOULSTORM_CHANNEL_OOC);
|
||||
|
||||
DoZoneInCombat();
|
||||
events.Reset();
|
||||
events.RescheduleEvent(EVENT_SPELL_SHADOW_BOLT, 2s);
|
||||
events.RescheduleEvent(EVENT_SPELL_MAGICS_BANE, 5s, 10s);
|
||||
events.RescheduleEvent(EVENT_SPELL_CORRUPT_SOUL, 14s, 20s);
|
||||
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_BRONJAHM, IN_PROGRESS);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (!me->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE) && me->HealthBelowPctDamaged(35, damage))
|
||||
{
|
||||
me->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE);
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->GetMotionMaster()->MoveIdle();
|
||||
me->CastSpell(me, SPELL_TELEPORT, false);
|
||||
events.CancelEvent(EVENT_SPELL_CORRUPT_SOUL);
|
||||
events.DelayEvents(6s);
|
||||
events.RescheduleEvent(EVENT_SPELL_FEAR, 8s, 14s);
|
||||
}
|
||||
}
|
||||
|
||||
void SpellHitTarget(Unit* /*target*/, SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_TELEPORT)
|
||||
{
|
||||
me->CastSpell(me, SPELL_TELEPORT_VISUAL, true);
|
||||
events.RescheduleEvent(EVENT_START_SOULSTORM, 1ms);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
if (me->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE))
|
||||
if (me->isAttackReady())
|
||||
me->SetFacingToObject(me->GetVictim());
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case EVENT_SPELL_SHADOW_BOLT:
|
||||
if (!me->IsWithinMeleeRange(me->GetVictim()))
|
||||
me->CastSpell(me->GetVictim(), SPELL_SHADOW_BOLT, false);
|
||||
events.Repeat(2s);
|
||||
break;
|
||||
case EVENT_SPELL_FEAR:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 10.0f, true))
|
||||
me->CastCustomSpell(SPELL_FEAR, SPELLVALUE_MAX_TARGETS, 1, target, false);
|
||||
events.Repeat(8s, 12s);
|
||||
break;
|
||||
case EVENT_SPELL_MAGICS_BANE:
|
||||
me->CastSpell(me->GetVictim(), SPELL_MAGICS_BANE, false);
|
||||
events.Repeat(10s, 15s);
|
||||
break;
|
||||
case EVENT_SPELL_CORRUPT_SOUL:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
|
||||
{
|
||||
Talk(SAY_CORRUPT_SOUL);
|
||||
me->CastSpell(target, SPELL_CORRUPT_SOUL, false);
|
||||
}
|
||||
events.Repeat(20s, 25s);
|
||||
break;
|
||||
case EVENT_START_SOULSTORM:
|
||||
Talk(SAY_SOUL_STORM);
|
||||
me->CastSpell(me, SPELL_SOULSTORM, false);
|
||||
me->CastSpell(me, SPELL_TELEPORT_VISUAL, true);
|
||||
me->CastSpell(me, SPELL_SOULSTORM_VISUAL, true);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_BRONJAHM, DONE);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* who) override
|
||||
{
|
||||
if (who->IsPlayer())
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
summon->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
me->RemoveUnitFlag(UNIT_FLAG_DISABLE_MOVE);
|
||||
ScriptedAI::EnterEvadeMode(why);
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void Reset() override
|
||||
{
|
||||
return GetForgeOfSoulsAI<boss_bronjahmAI>(creature);
|
||||
BossAI::Reset();
|
||||
me->RemoveUnitFlag(UNIT_FLAG_DISABLE_MOVE);
|
||||
DoCastSelf(SPELL_SOULSTORM_CHANNEL_OOC, true);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
Talk(SAY_AGGRO);
|
||||
me->RemoveAurasDueToSpell(SPELL_SOULSTORM_CHANNEL_OOC);
|
||||
|
||||
events.RescheduleEvent(EVENT_SPELL_SHADOW_BOLT, 2s);
|
||||
events.RescheduleEvent(EVENT_SPELL_MAGICS_BANE, 5s, 10s);
|
||||
events.RescheduleEvent(EVENT_SPELL_CORRUPT_SOUL, 14s, 20s);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (!me->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE) && me->HealthBelowPctDamaged(35, damage))
|
||||
{
|
||||
me->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE);
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->GetMotionMaster()->MoveIdle();
|
||||
DoCastSelf(SPELL_TELEPORT);
|
||||
events.CancelEvent(EVENT_SPELL_CORRUPT_SOUL);
|
||||
events.DelayEvents(6s);
|
||||
events.RescheduleEvent(EVENT_SPELL_FEAR, 8s, 14s);
|
||||
}
|
||||
}
|
||||
|
||||
void SpellHitTarget(Unit* /*target*/, SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_TELEPORT)
|
||||
{
|
||||
DoCastSelf(SPELL_TELEPORT_VISUAL, true);
|
||||
events.RescheduleEvent(EVENT_START_SOULSTORM, 1ms);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
if (me->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE))
|
||||
if (me->isAttackReady())
|
||||
me->SetFacingToObject(me->GetVictim());
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPELL_SHADOW_BOLT:
|
||||
if (!me->IsWithinMeleeRange(me->GetVictim()))
|
||||
DoCastVictim(SPELL_SHADOW_BOLT);
|
||||
events.Repeat(2s);
|
||||
break;
|
||||
case EVENT_SPELL_FEAR:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 10.0f, true))
|
||||
me->CastCustomSpell(SPELL_FEAR, SPELLVALUE_MAX_TARGETS, 1, target);
|
||||
events.Repeat(8s, 12s);
|
||||
break;
|
||||
case EVENT_SPELL_MAGICS_BANE:
|
||||
DoCastVictim(SPELL_MAGICS_BANE);
|
||||
events.Repeat(10s, 15s);
|
||||
break;
|
||||
case EVENT_SPELL_CORRUPT_SOUL:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
|
||||
{
|
||||
Talk(SAY_CORRUPT_SOUL);
|
||||
DoCast(target, SPELL_CORRUPT_SOUL);
|
||||
}
|
||||
events.Repeat(20s, 25s);
|
||||
break;
|
||||
case EVENT_START_SOULSTORM:
|
||||
Talk(SAY_SOUL_STORM);
|
||||
DoCastSelf(SPELL_SOULSTORM);
|
||||
DoCastSelf(SPELL_TELEPORT_VISUAL, true);
|
||||
DoCastSelf(SPELL_SOULSTORM_VISUAL, true);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* who) override
|
||||
{
|
||||
if (who->IsPlayer())
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
BossAI::JustSummoned(summon);
|
||||
summon->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
me->RemoveUnitFlag(UNIT_FLAG_DISABLE_MOVE);
|
||||
BossAI::EnterEvadeMode(why);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_fos_corrupted_soul_fragment : public CreatureScript
|
||||
struct npc_fos_corrupted_soul_fragment : public NullCreatureAI
|
||||
{
|
||||
public:
|
||||
npc_fos_corrupted_soul_fragment() : CreatureScript("npc_fos_corrupted_soul_fragment") { }
|
||||
|
||||
struct npc_fos_corrupted_soul_fragmentAI : public NullCreatureAI
|
||||
npc_fos_corrupted_soul_fragment(Creature* creature) : NullCreatureAI(creature)
|
||||
{
|
||||
npc_fos_corrupted_soul_fragmentAI(Creature* creature) : NullCreatureAI(creature)
|
||||
{
|
||||
pInstance = me->GetInstanceScript();
|
||||
}
|
||||
Instance = me->GetInstanceScript();
|
||||
}
|
||||
|
||||
uint32 timer;
|
||||
InstanceScript* pInstance;
|
||||
uint32 Timer = 0;
|
||||
InstanceScript* Instance = nullptr;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
timer = 0;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (pInstance)
|
||||
if (Creature* b = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_BRONJAHM)))
|
||||
{
|
||||
if (me->GetExactDist2d(b) <= 2.0f)
|
||||
{
|
||||
me->GetMotionMaster()->MoveIdle();
|
||||
me->CastSpell(b, SPELL_CONSUME_SOUL, true);
|
||||
me->DespawnOrUnsummon(1ms);
|
||||
return;
|
||||
}
|
||||
|
||||
if (timer <= diff)
|
||||
{
|
||||
if (!me->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED))
|
||||
me->GetMotionMaster()->MovePoint(0, *b);
|
||||
timer = 1000;
|
||||
}
|
||||
else
|
||||
timer -= diff;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void Reset() override
|
||||
{
|
||||
return GetForgeOfSoulsAI<npc_fos_corrupted_soul_fragmentAI>(creature);
|
||||
Timer = 0;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!Instance)
|
||||
return;
|
||||
|
||||
Creature* bronjahm = Instance->GetCreature(DATA_BRONJAHM);
|
||||
if (!bronjahm)
|
||||
return;
|
||||
|
||||
if (me->GetExactDist2d(bronjahm) <= 2.0f)
|
||||
{
|
||||
me->GetMotionMaster()->MoveIdle();
|
||||
me->CastSpell(bronjahm, SPELL_CONSUME_SOUL, true);
|
||||
me->DespawnOrUnsummon(1ms);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Timer <= diff)
|
||||
{
|
||||
if (!me->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED))
|
||||
me->GetMotionMaster()->MovePoint(0, *bronjahm);
|
||||
Timer = 1000;
|
||||
}
|
||||
else
|
||||
Timer -= diff;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -275,7 +239,7 @@ class spell_bronjahm_magic_bane : public SpellScript
|
|||
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
const int32 maxDamage = caster->GetMap()->GetSpawnMode() == 1 ? 15000 : 10000;
|
||||
int32 const maxDamage = caster->GetMap()->GetSpawnMode() == 1 ? 15000 : 10000;
|
||||
int32 newDamage = GetHitDamage();
|
||||
newDamage += GetHitUnit()->GetMaxPower(POWER_MANA) / 2;
|
||||
newDamage = std::min<int32>(maxDamage, newDamage);
|
||||
|
|
@ -365,9 +329,8 @@ class spell_bronjahm_soulstorm_targeting : public SpellScript
|
|||
|
||||
void AddSC_boss_bronjahm()
|
||||
{
|
||||
new boss_bronjahm();
|
||||
new npc_fos_corrupted_soul_fragment();
|
||||
|
||||
RegisterForgeOfSoulsCreatureAI(boss_bronjahm);
|
||||
RegisterForgeOfSoulsCreatureAI(npc_fos_corrupted_soul_fragment);
|
||||
RegisterSpellScript(spell_bronjahm_magic_bane);
|
||||
RegisterSpellScript(spell_bronjahm_soulstorm_channel_ooc_aura);
|
||||
RegisterSpellScript(spell_bronjahm_soulstorm_visual_aura);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
#include "SpellScriptLoader.h"
|
||||
#include "forge_of_souls.h"
|
||||
|
||||
enum eTexts
|
||||
enum Texts
|
||||
{
|
||||
SAY_FACE_AGGRO = 0,
|
||||
SAY_FACE_ANGER_SLAY = 1,
|
||||
|
|
@ -38,7 +38,7 @@ enum eTexts
|
|||
SAY_FACE_WAILING_SOUL = 9,
|
||||
};
|
||||
|
||||
enum eSpells
|
||||
enum Spells
|
||||
{
|
||||
SPELL_PHANTOM_BLAST = 68982,
|
||||
SPELL_PHANTOM_BLAST_H = 70322,
|
||||
|
|
@ -57,7 +57,7 @@ enum eSpells
|
|||
SPELL_WAILING_SOULS_DMG_H = 70324, // 100yd, 104.0
|
||||
};
|
||||
|
||||
enum eEvents
|
||||
enum Events
|
||||
{
|
||||
EVENT_SPELL_PHANTOM_BLAST = 1,
|
||||
EVENT_SPELL_MIRRORED_SOUL,
|
||||
|
|
@ -66,245 +66,214 @@ enum eEvents
|
|||
EVENT_SPELL_WAILING_SOULS,
|
||||
};
|
||||
|
||||
enum eDisplayIds
|
||||
enum ModelIds
|
||||
{
|
||||
DISPLAY_ANGER = 30148,
|
||||
DISPLAY_SORROW = 30149,
|
||||
DISPLAY_DESIRE = 30150,
|
||||
MODEL_ANGER = 30148,
|
||||
MODEL_SORROW = 30149,
|
||||
MODEL_DESIRE = 30150,
|
||||
};
|
||||
|
||||
enum eMisc
|
||||
enum Misc
|
||||
{
|
||||
NPC_CRUCIBLE_OF_SOULS = 37094,
|
||||
NPC_UNLEASHED_SOUL = 36595,
|
||||
QUEST_TEMPERING_THE_BLADE_A = 24476,
|
||||
QUEST_TEMPERING_THE_BLADE_H = 24560,
|
||||
};
|
||||
|
||||
class boss_devourer_of_souls : public CreatureScript
|
||||
struct boss_devourer_of_souls : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_devourer_of_souls() : CreatureScript("boss_devourer_of_souls") { }
|
||||
boss_devourer_of_souls(Creature* creature) : BossAI(creature, DATA_DEVOURER) { }
|
||||
|
||||
struct boss_devourer_of_soulsAI : public ScriptedAI
|
||||
bool AchievementCompleted = true;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
boss_devourer_of_soulsAI(Creature* creature) : ScriptedAI(creature), summons(me)
|
||||
{
|
||||
pInstance = creature->GetInstanceScript();
|
||||
}
|
||||
BossAI::Reset();
|
||||
AchievementCompleted = true;
|
||||
me->SetControlled(false, UNIT_STATE_ROOT);
|
||||
me->DisableRotate(false);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
}
|
||||
|
||||
InstanceScript* pInstance;
|
||||
EventMap events;
|
||||
SummonList summons;
|
||||
bool bAchiev;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
bAchiev = true;
|
||||
me->SetControlled(false, UNIT_STATE_ROOT);
|
||||
me->DisableRotate(false);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
events.Reset();
|
||||
summons.DespawnAll();
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_DEVOURER, NOT_STARTED);
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 id) const override
|
||||
{
|
||||
if (id == 1)
|
||||
return bAchiev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_FACE_AGGRO);
|
||||
DoZoneInCombat();
|
||||
events.Reset();
|
||||
events.RescheduleEvent(EVENT_SPELL_PHANTOM_BLAST, 5s);
|
||||
events.RescheduleEvent(EVENT_SPELL_MIRRORED_SOUL, 9s);
|
||||
events.RescheduleEvent(EVENT_SPELL_WELL_OF_SOULS, 6s, 8s);
|
||||
events.RescheduleEvent(EVENT_SPELL_UNLEASHED_SOULS, 18s, 20s);
|
||||
events.RescheduleEvent(EVENT_SPELL_WAILING_SOULS, 65s);
|
||||
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_DEVOURER, IN_PROGRESS);
|
||||
|
||||
// Suport for Quest Tempering the Blade
|
||||
Map::PlayerList const& pList = me->GetMap()->GetPlayers();
|
||||
for(Map::PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr)
|
||||
{
|
||||
Player* player = itr->GetSource();
|
||||
if ((player->GetTeamId() == TEAM_ALLIANCE && player->GetQuestStatus(QUEST_TEMPERING_THE_BLADE_A) == QUEST_STATUS_INCOMPLETE) ||
|
||||
(player->GetTeamId() == TEAM_HORDE && player->GetQuestStatus(QUEST_TEMPERING_THE_BLADE_H) == QUEST_STATUS_INCOMPLETE))
|
||||
{
|
||||
if (!me->FindNearestCreature(NPC_CRUCIBLE_OF_SOULS, 100.0f))
|
||||
me->SummonCreature(NPC_CRUCIBLE_OF_SOULS, 5672.29f, 2520.69f, 713.44f, 0.96f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpellHitTarget(Unit* target, SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_PHANTOM_BLAST_H)
|
||||
bAchiev = false;
|
||||
else if (spell->Id == SPELL_WAILING_SOULS_TARGETING)
|
||||
{
|
||||
me->SetOrientation(me->GetAngle(target));
|
||||
me->SetControlled(true, UNIT_STATE_ROOT);
|
||||
me->DisableRotate(true);
|
||||
me->SetGuidValue(UNIT_FIELD_TARGET, ObjectGuid::Empty);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->GetMotionMaster()->Clear(false);
|
||||
me->GetMotionMaster()->MoveIdle();
|
||||
me->StopMovingOnCurrentPos();
|
||||
|
||||
me->SetFacingToObject(target);
|
||||
me->SendMovementFlagUpdate();
|
||||
me->CastSpell(me, SPELL_WAILING_SOULS, false);
|
||||
}
|
||||
}
|
||||
|
||||
bool CanAIAttack(Unit const* target) const override { return target->GetPositionZ() > 706.5f; }
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (Spell* s = me->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
||||
if (s->m_spellInfo->Id == SPELL_MIRRORED_SOUL)
|
||||
{
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case EVENT_SPELL_PHANTOM_BLAST:
|
||||
me->CastSpell(me->GetVictim(), SPELL_PHANTOM_BLAST, false);
|
||||
events.Repeat(5s);
|
||||
break;
|
||||
default:
|
||||
events.Repeat(1s);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!me->GetCurrentSpell(CURRENT_GENERIC_SPELL))
|
||||
{
|
||||
me->ClearUnitState(UNIT_STATE_CASTING);
|
||||
DoMeleeAttackIfReady();
|
||||
me->AddUnitState(UNIT_STATE_CASTING);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case EVENT_SPELL_PHANTOM_BLAST:
|
||||
me->CastSpell(me->GetVictim(), SPELL_PHANTOM_BLAST, false);
|
||||
events.Repeat(5s);
|
||||
break;
|
||||
case EVENT_SPELL_MIRRORED_SOUL:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 90.0f, true))
|
||||
{
|
||||
me->CastSpell(target, SPELL_MIRRORED_SOUL, false);
|
||||
me->setAttackTimer(BASE_ATTACK, 2500);
|
||||
Talk(EMOTE_MIRRORED_SOUL);
|
||||
}
|
||||
events.Repeat(20s, 30s);
|
||||
break;
|
||||
case EVENT_SPELL_WELL_OF_SOULS:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f, true))
|
||||
me->CastSpell(target, SPELL_WELL_OF_SOULS, false);
|
||||
events.Repeat(25s, 30s);
|
||||
events.DelayEventsToMax(4s, 0);
|
||||
break;
|
||||
case EVENT_SPELL_UNLEASHED_SOULS:
|
||||
me->CastSpell(me, SPELL_UNLEASHED_SOULS, false);
|
||||
Talk(SAY_FACE_UNLEASH_SOUL);
|
||||
Talk(EMOTE_UNLEASH_SOUL);
|
||||
events.Repeat(30s, 40s);
|
||||
events.DelayEventsToMax(5s, 0);
|
||||
me->setAttackTimer(BASE_ATTACK, 5500);
|
||||
break;
|
||||
case EVENT_SPELL_WAILING_SOULS:
|
||||
Talk(SAY_FACE_WAILING_SOUL);
|
||||
Talk(EMOTE_WAILING_SOUL);
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
|
||||
me->CastCustomSpell(SPELL_WAILING_SOULS_TARGETING, SPELLVALUE_MAX_TARGETS, 1, target, false);
|
||||
events.Repeat(80s);
|
||||
events.DelayEventsToMax(20s, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_FACE_DEATH);
|
||||
summons.DespawnAll();
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_DEVOURER, DONE);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (!victim->IsPlayer())
|
||||
return;
|
||||
|
||||
int32 textId = 0;
|
||||
switch (me->GetDisplayId())
|
||||
{
|
||||
case DISPLAY_ANGER:
|
||||
textId = SAY_FACE_ANGER_SLAY;
|
||||
break;
|
||||
case DISPLAY_SORROW:
|
||||
textId = SAY_FACE_SORROW_SLAY;
|
||||
break;
|
||||
case DISPLAY_DESIRE:
|
||||
textId = SAY_FACE_DESIRE_SLAY;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (textId)
|
||||
Talk(textId);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
if (summon->GetEntry() != NPC_CRUCIBLE_OF_SOULS)
|
||||
summons.Summon(summon);
|
||||
|
||||
if (summon->GetEntry() == 36595)
|
||||
if (Player* plr = summon->SelectNearestPlayer(100.0f))
|
||||
{
|
||||
summon->AddThreat(plr, 100000.0f);
|
||||
summon->AI()->AttackStart(plr);
|
||||
}
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
me->SetControlled(false, UNIT_STATE_ROOT);
|
||||
me->DisableRotate(false);
|
||||
ScriptedAI::EnterEvadeMode(why);
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
uint32 GetData(uint32 id) const override
|
||||
{
|
||||
return GetForgeOfSoulsAI<boss_devourer_of_soulsAI>(creature);
|
||||
if (id == 1)
|
||||
return AchievementCompleted;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
Talk(SAY_FACE_AGGRO);
|
||||
events.RescheduleEvent(EVENT_SPELL_PHANTOM_BLAST, 5s);
|
||||
events.RescheduleEvent(EVENT_SPELL_MIRRORED_SOUL, 9s);
|
||||
events.RescheduleEvent(EVENT_SPELL_WELL_OF_SOULS, 6s, 8s);
|
||||
events.RescheduleEvent(EVENT_SPELL_UNLEASHED_SOULS, 18s, 20s);
|
||||
events.RescheduleEvent(EVENT_SPELL_WAILING_SOULS, 65s);
|
||||
|
||||
// Support for Quest Tempering the Blade
|
||||
me->GetMap()->DoForAllPlayers([this](Player* player)
|
||||
{
|
||||
if (me->FindNearestCreature(NPC_CRUCIBLE_OF_SOULS, 100.0f))
|
||||
return;
|
||||
|
||||
uint32 questId = player->GetTeamId() == TEAM_ALLIANCE ? QUEST_TEMPERING_THE_BLADE_A : QUEST_TEMPERING_THE_BLADE_H;
|
||||
if (player->GetQuestStatus(questId) == QUEST_STATUS_INCOMPLETE)
|
||||
me->SummonCreature(NPC_CRUCIBLE_OF_SOULS, 5672.29f, 2520.69f, 713.44f, 0.96f);
|
||||
});
|
||||
}
|
||||
|
||||
void SpellHitTarget(Unit* target, SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_PHANTOM_BLAST_H)
|
||||
AchievementCompleted = false;
|
||||
else if (spell->Id == SPELL_WAILING_SOULS_TARGETING)
|
||||
{
|
||||
me->SetOrientation(me->GetAngle(target));
|
||||
me->SetControlled(true, UNIT_STATE_ROOT);
|
||||
me->DisableRotate(true);
|
||||
me->SetGuidValue(UNIT_FIELD_TARGET, ObjectGuid::Empty);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->GetMotionMaster()->Clear(false);
|
||||
me->GetMotionMaster()->MoveIdle();
|
||||
me->StopMovingOnCurrentPos();
|
||||
|
||||
me->SetFacingToObject(target);
|
||||
me->SendMovementFlagUpdate();
|
||||
DoCastSelf(SPELL_WAILING_SOULS);
|
||||
}
|
||||
}
|
||||
|
||||
bool CanAIAttack(Unit const* target) const override { return target->GetPositionZ() > 706.5f; }
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (Spell* s = me->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
||||
if (s->m_spellInfo->Id == SPELL_MIRRORED_SOUL)
|
||||
{
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPELL_PHANTOM_BLAST:
|
||||
DoCastVictim(SPELL_PHANTOM_BLAST);
|
||||
events.Repeat(5s);
|
||||
break;
|
||||
default:
|
||||
events.Repeat(1s);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!me->GetCurrentSpell(CURRENT_GENERIC_SPELL))
|
||||
{
|
||||
me->ClearUnitState(UNIT_STATE_CASTING);
|
||||
DoMeleeAttackIfReady();
|
||||
me->AddUnitState(UNIT_STATE_CASTING);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPELL_PHANTOM_BLAST:
|
||||
DoCastVictim(SPELL_PHANTOM_BLAST);
|
||||
events.Repeat(5s);
|
||||
break;
|
||||
case EVENT_SPELL_MIRRORED_SOUL:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 90.0f, true))
|
||||
{
|
||||
DoCast(target, SPELL_MIRRORED_SOUL);
|
||||
me->setAttackTimer(BASE_ATTACK, 2500);
|
||||
Talk(EMOTE_MIRRORED_SOUL);
|
||||
}
|
||||
events.Repeat(20s, 30s);
|
||||
break;
|
||||
case EVENT_SPELL_WELL_OF_SOULS:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f, true))
|
||||
DoCast(target, SPELL_WELL_OF_SOULS);
|
||||
events.Repeat(25s, 30s);
|
||||
events.DelayEventsToMax(4s, 0);
|
||||
break;
|
||||
case EVENT_SPELL_UNLEASHED_SOULS:
|
||||
DoCastSelf(SPELL_UNLEASHED_SOULS);
|
||||
Talk(SAY_FACE_UNLEASH_SOUL);
|
||||
Talk(EMOTE_UNLEASH_SOUL);
|
||||
events.Repeat(30s, 40s);
|
||||
events.DelayEventsToMax(5s, 0);
|
||||
me->setAttackTimer(BASE_ATTACK, 5500);
|
||||
break;
|
||||
case EVENT_SPELL_WAILING_SOULS:
|
||||
Talk(SAY_FACE_WAILING_SOUL);
|
||||
Talk(EMOTE_WAILING_SOUL);
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
|
||||
me->CastCustomSpell(SPELL_WAILING_SOULS_TARGETING, SPELLVALUE_MAX_TARGETS, 1, target);
|
||||
events.Repeat(80s);
|
||||
events.DelayEventsToMax(20s, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
Talk(SAY_FACE_DEATH);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (!victim->IsPlayer())
|
||||
return;
|
||||
|
||||
uint8 textId = 0;
|
||||
switch (me->GetDisplayId())
|
||||
{
|
||||
case MODEL_ANGER:
|
||||
textId = SAY_FACE_ANGER_SLAY;
|
||||
break;
|
||||
case MODEL_SORROW:
|
||||
textId = SAY_FACE_SORROW_SLAY;
|
||||
break;
|
||||
case MODEL_DESIRE:
|
||||
textId = SAY_FACE_DESIRE_SLAY;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (textId)
|
||||
Talk(textId);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
if (summon->GetEntry() != NPC_CRUCIBLE_OF_SOULS)
|
||||
BossAI::JustSummoned(summon);
|
||||
|
||||
if (summon->GetEntry() == NPC_UNLEASHED_SOUL)
|
||||
if (Player* player = summon->SelectNearestPlayer(100.0f))
|
||||
{
|
||||
summon->AddThreat(player, 100000.0f);
|
||||
summon->AI()->AttackStart(player);
|
||||
}
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
me->SetControlled(false, UNIT_STATE_ROOT);
|
||||
me->DisableRotate(false);
|
||||
BossAI::EnterEvadeMode(why);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -317,7 +286,7 @@ class spell_wailing_souls_periodic_aura : public AuraScript
|
|||
return ValidateSpellInfo({ SPELL_WAILING_SOULS_DMG_N });
|
||||
}
|
||||
|
||||
int8 dir;
|
||||
int8 dir = 0;
|
||||
|
||||
bool Load() override
|
||||
{
|
||||
|
|
@ -328,31 +297,30 @@ class spell_wailing_souls_periodic_aura : public AuraScript
|
|||
void HandlePeriodicTick(AuraEffect const* aurEff)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
if (Unit* t = GetTarget())
|
||||
if (Unit* target = GetTarget())
|
||||
{
|
||||
if (aurEff->GetTickNumber() < 30)
|
||||
{
|
||||
// spinning, casting, etc.
|
||||
float diff = (2 * M_PI) / (4 * 30);
|
||||
float new_o = t->GetOrientation() + diff * dir;
|
||||
if (new_o >= 2 * M_PI)
|
||||
new_o -= 2 * M_PI;
|
||||
else if (new_o < 0)
|
||||
new_o += 2 * M_PI;
|
||||
t->UpdateOrientation(new_o);
|
||||
t->SetFacingTo(new_o);
|
||||
t->CastSpell(t, SPELL_WAILING_SOULS_DMG_N, true);
|
||||
float newOrientation = target->GetOrientation() + diff * dir;
|
||||
if (newOrientation >= 2 * M_PI)
|
||||
newOrientation -= 2 * M_PI;
|
||||
else if (newOrientation < 0)
|
||||
newOrientation += 2 * M_PI;
|
||||
target->UpdateOrientation(newOrientation);
|
||||
target->SetFacingTo(newOrientation);
|
||||
target->CastSpell(target, SPELL_WAILING_SOULS_DMG_N, true);
|
||||
}
|
||||
else if (aurEff->GetTickNumber() == 33)
|
||||
{
|
||||
t->SetControlled(false, UNIT_STATE_ROOT);
|
||||
t->DisableRotate(false);
|
||||
if (t->IsCreature())
|
||||
t->ToCreature()->SetReactState(REACT_AGGRESSIVE);
|
||||
if (t->GetVictim())
|
||||
target->SetControlled(false, UNIT_STATE_ROOT);
|
||||
target->DisableRotate(false);
|
||||
if (target->IsCreature())
|
||||
target->ToCreature()->SetReactState(REACT_AGGRESSIVE);
|
||||
if (target->GetVictim())
|
||||
{
|
||||
t->SetGuidValue(UNIT_FIELD_TARGET, t->GetVictim()->GetGUID());
|
||||
t->GetMotionMaster()->MoveChase(t->GetVictim());
|
||||
target->SetGuidValue(UNIT_FIELD_TARGET, target->GetVictim()->GetGUID());
|
||||
target->GetMotionMaster()->MoveChase(target->GetVictim());
|
||||
}
|
||||
}
|
||||
else if (aurEff->GetTickNumber() >= 34)
|
||||
|
|
@ -368,6 +336,6 @@ class spell_wailing_souls_periodic_aura : public AuraScript
|
|||
|
||||
void AddSC_boss_devourer_of_souls()
|
||||
{
|
||||
new boss_devourer_of_souls();
|
||||
RegisterForgeOfSoulsCreatureAI(boss_devourer_of_souls);
|
||||
RegisterSpellScript(spell_wailing_souls_periodic_aura);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,11 @@ enum Data
|
|||
DATA_BRONJAHM,
|
||||
DATA_DEVOURER,
|
||||
MAX_ENCOUNTER,
|
||||
|
||||
DATA_LEADER_FIRST,
|
||||
DATA_LEADER_SECOND,
|
||||
DATA_GUARD_FIRST,
|
||||
DATA_GUARD_SECOND,
|
||||
};
|
||||
|
||||
enum Creatures
|
||||
|
|
@ -99,4 +104,6 @@ inline AI* GetForgeOfSoulsAI(T* obj)
|
|||
return GetInstanceAI<AI>(obj, ForgeOfSoulsScriptName);
|
||||
}
|
||||
|
||||
#define RegisterForgeOfSoulsCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetForgeOfSoulsAI)
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -21,12 +21,29 @@
|
|||
#include "forge_of_souls.h"
|
||||
#include "Group.h"
|
||||
|
||||
enum Misc
|
||||
{
|
||||
NPC_CORRUPTED_SOUL_FRAGMENT = 36535,
|
||||
|
||||
ACHIEV_CRITERIA_SOUL_POWER = 12752,
|
||||
ACHIEV_CRITERIA_THREE_FACED = 12976,
|
||||
|
||||
SOUL_POWER_FRAGMENT_COUNT = 4,
|
||||
};
|
||||
|
||||
BossBoundaryData const boundaries =
|
||||
{
|
||||
{ DATA_BRONJAHM, new CircleBoundary(Position(5297.3f, 2506.45f), 100.96) },
|
||||
{ DATA_DEVOURER, new ParallelogramBoundary(Position(5663.56f, 2570.53f), Position(5724.39f, 2520.45f), Position(5570.36f, 2461.42f)) }
|
||||
};
|
||||
|
||||
static ObjectData const creatureData[] =
|
||||
{
|
||||
{ NPC_BRONJAHM, DATA_BRONJAHM },
|
||||
{ NPC_DEVOURER, DATA_DEVOURER },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
class instance_forge_of_souls : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
|
|
@ -42,38 +59,22 @@ public:
|
|||
instance_forge_of_souls_InstanceScript(Map* map) : InstanceScript(map)
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(MAX_ENCOUNTER);
|
||||
LoadObjectData(creatureData, nullptr);
|
||||
LoadBossBoundaries(boundaries);
|
||||
}
|
||||
|
||||
uint32 m_auiEncounter[MAX_ENCOUNTER];
|
||||
std::string str_data;
|
||||
ObjectGuid NPC_BronjahmGUID;
|
||||
ObjectGuid NPC_DevourerGUID;
|
||||
|
||||
ObjectGuid NPC_LeaderFirstGUID;
|
||||
ObjectGuid NPC_LeaderSecondGUID;
|
||||
ObjectGuid NPC_GuardFirstGUID;
|
||||
ObjectGuid NPC_GuardSecondGUID;
|
||||
|
||||
void Initialize() override
|
||||
{
|
||||
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
|
||||
}
|
||||
|
||||
bool IsEncounterInProgress() const override
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
|
||||
if (m_auiEncounter[i] == IN_PROGRESS) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
ObjectGuid LeaderFirstGUID;
|
||||
ObjectGuid LeaderSecondGUID;
|
||||
ObjectGuid GuardFirstGUID;
|
||||
ObjectGuid GuardSecondGUID;
|
||||
|
||||
void OnPlayerEnter(Player* player) override
|
||||
{
|
||||
InstanceScript::OnPlayerEnter(player);
|
||||
|
||||
// this will happen only after crash and loading the instance from db
|
||||
if (m_auiEncounter[0] == DONE && m_auiEncounter[1] == DONE && (!NPC_LeaderSecondGUID || !instance->GetCreature(NPC_LeaderSecondGUID)))
|
||||
if (AllBossesDone() && (!LeaderSecondGUID || !instance->GetCreature(LeaderSecondGUID)))
|
||||
{
|
||||
Position pos = {5658.15f, 2502.564f, 708.83f, 0.885207f};
|
||||
instance->SummonCreature(NPC_SYLVANAS_PART2, pos);
|
||||
|
|
@ -82,44 +83,40 @@ public:
|
|||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
{
|
||||
InstanceScript::OnCreatureCreate(creature);
|
||||
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_BRONJAHM:
|
||||
NPC_BronjahmGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_DEVOURER:
|
||||
NPC_DevourerGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_SYLVANAS_PART1:
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_JAINA_PART1);
|
||||
NPC_LeaderFirstGUID = creature->GetGUID();
|
||||
LeaderFirstGUID = creature->GetGUID();
|
||||
|
||||
if (m_auiEncounter[0] == DONE && m_auiEncounter[1] == DONE)
|
||||
if (AllBossesDone())
|
||||
creature->SetVisible(false);
|
||||
break;
|
||||
case NPC_SYLVANAS_PART2:
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_JAINA_PART2);
|
||||
NPC_LeaderSecondGUID = creature->GetGUID();
|
||||
LeaderSecondGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_LORALEN:
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_ELANDRA);
|
||||
if (!NPC_GuardFirstGUID)
|
||||
if (!GuardFirstGUID)
|
||||
{
|
||||
NPC_GuardFirstGUID = creature->GetGUID();
|
||||
if (m_auiEncounter[0] == DONE && m_auiEncounter[1] == DONE)
|
||||
GuardFirstGUID = creature->GetGUID();
|
||||
if (AllBossesDone())
|
||||
creature->SetVisible(false);
|
||||
}
|
||||
break;
|
||||
case NPC_KALIRA:
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_KORELN);
|
||||
if (!NPC_GuardSecondGUID)
|
||||
if (!GuardSecondGUID)
|
||||
{
|
||||
NPC_GuardSecondGUID = creature->GetGUID();
|
||||
if (m_auiEncounter[0] == DONE && m_auiEncounter[1] == DONE)
|
||||
GuardSecondGUID = creature->GetGUID();
|
||||
if (AllBossesDone())
|
||||
creature->SetVisible(false);
|
||||
}
|
||||
break;
|
||||
|
|
@ -128,9 +125,9 @@ public:
|
|||
|
||||
void HandleOutro()
|
||||
{
|
||||
if (!NPC_LeaderSecondGUID || !instance->GetCreature(NPC_LeaderSecondGUID))
|
||||
if (!LeaderSecondGUID || !instance->GetCreature(LeaderSecondGUID))
|
||||
if (Creature* leader = instance->SummonCreature(NPC_SYLVANAS_PART2, outroSpawnPoint))
|
||||
if (Creature* boss = instance->GetCreature(NPC_DevourerGUID))
|
||||
if (Creature* boss = GetCreature(DATA_DEVOURER))
|
||||
{
|
||||
float angle = boss->GetAngle(leader);
|
||||
leader->GetMotionMaster()->MovePoint(1, boss->GetPositionX() + 10.0f * cos(angle), boss->GetPositionY() + 10.0f * std::sin(angle), boss->GetPositionZ());
|
||||
|
|
@ -144,69 +141,37 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
bool SetBossState(uint32 type, EncounterState state) override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_BRONJAHM:
|
||||
m_auiEncounter[type] = data;
|
||||
break;
|
||||
case DATA_DEVOURER:
|
||||
m_auiEncounter[type] = data;
|
||||
if (m_auiEncounter[0] == DONE && m_auiEncounter[1] == DONE)
|
||||
HandleOutro();
|
||||
break;
|
||||
}
|
||||
if (!InstanceScript::SetBossState(type, state))
|
||||
return false;
|
||||
|
||||
if (data == DONE)
|
||||
SaveToDB();
|
||||
}
|
||||
if (state == DONE && AllBossesDone())
|
||||
HandleOutro();
|
||||
|
||||
ObjectGuid GetGuidData(uint32 type) const override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_BRONJAHM:
|
||||
return NPC_BronjahmGUID;
|
||||
}
|
||||
|
||||
return ObjectGuid::Empty;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target*/, uint32 /*miscvalue1*/) override
|
||||
{
|
||||
switch (criteria_id)
|
||||
{
|
||||
case 12752: // Soul Power
|
||||
if (Creature* c = instance->GetCreature(NPC_BronjahmGUID))
|
||||
case ACHIEV_CRITERIA_SOUL_POWER:
|
||||
if (Creature* bronjahm = GetCreature(DATA_BRONJAHM))
|
||||
{
|
||||
std::list<Creature*> L;
|
||||
uint8 count = 0;
|
||||
c->GetCreaturesWithEntryInRange(L, 200.0f, 36535); // find all Corrupted Soul Fragment (36535)
|
||||
for( std::list<Creature*>::const_iterator itr = L.begin(); itr != L.end(); ++itr )
|
||||
if ((*itr)->IsAlive())
|
||||
++count;
|
||||
return (count >= 4);
|
||||
std::list<Creature*> fragments;
|
||||
bronjahm->GetCreaturesWithEntryInRange(fragments, 200.0f, NPC_CORRUPTED_SOUL_FRAGMENT);
|
||||
return std::count_if(fragments.begin(), fragments.end(),
|
||||
[](Creature const* fragment) { return fragment->IsAlive(); }) >= SOUL_POWER_FRAGMENT_COUNT;
|
||||
}
|
||||
break;
|
||||
case 12976:
|
||||
if (Creature* c = instance->GetCreature(NPC_DevourerGUID))
|
||||
return (bool)c->AI()->GetData(1);
|
||||
case ACHIEV_CRITERIA_THREE_FACED:
|
||||
if (Creature* devourer = GetCreature(DATA_DEVOURER))
|
||||
return devourer->AI()->GetData(1) != 0;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ReadSaveDataMore(std::istringstream& data) override
|
||||
{
|
||||
data >> m_auiEncounter[0];
|
||||
data >> m_auiEncounter[1];
|
||||
}
|
||||
|
||||
void WriteSaveDataMore(std::ostringstream& data) override
|
||||
{
|
||||
data << m_auiEncounter[0] << ' ' << m_auiEncounter[1];
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue