fix(Core/RuinsOfAhnQiraj): Buru (#12524)

* fix(Core/RuinsOfAhnQiraj): Buru

* spaces

* revert phase transition

* leftover conversion
This commit is contained in:
Nefertumm
2022-07-26 01:29:12 -03:00
committed by GitHub
parent 90d08158d9
commit f236921498
3 changed files with 205 additions and 237 deletions
@@ -0,0 +1,4 @@
--
DELETE FROM `spell_custom_attr` WHERE `spell_id` = 5255;
INSERT INTO `spell_custom_attr` (`spell_id`, `attributes`) VALUES
(5255, 0x00008000);
@@ -18,6 +18,7 @@
#include "ScriptMgr.h" #include "ScriptMgr.h"
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "SpellScript.h" #include "SpellScript.h"
#include "TaskScheduler.h"
#include "ruins_of_ahnqiraj.h" #include "ruins_of_ahnqiraj.h"
enum Emotes enum Emotes
@@ -35,8 +36,9 @@ enum Spells
SPELL_BURU_TRANSFORM = 24721, SPELL_BURU_TRANSFORM = 24721,
SPELL_SUMMON_HATCHLING = 1881, SPELL_SUMMON_HATCHLING = 1881,
SPELL_EXPLODE = 19593, SPELL_EXPLODE = 19593,
SPELL_EXPLODE_2 = 5255, // Server-side script SPELL_EXPLODE_2 = 5255,
SPELL_BURU_EGG_TRIGGER = 26646 SPELL_BURU_EGG_TRIGGER = 26646,
SPELL_CREATURE_SPECIAL = 7155, // from sniffs
}; };
enum Events enum Events
@@ -45,7 +47,7 @@ enum Events
EVENT_GATHERING_SPEED = 2, EVENT_GATHERING_SPEED = 2,
EVENT_FULL_SPEED = 3, EVENT_FULL_SPEED = 3,
EVENT_CREEPING_PLAGUE = 4, EVENT_CREEPING_PLAGUE = 4,
EVENT_RESPAWN_EGG = 5 EVENT_RESPAWN_EGG = 5,
}; };
enum Phases enum Phases
@@ -54,45 +56,47 @@ enum Phases
PHASE_TRANSFORM = 1 PHASE_TRANSFORM = 1
}; };
enum Actions struct boss_buru : public BossAI
{ {
ACTION_EXPLODE = 0 boss_buru(Creature* creature) : BossAI(creature, DATA_BURU) {}
};
class boss_buru : public CreatureScript
{
public:
boss_buru() : CreatureScript("boss_buru") { }
struct boss_buruAI : public BossAI
{
boss_buruAI(Creature* creature) : BossAI(creature, DATA_BURU) {}
void EnterEvadeMode(EvadeReason why) override void EnterEvadeMode(EvadeReason why) override
{ {
BossAI::EnterEvadeMode(why); BossAI::EnterEvadeMode(why);
for (ObjectGuid const& guid : Eggs) DoCastSelf(SPELL_FULL_SPEED, true);
{
if (Creature* egg = me->GetMap()->GetCreature(guid)) ManipulateEggs(true);
{ _eggs.clear();
egg->Respawn();
} }
}
Eggs.clear(); void ManipulateEggs(bool respawn)
{
std::list<Creature*> eggs;
me->GetCreaturesWithEntryInRange(eggs, 150.0f, NPC_BURU_EGG);
for (Creature* egg : eggs)
respawn ? egg->Respawn() : Unit::Kill(me, egg);
} }
void EnterCombat(Unit* who) override void EnterCombat(Unit* who) override
{ {
_EnterCombat(); _EnterCombat();
Talk(EMOTE_TARGET, who); Talk(EMOTE_TARGET, who);
DoCast(me, SPELL_THORNS); DoCastSelf(SPELL_THORNS);
events.ScheduleEvent(EVENT_DISMEMBER, 5000); ManipulateEggs(true);
events.ScheduleEvent(EVENT_GATHERING_SPEED, 9000); me->RemoveAurasDueToSpell(SPELL_FULL_SPEED);
events.ScheduleEvent(EVENT_FULL_SPEED, 60000); events.ScheduleEvent(EVENT_DISMEMBER, 5s);
events.ScheduleEvent(EVENT_GATHERING_SPEED, 9s);
events.ScheduleEvent(EVENT_FULL_SPEED, 60s);
_phase = PHASE_EGG; _phase = PHASE_EGG;
} }
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
{
if (spell->Id == SPELL_CREATURE_SPECIAL)
ChaseNewVictim();
}
void JustDied(Unit* /*killer*/) override void JustDied(Unit* /*killer*/) override
{ {
if (InstanceScript* pInstance = me->GetInstanceScript()) if (InstanceScript* pInstance = me->GetInstanceScript())
@@ -101,24 +105,11 @@ public:
} }
} }
void DoAction(int32 action) override
{
if (action == ACTION_EXPLODE)
{
if (_phase == PHASE_EGG)
{
Unit::DealDamage(me, me, 45000);
}
}
}
void KilledUnit(Unit* victim) override void KilledUnit(Unit* victim) override
{ {
if (victim->GetTypeId() == TYPEID_PLAYER) if (victim->GetTypeId() == TYPEID_PLAYER)
{
ChaseNewVictim(); ChaseNewVictim();
} }
}
void ChaseNewVictim() void ChaseNewVictim()
{ {
@@ -127,21 +118,41 @@ public:
me->RemoveAurasDueToSpell(SPELL_FULL_SPEED); me->RemoveAurasDueToSpell(SPELL_FULL_SPEED);
me->RemoveAurasDueToSpell(SPELL_GATHERING_SPEED); me->RemoveAurasDueToSpell(SPELL_GATHERING_SPEED);
events.ScheduleEvent(EVENT_GATHERING_SPEED, 9000); events.ScheduleEvent(EVENT_GATHERING_SPEED, 9s);
events.ScheduleEvent(EVENT_FULL_SPEED, 60000); events.ScheduleEvent(EVENT_FULL_SPEED, 60s);
if (Unit* victim = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true)) if (Unit* victim = SelectTarget(SelectTargetMethod::Random, 0, 0.f, true))
{ {
DoResetThreat(); DoResetThreat();
AttackStart(victim); AttackStart(victim);
me->AddThreat(victim, 1000000.f);
Talk(EMOTE_TARGET, victim); Talk(EMOTE_TARGET, victim);
} }
} }
void ManageRespawn(ObjectGuid EggGUID) void SetGUID(ObjectGuid const guid, int32 /*type*/) override
{ {
ChaseNewVictim(); _eggs.push_back(guid);
Eggs.push_back(EggGUID); events.ScheduleEvent(EVENT_RESPAWN_EGG, 120s);
events.ScheduleEvent(EVENT_RESPAWN_EGG, 100000); }
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (attacker->GetEntry() != NPC_BURU_EGG && _phase == PHASE_EGG)
{
damage = damage * 0.01f; // 99% dmg resist
}
if (me->HealthBelowPctDamaged(20, damage) && _phase == PHASE_EGG)
{
DoCastSelf(SPELL_FULL_SPEED, true);
ManipulateEggs(false);
me->RemoveAurasDueToSpell(SPELL_THORNS);
events.Reset();
_phase = PHASE_TRANSFORM;
DoResetThreat();
events.ScheduleEvent(EVENT_CREEPING_PLAGUE, 2s);
DoCastSelf(SPELL_BURU_TRANSFORM);
}
} }
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
@@ -157,75 +168,49 @@ public:
{ {
case EVENT_DISMEMBER: case EVENT_DISMEMBER:
DoCastVictim(SPELL_DISMEMBER); DoCastVictim(SPELL_DISMEMBER);
events.ScheduleEvent(EVENT_DISMEMBER, 5000); events.ScheduleEvent(EVENT_DISMEMBER, 5s);
break; break;
case EVENT_GATHERING_SPEED: case EVENT_GATHERING_SPEED:
DoCastSelf(SPELL_GATHERING_SPEED); DoCastSelf(SPELL_GATHERING_SPEED);
events.ScheduleEvent(EVENT_GATHERING_SPEED, 9000); events.ScheduleEvent(EVENT_GATHERING_SPEED, 9s);
break; break;
case EVENT_FULL_SPEED: case EVENT_FULL_SPEED:
DoCastSelf(SPELL_FULL_SPEED); DoCastSelf(SPELL_FULL_SPEED);
break; break;
case EVENT_CREEPING_PLAGUE: case EVENT_CREEPING_PLAGUE:
DoCastAOE(SPELL_CREEPING_PLAGUE); DoCastAOE(SPELL_CREEPING_PLAGUE);
events.ScheduleEvent(EVENT_CREEPING_PLAGUE, urand(6250, 6500)); events.ScheduleEvent(EVENT_CREEPING_PLAGUE, 6s);
break; break;
case EVENT_RESPAWN_EGG: case EVENT_RESPAWN_EGG:
if (Creature* egg = me->GetMap()->GetCreature(*Eggs.begin())) if (Creature* egg = me->GetMap()->GetCreature(*_eggs.begin()))
{
egg->Respawn(); egg->Respawn();
Eggs.pop_front();
} _eggs.pop_front();
break; break;
default: default:
break; break;
} }
} }
if (me->GetHealthPct() < 20.0f && _phase == PHASE_EGG)
{
DoCastSelf(SPELL_BURU_TRANSFORM);
DoCastSelf(SPELL_FULL_SPEED, true);
me->RemoveAurasDueToSpell(SPELL_THORNS);
events.CancelEvent(EVENT_DISMEMBER);
events.ScheduleEvent(EVENT_CREEPING_PLAGUE, 2000);
_phase = PHASE_TRANSFORM;
std::list<Creature*> RemainingEgg;
me->GetCreaturesWithEntryInRange(RemainingEgg, 100.0f, NPC_BURU_EGG);
for (std::list<Creature*>::const_iterator itr = RemainingEgg.begin(); itr != RemainingEgg.end(); ++itr)
{
Unit::Kill(me, *itr);
}
}
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
private: private:
uint8 _phase; uint8 _phase;
GuidList Eggs; GuidList _eggs;
}; };
CreatureAI* GetAI(Creature* creature) const override struct npc_buru_egg : public ScriptedAI
{ {
return GetRuinsOfAhnQirajAI<boss_buruAI>(creature); npc_buru_egg(Creature* creature) : ScriptedAI(creature)
}
};
class npc_buru_egg : public CreatureScript
{
public:
npc_buru_egg() : CreatureScript("npc_buru_egg") { }
struct npc_buru_eggAI : public ScriptedAI
{
npc_buru_eggAI(Creature* creature) : ScriptedAI(creature)
{ {
_instance = me->GetInstanceScript(); _instance = me->GetInstanceScript();
SetCombatMovement(false); SetCombatMovement(false);
me->SetReactState(REACT_PASSIVE);
} }
void EnterCombat(Unit* attacker) override void EnterCombat(Unit* attacker) override
{ {
if (Creature* buru = me->GetMap()->GetCreature(_instance->GetGuidData(DATA_BURU))) if (Creature* buru = _instance->GetCreature(DATA_BURU))
{ {
if (!buru->IsInCombat()) if (!buru->IsInCombat())
{ {
@@ -238,7 +223,7 @@ public:
{ {
if (who->GetEntry() == NPC_HATCHLING) if (who->GetEntry() == NPC_HATCHLING)
{ {
if (Creature* buru = me->GetMap()->GetCreature(_instance->GetGuidData(DATA_BURU))) if (Creature* buru = _instance->GetCreature(DATA_BURU))
{ {
if (Unit* target = buru->AI()->SelectTarget(SelectTargetMethod::Random)) if (Unit* target = buru->AI()->SelectTarget(SelectTargetMethod::Random))
{ {
@@ -248,74 +233,52 @@ public:
} }
} }
void JustDied(Unit* /*killer*/) override void JustDied(Unit* killer) override
{ {
if (Creature* buru = me->GetMap()->GetCreature(_instance->GetGuidData(DATA_BURU))) DoCastSelf(SPELL_SUMMON_HATCHLING, true);
if (killer->GetEntry() != NPC_BURU)
{ {
if (!buru->HasAura(SPELL_BURU_TRANSFORM)) if (Creature* buru = _instance->GetCreature(DATA_BURU))
{ {
DoCast(me, SPELL_EXPLODE, true); DoCastSelf(SPELL_EXPLODE);
DoCast(me, SPELL_EXPLODE_2, true); DoCastSelf(SPELL_BURU_EGG_TRIGGER, true);
DoCast(me, SPELL_BURU_EGG_TRIGGER, true); buru->CastSpell(buru, SPELL_CREATURE_SPECIAL, true);
} if (buru->GetAI())
if (boss_buru::boss_buruAI* buruAI = dynamic_cast<boss_buru::boss_buruAI*>(buru->AI())) buru->AI()->SetGUID(me->GetGUID());
{
buruAI->ManageRespawn(me->GetGUID());
} }
} }
DoCast(me, SPELL_SUMMON_HATCHLING, true);
} }
private: private:
InstanceScript* _instance; InstanceScript* _instance;
}; };
CreatureAI* GetAI(Creature* creature) const override class spell_egg_explosion : public SpellScript
{ {
return GetRuinsOfAhnQirajAI<npc_buru_eggAI>(creature); PrepareSpellScript(spell_egg_explosion);
}
};
class spell_egg_explosion : public SpellScriptLoader
{
public:
spell_egg_explosion() : SpellScriptLoader("spell_egg_explosion") { }
class spell_egg_explosion_SpellScript : public SpellScript
{
PrepareSpellScript(spell_egg_explosion_SpellScript);
void HandleAfterCast()
{
if (Creature* buru = GetCaster()->FindNearestCreature(NPC_BURU, 5.f))
{
buru->AI()->DoAction(ACTION_EXPLODE);
}
}
void HandleDummyHitTarget(SpellEffIndex /*effIndex*/) void HandleDummyHitTarget(SpellEffIndex /*effIndex*/)
{ {
if (Unit* target = GetHitUnit()) if (Unit* target = GetHitUnit())
{ {
Unit::DealDamage(GetCaster(), target, -16 * GetCaster()->GetDistance(target) + 500); int32 damage = 0;
if (target->IsPlayer())
damage = -16 * GetCaster()->GetDistance(target) + 500;
else if (target->GetEntry() == NPC_BURU && target->HasAura(SPELL_THORNS))
damage = target->GetMaxHealth() * 7.f / 100;
GetCaster()->CastCustomSpell(target, SPELL_EXPLODE_2, &damage, nullptr, nullptr, true);
} }
} }
void Register() override void Register() override
{ {
AfterCast += SpellCastFn(spell_egg_explosion_SpellScript::HandleAfterCast); OnEffectHitTarget += SpellEffectFn(spell_egg_explosion::HandleDummyHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
OnEffectHitTarget += SpellEffectFn(spell_egg_explosion_SpellScript::HandleDummyHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_egg_explosion_SpellScript();
} }
}; };
void AddSC_boss_buru() void AddSC_boss_buru()
{ {
new boss_buru(); RegisterRuinsOfAhnQirajCreatureAI(boss_buru);
new npc_buru_egg(); RegisterRuinsOfAhnQirajCreatureAI(npc_buru_egg);
new spell_egg_explosion(); RegisterSpellScript(spell_egg_explosion);
} }
@@ -23,6 +23,7 @@
ObjectData const creatureData[] = ObjectData const creatureData[] =
{ {
{ NPC_BURU, DATA_BURU },
{ NPC_KURINNAXX, DATA_KURINNAXX }, { NPC_KURINNAXX, DATA_KURINNAXX },
{ NPC_RAJAXX, DATA_RAJAXX }, { NPC_RAJAXX, DATA_RAJAXX },
{ NPC_OSSIRIAN, DATA_OSSIRIAN }, { NPC_OSSIRIAN, DATA_OSSIRIAN },