Merge pull request #157 from azerothcore/master

Update
This commit is contained in:
bashermens
2026-01-22 17:27:50 +01:00
committed by GitHub
78 changed files with 1622 additions and 334 deletions
+2
View File
@@ -20,6 +20,8 @@ This tool compares your existing configuration files (`.conf`) with the latest d
## How to Use ## How to Use
There are two ways to use this. You can either copy this file directly to your `/configs` folder, or enable `TOOL_CONFIG_MERGER` in CMake. Upon compiling your core, the file will be generated in the same location as your `/configs` folder.
### Interactive Mode (Default) ### Interactive Mode (Default)
1. **Run the script** in your configs directory: 1. **Run the script** in your configs directory:
@@ -0,0 +1,18 @@
-- DB update 2026_01_14_01 -> 2026_01_15_00
-- Edit Spell Timers (Watcher Narjil, Gashra, Silthik)
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE (`entry` IN (28729, 28730, 28731));
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 28729) AND (`source_type` = 0) AND (`id` IN (0, 2, 3));
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 28730) AND (`source_type` = 0) AND (`id` IN (0, 1, 2));
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 28731) AND (`source_type` = 0) AND (`id` IN (0, 2, 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`, `event_param6`, `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
(28729, 0, 0, 0, 0, 0, 100, 0, 18000, 20000, 30000, 40000, 0, 0, 11, 52524, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Watcher Narjil - In Combat - Cast \'Blinding Webs\''),
(28729, 0, 2, 0, 0, 0, 100, 0, 20000, 25000, 20000, 25000, 0, 0, 11, 52086, 0, 0, 0, 0, 0, 5, 30, 0, 0, 0, 0, 0, 0, 0, 'Watcher Narjil - In Combat - Cast \'Web Wrap\''),
(28729, 0, 3, 0, 0, 0, 100, 0, 24000, 28000, 24000, 28000, 0, 0, 11, 52469, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Watcher Narjil - In Combat - Cast \'Infected Bite\''),
(28730, 0, 0, 0, 0, 0, 100, 0, 8000, 10000, 12000, 20000, 0, 0, 11, 52470, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Watcher Gashra - In Combat - Cast \'Enrage\''),
(28730, 0, 1, 0, 0, 0, 100, 0, 15000, 18000, 16000, 18000, 0, 0, 11, 52086, 0, 0, 0, 0, 0, 5, 30, 0, 0, 0, 0, 0, 0, 0, 'Watcher Gashra - In Combat - Cast \'Web Wrap\''),
(28730, 0, 2, 0, 0, 0, 100, 0, 24000, 28000, 24000, 28000, 0, 0, 11, 52469, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Watcher Gashra - In Combat - Cast \'Infected Bite\''),
(28731, 0, 0, 0, 0, 0, 100, 0, 8000, 10000, 18000, 20000, 0, 0, 11, 52493, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Watcher Silthik - In Combat - Cast \'Poison Spray\''),
(28731, 0, 2, 0, 0, 0, 100, 0, 15000, 18000, 16000, 18000, 0, 0, 11, 52086, 0, 0, 0, 0, 0, 5, 30, 0, 0, 0, 0, 0, 0, 0, 'Watcher Silthik - In Combat - Cast \'Web Wrap\''),
(28731, 0, 3, 0, 0, 0, 100, 0, 24000, 28000, 24000, 28000, 0, 0, 11, 52469, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Watcher Silthik - In Combat - Cast \'Infected Bite\'');
+243
View File
@@ -0,0 +1,243 @@
-- DB update 2026_01_15_00 -> 2026_01_16_00
-- Delete quest credit hack
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 30954) AND (`source_type` = 0) AND (`id` IN (3));
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 30956) AND (`source_type` = 0) AND (`id` IN (6));
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 30953) AND (`source_type` = 0) AND (`id` IN (3));
DELETE FROM `creature_template_addon` WHERE (`entry` = 31159);
INSERT INTO `creature_template_addon` (`entry`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) VALUES
(31159, 0, 0, 0, 1, 0, 0, '');
DELETE FROM `creature_template_addon` WHERE (`entry` = 31324);
INSERT INTO `creature_template_addon` (`entry`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) VALUES
(31324, 0, 0, 50331657, 0, 0, 0, '58269');
-- Phase if Stunning View (13160) has been completed
DELETE FROM `spell_area` WHERE `spell`=58863 AND `area`=4520 AND `quest_start`=13160;
INSERT INTO `spell_area` (`spell`, `area`, `quest_start`, `quest_end`, `aura_spell`, `racemask`, `gender`, `autocast`, `quest_start_status`, `quest_end_status`) VALUES
(58863, 4520, 13160, 0, 0, 0, 2, 1, 64, 0);
SET @GUID := 140200;
DELETE FROM `creature` WHERE `guid` BETWEEN @GUID AND @GUID+108 AND `phaseMask` IN (4) AND `areaId` IN (4520);
INSERT INTO `creature` (`guid`, `id1`, `map`, `zoneId`, `areaId`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `MovementType`, `VerifiedBuild`, `CreateObject`, `Comment`) VALUES
-- possibly incomplete waypoints
(@GUID+0 , 31159, 571, 210, 4520, 4, 1, 6408.76, 1725.81, 508.601, 6.02139, 300, 0, 2, 52237, 1, 'Phase Shift 2: Malykriss'),
-- definitely has waypoints, but not enough data
(@GUID+1 , 31160, 571, 210, 4520, 4, 1, 6069.33, 1921.17, 632.578, 5.48977, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Movement'),
-- static afaik
(@GUID+2 , 31161, 571, 210, 4520, 4, 1, 6559.47, 1563.07, 633.629, 5.00909, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+3 , 31223, 571, 210, 4520, 4, 0, 6470.11, 1724.35, 508.684, 2.37365, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+4 , 31224, 571, 210, 4520, 4, 0, 6564.62, 1612.34, 633.629, 1.85005, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+5 , 31225, 571, 210, 4520, 4, 0, 6055.63, 1954.17, 632.578, 3.42797, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
-- Lumbering Atrocity. Those in Phase 4 have different IDs from those in Phase 1
(@GUID+6 , 31226, 571, 210, 4520, 4, 0, 6444.69, 1972.97, 631.82, 3.38594, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+7 , 31226, 571, 210, 4520, 4, 0, 6447.33, 1952.95, 631.848, 3.19395, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+8 , 31226, 571, 210, 4520, 4, 0, 6366.38, 1970.99, 508.128, 3.33358, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+9 , 31226, 571, 210, 4520, 4, 0, 6371.61, 1933.05, 508.684, 3.22886, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+10 , 31226, 571, 210, 4520, 4, 0, 6523.95, 1943.55, 640.72, 4.08407, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+11 , 31226, 571, 210, 4520, 4, 0, 6433.1, 1895.42, 508.678, 4.11898, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+12 , 31226, 571, 210, 4520, 4, 0, 6456.81, 1881.75, 508.682, 3.9968, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+13 , 31226, 571, 210, 4520, 4, 0, 6531.53, 1874.53, 629.634, 4.64258, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+14 , 31226, 571, 210, 4520, 4, 0, 6431.99, 1812.84, 508.684, 3.4383, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+15 , 31226, 571, 210, 4520, 4, 0, 6555.41, 1876.79, 629.634, 4.62512, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+16 , 31226, 571, 210, 4520, 4, 0, 6432.28, 1788.37, 508.685, 3.14159, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+17 , 31226, 571, 210, 4520, 4, 0, 6382.83, 1777.58, 508.78, 0.767945, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+18 , 31226, 571, 210, 4520, 4, 0, 6389.62, 1751.7, 508.707, 0.15708, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+19 , 31226, 571, 210, 4520, 4, 0, 6326, 1926.51, 508.681, 0.20944, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+20 , 31226, 571, 210, 4520, 4, 0, 6319.5, 1964.06, 508.453, 0.349066, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+21 , 31226, 571, 210, 4520, 4, 0, 6243.68, 1944.27, 631.86, 0.226893, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+22 , 31226, 571, 210, 4520, 4, 0, 6246.83, 1923.25, 631.843, 0.296706, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+23 , 31226, 571, 210, 4520, 4, 0, 6282.74, 1768.32, 525.276, 0.418879, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+24 , 31226, 571, 210, 4520, 4, 0, 6285.05, 1739.98, 525.469, 6.26573, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss'),
(@GUID+25 , 31325, 571, 210, 4520, 4, 1, 6407.34, 1958.04, 631.298, 0.140488, 300, 10, 1, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Movement'),
(@GUID+26 , 31325, 571, 210, 4520, 4, 1, 6361.6, 1932.71, 508.595, 1.69059, 300, 10, 1, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Movement'),
(@GUID+27 , 31325, 571, 210, 4520, 4, 1, 6337.11, 1948.66, 507.983, 4.91094, 300, 10, 1, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Movement'),
(@GUID+28 , 31325, 571, 210, 4520, 4, 1, 6434.97, 1839.88, 508.601, 0.92626, 300, 10, 1, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Movement'),
(@GUID+29 , 31325, 571, 210, 4520, 4, 1, 6553.39, 1861.26, 629.716, 1.60466, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Movement'),
(@GUID+30 , 31325, 571, 210, 4520, 4, 1, 6370.85, 1811.2, 508.601, 5.52566, 300, 10, 1, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Movement'),
(@GUID+31 , 31325, 571, 210, 4520, 4, 1, 6417.08, 1881.77, 508.601, 3.21955, 300, 10, 1, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Movement'),
(@GUID+32 , 31325, 571, 210, 4520, 4, 1, 6348.4, 1857.11, 508.601, 0.0470463, 300, 10, 1, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Movement'),
(@GUID+33 , 31325, 571, 210, 4520, 4, 1, 6278.17, 1938.88, 631.367, 3.29251, 300, 10, 1, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Movement'),
(@GUID+34 , 31325, 571, 210, 4520, 4, 1, 6116.33, 1923.28, 632.661, 6.10865, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Movement'),
(@GUID+35 , 31325, 571, 210, 4520, 4, 1, 6112.24, 1906.16, 632.673, 6.26573, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Movement'),
(@GUID+36 , 31325, 571, 210, 4520, 4, 1, 6259.45, 1808.62, 525.193, 4.829, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Movement'),
(@GUID+37 , 31325, 571, 210, 4520, 4, 1, 6297.2, 1744.42, 525.193, 1.59532, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Movement'),
(@GUID+38 , 31325, 571, 210, 4520, 4, 1, 6545.26, 1632.77, 632.545, 1.55334, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Movement'),
(@GUID+39 , 31325, 571, 210, 4520, 4, 1, 6564.46, 1633.7, 632.528, 1.62316, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Movement'),
(@GUID+40 , 31325, 571, 210, 4520, 4, 1, 6543.76, 1676.96, 629.716, 4.7391, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Movement'),
-- 31326 and 31327 Spar, not necessarily against the other entry, using factions 1847 and 1848
-- Reset behaviours have not been observed, so this will be skipped
(@GUID+41 , 31326, 571, 210, 4520, 4, 1, 6421, 1972.77, 631.884, 5.64803, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+42 , 31326, 571, 210, 4520, 4, 1, 6409.48, 1971.11, 631.886, 5.89921, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+43 , 31326, 571, 210, 4520, 4, 1, 6410.79, 1970.23, 631.859, 2.55091, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+44 , 31326, 571, 210, 4520, 4, 1, 6388.46, 1966.7, 631.854, 2.54847, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+45 , 31326, 571, 210, 4520, 4, 1, 6413.71, 1945.59, 631.885, 1.03795, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+46 , 31326, 571, 210, 4520, 4, 1, 6402.12, 1944.07, 631.88, 0.899389, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+47 , 31326, 571, 210, 4520, 4, 1, 6375.5, 1965.78, 631.88, 5.69264, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+48 , 31326, 571, 210, 4520, 4, 1, 6414.83, 1947.49, 631.842, 4.17954, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+49 , 31326, 571, 210, 4520, 4, 1, 6390.57, 1942.33, 631.88, 0.930497, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+50 , 31326, 571, 210, 4520, 4, 1, 6380.64, 1942.28, 631.845, 4.06142, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+51 , 31326, 571, 210, 4520, 4, 1, 6350.3, 1964.71, 631.734, 5.95226, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+52 , 31326, 571, 210, 4520, 4, 1, 6379.43, 1940.68, 631.88, 0.91983, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+53 , 31326, 571, 210, 4520, 4, 1, 6355.59, 1934.22, 631.734, 0.489751, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+54 , 31326, 571, 210, 4520, 4, 1, 6341.18, 1931.79, 631.734, 2.77019, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+55 , 31326, 571, 210, 4520, 4, 1, 6514.8, 1855.03, 632.15, 3.24635, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+56 , 31326, 571, 210, 4520, 4, 1, 6512.74, 1837.83, 632.15, 5.97852, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+57 , 31326, 571, 210, 4520, 4, 1, 6335.24, 1961.79, 631.734, 0.504561, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+58 , 31326, 571, 210, 4520, 4, 1, 6517.62, 1769.83, 632.15, 3.42335, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+59 , 31326, 571, 210, 4520, 4, 1, 6515.39, 1769.18, 632.15, 0.281759, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+60 , 31326, 571, 210, 4520, 4, 1, 6316.04, 1931.22, 631.879, 2.49931, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+61 , 31326, 571, 210, 4520, 4, 1, 6293.26, 1927.77, 631.881, 2.54989, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+62 , 31326, 571, 210, 4520, 4, 1, 6314.37, 1932.47, 631.842, 5.6409, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+63 , 31326, 571, 210, 4520, 4, 1, 6303.14, 1930.49, 631.849, 5.67288, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+64 , 31326, 571, 210, 4520, 4, 1, 6288.14, 1951.45, 631.849, 0.969426, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+65 , 31326, 571, 210, 4520, 4, 1, 6259.95, 1923.17, 631.88, 2.52023, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+66 , 31326, 571, 210, 4520, 4, 1, 6289.28, 1953.11, 631.886, 4.11102, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+67 , 31326, 571, 210, 4520, 4, 1, 6254.01, 1946.15, 631.857, 0.823756, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+68 , 31326, 571, 210, 4520, 4, 1, 6299.69, 1953.39, 631.853, 0.815526, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+69 , 31326, 571, 210, 4520, 4, 1, 6276.51, 1949.8, 631.85, 0.849777, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+70 , 31326, 571, 210, 4520, 4, 1, 6255.31, 1947.56, 631.884, 3.87463, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+71 , 31326, 571, 210, 4520, 4, 1, 6268.72, 1925.74, 631.84, 5.70028, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+72 , 31326, 571, 210, 4520, 4, 1, 6300.99, 1954.76, 631.882, 3.95712, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+73 , 31326, 571, 210, 4520, 4, 1, 6521.29, 1666.02, 632.15, 2.81779, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+74 , 31326, 571, 210, 4520, 4, 1, 6566, 1681.54, 629.634, 1.60577, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+75 , 31326, 571, 210, 4520, 4, 1, 6519.12, 1683.8, 632.15, 3.58536, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+76 , 31326, 571, 210, 4520, 4, 1, 6565.26, 1706.1, 629.634, 4.71059, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+77 , 31326, 571, 210, 4520, 4, 1, 6565.25, 1704.2, 629.634, 1.569, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+78 , 31327, 571, 210, 4520, 4, 1, 6422.62, 1971.57, 631.849, 2.50643, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+79 , 31327, 571, 210, 4520, 4, 1, 6398.41, 1969.36, 631.884, 5.76359, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+80 , 31327, 571, 210, 4520, 4, 1, 6399.89, 1968.52, 631.858, 2.62199, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+81 , 31327, 571, 210, 4520, 4, 1, 6387.05, 1967.65, 631.883, 5.8294, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+82 , 31327, 571, 210, 4520, 4, 1, 6426.32, 1949.09, 631.845, 4.12847, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+83 , 31327, 571, 210, 4520, 4, 1, 6403.49, 1945.79, 631.843, 4.04098, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+84 , 31327, 571, 210, 4520, 4, 1, 6391.79, 1943.95, 631.844, 4.07209, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+85 , 31327, 571, 210, 4520, 4, 1, 6376.98, 1964.78, 631.85, 2.42601, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+86 , 31327, 571, 210, 4520, 4, 1, 6425, 1947.09, 631.889, 0.986876, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+87 , 31327, 571, 210, 4520, 4, 1, 6352.29, 1964.02, 631.734, 2.81067, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+88 , 31327, 571, 210, 4520, 4, 1, 6357, 1934.97, 631.734, 3.63134, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+89 , 31327, 571, 210, 4520, 4, 1, 6336.87, 1962.69, 631.734, 3.64615, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+90 , 31327, 571, 210, 4520, 4, 1, 6339.55, 1932.42, 631.734, 5.91178, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+91 , 31327, 571, 210, 4520, 4, 1, 6512.19, 1854.76, 632.15, 0.104753, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+92 , 31327, 571, 210, 4520, 4, 1, 6514.94, 1837.14, 632.15, 2.83693, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+93 , 31327, 571, 210, 4520, 4, 1, 6514.89, 1751.23, 632.15, 5.98097, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+94 , 31327, 571, 210, 4520, 4, 1, 6517.42, 1750.44, 632.15, 2.83938, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+95 , 31327, 571, 210, 4520, 4, 1, 6291.56, 1928.92, 631.846, 5.69148, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+96 , 31327, 571, 210, 4520, 4, 1, 6312.67, 1956.56, 631.884, 3.9432, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+97 , 31327, 571, 210, 4520, 4, 1, 6311.42, 1955.28, 631.857, 0.80161, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+98 , 31327, 571, 210, 4520, 4, 1, 6282.06, 1925.98, 631.883, 2.56944, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+99 , 31327, 571, 210, 4520, 4, 1, 6304.76, 1929.36, 631.883, 2.42601, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+100, 31327, 571, 210, 4520, 4, 1, 6280.15, 1927.21, 631.845, 5.71103, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+101, 31327, 571, 210, 4520, 4, 1, 6277.85, 1951.31, 631.883, 3.99137, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+102, 31327, 571, 210, 4520, 4, 1, 6265, 1947.88, 631.846, 0.792263, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+103, 31327, 571, 210, 4520, 4, 1, 6270.51, 1924.56, 631.875, 2.55869, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+104, 31327, 571, 210, 4520, 4, 1, 6266.5, 1949.4, 631.877, 3.93386, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+105, 31327, 571, 210, 4520, 4, 1, 6258.28, 1924.36, 631.848, 5.66182, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+106, 31327, 571, 210, 4520, 4, 1, 6517.89, 1667.16, 632.15, 5.95938, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+107, 31327, 571, 210, 4520, 4, 1, 6565.9, 1684.19, 629.634, 4.74737, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring'),
(@GUID+108, 31327, 571, 210, 4520, 4, 1, 6516.86, 1682.72, 632.15, 0.443765, 300, 0, 0, 52237, 1, 'Phase Shift 2: Malykriss, WIP: Sparring');
-- Baelok
DELETE FROM `waypoint_data` WHERE `id` = @GUID*10;
INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`) VALUES
(@GUID*10, 1, 6408.756, 1725.8109, 508.60083, 6.021385669708251953, 5000, 0), -- Guessed delay, incomplete path
(@GUID*10, 2, 6417.155, 1737.2736, 508.6008, NULL, 0, 0),
(@GUID*10, 3, 6430.235, 1737.4037, 508.60077, NULL, 0, 0);
DELETE FROM `creature_addon` WHERE `guid` = @GUID;
INSERT INTO `creature_addon` (`guid`, `path_id`, `bytes2`, `auras`) VALUES
(@GUID, @GUID*10, 1, NULL);
-- Worst part: Creatures from this phase are different id than those from phase 1, these are duplicated from what we already have because what I have on hand is basically the same thing
-- We can't really just upgrade their phases since then invisible players would be killing visible enemies
DELETE FROM `creature` WHERE `guid` BETWEEN @GUID+109 AND @GUID+172 AND `phaseMask` IN (4) AND `areaId` IN (4520);
INSERT INTO `creature` (`guid`, `id1`, `map`, `zoneId`, `areaId`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `MovementType`, `Comment`) VALUES
(@GUID+109, 31321, 571, 210, 4520, 4, 1, 6467.82, 1811.16, 527.525, 5.67232, 300, 0, 0, 'WIP'),
(@GUID+110, 31321, 571, 210, 4520, 4, 1, 6369.65, 1665.45, 555.737, 5.51524, 300, 0, 0, 'WIP'),
(@GUID+111, 31321, 571, 210, 4520, 4, 1, 6311.05, 1824.67, 510.092, 5.42797, 300, 0, 0, 'WIP'),
(@GUID+112, 31321, 571, 210, 4520, 4, 1, 6328.69, 1820.64, 509.913, 3.47321, 300, 0, 0, 'WIP'),
(@GUID+113, 31321, 571, 210, 4520, 4, 1, 6371.53, 1748.72, 525.308, 5.28835, 300, 0, 0, 'WIP'),
(@GUID+114, 31321, 571, 210, 4520, 4, 1, 6344.04, 1769.24, 525.375, 3.64774, 300, 0, 0, 'WIP'),
(@GUID+115, 31321, 571, 210, 4520, 4, 1, 6355.53, 1764.52, 525.276, 4.76475, 300, 0, 0, 'WIP'),
(@GUID+116, 31321, 571, 210, 4520, 4, 1, 6323.64, 1716.53, 525.551, 5.72468, 300, 0, 0, 'WIP'),
(@GUID+117, 31321, 571, 210, 4520, 4, 1, 6323.45, 1731.48, 525.515, 6.23082, 300, 0, 0, 'WIP'),
(@GUID+118, 31321, 571, 210, 4520, 4, 1, 6329.26, 1748.75, 525.276, 1.11701, 300, 0, 0, 'WIP'),
(@GUID+119, 31321, 571, 210, 4520, 4, 1, 6360.59, 1736.24, 525.276, 4.13643, 300, 0, 0, 'WIP'),
(@GUID+120, 31321, 571, 210, 4520, 4, 1, 6343.99, 1750.79, 525.739, 2.80998, 300, 0, 0, 'WIP'),
(@GUID+121, 31321, 571, 210, 4520, 4, 1, 6333.84, 1766.47, 525.276, 5.02655, 300, 0, 0, 'WIP'),
(@GUID+122, 31321, 571, 210, 4520, 4, 1, 6350.36, 1731.27, 525.276, 4.7822, 300, 0, 0, 'WIP'),
(@GUID+123, 31321, 571, 210, 4520, 4, 1, 6322.36, 1765.4, 525.276, 0.523599, 300, 0, 0, 'WIP'),
(@GUID+124, 31321, 571, 210, 4520, 4, 1, 6339.15, 1732.77, 525.276, 4.45059, 300, 0, 0, 'WIP'),
(@GUID+125, 31321, 571, 210, 4520, 4, 1, 6334.4, 1717.4, 525.276, 1.79769, 300, 0, 0, 'WIP'),
(@GUID+126, 31321, 571, 210, 4520, 4, 1, 6357.46, 1718.11, 525.276, 1.13446, 300, 0, 0, 'WIP'),
(@GUID+127, 31321, 571, 210, 4520, 4, 1, 6361.38, 1751.44, 525.581, 2.77507, 300, 0, 0, 'WIP'),
(@GUID+128, 31321, 571, 210, 4520, 4, 1, 6346.33, 1715.18, 525.276, 2.84489, 300, 0, 0, 'WIP'),
(@GUID+129, 31320, 571, 210, 4520, 4, 0, 6461.65, 1811.79, 526.024, 1.28865, 300, 0, 2, 'WIP'),
(@GUID+130, 31320, 571, 210, 4520, 4, 0, 6353.97, 1712.15, 525.317, 2.58031, 300, 0, 2, 'WIP'),
(@GUID+131, 31322, 571, 210, 4520, 4, 0, 6504.06, 1844.93, 508.697, 0.10472, 300, 5, 1, 'WIP'),
(@GUID+132, 31323, 571, 210, 4520, 4, 0, 6550.48, 1680.94, 629.651, 4.31997, 300, 5, 1, 'WIP'),
(@GUID+133, 31323, 571, 210, 4520, 4, 0, 6595.72, 1843.64, 672.109, 3.07178, 300, 5, 1, 'WIP'),
(@GUID+134, 31323, 571, 210, 4520, 4, 0, 6507.37, 1668.65, 632.067, 3.78131, 300, 5, 1, 'WIP'),
(@GUID+135, 31323, 571, 210, 4520, 4, 0, 6546.2, 1834.68, 629.651, 1.10748, 300, 5, 1, 'WIP'),
(@GUID+136, 31323, 571, 210, 4520, 4, 0, 6554.25, 1799.26, 629.651, 5.65689, 300, 5, 1, 'WIP'),
(@GUID+137, 31323, 571, 210, 4520, 4, 0, 6509.91, 1839.99, 632.067, 5.25873, 300, 5, 1, 'WIP'),
(@GUID+138, 31323, 571, 210, 4520, 4, 0, 6551.18, 1707.41, 629.651, 2.46494, 300, 5, 1, 'WIP'),
(@GUID+139, 31323, 571, 210, 4520, 4, 0, 6546.51, 1767.71, 629.651, 4.41886, 300, 5, 1, 'WIP'),
(@GUID+140, 31323, 571, 210, 4520, 4, 0, 6550.06, 1740.42, 629.651, 5.29382, 300, 0, 0, 'WIP'),
(@GUID+141, 31323, 571, 210, 4520, 4, 0, 6227.2, 1877.56, 631.58, 5.79449, 300, 0, 0, 'WIP'),
(@GUID+142, 31323, 571, 210, 4520, 4, 0, 6362.5, 1872.02, 508.726, 2.54692, 300, 5, 1, 'WIP'),
(@GUID+143, 31323, 571, 210, 4520, 4, 0, 6420.17, 1862.48, 508.726, 3.89239, 300, 5, 1, 'WIP'),
(@GUID+144, 31323, 571, 210, 4520, 4, 0, 6394.7, 1951.5, 631.629, 3.48342, 300, 5, 1, 'WIP'),
(@GUID+145, 31323, 571, 210, 4520, 4, 0, 6271.5, 1935.59, 631.49, 3.18501, 300, 5, 1, 'WIP'),
(@GUID+146, 31323, 571, 210, 4520, 4, 0, 6349.53, 1953.5, 631.751, 4.07865, 300, 5, 1, 'WIP'),
(@GUID+147, 31323, 571, 210, 4520, 4, 0, 6305.2, 1934.09, 631.785, 5.88206, 300, 5, 1, 'WIP'),
(@GUID+148, 31323, 571, 210, 4520, 4, 0, 6430.93, 1962.52, 631.463, 4.50238, 300, 0, 0, 'WIP'),
(@GUID+149, 31323, 571, 210, 4520, 4, 0, 6402.65, 1952.95, 631.615, 3.48321, 300, 5, 1, 'WIP'),
(@GUID+150, 31320, 571, 210, 4520, 4, 0, 6315.75, 1749.75, 525.318, 6.10961, 300, 5, 1, 'WIP'),
(@GUID+151, 31320, 571, 210, 4520, 4, 0, 6347.47, 1653.42, 555.433, 0.048457, 300, 5, 1, 'WIP'),
(@GUID+152, 31320, 571, 210, 4520, 4, 0, 6275.29, 1841.61, 523.07, 3.07487, 300, 5, 1, 'WIP'),
(@GUID+153, 31320, 571, 210, 4520, 4, 0, 6319.39, 1767.24, 525.262, 5.62052, 300, 5, 1, 'WIP'),
(@GUID+154, 31321, 571, 210, 4520, 4, 1, 6352.03, 1742.87, 525.318, 3.21439, 300, 0, 0, 'WIP'),
(@GUID+155, 31320, 571, 210, 4520, 4, 0, 6319.64, 1728.98, 525.212, 1.56194, 300, 5, 1, 'WIP'),
(@GUID+156, 31320, 571, 210, 4520, 4, 0, 6355.55, 1746.02, 525.318, 3.19243, 300, 5, 1, 'WIP'),
(@GUID+157, 31320, 571, 210, 4520, 4, 0, 6291.59, 1703.77, 527.392, 0.936473, 300, 5, 1, 'WIP'),
(@GUID+158, 31324, 571, 210, 4520, 4, 0, 6420.04, 1687.55, 569.111, 1.48353, 300, 0, 0, 'WIP'),
(@GUID+159, 31324, 571, 210, 4520, 4, 0, 6405.54, 1653.2, 579.39, 2.30383, 300, 0, 0, 'WIP'),
(@GUID+160, 31324, 571, 210, 4520, 4, 0, 6400.35, 1643.93, 600.349, 2.33874, 300, 0, 0, 'WIP'),
(@GUID+161, 31324, 571, 210, 4520, 4, 0, 6381.31, 1715.12, 546.677, 1.62316, 300, 0, 0, 'WIP'),
(@GUID+162, 31324, 571, 210, 4520, 4, 0, 6208.67, 1793.61, 617.382, 0.593412, 300, 0, 0, 'WIP'),
(@GUID+163, 31324, 571, 210, 4520, 4, 0, 6205.06, 1767.97, 619.533, 0.750492, 300, 0, 0, 'WIP'),
(@GUID+164, 31324, 571, 210, 4520, 4, 0, 6241.39, 1706.26, 599.038, 0, 300, 0, 0, 'WIP'),
(@GUID+165, 31324, 571, 210, 4520, 4, 0, 6472.36, 1677.34, 576.605, 2.35619, 300, 0, 0, 'WIP'),
(@GUID+166, 31324, 571, 210, 4520, 4, 0, 6429.15, 1660.39, 595.302, 2.42601, 300, 0, 0, 'WIP'),
(@GUID+167, 31324, 571, 210, 4520, 4, 0, 6216.64, 1785.2, 592.153, 0.750492, 300, 0, 0, 'WIP'),
(@GUID+168, 31324, 571, 210, 4520, 4, 0, 6257.61, 1739.57, 581.576, 6.16101, 300, 0, 0, 'WIP'),
(@GUID+169, 31324, 571, 210, 4520, 4, 0, 6238.85, 1729.19, 598.615, 0.017453, 300, 0, 0, 'WIP'),
(@GUID+170, 31324, 571, 210, 4520, 4, 0, 6220.54, 1703.19, 627.699, 5.48033, 300, 0, 0, 'WIP'),
(@GUID+171, 31324, 571, 210, 4520, 4, 0, 6385.01, 1703.41, 563.539, 1.50098, 300, 0, 0, 'WIP'),
(@GUID+172, 31324, 571, 210, 4520, 4, 0, 6235.08, 1762.35, 594.648, 0.628319, 300, 0, 0, 'WIP');
DELETE FROM `creature_addon` WHERE `guid` BETWEEN @GUID+109 AND @GUID+131;
INSERT INTO `creature_addon` (`guid`, `path_id`, `bytes2`, `emote`, `auras`) VALUES
(@GUID+109, 0, 1, 133, NULL),
(@GUID+110, 0, 1, 133, NULL),
(@GUID+111, 0, 1, 133, NULL),
(@GUID+112, 0, 1, 133, NULL),
(@GUID+113, 0, 1, 133, NULL),
(@GUID+114, 0, 1, 233, NULL),
(@GUID+115, 0, 1, 133, NULL),
(@GUID+116, 0, 1, 233, NULL),
(@GUID+117, 0, 1, 233, NULL),
(@GUID+118, 0, 1, 133, NULL),
(@GUID+119, 0, 1, 233, NULL),
(@GUID+120, 0, 1, 233, NULL),
(@GUID+121, 0, 1, 133, NULL),
(@GUID+122, 0, 1, 133, NULL),
(@GUID+123, 0, 1, 233, NULL),
(@GUID+124, 0, 1, 233, NULL),
(@GUID+125, 0, 1, 133, NULL),
(@GUID+126, 0, 1, 133, NULL),
(@GUID+127, 0, 1, 233, NULL),
(@GUID+128, 0, 1, 233, NULL),
(@GUID+129, 1242670, 1, 0, NULL),
(@GUID+130, 1242710, 1, 0, NULL),
(@GUID+131, 0, 1, 173, NULL);
@@ -0,0 +1,18 @@
-- DB update 2026_01_16_00 -> 2026_01_17_00
--
DELETE FROM `prospecting_loot_template` WHERE (`Entry` = 23424);
INSERT INTO `prospecting_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(23424, 21929, 0, 0, 0, 1, 1, 1, 2, 'Flame Spessarite'),
(23424, 23077, 0, 0, 0, 1, 1, 1, 2, 'Blood Garnet'),
(23424, 23079, 0, 0, 0, 1, 1, 1, 2, 'Deep Peridot'),
(23424, 23107, 0, 0, 0, 1, 1, 1, 2, 'Shadow Draenite'),
(23424, 23112, 0, 0, 0, 1, 1, 1, 2, 'Golden Draenite'),
(23424, 23117, 0, 0, 0, 1, 1, 1, 2, 'Azure Moonstone'),
(23424, 23436, 0, 4, 0, 1, 2, 1, 1, 'Living Ruby'),
(23424, 23437, 0, 4, 0, 1, 2, 1, 1, 'Talasite'),
(23424, 23438, 0, 4, 0, 1, 2, 1, 1, 'Star of Elune'),
(23424, 23439, 0, 4, 0, 1, 2, 1, 1, 'Noble Topaz'),
(23424, 23440, 0, 4, 0, 1, 2, 1, 1, 'Dawnstone'),
(23424, 23441, 0, 4, 0, 1, 2, 1, 1, 'Nightseye');
DELETE FROM `reference_loot_template` WHERE `Entry` = 1000;
@@ -0,0 +1,11 @@
-- DB update 2026_01_17_00 -> 2026_01_17_01
--
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 26261) AND (`source_type` = 0) AND (`id` IN (0));
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`, `event_param6`, `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
(26261, 0, 0, 0, 8, 0, 100, 512, 47394, 0, 0, 0, 0, 0, 80, 2626100, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grizzly Hills Giant - On Spellhit \'Kurun\'s Blessing\' - Run Script');
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 17) AND (`SourceGroup` = 0) AND (`SourceEntry` = 47394) AND (`SourceId` = 0) AND (`ElseGroup` = 0) AND (`ConditionTypeOrReference` = 29) AND (`ConditionTarget` = 1) AND (`ConditionValue1` = 26417) AND (`ConditionValue2` = 15) AND (`ConditionValue3` = 0);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(17, 0, 47394, 0, 0, 29, 1, 26417, 15, 0, 0, 0, 0, '', 'For Kurun\'s Blessing (47394) to have an effect the target Grizzly Hills Giant (26261) must be engaged with a Runed Giant (26417)');
UPDATE `creature` SET `spawntimesecs` = 120 WHERE `id1` = 26261;
@@ -0,0 +1,3 @@
-- DB update 2026_01_17_01 -> 2026_01_18_00
-- Sets "Spiritsbreath" to be 100 from 58 % drop rate for "Grumbald One-Eye"
UPDATE `creature_loot_template` SET `Chance` = 100 WHERE `Entry` = 26681 AND `Item` = 36740;
@@ -0,0 +1,9 @@
-- DB update 2026_01_18_00 -> 2026_01_18_01
-- Add skinning loot table for creature 1933 (Sheep) to enable Ruined Leather Scraps, Wool Cloth, and Light Leather drops.
UPDATE `creature_template` SET `skinloot` = 1933 WHERE (`entry` = 1933);
DELETE FROM `skinning_loot_template` WHERE (`Entry` = 1933);
INSERT INTO `skinning_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(1933, 2934, 0, 55, 0, 1, 1, 1, 1, 'Ruined Leather Scraps'),
(1933, 2592, 0, 35, 0, 1, 1, 1, 1, 'Wool Cloth'),
(1933, 2318, 0, 10, 0, 1, 1, 1, 1, 'Light Leather');
@@ -0,0 +1,5 @@
-- DB update 2026_01_18_01 -> 2026_01_18_02
--
UPDATE `trainer_spell` SET `ReqSkillRank`=275 WHERE `SpellId`=29356;
UPDATE `trainer_spell` SET `ReqSkillRank`=230 WHERE `SpellId`=16153;
UPDATE `trainer_spell` SET `ReqSkillRank`=375 WHERE `SpellId`=29361;
@@ -0,0 +1,40 @@
-- DB update 2026_01_18_02 -> 2026_01_19_00
--
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24539);
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`, `event_param6`, `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
(24539, 0, 0, 0, 0, 0, 100, 0, 3000, 6000, 15000, 22000, 0, 0, 11, 15091, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '\'Silvermoon\' Harry - In Combat - Cast \'Blast Wave\''),
(24539, 0, 1, 0, 0, 0, 100, 0, 2500, 4000, 4000, 5000, 0, 0, 11, 50183, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, '\'Silvermoon\' Harry - In Combat - Cast \'Scorch\''),
(24539, 0, 2, 0, 62, 0, 100, 0, 9010, 0, 0, 0, 0, 0, 80, 2453900, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '"Silvermoon" Harry - On Gossip Option "Taruk sent me to collect" Selected - Run Script: Attack'),
(24539, 0, 3, 4, 62, 0, 100, 0, 9011, 0, 0, 0, 0, 0, 56, 34115, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '"Silvermoon" Harry - On Gossip Option "Pay up, Harry!" Selected - Add Item \'"Silvermoon" Harry\'s Debt\' 1 Time'),
(24539, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '"Silvermoon" Harry - On Gossip Option 0 Selected - Close Gossip'),
(24539, 0, 5, 0, 2, 0, 100, 0, 0, 50, 30000, 30000, 0, 0, 80, 2453901, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '"Silvermoon" Harry - Between 0-50% Health - Run Script: Give Up Fight'),
(24539, 0, 7, 0, 32, 0, 100, 0, 0, 1000000, 15000, 15000, 0, 0, 42, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '"Silvermoon" Harry - On Damaged by Condition: Player in Quest - Set Invincibility'),
(24539, 0, 8, 0, 32, 0, 100, 0, 0, 1000000, 15000, 15000, 0, 0, 42, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '"Silvermoon" Harry - On Damaged by Condition: Player NOT in Quest - Remove Invincibility'),
(24539, 0, 9, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 240, 9010, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '"Silvermoon" Harry - Actionlist - Reset GossipMenuID to 9010'),
(24539, 0, 10, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 2, 1888, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '"Silvermoon" Harry - Actionlist - Reset Faction');
DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 2453900);
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`, `event_param6`, `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
(2453900, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '\'Silvermoon\' Harry - On Script - Say Line 0'),
(2453900, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 83, 131, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '"Silvermoon" Harry - Actionlist - Remove Npc Flags Gossip & Questgiver & Vendor'),
(2453900, 9, 2, 0, 0, 0, 100, 0, 1200, 1200, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 21, 10, 0, 0, 0, 0, 0, 0, 0, '"Silvermoon" Harry - Actionlist - Start Attacking');
DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 2453901);
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`, `event_param6`, `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
(2453901, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '"Silvermoon" Harry - Actionlist - Say Line 1'),
(2453901, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 2, 1080, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '"Silvermoon" Harry - Actionlist - Set Faction Friendly'),
(2453901, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '"Silvermoon" Harry - Actionlist - Evade'),
(2453901, 9, 3, 0, 0, 0, 100, 0, 2400, 2400, 0, 0, 0, 0, 82, 131, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '"Silvermoon" Harry - Actionlist - Add Npc Flags Gossip & Questgiver & Vendor'),
(2453901, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 240, 9011, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '"Silvermoon" Harry - Actionlist - Change GossipMenuID to 9011'),
(2453901, 9, 5, 0, 0, 0, 100, 0, 60000, 60000, 0, 0, 0, 0, 240, 9010, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '"Silvermoon" Harry - Actionlist - Reset GossipMenuID to 9010'),
(2453901, 9, 6, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 2, 1888, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '"Silvermoon" Harry - Actionlist - Reset Faction');
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 22) AND (`SourceEntry` = 24539) AND (`SourceId` = 0) AND (`ElseGroup` = 0) AND (`ConditionTypeOrReference` = 47);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(22, 8, 24539, 0, 0, 47, 0, 11464, 8, 0, 0, 0, 0, '', 'Only Play Script if Quest \'Gambling Debt\' (11464) is in progress'),
(22, 9, 24539, 0, 0, 47, 0, 11464, 8, 0, 1, 0, 0, '', 'Only Play Script if Quest \'Gambling Debt\' (11464) is in progress');
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 15) AND (`SourceGroup` IN (9010,9011)) AND (`ConditionTypeOrReference` = 2) AND (`ConditionValue1` = 34115);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(15, 9010, 0, 0, 0, 2, 0, 34115, 1, 0, 1, 0, 0, '', 'Only Show Gossip Option for quest Gambling Debt (11464) if player does not have Quest Item "Silvermoon" Harry\'s Debt (34115)'),
(15, 9011, 0, 0, 0, 2, 0, 34115, 1, 0, 1, 0, 0, '', 'Only Show Gossip Option for quest Gambling Debt (11464) if player does not have Quest Item "Silvermoon" Harry\'s Debt (34115)');
@@ -0,0 +1,31 @@
-- DB update 2026_01_19_00 -> 2026_01_19_01
-- Edit Spawn Time (Captured Rageclaw & Drakuru Shackles)
UPDATE `creature` SET `spawntimesecs` = 30 WHERE (`id1` IN (29700, 29686));
-- Remove C++ script and set SAI for Drakuru Shackles & Captured Rageclaw
UPDATE `creature_template` SET `AIName` = 'SmartAI', `ScriptName` = '' WHERE (`entry` IN (29700, 29686));
DELETE FROM `smart_scripts` WHERE (`source_type` = 0) AND (`entryorguid` IN (29700, 29686));
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`, `event_param6`, `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
(29700, 0, 0, 0, 8, 0, 100, 0, 54990, 0, 0, 0, 0, 0, 11, 55009, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Drakuru Shackles - On Spellhit \'Chains of the Scourge\' - Cast \'Chains of the Scourge\''),
(29700, 0, 1, 2, 8, 0, 100, 0, 55083, 0, 0, 0, 0, 0, 33, 29686, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Drakuru Shackles - On Spellhit \'Unlock Shackle\' - Quest Credit \'Captured Rageclaw\''),
(29700, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 223, 27, 0, 0, 0, 0, 0, 9, 29686, 0, 5, 1, 0, 0, 0, 0, 'Drakuru Shackles - On Spellhit \'Unlock Shackle\' - Do Action ID 27'),
(29686, 0, 0, 1, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 90, 8, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Captured Rageclaw - On Respawn - Set Flag Standstate Kneel'),
(29686, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 54990, 0, 0, 0, 0, 0, 9, 29700, 0, 5, 1, 0, 0, 0, 0, 'Captured Rageclaw - On Respawn - Cast \'Chains of the Scourge\''),
(29686, 0, 2, 3, 72, 0, 100, 0, 27, 0, 0, 0, 0, 0, 91, 8, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Captured Rageclaw - On Action 27 Done - Remove FlagStandstate Kneel'),
(29686, 0, 3, 4, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Captured Rageclaw - On Action 27 Done - Remove Aura \'all\''),
(29686, 0, 4, 5, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 55085, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Captured Rageclaw - On Action 27 Done - Cast \'Unshackled!\''),
(29686, 0, 5, 6, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Captured Rageclaw - On Action 27 Done - Say Line 0'),
(29686, 0, 6, 7, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 89, 5, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Captured Rageclaw - On Action 27 Done - Start Random Movement'),
(29686, 0, 7, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 12000, 30000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Captured Rageclaw - On Action 27 Done - Despawn In 12000 ms');
-- Set condition for Chains of the Scourge
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 13) AND (`SourceGroup` = 1) AND (`SourceEntry` = 54990) AND (`SourceId` = 0) AND (`ElseGroup` = 0) AND (`ConditionTypeOrReference` = 31) AND (`ConditionTarget` = 0) AND (`ConditionValue1` = 3) AND (`ConditionValue2` = 29700) AND (`ConditionValue3` = 0);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(13, 1, 54990, 0, 0, 31, 0, 3, 29700, 0, 0, 0, 0, '', 'Chains of the Scourge has Drakuru Shackles as implicit target');
-- Set condition for Unlock Shackle (prevent item spamming if Rageclaw is not chained/present)
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 13) AND (`SourceGroup` = 3) AND (`SourceEntry` = 55083) AND (`SourceId` = 0) AND (`ElseGroup` = 0) AND (`ConditionTypeOrReference` = 1) AND (`ConditionTarget` = 0) AND (`ConditionValue1` = 54990) AND (`ConditionValue2` = 0) AND (`ConditionValue3` = 0);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(13, 3, 55083, 0, 0, 1, 0, 54990, 0, 0, 0, 0, 0, '', 'Unlock Shackle target must have Chains of the Scourge aura.');
+388
View File
@@ -0,0 +1,388 @@
-- DB update 2026_01_19_01 -> 2026_01_20_00
-- Updates 3 vendors that spawn with arena season 5 to include missing items and correct costs.
DELETE FROM `npc_vendor` WHERE (`entry` IN (31863, 32407, 32405));
INSERT INTO `npc_vendor` (`entry`, `slot`, `item`, `maxcount`, `incrtime`, `ExtendedCost`, `VerifiedBuild`) VALUES
(31863, 0, 40784, 0, 0, 2462, 0),
(31863, 0, 40785, 0, 0, 2462, 0),
(31863, 0, 40786, 0, 0, 2462, 0),
(31863, 0, 40804, 0, 0, 2463, 0),
(31863, 0, 40805, 0, 0, 2463, 0),
(31863, 0, 40806, 0, 0, 2463, 0),
(31863, 0, 40823, 0, 0, 2464, 0),
(31863, 0, 40824, 0, 0, 2464, 0),
(31863, 0, 40825, 0, 0, 2464, 0),
(31863, 0, 40844, 0, 0, 2465, 0),
(31863, 0, 40845, 0, 0, 2465, 0),
(31863, 0, 40846, 0, 0, 2465, 0),
(31863, 0, 40862, 0, 0, 2470, 0),
(31863, 0, 40863, 0, 0, 2470, 0),
(31863, 0, 40864, 0, 0, 2470, 0),
(31863, 0, 40905, 0, 0, 2462, 0),
(31863, 0, 40926, 0, 0, 2463, 0),
(31863, 0, 40932, 0, 0, 2464, 0),
(31863, 0, 40938, 0, 0, 2465, 0),
(31863, 0, 40962, 0, 0, 2470, 0),
(31863, 0, 40990, 0, 0, 2462, 0),
(31863, 0, 40991, 0, 0, 2462, 0),
(31863, 0, 41000, 0, 0, 2463, 0),
(31863, 0, 41006, 0, 0, 2463, 0),
(31863, 0, 41012, 0, 0, 2464, 0),
(31863, 0, 41018, 0, 0, 2464, 0),
(31863, 0, 41026, 0, 0, 2465, 0),
(31863, 0, 41032, 0, 0, 2465, 0),
(31863, 0, 41037, 0, 0, 2470, 0),
(31863, 0, 41043, 0, 0, 2470, 0),
(31863, 0, 41080, 0, 0, 2462, 0),
(31863, 0, 41086, 0, 0, 2462, 0),
(31863, 0, 41136, 0, 0, 2463, 0),
(31863, 0, 41142, 0, 0, 2463, 0),
(31863, 0, 41150, 0, 0, 2464, 0),
(31863, 0, 41156, 0, 0, 2464, 0),
(31863, 0, 41198, 0, 0, 2465, 0),
(31863, 0, 41204, 0, 0, 2465, 0),
(31863, 0, 41210, 0, 0, 2470, 0),
(31863, 0, 41216, 0, 0, 2470, 0),
(31863, 0, 41274, 0, 0, 2470, 0),
(31863, 0, 41280, 0, 0, 2470, 0),
(31863, 0, 41286, 0, 0, 2463, 0),
(31863, 0, 41292, 0, 0, 2463, 0),
(31863, 0, 41297, 0, 0, 2465, 0),
(31863, 0, 41303, 0, 0, 2465, 0),
(31863, 0, 41309, 0, 0, 2462, 0),
(31863, 0, 41315, 0, 0, 2462, 0),
(31863, 0, 41320, 0, 0, 2464, 0),
(31863, 0, 41326, 0, 0, 2464, 0),
(31863, 0, 41649, 0, 0, 2462, 0),
(31863, 0, 41654, 0, 0, 2465, 0),
(31863, 0, 41660, 0, 0, 2462, 0),
(31863, 0, 41666, 0, 0, 2465, 0),
(31863, 0, 41671, 0, 0, 2464, 0),
(31863, 0, 41677, 0, 0, 2464, 0),
(31863, 0, 41682, 0, 0, 2470, 0),
(31863, 0, 41714, 0, 0, 2470, 0),
(31863, 0, 41766, 0, 0, 2463, 0),
(31863, 0, 41772, 0, 0, 2463, 0),
(31863, 0, 41853, 0, 0, 2464, 0),
(31863, 0, 41858, 0, 0, 2462, 0),
(31863, 0, 41863, 0, 0, 2465, 0),
(31863, 0, 41868, 0, 0, 2470, 0),
(31863, 0, 41873, 0, 0, 2463, 0),
(31863, 0, 41914, 0, 0, 2464, 0),
(31863, 0, 41920, 0, 0, 2462, 0),
(31863, 0, 41926, 0, 0, 2465, 0),
(31863, 0, 41933, 0, 0, 2470, 0),
(31863, 0, 41939, 0, 0, 2463, 0),
(31863, 0, 41945, 0, 0, 2464, 0),
(31863, 0, 41951, 0, 0, 2462, 0),
(31863, 0, 41958, 0, 0, 2465, 0),
(31863, 0, 41964, 0, 0, 2470, 0),
(31863, 0, 41970, 0, 0, 2463, 0),
(31863, 0, 41992, 0, 0, 2464, 0),
(31863, 0, 41997, 0, 0, 2462, 0),
(31863, 0, 42004, 0, 0, 2465, 0),
(31863, 0, 42010, 0, 0, 2470, 0),
(31863, 0, 42016, 0, 0, 2463, 0),
(31863, 0, 42208, 0, 0, 2466, 0),
(31863, 0, 42227, 0, 0, 2467, 0),
(31863, 0, 42232, 0, 0, 2467, 0),
(31863, 0, 42237, 0, 0, 2468, 0),
(31863, 0, 42242, 0, 0, 2466, 0),
(31863, 0, 42248, 0, 0, 2467, 0),
(31863, 0, 42255, 0, 0, 2467, 0),
(31863, 0, 42260, 0, 0, 2466, 0),
(31863, 0, 42265, 0, 0, 2467, 0),
(31863, 0, 42270, 0, 0, 2467, 0),
(31863, 0, 42275, 0, 0, 2466, 0),
(31863, 0, 42280, 0, 0, 2467, 0),
(31863, 0, 42285, 0, 0, 2466, 0),
(31863, 0, 42290, 0, 0, 2467, 0),
(31863, 0, 42317, 0, 0, 2460, 0),
(31863, 0, 42322, 0, 0, 2460, 0),
(31863, 0, 42327, 0, 0, 2460, 0),
(31863, 0, 42332, 0, 0, 2460, 0),
(31863, 0, 42346, 0, 0, 2466, 0),
(31863, 0, 42352, 0, 0, 2466, 0),
(31863, 0, 42362, 0, 0, 2460, 0),
(31863, 0, 42384, 0, 0, 2460, 0),
(31863, 0, 42390, 0, 0, 2460, 0),
(31863, 0, 42525, 0, 0, 2467, 0),
(31863, 0, 42531, 0, 0, 2467, 0),
(31863, 0, 42537, 0, 0, 2467, 0),
(31863, 0, 42450, 0, 0, 2468, 0),
(31863, 0, 42485, 0, 0, 2460, 0),
(31863, 0, 42490, 0, 0, 2460, 0),
(31863, 0, 42495, 0, 0, 2460, 0),
(31863, 0, 42502, 0, 0, 2468, 0),
(31863, 0, 42513, 0, 0, 2468, 0),
(31863, 0, 42519, 0, 0, 2468, 0),
(31863, 0, 42559, 0, 0, 2469, 0),
(31863, 0, 42564, 0, 0, 2469, 0),
(31863, 0, 42570, 0, 0, 2469, 0),
(31863, 0, 42578, 0, 0, 2468, 0),
(31863, 0, 42583, 0, 0, 2468, 0),
(31863, 0, 42588, 0, 0, 2468, 0),
(31863, 0, 42597, 0, 0, 2468, 0),
(31863, 0, 42602, 0, 0, 2468, 0),
(31863, 0, 42607, 0, 0, 2468, 0),
(31863, 0, 42614, 0, 0, 2468, 0),
(31863, 0, 42620, 0, 0, 2468, 0),
(31863, 0, 42852, 0, 0, 2468, 0),
(31863, 0, 44419, 0, 0, 2460, 0),
(31863, 0, 44420, 0, 0, 2460, 0),
(31863, 0, 45706, 0, 0, 2596, 0),
(32407, 0, 40784, 0, 0, 2462, 0),
(32407, 0, 40785, 0, 0, 2462, 0),
(32407, 0, 40786, 0, 0, 2462, 0),
(32407, 0, 40804, 0, 0, 2463, 0),
(32407, 0, 40805, 0, 0, 2463, 0),
(32407, 0, 40806, 0, 0, 2463, 0),
(32407, 0, 40823, 0, 0, 2464, 0),
(32407, 0, 40824, 0, 0, 2464, 0),
(32407, 0, 40825, 0, 0, 2464, 0),
(32407, 0, 40844, 0, 0, 2465, 0),
(32407, 0, 40845, 0, 0, 2465, 0),
(32407, 0, 40846, 0, 0, 2465, 0),
(32407, 0, 40862, 0, 0, 2470, 0),
(32407, 0, 40863, 0, 0, 2470, 0),
(32407, 0, 40864, 0, 0, 2470, 0),
(32407, 0, 40905, 0, 0, 2462, 0),
(32407, 0, 40926, 0, 0, 2463, 0),
(32407, 0, 40932, 0, 0, 2464, 0),
(32407, 0, 40938, 0, 0, 2465, 0),
(32407, 0, 40962, 0, 0, 2470, 0),
(32407, 0, 40990, 0, 0, 2462, 0),
(32407, 0, 40991, 0, 0, 2462, 0),
(32407, 0, 41000, 0, 0, 2463, 0),
(32407, 0, 41006, 0, 0, 2463, 0),
(32407, 0, 41012, 0, 0, 2464, 0),
(32407, 0, 41018, 0, 0, 2464, 0),
(32407, 0, 41026, 0, 0, 2465, 0),
(32407, 0, 41032, 0, 0, 2465, 0),
(32407, 0, 41037, 0, 0, 2470, 0),
(32407, 0, 41043, 0, 0, 2470, 0),
(32407, 0, 41080, 0, 0, 2462, 0),
(32407, 0, 41086, 0, 0, 2462, 0),
(32407, 0, 41136, 0, 0, 2463, 0),
(32407, 0, 41142, 0, 0, 2463, 0),
(32407, 0, 41150, 0, 0, 2464, 0),
(32407, 0, 41156, 0, 0, 2464, 0),
(32407, 0, 41198, 0, 0, 2465, 0),
(32407, 0, 41204, 0, 0, 2465, 0),
(32407, 0, 41210, 0, 0, 2470, 0),
(32407, 0, 41216, 0, 0, 2470, 0),
(32407, 0, 41274, 0, 0, 2470, 0),
(32407, 0, 41280, 0, 0, 2470, 0),
(32407, 0, 41286, 0, 0, 2463, 0),
(32407, 0, 41292, 0, 0, 2463, 0),
(32407, 0, 41297, 0, 0, 2465, 0),
(32407, 0, 41303, 0, 0, 2465, 0),
(32407, 0, 41309, 0, 0, 2462, 0),
(32407, 0, 41315, 0, 0, 2462, 0),
(32407, 0, 41320, 0, 0, 2464, 0),
(32407, 0, 41326, 0, 0, 2464, 0),
(32407, 0, 41649, 0, 0, 2462, 0),
(32407, 0, 41654, 0, 0, 2465, 0),
(32407, 0, 41660, 0, 0, 2462, 0),
(32407, 0, 41666, 0, 0, 2465, 0),
(32407, 0, 41671, 0, 0, 2464, 0),
(32407, 0, 41677, 0, 0, 2464, 0),
(32407, 0, 41682, 0, 0, 2470, 0),
(32407, 0, 41714, 0, 0, 2470, 0),
(32407, 0, 41766, 0, 0, 2463, 0),
(32407, 0, 41772, 0, 0, 2463, 0),
(32407, 0, 41853, 0, 0, 2464, 0),
(32407, 0, 41858, 0, 0, 2462, 0),
(32407, 0, 41863, 0, 0, 2465, 0),
(32407, 0, 41868, 0, 0, 2470, 0),
(32407, 0, 41873, 0, 0, 2463, 0),
(32407, 0, 41914, 0, 0, 2464, 0),
(32407, 0, 41920, 0, 0, 2462, 0),
(32407, 0, 41926, 0, 0, 2465, 0),
(32407, 0, 41933, 0, 0, 2470, 0),
(32407, 0, 41939, 0, 0, 2463, 0),
(32407, 0, 41945, 0, 0, 2464, 0),
(32407, 0, 41951, 0, 0, 2462, 0),
(32407, 0, 41958, 0, 0, 2465, 0),
(32407, 0, 41964, 0, 0, 2470, 0),
(32407, 0, 41970, 0, 0, 2463, 0),
(32407, 0, 41992, 0, 0, 2464, 0),
(32407, 0, 41997, 0, 0, 2462, 0),
(32407, 0, 42004, 0, 0, 2465, 0),
(32407, 0, 42010, 0, 0, 2470, 0),
(32407, 0, 42016, 0, 0, 2463, 0),
(32407, 0, 42208, 0, 0, 2466, 0),
(32407, 0, 42227, 0, 0, 2467, 0),
(32407, 0, 42232, 0, 0, 2467, 0),
(32407, 0, 42237, 0, 0, 2468, 0),
(32407, 0, 42242, 0, 0, 2466, 0),
(32407, 0, 42248, 0, 0, 2467, 0),
(32407, 0, 42255, 0, 0, 2467, 0),
(32407, 0, 42260, 0, 0, 2466, 0),
(32407, 0, 42265, 0, 0, 2467, 0),
(32407, 0, 42270, 0, 0, 2467, 0),
(32407, 0, 42275, 0, 0, 2466, 0),
(32407, 0, 42280, 0, 0, 2467, 0),
(32407, 0, 42285, 0, 0, 2466, 0),
(32407, 0, 42290, 0, 0, 2467, 0),
(32407, 0, 42317, 0, 0, 2460, 0),
(32407, 0, 42322, 0, 0, 2460, 0),
(32407, 0, 42327, 0, 0, 2460, 0),
(32407, 0, 42332, 0, 0, 2460, 0),
(32407, 0, 42346, 0, 0, 2466, 0),
(32407, 0, 42352, 0, 0, 2466, 0),
(32407, 0, 42362, 0, 0, 2460, 0),
(32407, 0, 42384, 0, 0, 2460, 0),
(32407, 0, 42390, 0, 0, 2460, 0),
(32407, 0, 42525, 0, 0, 2467, 0),
(32407, 0, 42531, 0, 0, 2467, 0),
(32407, 0, 42537, 0, 0, 2467, 0),
(32407, 0, 42450, 0, 0, 2468, 0),
(32407, 0, 42485, 0, 0, 2460, 0),
(32407, 0, 42490, 0, 0, 2460, 0),
(32407, 0, 42495, 0, 0, 2460, 0),
(32407, 0, 42502, 0, 0, 2468, 0),
(32407, 0, 42513, 0, 0, 2468, 0),
(32407, 0, 42519, 0, 0, 2468, 0),
(32407, 0, 42559, 0, 0, 2469, 0),
(32407, 0, 42564, 0, 0, 2469, 0),
(32407, 0, 42570, 0, 0, 2469, 0),
(32407, 0, 42578, 0, 0, 2468, 0),
(32407, 0, 42583, 0, 0, 2468, 0),
(32407, 0, 42588, 0, 0, 2468, 0),
(32407, 0, 42597, 0, 0, 2468, 0),
(32407, 0, 42602, 0, 0, 2468, 0),
(32407, 0, 42607, 0, 0, 2468, 0),
(32407, 0, 42614, 0, 0, 2468, 0),
(32407, 0, 42620, 0, 0, 2468, 0),
(32407, 0, 42852, 0, 0, 2468, 0),
(32407, 0, 44419, 0, 0, 2460, 0),
(32407, 0, 44420, 0, 0, 2460, 0),
(32407, 0, 45706, 0, 0, 2596, 0),
(32405, 0, 40784, 0, 0, 2462, 0),
(32405, 0, 40785, 0, 0, 2462, 0),
(32405, 0, 40786, 0, 0, 2462, 0),
(32405, 0, 40804, 0, 0, 2463, 0),
(32405, 0, 40805, 0, 0, 2463, 0),
(32405, 0, 40806, 0, 0, 2463, 0),
(32405, 0, 40823, 0, 0, 2464, 0),
(32405, 0, 40824, 0, 0, 2464, 0),
(32405, 0, 40825, 0, 0, 2464, 0),
(32405, 0, 40844, 0, 0, 2465, 0),
(32405, 0, 40845, 0, 0, 2465, 0),
(32405, 0, 40846, 0, 0, 2465, 0),
(32405, 0, 40862, 0, 0, 2470, 0),
(32405, 0, 40863, 0, 0, 2470, 0),
(32405, 0, 40864, 0, 0, 2470, 0),
(32405, 0, 40905, 0, 0, 2462, 0),
(32405, 0, 40926, 0, 0, 2463, 0),
(32405, 0, 40932, 0, 0, 2464, 0),
(32405, 0, 40938, 0, 0, 2465, 0),
(32405, 0, 40962, 0, 0, 2470, 0),
(32405, 0, 40990, 0, 0, 2462, 0),
(32405, 0, 40991, 0, 0, 2462, 0),
(32405, 0, 41000, 0, 0, 2463, 0),
(32405, 0, 41006, 0, 0, 2463, 0),
(32405, 0, 41012, 0, 0, 2464, 0),
(32405, 0, 41018, 0, 0, 2464, 0),
(32405, 0, 41026, 0, 0, 2465, 0),
(32405, 0, 41032, 0, 0, 2465, 0),
(32405, 0, 41037, 0, 0, 2470, 0),
(32405, 0, 41043, 0, 0, 2470, 0),
(32405, 0, 41080, 0, 0, 2462, 0),
(32405, 0, 41086, 0, 0, 2462, 0),
(32405, 0, 41136, 0, 0, 2463, 0),
(32405, 0, 41142, 0, 0, 2463, 0),
(32405, 0, 41150, 0, 0, 2464, 0),
(32405, 0, 41156, 0, 0, 2464, 0),
(32405, 0, 41198, 0, 0, 2465, 0),
(32405, 0, 41204, 0, 0, 2465, 0),
(32405, 0, 41210, 0, 0, 2470, 0),
(32405, 0, 41216, 0, 0, 2470, 0),
(32405, 0, 41274, 0, 0, 2470, 0),
(32405, 0, 41280, 0, 0, 2470, 0),
(32405, 0, 41286, 0, 0, 2463, 0),
(32405, 0, 41292, 0, 0, 2463, 0),
(32405, 0, 41297, 0, 0, 2465, 0),
(32405, 0, 41303, 0, 0, 2465, 0),
(32405, 0, 41309, 0, 0, 2462, 0),
(32405, 0, 41315, 0, 0, 2462, 0),
(32405, 0, 41320, 0, 0, 2464, 0),
(32405, 0, 41326, 0, 0, 2464, 0),
(32405, 0, 41649, 0, 0, 2462, 0),
(32405, 0, 41654, 0, 0, 2465, 0),
(32405, 0, 41660, 0, 0, 2462, 0),
(32405, 0, 41666, 0, 0, 2465, 0),
(32405, 0, 41671, 0, 0, 2464, 0),
(32405, 0, 41677, 0, 0, 2464, 0),
(32405, 0, 41682, 0, 0, 2470, 0),
(32405, 0, 41714, 0, 0, 2470, 0),
(32405, 0, 41766, 0, 0, 2463, 0),
(32405, 0, 41772, 0, 0, 2463, 0),
(32405, 0, 41853, 0, 0, 2464, 0),
(32405, 0, 41858, 0, 0, 2462, 0),
(32405, 0, 41863, 0, 0, 2465, 0),
(32405, 0, 41868, 0, 0, 2470, 0),
(32405, 0, 41873, 0, 0, 2463, 0),
(32405, 0, 41914, 0, 0, 2464, 0),
(32405, 0, 41920, 0, 0, 2462, 0),
(32405, 0, 41926, 0, 0, 2465, 0),
(32405, 0, 41933, 0, 0, 2470, 0),
(32405, 0, 41939, 0, 0, 2463, 0),
(32405, 0, 41945, 0, 0, 2464, 0),
(32405, 0, 41951, 0, 0, 2462, 0),
(32405, 0, 41958, 0, 0, 2465, 0),
(32405, 0, 41964, 0, 0, 2470, 0),
(32405, 0, 41970, 0, 0, 2463, 0),
(32405, 0, 41992, 0, 0, 2464, 0),
(32405, 0, 41997, 0, 0, 2462, 0),
(32405, 0, 42004, 0, 0, 2465, 0),
(32405, 0, 42010, 0, 0, 2470, 0),
(32405, 0, 42016, 0, 0, 2463, 0),
(32405, 0, 42208, 0, 0, 2466, 0),
(32405, 0, 42227, 0, 0, 2467, 0),
(32405, 0, 42232, 0, 0, 2467, 0),
(32405, 0, 42237, 0, 0, 2468, 0),
(32405, 0, 42242, 0, 0, 2466, 0),
(32405, 0, 42248, 0, 0, 2467, 0),
(32405, 0, 42255, 0, 0, 2467, 0),
(32405, 0, 42260, 0, 0, 2466, 0),
(32405, 0, 42265, 0, 0, 2467, 0),
(32405, 0, 42270, 0, 0, 2467, 0),
(32405, 0, 42275, 0, 0, 2466, 0),
(32405, 0, 42280, 0, 0, 2467, 0),
(32405, 0, 42285, 0, 0, 2466, 0),
(32405, 0, 42290, 0, 0, 2467, 0),
(32405, 0, 42317, 0, 0, 2460, 0),
(32405, 0, 42322, 0, 0, 2460, 0),
(32405, 0, 42327, 0, 0, 2460, 0),
(32405, 0, 42332, 0, 0, 2460, 0),
(32405, 0, 42346, 0, 0, 2466, 0),
(32405, 0, 42352, 0, 0, 2466, 0),
(32405, 0, 42362, 0, 0, 2460, 0),
(32405, 0, 42384, 0, 0, 2460, 0),
(32405, 0, 42390, 0, 0, 2460, 0),
(32405, 0, 42525, 0, 0, 2467, 0),
(32405, 0, 42531, 0, 0, 2467, 0),
(32405, 0, 42537, 0, 0, 2467, 0),
(32405, 0, 42450, 0, 0, 2468, 0),
(32405, 0, 42485, 0, 0, 2460, 0),
(32405, 0, 42490, 0, 0, 2460, 0),
(32405, 0, 42495, 0, 0, 2460, 0),
(32405, 0, 42502, 0, 0, 2468, 0),
(32405, 0, 42513, 0, 0, 2468, 0),
(32405, 0, 42519, 0, 0, 2468, 0),
(32405, 0, 42559, 0, 0, 2469, 0),
(32405, 0, 42564, 0, 0, 2469, 0),
(32405, 0, 42570, 0, 0, 2469, 0),
(32405, 0, 42578, 0, 0, 2468, 0),
(32405, 0, 42583, 0, 0, 2468, 0),
(32405, 0, 42588, 0, 0, 2468, 0),
(32405, 0, 42597, 0, 0, 2468, 0),
(32405, 0, 42602, 0, 0, 2468, 0),
(32405, 0, 42607, 0, 0, 2468, 0),
(32405, 0, 42614, 0, 0, 2468, 0),
(32405, 0, 42620, 0, 0, 2468, 0),
(32405, 0, 42852, 0, 0, 2468, 0),
(32405, 0, 44419, 0, 0, 2460, 0),
(32405, 0, 44420, 0, 0, 2460, 0),
(32405, 0, 45706, 0, 0, 2596, 0);
@@ -0,0 +1,11 @@
-- DB update 2026_01_20_00 -> 2026_01_20_01
--
UPDATE `smart_scripts` SET `target_param2`=40 WHERE `entryorguid`=7669 AND `source_type`=0 AND `id`=3 AND `link`=0;
UPDATE `smart_scripts` SET `target_param2`=40 WHERE `entryorguid`=7670 AND `source_type`=0 AND `id`=3 AND `link`=0;
UPDATE `smart_scripts` SET `target_param2`=40 WHERE `entryorguid`=7668 AND `source_type`=0 AND `id`=3 AND `link`=0;
UPDATE `smart_scripts` SET `target_param2`=40 WHERE `entryorguid`=7671 AND `source_type`=0 AND `id`=3 AND `link`=0;
UPDATE `smart_scripts` SET `target_param2`=40 WHERE `entryorguid`=141812 AND `source_type`=1 AND `id`=0 AND `link`=0;
UPDATE `smart_scripts` SET `target_param2`=40 WHERE `entryorguid`=141857 AND `source_type`=1 AND `id`=0 AND `link`=0;
UPDATE `smart_scripts` SET `target_param2`=40 WHERE `entryorguid`=141858 AND `source_type`=1 AND `id`=0 AND `link`=0;
UPDATE `smart_scripts` SET `target_param2`=40 WHERE `entryorguid`=141859 AND `source_type`=1 AND `id`=0 AND `link`=0;
@@ -0,0 +1,6 @@
-- DB update 2026_01_20_01 -> 2026_01_20_02
--
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 6492) AND (`source_type` = 0) AND (`id` IN (17, 18));
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`, `event_param6`, `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
(6492, 0, 17, 18, 7, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rift Spawn - On Evade - Say Line 1'),
(6492, 0, 18, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 1200, 10, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rift Spawn - On Evade - Despawn In 1200 ms');
@@ -0,0 +1,48 @@
-- DB update 2026_01_20_02 -> 2026_01_20_03
--
DELETE FROM `linked_respawn` WHERE `linkedGuid` = 126663 AND `linkType` = 0;
INSERT INTO `linked_respawn` (`guid`, `linkedGuid`, `linkType`) VALUES
(126619, 126663, 0),
(126620, 126663, 0),
(126621, 126663, 0),
(126622, 126663, 0),
(126623, 126663, 0),
(126624, 126663, 0),
(126625, 126663, 0),
(126626, 126663, 0),
(126627, 126663, 0),
(126628, 126663, 0),
(126629, 126663, 0),
(126630, 126663, 0),
(126631, 126663, 0),
(126632, 126663, 0),
(126633, 126663, 0),
(126634, 126663, 0),
(126635, 126663, 0),
(126636, 126663, 0),
(126637, 126663, 0),
(126638, 126663, 0),
(126639, 126663, 0),
(126640, 126663, 0),
(126641, 126663, 0),
(126642, 126663, 0),
(126643, 126663, 0),
(126644, 126663, 0),
(126645, 126663, 0),
(126646, 126663, 0),
(126647, 126663, 0),
(126648, 126663, 0),
(126649, 126663, 0),
(126650, 126663, 0),
(126651, 126663, 0),
(126652, 126663, 0),
(126653, 126663, 0),
(126654, 126663, 0),
(126655, 126663, 0),
(126656, 126663, 0),
(126657, 126663, 0),
(126658, 126663, 0),
(126659, 126663, 0),
(126660, 126663, 0),
(126661, 126663, 0),
(126662, 126663, 0);
@@ -0,0 +1,24 @@
-- DB update 2026_01_20_03 -> 2026_01_21_00
--
UPDATE `creature_loot_template` SET `Chance` = 100 WHERE `Entry` IN (24664, 24857) AND `Item` = 35008 AND `Reference` = 35008;
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 10) AND (`SourceGroup` = 35008) AND (`ConditionTypeOrReference` = 7) AND (`ConditionValue2` = 1);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(10, 35008, 35304, 0, 0, 7, 0, 755, 1, 0, 0, 0, 0, '', 'Player must have Jewelcrafting to loot BoP version of this Design'),
(10, 35008, 35305, 0, 0, 7, 0, 755, 1, 0, 0, 0, 0, '', 'Player must have Jewelcrafting to loot BoP version of this Design'),
(10, 35008, 35306, 0, 0, 7, 0, 755, 1, 0, 0, 0, 0, '', 'Player must have Jewelcrafting to loot BoP version of this Design'),
(10, 35008, 35307, 0, 0, 7, 0, 755, 1, 0, 0, 0, 0, '', 'Player must have Jewelcrafting to loot BoP version of this Design'),
(10, 35008, 35297, 0, 0, 7, 0, 333, 1, 0, 0, 0, 0, '', 'Player must have Enchanting to loot BoP version of this Formula'),
(10, 35008, 35298, 0, 0, 7, 0, 333, 1, 0, 0, 0, 0, '', 'Player must have Enchanting to loot BoP version of this Formula'),
(10, 35008, 35299, 0, 0, 7, 0, 333, 1, 0, 0, 0, 0, '', 'Player must have Enchanting to loot BoP version of this Formula'),
(10, 35008, 35300, 0, 0, 7, 0, 165, 1, 0, 0, 0, 0, '', 'Player must have Leatherworking to loot BoP version of this Pattern'),
(10, 35008, 35301, 0, 0, 7, 0, 165, 1, 0, 0, 0, 0, '', 'Player must have Leatherworking to loot BoP version of this Pattern'),
(10, 35008, 35302, 0, 0, 7, 0, 165, 1, 0, 0, 0, 0, '', 'Player must have Leatherworking to loot BoP version of this Pattern'),
(10, 35008, 35303, 0, 0, 7, 0, 165, 1, 0, 0, 0, 0, '', 'Player must have Leatherworking to loot BoP version of this Pattern'),
(10, 35008, 35308, 0, 0, 7, 0, 197, 1, 0, 0, 0, 0, '', 'Player must have Tailoring to loot BoP version of this Pattern'),
(10, 35008, 35309, 0, 0, 7, 0, 197, 1, 0, 0, 0, 0, '', 'Player must have Tailoring to loot BoP version of this Pattern'),
(10, 35008, 35296, 0, 0, 7, 0, 164, 1, 0, 0, 0, 0, '', 'Player must have Blacksmithing to loot BoP version of these Plans'),
(10, 35008, 35294, 0, 0, 7, 0, 171, 1, 0, 0, 0, 0, '', 'Player must have Alchemy to loot BoP version of this Recipe'),
(10, 35008, 35295, 0, 0, 7, 0, 171, 1, 0, 0, 0, 0, '', 'Player must have Alchemy to loot BoP version of this Recipe'),
(10, 35008, 35310, 0, 0, 7, 0, 202, 1, 0, 0, 0, 0, '', 'Player must have Engineering to loot BoP version of this Schematic'),
(10, 35008, 35311, 0, 0, 7, 0, 202, 1, 0, 0, 0, 0, '', 'Player must have Engineering to loot BoP version of this Schematic');
@@ -0,0 +1,99 @@
-- DB update 2026_01_21_00 -> 2026_01_21_01
-- Just missing from the mob, as it should have one pair of pants for each type (cloth, leather, etc)
DELETE FROM `creature_loot_template` WHERE (`Entry` = 18681) AND (`Item` IN (31246));
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(18681, 31246, 0, 0, 0, 1, 1, 1, 1, 'Coilfang Emissary - Nagahide Leggings');
-- Gruffscale Leggings: Appears to have been added in WotLK at some point, replacing an older "Boarhide Leggings" lvl 8 green. Due to that drop rates in Wowhead may be skewed towards lower than intended
DELETE FROM `creature_loot_template` WHERE (`Entry` = 6583) AND (`Item` IN (45052));
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(6583, 45052, 0, 100, 0, 1, 0, 1, 1, 'Gruff - Gruffscale Leggings');
-- Dustbringer: Super rare fishing loot item (novelty blue-quality drop)
DELETE FROM `gameobject_loot_template` WHERE `Entry` IN (25662,25663,25664,25665,25668,25669,25670,25671,25673,25674) AND `Item` = 44505;
INSERT INTO `gameobject_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(25662, 44505, 0, 0.01, 0, 1, 0, 1, 1, 'Glacial Salmon School - Dustbringer'),
(25663, 44505, 0, 0.01, 0, 1, 0, 1, 1, 'Fangtooth Herring School - Dustbringer'),
(25664, 44505, 0, 0.01, 0, 1, 0, 1, 1, 'Dragonfin Angelfish School - Dustbringer'),
(25665, 44505, 0, 0.01, 0, 1, 0, 1, 1, 'Musselback Sculpin School - Dustbringer'),
(25668, 44505, 0, 0.01, 0, 1, 0, 1, 1, 'Imperial Manta Ray School - Dustbringer'),
(25669, 44505, 0, 0.01, 0, 1, 0, 1, 1, 'Borean Man O\' War School - Dustbringer'),
(25670, 44505, 0, 0.01, 0, 1, 0, 1, 1, 'Moonglow Cuttlefish School - Dustbringer'),
(25671, 44505, 0, 0.01, 0, 1, 0, 1, 1, 'Deep Sea Monsterbelly School - Dustbringer'),
(25673, 44505, 0, 0.01, 0, 1, 0, 1, 1, 'Nettlefish School - Dustbringer'),
(25674, 44505, 0, 0.01, 0, 1, 0, 1, 1, 'Glassfin Minnow School - Dustbringer');
-- Runed Ring: Apparently these two items are rare Zul'Farrak zone BoEs, but their item level is higher than others of its type, so the only creatures that can drop them are actually the final bosses of the dungeon
-- Ensure Spellshock Leggings and Runed Ring drop from the final Zul'Farrak bosses in a separate shared loot group
DELETE FROM `creature_loot_template` WHERE (`Entry` IN (8127, 7267)) AND (`Item` IN (9484, 862));
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(8127, 9484, 0, 0.25, 0, 1, 2, 1, 1, 'Antu\'Sul - Spellshock Leggings'),
(8127, 862, 0, 0.25, 0, 1, 2, 1, 1, 'Antu\'sul - Runed Ring'),
(7267, 9484, 0, 0.25, 0, 1, 2, 1, 1, 'Chief Ukorz Sandscalp - Spellshock Leggings'),
(7267, 862, 0, 0.25, 0, 1, 2, 1, 1, 'Chief Ukorz Sandscalp - Runed Ring');
-- These seem to be rare drops from Vanilla endgame dungeons. It's inconclusive if they were removed from the game at some point, and if so, why
DELETE FROM `creature_loot_template` WHERE (`Entry` = 9237) AND (`Item` IN (13175));
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(9237, 13175, 0, 1, 0, 1, 0, 1, 1, 'War Master Voone - Voone\'s Twitchbow');
DELETE FROM `creature_loot_template` WHERE (`Entry` = 9568) AND (`Item` IN (13148));
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(9568, 13148, 0, 1, 0, 1, 0, 1, 1, 'Overlord Wyrmthalak - Chillpike');
DELETE FROM `creature_loot_template` WHERE (`Entry` = 10429) AND (`Item` IN (12588));
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(10429, 12588, 0, 1, 0, 1, 0, 1, 1, 'Warchief Rend Blackhand - Bonespike Shoulder');
DELETE FROM `creature_loot_template` WHERE (`Entry` = 1853) AND (`Item` IN (13950));
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(1853, 13950, 0, 1, 0, 1, 0, 1, 1, 'Darkmaster Gandling - Detention Strap');
DELETE FROM `creature_loot_template` WHERE (`Entry` = 10503) AND (`Item` IN (14543));
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(10503, 14543, 0, 1, 0, 1, 0, 1, 1, 'Jandice Barov - Darkshade Gloves');
DELETE FROM `creature_loot_template` WHERE (`Entry` = 9568) AND (`Item` IN (13164));
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(9568, 13164, 0, 1, 0, 1, 0, 1, 1, 'Overlord Wyrmthalak - Heart of the Scale');
-- Sack of Spoils and Chest of Spoils (AQ event reward containers)
DELETE FROM `item_loot_template` WHERE (`Entry` = 20601) AND (`Item` IN (20696, 20698));
INSERT INTO `item_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(20601, 20696, 0, 5, 0, 1, 1, 1, 1, 'Sack of Spoils - Crystal Spiked Maul'),
(20601, 20698, 0, 1, 0, 1, 1, 1, 1, 'Sack of Spoils - Elemental Attuned Blade');
DELETE FROM `item_loot_template` WHERE (`Entry` = 20602) AND (`Item` IN (20722, 20721, 20720));
INSERT INTO `item_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(20602, 20722, 0, 5, 0, 1, 1, 1, 1, 'Chest of Spoils - Crystal Slugthrower'),
(20602, 20721, 0, 5, 0, 1, 1, 1, 1, 'Chest of Spoils - Band of the Cultist'),
(20602, 20720, 0, 5, 0, 1, 1, 1, 1, 'Chest of Spoils - Dark Whisper Blade');
-- Missing from Jin'do Loot Table (same ilvl as the rest)
DELETE FROM `reference_loot_template` WHERE (`Entry` = 34089) AND (`Item` IN (19875));
INSERT INTO `reference_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(34089, 19875, 0, 0, 0, 1, 1, 1, 1, 'Bloodstained Coif');
-- Rare drop from Phalanx
DELETE FROM `creature_loot_template` WHERE (`Entry` = 9502) AND (`Item` IN (11743));
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(9502, 11743, 0, 2, 0, 1, 1, 1, 1, 'Phalanx - Rockfist');
-- Claimed to still drop during 3.3.3
DELETE FROM `creature_loot_template` WHERE (`Entry` = 9257) AND (`Item` IN (9214));
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(9257, 9214, 0, 7, 0, 1, 0, 1, 1, 'Scarshield Warlock - Grimoire of Inferno');
-- Alterac Valley Bosses
DELETE FROM `creature_loot_template` WHERE (`Entry` IN (13256, 13419)) AND (`Item` IN (19105, 19109, 19110, 19111, 19112, 19113));
DELETE FROM `reference_loot_template` WHERE (`Entry` = 13256);
INSERT INTO `reference_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(13256, 19105, 0, 0, 0, 1, 1, 1, 1, 'Alterac Valley Summon Boss - Frost Runed Headdress'),
(13256, 19109, 0, 0, 0, 1, 1, 1, 1, 'Alterac Valley Summon Boss - Deep Rooted Ring'),
(13256, 19110, 0, 0, 0, 1, 1, 1, 1, 'Alterac Valley Summon Boss - Cold Forged Blade'),
(13256, 19111, 0, 0, 0, 1, 1, 1, 1, 'Alterac Valley Summon Boss - Winteraxe Epaulets'),
(13256, 19112, 0, 0, 0, 1, 1, 1, 1, 'Alterac Valley Summon Boss - Frozen Steel Vambraces'),
(13256, 19113, 0, 0, 0, 1, 1, 1, 1, 'Alterac Valley Summon Boss - Yeti Hide Bracers');
DELETE FROM `creature_loot_template` WHERE (`Entry` IN (13256, 13419)) AND (`Item` IN (13256));
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(13256, 13256, 13256, 100, 0, 1, 0, 4, 4, 'Alterac Summon Boss Loot Table'),
(13419, 13256, 13256, 100, 0, 1, 0, 4, 4, 'Alterac Summon Boss Loot Table');
-- AQ40 Trash Epic
DELETE FROM `creature_loot_template` WHERE (`Entry` = 15312) AND (`Item` IN (21890));
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(15312, 21890, 0, 0.2, 0, 1, 0, 1, 1, 'Obsidian Nullifier - Gloves of the Fallen Prophet');
@@ -0,0 +1,22 @@
-- DB update 2026_01_21_01 -> 2026_01_21_02
--
SET @REPPORTALKEEPER := 30;
SET @REPREGULAR := 18;
SET @REPBOSS := 275;
DELETE FROM `creature_onkill_reputation` WHERE `creature_id` IN (31503, 31501, 31493, 31490, 31513, 32191, 31486, 31507, 31509, 31510, 31511, 31512, 31508, 31506);
INSERT INTO `creature_onkill_reputation` (`creature_id`,`RewOnKillRepFaction1`,`RewOnKillRepFaction2`,`MaxStanding1`,`IsTeamAward1`,`RewOnKillRepValue1`,`MaxStanding2`,`IsTeamAward2`,`RewOnKillRepValue2`,`TeamDependent`) VALUES
(31503,1037,1052,7,0,@REPPORTALKEEPER,7,0,@REPPORTALKEEPER,1), -- Portal Keeper
(31501,1037,1052,7,0,@REPPORTALKEEPER,7,0,@REPPORTALKEEPER,1), -- Portal Guardian
(31493,1037,1052,7,0,@REPREGULAR,7,0,@REPREGULAR,1), -- Azure Sorceror
(31490,1037,1052,7,0,@REPREGULAR,7,0,@REPREGULAR,1), -- Azure Raider
(31513,1037,1052,7,0,@REPREGULAR,7,0,@REPREGULAR,1), -- Erekem Guard
(32191,1037,1052,7,0,@REPREGULAR,7,0,@REPREGULAR,1), -- Azure Stalker
(31486,1037,1052,7,0,@REPREGULAR,7,0,@REPREGULAR,1), -- Azure Captain
(31507,1037,1052,7,0,@REPBOSS,7,0,@REPBOSS,1), -- Erekem
(31509,1037,1052,7,0,@REPBOSS,7,0,@REPBOSS,1), -- Lavanthor
(31510,1037,1052,7,0,@REPBOSS,7,0,@REPBOSS,1), -- Moragg
(31511,1037,1052,7,0,@REPBOSS,7,0,@REPBOSS,1), -- Zevoxx
(31512,1037,1052,7,0,@REPBOSS,7,0,@REPBOSS,1), -- Zuramat
(31508,1037,1052,7,0,@REPBOSS,7,0,@REPBOSS,1), -- Ichoron
(31506,1037,1052,7,0,@REPBOSS,7,0,@REPBOSS,1); -- Cyanigosa
@@ -0,0 +1,5 @@
-- DB update 2026_01_21_02 -> 2026_01_22_00
--
DELETE FROM `spell_script_names` WHERE `spell_id` = 28375;
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
(28375, 'spell_gluth_decimate_damage');
@@ -0,0 +1,27 @@
-- DB update 2026_01_22_00 -> 2026_01_22_01
-- PrevQuestID from 12822 to 18221, A Flawless Plan requires Opening the Backdoor, not Know No Fear
UPDATE `quest_template_addon` SET `PrevQuestID` = 12821 WHERE `ID` = 12823;
-- Remove phase shifts in Garm and Garm's Rise for Know No Fear
DELETE FROM `spell_area`
WHERE `Quest_start` = 12822
AND `quest_start_status` = 74;
-- Add phase shift in Garm and Garm's Rise after turning in Opening the Backdoor
DELETE FROM `spell_area` WHERE `Quest_start` = 12821 AND `Spell` = 54635;
INSERT INTO `spell_area`
(
`Spell`,
`Area`,
`Quest_start`,
`Quest_end`,
`Aura_spell`,
`Racemask`,
`Gender`,
`Autocast`,
`Quest_start_status`,
`Quest_end_status`
)
VALUES
(54635, 4421, 12821, 0, 0, 0, 2, 1, 64, 0),
(54635, 4461, 12821, 0, 0, 0, 2, 1, 64, 0);
@@ -0,0 +1,7 @@
-- DB update 2026_01_22_01 -> 2026_01_22_02
--
DELETE FROM `smart_scripts` WHERE `entryorguid` = 28581 AND `source_type` = 0 AND `id` IN (0, 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`, `event_param6`, `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
(28581, 0, 0, 0, 0, 0, 100, 2, 0, 9000, 11000, 14000, 0, 0, 11, 52778, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 'Stormforged Tactician - In Combat - Cast \'Welding Beam\' (Normal Dungeon)'),
(28581, 0, 1, 0, 0, 0, 100, 4, 0, 9000, 11000, 14000, 0, 0, 11, 59166, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 'Stormforged Tactician - In Combat - Cast \'Welding Beam\' (Heroic Dungeon)'),
(28581, 0, 2, 0, 2, 0, 100, 6, 0, 70, 15000, 27000, 0, 0, 11, 59085, 32, 0, 0, 0, 0, 5, 40, 0, 0, 0, 0, 0, 0, 0, 'Stormforged Tactician - Between 0-70% Health - Cast \'Arc Weld\' (Dungeon)');
@@ -0,0 +1,8 @@
-- DB update 2026_01_22_02 -> 2026_01_22_03
--
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 29134;
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 29134) AND (`source_type` = 0) AND (`id` IN (0, 1));
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`, `event_param6`, `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
(29134, 0, 0, 0, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 180000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Brown Rabbit - On Just Summoned - Despawn In 180000 ms'),
(29134, 0, 1, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 53273, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Brown Rabbit - On Death - Cast \'Decoy Explosive\'');
@@ -162,7 +162,7 @@ void AccountInfo::LoadResult(Field* fields)
Utf8ToUpperOnlyLatin(Login); Utf8ToUpperOnlyLatin(Login);
} }
AuthSession::AuthSession(tcp::socket&& socket) : AuthSession::AuthSession(IoContextTcpSocket&& socket) :
Socket(std::move(socket)), _status(STATUS_CHALLENGE), _build(0), _expversion(0) { } Socket(std::move(socket)), _status(STATUS_CHALLENGE), _build(0), _expversion(0) { }
void AuthSession::Start() void AuthSession::Start()
@@ -216,7 +216,7 @@ void AuthSession::CheckIpCallback(PreparedQueryResult result)
AsyncRead(); AsyncRead();
} }
void AuthSession::ReadHandler() SocketReadCallbackResult AuthSession::ReadHandler()
{ {
MessageBuffer& packet = GetReadBuffer(); MessageBuffer& packet = GetReadBuffer();
@@ -234,7 +234,7 @@ void AuthSession::ReadHandler()
if (_status != itr->second.status) if (_status != itr->second.status)
{ {
CloseSocket(); CloseSocket();
return; return SocketReadCallbackResult::Stop;
} }
uint16 size = uint16(itr->second.packetSize); uint16 size = uint16(itr->second.packetSize);
@@ -248,7 +248,7 @@ void AuthSession::ReadHandler()
if (size > MAX_ACCEPTED_CHALLENGE_SIZE) if (size > MAX_ACCEPTED_CHALLENGE_SIZE)
{ {
CloseSocket(); CloseSocket();
return; return SocketReadCallbackResult::Stop;
} }
} }
@@ -258,13 +258,13 @@ void AuthSession::ReadHandler()
if (!(*this.*itr->second.handler)()) if (!(*this.*itr->second.handler)())
{ {
CloseSocket(); CloseSocket();
return; return SocketReadCallbackResult::Stop;
} }
packet.ReadCompleted(size); packet.ReadCompleted(size);
} }
AsyncRead(); return SocketReadCallbackResult::KeepReading;
} }
void AuthSession::SendPacket(ByteBuffer& packet) void AuthSession::SendPacket(ByteBuffer& packet)
@@ -60,22 +60,22 @@ struct AccountInfo
AccountTypes SecurityLevel = SEC_PLAYER; AccountTypes SecurityLevel = SEC_PLAYER;
}; };
class AuthSession : public Socket<AuthSession> class AuthSession final : public Socket<AuthSession>
{ {
typedef Socket<AuthSession> AuthSocket; typedef Socket<AuthSession> AuthSocket;
public: public:
static std::unordered_map<uint8, AuthHandler> InitHandlers(); static std::unordered_map<uint8, AuthHandler> InitHandlers();
AuthSession(tcp::socket&& socket); AuthSession(IoContextTcpSocket&& socket);
void Start() override; void Start() override;
bool Update() override; bool Update() final;
void SendPacket(ByteBuffer& packet); void SendPacket(ByteBuffer& packet);
protected: protected:
void ReadHandler() override; SocketReadCallbackResult ReadHandler() final;
private: private:
bool HandleLogonChallenge(); bool HandleLogonChallenge();
@@ -54,9 +54,9 @@ protected:
return threads; return threads;
} }
static void OnSocketAccept(tcp::socket&& sock, uint32 threadIndex) static void OnSocketAccept(IoContextTcpSocket&& sock, uint32 threadIndex)
{ {
Instance().OnSocketOpen(std::forward<tcp::socket>(sock), threadIndex); Instance().OnSocketOpen(std::move(sock), threadIndex);
} }
}; };
@@ -18,18 +18,16 @@
#ifndef __RASESSION_H__ #ifndef __RASESSION_H__
#define __RASESSION_H__ #define __RASESSION_H__
#include <boost/asio/ip/tcp.hpp> #include "Socket.h"
#include <boost/asio/streambuf.hpp> #include <boost/asio/streambuf.hpp>
#include <future> #include <future>
using boost::asio::ip::tcp;
const std::size_t bufferSize = 4096; const std::size_t bufferSize = 4096;
class RASession : public std::enable_shared_from_this<RASession> class RASession : public std::enable_shared_from_this<RASession>
{ {
public: public:
RASession(tcp::socket&& socket) : RASession(IoContextTcpSocket&& socket) :
_socket(std::move(socket)), _commandExecuting(nullptr) { } _socket(std::move(socket)), _commandExecuting(nullptr) { }
void Start(); void Start();
@@ -47,7 +45,7 @@ private:
static void CommandPrint(void* callbackArg, std::string_view text); static void CommandPrint(void* callbackArg, std::string_view text);
static void CommandFinished(void* callbackArg, bool); static void CommandFinished(void* callbackArg, bool);
tcp::socket _socket; IoContextTcpSocket _socket;
boost::asio::streambuf _readBuffer; boost::asio::streambuf _readBuffer;
boost::asio::streambuf _writeBuffer; boost::asio::streambuf _writeBuffer;
std::promise<void>* _commandExecuting; std::promise<void>* _commandExecuting;
@@ -3296,6 +3296,19 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
target->ToUnit()->SetAnimTier(AnimTier(e.action.animTier.animTier)); target->ToUnit()->SetAnimTier(AnimTier(e.action.animTier.animTier));
break; break;
} }
case SMART_ACTION_SET_GOSSIP_MENU:
{
for (WorldObject* target : targets)
{
if (Creature* creature = target->ToCreature())
{
creature->SetGossipMenuId(e.action.setGossipMenu.gossipMenuId);
LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_SET_GOSSIP_MENU: Creature {} set gossip menu to {}",
creature->GetGUID().ToString(), e.action.setGossipMenu.gossipMenuId);
}
}
break;
}
default: default:
LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry {} SourceType {}, Event {}, Unhandled Action type {}", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry {} SourceType {}, Event {}, Unhandled Action type {}", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
break; break;
@@ -885,6 +885,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
case SMART_ACTION_WORLD_SCRIPT: return sizeof(SmartAction::worldStateScript); case SMART_ACTION_WORLD_SCRIPT: return sizeof(SmartAction::worldStateScript);
case SMART_ACTION_DISABLE_REWARD: return sizeof(SmartAction::reward); case SMART_ACTION_DISABLE_REWARD: return sizeof(SmartAction::reward);
case SMART_ACTION_SET_ANIM_TIER: return sizeof(SmartAction::animTier); case SMART_ACTION_SET_ANIM_TIER: return sizeof(SmartAction::animTier);
case SMART_ACTION_SET_GOSSIP_MENU: return sizeof(SmartAction::setGossipMenu);
case SMART_ACTION_DISMOUNT: return NO_PARAMS; case SMART_ACTION_DISMOUNT: return NO_PARAMS;
default: default:
LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using an action with no unused params specified in SmartAIMgr::CheckUnusedActionParams(), please report this.", LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using an action with no unused params specified in SmartAIMgr::CheckUnusedActionParams(), please report this.",
@@ -2040,6 +2041,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_ACTION_MOVEMENT_PAUSE: case SMART_ACTION_MOVEMENT_PAUSE:
case SMART_ACTION_MOVEMENT_RESUME: case SMART_ACTION_MOVEMENT_RESUME:
case SMART_ACTION_WORLD_SCRIPT: case SMART_ACTION_WORLD_SCRIPT:
case SMART_ACTION_SET_GOSSIP_MENU:
break; break;
default: default:
LOG_ERROR("sql.sql", "SmartAIMgr: Not handled action_type({}), event_type({}), Entry {} SourceType {} Event {}, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id); LOG_ERROR("sql.sql", "SmartAIMgr: Not handled action_type({}), event_type({}), Entry {} SourceType {} Event {}, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id);
@@ -724,8 +724,9 @@ enum SMART_ACTION
SMART_ACTION_WORLD_SCRIPT = 237, // eventId, param SMART_ACTION_WORLD_SCRIPT = 237, // eventId, param
SMART_ACTION_DISABLE_REWARD = 238, // reputation 0/1, loot 0/1 SMART_ACTION_DISABLE_REWARD = 238, // reputation 0/1, loot 0/1
SMART_ACTION_SET_ANIM_TIER = 239, // animtier SMART_ACTION_SET_ANIM_TIER = 239, // animtier
SMART_ACTION_SET_GOSSIP_MENU = 240, // gossipMenuId
SMART_ACTION_AC_END = 240, // placeholder SMART_ACTION_AC_END = 241, // placeholder
}; };
enum class SmartActionSummonCreatureFlags enum class SmartActionSummonCreatureFlags
@@ -1510,6 +1511,11 @@ struct SmartAction
{ {
uint32 animTier; uint32 animTier;
} animTier; } animTier;
struct
{
uint32 gossipMenuId;
} setGossipMenu;
}; };
}; };
@@ -52,6 +52,7 @@ BattlegroundSA::BattlegroundSA()
EndRoundTimer = 0s; EndRoundTimer = 0s;
ShipsStarted = false; ShipsStarted = false;
Status = BG_SA_NOTSTARTED; Status = BG_SA_NOTSTARTED;
_nextShipIsEast = true;
for (uint8 i = 0; i < 6; i++) for (uint8 i = 0; i < 6; i++)
GateStatus[i] = BG_SA_GATE_OK; GateStatus[i] = BG_SA_GATE_OK;
@@ -85,6 +86,7 @@ void BattlegroundSA::Init()
_notEvenAScratch[TEAM_HORDE] = true; _notEvenAScratch[TEAM_HORDE] = true;
Status = BG_SA_WARMUP; Status = BG_SA_WARMUP;
_relicClicked = false; _relicClicked = false;
_nextShipIsEast = true;
} }
bool BattlegroundSA::SetupBattleground() bool BattlegroundSA::SetupBattleground()
@@ -181,6 +183,7 @@ bool BattlegroundSA::ResetObjs()
TotalTime = 0s; TotalTime = 0s;
ShipsStarted = false; ShipsStarted = false;
_nextShipIsEast = true;
//Graveyards! //Graveyards!
for (uint8 i = 0; i < BG_SA_MAX_GY; i++) for (uint8 i = 0; i < BG_SA_MAX_GY; i++)
@@ -574,10 +577,12 @@ void BattlegroundSA::TeleportToEntrancePosition(Player* player)
if (!ShipsStarted) if (!ShipsStarted)
{ {
player->CastSpell(player, 12438, true);//Without this player falls before boat loads... player->CastSpell(player, 12438, true);//Without this player falls before boat loads...
if (urand(0, 1)) if (_nextShipIsEast)
player->TeleportTo(MAP_STRAND_OF_THE_ANCIENTS, 2682.936f, -830.368f, 15.0f, 2.895f, 0); player->TeleportTo(MAP_STRAND_OF_THE_ANCIENTS, 2682.936f, -830.368f, 15.0f, 2.895f, 0);
else else
player->TeleportTo(MAP_STRAND_OF_THE_ANCIENTS, 2577.003f, 980.261f, 15.0f, 0.807f, 0); player->TeleportTo(MAP_STRAND_OF_THE_ANCIENTS, 2577.003f, 980.261f, 15.0f, 0.807f, 0);
_nextShipIsEast = !_nextShipIsEast;
} }
else else
player->TeleportTo(MAP_STRAND_OF_THE_ANCIENTS, 1600.381f, -106.263f, 8.8745f, 3.78f, 0); player->TeleportTo(MAP_STRAND_OF_THE_ANCIENTS, 1600.381f, -106.263f, 8.8745f, 3.78f, 0);
@@ -620,5 +620,7 @@ private:
// Achievement: Not Even a Scratch // Achievement: Not Even a Scratch
bool _notEvenAScratch[PVP_TEAMS_COUNT]; bool _notEvenAScratch[PVP_TEAMS_COUNT];
/// Toggle for alternating player spawns between East and West ships (true = first/East ship, false = second/West ship)
bool _nextShipIsEast;
}; };
#endif #endif
+67 -2
View File
@@ -328,7 +328,7 @@ HostileReference* ThreatContainer::SelectNextVictim(Creature* attacker, HostileR
Unit* cvUnit = currentVictim->getTarget(); Unit* cvUnit = currentVictim->getTarget();
if (!attacker->CanCreatureAttack(cvUnit)) // pussywizard: if currentVictim is not valid => don't compare the threat with it, just take the highest threat valid target if (!attacker->CanCreatureAttack(cvUnit)) // pussywizard: if currentVictim is not valid => don't compare the threat with it, just take the highest threat valid target
currentVictim = nullptr; currentVictim = nullptr;
else if (cvUnit->IsImmunedToDamageOrSchool(attacker->GetMeleeDamageSchoolMask()) || cvUnit->HasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_TAKE_DAMAGE) || cvUnit->HasUnitState(UNIT_STATE_CONFUSED)) // pussywizard: no 10%/30% if currentVictim is immune to damage or has auras breakable by damage else if (!IsPreferredTarget(attacker, cvUnit)) // pussywizard: no 10%/30% if currentVictim is immune to damage or has auras breakable by damage
currentVictim = nullptr; currentVictim = nullptr;
} }
@@ -345,7 +345,7 @@ HostileReference* ThreatContainer::SelectNextVictim(Creature* attacker, HostileR
// pussywizard: don't go to threat comparison if this ref is immune to damage or has aura breakable on damage (second choice target) // pussywizard: don't go to threat comparison if this ref is immune to damage or has aura breakable on damage (second choice target)
// pussywizard: if this is the last entry on the threat list, then all targets are second choice, set bool to true and loop threat list again, ignoring this section // pussywizard: if this is the last entry on the threat list, then all targets are second choice, set bool to true and loop threat list again, ignoring this section
if (!noPriorityTargetFound && (target->IsImmunedToDamageOrSchool(attacker->GetMeleeDamageSchoolMask()) || target->HasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_TAKE_DAMAGE) || target->HasUnitState(UNIT_STATE_CONFUSED) || target->HasAuraTypeWithCaster(SPELL_AURA_IGNORED, attacker->GetGUID()))) if (!noPriorityTargetFound && !IsPreferredTarget(attacker, target))
{ {
if (iter != lastRef) if (iter != lastRef)
{ {
@@ -394,6 +394,8 @@ HostileReference* ThreatContainer::SelectNextVictim(Creature* attacker, HostileR
} }
else // pussywizard: no currentVictim, first passing all checks is chosen (highest threat, list is sorted) else // pussywizard: no currentVictim, first passing all checks is chosen (highest threat, list is sorted)
{ {
// tie-breaker if multiple targets have the same threat: select closest target
currentRef = SelectNextVictimTieBreaker(attacker, iter, noPriorityTargetFound);
found = true; found = true;
break; break;
} }
@@ -406,6 +408,69 @@ HostileReference* ThreatContainer::SelectNextVictim(Creature* attacker, HostileR
return currentRef; return currentRef;
} }
// Helper for Tie-breakers
HostileReference* ThreatContainer::SelectNextVictimTieBreaker(Creature* attacker, ThreatContainer::StorageType::const_iterator currentIter, bool noPriorityTargetFound) const
{
HostileReference* bestRef = *currentIter;
float bestThreat = bestRef->GetThreat();
float shortestDistSq = attacker->GetExactDistSq(bestRef->getTarget());
auto tieIter = std::next(currentIter);
while (tieIter != iThreatList.end())
{
HostileReference* nextRef = *tieIter;
if (!nextRef)
{
++tieIter;
continue;
}
// Threatlist is sorted, so we can stop as soon as we find a lower threat
if (bestThreat - nextRef->GetThreat() > 0.01f)
break;
Unit* target = nextRef->getTarget();
if (!target)
{
++tieIter;
continue;
}
if (attacker->CanCreatureAttack(target) && (noPriorityTargetFound || IsPreferredTarget(attacker, target)))
{
float distSq = attacker->GetExactDistSq(target);
if (distSq < shortestDistSq)
{
bestRef = nextRef;
shortestDistSq = distSq;
}
}
++tieIter;
}
return bestRef;
}
// Helper for checking if a target is preferred (not immune, not confused, etc)
bool ThreatContainer::IsPreferredTarget(Creature* attacker, Unit* target) const
{
if (target->IsImmunedToDamageOrSchool(attacker->GetMeleeDamageSchoolMask()))
return false;
if (target->HasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_TAKE_DAMAGE))
return false;
if (target->HasUnitState(UNIT_STATE_CONFUSED))
return false;
if (target->HasAuraTypeWithCaster(SPELL_AURA_IGNORED, attacker->GetGUID()))
return false;
return true;
}
//============================================================ //============================================================
//=================== ThreatMgr ========================== //=================== ThreatMgr ==========================
//============================================================ //============================================================
+4
View File
@@ -156,6 +156,10 @@ public:
HostileReference* SelectNextVictim(Creature* attacker, HostileReference* currentVictim) const; HostileReference* SelectNextVictim(Creature* attacker, HostileReference* currentVictim) const;
HostileReference* SelectNextVictimTieBreaker(Creature* attacker, ThreatContainer::StorageType::const_iterator currentIter, bool noPriorityTargetFound) const;
bool IsPreferredTarget(Creature* attacker, Unit* target) const;
void setDirty(bool isDirty) { iDirty = isDirty; } void setDirty(bool isDirty) { iDirty = isDirty; }
[[nodiscard]] bool isDirty() const { return iDirty; } [[nodiscard]] bool isDirty() const { return iDirty; }
+5 -5
View File
@@ -542,13 +542,13 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)
condMeets = object->GetMap()->GetDifficulty() == ConditionValue1; condMeets = object->GetMap()->GetDifficulty() == ConditionValue1;
break; break;
} }
case CONDITION_RANDOM_DUNGEON: case CONDITION_PLAYER_QUEUED_RANDOM_DUNGEON:
{ {
if (Unit* unit = object->ToUnit()) if (Unit* unit = object->ToUnit())
{ {
if (Player* player = unit->GetCharmerOrOwnerPlayerOrPlayerItself()) if (Player* player = unit->ToPlayer())
{ {
if (sLFGMgr->selectedRandomLfgDungeon(player->GetGUID())) if (sLFGMgr->IsPlayerQueuedForRandomDungeon(player->GetGUID()))
{ {
if (!ConditionValue1) if (!ConditionValue1)
condMeets = true; condMeets = true;
@@ -803,7 +803,7 @@ uint32 Condition::GetSearcherTypeMaskForCondition()
case CONDITION_CHARMED: case CONDITION_CHARMED:
mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER; mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
break; break;
case CONDITION_RANDOM_DUNGEON: case CONDITION_PLAYER_QUEUED_RANDOM_DUNGEON:
mask |= GRID_MAP_TYPE_MASK_PLAYER; mask |= GRID_MAP_TYPE_MASK_PLAYER;
break; break;
case CONDITION_WORLD_SCRIPT: case CONDITION_WORLD_SCRIPT:
@@ -2486,7 +2486,7 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond)
return false; return false;
} }
break; break;
case CONDITION_RANDOM_DUNGEON: case CONDITION_PLAYER_QUEUED_RANDOM_DUNGEON:
if (cond->ConditionValue1 > 1) if (cond->ConditionValue1 > 1)
{ {
LOG_ERROR("sql.sql", "RandomDungeon condition has useless data in value1 ({}).", cond->ConditionValue1); LOG_ERROR("sql.sql", "RandomDungeon condition has useless data in value1 ({}).", cond->ConditionValue1);
+1 -1
View File
@@ -88,7 +88,7 @@ enum ConditionTypes
CONDITION_HAS_AURA_TYPE = 102, // aura_type 0 0 true if has aura type CONDITION_HAS_AURA_TYPE = 102, // aura_type 0 0 true if has aura type
CONDITION_WORLD_SCRIPT = 103, // conditionId state 0 true if WorldState::IsConditionFulfilled returns true CONDITION_WORLD_SCRIPT = 103, // conditionId state 0 true if WorldState::IsConditionFulfilled returns true
CONDITION_AI_DATA = 104, // dataId value 0 true if AI::GetData returns value CONDITION_AI_DATA = 104, // dataId value 0 true if AI::GetData returns value
CONDITION_RANDOM_DUNGEON = 105, // difficulty (0 = any) 0 0 true if player is queued for a random dungeon via RDF (param1 = Difficulty) CONDITION_PLAYER_QUEUED_RANDOM_DUNGEON = 105, // checkDifficulty difficulty 0 true if player is queued for a random dungeon via RDF
CONDITION_AC_END = 106 // placeholder CONDITION_AC_END = 106 // placeholder
}; };
@@ -139,4 +139,13 @@ namespace lfg
return m_KicksLeft; return m_KicksLeft;
} }
void LfgGroupData::AddRandomQueuedPlayer(ObjectGuid guid)
{
m_RandomQueuedPlayers.insert(guid);
}
[[nodiscard]] bool LfgGroupData::IsRandomQueuedPlayer(ObjectGuid guid) const
{
return m_RandomQueuedPlayers.contains(guid);
}
} // namespace lfg } // namespace lfg
@@ -37,6 +37,8 @@ namespace lfg
void SetState(LfgState state); void SetState(LfgState state);
void RestoreState(); void RestoreState();
void AddPlayer(ObjectGuid guid); void AddPlayer(ObjectGuid guid);
void AddRandomQueuedPlayer(ObjectGuid guid);
[[nodiscard]] bool IsRandomQueuedPlayer(ObjectGuid guid) const;
uint8 RemovePlayer(ObjectGuid guid); uint8 RemovePlayer(ObjectGuid guid);
void RemoveAllPlayers(); void RemoveAllPlayers();
void SetLeader(ObjectGuid guid); void SetLeader(ObjectGuid guid);
@@ -66,6 +68,7 @@ namespace lfg
LfgState m_OldState; ///< Old State LfgState m_OldState; ///< Old State
ObjectGuid m_Leader; ///< Leader GUID ObjectGuid m_Leader; ///< Leader GUID
LfgGuidSet m_Players; ///< Players in group LfgGuidSet m_Players; ///< Players in group
LfgGuidSet m_RandomQueuedPlayers; ///< Players that queued for random dungeon
// Dungeon // Dungeon
uint32 m_Dungeon; ///< Dungeon entry uint32 m_Dungeon; ///< Dungeon entry
bool _isLFGGroup; bool _isLFGGroup;
+20
View File
@@ -2583,6 +2583,18 @@ namespace lfg
GroupsStore[gguid].AddPlayer(guid); GroupsStore[gguid].AddPlayer(guid);
} }
void LFGMgr::AddPlayerQueuedForRandomDungeonToGroup(ObjectGuid gguid, ObjectGuid guid)
{
const LfgDungeonSet& dungeons = GetSelectedDungeons(guid);
if (dungeons.empty())
return;
uint32 dungeonId = *dungeons.begin();
LFGDungeonData const* dungeon = GetLFGDungeon(dungeonId);
if (dungeon && (dungeon->type == LFG_TYPE_RANDOM))
GroupsStore[gguid].AddRandomQueuedPlayer(guid);
}
void LFGMgr::SetLeader(ObjectGuid gguid, ObjectGuid leader) void LFGMgr::SetLeader(ObjectGuid gguid, ObjectGuid leader)
{ {
GroupsStore[gguid].SetLeader(leader); GroupsStore[gguid].SetLeader(leader);
@@ -2839,4 +2851,12 @@ namespace lfg
sDisableMgr->IsDisabledFor(DISABLE_TYPE_LFG_MAP, mapId, nullptr); sDisableMgr->IsDisabledFor(DISABLE_TYPE_LFG_MAP, mapId, nullptr);
} }
bool LFGMgr::IsPlayerQueuedForRandomDungeon(ObjectGuid guid)
{
auto gguid = GetGroup(guid);
if (!gguid)
return false;
return GroupsStore[gguid].IsRandomQueuedPlayer(guid);
}
} // namespace lfg } // namespace lfg
+3
View File
@@ -506,6 +506,9 @@ namespace lfg
uint8 RemovePlayerFromGroup(ObjectGuid gguid, ObjectGuid guid); uint8 RemovePlayerFromGroup(ObjectGuid gguid, ObjectGuid guid);
/// Adds player to group /// Adds player to group
void AddPlayerToGroup(ObjectGuid gguid, ObjectGuid guid); void AddPlayerToGroup(ObjectGuid gguid, ObjectGuid guid);
/// Store player that selected random queue to group
void AddPlayerQueuedForRandomDungeonToGroup(ObjectGuid gguid, ObjectGuid guid);
bool IsPlayerQueuedForRandomDungeon(ObjectGuid guid);
/// Xinef: Set Random Players Count /// Xinef: Set Random Players Count
void SetRandomPlayersCount(ObjectGuid guid, uint8 count); void SetRandomPlayersCount(ObjectGuid guid, uint8 count);
/// Xinef: Get Random Players Count /// Xinef: Get Random Players Count
@@ -187,6 +187,7 @@ namespace lfg
sLFGMgr->SetGroup(guid, gguid); sLFGMgr->SetGroup(guid, gguid);
sLFGMgr->AddPlayerToGroup(gguid, guid); sLFGMgr->AddPlayerToGroup(gguid, guid);
sLFGMgr->AddPlayerQueuedForRandomDungeonToGroup(gguid, guid);
// pussywizard: after all necessary actions handle raid browser // pussywizard: after all necessary actions handle raid browser
if (sLFGMgr->GetState(guid) == LFG_STATE_RAIDBROWSER) if (sLFGMgr->GetState(guid) == LFG_STATE_RAIDBROWSER)
@@ -265,7 +265,7 @@ Creature::Creature(): Unit(), MovableMapObject(), m_groupLootTimer(0), lootingGr
m_corpseRemoveTime(0), m_respawnTime(0), m_respawnDelay(300), m_corpseDelay(60), m_wanderDistance(0.0f), m_boundaryCheckTime(2500), m_corpseRemoveTime(0), m_respawnTime(0), m_respawnDelay(300), m_corpseDelay(60), m_wanderDistance(0.0f), m_boundaryCheckTime(2500),
m_transportCheckTimer(1000), lootPickPocketRestoreTime(0), m_combatPulseTime(0), m_combatPulseDelay(0), m_reactState(REACT_AGGRESSIVE), m_defaultMovementType(IDLE_MOTION_TYPE), m_transportCheckTimer(1000), lootPickPocketRestoreTime(0), m_combatPulseTime(0), m_combatPulseDelay(0), m_reactState(REACT_AGGRESSIVE), m_defaultMovementType(IDLE_MOTION_TYPE),
m_spawnId(0), m_equipmentId(0), m_originalEquipmentId(0), m_alreadyCallForHelp(false), m_AlreadyCallAssistance(false), m_spawnId(0), m_equipmentId(0), m_originalEquipmentId(0), m_alreadyCallForHelp(false), m_AlreadyCallAssistance(false),
m_AlreadySearchedAssistance(false), m_regenHealth(true), m_regenPower(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_moveInLineOfSightDisabled(false), m_moveInLineOfSightStrictlyDisabled(false), m_AlreadySearchedAssistance(false), m_regenHealth(true), m_regenPower(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), _gossipMenuId(0), m_moveInLineOfSightDisabled(false), m_moveInLineOfSightStrictlyDisabled(false),
m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_detectionDistance(20.0f),_sparringPct(0.0f), m_waypointID(0), m_path_id(0), m_formation(nullptr), m_lastLeashExtensionTime(nullptr), m_cannotReachTimer(0), m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_detectionDistance(20.0f),_sparringPct(0.0f), m_waypointID(0), m_path_id(0), m_formation(nullptr), m_lastLeashExtensionTime(nullptr), m_cannotReachTimer(0),
_isMissingSwimmingFlagOutOfCombat(false), m_assistanceTimer(0), _playerDamageReq(0), _damagedByPlayer(false), _isCombatMovementAllowed(true) _isMissingSwimmingFlagOutOfCombat(false), m_assistanceTimer(0), _playerDamageReq(0), _damagedByPlayer(false), _isCombatMovementAllowed(true)
{ {
@@ -204,6 +204,8 @@ public:
[[nodiscard]] CreatureTemplate const* GetCreatureTemplate() const { return m_creatureInfo; } [[nodiscard]] CreatureTemplate const* GetCreatureTemplate() const { return m_creatureInfo; }
[[nodiscard]] CreatureData const* GetCreatureData() const { return m_creatureData; } [[nodiscard]] CreatureData const* GetCreatureData() const { return m_creatureData; }
[[nodiscard]] uint32 GetGossipMenuId() const { return _gossipMenuId ? _gossipMenuId : GetCreatureTemplate()->GossipMenuId; }
void SetGossipMenuId(uint32 gossipMenuId) { _gossipMenuId = gossipMenuId; }
void SetDetectionDistance(float dist){ m_detectionDistance = dist; } void SetDetectionDistance(float dist){ m_detectionDistance = dist; }
[[nodiscard]] CreatureAddon const* GetCreatureAddon() const; [[nodiscard]] CreatureAddon const* GetCreatureAddon() const;
@@ -478,6 +480,7 @@ protected:
SpellSchoolMask m_meleeDamageSchoolMask; SpellSchoolMask m_meleeDamageSchoolMask;
uint32 m_originalEntry; uint32 m_originalEntry;
uint32 _gossipMenuId;
bool m_moveInLineOfSightDisabled; bool m_moveInLineOfSightDisabled;
bool m_moveInLineOfSightStrictlyDisabled; bool m_moveInLineOfSightStrictlyDisabled;
+3 -6
View File
@@ -1642,12 +1642,9 @@ void Player::ProcessDelayedOperations()
if (m_DelayedOperations & DELAYED_SAVE_PLAYER) if (m_DelayedOperations & DELAYED_SAVE_PLAYER)
SaveToDB(false, false); SaveToDB(false, false);
if (m_DelayedOperations & DELAYED_SPELL_CAST_DESERTER) if ((m_DelayedOperations & DELAYED_SPELL_CAST_DESERTER)
{ && !GetAura(26013))
Aura* aura = GetAura(26013);
if (!aura || aura->GetDuration() <= 900000)
CastSpell(this, 26013, true); CastSpell(this, 26013, true);
}
if (m_DelayedOperations & DELAYED_BG_MOUNT_RESTORE) if (m_DelayedOperations & DELAYED_BG_MOUNT_RESTORE)
{ {
@@ -14378,7 +14375,7 @@ bool Player::CanSeeVendor(Creature const* creature) const
if (!sConditionMgr->IsObjectMeetToConditions(const_cast<Player*>(this), const_cast<Creature*>(creature), conditions)) if (!sConditionMgr->IsObjectMeetToConditions(const_cast<Player*>(this), const_cast<Creature*>(creature), conditions))
return false; return false;
uint32 const menuId = creature->GetCreatureTemplate()->GossipMenuId; uint32 const menuId = creature->GetGossipMenuId();
if (!AnyVendorOptionAvailable(menuId, creature)) if (!AnyVendorOptionAvailable(menuId, creature))
return false; return false;
@@ -429,7 +429,7 @@ uint32 Player::GetDefaultGossipMenuForSource(WorldObject* source)
switch (source->GetTypeId()) switch (source->GetTypeId())
{ {
case TYPEID_UNIT: case TYPEID_UNIT:
return source->ToCreature()->GetCreatureTemplate()->GossipMenuId; return source->ToCreature()->GetGossipMenuId();
case TYPEID_GAMEOBJECT: case TYPEID_GAMEOBJECT:
return source->ToGameObject()->GetGOInfo()->GetGossipMenuId(); return source->ToGameObject()->GetGOInfo()->GetGossipMenuId();
default: default:
+12 -12
View File
@@ -2148,7 +2148,7 @@ uint32 Unit::CalcArmorReducedDamage(Unit const* attacker, Unit const* victim, co
float Unit::GetEffectiveResistChance(Unit const* owner, SpellSchoolMask schoolMask, Unit const* victim) float Unit::GetEffectiveResistChance(Unit const* owner, SpellSchoolMask schoolMask, Unit const* victim)
{ {
float victimResistance = float(victim->GetResistance(schoolMask)); float victimResistance = static_cast<float>(victim->GetResistance(schoolMask));
if (owner) if (owner)
{ {
// Xinef: pets inherit 100% of masters penetration // Xinef: pets inherit 100% of masters penetration
@@ -2156,28 +2156,28 @@ float Unit::GetEffectiveResistChance(Unit const* owner, SpellSchoolMask schoolMa
Player const* player = owner->GetSpellModOwner(); Player const* player = owner->GetSpellModOwner();
if (player && owner->GetEntry() != WORLD_TRIGGER) if (player && owner->GetEntry() != WORLD_TRIGGER)
{ {
victimResistance += float(player->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask)); victimResistance += static_cast<float>(player->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask));
victimResistance -= float(player->GetSpellPenetrationItemMod()); victimResistance -= static_cast<float>(player->GetSpellPenetrationItemMod());
} }
else else
victimResistance += float(owner->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask)); victimResistance += static_cast<float>(owner->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask));
} }
victimResistance = std::max(victimResistance, 0.0f); victimResistance = std::max(victimResistance, 0.0f);
if (owner) if (owner)
victimResistance += std::max((float(victim->GetLevel()) - float(owner->GetLevel())) * 5.0f, 0.0f); victimResistance += std::max(static_cast<float>(victim->GetLevel() - owner->GetLevel()) * 5.0f, 0.0f);
static uint32 const BOSS_LEVEL = 83; float level = static_cast<float>(victim->GetLevel());
static float const BOSS_RESISTANCE_CONSTANT = 510.0f;
uint32 level = victim->GetLevel();
float resistanceConstant = 0.0f; float resistanceConstant = 0.0f;
if (level == BOSS_LEVEL) if (level > 60.0f)
resistanceConstant = BOSS_RESISTANCE_CONSTANT; resistanceConstant = 150.0f + (level - 60.0f) * (level - 67.5f);
else if (level > 20.0f)
resistanceConstant = 50.0f + (level - 20.0f) * 2.5f;
else else
resistanceConstant = level * 5.0f; resistanceConstant = 50.0f;
return victimResistance / (victimResistance + resistanceConstant); return std::min(victimResistance / (victimResistance + resistanceConstant), 0.75f);
} }
void Unit::CalcAbsorbResist(DamageInfo& dmgInfo, bool Splited) void Unit::CalcAbsorbResist(DamageInfo& dmgInfo, bool Splited)
+3
View File
@@ -602,7 +602,10 @@ void WorldSession::HandleSellItemOpcode(WorldPackets::Item::SellItem& packet)
if (pItem) if (pItem)
{ {
if (!sScriptMgr->OnPlayerCanSellItem(_player, pItem, creature)) if (!sScriptMgr->OnPlayerCanSellItem(_player, pItem, creature))
{
_player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, packet.ItemGuid, 0);
return; return;
}
// prevent sell not owner item // prevent sell not owner item
if (_player->GetGUID() != pItem->GetOwnerGUID()) if (_player->GetGUID() != pItem->GetOwnerGUID())
+1 -1
View File
@@ -179,7 +179,7 @@ void WorldSession::HandleGossipHelloOpcode(WorldPacket& recvData)
if (!sScriptMgr->OnGossipHello(_player, unit)) if (!sScriptMgr->OnGossipHello(_player, unit))
{ {
// _player->TalkedToCreature(unit->GetEntry(), unit->GetGUID()); // _player->TalkedToCreature(unit->GetEntry(), unit->GetGUID());
_player->PrepareGossipMenu(unit, unit->GetCreatureTemplate()->GossipMenuId, true); _player->PrepareGossipMenu(unit, unit->GetGossipMenuId(), true);
_player->SendPreparedGossip(unit); _player->SendPreparedGossip(unit);
} }
unit->AI()->sGossipHello(_player); unit->AI()->sGossipHello(_player);
+1 -1
View File
@@ -101,7 +101,7 @@ void WorldSession::HandleQuestgiverHelloOpcode(WorldPacket& recvData)
if (sScriptMgr->OnGossipHello(_player, creature)) if (sScriptMgr->OnGossipHello(_player, creature))
return; return;
_player->PrepareGossipMenu(creature, creature->GetCreatureTemplate()->GossipMenuId, true); _player->PrepareGossipMenu(creature, creature->GetGossipMenuId(), true);
_player->SendPreparedGossip(creature); _player->SendPreparedGossip(creature);
creature->AI()->sGossipHello(_player); creature->AI()->sGossipHello(_player);
@@ -436,7 +436,7 @@ static Optional<float> GetVelocity(Unit* owner, Unit* target, G3D::Vector3 const
(owner->IsPet() || owner->IsGuardian() || owner->GetGUID() == target->GetCritterGUID() || owner->GetCharmerOrOwnerGUID() == target->GetGUID())) (owner->IsPet() || owner->IsGuardian() || owner->GetGUID() == target->GetCritterGUID() || owner->GetCharmerOrOwnerGUID() == target->GetGUID()))
{ {
uint32 moveFlags = target->GetUnitMovementFlags(); uint32 moveFlags = target->GetUnitMovementFlags();
if (target->movespline->isWalking()) if (target->IsWalking())
{ {
moveFlags |= MOVEMENTFLAG_WALKING; moveFlags |= MOVEMENTFLAG_WALKING;
} }
@@ -635,7 +635,7 @@ bool FollowMovementGenerator<T>::DoUpdate(T* owner, uint32 time_diff)
Movement::MoveSplineInit init(owner); Movement::MoveSplineInit init(owner);
init.MovebyPath(i_path->GetPath()); init.MovebyPath(i_path->GetPath());
if (_inheritWalkState) if (_inheritWalkState)
init.SetWalk(target->IsWalking() || target->movespline->isWalking()); init.SetWalk(target->IsWalking());
if (_inheritSpeed) if (_inheritSpeed)
if (Optional<float> velocity = GetVelocity(owner, target, i_path->GetActualEndPosition(), owner->IsGuardian())) if (Optional<float> velocity = GetVelocity(owner, target, i_path->GetActualEndPosition(), owner->IsGuardian()))
@@ -116,7 +116,6 @@ namespace Movement
[[nodiscard]] bool Finalized() const { return splineflags.done; } [[nodiscard]] bool Finalized() const { return splineflags.done; }
[[nodiscard]] bool isCyclic() const { return splineflags.cyclic; } [[nodiscard]] bool isCyclic() const { return splineflags.cyclic; }
[[nodiscard]] bool isFalling() const { return splineflags.falling; } [[nodiscard]] bool isFalling() const { return splineflags.falling; }
[[nodiscard]] bool isWalking() const { return splineflags.walkmode; }
[[nodiscard]] bool isBoarding() const { return splineflags.transportEnter || splineflags.transportExit; } [[nodiscard]] bool isBoarding() const { return splineflags.transportEnter || splineflags.transportExit; }
[[nodiscard]] Vector3 FinalDestination() const { return Initialized() ? spline.getPoint(spline.last()) : Vector3(); } [[nodiscard]] Vector3 FinalDestination() const { return Initialized() ? spline.getPoint(spline.last()) : Vector3(); }
[[nodiscard]] Vector3 CurrentDestination() const { return Initialized() ? spline.getPoint(point_Idx + 1) : Vector3(); } [[nodiscard]] Vector3 CurrentDestination() const { return Initialized() ? spline.getPoint(point_Idx + 1) : Vector3(); }
@@ -40,7 +40,7 @@ namespace Movement
Falling = 0x00000200, // Affects elevation computation, can't be combined with Parabolic flag Falling = 0x00000200, // Affects elevation computation, can't be combined with Parabolic flag
No_Spline = 0x00000400, No_Spline = 0x00000400,
Parabolic = 0x00000800, // Affects elevation computation, can't be combined with Falling flag Parabolic = 0x00000800, // Affects elevation computation, can't be combined with Falling flag
Walkmode = 0x00001000, CanSwim = 0x00001000,
Flying = 0x00002000, // Smooth movement(Catmullrom interpolation mode), flying animation Flying = 0x00002000, // Smooth movement(Catmullrom interpolation mode), flying animation
OrientationFixed = 0x00004000, // Model orientation fixed OrientationFixed = 0x00004000, // Model orientation fixed
Final_Point = 0x00008000, Final_Point = 0x00008000,
@@ -117,7 +117,7 @@ namespace Movement
bool falling : 1; bool falling : 1;
bool no_spline : 1; bool no_spline : 1;
bool parabolic : 1; bool parabolic : 1;
bool walkmode : 1; bool canSwim : 1;
bool flying : 1; bool flying : 1;
bool orientationFixed : 1; bool orientationFixed : 1;
bool final_point : 1; bool final_point : 1;
@@ -118,7 +118,7 @@ namespace Movement
// If spline is initialized with SetWalk method it only means we need to select // If spline is initialized with SetWalk method it only means we need to select
// walk move speed for it but not add walk flag to unit // walk move speed for it but not add walk flag to unit
uint32 moveFlagsForSpeed = moveFlags; uint32 moveFlagsForSpeed = moveFlags;
if (args.flags.walkmode) if (args.walk)
moveFlagsForSpeed |= MOVEMENTFLAG_WALKING; moveFlagsForSpeed |= MOVEMENTFLAG_WALKING;
else else
moveFlagsForSpeed &= ~MOVEMENTFLAG_WALKING; moveFlagsForSpeed &= ~MOVEMENTFLAG_WALKING;
@@ -199,7 +199,7 @@ namespace Movement
args.splineId = splineIdGen.NewId(); args.splineId = splineIdGen.NewId();
args.TransformForTransport = unit->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && unit->GetTransGUID(); args.TransformForTransport = unit->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && unit->GetTransGUID();
// mix existing state into new // mix existing state into new
args.flags.walkmode = unit->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING); args.walk = unit->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING);
args.flags.flying = unit->m_movementInfo.HasMovementFlag((MovementFlags)(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_DISABLE_GRAVITY)); args.flags.flying = unit->m_movementInfo.HasMovementFlag((MovementFlags)(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_DISABLE_GRAVITY));
} }
@@ -154,7 +154,7 @@ namespace Movement
}; };
inline void MoveSplineInit::SetFly() { args.flags.EnableFlying(); } inline void MoveSplineInit::SetFly() { args.flags.EnableFlying(); }
inline void MoveSplineInit::SetWalk(bool enable) { args.flags.walkmode = enable; } inline void MoveSplineInit::SetWalk(bool enable) { args.walk = enable; }
inline void MoveSplineInit::SetSmooth() { args.flags.EnableCatmullRom(); } inline void MoveSplineInit::SetSmooth() { args.flags.EnableCatmullRom(); }
inline void MoveSplineInit::SetCyclic() { args.flags.cyclic = true; } inline void MoveSplineInit::SetCyclic() { args.flags.cyclic = true; }
inline void MoveSplineInit::SetFall() { args.flags.EnableFalling(); } inline void MoveSplineInit::SetFall() { args.flags.EnableFalling(); }
@@ -59,6 +59,7 @@ namespace Movement
float initialOrientation{0.f}; float initialOrientation{0.f};
bool HasVelocity{false}; bool HasVelocity{false};
bool TransformForTransport{true}; bool TransformForTransport{true};
bool walk;
/** Returns true to show that the arguments were configured correctly and MoveSpline initialization will succeed. */ /** Returns true to show that the arguments were configured correctly and MoveSpline initialization will succeed. */
bool Validate(Unit* unit) const; bool Validate(Unit* unit) const;
@@ -153,7 +153,7 @@ namespace Movement
STR(Falling ), // 0x00000200, // Not Compartible With Trajectory Movement STR(Falling ), // 0x00000200, // Not Compartible With Trajectory Movement
STR(No_Spline ), // 0x00000400, STR(No_Spline ), // 0x00000400,
STR(Trajectory ), // 0x00000800, // Not Compartible With Fall Movement STR(Trajectory ), // 0x00000800, // Not Compartible With Fall Movement
STR(Walkmode ), // 0x00001000, STR(CanSwim ), // 0x00001000,
STR(Flying ), // 0x00002000, // Smooth Movement(Catmullrom Interpolation Mode), Flying Animation STR(Flying ), // 0x00002000, // Smooth Movement(Catmullrom Interpolation Mode), Flying Animation
STR(Knockback ), // 0x00004000, // Model Orientation Fixed STR(Knockback ), // 0x00004000, // Model Orientation Fixed
STR(Final_Point ), // 0x00008000, STR(Final_Point ), // 0x00008000,
@@ -29,14 +29,14 @@ void ScriptMgr::OnNetworkStop()
CALL_ENABLED_HOOKS(ServerScript, SERVERHOOK_ON_NETWORK_STOP, script->OnNetworkStop()); CALL_ENABLED_HOOKS(ServerScript, SERVERHOOK_ON_NETWORK_STOP, script->OnNetworkStop());
} }
void ScriptMgr::OnSocketOpen(std::shared_ptr<WorldSocket> socket) void ScriptMgr::OnSocketOpen(std::shared_ptr<WorldSocket> const& socket)
{ {
ASSERT(socket); ASSERT(socket);
CALL_ENABLED_HOOKS(ServerScript, SERVERHOOK_ON_SOCKET_OPEN, script->OnSocketOpen(socket)); CALL_ENABLED_HOOKS(ServerScript, SERVERHOOK_ON_SOCKET_OPEN, script->OnSocketOpen(socket));
} }
void ScriptMgr::OnSocketClose(std::shared_ptr<WorldSocket> socket) void ScriptMgr::OnSocketClose(std::shared_ptr<WorldSocket> const& socket)
{ {
ASSERT(socket); ASSERT(socket);
@@ -46,11 +46,11 @@ public:
virtual void OnNetworkStop() { } virtual void OnNetworkStop() { }
// Called when a remote socket establishes a connection to the server. Do not store the socket object. // Called when a remote socket establishes a connection to the server. Do not store the socket object.
virtual void OnSocketOpen(std::shared_ptr<WorldSocket> /*socket*/) { } virtual void OnSocketOpen(std::shared_ptr<WorldSocket> const& /*socket*/) { }
// Called when a socket is closed. Do not store the socket object, and do not rely on the connection // Called when a socket is closed. Do not store the socket object, and do not rely on the connection
// being open; it is not. // being open; it is not.
virtual void OnSocketClose(std::shared_ptr<WorldSocket> /*socket*/) { } virtual void OnSocketClose(std::shared_ptr<WorldSocket> const& /*socket*/) { }
/** /**
* @brief This hook called when a packet is sent to a client. The packet object is a copy of the original packet, so reading and modifying it is safe. * @brief This hook called when a packet is sent to a client. The packet object is a copy of the original packet, so reading and modifying it is safe.
+2 -2
View File
@@ -174,8 +174,8 @@ public: /* SpellScriptLoader */
public: /* ServerScript */ public: /* ServerScript */
void OnNetworkStart(); void OnNetworkStart();
void OnNetworkStop(); void OnNetworkStop();
void OnSocketOpen(std::shared_ptr<WorldSocket> socket); void OnSocketOpen(std::shared_ptr<WorldSocket> const& socket);
void OnSocketClose(std::shared_ptr<WorldSocket> socket); void OnSocketClose(std::shared_ptr<WorldSocket> const& socket);
bool CanPacketReceive(WorldSession* session, WorldPacket const& packet); bool CanPacketReceive(WorldSession* session, WorldPacket const& packet);
void OnPacketReceived(WorldSession* session, WorldPacket const& packet); void OnPacketReceived(WorldSession* session, WorldPacket const& packet);
bool CanPacketSend(WorldSession* session, WorldPacket const& packet); bool CanPacketSend(WorldSession* session, WorldPacket const& packet);
+9 -9
View File
@@ -116,7 +116,7 @@ void EncryptableAndCompressiblePacket::CompressIfNeeded()
SetOpcode(SMSG_COMPRESSED_UPDATE_OBJECT); SetOpcode(SMSG_COMPRESSED_UPDATE_OBJECT);
} }
WorldSocket::WorldSocket(tcp::socket&& socket) WorldSocket::WorldSocket(IoContextTcpSocket&& socket)
: Socket(std::move(socket)), _OverSpeedPings(0), _worldSession(nullptr), _authed(false), _sendBufferSize(4096), _loggingPackets(false) : Socket(std::move(socket)), _OverSpeedPings(0), _worldSession(nullptr), _authed(false), _sendBufferSize(4096), _loggingPackets(false)
{ {
Acore::Crypto::GetRandomBytes(_authSeed); Acore::Crypto::GetRandomBytes(_authSeed);
@@ -238,10 +238,10 @@ void WorldSocket::OnClose()
} }
} }
void WorldSocket::ReadHandler() SocketReadCallbackResult WorldSocket::ReadHandler()
{ {
if (!IsOpen()) if (!IsOpen())
return; return SocketReadCallbackResult::Stop;
MessageBuffer& packet = GetReadBuffer(); MessageBuffer& packet = GetReadBuffer();
while (packet.GetActiveSize() > 0) while (packet.GetActiveSize() > 0)
@@ -264,7 +264,7 @@ void WorldSocket::ReadHandler()
if (!ReadHeaderHandler()) if (!ReadHeaderHandler())
{ {
CloseSocket(); CloseSocket();
return; return SocketReadCallbackResult::Stop;
} }
} }
@@ -295,11 +295,11 @@ void WorldSocket::ReadHandler()
CloseSocket(); CloseSocket();
} }
return; return SocketReadCallbackResult::Stop;
} }
} }
AsyncRead(); return SocketReadCallbackResult::KeepReading;
} }
bool WorldSocket::ReadHeaderHandler() bool WorldSocket::ReadHeaderHandler()
@@ -329,7 +329,7 @@ bool WorldSocket::ReadHeaderHandler()
return true; return true;
} }
struct AuthSession struct ClientAuthSession
{ {
uint32 BattlegroupID = 0; uint32 BattlegroupID = 0;
uint32 LoginServerType = 0; uint32 LoginServerType = 0;
@@ -528,7 +528,7 @@ void WorldSocket::SendPacket(WorldPacket const& packet)
void WorldSocket::HandleAuthSession(WorldPacket & recvPacket) void WorldSocket::HandleAuthSession(WorldPacket & recvPacket)
{ {
std::shared_ptr<AuthSession> authSession = std::make_shared<AuthSession>(); std::shared_ptr<ClientAuthSession> authSession = std::make_shared<ClientAuthSession>();
// Read the content of the packet // Read the content of the packet
recvPacket >> authSession->Build; recvPacket >> authSession->Build;
@@ -552,7 +552,7 @@ void WorldSocket::HandleAuthSession(WorldPacket & recvPacket)
_queryProcessor.AddCallback(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSocket::HandleAuthSessionCallback, this, authSession, std::placeholders::_1))); _queryProcessor.AddCallback(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSocket::HandleAuthSessionCallback, this, authSession, std::placeholders::_1)));
} }
void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<AuthSession> authSession, PreparedQueryResult result) void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<ClientAuthSession> authSession, PreparedQueryResult result)
{ {
// Stop if the account is not found // Stop if the account is not found
if (!result) if (!result)
+6 -6
View File
@@ -65,21 +65,21 @@ struct ClientPktHeader
}; };
#pragma pack(pop) #pragma pack(pop)
struct AuthSession; struct ClientAuthSession;
class AC_GAME_API WorldSocket : public Socket<WorldSocket> class AC_GAME_API WorldSocket final : public Socket<WorldSocket>
{ {
typedef Socket<WorldSocket> BaseSocket; typedef Socket<WorldSocket> BaseSocket;
public: public:
WorldSocket(tcp::socket&& socket); WorldSocket(IoContextTcpSocket&& socket);
~WorldSocket(); ~WorldSocket();
WorldSocket(WorldSocket const& right) = delete; WorldSocket(WorldSocket const& right) = delete;
WorldSocket& operator=(WorldSocket const& right) = delete; WorldSocket& operator=(WorldSocket const& right) = delete;
void Start() override; void Start() override;
bool Update() override; bool Update() final;
void SendPacket(WorldPacket const& packet); void SendPacket(WorldPacket const& packet);
@@ -90,7 +90,7 @@ public:
protected: protected:
void OnClose() override; void OnClose() override;
void ReadHandler() override; SocketReadCallbackResult ReadHandler() final;
bool ReadHeaderHandler(); bool ReadHeaderHandler();
enum class ReadDataHandlerResult enum class ReadDataHandlerResult
@@ -113,7 +113,7 @@ private:
void SendPacketAndLogOpcode(WorldPacket const& packet); void SendPacketAndLogOpcode(WorldPacket const& packet);
void HandleSendAuthSession(); void HandleSendAuthSession();
void HandleAuthSession(WorldPacket& recvPacket); void HandleAuthSession(WorldPacket& recvPacket);
void HandleAuthSessionCallback(std::shared_ptr<AuthSession> authSession, PreparedQueryResult result); void HandleAuthSessionCallback(std::shared_ptr<ClientAuthSession> authSession, PreparedQueryResult result);
void LoadSessionPermissionsCallback(PreparedQueryResult result); void LoadSessionPermissionsCallback(PreparedQueryResult result);
void SendAuthResponseError(uint8 code); void SendAuthResponseError(uint8 code);
+4 -4
View File
@@ -25,13 +25,13 @@
class WorldSocketThread : public NetworkThread<WorldSocket> class WorldSocketThread : public NetworkThread<WorldSocket>
{ {
public: public:
void SocketAdded(std::shared_ptr<WorldSocket> sock) override void SocketAdded(std::shared_ptr<WorldSocket> const& sock) override
{ {
sock->SetSendBufferSize(sWorldSocketMgr.GetApplicationSendBufferSize()); sock->SetSendBufferSize(sWorldSocketMgr.GetApplicationSendBufferSize());
sScriptMgr->OnSocketOpen(sock); sScriptMgr->OnSocketOpen(sock);
} }
void SocketRemoved(std::shared_ptr<WorldSocket> sock) override void SocketRemoved(std::shared_ptr<WorldSocket> const& sock) override
{ {
sScriptMgr->OnSocketClose(sock); sScriptMgr->OnSocketClose(sock);
} }
@@ -81,7 +81,7 @@ void WorldSocketMgr::StopNetwork()
sScriptMgr->OnNetworkStop(); sScriptMgr->OnNetworkStop();
} }
void WorldSocketMgr::OnSocketOpen(tcp::socket&& sock, uint32 threadIndex) void WorldSocketMgr::OnSocketOpen(IoContextTcpSocket&& sock, uint32 threadIndex)
{ {
// set some options here // set some options here
if (_socketSystemSendBufferSize >= 0) if (_socketSystemSendBufferSize >= 0)
@@ -109,7 +109,7 @@ void WorldSocketMgr::OnSocketOpen(tcp::socket&& sock, uint32 threadIndex)
} }
} }
BaseSocketMgr::OnSocketOpen(std::forward<tcp::socket>(sock), threadIndex); BaseSocketMgr::OnSocketOpen(std::move(sock), threadIndex);
} }
NetworkThread<WorldSocket>* WorldSocketMgr::CreateThreads() const NetworkThread<WorldSocket>* WorldSocketMgr::CreateThreads() const
+3 -3
View File
@@ -41,7 +41,7 @@ public:
/// Stops all network threads, It will wait for all running threads . /// Stops all network threads, It will wait for all running threads .
void StopNetwork() override; void StopNetwork() override;
void OnSocketOpen(tcp::socket&& sock, uint32 threadIndex) override; void OnSocketOpen(IoContextTcpSocket&& sock, uint32 threadIndex) override;
std::size_t GetApplicationSendBufferSize() const { return _socketApplicationSendBufferSize; } std::size_t GetApplicationSendBufferSize() const { return _socketApplicationSendBufferSize; }
@@ -50,9 +50,9 @@ protected:
NetworkThread<WorldSocket>* CreateThreads() const override; NetworkThread<WorldSocket>* CreateThreads() const override;
static void OnSocketAccept(tcp::socket&& sock, uint32 threadIndex) static void OnSocketAccept(IoContextTcpSocket&& sock, uint32 threadIndex)
{ {
Instance().OnSocketOpen(std::forward<tcp::socket>(sock), threadIndex); Instance().OnSocketOpen(std::move(sock), threadIndex);
} }
private: private:
@@ -24,6 +24,7 @@
#include "Chat.h" #include "Chat.h"
#include "CommandScript.h" #include "CommandScript.h"
#include "GroupMgr.h"
#include "Language.h" #include "Language.h"
#include "Player.h" #include "Player.h"
#include "SpellAuras.h" #include "SpellAuras.h"
@@ -211,6 +212,16 @@ public:
CharacterDatabase.Execute(stmt); CharacterDatabase.Execute(stmt);
} }
if (isInstance)
{
if (ObjectGuid groupId = sCharacterCache->GetCharacterGroupGuidByGuid(guid))
if (Group* group = sGroupMgr->GetGroupByGUID(groupId.GetCounter()))
if (group->isLFGGroup())
Player::RemoveFromGroup(group, guid);
}
else if (target && target->GetMap()->IsBattleground())
target->LeaveBattleground();
handler->PSendSysMessage("{} of {} Deserter has been added to player {}.", secsToTimeString(duration), isInstance ? "Instance" : "Battleground", handler->playerLink(*playerName)); handler->PSendSysMessage("{} of {} Deserter has been added to player {}.", secsToTimeString(duration), isInstance ? "Instance" : "Battleground", handler->playerLink(*playerName));
return true; return true;
} }
@@ -215,7 +215,7 @@ struct boss_archimonde : public BossAI
scheduler.CancelAll(); scheduler.CancelAll();
me->SetReactState(REACT_PASSIVE); me->SetReactState(REACT_PASSIVE);
DoCastAOE(SPELL_PROTECTION_OF_ELUNE, true); DoCastAOE(SPELL_PROTECTION_OF_ELUNE, true);
Talk(SAY_ENRAGE); Talk(SAY_DEATH);
_enraged = true; _enraged = true;
me->GetMotionMaster()->Clear(false); me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MoveIdle(); me->GetMotionMaster()->MoveIdle();
@@ -172,7 +172,7 @@ struct boss_hadronox : public BossAI
SummonCrusherPack(SUMMON_GROUP_CRUSHER_3); SummonCrusherPack(SUMMON_GROUP_CRUSHER_3);
events.ScheduleEvent(EVENT_HADRONOX_MOVE1, 0s); events.ScheduleEvent(EVENT_HADRONOX_MOVE1, 0s);
events.ScheduleEvent(EVENT_HADRONOX_MOVE2, 45s); events.ScheduleEvent(EVENT_HADRONOX_MOVE2, 45s);
events.ScheduleEvent(EVENT_HADRONOX_MOVE3, 90s); events.ScheduleEvent(EVENT_HADRONOX_MOVE3, 70s);
} }
} }
@@ -1137,7 +1137,7 @@ public:
{ {
me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL); me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL);
Talk(SAY_LK_SUMMON_VALKYR); Talk(SAY_LK_SUMMON_VALKYR);
DoCastSelf(IsHeroic() ? SPELL_SUMMON_VALKYR_PERIODIC : SPELL_SUMMON_VALKYR); DoCastSelf(Is25ManRaid() ? SPELL_SUMMON_VALKYR_PERIODIC : SPELL_SUMMON_VALKYR);
events.ScheduleEvent(EVENT_SUMMON_VALKYR, 45s, EVENT_GROUP_ABILITIES); events.ScheduleEvent(EVENT_SUMMON_VALKYR, 45s, EVENT_GROUP_ABILITIES);
// schedule a defile (or reschedule it) if next defile event // schedule a defile (or reschedule it) if next defile event
@@ -44,10 +44,7 @@ enum Spells
enum Misc enum Misc
{ {
ACHIEV_TIMED_START_EVENT = 9891, ACHIEV_TIMED_START_EVENT = 9891
EVENT_SPAWN_CRYPT_GUARDS_1 = 0,
EVENT_BERSERK = 1,
EVENT_SPAWN_CRYPT_GUARDS_EXTRA = 2,
}; };
Position const cryptguardPositions[] = { Position const cryptguardPositions[] = {
@@ -121,9 +118,10 @@ struct boss_anubrekhan : public BossAI
SummonCryptGuards(); SummonCryptGuards();
if (!Is25ManRaid()) if (!Is25ManRaid())
{ {
ScheduleUniqueTimedEvent(17500ms, [&] { me->m_Events.AddEventAtOffset([this]()
{
me->SummonCreature(NPC_CRYPT_GUARD, cryptguardPositions[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000); me->SummonCreature(NPC_CRYPT_GUARD, cryptguardPositions[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
}, EVENT_SPAWN_CRYPT_GUARDS_1); }, 17500ms);
} }
ScheduleTimedEvent(15s, [&] { ScheduleTimedEvent(15s, [&] {
@@ -255,7 +255,8 @@ class spell_gluth_decimate : public SpellScript
Unit::DealDamage(GetCaster(), cTarget, damage); Unit::DealDamage(GetCaster(), cTarget, damage);
return; return;
} }
GetCaster()->CastCustomSpell(SPELL_DECIMATE_DAMAGE, SPELLVALUE_BASE_POINT0, damage, unitTarget);
GetCaster()->CastSpell(unitTarget, SPELL_DECIMATE_DAMAGE);
} }
} }
@@ -265,8 +266,38 @@ class spell_gluth_decimate : public SpellScript
} }
}; };
// 28375 - Decimate
class spell_gluth_decimate_damage : public SpellScript
{
PrepareSpellScript(spell_gluth_decimate_damage)
void RecalculateDamage()
{
Unit* target = GetHitUnit();
if (!target)
return;
int32 targetHealth = int32(target->GetHealth());
int32 fivePctHealth = int32(target->CountPctFromMaxHealth(5));
// Damage needed to leave the target at exactly 5%
int32 damage = targetHealth - fivePctHealth;
if (damage <= 0)
damage = 0;
SetHitDamage(damage);
}
void Register() override
{
OnHit += SpellHitFn(spell_gluth_decimate_damage::RecalculateDamage);
}
};
void AddSC_boss_gluth() void AddSC_boss_gluth()
{ {
new boss_gluth(); new boss_gluth();
RegisterSpellScript(spell_gluth_decimate); RegisterSpellScript(spell_gluth_decimate);
RegisterSpellScript(spell_gluth_decimate_damage);
} }
@@ -18,6 +18,7 @@
#include "CreatureScript.h" #include "CreatureScript.h"
#include "InstanceMapScript.h" #include "InstanceMapScript.h"
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "TaskScheduler.h"
#include "nexus.h" #include "nexus.h"
#include "Player.h" #include "Player.h"
#include "Group.h" #include "Group.h"
@@ -44,6 +45,8 @@ public:
{ {
instance_nexus_InstanceMapScript(Map* map) : InstanceScript(map) {} instance_nexus_InstanceMapScript(Map* map) : InstanceScript(map) {}
GuidVector _frayerGUIDs;
void Initialize() override void Initialize() override
{ {
SetHeaders(DataHeader); SetHeaders(DataHeader);
@@ -80,6 +83,23 @@ public:
if (GetTeamIdInInstance() == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_COMMANDER_KOLURG); creature->UpdateEntry(NPC_COMMANDER_KOLURG);
break; break;
case NPC_CRYSTALLINE_FRAYER:
_frayerGUIDs.push_back(creature->GetGUID());
break;
}
}
void KillAllFrayers()
{
for (ObjectGuid const& guid : _frayerGUIDs)
{
if (Creature* frayer = instance->GetCreature(guid))
{
frayer->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
frayer->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
frayer->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
Unit::Kill(frayer, frayer);
}
} }
} }
@@ -141,7 +161,13 @@ public:
if (!InstanceScript::SetBossState(id, state)) if (!InstanceScript::SetBossState(id, state))
return false; return false;
if (state != DONE || id > DATA_ORMOROK_EVENT) if (state != DONE)
return true;
if (id == DATA_ORMOROK_EVENT)
KillAllFrayers();
if (id > DATA_ORMOROK_EVENT)
return true; return true;
BossInfo const* bossInfo = GetBossInfo(id + DATA_TELESTRA_ORB); BossInfo const* bossInfo = GetBossInfo(id + DATA_TELESTRA_ORB);
@@ -156,9 +182,17 @@ enum eFrayer
{ {
SPELL_SUMMON_SEED_POD = 52796, SPELL_SUMMON_SEED_POD = 52796,
SPELL_SEED_POD = 48082, SPELL_SEED_POD = 48082,
SPELL_AURA_OF_REGENERATION = 52067, SPELL_AURA_OF_REGENERATION = 57056,
SPELL_CRYSTAL_BLOOM = 48058, SPELL_CRYSTAL_BLOOM = 48058,
SPELL_ENSNARE = 48053 SPELL_ENSNARE = 48053,
SAY_EMOTE = 0
};
enum FrayerGroups
{
GROUP_COMBAT = 1,
GROUP_SEED_POD = 2
}; };
struct npc_crystalline_frayer : public ScriptedAI struct npc_crystalline_frayer : public ScriptedAI
@@ -166,27 +200,44 @@ struct npc_crystalline_frayer : public ScriptedAI
npc_crystalline_frayer(Creature* creature) : ScriptedAI(creature) { } npc_crystalline_frayer(Creature* creature) : ScriptedAI(creature) { }
bool _allowDeath; bool _allowDeath;
uint32 restoreTimer; bool _inSeedPod;
uint32 abilityTimer1; TaskScheduler _scheduler;
uint32 abilityTimer2;
void Reset() override void Reset() override
{ {
restoreTimer = 0; _allowDeath = false;
abilityTimer1 = 0; _inSeedPod = false;
abilityTimer2 = 30000; _scheduler.CancelAll();
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->RemoveAllAuras();
me->SetObjectScale(1.0f);
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
me->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
me->SetRegeneratingHealth(true);
me->SetReactState(REACT_AGGRESSIVE);
me->GetMotionMaster()->MoveRandom(10.0f);
} }
void JustEngagedWith(Unit*) override void JustEngagedWith(Unit*) override
{ {
_allowDeath = me->GetInstanceScript()->GetBossState(DATA_ORMOROK_EVENT) == DONE; if (InstanceScript* instance = me->GetInstanceScript())
_allowDeath = instance->GetBossState(DATA_ORMOROK_EVENT) == DONE;
_scheduler.Schedule(5s, GROUP_COMBAT, [this](TaskContext context)
{
DoCastVictim(SPELL_ENSNARE);
context.Repeat(5s);
}).Schedule(0s, GROUP_COMBAT, [this](TaskContext context)
{
DoCastVictim(SPELL_CRYSTAL_BLOOM);
context.Repeat(30s);
});
} }
void EnterEvadeMode(EvadeReason why) override void EnterEvadeMode(EvadeReason why) override
{ {
if (me->isRegeneratingHealth()) if (!_inSeedPod)
ScriptedAI::EnterEvadeMode(why); ScriptedAI::EnterEvadeMode(why);
} }
@@ -196,57 +247,67 @@ struct npc_crystalline_frayer : public ScriptedAI
{ {
if (!_allowDeath) if (!_allowDeath)
{ {
me->RemoveAllAuras();
me->GetThreatMgr().ClearAllThreat();
me->CombatStop(true);
damage = 0; damage = 0;
EnterSeedPod();
me->SetReactState(REACT_PASSIVE);
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->SetRegeneratingHealth(false);
me->CastSpell(me, SPELL_SUMMON_SEED_POD, true);
me->CastSpell(me, SPELL_SEED_POD, true);
me->CastSpell(me, SPELL_AURA_OF_REGENERATION, false);
restoreTimer = 1;
} }
} }
} }
void EnterSeedPod()
{
_inSeedPod = true;
_scheduler.CancelGroup(GROUP_COMBAT);
me->AttackStop();
me->GetThreatMgr().ClearAllThreat();
me->CombatStop(true);
me->RemoveAllAuras();
me->SetReactState(REACT_PASSIVE);
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
me->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
me->SetRegeneratingHealth(false);
me->SetObjectScale(0.6f);
DoCastSelf(SPELL_SEED_POD, true);
DoCastSelf(SPELL_SUMMON_SEED_POD, true);
DoCastSelf(SPELL_AURA_OF_REGENERATION, true);
_scheduler.Schedule(90s, GROUP_SEED_POD, [this](TaskContext /*context*/)
{
LeaveSeedPod();
});
}
void LeaveSeedPod()
{
_inSeedPod = false;
Talk(SAY_EMOTE);
me->RemoveAurasDueToSpell(SPELL_SEED_POD);
me->RemoveAurasDueToSpell(SPELL_AURA_OF_REGENERATION);
me->SetObjectScale(1.0f);
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
me->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
me->SetRegeneratingHealth(true);
me->SetReactState(REACT_AGGRESSIVE);
me->GetMotionMaster()->MoveRandom(10.0f);
}
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
if (restoreTimer) _scheduler.Update(diff);
{
restoreTimer += diff; if (_inSeedPod)
if (restoreTimer >= 90 * IN_MILLISECONDS)
{
Talk(0);
me->SetRegeneratingHealth(true);
restoreTimer = 0;
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
}
return; return;
}
if (!UpdateVictim()) if (!UpdateVictim())
return; return;
abilityTimer1 += diff;
abilityTimer2 += diff;
if (abilityTimer1 >= 5000)
{
me->CastSpell(me->GetVictim(), SPELL_ENSNARE, false);
abilityTimer1 = 0;
}
if (abilityTimer2 >= 30000)
{
me->CastSpell(me->GetVictim(), SPELL_CRYSTAL_BLOOM, false);
abilityTimer2 = 0;
}
} }
}; };
@@ -50,6 +50,7 @@ enum Npcs
NPC_COMMANDER_STOUTBEARD = 26796, NPC_COMMANDER_STOUTBEARD = 26796,
NPC_COMMANDER_KOLURG = 26798, NPC_COMMANDER_KOLURG = 26798,
NPC_CRYSTALLINE_FRAYER = 26793,
GO_TELESTRA_SPHERE = 188526, GO_TELESTRA_SPHERE = 188526,
GO_ANOMALUS_SPHERE = 188527, GO_ANOMALUS_SPHERE = 188527,
@@ -276,6 +276,7 @@ public:
orb->RemoveAurasDueToSpell(SPELL_AWAKEN_SUBBOSS); orb->RemoveAurasDueToSpell(SPELL_AWAKEN_SUBBOSS);
me->RemoveAurasDueToSpell(SPELL_FREEZE); me->RemoveAurasDueToSpell(SPELL_FREEZE);
me->GetThreatMgr().ResetAllThreat();
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
me->SetControlled(false, UNIT_STATE_STUNNED); me->SetControlled(false, UNIT_STATE_STUNNED);
// SETINCOMBATWITHZONE // SETINCOMBATWITHZONE
@@ -610,150 +610,6 @@ private:
BetrayalState _state; BetrayalState _state;
}; };
/*####
## npc_drakuru_shackles
####*/
enum DrakuruShackles
{
NPC_RAGECLAW = 29686,
QUEST_TROLLS_IS_GONE_CRAZY = 12861,
SPELL_LEFT_CHAIN = 59951,
SPELL_RIGHT_CHAIN = 59952,
SPELL_UNLOCK_SHACKLE = 55083,
SPELL_FREE_RAGECLAW = 55223
};
class npc_drakuru_shackles : public CreatureScript
{
public:
npc_drakuru_shackles() : CreatureScript("npc_drakuru_shackles") { }
struct npc_drakuru_shacklesAI : public NullCreatureAI
{
npc_drakuru_shacklesAI(Creature* creature) : NullCreatureAI(creature)
{
_rageclawGUID.Clear();
timer = 0;
}
void Reset() override
{
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
}
void UpdateAI(uint32 diff) override
{
timer += diff;
if (timer >= 2000)
{
timer = 0;
if (_rageclawGUID)
return;
if (Creature* cr = me->FindNearestCreature(NPC_RAGECLAW, 10.0f))
{
_rageclawGUID = cr->GetGUID();
LockRageclaw(cr);
}
}
}
void LockRageclaw(Creature* rageclaw)
{
// pointer check not needed
me->SetFacingToObject(rageclaw);
rageclaw->SetFacingToObject(me);
DoCast(rageclaw, SPELL_LEFT_CHAIN, true);
DoCast(rageclaw, SPELL_RIGHT_CHAIN, true);
}
void UnlockRageclaw(Unit* /*who*/, Creature* rageclaw)
{
// pointer check not needed
DoCast(rageclaw, SPELL_FREE_RAGECLAW, true);
_rageclawGUID.Clear();
me->DespawnOrUnsummon(1ms);
}
void SpellHit(Unit* caster, SpellInfo const* spell) override
{
if (spell->Id == SPELL_UNLOCK_SHACKLE)
{
if (caster->ToPlayer()->GetQuestStatus(QUEST_TROLLS_IS_GONE_CRAZY) == QUEST_STATUS_INCOMPLETE)
{
if (Creature* rageclaw = ObjectAccessor::GetCreature(*me, _rageclawGUID))
{
UnlockRageclaw(caster, rageclaw);
caster->ToPlayer()->KilledMonster(rageclaw->GetCreatureTemplate(), _rageclawGUID);
me->DespawnOrUnsummon();
}
else
me->setDeathState(DeathState::JustDied);
}
}
}
private:
ObjectGuid _rageclawGUID;
uint32 timer;
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_drakuru_shacklesAI(creature);
}
};
/*####
## npc_captured_rageclaw
####*/
enum Rageclaw
{
SPELL_UNSHACKLED = 55085,
SPELL_KNEEL = 39656,
SAY_RAGECLAW = 0
};
class npc_captured_rageclaw : public CreatureScript
{
public:
npc_captured_rageclaw() : CreatureScript("npc_captured_rageclaw") { }
struct npc_captured_rageclawAI : public NullCreatureAI
{
npc_captured_rageclawAI(Creature* creature) : NullCreatureAI(creature) { }
void Reset() override
{
me->SetFaction(FACTION_FRIENDLY);
DoCast(me, SPELL_KNEEL, true); // Little Hack for kneel - Thanks Illy :P
}
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
{
if (spell->Id == SPELL_FREE_RAGECLAW)
{
me->RemoveAurasDueToSpell(SPELL_LEFT_CHAIN);
me->RemoveAurasDueToSpell(SPELL_RIGHT_CHAIN);
me->RemoveAurasDueToSpell(SPELL_KNEEL);
me->SetFaction(me->GetCreatureTemplate()->faction);
DoCast(me, SPELL_UNSHACKLED, true);
Talk(SAY_RAGECLAW);
me->GetMotionMaster()->MoveRandom(10);
me->DespawnOrUnsummon(10s);
}
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_captured_rageclawAI(creature);
}
};
/*#### /*####
## npc_released_offspring_harkoa ## npc_released_offspring_harkoa
####*/ ####*/
@@ -973,8 +829,6 @@ void AddSC_zuldrak()
new npc_finklestein(); new npc_finklestein();
new go_finklestein_cauldron(); new go_finklestein_cauldron();
RegisterCreatureAI(npc_overlord_drakuru_betrayal); RegisterCreatureAI(npc_overlord_drakuru_betrayal);
new npc_drakuru_shackles();
new npc_captured_rageclaw();
new npc_released_offspring_harkoa(); new npc_released_offspring_harkoa();
new npc_crusade_recruit(); new npc_crusade_recruit();
new go_scourge_enclosure(); new go_scourge_enclosure();
@@ -56,17 +56,20 @@ struct boss_talon_king_ikiss : public BossAI
void Reset() override void Reset() override
{ {
_Reset(); _Reset();
_spoken = false; me->SetReactState(REACT_AGGRESSIVE);
ScheduleHealthCheckEvent({ 80, 50, 25 }, [&] { ScheduleHealthCheckEvent({ 80, 50, 25 }, [&] {
me->InterruptNonMeleeSpells(false); me->InterruptNonMeleeSpells(false);
me->SetReactState(REACT_PASSIVE);
me->AttackStop();
DoCastAOE(SPELL_BLINK); DoCastAOE(SPELL_BLINK);
DoCastSelf(SPELL_ARCANE_BUBBLE, true); DoCastSelf(SPELL_ARCANE_BUBBLE, true);
Talk(EMOTE_ARCANE_EXP); Talk(EMOTE_ARCANE_EXP);
scheduler.Schedule(1s, [this](TaskContext /*context*/) scheduler.Schedule(1s, [this](TaskContext /*context*/)
{ {
DoCastAOE(SPELL_ARCANE_EXPLOSION); DoCastAOE(SPELL_ARCANE_EXPLOSION);
}).Schedule(6500ms, [this](TaskContext /*context*/) }).Schedule(7s, [this](TaskContext /*context*/)
{ {
me->SetReactState(REACT_AGGRESSIVE);
me->GetThreatMgr().ResetAllThreat(); me->GetThreatMgr().ResetAllThreat();
}); });
}); });
@@ -160,7 +163,7 @@ class spell_talon_king_ikiss_blink : public SpellScript
void HandleDummyHitTarget(SpellEffIndex effIndex) void HandleDummyHitTarget(SpellEffIndex effIndex)
{ {
PreventHitDefaultEffect(effIndex); PreventHitDefaultEffect(effIndex);
GetHitUnit()->CastSpell(GetCaster(), SPELL_BLINK_TELEPORT, true); GetCaster()->CastSpell(GetHitUnit(), SPELL_BLINK_TELEPORT, true);
} }
void Register() override void Register() override
@@ -90,7 +90,7 @@ struct boss_pathaleon_the_calculator : public BossAI
me->LoadEquipment(EQUIPMENT_FRENZY); me->LoadEquipment(EQUIPMENT_FRENZY);
}); });
scheduler.Schedule(20s, 25s, [this](TaskContext context) scheduler.Schedule(10s, 16s, [this](TaskContext context)
{ {
if (!_isEnraged) if (!_isEnraged)
{ {
@@ -113,7 +113,7 @@ 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(10s, 15s, [this](TaskContext context) }).Schedule(10s, 16s, [this](TaskContext context)
{ {
if (DoCastRandomTarget(SPELL_DOMINATION, 0, 50.0f, true, false, false) == SPELL_CAST_OK) if (DoCastRandomTarget(SPELL_DOMINATION, 0, 50.0f, true, false, false) == SPELL_CAST_OK)
{ {
+9 -8
View File
@@ -20,6 +20,7 @@
#include "IpAddress.h" #include "IpAddress.h"
#include "Log.h" #include "Log.h"
#include "Socket.h"
#include "Systemd.h" #include "Systemd.h"
#include <atomic> #include <atomic>
#include <boost/asio/ip/tcp.hpp> #include <boost/asio/ip/tcp.hpp>
@@ -32,7 +33,7 @@ constexpr auto ACORE_MAX_LISTEN_CONNECTIONS = boost::asio::socket_base::max_list
class AsyncAcceptor class AsyncAcceptor
{ {
public: public:
typedef void(*AcceptCallback)(tcp::socket&& newSocket, uint32 threadIndex); typedef void(*AcceptCallback)(IoContextTcpSocket&& newSocket, uint32 threadIndex);
AsyncAcceptor(Acore::Asio::IoContext& ioContext, std::string const& bindIp, uint16 port, bool supportSocketActivation = false) : AsyncAcceptor(Acore::Asio::IoContext& ioContext, std::string const& bindIp, uint16 port, bool supportSocketActivation = false) :
_acceptor(ioContext), _endpoint(Acore::Net::make_address(bindIp), port), _acceptor(ioContext), _endpoint(Acore::Net::make_address(bindIp), port),
@@ -56,7 +57,7 @@ public:
template<AcceptCallback acceptCallback> template<AcceptCallback acceptCallback>
void AsyncAcceptWithCallback() void AsyncAcceptWithCallback()
{ {
tcp::socket* socket; IoContextTcpSocket* socket;
uint32 threadIndex; uint32 threadIndex;
std::tie(socket, threadIndex) = _socketFactory(); std::tie(socket, threadIndex) = _socketFactory();
_acceptor.async_accept(*socket, [this, socket, threadIndex](boost::system::error_code error) _acceptor.async_accept(*socket, [this, socket, threadIndex](boost::system::error_code error)
@@ -129,16 +130,16 @@ public:
_acceptor.close(err); _acceptor.close(err);
} }
void SetSocketFactory(std::function<std::pair<tcp::socket*, uint32>()> func) { _socketFactory = func; } void SetSocketFactory(std::function<std::pair<IoContextTcpSocket*, uint32>()> func) { _socketFactory = std::move(func); }
private: private:
std::pair<tcp::socket*, uint32> DefaultSocketFactory() { return std::make_pair(&_socket, 0); } std::pair<IoContextTcpSocket*, uint32> DefaultSocketFactory() { return std::make_pair(&_socket, 0); }
tcp::acceptor _acceptor; boost::asio::basic_socket_acceptor<boost::asio::ip::tcp, IoContextTcpSocket::executor_type> _acceptor;
tcp::endpoint _endpoint; boost::asio::ip::tcp::endpoint _endpoint;
tcp::socket _socket; IoContextTcpSocket _socket;
std::atomic<bool> _closed; std::atomic<bool> _closed;
std::function<std::pair<tcp::socket*, uint32>()> _socketFactory; std::function<std::pair<IoContextTcpSocket*, uint32>()> _socketFactory;
bool _supportSocketActivation; bool _supportSocketActivation;
}; };
+4 -4
View File
@@ -91,13 +91,13 @@ public:
SocketAdded(sock); SocketAdded(sock);
} }
tcp::socket* GetSocketForAccept() { return &_acceptSocket; } IoContextTcpSocket* GetSocketForAccept() { return &_acceptSocket; }
void EnableProxyProtocol() { _proxyHeaderReadingEnabled = true; } void EnableProxyProtocol() { _proxyHeaderReadingEnabled = true; }
protected: protected:
virtual void SocketAdded(std::shared_ptr<SocketType> /*sock*/) { } virtual void SocketAdded(std::shared_ptr<SocketType> const& /*sock*/) { }
virtual void SocketRemoved(std::shared_ptr<SocketType> /*sock*/) { } virtual void SocketRemoved(std::shared_ptr<SocketType> const& /*sock*/) { }
void AddNewSockets() void AddNewSockets()
{ {
@@ -229,7 +229,7 @@ private:
SocketContainer _newSockets; SocketContainer _newSockets;
Acore::Asio::IoContext _ioContext; Acore::Asio::IoContext _ioContext;
tcp::socket _acceptSocket; IoContextTcpSocket _acceptSocket;
boost::asio::steady_timer _updateTimer; boost::asio::steady_timer _updateTimer;
bool _proxyHeaderReadingEnabled; bool _proxyHeaderReadingEnabled;
+48 -21
View File
@@ -21,9 +21,8 @@
#include "Log.h" #include "Log.h"
#include "MessageBuffer.h" #include "MessageBuffer.h"
#include <atomic> #include <atomic>
#include <boost/asio.hpp> #include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp> #include <boost/asio/ip/tcp.hpp>
#include <functional>
#include <memory> #include <memory>
#include <queue> #include <queue>
#include <type_traits> #include <type_traits>
@@ -35,6 +34,23 @@ using boost::asio::ip::tcp;
#define AC_SOCKET_USE_IOCP #define AC_SOCKET_USE_IOCP
#endif #endif
// Specialize boost socket for io_context executor instead of type-erased any_io_executor
// This avoids the type-erasure overhead of any_io_executor
using IoContextTcpSocket = boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::io_context::executor_type>;
enum class SocketReadCallbackResult
{
KeepReading,
Stop
};
enum class SocketState : uint8
{
Open = 0,
Closing = 1,
Closed = 2
};
enum ProxyHeaderReadingState { enum ProxyHeaderReadingState {
PROXY_HEADER_READING_STATE_NOT_STARTED, PROXY_HEADER_READING_STATE_NOT_STARTED,
PROXY_HEADER_READING_STATE_STARTED, PROXY_HEADER_READING_STATE_STARTED,
@@ -51,8 +67,8 @@ template<class T>
class Socket : public std::enable_shared_from_this<T> class Socket : public std::enable_shared_from_this<T>
{ {
public: public:
explicit Socket(tcp::socket&& socket) : _socket(std::move(socket)), _remoteAddress(_socket.remote_endpoint().address()), explicit Socket(IoContextTcpSocket&& socket) : _socket(std::move(socket)), _remoteAddress(_socket.remote_endpoint().address()),
_remotePort(_socket.remote_endpoint().port()), _readBuffer(), _closed(false), _closing(false), _isWritingAsync(false), _remotePort(_socket.remote_endpoint().port()), _readBuffer(), _state(SocketState::Open), _isWritingAsync(false),
_proxyHeaderReadingState(PROXY_HEADER_READING_STATE_NOT_STARTED) _proxyHeaderReadingState(PROXY_HEADER_READING_STATE_NOT_STARTED)
{ {
_readBuffer.Resize(READ_BLOCK_SIZE); _readBuffer.Resize(READ_BLOCK_SIZE);
@@ -60,7 +76,7 @@ public:
virtual ~Socket() virtual ~Socket()
{ {
_closed = true; _state = SocketState::Closed;
boost::system::error_code error; boost::system::error_code error;
_socket.close(error); _socket.close(error);
} }
@@ -69,13 +85,14 @@ public:
virtual bool Update() virtual bool Update()
{ {
if (_closed) SocketState state = _state.load();
if (state == SocketState::Closed)
{ {
return false; return false;
} }
#ifndef AC_SOCKET_USE_IOCP #ifndef AC_SOCKET_USE_IOCP
if (_isWritingAsync || (_writeQueue.empty() && !_closing)) if (_isWritingAsync || (_writeQueue.empty() && state != SocketState::Closing))
{ {
return true; return true;
} }
@@ -150,12 +167,18 @@ public:
[[nodiscard]] ProxyHeaderReadingState GetProxyHeaderReadingState() const { return _proxyHeaderReadingState; } [[nodiscard]] ProxyHeaderReadingState GetProxyHeaderReadingState() const { return _proxyHeaderReadingState; }
[[nodiscard]] bool IsOpen() const { return !_closed && !_closing; } [[nodiscard]] bool IsOpen() const { return _state.load() == SocketState::Open; }
void CloseSocket() void CloseSocket()
{ {
if (_closed.exchange(true)) SocketState expected = SocketState::Open;
return; if (!_state.compare_exchange_strong(expected, SocketState::Closed))
{
// If it was Closing, try to transition to Closed
expected = SocketState::Closing;
if (!_state.compare_exchange_strong(expected, SocketState::Closed))
return; // Already closed
}
boost::system::error_code shutdownError; boost::system::error_code shutdownError;
_socket.shutdown(boost::asio::socket_base::shutdown_send, shutdownError); _socket.shutdown(boost::asio::socket_base::shutdown_send, shutdownError);
@@ -168,13 +191,17 @@ public:
} }
/// Marks the socket for closing after write buffer becomes empty /// Marks the socket for closing after write buffer becomes empty
void DelayedCloseSocket() { _closing = true; } void DelayedCloseSocket()
{
SocketState expected = SocketState::Open;
_state.compare_exchange_strong(expected, SocketState::Closing);
}
MessageBuffer& GetReadBuffer() { return _readBuffer; } MessageBuffer& GetReadBuffer() { return _readBuffer; }
protected: protected:
virtual void OnClose() { } virtual void OnClose() { }
virtual void ReadHandler() = 0; virtual SocketReadCallbackResult ReadHandler() = 0;
bool AsyncProcessQueue() bool AsyncProcessQueue()
{ {
@@ -188,7 +215,7 @@ protected:
_socket.async_write_some(boost::asio::buffer(buffer.GetReadPointer(), buffer.GetActiveSize()), std::bind(&Socket<T>::WriteHandler, _socket.async_write_some(boost::asio::buffer(buffer.GetReadPointer(), buffer.GetActiveSize()), std::bind(&Socket<T>::WriteHandler,
this->shared_from_this(), std::placeholders::_1, std::placeholders::_2)); this->shared_from_this(), std::placeholders::_1, std::placeholders::_2));
#else #else
_socket.async_wait(tcp::socket::wait_write, [self = this->shared_from_this()](boost::system::error_code error) _socket.async_wait(boost::asio::socket_base::wait_write, [self = this->shared_from_this()](boost::system::error_code error)
{ {
self->WriteHandlerWrapper(error, 0); self->WriteHandlerWrapper(error, 0);
}); });
@@ -216,7 +243,8 @@ private:
} }
_readBuffer.WriteCompleted(transferredBytes); _readBuffer.WriteCompleted(transferredBytes);
ReadHandler(); if (ReadHandler() == SocketReadCallbackResult::KeepReading)
AsyncRead();
} }
// ProxyReadHeaderHandler reads Proxy Protocol v2 header (v1 is not supported). // ProxyReadHeaderHandler reads Proxy Protocol v2 header (v1 is not supported).
@@ -344,7 +372,7 @@ private:
if (!_writeQueue.empty()) if (!_writeQueue.empty())
AsyncProcessQueue(); AsyncProcessQueue();
else if (_closing) else if (_state.load() == SocketState::Closing)
CloseSocket(); CloseSocket();
} }
else else
@@ -380,7 +408,7 @@ private:
_writeQueue.pop(); _writeQueue.pop();
if (_closing && _writeQueue.empty()) if (_state.load() == SocketState::Closing && _writeQueue.empty())
{ {
CloseSocket(); CloseSocket();
} }
@@ -391,7 +419,7 @@ private:
{ {
_writeQueue.pop(); _writeQueue.pop();
if (_closing && _writeQueue.empty()) if (_state.load() == SocketState::Closing && _writeQueue.empty())
{ {
CloseSocket(); CloseSocket();
} }
@@ -406,7 +434,7 @@ private:
_writeQueue.pop(); _writeQueue.pop();
if (_closing && _writeQueue.empty()) if (_state.load() == SocketState::Closing && _writeQueue.empty())
{ {
CloseSocket(); CloseSocket();
} }
@@ -415,7 +443,7 @@ private:
} }
#endif #endif
tcp::socket _socket; IoContextTcpSocket _socket;
boost::asio::ip::address _remoteAddress; boost::asio::ip::address _remoteAddress;
uint16 _remotePort; uint16 _remotePort;
@@ -423,8 +451,7 @@ private:
MessageBuffer _readBuffer; MessageBuffer _readBuffer;
std::queue<MessageBuffer> _writeQueue; std::queue<MessageBuffer> _writeQueue;
std::atomic<bool> _closed; std::atomic<SocketState> _state;
std::atomic<bool> _closing;
bool _isWritingAsync; bool _isWritingAsync;
+2 -2
View File
@@ -91,7 +91,7 @@ public:
_threads[i].Wait(); _threads[i].Wait();
} }
virtual void OnSocketOpen(tcp::socket&& sock, uint32 threadIndex) virtual void OnSocketOpen(IoContextTcpSocket&& sock, uint32 threadIndex)
{ {
try try
{ {
@@ -117,7 +117,7 @@ public:
return min; return min;
} }
std::pair<tcp::socket*, uint32> GetSocketForAccept() std::pair<IoContextTcpSocket*, uint32> GetSocketForAccept()
{ {
uint32 threadIndex = SelectThreadWithMinConnections(); uint32 threadIndex = SelectThreadWithMinConnections();
return { _threads[threadIndex].GetSocketForAccept(), threadIndex }; return { _threads[threadIndex].GetSocketForAccept(), threadIndex };
+141
View File
@@ -0,0 +1,141 @@
#!/usr/bin/env python3
"""
Socket Stress Test for AzerothCore
Tests authserver and worldserver connection handling under heavy load.
Usage:
python3 socket_stress_heavy.py [duration_seconds] [auth_threads] [world_threads]
Defaults:
duration: 300 seconds (5 minutes)
auth_threads: 100
world_threads: 150
"""
import socket
import time
import threading
import sys
AUTH_PORT = 3724
WORLD_PORT = 8085
HOST = '127.0.0.1'
stats = {'auth_ok': 0, 'auth_fail': 0, 'world_ok': 0, 'world_fail': 0}
running = True
def stress_auth():
"""Flood authserver with login challenge packets."""
global stats
while running:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(1)
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
s.connect((HOST, AUTH_PORT))
# AUTH_LOGON_CHALLENGE packet
packet = bytes([
0x00, # cmd: AUTH_LOGON_CHALLENGE
0x00, # error
0x24, 0x00, # size (36)
0x57, 0x6F, 0x57, 0x00, # 'WoW\0'
0x03, 0x03, 0x05, # version 3.3.5
0x30, 0x30, # build 12340
0x78, 0x38, 0x36, 0x00, # 'x86\0'
0x6E, 0x69, 0x57, 0x00, # 'niW\0' (Win reversed)
0x53, 0x55, 0x6E, 0x65, # 'SUne' (enUS reversed)
0x3C, 0x00, 0x00, 0x00, # timezone
0x7F, 0x00, 0x00, 0x01, # IP 127.0.0.1
0x04, # account name length
0x54, 0x45, 0x53, 0x54 # 'TEST'
])
s.sendall(packet)
s.close()
stats['auth_ok'] += 1
except Exception:
stats['auth_fail'] += 1
def stress_world():
"""Flood worldserver with connection attempts."""
global stats
while running:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(1)
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
s.connect((HOST, WORLD_PORT))
# Wait for SMSG_AUTH_CHALLENGE
s.recv(64)
s.close()
stats['world_ok'] += 1
except Exception:
stats['world_fail'] += 1
def main():
global running
# Parse arguments
duration = int(sys.argv[1]) if len(sys.argv) > 1 else 300
auth_threads = int(sys.argv[2]) if len(sys.argv) > 2 else 100
world_threads = int(sys.argv[3]) if len(sys.argv) > 3 else 150
print("=" * 60)
print("SOCKET STRESS TEST")
print("=" * 60)
print(f"Duration: {duration} seconds")
print(f"Auth threads: {auth_threads} -> {HOST}:{AUTH_PORT}")
print(f"World threads: {world_threads} -> {HOST}:{WORLD_PORT}")
print("-" * 60)
threads = []
for _ in range(auth_threads):
t = threading.Thread(target=stress_auth, daemon=True)
t.start()
threads.append(t)
for _ in range(world_threads):
t = threading.Thread(target=stress_world, daemon=True)
t.start()
threads.append(t)
print(f"Started {len(threads)} threads")
print("-" * 60)
start = time.time()
try:
while time.time() - start < duration:
elapsed = int(time.time() - start)
total = stats['auth_ok'] + stats['world_ok']
rate = total / max(elapsed, 1)
print(f"\r[{elapsed:3d}s] Auth: {stats['auth_ok']:7d} ok {stats['auth_fail']:5d} fail | "
f"World: {stats['world_ok']:7d} ok {stats['world_fail']:5d} fail | "
f"Rate: {rate:,.0f}/s ", end='', flush=True)
time.sleep(1)
except KeyboardInterrupt:
print("\n\nInterrupted by user")
running = False
time.sleep(0.5)
total_ok = stats['auth_ok'] + stats['world_ok']
total_fail = stats['auth_fail'] + stats['world_fail']
elapsed = time.time() - start
print("\n" + "=" * 60)
print("RESULTS:")
print(f" Duration: {elapsed:.1f} seconds")
print(f" Auth: {stats['auth_ok']:,} ok, {stats['auth_fail']:,} failed")
print(f" World: {stats['world_ok']:,} ok, {stats['world_fail']:,} failed")
print(f" Total: {total_ok:,} ok, {total_fail:,} failed")
print(f" Rate: {total_ok / elapsed:,.0f} connections/sec average")
if total_fail > 0:
print(f" Failure: {total_fail / (total_ok + total_fail) * 100:.2f}%")
print("=" * 60)
if __name__ == '__main__':
main()