Merge remote-tracking branch 'acore/master' into test-staging

# Conflicts:
#	.github/workflows/windows_build.yml
This commit is contained in:
Keleborn
2026-05-05 13:24:38 -07:00
27 changed files with 441 additions and 99 deletions

View File

@@ -19,8 +19,7 @@ jobs:
runs-on: ${{ matrix.os }}
name: ${{ matrix.os }}
env:
BOOST_ROOT: C:\local\boost_1_82_0
BOOST_ROOT: C:\local\boost_1_87_0
steps:
- name: Checkout AzerothCore
uses: actions/checkout@v4

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash
# Set SUDO variable - one liner
if [[ "$OSTYPE" == "msys"* ]]; then
if [[ "$OSTYPE" == "msys"* || "$OSTYPE" == "cygwin"* ]]; then
SUDO=""
else
SUDO=$([ "$EUID" -ne 0 ] && echo "sudo" || echo "")
@@ -49,7 +49,7 @@ function inst_configureOS() {
source "$AC_PATH_INSTALLER/includes/os_configs/$DISTRO.sh"
;;
*bsd*) echo "BSD is not supported yet" ;;
msys*) source "$AC_PATH_INSTALLER/includes/os_configs/windows.sh" ;;
msys*|cygwin*) source "$AC_PATH_INSTALLER/includes/os_configs/windows.sh" ;;
*) echo "This platform is not supported" ;;
esac
}

View File

@@ -0,0 +1,11 @@
-- DB update 2026_05_01_00 -> 2026_05_03_00
-- RBAC permissions for .pet list (sec 1+, Mod role 198) and .pet delete (sec 3+, Admin role 196).
DELETE FROM `rbac_permissions` WHERE `id` IN (914, 915);
INSERT INTO `rbac_permissions` (`id`, `name`) VALUES
(914, 'Command: pet list'),
(915, 'Command: pet delete');
DELETE FROM `rbac_linked_permissions` WHERE `linkedId` IN (914, 915);
INSERT INTO `rbac_linked_permissions` (`id`, `linkedId`) VALUES
(198, 914),
(196, 915);

View File

@@ -0,0 +1,9 @@
-- DB update 2026_05_02_02 -> 2026_05_03_00
-- acore_string entries for .pet list and .pet delete commands.
DELETE FROM `acore_string` WHERE `entry` BETWEEN 35435 AND 35439;
INSERT INTO `acore_string` (`entry`, `content_default`, `locale_koKR`, `locale_frFR`, `locale_deDE`, `locale_zhCN`, `locale_zhTW`, `locale_esES`, `locale_esMX`, `locale_ruRU`) VALUES
(35435, 'Pets owned by {} ({}):', '{}({})이(가) 소유한 펫:', 'Familiers de {} ({}) :', 'Begleiter von {} ({}):', '{} ({}) 拥有的宠物:', '{} ({}) 擁有的寵物:', 'Mascotas de {} ({}):', 'Mascotas de {} ({}):', 'Питомцы игрока {} ({}):'),
(35436, ' PetNumber: {} | Slot: {} | Entry: {} ({}) | Name: {} | Level: {} | Type: {}', ' 펫번호: {} | 슬롯: {} | Entry: {} ({}) | 이름: {} | 레벨: {} | 종류: {}', ' N° Familier : {} | Emplacement : {} | Entrée : {} ({}) | Nom : {} | Niveau : {} | Type : {}', ' Begleiter-Nr.: {} | Slot: {} | Eintrag: {} ({}) | Name: {} | Stufe: {} | Typ: {}', ' 宠物编号: {} | 槽位: {} | 条目: {} ({}) | 名称: {} | 等级: {} | 类型: {}', ' 寵物編號: {} | 槽位: {} | 條目: {} ({}) | 名稱: {} | 等級: {} | 類型: {}', ' N.º mascota: {} | Ranura: {} | Entrada: {} ({}) | Nombre: {} | Nivel: {} | Tipo: {}', ' N.º mascota: {} | Ranura: {} | Entrada: {} ({}) | Nombre: {} | Nivel: {} | Tipo: {}', ' Номер: {} | Слот: {} | Entry: {} ({}) | Имя: {} | Уровень: {} | Тип: {}'),
(35437, 'Player {} ({}) has no pets.', '플레이어 {}({})에게 펫이 없습니다.', "Le joueur {} ({}) n'a aucun familier.", 'Spieler {} ({}) besitzt keine Begleiter.', '玩家 {} ({}) 没有任何宠物。', '玩家 {} ({}) 沒有任何寵物。', 'El jugador {} ({}) no tiene mascotas.', 'El jugador {} ({}) no tiene mascotas.', 'У игрока {} ({}) нет питомцев.'),
(35438, 'No pet with PetNumber {0} found for player {1} ({2}).', '플레이어 {1} ({2})의 펫번호 {0}을(를) 찾을 수 없습니다.', "Aucun familier avec le N° {0} trouvé pour le joueur {1} ({2}).", 'Kein Begleiter mit Nummer {0} für Spieler {1} ({2}) gefunden.', '未找到玩家 {1} ({2}) 的宠物编号 {0}。', '找不到玩家 {1} ({2}) 的寵物編號 {0}。', 'No se encontró ninguna mascota con N.º {0} para el jugador {1} ({2}).', 'No se encontró ninguna mascota con N.º {0} para el jugador {1} ({2}).', 'У игрока {1} ({2}) не найден питомец с номером {0}.'),
(35439, 'Deleted pet {0} ({1}, entry {2} - {3}) from player {4} ({5}).', '플레이어 {4} ({5})로부터 펫 {0} ({1}, entry {2} - {3})을(를) 삭제했습니다.', "Familier {0} ({1}, entrée {2} - {3}) supprimé du joueur {4} ({5}).", 'Begleiter {0} ({1}, Eintrag {2} - {3}) von Spieler {4} ({5}) gelöscht.', '已从玩家 {4} ({5}) 删除宠物 {0} ({1}, 条目 {2} - {3})。', '已從玩家 {4} ({5}) 刪除寵物 {0} ({1}, 條目 {2} - {3})。', 'Eliminada la mascota {0} ({1}, entrada {2} - {3}) del jugador {4} ({5}).', 'Eliminada la mascota {0} ({1}, entrada {2} - {3}) del jugador {4} ({5}).', 'Питомец {0} ({1}, entry {2} - {3}) удалён у игрока {4} ({5}).');

View File

@@ -0,0 +1,41 @@
-- DB update 2026_05_03_00 -> 2026_05_03_01
-- Edit SmartAIs
DELETE FROM `smart_scripts` WHERE (`entryorguid` IN (-129500, -129501, -129502, -129503, -129520, -129529, -129530, -129531, -129532, -129546, -129547, -129556)) AND (`source_type` = 0) AND (`id` IN (41, 42, 43));
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
(-129500, 0, 41, 42, 109, 0, 100, 0, 0, 0, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Remove Npc Flags Gossip'),
(-129500, 0, 42, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Despawn In 5000 ms'),
(-129500, 0, 43, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Just Died - Despawn In 5000 ms'),
(-129501, 0, 41, 42, 109, 0, 100, 0, 0, 0, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Remove Npc Flags Gossip'),
(-129501, 0, 42, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Despawn In 5000 ms'),
(-129501, 0, 43, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Just Died - Despawn In 5000 ms'),
(-129502, 0, 41, 42, 109, 0, 100, 0, 0, 0, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Remove Npc Flags Gossip'),
(-129502, 0, 42, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Despawn In 5000 ms'),
(-129502, 0, 43, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Just Died - Despawn In 5000 ms'),
(-129503, 0, 41, 42, 109, 0, 100, 0, 0, 0, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Remove Npc Flags Gossip'),
(-129503, 0, 42, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Despawn In 5000 ms'),
(-129503, 0, 43, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Just Died - Despawn In 5000 ms'),
(-129520, 0, 41, 42, 109, 0, 100, 0, 0, 0, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Remove Npc Flags Gossip'),
(-129520, 0, 42, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Despawn In 5000 ms'),
(-129520, 0, 43, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Just Died - Despawn In 5000 ms'),
(-129529, 0, 41, 42, 109, 0, 100, 0, 0, 0, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Remove Npc Flags Gossip'),
(-129529, 0, 42, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Despawn In 5000 ms'),
(-129529, 0, 43, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Just Died - Despawn In 5000 ms'),
(-129530, 0, 41, 42, 109, 0, 100, 0, 0, 0, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Remove Npc Flags Gossip'),
(-129530, 0, 42, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Despawn In 5000 ms'),
(-129530, 0, 43, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Just Died - Despawn In 5000 ms'),
(-129531, 0, 41, 42, 109, 0, 100, 0, 0, 0, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Remove Npc Flags Gossip'),
(-129531, 0, 42, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Despawn In 5000 ms'),
(-129531, 0, 43, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Just Died - Despawn In 5000 ms'),
(-129532, 0, 41, 42, 109, 0, 100, 0, 0, 0, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Remove Npc Flags Gossip'),
(-129532, 0, 42, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Despawn In 5000 ms'),
(-129532, 0, 43, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Just Died - Despawn In 5000 ms'),
(-129546, 0, 41, 42, 109, 0, 100, 0, 0, 0, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Remove Npc Flags Gossip'),
(-129546, 0, 42, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Despawn In 5000 ms'),
(-129546, 0, 43, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Just Died - Despawn In 5000 ms'),
(-129547, 0, 41, 42, 109, 0, 100, 0, 0, 0, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Remove Npc Flags Gossip'),
(-129547, 0, 42, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Despawn In 5000 ms'),
(-129547, 0, 43, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Just Died - Despawn In 5000 ms'),
(-129556, 0, 41, 42, 109, 0, 100, 0, 0, 0, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Remove Npc Flags Gossip'),
(-129556, 0, 42, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Path 0 Finished - Despawn In 5000 ms'),
(-129556, 0, 43, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - On Just Died - Despawn In 5000 ms');

View File

@@ -0,0 +1,85 @@
-- DB update 2026_05_03_01 -> 2026_05_04_00
-- Delete old waypoint & add two new ones.
DELETE FROM `script_waypoint` WHERE `entry` = 29602;
DELETE FROM `waypoint_data` WHERE (`id` IN (2960200, 2960201));
INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES
(2960200, 1, 7079.6978, -2033.1096, 764.22363, NULL, 0, 1, 0, 100, 0),
(2960200, 2, 7068.746, -2081.6372, 758.46783, NULL, 0, 1, 0, 100, 0),
(2960200, 3, 7065.993, -2130.804, 756.0072, NULL, 0, 1, 0, 100, 0),
(2960200, 4, 7088.311, -2173.4739, 759.40454, NULL, 0, 1, 0, 100, 0),
(2960200, 5, 7124.069, -2207.86, 758.34875, NULL, 0, 1, 0, 100, 0),
(2960200, 6, 7152.243, -2248.376, 759.6332, NULL, 0, 1, 0, 100, 0),
(2960200, 7, 7196.3516, -2265.1384, 756.818, NULL, 0, 1, 0, 100, 0),
(2960200, 8, 7234.0127, -2297.4749, 752.40814, NULL, 0, 1, 0, 100, 0),
(2960200, 9, 7255.4043, -2341.076, 751.73083, NULL, 0, 1, 0, 100, 0),
(2960200, 10, 7297.8813, -2368.0906, 751.5218, NULL, 0, 1, 0, 100, 0),
(2960200, 11, 7304.3057, -2416.3677, 752.8529, NULL, 0, 1, 0, 100, 0),
(2960200, 12, 7320.8213, -2463.647, 750.73145, NULL, 0, 1, 0, 100, 0),
(2960200, 13, 7362.9956, -2490.5044, 749.8022, NULL, 0, 1, 0, 100, 0),
(2960200, 14, 7409.4863, -2475.0657, 751.87994, NULL, 0, 1, 0, 100, 0),
(2960200, 15, 7422.454, -2427.5562, 752.46826, NULL, 0, 1, 0, 100, 0),
(2960200, 16, 7407.2866, -2380.3416, 753.04663, NULL, 0, 1, 0, 100, 0),
(2960200, 17, 7407.848, -2331.121, 757.12366, NULL, 0, 1, 0, 100, 0),
(2960200, 18, 7366.268, -2303.2979, 756.10443, NULL, 0, 1, 0, 100, 0),
(2960200, 19, 7318.561, -2301.5312, 754.4625, NULL, 0, 1, 0, 100, 0),
(2960200, 20, 7280.9966, -2270.3918, 756.3627, NULL, 0, 1, 0, 100, 0),
(2960200, 21, 7237.944, -2246.7197, 756.31384, NULL, 0, 1, 0, 100, 0),
(2960200, 22, 7193.8286, -2231.046, 757.79626, NULL, 0, 1, 0, 100, 0),
(2960200, 23, 7159.3477, -2195.3066, 760.58264, NULL, 0, 1, 0, 100, 0),
(2960200, 24, 7122.389, -2164.836, 760.4839, NULL, 0, 1, 0, 100, 0),
(2960200, 25, 7112.4834, -2116.8887, 759.7804, NULL, 0, 1, 0, 100, 0),
(2960200, 26, 7116.9863, -2071.1887, 766.2056, NULL, 0, 1, 0, 100, 0),
(2960200, 27, 7117.6025, -2040.7129, 767.7893, NULL, 0, 1, 0, 100, 0),
(2960200, 28, 7107.0435, -2011.1892, 770.1438, NULL, 0, 1, 0, 100, 0),
(2960200, 29, 7103.9424, -1985.653, 771.0793, NULL, 0, 1, 0, 100, 0),
(2960200, 30, 7079.7, -1966.68, 769.305, NULL, 0, 1, 0, 100, 0),
(2960200, 31, 7087.928, -1931.9026, 773.7549, NULL, 0, 1, 0, 100, 0),
(2960201, 1, 7081.8774, -2012.0011, 766.2301, NULL, 0, 1, 0, 100, 0),
(2960201, 2, 7104.026, -2056.3606, 765.3837, NULL, 0, 1, 0, 100, 0),
(2960201, 3, 7104.528, -2105.8418, 760.49347, NULL, 0, 1, 0, 100, 0),
(2960201, 4, 7116.4165, -2153.7432, 759.7369, NULL, 0, 1, 0, 100, 0),
(2960201, 5, 7147.767, -2190.783, 759.2086, NULL, 0, 1, 0, 100, 0),
(2960201, 6, 7189.606, -2217.285, 759.46906, NULL, 0, 1, 0, 100, 0),
(2960201, 7, 7231.661, -2238.2708, 757.4844, NULL, 0, 1, 0, 100, 0),
(2960201, 8, 7272.987, -2260.4424, 756.20917, NULL, 0, 1, 0, 100, 0),
(2960201, 9, 7310.389, -2289.4739, 754.7779, NULL, 0, 1, 0, 100, 0),
(2960201, 10, 7355.282, -2303.5774, 755.6713, NULL, 0, 1, 0, 100, 0),
(2960201, 11, 7401.5444, -2318.8916, 757.8036, NULL, 0, 1, 0, 100, 0),
(2960201, 12, 7413.0244, -2353.2883, 755.66315, NULL, 0, 1, 0, 100, 0),
(2960201, 13, 7386.935, -2394.2864, 749.2125, NULL, 0, 1, 0, 100, 0),
(2960201, 14, 7343.7847, -2418.5652, 749.6803, NULL, 0, 1, 0, 100, 0),
(2960201, 15, 7300.632, -2393.1646, 751.9034, NULL, 0, 1, 0, 100, 0),
(2960201, 16, 7281.886, -2347.135, 749.444, NULL, 0, 1, 0, 100, 0),
(2960201, 17, 7268.9087, -2299.5518, 752.52783, NULL, 0, 1, 0, 100, 0),
(2960201, 18, 7227.1978, -2271.2617, 755.354, NULL, 0, 1, 0, 100, 0),
(2960201, 19, 7181.099, -2253.8003, 757.4965, NULL, 0, 1, 0, 100, 0),
(2960201, 20, 7136.719, -2232.0361, 758.35034, NULL, 0, 1, 0, 100, 0),
(2960201, 21, 7103.6987, -2195.238, 759.33044, NULL, 0, 1, 0, 100, 0),
(2960201, 22, 7072.1104, -2157.011, 759.6482, NULL, 0, 1, 0, 100, 0),
(2960201, 23, 7059.117, -2109.4075, 755.57043, NULL, 0, 1, 0, 100, 0),
(2960201, 24, 7069.828, -2068.9705, 759.4906, NULL, 0, 1, 0, 100, 0),
(2960201, 25, 7092.831, -2042.584, 766.1361, NULL, 0, 1, 0, 100, 0),
(2960201, 26, 7107.4473, -2013.8727, 769.5967, NULL, 0, 1, 0, 100, 0),
(2960201, 27, 7102.1475, -1985.027, 770.659, NULL, 0, 1, 0, 100, 0),
(2960201, 28, 7079.7, -1966.68, 769.305, NULL, 0, 1, 0, 100, 0),
(2960201, 29, 7087.928, -1931.9026, 773.7549, NULL, 0, 1, 0, 100, 0);
-- Set SmartAI
UPDATE `creature_template` SET `AIName` = 'SmartAI', `ScriptName` = '' WHERE (`entry` = 29602);
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 29602);
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
(29602, 0, 0, 1, 27, 0, 100, 512, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Icefang - On Passenger Boarded - Set Reactstate Passive'),
(29602, 0, 1, 2, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 117, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Icefang - On Passenger Boarded - Disable Evade'),
(29602, 0, 2, 0, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 233, 2960200, 2960201, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Icefang - On Passenger Boarded - Start Random Path 2960200-2960201'),
(29602, 0, 3, 0, 28, 0, 100, 512, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Icefang - On Passenger Removed - Despawn Instant'),
(29602, 0, 4, 0, 109, 0, 100, 512, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Icefang - On Any Path Finished - Despawn Instant');
-- Delete Old Condition (Icefang spellclick requires the Going Bearback quest to not be rewarded)
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 18) AND (`SourceGroup` = 29598) AND (`SourceEntry` = 54768) AND (`SourceId` = 0) AND (`ElseGroup` = 0) AND (`ConditionTypeOrReference` = 8) AND (`ConditionTarget` = 0) AND (`ConditionValue1` = 12856) AND (`ConditionValue2` = 0) AND (`ConditionValue3` = 0);
-- Add new Condition.
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 18) AND (`SourceGroup` = 29598) AND (`SourceEntry` = 54768) AND (`SourceId` = 0) AND (`ElseGroup` = 0) AND (`ConditionTypeOrReference` = 9) AND (`ConditionTarget` = 0) AND (`ConditionValue1` = 12851) AND (`ConditionValue2` = 0) AND (`ConditionValue3` = 0);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(18, 29598, 54768, 0, 0, 9, 0, 12851, 0, 0, 0, 0, 0, '', 'Icefang spellclick require Going Bearback quest taken');

View File

@@ -0,0 +1,6 @@
-- DB update 2026_05_04_00 -> 2026_05_04_01
-- Add Stitches to legacy spawn group.
DELETE FROM `spawn_group` WHERE `spawnId` = 300000;
INSERT INTO `spawn_group` (`groupId`, `spawnType`, `spawnId`) VALUES
(1, 0, 300000);

View File

@@ -0,0 +1,14 @@
-- DB update 2026_05_04_01 -> 2026_05_05_00
--
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 3568);
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
(3568, 0, 1, 2, 19, 0, 100, 512, 938, 0, 0, 0, 0, 0, 29, 1, 1, 3519, 938, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Mist - On Quest \'Mist\' Taken - Start Follow Invoker'),
(3568, 0, 2, 3, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 83, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Mist - On Quest \'Mist\' Taken - Remove Npc Flags Questgiver'),
(3568, 0, 3, 4, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 19, 512, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Mist - On Quest \'Mist\' Taken - Remove Flags Immune To NPC\'s'),
(3568, 0, 4, 0, 61, 0, 100, 513, 0, 0, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Mist - On Quest \'Mist\' Taken - Set Reactstate Defensive'),
(3568, 0, 5, 0, 6, 0, 100, 512, 0, 0, 0, 0, 0, 0, 70, 1000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Mist - On Just Died - Respawn Self'),
(3568, 0, 6, 7, 11, 0, 100, 512, 0, 0, 0, 0, 0, 0, 18, 512, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Mist - On Respawn - Set Flags Immune To NPC\'s'),
(3568, 0, 7, 8, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 81, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Mist - On Respawn - Set Npc Flags Questgiver'),
(3568, 0, 8, 0, 61, 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, 'Mist - On Respawn - Set Reactstate Passive'),
(3568, 0, 9, 10, 65, 0, 100, 512, 0, 0, 0, 0, 0, 0, 70, 2000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Mist - On Follow Complete - Respawn Self'),
(3568, 0, 10, 0, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 1, 0, 1000, 0, 0, 0, 0, 19, 3519, 10, 0, 0, 0, 0, 0, 0, 'Mist - On Follow Complete - Say Line 0');

View File

@@ -0,0 +1,18 @@
-- DB update 2026_05_05_00 -> 2026_05_05_01
-- Edit SAI (Talbot)
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 25301;
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 25301) AND (`source_type` = 0) AND (`id` IN (3, 4, 5, 6, 7, 8, 9));
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
(25301, 0, 3, 4, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 83, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Counselor Talbot - On Just Summoned - Remove Npc Flags Questgiver'),
(25301, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 232, 253011, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Counselor Talbot - On Just Summoned - Start Path 253011'),
(25301, 0, 5, 0, 109, 0, 100, 0, 0, 253011, 0, 0, 0, 0, 223, 1, 0, 0, 0, 0, 0, 10, 101303, 26170, 0, 0, 0, 0, 0, 0, 'Counselor Talbot - On Path Finished - Send Action to Thassarian'),
(25301, 0, 6, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 223, 1, 0, 0, 0, 0, 0, 19, 25250, 100, 0, 0, 0, 0, 0, 0, 'Counselor Talbot - On Just Died - Send Event to General Arlos'),
(25301, 0, 7, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 223, 1, 0, 0, 0, 0, 0, 19, 25251, 100, 0, 0, 0, 0, 0, 0, 'Counselor Talbot - On Just Died - Send Event to Leryssa'),
(25301, 0, 8, 0, 109, 0, 100, 0, 0, 253011, 0, 0, 0, 0, 90, 8, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Counselor Talbot - On Path Finished - Set Flag Standstate Kneel'),
(25301, 0, 9, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Counselor Talbot - On Respawn - Deload Equipment');
-- Edit Action Lists (Thassarian)
UPDATE `smart_scripts` SET `action_param3` = 1 WHERE (`entryorguid` = 2617004) AND (`source_type` = 9) AND (`id` IN (2));
UPDATE `smart_scripts` SET `action_param3` = 1 WHERE (`entryorguid` = 2617001) AND (`source_type` = 9) AND (`id` IN (5));

View File

@@ -0,0 +1,4 @@
-- DB update 2026_05_05_01 -> 2026_05_05_02
-- Delete Row 7
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 3099200) AND (`source_type` = 9) AND (`id` IN (7));

View File

@@ -0,0 +1,14 @@
-- DB update 2026_05_05_02 -> 2026_05_05_03
-- Edit Action Lists 1985100, 1985101 & update comments.
DELETE FROM `smart_scripts` WHERE (`source_type` = 9) AND (`entryorguid` IN (1985100, 1985101));
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
(1985100, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Negatron - Actionlist - Set Active On'),
(1985100, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 18, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Negatron - Actionlist - Set Flags Immune To Players & Immune To NPC\'s'),
(1985100, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 53, 2, 1985100, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Negatron - Actionlist - Start Waypoint Path 1985100'),
(1985100, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 15742, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Negatron - Actionlist - Cast \'Ashcrombe`s Teleport\''),
(1985100, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Negatron - Actionlist - Set Event Phase 2'),
(1985101, 9, 0, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 10, 70967, 19832, 0, 0, 0, 0, 0, 0, 'Negatron - Actionlist - Set Orientation Closest Creature \'Doctor Vomisa, Ph.T.\''),
(1985101, 9, 1, 0, 0, 0, 100, 0, 150, 150, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Negatron - Actionlist - Say Line 0'),
(1985101, 9, 2, 0, 0, 0, 100, 0, 6000, 6000, 0, 0, 0, 0, 19, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Negatron - Actionlist - Remove Flags Immune To Players & Immune To NPC\'s'),
(1985101, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 10, 70975, 19849, 0, 0, 0, 0, 0, 0, 'Negatron - Actionlist - Start Attacking');

View File

@@ -0,0 +1,5 @@
-- DB update 2026_05_05_03 -> 2026_05_05_04
-- Talisman of Troll Divinity (37734) - Touched by a Troll proc on direct heals
DELETE FROM `spell_proc` WHERE `SpellId` = 60517;
INSERT INTO `spell_proc` (`SpellId`, `SchoolMask`, `SpellFamilyName`, `SpellFamilyMask0`, `SpellFamilyMask1`, `SpellFamilyMask2`, `ProcFlags`, `SpellTypeMask`, `SpellPhaseMask`, `HitMask`, `AttributesMask`, `DisableEffectsMask`, `ProcsPerMinute`, `Chance`, `Cooldown`, `Charges`) VALUES
(60517, 0, 0, 0, 0, 0, 0x4000, 2, 2, 0, 0, 0, 0, 100, 0, 0);

View File

@@ -1241,6 +1241,23 @@ void SmartAI::SetFollow(Unit* target, float dist, float angle, uint32 credit, ui
void SmartAI::StopFollow(bool complete)
{
if (complete)
{
Player* player = ObjectAccessor::GetPlayer(*me, mFollowGuid);
if (player && mFollowCredit > 0)
{
if (!mFollowCreditType)
player->RewardPlayerAndGroupAtEvent(mFollowCredit, me);
else
player->GroupEventHappens(mFollowCredit, me);
}
SetDespawnTime(5000);
StartDespawn();
GetScript()->ProcessEventsFor(SMART_EVENT_FOLLOW_COMPLETED, player);
}
mFollowGuid.Clear();
mFollowDist = 0;
mFollowAngle = 0;
@@ -1252,23 +1269,6 @@ void SmartAI::StopFollow(bool complete)
me->GetMotionMaster()->Clear(false);
me->StopMoving();
me->GetMotionMaster()->MoveIdle();
if (!complete)
return;
Player* player = ObjectAccessor::GetPlayer(*me, mFollowGuid);
if (player)
{
if (!mFollowCreditType)
player->RewardPlayerAndGroupAtEvent(mFollowCredit, me);
else
player->GroupEventHappens(mFollowCredit, me);
}
SetDespawnTime(5000);
StartDespawn();
GetScript()->ProcessEventsFor(SMART_EVENT_FOLLOW_COMPLETED, player);
}
void SmartAI::SetScript9(SmartScriptHolder& e, uint32 entry, WorldObject* invoker)

View File

@@ -676,6 +676,8 @@ enum RBACPermissions
RBAC_PERM_COMMAND_CHARACTER_CHECK_PROFESSION = 911,
RBAC_PERM_COMMAND_GOBJECT_LOAD = 912,
RBAC_PERM_COMMAND_BF_QUEUE = 913,
RBAC_PERM_COMMAND_PET_LIST = 914,
RBAC_PERM_COMMAND_PET_DELETE = 915,
// custom permissions 1000+
RBAC_PERM_MAX
};

View File

@@ -2718,7 +2718,8 @@ bool Creature::CanCreatureAttack(Unit const* victim, bool skipDistCheck) const
float x, y, z;
x = y = z = 0.0f;
if (GetMotionMaster()->GetMotionSlot(MOTION_SLOT_IDLE)->GetResetPosition(x, y, z))
MovementGenerator* idleSlot = GetMotionMaster()->GetMotionSlot(MOTION_SLOT_IDLE);
if (idleSlot && idleSlot->GetResetPosition(x, y, z))
return IsInDist2d(x, y, dist);
else
return IsInDist2d(&m_homePosition, dist);

View File

@@ -14351,7 +14351,7 @@ bool Player::CanSeeSpellClickOn(Creature const* c) const
SpellClickInfoMapBounds clickPair = sObjectMgr->GetSpellClickInfoMapBounds(c->GetEntry());
if (clickPair.first == clickPair.second)
return true;
return false;
for (SpellClickInfoContainer::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr)
{

View File

@@ -8387,8 +8387,10 @@ void Unit::EnergizeBySpell(Unit* victim, uint32 spellID, uint32 damage, Powers p
{
victim->ModifyPower(powerType, damage, false);
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID))
victim->GetThreatMgr().ForwardThreatForAssistingMe(this, float(damage) / 2.0f, spellInfo, true);
// Happiness is internal hunter pet state, not combat assistance — energizing it must not generate threat
if (powerType != POWER_HAPPINESS)
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID))
victim->GetThreatMgr().ForwardThreatForAssistingMe(this, float(damage) / 2.0f, spellInfo, true);
SendEnergizeSpellLog(victim, spellID, damage, powerType);
}

View File

@@ -459,14 +459,35 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
return;
}
// log traded items before moving (pointers become invalid after moveItems)
// cache traded item info before moving (pointers become invalid after moveItems if items merge into existing stacks)
struct TradedItemInfo
{
bool present = false;
std::string name;
uint32 entry = 0;
uint32 count = 0;
};
TradedItemInfo myItemsInfo[TRADE_SLOT_TRADED_COUNT];
TradedItemInfo hisItemsInfo[TRADE_SLOT_TRADED_COUNT];
std::string myItemsStr, hisItemsStr;
for (uint8 i = 0; i < TRADE_SLOT_TRADED_COUNT; ++i)
{
if (myItems[i])
myItemsStr += Acore::StringFormat("{} (Entry:{}) x{}, ", myItems[i]->GetTemplate()->Name1, myItems[i]->GetEntry(), myItems[i]->GetCount());
{
myItemsInfo[i].present = true;
myItemsInfo[i].name = myItems[i]->GetTemplate()->Name1;
myItemsInfo[i].entry = myItems[i]->GetEntry();
myItemsInfo[i].count = myItems[i]->GetCount();
myItemsStr += Acore::StringFormat("{} (Entry:{}) x{}, ", myItemsInfo[i].name, myItemsInfo[i].entry, myItemsInfo[i].count);
}
if (hisItems[i])
hisItemsStr += Acore::StringFormat("{} (Entry:{}) x{}, ", hisItems[i]->GetTemplate()->Name1, hisItems[i]->GetEntry(), hisItems[i]->GetCount());
{
hisItemsInfo[i].present = true;
hisItemsInfo[i].name = hisItems[i]->GetTemplate()->Name1;
hisItemsInfo[i].entry = hisItems[i]->GetEntry();
hisItemsInfo[i].count = hisItems[i]->GetCount();
hisItemsStr += Acore::StringFormat("{} (Entry:{}) x{}, ", hisItemsInfo[i].name, hisItemsInfo[i].entry, hisItemsInfo[i].count);
}
}
// execute trade: 1. remove
@@ -509,10 +530,10 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
{
for (uint8 i = 0; i < TRADE_SLOT_TRADED_COUNT; ++i)
{
if (myItems[i])
if (myItemsInfo[i].present)
LOG_GM(GetAccountId(), "GM {} (Account: {}) traded item: {} (Entry: {} Count: {}) to {}",
_player->GetName(), GetAccountId(),
myItems[i]->GetTemplate()->Name1, myItems[i]->GetEntry(), myItems[i]->GetCount(),
myItemsInfo[i].name, myItemsInfo[i].entry, myItemsInfo[i].count,
trader->GetName());
}
if (my_trade->GetMoney() > 0)
@@ -523,10 +544,10 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
{
for (uint8 i = 0; i < TRADE_SLOT_TRADED_COUNT; ++i)
{
if (hisItems[i])
if (hisItemsInfo[i].present)
LOG_GM(trader->GetSession()->GetAccountId(), "GM {} (Account: {}) traded item: {} (Entry: {} Count: {}) to {}",
trader->GetName(), trader->GetSession()->GetAccountId(),
hisItems[i]->GetTemplate()->Name1, hisItems[i]->GetEntry(), hisItems[i]->GetCount(),
hisItemsInfo[i].name, hisItemsInfo[i].entry, hisItemsInfo[i].count,
_player->GetName());
}
if (his_trade->GetMoney() > 0)

View File

@@ -1478,6 +1478,15 @@ enum AcoreStrings
LANG_POOL_LOOKUP_IN_POOL = 35431,
LANG_POOL_LOOKUP_NOT_IN_POOL = 35432,
LANG_POOL_LOOKUP_USE_INFO = 35433,
LANG_POOL_LOOKUP_NOTARGET = 35434
LANG_POOL_LOOKUP_NOTARGET = 35434,
// Pet list command
LANG_PET_LIST_HEADER = 35435,
LANG_PET_LIST_ENTRY = 35436,
LANG_PET_LIST_EMPTY = 35437,
// Pet delete command
LANG_PET_DELETE_NOT_FOUND = 35438,
LANG_PET_DELETE_SUCCESS = 35439
};
#endif

View File

@@ -5390,10 +5390,10 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
{
if (target->isDead() && GetBase() && target->IsCreature() && target->GetEntry() == 24601)
{
auto caster2 = GetBase()->GetCaster();
if (caster2 && caster2->IsPlayer())
if (Unit* caster2 = GetBase()->GetCaster())
{
caster2->ToPlayer()->KilledMonsterCredit(25987);
if (Player* player = caster2->GetCharmerOrOwnerPlayerOrPlayerItself())
player->KilledMonsterCredit(25987);
}
}
return;

View File

@@ -17,6 +17,8 @@
#include "Chat.h"
#include "CommandScript.h"
#include "DatabaseEnv.h"
#include <algorithm>
#include "Language.h"
#include "Log.h"
#include "ObjectMgr.h"
@@ -37,9 +39,11 @@ public:
{
static ChatCommandTable petCommandTable =
{
{ "create", HandlePetCreateCommand, rbac::RBAC_PERM_COMMAND_PET_CREATE, Console::No },
{ "learn", HandlePetLearnCommand, rbac::RBAC_PERM_COMMAND_PET_LEARN, Console::No },
{ "unlearn", HandlePetUnlearnCommand, rbac::RBAC_PERM_COMMAND_PET_UNLEARN, Console::No }
{ "create", HandlePetCreateCommand, rbac::RBAC_PERM_COMMAND_PET_CREATE, Console::No },
{ "delete", HandlePetDeleteCommand, rbac::RBAC_PERM_COMMAND_PET_DELETE, Console::Yes },
{ "learn", HandlePetLearnCommand, rbac::RBAC_PERM_COMMAND_PET_LEARN, Console::No },
{ "list", HandlePetListCommand, rbac::RBAC_PERM_COMMAND_PET_LIST, Console::Yes },
{ "unlearn", HandlePetUnlearnCommand, rbac::RBAC_PERM_COMMAND_PET_UNLEARN, Console::No }
};
static ChatCommandTable commandTable =
@@ -126,6 +130,103 @@ public:
return true;
}
static bool HandlePetDeleteCommand(ChatHandler* handler, PlayerIdentifier owner, uint32 petNumber)
{
ObjectGuid ownerGuid = owner.GetGUID();
QueryResult result = CharacterDatabase.Query(
"SELECT entry, name FROM character_pet WHERE id = {} AND owner = {}",
petNumber, ownerGuid.GetCounter());
if (!result)
{
handler->SendErrorMessage(LANG_PET_DELETE_NOT_FOUND, petNumber, owner.GetName(),
ownerGuid.GetCounter());
return false;
}
if (Player* online = owner.GetConnectedPlayer())
{
if (Pet* activePet = online->GetPet())
{
if (activePet->GetCharmInfo() &&
activePet->GetCharmInfo()->GetPetNumber() == petNumber)
{
online->RemovePet(activePet, PET_SAVE_AS_DELETED);
}
}
// Drop the pet from the in-memory PetStable so the stable UI / call-pet
// logic does not reference a row that no longer exists in the database.
if (PetStable* stable = online->GetPetStable())
{
if (stable->CurrentPet && stable->CurrentPet->PetNumber == petNumber)
stable->CurrentPet.reset();
for (Optional<PetStable::PetInfo>& stabled : stable->StabledPets)
if (stabled && stabled->PetNumber == petNumber)
stabled.reset();
stable->UnslottedPets.erase(
std::remove_if(stable->UnslottedPets.begin(), stable->UnslottedPets.end(),
[petNumber](PetStable::PetInfo const& p) { return p.PetNumber == petNumber; }),
stable->UnslottedPets.end());
}
}
Field* fields = result->Fetch();
uint32 entry = fields[0].Get<uint32>();
std::string name = fields[1].Get<std::string>();
std::string creatureName = "<unknown>";
if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(entry))
creatureName = cInfo->Name;
Pet::DeleteFromDB(petNumber);
handler->PSendSysMessage(LANG_PET_DELETE_SUCCESS, petNumber, name, entry, creatureName,
owner.GetName(), ownerGuid.GetCounter());
return true;
}
static bool HandlePetListCommand(ChatHandler* handler, PlayerIdentifier owner)
{
ObjectGuid ownerGuid = owner.GetGUID();
QueryResult result = CharacterDatabase.Query(
"SELECT id, entry, level, slot, name, PetType FROM character_pet "
"WHERE owner = {} ORDER BY slot, id",
ownerGuid.GetCounter());
if (!result)
{
handler->PSendSysMessage(LANG_PET_LIST_EMPTY, owner.GetName(), ownerGuid.GetCounter());
return true;
}
handler->PSendSysMessage(LANG_PET_LIST_HEADER, owner.GetName(), ownerGuid.GetCounter());
do
{
Field* fields = result->Fetch();
uint32 petNumber = fields[0].Get<uint32>();
uint32 entry = fields[1].Get<uint32>();
uint8 level = fields[2].Get<uint8>();
uint8 slot = fields[3].Get<uint8>();
std::string name = fields[4].Get<std::string>();
uint8 petType = fields[5].Get<uint8>();
std::string creatureName = "<unknown>";
if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(entry))
creatureName = cInfo->Name;
handler->PSendSysMessage(LANG_PET_LIST_ENTRY, petNumber, uint32(slot), entry,
creatureName, name, uint32(level), uint32(petType));
} while (result->NextRow());
return true;
}
static bool HandlePetUnlearnCommand(ChatHandler* handler, SpellInfo const* spell)
{
if (!spell)

View File

@@ -189,17 +189,31 @@ public:
return true;
}
static bool HandleSendMoneyCommand(ChatHandler* handler, Optional<PlayerIdentifier> target, QuotedString subject, QuotedString text, uint32 money)
static bool HandleSendMoneyCommand(ChatHandler* handler, Optional<PlayerIdentifier> target, QuotedString subject, QuotedString text, Tail money)
{
if (!target)
{
target = PlayerIdentifier::FromTargetOrSelf(handler);
}
if (!target)
{
return false;
}
auto IsExistWord = [](std::string_view line, std::initializer_list<std::string_view> words)
{
for (auto const& word : words)
{
if (line.find(word) != std::string_view::npos)
return true;
}
return false;
};
Optional<int32> moneyToAddO = IsExistWord(money, { "g", "s", "c" }) ? MoneyStringToMoney(money) : Acore::StringTo<int32>(money);
if (!moneyToAddO)
return false;
int32 moneyToAdd = *moneyToAddO;
// from console show not existed sender
MailSender sender(MAIL_NORMAL, handler->GetSession() ? handler->GetSession()->GetPlayer()->GetGUID().GetCounter() : 0, MAIL_STATIONERY_GM);
@@ -207,7 +221,7 @@ public:
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
MailDraft(subject, text)
.AddMoney(money)
.AddMoney(moneyToAdd)
.SendMailTo(trans, MailReceiver(target->GetConnectedPlayer(), target->GetGUID().GetCounter()), sender);
CharacterDatabase.CommitTransaction(trans);

View File

@@ -21,10 +21,10 @@
enum Spells
{
SPELL_SHADOWWORDPAIN = 10894,
SPELL_MANABURN = 10876,
SPELL_PSYCHICSCREAM = 8122,
SPELL_SHADOWSHIELD = 22417
SPELL_SHADOWWORDPAIN = 14032,
SPELL_MANABURN = 14033,
SPELL_PSYCHICSCREAM = 13704,
SPELL_SHADOWSHIELD = 12040
};
struct boss_high_interrogator_gerstahn : public ScriptedAI

View File

@@ -416,6 +416,9 @@ struct boss_sartharion : public BossAI
for (uint32 i : dragons)
if (Creature* boss = instance->GetCreature(i))
boss->DespawnOrUnsummon();
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_TWILIGHT_TORMENT_VESPERON);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_TWILIGHT_TORMENT_SARTHARION);
}
void SetData(uint32 type, uint32 data) override
@@ -838,6 +841,8 @@ struct boss_sartharion_dragonAI : public BossAI
{
Talk(SAY_VESPERON_DEATH);
instance->DoAction(ACTION_CLEAR_PORTAL);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_TWILIGHT_TORMENT_VESPERON);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_TWILIGHT_TORMENT_SARTHARION);
if (!isCalledBySartharion || instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS)
instance->SetBossState(DATA_VESPERON, DONE);
break;

View File

@@ -215,12 +215,10 @@ public:
instance = me->GetInstanceScript();
if (!instance)
me->IsAIEnabled = false;
first = (instance && !instance->GetPersistentData(PERSISTENT_DATA_INTRO));
}
InstanceScript* instance;
EventMap events;
bool first;
bool shortver;
void Reset() override
@@ -228,9 +226,8 @@ public:
shortver = false;
events.Reset();
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
if (first)
if (instance && !instance->GetPersistentData(PERSISTENT_DATA_INTRO))
{
first = false;
events.ScheduleEvent(EVENT_PRE_INTRO_1, 10s);
events.ScheduleEvent(EVENT_PRE_INTRO_2, 11s);
events.ScheduleEvent(EVENT_EMOTE_LEADER_1, 16s);

View File

@@ -493,51 +493,6 @@ public:
}
};
class npc_icefang : public CreatureScript
{
public:
npc_icefang() : CreatureScript("npc_icefang") { }
struct npc_icefangAI : public npc_escortAI
{
npc_icefangAI(Creature* creature) : npc_escortAI(creature) { }
void AttackStart(Unit* /*who*/) override { }
void JustEngagedWith(Unit* /*who*/) override { }
void EnterEvadeMode(EvadeReason /*why*/) override { }
void PassengerBoarded(Unit* who, int8 /*seatId*/, bool apply) override
{
if (who->IsPlayer())
{
if (apply)
{
me->SetWalk(false);
Start(false, who->GetGUID());
}
}
}
using CreatureAI::WaypointReached;
void WaypointReached(uint32 /*waypointId*/) override { }
void JustDied(Unit* /*killer*/) override { }
void OnCharmed(bool /*apply*/) override { }
void UpdateAI(uint32 diff) override
{
npc_escortAI::UpdateAI(diff);
if (!UpdateVictim())
return;
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_icefangAI(creature);
}
};
struct npc_hyldsmeet_protodrake : public CreatureAI
{
explicit npc_hyldsmeet_protodrake(Creature* creature) : CreatureAI(creature), _accessoryInstalled(false), _accessoryRespawnTimer(0)
@@ -1344,7 +1299,6 @@ void AddSC_storm_peaks()
RegisterSpellScript(spell_q13007_iron_colossus);
new npc_brunnhildar_prisoner();
new npc_freed_protodrake();
new npc_icefang();
RegisterCreatureAI(npc_hyldsmeet_protodrake);
RegisterSpellScript(spell_close_rift_aura);
new npc_vehicle_d16_propelled_delivery();

View File

@@ -209,6 +209,16 @@ struct npc_pet_dk_ebon_gargoyle : ScriptedAI
_decisionTimer -= diff;
if (!UpdateVictimWithGaze())
{
// Re-engage if we still have a valid victim but lost engagement
// (e.g., PvP combat reference expired during CC like Cyclone)
if (Unit* victim = me->GetVictim())
{
if (me->IsValidAttackTarget(victim))
{
me->EngageWithTarget(victim);
return;
}
}
MySelectNextTarget();
return;
}
@@ -356,6 +366,26 @@ struct npc_pet_dk_army_of_the_dead : public AggressorAI
if (me->IsValidAttackTarget(attacker))
AttackStart(attacker);
}
void UpdateAI(uint32 /*diff*/) override
{
if (!UpdateVictim())
{
// Re-engage if we still have a valid victim but lost engagement
// (e.g., combat reference expired during CC like knockback)
if (Unit* victim = me->GetVictim())
{
if (me->IsValidAttackTarget(victim))
{
me->EngageWithTarget(victim);
return;
}
}
return;
}
DoMeleeAttackIfReady();
}
};
struct npc_pet_dk_dancing_rune_weapon : public NullCreatureAI