fix(Scripts/ShatteredHalls): Rewrite Warchief Kargath Bladefist (#16355)

This commit is contained in:
Angelo Venturini
2023-05-23 06:48:23 -03:00
committed by GitHub
parent 8e91065412
commit a56a400a13
4 changed files with 231 additions and 77 deletions

View File

@@ -17,41 +17,53 @@
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "SpellScript.h"
#include "TaskScheduler.h"
#include "shattered_halls.h"
enum Says
{
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_DEATH = 2
SAY_DEATH = 2,
SAY_EVADE = 5
};
enum Spells
{
SPELL_BLADE_DANCE = 30739,
SPELL_CHARGE = 25821,
SPELL_SPRINT = 32720
// Blade dance
SPELL_BLADE_DANCE_TARGETING = 30738,
SPELL_BLADE_DANCE_DMG = 30739,
SPELL_BLADE_DANCE_CHARGE = 30751,
// Warchief portal
SPELL_SUMMON_HEATHEN = 30737,
SPELL_SUMMON_REAVER = 30785,
SPELL_SUMMON_SHARPSHOOTER = 30786
};
enum Creatures
{
NPC_SHATTERED_ASSASSIN = 17695,
NPC_HEARTHEN_GUARD = 17621,
NPC_SHARPSHOOTER_GUARD = 17622,
NPC_REAVER_GUARD = 17623
NPC_BLADE_DANCE_TARGET = 20709
};
enum Misc
enum PortalData
{
EVENT_SPELL_CHARGE = 1,
EVENT_MOVE_TO_NEXT_POINT = 2,
EVENT_BLADE_DANCE = 3,
EVENT_FINISH_BLADE_DANCE = 4
DATA_START_FIGHT = 1,
DATA_RESET_FIGHT = 2
};
float AssassEntrance[3] = { 275.136f, -84.29f, 2.3f }; // y -8
float AssassExit[3] = { 184.233f, -84.29f, 2.3f }; // y -8
float AddsEntrance[3] = { 306.036f, -84.29f, 1.93f };
std::array<uint32, 3> const summonSpells = { SPELL_SUMMON_HEATHEN, SPELL_SUMMON_REAVER, SPELL_SUMMON_SHARPSHOOTER };
std::vector<Position> const assassinsPos =
{
{ 172.68164f, -80.65692f, 2.0834563f, 5.4279f },
{ 167.8295f, -86.55783f, 1.9949634f, 0.8118f },
{ 287.0375f, -88.17879f, 2.0663502f, 3.2490f },
{ 292.1491f, -82.25267f, 1.9973913f, 5.8568f }
};
Position const kargathRespawnPos = { 231.25f, -83.6449f, 5.02341f };
struct boss_warchief_kargath_bladefist : public BossAI
{
@@ -75,10 +87,45 @@ struct boss_warchief_kargath_bladefist : public BossAI
}
}
void JustDied(Unit* /*killer*/) override
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
}
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
{
if (summon)
{
summon->SetVisible(false);
scheduler.Schedule(20s, [summon](TaskContext /*context*/)
{
if (summon)
{
summon->Respawn(true);
summon->SetVisible(true);
}
});
}
}
void RespawnAssassins()
{
for (Position const& summonPos : assassinsPos)
me->SummonCreature(NPC_SHATTERED_ASSASSIN, summonPos);
}
void Reset() override
{
BossAI::Reset();
if (Creature* warchiefPortal = instance->GetCreature(DATA_WARCHIEF_PORTAL))
warchiefPortal->AI()->SetData(DATA_RESET_FIGHT, 0);
_danceCount = 0;
}
void JustDied(Unit* killer) override
{
Talk(SAY_DEATH);
_JustDied();
BossAI::JustDied(killer);
if (instance)
{
if (Creature* executioner = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EXECUTIONER)))
@@ -88,79 +135,58 @@ struct boss_warchief_kargath_bladefist : public BossAI
}
}
void JustEngagedWith(Unit* /*who*/) override
void JustEngagedWith(Unit* who) override
{
Talk(SAY_AGGRO);
_JustEngagedWith();
scheduler.Schedule(5s, [this](TaskContext /*context*/)
{
me->SummonCreature(NPC_SHATTERED_ASSASSIN, AssassEntrance[0], AssassEntrance[1] + 8, AssassEntrance[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
me->SummonCreature(NPC_SHATTERED_ASSASSIN, AssassEntrance[0], AssassEntrance[1] - 8, AssassEntrance[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
me->SummonCreature(NPC_SHATTERED_ASSASSIN, AssassExit[0], AssassExit[1] + 8, AssassExit[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
me->SummonCreature(NPC_SHATTERED_ASSASSIN, AssassExit[0], AssassExit[1] - 8, AssassExit[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
}).Schedule(30s, [this](TaskContext context)
{
for (uint8 i = 0; i < 2; ++i)
{
me->SummonCreature(NPC_HEARTHEN_GUARD + urand(0, 2), AddsEntrance[0], AddsEntrance[1], AddsEntrance[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
}
context.Repeat(30s);
}).Schedule(30s, [this](TaskContext context)
{
scheduler.DelayAll(10001ms);
context.Repeat(40s);
scheduler.Schedule(1ms, [this](TaskContext /*context*/)
{
float x = 210 + frand(0.0f, 35.0f);
float y = -65.0f - frand(0.0f, 35.0f);
me->GetMotionMaster()->MovePoint(1, x, y, me->GetPositionZ());
}).Schedule(10s, [this](TaskContext /*context*/)
{
//events.SetPhase(0); howToMigrate?
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveChase(me->GetVictim());
if (IsHeroic())
BossAI::JustEngagedWith(who);
if (Creature* warchiefPortal = instance->GetCreature(DATA_WARCHIEF_PORTAL))
warchiefPortal->AI()->SetData(DATA_START_FIGHT, 0);
RespawnAssassins();
scheduler
.Schedule(30s, [this](TaskContext context)
{
scheduler.Schedule(3s, [this](TaskContext context)
{
DoCastVictim(SPELL_CHARGE);
context.Repeat(30s);
});
}
});
//events.SetPhase(1); howToMigrate?
DoCastSelf(SPELL_SPRINT, true);
});
}
void JustSummoned(Creature* summon) override
{
if (summon->GetEntry() != NPC_SHATTERED_ASSASSIN)
{
summon->AI()->AttackStart(SelectTarget(SelectTargetMethod::Random, 0));
}
summons.Summon(summon);
me->SetReactState(REACT_PASSIVE);
_danceCount = 0;
DoCastAOE(SPELL_BLADE_DANCE_TARGETING);
context.Repeat(32850ms, 41350ms);
});
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
if (victim && victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
void MovementInform(uint32 type, uint32 id) override
void MovementInform(uint32 type, uint32 /*id*/) override
{
if (type != POINT_MOTION_TYPE || id != 1)
if (type != POINT_MOTION_TYPE)
return;
me->CastSpell(me, SPELL_BLADE_DANCE, true);
events.ScheduleEvent(EVENT_MOVE_TO_NEXT_POINT, 0);
if (_danceCount < 8)
{
_danceCount++;
scheduler.Schedule(100ms, [this](TaskContext /*context*/)
{
DoCastAOE(SPELL_BLADE_DANCE_TARGETING);
});
}
else
me->SetReactState(REACT_AGGRESSIVE);
}
bool IsInRoom()
{
if (me->GetExactDist2d(kargathRespawnPos) >= 42.f)
return false;
return true;
}
void UpdateAI(uint32 diff) override
{
if (me->GetPositionX() > 255 || me->GetPositionX() < 205)
if (!IsInRoom())
{
Talk(SAY_EVADE);
EnterEvadeMode();
return;
}
@@ -168,14 +194,128 @@ struct boss_warchief_kargath_bladefist : public BossAI
if (!UpdateVictim())
return;
scheduler.Update(diff);
scheduler.Update(diff, [this]
{
DoMeleeAttackIfReady();
});
}
if (!events.IsInPhase(1)) // howToMigrate?
DoMeleeAttackIfReady();
protected:
uint8 _danceCount;
};
struct npc_warchief_portal : public ScriptedAI
{
public:
npc_warchief_portal(Creature* creature) : ScriptedAI(creature) { }
void UpdateAI(uint32 diff) override
{
_scheduler.Update(diff);
}
void JustSummoned(Creature* creature) override
{
InstanceScript* instance = me->GetInstanceScript();
if (!instance)
return;
if (Creature* kargath = instance->GetCreature(DATA_KARGATH))
kargath->AI()->JustSummoned(creature);
}
void SetData(uint32 type, uint32 /*data*/) override
{
if (type == DATA_START_FIGHT)
{
_scheduler.Schedule(20600ms, [this](TaskContext context)
{
DoCastSelf(summonSpells[context.GetRepeatCounter() % 3]);
context.Repeat();
});
}
if (type == DATA_RESET_FIGHT)
{
_scheduler.CancelAll();
}
}
protected:
TaskScheduler _scheduler;
};
class spell_blade_dance_targeting : public SpellScript
{
PrepareSpellScript(spell_blade_dance_targeting);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_BLADE_DANCE_CHARGE, SPELL_BLADE_DANCE_DMG });
}
void FilterTargets(std::list<WorldObject*>& targets)
{
Unit* caster = GetCaster();
if (!caster)
return;
targets.remove_if([&](WorldObject* target) -> bool
{
float dist = caster->GetDistance2d(target);
// Do not target dummies that are too close or too far away
if (dist < 5.f || dist > 16.f)
return true;
// Do not target anything that is not a target dummy
if (target->GetEntry() != NPC_BLADE_DANCE_TARGET)
return true;
return false;
});
std::list<WorldObject*> targets2 = targets;
targets.remove_if([&](WorldObject* target) -> bool
{
if (target->SelectNearestPlayer(15.f))
return false;
return true;
});
Acore::Containers::RandomResize(targets2, 1);
if (urand(0, 2))
{
if (targets.empty())
targets = targets2;
else
Acore::Containers::RandomResize(targets, 1);
}
else
targets = targets2;
}
void HandleOnHit()
{
Unit* caster = GetCaster();
Unit* target = GetHitUnit();
if (!caster || !target)
return;
caster->CastSpell(target, SPELL_BLADE_DANCE_CHARGE, true);
caster->CastSpell(target, SPELL_BLADE_DANCE_DMG, true);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_blade_dance_targeting::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
OnHit += SpellHitFn(spell_blade_dance_targeting::HandleOnHit);
}
};
void AddSC_boss_warchief_kargath_bladefist()
{
RegisterShatteredHallsCreatureAI(boss_warchief_kargath_bladefist);
RegisterShatteredHallsCreatureAI(npc_warchief_portal);
RegisterSpellScript(spell_blade_dance_targeting);
}

View File

@@ -26,6 +26,7 @@ ObjectData const creatureData[] =
{ NPC_WARCHIEF_KARGATH , DATA_KARGATH },
{ NPC_OMROGG_LEFT_HEAD , DATA_OMROGG_LEFT_HEAD },
{ NPC_OMROGG_RIGHT_HEAD , DATA_OMROGG_RIGHT_HEAD },
{ NPC_WARCHIEF_PORTAL , DATA_WARCHIEF_PORTAL },
{ 0 , 0 }
};

View File

@@ -37,14 +37,17 @@ enum DataTypes
DATA_PRISONER_3 = 13,
DATA_EXECUTIONER = 14,
DATA_OMROGG_LEFT_HEAD = 15,
DATA_OMROGG_RIGHT_HEAD = 16
DATA_OMROGG_RIGHT_HEAD = 16,
DATA_WARCHIEF_PORTAL = 17
};
enum CreatureIds
{
NPC_GRAND_WARLOCK_NETHEKURSE = 16807,
NPC_WARCHIEF_KARGATH = 16808,
NPC_FEL_ORC_CONVERT = 17083,
// Warchief Kargath
NPC_WARCHIEF_KARGATH = 16808,
NPC_WARCHIEF_PORTAL = 17611,
// O'MROGG
NPC_OMROGG_LEFT_HEAD = 19523,