Scripts/Zul'Aman: Rewrite Jan'alai (#31857)

(cherry picked from commit f8d7962cd107b0dd90a354c6191ecc7cdda08950)
This commit is contained in:
offl
2026-07-23 01:37:06 +02:00
committed by Shauren
parent 01253c4ad8
commit 3de931116b
3 changed files with 737 additions and 64 deletions
@@ -0,0 +1,154 @@
--
SET @SPAWN_GROUP_ID := 376; -- 1
-- Jan'alai
UPDATE `creature_template_difficulty` SET `LevelScalingDeltaMin`=2, `LevelScalingDeltaMax`=2, `ContentTuningID`=1112, `DamageModifier`=35, `GoldMin`=80000, `GoldMax`=100000, `StaticFlags1`=0x10080000, `VerifiedBuild`=68453 WHERE `Entry`=23578 AND `DifficultyID`=2;
UPDATE `creature` SET `guid`=89322 WHERE `guid`=339123 AND `id`=23578;
DELETE FROM `creature_text` WHERE `CreatureID` = 23578 AND `GroupID` IN (7,8);
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(23578,7,0,"Come, strangers. The spirit of da dragonhawk be hungry for worthy souls.",14,0,100,0,0,12039,23314,0,"janalai SAY_EVENT_1"),
(23578,7,1,"Come, friends. Your bodies gonna feed ma hatchlings, and your souls gonna fill me with power!",14,0,100,0,0,12040,23313,0,"janalai SAY_EVENT_2"),
(23578,8,0,"%s goes into a frenzy!",41,0,100,0,0,0,10645,0,"janalai EMOTE_FRENZY");
-- Amani Dragonhawk Hatchling
UPDATE `creature_template` SET `speed_walk` = 1, `ScriptName` = 'npc_amani_dragonhawk_hatchling' WHERE `entry` = 23598;
UPDATE `creature_template_difficulty` SET `ContentTuningID`=1112, `StaticFlags1`=0x10080000, `VerifiedBuild`=68453 WHERE `Entry`=23598 AND `DifficultyID`=2; -- 23598 (Amani Dragonhawk Hatchling) - CanSwim
UPDATE `creature_model_info` SET `BoundingRadius` = 0.165, `CombatReach` = 0.82500005 WHERE `DisplayID` = 17546;
-- Dragonhawk Egg
UPDATE `creature_template` SET `ScriptName` = 'npc_dragonhawk_egg' WHERE `entry` = 23817;
UPDATE `creature_template_addon` SET `PvpFlags`=0 WHERE `entry` IN (24312,23817);
UPDATE `creature_model_info` SET `BoundingRadius`=0.167448967695236206, `CombatReach`=0.837244868278503417, `VerifiedBuild`=68453 WHERE `DisplayID`=37574;
DELETE FROM `creature` WHERE `id`=23817;
INSERT INTO `creature` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnDifficulties`, `phaseId`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `MovementType`, `ScriptName`, `StringId`, `VerifiedBuild`) VALUES
(89226, 23817, 568, 0, 0, '2', 0, 0, 0, -38.8813, 1084.2, 18.7948, 0.575959, 7200, 0, 0, 0, '', 'JanalaiEggsR', 0),
(89227, 23817, 568, 0, 0, '2', 0, 0, 0, -40.7069, 1088.51, 18.7948, 0.017453, 7200, 0, 0, 0, '', 'JanalaiEggsR', 0),
(89228, 23817, 568, 0, 0, '2', 0, 0, 0, -38.9577, 1207.25, 18.7947, 4.06662, 7200, 0, 0, 0, '', 'JanalaiEggsL', 0),
(89300, 23817, 568, 0, 0, '2', 0, 0, 0, -38.2802, 1088.14, 18.7948, 1.27409, 7200, 0, 0, 0, '', 'JanalaiEggsR', 0),
-- (89301, 23817, 568, 0, 0, '2', 0, 0, 0, -39.536, 1213.3, 18.7947, 5.58505, 7200, 0, 0, 0, '', 'JanalaiEggsL', 0),
(89302, 23817, 568, 0, 0, '2', 0, 0, 0, -38.5764, 1218.68, 18.7947, 4.97419, 7200, 0, 0, 0, '', 'JanalaiEggsL', 0),
(89314, 23817, 568, 0, 0, '2', 0, 0, 0, -42.8135, 1085.94, 18.7948, 2.04204, 7200, 0, 0, 0, '', 'JanalaiEggsR', 0),
-- (89315, 23817, 568, 0, 0, '2', 0, 0, 0, -37.6035, 1085.87, 18.7948, 0.296706, 7200, 0, 0, 0, '', 'JanalaiEggsR', 0),
(89316, 23817, 568, 0, 0, '2', 0, 0, 0, -36.2872, 1218.11, 18.7947, 0.034907, 7200, 0, 0, 0, '', 'JanalaiEggsL', 0),
(89317, 23817, 568, 0, 0, '2', 0, 0, 0, -39.7272, 1216.09, 18.7947, 5.58505, 7200, 0, 0, 0, '', 'JanalaiEggsL', 0),
(89319, 23817, 568, 0, 0, '2', 0, 0, 0, -39.7956, 1081.47, 18.7948, 2.74017, 7200, 0, 0, 0, '', 'JanalaiEggsR', 0),
(89320, 23817, 568, 0, 0, '2', 0, 0, 0, -39.3636, 1209.73, 18.7947, 0.593412, 7200, 0, 0, 0, '', 'JanalaiEggsL', 0),
(89321, 23817, 568, 0, 0, '2', 0, 0, 0, -37.3368, 1212.53, 18.7947, 0.314159, 7200, 0, 0, 0, '', 'JanalaiEggsL', 0),
(89323, 23817, 568, 0, 0, '2', 0, 0, 0, -41.177, 1084.59, 18.7948, 1.06465, 7200, 0, 0, 0, '', 'JanalaiEggsR', 0),
(89328, 23817, 568, 0, 0, '2', 0, 0, 0, -36.4398, 1209.93, 18.7947, 0.331613, 7200, 0, 0, 0, '', 'JanalaiEggsL', 0),
(89332, 23817, 568, 0, 0, '2', 0, 0, 0, -40.0005, 1090.55, 18.7948, 1.11701, 7200, 0, 0, 0, '', 'JanalaiEggsR', 0),
(89333, 23817, 568, 0, 0, '2', 0, 0, 0, -33.6638, 1087.02, 18.7948, 0.959931, 7200, 0, 0, 0, '', 'JanalaiEggsR', 0),
(89334, 23817, 568, 0, 0, '2', 0, 0, 0, -36.2434, 1088.15, 18.7948, 1.72788, 7200, 0, 0, 0, '', 'JanalaiEggsR', 0),
(89335, 23817, 568, 0, 0, '2', 0, 0, 0, -31.0391, 1088.33, 18.7948, 2.70526, 7200, 0, 0, 0, '', 'JanalaiEggsR', 0),
(89336, 23817, 568, 0, 0, '2', 0, 0, 0, -35.0347, 1084.92, 18.7948, 5.21853, 7200, 0, 0, 0, '', 'JanalaiEggsR', 0),
(89337, 23817, 568, 0, 0, '2', 0, 0, 0, -28.4201, 1082.09, 18.7948, 4.01426, 7200, 0, 0, 0, '', 'JanalaiEggsR', 0),
(89338, 23817, 568, 0, 0, '2', 0, 0, 0, -30.5146, 1084.72, 18.7948, 1.79769, 7200, 0, 0, 0, '', 'JanalaiEggsR', 0),
(89339, 23817, 568, 0, 0, '2', 0, 0, 0, -34.0568, 1082.02, 18.7947, 2.67035, 7200, 0, 0, 0, '', 'JanalaiEggsR', 0),
(89340, 23817, 568, 0, 0, '2', 0, 0, 0, -31.6647, 1081.88, 18.7948, 6.17846, 7200, 0, 0, 0, '', 'JanalaiEggsR', 0),
(89341, 23817, 568, 0, 0, '2', 0, 0, 0, -33.5926, 1090.16, 18.7948, 5.13127, 7200, 0, 0, 0, '', 'JanalaiEggsR', 0),
(89342, 23817, 568, 0, 0, '2', 0, 0, 0, -29.1757, 1090.27, 18.7948, 0.680678, 7200, 0, 0, 0, '', 'JanalaiEggsR', 0),
(89343, 23817, 568, 0, 0, '2', 0, 0, 0, -33.1212, 1209.77, 18.7947, 2.77507, 7200, 0, 0, 0, '', 'JanalaiEggsL', 0),
(89344, 23817, 568, 0, 0, '2', 0, 0, 0, -28.0851, 1214.22, 18.7947, 3.38594, 7200, 0, 0, 0, '', 'JanalaiEggsL', 0),
(89345, 23817, 568, 0, 0, '2', 0, 0, 0, -27.0043, 1211.99, 18.7947, 3.94444, 7200, 0, 0, 0, '', 'JanalaiEggsL', 0),
(89346, 23817, 568, 0, 0, '2', 0, 0, 0, -29.8651, 1211.38, 18.7947, 2.94961, 7200, 0, 0, 0, '', 'JanalaiEggsL', 0),
(89347, 23817, 568, 0, 0, '2', 0, 0, 0, -29.7244, 1208.43, 18.7947, 4.93928, 7200, 0, 0, 0, '', 'JanalaiEggsL', 0),
(89348, 23817, 568, 0, 0, '2', 0, 0, 0, -34.0586, 1207.23, 18.7947, 4.60767, 7200, 0, 0, 0, '', 'JanalaiEggsL', 0),
(89349, 23817, 568, 0, 0, '2', 0, 0, 0, -28.0705, 1216.81, 18.7947, 1.39626, 7200, 0, 0, 0, '', 'JanalaiEggsL', 0),
(89350, 23817, 568, 0, 0, '2', 0, 0, 0, -30.4304, 1216.39, 18.7947, 4.90438, 7200, 0, 0, 0, '', 'JanalaiEggsL', 0),
-- (89351, 23817, 568, 0, 0, '2', 0, 0, 0, -32.37, 1212.68, 18.7947, 1.0472, 7200, 0, 0, 0, '', 'JanalaiEggsL', 0),
(89352, 23817, 568, 0, 0, '2', 0, 0, 0, -32.0784, 1218.55, 18.7947, 5.65487, 7200, 0, 0, 0, '', 'JanalaiEggsL', 0),
(89353, 23817, 568, 0, 0, '2', 0, 0, 0, -34.4183, 1213.35, 18.7947, 2.26893, 7200, 0, 0, 0, '', 'JanalaiEggsL', 0),
(89354, 23817, 568, 0, 0, '2', 0, 0, 0, -32.7619, 1215.33, 18.7947, 2.80998, 7200, 0, 0, 0, '', 'JanalaiEggsL', 0),
(89355, 23817, 568, 0, 0, '2', 0, 0, 0, -26.5745, 1084.44, 18.7948, 2.79253, 7200, 0, 0, 0, '', 'JanalaiEggsR', 0);
-- (89356, 23817, 568, 0, 0, '2', 0, 0, 0, -27.2051, 1087.54, 18.7948, 1.76278, 7200, 0, 0, 0, '', 'JanalaiEggsR', 0);
DELETE FROM `spawn_group` WHERE `spawnId` IN (89226,89227,89228,89300,89301,89302,89314,89315,89316,89317,89319,89320,89321,89323,89328,89332,89333,89334,89335,89336,89337,89338,89339,89340,89341,89342,89343,89344,89345,89346,89347,89348,89349,89350,89351,89352,89353,89354,89355,89356) AND `spawnType` = 0;
INSERT INTO `spawn_group` (`groupId`, `spawnType`, `spawnId`) VALUES
(@SPAWN_GROUP_ID+0,0,89226),
(@SPAWN_GROUP_ID+0,0,89227),
(@SPAWN_GROUP_ID+0,0,89228),
(@SPAWN_GROUP_ID+0,0,89300),
-- (@SPAWN_GROUP_ID+0,0,89301),
(@SPAWN_GROUP_ID+0,0,89302),
(@SPAWN_GROUP_ID+0,0,89314),
-- (@SPAWN_GROUP_ID+0,0,89315),
(@SPAWN_GROUP_ID+0,0,89316),
(@SPAWN_GROUP_ID+0,0,89317),
(@SPAWN_GROUP_ID+0,0,89319),
(@SPAWN_GROUP_ID+0,0,89320),
(@SPAWN_GROUP_ID+0,0,89321),
(@SPAWN_GROUP_ID+0,0,89323),
(@SPAWN_GROUP_ID+0,0,89328),
(@SPAWN_GROUP_ID+0,0,89332),
(@SPAWN_GROUP_ID+0,0,89333),
(@SPAWN_GROUP_ID+0,0,89334),
(@SPAWN_GROUP_ID+0,0,89335),
(@SPAWN_GROUP_ID+0,0,89336),
(@SPAWN_GROUP_ID+0,0,89337),
(@SPAWN_GROUP_ID+0,0,89338),
(@SPAWN_GROUP_ID+0,0,89339),
(@SPAWN_GROUP_ID+0,0,89340),
(@SPAWN_GROUP_ID+0,0,89341),
(@SPAWN_GROUP_ID+0,0,89342),
(@SPAWN_GROUP_ID+0,0,89343),
(@SPAWN_GROUP_ID+0,0,89344),
(@SPAWN_GROUP_ID+0,0,89345),
(@SPAWN_GROUP_ID+0,0,89346),
(@SPAWN_GROUP_ID+0,0,89347),
(@SPAWN_GROUP_ID+0,0,89348),
(@SPAWN_GROUP_ID+0,0,89349),
(@SPAWN_GROUP_ID+0,0,89350),
-- (@SPAWN_GROUP_ID+0,0,89351),
(@SPAWN_GROUP_ID+0,0,89352),
(@SPAWN_GROUP_ID+0,0,89353),
(@SPAWN_GROUP_ID+0,0,89354),
(@SPAWN_GROUP_ID+0,0,89355);
-- (@SPAWN_GROUP_ID+0,0,89356);
DELETE FROM `spawn_group_template` WHERE `groupId` = @SPAWN_GROUP_ID+0;
INSERT INTO `spawn_group_template` (`groupId`, `groupName`, `groupFlags`) VALUES
(@SPAWN_GROUP_ID+0,"Zul'Aman - Dragonhawk Eggs",4);
-- Amani'shi Hatcher
UPDATE `creature_template` SET `speed_walk` = 1, `ScriptName` = 'npc_amanishi_hatcher' WHERE `entry` IN (23818,24504);
UPDATE `creature_template_difficulty` SET `ContentTuningID`=1112, `StaticFlags1`=0x10080000, `VerifiedBuild`=68453 WHERE `Entry` IN (23818,24504) AND `DifficultyID`=2;
UPDATE `creature` SET `guid` = 86476, `StringId` = 'AmanishiHatcherTrigger' WHERE `guid` = 339110 AND `id` = 22515;
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 13 AND `SourceEntry` IN (43962,45340);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`ConditionStringValue1`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES
(13,1,43962,0,0,58,0,0,0,0,"AmanishiHatcherTrigger",0,0,0,"","Group 0: Spell 'Summon Amani'shi Hatcher' (Effect 0) targets creature 'World Trigger'"),
(13,1,45340,0,0,58,0,0,0,0,"AmanishiHatcherTrigger",0,0,0,"","Group 0: Spell 'Summon Amani'shi Hatcher' (Effect 0) targets creature 'World Trigger'");
-- Fire Bomb (Zul'Aman)
UPDATE `creature_template` SET `speed_walk`=1, `unit_flags2`=0x0, `ScriptName` = 'npc_fire_bomb_zulaman' WHERE `entry` = 23920;
UPDATE `creature_template_difficulty` SET `ContentTuningID`=261, `StaticFlags1`=0x20000100, `VerifiedBuild`=68453 WHERE `Entry`=23920 AND `DifficultyID`=0;
-- Misc
UPDATE `spell_target_position` SET `PositionX` = -34.6677, `PositionY` = 1149.56, `PositionZ` = 19.1438, `Orientation` = 3.14159, `VerifiedBuild` = 15595 WHERE `ID` = 43098;
UPDATE `creature` SET `guid`=86475 WHERE `guid`=339089 AND `id`=21252;
UPDATE `creature` SET `guid`=130814 WHERE `guid`=339071 AND `id`=21252;
UPDATE `creature` SET `guid`=86474 WHERE `guid`=339072 AND `id`=21252;
UPDATE `creature` SET `guid`=86477 WHERE `guid`=339065 AND `id`=21252;
UPDATE `creature` SET `guid`=86478 WHERE `guid`=339069 AND `id`=21252;
UPDATE `creature` SET `StringId` = 'JanalaiFireWallTrigger' WHERE `guid` IN (86474,86475,86477,86478) AND `id` = 21252;
UPDATE `creature` SET `StringId` = 'JanalaiEggsR' WHERE `guid` IN (89226,89227,89300,89314,89315,89319,89323,89332,89333,89334,89335,89336,89337,89338,89339,89340,89341,89342,89355,89356) AND `id` = 23817;
UPDATE `creature` SET `StringId` = 'JanalaiEggsL' WHERE `guid` IN (89228,89301,89302,89316,89317,89320,89321,89328,89343,89344,89345,89346,89347,89348,89349,89350,89351,89352,89353,89354) AND `id` = 23817;
-- Spell scripts
DELETE FROM `spell_script_names` WHERE `ScriptName` IN (
'spell_janalai_summon_all_players',
'spell_janalai_fire_bomb',
'spell_janalai_hatch_eggs');
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
(43096, 'spell_janalai_summon_all_players'),
(42621, 'spell_janalai_fire_bomb'),
(42471, 'spell_janalai_hatch_eggs');
@@ -23,14 +23,17 @@
*/
#include "ScriptMgr.h"
#include "AreaTrigger.h"
#include "AreaTriggerAI.h"
#include "Containers.h"
#include "InstanceScript.h"
#include "Map.h"
#include "MotionMaster.h"
#include "PassiveAI.h"
#include "ScriptedCreature.h"
#include "SpellAuraEffects.h"
#include "SpellInfo.h"
#include "SpellMgr.h"
#include "SpellScript.h"
#include "zulaman.h"
@@ -15,60 +15,231 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Combat timers requires to be revisited
* SAY_EVENT is NYI
* Boundary is NYI
* Purpose of SPELL_FIRE_BOMB_DUMMY is unknown
*/
#include "ScriptMgr.h"
#include "Containers.h"
#include "InstanceScript.h"
#include "Map.h"
#include "MotionMaster.h"
#include "ScriptedCreature.h"
#include "SpellAuraEffects.h"
#include "SpellScript.h"
#include "SpellInfo.h"
#include "zulaman.h"
enum Says
enum JanalaiTexts
{
SAY_AGGRO = 0,
SAY_PLAYER_KILL = 1,
SAY_FIRE_BOMBS = 1,
SAY_SUMMON_HATCHER = 2,
SAY_FIRE_BOMB = 3,
SAY_HATCH_ALL_EGGS = 4,
EMOTE_FRENZY = 5,
SAY_DEATH = 6
SAY_ALL_EGGS = 3,
SAY_BERSERK = 4,
SAY_SLAY = 5,
SAY_DEATH = 6,
SAY_EVENT = 7,
EMOTE_FRENZY = 8
};
enum Spells
enum JanalaiSpells
{
// Jan'alai - Combat
SPELL_FLAME_BREATH = 43140,
SPELL_SUMMON_HATCHER_1 = 43962,
SPELL_SUMMON_HATCHER_2 = 45340,
SPELL_HATCH_ALL_EGGS = 43144,
SPELL_FRENZY = 44779,
SPELL_BERSERK = 45078,
// Jan'alai - Combat - Bomb Sequence
SPELL_TELEPORT_TO_CENTER = 43098,
SPELL_SUMMON_ALL_PLAYERS = 43096,
SPELL_FIRE_BOMB_INITIAL = 42621,
SPELL_FIRE_WALL = 43113,
SPELL_FIRE_BOMB_MISSILE = 42628,
// Fire Bomb
SPELL_FIRE_BOMB_VISUAL = 42629,
SPELL_FIRE_BOMB_DAMAGE = 42630,
SPELL_FIRE_BOMB_DUMMY = 42631,
// Amani'shi Hatcher
SPELL_HATCH_EGGS = 42471,
// Dragonhawk Egg
SPELL_SUMMON_HATCHLING = 42493,
// Amani Dragonhawk Hatchling
SPELL_FLAME_BUFFET = 43299,
// Scripts
SPELL_SUMMON_ALL_PLAYERS_2 = 43097,
SPELL_SUMMON_FIRE_BOMB_05 = 42622,
SPELL_SUMMON_FIRE_BOMB_10 = 42623,
SPELL_SUMMON_FIRE_BOMB_15 = 42624,
SPELL_SUMMON_FIRE_BOMB_20 = 42625,
SPELL_SUMMON_FIRE_BOMB_25 = 42626,
SPELL_SUMMON_FIRE_BOMB_30 = 42627
};
enum Events
enum JanalaiEvents
{
// Combat
EVENT_FLAME_BREATH = 1,
EVENT_SUMMON_HATCHERS,
EVENT_HATCH_ALL_EGGS,
EVENT_FRENZY,
EVENT_BERSERK,
// Combat - Fire Bomb Sequence
EVENT_FIRE_BOMBS,
EVENT_FIRE_BOMBS_2,
EVENT_FIRE_BOMBS_3,
EVENT_FIRE_BOMBS_4
};
class boss_janalai : public CreatureScript
enum JanalaiMisc
{
public:
NPC_AMANISHI_HATCHER_R = 23818,
NPC_AMANISHI_HATCHER_L = 24504,
NPC_DRAGONHAWK_EGG = 23817,
NPC_FIRE_BOMB = 23920,
ACTION_EXPLODE_BOMB = 0,
SPAWN_GROUP_EGGS = 376,
POINT_UPSTAIRS = 0,
POINT_HATCH_EGGS = 1,
POINT_BACKUP = 2,
};
boss_janalai() : CreatureScript("boss_janalai") { }
static constexpr std::array<uint32, 6> SummonFireBombSpells =
{
SPELL_SUMMON_FIRE_BOMB_05,
SPELL_SUMMON_FIRE_BOMB_10,
SPELL_SUMMON_FIRE_BOMB_15,
SPELL_SUMMON_FIRE_BOMB_20,
SPELL_SUMMON_FIRE_BOMB_25,
SPELL_SUMMON_FIRE_BOMB_30
};
struct boss_janalaiAI : public BossAI
static constexpr std::string_view EggsStringIdR = "JanalaiEggsR";
static constexpr std::string_view EggsStringIdL = "JanalaiEggsL";
static constexpr Position UpstairsPointR = { -55.058910f, 1147.5952f, 18.705223f, 0.0f };
static constexpr Position UpstairsPointL = { -55.047302f, 1153.5929f, 18.705204f, 0.0f };
static constexpr Position HatchEggsPointR = { -34.438860f, 1104.4828f, 18.711473f, 0.0f };
static constexpr Position HatchEggsPointL = { -34.767784f, 1192.8434f, 18.711363f, 0.0f };
// 23578 - Jan'alai
struct boss_janalai : public BossAI
{
boss_janalai(Creature* creature) : BossAI(creature, BOSS_JANALAI), _hasTriedToHatchEggs(false), _hasUsedFrenzy(false) { }
void JustAppeared() override
{
boss_janalaiAI(Creature* creature) : BossAI(creature, BOSS_JANALAI) { }
void Reset() override
{
_Reset();
me->GetMap()->SpawnGroupSpawn(SPAWN_GROUP_EGGS, true);
}
void JustEngagedWith(Unit* who) override
{
Talk(SAY_AGGRO);
BossAI::JustEngagedWith(who);
Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_FLAME_BREATH, 5s, 10s);
events.ScheduleEvent(EVENT_FIRE_BOMBS, 55s);
events.ScheduleEvent(EVENT_SUMMON_HATCHERS, 10s);
events.ScheduleEvent(EVENT_FRENZY, 5min);
events.ScheduleEvent(EVENT_BERSERK, 10min);
}
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
{
if (!_hasTriedToHatchEggs && me->HealthBelowPctDamaged(35, damage))
{
_hasTriedToHatchEggs = true;
if (!AllEggsWereHatched())
events.ScheduleEvent(EVENT_HATCH_ALL_EGGS, 0s);
}
if (!_hasUsedFrenzy && me->HealthBelowPctDamaged(20, damage))
{
_hasUsedFrenzy = true;
events.RescheduleEvent(EVENT_FRENZY, 0s);
}
}
void OnSpellCast(SpellInfo const* spellInfo) override
{
switch (spellInfo->Id)
{
case SPELL_HATCH_ALL_EGGS:
Talk(SAY_ALL_EGGS);
events.CancelEvent(EVENT_SUMMON_HATCHERS);
break;
case SPELL_FRENZY:
Talk(EMOTE_FRENZY);
_hasUsedFrenzy = true;
break;
case SPELL_BERSERK:
Talk(SAY_BERSERK);
break;
default:
break;
}
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
if (summon->GetEntry() == NPC_FIRE_BOMB)
DoCast(summon, SPELL_FIRE_BOMB_MISSILE, true);
}
bool AllEggsWereHatched()
{
return GetClosestCreatureWithOptions(me, 200.0f, { .CreatureId = NPC_DRAGONHAWK_EGG, .IsAlive = FindCreatureAliveState::Alive }) == nullptr;
}
void DoSummonHatchers()
{
// Verified: He summons no hatchers if both are alive, in this case he performs no emote
// Not verified: What happens if only one hatcher was killed? Currently we spawn no hatchers and perform no emote
if (AllEggsWereHatched())
return;
Creature* hatcherR = me->FindNearestCreature(NPC_AMANISHI_HATCHER_R, 150.0f, true);
Creature* hatcherL = me->FindNearestCreature(NPC_AMANISHI_HATCHER_L, 150.0f, true);
if (hatcherR || hatcherL)
return;
DoCastSelf(SPELL_SUMMON_HATCHER_1, true);
DoCastSelf(SPELL_SUMMON_HATCHER_2, true);
Talk(SAY_SUMMON_HATCHER);
}
void EnterEvadeMode(EvadeReason /*why*/) override
{
summons.DespawnAll();
_DespawnAtEvade();
}
void KilledUnit(Unit* /*victim*/) override
{
Talk(SAY_SLAY);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
_JustDied();
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_PLAYER_KILL);
Talk(SAY_DEATH);
}
void UpdateAI(uint32 diff) override
@@ -80,26 +251,371 @@ class boss_janalai : public CreatureScript
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
/*
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
// Combat
case EVENT_FLAME_BREATH:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true))
DoCast(target, SPELL_FLAME_BREATH);
events.Repeat(10s, 15s);
break;
case EVENT_SUMMON_HATCHERS:
DoSummonHatchers();
events.Repeat(90s);
break;
case EVENT_HATCH_ALL_EGGS:
DoCastSelf(SPELL_HATCH_ALL_EGGS, true);
break;
case EVENT_FRENZY:
DoCastSelf(SPELL_FRENZY, true);
break;
case EVENT_BERSERK:
DoCastSelf(SPELL_BERSERK, true);
break;
// Combat - Fire Bomb Sequence
case EVENT_FIRE_BOMBS:
Talk(SAY_FIRE_BOMBS);
DoCastSelf(SPELL_TELEPORT_TO_CENTER);
me->SetReactState(REACT_PASSIVE);
events.ScheduleEvent(EVENT_FIRE_BOMBS_2, 1200ms);
events.Repeat(30s);
break;
case EVENT_FIRE_BOMBS_2:
DoCastSelf(SPELL_SUMMON_ALL_PLAYERS);
events.ScheduleEvent(EVENT_FIRE_BOMBS_3, 1200ms);
break;
case EVENT_FIRE_BOMBS_3:
{
DoCastSelf(SPELL_FIRE_BOMB_INITIAL);
std::vector<Creature*> triggers;
GetCreatureListWithOptionsInGrid(triggers, me, 100.0f, { .StringId = "JanalaiFireWallTrigger" });
for (Creature* trigger : triggers)
trigger->CastSpell(trigger, SPELL_FIRE_WALL);
me->SetReactState(REACT_AGGRESSIVE);
events.ScheduleEvent(EVENT_FIRE_BOMBS_4, 10s);
break;
}
case EVENT_FIRE_BOMBS_4:
{
std::vector<Creature*> bombs;
GetCreatureListWithEntryInGrid(bombs, me, NPC_FIRE_BOMB, 100.0f);
for (Creature* bomb : bombs)
bomb->AI()->DoAction(ACTION_EXPLODE_BOMB);
break;
}
default:
break;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
}
private:
bool _hasTriedToHatchEggs;
bool _hasUsedFrenzy;
};
// 23920 - Fire Bomb (Zul'Aman)
struct npc_fire_bomb_zulaman : public ScriptedAI
{
using ScriptedAI::ScriptedAI;
void InitializeAI() override
{
me->SetReactState(REACT_PASSIVE);
}
void DoAction(int32 action) override
{
if (action == ACTION_EXPLODE_BOMB)
{
DoCastSelf(SPELL_FIRE_BOMB_DAMAGE);
me->RemoveAurasDueToSpell(SPELL_FIRE_BOMB_VISUAL);
me->DespawnOrUnsummon(3600ms);
}
}
void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_FIRE_BOMB_MISSILE)
DoCastSelf(SPELL_FIRE_BOMB_VISUAL);
}
};
// 23818 - Amani'shi Hatcher
// 24504 - Amani'shi Hatcher
struct npc_amanishi_hatcher : public ScriptedAI
{
npc_amanishi_hatcher(Creature* creature) : ScriptedAI(creature), _otherHatcherId(0) { }
void InitializeAI() override
{
me->SetReactState(REACT_PASSIVE);
me->SetCorpseDelay(5, true);
switch (me->GetEntry())
{
case NPC_AMANISHI_HATCHER_R:
_upstairsPoint = UpstairsPointR;
_hatchEggsPointA = HatchEggsPointR;
_hatchEggsPointB = HatchEggsPointL;
_eggsStringIdA = EggsStringIdR;
_eggsStringIdB = EggsStringIdL;
_otherHatcherId = NPC_AMANISHI_HATCHER_L;
break;
case NPC_AMANISHI_HATCHER_L:
_upstairsPoint = UpstairsPointL;
_hatchEggsPointA = HatchEggsPointL;
_hatchEggsPointB = HatchEggsPointR;
_eggsStringIdA = EggsStringIdL;
_eggsStringIdB = EggsStringIdR;
_otherHatcherId = NPC_AMANISHI_HATCHER_R;
break;
default:
break;
}
}
*/
}
};
CreatureAI* GetAI(Creature* creature) const override
void JustAppeared() override
{
return GetZulAmanAI<boss_janalaiAI>(creature);
me->GetMotionMaster()->MovePoint(POINT_UPSTAIRS, _upstairsPoint);
}
void Reset() override
{
_scheduler.CancelAll();
}
bool AreEggsHatchedA()
{
return GetClosestCreatureWithOptions(me, 200.0f, { .StringId = _eggsStringIdA, .IsAlive = FindCreatureAliveState::Alive }) == nullptr;
}
bool AreEggsHatchedB()
{
return GetClosestCreatureWithOptions(me, 200.0f, { .StringId = _eggsStringIdB, .IsAlive = FindCreatureAliveState::Alive }) == nullptr;
}
bool IsOtherHatcherAlive()
{
return me->FindNearestCreature(_otherHatcherId, 200.0f, true) != nullptr;
}
void MovementInform(uint32 type, uint32 id) override
{
if (type == POINT_MOTION_TYPE)
{
switch (id)
{
case POINT_UPSTAIRS:
_scheduler.Schedule(2s, [this](TaskContext const& /*task*/)
{
// Verified: If own eggs were hatched, move to the side with unhatched eggs. Yes, both hatchers move to the same side
if (!AreEggsHatchedA())
me->GetMotionMaster()->MovePoint(POINT_HATCH_EGGS, _hatchEggsPointA);
else
me->GetMotionMaster()->MovePoint(POINT_HATCH_EGGS, _hatchEggsPointB);
});
break;
case POINT_HATCH_EGGS:
_scheduler.Schedule(1s, [this](TaskContext& task)
{
// Verified: If eggs from the both sides are hatched, stay and continue to cast Hatch Eggs spell
// Verified: If own eggs were hatched, other hatcher's eggs were not hatched and other hatcher is dead, move to hatch his eggs
// Not verified: If own eggs were hatched, other hatcher's eggs were not hatched and other hatcher is alive, what should happen?
if (AreEggsHatchedA() && !AreEggsHatchedB() && !IsOtherHatcherAlive())
{
me->GetMotionMaster()->MovePoint(POINT_BACKUP, _hatchEggsPointB);
return;
}
DoCastSelf(SPELL_HATCH_EGGS);
task.Repeat(5s);
});
break;
case POINT_BACKUP:
_scheduler.Schedule(1s, [this](TaskContext& task)
{
DoCastSelf(SPELL_HATCH_EGGS);
task.Repeat(5s);
});
break;
}
}
}
void UpdateAI(uint32 diff) override
{
UpdateVictim();
_scheduler.Update(diff);
}
private:
TaskScheduler _scheduler;
Position _upstairsPoint;
Position _hatchEggsPointA;
Position _hatchEggsPointB;
std::string_view _eggsStringIdA;
std::string_view _eggsStringIdB;
uint32 _otherHatcherId;
};
// 23817 - Dragonhawk Egg
struct npc_dragonhawk_egg : public ScriptedAI
{
using ScriptedAI::ScriptedAI;
void InitializeAI() override
{
me->SetCorpseDelay(3, true);
}
void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_HATCH_EGGS || spellInfo->Id == SPELL_HATCH_ALL_EGGS)
DoCastSelf(SPELL_SUMMON_HATCHLING);
}
};
// 23598 - Amani Dragonhawk Hatchling
struct npc_amani_dragonhawk_hatchling : public ScriptedAI
{
npc_amani_dragonhawk_hatchling(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
void InitializeAI() override
{
me->SetCorpseDelay(4, true);
ScriptedAI::InitializeAI();
}
void JustAppeared() override
{
DoZoneInCombat();
if (Creature* janalai = _instance->GetCreature(BOSS_JANALAI))
janalai->AI()->JustSummoned(me);
}
void Reset() override
{
_scheduler.CancelAll();
}
void JustEngagedWith(Unit* /*who*/) override
{
_scheduler.Schedule(5s, 10s, [this](TaskContext& task)
{
DoCastVictim(SPELL_FLAME_BUFFET);
task.Repeat(5s, 10s);
});
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
_scheduler.Update(diff);
}
private:
InstanceScript* _instance;
TaskScheduler _scheduler;
};
// 43096 - Summon All Players
class spell_janalai_summon_all_players : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_SUMMON_ALL_PLAYERS_2 });
}
void HandleDummy(SpellEffIndex /*effIndex*/)
{
// Guessed value. Patch 2.4.0 (2008-03-25): Will now only teleport players to him if they are too far away.
if (!GetCaster()->IsWithinDist(GetHitUnit(), 30.0f, false))
GetCaster()->CastSpell(GetHitUnit(), SPELL_SUMMON_ALL_PLAYERS_2, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_janalai_summon_all_players::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 42621 - Fire Bomb
class spell_janalai_fire_bomb : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(SummonFireBombSpells);
}
void OnPeriodic(AuraEffect const* aurEff)
{
uint8 index = -1;
uint32 tick = aurEff->GetTickNumber();
if (tick)
{
if (tick < 10)
index = tick / 5;
else
index = tick / 10 + 1;
if (index < 6)
GetTarget()->CastSpell(GetTarget(), SummonFireBombSpells[index], true);
else
Remove();
}
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_janalai_fire_bomb::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
// 42471 - Hatch Eggs
class spell_janalai_hatch_eggs : public SpellScript
{
void FilterTargets(std::list<WorldObject*>& targets)
{
if (Creature* caster = GetCaster()->ToCreature())
{
targets.remove_if([caster](WorldObject const* target)
{
return !caster->IsWithinDist(target, 50.0f);
});
Trinity::Containers::RandomResize(targets, 3);
}
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_janalai_hatch_eggs::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
}
};
void AddSC_boss_janalai()
{
new boss_janalai();
RegisterZulAmanCreatureAI(boss_janalai);
RegisterZulAmanCreatureAI(npc_fire_bomb_zulaman);
RegisterZulAmanCreatureAI(npc_amanishi_hatcher);
RegisterZulAmanCreatureAI(npc_dragonhawk_egg);
RegisterZulAmanCreatureAI(npc_amani_dragonhawk_hatchling);
RegisterSpellScript(spell_janalai_summon_all_players);
RegisterSpellScript(spell_janalai_fire_bomb);
RegisterSpellScript(spell_janalai_hatch_eggs);
}