From b06352f41897d70b74ccef3eaba572865b7bd574 Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Sun, 13 Sep 2020 00:23:05 +0200 Subject: [PATCH] Scripts/ZA: implement Jan'alai encounter --- .../world/4.3.4/2020_09_13_00_world.sql | 79 +++ .../EasternKingdoms/ZulAman/boss_janalai.cpp | 546 +++++++++++++++++- .../ZulAman/instance_zulaman.cpp | 5 + .../scripts/EasternKingdoms/ZulAman/zulaman.h | 8 + 4 files changed, 624 insertions(+), 14 deletions(-) create mode 100644 sql/updates/world/4.3.4/2020_09_13_00_world.sql diff --git a/sql/updates/world/4.3.4/2020_09_13_00_world.sql b/sql/updates/world/4.3.4/2020_09_13_00_world.sql new file mode 100644 index 00000000000..5acb5355b82 --- /dev/null +++ b/sql/updates/world/4.3.4/2020_09_13_00_world.sql @@ -0,0 +1,79 @@ +UPDATE `creature_template` SET `DamageModifier`= 100, `BaseVariance`= 0.5, `flags_extra`= `flags_extra` | 0x800, `mechanic_immune_mask`= 667893631, `ScriptName`= 'boss_janalai' WHERE `entry`= 23578; +UPDATE `creature_template` SET `ScriptName`= 'npc_janalai_amanishi_hatcher', `RegenHealth`= 0, `flags_extra`= 0x100 | 0x40000000, `mechanic_immune_mask`= 42679163 WHERE `entry` IN (23818, 24504); +UPDATE `creature_template` SET `DamageModifier`= 8, `BaseVariance`= 0.5, `ScriptName`= 'npc_janalai_amani_dragonhawk_hatchling' WHERE `entry`= 23598; + +DELETE FROM `creature_text` WHERE `CreatureID`= 23578; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES +(23578, 0, 0, 'Come, friends. Your bodies gonna feed ma hatchlings, and your souls gonna fill me with power!', 14, 0, 100, 0, 0, 12040, 23313, 'Jan\'alai'), +(23578, 1, 0, 'Spirits of da wind be your doom!', 14, 0, 100, 0, 0, 12031, 23590, 'Jan\'alai'), +(23578, 2, 0, '%s goes into a frenzy!', 41, 0, 100, 0, 0, 0, 36719, 'Jan\'alai'), +(23578, 3, 0, 'I burn ya now!', 14, 0, 100, 0, 0, 12032, 23589, 'Jan\'alai'), +(23578, 4, 0, 'I show you strength... in numbers.', 14, 0, 100, 0, 0, 12034, 22838, 'Jan\'alai'), +(23578, 5, 0, 'Where ma hatcha? Get to work on dem eggs!', 14, 0, 100, 0, 0, 12033, 23528, 'Jan\'alai'), +(23578, 6, 0, 'It all be over now, mon!', 14, 0, 100, 0, 0, 12036, 23585, 'Jan\'alai'), +(23578, 7, 0, 'Tazaga-choo!', 14, 0, 100, 0, 0, 12037, 23586, 'Jan\'alai to Player'); + +DELETE FROM `spell_script_names` WHERE `ScriptName` IN +('spell_janalai_flame_breath', +'spell_janalai_fire_bomb', +'spell_janalai_firebomb_dummy', +'spell_janalai_hatch_all_eggs', +'spell_janalai_hatch_eggs'); + +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(43140, 'spell_janalai_flame_breath'), +(97855, 'spell_janalai_flame_breath'), +(42621, 'spell_janalai_fire_bomb'), +(42628, 'spell_janalai_firebomb_dummy'), +(43144, 'spell_janalai_hatch_all_eggs'), +(42471, 'spell_janalai_hatch_eggs'); + +DELETE FROM `conditions` WHERE `SourceEntry` IN (42631, 43144, 42471, 43962, 45340) AND `SourceTypeOrReferenceId`= 13; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ScriptName`, `Comment`) VALUES +(13, 1, 42631, 0, 0, 31, 0, 3, 23920, 0, 0, 0, '', 'Fire Bomb - Target Fire Bomb (Zul''Aman)'), +(13, 1, 43144, 0, 0, 31, 0, 3, 23817, 0, 0, 0, '', 'Hatch All Eggs - Target Dragonhawk Egg'), +(13, 1, 42471, 0, 0, 31, 0, 3, 23817, 0, 0, 0, '', 'Hatch Eggs - Target Dragonhawk Egg'), +(13, 1, 43962, 0, 0, 31, 0, 3, 22515, 0, 0, 0, '', 'Summon Aamani''shi Hatcher - Target World Trigger'), +(13, 1, 45340, 0, 0, 31, 0, 3, 22515, 0, 0, 0, '', 'Summon Aamani''shi Hatcher - Target World Trigger'); + +DELETE FROM `creature` WHERE `guid` IN (291804, 291805, 291806, 291807, 291808, 291809, 291810, 291811, 291812, 291813, 291814, 291815, 291816, 291817, 291818, 291819, 291820, 291821, 339092, 339093, 339094, 339095, 339096, 339097, 339098, 339099, 339100, 339101, 339102, 339103, 339104, 339105, 339106, 339107, 339108, 339109); +DELETE FROM `creature_addon` WHERE `guid` IN (291804, 291805, 291806, 291807, 291808, 291809, 291810, 291811, 291812, 291813, 291814, 291815, 291816, 291817, 291818, 291819, 291820, 291821, 339092, 339093, 339094, 339095, 339096, 339097, 339098, 339099, 339100, 339101, 339102, 339103, 339104, 339105, 339106, 339107, 339108, 339109); + +DELETE FROM `creature_summon_groups` WHERE `summonerId`= 23578 AND `summonerType`= 0; +INSERT INTO `creature_summon_groups` (`summonerId`, `summonerType`, `groupId`, `entry`, `position_x`, `position_y`, `position_z`, `orientation`, `summonType`, `summonTime`) VALUES +(23578, 0, 0, 23817, -28.0850696563720703, 1214.2236328125, 18.7946624755859375, 3.385938644409179687, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -34.4182929992675781, 1213.354736328125, 18.79468917846679687, 2.268928050994873046, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -39.7272148132324218, 1216.0911865234375, 18.79474067687988281, 5.585053443908691406, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -30.4304466247558593, 1216.3941650390625, 18.79466056823730468, 4.904375076293945312, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -32.0784492492675781, 1218.5543212890625, 18.79465866088867187, 5.654866695404052734, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -38.5763893127441406, 1218.6827392578125, 18.7947235107421875, 4.97418832778930664, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -28.0705299377441406, 1216.809814453125, 18.7946624755859375, 1.396263360977172851, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -29.8651256561279296, 1211.3843994140625, 18.79466438293457031, 2.94960641860961914, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -36.2872200012207031, 1218.10546875, 18.79469871520996093, 0.03490658476948738, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -27.0043411254882812, 1211.986083984375, 18.79466629028320312, 3.944444179534912109, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -32.7619361877441406, 1215.3272705078125, 18.79466438293457031, 2.809980154037475585, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -29.7243919372558593, 1208.43212890625, 18.79466819763183593, 4.939281940460205078, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -33.1212043762207031, 1209.771240234375, 18.79468345642089843, 2.775073528289794921, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -37.3368072509765625, 1212.525634765625, 18.79472160339355468, 0.314159274101257324, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -36.4397773742675781, 1209.9254150390625, 18.79470634460449218, 0.331612557172775268, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -39.3636054992675781, 1209.7332763671875, 18.79471206665039062, 0.593411922454833984, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -34.05859375, 1207.23291015625, 18.7946929931640625, 4.607669353485107421, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -38.9576835632324218, 1207.24609375, 18.79470634460449218, 4.066617012023925781, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -29.1756725311279296, 1090.2691650390625, 18.79482650756835937, 0.680678427219390869, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -33.5925559997558593, 1090.1617431640625, 18.79481697082519531, 5.131268024444580078, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -35.0347213745117187, 1084.9237060546875, 18.79476165771484375, 5.218534469604492187, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -38.2801666259765625, 1088.1441650390625, 18.79479789733886718, 1.274090290069580078, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -31.0390625, 1088.3272705078125, 18.7947998046875, 2.705260276794433593, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -40.0005416870117187, 1090.55224609375, 18.794830322265625, 1.117010712623596191, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -31.664712905883789, 1081.8824462890625, 18.7947845458984375, 6.17846536636352539, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -36.2433815002441406, 1088.146728515625, 18.79479598999023437, 1.727875947952270507, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -26.5745449066162109, 1084.4417724609375, 18.7948455810546875, 2.792526721954345703, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -33.6638450622558593, 1087.0233154296875, 18.7947845458984375, 0.959931075572967529, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -28.4201393127441406, 1082.093994140625, 18.7948455810546875, 4.014257431030273437, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -30.5146484375, 1084.7174072265625, 18.79480552673339843, 1.797689080238342285, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -40.7069244384765625, 1088.505126953125, 18.79483604431152343, 0.01745329238474369, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -38.8812942504882812, 1084.2034912109375, 18.79480934143066406, 0.575958669185638427, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -34.0567512512207031, 1082.0223388671875, 18.79473495483398437, 2.670353651046752929, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -41.1769752502441406, 1084.592529296875, 18.79484176635742187, 1.064650893211364746, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -39.7955741882324218, 1081.4669189453125, 18.79482841491699218, 2.740166902542114257, 6, 4000), -- 23817 (Area: 3805 - Difficulty: 2) +(23578, 0, 0, 23817, -42.8134765625, 1085.9434814453125, 18.79483985900878906, 2.042035102844238281, 6, 4000); -- 23817 (Area: 3805 - Difficulty: 2) diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_janalai.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_janalai.cpp index f1a420be913..0cabf7f33b1 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_janalai.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_janalai.cpp @@ -16,61 +16,579 @@ */ #include "ScriptMgr.h" -#include "CellImpl.h" -#include "GridNotifiers.h" +#include "ScriptedCreature.h" #include "InstanceScript.h" #include "MotionMaster.h" #include "ObjectAccessor.h" -#include "ScriptedCreature.h" -#include "TemporarySummon.h" +#include "PassiveAI.h" +#include "Spell.h" +#include "SpellAuraEffects.h" +#include "SpellScript.h" #include "zulaman.h" enum Texts { + // Jan'alai + SAY_INTRO = 0, + SAY_AGGRO = 1, + SAY_EMOTE_FRENZY = 2, + SAY_FIRE_BOMB = 3, + SAY_HATCH_ALL_EGGS = 4, + SAY_SUMMON_AMANI_HATCHER = 5, + SAY_SLAY = 6, + SAY_DEATH = 7 }; enum Spells { + // Jan'alai + SPELL_FLAME_BREATH = 43140, + SPELL_FLAME_BREATH_AREA_EFFECT = 97497, + SPELL_FRENZY = 44779, + SPELL_TELEPORT_TO_CENTER = 43098, + SPELL_SUMMON_ALL_PLAYERS = 43096, + SPELL_FIRE_BOMB = 42621, + SPELL_FIRE_BOMB_SUMMON_5YD = 42622, + SPELL_FIRE_BOMB_SUMMON_10YD = 42623, + SPELL_FIRE_BOMB_SUMMON_15YD = 42624, + SPELL_FIRE_BOMB_SUMMON_20YD = 42625, + SPELL_FIRE_BOMB_SUMMON_25YD = 42626, + SPELL_FIRE_BOMB_SUMMON_30YD = 42627, + SPELL_FIRE_BOMB_DUMMY_MISSILE = 42628, + SPELL_HATCH_ALL_EGGS = 43144, + SPELL_SUMMON_AMANISHI_HATCHER_1 = 43962, + SPELL_SUMMON_AMANISHI_HATCHER_2 = 45340, + + // Fire Bomb (Zul'Aman) + SPELL_FIRE_BOMB_VISUAL = 42629, + SPELL_FIRE_BOMB_AOE_DUMMY = 42631, + SPELL_FIRE_BOMB_DAMAGE = 42630, + + // Amani'shi Hatcher + SPELL_HATCH_EGGS = 42471, + + // Dragonhawk Egg + SPELL_SUMMON_DRAGONHAWK_HATCHLING = 42493, + + // Amani Dragonhawk Hatchling + SPELL_FLAME_BUFFET = 43299, + + // World Trigger (Not Immune PC) + SPELL_FIRE_WALL = 43113 }; enum Events { + // Jan'alai + EVENT_FLAME_BREATH = 1, + EVENT_TELEPORT_TO_CENTER, + EVENT_SUMMON_ALL_PLAYERS, + EVENT_FIRE_BOMB, + EVENT_DETONATE_FIRE_BOMBS, + EVENT_SUMMON_AMANISHI_HATCHER, + + // Amani'shi Hatcher + EVENT_MOVE_TO_EGGS, + EVENT_HATCH_EGGS, + + // Amani Dragonhawk Hatchling + EVENT_FLAME_BUFFET }; +enum MovePoints +{ + // Amani'shi Hatcher + POINT_DRAGONHAWK_EGGS_1 = 1, + POINT_DRAGONHAWK_EGGS_2 +}; + +enum Misc +{ + SUMMON_GROUP_DRAGONHAWK_EGGS = 0 +}; + +static constexpr uint8 MaxAmanishPathPoints = 2; +std::array AmanishiHatcherPath1 = +{ + Position(-55.058918f, 1147.5951f, 18.705215f), + Position(-35.54627f, 1104.8754f, 18.712082f) +}; + +std::array AmanishiHatcherPath2 = +{ + Position(-55.04731f, 1153.5928f, 18.705194f), + Position(-34.785084f, 1192.8384f, 18.71136f) +}; + +Position const FireWallReferencePos = { -34.719f, 1149.689f }; + struct boss_janalai : public BossAI { - boss_janalai(Creature* creature) : BossAI(creature, DATA_JANALAI) + boss_janalai(Creature* creature) : BossAI(creature, DATA_JANALAI), _frenzied(false), _hatchedAllEggs(false) { } + + void JustAppeared() override { - Initialize(); + me->SummonCreatureGroup(SUMMON_GROUP_DRAGONHAWK_EGGS); } - void Initialize() - { - } - - void Reset() override + void JustEngagedWith(Unit* who) override { + _JustEngagedWith(who); + Talk(SAY_AGGRO); + instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1); + events.ScheduleEvent(EVENT_FLAME_BREATH, 7s); + events.ScheduleEvent(EVENT_SUMMON_AMANISHI_HATCHER, 12s); + events.ScheduleEvent(EVENT_TELEPORT_TO_CENTER, 55s); } void JustDied(Unit* /*killer*/) override { + _JustDied(); + Talk(SAY_DEATH); + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); } - void KilledUnit(Unit* /*victim*/) override + void EnterEvadeMode(EvadeReason /*why*/) override { + _EnterEvadeMode(); + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + summons.DespawnAll(); + _DespawnAtEvade(); } - void JustEngagedWith(Unit* /*who*/) override + void KilledUnit(Unit* victim) override { + if (victim->IsPlayer()) + Talk(SAY_SLAY); } - void UpdateAI(uint32 /*diff*/) override + void DamageTaken(Unit* /*attacker*/, uint32& damage) override { + if (me->HasUnitState(UNIT_STATE_CASTING) || damage >= me->GetHealth()) + return; + if (!_frenzied && me->HealthBelowPctDamaged(20, damage)) + { + _frenzied = true; + DoCastSelf(SPELL_FRENZY, true); + Talk(SAY_EMOTE_FRENZY); + } + + if (!_hatchedAllEggs && me->HealthBelowPctDamaged(35, damage)) + { + _hatchedAllEggs = true; + DoCastAOE(SPELL_HATCH_ALL_EGGS, true); + Talk(SAY_HATCH_ALL_EGGS); + } + } + + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); + + switch (summon->GetEntry()) + { + case NPC_FIRE_BOMB_ZULAMAN: + DoCast(summon, SPELL_FIRE_BOMB_DUMMY_MISSILE); + break; + case NPC_AMANISHI_HATCHER_1: + case NPC_AMANISHI_HATCHER_2: + case NPC_AMANI_DRAGONHAWK_HATCHLING: + summon->SetCorpseDelay(4); // 4s ToDo: validate + break; + default: + break; + } + } + + 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_FLAME_BREATH: + // Flame Breath targets non-tank targets only. + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.f, true, false)) + { + me->SetFacingToObject(target); + DoCast(target, SPELL_FLAME_BREATH); + } + events.Repeat(8s); + break; + case EVENT_TELEPORT_TO_CENTER: + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + Talk(SAY_FIRE_BOMB); + DoCastSelf(SPELL_TELEPORT_TO_CENTER); + events.ScheduleEvent(EVENT_SUMMON_ALL_PLAYERS, 1s); + events.ScheduleEvent(EVENT_FIRE_BOMB, 2s + 500ms); + events.RescheduleEvent(EVENT_FLAME_BREATH, 16s); + events.Repeat(30s); + break; + case EVENT_SUMMON_ALL_PLAYERS: + DoCastAOE(SPELL_SUMMON_ALL_PLAYERS); + break; + case EVENT_FIRE_BOMB: + { + DoCastSelf(SPELL_FIRE_BOMB); + me->SetReactState(REACT_AGGRESSIVE); + events.ScheduleEvent(EVENT_DETONATE_FIRE_BOMBS, 10s); + + std::vector triggerList; + me->GetCreatureListWithEntryInGrid(triggerList, NPC_WORLD_TRIGGER_NOT_IMMUNE_PC, 30.f); + for (Creature* trigger : triggerList) + if (FireWallReferencePos.GetExactDist2d(trigger) > 10.f) + trigger->CastSpell(trigger, SPELL_FIRE_WALL); + break; + } + case EVENT_DETONATE_FIRE_BOMBS: + for (SummonList::iterator itr = summons.begin(); itr != summons.end();) + { + if (itr->GetEntry() != NPC_FIRE_BOMB_ZULAMAN) + { + ++itr; + continue; + } + + if (Creature* bomb = ObjectAccessor::GetCreature(*me, *itr)) + { + bomb->CastSpell(bomb, SPELL_FIRE_BOMB_AOE_DUMMY); + bomb->CastSpell(bomb, SPELL_FIRE_BOMB_DAMAGE); + bomb->RemoveAllAuras(); + bomb->DespawnOrUnsummon(4s); + itr = summons.erase(itr); + } + else + ++itr; + } + break; + case EVENT_SUMMON_AMANISHI_HATCHER: + if (!_hatchedAllEggs && (!summons.HasEntry(NPC_AMANISHI_HATCHER_1) || !summons.HasEntry(NPC_AMANISHI_HATCHER_2))) + { + Talk(SAY_SUMMON_AMANI_HATCHER); + DoCastAOE(SPELL_SUMMON_AMANISHI_HATCHER_1); + DoCastAOE(SPELL_SUMMON_AMANISHI_HATCHER_2); + events.Repeat(60s); + } + else if (!_hatchedAllEggs) + events.Repeat(30s); + break; + default: + break; + } + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + } + + DoMeleeAttackIfReady(); + } +private: + bool _frenzied; + bool _hatchedAllEggs; +}; + +struct npc_janalai_amanishi_hatcher : public PassiveAI +{ + npc_janalai_amanishi_hatcher(Creature* creature) : PassiveAI(creature) { } + + void JustAppeared() override + { + if (me->GetEntry() == NPC_AMANISHI_HATCHER_1) + me->GetMotionMaster()->MovePoint(POINT_DRAGONHAWK_EGGS_1, AmanishiHatcherPath1[0]); + else + me->GetMotionMaster()->MovePoint(POINT_DRAGONHAWK_EGGS_1, AmanishiHatcherPath2[0]); + } + + void MovementInform(uint32 motionType, uint32 pointId) override + { + if (motionType != POINT_MOTION_TYPE) + return; + + switch (pointId) + { + case POINT_DRAGONHAWK_EGGS_1: + _events.ScheduleEvent(EVENT_MOVE_TO_EGGS, 1s + 500ms); + break; + case POINT_DRAGONHAWK_EGGS_2: + _events.ScheduleEvent(EVENT_HATCH_EGGS, 1ms); + break; + default: + break; + } + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_MOVE_TO_EGGS: + { + Creature* egg = me->FindNearestCreature(NPC_DRAGONHAWK_EGG, 100.f); + if (me->GetEntry() == NPC_AMANISHI_HATCHER_1) + { + if (!egg || (egg && egg->GetExactDist2d(AmanishiHatcherPath1[1]) < egg->GetExactDist2d(AmanishiHatcherPath2[1]))) + me->GetMotionMaster()->MovePoint(POINT_DRAGONHAWK_EGGS_2, AmanishiHatcherPath1[1]); + else if (egg) + me->GetMotionMaster()->MovePoint(POINT_DRAGONHAWK_EGGS_2, AmanishiHatcherPath2[1]); + } + else + { + if (!egg || (egg && egg->GetExactDist2d(AmanishiHatcherPath2[1]) < egg->GetExactDist2d(AmanishiHatcherPath1[1]))) + me->GetMotionMaster()->MovePoint(POINT_DRAGONHAWK_EGGS_2, AmanishiHatcherPath2[1]); + else if (egg) + me->GetMotionMaster()->MovePoint(POINT_DRAGONHAWK_EGGS_2, AmanishiHatcherPath1[1]); + } + break; + } + case EVENT_HATCH_EGGS: + DoCastAOE(SPELL_HATCH_EGGS); + _events.Repeat(5s); + break; + default: + break; + } + } + } + +private: + EventMap _events; +}; + +struct npc_janalai_amani_dragonhawk_hatchling : public ScriptedAI +{ + npc_janalai_amani_dragonhawk_hatchling(Creature* creature) : ScriptedAI(creature) { } + + void JustAppeared() override + { + DoZoneInCombat(); + _events.ScheduleEvent(EVENT_FLAME_BUFFET, 6s); + } + + 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_FLAME_BUFFET: + DoCastVictim(SPELL_FLAME_BUFFET); + _events.Repeat(6s); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + +private: + EventMap _events; +}; + +class spell_janalai_flame_breath : public SpellScript +{ + void ModifyDestination(SpellDestination& dest) + { + float x = 0.f, y = 0.f, z = 0.f, o = 0.f; + GetCaster()->GetPosition(x, y, z, o); + x += std::cos(o) * 30.f; + y += std::sin(o) * 30.f; + dest.Relocate({ x, y, z }); + + // We have our destination now, no need to keep our object target anymore. + GetSpell()->m_targets.RemoveObjectTarget(); + } + + void Register() + { + OnDestinationTargetSelect.Register(&spell_janalai_flame_breath::ModifyDestination, EFFECT_0, TARGET_DEST_TARGET_ENEMY); + } +}; + +static constexpr uint8 MAX_FLAME_BREATH_AREAS = 9; + +class spell_janalai_flame_breath_AuraScript : public AuraScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_FLAME_BREATH_AREA_EFFECT }); + } + + void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Position const casterPosition = GetTarget()->GetPosition(); + + // Initialize target destinations for the upcoming ticks + for (uint8 i = 0; i < _castDestinations.size(); ++i) + { + _castDestinations[i] = casterPosition; + _castDestinations[i].m_positionX += std::cos(casterPosition.GetOrientation()) * (4.f * i); + _castDestinations[i].m_positionY += std::sin(casterPosition.GetOrientation()) * (4.f * i); + } + } + + void HandlePeriodicTick(AuraEffect const* aurEff) + { + uint32 tickNumber = aurEff->GetTickNumber(); + if (tickNumber > _castDestinations.size()) + return; + + float x = 0.f, y = 0.f, z = 0.f; + _castDestinations[tickNumber - 1].GetPosition(x, y, z); + GetTarget()->CastSpell(x, y, z, SPELL_FLAME_BREATH_AREA_EFFECT); + } + + void Register() override + { + AfterEffectApply.Register(&spell_janalai_flame_breath_AuraScript::AfterApply, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); + OnEffectPeriodic.Register(&spell_janalai_flame_breath_AuraScript::HandlePeriodicTick, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY); + } + +private: + std::array _castDestinations; +}; + +class spell_janalai_fire_bomb : public AuraScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo( + { + SPELL_FIRE_BOMB_SUMMON_5YD, + SPELL_FIRE_BOMB_SUMMON_10YD, + SPELL_FIRE_BOMB_SUMMON_15YD, + SPELL_FIRE_BOMB_SUMMON_20YD, + SPELL_FIRE_BOMB_SUMMON_25YD, + SPELL_FIRE_BOMB_SUMMON_30YD + }); + } + + void HandlePeriodicTick(AuraEffect const* aurEff) + { + Unit* target = GetTarget(); + uint32 const tick = aurEff->GetTickNumber(); + + if (tick < 5) + target->CastSpell(target, SPELL_FIRE_BOMB_SUMMON_5YD); + else if (tick < 10) + target->CastSpell(target, SPELL_FIRE_BOMB_SUMMON_10YD); + else if (tick < 20) + target->CastSpell(target, SPELL_FIRE_BOMB_SUMMON_15YD); + else if (tick < 30) + target->CastSpell(target, SPELL_FIRE_BOMB_SUMMON_20YD); + else if (tick < 40) + target->CastSpell(target, SPELL_FIRE_BOMB_SUMMON_25YD); + else if (tick < 50) + target->CastSpell(target, SPELL_FIRE_BOMB_SUMMON_30YD); + else + Remove(); + } + + void Register() override + { + OnEffectPeriodic.Register(&spell_janalai_fire_bomb::HandlePeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } +}; + +class spell_janalai_firebomb_dummy : public SpellScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_FIRE_BOMB_VISUAL }); + } + + void HandleDummyEffect(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_FIRE_BOMB_VISUAL); + } + + void Register() override + { + OnEffectHitTarget.Register(&spell_janalai_firebomb_dummy::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +class spell_janalai_hatch_all_eggs : public SpellScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_SUMMON_DRAGONHAWK_HATCHLING }); + } + + void HandleDummyEffect(SpellEffIndex /*effIndex*/) + { + if (Creature* creature = GetHitCreature()) + creature->CastSpell(creature, SPELL_SUMMON_DRAGONHAWK_HATCHLING); + } + + void Register() override + { + OnEffectHitTarget.Register(&spell_janalai_hatch_all_eggs::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +class spell_janalai_hatch_eggs : public SpellScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_SUMMON_DRAGONHAWK_HATCHLING }); + } + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster())); + + if (targets.size() > 3) + targets.resize(3); + } + + void HandleDummyEffect(SpellEffIndex /*effIndex*/) + { + if (Creature* creature = GetHitCreature()) + creature->CastSpell(creature, SPELL_SUMMON_DRAGONHAWK_HATCHLING); + } + + void Register() override + { + OnObjectAreaTargetSelect.Register(&spell_janalai_hatch_eggs::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnEffectHitTarget.Register(&spell_janalai_hatch_eggs::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY); } }; void AddSC_boss_janalai() { RegisterZulAamanCreatureAI(boss_janalai); + RegisterZulAamanCreatureAI(npc_janalai_amanishi_hatcher); + RegisterZulAamanCreatureAI(npc_janalai_amani_dragonhawk_hatchling); + RegisterSpellAndAuraScriptPair(spell_janalai_flame_breath, spell_janalai_flame_breath_AuraScript); + RegisterSpellScript(spell_janalai_fire_bomb); + RegisterSpellScript(spell_janalai_firebomb_dummy); + RegisterSpellScript(spell_janalai_hatch_all_eggs); + RegisterSpellScript(spell_janalai_hatch_eggs); } diff --git a/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp b/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp index 18fdf330389..42a9ac67cfa 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp @@ -103,6 +103,11 @@ public: if (creature->GetExactDist2d(AmanishiSavageDistanceCheckPos) < 100.0f) _amanishiSavageGUIDs.push_back(creature->GetGUID()); break; + case NPC_AMANI_DRAGONHAWK_HATCHLING: + if (Creature* janalai = GetCreature(DATA_JANALAI)) + if (janalai->IsAIEnabled) + janalai->AI()->JustSummoned(creature); + break; default: break; } diff --git a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.h b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.h index 1b9e4c913ca..4b70d31dc12 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.h +++ b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.h @@ -58,6 +58,14 @@ enum ZACreatureIds /*Akil'zon*/ NPC_SOARING_EAGLE = 24858, + /*Jan'alai*/ + NPC_FIRE_BOMB_ZULAMAN = 23920, + NPC_WORLD_TRIGGER_NOT_IMMUNE_PC = 21252, + NPC_AMANISHI_HATCHER_1 = 23818, + NPC_AMANISHI_HATCHER_2 = 24504, + NPC_AMANI_DRAGONHAWK_HATCHLING = 23598, + NPC_DRAGONHAWK_EGG = 23817, + NPC_VOLJIN = 52924, NPC_HEXLORD_MALACRASS_TRIGGER = 24363, NPC_AMANISHI_GUARDIAN = 23597,