diff --git a/data/sql/updates/pending_db_world/rev_1660487670384321500.sql b/data/sql/updates/pending_db_world/rev_1660487670384321500.sql new file mode 100644 index 000000000..be2b596c0 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1660487670384321500.sql @@ -0,0 +1,157 @@ +-- +DELETE FROM `spell_target_position` WHERE `ID` IN (25708, 25709, 25825, 25826, 25827, 25828); +INSERT INTO `spell_target_position` (`ID`, `EffectIndex`, `MapID`, `PositionX`, `PositionY`, `PositionZ`, `Orientation`, `VerifiedBuild`) VALUES +(25708, 0, 509, -9846, 1353, 106.083336, 0, 0), +(25709, 0, 509, -9757.87, 1416.71, 76.7664, 0, 0), +(25825, 0, 509, -9805.95, 1422.85, 77.5852, 0, 0), +(25826, 0, 509, -9827.58, 1506.28, 82.3052, 0, 0), +(25827, 0, 509, -9778.91, 1419.98, 61.0743, 0, 0), +(25828, 0, 509, -9829.42, 1456.37, 90.7015, 0, 0); + +DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_ayamiss_swarmer_teleport_trigger'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(25830, 'spell_ayamiss_swarmer_teleport_trigger'); + +DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_ayamiss_swarmer_swarm'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(25844, 'spell_ayamiss_swarmer_swarm'); + +UPDATE `spell_dbc` SET `Effect_1` = 28, `EffectMiscValueB_1` = 64, `EffectBasePoints_1` = 1, `EffectDieSides_1` = 0 WHERE `ID` = 25708; + +DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_ayamiss_swarmer_start_loop'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(25711, 'spell_ayamiss_swarmer_start_loop'); + +DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_gen_ayamiss_swarmer_loop_1', 'spell_gen_ayamiss_swarmer_loop_2', 'spell_gen_ayamiss_swarmer_loop_3'); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(25833, 'spell_gen_ayamiss_swarmer_loop_1'), +(25834, 'spell_gen_ayamiss_swarmer_loop_2'), +(25835, 'spell_gen_ayamiss_swarmer_loop_3'); + +UPDATE `creature_template` SET `ScriptName` = 'npc_hive_zara_swarmer' WHERE `entry` = 15546; + +SET @NPC := 15546; +SET @PATH := @NPC * 10; +DELETE FROM `waypoint_data` WHERE `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(@PATH, 1, -9758.247, 1426.3112, 84.167656, 0, 0, 0, 0, 100, 0), +(@PATH, 2, -9762.383, 1436.3455, 84.428795, 0, 0, 0, 0, 100, 0), +(@PATH, 3, -9760.481, 1452.1432, 75.32612, 0, 0, 0, 0, 100, 0), +(@PATH, 4, -9754.527, 1466.5826, 61.60388, 0, 0, 0, 0, 100, 0), +(@PATH, 5, -9750.208, 1479.4608, 45.937202, 0, 0, 0, 0, 100, 0); + +SET @PATH := (@NPC + 1) * 10; +DELETE FROM `waypoint_data` WHERE `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(@PATH, 1, -9804.298, 1432.3503, 85.9217, 0, 0, 0, 0, 100, 0), +(@PATH, 2, -9799.983, 1443.1294, 82.55095, 0, 0, 0, 0, 100, 0), +(@PATH, 3, -9785.31, 1456.0002, 76.88425, 0, 0, 0, 0, 100, 0), +(@PATH, 4, -9769.325, 1467.856, 68.520706, 0, 0, 0, 0, 100, 0), +(@PATH, 5, -9750.661, 1477.6143, 48.96516, 0, 0, 0, 0, 100, 0); + +SET @PATH := (@NPC + 2) * 10; +DELETE FROM `waypoint_data` WHERE `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(@PATH, 1, -9818.727, 1512.838, 89.24695, 0, 0, 0, 0, 100, 0), +(@PATH, 2, -9812.264, 1511.9375, 87.49864, 0, 0, 0, 0, 100, 0), +(@PATH, 3, -9806.9375, 1505.4645, 83.19313, 0, 0, 0, 0, 100, 0), +(@PATH, 4, -9796.596, 1494.5698, 76.8735, 0, 0, 0, 0, 100, 0), +(@PATH, 5, -9781.221, 1486.8652, 71.7902, 0, 0, 0, 0, 100, 0), +(@PATH, 6, -9765.105, 1476.7782, 63.17909, 0, 0, 0, 0, 100, 0), +(@PATH, 7, -9753.014, 1478.1317, 50.817974, 0, 0, 0, 0, 100, 0); + +SET @PATH := (@NPC + 3) * 10; +DELETE FROM `waypoint_data` WHERE `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(@PATH, 1, -9776.323, 1428.8531, 65.629776, 0, 0, 0, 0, 100, 0), +(@PATH, 2, -9776.123, 1436.0718, 67.35508, 0, 0, 0, 0, 100, 0), +(@PATH, 3, -9764.125, 1455.0714, 66.27153, 0, 0, 0, 0, 100, 0), +(@PATH, 4, -9754.778, 1466.8633, 62.577053, 0, 0, 0, 0, 100, 0), +(@PATH, 5, -9747.529, 1473.6367, 49.077087, 0, 0, 0, 0, 100, 0); + +SET @PATH := (@NPC + 4) * 10; +DELETE FROM `waypoint_data` WHERE `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(@PATH, 1, -9818.173, 1460.0463, 95.69417, 0, 0, 0, 0, 100, 0), +(@PATH, 2, -9811.176, 1460.6091, 92.56013, 0, 0, 0, 0, 100, 0), +(@PATH, 3, -9802.768, 1455.1123, 86.143425, 0, 0, 0, 0, 100, 0), +(@PATH, 4, -9797.88, 1450.7151, 81.69902, 0, 0, 0, 0, 100, 0), +(@PATH, 5, -9761.196, 1470.298, 64.64121, 0, 0, 0, 0, 100, 0), +(@PATH, 6, -9754.684, 1475.3403, 49.030098, 0, 0, 0, 0, 100, 0); + +SET @PATH := (@NPC + 5) * 10; +DELETE FROM `waypoint_data` WHERE `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(@PATH, 1, -9745.072, 1489.5533, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 2, -9745.766, 1502.0659, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 3, -9734.748, 1502.8883, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 4, -9715.551, 1496.5533, 42.267452, 0, 0, 0, 0, 100, 0), +(@PATH, 5, -9697.712, 1511.8822, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 6, -9694.466, 1539.3663, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 7, -9696.591, 1561.1914, 41.37858, 0, 0, 0, 0, 100, 0), +(@PATH, 8, -9667.614, 1571.5212, 43.489666, 0, 0, 0, 0, 100, 0), +(@PATH, 9, -9653.44, 1552.1632, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 10, -9612.033, 1551.3334, 39.26745, 0, 0, 0, 0, 100, 0), +(@PATH, 11, -9582.261, 1572.4617, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 12, -9598.483, 1615.416, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 13, -9638.286, 1645.0948, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 14, -9682.366, 1625.8219, 37.211887, 0, 0, 0, 0, 100, 0), +(@PATH, 15, -9667.457, 1593.8171, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 16, -9625.382, 1598.9684, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 17, -9618.158, 1566.9963, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 18, -9661.183, 1554.485, 42.489677, 0, 0, 0, 0, 100, 0), +(@PATH, 19, -9690.858, 1543.3951, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 20, -9711.017, 1540.3297, 43.517445, 0, 0, 0, 0, 100, 0), +(@PATH, 21, -9736.964, 1511.8362, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 22, -9725.431, 1487.6272, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 23, -9742.012, 1485.945, 44.323, 0, 0, 0, 0, 100, 0); + +SET @PATH := (@NPC + 6) * 10; +DELETE FROM `waypoint_data` WHERE `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(@PATH, 1, -9748.129, 1488.4904, 45.764896, 0, 0, 0, 0, 100, 0), +(@PATH, 2, -9748.667, 1498.9249, 47.07047, 0, 0, 0, 0, 100, 0), +(@PATH, 3, -9744.251, 1508.8634, 46.820465, 0, 0, 0, 0, 100, 0), +(@PATH, 4, -9713.56, 1502.6979, 43.542686, 0, 0, 0, 0, 100, 0), +(@PATH, 5, -9701.453, 1522.0952, 43.542686, 0, 0, 0, 0, 100, 0), +(@PATH, 6, -9702.735, 1548.3297, 40.987125, 0, 0, 0, 0, 100, 0), +(@PATH, 7, -9682.249, 1544.3987, 41.12602, 0, 0, 0, 0, 100, 0), +(@PATH, 8, -9661.323, 1537.9355, 42.959347, 0, 0, 0, 0, 100, 0), +(@PATH, 9, -9647.55, 1544.9911, 42.959347, 0, 0, 0, 0, 100, 0), +(@PATH, 10, -9651.3125, 1565.7776, 42.98713, 0, 0, 0, 0, 100, 0), +(@PATH, 11, -9657.682, 1593.8557, 45.070454, 0, 0, 0, 0, 100, 0), +(@PATH, 12, -9684.013, 1619.9458, 45.070454, 0, 0, 0, 0, 100, 0), +(@PATH, 13, -9645.765, 1642.1168, 50.042664, 0, 0, 0, 0, 100, 0), +(@PATH, 14, -9618.591, 1606.9883, 45.070454, 0, 0, 0, 0, 100, 0), +(@PATH, 15, -9624.827, 1566.3673, 45.070454, 0, 0, 0, 0, 100, 0), +(@PATH, 16, -9662.095, 1559.2485, 45.070454, 0, 0, 0, 0, 100, 0), +(@PATH, 17, -9689.207, 1559.972, 45.070454, 0, 0, 0, 0, 100, 0), +(@PATH, 18, -9692.733, 1523.6748, 45.070454, 0, 0, 0, 0, 100, 0), +(@PATH, 19, -9731.375, 1527.3365, 45.070454, 0, 0, 0, 0, 100, 0), +(@PATH, 20, -9729.185, 1490.0042, 45.070454, 0, 0, 0, 0, 100, 0), +(@PATH, 21, -9745.345, 1485.0509, 45.487125, 0, 0, 0, 0, 100, 0); + +SET @PATH := (@NPC + 7) * 10; +DELETE FROM `waypoint_data` WHERE `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(@PATH, 1, -9745.88, 1488.399, 45.917397, 0, 0, 0, 0, 100, 0), +(@PATH, 2, -9744.661, 1507.4883, 46.028458, 0, 0, 0, 0, 100, 0), +(@PATH, 3, -9735.175, 1527.706, 43.806267, 0, 0, 0, 0, 100, 0), +(@PATH, 4, -9701.6455, 1545.9641, 44.3896, 0, 0, 0, 0, 100, 0), +(@PATH, 5, -9658.681, 1541.812, 43.472916, 0, 0, 0, 0, 100, 0), +(@PATH, 6, -9616.4375, 1554.6978, 41.278492, 0, 0, 0, 0, 100, 0), +(@PATH, 7, -9583.255, 1572.3322, 42.61181, 0, 0, 0, 0, 100, 0), +(@PATH, 8, -9594.106, 1611.233, 43.16736, 0, 0, 0, 0, 100, 0), +(@PATH, 9, -9626.409, 1625.0471, 40.945137, 0, 0, 0, 0, 100, 0), +(@PATH, 10, -9665.356, 1653.7917, 45.472958, 0, 0, 0, 0, 100, 0), +(@PATH, 11, -9684.14, 1617.8658, 42.111813, 0, 0, 0, 0, 100, 0), +(@PATH, 12, -9687.5625, 1573.8448, 43.97294, 0, 0, 0, 0, 100, 0), +(@PATH, 13, -9690.304, 1535.7795, 44.167366, 0, 0, 0, 0, 100, 0), +(@PATH, 14, -9711.632, 1498.4967, 41.334064, 0, 0, 0, 0, 100, 0), +(@PATH, 15, -9741.987, 1484.3424, 45.7785, 0, 0, 0, 0, 100, 0); + +DELETE FROM `creature_addon` WHERE `guid` = 144641; + +DELETE FROM `creature_template_movement` WHERE `CreatureId` = 15369; +INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Chase`, `Random`, `InteractionPauseTimer`) VALUES +(15369, 1, 0, 1, 0, 0, NULL); diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp index 1f2e880db..41204a176 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp @@ -18,7 +18,9 @@ #include "Player.h" #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "SpellScript.h" #include "ruins_of_ahnqiraj.h" +#include "TaskScheduler.h" enum Spells { @@ -28,22 +30,31 @@ enum Spells SPELL_FRENZY = 8269, SPELL_LASH = 25852, SPELL_FEED = 25721, + SPELL_THRASH = 3391, // Server-side spells - SPELL_SUMMON_LARVA_A = 26538, - SPELL_SUMMON_LARVA_B = 26539, - SPELL_LARVA_AGGRO_EFFECT = 25724, // Unknown purpose - SPELL_LARVA_FEAR_EFFECT = 25726, // Unknown purpose + SPELL_SUMMON_LARVA_A = 26538, + SPELL_SUMMON_LARVA_B = 26539, + SPELL_LARVA_AGGRO_EFFECT = 25724, // Unknown purpose + SPELL_LARVA_FEAR_EFFECT = 25726, // Unknown purpose + SPELL_SUMMON_HIVEZARA_SWARMER = 25708, + SPELL_HIVEZARA_SWARMER_TELEPORT_1 = 25709, + SPELL_HIVEZARA_SWARMER_TELEPORT_2 = 25825, + SPELL_HIVEZARA_SWARMER_TELEPORT_3 = 25826, + SPELL_HIVEZARA_SWARMER_TELEPORT_4 = 25827, + SPELL_HIVEZARA_SWARMER_TELEPORT_5 = 25828, + SPELL_HIVEZARA_SWARMER_TELEPORT_TRIGGER = 25830, + SPELL_HIVEZARA_SWARMER_START_LOOP = 25711, + SPELL_HIVEZARA_SWARMER_LOOP_1 = 25833, + SPELL_HIVEZARA_SWARMER_LOOP_2 = 25834, + SPELL_HIVEZARA_SWARMER_LOOP_3 = 25835, + SPELL_HIVEZARA_SWARMER_SWARM = 25844 }; -enum Events +enum Misc { - EVENT_STINGER_SPRAY = 1, - EVENT_POISON_STINGER = 2, - EVENT_SUMMON_SWARMER = 3, - EVENT_SWARMER_ATTACK = 4, - EVENT_PARALYZE = 5, - EVENT_LASH = 6 + MAX_SWARMER_COUNT = 28, + ACTION_SWARMER_SWARM = 1, }; enum Emotes @@ -66,8 +77,6 @@ enum Points const Position AyamissAirPos = { -9689.292f, 1547.912f, 48.02729f, 0.0f }; const Position AltarPos = { -9717.18f, 1517.72f, 27.4677f, 0.0f }; -/// @todo These below are probably incorrect, taken from SD2 -const Position SwarmerPos = { -9647.352f, 1578.062f, 55.32f, 0.0f }; struct boss_ayamiss : public BossAI { @@ -79,6 +88,7 @@ struct boss_ayamiss : public BossAI _phase = PHASE_AIR; _enraged = false; SetCombatMovement(false); + _scheduler.CancelAll(); } void JustSummoned(Creature* who) override @@ -86,12 +96,14 @@ struct boss_ayamiss : public BossAI switch (who->GetEntry()) { case NPC_HIVEZARA_SWARMER: + who->CastSpell(who, SPELL_HIVEZARA_SWARMER_TELEPORT_TRIGGER, true); _swarmers.push_back(who->GetGUID()); break; case NPC_HIVEZARA_LARVA: who->GetMotionMaster()->MovePoint(POINT_PARALYZE, AltarPos); break; } + summons.Summon(who); } @@ -104,6 +116,7 @@ struct boss_ayamiss : public BossAI else if (type == WAYPOINT_MOTION_TYPE && id == POINT_GROUND) { SetCombatMovement(true); + me->m_Events.AddEventAtOffset([this]() { if (me->GetVictim()) @@ -115,6 +128,55 @@ struct boss_ayamiss : public BossAI } } + void ScheduleTasks() + { + _scheduler.Schedule(20s, 30s, [this](TaskContext context) + { + DoCastSelf(SPELL_STINGER_SPRAY); + context.Repeat(15s, 20s); + }).Schedule(5s, [this](TaskContext context) { + DoCastVictim(SPELL_POISON_STINGER); + context.SetGroup(PHASE_AIR); + context.Repeat(2s, 3s); + }).Schedule(5s, [this](TaskContext context) { + DoCastAOE(SPELL_SUMMON_HIVEZARA_SWARMER, true); + + if (_swarmers.size() >= MAX_SWARMER_COUNT) + { + DoCastAOE(SPELL_HIVEZARA_SWARMER_SWARM, true); + } + + context.Repeat(RAND(2400ms, 3600ms)); + }).Schedule(15s, [this](TaskContext context) { + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0, true)) + { + DoCast(target, SPELL_PARALYZE, true); + instance->SetGuidData(DATA_PARALYZED, target->GetGUID()); + DoCastAOE(RAND(SPELL_SUMMON_LARVA_A, SPELL_SUMMON_LARVA_B), true); + } + context.Repeat(); + }); + } + + void DoAction(int32 action) override + { + if (action == ACTION_SWARMER_SWARM) + { + for (ObjectGuid const& guid : _swarmers) + { + if (Creature* swarmer = me->GetMap()->GetCreature(guid)) + { + if (Unit* target = SelectTarget(SelectTargetMethod::Random)) + { + swarmer->AI()->AttackStart(target); + } + } + } + + _swarmers.clear(); + } + } + void EnterEvadeMode(EvadeReason why) override { me->ClearUnitState(UNIT_STATE_ROOT); @@ -125,14 +187,10 @@ struct boss_ayamiss : public BossAI void EnterCombat(Unit* attacker) override { BossAI::EnterCombat(attacker); - events.ScheduleEvent(EVENT_STINGER_SPRAY, 20s, 30s); - events.ScheduleEvent(EVENT_POISON_STINGER, 5s); - events.ScheduleEvent(EVENT_SUMMON_SWARMER, 5s); - events.ScheduleEvent(EVENT_SWARMER_ATTACK, 60s); - events.ScheduleEvent(EVENT_PARALYZE, 15s); me->SetCanFly(true); me->SetDisableGravity(true); me->GetMotionMaster()->MovePoint(POINT_AIR, AyamissAirPos); + ScheduleTasks(); } void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType, SpellSchoolMask) override @@ -144,9 +202,19 @@ struct boss_ayamiss : public BossAI me->SetCanFly(false); me->SetDisableGravity(false); me->GetMotionMaster()->MovePath(me->GetEntry() * 10, false); - events.ScheduleEvent(EVENT_LASH, 5s, 8s); - events.CancelEvent(EVENT_POISON_STINGER); DoResetThreat(); + + _scheduler.Schedule(5s, 8s, [this](TaskContext context) { + DoCastVictim(SPELL_LASH); + context.Repeat(8s, 15s); + }).Schedule(16s, [this](TaskContext context) + { + DoCastSelf(SPELL_THRASH); + context.Repeat(); + }); + + _scheduler.DelayAll(5s); + _scheduler.CancelGroup(PHASE_AIR); } if (!_enraged && me->HealthBelowPctDamaged(20, damage)) @@ -162,66 +230,14 @@ struct boss_ayamiss : public BossAI if (!UpdateVictim()) return; - events.Update(diff); - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_STINGER_SPRAY: - DoCastSelf(SPELL_STINGER_SPRAY); - events.ScheduleEvent(EVENT_STINGER_SPRAY, 15s, 20s); - break; - case EVENT_POISON_STINGER: - DoCastVictim(SPELL_POISON_STINGER); - events.ScheduleEvent(EVENT_POISON_STINGER, 2s, 3s); - break; - case EVENT_PARALYZE: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0, true)) - { - DoCast(target, SPELL_PARALYZE, true); - instance->SetGuidData(DATA_PARALYZED, target->GetGUID()); - DoCastAOE(RAND(SPELL_SUMMON_LARVA_A, SPELL_SUMMON_LARVA_B), true); - } - events.ScheduleEvent(EVENT_PARALYZE, 15s); - break; - case EVENT_SWARMER_ATTACK: - for (ObjectGuid const& guid : _swarmers) - { - if (Creature* swarmer = me->GetMap()->GetCreature(guid)) - { - if (Unit* target = SelectTarget(SelectTargetMethod::Random)) - { - swarmer->AI()->AttackStart(target); - } - } - } - _swarmers.clear(); - events.ScheduleEvent(EVENT_SWARMER_ATTACK, 60s); - break; - case EVENT_SUMMON_SWARMER: - { - Position const offset = { 0.0f, 0.0f, 20.0f, 0.0f }; - Position spawnpos = me->GetRandomPoint(SwarmerPos, 80.0f); - spawnpos.RelocateOffset(offset); - if (Creature* wasp = me->SummonCreature(NPC_HIVEZARA_SWARMER, spawnpos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000)) - { - wasp->GetMotionMaster()->MoveRandom(10.0f); - } - events.ScheduleEvent(EVENT_SUMMON_SWARMER, 5s); - break; - } - case EVENT_LASH: - DoCastVictim(SPELL_LASH); - events.ScheduleEvent(EVENT_LASH, 8s, 15s); - break; - } - } - DoMeleeAttackIfReady(); + _scheduler.Update(diff, + std::bind(&BossAI::DoMeleeAttackIfReady, this)); } private: GuidList _swarmers; uint8 _phase; bool _enraged; + TaskScheduler _scheduler; Position homePos; }; @@ -234,14 +250,11 @@ struct npc_hive_zara_larva : public ScriptedAI void MovementInform(uint32 type, uint32 id) override { - if (type == POINT_MOTION_TYPE) + if (type == POINT_MOTION_TYPE && id == POINT_PARALYZE) { - if (id == POINT_PARALYZE) + if (Player* target = ObjectAccessor::GetPlayer(*me, _instance->GetGuidData(DATA_PARALYZED))) { - if (Player* target = ObjectAccessor::GetPlayer(*me, _instance->GetGuidData(DATA_PARALYZED))) - { - DoCast(target, SPELL_FEED); - } + DoCast(target, SPELL_FEED); } } } @@ -255,7 +268,6 @@ struct npc_hive_zara_larva : public ScriptedAI } void MoveInLineOfSight(Unit* who) override - { if (_instance->GetBossState(DATA_AYAMISS) == IN_PROGRESS) return; @@ -282,8 +294,151 @@ private: InstanceScript* _instance; }; +struct npc_hive_zara_swarmer : public ScriptedAI +{ + npc_hive_zara_swarmer(Creature* creature) : ScriptedAI(creature) { } + + void PathEndReached(uint32 /*pathId*/) override + { + // Delay is required because we are calling the movement generator from inside the pathing hook. + // If we issue another call here, it will be flushed before it is executed. + me->m_Events.AddEventAtOffset([this]() + { + DoCastSelf(SPELL_HIVEZARA_SWARMER_START_LOOP); + }, 1s); + } +}; + +struct WaspTeleportData +{ + uint32 spellId; + uint32 pathId; +}; + +class spell_ayamiss_swarmer_teleport_trigger : public SpellScript +{ + PrepareSpellScript(spell_ayamiss_swarmer_teleport_trigger); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo + ( { + SPELL_HIVEZARA_SWARMER_TELEPORT_1, SPELL_HIVEZARA_SWARMER_TELEPORT_2, + SPELL_HIVEZARA_SWARMER_TELEPORT_3, SPELL_HIVEZARA_SWARMER_TELEPORT_4, + SPELL_HIVEZARA_SWARMER_TELEPORT_5 + }); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + WaspTeleportData telData[5] = + { + { SPELL_HIVEZARA_SWARMER_TELEPORT_1, NPC_HIVEZARA_SWARMER * 10 }, + { SPELL_HIVEZARA_SWARMER_TELEPORT_2, (NPC_HIVEZARA_SWARMER + 1) * 10 }, + { SPELL_HIVEZARA_SWARMER_TELEPORT_3, (NPC_HIVEZARA_SWARMER + 2) * 10 }, + { SPELL_HIVEZARA_SWARMER_TELEPORT_4, (NPC_HIVEZARA_SWARMER + 3) * 10 }, + { SPELL_HIVEZARA_SWARMER_TELEPORT_5, (NPC_HIVEZARA_SWARMER + 4) * 10 } + }; + + WaspTeleportData data = Acore::Containers::SelectRandomContainerElement(telData); + caster->CastSpell((Unit*)nullptr, data.spellId, true); + + uint32 pathId = data.pathId; + caster->m_Events.AddEventAtOffset([caster, pathId]() + { + caster->GetMotionMaster()->MovePath(pathId, false); + }, 1s); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_ayamiss_swarmer_teleport_trigger::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + +class spell_ayamiss_swarmer_swarm : public SpellScript +{ + PrepareSpellScript(spell_ayamiss_swarmer_swarm); + + bool Load() override + { + return GetCaster()->GetEntry() == NPC_AYAMISS; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->ToCreature()->AI()->DoAction(ACTION_SWARMER_SWARM); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_ayamiss_swarmer_swarm::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +class spell_ayamiss_swarmer_start_loop : public SpellScript +{ + PrepareSpellScript(spell_ayamiss_swarmer_start_loop); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_HIVEZARA_SWARMER_LOOP_1, SPELL_HIVEZARA_SWARMER_LOOP_2, SPELL_HIVEZARA_SWARMER_LOOP_3 }); + } + + bool Load() override + { + return GetCaster()->GetEntry() == NPC_HIVEZARA_SWARMER; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + uint32 loopSpells[3] = { SPELL_HIVEZARA_SWARMER_LOOP_1, SPELL_HIVEZARA_SWARMER_LOOP_2, SPELL_HIVEZARA_SWARMER_LOOP_3 }; + GetCaster()->CastSpell((Unit*)nullptr, Acore::Containers::SelectRandomContainerElement(loopSpells)); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_ayamiss_swarmer_start_loop::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + +class spell_gen_ayamiss_swarmer_loop: public SpellScript +{ + PrepareSpellScript(spell_gen_ayamiss_swarmer_loop); + +public: + spell_gen_ayamiss_swarmer_loop(uint32 pathId) : SpellScript(), _pathId(pathId) { } + + bool Load() override + { + return GetCaster()->GetEntry() == NPC_HIVEZARA_SWARMER; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->ToCreature()->GetMotionMaster()->Clear(); + GetCaster()->ToCreature()->GetMotionMaster()->MovePath(_pathId, false); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_gen_ayamiss_swarmer_loop::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); + } + +private: + uint32 _pathId; +}; + void AddSC_boss_ayamiss() { RegisterRuinsOfAhnQirajCreatureAI(boss_ayamiss); RegisterRuinsOfAhnQirajCreatureAI(npc_hive_zara_larva); + RegisterRuinsOfAhnQirajCreatureAI(npc_hive_zara_swarmer); + RegisterSpellScript(spell_ayamiss_swarmer_teleport_trigger); + RegisterSpellScript(spell_ayamiss_swarmer_swarm); + RegisterSpellScript(spell_ayamiss_swarmer_start_loop); + RegisterSpellScriptWithArgs(spell_gen_ayamiss_swarmer_loop, "spell_gen_ayamiss_swarmer_loop_1", (NPC_HIVEZARA_SWARMER + 5) * 10); + RegisterSpellScriptWithArgs(spell_gen_ayamiss_swarmer_loop, "spell_gen_ayamiss_swarmer_loop_2", (NPC_HIVEZARA_SWARMER + 6) * 10); + RegisterSpellScriptWithArgs(spell_gen_ayamiss_swarmer_loop, "spell_gen_ayamiss_swarmer_loop_3", (NPC_HIVEZARA_SWARMER + 7) * 10); }