mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-13 01:08:35 +00:00
Merge branch 'master' into Playerbot
This commit is contained in:
109
.github/SECURITY.md
vendored
109
.github/SECURITY.md
vendored
@@ -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:
|
||||
<br>
|
||||
|
||||
| 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
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
12
data/sql/updates/db_auth/2025_01_26_00.sql
Normal file
12
data/sql/updates/db_auth/2025_01_26_00.sql
Normal file
@@ -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
|
||||
;
|
||||
3
data/sql/updates/db_world/2025_01_23_04.sql
Normal file
3
data/sql/updates/db_world/2025_01_23_04.sql
Normal file
@@ -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;
|
||||
22
data/sql/updates/db_world/2025_01_24_00.sql
Normal file
22
data/sql/updates/db_world/2025_01_24_00.sql
Normal file
@@ -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));
|
||||
4
data/sql/updates/db_world/2025_01_24_01.sql
Normal file
4
data/sql/updates/db_world/2025_01_24_01.sql
Normal file
@@ -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));
|
||||
26
data/sql/updates/db_world/2025_01_25_00.sql
Normal file
26
data/sql/updates/db_world/2025_01_25_00.sql
Normal file
@@ -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');
|
||||
10
data/sql/updates/db_world/2025_01_26_00.sql
Normal file
10
data/sql/updates/db_world/2025_01_26_00.sql
Normal file
@@ -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;
|
||||
61
data/sql/updates/db_world/2025_01_26_01.sql
Normal file
61
data/sql/updates/db_world/2025_01_26_01.sql
Normal file
@@ -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\'');
|
||||
9
data/sql/updates/db_world/2025_01_26_02.sql
Normal file
9
data/sql/updates/db_world/2025_01_26_02.sql
Normal file
@@ -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\'');
|
||||
6
data/sql/updates/db_world/2025_01_27_00.sql
Normal file
6
data/sql/updates/db_world/2025_01_27_00.sql
Normal file
@@ -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, '{}: {}', '{}: {}', '{}: {}', '{}: {}', '{}: {}');
|
||||
27
data/sql/updates/db_world/2025_01_27_01.sql
Normal file
27
data/sql/updates/db_world/2025_01_27_01.sql
Normal file
@@ -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');
|
||||
8
data/sql/updates/db_world/2025_01_27_02.sql
Normal file
8
data/sql/updates/db_world/2025_01_27_02.sql
Normal file
@@ -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');
|
||||
8
data/sql/updates/db_world/2025_01_28_00.sql
Normal file
8
data/sql/updates/db_world/2025_01_28_00.sql
Normal file
@@ -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\'');
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<uint8>();
|
||||
|
||||
ObjectMgr::AddLocaleString(fields[2].Get<std::string>(), DEFAULT_LOCALE, _autobroadcasts[textId]);
|
||||
_autobroadcastsWeights[textId] = fields[1].Get<uint8>();
|
||||
|
||||
} 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<int32>("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>();
|
||||
uint8 textId = fields[0].Get<uint8>();
|
||||
LocaleConstant locale = GetLocaleByName(fields[1].Get<std::string>());
|
||||
|
||||
_autobroadcasts[id] = fields[2].Get<std::string>();
|
||||
_autobroadcastsWeights[id] = fields[1].Get<uint8>();
|
||||
if (locale == DEFAULT_LOCALE || ObjectMgr::GetLocaleString(_autobroadcasts[textId], DEFAULT_LOCALE).empty())
|
||||
continue;
|
||||
|
||||
++count;
|
||||
ObjectMgr::AddLocaleString(fields[2].Get<std::string>(), 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);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "Common.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
enum class AnnounceType : uint8
|
||||
{
|
||||
@@ -34,17 +35,18 @@ public:
|
||||
static AutobroadcastMgr* instance();
|
||||
|
||||
void LoadAutobroadcasts();
|
||||
void LoadAutobroadcastsLocalized();
|
||||
void SendAutobroadcasts();
|
||||
|
||||
private:
|
||||
void SendWorldAnnouncement(std::string msg);
|
||||
void SendNotificationAnnouncement(std::string msg);
|
||||
void SendWorldAnnouncement(uint8 textId);
|
||||
void SendNotificationAnnouncement(uint8 textId);
|
||||
|
||||
typedef std::map<uint8, std::string> AutobroadcastsMap;
|
||||
typedef std::map<uint8, std::vector<std::string>> AutobroadcastsMap;
|
||||
typedef std::map<uint8, uint8> AutobroadcastsWeightMap;
|
||||
|
||||
AutobroadcastsMap _autobroadcasts;
|
||||
AutobroadcastsWeightMap _autobroadcastsWeights;
|
||||
AutobroadcastsMap _autobroadcasts; // autobroadcast messages
|
||||
AutobroadcastsWeightMap _autobroadcastsWeights; // Weights for each message
|
||||
|
||||
AnnounceType _announceType;
|
||||
};
|
||||
|
||||
@@ -273,7 +273,7 @@ Creature::Creature(bool isWorldObject): Unit(isWorldObject), MovableMapObject(),
|
||||
m_transportCheckTimer(1000), lootPickPocketRestoreTime(0), m_combatPulseTime(0), m_combatPulseDelay(0), m_reactState(REACT_AGGRESSIVE), m_defaultMovementType(IDLE_MOTION_TYPE),
|
||||
m_spawnId(0), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false),
|
||||
m_AlreadySearchedAssistance(false), m_regenHealth(true), m_regenPower(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_moveInLineOfSightDisabled(false), m_moveInLineOfSightStrictlyDisabled(false),
|
||||
m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_detectionDistance(20.0f), m_waypointID(0), m_path_id(0), m_formation(nullptr), m_lastLeashExtensionTime(nullptr), m_cannotReachTimer(0),
|
||||
m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_detectionDistance(20.0f),_sparringPct(0.0f), m_waypointID(0), m_path_id(0), m_formation(nullptr), m_lastLeashExtensionTime(nullptr), m_cannotReachTimer(0),
|
||||
_isMissingSwimmingFlagOutOfCombat(false), m_assistanceTimer(0), _playerDamageReq(0), _damagedByPlayer(false), _isCombatMovementAllowed(true)
|
||||
{
|
||||
m_regenTimer = CREATURE_REGEN_INTERVAL;
|
||||
@@ -608,6 +608,8 @@ bool Creature::UpdateEntry(uint32 Entry, const CreatureData* data, bool changele
|
||||
SetCanModifyStats(true);
|
||||
UpdateAllStats();
|
||||
|
||||
LoadSparringPct();
|
||||
|
||||
// checked and error show at loading templates
|
||||
if (FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(cInfo->faction))
|
||||
{
|
||||
@@ -1189,6 +1191,7 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, u
|
||||
}
|
||||
|
||||
LoadCreaturesAddon();
|
||||
LoadSparringPct();
|
||||
|
||||
//! Need to be called after LoadCreaturesAddon - MOVEMENTFLAG_HOVER is set there
|
||||
m_positionZ += GetHoverHeight();
|
||||
@@ -2025,6 +2028,8 @@ void Creature::setDeathState(DeathState state, bool despawn)
|
||||
|
||||
Motion_Initialize();
|
||||
LoadCreaturesAddon(true);
|
||||
LoadSparringPct();
|
||||
|
||||
if (GetCreatureData() && GetPhaseMask() != GetCreatureData()->phaseMask)
|
||||
SetPhaseMask(GetCreatureData()->phaseMask, false);
|
||||
}
|
||||
@@ -2798,6 +2803,18 @@ bool Creature::LoadCreaturesAddon(bool reload)
|
||||
return true;
|
||||
}
|
||||
|
||||
void Creature::LoadSparringPct()
|
||||
{
|
||||
ObjectGuid::LowType spawnId = GetSpawnId();
|
||||
auto const& sparringData = sObjectMgr->GetSparringData();
|
||||
|
||||
auto itr = sparringData.find(spawnId);
|
||||
if (itr != sparringData.end() && !itr->second.empty())
|
||||
{
|
||||
_sparringPct = itr->second[0];
|
||||
}
|
||||
}
|
||||
|
||||
/// Send a message to LocalDefense channel for players opposition team in the zone
|
||||
void Creature::SendZoneUnderAttackMessage(Player* attacker)
|
||||
{
|
||||
|
||||
@@ -187,6 +187,9 @@ public:
|
||||
void UpdateAttackPowerAndDamage(bool ranged = false) override;
|
||||
void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage, uint8 damageIndex) override;
|
||||
|
||||
void LoadSparringPct();
|
||||
[[nodiscard]] float GetSparringPct() const { return _sparringPct; }
|
||||
|
||||
bool HasWeapon(WeaponAttackType type) const override;
|
||||
bool HasWeaponForAttack(WeaponAttackType type) const override { return (Unit::HasWeaponForAttack(type) && HasWeapon(type)); }
|
||||
void SetCanDualWield(bool value) override;
|
||||
@@ -483,6 +486,8 @@ protected:
|
||||
float m_detectionDistance;
|
||||
uint16 m_LootMode; // bitmask, default LOOT_MODE_DEFAULT, determines what loot will be lootable
|
||||
|
||||
float _sparringPct;
|
||||
|
||||
[[nodiscard]] bool IsInvisibleDueToDespawn() const override;
|
||||
bool CanAlwaysSee(WorldObject const* obj) const override;
|
||||
bool IsAlwaysDetectableFor(WorldObject const* seer) const override;
|
||||
|
||||
@@ -1032,6 +1032,17 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
|
||||
}
|
||||
}
|
||||
|
||||
// Sparring
|
||||
if (victim->CanSparringWith(attacker))
|
||||
{
|
||||
if (damage >= victim->GetHealth())
|
||||
damage = 0;
|
||||
|
||||
uint32 sparringHealth = victim->GetHealth() * (victim->ToCreature()->GetSparringPct() / 100);
|
||||
if (victim->GetHealth() - damage <= sparringHealth)
|
||||
damage = 0;
|
||||
}
|
||||
|
||||
if (health <= damage)
|
||||
{
|
||||
LOG_DEBUG("entities.unit", "DealDamage: victim just died");
|
||||
@@ -2635,6 +2646,10 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType /*= BASE_A
|
||||
Unit::DealDamageMods(victim, damageInfo.damages[i].damage, &damageInfo.damages[i].absorb);
|
||||
}
|
||||
|
||||
// Related to sparring system. Allow attack animations even if there are no damages
|
||||
if (victim->CanSparringWith(damageInfo.attacker))
|
||||
damageInfo.HitInfo |= HITINFO_FAKE_DAMAGE;
|
||||
|
||||
SendAttackStateUpdate(&damageInfo);
|
||||
|
||||
//TriggerAurasProcOnEvent(damageInfo);
|
||||
@@ -3954,6 +3969,24 @@ void Unit::_UpdateAutoRepeatSpell()
|
||||
}
|
||||
}
|
||||
|
||||
bool Unit::CanSparringWith(Unit const* attacker) const
|
||||
{
|
||||
if (!IsCreature() || IsCharmedOwnedByPlayerOrPlayer())
|
||||
return false;
|
||||
|
||||
if (!attacker)
|
||||
return false;
|
||||
|
||||
if (!attacker->IsCreature() || attacker->IsCharmedOwnedByPlayerOrPlayer())
|
||||
return false;
|
||||
|
||||
if (Creature const* creature = ToCreature())
|
||||
if (!creature->GetSparringPct())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Unit::SetCurrentCastedSpell(Spell* pSpell)
|
||||
{
|
||||
ASSERT(pSpell); // nullptr may be never passed here, use InterruptSpell or InterruptNonMeleeSpells
|
||||
|
||||
@@ -726,6 +726,9 @@ public:
|
||||
void RemoveUnitFlag2(UnitFlags2 flags) { RemoveFlag(UNIT_FIELD_FLAGS_2, flags); }
|
||||
void ReplaceAllUnitFlags2(UnitFlags2 flags) { SetUInt32Value(UNIT_FIELD_FLAGS_2, flags); }
|
||||
|
||||
void SetEmoteState(Emote emoteState) { SetUInt32Value(UNIT_NPC_EMOTESTATE, emoteState); } /// @brief Sets emote state (looping emote). Emotes available in SharedDefines.h
|
||||
void ClearEmoteState() { SetEmoteState(EMOTE_ONESHOT_NONE); } /// @brief Clears emote state (looping emote)
|
||||
|
||||
// NPC flags
|
||||
NPCFlags GetNpcFlags() const { return NPCFlags(GetUInt32Value(UNIT_NPC_FLAGS)); }
|
||||
bool HasNpcFlag(NPCFlags flags) const { return HasFlag(UNIT_NPC_FLAGS, flags) != 0; }
|
||||
@@ -2044,6 +2047,8 @@ protected:
|
||||
|
||||
void _UpdateAutoRepeatSpell();
|
||||
|
||||
bool CanSparringWith(Unit const* attacker) const; ///@brief: Check if unit is eligible for sparring damages. Work only if attacker and victim are creatures.
|
||||
|
||||
bool IsAlwaysVisibleFor(WorldObject const* seer) const override;
|
||||
bool IsAlwaysDetectableFor(WorldObject const* seer) const override;
|
||||
|
||||
|
||||
@@ -2298,6 +2298,42 @@ void ObjectMgr::LoadCreatures()
|
||||
LOG_INFO("server.loading", " ");
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadCreatureSparring()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
QueryResult result = WorldDatabase.Query("SELECT GUID, SparringPCT FROM creature_sparring");
|
||||
|
||||
if (!result)
|
||||
{
|
||||
LOG_WARN("server.loading", ">> Loaded 0 sparring data. DB table `creature_sparring` is empty.");
|
||||
LOG_INFO("server.loading", " ");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 count = 0;
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
ObjectGuid::LowType spawnId = fields[0].Get<uint32>();
|
||||
float sparringHealthPct = fields[1].Get<float>();
|
||||
|
||||
if (!sObjectMgr->GetCreatureData(spawnId))
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Entry {} has a record in `creature_sparring` but doesn't exist in `creatures` table");
|
||||
continue;
|
||||
}
|
||||
|
||||
_creatureSparringStore[spawnId].push_back(sparringHealthPct);
|
||||
|
||||
++count;
|
||||
} while (result->NextRow());
|
||||
|
||||
LOG_INFO("server.loading", ">> Loaded {} sparring data in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
|
||||
LOG_INFO("server.loading", " ");
|
||||
}
|
||||
|
||||
void ObjectMgr::AddCreatureToGrid(ObjectGuid::LowType guid, CreatureData const* data)
|
||||
{
|
||||
uint8 mask = data->spawnMask;
|
||||
|
||||
@@ -751,6 +751,8 @@ public:
|
||||
|
||||
typedef std::map<uint32, uint32> CharacterConversionMap;
|
||||
|
||||
typedef std::unordered_map<ObjectGuid::LowType, std::vector<float>> CreatureSparringContainer;
|
||||
|
||||
GameObjectTemplate const* GetGameObjectTemplate(uint32 entry);
|
||||
bool IsGameObjectStaticTransport(uint32 entry);
|
||||
[[nodiscard]] GameObjectTemplateContainer const* GetGameObjectTemplates() const { return &_gameObjectTemplateStore; }
|
||||
@@ -1029,6 +1031,7 @@ public:
|
||||
void LoadCreatureQuestItems();
|
||||
void LoadTempSummons();
|
||||
void LoadCreatures();
|
||||
void LoadCreatureSparring();
|
||||
void LoadLinkedRespawn();
|
||||
bool SetCreatureLinkedRespawn(ObjectGuid::LowType guid, ObjectGuid::LowType linkedGuid);
|
||||
void LoadCreatureAddons();
|
||||
@@ -1202,6 +1205,9 @@ public:
|
||||
if (itr == _creatureDataStore.end()) return nullptr;
|
||||
return &itr->second;
|
||||
}
|
||||
|
||||
[[nodiscard]] CreatureSparringContainer const& GetSparringData() const { return _creatureSparringStore; }
|
||||
|
||||
CreatureData& NewOrExistCreatureData(ObjectGuid::LowType spawnId) { return _creatureDataStore[spawnId]; }
|
||||
void DeleteCreatureData(ObjectGuid::LowType spawnId);
|
||||
[[nodiscard]] ObjectGuid GetLinkedRespawnGuid(ObjectGuid guid) const
|
||||
@@ -1527,6 +1533,8 @@ private:
|
||||
PageTextContainer _pageTextStore;
|
||||
InstanceTemplateContainer _instanceTemplateStore;
|
||||
|
||||
CreatureSparringContainer _creatureSparringStore;
|
||||
|
||||
private:
|
||||
void LoadScripts(ScriptsType type);
|
||||
void LoadQuestRelationsHelper(QuestRelations& map, std::string const& table, bool starter, bool go);
|
||||
|
||||
@@ -749,6 +749,9 @@ void WorldSession::HandleAuctionListItems(WorldPacket& recvData)
|
||||
if (usable)
|
||||
{
|
||||
AuctionHouseUsablePlayerInfo usablePlayerInfo;
|
||||
usablePlayerInfo.classMask = GetPlayer()->getClassMask();
|
||||
usablePlayerInfo.raceMask = GetPlayer()->getRaceMask();
|
||||
usablePlayerInfo.level = GetPlayer()->GetLevel();
|
||||
|
||||
SkillStatusMap const& skillMap = GetPlayer()->GetSkillStatusMap();
|
||||
for (auto const& pair : skillMap)
|
||||
|
||||
@@ -111,7 +111,8 @@ enum AcoreStrings
|
||||
LANG_RBAC_PERM_REVOKED_NOT_IN_LIST = 79,
|
||||
LANG_PVPSTATS = 80,
|
||||
LANG_PVPSTATS_DISABLED = 81,
|
||||
// Free 82 - 86
|
||||
LANG_GENERIC_TWO_CURLIES_WITH_COLON = 82,
|
||||
// Free 83 - 86
|
||||
|
||||
LANG_UNKNOWN_ERROR = 87,
|
||||
LANG_2FA_COMMANDS_NOT_SETUP = 88,
|
||||
|
||||
@@ -39,11 +39,6 @@ MotdMgr* MotdMgr::instance()
|
||||
return &instance;
|
||||
}
|
||||
|
||||
bool MotdMgr::IsValidLocale(std::string const& locale) {
|
||||
// Use std::find to search for the locale in the array
|
||||
return std::find(std::begin(localeNames), std::end(localeNames), locale) != std::end(localeNames);
|
||||
}
|
||||
|
||||
void MotdMgr::SetMotd(std::string motd, LocaleConstant locale)
|
||||
{
|
||||
// scripts may change motd
|
||||
@@ -53,31 +48,76 @@ void MotdMgr::SetMotd(std::string motd, LocaleConstant locale)
|
||||
MotdPackets[locale] = CreateWorldPacket(motd);
|
||||
}
|
||||
|
||||
void MotdMgr::CreateWorldPackages()
|
||||
{
|
||||
for (auto const& [locale, motd] : MotdMap)
|
||||
// Store the constructed packet in MotdPackets with the locale as the key
|
||||
MotdPackets[locale] = CreateWorldPacket(motd);
|
||||
}
|
||||
|
||||
void MotdMgr::LoadMotd()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
uint32 realmId = sConfigMgr->GetOption<int32>("RealmID", 0);
|
||||
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_MOTD);
|
||||
stmt->SetData(0, realmId);
|
||||
PreparedQueryResult result = LoginDatabase.Query(stmt);
|
||||
|
||||
// Load the main motd for the realm and assign it to enUS if available
|
||||
std::string motd = LoadDefaultMotd(realmId);
|
||||
if (result)
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
std::string motd = fields[0].Get<std::string>();
|
||||
|
||||
// Check if motd was loaded; if not, set default only for enUS
|
||||
if (motd.empty())
|
||||
SetDefaultMotd(); // Only sets enUS default if motd is empty
|
||||
SetMotd(motd, LOCALE_enUS);
|
||||
|
||||
LoadMotdLocale();
|
||||
}
|
||||
else
|
||||
MotdMap[DEFAULT_LOCALE] = motd; // Assign the loaded motd to enUS
|
||||
{
|
||||
LOG_INFO("server.loading", ">> Loaded 0 motd definitions. DB table `motd` is empty for this realm!");
|
||||
LOG_INFO("server.loading", ">> Loaded 0 motd locale definitions. DB table `motd` needs an entry to be able to load DB table `motd_locale`!");
|
||||
LOG_INFO("server.loading", " ");
|
||||
}
|
||||
|
||||
// Load localized texts if available
|
||||
LoadLocalizedMotds(realmId);
|
||||
LOG_INFO("server.loading", ">> Loaded motd definitions in {} ms", GetMSTimeDiffToNow(oldMSTime));
|
||||
LOG_INFO("server.loading", " ");
|
||||
}
|
||||
|
||||
// Create all world packages after loading motd and localized texts
|
||||
CreateWorldPackages();
|
||||
void MotdMgr::LoadMotdLocale()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
uint32 count = 0;
|
||||
LOG_INFO("server.loading", "Loading Motd locale...");
|
||||
|
||||
uint32 realmId = sConfigMgr->GetOption<int32>("RealmID", 0);
|
||||
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_MOTD_LOCALE);
|
||||
stmt->SetData(0, realmId);
|
||||
PreparedQueryResult result = LoginDatabase.Query(stmt);
|
||||
|
||||
if (result)
|
||||
{
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
// fields[0] is the locale string and fields[1] is the localized motd text
|
||||
std::string locale = fields[0].Get<std::string>();
|
||||
std::string localizedText = fields[1].Get<std::string>();
|
||||
|
||||
if (!IsLocaleValid(locale))
|
||||
{
|
||||
LOG_ERROR("server.loading", "DB table `motd_localized` has invalid locale ({}), skipped.", locale);
|
||||
continue;
|
||||
}
|
||||
|
||||
LocaleConstant localeId = GetLocaleByName(locale);
|
||||
if (localeId == LOCALE_enUS)
|
||||
continue;
|
||||
|
||||
SetMotd(localizedText, localeId);
|
||||
++count;
|
||||
} while (result->NextRow());
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_INFO("server.loading", ">> Loaded 0 motd locale definitions. DB table `motd_localized` is empty for this realm!");
|
||||
LOG_INFO("server.loading", " ");
|
||||
}
|
||||
|
||||
LOG_INFO("server.loading", ">> Loaded {} motd locale definitions in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
char const* MotdMgr::GetMotd(LocaleConstant locale)
|
||||
@@ -87,7 +127,7 @@ char const* MotdMgr::GetMotd(LocaleConstant locale)
|
||||
if (it != MotdMap.end())
|
||||
return it->second.c_str();
|
||||
|
||||
return MotdMap[DEFAULT_LOCALE].c_str(); // Fallback to enUS if locale is not found
|
||||
return MotdMap[LOCALE_enUS].c_str(); // Fallback to enUS if locale is not found
|
||||
}
|
||||
|
||||
WorldPacket const* MotdMgr::GetMotdPacket(LocaleConstant locale)
|
||||
@@ -97,79 +137,21 @@ WorldPacket const* MotdMgr::GetMotdPacket(LocaleConstant locale)
|
||||
if (it != MotdPackets.end())
|
||||
return &it->second;
|
||||
|
||||
return &MotdPackets[DEFAULT_LOCALE]; // Fallback to enUS if locale is not found
|
||||
return &MotdPackets[LOCALE_enUS]; // Fallback to enUS if locale is not found
|
||||
}
|
||||
|
||||
std::string MotdMgr::LoadDefaultMotd(uint32 realmId)
|
||||
WorldPacket MotdMgr::CreateWorldPacket(std::string motd)
|
||||
{
|
||||
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_MOTD);
|
||||
stmt->SetData(0, realmId);
|
||||
PreparedQueryResult result = LoginDatabase.Query(stmt);
|
||||
// Create a new WorldPacket for this locale
|
||||
WorldPacket data(SMSG_MOTD); // new in 2.0.1
|
||||
|
||||
if (result)
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
return fields[0].Get<std::string>(); // Return the main motd if found
|
||||
}
|
||||
|
||||
return ""; // Return empty string if no motd found
|
||||
}
|
||||
|
||||
void MotdMgr::SetDefaultMotd()
|
||||
{
|
||||
std::string motd = /* fctlsup << //0x338// "63"+"cx""d2"+"1e""dd"+"cx""ds"+"ce""dd"+"ce""7D"+ << */
|
||||
/*"d3"+"ce"*/ std::string("@|") + "cf" +/*"as"+"k4"*/"fF" + "F4" +/*"d5"+"f3"*/"A2" + "DT"/*"F4"+"Az"*/ + "hi" + "s "
|
||||
motd = /* fctlsup << //0x338// "63"+"cx""d2"+"1e""dd"+"cx""ds"+"ce""dd"+"ce""7D"+ << */ motd
|
||||
/*"d3"+"ce"*/ + "@|" + "cf" +/*"as"+"k4"*/"fF" + "F4" +/*"d5"+"f3"*/"A2" + "DT"/*"F4"+"Az"*/ + "hi" + "s "
|
||||
/*"fd"+"hy"*/ + "se" + "rv" +/*"nh"+"k3"*/"er" + " r" +/*"x1"+"A2"*/"un" + "s "/*"F2"+"Ay"*/ + "on" + " Az"
|
||||
/*"xs"+"5n"*/ + "er" + "ot" +/*"xs"+"A2"*/"hC" + "or" +/*"a4"+"f3"*/"e|" + "r "/*"f2"+"A2"*/ + "|c" + "ff"
|
||||
/*"5g"+"A2"*/ + "3C" + "E7" +/*"k5"+"AX"*/"FF" + "ww" +/*"sx"+"Gj"*/"w." + "az"/*"a1"+"vf"*/ + "er" + "ot"
|
||||
/*"ds"+"sx"*/ + "hc" + "or" +/*"F4"+"k5"*/"e." + "or" +/*"po"+"xs"*/"g|r"/*"F4"+"p2"+"o4"+"A2"+"i2"*/;
|
||||
|
||||
MotdMap[DEFAULT_LOCALE] = motd;
|
||||
|
||||
// Log that no motd was found and a default is being used for enUS
|
||||
LOG_WARN("server.loading", ">> Loaded 0 motd definitions. DB table `motd` is empty for this realm!");
|
||||
LOG_INFO("server.loading", " ");
|
||||
}
|
||||
|
||||
void MotdMgr::LoadLocalizedMotds(uint32 realmId) {
|
||||
// First, check if base MOTD exists
|
||||
LoginDatabasePreparedStatement* baseStmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_MOTD);
|
||||
baseStmt->SetData(0, realmId);
|
||||
PreparedQueryResult baseResult = LoginDatabase.Query(baseStmt);
|
||||
|
||||
if (!baseResult)
|
||||
{
|
||||
LOG_ERROR("server.loading", "No base MOTD found for realm {}. Localized MOTDs will not be loaded.", realmId);
|
||||
return;
|
||||
}
|
||||
|
||||
// Now load localized versions
|
||||
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_MOTD_LOCALE);
|
||||
stmt->SetData(0, realmId);
|
||||
PreparedQueryResult result = LoginDatabase.Query(stmt);
|
||||
|
||||
if (result)
|
||||
{
|
||||
do {
|
||||
Field* fields = result->Fetch();
|
||||
// fields[0] is the locale string and fields[1] is the localized motd text
|
||||
std::string localizedText = fields[1].Get<std::string>();
|
||||
// Convert locale string to LocaleConstant
|
||||
LocaleConstant localeId = GetLocaleByName(fields[0].Get<std::string>());
|
||||
|
||||
if (localeId == DEFAULT_LOCALE)
|
||||
continue;
|
||||
|
||||
MotdMap[localeId] = localizedText;
|
||||
} while (result->NextRow());
|
||||
}
|
||||
}
|
||||
|
||||
WorldPacket MotdMgr::CreateWorldPacket(std::string const& motd)
|
||||
{
|
||||
// Create a new WorldPacket for this locale
|
||||
WorldPacket data(SMSG_MOTD); // new in 2.0.1
|
||||
|
||||
// Tokenize the motd string by '@'
|
||||
std::vector<std::string_view> motdTokens = Acore::Tokenize(motd, '@', true);
|
||||
data << uint32(motdTokens.size()); // line count
|
||||
|
||||
@@ -29,9 +29,6 @@ class AC_GAME_API MotdMgr
|
||||
public:
|
||||
static MotdMgr* instance();
|
||||
|
||||
/// Converts the localized string to world packages
|
||||
void CreateWorldPackages();
|
||||
|
||||
/// Set a new Message of the Day
|
||||
void SetMotd(std::string motd, LocaleConstant locale);
|
||||
|
||||
@@ -44,18 +41,12 @@ public:
|
||||
/// Returns the current motd packet for the given locale
|
||||
WorldPacket const* GetMotdPacket(LocaleConstant locale);
|
||||
|
||||
// Checks if string is valid locale
|
||||
bool IsValidLocale(std::string const& locale);
|
||||
|
||||
private:
|
||||
// Loads the default motd from the motd table
|
||||
std::string LoadDefaultMotd(uint32 realmId);
|
||||
// Loads all available localized motd for the realm
|
||||
void LoadLocalizedMotds(uint32 realmId);
|
||||
// Sets the default mode if none is found in the database
|
||||
void SetDefaultMotd();
|
||||
void LoadMotdLocale();
|
||||
|
||||
// Create a worldpacket for a given motd localization
|
||||
WorldPacket CreateWorldPacket(std::string const& motd);
|
||||
WorldPacket CreateWorldPacket(std::string motd);
|
||||
};
|
||||
|
||||
#define sMotdMgr MotdMgr::instance()
|
||||
|
||||
@@ -1761,6 +1761,9 @@ void World::SetInitialWorldSettings()
|
||||
LOG_INFO("server.loading", "Loading Creature Data...");
|
||||
sObjectMgr->LoadCreatures();
|
||||
|
||||
LOG_INFO("server.loading", "Loading Creature sparring...");
|
||||
sObjectMgr->LoadCreatureSparring();
|
||||
|
||||
LOG_INFO("server.loading", "Loading Temporary Summon Data...");
|
||||
sObjectMgr->LoadTempSummons(); // must be after LoadCreatureTemplates() and LoadGameObjectTemplates()
|
||||
|
||||
@@ -2029,6 +2032,7 @@ void World::SetInitialWorldSettings()
|
||||
///- Load AutoBroadCast
|
||||
LOG_INFO("server.loading", "Loading Autobroadcasts...");
|
||||
sAutobroadcastMgr->LoadAutobroadcasts();
|
||||
sAutobroadcastMgr->LoadAutobroadcastsLocalized();
|
||||
|
||||
///- Load Motd
|
||||
LOG_INFO("server.loading", "Loading Motd...");
|
||||
|
||||
@@ -297,11 +297,9 @@ public:
|
||||
// Display the 'Message of the day' for the realm
|
||||
static bool HandleServerMotdCommand(ChatHandler* handler)
|
||||
{
|
||||
LocaleConstant localeConstant = DEFAULT_LOCALE;
|
||||
if (Player* player = handler->GetPlayer())
|
||||
localeConstant = player->GetSession()->GetSessionDbLocaleIndex();
|
||||
|
||||
handler->PSendSysMessage(LANG_MOTD_CURRENT, sMotdMgr->GetMotd(localeConstant));
|
||||
handler->PSendSysMessage(LANG_MOTD_CURRENT);
|
||||
for (uint32 i = 0; i < TOTAL_LOCALES; ++i)
|
||||
handler->PSendSysMessage(LANG_GENERIC_TWO_CURLIES_WITH_COLON, GetNameByLocaleConstant(LocaleConstant(i)), sMotdMgr->GetMotd(LocaleConstant(i)));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -533,7 +531,7 @@ public:
|
||||
}
|
||||
|
||||
// Define the 'Message of the day' for the realm
|
||||
static bool HandleServerSetMotdCommand(ChatHandler* handler, Optional<int32> realmId, Optional<std::string> locale, Tail motd)
|
||||
static bool HandleServerSetMotdCommand(ChatHandler* handler, Optional<int32> realmId, std::string locale, Tail motd)
|
||||
{
|
||||
std::wstring wMotd = std::wstring();
|
||||
std::string strMotd = std::string();
|
||||
@@ -542,39 +540,21 @@ public:
|
||||
if (!realmId)
|
||||
realmId = static_cast<int32>(realm.Id.Realm);
|
||||
|
||||
// Determine the locale; default to "enUS" if not provided
|
||||
LocaleConstant localeConstant;
|
||||
if (IsLocaleValid(locale))
|
||||
localeConstant = GetLocaleByName(locale);
|
||||
else
|
||||
{
|
||||
handler->SendErrorMessage("locale ({}) is not valid. Valid locales: enUS, koKR, frFR, deDE, zhCN, zhWE, esES, esMX, ruRU.", locale);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (motd.empty())
|
||||
return false;
|
||||
|
||||
// Convert Tail (motd) to std::string
|
||||
std::ostringstream motdStream;
|
||||
motdStream << motd;
|
||||
std::string motdString = motdStream.str(); // Convert Tail to std::string
|
||||
// Determine the locale; default to "enUS" if not provided
|
||||
LocaleConstant localeConstant = DEFAULT_LOCALE;
|
||||
if (locale.has_value())
|
||||
{
|
||||
if (sMotdMgr->IsValidLocale(locale.value()))
|
||||
{
|
||||
localeConstant = GetLocaleByName(locale.value());
|
||||
}
|
||||
else
|
||||
{
|
||||
motdStream.str("");
|
||||
motdStream << locale.value() << " " << motd;
|
||||
motdString = motdStream.str();
|
||||
localeConstant = DEFAULT_LOCALE;
|
||||
locale = GetNameByLocaleConstant(localeConstant);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set to default locale string
|
||||
localeConstant = DEFAULT_LOCALE;
|
||||
locale = GetNameByLocaleConstant(localeConstant);
|
||||
}
|
||||
|
||||
// Convert the concatenated motdString to UTF-8 and ensure encoding consistency
|
||||
if (!Utf8toWStr(motdString, wMotd))
|
||||
if (!Utf8toWStr(motd, wMotd))
|
||||
return false;
|
||||
|
||||
if (!WStrToUtf8(wMotd, strMotd))
|
||||
@@ -583,34 +563,29 @@ public:
|
||||
// Start a transaction for the database operations
|
||||
LoginDatabaseTransaction trans = LoginDatabase.BeginTransaction();
|
||||
|
||||
if (localeConstant == DEFAULT_LOCALE)
|
||||
if (localeConstant == LOCALE_enUS)
|
||||
{
|
||||
// Insert or update in the main motd table for enUS
|
||||
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_MOTD);
|
||||
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_REP_MOTD);
|
||||
stmt->SetData(0, realmId.value()); // realmId for insertion
|
||||
stmt->SetData(1, strMotd); // motd text for insertion
|
||||
stmt->SetData(2, strMotd); // motd text for ON DUPLICATE KEY UPDATE
|
||||
trans->Append(stmt);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Insert or update in the motd_localized table for other locales
|
||||
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_MOTD_LOCALE);
|
||||
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_REP_MOTD_LOCALE);
|
||||
stmt->SetData(0, realmId.value()); // realmId for insertion
|
||||
stmt->SetData(1, locale.value()); // locale for insertion
|
||||
stmt->SetData(1, locale); // locale for insertion
|
||||
stmt->SetData(2, strMotd); // motd text for insertion
|
||||
stmt->SetData(3, strMotd); // motd text for ON DUPLICATE KEY UPDATE
|
||||
trans->Append(stmt);
|
||||
}
|
||||
|
||||
// Commit the transaction & update db
|
||||
LoginDatabase.CommitTransaction(trans);
|
||||
|
||||
// Update the in-memory maps for the current realm. Otherwise, do not update
|
||||
if (realmId == -1 || realmId == static_cast<int32>(realm.Id.Realm))
|
||||
sMotdMgr->SetMotd(strMotd, localeConstant);
|
||||
|
||||
handler->PSendSysMessage(LANG_MOTD_NEW, realmId.value(), locale.value(), strMotd);
|
||||
sMotdMgr->SetMotd(strMotd, localeConstant);
|
||||
handler->PSendSysMessage(LANG_MOTD_NEW, realmId.value(), locale, strMotd);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,12 @@ enum Spells
|
||||
SPELL_GRAVITY_LAPSE_FLY = 44227,
|
||||
SPELL_GRAVITY_LAPSE_DOT = 44226,
|
||||
SPELL_GRAVITY_LAPSE_CHANNEL = 44251,
|
||||
SPELL_POWER_FEEDBACK = 44233
|
||||
SPELL_POWER_FEEDBACK = 44233,
|
||||
SPELL_CLEAR_FLIGHT = 44232, // Does nothing currently
|
||||
|
||||
SPELL_EMOTE_EXCLAMATION = 48348,
|
||||
SPELL_EMOTE_POINT = 48349,
|
||||
SPELL_EMOTE_ROAR = 48350
|
||||
};
|
||||
|
||||
enum Misc
|
||||
@@ -67,19 +72,13 @@ enum Misc
|
||||
|
||||
struct boss_felblood_kaelthas : public BossAI
|
||||
{
|
||||
boss_felblood_kaelthas(Creature* creature) : BossAI(creature, DATA_KAELTHAS)
|
||||
{
|
||||
_hasDoneIntro = false;
|
||||
}
|
||||
boss_felblood_kaelthas(Creature* creature) : BossAI(creature, DATA_KAELTHAS) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
_OOCScheduler.CancelAll();
|
||||
_gravityLapseCounter = 0;
|
||||
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false);
|
||||
me->SetImmuneToAll(false);
|
||||
summons.DespawnAll();
|
||||
|
||||
ScheduleHealthCheckEvent(50, [&]{
|
||||
me->CastStop();
|
||||
@@ -101,12 +100,6 @@ struct boss_felblood_kaelthas : public BossAI
|
||||
});
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
BossAI::JustSummoned(summon);
|
||||
summon->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
|
||||
void GravityLapseSequence(bool firstTime)
|
||||
{
|
||||
Talk(firstTime ? SAY_GRAVITY_LAPSE : SAY_RECAST_GRAVITY);
|
||||
@@ -132,12 +125,6 @@ struct boss_felblood_kaelthas : public BossAI
|
||||
});
|
||||
}
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
BossAI::InitializeAI();
|
||||
me->SetImmuneToAll(true);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
@@ -168,20 +155,32 @@ struct boss_felblood_kaelthas : public BossAI
|
||||
}, 50s);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
void DoAction(int32 actionId) override
|
||||
{
|
||||
if (!_hasDoneIntro && me->IsWithinDistInMap(who, 40.0f) && who->IsPlayer())
|
||||
if (actionId == DATA_KAEL_INTRO)
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
Talk(SAY_AGGRO_2, 20s);
|
||||
_hasDoneIntro = true;
|
||||
_OOCScheduler.Schedule(35s, [this](TaskContext){
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->SetImmuneToAll(false);
|
||||
me->SetInCombatWithZone();
|
||||
});
|
||||
uint32 counter = instance->GetPersistentData(DATA_KAEL_INTRO);
|
||||
instance->StorePersistentData(DATA_KAEL_INTRO, ++counter);
|
||||
|
||||
if (counter == 6 && !me->IsInCombat())
|
||||
{
|
||||
me->SetEmoteState(EMOTE_STATE_TALK);
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LAUGH_NO_SHEATHE);
|
||||
}, 15s);
|
||||
|
||||
Talk(SAY_AGGRO_2, 20s);
|
||||
me->SetImmuneToAll(true);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->ClearEmoteState();
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->SetImmuneToAll(false);
|
||||
}, 35s);
|
||||
}
|
||||
}
|
||||
BossAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask) override
|
||||
@@ -191,19 +190,35 @@ struct boss_felblood_kaelthas : public BossAI
|
||||
damage = me->GetHealth() - 1;
|
||||
if (me->isRegeneratingHealth())
|
||||
{
|
||||
me->CombatStop();
|
||||
me->CastStop();
|
||||
me->SetRegeneratingHealth(false);
|
||||
me->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE);
|
||||
me->SetImmuneToAll(true);
|
||||
me->SetStandState(UNIT_STAND_STATE_KNEEL);
|
||||
me->CombatStop();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
LapseAction(ACTION_REMOVE_FLY);
|
||||
scheduler.CancelAll();
|
||||
_OOCScheduler.Schedule(6s, [this](TaskContext){
|
||||
me->KillSelf();
|
||||
});
|
||||
summons.DespawnAll();
|
||||
|
||||
Talk(SAY_DEATH);
|
||||
DoCastSelf(SPELL_EMOTE_EXCLAMATION);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
DoCastSelf(SPELL_EMOTE_POINT);
|
||||
}, 3s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
DoCastSelf(SPELL_EMOTE_ROAR);
|
||||
}, 7s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
DoCastSelf(SPELL_EMOTE_ROAR);
|
||||
DoCastSelf(SPELL_CLEAR_FLIGHT);
|
||||
}, 9s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->KillSelf();
|
||||
}, 11s);
|
||||
}
|
||||
}
|
||||
BossAI::DamageTaken(attacker, damage, damagetype, damageSchoolMask);
|
||||
@@ -214,6 +229,9 @@ struct boss_felblood_kaelthas : public BossAI
|
||||
_gravityLapseCounter = 0;
|
||||
me->GetMap()->DoForAllPlayers([&](Player* player)
|
||||
{
|
||||
if (player->IsGameMaster())
|
||||
return;
|
||||
|
||||
if (action == ACTION_TELEPORT_PLAYERS)
|
||||
DoCast(player, SPELL_GRAVITY_LAPSE_PLAYER + _gravityLapseCounter, true);
|
||||
else if (action == ACTION_KNOCKUP)
|
||||
@@ -228,15 +246,7 @@ struct boss_felblood_kaelthas : public BossAI
|
||||
++_gravityLapseCounter;
|
||||
});
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
_OOCScheduler.Update(diff);
|
||||
BossAI::UpdateAI(diff);
|
||||
}
|
||||
private:
|
||||
TaskScheduler _OOCScheduler;
|
||||
bool _hasDoneIntro;
|
||||
uint8 _gravityLapseCounter;
|
||||
};
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ DoorData const doorData[] =
|
||||
{ GO_SELIN_ENCOUNTER_DOOR, DATA_SELIN_FIREHEART, DOOR_TYPE_ROOM },
|
||||
{ GO_VEXALLUS_DOOR, DATA_VEXALLUS, DOOR_TYPE_PASSAGE },
|
||||
{ GO_DELRISSA_DOOR, DATA_DELRISSA, DOOR_TYPE_PASSAGE },
|
||||
{ GO_KAEL_DOOR, DATA_KAELTHAS, DOOR_TYPE_ROOM },
|
||||
{ 0, 0, DOOR_TYPE_ROOM } // END
|
||||
};
|
||||
|
||||
@@ -64,6 +65,7 @@ public:
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(MAX_ENCOUNTER);
|
||||
SetPersistentDataCount(MAX_PERSISTENT_DATA);
|
||||
LoadObjectData(creatureData, gameobjectData);
|
||||
LoadDoorData(doorData);
|
||||
LoadSummonData(summonerData);
|
||||
|
||||
@@ -32,7 +32,11 @@ enum MTData
|
||||
MAX_ENCOUNTER = 4,
|
||||
|
||||
DATA_KALECGOS = 5,
|
||||
DATA_ESCAPE_ORB = 6
|
||||
DATA_ESCAPE_ORB = 6,
|
||||
|
||||
// Persistent data
|
||||
DATA_KAEL_INTRO = 0,
|
||||
MAX_PERSISTENT_DATA = 1
|
||||
};
|
||||
|
||||
enum MTCreatures
|
||||
@@ -40,8 +44,8 @@ enum MTCreatures
|
||||
NPC_DELRISSA = 24560,
|
||||
NPC_FEL_CRYSTAL = 24722,
|
||||
NPC_KAEL_THAS = 24664,
|
||||
NPC_PHOENIX = 21362,
|
||||
NPC_PHOENIX_EGG = 21364,
|
||||
NPC_PHOENIX = 24674,
|
||||
NPC_PHOENIX_EGG = 24675,
|
||||
NPC_KALECGOS = 24844
|
||||
};
|
||||
|
||||
|
||||
@@ -189,10 +189,12 @@ struct npc_madrigosa : public NullCreatureAI
|
||||
{
|
||||
if (param == ACTION_START_EVENT)
|
||||
{
|
||||
me->NearTeleportTo(1570.97f, 725.51f, 79.77f, 3.82f);
|
||||
me->SetDisableGravity(true);
|
||||
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
me->RemoveDynamicFlag(UNIT_DYNFLAG_DEAD);
|
||||
me->NearTeleportTo(1570.97f, 725.51f, 79.77f, 3.82f);
|
||||
me->SendMovementFlagUpdate();
|
||||
|
||||
events.ScheduleEvent(EVENT_MAD_1, 2000);
|
||||
}
|
||||
else if (param == ACTION_SPAWN_FELMYST)
|
||||
@@ -212,9 +214,9 @@ struct npc_madrigosa : public NullCreatureAI
|
||||
brutallus->SetReactState(REACT_PASSIVE);
|
||||
brutallus->setActive(true);
|
||||
}
|
||||
me->GetMotionMaster()->MovePoint(1, 1477.94f, 643.22f, 21.21f);
|
||||
me->GetMotionMaster()->MoveTakeoff(1, 1477.94f, 643.22f, 21.21f);
|
||||
me->AddUnitState(UNIT_STATE_NO_ENVIRONMENT_UPD);
|
||||
events.ScheduleEvent(EVENT_MAD_2, 6000);
|
||||
events.ScheduleEvent(EVENT_MAD_2, 4000);
|
||||
break;
|
||||
case EVENT_MAD_2:
|
||||
Talk(SAY_MAD_1);
|
||||
|
||||
@@ -333,11 +333,11 @@ struct boss_felmyst : public BossAI
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
scheduler.Update(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
scheduler.Update(diff);
|
||||
|
||||
if (!me->HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY))
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
@@ -61,7 +61,6 @@ enum Spells
|
||||
enum Misc
|
||||
{
|
||||
EVENT_SPELL_BERSERK = 1,
|
||||
|
||||
GROUP_DELAY = 1
|
||||
};
|
||||
|
||||
@@ -103,6 +102,7 @@ struct boss_gurtogg_bloodboil : public BossAI
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 40.0f, true))
|
||||
{
|
||||
me->RemoveAurasByType(SPELL_AURA_MOD_TAUNT);
|
||||
me->RemoveAurasDueToSpell(SPELL_ACIDIC_WOUND);
|
||||
DoCastSelf(SPELL_FEL_RAGE_SELF, true);
|
||||
DoCast(target, SPELL_FEL_RAGE_TARGET, true);
|
||||
DoCast(target, SPELL_FEL_RAGE_2, true);
|
||||
@@ -118,6 +118,10 @@ struct boss_gurtogg_bloodboil : public BossAI
|
||||
DoCastVictim(SPELL_CHARGE);
|
||||
}, 2s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
DoCastSelf(SPELL_ACIDIC_WOUND, true);
|
||||
}, 28s);
|
||||
|
||||
scheduler.DelayGroup(GROUP_DELAY, 30s);
|
||||
}
|
||||
}, 90s);
|
||||
@@ -139,7 +143,7 @@ struct boss_gurtogg_bloodboil : public BossAI
|
||||
return !who->IsImmunedToDamage(SPELL_SCHOOL_MASK_ALL) && !who->HasUnitState(UNIT_STATE_CONFUSED);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
if (!_recentlySpoken)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user