fix(Scripts/HellfireRamparts): modernise boss scripts for Hellfire Ramparts (#16250)

* first two bosses

* add vazruden+nazan

* dumb mistake fix

* remove double summon say from Omor

* new attempt at scheduling talking

* fix boolean condition for speaking

* debug

* revert debug

* initial

* diff comment
This commit is contained in:
Dan
2023-05-13 19:50:46 +02:00
committed by GitHub
parent dfa5da00b1
commit 8e28b64ccf
3 changed files with 161 additions and 170 deletions

View File

@@ -34,16 +34,7 @@ enum Spells
SPELL_SHADOW_BOLT = 30686,
SPELL_SUMMON_FIENDISH_HOUND = 30707,
SPELL_TREACHEROUS_AURA = 30695,
SPELL_DEMONIC_SHIELD = 31901,
};
enum Misc
{
EVENT_SUMMON1 = 1,
EVENT_SUMMON2 = 2,
EVENT_TREACHEROUS_AURA = 3,
EVENT_DEMONIC_SHIELD = 4,
EVENT_KILL_TALK = 5
SPELL_DEMONIC_SHIELD = 31901
};
class boss_omor_the_unscarred : public CreatureScript
@@ -56,33 +47,63 @@ public:
boss_omor_the_unscarredAI(Creature* creature) : BossAI(creature, DATA_OMOR_THE_UNSCARRED)
{
SetCombatMovement(false);
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void Reset() override
{
Talk(SAY_WIPE);
BossAI::Reset();
_Reset();
_targetGUID.Clear();
ScheduleHealthCheckEvent(21, [&]{
DoCastSelf(SPELL_DEMONIC_SHIELD);
scheduler.Schedule(15s, [this](TaskContext context)
{
DoCastSelf(SPELL_DEMONIC_SHIELD);
context.Repeat(15s);
});
});
}
void JustEngagedWith(Unit* who) override
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
BossAI::JustEngagedWith(who);
_JustEngagedWith();
events.ScheduleEvent(EVENT_SUMMON1, 10000);
events.ScheduleEvent(EVENT_SUMMON2, 25000);
events.ScheduleEvent(EVENT_TREACHEROUS_AURA, 6000);
events.ScheduleEvent(EVENT_DEMONIC_SHIELD, 1000);
scheduler.Schedule(6s, [this](TaskContext context)
{
if (roll_chance_i(33))
{
Talk(SAY_CURSE);
}
DoCastRandomTarget(SPELL_TREACHEROUS_AURA);
context.Repeat(12s, 18s);
}).Schedule(10s, [this](TaskContext /*context*/)
{
DoCastSelf(SPELL_SUMMON_FIENDISH_HOUND);
}).Schedule(25s, [this](TaskContext context)
{
DoCastSelf(SPELL_SUMMON_FIENDISH_HOUND);
context.Repeat(15s);
});
}
void KilledUnit(Unit*) override
{
if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
if(!_hasSpoken)
{
_hasSpoken = true;
Talk(SAY_KILL);
events.ScheduleEvent(EVENT_KILL_TALK, 6000);
}
scheduler.Schedule(6s, [this](TaskContext /*context*/)
{
_hasSpoken = false;
});
}
void JustSummoned(Creature* summon) override
@@ -92,49 +113,20 @@ public:
summon->SetInCombatWithZone();
}
void JustDied(Unit* killer) override
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DIE);
BossAI::JustDied(killer);
_JustDied();
}
void UpdateAI(uint32 diff) override
void UpdateAI(uint32 /*diff*/) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_SUMMON1:
Talk(SAY_SUMMON);
me->CastSpell(me, SPELL_SUMMON_FIENDISH_HOUND, false);
break;
case EVENT_SUMMON2:
me->CastSpell(me, SPELL_SUMMON_FIENDISH_HOUND, false);
events.ScheduleEvent(EVENT_SUMMON2, 15000);
break;
case EVENT_TREACHEROUS_AURA:
if (roll_chance_i(33))
Talk(SAY_CURSE);
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
me->CastSpell(target, SPELL_TREACHEROUS_AURA, false);
events.ScheduleEvent(EVENT_TREACHEROUS_AURA, urand(12000, 18000));
break;
case EVENT_DEMONIC_SHIELD:
if (me->HealthBelowPct(21))
{
me->CastSpell(me, SPELL_DEMONIC_SHIELD, false);
events.ScheduleEvent(EVENT_DEMONIC_SHIELD, 15000);
}
else
events.ScheduleEvent(EVENT_DEMONIC_SHIELD, 1000);
break;
}
if (!me->GetVictim() || !me->isAttackReady())
return;
@@ -153,6 +145,7 @@ public:
private:
ObjectGuid _targetGUID;
bool _hasSpoken;
};
CreatureAI* GetAI(Creature* creature) const override

View File

@@ -43,18 +43,14 @@ enum Spells
enum Misc
{
ACTION_FLY_DOWN = 0,
POINT_MIDDLE = 0,
POINT_FLIGHT = 1,
POINT_FLIGHT = 1
};
EVENT_SPELL_REVENGE = 1,
EVENT_KILL_TALK = 2,
EVENT_AGGRO_TALK = 3,
EVENT_SPELL_FIREBALL = 4,
EVENT_SPELL_CONE_OF_FIRE = 5,
EVENT_SPELL_BELLOWING_ROAR = 6,
EVENT_CHANGE_POS = 7,
EVENT_RESTORE_COMBAT = 8
enum GroupPhase
{
GROUP_PHASE_1 = 0,
GROUP_PHASE_2 = 1
};
const Position NazanPos[3] =
@@ -158,10 +154,14 @@ class boss_nazan : public CreatureScript
public:
boss_nazan() : CreatureScript("boss_nazan") { }
struct boss_nazanAI : public ScriptedAI
struct boss_nazanAI : public BossAI
{
boss_nazanAI(Creature* creature) : ScriptedAI(creature)
boss_nazanAI(Creature* creature) : BossAI(creature, DATA_VAZRUDEN)
{
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void Reset() override
@@ -178,8 +178,17 @@ public:
void JustEngagedWith(Unit*) override
{
events.ScheduleEvent(EVENT_CHANGE_POS, 0);
events.ScheduleEvent(EVENT_SPELL_FIREBALL, 5000);
scheduler.CancelGroup(GROUP_PHASE_2);
scheduler.Schedule(5ms, GROUP_PHASE_1, [this](TaskContext context)
{
me->GetMotionMaster()->MovePoint(POINT_FLIGHT, NazanPos[urand(0, 2)], false);
scheduler.DelayAll(7s);
context.Repeat(30s);
}).Schedule(5s, GROUP_PHASE_1, [this](TaskContext context)
{
DoCastRandomTarget(SPELL_FIREBALL);
context.Repeat(4s, 6s);
});
}
void AttackStart(Unit* who) override
@@ -209,48 +218,37 @@ public:
me->SetCanFly(false);
me->SetDisableGravity(false);
me->SetReactState(REACT_AGGRESSIVE);
events.ScheduleEvent(EVENT_RESTORE_COMBAT, 1);
events.ScheduleEvent(EVENT_SPELL_CONE_OF_FIRE, 5000);
events.ScheduleEvent(EVENT_SPELL_FIREBALL, 6000);
scheduler.CancelGroup(GROUP_PHASE_1);
me->GetMotionMaster()->MoveChase(me->GetVictim());
scheduler.Schedule(5s, GROUP_PHASE_2, [this](TaskContext context)
{
DoCastVictim(SPELL_CONE_OF_FIRE);
context.Repeat(12s);
}).Schedule(6s, GROUP_PHASE_2, [this](TaskContext context)
{
DoCastRandomTarget(SPELL_FIREBALL);
context.Repeat(4s, 6s);
});
if (IsHeroic())
events.ScheduleEvent(EVENT_SPELL_BELLOWING_ROAR, 10000);
{
scheduler.Schedule(10s, GROUP_PHASE_2, [this](TaskContext context)
{
DoCastSelf(SPELL_BELLOWING_ROAR);
context.Repeat(30s);
});
}
}
}
void UpdateAI(uint32 diff) override
void UpdateAI(uint32 /*diff*/) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_SPELL_FIREBALL:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
me->CastSpell(target, SPELL_FIREBALL, false);
events.ScheduleEvent(EVENT_SPELL_FIREBALL, urand(4000, 6000));
break;
case EVENT_CHANGE_POS:
me->GetMotionMaster()->MovePoint(POINT_FLIGHT, NazanPos[urand(0, 2)], false);
events.DelayEvents(7000);
events.ScheduleEvent(EVENT_CHANGE_POS, 30000);
break;
case EVENT_RESTORE_COMBAT:
me->GetMotionMaster()->MoveChase(me->GetVictim());
break;
case EVENT_SPELL_CONE_OF_FIRE:
me->CastSpell(me->GetVictim(), SPELL_CONE_OF_FIRE, false);
events.ScheduleEvent(EVENT_SPELL_CONE_OF_FIRE, 12000);
break;
case EVENT_SPELL_BELLOWING_ROAR:
me->CastSpell(me, SPELL_BELLOWING_ROAR, false);
events.ScheduleEvent(EVENT_SPELL_BELLOWING_ROAR, 30000);
break;
}
if (!me->IsLevitating())
DoMeleeAttackIfReady();
}
@@ -270,9 +268,15 @@ class boss_vazruden : public CreatureScript
public:
boss_vazruden() : CreatureScript("boss_vazruden") { }
struct boss_vazrudenAI : public ScriptedAI
struct boss_vazrudenAI : public BossAI
{
boss_vazrudenAI(Creature* creature) : ScriptedAI(creature) { }
boss_vazrudenAI(Creature* creature) : BossAI(creature, DATA_VAZRUDEN)
{
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void Reset() override
{
@@ -288,17 +292,27 @@ public:
void JustEngagedWith(Unit*) override
{
events.ScheduleEvent(EVENT_AGGRO_TALK, 5000);
events.ScheduleEvent(EVENT_SPELL_REVENGE, 4000);
scheduler.Schedule(5s, [this](TaskContext /*context*/)
{
Talk(SAY_AGGRO);
}).Schedule(4s, [this](TaskContext context)
{
DoCastVictim(DUNGEON_MODE(SPELL_REVENGE, SPELL_REVENGE_H));
context.Repeat(6s);
});
}
void KilledUnit(Unit*) override
{
if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
if (!_hasSpoken)
{
_hasSpoken = true;
Talk(SAY_KILL);
events.ScheduleEvent(EVENT_KILL_TALK, 6000);
}
scheduler.Schedule(6s, [this](TaskContext /*context*/)
{
_hasSpoken = false;
});
}
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*type*/, SpellSchoolMask /*school*/) override
@@ -315,28 +329,17 @@ public:
Talk(SAY_DIE);
}
void UpdateAI(uint32 diff) override
void UpdateAI(uint32 /*diff*/) override
{
if (!UpdateVictim())
return;
events.Update(diff);
switch (events.ExecuteEvent())
{
case EVENT_AGGRO_TALK:
Talk(SAY_AGGRO);
break;
case EVENT_SPELL_REVENGE:
me->CastSpell(me->GetVictim(), DUNGEON_MODE(SPELL_REVENGE, SPELL_REVENGE_H), false);
events.ScheduleEvent(EVENT_SPELL_REVENGE, 6000);
break;
}
DoMeleeAttackIfReady();
}
private:
EventMap events;
bool _hasSpoken;
bool _nazanCalled;
};

View File

@@ -38,13 +38,7 @@ enum Spells
enum Misc
{
NPC_HELLFIRE_WATCHER = 17309,
EVENT_MORTAL_WOUND = 1,
EVENT_SURGE = 2,
EVENT_RETALIATION = 3,
EVENT_KILL_TALK = 4,
EVENT_CHECK_HEALTH = 5
NPC_HELLFIRE_WATCHER = 17309
};
class boss_watchkeeper_gargolmar : public CreatureScript
@@ -57,21 +51,53 @@ public:
boss_watchkeeper_gargolmarAI(Creature* creature) : BossAI(creature, DATA_WATCHKEEPER_GARGOLMAR)
{
_taunted = false;
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void Reset() override
{
BossAI::Reset();
_Reset();
ScheduleHealthCheckEvent(50, [&]{
Talk(SAY_HEAL);
std::list<Creature*> clist;
me->GetCreaturesWithEntryInRange(clist, 100.0f, NPC_HELLFIRE_WATCHER);
for (std::list<Creature*>::const_iterator itr = clist.begin(); itr != clist.end(); ++itr)
(*itr)->AI()->SetData(NPC_HELLFIRE_WATCHER, 0);
});
ScheduleHealthCheckEvent(20, [&]{
DoCastSelf(SPELL_RETALIATION);
scheduler.Schedule(30s, [this](TaskContext context)
{
DoCastSelf(SPELL_RETALIATION);
context.Repeat(30s);
});
});
}
void JustEngagedWith(Unit* who) override
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
BossAI::JustEngagedWith(who);
events.ScheduleEvent(EVENT_MORTAL_WOUND, 5000);
events.ScheduleEvent(EVENT_SURGE, 3000);
events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000);
events.ScheduleEvent(EVENT_RETALIATION, 1000);
_JustEngagedWith();
scheduler.Schedule(5s, [this] (TaskContext context)
{
DoCastVictim(SPELL_MORTAL_WOUND);
context.Repeat(8s);
}).Schedule(3s, [this](TaskContext context)
{
Talk(SAY_SURGE);
if(Unit* target = SelectTarget((SelectTargetMethod::MinDistance), 0))
{
me->CastSpell(target, SPELL_SURGE);
}
context.Repeat(11s);
});
}
void MoveInLineOfSight(Unit* who) override
@@ -90,68 +116,37 @@ public:
void KilledUnit(Unit*) override
{
if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
if (!_hasSpoken)
{
_hasSpoken = true;
Talk(SAY_KILL);
events.ScheduleEvent(EVENT_KILL_TALK, 6000);
}
scheduler.Schedule(6s, [this](TaskContext /*context*/)
{
_hasSpoken = false;
});
}
void JustDied(Unit* killer) override
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DIE);
BossAI::JustDied(killer);
_JustDied();
}
void UpdateAI(uint32 diff) override
void UpdateAI(uint32 /*diff*/) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_MORTAL_WOUND:
me->CastSpell(me->GetVictim(), SPELL_MORTAL_WOUND, false);
events.ScheduleEvent(EVENT_MORTAL_WOUND, 8000);
break;
case EVENT_SURGE:
Talk(SAY_SURGE);
if (Unit* target = SelectTarget(SelectTargetMethod::MinDistance, 0))
me->CastSpell(target, SPELL_SURGE, false);
events.ScheduleEvent(EVENT_SURGE, 11000);
break;
case EVENT_RETALIATION:
if (me->HealthBelowPct(20))
{
me->CastSpell(me, SPELL_RETALIATION, false);
events.ScheduleEvent(EVENT_RETALIATION, 30000);
}
else
events.ScheduleEvent(EVENT_RETALIATION, 500);
break;
case EVENT_CHECK_HEALTH:
if (me->HealthBelowPct(50))
{
Talk(SAY_HEAL);
std::list<Creature*> clist;
me->GetCreaturesWithEntryInRange(clist, 100.0f, NPC_HELLFIRE_WATCHER);
for (std::list<Creature*>::const_iterator itr = clist.begin(); itr != clist.end(); ++itr)
(*itr)->AI()->SetData(NPC_HELLFIRE_WATCHER, 0);
break;
}
events.ScheduleEvent(EVENT_CHECK_HEALTH, 500);
break;
}
DoMeleeAttackIfReady();
}
private:
bool _taunted;
bool _hasSpoken;
};
CreatureAI* GetAI(Creature* creature) const override