Merge branch 'master' into Playerbot

# Conflicts:
#	src/server/game/Guilds/Guild.cpp
This commit is contained in:
郑佩茹
2023-04-03 07:52:56 -06:00
64 changed files with 944 additions and 216 deletions
+2 -1
View File
@@ -69,7 +69,8 @@ body:
attributes: attributes:
label: Operating system label: Operating system
description: | description: |
Operating System, i.e. Windows 10 x64, Debian 10 x64, etc The Operating System the Server is running on.
i.e. Windows 11 x64, Debian 10 x64, macOS 12, Ubuntu 20.04
validations: validations:
required: true required: true
- type: textarea - type: textarea
@@ -0,0 +1,3 @@
-- DB update 2023_03_29_04 -> 2023_03_30_00
--
DELETE FROM `creature` WHERE `id1` = 20978;
@@ -0,0 +1,3 @@
-- DB update 2023_03_30_00 -> 2023_03_30_01
--
DELETE FROM `creature_onkill_reputation` WHERE (`creature_id` IN (21466, 21467));
@@ -0,0 +1,9 @@
-- DB update 2023_03_30_01 -> 2023_03_30_02
--
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 1922001) AND (`source_type` = 9) AND (`id` IN (3));
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(1922001, 9, 3, 0, 0, 0, 100, 512, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Mechanar Gauntlet Engage - Actionlist - Set In Combat With Zone');
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 1922002) AND (`source_type` = 9) AND (`id` IN (2));
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(1922002, 9, 2, 0, 0, 0, 100, 512, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Mechanar Gauntlet Engage 2 - Actionlist - Set In Combat With Zone');
@@ -0,0 +1,9 @@
-- DB update 2023_03_30_02 -> 2023_03_30_03
--
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 13) AND (`SourceEntry` = 35301) AND (`ConditionTypeOrReference` = 31) AND (`ConditionValue2` = 21062);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(13, 1, 35301, 0, 0, 31, 0, 3, 21062, 0, 0, 0, 0, '', 'Spell Suicide (35301) only targets Nether Wraith (21062)');
DELETE FROM `creature_equip_template` WHERE (`CreatureID` = 19220 AND `ID` = 2);
INSERT INTO `creature_equip_template` (`CreatureID`, `ID`, `ItemID1`, `ItemID2`, `ItemID3`, `VerifiedBuild`) VALUES
(19220, 2, 29455, 0, 0, 48526);
@@ -0,0 +1,2 @@
-- DB update 2023_03_30_03 -> 2023_03_30_04
DELETE FROM reference_loot_template WHERE (`Entry` = 4110) AND (`Item` IN (30520, 30986));
@@ -0,0 +1,3 @@
-- DB update 2023_03_30_04 -> 2023_03_30_05
-- Floating Ivory Bell
UPDATE `gameobject` SET `position_z` = 145.04 WHERE `id` = 184443 AND `guid` = 25285;
@@ -0,0 +1,16 @@
-- DB update 2023_03_30_05 -> 2023_03_30_06
--
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 20405);
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(20405, 0, 0, 1, 25, 0, 100, 512, 0, 0, 0, 0, 0, 75, 35150, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Nether Charge - On Reset - Add Aura \'Nether Charge Passive\''),
(20405, 0, 1, 2, 61, 0, 100, 512, 0, 0, 0, 0, 0, 11, 37670, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Nether Charge - On Reset - Cast \'Nether Charge Timer\''),
(20405, 0, 2, 3, 61, 0, 100, 512, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Nether Charge - On Reset - Set Reactstate Passive'),
(20405, 0, 3, 0, 61, 0, 100, 512, 0, 0, 0, 0, 0, 89, 20, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Nether Charge - On Reset - Start Random Movement'),
(20405, 0, 4, 0, 60, 0, 100, 513, 8500, 8500, 0, 0, 0, 80, 2040500, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Nether Charge - On Update - Run Script (No Repeat)');
DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 2040500);
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(2040500, 9, 0, 0, 0, 0, 100, 512, 0, 0, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Nether Charge - Actionlist - Stop Random Movement'),
(2040500, 9, 1, 0, 0, 0, 100, 512, 2000, 2000, 0, 0, 0, 11, 35151, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Nether Charge - Actionlist - Cast \'Nether Charge Pulse\''),
(2040500, 9, 2, 0, 0, 0, 100, 512, 2000, 2000, 0, 0, 0, 11, 35151, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Nether Charge - Actionlist - Cast \'Nether Charge Pulse\''),
(2040500, 9, 3, 0, 0, 0, 100, 512, 2000, 2000, 0, 0, 0, 11, 35151, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Nether Charge - Actionlist - Cast \'Nether Charge Pulse\'');
@@ -0,0 +1,5 @@
-- DB update 2023_03_30_06 -> 2023_03_30_07
--
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 20210);
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(20210, 0, 0, 0, 1, 0, 100, 0, 0, 0, 600000, 600000, 0, 11, 36576, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shaleskin Flayer - Out Of Combat - Cast \'Shaleskin\'');
+278
View File
@@ -0,0 +1,278 @@
-- DB update 2023_03_30_07 -> 2023_03_31_00
--
UPDATE `spell_dbc` SET `Effect_1` = 28, `EffectMiscValueB_1` = 64, `EffectBasePoints_1` = -1 WHERE `ID` IN (
14802 -- Idol Room Spawn B
);
UPDATE `spell_dbc` SET `Effect_1` = 28, `EffectMiscValueB_1` = 64, `EffectBasePoints_1` = 0 WHERE `ID` IN (
12694, -- Idol Room Spawn A
12949, -- Idol Room Spawn End Boss
14801, -- Idol Room Spawn C
19826, -- Summon Blackwing Legionnaire
19827, -- Summon Blackwing Mage
19828, -- Summon Death Talon Dragonspawn
20172, -- Summon Onyxian Whelp
21287, -- Conjure Lokholar the Usurper DND
23118, -- Conjure Scourge Footsoldier DND
23209, -- Terrordale Haunting Spirit #2
23253, -- Terrordale Haunting Spirit #3
23361, -- Raise Undead Drakonid
24215, -- Create Heart of Hakkar Explosion
24250, -- Summon Zulian Stalker
24349, -- Summon Bloodlord's Raptor
25151, -- Summon Vekniss Drone
26140, -- Summon Hook Tentacle
26144, -- Summon Eye Tentacle
26145, -- Summon Eye Tentacle
26146, -- Summon Eye Tentacle
26147, -- Summon Eye Tentacle
26148, -- Summon Eye Tentacle
26149, -- Summon Eye Tentacle
26150, -- Summon Eye Tentacle
26151, -- Summon Eye Tentacle
26191, -- Teleport Giant Hook Tentacle
26216, -- Summon Giant Hook Tentacles
26396, -- Summon Portal Ground State
26477, -- Summon Giant Portal Ground State
26564, -- Summon Viscidus Trigger
26617, -- Summon Ouro Mound
26768, -- Summon Giant Eye Tentacles
26837, -- Summon InCombat Trigger
27178, -- Defile
27643, -- Summon Spirit of Jarien
27644, -- Summon Spirit of Sothos
27884, -- Summon Trainee
27921, -- Summon Spectral Trainee
27932, -- Summon Spectral Knight
27939, -- Summon Spectral Rivendare
28008, -- Summon Knight
28010, -- Summon Mounted Knight
28175, -- (DND) Summon Crystal Minion, Ghost
28177, -- (DND) Summon Crystal Minion, Skeleton
28179, -- (DND) Summon Crystal Minion, Ghoul
28217, -- Summon Zombie Chow
28218, -- Summon Fallout Slime
28227, -- (DND) Summon Crystal Minion, finder
28289, -- (DND) Summon Crystal Minion, Ghoul Uncommon
28290, -- (DND) Summon Crystal Minion, Ghost Uncommon
28291, -- (DND) Summon Crystal Minion, Skeleton Uncommon
28421, -- Summon Type A
28422, -- Summon Type B
28423, -- Summon Type C
28454, -- Summon Type D
28561, -- Summon Blizzard
28627, -- Summon Web Wrap
29141, -- Marauding Crust Borer
29218, -- Summon Flame Ring
29329, -- Summon Sapphiron's Wing Buffet
29508, -- Summon Crypt Guard
29869, -- Fished Up Murloc
30083, -- Summon Root Thresher
30445, -- Stillpine Ancestor Yor
30630, -- Debris
30737, -- Summon Heathen
30785, -- Summon Reaver
30786, -- Summon Sharpshooter
30954, -- Free Webbed Creature
30955, -- Free Webbed Creature
30956, -- Free Webbed Creature
30957, -- Free Webbed Creature
30958, -- Free Webbed Creature
30959, -- Free Webbed Creature
30960, -- Free Webbed Creature
30961, -- Free Webbed Creature
30962, -- Free Webbed Creature
30963, -- Free Webbed Creature
31010, -- Free Webbed Creature
31318, -- Summon Infinite Assassin
31321, -- Summon Black Morass Rift Lord
31391, -- Summon Black Morass Chrono Lord Deja
31392, -- Summon Black Morass Temporus
31393, -- Summon Black Morass Rift End Boss
31421, -- Summon Infinite Chronomancer
31528, -- Summon Gnome
31529, -- Summon Gnome
31530, -- Summon Gnome
31544, -- Summon Distiller
31545, -- Summon Distiller
31593, -- Summon Greater Manawraith
32114, -- Summon Wisp
32151, -- Infernal
32283, -- Focus Fire
32360, -- Summon Stolen Soul
32579, -- Portal Beam
32632, -- Summon Overrun Target
33121, -- A Vision of the Forgotten
33229, -- Wrath of the Astromancer
33242, -- Infernal
33363, -- Summon Infinite Executioner
33364, -- Summon Infinite Vanquisher
33367, -- Summon Astromancer Priest
33567, -- Summon Void Portal D
33677, -- Incite Chaos
33680, -- Incite Chaos
33681, -- Incite Chaos
33682, -- Incite Chaos
33683, -- Incite Chaos
33901, -- Summon Crystalhide Crumbler
33927, -- Summon Void Summoner
34064, -- Soul Split
34125, -- Spotlight
34175, -- Arcane Orb Primer
35127, -- Summon Boom Bot Target
35136, -- Summon Captured Critter
35142, -- Drijya Summon Imp
35145, -- Drijya Summon Doomguard
35146, -- Drijya Summon Terrorguard
35256, -- Summon Unstable Mushroom
35430, -- Infernal
35861, -- Summon Nether Vapor
35862, -- Summon Nether Vapor
35863, -- Summon Nether Vapor
35864, -- Summon Nether Vapor
36026, -- Conjure Elemental Soul: Earth
36036, -- Summon Netherstorm Target
36042, -- Summon Farahlon Crumbler
36043, -- Summon Farahlon Crumbler
36044, -- Summon Farahlon Crumbler
36045, -- Summon Farahlon Shardling
36046, -- Summon Farahlon Shardling
36047, -- Summon Farahlon Shardling
36048, -- Summon Motherlode Shardling
36049, -- Summon Motherlode Shardling
36050, -- Summon Motherlode Shardling
36112, -- Conjure Elemental Soul: Fire
36168, -- Conjure Elemental Soul: Water
36180, -- Conjure Elemental Soul: Air
36221, -- Summon Eye of the Citadel
36229, -- Summon Infinite Assassin
36231, -- Summon Infinite Chronomancer
36232, -- Summon Infinite Executioner
36233, -- Summon Infinite Vanquisher
36234, -- Summon Black Morass Rift Lord Alt
36235, -- Summon Black Morass Rift Keeper
36236, -- Summon Black Morass Rift Keeper
36521, -- Summon Arcane Explosion
36579, -- Summon Netherock Crumbler
36584, -- Summon Netherock Crumbler
36585, -- Summon Netherock Crumbler
36595, -- Summon Apex Crumbler
36596, -- Summon Apex Crumbler
36597, -- Summon Apex Crumbler
36724, -- Summon Phoenix Egg
36818, -- Attacking Infernal
36865, -- Summon Gnome Cannon Channel Target (DND)
37177, -- Summon Black Morass Infinite Chrono-Lord
37178, -- Summon Black Morass Infinite Timereaver
37457, -- Windsor Dismisses Horse DND
37606, -- Summon Infinite Assassin
37758, -- Bone Wastes - Summon Auchenai Spirit
37766, -- Summon Murloc A1
37772, -- Summon Murloc B1
37773, -- Summon Elemental A1
37774, -- Summon Elemental B1
37911, -- Summon Elemental A2
37912, -- Summon Elemental A3
37914, -- Summon Elemental B2
37916, -- Summon Elemental B3
37923, -- Summon Murloc A2
37925, -- Summon Murloc A3
37926, -- Summon Murloc A4
37927, -- Summon Murloc A5
37928, -- Summon Murloc B2
37929, -- Summon Murloc B3
37931, -- Summon Murloc B4
37932, -- Summon Murloc B5
38111, -- Summon Horde Bat Rider Guard
38114, -- Summon Horde Rooftop Alarm Sensor
38118, -- Summon Area 52 Death Machine Guard
38124, -- Summon Horde Ground Alarm Sensor
38137, -- Summon Sky Marker
38179, -- Summon Alliance Ground Alarm Sensor
38180, -- Summon Alliance Rooftop Alarm Sensor
38181, -- Summon Alliance Gryphon Guard
38261, -- Summon Area 52 Rooftop Alarm Sensor
38266, -- Summon Stormspire Ethereal Guard
38268, -- Summon Scryer Dragonhawk Guard
38270, -- Summon Stormspire Rooftop Alarm Sensor
38271, -- Summon Scryer Rooftop Alarm Sensor
38278, -- Summon Aldor Gryphon Guard
38283, -- Summon Aldor Rooftop Alarm Sensor
38286, -- Summon Sporeggar Sporebat Guard
38287, -- Summon Sporeggar Rooftop Alarm Sensor
38288, -- Summon Toshley Guard
38291, -- Summon Toshley Rooftop Alarm Sensor
38402, -- Summon Cenarion Storm Crow Guard
38403, -- Summon Cenarion Expedition Rooftop Alarm Sensor
38512, -- Fiery Boulder
38587, -- Summon Spirit of Redemption
38854, -- Hatch Arakkoa
38865, -- Hatch Bad Arakkoa
39080, -- Summon Mountain Shardling
39081, -- Summon Vortex Shardling
39186, -- Summon Random Tractor
39191, -- Sha'tari Flames
39302, -- Quest - The Exorcism, Summon Foul Purge
39305 -- Summon Flying Skull
);
UPDATE `spell_dbc` SET `Effect_1` = 28, `EffectMiscValueB_1` = 64, `EffectBasePoints_1` = 1 WHERE `ID` IN (
20734, -- Black Arrow
30792, -- Summon Ravager Ambusher
30825, -- Summon Siltfin Ambusher
30826, -- Summon Wildkin Ambusher
30976, -- Summon Gauntlet Guards
31995, -- Shattered Rumbler
39110 -- Summon Phoenix Adds
);
UPDATE `spell_dbc` SET `Effect_1` = 28, `EffectMiscValueB_1` = 64, `EffectBasePoints_1` = 2 WHERE `ID` IN (
30076, -- Summon Maexxna Spiderling
30827, -- Summon Bristlelimb Ambusher
36379 -- Call Skitterers
);
UPDATE `spell_dbc` SET `Effect_1` = 28, `EffectMiscValueB_1` = 64, `EffectBasePoints_1` = 3 WHERE `ID` IN (
26630, -- Spawn Vekniss Hatchlings
26631, -- Spawn Vekniss Hatchlings
26632, -- Spawn Vekniss Hatchlings
30828 -- Summon Sunhawk Ambushers
);
UPDATE `spell_dbc` SET `Effect_1` = 28, `EffectMiscValueB_1` = 64, `EffectBasePoints_1` = 4 WHERE `ID` IN (
33362 -- Summon Astromancer Adds
);
UPDATE `spell_dbc` SET `Effect_1` = 28, `EffectMiscValueB_1` = 64, `EffectBasePoints_1` = 5 WHERE `ID` IN (
23119, -- Conjure Peasant DND
23121 -- Conjure Peasant DND
);
UPDATE `spell_dbc` SET `Effect_1` = 28, `EffectMiscValueB_1` = 64, `EffectBasePoints_1` = 9 WHERE `ID` IN (
25789, -- Summon Yauj Brood
29434 -- Summon Maexxna Spiderling
);
UPDATE `spell_dbc` SET `Effect_2` = 28, `EffectMiscValueB_2` = 64, `EffectBasePoints_2` = 1 WHERE `ID` IN (
21883 -- Summon Healed Celebrian Vine
);
UPDATE `spell_dbc` SET `Effect_2` = 28, `EffectMiscValueB_2` = 64, `EffectBasePoints_2` = 0 WHERE `ID` IN (
23201, -- Hunter Epic Anti-Cheat DND
27939, -- Summon Spectral Rivendare
29110, -- Summon Enraged Mounts
30774, -- Summon Elekk
33614, -- Summon Void Portal B
33616, -- Summon Void Portal E
36616, -- Veneratus Spawn
39074, -- [DND]Rexxars Bird Effect
69868 -- Carrying Beer Barrels [TEST]
);
UPDATE `spell_dbc` SET `Effect_2` = 28, `EffectMiscValueB_2` = 496, `EffectBasePoints_2` = 0 WHERE `ID` IN (
74125 -- Summon Creator Spell Test
);
UPDATE `spell_dbc` SET `Effect_3` = 28, `EffectMiscValueB_3` = 496, `EffectBasePoints_3` = 0 WHERE `ID` IN (
33615 -- Summon Void Portal C
);
@@ -0,0 +1,8 @@
-- DB update 2023_03_31_00 -> 2023_03_31_01
--
DELETE FROM `smart_scripts` WHERE (`entryorguid` IN (20867, -138927)) AND (`source_type` = 0) AND (`id` IN (3, 4));
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(20867, 0, 3, 4, 6, 0, 100, 0, 0, 0, 0, 0, 0, 28, 36657, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Watcher - On Just Died - Remove Aura \'Death Count\''),
(20867, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 28, 38818, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Watcher - On Just Died - Remove Aura \'Death Count\''),
(-138927, 0, 3, 4, 6, 0, 100, 0, 0, 0, 0, 0, 0, 28, 36657, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Watcher - On Just Died - Remove Aura \'Death Count\''),
(-138927, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 28, 38818, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Watcher - On Just Died - Remove Aura \'Death Count\'');
@@ -0,0 +1,3 @@
-- DB update 2023_03_31_01 -> 2023_03_31_02
--
UPDATE `smart_scripts` SET `action_param2` = 2 WHERE `id` = 3 AND `entryorguid` IN (-28368, -27554, -27555, -27794);
@@ -0,0 +1,9 @@
-- DB update 2023_03_31_02 -> 2023_03_31_03
DELETE FROM `smart_scripts` WHERE (`entryorguid` BETWEEN 2087501 AND 2087506) AND (`source_type` = 9) AND (`id` IN (5));
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(2087501, 9, 5, 0, 0, 0, 100, 0, 1500, 1500, 0, 0, 0, 28, 34333, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Negaton Screamer - Actionlist - Remove Aura \'Damage Reduction: Fire\''),
(2087502, 9, 5, 0, 0, 0, 100, 0, 1500, 1500, 0, 0, 0, 28, 34334, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Negaton Screamer - Actionlist - Remove Aura \'Damage Reduction: Frost\''),
(2087503, 9, 5, 0, 0, 0, 100, 0, 1500, 1500, 0, 0, 0, 28, 34331, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Negaton Screamer - Actionlist - Remove Aura \'Damage Reduction: Arcane\''),
(2087504, 9, 5, 0, 0, 0, 100, 0, 1500, 1500, 0, 0, 0, 28, 34335, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Negaton Screamer - Actionlist - Remove Aura \'Damage Reduction: Nature\''),
(2087505, 9, 5, 0, 0, 0, 100, 0, 1500, 1500, 0, 0, 0, 28, 34338, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Negaton Screamer - Actionlist - Remove Aura \'Damage Reduction: Shadow\''),
(2087506, 9, 5, 0, 0, 0, 100, 0, 1500, 1500, 0, 0, 0, 28, 34336, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Negaton Screamer - Actionlist - Remove Aura \'Damage Reduction: Holy\'');
@@ -0,0 +1,8 @@
-- DB update 2023_03_31_03 -> 2023_03_31_04
--
UPDATE `creature_template` SET `AIName` = '' WHERE `entry` = 13696;
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 13696) AND (`source_type` = 0);
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 178908) AND (`source_type` = 1) AND (`id` IN (4));
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(178908, 1, 4, 0, 8, 0, 100, 0, 21885, 0, 0, 0, 0, 50, 178904, 90000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Vylestem Vine - On Spellhit \'Heal Vylestem Vine\' - Summon Gameobject \'Vylestem Vine\'');
@@ -0,0 +1,3 @@
-- DB update 2023_03_31_04 -> 2023_03_31_05
--
UPDATE `creature_onkill_reputation` SET `MaxStanding1` = 7 WHERE (`creature_id` = 26081);
@@ -0,0 +1,12 @@
-- DB update 2023_03_31_05 -> 2023_04_01_00
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` IN (20867, -138927) AND `id` IN (3, 4, 5, 6));
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(20867, 0, 3, 4, 6, 0, 100, 0, 0, 0, 0, 0, 0, 28, 36657, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Watcher - On Just Died - Remove Aura \'Death Count\''),
(20867, 0, 4, 5, 61, 0, 100, 0, 0, 0, 0, 0, 0, 28, 38818, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Watcher - On Just Died - Remove Aura \'Death Count\''),
(20867, 0, 5, 6, 61, 0, 100, 0, 0, 0, 0, 0, 0, 28, 36657, 0, 0, 0, 0, 0, 9, 0, 0, 100, 0, 0, 0, 0, 0, 'Death Watcher - On Just Died - Remove Aura \'Death Count\''),
(20867, 0, 6, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 28, 38818, 0, 0, 0, 0, 0, 9, 0, 0, 100, 0, 0, 0, 0, 0, 'Death Watcher - On Just Died - Remove Aura \'Death Count\''),
(-138927, 0, 3, 4, 6, 0, 100, 0, 0, 0, 0, 0, 0, 28, 36657, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Watcher - On Just Died - Remove Aura \'Death Count\''),
(-138927, 0, 4, 5, 61, 0, 100, 0, 0, 0, 0, 0, 0, 28, 38818, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Watcher - On Just Died - Remove Aura \'Death Count\''),
(-138927, 0, 5, 6, 61, 0, 100, 0, 0, 0, 0, 0, 0, 28, 36657, 0, 0, 0, 0, 0, 9, 0, 0, 100, 0, 0, 0, 0, 0, 'Death Watcher - On Just Died - Remove Aura \'Death Count\''),
(-138927, 0, 6, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 28, 38818, 0, 0, 0, 0, 0, 9, 0, 0, 100, 0, 0, 0, 0, 0, 'Death Watcher - On Just Died - Remove Aura \'Death Count\'');
@@ -0,0 +1,6 @@
-- DB update 2023_04_01_00 -> 2023_04_01_01
--
-- Harbinger Skyriss Normal Loot
UPDATE `reference_loot_template` SET `GroupId`=3 WHERE `Entry`=25004 AND `Item` IN (28413, 28414, 28415, 28416, 28418, 28419);
DELETE FROM `creature_loot_template` WHERE `Entry`=20912 AND `Item`=25004 AND `Reference`=25004 AND `GroupId`=3;
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES (20912, 25004, 25004, 100, 0, 1, 3, 1, 1, 'Harbinger Skyriss - High Value Table (ReferenceTable)');
@@ -0,0 +1,10 @@
-- DB update 2023_04_01_01 -> 2023_04_01_02
--
DELETE FROM `event_scripts` WHERE `id` IN (14592, 14593, 14595);
UPDATE `gameobject_template` SET `AIName` = 'SmartGameObjectAI' WHERE `entry` IN (182196, 182197, 182198);
DELETE FROM `smart_scripts` WHERE (`source_type` = 1 AND `entryorguid` IN (182196, 182197, 182198));
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(182196, 1, 0, 0, 71, 0, 100, 1, 14592, 0, 0, 0, 0, 12, 22890, 4, 300000, 0, 0, 0, 8, 0, 0, 0, 0, -108.252, -510.302, 21.4761, 2.44346, 'Arcane Container - On Event 14592 Inform - Summon Creature \'First Fragment Guardian\''),
(182197, 1, 0, 0, 71, 0, 100, 1, 14593, 0, 0, 0, 0, 12, 22891, 4, 300000, 0, 0, 0, 8, 0, 0, 0, 0, 13.49, -307.87, -66, 3.12, 'Arcane Container - On Event 14593 Inform - Summon Creature \'Second Fragment Guardian\''),
(182198, 1, 0, 0, 71, 0, 100, 1, 14595, 0, 0, 0, 0, 12, 22892, 4, 300000, 0, 0, 0, 8, 0, 0, 0, 0, 312.72, -19.24, 22.44, 2.12, 'Arcane Container - On Event 14595 Inform - Summon Creature \'Third Fragment Guardian\'');
@@ -0,0 +1,6 @@
-- DB update 2023_04_01_02 -> 2023_04_02_00
DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 2202300);
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(2202300, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 0, 0, 0, 19, 22160, 50, 0, 0, 0, 0, 0, 0, '[DND]Spirit 1 - Actionlist - Move To Closest Creature \'Bloodmaul Taskmaster\''),
(2202300, 9, 1, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 0, 69, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '[DND]Spirit 1 - Actionlist - Move To Invoker'),
(2202300, 9, 2, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 0, 33, 22383, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '[DND]Spirit 1 - Actionlist - Quest Credit \'On Spirit\'s Wings\'');
@@ -0,0 +1,24 @@
-- DB update 2023_04_02_00 -> 2023_04_02_01
-- Mote of Shadow
DELETE FROM `creature_loot_template` WHERE `Item` = 22577;
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(16974, 22577, 0, 20, 0, 1, 0, 1, 1, 'Rogue Voidwalker - Mote of Shadow'),
(16975, 22577, 0, 20, 0, 1, 0, 1, 1, 'Uncontrolled Voidwalker - Mote of Shadow'),
(17014, 22577, 0, 20, 0, 1, 0, 1, 2, 'Collapsing Voidwalker - Mote of Shadow'),
(17981, 22577, 0, 18.6912, 0, 1, 0, 1, 2, 'Voidspawn - Mote of Shadow'),
(18683, 22577, 0, 25, 0, 1, 0, 1, 2, 'Voidhunter Yar - Mote of Shadow'),
(18869, 22577, 0, 1.0615, 0, 1, 0, 1, 2, 'Unstable Voidwraith - Mote of Shadow'),
(18870, 22577, 0, 1.0194, 0, 1, 0, 1, 2, 'Voidshrieker - Mote of Shadow'),
(19307, 22577, 0, 17.8397, 0, 1, 0, 1, 4, 'Nexus Terror - Mote of Shadow'),
(19527, 22577, 0, 20, 0, 1, 0, 1, 2, 'Vacillating Voidcaller - Mote of Shadow'),
(19554, 22577, 0, 60, 0, 1, 0, 2, 4, 'Dimensius the All-Devouring - Mote of Shadow'),
(20554, 22577, 0, 26.6608, 0, 1, 0, 1, 2, 'Arconus the Insatiable - Mote of Shadow'),
(20873, 22577, 0, 31.15, 0, 1, 0, 2, 4, 'Negaton Warp-Master - Mote of Shadow'),
(20875, 22577, 0, 30.59, 0, 1, 0, 2, 4, 'Negaton Screamer - Mote of Shadow'),
(22295, 22577, 0, 27.0833, 0, 1, 0, 2, 4, 'Deathforge Automaton - Mote of Shadow'),
(22301, 22577, 0, 37.8378, 0, 1, 0, 1, 2, 'Throne-Guard Sentinel - Mote of Shadow'),
-- Previously missing, from TrinityCore
(19299, 22577, 0, 42.4242, 0, 1, 0, 2, 4,'Deathwhisperer - Mote of Shadow'),
(20870, 22577, 0, 15, 0, 1, 0, 2, 4, 'Zereketh the Unbound - Mote of Shadow'),
(18341, 22577, 0, 15, 0, 1, 0, 2, 4, 'Pandemonius - Mote of Shadow'),
(19354, 22577, 0, 19.0751, 0, 1, 0, 2, 4, 'Arzeth the Merciless - Mote of Shadow');
@@ -0,0 +1,2 @@
-- DB update 2023_04_02_01 -> 2023_04_02_02
UPDATE `smart_scripts` SET `event_type` = 25 AND `comment` = 'Arcatraz Sentinel - On Reset - Set Health 40%' WHERE `source_type` = 0 AND `entryorguid` = 20869 AND `id` = 0;
@@ -0,0 +1,2 @@
-- DB update 2023_04_02_02 -> 2023_04_02_03
UPDATE `creature_template_addon` SET `mount` = 17697 WHERE (`entry` = 35101);
@@ -0,0 +1,8 @@
-- DB update 2023_04_02_03 -> 2023_04_02_04
--
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 2179700) AND (`source_type` = 9) AND (`id` IN (12));
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(2179700, 9, 12, 0, 0, 0, 100, 512, 0, 0, 0, 0, 0, 41, 300000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Ancient Shadowmoon Spirit - Actionlist - Despawn In 300000 ms');
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 21797) AND (`source_type` = 0) AND (`id` IN (9));
@@ -0,0 +1,4 @@
-- DB update 2023_04_02_04 -> 2023_04_02_05
--
ALTER TABLE `spell_enchant_proc_data` ADD COLUMN `attributeMask` INT UNSIGNED DEFAULT 0 NOT NULL AFTER `procEx`;
UPDATE `spell_enchant_proc_data` SET `attributeMask`=1 WHERE `entry`=3225;
@@ -0,0 +1,8 @@
-- DB update 2023_04_02_05 -> 2023_04_02_06
--
DELETE FROM `smart_scripts` WHERE (`entryorguid` IN (-138927, 20867)) AND (`source_type` = 0) AND (`id` IN (1, 2));
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(20867, 0, 1, 0, 2, 0, 100, 0, 0, 75, 15000, 15000, 0, 11, 36655, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Watcher - Between 0-75% Health - Cast \'Drain Life\''),
(20867, 0, 2, 0, 2, 0, 100, 1, 0, 50, 0, 0, 0, 11, 36657, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Watcher - Between 0-50% Health - Cast \'Death Count\' (No Repeat)'),
(-138927, 0, 1, 0, 2, 0, 100, 0, 0, 75, 15000, 15000, 0, 11, 36655, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Watcher - Between 0-75% Health - Cast \'Drain Life\''),
(-138927, 0, 2, 0, 2, 0, 100, 1, 0, 50, 0, 0, 0, 11, 36657, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Watcher - Between 0-50% Health - Cast \'Death Count\' (No Repeat)');
@@ -0,0 +1,7 @@
-- DB update 2023_04_02_06 -> 2023_04_02_07
--
UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|46284631 WHERE (`entry` IN (20866, 21614, 20898, 21598));
UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|652689279 WHERE (`entry` IN (20870, 21626, 20912, 21601));
UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|37882897 WHERE (`entry` IN (20875, 21604));
UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|3089, `flags_extra`=`flags_extra`|256 WHERE (`entry` IN (20883, 21615));
UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|16405, `flags_extra`=`flags_extra`|256 WHERE (`entry` IN (20869, 21586));
@@ -0,0 +1,11 @@
-- DB update 2023_04_02_07 -> 2023_04_02_08
--
-- Warlord Kalithresh Normal Loot Repairs
UPDATE `creature_loot_template` SET `GroupId`=0 WHERE `Entry`=17798 AND `Item`=23572 AND `Reference`=0 AND `GroupId`=3;
UPDATE `creature_loot_template` SET `MaxCount`=1 WHERE `Entry`=17798 AND `Item`=35001 AND `Reference`=35001 AND `GroupId`=2;
UPDATE `reference_loot_template` SET `GroupId`=3 WHERE `Entry`=35001 AND `Item` IN (27475, 27510, 27804, 27805, 27806, 27874);
DELETE FROM `creature_loot_template` WHERE `Entry`=17798 AND `Item`=24313;
DELETE FROM `creature_loot_template` WHERE `Entry`=17798 AND `Item`=35001 AND `Reference`=35001 AND `GroupId`=3;
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(17798, 24313, 0, 3.25, 0, 1, 0, 1, 1, 'Warlord Kalithresh - Pattern: Battlecast Hood'),
(17798, 35001, 35001, 100, 0, 1, 3, 1, 1, 'Warlord Kalithresh Table B - (ReferenceTable)');
@@ -0,0 +1,34 @@
-- DB update 2023_04_02_08 -> 2023_04_02_09
-- Form Rhok'delar and Lok'delar at once
DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=23192;
INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES (23192, 24872, 0, 'Form Rhok\'delar and Lok\'delar at once ');
-- Gossip_menu_option (30201) conditions (QUEST_REWARDED & _ITEM)
-- Require both quests 7636(Stave of the Ancients) & 7635(A Proper String) to be rewarded, to not have either Sinew or Rune and to not have either Bow or Stave.
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 15 AND `SourceGroup` = 30201;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(15, 30201, 0, 0, 0, 8, 0, 7636, 0, 0, 0, 0, 0, '', '(AND) Require quest 7636(Stave of the Ancients) to be rewarded.'),
(15, 30201, 0, 0, 0, 8, 0, 7635, 0, 0, 0, 0, 0, '', '(AND) Require quest 7635(A Proper String) to be rewarded.'),
(15, 30201, 0, 0, 0, 2, 0, 18713, 1, 1, 1, 0, 0, '', '(AND) Require item 18713(Rhok\'delar) to not be in inventory or bank.'),
(15, 30201, 0, 0, 0, 2, 0, 18707, 1, 1, 1, 0, 0, '', '(AND) Require item 18707(Ancient Rune Etched Stave) to not be in inventory or bank.'),
(15, 30201, 0, 0, 0, 2, 0, 18724, 1, 1, 1, 0, 0, '', '(AND) Require item 18724(Enchanted Black Dragon Sinew) to not be in inventory or bank.'),
(15, 30201, 1, 0, 0, 8, 0, 7636, 0, 0, 0, 0, 0, '', '(AND) Require quest 7636(Stave of the Ancients) to be rewarded.'),
(15, 30201, 1, 0, 0, 8, 0, 7635, 0, 0, 0, 0, 0, '', '(AND) Require quest 7635(A Proper String) to be rewarded.'),
(15, 30201, 1, 0, 0, 2, 0, 18715, 1, 1, 1, 0, 0, '', '(AND) Require item 18715(Lok\'delar) to not be in inventory or bank.'),
(15, 30201, 1, 0, 0, 2, 0, 18707, 1, 1, 1, 0, 0, '', '(AND) Require item 18707(Ancient Rune Etched Stave) to not be in inventory or bank.'),
(15, 30201, 1, 0, 0, 2, 0, 18724, 1, 1, 1, 0, 0, '', '(AND) Require item 18724(Enchanted Black Dragon Sinew) to not be in inventory or bank.');
-- Vartus the Ancient
DELETE FROM `gossip_menu_option` WHERE `MenuID`=30201;
INSERT INTO `gossip_menu_option` (`MenuID`, `OptionID`, `OptionIcon`, `OptionText`, `OptionBroadcastTextID`, `OptionType`, `OptionNpcFlag`, `ActionMenuID`, `ActionPoiID`, `BoxCoded`, `BoxMoney`, `BoxText`, `BoxBroadcastTextID`, `VerifiedBuild`) VALUES
(30201, 0, 0, 'Greetings, ancient one. I have done all that has been asked of me. I now ask that you grant me Rhok\'delar.', 10784, 1, 1, 0, 0, 0, 0, '', 0, 0),
(30201, 1, 0, 'Greetings, ancient one. I have done all that has been asked of me. I now ask that you grant me Lok\'delar.', 10785, 1, 1, 0, 0, 0, 0, '', 0, 0);
-- SAI
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 14524;
DELETE FROM `smart_scripts` WHERE `entryorguid` = 14524;
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(14524, 0, 0, 2, 62, 0, 100, 0, 30201, 0, 0, 0, 0, 56, 18713, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Vartrus the Ancient - On Gossip Option 0 Selected - Add Item \'Rhok\'delar, Longbow of the Ancient Keepers\' '),
(14524, 0, 1, 2, 62, 0, 100, 0, 30201, 1, 0, 0, 0, 56, 18715, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Vartrus the Ancient - On Gossip Option 1 Selected - Add Item \'Lok\'delar, Stave of the Ancient Keepers\''),
(14524, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Vartrus the Ancient - On Gossip Option - Close Gossip');
@@ -0,0 +1,7 @@
-- DB update 2023_04_02_09 -> 2023_04_02_10
--
DELETE FROM `reference_loot_template` WHERE `Entry` = 24076 AND `Item` = 1927;
DELETE FROM `creature_loot_template` WHERE `Entry` = 594 AND `Item` = 1927;
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(594,1927,0,6,0,1,1,1,1,'Defias Henchman - Deadmines Cleaver');
@@ -0,0 +1,5 @@
-- DB update 2023_04_02_10 -> 2023_04_02_11
--
DELETE FROM `spell_proc_event` WHERE `entry`=43730;
INSERT INTO `spell_proc_event` (`entry`, `SchoolMask`, `SpellFamilyName`, `SpellFamilyMask0`, `SpellFamilyMask1`, `SpellFamilyMask2`, `procFlags`, `procEx`, `procPhase`, `ppmRate`, `CustomChance`, `Cooldown`) VALUES
(43730,0,0,0,0,0,0,0,2,0,0,8000);
@@ -0,0 +1,13 @@
-- DB update 2023_04_02_11 -> 2023_04_03_00
--
SET @PATH = 36853 * 10;
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH, 1, 4551.7847, 2444.7153, 228.58171,0,0,0,0,100,0),
(@PATH, 2, 4555.238, 2370.889, 229.2206,0,0,0,0,100,0),
(@PATH, 3, 4617.6616, 2352.2952, 214.60947,0,0,0,0,100,0),
(@PATH, 4, 4673.6704, 2437.1182, 218.91505,0,0,0,0,100,0),
(@PATH, 5, 4659.0747, 2579.3906, 229.49834,0,0,0,0,100,0),
(@PATH, 6, 4591.4316, 2598.192, 229.97064,0,0,0,0,100,0),
(@PATH, 7, 4564.4287, 2562.0461, 230.72063,0,0,0,0,100,0),
(@PATH, 8, 4555.6953, 2487.9895, 229.9706,0,0,0,0,100,0);
+63 -12
View File
@@ -72,13 +72,15 @@ char serviceDescription[] = "AzerothCore World of Warcraft emulator world servic
* 2 - paused * 2 - paused
*/ */
int m_ServiceStatus = -1; int m_ServiceStatus = -1;
#include <boost/dll/shared_library.hpp>
#include <timeapi.h>
#endif #endif
#ifndef _ACORE_CORE_CONFIG #ifndef _ACORE_CORE_CONFIG
#define _ACORE_CORE_CONFIG "worldserver.conf" #define _ACORE_CORE_CONFIG "worldserver.conf"
#endif #endif
#define WORLD_SLEEP_CONST 10
using namespace boost::program_options; using namespace boost::program_options;
namespace fs = std::filesystem; namespace fs = std::filesystem;
@@ -137,6 +139,44 @@ int main(int argc, char** argv)
return WinServiceUninstall() == true ? 0 : 1; return WinServiceUninstall() == true ? 0 : 1;
else if (configService.compare("run") == 0) else if (configService.compare("run") == 0)
WinServiceRun(); WinServiceRun();
Optional<UINT> newTimerResolution;
boost::system::error_code dllError;
std::shared_ptr<boost::dll::shared_library> winmm(new boost::dll::shared_library("winmm.dll", dllError, boost::dll::load_mode::search_system_folders), [&](boost::dll::shared_library* lib)
{
try
{
if (newTimerResolution)
lib->get<decltype(timeEndPeriod)>("timeEndPeriod")(*newTimerResolution);
}
catch (std::exception const&)
{
// ignore
}
delete lib;
});
if (winmm->is_loaded())
{
try
{
auto timeGetDevCapsPtr = winmm->get<decltype(timeGetDevCaps)>("timeGetDevCaps");
// setup timer resolution
TIMECAPS timeResolutionLimits;
if (timeGetDevCapsPtr(&timeResolutionLimits, sizeof(TIMECAPS)) == TIMERR_NOERROR)
{
auto timeBeginPeriodPtr = winmm->get<decltype(timeBeginPeriod)>("timeBeginPeriod");
newTimerResolution = std::min(std::max(timeResolutionLimits.wPeriodMin, 1u), timeResolutionLimits.wPeriodMax);
timeBeginPeriodPtr(*newTimerResolution);
}
}
catch (std::exception const& e)
{
printf("Failed to initialize timer resolution: %s\n", e.what());
}
}
#endif #endif
// Add file and args in config // Add file and args in config
@@ -530,9 +570,15 @@ void ShutdownCLIThread(std::thread* cliThread)
void WorldUpdateLoop() void WorldUpdateLoop()
{ {
uint32 minUpdateDiff = uint32(sConfigMgr->GetOption<int32>("MinWorldUpdateTime", 1));
uint32 realCurrTime = 0; uint32 realCurrTime = 0;
uint32 realPrevTime = getMSTime(); uint32 realPrevTime = getMSTime();
uint32 maxCoreStuckTime = uint32(sConfigMgr->GetOption<int32>("MaxCoreStuckTime", 60)) * 1000;
uint32 halfMaxCoreStuckTime = maxCoreStuckTime / 2;
if (!halfMaxCoreStuckTime)
halfMaxCoreStuckTime = std::numeric_limits<uint32>::max();
LoginDatabase.WarnAboutSyncQueries(true); LoginDatabase.WarnAboutSyncQueries(true);
CharacterDatabase.WarnAboutSyncQueries(true); CharacterDatabase.WarnAboutSyncQueries(true);
WorldDatabase.WarnAboutSyncQueries(true); WorldDatabase.WarnAboutSyncQueries(true);
@@ -546,18 +592,19 @@ void WorldUpdateLoop()
realCurrTime = getMSTime(); realCurrTime = getMSTime();
uint32 diff = getMSTimeDiff(realPrevTime, realCurrTime); uint32 diff = getMSTimeDiff(realPrevTime, realCurrTime);
if (diff < minUpdateDiff)
{
uint32 sleepTime = minUpdateDiff - diff;
if (sleepTime >= halfMaxCoreStuckTime)
LOG_ERROR("server.worldserver", "WorldUpdateLoop() waiting for {} ms with MaxCoreStuckTime set to {} ms", sleepTime, maxCoreStuckTime);
// sleep until enough time passes that we can update all timers
std::this_thread::sleep_for(Milliseconds(sleepTime));
continue;
}
sWorld->Update(diff); sWorld->Update(diff);
realPrevTime = realCurrTime; realPrevTime = realCurrTime;
uint32 executionTimeDiff = getMSTimeDiff(realCurrTime, getMSTime());
// we know exactly how long it took to update the world, if the update took less than WORLD_SLEEP_CONST, sleep for WORLD_SLEEP_CONST - world update time
if (executionTimeDiff < WORLD_SLEEP_CONST)
{
std::this_thread::sleep_for(Milliseconds(WORLD_SLEEP_CONST - executionTimeDiff));
}
#ifdef _WIN32 #ifdef _WIN32
if (m_ServiceStatus == 0) if (m_ServiceStatus == 0)
World::StopNow(SHUTDOWN_EXIT_CODE); World::StopNow(SHUTDOWN_EXIT_CODE);
@@ -595,10 +642,14 @@ void FreezeDetector::Handler(std::weak_ptr<FreezeDetector> freezeDetectorRef, bo
freezeDetector->_worldLoopCounter = worldLoopCounter; freezeDetector->_worldLoopCounter = worldLoopCounter;
} }
// possible freeze // possible freeze
else if (getMSTimeDiff(freezeDetector->_lastChangeMsTime, curtime) > freezeDetector->_maxCoreStuckTimeInMs) else
{ {
LOG_ERROR("server.worldserver", "World Thread hangs, kicking out server!"); uint32 msTimeDiff = getMSTimeDiff(freezeDetector->_lastChangeMsTime, curtime);
ABORT(); if (msTimeDiff > freezeDetector->_maxCoreStuckTimeInMs)
{
LOG_ERROR("server.worldserver", "World Thread hangs for {} ms, forcing a crash!", msTimeDiff);
ABORT("World Thread hangs for {} ms, forcing a crash!", msTimeDiff);
}
} }
freezeDetector->_timer.expires_from_now(boost::posix_time::seconds(1)); freezeDetector->_timer.expires_from_now(boost::posix_time::seconds(1));
@@ -339,12 +339,19 @@ SocketTimeOutTimeActive = 60000
SessionAddDelay = 10000 SessionAddDelay = 10000
#
# MinWorldUpdateTime
# Description: Minimum time (milliseconds) between world update ticks (for mostly idle servers).
# Default: 1 - (0.001 second)
MinWorldUpdateTime = 1
# #
# MapUpdateInterval # MapUpdateInterval
# Description: Time (milliseconds) for map update interval. # Description: Time (milliseconds) for map update interval.
# Default: 100 - (0.1 second) # Default: 10 - (0.01 second)
MapUpdateInterval = 100 MapUpdateInterval = 10
# #
# ChangeWeatherInterval # ChangeWeatherInterval
@@ -467,6 +474,7 @@ LogDB.Opt.ClearTime = 1209600
# #
# MaxCoreStuckTime # MaxCoreStuckTime
# Description: Time (in seconds) before the server is forced to crash if it is frozen. # Description: Time (in seconds) before the server is forced to crash if it is frozen.
# FreezeDetector
# Default: 0 - (Disabled) # Default: 0 - (Disabled)
# 10+ - (Enabled, Recommended 30+) # 10+ - (Enabled, Recommended 30+)
# Note: If enabled and the setting is too low, it can cause unexpected crash. # Note: If enabled and the setting is too low, it can cause unexpected crash.
@@ -3905,7 +3905,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
if (!me || !me->IsEngaged()) if (!me || !me->IsEngaged())
return; return;
ObjectVector targets; Unit* unitTarget = nullptr;
switch (e.GetTargetType()) switch (e.GetTargetType())
{ {
case SMART_TARGET_CREATURE_RANGE: case SMART_TARGET_CREATURE_RANGE:
@@ -3916,8 +3916,8 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
case SMART_TARGET_PLAYER_RANGE: case SMART_TARGET_PLAYER_RANGE:
case SMART_TARGET_PLAYER_DISTANCE: case SMART_TARGET_PLAYER_DISTANCE:
{ {
if (targets.empty()) ObjectVector targets;
return; GetTargets(targets, e);
for (WorldObject* target : targets) for (WorldObject* target : targets)
{ {
if (IsUnit(target) && me->IsFriendlyTo(target->ToUnit()) && target->ToUnit()->IsAlive() && target->ToUnit()->IsInCombat()) if (IsUnit(target) && me->IsFriendlyTo(target->ToUnit()) && target->ToUnit()->IsAlive() && target->ToUnit()->IsInCombat())
@@ -3928,7 +3928,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
continue; continue;
} }
target = target->ToUnit(); unitTarget = target->ToUnit();
break; break;
} }
} }
@@ -3937,16 +3937,16 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
} }
case SMART_TARGET_SELF: case SMART_TARGET_SELF:
case SMART_TARGET_ACTION_INVOKER: case SMART_TARGET_ACTION_INVOKER:
DoSelectLowestHpPercentFriendly((float)e.event.friendlyHealthPct.radius, e.event.friendlyHealthPct.minHpPct, e.event.friendlyHealthPct.maxHpPct); unitTarget = DoSelectLowestHpPercentFriendly((float)e.event.friendlyHealthPct.radius, e.event.friendlyHealthPct.minHpPct, e.event.friendlyHealthPct.maxHpPct);
break; break;
default: default:
return; return;
} }
if (targets.empty()) if (!unitTarget)
return; return;
ProcessTimedAction(e, e.event.friendlyHealthPct.repeatMin, e.event.friendlyHealthPct.repeatMax); ProcessTimedAction(e, e.event.friendlyHealthPct.repeatMin, e.event.friendlyHealthPct.repeatMax, unitTarget);
break; break;
} }
case SMART_EVENT_DISTANCE_CREATURE: case SMART_EVENT_DISTANCE_CREATURE:
+23 -1
View File
@@ -2101,34 +2101,52 @@ void Pet::resetTalentsForAllPetsOf(Player* owner, Pet* onlinePet /*= nullptr*/)
{ {
// not need after this call // not need after this call
if (owner->ToPlayer()->HasAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS)) if (owner->ToPlayer()->HasAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS))
{
owner->ToPlayer()->RemoveAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS, true); owner->ToPlayer()->RemoveAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS, true);
}
// reset for online // reset for online
if (onlinePet) if (onlinePet)
{
onlinePet->resetTalents(); onlinePet->resetTalents();
}
PetStable* petStable = owner->GetPetStable(); PetStable* petStable = owner->GetPetStable();
if (!petStable) if (!petStable)
{
return; return;
}
std::unordered_set<uint32> petIds; std::unordered_set<uint32> petIds;
if (petStable->CurrentPet) if (petStable->CurrentPet)
{
petIds.insert(petStable->CurrentPet->PetNumber); petIds.insert(petStable->CurrentPet->PetNumber);
}
for (Optional<PetStable::PetInfo> const& stabledPet : petStable->StabledPets) for (Optional<PetStable::PetInfo> const& stabledPet : petStable->StabledPets)
{
if (stabledPet) if (stabledPet)
{
petIds.insert(stabledPet->PetNumber); petIds.insert(stabledPet->PetNumber);
}
}
for (PetStable::PetInfo const& unslottedPet : petStable->UnslottedPets) for (PetStable::PetInfo const& unslottedPet : petStable->UnslottedPets)
{
petIds.insert(unslottedPet.PetNumber); petIds.insert(unslottedPet.PetNumber);
}
// now need only reset for offline pets (all pets except online case) // now need only reset for offline pets (all pets except online case)
if (onlinePet) if (onlinePet)
{
petIds.erase(onlinePet->GetCharmInfo()->GetPetNumber()); petIds.erase(onlinePet->GetCharmInfo()->GetPetNumber());
}
// no offline pets // no offline pets
if (!petIds.empty()) if (petIds.empty())
{
return; return;
}
bool need_comma = false; bool need_comma = false;
std::ostringstream ss; std::ostringstream ss;
@@ -2137,7 +2155,9 @@ void Pet::resetTalentsForAllPetsOf(Player* owner, Pet* onlinePet /*= nullptr*/)
for (uint32 id : petIds) for (uint32 id : petIds)
{ {
if (need_comma) if (need_comma)
{
ss << ','; ss << ',';
}
ss << id; ss << id;
@@ -2150,7 +2170,9 @@ void Pet::resetTalentsForAllPetsOf(Player* owner, Pet* onlinePet /*= nullptr*/)
for (uint32 spell : sPetTalentSpells) for (uint32 spell : sPetTalentSpells)
{ {
if (need_comma) if (need_comma)
{
ss << ','; ss << ',';
}
ss << spell; ss << spell;
+18 -5
View File
@@ -1462,7 +1462,10 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
else else
{ {
if (getClass() == CLASS_DEATH_KNIGHT && GetMapId() == 609 && !IsGameMaster() && !HasSpell(50977)) if (getClass() == CLASS_DEATH_KNIGHT && GetMapId() == 609 && !IsGameMaster() && !HasSpell(50977))
{
SendTransferAborted(mapid, TRANSFER_ABORT_UNIQUE_MESSAGE, 1);
return false; return false;
}
// far teleport to another map // far teleport to another map
Map* oldmap = IsInWorld() ? GetMap() : nullptr; Map* oldmap = IsInWorld() ? GetMap() : nullptr;
@@ -6824,8 +6827,10 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt
if (extraDPS) if (extraDPS)
{ {
float average = extraDPS * proto->Delay / 1000.0f; float average = extraDPS * proto->Delay / 1000.0f;
minDamage = 0.7f * average; float mod = ssv->IsTwoHand(proto->ScalingStatValue) ? 0.2f : 0.3f;
maxDamage = 1.3f * average;
minDamage = (1.0f - mod) * average;
maxDamage = (1.0f + mod) * average;
} }
} }
@@ -7220,6 +7225,15 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
continue; continue;
} }
if (entry && (entry->attributeMask & ENCHANT_PROC_ATTR_EXCLUSIVE) != 0)
{
Unit* checkTarget = spellInfo->IsPositive() ? this : target;
if (checkTarget->HasAura(spellInfo->Id, GetGUID()))
{
continue;
}
}
float chance = pEnchant->amount[s] != 0 ? float(pEnchant->amount[s]) : GetWeaponProcChance(); float chance = pEnchant->amount[s] != 0 ? float(pEnchant->amount[s]) : GetWeaponProcChance();
if (entry) if (entry)
@@ -11579,7 +11593,6 @@ void Player::SendInitialPacketsAfterAddToMap()
SendMessageToSet(&data2, true); SendMessageToSet(&data2, true);
} }
GetAurasForTarget(this);
SendEnchantmentDurations(); // must be after add to map SendEnchantmentDurations(); // must be after add to map
SendItemDurations(); // must be after add to map SendItemDurations(); // must be after add to map
SendQuestGiverStatusMultiple(); SendQuestGiverStatusMultiple();
@@ -11960,9 +11973,9 @@ void Player::learnSkillRewardedSpells(uint32 skill_id, uint32 skill_value)
} }
} }
void Player::GetAurasForTarget(Unit* target) // pussywizard: contact before changing ANYTHING! void Player::GetAurasForTarget(Unit* target, bool force /*= false*/)
{ {
if (!target/* || target->GetVisibleAuras()->empty()*/) // speedup things if (!target || (!force && target->GetVisibleAuras()->empty())) // speedup things
return; return;
/*! Blizz sends certain movement packets sometimes even before CreateObject /*! Blizz sends certain movement packets sometimes even before CreateObject
+1 -1
View File
@@ -2183,7 +2183,7 @@ public:
void SendBGWeekendWorldStates(); void SendBGWeekendWorldStates();
void SendBattlefieldWorldStates(); void SendBattlefieldWorldStates();
void GetAurasForTarget(Unit* target); void GetAurasForTarget(Unit* target, bool force = false);
PlayerMenu* PlayerTalkClass; PlayerMenu* PlayerTalkClass;
std::vector<ItemSetEffect*> ItemSetEff; std::vector<ItemSetEffect*> ItemSetEff;
+31 -14
View File
@@ -3822,6 +3822,8 @@ void Unit::_UpdateSpells(uint32 time)
{ {
if (i->second->IsExpired()) if (i->second->IsExpired())
RemoveOwnedAura(i, AURA_REMOVE_BY_EXPIRE); RemoveOwnedAura(i, AURA_REMOVE_BY_EXPIRE);
else if (i->second->GetSpellInfo()->IsChanneled() && i->second->GetCasterGUID() != GetGUID() && !ObjectAccessor::GetWorldObject(*this, i->second->GetCasterGUID()))
RemoveOwnedAura(i, AURA_REMOVE_BY_CANCEL); // remove channeled auras when caster is not on the same map
else else
++i; ++i;
} }
@@ -6498,11 +6500,12 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit* target, uint8 /*SwingType
} }
//victim may be nullptr //victim may be nullptr
bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, Spell const* spellProc /*= nullptr*/) bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, ProcEventInfo const& eventInfo)
{ {
SpellInfo const* dummySpell = triggeredByAura->GetSpellInfo(); SpellInfo const* dummySpell = triggeredByAura->GetSpellInfo();
uint32 effIndex = triggeredByAura->GetEffIndex(); uint32 effIndex = triggeredByAura->GetEffIndex();
int32 triggerAmount = triggeredByAura->GetAmount(); int32 triggerAmount = triggeredByAura->GetAmount();
Spell const* spellProc = eventInfo.GetProcSpell();
Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER
? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : nullptr; ? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : nullptr;
@@ -7864,12 +7867,22 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
if (!procSpell || !procSpell->IsPositive()) if (!procSpell || !procSpell->IsPositive())
return false; return false;
// heal amount HealInfo const* healInfo = eventInfo.GetHealInfo();
basepoints0 = int32(CalculatePct(std::min(damage, GetMaxHealth() - GetHealth()), triggerAmount)); if (!healInfo)
target = this; {
return false;
}
if (basepoints0) uint32 effectiveHeal = healInfo->GetEffectiveHeal();
triggered_spell_id = 31786; if (effectiveHeal)
{
// heal amount
basepoints0 = int32(CalculatePct(effectiveHeal, triggerAmount));
target = this;
if (basepoints0)
triggered_spell_id = 31786;
}
break; break;
} }
// Paladin Tier 6 Trinket (Ashtongue Talisman of Zeal) // Paladin Tier 6 Trinket (Ashtongue Talisman of Zeal)
@@ -11202,16 +11215,18 @@ void Unit::UnsummonAllTotems(bool onDeath /*= false*/)
} }
} }
void Unit::SendHealSpellLog(Unit* victim, uint32 SpellID, uint32 Damage, uint32 OverHeal, uint32 Absorb, bool critical) void Unit::SendHealSpellLog(HealInfo const& healInfo, bool critical)
{ {
uint32 overheal = healInfo.GetHeal() - healInfo.GetEffectiveHeal();
// we guess size // we guess size
WorldPacket data(SMSG_SPELLHEALLOG, (8 + 8 + 4 + 4 + 4 + 4 + 1 + 1)); WorldPacket data(SMSG_SPELLHEALLOG, (8 + 8 + 4 + 4 + 4 + 4 + 1 + 1));
data << victim->GetPackGUID(); data << healInfo.GetTarget()->GetPackGUID();
data << GetPackGUID(); data << GetPackGUID();
data << uint32(SpellID); data << uint32(healInfo.GetSpellInfo()->Id);
data << uint32(Damage); data << uint32(healInfo.GetHeal());
data << uint32(OverHeal); data << uint32(overheal);
data << uint32(Absorb); // Absorb amount data << uint32(healInfo.GetAbsorb()); // Absorb amount
data << uint8(critical ? 1 : 0); data << uint8(critical ? 1 : 0);
data << uint8(0); // unused data << uint8(0); // unused
SendMessageToSet(&data, true); SendMessageToSet(&data, true);
@@ -11227,7 +11242,9 @@ int32 Unit::HealBySpell(HealInfo& healInfo, bool critical)
CalcHealAbsorb(healInfo); CalcHealAbsorb(healInfo);
int32 gain = Unit::DealHeal(healInfo.GetHealer(), healInfo.GetTarget(), healInfo.GetHeal()); int32 gain = Unit::DealHeal(healInfo.GetHealer(), healInfo.GetTarget(), healInfo.GetHeal());
SendHealSpellLog(healInfo.GetTarget(), healInfo.GetSpellInfo()->Id, healInfo.GetHeal(), uint32(healInfo.GetHeal() - gain), healInfo.GetAbsorb(), critical); healInfo.SetEffectiveHeal(gain);
SendHealSpellLog(healInfo, critical);
return gain; return gain;
} }
@@ -16555,7 +16572,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
case SPELL_AURA_DUMMY: case SPELL_AURA_DUMMY:
{ {
LOG_DEBUG("spells.aura", "ProcDamageAndSpell: casting spell id {} (triggered by {} dummy aura of spell {})", spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId()); LOG_DEBUG("spells.aura", "ProcDamageAndSpell: casting spell id {} (triggered by {} dummy aura of spell {})", spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
if (HandleDummyAuraProc(target, damage, triggeredByAura, procSpellInfo, procFlag, procExtra, cooldown, procSpell)) if (HandleDummyAuraProc(target, damage, triggeredByAura, procSpellInfo, procFlag, procExtra, cooldown, eventInfo))
takeCharges = true; takeCharges = true;
break; break;
} }
+14 -2
View File
@@ -806,6 +806,7 @@ private:
Unit* const m_healer; Unit* const m_healer;
Unit* const m_target; Unit* const m_target;
uint32 m_heal; uint32 m_heal;
uint32 m_effectiveHeal;
uint32 m_absorb; uint32 m_absorb;
SpellInfo const* const m_spellInfo; SpellInfo const* const m_spellInfo;
SpellSchoolMask const m_schoolMask; SpellSchoolMask const m_schoolMask;
@@ -814,12 +815,17 @@ public:
: m_healer(_healer), m_target(_target), m_heal(_heal), m_spellInfo(_spellInfo), m_schoolMask(_schoolMask) : m_healer(_healer), m_target(_target), m_heal(_heal), m_spellInfo(_spellInfo), m_schoolMask(_schoolMask)
{ {
m_absorb = 0; m_absorb = 0;
m_effectiveHeal = 0;
} }
void AbsorbHeal(uint32 amount) void AbsorbHeal(uint32 amount)
{ {
amount = std::min(amount, GetHeal()); amount = std::min(amount, GetHeal());
m_absorb += amount; m_absorb += amount;
m_heal -= amount; m_heal -= amount;
amount = std::min(amount, GetEffectiveHeal());
m_effectiveHeal -= amount;
} }
void SetHeal(uint32 amount) void SetHeal(uint32 amount)
@@ -827,9 +833,15 @@ public:
m_heal = amount; m_heal = amount;
} }
void SetEffectiveHeal(uint32 amount)
{
m_effectiveHeal = amount;
}
[[nodiscard]] Unit* GetHealer() const { return m_healer; } [[nodiscard]] Unit* GetHealer() const { return m_healer; }
[[nodiscard]] Unit* GetTarget() const { return m_target; } [[nodiscard]] Unit* GetTarget() const { return m_target; }
[[nodiscard]] uint32 GetHeal() const { return m_heal; } [[nodiscard]] uint32 GetHeal() const { return m_heal; }
[[nodiscard]] uint32 GetEffectiveHeal() const { return m_effectiveHeal; }
[[nodiscard]] uint32 GetAbsorb() const { return m_absorb; } [[nodiscard]] uint32 GetAbsorb() const { return m_absorb; }
[[nodiscard]] SpellInfo const* GetSpellInfo() const { return m_spellInfo; }; [[nodiscard]] SpellInfo const* GetSpellInfo() const { return m_spellInfo; };
[[nodiscard]] SpellSchoolMask GetSchoolMask() const { return m_schoolMask; }; [[nodiscard]] SpellSchoolMask GetSchoolMask() const { return m_schoolMask; };
@@ -1724,7 +1736,7 @@ public:
[[nodiscard]] virtual bool IsUnderWater() const; [[nodiscard]] virtual bool IsUnderWater() const;
bool isInAccessiblePlaceFor(Creature const* c) const; bool isInAccessiblePlaceFor(Creature const* c) const;
void SendHealSpellLog(Unit* victim, uint32 SpellID, uint32 Damage, uint32 OverHeal, uint32 Absorb, bool critical = false); void SendHealSpellLog(HealInfo const& healInfo, bool critical = false);
int32 HealBySpell(HealInfo& healInfo, bool critical = false); int32 HealBySpell(HealInfo& healInfo, bool critical = false);
void SendEnergizeSpellLog(Unit* victim, uint32 SpellID, uint32 Damage, Powers powertype); void SendEnergizeSpellLog(Unit* victim, uint32 SpellID, uint32 Damage, Powers powertype);
void EnergizeBySpell(Unit* victim, uint32 SpellID, uint32 Damage, Powers powertype); void EnergizeBySpell(Unit* victim, uint32 SpellID, uint32 Damage, Powers powertype);
@@ -2551,7 +2563,7 @@ protected:
private: private:
bool IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent, ProcEventInfo const& eventInfo); bool IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent, ProcEventInfo const& eventInfo);
bool HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, Spell const* spellProc = nullptr); bool HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, ProcEventInfo const& eventInfo);
bool HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, bool* handled); bool HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, bool* handled);
bool HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, uint32 procPhase, ProcEventInfo& eventInfo); bool HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, uint32 procPhase, ProcEventInfo& eventInfo);
bool HandleOverrideClassScriptAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 cooldown); bool HandleOverrideClassScriptAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 cooldown);
+1 -1
View File
@@ -39,7 +39,7 @@ class ObjectGuid;
#define CENTER_GRID_OFFSET (SIZE_OF_GRIDS/2) #define CENTER_GRID_OFFSET (SIZE_OF_GRIDS/2)
#define MIN_GRID_DELAY (MINUTE*IN_MILLISECONDS) #define MIN_GRID_DELAY (MINUTE*IN_MILLISECONDS)
#define MIN_MAP_UPDATE_DELAY 10 #define MIN_MAP_UPDATE_DELAY 1
#define SIZE_OF_GRID_CELL (SIZE_OF_GRIDS/MAX_NUMBER_OF_CELLS) #define SIZE_OF_GRID_CELL (SIZE_OF_GRIDS/MAX_NUMBER_OF_CELLS)
+2
View File
@@ -1201,6 +1201,7 @@ void Guild::HandleRoster(WorldSession* session)
{ {
WorldPackets::Guild::GuildRoster roster; WorldPackets::Guild::GuildRoster roster;
roster.RankData.reserve(m_ranks.size());
for (RankInfo const& rank : m_ranks) for (RankInfo const& rank : m_ranks)
{ {
WorldPackets::Guild::GuildRankData& rankData = roster.RankData.emplace_back(); WorldPackets::Guild::GuildRankData& rankData = roster.RankData.emplace_back();
@@ -1215,6 +1216,7 @@ void Guild::HandleRoster(WorldSession* session)
} }
bool sendOfficerNote = HasRankRight(session->GetPlayer(), GR_RIGHT_VIEWOFFNOTE); bool sendOfficerNote = HasRankRight(session->GetPlayer(), GR_RIGHT_VIEWOFFNOTE);
roster.MemberData.reserve(m_members.size());
for (auto const& [guid, member] : m_members) for (auto const& [guid, member] : m_members)
{ {
WorldPackets::Guild::GuildRosterMemberData& memberData = roster.MemberData.emplace_back(); WorldPackets::Guild::GuildRosterMemberData& memberData = roster.MemberData.emplace_back();
+7 -6
View File
@@ -784,14 +784,15 @@ void WorldSession::HandleRaidReadyCheckOpcode(WorldPacket& recvData)
void WorldSession::HandleRaidReadyCheckFinishedOpcode(WorldPacket& /*recvData*/) void WorldSession::HandleRaidReadyCheckFinishedOpcode(WorldPacket& /*recvData*/)
{ {
//Group* group = GetPlayer()->GetGroup(); Group* group = GetPlayer()->GetGroup();
//if (!group) if (!group)
// return; return;
//if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
// return; return;
// Is any reaction need? WorldPacket data(MSG_RAID_READY_CHECK_FINISHED);
group->BroadcastPacket(&data, true, -1);
} }
void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacket* data) void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacket* data)
+13 -2
View File
@@ -2525,6 +2525,7 @@ void Map::SendInitSelf(Player* player)
{ {
LOG_DEBUG("maps", "Creating player data for himself {}", player->GetGUID().ToString()); LOG_DEBUG("maps", "Creating player data for himself {}", player->GetGUID().ToString());
WorldPacket packet;
UpdateData data; UpdateData data;
// attach to player data current transport data // attach to player data current transport data
@@ -2534,15 +2535,25 @@ void Map::SendInitSelf(Player* player)
// build data for self presence in world at own client (one time for map) // build data for self presence in world at own client (one time for map)
player->BuildCreateUpdateBlockForPlayer(&data, player); player->BuildCreateUpdateBlockForPlayer(&data, player);
// build and send self update packet before sending to player his own auras
data.BuildPacket(&packet);
player->SendDirectMessage(&packet);
// send to player his own auras (this is needed here for timely initialization of some fields on client)
player->GetAurasForTarget(player, true);
// clean buffers for further work
packet.clear();
data.Clear();
// build other passengers at transport also (they always visible and marked as visible and will not send at visibility update at add to map // build other passengers at transport also (they always visible and marked as visible and will not send at visibility update at add to map
if (Transport* transport = player->GetTransport()) if (Transport* transport = player->GetTransport())
for (Transport::PassengerSet::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end(); ++itr) for (Transport::PassengerSet::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end(); ++itr)
if (player != (*itr) && player->HaveAtClient(*itr)) if (player != (*itr) && player->HaveAtClient(*itr))
(*itr)->BuildCreateUpdateBlockForPlayer(&data, player); (*itr)->BuildCreateUpdateBlockForPlayer(&data, player);
WorldPacket packet;
data.BuildPacket(&packet); data.BuildPacket(&packet);
player->GetSession()->SendPacket(&packet); player->SendDirectMessage(&packet);
} }
void Map::SendInitTransports(Player* player) void Map::SendInitTransports(Player* player)
@@ -6626,8 +6626,9 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
HealInfo healInfo(caster, target, heal, GetSpellInfo(), GetSpellInfo()->GetSchoolMask()); HealInfo healInfo(caster, target, heal, GetSpellInfo(), GetSpellInfo()->GetSchoolMask());
Unit::CalcHealAbsorb(healInfo); Unit::CalcHealAbsorb(healInfo);
int32 gain = Unit::DealHeal(caster, target, healInfo.GetHeal()); int32 gain = Unit::DealHeal(caster, target, healInfo.GetHeal());
healInfo.SetEffectiveHeal(gain);
SpellPeriodicAuraLogInfo pInfo(this, healInfo.GetHeal(), healInfo.GetHeal() - gain, healInfo.GetAbsorb(), 0, 0.0f, crit); SpellPeriodicAuraLogInfo pInfo(this, healInfo.GetHeal(), healInfo.GetHeal() - healInfo.GetEffectiveHeal(), healInfo.GetAbsorb(), 0, 0.0f, crit);
target->SendPeriodicAuraLog(&pInfo); target->SendPeriodicAuraLog(&pInfo);
if (caster) if (caster)
@@ -4374,7 +4374,8 @@ void SpellMgr::LoadSpellInfoCorrections()
}); });
// Judgement (Paladin T2 8P Bonus) // Judgement (Paladin T2 8P Bonus)
ApplySpellFix({ 23591 }, [](SpellInfo* spellInfo) // Battlegear of Eternal Justice
ApplySpellFix({ 23591, 26135 }, [](SpellInfo* spellInfo)
{ {
spellInfo->ProcFlags = PROC_FLAG_DONE_SPELL_MELEE_DMG_CLASS; spellInfo->ProcFlags = PROC_FLAG_DONE_SPELL_MELEE_DMG_CLASS;
}); });
+3 -2
View File
@@ -2211,8 +2211,8 @@ void SpellMgr::LoadSpellEnchantProcData()
mSpellEnchantProcEventMap.clear(); // need for reload case mSpellEnchantProcEventMap.clear(); // need for reload case
// 0 1 2 3 // 0 1 2 3 4
QueryResult result = WorldDatabase.Query("SELECT entry, customChance, PPMChance, procEx FROM spell_enchant_proc_data"); QueryResult result = WorldDatabase.Query("SELECT entry, customChance, PPMChance, procEx, attributeMask FROM spell_enchant_proc_data");
if (!result) if (!result)
{ {
LOG_WARN("server.loading", ">> Loaded 0 spell enchant proc event conditions. DB table `spell_enchant_proc_data` is empty."); LOG_WARN("server.loading", ">> Loaded 0 spell enchant proc event conditions. DB table `spell_enchant_proc_data` is empty.");
@@ -2239,6 +2239,7 @@ void SpellMgr::LoadSpellEnchantProcData()
spe.customChance = fields[1].Get<uint32>(); spe.customChance = fields[1].Get<uint32>();
spe.PPMChance = fields[2].Get<float>(); spe.PPMChance = fields[2].Get<float>();
spe.procEx = fields[3].Get<uint32>(); spe.procEx = fields[3].Get<uint32>();
spe.attributeMask = fields[4].Get<uint32>();
mSpellEnchantProcEventMap[enchantId] = spe; mSpellEnchantProcEventMap[enchantId] = spe;
+6
View File
@@ -304,11 +304,17 @@ struct SpellProcEntry
typedef std::unordered_map<uint32, SpellProcEntry> SpellProcMap; typedef std::unordered_map<uint32, SpellProcEntry> SpellProcMap;
enum EnchantProcAttributes
{
ENCHANT_PROC_ATTR_EXCLUSIVE = 0x1 // Only one instance of that effect can be active
};
struct SpellEnchantProcEntry struct SpellEnchantProcEntry
{ {
uint32 customChance; uint32 customChance;
float PPMChance; float PPMChance;
uint32 procEx; uint32 procEx;
uint32 attributeMask;
}; };
typedef std::unordered_map<uint32, SpellEnchantProcEntry> SpellEnchantProcEventMap; typedef std::unordered_map<uint32, SpellEnchantProcEntry> SpellEnchantProcEventMap;
+1 -1
View File
@@ -667,7 +667,7 @@ void World::LoadConfigSettings(bool reload)
_int_configs[CONFIG_MIN_LEVEL_STAT_SAVE] = 0; _int_configs[CONFIG_MIN_LEVEL_STAT_SAVE] = 0;
} }
_int_configs[CONFIG_INTERVAL_MAPUPDATE] = sConfigMgr->GetOption<int32>("MapUpdateInterval", 100); _int_configs[CONFIG_INTERVAL_MAPUPDATE] = sConfigMgr->GetOption<int32>("MapUpdateInterval", 10);
if (_int_configs[CONFIG_INTERVAL_MAPUPDATE] < MIN_MAP_UPDATE_DELAY) if (_int_configs[CONFIG_INTERVAL_MAPUPDATE] < MIN_MAP_UPDATE_DELAY)
{ {
LOG_ERROR("server.loading", "MapUpdateInterval ({}) must be greater {}. Use this minimal value.", _int_configs[CONFIG_INTERVAL_MAPUPDATE], MIN_MAP_UPDATE_DELAY); LOG_ERROR("server.loading", "MapUpdateInterval ({}) must be greater {}. Use this minimal value.", _int_configs[CONFIG_INTERVAL_MAPUPDATE], MIN_MAP_UPDATE_DELAY);
-2
View File
@@ -141,8 +141,6 @@ enum WorldStates
WS_DAILY_CALENDAR_DELETION_OLD_EVENTS_TIME = 20008 // Next daily calendar deletions of old events time WS_DAILY_CALENDAR_DELETION_OLD_EVENTS_TIME = 20008 // Next daily calendar deletions of old events time
}; };
#define WORLD_SLEEP_CONST 10
// xinef: petitions storage // xinef: petitions storage
struct PetitionData struct PetitionData
{ {
@@ -168,20 +168,19 @@ public:
int32 multiplier = 1; int32 multiplier = 1;
switch (aurEff->GetTickNumber()) switch (aurEff->GetTickNumber())
{ {
case 2:
case 3: case 3:
case 4:
multiplier = 2; multiplier = 2;
break; break;
case 4:
case 5: case 5:
multiplier = 3;
break;
case 6: case 6:
case 7:
multiplier = 4; multiplier = 4;
break; break;
case 7:
multiplier = 6;
break;
case 8: case 8:
multiplier = 5; multiplier = 10;
break; break;
} }
@@ -134,7 +134,12 @@ public:
// Not in progress // Not in progress
instance->SetData(DATA_ARAN, NOT_STARTED); instance->SetData(DATA_ARAN, NOT_STARTED);
instance->HandleGameObject(instance->GetGuidData(DATA_GO_LIBRARY_DOOR), true);
if (GameObject* libraryDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_GO_LIBRARY_DOOR)))
{
libraryDoor->SetGoState(GO_STATE_ACTIVE);
libraryDoor->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
}
} }
void KilledUnit(Unit* /*victim*/) override void KilledUnit(Unit* /*victim*/) override
@@ -147,7 +152,12 @@ public:
Talk(SAY_DEATH); Talk(SAY_DEATH);
instance->SetData(DATA_ARAN, DONE); instance->SetData(DATA_ARAN, DONE);
instance->HandleGameObject(instance->GetGuidData(DATA_GO_LIBRARY_DOOR), true);
if (GameObject* libraryDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_GO_LIBRARY_DOOR)))
{
libraryDoor->SetGoState(GO_STATE_ACTIVE);
libraryDoor->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
}
} }
void JustEngagedWith(Unit* /*who*/) override void JustEngagedWith(Unit* /*who*/) override
@@ -155,7 +165,13 @@ public:
Talk(SAY_AGGRO); Talk(SAY_AGGRO);
instance->SetData(DATA_ARAN, IN_PROGRESS); instance->SetData(DATA_ARAN, IN_PROGRESS);
instance->HandleGameObject(instance->GetGuidData(DATA_GO_LIBRARY_DOOR), false);
if (GameObject* libraryDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_GO_LIBRARY_DOOR)))
{
libraryDoor->SetGoState(GO_STATE_READY);
libraryDoor->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
}
DoZoneInCombat(); DoZoneInCombat();
} }
@@ -203,7 +219,11 @@ public:
{ {
if (CloseDoorTimer <= diff) if (CloseDoorTimer <= diff)
{ {
instance->HandleGameObject(instance->GetGuidData(DATA_GO_LIBRARY_DOOR), false); if (GameObject* libraryDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_GO_LIBRARY_DOOR)))
{
libraryDoor->SetGoState(GO_STATE_READY);
libraryDoor->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
}
CloseDoorTimer = 0; CloseDoorTimer = 0;
} }
else else
@@ -163,7 +163,6 @@ Position const RimefangFlyPos = {4413.309f, 2456.421f, 233.3795f, 2.890186f
Position const RimefangLandPos = {4413.309f, 2456.421f, 203.3848f, 2.890186f}; Position const RimefangLandPos = {4413.309f, 2456.421f, 203.3848f, 2.890186f};
Position const SpinestalkerFlyPos = {4418.895f, 2514.233f, 230.4864f, 3.396045f}; Position const SpinestalkerFlyPos = {4418.895f, 2514.233f, 230.4864f, 3.396045f};
Position const SpinestalkerLandPos = {4418.895f, 2514.233f, 203.3848f, 3.396045f}; Position const SpinestalkerLandPos = {4418.895f, 2514.233f, 203.3848f, 3.396045f};
Position const SindragosaSpawnPos = {4818.700f, 2483.710f, 287.0650f, 3.089233f};
Position const SindragosaFlyInPos = {4420.190f, 2484.360f, 232.5150f, 3.141593f}; Position const SindragosaFlyInPos = {4420.190f, 2484.360f, 232.5150f, 3.141593f};
Position const SindragosaLandPos = {4419.190f, 2484.570f, 203.3848f, 3.141593f}; Position const SindragosaLandPos = {4419.190f, 2484.570f, 203.3848f, 3.141593f};
Position const SindragosaAirPos = {4475.990f, 2484.430f, 247.9340f, 3.141593f}; Position const SindragosaAirPos = {4475.990f, 2484.430f, 247.9340f, 3.141593f};
@@ -273,7 +272,7 @@ public:
struct boss_sindragosaAI : public BossAI struct boss_sindragosaAI : public BossAI
{ {
boss_sindragosaAI(Creature* creature) : BossAI(creature, DATA_SINDRAGOSA), _summoned(false) boss_sindragosaAI(Creature* creature) : BossAI(creature, DATA_SINDRAGOSA)
{ {
me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_HASTE_SPELLS, true); me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_HASTE_SPELLS, true);
} }
@@ -286,16 +285,9 @@ public:
_bombCount = 0; _bombCount = 0;
_mysticBuffetStack = 0; _mysticBuffetStack = 0;
_Reset(); _Reset();
me->DisableRotate(false);
me->SetControlled(false, UNIT_STATE_ROOT);
me->SetSpeed(MOVE_RUN, me->GetCreatureTemplate()->speed_run); me->SetSpeed(MOVE_RUN, me->GetCreatureTemplate()->speed_run);
me->SetReactState(REACT_AGGRESSIVE); me->SetReactState(REACT_AGGRESSIVE);
me->CastSpell(me, SPELL_TANK_MARKER, true); me->CastSpell(me, SPELL_TANK_MARKER, true);
if (!_summoned)
{
me->SetDisableGravity(true);
}
} }
void MoveInLineOfSight(Unit* who) override void MoveInLineOfSight(Unit* who) override
@@ -359,20 +351,9 @@ public:
return me->IsVisible() && target->GetEntry() != NPC_CROK_SCOURGEBANE; return me->IsVisible() && target->GetEntry() != NPC_CROK_SCOURGEBANE;
} }
void JustReachedHome() override
{
_JustReachedHome();
instance->SetBossState(DATA_SINDRAGOSA, FAIL);
if (_summoned)
{
me->SetDisableGravity(false);
}
}
void EnterEvadeMode(EvadeReason why) override void EnterEvadeMode(EvadeReason why) override
{ {
me->DisableRotate(false); instance->SetBossState(DATA_SINDRAGOSA, FAIL);
me->SetControlled(false, UNIT_STATE_ROOT);
BossAI::EnterEvadeMode(why); BossAI::EnterEvadeMode(why);
} }
@@ -386,10 +367,6 @@ public:
{ {
if (action == ACTION_START_FROSTWYRM) if (action == ACTION_START_FROSTWYRM)
{ {
if (_summoned)
return;
_summoned = true;
if (TempSummon* summon = me->ToTempSummon()) if (TempSummon* summon = me->ToTempSummon())
summon->SetTempSummonType(TEMPSUMMON_DEAD_DESPAWN); summon->SetTempSummonType(TEMPSUMMON_DEAD_DESPAWN);
@@ -403,7 +380,11 @@ public:
float moveTime = me->GetExactDist(&SindragosaFlyInPos) / (me->GetSpeed(MOVE_RUN) * 0.001f); float moveTime = me->GetExactDist(&SindragosaFlyInPos) / (me->GetSpeed(MOVE_RUN) * 0.001f);
me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, SindragosaLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250)); me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, SindragosaLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250));
me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, SindragosaFlyInPos); me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, SindragosaFlyInPos);
me->CastSpell(me, SPELL_SINDRAGOSA_S_FURY, true);
if (!instance->GetData(DATA_SINDRAGOSA_INTRO))
{
DoCastAOE(SPELL_SINDRAGOSA_S_FURY);
}
} }
} }
@@ -685,7 +666,6 @@ public:
} }
private: private:
bool _summoned;
uint8 _bombCount; uint8 _bombCount;
uint8 _mysticBuffetStack; uint8 _mysticBuffetStack;
bool _didFirstFlyPhase; bool _didFirstFlyPhase;
@@ -1724,13 +1704,10 @@ public:
if (Creature* rimefang = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_RIMEFANG))) if (Creature* rimefang = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_RIMEFANG)))
rimefang->AI()->DoAction(ACTION_START_FROSTWYRM); rimefang->AI()->DoAction(ACTION_START_FROSTWYRM);
if (!instance->GetData(DATA_SINDRAGOSA_FROSTWYRMS) && !instance->GetGuidData(DATA_SINDRAGOSA) && instance->GetBossState(DATA_SINDRAGOSA) != DONE) if (!instance->GetData(DATA_SINDRAGOSA_FROSTWYRMS))
{ {
if (instance->GetData(DATA_HAS_LIMITED_ATTEMPTS) && !instance->GetData(DATA_HEROIC_ATTEMPTS))
return true;
player->GetMap()->LoadGrid(SindragosaSpawnPos.GetPositionX(), SindragosaSpawnPos.GetPositionY()); player->GetMap()->LoadGrid(SindragosaSpawnPos.GetPositionX(), SindragosaSpawnPos.GetPositionY());
if (Creature* sindragosa = player->GetMap()->SummonCreature(NPC_SINDRAGOSA, SindragosaSpawnPos)) if (Creature* sindragosa = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_SINDRAGOSA)))
sindragosa->AI()->DoAction(ACTION_START_FROSTWYRM); sindragosa->AI()->DoAction(ACTION_START_FROSTWYRM);
} }
} }
@@ -144,6 +144,7 @@ enum DataTypes
DATA_PUTRICIDE_TRAP_STATE = 254, DATA_PUTRICIDE_TRAP_STATE = 254,
DATA_HAS_LIMITED_ATTEMPTS = 255, DATA_HAS_LIMITED_ATTEMPTS = 255,
DATA_LK_HC_AVAILABLE = 256, DATA_LK_HC_AVAILABLE = 256,
DATA_SINDRAGOSA_INTRO = 257,
DATA_BPC_TRASH_DIED = 300, DATA_BPC_TRASH_DIED = 300,
}; };
@@ -49,7 +49,8 @@ enum TimedEvents
EVENT_UPDATE_EXECUTION_TIME = 1, EVENT_UPDATE_EXECUTION_TIME = 1,
EVENT_QUAKE_SHATTER = 2, EVENT_QUAKE_SHATTER = 2,
EVENT_REBUILD_PLATFORM = 3, EVENT_REBUILD_PLATFORM = 3,
EVENT_RESPAWN_GUNSHIP = 4 EVENT_RESPAWN_GUNSHIP = 4,
EVENT_RESPAWN_SINDRAGOSA = 5
}; };
enum Spells enum Spells
@@ -140,6 +141,7 @@ Position const JainaSpawnPos = { -48.65278f, 2211.026f, 27.98586f, 3.124139f
Position const MuradinSpawnPos = { -47.34549f, 2208.087f, 27.98586f, 3.106686f }; Position const MuradinSpawnPos = { -47.34549f, 2208.087f, 27.98586f, 3.106686f };
Position const UtherSpawnPos = { -26.58507f, 2211.524f, 30.19898f, 3.124139f }; Position const UtherSpawnPos = { -26.58507f, 2211.524f, 30.19898f, 3.124139f };
Position const SylvanasSpawnPos = { -41.45833f, 2222.891f, 27.98586f, 3.647738f }; Position const SylvanasSpawnPos = { -41.45833f, 2222.891f, 27.98586f, 3.647738f };
Position const SindragosaSpawnPos = { 4818.6997f, 2483.7102f, 287.06497f, 3.286661f };
// Set position traps Spirit Alarm // Set position traps Spirit Alarm
std::vector<Position> GoSpiritAlarm_1 = { { -160.96f, 2210.46f, 35.24f, 0.0f }, { -176.27f, 2201.93f, 35.24f, 0.0f}, { -207.83f, 2207.38f, 35.24f, 0.0f } }; std::vector<Position> GoSpiritAlarm_1 = { { -160.96f, 2210.46f, 35.24f, 0.0f }, { -176.27f, 2201.93f, 35.24f, 0.0f}, { -207.83f, 2207.38f, 35.24f, 0.0f } };
@@ -212,6 +214,7 @@ public:
BloodQuickeningState = NOT_STARTED; BloodQuickeningState = NOT_STARTED;
BloodQuickeningMinutes = 0; BloodQuickeningMinutes = 0;
BloodPrinceTrashCount = 0; BloodPrinceTrashCount = 0;
IsSindragosaIntroDone = false;
} }
void FillInitialWorldStates(WorldPacket& data) override void FillInitialWorldStates(WorldPacket& data) override
@@ -254,6 +257,11 @@ public:
if (GetBossState(DATA_LADY_DEATHWHISPER) == DONE && GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != DONE) if (GetBossState(DATA_LADY_DEATHWHISPER) == DONE && GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != DONE)
SpawnGunship(); SpawnGunship();
if (GetBossState(DATA_SINDRAGOSA) != DONE && IsSindragosaIntroDone && SindragosaGUID.IsEmpty() && Events.GetTimeUntilEvent(EVENT_RESPAWN_SINDRAGOSA) == Milliseconds::max())
{
Events.ScheduleEvent(EVENT_RESPAWN_SINDRAGOSA, 30s);
}
if (IsBuffAvailable) if (IsBuffAvailable)
{ {
SpellAreaForAreaMapBounds saBounds = sSpellMgr->GetSpellAreaForAreaMapBounds(4812); SpellAreaForAreaMapBounds saBounds = sSpellMgr->GetSpellAreaForAreaMapBounds(4812);
@@ -937,6 +945,8 @@ public:
return BloodQuickeningState; return BloodQuickeningState;
case DATA_HEROIC_ATTEMPTS: case DATA_HEROIC_ATTEMPTS:
return HeroicAttempts; return HeroicAttempts;
case DATA_SINDRAGOSA_INTRO:
return (IsSindragosaIntroDone ? 1 : 0);
default: default:
break; break;
} }
@@ -1161,7 +1171,21 @@ public:
if (state == DONE) if (state == DONE)
CheckLichKingAvailability(); CheckLichKingAvailability();
else if (state == FAIL) else if (state == FAIL)
{
IsSindragosaIntroDone = true;
HandleDropAttempt(); HandleDropAttempt();
if (instance->IsHeroic())
{
if (HeroicAttempts)
{
Events.ScheduleEvent(EVENT_RESPAWN_SINDRAGOSA, 30s);
}
}
else
{
Events.ScheduleEvent(EVENT_RESPAWN_SINDRAGOSA, 30s);
}
}
if (state == DONE && !instance->IsHeroic() && LichKingHeroicAvailable) if (state == DONE && !instance->IsHeroic() && LichKingHeroicAvailable)
{ {
LichKingHeroicAvailable = false; LichKingHeroicAvailable = false;
@@ -1626,6 +1650,7 @@ public:
data >> BloodPrinceTrashCount; data >> BloodPrinceTrashCount;
data >> IsBuffAvailable; data >> IsBuffAvailable;
SetData(DATA_BUFF_AVAILABLE, IsBuffAvailable); SetData(DATA_BUFF_AVAILABLE, IsBuffAvailable);
data >> IsSindragosaIntroDone;
} }
void WriteSaveDataMore(std::ostringstream& data) override void WriteSaveDataMore(std::ostringstream& data) override
@@ -1638,7 +1663,8 @@ public:
<< PutricideEventProgress << ' ' << PutricideEventProgress << ' '
<< uint32(LichKingHeroicAvailable ? 1 : 0) << ' ' << uint32(LichKingHeroicAvailable ? 1 : 0) << ' '
<< BloodPrinceTrashCount << ' ' << BloodPrinceTrashCount << ' '
<< uint32(IsBuffAvailable ? 1 : 0); << uint32(IsBuffAvailable ? 1 : 0) << ' '
<< uint32(IsSindragosaIntroDone ? 1 : 0);
} }
void Update(uint32 diff) override void Update(uint32 diff) override
@@ -1679,7 +1705,7 @@ public:
else else
DarkwhisperElevatorTimer -= diff; DarkwhisperElevatorTimer -= diff;
if (BloodQuickeningState != IN_PROGRESS && GetBossState(DATA_THE_LICH_KING) != IN_PROGRESS && GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != FAIL) if (Events.Empty())
return; return;
Events.Update(diff); Events.Update(diff);
@@ -1732,6 +1758,21 @@ public:
case EVENT_RESPAWN_GUNSHIP: case EVENT_RESPAWN_GUNSHIP:
SpawnGunship(); SpawnGunship();
break; break;
case EVENT_RESPAWN_SINDRAGOSA:
if (Creature* sindragosa = instance->SummonCreature(NPC_SINDRAGOSA, SindragosaSpawnPos))
{
sindragosa->setActive(true);
sindragosa->SetDisableGravity(true);
sindragosa->GetMotionMaster()->MovePath(NPC_SINDRAGOSA * 10, true);
if (TempSummon* summon = sindragosa->ToTempSummon())
{
summon->SetTempSummonType(TEMPSUMMON_DEAD_DESPAWN);
}
}
// Could happen more than once if more than one player enters before she respawns.
Events.CancelEvent(EVENT_RESPAWN_SINDRAGOSA);
break;
default: default:
break; break;
} }
@@ -1944,6 +1985,7 @@ public:
bool IsOozeDanceEligible; bool IsOozeDanceEligible;
bool IsNauseaEligible; bool IsNauseaEligible;
bool IsOrbWhispererEligible; bool IsOrbWhispererEligible;
bool IsSindragosaIntroDone;
}; };
InstanceScript* GetInstanceScript(InstanceMap* map) const override InstanceScript* GetInstanceScript(InstanceMap* map) const override
@@ -23,7 +23,9 @@
enum vYells enum vYells
{ {
CYANIGOSA_SAY_SPAWN = 3, CYANIGOSA_SAY_SPAWN = 3,
SAY_SINCLARI_1 = 0 SAY_SINCLARI_LEAVING = 0,
SAY_SINCLARI_DOOR_LOCK = 1,
SAY_SINCLARI_COMPLETE = 2,
}; };
class instance_violet_hold : public InstanceMapScript class instance_violet_hold : public InstanceMapScript
@@ -214,7 +216,7 @@ public:
{ {
EncounterStatus = IN_PROGRESS; EncounterStatus = IN_PROGRESS;
if (Creature* c = instance->GetCreature(NPC_SinclariGUID)) if (Creature* c = instance->GetCreature(NPC_SinclariGUID))
c->AI()->Talk(SAY_SINCLARI_1); c->AI()->Talk(SAY_SINCLARI_LEAVING);
events.RescheduleEvent(EVENT_GUARDS_FALL_BACK, 4s); events.RescheduleEvent(EVENT_GUARDS_FALL_BACK, 4s);
} }
break; break;
@@ -251,7 +253,12 @@ public:
EncounterStatus = DONE; EncounterStatus = DONE;
HandleGameObject(GO_MainGateGUID, true); HandleGameObject(GO_MainGateGUID, true);
DoUpdateWorldState(WORLD_STATE_VH_SHOW, 0); DoUpdateWorldState(WORLD_STATE_VH_SHOW, 0);
if (Creature* c = instance->GetCreature(NPC_SinclariGUID)) { c->DespawnOrUnsummon(); c->SetRespawnTime(3); } if (Creature* c = instance->GetCreature(NPC_SinclariGUID))
{
c->AI()->Talk(SAY_SINCLARI_COMPLETE);
c->DespawnOrUnsummon();
c->SetRespawnTime(3);
}
} }
SaveToDB(); SaveToDB();
if (WaveCount < 18) if (WaveCount < 18)
@@ -440,8 +447,14 @@ public:
break; break;
case EVENT_START_ENCOUNTER: case EVENT_START_ENCOUNTER:
{ {
if (Creature* c = instance->GetCreature(NPC_SinclariGUID))
{
c->AI()->Talk(SAY_SINCLARI_DOOR_LOCK);
}
if (Creature* c = instance->GetCreature(NPC_DoorSealGUID)) if (Creature* c = instance->GetCreature(NPC_DoorSealGUID))
{
c->RemoveAllAuras(); // just to be sure... c->RemoveAllAuras(); // just to be sure...
}
GateHealth = 100; GateHealth = 100;
HandleGameObject(GO_MainGateGUID, false); HandleGameObject(GO_MainGateGUID, false);
DoUpdateWorldState(WORLD_STATE_VH_SHOW, 1); DoUpdateWorldState(WORLD_STATE_VH_SHOW, 1);
@@ -24,6 +24,21 @@
#include "ScriptedGossip.h" #include "ScriptedGossip.h"
#include "SpellScript.h" #include "SpellScript.h"
/// @todo: Missing Sinclari Trigger announcements (32204) Look at its creature_text for more info.
/// @todo: Activation Crystals (go_vh_activation_crystal) (193611) are spammable, should be a 1 time use per crystal.
enum Texts
{
GOSSIP_MENU_START_EVENT = 9998,
GOSSIP_MENU_ITEM = 9997,
GOSSIP_MENU_LATE_JOIN = 10275,
NPC_TEXT_SINCLARI_IN = 13853,
NPC_TEXT_SINCLARI_ITEM = 13854,
NPC_TEXT_SINCLARI_DONE = 13910,
NPC_TEXT_SINCLARI_LATE_JOIN = 14271,
};
/*********** /***********
** DEFENSE SYSTEM CRYSTAL ** DEFENSE SYSTEM CRYSTAL
***********/ ***********/
@@ -45,10 +60,6 @@ public:
** SINCLARI ** SINCLARI
***********/ ***********/
#define GOSSIP_START_EVENT "Get your people to safety, we'll keep the Blue Dragonflight's forces at bay."
#define GOSSIP_ITEM_1 "Activate the crystals when we get in trouble, right."
#define GOSSIP_I_WANT_IN "Sorry, I'm late! Can I get in to help my friends?"
class npc_vh_sinclari : public CreatureScript class npc_vh_sinclari : public CreatureScript
{ {
public: public:
@@ -60,16 +71,16 @@ public:
switch (pInstance->GetData(DATA_ENCOUNTER_STATUS)) switch (pInstance->GetData(DATA_ENCOUNTER_STATUS))
{ {
case NOT_STARTED: case NOT_STARTED:
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); AddGossipItemFor(player, GOSSIP_MENU_ITEM, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_START_EVENT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); AddGossipItemFor(player, GOSSIP_MENU_START_EVENT, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
SendGossipMenuFor(player, 13853, creature->GetGUID()); SendGossipMenuFor(player, NPC_TEXT_SINCLARI_IN, creature->GetGUID());
break; break;
case IN_PROGRESS: case IN_PROGRESS:
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_I_WANT_IN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); AddGossipItemFor(player, GOSSIP_MENU_LATE_JOIN, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
SendGossipMenuFor(player, 13853, creature->GetGUID()); SendGossipMenuFor(player, NPC_TEXT_SINCLARI_LATE_JOIN, creature->GetGUID());
break; break;
default: // DONE or invalid default: // DONE or invalid
SendGossipMenuFor(player, 13910, creature->GetGUID()); SendGossipMenuFor(player, NPC_TEXT_SINCLARI_DONE, creature->GetGUID());
} }
return true; return true;
} }
@@ -86,7 +97,7 @@ public:
pInstance->SetData(DATA_START_INSTANCE, 1); pInstance->SetData(DATA_START_INSTANCE, 1);
break; break;
case GOSSIP_ACTION_INFO_DEF+2: case GOSSIP_ACTION_INFO_DEF+2:
SendGossipMenuFor(player, 13854, creature->GetGUID()); SendGossipMenuFor(player, NPC_TEXT_SINCLARI_ITEM, creature->GetGUID());
break; break;
case GOSSIP_ACTION_INFO_DEF+3: case GOSSIP_ACTION_INFO_DEF+3:
player->NearTeleportTo(playerTeleportPosition.GetPositionX(), playerTeleportPosition.GetPositionY(), playerTeleportPosition.GetPositionZ(), playerTeleportPosition.GetOrientation(), true); player->NearTeleportTo(playerTeleportPosition.GetPositionX(), playerTeleportPosition.GetPositionY(), playerTeleportPosition.GetPositionZ(), playerTeleportPosition.GetOrientation(), true);
@@ -43,7 +43,7 @@ enum Spells
struct boss_talon_king_ikiss : public BossAI struct boss_talon_king_ikiss : public BossAI
{ {
boss_talon_king_ikiss(Creature* creature) : BossAI(creature, DATA_IKISS), _spoken(false), _manaShield(false) boss_talon_king_ikiss(Creature* creature) : BossAI(creature, DATA_IKISS), _spoken(false)
{ {
scheduler.SetValidator([this] scheduler.SetValidator([this]
{ {
@@ -55,8 +55,44 @@ struct boss_talon_king_ikiss : public BossAI
{ {
_Reset(); _Reset();
_spoken = false; _spoken = false;
_manaShield = false;
_comboHealthStages.fill(false); ScheduleHealthCheckEvent(80, [&] {
TeleportAndCastExplosion();
});
ScheduleHealthCheckEvent(50, [&] {
TeleportAndCastExplosion();
});
ScheduleHealthCheckEvent(25, [&] {
TeleportAndCastExplosion();
});
ScheduleHealthCheckEvent(20, [&] {
DoCast(me, SPELL_MANA_SHIELD);
});
}
/// @todo: remove this once pets stop going through doors.
bool CanAIAttack(Unit const* /*victim*/) const override
{
return _spoken;
}
void TeleportAndCastExplosion()
{
me->InterruptNonMeleeSpells(false);
DoCastSelf(SPELL_ARCANE_BUBBLE, true);
DoCastAOE(SPELL_BLINK);
Talk(EMOTE_ARCANE_EXP);
scheduler.Schedule(1s, [this](TaskContext)
{
DoCastAOE(SPELL_ARCANE_EXPLOSION);
}).Schedule(6500ms, [this](TaskContext /*context*/)
{
me->GetThreatMgr().ResetAllThreat();
});
} }
void MoveInLineOfSight(Unit* who) override void MoveInLineOfSight(Unit* who) override
@@ -106,69 +142,6 @@ struct boss_talon_king_ikiss : public BossAI
} }
} }
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
{
if (!_comboHealthStages[0] && me->HealthBelowPctDamaged(80, damage))
{
_comboHealthStages[0] = true;
me->InterruptNonMeleeSpells(false);
DoCastSelf(SPELL_ARCANE_BUBBLE, true);
DoCastAOE(SPELL_BLINK);
Talk(EMOTE_ARCANE_EXP);
scheduler.Schedule(1s, [this](TaskContext)
{
DoCastAOE(SPELL_ARCANE_EXPLOSION);
}).Schedule(6500ms, [this](TaskContext /*context*/)
{
me->GetThreatMgr().ResetAllThreat();
});
}
if (!_comboHealthStages[1] && me->HealthBelowPctDamaged(50, damage))
{
_comboHealthStages[1] = true;
me->InterruptNonMeleeSpells(false);
DoCastSelf(SPELL_ARCANE_BUBBLE, true);
DoCastAOE(SPELL_BLINK);
Talk(EMOTE_ARCANE_EXP);
scheduler.Schedule(1s, [this](TaskContext)
{
DoCastAOE(SPELL_ARCANE_EXPLOSION);
}).Schedule(6500ms, [this](TaskContext /*context*/)
{
me->GetThreatMgr().ResetAllThreat();
});
}
if (!_comboHealthStages[2] && me->HealthBelowPctDamaged(25, damage))
{
_comboHealthStages[2] = true;
me->InterruptNonMeleeSpells(false);
DoCastSelf(SPELL_ARCANE_BUBBLE, true);
DoCastAOE(SPELL_BLINK);
Talk(EMOTE_ARCANE_EXP);
scheduler.Schedule(1s, [this](TaskContext)
{
DoCastAOE(SPELL_ARCANE_EXPLOSION);
}).Schedule(6500ms, [this](TaskContext /*context*/)
{
me->GetThreatMgr().ResetAllThreat();
});
}
if (!_manaShield && me->HealthBelowPctDamaged(20, damage))
{
DoCast(me, SPELL_MANA_SHIELD);
_manaShield = true;
}
}
void KilledUnit(Unit* /*victim*/) override void KilledUnit(Unit* /*victim*/) override
{ {
if (urand(0, 1)) if (urand(0, 1))
@@ -177,8 +150,6 @@ struct boss_talon_king_ikiss : public BossAI
private: private:
bool _spoken; bool _spoken;
bool _manaShield;
std::array<bool, 3> _comboHealthStages;
}; };
// 38194 - Blink // 38194 - Blink
@@ -37,6 +37,8 @@ enum Spells
SPELL_ARCANE_TORRENT = 36022, SPELL_ARCANE_TORRENT = 36022,
SPELL_MANA_TAP = 36021, SPELL_MANA_TAP = 36021,
SPELL_DOMINATION = 35280, SPELL_DOMINATION = 35280,
SPELL_FRENZY = 36992,
SPELL_SUICIDE = 35301,
SPELL_ETHEREAL_TELEPORT = 34427, SPELL_ETHEREAL_TELEPORT = 34427,
SPELL_GREATER_INVISIBILITY = 34426, SPELL_GREATER_INVISIBILITY = 34426,
SPELL_SUMMON_NETHER_WRAITH_1 = 35285, SPELL_SUMMON_NETHER_WRAITH_1 = 35285,
@@ -48,6 +50,8 @@ enum Spells
enum Misc enum Misc
{ {
ACTION_BRIDGE_MOB_DEATH = 1, // Used by SAI ACTION_BRIDGE_MOB_DEATH = 1, // Used by SAI
EQUIPMENT_NORMAL = 1,
EQUIPMENT_FRENZY = 2,
}; };
struct boss_pathaleon_the_calculator : public BossAI struct boss_pathaleon_the_calculator : public BossAI
@@ -60,9 +64,13 @@ struct boss_pathaleon_the_calculator : public BossAI
}); });
} }
bool _isEnraged;
void Reset() override void Reset() override
{ {
_Reset(); _Reset();
_isEnraged = false;
me->LoadEquipment(EQUIPMENT_NORMAL);
if (instance->GetPersistentData(DATA_BRIDGE_MOB_DEATH_COUNT) < 4) if (instance->GetPersistentData(DATA_BRIDGE_MOB_DEATH_COUNT) < 4)
{ {
@@ -81,18 +89,23 @@ struct boss_pathaleon_the_calculator : public BossAI
ScheduleHealthCheckEvent(20, [&]() ScheduleHealthCheckEvent(20, [&]()
{ {
summons.DespawnAll(); DoCastSelf(SPELL_SUICIDE, true);
DoCastSelf(SPELL_DISGRUNTLED_ANGER, true); DoCastSelf(SPELL_FRENZY, true);
Talk(SAY_ENRAGE); Talk(SAY_ENRAGE);
_isEnraged = true;
me->LoadEquipment(EQUIPMENT_FRENZY);
}); });
scheduler.Schedule(30s, [this](TaskContext context) scheduler.Schedule(20s, 25s, [this](TaskContext context)
{ {
for (uint8 i = 0; i < DUNGEON_MODE(3, 4); ++i) if (!_isEnraged)
me->CastSpell(me, SPELL_SUMMON_NETHER_WRAITH_1 + i, true); {
for (uint8 i = 0; i < DUNGEON_MODE(3, 4); ++i)
me->CastSpell(me, SPELL_SUMMON_NETHER_WRAITH_1 + i, true);
Talk(SAY_SUMMON); Talk(SAY_SUMMON);
context.Repeat(30s, 40s); }
context.Repeat(45s, 50s);
}).Schedule(12s, [this](TaskContext context) }).Schedule(12s, [this](TaskContext context)
{ {
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, PowerUsersSelector(me, POWER_MANA, 40.0f, false))) if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, PowerUsersSelector(me, POWER_MANA, 40.0f, false)))
@@ -106,13 +119,17 @@ struct boss_pathaleon_the_calculator : public BossAI
me->ModifyPower(POWER_MANA, 5000); me->ModifyPower(POWER_MANA, 5000);
DoCastSelf(SPELL_ARCANE_TORRENT); DoCastSelf(SPELL_ARCANE_TORRENT);
context.Repeat(15s); context.Repeat(15s);
}).Schedule(25s, [this](TaskContext context) }).Schedule(10s, 15s, [this](TaskContext context)
{ {
if (DoCastRandomTarget(SPELL_DOMINATION, 1, 50.0f) == SPELL_CAST_OK) if (DoCastRandomTarget(SPELL_DOMINATION, 1, 50.0f) == SPELL_CAST_OK)
{ {
Talk(SAY_DOMINATION); Talk(SAY_DOMINATION);
} }
context.Repeat(30s); context.Repeat(27s, 40s);
}).Schedule(25s, [this](TaskContext context)
{
DoCast(SPELL_DISGRUNTLED_ANGER);
context.Repeat(40s, 90s);
}); });
if (IsHeroic()) if (IsHeroic())
@@ -349,7 +349,10 @@ public:
instance->SetBossState(DATA_WARDEN_MELLICHAR, DONE); instance->SetBossState(DATA_WARDEN_MELLICHAR, DONE);
if (Creature* creature = summons.GetCreatureWithEntry(NPC_MILLHOUSE)) if (Creature* creature = summons.GetCreatureWithEntry(NPC_MILLHOUSE))
{ {
instance->DoCastSpellOnPlayers(SPELL_QID10886); if (IsHeroic())
{
instance->DoCastSpellOnPlayers(SPELL_QID10886);
}
creature->AI()->Talk(SAY_COMPLETE); creature->AI()->Talk(SAY_COMPLETE);
creature->ReplaceAllNpcFlags(UNIT_NPC_FLAG_GOSSIP); creature->ReplaceAllNpcFlags(UNIT_NPC_FLAG_GOSSIP);
} }
@@ -91,15 +91,15 @@ struct boss_dalliah_the_doomsayer : public BossAI
} }
} }
scheduler.Schedule(1s, 4s, [this](TaskContext context) scheduler.Schedule(8s, 12s, [this](TaskContext context)
{ {
DoCastVictim(SPELL_GIFT_OF_THE_DOOMSAYER); DoCastVictim(SPELL_GIFT_OF_THE_DOOMSAYER);
context.Repeat(16s, 21s); context.Repeat(17s, 35s);
}).Schedule(7s, 9s, [this](TaskContext context) }).Schedule(20s, 30s, [this](TaskContext context)
{ {
Talk(SAY_WHIRLWIND); Talk(SAY_WHIRLWIND);
DoCastAOE(SPELL_WHIRLWIND); DoCastAOE(SPELL_WHIRLWIND);
context.Repeat(19s, 21s); context.Repeat();
scheduler.Schedule(7s, [this](TaskContext) scheduler.Schedule(7s, [this](TaskContext)
{ {
@@ -110,10 +110,10 @@ struct boss_dalliah_the_doomsayer : public BossAI
if (IsHeroic()) if (IsHeroic())
{ {
scheduler.Schedule(11s, 16s, [this](TaskContext context) scheduler.Schedule(11s, 30s, [this](TaskContext context)
{ {
DoCastVictim(SPELL_SHADOW_WAVE); DoCastVictim(SPELL_SHADOW_WAVE);
context.Repeat(11s, 16s); context.Repeat();
}); });
} }
} }
@@ -128,9 +128,10 @@ struct boss_wrath_scryer_soccothrates : public BossAI
scheduler.Schedule(30s, 35s, [this](TaskContext context) scheduler.Schedule(30s, 35s, [this](TaskContext context)
{ {
scheduler.DelayAll(5s);
me->CastSpell(me, SPELL_KNOCK_AWAY, false); me->CastSpell(me, SPELL_KNOCK_AWAY, false);
me->HandleEmoteCommand(EMOTE_ONESHOT_POINT);
Talk(SAY_KNOCK_AWAY); Talk(SAY_KNOCK_AWAY);
me->HandleEmoteCommand(EMOTE_ONESHOT_POINT);
scheduler.Schedule(4600ms, [this](TaskContext) scheduler.Schedule(4600ms, [this](TaskContext)
{ {
@@ -149,7 +150,7 @@ struct boss_wrath_scryer_soccothrates : public BossAI
}); });
context.Repeat(20s, 35s); context.Repeat(20s, 35s);
}).Schedule(12s, 14s, [this](TaskContext context) }).Schedule(8500ms, 22s, [this](TaskContext context)
{ {
DoCastVictim(SPELL_FELFIRE_SHOCK); DoCastVictim(SPELL_FELFIRE_SHOCK);
context.Repeat(); context.Repeat();
@@ -56,22 +56,22 @@ struct boss_zereketh_the_unbound : public BossAI
_JustEngagedWith(); _JustEngagedWith();
Talk(SAY_AGGRO); Talk(SAY_AGGRO);
scheduler.Schedule(6s, [this](TaskContext context) scheduler.Schedule(11s, 29s, [this](TaskContext context)
{ {
DoCastRandomTarget(SPELL_VOID_ZONE, 0, 60.0f); DoCastRandomTarget(SPELL_VOID_ZONE, 0, 60.0f);
context.Repeat(15s); context.Repeat();
}).Schedule(10s, [this](TaskContext context) }).Schedule(12s, 22s, [this](TaskContext context)
{ {
DoCastAOE(SPELL_SHADOW_NOVA); DoCastAOE(SPELL_SHADOW_NOVA);
if (roll_chance_i(50)) if (roll_chance_i(50))
{ {
Talk(SAY_SHADOW_NOVA); Talk(SAY_SHADOW_NOVA);
} }
context.Repeat(12s); context.Repeat();
}).Schedule(16s, [this](TaskContext context) }).Schedule(6s, 12s, [this](TaskContext context)
{ {
DoCastRandomTarget(SPELL_SEED_OF_CORRUPTION, 0, 30.0f); DoCastRandomTarget(SPELL_SEED_OF_CORRUPTION, 0, 30.0f);
context.Repeat(16s); context.Repeat(13s, 27s);
}); });
} }
@@ -1554,6 +1554,16 @@ struct ScalingStatValuesEntry
return 0; return 0;
} }
bool IsTwoHand(uint32 mask) const
{
if (mask & 0x7E00)
{
if (mask & 0x00000400) return true;
if (mask & 0x00001000) return true;
}
return false;
}
[[nodiscard]] uint32 getSpellBonus(uint32 mask) const [[nodiscard]] uint32 getSpellBonus(uint32 mask) const
{ {
if (mask & 0x00008000) return spellPower; if (mask & 0x00008000) return spellPower;
+4 -4
View File
@@ -121,8 +121,8 @@ protected:
{ {
LOG_DEBUG("misc", "Network Thread Starting"); LOG_DEBUG("misc", "Network Thread Starting");
_updateTimer.expires_from_now(boost::posix_time::milliseconds(10)); _updateTimer.expires_from_now(boost::posix_time::milliseconds(1));
_updateTimer.async_wait(std::bind(&NetworkThread<SocketType>::Update, this)); _updateTimer.async_wait([this](boost::system::error_code const&) { Update(); });
_ioContext.run(); _ioContext.run();
LOG_DEBUG("misc", "Network Thread exits"); LOG_DEBUG("misc", "Network Thread exits");
@@ -135,8 +135,8 @@ protected:
if (_stopped) if (_stopped)
return; return;
_updateTimer.expires_from_now(boost::posix_time::milliseconds(10)); _updateTimer.expires_from_now(boost::posix_time::milliseconds(1));
_updateTimer.async_wait(std::bind(&NetworkThread<SocketType>::Update, this)); _updateTimer.async_wait([this](boost::system::error_code const&) { Update(); });
AddNewSockets(); AddNewSockets();