diff options
3 files changed, 131 insertions, 81 deletions
diff --git a/sql/updates/world/master/2020_08_19_02_world_2017_07_21_00_world.sql b/sql/updates/world/master/2020_08_19_02_world_2017_07_21_00_world.sql new file mode 100644 index 00000000000..804c0ba9dcd --- /dev/null +++ b/sql/updates/world/master/2020_08_19_02_world_2017_07_21_00_world.sql @@ -0,0 +1,3 @@ +-- +DELETE FROM `spell_script_names` WHERE `scriptname`="spell_blackheart_incite_chaos"; +INSERT INTO `spell_script_names` (`spell_id`,`scriptname`) VALUES (33676,"spell_blackheart_incite_chaos"); diff --git a/src/server/game/AI/PlayerAI/PlayerAI.cpp b/src/server/game/AI/PlayerAI/PlayerAI.cpp index 0f99211a84b..a5209c68680 100644 --- a/src/server/game/AI/PlayerAI/PlayerAI.cpp +++ b/src/server/game/AI/PlayerAI/PlayerAI.cpp @@ -1219,7 +1219,7 @@ void SimpleCharmedPlayerAI::UpdateAI(const uint32 diff) if (charmer->IsEngaged()) { Unit* target = me->GetVictim(); - if (!target || !charmer->IsValidAttackTarget(target) || target->HasBreakableByDamageCrowdControlAura()) + if (!target || !charmer->IsValidAttackTarget(target) || !me->IsValidAttackTarget(target) || target->HasBreakableByDamageCrowdControlAura()) { target = SelectAttackTarget(); if (!target) diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp index f7ece3c01e1..a7305c6528c 100644 --- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp @@ -15,16 +15,12 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* -Name: Boss_Blackheart_the_Inciter -%Complete: 75 -Comment: Incite Chaos not functional since core lacks Mind Control support -Category: Auchindoun, Shadow Labyrinth -*/ - -#include "ScriptMgr.h" #include "ObjectAccessor.h" +#include "Player.h" +#include "PlayerAI.h" +#include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "SpellScript.h" #include "shadow_labyrinth.h" enum BlackheartTheInciter @@ -55,94 +51,145 @@ enum Events EVENT_WAR_STOMP = 3 }; -class boss_blackheart_the_inciter : public CreatureScript +class BlackheartCharmedPlayerAI : public SimpleCharmedPlayerAI { - public: - boss_blackheart_the_inciter() : CreatureScript("boss_blackheart_the_inciter") { } - - struct boss_blackheart_the_inciterAI : public BossAI + using SimpleCharmedPlayerAI::SimpleCharmedPlayerAI; + Unit* SelectAttackTarget() const override + { + if (Unit* charmer = me->GetCharmer()) { - boss_blackheart_the_inciterAI(Creature* creature) : BossAI(creature, DATA_BLACKHEART_THE_INCITER) { } - - void Reset() override + if (charmer->m_Controlled.size() <= 1) + return nullptr; + Unit* target = nullptr; + do { - _Reset(); - } - - void EnterCombat(Unit* /*who*/) override - { - _EnterCombat(); - events.ScheduleEvent(EVENT_INCITE_CHAOS, 20000); - events.ScheduleEvent(EVENT_CHARGE_ATTACK, 5000); - events.ScheduleEvent(EVENT_WAR_STOMP, 15000); - - Talk(SAY_AGGRO); - } - - void KilledUnit(Unit* who) override - { - if (who->GetTypeId() == TYPEID_PLAYER) - Talk(SAY_SLAY); - } - - void JustDied(Unit* /*killer*/) override + auto it = charmer->m_Controlled.begin(); + std::advance(it, urand(0, charmer->m_Controlled.size() - 1)); + target = *it; + } while (target == me); + return target; + } + return nullptr; + } + void OnCharmed(bool apply) override + { + SimpleCharmedPlayerAI::OnCharmed(apply); + if (apply) + if (Unit* charmer = GetCharmer()) { - _JustDied(); - Talk(SAY_DEATH); + // @todo hack to be removed in new combat system + charmer->SetInCombatState(false); + me->SetInCombatState(false); } + } +}; - void UpdateAI(uint32 diff) override +struct boss_blackheart_the_inciter : public BossAI +{ + boss_blackheart_the_inciter(Creature* creature) : BossAI(creature, DATA_BLACKHEART_THE_INCITER) { } + + void Reset() override + { + me->SetReactState(REACT_AGGRESSIVE); + _Reset(); + } + + void EnterCombat(Unit* /*who*/) override + { + _EnterCombat(); + events.ScheduleEvent(EVENT_INCITE_CHAOS, 20000); + events.ScheduleEvent(EVENT_CHARGE_ATTACK, 5000); + events.ScheduleEvent(EVENT_WAR_STOMP, 15000); + + Talk(SAY_AGGRO); + } + + void KilledUnit(Unit* who) override + { + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } + + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + Talk(SAY_DEATH); + } + + void UpdateAI(uint32 diff) override + { + if (me->HasReactState(REACT_PASSIVE) && me->m_Controlled.empty()) + me->SetReactState(REACT_AGGRESSIVE); + + if (me->HasReactState(REACT_PASSIVE) || !UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + case EVENT_INCITE_CHAOS: { - switch (eventId) + if (me->GetThreatManager().GetThreatListSize() > 1) { - case EVENT_INCITE_CHAOS: - { - DoCast(me, SPELL_INCITE_CHAOS); - - for (ThreatReference const* ref : me->GetThreatManager().GetUnsortedThreatList()) - if (ref->GetVictim()->GetTypeId() == TYPEID_PLAYER) - me->CastSpell(ref->GetVictim(), SPELL_INCITE_CHAOS_B, true); - - ResetThreatList(); - events.ScheduleEvent(EVENT_INCITE_CHAOS, 40000); - break; - } - case EVENT_CHARGE_ATTACK: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_CHARGE); - events.ScheduleEvent(EVENT_CHARGE, urand(15000, 25000)); - break; - case EVENT_WAR_STOMP: - DoCast(me, SPELL_WAR_STOMP); - events.ScheduleEvent(EVENT_WAR_STOMP, urand(18000, 24000)); - break; + me->SetReactState(REACT_PASSIVE); + DoCast(me, SPELL_INCITE_CHAOS); } - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + events.ScheduleEvent(EVENT_INCITE_CHAOS, 40000); + break; } - - DoMeleeAttackIfReady(); + case EVENT_CHARGE_ATTACK: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_CHARGE); + events.ScheduleEvent(EVENT_CHARGE, urand(15000, 25000)); + break; + case EVENT_WAR_STOMP: + DoCast(me, SPELL_WAR_STOMP); + events.ScheduleEvent(EVENT_WAR_STOMP, urand(18000, 24000)); + break; } - }; - CreatureAI* GetAI(Creature* creature) const override - { - return GetShadowLabyrinthAI<boss_blackheart_the_inciterAI>(creature); + if (me->HasReactState(REACT_PASSIVE) || me->HasUnitState(UNIT_STATE_CASTING)) + return; } + + DoMeleeAttackIfReady(); + } + + PlayerAI* GetAIForCharmedPlayer(Player* player) override + { + return new BlackheartCharmedPlayerAI(player); + } +}; + +class spell_blackheart_incite_chaos : public SpellScript +{ + PrepareSpellScript(spell_blackheart_incite_chaos); + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_INCITE_CHAOS_B }); + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + if (Unit* caster = GetCaster()) + if (Unit* target = GetHitUnit()) + caster->CastSpell(target, SPELL_INCITE_CHAOS_B, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_blackheart_incite_chaos::HandleDummy, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } }; void AddSC_boss_blackheart_the_inciter() { - new boss_blackheart_the_inciter(); + RegisterCreatureAIWithFactory(boss_blackheart_the_inciter, GetShadowLabyrinthAI); + RegisterSpellScript(spell_blackheart_incite_chaos); } |