mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-15 18:10:26 +00:00
fix(Core/ZulGurub): Mandokir charge and chained spirits (#12072)
* fix(Core/ZulGurub): Mandokir charge and chained spirits * build * properly script threatening gaze * refactor vilebranch speaker script * remove useless trigger spell for Frightening Shout * blank spaces * build... * sadly you can cheese threatening gaze * revert threatening gaze part * style * charge should target the farthest one * revert last thing of threatening gaze * mod charge
This commit is contained in:
@@ -47,6 +47,7 @@ enum Spells
|
||||
SPELL_LEVEL_UP = 24312,
|
||||
SPELL_EXECUTE = 7160,
|
||||
SPELL_MANDOKIR_CLEAVE = 20691,
|
||||
SPELL_SUMMON_PLAYER = 25104,
|
||||
|
||||
SPELL_REVIVE = 24341 // chained spirit
|
||||
};
|
||||
@@ -63,8 +64,7 @@ enum Events
|
||||
EVENT_WATCH_PLAYER = 8,
|
||||
EVENT_CHARGE_PLAYER = 9,
|
||||
EVENT_EXECUTE = 10,
|
||||
EVENT_FRIGHTENING_SHOUT = 11,
|
||||
EVENT_CLEAVE = 12
|
||||
EVENT_CLEAVE = 11
|
||||
};
|
||||
|
||||
enum Action
|
||||
@@ -113,6 +113,32 @@ Position const PosMandokir[2] =
|
||||
{ -12197.86f, -1949.392f, 130.2745f, 0.0f }
|
||||
};
|
||||
|
||||
void RevivePlayer(Unit* victim, ObjectGuid& reviveGUID)
|
||||
{
|
||||
std::list<Creature*> chainedSpirits;
|
||||
GetCreatureListWithEntryInGrid(chainedSpirits, victim, NPC_CHAINED_SPIRIT, 200.f);
|
||||
if (chainedSpirits.empty())
|
||||
return;
|
||||
|
||||
// Sort the list by distance to the victim.
|
||||
chainedSpirits.sort([victim](Creature const* c1, Creature const* c2)
|
||||
{
|
||||
return c1->GetDistance2d(victim) < c2->GetDistance2d(victim);
|
||||
});
|
||||
|
||||
// Now we have to check if the spirit is already reviving someone...
|
||||
for (Creature* spirit : chainedSpirits)
|
||||
{
|
||||
if (!spirit->isMoving() && !spirit->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
spirit->AI()->SetGUID(reviveGUID);
|
||||
spirit->AI()->DoAction(ACTION_REVIVE);
|
||||
reviveGUID.Clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class boss_mandokir : public CreatureScript
|
||||
{
|
||||
public:
|
||||
@@ -147,14 +173,11 @@ public:
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
// Do not want to unsummon Ohgan
|
||||
for (int i = 0; i < CHAINED_SPIRIT_COUNT; ++i)
|
||||
{
|
||||
if (Creature* unsummon = ObjectAccessor::GetCreature(*me, chainedSpiritGUIDs[i]))
|
||||
{
|
||||
unsummon->DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
std::list<Creature*> chainedSpirits;
|
||||
GetCreatureListWithEntryInGrid(chainedSpirits, me, NPC_CHAINED_SPIRIT, 200.f);
|
||||
for (Creature* spirit : chainedSpirits)
|
||||
spirit->DespawnOrUnsummon();
|
||||
|
||||
instance->SetBossState(DATA_MANDOKIR, DONE);
|
||||
instance->SaveToDB();
|
||||
}
|
||||
@@ -176,8 +199,7 @@ public:
|
||||
me->SummonCreature(NPC_OHGAN, me->GetPositionX() - 3, me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 35000);
|
||||
for (int i = 0; i < CHAINED_SPIRIT_COUNT; ++i)
|
||||
{
|
||||
Creature* chainedSpirit = me->SummonCreature(NPC_CHAINED_SPIRIT, PosSummonChainedSpirits[i], TEMPSUMMON_CORPSE_DESPAWN);
|
||||
chainedSpiritGUIDs[i] = chainedSpirit->GetGUID();
|
||||
me->SummonCreature(NPC_CHAINED_SPIRIT, PosSummonChainedSpirits[i], TEMPSUMMON_CORPSE_DESPAWN);
|
||||
}
|
||||
DoZoneInCombat();
|
||||
}
|
||||
@@ -188,7 +210,7 @@ public:
|
||||
return;
|
||||
|
||||
reviveGUID = victim->GetGUID();
|
||||
DoAction(ACTION_START_REVIVE);
|
||||
RevivePlayer(victim, reviveGUID);
|
||||
if (++killCount == 3)
|
||||
{
|
||||
Talk(SAY_DING_KILL);
|
||||
@@ -199,32 +221,11 @@ public:
|
||||
jindo->AI()->Talk(SAY_GRATS_JINDO);
|
||||
}
|
||||
}
|
||||
DoCast(me, SPELL_LEVEL_UP, true);
|
||||
DoCastSelf(SPELL_LEVEL_UP, true);
|
||||
killCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_START_REVIVE)
|
||||
{
|
||||
std::list<Creature*> creatures;
|
||||
GetCreatureListWithEntryInGrid(creatures, me, NPC_CHAINED_SPIRIT, 200.0f);
|
||||
if (creatures.empty())
|
||||
return;
|
||||
|
||||
for (std::list<Creature*>::iterator itr = creatures.begin(); itr != creatures.end(); ++itr)
|
||||
{
|
||||
if (Creature* chainedSpirit = ObjectAccessor::GetCreature(*me, (*itr)->GetGUID()))
|
||||
{
|
||||
chainedSpirit->AI()->SetGUID(reviveGUID);
|
||||
chainedSpirit->AI()->DoAction(ACTION_REVIVE);
|
||||
reviveGUID.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetGUID(ObjectGuid const guid, int32 /*type = 0 */) override
|
||||
{
|
||||
reviveGUID = guid;
|
||||
@@ -297,7 +298,7 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING) || me->HasUnitState(UNIT_STATE_CHARGING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
@@ -342,11 +343,21 @@ public:
|
||||
events.ScheduleEvent(EVENT_WATCH_PLAYER, urand(12000, 24000));
|
||||
break;
|
||||
case EVENT_CHARGE_PLAYER:
|
||||
DoCast(SelectTarget(SelectTargetMethod::Random, 0, 40, true), SPELL_CHARGE);
|
||||
events.ScheduleEvent(EVENT_FRIGHTENING_SHOUT, 1500);
|
||||
if (Unit* mainTarget = SelectTarget(SelectTargetMethod::MaxThreat, 0, 100.0f))
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MinDistance, 0, [this](Unit const* target)
|
||||
{
|
||||
if (!me || !target)
|
||||
return false;
|
||||
if (target->GetTypeId() != TYPEID_PLAYER || !me->IsWithinLOSInMap(target))
|
||||
return false;
|
||||
return true;
|
||||
}))
|
||||
{
|
||||
me->GetThreatMgr().modifyThreatPercent(mainTarget, -100);
|
||||
DoCast(target, SPELL_CHARGE);
|
||||
events.DelayEvents(1500);
|
||||
if (Unit* mainTarget = SelectTarget(SelectTargetMethod::MaxThreat, 0, 100.0f))
|
||||
{
|
||||
me->GetThreatMgr().modifyThreatPercent(mainTarget, -100);
|
||||
}
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHARGE_PLAYER, urand(30000, 40000));
|
||||
break;
|
||||
@@ -354,9 +365,6 @@ public:
|
||||
DoCastVictim(SPELL_EXECUTE, true);
|
||||
events.ScheduleEvent(EVENT_EXECUTE, urand(7000, 14000));
|
||||
break;
|
||||
case EVENT_FRIGHTENING_SHOUT:
|
||||
DoCastAOE(SPELL_FRIGHTENING_SHOUT);
|
||||
break;
|
||||
case EVENT_CLEAVE:
|
||||
{
|
||||
std::list<Unit*> meleeRangeTargets;
|
||||
@@ -384,12 +392,12 @@ public:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
uint8 killCount;
|
||||
ObjectGuid chainedSpiritGUIDs[CHAINED_SPIRIT_COUNT];
|
||||
ObjectGuid reviveGUID;
|
||||
bool _useExecute;
|
||||
};
|
||||
@@ -401,7 +409,6 @@ public:
|
||||
};
|
||||
|
||||
// Ohgan
|
||||
|
||||
enum OhganSpells
|
||||
{
|
||||
SPELL_SUNDERARMOR = 24317,
|
||||
@@ -422,9 +429,9 @@ public:
|
||||
me->AddAura(SPELL_THRASH, me);
|
||||
_scheduler.CancelAll();
|
||||
_scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
|
||||
reviveGUID.Clear();
|
||||
}
|
||||
@@ -434,12 +441,10 @@ public:
|
||||
if (victim->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
reviveGUID = victim->GetGUID();
|
||||
DoAction(ACTION_START_REVIVE);
|
||||
_scheduler.Schedule(6s, 12s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_SUNDERARMOR);
|
||||
context.Repeat(6s, 12s);
|
||||
DoCastVictim(SPELL_SUNDERARMOR);
|
||||
context.Repeat(6s, 12s);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -449,25 +454,7 @@ public:
|
||||
return;
|
||||
|
||||
reviveGUID = victim->GetGUID();
|
||||
DoAction(ACTION_START_REVIVE);
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_START_REVIVE)
|
||||
{
|
||||
std::list<Creature*> creatures;
|
||||
GetCreatureListWithEntryInGrid(creatures, me, NPC_CHAINED_SPIRIT, 200.0f);
|
||||
if (creatures.empty())
|
||||
return;
|
||||
|
||||
for (Creature* chainedSpirit : creatures)
|
||||
{
|
||||
chainedSpirit->AI()->SetGUID(reviveGUID);
|
||||
chainedSpirit->AI()->DoAction(ACTION_REVIVE);
|
||||
reviveGUID.Clear();
|
||||
}
|
||||
}
|
||||
RevivePlayer(victim, reviveGUID);
|
||||
}
|
||||
|
||||
void SetGUID(ObjectGuid const guid, int32 /*type = 0 */) override
|
||||
@@ -553,15 +540,6 @@ public:
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Player* target = ObjectAccessor::GetPlayer(*me, revivePlayerGUID);
|
||||
if (!target || target->IsAlive())
|
||||
return;
|
||||
|
||||
if (Creature* mandokir = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MANDOKIR)))
|
||||
{
|
||||
mandokir->GetAI()->SetGUID(target->GetGUID());
|
||||
mandokir->GetAI()->DoAction(ACTION_START_REVIVE);
|
||||
}
|
||||
me->DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
@@ -579,61 +557,50 @@ enum VilebranchSpells
|
||||
SPELL_CLEAVE = 15284
|
||||
};
|
||||
|
||||
class npc_vilebranch_speaker : public CreatureScript
|
||||
struct npc_vilebranch_speaker : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
npc_vilebranch_speaker() : CreatureScript("npc_vilebranch_speaker") { }
|
||||
npc_vilebranch_speaker(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript()) { }
|
||||
|
||||
struct npc_vilebranch_speakerAI : public ScriptedAI
|
||||
void Reset() override
|
||||
{
|
||||
npc_vilebranch_speakerAI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript()) { }
|
||||
_scheduler.CancelAll();
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
demoralizing_Shout_Timer = urand(2000, 4000);
|
||||
cleave_Timer = urand(5000, 8000);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override { }
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
instance->SetBossState(DATA_MANDOKIR, SPECIAL);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
// Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (demoralizing_Shout_Timer <= diff)
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
_scheduler
|
||||
.Schedule(2s, 4s, [this](TaskContext context)
|
||||
{
|
||||
DoCast(me, SPELL_DEMORALIZING_SHOUT);
|
||||
demoralizing_Shout_Timer = urand(22000, 30000);
|
||||
}
|
||||
else demoralizing_Shout_Timer -= diff;
|
||||
|
||||
if (cleave_Timer <= diff)
|
||||
DoCastAOE(SPELL_DEMORALIZING_SHOUT);
|
||||
context.Repeat(22s, 30s);
|
||||
})
|
||||
.Schedule(5s, 8s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_CLEAVE, true);
|
||||
cleave_Timer = urand(6000, 9000);
|
||||
}
|
||||
else cleave_Timer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 demoralizing_Shout_Timer;
|
||||
uint32 cleave_Timer;
|
||||
InstanceScript* instance;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetZulGurubAI<npc_vilebranch_speakerAI>(creature);
|
||||
context.Repeat(6s, 9s);
|
||||
});
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
instance->SetBossState(DATA_MANDOKIR, SPECIAL);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
// Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff, [this]
|
||||
{
|
||||
DoMeleeAttackIfReady();
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
InstanceScript* instance;
|
||||
};
|
||||
|
||||
class spell_threatening_gaze : public SpellScriptLoader
|
||||
@@ -671,11 +638,30 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class spell_mandokir_charge : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_mandokir_charge);
|
||||
|
||||
void LaunchHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
Unit* target = GetHitUnit();
|
||||
if (caster && target)
|
||||
caster->CastSpell(target, SPELL_FRIGHTENING_SHOUT, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_mandokir_charge::LaunchHit, EFFECT_0, SPELL_EFFECT_CHARGE);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_mandokir()
|
||||
{
|
||||
new boss_mandokir();
|
||||
new npc_ohgan();
|
||||
RegisterZulGurubCreatureAI(npc_chained_spirit);
|
||||
new npc_vilebranch_speaker();
|
||||
RegisterZulGurubCreatureAI(npc_vilebranch_speaker);
|
||||
new spell_threatening_gaze();
|
||||
RegisterSpellScript(spell_mandokir_charge);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user