diff --git a/.github/SECURITY.md b/.github/SECURITY.md
index 7feca2632..00d09000e 100644
--- a/.github/SECURITY.md
+++ b/.github/SECURITY.md
@@ -4,60 +4,91 @@
We support the following versions of dependencies.
-:white_check_mark: = supported
+| Icon | Meaning |
+| :------------------- | :---------------: |
+| :white_check_mark: | **Supported** |
+| :red_circle: | **NOT** Supported |
+| :large_blue_diamond: | **Recommended** |
-:red_circle: = NOT supported
+### Versions of AzerothCore:
-unspecified = might work but no guarantee
+| AzerothCore Branch | Status | Recommended |
+| ---------------------------- | :----------------: | :------------------: |
+| **master** | :white_check_mark: | :large_blue_diamond: |
+| Any non-official fork | :red_circle: | |
+| Any Playerbots fork | :red_circle: | |
+| Any NPCBots fork | :red_circle: | |
+| Any AC (non-official) repack | :red_circle: | |
-Versions of AzerothCore:
+### Supported Operating Systems
-| AzerothCore Branch | Supported |
-| ------------------ | ------------------ |
-| master | :white_check_mark: |
-| Any playerbot fork | :red_circle: |
-| Any NPCBot fork | :red_circle: |
+| Linux (Ubuntu) | Status | Recommended |
+| :------------- | :----------------: | :------------------: |
+| 24.04 | :white_check_mark: | :large_blue_diamond: |
+| 22.04 | :white_check_mark: | |
+| 20.04 ≤ | :red_circle: | |
-Versions of MySQL:
+| macOS | Status | Recommended |
+| :---- | :----------------: | :------------------: |
+| 14 | :white_check_mark: | :large_blue_diamond: |
+| 12 ≤ | :red_circle: | |
-| MySQL Version | Supported |
-| ------------- | ------------------ |
-| 8.4 | :white_check_mark: |
-| 8.0 | :white_check_mark: |
-| 5.7 and lower | :red_circle: |
+| Windows | Status | Recommended |
+| :------------ | :----------------: | :------------------: |
+| Windows 11 | :white_check_mark: | :large_blue_diamond: |
+| Windows 10 | :white_check_mark: |
+| Windows 8.1 ≤ | :red_circle: |
-Versions of CLang:
+
-| CLang Version | Supported |
-| ------------- | ------------------ |
-| 18 | :white_check_mark: |
-| 15 | :white_check_mark: |
-| 14 and lower | :red_circle: |
+### Supported Boost Versions:
-Versions of GCC:
+| Boost | Status | Recommended |
+| :----- | :----------------: | :------------------: |
+| 1.70 ≥ | :white_check_mark: | :large_blue_diamond: |
-| GCC Version | Supported |
-| ------------ | ------------------ |
-| 14 | :white_check_mark: |
-| 12 | :white_check_mark: |
-| 11 and lower | :red_circle: |
+### Supported OpenSSL Versions:
-Versions of Ubuntu:
+| OpenSSL | Status | Recommended |
+| :------ | :----------------: | :------------------: |
+| 3.X.X ≥ | :white_check_mark: | :large_blue_diamond: |
-| Ubuntu version | Supported |
-| --------------- | ------------------ |
-| 24.04 | :white_check_mark: |
-| 22.04 | :white_check_mark: |
-| 20.04 and lower | :red_circle: |
+### Supported CMake Versions:
-Versions of macOS:
+| CMake | Status | Recommended |
+| :----- | :----------------: | :------------------: |
+| 3.16 ≥ | :white_check_mark: | :large_blue_diamond: |
-| macOS Version | Supported |
-| ------------- | ------------------ |
-| 14 | :white_check_mark: |
-| 12 and lower | :red_circle: |
+### Supported MySQL Versions:
-**Note**: We do NOT support any repacks that may or may not have been made based on AzerothCore. This is because they are usually based on older versions and there is no way to know what is in the precompiled binaries. Instead, you should compile your binaries from the AzerothCore source. To get started, read the [Installation Guide](https://www.azerothcore.org/wiki/installation).
+| MySQL | Status | Recommended |
+| :---- | :----------------: | :------------------: |
+| 8.4 ≥ | :white_check_mark: | :large_blue_diamond: |
+| 8.0 | :white_check_mark: | |
+| 8.1 | :red_circle: | |
+| 8.0 < | :red_circle: | |
+
+### Supported CLang Versions:
+
+| CLang | Status | Recommended |
+| :---- | :----------------: | :------------------: |
+| 18 | :white_check_mark: | :large_blue_diamond: |
+| 15 | :white_check_mark: | |
+| 14 ≤ | :red_circle: | |
+
+### Supported GCC Versions:
+
+| GCC | Status | Recommended |
+| :--- | :----------------: | :------------------: |
+| 14 | :white_check_mark: | :large_blue_diamond: |
+| 12 | :white_check_mark: | |
+| 11 ≤ | :red_circle: | |
+
+> [!NOTE]
+> We do **NOT** support any repacks that may or may not have been made based on AzerothCore. This is because they are usually based on older versions and there is no way to know what is in the precompiled binaries. Instead, you should compile your binaries from the AzerothCore source. To get started, read the [Installation Guide](https://www.azerothcore.org/wiki/installation).
+
+> [!CAUTION]
+> [Why you should not use repacks to run your WoW server](https://www.mangosrumors.org/why-you-should-not-use-repacks-to-run-your-wow-server/)
## Reporting a Vulnerability
diff --git a/apps/codestyle/codestyle-sql.py b/apps/codestyle/codestyle-sql.py
index f15dceed6..0df5dec05 100644
--- a/apps/codestyle/codestyle-sql.py
+++ b/apps/codestyle/codestyle-sql.py
@@ -112,7 +112,7 @@ def sql_check(file: io, file_path: str) -> None:
check_failed = True
if "EntryOrGuid" in line:
print(
- f"Please use entryorguid syntax instead of EntryOrgGuid in {file_path} at line {line_number}\nWe recommend to use keira to have the right syntax in auto-query generation")
+ f"Please use entryorguid syntax instead of EntryOrGuid in {file_path} at line {line_number}\nWe recommend to use keira to have the right syntax in auto-query generation")
check_failed = True
if [match for match in [';;'] if match in line]:
print(
@@ -142,6 +142,8 @@ def insert_safety_check(file: io, file_path: str) -> None:
# Parse all the file
for line_number, line in enumerate(file, start = 1):
+ if line.startswith("--"):
+ continue
if "INSERT" in line and "DELETE" not in previous_line:
print(f"No DELETE keyword found after the INSERT in {file_path} at line {line_number}\nIf this error is intended, please advert a maintainer")
check_failed = True
@@ -163,7 +165,11 @@ def semicolon_check(file: io, file_path: str) -> None:
total_lines = len(lines)
for line_number, line in enumerate(lines, start=1):
- stripped_line = line.rstrip() # Remove trailing whitespace including newline
+ if line.startswith('--'):
+ continue
+ # Remove trailing whitespace including newline
+ # Remove comments from the line
+ stripped_line = line.split('--', 1)[0].strip()
# Check if one keyword is in the line
if not query_open and any(keyword in stripped_line for keyword in sql_keywords):
diff --git a/data/sql/updates/db_auth/2025_01_26_00.sql b/data/sql/updates/db_auth/2025_01_26_00.sql
new file mode 100644
index 000000000..1c3f4f99b
--- /dev/null
+++ b/data/sql/updates/db_auth/2025_01_26_00.sql
@@ -0,0 +1,12 @@
+-- DB update 2024_12_15_00 -> 2025_01_26_00
+DROP TABLE IF EXISTS `autobroadcast_locale`;
+CREATE TABLE `autobroadcast_locale` (
+ `realmid` INT NOT NULL,
+ `id` INT NOT NULL,
+ `locale` VARCHAR(4) NOT NULL,
+ `text` VARCHAR(45) NULL,
+ PRIMARY KEY (`realmid`, `id`))
+CHARSET = utf8mb4
+COLLATE = utf8mb4_unicode_ci
+ENGINE = InnoDB
+;
diff --git a/data/sql/updates/db_world/2025_01_23_04.sql b/data/sql/updates/db_world/2025_01_23_04.sql
new file mode 100644
index 000000000..42396e60d
--- /dev/null
+++ b/data/sql/updates/db_world/2025_01_23_04.sql
@@ -0,0 +1,3 @@
+-- DB update 2025_01_23_03 -> 2025_01_23_04
+--
+UPDATE `creature_template_movement` SET `Rooted`= 1, `Flight` = 1 WHERE `CreatureId` = 24666;
diff --git a/data/sql/updates/db_world/2025_01_24_00.sql b/data/sql/updates/db_world/2025_01_24_00.sql
new file mode 100644
index 000000000..52974735b
--- /dev/null
+++ b/data/sql/updates/db_world/2025_01_24_00.sql
@@ -0,0 +1,22 @@
+-- DB update 2025_01_23_04 -> 2025_01_24_00
+-- Fix Kaelthas HC
+DELETE FROM `creature_loot_template` WHERE (`Entry` = 24857) AND (`Item` IN (23572, 25028, 25029, 34609, 34610, 34611, 34612, 34613, 34614, 34615, 34616));
+INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
+(24857, 23572, 0, 100, 0, 1, 0, 1, 1, 'Kael\'thas Sunstrider (1) - Primal Nether'),
+(24857, 34612, 0, 0, 0, 1, 1, 1, 1, 'Kael\'thas Sunstrider (1) - Greaves of the Penitent Knight'),
+(24857, 34609, 0, 0, 0, 1, 1, 1, 1, 'Kael\'thas Sunstrider (1) - Quickening Blade of the Prince'),
+(24857, 34611, 0, 0, 0, 1, 1, 1, 1, 'Kael\'thas Sunstrider (1) - Cudgel of Consecration'),
+(24857, 34610, 0, 0, 0, 1, 1, 1, 1, 'Kael\'thas Sunstrider (1) - Scarlet Sin\'dorei Robes'),
+(24857, 34614, 0, 0, 0, 1, 2, 1, 1, 'Kael\'thas Sunstrider (1) - Tunic of the Ranger Lord'),
+(24857, 34615, 0, 0, 0, 1, 2, 1, 1, 'Kael\'thas Sunstrider (1) - Netherforce Chestplate'),
+(24857, 34616, 0, 0, 0, 1, 2, 1, 1, 'Kael\'thas Sunstrider (1) - Breeching Comet'),
+(24857, 34613, 0, 0, 0, 1, 2, 1, 1, 'Kael\'thas Sunstrider (1) - Shoulderpads of the Silvermoon Retainer');
+
+-- Remove normal loot from Delrissa HC
+DELETE FROM `creature_loot_template` WHERE (`Entry` = 25560) AND (`Item` IN (25027));
+
+-- Remove normal loot from Vexallus HC
+DELETE FROM `creature_loot_template` WHERE (`Entry` = 25573) AND (`Item` IN (25026));
+
+-- Remove normal loot from Selin Fireheart HC
+DELETE FROM `creature_loot_template` WHERE (`Entry` = 25562) AND (`Item` IN (25025));
diff --git a/data/sql/updates/db_world/2025_01_24_01.sql b/data/sql/updates/db_world/2025_01_24_01.sql
new file mode 100644
index 000000000..a10c9cde7
--- /dev/null
+++ b/data/sql/updates/db_world/2025_01_24_01.sql
@@ -0,0 +1,4 @@
+-- DB update 2025_01_24_00 -> 2025_01_24_01
+--
+-- Remove extra Sanctum Planetarium
+DELETE FROM `gameobject` WHERE (`id` = 188081) AND (`guid` IN (27809));
diff --git a/data/sql/updates/db_world/2025_01_25_00.sql b/data/sql/updates/db_world/2025_01_25_00.sql
new file mode 100644
index 000000000..407ab7011
--- /dev/null
+++ b/data/sql/updates/db_world/2025_01_25_00.sql
@@ -0,0 +1,26 @@
+-- DB update 2025_01_24_01 -> 2025_01_25_00
+--
+DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24674);
+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
+(24674, 0, 0, 0, 37, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44196, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Phoenix - On Initialize - Cast \'Rebirth\''),
+(24674, 0, 1, 0, 25, 0, 100, 0, 0, 0, 0, 0, 0, 0, 42, 0, 5, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Phoenix - On Reset - Set Invincibility Hp 5%'),
+(24674, 0, 2, 0, 4, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44197, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Phoenix - On Aggro - Cast \'Burn\''),
+(24674, 0, 3, 0, 24, 0, 100, 0, 44226, 1, 5000, 5000, 0, 0, 11, 44202, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Phoenix - On Target Buffed With \'Gravity Lapse\' - Cast \'Fireball\''),
+(24674, 0, 4, 5, 2, 0, 100, 0, 0, 5, 10000, 10000, 0, 0, 11, 44199, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Phoenix - Between 0-5% Health - Cast \'Ember Blast\''),
+(24674, 0, 5, 6, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 12, 24675, 3, 20000, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Phoenix - Between 0-5% Health - Summon Creature \'Phoenix Egg\''),
+(24674, 0, 6, 7, 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, 'Phoenix - Between 0-5% Health - Set Reactstate Passive'),
+(24674, 0, 7, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Phoenix - Between 0-5% Health - Stop Combat'),
+(24674, 0, 8, 9, 8, 0, 100, 0, 44199, 0, 0, 0, 0, 0, 28, 44197, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Phoenix - On Spellhit \'Ember Blast\' - Remove Aura \'Burn\''),
+(24674, 0, 9, 10, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Phoenix - On Spellhit \'Ember Blast\' - Set Visibility Off'),
+(24674, 0, 10, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 204, 24675, 0, 0, 0, 0, 0, 0, 0, 'Phoenix - On Spellhit \'Ember Blast\' - Despawn Instant');
+
+DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24675);
+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
+(24675, 0, 0, 0, 37, 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, 'Phoenix Egg - On Initialize - Set Reactstate Passive'),
+(24675, 0, 1, 2, 60, 0, 100, 0, 15000, 15000, 0, 0, 0, 0, 142, 100, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 'Phoenix Egg - On Update - Set HP to 100%'),
+(24675, 0, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 28, 44199, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 'Phoenix Egg - On Update - Remove Aura \'Ember Blast\''),
+(24675, 0, 3, 4, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 8, 2, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 'Phoenix Egg - On Update - Set Reactstate Aggressive'),
+(24675, 0, 4, 5, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 'Phoenix Egg - On Update - Set In Combat With Zone'),
+(24675, 0, 5, 6, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 'Phoenix Egg - On Update - Set Visibility On'),
+(24675, 0, 6, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Phoenix Egg - On Update - Despawn Instant'),
+(24675, 0, 8, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 3000, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 'Phoenix Egg - On Just Died - Despawn In 3000 ms');
diff --git a/data/sql/updates/db_world/2025_01_26_00.sql b/data/sql/updates/db_world/2025_01_26_00.sql
new file mode 100644
index 000000000..2de6ccebc
--- /dev/null
+++ b/data/sql/updates/db_world/2025_01_26_00.sql
@@ -0,0 +1,10 @@
+-- DB update 2025_01_25_00 -> 2025_01_26_00
+--
+DROP TABLE IF EXISTS `creature_sparring`;
+CREATE TABLE `creature_sparring` (
+ `GUID` int unsigned NOT NULL,
+ `SparringPCT` float NOT NULL,
+ PRIMARY KEY (`GUID`),
+ FOREIGN KEY (`GUID`) REFERENCES creature(`guid`),
+ CONSTRAINT `creature_sparring_chk_1` CHECK (`SparringPCT` BETWEEN 0 AND 100)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
diff --git a/data/sql/updates/db_world/2025_01_26_01.sql b/data/sql/updates/db_world/2025_01_26_01.sql
new file mode 100644
index 000000000..174e77f24
--- /dev/null
+++ b/data/sql/updates/db_world/2025_01_26_01.sql
@@ -0,0 +1,61 @@
+-- DB update 2025_01_26_00 -> 2025_01_26_01
+
+-- Dragonflayer Vrykul
+UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 23652;
+
+DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 23652);
+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
+(23652, 0, 0, 0, 8, 0, 100, 1, 43381, 0, 0, 0, 0, 0, 11, 43384, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Vrykul - On Spellhit \'Plague Spray\' - Cast \'Spray Credit\' (No Repeat)'),
+(23652, 0, 1, 0, 4, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 38557, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Vrykul - On Aggro - Cast \'Throw\''),
+(23652, 0, 2, 0, 0, 0, 100, 0, 4000, 6000, 12000, 20000, 0, 0, 11, 43410, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Vrykul - In Combat - Cast \'Chop\''),
+(23652, 0, 3, 0, 0, 0, 100, 0, 25000, 30000, 30000, 45000, 0, 0, 11, 38557, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Vrykul - In Combat - Cast \'Throw\'');
+
+-- Dragonflayer Tribesman
+UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 23651;
+
+DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 23651);
+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
+(23651, 0, 0, 0, 9, 0, 100, 0, 8000, 10000, 8000, 10000, 8, 25, 11, 35570, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Tribesman - Within 8-25 Range - Cast \'Charge\''),
+(23651, 0, 1, 0, 0, 0, 100, 0, 12000, 18000, 50000, 60000, 0, 0, 11, 48193, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Tribesman - In Combat - Cast \'Enrage\''),
+(23651, 0, 2, 0, 0, 0, 100, 0, 2000, 6000, 8000, 12000, 0, 0, 11, 15496, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Tribesman - In Combat - Cast \'Cleave\'');
+
+-- Dragonflayer Thane
+UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 23660;
+
+DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 23660);
+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
+(23660, 0, 0, 0, 0, 0, 100, 0, 12000, 18000, 12000, 24000, 0, 0, 11, 11971, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Thane - In Combat - Cast \'Sunder Armor\''),
+(23660, 0, 1, 0, 0, 0, 100, 0, 8000, 12000, 12000, 16000, 0, 0, 11, 9080, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Thane - In Combat - Cast \'Hamstring\'');
+
+-- Dragonflayer Death Weaver
+UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 23658;
+
+DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 23658);
+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
+(23658, 0, 0, 0, 1, 0, 100, 0, 1000, 1000, 1000, 1000, 0, 0, 11, 43159, 0, 0, 0, 0, 0, 19, 24158, 30, 0, 0, 0, 0, 0, 0, 'Dragonflayer Death Weaver - Out of Combat - Cast \'Soul Infusion\''),
+(23658, 0, 1, 0, 0, 0, 100, 0, 2000, 4000, 8000, 12000, 0, 0, 11, 9613, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Death Weaver - In Combat - Cast \'Shadow Bolt\''),
+(23658, 0, 2, 0, 0, 0, 100, 0, 6000, 8000, 12000, 16000, 0, 0, 11, 43417, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Death Weaver - In Combat - Cast \'Drain Life\'');
+
+-- Dragonflayer Harpooner
+UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 24635;
+
+DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24635);
+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
+(24635, 0, 0, 0, 0, 0, 100, 0, 12000, 18000, 50000, 60000, 0, 0, 11, 48193, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Tribesman - In Combat - Cast \'Enrage\''),
+(24635, 0, 1, 0, 0, 0, 100, 0, 2000, 6000, 8000, 12000, 0, 0, 11, 43325, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Tribesman - In Combat - Cast \'Oluf`s Harpoon\'');
+
+-- Dragonflayer Lieutenant
+UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 24169;
+
+DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24169);
+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
+(24169, 0, 0, 0, 0, 0, 100, 0, 6000, 8000, 12000, 14000, 0, 0, 11, 48245, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Lieutenant - In Combat - Cast \'Head Slash\''),
+(24169, 0, 1, 0, 0, 0, 100, 0, 10000, 14000, 18000, 25000, 0, 0, 11, 48250, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Lieutenant - In Combat - Cast \'Risky Feint\'');
+
+-- Yanis the Mystic
+UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 23932;
+
+DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 23932);
+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
+(23932, 0, 0, 0, 0, 0, 100, 0, 6000, 8000, 12000, 14000, 0, 0, 11, 42870, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Yanis the Mystic - In Combat - Cast \'Throw Dragonflayer Harpoon\''),
+(23932, 0, 1, 0, 0, 0, 100, 0, 2000, 4000, 16000, 18000, 0, 0, 11, 58747, 0, 0, 0, 0, 0, 5, 25, 0, 0, 0, 0, 0, 0, 0, 'Yanis the Mystic - In Combat - Cast \'Intercept\'');
diff --git a/data/sql/updates/db_world/2025_01_26_02.sql b/data/sql/updates/db_world/2025_01_26_02.sql
new file mode 100644
index 000000000..db59d9c04
--- /dev/null
+++ b/data/sql/updates/db_world/2025_01_26_02.sql
@@ -0,0 +1,9 @@
+-- DB update 2025_01_26_01 -> 2025_01_26_02
+--
+-- Updates the Action from "Action Invoker" (7) to "Self" (1).
+UPDATE `smart_scripts` SET `target_type` = 1 WHERE `entryorguid` = 9456 AND `source_type` = 0 AND `id` = 1;
+
+-- Adds Strike sniffed from: 4.4.1.58158 and 1.15.5.57979
+DELETE FROM `smart_scripts` WHERE `entryorguid` = 9456 AND `source_type` = 0 AND `id` = 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
+(9456, 0, 0, 0, 0, 0, 100, 0, 0, 1000, 4000, 6000, 0, 0, 11, 11976, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Warlord Krom\'zar - In Combat - Cast \'Strike\'');
diff --git a/data/sql/updates/db_world/2025_01_27_00.sql b/data/sql/updates/db_world/2025_01_27_00.sql
new file mode 100644
index 000000000..a4d0d0138
--- /dev/null
+++ b/data/sql/updates/db_world/2025_01_27_00.sql
@@ -0,0 +1,6 @@
+-- DB update 2025_01_26_02 -> 2025_01_27_00
+--
+DELETE FROM `acore_string` WHERE `entry` IN (56, 82);
+INSERT INTO `acore_string` (`entry`, `content_default`, `locale_deDE`, `locale_zhCN`, `locale_esES`, `locale_esMX`) VALUES
+(56, 'Current Message of the day:', 'Aktuelle Nachricht des Tages:', '当前每日信息:', 'Mensaje actual del día:', 'Mensaje actual del día:'),
+(82, '{}: {}', '{}: {}', '{}: {}', '{}: {}', '{}: {}');
diff --git a/data/sql/updates/db_world/2025_01_27_01.sql b/data/sql/updates/db_world/2025_01_27_01.sql
new file mode 100644
index 000000000..0891dbedf
--- /dev/null
+++ b/data/sql/updates/db_world/2025_01_27_01.sql
@@ -0,0 +1,27 @@
+-- DB update 2025_01_27_00 -> 2025_01_27_01
+--
+UPDATE `creature_template` SET `flags_extra` = `flags_extra` |134217728 WHERE `entry` IN (24698, 24684, 24697, 24696, 24683, 24686);
+
+DELETE FROM `smart_scripts` WHERE (`entryorguid` = -96841) AND (`source_type` = 0) AND (`id` IN (0));
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(-96841, 0, 0, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 223, 0, 0, 0, 0, 0, 0, 205, 3, 1, 0, 0, 0, 0, 0, 0, 'Coilskar Witch - On Just Died - Felblood Kaeltas Do Action ID 0');
+
+DELETE FROM `smart_scripts` WHERE (`entryorguid` = -96781) AND (`source_type` = 0) AND (`id` IN (0));
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(-96781, 0, 0, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 223, 0, 0, 0, 0, 0, 0, 205, 3, 1, 0, 0, 0, 0, 0, 0, 'Sunblade Blood Knight - On Just Died - Felblood Kaeltas Do Action ID 0');
+
+DELETE FROM `smart_scripts` WHERE (`entryorguid` = -96809) AND (`source_type` = 0) AND (`id` IN (0));
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(-96809, 0, 0, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 223, 0, 0, 0, 0, 0, 0, 205, 3, 1, 0, 0, 0, 0, 0, 0, 'Sunblade Warlock - On Just Died - Felblood Kaeltas Do Action ID 0');
+
+DELETE FROM `smart_scripts` WHERE (`entryorguid` = -96770) AND (`source_type` = 0) AND (`id` IN (0));
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(-96770, 0, 0, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 223, 0, 0, 0, 0, 0, 0, 205, 3, 1, 0, 0, 0, 0, 0, 0, 'Sunblade Mage Guard - On Just Died - Felblood Kaeltas Do Action ID 0');
+
+DELETE FROM `smart_scripts` WHERE (`entryorguid` = -96850) AND (`source_type` = 0) AND (`id` IN (0));
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(-96850, 0, 0, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 223, 0, 0, 0, 0, 0, 0, 205, 3, 1, 0, 0, 0, 0, 0, 0, 'Ethereum Smuggler - On Just Died - Felblood Kaeltas Do Action ID 0');
+
+DELETE FROM `smart_scripts` WHERE (`entryorguid` = -96847) AND (`source_type` = 0) AND (`id` IN (0));
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(-96847, 0, 0, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 223, 0, 0, 0, 0, 0, 0, 205, 3, 1, 0, 0, 0, 0, 0, 0, 'Sister of Torment - On Just Died - Felblood Kaeltas Do Action ID 0');
diff --git a/data/sql/updates/db_world/2025_01_27_02.sql b/data/sql/updates/db_world/2025_01_27_02.sql
new file mode 100644
index 000000000..29f1c98cb
--- /dev/null
+++ b/data/sql/updates/db_world/2025_01_27_02.sql
@@ -0,0 +1,8 @@
+-- DB update 2025_01_27_01 -> 2025_01_27_02
+-- Fix Amani Trainer Abilities
+UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 23774;
+
+DELETE FROM `smart_scripts` WHERE (`entryorguid` = 23774) AND (`source_type` = 0) AND (`id` IN (0, 1));
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(23774, 0, 0, 0, 0, 0, 100, 0, 5000, 8000, 12000, 15000, 0, 0, 11, 43292, 0, 0, 0, 0, 0, 19, 23834, 30, 0, 0, 0, 0, 0, 0, 'Target Amashi Dragonhawk for Incite Rage'),
+(23774, 0, 1, 0, 0, 0, 100, 0, 10000, 12000, 20000, 25000, 0, 0, 11, 20989, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Cast Sleep on Random Enemy');
diff --git a/data/sql/updates/db_world/2025_01_28_00.sql b/data/sql/updates/db_world/2025_01_28_00.sql
new file mode 100644
index 000000000..4b0445d8e
--- /dev/null
+++ b/data/sql/updates/db_world/2025_01_28_00.sql
@@ -0,0 +1,8 @@
+-- DB update 2025_01_27_02 -> 2025_01_28_00
+
+UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 23774;
+
+DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 23774);
+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
+(23774, 0, 0, 0, 0, 0, 100, 0, 5000, 8000, 12000, 15000, 0, 0, 11, 43292, 0, 0, 0, 0, 0, 19, 23834, 30, 0, 0, 0, 0, 0, 0, 'Amani\'shi Trainer - In Combat - Cast \'Incite Rage\''),
+(23774, 0, 1, 0, 0, 0, 100, 0, 10000, 12000, 20000, 25000, 0, 0, 11, 20989, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Amani\'shi Trainer - In Combat - Cast \'Sleep\'');
diff --git a/src/common/Common.cpp b/src/common/Common.cpp
index e25611e06..530dec961 100644
--- a/src/common/Common.cpp
+++ b/src/common/Common.cpp
@@ -30,13 +30,20 @@ char const* localeNames[TOTAL_LOCALES] =
"ruRU"
};
+bool IsLocaleValid(std::string const& locale)
+{
+ for (int i = 0; i < TOTAL_LOCALES; ++i)
+ if (locale == localeNames[i])
+ return true;
+
+ return false;
+}
+
LocaleConstant GetLocaleByName(const std::string& name)
{
for (uint32 i = 0; i < TOTAL_LOCALES; ++i)
if (name == localeNames[i])
- {
return LocaleConstant(i);
- }
return LOCALE_enUS; // including enGB case
}
diff --git a/src/common/Common.h b/src/common/Common.h
index 6b7f482db..87ec6b4d2 100644
--- a/src/common/Common.h
+++ b/src/common/Common.h
@@ -83,6 +83,7 @@ enum LocaleConstant
AC_COMMON_API extern char const* localeNames[TOTAL_LOCALES];
+AC_COMMON_API bool IsLocaleValid(std::string const& locale);
AC_COMMON_API LocaleConstant GetLocaleByName(const std::string& name);
AC_COMMON_API const std::string GetNameByLocaleConstant(LocaleConstant localeConstant);
AC_COMMON_API void CleanStringForMysqlQuery(std::string& str);
diff --git a/src/server/database/Database/Implementation/LoginDatabase.cpp b/src/server/database/Database/Implementation/LoginDatabase.cpp
index ca56f4ac9..f552c8175 100644
--- a/src/server/database/Database/Implementation/LoginDatabase.cpp
+++ b/src/server/database/Database/Implementation/LoginDatabase.cpp
@@ -116,10 +116,11 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_SEL_REALMLIST_SECURITY_LEVEL, "SELECT allowedSecurityLevel from realmlist WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_DEL_ACCOUNT, "DELETE FROM account WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_AUTOBROADCAST, "SELECT id, weight, text FROM autobroadcast WHERE realmid = ? OR realmid = -1", CONNECTION_SYNCH);
+ PrepareStatement(LOGIN_SEL_AUTOBROADCAST_LOCALIZED, "SELECT id, locale, text FROM autobroadcast_locale WHERE realmid = ? OR realmid = -1", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_MOTD, "SELECT text FROM motd WHERE realmid = ? OR realmid = -1 ORDER BY realmid DESC", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_MOTD_LOCALE, "SELECT locale, text FROM motd_localized WHERE realmid = ? OR realmid = -1 ORDER BY realmid DESC", CONNECTION_SYNCH);
- PrepareStatement(LOGIN_INS_MOTD, "INSERT INTO motd (realmid, text) VALUES (?, ?) ON DUPLICATE KEY UPDATE text = ?", CONNECTION_ASYNC);
- PrepareStatement(LOGIN_INS_MOTD_LOCALE, "INSERT INTO motd_localized (realmid, locale, text) VALUES(?, ?, ?) ON DUPLICATE KEY UPDATE text = ?;", CONNECTION_ASYNC);
+ PrepareStatement(LOGIN_REP_MOTD, "REPLACE INTO motd (realmid, text) VALUES (?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(LOGIN_REP_MOTD_LOCALE, "REPLACE INTO motd_localized (realmid, locale, text) VALUES (?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(LOGIN_INS_ACCOUNT_MUTE, "INSERT INTO account_muted VALUES (?, UNIX_TIMESTAMP(), ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_ACCOUNT_MUTE_INFO, "SELECT mutedate, mutetime, mutereason, mutedby FROM account_muted WHERE guid = ? ORDER BY mutedate ASC", CONNECTION_SYNCH);
PrepareStatement(LOGIN_DEL_ACCOUNT_MUTED, "DELETE FROM account_muted WHERE guid = ?", CONNECTION_ASYNC);
diff --git a/src/server/database/Database/Implementation/LoginDatabase.h b/src/server/database/Database/Implementation/LoginDatabase.h
index ad1ceec8f..c99ee5902 100644
--- a/src/server/database/Database/Implementation/LoginDatabase.h
+++ b/src/server/database/Database/Implementation/LoginDatabase.h
@@ -98,10 +98,11 @@ enum LoginDatabaseStatements : uint32
LOGIN_SEL_REALMLIST_SECURITY_LEVEL,
LOGIN_DEL_ACCOUNT,
LOGIN_SEL_AUTOBROADCAST,
+ LOGIN_SEL_AUTOBROADCAST_LOCALIZED,
LOGIN_SEL_MOTD,
LOGIN_SEL_MOTD_LOCALE,
- LOGIN_INS_MOTD,
- LOGIN_INS_MOTD_LOCALE,
+ LOGIN_REP_MOTD,
+ LOGIN_REP_MOTD_LOCALE,
LOGIN_SEL_LAST_ATTEMPT_IP,
LOGIN_SEL_LAST_IP,
LOGIN_INS_ALDL_IP_LOGGING,
diff --git a/src/server/game/Autobroadcast/AutobroadcastMgr.cpp b/src/server/game/Autobroadcast/AutobroadcastMgr.cpp
index 8b31bf893..a7756c658 100644
--- a/src/server/game/Autobroadcast/AutobroadcastMgr.cpp
+++ b/src/server/game/Autobroadcast/AutobroadcastMgr.cpp
@@ -42,7 +42,6 @@ void AutobroadcastMgr::LoadAutobroadcasts()
if (!result)
{
LOG_WARN("autobroadcast", ">> Loaded 0 autobroadcasts definitions. DB table `autobroadcast` is empty for this realm!");
- LOG_INFO("autobroadcast", " ");
return;
}
@@ -54,35 +53,66 @@ void AutobroadcastMgr::LoadAutobroadcasts()
_announceType = AnnounceType::World;
}
- uint32 count = 0;
+ do
+ {
+ Field* fields = result->Fetch();
+ uint8 textId = fields[0].Get();
+
+ ObjectMgr::AddLocaleString(fields[2].Get(), DEFAULT_LOCALE, _autobroadcasts[textId]);
+ _autobroadcastsWeights[textId] = fields[1].Get();
+
+ } while (result->NextRow());
+
+ LOG_INFO("server.loading", ">> Loaded {} Autobroadcast Definitions in {} ms", _autobroadcasts.size(), GetMSTimeDiffToNow(oldMSTime));
+}
+
+void AutobroadcastMgr::LoadAutobroadcastsLocalized()
+{
+ uint32 oldMSTime = getMSTime();
+ uint32 realmId = sConfigMgr->GetOption("RealmID", 0);
+
+ if (_autobroadcasts.empty())
+ return;
+
+ LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_AUTOBROADCAST_LOCALIZED);
+ stmt->SetData(0, realmId);
+ PreparedQueryResult result = LoginDatabase.Query(stmt);
+
+ if (!result)
+ {
+ LOG_WARN("server.loading", ">> Loaded 0 localized autobroadcasts definitions. DB table `autobroadcast_localized` is empty for this realm!");
+ LOG_INFO("server.loading", " ");
+ return;
+ }
+
+ uint8 count = 0;
do
{
Field* fields = result->Fetch();
- uint8 id = fields[0].Get();
+ uint8 textId = fields[0].Get();
+ LocaleConstant locale = GetLocaleByName(fields[1].Get());
- _autobroadcasts[id] = fields[2].Get();
- _autobroadcastsWeights[id] = fields[1].Get();
+ if (locale == DEFAULT_LOCALE || ObjectMgr::GetLocaleString(_autobroadcasts[textId], DEFAULT_LOCALE).empty())
+ continue;
- ++count;
+ ObjectMgr::AddLocaleString(fields[2].Get(), locale, _autobroadcasts[textId]);
+ count++;
} while (result->NextRow());
- LOG_INFO("autobroadcast", ">> Loaded {} Autobroadcast Definitions in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
- LOG_INFO("autobroadcast", " ");
+ LOG_INFO("server.loading", ">> Loaded {} Localized Autobroadcast Definitions in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
+ LOG_INFO("server.loading", " ");
}
void AutobroadcastMgr::SendAutobroadcasts()
{
if (_autobroadcasts.empty())
- {
return;
- }
uint32 weight = 0;
+ uint8 textId = 0;
AutobroadcastsWeightMap selectionWeights;
- std::string msg;
-
for (AutobroadcastsWeightMap::const_iterator it = _autobroadcastsWeights.begin(); it != _autobroadcastsWeights.end(); ++it)
{
if (it->second)
@@ -101,42 +131,78 @@ void AutobroadcastMgr::SendAutobroadcasts()
weight += it->second;
if (selectedWeight < weight)
{
- msg = _autobroadcasts[it->first];
+ textId = it->first;
break;
}
}
}
else
{
- msg = _autobroadcasts[urand(0, _autobroadcasts.size())];
+ textId = urand(0, _autobroadcasts.size());
}
switch (_announceType)
{
case AnnounceType::World:
- SendWorldAnnouncement(msg);
+ SendWorldAnnouncement(textId);
break;
case AnnounceType::Notification:
- SendNotificationAnnouncement(msg);
+ SendNotificationAnnouncement(textId);
break;
case AnnounceType::Both:
- SendWorldAnnouncement(msg);
- SendNotificationAnnouncement(msg);
+ SendWorldAnnouncement(textId);
+ SendNotificationAnnouncement(textId);
default:
break;
}
- LOG_DEBUG("autobroadcast", "AutobroadcastMgr::SendAutobroadcasts: '{}'", msg);
+ LOG_DEBUG("autobroadcast", "AutobroadcastMgr::SendAutobroadcasts: '{}'", textId);
}
-void AutobroadcastMgr::SendWorldAnnouncement(std::string msg)
+void AutobroadcastMgr::SendWorldAnnouncement(uint8 textId)
{
- ChatHandler(nullptr).SendWorldTextOptional(LANG_AUTO_BROADCAST, ANNOUNCER_FLAG_DISABLE_AUTOBROADCAST, msg.data());
+ // Send localized messages to all sessions
+ ChatHandler(nullptr).DoForAllValidSessions([&](Player* player)
+ {
+ // Get player's locale
+ LocaleConstant locale = player->GetSession()->GetSessionDbLocaleIndex();
+
+ if (!_autobroadcasts.empty())
+ return;
+
+ std::string_view localizedMessage = ObjectMgr::GetLocaleString(_autobroadcasts[textId], locale);
+
+ // Check if there is a localized message if not use default one.
+ if (localizedMessage.empty())
+ localizedMessage = ObjectMgr::GetLocaleString(_autobroadcasts[textId], DEFAULT_LOCALE);
+
+ // Send the localized or fallback message
+ ChatHandler(player->GetSession()).SendWorldTextOptional(localizedMessage, ANNOUNCER_FLAG_DISABLE_AUTOBROADCAST);
+ });
}
-void AutobroadcastMgr::SendNotificationAnnouncement(std::string msg)
+void AutobroadcastMgr::SendNotificationAnnouncement(uint8 textId)
{
- WorldPacket data(SMSG_NOTIFICATION, (msg.size() + 1));
- data << msg.data();
- sWorld->SendGlobalMessage(&data);
+ ChatHandler(nullptr).DoForAllValidSessions([&](Player* player)
+ {
+ // Retrieve player's locale
+ LocaleConstant locale = player->GetSession()->GetSessionDbLocaleIndex();
+
+ if (!_autobroadcasts.count(textId))
+ return;
+
+ // Get localized message
+ std::string_view localizedMessage = ObjectMgr::GetLocaleString(_autobroadcasts[textId], locale);
+
+ // Check if there is a localized message if not use default one.
+ if (localizedMessage.empty())
+ localizedMessage = ObjectMgr::GetLocaleString(_autobroadcasts[textId], DEFAULT_LOCALE);
+
+ // Prepare the WorldPacket
+ WorldPacket data(SMSG_NOTIFICATION, (localizedMessage.size() + 1));
+ data << localizedMessage;
+
+ // Send packet to the player
+ player->GetSession()->SendPacket(&data);
+ });
}
diff --git a/src/server/game/Autobroadcast/AutobroadcastMgr.h b/src/server/game/Autobroadcast/AutobroadcastMgr.h
index 3f4066e91..05dc6319e 100644
--- a/src/server/game/Autobroadcast/AutobroadcastMgr.h
+++ b/src/server/game/Autobroadcast/AutobroadcastMgr.h
@@ -20,6 +20,7 @@
#include "Common.h"
#include