Compare commits
25
Commits
08105da605
...
bfe79dc2d0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bfe79dc2d0 | ||
|
|
429ecdbe18 | ||
|
|
29e1d475f2 | ||
|
|
609aee127d | ||
|
|
7d1bc1237a | ||
|
|
5cb9dee306 | ||
|
|
3b52d609b1 | ||
|
|
4995d2ad14 | ||
|
|
b76377791b | ||
|
|
2f83245d87 | ||
|
|
bed3e0ff04 | ||
|
|
ca9f547035 | ||
|
|
5b021fc840 | ||
|
|
9cded4b858 | ||
|
|
53a7b0bbe9 | ||
|
|
e0ec5ac309 | ||
|
|
5f9987f63c | ||
|
|
238bc1541d | ||
|
|
deb42069d1 | ||
|
|
0cca4fcaf3 | ||
|
|
c2c22d88e8 | ||
|
|
4f387f1a3b | ||
|
|
f26a91fccf | ||
|
|
1a4902da04 | ||
|
|
4f942bbfe2 |
@@ -0,0 +1,108 @@
|
||||
|
||||
-- AZSUNA: Fix chain break between "Down to Azsuna" and "Into the Fray"
|
||||
UPDATE quest_template_addon SET NextQuestID = 38834 WHERE ID = 41220;
|
||||
UPDATE quest_template_addon SET PrevQuestID = 41220 WHERE ID = 38834;
|
||||
|
||||
-- STORMHEIM: Fix Alliance breadcrumb chain "A Royal Summons" -> "Making the Rounds"
|
||||
UPDATE quest_template_addon SET NextQuestID = 38206 WHERE ID = 38035;
|
||||
|
||||
-- STORMHEIM: Fix Horde breadcrumb chain "The Warchief Beckons" -> "Havi's Test"
|
||||
UPDATE quest_template_addon SET NextQuestID = 38331 WHERE ID = 38307;
|
||||
|
||||
-- STORMHEIM: Fix dragon chain - both 38413 and 38414 lead to 39652, so PrevQuest must allow either
|
||||
UPDATE quest_template_addon SET PrevQuestID = 0 WHERE ID = 39652;
|
||||
|
||||
|
||||
REPLACE INTO `conversation_actors` (`ConversationId`, `ConversationActorId`, `Idx`, `CreatureId`, `CreatureDisplayInfoId`, `NoActorObject`, `ActivePlayerObject`, `VerifiedBuild`) VALUES
|
||||
(25770, 99466, 0, 224736, 119519, 0, 0, 69875),
|
||||
(25772, 99466, 0, 224736, 119519, 0, 0, 69875),
|
||||
(25814, 94742, 0, 213119, 119519, 0, 0, 69875), -- Full: 0x2041E14B80D01FC000B16A000031380C Creature/0 R4216/S45418 Map: 2652 (The Stonevault) Entry: 213119 (Void Speaker Eirich) Low: 3225612
|
||||
(25767, 99466, 0, 224736, 119519, 0, 0, 69875),
|
||||
(25771, 99466, 0, 224736, 119519, 0, 0, 69875),
|
||||
(25775, 99466, 0, 224736, 119519, 0, 0, 69875),
|
||||
(25773, 99466, 0, 224736, 119519, 0, 0, 69875);
|
||||
|
||||
UPDATE `conversation_actors` SET `VerifiedBuild`=69875 WHERE (`Idx`=0 AND `ConversationId` IN (25768,25769));
|
||||
|
||||
|
||||
UPDATE `conversation_line_template` SET `VerifiedBuild`=69875 WHERE `Id` IN (70042, 70044, 70040, 70039, 70204, 70203, 70038, 70037, 70036, 70043, 70041, 70049, 70048, 70046, 70045);
|
||||
|
||||
|
||||
UPDATE `conversation_template` SET `VerifiedBuild`=69875 WHERE `Id`=25814;
|
||||
UPDATE `conversation_template` SET `VerifiedBuild`=69875 WHERE `Id`=25775;
|
||||
UPDATE `conversation_template` SET `VerifiedBuild`=69875 WHERE `Id`=25773;
|
||||
UPDATE `conversation_template` SET `VerifiedBuild`=69875 WHERE `Id`=25772;
|
||||
UPDATE `conversation_template` SET `VerifiedBuild`=69875 WHERE `Id`=25771;
|
||||
UPDATE `conversation_template` SET `VerifiedBuild`=69875 WHERE `Id`=25770;
|
||||
UPDATE `conversation_template` SET `VerifiedBuild`=69875 WHERE `Id`=25769;
|
||||
UPDATE `conversation_template` SET `VerifiedBuild`=69875 WHERE `Id`=25768;
|
||||
UPDATE `conversation_template` SET `VerifiedBuild`=69875 WHERE `Id`=25767;
|
||||
|
||||
|
||||
|
||||
DELETE FROM `world_quest_template` WHERE `QuestID` IN (52463 /*Haegol the Hammer*/, 50513 /*Tainted Guardian*/, 65102 /*Fish Eyes*/, 55889 /*Champion Kyx'zhul the Deepspeaker*/, 54572 /*Darbel Montrose*/, 58221 /*Gettin' Even*/, 64717 /*Materials of Creation*/, 51512 /*Bilefang Mother*/, 70172 /*Mountain Mysteries*/, 51824 /*You're Grounded*/, 58460 /*Marshals of Madness*/, 56397 /*CK-9 Micro-Oppression Unit*/, 49056 /*Pilfer*/, 61148 /*AHHH! Real Monsters!*/, 51406 /*The Lord's Hunt*/, 52045 /*Boarder Patrol*/, 65262 /*Save the Vombata*/, 50499 /*Gwugnug*/);
|
||||
INSERT INTO `world_quest_template` (`QuestID`, `Duration`, `VariableID`, `Value`) VALUES
|
||||
(52463, 86400, 15763, 1), -- Haegol the Hammer
|
||||
(50513, 86400, 14807, 1), -- Tainted Guardian
|
||||
(65102, 86400, 21265, 1), -- Fish Eyes
|
||||
(55889, 259200, 17587, 1), -- Champion Kyx'zhul the Deepspeaker
|
||||
(54572, 86400, 16866, 1), -- Darbel Montrose
|
||||
(58221, 86400, 18290, 1), -- Gettin' Even
|
||||
(64717, 86400, 21348, 2), -- Materials of Creation
|
||||
(51512, 86400, 15256, 1), -- Bilefang Mother
|
||||
(70172, 302400, 22456, 1), -- Mountain Mysteries
|
||||
(51824, 86400, 15528, 1), -- You're Grounded
|
||||
(58460, 86400, 18540, 3), -- Marshals of Madness
|
||||
(56397, 86400, 17788, 5), -- CK-9 Micro-Oppression Unit
|
||||
(49056, 86400, 14322, 1), -- Pilfer
|
||||
(61148, 86400, 19408, 2), -- AHHH! Real Monsters!
|
||||
(51406, 86400, 15766, 1), -- The Lord's Hunt
|
||||
(52045, 86400, 15621, 1), -- Boarder Patrol
|
||||
(65262, 86400, 21383, 1), -- Save the Vombata
|
||||
(50499, 86400, 14796, 1); -- Gwugnug
|
||||
|
||||
|
||||
|
||||
UPDATE `spawn_tracking_template` SET `VerifiedBuild`=69875 WHERE `SpawnTrackingId` IN (1978804, 1890492, 1989444, 1864180, 1922790, 1997407, 1994265, 1960887, 1838831, 1989140, 1989145, 1888621, 1989132, 1964065, 3262739, 3275039, 3274804, 3275034, 3274764, 2853599, 3258080, 3257755, 3144987, 3102636, 2914859, 3162881, 2196338, 1824267, 2026887, 1870387, 1867398, 1867410, 1792406, 1751724, 1738299, 1603576, 1767633, 1727469, 1429886, 1500761, 1486549, 1484068);
|
||||
UPDATE `spawn_tracking_template` SET `MapId`=1642, `VerifiedBuild`=69875 WHERE `SpawnTrackingId`=1578973; -- Map: 1642 (Zandalar) - Phase: 0
|
||||
UPDATE `spawn_tracking_template` SET `MapId`=1643, `VerifiedBuild`=69875 WHERE `SpawnTrackingId`=1483872; -- Map: 1643 (Kul Tiras) - Phase: 0
|
||||
|
||||
|
||||
|
||||
REPLACE INTO `spell_target_position` (`ID`, `EffectIndex`, `OrderIndex`, `MapID`, `PositionX`, `PositionY`, `PositionZ`, `VerifiedBuild`) VALUES
|
||||
(346210, 0, 0, 2222, 4617.888671875, 7026.46533203125, 4826.462890625, 69875), -- Spell: 346210 (Molten Eruption) Effect 0: 32 (SPELL_EFFECT_TRIGGER_MISSILE)
|
||||
(346210, 0, 1, 2222, 4607.80615234375, 7010.3359375, 4827.0068359375, 69875), -- Spell: 346210 (Molten Eruption) Effect 0: 32 (SPELL_EFFECT_TRIGGER_MISSILE)
|
||||
(346210, 0, 2, 2222, 4624.658203125, 7014.18701171875, 4826.96875, 69875), -- Spell: 346210 (Molten Eruption) Effect 0: 32 (SPELL_EFFECT_TRIGGER_MISSILE)
|
||||
(346210, 0, 3, 2222, 4665.35302734375, 7028.07666015625, 4827.82666015625, 69875), -- Spell: 346210 (Molten Eruption) Effect 0: 32 (SPELL_EFFECT_TRIGGER_MISSILE)
|
||||
(346210, 0, 4, 2222, 4670.82568359375, 7007.93115234375, 4831.5107421875, 69875), -- Spell: 346210 (Molten Eruption) Effect 0: 32 (SPELL_EFFECT_TRIGGER_MISSILE)
|
||||
(346210, 0, 5, 2222, 4579.4697265625, 7012.05810546875, 4827.4619140625, 69875), -- Spell: 346210 (Molten Eruption) Effect 0: 32 (SPELL_EFFECT_TRIGGER_MISSILE)
|
||||
(346210, 0, 6, 2222, 4610.82373046875, 6970.57080078125, 4838.31787109375, 69875), -- Spell: 346210 (Molten Eruption) Effect 0: 32 (SPELL_EFFECT_TRIGGER_MISSILE)
|
||||
(346210, 0, 7, 2222, 4611.87646484375, 7015.9013671875, 4826.7978515625, 69875), -- Spell: 346210 (Molten Eruption) Effect 0: 32 (SPELL_EFFECT_TRIGGER_MISSILE)
|
||||
(346210, 0, 8, 2222, 4581.7568359375, 6991.1083984375, 4828.62353515625, 69875), -- Spell: 346210 (Molten Eruption) Effect 0: 32 (SPELL_EFFECT_TRIGGER_MISSILE)
|
||||
(346210, 0, 9, 2222, 4630.5537109375, 7015.6220703125, 4826.8974609375, 69875), -- Spell: 346210 (Molten Eruption) Effect 0: 32 (SPELL_EFFECT_TRIGGER_MISSILE)
|
||||
(346210, 0, 10, 2222, 4603.8916015625, 6979.06640625, 4833.4638671875, 69875), -- Spell: 346210 (Molten Eruption) Effect 0: 32 (SPELL_EFFECT_TRIGGER_MISSILE)
|
||||
(346210, 0, 11, 2222, 4622.50341796875, 7009.1640625, 4827.22412109375, 69875), -- Spell: 346210 (Molten Eruption) Effect 0: 32 (SPELL_EFFECT_TRIGGER_MISSILE)
|
||||
(346210, 0, 12, 2222, 4658.17529296875, 7012.29736328125, 4831.14111328125, 69875), -- Spell: 346210 (Molten Eruption) Effect 0: 32 (SPELL_EFFECT_TRIGGER_MISSILE)
|
||||
(346210, 0, 13, 2222, 4620.7958984375, 7026.10888671875, 4826.4951171875, 69875), -- Spell: 346210 (Molten Eruption) Effect 0: 32 (SPELL_EFFECT_TRIGGER_MISSILE)
|
||||
(346210, 0, 14, 2222, 4590.6630859375, 6999.40234375, 4828.29150390625, 69875); -- Spell: 346210 (Molten Eruption) Effect 0: 32 (SPELL_EFFECT_TRIGGER_MISSILE)
|
||||
|
||||
|
||||
DELETE FROM `creature_template_difficulty` WHERE (`Entry`=237776 AND `DifficultyID`=205);
|
||||
INSERT INTO `creature_template_difficulty` (`Entry`, `DifficultyID`, `HealthScalingExpansion`, `HealthModifier`, `ManaModifier`, `CreatureDifficultyID`, `TypeFlags`, `TypeFlags2`, `TypeFlags3`) VALUES
|
||||
(237776, 205, 11, 3, 1, 316716, 0x0, 0, 0); -- Mecha-Scrapper
|
||||
|
||||
|
||||
DELETE FROM `creature_template_difficulty` WHERE (`Entry`=237776 AND `DifficultyID`=205);
|
||||
INSERT INTO `creature_template_difficulty` (`Entry`, `DifficultyID`, `LevelScalingDeltaMin`, `LevelScalingDeltaMax`, `ContentTuningID`, `StaticFlags1`, `StaticFlags2`, `StaticFlags3`, `StaticFlags4`, `StaticFlags5`, `StaticFlags6`, `StaticFlags7`, `StaticFlags8`, `VerifiedBuild`) VALUES
|
||||
(237776, 205, 0, 0, 391, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 69875); -- 237776 (Mecha-Scrapper) -
|
||||
|
||||
|
||||
INSERT INTO `creature` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnDifficulties`, `PhaseId`, `PhaseGroup`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `MovementType`, `npcflag`, `unit_flags`, `unit_flags2`, `unit_flags3`, `VerifiedBuild`) VALUES
|
||||
(900133, 264418, 0, 15969, 16079, '0', '0', 0, 0, 0, 8331.859375, -4907.92041015625, 91.51644134521484375, 5.476967811584472656, 120, 0, 0, 0, NULL, NULL, NULL, NULL, 69497), -- Penny (Area: The Bazaar - Difficulty: 0) CreateObject1
|
||||
(900134, 256563, 0, 15969, 16088, '0', '0', 0, 0, 0, 8334.8603515625, -4110.10595703125, 44.21979904174804687, 5.380497455596923828, 120, 0, 0, 0, NULL, NULL, NULL, NULL, 68974), -- -Unknown- (Area: 16088 - Difficulty: 0) CreateObject1 (Auras: 1269392 - 1269392, 1263773 - 1263773, 421177 - 421177, 1260011 - 1260011, 421175 - 421175)
|
||||
(900135, 266434, 0, 15969, 16079, '0', '0', 0, 0, 0, 8785.796875, -4459.45654296875, 29.78347587585449218, 1.880817055702209472, 120, 0, 0, 0, NULL, NULL, NULL, NULL, 68974), -- -Unknown- (Area: 16079 - Difficulty: 0) CreateObject1 (Auras: 1250294 - 1250294)
|
||||
(900136, 265582, 0, 15969, 16079, '0', '0', 0, 0, 0, 8863.4150390625, -4678.1787109375, 76.85699462890625, 4.171336650848388671, 120, 0, 0, 0, NULL, NULL, NULL, NULL, 68974), -- -Unknown- (Area: 16079 - Difficulty: 0) CreateObject1
|
||||
(900137, 263598, 0, 15969, 16079, '0', '0', 0, 0, 0, 8860.12890625, -4689.8681640625, 76.85699462890625, 5.51227569580078125, 120, 0, 0, 0, NULL, NULL, NULL, NULL, 68974), -- -Unknown- (Area: 16079 - Difficulty: 0) CreateObject1
|
||||
(900138, 263604, 0, 15969, 16079, '0', '0', 0, 0, 0, 8858.0693359375, -4691.61474609375, 76.85699462890625, 5.881916999816894531, 120, 0, 0, 0, NULL, NULL, NULL, NULL, 68974), -- -Unknown- (Area: 16079 - Difficulty: 0) CreateObject1
|
||||
(900139, 263601, 0, 15969, 16079, '0', '0', 0, 0, 0, 8862.560546875, -4688.6162109375, 76.85699462890625, 4.870819568634033203, 120, 0, 0, 0, NULL, NULL, NULL, NULL, 68974), -- -Unknown- (Area: 16079 - Difficulty: 0) CreateObject1
|
||||
(900140, 267869, 0, 15969, 0, '0', '0', 0, 0, 0, 8664.6845703125, -4437.46728515625, 71.44916534423828125, 3.940832376480102539, 120, 0, 0, 0, NULL, NULL, NULL, NULL, 68974); -- -Unknown- (Area: 0 - Difficulty: 0) CreateObject1 (Auras: 179665 - 179665)
|
||||
@@ -0,0 +1,251 @@
|
||||
-- =====
|
||||
-- Fixes
|
||||
-- =====
|
||||
|
||||
-- NPC Possessed Vrykul (103529)
|
||||
UPDATE `npc_spellclick_spells` SET `spell_id`=46598 WHERE `npc_entry`=103529 AND `spell_id`=206469;
|
||||
|
||||
|
||||
|
||||
-- NPC Theramore Combat Dummy (4952)
|
||||
UPDATE `creature_template_addon` SET `PvPFlags`=0 WHERE `entry`=4952;
|
||||
|
||||
|
||||
|
||||
-- NPC Training Dummy (60197)
|
||||
DELETE FROM `creature_addon` WHERE `guid` IN (SELECT `guid` FROM `creature` WHERE `id`=60197);
|
||||
|
||||
|
||||
|
||||
-- Misc: Invalid Areatrigger
|
||||
UPDATE `creature_addon` SET `auras`='' WHERE `auras`='212102';
|
||||
|
||||
UPDATE `creature_addon` SET `auras`='288179' WHERE `guid`=444249;
|
||||
UPDATE `creature_addon` SET `auras`='42459' WHERE `guid`=443776;
|
||||
UPDATE `creature_addon` SET `auras`='259919 288179' WHERE `guid`=443768;
|
||||
UPDATE `creature_addon` SET `auras`='170528' WHERE `guid`=444341;
|
||||
UPDATE `creature_addon` SET `auras`='288178' WHERE `guid`=444236;
|
||||
UPDATE `creature_addon` SET `auras`='288178' WHERE `guid`=444237;
|
||||
UPDATE `creature_addon` SET `auras`='144465' WHERE `guid`=443729;
|
||||
UPDATE `creature_addon` SET `auras`='123168' WHERE `guid`=344263;
|
||||
|
||||
UPDATE `creature_template_addon` SET `auras`='288178' WHERE `entry`=142686;
|
||||
UPDATE `creature_template_addon` SET `auras`='144465' WHERE `entry`=142725;
|
||||
UPDATE `creature_template_addon` SET `auras`='288178' WHERE `entry`=142684;
|
||||
UPDATE `creature_template_addon` SET `auras`='170528' WHERE `entry`=142683;
|
||||
UPDATE `creature_template_addon` SET `auras`='259919 288179' WHERE `entry`=141615;
|
||||
UPDATE `creature_template_addon` SET `auras`='42459' WHERE `entry`=142423;
|
||||
UPDATE `creature_template_addon` SET `auras`='288014 288179' WHERE `entry`=141620;
|
||||
UPDATE `creature_template_addon` SET `auras`='389215' WHERE `entry`=196805;
|
||||
UPDATE `creature_template_addon` SET `auras`='465756' WHERE `entry`=231436;
|
||||
UPDATE `creature_template_addon` SET `auras`='203761 67236' WHERE `entry`=114873;
|
||||
UPDATE `creature_template_addon` SET `auras`='123168' WHERE `entry`=102303;
|
||||
UPDATE `creature_template_addon` SET `auras`='223531 214336' WHERE `entry`=109954;
|
||||
UPDATE `creature_template_addon` SET `auras`='214336' WHERE `entry`=109954;
|
||||
|
||||
UPDATE `creature_addon` SET `auras`='' WHERE `guid` IN (443699,444335,443681,443670,340845);
|
||||
UPDATE `creature_template_addon` SET `auras`='' WHERE `entry` IN (142440,142436,142435,142508,182696,181680,185172,189930,106873,110944);
|
||||
|
||||
DELETE FROM `disables` WHERE `sourceType`=0 AND `entry` IN (287904,287906,287908,287911,287953,287954,287959,287960,287961,287962,287966,389216,362331,398620,212102,214074,222299,222401,222412,222423,228771,223526,223532,219489,223531);
|
||||
INSERT INTO `disables` (`sourceType`, `entry`, `flags`, `params_0`, `params_1`, `comment`) VALUES
|
||||
(0, 287904, 8, '0', '0', 'Spell Area Trigger - Invalid Areatrigger 15745 Create Properties'),
|
||||
(0, 287906, 8, '0', '0', 'Spell Area Trigger - Invalid Areatrigger 15747 Create Properties'),
|
||||
(0, 287908, 8, '0', '0', 'Spell Area Trigger - Invalid Areatrigger 15750 Create Properties'),
|
||||
(0, 287911, 8, '0', '0', 'Spell Area Trigger - Invalid Areatrigger 15753 Create Properties'),
|
||||
(0, 287953, 8, '0', '0', 'Spell Area Trigger - Invalid Areatrigger 15777 Create Properties'),
|
||||
(0, 287954, 8, '0', '0', 'Spell Area Trigger - Invalid Areatrigger 15778 Create Properties'),
|
||||
(0, 287959, 8, '0', '0', 'Spell Area Trigger - Invalid Areatrigger 15783 Create Properties'),
|
||||
(0, 287960, 8, '0', '0', 'Spell Area Trigger - Invalid Areatrigger 15784 Create Properties'),
|
||||
(0, 287961, 8, '0', '0', 'Spell Area Trigger - Invalid Areatrigger 15785 Create Properties'),
|
||||
(0, 287962, 8, '0', '0', 'Spell Area Trigger - Invalid Areatrigger 15786 Create Properties'),
|
||||
(0, 287966, 8, '0', '0', 'Spell Area Trigger - Invalid Areatrigger 15790 Create Properties'),
|
||||
(0, 389216, 8, '0', '0', 'Spell Conjured Goods Stolen Area Trigger [DNT] - Invalid Areatrigger 26684 Create Properties'),
|
||||
(0, 362331, 8, '0', '0', 'Spell Stasis - Invalid Areatrigger 24255 Create Properties'),
|
||||
(0, 398620, 8, '0', '0', 'Spell Stasis - Invalid Areatrigger 24255 Create Properties'),
|
||||
(0, 212102, 8, '0', '0', 'Spell Arcane Font Area Aura - Invalid Areatrigger 6946 Create Properties'),
|
||||
(0, 214074, 8, '0', '0', 'Spell Aluneth Charge Whispers Half-Hour Timer - Invalid Areatrigger 6946 Create Properties'),
|
||||
(0, 222299, 8, '0', '0', 'Spell Aluneth Dungeon Whispers Two-Hour Timer - Invalid Areatrigger 6946 Create Properties'),
|
||||
(0, 222401, 8, '0', '0', 'Spell Aluneth Dalaran Whispers Control - Invalid Areatrigger 6946 Create Properties'),
|
||||
(0, 222412, 8, '0', '0', 'Spell Aluneth Dalaran Whispers Four-Hour Timer - Invalid Areatrigger 6946 Create Properties'),
|
||||
(0, 222423, 8, '0', '0', 'Spell Aluneth General Whispers One-Hour Timer - Invalid Areatrigger 6946 Create Properties'),
|
||||
(0, 228771, 8, '0', '0', 'Spell Waylay Citizens - Invalid Areatrigger 8902 Create Properties'),
|
||||
(0, 223526, 8, '0', '0', 'Spell Guardian Thor\'el - Level 3 - Invalid Areatrigger 8325 Create Properties'),
|
||||
(0, 223532, 8, '0', '0', 'Spell Lieutenant Strathmar - Level 3 - Invalid Areatrigger 8335 Create Properties'),
|
||||
(0, 219489, 8, '0', '0', 'Spell Illusions Explode Area Trigger - Invalid Areatrigger 7872 Create Properties'),
|
||||
(0, 223531, 8, '0', '0', 'Spell Magister Phaedris - Level 3 - Invalid Areatrigger 8333 Create Properties');
|
||||
|
||||
|
||||
|
||||
-- ======================
|
||||
-- Stormwind Calibrations
|
||||
-- ======================
|
||||
|
||||
-- Clean
|
||||
DELETE FROM `creature` WHERE `guid` IN (671121,631635,671104,364873,364874,595458,595456,364866,671094,595478,671044,671070,113132,196497,196498,196499,671178,9796,671168,595413);
|
||||
DELETE FROM `creature_addon` WHERE `guid` IN (671121,631635,671104,364873,364874,595458,595456,364866,671094,595478,671044,671070,113132,196497,196498,196499,671178,9796,671168,595413);
|
||||
UPDATE `creature` SET `areaId`=5390 WHERE `guid`=364864;
|
||||
UPDATE `creature` SET `zoneId`=1519, `areaId`=4411 WHERE `guid` IN (605468,475063,475064,475065,475066,475062);
|
||||
|
||||
DELETE FROM `gameobject` WHERE `guid` IN (212103,144285,67725);
|
||||
DELETE FROM `gameobject_addon` WHERE `guid` IN (212103,144285,67725);
|
||||
|
||||
|
||||
-- NPC [DNT] Kill Credit (200001)
|
||||
DELETE FROM `creature_addon` WHERE `guid` IN (SELECT `guid` FROM `creature` WHERE `id`=200001);
|
||||
DELETE FROM `creature` WHERE `id`=200001;
|
||||
UPDATE `creature_template` SET `AIName`='' WHERE `entry`=200001;
|
||||
UPDATE `creature_template_addon` SET `SheathState`=0 WHERE `entry`=200001;
|
||||
UPDATE `creature_template_difficulty` SET `StaticFlags1`=536871168 WHERE `Entry`=200001;
|
||||
DELETE FROM `creature_text` WHERE `CreatureID`=200001;
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid`=200001 AND `source_type`=0;
|
||||
|
||||
|
||||
-- NPC Plump Turkey Bunny (32819)
|
||||
DELETE FROM `creature_addon` WHERE `guid` IN (SELECT `guid` FROM `creature` WHERE `id`=32819);
|
||||
DELETE FROM `creature` WHERE `id`=32819;
|
||||
UPDATE `creature_template_addon` SET `SheathState`=0 WHERE `entry`=32819;
|
||||
UPDATE `creature_template_difficulty` SET `StaticFlags1`=536871168 WHERE `Entry`=32819;
|
||||
DELETE FROM `game_event_creature` WHERE `guid`=223831 AND `eventEntry`=41;
|
||||
|
||||
|
||||
-- NPC Rat (4075)
|
||||
DELETE FROM `creature_addon` WHERE `guid` IN (SELECT `guid` FROM `creature` WHERE `id`=4075 AND `zoneid`=1519);
|
||||
DELETE FROM `creature` WHERE `id`=4075 AND `zoneid`=1519;
|
||||
|
||||
|
||||
-- NPC Squirrel (1412)
|
||||
DELETE FROM `creature_addon` WHERE `guid` IN (SELECT `guid` FROM `creature` WHERE `id`=1412 AND `zoneid`=1519);
|
||||
DELETE FROM `creature` WHERE `id`=1412 AND `zoneid`=1519;
|
||||
|
||||
|
||||
-- NPC Rabbit (61080)
|
||||
DELETE FROM `creature_addon` WHERE `guid` IN (SELECT `guid` FROM `creature` WHERE `id`=61080);
|
||||
DELETE FROM `creature` WHERE `id`=61080;
|
||||
|
||||
|
||||
-- NPC Squirrel (61081)
|
||||
DELETE FROM `creature_addon` WHERE `guid` IN (SELECT `guid` FROM `creature` WHERE `id`=61081);
|
||||
DELETE FROM `creature` WHERE `id`=61081;
|
||||
|
||||
|
||||
-- NPC Super Shellkhan Gang (198147)
|
||||
DELETE FROM `creature_addon` WHERE `guid` IN (SELECT `guid` FROM `creature` WHERE `id`=198147);
|
||||
DELETE FROM `creature` WHERE `id`=198147;
|
||||
UPDATE `creature_template_addon` SET `SheathState`=0 WHERE `entry`=198147;
|
||||
|
||||
|
||||
-- GO Trail of Gore (205162)
|
||||
DELETE FROM `gameobject_addon` WHERE `guid` IN (SELECT `guid` FROM `gameobject` WHERE `id`=205162);
|
||||
DELETE FROM `gameobject` WHERE `id`=205162;
|
||||
|
||||
|
||||
-- GO Trail of Gore (205163)
|
||||
DELETE FROM `gameobject_addon` WHERE `guid` IN (SELECT `guid` FROM `gameobject` WHERE `id`=205163);
|
||||
DELETE FROM `gameobject` WHERE `id`=205163;
|
||||
|
||||
|
||||
-- GO Worm Mound (204281)
|
||||
DELETE FROM `gameobject_addon` WHERE `guid` IN (SELECT `guid` FROM `gameobject` WHERE `id`=204281);
|
||||
DELETE FROM `gameobject` WHERE `id`=204281;
|
||||
|
||||
|
||||
-- NPC ELM General Purpose Bunny (23837)
|
||||
UPDATE `creature_template` SET `flags_extra`=128 WHERE `entry`=23837;
|
||||
UPDATE `creature_template_addon` SET `SheathState`=0 WHERE `entry`=23837;
|
||||
UPDATE `creature_template_difficulty` SET `StaticFlags1`=536871168 WHERE `Entry`=23837;
|
||||
|
||||
|
||||
-- Event Darkmoon Faire (3)
|
||||
DELETE FROM `game_event_gameobject` WHERE `guid` IN (113115,113116,113117,113118,113124,113126,113127,113128);
|
||||
INSERT INTO `game_event_gameobject` (`eventEntry`, `guid`) VALUES
|
||||
(3, 113115),
|
||||
(3, 113116),
|
||||
(3, 113117),
|
||||
(3, 113118),
|
||||
(3, 113124),
|
||||
(3, 113126),
|
||||
(3, 113127),
|
||||
(3, 113128);
|
||||
|
||||
|
||||
-- Event Fireworks Spectacular (72)
|
||||
DELETE FROM `game_event_gameobject` WHERE `guid` IN (111674,111673,111672,111671,111670,111669,111668,111667,111666,111665,111664,111663,111662,111661,162197,111660,111659);
|
||||
INSERT INTO `game_event_gameobject` (`eventEntry`, `guid`) VALUES
|
||||
(72, 111674),
|
||||
(72, 111673),
|
||||
(72, 111672),
|
||||
(72, 111671),
|
||||
(72, 111670),
|
||||
(72, 111669),
|
||||
(72, 111668),
|
||||
(72, 111667),
|
||||
(72, 111666),
|
||||
(72, 111665),
|
||||
(72, 111664),
|
||||
(72, 111663),
|
||||
(72, 111662),
|
||||
(72, 111661),
|
||||
(72, 162197),
|
||||
(72, 111660),
|
||||
(72, 111659);
|
||||
|
||||
|
||||
-- Event Midsummer Fire Festival (1)
|
||||
DELETE FROM `game_event_creature` WHERE `guid` IN (222734,222779,222785,222804,222860,222865,222872,222874,222882,222891,222895,222898,222952,222969,222973,222982,223005,223049,223051,223080,223085,223095,223121,223145,223147,223173,223185,223191,223193,223201,223229,223231,223233,223279,223282,223299,223328,223340,223363,223386,223389,223392,223432,223435,223440,223496,226696,226909,226923,226926,226933,226938,226947,227007,227024);
|
||||
INSERT INTO `game_event_creature` (`eventEntry`, `guid`) VALUES
|
||||
(1, 222734),
|
||||
(1, 222779),
|
||||
(1, 222785),
|
||||
(1, 222804),
|
||||
(1, 222860),
|
||||
(1, 222865),
|
||||
(1, 222872),
|
||||
(1, 222874),
|
||||
(1, 222882),
|
||||
(1, 222891),
|
||||
(1, 222895),
|
||||
(1, 222898),
|
||||
(1, 222952),
|
||||
(1, 222969),
|
||||
(1, 222973),
|
||||
(1, 222982),
|
||||
(1, 223005),
|
||||
(1, 223049),
|
||||
(1, 223051),
|
||||
(1, 223080),
|
||||
(1, 223085),
|
||||
(1, 223095),
|
||||
(1, 223121),
|
||||
(1, 223145),
|
||||
(1, 223147),
|
||||
(1, 223173),
|
||||
(1, 223185),
|
||||
(1, 223191),
|
||||
(1, 223193),
|
||||
(1, 223201),
|
||||
(1, 223229),
|
||||
(1, 223231),
|
||||
(1, 223233),
|
||||
(1, 223279),
|
||||
(1, 223282),
|
||||
(1, 223299),
|
||||
(1, 223328),
|
||||
(1, 223340),
|
||||
(1, 223363),
|
||||
(1, 223386),
|
||||
(1, 223389),
|
||||
(1, 223392),
|
||||
(1, 223432),
|
||||
(1, 223435),
|
||||
(1, 223440),
|
||||
(1, 223496),
|
||||
(1, 226696),
|
||||
(1, 226909),
|
||||
(1, 226923),
|
||||
(1, 226926),
|
||||
(1, 226933),
|
||||
(1, 226938),
|
||||
(1, 226947),
|
||||
(1, 227007),
|
||||
(1, 227024);
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
DELETE FROM `areatrigger_create_properties` WHERE (`Id`=35958 AND `IsCustom`=0);
|
||||
INSERT INTO `areatrigger_create_properties` (`Id`, `IsCustom`, `AreaTriggerId`, `IsAreatriggerCustom`, `Flags`, `MoveCurveId`, `ScaleCurveId`, `MorphCurveId`, `FacingCurveId`, `AnimId`, `AnimKitId`, `DecalPropertiesId`, `SpellForVisuals`, `PositionalSoundKitId`, `TimeToTargetScale`, `Speed`, `Shape`, `ShapeData0`, `ShapeData1`, `ShapeData2`, `ShapeData3`, `ShapeData4`, `ShapeData5`, `ShapeData6`, `ShapeData7`, `ScriptName`, `VerifiedBuild`) VALUES
|
||||
(35958, 0, 3678, 0, 0, 0, 0, 0, 0, -1, 0, 0, 132950, 0, 20000, 0, 4, 15, 15, 7, 7, 3, 3, 0, 0, 'at_hun_legion_flare', 69875); -- SpellForVisuals: 132950 (Flare)
|
||||
|
||||
UPDATE `areatrigger_create_properties` SET `ScriptName`='at_hun_legion_flare' WHERE `Id`=510;
|
||||
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_hun_kindling_flare';
|
||||
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
|
||||
(132950, 'spell_hun_kindling_flare');
|
||||
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_hun_take_aim';
|
||||
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
|
||||
(257045, 'spell_hun_take_aim');
|
||||
|
||||
DELETE FROM `spell_proc` WHERE `SpellId` IN (1301406);
|
||||
INSERT INTO `spell_proc` (`SpellId`,`SchoolMask`,`SpellFamilyName`,`SpellFamilyMask0`,`SpellFamilyMask1`,`SpellFamilyMask2`,`SpellFamilyMask3`,`ProcFlags`,`ProcFlags2`,`SpellTypeMask`,`SpellPhaseMask`,`HitMask`,`AttributesMask`,`DisableEffectsMask`,`ProcsPerMinute`,`Chance`,`Cooldown`,`Charges`) VALUES
|
||||
(1301406,0x00,9,0x00000000,0x80000000,0x00000000,0x00000000,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0,0,0,0); -- Tactical Reload
|
||||
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_hun_quick_draw', 'spell_hun_quick_draw_speed');
|
||||
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
|
||||
(459794, 'spell_hun_quick_draw'),
|
||||
(1279347, 'spell_hun_quick_draw_speed');
|
||||
|
||||
DELETE FROM `spell_proc` WHERE `SpellId` IN (459794);
|
||||
INSERT INTO `spell_proc` (`SpellId`,`SchoolMask`,`SpellFamilyName`,`SpellFamilyMask0`,`SpellFamilyMask1`,`SpellFamilyMask2`,`SpellFamilyMask3`,`ProcFlags`,`ProcFlags2`,`SpellTypeMask`,`SpellPhaseMask`,`HitMask`,`AttributesMask`,`DisableEffectsMask`,`ProcsPerMinute`,`Chance`,`Cooldown`,`Charges`) VALUES
|
||||
(459794,0x00,9,0x00020000,0x00000000,0x00000000,0x00000000,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0,0,0,0); -- Quick Draw
|
||||
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_hun_harriers_cry';
|
||||
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
|
||||
(466904, 'spell_hun_harriers_cry');
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
|
||||
INSERT IGNORE INTO `creature_questender` (`id`, `quest`, `VerifiedBuild`)
|
||||
SELECT steward.`entry`, quest.`ID`, 69875
|
||||
FROM (SELECT 233063 AS `entry` UNION ALL SELECT 233708) AS steward
|
||||
INNER JOIN `quest_template` AS quest ON quest.`ID` IN (91863, 94210);
|
||||
|
||||
-- Keep existing addon rows; only wire the tutorial predecessors.
|
||||
INSERT INTO `quest_template_addon` (`ID`, `PrevQuestID`)
|
||||
SELECT 93057, 0 FROM `quest_template` WHERE `ID` = 93057
|
||||
ON DUPLICATE KEY UPDATE `PrevQuestID` = VALUES(`PrevQuestID`);
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`, `PrevQuestID`)
|
||||
SELECT 91863, 0 FROM `quest_template` WHERE `ID` = 91863
|
||||
ON DUPLICATE KEY UPDATE `PrevQuestID` = VALUES(`PrevQuestID`);
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`, `PrevQuestID`)
|
||||
SELECT 94455, 0 FROM `quest_template` WHERE `ID` = 94455
|
||||
ON DUPLICATE KEY UPDATE `PrevQuestID` = VALUES(`PrevQuestID`);
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`, `PrevQuestID`)
|
||||
SELECT 91968,
|
||||
IF(EXISTS(SELECT 1 FROM `quest_template` WHERE `ID` = 94455), 94455, 91863)
|
||||
FROM `quest_template` WHERE `ID` = 91968
|
||||
ON DUPLICATE KEY UPDATE `PrevQuestID` = VALUES(`PrevQuestID`);
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`, `PrevQuestID`)
|
||||
SELECT 91969, 91968 FROM `quest_template` WHERE `ID` = 91969
|
||||
ON DUPLICATE KEY UPDATE `PrevQuestID` = VALUES(`PrevQuestID`);
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`, `PrevQuestID`)
|
||||
SELECT 94210, 91969 FROM `quest_template` WHERE `ID` = 94210
|
||||
ON DUPLICATE KEY UPDATE `PrevQuestID` = VALUES(`PrevQuestID`);
|
||||
|
||||
UPDATE `creature_template`
|
||||
SET `npcflag` = `npcflag` | 3,
|
||||
`ScriptName` = 'npc_housing_steward'
|
||||
WHERE `entry` IN (233063, 233708);
|
||||
|
||||
DELETE FROM `creature_queststarter`
|
||||
WHERE `id` IN (233063, 233708)
|
||||
AND `quest` IN (91863, 91968, 91969, 93057, 94455, 94210);
|
||||
|
||||
-- Exile's Reach: bind the C++ scripts. Without these rows the quest scripts never run,
|
||||
-- so the ship, beach, escorts and scenes do not advance.
|
||||
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_ship_166573_156280' WHERE `entry` IN (166573, 156280);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_ship_training_dummy' WHERE `entry` = 160737;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_ship_166583_160664' WHERE `entry` IN (166583, 160664);
|
||||
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_shore_166782_156626' WHERE `entry` IN (166782, 156626);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_shore_injured_buddie' WHERE `entry` IN (166786, 156612, 166791, 156610, 166796, 156609);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_shore_other_two_injured' WHERE `entry` IN (166784, 166800, 149917, 156622);
|
||||
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_abandoned_camp_166854_156607' WHERE `entry` IN (166854, 156607);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_abandoned_camp_166906_156651' WHERE `entry` IN (166906, 156651);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_abandoned_camp_175030_175031' WHERE `entry` IN (175030, 175031);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_jrokgar_161265' WHERE `entry` = 161265;
|
||||
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_quilboar_briarpatch_166824_156662' WHERE `entry` IN (166824, 156662);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_quilboar_briarpatch_166996_154327' WHERE `entry` IN (166996, 154327);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_geolord_grekog_151091' WHERE `entry` = 151091;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_quilboars_150237_150238' WHERE `entry` IN (150237, 150238);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_ogre_overseer_156676' WHERE `entry` = 156676;
|
||||
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_darkmaul_plains_167019_149899' WHERE `entry` IN (167019, 149899);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_darkmaul_plains_167905_156526' WHERE `entry` IN (167905, 156526);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_darkmaul_plains_167915_156749' WHERE `entry` IN (167915, 156749);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_darkmaul_plains_156736_156716' WHERE `entry` IN (156736, 156716);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_darkmaul_plains_156267' WHERE `entry` = 156267;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_darkmaul_plains_157114' WHERE `entry` = 157114;
|
||||
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_ogre_ruins_167145_156807' WHERE `entry` IN (167145, 156807);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_ogre_ruins_162817' WHERE `entry` = 162817;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_ogre_ruins_167126_167128_156799' WHERE `entry` IN (167126, 167128, 156799);
|
||||
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_hruns_barrow_156900' WHERE `entry` = 156900;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_hruns_barrow_167244_160964' WHERE `entry` IN (167244, 160964);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_hruns_barrow_156929_167254' WHERE `entry` IN (156929, 167254);
|
||||
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_ogre_ruins_156833_167219_156859_167307' WHERE `entry` IN (156833, 167219, 156859, 167307);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_harpy_roost_167298_153211' WHERE `entry` IN (167298, 153211);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_harpy_roost_155197_167301_155199_167300' WHERE `entry` IN (155197, 167301, 155199, 167300);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_harpy_roost_153964' WHERE `entry` = 153964;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_harpy_roost_152843_152571_152998' WHERE `entry` IN (152843, 152571, 152998);
|
||||
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_darkmaul_bridge_167596_156941' WHERE `entry` IN (167596, 156941);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_darkmaul_bridge_167598' WHERE `entry` = 167598;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_darkmaul_bridge_156943' WHERE `entry` = 156943;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_darkmaul_bridge_prisoners' WHERE `entry` IN (167599, 167597, 156944, 156942);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_killclaw_153266' WHERE `entry` = 153266;
|
||||
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_darkmaul_citadel_153239_153242_154103' WHERE `entry` IN (153239, 153242, 154103);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_darkmaul_citadel_153581_153582_153583' WHERE `entry` IN (153581, 153582, 153583);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_darkmaul_citadel_153580' WHERE `entry` = 153580;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_darkmaul_citadel_156954_167646' WHERE `entry` IN (156954, 167646);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_exiles_reach_darkmaul_citadel_161306' WHERE `entry` = 161306;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_tunk' WHERE `entry` = 157300;
|
||||
|
||||
UPDATE `gameobject_template` SET `ScriptName` = 'go_campfire_339769' WHERE `entry` = 339769;
|
||||
UPDATE `gameobject_template` SET `ScriptName` = 'go_exiles_reach_darkmaul_plains_326716_326717_326718_326719' WHERE `entry` IN (326716, 326717, 326718, 326719);
|
||||
UPDATE `gameobject_template` SET `ScriptName` = 'go_exiles_reach_hruns_barrow_339568_350796' WHERE `entry` IN (339568, 350796);
|
||||
UPDATE `gameobject_template` SET `ScriptName` = 'go_exiles_reach_harpy_roost_350803_327146' WHERE `entry` IN (350803, 327146);
|
||||
UPDATE `gameobject_template` SET `ScriptName` = 'go_exiles_reach_catapult_351477_326651' WHERE `entry` IN (351477, 326651);
|
||||
UPDATE `gameobject_template` SET `ScriptName` = 'go_exiles_reach_ogre_runestone_351476_339865' WHERE `entry` IN (351476, 339865);
|
||||
|
||||
UPDATE `instance_template` SET `script` = 'instance_darkmaul_citadel' WHERE `map` = 2236;
|
||||
INSERT INTO `instance_template` (`map`, `parent`, `script`, `insideResurrection`)
|
||||
SELECT 2236, 0, 'instance_darkmaul_citadel', 0 FROM DUAL
|
||||
WHERE NOT EXISTS (SELECT 1 FROM `instance_template` WHERE `map` = 2236);
|
||||
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName` IN (
|
||||
'spell_necrotic_ritual_325406',
|
||||
'spell_exiles_reach_scene_spells',
|
||||
'spell_exiles_reach_stormwind_teleport_299565',
|
||||
'spell_exiles_reach_orgrimmar_teleport_326311',
|
||||
'spell_trampling_charge_210131',
|
||||
'spell_ogre_transformation_313583',
|
||||
'spell_swooping_lunge_317559',
|
||||
'spell_re_sizing_313269',
|
||||
'spell_re_sizing_305716',
|
||||
'spell_resizer_hit_305742',
|
||||
'spell_re_sizing_325346',
|
||||
'spell_riding_giant_boar_305068',
|
||||
'spell_ride_vehicle_173426',
|
||||
'spell_giant_boar_charge_321627',
|
||||
'spell_giant_boar_ping_vehicle_305559',
|
||||
'spell_around_front_door_299483',
|
||||
'spell_around_cooking_area_299486'
|
||||
);
|
||||
|
||||
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
|
||||
(325406, 'spell_necrotic_ritual_325406'),
|
||||
(321690, 'spell_exiles_reach_scene_spells'),
|
||||
(321691, 'spell_exiles_reach_scene_spells'),
|
||||
(321692, 'spell_exiles_reach_scene_spells'),
|
||||
(321693, 'spell_exiles_reach_scene_spells'),
|
||||
(312605, 'spell_exiles_reach_scene_spells'),
|
||||
(299565, 'spell_exiles_reach_stormwind_teleport_299565'),
|
||||
(326311, 'spell_exiles_reach_orgrimmar_teleport_326311'),
|
||||
(210131, 'spell_trampling_charge_210131'),
|
||||
(313583, 'spell_ogre_transformation_313583'),
|
||||
(317559, 'spell_swooping_lunge_317559'),
|
||||
(313269, 'spell_re_sizing_313269'),
|
||||
(305716, 'spell_re_sizing_305716'),
|
||||
(305742, 'spell_resizer_hit_305742'),
|
||||
(325346, 'spell_re_sizing_325346'),
|
||||
(305068, 'spell_riding_giant_boar_305068'),
|
||||
(173426, 'spell_ride_vehicle_173426'),
|
||||
(321627, 'spell_giant_boar_charge_321627'),
|
||||
(305559, 'spell_giant_boar_ping_vehicle_305559'),
|
||||
(299483, 'spell_around_front_door_299483'),
|
||||
(299486, 'spell_around_cooking_area_299486');
|
||||
|
||||
DELETE FROM `item_script_names` WHERE `Id` = 168410;
|
||||
INSERT INTO `item_script_names` (`Id`, `ScriptName`) VALUES (168410, 'item_first_aid_kit');
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_gorgroth' WHERE `entry` = 156814;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_ravnyr' WHERE `entry` = 156501;
|
||||
|
||||
DELETE FROM `creature_text` WHERE `CreatureID` IN (156814, 156501);
|
||||
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `SoundPlayType`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
|
||||
(156814, 0, 0, 'Ravnyr will destroy you all!', 14, 0, 100, 0, 0, 0, 0, 0, 0, 'Gor''groth - Aggro'),
|
||||
(156814, 1, 0, 'We... will be... the final sacrifice!', 14, 0, 100, 0, 0, 0, 0, 0, 0, 'Gor''groth - Sacrifice'),
|
||||
(156501, 0, 0, 'Foolish ogre! You have given me nowhere near enough power!', 14, 0, 100, 0, 0, 0, 0, 0, 0, 'Ravnyr - Aggro'),
|
||||
(156501, 1, 0, 'Pathetic mortals. Your deaths will nourish me!', 14, 0, 100, 0, 0, 0, 0, 0, 0, 'Ravnyr - Slay');
|
||||
|
||||
-- Amirdrassil, Vault of the Incarnates (Sennarth) and De Other Side script bindings.
|
||||
-- Without ScriptName the creature AI never runs. Without instance_template.script the encounter state is not saved.
|
||||
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_gnarlroot' WHERE `entry` = 209333;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_igira_the_cruel' WHERE `entry` = 200926;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_volcoross' WHERE `entry` = 208478;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_urctos' WHERE `entry` = 208363;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_aerwynn' WHERE `entry` = 208365;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_pip' WHERE `entry` = 208367;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_larodar_keeper_of_the_flame' WHERE `entry` = 208445;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_nymue_weaver_of_the_cycle' WHERE `entry` = 206172;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_smolderon' WHERE `entry` = 200927;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_tindral_sageswift_seer_of_the_flame' WHERE `entry` = 209090;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_fyrakk_the_blazing' WHERE `entry` = 204931;
|
||||
|
||||
UPDATE `instance_template` SET `script` = 'instance_amirdrassil_the_dreams_hope' WHERE `map` = 2549;
|
||||
INSERT INTO `instance_template` (`map`, `parent`, `script`, `insideResurrection`)
|
||||
SELECT 2549, 0, 'instance_amirdrassil_the_dreams_hope', 0 FROM DUAL
|
||||
WHERE NOT EXISTS (SELECT 1 FROM `instance_template` WHERE `map` = 2549);
|
||||
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_sennarth' WHERE `entry` = 187967;
|
||||
UPDATE `instance_template` SET `script` = 'instance_vault_of_the_incarnates' WHERE `map` = 2522;
|
||||
INSERT INTO `instance_template` (`map`, `parent`, `script`, `insideResurrection`)
|
||||
SELECT 2522, 0, 'instance_vault_of_the_incarnates', 0 FROM DUAL
|
||||
WHERE NOT EXISTS (SELECT 1 FROM `instance_template` WHERE `map` = 2522);
|
||||
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_hakkar_the_soulflayer_os' WHERE `entry` = 164558;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_the_manastorms' WHERE `entry` IN (164556, 164555);
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_dealer_xyexa' WHERE `entry` = 164450;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_muehzala' WHERE `entry` = 166608;
|
||||
UPDATE `instance_template` SET `script` = 'instance_de_other_side' WHERE `map` = 2291;
|
||||
INSERT INTO `instance_template` (`map`, `parent`, `script`, `insideResurrection`)
|
||||
SELECT 2291, 0, 'instance_de_other_side', 0 FROM DUAL
|
||||
WHERE NOT EXISTS (SELECT 1 FROM `instance_template` WHERE `map` = 2291);
|
||||
|
||||
|
||||
REPLACE INTO `areatrigger_create_properties_orbit` (`AreaTriggerCreatePropertiesId`, `IsCustom`, `ExtraTimeForBlending`, `CircleRadius`, `BlendFromRadius`, `InitialAngle`, `ZOffset`, `CounterClockwise`, `CanLoop`, `VerifiedBuild`) VALUES
|
||||
(31874, 0, 0, 15, 14.99997234344482421, 1.714424490928649902, 0, 0, 0, 69875); -- Spell: 433766 (Eye of the Swarm)
|
||||
|
||||
|
||||
INSERT IGNORE INTO `conversation_actors` (`ConversationId`, `ConversationActorId`, `Idx`, `CreatureId`, `CreatureDisplayInfoId`, `NoActorObject`, `ActivePlayerObject`, `VerifiedBuild`) VALUES
|
||||
(15668, 76253, 0, 162804, 115723, 0, 0, 69875), -- Full: 0x203B1915C09EFD000420300000326EA9 Creature/0 R3782/S270384 Map: 2222 (The Shadowlands) Entry: 162804 (Ve'nari) Low: 3305129
|
||||
(26371, 96026, 0, 215405, 115723, 0, 0, 69875),
|
||||
(15664, 76253, 0, 162804, 95004, 0, 0, 69875),
|
||||
(15663, 76253, 0, 162804, 95004, 0, 0, 69875),
|
||||
(15662, 76253, 0, 162804, 95004, 0, 0, 69875),
|
||||
(15507, 76253, 0, 0, 0, 0, 0, 69875), -- Full: 0x0
|
||||
(15665, 76253, 0, 162804, 95004, 0, 0, 69875),
|
||||
(16869, 73604, 0, 175559, 101866, 0, 0, 69875);
|
||||
|
||||
|
||||
DELETE FROM `conversation_line_template` WHERE `Id`=42683;
|
||||
INSERT INTO `conversation_line_template` (`Id`, `UiCameraID`, `ActorIdx`, `Flags`, `ChatType`, `VerifiedBuild`) VALUES
|
||||
(42683, 1588, 0, 0, 0, 69875);
|
||||
|
||||
|
||||
DELETE FROM `conversation_template` WHERE `Id` IN (25181, 26371, 15507, 15665, 15664, 15663, 15662, 15668);
|
||||
INSERT INTO `conversation_template` (`Id`, `FirstLineID`, `TextureKitId`, `VerifiedBuild`) VALUES
|
||||
(25181, 68556, 0, 69875),
|
||||
(26371, 71951, 0, 69875),
|
||||
(15507, 38903, 0, 69875),
|
||||
(15665, 39300, 0, 69875),
|
||||
(15664, 39299, 0, 69875),
|
||||
(15663, 39298, 0, 69875),
|
||||
(15662, 39297, 0, 69875),
|
||||
(15668, 39303, 0, 69875);
|
||||
|
||||
UPDATE `conversation_template` SET `FirstLineID`=42683 WHERE `Id`=16869;
|
||||
|
||||
|
||||
DELETE FROM `world_quest_template` WHERE `QuestID` IN (58981 /*Hardened Hive*/, 54601 /*Ragebeak*/, 64974 /*Clean Up, Automa Aisle*/, 51467 /*Hyo'gi*/, 64854 /*Trappings of Success*/, 82964 /*Hillhelm Family: Uncle's Eye*/, 82963 /*Hillhelm Family: Lil Piggy*/, 51588 /*Familiar Foes*/, 56386 /*Elderspawn of Nalaada*/, 51461 /*Deathcap*/, 52200 /*Turtle Tactics*/, 55825 /*Bounty: A Few Fathom Rays*/, 65252 /*Stomp It Now*/, 58990 /*Titanus Egg*/, 65177 /*Fruit of the Bloom*/, 82995 /*Nerubian Device*/, 82966 /*Hillhelm Family: Unusual Potato*/, 51385 /*A Supply of Stingers*/, 82961 /*Hillhelm Family: The Chicken*/);
|
||||
INSERT INTO `world_quest_template` (`QuestID`, `Duration`, `VariableID`, `Value`) VALUES
|
||||
(58981, 86400, 18721, 1), -- Hardened Hive
|
||||
(54601, 86400, 16889, 1), -- Ragebeak
|
||||
(64974, 86400, 21351, 1), -- Clean Up, Automa Aisle
|
||||
(51467, 86400, 15239, 1), -- Hyo'gi
|
||||
(64854, 86400, 21241, 1), -- Trappings of Success
|
||||
(82964, 604800, 23011, 1), -- Hillhelm Family: Uncle's Eye
|
||||
(82963, 604800, 23011, 1), -- Hillhelm Family: Lil Piggy
|
||||
(51588, 86400, 15490, 1), -- Familiar Foes
|
||||
(56386, 86400, 17787, 6), -- Elderspawn of Nalaada
|
||||
(51461, 86400, 15237, 1), -- Deathcap
|
||||
(52200, 86400, 15660, 1), -- Turtle Tactics
|
||||
(55825, 86400, 17520, 1), -- Bounty: A Few Fathom Rays
|
||||
(65252, 86400, 21377, 1), -- Stomp It Now
|
||||
(58990, 86400, 18722, 1), -- Titanus Egg
|
||||
(65177, 86400, 21353, 1), -- Fruit of the Bloom
|
||||
(82995, 604800, 23011, 1), -- Nerubian Device
|
||||
(82966, 604800, 23011, 1), -- Hillhelm Family: Unusual Potato
|
||||
(51385, 86400, 15206, 1), -- A Supply of Stingers
|
||||
(82961, 604800, 23011, 1); -- Hillhelm Family: The Chicken
|
||||
|
||||
|
||||
DELETE FROM `creature_template_difficulty` WHERE (`DifficultyID`=205 AND `Entry` IN (224552,218324,217533,216413,216293,216336,253060));
|
||||
INSERT INTO `creature_template_difficulty` (`Entry`, `DifficultyID`, `HealthScalingExpansion`, `HealthModifier`, `ManaModifier`, `CreatureDifficultyID`, `TypeFlags`, `TypeFlags2`, `TypeFlags3`) VALUES
|
||||
(224552, 205, 10, 1500, 1, 275475, 0x0, 67108928, 0), -- Rasha'nan
|
||||
(218324, 205, 10, 10, 1, 267828, 0x200048, 2147483648, 0), -- Nakt
|
||||
(217533, 205, 10, 12, 1, 267026, 0x200048, 2147483648, 0), -- Atik
|
||||
(216413, 205, 10, 1, 1, 265899, 0x60000010, 6, 0), -- [DNT] Spawner
|
||||
(216293, 205, 10, 4.5, 1, 265779, 0x200048, 0, 0), -- Trilling Attendant
|
||||
(216336, 205, 10, 1.279999971389770507, 1, 265822, 0x200048, 0, 0), -- Ravenous Crawler
|
||||
(253060, 205, 11, 1, 1, 333916, 0x0, 0, 0); -- El-ahrairah
|
||||
|
||||
|
||||
DELETE FROM `creature_template_difficulty` WHERE (`DifficultyID`=205 AND `Entry` IN (253060,216293,218324,217533,224552,216413,216336));
|
||||
INSERT INTO `creature_template_difficulty` (`Entry`, `DifficultyID`, `LevelScalingDeltaMin`, `LevelScalingDeltaMax`, `ContentTuningID`, `StaticFlags1`, `StaticFlags2`, `StaticFlags3`, `StaticFlags4`, `StaticFlags5`, `StaticFlags6`, `StaticFlags7`, `StaticFlags8`, `VerifiedBuild`) VALUES
|
||||
(253060, 205, 0, 0, 181, 0x100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 69875), -- 253060 (El-ahrairah) - Sessile
|
||||
(216293, 205, 0, 0, 2893, 0x10000000, 0x0, 0x0, 0x2000000, 0x0, 0x0, 0x0, 0x0, 69875), -- 216293 (Trilling Attendant) - CanSwim - HideInCombatLog
|
||||
(218324, 205, 1, 1, 2893, 0x10000100, 0x0, 0x0, 0x2000000, 0x0, 0x0, 0x0, 0x0, 69875), -- 218324 (Nakt) - Sessile, CanSwim - HideInCombatLog
|
||||
(217533, 205, 1, 1, 2893, 0x10000100, 0x0, 0x0, 0x2000000, 0x0, 0x0, 0x0, 0x0, 69875), -- 217533 (Atik) - Sessile, CanSwim - HideInCombatLog
|
||||
(224552, 205, 3, 3, 2893, 0x30000000, 0x0, 0x4, 0x0, 0x1, 0x0, 0x0, 0x0, 69875), -- 224552 (Rasha'nan) - CanSwim, Floating - DoNotFadeIn - UntargetableByClient
|
||||
(216413, 205, 0, 0, 2893, 0x100, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 69875), -- 216413 ([DNT] Spawner) - Sessile - UntargetableByClient
|
||||
(216336, 205, 0, 0, 2893, 0x10000000, 0x0, 0x4, 0x2000000, 0x0, 0x0, 0x0, 0x0, 69875); -- 216336 (Ravenous Crawler) - CanSwim - DoNotFadeIn - HideInCombatLog
|
||||
|
||||
UPDATE `creature_model_info` SET `BoundingRadius`=3.728271484375, `CombatReach`=3 WHERE `DisplayID`=114552;
|
||||
UPDATE `creature_model_info` SET `BoundingRadius`=0.310000002384185791, `CombatReach`=1 WHERE `DisplayID`=24107;
|
||||
UPDATE `creature_model_info` SET `BoundingRadius`=1.256006956100463867, `CombatReach`=1 WHERE `DisplayID`=96826;
|
||||
|
||||
UPDATE `creature_template_model` SET `CreatureDisplayID`=11686 WHERE (`Idx`=1 AND `CreatureID` IN (179114,247012,180358,180347,70528,177525)) OR (`Idx`=0 AND `CreatureID` IN (43499,216413));
|
||||
UPDATE `creature_template_model` SET `CreatureDisplayID`=27823 WHERE (`Idx`=1 AND `CreatureID` IN (230874,253060,172631,180633));
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,763 @@
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(88920), (88923), (88925), (88937), (88927), (88922), (88938), (88939), (88941)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 88923, `ExclusiveGroup` = 0 WHERE `ID` = 88920;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 88920, `NextQuestID` = 88925, `ExclusiveGroup` = 0 WHERE `ID` = 88923;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 88923, `NextQuestID` = 88937, `ExclusiveGroup` = 0 WHERE `ID` = 88925;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 88925, `NextQuestID` = 88927, `ExclusiveGroup` = 0 WHERE `ID` = 88937;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 88937, `NextQuestID` = 88922, `ExclusiveGroup` = 0 WHERE `ID` = 88927;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 88927, `NextQuestID` = 88938, `ExclusiveGroup` = 0 WHERE `ID` = 88922;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 88922, `NextQuestID` = 88939, `ExclusiveGroup` = 0 WHERE `ID` = 88938;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 88938, `NextQuestID` = 88941, `ExclusiveGroup` = 0 WHERE `ID` = 88939;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 88939, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 88941;
|
||||
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Legacy of the Amani (12.1 capital campaign). Wowhead / warcraft.wiki.gg:
|
||||
-- 92897 (Adventure Guide breadcrumb) -> 92895 -> 92899 -> 92900 -> 92901 ->
|
||||
-- 92904 -> 92907 -> 92955 -> (92957 + 92958) -> 92952 -> (92953 + 92951) ->
|
||||
-- 92954 -> 93010 -> 93011 -> 93012
|
||||
-- 92897 can be skipped. 92957/92958 and 92953/92951 are both required.
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(92897), (92895), (92899), (92900), (92901), (92904), (92907), (92955),
|
||||
(92957), (92958), (92952), (92953), (92951), (92954), (93010), (93011), (93012)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 92895, `ExclusiveGroup` = 0, `BreadcrumbForQuestId` = 92895 WHERE `ID` = 92897;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 92899, `ExclusiveGroup` = 0, `BreadcrumbForQuestId` = 0 WHERE `ID` = 92895;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92895, `NextQuestID` = 92900, `ExclusiveGroup` = 0 WHERE `ID` = 92899;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92899, `NextQuestID` = 92901, `ExclusiveGroup` = 0 WHERE `ID` = 92900;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92900, `NextQuestID` = 92904, `ExclusiveGroup` = 0 WHERE `ID` = 92901;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92901, `NextQuestID` = 92907, `ExclusiveGroup` = 0 WHERE `ID` = 92904;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92904, `NextQuestID` = 92955, `ExclusiveGroup` = 0 WHERE `ID` = 92907;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92907, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 92955;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92955, `NextQuestID` = 92952, `ExclusiveGroup` = -92957 WHERE `ID` IN (92957, 92958);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 92952;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92952, `NextQuestID` = 92954, `ExclusiveGroup` = -92953 WHERE `ID` IN (92953, 92951);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 93010, `ExclusiveGroup` = 0 WHERE `ID` = 92954;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92954, `NextQuestID` = 93011, `ExclusiveGroup` = 0 WHERE `ID` = 93010;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 93010, `NextQuestID` = 93012, `ExclusiveGroup` = 0 WHERE `ID` = 93011;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 93011, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 93012;
|
||||
|
||||
|
||||
-- 253640 Orweyna is in Silvermoon (Wowhead; accept line for 92895).
|
||||
-- 241795 Orweyna is in Harandar (Wowhead; turn-in for 92895 / start 92899).
|
||||
-- npcflag 1 = gossip, 2 = questgiver.
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3 WHERE `entry` IN (253640, 241795);
|
||||
|
||||
DELETE FROM `creature_queststarter` WHERE (`id` = 253640 AND `quest` = 92895) OR (`id` = 241795 AND `quest` = 92899);
|
||||
INSERT INTO `creature_queststarter` (`id`, `quest`, `VerifiedBuild`) VALUES
|
||||
(253640, 92895, 69497), -- Hagar's Invitation offered by Orweyna in Silvermoon
|
||||
(241795, 92899, 69497); -- History Lesson offered by Orweyna in Harandar
|
||||
|
||||
DELETE FROM `creature_questender` WHERE (`id` = 253640 AND `quest` = 92897) OR (`id` = 241795 AND `quest` IN (92895, 92899));
|
||||
INSERT INTO `creature_questender` (`id`, `quest`, `VerifiedBuild`) VALUES
|
||||
(253640, 92897, 69497), -- The Preparations Are Complete turned in to Orweyna in Silvermoon
|
||||
(241795, 92895, 69497), -- Hagar's Invitation turned in to Orweyna in Harandar
|
||||
(241795, 92899, 69497); -- History Lesson turned in to Orweyna in Harandar
|
||||
|
||||
-- Midnight leveling campaign. Quest IDs and order come from Wowhead storyline
|
||||
-- pages plus warcraft.wiki.gg. TBC Eversong/Ghostlands scripts stay for Chromie Time.
|
||||
-- Parallel steps use ExclusiveGroup < 0 (all required). The two Paved in Ash IDs
|
||||
-- (86735/86736) are faction variants (ExclusiveGroup > 0). Bonus / sojourner
|
||||
-- quests stay unlinked. No invented IDs or spawns.
|
||||
--
|
||||
-- After Eversong, Zul'Aman / Harandar / Arator's Journey can be done in any
|
||||
-- order. Voidstorm is last on live; that three-path gate is not encoded here
|
||||
-- (quest_template_addon has one PrevQuestID).
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Intro: The Light's Summons (Wowhead 91281)
|
||||
-- 91281 -> 88719 -> 86769 -> (86770 + 89271 + 86780) -> (86805 + 89012)
|
||||
-- -> 86806 -> 86807 -> (91274 + 86834) -> (86811 + 86848) -> 86849 -> 86850
|
||||
-- -> 86852. Bonus Clear the Decks / Light Show / Protecting the Flank stay off.
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(91281), (88719), (86769), (86770), (89271), (86780), (86805), (89012),
|
||||
(86806), (86807), (91274), (86834), (86811), (86848), (86849), (86850),
|
||||
(86852)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 88719, `ExclusiveGroup` = 0 WHERE `ID` = 91281;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 91281, `NextQuestID` = 86769, `ExclusiveGroup` = 0 WHERE `ID` = 88719;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 88719, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86769;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86769, `NextQuestID` = 0, `ExclusiveGroup` = -86770 WHERE `ID` IN (86770, 89271, 86780);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86770, `NextQuestID` = 86806, `ExclusiveGroup` = -86805 WHERE `ID` IN (86805, 89012);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86805, `NextQuestID` = 86807, `ExclusiveGroup` = 0 WHERE `ID` = 86806;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86806, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86807;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86807, `NextQuestID` = 0, `ExclusiveGroup` = -86834 WHERE `ID` IN (86834, 91274);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86834, `NextQuestID` = 86849, `ExclusiveGroup` = -86811 WHERE `ID` IN (86811, 86848);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86850, `ExclusiveGroup` = 0 WHERE `ID` = 86849;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86849, `NextQuestID` = 86852, `ExclusiveGroup` = 0 WHERE `ID` = 86850;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86850, `NextQuestID` = 86733, `ExclusiveGroup` = 0 WHERE `ID` = 86852;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Eversong: Whispers in the Twilight (Wowhead 86733)
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(86733), (86734), (86735), (86736), (86737), (86738), (86739), (86740),
|
||||
(86741), (86742), (86743), (86744), (86745)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86852, `NextQuestID` = 86734, `ExclusiveGroup` = 0 WHERE `ID` = 86733;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86733, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86734;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86734, `NextQuestID` = 86737, `ExclusiveGroup` = 86735 WHERE `ID` IN (86735, 86736);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86737;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86737, `NextQuestID` = 86741, `ExclusiveGroup` = -86738 WHERE `ID` IN (86738, 86739, 86740);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86741;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86741, `NextQuestID` = 86744, `ExclusiveGroup` = -86742 WHERE `ID` IN (86742, 86743);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86745, `ExclusiveGroup` = 0 WHERE `ID` = 86744;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86744, `NextQuestID` = 86621, `ExclusiveGroup` = 0 WHERE `ID` = 86745;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Eversong: Shadowfall (Wowhead 86621). Tranquillien chapter, not Outland
|
||||
-- Shadowmoon. 86625 The Clue in the Inn is not on the wiki campaign list.
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(86621), (86623), (86624), (90907), (86622), (86626), (86632), (90509),
|
||||
(90493), (90494), (86781), (86634), (86633), (86635), (86636)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86745, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86621;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86621, `NextQuestID` = 90907, `ExclusiveGroup` = -86623 WHERE `ID` IN (86623, 86624);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86622, `ExclusiveGroup` = 0 WHERE `ID` = 90907;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 90907, `NextQuestID` = 86626, `ExclusiveGroup` = 0 WHERE `ID` = 86622;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86622, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86626;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86626, `NextQuestID` = 90494, `ExclusiveGroup` = -86632 WHERE `ID` IN (86632, 90509, 90493);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86781, `ExclusiveGroup` = 0 WHERE `ID` = 90494;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 90494, `NextQuestID` = 86634, `ExclusiveGroup` = 0 WHERE `ID` = 86781;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86781, `NextQuestID` = 86633, `ExclusiveGroup` = 0 WHERE `ID` = 86634;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86634, `NextQuestID` = 86635, `ExclusiveGroup` = 0 WHERE `ID` = 86633;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86633, `NextQuestID` = 86636, `ExclusiveGroup` = 0 WHERE `ID` = 86635;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86635, `NextQuestID` = 86637, `ExclusiveGroup` = 0 WHERE `ID` = 86636;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Eversong: Ripple Effects (Wowhead 86637). Skip 86645 Hidden [DNT].
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(86637), (86638), (86639), (86640), (86641), (86642), (86643), (86644),
|
||||
(86646), (86647), (86648), (86649), (86650)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86636, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86637;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86637, `NextQuestID` = 86640, `ExclusiveGroup` = -86638 WHERE `ID` IN (86638, 86639);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86640;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86640, `NextQuestID` = 86643, `ExclusiveGroup` = -86641 WHERE `ID` IN (86641, 86642);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86644, `ExclusiveGroup` = 0 WHERE `ID` = 86643;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86643, `NextQuestID` = 86646, `ExclusiveGroup` = 0 WHERE `ID` = 86644;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86644, `NextQuestID` = 86647, `ExclusiveGroup` = 0 WHERE `ID` = 86646;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86646, `NextQuestID` = 86648, `ExclusiveGroup` = 0 WHERE `ID` = 86647;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86647, `NextQuestID` = 86649, `ExclusiveGroup` = 0 WHERE `ID` = 86648;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86648, `NextQuestID` = 86650, `ExclusiveGroup` = 0 WHERE `ID` = 86649;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86649, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86650;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Zul'Aman: Dis Was Our Land (Wowhead 86708)
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(86708), (86710), (90749), (86868), (86711), (86719), (86717), (86716),
|
||||
(86721), (86712), (86718), (86715), (86720), (86722), (86723), (86652)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86710, `ExclusiveGroup` = 0 WHERE `ID` = 86708;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86708, `NextQuestID` = 90749, `ExclusiveGroup` = 0 WHERE `ID` = 86710;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86710, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 90749;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 90749, `NextQuestID` = 0, `ExclusiveGroup` = -86868 WHERE `ID` IN (86868, 86711);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86868, `NextQuestID` = 0, `ExclusiveGroup` = -86719 WHERE `ID` IN (86719, 86717);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86719, `NextQuestID` = 0, `ExclusiveGroup` = -86716 WHERE `ID` IN (86716, 86721);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86716, `NextQuestID` = 86720, `ExclusiveGroup` = -86712 WHERE `ID` IN (86712, 86718, 86715);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86722, `ExclusiveGroup` = 0 WHERE `ID` = 86720;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86720, `NextQuestID` = 86723, `ExclusiveGroup` = 0 WHERE `ID` = 86722;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86722, `NextQuestID` = 86652, `ExclusiveGroup` = 0 WHERE `ID` = 86723;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86723, `NextQuestID` = 86653, `ExclusiveGroup` = 0 WHERE `ID` = 86652;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Zul'Aman: Path of de Hash'ey (Wowhead 86653)
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(86653), (86655), (89334), (86654), (86656), (86809), (86657), (86658),
|
||||
(86660), (86659), (92084), (86661), (86808), (86663), (86664), (86665),
|
||||
(90772), (86666)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86652, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86653;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86653, `NextQuestID` = 86656, `ExclusiveGroup` = -86655 WHERE `ID` IN (86655, 89334, 86654);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86809, `ExclusiveGroup` = 0 WHERE `ID` = 86656;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86656, `NextQuestID` = 86657, `ExclusiveGroup` = 0 WHERE `ID` = 86809;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86809, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86657;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86657, `NextQuestID` = 86659, `ExclusiveGroup` = -86658 WHERE `ID` IN (86658, 86660);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 92084, `ExclusiveGroup` = 0 WHERE `ID` = 86659;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86659, `NextQuestID` = 86661, `ExclusiveGroup` = 0 WHERE `ID` = 92084;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92084, `NextQuestID` = 86808, `ExclusiveGroup` = 0 WHERE `ID` = 86661;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86661, `NextQuestID` = 86663, `ExclusiveGroup` = 0 WHERE `ID` = 86808;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86808, `NextQuestID` = 86664, `ExclusiveGroup` = 0 WHERE `ID` = 86663;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86663, `NextQuestID` = 86665, `ExclusiveGroup` = 0 WHERE `ID` = 86664;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86664, `NextQuestID` = 90772, `ExclusiveGroup` = 0 WHERE `ID` = 86665;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86665, `NextQuestID` = 86666, `ExclusiveGroup` = 0 WHERE `ID` = 90772;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 90772, `NextQuestID` = 86681, `ExclusiveGroup` = 0 WHERE `ID` = 86666;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Zul'Aman: Where War Slumbers (Wowhead 86681)
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(86681), (86682), (91958)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86666, `NextQuestID` = 86682, `ExclusiveGroup` = 0 WHERE `ID` = 86681;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86681, `NextQuestID` = 91958, `ExclusiveGroup` = 0 WHERE `ID` = 86682;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86682, `NextQuestID` = 86683, `ExclusiveGroup` = 0 WHERE `ID` = 91958;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Zul'Aman: De Amani Never Die (Wowhead 86683)
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(86683), (86684), (86687), (86685), (86686), (91001), (86692), (86693),
|
||||
(91062), (91087)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 91958, `NextQuestID` = 86684, `ExclusiveGroup` = 0 WHERE `ID` = 86683;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86683, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86684;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86684, `NextQuestID` = 91001, `ExclusiveGroup` = -86687 WHERE `ID` IN (86687, 86685, 86686);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86692, `ExclusiveGroup` = 0 WHERE `ID` = 91001;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 91001, `NextQuestID` = 86693, `ExclusiveGroup` = 0 WHERE `ID` = 86692;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86692, `NextQuestID` = 91062, `ExclusiveGroup` = 0 WHERE `ID` = 86693;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86693, `NextQuestID` = 91087, `ExclusiveGroup` = 0 WHERE `ID` = 91062;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 91062, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 91087;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Harandar: Of Caves and Cradles (Wowhead 86899). 89402 is the zone breadcrumb.
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(89402), (86899), (86900), (86901), (86929), (86907), (86911), (90094),
|
||||
(90095), (86912), (86913), (86914), (86956), (86910), (86973), (86942),
|
||||
(89034), (86944)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86899, `ExclusiveGroup` = 0, `BreadcrumbForQuestId` = 86899 WHERE `ID` = 89402;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86900, `ExclusiveGroup` = 0, `BreadcrumbForQuestId` = 0 WHERE `ID` = 86899;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86899, `NextQuestID` = 86901, `ExclusiveGroup` = 0 WHERE `ID` = 86900;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86900, `NextQuestID` = 86929, `ExclusiveGroup` = 0 WHERE `ID` = 86901;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86901, `NextQuestID` = 86907, `ExclusiveGroup` = 0 WHERE `ID` = 86929;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86929, `NextQuestID` = 86911, `ExclusiveGroup` = 0 WHERE `ID` = 86907;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86907, `NextQuestID` = 90094, `ExclusiveGroup` = 0 WHERE `ID` = 86911;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86911, `NextQuestID` = 90095, `ExclusiveGroup` = 0 WHERE `ID` = 90094;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 90094, `NextQuestID` = 86912, `ExclusiveGroup` = 0 WHERE `ID` = 90095;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 90095, `NextQuestID` = 86913, `ExclusiveGroup` = 0 WHERE `ID` = 86912;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86912, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86913;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86913, `NextQuestID` = 86910, `ExclusiveGroup` = -86914 WHERE `ID` IN (86914, 86956);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86910;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86910, `NextQuestID` = 86944, `ExclusiveGroup` = -86973 WHERE `ID` IN (86973, 86942, 89034);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86930, `ExclusiveGroup` = 0 WHERE `ID` = 86944;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Harandar: Call of the Goddess (Wowhead 86930)
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(86930), (86864), (86836), (86855), (86851), (86856), (86857), (86858),
|
||||
(86861), (86860), (86859), (86862), (86865), (86866), (94677), (86882),
|
||||
(86867), (86881), (86880), (86877), (86890)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86944, `NextQuestID` = 86864, `ExclusiveGroup` = 0 WHERE `ID` = 86930;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86930, `NextQuestID` = 86836, `ExclusiveGroup` = 0 WHERE `ID` = 86864;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86864, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86836;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86836, `NextQuestID` = 86856, `ExclusiveGroup` = -86855 WHERE `ID` IN (86855, 86851);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86857, `ExclusiveGroup` = 0 WHERE `ID` = 86856;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86856, `NextQuestID` = 86858, `ExclusiveGroup` = 0 WHERE `ID` = 86857;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86857, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86858;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86858, `NextQuestID` = 86862, `ExclusiveGroup` = -86861 WHERE `ID` IN (86861, 86860, 86859);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86865, `ExclusiveGroup` = 0 WHERE `ID` = 86862;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86862, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86865;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86865, `NextQuestID` = 86882, `ExclusiveGroup` = -86866 WHERE `ID` IN (86866, 94677);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86867, `ExclusiveGroup` = 0 WHERE `ID` = 86882;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86882, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86867;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86867, `NextQuestID` = 86890, `ExclusiveGroup` = -86881 WHERE `ID` IN (86881, 86880, 86877);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86883, `ExclusiveGroup` = 0 WHERE `ID` = 86890;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Harandar: Emergence (Wowhead 86883)
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(86883), (86885), (86884), (86887), (86891), (86892), (86894), (86896),
|
||||
(86897), (86898), (91084)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86890, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86883;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86883, `NextQuestID` = 0, `ExclusiveGroup` = -86885 WHERE `ID` IN (86885, 86884);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86885, `NextQuestID` = 86892, `ExclusiveGroup` = -86887 WHERE `ID` IN (86887, 86891);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86892;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86892, `NextQuestID` = 86897, `ExclusiveGroup` = -86894 WHERE `ID` IN (86894, 86896);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86898, `ExclusiveGroup` = 0 WHERE `ID` = 86897;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86897, `NextQuestID` = 91084, `ExclusiveGroup` = 0 WHERE `ID` = 86898;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86898, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 91084;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Arator: The Path of Light (Wowhead 86837). 89193 is the chapter breadcrumb.
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(89193), (86837), (86838), (86839), (86840), (86841), (86842), (86843),
|
||||
(86844), (92136), (86902), (86845), (91000), (86846), (89338)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86837, `ExclusiveGroup` = 0, `BreadcrumbForQuestId` = 86837 WHERE `ID` = 89193;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86838, `ExclusiveGroup` = 0, `BreadcrumbForQuestId` = 0 WHERE `ID` = 86837;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86837, `NextQuestID` = 86839, `ExclusiveGroup` = 0 WHERE `ID` = 86838;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86838, `NextQuestID` = 86840, `ExclusiveGroup` = 0 WHERE `ID` = 86839;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86839, `NextQuestID` = 86841, `ExclusiveGroup` = 0 WHERE `ID` = 86840;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86840, `NextQuestID` = 86842, `ExclusiveGroup` = 0 WHERE `ID` = 86841;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86841, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86842;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86842, `NextQuestID` = 92136, `ExclusiveGroup` = -86843 WHERE `ID` IN (86843, 86844);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86902, `ExclusiveGroup` = 0 WHERE `ID` = 92136;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92136, `NextQuestID` = 86845, `ExclusiveGroup` = 0 WHERE `ID` = 86902;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86902, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86845;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86845, `NextQuestID` = 89338, `ExclusiveGroup` = -91000 WHERE `ID` IN (91000, 86846);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86822, `ExclusiveGroup` = 0 WHERE `ID` = 89338;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Arator: Regrets of the Past (Wowhead 86822)
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(86822), (86823), (86824), (86825), (91391), (86827), (86826), (91842),
|
||||
(86828), (86831), (86830), (86829), (91726), (86832), (86833), (86903),
|
||||
(91787)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 89338, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86822;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86822, `NextQuestID` = 91391, `ExclusiveGroup` = -86823 WHERE `ID` IN (86823, 86824, 86825);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 91391;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 91391, `NextQuestID` = 86828, `ExclusiveGroup` = -86827 WHERE `ID` IN (86827, 86826, 91842);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86828;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86828, `NextQuestID` = 86829, `ExclusiveGroup` = -86831 WHERE `ID` IN (86831, 86830);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 91726, `ExclusiveGroup` = 0 WHERE `ID` = 86829;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86829, `NextQuestID` = 86832, `ExclusiveGroup` = 0 WHERE `ID` = 91726;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 91726, `NextQuestID` = 86833, `ExclusiveGroup` = 0 WHERE `ID` = 86832;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86832, `NextQuestID` = 86903, `ExclusiveGroup` = 0 WHERE `ID` = 86833;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86833, `NextQuestID` = 91787, `ExclusiveGroup` = 0 WHERE `ID` = 86903;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86903, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 91787;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Voidstorm: Into the Abyss (Wowhead 86543). 89388 is the zone breadcrumb.
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(89388), (92061), (86543), (86549), (86558), (86557), (86559), (86562),
|
||||
(86561), (86565)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 92061, `ExclusiveGroup` = 0, `BreadcrumbForQuestId` = 92061 WHERE `ID` = 89388;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86543, `ExclusiveGroup` = 0, `BreadcrumbForQuestId` = 0 WHERE `ID` = 92061;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92061, `NextQuestID` = 86549, `ExclusiveGroup` = 0 WHERE `ID` = 86543;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86543, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86549;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86549, `NextQuestID` = 86559, `ExclusiveGroup` = -86558 WHERE `ID` IN (86558, 86557);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86559;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86559, `NextQuestID` = 86565, `ExclusiveGroup` = -86562 WHERE `ID` IN (86562, 86561);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86536, `ExclusiveGroup` = 0 WHERE `ID` = 86565;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Voidstorm: The Night's Veil (Wowhead 86536)
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(86536), (86531), (86530), (86528), (86538), (86537), (86539), (86540),
|
||||
(86541), (88768), (86542), (89249), (86544), (86545)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86565, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86536;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86536, `NextQuestID` = 0, `ExclusiveGroup` = -86531 WHERE `ID` IN (86531, 86530, 86528);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86531, `NextQuestID` = 86539, `ExclusiveGroup` = -86538 WHERE `ID` IN (86538, 86537);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86539;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86539, `NextQuestID` = 86542, `ExclusiveGroup` = -86540 WHERE `ID` IN (86540, 86541, 88768);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 89249, `ExclusiveGroup` = 0 WHERE `ID` = 86542;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86542, `NextQuestID` = 86544, `ExclusiveGroup` = 0 WHERE `ID` = 89249;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 89249, `NextQuestID` = 86545, `ExclusiveGroup` = 0 WHERE `ID` = 86544;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86544, `NextQuestID` = 86509, `ExclusiveGroup` = 0 WHERE `ID` = 86545;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Voidstorm: Dawn of Reckoning (Wowhead 86509)
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(86509), (86510), (90571), (86511), (86512), (86513), (86514), (86516),
|
||||
(86517), (86515), (86518), (86519), (86520), (86521), (86522), (95276)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86545, `NextQuestID` = 86510, `ExclusiveGroup` = 0 WHERE `ID` = 86509;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86509, `NextQuestID` = 90571, `ExclusiveGroup` = 0 WHERE `ID` = 86510;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86510, `NextQuestID` = 86511, `ExclusiveGroup` = 0 WHERE `ID` = 90571;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 90571, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86511;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86511, `NextQuestID` = 86514, `ExclusiveGroup` = -86512 WHERE `ID` IN (86512, 86513);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 86514;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86514, `NextQuestID` = 86518, `ExclusiveGroup` = -86516 WHERE `ID` IN (86516, 86517, 86515);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 86519, `ExclusiveGroup` = 0 WHERE `ID` = 86518;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86518, `NextQuestID` = 86520, `ExclusiveGroup` = 0 WHERE `ID` = 86519;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86519, `NextQuestID` = 86521, `ExclusiveGroup` = 0 WHERE `ID` = 86520;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86520, `NextQuestID` = 86522, `ExclusiveGroup` = 0 WHERE `ID` = 86521;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86521, `NextQuestID` = 95276, `ExclusiveGroup` = 0 WHERE `ID` = 86522;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 86522, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 95276;
|
||||
|
||||
-- Harandar chapter 1 conversations already implemented in C++.
|
||||
UPDATE `conversation_template` SET `ScriptName` = 'conversation_the_root_cause_open_portal' WHERE `Id` = 28444;
|
||||
UPDATE `conversation_template` SET `ScriptName` = 'conversation_to_harathir_follow_orweyna' WHERE `Id` = 29720;
|
||||
UPDATE `conversation_template` SET `ScriptName` = 'conversation_to_harathir_talk_to_kupaal' WHERE `Id` = 29598;
|
||||
|
||||
-- Missing Midnight content after 2026_09_22_15.
|
||||
-- 1) Bind Blinding Vale, Nexus-Point Xenas, and Voidscar Arena. The C++ already
|
||||
-- exists; ScriptName and instance_template.script were never set, so the AIs
|
||||
-- never attached. NPC entries match the enums next to each Register* call.
|
||||
-- 2) Wire the max-level War of Light and Shadow plus the remaining Curse of
|
||||
-- Ula'tek chapters. IDs and order come from Wowhead storyline lists plus
|
||||
-- warcraft.wiki.gg parallels. Sojourner / Snake Charmed stay unlinked.
|
||||
-- No invented IDs or spawns.
|
||||
|
||||
-- ===========================================================================
|
||||
-- Blinding Vale (map 2859)
|
||||
-- ===========================================================================
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_kezkitt' WHERE `entry` = 243029;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_meittik' WHERE `entry` = 243028;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_lekshi' WHERE `entry` = 243030;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_lightblossom' WHERE `entry` = 244528;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_ikuzz' WHERE `entry` = 244887;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_bloodthorn_roots' WHERE `entry` = 253571;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_lightwarden_ruia' WHERE `entry` = 245912;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_ziekket' WHERE `entry` = 247676;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_lightspawn_lasher' WHERE `entry` = 247755;
|
||||
|
||||
UPDATE `instance_template` SET `script` = 'instance_blindingvale' WHERE `map` = 2859;
|
||||
INSERT INTO `instance_template` (`map`, `parent`, `script`, `insideResurrection`)
|
||||
SELECT 2859, 0, 'instance_blindingvale', 0 FROM DUAL
|
||||
WHERE NOT EXISTS (SELECT 1 FROM `instance_template` WHERE `map` = 2859);
|
||||
|
||||
-- ===========================================================================
|
||||
-- Nexus-Point Xenas (map 2915)
|
||||
-- ===========================================================================
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_kasreth' WHERE `entry` = 241539;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_nysarra' WHERE `entry` = 241542;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_lothraxion' WHERE `entry` = 241546;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_lingering_image' WHERE `entry` = 241642;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_fractured_image' WHERE `entry` = 251568;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_corespark_pylon' WHERE `entry` = 254485;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_coresparks' WHERE `entry` = 252938;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_circuit_seer' WHERE `entry` = 248373;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_umbra_weaver' WHERE `entry` = 248708;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_manacite_worker' WHERE `entry` = 249096;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_flux_engineer' WHERE `entry` = 241647;
|
||||
|
||||
UPDATE `instance_template` SET `script` = 'instance_nexuspointxenas' WHERE `map` = 2915;
|
||||
INSERT INTO `instance_template` (`map`, `parent`, `script`, `insideResurrection`)
|
||||
SELECT 2915, 0, 'instance_nexuspointxenas', 0 FROM DUAL
|
||||
WHERE NOT EXISTS (SELECT 1 FROM `instance_template` WHERE `map` = 2915);
|
||||
|
||||
-- ===========================================================================
|
||||
-- Voidscar Arena (map 2923)
|
||||
-- ===========================================================================
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_atroxus' WHERE `entry` = 239008;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_aegyra_the_unyielding' WHERE `entry` = 267545;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_champions_spear' WHERE `entry` = 267550;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_brutok' WHERE `entry` = 244309;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_brutal_overseer' WHERE `entry` = 252053;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_devouring_brutalizer' WHERE `entry` = 268184;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_watchful_harrower' WHERE `entry` = 245950;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_tazrah' WHERE `entry` = 238887;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'boss_charonus' WHERE `entry` = 239167;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_targeting_stalker' WHERE `entry` = 255000;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_gravitic_orb' WHERE `entry` = 255001;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_voidscar_ethereal_shade' WHERE `entry` = 254677;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_voidscar_voidminder' WHERE `entry` = 244708;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_voidscar_longtooth_tuskarr' WHERE `entry` = 243985;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_voidscar_sycophantic_tarasek' WHERE `entry` = 243983;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_voidscar_dominated_brawler' WHERE `entry` = 238883;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_voidscar_protective_turtle' WHERE `entry` = 249603;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_voidscar_kilivore_screamer' WHERE `entry` = 243766;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_voidscar_chitigoth' WHERE `entry` = 244260;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_voidscar_toxic_creeper' WHERE `entry` = 239070;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_voidscar_abducted_drakonid' WHERE `entry` = 249461;
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_voidscar_raging_raptor' WHERE `entry` = 249608;
|
||||
|
||||
UPDATE `instance_template` SET `script` = 'instance_voidscar_arena' WHERE `map` = 2923;
|
||||
INSERT INTO `instance_template` (`map`, `parent`, `script`, `insideResurrection`)
|
||||
SELECT 2923, 0, 'instance_voidscar_arena', 0 FROM DUAL
|
||||
WHERE NOT EXISTS (SELECT 1 FROM `instance_template` WHERE `map` = 2923);
|
||||
|
||||
-- ===========================================================================
|
||||
-- Max-level: Foothold (Wowhead 90777). Follows The Last Push (95276).
|
||||
-- ===========================================================================
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(90777), (88696), (88697), (88698), (88699), (91417), (88700), (88701),
|
||||
(88702), (91426), (88703), (88704), (88705), (88706), (94957)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `NextQuestID` = 90777 WHERE `ID` = 95276;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 95276, `NextQuestID` = 88696, `ExclusiveGroup` = 0 WHERE `ID` = 90777;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 90777, `NextQuestID` = 88697, `ExclusiveGroup` = 0 WHERE `ID` = 88696;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 88696, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 88697;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 88697, `NextQuestID` = 91417, `ExclusiveGroup` = -88698 WHERE `ID` IN (88698, 88699);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 88700, `ExclusiveGroup` = 0 WHERE `ID` = 91417;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 91417, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 88700;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 88700, `NextQuestID` = 91426, `ExclusiveGroup` = -88701 WHERE `ID` IN (88701, 88702);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 88703, `ExclusiveGroup` = 0 WHERE `ID` = 91426;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 91426, `NextQuestID` = 88704, `ExclusiveGroup` = 0 WHERE `ID` = 88703;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 88703, `NextQuestID` = 88705, `ExclusiveGroup` = 0 WHERE `ID` = 88704;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 88704, `NextQuestID` = 88706, `ExclusiveGroup` = 0 WHERE `ID` = 88705;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 88705, `NextQuestID` = 94957, `ExclusiveGroup` = 0 WHERE `ID` = 88706;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 88706, `NextQuestID` = 90690, `ExclusiveGroup` = 0 WHERE `ID` = 94957;
|
||||
|
||||
-- ===========================================================================
|
||||
-- Max-level: The Voidspire (Wowhead 90690)
|
||||
-- ===========================================================================
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(90690), (88709), (90724), (92520)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 94957, `NextQuestID` = 88709, `ExclusiveGroup` = 0 WHERE `ID` = 90690;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 90690, `NextQuestID` = 90724, `ExclusiveGroup` = 0 WHERE `ID` = 88709;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 88709, `NextQuestID` = 92520, `ExclusiveGroup` = 0 WHERE `ID` = 90724;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 90724, `NextQuestID` = 88920, `ExclusiveGroup` = 0 WHERE `ID` = 92520;
|
||||
|
||||
-- Gathering of the Elves (88920-88941) is already chained in 2026_09_22_14.
|
||||
-- After Voidspire it is the next max-level chapter.
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92520 WHERE `ID` = 88920;
|
||||
UPDATE `quest_template_addon` SET `NextQuestID` = 90746 WHERE `ID` = 88941;
|
||||
|
||||
-- ===========================================================================
|
||||
-- Max-level: The Battle of the Bridge / The Darkwell / Dawn of a New Well
|
||||
-- ===========================================================================
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(90746), (88769), (90748), (88710), (92689), (90876), (90871), (90861),
|
||||
(90862), (90867)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 88941, `NextQuestID` = 88769, `ExclusiveGroup` = 0 WHERE `ID` = 90746;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 90746, `NextQuestID` = 90748, `ExclusiveGroup` = 0 WHERE `ID` = 88769;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 88769, `NextQuestID` = 88710, `ExclusiveGroup` = 0 WHERE `ID` = 90748;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 90748, `NextQuestID` = 92689, `ExclusiveGroup` = 0 WHERE `ID` = 88710;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 88710, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 92689;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92689, `NextQuestID` = 90861, `ExclusiveGroup` = -90876 WHERE `ID` IN (90876, 90871);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 90862, `ExclusiveGroup` = 0 WHERE `ID` = 90861;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 90861, `NextQuestID` = 90867, `ExclusiveGroup` = 0 WHERE `ID` = 90862;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 90862, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 90867;
|
||||
|
||||
-- ===========================================================================
|
||||
-- Curse of Ula'tek: An Island of Fangs (Wowhead 98218). Follows Dead End 93012.
|
||||
-- ===========================================================================
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(98218), (92916), (92917), (92919), (93265), (92921), (93263), (93266),
|
||||
(92920), (92924), (95804), (93019), (95564), (93018), (93022), (93023),
|
||||
(93024)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `NextQuestID` = 98218 WHERE `ID` = 93012;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 93012, `NextQuestID` = 92916, `ExclusiveGroup` = 0 WHERE `ID` = 98218;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 98218, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 92916;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92916, `NextQuestID` = 93265, `ExclusiveGroup` = -92917 WHERE `ID` IN (92917, 92919);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 92921, `ExclusiveGroup` = 0 WHERE `ID` = 93265;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 93265, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 92921;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92921, `NextQuestID` = 92920, `ExclusiveGroup` = -93263 WHERE `ID` IN (93263, 93266);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 92924, `ExclusiveGroup` = 0 WHERE `ID` = 92920;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92920, `NextQuestID` = 95804, `ExclusiveGroup` = 0 WHERE `ID` = 92924;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92924, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 95804;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 95804, `NextQuestID` = 0, `ExclusiveGroup` = -93019 WHERE `ID` IN (93019, 95564);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 93019, `NextQuestID` = 93023, `ExclusiveGroup` = -93018 WHERE `ID` IN (93018, 93022);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 93024, `ExclusiveGroup` = 0 WHERE `ID` = 93023;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 93023, `NextQuestID` = 93454, `ExclusiveGroup` = 0 WHERE `ID` = 93024;
|
||||
|
||||
-- ===========================================================================
|
||||
-- Curse of Ula'tek: Ghosts of the Past (Wowhead 93454)
|
||||
-- ===========================================================================
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(93454), (92925), (92927), (92928), (92929), (92930)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 93024, `NextQuestID` = 92925, `ExclusiveGroup` = 0 WHERE `ID` = 93454;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 93454, `NextQuestID` = 92927, `ExclusiveGroup` = 0 WHERE `ID` = 92925;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92925, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 92927;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92927, `NextQuestID` = 92930, `ExclusiveGroup` = -92928 WHERE `ID` IN (92928, 92929);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 92931, `ExclusiveGroup` = 0 WHERE `ID` = 92930;
|
||||
|
||||
-- ===========================================================================
|
||||
-- Curse of Ula'tek: Original Sin (Wowhead 92931)
|
||||
-- ===========================================================================
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(92931), (92932), (92933), (92938), (93063), (93064), (92934), (92935),
|
||||
(92936), (92937)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92930, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 92931;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92931, `NextQuestID` = 0, `ExclusiveGroup` = -92932 WHERE `ID` IN (92932, 92933);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92932, `NextQuestID` = 93064, `ExclusiveGroup` = -92938 WHERE `ID` IN (92938, 93063);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 93064;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 93064, `NextQuestID` = 92936, `ExclusiveGroup` = -92934 WHERE `ID` IN (92934, 92935);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 92937, `ExclusiveGroup` = 0 WHERE `ID` = 92936;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92936, `NextQuestID` = 93417, `ExclusiveGroup` = 0 WHERE `ID` = 92937;
|
||||
|
||||
-- ===========================================================================
|
||||
-- Curse of Ula'tek: The Battle for Atal'Utek (Wowhead 93417)
|
||||
-- Extra Vaults helper steps on some wiki lists are not on the Wowhead series.
|
||||
-- ===========================================================================
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(93417), (93419), (93418), (93420)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 92937, `NextQuestID` = 93419, `ExclusiveGroup` = 0 WHERE `ID` = 93417;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 93417, `NextQuestID` = 93418, `ExclusiveGroup` = 0 WHERE `ID` = 93419;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 93419, `NextQuestID` = 93420, `ExclusiveGroup` = 0 WHERE `ID` = 93418;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 93418, `NextQuestID` = 95973, `ExclusiveGroup` = 0 WHERE `ID` = 93420;
|
||||
|
||||
-- ===========================================================================
|
||||
-- Curse of Ula'tek: The Call of the Void (Wowhead 95973)
|
||||
-- ===========================================================================
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES
|
||||
(95973), (94519), (94520), (94521), (94522), (94523), (94524), (94525),
|
||||
(94526), (94527), (94528), (94529), (94530), (94531)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 93420, `NextQuestID` = 94519, `ExclusiveGroup` = 0 WHERE `ID` = 95973;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 95973, `NextQuestID` = 94520, `ExclusiveGroup` = 0 WHERE `ID` = 94519;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 94519, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 94520;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 94520, `NextQuestID` = 0, `ExclusiveGroup` = -94521 WHERE `ID` IN (94521, 94522, 94523);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 94521, `NextQuestID` = 94526, `ExclusiveGroup` = -94524 WHERE `ID` IN (94524, 94525);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 94527, `ExclusiveGroup` = 0 WHERE `ID` = 94526;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 94526, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 94527;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 94527, `NextQuestID` = 94530, `ExclusiveGroup` = -94528 WHERE `ID` IN (94528, 94529);
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0, `NextQuestID` = 94531, `ExclusiveGroup` = 0 WHERE `ID` = 94530;
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 94530, `NextQuestID` = 0, `ExclusiveGroup` = 0 WHERE `ID` = 94531;
|
||||
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3, `ScriptName` = 'npc_image_of_lady_liadrin_midnight' WHERE `entry` = 241677;
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3, `ScriptName` = 'npc_liadrin_lights_last_stand' WHERE `entry` = 241575;
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3, `ScriptName` = 'npc_arator_wayward_magister' WHERE `entry` = 236716;
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3, `ScriptName` = 'npc_umbric_tranquillien' WHERE `entry` = 236087;
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3, `ScriptName` = 'npc_lord_antenorian_tranquillien' WHERE `entry` = 245004;
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3, `ScriptName` = 'npc_lorthemar_sanctum_of_light' WHERE `entry` IN (235787, 245704);
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3, `ScriptName` = 'npc_contact_silvermoon_midnight' WHERE `entry` IN (241050, 239685);
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3, `ScriptName` = 'npc_liadrin_gates_of_zulaman' WHERE `entry` = 236436;
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3, `ScriptName` = 'npc_zuljarra_midnight' WHERE `entry` IN (236126, 240186, 240934);
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3, `ScriptName` = 'npc_zuljan_midnight' WHERE `entry` = 249211;
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3, `ScriptName` = 'npc_orweyna_fairbreeze_midnight' WHERE `entry` = 236704;
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3, `ScriptName` = 'npc_follow_orweyna_harandar' WHERE `entry` = 237209;
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3, `ScriptName` = 'npc_kupaal_harandar' WHERE `entry` = 237866;
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3, `ScriptName` = 'npc_halduron_harandar_council' WHERE `entry` = 237345;
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3, `ScriptName` = 'npc_umbric_voidstorm' WHERE `entry` IN (235386, 235405);
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3, `ScriptName` = 'npc_lothraxion_voidstorm' WHERE `entry` IN (235606, 260236);
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3, `ScriptName` = 'npc_liadrin_feeding_the_flame' WHERE `entry` = 247414;
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3, `ScriptName` = 'npc_umbric_clarity_of_purpose' WHERE `entry` = 242722;
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3, `ScriptName` = 'npc_alonsus_faol_arator' WHERE `entry` IN (237565, 240747);
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3, `ScriptName` = 'npc_arator_journey' WHERE `entry` IN (244644, 240267, 239827, 254884);
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 3, `ScriptName` = 'npc_shandris_children_of_the_stars' WHERE `entry` = 240334;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Generic talk-to / stay-awhile / speak-with (Wowhead objective NPCs)
|
||||
-- ---------------------------------------------------------------------------
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 1, `ScriptName` = 'npc_midnight_objective_talk' WHERE `entry` IN
|
||||
(237211, 236657, 236789, 236959, 236964, 243091, 237343, 237865, 237210,
|
||||
247408, 247410, 247411, 239405, 236149, 239457, 239406, 242568, 244840,
|
||||
240582, 240777, 239630, 239673, 239639, 239664, 242435, 240936, 240940,
|
||||
236583, 252821, 243882, 243958, 252348, 237857, 237837, 253343, 239623,
|
||||
242608, 242606, 244867, 242614, 242613, 242607, 242609, 242615, 242611,
|
||||
246863, 238157, 260106, 243760, 245886, 245697, 252294, 253508, 240335,
|
||||
253613, 250853, 248629, 237483, 240539, 240928, 236903, 242748);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Generic arrive / meet / reach / portal credits (Wowhead objective NPCs)
|
||||
-- ---------------------------------------------------------------------------
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_midnight_objective_proximity' WHERE `entry` IN
|
||||
(239653, 242375, 240573, 258837, 240587, 239527, 238613, 240048, 240448,
|
||||
244433, 241042, 253687, 247020, 243995, 241610, 239973, 244261, 251871,
|
||||
252596, 246476, 252309, 252347, 236140, 245606, 235395, 241126, 239600,
|
||||
246899, 244383, 240555);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Questgivers (Wowhead named NPCs on the chapter-start quests)
|
||||
-- ---------------------------------------------------------------------------
|
||||
DELETE FROM `creature_queststarter` WHERE
|
||||
(`id` = 241677 AND `quest` IN (91281, 88719))
|
||||
OR (`id` = 236704 AND `quest` IN (86899, 89402))
|
||||
OR (`id` = 237565 AND `quest` IN (89193, 86837))
|
||||
OR (`id` = 244644 AND `quest` = 86837)
|
||||
OR (`id` = 235386 AND `quest` = 89388)
|
||||
OR (`id` = 235405 AND `quest` = 86543)
|
||||
OR (`id` = 236716 AND `quest` = 86621)
|
||||
OR (`id` = 247414 AND `quest` = 90777)
|
||||
OR (`id` = 236436 AND `quest` = 86708)
|
||||
OR (`id` = 236126 AND `quest` = 86653)
|
||||
OR (`id` = 240267 AND `quest` = 88920)
|
||||
OR (`id` = 240747 AND `quest` = 86822)
|
||||
OR (`id` = 235787 AND `quest` IN (86733, 86734));
|
||||
|
||||
INSERT INTO `creature_queststarter` (`id`, `quest`, `VerifiedBuild`) VALUES
|
||||
(241677, 91281, 69875), -- Midnight offered by Image of Lady Liadrin
|
||||
(241677, 88719, 69875), -- A Voice from the Light
|
||||
(236704, 86899, 69875), -- The Root Cause offered by Orweyna
|
||||
(236704, 89402, 69875), -- Harandar breadcrumb
|
||||
(237565, 89193, 69875), -- Arator offered by Alonsus Faol
|
||||
(237565, 86837, 69875), -- Meet at the Sunwell
|
||||
(244644, 86837, 69875), -- Meet at the Sunwell (Arator)
|
||||
(235386, 89388, 69875), -- Voidstorm offered by Umbric
|
||||
(235405, 86543, 69875), -- Magisters' Terrace: Homecoming
|
||||
(236716, 86621, 69875), -- The Wayward Magister offered by Arator
|
||||
(247414, 90777, 69875), -- Feeding the Flame offered by Liadrin
|
||||
(236436, 86708, 69875), -- The Gates of Zul'Aman offered by Liadrin
|
||||
(236126, 86653, 69875), -- The Path of the Amani offered by Zul'jarra
|
||||
(240267, 88920, 69875), -- The Kaldorei offered by Arator
|
||||
(240747, 86822, 69875), -- One Final Relic offered by Alonsus Faol
|
||||
(235787, 86733, 69875), -- Silvermoon Negotiations offered by Lor'themar
|
||||
(235787, 86734, 69875); -- Diplomacy
|
||||
|
||||
DELETE FROM `creature_questender` WHERE
|
||||
(`id` = 241677 AND `quest` = 91281)
|
||||
OR (`id` = 236704 AND `quest` IN (89402, 86899))
|
||||
OR (`id` = 237565 AND `quest` = 89193)
|
||||
OR (`id` = 244644 AND `quest` = 86837)
|
||||
OR (`id` = 235386 AND `quest` = 89388)
|
||||
OR (`id` = 235405 AND `quest` = 86543)
|
||||
OR (`id` = 236087 AND `quest` = 86621)
|
||||
OR (`id` = 247414 AND `quest` = 90777)
|
||||
OR (`id` = 236436 AND `quest` = 86708)
|
||||
OR (`id` = 236126 AND `quest` = 86653)
|
||||
OR (`id` = 240267 AND `quest` = 88920)
|
||||
OR (`id` = 240747 AND `quest` = 86822)
|
||||
OR (`id` = 235787 AND `quest` IN (86733, 86734, 86650));
|
||||
|
||||
INSERT INTO `creature_questender` (`id`, `quest`, `VerifiedBuild`) VALUES
|
||||
(241677, 91281, 69875),
|
||||
(236704, 89402, 69875),
|
||||
(236704, 86899, 69875),
|
||||
(237565, 89193, 69875),
|
||||
(244644, 86837, 69875),
|
||||
(235386, 89388, 69875),
|
||||
(235405, 86543, 69875),
|
||||
(236087, 86621, 69875),
|
||||
(247414, 90777, 69875),
|
||||
(236436, 86708, 69875),
|
||||
(236126, 86653, 69875),
|
||||
(240267, 88920, 69875),
|
||||
(240747, 86822, 69875),
|
||||
(235787, 86733, 69875),
|
||||
(235787, 86734, 69875),
|
||||
(235787, 86650, 69875);
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
UPDATE `creature_template` SET `npcflag` = `npcflag` | 2 WHERE `entry` IN (156280, 166573, 160664, 166583);
|
||||
|
||||
DELETE FROM `creature_queststarter` WHERE (`id` = 156280 AND `quest` IN (56775, 58208))
|
||||
OR (`id` = 160664 AND `quest` = 58209)
|
||||
OR (`id` = 166573 AND `quest` IN (59926, 59928))
|
||||
OR (`id` = 166583 AND `quest` = 59927);
|
||||
INSERT INTO `creature_queststarter` (`id`, `quest`, `VerifiedBuild`) VALUES
|
||||
(156280, 56775, 69875),
|
||||
(156280, 58208, 69875),
|
||||
(160664, 58209, 69875),
|
||||
(166573, 59926, 69875),
|
||||
(166573, 59928, 69875),
|
||||
(166583, 59927, 69875);
|
||||
|
||||
DELETE FROM `creature_questender` WHERE (`id` = 156280 AND `quest` IN (56775, 58208))
|
||||
OR (`id` = 160664 AND `quest` = 58209)
|
||||
OR (`id` = 166573 AND `quest` IN (59926, 59928))
|
||||
OR (`id` = 166583 AND `quest` = 59927);
|
||||
INSERT INTO `creature_questender` (`id`, `quest`, `VerifiedBuild`) VALUES
|
||||
(156280, 56775, 69875),
|
||||
(156280, 58208, 69875),
|
||||
(160664, 58209, 69875),
|
||||
(166573, 59926, 69875),
|
||||
(166573, 59928, 69875),
|
||||
(166583, 59927, 69875);
|
||||
|
||||
INSERT INTO `quest_template_addon` (`ID`) VALUES (56775), (59926)
|
||||
ON DUPLICATE KEY UPDATE `ID` = `ID`;
|
||||
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID` = 0 WHERE `ID` IN (56775, 59926);
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "Random.h"
|
||||
#include "Errors.h"
|
||||
#include "SFMTRand.h"
|
||||
#include <boost/math/tools/roots.hpp>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
|
||||
@@ -89,3 +90,55 @@ uint32 urandweighted(size_t count, double const* chances)
|
||||
std::discrete_distribution<uint32> dd(chances, chances + count);
|
||||
return dd(engine);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct PseudoRandomDistributionChanceTable : std::array<float, 10000>
|
||||
{
|
||||
PseudoRandomDistributionChanceTable()
|
||||
{
|
||||
(*this)[0] = 0.0f;
|
||||
for (std::size_t i = 1; i < size(); ++i)
|
||||
(*this)[i] = NormalizePseudoRandomDistributionChance(i * 0.0001f);
|
||||
}
|
||||
|
||||
static float NormalizePseudoRandomDistributionChance(float chance)
|
||||
{
|
||||
std::uintptr_t iterationLimit = 10;
|
||||
return boost::math::tools::newton_raphson_iterate([target = 1.0f / chance](float p) -> std::pair<float, float>
|
||||
{
|
||||
// (value, derivative) pairs
|
||||
std::pair<float, float> chain = { 1.0f, 0.0f };
|
||||
std::pair<float, float> result = { 1.0f - target, 0.0f };
|
||||
|
||||
uint32 cap = uint32(std::ceil(1.0f / p));
|
||||
for (uint32 i = 1; i < cap; ++i)
|
||||
{
|
||||
float chanceToFail = 1 - p * i;
|
||||
chain.second = chain.second * chanceToFail - chain.first * i;
|
||||
chain.first = chain.first * chanceToFail;
|
||||
|
||||
result.first += chain.first;
|
||||
result.second += chain.second;
|
||||
}
|
||||
|
||||
return result;
|
||||
}, chance * chance, 0.0f, chance, 6, iterationLimit);
|
||||
}
|
||||
} const ChanceCache;
|
||||
}
|
||||
|
||||
bool roll_chance(float chance, PseudoRandomDistributionState& state)
|
||||
{
|
||||
std::ptrdiff_t chanceIndex = std::ptrdiff_t(std::round(chance * 100.0f));
|
||||
if (chanceIndex < 0)
|
||||
return false;
|
||||
|
||||
if (chanceIndex >= std::ssize(ChanceCache) || state.AccumulateChance(ChanceCache[chanceIndex]) > rand_norm())
|
||||
{
|
||||
state.Reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -84,4 +84,16 @@ public:
|
||||
result_type operator()() const { return rand32(); }
|
||||
};
|
||||
|
||||
#endif // Random_h__
|
||||
struct PseudoRandomDistributionState
|
||||
{
|
||||
float AccumulateChance(float progress) { return _progress += progress; }
|
||||
void Reset() { _progress = 0; }
|
||||
|
||||
private:
|
||||
float _progress = 0.0f;
|
||||
};
|
||||
|
||||
/* Return true if a random roll fits in the specified chance (range 0-100) using pseudo random distribution that minimizes long good/bad luck streaks. */
|
||||
TC_COMMON_API bool roll_chance(float chance, PseudoRandomDistributionState& state);
|
||||
|
||||
#endif // TRINITYCORE_RANDOM_H
|
||||
|
||||
+504
-138
@@ -17,17 +17,146 @@
|
||||
|
||||
#include "Crafting.h"
|
||||
#include "Containers.h"
|
||||
#include "Log.h"
|
||||
#include "DB2Stores.h"
|
||||
#include "DB2Structure.h"
|
||||
#include "Item.h"
|
||||
#include "ItemBonusMgr.h"
|
||||
#include "ItemEnchantmentMgr.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Player.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "Spell.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "CraftingPacketsCommon.h"
|
||||
#include "Random.h"
|
||||
#include "SpellPackets.h"
|
||||
#include "Player.h"
|
||||
#include "UpdateFields.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace
|
||||
{
|
||||
struct PendingBonusTree
|
||||
{
|
||||
uint32 TreeId = 0;
|
||||
ItemContext Context = ItemContext::Trade_Skill;
|
||||
bool ChoosesStats = false;
|
||||
};
|
||||
|
||||
int32 ReagentItemId(WorldPackets::Spells::SpellCraftingReagent const& reagent)
|
||||
{
|
||||
if (reagent.Reagent.ItemID && *reagent.Reagent.ItemID > 0)
|
||||
return *reagent.Reagent.ItemID;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 ReagentCurrencyId(WorldPackets::Spells::SpellCraftingReagent const& reagent)
|
||||
{
|
||||
if (reagent.Reagent.CurrencyID && *reagent.Reagent.CurrencyID > 0)
|
||||
return *reagent.Reagent.CurrencyID;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ItemContext ContextForReagent(ModifiedCraftingReagentItemEntry const* reagentItem)
|
||||
{
|
||||
if (!reagentItem || reagentItem->ItemContextOffset <= 0)
|
||||
return ItemContext::Trade_Skill;
|
||||
|
||||
uint32 shifted = uint32(ItemContext::Trade_Skill) + uint32(reagentItem->ItemContextOffset);
|
||||
if (shifted > 255)
|
||||
return ItemContext::Trade_Skill;
|
||||
|
||||
return ItemContext(shifted);
|
||||
}
|
||||
|
||||
bool MatchItemReagent(uint32 itemId, std::vector<ModifiedCraftingCategoryEntry const*> const& categories, ModifiedCraftingReagentItemEntry const*& reagentItem, ModifiedCraftingCategoryEntry const*& category)
|
||||
{
|
||||
for (ModifiedCraftingCategoryEntry const* candidate : categories)
|
||||
{
|
||||
for (ModifiedCraftingReagentItemEntry const* candidateItem : sDB2Manager.GetMCRReagentItemByCategory(candidate->ID))
|
||||
{
|
||||
for (ItemSparseEntry const* sparse : sDB2Manager.GetItemSparseByMCRReagentItem(candidateItem->ID))
|
||||
{
|
||||
if (sparse->ID != itemId)
|
||||
continue;
|
||||
|
||||
reagentItem = candidateItem;
|
||||
category = candidate;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MatchCurrencyReagent(uint32 currencyId, std::vector<ModifiedCraftingCategoryEntry const*> const& categories, ModifiedCraftingCategoryEntry const*& category, CraftingReagentQualityEntry const*& quality)
|
||||
{
|
||||
for (ModifiedCraftingCategoryEntry const* candidate : categories)
|
||||
{
|
||||
for (CraftingReagentQualityEntry const* candidateQuality : sCraftingReagentQualityStore)
|
||||
{
|
||||
if (candidateQuality->CurrencyTypesID != int32(currencyId))
|
||||
continue;
|
||||
|
||||
if (candidateQuality->ModifiedCraftingCategoryID != int32(candidate->ID))
|
||||
continue;
|
||||
|
||||
category = candidate;
|
||||
quality = candidateQuality;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
struct CraftingQualityMatch
|
||||
{
|
||||
int32 CraftingQualityID = 0;
|
||||
uint32 Tier = 0;
|
||||
float NextPercentage = 0.0f;
|
||||
};
|
||||
|
||||
CraftingQualityMatch MatchCraftingQuality(int32 craftingDifficultyID, float skillPercent)
|
||||
{
|
||||
CraftingQualityMatch match;
|
||||
float bestPercentage = -1.0f;
|
||||
bool foundNext = false;
|
||||
|
||||
for (CraftingDifficultyQualityEntry const* row : sCraftingDifficultyQualityStore)
|
||||
{
|
||||
if (row->CraftingDifficultyID != craftingDifficultyID)
|
||||
continue;
|
||||
|
||||
if (row->QualityPercentage <= skillPercent && row->QualityPercentage >= bestPercentage)
|
||||
{
|
||||
bestPercentage = row->QualityPercentage;
|
||||
match.CraftingQualityID = row->CraftingQualityID;
|
||||
if (CraftingQualityEntry const* quality = sCraftingQualityStore.LookupEntry(row->CraftingQualityID))
|
||||
match.Tier = uint32(std::max(0, quality->QualityTier));
|
||||
else
|
||||
match.Tier = 0;
|
||||
}
|
||||
|
||||
if (row->QualityPercentage > skillPercent && (!foundNext || row->QualityPercentage < match.NextPercentage))
|
||||
{
|
||||
match.NextPercentage = row->QualityPercentage;
|
||||
foundNext = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundNext)
|
||||
match.NextPercentage = 0.0f;
|
||||
|
||||
return match;
|
||||
}
|
||||
}
|
||||
|
||||
SpellCastResult Crafting::DoCraft(uint32 craftingDataId)
|
||||
{
|
||||
@@ -37,193 +166,437 @@ SpellCastResult Crafting::DoCraft(uint32 craftingDataId)
|
||||
if (!_craftingData || spellSlots.empty())
|
||||
return SpellCastResult::SPELL_FAILED_ERROR;
|
||||
|
||||
std::unordered_map<uint32 /*itemId*/, uint32 /*quantity*/> usedReagentsToDestroy;
|
||||
std::vector<uint32> bonusTreeIds;
|
||||
std::unordered_map<uint32, uint32> usedItems;
|
||||
std::unordered_map<uint32, uint32> usedCurrencies;
|
||||
std::vector<PendingBonusTree> bonusTrees;
|
||||
bool statsChosenByReagent = false;
|
||||
float difficulty = float(_craftingData->CraftingDifficulty);
|
||||
float totalWeight = 0.0f;
|
||||
float weightedEffect = 0.0f;
|
||||
|
||||
if (_craftingData->ItemBonusTreeID)
|
||||
bonusTreeIds.push_back(_craftingData->ItemBonusTreeID);
|
||||
if (_craftingData->ItemBonusTreeID > 0)
|
||||
bonusTrees.push_back({ uint32(_craftingData->ItemBonusTreeID), ItemContext::Trade_Skill, false });
|
||||
|
||||
uint32 craftingDifficulty = _craftingData->CraftingDifficulty;
|
||||
|
||||
// List all reagent "slots" for this craft, with ReagentSlotID & ReagentCount
|
||||
for (ModifiedCraftingSpellSlotEntry const* spellSlot : spellSlots)
|
||||
{
|
||||
// If no ReagentCount used by spell why even bother ?
|
||||
if (spellSlot->ReagentCount < 1)
|
||||
int32 requiredRaw = _recraft ? spellSlot->ReagentReCraftCount : spellSlot->ReagentCount;
|
||||
if (requiredRaw < 1)
|
||||
continue;
|
||||
|
||||
uint32 requiredCount = uint32(requiredRaw);
|
||||
ModifiedCraftingReagentSlotEntry const* reagentSlot = sModifiedCraftingReagentSlotStore.LookupEntry(spellSlot->ModifiedCraftingReagentSlotID);
|
||||
uint32 reagentCountForSlot = 0;
|
||||
if (!reagentSlot)
|
||||
continue;
|
||||
|
||||
auto providedReagentItr = _spell->m_targets.ModifiedCraftingReagents.find(spellSlot->Slot);
|
||||
if (providedReagentItr != _spell->m_targets.ModifiedCraftingReagents.end())
|
||||
auto providedReagentItr = _spell->m_targets.ModifiedCraftingReagents.find(uint32(spellSlot->Slot));
|
||||
if (providedReagentItr == _spell->m_targets.ModifiedCraftingReagents.end())
|
||||
{
|
||||
if (reagentSlot->ReagentType == MCR_REAGENT_TYPE_REQUIRED)
|
||||
return SpellCastResult::SPELL_FAILED_NEED_MORE_ITEMS;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32 providedCount = 0;
|
||||
std::unordered_map<uint32, uint32> slotItems;
|
||||
std::unordered_map<uint32, uint32> slotCurrencies;
|
||||
for (WorldPackets::Spells::SpellCraftingReagent const& provided : providedReagentItr->second)
|
||||
{
|
||||
if (provided.Quantity <= 0)
|
||||
return SpellCastResult::SPELL_FAILED_ERROR;
|
||||
|
||||
if (int32 itemId = ReagentItemId(provided))
|
||||
{
|
||||
slotItems[uint32(itemId)] += uint32(provided.Quantity);
|
||||
if (!_player->HasItemCount(uint32(itemId), usedItems[uint32(itemId)] + slotItems[uint32(itemId)]))
|
||||
return SpellCastResult::SPELL_FAILED_NEED_MORE_ITEMS;
|
||||
|
||||
providedCount += uint32(provided.Quantity);
|
||||
}
|
||||
else if (int32 currencyId = ReagentCurrencyId(provided))
|
||||
{
|
||||
slotCurrencies[uint32(currencyId)] += uint32(provided.Quantity);
|
||||
if (!_player->HasCurrency(uint32(currencyId), usedCurrencies[uint32(currencyId)] + slotCurrencies[uint32(currencyId)]))
|
||||
return SpellCastResult::SPELL_FAILED_NEED_MORE_ITEMS;
|
||||
|
||||
providedCount += uint32(provided.Quantity);
|
||||
}
|
||||
else
|
||||
return SpellCastResult::SPELL_FAILED_NEED_MORE_ITEMS;
|
||||
}
|
||||
|
||||
if (providedCount < requiredCount)
|
||||
{
|
||||
for (WorldPackets::Spells::SpellCraftingReagent const& providedReagentForSlot : providedReagentItr->second)
|
||||
{
|
||||
if (_player->HasItemCount(providedReagentForSlot.Slot, providedReagentForSlot.Quantity))
|
||||
{
|
||||
reagentCountForSlot += providedReagentForSlot.Quantity;
|
||||
usedReagentsToDestroy[providedReagentForSlot.Slot] = providedReagentForSlot.Quantity;
|
||||
|
||||
if (CraftingReagentQualityEntry const* reagentQuality = sDB2Manager.GetCraftingReagentQualityByItem(providedReagentForSlot.Slot))
|
||||
craftingDifficulty += reagentQuality->MaxDifficultyAdjustment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (reagentCountForSlot < uint32(spellSlot->ReagentCount))
|
||||
{
|
||||
// If we don't have enough Reagent for this slot and it is required, craft failed
|
||||
if (reagentSlot->ReagentType == MCR_REAGENT_TYPE_REQUIRED)
|
||||
return SpellCastResult::SPELL_FAILED_NEED_MORE_ITEMS;
|
||||
|
||||
// Still not enough but the reagent is optional, just skip
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<ModifiedCraftingCategoryEntry const*> categories = sDB2Manager.GetMCRCategoryByReagentSlot(spellSlot->ModifiedCraftingReagentSlotID);
|
||||
bool hasOneMatchingItem = false;
|
||||
bool slotWeightAdded = false;
|
||||
|
||||
for (ModifiedCraftingCategoryEntry const* category : categories)
|
||||
for (WorldPackets::Spells::SpellCraftingReagent const& provided : providedReagentItr->second)
|
||||
{
|
||||
std::vector<ModifiedCraftingReagentItemEntry const*> reagentItems = sDB2Manager.GetMCRReagentItemByCategory(category->ID);
|
||||
ModifiedCraftingReagentItemEntry const* reagentItem = nullptr;
|
||||
ModifiedCraftingCategoryEntry const* category = nullptr;
|
||||
CraftingReagentQualityEntry const* quality = nullptr;
|
||||
uint32 quantity = uint32(provided.Quantity);
|
||||
|
||||
for (ModifiedCraftingReagentItemEntry const* reagentItem : reagentItems)
|
||||
if (int32 itemId = ReagentItemId(provided))
|
||||
{
|
||||
std::set<ItemSparseEntry const*> requiredItems = sDB2Manager.GetItemSparseByMCRReagentItem(reagentItem->ID);
|
||||
if (!MatchItemReagent(uint32(itemId), categories, reagentItem, category))
|
||||
return SpellCastResult::SPELL_FAILED_NEED_MORE_ITEMS;
|
||||
|
||||
for (WorldPackets::Spells::SpellCraftingReagent const& providedReagent : providedReagentItr->second)
|
||||
quality = sDB2Manager.GetCraftingReagentQualityByItem(uint32(itemId));
|
||||
usedItems[uint32(itemId)] += quantity;
|
||||
}
|
||||
else if (int32 currencyId = ReagentCurrencyId(provided))
|
||||
{
|
||||
if (!MatchCurrencyReagent(uint32(currencyId), categories, category, quality))
|
||||
return SpellCastResult::SPELL_FAILED_NEED_MORE_ITEMS;
|
||||
|
||||
usedCurrencies[uint32(currencyId)] += quantity;
|
||||
}
|
||||
|
||||
if (quality)
|
||||
difficulty += quality->MaxDifficultyAdjustment * float(quantity) / float(requiredCount);
|
||||
|
||||
if (category)
|
||||
{
|
||||
if (!slotWeightAdded)
|
||||
{
|
||||
bool hasItem = std::count_if(std::cbegin(requiredItems), std::cend(requiredItems), [providedReagent](ItemSparseEntry const* itemSparse) {
|
||||
return itemSparse->ID == uint32(providedReagent.Slot);
|
||||
});
|
||||
|
||||
if (hasItem)
|
||||
bonusTreeIds.push_back(reagentItem->ItemBonusTreeID);
|
||||
|
||||
hasOneMatchingItem = hasOneMatchingItem || hasItem;
|
||||
totalWeight += category->MatQualityWeight * float(requiredCount);
|
||||
slotWeightAdded = true;
|
||||
}
|
||||
|
||||
float effect = quality ? quality->ReagentEffectPct / 100.0f : 0.0f;
|
||||
weightedEffect += category->MatQualityWeight * float(quantity) * effect;
|
||||
}
|
||||
|
||||
if (reagentItem)
|
||||
{
|
||||
if (reagentItem->ItemBonusTreeID > 0)
|
||||
bonusTrees.push_back({ uint32(reagentItem->ItemBonusTreeID), ContextForReagent(reagentItem), (reagentItem->Flags & 1) != 0 });
|
||||
|
||||
if (reagentItem->Flags & 1)
|
||||
statsChosenByReagent = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If any item provided do not match, probably a cheater, return
|
||||
if (!hasOneMatchingItem)
|
||||
return SpellCastResult::SPELL_FAILED_NEED_MORE_ITEMS;
|
||||
}
|
||||
|
||||
uint32 skillLevel = GetSkillLevelForCraft();
|
||||
uint32 difficultyPercentMatched = round(float(skillLevel) / float(craftingDifficulty) * 100.f);
|
||||
uint32 skillLevel = _player->GetSkillValue(GetSkillIdForSpell(_spell->GetSpellInfo()->Id));
|
||||
uint32 reagentSkill = 0;
|
||||
float baseDifficulty = float(_craftingData->CraftingDifficulty);
|
||||
CraftingDifficultyEntry const* craftingDifficultyEntry = sCraftingDifficultyStore.LookupEntry(_craftingData->CraftingDifficultyID);
|
||||
if (craftingDifficultyEntry)
|
||||
{
|
||||
float bonusPercent = _recraft ? craftingDifficultyEntry->ReCraftSkillBonusPercent : craftingDifficultyEntry->CraftSkillBonusPercent;
|
||||
if (totalWeight > 0.0f && bonusPercent > 0.0f)
|
||||
{
|
||||
float maximumReagentBonus = std::round(baseDifficulty * bonusPercent / 100.0f);
|
||||
reagentSkill = uint32(std::max(0L, std::lround(maximumReagentBonus * weightedEffect / totalWeight)));
|
||||
skillLevel += reagentSkill;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 qualityTier = sDB2Manager.GetCraftingQualityTierByDifficultyPercent(_craftingData->CraftingDifficultyID, difficultyPercentMatched);
|
||||
SkillLineAbilityEntry const* skillAbility = nullptr;
|
||||
SkillLineAbilityMapBounds abilityBounds = sSpellMgr->GetSkillLineAbilityMapBounds(_spell->GetSpellInfo()->Id);
|
||||
for (SkillLineAbilityMap::const_iterator ability = abilityBounds.first; ability != abilityBounds.second; ++ability)
|
||||
{
|
||||
if (!skillAbility)
|
||||
skillAbility = ability->second;
|
||||
if (ability->second->SkillupSkillLineID)
|
||||
{
|
||||
skillAbility = ability->second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ProfessionEffectTotals traitEffects;
|
||||
auto visitSkillLineChain = [](uint32 skillLineId, auto&& visitor)
|
||||
{
|
||||
for (uint32 step = 0; skillLineId && step < 8; ++step)
|
||||
{
|
||||
if (visitor(skillLineId))
|
||||
return true;
|
||||
|
||||
SkillLineEntry const* skillLine = sSkillLineStore.LookupEntry(skillLineId);
|
||||
uint32 parent = skillLine ? skillLine->ParentSkillLineID : 0;
|
||||
if (!parent || parent == skillLineId)
|
||||
break;
|
||||
|
||||
skillLineId = parent;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
if (skillAbility)
|
||||
{
|
||||
std::unordered_set<uint32> skillLines;
|
||||
auto addChain = [&](uint32 skillLineId)
|
||||
{
|
||||
visitSkillLineChain(skillLineId, [&](uint32 line)
|
||||
{
|
||||
return !skillLines.insert(line).second;
|
||||
});
|
||||
};
|
||||
addChain(skillAbility->SkillLine);
|
||||
addChain(skillAbility->SkillupSkillLineID);
|
||||
|
||||
auto applyTraitEntry = [&](UF::TraitEntry const& entry)
|
||||
{
|
||||
int32 rank = entry.Rank + entry.GrantedRanks + entry.BonusRanks;
|
||||
if (rank <= 0 || entry.TraitNodeEntryID <= 0)
|
||||
return;
|
||||
|
||||
TraitNodeEntryEntry const* nodeEntry = sTraitNodeEntryStore.LookupEntry(entry.TraitNodeEntryID);
|
||||
if (!nodeEntry || nodeEntry->TraitDefinitionID <= 0)
|
||||
return;
|
||||
|
||||
sDB2Manager.AccumulateProfessionTraitEffects(nodeEntry->TraitDefinitionID, rank, traitEffects);
|
||||
};
|
||||
|
||||
for (auto const& [_, traitConfig] : _player->m_activePlayerData->TraitConfigs)
|
||||
{
|
||||
if (TraitConfigType(*traitConfig.value.Type) != TraitConfigType::Profession)
|
||||
continue;
|
||||
|
||||
int32 configSkillLine = traitConfig.value.SkillLineID;
|
||||
if (configSkillLine <= 0 || !skillLines.contains(uint32(configSkillLine)))
|
||||
continue;
|
||||
|
||||
for (UF::TraitEntry const& entry : traitConfig.value.Entries)
|
||||
applyTraitEntry(entry);
|
||||
|
||||
for (UF::TraitSubTreeCache const& subTree : traitConfig.value.SubTrees)
|
||||
for (UF::TraitEntry const& entry : subTree.Entries)
|
||||
applyTraitEntry(entry);
|
||||
}
|
||||
}
|
||||
|
||||
if (traitEffects.Skill > 0.0f)
|
||||
skillLevel += uint32(std::lround(traitEffects.Skill));
|
||||
|
||||
difficulty += traitEffects.DifficultyDelta;
|
||||
if (difficulty < 1.0f)
|
||||
difficulty = 1.0f;
|
||||
|
||||
// Client profession UI scale shared by Dragonflight, The War Within and Midnight: 1100 rating is 100%.
|
||||
// This is not a spell id.
|
||||
constexpr float ProfessionRatingScale = 1100.0f;
|
||||
bool inspired = false;
|
||||
float critBonusSkill = 0.0f;
|
||||
if (traitEffects.InspirationRating > 0.0f && roll_chance(traitEffects.InspirationRating / ProfessionRatingScale * 100.0f))
|
||||
{
|
||||
inspired = true;
|
||||
float bonusPercent = _craftingData->InspirationSkillBonusPercent;
|
||||
if (bonusPercent <= 0.0f && craftingDifficultyEntry)
|
||||
bonusPercent = craftingDifficultyEntry->InspirationSkillBonusPercent;
|
||||
|
||||
critBonusSkill = difficulty * bonusPercent / 100.0f + traitEffects.InspirationBonusSkill;
|
||||
if (critBonusSkill > 0.0f)
|
||||
skillLevel += uint32(std::lround(critBonusSkill));
|
||||
}
|
||||
|
||||
auto skillPercent = [&]()
|
||||
{
|
||||
return float(skillLevel) / difficulty * 100.0f;
|
||||
};
|
||||
|
||||
uint32 concentrationCurrency = 0;
|
||||
if (skillAbility)
|
||||
{
|
||||
auto findCurrency = [&](uint32 skillLineId)
|
||||
{
|
||||
return visitSkillLineChain(skillLineId, [&](uint32 line)
|
||||
{
|
||||
concentrationCurrency = sDB2Manager.GetConcentrationCurrencyForSkillLine(line);
|
||||
return concentrationCurrency != 0;
|
||||
});
|
||||
};
|
||||
|
||||
if (!findCurrency(skillAbility->SkillLine))
|
||||
findCurrency(skillAbility->SkillupSkillLineID);
|
||||
}
|
||||
|
||||
int32 concentrationSpent = 0;
|
||||
bool concentrationApplied = false;
|
||||
CraftingQualityMatch quality = MatchCraftingQuality(_craftingData->CraftingDifficultyID, skillPercent());
|
||||
if (_spell->m_targets.ApplyConcentration && quality.NextPercentage > skillPercent())
|
||||
{
|
||||
bool haveCurves = craftingDifficultyEntry
|
||||
&& craftingDifficultyEntry->ConcentrationSkillCurveID > 0
|
||||
&& craftingDifficultyEntry->ConcentrationDifficultyCurveID > 0;
|
||||
float skillFactor = 0.0f;
|
||||
float difficultyFactor = 0.0f;
|
||||
if (haveCurves)
|
||||
{
|
||||
skillFactor = sDB2Manager.GetCurveValueAt(uint32(craftingDifficultyEntry->ConcentrationSkillCurveID), skillPercent());
|
||||
difficultyFactor = sDB2Manager.GetCurveValueAt(uint32(craftingDifficultyEntry->ConcentrationDifficultyCurveID), difficulty);
|
||||
}
|
||||
|
||||
float reduction = traitEffects.ConcentrationCostReductionPercent;
|
||||
if (reduction < 0.0f)
|
||||
reduction = 0.0f;
|
||||
else if (reduction > 100.0f)
|
||||
reduction = 100.0f;
|
||||
|
||||
int32 cost = 0;
|
||||
if (skillFactor > 0.0f && difficultyFactor > 0.0f)
|
||||
cost = int32(std::lround(skillFactor * difficultyFactor * (1.0f - reduction / 100.0f)));
|
||||
|
||||
if (!haveCurves || !concentrationCurrency || cost <= 0)
|
||||
{
|
||||
TC_LOG_DEBUG("spells", "Spell {} crafted without concentration because the profession currency or cost curve is missing.", _spell->GetSpellInfo()->Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 reserved = 0;
|
||||
if (auto reservedCurrency = usedCurrencies.find(concentrationCurrency); reservedCurrency != usedCurrencies.end())
|
||||
reserved = reservedCurrency->second;
|
||||
|
||||
if (!_player->HasCurrency(concentrationCurrency, reserved + uint32(cost)))
|
||||
return SpellCastResult::SPELL_FAILED_NOT_ENOUGH_CURRENCY;
|
||||
|
||||
skillLevel = std::max(skillLevel, uint32(std::ceil(difficulty * quality.NextPercentage / 100.0f)));
|
||||
concentrationSpent = cost;
|
||||
concentrationApplied = true;
|
||||
quality = MatchCraftingQuality(_craftingData->CraftingDifficultyID, skillPercent());
|
||||
}
|
||||
}
|
||||
|
||||
uint32 qualityTier = quality.Tier;
|
||||
uint32 craftedItemId = GetCraftedItemIdForQuality(qualityTier);
|
||||
|
||||
// If we didn't found anything, we have a problem. Return and don't take reagent from player.
|
||||
if (!craftedItemId)
|
||||
return SpellCastResult::SPELL_FAILED_ERROR;
|
||||
|
||||
ItemContext context = _spell->GetSpellInfo()->HasAttribute(SPELL_ATTR0_IS_TRADESKILL) ? ItemContext::Trade_Skill : ItemContext::NONE;
|
||||
ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(craftedItemId);
|
||||
std::vector<int32> bonusLists = ItemBonusMgr::GetBonusListsForItem(craftedItemId, context, _player);
|
||||
std::unordered_set<int32> seenBonuses(bonusLists.begin(), bonusLists.end());
|
||||
|
||||
std::vector<int32> bonusLists;
|
||||
|
||||
for (PendingBonusTree const& tree : bonusTrees)
|
||||
{
|
||||
std::vector<int32> contextBonusLists = ItemBonusMgr::GetBonusListsForItem(craftedItemId, context, _player);
|
||||
bonusLists.insert(std::end(bonusLists), std::begin(contextBonusLists), std::end(contextBonusLists));
|
||||
for (int32 bonusListId : ItemBonusMgr::GetBonusListsForTree(tree.TreeId, itemTemplate, { tree.Context }, _player))
|
||||
{
|
||||
if (seenBonuses.insert(bonusListId).second)
|
||||
bonusLists.push_back(bonusListId);
|
||||
}
|
||||
|
||||
if (tree.ChoosesStats)
|
||||
statsChosenByReagent = true;
|
||||
}
|
||||
|
||||
for (int32 bonusTreeID : bonusTreeIds)
|
||||
uint32 craftCount = 1;
|
||||
uint32 multicraftExtra = 0;
|
||||
if (itemTemplate && itemTemplate->GetMaxStackSize() > 1 && traitEffects.MulticraftRating > 0.0f
|
||||
&& roll_chance(traitEffects.MulticraftRating / ProfessionRatingScale * 100.0f))
|
||||
{
|
||||
std::vector<int32> treeBonusList = ItemBonusMgr::GetAllBonusListsForTree(bonusTreeID);
|
||||
bonusLists.insert(std::end(bonusLists), std::begin(treeBonusList), std::end(treeBonusList));
|
||||
float minExtra = 0.0f;
|
||||
float maxExtra = 0.0f;
|
||||
bool haveRange = false;
|
||||
if (skillAbility)
|
||||
{
|
||||
auto findRange = [&](uint32 skillLineId)
|
||||
{
|
||||
return visitSkillLineChain(skillLineId, [&](uint32 line)
|
||||
{
|
||||
haveRange = sDB2Manager.GetMulticraftExtraQuantityRange(line, minExtra, maxExtra);
|
||||
return haveRange;
|
||||
});
|
||||
};
|
||||
|
||||
if (!findRange(skillAbility->SkillLine))
|
||||
findRange(skillAbility->SkillupSkillLineID);
|
||||
}
|
||||
|
||||
if (haveRange)
|
||||
{
|
||||
maxExtra += traitEffects.MulticraftExtraPercent;
|
||||
if (maxExtra < minExtra)
|
||||
maxExtra = minExtra;
|
||||
|
||||
float rolled = frand(minExtra, maxExtra);
|
||||
multicraftExtra = std::max<uint32>(1, uint32(std::lround(float(craftCount) * rolled / 100.0f)));
|
||||
}
|
||||
else
|
||||
multicraftExtra = 1;
|
||||
}
|
||||
|
||||
uint32 totalCount = craftCount + multicraftExtra;
|
||||
ItemPosCountVec dest;
|
||||
uint32 no_space = 0;
|
||||
InventoryResult msg = _player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, craftedItemId, 1, &no_space);
|
||||
uint32 noSpace = 0;
|
||||
InventoryResult msg = _player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, craftedItemId, totalCount, &noSpace);
|
||||
if (msg != EQUIP_ERR_OK)
|
||||
{
|
||||
_player->SendEquipError(msg, nullptr, nullptr, craftedItemId);
|
||||
return SpellCastResult::SPELL_FAILED_DONT_REPORT;
|
||||
}
|
||||
|
||||
if (Item* createdItem = _player->StoreNewItem(dest, craftedItemId, true, GenerateItemRandomBonusListId(craftedItemId), GuidSet(), context, &bonusLists))
|
||||
{
|
||||
InitCraftingStatModifier(createdItem);
|
||||
Item* createdItem = _player->StoreNewItem(dest, craftedItemId, true, GenerateItemRandomBonusListId(craftedItemId), GuidSet(), context, &bonusLists);
|
||||
if (!createdItem)
|
||||
return SpellCastResult::SPELL_FAILED_ERROR;
|
||||
|
||||
if (createdItem->GetTemplate()->HasSignature())
|
||||
createdItem->SetCreator(_player->GetGUID());
|
||||
InitCraftingStatModifier(createdItem, statsChosenByReagent);
|
||||
|
||||
_player->SendNewItem(createdItem, 1, true, true);
|
||||
}
|
||||
if (createdItem->GetTemplate()->HasSignature())
|
||||
createdItem->SetCreator(_player->GetGUID());
|
||||
|
||||
// Item has been crafted, remove reagent from player
|
||||
for (auto const& [itemId, itemCount] : usedReagentsToDestroy)
|
||||
if (concentrationApplied)
|
||||
usedCurrencies[concentrationCurrency] += uint32(concentrationSpent);
|
||||
|
||||
for (auto const& [itemId, itemCount] : usedItems)
|
||||
_player->DestroyItemCount(itemId, itemCount, true);
|
||||
|
||||
for (auto const& [currencyId, currencyCount] : usedCurrencies)
|
||||
_player->ModifyCurrency(currencyId, -int32(currencyCount), CurrencyGainSource::Spell, CurrencyDestroyReason::Spell);
|
||||
|
||||
float progress = float(skillLevel) / difficulty;
|
||||
if (progress < 0.0f)
|
||||
progress = 0.0f;
|
||||
else if (progress > 1.0f)
|
||||
progress = 1.0f;
|
||||
|
||||
WorldPackets::Crafting::CraftingData craftingData;
|
||||
craftingData.CraftingQualityID = quality.CraftingQualityID;
|
||||
craftingData.QualityProgress = progress;
|
||||
craftingData.SkillLineAbilityID = skillAbility ? int32(skillAbility->ID) : 0;
|
||||
craftingData.CraftingDataID = int32(_craftingData->ID);
|
||||
craftingData.Multicraft = int32(multicraftExtra);
|
||||
craftingData.SkillFromReagents = int32(reagentSkill);
|
||||
craftingData.Skill = int32(skillLevel);
|
||||
craftingData.CritBonusSkill = inspired ? int32(std::lround(critBonusSkill)) : 0;
|
||||
craftingData.IsCrit = inspired;
|
||||
craftingData.IsRecraft = _recraft;
|
||||
craftingData.ItemGUID = createdItem->GetGUID();
|
||||
craftingData.Quantity = int32(totalCount);
|
||||
craftingData.NewItem.Initialize(createdItem);
|
||||
craftingData.ConcentrationCurrencyID = concentrationApplied ? int32(concentrationCurrency) : 0;
|
||||
craftingData.ConcentrationSpent = concentrationSpent;
|
||||
craftingData.ApplyConcentration = concentrationApplied;
|
||||
|
||||
_player->SendNewItem(createdItem, totalCount, true, true, false, 0, &craftingData);
|
||||
_player->UpdateCraftSkill(_spell->GetSpellInfo());
|
||||
return SpellCastResult::SPELL_CAST_OK;
|
||||
}
|
||||
|
||||
uint32 Crafting::GetSkillLevelForCraft()
|
||||
{
|
||||
uint32 skillId = GetSkillIdForSpell(_spell->GetSpellInfo()->Id);
|
||||
uint32 skillValue = _player->GetSkillValue(skillId);
|
||||
|
||||
uint32 totalReagentWeigth = CalculateTotalReagentWeights();
|
||||
|
||||
CraftingDifficultyEntry const* craftingDifficultyEntry = sCraftingDifficultyStore.LookupEntry(_craftingData->CraftingDifficultyID);
|
||||
if (!craftingDifficultyEntry)
|
||||
return skillValue;
|
||||
|
||||
float maximumReagentBonus = round(float(_craftingData->CraftingDifficulty) * float(craftingDifficultyEntry->CraftSkillBonusPercent) / 100.f);
|
||||
|
||||
for (ModifiedCraftingSpellSlotEntry const* spellSlot : sDB2Manager.GetMCRSpellSlotBySpell(_spell->GetSpellInfo()->Id))
|
||||
{
|
||||
for (ModifiedCraftingCategoryEntry const* category : sDB2Manager.GetMCRCategoryByReagentSlot(spellSlot->ModifiedCraftingReagentSlotID))
|
||||
{
|
||||
auto providedReagentItr = _spell->m_targets.ModifiedCraftingReagents.find(spellSlot->Slot);
|
||||
if (providedReagentItr != _spell->m_targets.ModifiedCraftingReagents.end())
|
||||
{
|
||||
for (WorldPackets::Spells::SpellCraftingReagent const& providedReagentForSlot : providedReagentItr->second)
|
||||
{
|
||||
if (CraftingReagentQualityEntry const* reagentQuality = sDB2Manager.GetCraftingReagentQualityByItem(providedReagentForSlot.Slot))
|
||||
{
|
||||
float reagentWeight = float(category->MatQualityWeight) * float(providedReagentForSlot.Quantity) / 2.0f * float(reagentQuality->OrderIndex);
|
||||
uint32 addedSkillByReagent = round(maximumReagentBonus * reagentWeight / float(totalReagentWeigth));
|
||||
skillValue += addedSkillByReagent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return skillValue;
|
||||
}
|
||||
|
||||
uint32 Crafting::GetSkillIdForSpell(uint32 spellId)
|
||||
uint32 Crafting::GetSkillIdForSpell(uint32 spellId) const
|
||||
{
|
||||
SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spellId);
|
||||
for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx)
|
||||
if (_spell_idx->second->SkillupSkillLineID)
|
||||
return _spell_idx->second->SkillupSkillLineID;
|
||||
for (SkillLineAbilityMap::const_iterator spellIndex = bounds.first; spellIndex != bounds.second; ++spellIndex)
|
||||
if (spellIndex->second->SkillupSkillLineID)
|
||||
return spellIndex->second->SkillupSkillLineID;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 Crafting::CalculateTotalReagentWeights()
|
||||
void Crafting::InitCraftingStatModifier(Item* item, bool statsChosenByReagent)
|
||||
{
|
||||
uint32 totalWeight = 0;
|
||||
if (statsChosenByReagent)
|
||||
return;
|
||||
|
||||
for (ModifiedCraftingSpellSlotEntry const* spellSlot : sDB2Manager.GetMCRSpellSlotBySpell(_spell->GetSpellInfo()->Id))
|
||||
for (ModifiedCraftingCategoryEntry const* category : sDB2Manager.GetMCRCategoryByReagentSlot(spellSlot->ModifiedCraftingReagentSlotID))
|
||||
totalWeight += category->MatQualityWeight * spellSlot->ReagentCount;
|
||||
|
||||
return totalWeight;
|
||||
}
|
||||
|
||||
// Todo : We currently only set random stats, but crafter
|
||||
// can define stats using a "Missive" item
|
||||
void Crafting::InitCraftingStatModifier(Item* item)
|
||||
{
|
||||
std::vector<uint32> allowedStats = {
|
||||
ITEM_MOD_MASTERY_RATING,
|
||||
ITEM_MOD_HASTE_RATING,
|
||||
@@ -242,20 +615,13 @@ void Crafting::InitCraftingStatModifier(Item* item)
|
||||
}
|
||||
}
|
||||
|
||||
uint32 Crafting::GetCraftedItemIdForQuality(uint32 qualityTier)
|
||||
uint32 Crafting::GetCraftedItemIdForQuality(uint32 qualityTier) const
|
||||
{
|
||||
// If this is a simple item (no quality), we have the id
|
||||
uint32 newItemId = _craftingData->CraftedItemID;
|
||||
uint32 craftedItemId = _craftingData->CraftedItemID > 0 ? uint32(_craftingData->CraftedItemID) : 0;
|
||||
std::vector<uint32> craftedItemList = sDB2Manager.GetCraftingDataItemIDByCraftingData(_craftingData->ID);
|
||||
if (craftedItemList.empty() || qualityTier == 0)
|
||||
return craftedItemId;
|
||||
|
||||
// If it's a reagent with quality, get id from CraftingDataItem
|
||||
if (!newItemId)
|
||||
{
|
||||
std::vector<uint32> craftedItemList = sDB2Manager.GetCraftingDataItemIDByCraftingData(_craftingData->ID);
|
||||
if (craftedItemList.size() < qualityTier)
|
||||
return 0;
|
||||
|
||||
newItemId = craftedItemList[qualityTier - 1];
|
||||
}
|
||||
|
||||
return newItemId;
|
||||
uint32 index = std::min(qualityTier, uint32(craftedItemList.size())) - 1;
|
||||
return craftedItemList[index] ? craftedItemList[index] : craftedItemId;
|
||||
}
|
||||
|
||||
@@ -31,22 +31,22 @@ enum SpellCastResult : int32;
|
||||
class TC_GAME_API Crafting
|
||||
{
|
||||
public:
|
||||
Crafting(Player* player, Spell* spell) :
|
||||
_player(player), _spell(spell), _craftingData(nullptr) { }
|
||||
Crafting(Player* player, Spell* spell, bool recraft = false) :
|
||||
_player(player), _spell(spell), _craftingData(nullptr), _recraft(recraft) {
|
||||
}
|
||||
|
||||
SpellCastResult DoCraft(uint32 craftingDataId);
|
||||
SpellCastResult DoCraft(uint32 craftingDataId);
|
||||
|
||||
private:
|
||||
uint32 GetSkillLevelForCraft();
|
||||
uint32 GetSkillIdForSpell(uint32 spellId);
|
||||
uint32 CalculateTotalReagentWeights();
|
||||
void InitCraftingStatModifier(Item* item);
|
||||
uint32 GetCraftedItemIdForQuality(uint32 qualityTier);
|
||||
uint32 GetSkillIdForSpell(uint32 spellId) const;
|
||||
uint32 GetCraftedItemIdForQuality(uint32 qualityTier) const;
|
||||
void InitCraftingStatModifier(Item* item, bool statsChosenByReagent);
|
||||
|
||||
Player* _player;
|
||||
Spell* _spell;
|
||||
|
||||
CraftingDataEntry const* _craftingData;
|
||||
bool _recraft;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -37,6 +37,12 @@
|
||||
#include <numeric>
|
||||
#include <cctype>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
//WowCommunity
|
||||
#include "DB2FileSystemSource.h"
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
//WowCommunity
|
||||
|
||||
DB2Storage<AchievementEntry> sAchievementStore("Achievement.db2", &AchievementLoadInfo::Instance);
|
||||
DB2Storage<Achievement_CategoryEntry> sAchievementCategoryStore("Achievement_Category.db2", &AchievementCategoryLoadInfo::Instance);
|
||||
@@ -726,6 +732,322 @@ namespace
|
||||
std::unordered_map<uint32, std::set<ItemSparseEntry const*>> _ItemSparseByMCRReagentItem;
|
||||
std::unordered_map<uint32, std::vector<uint32>> _CraftingDataItemIDByCraftingData;
|
||||
std::unordered_map<uint32, CraftingReagentQualityEntry const*> _CraftingReagentQualityByItem;
|
||||
|
||||
//WowCommunity
|
||||
struct ProfessionEffectValue
|
||||
{
|
||||
int32 Type = 0;
|
||||
float Amount = 0.0f;
|
||||
};
|
||||
|
||||
std::unordered_map<uint32, std::vector<ProfessionEffectValue>> _professionEffectsByTraitDefinition;
|
||||
std::unordered_map<uint32, uint32> _concentrationCurrencyBySkillLine;
|
||||
std::unordered_map<uint32, std::pair<float, float>> _multicraftExtraPercentBySkillLine;
|
||||
|
||||
// Client files only. These tables have no hotfix statement, so a missing or
|
||||
// mismatched db2 must not be added to the fatal load error list.
|
||||
void LoadProfessionProcTables(std::string const& path)
|
||||
{
|
||||
#pragma pack(push, 1)
|
||||
struct ProfessionRecord
|
||||
{
|
||||
uint32 ID;
|
||||
int32 SkillLineID;
|
||||
int32 ProfessionEnumValue;
|
||||
float ResourcefulEffectLow;
|
||||
float ResourcefulEffectHigh;
|
||||
float MinCraftExtraQtyPct;
|
||||
float MaxCraftExtraQtyPct;
|
||||
float GatherTimeIncreasePct;
|
||||
int32 ActionTypeEnumValue;
|
||||
float RecraftModSkillGainPct;
|
||||
int32 PublicOrderCapacityCurrencyID;
|
||||
};
|
||||
|
||||
struct ProfessionEffectRecord
|
||||
{
|
||||
uint32 ID;
|
||||
int32 ProfessionEffectTypeEnumID;
|
||||
float Amount;
|
||||
int32 ModifiedCraftingReagentSlotID;
|
||||
};
|
||||
|
||||
struct ProfessionTraitRecord
|
||||
{
|
||||
uint32 ID;
|
||||
int32 TraitDefinitionID;
|
||||
};
|
||||
|
||||
struct ProfessionTraitXEffectRecord
|
||||
{
|
||||
uint32 ID;
|
||||
int32 ProfessionTraitID;
|
||||
int32 ProfessionEffectID;
|
||||
int32 Unused;
|
||||
};
|
||||
|
||||
struct ProfessionExpansionRecord
|
||||
{
|
||||
uint32 ID;
|
||||
int32 SkillLineID;
|
||||
int32 RecraftSpellID;
|
||||
int32 ConcentrationCurrencyID;
|
||||
int32 ExpansionID;
|
||||
int32 SpecResetSpellID;
|
||||
int32 SpecResetCurrencyID;
|
||||
int32 ProfessionID;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
static_assert(sizeof(ProfessionRecord) == 44);
|
||||
static_assert(sizeof(ProfessionEffectRecord) == 16);
|
||||
static_assert(sizeof(ProfessionTraitRecord) == 8);
|
||||
static_assert(sizeof(ProfessionTraitXEffectRecord) == 16);
|
||||
static_assert(sizeof(ProfessionExpansionRecord) == 32);
|
||||
|
||||
// Layout hashes are the 12.1.0.69875 WoWDBDefs LAYOUT ids.
|
||||
static const DB2MetaField ProfessionFields[11] =
|
||||
{
|
||||
{.Type = FT_INT, .ArraySize = 1, .IsSigned = false },
|
||||
{.Type = FT_INT, .ArraySize = 1, .IsSigned = true },
|
||||
{.Type = FT_INT, .ArraySize = 1, .IsSigned = true },
|
||||
{.Type = FT_FLOAT, .ArraySize = 1, .IsSigned = false },
|
||||
{.Type = FT_FLOAT, .ArraySize = 1, .IsSigned = false },
|
||||
{.Type = FT_FLOAT, .ArraySize = 1, .IsSigned = false },
|
||||
{.Type = FT_FLOAT, .ArraySize = 1, .IsSigned = false },
|
||||
{.Type = FT_FLOAT, .ArraySize = 1, .IsSigned = false },
|
||||
{.Type = FT_INT, .ArraySize = 1, .IsSigned = true },
|
||||
{.Type = FT_FLOAT, .ArraySize = 1, .IsSigned = false },
|
||||
{.Type = FT_INT, .ArraySize = 1, .IsSigned = true },
|
||||
};
|
||||
static const DB2Meta ProfessionMeta =
|
||||
{
|
||||
.FileDataId = 4508544,
|
||||
.IndexField = 0,
|
||||
.ParentIndexField = -1,
|
||||
.FieldCount = 11,
|
||||
.FileFieldCount = 11,
|
||||
.LayoutHash = 0x86FE926D,
|
||||
.Fields = ProfessionFields
|
||||
};
|
||||
static const DB2FieldMeta ProfessionLoadFields[11] =
|
||||
{
|
||||
{.IsSigned = false, .Type = FT_INT, .Name = "ID" },
|
||||
{.IsSigned = true, .Type = FT_INT, .Name = "SkillLineID" },
|
||||
{.IsSigned = true, .Type = FT_INT, .Name = "ProfessionEnumValue" },
|
||||
{.IsSigned = false, .Type = FT_FLOAT, .Name = "ResourcefulEffectLow" },
|
||||
{.IsSigned = false, .Type = FT_FLOAT, .Name = "ResourcefulEffectHigh" },
|
||||
{.IsSigned = false, .Type = FT_FLOAT, .Name = "MinCraftExtraQtyPct" },
|
||||
{.IsSigned = false, .Type = FT_FLOAT, .Name = "MaxCraftExtraQtyPct" },
|
||||
{.IsSigned = false, .Type = FT_FLOAT, .Name = "GatherTimeIncreasePct" },
|
||||
{.IsSigned = true, .Type = FT_INT, .Name = "ActionTypeEnumValue" },
|
||||
{.IsSigned = false, .Type = FT_FLOAT, .Name = "RecraftModSkillGainPct" },
|
||||
{.IsSigned = true, .Type = FT_INT, .Name = "PublicOrderCapacityCurrencyID" },
|
||||
};
|
||||
static const DB2FileLoadInfo ProfessionLoadInfo{ ProfessionLoadFields, 11, &ProfessionMeta };
|
||||
|
||||
static const DB2MetaField ProfessionEffectFields[3] =
|
||||
{
|
||||
{.Type = FT_INT, .ArraySize = 1, .IsSigned = true },
|
||||
{.Type = FT_FLOAT, .ArraySize = 1, .IsSigned = false },
|
||||
{.Type = FT_INT, .ArraySize = 1, .IsSigned = true },
|
||||
};
|
||||
static const DB2Meta ProfessionEffectMeta =
|
||||
{
|
||||
.FileDataId = 4505297,
|
||||
.IndexField = -1,
|
||||
.ParentIndexField = -1,
|
||||
.FieldCount = 3,
|
||||
.FileFieldCount = 3,
|
||||
.LayoutHash = 0x04C16FA9,
|
||||
.Fields = ProfessionEffectFields
|
||||
};
|
||||
static const DB2FieldMeta ProfessionEffectLoadFields[4] =
|
||||
{
|
||||
{.IsSigned = false, .Type = FT_INT, .Name = "ID" },
|
||||
{.IsSigned = true, .Type = FT_INT, .Name = "ProfessionEffectTypeEnumID" },
|
||||
{.IsSigned = false, .Type = FT_FLOAT, .Name = "Amount" },
|
||||
{.IsSigned = true, .Type = FT_INT, .Name = "ModifiedCraftingReagentSlotID" },
|
||||
};
|
||||
static const DB2FileLoadInfo ProfessionEffectLoadInfo{ ProfessionEffectLoadFields, 4, &ProfessionEffectMeta };
|
||||
|
||||
static const DB2MetaField ProfessionTraitFields[2] =
|
||||
{
|
||||
{.Type = FT_INT, .ArraySize = 1, .IsSigned = false },
|
||||
{.Type = FT_INT, .ArraySize = 1, .IsSigned = true },
|
||||
};
|
||||
static const DB2Meta ProfessionTraitMeta =
|
||||
{
|
||||
.FileDataId = 4505298,
|
||||
.IndexField = 0,
|
||||
.ParentIndexField = -1,
|
||||
.FieldCount = 2,
|
||||
.FileFieldCount = 2,
|
||||
.LayoutHash = 0x306455FE,
|
||||
.Fields = ProfessionTraitFields
|
||||
};
|
||||
static const DB2FieldMeta ProfessionTraitLoadFields[2] =
|
||||
{
|
||||
{.IsSigned = false, .Type = FT_INT, .Name = "ID" },
|
||||
{.IsSigned = true, .Type = FT_INT, .Name = "TraitDefinitionID" },
|
||||
};
|
||||
static const DB2FileLoadInfo ProfessionTraitLoadInfo{ ProfessionTraitLoadFields, 2, &ProfessionTraitMeta };
|
||||
|
||||
static const DB2MetaField ProfessionTraitXEffectFields[4] =
|
||||
{
|
||||
{.Type = FT_INT, .ArraySize = 1, .IsSigned = false },
|
||||
{.Type = FT_INT, .ArraySize = 1, .IsSigned = true },
|
||||
{.Type = FT_INT, .ArraySize = 1, .IsSigned = true },
|
||||
{.Type = FT_INT, .ArraySize = 1, .IsSigned = true },
|
||||
};
|
||||
static const DB2Meta ProfessionTraitXEffectMeta =
|
||||
{
|
||||
.FileDataId = 4505494,
|
||||
.IndexField = 0,
|
||||
.ParentIndexField = 1,
|
||||
.FieldCount = 4,
|
||||
.FileFieldCount = 4,
|
||||
.LayoutHash = 0x97A0A286,
|
||||
.Fields = ProfessionTraitXEffectFields
|
||||
};
|
||||
static const DB2FieldMeta ProfessionTraitXEffectLoadFields[4] =
|
||||
{
|
||||
{.IsSigned = false, .Type = FT_INT, .Name = "ID" },
|
||||
{.IsSigned = true, .Type = FT_INT, .Name = "ProfessionTraitID" },
|
||||
{.IsSigned = true, .Type = FT_INT, .Name = "ProfessionEffectID" },
|
||||
{.IsSigned = true, .Type = FT_INT, .Name = "Field_10_0_0_44649_003" },
|
||||
};
|
||||
static const DB2FileLoadInfo ProfessionTraitXEffectLoadInfo{ ProfessionTraitXEffectLoadFields, 4, &ProfessionTraitXEffectMeta };
|
||||
|
||||
static const DB2MetaField ProfessionExpansionFields[8] =
|
||||
{
|
||||
{.Type = FT_INT, .ArraySize = 1, .IsSigned = false },
|
||||
{.Type = FT_INT, .ArraySize = 1, .IsSigned = true },
|
||||
{.Type = FT_INT, .ArraySize = 1, .IsSigned = true },
|
||||
{.Type = FT_INT, .ArraySize = 1, .IsSigned = true },
|
||||
{.Type = FT_INT, .ArraySize = 1, .IsSigned = true },
|
||||
{.Type = FT_INT, .ArraySize = 1, .IsSigned = true },
|
||||
{.Type = FT_INT, .ArraySize = 1, .IsSigned = true },
|
||||
{.Type = FT_INT, .ArraySize = 1, .IsSigned = true },
|
||||
};
|
||||
static const DB2Meta ProfessionExpansionMeta =
|
||||
{
|
||||
.FileDataId = 5662322,
|
||||
.IndexField = 0,
|
||||
.ParentIndexField = 7,
|
||||
.FieldCount = 8,
|
||||
.FileFieldCount = 7,
|
||||
.LayoutHash = 0x6DABCB98,
|
||||
.Fields = ProfessionExpansionFields
|
||||
};
|
||||
static const DB2FieldMeta ProfessionExpansionLoadFields[8] =
|
||||
{
|
||||
{.IsSigned = false, .Type = FT_INT, .Name = "ID" },
|
||||
{.IsSigned = true, .Type = FT_INT, .Name = "SkillLineID" },
|
||||
{.IsSigned = true, .Type = FT_INT, .Name = "RecraftSpellID" },
|
||||
{.IsSigned = true, .Type = FT_INT, .Name = "ConcentrationCurrencyID" },
|
||||
{.IsSigned = true, .Type = FT_INT, .Name = "ExpansionID" },
|
||||
{.IsSigned = true, .Type = FT_INT, .Name = "SpecResetSpellID" },
|
||||
{.IsSigned = true, .Type = FT_INT, .Name = "SpecResetCurrencyID" },
|
||||
{.IsSigned = true, .Type = FT_INT, .Name = "ProfessionID" },
|
||||
};
|
||||
static const DB2FileLoadInfo ProfessionExpansionLoadInfo{ ProfessionExpansionLoadFields, 8, &ProfessionExpansionMeta };
|
||||
|
||||
auto loadRecords = [&](char const* fileName, DB2FileLoadInfo const* loadInfo, auto& out)
|
||||
{
|
||||
using Record = typename std::decay_t<decltype(out)>::value_type;
|
||||
try
|
||||
{
|
||||
DB2FileLoader loader;
|
||||
DB2FileSystemSource source(path + fileName);
|
||||
loader.Load(&source, loadInfo);
|
||||
|
||||
uint32 indexSize = 0;
|
||||
char** index = nullptr;
|
||||
char* data = loader.AutoProduceData(indexSize, index);
|
||||
loader.AutoProduceRecordCopies(indexSize, index, data);
|
||||
|
||||
if (loadInfo->Meta->GetRecordSize() != sizeof(Record))
|
||||
{
|
||||
delete[] data;
|
||||
delete[] index;
|
||||
TC_LOG_ERROR("server.loading", "Profession table {} record size {} does not match C++ size {}", fileName, loadInfo->Meta->GetRecordSize(), sizeof(Record));
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < indexSize; ++i)
|
||||
{
|
||||
if (!index[i])
|
||||
continue;
|
||||
|
||||
Record record;
|
||||
std::memcpy(&record, index[i], sizeof(Record));
|
||||
out.push_back(record);
|
||||
}
|
||||
|
||||
delete[] data;
|
||||
delete[] index;
|
||||
TC_LOG_INFO("server.loading", ">> Loaded {} rows from {}", out.size(), fileName);
|
||||
}
|
||||
catch (std::exception const& error)
|
||||
{
|
||||
TC_LOG_ERROR("server.loading", "Profession table {} was not loaded ({}). Concentration, inspiration and multicraft stay off for data from this file.", fileName, error.what());
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<ProfessionRecord> professions;
|
||||
std::vector<ProfessionEffectRecord> effects;
|
||||
std::vector<ProfessionTraitRecord> traits;
|
||||
std::vector<ProfessionTraitXEffectRecord> links;
|
||||
std::vector<ProfessionExpansionRecord> expansions;
|
||||
loadRecords("Profession.db2", &ProfessionLoadInfo, professions);
|
||||
loadRecords("ProfessionEffect.db2", &ProfessionEffectLoadInfo, effects);
|
||||
loadRecords("ProfessionTrait.db2", &ProfessionTraitLoadInfo, traits);
|
||||
loadRecords("ProfessionTraitXEffect.db2", &ProfessionTraitXEffectLoadInfo, links);
|
||||
loadRecords("ProfessionExpansion.db2", &ProfessionExpansionLoadInfo, expansions);
|
||||
|
||||
if (professions.empty() || effects.empty() || traits.empty() || links.empty() || expansions.empty())
|
||||
{
|
||||
TC_LOG_ERROR("server.loading", "Profession proc tables are incomplete. Concentration, inspiration and multicraft stay disabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
std::unordered_map<uint32, ProfessionEffectValue> effectsById;
|
||||
for (ProfessionEffectRecord const& effect : effects)
|
||||
effectsById[effect.ID] = { effect.ProfessionEffectTypeEnumID, effect.Amount };
|
||||
|
||||
std::unordered_map<uint32, uint32> traitDefinitionById;
|
||||
for (ProfessionTraitRecord const& trait : traits)
|
||||
if (trait.TraitDefinitionID > 0)
|
||||
traitDefinitionById[trait.ID] = uint32(trait.TraitDefinitionID);
|
||||
|
||||
for (ProfessionTraitXEffectRecord const& link : links)
|
||||
{
|
||||
if (link.ProfessionTraitID <= 0 || link.ProfessionEffectID <= 0)
|
||||
continue;
|
||||
|
||||
auto trait = traitDefinitionById.find(uint32(link.ProfessionTraitID));
|
||||
auto effect = effectsById.find(uint32(link.ProfessionEffectID));
|
||||
if (trait == traitDefinitionById.end() || effect == effectsById.end())
|
||||
continue;
|
||||
|
||||
_professionEffectsByTraitDefinition[trait->second].push_back(effect->second);
|
||||
}
|
||||
|
||||
for (ProfessionRecord const& profession : professions)
|
||||
{
|
||||
if (profession.SkillLineID <= 0)
|
||||
continue;
|
||||
|
||||
if (profession.MinCraftExtraQtyPct > 0.0f || profession.MaxCraftExtraQtyPct > 0.0f)
|
||||
_multicraftExtraPercentBySkillLine[uint32(profession.SkillLineID)] = { profession.MinCraftExtraQtyPct, profession.MaxCraftExtraQtyPct };
|
||||
}
|
||||
|
||||
for (ProfessionExpansionRecord const& expansion : expansions)
|
||||
if (expansion.SkillLineID > 0 && expansion.ConcentrationCurrencyID > 0)
|
||||
_concentrationCurrencyBySkillLine[uint32(expansion.SkillLineID)] = uint32(expansion.ConcentrationCurrencyID);
|
||||
}
|
||||
//WowCommunity
|
||||
}
|
||||
|
||||
static void LoadDB2(std::bitset<TOTAL_LOCALES>& availableDb2Locales, std::vector<std::string>& errlist, StorageMap& stores, DB2StorageBase* storage, std::string const& db2Path,
|
||||
@@ -1377,6 +1699,7 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul
|
||||
LOAD_DB2(sItemLogicalCostStore);
|
||||
LOAD_DB2(sTrophyStore);
|
||||
LOAD_DB2(sManagedWorldStateBuffStore);
|
||||
LoadProfessionProcTables(db2Path + localeNames[defaultLocale] + '/');
|
||||
//WowCommunity
|
||||
// error checks
|
||||
|
||||
@@ -1866,6 +2189,61 @@ void DB2Manager::IndexLoadedStores()
|
||||
if (sSkillLineStore.LookupEntry(entry->SkillID))
|
||||
_skillRaceClassInfoBySkill.insert(SkillRaceClassInfoContainer::value_type(entry->SkillID, entry));
|
||||
|
||||
for (ModifiedCraftingSpellSlotEntry const* slot : sModifiedCraftingSpellSlotStore)
|
||||
if (slot->SpellID > 0)
|
||||
_MCRSpellSlotBySpell[uint32(slot->SpellID)].push_back(slot);
|
||||
|
||||
for (MCRSlotXMCRCategoryEntry const* link : sMCRSlotXMCRCategoryStore)
|
||||
if (ModifiedCraftingCategoryEntry const* category = sModifiedCraftingCategoryStore.LookupEntry(link->ModifiedCraftingCategoryID))
|
||||
_MCRCategoryByReagentSlot[uint32(link->ModifiedCraftingReagentSlotID)].push_back(category);
|
||||
|
||||
for (ModifiedCraftingReagentItemEntry const* reagentItem : sModifiedCraftingReagentItemStore)
|
||||
if (reagentItem->ModifiedCraftingCategoryID > 0)
|
||||
_MCRReagentItemByCategory[uint32(reagentItem->ModifiedCraftingCategoryID)].push_back(reagentItem);
|
||||
|
||||
for (ItemSparseEntry const* sparse : sItemSparseStore)
|
||||
if (sparse->ModifiedCraftingReagentItemID > 0)
|
||||
_ItemSparseByMCRReagentItem[uint32(sparse->ModifiedCraftingReagentItemID)].insert(sparse);
|
||||
|
||||
for (CraftingReagentQualityEntry const* quality : sCraftingReagentQualityStore)
|
||||
if (quality->ItemID > 0)
|
||||
_CraftingReagentQualityByItem[uint32(quality->ItemID)] = quality;
|
||||
|
||||
struct CraftingQualityItem
|
||||
{
|
||||
int32 Order = 0;
|
||||
uint32 RowId = 0;
|
||||
uint32 ItemId = 0;
|
||||
};
|
||||
|
||||
std::unordered_map<uint32, std::vector<CraftingQualityItem>> craftingItemsByData;
|
||||
for (CraftingDataItemQualityEntry const* row : sCraftingDataItemQualityStore)
|
||||
{
|
||||
if (row->ItemID <= 0 || row->CraftingDataID <= 0)
|
||||
continue;
|
||||
|
||||
int32 order = std::numeric_limits<int32>::max();
|
||||
if (CraftingReagentQualityEntry const* quality = Trinity::Containers::MapGetValuePtr(_CraftingReagentQualityByItem, uint32(row->ItemID)))
|
||||
order = quality->OrderIndex;
|
||||
|
||||
craftingItemsByData[uint32(row->CraftingDataID)].push_back({ order, row->ID, uint32(row->ItemID) });
|
||||
}
|
||||
|
||||
for (auto& [craftingDataId, rows] : craftingItemsByData)
|
||||
{
|
||||
std::ranges::sort(rows, [](CraftingQualityItem const& left, CraftingQualityItem const& right)
|
||||
{
|
||||
if (left.Order != right.Order)
|
||||
return left.Order < right.Order;
|
||||
return left.RowId < right.RowId;
|
||||
});
|
||||
|
||||
std::vector<uint32>& itemIds = _CraftingDataItemIDByCraftingData[craftingDataId];
|
||||
itemIds.reserve(rows.size());
|
||||
for (CraftingQualityItem const& row : rows)
|
||||
itemIds.push_back(row.ItemId);
|
||||
}
|
||||
|
||||
for (SoulbindConduitRankEntry const* soulbindConduitRank : sSoulbindConduitRankStore)
|
||||
_soulbindConduitRanks[{ soulbindConduitRank->SoulbindConduitID, soulbindConduitRank->RankIndex }] = soulbindConduitRank;
|
||||
|
||||
@@ -3856,32 +4234,47 @@ DB2Manager::DelvesSeasonXSpellContainer const* DB2Manager::GetDelvesSeasonSpells
|
||||
|
||||
std::vector<ModifiedCraftingSpellSlotEntry const*> DB2Manager::GetMCRSpellSlotBySpell(uint32 spellId)
|
||||
{
|
||||
return _MCRSpellSlotBySpell[spellId];
|
||||
if (std::vector<ModifiedCraftingSpellSlotEntry const*> const* slots = Trinity::Containers::MapGetValuePtr(_MCRSpellSlotBySpell, spellId))
|
||||
return *slots;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<ModifiedCraftingCategoryEntry const*> DB2Manager::GetMCRCategoryByReagentSlot(uint32 reagentSlotID)
|
||||
{
|
||||
return _MCRCategoryByReagentSlot[reagentSlotID];
|
||||
if (std::vector<ModifiedCraftingCategoryEntry const*> const* categories = Trinity::Containers::MapGetValuePtr(_MCRCategoryByReagentSlot, reagentSlotID))
|
||||
return *categories;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<ModifiedCraftingReagentItemEntry const*> DB2Manager::GetMCRReagentItemByCategory(uint32 categoryID)
|
||||
{
|
||||
return _MCRReagentItemByCategory[categoryID];
|
||||
if (std::vector<ModifiedCraftingReagentItemEntry const*> const* reagentItems = Trinity::Containers::MapGetValuePtr(_MCRReagentItemByCategory, categoryID))
|
||||
return *reagentItems;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::set<ItemSparseEntry const*> DB2Manager::GetItemSparseByMCRReagentItem(uint32 reagentItemID)
|
||||
{
|
||||
return _ItemSparseByMCRReagentItem[reagentItemID];
|
||||
if (std::set<ItemSparseEntry const*> const* items = Trinity::Containers::MapGetValuePtr(_ItemSparseByMCRReagentItem, reagentItemID))
|
||||
return *items;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<uint32> DB2Manager::GetCraftingDataItemIDByCraftingData(uint32 craftingDataID)
|
||||
{
|
||||
return _CraftingDataItemIDByCraftingData[craftingDataID];
|
||||
if (std::vector<uint32> const* itemIds = Trinity::Containers::MapGetValuePtr(_CraftingDataItemIDByCraftingData, craftingDataID))
|
||||
return *itemIds;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
CraftingReagentQualityEntry const* DB2Manager::GetCraftingReagentQualityByItem(uint32 itemID)
|
||||
{
|
||||
return _CraftingReagentQualityByItem[itemID];
|
||||
return Trinity::Containers::MapGetValuePtr(_CraftingReagentQualityByItem, itemID);
|
||||
}
|
||||
|
||||
uint32 DB2Manager::GetCraftingQualityTierByDifficultyPercent(int32 craftingDifficultyID, uint32 difficultyPercent)
|
||||
@@ -3900,6 +4293,69 @@ uint32 DB2Manager::GetCraftingQualityTierByDifficultyPercent(int32 craftingDiffi
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void DB2Manager::AccumulateProfessionTraitEffects(int32 traitDefinitionId, int32 rank, ProfessionEffectTotals& totals) const
|
||||
{
|
||||
if (traitDefinitionId <= 0 || rank <= 0)
|
||||
return;
|
||||
|
||||
auto itr = _professionEffectsByTraitDefinition.find(uint32(traitDefinitionId));
|
||||
if (itr == _professionEffectsByTraitDefinition.end())
|
||||
return;
|
||||
|
||||
// ProfessionEffectType.EnumID, build 12.1.0.69875. Amount is per rank.
|
||||
for (ProfessionEffectValue const& effect : itr->second)
|
||||
{
|
||||
float value = effect.Amount * float(rank);
|
||||
switch (effect.Type)
|
||||
{
|
||||
case 0: // Skill
|
||||
totals.Skill += value;
|
||||
break;
|
||||
case 1: // Inspiration rating
|
||||
totals.InspirationRating += value;
|
||||
break;
|
||||
case 7: // Multicraft rating
|
||||
totals.MulticraftRating += value;
|
||||
break;
|
||||
case 18: // additional items crafted with Multicraft, percent
|
||||
totals.MulticraftExtraPercent += value;
|
||||
break;
|
||||
case 20: // bonus Crafting Skill from Inspiration
|
||||
totals.InspirationBonusSkill += value;
|
||||
break;
|
||||
case 22: // Decrease Difficulty
|
||||
totals.DifficultyDelta -= value;
|
||||
break;
|
||||
case 23: // Increase Difficulty
|
||||
totals.DifficultyDelta += value;
|
||||
break;
|
||||
case 27: // reduce concentration cost, percent
|
||||
totals.ConcentrationCostReductionPercent += value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32 DB2Manager::GetConcentrationCurrencyForSkillLine(uint32 skillLineId) const
|
||||
{
|
||||
auto itr = _concentrationCurrencyBySkillLine.find(skillLineId);
|
||||
return itr != _concentrationCurrencyBySkillLine.end() ? itr->second : 0;
|
||||
}
|
||||
|
||||
bool DB2Manager::GetMulticraftExtraQuantityRange(uint32 skillLineId, float& minPercent, float& maxPercent) const
|
||||
{
|
||||
auto itr = _multicraftExtraPercentBySkillLine.find(skillLineId);
|
||||
if (itr == _multicraftExtraPercentBySkillLine.end())
|
||||
return false;
|
||||
|
||||
minPercent = itr->second.first;
|
||||
maxPercent = itr->second.second;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 DB2Manager::GetConduitForItem(uint32 itemId) const
|
||||
{
|
||||
auto itr = _conduitsByItem.find(itemId);
|
||||
|
||||
@@ -541,6 +541,20 @@ TC_GAME_API extern TaxiPathNodesByPath sTaxiPathNod
|
||||
static bool Compare(structure const* left, structure const* right); \
|
||||
};
|
||||
|
||||
|
||||
// Sum of ProfessionEffect rows reached through the player's profession trait config.
|
||||
// Amounts are already multiplied by rank. Effect types are ProfessionEffectType.EnumID.
|
||||
struct ProfessionEffectTotals
|
||||
{
|
||||
float Skill = 0.0f;
|
||||
float InspirationRating = 0.0f;
|
||||
float MulticraftRating = 0.0f;
|
||||
float MulticraftExtraPercent = 0.0f;
|
||||
float InspirationBonusSkill = 0.0f;
|
||||
float ConcentrationCostReductionPercent = 0.0f;
|
||||
float DifficultyDelta = 0.0f;
|
||||
};
|
||||
|
||||
class TC_GAME_API DB2Manager
|
||||
{
|
||||
public:
|
||||
@@ -737,6 +751,9 @@ public:
|
||||
std::vector<uint32> GetCraftingDataItemIDByCraftingData(uint32 craftingDataID);
|
||||
CraftingReagentQualityEntry const* GetCraftingReagentQualityByItem(uint32 itemID);
|
||||
uint32 GetCraftingQualityTierByDifficultyPercent(int32 craftingDifficultyID, uint32 difficultyPercent);
|
||||
void AccumulateProfessionTraitEffects(int32 traitDefinitionId, int32 rank, ProfessionEffectTotals& totals) const;
|
||||
uint32 GetConcentrationCurrencyForSkillLine(uint32 skillLineId) const;
|
||||
bool GetMulticraftExtraQuantityRange(uint32 skillLineId, float& minPercent, float& maxPercent) const;
|
||||
std::vector<RenownRewardsEntry const*> const* GetRenownRewards(int32 covenantId, int32 level) const;
|
||||
std::vector<BountyEntry const*> const* GetBountiesForBountySet(int32 bountySetId) const;
|
||||
|
||||
|
||||
@@ -584,6 +584,8 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons)
|
||||
{
|
||||
Player* plrg = itr.GetSource();
|
||||
ObjectGuid pguid = plrg->GetGUID();
|
||||
uint8 memberRoles = (pguid == guid) ? roles : grp->GetLfgRoles(pguid);
|
||||
SetRoles(pguid, memberRoles);
|
||||
plrg->GetSession()->SendLfgUpdateStatus(updateData, true);
|
||||
SetState(pguid, LFG_STATE_ROLECHECK);
|
||||
SetTicket(pguid, ticket);
|
||||
@@ -1383,6 +1385,12 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false*
|
||||
{
|
||||
TC_LOG_DEBUG("lfg.teleport", "Player {} is being teleported out. Current Map {} - Expected Map {}",
|
||||
player->GetName(), player->GetMapId(), uint32(dungeon->map));
|
||||
|
||||
// In a follower dungeon, clean up the companion party before the player leaves the map
|
||||
// so the client doesn't keep "Unknown" members in the group frame.
|
||||
if (group)
|
||||
group->DespawnFollowerModeBots(player);
|
||||
|
||||
if (player->GetMapId() == uint32(dungeon->map))
|
||||
player->TeleportToBGEntryPoint();
|
||||
|
||||
|
||||
@@ -427,19 +427,8 @@ int32 GetAzeriteUnlockBonusList(uint16 azeriteUnlockMappingSetId, uint16 minItem
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<int32> GetBonusListsForItem(uint32 itemId, ItemBonusGenerationParams const& params, Player const* player)
|
||||
void AppendItemLevelSelectorBonuses(ItemTemplate const* itemTemplate, uint32 itemLevelSelectorId, std::vector<int32>& bonusListIDs)
|
||||
{
|
||||
std::vector<int32> bonusListIDs;
|
||||
|
||||
ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId);
|
||||
if (!itemTemplate)
|
||||
return bonusListIDs;
|
||||
|
||||
uint32 itemLevelSelectorId = 0;
|
||||
|
||||
for (auto [_, itemBonusTreeId] : Trinity::Containers::MapEqualRange(_itemToBonusTree, itemId))
|
||||
ApplyBonusTreeHelper(itemTemplate, itemBonusTreeId, params, 0, &itemLevelSelectorId, &bonusListIDs, player);
|
||||
|
||||
if (ItemLevelSelectorEntry const* selector = sItemLevelSelectorStore.LookupEntry(itemLevelSelectorId))
|
||||
{
|
||||
int16 delta = int16(selector->MinItemLevel) - int16(itemTemplate->GetBaseItemLevel());
|
||||
@@ -470,6 +459,35 @@ std::vector<int32> GetBonusListsForItem(uint32 itemId, ItemBonusGenerationParams
|
||||
bonusListIDs.push_back(azeriteUnlockBonusListId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::vector<int32> GetBonusListsForItem(uint32 itemId, ItemBonusGenerationParams const& params, Player const* player)
|
||||
{
|
||||
std::vector<int32> bonusListIDs;
|
||||
|
||||
ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId);
|
||||
if (!itemTemplate)
|
||||
return bonusListIDs;
|
||||
|
||||
uint32 itemLevelSelectorId = 0;
|
||||
|
||||
for (auto [_, itemBonusTreeId] : Trinity::Containers::MapEqualRange(_itemToBonusTree, itemId))
|
||||
ApplyBonusTreeHelper(itemTemplate, itemBonusTreeId, params, 0, &itemLevelSelectorId, &bonusListIDs, player);
|
||||
|
||||
AppendItemLevelSelectorBonuses(itemTemplate, itemLevelSelectorId, bonusListIDs);
|
||||
|
||||
return bonusListIDs;
|
||||
}
|
||||
|
||||
std::vector<int32> GetBonusListsForTree(uint32 itemBonusTreeId, ItemTemplate const* itemTemplate, ItemBonusGenerationParams const& params, Player const* player)
|
||||
{
|
||||
std::vector<int32> bonusListIDs;
|
||||
if (!itemBonusTreeId || !itemTemplate)
|
||||
return bonusListIDs;
|
||||
|
||||
uint32 itemLevelSelectorId = 0;
|
||||
ApplyBonusTreeHelper(itemTemplate, itemBonusTreeId, params, 0, &itemLevelSelectorId, &bonusListIDs, player);
|
||||
AppendItemLevelSelectorBonuses(itemTemplate, itemLevelSelectorId, bonusListIDs);
|
||||
return bonusListIDs;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
class ItemTemplate;
|
||||
class Player;
|
||||
struct ItemBonusEntry;
|
||||
struct MapDifficultyEntry;
|
||||
@@ -48,6 +49,7 @@ struct ItemBonusGenerationParams
|
||||
Optional<int32> PvpTier;
|
||||
};
|
||||
|
||||
TC_GAME_API std::vector<int32> GetBonusListsForTree(uint32 itemBonusTreeId, ItemTemplate const* itemTemplate, ItemBonusGenerationParams const& params, Player const* player = nullptr);
|
||||
TC_GAME_API std::vector<int32> GetBonusListsForItem(uint32 itemId, ItemBonusGenerationParams const& params, Player const* player = nullptr);
|
||||
TC_GAME_API std::vector<int32> GetAllBonusListsForTree(uint32 itemBonusTreeId);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "ObjectGuid.h"
|
||||
#include <atomic>
|
||||
|
||||
class ObjectGuidGenerator
|
||||
class TC_GAME_API ObjectGuidGenerator
|
||||
{
|
||||
public:
|
||||
explicit ObjectGuidGenerator(HighGuid high, ObjectGuid::LowType start = UI64LIT(1)) : _nextGuid(start), _high(high) { }
|
||||
|
||||
@@ -14021,7 +14021,7 @@ void Player::SendItemPassives()
|
||||
SendDirectMessage(sendItemPassives.Write());
|
||||
}
|
||||
|
||||
void Player::SendNewItem(Item* item, uint32 quantity, bool pushed, bool created, bool broadcast /*= false*/, uint32 dungeonEncounterId /*= 0*/)
|
||||
void Player::SendNewItem(Item* item, uint32 quantity, bool pushed, bool created, bool broadcast /*= false*/, uint32 dungeonEncounterId /*= 0*/, WorldPackets::Crafting::CraftingData const* craftingData /*= nullptr*/)
|
||||
{
|
||||
if (!item) // prevent crash
|
||||
return;
|
||||
@@ -14047,6 +14047,8 @@ void Player::SendNewItem(Item* item, uint32 quantity, bool pushed, bool created,
|
||||
packet.BattlePetLevel = item->GetModifier(ITEM_MODIFIER_BATTLE_PET_LEVEL);
|
||||
|
||||
packet.ItemGUID = item->GetGUID();
|
||||
if (craftingData)
|
||||
packet.CraftingData = *craftingData;
|
||||
|
||||
packet.Pushed = pushed;
|
||||
packet.ChatNotifyType = WorldPackets::Item::ItemPushResult::DISPLAY_TYPE_NORMAL;
|
||||
|
||||
@@ -1724,7 +1724,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
|
||||
bool IsUseEquipedWeapon(bool mainhand) const;
|
||||
bool IsTwoHandUsed() const;
|
||||
bool IsUsingTwoHandedWeaponInOneHand() const;
|
||||
void SendNewItem(Item* item, uint32 quantity, bool pushed, bool created, bool broadcast = false, uint32 dungeonEncounterId = 0);
|
||||
void SendNewItem(Item* item, uint32 quantity, bool pushed, bool created, bool broadcast = false, uint32 dungeonEncounterId = 0, WorldPackets::Crafting::CraftingData const* craftingData = nullptr);
|
||||
bool BuyItemFromVendorSlot(ObjectGuid vendorguid, uint32 vendorslot, uint32 item, uint32 count, uint8 bag, uint8 slot);
|
||||
Optional<SellResult> CanSellItemToVendor(Item const* item, uint32 amount) const;
|
||||
Optional<SellResult> SellItemToVendor(Item* item, uint32 amount);
|
||||
|
||||
@@ -112,6 +112,10 @@ void SceneMgr::OnSceneTrigger(uint32 sceneInstanceID, std::string const& trigger
|
||||
|
||||
SceneTemplate const* sceneTemplate = GetSceneTemplateFromInstanceId(sceneInstanceID);
|
||||
sScriptMgr->OnSceneTrigger(GetPlayer(), sceneInstanceID, sceneTemplate, triggerName);
|
||||
|
||||
// Exile's Reach reacts to scene triggers ("Teleport", "Big Kill Credit", ...) from a player script.
|
||||
// Scene template scripts are optional and do not receive those events.
|
||||
sScriptMgr->OnSceneTriggerEvent(GetPlayer(), sceneInstanceID, triggerName);
|
||||
}
|
||||
|
||||
void SceneMgr::OnSceneCancel(uint32 sceneInstanceID)
|
||||
|
||||
@@ -581,10 +581,19 @@ bool Group::RemoveMember(ObjectGuid guid, RemoveMethod method /*= GROUP_REMOVEME
|
||||
Player* player = ObjectAccessor::FindConnectedPlayer(guid);
|
||||
if (player)
|
||||
{
|
||||
for (GroupReference const& itr : GetMembers())
|
||||
// Snapshot member GUIDs first: aura removal below can re-enter group code
|
||||
// (script hooks, follower bot cleanup) and mutate m_memberSlots, which would
|
||||
// leave this loop walking a dead list.
|
||||
std::vector<ObjectGuid> memberGuids;
|
||||
memberGuids.reserve(m_memberSlots.size());
|
||||
for (MemberSlot const& slot : m_memberSlots)
|
||||
if (slot.guid != guid && slot.guid.IsPlayer())
|
||||
memberGuids.push_back(slot.guid);
|
||||
|
||||
for (ObjectGuid const& memberGuid : memberGuids)
|
||||
{
|
||||
Player* groupMember = itr.GetSource();
|
||||
if (groupMember->GetGUID() == guid)
|
||||
Player* groupMember = ObjectAccessor::FindConnectedPlayer(memberGuid);
|
||||
if (!groupMember)
|
||||
continue;
|
||||
|
||||
groupMember->RemoveAllGroupBuffsFromCaster(guid);
|
||||
@@ -2163,6 +2172,10 @@ void Group::DespawnFollowerModeBots(Player* player)
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
// Clean up LFG data so the player doesn't keep a stale follower dungeon state.
|
||||
if (isLFGGroup())
|
||||
sLFGMgr->RemoveGroupData(GetGUID());
|
||||
|
||||
uint32 playerMembers = 0;
|
||||
for (MemberSlot const& slot : m_memberSlots)
|
||||
if (slot.guid.IsPlayer())
|
||||
@@ -2202,6 +2215,12 @@ void Group::DespawnFollowerModeBots(Player* player)
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: never call RemoveMember() here. This runs inside
|
||||
// GroupScript::OnRemoveMember during an in-flight RemoveMember(); a nested
|
||||
// removal can Disband()/delete `this` and leave the outer call running on a
|
||||
// dead object. The outer RemoveMember (or the OnMapChanged LFG script)
|
||||
// removes the last real player and disbands the group by itself.
|
||||
|
||||
SendUpdate();
|
||||
}
|
||||
|
||||
|
||||
@@ -329,7 +329,24 @@ void WorldSession::SendLfgUpdateStatus(lfg::LfgUpdateData const& updateData, boo
|
||||
{
|
||||
return sLFGMgr->GetLFGDungeonEntry(dungeonId);
|
||||
});
|
||||
lfgUpdateStatus.RequestedRoles = sLFGMgr->GetRoles(_player->GetGUID());
|
||||
uint8 requestedRoles = sLFGMgr->GetRoles(_player->GetGUID());
|
||||
if (requestedRoles == 0)
|
||||
{
|
||||
if (Group* group = _player->GetGroup())
|
||||
requestedRoles = group->GetLfgRoles(_player->GetGUID());
|
||||
|
||||
if (requestedRoles == 0)
|
||||
{
|
||||
uint32 roleForGroup = _player->GetRoleForGroup();
|
||||
if (roleForGroup == ROLE_TANK)
|
||||
requestedRoles = lfg::PLAYER_ROLE_TANK;
|
||||
else if (roleForGroup == ROLE_HEALER)
|
||||
requestedRoles = lfg::PLAYER_ROLE_HEALER;
|
||||
else
|
||||
requestedRoles = lfg::PLAYER_ROLE_DAMAGE;
|
||||
}
|
||||
}
|
||||
lfgUpdateStatus.RequestedRoles = requestedRoles;
|
||||
//lfgUpdateStatus.SuspendedPlayers;
|
||||
lfgUpdateStatus.IsParty = party;
|
||||
lfgUpdateStatus.NotifyUI = true;
|
||||
|
||||
@@ -889,10 +889,15 @@ void WorldSession::HandleLFGListInviteResponse(WorldPackets::LFGList::LFGListInv
|
||||
|
||||
namespace
|
||||
{
|
||||
// GroupFinderActivity.ExpansionID of the expansion that has not shipped yet. Not a named client constant -
|
||||
// read straight out of the data: the 205 activities the 12.1 captures blacklist with reason 1 are exactly
|
||||
// the ExpansionID == 11 rows of GroupFinderActivity, and no reason-1 row has any other ExpansionID.
|
||||
constexpr int32 EXPANSION_UNRELEASED_GROUP_FINDER = 11;
|
||||
// GroupFinderActivity.ExpansionID of the expansion that has not shipped yet.
|
||||
// The 69382/69404 captures (18-20 Aug 2026) blacklist reason 1 as exactly the 205 ExpansionID == 11
|
||||
// rows, and 69273 (11 Aug) sends no reason 1 at all. That set is Midnight, not a future expansion:
|
||||
// 12.1.0.69875 GroupFinderActivity names them Windrunner Spire, Maisara Caverns, Murder Row,
|
||||
// Voidspire, March on Quel'Danas, the Midnight delves and the Midnight zones. Forwarding that
|
||||
// reason-1 set tells a 69875 client the current expansion is still locked, which is the Premade
|
||||
// Group Finder with no Midnight activities. 12 is the next id; this build's table has no
|
||||
// ExpansionID 12 rows.
|
||||
constexpr int32 EXPANSION_UNRELEASED_GROUP_FINDER = 12;
|
||||
|
||||
// SMSG_LFG_LIST_UPDATE_BLACKLIST content, extracted verbatim from the TARGET build 12.1.0.69382
|
||||
// (C:/dumps/wpp_work/lfg_ref/69382_s69382_ws6_5A000E_{0,1}.bin, both 9100 byte and BYTE-IDENTICAL to each
|
||||
@@ -913,8 +918,9 @@ namespace
|
||||
// nothing more.
|
||||
//
|
||||
// What the reasons are, as far as the captures decide it:
|
||||
// reason 1 - EXACT RULE, see below: ExpansionID == 11 (the unreleased expansion). 205 activities,
|
||||
// and the set is byte-for-byte identical in all three captures that carry it.
|
||||
// reason 1 - ExpansionID == 11, 205 activities, identical in the three captures that carry it.
|
||||
// On 69875 those rows are the live Midnight catalog, so HandleRequestLFGListBlacklist
|
||||
// does not forward reason 1. The snapshot below is left intact as the capture record.
|
||||
// reason 18 - 143 rows in ALL FOUR captures, identical set: legacy content permanently off the group
|
||||
// finder (MoP/WoD zones and the 10-man raid tiers - "The Jade Forest", "Mogu'shan Vaults
|
||||
// (10 Heroic)"). Constant, therefore derivable, but the deriving field is not yet found.
|
||||
@@ -1063,22 +1069,23 @@ void WorldSession::HandleRequestLFGListBlacklist(WorldPackets::LFGList::RequestL
|
||||
sent.reserve(std::size(LFGListActivityBlacklist));
|
||||
for (LFGListBlacklistRow const& row : LFGListActivityBlacklist)
|
||||
{
|
||||
// The 205 reason-1 rows are every ExpansionID 11 activity. That was "unreleased" on the
|
||||
// 69382 capture and is the live Midnight list on 69875 (see EXPANSION_UNRELEASED_GROUP_FINDER).
|
||||
// Sending them makes the client drop Maisara, Windrunner Spire, Voidspire and the rest.
|
||||
if (row.Reason == 1)
|
||||
continue;
|
||||
|
||||
WorldPackets::LFGList::LFGListBlacklistEntry& entry = packet.Entries.emplace_back();
|
||||
entry.ActivityID = row.ActivityID;
|
||||
entry.Reason = row.Reason;
|
||||
sent.insert(row.ActivityID);
|
||||
}
|
||||
|
||||
// Reason 1 is the one rule the captures settle exactly, so it is DERIVED and not trusted to the snapshot
|
||||
// above. In all three 12.1 captures that carry reason 1 (69382 x1, 69404 x2 - different build, different
|
||||
// faction, different character) the reason-1 set is EXACTLY the set of GroupFinderActivity rows with
|
||||
// ExpansionID == 11, 205 of 205, no row missing and no row extra. 69273 carries no reason 1 at all, which
|
||||
// fits: expansion 11 is the unreleased one and its activities entered the client data later.
|
||||
// Deriving it matters because the alternative rots on a schedule. Every build adds ExpansionID 11
|
||||
// activities, retail blacklists each of them on sight, and a frozen list of 205 ids would keep answering
|
||||
// with yesterday's set - the exact failure that put the 12.0.7 table into a 12.1 branch in the first
|
||||
// place. Rows already present in the snapshot are left alone so the observed 1137 keep their observed
|
||||
// order and no activity is ever sent twice (the retail payload has no duplicate ids either).
|
||||
// Reason 1 stays derived, but for the expansion that is not in this client yet. The August captures
|
||||
// used 11 because those rows were still locked; 69875 ships them. New GroupFinderActivity rows with
|
||||
// ExpansionID == EXPANSION_UNRELEASED_GROUP_FINDER are appended so a later DB2 does not start
|
||||
// offering the next expansion's activities the day they appear in the file. Snapshot rows already
|
||||
// copied above are left alone, and no activity is sent twice.
|
||||
for (GroupFinderActivityEntry const* activity : sGroupFinderActivityStore)
|
||||
{
|
||||
if (activity->ExpansionID != EXPANSION_UNRELEASED_GROUP_FINDER || sent.count(activity->ID))
|
||||
|
||||
@@ -2185,6 +2185,11 @@ void ScriptMgr::OnMovieComplete(Player* player, uint32 movieId)
|
||||
FOREACH_SCRIPT(PlayerScript)->OnMovieComplete(player, movieId);
|
||||
}
|
||||
|
||||
void ScriptMgr::OnSceneTriggerEvent(Player* player, uint32 sceneInstanceId, std::string event)
|
||||
{
|
||||
FOREACH_SCRIPT(PlayerScript)->OnSceneTriggerEvent(player, sceneInstanceId, std::move(event));
|
||||
}
|
||||
|
||||
void ScriptMgr::OnPlayerChoiceResponse(WorldObject* object, Player* player, PlayerChoice const* choice, PlayerChoiceResponse const* response, uint16 clientIdentifier)
|
||||
{
|
||||
ASSERT(choice);
|
||||
@@ -3299,22 +3304,16 @@ void ScriptMgr::OnQuestAbandon(Player* player, const Quest* quest)
|
||||
|
||||
void WowCommunity::PhaseShift(Player* player, std::vector<uint32> phaseIDs, bool add)
|
||||
{
|
||||
for (uint32 phaseID : phaseIDs)
|
||||
{
|
||||
if (add)
|
||||
{
|
||||
if (!player->GetPhaseShift().HasPhase(phaseID))
|
||||
PhasingHandler::AddPhase(player, phaseID, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (player->GetPhaseShift().HasPhase(phaseID))
|
||||
PhasingHandler::RemovePhase(player, phaseID, true);
|
||||
}
|
||||
}
|
||||
// Exile's Reach calls this every second. A false condition used to RemovePhase,
|
||||
// which stripped phases the world database had already applied and hid the quest
|
||||
// givers for the rest of the island. Only additions run here. A caller that must
|
||||
// drop a phase uses PhasingHandler::RemovePhase itself.
|
||||
if (!player || !add)
|
||||
return;
|
||||
|
||||
PhasingHandler::SendToPlayer(player);
|
||||
player->UpdateObjectVisibility(true);
|
||||
for (uint32 phaseID : phaseIDs)
|
||||
if (!player->GetPhaseShift().HasPhase(phaseID))
|
||||
PhasingHandler::AddPhase(player, phaseID, true);
|
||||
}
|
||||
|
||||
void ScriptMgr::OnPlayerWorldObjectUpdate(Player* player, uint32 diff)
|
||||
|
||||
@@ -254,8 +254,8 @@ namespace WorldPackets
|
||||
MissileTrajectoryRequest MissileTrajectory;
|
||||
Optional<MovementInfo> MoveUpdate;
|
||||
std::vector<SpellWeight> Weight;
|
||||
Array<SpellCraftingReagent, 6> CraftingReagents;
|
||||
Array<SpellCraftingReagent, 6> RemovedReagents;
|
||||
Array<SpellCraftingReagent, 16> CraftingReagents;
|
||||
Array<SpellCraftingReagent, 16> RemovedReagents;
|
||||
Array<SpellExtraCurrencyCost, 5 /*MAX_ITEM_EXT_COST_CURRENCIES*/> ExtraCurrencyCosts;
|
||||
Optional<uint64> CraftingOrderID;
|
||||
uint8 CraftingCastFlags = 0; // 1 = ApplyConcentration
|
||||
|
||||
@@ -1894,7 +1894,7 @@ void OpcodeTable::InitializeServerOpcodes()
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_LIST_APPLICANT_LIST_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_LIST_APPLICATION_STATUS_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_LIST_APPLY_TO_GROUP_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_LIST_CENSORED_ACTIVE_ENTRY_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_LIST_CENSORED_ACTIVE_ENTRY_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_LIST_JOIN_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_LIST_SEARCH_RESULTS, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_LIST_SEARCH_RESULTS_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
|
||||
@@ -140,6 +140,21 @@ SpellCastTargets::SpellCastTargets(Unit* caster, WorldPackets::Spells::SpellCast
|
||||
SetPitch(spellCastRequest.MissileTrajectory.Pitch);
|
||||
SetSpeed(spellCastRequest.MissileTrajectory.Speed);
|
||||
|
||||
for (WorldPackets::Spells::SpellCraftingReagent const& reagent : spellCastRequest.CraftingReagents)
|
||||
{
|
||||
if (reagent.Quantity <= 0)
|
||||
continue;
|
||||
|
||||
bool hasItem = reagent.Reagent.ItemID && *reagent.Reagent.ItemID > 0;
|
||||
bool hasCurrency = reagent.Reagent.CurrencyID && *reagent.Reagent.CurrencyID > 0;
|
||||
if (!hasItem && !hasCurrency)
|
||||
continue;
|
||||
|
||||
ModifiedCraftingReagents[uint32(reagent.Slot)].push_back(reagent);
|
||||
}
|
||||
|
||||
ApplyConcentration = (spellCastRequest.CraftingCastFlags & 1) != 0;
|
||||
|
||||
Update(caster);
|
||||
}
|
||||
|
||||
|
||||
@@ -452,6 +452,7 @@ public:
|
||||
|
||||
//WowCommunity
|
||||
std::unordered_map<uint32 /*SpellSlot*/, std::vector<WorldPackets::Spells::SpellCraftingReagent>> ModifiedCraftingReagents;
|
||||
bool ApplyConcentration = false; // SpellCastRequest.CraftingCastFlags bit 0 (value 1)
|
||||
//WowCommunity
|
||||
|
||||
private:
|
||||
|
||||
@@ -97,6 +97,7 @@
|
||||
#include "GarrisonMgr.h"
|
||||
#include "GroupMgr.h"
|
||||
#include "LFG.h"
|
||||
#include <unordered_map>
|
||||
//WowCommunity
|
||||
|
||||
NonDefaultConstructible<SpellEffectHandlerFn> SpellEffectHandlers[TOTAL_SPELL_EFFECTS] =
|
||||
@@ -2903,7 +2904,7 @@ void Spell::EffectCraftEnchant()
|
||||
return;
|
||||
}
|
||||
|
||||
Crafting craftingInstance = Crafting(player, this);
|
||||
Crafting craftingInstance = Crafting(player, this, true);
|
||||
SpellCastResult result = craftingInstance.DoCraft(effectInfo->MiscValue);
|
||||
|
||||
if (result != SpellCastResult::SPELL_CAST_OK)
|
||||
@@ -7998,6 +7999,15 @@ void Spell::EffectCraftItem()
|
||||
|
||||
Player* player = unitTarget->ToPlayer();
|
||||
|
||||
if (!sDB2Manager.GetMCRSpellSlotBySpell(m_spellInfo->Id).empty())
|
||||
{
|
||||
Crafting crafting(player, this, false);
|
||||
SpellCastResult result = crafting.DoCraft(uint32(effectInfo->MiscValue));
|
||||
if (result != SPELL_CAST_OK)
|
||||
SendCastResult(result);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 craftingID = effectInfo->MiscValue;
|
||||
|
||||
CraftingDataEntry const* craftingData = sCraftingDataStore.LookupEntry(craftingID);
|
||||
@@ -8044,8 +8054,33 @@ void Spell::EffectCraftLoot()
|
||||
if (!treasureId)
|
||||
return;
|
||||
|
||||
std::unordered_map<uint32, uint32> usedItems;
|
||||
for (auto const& [slot, reagents] : m_targets.ModifiedCraftingReagents)
|
||||
{
|
||||
for (WorldPackets::Spells::SpellCraftingReagent const& reagent : reagents)
|
||||
{
|
||||
if (!reagent.Reagent.ItemID || *reagent.Reagent.ItemID <= 0 || reagent.Quantity <= 0)
|
||||
continue;
|
||||
|
||||
uint32 itemId = uint32(*reagent.Reagent.ItemID);
|
||||
uint32 quantity = usedItems[itemId] + uint32(reagent.Quantity);
|
||||
if (!player->HasItemCount(itemId, quantity))
|
||||
{
|
||||
SendCastResult(SpellCastResult::SPELL_FAILED_NEED_MORE_ITEMS);
|
||||
return;
|
||||
}
|
||||
|
||||
usedItems[itemId] = quantity;
|
||||
}
|
||||
}
|
||||
|
||||
ItemContext context = m_spellInfo->HasAttribute(SPELL_ATTR0_IS_TRADESKILL) ? ItemContext::Trade_Skill : ItemContext::NONE;
|
||||
player->AutoStoreLoot(treasureId, LootTemplates_Spell, context, false, false, true);
|
||||
|
||||
for (auto const& [itemId, quantity] : usedItems)
|
||||
player->DestroyItemCount(itemId, quantity, true);
|
||||
|
||||
player->UpdateCraftSkill(m_spellInfo);
|
||||
}
|
||||
|
||||
void Spell::EffectApplyAreaAura()
|
||||
|
||||
@@ -16,7 +16,8 @@ uint32 const EncounterCount = 9;
|
||||
enum AmirdrassilDataTypes
|
||||
{
|
||||
// Encounters
|
||||
DATA_GNARLROOT = 1,
|
||||
// Encounters ? 0-based. EncounterCount is 9, so Fyrakk must stay index 8.
|
||||
DATA_GNARLROOT = 0,
|
||||
DATA_IGIRA_THE_CRUEL,
|
||||
DATA_VOLCOROSS,
|
||||
DATA_COUNCIL_OF_DREAMS,
|
||||
|
||||
+386
-14
@@ -1,32 +1,404 @@
|
||||
/*
|
||||
* This file is part of Algeth Team
|
||||
* Council of Dreams ? Urctos (208363), Aerwynn (208365), Pip (208367).
|
||||
*
|
||||
* One journal encounter. A member who would die while another is still standing
|
||||
* is downed and reborn after 12 seconds (418187 Rebirth). The encounter is
|
||||
* complete only when all three are down together.
|
||||
*
|
||||
* Body spells confirmed on Wowhead:
|
||||
* Urctos: 420946 Barreling Charge, 421020 Agonizing Claws, 420525 Blind Rage.
|
||||
* Aerwynn: 420937 Relentless Barrage, 421292 Constricting Thicket, 420856 Poisonous Javelin.
|
||||
* Pip's creature page listed no spells. The remaining council spells from the
|
||||
* Urctos/Aerwynn pages are cast by Pip: 418720 Polymorph Bomb, 421029 Song of the Dragon,
|
||||
* 421032 Captivating Finale.
|
||||
*/
|
||||
|
||||
#include "AreaTrigger.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "CellImpl.h"
|
||||
#include "GameObject.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "SpellScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "amirdrassil.h"
|
||||
|
||||
enum amirdrassilSpells
|
||||
enum CouncilSpells
|
||||
{
|
||||
|
||||
SPELL_COUNCIL_REBIRTH = 418187,
|
||||
SPELL_BARRELING_CHARGE = 420946,
|
||||
SPELL_AGONIZING_CLAWS = 421020,
|
||||
SPELL_BLIND_RAGE = 420525,
|
||||
SPELL_RELENTLESS_BARRAGE = 420937,
|
||||
SPELL_CONSTRICTING_THICKET = 421292,
|
||||
SPELL_POISONOUS_JAVELIN = 420856,
|
||||
SPELL_POLYMORPH_BOMB = 418720,
|
||||
SPELL_SONG_OF_THE_DRAGON = 421029,
|
||||
SPELL_CAPTIVATING_FINALE = 421032
|
||||
};
|
||||
|
||||
enum amirdrassilEvents
|
||||
enum CouncilEvents
|
||||
{
|
||||
|
||||
EVENT_COUNCIL_REBIRTH = 1,
|
||||
EVENT_COUNCIL_SPELL_1,
|
||||
EVENT_COUNCIL_SPELL_2,
|
||||
EVENT_COUNCIL_SPELL_3
|
||||
};
|
||||
|
||||
static constexpr float CouncilSearchRange = 150.0f;
|
||||
|
||||
struct council_ai : public ScriptedAI
|
||||
{
|
||||
council_ai(Creature* creature) : ScriptedAI(creature), _downed(false), _finishing(false), _linking(false), _evading(false) {}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_events.Reset();
|
||||
_downed = false;
|
||||
_finishing = false;
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->SetControlled(false, UNIT_STATE_ROOT);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
if (InstanceScript* instance = me->GetInstanceScript())
|
||||
{
|
||||
if (instance->GetBossState(DATA_COUNCIL_OF_DREAMS) == DONE)
|
||||
{
|
||||
EnterEvadeMode(EvadeReason::Other);
|
||||
return;
|
||||
}
|
||||
|
||||
if (instance->GetBossState(DATA_COUNCIL_OF_DREAMS) != IN_PROGRESS)
|
||||
{
|
||||
instance->SetBossState(DATA_COUNCIL_OF_DREAMS, IN_PROGRESS);
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||
}
|
||||
else
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||
}
|
||||
|
||||
PullSiblings(who);
|
||||
ScheduleCouncilEvents();
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
uint64 health = me->GetHealth();
|
||||
if (_finishing || damage < health)
|
||||
return;
|
||||
|
||||
if (!AnySiblingStanding())
|
||||
{
|
||||
_finishing = true;
|
||||
return;
|
||||
}
|
||||
|
||||
damage = health > 1 ? uint32(health - 1) : 0;
|
||||
if (_downed)
|
||||
return;
|
||||
|
||||
_downed = true;
|
||||
_events.Reset();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->AttackStop();
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
me->SetControlled(true, UNIT_STATE_ROOT);
|
||||
_events.ScheduleEvent(EVENT_COUNCIL_REBIRTH, 12s);
|
||||
CastRebirthFromSibling();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (InstanceScript* instance = me->GetInstanceScript())
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
|
||||
if (AnySiblingStanding())
|
||||
return;
|
||||
|
||||
if (InstanceScript* instance = me->GetInstanceScript())
|
||||
if (instance->GetBossState(DATA_COUNCIL_OF_DREAMS) != DONE)
|
||||
instance->SetBossState(DATA_COUNCIL_OF_DREAMS, DONE);
|
||||
|
||||
ForEachSibling([](council_ai* ai) { ai->ForceFinish(); });
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (_evading)
|
||||
return;
|
||||
|
||||
_evading = true;
|
||||
|
||||
if (InstanceScript* instance = me->GetInstanceScript())
|
||||
{
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
if (instance->GetBossState(DATA_COUNCIL_OF_DREAMS) == IN_PROGRESS)
|
||||
instance->SetBossState(DATA_COUNCIL_OF_DREAMS, FAIL);
|
||||
}
|
||||
|
||||
ForEachSibling([why](council_ai* ai)
|
||||
{
|
||||
if (ai->me->IsEngaged())
|
||||
ai->EnterEvadeMode(why);
|
||||
});
|
||||
|
||||
ScriptedAI::EnterEvadeMode(why);
|
||||
_evading = false;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (_finishing)
|
||||
return;
|
||||
|
||||
// A downed member has dropped its victim, but still has to finish Rebirth.
|
||||
if (!_downed && !UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
if (_downed)
|
||||
{
|
||||
while (uint32 eventId = _events.ExecuteEvent())
|
||||
{
|
||||
if (eventId == EVENT_COUNCIL_REBIRTH)
|
||||
CompleteRebirth();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = _events.ExecuteEvent())
|
||||
{
|
||||
ExecuteCouncilEvent(eventId);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ForceFinish()
|
||||
{
|
||||
if (!me->IsAlive() || _finishing)
|
||||
return;
|
||||
|
||||
_finishing = true;
|
||||
_downed = false;
|
||||
me->SetControlled(false, UNIT_STATE_ROOT);
|
||||
me->KillSelf();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void ScheduleCouncilEvents() = 0;
|
||||
virtual void ExecuteCouncilEvent(uint32 eventId) = 0;
|
||||
|
||||
EventMap _events;
|
||||
|
||||
private:
|
||||
bool SiblingStanding(uint32 entry) const
|
||||
{
|
||||
Creature* sibling = me->FindNearestCreature(entry, CouncilSearchRange, true);
|
||||
if (!sibling)
|
||||
return false;
|
||||
|
||||
if (council_ai* ai = dynamic_cast<council_ai*>(sibling->AI()))
|
||||
return !ai->_downed;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AnySiblingStanding() const
|
||||
{
|
||||
return SiblingStanding(SiblingEntryA()) || SiblingStanding(SiblingEntryB());
|
||||
}
|
||||
|
||||
virtual uint32 SiblingEntryA() const = 0;
|
||||
virtual uint32 SiblingEntryB() const = 0;
|
||||
|
||||
void PullSiblings(Unit* who)
|
||||
{
|
||||
if (_linking)
|
||||
return;
|
||||
|
||||
_linking = true;
|
||||
for (uint32 entry : { SiblingEntryA(), SiblingEntryB() })
|
||||
{
|
||||
if (Creature* sibling = me->FindNearestCreature(entry, CouncilSearchRange, true))
|
||||
if (CreatureAI* ai = sibling->AI())
|
||||
if (!sibling->IsEngaged())
|
||||
ai->AttackStart(who);
|
||||
}
|
||||
_linking = false;
|
||||
}
|
||||
|
||||
template<typename Callback>
|
||||
void ForEachSibling(Callback&& callback)
|
||||
{
|
||||
for (uint32 entry : { SiblingEntryA(), SiblingEntryB() })
|
||||
{
|
||||
if (Creature* sibling = me->FindNearestCreature(entry, CouncilSearchRange, true))
|
||||
if (council_ai* ai = dynamic_cast<council_ai*>(sibling->AI()))
|
||||
callback(ai);
|
||||
}
|
||||
}
|
||||
|
||||
void CastRebirthFromSibling()
|
||||
{
|
||||
for (uint32 entry : { SiblingEntryA(), SiblingEntryB() })
|
||||
{
|
||||
Creature* sibling = me->FindNearestCreature(entry, CouncilSearchRange, true);
|
||||
if (!sibling)
|
||||
continue;
|
||||
|
||||
if (council_ai* ai = dynamic_cast<council_ai*>(sibling->AI()))
|
||||
if (ai->_downed)
|
||||
continue;
|
||||
|
||||
sibling->CastSpell(me, SPELL_COUNCIL_REBIRTH, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void CompleteRebirth()
|
||||
{
|
||||
if (!_downed)
|
||||
return;
|
||||
|
||||
if (!AnySiblingStanding())
|
||||
{
|
||||
ForceFinish();
|
||||
return;
|
||||
}
|
||||
|
||||
_downed = false;
|
||||
me->SetControlled(false, UNIT_STATE_ROOT);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->SetFullHealth();
|
||||
_events.Reset();
|
||||
ScheduleCouncilEvents();
|
||||
|
||||
if (Unit* victim = me->GetVictim())
|
||||
AttackStart(victim);
|
||||
else if (Player* player = me->SelectNearestPlayer(50.0f))
|
||||
AttackStart(player);
|
||||
}
|
||||
|
||||
bool _downed;
|
||||
bool _finishing;
|
||||
bool _linking;
|
||||
bool _evading;
|
||||
};
|
||||
|
||||
struct boss_urctos : public council_ai
|
||||
{
|
||||
boss_urctos(Creature* creature) : council_ai(creature) {}
|
||||
|
||||
uint32 SiblingEntryA() const override { return BOSS_AEWYN; }
|
||||
uint32 SiblingEntryB() const override { return BOSS_PIP; }
|
||||
|
||||
void ScheduleCouncilEvents() override
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_COUNCIL_SPELL_1, 6s);
|
||||
_events.ScheduleEvent(EVENT_COUNCIL_SPELL_2, 12s);
|
||||
_events.ScheduleEvent(EVENT_COUNCIL_SPELL_3, 22s);
|
||||
}
|
||||
|
||||
void ExecuteCouncilEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_COUNCIL_SPELL_1:
|
||||
DoCastVictim(SPELL_BARRELING_CHARGE);
|
||||
_events.Repeat(18s);
|
||||
break;
|
||||
case EVENT_COUNCIL_SPELL_2:
|
||||
DoCastVictim(SPELL_AGONIZING_CLAWS);
|
||||
_events.Repeat(14s);
|
||||
break;
|
||||
case EVENT_COUNCIL_SPELL_3:
|
||||
DoCastSelf(SPELL_BLIND_RAGE);
|
||||
_events.Repeat(32s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct boss_aerwynn : public council_ai
|
||||
{
|
||||
boss_aerwynn(Creature* creature) : council_ai(creature) {}
|
||||
|
||||
uint32 SiblingEntryA() const override { return BOSS_URCTOS; }
|
||||
uint32 SiblingEntryB() const override { return BOSS_PIP; }
|
||||
|
||||
void ScheduleCouncilEvents() override
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_COUNCIL_SPELL_1, 8s);
|
||||
_events.ScheduleEvent(EVENT_COUNCIL_SPELL_2, 14s);
|
||||
_events.ScheduleEvent(EVENT_COUNCIL_SPELL_3, 20s);
|
||||
}
|
||||
|
||||
void ExecuteCouncilEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_COUNCIL_SPELL_1:
|
||||
DoCastSelf(SPELL_RELENTLESS_BARRAGE);
|
||||
_events.Repeat(24s);
|
||||
break;
|
||||
case EVENT_COUNCIL_SPELL_2:
|
||||
DoCastSelf(SPELL_CONSTRICTING_THICKET);
|
||||
_events.Repeat(28s);
|
||||
break;
|
||||
case EVENT_COUNCIL_SPELL_3:
|
||||
DoCastVictim(SPELL_POISONOUS_JAVELIN);
|
||||
_events.Repeat(16s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct boss_pip : public council_ai
|
||||
{
|
||||
boss_pip(Creature* creature) : council_ai(creature) {}
|
||||
|
||||
uint32 SiblingEntryA() const override { return BOSS_URCTOS; }
|
||||
uint32 SiblingEntryB() const override { return BOSS_AEWYN; }
|
||||
|
||||
void ScheduleCouncilEvents() override
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_COUNCIL_SPELL_1, 10s);
|
||||
_events.ScheduleEvent(EVENT_COUNCIL_SPELL_2, 18s);
|
||||
_events.ScheduleEvent(EVENT_COUNCIL_SPELL_3, 28s);
|
||||
}
|
||||
|
||||
void ExecuteCouncilEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_COUNCIL_SPELL_1:
|
||||
DoCastSelf(SPELL_POLYMORPH_BOMB);
|
||||
_events.Repeat(26s);
|
||||
break;
|
||||
case EVENT_COUNCIL_SPELL_2:
|
||||
DoCastSelf(SPELL_SONG_OF_THE_DRAGON);
|
||||
_events.Repeat(34s);
|
||||
break;
|
||||
case EVENT_COUNCIL_SPELL_3:
|
||||
DoCastSelf(SPELL_CAPTIVATING_FINALE);
|
||||
_events.Repeat(40s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_council_of_dreams()
|
||||
{
|
||||
|
||||
RegisterAmirdrassilTheDreamsHopeCreatureAI(boss_urctos);
|
||||
RegisterAmirdrassilTheDreamsHopeCreatureAI(boss_aerwynn);
|
||||
RegisterAmirdrassilTheDreamsHopeCreatureAI(boss_pip);
|
||||
}
|
||||
|
||||
+160
-15
@@ -1,32 +1,177 @@
|
||||
/*
|
||||
* This file is part of Algeth Team
|
||||
*
|
||||
* Fyrakk the Blazing (204931) ? Amirdrassil.
|
||||
* Phase 1: 426368 Darkflame Cleave, 419506 Firestorm, 417455 Dream Rend.
|
||||
* Phase 2 (70%): 422524 Shadowflame Devastation, 422837 Apocalypse Roar, 417443 Fyr'alath's Mark.
|
||||
* Phase 3 (40%): 422518 Greater Firestorm, 425492 Infernal Maw, 428400 Exploding Core.
|
||||
*/
|
||||
|
||||
#include "AreaTrigger.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "CellImpl.h"
|
||||
#include "GameObject.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "SpellScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "amirdrassil.h"
|
||||
|
||||
enum amirdrassilSpells
|
||||
enum FyrakkSpells
|
||||
{
|
||||
|
||||
SPELL_DARKFLAME_CLEAVE = 426368,
|
||||
SPELL_FIRESTORM = 419506,
|
||||
SPELL_DREAM_REND = 417455,
|
||||
SPELL_SHADOWFLAME_DEVASTATION = 422524,
|
||||
SPELL_APOCALYPSE_ROAR = 422837,
|
||||
SPELL_FYRALATHS_MARK = 417443,
|
||||
SPELL_GREATER_FIRESTORM = 422518,
|
||||
SPELL_INFERNAL_MAW = 425492,
|
||||
SPELL_EXPLODING_CORE = 428400
|
||||
};
|
||||
|
||||
enum amirdrassilEvents
|
||||
enum FyrakkEvents
|
||||
{
|
||||
|
||||
EVENT_DARKFLAME_CLEAVE = 1,
|
||||
EVENT_FIRESTORM,
|
||||
EVENT_DREAM_REND,
|
||||
EVENT_SHADOWFLAME_DEVASTATION,
|
||||
EVENT_APOCALYPSE_ROAR,
|
||||
EVENT_FYRALATHS_MARK,
|
||||
EVENT_GREATER_FIRESTORM,
|
||||
EVENT_INFERNAL_MAW,
|
||||
EVENT_EXPLODING_CORE
|
||||
};
|
||||
|
||||
// 204931 - Fyrakk the Blazing
|
||||
struct boss_fyrakk_the_blazing : public BossAI
|
||||
{
|
||||
boss_fyrakk_the_blazing(Creature* creature) : BossAI(creature, DATA_FYRAKK_THE_BLAZING), _phase(1) {}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
_phase = 1;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
if (!instance || instance->GetBossState(DATA_FYRAKK_THE_BLAZING) != IN_PROGRESS)
|
||||
return;
|
||||
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||
SchedulePhaseOne();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
BossAI::EnterEvadeMode(why);
|
||||
if (instance && instance->GetBossState(DATA_FYRAKK_THE_BLAZING) != DONE)
|
||||
instance->SetBossState(DATA_FYRAKK_THE_BLAZING, FAIL);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (_phase == 1 && me->HealthBelowPct(70))
|
||||
{
|
||||
_phase = 2;
|
||||
events.Reset();
|
||||
SchedulePhaseTwo();
|
||||
}
|
||||
|
||||
if (_phase == 2 && me->HealthBelowPct(40))
|
||||
{
|
||||
_phase = 3;
|
||||
events.Reset();
|
||||
SchedulePhaseThree();
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_DARKFLAME_CLEAVE:
|
||||
DoCastVictim(SPELL_DARKFLAME_CLEAVE);
|
||||
events.Repeat(16s);
|
||||
break;
|
||||
case EVENT_FIRESTORM:
|
||||
DoCastSelf(SPELL_FIRESTORM);
|
||||
events.Repeat(28s);
|
||||
break;
|
||||
case EVENT_DREAM_REND:
|
||||
DoCastVictim(SPELL_DREAM_REND);
|
||||
events.Repeat(22s);
|
||||
break;
|
||||
case EVENT_SHADOWFLAME_DEVASTATION:
|
||||
DoCastSelf(SPELL_SHADOWFLAME_DEVASTATION);
|
||||
events.Repeat(30s);
|
||||
break;
|
||||
case EVENT_APOCALYPSE_ROAR:
|
||||
DoCastSelf(SPELL_APOCALYPSE_ROAR);
|
||||
events.Repeat(24s);
|
||||
break;
|
||||
case EVENT_FYRALATHS_MARK:
|
||||
DoCastVictim(SPELL_FYRALATHS_MARK);
|
||||
events.Repeat(20s);
|
||||
break;
|
||||
case EVENT_GREATER_FIRESTORM:
|
||||
DoCastSelf(SPELL_GREATER_FIRESTORM);
|
||||
events.Repeat(32s);
|
||||
break;
|
||||
case EVENT_INFERNAL_MAW:
|
||||
DoCastVictim(SPELL_INFERNAL_MAW);
|
||||
events.Repeat(18s);
|
||||
break;
|
||||
case EVENT_EXPLODING_CORE:
|
||||
DoCastSelf(SPELL_EXPLODING_CORE);
|
||||
events.Repeat(26s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void SchedulePhaseOne()
|
||||
{
|
||||
events.ScheduleEvent(EVENT_DARKFLAME_CLEAVE, 6s);
|
||||
events.ScheduleEvent(EVENT_DREAM_REND, 12s);
|
||||
events.ScheduleEvent(EVENT_FIRESTORM, 20s);
|
||||
}
|
||||
|
||||
void SchedulePhaseTwo()
|
||||
{
|
||||
events.ScheduleEvent(EVENT_FYRALATHS_MARK, 4s);
|
||||
events.ScheduleEvent(EVENT_APOCALYPSE_ROAR, 10s);
|
||||
events.ScheduleEvent(EVENT_SHADOWFLAME_DEVASTATION, 18s);
|
||||
}
|
||||
|
||||
void SchedulePhaseThree()
|
||||
{
|
||||
events.ScheduleEvent(EVENT_INFERNAL_MAW, 4s);
|
||||
events.ScheduleEvent(EVENT_EXPLODING_CORE, 10s);
|
||||
events.ScheduleEvent(EVENT_GREATER_FIRESTORM, 18s);
|
||||
}
|
||||
|
||||
uint8 _phase;
|
||||
};
|
||||
|
||||
void AddSC_boss_fyrakk_the_blazing()
|
||||
{
|
||||
|
||||
RegisterAmirdrassilTheDreamsHopeCreatureAI(boss_fyrakk_the_blazing);
|
||||
}
|
||||
|
||||
@@ -1,32 +1,113 @@
|
||||
/*
|
||||
* This file is part of Algeth Team
|
||||
*
|
||||
* Gnarlroot (209333) ? Amirdrassil.
|
||||
* Spell ids taken from the retail encounter (cast spells, not their damage twins):
|
||||
* 422026 Tortured Scream, 424352 Dreadfire Barrage, 421971 Controlled Burn,
|
||||
* 421898 Flaming Pestilence, 421013 Doom Cultivation.
|
||||
*/
|
||||
|
||||
#include "AreaTrigger.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "CellImpl.h"
|
||||
#include "GameObject.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "SpellScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "amirdrassil.h"
|
||||
|
||||
enum amirdrassilSpells
|
||||
enum GnarlrootSpells
|
||||
{
|
||||
|
||||
SPELL_TORTURED_SCREAM = 422026,
|
||||
SPELL_DREADFIRE_BARRAGE = 424352,
|
||||
SPELL_CONTROLLED_BURN = 421971,
|
||||
SPELL_FLAMING_PESTILENCE = 421898,
|
||||
SPELL_DOOM_CULTIVATION = 421013
|
||||
};
|
||||
|
||||
enum amirdrassilEvents
|
||||
enum GnarlrootEvents
|
||||
{
|
||||
|
||||
EVENT_TORTURED_SCREAM = 1,
|
||||
EVENT_DREADFIRE_BARRAGE,
|
||||
EVENT_CONTROLLED_BURN,
|
||||
EVENT_FLAMING_PESTILENCE,
|
||||
EVENT_DOOM_CULTIVATION
|
||||
};
|
||||
|
||||
// 209333 - Gnarlroot
|
||||
struct boss_gnarlroot : public BossAI
|
||||
{
|
||||
boss_gnarlroot(Creature* creature) : BossAI(creature, DATA_GNARLROOT) {}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
if (!instance || instance->GetBossState(DATA_GNARLROOT) != IN_PROGRESS)
|
||||
return;
|
||||
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||
events.ScheduleEvent(EVENT_TORTURED_SCREAM, 6s);
|
||||
events.ScheduleEvent(EVENT_DREADFIRE_BARRAGE, 12s);
|
||||
events.ScheduleEvent(EVENT_CONTROLLED_BURN, 18s);
|
||||
events.ScheduleEvent(EVENT_FLAMING_PESTILENCE, 24s);
|
||||
events.ScheduleEvent(EVENT_DOOM_CULTIVATION, 32s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
BossAI::EnterEvadeMode(why);
|
||||
if (instance && instance->GetBossState(DATA_GNARLROOT) != DONE)
|
||||
instance->SetBossState(DATA_GNARLROOT, FAIL);
|
||||
}
|
||||
|
||||
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_TORTURED_SCREAM:
|
||||
DoCastSelf(SPELL_TORTURED_SCREAM);
|
||||
events.Repeat(22s);
|
||||
break;
|
||||
case EVENT_DREADFIRE_BARRAGE:
|
||||
DoCastSelf(SPELL_DREADFIRE_BARRAGE);
|
||||
events.Repeat(28s);
|
||||
break;
|
||||
case EVENT_CONTROLLED_BURN:
|
||||
DoCastVictim(SPELL_CONTROLLED_BURN);
|
||||
events.Repeat(24s);
|
||||
break;
|
||||
case EVENT_FLAMING_PESTILENCE:
|
||||
DoCastSelf(SPELL_FLAMING_PESTILENCE);
|
||||
events.Repeat(30s);
|
||||
break;
|
||||
case EVENT_DOOM_CULTIVATION:
|
||||
DoCastSelf(SPELL_DOOM_CULTIVATION);
|
||||
events.Repeat(40s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_gnarlroot()
|
||||
{
|
||||
|
||||
RegisterAmirdrassilTheDreamsHopeCreatureAI(boss_gnarlroot);
|
||||
}
|
||||
|
||||
@@ -1,32 +1,113 @@
|
||||
/*
|
||||
* This file is part of Algeth Team
|
||||
*
|
||||
* Igira the Cruel (200926) ? Amirdrassil.
|
||||
* Spell ids taken from the retail encounter:
|
||||
* 414425 Blistering Spear, 416998 Twisting Blade, 415624 Heart Stopper,
|
||||
* 418533 Smashing Viscera, 422776 Marked for Torment.
|
||||
*/
|
||||
|
||||
#include "AreaTrigger.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "CellImpl.h"
|
||||
#include "GameObject.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "SpellScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "amirdrassil.h"
|
||||
|
||||
enum amirdrassilSpells
|
||||
enum IgiraSpells
|
||||
{
|
||||
|
||||
SPELL_BLISTERING_SPEAR = 414425,
|
||||
SPELL_TWISTING_BLADE = 416998,
|
||||
SPELL_HEART_STOPPER = 415624,
|
||||
SPELL_SMASHING_VISCERA = 418533,
|
||||
SPELL_MARKED_FOR_TORMENT = 422776
|
||||
};
|
||||
|
||||
enum amirdrassilEvents
|
||||
enum IgiraEvents
|
||||
{
|
||||
|
||||
EVENT_BLISTERING_SPEAR = 1,
|
||||
EVENT_TWISTING_BLADE,
|
||||
EVENT_HEART_STOPPER,
|
||||
EVENT_SMASHING_VISCERA,
|
||||
EVENT_MARKED_FOR_TORMENT
|
||||
};
|
||||
|
||||
// 200926 - Igira the Cruel
|
||||
struct boss_igira_the_cruel : public BossAI
|
||||
{
|
||||
boss_igira_the_cruel(Creature* creature) : BossAI(creature, DATA_IGIRA_THE_CRUEL) {}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
if (!instance || instance->GetBossState(DATA_IGIRA_THE_CRUEL) != IN_PROGRESS)
|
||||
return;
|
||||
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||
events.ScheduleEvent(EVENT_BLISTERING_SPEAR, 5s);
|
||||
events.ScheduleEvent(EVENT_TWISTING_BLADE, 11s);
|
||||
events.ScheduleEvent(EVENT_HEART_STOPPER, 16s);
|
||||
events.ScheduleEvent(EVENT_SMASHING_VISCERA, 22s);
|
||||
events.ScheduleEvent(EVENT_MARKED_FOR_TORMENT, 30s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
BossAI::EnterEvadeMode(why);
|
||||
if (instance && instance->GetBossState(DATA_IGIRA_THE_CRUEL) != DONE)
|
||||
instance->SetBossState(DATA_IGIRA_THE_CRUEL, FAIL);
|
||||
}
|
||||
|
||||
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_BLISTERING_SPEAR:
|
||||
DoCastVictim(SPELL_BLISTERING_SPEAR);
|
||||
events.Repeat(18s);
|
||||
break;
|
||||
case EVENT_TWISTING_BLADE:
|
||||
DoCastVictim(SPELL_TWISTING_BLADE);
|
||||
events.Repeat(21s);
|
||||
break;
|
||||
case EVENT_HEART_STOPPER:
|
||||
DoCastVictim(SPELL_HEART_STOPPER);
|
||||
events.Repeat(26s);
|
||||
break;
|
||||
case EVENT_SMASHING_VISCERA:
|
||||
DoCastVictim(SPELL_SMASHING_VISCERA);
|
||||
events.Repeat(32s);
|
||||
break;
|
||||
case EVENT_MARKED_FOR_TORMENT:
|
||||
DoCastVictim(SPELL_MARKED_FOR_TORMENT);
|
||||
events.Repeat(35s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_igira_the_cruel()
|
||||
{
|
||||
|
||||
RegisterAmirdrassilTheDreamsHopeCreatureAI(boss_igira_the_cruel);
|
||||
}
|
||||
|
||||
+120
-15
@@ -1,32 +1,137 @@
|
||||
/*
|
||||
* This file is part of Algeth Team
|
||||
*
|
||||
* Larodar, Keeper of the Flame (208445) ? Amirdrassil.
|
||||
* Spell ids taken from the retail encounter:
|
||||
* 418637 Furious Charge, 417634 Raging Inferno, 417610 Burning Ground,
|
||||
* 418654 Scorching Roots. At 40%: 421998 Avatar of Ash, 421316 Consuming Flame.
|
||||
*/
|
||||
|
||||
#include "AreaTrigger.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "CellImpl.h"
|
||||
#include "GameObject.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "SpellScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "amirdrassil.h"
|
||||
|
||||
enum amirdrassilSpells
|
||||
enum LarodarSpells
|
||||
{
|
||||
|
||||
SPELL_FURIOUS_CHARGE = 418637,
|
||||
SPELL_RAGING_INFERNO = 417634,
|
||||
SPELL_BURNING_GROUND = 417610,
|
||||
SPELL_SCORCHING_ROOTS = 418654,
|
||||
SPELL_AVATAR_OF_ASH = 421998,
|
||||
SPELL_CONSUMING_FLAME = 421316
|
||||
};
|
||||
|
||||
enum amirdrassilEvents
|
||||
enum LarodarEvents
|
||||
{
|
||||
|
||||
EVENT_FURIOUS_CHARGE = 1,
|
||||
EVENT_RAGING_INFERNO,
|
||||
EVENT_BURNING_GROUND,
|
||||
EVENT_SCORCHING_ROOTS,
|
||||
EVENT_CONSUMING_FLAME
|
||||
};
|
||||
|
||||
// 208445 - Larodar, Keeper of the Flame
|
||||
struct boss_larodar_keeper_of_the_flame : public BossAI
|
||||
{
|
||||
boss_larodar_keeper_of_the_flame(Creature* creature) : BossAI(creature, DATA_LARODAR_KEEPER_OF_THE_FLAME), _phase(1) {}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
_phase = 1;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
if (!instance || instance->GetBossState(DATA_LARODAR_KEEPER_OF_THE_FLAME) != IN_PROGRESS)
|
||||
return;
|
||||
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||
SchedulePhaseOne();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
BossAI::EnterEvadeMode(why);
|
||||
if (instance && instance->GetBossState(DATA_LARODAR_KEEPER_OF_THE_FLAME) != DONE)
|
||||
instance->SetBossState(DATA_LARODAR_KEEPER_OF_THE_FLAME, FAIL);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (_phase == 1 && me->HealthBelowPct(40))
|
||||
{
|
||||
_phase = 2;
|
||||
events.Reset();
|
||||
DoCastSelf(SPELL_AVATAR_OF_ASH);
|
||||
events.ScheduleEvent(EVENT_CONSUMING_FLAME, 8s);
|
||||
events.ScheduleEvent(EVENT_FURIOUS_CHARGE, 14s);
|
||||
events.ScheduleEvent(EVENT_SCORCHING_ROOTS, 20s);
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_FURIOUS_CHARGE:
|
||||
DoCastVictim(SPELL_FURIOUS_CHARGE);
|
||||
events.Repeat(22s);
|
||||
break;
|
||||
case EVENT_RAGING_INFERNO:
|
||||
DoCastSelf(SPELL_RAGING_INFERNO);
|
||||
events.Repeat(30s);
|
||||
break;
|
||||
case EVENT_BURNING_GROUND:
|
||||
DoCastVictim(SPELL_BURNING_GROUND);
|
||||
events.Repeat(18s);
|
||||
break;
|
||||
case EVENT_SCORCHING_ROOTS:
|
||||
DoCastSelf(SPELL_SCORCHING_ROOTS);
|
||||
events.Repeat(26s);
|
||||
break;
|
||||
case EVENT_CONSUMING_FLAME:
|
||||
DoCastVictim(SPELL_CONSUMING_FLAME);
|
||||
events.Repeat(16s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void SchedulePhaseOne()
|
||||
{
|
||||
events.ScheduleEvent(EVENT_FURIOUS_CHARGE, 6s);
|
||||
events.ScheduleEvent(EVENT_BURNING_GROUND, 12s);
|
||||
events.ScheduleEvent(EVENT_SCORCHING_ROOTS, 18s);
|
||||
events.ScheduleEvent(EVENT_RAGING_INFERNO, 26s);
|
||||
}
|
||||
|
||||
uint8 _phase;
|
||||
};
|
||||
|
||||
void AddSC_boss_larodar_keeper_of_the_flame()
|
||||
{
|
||||
|
||||
RegisterAmirdrassilTheDreamsHopeCreatureAI(boss_larodar_keeper_of_the_flame);
|
||||
}
|
||||
|
||||
+97
-16
@@ -1,32 +1,113 @@
|
||||
/*
|
||||
* This file is part of Algeth Team
|
||||
*
|
||||
* Nymue, Weaver of the Cycle (206172) ? Amirdrassil.
|
||||
* Spell ids taken from the retail encounter:
|
||||
* 420846 Continuum, 429785 Impending Loom, 427722 Weaver's Burden,
|
||||
* 425357 Surging Growth, 418423 Verdant Matrix.
|
||||
*/
|
||||
|
||||
#include "AreaTrigger.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "CellImpl.h"
|
||||
#include "GameObject.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "SpellScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "amirdrassil.h"
|
||||
|
||||
enum amirdrassilSpells
|
||||
enum NymueSpells
|
||||
{
|
||||
|
||||
SPELL_CONTINUUM = 420846,
|
||||
SPELL_IMPENDING_LOOM = 429785,
|
||||
SPELL_WEAVERS_BURDEN = 427722,
|
||||
SPELL_SURGING_GROWTH = 425357,
|
||||
SPELL_VERDANT_MATRIX = 418423
|
||||
};
|
||||
|
||||
enum amirdrassilEvents
|
||||
enum NymueEvents
|
||||
{
|
||||
|
||||
EVENT_CONTINUUM = 1,
|
||||
EVENT_IMPENDING_LOOM,
|
||||
EVENT_WEAVERS_BURDEN,
|
||||
EVENT_SURGING_GROWTH,
|
||||
EVENT_VERDANT_MATRIX
|
||||
};
|
||||
|
||||
|
||||
void AddSC_boss_nyume_weaver_of_the_cycle()
|
||||
// 206172 - Nymue, Weaver of the Cycle
|
||||
struct boss_nymue_weaver_of_the_cycle : public BossAI
|
||||
{
|
||||
boss_nymue_weaver_of_the_cycle(Creature* creature) : BossAI(creature, DATA_NYMUE_WEAVER_OF_THE_CYCLE) {}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
if (!instance || instance->GetBossState(DATA_NYMUE_WEAVER_OF_THE_CYCLE) != IN_PROGRESS)
|
||||
return;
|
||||
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||
events.ScheduleEvent(EVENT_WEAVERS_BURDEN, 6s);
|
||||
events.ScheduleEvent(EVENT_SURGING_GROWTH, 12s);
|
||||
events.ScheduleEvent(EVENT_VERDANT_MATRIX, 18s);
|
||||
events.ScheduleEvent(EVENT_CONTINUUM, 24s);
|
||||
events.ScheduleEvent(EVENT_IMPENDING_LOOM, 34s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
BossAI::EnterEvadeMode(why);
|
||||
if (instance && instance->GetBossState(DATA_NYMUE_WEAVER_OF_THE_CYCLE) != DONE)
|
||||
instance->SetBossState(DATA_NYMUE_WEAVER_OF_THE_CYCLE, FAIL);
|
||||
}
|
||||
|
||||
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_CONTINUUM:
|
||||
DoCastSelf(SPELL_CONTINUUM);
|
||||
events.Repeat(36s);
|
||||
break;
|
||||
case EVENT_IMPENDING_LOOM:
|
||||
DoCastSelf(SPELL_IMPENDING_LOOM);
|
||||
events.Repeat(42s);
|
||||
break;
|
||||
case EVENT_WEAVERS_BURDEN:
|
||||
DoCastVictim(SPELL_WEAVERS_BURDEN);
|
||||
events.Repeat(22s);
|
||||
break;
|
||||
case EVENT_SURGING_GROWTH:
|
||||
DoCastSelf(SPELL_SURGING_GROWTH);
|
||||
events.Repeat(28s);
|
||||
break;
|
||||
case EVENT_VERDANT_MATRIX:
|
||||
DoCastSelf(SPELL_VERDANT_MATRIX);
|
||||
events.Repeat(32s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_nymue_weaver_of_the_cycle()
|
||||
{
|
||||
RegisterAmirdrassilTheDreamsHopeCreatureAI(boss_nymue_weaver_of_the_cycle);
|
||||
}
|
||||
|
||||
@@ -1,32 +1,113 @@
|
||||
/*
|
||||
* This file is part of Algeth Team
|
||||
*
|
||||
* Smolderon (200927) ? Amirdrassil.
|
||||
* Spell ids taken from the retail encounter:
|
||||
* 421343 Brand of Damnation, 421455 Overheated, 422172 World in Flames,
|
||||
* 422691 Lava Geysers, 426018 Seeking Inferno.
|
||||
*/
|
||||
|
||||
#include "AreaTrigger.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "CellImpl.h"
|
||||
#include "GameObject.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "SpellScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "amirdrassil.h"
|
||||
|
||||
enum amirdrassilSpells
|
||||
enum SmolderonSpells
|
||||
{
|
||||
|
||||
SPELL_BRAND_OF_DAMNATION = 421343,
|
||||
SPELL_OVERHEATED = 421455,
|
||||
SPELL_WORLD_IN_FLAMES = 422172,
|
||||
SPELL_LAVA_GEYSERS = 422691,
|
||||
SPELL_SEEKING_INFERNO = 426018
|
||||
};
|
||||
|
||||
enum amirdrassilEvents
|
||||
enum SmolderonEvents
|
||||
{
|
||||
|
||||
EVENT_BRAND_OF_DAMNATION = 1,
|
||||
EVENT_OVERHEATED,
|
||||
EVENT_WORLD_IN_FLAMES,
|
||||
EVENT_LAVA_GEYSERS,
|
||||
EVENT_SEEKING_INFERNO
|
||||
};
|
||||
|
||||
// 200927 - Smolderon
|
||||
struct boss_smolderon : public BossAI
|
||||
{
|
||||
boss_smolderon(Creature* creature) : BossAI(creature, DATA_SMOLDERON) {}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
if (!instance || instance->GetBossState(DATA_SMOLDERON) != IN_PROGRESS)
|
||||
return;
|
||||
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||
events.ScheduleEvent(EVENT_BRAND_OF_DAMNATION, 6s);
|
||||
events.ScheduleEvent(EVENT_LAVA_GEYSERS, 12s);
|
||||
events.ScheduleEvent(EVENT_SEEKING_INFERNO, 18s);
|
||||
events.ScheduleEvent(EVENT_OVERHEATED, 26s);
|
||||
events.ScheduleEvent(EVENT_WORLD_IN_FLAMES, 36s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
BossAI::EnterEvadeMode(why);
|
||||
if (instance && instance->GetBossState(DATA_SMOLDERON) != DONE)
|
||||
instance->SetBossState(DATA_SMOLDERON, FAIL);
|
||||
}
|
||||
|
||||
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_BRAND_OF_DAMNATION:
|
||||
DoCastVictim(SPELL_BRAND_OF_DAMNATION);
|
||||
events.Repeat(24s);
|
||||
break;
|
||||
case EVENT_OVERHEATED:
|
||||
DoCastSelf(SPELL_OVERHEATED);
|
||||
events.Repeat(40s);
|
||||
break;
|
||||
case EVENT_WORLD_IN_FLAMES:
|
||||
DoCastSelf(SPELL_WORLD_IN_FLAMES);
|
||||
events.Repeat(48s);
|
||||
break;
|
||||
case EVENT_LAVA_GEYSERS:
|
||||
DoCastSelf(SPELL_LAVA_GEYSERS);
|
||||
events.Repeat(28s);
|
||||
break;
|
||||
case EVENT_SEEKING_INFERNO:
|
||||
DoCastVictim(SPELL_SEEKING_INFERNO);
|
||||
events.Repeat(22s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_smolderon()
|
||||
{
|
||||
|
||||
RegisterAmirdrassilTheDreamsHopeCreatureAI(boss_smolderon);
|
||||
}
|
||||
|
||||
+123
-15
@@ -1,32 +1,140 @@
|
||||
/*
|
||||
* This file is part of Algeth Team
|
||||
*
|
||||
* Tindral Sageswift, Seer of the Flame (209090) ? Amirdrassil.
|
||||
* Spell ids taken from the retail encounter:
|
||||
* 424495 Mass Entanglement, 421398 Fire Beam, 424140 Supernova,
|
||||
* 420236 Falling Star, 423266 Flaming Germination.
|
||||
* Later phase: 420240 Sunflame.
|
||||
*/
|
||||
|
||||
#include "AreaTrigger.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "CellImpl.h"
|
||||
#include "GameObject.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "SpellScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "amirdrassil.h"
|
||||
|
||||
enum amirdrassilSpells
|
||||
enum TindralSpells
|
||||
{
|
||||
|
||||
SPELL_MASS_ENTANGLEMENT = 424495,
|
||||
SPELL_FIRE_BEAM = 421398,
|
||||
SPELL_SUPERNOVA = 424140,
|
||||
SPELL_FALLING_STAR = 420236,
|
||||
SPELL_FLAMING_GERMINATION = 423266,
|
||||
SPELL_SUNFLAME = 420240
|
||||
};
|
||||
|
||||
enum amirdrassilEvents
|
||||
enum TindralEvents
|
||||
{
|
||||
|
||||
EVENT_MASS_ENTANGLEMENT = 1,
|
||||
EVENT_FIRE_BEAM,
|
||||
EVENT_SUPERNOVA,
|
||||
EVENT_FALLING_STAR,
|
||||
EVENT_FLAMING_GERMINATION,
|
||||
EVENT_SUNFLAME
|
||||
};
|
||||
|
||||
// 209090 - Tindral Sageswift, Seer of the Flame
|
||||
struct boss_tindral_sageswift_seer_of_the_flame : public BossAI
|
||||
{
|
||||
boss_tindral_sageswift_seer_of_the_flame(Creature* creature) : BossAI(creature, DATA_TINDRAL_SAGESWIFT_SEER_OF_THE_FLAME), _phase(1) {}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
_phase = 1;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
if (!instance || instance->GetBossState(DATA_TINDRAL_SAGESWIFT_SEER_OF_THE_FLAME) != IN_PROGRESS)
|
||||
return;
|
||||
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||
SchedulePhaseOne();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
BossAI::EnterEvadeMode(why);
|
||||
if (instance && instance->GetBossState(DATA_TINDRAL_SAGESWIFT_SEER_OF_THE_FLAME) != DONE)
|
||||
instance->SetBossState(DATA_TINDRAL_SAGESWIFT_SEER_OF_THE_FLAME, FAIL);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (_phase == 1 && me->HealthBelowPct(40))
|
||||
{
|
||||
_phase = 2;
|
||||
events.ScheduleEvent(EVENT_SUNFLAME, 4s);
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_MASS_ENTANGLEMENT:
|
||||
DoCastSelf(SPELL_MASS_ENTANGLEMENT);
|
||||
events.Repeat(28s);
|
||||
break;
|
||||
case EVENT_FIRE_BEAM:
|
||||
DoCastVictim(SPELL_FIRE_BEAM);
|
||||
events.Repeat(18s);
|
||||
break;
|
||||
case EVENT_SUPERNOVA:
|
||||
DoCastSelf(SPELL_SUPERNOVA);
|
||||
events.Repeat(36s);
|
||||
break;
|
||||
case EVENT_FALLING_STAR:
|
||||
DoCastSelf(SPELL_FALLING_STAR);
|
||||
events.Repeat(22s);
|
||||
break;
|
||||
case EVENT_FLAMING_GERMINATION:
|
||||
DoCastSelf(SPELL_FLAMING_GERMINATION);
|
||||
events.Repeat(32s);
|
||||
break;
|
||||
case EVENT_SUNFLAME:
|
||||
DoCastSelf(SPELL_SUNFLAME);
|
||||
events.Repeat(20s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void SchedulePhaseOne()
|
||||
{
|
||||
events.ScheduleEvent(EVENT_FIRE_BEAM, 6s);
|
||||
events.ScheduleEvent(EVENT_FALLING_STAR, 12s);
|
||||
events.ScheduleEvent(EVENT_MASS_ENTANGLEMENT, 18s);
|
||||
events.ScheduleEvent(EVENT_FLAMING_GERMINATION, 24s);
|
||||
events.ScheduleEvent(EVENT_SUPERNOVA, 34s);
|
||||
}
|
||||
|
||||
uint8 _phase;
|
||||
};
|
||||
|
||||
void AddSC_boss_tindral_sageswift_seer_of_the_flame()
|
||||
{
|
||||
|
||||
RegisterAmirdrassilTheDreamsHopeCreatureAI(boss_tindral_sageswift_seer_of_the_flame);
|
||||
}
|
||||
|
||||
@@ -1,32 +1,113 @@
|
||||
/*
|
||||
* This file is part of Algeth Team
|
||||
*
|
||||
* Volcoross (208478) ? Amirdrassil.
|
||||
* Spell ids taken from the retail encounter:
|
||||
* 423117 Cataclysm Jaws, 420933 Flood of the Firelands, 421616 Volcanic Disgorge,
|
||||
* 421672 Serpent's Fury, 420415 Scorchtail Crash.
|
||||
*/
|
||||
|
||||
#include "AreaTrigger.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "CellImpl.h"
|
||||
#include "GameObject.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "SpellScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "amirdrassil.h"
|
||||
|
||||
enum amirdrassilSpells
|
||||
enum VolcorossSpells
|
||||
{
|
||||
|
||||
SPELL_CATACLYSM_JAWS = 423117,
|
||||
SPELL_FLOOD_OF_THE_FIRELANDS = 420933,
|
||||
SPELL_VOLCANIC_DISGORGE = 421616,
|
||||
SPELL_SERPENTS_FURY = 421672,
|
||||
SPELL_SCORCHTAIL_CRASH = 420415
|
||||
};
|
||||
|
||||
enum amirdrassilEvents
|
||||
enum VolcorossEvents
|
||||
{
|
||||
|
||||
EVENT_CATACLYSM_JAWS = 1,
|
||||
EVENT_FLOOD_OF_THE_FIRELANDS,
|
||||
EVENT_VOLCANIC_DISGORGE,
|
||||
EVENT_SERPENTS_FURY,
|
||||
EVENT_SCORCHTAIL_CRASH
|
||||
};
|
||||
|
||||
// 208478 - Volcoross
|
||||
struct boss_volcoross : public BossAI
|
||||
{
|
||||
boss_volcoross(Creature* creature) : BossAI(creature, DATA_VOLCOROSS) {}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
if (!instance || instance->GetBossState(DATA_VOLCOROSS) != IN_PROGRESS)
|
||||
return;
|
||||
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||
events.ScheduleEvent(EVENT_CATACLYSM_JAWS, 6s);
|
||||
events.ScheduleEvent(EVENT_SCORCHTAIL_CRASH, 12s);
|
||||
events.ScheduleEvent(EVENT_VOLCANIC_DISGORGE, 18s);
|
||||
events.ScheduleEvent(EVENT_SERPENTS_FURY, 24s);
|
||||
events.ScheduleEvent(EVENT_FLOOD_OF_THE_FIRELANDS, 34s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
BossAI::EnterEvadeMode(why);
|
||||
if (instance && instance->GetBossState(DATA_VOLCOROSS) != DONE)
|
||||
instance->SetBossState(DATA_VOLCOROSS, FAIL);
|
||||
}
|
||||
|
||||
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_CATACLYSM_JAWS:
|
||||
DoCastVictim(SPELL_CATACLYSM_JAWS);
|
||||
events.Repeat(20s);
|
||||
break;
|
||||
case EVENT_FLOOD_OF_THE_FIRELANDS:
|
||||
DoCastSelf(SPELL_FLOOD_OF_THE_FIRELANDS);
|
||||
events.Repeat(45s);
|
||||
break;
|
||||
case EVENT_VOLCANIC_DISGORGE:
|
||||
DoCastSelf(SPELL_VOLCANIC_DISGORGE);
|
||||
events.Repeat(28s);
|
||||
break;
|
||||
case EVENT_SERPENTS_FURY:
|
||||
DoCastSelf(SPELL_SERPENTS_FURY);
|
||||
events.Repeat(32s);
|
||||
break;
|
||||
case EVENT_SCORCHTAIL_CRASH:
|
||||
DoCastVictim(SPELL_SCORCHTAIL_CRASH);
|
||||
events.Repeat(24s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_volcoross()
|
||||
{
|
||||
|
||||
RegisterAmirdrassilTheDreamsHopeCreatureAI(boss_volcoross);
|
||||
}
|
||||
|
||||
+2
-2
@@ -19,7 +19,6 @@ ObjectData const creatureData[] =
|
||||
{ BOSS_SMOLDERON, DATA_SMOLDERON },
|
||||
{ BOSS_TINDRAL_SAGESWIFT_SEER_OF_THE_FLAME, DATA_TINDRAL_SAGESWIFT_SEER_OF_THE_FLAME },
|
||||
{ BOSS_FYRAKK_THE_BLAZING, DATA_FYRAKK_THE_BLAZING },
|
||||
{ 0, 0 } // END
|
||||
};
|
||||
|
||||
DungeonEncounterData const encounters[] =
|
||||
@@ -48,7 +47,7 @@ enum AmirdrassilInstanceSpells
|
||||
class instance_amirdrassil_the_dreams_hope : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
instance_amirdrassil_the_dreams_hope() : InstanceMapScript(ATSCScriptName, 2549) { }
|
||||
instance_amirdrassil_the_dreams_hope() : InstanceMapScript(ATSCScriptName, 2549) {}
|
||||
|
||||
struct instance_amirdrassil_the_dreams_hope_InstanceMapScript : public InstanceScript
|
||||
{
|
||||
@@ -56,6 +55,7 @@ public:
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(EncounterCount);
|
||||
LoadObjectData(creatureData, {});
|
||||
LoadDungeonEncounterData(encounters);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,32 +1,91 @@
|
||||
/*
|
||||
* Thordekk
|
||||
*
|
||||
*
|
||||
*/
|
||||
* Sennarth, The Cold Breath (187967) ? Vault of the Incarnates.
|
||||
* The two spells already named in this file:
|
||||
* 372539 Apex of Ice, 372051 Breath of Ice.
|
||||
*/
|
||||
|
||||
#include "AreaTrigger.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "CellImpl.h"
|
||||
#include "GameObject.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "SpellScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "Vault_of_the_Incarnates.h"
|
||||
|
||||
enum SennarthSpells
|
||||
{
|
||||
SPELL_APEX_OF_ICE = 372539,
|
||||
SPELL_BREATH_OF_ICE = 372051,
|
||||
SPELL_APEX_OF_ICE = 372539,
|
||||
SPELL_BREATH_OF_ICE = 372051
|
||||
};
|
||||
|
||||
enum SennarthEvents
|
||||
{
|
||||
EVENT_APEX_OF_ICE = 1,
|
||||
EVENT_BREATH_OF_ICE
|
||||
};
|
||||
|
||||
// 187967 - Sennarth, The Cold Breath
|
||||
struct boss_sennarth : public BossAI
|
||||
{
|
||||
boss_sennarth(Creature* creature) : BossAI(creature, DATA_SENNARTH) {}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
if (!instance || instance->GetBossState(DATA_SENNARTH) != IN_PROGRESS)
|
||||
return;
|
||||
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||
events.ScheduleEvent(EVENT_BREATH_OF_ICE, 8s);
|
||||
events.ScheduleEvent(EVENT_APEX_OF_ICE, 16s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
BossAI::EnterEvadeMode(why);
|
||||
if (instance && instance->GetBossState(DATA_SENNARTH) != DONE)
|
||||
instance->SetBossState(DATA_SENNARTH, FAIL);
|
||||
}
|
||||
|
||||
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_APEX_OF_ICE:
|
||||
DoCastSelf(SPELL_APEX_OF_ICE);
|
||||
events.Repeat(28s);
|
||||
break;
|
||||
case EVENT_BREATH_OF_ICE:
|
||||
DoCastVictim(SPELL_BREATH_OF_ICE);
|
||||
events.Repeat(18s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//187967
|
||||
void AddSC_boss_Sennarth()
|
||||
{
|
||||
RegisterCreatureAI(boss_sennarth);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ enum VaultOfIncarnatesDataTypes
|
||||
DATA_DATHEA,
|
||||
DATA_OPALFANG,
|
||||
DATA_EMBER_FIREPATH,
|
||||
DATA_SENNARTH = 7,
|
||||
};
|
||||
|
||||
enum VaultOfIncarnatesCreatures
|
||||
|
||||
@@ -74,8 +74,17 @@ void AddSC_boss_treemouth();
|
||||
void AddSC_Boss_Gutshoot();
|
||||
void AddSC_BrackenhideHollow_trash();
|
||||
|
||||
//AmirdrassilTheDreamsHope
|
||||
// TODO
|
||||
// Amirdrassil, the Dream's Hope
|
||||
void AddSC_instance_amirdrassil_the_dreams_hope();
|
||||
void AddSC_boss_gnarlroot();
|
||||
void AddSC_boss_igira_the_cruel();
|
||||
void AddSC_boss_volcoross();
|
||||
void AddSC_boss_council_of_dreams();
|
||||
void AddSC_boss_larodar_keeper_of_the_flame();
|
||||
void AddSC_boss_nymue_weaver_of_the_cycle();
|
||||
void AddSC_boss_smolderon();
|
||||
void AddSC_boss_tindral_sageswift_seer_of_the_flame();
|
||||
void AddSC_boss_fyrakk_the_blazing();
|
||||
|
||||
// Dawn Of The Infinite
|
||||
void AddSC_instance_dawnoftheinfinite_df();
|
||||
@@ -186,8 +195,17 @@ void AddDragonIslesScripts()
|
||||
AddSC_Boss_Gutshoot();
|
||||
AddSC_BrackenhideHollow_trash();
|
||||
|
||||
//AmirdrassilTheDreamsHope
|
||||
// TODO
|
||||
// Amirdrassil, the Dream's Hope
|
||||
AddSC_instance_amirdrassil_the_dreams_hope();
|
||||
AddSC_boss_gnarlroot();
|
||||
AddSC_boss_igira_the_cruel();
|
||||
AddSC_boss_volcoross();
|
||||
AddSC_boss_council_of_dreams();
|
||||
AddSC_boss_larodar_keeper_of_the_flame();
|
||||
AddSC_boss_nymue_weaver_of_the_cycle();
|
||||
AddSC_boss_smolderon();
|
||||
AddSC_boss_tindral_sageswift_seer_of_the_flame();
|
||||
AddSC_boss_fyrakk_the_blazing();
|
||||
|
||||
// Dawn Of The Infinite
|
||||
AddSC_instance_dawnoftheinfinite_df();
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* Darkmaul Citadel ? Gor'groth (156814) and Ravnyr (156501).
|
||||
*
|
||||
* One encounter: Gor'groth fights until 40%, sacrifices himself and turns to
|
||||
* stone, then Ravnyr is the journal boss (encounter 2326).
|
||||
*
|
||||
* Spell ids confirmed on Wowhead:
|
||||
* 305913 Shadow Bolt (Exile's Reach ogre bolt)
|
||||
* 308527 Unstable Shadows (1.5s cast, up to 3 motes, explode after 5s, 8 yards)
|
||||
* 337047 Necrotic Breath (frontal cone, 40 Shadow damage)
|
||||
* 305567 Wing Buffet (necrotic blast, 60 yards, knockback)
|
||||
*/
|
||||
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "darkmaul_citadel.h"
|
||||
|
||||
enum GorgrothSpells
|
||||
{
|
||||
SPELL_GORGROTH_SHADOW_BOLT = 305913,
|
||||
SPELL_GORGROTH_UNSTABLE_SHADOWS = 308527,
|
||||
SPELL_RAVNYR_NECROTIC_BREATH = 337047,
|
||||
SPELL_RAVNYR_WING_BUFFET = 305567
|
||||
};
|
||||
|
||||
enum GorgrothEvents
|
||||
{
|
||||
EVENT_SHADOW_BOLT = 1,
|
||||
EVENT_UNSTABLE_SHADOWS,
|
||||
EVENT_NECROTIC_BREATH,
|
||||
EVENT_WING_BUFFET
|
||||
};
|
||||
|
||||
enum GorgrothTexts
|
||||
{
|
||||
SAY_GORGROTH_AGGRO = 0,
|
||||
SAY_GORGROTH_SACRIFICE = 1
|
||||
};
|
||||
|
||||
enum RavnyrTexts
|
||||
{
|
||||
SAY_RAVNYR_AGGRO = 0,
|
||||
SAY_RAVNYR_SLAY = 1
|
||||
};
|
||||
|
||||
static constexpr float SacrificeHealthPct = 40.0f;
|
||||
|
||||
// 156814 - Gor'groth
|
||||
struct boss_gorgroth : public ScriptedAI
|
||||
{
|
||||
boss_gorgroth(Creature* creature) : ScriptedAI(creature), _sacrificed(false), _evading(false) {}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_events.Reset();
|
||||
_sacrificed = false;
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->SetImmuneToPC(false);
|
||||
me->SetUninteractible(false);
|
||||
me->SetControlled(false, UNIT_STATE_ROOT);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
if (InstanceScript* instance = me->GetInstanceScript())
|
||||
{
|
||||
if (instance->GetBossState(DATA_RAVNYR) == DONE)
|
||||
{
|
||||
EnterEvadeMode(EvadeReason::Other);
|
||||
return;
|
||||
}
|
||||
|
||||
instance->SetBossState(DATA_RAVNYR, IN_PROGRESS);
|
||||
}
|
||||
|
||||
Talk(SAY_GORGROTH_AGGRO);
|
||||
_events.ScheduleEvent(EVENT_SHADOW_BOLT, 3s);
|
||||
_events.ScheduleEvent(EVENT_UNSTABLE_SHADOWS, 12s);
|
||||
|
||||
if (who && !who->IsPlayer())
|
||||
if (Player* player = me->SelectNearestPlayer(50.0f))
|
||||
me->SetInCombatWith(player);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
if (_sacrificed)
|
||||
{
|
||||
damage = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!me->HealthBelowPctDamaged(SacrificeHealthPct, damage))
|
||||
return;
|
||||
|
||||
_sacrificed = true;
|
||||
damage = 0;
|
||||
_events.Reset();
|
||||
me->InterruptNonMeleeSpells(true);
|
||||
|
||||
Unit* victim = me->GetVictim();
|
||||
if (!victim)
|
||||
victim = attacker;
|
||||
if (victim && !victim->IsPlayer())
|
||||
victim = me->SelectNearestPlayer(80.0f);
|
||||
|
||||
me->AttackStop();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetImmuneToPC(true);
|
||||
me->SetUninteractible(true);
|
||||
me->SetControlled(true, UNIT_STATE_ROOT);
|
||||
|
||||
uint64 threshold = me->CountPctFromMaxHealth(SacrificeHealthPct);
|
||||
if (me->GetHealth() > threshold)
|
||||
me->SetHealth(threshold);
|
||||
|
||||
// Drop combat without running home. EnterEvadeMode ignores this while Ravnyr is still up.
|
||||
me->CombatStop(true);
|
||||
Talk(SAY_GORGROTH_SACRIFICE);
|
||||
RaiseRavnyr(victim);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
// Sacrifice ends combat. Only a Ravnyr wipe (boss state FAIL) may reset Gor'groth.
|
||||
if (_sacrificed)
|
||||
{
|
||||
InstanceScript* instance = me->GetInstanceScript();
|
||||
if (!instance || instance->GetBossState(DATA_RAVNYR) != FAIL)
|
||||
return;
|
||||
}
|
||||
|
||||
if (_evading)
|
||||
return;
|
||||
|
||||
_evading = true;
|
||||
_sacrificed = false;
|
||||
me->SetControlled(false, UNIT_STATE_ROOT);
|
||||
me->SetImmuneToPC(false);
|
||||
me->SetUninteractible(false);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
|
||||
if (Creature* ravnyr = me->FindNearestCreature(BOSS_RAVNYR, 150.0f, true))
|
||||
if (ravnyr->IsInCombat())
|
||||
ravnyr->AI()->EnterEvadeMode(why);
|
||||
|
||||
if (InstanceScript* instance = me->GetInstanceScript())
|
||||
if (instance->GetBossState(DATA_RAVNYR) == IN_PROGRESS)
|
||||
instance->SetBossState(DATA_RAVNYR, FAIL);
|
||||
|
||||
ScriptedAI::EnterEvadeMode(why);
|
||||
_evading = false;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (_sacrificed || !UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = _events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SHADOW_BOLT:
|
||||
DoCastVictim(SPELL_GORGROTH_SHADOW_BOLT);
|
||||
_events.Repeat(6s);
|
||||
break;
|
||||
case EVENT_UNSTABLE_SHADOWS:
|
||||
DoCast(SPELL_GORGROTH_UNSTABLE_SHADOWS);
|
||||
_events.Repeat(22s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void RaiseRavnyr(Unit* victim)
|
||||
{
|
||||
Creature* ravnyr = me->FindNearestCreature(BOSS_RAVNYR, 150.0f, true);
|
||||
if (!ravnyr)
|
||||
{
|
||||
Position pos(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 6.0f, me->GetOrientation());
|
||||
ravnyr = me->SummonCreature(BOSS_RAVNYR, pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30s);
|
||||
}
|
||||
|
||||
if (!ravnyr)
|
||||
return;
|
||||
|
||||
ravnyr->SetImmuneToPC(false);
|
||||
ravnyr->SetUninteractible(false);
|
||||
ravnyr->SetReactState(REACT_AGGRESSIVE);
|
||||
|
||||
if (victim)
|
||||
ravnyr->AI()->AttackStart(victim);
|
||||
|
||||
// Summoning Ravnyr calls BossAI::Reset, which clears IN_PROGRESS. Put the encounter back.
|
||||
if (InstanceScript* instance = me->GetInstanceScript())
|
||||
if (instance->GetBossState(DATA_RAVNYR) == NOT_STARTED)
|
||||
instance->SetBossState(DATA_RAVNYR, IN_PROGRESS);
|
||||
}
|
||||
|
||||
EventMap _events;
|
||||
bool _sacrificed;
|
||||
bool _evading;
|
||||
};
|
||||
|
||||
// 156501 - Ravnyr
|
||||
struct boss_ravnyr : public BossAI
|
||||
{
|
||||
boss_ravnyr(Creature* creature) : BossAI(creature, DATA_RAVNYR), _evading(false) {}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetImmuneToPC(true);
|
||||
me->SetUninteractible(true);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||
Talk(SAY_RAVNYR_AGGRO);
|
||||
|
||||
events.ScheduleEvent(EVENT_NECROTIC_BREATH, 8s);
|
||||
events.ScheduleEvent(EVENT_WING_BUFFET, 18s);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->IsPlayer())
|
||||
Talk(SAY_RAVNYR_SLAY);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
_JustDied();
|
||||
|
||||
if (Creature* gorgroth = instance->GetCreature(DATA_GORGROTH))
|
||||
gorgroth->DespawnOrUnsummon(10s);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (_evading)
|
||||
return;
|
||||
|
||||
_evading = true;
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
|
||||
if (instance->GetBossState(DATA_RAVNYR) == IN_PROGRESS)
|
||||
instance->SetBossState(DATA_RAVNYR, FAIL);
|
||||
|
||||
if (Creature* gorgroth = instance->GetCreature(DATA_GORGROTH))
|
||||
if (gorgroth->IsAlive() && (gorgroth->IsInCombat() || gorgroth->IsImmuneToPC()))
|
||||
gorgroth->AI()->EnterEvadeMode(why);
|
||||
|
||||
CreatureAI::EnterEvadeMode(why);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetImmuneToPC(true);
|
||||
me->SetUninteractible(true);
|
||||
_evading = false;
|
||||
}
|
||||
|
||||
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_NECROTIC_BREATH:
|
||||
DoCastVictim(SPELL_RAVNYR_NECROTIC_BREATH);
|
||||
events.Repeat(16s);
|
||||
break;
|
||||
case EVENT_WING_BUFFET:
|
||||
DoCast(SPELL_RAVNYR_WING_BUFFET);
|
||||
events.Repeat(25s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool _evading;
|
||||
};
|
||||
|
||||
void AddSC_boss_gorgroth_ravnyr()
|
||||
{
|
||||
RegisterDarkmaulCitadelCreatureAI(boss_gorgroth);
|
||||
RegisterDarkmaulCitadelCreatureAI(boss_ravnyr);
|
||||
}
|
||||
@@ -579,6 +579,91 @@ enum ExileReachHelpers
|
||||
CONVERSATION_REACHED_COOKING_PIT = 11408,
|
||||
CONVERSATION_WAVED_TO_GORGROTH = 11512,
|
||||
|
||||
// Retail conversation ids (TrinityCore zone_exiles_reach). These replace scheduled creature_text Says.
|
||||
CONVERSATION_WARMING_UP_ACCEPT = 12818,
|
||||
CONVERSATION_WARMING_UP_COMPLETE = 12798,
|
||||
CONVERSATION_STAND_PREFIGHT = 14422,
|
||||
CONVERSATION_STAND_AGGRO = 14423,
|
||||
CONVERSATION_STAND_JUMP = 14424,
|
||||
CONVERSATION_MURLOC_MANIA_A = 12043,
|
||||
CONVERSATION_MURLOC_MANIA_H = 14432,
|
||||
CONVERSATION_BEACH_BJORN = 11685,
|
||||
CONVERSATION_BEACH_AUSTIN = 12128,
|
||||
CONVERSATION_BEACH_KEELA = 12127,
|
||||
CONVERSATION_ESCORT_SURVIVOR_A = 12044,
|
||||
CONVERSATION_ESCORT_SURVIVOR_H = 14437,
|
||||
CONVERSATION_ESCORT_REACHED_CAMP = 12058,
|
||||
CONVERSATION_COOKING_COMPLETE_A = 12863,
|
||||
CONVERSATION_COOKING_COMPLETE_H = 14611,
|
||||
CONVERSATION_NORTHBOUND_A = 12066,
|
||||
CONVERSATION_NORTHBOUND_H = 14499,
|
||||
CONVERSATION_BRIARPATCH_A = 12073,
|
||||
CONVERSATION_BRIARPATCH_H = 14513,
|
||||
CONVERSATION_GEOLORD_AGGRO = 13712,
|
||||
CONVERSATION_QUILBOAR_COMPLETE_A = 12076,
|
||||
CONVERSATION_QUILBOAR_COMPLETE_H = 14514,
|
||||
CONVERSATION_RESIZE_COPTER_A = 12078,
|
||||
CONVERSATION_RESIZE_COPTER_H = 14516,
|
||||
CONVERSATION_RIDE_TO_RUINS_A = 12083,
|
||||
CONVERSATION_RIDE_FROM_RUINS_A = 12084,
|
||||
CONVERSATION_RIDE_TO_RUINS_H = 14517,
|
||||
CONVERSATION_RIDE_FROM_RUINS_H = 14520,
|
||||
CONVERSATION_RESIZING_ACCEPT = 12086,
|
||||
CONVERSATION_RESIZING_REPORT = 12089,
|
||||
CONVERSATION_BOAR_ACCEPT = 12090,
|
||||
CONVERSATION_BOAR_HENRY = 15615,
|
||||
CONVERSATION_BOAR_EXIT = 12092,
|
||||
CONVERSATION_REDEATHER_ACCEPT = 14525,
|
||||
CONVERSATION_REDEATHER_EXPLODE = 14526,
|
||||
CONVERSATION_GRIMAXE_REDEATHER_SPAWN = 14527,
|
||||
CONVERSATION_GRIMAXE_REDEATHER_COMPLETE = 15618,
|
||||
CONVERSATION_ENHANCED_PREFIGHT = 13710,
|
||||
CONVERSATION_ENHANCED_USE_SPELLS_AT_RANGE = 13630,
|
||||
CONVERSATION_ENHANCED_READY = 14440,
|
||||
CONVERSATION_ENHANCED_READY_WARRIOR = 14441,
|
||||
CONVERSATION_ENHANCED_CHARGE_ZERO = 14444,
|
||||
CONVERSATION_ENHANCED_SLAM = 14447,
|
||||
CONVERSATION_ENHANCED_CHARGE_ONE = 14448,
|
||||
CONVERSATION_ENHANCED_CHARGE_FINAL = 14449,
|
||||
CONVERSATION_ENHANCED_HOLY_POWER_ONE = 14452,
|
||||
CONVERSATION_ENHANCED_CRUSADER_ONE = 14453,
|
||||
CONVERSATION_ENHANCED_CRUSADER_TWO = 14454,
|
||||
CONVERSATION_ENHANCED_SHIELD_ONE = 14455,
|
||||
CONVERSATION_ENHANCED_HOLY_POWER_TWO = 14456,
|
||||
CONVERSATION_ENHANCED_SHIELD_TWO = 14457,
|
||||
CONVERSATION_ENHANCED_CRUSADER_THREE = 14458,
|
||||
CONVERSATION_ENHANCED_HOLY_POWER_THREE = 14459,
|
||||
CONVERSATION_ENHANCED_SINISTER_ONE = 14486,
|
||||
CONVERSATION_ENHANCED_ROGUE_ATTACKS = 14487,
|
||||
CONVERSATION_ENHANCED_COMBO_THREE = 14488,
|
||||
CONVERSATION_ENHANCED_EVISCERATE_THREE = 14489,
|
||||
CONVERSATION_ENHANCED_SINISTER_TWO = 14490,
|
||||
CONVERSATION_ENHANCED_COMBO_FOUR = 14491,
|
||||
CONVERSATION_ENHANCED_EVISCERATE_FOUR = 14492,
|
||||
CONVERSATION_ENHANCED_SINISTER_THREE = 14493,
|
||||
CONVERSATION_ENHANCED_COMBO_FIVE = 14494,
|
||||
CONVERSATION_ENHANCED_EVISCERATE_FAIL = 14495,
|
||||
CONVERSATION_ENHANCED_SWP_CREDIT = 13892,
|
||||
CONVERSATION_ENHANCED_SMITE = 14460,
|
||||
CONVERSATION_ENHANCED_SWP_PRE = 14461,
|
||||
CONVERSATION_ENHANCED_SWP_SOON = 14462,
|
||||
CONVERSATION_ENHANCED_LB_FIRST = 13631,
|
||||
CONVERSATION_ENHANCED_PRIMAL_FIRST = 13632,
|
||||
CONVERSATION_ENHANCED_PRIMAL_CREDIT = 13633,
|
||||
CONVERSATION_ENHANCED_LB_RANGE = 14475,
|
||||
CONVERSATION_ENHANCED_FROSTBOLT = 13634,
|
||||
CONVERSATION_ENHANCED_FIRE_BLAST_CREDIT = 13635,
|
||||
CONVERSATION_ENHANCED_FROSTBOLT_CLOSE = 14476,
|
||||
CONVERSATION_ENHANCED_FIRE_BLAST_NO_CREDIT = 14477,
|
||||
CONVERSATION_ENHANCED_CORRUPTION_CREDIT = 13895,
|
||||
CONVERSATION_ENHANCED_SHADOW_BOLT_WL = 14465,
|
||||
CONVERSATION_ENHANCED_CORRUPTION_PRE = 14466,
|
||||
CONVERSATION_ENHANCED_CORRUPTION_SOON = 14467,
|
||||
CONVERSATION_ENHANCED_MOONFIRE_CREDIT = 13893,
|
||||
CONVERSATION_ENHANCED_WRATH = 14471,
|
||||
CONVERSATION_ENHANCED_MOONFIRE_PRE = 14472,
|
||||
CONVERSATION_ENHANCED_MOONFIRE_SOON = 14473,
|
||||
|
||||
QUEST_OBJECTIVE_RIGHT_BENEATH_THEIR_EYES_REACHED_DARKMAUL_CITADEL_ENTRANCE = 16996,
|
||||
QUEST_OBJECTIVE_RIGHT_BENEATH_THEIR_EYES_REACHED_COOKING_PIT = 17000,
|
||||
QUEST_OBJECTIVE_RIGHT_BENEATH_THEIR_EYES_DANCING_AT_COOKING_PIT_A = 80052,
|
||||
@@ -955,6 +1040,14 @@ private:
|
||||
bool _fly;
|
||||
};
|
||||
|
||||
inline void PlayExileConversation(Player* player, uint32 conversationId)
|
||||
{
|
||||
if (!player || !conversationId)
|
||||
return;
|
||||
|
||||
player->PlayConversation(conversationId);
|
||||
}
|
||||
|
||||
static void StartPrivateConversation(Player* player, uint32 conversationId, std::vector<Creature*> actors)
|
||||
{
|
||||
Conversation* conversation = Conversation::CreateConversation(conversationId, player, *player, player->GetGUID(), nullptr, false);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "Loot.h"
|
||||
#include "exiles_reach.h"
|
||||
#include <set>
|
||||
|
||||
class exiles_reach_abandoned_camp_playerscript : public PlayerScript
|
||||
{
|
||||
@@ -154,23 +155,14 @@ struct npc_exiles_reach_abandoned_camp_166854_156607 : public ScriptedAI
|
||||
{
|
||||
if (Creature* breka = player->GetSummonedCreatureByEntry(NPC_MURLOC_HIDEAWAY_BREKA))
|
||||
{
|
||||
breka->AI()->Talk(3, player);
|
||||
// Won'sa!
|
||||
|
||||
me->AddDelayedEvent(3000, [this, player]() // time_delay
|
||||
{
|
||||
me->AI()->Talk(2, player); // So... hungry...
|
||||
});
|
||||
|
||||
PlayExileConversation(player, CONVERSATION_ESCORT_REACHED_CAMP);
|
||||
breka->GetMotionMaster()->MovePoint(0, -249.05f, -2492.35f, 17.957f, true);
|
||||
metBrekaOrGarrick = true;
|
||||
}
|
||||
|
||||
if (Creature* garrick = player->GetSummonedCreatureByEntry(NPC_MURLOC_HIDEAWAY_GARRICK))
|
||||
{
|
||||
garrick->AI()->Talk(3, player);
|
||||
// Alaria!
|
||||
|
||||
PlayExileConversation(player, CONVERSATION_ESCORT_REACHED_CAMP);
|
||||
garrick->GetMotionMaster()->MovePoint(0, -249.05f, -2492.35f, 17.957f, true);
|
||||
metBrekaOrGarrick = true;
|
||||
}
|
||||
@@ -253,9 +245,9 @@ struct npc_exiles_reach_abandoned_camp_166906_156651 : public ScriptedAI
|
||||
{
|
||||
if (Creature* clone = player->SummonCreature(me->GetEntry(), me->GetPosition(), TEMPSUMMON_MANUAL_DESPAWN, 0s, 0U, 0U, player->GetGUID()))
|
||||
{
|
||||
clone->AI()->Talk(2, player);
|
||||
// Recruit. Quilboar pose a far greater threat than murlocs. You must be ready to face them in battle.
|
||||
// Recruit! Quilboar are far deadlier than murlocs. You need to be ready for the dangers ahead.
|
||||
PlayExileConversation(player, CONVERSATION_ENHANCED_PREFIGHT);
|
||||
|
||||
uint32 readyConversation = player->GetClass() == CLASS_WARRIOR ? CONVERSATION_ENHANCED_READY_WARRIOR : CONVERSATION_ENHANCED_READY;
|
||||
|
||||
player->GetScheduler().Schedule(2s, [clone](TaskContext /*context*/)
|
||||
{ clone->GetMotionMaster()->MovePoint(1, EnhancedCombatTacticFightingPositions[1], true); })
|
||||
@@ -265,11 +257,9 @@ struct npc_exiles_reach_abandoned_camp_166906_156651 : public ScriptedAI
|
||||
clone->GetMotionMaster()->MovePoint(2, EnhancedCombatTacticFightingPositions[2], true);
|
||||
else
|
||||
clone->GetMotionMaster()->MovePoint(3, EnhancedCombatTacticFightingPositions[3], true); })
|
||||
.Schedule(12s, [clone, player](TaskContext /*context*/)
|
||||
.Schedule(12s, [clone, player, readyConversation](TaskContext /*context*/)
|
||||
{
|
||||
clone->AI()->Talk(3, player);
|
||||
// Your next lesson begins now!
|
||||
// Alright, let's see what you know!
|
||||
PlayExileConversation(player, readyConversation);
|
||||
clone->SetFaction(14);
|
||||
clone->SetLevel(player->GetLevel());
|
||||
clone->SetTarget(player->GetGUID());
|
||||
@@ -280,13 +270,13 @@ struct npc_exiles_reach_abandoned_camp_166906_156651 : public ScriptedAI
|
||||
me->CastSpell(player, SPELL_UPDATE_PHASESHIFT, true);
|
||||
}
|
||||
|
||||
void SpellHit(WorldObject* caster, SpellInfo const* /*spell*/) override
|
||||
void SpellHit(WorldObject* caster, SpellInfo const* spell) override
|
||||
{
|
||||
// @TODO : make it class specific
|
||||
Player* player = caster->ToPlayer();
|
||||
if (!player)
|
||||
if (!player || !spell)
|
||||
return;
|
||||
|
||||
PlayEnhancedCombatConversation(player, spell->Id);
|
||||
hitCounter++;
|
||||
|
||||
if (hitCounter == 3)
|
||||
@@ -348,10 +338,115 @@ struct npc_exiles_reach_abandoned_camp_166906_156651 : public ScriptedAI
|
||||
}
|
||||
|
||||
private:
|
||||
void PlayEnhancedCombatConversation(Player* player, uint32 spellId)
|
||||
{
|
||||
if (player->GetQuestStatus(QUEST_ENHANCED_COMBAT_TACTICS) != QUEST_STATUS_INCOMPLETE &&
|
||||
player->GetQuestStatus(QUEST_H_ENHANCED_COMBAT_TACTICS) != QUEST_STATUS_INCOMPLETE)
|
||||
return;
|
||||
|
||||
uint32 conversationId = 0;
|
||||
switch (player->GetClass())
|
||||
{
|
||||
case CLASS_WARRIOR:
|
||||
if (spellId == 100)
|
||||
conversationId = _chargeCasts++ == 0 ? CONVERSATION_ENHANCED_CHARGE_ZERO : (_chargeCasts == 2 ? CONVERSATION_ENHANCED_CHARGE_ONE : CONVERSATION_ENHANCED_CHARGE_FINAL);
|
||||
else if (spellId == 1464)
|
||||
conversationId = CONVERSATION_ENHANCED_SLAM;
|
||||
break;
|
||||
case CLASS_PALADIN:
|
||||
if (spellId == 35395)
|
||||
{
|
||||
if (player->GetPower(POWER_HOLY_POWER) >= 3)
|
||||
conversationId = CONVERSATION_ENHANCED_HOLY_POWER_THREE;
|
||||
else if (_classCasts == 0)
|
||||
conversationId = CONVERSATION_ENHANCED_CRUSADER_ONE;
|
||||
else if (_classCasts == 1)
|
||||
conversationId = CONVERSATION_ENHANCED_CRUSADER_TWO;
|
||||
else
|
||||
conversationId = CONVERSATION_ENHANCED_CRUSADER_THREE;
|
||||
++_classCasts;
|
||||
}
|
||||
else if (spellId == 53600)
|
||||
conversationId = _shieldCasts++ == 0 ? CONVERSATION_ENHANCED_SHIELD_ONE : CONVERSATION_ENHANCED_SHIELD_TWO;
|
||||
break;
|
||||
case CLASS_ROGUE:
|
||||
if (spellId == 1752)
|
||||
{
|
||||
uint8 combo = static_cast<uint8>(player->GetPower(POWER_COMBO_POINTS));
|
||||
if (combo >= 5)
|
||||
conversationId = CONVERSATION_ENHANCED_COMBO_FIVE;
|
||||
else if (combo >= 4)
|
||||
conversationId = CONVERSATION_ENHANCED_COMBO_FOUR;
|
||||
else if (combo >= 3)
|
||||
conversationId = CONVERSATION_ENHANCED_COMBO_THREE;
|
||||
else if (_classCasts == 0)
|
||||
conversationId = CONVERSATION_ENHANCED_SINISTER_ONE;
|
||||
else if (_classCasts == 1)
|
||||
conversationId = CONVERSATION_ENHANCED_SINISTER_TWO;
|
||||
else
|
||||
conversationId = CONVERSATION_ENHANCED_SINISTER_THREE;
|
||||
++_classCasts;
|
||||
}
|
||||
else if (spellId == 196819)
|
||||
{
|
||||
uint8 combo = static_cast<uint8>(player->GetPower(POWER_COMBO_POINTS));
|
||||
if (combo < 3)
|
||||
conversationId = CONVERSATION_ENHANCED_EVISCERATE_FAIL;
|
||||
else if (combo < 4)
|
||||
conversationId = CONVERSATION_ENHANCED_EVISCERATE_THREE;
|
||||
else
|
||||
conversationId = CONVERSATION_ENHANCED_EVISCERATE_FOUR;
|
||||
}
|
||||
break;
|
||||
case CLASS_PRIEST:
|
||||
if (spellId == 585)
|
||||
conversationId = CONVERSATION_ENHANCED_SMITE;
|
||||
else if (spellId == 589)
|
||||
conversationId = _classCasts++ == 0 ? CONVERSATION_ENHANCED_SWP_PRE : CONVERSATION_ENHANCED_SWP_CREDIT;
|
||||
break;
|
||||
case CLASS_SHAMAN:
|
||||
if (spellId == 188196)
|
||||
conversationId = player->GetDistance(me) > 10.0f ? CONVERSATION_ENHANCED_LB_RANGE : CONVERSATION_ENHANCED_LB_FIRST;
|
||||
else if (spellId == 73899)
|
||||
conversationId = _classCasts++ == 0 ? CONVERSATION_ENHANCED_PRIMAL_FIRST : CONVERSATION_ENHANCED_PRIMAL_CREDIT;
|
||||
break;
|
||||
case CLASS_MAGE:
|
||||
if (spellId == 116)
|
||||
conversationId = player->GetDistance(me) < 8.0f ? CONVERSATION_ENHANCED_FROSTBOLT_CLOSE : CONVERSATION_ENHANCED_FROSTBOLT;
|
||||
else if (spellId == 319836)
|
||||
conversationId = _classCasts++ == 0 ? CONVERSATION_ENHANCED_FIRE_BLAST_NO_CREDIT : CONVERSATION_ENHANCED_FIRE_BLAST_CREDIT;
|
||||
break;
|
||||
case CLASS_WARLOCK:
|
||||
if (spellId == 686)
|
||||
conversationId = CONVERSATION_ENHANCED_SHADOW_BOLT_WL;
|
||||
else if (spellId == 172)
|
||||
conversationId = _classCasts++ == 0 ? CONVERSATION_ENHANCED_CORRUPTION_PRE : CONVERSATION_ENHANCED_CORRUPTION_CREDIT;
|
||||
break;
|
||||
case CLASS_DRUID:
|
||||
if (spellId == 5176)
|
||||
conversationId = CONVERSATION_ENHANCED_WRATH;
|
||||
else if (spellId == 164812 || spellId == 8921)
|
||||
conversationId = _classCasts++ == 0 ? CONVERSATION_ENHANCED_MOONFIRE_PRE : CONVERSATION_ENHANCED_MOONFIRE_CREDIT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!conversationId || _playedConversations.count(conversationId))
|
||||
return;
|
||||
|
||||
_playedConversations.insert(conversationId);
|
||||
PlayExileConversation(player, conversationId);
|
||||
}
|
||||
|
||||
float orientation = 0.f;
|
||||
uint32 timer = 1000;
|
||||
int8 hitCounter = 0;
|
||||
uint8 _chargeCasts = 0;
|
||||
uint8 _classCasts = 0;
|
||||
uint8 _shieldCasts = 0;
|
||||
bool trainingQuestDone = false;
|
||||
std::set<uint32> _playedConversations;
|
||||
};
|
||||
|
||||
// Won'sa, Alaria (abandoned camp) (eaten)
|
||||
@@ -365,17 +460,8 @@ struct npc_exiles_reach_abandoned_camp_175030_175031 : public ScriptedAI
|
||||
{
|
||||
if (TempSummon* tempBreka = player->SummonCreature(NPC_ABANDONED_CAMP_BREKA_WALKING, Position(-249.05f, -2492.35f, 17.957f, 0.466517f), TEMPSUMMON_TIMED_DESPAWN, 5min, 0U, 0U, player->GetGUID()))
|
||||
{
|
||||
tempBreka->AI()->Talk(0, player); // We'll head north to see what the others have found. Won'sa, rest and regain your strength before joining us.
|
||||
tempBreka->FollowTarget(player);
|
||||
tempBreka->SetSpeed(MOVE_RUN, player->GetSpeed(MOVE_RUN));
|
||||
player->GetScheduler().Schedule(Milliseconds(10000), [this, player](TaskContext /*context*/)
|
||||
{
|
||||
me->AI()->Talk(0, player); // I be seein' ya soon, den. Ya daughter be right ta count on ya.
|
||||
})
|
||||
.Schedule(Milliseconds(16000), [this, tempBreka, player](TaskContext /*context*/)
|
||||
{
|
||||
tempBreka->AI()->Talk(1, player); // The Horde never abandons its soldiers. I will not abandon her.
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -383,14 +469,8 @@ struct npc_exiles_reach_abandoned_camp_175030_175031 : public ScriptedAI
|
||||
{
|
||||
if (TempSummon* tempGarrick = player->SummonCreature(NPC_ABANDONED_CAMP_GARRICK_WALKING, Position(-249.05f, -2492.35f, 17.957f, 0.466517f), TEMPSUMMON_TIMED_DESPAWN, 5min, 0U, 0U, player->GetGUID()))
|
||||
{
|
||||
tempGarrick->AI()->Talk(4, player); // We'll head north and rendezvous with the others. Alaria, recover your stamina before pushing forward.
|
||||
tempGarrick->FollowTarget(player);
|
||||
tempGarrick->SetSpeed(MOVE_RUN, player->GetSpeed(MOVE_RUN));
|
||||
player->GetScheduler().Schedule(Milliseconds(10000), [tempGarrick, player](TaskContext /*context*/)
|
||||
{
|
||||
// I've never given up on any member of the Alliance. I'm not about to start by failing my son.
|
||||
tempGarrick->Say(178620, player);
|
||||
tempGarrick->PlayDirectSound(152746, player, 178620); });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Exile's Reach retail conversations.
|
||||
* Quest accepts and completes that used to be scheduled creature Says
|
||||
* play the same private conversation ids TrinityCore uses.
|
||||
*/
|
||||
|
||||
#include "exiles_reach.h"
|
||||
|
||||
class exiles_reach_conversation_playerscript : public PlayerScript
|
||||
{
|
||||
public:
|
||||
exiles_reach_conversation_playerscript() : PlayerScript("exiles_reach_conversation_playerscript") { }
|
||||
|
||||
void OnQuestStatusChange(Player* player, uint32 questId) override
|
||||
{
|
||||
if (player->GetMapId() != MAP_EXILES_REACH && player->GetMapId() != MAP_NPE)
|
||||
return;
|
||||
|
||||
uint32 conversationId = 0;
|
||||
switch (player->GetQuestStatus(questId))
|
||||
{
|
||||
case QUEST_STATUS_INCOMPLETE:
|
||||
conversationId = ConversationOnAccept(questId);
|
||||
break;
|
||||
case QUEST_STATUS_COMPLETE:
|
||||
conversationId = ConversationOnComplete(questId);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
PlayExileConversation(player, conversationId);
|
||||
}
|
||||
|
||||
private:
|
||||
static uint32 ConversationOnAccept(uint32 questId)
|
||||
{
|
||||
switch (questId)
|
||||
{
|
||||
case QUEST_WARMING_UP:
|
||||
case QUEST_H_WARMING_UP:
|
||||
return CONVERSATION_WARMING_UP_ACCEPT;
|
||||
case QUEST_MURLOC_MANIA:
|
||||
return CONVERSATION_MURLOC_MANIA_A;
|
||||
case QUEST_H_MURLOC_MANIA:
|
||||
return CONVERSATION_MURLOC_MANIA_H;
|
||||
case QUEST_NORTHBOUND:
|
||||
return CONVERSATION_NORTHBOUND_A;
|
||||
case QUEST_H_NORTHBOUND:
|
||||
return CONVERSATION_NORTHBOUND_H;
|
||||
case QUEST_RIDE_OF_THE_SCIENTIFICALLY_ENHANCED_BOAR:
|
||||
return CONVERSATION_BOAR_ACCEPT;
|
||||
case QUEST_H_THE_REDEATHER:
|
||||
return CONVERSATION_REDEATHER_ACCEPT;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32 ConversationOnComplete(uint32 questId)
|
||||
{
|
||||
switch (questId)
|
||||
{
|
||||
case QUEST_WARMING_UP:
|
||||
case QUEST_H_WARMING_UP:
|
||||
return CONVERSATION_WARMING_UP_COMPLETE;
|
||||
case QUEST_COOKING_MEAT:
|
||||
return CONVERSATION_COOKING_COMPLETE_A;
|
||||
case QUEST_H_COOKING_MEAT:
|
||||
return CONVERSATION_COOKING_COMPLETE_H;
|
||||
case QUEST_DOWN_WITH_THE_QUILBOAR:
|
||||
return CONVERSATION_QUILBOAR_COMPLETE_A;
|
||||
case QUEST_H_DOWN_WITH_THE_QUILBOAR:
|
||||
return CONVERSATION_QUILBOAR_COMPLETE_H;
|
||||
case QUEST_H_THE_REDEATHER:
|
||||
return CONVERSATION_GRIMAXE_REDEATHER_COMPLETE;
|
||||
case QUEST_RE_SIZING_THE_SITUATION:
|
||||
case QUEST_H_RE_SIZING_THE_SITUATION:
|
||||
return CONVERSATION_RESIZING_REPORT;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_exiles_reach_conversations()
|
||||
{
|
||||
new exiles_reach_conversation_playerscript();
|
||||
}
|
||||
@@ -164,7 +164,7 @@ struct npc_exiles_reach_darkmaul_plains_167019_149899 : public ScriptedAI
|
||||
scoutOmatic->SetObjectScale(0.2f);
|
||||
scoutOmatic->SetUninteractible(true);
|
||||
|
||||
tempSpringstock->AI()->Talk(2, player); // I brought along a miniaturized Scout-o-Matic 5000! Let's just unshrink it...
|
||||
PlayExileConversation(player, CONVERSATION_RESIZE_COPTER_A);
|
||||
|
||||
player->GetScheduler().Schedule(7s, [tempSpringstock, scoutOmatic, player](TaskContext /*context*/)
|
||||
{ tempSpringstock->CastSpell(scoutOmatic, SPELL_RE_SIZING); });
|
||||
@@ -181,7 +181,7 @@ struct npc_exiles_reach_darkmaul_plains_167019_149899 : public ScriptedAI
|
||||
choppyBooster->SetObjectScale(0.2f);
|
||||
choppyBooster->SetUninteractible(true);
|
||||
|
||||
tempFizzlepop->AI()->Talk(2, player); // I brought along a miniaturized Scout-o-Matic 5000! Let's just unshrink it...
|
||||
PlayExileConversation(player, CONVERSATION_RESIZE_COPTER_H);
|
||||
|
||||
player->GetScheduler().Schedule(7s, [tempFizzlepop, choppyBooster, player](TaskContext /*context*/)
|
||||
{ tempFizzlepop->CastSpell(choppyBooster, SPELL_RE_SIZING); });
|
||||
@@ -200,10 +200,7 @@ struct npc_exiles_reach_darkmaul_plains_167019_149899 : public ScriptedAI
|
||||
}
|
||||
|
||||
if (quest->GetQuestId() == QUEST_H_THE_REDEATHER)
|
||||
{
|
||||
me->AI()->Talk(4);
|
||||
player->SummonCreature(NPC_DARKMAUL_PLAINS_CHOPPYBOOSTER_SLAUGHTER, CopterPositions[0], TEMPSUMMON_MANUAL_DESPAWN, 0s, 0U, 0U, player->GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
@@ -297,9 +294,9 @@ struct npc_exiles_reach_darkmaul_plains_167905_156526 : public VehicleAI
|
||||
me->GetMotionMaster()->MovePoint(1, CopterPositions[0], true);
|
||||
|
||||
if (player->GetTeam() == ALLIANCE)
|
||||
player->PlayConversation(12078);
|
||||
player->PlayConversation(CONVERSATION_RIDE_FROM_RUINS_A);
|
||||
else
|
||||
player->PlayConversation(14520);
|
||||
player->PlayConversation(CONVERSATION_RIDE_FROM_RUINS_H);
|
||||
}
|
||||
|
||||
// We are at the start point again
|
||||
@@ -335,9 +332,9 @@ struct npc_exiles_reach_darkmaul_plains_167905_156526 : public VehicleAI
|
||||
me->GetMotionMaster()->MovePoint(1, CopterPositions[1], true);
|
||||
|
||||
if (player->GetTeam() == ALLIANCE)
|
||||
player->PlayConversation(12083);
|
||||
player->PlayConversation(CONVERSATION_RIDE_TO_RUINS_A);
|
||||
else
|
||||
player->PlayConversation(14517);
|
||||
player->PlayConversation(CONVERSATION_RIDE_TO_RUINS_H);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -381,7 +378,7 @@ struct npc_exiles_reach_darkmaul_plains_167915_156749 : public ScriptedAI
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
player->PlayConversation(12086);
|
||||
player->PlayConversation(CONVERSATION_RESIZING_ACCEPT);
|
||||
me->FollowTarget(player);
|
||||
}
|
||||
|
||||
@@ -602,8 +599,6 @@ public:
|
||||
if (!caster || !target)
|
||||
return;
|
||||
|
||||
Creature* creature = caster->ToCreature();
|
||||
|
||||
Creature* smallCopter = target->ToCreature();
|
||||
if (!smallCopter)
|
||||
return;
|
||||
@@ -612,18 +607,6 @@ public:
|
||||
|
||||
smallCopter->CastSpell(smallCopter, SPELL_GROW_1);
|
||||
smallCopter->PlayObjectSound(SOUND_COPTER_SIZING_1, smallCopter->GetGUID());
|
||||
|
||||
if (creature)
|
||||
{
|
||||
if (creature->GetEntry() == NPC_DARKMAUL_PLAINS_SPRINGSTOCK)
|
||||
{
|
||||
creature->AI()->Talk(3); // Whoops, too big! A slight adjustment, and...
|
||||
}
|
||||
if (creature->GetEntry() == NPC_DARKMAUL_PLAINS_FIZZLEPOP)
|
||||
{
|
||||
creature->AI()->Talk(1); // Okay, might have overdone it a bit. Hold on...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PeriodicTick(AuraEffect const* /*aurEff*/)
|
||||
@@ -693,30 +676,10 @@ public:
|
||||
tickCount++;
|
||||
}
|
||||
|
||||
void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
if (!caster)
|
||||
return;
|
||||
|
||||
if (Creature* creature = caster->ToCreature())
|
||||
{
|
||||
if (creature->GetEntry() == NPC_DARKMAUL_PLAINS_SPRINGSTOCK)
|
||||
{
|
||||
creature->AI()->Talk(4); // There! Just right. Give it a try!
|
||||
}
|
||||
if (creature->GetEntry() == NPC_DARKMAUL_PLAINS_FIZZLEPOP)
|
||||
{
|
||||
creature->AI()->Talk(2); // Perfect! It ain't pretty, but it gets the job done.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectApply += AuraEffectApplyFn(spell_re_sizing_313269_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_re_sizing_313269_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_re_sizing_313269_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -772,6 +735,9 @@ public:
|
||||
|
||||
if (player->GetQuestStatus(QUEST_RE_SIZING_THE_SITUATION) || player->GetQuestStatus(QUEST_H_RE_SIZING_THE_SITUATION))
|
||||
{
|
||||
if (selectedFailedSpell == SPELL_RESIZER_HIT_EXPLODE && QuestAccepted(player, QUEST_H_THE_REDEATHER))
|
||||
PlayExileConversation(player, CONVERSATION_REDEATHER_EXPLODE);
|
||||
|
||||
if (player->GetQuestObjectiveProgress(QUEST_RE_SIZING_THE_SITUATION, 0) < 2)
|
||||
{
|
||||
player->CastSpell(target, selectedFailedSpell, true);
|
||||
|
||||
@@ -164,9 +164,7 @@ struct npc_exiles_reach_shore_166782_156626 : public ScriptedAI
|
||||
{
|
||||
case QUEST_MURLOC_MANIA:
|
||||
case QUEST_H_MURLOC_MANIA:
|
||||
Talk(1);
|
||||
// Recover our supplies, but don't fight too many murlocs at once. They're dangerous in packs.
|
||||
// Murlocs are dangerous in large numbers.Take back our supplies, but avoid fighting too many of them at once.
|
||||
// Conversations 12043 / 14432 are played from the quest-status script.
|
||||
break;
|
||||
case QUEST_H_EMERGENCY_FIRST_AID:
|
||||
case QUEST_EMERGENCY_FIRST_AID:
|
||||
@@ -238,9 +236,7 @@ struct npc_exiles_reach_shore_166782_156626 : public ScriptedAI
|
||||
PhasingHandler::InheritPhaseShift(clone, player);
|
||||
|
||||
clone->FollowTarget(player);
|
||||
clone->AI()->Talk(2, player);
|
||||
// You three, search for more survivors. $n, you and I will push forward.
|
||||
// You three, scour the island for any sign of the expedition. $N, you and I will scout ahead.
|
||||
PlayExileConversation(player, player->IsInAlliance() ? CONVERSATION_ESCORT_SURVIVOR_A : CONVERSATION_ESCORT_SURVIVOR_H);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -319,8 +315,22 @@ struct npc_exiles_reach_shore_injured_buddie : public ScriptedAI
|
||||
}
|
||||
|
||||
me->SetEmoteState(EMOTE_STATE_STAND);
|
||||
player->KilledMonsterCredit(me->GetEntry());
|
||||
Talk(0, player); // various text e.g: My thanks. We'll find the expedition yet.
|
||||
player->KilledMonsterCredit(me->GetEntry());
|
||||
|
||||
uint32 beachConversation = 0;
|
||||
switch (me->GetEntry())
|
||||
{
|
||||
case 156609: beachConversation = CONVERSATION_BEACH_BJORN; break;
|
||||
case 156610: beachConversation = CONVERSATION_BEACH_AUSTIN; break;
|
||||
case 156612: beachConversation = CONVERSATION_BEACH_KEELA; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (beachConversation)
|
||||
PlayExileConversation(player, beachConversation);
|
||||
else
|
||||
Talk(0, player);
|
||||
|
||||
me->m_Events.AddEventAtOffset(new DelayedMoveEvent(player, me, pos, 0, false, false), 3s);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -29,27 +29,75 @@ class exiles_reach_north_sea_playerscript : public PlayerScript
|
||||
public:
|
||||
exiles_reach_north_sea_playerscript() : PlayerScript("exiles_reach_north_sea_playerscript") {}
|
||||
|
||||
|
||||
void GiveExileShipIntroQuest(Player* player)
|
||||
{
|
||||
uint32 const questId = player->IsInHorde() ? QUEST_H_WARMING_UP : QUEST_WARMING_UP;
|
||||
if (player->GetQuestStatus(questId) != QUEST_STATUS_NONE)
|
||||
return;
|
||||
|
||||
uint32 const laterQuests[] =
|
||||
{
|
||||
player->IsInHorde() ? QUEST_H_STAND_YOUR_GROUND : QUEST_STAND_YOUR_GROUND,
|
||||
player->IsInHorde() ? QUEST_H_BRACE_FOR_IMPACT : QUEST_BRACE_FOR_IMPACT,
|
||||
player->IsInHorde() ? QUEST_H_MURLOC_MANIA : QUEST_MURLOC_MANIA,
|
||||
player->IsInHorde() ? QUEST_H_AN_END_TO_BEGINNINGS : QUEST_AN_END_TO_BEGINNINGS,
|
||||
};
|
||||
|
||||
for (uint32 laterQuestId : laterQuests)
|
||||
if (player->GetQuestStatus(laterQuestId) != QUEST_STATUS_NONE)
|
||||
return;
|
||||
|
||||
Quest const* quest = sObjectMgr->GetQuestTemplate(questId);
|
||||
if (!quest || !player->CanTakeQuest(quest, false) || !player->CanAddQuest(quest, false))
|
||||
return;
|
||||
|
||||
player->AddQuestAndCheckCompletion(quest, nullptr);
|
||||
}
|
||||
|
||||
void CheckExilesReachPhaseShift(Player* player)
|
||||
{
|
||||
// A new character has no quest yet. Hand out Warming Up before the phase
|
||||
// update so the ship quest giver and the combat dummy stay visible.
|
||||
GiveExileShipIntroQuest(player);
|
||||
|
||||
if (player->GetMapId() == MAP_EXILES_REACH)
|
||||
{
|
||||
switch (player->GetAreaId())
|
||||
{
|
||||
case AREA_NORTH_SEA_H:
|
||||
{
|
||||
WowCommunity::PhaseShift(player, { PHASE_GENERAL_SHIP, PHASE_HORDE_SHIP_15514 }, player->GetQuestStatus(QUEST_H_BRACE_FOR_IMPACT) || player->GetQuestStatus(QUEST_H_STAND_YOUR_GROUND));
|
||||
// The general ship phase has to stay on. Gating it on Brace for Impact
|
||||
// or Stand Your Ground hides Thrall / Breka from a character who has
|
||||
// not taken a quest yet.
|
||||
WowCommunity::PhaseShift(player, { PHASE_GENERAL_SHIP }, true);
|
||||
if (player->IsInHorde())
|
||||
{
|
||||
WowCommunity::PhaseShift(player, { PHASE_ALLIANCE_SHIP_COLE, PHASE_ALLIANCE_SHIP_GARRICK_1, PHASE_ALLIANCE_SHIP_CREW_OUTSIDE }, true);
|
||||
WowCommunity::PhaseShift(player, { PHASE_HORDE_SHIP_THROG }, !QuestAccepted(player, QUEST_H_STAND_YOUR_GROUND));
|
||||
WowCommunity::PhaseShift(player, { PHASE_HORDE_SHIP_15287, PHASE_HORDE_SHIP_15516 }, player->GetQuestStatus(QUEST_H_BRACE_FOR_IMPACT));
|
||||
// PhaseShift no longer removes phases. Drop the Alliance ship
|
||||
// phases here so a Horde character does not keep Jaina's crew.
|
||||
uint32 const allianceShipPhases[] =
|
||||
{
|
||||
PHASE_ALLIANCE_SHIP_COLE,
|
||||
PHASE_ALLIANCE_SHIP_GARRICK_1,
|
||||
PHASE_ALLIANCE_SHIP_CREW_OUTSIDE,
|
||||
PHASE_ALLIANCE_SHIP_13619,
|
||||
PHASE_ALLIANCE_SHIP_14350,
|
||||
PHASE_ALLIANCE_SHIP_GARRICK_2,
|
||||
PHASE_ALLIANCE_SHIP_CREW_INSIDE,
|
||||
};
|
||||
|
||||
for (uint32 phaseId : allianceShipPhases)
|
||||
if (player->GetPhaseShift().HasPhase(phaseId))
|
||||
PhasingHandler::RemovePhase(player, phaseId, true);
|
||||
WowCommunity::PhaseShift(player, { PHASE_HORDE_SHIP_15514 }, !QuestRewarded(player, QUEST_H_WARMING_UP));
|
||||
WowCommunity::PhaseShift(player, { PHASE_HORDE_SHIP_THROG }, !QuestAccepted(player, QUEST_H_STAND_YOUR_GROUND) && !QuestCompleted(player, QUEST_H_BRACE_FOR_IMPACT));
|
||||
WowCommunity::PhaseShift(player, { PHASE_HORDE_SHIP_15287 }, QuestRewarded(player, QUEST_H_WARMING_UP) && !QuestCompleted(player, QUEST_H_BRACE_FOR_IMPACT));
|
||||
WowCommunity::PhaseShift(player, { PHASE_HORDE_SHIP_15516 }, QuestAcceptedOrCompleted(player, QUEST_H_BRACE_FOR_IMPACT));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AREA_NORTH_SEA_A:
|
||||
{
|
||||
WowCommunity::PhaseShift(player, { PHASE_GENERAL_SHIP }, true);
|
||||
WowCommunity::PhaseShift(player, { PHASE_GENERAL_SHIP }, true);
|
||||
if (player->IsInAlliance())
|
||||
{
|
||||
WowCommunity::PhaseShift(player, { PHASE_ALLIANCE_SHIP_COLE }, !QuestAccepted(player, QUEST_STAND_YOUR_GROUND) && !QuestCompleted(player, QUEST_BRACE_FOR_IMPACT));
|
||||
@@ -119,12 +167,8 @@ struct npc_exiles_reach_ship_166573_156280 : public ScriptedAI
|
||||
switch (quest->GetQuestId())
|
||||
{
|
||||
case QUEST_WARMING_UP:
|
||||
// I need everyone in top form if we're to complete this mission. Show me what you can do!
|
||||
Talk(1, player);
|
||||
break;
|
||||
case QUEST_H_WARMING_UP:
|
||||
// We need to be ready for anything. Show me your skill in combat.
|
||||
Talk(0, player);
|
||||
// Conversation 12818 is played from the quest-status script.
|
||||
break;
|
||||
case QUEST_RIDE_OF_THE_SCIENTIFICALLY_ENHANCED_BOAR:
|
||||
if (Creature* clone = player->SummonCreature(NPC_OGRE_RUINS_TORGOK_FIGHTER_A, FindSummonPosition(player, NPC_DARKMAUL_PLAINS_GARRICK), TEMPSUMMON_MANUAL_DESPAWN, 0s, 0U, 0U, player->GetGUID()))
|
||||
@@ -138,12 +182,8 @@ struct npc_exiles_reach_ship_166573_156280 : public ScriptedAI
|
||||
switch (quest->GetQuestId())
|
||||
{
|
||||
case QUEST_WARMING_UP:
|
||||
// @TODO: walk inside and spawn it inside too and make phaseshift for it
|
||||
Talk(3, player); // Private Cole will run you through the rest of the drills. I need to discuss this storm with the helmsman.
|
||||
break;
|
||||
case QUEST_H_WARMING_UP:
|
||||
// @TODO: walk inside and spawn it inside too and make phaseshift for it
|
||||
Talk(1, player); // Throg will spar with you for now. I must speak to the crew about the rain.
|
||||
// Completion conversation 12798 is played from the quest-status script.
|
||||
break;
|
||||
case QUEST_BRACE_FOR_IMPACT:
|
||||
player->TeleportTo(2175, -462.722f, -2620.544f, 0.472f, 0.760f);
|
||||
@@ -191,21 +231,8 @@ struct npc_exiles_reach_ship_training_dummy : public ScriptedAI
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
if (player->GetQuestStatus(QUEST_H_WARMING_UP))
|
||||
{
|
||||
if (Creature* breka = me->FindNearestCreature(NPC_SHIP_BREKA, 20.f, true))
|
||||
breka->AI()->Talk(3, player); // Fine work. Next, we... rain? Our shaman said the skies would be clear.
|
||||
|
||||
if (player->GetQuestStatus(QUEST_H_WARMING_UP) || player->GetQuestStatus(QUEST_WARMING_UP))
|
||||
player->CastSpell(player, SPELL_MEDIUM_FOG_AND_RAIN, true);
|
||||
}
|
||||
|
||||
if (player->GetQuestStatus(QUEST_WARMING_UP))
|
||||
{
|
||||
if (Creature* garrick = me->FindNearestCreature(NPC_SHIP_GARRICK, 20.f, true))
|
||||
garrick->AI()->Talk(2, player); // Good! Next... hm, that's odd. We weren't expecting rain...
|
||||
|
||||
player->CastSpell(player, SPELL_MEDIUM_FOG_AND_RAIN, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -231,24 +258,22 @@ struct npc_exiles_reach_ship_166583_160664 : public ScriptedAI
|
||||
if (Creature* clone = me->SummonPersonalClone(me->GetPosition(), TEMPSUMMON_MANUAL_DESPAWN, 0s, 0U, 0U, player))
|
||||
{
|
||||
clone->SetHealth(player->GetHealth());
|
||||
clone->AI()->Talk(0, player);
|
||||
// I'll take my position. Strike first, and strike hard!
|
||||
// Let's move into sparring positions. I'll let you have the first strike.
|
||||
PlayExileConversation(player, CONVERSATION_STAND_PREFIGHT);
|
||||
|
||||
player->GetScheduler().Schedule(Milliseconds(3000), [clone, player](TaskContext /*context*/)
|
||||
// Chained TaskScheduler::Schedule calls are both relative to now, so the
|
||||
// aggro step has to be nested. Jump first, then turn hostile.
|
||||
player->GetScheduler().Schedule(Milliseconds(3000), [clone, player](TaskContext context)
|
||||
{
|
||||
clone->CastSpell(player, SPELL_JUMP_BEHIND, true);
|
||||
clone->SetFaction(14);
|
||||
clone->SetReactState(REACT_AGGRESSIVE);
|
||||
clone->AI()->Talk(1, player);
|
||||
// Never run from your foe! Victory or death!
|
||||
// Never run from your opponent.Stand your ground and fight until the end!
|
||||
})
|
||||
.Schedule(Milliseconds(5000), [clone, player](TaskContext /*context*/)
|
||||
{
|
||||
if (clone->GetEntry() == 166583) // @TODO: add this text to cole too
|
||||
clone->AI()->Talk(3, player); // Always face your enemy!
|
||||
});
|
||||
PlayExileConversation(player, CONVERSATION_STAND_JUMP);
|
||||
|
||||
context.Schedule(Milliseconds(2000), [clone, player](TaskContext /*context*/)
|
||||
{
|
||||
clone->SetFaction(14);
|
||||
clone->SetReactState(REACT_AGGRESSIVE);
|
||||
PlayExileConversation(player, CONVERSATION_STAND_AGGRO);
|
||||
});
|
||||
});
|
||||
}
|
||||
break;
|
||||
case QUEST_BRACE_FOR_IMPACT:
|
||||
@@ -299,7 +324,7 @@ struct npc_exiles_reach_ship_166583_160664 : public ScriptedAI
|
||||
me->AI()->Talk(4, player);
|
||||
BeFriendly();
|
||||
// I concede! Your strength will see our mission through.
|
||||
me->DespawnOrUnsummon();
|
||||
me->DespawnOrUnsummon();
|
||||
});
|
||||
}
|
||||
else
|
||||
|
||||
@@ -354,6 +354,11 @@ struct npc_exiles_reach_ogre_ruins_167126_167128_156799 : public ScriptedAI
|
||||
{
|
||||
npc_exiles_reach_ogre_ruins_167126_167128_156799(Creature* creature) : ScriptedAI(creature) {}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_playedHenry = false;
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
Player* player = who->ToPlayer();
|
||||
@@ -363,8 +368,18 @@ struct npc_exiles_reach_ogre_ruins_167126_167128_156799 : public ScriptedAI
|
||||
if (player->GetQuestObjectiveProgress(QUEST_H_THE_REDEATHER, 2) == 8 && player->GetQuestObjectiveProgress(QUEST_H_THE_REDEATHER, 1) == 0 && !player->GetSummonedCreatureByEntry(NPC_OGRE_RUINS_TORGOK_FIGHTER_H))
|
||||
{
|
||||
player->SummonCreature(NPC_OGRE_RUINS_TORGOK_FIGHTER_H, FindSummonPosition(player, NPC_OGRE_RUINS_TORGOK_FIGHTER_H), TEMPSUMMON_MANUAL_DESPAWN, 0s, 0U, 0U, player->GetGUID());
|
||||
PlayExileConversation(player, CONVERSATION_GRIMAXE_REDEATHER_SPAWN);
|
||||
}
|
||||
|
||||
if (!_playedHenry && QuestAccepted(player, QUEST_RIDE_OF_THE_SCIENTIFICALLY_ENHANCED_BOAR) && player->IsInAlliance() && player->IsInDist(me, 15.0f))
|
||||
{
|
||||
_playedHenry = true;
|
||||
PlayExileConversation(player, CONVERSATION_BOAR_HENRY);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool _playedHenry = false;
|
||||
};
|
||||
|
||||
/* ## ACHIEVEMENT SCRIPTS > ## */
|
||||
|
||||
@@ -166,14 +166,9 @@ struct npc_exiles_reach_quilboar_briarpatch_166996_154327 : public ScriptedAI
|
||||
ObjectGuid mithdranGuid = tempMithdranOrAustin->GetGUID();
|
||||
ObjectGuid brekaGuid = tempBrekaOrGarrick->GetGUID();
|
||||
|
||||
tempBrekaOrGarrick->AI()->Talk(0, player);
|
||||
PlayExileConversation(player, player->IsInHorde() ? CONVERSATION_BRIARPATCH_H : CONVERSATION_BRIARPATCH_A);
|
||||
|
||||
player->GetScheduler()
|
||||
.Schedule(5s + 500ms, [mithdranGuid, player](TaskContext /*context*/)
|
||||
{
|
||||
if (Creature* mithdran = ObjectAccessor::GetCreature(*player, mithdranGuid))
|
||||
mithdran->AI()->Talk(0, player);
|
||||
})
|
||||
.Schedule(10s, [mithdranGuid, brekaGuid, player](TaskContext /*context*/)
|
||||
{
|
||||
Creature* mithdran = ObjectAccessor::GetCreature(*player, mithdranGuid);
|
||||
@@ -181,8 +176,6 @@ struct npc_exiles_reach_quilboar_briarpatch_166996_154327 : public ScriptedAI
|
||||
if (!mithdran || !breka)
|
||||
return;
|
||||
|
||||
breka->AI()->Talk(1, player);
|
||||
|
||||
mithdran->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
breka->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
|
||||
@@ -222,11 +215,10 @@ struct npc_exiles_reach_geolord_grekog_151091 : public ScriptedAI
|
||||
return;
|
||||
|
||||
me->SetEmoteState(EMOTE_ONESHOT_NONE);
|
||||
|
||||
Talk(0);
|
||||
PlayExileConversation(player, CONVERSATION_GEOLORD_AGGRO);
|
||||
}
|
||||
|
||||
void JustDied(Unit* attacker) override
|
||||
void JustDied(Unit* /*attacker*/) override
|
||||
{
|
||||
// No need for personal summon
|
||||
|
||||
@@ -238,12 +230,7 @@ struct npc_exiles_reach_geolord_grekog_151091 : public ScriptedAI
|
||||
if (creature->GetEntry() == NPC_QUILBOAR_BRIARPATCH_FIZZLEPOP || creature->GetEntry() == NPC_QUILBOAR_BRIARPATCH_SPRINGSTOCK)
|
||||
{
|
||||
creature->RemoveAura(SPELL_NECROTIC_RITUAL);
|
||||
creature->AI()->Talk(1, attacker->ToPlayer());
|
||||
|
||||
creature->GetMotionMaster()->MovePoint(0, 16.6666f, -2511.82f, 73.39143f, true);
|
||||
creature->AI()->Talk(1, attacker->ToPlayer());
|
||||
// And that's why I always bet on the Horde! Let's scram!
|
||||
// @TODO: Alliance text missing
|
||||
|
||||
creature->GetScheduler().Schedule(Milliseconds(3000), [creature, this](TaskContext /*context*/)
|
||||
{
|
||||
|
||||
@@ -26,6 +26,10 @@ void AddSC_exiles_reach_hruns_barrow();
|
||||
void AddSC_exiles_reach_harpy_roost();
|
||||
void AddSC_exiles_reach_darkmaul_bridge();
|
||||
void AddSC_exiles_reach_darkmaul_citadel();
|
||||
void AddSC_instance_darkmaul_citadel();
|
||||
void AddSC_boss_tunk();
|
||||
void AddSC_boss_gorgroth_ravnyr();
|
||||
void AddSC_exiles_reach_conversations();
|
||||
|
||||
void AddExilesReachScripts()
|
||||
{
|
||||
@@ -40,4 +44,8 @@ void AddExilesReachScripts()
|
||||
AddSC_exiles_reach_harpy_roost();
|
||||
AddSC_exiles_reach_darkmaul_bridge();
|
||||
AddSC_exiles_reach_darkmaul_citadel();
|
||||
AddSC_instance_darkmaul_citadel();
|
||||
AddSC_boss_tunk();
|
||||
AddSC_boss_gorgroth_ravnyr();
|
||||
AddSC_exiles_reach_conversations();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Creature.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellScript.h"
|
||||
#include "TemporarySummon.h"
|
||||
#include "the_stonevault.h"
|
||||
|
||||
enum SpeakerSpells
|
||||
{
|
||||
// Shared
|
||||
SPELL_SILENCED_SPEAKER = 439577,
|
||||
|
||||
// Speaker Dorlita
|
||||
SPELL_IGNEOUS_HAMMER = 428711,
|
||||
SPELL_LAVA_CANNON = 449167,
|
||||
SPELL_BLAZING_CRESCENDO = 428508,
|
||||
SPELL_MAGMA_WAVE = 463057,
|
||||
|
||||
// Speaker Brokk
|
||||
SPELL_MOLTEN_METAL = 430097,
|
||||
SPELL_EXHAUST_VENTS = 428819,
|
||||
SPELL_FLAMING_SCRAP = 429999,
|
||||
SPELL_SCRAP_SONG = 428202
|
||||
};
|
||||
|
||||
enum SpeakerEvents
|
||||
{
|
||||
// Speaker Dorlita
|
||||
EVENT_IGNEOUS_HAMMER = 1,
|
||||
EVENT_LAVA_CANNON,
|
||||
|
||||
// Speaker Brokk
|
||||
EVENT_MOLTEN_METAL,
|
||||
EVENT_EXHAUST_VENTS,
|
||||
EVENT_FLAMING_SCRAP,
|
||||
EVENT_SCRAP_SONG,
|
||||
EVENT_SUMMON_SCRAP_CUBE,
|
||||
EVENT_TRIGGER_CRESCENDO
|
||||
};
|
||||
|
||||
enum SpeakerTexts
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_DEATH = 1
|
||||
};
|
||||
|
||||
enum SpeakerMisc
|
||||
{
|
||||
FLAMING_SCRAP_TICKS = 12
|
||||
};
|
||||
|
||||
// 213216 - Speaker Dorlita
|
||||
struct boss_speaker_dorlita : public BossAI
|
||||
{
|
||||
boss_speaker_dorlita(Creature* creature) : BossAI(creature, DATA_MASTER_MACHINISTS) { }
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
if (Creature* brokk = instance->GetCreature(DATA_SPEAKER_BROKK))
|
||||
DoZoneInCombat(brokk);
|
||||
|
||||
events.ScheduleEvent(EVENT_IGNEOUS_HAMMER, 2s);
|
||||
events.ScheduleEvent(EVENT_LAVA_CANNON, 8s);
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action != ACTION_START_BLAZING_CRESCENDO)
|
||||
return;
|
||||
|
||||
if (Creature* cube = me->FindNearestCreature(NPC_SCRAP_CUBE, 100.0f, true))
|
||||
{
|
||||
DoCast(cube, SPELL_BLAZING_CRESCENDO);
|
||||
|
||||
if (IsHeroic() || IsMythic() || IsMythicPlus())
|
||||
me->CastSpell(cube->GetPosition(), SPELL_MAGMA_WAVE, true);
|
||||
}
|
||||
else
|
||||
DoCastSelf(SPELL_BLAZING_CRESCENDO);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
HandlePartnerDeath(killer);
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_IGNEOUS_HAMMER:
|
||||
DoCastVictim(SPELL_IGNEOUS_HAMMER);
|
||||
events.Repeat(12s);
|
||||
break;
|
||||
case EVENT_LAVA_CANNON:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 45.0f, true))
|
||||
DoCast(target, SPELL_LAVA_CANNON);
|
||||
events.Repeat(17s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void HandlePartnerDeath(Unit* killer)
|
||||
{
|
||||
Creature* partner = instance->GetCreature(DATA_SPEAKER_BROKK);
|
||||
if (partner && partner->IsAlive())
|
||||
{
|
||||
partner->CastSpell(partner, SPELL_SILENCED_SPEAKER, true);
|
||||
return;
|
||||
}
|
||||
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
};
|
||||
|
||||
// 213217 - Speaker Brokk
|
||||
struct boss_speaker_brokk : public BossAI
|
||||
{
|
||||
boss_speaker_brokk(Creature* creature) : BossAI(creature, DATA_MASTER_MACHINISTS), _flamingScrapTicks(0) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
_flamingScrapTicks = 0;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
if (Creature* dorlita = instance->GetCreature(DATA_SPEAKER_DORLITA))
|
||||
DoZoneInCombat(dorlita);
|
||||
|
||||
events.ScheduleEvent(EVENT_MOLTEN_METAL, 1s);
|
||||
events.ScheduleEvent(EVENT_EXHAUST_VENTS, 3s);
|
||||
events.ScheduleEvent(EVENT_SCRAP_SONG, 11s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
HandlePartnerDeath(killer);
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_MOLTEN_METAL:
|
||||
DoCastSelf(SPELL_MOLTEN_METAL);
|
||||
events.Repeat(12s);
|
||||
break;
|
||||
case EVENT_EXHAUST_VENTS:
|
||||
DoCastSelf(SPELL_EXHAUST_VENTS, true);
|
||||
_flamingScrapTicks = FLAMING_SCRAP_TICKS;
|
||||
events.ScheduleEvent(EVENT_FLAMING_SCRAP, 500ms);
|
||||
events.Repeat(30s);
|
||||
break;
|
||||
case EVENT_FLAMING_SCRAP:
|
||||
me->CastSpell(me->GetRandomNearPosition(14.0f), SPELL_FLAMING_SCRAP, true);
|
||||
if (--_flamingScrapTicks > 0)
|
||||
events.Repeat(500ms);
|
||||
break;
|
||||
case EVENT_SCRAP_SONG:
|
||||
DoCastSelf(SPELL_SCRAP_SONG);
|
||||
events.ScheduleEvent(EVENT_SUMMON_SCRAP_CUBE, 2500ms);
|
||||
events.Repeat(35s);
|
||||
break;
|
||||
case EVENT_SUMMON_SCRAP_CUBE:
|
||||
me->SummonCreature(NPC_SCRAP_CUBE, me->GetPosition(), TEMPSUMMON_TIMED_DESPAWN, 25s);
|
||||
events.ScheduleEvent(EVENT_TRIGGER_CRESCENDO, 6s);
|
||||
break;
|
||||
case EVENT_TRIGGER_CRESCENDO:
|
||||
if (Creature* dorlita = instance->GetCreature(DATA_SPEAKER_DORLITA))
|
||||
if (dorlita->IsAlive())
|
||||
dorlita->AI()->DoAction(ACTION_START_BLAZING_CRESCENDO);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void HandlePartnerDeath(Unit* killer)
|
||||
{
|
||||
Creature* partner = instance->GetCreature(DATA_SPEAKER_DORLITA);
|
||||
if (partner && partner->IsAlive())
|
||||
{
|
||||
partner->CastSpell(partner, SPELL_SILENCED_SPEAKER, true);
|
||||
return;
|
||||
}
|
||||
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
|
||||
uint8 _flamingScrapTicks;
|
||||
};
|
||||
|
||||
void AddSC_boss_speaker_dorlita()
|
||||
{
|
||||
RegisterTheStonevaultCreatureAI(boss_speaker_dorlita);
|
||||
RegisterTheStonevaultCreatureAI(boss_speaker_brokk);
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Creature.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellScript.h"
|
||||
#include "TemporarySummon.h"
|
||||
#include "the_stonevault.h"
|
||||
|
||||
enum EirichSpells
|
||||
{
|
||||
SPELL_VOID_RIFT = 427315,
|
||||
SPELL_VOID_CORRUPTION = 427461,
|
||||
SPELL_VOID_CORRUPTION_AURA = 427329,
|
||||
SPELL_UNBRIDLED_VOID = 427869,
|
||||
SPELL_ENTROPIC_RECKONING = 427852
|
||||
};
|
||||
|
||||
enum EirichEvents
|
||||
{
|
||||
EVENT_UNBRIDLED_VOID = 1,
|
||||
EVENT_VOID_CORRUPTION,
|
||||
EVENT_ENTROPIC_RECKONING,
|
||||
EVENT_OPEN_VOID_RIFT
|
||||
};
|
||||
|
||||
enum EirichTexts
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_DEATH = 1
|
||||
};
|
||||
|
||||
enum EirichMisc
|
||||
{
|
||||
VOID_CORRUPTION_RIFT_RANGE = 2
|
||||
};
|
||||
|
||||
// 213119 - Void Speaker Eirich
|
||||
struct boss_void_speaker_eirich : public BossAI
|
||||
{
|
||||
boss_void_speaker_eirich(Creature* creature) : BossAI(creature, DATA_VOID_SPEAKER_EIRICH) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
summons.DespawnAll();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
OpenVoidRift();
|
||||
OpenVoidRift();
|
||||
|
||||
events.ScheduleEvent(EVENT_UNBRIDLED_VOID, 2s);
|
||||
events.ScheduleEvent(EVENT_VOID_CORRUPTION, 8s);
|
||||
events.ScheduleEvent(EVENT_ENTROPIC_RECKONING, 13s);
|
||||
events.ScheduleEvent(EVENT_OPEN_VOID_RIFT, 30s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
summons.DespawnAll();
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_UNBRIDLED_VOID:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 55.0f, true))
|
||||
DoCast(target, SPELL_UNBRIDLED_VOID);
|
||||
events.Repeat(22s);
|
||||
break;
|
||||
case EVENT_VOID_CORRUPTION:
|
||||
{
|
||||
std::list<Unit*> targets;
|
||||
SelectTargetList(targets, IsMythicPlus() ? 4 : 2, SelectTargetMethod::Random, 0, 50.0f, true);
|
||||
for (Unit* target : targets)
|
||||
DoCast(target, SPELL_VOID_CORRUPTION);
|
||||
events.Repeat(29s);
|
||||
break;
|
||||
}
|
||||
case EVENT_ENTROPIC_RECKONING:
|
||||
{
|
||||
std::list<Unit*> targets;
|
||||
SelectTargetList(targets, 3, SelectTargetMethod::Random, 0, 55.0f, true);
|
||||
for (Unit* target : targets)
|
||||
DoCast(target, SPELL_ENTROPIC_RECKONING);
|
||||
events.Repeat(28s);
|
||||
break;
|
||||
}
|
||||
case EVENT_OPEN_VOID_RIFT:
|
||||
OpenVoidRift();
|
||||
events.Repeat(30s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void OpenVoidRift()
|
||||
{
|
||||
Position pos = me->GetRandomNearPosition(20.0f);
|
||||
me->SummonCreature(NPC_VOID_RIFT, pos, TEMPSUMMON_TIMED_DESPAWN, 90s);
|
||||
}
|
||||
};
|
||||
|
||||
// 213125 - Void Rift
|
||||
struct npc_void_rift : public ScriptedAI
|
||||
{
|
||||
npc_void_rift(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
DoCastSelf(SPELL_VOID_RIFT, true);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
}
|
||||
};
|
||||
|
||||
// 427329 - Void Corruption
|
||||
class spell_eirich_void_corruption : public AuraScript
|
||||
{
|
||||
void PeriodicTick(AuraEffect const* /*aurEff*/) const
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
|
||||
if (Creature* rift = target->FindNearestCreature(NPC_VOID_RIFT, VOID_CORRUPTION_RIFT_RANGE, true))
|
||||
{
|
||||
target->RemoveAurasDueToSpell(SPELL_VOID_CORRUPTION_AURA);
|
||||
return;
|
||||
}
|
||||
|
||||
if (AuraEffect* effect = GetAura()->GetEffect(EFFECT_0))
|
||||
effect->SetAmount(int32(effect->GetAmount() * 1.25f));
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_eirich_void_corruption::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_void_speaker_eirich()
|
||||
{
|
||||
RegisterTheStonevaultCreatureAI(boss_void_speaker_eirich);
|
||||
RegisterTheStonevaultCreatureAI(npc_void_rift);
|
||||
RegisterSpellScript(spell_eirich_void_corruption);
|
||||
}
|
||||
@@ -122,6 +122,22 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void OnPlayerEnter(Player* player) override
|
||||
{
|
||||
if (!player->GetGroup() || !player->GetGroup()->GetLeaderGUID())
|
||||
return;
|
||||
|
||||
player->GetGroup()->AddFollowerModeBots(player);
|
||||
}
|
||||
|
||||
void OnPlayerExit(Player* player)
|
||||
{
|
||||
if (!player->GetGroup())
|
||||
return;
|
||||
|
||||
player->GetGroup()->DespawnFollowerModeBots(player);
|
||||
}
|
||||
|
||||
private:
|
||||
uint8 _ednaIntroState;
|
||||
uint8 _ednaIntroNPCsKillCount;
|
||||
|
||||
@@ -46,7 +46,12 @@ enum TheStonevaultCreatureIds
|
||||
BOSS_SKARMORAX = 210156,
|
||||
BOSS_SPEAKER_DORLITA = 213216,
|
||||
BOSS_SPEAKER_BROKK = 213217,
|
||||
BOSS_VOID_SPEAKER_EIRICH = 213119
|
||||
BOSS_VOID_SPEAKER_EIRICH = 213119,
|
||||
|
||||
// Encounter Mechanics
|
||||
NPC_SCRAP_CUBE = 213694,
|
||||
NPC_VENT_STALKER = 214049,
|
||||
NPC_VOID_RIFT = 213125
|
||||
};
|
||||
|
||||
enum TheStonevaultGameObjectIds
|
||||
@@ -58,7 +63,8 @@ enum TheStonevaultGameObjectIds
|
||||
|
||||
enum TheStonevaultSharedActions
|
||||
{
|
||||
ACTION_START_EDNA_INTRO = 0
|
||||
ACTION_START_EDNA_INTRO = 0,
|
||||
ACTION_START_BLAZING_CRESCENDO = 1
|
||||
};
|
||||
|
||||
template <class AI, class T>
|
||||
|
||||
@@ -36,6 +36,8 @@ void AddSC_campaign_visions_of_a_shadowed_sun();
|
||||
void AddSC_instance_the_stonevault();
|
||||
void AddSC_boss_edna();
|
||||
void AddSC_boss_skarmorak();
|
||||
void AddSC_boss_speaker_dorlita();
|
||||
void AddSC_boss_void_speaker_eirich();
|
||||
|
||||
// Nerub'ar Palace
|
||||
void AddSC_instance_nerubar_palace();
|
||||
@@ -97,6 +99,8 @@ void AddKhazAlgarScripts()
|
||||
AddSC_instance_the_stonevault();
|
||||
AddSC_boss_edna();
|
||||
AddSC_boss_skarmorak();
|
||||
AddSC_boss_speaker_dorlita();
|
||||
AddSC_boss_void_speaker_eirich();
|
||||
|
||||
// Nerub'ar Palace
|
||||
AddSC_instance_nerubar_palace();
|
||||
|
||||
@@ -36,7 +36,7 @@ static constexpr DungeonEncounterData encounters[] =
|
||||
class instance_maisara_caverns : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
instance_maisara_caverns() : InstanceMapScript("instance_maisara_caverns", 16395) { }
|
||||
instance_maisara_caverns() : InstanceMapScript("instance_maisara_caverns", 2874) { }
|
||||
|
||||
struct instance_maisara_caverns_InstanceMapScript : public InstanceScript
|
||||
{
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MIDNIGHT_ZONE_AI_H_
|
||||
#define MIDNIGHT_ZONE_AI_H_
|
||||
|
||||
#include "Player.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptedGossip.h"
|
||||
|
||||
namespace Scripts::QuelThalas::MidnightZones
|
||||
{
|
||||
inline void CreditMidnightObjective(Player* player, Creature* creature)
|
||||
{
|
||||
player->TalkedToCreature(creature->GetEntry(), creature->GetGUID());
|
||||
player->KilledMonsterCredit(creature->GetEntry(), creature->GetGUID());
|
||||
}
|
||||
|
||||
inline bool GossipCreditMidnightObjective(Creature* me, Player* player)
|
||||
{
|
||||
if (me->IsQuestGiver())
|
||||
player->PrepareQuestMenu(me->GetGUID());
|
||||
|
||||
CreditMidnightObjective(player, me);
|
||||
SendGossipMenuFor(player, player->GetGossipTextId(me), me->GetGUID());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Talk-to / stay-awhile / speak-with objectives from Wowhead.
|
||||
struct npc_midnight_objective_talk : public ScriptedAI
|
||||
{
|
||||
npc_midnight_objective_talk(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
return GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
};
|
||||
|
||||
// Arrive / meet / reach / take-portal credits from Wowhead.
|
||||
struct npc_midnight_objective_proximity : public ScriptedAI
|
||||
{
|
||||
npc_midnight_objective_proximity(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
Player* player = who->ToPlayer();
|
||||
if (!player || !player->IsInDist(me, 15.0f))
|
||||
return;
|
||||
|
||||
CreditMidnightObjective(player, me);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "midnight_zone_ai.h"
|
||||
|
||||
void AddSC_midnight_zone_objectives()
|
||||
{
|
||||
using namespace Scripts::QuelThalas::MidnightZones;
|
||||
|
||||
RegisterCreatureAI(npc_midnight_objective_talk);
|
||||
RegisterCreatureAI(npc_midnight_objective_proximity);
|
||||
}
|
||||
@@ -20,6 +20,15 @@
|
||||
// Silvermoon
|
||||
void AddSC_silvermoon_city_midnight();
|
||||
|
||||
// Midnight zone campaigns
|
||||
void AddSC_midnight_zone_objectives();
|
||||
void AddSC_zone_isle_of_queldanas_midnight();
|
||||
void AddSC_zone_eversong_woods_midnight();
|
||||
void AddSC_zone_zulaman_midnight();
|
||||
void AddSC_zone_harandar();
|
||||
void AddSC_zone_voidstorm();
|
||||
void AddSC_zone_arator_journey();
|
||||
|
||||
// Harandar
|
||||
void AddSC_harandar_chapter_1_of_caves_and_cradles();
|
||||
|
||||
@@ -38,6 +47,15 @@ void AddQuelThalasScripts()
|
||||
// Silvermoon
|
||||
AddSC_silvermoon_city_midnight();
|
||||
|
||||
// Midnight zone campaigns
|
||||
AddSC_midnight_zone_objectives();
|
||||
AddSC_zone_isle_of_queldanas_midnight();
|
||||
AddSC_zone_eversong_woods_midnight();
|
||||
AddSC_zone_zulaman_midnight();
|
||||
AddSC_zone_harandar();
|
||||
AddSC_zone_voidstorm();
|
||||
AddSC_zone_arator_journey();
|
||||
|
||||
// Harandar
|
||||
AddSC_harandar_chapter_1_of_caves_and_cradles();
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "midnight_zone_ai.h"
|
||||
|
||||
namespace Scripts::QuelThalas::AratorsJourney
|
||||
{
|
||||
// 237565 / 240747 - Alonsus Faol (Wowhead: Arator / One Final Relic)
|
||||
struct npc_alonsus_faol_arator : public ScriptedAI
|
||||
{
|
||||
npc_alonsus_faol_arator(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
};
|
||||
|
||||
// 244644 / 240267 / 239827 / 254884 - Arator (Wowhead Path of Light / Gathering / Foothold)
|
||||
struct npc_arator_journey : public ScriptedAI
|
||||
{
|
||||
npc_arator_journey(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
};
|
||||
|
||||
// 240334 - Shandris Feathermoon (Wowhead: Children of the Stars)
|
||||
struct npc_shandris_children_of_the_stars : public ScriptedAI
|
||||
{
|
||||
npc_shandris_children_of_the_stars(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void AddSC_zone_arator_journey()
|
||||
{
|
||||
using namespace Scripts::QuelThalas::AratorsJourney;
|
||||
|
||||
RegisterCreatureAI(npc_alonsus_faol_arator);
|
||||
RegisterCreatureAI(npc_arator_journey);
|
||||
RegisterCreatureAI(npc_shandris_children_of_the_stars);
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "midnight_zone_ai.h"
|
||||
|
||||
namespace Scripts::QuelThalas::EversongWoodsMidnight
|
||||
{
|
||||
// 236716 - Arator (Wowhead: The Wayward Magister)
|
||||
struct npc_arator_wayward_magister : public ScriptedAI
|
||||
{
|
||||
npc_arator_wayward_magister(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
};
|
||||
|
||||
// 236087 - Magister Umbric (Wowhead: The Wayward Magister)
|
||||
struct npc_umbric_tranquillien : public ScriptedAI
|
||||
{
|
||||
npc_umbric_tranquillien(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
};
|
||||
|
||||
// 245004 - Lord Antenorian (Wowhead: The First to Know / Chance Meeting)
|
||||
struct npc_lord_antenorian_tranquillien : public ScriptedAI
|
||||
{
|
||||
npc_lord_antenorian_tranquillien(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
};
|
||||
|
||||
// 235787 / 245704 - Lor'themar (Wowhead: Diplomacy / Fractured)
|
||||
struct npc_lorthemar_sanctum_of_light : public ScriptedAI
|
||||
{
|
||||
npc_lorthemar_sanctum_of_light(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
};
|
||||
|
||||
// 241050 / 239685 - Contact Silvermoon (Wowhead: Silvermoon Must Know / Anything but Reprieve)
|
||||
struct npc_contact_silvermoon_midnight : public ScriptedAI
|
||||
{
|
||||
npc_contact_silvermoon_midnight(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void AddSC_zone_eversong_woods_midnight()
|
||||
{
|
||||
using namespace Scripts::QuelThalas::EversongWoodsMidnight;
|
||||
|
||||
RegisterCreatureAI(npc_arator_wayward_magister);
|
||||
RegisterCreatureAI(npc_umbric_tranquillien);
|
||||
RegisterCreatureAI(npc_lord_antenorian_tranquillien);
|
||||
RegisterCreatureAI(npc_lorthemar_sanctum_of_light);
|
||||
RegisterCreatureAI(npc_contact_silvermoon_midnight);
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Conversation.h"
|
||||
#include "Player.h"
|
||||
#include "QuestDef.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "midnight_zone_ai.h"
|
||||
|
||||
namespace Scripts::QuelThalas::HarandarZone
|
||||
{
|
||||
namespace Quests
|
||||
{
|
||||
static constexpr uint32 TheRootCause = 86899;
|
||||
static constexpr uint32 ToHarathir = 86900;
|
||||
static constexpr uint32 HarandarBreadcrumb = 89402;
|
||||
}
|
||||
|
||||
namespace Conversations
|
||||
{
|
||||
static constexpr uint32 TheRootCauseOpenPortal = 28444;
|
||||
static constexpr uint32 FollowOrweyna = 29720;
|
||||
static constexpr uint32 TalkToKupaal = 29598;
|
||||
}
|
||||
|
||||
// 236704 - Orweyna (Wowhead: Harandar / The Root Cause)
|
||||
struct npc_orweyna_fairbreeze_midnight : public ScriptedAI
|
||||
{
|
||||
npc_orweyna_fairbreeze_midnight(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
|
||||
void OnQuestAccept(Player* player, Quest const* quest) override
|
||||
{
|
||||
if (quest->GetQuestId() == Quests::TheRootCause || quest->GetQuestId() == Quests::HarandarBreadcrumb)
|
||||
Conversation::CreateConversation(Conversations::TheRootCauseOpenPortal, player, *player, player->GetGUID(), nullptr, false);
|
||||
}
|
||||
};
|
||||
|
||||
// 237209 - Follow Orweyna (Wowhead: To Har'athir)
|
||||
struct npc_follow_orweyna_harandar : public ScriptedAI
|
||||
{
|
||||
npc_follow_orweyna_harandar(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
if (player->GetQuestStatus(Quests::ToHarathir) == QUEST_STATUS_INCOMPLETE)
|
||||
Conversation::CreateConversation(Conversations::FollowOrweyna, player, *player, player->GetGUID(), nullptr, false);
|
||||
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
};
|
||||
|
||||
// 237866 - Talk to Ku'paal (Wowhead: To Har'athir)
|
||||
struct npc_kupaal_harandar : public ScriptedAI
|
||||
{
|
||||
npc_kupaal_harandar(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
if (player->GetQuestStatus(Quests::ToHarathir) == QUEST_STATUS_INCOMPLETE)
|
||||
Conversation::CreateConversation(Conversations::TalkToKupaal, player, *player, player->GetGUID(), nullptr, false);
|
||||
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
};
|
||||
|
||||
// 237345 - Talk to Halduron (Wowhead: The Council Assembles)
|
||||
struct npc_halduron_harandar_council : public ScriptedAI
|
||||
{
|
||||
npc_halduron_harandar_council(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void AddSC_zone_harandar()
|
||||
{
|
||||
using namespace Scripts::QuelThalas::HarandarZone;
|
||||
|
||||
RegisterCreatureAI(npc_orweyna_fairbreeze_midnight);
|
||||
RegisterCreatureAI(npc_follow_orweyna_harandar);
|
||||
RegisterCreatureAI(npc_kupaal_harandar);
|
||||
RegisterCreatureAI(npc_halduron_harandar_council);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Player.h"
|
||||
#include "QuestDef.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "midnight_zone_ai.h"
|
||||
|
||||
namespace Scripts::QuelThalas::IsleOfQuelDanasMidnight
|
||||
{
|
||||
namespace Quests
|
||||
{
|
||||
static constexpr uint32 LightLastStand = 86852;
|
||||
}
|
||||
|
||||
// 241677 - Image of Lady Liadrin (Wowhead: Midnight / A Voice from the Light)
|
||||
struct npc_image_of_lady_liadrin_midnight : public ScriptedAI
|
||||
{
|
||||
npc_image_of_lady_liadrin_midnight(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
};
|
||||
|
||||
// 241575 - Speak with Liadrin to begin the ritual (Wowhead: Light's Last Stand)
|
||||
struct npc_liadrin_lights_last_stand : public ScriptedAI
|
||||
{
|
||||
npc_liadrin_lights_last_stand(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
if (player->GetQuestStatus(Quests::LightLastStand) == QUEST_STATUS_INCOMPLETE)
|
||||
Scripts::QuelThalas::MidnightZones::CreditMidnightObjective(player, me);
|
||||
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void AddSC_zone_isle_of_queldanas_midnight()
|
||||
{
|
||||
using namespace Scripts::QuelThalas::IsleOfQuelDanasMidnight;
|
||||
|
||||
RegisterCreatureAI(npc_image_of_lady_liadrin_midnight);
|
||||
RegisterCreatureAI(npc_liadrin_lights_last_stand);
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "midnight_zone_ai.h"
|
||||
|
||||
namespace Scripts::QuelThalas::Voidstorm
|
||||
{
|
||||
// 235386 / 235405 - Magister Umbric (Wowhead: Voidstorm / Homecoming)
|
||||
struct npc_umbric_voidstorm : public ScriptedAI
|
||||
{
|
||||
npc_umbric_voidstorm(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
};
|
||||
|
||||
// 235606 / 260236 - Lothraxion / Decimus (Wowhead: Reliable Enemies)
|
||||
struct npc_lothraxion_voidstorm : public ScriptedAI
|
||||
{
|
||||
npc_lothraxion_voidstorm(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
};
|
||||
|
||||
// 247414 - Lady Liadrin (Wowhead: Feeding the Flame)
|
||||
struct npc_liadrin_feeding_the_flame : public ScriptedAI
|
||||
{
|
||||
npc_liadrin_feeding_the_flame(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
};
|
||||
|
||||
// 242722 - Speak to Umbric (Wowhead: Clarity of Purpose)
|
||||
struct npc_umbric_clarity_of_purpose : public ScriptedAI
|
||||
{
|
||||
npc_umbric_clarity_of_purpose(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void AddSC_zone_voidstorm()
|
||||
{
|
||||
using namespace Scripts::QuelThalas::Voidstorm;
|
||||
|
||||
RegisterCreatureAI(npc_umbric_voidstorm);
|
||||
RegisterCreatureAI(npc_lothraxion_voidstorm);
|
||||
RegisterCreatureAI(npc_liadrin_feeding_the_flame);
|
||||
RegisterCreatureAI(npc_umbric_clarity_of_purpose);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "midnight_zone_ai.h"
|
||||
|
||||
namespace Scripts::QuelThalas::ZulAmanMidnight
|
||||
{
|
||||
// 236436 - Lady Liadrin (Wowhead: The Gates of Zul'Aman)
|
||||
struct npc_liadrin_gates_of_zulaman : public ScriptedAI
|
||||
{
|
||||
npc_liadrin_gates_of_zulaman(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
};
|
||||
|
||||
// 236126 / 240186 / 240934 - Zul'jarra (Wowhead Path / Hash'ey Away)
|
||||
struct npc_zuljarra_midnight : public ScriptedAI
|
||||
{
|
||||
npc_zuljarra_midnight(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
};
|
||||
|
||||
// 249211 - Zul'jan (Wowhead: The Line Must Be Drawn Here)
|
||||
struct npc_zuljan_midnight : public ScriptedAI
|
||||
{
|
||||
npc_zuljan_midnight(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void AddSC_zone_zulaman_midnight()
|
||||
{
|
||||
using namespace Scripts::QuelThalas::ZulAmanMidnight;
|
||||
|
||||
RegisterCreatureAI(npc_liadrin_gates_of_zulaman);
|
||||
RegisterCreatureAI(npc_zuljarra_midnight);
|
||||
RegisterCreatureAI(npc_zuljan_midnight);
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
enum Data
|
||||
{
|
||||
DATA_HAKKAR_THE_SOULFLAYER = 1,
|
||||
DATA_HAKKAR_THE_SOULFLAYER = 0,
|
||||
DATA_THE_MANASTORMS,
|
||||
DATA_DEALER_XYEXA,
|
||||
DATA_MUEHZALA
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "Player.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "de_other_side.h"
|
||||
|
||||
class instance_de_other_side : public InstanceMapScript
|
||||
{
|
||||
@@ -19,6 +20,8 @@ public:
|
||||
{
|
||||
instance_de_other_side_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
|
||||
{
|
||||
SetHeaders("DeOtherSide");
|
||||
SetBossNumber(4);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -5002,6 +5002,7 @@ enum BloodlustExhaustionSpell : uint32
|
||||
// 256740 - Drums of the Maelstrom
|
||||
// 309658 - Drums of Deathly Ferocity
|
||||
// 381301 - Feral Hide Drums
|
||||
// 466904 - Harrier's Cry
|
||||
class spell_gen_bloodlust : public SpellScript
|
||||
{
|
||||
public:
|
||||
@@ -6026,6 +6027,7 @@ void AddSC_generic_spell_scripts()
|
||||
RegisterSpellScriptWithArgs(spell_gen_bloodlust, "spell_sha_heroism", SPELL_SHAMAN_EXHAUSTION);
|
||||
RegisterSpellScriptWithArgs(spell_gen_bloodlust, "spell_mage_time_warp", SPELL_MAGE_TEMPORAL_DISPLACEMENT);
|
||||
RegisterSpellScriptWithArgs(spell_gen_bloodlust, "spell_hun_primal_rage", SPELL_HUNTER_FATIGUED);
|
||||
RegisterSpellScriptWithArgs(spell_gen_bloodlust, "spell_hun_harriers_cry", SPELL_HUNTER_FATIGUED);
|
||||
RegisterSpellScriptWithArgs(spell_gen_bloodlust, "spell_evo_fury_of_the_aspects", SPELL_EVOKER_EXHAUSTION);
|
||||
RegisterSpellScriptWithArgs(spell_gen_bloodlust, "spell_item_bloodlust_drums", SPELL_SHAMAN_EXHAUSTION);
|
||||
RegisterSpellScript(spell_gen_spirit_heal_aoe);
|
||||
|
||||
@@ -58,6 +58,7 @@ enum HunterSpells
|
||||
SPELL_HUNTER_EXHILARATION_PET = 128594,
|
||||
SPELL_HUNTER_EXHILARATION_R2 = 231546,
|
||||
SPELL_HUNTER_EXPLOSIVE_SHOT_DAMAGE = 212680,
|
||||
SPELL_HUNTER_FLARE_DISPEL = 132951,
|
||||
SPELL_HUNTER_GREVIOUS_INJURY = 1217789,
|
||||
SPELL_HUNTER_HIGH_EXPLOSIVE_TRAP = 236775,
|
||||
SPELL_HUNTER_HIGH_EXPLOSIVE_TRAP_DAMAGE = 236777,
|
||||
@@ -65,6 +66,7 @@ enum HunterSpells
|
||||
SPELL_HUNTER_IMPLOSIVE_TRAP_DAMAGE = 462033,
|
||||
SPELL_HUNTER_INTIMIDATION = 19577,
|
||||
SPELL_HUNTER_INTIMIDATION_MARKSMANSHIP = 474421,
|
||||
SPELL_HUNTER_KINDLING_FLARE = 459506,
|
||||
SPELL_HUNTER_LATENT_POISON_STACK = 378015,
|
||||
SPELL_HUNTER_LATENT_POISON_DAMAGE = 378016,
|
||||
SPELL_HUNTER_LATENT_POISON_INJECTORS_STACK = 336903,
|
||||
@@ -82,6 +84,7 @@ enum HunterSpells
|
||||
SPELL_HUNTER_POSTHASTE_INCREASE_SPEED = 118922,
|
||||
SPELL_HUNTER_POSTHASTE_TALENT = 109215,
|
||||
SPELL_HUNTER_PRECISE_SHOTS = 260242,
|
||||
SPELL_HUNTER_QUICK_DRAW_SPEED = 1279347,
|
||||
SPELL_HUNTER_RAPID_FIRE = 257044,
|
||||
SPELL_HUNTER_RAPID_FIRE_DAMAGE = 257045,
|
||||
SPELL_HUNTER_RAPID_FIRE_ENERGIZE = 263585,
|
||||
@@ -97,6 +100,7 @@ enum HunterSpells
|
||||
SPELL_HUNTER_STREAMLINE_BUFF = 342076,
|
||||
SPELL_HUNTER_T9_4P_GREATNESS = 68130,
|
||||
SPELL_HUNTER_T29_2P_MARKSMANSHIP_DAMAGE = 394371,
|
||||
SPELL_HUNTER_TAKE_AIM = 1273132,
|
||||
SPELL_HUNTER_TAR_TRAP = 187699,
|
||||
SPELL_HUNTER_TAR_TRAP_AREATRIGGER = 187700,
|
||||
SPELL_HUNTER_TAR_TRAP_SLOW = 135299,
|
||||
@@ -488,6 +492,25 @@ class spell_hun_explosive_shot : public AuraScript
|
||||
}
|
||||
};
|
||||
|
||||
// 132950 - Flare
|
||||
// Ids - 510 and 35958
|
||||
struct at_hun_legion_flare : public AreaTriggerAI
|
||||
{
|
||||
using AreaTriggerAI::AreaTriggerAI;
|
||||
|
||||
void OnUnitEnter(Unit* unit) override
|
||||
{
|
||||
if (Unit* caster = at->GetCaster())
|
||||
if (caster->IsValidAttackTarget(unit))
|
||||
unit->CastSpell(unit, SPELL_HUNTER_FLARE_DISPEL, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
|
||||
}
|
||||
|
||||
void OnUnitExit(Unit* unit, AreaTriggerExitReason /*reason*/) override
|
||||
{
|
||||
unit->RemoveAurasDueToSpell(SPELL_HUNTER_FLARE_DISPEL);
|
||||
}
|
||||
};
|
||||
|
||||
// 236775 - High Explosive Trap
|
||||
// 9810 - AreatriggerId
|
||||
struct areatrigger_hun_high_explosive_trap : AreaTriggerAI
|
||||
@@ -565,6 +588,33 @@ struct areatrigger_hun_implosive_trap : AreaTriggerAI
|
||||
}
|
||||
};
|
||||
|
||||
// 459506 - Kindling Flare (attached to 132950 - Flare)
|
||||
class spell_hun_kindling_flare : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_HUNTER_KINDLING_FLARE });
|
||||
}
|
||||
|
||||
void HandleFlare(SpellEffIndex effIndex)
|
||||
{
|
||||
if (GetCaster()->HasAura(SPELL_HUNTER_KINDLING_FLARE))
|
||||
PreventHitEffect(effIndex);
|
||||
}
|
||||
|
||||
void HandleKindlingFlare(SpellEffIndex effIndex)
|
||||
{
|
||||
if (!GetCaster()->HasAura(SPELL_HUNTER_KINDLING_FLARE))
|
||||
PreventHitEffect(effIndex);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectLaunch += SpellEffectFn(spell_hun_kindling_flare::HandleFlare, EFFECT_0, SPELL_EFFECT_CREATE_AREATRIGGER);
|
||||
OnEffectLaunch += SpellEffectFn(spell_hun_kindling_flare::HandleKindlingFlare, EFFECT_1, SPELL_EFFECT_CREATE_AREATRIGGER);
|
||||
}
|
||||
};
|
||||
|
||||
// 378016 - Latent Poison
|
||||
class spell_hun_latent_poison_damage : public SpellScript
|
||||
{
|
||||
@@ -1282,6 +1332,48 @@ class spell_hun_precise_shots : public AuraScript
|
||||
}
|
||||
};
|
||||
|
||||
// 459794 - Quick Draw
|
||||
class spell_hun_quick_draw : public AuraScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_HUNTER_QUICK_DRAW_SPEED });
|
||||
}
|
||||
|
||||
void HandleProc(ProcEventInfo const& eventInfo) const
|
||||
{
|
||||
eventInfo.GetActor()->CastSpell(eventInfo.GetActor(), SPELL_HUNTER_QUICK_DRAW_SPEED, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnProc += AuraProcFn(spell_hun_quick_draw::HandleProc);
|
||||
}
|
||||
};
|
||||
|
||||
// 1279347 - Quick Draw
|
||||
class spell_hun_quick_draw_speed : public AuraScript
|
||||
{
|
||||
static constexpr uint8 SpeedAmount = 5;
|
||||
|
||||
bool Validate(SpellInfo const* spellInfo) override
|
||||
{
|
||||
return ValidateSpellEffect({ { spellInfo->Id, EFFECT_0 } })
|
||||
&& spellInfo->GetEffect(EFFECT_0).IsAura(SPELL_AURA_MOD_INCREASE_SPEED);
|
||||
}
|
||||
|
||||
void HandleSpeed(AuraEffect const* /*aurEff*/) const
|
||||
{
|
||||
if (AuraEffect* speed = GetEffect(EFFECT_0))
|
||||
speed->ChangeAmount(speed->GetAmount() - SpeedAmount);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_hun_quick_draw_speed::HandleSpeed, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 257044 - Rapid Fire
|
||||
class spell_hun_rapid_fire : public AuraScript
|
||||
{
|
||||
@@ -1290,10 +1382,10 @@ class spell_hun_rapid_fire : public AuraScript
|
||||
return ValidateSpellInfo({ SPELL_HUNTER_RAPID_FIRE_DAMAGE });
|
||||
}
|
||||
|
||||
void HandlePeriodic(AuraEffect const* /*aurEff*/)
|
||||
void HandlePeriodic(AuraEffect const* /*aurEff*/) const
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
caster->CastSpell(GetTarget(), SPELL_HUNTER_RAPID_FIRE_DAMAGE, true);
|
||||
caster->CastSpell(GetTarget(), SPELL_HUNTER_RAPID_FIRE_DAMAGE, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
@@ -1310,9 +1402,12 @@ class spell_hun_rapid_fire_damage : public SpellScript
|
||||
return ValidateSpellInfo({ SPELL_HUNTER_RAPID_FIRE_ENERGIZE });
|
||||
}
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
void HandleHit(SpellEffIndex /*effIndex*/) const
|
||||
{
|
||||
GetCaster()->CastSpell(nullptr, SPELL_HUNTER_RAPID_FIRE_ENERGIZE, true);
|
||||
GetCaster()->CastSpell(nullptr, SPELL_HUNTER_RAPID_FIRE_ENERGIZE, CastSpellExtraArgsInit{
|
||||
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
|
||||
.TriggeringSpell = GetSpell()
|
||||
});
|
||||
}
|
||||
|
||||
void Register() override
|
||||
@@ -1558,6 +1653,26 @@ class spell_hun_surging_shots : public AuraScript
|
||||
}
|
||||
};
|
||||
|
||||
// 1273132 Take Aim (attached to 257045 - Rapid Fire)
|
||||
class spell_hun_take_aim : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_HUNTER_TAKE_AIM, SPELL_HUNTER_AIMED_SHOT });
|
||||
}
|
||||
|
||||
void HandleOnHit() const
|
||||
{
|
||||
if (AuraEffect const* takeAim = GetCaster()->GetAuraEffect(SPELL_HUNTER_TAKE_AIM, EFFECT_1))
|
||||
GetCaster()->GetSpellHistory()->ModifyChargeRecoveryTime(sSpellMgr->AssertSpellInfo(SPELL_HUNTER_AIMED_SHOT, GetCastDifficulty())->ChargeCategoryId, Milliseconds(-takeAim->GetAmountAsInt()));
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnHit += SpellHitFn(spell_hun_take_aim::HandleOnHit);
|
||||
}
|
||||
};
|
||||
|
||||
// 1515 - Tame Beast
|
||||
class spell_hun_tame_beast : public SpellScript
|
||||
{
|
||||
@@ -2412,9 +2527,11 @@ void AddSC_hunter_spell_scripts()
|
||||
RegisterSpellScript(spell_hun_emergency_salve);
|
||||
RegisterSpellScript(spell_hun_exhilaration);
|
||||
RegisterSpellScript(spell_hun_explosive_shot);
|
||||
RegisterAreaTriggerAI(at_hun_legion_flare);
|
||||
RegisterAreaTriggerAI(areatrigger_hun_high_explosive_trap);
|
||||
RegisterSpellScript(spell_hun_hunting_party);
|
||||
RegisterAreaTriggerAI(areatrigger_hun_implosive_trap);
|
||||
RegisterSpellScript(spell_hun_kindling_flare);
|
||||
RegisterSpellScript(spell_hun_latent_poison_damage);
|
||||
RegisterSpellScript(spell_hun_latent_poison_trigger);
|
||||
RegisterSpellScript(spell_hun_latent_poison_injectors_damage);
|
||||
@@ -2430,6 +2547,8 @@ void AddSC_hunter_spell_scripts()
|
||||
RegisterSpellScript(spell_hun_pet_heart_of_the_phoenix);
|
||||
RegisterSpellScript(spell_hun_posthaste);
|
||||
RegisterSpellScript(spell_hun_precise_shots);
|
||||
RegisterSpellScript(spell_hun_quick_draw);
|
||||
RegisterSpellScript(spell_hun_quick_draw_speed);
|
||||
RegisterSpellScript(spell_hun_rapid_fire);
|
||||
RegisterSpellScript(spell_hun_rapid_fire_damage);
|
||||
RegisterSpellScript(spell_hun_rejuvenating_wind);
|
||||
@@ -2441,6 +2560,7 @@ void AddSC_hunter_spell_scripts()
|
||||
RegisterSpellScript(spell_hun_steady_shot);
|
||||
RegisterSpellScript(spell_hun_streamline);
|
||||
RegisterSpellScript(spell_hun_surging_shots);
|
||||
RegisterSpellScript(spell_hun_take_aim);
|
||||
RegisterSpellScript(spell_hun_tame_beast);
|
||||
RegisterAreaTriggerAI(areatrigger_hun_tar_trap);
|
||||
RegisterAreaTriggerAI(areatrigger_hun_tar_trap_activate);
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (C) WowCommunity Project
|
||||
*
|
||||
* This SourceCode is NOT free a software. Please hold everything Private
|
||||
* and read our Terms
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "city_of_echoes.h"
|
||||
#include "TemporarySummon.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_SCARAB_LORD_ENERGY = 434302,
|
||||
SPELL_INFESTATION = 433740,
|
||||
SPELL_IMPALE = 435012,
|
||||
SPELL_BURROW_CHARGE = 439506,
|
||||
SPELL_EYE_OF_THE_SWARM = 433766,
|
||||
SPELL_EYE_OF_THE_SWARM_BC = 435151,
|
||||
SPELL_CEASELESS_SWARM = 433781,
|
||||
SPELL_SUMMON_WEBMAGE = 1283246,
|
||||
SPELL_WEB_BOLT = 434786,
|
||||
SPELL_REVOLTING_VOLLEY = 448248
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_IMPALE = 1,
|
||||
EVENT_INFESTATION,
|
||||
EVENT_BURROW_CHARGE,
|
||||
EVENT_EYE_OF_THE_SWARM,
|
||||
EVENT_SUMMON_WEBMAGE
|
||||
};
|
||||
|
||||
enum WebmageEvents
|
||||
{
|
||||
EVENT_WEB_BOLT = 1,
|
||||
EVENT_REVOLTING_VOLLEY
|
||||
};
|
||||
|
||||
enum Misc
|
||||
{
|
||||
MAX_ENERGY = 100,
|
||||
ENERGY_GAIN_PER_SEC = 3,
|
||||
SWARM_ENERGY = 100
|
||||
};
|
||||
|
||||
struct boss_anubzekt : public BossAI
|
||||
{
|
||||
boss_anubzekt(Creature* creature) : BossAI(creature, DATA_ANUBZEKT) { }
|
||||
|
||||
void ScheduleTasks() override
|
||||
{
|
||||
_energy = 0;
|
||||
DoCastSelf(SPELL_SCARAB_LORD_ENERGY, true);
|
||||
|
||||
events.ScheduleEvent(EVENT_INFESTATION, 2s);
|
||||
events.ScheduleEvent(EVENT_IMPALE, 5s);
|
||||
events.ScheduleEvent(EVENT_BURROW_CHARGE, 15s);
|
||||
events.ScheduleEvent(EVENT_SUMMON_WEBMAGE, 25s);
|
||||
events.ScheduleEvent(EVENT_EYE_OF_THE_SWARM, 1s);
|
||||
}
|
||||
|
||||
void OnSpellCast(SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_EYE_OF_THE_SWARM)
|
||||
DoCastSelf(SPELL_EYE_OF_THE_SWARM_BC, true);
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_IMPALE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 0, 40.0f))
|
||||
DoCast(target, SPELL_IMPALE);
|
||||
events.Repeat(15s);
|
||||
break;
|
||||
case EVENT_INFESTATION:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f, true))
|
||||
DoCast(target, SPELL_INFESTATION);
|
||||
events.Repeat(11s);
|
||||
break;
|
||||
case EVENT_BURROW_CHARGE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f, true))
|
||||
DoCast(target, SPELL_BURROW_CHARGE);
|
||||
events.Repeat(35s);
|
||||
break;
|
||||
case EVENT_SUMMON_WEBMAGE:
|
||||
if (Creature* webmage = me->SummonCreature(NPC_BLOODSTAINED_WEBMAGE,
|
||||
me->GetRandomNearPosition(10.0f), TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5s))
|
||||
{
|
||||
DoCastSelf(SPELL_SUMMON_WEBMAGE, true);
|
||||
webmage->AI()->DoZoneInCombat();
|
||||
}
|
||||
events.Repeat(IsMythicPlus() ? 30s : 45s);
|
||||
break;
|
||||
case EVENT_EYE_OF_THE_SWARM:
|
||||
{
|
||||
_energy += ENERGY_GAIN_PER_SEC;
|
||||
if (_energy >= SWARM_ENERGY && !me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
_energy = 0;
|
||||
DoCastSelf(SPELL_EYE_OF_THE_SWARM);
|
||||
DoCastSelf(SPELL_CEASELESS_SWARM, true);
|
||||
events.DelayEvents(8s);
|
||||
}
|
||||
events.Repeat(1s);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint8 _energy;
|
||||
};
|
||||
|
||||
struct npc_bloodstained_webmage : public ScriptedAI
|
||||
{
|
||||
npc_bloodstained_webmage(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void ScheduleTasks() override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_WEB_BOLT, 2s);
|
||||
events.ScheduleEvent(EVENT_REVOLTING_VOLLEY, 12s);
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_WEB_BOLT:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f, true))
|
||||
DoCast(target, SPELL_WEB_BOLT);
|
||||
events.Repeat(4s);
|
||||
break;
|
||||
case EVENT_REVOLTING_VOLLEY:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f, true))
|
||||
DoCast(target, SPELL_REVOLTING_VOLLEY);
|
||||
events.Repeat(15s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_anubzekt()
|
||||
{
|
||||
RegisterCityOfEchoesCreatureAI(boss_anubzekt);
|
||||
RegisterCreatureAI(npc_bloodstained_webmage);
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (C) WowCommunity Project
|
||||
*
|
||||
* This SourceCode is NOT free a software. Please hold everything Private
|
||||
* and read our Terms
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "city_of_echoes.h"
|
||||
#include "TemporarySummon.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_VORACIOUS_BITE = 438471,
|
||||
SPELL_ALERTING_SHRILL = 438476,
|
||||
SPELL_ALERTING_SHRILL_DMG = 438495,
|
||||
SPELL_GOSSAMER_ONSLAUGHT = 438473,
|
||||
SPELL_VILE_WEBBING = 438960,
|
||||
SPELL_SPAWN_JUMP = 439065,
|
||||
SPELL_SCREENSHAKE = 439035,
|
||||
SPELL_SPAWN_EGGS = 439027,
|
||||
SPELL_HUNGER = 438490,
|
||||
SPELL_HUNGER_CHANNEL = 439070,
|
||||
SPELL_INSATIABLE = 446788,
|
||||
SPELL_TREMOR_SENSE = 438486,
|
||||
SPELL_HATCH = 436408
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_VORACIOUS_BITE = 1,
|
||||
EVENT_ALERTING_SHRILL,
|
||||
EVENT_GOSSAMER_ONSLAUGHT,
|
||||
EVENT_CHECK_CRAWLER_DISTANCE,
|
||||
EVENT_HATCH_EGG
|
||||
};
|
||||
|
||||
struct boss_avanoxx : public BossAI
|
||||
{
|
||||
boss_avanoxx(Creature* creature) : BossAI(creature, DATA_AVANOXX) { }
|
||||
|
||||
void ScheduleTasks() override
|
||||
{
|
||||
_eggs.clear();
|
||||
_crawlers.clear();
|
||||
|
||||
DoCastSelf(SPELL_SCREENSHAKE, true);
|
||||
DoCastSelf(SPELL_SPAWN_JUMP);
|
||||
DoCastSelf(SPELL_TREMOR_SENSE, true);
|
||||
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
SummonEgg();
|
||||
|
||||
events.ScheduleEvent(EVENT_VORACIOUS_BITE, 30s);
|
||||
events.ScheduleEvent(EVENT_ALERTING_SHRILL, 38s);
|
||||
events.ScheduleEvent(EVENT_GOSSAMER_ONSLAUGHT, 57s);
|
||||
events.ScheduleEvent(EVENT_CHECK_CRAWLER_DISTANCE, 2s);
|
||||
}
|
||||
|
||||
void OnSpellCast(SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_ALERTING_SHRILL)
|
||||
DoCastAOE(SPELL_ALERTING_SHRILL_DMG);
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_VORACIOUS_BITE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 0, 40.0f))
|
||||
DoCast(target, SPELL_VORACIOUS_BITE);
|
||||
events.Repeat(15s);
|
||||
break;
|
||||
case EVENT_ALERTING_SHRILL:
|
||||
DoCastSelf(SPELL_ALERTING_SHRILL);
|
||||
HatchEggs();
|
||||
events.Repeat(30s);
|
||||
break;
|
||||
case EVENT_GOSSAMER_ONSLAUGHT:
|
||||
DoCastSelf(SPELL_GOSSAMER_ONSLAUGHT);
|
||||
for (uint8 i = 0; i < 5; ++i)
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f))
|
||||
me->CastSpell(target, SPELL_VILE_WEBBING, true);
|
||||
events.Repeat(45s);
|
||||
break;
|
||||
case EVENT_CHECK_CRAWLER_DISTANCE:
|
||||
CheckCrawlersAndApplyInsatiable();
|
||||
events.Repeat(1s);
|
||||
break;
|
||||
case EVENT_HATCH_EGG:
|
||||
if (Creature* egg = FindEgg())
|
||||
{
|
||||
if (egg->IsAlive())
|
||||
{
|
||||
egg->CastSpell(egg, SPELL_HATCH);
|
||||
SpawnCrawler(egg->GetPosition());
|
||||
egg->DespawnOrUnsummon(100ms);
|
||||
}
|
||||
events.Repeat(500ms);
|
||||
}
|
||||
else
|
||||
events.Repeat(1s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void SummonEgg()
|
||||
{
|
||||
Position pos = me->GetRandomNearPosition(8.0f);
|
||||
if (Creature* egg = me->SummonCreature(NPC_CRAWLER_EGG, pos, TEMPSUMMON_MANUAL_DESPAWN))
|
||||
_eggs.push_back(egg->GetGUID());
|
||||
}
|
||||
|
||||
void HatchEggs()
|
||||
{
|
||||
events.ScheduleEvent(EVENT_HATCH_EGG, 1s);
|
||||
}
|
||||
|
||||
void SpawnCrawler(Position pos)
|
||||
{
|
||||
if (Creature* crawler = me->SummonCreature(NPC_STARVED_CRAWLER, pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3s))
|
||||
{
|
||||
crawler->CastSpell(crawler, SPELL_HUNGER, true);
|
||||
crawler->CastSpell(crawler, SPELL_HUNGER_CHANNEL, true);
|
||||
_crawlers.push_back(crawler->GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
Creature* FindEgg()
|
||||
{
|
||||
for (ObjectGuid guid : _eggs)
|
||||
if (Creature* egg = ObjectAccessor::GetCreature(*me, guid))
|
||||
if (egg->IsAlive())
|
||||
return egg;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CheckCrawlersAndApplyInsatiable()
|
||||
{
|
||||
if (_crawlers.empty())
|
||||
return;
|
||||
|
||||
for (auto it = _crawlers.begin(); it != _crawlers.end();)
|
||||
{
|
||||
Creature* crawler = ObjectAccessor::GetCreature(*me, *it);
|
||||
if (!crawler || !crawler->IsAlive())
|
||||
{
|
||||
it = _crawlers.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (me->GetDistance(crawler) <= 5.0f)
|
||||
{
|
||||
me->CastSpell(me, SPELL_INSATIABLE, true);
|
||||
crawler->DespawnOrUnsummon();
|
||||
it = _crawlers.erase(it);
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<ObjectGuid> _eggs;
|
||||
std::vector<ObjectGuid> _crawlers;
|
||||
};
|
||||
|
||||
struct npc_crawler_egg : public ScriptedAI
|
||||
{
|
||||
npc_crawler_egg(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
}
|
||||
};
|
||||
|
||||
struct npc_starved_crawler : public ScriptedAI
|
||||
{
|
||||
npc_starved_crawler(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
|
||||
AttackStart(target);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 /*diff*/) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
me->DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_avanoxx()
|
||||
{
|
||||
RegisterCityOfEchoesCreatureAI(boss_avanoxx);
|
||||
RegisterCreatureAI(npc_crawler_egg);
|
||||
RegisterCreatureAI(npc_starved_crawler);
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (C) WowCommunity Project
|
||||
*
|
||||
* This SourceCode is NOT free a software. Please hold everything Private
|
||||
* and read our Terms
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "city_of_echoes.h"
|
||||
#include "TemporarySummon.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_COSMIC_POWER = 431125,
|
||||
SPELL_CALL_DRONES = 431960,
|
||||
SPELL_ERUPTING_WEBS = 432130,
|
||||
SPELL_VENOM_VOLLEY = 432227,
|
||||
SPELL_COSMIC_SINGULARITY = 432117,
|
||||
SPELL_SINGULARITY_PRECAST = 447504,
|
||||
SPELL_COSMIC_SINGULARITY_KB = 439680,
|
||||
SPELL_FADED = 432119,
|
||||
SPELL_BLACK_BLOOD = 431985,
|
||||
SPELL_BLACK_BLOOD_DMG = 432011,
|
||||
SPELL_BREAK_PLAYER_TARGET = 140562
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_CALL_DRONES = 1,
|
||||
EVENT_ERUPTING_WEBS,
|
||||
EVENT_VENOM_VOLLEY,
|
||||
EVENT_COSMIC_SINGULARITY
|
||||
};
|
||||
|
||||
enum Misc
|
||||
{
|
||||
MAX_ENERGY = 100,
|
||||
ENERGY_GAIN_PER_SEC = 4,
|
||||
SINGULARITY_ENERGY = 100
|
||||
};
|
||||
|
||||
enum BloodworkerEvents
|
||||
{
|
||||
EVENT_BLACK_BLOOD = 1
|
||||
};
|
||||
|
||||
struct boss_kikatal : public BossAI
|
||||
{
|
||||
boss_kikatal(Creature* creature) : BossAI(creature, DATA_KIKATAL_THE_HARVESTER) { }
|
||||
|
||||
void ScheduleTasks() override
|
||||
{
|
||||
_energy = 0;
|
||||
DoCastSelf(SPELL_COSMIC_POWER, true);
|
||||
|
||||
events.ScheduleEvent(EVENT_CALL_DRONES, 5s);
|
||||
events.ScheduleEvent(EVENT_ERUPTING_WEBS, 10s);
|
||||
events.ScheduleEvent(EVENT_VENOM_VOLLEY, 16s);
|
||||
events.ScheduleEvent(EVENT_COSMIC_SINGULARITY, 1s);
|
||||
}
|
||||
|
||||
void OnSpellCast(SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_COSMIC_SINGULARITY)
|
||||
{
|
||||
DoCastSelf(SPELL_COSMIC_SINGULARITY_KB, true);
|
||||
for (MapReference const& ref : me->GetMap()->GetPlayers())
|
||||
if (Player* player = ref.GetSource())
|
||||
if (player->IsAlive() && me->GetDistance(player) <= 60.0f)
|
||||
me->CastSpell(player, SPELL_FADED, true);
|
||||
}
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_CALL_DRONES:
|
||||
{
|
||||
Position pos = me->GetRandomNearPosition(20.0f);
|
||||
if (Creature* bloodworker = me->SummonCreature(NPC_BLOODWORKER, pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, IsMythicPlus() ? 30s : 70s))
|
||||
{
|
||||
DoCastSelf(SPELL_CALL_DRONES, true);
|
||||
bloodworker->AI()->DoZoneInCombat();
|
||||
}
|
||||
events.Repeat(IsMythicPlus() ? 20s : 35s);
|
||||
break;
|
||||
}
|
||||
case EVENT_ERUPTING_WEBS:
|
||||
DoCastSelf(SPELL_ERUPTING_WEBS);
|
||||
events.Repeat(27s);
|
||||
break;
|
||||
case EVENT_VENOM_VOLLEY:
|
||||
DoCastRandom(SPELL_VENOM_VOLLEY);
|
||||
events.Repeat(27s);
|
||||
break;
|
||||
case EVENT_COSMIC_SINGULARITY:
|
||||
_energy += ENERGY_GAIN_PER_SEC;
|
||||
if (_energy >= SINGULARITY_ENERGY && !me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
_energy = 0;
|
||||
DoCastSelf(SPELL_SINGULARITY_PRECAST, true);
|
||||
DoCastSelf(SPELL_COSMIC_SINGULARITY);
|
||||
events.DelayEvents(8s);
|
||||
}
|
||||
events.Repeat(1s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint8 _energy;
|
||||
};
|
||||
|
||||
struct npc_bloodworker : public ScriptedAI
|
||||
{
|
||||
npc_bloodworker(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void ScheduleTasks() override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_BLACK_BLOOD, 2s);
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_BLACK_BLOOD:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 30.0f, true))
|
||||
{
|
||||
DoCast(target, SPELL_BLACK_BLOOD);
|
||||
DoCast(target, SPELL_BLACK_BLOOD_DMG, true);
|
||||
DoCast(target, SPELL_BREAK_PLAYER_TARGET, true);
|
||||
}
|
||||
events.Repeat(2s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
void AddSC_boss_kikatal()
|
||||
{
|
||||
RegisterCityOfEchoesCreatureAI(boss_kikatal);
|
||||
RegisterCreatureAI(npc_bloodworker);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) WowCommunity Project
|
||||
*
|
||||
* This SourceCode is NOT free a software. Please hold everything Private
|
||||
* and read our Terms
|
||||
*/
|
||||
|
||||
#ifndef DEF_CITY_OF_ECHOES_H_
|
||||
#define DEF_CITY_OF_ECHOES_H_
|
||||
|
||||
#include "CreatureAIImpl.h"
|
||||
|
||||
#define COEScriptName "instance_city_of_echoes"
|
||||
#define DataHeader "cityofechoes"
|
||||
|
||||
uint32 const EncounterCount = 3;
|
||||
|
||||
enum CityOfEchoesDataTypes
|
||||
{
|
||||
DATA_AVANOXX = 0,
|
||||
DATA_ANUBZEKT,
|
||||
DATA_KIKATAL_THE_HARVESTER,
|
||||
};
|
||||
|
||||
enum CityOfEchoesCreatureIds
|
||||
{
|
||||
BOSS_AVANOXX = 213179,
|
||||
BOSS_ANUBZEKT = 215405,
|
||||
BOSS_KIKATAL_THE_HARVESTER = 215407,
|
||||
NPC_CRAWLER_EGG = 218183,
|
||||
NPC_STARVED_CRAWLER = 218961,
|
||||
NPC_BLOODSTAINED_WEBMAGE = 223253,
|
||||
NPC_BLOODWORKER = 215826,
|
||||
NPC_BLACK_BLOOD = 215968,
|
||||
};
|
||||
|
||||
template <class AI, class T>
|
||||
inline AI* GetCityOfEchoesAI(T* obj)
|
||||
{
|
||||
return GetInstanceAI<AI>(obj, COEScriptName);
|
||||
}
|
||||
|
||||
#define RegisterCityOfEchoesCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetCityOfEchoesAI)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) WowCommunity Project
|
||||
*
|
||||
* This SourceCode is NOT free a software. Please hold everything Private
|
||||
* and read our Terms
|
||||
*/
|
||||
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "city_of_echoes.h"
|
||||
|
||||
static constexpr ObjectData creatureData[] =
|
||||
{
|
||||
{ BOSS_AVANOXX, DATA_AVANOXX },
|
||||
{ BOSS_ANUBZEKT, DATA_ANUBZEKT },
|
||||
{ BOSS_KIKATAL_THE_HARVESTER, DATA_KIKATAL_THE_HARVESTER },
|
||||
};
|
||||
|
||||
static constexpr DungeonEncounterData const encounters[] =
|
||||
{
|
||||
{ DATA_AVANOXX, {{ 2907 }} },
|
||||
{ DATA_ANUBZEKT, {{ 2908 }} },
|
||||
{ DATA_KIKATAL_THE_HARVESTER, {{ 2905 }} },
|
||||
};
|
||||
|
||||
class instance_city_of_echoes : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
instance_city_of_echoes() : InstanceMapScript(COEScriptName, 2660) { }
|
||||
|
||||
struct instance_city_of_echoes_InstanceMapScript: public InstanceScript
|
||||
{
|
||||
instance_city_of_echoes_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(EncounterCount);
|
||||
LoadObjectData(creatureData, {});
|
||||
LoadDungeonEncounterData(encounters);
|
||||
}
|
||||
|
||||
void OnPlayerEnter(Player* player) override
|
||||
{
|
||||
if (!player->GetGroup() || !player->GetGroup()->GetLeaderGUID())
|
||||
return;
|
||||
|
||||
ObjectGuid leaderguid = player->GetGroup()->GetLeaderGUID();
|
||||
if (!leaderguid)
|
||||
return;
|
||||
|
||||
if (Player* leader = ObjectAccessor::GetPlayer(*player, leaderguid))
|
||||
{
|
||||
if (leader->GetTeam() == HORDE)
|
||||
faction_group = HORDE;
|
||||
else if (leader->GetTeam() == ALLIANCE)
|
||||
faction_group = ALLIANCE;
|
||||
else
|
||||
faction_group = HORDE;
|
||||
}
|
||||
|
||||
player->GetGroup()->AddFollowerModeBots(player);
|
||||
|
||||
}
|
||||
|
||||
void OnPlayerExit(Player* player)
|
||||
{
|
||||
player->GetGroup()->DespawnFollowerModeBots(player);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Team faction_group = HORDE;
|
||||
};
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||
{
|
||||
return new instance_city_of_echoes_InstanceMapScript(map);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_instance_city_of_echoes()
|
||||
{
|
||||
new instance_city_of_echoes();
|
||||
}
|
||||
@@ -24,6 +24,12 @@ void AddSC_boss_captain_dailcry();
|
||||
void AddSC_boss_prioress_murrpray();
|
||||
void AddSC_priority_of_the_sacred_flame();
|
||||
|
||||
//Ara-Kara, City of Echoes
|
||||
void AddSC_instance_city_of_echoes();
|
||||
void AddSC_boss_avanoxx();
|
||||
void AddSC_boss_anubzekt();
|
||||
void AddSC_boss_kikatal();
|
||||
|
||||
// The name of this function should match:
|
||||
// void Add${NameOfDirectory}Scripts()
|
||||
void AddWarWithinScripts()
|
||||
@@ -43,4 +49,10 @@ void AddWarWithinScripts()
|
||||
AddSC_boss_prioress_murrpray();
|
||||
AddSC_priority_of_the_sacred_flame();
|
||||
|
||||
//Ara-Kara, City of Echoes
|
||||
AddSC_instance_city_of_echoes();
|
||||
AddSC_boss_avanoxx();
|
||||
AddSC_boss_anubzekt();
|
||||
AddSC_boss_kikatal();
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user