fix(Core/ZulGurub): Jin'do the Hexxer rewrite (#12233)

Co-authored-by: UltraNix <ultranix@users.noreply.github.com>
This commit is contained in:
Nefertumm
2022-07-09 18:36:51 -03:00
committed by GitHub
parent c63d70e95f
commit 9c09857b19
2 changed files with 244 additions and 217 deletions
@@ -0,0 +1,36 @@
--
DELETE FROM `spell_target_position` WHERE `id` = 24466;
INSERT INTO `spell_target_position` (`ID`, `EffectIndex`, `MapID`, `PositionX`, `PositionY`, `PositionZ`, `Orientation`) VALUES
(24466, 0, 309, -11582.9, -1251.15, 90, 5.04179);
UPDATE `creature` SET `spawntimesecs` = 20 WHERE `id1` = 14826;
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 14826;
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 14826) AND (`source_type` = 0) AND (`id` IN (0, 1));
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(14826, 0, 0, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 41, 5000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Sacrificed Troll - On Just Died - Despawn In 5000 ms'),
(14826, 0, 1, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 70, 0, 0, 0, 0, 0, 0, 9, 14826, 0, 100, 2, 0, 0, 0, 0, 'Sacrificed Troll - On Respawn - Respawn Closest Creature \'Sacrificed Troll\'');
SET @LEADERGUID := 49081;
DELETE FROM `creature_formations` WHERE `memberGUID` IN (@LEADERGUID, 49078, 49079, 49080, 49082, 49083, 49084, 49085, 49086, 49087);
INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`) VALUES
(@LEADERGUID, @LEADERGUID, 0, 0, 3),
(@LEADERGUID, 49078, 0, 0, 3),
(@LEADERGUID, 49079, 0, 0, 3),
(@LEADERGUID, 49080, 0, 0, 3),
(@LEADERGUID, 49082, 0, 0, 3),
(@LEADERGUID, 49083, 0, 0, 3),
(@LEADERGUID, 49084, 0, 0, 3),
(@LEADERGUID, 49085, 0, 0, 3),
(@LEADERGUID, 49086, 0, 0, 3),
(@LEADERGUID, 49087, 0, 0, 3);
UPDATE `creature_template_spell` SET `Spell` = 24261 WHERE `CreatureID` = 15112 AND `Index` = 0;
DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_random_aggro', 'spell_delusions_of_jindo');
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
(23878, 'spell_random_aggro'),
(24306, 'spell_delusions_of_jindo');
UPDATE `creature_template` SET `speed_run` = 1.14286, `speed_walk` = 1.32 WHERE `entry` = 11380;
@@ -15,15 +15,10 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/* ScriptData
SDName: Boss_Jin'do the Hexxer
SD%Complete: 85
SDComment: Mind Control not working because of core bug. Shades visible for all.
SDCategory: Zul'Gurub
EndScriptData */
#include "ScriptMgr.h" #include "ScriptMgr.h"
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "SpellScript.h"
#include "TaskScheduler.h"
#include "zulgurub.h" #include "zulgurub.h"
enum Say enum Say
@@ -33,269 +28,265 @@ enum Say
enum Spells enum Spells
{ {
SPELL_BRAINWASHTOTEM = 24262, SPELL_BRAIN_WASH_TOTEM = 24262,
SPELL_POWERFULLHEALINGWARD = 24309, SPELL_POWERFULL_HEALING_WARD = 24309,
SPELL_HEX = 24053, SPELL_HEX = 24053,
SPELL_DELUSIONSOFJINDO = 24306, SPELL_DELUSIONS_OF_JINDO = 24306,
SPELL_SUMMON_SHADE_OF_JINDO = 24308,
SPELL_BANISH = 24466,
//Healing Ward Spell //Healing Ward Spell
SPELL_HEAL = 24311, SPELL_HEAL = 24311,
//Shade of Jindo Spell //Shade of Jindo Spell
SPELL_SHADEOFJINDO_PASSIVE = 24307, SPELL_SHADE_OF_JINDO_PASSIVE = 24307,
SPELL_SHADEOFJINDO_VISUAL = 24313, SPELL_SHADE_OF_JINDO_VISUAL = 24313,
SPELL_SHADOWSHOCK = 19460 SPELL_SHADOW_SHOCK = 19460,
SPELL_RANDOM_AGGRO = 23878
}; };
enum Events enum Events
{ {
EVENT_BRAINWASHTOTEM = 1, EVENT_BRAIN_WASH_TOTEM = 1,
EVENT_POWERFULLHEALINGWARD = 2, EVENT_POWERFULL_HEALING_WARD = 2,
EVENT_HEX = 3, EVENT_HEX = 3,
EVENT_DELUSIONSOFJINDO = 4, EVENT_DELUSIONS_OF_JINDO = 4,
EVENT_TELEPORT = 5 EVENT_TELEPORT = 5
}; };
Position const TeleportLoc = {-11583.7783f, -1249.4278f, 77.5471f, 4.745f}; struct boss_jindo : public BossAI
class boss_jindo : public CreatureScript
{ {
public: boss_jindo(Creature* creature) : BossAI(creature, DATA_JINDO) { }
boss_jindo() : CreatureScript("boss_jindo") { }
struct boss_jindoAI : public BossAI void EnterCombat(Unit* who) override
{ {
boss_jindoAI(Creature* creature) : BossAI(creature, DATA_JINDO) { } BossAI::EnterCombat(who);
events.ScheduleEvent(EVENT_BRAIN_WASH_TOTEM, 20000);
events.ScheduleEvent(EVENT_POWERFULL_HEALING_WARD, 16000);
events.ScheduleEvent(EVENT_HEX, 8000);
events.ScheduleEvent(EVENT_DELUSIONS_OF_JINDO, 10000);
events.ScheduleEvent(EVENT_TELEPORT, 5000);
void Reset() override Talk(SAY_AGGRO);
}
void JustSummoned(Creature* summon) override
{
BossAI::JustSummoned(summon);
switch (summon->GetEntry())
{ {
_Reset(); case NPC_BRAIN_WASH_TOTEM:
} if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1))
void JustDied(Unit* /*killer*/) override
{
_JustDied();
}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
events.ScheduleEvent(EVENT_BRAINWASHTOTEM, 20000);
events.ScheduleEvent(EVENT_POWERFULLHEALINGWARD, 16000);
events.ScheduleEvent(EVENT_HEX, 8000);
events.ScheduleEvent(EVENT_DELUSIONSOFJINDO, 10000);
events.ScheduleEvent(EVENT_TELEPORT, 5000);
Talk(SAY_AGGRO);
}
void JustSummoned(Creature* summon) override
{
BossAI::JustSummoned(summon);
switch (summon->GetEntry())
{ {
case NPC_BRAIN_WASH_TOTEM: summon->CastSpell(target, summon->m_spells[0], true);
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1)) }
{ break;
summon->CastSpell(target, summon->m_spells[0], true); default:
} break;
break; }
default: }
break;
void EnterEvadeMode(EvadeReason evadeReason) override
{
if (_EnterEvadeMode(evadeReason))
{
me->AddUnitState(UNIT_STATE_EVADE);
Reset();
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_DANCE);
me->m_Events.AddEventAtOffset([&]()
{
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE);
me->GetMotionMaster()->MoveTargetedHome();
}, 4s);
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_BRAIN_WASH_TOTEM:
DoCastSelf(SPELL_BRAIN_WASH_TOTEM);
events.ScheduleEvent(EVENT_BRAIN_WASH_TOTEM, urand(18000, 26000));
break;
case EVENT_POWERFULL_HEALING_WARD:
DoCastSelf(SPELL_POWERFULL_HEALING_WARD, true);
events.ScheduleEvent(EVENT_POWERFULL_HEALING_WARD, urand(14000, 20000));
break;
case EVENT_HEX:
if (me->GetThreatMgr().getThreatList().size() > 1)
DoCastVictim(SPELL_HEX, true);
events.ScheduleEvent(EVENT_HEX, urand(12000, 20000));
break;
case EVENT_DELUSIONS_OF_JINDO:
DoCastRandomTarget(SPELL_DELUSIONS_OF_JINDO);
events.ScheduleEvent(EVENT_DELUSIONS_OF_JINDO, urand(4000, 12000));
break;
case EVENT_TELEPORT:
DoCastRandomTarget(SPELL_BANISH);
events.ScheduleEvent(EVENT_TELEPORT, urand(15000, 23000));
break;
default:
break;
} }
} }
void UpdateAI(uint32 diff) override DoMeleeAttackIfReady();
{ }
if (!UpdateVictim())
return;
events.Update(diff); bool CanAIAttack(Unit const* target) const override
{
if (me->HasUnitState(UNIT_STATE_CASTING)) if (me->GetThreatMgr().getThreatList().size() > 1 && me->GetThreatMgr().getOnlineContainer().getMostHated()->getTarget() == target)
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_BRAINWASHTOTEM:
DoCast(me, SPELL_BRAINWASHTOTEM);
events.ScheduleEvent(EVENT_BRAINWASHTOTEM, urand(18000, 26000));
break;
case EVENT_POWERFULLHEALINGWARD:
DoCastSelf(SPELL_POWERFULLHEALINGWARD, true);
events.ScheduleEvent(EVENT_POWERFULLHEALINGWARD, urand(14000, 20000));
break;
case EVENT_HEX:
DoCastVictim(SPELL_HEX, true);
events.ScheduleEvent(EVENT_HEX, urand(12000, 20000));
break;
case EVENT_DELUSIONSOFJINDO: // HACK
// Casting the delusion curse with a shade so shade will attack the same target with the curse.
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
{
DoCast(target, SPELL_DELUSIONSOFJINDO);
Creature* Shade = me->SummonCreature(NPC_SHADE_OF_JINDO, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
if (Shade)
Shade->AI()->AttackStart(target);
}
events.ScheduleEvent(EVENT_DELUSIONSOFJINDO, urand(4000, 12000));
break;
case EVENT_TELEPORT: // Possible HACK
// Teleports a random player and spawns 9 Sacrificed Trolls to attack player
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
{
DoTeleportPlayer(target, TeleportLoc.m_positionX, TeleportLoc.m_positionY, TeleportLoc.m_positionZ, TeleportLoc.GetOrientation());
if (DoGetThreat(me->GetVictim()))
DoModifyThreatPercent(target, -100);
Creature* SacrificedTroll;
SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, TeleportLoc.m_positionX + 2, TeleportLoc.m_positionY, TeleportLoc.m_positionZ, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
if (SacrificedTroll)
SacrificedTroll->AI()->AttackStart(target);
SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, TeleportLoc.m_positionX - 2, TeleportLoc.m_positionY, TeleportLoc.m_positionZ, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
if (SacrificedTroll)
SacrificedTroll->AI()->AttackStart(target);
SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, TeleportLoc.m_positionX + 4, TeleportLoc.m_positionY, TeleportLoc.m_positionZ, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
if (SacrificedTroll)
SacrificedTroll->AI()->AttackStart(target);
SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, TeleportLoc.m_positionX - 4, TeleportLoc.m_positionY, TeleportLoc.m_positionZ, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
if (SacrificedTroll)
SacrificedTroll->AI()->AttackStart(target);
SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, TeleportLoc.m_positionX, TeleportLoc.m_positionY + 2, TeleportLoc.m_positionZ, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
if (SacrificedTroll)
SacrificedTroll->AI()->AttackStart(target);
SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, TeleportLoc.m_positionX, TeleportLoc.m_positionY - 2, TeleportLoc.m_positionZ, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
if (SacrificedTroll)
SacrificedTroll->AI()->AttackStart(target);
SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, TeleportLoc.m_positionX, TeleportLoc.m_positionY + 4, TeleportLoc.m_positionZ, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
if (SacrificedTroll)
SacrificedTroll->AI()->AttackStart(target);
SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, TeleportLoc.m_positionX, TeleportLoc.m_positionY - 4, TeleportLoc.m_positionZ, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
if (SacrificedTroll)
SacrificedTroll->AI()->AttackStart(target);
SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, TeleportLoc.m_positionX + 3, TeleportLoc.m_positionY, TeleportLoc.m_positionZ, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
if (SacrificedTroll)
SacrificedTroll->AI()->AttackStart(target);
}
events.ScheduleEvent(EVENT_TELEPORT, urand(15000, 23000));
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
bool CanAIAttack(Unit const* target) const override
{
return !target->HasAura(SPELL_HEX); return !target->HasAura(SPELL_HEX);
}
};
CreatureAI* GetAI(Creature* creature) const override return true;
{
return GetZulGurubAI<boss_jindoAI>(creature);
} }
}; };
//Healing Ward //Healing Ward
class npc_healing_ward : public CreatureScript struct npc_healing_ward : public ScriptedAI
{ {
public: npc_healing_ward(Creature* creature) : ScriptedAI(creature)
npc_healing_ward()
: CreatureScript("npc_healing_ward")
{ {
_instance = creature->GetInstanceScript();
} }
struct npc_healing_wardAI : public ScriptedAI void Reset() override
{ {
npc_healing_wardAI(Creature* creature) : ScriptedAI(creature) _scheduler.CancelAll();
{ }
instance = creature->GetInstanceScript();
}
uint32 Heal_Timer; void EnterCombat(Unit* /*who*/) override
{
InstanceScript* instance; _scheduler.
Schedule(2s, [this](TaskContext context)
void Reset() override
{
Heal_Timer = 2000;
}
void EnterCombat(Unit* /*who*/) override
{
}
void UpdateAI(uint32 diff) override
{
//Heal_Timer
if (Heal_Timer <= diff)
{ {
Unit* pJindo = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_JINDO)); Unit* pJindo = ObjectAccessor::GetUnit(*me, _instance->GetGuidData(DATA_JINDO));
if (pJindo) if (pJindo)
DoCast(pJindo, SPELL_HEAL); DoCast(pJindo, SPELL_HEAL);
Heal_Timer = 3000; context.Repeat(3s);
} });
else Heal_Timer -= diff;
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetZulGurubAI<npc_healing_wardAI>(creature);
} }
void UpdateAI(uint32 diff) override
{
_scheduler.Update(diff, [this]
{
DoMeleeAttackIfReady();
});
}
private:
InstanceScript* _instance;
TaskScheduler _scheduler;
}; };
//Shade of Jindo //Shade of Jindo
class npc_shade_of_jindo : public CreatureScript struct npc_shade_of_jindo : public ScriptedAI
{ {
public: npc_shade_of_jindo(Creature* creature) : ScriptedAI(creature) { }
npc_shade_of_jindo()
: CreatureScript("npc_shade_of_jindo") void IsSummonedBy(Unit* /*summoner*/) override
{ {
DoZoneInCombat();
DoCastSelf(SPELL_SHADE_OF_JINDO_PASSIVE, true);
DoCastSelf(SPELL_SHADE_OF_JINDO_VISUAL, true);
DoCastAOE(SPELL_RANDOM_AGGRO, true);
} }
struct npc_shade_of_jindoAI : public ScriptedAI void Reset() override
{ {
npc_shade_of_jindoAI(Creature* creature) : ScriptedAI(creature) { } _scheduler.CancelAll();
uint32 ShadowShock_Timer; _scheduler.
Schedule(1s, [this](TaskContext context)
void Reset() override
{
ShadowShock_Timer = 1000;
DoCastSelf(SPELL_SHADEOFJINDO_PASSIVE, true);
DoCastSelf(SPELL_SHADEOFJINDO_VISUAL, true);
}
void EnterCombat(Unit* /*who*/) override { }
void UpdateAI(uint32 diff) override
{
//ShadowShock_Timer
if (ShadowShock_Timer <= diff)
{ {
DoCastVictim(SPELL_SHADOWSHOCK); DoCastAOE(SPELL_RANDOM_AGGRO, true);
ShadowShock_Timer = 2000; context.Repeat();
} });
else ShadowShock_Timer -= diff; }
DoMeleeAttackIfReady(); void EnterCombat(Unit* /*who*/) override
}
};
CreatureAI* GetAI(Creature* creature) const override
{ {
return GetZulGurubAI<npc_shade_of_jindoAI>(creature); _scheduler.
Schedule(1s, [this](TaskContext context)
{
DoCastVictim(SPELL_SHADOW_SHOCK);
context.Repeat(2s);
});
}
void UpdateAI(uint32 diff) override
{
_scheduler.Update(diff, [this]
{
DoMeleeAttackIfReady();
});
}
private:
TaskScheduler _scheduler;
};
class spell_random_aggro : public SpellScript
{
PrepareSpellScript(spell_random_aggro);
void HandleOnHit()
{
Unit* caster = GetCaster();
Unit* target = GetHitUnit();
if (!caster || !target || !caster->GetAI())
return;
caster->GetAI()->AttackStart(target);
}
void Register() override
{
OnHit += SpellHitFn(spell_random_aggro::HandleOnHit);
}
};
class spell_delusions_of_jindo : public SpellScript
{
PrepareSpellScript(spell_delusions_of_jindo);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_SUMMON_SHADE_OF_JINDO });
}
void HandleOnHit()
{
Unit* caster = GetCaster();
if (caster)
caster->CastSpell(caster, SPELL_SUMMON_SHADE_OF_JINDO, true);
}
void Register() override
{
OnHit += SpellHitFn(spell_delusions_of_jindo::HandleOnHit);
} }
}; };
void AddSC_boss_jindo() void AddSC_boss_jindo()
{ {
new boss_jindo(); RegisterZulGurubCreatureAI(boss_jindo);
new npc_healing_ward(); RegisterZulGurubCreatureAI(npc_healing_ward);
new npc_shade_of_jindo(); RegisterZulGurubCreatureAI(npc_shade_of_jindo);
RegisterSpellScript(spell_random_aggro);
RegisterSpellScript(spell_delusions_of_jindo);
} }