diff --git a/data/sql/updates/pending_db_world/rev_1656469500232857400.sql b/data/sql/updates/pending_db_world/rev_1656469500232857400.sql
new file mode 100644
index 000000000..d5e671a32
--- /dev/null
+++ b/data/sql/updates/pending_db_world/rev_1656469500232857400.sql
@@ -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;
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp
index 0b912aef1..d4aa84a18 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp
@@ -15,15 +15,10 @@
* with this program. If not, see .
*/
-/* 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(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(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(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);
}