diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp index 638c67c3a..fa19acaeb 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp @@ -577,6 +577,7 @@ void BossAI::_Reset() events.Reset(); scheduler.CancelAll(); summons.DespawnAll(); + _healthCheckEvents.clear(); if (instance) instance->SetBossState(_bossId, NOT_STARTED); } @@ -586,6 +587,7 @@ void BossAI::_JustDied() events.Reset(); scheduler.CancelAll(); summons.DespawnAll(); + _healthCheckEvents.clear(); if (instance) { instance->SetBossState(_bossId, DONE); @@ -667,6 +669,39 @@ void BossAI::UpdateAI(uint32 diff) DoMeleeAttackIfReady(); } +void BossAI::DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) +{ + if (!_healthCheckEvents.empty()) + { + _healthCheckEvents.remove_if([&](HealthCheckEventData data) -> bool + { + return _ProccessHealthCheckEvent(data._healthPct, damage, data._exec); + }); + } +} + +/** + * @brief Executes a function once the creature reaches the defined health point percent. + * + * @param healthPct The health percent at which the code will be executed. + * @param exec The fuction to be executed. + */ +void BossAI::ScheduleHealthCheckEvent(uint32 healthPct, std::function exec) +{ + _healthCheckEvents.push_back(HealthCheckEventData(healthPct, exec)); +}; + +bool BossAI::_ProccessHealthCheckEvent(uint8 healthPct, uint32 damage, std::function exec) const +{ + if (me->HealthBelowPctDamaged(healthPct, damage)) + { + exec(); + return true; + } + + return false; +} + // WorldBossAI - for non-instanced bosses WorldBossAI::WorldBossAI(Creature* creature) : diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h index f846a4367..4778c2215 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h @@ -430,6 +430,14 @@ private: bool _isHeroic; }; +struct HealthCheckEventData +{ + HealthCheckEventData(uint8 healthPct, std::function exec) : _healthPct(healthPct), _exec(exec) { }; + + uint8 _healthPct; + std::function _exec; +}; + class BossAI : public ScriptedAI { public: @@ -440,12 +448,15 @@ public: bool CanRespawn() override; + void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask) override; void JustSummoned(Creature* summon) override; void SummonedCreatureDespawn(Creature* summon) override; void SummonedCreatureDespawnAll() override; void UpdateAI(uint32 diff) override; + void ScheduleHealthCheckEvent(uint32 healthPct, std::function exec); + // Hook used to execute events scheduled into EventMap without the need // to override UpdateAI // note: You must re-schedule the event within this method if the event @@ -464,6 +475,7 @@ protected: void _JustEngagedWith(); void _JustDied(); void _JustReachedHome() { me->setActive(false); } + [[nodiscard]] bool _ProccessHealthCheckEvent(uint8 healthPct, uint32 damage, std::function exec) const; void TeleportCheaters(); @@ -473,6 +485,7 @@ protected: private: uint32 const _bossId; + std::list _healthCheckEvents; }; class WorldBossAI : public ScriptedAI diff --git a/src/server/scripts/Outland/TempestKeep/botanica/boss_thorngrin_the_tender.cpp b/src/server/scripts/Outland/TempestKeep/botanica/boss_thorngrin_the_tender.cpp index dee13b043..8a4551bf4 100644 --- a/src/server/scripts/Outland/TempestKeep/botanica/boss_thorngrin_the_tender.cpp +++ b/src/server/scripts/Outland/TempestKeep/botanica/boss_thorngrin_the_tender.cpp @@ -44,8 +44,6 @@ enum Events EVENT_SACRIFICE = 1, EVENT_HELLFIRE = 2, EVENT_ENRAGE = 3, - EVENT_HEALTH_CHECK_50 = 4, - EVENT_HEALTH_CHECK_20 = 5 }; class boss_thorngrin_the_tender : public CreatureScript @@ -64,6 +62,12 @@ public: void Reset() override { _Reset(); + ScheduleHealthCheckEvent(20, [&]() { + Talk(SAY_20_PERCENT_HP); + }); + ScheduleHealthCheckEvent(50, [&]() { + Talk(SAY_50_PERCENT_HP); + }); } void MoveInLineOfSight(Unit* who) override @@ -83,8 +87,6 @@ public: events.ScheduleEvent(EVENT_SACRIFICE, 6000); events.ScheduleEvent(EVENT_HELLFIRE, 18000); events.ScheduleEvent(EVENT_ENRAGE, 15000); - events.ScheduleEvent(EVENT_HEALTH_CHECK_50, 500); - events.ScheduleEvent(EVENT_HEALTH_CHECK_20, 500); } void KilledUnit(Unit* victim) override @@ -129,22 +131,6 @@ public: me->CastSpell(me, SPELL_ENRAGE, false); events.ScheduleEvent(EVENT_ENRAGE, 30000); break; - case EVENT_HEALTH_CHECK_50: - if (me->HealthBelowPct(50)) - { - Talk(SAY_50_PERCENT_HP); - break; - } - events.ScheduleEvent(EVENT_HEALTH_CHECK_50, 500); - break; - case EVENT_HEALTH_CHECK_20: - if (me->HealthBelowPct(20)) - { - Talk(SAY_20_PERCENT_HP); - break; - } - events.ScheduleEvent(EVENT_HEALTH_CHECK_20, 500); - break; } DoMeleeAttackIfReady();