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

View File

@@ -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;

View File

@@ -15,15 +15,10 @@
* 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 "ScriptedCreature.h"
#include "SpellScript.h"
#include "TaskScheduler.h"
#include "zulgurub.h"
enum Say
@@ -33,269 +28,265 @@ enum Say
enum Spells
{
SPELL_BRAINWASHTOTEM = 24262,
SPELL_POWERFULLHEALINGWARD = 24309,
SPELL_BRAIN_WASH_TOTEM = 24262,
SPELL_POWERFULL_HEALING_WARD = 24309,
SPELL_HEX = 24053,
SPELL_DELUSIONSOFJINDO = 24306,
SPELL_DELUSIONS_OF_JINDO = 24306,
SPELL_SUMMON_SHADE_OF_JINDO = 24308,
SPELL_BANISH = 24466,
//Healing Ward Spell
SPELL_HEAL = 24311,
//Shade of Jindo Spell
SPELL_SHADEOFJINDO_PASSIVE = 24307,
SPELL_SHADEOFJINDO_VISUAL = 24313,
SPELL_SHADOWSHOCK = 19460
SPELL_SHADE_OF_JINDO_PASSIVE = 24307,
SPELL_SHADE_OF_JINDO_VISUAL = 24313,
SPELL_SHADOW_SHOCK = 19460,
SPELL_RANDOM_AGGRO = 23878
};
enum Events
{
EVENT_BRAINWASHTOTEM = 1,
EVENT_POWERFULLHEALINGWARD = 2,
EVENT_BRAIN_WASH_TOTEM = 1,
EVENT_POWERFULL_HEALING_WARD = 2,
EVENT_HEX = 3,
EVENT_DELUSIONSOFJINDO = 4,
EVENT_DELUSIONS_OF_JINDO = 4,
EVENT_TELEPORT = 5
};
Position const TeleportLoc = {-11583.7783f, -1249.4278f, 77.5471f, 4.745f};
class boss_jindo : public CreatureScript
struct boss_jindo : public BossAI
{
public:
boss_jindo() : CreatureScript("boss_jindo") { }
boss_jindo(Creature* creature) : BossAI(creature, DATA_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();
}
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:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1))
{
case NPC_BRAIN_WASH_TOTEM:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1))
{
summon->CastSpell(target, summon->m_spells[0], true);
}
break;
default:
break;
summon->CastSpell(target, summon->m_spells[0], true);
}
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
{
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
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
{
bool CanAIAttack(Unit const* target) const override
{
if (me->GetThreatMgr().getThreatList().size() > 1 && me->GetThreatMgr().getOnlineContainer().getMostHated()->getTarget() == target)
return !target->HasAura(SPELL_HEX);
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetZulGurubAI<boss_jindoAI>(creature);
return true;
}
};
//Healing Ward
class npc_healing_ward : public CreatureScript
struct npc_healing_ward : public ScriptedAI
{
public:
npc_healing_ward()
: CreatureScript("npc_healing_ward")
npc_healing_ward(Creature* creature) : ScriptedAI(creature)
{
_instance = creature->GetInstanceScript();
}
struct npc_healing_wardAI : public ScriptedAI
void Reset() override
{
npc_healing_wardAI(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
}
_scheduler.CancelAll();
}
uint32 Heal_Timer;
InstanceScript* instance;
void Reset() override
{
Heal_Timer = 2000;
}
void EnterCombat(Unit* /*who*/) override
{
}
void UpdateAI(uint32 diff) override
{
//Heal_Timer
if (Heal_Timer <= diff)
void EnterCombat(Unit* /*who*/) override
{
_scheduler.
Schedule(2s, [this](TaskContext context)
{
Unit* pJindo = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_JINDO));
Unit* pJindo = ObjectAccessor::GetUnit(*me, _instance->GetGuidData(DATA_JINDO));
if (pJindo)
DoCast(pJindo, SPELL_HEAL);
Heal_Timer = 3000;
}
else Heal_Timer -= diff;
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetZulGurubAI<npc_healing_wardAI>(creature);
context.Repeat(3s);
});
}
void UpdateAI(uint32 diff) override
{
_scheduler.Update(diff, [this]
{
DoMeleeAttackIfReady();
});
}
private:
InstanceScript* _instance;
TaskScheduler _scheduler;
};
//Shade of Jindo
class npc_shade_of_jindo : public CreatureScript
struct npc_shade_of_jindo : public ScriptedAI
{
public:
npc_shade_of_jindo()
: CreatureScript("npc_shade_of_jindo")
npc_shade_of_jindo(Creature* creature) : ScriptedAI(creature) { }
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;
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)
_scheduler.
Schedule(1s, [this](TaskContext context)
{
DoCastVictim(SPELL_SHADOWSHOCK);
ShadowShock_Timer = 2000;
}
else ShadowShock_Timer -= diff;
DoCastAOE(SPELL_RANDOM_AGGRO, true);
context.Repeat();
});
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
void EnterCombat(Unit* /*who*/) 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()
{
new boss_jindo();
new npc_healing_ward();
new npc_shade_of_jindo();
RegisterZulGurubCreatureAI(boss_jindo);
RegisterZulGurubCreatureAI(npc_healing_ward);
RegisterZulGurubCreatureAI(npc_shade_of_jindo);
RegisterSpellScript(spell_random_aggro);
RegisterSpellScript(spell_delusions_of_jindo);
}