Scripts/Auchindoun: Blackheart the Inciter fully fixed now. I had way too much fun with this one.

Two points of note:
1) Spawning 5 invisible triggers with 5 distinct factions which then MC one target each? Biggest. Hack. Ever. Best part? It's blizzlike.
2) For over ten years, I thought it was spelled "Auchinodoun". It's not. It's spelled "Auchindoun". TIL.

# Conflicts:
#	sql/old/4.3.4/world/19_2017_06_18/2017_07_21_01_world.sql
This commit is contained in:
Treeston
2017-07-21 16:07:27 +02:00
committed by Ovahlord
parent af9bc15a42
commit ed6a4a4bcd

View File

@@ -15,6 +15,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PassiveAI.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "PlayerAI.h"
@@ -25,6 +26,7 @@
enum BlackheartTheInciter
{
NPC_BLACKHEART = 18667,
SPELL_INCITE_CHAOS = 33676,
SPELL_INCITE_CHAOS_B = 33684, //debuff applied to each member of party
SPELL_CHARGE = 33709,
@@ -58,29 +60,30 @@ class BlackheartCharmedPlayerAI : public SimpleCharmedPlayerAI
{
if (Unit* charmer = me->GetCharmer())
{
if (charmer->m_Controlled.size() <= 1)
return nullptr;
Unit* target = nullptr;
do
std::list<Player*> targets;
for (ThreatReference const* ref : charmer->GetThreatManager().GetUnsortedThreatList())
{
auto it = charmer->m_Controlled.begin();
std::advance(it, urand(0, charmer->m_Controlled.size() - 1));
target = *it;
} while (target == me);
return target;
if (Player* victim = ref->GetVictim()->ToPlayer())
if (me->IsValidAttackTarget(victim))
targets.push_back(victim);
}
if (targets.empty())
return nullptr;
auto it = targets.begin();
std::advance(it, urand(0, targets.size() - 1));
return *it;
}
return nullptr;
}
void OnCharmed(bool apply) override
{
SimpleCharmedPlayerAI::OnCharmed(apply);
if (apply)
if (Unit* charmer = GetCharmer())
{
// @todo hack to be removed in new combat system
charmer->SetInCombatState(false);
me->SetInCombatState(false);
}
if (Creature* blackheart = me->FindNearestCreature(NPC_BLACKHEART, 50000.0f))
{
blackheart->AI()->SetData(0, apply);
blackheart->GetThreatManager().AddThreat(me, 0.0f);
}
}
};
@@ -116,16 +119,29 @@ struct boss_blackheart_the_inciter : public BossAI
Talk(SAY_DEATH);
}
uint8 charmCount = 0;
void SetData(uint32 /*index*/, uint32 data) override
{
if (data)
++charmCount;
else
{
if (!charmCount)
EnterEvadeMode(EVADE_REASON_OTHER); // sanity check
--charmCount;
}
if (charmCount)
me->SetReactState(REACT_PASSIVE);
else
me->SetReactState(REACT_AGGRESSIVE);
}
void UpdateAI(uint32 diff) override
{
if (me->HasReactState(REACT_PASSIVE) && me->m_Controlled.empty())
me->SetReactState(REACT_AGGRESSIVE);
events.Update(diff);
if (me->HasReactState(REACT_PASSIVE) || !UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
@@ -137,7 +153,7 @@ struct boss_blackheart_the_inciter : public BossAI
{
if (me->GetThreatManager().GetThreatListSize() > 1)
{
me->SetReactState(REACT_PASSIVE);
ResetThreatList();
DoCast(me, SPELL_INCITE_CHAOS);
}
events.ScheduleEvent(EVENT_INCITE_CHAOS, 40000);
@@ -160,7 +176,36 @@ struct boss_blackheart_the_inciter : public BossAI
DoMeleeAttackIfReady();
}
};
struct boss_blackheart_the_inciter_mc_dummy : public NullCreatureAI
{
using NullCreatureAI::NullCreatureAI;
void InitializeAI() override { me->SetReactState(REACT_PASSIVE); }
static const uint32 FIRST_DUMMY = 19300, LAST_DUMMY = 19304;
void IsSummonedBy(Unit* who) override
{
me->CastSpell(who, SPELL_INCITE_CHAOS_B, true);
// ensure everyone is in combat with everyone
for (uint32 entry = FIRST_DUMMY; entry <= LAST_DUMMY; ++entry)
if (entry != me->GetEntry())
if (Creature* trigger = me->FindNearestCreature(entry, 50000.0f))
{
me->GetThreatManager().AddThreat(trigger, 0.0f);
trigger->GetThreatManager().AddThreat(who, 0.0f);
for (Unit* other : trigger->m_Controlled)
{
me->GetThreatManager().AddThreat(other, 0.0f);
other->GetThreatManager().AddThreat(who, 0.0f);
}
}
}
void UpdateAI(uint32 /*diff*/) override
{
if (me->m_Controlled.empty())
me->DespawnOrUnsummon();
}
PlayerAI* GetAIForCharmedPlayer(Player* player) override
{
return new BlackheartCharmedPlayerAI(player);
@@ -175,11 +220,16 @@ class spell_blackheart_incite_chaos : public SpellScript
return ValidateSpellInfo({ SPELL_INCITE_CHAOS_B });
}
static const uint8 NUM_INCITE_SPELLS = 5;
static const uint32 INCITE_SPELLS[NUM_INCITE_SPELLS];
uint8 i=0;
void HandleDummy(SpellEffIndex /*effIndex*/)
{
if (Unit* caster = GetCaster())
if (Unit* target = GetHitUnit())
caster->CastSpell(target, SPELL_INCITE_CHAOS_B, true);
if (Unit* target = GetHitUnit())
{
target->CastSpell((Unit*)nullptr, INCITE_SPELLS[i], true);
i = (i + 1) % NUM_INCITE_SPELLS;
}
}
void Register() override
@@ -187,9 +237,11 @@ class spell_blackheart_incite_chaos : public SpellScript
OnEffectHitTarget += SpellEffectFn(spell_blackheart_incite_chaos::HandleDummy, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
const uint32 spell_blackheart_incite_chaos::INCITE_SPELLS[spell_blackheart_incite_chaos::NUM_INCITE_SPELLS] = { 33677,33680,33681,33682,33683 };
void AddSC_boss_blackheart_the_inciter()
{
RegisterCreatureAIWithFactory(boss_blackheart_the_inciter, GetShadowLabyrinthAI);
RegisterCreatureAIWithFactory(boss_blackheart_the_inciter_mc_dummy, GetShadowLabyrinthAI);
RegisterSpellScript(spell_blackheart_incite_chaos);
}