Merge branch 'master' into Playerbot
This commit is contained in:
@@ -122,12 +122,26 @@ EOF
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "Starting $BINFILE without GDB"
|
echo "Starting $BINFILE without GDB"
|
||||||
if [[ "$AC_LAUNCHED_BY_PM2" == "1" ]]; then
|
# Determine if PM2 is active
|
||||||
echo "Running under PM2"
|
is_pm2_active="0"
|
||||||
|
[ "$AC_LAUNCHED_BY_PM2" == "1" ] && is_pm2_active="1"
|
||||||
|
|
||||||
|
# Determine if interactive mode is enabled
|
||||||
|
is_interactive_enabled="1"
|
||||||
|
[ "$AC_DISABLE_INTERACTIVE" == "1" ] && is_interactive_enabled="0"
|
||||||
|
|
||||||
|
# use normal execution if we are running the binary under PM2
|
||||||
|
# or when interactive mode is enabled
|
||||||
|
if [[ "$is_pm2_active" == "1" || "$is_interactive_enabled" == "1" ]]; then
|
||||||
|
echo "Running AC"
|
||||||
"$EXECPATH" ${CONFIG_ABS:+-c "$CONFIG_ABS"}
|
"$EXECPATH" ${CONFIG_ABS:+-c "$CONFIG_ABS"}
|
||||||
else
|
else
|
||||||
|
# When AC_DISABLE_INTERACTIVE is set to 1 and we are not in PM2
|
||||||
|
# This means we are using systemd without interactive mode and no session managers
|
||||||
|
# in this case we need to run AC with unbuffer for line-buffered output
|
||||||
|
# NOTE unbuffer doesn't fully support interactive mode
|
||||||
if command -v unbuffer >/dev/null 2>&1; then
|
if command -v unbuffer >/dev/null 2>&1; then
|
||||||
export AC_DISABLE_INTERACTIVE=0
|
echo "Running AC with unbuffer for line-buffered output"
|
||||||
unbuffer "$EXECPATH" ${CONFIG_ABS:+-c "$CONFIG_ABS"}
|
unbuffer "$EXECPATH" ${CONFIG_ABS:+-c "$CONFIG_ABS"}
|
||||||
else
|
else
|
||||||
echo "⚠️ unbuffer not found, the output may not be line-buffered. Try installing expect."
|
echo "⚠️ unbuffer not found, the output may not be line-buffered. Try installing expect."
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- DB update 2025_07_11_00 -> 2025_07_29_00
|
||||||
|
--
|
||||||
|
ALTER TABLE `mail_server_template_conditions`
|
||||||
|
CHANGE COLUMN `conditionType` `conditionType` ENUM('Level','PlayTime','Quest','Achievement','Reputation','Faction','Race','Class','AccountFlags') NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `templateID`;
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- DB update 2025_07_25_00 -> 2025_07_26_00
|
||||||
|
UPDATE `page_text_locale` SET `Text`='<HTML>\r\n<BODY>\r\n<BR/>\r\n<P>О, великий вождь!<br /><br />да озарит Свет каждый ваш шаг, и да пребудет он вечно в вашем сердце. Я молю вас о пощаде для этого павшего рыцаря, и смиренно прошу выслушать меня до конца.<br /><br />Податель сего письма некогда $Gбыл:была; героем Орды. Хотя отныне чело $Gего:ее; отмечено печатью смерти и обликом Плети, душой $Gон остался верен:она осталась верна; нашему делу.\r\n</P>\r\n</BODY>\r\n</HTML>' WHERE `ID` = 3539 AND `locale`='ruRU';
|
||||||
|
UPDATE `page_text_locale` SET `Text`='<HTML>\r\n<BODY>\r\n<BR/>\r\n<P>$N $Gбыл избран:была избрана; мной в качестве представителя нового союза, сражающегося против Короля-лича. Этот орден носит имя Рыцарей Черного Клинка. Да, ваше величество, вы не ошибаетесь: рыцари смерти объединились против своего бывшего повелителя. Их возглавляет сын лорда Александроса Могрейна – сам Испепелитель, и жаждут они того же, что и все мы: положить конец Плети.<br /><br />Я не смею просить вас принять $N и всех Рыцарей Черного Клинка в Орду, но надеюсь, что вы проявите к ним снисхождение.\r\n</P>\r\n</BODY>\r\n</HTML>' WHERE `ID` = 3540 AND `locale`='ruRU';
|
||||||
|
UPDATE `page_text_locale` SET `Text`='<HTML>\r\n<BODY>\r\n<BR/>\r\n<P>Помните, вождь, что все мы служим кровью и честью во имя великой цели.<br /><br />С глубочайшим уважением,<br /><br />Верховный лорд Тирион Фордринг<br />P.S. Передайте Эйтриггу мои пожелания долгого здравия и скажите ему, что мне не помешает такой союзник в Нордсколе – разумеется, если вы не будете возражать.\r\n</P>\r\n</BODY>\r\n</HTML>' WHERE `ID`= 3541 AND `locale`='ruRU';
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
-- DB update 2025_07_26_00 -> 2025_07_26_01
|
||||||
|
--
|
||||||
|
UPDATE `spell_dbc` SET `Effect_1` = 6, `EffectBasePoints_1`= 100, `ImplicitTargetA_1`= 1, `EffectAura_1` = 61, `CumulativeAura`= 3 WHERE `ID`= 57059;
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
-- DB update 2025_07_26_01 -> 2025_07_27_00
|
||||||
|
--
|
||||||
|
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 496101) AND (`source_type` = 9) 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
|
||||||
|
(496101, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 26, 1447, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Dashel Stonefist - On Script - Quest Credit \'The Missing Diplomat\'');
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
-- DB update 2025_07_27_00 -> 2025_07_27_01
|
||||||
|
--
|
||||||
|
DELETE FROM `acore_string` WHERE `entry` = 179;
|
||||||
|
INSERT INTO `acore_string` (`entry`, `content_default`) VALUES
|
||||||
|
(179, '| AccountFlags:');
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
-- DB update 2025_07_27_01 -> 2025_07_27_02
|
||||||
|
|
||||||
|
-- Haerthsinger Forresten
|
||||||
|
DELETE FROM `creature_text` WHERE (`CreatureID` = 30551);
|
||||||
|
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
|
||||||
|
(30551, 0, 0, 'This whole situation seems a bit paranoid, don\'t you think?', 12, 0, 100, 1, 0, 0, 31324, 0, ''),
|
||||||
|
(30551, 1, 0, 'Thank the Light for that.', 12, 0, 100, 1, 0, 0, 32573, 0, '');
|
||||||
|
|
||||||
|
-- Fras Siabi
|
||||||
|
DELETE FROM `creature_text` WHERE (`CreatureID` = 30552);
|
||||||
|
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
|
||||||
|
(30552, 0, 0, 'It\'s a strange order, you can\'t deny. Suspicious food? Under that definition, you should arrest Belfast!', 12, 0, 100, 1, 0, 0, 31326, 0, ''),
|
||||||
|
(30552, 1, 0, '%s nods.', 16, 0, 100, 0, 0, 0, 32046, 0, '');
|
||||||
|
|
||||||
|
-- Footman James
|
||||||
|
DELETE FROM `creature_text` WHERE (`CreatureID` = 30553);
|
||||||
|
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
|
||||||
|
(30553, 0, 0, 'Orders are orders. If the Prince says jump...', 12, 0, 100, 1, 0, 0, 31325, 0, ''),
|
||||||
|
(30553, 1, 0, 'Don\'t worry too much. By the time I went off duty, we hadn\'t found a scrap of befouled grain here.', 12, 0, 100, 1, 0, 0, 32572, 0, '');
|
||||||
|
|
||||||
|
-- Michael Belfast
|
||||||
|
DELETE FROM `creature_text` WHERE (`CreatureID` = 30571);
|
||||||
|
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
|
||||||
|
(30571, 0, 0, 'Hey! Stop rooting around in my cellar! Clear out!', 12, 0, 100, 5, 0, 0, 31322, 0, ''),
|
||||||
|
(30571, 0, 1, 'What were you doing in my cellar? There\'s a food scare going on, and the last thing I need is strangers rummaging around in my goods! Shoo!', 12, 0, 100, 5, 0, 0, 31323, 0, ''),
|
||||||
|
(30571, 1, 0, 'I HEARD THAT! No more ale for you! Not a drop!', 12, 0, 100, 25, 0, 0, 31327, 0, '');
|
||||||
|
|
||||||
|
-- Mal Corricks
|
||||||
|
DELETE FROM `creature_text` WHERE (`CreatureID` = 31017);
|
||||||
|
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
|
||||||
|
(31017, 0, 0, 'Enough, Michael. Business is hurting enough with this scare as it is. We can use every copper.', 12, 0, 100, 274, 0, 0, 32560, 0, ''),
|
||||||
|
(31017, 1, 0, '%s grudgingly nods.', 16, 0, 100, 0, 0, 0, 32569, 0, ''),
|
||||||
|
(31017, 2, 0, 'I can\'t argue with that.', 12, 0, 100, 1, 0, 0, 32570, 0, '');
|
||||||
|
|
||||||
|
-- Gryan Stoutmantle
|
||||||
|
DELETE FROM `creature_text` WHERE (`CreatureID` = 30561);
|
||||||
|
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
|
||||||
|
(30561, 0, 0, 'The soldiers are doing important work. The safety of the people is more important, Mal, if you\'re interested in your customers living to spend another day.', 12, 0, 0, 1, 0, 0, 32571, 0, '');
|
||||||
|
|
||||||
|
-- Move old Waypoint into waypoint_data.
|
||||||
|
DELETE FROM `waypoints` WHERE `entry` IN (3057100);
|
||||||
|
DELETE FROM `waypoint_data` WHERE `id` IN (3057100);
|
||||||
|
INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES
|
||||||
|
("3057100", 1, 1549.5714, 575.55707, 100.05218, NULL, 10000, 0, 0, 100, 0),
|
||||||
|
("3057100", 2, 1550.5083, 579.5038, 99.76226, NULL, 10000, 0, 0, 100, 0),
|
||||||
|
("3057100", 3, 1553.4889, 578.15356, 99.76225, NULL, 10000, 0, 0, 100, 0);
|
||||||
|
|
||||||
|
-- Set New Waypoint (Michael Belfast)
|
||||||
|
DELETE FROM `waypoint_data` WHERE `id` IN (3057101);
|
||||||
|
INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES
|
||||||
|
("3057101", 1, 1554.98, 588.784, 99.7754, NULL, 0, 0, 0, 100, 0);
|
||||||
|
|
||||||
|
-- Set New SmartAI (Michael Belfast)
|
||||||
|
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 30571;
|
||||||
|
|
||||||
|
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 30571);
|
||||||
|
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
|
||||||
|
(30571, 0, 0, 0, 38, 0, 100, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Michael Belfast - On Data Set 0 1 - Say Line 0 (No Repeat)'),
|
||||||
|
(30571, 0, 1, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 232, 3057100, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Michael Belfast - On Respawn - Start Path 3057100'),
|
||||||
|
(30571, 0, 2, 3, 108, 0, 100, 0, 1, 3057100, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Michael Belfast - On Point 1 of Path 3057100 Reached - Set Emote State 0'),
|
||||||
|
(30571, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 66, 1, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4.5, 'Michael Belfast - On Point 1 of Path 3057100 Reached - Set Orientation 4.5'),
|
||||||
|
(30571, 0, 4, 5, 108, 0, 100, 0, 2, 3057100, 0, 0, 0, 0, 66, 1, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 3, 'Michael Belfast - On Point 2 of Path 3057100 Reached - Set Orientation 3'),
|
||||||
|
(30571, 0, 5, 0, 61, 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, 'Michael Belfast - On Point 2 of Path 3057100 Reached - Set Flag Standstate Kneel'),
|
||||||
|
(30571, 0, 6, 7, 108, 0, 100, 0, 3, 3057100, 0, 0, 0, 0, 91, 8, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Michael Belfast - On Point 3 of Path 3057100 Reached - Remove FlagStandstate Kneel'),
|
||||||
|
(30571, 0, 7, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 17, 69, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Michael Belfast - On Point 3 of Path 3057100 Reached - Set Emote State 69'),
|
||||||
|
(30571, 0, 8, 0, 52, 0, 100, 0, 0, 0, 0, 0, 0, 0, 80, 3057100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Michael Belfast - On Text 0 Over - Run Script'),
|
||||||
|
(30571, 0, 9, 10, 38, 0, 100, 0, 0, 2, 0, 0, 0, 0, 91, 8, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Michael Belfast - On Data Set 0 2 - Remove FlagStandstate Kneel'),
|
||||||
|
(30571, 0, 10, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 232, 3057101, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Michael Belfast - On Data Set 0 2 - Start Path 3057101'),
|
||||||
|
(30571, 0, 12, 0, 38, 0, 100, 0, 0, 3, 0, 0, 0, 0, 232, 3057100, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Michael Belfast - On Data Set 0 3 - Start Path 3057100');
|
||||||
|
|
||||||
|
-- Set New Timed Action List and Remove the old ones (Michael Belfast - Conversation).
|
||||||
|
DELETE FROM `smart_scripts` WHERE (`source_type` = 9) AND (`entryorguid` IN (3057100, 3057101, 3057102));
|
||||||
|
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
|
||||||
|
(3057100, 9, 0, 0, 0, 0, 100, 0, 14000, 14000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10, 1970878, 30551, 0, 0, 0, 0, 0, 0, 'Michael Belfast - Actionlist - Say Line 0'),
|
||||||
|
(3057100, 9, 1, 0, 0, 0, 100, 0, 6000, 6000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10, 1970880, 30553, 0, 0, 0, 0, 0, 0, 'Michael Belfast - Actionlist - Say Line 0'),
|
||||||
|
(3057100, 9, 2, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10, 1970879, 30552, 0, 0, 0, 0, 0, 0, 'Michael Belfast - Actionlist - Say Line 0'),
|
||||||
|
(3057100, 9, 3, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 0, 0, 45, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Michael Belfast - Actionlist - Set Data 0 2'),
|
||||||
|
(3057100, 9, 4, 0, 0, 0, 100, 0, 6000, 6000, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Michael Belfast - Actionlist - Say Line 1'),
|
||||||
|
(3057100, 9, 5, 0, 0, 0, 100, 0, 4000, 4000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10, 1970865, 31017, 0, 0, 0, 0, 0, 0, 'Michael Belfast - Actionlist - Say Line 0'),
|
||||||
|
(3057100, 9, 6, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10, 1970898, 30561, 0, 0, 0, 0, 0, 0, 'Michael Belfast - Actionlist - Say Line 0'),
|
||||||
|
(3057100, 9, 7, 0, 0, 0, 100, 0, 12000, 12000, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 10, 1970865, 31017, 0, 0, 0, 0, 0, 0, 'Michael Belfast - Actionlist - Say Line 1'),
|
||||||
|
(3057100, 9, 8, 0, 0, 0, 100, 0, 3000, 3000, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 10, 1970865, 31017, 0, 0, 0, 0, 0, 0, 'Michael Belfast - Actionlist - Say Line 2'),
|
||||||
|
(3057100, 9, 9, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 45, 0, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Michael Belfast - Actionlist - Set Data 0 3'),
|
||||||
|
(3057100, 9, 10, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 10, 1970880, 30553, 0, 0, 0, 0, 0, 0, 'Michael Belfast - Actionlist - Say Line 1'),
|
||||||
|
(3057100, 9, 11, 0, 0, 0, 100, 0, 6000, 6000, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 10, 1970878, 30551, 0, 0, 0, 0, 0, 0, 'Michael Belfast - Actionlist - Say Line 1'),
|
||||||
|
(3057100, 9, 12, 0, 0, 0, 100, 0, 4000, 4000, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 10, 1970879, 30552, 0, 0, 0, 0, 0, 0, 'Michael Belfast - Actionlist - Say Line 1');
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
-- DB update 2025_07_27_02 -> 2025_07_29_00
|
||||||
|
--
|
||||||
|
DELETE FROM `creature_template_addon` WHERE `entry` IN (31461, 31462);
|
||||||
|
INSERT INTO `creature_template_addon` (`entry`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) VALUES
|
||||||
|
(31461, 0, 0, 0, 0, 0, 0, '31690 56740'),
|
||||||
|
(31462, 0, 0, 0, 0, 0, 0, '31690 56741');
|
||||||
|
|
||||||
|
UPDATE `creature_template` SET `unit_flags` = `unit_flags` &~2&~33554432, `flags_extra` = `flags_extra` &~128, `ScriptName` = '' WHERE `entry` IN (30435, 30391, 31461, 31462);
|
||||||
|
|
||||||
|
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 30435;
|
||||||
|
|
||||||
|
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 30435);
|
||||||
|
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
|
||||||
|
(30435, 0, 0, 0, 60, 0, 100, 1, 1000, 1000, 0, 0, 0, 0, 11, 57059, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Poisonous Mushroom - On Update - Cast \'Serverside - Grow\' (No Repeat)'),
|
||||||
|
(30435, 0, 1, 0, 26, 0, 100, 1, 0, 3, 0, 0, 1, 0, 223, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Poisonous Mushroom - In Combat LoS - Do Action ID 1 (No Repeat)'),
|
||||||
|
(30435, 0, 2, 3, 2, 0, 100, 0, 0, 5, 0, 0, 0, 0, 11, 31691, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Poisonous Mushroom - Between 0-5% Health - Cast \'Serverside - Shrink\''),
|
||||||
|
(30435, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 4000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Poisonous Mushroom - Between 0-5% Health - Despawn In 4000 ms'),
|
||||||
|
(30435, 0, 4, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Poisonous Mushroom - On Respawn - Set Reactstate Passive'),
|
||||||
|
(30435, 0, 5, 0, 32, 0, 100, 1, 1, 150, 0, 0, 0, 0, 223, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Poisonous Mushroom - On Damaged Between 1-150 - Do Action ID 1 (No Repeat)'),
|
||||||
|
(30435, 0, 6, 0, 72, 0, 100, 1, 1, 0, 0, 0, 0, 0, 80, 3043500, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Poisonous Mushroom - On Action 1 Done - Run Script (No Repeat)'),
|
||||||
|
(30435, 0, 7, 0, 101, 0, 100, 0, 1, 0, 4000, 4000, 4000, 0, 28, 56648, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Poisonous Mushroom - On 1 or More Players in Range - Remove Aura \'Potent Fungus\'');
|
||||||
|
|
||||||
|
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 3043500) AND (`source_type` = 9) 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
|
||||||
|
(3043500, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 57061, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Poisonous Mushroom - Actionlist - Cast \'Poison Cloud\''),
|
||||||
|
(3043500, 9, 1, 0, 0, 0, 100, 0, 1000, 1000, 0, 0, 0, 0, 11, 31691, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Poisonous Mushroom - Actionlist - Cast \'Serverside - Shrink\''),
|
||||||
|
(3043500, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 3000, 3000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Poisonous Mushroom - Actionlist - Despawn In 3000 ms');
|
||||||
|
|
||||||
|
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 30391;
|
||||||
|
|
||||||
|
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 30391);
|
||||||
|
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
|
||||||
|
(30391, 0, 0, 0, 60, 0, 100, 0, 1000, 1000, 0, 0, 0, 0, 11, 57059, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Healthy Mushroom - On Update - Cast \'Serverside - Grow\''),
|
||||||
|
(30391, 0, 1, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Healthy Mushroom - On Respawn - Set Reactstate Passive'),
|
||||||
|
(30391, 0, 2, 3, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 56648, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Healthy Mushroom - On Just Died - Cast \'Potent Fungus\''),
|
||||||
|
(30391, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 31691, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Healthy Mushroom - On Just Died - Cast \'Serverside - Shrink\'');
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- DB update 2025_07_29_00 -> 2025_07_29_01
|
||||||
|
-- Moonglade Raiment 2 set
|
||||||
|
DELETE FROM `spell_script_names` WHERE `spell_id`=-774 AND `ScriptName`='spell_dru_rejuvenation_moonglade_2_set';
|
||||||
|
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES (-774, 'spell_dru_rejuvenation_moonglade_2_set');
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
-- DB update 2025_07_29_01 -> 2025_07_29_02
|
||||||
|
-- improved shadow bolt into spell crit debuff
|
||||||
|
DELETE FROM `spell_group` WHERE `id` = 1010 AND `spell_id` IN (17800);
|
||||||
|
INSERT INTO `spell_group` VALUES (1010, 17800, 0);
|
||||||
|
|
||||||
|
-- curse of weakness and spore cloud into low armor% debuff, remove curse of recklessness
|
||||||
|
-- combine low armor% and attack power debuff because of curse of weakness
|
||||||
|
-- add vindication and demoralizing screech
|
||||||
|
DELETE FROM `spell_group` WHERE `id` = 1004 AND `spell_id` IN (702, 50274, 16231, 99, 1160, 67, 24423);
|
||||||
|
INSERT INTO `spell_group` VALUES (1004, 702, 0), (1004, 50274, 0), (1004, 99, 0), (1004, 1160, 0), (1004, 67, 0), (1004, 24423, 0);
|
||||||
|
|
||||||
|
-- rename
|
||||||
|
UPDATE `spell_group_stack_rules` SET `description` = 'Group of minor Armor reducing, hit increase and AP reducing debuffs, effect exclusive' WHERE `group_id` = 1004;
|
||||||
|
|
||||||
|
-- remove old ap debuff group
|
||||||
|
DELETE FROM `spell_group` WHERE `id` = 1017;
|
||||||
|
DELETE FROM `spell_group_stack_rules` WHERE `group_id` = 1017;
|
||||||
|
|
||||||
|
-- stampede into bleed debuff
|
||||||
|
DELETE FROM `spell_group` WHERE `id` = 1008 AND `spell_id` IN (57386);
|
||||||
|
INSERT INTO `spell_group` VALUES (1008, 57386, 0);
|
||||||
|
|
||||||
|
-- poison spit, lava breath into spell haste debuff
|
||||||
|
DELETE FROM `spell_group` WHERE `id` = 1022 AND `spell_id` IN (35387, 58604);
|
||||||
|
INSERT INTO `spell_group` VALUES (1022, 35387, 0), (1022, 58604, 0);
|
||||||
|
|
||||||
|
-- master poisoner into crit taken debuff (untested)
|
||||||
|
DELETE FROM `spell_group` WHERE `id` = 1013 AND `spell_id` IN (45176);
|
||||||
|
INSERT INTO `spell_group` VALUES (1013, 45176, 0);
|
||||||
|
|
||||||
|
-- physical damage taken group with savage combat and blood frenzy
|
||||||
|
DELETE FROM `spell_group_stack_rules` WHERE `group_id` = 1024;
|
||||||
|
INSERT INTO `spell_group_stack_rules` VALUES (1024, 17, 'Group of physical damage taken increasing debuffs');
|
||||||
|
|
||||||
|
DELETE FROM `spell_group` WHERE `id` = 1024 AND `spell_id` IN (30069, 58684);
|
||||||
|
INSERT INTO `spell_group` VALUES (1024, 30069, 0), (1024, 58684, 0);
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
-- DB update 2025_07_29_02 -> 2025_07_29_03
|
||||||
|
--
|
||||||
|
DELETE FROM `command` WHERE `name` = "go gameobject";
|
||||||
|
INSERT INTO `command` (`name`, `security`, `help`) VALUES
|
||||||
|
("go gameobject", 1, "Syntax: .go gameobject $gameobject.guid\r\nTeleports you to the gameobject using `guid` value of `gameobject` table.");
|
||||||
|
|
||||||
|
UPDATE `command` SET `help` = "Syntax: .go creature $creature.guid \r\nTeleports you to the creature using `guid` value of `creature` table." WHERE `name` LIKE "go creature";
|
||||||
|
UPDATE `command` SET `help` = "Syntax: .go creature name $creature_template.name \r\nTeleports you to a creature using the `name` value of `creature_template` table. \r\nIn the case of multiple creature of the same `name` existing in the world, you will be teleported to the lowest `guid` creature.\r\nWhen running the command for names with spaces don't break the string, example: .go creature name Ruby Scalebane" WHERE `name` LIKE "go creature name";
|
||||||
|
UPDATE `command` SET `help` = "Syntax: .group revive $characterName \r\nRevives all group members of the given character or self if not provided." WHERE `name` LIKE "group revive";
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
-- DB update 2025_07_29_03 -> 2025_08_01_00
|
||||||
|
--
|
||||||
|
ALTER TABLE `item_template` DROP COLUMN `StatsCount`;
|
||||||
|
|
||||||
|
UPDATE `item_template` SET `fire_res` = `stat_value1`, `frost_res` = `stat_value2`, `shadow_res` = `stat_value3`, `arcane_res` = `stat_value4`, `nature_res` = `stat_value5`, `stat_type1` = 0, `stat_value1` = 0, `stat_type2` = 0, `stat_value2` = 0, `stat_type3` = 0, `stat_value3` = 0, `stat_type4` = 0, `stat_value4` = 0, `stat_type5` = 0, `stat_value5` = 0, `VerifiedBuild` = 0 WHERE `entry` = 5828;
|
||||||
|
UPDATE `item_template` SET `fire_res` = `stat_value3`, `nature_res` = `stat_value4`, `stat_type3` = 0, `stat_value3` = 0, `stat_type4` = 0, `stat_value4` = 0, `VerifiedBuild` = 0 WHERE `entry` = 17802;
|
||||||
|
UPDATE `item_template` SET `fire_res` = `stat_value3`, `stat_type3` = 0, `stat_value3` = 0, `VerifiedBuild` = 0 WHERE `entry` = 18881;
|
||||||
|
UPDATE `item_template` SET `ArmorDamageModifier` = `stat_value3`, `stat_type3` = 0, `stat_value3` = 0, `VerifiedBuild` = 0 WHERE `entry` = 19065;
|
||||||
|
UPDATE `item_template` SET `fire_res` = `stat_value3`, `stat_type3` = 0, `stat_value3` = 0, `VerifiedBuild` = 0 WHERE `entry` = 19158;
|
||||||
|
UPDATE `item_template` SET `ArmorDamageModifier` = `stat_value3`, `fire_res` = `stat_value4`, `frost_res` = `stat_value5`, `shadow_res` = `stat_value6`, `arcane_res` = `stat_value7`, `nature_res` = `stat_value8`, `stat_type3` = 0, `stat_value3` = 0, `stat_type4` = 0, `stat_value4` = 0, `stat_type5` = 0, `stat_value5` = 0, `stat_type6` = 0, `stat_value6` = 0, `stat_type7` = 0, `stat_value7` = 0, `stat_type8` = 0, `stat_value8` = 0, `VerifiedBuild` = 0 WHERE `entry` = 20142;
|
||||||
|
UPDATE `item_template` SET `ArmorDamageModifier` = `stat_value3`, `stat_type3` = 0, `stat_value3` = 0, `VerifiedBuild` = 0 WHERE `entry` = 20522;
|
||||||
|
UPDATE `item_template` SET `ArmorDamageModifier` = `stat_value3`, `stat_type3` = 0, `stat_value3` = 0, `shadow_res` = `stat_value4`, `stat_type4` = 0, `stat_value4` = 0, `VerifiedBuild` = 0 WHERE `entry` = 20524;
|
||||||
|
UPDATE `item_template` SET `nature_res` = `stat_value3`, `stat_type3` = 0, `stat_value3` = 0, `VerifiedBuild` = 0 WHERE `entry` = 21614;
|
||||||
|
UPDATE `item_template` SET `ArmorDamageModifier` = `stat_value2`, `stat_type2` = 0, `stat_value2` = 0, `VerifiedBuild` = 0 WHERE `entry` = 22230;
|
||||||
|
UPDATE `item_template` SET `ArmorDamageModifier` = `stat_value5`, `fire_res` = `stat_value6`, `shadow_res` = `stat_value7`,`stat_type5` = 0, `stat_value5` = 0, `stat_type6` = 0, `stat_value6` = 0, `stat_type7` = 0, `stat_value7` = 0, `VerifiedBuild` = 0 WHERE `entry` = 23362;
|
||||||
|
UPDATE `item_template` SET `nature_res` = `stat_value5`, `arcane_res` = `stat_value6`, `stat_type5` = 0, `stat_value5` = 0, `stat_type6` = 0, `stat_value6` = 0, `VerifiedBuild` = 0 WHERE `entry` = 23363;
|
||||||
|
UPDATE `item_template` SET `ArmorDamageModifier` = `stat_value5`, `stat_type5` = 0, `stat_value5` = 0, `VerifiedBuild` = 0 WHERE `entry` IN (32113, 32114, 32115, 32116, 32117, 32118, 32119, 32121, 32122, 32123, 32128, 32129, 32130, 32131, 32132);
|
||||||
|
UPDATE `item_template` SET `ArmorDamageModifier` = `stat_value1`, `stat_type1` = 0, `stat_value1` = 0, `VerifiedBuild` = 0 WHERE `entry` = 34187;
|
||||||
|
UPDATE `item_template` SET `fire_res` = `stat_value5`, `stat_type5` = 0, `stat_value5` = 0, `VerifiedBuild` = 0 WHERE `entry` = 40762;
|
||||||
|
UPDATE `item_template` SET `ArmorDamageModifier` = `stat_value1`, `stat_type1` = 0, `stat_value1` = 0, `VerifiedBuild` = 0 WHERE `entry` = 45860;
|
||||||
|
UPDATE `item_template` SET `ArmorDamageModifier` = `stat_value2`, `stat_type2` = 0, `stat_value2` = 0, `VerifiedBuild` = 0 WHERE `entry` = 48945;
|
||||||
|
UPDATE `item_template` SET `fire_res` = `stat_value3`, `stat_type3` = 0, `stat_value3` = 0, `VerifiedBuild` = 0 WHERE `entry` = 49312;
|
||||||
|
UPDATE `item_template` SET `fire_res` = `stat_value5`, `stat_type5` = 0, `stat_value5` = 0, `VerifiedBuild` = 0 WHERE `entry` = 49314;
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
-- DB update 2025_08_01_00 -> 2025_08_01_01
|
||||||
|
-- fix quest 12616 'Chamber of Secrets'
|
||||||
|
UPDATE `gameobject_template` SET `AIName` = 'SmartGameObjectAI' WHERE `entry` = 190610;
|
||||||
|
|
||||||
|
DELETE FROM `smart_scripts` WHERE (`source_type` = 1 AND `entryorguid` = 190610);
|
||||||
|
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
|
||||||
|
(190610, 1, 0, 0, 70, 0, 100, 0, 2, 0, 0, 0, 0, 0, 56, 38629, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Orders from the Lich King - On Gameobject State Changed - Add Item \'Orders from the Lich King\' 1 Time');
|
||||||
|
|
||||||
|
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 22) AND (`SourceGroup` = 1) AND (`SourceEntry` = 190610) AND (`ConditionTypeOrReference` IN (2, 9)) AND (`ConditionValue1` IN (38629, 12616));
|
||||||
|
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
|
||||||
|
(22, 1, 190610, 1, 0, 9, 0, 12616, 0, 0, 0, 0, 0, '', '\'Orders from the Lich King\' requires quest \'Chamber of Secrets\''),
|
||||||
|
(22, 1, 190610, 1, 0, 2, 0, 38629, 1, 0, 1, 0, 0, '', 'Can\'t receive more than one \'Orders from the Lich King\'');
|
||||||
+15
-1
@@ -61,6 +61,7 @@ enum AccountTypes
|
|||||||
SEC_CONSOLE = 4 // must be always last in list, accounts must have less security level always also
|
SEC_CONSOLE = 4 // must be always last in list, accounts must have less security level always also
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define MAX_ACCOUNT_FLAG 32
|
||||||
enum AccountFlag
|
enum AccountFlag
|
||||||
{
|
{
|
||||||
ACCOUNT_FLAG_GM = 0x1, // Account is GM
|
ACCOUNT_FLAG_GM = 0x1, // Account is GM
|
||||||
@@ -96,9 +97,22 @@ enum AccountFlag
|
|||||||
// Below might be StarCraft II related
|
// Below might be StarCraft II related
|
||||||
ACCOUNT_FLAG_S2_REQUIRE_IGR = 0x40000000, // NYI UNK
|
ACCOUNT_FLAG_S2_REQUIRE_IGR = 0x40000000, // NYI UNK
|
||||||
ACCOUNT_FLAG_S2_TRIAL = 0x80000000, // NYI UNK
|
ACCOUNT_FLAG_S2_TRIAL = 0x80000000, // NYI UNK
|
||||||
ACCOUNT_FLAG_S2_RESTRICTED = 0xFFFFFFFF // NYI UNK
|
// ACCOUNT_FLAG_S2_RESTRICTED = 0xFFFFFFFF, // NYI UNK
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr uint32 ACCOUNT_FLAGS_ALL =
|
||||||
|
ACCOUNT_FLAG_GM | ACCOUNT_FLAG_NOKICK | ACCOUNT_FLAG_COLLECTOR |
|
||||||
|
ACCOUNT_FLAG_TRIAL | ACCOUNT_FLAG_CANCELLED | ACCOUNT_FLAG_IGR |
|
||||||
|
ACCOUNT_FLAG_WHOLESALER | ACCOUNT_FLAG_PRIVILEGED | ACCOUNT_FLAG_EU_FORBID_ELV |
|
||||||
|
ACCOUNT_FLAG_EU_FORBID_BILLING | ACCOUNT_FLAG_RESTRICTED | ACCOUNT_FLAG_REFERRAL |
|
||||||
|
ACCOUNT_FLAG_BLIZZARD | ACCOUNT_FLAG_RECURRING_BILLING | ACCOUNT_FLAG_NOELECTUP |
|
||||||
|
ACCOUNT_FLAG_KR_CERTIFICATE | ACCOUNT_FLAG_EXPANSION_COLLECTOR | ACCOUNT_FLAG_DISABLE_VOICE |
|
||||||
|
ACCOUNT_FLAG_DISABLE_VOICE_SPEAK | ACCOUNT_FLAG_REFERRAL_RESURRECT | ACCOUNT_FLAG_EU_FORBID_CC |
|
||||||
|
ACCOUNT_FLAG_OPENBETA_DELL | ACCOUNT_FLAG_PROPASS | ACCOUNT_FLAG_PROPASS_LOCK |
|
||||||
|
ACCOUNT_FLAG_PENDING_UPGRADE | ACCOUNT_FLAG_RETAIL_FROM_TRIAL | ACCOUNT_FLAG_EXPANSION2_COLLECTOR |
|
||||||
|
ACCOUNT_FLAG_OVERMIND_LINKED | ACCOUNT_FLAG_DEMOS | ACCOUNT_FLAG_DEATH_KNIGHT_OK |
|
||||||
|
ACCOUNT_FLAG_S2_REQUIRE_IGR | ACCOUNT_FLAG_S2_TRIAL;
|
||||||
|
|
||||||
enum LocaleConstant
|
enum LocaleConstant
|
||||||
{
|
{
|
||||||
LOCALE_enUS = 0,
|
LOCALE_enUS = 0,
|
||||||
|
|||||||
@@ -1767,6 +1767,16 @@ CleanCharacterDB = 0
|
|||||||
|
|
||||||
PersistentCharacterCleanFlags = 0
|
PersistentCharacterCleanFlags = 0
|
||||||
|
|
||||||
|
#
|
||||||
|
# ValidateSkillLearnedBySpells
|
||||||
|
# Description: If enabled, players will lose spells that are invalid for their race/class.
|
||||||
|
# Default: 1 - (Enabled, enforce valid spells)
|
||||||
|
# 0 - (Disabled, allow invalid spells)
|
||||||
|
# Disabling this and then having your character learn spells which require DBC edits can result in the character not being saved in the database
|
||||||
|
# Disable AT YOUR OWN RISK
|
||||||
|
|
||||||
|
ValidateSkillLearnedBySpells = 1
|
||||||
|
|
||||||
#
|
#
|
||||||
###################################################################################################
|
###################################################################################################
|
||||||
|
|
||||||
@@ -3503,6 +3513,14 @@ Wintergrasp.CrashRestartTimer = 10
|
|||||||
|
|
||||||
###################################################################################################
|
###################################################################################################
|
||||||
# BATTLEGROUND
|
# BATTLEGROUND
|
||||||
|
#
|
||||||
|
# Battleground.PrepTime
|
||||||
|
# Description: Time (in seconds) for battleground preparation phase. Strand of the Ancients will be
|
||||||
|
# the exception and will always use the default 120 seconds timer, due to its boat timing mechanic.
|
||||||
|
# Default: 120
|
||||||
|
|
||||||
|
Battleground.PrepTime = 120
|
||||||
|
|
||||||
#
|
#
|
||||||
# Battleground.CastDeserter
|
# Battleground.CastDeserter
|
||||||
# Description: Cast Deserter spell at players who leave battlegrounds in progress.
|
# Description: Cast Deserter spell at players who leave battlegrounds in progress.
|
||||||
@@ -3768,6 +3786,13 @@ Battleground.EyeOfTheStorm.CapturePoints = 1600
|
|||||||
|
|
||||||
###################################################################################################
|
###################################################################################################
|
||||||
# ARENA
|
# ARENA
|
||||||
|
#
|
||||||
|
# Arena.PrepTime
|
||||||
|
# Description: Time (in seconds) for arena preparation phase.
|
||||||
|
# Default: 60
|
||||||
|
|
||||||
|
Arena.PrepTime = 60
|
||||||
|
|
||||||
#
|
#
|
||||||
# Arena.MaxRatingDifference
|
# Arena.MaxRatingDifference
|
||||||
# Description: Maximum rating difference between two teams in rated matches.
|
# Description: Maximum rating difference between two teams in rated matches.
|
||||||
|
|||||||
@@ -617,6 +617,10 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
|||||||
"ON DUPLICATE KEY UPDATE state = VALUES(state)", CONNECTION_ASYNC);
|
"ON DUPLICATE KEY UPDATE state = VALUES(state)", CONNECTION_ASYNC);
|
||||||
PrepareStatement(CHAR_DELETE_INSTANCE_SAVED_DATA, "DELETE FROM instance_saved_go_state_data WHERE id = ?", CONNECTION_ASYNC);
|
PrepareStatement(CHAR_DELETE_INSTANCE_SAVED_DATA, "DELETE FROM instance_saved_go_state_data WHERE id = ?", CONNECTION_ASYNC);
|
||||||
PrepareStatement(CHAR_SANITIZE_INSTANCE_SAVED_DATA, "DELETE FROM instance_saved_go_state_data WHERE id NOT IN (SELECT instance.id FROM instance)", CONNECTION_ASYNC);
|
PrepareStatement(CHAR_SANITIZE_INSTANCE_SAVED_DATA, "DELETE FROM instance_saved_go_state_data WHERE id NOT IN (SELECT instance.id FROM instance)", CONNECTION_ASYNC);
|
||||||
|
|
||||||
|
// world_state
|
||||||
|
PrepareStatement(CHAR_SEL_WORLD_STATE, "SELECT Id, Data FROM world_state", CONNECTION_SYNCH);
|
||||||
|
PrepareStatement(CHAR_REP_WORLD_STATE, "REPLACE INTO world_state (Id, Data) VALUES(?, ?)", CONNECTION_ASYNC);
|
||||||
}
|
}
|
||||||
|
|
||||||
CharacterDatabaseConnection::CharacterDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo)
|
CharacterDatabaseConnection::CharacterDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo)
|
||||||
|
|||||||
@@ -529,6 +529,9 @@ enum CharacterDatabaseStatements : uint32
|
|||||||
CHAR_DELETE_INSTANCE_SAVED_DATA,
|
CHAR_DELETE_INSTANCE_SAVED_DATA,
|
||||||
CHAR_SANITIZE_INSTANCE_SAVED_DATA,
|
CHAR_SANITIZE_INSTANCE_SAVED_DATA,
|
||||||
|
|
||||||
|
CHAR_SEL_WORLD_STATE,
|
||||||
|
CHAR_REP_WORLD_STATE,
|
||||||
|
|
||||||
MAX_CHARACTERDATABASE_STATEMENTS
|
MAX_CHARACTERDATABASE_STATEMENTS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -103,8 +103,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
|
|||||||
PrepareStatement(LOGIN_SEL_CHECK_PASSWORD, "SELECT salt, verifier FROM account WHERE id = ?", CONNECTION_SYNCH);
|
PrepareStatement(LOGIN_SEL_CHECK_PASSWORD, "SELECT salt, verifier FROM account WHERE id = ?", CONNECTION_SYNCH);
|
||||||
PrepareStatement(LOGIN_SEL_CHECK_PASSWORD_BY_NAME, "SELECT salt, verifier FROM account WHERE username = ?", CONNECTION_SYNCH);
|
PrepareStatement(LOGIN_SEL_CHECK_PASSWORD_BY_NAME, "SELECT salt, verifier FROM account WHERE username = ?", CONNECTION_SYNCH);
|
||||||
PrepareStatement(LOGIN_SEL_ACCOUNT_FLAG, "SELECT Flags FROM account WHERE id = ?", CONNECTION_SYNCH);
|
PrepareStatement(LOGIN_SEL_ACCOUNT_FLAG, "SELECT Flags FROM account WHERE id = ?", CONNECTION_SYNCH);
|
||||||
PrepareStatement(LOGIN_UPD_ADD_ACCOUNT_FLAG, "UPDATE account SET Flags = Flags | ? WHERE id = ?", CONNECTION_ASYNC);
|
PrepareStatement(LOGIN_UPD_SET_ACCOUNT_FLAG, "UPDATE account SET Flags = ? WHERE id = ?", CONNECTION_ASYNC);
|
||||||
PrepareStatement(LOGIN_UPD_REMOVE_ACCOUNT_FLAG, "UPDATE account SET Flags = Flags &~ ? WHERE id = ?", CONNECTION_ASYNC);
|
|
||||||
PrepareStatement(LOGIN_SEL_PINFO, "SELECT a.username, aa.gmlevel, a.email, a.reg_mail, a.last_ip, DATE_FORMAT(a.last_login, '%Y-%m-%d %T'), a.mutetime, a.mutereason, a.muteby, a.failed_logins, a.locked, a.OS FROM account a LEFT JOIN account_access aa ON (a.id = aa.id AND (aa.RealmID = ? OR aa.RealmID = -1)) WHERE a.id = ?", CONNECTION_SYNCH);
|
PrepareStatement(LOGIN_SEL_PINFO, "SELECT a.username, aa.gmlevel, a.email, a.reg_mail, a.last_ip, DATE_FORMAT(a.last_login, '%Y-%m-%d %T'), a.mutetime, a.mutereason, a.muteby, a.failed_logins, a.locked, a.OS FROM account a LEFT JOIN account_access aa ON (a.id = aa.id AND (aa.RealmID = ? OR aa.RealmID = -1)) WHERE a.id = ?", CONNECTION_SYNCH);
|
||||||
PrepareStatement(LOGIN_SEL_PINFO_BANS, "SELECT unbandate, bandate = unbandate, bannedby, banreason FROM account_banned WHERE id = ? AND active ORDER BY bandate ASC LIMIT 1", CONNECTION_SYNCH);
|
PrepareStatement(LOGIN_SEL_PINFO_BANS, "SELECT unbandate, bandate = unbandate, bannedby, banreason FROM account_banned WHERE id = ? AND active ORDER BY bandate ASC LIMIT 1", CONNECTION_SYNCH);
|
||||||
PrepareStatement(LOGIN_SEL_GM_ACCOUNTS, "SELECT a.username, aa.gmlevel FROM account a, account_access aa WHERE a.id=aa.id AND aa.gmlevel >= ? AND (aa.realmid = -1 OR aa.realmid = ?)", CONNECTION_SYNCH);
|
PrepareStatement(LOGIN_SEL_GM_ACCOUNTS, "SELECT a.username, aa.gmlevel FROM account a, account_access aa WHERE a.id=aa.id AND aa.gmlevel >= ? AND (aa.realmid = -1 OR aa.realmid = ?)", CONNECTION_SYNCH);
|
||||||
|
|||||||
@@ -87,8 +87,7 @@ enum LoginDatabaseStatements : uint32
|
|||||||
LOGIN_SEL_CHECK_PASSWORD,
|
LOGIN_SEL_CHECK_PASSWORD,
|
||||||
LOGIN_SEL_CHECK_PASSWORD_BY_NAME,
|
LOGIN_SEL_CHECK_PASSWORD_BY_NAME,
|
||||||
LOGIN_SEL_ACCOUNT_FLAG,
|
LOGIN_SEL_ACCOUNT_FLAG,
|
||||||
LOGIN_UPD_ADD_ACCOUNT_FLAG,
|
LOGIN_UPD_SET_ACCOUNT_FLAG,
|
||||||
LOGIN_UPD_REMOVE_ACCOUNT_FLAG,
|
|
||||||
LOGIN_SEL_PINFO,
|
LOGIN_SEL_PINFO,
|
||||||
LOGIN_SEL_PINFO_BANS,
|
LOGIN_SEL_PINFO_BANS,
|
||||||
LOGIN_SEL_GM_ACCOUNTS,
|
LOGIN_SEL_GM_ACCOUNTS,
|
||||||
|
|||||||
@@ -299,39 +299,6 @@ namespace AccountMgr
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasAccountFlag(uint32 accountId, uint32 flag)
|
|
||||||
{
|
|
||||||
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_FLAG);
|
|
||||||
stmt->SetData(0, accountId);
|
|
||||||
if (PreparedQueryResult result = LoginDatabase.Query(stmt))
|
|
||||||
{
|
|
||||||
uint32 flags = (*result)[0].Get<uint32>();
|
|
||||||
return (flags & flag) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAccountFlag(uint32 accountId, uint32 flag, bool remove /*= false*/)
|
|
||||||
{
|
|
||||||
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(
|
|
||||||
remove ? LOGIN_UPD_REMOVE_ACCOUNT_FLAG : LOGIN_UPD_ADD_ACCOUNT_FLAG
|
|
||||||
);
|
|
||||||
stmt->SetData(0, flag);
|
|
||||||
stmt->SetData(1, accountId);
|
|
||||||
LoginDatabase.Execute(stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValidateAccountFlags(uint32 accountId, uint32 flags, uint32 security)
|
|
||||||
{
|
|
||||||
bool hasGMFlag = (flags & ACCOUNT_FLAG_GM) != 0;
|
|
||||||
|
|
||||||
if (IsGMAccount(security) && !hasGMFlag)
|
|
||||||
UpdateAccountFlag(accountId, ACCOUNT_FLAG_GM);
|
|
||||||
else if (hasGMFlag && !IsGMAccount(security))
|
|
||||||
UpdateAccountFlag(accountId, ACCOUNT_FLAG_GM, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 GetCharactersCount(uint32 accountId)
|
uint32 GetCharactersCount(uint32 accountId)
|
||||||
{
|
{
|
||||||
// check character count
|
// check character count
|
||||||
|
|||||||
@@ -56,10 +56,6 @@ namespace AccountMgr
|
|||||||
bool IsGMAccount(uint32 gmlevel);
|
bool IsGMAccount(uint32 gmlevel);
|
||||||
bool IsAdminAccount(uint32 gmlevel);
|
bool IsAdminAccount(uint32 gmlevel);
|
||||||
bool IsConsoleAccount(uint32 gmlevel);
|
bool IsConsoleAccount(uint32 gmlevel);
|
||||||
|
|
||||||
bool HasAccountFlag(uint32 accountId, uint32 flag);
|
|
||||||
void UpdateAccountFlag(uint32 accountId, uint32 flag, bool remove = false);
|
|
||||||
void ValidateAccountFlags(uint32 accountId, uint32 flags, uint32 security);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry* auction, CharacterDatabas
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
sAuctionMgr->RemoveAItem(auction->item_guid, true, &trans);
|
RemoveAItem(auction->item_guid, true, &trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AuctionHouseMgr::SendAuctionSalePendingMail(AuctionEntry* auction, CharacterDatabaseTransaction trans, bool sendMail)
|
void AuctionHouseMgr::SendAuctionSalePendingMail(AuctionEntry* auction, CharacterDatabaseTransaction trans, bool sendMail)
|
||||||
@@ -256,7 +256,7 @@ void AuctionHouseMgr::SendAuctionExpiredMail(AuctionEntry* auction, CharacterDat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
sAuctionMgr->RemoveAItem(auction->item_guid, true, &trans);
|
RemoveAItem(auction->item_guid, true, &trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
//this function sends mail to old bidder
|
//this function sends mail to old bidder
|
||||||
|
|||||||
@@ -195,6 +195,8 @@ Battleground::Battleground()
|
|||||||
|
|
||||||
m_HonorMode = BG_NORMAL;
|
m_HonorMode = BG_NORMAL;
|
||||||
|
|
||||||
|
m_SetupCompleted = false;
|
||||||
|
|
||||||
StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_2M;
|
StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_2M;
|
||||||
StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_1M;
|
StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_1M;
|
||||||
StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_30S;
|
StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_30S;
|
||||||
@@ -475,10 +477,8 @@ inline void Battleground::_ProcessJoin(uint32 diff)
|
|||||||
itr->second->ResetAllPowers();
|
itr->second->ResetAllPowers();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(m_Events & BG_STARTING_EVENT_1))
|
if (!m_SetupCompleted)
|
||||||
{
|
{
|
||||||
m_Events |= BG_STARTING_EVENT_1;
|
|
||||||
|
|
||||||
if (!FindBgMap())
|
if (!FindBgMap())
|
||||||
{
|
{
|
||||||
LOG_ERROR("bg.battleground", "Battleground::_ProcessJoin: map (map id: {}, instance id: {}) is not created!", m_MapId, m_InstanceID);
|
LOG_ERROR("bg.battleground", "Battleground::_ProcessJoin: map (map id: {}, instance id: {}) is not created!", m_MapId, m_InstanceID);
|
||||||
@@ -494,13 +494,52 @@ inline void Battleground::_ProcessJoin(uint32 diff)
|
|||||||
}
|
}
|
||||||
|
|
||||||
StartingEventCloseDoors();
|
StartingEventCloseDoors();
|
||||||
SetStartDelayTime(StartDelayTimes[BG_STARTING_EVENT_FIRST]);
|
|
||||||
|
|
||||||
// First start warning - 2 or 1 minute
|
// Get the configured prep time
|
||||||
|
uint32 configuredPrepTime;
|
||||||
|
|
||||||
|
// Special case for Strand of the Ancients - always use 120 seconds due to boat timing mechanics
|
||||||
|
if (GetBgTypeID() == BATTLEGROUND_SA)
|
||||||
|
configuredPrepTime = 120 * IN_MILLISECONDS;
|
||||||
|
else
|
||||||
|
configuredPrepTime = isArena() ?
|
||||||
|
sWorld->getIntConfig(CONFIG_ARENA_PREP_TIME) * IN_MILLISECONDS :
|
||||||
|
sWorld->getIntConfig(CONFIG_BATTLEGROUND_PREP_TIME) * IN_MILLISECONDS;
|
||||||
|
|
||||||
|
SetStartDelayTime(configuredPrepTime);
|
||||||
|
|
||||||
|
// Pre-mark events for announcements that should be skipped based on configured prep time
|
||||||
|
if (configuredPrepTime < StartDelayTimes[BG_STARTING_EVENT_FIRST])
|
||||||
|
{
|
||||||
|
// Skip first announcement (120s for BG, 60s for Arena)
|
||||||
|
m_Events |= BG_STARTING_EVENT_1;
|
||||||
|
|
||||||
|
if (configuredPrepTime < StartDelayTimes[BG_STARTING_EVENT_SECOND])
|
||||||
|
{
|
||||||
|
// Skip second announcement (60s for BG, 30s for Arena)
|
||||||
|
m_Events |= BG_STARTING_EVENT_2;
|
||||||
|
|
||||||
|
if (configuredPrepTime < StartDelayTimes[BG_STARTING_EVENT_THIRD])
|
||||||
|
{
|
||||||
|
// Skip third announcement (30s for BG, 15s for Arena)
|
||||||
|
m_Events |= BG_STARTING_EVENT_3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark setup as completed
|
||||||
|
m_SetupCompleted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// First announcement at 120s or 60s (Depending on BG or Arena and configured time)
|
||||||
|
if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_FIRST] && !(m_Events & BG_STARTING_EVENT_1))
|
||||||
|
{
|
||||||
|
m_Events |= BG_STARTING_EVENT_1;
|
||||||
|
|
||||||
if (StartMessageIds[BG_STARTING_EVENT_FIRST])
|
if (StartMessageIds[BG_STARTING_EVENT_FIRST])
|
||||||
SendBroadcastText(StartMessageIds[BG_STARTING_EVENT_FIRST], CHAT_MSG_BG_SYSTEM_NEUTRAL);
|
SendBroadcastText(StartMessageIds[BG_STARTING_EVENT_FIRST], CHAT_MSG_BG_SYSTEM_NEUTRAL);
|
||||||
}
|
}
|
||||||
// After 1 minute or 30 seconds, warning is signaled
|
// Second announcement at 60s or 30s
|
||||||
else if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_SECOND] && !(m_Events & BG_STARTING_EVENT_2))
|
else if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_SECOND] && !(m_Events & BG_STARTING_EVENT_2))
|
||||||
{
|
{
|
||||||
m_Events |= BG_STARTING_EVENT_2;
|
m_Events |= BG_STARTING_EVENT_2;
|
||||||
@@ -508,7 +547,7 @@ inline void Battleground::_ProcessJoin(uint32 diff)
|
|||||||
if (StartMessageIds[BG_STARTING_EVENT_SECOND])
|
if (StartMessageIds[BG_STARTING_EVENT_SECOND])
|
||||||
SendBroadcastText(StartMessageIds[BG_STARTING_EVENT_SECOND], CHAT_MSG_BG_SYSTEM_NEUTRAL);
|
SendBroadcastText(StartMessageIds[BG_STARTING_EVENT_SECOND], CHAT_MSG_BG_SYSTEM_NEUTRAL);
|
||||||
}
|
}
|
||||||
// After 30 or 15 seconds, warning is signaled
|
// Third announcement at 30s or 15s
|
||||||
else if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_THIRD] && !(m_Events & BG_STARTING_EVENT_3))
|
else if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_THIRD] && !(m_Events & BG_STARTING_EVENT_3))
|
||||||
{
|
{
|
||||||
m_Events |= BG_STARTING_EVENT_3;
|
m_Events |= BG_STARTING_EVENT_3;
|
||||||
@@ -543,11 +582,12 @@ inline void Battleground::_ProcessJoin(uint32 diff)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Delay expired (after 2 or 1 minute)
|
// Delay expired (after configured prep time)
|
||||||
else if (GetStartDelayTime() <= 0 && !(m_Events & BG_STARTING_EVENT_4))
|
else if (GetStartDelayTime() <= 0 && !(m_Events & BG_STARTING_EVENT_4))
|
||||||
{
|
{
|
||||||
m_Events |= BG_STARTING_EVENT_4;
|
m_Events |= BG_STARTING_EVENT_4;
|
||||||
|
|
||||||
|
// Start the battle
|
||||||
StartingEventOpenDoors();
|
StartingEventOpenDoors();
|
||||||
|
|
||||||
if (StartMessageIds[BG_STARTING_EVENT_FOURTH])
|
if (StartMessageIds[BG_STARTING_EVENT_FOURTH])
|
||||||
|
|||||||
@@ -615,6 +615,9 @@ protected:
|
|||||||
void _ProcessJoin(uint32 diff);
|
void _ProcessJoin(uint32 diff);
|
||||||
void _CheckSafePositions(uint32 diff);
|
void _CheckSafePositions(uint32 diff);
|
||||||
|
|
||||||
|
// Setup completion marker
|
||||||
|
bool m_SetupCompleted;
|
||||||
|
|
||||||
// Scorekeeping
|
// Scorekeeping
|
||||||
BattlegroundScoreMap PlayerScores; // Player scores
|
BattlegroundScoreMap PlayerScores; // Player scores
|
||||||
// must be implemented in BG subclass
|
// must be implemented in BG subclass
|
||||||
|
|||||||
@@ -296,7 +296,6 @@ Creature::Creature(bool isWorldObject): Unit(isWorldObject), MovableMapObject(),
|
|||||||
|
|
||||||
ResetLootMode(); // restore default loot mode
|
ResetLootMode(); // restore default loot mode
|
||||||
TriggerJustRespawned = false;
|
TriggerJustRespawned = false;
|
||||||
m_isTempWorldObject = false;
|
|
||||||
_focusSpell = nullptr;
|
_focusSpell = nullptr;
|
||||||
|
|
||||||
m_respawnedTime = time_t(0);
|
m_respawnedTime = time_t(0);
|
||||||
@@ -802,7 +801,7 @@ void Creature::Update(uint32 diff)
|
|||||||
// Periodically check if able to move, if not, extend leash timer
|
// Periodically check if able to move, if not, extend leash timer
|
||||||
if (diff >= m_extendLeashTime)
|
if (diff >= m_extendLeashTime)
|
||||||
{
|
{
|
||||||
if (!CanFreeMove())
|
if (HasUnitState(UNIT_STATE_LOST_CONTROL))
|
||||||
UpdateLeashExtensionTime();
|
UpdateLeashExtensionTime();
|
||||||
m_extendLeashTime = EXTEND_LEASH_CHECK_INTERVAL;
|
m_extendLeashTime = EXTEND_LEASH_CHECK_INTERVAL;
|
||||||
}
|
}
|
||||||
@@ -2685,14 +2684,13 @@ bool Creature::CanCreatureAttack(Unit const* victim, bool skipDistCheck) const
|
|||||||
if (skipDistCheck)
|
if (skipDistCheck)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
float dist = sWorld->getFloatConfig(CONFIG_CREATURE_LEASH_RADIUS);
|
if (Unit* unit = GetCharmerOrOwner())
|
||||||
|
|
||||||
if (GetCharmerOrOwner())
|
|
||||||
{
|
{
|
||||||
dist = std::min<float>(GetMap()->GetVisibilityRange() + GetObjectSize() * 2, 150.0f);
|
float visibilityDist = std::min<float>(GetMap()->GetVisibilityRange() + GetObjectSize() * 2, DEFAULT_VISIBILITY_DISTANCE);
|
||||||
return IsWithinDist(victim, dist);
|
return victim->IsWithinDist(unit, visibilityDist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float dist = sWorld->getFloatConfig(CONFIG_CREATURE_LEASH_RADIUS);
|
||||||
if (!dist)
|
if (!dist)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|||||||
@@ -376,8 +376,6 @@ public:
|
|||||||
|
|
||||||
float m_SightDistance, m_CombatDistance;
|
float m_SightDistance, m_CombatDistance;
|
||||||
|
|
||||||
bool m_isTempWorldObject; //true when possessed
|
|
||||||
|
|
||||||
// Handling caster facing during spellcast
|
// Handling caster facing during spellcast
|
||||||
void SetTarget(ObjectGuid guid = ObjectGuid::Empty) override;
|
void SetTarget(ObjectGuid guid = ObjectGuid::Empty) override;
|
||||||
void ClearTarget() { SetTarget(); };
|
void ClearTarget() { SetTarget(); };
|
||||||
|
|||||||
@@ -1072,25 +1072,6 @@ void WorldObject::Update(uint32 diff)
|
|||||||
sScriptMgr->OnWorldObjectUpdate(this, diff);
|
sScriptMgr->OnWorldObjectUpdate(this, diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldObject::SetWorldObject(bool on)
|
|
||||||
{
|
|
||||||
if (!IsInWorld())
|
|
||||||
return;
|
|
||||||
|
|
||||||
GetMap()->AddObjectToSwitchList(this, on);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WorldObject::IsWorldObject() const
|
|
||||||
{
|
|
||||||
if (m_isWorldObject)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (ToCreature() && ToCreature()->m_isTempWorldObject)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorldObject::setActive(bool on)
|
void WorldObject::setActive(bool on)
|
||||||
{
|
{
|
||||||
if (m_isActive == on)
|
if (m_isActive == on)
|
||||||
@@ -1944,8 +1925,8 @@ bool WorldObject::CanDetectInvisibilityOf(WorldObject const* obj) const
|
|||||||
bool isPermInvisibleCreature = false;
|
bool isPermInvisibleCreature = false;
|
||||||
if (Creature const* baseObj = ToCreature())
|
if (Creature const* baseObj = ToCreature())
|
||||||
{
|
{
|
||||||
auto auraEffects = baseObj->GetAuraEffectsByType(SPELL_AURA_MOD_INVISIBILITY);
|
Unit::AuraEffectList const& auraEffects = baseObj->GetAuraEffectsByType(SPELL_AURA_MOD_INVISIBILITY);
|
||||||
for (auto const effect : auraEffects)
|
for (AuraEffect* const effect : auraEffects)
|
||||||
{
|
{
|
||||||
if (SpellInfo const* spell = effect->GetSpellInfo())
|
if (SpellInfo const* spell = effect->GetSpellInfo())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -635,9 +635,7 @@ public:
|
|||||||
[[nodiscard]] bool IsFarVisible() const { return m_isFarVisible; }
|
[[nodiscard]] bool IsFarVisible() const { return m_isFarVisible; }
|
||||||
[[nodiscard]] bool IsVisibilityOverridden() const { return m_visibilityDistanceOverride.has_value(); }
|
[[nodiscard]] bool IsVisibilityOverridden() const { return m_visibilityDistanceOverride.has_value(); }
|
||||||
void SetVisibilityDistanceOverride(VisibilityDistanceType type);
|
void SetVisibilityDistanceOverride(VisibilityDistanceType type);
|
||||||
void SetWorldObject(bool apply);
|
[[nodiscard]] bool IsWorldObject() const { return m_isWorldObject; }
|
||||||
[[nodiscard]] bool IsPermanentWorldObject() const { return m_isWorldObject; }
|
|
||||||
[[nodiscard]] bool IsWorldObject() const;
|
|
||||||
|
|
||||||
[[nodiscard]] bool IsInWintergrasp() const
|
[[nodiscard]] bool IsInWintergrasp() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -48,6 +48,8 @@
|
|||||||
#define NOMINAL_MELEE_RANGE 5.0f
|
#define NOMINAL_MELEE_RANGE 5.0f
|
||||||
#define MELEE_RANGE (NOMINAL_MELEE_RANGE - MIN_MELEE_REACH * 2) //center to center for players
|
#define MELEE_RANGE (NOMINAL_MELEE_RANGE - MIN_MELEE_REACH * 2) //center to center for players
|
||||||
#define DEFAULT_COLLISION_HEIGHT 2.03128f // Most common value in dbc
|
#define DEFAULT_COLLISION_HEIGHT 2.03128f // Most common value in dbc
|
||||||
|
#define LEEWAY_MIN_MOVE_SPEED 4.97f // NYI
|
||||||
|
#define LEEWAY_BONUS_RANGE 2.66f
|
||||||
|
|
||||||
// used for creating values for respawn for example
|
// used for creating values for respawn for example
|
||||||
inline uint32 PAIR64_HIPART(uint64 x);
|
inline uint32 PAIR64_HIPART(uint64 x);
|
||||||
|
|||||||
@@ -318,6 +318,8 @@ Player::Player(WorldSession* session): Unit(true), m_mover(this)
|
|||||||
m_baseRatingValue[i] = 0;
|
m_baseRatingValue[i] = 0;
|
||||||
|
|
||||||
m_baseSpellPower = 0;
|
m_baseSpellPower = 0;
|
||||||
|
m_baseSpellDamage = 0;
|
||||||
|
m_baseSpellHealing = 0;
|
||||||
m_baseFeralAP = 0;
|
m_baseFeralAP = 0;
|
||||||
m_baseManaRegen = 0;
|
m_baseManaRegen = 0;
|
||||||
m_baseHealthRegen = 0;
|
m_baseHealthRegen = 0;
|
||||||
@@ -3103,6 +3105,9 @@ bool Player::addSpell(uint32 spellId, uint8 addSpecMask, bool updateActive, bool
|
|||||||
|
|
||||||
bool Player::CheckSkillLearnedBySpell(uint32 spellId)
|
bool Player::CheckSkillLearnedBySpell(uint32 spellId)
|
||||||
{
|
{
|
||||||
|
if (!sWorld->getBoolConfig(CONFIG_VALIDATE_SKILL_LEARNED_BY_SPELLS))
|
||||||
|
return true;
|
||||||
|
|
||||||
SkillLineAbilityMapBounds skill_bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spellId);
|
SkillLineAbilityMapBounds skill_bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spellId);
|
||||||
uint32 errorSkill = 0;
|
uint32 errorSkill = 0;
|
||||||
for (SkillLineAbilityMap::const_iterator sla = skill_bounds.first; sla != skill_bounds.second; ++sla)
|
for (SkillLineAbilityMap::const_iterator sla = skill_bounds.first; sla != skill_bounds.second; ++sla)
|
||||||
@@ -6844,7 +6849,10 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
|
|||||||
break;
|
break;
|
||||||
/// @deprecated item mods
|
/// @deprecated item mods
|
||||||
case ITEM_MOD_SPELL_HEALING_DONE:
|
case ITEM_MOD_SPELL_HEALING_DONE:
|
||||||
|
ApplySpellHealingBonus(int32(val), apply);
|
||||||
|
break;
|
||||||
case ITEM_MOD_SPELL_DAMAGE_DONE:
|
case ITEM_MOD_SPELL_DAMAGE_DONE:
|
||||||
|
ApplySpellDamageBonus(int32(val), apply);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1954,6 +1954,8 @@ public:
|
|||||||
void UpdateAttackPowerAndDamage(bool ranged = false) override;
|
void UpdateAttackPowerAndDamage(bool ranged = false) override;
|
||||||
void UpdateShieldBlockValue();
|
void UpdateShieldBlockValue();
|
||||||
void ApplySpellPowerBonus(int32 amount, bool apply);
|
void ApplySpellPowerBonus(int32 amount, bool apply);
|
||||||
|
void ApplySpellDamageBonus(int32 amount, bool apply);
|
||||||
|
void ApplySpellHealingBonus(int32 amount, bool apply);
|
||||||
void UpdateSpellDamageAndHealingBonus();
|
void UpdateSpellDamageAndHealingBonus();
|
||||||
void ApplyRatingMod(CombatRating cr, int32 value, bool apply);
|
void ApplyRatingMod(CombatRating cr, int32 value, bool apply);
|
||||||
void UpdateRating(CombatRating cr);
|
void UpdateRating(CombatRating cr);
|
||||||
@@ -1972,6 +1974,8 @@ public:
|
|||||||
[[nodiscard]] float GetRatingMultiplier(CombatRating cr) const;
|
[[nodiscard]] float GetRatingMultiplier(CombatRating cr) const;
|
||||||
[[nodiscard]] float GetRatingBonusValue(CombatRating cr) const;
|
[[nodiscard]] float GetRatingBonusValue(CombatRating cr) const;
|
||||||
uint32 GetBaseSpellPowerBonus() { return m_baseSpellPower; }
|
uint32 GetBaseSpellPowerBonus() { return m_baseSpellPower; }
|
||||||
|
uint32 GetBaseSpellDamageBonus() { return m_baseSpellDamage; }
|
||||||
|
uint32 GetBaseSpellHealingBonus() { return m_baseSpellHealing; }
|
||||||
[[nodiscard]] int32 GetSpellPenetrationItemMod() const { return m_spellPenetrationItemMod; }
|
[[nodiscard]] int32 GetSpellPenetrationItemMod() const { return m_spellPenetrationItemMod; }
|
||||||
|
|
||||||
[[nodiscard]] float GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const;
|
[[nodiscard]] float GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const;
|
||||||
@@ -2831,6 +2835,8 @@ protected:
|
|||||||
float m_auraBaseMod[BASEMOD_END][MOD_END];
|
float m_auraBaseMod[BASEMOD_END][MOD_END];
|
||||||
int32 m_baseRatingValue[MAX_COMBAT_RATING];
|
int32 m_baseRatingValue[MAX_COMBAT_RATING];
|
||||||
uint32 m_baseSpellPower;
|
uint32 m_baseSpellPower;
|
||||||
|
uint32 m_baseSpellDamage;
|
||||||
|
uint32 m_baseSpellHealing;
|
||||||
uint32 m_baseFeralAP;
|
uint32 m_baseFeralAP;
|
||||||
uint32 m_baseManaRegen;
|
uint32 m_baseManaRegen;
|
||||||
uint32 m_baseHealthRegen;
|
uint32 m_baseHealthRegen;
|
||||||
|
|||||||
@@ -1272,7 +1272,7 @@ bool Player::SatisfyQuestDay(Quest const* qInfo, bool msg) const
|
|||||||
|
|
||||||
if (qInfo->IsDFQuest())
|
if (qInfo->IsDFQuest())
|
||||||
{
|
{
|
||||||
if (!m_DFQuests.empty())
|
if (m_DFQuests.find(qInfo->GetQuestId()) != m_DFQuests.end())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -4616,8 +4616,15 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
|
|||||||
HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(enchant_amount), apply);
|
HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(enchant_amount), apply);
|
||||||
LOG_DEBUG("entities.player.items", "+ {} BLOCK_VALUE", enchant_amount);
|
LOG_DEBUG("entities.player.items", "+ {} BLOCK_VALUE", enchant_amount);
|
||||||
break;
|
break;
|
||||||
case ITEM_MOD_SPELL_HEALING_DONE: // deprecated
|
/// @deprecated item mods
|
||||||
case ITEM_MOD_SPELL_DAMAGE_DONE: // deprecated
|
case ITEM_MOD_SPELL_HEALING_DONE:
|
||||||
|
ApplySpellHealingBonus(enchant_amount, apply);
|
||||||
|
LOG_DEBUG("entities.player.items", "+ {} SPELL_HEALING", enchant_amount);
|
||||||
|
break;
|
||||||
|
case ITEM_MOD_SPELL_DAMAGE_DONE:
|
||||||
|
ApplySpellDamageBonus(enchant_amount, apply);
|
||||||
|
LOG_DEBUG("entities.player.items", "+ {} SPELL_DAMAGE", enchant_amount);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,8 +181,8 @@ void Player::Update(uint32 p_time)
|
|||||||
m_swingErrorMsg = 1;
|
m_swingErrorMsg = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 120 degrees of radiant range
|
// 120 degrees of radiant range, if player is not in boundary radius
|
||||||
else if (!HasInArc(2 * M_PI / 3, victim))
|
else if (!IsWithinBoundaryRadius(victim) && !HasInArc(2 * float(M_PI) / 3, victim))
|
||||||
{
|
{
|
||||||
setAttackTimer(BASE_ATTACK, 100);
|
setAttackTimer(BASE_ATTACK, 100);
|
||||||
if (m_swingErrorMsg != 2) // send single time (client auto repeat)
|
if (m_swingErrorMsg != 2) // send single time (client auto repeat)
|
||||||
@@ -211,8 +211,8 @@ void Player::Update(uint32 p_time)
|
|||||||
{
|
{
|
||||||
if (!IsWithinMeleeRange(victim))
|
if (!IsWithinMeleeRange(victim))
|
||||||
setAttackTimer(OFF_ATTACK, 100);
|
setAttackTimer(OFF_ATTACK, 100);
|
||||||
else if (!HasInArc(2 * M_PI / 3, victim))
|
else if (!IsWithinBoundaryRadius(victim) && !HasInArc(2 * float(M_PI) / 3, victim))
|
||||||
setAttackTimer(OFF_ATTACK, 100);
|
setAttackTimer(BASE_ATTACK, 100);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// prevent base and off attack in same time, delay attack at
|
// prevent base and off attack in same time, delay attack at
|
||||||
|
|||||||
@@ -174,6 +174,23 @@ void Player::ApplySpellPowerBonus(int32 amount, bool apply)
|
|||||||
ApplyModInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + i, amount, apply);
|
ApplyModInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + i, amount, apply);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Player::ApplySpellDamageBonus(int32 amount, bool apply)
|
||||||
|
{
|
||||||
|
apply = _ModifyUInt32(apply, m_baseSpellDamage, amount);
|
||||||
|
|
||||||
|
// For speed just update for client
|
||||||
|
for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
|
||||||
|
ApplyModInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + i, amount, apply);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::ApplySpellHealingBonus(int32 amount, bool apply)
|
||||||
|
{
|
||||||
|
apply = _ModifyUInt32(apply, m_baseSpellHealing, amount);
|
||||||
|
|
||||||
|
// For speed just update for client
|
||||||
|
ApplyModUInt32Value(PLAYER_FIELD_MOD_HEALING_DONE_POS, amount, apply);
|
||||||
|
}
|
||||||
|
|
||||||
void Player::UpdateSpellDamageAndHealingBonus()
|
void Player::UpdateSpellDamageAndHealingBonus()
|
||||||
{
|
{
|
||||||
// Magic damage modifiers implemented in Unit::SpellDamageBonusDone
|
// Magic damage modifiers implemented in Unit::SpellDamageBonusDone
|
||||||
|
|||||||
@@ -674,6 +674,9 @@ bool Unit::IsWithinMeleeRange(Unit const* obj, float dist) const
|
|||||||
|
|
||||||
float maxdist = dist + GetMeleeRange(obj);
|
float maxdist = dist + GetMeleeRange(obj);
|
||||||
|
|
||||||
|
if ((IsPlayer() || obj->IsPlayer()) && HasLeewayMovement() && obj->HasLeewayMovement())
|
||||||
|
maxdist += LEEWAY_BONUS_RANGE;
|
||||||
|
|
||||||
return distsq < maxdist * maxdist;
|
return distsq < maxdist * maxdist;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -698,6 +701,16 @@ bool Unit::IsWithinRange(Unit const* obj, float dist) const
|
|||||||
return distsq <= dist * dist;
|
return distsq <= dist * dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Unit::IsWithinBoundaryRadius(const Unit* obj) const
|
||||||
|
{
|
||||||
|
if (!obj || !IsInMap(obj) || !InSamePhase(obj))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
float objBoundaryRadius = std::max(obj->GetBoundaryRadius(), MIN_MELEE_REACH);
|
||||||
|
|
||||||
|
return IsInDist(obj, objBoundaryRadius);
|
||||||
|
}
|
||||||
|
|
||||||
bool Unit::GetRandomContactPoint(Unit const* obj, float& x, float& y, float& z, bool force) const
|
bool Unit::GetRandomContactPoint(Unit const* obj, float& x, float& y, float& z, bool force) const
|
||||||
{
|
{
|
||||||
float combat_reach = GetCombatReach();
|
float combat_reach = GetCombatReach();
|
||||||
@@ -2256,7 +2269,7 @@ void Unit::CalcAbsorbResist(DamageInfo& dmgInfo, bool Splited)
|
|||||||
// We're going to call functions which can modify content of the list during iteration over it's elements
|
// We're going to call functions which can modify content of the list during iteration over it's elements
|
||||||
// Let's copy the list so we can prevent iterator invalidation
|
// Let's copy the list so we can prevent iterator invalidation
|
||||||
AuraEffectList vSchoolAbsorbCopy(victim->GetAuraEffectsByType(SPELL_AURA_SCHOOL_ABSORB));
|
AuraEffectList vSchoolAbsorbCopy(victim->GetAuraEffectsByType(SPELL_AURA_SCHOOL_ABSORB));
|
||||||
vSchoolAbsorbCopy.sort(Acore::AbsorbAuraOrderPred());
|
std::sort(vSchoolAbsorbCopy.begin(), vSchoolAbsorbCopy.end(), Acore::AbsorbAuraOrderPred());
|
||||||
|
|
||||||
// absorb without mana cost
|
// absorb without mana cost
|
||||||
for (AuraEffectList::iterator itr = vSchoolAbsorbCopy.begin(); (itr != vSchoolAbsorbCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
|
for (AuraEffectList::iterator itr = vSchoolAbsorbCopy.begin(); (itr != vSchoolAbsorbCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
|
||||||
@@ -2439,7 +2452,7 @@ void Unit::CalcAbsorbResist(DamageInfo& dmgInfo, bool Splited)
|
|||||||
// We're going to call functions which can modify content of the list during iteration over it's elements
|
// We're going to call functions which can modify content of the list during iteration over it's elements
|
||||||
// Let's copy the list so we can prevent iterator invalidation
|
// Let's copy the list so we can prevent iterator invalidation
|
||||||
AuraEffectList vSplitDamagePctCopy(victim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_PCT));
|
AuraEffectList vSplitDamagePctCopy(victim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_PCT));
|
||||||
for (AuraEffectList::iterator itr = vSplitDamagePctCopy.begin(), next; (itr != vSplitDamagePctCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
|
for (AuraEffectList::iterator itr = vSplitDamagePctCopy.begin(); (itr != vSplitDamagePctCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
|
||||||
{
|
{
|
||||||
// Check if aura was removed during iteration - we don't need to work on such auras
|
// Check if aura was removed during iteration - we don't need to work on such auras
|
||||||
AuraApplication const* aurApp = (*itr)->GetBase()->GetApplicationOfTarget(victim->GetGUID());
|
AuraApplication const* aurApp = (*itr)->GetBase()->GetApplicationOfTarget(victim->GetGUID());
|
||||||
@@ -2565,7 +2578,7 @@ void Unit::CalcHealAbsorb(HealInfo& healInfo)
|
|||||||
{
|
{
|
||||||
uint32 removedAuras = healInfo.GetTarget()->m_removedAurasCount;
|
uint32 removedAuras = healInfo.GetTarget()->m_removedAurasCount;
|
||||||
auraEff->GetBase()->Remove(AURA_REMOVE_BY_ENEMY_SPELL);
|
auraEff->GetBase()->Remove(AURA_REMOVE_BY_ENEMY_SPELL);
|
||||||
if (removedAuras + 1 < healInfo.GetTarget()->m_removedAurasCount)
|
if (healInfo.GetTarget()->m_removedAurasCount > removedAuras)
|
||||||
i = vHealAbsorb.begin();
|
i = vHealAbsorb.begin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4175,6 +4188,15 @@ void Unit::InterruptNonMeleeSpells(bool withDelayed, uint32 spell_id, bool withI
|
|||||||
InterruptSpell(CURRENT_CHANNELED_SPELL, true, true, bySelf);
|
InterruptSpell(CURRENT_CHANNELED_SPELL, true, true, bySelf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spell* Unit::GetFirstCurrentCastingSpell() const
|
||||||
|
{
|
||||||
|
for (uint32 i = 0; i < CURRENT_MAX_SPELL; i++)
|
||||||
|
if (m_currentSpells[i] && m_currentSpells[i]->GetCastTimeRemaining() > 0)
|
||||||
|
return m_currentSpells[i];
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
Spell* Unit::FindCurrentSpellBySpellId(uint32 spell_id) const
|
Spell* Unit::FindCurrentSpellBySpellId(uint32 spell_id) const
|
||||||
{
|
{
|
||||||
for (uint32 i = 0; i < CURRENT_MAX_SPELL; i++)
|
for (uint32 i = 0; i < CURRENT_MAX_SPELL; i++)
|
||||||
@@ -4732,7 +4754,7 @@ void Unit::_RegisterAuraEffect(AuraEffect* aurEff, bool apply)
|
|||||||
if (apply)
|
if (apply)
|
||||||
m_modAuras[aurEff->GetAuraType()].push_back(aurEff);
|
m_modAuras[aurEff->GetAuraType()].push_back(aurEff);
|
||||||
else
|
else
|
||||||
m_modAuras[aurEff->GetAuraType()].remove(aurEff);
|
m_modAuras[aurEff->GetAuraType()].erase(std::remove(m_modAuras[aurEff->GetAuraType()].begin(), m_modAuras[aurEff->GetAuraType()].end(), aurEff), m_modAuras[aurEff->GetAuraType()].end());
|
||||||
}
|
}
|
||||||
|
|
||||||
// All aura base removes should go threw this function!
|
// All aura base removes should go threw this function!
|
||||||
@@ -5158,7 +5180,7 @@ void Unit::RemoveAurasByType(AuraType auraType, ObjectGuid casterGUID, Aura* exc
|
|||||||
{
|
{
|
||||||
uint32 removedAuras = m_removedAurasCount;
|
uint32 removedAuras = m_removedAurasCount;
|
||||||
RemoveAura(aurApp);
|
RemoveAura(aurApp);
|
||||||
if (m_removedAurasCount > removedAuras + 1)
|
if (m_removedAurasCount > removedAuras)
|
||||||
iter = m_modAuras[auraType].begin();
|
iter = m_modAuras[auraType].begin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10419,8 +10441,29 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
|
|||||||
if (meleeAttack)
|
if (meleeAttack)
|
||||||
AddUnitState(UNIT_STATE_MELEE_ATTACKING);
|
AddUnitState(UNIT_STATE_MELEE_ATTACKING);
|
||||||
|
|
||||||
|
Unit* owner = GetCharmerOrOwner();
|
||||||
|
Creature* ownerCreature = owner ? owner->ToCreature() : nullptr;
|
||||||
|
Creature* controlledCreatureWithSameVictim = nullptr;
|
||||||
|
if (creature && !m_Controlled.empty())
|
||||||
|
{
|
||||||
|
for (ControlSet::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
|
||||||
|
{
|
||||||
|
if ((*itr)->ToCreature() && (*itr)->GetVictim() == victim)
|
||||||
|
{
|
||||||
|
controlledCreatureWithSameVictim = (*itr)->ToCreature();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Share leash timer with controlled unit
|
||||||
|
if (controlledCreatureWithSameVictim)
|
||||||
|
creature->SetLastLeashExtensionTimePtr(controlledCreatureWithSameVictim->GetLastLeashExtensionTimePtr());
|
||||||
|
// Share leash timer with owner
|
||||||
|
else if (creature && ownerCreature && ownerCreature->GetVictim() == victim)
|
||||||
|
creature->SetLastLeashExtensionTimePtr(ownerCreature->GetLastLeashExtensionTimePtr());
|
||||||
// Update leash timer when attacking creatures
|
// Update leash timer when attacking creatures
|
||||||
if (victim->IsCreature())
|
else if (victim->IsCreature())
|
||||||
victim->ToCreature()->UpdateLeashExtensionTime();
|
victim->ToCreature()->UpdateLeashExtensionTime();
|
||||||
|
|
||||||
// set position before any AI calls/assistance
|
// set position before any AI calls/assistance
|
||||||
@@ -11229,10 +11272,8 @@ Unit* Unit::GetNextRandomRaidMemberOrPet(float radius)
|
|||||||
void Unit::AddPlayerToVision(Player* player)
|
void Unit::AddPlayerToVision(Player* player)
|
||||||
{
|
{
|
||||||
if (m_sharedVision.empty())
|
if (m_sharedVision.empty())
|
||||||
{
|
|
||||||
setActive(true);
|
setActive(true);
|
||||||
SetWorldObject(true);
|
|
||||||
}
|
|
||||||
m_sharedVision.push_back(player);
|
m_sharedVision.push_back(player);
|
||||||
player->m_isInSharedVisionOf.insert(this);
|
player->m_isInSharedVisionOf.insert(this);
|
||||||
}
|
}
|
||||||
@@ -11242,11 +11283,10 @@ void Unit::RemovePlayerFromVision(Player* player)
|
|||||||
{
|
{
|
||||||
m_sharedVision.remove(player);
|
m_sharedVision.remove(player);
|
||||||
player->m_isInSharedVisionOf.erase(this);
|
player->m_isInSharedVisionOf.erase(this);
|
||||||
|
|
||||||
|
/// @todo: This isn't right, if a previously active object was set to active with e.g. Mind Vision this will make them no longer active
|
||||||
if (m_sharedVision.empty())
|
if (m_sharedVision.empty())
|
||||||
{
|
|
||||||
setActive(false);
|
setActive(false);
|
||||||
SetWorldObject(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::RemoveBindSightAuras()
|
void Unit::RemoveBindSightAuras()
|
||||||
@@ -12011,6 +12051,7 @@ int32 Unit::SpellBaseDamageBonusDone(SpellSchoolMask schoolMask)
|
|||||||
{
|
{
|
||||||
// Base value
|
// Base value
|
||||||
DoneAdvertisedBenefit += ToPlayer()->GetBaseSpellPowerBonus();
|
DoneAdvertisedBenefit += ToPlayer()->GetBaseSpellPowerBonus();
|
||||||
|
DoneAdvertisedBenefit += ToPlayer()->GetBaseSpellDamageBonus();
|
||||||
|
|
||||||
// Damage bonus from stats
|
// Damage bonus from stats
|
||||||
AuraEffectList const& mDamageDoneOfStatPercent = GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT);
|
AuraEffectList const& mDamageDoneOfStatPercent = GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT);
|
||||||
@@ -12773,6 +12814,7 @@ int32 Unit::SpellBaseHealingBonusDone(SpellSchoolMask schoolMask)
|
|||||||
{
|
{
|
||||||
// Base value
|
// Base value
|
||||||
AdvertisedBenefit += ToPlayer()->GetBaseSpellPowerBonus();
|
AdvertisedBenefit += ToPlayer()->GetBaseSpellPowerBonus();
|
||||||
|
AdvertisedBenefit += ToPlayer()->GetBaseSpellHealingBonus();
|
||||||
|
|
||||||
// Healing bonus from stats
|
// Healing bonus from stats
|
||||||
AuraEffectList const& mHealingDoneOfStatPercent = GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT);
|
AuraEffectList const& mHealingDoneOfStatPercent = GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT);
|
||||||
|
|||||||
@@ -633,7 +633,7 @@ public:
|
|||||||
typedef std::multimap<AuraStateType, AuraApplication*> AuraStateAurasMap;
|
typedef std::multimap<AuraStateType, AuraApplication*> AuraStateAurasMap;
|
||||||
typedef std::pair<AuraStateAurasMap::const_iterator, AuraStateAurasMap::const_iterator> AuraStateAurasMapBounds;
|
typedef std::pair<AuraStateAurasMap::const_iterator, AuraStateAurasMap::const_iterator> AuraStateAurasMapBounds;
|
||||||
|
|
||||||
typedef std::list<AuraEffect*> AuraEffectList;
|
typedef std::vector<AuraEffect*> AuraEffectList;
|
||||||
typedef std::list<Aura*> AuraList;
|
typedef std::list<Aura*> AuraList;
|
||||||
typedef std::list<AuraApplication*> AuraApplicationList;
|
typedef std::list<AuraApplication*> AuraApplicationList;
|
||||||
typedef std::list<DiminishingReturn> Diminishing;
|
typedef std::list<DiminishingReturn> Diminishing;
|
||||||
@@ -818,9 +818,11 @@ public:
|
|||||||
bool _IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) const;
|
bool _IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) const;
|
||||||
|
|
||||||
// Combat range
|
// Combat range
|
||||||
|
[[nodiscard]] float GetBoundaryRadius() const { return m_floatValues[UNIT_FIELD_BOUNDINGRADIUS]; }
|
||||||
[[nodiscard]] float GetCombatReach() const override { return m_floatValues[UNIT_FIELD_COMBATREACH]; }
|
[[nodiscard]] float GetCombatReach() const override { return m_floatValues[UNIT_FIELD_COMBATREACH]; }
|
||||||
[[nodiscard]] float GetMeleeReach() const { float reach = m_floatValues[UNIT_FIELD_COMBATREACH]; return reach > MIN_MELEE_REACH ? reach : MIN_MELEE_REACH; }
|
[[nodiscard]] float GetMeleeReach() const { float reach = m_floatValues[UNIT_FIELD_COMBATREACH]; return reach > MIN_MELEE_REACH ? reach : MIN_MELEE_REACH; }
|
||||||
[[nodiscard]] bool IsWithinRange(Unit const* obj, float dist) const;
|
[[nodiscard]] bool IsWithinRange(Unit const* obj, float dist) const;
|
||||||
|
bool IsWithinBoundaryRadius(const Unit* obj) const;
|
||||||
bool IsWithinCombatRange(Unit const* obj, float dist2compare) const;
|
bool IsWithinCombatRange(Unit const* obj, float dist2compare) const;
|
||||||
bool IsWithinMeleeRange(Unit const* obj, float dist = 0.f) const;
|
bool IsWithinMeleeRange(Unit const* obj, float dist = 0.f) const;
|
||||||
float GetMeleeRange(Unit const* target) const;
|
float GetMeleeRange(Unit const* target) const;
|
||||||
@@ -1492,6 +1494,7 @@ public:
|
|||||||
[[nodiscard]] Player* GetSpellModOwner() const;
|
[[nodiscard]] Player* GetSpellModOwner() const;
|
||||||
[[nodiscard]] Spell* GetCurrentSpell(CurrentSpellTypes spellType) const { return m_currentSpells[spellType]; }
|
[[nodiscard]] Spell* GetCurrentSpell(CurrentSpellTypes spellType) const { return m_currentSpells[spellType]; }
|
||||||
[[nodiscard]] Spell* GetCurrentSpell(uint32 spellType) const { return m_currentSpells[spellType]; }
|
[[nodiscard]] Spell* GetCurrentSpell(uint32 spellType) const { return m_currentSpells[spellType]; }
|
||||||
|
[[nodiscard]] Spell* GetFirstCurrentCastingSpell() const;
|
||||||
[[nodiscard]] Spell* FindCurrentSpellBySpellId(uint32 spell_id) const;
|
[[nodiscard]] Spell* FindCurrentSpellBySpellId(uint32 spell_id) const;
|
||||||
[[nodiscard]] int32 GetCurrentSpellCastTime(uint32 spell_id) const;
|
[[nodiscard]] int32 GetCurrentSpellCastTime(uint32 spell_id) const;
|
||||||
|
|
||||||
@@ -1636,6 +1639,12 @@ public:
|
|||||||
UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED) && !GetOwnerGUID();
|
UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED) && !GetOwnerGUID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool HasLeewayMovement() const
|
||||||
|
{
|
||||||
|
return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT | MOVEMENTFLAG_FALLING)
|
||||||
|
&& !IsWalking();
|
||||||
|
}
|
||||||
|
|
||||||
void KnockbackFrom(float x, float y, float speedXY, float speedZ);
|
void KnockbackFrom(float x, float y, float speedXY, float speedZ);
|
||||||
void JumpTo(float speedXY, float speedZ, bool forward = true);
|
void JumpTo(float speedXY, float speedZ, bool forward = true);
|
||||||
void JumpTo(WorldObject* obj, float speedZ);
|
void JumpTo(WorldObject* obj, float speedZ);
|
||||||
|
|||||||
@@ -1934,7 +1934,7 @@ void GameEventMgr::SetHolidayEventTime(GameEventData& event)
|
|||||||
|
|
||||||
uint32 GameEventMgr::GetHolidayEventId(uint32 holidayId) const
|
uint32 GameEventMgr::GetHolidayEventId(uint32 holidayId) const
|
||||||
{
|
{
|
||||||
auto const& events = sGameEventMgr->GetEventMap();
|
auto const& events = GetEventMap();
|
||||||
|
|
||||||
for (auto const& eventEntry : events)
|
for (auto const& eventEntry : events)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -871,7 +871,7 @@ void ObjectMgr::LoadCreatureTemplateAddons()
|
|||||||
|
|
||||||
uint32 entry = fields[0].Get<uint32>();
|
uint32 entry = fields[0].Get<uint32>();
|
||||||
|
|
||||||
if (!sObjectMgr->GetCreatureTemplate(entry))
|
if (!GetCreatureTemplate(entry))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Creature template (Entry: {}) does not exist but has a record in `creature_template_addon`", entry);
|
LOG_ERROR("sql.sql", "Creature template (Entry: {}) does not exist but has a record in `creature_template_addon`", entry);
|
||||||
continue;
|
continue;
|
||||||
@@ -1501,7 +1501,7 @@ void ObjectMgr::LoadEquipmentTemplates()
|
|||||||
|
|
||||||
uint32 entry = fields[0].Get<uint32>();
|
uint32 entry = fields[0].Get<uint32>();
|
||||||
|
|
||||||
if (!sObjectMgr->GetCreatureTemplate(entry))
|
if (!GetCreatureTemplate(entry))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Creature template (CreatureID: {}) does not exist but has a record in `creature_equip_template`", entry);
|
LOG_ERROR("sql.sql", "Creature template (CreatureID: {}) does not exist but has a record in `creature_equip_template`", entry);
|
||||||
continue;
|
continue;
|
||||||
@@ -2455,7 +2455,7 @@ void ObjectMgr::LoadCreatureSparring()
|
|||||||
ObjectGuid::LowType spawnId = fields[0].Get<uint32>();
|
ObjectGuid::LowType spawnId = fields[0].Get<uint32>();
|
||||||
float sparringHealthPct = fields[1].Get<float>();
|
float sparringHealthPct = fields[1].Get<float>();
|
||||||
|
|
||||||
if (!sObjectMgr->GetCreatureData(spawnId))
|
if (!GetCreatureData(spawnId))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Entry {} has a record in `creature_sparring` but doesn't exist in `creatures` table");
|
LOG_ERROR("sql.sql", "Entry {} has a record in `creature_sparring` but doesn't exist in `creatures` table");
|
||||||
continue;
|
continue;
|
||||||
@@ -2535,7 +2535,7 @@ ObjectGuid::LowType ObjectMgr::AddGOData(uint32 entry, uint32 mapId, float x, fl
|
|||||||
// We use spawn coords to spawn
|
// We use spawn coords to spawn
|
||||||
if (!map->Instanceable() && map->IsGridLoaded(x, y))
|
if (!map->Instanceable() && map->IsGridLoaded(x, y))
|
||||||
{
|
{
|
||||||
GameObject* go = sObjectMgr->IsGameObjectStaticTransport(data.id) ? new StaticTransport() : new GameObject();
|
GameObject* go = IsGameObjectStaticTransport(data.id) ? new StaticTransport() : new GameObject();
|
||||||
if (!go->LoadGameObjectFromDB(spawnId, map))
|
if (!go->LoadGameObjectFromDB(spawnId, map))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "AddGOData: cannot add gameobject entry {} to map", entry);
|
LOG_ERROR("sql.sql", "AddGOData: cannot add gameobject entry {} to map", entry);
|
||||||
@@ -2862,35 +2862,35 @@ void ObjectMgr::LoadItemTemplates()
|
|||||||
|
|
||||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12
|
// 0 1 2 3 4 5 6 7 8 9 10 11 12
|
||||||
QueryResult result = WorldDatabase.Query("SELECT entry, class, subclass, SoundOverrideSubclass, name, displayid, Quality, Flags, FlagsExtra, BuyCount, BuyPrice, SellPrice, InventoryType, "
|
QueryResult result = WorldDatabase.Query("SELECT entry, class, subclass, SoundOverrideSubclass, name, displayid, Quality, Flags, FlagsExtra, BuyCount, BuyPrice, SellPrice, InventoryType, "
|
||||||
// 13 14 15 16 17 18 19 20
|
// 13 14 15 16 17 18 19 20
|
||||||
"AllowableClass, AllowableRace, ItemLevel, RequiredLevel, RequiredSkill, RequiredSkillRank, requiredspell, requiredhonorrank, "
|
"AllowableClass, AllowableRace, ItemLevel, RequiredLevel, RequiredSkill, RequiredSkillRank, requiredspell, requiredhonorrank, "
|
||||||
// 21 22 23 24 25 26 27 28
|
// 21 22 23 24 25 26 27
|
||||||
"RequiredCityRank, RequiredReputationFaction, RequiredReputationRank, maxcount, stackable, ContainerSlots, StatsCount, stat_type1, "
|
"RequiredCityRank, RequiredReputationFaction, RequiredReputationRank, maxcount, stackable, ContainerSlots, stat_type1, "
|
||||||
// 29 30 31 32 33 34 35 36 37 38
|
// 28 29 30 31 32 33 34 35 36 37
|
||||||
"stat_value1, stat_type2, stat_value2, stat_type3, stat_value3, stat_type4, stat_value4, stat_type5, stat_value5, stat_type6, "
|
"stat_value1, stat_type2, stat_value2, stat_type3, stat_value3, stat_type4, stat_value4, stat_type5, stat_value5, stat_type6, "
|
||||||
// 39 40 41 42 43 44 45 46 47
|
// 38 39 40 41 42 43 44 45 46
|
||||||
"stat_value6, stat_type7, stat_value7, stat_type8, stat_value8, stat_type9, stat_value9, stat_type10, stat_value10, "
|
"stat_value6, stat_type7, stat_value7, stat_type8, stat_value8, stat_type9, stat_value9, stat_type10, stat_value10, "
|
||||||
// 48 49 50 51 52 53 54 55 56 57 58
|
// 47 48 49 50 51 52 53 54 55 56 57
|
||||||
"ScalingStatDistribution, ScalingStatValue, dmg_min1, dmg_max1, dmg_type1, dmg_min2, dmg_max2, dmg_type2, armor, holy_res, fire_res, "
|
"ScalingStatDistribution, ScalingStatValue, dmg_min1, dmg_max1, dmg_type1, dmg_min2, dmg_max2, dmg_type2, armor, holy_res, fire_res, "
|
||||||
// 59 60 61 62 63 64 65 66 67 68
|
// 58 59 60 61 62 63 64 65 66 67
|
||||||
"nature_res, frost_res, shadow_res, arcane_res, delay, ammo_type, RangedModRange, spellid_1, spelltrigger_1, spellcharges_1, "
|
"nature_res, frost_res, shadow_res, arcane_res, delay, ammo_type, RangedModRange, spellid_1, spelltrigger_1, spellcharges_1, "
|
||||||
// 69 70 71 72 73 74 75
|
// 68 69 70 71 72 73 74
|
||||||
"spellppmRate_1, spellcooldown_1, spellcategory_1, spellcategorycooldown_1, spellid_2, spelltrigger_2, spellcharges_2, "
|
"spellppmRate_1, spellcooldown_1, spellcategory_1, spellcategorycooldown_1, spellid_2, spelltrigger_2, spellcharges_2, "
|
||||||
// 76 77 78 79 80 81 82
|
// 75 76 77 78 79 80 81
|
||||||
"spellppmRate_2, spellcooldown_2, spellcategory_2, spellcategorycooldown_2, spellid_3, spelltrigger_3, spellcharges_3, "
|
"spellppmRate_2, spellcooldown_2, spellcategory_2, spellcategorycooldown_2, spellid_3, spelltrigger_3, spellcharges_3, "
|
||||||
// 83 84 85 86 87 88 89
|
// 82 83 84 85 86 87 88
|
||||||
"spellppmRate_3, spellcooldown_3, spellcategory_3, spellcategorycooldown_3, spellid_4, spelltrigger_4, spellcharges_4, "
|
"spellppmRate_3, spellcooldown_3, spellcategory_3, spellcategorycooldown_3, spellid_4, spelltrigger_4, spellcharges_4, "
|
||||||
// 90 91 92 93 94 95 96
|
// 89 90 91 92 93 94 95
|
||||||
"spellppmRate_4, spellcooldown_4, spellcategory_4, spellcategorycooldown_4, spellid_5, spelltrigger_5, spellcharges_5, "
|
"spellppmRate_4, spellcooldown_4, spellcategory_4, spellcategorycooldown_4, spellid_5, spelltrigger_5, spellcharges_5, "
|
||||||
// 97 98 99 100 101 102 103 104 105
|
// 96 97 98 99 100 101 102 103 104
|
||||||
"spellppmRate_5, spellcooldown_5, spellcategory_5, spellcategorycooldown_5, bonding, description, PageText, LanguageID, PageMaterial, "
|
"spellppmRate_5, spellcooldown_5, spellcategory_5, spellcategorycooldown_5, bonding, description, PageText, LanguageID, PageMaterial, "
|
||||||
// 106 107 108 109 110 111 112 113 114 115 116 117
|
// 105 106 107 108 109 110 111 112 113 114 115 116
|
||||||
"startquest, lockid, Material, sheath, RandomProperty, RandomSuffix, block, itemset, MaxDurability, area, Map, BagFamily, "
|
"startquest, lockid, Material, sheath, RandomProperty, RandomSuffix, block, itemset, MaxDurability, area, Map, BagFamily, "
|
||||||
// 118 119 120 121 122 123 124 125
|
// 117 118 119 120 121 122 123 124
|
||||||
"TotemCategory, socketColor_1, socketContent_1, socketColor_2, socketContent_2, socketColor_3, socketContent_3, socketBonus, "
|
"TotemCategory, socketColor_1, socketContent_1, socketColor_2, socketContent_2, socketColor_3, socketContent_3, socketBonus, "
|
||||||
// 126 127 128 129 130 131 132 133
|
// 125 126 127 128 129 130 131 132
|
||||||
"GemProperties, RequiredDisenchantSkill, ArmorDamageModifier, duration, ItemLimitCategory, HolidayId, ScriptName, DisenchantID, "
|
"GemProperties, RequiredDisenchantSkill, ArmorDamageModifier, duration, ItemLimitCategory, HolidayId, ScriptName, DisenchantID, "
|
||||||
// 134 135 136
|
// 133 134 135 136
|
||||||
"FoodType, minMoneyLoot, maxMoneyLoot, flagsCustom FROM item_template");
|
"FoodType, minMoneyLoot, maxMoneyLoot, flagsCustom FROM item_template");
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
@@ -2940,84 +2940,91 @@ void ObjectMgr::LoadItemTemplates()
|
|||||||
itemTemplate.MaxCount = fields[24].Get<int32>();
|
itemTemplate.MaxCount = fields[24].Get<int32>();
|
||||||
itemTemplate.Stackable = fields[25].Get<int32>();
|
itemTemplate.Stackable = fields[25].Get<int32>();
|
||||||
itemTemplate.ContainerSlots = uint32(fields[26].Get<uint8>());
|
itemTemplate.ContainerSlots = uint32(fields[26].Get<uint8>());
|
||||||
itemTemplate.StatsCount = uint32(fields[27].Get<uint8>());
|
|
||||||
|
|
||||||
for (uint8 i = 0; i < itemTemplate.StatsCount; ++i)
|
uint8 statsCount = 0;
|
||||||
|
while (statsCount < MAX_ITEM_PROTO_STATS)
|
||||||
{
|
{
|
||||||
itemTemplate.ItemStat[i].ItemStatType = uint32(fields[28 + i * 2].Get<uint8>());
|
uint32 statType = uint32(fields[27 + statsCount * 2].Get<uint8>());
|
||||||
itemTemplate.ItemStat[i].ItemStatValue = fields[29 + i * 2].Get<int32>();
|
int32 statValue = fields[28 + statsCount * 2].Get<int32>();
|
||||||
}
|
if (statType == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
itemTemplate.ScalingStatDistribution = uint32(fields[48].Get<uint16>());
|
itemTemplate.ItemStat[statsCount].ItemStatType = statType;
|
||||||
itemTemplate.ScalingStatValue = fields[49].Get<int32>();
|
itemTemplate.ItemStat[statsCount].ItemStatValue = statValue;
|
||||||
|
statsCount++;
|
||||||
|
}
|
||||||
|
itemTemplate.StatsCount = statsCount;
|
||||||
|
|
||||||
|
itemTemplate.ScalingStatDistribution = uint32(fields[47].Get<uint16>());
|
||||||
|
itemTemplate.ScalingStatValue = fields[48].Get<int32>();
|
||||||
|
|
||||||
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||||
{
|
{
|
||||||
itemTemplate.Damage[i].DamageMin = fields[50 + i * 3].Get<float>();
|
itemTemplate.Damage[i].DamageMin = fields[49 + i * 3].Get<float>();
|
||||||
itemTemplate.Damage[i].DamageMax = fields[51 + i * 3].Get<float>();
|
itemTemplate.Damage[i].DamageMax = fields[50 + i * 3].Get<float>();
|
||||||
itemTemplate.Damage[i].DamageType = uint32(fields[52 + i * 3].Get<uint8>());
|
itemTemplate.Damage[i].DamageType = uint32(fields[51 + i * 3].Get<uint8>());
|
||||||
}
|
}
|
||||||
|
|
||||||
itemTemplate.Armor = fields[56].Get<uint32>();
|
itemTemplate.Armor = fields[55].Get<uint32>();
|
||||||
itemTemplate.HolyRes = fields[57].Get<int32>();
|
itemTemplate.HolyRes = fields[56].Get<int32>();
|
||||||
itemTemplate.FireRes = fields[58].Get<int32>();
|
itemTemplate.FireRes = fields[57].Get<int32>();
|
||||||
itemTemplate.NatureRes = fields[59].Get<int32>();
|
itemTemplate.NatureRes = fields[58].Get<int32>();
|
||||||
itemTemplate.FrostRes = fields[60].Get<int32>();
|
itemTemplate.FrostRes = fields[59].Get<int32>();
|
||||||
itemTemplate.ShadowRes = fields[61].Get<int32>();
|
itemTemplate.ShadowRes = fields[60].Get<int32>();
|
||||||
itemTemplate.ArcaneRes = fields[62].Get<int32>();
|
itemTemplate.ArcaneRes = fields[61].Get<int32>();
|
||||||
itemTemplate.Delay = uint32(fields[63].Get<uint16>());
|
itemTemplate.Delay = uint32(fields[62].Get<uint16>());
|
||||||
itemTemplate.AmmoType = uint32(fields[64].Get<uint8>());
|
itemTemplate.AmmoType = uint32(fields[63].Get<uint8>());
|
||||||
itemTemplate.RangedModRange = fields[65].Get<float>();
|
itemTemplate.RangedModRange = fields[64].Get<float>();
|
||||||
|
|
||||||
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
|
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
|
||||||
{
|
{
|
||||||
itemTemplate.Spells[i].SpellId = fields[66 + i * 7 ].Get<int32>();
|
itemTemplate.Spells[i].SpellId = fields[65 + i * 7 ].Get<int32>();
|
||||||
itemTemplate.Spells[i].SpellTrigger = uint32(fields[67 + i * 7].Get<uint8>());
|
itemTemplate.Spells[i].SpellTrigger = uint32(fields[66 + i * 7].Get<uint8>());
|
||||||
itemTemplate.Spells[i].SpellCharges = int32(fields[68 + i * 7].Get<int16>());
|
itemTemplate.Spells[i].SpellCharges = int32(fields[67 + i * 7].Get<int16>());
|
||||||
itemTemplate.Spells[i].SpellPPMRate = fields[69 + i * 7].Get<float>();
|
itemTemplate.Spells[i].SpellPPMRate = fields[68 + i * 7].Get<float>();
|
||||||
itemTemplate.Spells[i].SpellCooldown = fields[70 + i * 7].Get<int32>();
|
itemTemplate.Spells[i].SpellCooldown = fields[69 + i * 7].Get<int32>();
|
||||||
itemTemplate.Spells[i].SpellCategory = uint32(fields[71 + i * 7].Get<uint16>());
|
itemTemplate.Spells[i].SpellCategory = uint32(fields[70 + i * 7].Get<uint16>());
|
||||||
itemTemplate.Spells[i].SpellCategoryCooldown = fields[72 + i * 7].Get<int32>();
|
itemTemplate.Spells[i].SpellCategoryCooldown = fields[71 + i * 7].Get<int32>();
|
||||||
}
|
}
|
||||||
|
|
||||||
itemTemplate.Bonding = uint32(fields[101].Get<uint8>());
|
itemTemplate.Bonding = uint32(fields[100].Get<uint8>());
|
||||||
itemTemplate.Description = fields[102].Get<std::string>();
|
itemTemplate.Description = fields[101].Get<std::string>();
|
||||||
itemTemplate.PageText = fields[103].Get<uint32>();
|
itemTemplate.PageText = fields[102].Get<uint32>();
|
||||||
itemTemplate.LanguageID = uint32(fields[104].Get<uint8>());
|
itemTemplate.LanguageID = uint32(fields[103].Get<uint8>());
|
||||||
itemTemplate.PageMaterial = uint32(fields[105].Get<uint8>());
|
itemTemplate.PageMaterial = uint32(fields[104].Get<uint8>());
|
||||||
itemTemplate.StartQuest = fields[106].Get<uint32>();
|
itemTemplate.StartQuest = fields[105].Get<uint32>();
|
||||||
itemTemplate.LockID = fields[107].Get<uint32>();
|
itemTemplate.LockID = fields[106].Get<uint32>();
|
||||||
itemTemplate.Material = int32(fields[108].Get<int8>());
|
itemTemplate.Material = int32(fields[107].Get<int8>());
|
||||||
itemTemplate.Sheath = uint32(fields[109].Get<uint8>());
|
itemTemplate.Sheath = uint32(fields[108].Get<uint8>());
|
||||||
itemTemplate.RandomProperty = fields[110].Get<int32>();
|
itemTemplate.RandomProperty = fields[109].Get<int32>();
|
||||||
itemTemplate.RandomSuffix = fields[111].Get<int32>();
|
itemTemplate.RandomSuffix = fields[110].Get<int32>();
|
||||||
itemTemplate.Block = fields[112].Get<uint32>();
|
itemTemplate.Block = fields[111].Get<uint32>();
|
||||||
itemTemplate.ItemSet = fields[113].Get<uint32>();
|
itemTemplate.ItemSet = fields[112].Get<uint32>();
|
||||||
itemTemplate.MaxDurability = uint32(fields[114].Get<uint16>());
|
itemTemplate.MaxDurability = uint32(fields[113].Get<uint16>());
|
||||||
itemTemplate.Area = fields[115].Get<uint32>();
|
itemTemplate.Area = fields[114].Get<uint32>();
|
||||||
itemTemplate.Map = uint32(fields[116].Get<uint16>());
|
itemTemplate.Map = uint32(fields[115].Get<uint16>());
|
||||||
itemTemplate.BagFamily = fields[117].Get<uint32>();
|
itemTemplate.BagFamily = fields[116].Get<uint32>();
|
||||||
itemTemplate.TotemCategory = fields[118].Get<uint32>();
|
itemTemplate.TotemCategory = fields[117].Get<uint32>();
|
||||||
|
|
||||||
for (uint8 i = 0; i < MAX_ITEM_PROTO_SOCKETS; ++i)
|
for (uint8 i = 0; i < MAX_ITEM_PROTO_SOCKETS; ++i)
|
||||||
{
|
{
|
||||||
itemTemplate.Socket[i].Color = uint32(fields[119 + i * 2].Get<uint8>());
|
itemTemplate.Socket[i].Color = uint32(fields[118 + i * 2].Get<uint8>());
|
||||||
itemTemplate.Socket[i].Content = fields[120 + i * 2].Get<uint32>();
|
itemTemplate.Socket[i].Content = fields[119 + i * 2].Get<uint32>();
|
||||||
}
|
}
|
||||||
|
|
||||||
itemTemplate.socketBonus = fields[125].Get<uint32>();
|
itemTemplate.socketBonus = fields[124].Get<uint32>();
|
||||||
itemTemplate.GemProperties = fields[126].Get<uint32>();
|
itemTemplate.GemProperties = fields[125].Get<uint32>();
|
||||||
itemTemplate.RequiredDisenchantSkill = uint32(fields[127].Get<int16>());
|
itemTemplate.RequiredDisenchantSkill = uint32(fields[126].Get<int16>());
|
||||||
itemTemplate.ArmorDamageModifier = fields[128].Get<float>();
|
itemTemplate.ArmorDamageModifier = fields[127].Get<float>();
|
||||||
itemTemplate.Duration = fields[129].Get<uint32>();
|
itemTemplate.Duration = fields[128].Get<uint32>();
|
||||||
itemTemplate.ItemLimitCategory = uint32(fields[130].Get<int16>());
|
itemTemplate.ItemLimitCategory = uint32(fields[129].Get<int16>());
|
||||||
itemTemplate.HolidayId = fields[131].Get<uint32>();
|
itemTemplate.HolidayId = fields[130].Get<uint32>();
|
||||||
itemTemplate.ScriptId = sObjectMgr->GetScriptId(fields[132].Get<std::string>());
|
itemTemplate.ScriptId = GetScriptId(fields[131].Get<std::string>());
|
||||||
itemTemplate.DisenchantID = fields[133].Get<uint32>();
|
itemTemplate.DisenchantID = fields[132].Get<uint32>();
|
||||||
itemTemplate.FoodType = uint32(fields[134].Get<uint8>());
|
itemTemplate.FoodType = uint32(fields[133].Get<uint8>());
|
||||||
itemTemplate.MinMoneyLoot = fields[135].Get<uint32>();
|
itemTemplate.MinMoneyLoot = fields[134].Get<uint32>();
|
||||||
itemTemplate.MaxMoneyLoot = fields[136].Get<uint32>();
|
itemTemplate.MaxMoneyLoot = fields[135].Get<uint32>();
|
||||||
itemTemplate.FlagsCu = ItemFlagsCustom(fields[137].Get<uint32>());
|
itemTemplate.FlagsCu = ItemFlagsCustom(fields[136].Get<uint32>());
|
||||||
|
|
||||||
// Checks
|
// Checks
|
||||||
ItemEntry const* dbcitem = sItemStore.LookupEntry(entry);
|
ItemEntry const* dbcitem = sItemStore.LookupEntry(entry);
|
||||||
@@ -3171,12 +3178,6 @@ void ObjectMgr::LoadItemTemplates()
|
|||||||
itemTemplate.ContainerSlots = MAX_BAG_SIZE;
|
itemTemplate.ContainerSlots = MAX_BAG_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemTemplate.StatsCount > MAX_ITEM_PROTO_STATS)
|
|
||||||
{
|
|
||||||
LOG_ERROR("sql.sql", "Item (Entry: {}) has too large value in statscount ({}), replace by hardcoded limit ({}).", entry, itemTemplate.StatsCount, MAX_ITEM_PROTO_STATS);
|
|
||||||
itemTemplate.StatsCount = MAX_ITEM_PROTO_STATS;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint8 j = 0; j < itemTemplate.StatsCount; ++j)
|
for (uint8 j = 0; j < itemTemplate.StatsCount; ++j)
|
||||||
{
|
{
|
||||||
// for ItemStatValue != 0
|
// for ItemStatValue != 0
|
||||||
@@ -3189,7 +3190,8 @@ void ObjectMgr::LoadItemTemplates()
|
|||||||
switch (itemTemplate.ItemStat[j].ItemStatType)
|
switch (itemTemplate.ItemStat[j].ItemStatType)
|
||||||
{
|
{
|
||||||
case ITEM_MOD_SPELL_HEALING_DONE:
|
case ITEM_MOD_SPELL_HEALING_DONE:
|
||||||
LOG_ERROR("sql.sql", "Item (Entry: {}) has deprecated stat_type{} ({})", entry, j + 1, itemTemplate.ItemStat[j].ItemStatType);
|
case ITEM_MOD_SPELL_DAMAGE_DONE:
|
||||||
|
LOG_WARN("sql.sql", "Item (Entry: {}) has deprecated stat_type{} ({})", entry, j + 1, itemTemplate.ItemStat[j].ItemStatType);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -3570,7 +3572,7 @@ void ObjectMgr::LoadItemSetNames()
|
|||||||
{
|
{
|
||||||
uint32 entry = *itr;
|
uint32 entry = *itr;
|
||||||
// add data from item_template if available
|
// add data from item_template if available
|
||||||
pProto = sObjectMgr->GetItemTemplate(entry);
|
pProto = GetItemTemplate(entry);
|
||||||
if (pProto)
|
if (pProto)
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Item set part (Entry: {}) does not have entry in `item_set_names`, adding data from `item_template`.", entry);
|
LOG_ERROR("sql.sql", "Item set part (Entry: {}) does not have entry in `item_set_names`, adding data from `item_template`.", entry);
|
||||||
@@ -3617,13 +3619,13 @@ void ObjectMgr::LoadVehicleTemplateAccessories()
|
|||||||
uint8 uiSummonType = fields[4].Get<uint8>();
|
uint8 uiSummonType = fields[4].Get<uint8>();
|
||||||
uint32 uiSummonTimer = fields[5].Get<uint32>();
|
uint32 uiSummonTimer = fields[5].Get<uint32>();
|
||||||
|
|
||||||
if (!sObjectMgr->GetCreatureTemplate(uiEntry))
|
if (!GetCreatureTemplate(uiEntry))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Table `vehicle_template_accessory`: creature template entry {} does not exist.", uiEntry);
|
LOG_ERROR("sql.sql", "Table `vehicle_template_accessory`: creature template entry {} does not exist.", uiEntry);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sObjectMgr->GetCreatureTemplate(uiAccessory))
|
if (!GetCreatureTemplate(uiAccessory))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Table `vehicle_template_accessory`: Accessory {} does not exist.", uiAccessory);
|
LOG_ERROR("sql.sql", "Table `vehicle_template_accessory`: Accessory {} does not exist.", uiAccessory);
|
||||||
continue;
|
continue;
|
||||||
@@ -3673,7 +3675,7 @@ void ObjectMgr::LoadVehicleAccessories()
|
|||||||
uint8 uiSummonType = fields[4].Get<uint8>();
|
uint8 uiSummonType = fields[4].Get<uint8>();
|
||||||
uint32 uiSummonTimer = fields[5].Get<uint32>();
|
uint32 uiSummonTimer = fields[5].Get<uint32>();
|
||||||
|
|
||||||
if (!sObjectMgr->GetCreatureTemplate(uiAccessory))
|
if (!GetCreatureTemplate(uiAccessory))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Table `vehicle_accessory`: Accessory {} does not exist.", uiAccessory);
|
LOG_ERROR("sql.sql", "Table `vehicle_accessory`: Accessory {} does not exist.", uiAccessory);
|
||||||
continue;
|
continue;
|
||||||
@@ -3765,7 +3767,7 @@ void ObjectMgr::LoadPetLevelInfo()
|
|||||||
Field* fields = result->Fetch();
|
Field* fields = result->Fetch();
|
||||||
|
|
||||||
uint32 creature_id = fields[0].Get<uint32>();
|
uint32 creature_id = fields[0].Get<uint32>();
|
||||||
if (!sObjectMgr->GetCreatureTemplate(creature_id))
|
if (!GetCreatureTemplate(creature_id))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Wrong creature id {} in `pet_levelstats` table, ignoring.", creature_id);
|
LOG_ERROR("sql.sql", "Wrong creature id {} in `pet_levelstats` table, ignoring.", creature_id);
|
||||||
continue;
|
continue;
|
||||||
@@ -4998,7 +5000,7 @@ void ObjectMgr::LoadQuests()
|
|||||||
|
|
||||||
if (qinfo->StartItem)
|
if (qinfo->StartItem)
|
||||||
{
|
{
|
||||||
if (!sObjectMgr->GetItemTemplate(qinfo->StartItem))
|
if (!GetItemTemplate(qinfo->StartItem))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Quest {} has `StartItem` = {} but item with entry {} does not exist, quest can't be done.",
|
LOG_ERROR("sql.sql", "Quest {} has `StartItem` = {} but item with entry {} does not exist, quest can't be done.",
|
||||||
qinfo->GetQuestId(), qinfo->StartItem, qinfo->StartItem);
|
qinfo->GetQuestId(), qinfo->StartItem, qinfo->StartItem);
|
||||||
@@ -5049,7 +5051,7 @@ void ObjectMgr::LoadQuests()
|
|||||||
|
|
||||||
qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER);
|
qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER);
|
||||||
|
|
||||||
if (!sObjectMgr->GetItemTemplate(id))
|
if (!GetItemTemplate(id))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Quest {} has `RequiredItemId{}` = {} but item with entry {} does not exist, quest can't be done.",
|
LOG_ERROR("sql.sql", "Quest {} has `RequiredItemId{}` = {} but item with entry {} does not exist, quest can't be done.",
|
||||||
qinfo->GetQuestId(), j + 1, id, id);
|
qinfo->GetQuestId(), j + 1, id, id);
|
||||||
@@ -5069,7 +5071,7 @@ void ObjectMgr::LoadQuests()
|
|||||||
uint32 id = qinfo->ItemDrop[j];
|
uint32 id = qinfo->ItemDrop[j];
|
||||||
if (id)
|
if (id)
|
||||||
{
|
{
|
||||||
if (!sObjectMgr->GetItemTemplate(id))
|
if (!GetItemTemplate(id))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Quest {} has `ItemDrop{}` = {} but item with entry {} does not exist, quest can't be done.",
|
LOG_ERROR("sql.sql", "Quest {} has `ItemDrop{}` = {} but item with entry {} does not exist, quest can't be done.",
|
||||||
qinfo->GetQuestId(), j + 1, id, id);
|
qinfo->GetQuestId(), j + 1, id, id);
|
||||||
@@ -5090,14 +5092,14 @@ void ObjectMgr::LoadQuests()
|
|||||||
for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j)
|
for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j)
|
||||||
{
|
{
|
||||||
int32 id = qinfo->RequiredNpcOrGo[j];
|
int32 id = qinfo->RequiredNpcOrGo[j];
|
||||||
if (id < 0 && !sObjectMgr->GetGameObjectTemplate(-id))
|
if (id < 0 && !GetGameObjectTemplate(-id))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Quest {} has `RequiredNpcOrGo{}` = {} but gameobject {} does not exist, quest can't be done.",
|
LOG_ERROR("sql.sql", "Quest {} has `RequiredNpcOrGo{}` = {} but gameobject {} does not exist, quest can't be done.",
|
||||||
qinfo->GetQuestId(), j + 1, id, uint32(-id));
|
qinfo->GetQuestId(), j + 1, id, uint32(-id));
|
||||||
qinfo->RequiredNpcOrGo[j] = 0; // quest can't be done for this requirement
|
qinfo->RequiredNpcOrGo[j] = 0; // quest can't be done for this requirement
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id > 0 && !sObjectMgr->GetCreatureTemplate(id))
|
if (id > 0 && !GetCreatureTemplate(id))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Quest {} has `RequiredNpcOrGo{}` = {} but creature with entry {} does not exist, quest can't be done.",
|
LOG_ERROR("sql.sql", "Quest {} has `RequiredNpcOrGo{}` = {} but creature with entry {} does not exist, quest can't be done.",
|
||||||
qinfo->GetQuestId(), j + 1, id, uint32(id));
|
qinfo->GetQuestId(), j + 1, id, uint32(id));
|
||||||
@@ -5130,7 +5132,7 @@ void ObjectMgr::LoadQuests()
|
|||||||
uint32 id = qinfo->RewardChoiceItemId[j];
|
uint32 id = qinfo->RewardChoiceItemId[j];
|
||||||
if (id)
|
if (id)
|
||||||
{
|
{
|
||||||
if (!sObjectMgr->GetItemTemplate(id))
|
if (!GetItemTemplate(id))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Quest {} has `RewardChoiceItemId{}` = {} but item with entry {} does not exist, quest will not reward this item.",
|
LOG_ERROR("sql.sql", "Quest {} has `RewardChoiceItemId{}` = {} but item with entry {} does not exist, quest will not reward this item.",
|
||||||
qinfo->GetQuestId(), j + 1, id, id);
|
qinfo->GetQuestId(), j + 1, id, id);
|
||||||
@@ -5176,7 +5178,7 @@ void ObjectMgr::LoadQuests()
|
|||||||
uint32 id = qinfo->RewardItemId[j];
|
uint32 id = qinfo->RewardItemId[j];
|
||||||
if (id)
|
if (id)
|
||||||
{
|
{
|
||||||
if (!sObjectMgr->GetItemTemplate(id))
|
if (!GetItemTemplate(id))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Quest {} has `RewardItemId{}` = {} but item with entry {} does not exist, quest will not reward this item.",
|
LOG_ERROR("sql.sql", "Quest {} has `RewardItemId{}` = {} but item with entry {} does not exist, quest will not reward this item.",
|
||||||
qinfo->GetQuestId(), j + 1, id, id);
|
qinfo->GetQuestId(), j + 1, id, id);
|
||||||
@@ -5760,7 +5762,7 @@ void ObjectMgr::LoadEventScripts()
|
|||||||
|
|
||||||
std::set<uint32> evt_scripts;
|
std::set<uint32> evt_scripts;
|
||||||
// Load all possible script entries from gameobjects
|
// Load all possible script entries from gameobjects
|
||||||
GameObjectTemplateContainer const* gotc = sObjectMgr->GetGameObjectTemplates();
|
GameObjectTemplateContainer const* gotc = GetGameObjectTemplates();
|
||||||
for (GameObjectTemplateContainer::const_iterator itr = gotc->begin(); itr != gotc->end(); ++itr)
|
for (GameObjectTemplateContainer::const_iterator itr = gotc->begin(); itr != gotc->end(); ++itr)
|
||||||
if (uint32 eventId = itr->second.GetEventScriptId())
|
if (uint32 eventId = itr->second.GetEventScriptId())
|
||||||
evt_scripts.insert(eventId);
|
evt_scripts.insert(eventId);
|
||||||
@@ -6069,7 +6071,7 @@ void ObjectMgr::LoadInstanceTemplate()
|
|||||||
|
|
||||||
instanceTemplate.AllowMount = fields[3].Get<bool>();
|
instanceTemplate.AllowMount = fields[3].Get<bool>();
|
||||||
instanceTemplate.Parent = uint32(fields[1].Get<uint16>());
|
instanceTemplate.Parent = uint32(fields[1].Get<uint16>());
|
||||||
instanceTemplate.ScriptId = sObjectMgr->GetScriptId(fields[2].Get<std::string>());
|
instanceTemplate.ScriptId = GetScriptId(fields[2].Get<std::string>());
|
||||||
|
|
||||||
_instanceTemplateStore[mapID] = instanceTemplate;
|
_instanceTemplateStore[mapID] = instanceTemplate;
|
||||||
|
|
||||||
@@ -6515,14 +6517,14 @@ void ObjectMgr::LoadQuestGreetings()
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case 0: // Creature
|
case 0: // Creature
|
||||||
if (!sObjectMgr->GetCreatureTemplate(id))
|
if (!GetCreatureTemplate(id))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Table `quest_greeting`: creature template entry {} does not exist.", id);
|
LOG_ERROR("sql.sql", "Table `quest_greeting`: creature template entry {} does not exist.", id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1: // GameObject
|
case 1: // GameObject
|
||||||
if (!sObjectMgr->GetGameObjectTemplate(id))
|
if (!GetGameObjectTemplate(id))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Table `quest_greeting`: gameobject template entry {} does not exist.", id);
|
LOG_ERROR("sql.sql", "Table `quest_greeting`: gameobject template entry {} does not exist.", id);
|
||||||
continue;
|
continue;
|
||||||
@@ -6568,14 +6570,14 @@ void ObjectMgr::LoadQuestGreetingsLocales()
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case 0: // Creature
|
case 0: // Creature
|
||||||
if (!sObjectMgr->GetCreatureTemplate(id))
|
if (!GetCreatureTemplate(id))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Table `quest_greeting_locale`: creature template entry {} does not exist.", id);
|
LOG_ERROR("sql.sql", "Table `quest_greeting_locale`: creature template entry {} does not exist.", id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1: // GameObject
|
case 1: // GameObject
|
||||||
if (!sObjectMgr->GetGameObjectTemplate(id))
|
if (!GetGameObjectTemplate(id))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Table `quest_greeting_locale`: gameobject template entry {} does not exist.", id);
|
LOG_ERROR("sql.sql", "Table `quest_greeting_locale`: gameobject template entry {} does not exist.", id);
|
||||||
continue;
|
continue;
|
||||||
@@ -7577,7 +7579,7 @@ void ObjectMgr::LoadGameObjectTemplateAddons()
|
|||||||
|
|
||||||
uint32 entry = fields[0].Get<uint32>();
|
uint32 entry = fields[0].Get<uint32>();
|
||||||
|
|
||||||
GameObjectTemplate const* got = sObjectMgr->GetGameObjectTemplate(entry);
|
GameObjectTemplate const* got = GetGameObjectTemplate(entry);
|
||||||
if (!got)
|
if (!got)
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql",
|
LOG_ERROR("sql.sql",
|
||||||
@@ -8222,7 +8224,7 @@ void ObjectMgr::LoadNPCSpellClickSpells()
|
|||||||
|
|
||||||
// all spellclick data loaded, now we check if there are creatures with NPC_FLAG_SPELLCLICK but with no data
|
// all spellclick data loaded, now we check if there are creatures with NPC_FLAG_SPELLCLICK but with no data
|
||||||
// NOTE: It *CAN* be the other way around: no spellclick flag but with spellclick data, in case of creature-only vehicle accessories
|
// NOTE: It *CAN* be the other way around: no spellclick flag but with spellclick data, in case of creature-only vehicle accessories
|
||||||
CreatureTemplateContainer const* ctc = sObjectMgr->GetCreatureTemplates();
|
CreatureTemplateContainer const* ctc = GetCreatureTemplates();
|
||||||
for (CreatureTemplateContainer::const_iterator itr = ctc->begin(); itr != ctc->end(); ++itr)
|
for (CreatureTemplateContainer::const_iterator itr = ctc->begin(); itr != ctc->end(); ++itr)
|
||||||
{
|
{
|
||||||
if ((itr->second.npcflag & UNIT_NPC_FLAG_SPELLCLICK) && _spellClickInfoStore.find(itr->second.Entry) == _spellClickInfoStore.end())
|
if ((itr->second.npcflag & UNIT_NPC_FLAG_SPELLCLICK) && _spellClickInfoStore.find(itr->second.Entry) == _spellClickInfoStore.end())
|
||||||
@@ -8747,7 +8749,7 @@ void ObjectMgr::LoadGameObjectForQuests()
|
|||||||
{
|
{
|
||||||
uint32 oldMSTime = getMSTime();
|
uint32 oldMSTime = getMSTime();
|
||||||
|
|
||||||
if (sObjectMgr->GetGameObjectTemplates()->empty())
|
if (GetGameObjectTemplates()->empty())
|
||||||
{
|
{
|
||||||
LOG_WARN("server.loading", ">> Loaded 0 GameObjects for quests");
|
LOG_WARN("server.loading", ">> Loaded 0 GameObjects for quests");
|
||||||
LOG_INFO("server.loading", " ");
|
LOG_INFO("server.loading", " ");
|
||||||
@@ -8757,7 +8759,7 @@ void ObjectMgr::LoadGameObjectForQuests()
|
|||||||
uint32 count = 0;
|
uint32 count = 0;
|
||||||
|
|
||||||
// collect GO entries for GO that must activated
|
// collect GO entries for GO that must activated
|
||||||
GameObjectTemplateContainer* gotc = const_cast<GameObjectTemplateContainer*>(sObjectMgr->GetGameObjectTemplates());
|
GameObjectTemplateContainer* gotc = const_cast<GameObjectTemplateContainer*>(GetGameObjectTemplates());
|
||||||
for (GameObjectTemplateContainer::iterator itr = gotc->begin(); itr != gotc->end(); ++itr)
|
for (GameObjectTemplateContainer::iterator itr = gotc->begin(); itr != gotc->end(); ++itr)
|
||||||
{
|
{
|
||||||
itr->second.IsForQuests = false;
|
itr->second.IsForQuests = false;
|
||||||
@@ -9666,7 +9668,7 @@ bool ObjectMgr::RemoveVendorItem(uint32 entry, uint32 item, bool persist /*= tru
|
|||||||
bool ObjectMgr::IsVendorItemValid(uint32 vendor_entry, uint32 item_id, int32 maxcount, uint32 incrtime, uint32 ExtendedCost, Player* player, std::set<uint32>* /*skip_vendors*/, uint32 /*ORnpcflag*/) const
|
bool ObjectMgr::IsVendorItemValid(uint32 vendor_entry, uint32 item_id, int32 maxcount, uint32 incrtime, uint32 ExtendedCost, Player* player, std::set<uint32>* /*skip_vendors*/, uint32 /*ORnpcflag*/) const
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(vendor_entry);
|
CreatureTemplate const* cInfo = GetCreatureTemplate(vendor_entry);
|
||||||
if (!cInfo)
|
if (!cInfo)
|
||||||
{
|
{
|
||||||
if (player)
|
if (player)
|
||||||
@@ -10040,7 +10042,7 @@ void ObjectMgr::LoadCreatureClassLevelStats()
|
|||||||
++count;
|
++count;
|
||||||
} while (result->NextRow());
|
} while (result->NextRow());
|
||||||
|
|
||||||
CreatureTemplateContainer const* ctc = sObjectMgr->GetCreatureTemplates();
|
CreatureTemplateContainer const* ctc = GetCreatureTemplates();
|
||||||
for (CreatureTemplateContainer::const_iterator itr = ctc->begin(); itr != ctc->end(); ++itr)
|
for (CreatureTemplateContainer::const_iterator itr = ctc->begin(); itr != ctc->end(); ++itr)
|
||||||
{
|
{
|
||||||
for (uint16 lvl = itr->second.minlevel; lvl <= itr->second.maxlevel; ++lvl)
|
for (uint16 lvl = itr->second.minlevel; lvl <= itr->second.maxlevel; ++lvl)
|
||||||
@@ -10148,9 +10150,9 @@ void ObjectMgr::LoadFactionChangeQuests()
|
|||||||
uint32 alliance = fields[0].Get<uint32>();
|
uint32 alliance = fields[0].Get<uint32>();
|
||||||
uint32 horde = fields[1].Get<uint32>();
|
uint32 horde = fields[1].Get<uint32>();
|
||||||
|
|
||||||
if (!sObjectMgr->GetQuestTemplate(alliance))
|
if (!GetQuestTemplate(alliance))
|
||||||
LOG_ERROR("sql.sql", "Quest {} (alliance_id) referenced in `player_factionchange_quests` does not exist, pair skipped!", alliance);
|
LOG_ERROR("sql.sql", "Quest {} (alliance_id) referenced in `player_factionchange_quests` does not exist, pair skipped!", alliance);
|
||||||
else if (!sObjectMgr->GetQuestTemplate(horde))
|
else if (!GetQuestTemplate(horde))
|
||||||
LOG_ERROR("sql.sql", "Quest {} (horde_id) referenced in `player_factionchange_quests` does not exist, pair skipped!", horde);
|
LOG_ERROR("sql.sql", "Quest {} (horde_id) referenced in `player_factionchange_quests` does not exist, pair skipped!", horde);
|
||||||
else
|
else
|
||||||
FactionChangeQuests[alliance] = horde;
|
FactionChangeQuests[alliance] = horde;
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ class ObjectGuid;
|
|||||||
#define MAP_HALFSIZE (MAP_SIZE/2)
|
#define MAP_HALFSIZE (MAP_SIZE/2)
|
||||||
|
|
||||||
// Creature used instead pet to simplify *::Visit templates (not required duplicate code for Creature->Pet case)
|
// Creature used instead pet to simplify *::Visit templates (not required duplicate code for Creature->Pet case)
|
||||||
typedef TYPELIST_5(GameObject, Player, Creature/*pets*/, Corpse/*resurrectable*/, DynamicObject/*farsight target*/) AllWorldObjectTypes;
|
typedef TYPELIST_4(GameObject, Player, Creature/*pets*/, Corpse/*resurrectable*/) AllWorldObjectTypes;
|
||||||
typedef TYPELIST_4(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/) AllGridObjectTypes;
|
typedef TYPELIST_4(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/) AllGridObjectTypes;
|
||||||
typedef TYPELIST_5(Creature, GameObject, DynamicObject, Pet, Corpse) AllMapStoredObjectTypes;
|
typedef TYPELIST_5(Creature, GameObject, DynamicObject, Pet, Corpse) AllMapStoredObjectTypes;
|
||||||
|
|
||||||
|
|||||||
@@ -84,20 +84,14 @@ void GridObjectLoader::LoadAllCellsInGrid()
|
|||||||
LoadGameObjects(cell_guids.gameobjects, _map);
|
LoadGameObjects(cell_guids.gameobjects, _map);
|
||||||
LoadCreatures(cell_guids.creatures, _map);
|
LoadCreatures(cell_guids.creatures, _map);
|
||||||
|
|
||||||
if (std::unordered_set<Corpse*> const* corpses = _map->GetCorpsesInCell(_grid.GetId()))
|
if (std::unordered_set<Corpse*> const* corpses = _map->GetCorpsesInGrid(_grid.GetId()))
|
||||||
{
|
{
|
||||||
for (Corpse* corpse : *corpses)
|
for (Corpse* corpse : *corpses)
|
||||||
{
|
{
|
||||||
if (corpse->IsInGrid())
|
if (corpse->IsInGrid())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CellCoord cellCoord = Acore::ComputeCellCoord(corpse->GetPositionX(), corpse->GetPositionY());
|
AddObjectHelper<Corpse>(_map, corpse);
|
||||||
Cell cell(cellCoord);
|
|
||||||
|
|
||||||
if (corpse->IsWorldObject())
|
|
||||||
_grid.AddWorldObject(cell.CellX(), cell.CellY(), corpse);
|
|
||||||
else
|
|
||||||
_grid.AddGridObject(cell.CellX(), cell.CellY(), corpse);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ServerMailMgr.h"
|
#include "ServerMailMgr.h"
|
||||||
|
#include "AccountMgr.h"
|
||||||
#include "AchievementMgr.h"
|
#include "AchievementMgr.h"
|
||||||
|
#include "Common.h"
|
||||||
#include "DatabaseEnv.h"
|
#include "DatabaseEnv.h"
|
||||||
#include "Item.h"
|
#include "Item.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
@@ -240,21 +242,28 @@ void ServerMailMgr::LoadMailServerTemplatesConditions()
|
|||||||
case ServerMailConditionType::Faction:
|
case ServerMailConditionType::Faction:
|
||||||
if (conditionValue < TEAM_ALLIANCE || conditionValue > TEAM_HORDE)
|
if (conditionValue < TEAM_ALLIANCE || conditionValue > TEAM_HORDE)
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Faction' with invalid conditionValue ({}) for templateID {}, skipped.", conditionState, templateID);
|
LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Faction' with invalid conditionValue ({}) for templateID {}, skipped.", conditionValue, templateID);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ServerMailConditionType::Race:
|
case ServerMailConditionType::Race:
|
||||||
if (conditionValue & ~RACEMASK_ALL_PLAYABLE)
|
if (conditionValue & ~RACEMASK_ALL_PLAYABLE)
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Race' with invalid conditionValue ({}) for templateID {}, skipped.", conditionState, templateID);
|
LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Race' with invalid conditionValue ({}) for templateID {}, skipped.", conditionValue, templateID);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ServerMailConditionType::Class:
|
case ServerMailConditionType::Class:
|
||||||
if (conditionValue & ~CLASSMASK_ALL_PLAYABLE)
|
if (conditionValue & ~CLASSMASK_ALL_PLAYABLE)
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Class' with invalid conditionValue ({}) for templateID {}, skipped.", conditionState, templateID);
|
LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Class' with invalid conditionValue ({}) for templateID {}, skipped.", conditionValue, templateID);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ServerMailConditionType::AccountFlags:
|
||||||
|
if ((conditionValue & ~ACCOUNT_FLAGS_ALL) != 0)
|
||||||
|
{
|
||||||
|
LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'AccountFlags' with invalid conditionValue ({}) for templateID {}, skipped.", conditionValue, templateID);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -344,6 +353,8 @@ bool ServerMailCondition::CheckCondition(Player* player) const
|
|||||||
return (player->getRaceMask() & value) != 0;
|
return (player->getRaceMask() & value) != 0;
|
||||||
case ServerMailConditionType::Class:
|
case ServerMailConditionType::Class:
|
||||||
return (player->getClassMask() & value) != 0;
|
return (player->getClassMask() & value) != 0;
|
||||||
|
case ServerMailConditionType::AccountFlags:
|
||||||
|
return player->GetSession()->HasAccountFlag(value);
|
||||||
default:
|
default:
|
||||||
[[unlikely]] LOG_ERROR("server.mail", "Unknown server mail condition type '{}'", static_cast<uint32>(type));
|
[[unlikely]] LOG_ERROR("server.mail", "Unknown server mail condition type '{}'", static_cast<uint32>(type));
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ enum class ServerMailConditionType : uint8
|
|||||||
Faction = 6, ///< Requires the player to be a part of a specific faction. Horde/Alliance.
|
Faction = 6, ///< Requires the player to be a part of a specific faction. Horde/Alliance.
|
||||||
Race = 7, ///< Requires the player to be a specific race.
|
Race = 7, ///< Requires the player to be a specific race.
|
||||||
Class = 8, ///< Requires the player to be a specific class.
|
Class = 8, ///< Requires the player to be a specific class.
|
||||||
|
AccountFlags = 9, ///< Requires the player to have a specific AccountFlag (bit)
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,7 +68,8 @@ constexpr std::pair<std::string_view, ServerMailConditionType> ServerMailConditi
|
|||||||
{ "Reputation", ServerMailConditionType::Reputation },
|
{ "Reputation", ServerMailConditionType::Reputation },
|
||||||
{ "Faction", ServerMailConditionType::Faction },
|
{ "Faction", ServerMailConditionType::Faction },
|
||||||
{ "Race", ServerMailConditionType::Race },
|
{ "Race", ServerMailConditionType::Race },
|
||||||
{ "Class", ServerMailConditionType::Class }
|
{ "Class", ServerMailConditionType::Class },
|
||||||
|
{ "AccountFlags", ServerMailConditionType::AccountFlags }
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+12
-122
@@ -175,81 +175,6 @@ void Map::AddToGrid(Corpse* obj, Cell const& cell)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
|
||||||
void Map::SwitchGridContainers(T* /*obj*/, bool /*on*/)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
void Map::SwitchGridContainers(Creature* obj, bool on)
|
|
||||||
{
|
|
||||||
ASSERT(!obj->IsPermanentWorldObject());
|
|
||||||
CellCoord p = Acore::ComputeCellCoord(obj->GetPositionX(), obj->GetPositionY());
|
|
||||||
if (!p.IsCoordValid())
|
|
||||||
{
|
|
||||||
LOG_ERROR("maps", "Map::SwitchGridContainers: Object {} has invalid coordinates X:{} Y:{} grid cell [{}:{}]",
|
|
||||||
obj->GetGUID().ToString(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Cell cell(p);
|
|
||||||
if (!IsGridLoaded(GridCoord(cell.data.Part.grid_x, cell.data.Part.grid_y)))
|
|
||||||
return;
|
|
||||||
|
|
||||||
LOG_DEBUG("maps", "Switch object {} from grid[{}, {}] {}", obj->GetGUID().ToString(), cell.GridX(), cell.GridY(), on);
|
|
||||||
MapGridType* grid = GetMapGrid(cell.GridX(), cell.GridY());
|
|
||||||
ASSERT(grid);
|
|
||||||
|
|
||||||
obj->RemoveFromGrid(); //This step is not really necessary but we want to do ASSERT in remove/add
|
|
||||||
|
|
||||||
if (on)
|
|
||||||
{
|
|
||||||
grid->AddWorldObject(cell.CellX(), cell.CellY(), obj);
|
|
||||||
AddWorldObject(obj);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
grid->AddGridObject(cell.CellX(), cell.CellY(), obj);
|
|
||||||
RemoveWorldObject(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
obj->m_isTempWorldObject = on;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
void Map::SwitchGridContainers(GameObject* obj, bool on)
|
|
||||||
{
|
|
||||||
ASSERT(!obj->IsPermanentWorldObject());
|
|
||||||
CellCoord p = Acore::ComputeCellCoord(obj->GetPositionX(), obj->GetPositionY());
|
|
||||||
if (!p.IsCoordValid())
|
|
||||||
{
|
|
||||||
LOG_ERROR("maps", "Map::SwitchGridContainers: Object {} has invalid coordinates X:{} Y:{} grid cell [{}:{}]",
|
|
||||||
obj->GetGUID().ToString(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Cell cell(p);
|
|
||||||
if (!IsGridLoaded(GridCoord(cell.data.Part.grid_x, cell.data.Part.grid_y)))
|
|
||||||
return;
|
|
||||||
|
|
||||||
//LOG_DEBUG(LOG_FILTER_MAPS, "Switch object {} from grid[{}, {}] {}", obj->GetGUID().ToString(), cell.data.Part.grid_x, cell.data.Part.grid_y, on);
|
|
||||||
MapGridType* grid = GetMapGrid(cell.GridX(), cell.GridY());
|
|
||||||
ASSERT(grid);
|
|
||||||
|
|
||||||
obj->RemoveFromGrid(); //This step is not really necessary but we want to do ASSERT in remove/add
|
|
||||||
|
|
||||||
if (on)
|
|
||||||
{
|
|
||||||
grid->AddWorldObject(cell.CellX(), cell.CellY(), obj);
|
|
||||||
AddWorldObject(obj);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
grid->AddGridObject(cell.CellX(), cell.CellY(), obj);
|
|
||||||
RemoveWorldObject(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void Map::DeleteFromWorld(T* obj)
|
void Map::DeleteFromWorld(T* obj)
|
||||||
{
|
{
|
||||||
@@ -1108,7 +1033,7 @@ void Map::UnloadAll()
|
|||||||
|
|
||||||
_transports.clear();
|
_transports.clear();
|
||||||
|
|
||||||
for (auto& cellCorpsePair : _corpsesByCell)
|
for (auto& cellCorpsePair : _corpsesByGrid)
|
||||||
{
|
{
|
||||||
for (Corpse* corpse : cellCorpsePair.second)
|
for (Corpse* corpse : cellCorpsePair.second)
|
||||||
{
|
{
|
||||||
@@ -1118,7 +1043,7 @@ void Map::UnloadAll()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_corpsesByCell.clear();
|
_corpsesByGrid.clear();
|
||||||
_corpsesByPlayer.clear();
|
_corpsesByPlayer.clear();
|
||||||
_corpseBones.clear();
|
_corpseBones.clear();
|
||||||
}
|
}
|
||||||
@@ -1849,49 +1774,8 @@ void Map::AddObjectToRemoveList(WorldObject* obj)
|
|||||||
//LOG_DEBUG("maps", "Object ({}) added to removing list.", obj->GetGUID().ToString());
|
//LOG_DEBUG("maps", "Object ({}) added to removing list.", obj->GetGUID().ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Map::AddObjectToSwitchList(WorldObject* obj, bool on)
|
|
||||||
{
|
|
||||||
ASSERT(obj->GetMapId() == GetId() && obj->GetInstanceId() == GetInstanceId());
|
|
||||||
// i_objectsToSwitch is iterated only in Map::RemoveAllObjectsInRemoveList() and it uses
|
|
||||||
// the contained objects only if IsCreature() , so we can return in all other cases
|
|
||||||
if (!obj->IsCreature() && !obj->IsGameObject())
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::map<WorldObject*, bool>::iterator itr = i_objectsToSwitch.find(obj);
|
|
||||||
if (itr == i_objectsToSwitch.end())
|
|
||||||
i_objectsToSwitch.insert(itr, std::make_pair(obj, on));
|
|
||||||
else if (itr->second != on)
|
|
||||||
i_objectsToSwitch.erase(itr);
|
|
||||||
else
|
|
||||||
ABORT();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Map::RemoveAllObjectsInRemoveList()
|
void Map::RemoveAllObjectsInRemoveList()
|
||||||
{
|
{
|
||||||
while (!i_objectsToSwitch.empty())
|
|
||||||
{
|
|
||||||
std::map<WorldObject*, bool>::iterator itr = i_objectsToSwitch.begin();
|
|
||||||
WorldObject* obj = itr->first;
|
|
||||||
bool on = itr->second;
|
|
||||||
i_objectsToSwitch.erase(itr);
|
|
||||||
|
|
||||||
if (!obj->IsPermanentWorldObject())
|
|
||||||
{
|
|
||||||
switch (obj->GetTypeId())
|
|
||||||
{
|
|
||||||
case TYPEID_UNIT:
|
|
||||||
SwitchGridContainers<Creature>(obj->ToCreature(), on);
|
|
||||||
break;
|
|
||||||
case TYPEID_GAMEOBJECT:
|
|
||||||
SwitchGridContainers<GameObject>(obj->ToGameObject(), on);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//LOG_DEBUG("maps", "Object remover 1 check.");
|
|
||||||
while (!i_objectsToRemove.empty())
|
while (!i_objectsToRemove.empty())
|
||||||
{
|
{
|
||||||
std::unordered_set<WorldObject*>::iterator itr = i_objectsToRemove.begin();
|
std::unordered_set<WorldObject*>::iterator itr = i_objectsToRemove.begin();
|
||||||
@@ -1929,8 +1813,6 @@ void Map::RemoveAllObjectsInRemoveList()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//LOG_DEBUG("maps", "Object remover 2 check.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Map::GetPlayersCountExceptGMs() const
|
uint32 Map::GetPlayersCountExceptGMs() const
|
||||||
@@ -1972,6 +1854,12 @@ void Map::AddToActive(GameObject* d)
|
|||||||
AddToActiveHelper(d);
|
AddToActiveHelper(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void Map::AddToActive(Corpse* /*c*/)
|
||||||
|
{
|
||||||
|
// do nothing for corpses
|
||||||
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void Map::RemoveFromActive(T* obj)
|
void Map::RemoveFromActive(T* obj)
|
||||||
{
|
{
|
||||||
@@ -2791,7 +2679,8 @@ void Map::AddCorpse(Corpse* corpse)
|
|||||||
{
|
{
|
||||||
corpse->SetMap(this);
|
corpse->SetMap(this);
|
||||||
|
|
||||||
_corpsesByCell[corpse->GetCellCoord().GetId()].insert(corpse);
|
GridCoord const gridCoord = Acore::ComputeGridCoord(corpse->GetPositionX(), corpse->GetPositionY());
|
||||||
|
_corpsesByGrid[gridCoord.GetId()].insert(corpse);
|
||||||
if (corpse->GetType() != CORPSE_BONES)
|
if (corpse->GetType() != CORPSE_BONES)
|
||||||
_corpsesByPlayer[corpse->GetOwnerGUID()] = corpse;
|
_corpsesByPlayer[corpse->GetOwnerGUID()] = corpse;
|
||||||
else
|
else
|
||||||
@@ -2801,6 +2690,7 @@ void Map::AddCorpse(Corpse* corpse)
|
|||||||
void Map::RemoveCorpse(Corpse* corpse)
|
void Map::RemoveCorpse(Corpse* corpse)
|
||||||
{
|
{
|
||||||
ASSERT(corpse);
|
ASSERT(corpse);
|
||||||
|
GridCoord const gridCoord = Acore::ComputeGridCoord(corpse->GetPositionX(), corpse->GetPositionY());
|
||||||
|
|
||||||
corpse->DestroyForNearbyPlayers();
|
corpse->DestroyForNearbyPlayers();
|
||||||
if (corpse->IsInGrid())
|
if (corpse->IsInGrid())
|
||||||
@@ -2811,7 +2701,7 @@ void Map::RemoveCorpse(Corpse* corpse)
|
|||||||
corpse->ResetMap();
|
corpse->ResetMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
_corpsesByCell[corpse->GetCellCoord().GetId()].erase(corpse);
|
_corpsesByGrid[gridCoord.GetId()].erase(corpse);
|
||||||
if (corpse->GetType() != CORPSE_BONES)
|
if (corpse->GetType() != CORPSE_BONES)
|
||||||
_corpsesByPlayer.erase(corpse->GetOwnerGUID());
|
_corpsesByPlayer.erase(corpse->GetOwnerGUID());
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -306,7 +306,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AddObjectToRemoveList(WorldObject* obj);
|
void AddObjectToRemoveList(WorldObject* obj);
|
||||||
void AddObjectToSwitchList(WorldObject* obj, bool on);
|
|
||||||
virtual void DelayedUpdate(const uint32 diff);
|
virtual void DelayedUpdate(const uint32 diff);
|
||||||
|
|
||||||
void resetMarkedCells() { marked_cells.reset(); }
|
void resetMarkedCells() { marked_cells.reset(); }
|
||||||
@@ -336,7 +335,6 @@ public:
|
|||||||
template<class T>
|
template<class T>
|
||||||
void RemoveFromActive(T* obj);
|
void RemoveFromActive(T* obj);
|
||||||
|
|
||||||
template<class T> void SwitchGridContainers(T* obj, bool on);
|
|
||||||
CreatureGroupHolderType CreatureGroupHolder;
|
CreatureGroupHolderType CreatureGroupHolder;
|
||||||
|
|
||||||
void UpdateIteratorBack(Player* player);
|
void UpdateIteratorBack(Player* player);
|
||||||
@@ -361,10 +359,10 @@ public:
|
|||||||
typedef std::unordered_multimap<ObjectGuid::LowType, GameObject*> GameObjectBySpawnIdContainer;
|
typedef std::unordered_multimap<ObjectGuid::LowType, GameObject*> GameObjectBySpawnIdContainer;
|
||||||
GameObjectBySpawnIdContainer& GetGameObjectBySpawnIdStore() { return _gameobjectBySpawnIdStore; }
|
GameObjectBySpawnIdContainer& GetGameObjectBySpawnIdStore() { return _gameobjectBySpawnIdStore; }
|
||||||
|
|
||||||
[[nodiscard]] std::unordered_set<Corpse*> const* GetCorpsesInCell(uint32 cellId) const
|
[[nodiscard]] std::unordered_set<Corpse*> const* GetCorpsesInGrid(uint32 gridId) const
|
||||||
{
|
{
|
||||||
auto itr = _corpsesByCell.find(cellId);
|
auto itr = _corpsesByGrid.find(gridId);
|
||||||
if (itr != _corpsesByCell.end())
|
if (itr != _corpsesByGrid.end())
|
||||||
return &itr->second;
|
return &itr->second;
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -577,7 +575,6 @@ private:
|
|||||||
|
|
||||||
bool i_scriptLock;
|
bool i_scriptLock;
|
||||||
std::unordered_set<WorldObject*> i_objectsToRemove;
|
std::unordered_set<WorldObject*> i_objectsToRemove;
|
||||||
std::map<WorldObject*, bool> i_objectsToSwitch;
|
|
||||||
std::unordered_set<WorldObject*> i_worldObjects;
|
std::unordered_set<WorldObject*> i_worldObjects;
|
||||||
|
|
||||||
typedef std::multimap<time_t, ScriptAction> ScriptScheduleMap;
|
typedef std::multimap<time_t, ScriptAction> ScriptScheduleMap;
|
||||||
@@ -634,7 +631,7 @@ private:
|
|||||||
MapStoredObjectTypesContainer _objectsStore;
|
MapStoredObjectTypesContainer _objectsStore;
|
||||||
CreatureBySpawnIdContainer _creatureBySpawnIdStore;
|
CreatureBySpawnIdContainer _creatureBySpawnIdStore;
|
||||||
GameObjectBySpawnIdContainer _gameobjectBySpawnIdStore;
|
GameObjectBySpawnIdContainer _gameobjectBySpawnIdStore;
|
||||||
std::unordered_map<uint32/*cellId*/, std::unordered_set<Corpse*>> _corpsesByCell;
|
std::unordered_map<uint32/*gridId*/, std::unordered_set<Corpse*>> _corpsesByGrid;
|
||||||
std::unordered_map<ObjectGuid, Corpse*> _corpsesByPlayer;
|
std::unordered_map<ObjectGuid, Corpse*> _corpsesByPlayer;
|
||||||
std::unordered_set<Corpse*> _corpseBones;
|
std::unordered_set<Corpse*> _corpseBones;
|
||||||
|
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ Map::EnterState MapMgr::PlayerCannotEnter(uint32 mapid, Player* player, bool log
|
|||||||
{
|
{
|
||||||
uint32 destInstId = sInstanceSaveMgr->PlayerGetDestinationInstanceId(player, mapid, targetDifficulty);
|
uint32 destInstId = sInstanceSaveMgr->PlayerGetDestinationInstanceId(player, mapid, targetDifficulty);
|
||||||
if (destInstId)
|
if (destInstId)
|
||||||
if (Map* boundMap = sMapMgr->FindMap(mapid, destInstId))
|
if (Map* boundMap = FindMap(mapid, destInstId))
|
||||||
if (Map::EnterState denyReason = boundMap->CannotEnter(player, loginCheck))
|
if (Map::EnterState denyReason = boundMap->CannotEnter(player, loginCheck))
|
||||||
return denyReason;
|
return denyReason;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,9 @@
|
|||||||
#include "MapUpdater.h"
|
#include "MapUpdater.h"
|
||||||
#include "DatabaseEnv.h"
|
#include "DatabaseEnv.h"
|
||||||
#include "LFGMgr.h"
|
#include "LFGMgr.h"
|
||||||
|
#include "Log.h"
|
||||||
#include "Map.h"
|
#include "Map.h"
|
||||||
|
#include "MapMgr.h"
|
||||||
#include "Metric.h"
|
#include "Metric.h"
|
||||||
|
|
||||||
class UpdateRequest
|
class UpdateRequest
|
||||||
@@ -52,6 +54,27 @@ private:
|
|||||||
uint32 s_diff;
|
uint32 s_diff;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MapPreloadRequest : public UpdateRequest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MapPreloadRequest(uint32 mapId, MapUpdater& updater)
|
||||||
|
: _mapId(mapId), _updater(updater)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void call() override
|
||||||
|
{
|
||||||
|
Map* map = sMapMgr->CreateBaseMap(_mapId);
|
||||||
|
LOG_INFO("server.loading", ">> Loading All Grids For Map {} ({})", map->GetId(), map->GetMapName());
|
||||||
|
map->LoadAllGrids();
|
||||||
|
_updater.update_finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32 _mapId;
|
||||||
|
MapUpdater& _updater;
|
||||||
|
};
|
||||||
|
|
||||||
class LFGUpdateRequest : public UpdateRequest
|
class LFGUpdateRequest : public UpdateRequest
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -120,6 +143,11 @@ void MapUpdater::schedule_update(Map& map, uint32 diff, uint32 s_diff)
|
|||||||
schedule_task(new MapUpdateRequest(map, *this, diff, s_diff));
|
schedule_task(new MapUpdateRequest(map, *this, diff, s_diff));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MapUpdater::schedule_map_preload(uint32 mapid)
|
||||||
|
{
|
||||||
|
schedule_task(new MapPreloadRequest(mapid, *this));
|
||||||
|
}
|
||||||
|
|
||||||
void MapUpdater::schedule_lfg_update(uint32 diff)
|
void MapUpdater::schedule_lfg_update(uint32 diff)
|
||||||
{
|
{
|
||||||
schedule_task(new LFGUpdateRequest(*this, diff));
|
schedule_task(new LFGUpdateRequest(*this, diff));
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public:
|
|||||||
|
|
||||||
void schedule_task(UpdateRequest* request);
|
void schedule_task(UpdateRequest* request);
|
||||||
void schedule_update(Map& map, uint32 diff, uint32 s_diff);
|
void schedule_update(Map& map, uint32 diff, uint32 s_diff);
|
||||||
|
void schedule_map_preload(uint32 mapid);
|
||||||
void schedule_lfg_update(uint32 diff);
|
void schedule_lfg_update(uint32 diff);
|
||||||
void wait();
|
void wait();
|
||||||
void activate(std::size_t num_threads);
|
void activate(std::size_t num_threads);
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ GraveyardStruct const* Graveyard::GetDefaultGraveyard(TeamId teamId)
|
|||||||
ALLIANCE_GRAVEYARD = 4, // Westfall
|
ALLIANCE_GRAVEYARD = 4, // Westfall
|
||||||
};
|
};
|
||||||
|
|
||||||
return sGraveyard->GetGraveyard(teamId == TEAM_HORDE ? HORDE_GRAVEYARD : ALLIANCE_GRAVEYARD);
|
return GetGraveyard(teamId == TEAM_HORDE ? HORDE_GRAVEYARD : ALLIANCE_GRAVEYARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
GraveyardStruct const* Graveyard::GetClosestGraveyard(Player* player, TeamId teamId, bool nearCorpse)
|
GraveyardStruct const* Graveyard::GetClosestGraveyard(Player* player, TeamId teamId, bool nearCorpse)
|
||||||
@@ -100,7 +100,7 @@ GraveyardStruct const* Graveyard::GetClosestGraveyard(Player* player, TeamId tea
|
|||||||
sScriptMgr->OnPlayerBeforeChooseGraveyard(player, teamId, nearCorpse, graveyardOverride);
|
sScriptMgr->OnPlayerBeforeChooseGraveyard(player, teamId, nearCorpse, graveyardOverride);
|
||||||
if (graveyardOverride)
|
if (graveyardOverride)
|
||||||
{
|
{
|
||||||
return sGraveyard->GetGraveyard(graveyardOverride);
|
return GetGraveyard(graveyardOverride);
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldLocation loc = player->GetWorldLocation();
|
WorldLocation loc = player->GetWorldLocation();
|
||||||
@@ -187,7 +187,7 @@ GraveyardStruct const* Graveyard::GetClosestGraveyard(uint32 mapId, float x, flo
|
|||||||
for (; range.first != range.second; ++range.first)
|
for (; range.first != range.second; ++range.first)
|
||||||
{
|
{
|
||||||
GraveyardData const& graveyardLink = range.first->second;
|
GraveyardData const& graveyardLink = range.first->second;
|
||||||
GraveyardStruct const* entry = sGraveyard->GetGraveyard(graveyardLink.safeLocId);
|
GraveyardStruct const* entry = GetGraveyard(graveyardLink.safeLocId);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Table `graveyard_zone` has record for not existing `game_graveyard` table {}, skipped.", graveyardLink.safeLocId);
|
LOG_ERROR("sql.sql", "Table `graveyard_zone` has record for not existing `game_graveyard` table {}, skipped.", graveyardLink.safeLocId);
|
||||||
@@ -393,7 +393,7 @@ void Graveyard::LoadGraveyardZones()
|
|||||||
uint32 team = fields[2].Get<uint16>();
|
uint32 team = fields[2].Get<uint16>();
|
||||||
TeamId teamId = team == 0 ? TEAM_NEUTRAL : (team == ALLIANCE ? TEAM_ALLIANCE : TEAM_HORDE);
|
TeamId teamId = team == 0 ? TEAM_NEUTRAL : (team == ALLIANCE ? TEAM_ALLIANCE : TEAM_HORDE);
|
||||||
|
|
||||||
GraveyardStruct const* entry = sGraveyard->GetGraveyard(safeLocId);
|
GraveyardStruct const* entry = GetGraveyard(safeLocId);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Table `graveyard_zone` has a record for not existing `game_graveyard` table {}, skipped.", safeLocId);
|
LOG_ERROR("sql.sql", "Table `graveyard_zone` has a record for not existing `game_graveyard` table {}, skipped.", safeLocId);
|
||||||
|
|||||||
@@ -217,7 +217,11 @@ enum AcoreStrings
|
|||||||
LANG_INVALID_GAMEOBJECT_TYPE = 176,
|
LANG_INVALID_GAMEOBJECT_TYPE = 176,
|
||||||
LANG_GAMEOBJECT_DAMAGED = 177,
|
LANG_GAMEOBJECT_DAMAGED = 177,
|
||||||
LANG_GRID_POSITION = 178,
|
LANG_GRID_POSITION = 178,
|
||||||
// 179-185 used in other client versions
|
|
||||||
|
LANG_ACCOUNT_FLAGS_PINFO = 179,
|
||||||
|
|
||||||
|
// Free 180-185
|
||||||
|
|
||||||
LANG_TRANSPORT_POSITION = 186,
|
LANG_TRANSPORT_POSITION = 186,
|
||||||
LANG_PROFANITY_NAME = 187,
|
LANG_PROFANITY_NAME = 187,
|
||||||
LANG_2FA_SECRET_TOO_LONG = 188,
|
LANG_2FA_SECRET_TOO_LONG = 188,
|
||||||
|
|||||||
@@ -72,15 +72,27 @@ bool ChaseMovementGenerator<T>::DoUpdate(T* owner, uint32 time_diff)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
Creature* cOwner = owner->ToCreature();
|
Creature* cOwner = owner->ToCreature();
|
||||||
|
bool isStoppedBecauseOfCasting = cOwner && cOwner->IsMovementPreventedByCasting();
|
||||||
|
|
||||||
// the owner might be unable to move (rooted or casting), or we have lost the target, pause movement
|
// the owner might be unable to move (rooted or casting), or we have lost the target, pause movement
|
||||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || HasLostTarget(owner) || (cOwner && cOwner->IsMovementPreventedByCasting()))
|
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || HasLostTarget(owner) || isStoppedBecauseOfCasting)
|
||||||
{
|
{
|
||||||
owner->StopMoving();
|
owner->StopMoving();
|
||||||
_lastTargetPosition.reset();
|
_lastTargetPosition.reset();
|
||||||
if (cOwner)
|
if (cOwner)
|
||||||
{
|
{
|
||||||
cOwner->UpdateLeashExtensionTime();
|
if (isStoppedBecauseOfCasting)
|
||||||
|
{
|
||||||
|
// Don't reset leash timer if it's a spell like Shoot with a short cast time.
|
||||||
|
/// @todo: Research how it should actually work.
|
||||||
|
Spell *spell = cOwner->GetFirstCurrentCastingSpell();
|
||||||
|
bool spellHasLongCast = spell && spell->GetCastTime() > 1 * SECOND * IN_MILLISECONDS;
|
||||||
|
if (spellHasLongCast)
|
||||||
|
cOwner->UpdateLeashExtensionTime();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cOwner->UpdateLeashExtensionTime();
|
||||||
|
|
||||||
cOwner->SetCannotReachTarget();
|
cOwner->SetCannotReachTarget();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ bool WorldSessionFilter::Process(WorldPacket* packet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// WorldSession constructor
|
/// WorldSession constructor
|
||||||
WorldSession::WorldSession(uint32 id, std::string&& name, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion,
|
WorldSession::WorldSession(uint32 id, std::string&& name, uint32 accountFlags, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion,
|
||||||
time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter, bool skipQueue, uint32 TotalTime, bool isBot) :
|
time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter, bool skipQueue, uint32 TotalTime, bool isBot) :
|
||||||
m_muteTime(mute_time),
|
m_muteTime(mute_time),
|
||||||
m_timeOutTime(0),
|
m_timeOutTime(0),
|
||||||
@@ -116,6 +116,7 @@ WorldSession::WorldSession(uint32 id, std::string&& name, std::shared_ptr<WorldS
|
|||||||
_skipQueue(skipQueue),
|
_skipQueue(skipQueue),
|
||||||
_accountId(id),
|
_accountId(id),
|
||||||
_accountName(std::move(name)),
|
_accountName(std::move(name)),
|
||||||
|
_accountFlags(accountFlags),
|
||||||
m_expansion(expansion),
|
m_expansion(expansion),
|
||||||
m_total_time(TotalTime),
|
m_total_time(TotalTime),
|
||||||
_logoutTime(0),
|
_logoutTime(0),
|
||||||
@@ -182,6 +183,30 @@ WorldSession::~WorldSession()
|
|||||||
LoginDatabase.Execute("UPDATE account SET online = 0 WHERE id = {};", GetAccountId()); // One-time query
|
LoginDatabase.Execute("UPDATE account SET online = 0 WHERE id = {};", GetAccountId()); // One-time query
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WorldSession::UpdateAccountFlag(uint32 flag, bool remove /*= flase*/)
|
||||||
|
{
|
||||||
|
if (remove)
|
||||||
|
_accountFlags &= ~flag;
|
||||||
|
else
|
||||||
|
_accountFlags |= flag;
|
||||||
|
|
||||||
|
// Async update
|
||||||
|
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_SET_ACCOUNT_FLAG);
|
||||||
|
stmt->SetData(0, _accountFlags);
|
||||||
|
stmt->SetData(1, GetAccountId());
|
||||||
|
LoginDatabase.Execute(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldSession::ValidateAccountFlags()
|
||||||
|
{
|
||||||
|
bool hasGMFlag = HasAccountFlag(ACCOUNT_FLAG_GM);
|
||||||
|
|
||||||
|
if (IsGMAccount() && !hasGMFlag)
|
||||||
|
UpdateAccountFlag(ACCOUNT_FLAG_GM);
|
||||||
|
else if (hasGMFlag && !IsGMAccount())
|
||||||
|
UpdateAccountFlag(ACCOUNT_FLAG_GM, true);
|
||||||
|
}
|
||||||
|
|
||||||
bool WorldSession::IsGMAccount() const
|
bool WorldSession::IsGMAccount() const
|
||||||
{
|
{
|
||||||
return GetSecurity() >= SEC_GAMEMASTER;
|
return GetSecurity() >= SEC_GAMEMASTER;
|
||||||
|
|||||||
@@ -348,10 +348,14 @@ struct PacketCounter
|
|||||||
class WorldSession
|
class WorldSession
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WorldSession(uint32 id, std::string&& name, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale,
|
WorldSession(uint32 id, std::string&& name, uint32 accountFlags, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter, bool skipQueue, uint32 TotalTime, bool is_bot = false);
|
||||||
uint32 recruiter, bool isARecruiter, bool skipQueue, uint32 TotalTime, bool isBot = false);
|
|
||||||
~WorldSession();
|
~WorldSession();
|
||||||
|
|
||||||
|
uint32 GetAccountFlags() const { return _accountFlags; }
|
||||||
|
bool HasAccountFlag(uint32 flag) const { return (_accountFlags & flag) != 0; }
|
||||||
|
void UpdateAccountFlag(uint32 flag, bool remove = false);
|
||||||
|
void ValidateAccountFlags();
|
||||||
|
|
||||||
bool IsGMAccount() const;
|
bool IsGMAccount() const;
|
||||||
|
|
||||||
bool PlayerLoading() const { return m_playerLoading; }
|
bool PlayerLoading() const { return m_playerLoading; }
|
||||||
@@ -1188,6 +1192,7 @@ private:
|
|||||||
bool _skipQueue;
|
bool _skipQueue;
|
||||||
uint32 _accountId;
|
uint32 _accountId;
|
||||||
std::string _accountName;
|
std::string _accountName;
|
||||||
|
uint32 _accountFlags;
|
||||||
uint8 m_expansion;
|
uint8 m_expansion;
|
||||||
uint32 m_total_time;
|
uint32 m_total_time;
|
||||||
|
|
||||||
|
|||||||
@@ -698,8 +698,6 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<AuthSession> authSes
|
|||||||
|
|
||||||
LoginDatabase.Execute(stmt);
|
LoginDatabase.Execute(stmt);
|
||||||
|
|
||||||
AccountMgr::ValidateAccountFlags(account.Id, account.Flags, account.Security);
|
|
||||||
|
|
||||||
// At this point, we can safely hook a successful login
|
// At this point, we can safely hook a successful login
|
||||||
sScriptMgr->OnAccountLogin(account.Id);
|
sScriptMgr->OnAccountLogin(account.Id);
|
||||||
|
|
||||||
@@ -707,7 +705,7 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<AuthSession> authSes
|
|||||||
|
|
||||||
sScriptMgr->OnLastIpUpdate(account.Id, address);
|
sScriptMgr->OnLastIpUpdate(account.Id, address);
|
||||||
|
|
||||||
_worldSession = new WorldSession(account.Id, std::move(authSession->Account), shared_from_this(), account.Security,
|
_worldSession = new WorldSession(account.Id, std::move(authSession->Account), account.Flags, shared_from_this(), account.Security,
|
||||||
account.Expansion, account.MuteTime, account.Locale, account.Recruiter, account.IsRectuiter, account.Security ? true : false, account.TotalTime);
|
account.Expansion, account.MuteTime, account.Locale, account.Recruiter, account.IsRectuiter, account.Security ? true : false, account.TotalTime);
|
||||||
|
|
||||||
_worldSession->ReadAddonsInfo(authSession->AddonInfo);
|
_worldSession->ReadAddonsInfo(authSession->AddonInfo);
|
||||||
@@ -718,6 +716,8 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<AuthSession> authSes
|
|||||||
_worldSession->InitWarden(account.SessionKey, account.OS);
|
_worldSession->InitWarden(account.SessionKey, account.OS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_worldSession->ValidateAccountFlags();
|
||||||
|
|
||||||
sWorldSessionMgr->AddSession(_worldSession);
|
sWorldSessionMgr->AddSession(_worldSession);
|
||||||
|
|
||||||
AsyncRead();
|
AsyncRead();
|
||||||
|
|||||||
@@ -2238,21 +2238,15 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar
|
|||||||
if (isBouncingFar)
|
if (isBouncingFar)
|
||||||
searchRadius *= chainTargets;
|
searchRadius *= chainTargets;
|
||||||
|
|
||||||
|
WorldObject* chainSource = m_spellInfo->HasAttribute(SPELL_ATTR2_CHAIN_FROM_CASTER) ? m_caster : target;
|
||||||
std::list<WorldObject*> tempTargets;
|
std::list<WorldObject*> tempTargets;
|
||||||
SearchAreaTargets(tempTargets, searchRadius, target, m_caster, objectType, selectType, condList);
|
SearchAreaTargets(tempTargets, searchRadius, chainSource, m_caster, objectType, selectType, condList);
|
||||||
tempTargets.remove(target);
|
tempTargets.remove(target);
|
||||||
|
|
||||||
// remove targets which are always invalid for chain spells
|
// remove targets which are always invalid for chain spells
|
||||||
// for some spells allow only chain targets in front of caster (swipe for example)
|
// for some spells allow only chain targets in front of caster (swipe for example)
|
||||||
if (!isBouncingFar)
|
if (!isBouncingFar)
|
||||||
{
|
tempTargets.remove_if([this](WorldObject* target) { return !m_caster->HasInArc(static_cast<float>(M_PI), target); });
|
||||||
for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end();)
|
|
||||||
{
|
|
||||||
std::list<WorldObject*>::iterator checkItr = itr++;
|
|
||||||
if (!m_caster->HasInArc(static_cast<float>(M_PI), *checkItr))
|
|
||||||
tempTargets.erase(checkItr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (chainTargets)
|
while (chainTargets)
|
||||||
{
|
{
|
||||||
@@ -2267,7 +2261,7 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar
|
|||||||
if (Unit* unit = (*itr)->ToUnit())
|
if (Unit* unit = (*itr)->ToUnit())
|
||||||
{
|
{
|
||||||
uint32 deficit = unit->GetMaxHealth() - unit->GetHealth();
|
uint32 deficit = unit->GetMaxHealth() - unit->GetHealth();
|
||||||
if (deficit > maxHPDeficit && target->IsWithinDist(unit, jumpRadius) && target->IsWithinLOSInMap(unit, VMAP::ModelIgnoreFlags::M2))
|
if (deficit > maxHPDeficit && chainSource->IsWithinDist(unit, jumpRadius) && chainSource->IsWithinLOSInMap(unit, VMAP::ModelIgnoreFlags::M2))
|
||||||
{
|
{
|
||||||
foundItr = itr;
|
foundItr = itr;
|
||||||
maxHPDeficit = deficit;
|
maxHPDeficit = deficit;
|
||||||
@@ -2282,19 +2276,22 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar
|
|||||||
{
|
{
|
||||||
if (foundItr == tempTargets.end())
|
if (foundItr == tempTargets.end())
|
||||||
{
|
{
|
||||||
if ((!isBouncingFar || target->IsWithinDist(*itr, jumpRadius)) && target->IsWithinLOSInMap(*itr, VMAP::ModelIgnoreFlags::M2))
|
if ((!isBouncingFar || chainSource->IsWithinDist(*itr, jumpRadius)) && chainSource->IsWithinLOSInMap(*itr, VMAP::ModelIgnoreFlags::M2))
|
||||||
foundItr = itr;
|
foundItr = itr;
|
||||||
}
|
}
|
||||||
else if (target->GetDistanceOrder(*itr, *foundItr) && target->IsWithinLOSInMap(*itr, VMAP::ModelIgnoreFlags::M2))
|
else if (chainSource->GetDistanceOrder(*itr, *foundItr) && chainSource->IsWithinLOSInMap(*itr, VMAP::ModelIgnoreFlags::M2))
|
||||||
foundItr = itr;
|
foundItr = itr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// not found any valid target - chain ends
|
// not found any valid target - chain ends
|
||||||
if (foundItr == tempTargets.end())
|
if (foundItr == tempTargets.end())
|
||||||
break;
|
break;
|
||||||
target = *foundItr;
|
|
||||||
|
if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CHAIN_FROM_CASTER))
|
||||||
|
chainSource = *foundItr;
|
||||||
|
|
||||||
|
targets.push_back(*foundItr);
|
||||||
tempTargets.erase(foundItr);
|
tempTargets.erase(foundItr);
|
||||||
targets.push_back(target);
|
|
||||||
--chainTargets;
|
--chainTargets;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7112,7 +7109,7 @@ SpellCastResult Spell::CheckRange(bool strict)
|
|||||||
if (range_type == SPELL_RANGE_MELEE)
|
if (range_type == SPELL_RANGE_MELEE)
|
||||||
{
|
{
|
||||||
float real_max_range = max_range;
|
float real_max_range = max_range;
|
||||||
if (!m_caster->IsCreature() && m_caster->isMoving() && target->isMoving() && !m_caster->IsWalking() && !target->IsWalking())
|
if (!m_caster->IsCreature() && m_caster->HasLeewayMovement() && target->HasLeewayMovement())
|
||||||
real_max_range -= MIN_MELEE_REACH; // Because of lag, we can not check too strictly here (is only used if both caster and target are moving)
|
real_max_range -= MIN_MELEE_REACH; // Because of lag, we can not check too strictly here (is only used if both caster and target are moving)
|
||||||
else
|
else
|
||||||
real_max_range -= 2 * MIN_MELEE_REACH;
|
real_max_range -= 2 * MIN_MELEE_REACH;
|
||||||
@@ -7129,7 +7126,7 @@ SpellCastResult Spell::CheckRange(bool strict)
|
|||||||
return SPELL_FAILED_TOO_CLOSE;
|
return SPELL_FAILED_TOO_CLOSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_caster->IsPlayer() && (m_spellInfo->FacingCasterFlags & SPELL_FACING_FLAG_INFRONT) && !m_caster->HasInArc(static_cast<float>(M_PI), target))
|
if (m_caster->IsPlayer() && (m_spellInfo->FacingCasterFlags & SPELL_FACING_FLAG_INFRONT) && !m_caster->HasInArc(static_cast<float>(M_PI), target) && !m_caster->IsWithinBoundaryRadius(target))
|
||||||
return SPELL_FAILED_UNIT_NOT_INFRONT;
|
return SPELL_FAILED_UNIT_NOT_INFRONT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9040,7 +9037,7 @@ namespace Acore
|
|||||||
case TARGET_CHECK_PARTY:
|
case TARGET_CHECK_PARTY:
|
||||||
if (unitTarget->IsTotem())
|
if (unitTarget->IsTotem())
|
||||||
return false;
|
return false;
|
||||||
if (unitTarget->IsGuardian())
|
if (unitTarget->IsGuardian() && !unitTarget->IsControllableGuardian())
|
||||||
return false;
|
return false;
|
||||||
if (!_caster->_IsValidAssistTarget(unitTarget, _spellInfo))
|
if (!_caster->_IsValidAssistTarget(unitTarget, _spellInfo))
|
||||||
return false;
|
return false;
|
||||||
@@ -9054,7 +9051,7 @@ namespace Acore
|
|||||||
case TARGET_CHECK_RAID:
|
case TARGET_CHECK_RAID:
|
||||||
if (unitTarget->IsTotem())
|
if (unitTarget->IsTotem())
|
||||||
return false;
|
return false;
|
||||||
if (unitTarget->IsGuardian())
|
if (unitTarget->IsGuardian() && !unitTarget->IsControllableGuardian())
|
||||||
return false;
|
return false;
|
||||||
if (!_caster->_IsValidAssistTarget(unitTarget, _spellInfo))
|
if (!_caster->_IsValidAssistTarget(unitTarget, _spellInfo))
|
||||||
return false;
|
return false;
|
||||||
@@ -9132,7 +9129,7 @@ namespace Acore
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!_caster->isInFront(target, _coneAngle))
|
if (!_caster->IsWithinBoundaryRadius(target->ToUnit()) && !_caster->isInFront(target, _coneAngle))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return WorldObjectSpellAreaTargetCheck::operator ()(target);
|
return WorldObjectSpellAreaTargetCheck::operator ()(target);
|
||||||
|
|||||||
@@ -2731,7 +2731,7 @@ void Spell::EffectAddFarsight(SpellEffIndex effIndex)
|
|||||||
// Remove old farsight if exist
|
// Remove old farsight if exist
|
||||||
bool updateViewerVisibility = m_caster->RemoveDynObject(m_spellInfo->Id);
|
bool updateViewerVisibility = m_caster->RemoveDynObject(m_spellInfo->Id);
|
||||||
|
|
||||||
DynamicObject* dynObj = new DynamicObject(true);
|
DynamicObject* dynObj = new DynamicObject(false);
|
||||||
if (!dynObj->CreateDynamicObject(m_caster->GetMap()->GenerateLowGuid<HighGuid::DynamicObject>(), m_caster, m_spellInfo->Id, *destTarget, radius, DYNAMIC_OBJECT_FARSIGHT_FOCUS))
|
if (!dynObj->CreateDynamicObject(m_caster->GetMap()->GenerateLowGuid<HighGuid::DynamicObject>(), m_caster, m_spellInfo->Id, *destTarget, radius, DYNAMIC_OBJECT_FARSIGHT_FOCUS))
|
||||||
{
|
{
|
||||||
delete dynObj;
|
delete dynObj;
|
||||||
|
|||||||
@@ -592,6 +592,12 @@ void SpellMgr::LoadSpellInfoCorrections()
|
|||||||
spellInfo->AttributesEx3 &= ~SPELL_ATTR3_SUPPRESS_CASTER_PROCS;
|
spellInfo->AttributesEx3 &= ~SPELL_ATTR3_SUPPRESS_CASTER_PROCS;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Vindication
|
||||||
|
ApplySpellFix({ 67, 26017}, [](SpellInfo* spellInfo)
|
||||||
|
{
|
||||||
|
spellInfo->Effects[EFFECT_0].MiscValue = 0;
|
||||||
|
});
|
||||||
|
|
||||||
// Arcane Missiles
|
// Arcane Missiles
|
||||||
ApplySpellFix({ 5143, 5144, 5145, 8416, 8417, 10211, 10212, 25345, 27075, 38699, 38704, 42843, 42846 }, [](SpellInfo* spellInfo)
|
ApplySpellFix({ 5143, 5144, 5145, 8416, 8417, 10211, 10212, 25345, 27075, 38699, 38704, 42843, 42846 }, [](SpellInfo* spellInfo)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1614,7 +1614,7 @@ void SpellMgr::LoadSpellTargetPositions()
|
|||||||
}
|
}
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
if (!sSpellMgr->GetSpellTargetPosition(i))
|
if (!GetSpellTargetPosition(i))
|
||||||
LOG_DEBUG("spells.aura", "Spell (ID: {}) does not have record in `spell_target_position`", i);
|
LOG_DEBUG("spells.aura", "Spell (ID: {}) does not have record in `spell_target_position`", i);
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
@@ -2348,7 +2348,7 @@ void SpellMgr::LoadPetLevelupSpellMap()
|
|||||||
LOG_INFO("server.loading", " ");
|
LOG_INFO("server.loading", " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadPetDefaultSpells_helper(CreatureTemplate const* cInfo, PetDefaultSpellsEntry& petDefSpells)
|
static bool LoadPetDefaultSpells_helper(CreatureTemplate const* cInfo, PetDefaultSpellsEntry& petDefSpells)
|
||||||
{
|
{
|
||||||
// skip empty list;
|
// skip empty list;
|
||||||
bool have_spell = false;
|
bool have_spell = false;
|
||||||
@@ -3448,9 +3448,9 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
|
|||||||
|
|
||||||
spellInfo->_InitializeExplicitTargetMask();
|
spellInfo->_InitializeExplicitTargetMask();
|
||||||
|
|
||||||
if (sSpellMgr->HasSpellCooldownOverride(spellInfo->Id))
|
if (HasSpellCooldownOverride(spellInfo->Id))
|
||||||
{
|
{
|
||||||
SpellCooldownOverride spellOverride = sSpellMgr->GetSpellCooldownOverride(spellInfo->Id);
|
SpellCooldownOverride spellOverride = GetSpellCooldownOverride(spellInfo->Id);
|
||||||
|
|
||||||
if (spellInfo->RecoveryTime != spellOverride.RecoveryTime)
|
if (spellInfo->RecoveryTime != spellOverride.RecoveryTime)
|
||||||
{
|
{
|
||||||
@@ -3497,7 +3497,7 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
|
|||||||
case SPELL_AURA_PERIODIC_TRIGGER_SPELL:
|
case SPELL_AURA_PERIODIC_TRIGGER_SPELL:
|
||||||
case SPELL_AURA_PERIODIC_TRIGGER_SPELL_FROM_CLIENT:
|
case SPELL_AURA_PERIODIC_TRIGGER_SPELL_FROM_CLIENT:
|
||||||
case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE:
|
case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE:
|
||||||
if (SpellInfo const* triggerSpell = sSpellMgr->GetSpellInfo(spellInfo->Effects[j].TriggerSpell))
|
if (SpellInfo const* triggerSpell = GetSpellInfo(spellInfo->Effects[j].TriggerSpell))
|
||||||
{
|
{
|
||||||
overrideAttr = true;
|
overrideAttr = true;
|
||||||
if (triggerSpell->AttributesCu & SPELL_ATTR0_CU_BINARY_SPELL)
|
if (triggerSpell->AttributesCu & SPELL_ATTR0_CU_BINARY_SPELL)
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ void TicketMgr::ResetTickets()
|
|||||||
{
|
{
|
||||||
uint32 ticketId = itr->second->GetId();
|
uint32 ticketId = itr->second->GetId();
|
||||||
++itr;
|
++itr;
|
||||||
sTicketMgr->RemoveTicket(ticketId);
|
RemoveTicket(ticketId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
++itr;
|
++itr;
|
||||||
|
|||||||
@@ -218,10 +218,10 @@ void World::LoadConfigSettings(bool reload)
|
|||||||
|
|
||||||
//visibility on continents
|
//visibility on continents
|
||||||
_maxVisibleDistanceOnContinents = sConfigMgr->GetOption<float>("Visibility.Distance.Continents", DEFAULT_VISIBILITY_DISTANCE);
|
_maxVisibleDistanceOnContinents = sConfigMgr->GetOption<float>("Visibility.Distance.Continents", DEFAULT_VISIBILITY_DISTANCE);
|
||||||
if (_maxVisibleDistanceOnContinents < 45 * sWorld->getRate(RATE_CREATURE_AGGRO))
|
if (_maxVisibleDistanceOnContinents < 45 * getRate(RATE_CREATURE_AGGRO))
|
||||||
{
|
{
|
||||||
LOG_ERROR("server.loading", "Visibility.Distance.Continents can't be less max aggro radius {}", 45 * sWorld->getRate(RATE_CREATURE_AGGRO));
|
LOG_ERROR("server.loading", "Visibility.Distance.Continents can't be less max aggro radius {}", 45 * getRate(RATE_CREATURE_AGGRO));
|
||||||
_maxVisibleDistanceOnContinents = 45 * sWorld->getRate(RATE_CREATURE_AGGRO);
|
_maxVisibleDistanceOnContinents = 45 * getRate(RATE_CREATURE_AGGRO);
|
||||||
}
|
}
|
||||||
else if (_maxVisibleDistanceOnContinents > MAX_VISIBILITY_DISTANCE)
|
else if (_maxVisibleDistanceOnContinents > MAX_VISIBILITY_DISTANCE)
|
||||||
{
|
{
|
||||||
@@ -231,10 +231,10 @@ void World::LoadConfigSettings(bool reload)
|
|||||||
|
|
||||||
//visibility in instances
|
//visibility in instances
|
||||||
_maxVisibleDistanceInInstances = sConfigMgr->GetOption<float>("Visibility.Distance.Instances", DEFAULT_VISIBILITY_INSTANCE);
|
_maxVisibleDistanceInInstances = sConfigMgr->GetOption<float>("Visibility.Distance.Instances", DEFAULT_VISIBILITY_INSTANCE);
|
||||||
if (_maxVisibleDistanceInInstances < 45 * sWorld->getRate(RATE_CREATURE_AGGRO))
|
if (_maxVisibleDistanceInInstances < 45 * getRate(RATE_CREATURE_AGGRO))
|
||||||
{
|
{
|
||||||
LOG_ERROR("server.loading", "Visibility.Distance.Instances can't be less max aggro radius {}", 45 * sWorld->getRate(RATE_CREATURE_AGGRO));
|
LOG_ERROR("server.loading", "Visibility.Distance.Instances can't be less max aggro radius {}", 45 * getRate(RATE_CREATURE_AGGRO));
|
||||||
_maxVisibleDistanceInInstances = 45 * sWorld->getRate(RATE_CREATURE_AGGRO);
|
_maxVisibleDistanceInInstances = 45 * getRate(RATE_CREATURE_AGGRO);
|
||||||
}
|
}
|
||||||
else if (_maxVisibleDistanceInInstances > MAX_VISIBILITY_DISTANCE)
|
else if (_maxVisibleDistanceInInstances > MAX_VISIBILITY_DISTANCE)
|
||||||
{
|
{
|
||||||
@@ -244,10 +244,10 @@ void World::LoadConfigSettings(bool reload)
|
|||||||
|
|
||||||
//visibility in BG/Arenas
|
//visibility in BG/Arenas
|
||||||
_maxVisibleDistanceInBGArenas = sConfigMgr->GetOption<float>("Visibility.Distance.BGArenas", DEFAULT_VISIBILITY_BGARENAS);
|
_maxVisibleDistanceInBGArenas = sConfigMgr->GetOption<float>("Visibility.Distance.BGArenas", DEFAULT_VISIBILITY_BGARENAS);
|
||||||
if (_maxVisibleDistanceInBGArenas < 45 * sWorld->getRate(RATE_CREATURE_AGGRO))
|
if (_maxVisibleDistanceInBGArenas < 45 * getRate(RATE_CREATURE_AGGRO))
|
||||||
{
|
{
|
||||||
LOG_ERROR("server.loading", "Visibility.Distance.BGArenas can't be less max aggro radius {}", 45 * sWorld->getRate(RATE_CREATURE_AGGRO));
|
LOG_ERROR("server.loading", "Visibility.Distance.BGArenas can't be less max aggro radius {}", 45 * getRate(RATE_CREATURE_AGGRO));
|
||||||
_maxVisibleDistanceInBGArenas = 45 * sWorld->getRate(RATE_CREATURE_AGGRO);
|
_maxVisibleDistanceInBGArenas = 45 * getRate(RATE_CREATURE_AGGRO);
|
||||||
}
|
}
|
||||||
else if (_maxVisibleDistanceInBGArenas > MAX_VISIBILITY_DISTANCE)
|
else if (_maxVisibleDistanceInBGArenas > MAX_VISIBILITY_DISTANCE)
|
||||||
{
|
{
|
||||||
@@ -1001,7 +1001,7 @@ void World::SetInitialWorldSettings()
|
|||||||
|
|
||||||
sScriptMgr->OnBeforeWorldInitialized();
|
sScriptMgr->OnBeforeWorldInitialized();
|
||||||
|
|
||||||
if (sWorld->getBoolConfig(CONFIG_PRELOAD_ALL_NON_INSTANCED_MAP_GRIDS))
|
if (getBoolConfig(CONFIG_PRELOAD_ALL_NON_INSTANCED_MAP_GRIDS))
|
||||||
{
|
{
|
||||||
LOG_INFO("server.loading", "Loading All Grids For All Non-Instanced Maps...");
|
LOG_INFO("server.loading", "Loading All Grids For All Non-Instanced Maps...");
|
||||||
|
|
||||||
@@ -1011,15 +1011,23 @@ void World::SetInitialWorldSettings()
|
|||||||
|
|
||||||
if (mapEntry && !mapEntry->Instanceable())
|
if (mapEntry && !mapEntry->Instanceable())
|
||||||
{
|
{
|
||||||
Map* map = sMapMgr->CreateBaseMap(mapEntry->MapID);
|
if (sMapMgr->GetMapUpdater()->activated())
|
||||||
|
sMapMgr->GetMapUpdater()->schedule_map_preload(mapEntry->MapID);
|
||||||
if (map)
|
else
|
||||||
{
|
{
|
||||||
LOG_INFO("server.loading", ">> Loading All Grids For Map {}", map->GetId());
|
Map* map = sMapMgr->CreateBaseMap(mapEntry->MapID);
|
||||||
map->LoadAllGrids();
|
|
||||||
|
if (map)
|
||||||
|
{
|
||||||
|
LOG_INFO("server.loading", ">> Loading All Grids For Map {}", map->GetId());
|
||||||
|
map->LoadAllGrids();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sMapMgr->GetMapUpdater()->activated())
|
||||||
|
sMapMgr->GetMapUpdater()->wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 startupDuration = GetMSTimeDiffToNow(startupBegin);
|
uint32 startupDuration = GetMSTimeDiffToNow(startupBegin);
|
||||||
@@ -1191,7 +1199,7 @@ void World::Update(uint32 diff)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <li> Clean logs table
|
/// <li> Clean logs table
|
||||||
if (sWorld->getIntConfig(CONFIG_LOGDB_CLEARTIME) > 0) // if not enabled, ignore the timer
|
if (getIntConfig(CONFIG_LOGDB_CLEARTIME) > 0) // if not enabled, ignore the timer
|
||||||
{
|
{
|
||||||
if (_timers[WUPDATE_CLEANDB].Passed())
|
if (_timers[WUPDATE_CLEANDB].Passed())
|
||||||
{
|
{
|
||||||
@@ -1200,7 +1208,7 @@ void World::Update(uint32 diff)
|
|||||||
_timers[WUPDATE_CLEANDB].Reset();
|
_timers[WUPDATE_CLEANDB].Reset();
|
||||||
|
|
||||||
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_OLD_LOGS);
|
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_OLD_LOGS);
|
||||||
stmt->SetData(0, sWorld->getIntConfig(CONFIG_LOGDB_CLEARTIME));
|
stmt->SetData(0, getIntConfig(CONFIG_LOGDB_CLEARTIME));
|
||||||
stmt->SetData(1, uint32(currentGameTime.count()));
|
stmt->SetData(1, uint32(currentGameTime.count()));
|
||||||
LoginDatabase.Execute(stmt);
|
LoginDatabase.Execute(stmt);
|
||||||
}
|
}
|
||||||
@@ -1217,7 +1225,7 @@ void World::Update(uint32 diff)
|
|||||||
sMapMgr->Update(diff);
|
sMapMgr->Update(diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sWorld->getBoolConfig(CONFIG_AUTOBROADCAST))
|
if (getBoolConfig(CONFIG_AUTOBROADCAST))
|
||||||
{
|
{
|
||||||
if (_timers[WUPDATE_AUTOBROADCAST].Passed())
|
if (_timers[WUPDATE_AUTOBROADCAST].Passed())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ void WorldConfig::BuildConfigCache()
|
|||||||
SetConfigValue<uint32>(CONFIG_INTERVAL_SAVE, "PlayerSaveInterval", 900000);
|
SetConfigValue<uint32>(CONFIG_INTERVAL_SAVE, "PlayerSaveInterval", 900000);
|
||||||
SetConfigValue<uint32>(CONFIG_INTERVAL_DISCONNECT_TOLERANCE, "DisconnectToleranceInterval", 0);
|
SetConfigValue<uint32>(CONFIG_INTERVAL_DISCONNECT_TOLERANCE, "DisconnectToleranceInterval", 0);
|
||||||
SetConfigValue<bool>(CONFIG_STATS_SAVE_ONLY_ON_LOGOUT, "PlayerSave.Stats.SaveOnlyOnLogout", true);
|
SetConfigValue<bool>(CONFIG_STATS_SAVE_ONLY_ON_LOGOUT, "PlayerSave.Stats.SaveOnlyOnLogout", true);
|
||||||
|
SetConfigValue<bool>(CONFIG_VALIDATE_SKILL_LEARNED_BY_SPELLS, "ValidateSkillLearnedBySpells", true);
|
||||||
|
|
||||||
SetConfigValue<uint32>(CONFIG_MIN_LEVEL_STAT_SAVE, "PlayerSave.Stats.MinLevel", 0, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value < MAX_LEVEL; }, "< MAX_LEVEL");
|
SetConfigValue<uint32>(CONFIG_MIN_LEVEL_STAT_SAVE, "PlayerSave.Stats.MinLevel", 0, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value < MAX_LEVEL; }, "< MAX_LEVEL");
|
||||||
|
|
||||||
@@ -406,6 +407,7 @@ void WorldConfig::BuildConfigCache()
|
|||||||
SetConfigValue<float>(CONFIG_LISTEN_RANGE_TEXTEMOTE, "ListenRange.TextEmote", 40.0f);
|
SetConfigValue<float>(CONFIG_LISTEN_RANGE_TEXTEMOTE, "ListenRange.TextEmote", 40.0f);
|
||||||
SetConfigValue<float>(CONFIG_LISTEN_RANGE_YELL, "ListenRange.Yell", 300.0f);
|
SetConfigValue<float>(CONFIG_LISTEN_RANGE_YELL, "ListenRange.Yell", 300.0f);
|
||||||
|
|
||||||
|
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_PREP_TIME, "Battleground.PrepTime", 120);
|
||||||
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_OVERRIDE_LOWLEVELS_MINPLAYERS, "Battleground.Override.LowLevels.MinPlayers", 0);
|
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_OVERRIDE_LOWLEVELS_MINPLAYERS, "Battleground.Override.LowLevels.MinPlayers", 0);
|
||||||
SetConfigValue<bool>(CONFIG_BATTLEGROUND_DISABLE_QUEST_SHARE_IN_BG, "Battleground.DisableQuestShareInBG", false);
|
SetConfigValue<bool>(CONFIG_BATTLEGROUND_DISABLE_QUEST_SHARE_IN_BG, "Battleground.DisableQuestShareInBG", false);
|
||||||
SetConfigValue<bool>(CONFIG_BATTLEGROUND_DISABLE_READY_CHECK_IN_BG, "Battleground.DisableReadyCheckInBG", false);
|
SetConfigValue<bool>(CONFIG_BATTLEGROUND_DISABLE_READY_CHECK_IN_BG, "Battleground.DisableReadyCheckInBG", false);
|
||||||
@@ -436,6 +438,7 @@ void WorldConfig::BuildConfigCache()
|
|||||||
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_ALTERAC_REP_ONBOSSDEATH, "Battleground.Alterac.ReputationOnBossDeath", 350);
|
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_ALTERAC_REP_ONBOSSDEATH, "Battleground.Alterac.ReputationOnBossDeath", 350);
|
||||||
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_EYEOFTHESTORM_CAPTUREPOINTS, "Battleground.EyeOfTheStorm.CapturePoints", 1600);
|
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_EYEOFTHESTORM_CAPTUREPOINTS, "Battleground.EyeOfTheStorm.CapturePoints", 1600);
|
||||||
|
|
||||||
|
SetConfigValue<uint32>(CONFIG_ARENA_PREP_TIME, "Arena.PrepTime", 60);
|
||||||
SetConfigValue<uint32>(CONFIG_ARENA_MAX_RATING_DIFFERENCE, "Arena.MaxRatingDifference", 150);
|
SetConfigValue<uint32>(CONFIG_ARENA_MAX_RATING_DIFFERENCE, "Arena.MaxRatingDifference", 150);
|
||||||
SetConfigValue<uint32>(CONFIG_ARENA_RATING_DISCARD_TIMER, "Arena.RatingDiscardTimer", 600000);
|
SetConfigValue<uint32>(CONFIG_ARENA_RATING_DISCARD_TIMER, "Arena.RatingDiscardTimer", 600000);
|
||||||
SetConfigValue<uint32>(CONFIG_ARENA_PREV_OPPONENTS_DISCARD_TIMER, "Arena.PreviousOpponentsDiscardTimer", 120000);
|
SetConfigValue<uint32>(CONFIG_ARENA_PREV_OPPONENTS_DISCARD_TIMER, "Arena.PreviousOpponentsDiscardTimer", 120000);
|
||||||
|
|||||||
@@ -254,6 +254,7 @@ enum ServerConfigs
|
|||||||
CONFIG_DEATH_SICKNESS_LEVEL,
|
CONFIG_DEATH_SICKNESS_LEVEL,
|
||||||
CONFIG_INSTANT_LOGOUT,
|
CONFIG_INSTANT_LOGOUT,
|
||||||
CONFIG_DISABLE_BREATHING,
|
CONFIG_DISABLE_BREATHING,
|
||||||
|
CONFIG_BATTLEGROUND_PREP_TIME,
|
||||||
CONFIG_BATTLEGROUND_OVERRIDE_LOWLEVELS_MINPLAYERS,
|
CONFIG_BATTLEGROUND_OVERRIDE_LOWLEVELS_MINPLAYERS,
|
||||||
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_SPAM_DELAY,
|
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_SPAM_DELAY,
|
||||||
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_TIMER,
|
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_TIMER,
|
||||||
@@ -274,6 +275,7 @@ enum ServerConfigs
|
|||||||
CONFIG_BATTLEGROUND_ALTERAC_REP_ONBOSSDEATH,
|
CONFIG_BATTLEGROUND_ALTERAC_REP_ONBOSSDEATH,
|
||||||
CONFIG_BATTLEGROUND_EYEOFTHESTORM_CAPTUREPOINTS,
|
CONFIG_BATTLEGROUND_EYEOFTHESTORM_CAPTUREPOINTS,
|
||||||
CONFIG_WINTERGRASP_ENABLE,
|
CONFIG_WINTERGRASP_ENABLE,
|
||||||
|
CONFIG_ARENA_PREP_TIME,
|
||||||
CONFIG_ARENA_MAX_RATING_DIFFERENCE,
|
CONFIG_ARENA_MAX_RATING_DIFFERENCE,
|
||||||
CONFIG_ARENA_RATING_DISCARD_TIMER,
|
CONFIG_ARENA_RATING_DISCARD_TIMER,
|
||||||
CONFIG_ARENA_PREV_OPPONENTS_DISCARD_TIMER,
|
CONFIG_ARENA_PREV_OPPONENTS_DISCARD_TIMER,
|
||||||
@@ -472,6 +474,7 @@ enum ServerConfigs
|
|||||||
RATE_MISS_CHANCE_MULTIPLIER_TARGET_CREATURE,
|
RATE_MISS_CHANCE_MULTIPLIER_TARGET_CREATURE,
|
||||||
RATE_MISS_CHANCE_MULTIPLIER_TARGET_PLAYER,
|
RATE_MISS_CHANCE_MULTIPLIER_TARGET_PLAYER,
|
||||||
CONFIG_NEW_CHAR_STRING,
|
CONFIG_NEW_CHAR_STRING,
|
||||||
|
CONFIG_VALIDATE_SKILL_LEARNED_BY_SPELLS,
|
||||||
|
|
||||||
MAX_NUM_SERVER_CONFIGS
|
MAX_NUM_SERVER_CONFIGS
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -47,7 +47,9 @@ WorldState::~WorldState()
|
|||||||
|
|
||||||
void WorldState::Load()
|
void WorldState::Load()
|
||||||
{
|
{
|
||||||
QueryResult result = CharacterDatabase.Query("SELECT Id, Data FROM world_state");
|
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_WORLD_STATE);
|
||||||
|
PreparedQueryResult result = CharacterDatabase.Query(stmt);
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
@@ -205,8 +207,10 @@ void WorldState::Save(WorldStateSaveIds saveId)
|
|||||||
|
|
||||||
void WorldState::SaveHelper(std::string& stringToSave, WorldStateSaveIds saveId)
|
void WorldState::SaveHelper(std::string& stringToSave, WorldStateSaveIds saveId)
|
||||||
{
|
{
|
||||||
CharacterDatabase.Execute("DELETE FROM world_state WHERE Id='{}'", saveId);
|
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_WORLD_STATE);
|
||||||
CharacterDatabase.Execute("INSERT INTO world_state(Id,Data) VALUES('{}','{}')", saveId, stringToSave.data());
|
stmt->SetData(0, saveId);
|
||||||
|
stmt->SetData(1, stringToSave);
|
||||||
|
CharacterDatabase.Execute(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorldState::IsConditionFulfilled(uint32 conditionId, uint32 state) const
|
bool WorldState::IsConditionFulfilled(uint32 conditionId, uint32 state) const
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "CharacterCache.h"
|
#include "CharacterCache.h"
|
||||||
#include "Chat.h"
|
#include "Chat.h"
|
||||||
#include "CommandScript.h"
|
#include "CommandScript.h"
|
||||||
|
#include "Common.h"
|
||||||
#include "GameGraveyard.h"
|
#include "GameGraveyard.h"
|
||||||
#include "GameTime.h"
|
#include "GameTime.h"
|
||||||
#include "GridNotifiers.h"
|
#include "GridNotifiers.h"
|
||||||
@@ -57,6 +58,49 @@
|
|||||||
constexpr auto SPELL_STUCK = 7355;
|
constexpr auto SPELL_STUCK = 7355;
|
||||||
constexpr auto SPELL_FREEZE = 9454;
|
constexpr auto SPELL_FREEZE = 9454;
|
||||||
|
|
||||||
|
struct AccountFlagText
|
||||||
|
{
|
||||||
|
AccountFlag flag;
|
||||||
|
std::string text;
|
||||||
|
};
|
||||||
|
|
||||||
|
AccountFlagText const accountFlagText[MAX_ACCOUNT_FLAG] =
|
||||||
|
{
|
||||||
|
{ ACCOUNT_FLAG_GM, "ACCOUNT_FLAG_GM" },
|
||||||
|
{ ACCOUNT_FLAG_NOKICK, "ACCOUNT_FLAG_NOKICK" },
|
||||||
|
{ ACCOUNT_FLAG_COLLECTOR, "ACCOUNT_FLAG_COLLECTOR" },
|
||||||
|
{ ACCOUNT_FLAG_TRIAL, "ACCOUNT_FLAG_TRIAL" },
|
||||||
|
{ ACCOUNT_FLAG_CANCELLED, "ACCOUNT_FLAG_CANCELLED" },
|
||||||
|
{ ACCOUNT_FLAG_IGR, "ACCOUNT_FLAG_IGR" },
|
||||||
|
{ ACCOUNT_FLAG_WHOLESALER, "ACCOUNT_FLAG_WHOLESALER" },
|
||||||
|
{ ACCOUNT_FLAG_PRIVILEGED, "ACCOUNT_FLAG_PRIVILEGED" },
|
||||||
|
{ ACCOUNT_FLAG_EU_FORBID_ELV, "ACCOUNT_FLAG_EU_FORBID_ELV" },
|
||||||
|
{ ACCOUNT_FLAG_EU_FORBID_BILLING, "ACCOUNT_FLAG_EU_FORBID_BILLING" },
|
||||||
|
{ ACCOUNT_FLAG_RESTRICTED, "ACCOUNT_FLAG_RESTRICTED" },
|
||||||
|
{ ACCOUNT_FLAG_REFERRAL, "ACCOUNT_FLAG_REFERRAL" },
|
||||||
|
{ ACCOUNT_FLAG_BLIZZARD, "ACCOUNT_FLAG_BLIZZARD" },
|
||||||
|
{ ACCOUNT_FLAG_RECURRING_BILLING, "ACCOUNT_FLAG_RECURRING_BILLING" },
|
||||||
|
{ ACCOUNT_FLAG_NOELECTUP, "ACCOUNT_FLAG_NOELECTUP" },
|
||||||
|
{ ACCOUNT_FLAG_KR_CERTIFICATE, "ACCOUNT_FLAG_KR_CERTIFICATE" },
|
||||||
|
{ ACCOUNT_FLAG_EXPANSION_COLLECTOR, "ACCOUNT_FLAG_EXPANSION_COLLECTOR" },
|
||||||
|
{ ACCOUNT_FLAG_DISABLE_VOICE, "ACCOUNT_FLAG_DISABLE_VOICE" },
|
||||||
|
{ ACCOUNT_FLAG_DISABLE_VOICE_SPEAK, "ACCOUNT_FLAG_DISABLE_VOICE_SPEAK" },
|
||||||
|
{ ACCOUNT_FLAG_REFERRAL_RESURRECT, "ACCOUNT_FLAG_REFERRAL_RESURRECT" },
|
||||||
|
{ ACCOUNT_FLAG_EU_FORBID_CC, "ACCOUNT_FLAG_EU_FORBID_CC" },
|
||||||
|
{ ACCOUNT_FLAG_OPENBETA_DELL, "ACCOUNT_FLAG_OPENBETA_DELL" },
|
||||||
|
{ ACCOUNT_FLAG_PROPASS, "ACCOUNT_FLAG_PROPASS" },
|
||||||
|
{ ACCOUNT_FLAG_PROPASS_LOCK, "ACCOUNT_FLAG_PROPASS_LOCK" },
|
||||||
|
{ ACCOUNT_FLAG_PENDING_UPGRADE, "ACCOUNT_FLAG_PENDING_UPGRADE" },
|
||||||
|
{ ACCOUNT_FLAG_RETAIL_FROM_TRIAL, "ACCOUNT_FLAG_RETAIL_FROM_TRIAL" },
|
||||||
|
{ ACCOUNT_FLAG_EXPANSION2_COLLECTOR, "ACCOUNT_FLAG_EXPANSION2_COLLECTOR" },
|
||||||
|
{ ACCOUNT_FLAG_OVERMIND_LINKED, "ACCOUNT_FLAG_OVERMIND_LINKED" },
|
||||||
|
{ ACCOUNT_FLAG_DEMOS, "ACCOUNT_FLAG_DEMOS" },
|
||||||
|
{ ACCOUNT_FLAG_DEATH_KNIGHT_OK, "ACCOUNT_FLAG_DEATH_KNIGHT_OK" },
|
||||||
|
{ ACCOUNT_FLAG_S2_REQUIRE_IGR, "ACCOUNT_FLAG_S2_REQUIRE_IGR" },
|
||||||
|
{ ACCOUNT_FLAG_S2_TRIAL, "ACCOUNT_FLAG_S2_TRIAL" },
|
||||||
|
// { ACCOUNT_FLAG_S2_RESTRICTED, "ACCOUNT_FLAG_S2_RESTRICTED" }
|
||||||
|
};
|
||||||
|
|
||||||
std::string const GetLocalizeCreatureName(Creature* creature, LocaleConstant locale)
|
std::string const GetLocalizeCreatureName(Creature* creature, LocaleConstant locale)
|
||||||
{
|
{
|
||||||
auto creatureTemplate = sObjectMgr->GetCreatureTemplate(creature->GetEntry());
|
auto creatureTemplate = sObjectMgr->GetCreatureTemplate(creature->GetEntry());
|
||||||
@@ -2193,6 +2237,15 @@ public:
|
|||||||
// Output V. LANG_PINFO_ACC_ACCOUNT
|
// Output V. LANG_PINFO_ACC_ACCOUNT
|
||||||
handler->PSendSysMessage(LANG_PINFO_ACC_ACCOUNT, userName, accId, security);
|
handler->PSendSysMessage(LANG_PINFO_ACC_ACCOUNT, userName, accId, security);
|
||||||
|
|
||||||
|
if (playerTarget)
|
||||||
|
{
|
||||||
|
uint32 accountFlags = playerTarget->GetSession()->GetAccountFlags();
|
||||||
|
handler->PSendSysMessage(LANG_ACCOUNT_FLAGS_PINFO);
|
||||||
|
for (uint8 i = 0; i < MAX_ACCOUNT_FLAG; i++)
|
||||||
|
if (accountFlags & static_cast<uint32>(accountFlagText[i].flag))
|
||||||
|
handler->PSendSysMessage(LANG_SUBCMDS_LIST_ENTRY, accountFlagText[i].text);
|
||||||
|
}
|
||||||
|
|
||||||
// Output VI. LANG_PINFO_ACC_LASTLOGIN
|
// Output VI. LANG_PINFO_ACC_LASTLOGIN
|
||||||
handler->PSendSysMessage(LANG_PINFO_ACC_LASTLOGIN, lastLogin, failedLogins);
|
handler->PSendSysMessage(LANG_PINFO_ACC_LASTLOGIN, lastLogin, failedLogins);
|
||||||
|
|
||||||
|
|||||||
+1
@@ -692,6 +692,7 @@ public:
|
|||||||
// Start Event
|
// Start Event
|
||||||
Start(true, false);
|
Start(true, false);
|
||||||
SetDespawnAtEnd(false);
|
SetDespawnAtEnd(false);
|
||||||
|
SetDespawnAtFar(false);
|
||||||
|
|
||||||
ScheduleNextEvent(currentEvent, 9000);
|
ScheduleNextEvent(currentEvent, 9000);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -31,14 +31,7 @@ enum Spells
|
|||||||
SPELL_REMOVE_MUSHROOM_POWER = 57283,
|
SPELL_REMOVE_MUSHROOM_POWER = 57283,
|
||||||
|
|
||||||
// Mushroom
|
// Mushroom
|
||||||
SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS = 56648,
|
SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS = 56648
|
||||||
SPELL_POISONOUS_MUSHROOM_POISON_CLOUD = 57061,
|
|
||||||
SPELL_POISONOUS_MUSHROOM_VISUAL_AURA = 56741,
|
|
||||||
SPELL_POISONOUS_MUSHROOM_VISUAL_AREA = 61566, // Self
|
|
||||||
SPELL_HEALTHY_MUSHROOM_VISUAL_AURA = 56740,
|
|
||||||
SPELL_PUTRID_MUSHROOM = 31690,
|
|
||||||
SPELL_GROW = 57059,
|
|
||||||
SPELL_SHRINK = 31691,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Creatures
|
enum Creatures
|
||||||
@@ -94,13 +87,12 @@ Position const MushroomPositions[MAX_MUSHROOMS_COUNT] =
|
|||||||
|
|
||||||
struct boss_amanitar : public BossAI
|
struct boss_amanitar : public BossAI
|
||||||
{
|
{
|
||||||
boss_amanitar(Creature* creature) : BossAI(creature, DATA_AMANITAR), mushroomsSummoned(false) { }
|
boss_amanitar(Creature* creature) : BossAI(creature, DATA_AMANITAR) { }
|
||||||
|
|
||||||
void Reset() override
|
void Reset() override
|
||||||
{
|
{
|
||||||
_Reset();
|
_Reset();
|
||||||
_mushroomsDeque.clear();
|
_mushroomsDeque.clear();
|
||||||
mushroomsSummoned = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JustEngagedWith(Unit* /*attacker*/) override
|
void JustEngagedWith(Unit* /*attacker*/) override
|
||||||
@@ -110,7 +102,7 @@ struct boss_amanitar : public BossAI
|
|||||||
}, 10s, 15s);
|
}, 10s, 15s);
|
||||||
|
|
||||||
ScheduleTimedEvent(10s, 14s, [&] {
|
ScheduleTimedEvent(10s, 14s, [&] {
|
||||||
DoCastVictim(SPELL_BASH, false);
|
DoCastVictim(SPELL_BASH);
|
||||||
}, 15s, 20s);
|
}, 15s, 20s);
|
||||||
|
|
||||||
ScheduleTimedEvent(15s, 20s, [&] {
|
ScheduleTimedEvent(15s, 20s, [&] {
|
||||||
@@ -153,10 +145,10 @@ struct boss_amanitar : public BossAI
|
|||||||
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI);
|
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SummonedCreatureDies(Creature* summon, Unit* killer) override
|
void SummonedCreatureDespawn(Creature* summon) override
|
||||||
{
|
{
|
||||||
_mushroomsDeque.push_back(summon->GetPosition());
|
_mushroomsDeque.push_back(summon->GetPosition());
|
||||||
BossAI::SummonedCreatureDies(summon, killer);
|
BossAI::SummonedCreatureDespawn(summon);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnterEvadeMode(EvadeReason why) override
|
void EnterEvadeMode(EvadeReason why) override
|
||||||
@@ -167,7 +159,6 @@ struct boss_amanitar : public BossAI
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::deque<Position> _mushroomsDeque;
|
std::deque<Position> _mushroomsDeque;
|
||||||
bool mushroomsSummoned;
|
|
||||||
|
|
||||||
void SummonMushroom(Position const& pos)
|
void SummonMushroom(Position const& pos)
|
||||||
{
|
{
|
||||||
@@ -175,98 +166,6 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct npc_amanitar_mushrooms : public ScriptedAI
|
|
||||||
{
|
|
||||||
npc_amanitar_mushrooms(Creature* pCreature) : ScriptedAI(pCreature)
|
|
||||||
{
|
|
||||||
me->SetCombatMovement(false);
|
|
||||||
|
|
||||||
//TODO: this prolly needs to be done in database
|
|
||||||
pCreature->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
|
||||||
pCreature->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
|
||||||
pCreature->SetRegeneratingHealth(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disabled events
|
|
||||||
void JustEngagedWith(Unit* /*who*/) override {}
|
|
||||||
void AttackStart(Unit* /*victim*/) override {}
|
|
||||||
void EnterEvadeMode(EvadeReason /*why*/) override {}
|
|
||||||
|
|
||||||
void Reset() override
|
|
||||||
{
|
|
||||||
me->SetReactState(REACT_PASSIVE);
|
|
||||||
DoCastSelf(SPELL_PUTRID_MUSHROOM);
|
|
||||||
|
|
||||||
if (me->GetEntry() == NPC_POISONOUS_MUSHROOM)
|
|
||||||
{
|
|
||||||
DoCastSelf(SPELL_POISONOUS_MUSHROOM_VISUAL_AURA, true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DoCastSelf(SPELL_HEALTHY_MUSHROOM_VISUAL_AURA, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
events.ScheduleEvent(EVENT_GROW, 800ms);
|
|
||||||
|
|
||||||
if (me->GetEntry() == NPC_POISONOUS_MUSHROOM)
|
|
||||||
{
|
|
||||||
events.ScheduleEvent(EVENT_CHECK_PLAYER, 250ms);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
|
|
||||||
{
|
|
||||||
if (me->GetEntry() == NPC_HEALTHY_MUSHROOM && damage >= me->GetHealth())
|
|
||||||
{
|
|
||||||
DoCastSelf(SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
|
||||||
{
|
|
||||||
if (events.Empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
events.Update(diff);
|
|
||||||
while (uint32 const eventId = events.ExecuteEvent())
|
|
||||||
{
|
|
||||||
switch (eventId)
|
|
||||||
{
|
|
||||||
case EVENT_GROW:
|
|
||||||
{
|
|
||||||
DoCastSelf(SPELL_GROW);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case EVENT_CHECK_PLAYER:
|
|
||||||
{
|
|
||||||
if (Player* plr = me->SelectNearestPlayer(2.0f))
|
|
||||||
{
|
|
||||||
plr->RemoveAurasDueToSpell(SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS);
|
|
||||||
DoCastSelf(SPELL_POISONOUS_MUSHROOM_VISUAL_AREA);
|
|
||||||
DoCastSelf(SPELL_POISONOUS_MUSHROOM_POISON_CLOUD);
|
|
||||||
DoCastSelf(SPELL_SHRINK);
|
|
||||||
events.ScheduleEvent(EVENT_KILLSELF, 4s);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
events.Repeat(250ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case EVENT_KILLSELF:
|
|
||||||
{
|
|
||||||
me->DisappearAndDie();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
EventMap events;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 57283 Remove Mushroom Power
|
// 57283 Remove Mushroom Power
|
||||||
class spell_amanitar_remove_mushroom_power : public AuraScript
|
class spell_amanitar_remove_mushroom_power : public AuraScript
|
||||||
{
|
{
|
||||||
@@ -274,8 +173,7 @@ class spell_amanitar_remove_mushroom_power : public AuraScript
|
|||||||
|
|
||||||
void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||||
{
|
{
|
||||||
if (Unit* target = GetTarget())
|
GetTarget()->RemoveAurasDueToSpell(SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS);
|
||||||
target->RemoveAurasDueToSpell(SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Register() override
|
void Register() override
|
||||||
@@ -287,8 +185,5 @@ class spell_amanitar_remove_mushroom_power : public AuraScript
|
|||||||
void AddSC_boss_amanitar()
|
void AddSC_boss_amanitar()
|
||||||
{
|
{
|
||||||
RegisterAhnKahetCreatureAI(boss_amanitar);
|
RegisterAhnKahetCreatureAI(boss_amanitar);
|
||||||
RegisterAhnKahetCreatureAI(npc_amanitar_mushrooms);
|
|
||||||
|
|
||||||
// Spells
|
|
||||||
RegisterSpellScript(spell_amanitar_remove_mushroom_power);
|
RegisterSpellScript(spell_amanitar_remove_mushroom_power);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ enum Misc
|
|||||||
MAX_EMBRACE_DMG_H = 40000,
|
MAX_EMBRACE_DMG_H = 40000,
|
||||||
|
|
||||||
SUMMON_GROUP_TRIGGERS = 0,
|
SUMMON_GROUP_TRIGGERS = 0,
|
||||||
|
|
||||||
|
GROUP_COMBAT_ABILITIES = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Actions
|
enum Actions
|
||||||
@@ -64,15 +66,6 @@ enum Actions
|
|||||||
ACTION_SPHERE,
|
ACTION_SPHERE,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Event
|
|
||||||
{
|
|
||||||
EVENT_PRINCE_FLAME_SPHERES = 1,
|
|
||||||
EVENT_PRINCE_VANISH,
|
|
||||||
EVENT_PRINCE_BLOODTHIRST,
|
|
||||||
EVENT_PRINCE_VANISH_RUN,
|
|
||||||
EVENT_PRINCE_RESCHEDULE,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Yells
|
enum Yells
|
||||||
{
|
{
|
||||||
//SAY_SPHERE_ACTIVATED = 0,
|
//SAY_SPHERE_ACTIVATED = 0,
|
||||||
@@ -178,9 +171,12 @@ private:
|
|||||||
|
|
||||||
struct boss_taldaram : public BossAI
|
struct boss_taldaram : public BossAI
|
||||||
{
|
{
|
||||||
boss_taldaram(Creature* pCreature) : BossAI(pCreature, DATA_PRINCE_TALDARAM),
|
boss_taldaram(Creature* pCreature) : BossAI(pCreature, DATA_PRINCE_TALDARAM), vanishDamage(0)
|
||||||
vanishDamage(0)
|
|
||||||
{
|
{
|
||||||
|
scheduler.SetValidator([this]
|
||||||
|
{
|
||||||
|
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeAI() override
|
void InitializeAI() override
|
||||||
@@ -193,19 +189,16 @@ struct boss_taldaram : public BossAI
|
|||||||
me->SetImmuneToAll(true);
|
me->SetImmuneToAll(true);
|
||||||
me->SetDisableGravity(true);
|
me->SetDisableGravity(true);
|
||||||
me->SetHover(true);
|
me->SetHover(true);
|
||||||
|
|
||||||
if (!me->HasAura(SPELL_BEAM_VISUAL))
|
if (!me->HasAura(SPELL_BEAM_VISUAL))
|
||||||
{
|
|
||||||
DoCastSelf(SPELL_BEAM_VISUAL, true);
|
DoCastSelf(SPELL_BEAM_VISUAL, true);
|
||||||
}
|
|
||||||
|
|
||||||
me->SummonCreatureGroup(SUMMON_GROUP_TRIGGERS);
|
me->SummonCreatureGroup(SUMMON_GROUP_TRIGGERS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instance->GetPersistentData(DATA_TELDRAM_SPHERE1) == DONE && instance->GetPersistentData(DATA_TELDRAM_SPHERE2) == DONE)
|
if (instance->GetPersistentData(DATA_TELDRAM_SPHERE1) == DONE && instance->GetPersistentData(DATA_TELDRAM_SPHERE2) == DONE)
|
||||||
{
|
|
||||||
DoAction(ACTION_REMOVE_PRISON_AT_RESET);
|
DoAction(ACTION_REMOVE_PRISON_AT_RESET);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset() override
|
void Reset() override
|
||||||
@@ -213,7 +206,45 @@ struct boss_taldaram : public BossAI
|
|||||||
_Reset();
|
_Reset();
|
||||||
|
|
||||||
vanishDamage = 0;
|
vanishDamage = 0;
|
||||||
vanishTarget_GUID.Clear();
|
|
||||||
|
me->SetReactState(REACT_AGGRESSIVE);
|
||||||
|
|
||||||
|
ScheduleHealthCheckEvent({ 75, 50, 25 }, [&] {
|
||||||
|
scheduler.Schedule(1s, [this](TaskContext)
|
||||||
|
{
|
||||||
|
Talk(SAY_VANISH);
|
||||||
|
DoCastSelf(SPELL_VANISH);
|
||||||
|
me->SetReactState(REACT_PASSIVE);
|
||||||
|
me->GetMotionMaster()->Clear();
|
||||||
|
DoStopAttack();
|
||||||
|
scheduler.CancelGroup(GROUP_COMBAT_ABILITIES);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnAuraRemove(AuraApplication* auraApp, AuraRemoveMode mode) override
|
||||||
|
{
|
||||||
|
if (auraApp->GetBase()->GetId() == SPELL_VANISH && mode == AURA_REMOVE_BY_EXPIRE)
|
||||||
|
{
|
||||||
|
scheduler.Schedule(2500ms, [this](TaskContext)
|
||||||
|
{
|
||||||
|
if (Unit* vanishTarget = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
|
||||||
|
{
|
||||||
|
vanishDamage = 0;
|
||||||
|
DoCast(vanishTarget, SPELL_SHADOWSTEP);
|
||||||
|
DoCast(vanishTarget, SPELL_EMBRACE_OF_THE_VAMPYR);
|
||||||
|
}
|
||||||
|
|
||||||
|
me->m_Events.AddEventAtOffset([&] {
|
||||||
|
if (!scheduler.IsGroupScheduled(GROUP_COMBAT_ABILITIES))
|
||||||
|
{
|
||||||
|
ScheduleCombatEvents();
|
||||||
|
me->SetReactState(REACT_AGGRESSIVE);
|
||||||
|
me->ResumeChasingVictim();
|
||||||
|
}
|
||||||
|
}, 20s);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoAction(int32 action) override
|
void DoAction(int32 action) override
|
||||||
@@ -256,20 +287,20 @@ struct boss_taldaram : public BossAI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*school*/) override
|
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damageType, SpellSchoolMask school) override
|
||||||
{
|
{
|
||||||
if (vanishTarget_GUID)
|
BossAI::DamageTaken(attacker, damage, damageType, school);
|
||||||
|
|
||||||
|
if (me->FindCurrentSpellBySpellId(SPELL_EMBRACE_OF_THE_VAMPYR))
|
||||||
{
|
{
|
||||||
if (me->FindCurrentSpellBySpellId(SPELL_EMBRACE_OF_THE_VAMPYR))
|
vanishDamage += damage;
|
||||||
|
if (vanishDamage >= DUNGEON_MODE<uint32>(MAX_EMBRACE_DMG, MAX_EMBRACE_DMG_H))
|
||||||
{
|
{
|
||||||
vanishDamage += damage;
|
ScheduleCombatEvents();
|
||||||
if (vanishDamage >= DUNGEON_MODE<uint32>(MAX_EMBRACE_DMG, MAX_EMBRACE_DMG_H))
|
me->CastStop();
|
||||||
{
|
me->ResumeChasingVictim();
|
||||||
ScheduleCombatEvents();
|
me->SetReactState(REACT_AGGRESSIVE);
|
||||||
me->CastStop();
|
vanishDamage = 0;
|
||||||
vanishTarget_GUID.Clear();
|
|
||||||
vanishDamage = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -283,17 +314,9 @@ struct boss_taldaram : public BossAI
|
|||||||
void KilledUnit(Unit* victim) override
|
void KilledUnit(Unit* victim) override
|
||||||
{
|
{
|
||||||
if (!victim->IsPlayer())
|
if (!victim->IsPlayer())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
Talk(SAY_SLAY);
|
Talk(SAY_SLAY);
|
||||||
|
|
||||||
if (vanishTarget_GUID && victim->GetGUID() == vanishTarget_GUID)
|
|
||||||
{
|
|
||||||
vanishTarget_GUID.Clear();
|
|
||||||
vanishDamage = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JustEngagedWith(Unit* /*who*/) override
|
void JustEngagedWith(Unit* /*who*/) override
|
||||||
@@ -309,9 +332,7 @@ struct boss_taldaram : public BossAI
|
|||||||
void SpellHitTarget(Unit* /*target*/, SpellInfo const* spellInfo) override
|
void SpellHitTarget(Unit* /*target*/, SpellInfo const* spellInfo) override
|
||||||
{
|
{
|
||||||
if (spellInfo->Id == SPELL_CONJURE_FLAME_SPHERE)
|
if (spellInfo->Id == SPELL_CONJURE_FLAME_SPHERE)
|
||||||
{
|
|
||||||
summons.DoAction(ACTION_SPHERE);
|
summons.DoAction(ACTION_SPHERE);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JustSummoned(Creature* summon) override
|
void JustSummoned(Creature* summon) override
|
||||||
@@ -324,9 +345,7 @@ struct boss_taldaram : public BossAI
|
|||||||
case NPC_FLAME_SPHERE_3:
|
case NPC_FLAME_SPHERE_3:
|
||||||
{
|
{
|
||||||
if (npc_taldaram_flamesphere* summonAI = dynamic_cast<npc_taldaram_flamesphere*>(summon->AI()))
|
if (npc_taldaram_flamesphere* summonAI = dynamic_cast<npc_taldaram_flamesphere*>(summon->AI()))
|
||||||
{
|
|
||||||
summonAI->SetVictimPos(victimSperePos);
|
summonAI->SetVictimPos(victimSperePos);
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -338,130 +357,27 @@ struct boss_taldaram : public BossAI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
|
||||||
{
|
|
||||||
if (!UpdateVictim())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
events.Update(diff);
|
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (uint32 const eventId = events.ExecuteEvent())
|
|
||||||
{
|
|
||||||
switch (eventId)
|
|
||||||
{
|
|
||||||
case EVENT_PRINCE_BLOODTHIRST:
|
|
||||||
{
|
|
||||||
DoCastVictim(SPELL_BLOODTHIRST);
|
|
||||||
events.Repeat(10s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case EVENT_PRINCE_FLAME_SPHERES:
|
|
||||||
{
|
|
||||||
if (Unit* victim = me->GetVictim())
|
|
||||||
{
|
|
||||||
DoCast(victim, SPELL_CONJURE_FLAME_SPHERE);
|
|
||||||
victimSperePos = victim->GetPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!events.GetNextEventTime(EVENT_PRINCE_VANISH))
|
|
||||||
{
|
|
||||||
events.RescheduleEvent(EVENT_PRINCE_VANISH, 14s);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Make sure that Vanish won't get triggered at same time as sphere summon
|
|
||||||
events.DelayEvents(4s);
|
|
||||||
}
|
|
||||||
|
|
||||||
events.Repeat(15s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case EVENT_PRINCE_VANISH:
|
|
||||||
{
|
|
||||||
//Count alive players
|
|
||||||
uint8 count = 0;
|
|
||||||
std::list<HostileReference*> const t_list = me->GetThreatMgr().GetThreatList();
|
|
||||||
if (!t_list.empty())
|
|
||||||
{
|
|
||||||
for (HostileReference const* reference : t_list)
|
|
||||||
{
|
|
||||||
if (reference)
|
|
||||||
{
|
|
||||||
Unit const* pTarget = ObjectAccessor::GetUnit(*me, reference->getUnitGuid());
|
|
||||||
if (pTarget && pTarget->IsPlayer() && pTarget->IsAlive())
|
|
||||||
{
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// He only vanishes if there are 3 or more alive players
|
|
||||||
if (count > 2)
|
|
||||||
{
|
|
||||||
Talk(SAY_VANISH);
|
|
||||||
DoCastSelf(SPELL_VANISH, false);
|
|
||||||
if (Unit* pEmbraceTarget = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
|
||||||
{
|
|
||||||
vanishTarget_GUID = pEmbraceTarget->GetGUID();
|
|
||||||
}
|
|
||||||
|
|
||||||
events.CancelEvent(EVENT_PRINCE_FLAME_SPHERES);
|
|
||||||
events.CancelEvent(EVENT_PRINCE_BLOODTHIRST);
|
|
||||||
events.ScheduleEvent(EVENT_PRINCE_VANISH_RUN, 2499ms);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case EVENT_PRINCE_VANISH_RUN:
|
|
||||||
{
|
|
||||||
if (Unit* _vanishTarget = ObjectAccessor::GetUnit(*me, vanishTarget_GUID))
|
|
||||||
{
|
|
||||||
vanishDamage = 0;
|
|
||||||
DoCast(_vanishTarget, SPELL_SHADOWSTEP);
|
|
||||||
me->CastSpell(_vanishTarget, SPELL_EMBRACE_OF_THE_VAMPYR, false);
|
|
||||||
me->RemoveAura(SPELL_VANISH);
|
|
||||||
}
|
|
||||||
|
|
||||||
events.ScheduleEvent(EVENT_PRINCE_RESCHEDULE, 20s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case EVENT_PRINCE_RESCHEDULE:
|
|
||||||
{
|
|
||||||
ScheduleCombatEvents();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (me->IsVisible())
|
|
||||||
{
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Position victimSperePos;
|
Position victimSperePos;
|
||||||
ObjectGuid vanishTarget_GUID;
|
|
||||||
uint32 vanishDamage;
|
uint32 vanishDamage;
|
||||||
|
|
||||||
void ScheduleCombatEvents()
|
void ScheduleCombatEvents()
|
||||||
{
|
{
|
||||||
events.Reset();
|
scheduler.Schedule(10s, GROUP_COMBAT_ABILITIES, [this](TaskContext context)
|
||||||
events.RescheduleEvent(EVENT_PRINCE_FLAME_SPHERES, 10s);
|
{
|
||||||
events.RescheduleEvent(EVENT_PRINCE_BLOODTHIRST, 10s);
|
DoCastVictim(SPELL_BLOODTHIRST);
|
||||||
vanishTarget_GUID.Clear();
|
context.Repeat(15s);
|
||||||
|
}).Schedule(10s, GROUP_COMBAT_ABILITIES, [this](TaskContext context)
|
||||||
|
{
|
||||||
|
if (Unit* victim = me->GetVictim())
|
||||||
|
{
|
||||||
|
DoCast(victim, SPELL_CONJURE_FLAME_SPHERE);
|
||||||
|
victimSperePos = victim->GetPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Repeat(15s);
|
||||||
|
});
|
||||||
|
|
||||||
vanishDamage = 0;
|
vanishDamage = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -74,6 +74,9 @@ enum DeathKnightSpells
|
|||||||
SPELL_DK_UNHOLY_PRESENCE_TRIGGERED = 49772,
|
SPELL_DK_UNHOLY_PRESENCE_TRIGGERED = 49772,
|
||||||
SPELL_DK_WILL_OF_THE_NECROPOLIS_TALENT_R1 = 49189,
|
SPELL_DK_WILL_OF_THE_NECROPOLIS_TALENT_R1 = 49189,
|
||||||
SPELL_DK_WILL_OF_THE_NECROPOLIS_AURA_R1 = 52284,
|
SPELL_DK_WILL_OF_THE_NECROPOLIS_AURA_R1 = 52284,
|
||||||
|
SPELL_DK_ICY_TALONS_TALENT_R1 = 50880,
|
||||||
|
SPELL_DK_CRYPT_FEVER_R1 = 50508,
|
||||||
|
SPELL_DK_EBON_PLAGUE_R1 = 51726,
|
||||||
// Risen Ally
|
// Risen Ally
|
||||||
SPELL_DK_RAISE_ALLY = 46619,
|
SPELL_DK_RAISE_ALLY = 46619,
|
||||||
SPELL_DK_THRASH = 47480,
|
SPELL_DK_THRASH = 47480,
|
||||||
@@ -342,7 +345,7 @@ class spell_dk_death_and_decay_aura : public AuraScript
|
|||||||
if (GetCaster() && GetTarget())
|
if (GetCaster() && GetTarget())
|
||||||
{
|
{
|
||||||
int32 basePoints0 = aurEff->GetAmount();
|
int32 basePoints0 = aurEff->GetAmount();
|
||||||
GetCaster()->CastCustomSpell(GetTarget(), SPELL_DK_DEATH_AND_DECAY_TRIGGER, &basePoints0, nullptr, nullptr, true, 0, aurEff);
|
GetCaster()->CastCustomSpell(GetTarget(), SPELL_DK_DEATH_AND_DECAY_TRIGGER, &basePoints0, nullptr, nullptr, false, 0, aurEff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1746,7 +1749,8 @@ class spell_dk_pestilence : public SpellScript
|
|||||||
{
|
{
|
||||||
SPELL_DK_GLYPH_OF_DISEASE,
|
SPELL_DK_GLYPH_OF_DISEASE,
|
||||||
SPELL_DK_BLOOD_PLAGUE,
|
SPELL_DK_BLOOD_PLAGUE,
|
||||||
SPELL_DK_FROST_FEVER
|
SPELL_DK_FROST_FEVER,
|
||||||
|
SPELL_DK_ICY_TALONS_TALENT_R1
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1758,46 +1762,36 @@ class spell_dk_pestilence : public SpellScript
|
|||||||
if (!target)
|
if (!target)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (target != hitUnit || caster->GetAura(SPELL_DK_GLYPH_OF_DISEASE))
|
// Spread on others
|
||||||
|
if (target != hitUnit)
|
||||||
{
|
{
|
||||||
// xinef: checked in target selection
|
|
||||||
//if (!m_targets.GetUnitTarget()->IsWithinLOSInMap(unitTarget))
|
|
||||||
// return;
|
|
||||||
|
|
||||||
// And spread them on target
|
|
||||||
// Blood Plague
|
// Blood Plague
|
||||||
if (Aura* disOld = target->GetAura(SPELL_DK_BLOOD_PLAGUE, caster->GetGUID()))
|
if (target->GetAura(SPELL_DK_BLOOD_PLAGUE, caster->GetGUID()))
|
||||||
if (AuraEffect* effOld = disOld->GetEffect(EFFECT_0))
|
caster->CastSpell(hitUnit, SPELL_DK_BLOOD_PLAGUE, true);
|
||||||
{
|
|
||||||
float pctMods = effOld->GetPctMods();
|
|
||||||
float crit = effOld->GetCritChance();
|
|
||||||
caster->CastSpell(hitUnit, SPELL_DK_BLOOD_PLAGUE, true);
|
|
||||||
|
|
||||||
if (Aura* disNew = hitUnit->GetAura(SPELL_DK_BLOOD_PLAGUE, caster->GetGUID()))
|
|
||||||
if (AuraEffect* effNew = disNew->GetEffect(EFFECT_0))
|
|
||||||
{
|
|
||||||
effNew->SetPctMods(pctMods);
|
|
||||||
effNew->SetCritChance(crit);
|
|
||||||
effNew->SetAmount(effNew->CalculateAmount(effNew->GetCaster()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Frost Fever
|
// Frost Fever
|
||||||
if (Aura* disOld = target->GetAura(SPELL_DK_FROST_FEVER, caster->GetGUID()))
|
if (target->GetAura(SPELL_DK_FROST_FEVER, caster->GetGUID()))
|
||||||
if (AuraEffect* effOld = disOld->GetEffect(EFFECT_0))
|
caster->CastSpell(hitUnit, SPELL_DK_FROST_FEVER, true);
|
||||||
{
|
}
|
||||||
float pctMods = effOld->GetPctMods();
|
// Refresh on target
|
||||||
float crit = effOld->GetCritChance();
|
else if (caster->GetAura(SPELL_DK_GLYPH_OF_DISEASE))
|
||||||
caster->CastSpell(hitUnit, SPELL_DK_FROST_FEVER, true);
|
{
|
||||||
|
// Blood Plague
|
||||||
|
if (Aura* disease = target->GetAura(SPELL_DK_BLOOD_PLAGUE, caster->GetGUID()))
|
||||||
|
disease->RefreshDuration();
|
||||||
|
|
||||||
if (Aura* disNew = hitUnit->GetAura(SPELL_DK_FROST_FEVER, caster->GetGUID()))
|
// Frost Fever
|
||||||
if (AuraEffect* effNew = disNew->GetEffect(EFFECT_0))
|
if (Aura* disease = target->GetAura(SPELL_DK_FROST_FEVER, caster->GetGUID()))
|
||||||
{
|
{
|
||||||
effNew->SetPctMods(pctMods);
|
disease->RefreshDuration();
|
||||||
effNew->SetCritChance(crit);
|
if (Aura const* talons = caster->GetAuraOfRankedSpell(SPELL_DK_ICY_TALONS_TALENT_R1))
|
||||||
effNew->SetAmount(effNew->CalculateAmount(effNew->GetCaster()));
|
caster->CastSpell(caster, talons->GetSpellInfo()->Effects[EFFECT_0].TriggerSpell, true);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (Aura* disease = target->GetAuraOfRankedSpell(SPELL_DK_EBON_PLAGUE_R1, caster->GetGUID()))
|
||||||
|
disease->RefreshDuration();
|
||||||
|
else if (Aura* disease = target->GetAuraOfRankedSpell(SPELL_DK_CRYPT_FEVER_R1, caster->GetGUID()))
|
||||||
|
disease->RefreshDuration();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ enum DruidSpells
|
|||||||
SPELL_DRUID_ENRAGE = 5229,
|
SPELL_DRUID_ENRAGE = 5229,
|
||||||
SPELL_DRUID_ENRAGED_DEFENSE = 70725,
|
SPELL_DRUID_ENRAGED_DEFENSE = 70725,
|
||||||
SPELL_DRUID_ITEM_T10_FERAL_4P_BONUS = 70726,
|
SPELL_DRUID_ITEM_T10_FERAL_4P_BONUS = 70726,
|
||||||
|
SPELL_DRUID_MOONGLADE_2P_BONUS = 37286
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DruidIcons
|
enum DruidIcons
|
||||||
@@ -1194,6 +1195,60 @@ class spell_dru_moonkin_form_passive_proc : public AuraScript
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// -774 - Rejuvenation
|
||||||
|
class spell_dru_rejuvenation_moonglade_2_set : public AuraScript
|
||||||
|
{
|
||||||
|
PrepareAuraScript(spell_dru_rejuvenation_moonglade_2_set);
|
||||||
|
|
||||||
|
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||||
|
{
|
||||||
|
return ValidateSpellInfo({ SPELL_DRUID_MOONGLADE_2P_BONUS });
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Load() override
|
||||||
|
{
|
||||||
|
_casterGUID.Clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||||
|
{
|
||||||
|
if (Player* caster = ObjectAccessor::FindPlayer(GetCasterGUID()))
|
||||||
|
if (caster->HasAura(SPELL_DRUID_MOONGLADE_2P_BONUS))
|
||||||
|
{
|
||||||
|
Player* target = GetTarget()->ToPlayer();
|
||||||
|
if (!target)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_casterGUID = GetCasterGUID();
|
||||||
|
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_DRUID_MOONGLADE_2P_BONUS);
|
||||||
|
target->ApplyRatingMod(CR_DODGE, spellInfo->Effects[EFFECT_0].CalcValue(), true); // 35 rating
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||||
|
{
|
||||||
|
if (_casterGUID)
|
||||||
|
{
|
||||||
|
Player* target = GetTarget()->ToPlayer();
|
||||||
|
if (!target)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_DRUID_MOONGLADE_2P_BONUS);
|
||||||
|
target->ApplyRatingMod(CR_DODGE, spellInfo->Effects[EFFECT_0].CalcValue(), false); // 35 rating
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Register() override
|
||||||
|
{
|
||||||
|
AfterEffectApply += AuraEffectApplyFn(spell_dru_rejuvenation_moonglade_2_set::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_HEAL, AURA_EFFECT_HANDLE_REAL);
|
||||||
|
AfterEffectRemove += AuraEffectRemoveFn(spell_dru_rejuvenation_moonglade_2_set::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_HEAL, AURA_EFFECT_HANDLE_REAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ObjectGuid _casterGUID;
|
||||||
|
};
|
||||||
|
|
||||||
void AddSC_druid_spell_scripts()
|
void AddSC_druid_spell_scripts()
|
||||||
{
|
{
|
||||||
RegisterSpellScript(spell_dru_bear_form_passive);
|
RegisterSpellScript(spell_dru_bear_form_passive);
|
||||||
@@ -1229,4 +1284,5 @@ void AddSC_druid_spell_scripts()
|
|||||||
RegisterSpellScript(spell_dru_t10_restoration_4p_bonus);
|
RegisterSpellScript(spell_dru_t10_restoration_4p_bonus);
|
||||||
RegisterSpellScript(spell_dru_wild_growth);
|
RegisterSpellScript(spell_dru_wild_growth);
|
||||||
RegisterSpellScript(spell_dru_moonkin_form_passive_proc);
|
RegisterSpellScript(spell_dru_moonkin_form_passive_proc);
|
||||||
|
RegisterSpellScript(spell_dru_rejuvenation_moonglade_2_set);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -910,7 +910,7 @@ class spell_warr_heroic_strike : public SpellScript
|
|||||||
Unit* target = GetHitUnit();
|
Unit* target = GetHitUnit();
|
||||||
if (!target)
|
if (!target)
|
||||||
return;
|
return;
|
||||||
std::list<AuraEffect*> AuraEffectList = target->GetAuraEffectsByType(SPELL_AURA_MOD_DECREASE_SPEED);
|
Unit::AuraEffectList const& AuraEffectList = target->GetAuraEffectsByType(SPELL_AURA_MOD_DECREASE_SPEED);
|
||||||
bool bonusDamage = false;
|
bool bonusDamage = false;
|
||||||
for (AuraEffect* eff : AuraEffectList)
|
for (AuraEffect* eff : AuraEffectList)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -465,7 +465,7 @@ enum SpellAttr2 : uint32
|
|||||||
SPELL_ATTR2_ALWAYS_CAST_AS_UNIT = 0x00000200, // TITLE Unknown attribute 9@Attr2
|
SPELL_ATTR2_ALWAYS_CAST_AS_UNIT = 0x00000200, // TITLE Unknown attribute 9@Attr2
|
||||||
SPELL_ATTR2_SPECIAL_TAMING_FLAG = 0x00000400, // TITLE Unknown attribute 10@Attr2 DESCRIPTION Related to taming?
|
SPELL_ATTR2_SPECIAL_TAMING_FLAG = 0x00000400, // TITLE Unknown attribute 10@Attr2 DESCRIPTION Related to taming?
|
||||||
SPELL_ATTR2_NO_TARGET_PER_SECOND_COST = 0x00000800, // TITLE Health Funnel
|
SPELL_ATTR2_NO_TARGET_PER_SECOND_COST = 0x00000800, // TITLE Health Funnel
|
||||||
SPELL_ATTR2_CHAIN_FROM_CASTER = 0x00001000, // TITLE Unknown attribute 12@Attr2 DESCRIPTION Cleave, Heart Strike, Maul, Sunder Armor, Swipe
|
SPELL_ATTR2_CHAIN_FROM_CASTER = 0x00001000, // TITLE Chain from caster DESCRIPTION Cleave, Heart Strike, Maul, Sunder Armor, Swipe
|
||||||
SPELL_ATTR2_ENCHANT_OWN_ITEM_ONLY = 0x00002000, // TITLE Enchant persists when entering arena
|
SPELL_ATTR2_ENCHANT_OWN_ITEM_ONLY = 0x00002000, // TITLE Enchant persists when entering arena
|
||||||
SPELL_ATTR2_ALLOW_WHILE_INVISIBLE = 0x00004000, // TITLE Unknown attribute 14@Attr2
|
SPELL_ATTR2_ALLOW_WHILE_INVISIBLE = 0x00004000, // TITLE Unknown attribute 14@Attr2
|
||||||
SPELL_ATTR2_DO_NOT_CONSUME_IF_GAINED_DURING_CAST = 0x00008000, // TITLE Unused attribute 15@Attr2 DESCRIPTION not set in 3.3.5a
|
SPELL_ATTR2_DO_NOT_CONSUME_IF_GAINED_DURING_CAST = 0x00008000, // TITLE Unused attribute 15@Attr2 DESCRIPTION not set in 3.3.5a
|
||||||
|
|||||||
Reference in New Issue
Block a user