fix(Core/Scripts): Rewrite Hungarfen (#14426)

This commit is contained in:
Angelo Venturini
2023-01-02 20:43:42 -03:00
committed by GitHub
parent 9e18b86311
commit b7e002ebae
7 changed files with 376 additions and 181 deletions

View File

@@ -35,9 +35,9 @@ enum eBlackStalker
ACTION_MOVE_TO_PLATFORM = 1
};
struct boss_ghazan : public ScriptedAI
struct boss_ghazan : public BossAI
{
boss_ghazan(Creature* creature) : ScriptedAI(creature)
boss_ghazan(Creature* creature) : BossAI(creature, DATA_GHAZAN)
{
}
@@ -50,19 +50,22 @@ struct boss_ghazan : public ScriptedAI
void Reset() override
{
events.Reset();
_enraged = false;
if (!_reachedPlatform)
{
_movedToPlatform = false;
}
BossAI::Reset();
}
void EnterCombat(Unit*) override
void EnterCombat(Unit* who) override
{
events.ScheduleEvent(EVENT_ACID_BREATH, 3s);
events.ScheduleEvent(EVENT_ACID_SPIT, 1s);
events.ScheduleEvent(EVENT_TAIL_SWEEP, DUNGEON_MODE<Milliseconds>(5900ms, 10s));
BossAI::EnterCombat(who);
}
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*type*/, SpellSchoolMask /*school*/) override
@@ -106,6 +109,8 @@ struct boss_ghazan : public ScriptedAI
{
me->GetMotionMaster()->MoveRandom(12.f);
}
BossAI::JustReachedHome();
}
void UpdateAI(uint32 diff) override
@@ -164,7 +169,7 @@ public:
{
if (InstanceScript* instance = player->GetInstanceScript())
{
if (Creature* ghazan = ObjectAccessor::GetCreature(*player, instance->GetGuidData(NPC_GHAZAN)))
if (Creature* ghazan = instance->GetCreature(DATA_GHAZAN))
{
ghazan->AI()->DoAction(ACTION_MOVE_TO_PLATFORM);
return true;

View File

@@ -0,0 +1,197 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Player.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "SpellScript.h"
#include "TaskScheduler.h"
#include "the_underbog.h"
enum Spells
{
// Hungarfen
SPELL_SPAWN_MUSHROOMS = 31692,
SPELL_DESPAWN_MUSHROOMS = 34874,
SPELL_FOUL_SPORES = 31673,
SPELL_ACID_GEYSER = 38739,
// Underbog Mushroom
SPELL_SHRINK = 31691,
SPELL_GROW = 31698,
SPELL_SPORE_CLOUD = 34168
};
enum Misc
{
MAX_GROW_REPEAT = 9,
EMOTE_ROARS = 0
};
struct boss_hungarfen : public BossAI
{
boss_hungarfen(Creature* creature) : BossAI(creature, DATA_HUNGARFEN), _foul_spores(false) { }
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (me->HealthBelowPctDamaged(20, damage) && !_foul_spores)
{
_foul_spores = true;
me->AddUnitState(UNIT_STATE_ROOT);
Talk(EMOTE_ROARS);
DoCastSelf(SPELL_FOUL_SPORES);
_scheduler.DelayAll(11s);
_scheduler.Schedule(11s, [this](TaskContext /*context*/)
{
me->ClearUnitState(UNIT_STATE_ROOT);
});
}
}
void Reset() override
{
BossAI::Reset();
_foul_spores = false;
_scheduler.CancelAll();
DoCastAOE(SPELL_DESPAWN_MUSHROOMS, true);
}
void EnterCombat(Unit* who) override
{
BossAI::EnterCombat(who);
_scheduler.Schedule(IsHeroic() ? randtime(2400ms, 3600ms) : 10s, [this](TaskContext context)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0, true))
{
target->CastSpell(target, SPELL_SPAWN_MUSHROOMS, true);
}
context.Repeat();
});
if (IsHeroic())
{
_scheduler.Schedule(6s, [this](TaskContext context)
{
DoCastAOE(SPELL_ACID_GEYSER);
context.Repeat(8500ms, 11s);
});
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
_scheduler.Update(diff, [this]
{
DoMeleeAttackIfReady();
});
}
private:
TaskScheduler _scheduler;
bool _foul_spores;
};
struct npc_underbog_mushroom : public ScriptedAI
{
npc_underbog_mushroom(Creature* creature) : ScriptedAI(creature) { }
void InitializeAI() override
{
DoCastSelf(SPELL_SHRINK, true);
_scheduler.Schedule(2s, [this](TaskContext context)
{
DoCastSelf(SPELL_GROW, true);
if (context.GetRepeatCounter() == MAX_GROW_REPEAT)
{
DoCastSelf(SPELL_SPORE_CLOUD);
context.Schedule(4s, [this](TaskContext /*context*/)
{
me->RemoveAurasDueToSpell(SPELL_GROW);
me->DespawnOrUnsummon(2000);
});
}
else
context.Repeat();
});
}
void UpdateAI(uint32 diff) override
{
_scheduler.Update(diff);
}
protected:
TaskScheduler _scheduler;
};
class spell_spore_cloud : public AuraScript
{
PrepareAuraScript(spell_spore_cloud);
void HandlePeriodic(AuraEffect const* /*aurEff*/)
{
PreventDefaultAction();
if (Unit* caster = GetCaster())
{
if (InstanceScript* instance = caster->GetInstanceScript())
{
if (Creature* hungarfen = instance->GetCreature(DATA_HUNGARFEN))
caster->CastSpell((Unit*)nullptr, GetSpellInfo()->Effects[EFFECT_0].TriggerSpell, true, nullptr, nullptr, hungarfen->GetGUID());
}
}
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_spore_cloud::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
class spell_despawn_underbog_mushrooms : public SpellScript
{
PrepareSpellScript(spell_despawn_underbog_mushrooms);
void HandleScript(SpellEffIndex /*effIndex*/)
{
if (Unit* target = GetHitUnit())
if (Creature* cTarget = target->ToCreature())
if (cTarget->GetEntry() == NPC_UNDERBOG_MUSHROOM)
cTarget->DespawnOrUnsummon();
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_despawn_underbog_mushrooms::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
void AddSC_boss_hungarfen()
{
RegisterUnderbogCreatureAI(boss_hungarfen);
RegisterUnderbogCreatureAI(npc_underbog_mushroom);
RegisterSpellScript(spell_spore_cloud);
RegisterSpellScript(spell_despawn_underbog_mushrooms);
}

View File

@@ -15,13 +15,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* ScriptData
SDName: Boss_the_black_stalker
SD%Complete: 95
SDComment: Timers may be incorrect
SDCategory: Coilfang Resevoir, Underbog
EndScriptData */
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "SpellScript.h"
@@ -48,173 +41,147 @@ enum eBlackStalker
ENTRY_SPORE_STRIDER = 22299
};
class boss_the_black_stalker : public CreatureScript
struct boss_the_black_stalker : public BossAI
{
public:
boss_the_black_stalker() : CreatureScript("boss_the_black_stalker") { }
CreatureAI* GetAI(Creature* creature) const override
boss_the_black_stalker(Creature* creature) : BossAI(creature, DATA_BLACK_STALKER)
{
return GetTheUnderbogAI<boss_the_black_stalkerAI>(creature);
}
struct boss_the_black_stalkerAI : public ScriptedAI
void Reset() override
{
boss_the_black_stalkerAI(Creature* creature) : ScriptedAI(creature), summons(me)
{
}
lTarget.Clear();
BossAI::Reset();
}
EventMap events;
SummonList summons;
ObjectGuid lTarget;
void EnterCombat(Unit* who) override
{
events.ScheduleEvent(EVENT_LEVITATE, 12000);
events.ScheduleEvent(EVENT_SPELL_CHAIN, 6000);
events.ScheduleEvent(EVENT_SPELL_STATIC, 10000);
events.ScheduleEvent(EVENT_CHECK, 5000);
if (IsHeroic())
events.ScheduleEvent(EVENT_SPELL_SPORES, urand(10000, 15000));
void Reset() override
{
events.Reset();
summons.DespawnAll();
lTarget.Clear();
}
BossAI::EnterCombat(who);
}
void EnterCombat(Unit*) override
{
events.ScheduleEvent(EVENT_LEVITATE, 12000);
events.ScheduleEvent(EVENT_SPELL_CHAIN, 6000);
events.ScheduleEvent(EVENT_SPELL_STATIC, 10000);
events.ScheduleEvent(EVENT_CHECK, 5000);
if (IsHeroic())
events.ScheduleEvent(EVENT_SPELL_SPORES, urand(10000, 15000));
}
void JustSummoned(Creature* summon) override
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1))
summon->AI()->AttackStart(target);
else if (me->GetVictim())
summon->AI()->AttackStart(me->GetVictim());
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1))
summon->AI()->AttackStart(target);
else if (me->GetVictim())
summon->AI()->AttackStart(me->GetVictim());
}
BossAI::JustSummoned(summon);
}
void SummonedCreatureDies(Creature* summon, Unit*) override
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
{
summons.Despawn(summon);
for (uint8 i = 0; i < 3; ++i)
me->CastSpell(me, SPELL_SUMMON_SPORE_STRIDER, false);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
switch (events.ExecuteEvent())
{
summons.Despawn(summon);
for (uint8 i = 0; i < 3; ++i)
case EVENT_CHECK:
float x, y, z, o;
me->GetHomePosition(x, y, z, o);
if (!me->IsWithinDist3d(x, y, z, 60))
{
EnterEvadeMode();
return;
}
events.RepeatEvent(5000);
break;
case EVENT_SPELL_SPORES:
me->CastSpell(me, SPELL_SUMMON_SPORE_STRIDER, false);
}
void JustDied(Unit*) override
{
summons.DespawnAll();
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
switch (events.ExecuteEvent())
{
case EVENT_CHECK:
float x, y, z, o;
me->GetHomePosition(x, y, z, o);
if (!me->IsWithinDist3d(x, y, z, 60))
events.RepeatEvent(urand(10000, 15000));
break;
case EVENT_SPELL_CHAIN:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
me->CastSpell(target, SPELL_CHAIN_LIGHTNING, false);
events.DelayEvents(3000);
events.RepeatEvent(9000);
break;
case EVENT_SPELL_STATIC:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 30, true))
me->CastSpell(target, SPELL_STATIC_CHARGE, false);
events.RepeatEvent(10000);
break;
case EVENT_LEVITATE:
events.RepeatEvent(15000);
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1))
{
me->CastSpell(target, SPELL_LEVITATE, false);
lTarget = target->GetGUID();
events.DelayEvents(5000);
events.ScheduleEvent(EVENT_LEVITATE_TARGET_1, 2000);
}
break;
case EVENT_LEVITATE_TARGET_1:
if (Unit* target = ObjectAccessor::GetUnit(*me, lTarget))
{
if (!target->HasAura(SPELL_LEVITATE))
lTarget.Clear();
else
{
EnterEvadeMode();
return;
target->CastSpell(target, SPELL_MAGNETIC_PULL, true);
events.ScheduleEvent(EVENT_LEVITATE_TARGET_2, 1500);
}
events.RepeatEvent(5000);
break;
case EVENT_SPELL_SPORES:
me->CastSpell(me, SPELL_SUMMON_SPORE_STRIDER, false);
events.RepeatEvent(urand(10000, 15000));
break;
case EVENT_SPELL_CHAIN:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
me->CastSpell(target, SPELL_CHAIN_LIGHTNING, false);
events.DelayEvents(3000);
events.RepeatEvent(9000);
break;
case EVENT_SPELL_STATIC:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 30, true))
me->CastSpell(target, SPELL_STATIC_CHARGE, false);
events.RepeatEvent(10000);
break;
case EVENT_LEVITATE:
events.RepeatEvent(15000);
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1))
}
break;
case EVENT_LEVITATE_TARGET_2:
if (Unit* target = ObjectAccessor::GetUnit(*me, lTarget))
{
if (!target->HasAura(SPELL_LEVITATE))
lTarget.Clear();
else
{
me->CastSpell(target, SPELL_LEVITATE, false);
lTarget = target->GetGUID();
events.DelayEvents(5000);
events.ScheduleEvent(EVENT_LEVITATE_TARGET_1, 2000);
target->AddAura(SPELL_SUSPENSION, target);
lTarget.Clear();
}
break;
case EVENT_LEVITATE_TARGET_1:
if (Unit* target = ObjectAccessor::GetUnit(*me, lTarget))
{
if (!target->HasAura(SPELL_LEVITATE))
lTarget.Clear();
else
{
target->CastSpell(target, SPELL_MAGNETIC_PULL, true);
events.ScheduleEvent(EVENT_LEVITATE_TARGET_2, 1500);
}
}
break;
case EVENT_LEVITATE_TARGET_2:
if (Unit* target = ObjectAccessor::GetUnit(*me, lTarget))
{
if (!target->HasAura(SPELL_LEVITATE))
lTarget.Clear();
else
{
target->AddAura(SPELL_SUSPENSION, target);
lTarget.Clear();
}
}
break;
}
break;
}
DoMeleeAttackIfReady();
}
};
DoMeleeAttackIfReady();
}
private:
ObjectGuid lTarget;
};
class spell_gen_allergies : public SpellScriptLoader
class spell_gen_allergies : public AuraScript
{
public:
spell_gen_allergies() : SpellScriptLoader("spell_gen_allergies") { }
PrepareAuraScript(spell_gen_allergies);
class spell_gen_allergies_AuraScript : public AuraScript
void CalcPeriodic(AuraEffect const* /*effect*/, bool& isPeriodic, int32& amplitude)
{
PrepareAuraScript(spell_gen_allergies_AuraScript);
isPeriodic = true;
amplitude = urand(10 * IN_MILLISECONDS, 200 * IN_MILLISECONDS);
}
void CalcPeriodic(AuraEffect const* /*effect*/, bool& isPeriodic, int32& amplitude)
{
isPeriodic = true;
amplitude = urand(10 * IN_MILLISECONDS, 200 * IN_MILLISECONDS);
}
void Update(AuraEffect* /*effect*/)
{
SetDuration(0);
}
void Register() override
{
DoEffectCalcPeriodic += AuraEffectCalcPeriodicFn(spell_gen_allergies_AuraScript::CalcPeriodic, EFFECT_0, SPELL_AURA_DUMMY);
OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_gen_allergies_AuraScript::Update, EFFECT_0, SPELL_AURA_DUMMY);
}
};
AuraScript* GetAuraScript() const override
void Update(AuraEffect* /*effect*/)
{
return new spell_gen_allergies_AuraScript();
SetDuration(0);
}
void Register() override
{
DoEffectCalcPeriodic += AuraEffectCalcPeriodicFn(spell_gen_allergies::CalcPeriodic, EFFECT_0, SPELL_AURA_DUMMY);
OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_gen_allergies::Update, EFFECT_0, SPELL_AURA_DUMMY);
}
};
void AddSC_boss_the_black_stalker()
{
new boss_the_black_stalker();
new spell_gen_allergies();
RegisterUnderbogCreatureAI(boss_the_black_stalker);
RegisterSpellScript(spell_gen_allergies);
}

View File

@@ -20,6 +20,12 @@
#include "ScriptMgr.h"
#include "the_underbog.h"
ObjectData const creatureData[] =
{
{ NPC_HUNGARFEN, DATA_HUNGARFEN },
{ NPC_GHAZAN, DATA_GHAZAN }
};
class instance_the_underbog : public InstanceMapScript
{
public:
@@ -34,35 +40,11 @@ public:
{
instance_the_underbog_InstanceMapScript(Map* map) : InstanceScript(map) { }
void OnCreatureCreate(Creature* creature) override
void Initialize() override
{
InstanceScript::OnCreatureCreate(creature);
switch (creature->GetEntry())
{
case NPC_GHAZAN:
_ghazanGUID = creature->GetGUID();
break;
default:
break;
}
SetBossNumber(MAX_ENCOUNTERS);
LoadObjectData(creatureData, nullptr);
}
ObjectGuid GetGuidData(uint32 type) const override
{
switch (type)
{
case NPC_GHAZAN:
return _ghazanGUID;
default:
break;
}
return ObjectGuid::Empty;
}
private:
ObjectGuid _ghazanGUID;
};
};

View File

@@ -22,9 +22,21 @@
#define TheUnderbogScriptName "instance_the_underbog"
enum Data
{
DATA_HUNGARFEN = 0,
DATA_GHAZAN = 1,
DATA_MUSELEK = 2,
DATA_BLACK_STALKER = 3,
MAX_ENCOUNTERS = 4
};
enum NPCs
{
NPC_GHAZAN = 18105
NPC_HUNGARFEN = 17770,
NPC_UNDERBOG_MUSHROOM = 17990,
NPC_GHAZAN = 18105
};
template <class AI, class T>

View File

@@ -50,8 +50,9 @@ void AddSC_boss_hydromancer_thespia(); //CR Steam Vault
void AddSC_boss_mekgineer_steamrigger();
void AddSC_boss_warlord_kalithresh();
void AddSC_instance_steam_vault();
void AddSC_boss_the_black_stalker(); //CR Underbog
void AddSC_boss_hungarfen(); //CR Underbog
void AddSC_boss_ghazan();
void AddSC_boss_the_black_stalker();
void AddSC_instance_the_underbog();
void AddSC_boss_ahune();
void AddSC_instance_the_slave_pens();
@@ -144,8 +145,9 @@ void AddOutlandScripts()
AddSC_boss_mekgineer_steamrigger();
AddSC_boss_warlord_kalithresh();
AddSC_instance_steam_vault();
AddSC_boss_the_black_stalker(); //CR Underbog
AddSC_boss_hungarfen(); //CR Underbog
AddSC_boss_ghazan();
AddSC_boss_the_black_stalker();
AddSC_instance_the_underbog();
AddSC_boss_ahune();
AddSC_instance_the_slave_pens();