Merge pull request #185 from mod-playerbots/20260328-ac-merge

20260328 ac merge
This commit is contained in:
bashermens
2026-04-02 15:23:37 +02:00
committed by GitHub
393 changed files with 19287 additions and 15956 deletions
+1 -1
View File
@@ -109,7 +109,7 @@ Based on CLAUDE.md, always verify:
- Be constructive and educational
- Reference specific sections of CLAUDE.md, C++ Code Standards, or SQL Standards when applicable
- Suggest specific fixes with code examples when possible
- Suggest specific fixes with code examples if necessary
- Highlight both issues and good practices
- For C++ issues, cite specific rule from C++ Code Standards wiki
- For SQL issues, cite specific rule from SQL Standards wiki
+5
View File
@@ -53,6 +53,11 @@ CMakeLists.txt.user
*.BASE.*
*.LOCAL.*
#
# AI tools
#
.claude
#
# IDE & other software
#
+1
View File
@@ -76,6 +76,7 @@ git clone --depth=1 --branch=master https://github.com/azerothcore/mod-pocket-po
git clone --depth=1 --branch=master https://github.com/azerothcore/mod-premium modules/mod-premium
git clone --depth=1 --branch=main https://github.com/azerothcore/mod-progression-system.git modules/mod-progression-system
git clone --depth=1 --branch=master https://github.com/azerothcore/mod-promotion-azerothcore modules/mod-promotion-azerothcore
git clone --depth=1 --branch=master https://github.com/azerothcore/mod-ptr-template modules/mod-ptr-template
git clone --depth=1 --branch=master https://github.com/azerothcore/mod-pvp-quests modules/mod-pvp-quests
git clone --depth=1 --branch=master https://github.com/azerothcore/mod-pvp-titles modules/mod-pvp-titles
git clone --depth=1 --branch=master https://github.com/azerothcore/mod-pvp-zones modules/mod-pvp-zones
@@ -0,0 +1,4 @@
-- DB update 2026_03_20_01 -> 2026_03_21_00
-- Spirit Burn (54647) - Add 10s internal cooldown
DELETE FROM `spell_proc` WHERE `SpellId` = 54647;
INSERT INTO `spell_proc` (`SpellId`, `Cooldown`) VALUES (54647, 8000);
@@ -0,0 +1,5 @@
-- DB update 2026_03_21_00 -> 2026_03_21_01
-- Add language string for pinfo online time
DELETE FROM `acore_string` WHERE `entry` = 35410;
INSERT INTO `acore_string` (`entry`, `content_default`, `locale_koKR`, `locale_frFR`, `locale_deDE`, `locale_zhCN`, `locale_zhTW`, `locale_esES`, `locale_esMX`, `locale_ruRU`) VALUES
(35410, '¦ Online for: {}', '¦ 온라인 시간: {}', '¦ Online depuis : {}', '¦ Online seit: {}', '¦ 在线时长:{}', '¦ 線上時間:{}', '¦ Conectado durante: {}', '¦ Conectado durante: {}', '¦ Онлайн: {}');
@@ -0,0 +1,5 @@
-- DB update 2026_03_21_01 -> 2026_03_21_02
--
-- swap trainers of Engineering (33611) and Leatherworking (33612) bookshelf creature entries
UPDATE `creature_default_trainer` SET `TrainerId` = 91 WHERE (`CreatureId` = 33611);
UPDATE `creature_default_trainer` SET `TrainerId` = 62 WHERE (`CreatureId` = 33612);
@@ -0,0 +1,9 @@
-- DB update 2026_03_21_02 -> 2026_03_21_03
--
DELETE FROM `command` WHERE `name`='learn all my quest';
DELETE FROM `command` WHERE `name`='learn all my trainer';
DELETE FROM `command` WHERE `name`='learn all my spells';
INSERT INTO `command` (`name`, `security`, `help`) VALUES
('learn all my quest', 2, 'Syntax: .learn all my quest Learn all spells rewarded from quest for your class.'),
('learn all my trainer', 2, 'Syntax: .learn all my trainer Learn all spells taught by trainers for your class.');
UPDATE `command` SET `help` = 'Syntax: .learn all my class Learn all spells (trainer, talent, and quest rewards) for your class.' WHERE `name`='learn all my class';
@@ -0,0 +1,3 @@
-- DB update 2026_03_21_03 -> 2026_03_21_04
DELETE FROM `spell_script_names` WHERE `spell_id` = 55002;
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES (55002, 'spell_item_flexweave_underlay');
@@ -0,0 +1,10 @@
-- DB update 2026_03_21_04 -> 2026_03_22_00
--
UPDATE `creature_template` SET `ScriptName` = 'npc_oathbound_warder' WHERE `entry` = 30270;
DELETE FROM `creature_template_spell` WHERE `CreatureID` = 30270;
INSERT INTO `creature_template_spell` (`CreatureID`, `Index`, `Spell`, `VerifiedBuild`) VALUES
(30270, 0, 56491, 0),
(30270, 1, 56425, 0),
(30270, 2, 56451, 0),
(30270, 3, 56506, 0);
@@ -0,0 +1,13 @@
-- DB update 2026_03_22_00 -> 2026_03_22_01
--
-- Fix Quest 9927 (Ruthless Cunning): banner spell 32307 conditions only checked for Kil'sorrow Deathsworn (17148)
-- Each ElseGroup should check a different Kil'sorrow creature so banners work on all applicable mobs
-- No double-banner check needed: SpellEffects.cpp already removes corpse after banner placement
-- Remove old conditions for spell 32307 and insert corrected ones: CONDITION_NEAR_CREATURE (29) per mob
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 17 AND `SourceEntry` = 32307;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(17, 0, 32307, 0, 0, 29, 0, 17148, 5, 1, 0, 12, 0, '', 'Spell Place Kil''sorrow Banner requires nearby Kil''sorrow Deathsworn'),
(17, 0, 32307, 0, 1, 29, 0, 17147, 5, 1, 0, 12, 0, '', 'Spell Place Kil''sorrow Banner requires nearby Kil''sorrow Cultist'),
(17, 0, 32307, 0, 2, 29, 0, 17146, 5, 1, 0, 12, 0, '', 'Spell Place Kil''sorrow Banner requires nearby Kil''sorrow Spellbinder'),
(17, 0, 32307, 0, 3, 29, 0, 18391, 5, 1, 0, 12, 0, '', 'Spell Place Kil''sorrow Banner requires nearby Giselda the Crone');
@@ -0,0 +1,22 @@
-- DB update 2026_03_22_01 -> 2026_03_22_02
--
-- Brandon Eiredeck (31023) should cower and say "Please, I'm just a delivery man!"
-- Agitated Stratholme Citizens (31126) near Brandon should chastise him about the grain
--
DELETE FROM `creature_text` WHERE `CreatureID` = 31023;
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(31023, 0, 0, 'Please, I''m just a delivery man!', 12, 0, 100, 431, 0, 0, 32044, 0, 'Brandon Eiredeck - Ambient');
-- Add group 3 for the Brandon Eiredeck crowd (different from Barthilas crowd)
DELETE FROM `creature_text` WHERE `CreatureID` = 31126 AND `GroupID` = 3;
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(31126, 3, 0, 'I think it''s your grain that''s making us sick!', 12, 0, 100, 5, 0, 0, 32032, 0, 'Agitated Stratholme Citizen - Brandon Crowd'),
(31126, 3, 1, 'We were fine until we ate from this tainted grain of yours!', 12, 0, 100, 5, 0, 0, 32035, 0, 'Agitated Stratholme Citizen - Brandon Crowd');
-- Enable SmartAI for Brandon Eiredeck
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 31023;
DELETE FROM `smart_scripts` WHERE `entryorguid` = 31023 AND `source_type` = 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
(31023, 0, 0, 0, 1, 0, 100, 0, 5000, 15000, 15000, 25000, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Brandon Eiredeck - OOC - Say Line 0'),
(31023, 0, 1, 0, 1, 0, 100, 0, 0, 0, 3000, 3000, 0, 0, 17, 431, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Brandon Eiredeck - OOC - Set Emote State Cower');
@@ -0,0 +1,24 @@
-- DB update 2026_03_22_02 -> 2026_03_22_03
--
CREATE TABLE `creature_immunities` (
`ID` int NOT NULL,
`SchoolMask` tinyint NOT NULL DEFAULT '0',
`DispelTypeMask` smallint NOT NULL DEFAULT '0',
`MechanicsMask` bigint NOT NULL DEFAULT '0',
`Effects` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL,
`Auras` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL,
`ImmuneAoE` tinyint(1) NOT NULL DEFAULT '0',
`ImmuneChain` tinyint(1) NOT NULL DEFAULT '0',
`Comment` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `creature_template` ADD `CreatureImmunitiesId` int NOT NULL DEFAULT '0' AFTER `RegenHealth`;
UPDATE `creature_template` SET `CreatureImmunitiesId`=COALESCE((SELECT ci.`ID` FROM `creature_immunities` ci WHERE ci.`SchoolMask`=`spell_school_immune_mask` AND ci.`MechanicsMask`=`mechanic_immune_mask`*2),0);
ALTER TABLE `creature_template`
DROP `spell_school_immune_mask`,
DROP `mechanic_immune_mask`;
ALTER TABLE `creature_template` DROP COLUMN `scale`;
@@ -0,0 +1,38 @@
-- DB update 2026_03_22_03 -> 2026_03_22_04
--
DELETE FROM `creature_immunities` WHERE `ID` IN (95,96,315,477,679,878,1537,1557,1614,1615,1630,1632,1664,1676,1682,1693,1694,1695,1733);
INSERT INTO `creature_immunities` (`ID`, `SchoolMask`, `DispelTypeMask`, `MechanicsMask`, `Effects`, `Auras`, `ImmuneAoE`, `ImmuneChain`, `Comment`) VALUES
(95, 0, 0, 32, '', '', 0, 0, 'Immune to Fear'),
(96, 0, 0, 1234599598, '', '5,7,12,26,33', 0, 0, 'Immune to CC (Free Friend, Uncontrollable Frenzy, Warlord\'s Presence)'),
(315, 127, 0, 0, '', '', 0, 0, 'Immune to damage'),
(477, 0, 0, 68719476736, '114', '11', 0, 0, 'Immune to Taunt'),
(679, 0, 0, 1234599078, '', '5,7,12,26,33', 0, 0, 'Immune to CC'),
(878, 0, 0, 4096, '', '12', 0, 0, 'Immune to Stun'),
(1537, 0, 0, 32, '', '7', 0, 0, 'Immune to Fear'),
(1557, 0, 0, 1234599078, '98,124,144,145', '', 0, 0, 'Immune CC+Stun+Move'),
(1614, 0, 0, 68719476736, '114', '11', 0, 0, 'Immune to Taunt'),
(1615, 0, 0, 1301707942, '68', '5,7,12,26,27,33,60', 0, 0, 'Immune to CC+Interrupt'),
(1630, 0, 0, 69954075814, '114', '5,7,11,12,26,33', 0, 0, 'Immune to CC+Taunt'),
(1632, 0, 0, 584472182, '', '', 0, 0, 'Immune to hard CC'),
(1664, 0, 0, 2176, '', '', 0, 0, 'Immune to slow'),
(1676, 0, 0, 570425344, '', '', 0, 0, 'Immune to immunities'),
(1682, 0, 0, 4096, '', '', 0, 0, 'Immune to Stun'),
(1693, 0, 0, 584472182, '68', '', 0, 0, 'Immune to hard CC+Interrupt'),
(1694, 0, 0, 68719476736, '114', '11', 0, 0, 'Immune to Taunt'),
(1695, 0, 0, 4096, '', '12', 0, 0, 'Immune to Stun'),
(1733, 0, 0, 1234599078, '98,124,144,145', '', 0, 0, 'Immune CC+Stun+Move');
DELETE FROM `creature_immunities` WHERE `ID` IN (1762,1771,1794,1799,1808,1835,1887,1893,1944,1964,1971);
INSERT INTO `creature_immunities` (`ID`, `SchoolMask`, `DispelTypeMask`, `MechanicsMask`, `Effects`, `Auras`, `ImmuneAoE`, `ImmuneChain`, `Comment`) VALUES
(1762, 0, 4, 0, '', '', 0, 0, 'Immune to Curses'),
(1771, 0, 0, 0, '', '', 1, 0, 'Immune to AoE'),
(1794, 0, 0, 67108864, '68', '', 0, 0, 'Immune to Interrupts'),
(1799, 0, 0, 67109376, '68', '27,60', 0, 0, 'Immune to Interrupts+Silence'),
(1808, 0, 0, 0, '98,124,144,145', '', 0, 0, 'Immune to knockback'),
(1835, 0, 0, 1075183616, '', '', 0, 0, 'Immune to polymorph+banish+shackle+sap'),
(1887, 0, 0, 0, '98,124,144,145', '', 0, 0, 'Immune to knockback'),
(1893, 0, 0, 1091728546, '', '', 0, 0, 'Immune to Charm+Fear+Freeze+Horror+Knockout+Polymorph+Root+Sap+Shackle+Sleep+Stun'),
(1944, 0, 0, 68719476736, '114', '11', 0, 0, 'Immune to Taunt'),
(1964, 0, 0, 67109376, '68', '27,60', 0, 0, 'Immune to Interrupts+Silence'),
(1971, 0, 0, 4096, '', '', 0, 0, 'Immune to Stun');
@@ -0,0 +1,9 @@
-- DB update 2026_03_22_04 -> 2026_03_22_05
--
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 22) AND (`SourceGroup` = 11) AND (`SourceEntry` = 21838) AND (`SourceId` = 0) AND (`ElseGroup` = 0) AND (`ConditionTypeOrReference` = 29) AND (`ConditionTarget` = 0) AND (`ConditionValue1` = 23377) AND (`ConditionValue2` = 90) AND (`ConditionValue3` = 0);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(22, 11, 21838, 0, 0, 29, 1, 23377, 90, 0, 0, 0, 0, '', 'Terokk will only Despawn on Evade if Skyguard Ace is nearby.');
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 22) AND (`SourceGroup` = 12) AND (`SourceEntry` = 21838) AND (`SourceId` = 0) AND (`ElseGroup` = 0) AND (`ConditionTypeOrReference` = 29) AND (`ConditionTarget` = 0) AND (`ConditionValue1` = 23377) AND (`ConditionValue2` = 90) AND (`ConditionValue3` = 0);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(22, 12, 21838, 0, 0, 29, 1, 23377, 90, 0, 0, 0, 0, '', 'Terokk will only Despawn on Evade if Skyguard Ace is nearby.');
@@ -0,0 +1,13 @@
-- DB update 2026_03_22_05 -> 2026_03_23_00
-- Add creature_text for Stephanie Sindree (31019)
DELETE FROM `creature_text` WHERE `CreatureID` = 31019;
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(31019, 0, 0, 'It wasn''t my food!', 12, 0, 100, 6, 0, 0, 31838, 0, 'Stephanie Sindree - Stephanie Crowd'),
(31019, 1, 0, 'Please, it''s not my fault! If... if I give you a refund, maybe you can speak to a healer? I don''t know what you expect me to do!', 12, 0, 100, 20, 0, 0, 31840, 0, 'Stephanie Sindree - Stephanie Crowd');
-- Add creature_text for Agitated Stratholme Citizen (31126) - Stephanie Crowd
DELETE FROM `creature_text` WHERE `CreatureID` = 31126 AND `GroupID` IN (4, 5, 6);
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(31126, 4, 0, 'My wife and children are sick in bed because of the poison you sold me!', 12, 0, 100, 5, 0, 0, 31837, 0, 'Agitated Stratholme Citizen - Stephanie Crowd'),
(31126, 5, 0, 'Don''t try to weasel out of this!', 12, 0, 100, 25, 0, 0, 31839, 0, 'Agitated Stratholme Citizen - Stephanie Crowd'),
(31126, 6, 0, 'That... no, keep your filthy money! It won''t help my family!', 12, 0, 100, 5, 0, 0, 31842, 0, 'Agitated Stratholme Citizen - Stephanie Crowd');
@@ -0,0 +1,16 @@
-- DB update 2026_03_23_00 -> 2026_03_23_01
-- Add velocity and smoothTransition columns to waypoint_data
ALTER TABLE `waypoint_data`
ADD COLUMN `velocity` FLOAT NOT NULL DEFAULT 0 AFTER `orientation`,
ADD COLUMN `smoothTransition` TINYINT NOT NULL DEFAULT 0 AFTER `delay`;
-- Create waypoint_data_addon table for custom spline points
CREATE TABLE IF NOT EXISTS `waypoint_data_addon` (
`PathID` INT UNSIGNED NOT NULL,
`PointID` INT UNSIGNED NOT NULL,
`SplinePointIndex` INT UNSIGNED NOT NULL,
`PositionX` FLOAT NOT NULL DEFAULT 0,
`PositionY` FLOAT NOT NULL DEFAULT 0,
`PositionZ` FLOAT NOT NULL DEFAULT 0,
PRIMARY KEY (`PathID`, `PointID`, `SplinePointIndex`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
@@ -0,0 +1,23 @@
-- DB update 2026_03_23_01 -> 2026_03_23_02
-- Convert npc_slim (entry 19679) from C++ script to database gossip + conditions
-- Remove ScriptName from creature_template
UPDATE `creature_template` SET `ScriptName` = '' WHERE `entry` = 19679;
-- Add gossip_menu entry for non-friendly text (9895)
DELETE FROM `gossip_menu` WHERE `MenuID` = 8021 AND `TextID` = 9895;
INSERT INTO `gossip_menu` (`MenuID`, `TextID`) VALUES (8021, 9895);
-- Add conditions for gossip_menu text display
-- Show text 9896 (vendor greeting) only if player is Friendly+ with Consortium (faction 933)
-- Friendly(16) + Honored(32) + Revered(64) + Exalted(128) = 240
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 14 AND `SourceGroup` = 8021 AND `SourceEntry` IN (9895, 9896);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(14, 8021, 9896, 0, 0, 5, 0, 933, 240, 0, 0, 0, 0, '', 'Gossip Menu 8021 - Show text 9896 if player is Friendly+ with Consortium'),
(14, 8021, 9895, 0, 0, 5, 0, 933, 240, 0, 1, 0, 0, '', 'Gossip Menu 8021 - Show text 9895 if player is not Friendly+ with Consortium');
-- Add condition for gossip_menu_option vendor option
-- Show vendor option only if player is Friendly+ with Consortium
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 15 AND `SourceGroup` = 8021 AND `SourceEntry` = 0;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(15, 8021, 0, 0, 0, 5, 0, 933, 240, 0, 0, 0, 0, '', 'Gossip Option 8021/0 - Show vendor option if player is Friendly+ with Consortium');
@@ -0,0 +1,23 @@
-- DB update 2026_03_23_02 -> 2026_03_24_00
-- Move npc_maredis_firestar (Mathredis Firestar, entry 9836) from C++ script to DB gossip
-- Remove C++ ScriptName
UPDATE `creature_template` SET `ScriptName`='' WHERE `entry`=9836;
-- Move gossip options from sub-menus (2299-2303) to the NPC's main menu (2298) with conditions
DELETE FROM `gossip_menu_option` WHERE `MenuID` IN (2298,2299,2300,2301,2302,2303);
INSERT INTO `gossip_menu_option` (`MenuID`,`OptionID`,`OptionIcon`,`OptionText`,`OptionBroadcastTextID`,`OptionType`,`OptionNpcFlag`,`ActionMenuID`,`ActionPoiID`,`BoxCoded`,`BoxMoney`,`BoxText`,`BoxBroadcastTextID`,`VerifiedBuild`) VALUES
(2298,0,0,'I present to you the Libram of Rumination.',5291,1,1,2299,0,0,0,'',0,0),
(2298,1,0,'I present to you the Libram of Constitution.',5416,1,1,2300,0,0,0,'',0,0),
(2298,2,0,'I present to you the Libram of Tenacity.',5417,1,1,2301,0,0,0,'',0,0),
(2298,3,0,'I present to you the Libram of Resilience.',5418,1,1,2302,0,0,0,'',0,0),
(2298,4,0,'I present to you the Libram of Voracity.',5419,1,1,2303,0,0,0,'',0,0);
-- Add conditions: show each option only if player has the corresponding Libram
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=2298;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES
(15,2298,0,0,0,2,0,11732,1,0,0,0,0,'','Show gossip option if player has Libram of Rumination'),
(15,2298,1,0,0,2,0,11733,1,0,0,0,0,'','Show gossip option if player has Libram of Constitution'),
(15,2298,2,0,0,2,0,11734,1,0,0,0,0,'','Show gossip option if player has Libram of Tenacity'),
(15,2298,3,0,0,2,0,11736,1,0,0,0,0,'','Show gossip option if player has Libram of Resilience'),
(15,2298,4,0,0,2,0,11737,1,0,0,0,0,'','Show gossip option if player has Libram of Voracity');
@@ -0,0 +1,57 @@
-- DB update 2026_03_24_00 -> 2026_03_24_01
-- Defias Tower Patroller smart ai
SET @ENTRY := 7052;
UPDATE `creature_template` SET `AIName` = 'SmartAI', `ScriptName` = '' WHERE `entry` = @ENTRY;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = @ENTRY);
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
(@ENTRY, 0, 0, 0, 0, 0, 100, 0, 3100, 4700, 8600, 10100, 0, 0, 11, 5679, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Patroller - In Combat - Cast \'Torch Burn\''),
(@ENTRY, 0, 1, 0, 8, 0, 100, 0, 53, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Patroller - On Spellhit \'Backstab (53)\' - Kill Self'),
(@ENTRY, 0, 2, 0, 8, 0, 100, 0, 2589, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Patroller - On Spellhit \'Backstab (2589)\' - Kill Self'),
(@ENTRY, 0, 3, 0, 8, 0, 100, 0, 2590, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Patroller - On Spellhit \'Backstab (2590)\' - Kill Self'),
(@ENTRY, 0, 4, 0, 8, 0, 100, 0, 2591, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Patroller - On Spellhit \'Backstab (2591)\' - Kill Self'),
(@ENTRY, 0, 5, 0, 8, 0, 100, 0, 8721, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Patroller - On Spellhit \'Backstab (8721)\' - Kill Self'),
(@ENTRY, 0, 6, 0, 8, 0, 100, 0, 11279, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Patroller - On Spellhit \'Backstab (11279)\' - Kill Self'),
(@ENTRY, 0, 7, 0, 8, 0, 100, 0, 11280, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Patroller - On Spellhit \'Backstab (11280)\' - Kill Self'),
(@ENTRY, 0, 8, 0, 8, 0, 100, 0, 11281, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Patroller - On Spellhit \'Backstab (11281)\' - Kill Self'),
(@ENTRY, 0, 9, 0, 8, 0, 100, 0, 25300, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Patroller - On Spellhit \'Backstab (25300)\' - Kill Self'),
(@ENTRY, 0, 10, 0, 8, 0, 100, 0, 26863, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Patroller - On Spellhit \'Backstab (26863)\' - Kill Self'),
(@ENTRY, 0, 11, 0, 8, 0, 100, 0, 48656, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Patroller - On Spellhit \'Backstab (48656)\' - Kill Self'),
(@ENTRY, 0, 12, 0, 8, 0, 100, 0, 48657, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Patroller - On Spellhit \'Backstab (48657)\' - Kill Self'),
(@ENTRY, 0, 13, 0, 8, 0, 100, 0, 8676, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Patroller - On Spellhit \'Ambush (8676)\' - Kill Self'),
(@ENTRY, 0, 14, 0, 8, 0, 100, 0, 8724, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Patroller - On Spellhit \'Ambush (8724)\' - Kill Self'),
(@ENTRY, 0, 15, 0, 8, 0, 100, 0, 8725, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Patroller - On Spellhit \'Ambush (8725)\' - Kill Self'),
(@ENTRY, 0, 16, 0, 8, 0, 100, 0, 11267, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Patroller - On Spellhit \'Ambush (11267)\' - Kill Self'),
(@ENTRY, 0, 17, 0, 8, 0, 100, 0, 11268, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Patroller - On Spellhit \'Ambush (11268)\' - Kill Self'),
(@ENTRY, 0, 18, 0, 8, 0, 100, 0, 11269, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Patroller - On Spellhit \'Ambush (11269)\' - Kill Self'),
(@ENTRY, 0, 19, 0, 8, 0, 100, 0, 27441, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Patroller - On Spellhit \'Ambush (27441)\' - Kill Self'),
(@ENTRY, 0, 20, 0, 8, 0, 100, 0, 48689, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Patroller - On Spellhit \'Ambush (48689)\' - Kill Self');
-- Defias Tower Sentry smart ai
SET @ENTRY := 7056;
UPDATE `creature_template` SET `AIName` = 'SmartAI', `ScriptName` = '' WHERE `entry` = @ENTRY;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = @ENTRY);
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
(@ENTRY, 0, 0, 0, 1, 0, 100, 1, 1000, 1500, 0, 0, 0, 0, 11, 22766, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Sentry - Out of Combat - Cast \'Sneak\' (No Repeat)'),
(@ENTRY, 0, 1, 0, 8, 0, 100, 0, 53, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Sentry - On Spellhit \'Backstab (53)\' - Kill Self'),
(@ENTRY, 0, 2, 0, 8, 0, 100, 0, 2589, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Sentry - On Spellhit \'Backstab (2589)\' - Kill Self'),
(@ENTRY, 0, 3, 0, 8, 0, 100, 0, 2590, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Sentry - On Spellhit \'Backstab (2590)\' - Kill Self'),
(@ENTRY, 0, 4, 0, 8, 0, 100, 0, 2591, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Sentry - On Spellhit \'Backstab (2591)\' - Kill Self'),
(@ENTRY, 0, 5, 0, 8, 0, 100, 0, 8721, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Sentry - On Spellhit \'Backstab (8721)\' - Kill Self'),
(@ENTRY, 0, 6, 0, 8, 0, 100, 0, 11279, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Sentry - On Spellhit \'Backstab (11279)\' - Kill Self'),
(@ENTRY, 0, 7, 0, 8, 0, 100, 0, 11280, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Sentry - On Spellhit \'Backstab (11280)\' - Kill Self'),
(@ENTRY, 0, 8, 0, 8, 0, 100, 0, 11281, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Sentry - On Spellhit \'Backstab (11281)\' - Kill Self'),
(@ENTRY, 0, 9, 0, 8, 0, 100, 0, 25300, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Sentry - On Spellhit \'Backstab (25300)\' - Kill Self'),
(@ENTRY, 0, 10, 0, 8, 0, 100, 0, 26863, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Sentry - On Spellhit \'Backstab (26863)\' - Kill Self'),
(@ENTRY, 0, 11, 0, 8, 0, 100, 0, 48656, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Sentry - On Spellhit \'Backstab (48656)\' - Kill Self'),
(@ENTRY, 0, 12, 0, 8, 0, 100, 0, 48657, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Sentry - On Spellhit \'Backstab (48657)\' - Kill Self'),
(@ENTRY, 0, 13, 0, 8, 0, 100, 0, 8676, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Sentry - On Spellhit \'Ambush (8676)\' - Kill Self'),
(@ENTRY, 0, 14, 0, 8, 0, 100, 0, 8724, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Sentry - On Spellhit \'Ambush (8724)\' - Kill Self'),
(@ENTRY, 0, 15, 0, 8, 0, 100, 0, 8725, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Sentry - On Spellhit \'Ambush (8725)\' - Kill Self'),
(@ENTRY, 0, 16, 0, 8, 0, 100, 0, 11267, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Sentry - On Spellhit \'Ambush (11267)\' - Kill Self'),
(@ENTRY, 0, 17, 0, 8, 0, 100, 0, 11268, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Sentry - On Spellhit \'Ambush (11268)\' - Kill Self'),
(@ENTRY, 0, 18, 0, 8, 0, 100, 0, 11269, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Sentry - On Spellhit \'Ambush (11269)\' - Kill Self'),
(@ENTRY, 0, 19, 0, 8, 0, 100, 0, 27441, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Sentry - On Spellhit \'Ambush (27441)\' - Kill Self'),
(@ENTRY, 0, 20, 0, 8, 0, 100, 0, 48689, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Defias Tower Sentry - On Spellhit \'Ambush (48689)\' - Kill Self');
-- Remove Conditions
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 22 AND (`SourceEntry` IN (7052, 7056)) AND `SourceId` = 0;
+199
View File
@@ -0,0 +1,199 @@
-- DB update 2026_03_24_01 -> 2026_03_24_02
-- Ensure Grauf has RegenHealth disabled so harpoon damage persists
UPDATE `creature_template` SET `RegenHealth` = 0 WHERE `entry` IN (26893, 30775);
-- Remove go_harpoon_canon script, use built-in GOOBER spell (48641) instead
UPDATE `gameobject_template` SET `ScriptName` = '' WHERE `entry` IN (192175, 192176, 192177);
-- Register spell scripts
DELETE FROM `spell_script_names` WHERE `spell_id` IN (48642, 50255, 47574, 47594, 47579, 60020, 49308, 59275);
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
(48642, 'spell_skadi_launch_harpoon'),
(50255, 'spell_skadi_poisoned_spear'),
(47574, 'spell_freezing_cloud_area_left'),
(47594, 'spell_freezing_cloud_area_right'),
(47579, 'spell_freezing_cloud_damage'),
(60020, 'spell_freezing_cloud_damage'),
(59275, 'spell_summon_gauntlet_mobs_periodic'),
(49308, 'spell_skadi_reset_check');
-- Breath trigger SmartAI: on SpellHit 47563/47593 cast area spells 47574/47594
UPDATE `creature_template` SET `AIName` = 'SmartAI', `ScriptName` = '' WHERE `entry` = 28351;
DELETE FROM `smart_scripts` WHERE `entryorguid` = 28351 AND `source_type` = 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`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(28351, 0, 0, 0, 8, 0, 100, 0, 47563, 0, 0, 0, 11, 47574, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Breath Trigger - On SpellHit (Freezing Cloud Left) - Cast Freezing Cloud Left Area'),
(28351, 0, 1, 0, 8, 0, 100, 0, 47593, 0, 0, 0, 11, 47594, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Breath Trigger - On SpellHit (Freezing Cloud Right) - Cast Freezing Cloud Right Area');
-- Conditions for freezing cloud spells to target correct entries
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 13 AND `SourceEntry` IN (47593, 47594, 47563, 48642, 47547, 49308);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(13, 1, 47593, 0, 0, 31, 0, 3, 28351, 0, 0, 0, 0, '', 'Freezing Cloud Right - Target Breath Trigger'),
(13, 1, 47594, 0, 0, 31, 0, 3, 28351, 0, 0, 0, 0, '', 'Freezing Cloud Right Area - Target Breath Trigger'),
(13, 1, 47563, 0, 0, 31, 0, 3, 28351, 0, 0, 0, 0, '', 'Freezing Cloud Left - Target Breath Trigger'),
(13, 1, 48642, 0, 0, 31, 0, 3, 26893, 0, 0, 0, 0, '', 'Launch Harpoon - Target Grauf'),
(13, 1, 48642, 0, 1, 31, 0, 3, 22515, 0, 0, 0, 0, '', 'Launch Harpoon - Target World Trigger'),
(13, 1, 47547, 0, 0, 31, 0, 3, 28351, 0, 0, 0, 0, '', 'Gauntlet Effect - Target Breath Trigger'),
(13, 1, 49308, 0, 0, 31, 0, 3, 28351, 0, 0, 0, 0, '', 'Gauntlet Reset Check - Target Breath Trigger'),
(13, 2, 49308, 0, 0, 31, 0, 3, 26693, 0, 0, 0, 0, '', 'Gauntlet Reset Check - Target Skadi');
-- Update condition for harpoon launcher spell (48641) to target trigger NPC (TC)
UPDATE `conditions` SET `ConditionValue2` = 19871 WHERE `SourceTypeOrReferenceId` = 13 AND `SourceGroup` = 1 AND `SourceEntry` = 48641;
-- Spawn World Trigger (Not Immune NPC) near harpoon launchers (from TC TDB335)
DELETE FROM `creature` WHERE `guid` BETWEEN 5300675 AND 5300678 AND `id1` = 19871;
INSERT INTO `creature` (`guid`, `id1`, `id2`, `id3`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`, `CreateObject`, `Comment`) VALUES
(5300675, 19871, 0, 0, 575, 0, 0, 3, 1, 0, 389.929, -439.88, 83.0081, 2.79273, 300, 5, 0, 0, 0, 1, 0, 0, 0, '', NULL, 0, NULL),
(5300676, 19871, 0, 0, 575, 0, 0, 3, 1, 0, 490.516, -508.443, 107.042, 5.65487, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300677, 19871, 0, 0, 575, 0, 0, 3, 1, 0, 487.632, -517.329, 106.799, 5.55015, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300678, 19871, 0, 0, 575, 0, 0, 3, 1, 0, 480.202, -523.332, 107.042, 5.46288, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL);
-- Skadi teleport destination (phase 2 transition)
DELETE FROM `spell_target_position` WHERE `ID` = 61790;
INSERT INTO `spell_target_position` (`ID`, `EffectIndex`, `MapID`, `PositionX`, `PositionY`, `PositionZ`, `Orientation`, `VerifiedBuild`) VALUES
(61790, 0, 575, 476.799, -511.167, 104.723, 3.14159, 0);
-- Gauntlet area aura
DELETE FROM `spell_area` WHERE `spell` = 47546;
INSERT INTO `spell_area` (`spell`, `area`, `quest_start`, `quest_end`, `aura_spell`, `racemask`, `gender`, `autocast`, `quest_start_status`, `quest_end_status`) VALUES
(47546, 1196, 0, 0, 0, 0, 0, 1, 64, 11);
-- Disable LoS for Gauntlet Reset Check
DELETE FROM `disables` WHERE `sourceType` = 0 AND `entry` = 49308;
INSERT INTO `disables` (`sourceType`, `entry`, `flags`, `params_0`, `params_1`, `comment`) VALUES
(0, 49308, 64, 0, 0, 'Disable LoS for spell Utgarde Pinnacle Reset Check');
-- Launch Harpoon ignore armor
DELETE FROM `spell_custom_attr` WHERE `spell_id` = 48642;
INSERT INTO `spell_custom_attr` (`spell_id`, `attributes`) VALUES
(48642, 32768);
-- Missing spell difficulty entries
DELETE FROM `spelldifficulty_dbc` WHERE `ID` IN (50228, 50258, 49084, 49089, 49091);
INSERT INTO `spelldifficulty_dbc` (`ID`, `DifficultySpellID_1`, `DifficultySpellID_2`, `DifficultySpellID_3`, `DifficultySpellID_4`) VALUES
(49084, 49084, 59246, 0, 0),
(49089, 49089, 59247, 0, 0),
(49091, 49091, 59249, 0, 0),
(50228, 50228, 59322, 0, 0),
(50258, 50258, 59334, 0, 0);
-- Spawn Freezing Cloud Breath Triggers along the Skadi gauntlet corridor (ported from TrinityCore TDB335)
DELETE FROM `creature` WHERE `guid` BETWEEN 5300600 AND 5300674 AND `id1` = 28351;
INSERT INTO `creature` (`guid`, `id1`, `id2`, `id3`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`, `CreateObject`, `Comment`) VALUES
(5300600, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 483.221, -507.151, 104.806, 0.034907, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300601, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 474.404, -507.532, 104.807, 0.034907, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300602, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 473.898, -515.257, 104.806, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300603, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 477.645, -492.175, 104.82, 6.23082, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300604, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 477.021, -520.94, 104.806, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300605, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 425.011, -510.068, 104.832, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300606, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 430.051, -510.1, 104.944, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300607, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 434.669, -510.101, 104.983, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300608, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 440.11, -510.148, 104.97, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300609, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 445.131, -509.703, 104.831, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300610, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 450.289, -509.936, 104.705, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300611, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 455, -509.52, 104.757, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300612, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 460, -509.52, 104.757, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300613, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 465.341, -508.352, 104.438, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300614, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 470.032, -507.361, 104.807, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300615, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 489.557, -514.06, 105.487, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300616, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 482.133, -519.963, 104.806, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300617, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 325, -506.384, 104.419, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300618, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 330, -506.406, 104.434, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300619, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 335.192, -506.95, 105.056, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300620, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 339.973, -507.026, 104.669, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300621, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 344.931, -507.345, 104.592, 6.23082, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300622, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 349.864, -507.751, 104.655, 6.23082, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300623, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 354.289, -507.828, 104.759, 6.23082, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300624, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 359.405, -508.154, 104.871, 6.23082, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300625, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 364.746, -508.335, 104.896, 6.23082, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300626, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 370.505, -508.554, 104.898, 6.23082, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300627, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 374.827, -515.69, 104.877, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300628, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 379.7, -515.287, 104.841, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300629, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 384.809, -514.81, 104.812, 0.017453, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300630, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 390.011, -513.91, 104.811, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300631, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 394.974, -514.631, 104.808, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300632, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 399.738, -514.939, 104.809, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300633, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 404.576, -515.878, 104.827, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300634, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 409.497, -516.404, 105.045, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300635, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 415.076, -516.494, 105.342, 0.017453, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300636, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 420.109, -517.266, 105.089, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300637, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 488.181, -506.897, 104.806, 0.034907, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300638, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 477.551, -499.34, 104.81, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300639, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 485.686, -500.599, 104.806, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300640, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 471.163, -499.268, 104.81, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300641, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 478.264, -514.318, 104.806, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300642, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 483.638, -513.85, 104.806, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300643, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 471.796, -521.457, 104.806, 0.174533, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300644, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 424.786, -517.297, 105.033, 0.034907, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300645, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 429.779, -517.261, 105.039, 0.034907, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300646, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 434.894, -517.11, 105.029, 0.034907, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300647, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 439.402, -517.239, 105.008, 0.034907, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300648, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 444.91, -517.682, 104.947, 0.034907, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300649, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 450.614, -517.208, 104.903, 0.05236, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300650, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 455.604, -517.101, 104.832, 0.05236, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300651, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 460.245, -516.405, 104.679, 0.05236, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300652, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 465.499, -515.925, 104.59, 0.069813, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300653, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 470, -515.214, 105.112, 0.069813, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300654, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 375, -508.566, 104.878, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300655, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 380, -508.366, 104.876, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300656, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 385, -508.366, 104.876, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300657, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 390, -508.366, 104.876, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300658, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 395, -508.366, 104.876, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300659, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 400, -508.366, 104.876, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300660, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 405.287, -508.99, 105.087, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300661, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 409.909, -508.887, 105.106, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300662, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 415.074, -509.304, 105.271, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300663, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 420.093, -509.834, 104.897, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300664, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 478.792, -507.378, 104.806, 0.034907, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300665, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 324.531, -514.289, 104.761, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300666, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 329.63, -514.616, 104.712, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300667, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 334.909, -514.734, 104.623, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300668, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 339.554, -514.984, 104.61, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300669, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 344.693, -515.33, 104.573, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300670, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 349.831, -515.439, 104.556, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300671, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 354.77, -515.736, 104.57, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300672, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 359.338, -515.586, 104.638, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300673, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 364.401, -515.771, 104.757, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(5300674, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 369.849, -515.944, 104.886, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL);
-- Grauf waypoint paths (ported from TrinityCore TDB335)
SET @PATH := 2689300;
DELETE FROM `waypoint_data` WHERE `id` IN (@PATH, @PATH+1, @PATH+2);
INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES
-- Initial path (takeoff to breach)
(@PATH, 0, 310.2165, -510.5302, 120.5487, 0, 0, 2, 0, 100, 0),
(@PATH, 1, 300.8685, -520.3249, 133.3664, 0, 0, 2, 0, 100, 0),
(@PATH, 2, 298.3447, -529.4818, 137.2831, 0, 0, 2, 0, 100, 0),
(@PATH, 3, 309.0959, -540.3195, 134.9774, 0, 0, 2, 0, 100, 0),
(@PATH, 4, 323.6415, -547.9715, 130.3106, 0, 0, 2, 0, 100, 0),
(@PATH, 5, 357.078, -549.1597, 116.3105, 0, 0, 2, 0, 100, 0),
(@PATH, 6, 401.2573, -550.2768, 114.9216, 0, 0, 2, 0, 100, 0),
(@PATH, 7, 464.5062, -555.9442, 114.4494, 0, 0, 2, 0, 100, 0),
(@PATH, 8, 496.192, -556.9628, 114.8661, 0, 0, 2, 0, 100, 0),
(@PATH, 9, 523.2011, -548.9916, 114.8661, 0, 0, 2, 0, 100, 0),
-- Right path (breach to right end and back)
(@PATH+1, 0, 453.1242, -517.17, 120.0273, 0, 0, 2, 0, 100, 0),
(@PATH+1, 1, 388.3312, -514.3768, 121.1193, 0, 0, 2, 0, 100, 0),
(@PATH+1, 2, 340.2752, -512.0926, 122.3138, 0, 0, 2, 0, 100, 0),
(@PATH+1, 3, 313.0756, -509.138, 125.175, 0, 0, 2, 0, 100, 0),
(@PATH+1, 4, 296.6964, -522.6705, 133.7026, 0, 0, 2, 0, 100, 0),
(@PATH+1, 5, 301.2957, -549.4583, 137.4249, 0, 0, 2, 0, 100, 0),
(@PATH+1, 6, 335.0746, -552.1211, 119.8416, 0, 0, 2, 0, 100, 0),
(@PATH+1, 7, 397.6237, -553.9203, 119.8416, 0, 0, 2, 0, 100, 0),
(@PATH+1, 8, 459.6321, -558.0078, 119.8416, 0, 0, 2, 0, 100, 0),
(@PATH+1, 9, 505.5458, -568.7815, 119.8416, 0, 0, 2, 0, 100, 0),
(@PATH+1, 10, 518.099, -560.8499, 119.8416, 0, 0, 2, 0, 100, 0),
(@PATH+1, 11, 520.4827, -541.5633, 119.8416, 0, 0, 2, 0, 100, 0),
-- Left path (breach to left end and back)
(@PATH+2, 0, 451.9824, -509.2508, 120.0273, 0, 0, 2, 0, 100, 0),
(@PATH+2, 1, 399.2607, -510.0719, 121.1193, 0, 0, 2, 0, 100, 0),
(@PATH+2, 2, 350.6099, -508.3901, 122.3138, 0, 0, 2, 0, 100, 0),
(@PATH+2, 3, 325.8217, -506.7769, 125.175, 0, 0, 2, 0, 100, 0),
(@PATH+2, 4, 301.2941, -516.6706, 133.7026, 0, 0, 2, 0, 100, 0),
(@PATH+2, 5, 301.2957, -549.4583, 137.4249, 0, 0, 2, 0, 100, 0),
(@PATH+2, 6, 335.0746, -552.1211, 119.8416, 0, 0, 2, 0, 100, 0),
(@PATH+2, 7, 397.6237, -553.9203, 119.8416, 0, 0, 2, 0, 100, 0),
(@PATH+2, 8, 459.6321, -558.0078, 119.8416, 0, 0, 2, 0, 100, 0),
(@PATH+2, 9, 505.5458, -568.7815, 119.8416, 0, 0, 2, 0, 100, 0),
(@PATH+2, 10, 518.099, -560.8499, 119.8416, 0, 0, 2, 0, 100, 0),
(@PATH+2, 11, 520.4827, -541.5633, 119.8416, 0, 0, 2, 0, 100, 0);
@@ -0,0 +1,7 @@
-- DB update 2026_03_24_02 -> 2026_03_24_03
-- https://eu.forums.blizzard.com/en/wow/t/unnerf-unholy-dk-pet-names-plz/113162
-- Removes extra 'Stone' from First names for DK Ghouls
DELETE FROM `pet_name_generation` WHERE `id`=261 AND `word` = 'Stone' AND `entry` = 26125 AND `half` = 0;
-- Updates last name 'rawler' to 'crawler' for DK Ghouls
UPDATE `pet_name_generation` SET `word` = 'crawler' WHERE `id` = 308 AND `word` = 'rawler' AND `entry` = 26125 AND `half` = 1;
@@ -0,0 +1,19 @@
-- DB update 2026_03_24_03 -> 2026_03_24_04
--
DELETE FROM `command` WHERE `name` = 'debug loot';
INSERT INTO `command` (`name`, `security`, `help`) VALUES
('debug loot', 2, 'Syntax: .debug loot <type> <id> [count]\nSimulates loot generation for the given loot type and ID, outputting the results to chat without creating items.\nOptional count (1-100) repeats the simulation and shows aggregated drop rates.\nValid types: creature, gameobject, fishing, item, pickpocketing, skinning, disenchant, prospecting, milling, spell, reference, mail, player');
DELETE FROM `acore_string` WHERE `entry` IN (30099, 30100, 30101, 30102, 30103, 30104, 30105, 30106, 30107, 30108, 30109);
INSERT INTO `acore_string` (`entry`, `content_default`, `locale_koKR`, `locale_frFR`, `locale_deDE`, `locale_zhCN`, `locale_zhTW`, `locale_esES`, `locale_esMX`, `locale_ruRU`) VALUES
(30099, 'Simulating loot for {} "{}" (ID: {})', '루팅 시뮬레이션: {} "{}" (ID: {})', 'Simulation du butin pour {} "{}" (ID: {})', 'Beutesimulation für {} "{}" (ID: {})', '模拟 {} "{}" 的战利品 (ID: {})', '模擬 {} "{}" 的戰利品 (ID: {})', 'Simulando botín para {} "{}" (ID: {})', 'Simulando botín para {} "{}" (ID: {})', 'Симуляция добычи для {} "{}" (ID: {})'),
(30100, ' [{}] x{} - {} ({}, RandProp: {}, RandSuffix: {})', ' [{}] x{} - {} ({}, 랜덤속성: {}, 랜덤접미사: {})', ' [{}] x{} - {} ({}, PropAléa: {}, SuffAléa: {})', ' [{}] x{} - {} ({}, ZufEig: {}, ZufSuf: {})', ' [{}] x{} - {} ({}, 随机属性: {}, 随机后缀: {})', ' [{}] x{} - {} ({}, 隨機屬性: {}, 隨機後綴: {})', ' [{}] x{} - {} ({}, PropAleat: {}, SufAleat: {})', ' [{}] x{} - {} ({}, PropAleat: {}, SufAleat: {})', ' [{}] x{} - {} ({}, СлСвойство: {}, СлСуффикс: {})'),
(30101, ' [{}] x{} - {} ({}) [Quest]', ' [{}] x{} - {} ({}) [퀘스트]', ' [{}] x{} - {} ({}) [Quête]', ' [{}] x{} - {} ({}) [Quest]', ' [{}] x{} - {} ({}) [任务]', ' [{}] x{} - {} ({}) [任務]', ' [{}] x{} - {} ({}) [Misión]', ' [{}] x{} - {} ({}) [Misión]', ' [{}] x{} - {} ({}) [Задание]'),
(30102, 'Gold: {} copper ({}g {}s {}c)', '골드: {} 코퍼 ({}금 {}은 {}동)', 'Or: {} cuivre ({}po {}pa {}pc)', 'Gold: {} Kupfer ({}G {}S {}K)', '金币: {} 铜 ({}金 {}银 {}铜)', '金幣: {} 銅 ({}金 {}銀 {}銅)', 'Oro: {} cobre ({}o {}p {}c)', 'Oro: {} cobre ({}o {}p {}c)', 'Золото: {} медь ({}зол {}сер {}мед)'),
(30103, 'No loot generated.', '생성된 전리품이 없습니다.', 'Aucun butin généré.', 'Keine Beute generiert.', '未生成战利品。', '未生成戰利品。', 'No se generó botín.', 'No se generó botín.', 'Добыча не сгенерирована.'),
(30104, 'Invalid loot type "{}". Valid: creature, gameobject, fishing, item, pickpocketing, skinning, disenchant, prospecting, milling, spell, reference, mail, player', '잘못된 전리품 유형 "{}". 유효: creature, gameobject, fishing, item, pickpocketing, skinning, disenchant, prospecting, milling, spell, reference, mail, player', 'Type de butin invalide "{}". Valides: creature, gameobject, fishing, item, pickpocketing, skinning, disenchant, prospecting, milling, spell, reference, mail, player', 'Ungültiger Beutetyp "{}". Gültig: creature, gameobject, fishing, item, pickpocketing, skinning, disenchant, prospecting, milling, spell, reference, mail, player', '无效的战利品类型 "{}"。有效: creature, gameobject, fishing, item, pickpocketing, skinning, disenchant, prospecting, milling, spell, reference, mail, player', '無效的戰利品類型 "{}"。有效: creature, gameobject, fishing, item, pickpocketing, skinning, disenchant, prospecting, milling, spell, reference, mail, player', 'Tipo de botín inválido "{}". Válidos: creature, gameobject, fishing, item, pickpocketing, skinning, disenchant, prospecting, milling, spell, reference, mail, player', 'Tipo de botín inválido "{}". Válidos: creature, gameobject, fishing, item, pickpocketing, skinning, disenchant, prospecting, milling, spell, reference, mail, player', 'Неверный тип добычи "{}". Допустимые: creature, gameobject, fishing, item, pickpocketing, skinning, disenchant, prospecting, milling, spell, reference, mail, player'),
(30105, 'No loot template found for {} ID {}.', '{}의 전리품 템플릿을 찾을 수 없습니다 (ID: {}).', 'Aucun modèle de butin trouvé pour {} ID {}.', 'Keine Beutevorlage gefunden für {} ID {}.', '未找到 {} ID {} 的战利品模板。', '未找到 {} ID {} 的戰利品模板。', 'No se encontró plantilla de botín para {} ID {}.', 'No se encontró plantilla de botín para {} ID {}.', 'Шаблон добычи не найден для {} ID {}.'),
(30106, 'Simulating loot for {} "{}" (ID: {}) - {} iterations', '루팅 시뮬레이션: {} "{}" (ID: {}) - {} 반복', 'Simulation du butin pour {} "{}" (ID: {}) - {} itérations', 'Beutesimulation für {} "{}" (ID: {}) - {} Durchläufe', '模拟 {} "{}" 的战利品 (ID: {}) - {} 次迭代', '模擬 {} "{}" 的戰利品 (ID: {}) - {} 次迭代', 'Simulando botín para {} "{}" (ID: {}) - {} iteraciones', 'Simulando botín para {} "{}" (ID: {}) - {} iteraciones', 'Симуляция добычи для {} "{}" (ID: {}) - {} итераций'),
(30107, ' [{}] x{} - {} ({}) - dropped {}/{} ({}.{}%)', ' [{}] x{} - {} ({}) - 드롭 {}/{} ({}.{}%)', ' [{}] x{} - {} ({}) - obtenu {}/{} ({}.{}%)', ' [{}] x{} - {} ({}) - gefallen {}/{} ({}.{}%)', ' [{}] x{} - {} ({}) - 掉落 {}/{} ({}.{}%)', ' [{}] x{} - {} ({}) - 掉落 {}/{} ({}.{}%)', ' [{}] x{} - {} ({}) - obtenido {}/{} ({}.{}%)', ' [{}] x{} - {} ({}) - obtenido {}/{} ({}.{}%)', ' [{}] x{} - {} ({}) - выпало {}/{} ({}.{}%)'),
(30108, ' [{}] x{} - {} ({}) [Quest] - dropped {}/{} ({}.{}%)', ' [{}] x{} - {} ({}) [퀘스트] - 드롭 {}/{} ({}.{}%)', ' [{}] x{} - {} ({}) [Quête] - obtenu {}/{} ({}.{}%)', ' [{}] x{} - {} ({}) [Quest] - gefallen {}/{} ({}.{}%)', ' [{}] x{} - {} ({}) [任务] - 掉落 {}/{} ({}.{}%)', ' [{}] x{} - {} ({}) [任務] - 掉落 {}/{} ({}.{}%)', ' [{}] x{} - {} ({}) [Misión] - obtenido {}/{} ({}.{}%)', ' [{}] x{} - {} ({}) [Misión] - obtenido {}/{} ({}.{}%)', ' [{}] x{} - {} ({}) [Задание] - выпало {}/{} ({}.{}%)'),
(30109, 'Gold avg: {} copper ({}g {}s {}c) over {} iterations', '골드 평균: {} 코퍼 ({}금 {}은 {}동) {} 반복', 'Or moy: {} cuivre ({}po {}pa {}pc) sur {} itérations', 'Gold Durchschn.: {} Kupfer ({}G {}S {}K) über {} Durchläufe', '金币均值: {} 铜 ({}金 {}银 {}铜) 共 {} 次迭代', '金幣均值: {} 銅 ({}金 {}銀 {}銅) 共 {} 次迭代', 'Oro prom: {} cobre ({}o {}p {}c) en {} iteraciones', 'Oro prom: {} cobre ({}o {}p {}c) en {} iteraciones', 'Золото сред.: {} медь ({}зол {}сер {}мед) за {} итераций');
@@ -0,0 +1,48 @@
-- DB update 2026_03_24_04 -> 2026_03_24_05
-- Set High Priest Talet-Kha SAI.
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 26073;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 26073);
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
(26073, 0, 0, 1, 25, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Priest Talet-Kha - On Reset - Set Event Phase 0'),
(26073, 0, 1, 2, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 18, 33555200, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Priest Talet-Kha - On Reset - Set Flags Immune To Players & Immune To NPC\'s & Not Selectable'),
(26073, 0, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 70, 0, 0, 0, 0, 0, 0, 10, 85118, 25422, 0, 0, 0, 0, 0, 0, 'High Priest Talet-Kha - On Reset - Respawn Closest Creature \'Mystical Webbing\''),
(26073, 0, 3, 4, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 70, 0, 0, 0, 0, 0, 0, 10, 85098, 25422, 0, 0, 0, 0, 0, 0, 'High Priest Talet-Kha - On Reset - Respawn Closest Creature \'Mystical Webbing\''),
(26073, 0, 4, 5, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 223, 23, 0, 0, 0, 0, 0, 10, 85175, 23033, 0, 0, 0, 0, 0, 0, 'High Priest Talet-Kha - On Reset - Do Action ID 23'),
(26073, 0, 5, 6, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 223, 23, 0, 0, 0, 0, 0, 10, 85176, 23033, 0, 0, 0, 0, 0, 0, 'High Priest Talet-Kha - On Reset - Do Action ID 23'),
(26073, 0, 6, 7, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 223, 23, 0, 0, 0, 0, 0, 10, 85098, 25422, 0, 0, 0, 0, 0, 0, 'High Priest Talet-Kha - On Reset - Do Action ID 23'),
(26073, 0, 7, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 223, 23, 0, 0, 0, 0, 0, 10, 85118, 25422, 0, 0, 0, 0, 0, 0, 'High Priest Talet-Kha - On Reset - Do Action ID 23'),
(26073, 0, 8, 0, 72, 0, 100, 1, 25, 0, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Priest Talet-Kha - On Action 25 Done - Increment Phase (No Repeat)'),
(26073, 0, 9, 0, 72, 0, 100, 1, 26, 0, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Priest Talet-Kha - On Action 26 Done - Increment Phase (No Repeat)'),
(26073, 0, 10, 0, 66, 0, 100, 1, 2, 0, 0, 0, 0, 0, 80, 2607300, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Priest Talet-Kha - On Event Phase 2 Set - Run Script (No Repeat)'),
(26073, 0, 11, 0, 2, 0, 100, 0, 1, 45, 1000, 3000, 0, 0, 11, 11640, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Priest Talet-Kha - Between 1-45% Health - Cast \'Renew\''),
(26073, 0, 12, 0, 0, 0, 100, 0, 4000, 6000, 5000, 8000, 0, 0, 11, 15587, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'High Priest Talet-Kha - In Combat - Cast \'Mind Blast\'');
-- Set Action List
DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 2607300);
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
(2607300, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 91, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Priest Talet-Kha - Actionlist - Remove FlagStandstate Sit Down'),
(2607300, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Priest Talet-Kha - Actionlist - Set Fly Off'),
(2607300, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 3788.44, 3418.25, 85.0562, 0, 'High Priest Talet-Kha - Actionlist - Move To Position'),
(2607300, 9, 3, 0, 0, 0, 100, 0, 1000, 1000, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 1.1672, 'High Priest Talet-Kha - Actionlist - Set Orientation 1.1672'),
(2607300, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Priest Talet-Kha - Actionlist - Say Line 0'),
(2607300, 9, 5, 0, 0, 0, 100, 0, 4000, 4000, 0, 0, 0, 0, 11, 45492, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Priest Talet-Kha - Actionlist - Cast \'Shadow Nova\''),
(2607300, 9, 6, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 0, 0, 19, 33555200, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Priest Talet-Kha - Actionlist - Remove Flags Immune To Players & Immune To NPC\'s & Not Selectable'),
(2607300, 9, 7, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 21, 40, 0, 0, 0, 0, 0, 0, 0, 'High Priest Talet-Kha - Actionlist - Start Attacking');
-- Set Invisible Stalker & Mystical Webbing Guid SAIs.
DELETE FROM `smart_scripts` WHERE (`source_type` = 0) AND (`entryorguid` IN (-85175, -85176, -85098, -85118));
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
(-85176, 0, 0, 0, 72, 0, 100, 0, 23, 0, 0, 0, 0, 0, 11, 45497, 2, 0, 0, 0, 0, 11, 26073, 40, 0, 0, 0, 0, 0, 0, 'Invisible Stalker (Floating) - On Action 23 Done - Cast \'Web Beam\''),
(-85176, 0, 1, 0, 72, 0, 100, 0, 24, 0, 0, 0, 0, 0, 92, 0, 45497, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Invisible Stalker (Floating) - On Action 24 Done - Interrupt Spell \'Web Beam\''),
(-85175, 0, 0, 0, 72, 0, 100, 0, 23, 0, 0, 0, 0, 0, 11, 45497, 2, 0, 0, 0, 0, 11, 26073, 40, 0, 0, 0, 0, 0, 0, 'Invisible Stalker (Floating) - On Action 23 Done - Cast \'Web Beam\''),
(-85175, 0, 1, 0, 72, 0, 100, 0, 24, 0, 0, 0, 0, 0, 92, 0, 45497, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Invisible Stalker (Floating) - On Action 24 Done - Interrupt Spell \'Web Beam\''),
(-85098, 0, 0, 1, 72, 0, 100, 0, 23, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Mystical Webbing - On Action 23 Done - Set Reactstate Passive'),
(-85098, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 45497, 2, 0, 0, 0, 0, 11, 26073, 40, 0, 0, 0, 0, 0, 0, 'Mystical Webbing - On Action 23 Done - Cast \'Web Beam\''),
(-85098, 0, 2, 3, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 223, 24, 0, 0, 0, 0, 0, 10, 85176, 23033, 0, 0, 0, 0, 0, 0, 'Mystical Webbing - On Just Died - Do Action ID 24'),
(-85098, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 223, 26, 0, 0, 0, 0, 0, 10, 85240, 26073, 0, 0, 0, 0, 0, 0, 'Mystical Webbing - On Just Died - Do Action ID 26'),
(-85118, 0, 0, 1, 72, 0, 100, 0, 23, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Mystical Webbing - On Action 23 Done - Set Reactstate Passive'),
(-85118, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 45497, 2, 0, 0, 0, 0, 11, 26073, 40, 0, 0, 0, 0, 0, 0, 'Mystical Webbing - On Action 23 Done - Cast \'Web Beam\''),
(-85118, 0, 2, 3, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 223, 24, 0, 0, 0, 0, 0, 10, 85175, 23033, 0, 0, 0, 0, 0, 0, 'Mystical Webbing - On Just Died - Do Action ID 24'),
(-85118, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 223, 25, 0, 0, 0, 0, 0, 10, 85240, 26073, 0, 0, 0, 0, 0, 0, 'Mystical Webbing - On Just Died - Do Action ID 25');
@@ -0,0 +1,25 @@
-- DB update 2026_03_24_05 -> 2026_03_25_00
-- Add acore_string entries (30110-30125) and command table entry for .debug factionchange
DELETE FROM `acore_string` WHERE `entry` BETWEEN 30110 AND 30125;
INSERT INTO `acore_string` (`entry`, `content_default`, `locale_koKR`, `locale_frFR`, `locale_deDE`, `locale_zhCN`, `locale_zhTW`, `locale_esES`, `locale_esMX`, `locale_ruRU`) VALUES
(30110, '=== Faction/Race Change Debug for {} (GUID: {}) ===', '=== {} 진영/종족 변경 디버그 (GUID: {}) ===', '=== Débogage changement de faction/race pour {} (GUID : {}) ===', '=== Fraktions-/Rassenwechsel-Debug für {} (GUID: {}) ===', '=== 阵营/种族变更调试:{} (GUID: {}) ===', '=== 陣營/種族變更調試:{} (GUID: {}) ===', '=== Depuración de cambio de facción/raza para {} (GUID: {}) ===', '=== Depuración de cambio de facción/raza para {} (GUID: {}) ===', '=== Отладка смены фракции/расы для {} (GUID: {}) ==='),
(30111, ' Faction change flag: SET [OK]', ' 진영 변경 플래그: 설정됨 [OK]', ' Flag changement de faction : ACTIVÉ [OK]', ' Fraktionswechsel-Flag: GESETZT [OK]', ' 阵营变更标记:已设置 [OK]', ' 陣營變更標記:已設置 [OK]', ' Flag de cambio de facción: ACTIVO [OK]', ' Flag de cambio de facción: ACTIVO [OK]', ' Флаг смены фракции: УСТАНОВЛЕН [OK]'),
(30112, ' Race change flag: SET [OK]', ' 종족 변경 플래그: 설정됨 [OK]', ' Flag changement de race : ACTIVÉ [OK]', ' Rassenwechsel-Flag: GESETZT [OK]', ' 种族变更标记:已设置 [OK]', ' 種族變更標記:已設置 [OK]', ' Flag de cambio de raza: ACTIVO [OK]', ' Flag de cambio de raza: ACTIVO [OK]', ' Флаг смены расы: УСТАНОВЛЕН [OK]'),
(30113, ' Change flag: NEITHER faction nor race change flag is set [FAIL]', ' 변경 플래그: 진영 및 종족 변경 플래그가 설정되지 않음 [실패]', ' Flag de changement : NI faction NI race n''est activé [ÉCHEC]', ' Wechsel-Flag: WEDER Fraktions- noch Rassenwechsel-Flag gesetzt [FEHLER]', ' 变更标记:阵营和种族变更标记均未设置 [失败]', ' 變更標記:陣營和種族變更標記均未設置 [失敗]', ' Flag de cambio: NI facción NI raza están activos [FALLO]', ' Flag de cambio: NI facción NI raza están activos [FALLO]', ' Флаг смены: НЕ установлен ни флаг фракции, ни расы [ОШИБКА]'),
(30114, ' Guild: member of \"{}\" - must leave before faction change [FAIL]', ' 길드: \"{}\"의 멤버 - 진영 변경 전 탈퇴 필요 [실패]', ' Guilde : membre de \"{}\" - doit quitter avant le changement de faction [ÉCHEC]', ' Gilde: Mitglied von \"{}\" - muss vor dem Fraktionswechsel austreten [FEHLER]', ' 公会:是\"{}\"的成员 - 必须在阵营变更前退出 [失败]', ' 公會:是\"{}\"的成員 - 必須在陣營變更前退出 [失敗]', ' Hermandad: miembro de \"{}\" - debe abandonar antes de cambiar de facción [FALLO]', ' Hermandad: miembro de \"{}\" - debe abandonar antes de cambiar de facción [FALLO]', ' Гильдия: состоит в \"{}\" - необходимо покинуть перед сменой фракции [ОШИБКА]'),
(30115, ' Guild: not in a guild or cross-faction guilds enabled [OK]', ' 길드: 길드 미가입 또는 교차 진영 길드 허용됨 [OK]', ' Guilde : pas dans une guilde ou guildes cross-faction activées [OK]', ' Gilde: nicht in einer Gilde oder fraktionsübergreifende Gilden aktiviert [OK]', ' 公会:未加入公会或已启用跨阵营公会 [OK]', ' 公會:未加入公會或已啟用跨陣營公會 [OK]', ' Hermandad: sin hermandad o hermandades cross-facción habilitadas [OK]', ' Hermandad: sin hermandad o hermandades cross-facción habilitadas [OK]', ' Гильдия: не в гильдии или межфракционные гильдии включены [OK]'),
(30116, ' Arena captain: is captain of an arena team - must transfer or disband [FAIL]', ' 아레나 대장: 아레나 팀의 대장 - 양도 또는 해체 필요 [실패]', ' Capitaine d''arène : est capitaine d''une équipe d''arène - doit transférer ou dissoudre [ÉCHEC]', ' Arena-Kapitän: ist Kapitän eines Arena-Teams - muss übergeben oder auflösen [FEHLER]', ' 竞技场队长:是竞技场队伍的队长 - 必须转让或解散 [失败]', ' 競技場隊長:是競技場隊伍的隊長 - 必須轉讓或解散 [失敗]', ' Capitán de arena: es capitán de un equipo de arena - debe transferir o disolver [FALLO]', ' Capitán de arena: es capitán de un equipo de arena - debe transferir o disolver [FALLO]', ' Капитан арены: является капитаном команды арены - необходимо передать или распустить [ОШИБКА]'),
(30117, ' Arena captain: not a captain [OK]', ' 아레나 대장: 대장 아님 [OK]', ' Capitaine d''arène : n''est pas capitaine [OK]', ' Arena-Kapitän: kein Kapitän [OK]', ' 竞技场队长:不是队长 [OK]', ' 競技場隊長:不是隊長 [OK]', ' Capitán de arena: no es capitán [OK]', ' Capitán de arena: no es capitán [OK]', ' Капитан арены: не является капитаном [OK]'),
(30118, ' Mail: {} message(s) in mailbox - must clear mail [FAIL]', ' 우편: 우편함에 {}개의 메시지 - 우편 정리 필요 [실패]', ' Courrier : {} message(s) dans la boîte - doit vider le courrier [ÉCHEC]', ' Post: {} Nachricht(en) im Postfach - Post muss gelöscht werden [FEHLER]', ' 邮件:邮箱中有{}封邮件 - 必须清空邮箱 [失败]', ' 郵件:信箱中有{}封郵件 - 必須清空信箱 [失敗]', ' Correo: {} mensaje(s) en el buzón - debe vaciar el correo [FALLO]', ' Correo: {} mensaje(s) en el buzón - debe vaciar el correo [FALLO]', ' Почта: {} сообщений в почтовом ящике - необходимо очистить почту [ОШИБКА]'),
(30119, ' Mail: mailbox is empty [OK]', ' 우편: 우편함 비어 있음 [OK]', ' Courrier : boîte aux lettres vide [OK]', ' Post: Postfach ist leer [OK]', ' 邮件:邮箱为空 [OK]', ' 郵件:信箱為空 [OK]', ' Correo: buzón vacío [OK]', ' Correo: buzón vacío [OK]', ' Почта: почтовый ящик пуст [OK]'),
(30120, ' Auctions: has active auctions or bids - must clear auctions [FAIL]', ' 경매: 활성 경매 또는 입찰 있음 - 경매 정리 필요 [실패]', ' Enchères : a des enchères ou offres actives - doit supprimer les enchères [ÉCHEC]', ' Auktionen: hat aktive Auktionen oder Gebote - Auktionen müssen gelöscht werden [FEHLER]', ' 拍卖:有活跃的拍卖或出价 - 必须清除拍卖 [失败]', ' 拍賣:有活躍的拍賣或出價 - 必須清除拍賣 [失敗]', ' Subastas: tiene subastas o pujas activas - debe eliminar las subastas [FALLO]', ' Subastas: tiene subastas o pujas activas - debe eliminar las subastas [FALLO]', ' Аукционы: есть активные аукционы или ставки - необходимо очистить аукционы [ОШИБКА]'),
(30121, ' Auctions: no active auctions or bids [OK]', ' 경매: 활성 경매 또는 입찰 없음 [OK]', ' Enchères : aucune enchère ni offre active [OK]', ' Auktionen: keine aktiven Auktionen oder Gebote [OK]', ' 拍卖:没有活跃的拍卖或出价 [OK]', ' 拍賣:沒有活躍的拍賣或出價 [OK]', ' Subastas: sin subastas ni pujas activas [OK]', ' Subastas: sin subastas ni pujas activas [OK]', ' Аукционы: нет активных аукционов или ставок [OK]'),
(30122, ' Gold: {} copper, exceeds limit of {} copper [FAIL]', ' 골드: {} 코퍼, 제한 {} 코퍼 초과 [실패]', ' Or : {} cuivres, dépasse la limite de {} cuivres [ÉCHEC]', ' Gold: {} Kupfer, überschreitet Limit von {} Kupfer [FEHLER]', ' 金币:{}铜币,超过限额{}铜币 [失败]', ' 金幣:{}銅幣,超過限額{}銅幣 [失敗]', ' Oro: {} cobres, excede el límite de {} cobres [FALLO]', ' Oro: {} cobres, excede el límite de {} cobres [FALLO]', ' Золото: {} медных, превышает лимит в {} медных [ОШИБКА]'),
(30123, ' Gold: {} copper (limit: {} copper) [OK]', ' 골드: {} 코퍼 (제한: {} 코퍼) [OK]', ' Or : {} cuivres (limite : {} cuivres) [OK]', ' Gold: {} Kupfer (Limit: {} Kupfer) [OK]', ' 金币:{}铜币(限额:{}铜币)[OK]', ' 金幣:{}銅幣(限額:{}銅幣)[OK]', ' Oro: {} cobres (límite: {} cobres) [OK]', ' Oro: {} cobres (límite: {} cobres) [OK]', ' Золото: {} медных (лимит: {} медных) [OK]'),
(30124, ' Gold: {} copper (no limit configured) [OK]', ' 골드: {} 코퍼 (제한 없음) [OK]', ' Or : {} cuivres (aucune limite configurée) [OK]', ' Gold: {} Kupfer (kein Limit konfiguriert) [OK]', ' 金币:{}铜币(未配置限额)[OK]', ' 金幣:{}銅幣(未配置限額)[OK]', ' Oro: {} cobres (sin límite configurado) [OK]', ' Oro: {} cobres (sin límite configurado) [OK]', ' Золото: {} медных (лимит не настроен) [OK]'),
(30125, ' Guild/Arena/Mail/Auction checks: N/A (faction change not requested, only applies to faction change)', ' 길드/아레나/우편/경매 검사: 해당 없음 (진영 변경이 요청되지 않음, 진영 변경에만 적용)', ' Vérifications guilde/arène/courrier/enchères : N/A (changement de faction non demandé, applicable uniquement au changement de faction)', ' Gilden-/Arena-/Post-/Auktionsprüfungen: Nicht zutreffend (kein Fraktionswechsel angefordert, gilt nur für Fraktionswechsel)', ' 公会/竞技场/邮件/拍卖检查:不适用(未请求阵营变更,仅适用于阵营变更)', ' 公會/競技場/郵件/拍賣檢查:不適用(未請求陣營變更,僅適用於陣營變更)', ' Comprobaciones de hermandad/arena/correo/subastas: N/A (no se solicitó cambio de facción, solo aplica a cambio de facción)', ' Comprobaciones de hermandad/arena/correo/subastas: N/A (no se solicitó cambio de facción, solo aplica a cambio de facción)', ' Проверки гильдии/арены/почты/аукционов: Н/Д (смена фракции не запрошена, применимо только к смене фракции)');
DELETE FROM `command` WHERE `name` = 'debug factionchange';
INSERT INTO `command` (`name`, `security`, `help`) VALUES
('debug factionchange', 3, 'Syntax: .debug factionchange [$playerName]\nChecks all faction/race change requirements for the target player and reports pass/fail for each condition (AT_LOGIN flags, guild, arena captain, mail, auctions, gold limit).');
@@ -0,0 +1,22 @@
-- DB update 2026_03_25_00 -> 2026_03_25_01
-- Add autobroadcast commands
DELETE FROM `command` WHERE `name` IN ('autobroadcast', 'autobroadcast list', 'autobroadcast add', 'autobroadcast locale', 'autobroadcast remove');
INSERT INTO `command` (`name`, `security`, `help`) VALUES
('autobroadcast', 2, 'Syntax: .autobroadcast $subcommand\nType .autobroadcast to see a list of subcommands or .help autobroadcast $subcommand to see info on subcommands.'),
('autobroadcast list', 2, 'Syntax: .autobroadcast list\nList all autobroadcast entries.'),
('autobroadcast add', 3, 'Syntax: .autobroadcast add $weight $text\nAdd a new autobroadcast entry with the given weight and text.'),
('autobroadcast locale', 3, 'Syntax: .autobroadcast locale $id $locale $text\nAdd or replace a localized text for the autobroadcast entry with the given ID.'),
('autobroadcast remove', 3, 'Syntax: .autobroadcast remove $id\nRemove the autobroadcast entry with the given ID and its locale entries.');
-- Add acore_string entries for autobroadcast commands
DELETE FROM `acore_string` WHERE `entry` IN (5126, 5127, 5128, 5129, 5130, 5131, 5132, 5133, 5134);
INSERT INTO `acore_string` (`entry`, `content_default`, `locale_koKR`, `locale_frFR`, `locale_deDE`, `locale_zhCN`, `locale_zhTW`, `locale_esES`, `locale_esMX`, `locale_ruRU`) VALUES
(5126, 'Autobroadcast entries:', '자동 방송 항목:', 'Entrées d''annonce automatique :', 'Autobroadcast-Einträge:', '自动广播条目:', '自動廣播條目:', 'Entradas de transmisión automática:', 'Entradas de transmisión automática:', 'Записи автоматической рассылки:'),
(5127, ' ID: {} | Weight: {} | Text: {}', ' ID: {} | 가중치: {} | 텍스트: {}', ' ID : {} | Poids : {} | Texte : {}', ' ID: {} | Gewicht: {} | Text: {}', ' ID:{} | 权重:{} | 文本:{}', ' ID:{} | 權重:{} | 文本:{}', ' ID: {} | Peso: {} | Texto: {}', ' ID: {} | Peso: {} | Texto: {}', ' ID: {} | Вес: {} | Текст: {}'),
(5128, 'No autobroadcast entries found.', '자동 방송 항목을 찾을 수 없습니다.', 'Aucune entrée d''annonce automatique trouvée.', 'Keine Autobroadcast-Einträge gefunden.', '未找到自动广播条目。', '未找到自動廣播條目。', 'No se encontraron entradas de transmisión automática.', 'No se encontraron entradas de transmisión automática.', 'Записи автоматической рассылки не найдены.'),
(5129, 'Autobroadcast entry added with ID {}.', 'ID {}로 자동 방송 항목이 추가되었습니다.', 'Entrée d''annonce automatique ajoutée avec l''ID {}.', 'Autobroadcast-Eintrag mit ID {} hinzugefügt.', '已添加ID为{}的自动广播条目。', '已新增ID為{}的自動廣播條目。', 'Entrada de transmisión automática añadida con ID {}.', 'Entrada de transmisión automática añadida con ID {}.', 'Добавлена запись автоматической рассылки с ID {}.'),
(5130, 'Autobroadcast entry #{} removed.', '자동 방송 항목 #{}이(가) 제거되었습니다.', 'Entrée d''annonce automatique #{} supprimée.', 'Autobroadcast-Eintrag #{} entfernt.', '自动广播条目 #{} 已移除。', '自動廣播條目 #{} 已移除。', 'Entrada de transmisión automática #{} eliminada.', 'Entrada de transmisión automática #{} eliminada.', 'Запись автоматической рассылки #{} удалена.'),
(5131, 'Autobroadcast entry #{} not found.', '자동 방송 항목 #{}을(를) 찾을 수 없습니다.', 'Entrée d''annonce automatique #{} introuvable.', 'Autobroadcast-Eintrag #{} nicht gefunden.', '未找到自动广播条目 #{}。', '未找到自動廣播條目 #{}。', 'Entrada de transmisión automática #{} no encontrada.', 'Entrada de transmisión automática #{} no encontrada.', 'Запись автоматической рассылки #{} не найдена.'),
(5132, 'Autobroadcast locale ''{}'' added for entry #{}.', '자동 방송 항목 #{}에 로캘 ''{}''이(가) 추가되었습니다.', 'Localisation ''{}'' ajoutée pour l''entrée d''annonce automatique #{}.', 'Autobroadcast-Lokalisierung ''{}'' für Eintrag #{} hinzugefügt.', '已为自动广播条目 #{} 添加语言区域 ''{}''。', '已為自動廣播條目 #{} 新增語言區域 ''{}''。', 'Localización ''{}'' añadida para la entrada de transmisión automática #{}.', 'Localización ''{}'' añadida para la entrada de transmisión automática #{}.', 'Локализация ''{}'' добавлена для записи автоматической рассылки #{}.'),
(5133, ' Locale: {} | Text: {}', ' 로캘: {} | 텍스트: {}', ' Langue : {} | Texte : {}', ' Sprache: {} | Text: {}', ' 语言区域:{} | 文本:{}', ' 語言區域:{} | 文本:{}', ' Localización: {} | Texto: {}', ' Localización: {} | Texto: {}', ' Локализация: {} | Текст: {}'),
(5134, 'Invalid locale. Valid locales: enUS, koKR, frFR, deDE, zhCN, zhTW, esES, esMX, ruRU.', '잘못된 로캘입니다. 유효한 로캘: enUS, koKR, frFR, deDE, zhCN, zhTW, esES, esMX, ruRU.', 'Langue invalide. Langues valides : enUS, koKR, frFR, deDE, zhCN, zhTW, esES, esMX, ruRU.', 'Ungültige Sprache. Gültige Sprachen: enUS, koKR, frFR, deDE, zhCN, zhTW, esES, esMX, ruRU.', '无效的语言区域。有效的语言区域:enUS、koKR、frFR、deDE、zhCN、zhTW、esES、esMX、ruRU。', '無效的語言區域。有效的語言區域:enUS、koKR、frFR、deDE、zhCN、zhTW、esES、esMX、ruRU。', 'Localización inválida. Localizaciones válidas: enUS, koKR, frFR, deDE, zhCN, zhTW, esES, esMX, ruRU.', 'Localización inválida. Localizaciones válidas: enUS, koKR, frFR, deDE, zhCN, zhTW, esES, esMX, ruRU.', 'Недопустимая локализация. Допустимые локализации: enUS, koKR, frFR, deDE, zhCN, zhTW, esES, esMX, ruRU.');
+820
View File
@@ -0,0 +1,820 @@
-- DB update 2026_03_25_01 -> 2026_03_25_02
--
-- Fix: Repopulate CreatureImmunitiesId for all creatures that had mechanic/school immune masks
-- The original migration (2026_03_22_03) ran the UPDATE before creature_immunities rows existed,
-- resulting in all creatures getting CreatureImmunitiesId=0
--
DELETE FROM `creature_immunities` WHERE `ID` IN (1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021);
INSERT INTO `creature_immunities` (`ID`, `SchoolMask`, `DispelTypeMask`, `MechanicsMask`, `Effects`, `Auras`, `ImmuneAoE`, `ImmuneChain`, `Comment`) VALUES
(1972, 0, 0, 2, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2'),
(1973, 0, 0, 4, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 4'),
(1974, 0, 0, 16, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 16'),
(1975, 0, 0, 18, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 18'),
(1976, 0, 0, 34, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 34'),
(1977, 0, 0, 40, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 40'),
(1978, 0, 0, 42, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 42'),
(1979, 0, 0, 64, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 64'),
(1980, 0, 0, 512, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 512'),
(1981, 0, 0, 514, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 514'),
(1982, 0, 0, 1024, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1024'),
(1983, 0, 0, 1056, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1056'),
(1984, 0, 0, 1058, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1058'),
(1985, 0, 0, 2048, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2048'),
(1986, 0, 0, 2050, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2050'),
(1987, 0, 0, 2052, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2052'),
(1988, 0, 0, 2080, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2080'),
(1989, 0, 0, 2082, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2082'),
(1990, 0, 0, 2178, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2178'),
(1991, 0, 0, 2192, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2192'),
(1992, 0, 0, 2208, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2208'),
(1993, 0, 0, 2210, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2210'),
(1994, 0, 0, 2562, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2562'),
(1995, 0, 0, 3074, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 3074'),
(1996, 0, 0, 4098, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 4098'),
(1997, 0, 0, 4114, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 4114'),
(1998, 0, 0, 4128, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 4128'),
(1999, 0, 0, 4608, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 4608'),
(2000, 0, 0, 4624, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 4624'),
(2001, 0, 0, 6178, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 6178'),
(2002, 0, 0, 6810, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 6810'),
(2003, 0, 0, 8192, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 8192'),
(2004, 0, 0, 8224, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 8224'),
(2005, 0, 0, 12584, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 12584'),
(2006, 0, 0, 14374, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 14374'),
(2007, 0, 0, 14982, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 14982'),
(2008, 0, 0, 16384, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 16384'),
(2009, 0, 0, 20516, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 20516'),
(2010, 0, 0, 21114, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 21114'),
(2011, 0, 0, 32768, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 32768'),
(2012, 0, 0, 65278, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 65278'),
(2013, 0, 0, 131072, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 131072'),
(2014, 0, 0, 131074, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 131074'),
(2015, 0, 0, 131106, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 131106'),
(2016, 0, 0, 132128, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 132128'),
(2017, 0, 0, 133122, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 133122'),
(2018, 0, 0, 133248, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 133248'),
(2019, 0, 0, 133250, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 133250'),
(2020, 0, 0, 139264, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 139264'),
(2021, 0, 0, 139298, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 139298');
DELETE FROM `creature_immunities` WHERE `ID` IN (2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071);
INSERT INTO `creature_immunities` (`ID`, `SchoolMask`, `DispelTypeMask`, `MechanicsMask`, `Effects`, `Auras`, `ImmuneAoE`, `ImmuneChain`, `Comment`) VALUES
(2022, 0, 0, 141440, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 141440'),
(2023, 0, 0, 143360, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 143360'),
(2024, 0, 0, 143396, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 143396'),
(2025, 0, 0, 262144, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 262144'),
(2026, 0, 0, 262146, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 262146'),
(2027, 0, 0, 262172, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 262172'),
(2028, 0, 0, 263222, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 263222'),
(2029, 0, 0, 265792, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 265792'),
(2030, 0, 0, 274592, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 274592'),
(2031, 0, 0, 278534, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 278534'),
(2032, 0, 0, 404998, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 404998'),
(2033, 0, 0, 407714, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 407714'),
(2034, 0, 0, 16777216, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 16777216'),
(2035, 0, 0, 16777248, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 16777248'),
(2036, 0, 0, 16777250, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 16777250'),
(2037, 0, 0, 16777264, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 16777264'),
(2038, 0, 0, 16777312, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 16777312'),
(2039, 0, 0, 16777376, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 16777376'),
(2040, 0, 0, 16779424, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 16779424'),
(2041, 0, 0, 16779428, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 16779428'),
(2042, 0, 0, 16779488, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 16779488'),
(2043, 0, 0, 16781344, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 16781344'),
(2044, 0, 0, 16781984, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 16781984'),
(2045, 0, 0, 16783392, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 16783392'),
(2046, 0, 0, 16788644, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 16788644'),
(2047, 0, 0, 16791714, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 16791714'),
(2048, 0, 0, 16794664, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 16794664'),
(2049, 0, 0, 16794668, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 16794668'),
(2050, 0, 0, 16794676, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 16794676'),
(2051, 0, 0, 16827436, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 16827436'),
(2052, 0, 0, 16932526, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 16932526'),
(2053, 0, 0, 17039394, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 17039394'),
(2054, 0, 0, 17039520, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 17039520'),
(2055, 0, 0, 17041570, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 17041570'),
(2056, 0, 0, 17045536, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 17045536'),
(2057, 0, 0, 17171490, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 17171490'),
(2058, 0, 0, 17171494, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 17171494'),
(2059, 0, 0, 17204258, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 17204258'),
(2060, 0, 0, 17825824, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 17825824'),
(2061, 0, 0, 17825826, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 17825826'),
(2062, 0, 0, 17826336, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 17826336'),
(2063, 0, 0, 25198706, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 25198706'),
(2064, 0, 0, 25574434, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 25574434'),
(2065, 0, 0, 26216098, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 26216098'),
(2066, 0, 0, 67272418, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 67272418'),
(2067, 0, 0, 75497986, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 75497986'),
(2068, 0, 0, 75502082, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 75502082'),
(2069, 0, 0, 75765794, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 75765794'),
(2070, 0, 0, 84032160, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 84032160'),
(2071, 0, 0, 84180644, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 84180644');
DELETE FROM `creature_immunities` WHERE `ID` IN (2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121);
INSERT INTO `creature_immunities` (`ID`, `SchoolMask`, `DispelTypeMask`, `MechanicsMask`, `Effects`, `Auras`, `ImmuneAoE`, `ImmuneChain`, `Comment`) VALUES
(2072, 0, 0, 84180654, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 84180654'),
(2073, 0, 0, 92569262, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 92569262'),
(2074, 0, 0, 93617828, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 93617828'),
(2075, 0, 0, 134217728, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 134217728'),
(2076, 0, 0, 134219776, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 134219776'),
(2077, 0, 0, 134221834, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 134221834'),
(2078, 0, 0, 134368350, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 134368350'),
(2079, 0, 0, 134487696, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 134487696'),
(2080, 0, 0, 134487698, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 134487698'),
(2081, 0, 0, 134610954, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 134610954'),
(2082, 0, 0, 142884558, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 142884558'),
(2083, 0, 0, 151259878, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 151259878'),
(2084, 0, 0, 151262366, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 151262366'),
(2085, 0, 0, 151262398, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 151262398'),
(2086, 0, 0, 151273214, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 151273214'),
(2087, 0, 0, 151314166, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 151314166'),
(2088, 0, 0, 151401654, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 151401654'),
(2089, 0, 0, 152469182, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 152469182'),
(2090, 0, 0, 159516926, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 159516926'),
(2091, 0, 0, 160853686, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 160853686'),
(2092, 0, 0, 160857782, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 160857782'),
(2093, 0, 0, 160857790, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 160857790'),
(2094, 0, 0, 160857854, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 160857854'),
(2095, 0, 0, 161361662, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 161361662'),
(2096, 0, 0, 201719818, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 201719818'),
(2097, 0, 0, 226915902, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 226915902'),
(2098, 0, 0, 227962558, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 227962558'),
(2099, 0, 0, 688815860, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 688815860'),
(2100, 0, 0, 1002405630, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1002405630'),
(2101, 0, 0, 1073741824, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1073741824'),
(2102, 0, 0, 1073741826, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1073741826'),
(2103, 0, 0, 1073741892, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1073741892'),
(2104, 0, 0, 1073758240, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1073758240'),
(2105, 0, 0, 1073873920, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1073873920'),
(2106, 0, 0, 1073877158, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1073877158'),
(2107, 0, 0, 1073886882, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1073886882'),
(2108, 0, 0, 1074009602, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1074009602'),
(2109, 0, 0, 1074167486, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1074167486'),
(2110, 0, 0, 1075202048, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1075202048'),
(2111, 0, 0, 1082677838, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1082677838'),
(2112, 0, 0, 1082686030, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1082686030'),
(2113, 0, 0, 1082686046, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1082686046'),
(2114, 0, 0, 1090534560, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1090534560'),
(2115, 0, 0, 1090679030, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1090679030'),
(2116, 0, 0, 1090681014, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1090681014'),
(2117, 0, 0, 1090681270, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1090681270'),
(2118, 0, 0, 1090936558, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1090936558'),
(2119, 0, 0, 1090936574, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1090936574'),
(2120, 0, 0, 1090940076, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1090940076'),
(2121, 0, 0, 1090940670, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1090940670');
DELETE FROM `creature_immunities` WHERE `ID` IN (2122,2123,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171);
INSERT INTO `creature_immunities` (`ID`, `SchoolMask`, `DispelTypeMask`, `MechanicsMask`, `Effects`, `Auras`, `ImmuneAoE`, `ImmuneChain`, `Comment`) VALUES
(2122, 0, 0, 1090944742, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1090944742'),
(2123, 0, 0, 1090944766, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1090944766'),
(2124, 0, 0, 1099040290, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1099040290'),
(2125, 0, 0, 1099043874, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1099043874'),
(2126, 0, 0, 1099060258, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1099060258'),
(2127, 0, 0, 1100219550, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1100219550'),
(2128, 0, 0, 1100248830, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1100248830'),
(2129, 0, 0, 1100350654, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1100350654'),
(2130, 0, 0, 1100359230, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1100359230'),
(2131, 0, 0, 1100366910, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1100366910'),
(2132, 0, 0, 1100375718, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1100375718'),
(2133, 0, 0, 1100379710, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1100379710'),
(2134, 0, 0, 1100379774, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1100379774'),
(2135, 0, 0, 1100904190, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1100904190'),
(2136, 0, 0, 1100906238, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1100906238'),
(2137, 0, 0, 1102477054, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1102477054'),
(2138, 0, 0, 1102872318, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1102872318'),
(2139, 0, 0, 1141118466, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1141118466'),
(2140, 0, 0, 1158053548, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1158053548'),
(2141, 0, 0, 1158053550, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1158053550'),
(2142, 0, 0, 1158053630, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1158053630'),
(2143, 0, 0, 1167484670, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1167484670'),
(2144, 0, 0, 1167488694, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1167488694'),
(2145, 0, 0, 1207983274, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1207983274'),
(2146, 0, 0, 1208099366, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1208099366'),
(2147, 0, 0, 1208110334, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1208110334'),
(2148, 0, 0, 1208117942, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1208117942'),
(2149, 0, 0, 1208118454, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1208118454'),
(2150, 0, 0, 1208123134, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1208123134'),
(2151, 0, 0, 1208245410, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1208245410'),
(2152, 0, 0, 1209171606, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1209171606'),
(2153, 0, 0, 1217817766, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1217817766'),
(2154, 0, 0, 1224758964, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1224758964'),
(2155, 0, 0, 1224758966, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1224758966'),
(2156, 0, 0, 1224764576, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1224764576'),
(2157, 0, 0, 1224891646, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1224891646'),
(2158, 0, 0, 1224892158, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1224892158'),
(2159, 0, 0, 1224899750, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1224899750'),
(2160, 0, 0, 1224899830, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1224899830'),
(2161, 0, 0, 1225030910, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1225030910'),
(2162, 0, 0, 1225031358, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1225031358'),
(2163, 0, 0, 1225064188, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1225064188'),
(2164, 0, 0, 1225162494, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1225162494'),
(2165, 0, 0, 1225293566, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1225293566'),
(2166, 0, 0, 1225424638, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1225424638'),
(2167, 0, 0, 1225588478, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1225588478'),
(2168, 0, 0, 1225686782, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1225686782'),
(2169, 0, 0, 1226206902, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1226206902'),
(2170, 0, 0, 1226209946, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1226209946'),
(2171, 0, 0, 1226209974, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1226209974');
DELETE FROM `creature_immunities` WHERE `ID` IN (2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2220,2221);
INSERT INTO `creature_immunities` (`ID`, `SchoolMask`, `DispelTypeMask`, `MechanicsMask`, `Effects`, `Auras`, `ImmuneAoE`, `ImmuneChain`, `Comment`) VALUES
(2172, 0, 0, 1226210998, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1226210998'),
(2173, 0, 0, 1226211006, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1226211006'),
(2174, 0, 0, 1226211070, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1226211070'),
(2175, 0, 0, 1230420214, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1230420214'),
(2176, 0, 0, 1233288886, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1233288886'),
(2177, 0, 0, 1233419518, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1233419518'),
(2178, 0, 0, 1233551102, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1233551102'),
(2179, 0, 0, 1233944318, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1233944318'),
(2180, 0, 0, 1234075390, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1234075390'),
(2181, 0, 0, 1234568766, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1234568766'),
(2182, 0, 0, 1234583806, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1234583806'),
(2183, 0, 0, 1234595510, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1234595510'),
(2184, 0, 0, 1234595518, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1234595518'),
(2185, 0, 0, 1234595582, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1234595582'),
(2186, 0, 0, 1234597430, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1234597430'),
(2187, 0, 0, 1234599094, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1234599094'),
(2188, 0, 0, 1234599158, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1234599158'),
(2189, 0, 0, 1234599606, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1234599606'),
(2190, 0, 0, 1234599610, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1234599610'),
(2191, 0, 0, 1234599614, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1234599614'),
(2192, 0, 0, 1234599654, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1234599654'),
(2193, 0, 0, 1234599670, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1234599670'),
(2194, 0, 0, 1234599678, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1234599678'),
(2195, 0, 0, 1234632374, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1234632374'),
(2196, 0, 0, 1234992894, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1234992894'),
(2197, 0, 0, 1235119870, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1235119870'),
(2198, 0, 0, 1235123964, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1235123964'),
(2199, 0, 0, 1235123966, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1235123966'),
(2200, 0, 0, 1237221118, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1237221118'),
(2201, 0, 0, 1275494326, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1275494326'),
(2202, 0, 0, 1291996862, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1291996862'),
(2203, 0, 0, 1292000954, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1292000954'),
(2204, 0, 0, 1292000958, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1292000958'),
(2205, 0, 0, 1292009150, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1292009150'),
(2206, 0, 0, 1292033724, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1292033724'),
(2207, 0, 0, 1292033726, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1292033726'),
(2208, 0, 0, 1292270270, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1292270270'),
(2209, 0, 0, 1292271166, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1292271166'),
(2210, 0, 0, 1292271294, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1292271294'),
(2211, 0, 0, 1292271358, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1292271358'),
(2212, 0, 0, 1293188798, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1293188798'),
(2213, 0, 0, 1293311670, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1293311670'),
(2214, 0, 0, 1293315754, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1293315754'),
(2215, 0, 0, 1293315774, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1293315774'),
(2216, 0, 0, 1293317684, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1293317684'),
(2217, 0, 0, 1293318838, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1293318838'),
(2218, 0, 0, 1293319862, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1293319862'),
(2219, 0, 0, 1293319870, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1293319870'),
(2220, 0, 0, 1293319926, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1293319926'),
(2221, 0, 0, 1293876926, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1293876926');
DELETE FROM `creature_immunities` WHERE `ID` IN (2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271);
INSERT INTO `creature_immunities` (`ID`, `SchoolMask`, `DispelTypeMask`, `MechanicsMask`, `Effects`, `Auras`, `ImmuneAoE`, `ImmuneChain`, `Comment`) VALUES
(2222, 0, 0, 1300692542, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1300692542'),
(2223, 0, 0, 1300692670, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1300692670'),
(2224, 0, 0, 1301053166, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301053166'),
(2225, 0, 0, 1301184254, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301184254'),
(2226, 0, 0, 1301446398, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301446398'),
(2227, 0, 0, 1301677626, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301677626'),
(2228, 0, 0, 1301677630, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301677630'),
(2229, 0, 0, 1301702270, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301702270'),
(2230, 0, 0, 1301703934, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301703934'),
(2231, 0, 0, 1301704382, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301704382'),
(2232, 0, 0, 1301704446, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301704446'),
(2233, 0, 0, 1301706494, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301706494'),
(2234, 0, 0, 1301707958, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301707958'),
(2235, 0, 0, 1301708022, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301708022'),
(2236, 0, 0, 1301708462, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301708462'),
(2237, 0, 0, 1301708470, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301708470'),
(2238, 0, 0, 1301708478, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301708478'),
(2239, 0, 0, 1301708526, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301708526'),
(2240, 0, 0, 1301708534, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301708534'),
(2241, 0, 0, 1301708538, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301708538'),
(2242, 0, 0, 1301708540, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301708540'),
(2243, 0, 0, 1301708542, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301708542'),
(2244, 0, 0, 1301741246, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301741246'),
(2245, 0, 0, 1301741310, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1301741310'),
(2246, 0, 0, 1302232766, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1302232766'),
(2247, 0, 0, 1302232830, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1302232830'),
(2248, 0, 0, 1303871230, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1303871230'),
(2249, 0, 0, 1304395518, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1304395518'),
(2250, 0, 0, 1304428286, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1304428286'),
(2251, 0, 0, 1305378558, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1305378558'),
(2252, 0, 0, 1335787254, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1335787254'),
(2253, 0, 0, 1539276542, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1539276542'),
(2254, 0, 0, 1770663678, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1770663678'),
(2255, 0, 0, 1770946302, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1770946302'),
(2256, 0, 0, 1804534846, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 1804534846'),
(2257, 0, 0, 2013265920, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2013265920'),
(2258, 0, 0, 2013528064, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2013528064'),
(2259, 0, 0, 2013528100, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2013528100'),
(2260, 0, 0, 2013660192, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2013660192'),
(2261, 0, 0, 2022966272, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2022966272'),
(2262, 0, 0, 2030453792, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2030453792'),
(2263, 0, 0, 2031386302, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2031386302'),
(2264, 0, 0, 2031502368, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2031502368'),
(2265, 0, 0, 2031502372, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2031502372'),
(2266, 0, 0, 2031512736, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2031512736'),
(2267, 0, 0, 2031516704, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2031516704'),
(2268, 0, 0, 2031516708, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2031516708'),
(2269, 0, 0, 2031516836, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2031516836'),
(2270, 0, 0, 2031517372, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2031517372'),
(2271, 0, 0, 2038842400, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2038842400');
DELETE FROM `creature_immunities` WHERE `ID` IN (2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321);
INSERT INTO `creature_immunities` (`ID`, `SchoolMask`, `DispelTypeMask`, `MechanicsMask`, `Effects`, `Auras`, `ImmuneAoE`, `ImmuneChain`, `Comment`) VALUES
(2272, 0, 0, 2038842402, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2038842402'),
(2273, 0, 0, 2039890978, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2039890978'),
(2274, 0, 0, 2039890982, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2039890982'),
(2275, 0, 0, 2039901750, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2039901750'),
(2276, 0, 0, 2039905318, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2039905318'),
(2277, 0, 0, 2039905444, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2039905444'),
(2278, 0, 0, 2039905446, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2039905446'),
(2279, 0, 0, 2039905454, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2039905454'),
(2280, 0, 0, 2039905956, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2039905956'),
(2281, 0, 0, 2039905974, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2039905974'),
(2282, 0, 0, 2039906038, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2039906038'),
(2283, 0, 0, 2039906046, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2039906046'),
(2284, 0, 0, 2041872062, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2041872062'),
(2285, 0, 0, 2042588340, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2042588340'),
(2286, 0, 0, 2042588342, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2042588342'),
(2287, 0, 0, 2042592436, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2042592436'),
(2288, 0, 0, 2042592438, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2042592438'),
(2289, 0, 0, 2044099622, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2044099622'),
(2290, 0, 0, 2076147382, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2076147382'),
(2291, 0, 0, 2107014838, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2107014838'),
(2292, 0, 0, 2143256254, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2143256254'),
(2293, 0, 0, 2143289022, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2143289022'),
(2294, 0, 0, 2147483646, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 2147483646'),
(2295, 0, 0, 3116367612, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 3116367612'),
(2296, 0, 0, 3386277110, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 3386277110'),
(2297, 0, 0, 4294934270, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 4294934270'),
(2298, 0, 0, 4294967038, '', '', 0, 0, 'SchoolMask 0, MechanicsMask 4294967038'),
(2299, 1, 0, 16777248, '', '', 0, 0, 'SchoolMask 1, MechanicsMask 16777248'),
(2300, 1, 0, 1301708478, '', '', 0, 0, 'SchoolMask 1, MechanicsMask 1301708478'),
(2301, 4, 0, 0, '', '', 0, 0, 'SchoolMask 4, MechanicsMask 0'),
(2302, 4, 0, 32, '', '', 0, 0, 'SchoolMask 4, MechanicsMask 32'),
(2303, 4, 0, 17416, '', '', 0, 0, 'SchoolMask 4, MechanicsMask 17416'),
(2304, 4, 0, 17420, '', '', 0, 0, 'SchoolMask 4, MechanicsMask 17420'),
(2305, 4, 0, 17432, '', '', 0, 0, 'SchoolMask 4, MechanicsMask 17432'),
(2306, 4, 0, 16784544, '', '', 0, 0, 'SchoolMask 4, MechanicsMask 16784544'),
(2307, 4, 0, 1226210998, '', '', 0, 0, 'SchoolMask 4, MechanicsMask 1226210998'),
(2308, 4, 0, 1226211006, '', '', 0, 0, 'SchoolMask 4, MechanicsMask 1226211006'),
(2309, 4, 0, 1234599606, '', '', 0, 0, 'SchoolMask 4, MechanicsMask 1234599606'),
(2310, 4, 0, 1292000954, '', '', 0, 0, 'SchoolMask 4, MechanicsMask 1292000954'),
(2311, 4, 0, 1292271294, '', '', 0, 0, 'SchoolMask 4, MechanicsMask 1292271294'),
(2312, 4, 0, 1293188798, '', '', 0, 0, 'SchoolMask 4, MechanicsMask 1293188798'),
(2313, 4, 0, 1301704446, '', '', 0, 0, 'SchoolMask 4, MechanicsMask 1301704446'),
(2314, 4, 0, 1301708478, '', '', 0, 0, 'SchoolMask 4, MechanicsMask 1301708478'),
(2315, 4, 0, 1301708542, '', '', 0, 0, 'SchoolMask 4, MechanicsMask 1301708542'),
(2316, 4, 0, 2039905974, '', '', 0, 0, 'SchoolMask 4, MechanicsMask 2039905974'),
(2317, 8, 0, 0, '', '', 0, 0, 'SchoolMask 8, MechanicsMask 0'),
(2318, 8, 0, 16, '', '', 0, 0, 'SchoolMask 8, MechanicsMask 16'),
(2319, 8, 0, 1090674362, '', '', 0, 0, 'SchoolMask 8, MechanicsMask 1090674362'),
(2320, 8, 0, 1217817766, '', '', 0, 0, 'SchoolMask 8, MechanicsMask 1217817766'),
(2321, 8, 0, 1234599606, '', '', 0, 0, 'SchoolMask 8, MechanicsMask 1234599606');
DELETE FROM `creature_immunities` WHERE `ID` IN (2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,2334,2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,2352,2353,2354,2355);
INSERT INTO `creature_immunities` (`ID`, `SchoolMask`, `DispelTypeMask`, `MechanicsMask`, `Effects`, `Auras`, `ImmuneAoE`, `ImmuneChain`, `Comment`) VALUES
(2322, 8, 0, 1291998778, '', '', 0, 0, 'SchoolMask 8, MechanicsMask 1291998778'),
(2323, 8, 0, 1292000954, '', '', 0, 0, 'SchoolMask 8, MechanicsMask 1292000954'),
(2324, 8, 0, 1292000958, '', '', 0, 0, 'SchoolMask 8, MechanicsMask 1292000958'),
(2325, 8, 0, 1292271358, '', '', 0, 0, 'SchoolMask 8, MechanicsMask 1292271358'),
(2326, 8, 0, 1293188798, '', '', 0, 0, 'SchoolMask 8, MechanicsMask 1293188798'),
(2327, 8, 0, 1293319870, '', '', 0, 0, 'SchoolMask 8, MechanicsMask 1293319870'),
(2328, 8, 0, 1300397758, '', '', 0, 0, 'SchoolMask 8, MechanicsMask 1300397758'),
(2329, 16, 0, 0, '', '', 0, 0, 'SchoolMask 16, MechanicsMask 0'),
(2330, 16, 0, 16, '', '', 0, 0, 'SchoolMask 16, MechanicsMask 16'),
(2331, 16, 0, 20516, '', '', 0, 0, 'SchoolMask 16, MechanicsMask 20516'),
(2332, 16, 0, 16777248, '', '', 0, 0, 'SchoolMask 16, MechanicsMask 16777248'),
(2333, 16, 0, 1090674362, '', '', 0, 0, 'SchoolMask 16, MechanicsMask 1090674362'),
(2334, 16, 0, 1217817766, '', '', 0, 0, 'SchoolMask 16, MechanicsMask 1217817766'),
(2335, 16, 0, 1226210998, '', '', 0, 0, 'SchoolMask 16, MechanicsMask 1226210998'),
(2336, 16, 0, 1234599606, '', '', 0, 0, 'SchoolMask 16, MechanicsMask 1234599606'),
(2337, 16, 0, 1292000954, '', '', 0, 0, 'SchoolMask 16, MechanicsMask 1292000954'),
(2338, 16, 0, 1293188798, '', '', 0, 0, 'SchoolMask 16, MechanicsMask 1293188798'),
(2339, 16, 0, 1301708538, '', '', 0, 0, 'SchoolMask 16, MechanicsMask 1301708538'),
(2340, 16, 0, 1301708542, '', '', 0, 0, 'SchoolMask 16, MechanicsMask 1301708542'),
(2341, 32, 0, 0, '', '', 0, 0, 'SchoolMask 32, MechanicsMask 0'),
(2342, 64, 0, 0, '', '', 0, 0, 'SchoolMask 64, MechanicsMask 0'),
(2343, 64, 0, 32, '', '', 0, 0, 'SchoolMask 64, MechanicsMask 32'),
(2344, 64, 0, 6688, '', '', 0, 0, 'SchoolMask 64, MechanicsMask 6688'),
(2345, 64, 0, 10368, '', '', 0, 0, 'SchoolMask 64, MechanicsMask 10368'),
(2346, 64, 0, 1234599094, '', '', 0, 0, 'SchoolMask 64, MechanicsMask 1234599094'),
(2347, 64, 0, 1235123966, '', '', 0, 0, 'SchoolMask 64, MechanicsMask 1235123966'),
(2348, 96, 0, 0, '', '', 0, 0, 'SchoolMask 96, MechanicsMask 0'),
(2349, 116, 0, 0, '', '', 0, 0, 'SchoolMask 116, MechanicsMask 0'),
(2350, 124, 0, 17171490, '', '', 0, 0, 'SchoolMask 124, MechanicsMask 17171490'),
(2351, 124, 0, 1234599614, '', '', 0, 0, 'SchoolMask 124, MechanicsMask 1234599614'),
(2352, 126, 0, 0, '', '', 0, 0, 'SchoolMask 126, MechanicsMask 0'),
(2353, 126, 0, 1292271286, '', '', 0, 0, 'SchoolMask 126, MechanicsMask 1292271286'),
(2354, 127, 0, 16777248, '', '', 0, 0, 'SchoolMask 127, MechanicsMask 16777248'),
(2355, 127, 0, 1301741246, '', '', 0, 0, 'SchoolMask 127, MechanicsMask 1301741246');
-- Update creature_template.CreatureImmunitiesId
UPDATE `creature_template` SET `CreatureImmunitiesId`=1537 WHERE `entry` IN (17543,18404);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1664 WHERE `entry` IN (4468);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1794 WHERE `entry` IN (3253,36551,37564);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1964 WHERE `entry` IN (20047);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1971 WHERE `entry` IN (20038,25367,25368,25371,25507);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1972 WHERE `entry` IN (352,523,752,931,1387,1571,1572,1573,2299,2409,2432,2835,2851,2858,2859,2861,2941,2995,3305,3310,3615,3725,3728,4312,4314,4317,4321,6026,6726,7823,7824,8018,8020,8609,8610,10378,11139,11830,11899,11900,11901,12596,12616,12617,12740,13177,15178,16218,16461,16593,16699,16704,17083,17229,17398,17420,17429,17461,17491,17622,17695,18048,18049,18050,18052,18053,18054,18057,18058,18603,18609,18610,18612,18615,18619,18631,18632,18635,18636,18830,19885,19887,19889,19903,20033,20034,20255,20256,20257,20258,20259,20260,20261,20578,20579,20580,20581,20582,20586,20587,20590,20594,20621,20624,20626,20639,20640,20641,20642,20644,20645,20661,20693,20695,20699,20701,20923,21230,21522,21524,21527,21528,21532,21545,21548,21563,21564,21565,21570,21571,21573,21575,21576,21585,21587,21613,21857,21865,21873,22876,23168,24994,25509,25591,25593,25595,25599,25851,26799,26800,26801,26802,26803,26805,27947,27949,29503,29626,30460,30478,30485,30495,30496,30497,30498,30508,30509,32922,32923,32924,32925,33235,33236,33259,33287,33355,33527,33579,33620,33622,33624,33626,33627,33629,33662,33669,33672,33696,33701,33737,33741,33754,33755,33757,33758,33774,33775,33816,33818,33819);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1972 WHERE `entry` IN (33820,33822,33823,33824,33827,33828,33829,33830,33831,33832,33956,33957,34054,34113,34144,34145,34198,34199,34236,34237,34255,34256,34257,34441,34442,34443,34444,34445,34447,34448,34449,34450,34451,34453,34454,34455,34456,34458,34459,34460,34461,34463,34465,34466,34467,34468,34469,34470,34471,34472,34473,34474,34475,35465,35610,35662,35663,35664,35665,35666,35667,35668,35669,35670,35671,35672,35673,35674,35675,35676,35680,35681,35682,35683,35684,35685,35686,35687,35688,35689,35690,35691,35692,35693,35694,35695,35696,35697,35699,35700,35701,35702,35703,35704,35705,35706,35707,35708,35709,35710,35711,35712,35713,35714,35715,35716,35718,35719,35720,35721,35722,35723,35724,35725,35726,35728,35729,35730,35731,35732,35733,35734,35735,35736,35737,35738,35739,35740,35741,35742,35743,35744,35745,35746,35747,35748,35749,35774,35775,35776,36070,36301,36302,36303,36473,36474,36475);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1973 WHERE `entry` IN (12737);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1974 WHERE `entry` IN (13996,14462,25752,25753,25758,25792);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1975 WHERE `entry` IN (24553,24554,24555,24556,24557,24558,24559,24561,24656,25541,25549,25550,25553,25555,25556,25574,25578,25579);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1976 WHERE `entry` IN (8717,21549);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1977 WHERE `entry` IN (30839);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1978 WHERE `entry` IN (20869,21586);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1979 WHERE `entry` IN (2673,2674,4952,12426,16844,16968,17578,18215,19139,21157,21849,22038,22466,22482,24792,30527,31143,31144,31146,32541,32542,32543,32545,32546,32547,32666,32667,33229,33243,33272,37127,38126);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1980 WHERE `entry` IN (20897,23398);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1981 WHERE `entry` IN (21597,22879,22882,22945,23018,23049,23147,23172,23223,23235,23236,23237,24815,25566);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1982 WHERE `entry` IN (5277,5280,5283,8319,16098,17669,20574);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1983 WHERE `entry` IN (22299,22300);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1984 WHERE `entry` IN (3678);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1985 WHERE `entry` IN (23584);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1986 WHERE `entry` IN (19005,22874,22885);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1987 WHERE `entry` IN (18707);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1988 WHERE `entry` IN (18533,20772);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1989 WHERE `entry` IN (21166);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1990 WHERE `entry` IN (18044,22939);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1991 WHERE `entry` IN (8908);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1992 WHERE `entry` IN (18258);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1993 WHERE `entry` IN (18046);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1994 WHERE `entry` IN (22957,22962);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1995 WHERE `entry` IN (18420,21574);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1996 WHERE `entry` IN (20052);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1997 WHERE `entry` IN (21225);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1998 WHERE `entry` IN (24549);
UPDATE `creature_template` SET `CreatureImmunitiesId`=1999 WHERE `entry` IN (34702,34703,35569,35570,35571,35572,35617,36082,36083,36084,36085,36086,36087,36088,36089,36090,36091);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2000 WHERE `entry` IN (20048);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2001 WHERE `entry` IN (20883,21615);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2002 WHERE `entry` IN (28163,28168);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2003 WHERE `entry` IN (12800,12801,12802);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2004 WHERE `entry` IN (24047);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2005 WHERE `entry` IN (18423);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2006 WHERE `entry` IN (12458);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2007 WHERE `entry` IN (22875);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2008 WHERE `entry` IN (7397);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2009 WHERE `entry` IN (13601);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2010 WHERE `entry` IN (30829,30830,30831);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2011 WHERE `entry` IN (2667,2671,7076,7077,7309,8376,8816,9657,15104,15108,15429,15631,15698,15706,15904,15910,15964,15973,16511);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2012 WHERE `entry` IN (26688);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2013 WHERE `entry` IN (16700,17732,19632,20174,24179,29273);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2014 WHERE `entry` IN (14261,14262,14263,14264,14265,20588,20589);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2015 WHERE `entry` IN (17816,17817,19884,19892);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2016 WHERE `entry` IN (19513,19598,19865,21560,21561,21562);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2017 WHERE `entry` IN (17465,20583,22955);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2018 WHERE `entry` IN (32361,32377,32409,32417,32422,32429,32447,32475,32481,32485);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2019 WHERE `entry` IN (22965);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2020 WHERE `entry` IN (24180);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2021 WHERE `entry` IN (24065);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2022 WHERE `entry` IN (21515);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2023 WHERE `entry` IN (24530);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2024 WHERE `entry` IN (18322,20696);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2025 WHERE `entry` IN (15146,25363);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2026 WHERE `entry` IN (17818,17864,18848,20656,20881,20900,21619,21621,25592,25948);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2027 WHERE `entry` IN (7728);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2028 WHERE `entry` IN (25798,25799);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2029 WHERE `entry` IN (26928,26929,26930,30511,30512,30513);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2030 WHERE `entry` IN (18182);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2031 WHERE `entry` IN (32500);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2032 WHERE `entry` IN (17731,20173);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2033 WHERE `entry` IN (19191);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2034 WHERE `entry` IN (19261);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2035 WHERE `entry` IN (3,36,114,115,200,201,204,210,302,314,315,392,412,480,503,511,522,570,572,573,604,624,625,626,725,846,882,948,1159,1270,1488,1489,1491,1501,1502,1525,1526,1527,1528,1529,1530,1532,1533,1654,1656,1663,1666,1674,1675,1696,1716,1717,1720,1753,1772,1773,1790,1791,1792,1793,1794,1795,1796,1798,1805,1847,1849,1850,1852,1866,1868,1917,1918,1919,1921,1939,1940,1941,1942,1943,1944,1948,1971,1974,2045,2056,2217,2218,2219,2220,2221,2222,2227,2278,2288,2325,2433,2475,2479,2520,2531,2535,2536,2537,2623,2676,2678,2748,2763,2922,3094,3301,3538,3558,3565,3617,3654,3669,3670,3671,3673,3674,3799,3802,3803,3869,3870,3876,3914,3940,3941,3942,3983,4073,4074,4251,4252,4260,4308,4473,4474,4475,4476,4550,4566,4606,4610,4612,4854,4872,4945,4946,4958,5097,5202,5263,5267,5270,5271,5400,5621,5624,5626,5627,5674,5685,5686,5687,5712,5713,5714,5715,5716,5717,5723,5775,5854,5912,5954,6036,6092,6106,6107,6108,6225,6226,6227,6230,6231,6232,6233,6234,6346,6386,6426,6427,6486,6493,6669,6906);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2035 WHERE `entry` IN (6907,6908,6910,7023,7039,7050,7067,7068,7069,7070,7071,7072,7075,7166,7206,7209,7270,7273,7274,7276,7286,7291,7310,7327,7328,7329,7332,7333,7334,7340,7347,7348,7349,7351,7352,7353,7354,7355,7356,7357,7358,7374,7375,7503,7504,7527,7624,7784,7791,7806,7807,7849,7895,7897,8035,8447,8500,8501,8530,8531,8532,8534,8535,8536,8537,8543,8544,8545,8552,8555,8556,8557,8558,8559,8567,8580,8585,8615,8663,8856,9437,9438,9439,9441,9442,9443,9476,9623,10080,10081,10082,10117,10381,10382,10383,10395,10397,10402,10403,10405,10406,10407,10408,10409,10411,10412,10413,10414,10416,10417,10463,10464,10479,10480,10481,10483,10484,10492,10493,10494,10495,10497,10498,10499,10500,10580,10666,10684,10698,10699,10778,10801,10810,10818,10819,10820,10821,10825,10836,10926,10927,10936,10937,10939,10943,10944,10945,10946,10949,10950,10951,10953,10954,11027,11030,11075,11082,11151,11153,11154,11155,11179,11195,11199,11216,11217,11263,11277,11278,11279,11280,11281,11282,11283,11286,11287,11290,11291,11292,11316,11412,11414,11415,11446,11468,11469,11470,11471,11472,11473,11474,11475,11477,11517,11518,11519,11520,11551,11580,11598);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2035 WHERE `entry` IN (11628,11684,11875,11936,12238,12239,12240,12241,12242,12243,12248,12250,12261,12262,12263,12363,12364,12365,12367,12368,12379,12380,12385,12473,12865,13146,13378,13416,13619,13738,13739,13740,13741,13742,14224,14308,14337,14358,14364,14484,14485,14494,14511,14512,14513,14514,14518,14519,14520,14521,14551,14552,14553,14554,14562,14563,14605,14683,14685,14686,14687,14688,14691,14692,14694,14695,14696,14697,14698,14699,14700,14701,14702,14703,14704,14705,14706,14707,14708,14709,14710,14711,14712,14713,14714,14825,14826,14986,15079,15081,15117,15121,15163,15195,15349,15364,15368,15374,15376,15377,15547,15548,15551,15654,15655,15656,15657,15658,15665,15720,15958,16025,16026,16039,16040,16059,16066,16067,16093,16099,16103,16104,16119,16120,16125,16138,16141,16145,16146,16148,16153,16154,16159,16163,16169,16184,16211,16245,16246,16247,16248,16249,16250,16298,16300,16301,16302,16303,16305,16306,16307,16308,16309,16311,16312,16313,16314,16316,16319,16320,16321,16322,16323,16324,16325,16326,16327,16328,16329,16342,16357,16382,16383,16388,16389,16390,16393,16394,16402,16403,16406,16407,16408,16409,16410,16411,16412,16415,16424,16425,16426,16432,16437,16439,16451,16459,16460,16468,16470,16471);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2035 WHERE `entry` IN (16481,16482,16525,16526,16805,16806,16811,16812,16813,16814,16815,16861,16904,16905,16906,16976,16977,16978,17007,17063,17064,17067,17086,17261,17415,17466,17503,17588,17589,17592,17612,17660,17672,17674,17714,17878,17895,17897,17898,17902,17903,17905,17906,18043,18287,18319,18320,18327,18355,18367,18441,18460,18478,18498,18499,18500,18501,18506,18521,18524,18556,18557,18558,18559,18588,18643,18689,18700,18797,18872,18873,19416,19417,19460,19463,19464,19488,19489,19543,19544,19545,19546,19579,19580,19682,19698,19719,19736,19749,19751,19825,19826,19827,19846,19863,19864,19872,19873,19874,19875,19876,19878,19879,19881,19937,20117,20137,20298,20303,20305,20310,20311,20312,20313,20315,20316,20317,20319,20320,20321,20322,20323,20409,20410,20480,20483,20495,20496,20512,20662,20691,20697,20698,20934,21049,21058,21065,21093,21163,21184,21198,21199,21200,21201,21202,21324,21354,21384,21385,21386,21430,21446,21449,21450,21452,21628,21636,21638,21651,21763,21778,21779,21784,21787,21788,21795,21797,21801,21815,21866,21867,21869,21870,21941,22025,22041,22045,22062,22138,22226,22235,22369,22441,22452,22454,22701,22706,23066,23067,23068,23103,23109,23111,23126,23161,23193,23204,23370,23371,23389);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2035 WHERE `entry` IN (23408,23503,23509,23545,23554,23555,23561,23562,23563,23575,23643,23644,23645,23786,23861,23898,23904,23935,23970,23992,23993,24013,24019,24027,24029,24041,24073,24074,24084,24118,24153,24168,24177,24207,24246,24247,24248,24258,24262,24266,24267,24272,24327,24344,24440,24446,24447,24485,24546,24562,24563,24564,24566,24621,24622,24623,24624,24625,24626,24627,24693,24695,24712,24789,24790,24796,24808,24814,24871,24872,24874,24875,24876,24877,24880,25027,25028,25041,25224,25227,25228,25268,25294,25296,25330,25331,25332,25333,25350,25351,25352,25359,25365,25366,25375,25377,25382,25383,25386,25387,25393,25396,25445,25451,25452,25453,25462,25463,25465,25469,25542,25546,25559,25582,25600,25611,25619,25622,25625,25629,25650,25652,25655,25660,25668,25678,25682,25684,25981,26073,26076,26103,26115,26125,26126,26165,26195,26202,26203,26224,26225,26250,26252,26286,26287,26292,26294,26317,26318,26320,26336,26343,26344,26402,26404,26413,26455,26457,26458,26461,26475,26490,26491,26492,26501,26509,26515,26517,26518,26526,26536,26555,26570,26573,26605,26606,26607,26608,26621,26623,26624,26635,26636,26637,26638,26658,26669,26670,26676,26690,26691,26692,26694,26696,26702,26703,26769,26770,26771,26811);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2035 WHERE `entry` IN (26812,26824,26830,26840,26841,26858,26871,26891,26946,26948,26966,26967,27018,27059,27105,27122,27152,27153,27165,27219,27220,27224,27225,27226,27229,27240,27241,27268,27270,27272,27282,27283,27284,27285,27286,27287,27288,27290,27335,27360,27362,27363,27370,27383,27400,27401,27410,27465,27505,27510,27513,27531,27533,27534,27551,27552,27556,27561,27604,27605,27611,27614,27616,27618,27620,27623,27624,27630,27631,27680,27683,27685,27686,27691,27693,27694,27696,27712,27729,27733,27734,27736,27737,27766,27767,27768,27769,27770,27771,27772,27773,27774,27775,27776,27777,27778,27779,27780,27781,27782,27797,27799,27800,27807,27808,27809,27821,27822,27823,27824,27825,27829,27835,27836,27848,27854,27871,27874,27941,27957,28005,28006,28007,28014,28018,28022,28023,28026,28101,28103,28104,28108,28144,28158,28159,28162,28170,28194,28199,28200,28201,28207,28208,28211,28212,28218,28220,28232,28242,28243,28246,28249,28255,28257,28258,28268,28270,28278,28349,28350,28356,28357,28364,28365,28369,28377,28383,28395,28405,28406,28412,28414,28419,28420,28421,28422,28423,28424,28425,28426,28427,28428,28429,28430,28431,28432,28433,28434,28435,28436,28437,28438,28444,28445,28446,28447,28448,28449,28450,28471);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2035 WHERE `entry` IN (28472,28474,28475,28476,28487,28488,28498,28499,28500,28503,28506,28510,28512,28519,28528,28534,28564,28565,28570,28589,28590,28599,28603,28615,28628,28641,28642,28647,28651,28653,28654,28657,28658,28659,28666,28669,28670,28711,28732,28733,28734,28735,28736,28745,28747,28748,28749,28750,28752,28754,28756,28759,28760,28768,28769,28782,28788,28793,28802,28803,28805,28843,28864,28866,28867,28868,28869,28870,28871,28872,28875,28878,28879,28889,28890,28897,28901,28903,28905,28906,28907,28908,28909,28910,28911,28913,28914,28915,28919,28924,28925,28930,28931,28933,28934,28937,28943,28948,28998,29030,29031,29047,29051,29053,29062,29063,29064,29096,29097,29098,29101,29106,29107,29108,29109,29110,29111,29112,29113,29115,29117,29118,29119,29123,29128,29129,29133,29136,29153,29172,29173,29183,29185,29186,29187,29188,29189,29190,29191,29193,29194,29195,29196,29197,29198,29199,29200,29201,29202,29204,29205,29206,29207,29208,29209,29210,29212,29213,29214,29216,29217,29219,29221,29227,29230,29231,29232,29238,29239,29245,29246,29256,29263,29280,29286,29335,29340,29347,29349,29353,29354,29355,29356,29359,29362,29363,29371,29388,29394,29400,29414,29449,29450,29451,29453,29468,29480,29488,29501,29517);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2035 WHERE `entry` IN (29519,29520,29522,29565,29566,29567,29570,29574,29576,29587,29609,29629,29632,29633,29634,29635,29646,29648,29654,29656,29697,29699,29704,29719,29720,29722,29738,29769,29770,29821,29823,29824,29825,29828,29831,29833,29835,29837,29840,29842,29851,29852,29856,29858,29859,29860,29863,29872,29882,29887,29890,29891,29892,29893,29894,29895,29897,29898,29899,29900,29901,29934,29935,29943,29974,29985,29986,29987,29988,29989,29990,30015,30016,30018,30027,30028,30029,30030,30031,30032,30033,30034,30047,30048,30049,30071,30074,30075,30083,30085,30087,30097,30135,30144,30150,30202,30203,30204,30205,30216,30230,30232,30235,30250,30264,30276,30277,30278,30283,30284,30285,30286,30287,30288,30303,30306,30307,30309,30310,30311,30333,30335,30338,30378,30389,30403,30404,30406,30409,30424,30432,30443,30471,30482,30486,30501,30523,30541,30542,30543,30544,30545,30546,30575,30593,30594,30597,30609,30629,30670,30687,30689,30696,30697,30698,30701,30728,30746,30778,30791,30806,30816,30817,30818,30819,30821,30822,30823,30836,30843,30851,30863,30864,30865,30894,30895,30920,30921,30922,30944,30945,30946,30947,30949,30951,30952,30953,30954,30955,30956,30957,30958,30960,30984,30985,30986,30987,30988,30989,30992);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2035 WHERE `entry` IN (30993,31012,31014,31015,31029,31037,31039,31040,31042,31043,31048,31078,31082,31083,31084,31087,31088,31089,31090,31094,31095,31096,31097,31098,31099,31100,31104,31107,31110,31123,31135,31137,31139,31140,31141,31142,31147,31150,31152,31154,31155,31157,31159,31160,31161,31163,31178,31179,31183,31184,31187,31188,31191,31192,31193,31194,31195,31196,31198,31199,31200,31205,31207,31208,31220,31221,31222,31223,31224,31225,31226,31227,31231,31237,31251,31255,31263,31266,31268,31271,31274,31278,31283,31301,31318,31320,31321,31322,31323,31324,31325,31326,31327,31341,31342,31346,31347,31351,31352,31354,31355,31357,31361,31363,31396,31398,31411,31413,31438,31442,31443,31447,31449,31450,31451,31457,31460,31466,31468,31530,31531,31532,31554,31555,31556,31565,31583,31585,31586,31587,31588,31589,31590,31591,31593,31594,31595,31596,31597,31598,31599,31600,31601,31602,31603,31604,31605,31606,31607,31608,31609,31613,31614,31635,31647,31671,31681,31692,31702,31718,31721,31754,31775,31779,31780,31783,31787,31812,31813,31815,31843,31844,31847,31853,31900,32031,32037,32149,32160,32161,32163,32164,32175,32176,32178,32179,32181,32182,32183,32184,32188,32255,32257,32267,32272,32278,32280,32283,32284,32288);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2035 WHERE `entry` IN (32292,32299,32300,32309,32323,32326,32350,32390,32391,32404,32408,32410,32423,32446,32467,32479,32480,32482,32483,32490,32492,32497,32499,32502,32503,32505,32507,32508,32511,32556,32593,32609,32767,32769,32770,32771,32772,32786,32787,33016,33017,33429,33438,33441,33499,33513,33519,33550,33663,33664,33667,33668,33687,33704,33798,34127,34154,34238,34801,35169,35255,35444,35461,35474,35493,35547,35557,35559,35560,35652,35653,35654,35763,36065,36066,36128,36173,36478,36503,36504,36522,36564,36595,36666,36677,36724,36725,36726,36792,36794,36796,36807,36824,36829,36830,36840,36841,36842,36844,36875,36877,36879,36880,36881,36886,36893,36896,36907,36916,36940,36941,37007,37011,37012,37022,37023,37038,37069,37120,37128,37228,37229,37232,37351,37357,37491,37493,37494,37495,37501,37502,37530,37532,37535,37538,37539,37541,37542,37544,37545,37546,37549,37550,37551,37563,37565,37569,37571,37586,37595,37612,37622,37635,37636,37637,37638,37639,37640,37642,37644,37655,37656,37657,37658,37662,37663,37664,37665,37666,37678,37711,37728,37729,37730,37731,37755,37845,37846,37857,37881,37893,37906,37945,37976,38004,38031,38057,38058,38059,38061,38062,38063,38073,38074,38077,38098,38099,38100,38101,38102);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2035 WHERE `entry` IN (38104,38105,38108,38134,38137,38151,38172,38173,38175,38176,38177,38184,38185,38186,38193,38197,38198,38216,38222,38248,38249,38260,38308,38309,38349,38350,38351,38352,38362,38367,38386,38388,38391,38392,38410,38419,38429,38430,38445,38446,38479,38480,38481,38487,38524,38525,38544,38545,38563,38564,38567,38568,38572,38610,38763,38857,38883,39048,39231,39232,39233,39234,39296,39639,40274);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2036 WHERE `entry` IN (25597,37695,39309,39310,39311);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2037 WHERE `entry` IN (8836);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2038 WHERE `entry` IN (7915,16111);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2039 WHERE `entry` IN (14682);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2040 WHERE `entry` IN (18259,18648);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2041 WHERE `entry` IN (20682);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2042 WHERE `entry` IN (20783,20784,20785,20786,20788,20789,20790);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2043 WHERE `entry` IN (14684,14690);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2044 WHERE `entry` IN (14693);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2045 WHERE `entry` IN (17725,17871,20188,20190);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2046 WHERE `entry` IN (22848);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2047 WHERE `entry` IN (11447,11497,11498);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2048 WHERE `entry` IN (1157,1158,1160,1534,1655,1800,1801,1802,1804,1946,1983,2044,2176,2177,2178,2638,3667,3801,4472,6116,6117,6133,7073,7074,7370,7523,7524,7864,8538,8539,8540,8541,8542,10387,10388,10389,10940,10947,10948,11064,11078,11141,11285,11288,11289,11296,11560,11620,11621,11686,11687,11873,12178,12179,12199,12377,12378,14564,16423);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2049 WHERE `entry` IN (1531,2184,3863,3872,3873,3875,3877,6118,10358,10384,10385,10938,10996,16143,16379);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2050 WHERE `entry` IN (18856);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2051 WHERE `entry` IN (6021,9299,10988);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2052 WHERE `entry` IN (15554);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2053 WHERE `entry` IN (22338);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2054 WHERE `entry` IN (23269);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2055 WHERE `entry` IN (19354);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2056 WHERE `entry` IN (17724,20185,20465,21943);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2057 WHERE `entry` IN (48,202,203,531,623,785,787,1110,1520,1522,1523,1657,1658,1783,1784,1785,1787,1788,1789,1865,1869,1870,1871,1890,1916,1973,2454,6388,6412,7343,7344,7346,7786,8477,8523,8524,8525,8526,8527,8528,8529,8884,10390,10391,10482,10816,10952,11076,11077,11156,11197,11200,11258,11476,11547,12208,12341,12342,12343,12344,14486,14489,14558,16299,16422,16438);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2058 WHERE `entry` IN (771,2283,2946,7341,7342,7345,10393,10394,10478,10486,10487,10488,10489,10491,10826,16380);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2059 WHERE `entry` IN (11561);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2060 WHERE `entry` IN (22953);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2061 WHERE `entry` IN (5711);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2062 WHERE `entry` IN (23401);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2063 WHERE `entry` IN (28443);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2064 WHERE `entry` IN (19307,20265);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2065 WHERE `entry` IN (17958);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2066 WHERE `entry` IN (12557);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2067 WHERE `entry` IN (22853);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2068 WHERE `entry` IN (22869,23339);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2069 WHERE `entry` IN (20875,21604);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2070 WHERE `entry` IN (21102);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2071 WHERE `entry` IN (21181,21251);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2072 WHERE `entry` IN (16504);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2073 WHERE `entry` IN (20866,20898,21598,21614,22954);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2074 WHERE `entry` IN (16414,16473);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2075 WHERE `entry` IN (35644,36558);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2076 WHERE `entry` IN (33060,33062,33067,33109,33167,34045);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2077 WHERE `entry` IN (19797);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2078 WHERE `entry` IN (17454);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2079 WHERE `entry` IN (17940,19891,21127);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2080 WHERE `entry` IN (21843);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2081 WHERE `entry` IN (21270,21274);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2082 WHERE `entry` IN (20873,21605);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2083 WHERE `entry` IN (20175);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2084 WHERE `entry` IN (17726,17735,20191,20193);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2085 WHERE `entry` IN (17727,20192);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2086 WHERE `entry` IN (20908,20909,21616,21617);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2087 WHERE `entry` IN (22849);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2088 WHERE `entry` IN (14349);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2089 WHERE `entry` IN (644);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2090 WHERE `entry` IN (15334,15725,15726,15728,15802);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2091 WHERE `entry` IN (18497,20299);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2092 WHERE `entry` IN (21694,21914,24068,25372,31655);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2093 WHERE `entry` IN (18796,20652);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2094 WHERE `entry` IN (17907);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2095 WHERE `entry` IN (20043,20044);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2096 WHERE `entry` IN (21268,21269,21271,21272,21273);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2097 WHERE `entry` IN (14987);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2098 WHERE `entry` IN (15630,15984);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2099 WHERE `entry` IN (25334,26523,27881,27894,28094,28312,28319,28366,28781,32627,32629,32795,32796,34775,34776,34777,34778,34793,34802,34922,34924,34929,34935,34944,35069,35273,35403,35405,35410,35413,35415,35417,35419,35421,35427,35429,35431,35433,35436,35819,36355,36356,36357,36358);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2100 WHERE `entry` IN (20992);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2101 WHERE `entry` IN (16507);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2102 WHERE `entry` IN (20593);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2103 WHERE `entry` IN (16857);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2104 WHERE `entry` IN (18554);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2105 WHERE `entry` IN (23586);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2106 WHERE `entry` IN (19886);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2107 WHERE `entry` IN (34657,34701,34705);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2108 WHERE `entry` IN (22845,23374);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2109 WHERE `entry` IN (12339);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2110 WHERE `entry` IN (10814);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2111 WHERE `entry` IN (23402);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2112 WHERE `entry` IN (23403);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2113 WHERE `entry` IN (23400);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2114 WHERE `entry` IN (6584);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2115 WHERE `entry` IN (17827,20165);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2116 WHERE `entry` IN (22930);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2117 WHERE `entry` IN (17671,20584,20993);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2118 WHERE `entry` IN (23196);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2119 WHERE `entry` IN (22880,22956,22964,23222,23239,23337,23399);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2120 WHERE `entry` IN (22199);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2121 WHERE `entry` IN (18680,22877,22884);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2122 WHERE `entry` IN (22960);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2123 WHERE `entry` IN (22844,22847,22873,22878,22963,23028,23030);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2124 WHERE `entry` IN (34605,34650,35658,35659);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2125 WHERE `entry` IN (36561,36571,40681,40682,40683,40684);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2126 WHERE `entry` IN (40417,40418,40419,40420,40421,40422,40423,40424);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2127 WHERE `entry` IN (37890,37949,38393,38394,38625,38626,38628,38629);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2128 WHERE `entry` IN (18692);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2129 WHERE `entry` IN (38009,38010,38135,38136,38395,38396,38397,38398,38630,38631,38632,38633,38634,38635,39000,39001);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2130 WHERE `entry` IN (38508,38596,38597,38598);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2131 WHERE `entry` IN (38472,38485);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2132 WHERE `entry` IN (34607,34648,35655,35656);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2133 WHERE `entry` IN (37863,38171,38727,38737);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2134 WHERE `entry` IN (36791,37868,37886,37934,38166,38167,38169,38170,38721,38722,38723,38724,38725,38733,38734,38735);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2135 WHERE `entry` IN (20032);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2136 WHERE `entry` IN (20040);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2137 WHERE `entry` IN (20035);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2138 WHERE `entry` IN (20050);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2139 WHERE `entry` IN (22846);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2140 WHERE `entry` IN (20216,20600,22910);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2141 WHERE `entry` IN (16545,22911);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2142 WHERE `entry` IN (23330);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2143 WHERE `entry` IN (36609,37799,39120,39121,39122,39284,39285,39286);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2144 WHERE `entry` IN (33346,33886);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2145 WHERE `entry` IN (22075);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2146 WHERE `entry` IN (20692);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2147 WHERE `entry` IN (18836);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2148 WHERE `entry` IN (11347);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2149 WHERE `entry` IN (11348);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2150 WHERE `entry` IN (17256);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2151 WHERE `entry` IN (22074);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2152 WHERE `entry` IN (14101);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2153 WHERE `entry` IN (639,642,643,645,646,647,1763,3586,3886,3887,3927,4274,4275,4278,4279,4420,4421,4422,4424,4428,4829,4830,4831,4832,4842,6168,6228,6229,6235,6243,6488,6489,6490,7361,7800,10439,11356,12203,12225,12236,12258,12902,13021,13596);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2154 WHERE `entry` IN (24683,24684,24686,24687,24688,24689,24690,24762,25565,25567,25568,25570,25572,25575,25576,25577);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2155 WHERE `entry` IN (24685,25569);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2156 WHERE `entry` IN (12803);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2157 WHERE `entry` IN (19389,21350);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2158 WHERE `entry` IN (18829);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2159 WHERE `entry` IN (8923,9217,9218,9219,9718,10263,10809,11467);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2160 WHERE `entry` IN (30385,31474);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2161 WHERE `entry` IN (17723,20164);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2162 WHERE `entry` IN (11663);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2163 WHERE `entry` IN (21346,21612);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2164 WHERE `entry` IN (23061,23261,23281,23282);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2165 WHERE `entry` IN (18731,20636);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2166 WHERE `entry` IN (22076);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2167 WHERE `entry` IN (17990,20189);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2168 WHERE `entry` IN (17796,20630);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2169 WHERE `entry` IN (8929,9025,9502,10076,14321,14323,14326);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2170 WHERE `entry` IN (12422);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2171 WHERE `entry` IN (10376,10596);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2172 WHERE `entry` IN (8983,9018,9019,9024,9027,9028,9029,9030,9031,9032,9033,9034,9035,9036,9037,9038,9039,9040,9041,9042,9056,9156,9196,9236,9237,9319,9537,9543,9568,9736,9938,10220,10268,10339,10363,10429,10430,10503,10509,10584,10812,11486,11487,11488,11489,11490,11492,11496,11501,12459,12461,12463,12464,14322,14324,14325,14327,14354,14502,14506,15229,15230,15233,15235,15236,15240,15246,15249,15250,15252,15262,15264,15277,15311,15312,16042,16080,16097);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2173 WHERE `entry` IN (11662,12460,12467);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2174 WHERE `entry` IN (17862,20521);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2175 WHERE `entry` IN (24238);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2176 WHERE `entry` IN (1840);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2177 WHERE `entry` IN (20901,20902,21610,21611);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2178 WHERE `entry` IN (21218,21221,21298,21299,21301,21339,21508);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2179 WHERE `entry` IN (20885,20886,21466,21467,21590,21599,21600,21624);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2180 WHERE `entry` IN (17826,17882,18105,20168,20183,20184);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2181 WHERE `entry` IN (33836,34218);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2182 WHERE `entry` IN (30245,30249,31750,31751);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2183 WHERE `entry` IN (33202,33398);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2184 WHERE `entry` IN (15516,32857,33694);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2185 WHERE `entry` IN (36272,36296,36565);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2186 WHERE `entry` IN (32916,33400);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2187 WHERE `entry` IN (12899);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2188 WHERE `entry` IN (16472);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2189 WHERE `entry` IN (929,1284,1748,2425,3974,3975,3976,3977,4542,4543,6487,7228,9095,10156,10162,10432,10433,10435,10436,10437,10438,10502,10504,10505,10506,10507,10508,10558,10808,10811,10813,10901,10942,10997,11032,11142,11261,11380,11439,11622,11946,11947,11948,11949,11978,11982,12129,12756,12804,13256,13419,14352,14507,14509,14510,14515,14517,14831,14834,14861,14988,15082,15083,15084,15085,15114,15192,15204,15205,15299,15302,15348,15362,15369,15370,15378,15379,15380,15381,15382,15410,15411,15412,15413,15427,15481,15491,15509,15510,15511,15514,15543,15544,15571,15608,15625,15628,15633,15667,15688,15776,15963,16077,16101,16102,16118,16128,16440,16524,16775,16776,16777,16778,16816,17008,17009,17010,17011,17012,17026,17076,17233,17354,17380,17381,17500,17521,17533,17534,17651,17772,17797,17798,17852,17874,17941,17942,17948,17949,17991,18040,18041,18060,18063,18075,18076,18141,18254,18338,18343,18344,18371,18373,18472,18601,18621,18624,18667,18728,18780,18932,19214,19556,19597,19604,19647,19893,19894,19895,20266,20268,20306,20318,20481,20629,20633,20637,20690,21003,21538,21768,21823,21845,21932,22409,22522,22605,22606,22627,22629,22641,22644,22996,23035,23054,23230,23426,23467,23499,23508);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2189 WHERE `entry` IN (23578,23759,23812,23863,23877,23878,23879,23880,23899,23912,23913,23914,23944,24143,24144,24239,24505,31055,31818,31819,31820,31821,31822,32918,32919,33399,33401,37243,37244,37283,37444);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2190 WHERE `entry` IN (15552);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2191 WHERE `entry` IN (11382,12017,15263,23576,23577);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2192 WHERE `entry` IN (37226);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2193 WHERE `entry` IN (2784,3057,3516,4949,4968,7937,7999,10181,10540,20888,21224,21227,22825,22826,22827,22828,22920);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2194 WHERE `entry` IN (16028,16800,16802,17468,19622,20906,21606,21964,22951,23419,23953,23954,23980,24200,24201,26529,26530,26532,26533,27389,27390,28684,29249,29268,29278,29305,29311,29315,29324,29373,29417,29446,29447,29448,29611,29615,29701,29718,29940,29955,29991,30057,30061,30452,30530,30549,30600,30601,30602,30603,30748,31125,31211,31212,31215,31217,31464,31507,31534,31612,31656,31657,31673,31674,31679,31680,31722,32273,32295,32313,32353,32368,32865,33147,33271,33350,33388,33449,33453,33515,33524,33846,33850,33851,33852,33985,33986,33988,33989,33993,33994,34015,34016,34057,34115,34152,34175,34496,34497,34780,35013,35143,35216,35268,35269,35347,35348,35349,35350,35351,35352,35359,35360,36064,36067,36476,36477,36494,36502,36612,36658,36723,36855,36938,37613,37627,37629,37677,37720,37813,37957,37958,37959,38106,38112,38113,38296,38297,38402,38433,38462,38482,38483,38582,38583,38599,38603);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2195 WHERE `entry` IN (15193);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2196 WHERE `entry` IN (20905,20910,20911,21588,21589,21618,21838);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2197 WHERE `entry` IN (24560,25560);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2198 WHERE `entry` IN (20896,21702);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2199 WHERE `entry` IN (11980,16807,16808,16809,17711,17734,18481,20039,20045,20046,20049,20187,20568,20596,20597,20864,20867,20868,20879,20880,21174,21303,21304,21591,21592,21593,21594,21595,21596,21608,21623,22330,22346,23397,24723,24744,25562,25573);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2200 WHERE `entry` IN (20036,20037,24664,24857);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2201 WHERE `entry` IN (25772);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2202 WHERE `entry` IN (4814);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2203 WHERE `entry` IN (329,2359,7031,7032,8324,14331);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2204 WHERE `entry` IN (16193);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2205 WHERE `entry` IN (11665,11672,12076,12099,12100,12101);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2206 WHERE `entry` IN (14401);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2207 WHERE `entry` IN (16336,16338);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2208 WHERE `entry` IN (15141);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2209 WHERE `entry` IN (11669);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2210 WHERE `entry` IN (11658,11659,11661,11671,11673,11988,12057,12098,12118,12259,12264,14081,14465,14466,14751,14752);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2211 WHERE `entry` IN (24722,25552);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2212 WHERE `entry` IN (14464);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2213 WHERE `entry` IN (10264);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2214 WHERE `entry` IN (15748,15751,15754,15758,15807,15810);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2215 WHERE `entry` IN (11664,15747,15753,15757,15812);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2216 WHERE `entry` IN (10516);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2217 WHERE `entry` IN (12465);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2218 WHERE `entry` IN (9499,12468,15247);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2219 WHERE `entry` IN (1842,5709,5710,5719,5720,5721,5722,7267,7271,7272,7275,7604,7795,7796,7797,8127,8443,11878,12018,15743,15744,15750,15806,15813,15814,15815,15816,15817,15818);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2220 WHERE `entry` IN (10184);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2221 WHERE `entry` IN (15286,15288,15290);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2222 WHERE `entry` IN (14662,14663,14664,14666);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2223 WHERE `entry` IN (14503);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2224 WHERE `entry` IN (22855);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2225 WHERE `entry` IN (17770,20169);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2226 WHERE `entry` IN (15689);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2227 WHERE `entry` IN (30084);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2228 WHERE `entry` IN (32187);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2229 WHERE `entry` IN (22056);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2230 WHERE `entry` IN (25588);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2231 WHERE `entry` IN (37698,39299,39300,39301);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2232 WHERE `entry` IN (22952,34815,35262);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2233 WHERE `entry` IN (21362);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2234 WHERE `entry` IN (33203,33376);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2235 WHERE `entry` IN (34147,34148);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2236 WHERE `entry` IN (17767,17808,17842,17888);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2237 WHERE `entry` IN (1853,12397,12435,15517,15589,15690,15727,17225,17535,17968,18341,18473,18708,18732,20267,20653,20657,20706,23574);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2238 WHERE `entry` IN (10340,10538,14020,15206,15207,15208,15220,15467,15740,15741,15742,18168,33052,33116);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2239 WHERE `entry` IN (25741);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2240 WHERE `entry` IN (15550,16152,18832,18834,18835,23682,23709,29306,29310,31368,31465,34796,35438);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2241 WHERE `entry` IN (27386,30178,30756,31448);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2242 WHERE `entry` IN (32877,33155);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2243 WHERE `entry` IN (10404,15687,15691,16151,16457,17096,17257,17281,17306,17308,17455,17536,17537,17848,17879,17880,17881,17975,17976,17977,17978,17980,18051,18055,18069,18096,18398,18399,18400,18401,18402,18432,18433,18434,18436,18805,18831,18945,19044,19218,19219,19220,19221,19516,19710,19781,19782,19783,20060,20062,20063,20064,20243,20531,20535,20737,20738,20745,21212,21213,21214,21215,21216,21217,21364,21369,21525,21526,21533,21536,21537,21551,21558,21559,21581,21582,21697,21698,21712,21875,21920,21958,21965,21966,22055,22119,22120,22140,22167,22841,22856,22871,22887,22898,22917,22947,22948,22949,22950,22997,23089,23191,23197,23375,23418,23420,23421,23469,23965,24850,24882,24891,24892,25038,25165,25166,25315,25502,25708,25840,26630,26631,26632,26668,26683,26684,26685,26686,26687,26693,26723,26731,26763,26794,26796,26798,26861,26893,26918,27447,27483,27654,27655,27656,27975,27977,27978,28132,28171,28546,28586,28587,28729,28730,28731,28859,28860,28921,28922,28923,29120,29266,29281,29304,29307,29308,29309,29312,29313,29314,29316,29573,29932,30114,30176,30397,30398,30449,30451,30510,30522,30529,30532,30540,30770,30772,30774,30775,30788,30790,30803,30807,30809,30810,31134,31311,31349,31350,31360,31362);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2243 WHERE `entry` IN (31365,31367,31370,31381,31384,31386,31441,31456,31469,31473,31506,31508,31509,31510,31511,31512,31520,31533,31535,31536,31537,31538,31558,31559,31560,31561,31592,31610,31611,31615,31616,31617,31672,31734,32845,32846,32867,32871,32872,32873,32874,32875,32876,32878,32882,32883,32885,32886,32904,32906,32907,32908,32913,32914,32915,32927,32930,32933,32934,32955,33070,33089,33113,33118,33121,33148,33149,33150,33151,33152,33153,33154,33156,33157,33158,33159,33161,33162,33163,33186,33190,33191,33228,33288,33293,33329,33344,33360,33385,33391,33392,33393,33432,33433,33567,33651,33670,33692,33693,33699,33700,33715,33716,33717,33718,33719,33720,33722,33723,33724,33756,33772,33773,33885,33888,33890,33909,33910,33911,33943,33954,33955,33959,33966,33967,33983,33984,33990,33995,34003,34004,34014,34035,34069,34071,34097,34106,34108,34109,34133,34134,34139,34141,34164,34165,34166,34171,34185,34197,34215,34221,34222,34226,34564,34566,34660,34797,34799,34800,34813,34825,34826,34928,34942,35028,35029,35030,35031,35032,35033,35034,35036,35037,35038,35039,35040,35041,35042,35043,35044,35045,35046,35047,35048,35049,35050,35051,35052,35119,35144,35263,35264,35265,35266,35267,35270,35271,35272,35278,35279);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2243 WHERE `entry` IN (35280,35311,35439,35440,35441,35442,35443,35447,35448,35449,35451,35490,35511,35512,35513,35514,35515,35516,35517,35518,35519,35520,35521,35522,35523,35524,35525,35527,35528,35529,35530,35531,35532,35533,35534,35535,35536,35537,35538,35539,35540,35541,35542,35543,35544,35615,35616,36135,36497,36498,36538,36597,36626,36627,36633,36678,36701,36789,36838,36839,36853,36897,36899,36939,36948,36950,36954,36957,36960,36961,36968,36969,36970,36971,36978,36982,37025,37098,37116,37117,37126,37182,37184,37215,37217,37227,37230,37488,37504,37505,37506,37531,37533,37534,37540,37562,37697,37833,37955,37970,37972,37973,38064,38103,38110,38123,38128,38129,38138,38139,38156,38157,38174,38219,38220,38256,38257,38258,38261,38262,38265,38266,38267,38369,38390,38399,38400,38401,38403,38404,38405,38406,38407,38408,38418,38431,38434,38435,38436,38444,38454,38490,38494,38549,38550,38585,38586,38602,38604,38637,38638,38639,38640,38675,38676,38677,38678,38679,38680,38681,38682,38683,38684,38685,38686,38687,38688,38689,38690,38691,38692,38693,38694,38699,38700,38701,38702,38758,38759,38760,38761,38769,38770,38771,38772,38775,38776,38777,38784,38785,39166,39167,39168,39190,39287,39288,39289,39302,39303,39304);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2243 WHERE `entry` IN (39305,39306,39307,39746,39747,39751,39805,39814,39815,39823,39863,39864,39899,39920,39922,39944,39945,40142,40143,40144,40145);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2244 WHERE `entry` IN (14862);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2245 WHERE `entry` IN (32926,32938,33352,33353,36980,38320,38321,38322);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2246 WHERE `entry` IN (15261);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2247 WHERE `entry` IN (20041,23394);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2248 WHERE `entry` IN (18503,20309);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2249 WHERE `entry` IN (36619,38233,38459,38460,38711,38712,38970,38971,38972,38973,38974,38975);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2250 WHERE `entry` IN (38028);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2251 WHERE `entry` IN (20870,20912,21601,21626);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2252 WHERE `entry` IN (17839,20744,21104,21140,21148,22170,22171,22172);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2253 WHERE `entry` IN (22128,22129);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2254 WHERE `entry` IN (23597);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2255 WHERE `entry` IN (24374);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2256 WHERE `entry` IN (2675,4277,8937);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2257 WHERE `entry` IN (16127);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2258 WHERE `entry` IN (16124);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2259 WHERE `entry` IN (16149);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2260 WHERE `entry` IN (16156,16157,16158);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2261 WHERE `entry` IN (11657,11677,12096,12097,13078,13079,13086,13088,13137,13138,13139,13143,13144,13145,13147,13152,13153,13154,13176,13179,13180,13181,13216,13218,13236,13257,13296,13297,13298,13299,13300,13318,13319,13320,13356,13357,13437,13438,13439,13441,13442,13447,13577,13597,13598,13616,13617,13797,13798);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2262 WHERE `entry` IN (16244,16360,16427,16983);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2263 WHERE `entry` IN (16150);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2264 WHERE `entry` IN (16022,16981);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2265 WHERE `entry` IN (16027,16164,16449);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2266 WHERE `entry` IN (16167);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2267 WHERE `entry` IN (16020);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2268 WHERE `entry` IN (16024);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2269 WHERE `entry` IN (16375);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2270 WHERE `entry` IN (16290);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2271 WHERE `entry` IN (16447);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2272 WHERE `entry` IN (16982,16984);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2273 WHERE `entry` IN (16036,16056,16057,16236,16297,16698,17055);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2274 WHERE `entry` IN (16037);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2275 WHERE `entry` IN (15318,15319,15320,15323,15324,15325,15336);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2276 WHERE `entry` IN (16034);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2277 WHERE `entry` IN (16428,16429);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2278 WHERE `entry` IN (16021,16165,16368,16448,16452);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2279 WHERE `entry` IN (16194,16215,16216);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2280 WHERE `entry` IN (16017,16018,16029);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2281 WHERE `entry` IN (11352,12159,14750,14762,14763,14764,14765,14766,14767,14768,14769,14770,14771,14772,14773,14774,14775,14776,14777,14943,14944,14945,14946,14947,14948,15327,15335,15338,15339,15340,15341,15343,15355,15385,15386,15388,15389,15390,15391,15392,15555,16062);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2282 WHERE `entry` IN (15928,15929,15930,15931,15932,15936,15952,15953,15954,15956,15989,15990,16011,16060,16061,16063,16064,16065);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2283 WHERE `entry` IN (16441);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2284 WHERE `entry` IN (16126);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2285 WHERE `entry` IN (15974,15975,16505,29274);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2286 WHERE `entry` IN (15980,15981,16506);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2287 WHERE `entry` IN (16573);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2288 WHERE `entry` IN (15976,15978,15979,16142,16453);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2289 WHERE `entry` IN (16243);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2290 WHERE `entry` IN (16387);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2291 WHERE `entry` IN (10440);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2292 WHERE `entry` IN (12119,15620,16168,16446);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2293 WHERE `entry` IN (13116,13117,14302,15047,15224,15922);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2294 WHERE `entry` IN (22250);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2295 WHERE `entry` IN (24175);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2296 WHERE `entry` IN (12900);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2297 WHERE `entry` IN (32357,32358,32471,32495,32501);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2298 WHERE `entry` IN (32386,32398,32400,32438);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2299 WHERE `entry` IN (11284);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2300 WHERE `entry` IN (15276);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2301 WHERE `entry` IN (2091,2108,2726,4339,4676,6073,7135,7136,7137,8608,8616,14668,15209,15438,17267,19203,19973,20703,21706,22323,25001,25417,28584,30416,30847,30983,31453);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2302 WHERE `entry` IN (12143);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2303 WHERE `entry` IN (2760,3417,4036,4037,4038,5893,5896,6521,7266,7738,9178,9878,9879);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2304 WHERE `entry` IN (2745,8281,8909,8910,8911,9026,9376);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2305 WHERE `entry` IN (14460);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2306 WHERE `entry` IN (2447);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2307 WHERE `entry` IN (9016,9017,9816);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2308 WHERE `entry` IN (11981,11983,14601);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2309 WHERE `entry` IN (7846,8680,15203);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2310 WHERE `entry` IN (575,5850,5852,6520,17003);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2311 WHERE `entry` IN (11502,11667,11668,12056,12265);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2312 WHERE `entry` IN (14461);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2313 WHERE `entry` IN (19551);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2314 WHERE `entry` IN (11583,13020);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2315 WHERE `entry` IN (19514);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2316 WHERE `entry` IN (11666);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2317 WHERE `entry` IN (832,2258,2592,2736,2752,2762,4034,4035,4499,4526,5898,5902,6239,8667,9377,9397,11576,11577,11578,11744,11745,11777,11778,11779,11783,11784,14399,14400,14478,15352,16043,17085,17154,17156,17157,17158,17159,17160,18062,18181,21707,22036,23029,26407,28411,28547,28585,28825,30418,30965,30970,30979,31452);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2318 WHERE `entry` IN (14455);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2319 WHERE `entry` IN (5855);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2320 WHERE `entry` IN (12237);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2321 WHERE `entry` IN (14435);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2322 WHERE `entry` IN (92);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2323 WHERE `entry` IN (2735,2791);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2324 WHERE `entry` IN (11321);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2325 WHERE `entry` IN (30258,31463);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2326 WHERE `entry` IN (14454);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2327 WHERE `entry` IN (12201);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2328 WHERE `entry` IN (14887,14888,14889,14890);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2329 WHERE `entry` IN (2761,2776,2794,3851,3861,3950,4978,5462,5894,5895,5897,6047,6220,6748,7132,7428,7429,8519,8520,8521,8522,8837,9453,10198,10642,11256,11862,12759,13278,13279,13322,13456,13696,13736,14269,14350,15211,16570,17153,17155,17167,17207,17358,19204,20704,21428,21728,22035,22309,24228,24601,25226,25514,25715,25755,25756,25757,26116,26178,26204,26214,26215,26216,26316,26340,26341,26342,30419,30846,31454,37994);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2330 WHERE `entry` IN (14458);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2331 WHERE `entry` IN (13282);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2332 WHERE `entry` IN (12876);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2333 WHERE `entry` IN (3917);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2334 WHERE `entry` IN (7079);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2335 WHERE `entry` IN (13280);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2336 WHERE `entry` IN (15305);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2337 WHERE `entry` IN (510,691,5461,10756,10757,10955);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2338 WHERE `entry` IN (14457);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2339 WHERE `entry` IN (22009);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2340 WHERE `entry` IN (25740,25865,26338,26339);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2341 WHERE `entry` IN (703,1043,1364,19206,20705);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2342 WHERE `entry` IN (6492,6550,11480,11483,11484,14397,15527,16530,16854,18864,18865,18866,18867,19205,20516,20702,22310,26370,30848);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2343 WHERE `entry` IN (10202);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2344 WHERE `entry` IN (10662);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2345 WHERE `entry` IN (10663);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2346 WHERE `entry` IN (10664);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2347 WHERE `entry` IN (6109);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2348 WHERE `entry` IN (21032);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2349 WHERE `entry` IN (7734,7735);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2350 WHERE `entry` IN (10485);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2351 WHERE `entry` IN (15275);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2352 WHERE `entry` IN (16491);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2353 WHERE `entry` IN (12457);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2354 WHERE `entry` IN (28912);
UPDATE `creature_template` SET `CreatureImmunitiesId`=2355 WHERE `entry` IN (8317);
File diff suppressed because one or more lines are too long
+336
View File
@@ -0,0 +1,336 @@
-- DB update 2026_03_25_03 -> 2026_03_25_04
-- Enable smooth waypoint transitions for flying creatures
-- Paths with actions or delays are excluded
-- Buzzard (2830)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (71370, 72510, 72520, 72530, 76140);
-- Antilus the Soarer (5347)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (518400);
-- Soaring Razorbeak (8276)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (928800, 928810);
-- Bloodseeker Bat (11368)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (491230, 491460, 491580, 521360, 522670, 915550);
-- Bat Rider Guard (15242)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (548400, 548410, 548420, 548430);
-- OLDWorld Trigger (DO NOT DELETE) (15384)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (876470);
-- Eye of Thrallmar (16598)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (575850, 575860, 575870, 575880);
-- Eye of Honor Hold (16887)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (584380);
-- Skeletal Gryphon (17660)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (125540, 125550);
-- Large AOI Underbat (18409)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1383120, 1383140, 1383160, 1383210, 1383270, 1383410, 1383480, 1383520);
-- Night Elf Wisp (18502)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1396910, 1396920, 1396930, 1396940, 1396950, 1396960, 1396970, 1396990);
-- Torgos (18707)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (2469160);
-- Flying Raging Soul (18726)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1324010, 1324030, 1324100, 1324150, 1324320);
-- Wildhammer Gryphon Rider (19382)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (11580, 1259220, 1259270, 1259300, 1259310, 1259320, 1260520);
-- Al'ar (19514)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1580410);
-- Nuramoc (20932)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (249410, 249420, 249430);
-- Bladewing Bloodletter (21033)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (738490, 738500, 738520, 738530, 738580, 738600);
-- Kor'kron Wyvern Rider (21153)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (742190);
-- Mature Netherwing Drake (21648)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (755410, 755420, 755430, 755440, 755450, 755460, 755470, 755480, 755490, 755500, 755510, 755520, 755530, 755540, 755550, 755560, 755570, 755580, 861030);
-- Vhel'kur (21801)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (218010);
-- Vilewing Chimaera (21879)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (844880, 845940, 845970, 846130, 846320);
-- Avian Flyer (21931)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1387630, 1387660, 1387690);
-- [PH] Cave Bat JZB (22040)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (771910, 771920, 771930, 771940, 771950, 771960);
-- Dragonmaw Skybreaker (22274)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (782910, 782920, 782930, 782940, 782950, 782960, 782970, 782980, 782990, 783000);
-- Corvax (22842)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (697120);
-- Rook (22843)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (697110);
-- Dragonmaw Sky Stalker (23030)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1481220, 1481230, 1481270, 1481280, 1481290, 1481380, 1481390);
-- Invisible Stalker (Floating) (23033)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1312500, 1312520, 1338940, 1338990, 1339000);
-- Monstrous Kaliri (23051)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (790170, 832370, 832380, 860990, 861150, 861160, 861170, 861310, 861330, 1325530, 1325540, 1325550, 1325560, 1325570, 1325580, 1325600, 1325620, 1325640, 1325650, 1325660, 1325670);
-- Dragonmaw Transporter (23188)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1328140, 1328180);
-- Lady Sinestra (23283)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (287960);
-- Dragonflayer Raider (23557)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (971330, 971340, 971350, 971390, 971400);
-- Plagued Proto-Dragon (23680)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1076260);
-- Proto-Drake (23689)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1081500, 1081510, 1081520, 1081550, 1081560, 1081580);
-- Spotted Hippogryph (23772)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (938020, 938030, 938040, 938050, 938060, 938070, 938080, 938090, 938100, 938110, 938120, 938130, 938140, 938150, 938160, 938170, 938180, 938190, 938200, 938210, 938220, 938230, 938240, 938250, 938260, 938270, 938280, 938290, 938300, 938310, 938320, 938330, 938340, 938350, 938360, 938370, 938380, 938390, 938400, 938410, 938420, 938430, 938440);
-- Val'kyr Watcher (23935)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (482340, 482350, 482360, 482370, 482380, 482390, 482400, 482410, 482420, 482430, 482440);
-- Windy Cloud (24222)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1410000, 1410010, 1410020, 1410030, 1410040, 1410060, 1410070, 1410080);
-- Steelfeather (24514)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1142380);
-- Talonshrike (24518)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1147130);
-- Buoy (24707)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1078110);
-- Fjord Hawk (24747)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (938510, 938530, 938560, 938590, 938600, 938640, 938660, 938680, 938730, 938750, 938790, 938810, 938880, 938900);
-- Nexus Watcher (24770)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1241160, 1241170, 1241180, 1241190, 1241200, 1241210, 1241220, 1241230, 1241240, 1241250, 1241260);
-- Fjord Hawk Matriarch (24787)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1158350, 1158370, 1158430, 1158440, 1158450);
-- Proto-Drake Rider (24849)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1259340, 1259360, 1259370, 1259400);
-- Dawnblade Hawkrider (25063)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (839990, 840020, 840030, 840040, 840050, 840060);
-- Shattered Sun Bombardier (25144)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (853700, 853720, 853730, 853740);
-- Bloodspore Moth (25464)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1327080);
-- Spirit of the North (25711)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1210760, 1225710);
-- Fizzcrank Bomber (25765)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1113600);
-- D.E.H.T.A. Enforcer (25819)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1329840);
-- Shaman Beam Bunny 000 (25964)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (125390);
-- Shaman Beam Bunny 001 (25965)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (125400);
-- Shaman Beam Bunny 002 (25966)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (125410);
-- Nexus Drake Hatchling (26127)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1210410, 1210420, 1210430, 1210440, 1210450, 1210460, 1210470);
-- Carrion Condor (26174)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1018170, 1018400, 1018550, 1018860, 1018870, 1019250, 1019290);
-- Nexus Guardian (26276)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1113040, 1113590);
-- Emberwyrm (26286)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1123860, 1123870);
-- Dreadtalon (26838)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1161740);
-- Reanimated Frost Wyrm (26841)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (404970, 404980, 404990, 405000, 405010, 405020, 405030, 405040, 405050);
-- Sarathstra (26858)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1124010);
-- Wyrmrest Temple Drake (26925)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1001700, 1002060, 1002070, 1002080, 1002090, 1002100, 1002130, 1002150, 1002160, 1002260, 1309990);
-- Wyrmrest Guardian (26933)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1008230, 1008240, 1008250, 1008260, 1310350, 1310360, 1310370, 1310380);
-- Forgotten Captain (27220)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1033880, 1033910, 1033940, 1033960, 1033980, 1034000, 1034030, 1034110);
-- Risen Gryphon (27241)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1311770, 1311780);
-- Emerald Skytalon (27244)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1057430, 1057510, 1057710, 1057730, 1057760, 1057900, 1057920, 1057930);
-- Reconstructed Frost Wyrm (27285)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1099150, 1099160, 1099270);
-- Cosmetic Drakkari Bat [PH] (27490)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1275080, 1275090, 1275100, 1275110, 1275120, 1275130);
-- Azure Dragon (27608)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (991050, 991060, 991070, 991080, 991090, 991100, 991110, 991120, 991130, 991140, 991150, 991160, 991170, 991180);
-- Azure Drake (27682)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (990780, 990790, 990830, 990840, 990850, 990860, 990870, 990880, 990890, 990920, 990930, 990940, 990950, 990960, 990970, 990980, 990990, 991030, 991040);
-- Heb'Drakkar Striker (28465)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1005360, 1005400);
-- Scarlet Gryphon (28614)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1293080, 1293090);
-- Olrun the Battlecaller (29047)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1287390);
-- Gundrak Bat Rider (29332)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1097750, 1097780, 1097820, 1097840, 1097860, 1097870, 1097930, 1097950, 1098560);
-- Onslaught Gryphon Rider (29333)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1231100, 1231120, 1231290, 1231300, 1231320, 1231330, 1231420, 1231430, 1231460, 1231470, 1231560, 1231570);
-- Vargul Plaguetalon (29453)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (976340);
-- Frigid Proto-Drake (29460)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (979910, 979920, 979950, 980250, 980260, 980270, 980280);
-- Nascent Val'kyr (29570)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1077080, 1077240, 1077780, 1077820, 1077870, 1077890, 1077910, 1077930, 1077950, 1077960, 1077970, 1077980, 1077990);
-- Hyldsmeet Proto-Drake (29625)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1134270, 1134280, 1134290, 1134300, 1134460, 1134470, 1134480, 1134490, 1134500, 1134510, 1134520, 1134570, 1134580, 1134590, 1134610, 1134620, 1134630, 1134640, 1134650, 1134660, 1134670);
-- Stormpeak Wyrm (29753)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1010000, 1011070, 1011080, 1011090, 1011100, 1011110, 1011120, 1011130, 1011140, 1011150, 1011170, 1011180, 1011190, 1011200, 1011210, 1011220);
-- Sirana Iceshriek (29794)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (2025870);
-- Stormcrest Eagle (30013)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1017130, 1017140, 1017150, 1018010);
-- Wild Wyrm (30275)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (2029720, 2029730, 2029740, 2029750, 2029760, 2029770);
-- Jotunheim Proto-Drake (30330)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1227590, 1227600, 1227610, 1227620, 1227630, 1227640, 1227650, 1227660, 1227670, 1227680, 1227690, 1227700, 1227710, 1227720, 1227730, 1227740, 1227750, 1227760, 1241110, 1241120);
-- Wrathstrike Gargoyle (30482)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1348070, 1348080, 1348090, 1348100, 1348110, 1348120, 1348130, 1348140);
-- Scourgebeak Fleshripper (30988)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1210070, 1210110, 1210140, 1210170, 1210190, 1210230, 1210250);
-- Wrathstrike Gargoyle (31040)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1217480, 1217490, 1217500, 1217510, 1217520, 1217530, 1217540, 1217550);
-- Frostbrood Skytalon (31137)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1234960, 1234970, 1234980, 1234990, 1235020, 1235030, 1235040, 1235070, 1235090);
-- Kor'kron Battle Wyvern (31269)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (992270, 992280, 992300);
-- Crystal Wyrm (31393)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1111560, 1111620);
-- Frostbrood Spawn (31702)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1244190, 1244200, 1244210, 1244220, 1244230, 1244240, 1244250);
-- Stabled Hunter Pet (31768)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (2087870);
-- Stabled Hunter Pet (31769)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (2087880);
-- Tempus Wyrm (32180)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1129570);
-- Infinite Eradicator (32185)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1134360, 1134380);
-- Skybreaker Recon Fighter (32189)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1240870, 1240880, 1240890, 1240900);
-- Orgrim's Hammer Scout (32201)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1241600, 1241870, 1241880, 1241890, 1241900, 1241910, 1241920, 1241930, 1241940, 1241950, 1241960, 1242070, 1242080, 1242090, 1242120, 1242130, 1242140, 1242150, 1242160, 1242180, 1242190, 1242200, 1242210, 1242220);
-- Northrend Daily Dungeon Image Bunny (32265)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (973340);
-- Fumblub Gearwind (32358)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1519380);
-- Ebon Blade Gargoyle (32472)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1244280, 1244290);
-- Time-Lost Proto Drake (32491)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (392030, 392040, 392050, 392060);
-- Frostbrood Matriarch (32492)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1181850, 1181860, 1181880, 1181890, 1181900);
-- Vyragosa (32630)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (392030, 392040, 392050, 392060);
-- Frostbrood Sentry (32767)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1251080, 1251090, 1251100, 1251550, 1251620);
-- Mechanolift 304-A (33214)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (13681700, 13681801, 13681802, 13681803, 13681804, 13681805, 13681806, 13681807, 13681808, 13681809, 13681810, 13681811, 13681812, 13681813, 13681814, 13681815, 13681816, 13681817, 13681818, 13682000, 13682101, 13682102, 13682103, 13682104, 13682105, 13682106, 13682107, 13682108, 13682109, 13682110, 13682300, 13682700, 13683000, 13683100, 13685300, 13686200, 13686800, 13687000, 13688500);
-- Guardian of Life (33528)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1375280, 1375290, 1375300, 1375310);
-- Chillmaw (33687)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (2008510);
-- Tournament Hippogryph (33778)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (1231520);
-- Stonespine Gargoyle (36896)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (2018220, 2018240, 2018340, 2018380, 2018460);
-- Val'kyr Herald (37098)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (2012450, 2013220);
-- Spire Frostwyrm (Ambient) (37528)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (2008870, 2009600, 2009750);
-- Argent Hippogryph (37968)
UPDATE `waypoint_data` SET `smoothTransition` = 1 WHERE `id` IN (887940, 887960, 887980, 887990);
@@ -0,0 +1,3 @@
-- DB update 2026_03_25_04 -> 2026_03_25_05
-- Also add spark visual aura from Power Spark to Power Spark (1)
UPDATE `creature_template_addon` SET `auras` = '55845' WHERE (`entry` = 32187);
@@ -0,0 +1,3 @@
-- DB update 2026_03_25_05 -> 2026_03_25_06
-- Remove smoothTransition for Guardian of Life (33528)
UPDATE `waypoint_data` SET `smoothTransition` = 0 WHERE `id` IN (1375280, 1375290, 1375300, 1375310);
@@ -0,0 +1,20 @@
-- DB update 2026_03_25_06 -> 2026_03_26_00
-- Add mail commands
DELETE FROM `command` WHERE `name` IN ('mail', 'mail list', 'mail return');
INSERT INTO `command` (`name`, `security`, `help`) VALUES
('mail', 2, 'Syntax: .mail $subcommand\nType .mail to see a list of subcommands or .help mail $subcommand to see info on subcommands.'),
('mail list', 2, 'Syntax: .mail list [$player]\nDisplays all mail data (except subject and body) for the target player.'),
('mail return', 2, 'Syntax: .mail return $player $mailId\nReturns the specified mail to its original sender.');
-- Add acore_string entries for mail commands
DELETE FROM `acore_string` WHERE `entry` IN (5135, 5136, 5137, 5138, 5139, 5140, 5141, 5142, 5143);
INSERT INTO `acore_string` (`entry`, `content_default`, `locale_koKR`, `locale_frFR`, `locale_deDE`, `locale_zhCN`, `locale_zhTW`, `locale_esES`, `locale_esMX`, `locale_ruRU`) VALUES
(5135, 'Mail list for player {}:', '플레이어 {}의 우편 목록:', 'Liste des courriers du joueur {} :', 'Postliste für Spieler {}:', '玩家 {} 的邮件列表:', '玩家 {} 的郵件列表:', 'Lista de correo del jugador {}:', 'Lista de correo del jugador {}:', 'Список писем игрока {}:'),
(5136, ' ID: {} | Type: {} | Stationery: {} | Template: {} | Sender: {} ({}) | Receiver: {} | Expires: {} | Delivered: {} | Money: {} | COD: {} | Flags: {} | Items: {}', ' ID: {} | 유형: {} | 편지지: {} | 템플릿: {} | 발신자: {} ({}) | 수신자: {} | 만료: {} | 배달: {} | 금액: {} | 대금상환: {} | 플래그: {} | 아이템: {}', ' ID : {} | Type : {} | Papeterie : {} | Modèle : {} | Expéditeur : {} ({}) | Destinataire : {} | Expiration : {} | Livré : {} | Argent : {} | Remboursement : {} | Drapeaux : {} | Objets : {}', ' ID: {} | Typ: {} | Briefpapier: {} | Vorlage: {} | Absender: {} ({}) | Empfänger: {} | Ablauf: {} | Zugestellt: {} | Gold: {} | Nachnahme: {} | Flags: {} | Gegenstände: {}', ' ID:{} | 类型:{} | 信纸:{} | 模板:{} | 发件人:{} ({}) | 收件人:{} | 过期:{} | 投递:{} | 金币:{} | 货到付款:{} | 标记:{} | 物品:{}', ' ID:{} | 類型:{} | 信紙:{} | 範本:{} | 寄件人:{} ({}) | 收件人:{} | 到期:{} | 投遞:{} | 金幣:{} | 貨到付款:{} | 標記:{} | 物品:{}', ' ID: {} | Tipo: {} | Papelería: {} | Plantilla: {} | Remitente: {} ({}) | Destinatario: {} | Expira: {} | Entregado: {} | Dinero: {} | Contrareembolso: {} | Marcas: {} | Objetos: {}', ' ID: {} | Tipo: {} | Papelería: {} | Plantilla: {} | Remitente: {} ({}) | Destinatario: {} | Expira: {} | Entregado: {} | Dinero: {} | Contrareembolso: {} | Marcas: {} | Objetos: {}', ' ID: {} | Тип: {} | Бланк: {} | Шаблон: {} | Отправитель: {} ({}) | Получатель: {} | Истекает: {} | Доставлено: {} | Деньги: {} | Наложенный платёж: {} | Флаги: {} | Предметы: {}'),
(5137, 'No mail found for player {}.', '플레이어 {}의 우편이 없습니다.', 'Aucun courrier trouvé pour le joueur {}.', 'Keine Post für Spieler {} gefunden.', '未找到玩家 {} 的邮件。', '未找到玩家 {} 的郵件。', 'No se encontró correo para el jugador {}.', 'No se encontró correo para el jugador {}.', 'Письма для игрока {} не найдены.'),
(5138, 'Mail #{} returned to sender for player {}.', '우편 #{}이(가) 플레이어 {}의 발신자에게 반송되었습니다.', 'Courrier #{} renvoyé à l''expéditeur pour le joueur {}.', 'Post #{} wurde an den Absender für Spieler {} zurückgesendet.', '邮件 #{} 已退回给玩家 {} 的发件人。', '郵件 #{} 已退回給玩家 {} 的寄件人。', 'Correo #{} devuelto al remitente del jugador {}.', 'Correo #{} devuelto al remitente del jugador {}.', 'Письмо #{} возвращено отправителю для игрока {}.'),
(5139, 'Mail #{} not found.', '우편 #{}을(를) 찾을 수 없습니다.', 'Courrier #{} introuvable.', 'Post #{} nicht gefunden.', '未找到邮件 #{}。', '未找到郵件 #{}。', 'Correo #{} no encontrado.', 'Correo #{} no encontrado.', 'Письмо #{} не найдено.'),
(5140, 'Only normal mail can be returned.', '일반 우편만 반송할 수 있습니다.', 'Seul le courrier normal peut être renvoyé.', 'Nur normale Post kann zurückgesendet werden.', '只能退回普通邮件。', '只能退回普通郵件。', 'Solo se puede devolver correo normal.', 'Solo se puede devolver correo normal.', 'Можно вернуть только обычные письма.'),
(5141, 'Mail has no valid sender to return to.', '반송할 유효한 발신자가 없습니다.', 'Le courrier n''a pas d''expéditeur valide.', 'Die Post hat keinen gültigen Absender.', '邮件没有有效的发件人可退回。', '郵件沒有有效的寄件人可退回。', 'El correo no tiene un remitente válido.', 'El correo no tiene un remitente válido.', 'У письма нет действительного отправителя для возврата.'),
(5142, 'Mail has already been returned.', '이미 반송된 우편입니다.', 'Ce courrier a déjà été renvoyé.', 'Diese Post wurde bereits zurückgesendet.', '邮件已被退回。', '郵件已被退回。', 'El correo ya ha sido devuelto.', 'El correo ya ha sido devuelto.', 'Письмо уже было возвращено.'),
(5143, 'A script hook prevented this mail from being returned.', '스크립트 후크가 이 우편의 반송을 차단했습니다.', 'Un hook de script a empêché le renvoi de ce courrier.', 'Ein Script-Hook hat die Rücksendung dieser Post verhindert.', '脚本钩子阻止了此邮件的退回。', '腳本鉤子阻止了此郵件的退回。', 'Un hook de script impidió la devolución de este correo.', 'Un hook de script impidió la devolución de este correo.', 'Хук скрипта предотвратил возврат этого письма.');
@@ -0,0 +1,4 @@
-- DB update 2026_03_26_00 -> 2026_03_26_01
-- Set Extra Flag Ignore Pathfinding
UPDATE `creature_template` SET `flags_extra` = `flags_extra` |536871042 WHERE (`entry` = 30616);
@@ -0,0 +1,4 @@
-- DB update 2026_03_26_01 -> 2026_03_27_00
-- Move Flexweave Underlay script from enchant application spell (55002) to parachute use-spell (55001)
DELETE FROM `spell_script_names` WHERE `spell_id` IN (55001, 55002) AND `ScriptName` = 'spell_item_flexweave_underlay';
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES (55001, 'spell_item_flexweave_underlay');
@@ -0,0 +1,43 @@
-- DB update 2026_03_27_00 -> 2026_03_27_01
-- Doomrel (9039): Create "Continue..." menu and chain from initial gossip
DELETE FROM `gossip_menu` WHERE `MenuID` = 1950;
INSERT INTO `gossip_menu` (`MenuID`, `TextID`) VALUES (1950, 2605);
DELETE FROM `gossip_menu_option` WHERE `MenuID` = 1950;
INSERT INTO `gossip_menu_option` (`MenuID`, `OptionID`, `OptionIcon`, `OptionText`, `OptionBroadcastTextID`, `OptionType`, `OptionNpcFlag`, `ActionMenuID`, `ActionPoiID`, `BoxCoded`, `BoxMoney`, `BoxText`, `BoxBroadcastTextID`, `VerifiedBuild`) VALUES
(1950, 0, 0, 'Continue...', 5256, 1, 1, 0, 0, 0, 0, '', 0, 0);
UPDATE `gossip_menu_option` SET `ActionMenuID` = 1950 WHERE `MenuID` = 1947 AND `OptionID` = 0;
-- Gloomrel (9037): Create "Continue..." menus for smelt and chalice paths
DELETE FROM `gossip_menu` WHERE `MenuID` IN (1952, 1953);
INSERT INTO `gossip_menu` (`MenuID`, `TextID`) VALUES
(1952, 2606),
(1953, 2604);
DELETE FROM `gossip_menu_option` WHERE `MenuID` IN (1952, 1953);
INSERT INTO `gossip_menu_option` (`MenuID`, `OptionID`, `OptionIcon`, `OptionText`, `OptionBroadcastTextID`, `OptionType`, `OptionNpcFlag`, `ActionMenuID`, `ActionPoiID`, `BoxCoded`, `BoxMoney`, `BoxText`, `BoxBroadcastTextID`, `VerifiedBuild`) VALUES
(1952, 0, 0, 'Continue...', 5256, 1, 1, 0, 0, 0, 0, '', 0, 0),
(1953, 0, 0, 'Continue...', 5256, 1, 1, 0, 0, 0, 0, '', 0, 0);
UPDATE `gossip_menu_option` SET `ActionMenuID` = 1952 WHERE `MenuID` = 1945 AND `OptionID` = 0;
UPDATE `gossip_menu_option` SET `ActionMenuID` = 1953 WHERE `MenuID` = 1945 AND `OptionID` = 1;
-- Gloomrel: Conditional gossip text when quest completed
DELETE FROM `gossip_menu` WHERE `MenuID` = 1945 AND `TextID` = 2605;
INSERT INTO `gossip_menu` (`MenuID`, `TextID`) VALUES (1945, 2605);
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 14 AND `SourceGroup` = 1945 AND `SourceEntry` = 2605;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(14, 1945, 2605, 0, 0, 8, 0, 4083, 0, 0, 0, 0, 0, '', 'Gloomrel - text requires quest 4083 rewarded'),
(14, 1945, 2605, 0, 0, 7, 0, 186, 230, 0, 0, 0, 0, '', 'Gloomrel - text requires Mining >= 230'),
(14, 1945, 2605, 0, 0, 16, 0, 14891, 0, 0, 1, 0, 0, '', 'Gloomrel - text requires NOT having Smelt Dark Iron');
-- Gloomrel: Conditions for gossip options
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 15 AND `SourceGroup` = 1945 AND `SourceEntry` IN (0, 1);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(15, 1945, 0, 0, 0, 8, 0, 4083, 0, 0, 0, 0, 0, '', 'Gloomrel - option 0 requires quest 4083 rewarded'),
(15, 1945, 0, 0, 0, 7, 0, 186, 230, 0, 0, 0, 0, '', 'Gloomrel - option 0 requires Mining >= 230'),
(15, 1945, 0, 0, 0, 16, 0, 14891, 0, 0, 1, 0, 0, '', 'Gloomrel - option 0 requires NOT having Smelt Dark Iron'),
(15, 1945, 1, 0, 0, 8, 0, 4083, 0, 0, 1, 0, 0, '', 'Gloomrel - option 1 requires quest 4083 NOT rewarded'),
(15, 1945, 1, 0, 0, 7, 0, 186, 230, 0, 0, 0, 0, '', 'Gloomrel - option 1 requires Mining >= 230');
@@ -0,0 +1,8 @@
-- DB update 2026_03_27_01 -> 2026_03_27_02
-- Change row 3 event from ON_WAYPOINT_REACHED to ON_WAYPOINT_ENDED.
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = -129210);
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
(-129210, 0, 2, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 232, 12921000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Havenshire Stallion - On Respawn - Start Path 12921000'),
(-129210, 0, 3, 4, 109, 0, 100, 0, 0, 12921000, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Havenshire Stallion - On Path 12921000 Finished - Stop Movement'),
(-129210, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 80, 2860500, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Havenshire Stallion - On Path 12921000 Finished - Run Script');
@@ -0,0 +1,9 @@
-- DB update 2026_03_27_02 -> 2026_03_27_03
--
DELETE FROM `creature_equip_template` WHERE (`CreatureID` = 28912);
INSERT INTO `creature_equip_template` (`CreatureID`, `ID`, `ItemID1`, `ItemID2`, `ItemID3`, `VerifiedBuild`) VALUES
(28912, 1, 38633, 0, 0, 42010);
UPDATE `creature` SET `spawntimesecs` = 60 WHERE (`id1` = 28912) AND (`guid` IN (130354));
UPDATE `creature_template` SET `CreatureImmunitiesId` = -93 WHERE (`entry` = 28912);
@@ -0,0 +1,4 @@
-- DB update 2026_03_27_03 -> 2026_03_27_04
--
-- School immunities are set by `creature_addon.auras` immunity auras
UPDATE `creature_template` SET `CreatureImmunitiesId` = -367 WHERE (`entry` = 8317);
+173
View File
@@ -0,0 +1,173 @@
-- DB update 2026_03_27_04 -> 2026_03_28_00
-- Move Kalimdor gossip handlers from C++ to database
-- NPCs: Rivern Frostwind, Stone Watcher of Norgannon, Great Bear Spirit,
-- Braug Dimspirit, Steward of Time, Thrall Warchief
-- =====================================================
-- 1. npc_rivern_frostwind (10618) - zone_winterspring
-- Show vendor option only if Exalted with Wintersaber Trainers (faction 589)
-- =====================================================
-- Condition: gossip_menu_option MenuID=3130, OptionID=0 requires Exalted (rank 7, mask 128)
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=3130 AND `SourceEntry`=0 AND `ConditionTypeOrReference`=5;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(15, 3130, 0, 0, 0, 5, 0, 589, 128, 0, 0, 0, 0, '', 'Rivern Frostwind - Show vendor option only if Exalted with Wintersaber Trainers');
-- Remove ScriptName
UPDATE `creature_template` SET `ScriptName`='' WHERE `entry`=10618;
-- =====================================================
-- 2. npc_stone_watcher_of_norgannon (7918) - zone_tanaris
-- 5-step gossip chain, quest 2954 credit at end
-- =====================================================
-- Add missing gossip_menu entries (MenuID -> TextID)
DELETE FROM `gossip_menu` WHERE `MenuID` IN (57000,57001,57002,57003,57004,57005);
INSERT INTO `gossip_menu` (`MenuID`, `TextID`) VALUES
(57000, 1674),
(57001, 1675),
(57002, 1676),
(57003, 1677),
(57004, 1678),
(57005, 1679);
-- Condition: show first option only if quest 2954 is taken (incomplete)
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=57000 AND `SourceEntry`=0 AND `ConditionTypeOrReference`=9;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(15, 57000, 0, 0, 0, 9, 0, 2954, 0, 0, 0, 0, 0, '', 'Stone Watcher of Norgannon - Show gossip option if quest 2954 is taken');
-- SAI: on final gossip select (menu 57005, option 0) -> close gossip + quest credit 2954
DELETE FROM `smart_scripts` WHERE `entryorguid`=7918 AND `source_type`=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
(7918, 0, 0, 1, 62, 0, 100, 512, 57005, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Stone Watcher of Norgannon - On Gossip Select - Close Gossip'),
(7918, 0, 1, 0, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 15, 2954, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Stone Watcher of Norgannon - Linked - Quest Credit 2954');
-- Update creature_template: set gossip_menu_id, add gossip npcflag, set SmartAI
UPDATE `creature_template` SET `gossip_menu_id`=57000, `npcflag`=`npcflag`|1, `ScriptName`='', `AIName`='SmartAI' WHERE `entry`=7918;
-- =====================================================
-- 3. npc_great_bear_spirit (11956) - zone_moonglade
-- 4-step gossip chain, quest 5929/5930 credit at end
-- =====================================================
-- Add quest-active text for menu 3882
DELETE FROM `gossip_menu` WHERE `MenuID`=3882 AND `TextID`=4719;
INSERT INTO `gossip_menu` (`MenuID`, `TextID`) VALUES
(3882, 4719);
-- Condition on gossip_menu: show TextID 4719 if quest 5929 OR 5930 is taken
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=3882 AND `SourceEntry`=4719;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(14, 3882, 4719, 0, 0, 9, 0, 5929, 0, 0, 0, 0, 0, '', 'Great Bear Spirit - Show text 4719 if quest 5929 is taken'),
(14, 3882, 4719, 0, 1, 9, 0, 5930, 0, 0, 0, 0, 0, '', 'Great Bear Spirit - Show text 4719 if quest 5930 is taken');
-- Condition on gossip_menu_option: show option if quest 5929 OR 5930 is taken
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=3882 AND `SourceEntry`=0;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(15, 3882, 0, 0, 0, 9, 0, 5929, 0, 0, 0, 0, 0, '', 'Great Bear Spirit - Show gossip option if quest 5929 is taken'),
(15, 3882, 0, 0, 1, 9, 0, 5930, 0, 0, 0, 0, 0, '', 'Great Bear Spirit - Show gossip option if quest 5930 is taken');
-- Clean up duplicate OptionID=1 on menu 3884 (identical to OptionID=0)
DELETE FROM `gossip_menu_option` WHERE `MenuID`=3884 AND `OptionID`=1;
-- SAI: on gossip select (menu 3884, option 0) -> quest credit for both 5929 and 5930
DELETE FROM `smart_scripts` WHERE `entryorguid`=11956 AND `source_type`=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
(11956, 0, 0, 1, 62, 0, 100, 512, 3884, 0, 0, 0, 0, 0, 15, 5929, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Great Bear Spirit - On Gossip Select - Quest Credit 5929'),
(11956, 0, 1, 0, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 15, 5930, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Great Bear Spirit - On Gossip Select - Quest Credit 5930');
-- Update creature_template
UPDATE `creature_template` SET `ScriptName`='', `AIName`='SmartAI' WHERE `entry`=11956;
-- =====================================================
-- 4. npc_braug_dimspirit (4489) - zone_stonetalon_mountains
-- Quiz: 5 dragon options, Neltharion = correct, others = wrong spell
-- =====================================================
-- Add missing Nozdormu option (OptionID=4)
DELETE FROM `gossip_menu_option` WHERE `MenuID`=4763 AND `OptionID`=4;
INSERT INTO `gossip_menu_option` (`MenuID`, `OptionID`, `OptionIcon`, `OptionText`, `OptionBroadcastTextID`, `OptionType`, `OptionNpcFlag`, `ActionMenuID`, `ActionPoiID`, `BoxCoded`, `BoxMoney`, `BoxText`) VALUES
(4763, 4, 0, 'Nozdormu is my answer.', 0, 1, 1, 0, 0, 0, 0, '');
-- Condition on gossip_menu: show text 5820 (quiz text) if quest 6627 is taken
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=4763 AND `SourceEntry`=5820;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(14, 4763, 5820, 0, 0, 9, 0, 6627, 0, 0, 0, 0, 0, '', 'Braug Dimspirit - Show quiz text if quest 6627 is taken');
-- Conditions on all 5 options: show only if quest 6627 is taken
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=4763 AND `SourceEntry` IN (0,1,2,3,4) AND `ConditionTypeOrReference`=9;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(15, 4763, 0, 0, 0, 9, 0, 6627, 0, 0, 0, 0, 0, '', 'Braug Dimspirit - Show Ysera option if quest 6627 is taken'),
(15, 4763, 1, 0, 0, 9, 0, 6627, 0, 0, 0, 0, 0, '', 'Braug Dimspirit - Show Neltharion option if quest 6627 is taken'),
(15, 4763, 2, 0, 0, 9, 0, 6627, 0, 0, 0, 0, 0, '', 'Braug Dimspirit - Show Alexstrasza option if quest 6627 is taken'),
(15, 4763, 3, 0, 0, 9, 0, 6627, 0, 0, 0, 0, 0, '', 'Braug Dimspirit - Show Malygos option if quest 6627 is taken'),
(15, 4763, 4, 0, 0, 9, 0, 6627, 0, 0, 0, 0, 0, '', 'Braug Dimspirit - Show Nozdormu option if quest 6627 is taken');
-- SAI: Neltharion (option 1) = correct answer -> quest credit
-- All others (options 0,2,3,4) = wrong answer -> cast spell 6766
DELETE FROM `smart_scripts` WHERE `entryorguid`=4489 AND `source_type`=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
(4489, 0, 0, 0, 62, 0, 100, 512, 4763, 1, 0, 0, 0, 0, 15, 6627, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Braug Dimspirit - On Gossip Select Neltharion - Quest Credit 6627'),
(4489, 0, 1, 0, 62, 0, 100, 512, 4763, 0, 0, 0, 0, 0, 11, 6766, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Braug Dimspirit - On Gossip Select Ysera - Cast Wrong Answer'),
(4489, 0, 2, 0, 62, 0, 100, 512, 4763, 2, 0, 0, 0, 0, 11, 6766, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Braug Dimspirit - On Gossip Select Alexstrasza - Cast Wrong Answer'),
(4489, 0, 3, 0, 62, 0, 100, 512, 4763, 3, 0, 0, 0, 0, 11, 6766, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Braug Dimspirit - On Gossip Select Malygos - Cast Wrong Answer'),
(4489, 0, 4, 0, 62, 0, 100, 512, 4763, 4, 0, 0, 0, 0, 11, 6766, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Braug Dimspirit - On Gossip Select Nozdormu - Cast Wrong Answer');
-- Update creature_template
UPDATE `creature_template` SET `ScriptName`='', `AIName`='SmartAI' WHERE `entry`=4489;
-- =====================================================
-- 5. npc_steward_of_time (20142) - zone_tanaris
-- Gossip shows flight option if quest 10279 incomplete or rewarded
-- On select casts spell 34891. Keep OnQuestAccept in C++.
-- =====================================================
-- Condition on gossip_menu: show text 9978 if quest 10279 is taken OR rewarded
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8072 AND `SourceEntry`=9978;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(14, 8072, 9978, 0, 0, 9, 0, 10279, 0, 0, 0, 0, 0, '', 'Steward of Time - Show text 9978 if quest 10279 is taken'),
(14, 8072, 9978, 0, 1, 8, 0, 10279, 0, 0, 0, 0, 0, '', 'Steward of Time - Show text 9978 if quest 10279 is rewarded');
-- Condition on gossip_menu_option: show option if quest 10279 is taken OR rewarded
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=8072 AND `SourceEntry`=0;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(15, 8072, 0, 0, 0, 9, 0, 10279, 0, 0, 0, 0, 0, '', 'Steward of Time - Show gossip option if quest 10279 is taken'),
(15, 8072, 0, 0, 1, 8, 0, 10279, 0, 0, 0, 0, 0, '', 'Steward of Time - Show gossip option if quest 10279 is rewarded');
-- SAI: on gossip select (menu 8072, option 0) -> invoker self-casts spell 34891
-- Using SMART_ACTION_INVOKER_CAST (134) so the player casts on themselves,
-- matching original C++: player->CastSpell(player, 34891, true)
DELETE FROM `smart_scripts` WHERE `entryorguid`=20142 AND `source_type`=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
(20142, 0, 0, 0, 62, 0, 100, 512, 8072, 0, 0, 0, 0, 0, 134, 34891, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Steward of Time - On Gossip Select - Invoker Cast Flight Through Caverns');
-- Update creature_template: add SmartAI (keep ScriptName for OnQuestAccept)
UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=20142;
-- =====================================================
-- 6. npc_thrall_warchief (4949) - zone_orgrimmar
-- 7-step gossip chain, quest 6566 credit at end
-- Keep ScriptName for OnQuestReward + AI
-- =====================================================
-- Add missing gossip_menu entries for chain steps
DELETE FROM `gossip_menu` WHERE `MenuID` IN (3665,3666,3667,3668,3669,3670);
INSERT INTO `gossip_menu` (`MenuID`, `TextID`) VALUES
(3665, 5733),
(3666, 5734),
(3667, 5735),
(3668, 5736),
(3669, 5737),
(3670, 5738);
-- Fix menu 3670: ActionMenuID should be 0 (close), not 3664 (loop)
UPDATE `gossip_menu_option` SET `ActionMenuID`=0 WHERE `MenuID`=3670 AND `OptionID`=0;
-- Condition on gossip_menu_option: show first option only if quest 6566 is taken
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=3664 AND `SourceEntry`=0 AND `ConditionTypeOrReference`=9;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(15, 3664, 0, 0, 0, 9, 0, 6566, 0, 0, 0, 0, 0, '', 'Thrall - Show gossip option if quest 6566 is taken');
-- Quest credit on final gossip step handled via sGossipSelect in C++ AI struct.
-- Cannot use SAI because Thrall's custom C++ AI (GetAI) takes precedence over SmartAI.
-- No AIName change needed.
+2 -18
View File
@@ -31,6 +31,8 @@ This is the minimum interface to the VMapMamager.
namespace VMAP
{
class StaticMapTree;
enum VMAP_LOAD_RESULT
{
VMAP_LOAD_RESULT_ERROR,
@@ -88,20 +90,8 @@ namespace VMAP
virtual ~IVMapMgr() = default;
virtual int loadMap(const char* pBasePath, unsigned int pMapId, int x, int y) = 0;
virtual LoadResult existsMap(const char* pBasePath, unsigned int pMapId, int x, int y) = 0;
virtual void unloadMap(unsigned int pMapId, int x, int y) = 0;
virtual void unloadMap(unsigned int pMapId) = 0;
virtual bool isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, ModelIgnoreFlags ignoreFlags) = 0;
virtual float getHeight(unsigned int pMapId, float x, float y, float z, float maxSearchDist) = 0;
/**
test if we hit an object. return true if we hit one. rx, ry, rz will hold the hit position or the dest position, if no intersection was found
return a position, that is pReduceDist closer to the origin
*/
virtual bool GetObjectHitPos(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float& ry, float& rz, float pModifyDist) = 0;
/**
send debug commands
*/
@@ -123,12 +113,6 @@ namespace VMAP
[[nodiscard]] bool isMapLoadingEnabled() const { return (iEnableLineOfSightCalc || iEnableHeightCalc ); }
[[nodiscard]] virtual std::string getDirFileName(unsigned int pMapId, int x, int y) const = 0;
/**
Query world model area info.
\param z gets adjusted to the ground height for which this are info is valid
*/
virtual bool GetAreaAndLiquidData(uint32 mapId, float x, float y, float z, Optional<uint8> reqLiquidType, AreaAndLiquidData& data) const = 0;
};
}
@@ -1,56 +0,0 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "MMapFactory.h"
#include <cstring>
namespace MMAP
{
// ######################## MMapFactory ########################
// our global singleton copy
MMapMgr* g_MMapMgr = nullptr;
bool MMapFactory::forbiddenMaps[1000] = {0};
MMapMgr* MMapFactory::createOrGetMMapMgr()
{
if (!g_MMapMgr)
{
g_MMapMgr = new MMapMgr();
}
return g_MMapMgr;
}
void MMapFactory::InitializeDisabledMaps()
{
memset(&forbiddenMaps, 0, sizeof(forbiddenMaps));
int32 f[] = {616 /*EoE*/, 649 /*ToC25*/, 650 /*ToC5*/, -1};
uint32 i = 0;
while (f[i] >= 0)
{
forbiddenMaps[f[i++]] = true;
}
}
void MMapFactory::clear()
{
if (g_MMapMgr)
{
delete g_MMapMgr;
g_MMapMgr = nullptr;
}
}
}
@@ -1,45 +0,0 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _MMAP_FACTORY_H
#define _MMAP_FACTORY_H
#include "MMapMgr.h"
namespace MMAP
{
enum MMAP_LOAD_RESULT
{
MMAP_LOAD_RESULT_ERROR,
MMAP_LOAD_RESULT_OK,
MMAP_LOAD_RESULT_IGNORED,
};
// static class
// holds all mmap global data
// access point to MMapMgr singleton
class MMapFactory
{
public:
static MMapMgr* createOrGetMMapMgr();
static void clear();
static void InitializeDisabledMaps();
static bool forbiddenMaps[1000];
};
}
#endif
+12 -219
View File
@@ -24,63 +24,8 @@
namespace MMAP
{
// ######################## MMapMgr ########################
MMapMgr::~MMapMgr()
std::shared_ptr<dtNavMesh> MMapMgr::LoadNavMesh(uint32 mapId)
{
for (MMapDataSet::iterator i = loadedMMaps.begin(); i != loadedMMaps.end(); ++i)
{
delete i->second;
}
// by now we should not have maps loaded
// if we had, tiles in MMapData->mmapLoadedTiles, their actual data is lost!
}
void MMapMgr::InitializeThreadUnsafe(const std::vector<uint32>& mapIds)
{
// the caller must pass the list of all mapIds that will be used in the VMapMgr2 lifetime
for (const uint32& mapId : mapIds)
{
loadedMMaps.emplace(mapId, nullptr);
}
thread_safe_environment = false;
}
MMapDataSet::const_iterator MMapMgr::GetMMapData(uint32 mapId) const
{
// return the iterator if found or end() if not found/NULL
MMapDataSet::const_iterator itr = loadedMMaps.find(mapId);
if (itr != loadedMMaps.cend() && !itr->second)
{
itr = loadedMMaps.cend();
}
return itr;
}
bool MMapMgr::loadMapData(uint32 mapId)
{
// we already have this map loaded?
MMapDataSet::iterator itr = loadedMMaps.find(mapId);
if (itr != loadedMMaps.end())
{
if (itr->second)
{
return true;
}
}
else
{
if (thread_safe_environment)
{
itr = loadedMMaps.insert(MMapDataSet::value_type(mapId, nullptr)).first;
}
else
{
ABORT("Invalid mapId {} passed to MMapMgr after startup in thread unsafe environment", mapId);
}
}
// load and init dtNavMesh - read parameters from file
std::string fileName = Acore::StringFormat(MAP_FILE_NAME_FORMAT, sConfigMgr->GetOption<std::string>("DataDir", "."), mapId);
@@ -88,7 +33,7 @@ namespace MMAP
if (!file)
{
LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not open mmap file '{}'", fileName);
return false;
return nullptr;
}
dtNavMeshParams params;
@@ -97,7 +42,7 @@ namespace MMAP
if (count != 1)
{
LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not read params from file '{}'", fileName);
return false;
return nullptr;
}
dtNavMesh* mesh = dtAllocNavMesh();
@@ -106,15 +51,13 @@ namespace MMAP
{
dtFreeNavMesh(mesh);
LOG_ERROR("maps", "MMAP:loadMapData: Failed to initialize dtNavMesh for mmap {:03} from file {}", mapId, fileName);
return false;
return nullptr;
}
LOG_DEBUG("maps", "MMAP:loadMapData: Loaded {:03}.mmap", mapId);
// store inside our map list
MMapData* mmap_data = new MMapData(mesh);
itr->second = mmap_data;
return true;
std::shared_ptr<dtNavMesh> navMesh = std::shared_ptr<dtNavMesh>(mesh, NavMeshDeleter());
return navMesh;
}
uint32 MMapMgr::packTileID(int32 x, int32 y)
@@ -122,26 +65,8 @@ namespace MMAP
return uint32(x << 16 | y);
}
bool MMapMgr::loadMap(uint32 mapId, int32 x, int32 y)
bool MMapMgr::LoadTile(dtNavMesh* navMesh, uint32 mapId, int32 x, int32 y)
{
// make sure the mmap is loaded and ready to load tiles
if (!loadMapData(mapId))
{
return false;
}
// get this mmap data
MMapData* mmap = loadedMMaps[mapId];
ASSERT(mmap->navMesh);
// check if we already have this tile loaded
uint32 packedGridPos = packTileID(x, y);
if (mmap->loadedTileRefs.find(packedGridPos) != mmap->loadedTileRefs.end())
{
LOG_ERROR("maps", "MMAP:loadMap: Asked to load already loaded navmesh tile. {:03}{:02}{:02}.mmtile", mapId, x, y);
return false;
}
// load this tile :: mmaps/MMMXXYY.mmtile
std::string fileName = Acore::StringFormat(TILE_FILE_NAME_FORMAT, sConfigMgr->GetOption<std::string>("DataDir", "."), mapId, x, y);
FILE* file = fopen(fileName.c_str(), "rb");
@@ -184,10 +109,8 @@ namespace MMAP
dtTileRef tileRef = 0;
// memory allocated for data is now managed by detour, and will be deallocated when the tile is removed
if (dtStatusSucceed(mmap->navMesh->addTile(data, fileHeader.size, DT_TILE_FREE_DATA, 0, &tileRef)))
if (dtStatusSucceed(navMesh->addTile(data, fileHeader.size, DT_TILE_FREE_DATA, 0, &tileRef)))
{
mmap->loadedTileRefs.insert(std::pair<uint32, dtTileRef>(packedGridPos, tileRef));
++loadedTiles;
dtMeshHeader* header = (dtMeshHeader*)data;
LOG_DEBUG("maps", "MMAP:loadMap: Loaded mmtile {:03}[{:02},{:02}] into {:03}[{:02},{:02}]", mapId, x, y, mapId, header->x, header->y);
return true;
@@ -198,149 +121,19 @@ namespace MMAP
return false;
}
bool MMapMgr::unloadMap(uint32 mapId, int32 x, int32 y)
{
// check if we have this map loaded
MMapDataSet::const_iterator itr = GetMMapData(mapId);
if (itr == loadedMMaps.end())
{
// file may not exist, therefore not loaded
LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map. {:03}{:02}{:02}.mmtile", mapId, x, y);
return false;
}
MMapData* mmap = itr->second;
// check if we have this tile loaded
uint32 packedGridPos = packTileID(x, y);
if (mmap->loadedTileRefs.find(packedGridPos) == mmap->loadedTileRefs.end())
{
// file may not exist, therefore not loaded
LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh tile. {:03}{:02}{:02}.mmtile", mapId, x, y);
return false;
}
dtTileRef tileRef = mmap->loadedTileRefs[packedGridPos];
// unload, and mark as non loaded
if (dtStatusFailed(mmap->navMesh->removeTile(tileRef, nullptr, nullptr)))
{
// this is technically a memory leak
// if the grid is later reloaded, dtNavMesh::addTile will return error but no extra memory is used
// we cannot recover from this error - assert out
LOG_ERROR("maps", "MMAP:unloadMap: Could not unload {:03}{:02}{:02}.mmtile from navmesh", mapId, x, y);
ABORT();
}
mmap->loadedTileRefs.erase(packedGridPos);
--loadedTiles;
LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile {:03}[{:02},{:02}] from {:03}", mapId, x, y, mapId);
return true;
}
bool MMapMgr::unloadMap(uint32 mapId)
{
MMapDataSet::iterator itr = loadedMMaps.find(mapId);
if (itr == loadedMMaps.end() || !itr->second)
{
// file may not exist, therefore not loaded
LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map {:03}", mapId);
return false;
}
// unload all tiles from given map
MMapData* mmap = itr->second;
for (auto& i : mmap->loadedTileRefs)
{
uint32 x = (i.first >> 16);
uint32 y = (i.first & 0x0000FFFF);
if (dtStatusFailed(mmap->navMesh->removeTile(i.second, nullptr, nullptr)))
{
LOG_ERROR("maps", "MMAP:unloadMap: Could not unload {:03}{:02}{:02}.mmtile from navmesh", mapId, x, y);
}
else
{
--loadedTiles;
LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile {:03}[{:02},{:02}] from {:03}", mapId, x, y, mapId);
}
}
delete mmap;
itr->second = nullptr;
LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded {:03}.mmap", mapId);
return true;
}
bool MMapMgr::unloadMapInstance(uint32 mapId, uint32 instanceId)
{
// check if we have this map loaded
MMapDataSet::const_iterator itr = GetMMapData(mapId);
if (itr == loadedMMaps.end())
{
// file may not exist, therefore not loaded
LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded navmesh map {:03}", mapId);
return false;
}
MMapData* mmap = itr->second;
if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
{
LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId {:03} instanceId {}", mapId, instanceId);
return false;
}
dtNavMeshQuery* query = mmap->navMeshQueries[instanceId];
dtFreeNavMeshQuery(query);
mmap->navMeshQueries.erase(instanceId);
LOG_DEBUG("maps", "MMAP:unloadMapInstance: Unloaded mapId {:03} instanceId {}", mapId, instanceId);
return true;
}
dtNavMesh const* MMapMgr::GetNavMesh(uint32 mapId)
{
MMapDataSet::const_iterator itr = GetMMapData(mapId);
if (itr == loadedMMaps.end())
{
return nullptr;
}
return itr->second->navMesh;
}
dtNavMeshQuery const* MMapMgr::GetNavMeshQuery(uint32 mapId, uint32 instanceId)
{
MMapDataSet::const_iterator itr = GetMMapData(mapId);
if (itr == loadedMMaps.end())
{
return nullptr;
}
MMapData* mmap = itr->second;
if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
{
// check again after acquiring mutex
if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
ManagedNavMeshQuery MMapMgr::CreateNavMeshQuery(dtNavMesh* navMesh)
{
// allocate mesh query
dtNavMeshQuery* query = dtAllocNavMeshQuery();
ASSERT(query);
if (dtStatusFailed(query->init(mmap->navMesh, 1024)))
if (dtStatusFailed(query->init(navMesh, 1024)))
{
dtFreeNavMeshQuery(query);
LOG_ERROR("maps", "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId {:03} instanceId {}", mapId, instanceId);
return nullptr;
}
LOG_DEBUG("maps", "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId {:03} instanceId {}", mapId, instanceId);
mmap->navMeshQueries.insert(std::pair<uint32, dtNavMeshQuery*>(instanceId, query));
}
}
return mmap->navMeshQueries[instanceId];
ManagedNavMeshQuery navMeshQuery = ManagedNavMeshQuery(query);
return navMeshQuery;
}
}
+21 -49
View File
@@ -22,8 +22,7 @@
#include "DetourAlloc.h"
#include "DetourExtended.h"
#include "DetourNavMesh.h"
#include <unordered_map>
#include <vector>
#include <memory>
// memory management
inline void* dtCustomAlloc(std::size_t size, dtAllocHint /*hint*/)
@@ -39,67 +38,40 @@ inline void dtCustomFree(void* ptr)
// move map related classes
namespace MMAP
{
enum MMAP_LOAD_RESULT
{
MMAP_LOAD_RESULT_ERROR,
MMAP_LOAD_RESULT_OK,
MMAP_LOAD_RESULT_IGNORED,
};
static char const* const MAP_FILE_NAME_FORMAT = "{}/mmaps/{:03}.mmap";
static char const* const TILE_FILE_NAME_FORMAT = "{}/mmaps/{:03}{:02}{:02}.mmtile";
typedef std::unordered_map<uint32, dtTileRef> MMapTileSet;
typedef std::unordered_map<uint32, dtNavMeshQuery*> NavMeshQuerySet;
// dummy struct to hold map's mmap data
struct MMapData
struct NavMeshDeleter
{
MMapData(dtNavMesh* mesh) : navMesh(mesh) { }
~MMapData()
{
for (auto& navMeshQuerie : navMeshQueries)
{
dtFreeNavMeshQuery(navMeshQuerie.second);
}
if (navMesh)
{
dtFreeNavMesh(navMesh);
}
}
// we have to use single dtNavMeshQuery for every instance, since those are not thread safe
NavMeshQuerySet navMeshQueries; // instanceId to query
dtNavMesh* navMesh;
MMapTileSet loadedTileRefs; // maps [map grid coords] to [dtTile]
void operator()(dtNavMesh* navMesh) noexcept { dtFreeNavMesh(navMesh); }
};
typedef std::unordered_map<uint32, MMapData*> MMapDataSet;
struct NavMeshQueryDeleter
{
void operator()(dtNavMeshQuery* query) noexcept { dtFreeNavMeshQuery(query); }
};
using ManagedNavMeshQuery = std::unique_ptr<dtNavMeshQuery, NavMeshQueryDeleter>;
// singleton class
// holds all all access to mmap loading unloading and meshes
class MMapMgr
{
public:
MMapMgr() = default;
~MMapMgr();
~MMapMgr() = default;
void InitializeThreadUnsafe(const std::vector<uint32>& mapIds);
bool loadMap(uint32 mapId, int32 x, int32 y);
bool unloadMap(uint32 mapId, int32 x, int32 y);
bool unloadMap(uint32 mapId);
bool unloadMapInstance(uint32 mapId, uint32 instanceId);
// the returned [dtNavMeshQuery const*] is NOT threadsafe
dtNavMeshQuery const* GetNavMeshQuery(uint32 mapId, uint32 instanceId);
dtNavMesh const* GetNavMesh(uint32 mapId);
[[nodiscard]] uint32 getLoadedTilesCount() const { return loadedTiles; }
[[nodiscard]] uint32 getLoadedMapsCount() const { return loadedMMaps.size(); }
static std::shared_ptr<dtNavMesh> LoadNavMesh(uint32 mapId);
static bool LoadTile(dtNavMesh* navMesh, uint32 mapId, int32 x, int32 y);
static ManagedNavMeshQuery CreateNavMeshQuery(dtNavMesh* navMesh);
private:
bool loadMapData(uint32 mapId);
uint32 packTileID(int32 x, int32 y);
[[nodiscard]] MMapDataSet::const_iterator GetMMapData(uint32 mapId) const;
MMapDataSet loadedMMaps;
uint32 loadedTiles{0};
bool thread_safe_environment{true};
static uint32 packTileID(int32 x, int32 y);
};
}
+1 -273
View File
@@ -17,11 +17,8 @@
#include "VMapMgr2.h"
#include "Errors.h"
#include "Log.h"
#include "MapDefines.h"
#include "MapTree.h"
#include "ModelInstance.h"
#include "WorldModel.h"
#include <G3D/Vector3.h>
#include <iomanip>
#include <sstream>
@@ -35,34 +32,13 @@ namespace VMAP
{
GetLiquidFlagsPtr = &GetLiquidFlagsDummy;
IsVMAPDisabledForPtr = &IsVMAPDisabledForDummy;
thread_safe_environment = true;
}
VMapMgr2::~VMapMgr2()
{
for (InstanceTreeMap::iterator i = iInstanceMapTrees.begin(); i != iInstanceMapTrees.end(); ++i)
{
delete i->second;
}
for (ModelFileMap::iterator i = iLoadedModelFiles.begin(); i != iLoadedModelFiles.end(); ++i)
{
delete i->second.getModel();
}
}
void VMapMgr2::InitializeThreadUnsafe(const std::vector<uint32>& mapIds)
{
// the caller must pass the list of all mapIds that will be used in the VMapMgr2 lifetime
for (const uint32& mapId : mapIds)
{
iInstanceMapTrees.emplace(mapId, nullptr);
}
thread_safe_environment = false;
}
Vector3 VMapMgr2::convertPositionToInternalRep(float x, float y, float z) const
Vector3 VMapMgr2::convertPositionToInternalRep(float x, float y, float z)
{
Vector3 pos;
const float mid = 0.5f * MAX_NUMBER_OF_GRIDS * SIZE_OF_GRIDS;
@@ -73,18 +49,6 @@ namespace VMAP
return pos;
}
InstanceTreeMap::const_iterator VMapMgr2::GetMapTree(uint32 mapId) const
{
// return the iterator if found or end() if not found/NULL
InstanceTreeMap::const_iterator itr = iInstanceMapTrees.find(mapId);
if (itr != iInstanceMapTrees.cend() && !itr->second)
{
itr = iInstanceMapTrees.cend();
}
return itr;
}
// move to MapTree too?
std::string VMapMgr2::getMapFileName(unsigned int mapId)
{
@@ -95,245 +59,9 @@ namespace VMAP
return fname.str();
}
int VMapMgr2::loadMap(const char* basePath, unsigned int mapId, int x, int y)
{
int result = VMAP_LOAD_RESULT_IGNORED;
if (isMapLoadingEnabled())
{
if (_loadMap(mapId, basePath, x, y))
{
result = VMAP_LOAD_RESULT_OK;
}
else
{
result = VMAP_LOAD_RESULT_ERROR;
}
}
return result;
}
// load one tile (internal use only)
bool VMapMgr2::_loadMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY)
{
InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId);
if (instanceTree == iInstanceMapTrees.end())
{
if (thread_safe_environment)
{
instanceTree = iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, nullptr)).first;
}
else
ABORT("Invalid mapId {} tile [{}, {}] passed to VMapMgr2 after startup in thread unsafe environment",
mapId, tileX, tileY);
}
if (!instanceTree->second)
{
std::string mapFileName = getMapFileName(mapId);
StaticMapTree* newTree = new StaticMapTree(mapId, basePath);
if (!newTree->InitMap(mapFileName, this))
{
delete newTree;
return false;
}
instanceTree->second = newTree;
}
return instanceTree->second->LoadMapTile(tileX, tileY, this);
}
void VMapMgr2::unloadMap(unsigned int mapId)
{
InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId);
if (instanceTree != iInstanceMapTrees.end() && instanceTree->second)
{
instanceTree->second->UnloadMap(this);
if (instanceTree->second->numLoadedTiles() == 0)
{
delete instanceTree->second;
instanceTree->second = nullptr;
}
}
}
void VMapMgr2::unloadMap(unsigned int mapId, int x, int y)
{
InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId);
if (instanceTree != iInstanceMapTrees.end() && instanceTree->second)
{
instanceTree->second->UnloadMapTile(x, y, this);
if (instanceTree->second->numLoadedTiles() == 0)
{
delete instanceTree->second;
instanceTree->second = nullptr;
}
}
}
bool VMapMgr2::isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, ModelIgnoreFlags ignoreFlags)
{
#if defined(ENABLE_VMAP_CHECKS)
if (!isLineOfSightCalcEnabled() || IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LOS))
{
return true;
}
#endif
InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
if (instanceTree != iInstanceMapTrees.end())
{
Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1);
Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2);
if (pos1 != pos2)
{
return instanceTree->second->isInLineOfSight(pos1, pos2, ignoreFlags);
}
}
return true;
}
/**
get the hit position and return true if we hit something
otherwise the result pos will be the dest pos
*/
bool VMapMgr2::GetObjectHitPos(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float& ry, float& rz, float modifyDist)
{
#if defined(ENABLE_VMAP_CHECKS)
if (isLineOfSightCalcEnabled() && !IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LOS))
#endif
{
InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
if (instanceTree != iInstanceMapTrees.end())
{
Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1);
Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2);
Vector3 resultPos;
bool result = instanceTree->second->GetObjectHitPos(pos1, pos2, resultPos, modifyDist);
resultPos = convertPositionToInternalRep(resultPos.x, resultPos.y, resultPos.z);
rx = resultPos.x;
ry = resultPos.y;
rz = resultPos.z;
return result;
}
}
rx = x2;
ry = y2;
rz = z2;
return false;
}
/**
get height or INVALID_HEIGHT if no height available
*/
float VMapMgr2::getHeight(unsigned int mapId, float x, float y, float z, float maxSearchDist)
{
#if defined(ENABLE_VMAP_CHECKS)
if (isHeightCalcEnabled() && !IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_HEIGHT))
#endif
{
InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
if (instanceTree != iInstanceMapTrees.end())
{
Vector3 pos = convertPositionToInternalRep(x, y, z);
float height = instanceTree->second->getHeight(pos, maxSearchDist);
if (height >= G3D::finf())
{
return height = VMAP_INVALID_HEIGHT_VALUE; // No height
}
return height;
}
}
return VMAP_INVALID_HEIGHT_VALUE;
}
bool VMapMgr2::GetAreaAndLiquidData(uint32 mapId, float x, float y, float z, Optional<uint8> reqLiquidType, AreaAndLiquidData& data) const
{
InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
if (instanceTree != iInstanceMapTrees.end())
{
LocationInfo info;
Vector3 pos = convertPositionToInternalRep(x, y, z);
if (instanceTree->second->GetLocationInfo(pos, info))
{
data.floorZ = info.ground_Z;
if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LIQUIDSTATUS))
{
uint32 liquidType = info.hitModel->GetLiquidType(); // entry from LiquidType.dbc
float liquidLevel;
if (!reqLiquidType || (GetLiquidFlagsPtr(liquidType) & *reqLiquidType))
if (info.hitInstance->GetLiquidLevel(pos, info, liquidLevel))
data.liquidInfo.emplace(liquidType, liquidLevel);
}
if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_AREAFLAG))
data.areaInfo.emplace(info.hitModel->GetWmoID(), info.hitInstance->adtId, info.rootId, info.hitModel->GetMogpFlags(), info.hitInstance->ID);
return true;
}
}
return false;
}
WorldModel* VMapMgr2::acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags/* Only used when creating the model */)
{
//! Critical section, thread safe access to iLoadedModelFiles
std::lock_guard<std::mutex> lock(LoadedModelFilesLock);
ModelFileMap::iterator model = iLoadedModelFiles.find(filename);
if (model == iLoadedModelFiles.end())
{
WorldModel* worldmodel = new WorldModel();
if (!worldmodel->readFile(basepath + filename + ".vmo"))
{
LOG_ERROR("maps", "VMapMgr2: could not load '{}{}.vmo'", basepath, filename);
delete worldmodel;
return nullptr;
}
LOG_DEBUG("maps", "VMapMgr2: loading file '{}{}'", basepath, filename);
worldmodel->Flags = flags;
model = iLoadedModelFiles.insert(std::pair<std::string, ManagedModel>(filename, ManagedModel())).first;
model->second.setModel(worldmodel);
}
return model->second.getModel();
}
void VMapMgr2::releaseModelInstance(const std::string& filename)
{
//! Critical section, thread safe access to iLoadedModelFiles
std::lock_guard<std::mutex> lock(LoadedModelFilesLock);
ModelFileMap::iterator model = iLoadedModelFiles.find(filename);
if (model == iLoadedModelFiles.end())
{
LOG_ERROR("maps", "VMapMgr2: trying to unload non-loaded file '{}'", filename);
return;
}
if (model->second.decRefCount() == 0)
{
LOG_DEBUG("maps", "VMapMgr2: unloading file '{}'", filename);
delete model->second.getModel();
iLoadedModelFiles.erase(model);
}
}
LoadResult VMapMgr2::existsMap(const char* basePath, unsigned int mapId, int x, int y)
{
return StaticMapTree::CanLoadMap(std::string(basePath), mapId, x, y);
}
void VMapMgr2::GetInstanceMapTree(InstanceTreeMap& instanceMapTree)
{
instanceMapTree = iInstanceMapTrees;
}
} // namespace VMAP
+1 -55
View File
@@ -19,9 +19,6 @@
#define _VMAPMANAGER2_H
#include "IVMapMgr.h"
#include <mutex>
#include <unordered_map>
#include <vector>
//===========================================================
@@ -46,24 +43,6 @@ namespace G3D
namespace VMAP
{
class StaticMapTree;
class WorldModel;
class ManagedModel
{
public:
ManagedModel() { }
void setModel(WorldModel* model) { iModel = model; }
WorldModel* getModel() { return iModel; }
int decRefCount() { return --iRefCount; }
protected:
WorldModel* iModel{nullptr};
int iRefCount{0};
};
typedef std::unordered_map<uint32, StaticMapTree*> InstanceTreeMap;
typedef std::unordered_map<std::string, ManagedModel> ModelFileMap;
enum DisableTypes
{
VMAP_DISABLE_AREAFLAG = 0x1,
@@ -75,58 +54,25 @@ namespace VMAP
class VMapMgr2 : public IVMapMgr
{
protected:
// Tree to check collision
ModelFileMap iLoadedModelFiles;
InstanceTreeMap iInstanceMapTrees;
bool thread_safe_environment;
// Mutex for iLoadedModelFiles
std::mutex LoadedModelFilesLock;
bool _loadMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY);
/* void _unloadMap(uint32 pMapId, uint32 x, uint32 y); */
static uint32 GetLiquidFlagsDummy(uint32) { return 0; }
static bool IsVMAPDisabledForDummy(uint32 /*entry*/, uint8 /*flags*/) { return false; }
InstanceTreeMap::const_iterator GetMapTree(uint32 mapId) const;
public:
// public for debug
[[nodiscard]] G3D::Vector3 convertPositionToInternalRep(float x, float y, float z) const;
static G3D::Vector3 convertPositionToInternalRep(float x, float y, float z);
static std::string getMapFileName(unsigned int mapId);
VMapMgr2();
~VMapMgr2() override;
void InitializeThreadUnsafe(const std::vector<uint32>& mapIds);
int loadMap(const char* pBasePath, unsigned int mapId, int x, int y) override;
void unloadMap(unsigned int mapId, int x, int y) override;
void unloadMap(unsigned int mapId) override;
bool isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, ModelIgnoreFlags ignoreFlags) override ;
/**
fill the hit pos and return true, if an object was hit
*/
bool GetObjectHitPos(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float& ry, float& rz, float modifyDist) override;
float getHeight(unsigned int mapId, float x, float y, float z, float maxSearchDist) override;
bool processCommand(char* /*command*/) override { return false; } // for debug and extensions
bool GetAreaAndLiquidData(uint32 mapId, float x, float y, float z, Optional<uint8> reqLiquidType, AreaAndLiquidData& data) const override;
WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags);
void releaseModelInstance(const std::string& filename);
// what's the use of this? o.O
[[nodiscard]] std::string getDirFileName(unsigned int mapId, int /*x*/, int /*y*/) const override
{
return getMapFileName(mapId);
}
LoadResult existsMap(const char* basePath, unsigned int mapId, int x, int y) override;
void GetInstanceMapTree(InstanceTreeMap& instanceMapTree);
typedef uint32(*GetLiquidFlagsFn)(uint32 liquidType);
GetLiquidFlagsFn GetLiquidFlagsPtr;
@@ -0,0 +1,43 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Log.h"
#include "WorldModelStore.h"
std::shared_ptr<VMAP::WorldModel> WorldModelStore::AcquireModelInstance(std::string const& basepath, std::string const& filename, uint32 flags/* Only used when creating the model */)
{
//! Critical section, thread safe access
std::lock_guard<std::mutex> lock(_lock);
ModelFileMap::iterator model = _loadedModels.find(filename);
if (model == _loadedModels.end())
{
std::shared_ptr<VMAP::WorldModel> worldmodel = std::make_shared<VMAP::WorldModel>();
LOG_DEBUG("maps", "WorldModelStore: loading file '{}{}'", basepath, filename);
if (!worldmodel->readFile(basepath + filename + ".vmo"))
{
LOG_ERROR("maps", "WorldModelStore: could not load '{}{}.vmo'", basepath, filename);
return nullptr;
}
worldmodel->Flags = flags;
model = _loadedModels.insert(std::pair<std::string, std::shared_ptr<VMAP::WorldModel>>(filename, worldmodel)).first;
}
return model->second;
}
@@ -15,32 +15,32 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _IMMAPMANAGER_H
#define _IMMAPMANAGER_H
#ifndef _WORLDMODELSTORE_H
#define _WORLDMODELSTORE_H
// Interface for IMMapManger
namespace MMAP
#include "WorldModel.h"
#include <memory>
#include <mutex>
#include <unordered_map>
class WorldModelStore
{
enum MMAP_LOAD_RESULT
public:
static WorldModelStore* instance()
{
MMAP_LOAD_RESULT_ERROR,
MMAP_LOAD_RESULT_OK,
MMAP_LOAD_RESULT_IGNORED,
};
static WorldModelStore instance;
return &instance;
}
class IMMapMgr
{
private:
bool iEnablePathFinding;
std::shared_ptr<VMAP::WorldModel> AcquireModelInstance(std::string const& basepath, std::string const& filename, uint32 flags);
public:
IMMapMgr() : iEnablePathFinding(true) {}
virtual ~IMMapMgr(void) {}
private:
typedef std::unordered_map<std::string, std::shared_ptr<VMAP::WorldModel>> ModelFileMap;
ModelFileMap _loadedModels;
//Enabled/Disabled Pathfinding
void setEnablePathFinding(bool value) { iEnablePathFinding = value; }
bool isEnablePathFinding() const { return (iEnablePathFinding); }
};
}
std::mutex _lock;
};
#define sWorldModelStore WorldModelStore::instance()
#endif
+17 -76
View File
@@ -22,6 +22,7 @@
#include "ModelInstance.h"
#include "VMapDefinitions.h"
#include "VMapMgr2.h"
#include "WorldModelStore.h"
#include <iomanip>
#include <limits>
#include <sstream>
@@ -259,7 +260,7 @@ namespace VMAP
//=========================================================
bool StaticMapTree::InitMap(const std::string& fname, VMapMgr2* vm)
bool StaticMapTree::InitMap(const std::string& fname)
{
//VMAP_DEBUG_LOG(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : initializing StaticMapTree '{}'", fname);
bool success = false;
@@ -291,13 +292,12 @@ namespace VMAP
#endif
if (!iIsTiled && ModelSpawn::readFromFile(rf, spawn))
{
WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name, spawn.flags);
std::shared_ptr<WorldModel> model = sWorldModelStore->AcquireModelInstance(iBasePath, spawn.name, spawn.flags);
//VMAP_DEBUG_LOG(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : loading {}", spawn.name);
if (model)
{
// assume that global model always is the first and only tree value (could be improved...)
iTreeValues[0] = ModelInstance(spawn, model);
iLoadedSpawns[0] = 1;
}
else
{
@@ -312,23 +312,14 @@ namespace VMAP
//=========================================================
void StaticMapTree::UnloadMap(VMapMgr2* vm)
void StaticMapTree::UnloadMap()
{
for (loadedSpawnMap::iterator i = iLoadedSpawns.begin(); i != iLoadedSpawns.end(); ++i)
{
iTreeValues[i->first].setUnloaded();
for (uint32 refCount = 0; refCount < i->second; ++refCount)
{
vm->releaseModelInstance(iTreeValues[i->first].name);
}
}
iLoadedSpawns.clear();
iLoadedTiles.clear();
}
//=========================================================
bool StaticMapTree::LoadMapTile(uint32 tileX, uint32 tileY, VMapMgr2* vm)
bool StaticMapTree::LoadMapTile(uint32 tileX, uint32 tileY)
{
if (!iIsTiled)
{
@@ -367,10 +358,11 @@ namespace VMAP
if (result)
{
// acquire model instance
WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name, spawn.flags);
std::shared_ptr<WorldModel> model = sWorldModelStore->AcquireModelInstance(iBasePath, spawn.name, spawn.flags);
if (!model)
{
LOG_ERROR("maps", "StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [{}, {}]", tileX, tileY);
// why do we continue to try to load if the model was unsuccessful here?
}
// update tree
@@ -378,22 +370,22 @@ namespace VMAP
if (fread(&referencedVal, sizeof(uint32), 1, tf) == 1)
{
if (!iLoadedSpawns.count(referencedVal))
{
#if defined(VMAP_DEBUG)
if (referencedVal > iNTreeValues)
if (referencedVal >= iNTreeValues)
{
LOG_DEBUG("maps", "StaticMapTree::LoadMapTile() : invalid tree element ({}/{})", referencedVal, iNTreeValues);
continue;
}
#endif
// This looks odd and is confusing, took some research to figure it out:
// the first WorldModel will create a "groupmodel" of all other same-models in the tile
// we don't actually care about anything else
if (!iTreeValues[referencedVal].getWorldModel())
{
iTreeValues[referencedVal] = ModelInstance(spawn, model);
iLoadedSpawns[referencedVal] = 1;
}
#if defined(VMAP_DEBUG)
else
{
++iLoadedSpawns[referencedVal];
#if defined(VMAP_DEBUG)
if (iTreeValues[referencedVal].ID != spawn.ID)
{
LOG_DEBUG("maps", "StaticMapTree::LoadMapTile() : trying to load wrong spawn in node");
@@ -402,8 +394,8 @@ namespace VMAP
{
LOG_DEBUG("maps", "StaticMapTree::LoadMapTile() : name collision on GUID={}", spawn.ID);
}
#endif
}
#endif
}
else
{
@@ -427,7 +419,7 @@ namespace VMAP
//=========================================================
void StaticMapTree::UnloadMapTile(uint32 tileX, uint32 tileY, VMapMgr2* vm)
void StaticMapTree::UnloadMapTile(uint32 tileX, uint32 tileY)
{
uint32 tileID = packTileID(tileX, tileY);
loadedTileMap::iterator tile = iLoadedTiles.find(tileID);
@@ -436,57 +428,6 @@ namespace VMAP
LOG_ERROR("maps", "StaticMapTree::UnloadMapTile() : trying to unload non-loaded tile - Map:{} X:{} Y:{}", iMapID, tileX, tileY);
return;
}
if (tile->second) // file associated with tile
{
std::string tilefile = iBasePath + getTileFileName(iMapID, tileX, tileY);
FILE* tf = fopen(tilefile.c_str(), "rb");
if (tf)
{
bool result = true;
char chunk[8];
if (!readChunk(tf, chunk, VMAP_MAGIC, 8))
{
result = false;
}
uint32 numSpawns;
if (fread(&numSpawns, sizeof(uint32), 1, tf) != 1)
{
result = false;
}
for (uint32 i = 0; i < numSpawns && result; ++i)
{
// read model spawns
ModelSpawn spawn;
result = ModelSpawn::readFromFile(tf, spawn);
if (result)
{
// release model instance
vm->releaseModelInstance(spawn.name);
// update tree
uint32 referencedNode;
if (fread(&referencedNode, sizeof(uint32), 1, tf) != 1)
{
result = false;
}
else
{
if (!iLoadedSpawns.count(referencedNode))
{
LOG_ERROR("maps", "StaticMapTree::UnloadMapTile() : trying to unload non-referenced model '{}' (ID:{})", spawn.name, spawn.ID);
}
else if (--iLoadedSpawns[referencedNode] == 0)
{
iTreeValues[referencedNode].setUnloaded();
iLoadedSpawns.erase(referencedNode);
}
}
}
}
fclose(tf);
}
}
iLoadedTiles.erase(tile);
METRIC_EVENT("map_events", "UnloadMapTile",
+4 -6
View File
@@ -60,8 +60,6 @@ namespace VMAP
// some maps are not splitted into tiles and we have to make sure, not removing the map before all tiles are removed
// empty tiles have no tile file, hence map with bool instead of just a set (consistency check)
loadedTileMap iLoadedTiles;
// stores <tree_index, reference_count> to invalidate tree values, unload map, and to be able to report errors
loadedSpawnMap iLoadedSpawns;
std::string iBasePath;
private:
@@ -81,10 +79,10 @@ namespace VMAP
[[nodiscard]] float getHeight(const G3D::Vector3& pPos, float maxSearchDist) const;
bool GetLocationInfo(const G3D::Vector3& pos, LocationInfo& info) const;
bool InitMap(const std::string& fname, VMapMgr2* vm);
void UnloadMap(VMapMgr2* vm);
bool LoadMapTile(uint32 tileX, uint32 tileY, VMapMgr2* vm);
void UnloadMapTile(uint32 tileX, uint32 tileY, VMapMgr2* vm);
bool InitMap(const std::string& fname);
void UnloadMap();
bool LoadMapTile(uint32 tileX, uint32 tileY);
void UnloadMapTile(uint32 tileX, uint32 tileY);
[[nodiscard]] bool isTiled() const { return iIsTiled; }
[[nodiscard]] uint32 numLoadedTiles() const { return iLoadedTiles.size(); }
void GetModelInstances(ModelInstance*& models, uint32& count);
@@ -24,6 +24,7 @@
#include "VMapFactory.h"
#include "VMapMgr2.h"
#include "WorldModel.h"
#include "WorldModelStore.h"
using G3D::Vector3;
using G3D::Ray;
@@ -101,14 +102,6 @@ void LoadGameObjectModelList(std::string const& dataPath)
LOG_INFO("server.loading", " ");
}
GameObjectModel::~GameObjectModel()
{
if (iModel)
{
VMAP::VMapFactory::createOrGetVMapMgr()->releaseModelInstance(name);
}
}
bool GameObjectModel::initialize(std::unique_ptr<GameObjectModelOwnerBase> modelOwner, std::string const& dataPath)
{
ModelList::const_iterator it = model_list.find(modelOwner->GetDisplayId());
@@ -125,7 +118,7 @@ bool GameObjectModel::initialize(std::unique_ptr<GameObjectModelOwnerBase> model
return false;
}
iModel = VMAP::VMapFactory::createOrGetVMapMgr()->acquireModelInstance(dataPath + "vmaps/", it->second.name,
iModel = sWorldModelStore->AcquireModelInstance(dataPath + "vmaps/", it->second.name,
it->second.isWmo ? VMAP::ModelFlags::MOD_WORLDSPAWN : VMAP::ModelFlags::MOD_M2);
if (!iModel)
@@ -23,6 +23,7 @@
#include <G3D/Matrix3.h>
#include <G3D/Ray.h>
#include <G3D/Vector3.h>
#include <memory>
namespace VMAP
{
@@ -58,7 +59,7 @@ public:
[[nodiscard]] const G3D::AABox& GetBounds() const { return iBound; }
~GameObjectModel();
~GameObjectModel() = default;
[[nodiscard]] const G3D::Vector3& GetPosition() const { return iPos; }
@@ -86,7 +87,7 @@ private:
G3D::Vector3 iPos;
float iInvScale{0};
float iScale{0};
VMAP::WorldModel* iModel{nullptr};
std::shared_ptr<VMAP::WorldModel> iModel;
std::unique_ptr<GameObjectModelOwnerBase> owner;
bool isWmo{false};
};
@@ -24,7 +24,7 @@ using G3D::Ray;
namespace VMAP
{
ModelInstance::ModelInstance(const ModelSpawn& spawn, WorldModel* model): ModelSpawn(spawn), iModel(model)
ModelInstance::ModelInstance(const ModelSpawn& spawn, std::shared_ptr<WorldModel> model): ModelSpawn(spawn), iModel(model)
{
iInvRot = G3D::Matrix3::fromEulerAnglesZYX(G3D::pi() * iRot.y / 180.f, G3D::pi() * iRot.x / 180.f, G3D::pi() * iRot.z / 180.f).inverse();
iInvScale = 1.f / iScale;
+4 -4
View File
@@ -23,6 +23,7 @@
#include <G3D/Matrix3.h>
#include <G3D/Ray.h>
#include <G3D/Vector3.h>
#include <memory>
namespace VMAP
{
@@ -63,16 +64,15 @@ namespace VMAP
{
public:
ModelInstance() { }
ModelInstance(const ModelSpawn& spawn, WorldModel* model);
void setUnloaded() { iModel = nullptr; }
ModelInstance(const ModelSpawn& spawn, std::shared_ptr<WorldModel> model);
bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit, ModelIgnoreFlags ignoreFlags) const;
bool GetLocationInfo(const G3D::Vector3& p, LocationInfo& info) const;
bool GetLiquidLevel(const G3D::Vector3& p, LocationInfo& info, float& liqHeight) const;
WorldModel* getWorldModel() { return iModel; }
WorldModel* getWorldModel() { return iModel.get(); }
protected:
G3D::Matrix3 iInvRot;
float iInvScale{0.0f};
WorldModel* iModel{nullptr};
std::shared_ptr<WorldModel> iModel;
};
} // namespace VMAP
@@ -3629,6 +3629,15 @@ Wintergrasp.NoBattleTimer = 150
Wintergrasp.CrashRestartTimer = 10
#
# Wintergrasp.SkipBattleSessionCount
# Description: When the peace timer expires, if the number of active sessions
# exceeds this value, a new war will not start.
# Set to 0 to disable this check.
# Default: 3500
Wintergrasp.SkipBattleSessionCount = 3500
#
###################################################################################################
@@ -119,6 +119,13 @@ void LoginDatabaseConnection::DoPrepareStatements()
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_INS_AUTOBROADCAST, "INSERT INTO autobroadcast (realmid, weight, text) VALUES (?, ?, ?)", CONNECTION_SYNCH);
PrepareStatement(LOGIN_DEL_AUTOBROADCAST, "DELETE FROM autobroadcast WHERE id = ? AND (realmid = ? OR realmid = -1)", CONNECTION_SYNCH);
PrepareStatement(LOGIN_INS_AUTOBROADCAST_LOCALE, "REPLACE INTO autobroadcast_locale (realmid, id, locale, text) VALUES (?, ?, ?, ?)", CONNECTION_SYNCH);
PrepareStatement(LOGIN_DEL_AUTOBROADCAST_LOCALE, "DELETE FROM autobroadcast_locale WHERE id = ? AND (realmid = ? OR realmid = -1)", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_AUTOBROADCAST_BY_ID, "SELECT 1 FROM autobroadcast WHERE id = ? AND (realmid = ? OR realmid = -1)", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_AUTOBROADCAST_LOCALE_BY_ID, "SELECT locale, text FROM autobroadcast_locale WHERE (realmid = ? OR realmid = -1) AND id = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_AUTOBROADCAST_MAX_ID, "SELECT MAX(id) FROM autobroadcast 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_REP_MOTD, "REPLACE INTO motd (realmid, text) VALUES (?, ?)", CONNECTION_ASYNC);
@@ -101,6 +101,13 @@ enum LoginDatabaseStatements : uint32
LOGIN_DEL_ACCOUNT,
LOGIN_SEL_AUTOBROADCAST,
LOGIN_SEL_AUTOBROADCAST_LOCALIZED,
LOGIN_INS_AUTOBROADCAST,
LOGIN_DEL_AUTOBROADCAST,
LOGIN_INS_AUTOBROADCAST_LOCALE,
LOGIN_DEL_AUTOBROADCAST_LOCALE,
LOGIN_SEL_AUTOBROADCAST_BY_ID,
LOGIN_SEL_AUTOBROADCAST_LOCALE_BY_ID,
LOGIN_SEL_AUTOBROADCAST_MAX_ID,
LOGIN_SEL_MOTD,
LOGIN_SEL_MOTD_LOCALE,
LOGIN_REP_MOTD,
@@ -52,7 +52,7 @@ void WorldDatabaseConnection::DoPrepareStatements()
PrepareStatement(WORLD_UPD_WAYPOINT_DATA_WPGUID, "UPDATE waypoint_data SET wpguid = ? WHERE id = ? and point = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_SEL_WAYPOINT_DATA_MAX_ID, "SELECT MAX(id) FROM waypoint_data", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_WAYPOINT_DATA_MAX_POINT, "SELECT MAX(point) FROM waypoint_data WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_WAYPOINT_DATA_BY_ID, "SELECT point, position_x, position_y, position_z, orientation, move_type, delay, action, action_chance FROM waypoint_data WHERE id = ? ORDER BY point", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_WAYPOINT_DATA_BY_ID, "SELECT point, position_x, position_y, position_z, orientation, velocity, delay, smoothTransition, move_type, action, action_chance FROM waypoint_data WHERE id = ? ORDER BY point", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_WAYPOINT_DATA_POS_BY_ID, "SELECT point, position_x, position_y, position_z FROM waypoint_data WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_WAYPOINT_DATA_POS_FIRST_BY_ID, "SELECT position_x, position_y, position_z FROM waypoint_data WHERE point = 1 AND id = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_WAYPOINT_DATA_POS_LAST_BY_ID, "SELECT position_x, position_y, position_z, orientation FROM waypoint_data WHERE id = ? ORDER BY point DESC LIMIT 1", CONNECTION_SYNCH);
@@ -77,7 +77,7 @@ void WorldDatabaseConnection::DoPrepareStatements()
PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_ID_BY_GUID, "SELECT id FROM waypoint_scripts WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_DEL_CREATURE, "DELETE FROM creature WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_SEL_COMMANDS, "SELECT name, security, help FROM command", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction, npcflag, speed_walk, speed_run, speed_swim, speed_flight, detection_range, scale, `rank`, dmgschool, DamageModifier, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, dynamicflags, family, type, type_flags, lootid, pickpocketloot, skinloot, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, ctm.Chase, ctm.Random, ctm.InteractionPauseTimer, HoverHeight, HealthModifier, ManaModifier, ArmorModifier, ExperienceModifier, RacialLeader, movementId, RegenHealth, mechanic_immune_mask, spell_school_immune_mask, flags_extra, ScriptName FROM creature_template ct LEFT JOIN creature_template_movement ctm ON ct.entry = ctm.CreatureId WHERE entry = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction, npcflag, speed_walk, speed_run, speed_swim, speed_flight, detection_range, `rank`, dmgschool, DamageModifier, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, dynamicflags, family, type, type_flags, lootid, pickpocketloot, skinloot, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, ctm.Chase, ctm.Random, ctm.InteractionPauseTimer, HoverHeight, HealthModifier, ManaModifier, ArmorModifier, ExperienceModifier, RacialLeader, movementId, RegenHealth, CreatureImmunitiesId, flags_extra, ScriptName FROM creature_template ct LEFT JOIN creature_template_movement ctm ON ct.entry = ctm.CreatureId WHERE entry = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_BY_ID, "SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_ITEM_TEMPLATE_BY_NAME, "SELECT entry FROM item_template WHERE name = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_CREATURE_BY_ID, "SELECT guid FROM creature WHERE id1 = ? OR id2 = ? OR id3 = ?", CONNECTION_SYNCH);
+6 -1
View File
@@ -20,7 +20,12 @@
PassiveAI::PassiveAI(Creature* c) : CreatureAI(c) { me->SetReactState(REACT_PASSIVE); }
PossessedAI::PossessedAI(Creature* c) : CreatureAI(c) { me->SetReactState(REACT_PASSIVE); }
NullCreatureAI::NullCreatureAI(Creature* c) : CreatureAI(c) { me->SetReactState(REACT_PASSIVE); }
NullCreatureAI::NullCreatureAI(Creature* c) : CreatureAI(c)
{
me->SetReactState(REACT_PASSIVE);
// TODO: Remove once WorldObject casting is ported (triggers won't create combat refs from spell casts)
me->SetIsCombatDisallowed(true);
}
int32 NullCreatureAI::Permissible(Creature const* creature)
{
+20 -5
View File
@@ -198,8 +198,12 @@ void CreatureAI::OnOwnerCombatInteraction(Unit* target)
if (!target || !me->IsAlive())
return;
// Prevent guardian from disengaging from current target
if (me->GetVictim() && me->GetVictim()->IsAlive())
return;
if (!me->HasReactState(REACT_PASSIVE) && me->CanStartAttack(target, true))
me->EngageWithTarget(target);
AttackStart(target);
}
// Distract creature, if player gets too close while stealthed/prowling
@@ -211,6 +215,9 @@ void CreatureAI::TriggerAlert(Unit const* who) const
// If this unit isn't an NPC, is already distracted, is in combat, is confused, stunned or fleeing, do nothing
if (!me->IsCreature() || me->IsEngaged() || me->HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_STUNNED | UNIT_STATE_FLEEING | UNIT_STATE_DISTRACTED))
return;
// If the creature is immune to players, it should not be alerted by them
if (me->IsImmuneToPC())
return;
// Only alert for hostiles!
if (me->IsCivilian() || me->HasReactState(REACT_PASSIVE) || !me->IsHostileTo(who) || !me->_IsTargetAcceptable(who))
return;
@@ -235,15 +242,20 @@ void CreatureAI::EnterEvadeMode(EvadeReason why)
if (!me->GetVehicle()) // otherwise me will be in evade mode forever
{
if (Unit* owner = me->GetCharmerOrOwner())
{
// Owned creatures (pets/guardians) follow their owner — clear evade state
// so they can re-enter combat immediately via CanBeginCombat
me->ClearUnitState(UNIT_STATE_EVADE);
if (!me->IsVehicle()) // vehicles should not follow their owner (passenger)
{
me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle(), MOTION_SLOT_ACTIVE);
}
}
else
{
// Required to prevent attacking creatures that are evading and cause them to reenter combat
// Does not apply to MoveFollow
me->AddUnitState(UNIT_STATE_EVADE);
// Does not apply to MoveFollow — UNIT_STATE_EVADE is already set from _EnterEvadeMode
me->GetMotionMaster()->MoveTargetedHome();
}
}
@@ -378,8 +390,11 @@ bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/)
return false;
}
// Set evade state early to prevent recursion when CombatStop triggers JustExitedCombat
// This will be cleared in MoveTargetedHome for pets/guardians following their owner
// Set evade state early to prevent recursion: CombatStop below purges combat
// refs, which triggers JustExitedCombat -> EnterEvadeMode -> _EnterEvadeMode.
// The IsInEvadeMode() check above will catch it.
// EnterEvadeMode will clear this for owned creatures (pets/guardians) that
// use MoveFollow instead of MoveTargetedHome.
me->AddUnitState(UNIT_STATE_EVADE);
// don't remove vehicle auras, passengers aren't supposed to drop off the vehicle
+7
View File
@@ -186,6 +186,13 @@ public:
// Called at MovePath End
virtual void PathEndReached(uint32 /*pathId*/) {}
/// == Waypoints system =============================
virtual void WaypointPathStarted(uint32 /*pathId*/) { }
virtual void WaypointStarted(uint32 /*nodeId*/, uint32 /*pathId*/) { }
virtual void WaypointReached(uint32 /*nodeId*/, uint32 /*pathId*/) { }
virtual void WaypointPathEnded(uint32 /*nodeId*/, uint32 /*pathId*/) { }
void OnCharmed(bool apply) override;
// Called at reaching home after evade
@@ -472,7 +472,7 @@ void ScriptedAI::DoResetThreat(Unit* unit)
void ScriptedAI::DoResetThreatList()
{
if (!me->CanHaveThreatList() || me->GetThreatMgr().IsThreatListEmpty())
if (!me->CanHaveThreatList() || me->GetThreatMgr().IsThreatListEmpty(true))
{
LOG_ERROR("entities.unit.ai", "DoResetThreatList called for creature that either cannot have threat list or has empty threat list (me entry = {})", me->GetEntry());
return;
@@ -87,6 +87,7 @@ public:
void GenerateWaypointArray(Movement::PointsArray* points);
using CreatureAI::WaypointReached;
virtual void WaypointReached(uint32 pointId) = 0;
virtual void WaypointStart(uint32 /*pointId*/) {}
+97 -50
View File
@@ -109,27 +109,67 @@ void SmartAI::UpdateDespawn(const uint32 diff)
mDespawnTime -= diff;
}
WaypointData const* SmartAI::GetNextWayPoint()
void SmartAI::UpdateFollow(const uint32 diff)
{
if (!mWayPoints || mWayPoints->empty())
if (!mFollowGuid)
return;
if (mFollowArrivedTimer < diff)
{
if (me->FindNearestCreature(mFollowArrivedEntry, INTERACTION_DISTANCE, mFollowArrivedAlive))
StopFollow(true);
else
mFollowArrivedTimer = 1000;
}
else
mFollowArrivedTimer -= diff;
if (mFollowGuid.IsPlayer())
{
if (_followCheckTimer < diff)
{
bool shouldDespawn = false;
if (Player* player = ObjectAccessor::FindPlayer(mFollowGuid))
{
float checkDist = me->GetInstanceScript() ? SMART_ESCORT_MAX_PLAYER_DIST * 2 : SMART_ESCORT_MAX_PLAYER_DIST;
if (!me->IsWithinDistInMap(player, checkDist))
shouldDespawn = true;
}
else
shouldDespawn = true;
if (shouldDespawn)
me->DespawnOrUnsummon();
_followCheckTimer = 1000;
}
else
_followCheckTimer -= diff;
}
}
WaypointNode const* SmartAI::GetNextWayPoint()
{
if (!mWayPoints || mWayPoints->Nodes.empty())
return nullptr;
mCurrentWPID++;
auto itr = mWayPoints->find(mCurrentWPID);
if (itr != mWayPoints->end())
{
mLastWP = &(*itr).second;
if (mLastWP->id != mCurrentWPID)
LOG_ERROR("scripts.ai.sai", "SmartAI::GetNextWayPoint: Got not expected waypoint id {}, expected {}", mLastWP->id, mCurrentWPID);
return &(*itr).second;
}
// mCurrentWPID is 1-based for SmartAI escort paths
if (mCurrentWPID > mWayPoints->Nodes.size())
return nullptr;
// Nodes are 0-indexed, mCurrentWPID is 1-based
WaypointNode const& node = mWayPoints->Nodes[mCurrentWPID - 1];
mLastWP = &node;
if (mLastWP->Id != mCurrentWPID)
LOG_ERROR("scripts.ai.sai", "SmartAI::GetNextWayPoint: Got not expected waypoint id {}, expected {}", mLastWP->Id, mCurrentWPID);
return mLastWP;
}
void SmartAI::GenerateWayPointArray(Movement::PointsArray* points)
{
if (!mWayPoints || mWayPoints->empty())
if (!mWayPoints || mWayPoints->Nodes.empty())
return;
// Flying unit, just fill array
@@ -138,16 +178,12 @@ void SmartAI::GenerateWayPointArray(Movement::PointsArray* points)
// xinef: first point in vector is unit real position
points->clear();
points->push_back(G3D::Vector3(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()));
uint32 wpCounter = mCurrentWPID;
auto itr = mWayPoints->find(wpCounter++);
do
// mCurrentWPID is 1-based
for (uint32 i = mCurrentWPID > 0 ? mCurrentWPID - 1 : 0; i < mWayPoints->Nodes.size(); ++i)
{
WaypointData const& wp = (*itr).second;
points->push_back(G3D::Vector3(wp.x, wp.y, wp.z));
itr = mWayPoints->find(wpCounter++);
WaypointNode const& wp = mWayPoints->Nodes[i];
points->push_back(G3D::Vector3(wp.X, wp.Y, wp.Z));
}
while (itr != mWayPoints->end());
}
else
{
@@ -156,15 +192,15 @@ void SmartAI::GenerateWayPointArray(Movement::PointsArray* points)
std::vector<G3D::Vector3> pVector;
// xinef: first point in vector is unit real position
pVector.push_back(G3D::Vector3(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()));
uint32 wpCounter = mCurrentWPID;
uint32 length = (mWayPoints->size() - mCurrentWPID) * size;
uint32 startIdx = mCurrentWPID > 0 ? mCurrentWPID - 1 : 0;
uint32 length = (uint32)((mWayPoints->Nodes.size() - startIdx) * size);
uint32 cnt = 0;
for (auto itr = mWayPoints->find(wpCounter); itr != mWayPoints->end() && cnt++ <= length; ++itr)
for (uint32 i = startIdx; i < mWayPoints->Nodes.size() && cnt++ <= length; ++i)
{
WaypointData const& wp = (*itr).second;
pVector.push_back(G3D::Vector3(wp.x, wp.y, wp.z));
WaypointNode const& wp = mWayPoints->Nodes[i];
pVector.push_back(G3D::Vector3(wp.X, wp.Y, wp.Z));
}
if (pVector.size() > 2) // more than source + dest
@@ -204,10 +240,10 @@ void SmartAI::StartPath(ForcedMovement forcedMovement, uint32 path, bool repeat,
return;
}
if (!mWayPoints || mWayPoints->empty())
if (!mWayPoints || mWayPoints->Nodes.empty())
return;
if (WaypointData const* wp = GetNextWayPoint())
if (WaypointNode const* wp = GetNextWayPoint())
{
AddEscortState(SMART_ESCORT_ESCORTING);
mCanRepeatPath = repeat;
@@ -223,7 +259,7 @@ void SmartAI::StartPath(ForcedMovement forcedMovement, uint32 path, bool repeat,
GenerateWayPointArray(&pathPoints);
me->GetMotionMaster()->MoveSplinePath(&pathPoints, mForcedMovement);
GetScript()->ProcessEventsFor(SMART_EVENT_ESCORT_START, nullptr, wp->id, GetScript()->GetPathId());
GetScript()->ProcessEventsFor(SMART_EVENT_ESCORT_START, nullptr, wp->Id, GetScript()->GetPathId());
}
}
@@ -282,10 +318,11 @@ void SmartAI::PausePath(uint32 delay, bool forced)
me->StopMoving();
me->GetMotionMaster()->MoveIdle();//force stop
auto waypoint = mWayPoints->find(mCurrentWPID);
if (waypoint->second.orientation.has_value())
if (mCurrentWPID > 0 && mCurrentWPID <= mWayPoints->Nodes.size())
{
me->SetFacingTo(*waypoint->second.orientation);
WaypointNode const& waypoint = mWayPoints->Nodes[mCurrentWPID - 1];
if (waypoint.Orientation.has_value())
me->SetFacingTo(*waypoint.Orientation);
}
}
GetScript()->ProcessEventsFor(SMART_EVENT_ESCORT_PAUSED, nullptr, mCurrentWPID, GetScript()->GetPathId());
@@ -536,23 +573,7 @@ void SmartAI::UpdateAI(uint32 diff)
GetScript()->OnUpdate(diff);
UpdatePath(diff);
UpdateDespawn(diff);
//TODO move to void
if (mFollowGuid)
{
if (mFollowArrivedTimer < diff)
{
if (me->FindNearestCreature(mFollowArrivedEntry, INTERACTION_DISTANCE, mFollowArrivedAlive))
{
StopFollow(true);
return;
}
mFollowArrivedTimer = 1000;
}
else
mFollowArrivedTimer -= diff;
}
UpdateFollow(diff);
if (!IsAIControlled())
{
@@ -632,7 +653,7 @@ void SmartAI::MovepointReached(uint32 id)
if (mLastWP)
{
me->SetPosition(mLastWP->x, mLastWP->y, mLastWP->z, me->GetOrientation());
me->SetPosition(mLastWP->X, mLastWP->Y, mLastWP->Z, me->GetOrientation());
me->SetHomePosition(me->GetPosition());
}
@@ -755,7 +776,7 @@ void SmartAI::MoveInLineOfSight(Unit* who)
bool SmartAI::CanAIAttack(Unit const* /*who*/) const
{
return !(me->GetReactState() == REACT_PASSIVE);
return true;
}
bool SmartAI::AssistPlayerInCombatAgainst(Unit* who)
@@ -1255,6 +1276,32 @@ void SmartAI::PathEndReached(uint32 /*pathId*/)
me->LoadPath(0);
}
void SmartAI::WaypointPathStarted(uint32 /*pathId*/)
{
}
void SmartAI::WaypointStarted(uint32 /*nodeId*/, uint32 /*pathId*/)
{
}
void SmartAI::WaypointReached(uint32 nodeId, uint32 pathId)
{
if (!HasEscortState(SMART_ESCORT_ESCORTING))
{
GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_REACHED, nullptr, nodeId, pathId);
return;
}
}
void SmartAI::WaypointPathEnded(uint32 nodeId, uint32 pathId)
{
if (!HasEscortState(SMART_ESCORT_ESCORTING))
{
GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_ENDED, nullptr, nodeId, pathId);
return;
}
}
void SmartAI::DistancingEnded()
{
SetCurrentRangeMode(true, _pendingDistancing);
+10 -3
View File
@@ -58,7 +58,7 @@ public:
void StopPath(uint32 DespawnTime = 0, uint32 quest = 0, bool fail = false);
void EndPath(bool fail = false);
void ResumePath();
WaypointData const* GetNextWayPoint();
WaypointNode const* GetNextWayPoint();
void GenerateWayPointArray(Movement::PointsArray* points);
bool HasEscortState(uint32 uiEscortState) { return (mEscortState & uiEscortState); }
void AddEscortState(uint32 uiEscortState) { mEscortState |= uiEscortState; }
@@ -206,6 +206,11 @@ public:
void PathEndReached(uint32 pathId) override;
void WaypointPathStarted(uint32 pathId) override;
void WaypointStarted(uint32 nodeId, uint32 pathId) override;
void WaypointReached(uint32 nodeId, uint32 pathId) override;
void WaypointPathEnded(uint32 nodeId, uint32 pathId) override;
bool CanRespawn() override { return mcanSpawn; };
void SetCanRespawn(bool canSpawn) { mcanSpawn = canSpawn; }
@@ -222,6 +227,7 @@ private:
bool mIsCharmed;
uint32 mFollowCreditType;
uint32 mFollowArrivedTimer;
uint32 _followCheckTimer;
uint32 mFollowCredit;
uint32 mFollowArrivedEntry;
bool mFollowArrivedAlive;
@@ -238,9 +244,9 @@ private:
bool mWPReached;
bool mOOCReached;
uint32 mWPPauseTimer;
WaypointData const* mLastWP;
WaypointNode const* mLastWP;
uint32 mEscortNPCFlags;
uint32 GetWPCount() { return mWayPoints ? mWayPoints->size() : 0; }
uint32 GetWPCount() { return mWayPoints ? mWayPoints->Nodes.size() : 0; }
bool mCanRepeatPath;
bool mEvadeDisabled;
bool mCanAutoAttack;
@@ -253,6 +259,7 @@ private:
uint32 mDespawnTime;
uint32 mDespawnState;
void UpdateDespawn(const uint32 diff);
void UpdateFollow(const uint32 diff);
uint32 mEscortInvokerCheckTimer;
bool mJustReset;
@@ -2533,14 +2533,12 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
break;
}
if (!path || path->empty())
if (!path || path->Nodes.empty())
continue;
auto itrWp = path->find(1);
if (itrWp != path->end())
{
WaypointData const& wpData = itrWp->second;
float distToThisPath = creature->GetExactDistSq(wpData.x, wpData.y, wpData.z);
WaypointNode const& wpData = path->Nodes[0];
float distToThisPath = creature->GetExactDistSq(wpData.X, wpData.Y, wpData.Z);
if (distToThisPath < distanceToClosest)
{
@@ -2957,7 +2955,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (!IsPlayer(target))
continue;
target->ToPlayer()->SendCinematicStart(e.action.cinematic.entry);
target->ToPlayer()->GetCinematicMgr().StartCinematic(e.action.cinematic.entry);
}
break;
}
@@ -48,11 +48,6 @@ void SmartWaypointMgr::LoadFromDB()
{
uint32 oldMSTime = getMSTime();
for (auto itr : waypoint_map)
{
delete itr.second;
}
waypoint_map.clear();
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_SMARTAI_WP);
@@ -78,14 +73,15 @@ void SmartWaypointMgr::LoadFromDB()
float x = fields[2].Get<float>();
float y = fields[3].Get<float>();
float z = fields[4].Get<float>();
Optional<float> o;
std::optional<float> o;
if (!fields[5].IsNull())
o = fields[5].Get<float>();
uint32 delay = fields[6].Get<uint32>();
if (last_entry != entry)
{
waypoint_map[entry] = new WaypointPath();
waypoint_map[entry] = WaypointPath();
waypoint_map[entry].Id = entry;
last_id = 1;
count++;
}
@@ -94,15 +90,15 @@ void SmartWaypointMgr::LoadFromDB()
LOG_ERROR("sql.sql", "SmartWaypointMgr::LoadFromDB: Path entry {}, unexpected point id {}, expected {}.", entry, id, last_id);
last_id++;
WaypointData data;
data.id = id;
data.x = x;
data.y = y;
data.z = z;
data.orientation = o;
data.delay = delay;
data.move_type = WAYPOINT_MOVE_TYPE_MAX;
(*waypoint_map[entry]).emplace(id, data);
WaypointNode node;
node.Id = id;
node.X = x;
node.Y = y;
node.Z = z;
node.Orientation = o;
node.Delay = delay;
node.MoveType = WAYPOINT_MOVE_TYPE_MAX;
waypoint_map[entry].Nodes.push_back(std::move(node));
last_entry = entry;
total++;
@@ -112,14 +108,6 @@ void SmartWaypointMgr::LoadFromDB()
LOG_INFO("server.loading", " ");
}
SmartWaypointMgr::~SmartWaypointMgr()
{
for (auto itr : waypoint_map)
{
delete itr.second;
}
}
SmartAIMgr* SmartAIMgr::instance()
{
static SmartAIMgr instance;
@@ -2064,21 +2064,22 @@ class SmartWaypointMgr
{
SmartWaypointMgr() {}
public:
~SmartWaypointMgr();
~SmartWaypointMgr() = default;
static SmartWaypointMgr* instance();
void LoadFromDB();
WaypointPath* GetPath(uint32 id)
WaypointPath const* GetPath(uint32 id) const
{
if (waypoint_map.find(id) != waypoint_map.end())
return waypoint_map[id];
else return 0;
auto itr = waypoint_map.find(id);
if (itr != waypoint_map.end())
return &itr->second;
return nullptr;
}
private:
std::unordered_map<uint32, WaypointPath*> waypoint_map;
std::unordered_map<uint32, WaypointPath> waypoint_map;
};
// all events for a single entry
+41 -45
View File
@@ -31,6 +31,7 @@
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Transport.h"
#include "World.h"
#include "WorldPacket.h"
#include "WorldSessionMgr.h"
@@ -57,9 +58,6 @@ Battlefield::Battlefield() :
NoWarBattleTime(0),
RestartAfterCrash(0),
TimeForAcceptInvite(20),
KickDontAcceptTimer(1000),
KickAfkPlayersTimer(1000),
LastResurrectTimer(RESURRECTION_INTERVAL),
StartGroupingTimer(0),
StartGrouping(false)
{
@@ -132,6 +130,7 @@ void Battlefield::HandlePlayerLeaveZone(Player* player, uint32 /*zone*/)
cp->HandlePlayerLeave(player);
InvitedPlayers[player->GetTeamId()].erase(player->GetGUID());
PlayersInQueue[player->GetTeamId()].erase(player->GetGUID());
PlayersWillBeKick[player->GetTeamId()].erase(player->GetGUID());
Players[player->GetTeamId()].erase(player->GetGUID());
SendRemoveWorldStates(player);
@@ -147,7 +146,11 @@ bool Battlefield::Update(uint32 diff)
{
if (Timer <= diff)
{
if (!IsEnabled() || (!IsWarTime() && sWorldSessionMgr->GetActiveSessionCount() > 3500)) // if WG is disabled or there is more than 3500 connections, switch automatically
uint32 sessionLimit = sWorld->getIntConfig(CONFIG_WINTERGRASP_SKIP_BATTLE_SESSION_COUNT);
bool tooManySessions = sessionLimit && !IsWarTime()
&& sWorldSessionMgr->GetActiveSessionCount() > sessionLimit;
if (!IsEnabled() || tooManySessions)
{
Active = true;
EndBattle(false);
@@ -174,52 +177,16 @@ bool Battlefield::Update(uint32 diff)
SendUpdateWorldStates();
}
_scheduler.Update(diff);
bool objectiveChanged = false;
if (IsWarTime())
{
if (KickAfkPlayersTimer <= diff)
{
KickAfkPlayersTimer = 20000;
KickAfkPlayers();
}
else
KickAfkPlayersTimer -= diff;
// Kick players who chose not to accept invitation to the battle
if (KickDontAcceptTimer <= diff)
{
time_t now = GameTime::GetGameTime().count();
for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team)
for (PlayerTimerMap::value_type const& pair : InvitedPlayers[team])
if (pair.second <= now)
KickPlayerFromBattlefield(pair.first);
InvitePlayersInZoneToWar();
for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team)
for (PlayerTimerMap::value_type const& pair : PlayersWillBeKick[team])
if (pair.second <= now)
KickPlayerFromBattlefield(pair.first);
KickDontAcceptTimer = 5000;
}
else
KickDontAcceptTimer -= diff;
for (BfCapturePoint* cp : CapturePoints)
if (cp->Update(diff))
objectiveChanged = true;
}
if (LastResurrectTimer <= diff)
{
for (BfGraveyard* gy : GraveyardList)
if (gy)
gy->Resurrect();
LastResurrectTimer = RESURRECTION_INTERVAL;
}
else
LastResurrectTimer -= diff;
return objectiveChanged;
}
@@ -324,7 +291,8 @@ void Battlefield::KickAfkPlayers()
void Battlefield::KickPlayerFromBattlefield(ObjectGuid guid)
{
if (Player* player = ObjectAccessor::FindPlayer(guid))
if (player->GetZoneId() == GetZoneId() && !player->IsGameMaster())
if (player->GetZoneId() == GetZoneId() && !player->IsGameMaster()
&& !PlayersInWar[player->GetTeamId()].count(guid))
player->TeleportTo(KickPosition);
}
@@ -342,6 +310,30 @@ void Battlefield::StartBattle()
Timer = BattleTime;
Active = true;
// Schedule war-only periodic timers
_scheduler.Schedule(1s, BATTLEFIELD_TIMER_GROUP_WAR, [this](TaskContext context)
{
KickAfkPlayers();
context.Repeat(20s);
});
_scheduler.Schedule(1s, BATTLEFIELD_TIMER_GROUP_WAR, [this](TaskContext context)
{
time_t now = GameTime::GetGameTime().count();
for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team)
for (PlayerTimerMap::value_type const& pair : InvitedPlayers[team])
if (pair.second <= now)
KickPlayerFromBattlefield(pair.first);
InvitePlayersInZoneToWar();
for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team)
for (PlayerTimerMap::value_type const& pair : PlayersWillBeKick[team])
if (pair.second <= now)
KickPlayerFromBattlefield(pair.first);
context.Repeat(5s);
});
InvitePlayersInZoneToWar();
InvitePlayersInQueueToWar();
@@ -359,6 +351,8 @@ void Battlefield::EndBattle(bool endByTimer)
Active = false;
_scheduler.CancelGroup(BATTLEFIELD_TIMER_GROUP_WAR);
StartGrouping = false;
if (!endByTimer)
@@ -424,7 +418,7 @@ void Battlefield::PlayerAcceptInviteToWar(Player* player)
{
player->GetSession()->SendBfEntered(BattleId);
PlayersInWar[player->GetTeamId()].insert(player->GetGUID());
InvitedPlayers[player->GetTeamId(true)].erase(player->GetGUID());
InvitedPlayers[player->GetTeamId()].erase(player->GetGUID());
if (player->isAFK())
player->ToggleAFK();
@@ -626,7 +620,9 @@ void Battlefield::RemovePlayerFromResurrectQueue(ObjectGuid playerGuid)
void Battlefield::SendAreaSpiritHealerQueryOpcode(Player* player, ObjectGuid const& guid)
{
WorldPacket data(SMSG_AREA_SPIRIT_HEALER_TIME, 12);
uint32 time = LastResurrectTimer; // resurrect every 30 seconds
Milliseconds remaining = _scheduler.GetNextGroupOccurrence(BATTLEFIELD_TIMER_GROUP_RESURRECT);
uint32 time = static_cast<uint32>(std::clamp(remaining,
Milliseconds::zero(), Milliseconds(RESURRECTION_INTERVAL)).count());
data << guid << time;
ASSERT(player);
+10 -4
View File
@@ -22,6 +22,7 @@
#include "GameObject.h"
#include "ObjectAccessor.h"
#include "SharedDefines.h"
#include "TaskScheduler.h"
#include "ZoneScript.h"
enum BattlefieldTypes
@@ -55,6 +56,13 @@ enum BattlefieldSounds
constexpr auto BATTLEFIELD_OBJECTIVE_UPDATE_INTERVAL = 1000;
enum BattlefieldTimerGroups
{
BATTLEFIELD_TIMER_GROUP_RESURRECT = 1,
BATTLEFIELD_TIMER_GROUP_WAR = 2,
BATTLEFIELD_TIMER_GROUP_SAVE = 3,
};
const uint32 BattlefieldFactions[PVP_TEAMS_COUNT] =
{
1732, // Alliance
@@ -401,18 +409,16 @@ protected:
uint32 NoWarBattleTime; // Time between two battles
uint32 RestartAfterCrash; // Delay to restart Wintergrasp if the server crashed during a running battle
uint32 TimeForAcceptInvite;
uint32 KickDontAcceptTimer;
WorldLocation KickPosition; // Position where players are teleported if they switch to afk during the battle or if they don't accept invitation
uint32 KickAfkPlayersTimer; // Timer for check Afk in war
// Graveyard variables
GraveyardVect GraveyardList; // Vector which contains the different GY of the battle
uint32 LastResurrectTimer; // Timer for resurrect player every 30 sec
uint32 StartGroupingTimer; // Timer for invite players in area 15 minutes before start battle
bool StartGrouping; // bool for knowing if all players in area have been invited
TaskScheduler _scheduler;
GuidUnorderedSet Groups[PVP_TEAMS_COUNT]; // Contains different raid groups
std::vector<uint64> Data64;
@@ -77,8 +77,6 @@ bool BattlefieldWG::SetupBattlefield()
Data32.resize(BATTLEFIELD_WG_DATA_MAX);
SaveTimer = 60000;
// Init Graveyards
SetGraveyardNumber(BATTLEFIELD_WG_GRAVEYARD_MAX);
@@ -189,37 +187,31 @@ bool BattlefieldWG::SetupBattlefield()
}
UpdateCounterVehicle(true);
// Schedule always-running periodic timers
_scheduler.Schedule(Milliseconds(RESURRECTION_INTERVAL),
BATTLEFIELD_TIMER_GROUP_RESURRECT, [this](TaskContext context)
{
for (BfGraveyard* gy : GraveyardList)
if (gy)
gy->Resurrect();
context.Repeat();
});
_scheduler.Schedule(60s, BATTLEFIELD_TIMER_GROUP_SAVE, [this](TaskContext context)
{
sWorldState->setWorldState(WORLD_STATE_BATTLEFIELD_WG_ACTIVE, Active);
sWorldState->setWorldState(WORLD_STATE_BATTLEFIELD_WG_DEFENDER, DefenderTeam);
sWorldState->setWorldState(ClockWorldState[0], Timer);
context.Repeat();
});
return true;
}
bool BattlefieldWG::Update(uint32 diff)
{
bool result = Battlefield::Update(diff);
if (SaveTimer <= diff)
{
sWorldState->setWorldState(WORLD_STATE_BATTLEFIELD_WG_ACTIVE, Active);
sWorldState->setWorldState(WORLD_STATE_BATTLEFIELD_WG_DEFENDER, DefenderTeam);
sWorldState->setWorldState(ClockWorldState[0], Timer);
SaveTimer = 60 * IN_MILLISECONDS;
}
else
SaveTimer -= diff;
// Update Tenacity
if (IsWarTime())
{
if (TenacityUpdateTimer <= diff)
{
TenacityUpdateTimer = 10000;
if (!UpdateTenacityList.empty())
UpdateTenacity();
UpdateTenacityList.clear();
}
else
TenacityUpdateTimer -= diff;
}
return result;
return Battlefield::Update(diff);
}
void BattlefieldWG::OnBattleStart()
@@ -293,7 +285,14 @@ void BattlefieldWG::OnBattleStart()
// Xinef: reset tenacity counter
TenacityStack = 0;
TenacityUpdateTimer = 20000;
_scheduler.Schedule(20s, BATTLEFIELD_TIMER_GROUP_WAR, [this](TaskContext context)
{
if (!UpdateTenacityList.empty())
UpdateTenacity();
UpdateTenacityList.clear();
context.Repeat(10s);
});
if (sWorld->getBoolConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE))
ChatHandler(nullptr).SendWorldText(BATTLEFIELD_WG_WORLD_START_MESSAGE);
@@ -449,8 +449,6 @@ protected:
GuidUnorderedSet UpdateTenacityList;
int32 TenacityStack;
uint32 TenacityUpdateTimer;
uint32 SaveTimer;
ObjectGuid TitansRelic;
};
@@ -132,6 +132,8 @@ bool ArenaTeam::AddMember(ObjectGuid playerGuid)
if (sWorld->getIntConfig(CONFIG_ARENA_START_PERSONAL_RATING) > 0)
personalRating = sWorld->getIntConfig(CONFIG_ARENA_START_PERSONAL_RATING);
else if (sArenaSeasonMgr->GetCurrentSeason() < 6)
personalRating = 1500;
else if (GetRating() >= 1000)
personalRating = 1000;
+3
View File
@@ -427,6 +427,9 @@ bool CombatManager::UpdateOwnerCombatState() const
_owner->AtExitCombat();
if (!_owner->IsCreature())
_owner->AtDisengage();
if (Player* player = _owner->ToPlayer())
sScriptMgr->OnPlayerLeaveCombat(player);
}
if (Unit* master = _owner->GetCharmerOrOwner())
+5
View File
@@ -540,6 +540,11 @@ void ThreatManager::TauntUpdate()
// taunt aura update also re-evaluates all suppressed states (retail behavior)
EvaluateSuppressed(true);
// immediately reselect victim so taunt takes effect without waiting
// for the next THREAT_UPDATE_INTERVAL (1 s) timer tick
UpdateVictim();
_updateTimer = THREAT_UPDATE_INTERVAL;
}
void ThreatManager::SetTauntStateForTesting(
+2
View File
@@ -182,6 +182,8 @@ public:
// Test-only: directly set taunt state on a threat ref
// Uses uint32 to avoid incomplete-type issue with ThreatReference
void SetTauntStateForTesting(Unit* target, uint32 state);
// Immediately reselect victim (bypasses 1-second Update timer)
void UpdateVictimForTesting() { UpdateVictim(); }
///== REDIRECT SYSTEM ==
void RegisterRedirectThreat(uint32 spellId, ObjectGuid const& victim, uint32 pct);
+13 -2
View File
@@ -17,7 +17,6 @@
#include "DisableMgr.h"
#include "GameEventMgr.h"
#include "MMapFactory.h"
#include "ObjectMgr.h"
#include "OutdoorPvP.h"
#include "Player.h"
@@ -448,5 +447,17 @@ bool DisableMgr::IsPathfindingEnabled(Map const* map)
if (!map)
return false;
return !MMAP::MMapFactory::forbiddenMaps[map->GetId()] && (sWorld->getBoolConfig(CONFIG_ENABLE_MMAPS) ? true : map->IsBattlegroundOrArena());
// Still not an ideal solution but removes the extra awful forbiddenMaps hack
// int32 f[] = {616 /*EoE*/, 649 /*ToC25*/, 650 /*ToC5*/, -1};
switch (map->GetId())
{
case 616: // EoE
case 649: // ToC25
case 650: // ToC5
return false;
default:
break;
}
return (sWorld->getBoolConfig(CONFIG_ENABLE_MMAPS) ? true : map->IsBattlegroundOrArena());
}
+73 -28
View File
@@ -388,6 +388,33 @@ void Creature::SearchFormation()
}
}
bool Creature::IsFormationLeader() const
{
if (!m_formation)
return false;
return m_formation->GetLeader() == this;
}
void Creature::SignalFormationMovement()
{
if (!m_formation)
return;
if (!m_formation->GetLeader() || m_formation->GetLeader() != this)
return;
m_formation->LeaderStartedMoving();
}
bool Creature::IsFormationLeaderMoveAllowed() const
{
if (!m_formation)
return true;
return m_formation->CanLeaderStartMoving();
}
void Creature::RemoveCorpse(bool setSpawnTime, bool skipVisibility)
{
if (getDeathState() != DeathState::Corpse)
@@ -643,7 +670,7 @@ bool Creature::UpdateEntry(uint32 Entry, const CreatureData* data, bool changele
SetControlled(true, UNIT_STATE_ROOT);
UpdateMovementFlags();
LoadSpellTemplateImmunity();
LoadTemplateImmunities(cInfo->CreatureImmunitiesId);
if (updateAI)
{
@@ -2132,39 +2159,55 @@ void Creature::InitializeReactState()
SetReactState(REACT_AGGRESSIVE);
}
bool Creature::HasMechanicTemplateImmunity(uint32 mask) const
bool Creature::HasMechanicTemplateImmunity(uint64 mask) const
{
return !GetOwnerGUID().IsPlayer() && (GetCreatureTemplate()->MechanicImmuneMask & mask);
if (GetOwnerGUID().IsPlayer())
return false;
if (CreatureImmunities const* immunities = sSpellMgr->GetCreatureImmunities(_creatureImmunitiesId))
return (immunities->Mechanic.to_ullong() & mask) != 0;
// no custom immunity entry => no mechanic immunity
return false;
}
void Creature::LoadSpellTemplateImmunity()
void Creature::LoadTemplateImmunities(int32 creatureImmunitiesId)
{
// uint32 max used for "spell id", the immunity system will not perform SpellInfo checks against invalid spells
// used so we know which immunities were loaded from template
static uint32 const placeholderSpellId = std::numeric_limits<uint32>::max();
static uint32 constexpr placeholderSpellId = std::numeric_limits<uint32>::max();
// unapply template immunities (in case we're updating entry)
for (uint8 i = SPELL_SCHOOL_NORMAL; i <= SPELL_SCHOOL_ARCANE; ++i)
{
ApplySpellImmune(placeholderSpellId, IMMUNITY_SCHOOL, i, false);
}
// don't inherit immunities for hunter pets
if (GetOwnerGUID().IsPlayer() && IsHunterPet())
auto applyCreatureImmunities = [this](CreatureImmunities const* immunities, bool apply)
{
if (!immunities)
return;
}
for (std::size_t i = 0; i < immunities->School.size(); ++i)
if (immunities->School[i])
ApplySpellImmune(placeholderSpellId, IMMUNITY_SCHOOL, 1 << i, apply);
for (std::size_t i = 0; i < immunities->DispelType.size(); ++i)
if (immunities->DispelType[i])
ApplySpellImmune(placeholderSpellId, IMMUNITY_DISPEL, i, apply);
for (std::size_t i = 0; i < immunities->Mechanic.size(); ++i)
if (immunities->Mechanic[i])
ApplySpellImmune(placeholderSpellId, IMMUNITY_MECHANIC, i, apply);
for (SpellEffects effect : immunities->Effect)
ApplySpellImmune(placeholderSpellId, IMMUNITY_EFFECT, effect, apply);
for (AuraType aura : immunities->Aura)
ApplySpellImmune(placeholderSpellId, IMMUNITY_STATE, aura, apply);
};
if (uint8 mask = GetCreatureTemplate()->SpellSchoolImmuneMask)
// unapply old template if any
if (CreatureImmunities const* oldImmunities = sSpellMgr->GetCreatureImmunities(_creatureImmunitiesId))
applyCreatureImmunities(oldImmunities, false);
// apply requested immunities
if (CreatureImmunities const* newImmunities = sSpellMgr->GetCreatureImmunities(creatureImmunitiesId))
{
for (uint8 i = SPELL_SCHOOL_NORMAL; i <= SPELL_SCHOOL_ARCANE; ++i)
{
if (mask & (1 << i))
{
ApplySpellImmune(placeholderSpellId, IMMUNITY_SCHOOL, 1 << i, true);
}
}
_creatureImmunitiesId = creatureImmunitiesId;
applyCreatureImmunities(newImmunities, true);
}
else
_creatureImmunitiesId = 0;
}
bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell)
@@ -2179,11 +2222,13 @@ bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell)
// Xinef: this should exclude self casts...
// Spells that don't have effectMechanics.
if (spellInfo->Mechanic > MECHANIC_NONE && HasMechanicTemplateImmunity(1 << (spellInfo->Mechanic - 1)))
if (spellInfo->Mechanic > MECHANIC_NONE && HasMechanicTemplateImmunity(UI64LIT(1) << spellInfo->Mechanic))
return true;
// This check must be done instead of 'if (GetCreatureTemplate()->MechanicImmuneMask & (1 << (spellInfo->Mechanic - 1)))' for not break
// the check of mechanic immunity on DB (tested) because GetCreatureTemplate()->MechanicImmuneMask and m_spellImmune[IMMUNITY_MECHANIC] don't have same data.
// The above helper uses the creature_immunities table rather than a
// simple mask on creature_template. We can't rely on the old mask field
// (which has been removed) because it no longer exists and did not always
// match the runtime immunity set stored in m_spellImmune.
bool immunedToAllEffects = true;
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
if (spellInfo->Effects[i].IsEffect() && !IsImmunedToSpellEffect(spellInfo, i))
@@ -2197,16 +2242,16 @@ bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell)
return Unit::IsImmunedToSpell(spellInfo, spell);
}
bool Creature::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const
bool Creature::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Unit const* caster /*= nullptr*/) const
{
// Xinef: this should exclude self casts...
if (spellInfo->Effects[index].Mechanic > MECHANIC_NONE && HasMechanicTemplateImmunity(1 << (spellInfo->Effects[index].Mechanic - 1)))
if (spellInfo->Effects[index].Mechanic > MECHANIC_NONE && HasMechanicTemplateImmunity(UI64LIT(1) << spellInfo->Effects[index].Mechanic))
return true;
if (GetCreatureTemplate()->type == CREATURE_TYPE_MECHANICAL && spellInfo->Effects[index].Effect == SPELL_EFFECT_HEAL)
return true;
return Unit::IsImmunedToSpellEffect(spellInfo, index);
return Unit::IsImmunedToSpellEffect(spellInfo, index, caster);
}
SpellInfo const* Creature::reachWithSpellAttack(Unit* victim)
+14 -3
View File
@@ -105,12 +105,11 @@ public:
bool isCanInteractWithBattleMaster(Player* player, bool msg) const;
bool CanResetTalents(Player* player) const;
bool CanCreatureAttack(Unit const* victim, bool skipDistCheck = false) const;
void LoadSpellTemplateImmunity();
bool IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell = nullptr) override;
[[nodiscard]] bool HasMechanicTemplateImmunity(uint32 mask) const;
[[nodiscard]] bool HasMechanicTemplateImmunity(uint64 mask) const;
// redefine Unit::IsImmunedToSpell
bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const override;
bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Unit const* caster = nullptr) const override;
// redefine Unit::IsImmunedToSpellEffect
[[nodiscard]] bool isElite() const
{
@@ -186,6 +185,8 @@ public:
void UpdateAttackPowerAndDamage(bool ranged = false) override;
void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage, uint8 damageIndex) override;
void LoadTemplateImmunities(int32 creatureImmunitiesId);
void LoadSparringPct();
[[nodiscard]] float GetSparringPct() const { return _sparringPct; }
@@ -357,6 +358,14 @@ public:
[[nodiscard]] uint32 GetCurrentWaypointID() const { return m_waypointID; }
void UpdateWaypointID(uint32 wpID) { m_waypointID = wpID; }
// nodeId, pathId
std::pair<uint32, uint32> GetCurrentWaypointInfo() const { return _currentWaypointNodeInfo; }
void UpdateCurrentWaypointInfo(uint32 nodeId, uint32 pathId) { _currentWaypointNodeInfo = { nodeId, pathId }; }
bool IsFormationLeader() const;
void SignalFormationMovement();
bool IsFormationLeaderMoveAllowed() const;
void SearchFormation();
[[nodiscard]] CreatureGroup const* GetFormation() const { return m_formation; }
[[nodiscard]] CreatureGroup* GetFormation() { return m_formation; }
@@ -486,6 +495,7 @@ protected:
SpellSchoolMask m_meleeDamageSchoolMask;
uint32 m_originalEntry;
int32 _creatureImmunitiesId;
uint32 _gossipMenuId;
bool m_moveInLineOfSightDisabled;
@@ -517,6 +527,7 @@ private:
// WaypointMovementGenerator variable
uint32 m_waypointID;
uint32 m_path_id;
std::pair<uint32, uint32> _currentWaypointNodeInfo{0, 0};
// Formation variable
CreatureGroup* m_formation;
@@ -22,6 +22,7 @@
#include "DatabaseEnv.h"
#include "ItemTemplate.h"
#include "LootMgr.h"
#include "SpawnData.h"
#include "Unit.h"
#include <list>
@@ -202,7 +203,6 @@ struct CreatureTemplate
float speed_swim;
float speed_flight;
float detection_range; // Detection Range for Line of Sight aggro
float scale;
uint32 rank;
uint32 dmgschool;
float DamageModifier;
@@ -237,8 +237,7 @@ struct CreatureTemplate
bool RacialLeader;
uint32 movementId;
bool RegenHealth;
uint32 MechanicImmuneMask;
uint8 SpellSchoolImmuneMask;
int32 CreatureImmunitiesId;
uint32 flags_extra;
uint32 ScriptID;
WorldPacket queryData; // pussywizard
@@ -367,33 +366,24 @@ typedef std::unordered_map<uint8, EquipmentInfo> EquipmentInfoContainerInternal;
typedef std::unordered_map<uint32, EquipmentInfoContainerInternal> EquipmentInfoContainer;
// from `creature` table
struct CreatureData
struct CreatureData : public SpawnData
{
CreatureData() = default;
CreatureData() : SpawnData(SPAWN_TYPE_CREATURE) {}
ObjectGuid::LowType spawnId{ 0 }; // mod_playerbots
uint32 id1{0}; // entry in creature_template
uint32 id2{0}; // entry in creature_template
uint32 id3{0}; // entry in creature_template
uint16 mapid{0};
uint32 phaseMask{0};
uint32 displayid{0};
int8 equipmentId{0};
float posX{0.0f};
float posY{0.0f};
float posZ{0.0f};
float orientation{0.0f};
uint32 spawntimesecs{0};
float wander_distance{0.0f};
uint32 currentwaypoint{0};
uint32 curhealth{0};
uint32 curmana{0};
uint8 movementType{0};
uint8 spawnMask{0};
uint32 npcflag{0};
uint32 unit_flags{0}; // enum UnitFlags mask values
uint32 dynamicflags{0};
uint32 ScriptId;
bool dbData{true};
};
struct CreatureModelInfo
@@ -130,7 +130,7 @@ namespace Trainer
return nullptr;
}
bool Trainer::CanTeachSpell(Player const* player, Spell const* trainerSpell)
bool Trainer::CanTeachSpell(Player const* player, Spell const* trainerSpell) const
{
SpellState state = GetSpellState(player, trainerSpell);
if (state != SpellState::Available)
+1 -1
View File
@@ -70,7 +70,7 @@ namespace Trainer
[[nodiscard]] Spell const* GetSpell(uint32 spellId) const;
[[nodiscard]] std::vector<Spell> const& GetSpells() const { return _spells; }
void SendSpells(Creature* npc, Player* player, LocaleConstant locale) const;
bool CanTeachSpell(Player const* player, Spell const* trainerSpell);
bool CanTeachSpell(Player const* player, Spell const* trainerSpell) const;
void TeachSpell(Creature* npc, Player* player, uint32 spellId);
[[nodiscard]] Type GetTrainerType() const { return _type; }
@@ -1703,7 +1703,7 @@ void GameObject::Use(Unit* user)
Player* player = user->ToPlayer();
if (info->camera.cinematicId)
player->SendCinematicStart(info->camera.cinematicId);
player->GetCinematicMgr().StartCinematic(info->camera.cinematicId);
if (info->camera.eventID)
{
@@ -2142,7 +2142,32 @@ void GameObject::SendCustomAnim(uint32 anim)
SendMessageToSet(&data, true);
}
bool GameObject::IsInRange(float x, float y, float z, float radius) const
bool GameObject::IsInRange2d(float x, float y, float radius) const
{
GameObjectDisplayInfoEntry const* info = sGameObjectDisplayInfoStore.LookupEntry(m_goInfo->displayId);
if (!info)
return IsWithinDist2d(x, y, radius);
float sinA = std::sin(GetOrientation());
float cosA = cos(GetOrientation());
float dx = x - GetPositionX();
float dy = y - GetPositionY();
float dist = std::sqrt(dx * dx + dy * dy);
//! Check if the distance between the 2 objects is 0, can happen if both objects are on the same position.
//! The code below this check wont crash if dist is 0 because 0/0 in float operations is valid, and returns infinite
if (G3D::fuzzyEq(dist, 0.0f))
return true;
float scale = GetObjectScale();
float sinB = dx / dist;
float cosB = dy / dist;
dx = dist * (cosA * cosB + sinA * sinB);
dy = dist * (cosA * sinB - sinA * cosB);
return dx < (info->maxX * scale) + radius && dx >(info->minX * scale) - radius
&& dy < (info->maxY * scale) + radius && dy >(info->minY * scale) - radius;
}
bool GameObject::IsInRange3d(float x, float y, float z, float radius) const
{
GameObjectDisplayInfoEntry const* info = sGameObjectDisplayInfoStore.LookupEntry(m_goInfo->displayId);
if (!info)
@@ -2217,6 +2242,11 @@ void GameObject::UpdatePackedRotation()
m_packedRotation = z | (y << 21) | (x << 42);
}
bool GameObject::IsWithinSightRange(Position const& pos, float dist) const
{
return IsInRange2d(pos.GetPositionX(), pos.GetPositionY(), dist);
}
void GameObject::SetWorldRotation(G3D::Quat const& rot)
{
G3D::Quat rotation = rot;
@@ -284,7 +284,8 @@ public:
void CastSpell(Unit* target, uint32 spell);
void SendCustomAnim(uint32 anim);
[[nodiscard]] bool IsInRange(float x, float y, float z, float radius) const;
bool IsInRange2d(float x, float y, float radius) const;
bool IsInRange3d(float x, float y, float z, float radius) const;
void ModifyHealth(int32 change, Unit* attackerOrHealer = nullptr, uint32 spellId = 0);
void SetDestructibleBuildingModifyState(bool allow) { m_allowModifyDestructibleBuilding = allow; }
@@ -418,8 +419,11 @@ private:
{
//! Following check does check 3d distance
dist2compare += obj->GetObjectSize();
return IsInRange(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), dist2compare);
return IsInRange3d(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), dist2compare);
}
bool IsWithinSightRange(Position const& pos, float dist) const override;
GameObjectAI* m_AI;
bool m_saveStateOnDb = false;
@@ -19,6 +19,7 @@
#define GAMEOBJECTDATA_H
#include "SharedDefines.h"
#include "SpawnData.h"
#include <array>
#include <vector>
#include <string>
@@ -710,24 +711,15 @@ enum GOState
};
// from `gameobject`
struct GameObjectData
struct GameObjectData : public SpawnData
{
explicit GameObjectData() = default;
uint32 id{ 0 }; // entry in gamobject_template
uint16 mapid{ 0 };
uint32 phaseMask{ 0 };
float posX{ 0.0f };
float posY{ 0.0f };
float posZ{ 0.0f };
float orientation{ 0.0f };
GameObjectData() : SpawnData(SPAWN_TYPE_GAMEOBJECT) {}
uint32 id{0}; // entry in gameobject_template
G3D::Quat rotation;
int32 spawntimesecs{ 0 };
uint32 ScriptId;
uint32 animprogress{ 0 };
GOState go_state{ GO_STATE_ACTIVE };
uint8 spawnMask{ 0 };
uint8 artKit{ 0 };
bool dbData{ true };
int32 spawntimesecs{0};
uint32 animprogress{0};
GOState go_state{GO_STATE_ACTIVE};
uint8 artKit{0};
};
#endif // GameObjectData_h__
+11 -6
View File
@@ -1362,6 +1362,12 @@ bool WorldObject::IsWithinDist2d(const Position* pos, float dist) const
return IsInDist2d(pos, dist + GetObjectSize());
}
// Visibility always uses 2d checks, factors in self-object size already. Gameobjects will override this for custom calc
bool WorldObject::IsWithinSightRange(Position const& pos, float dist) const
{
return IsInDist2d(&pos, dist + GetObjectSize());
}
// use only if you will sure about placing both object at same map
bool WorldObject::IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D, bool incOwnRadius, bool incTargetRadius) const
{
@@ -1674,7 +1680,7 @@ float WorldObject::GetGridActivationRange() const
{
if (ToPlayer())
{
if (ToPlayer()->GetCinematicMgr()->IsOnCinematic())
if (ToPlayer()->GetCinematicMgr().IsOnCinematic())
{
return DEFAULT_VISIBILITY_INSTANCE;
}
@@ -1725,7 +1731,7 @@ float WorldObject::GetSightRange(WorldObject const* target) const
return VISIBILITY_DIST_WINTERGRASP;
else if (target->IsVisibilityOverridden())
return target->GetVisibilityOverrideDistance();
else if (ToPlayer()->GetCinematicMgr()->IsOnCinematic())
else if (ToPlayer()->GetCinematicMgr().IsOnCinematic())
return DEFAULT_VISIBILITY_INSTANCE;
else
return GetMap()->GetVisibilityRange();
@@ -1794,10 +1800,10 @@ bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth, boo
if (distanceCheck)
{
bool corpseCheck = false;
WorldObject const* viewpoint = this;
Position const* sightPosition = this;
if (Player const* thisPlayer = ToPlayer())
{
viewpoint = thisPlayer->GetSeer();
sightPosition = &thisPlayer->GetSightPosition();
if (Creature const* creature = obj->ToCreature())
{
@@ -1843,8 +1849,7 @@ bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth, boo
return false;
}
// Xinef: check reversely obj vs viewpoint, object could be a gameObject which overrides _IsWithinDist function to include gameobject size
if (!corpseCheck && !viewpoint->IsWithinDist(obj, GetSightRange(obj), false))
if (!corpseCheck && !obj->IsWithinSightRange(*sightPosition, GetSightRange(obj)))
return false;
}
+1
View File
@@ -543,6 +543,7 @@ public:
bool IsWithinDist3d(const Position* pos, float dist) const;
[[nodiscard]] bool IsWithinDist2d(float x, float y, float dist) const;
bool IsWithinDist2d(const Position* pos, float dist) const;
virtual bool IsWithinSightRange(Position const& pos, float dist) const;
// use only if you will sure about placing both object at same map
bool IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D = true, bool incOwnRadius = true, bool incTargetRadius = true) const;
bool IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D = true, bool incOwnRadius = true, bool incTargetRadius = true) const;
+1 -1
View File
@@ -491,7 +491,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
}
// must be after SetMinion (owner guid check)
//LoadTemplateImmunities();
LoadTemplateImmunities(0);
//LoadMechanicTemplateImmunity();
m_loading = false;
});
@@ -17,92 +17,84 @@
#include "CinematicMgr.h"
#include "M2Stores.h"
#include "MotionMaster.h"
#include "Player.h"
CinematicMgr::CinematicMgr(Player* playerref)
CinematicMgr::CinematicMgr(Player& player) : _player(player)
{
player = playerref;
m_cinematicDiff = 0;
m_lastCinematicCheck = 0;
m_activeCinematicCameraId = 0;
m_cinematicLength = 0;
m_cinematicCamera = nullptr;
m_remoteSightPosition = Position(0.0f, 0.0f, 0.0f);
m_CinematicObject = nullptr;
_cinematicDiff = 0;
_activeCinematicCameraId = 0;
_cinematicCamera = nullptr;
_remoteSightPosition = Position(0.0f, 0.0f, 0.0f);
_cinematicUpdateTimer.SetInterval(CINEMATIC_UPDATEDIFF);
}
CinematicMgr::~CinematicMgr()
void CinematicMgr::StartCinematic(uint32 const cinematicSequenceId)
{
if (m_cinematicCamera && m_activeCinematicCameraId)
EndCinematic();
_player.SendCinematicStart(cinematicSequenceId);
if (CinematicSequencesEntry const* sequence = sCinematicSequencesStore.LookupEntry(cinematicSequenceId))
SetActiveCinematicCamera(sequence->cinematicCamera);
}
void CinematicMgr::BeginCinematic()
void CinematicMgr::StartCinematicCamera()
{
// Sanity check for active camera set
if (m_activeCinematicCameraId == 0)
if (_activeCinematicCameraId == 0)
return;
if (std::vector<FlyByCamera> const* flyByCameras = GetFlyByCameras(m_activeCinematicCameraId))
if (std::vector<FlyByCamera> const* flyByCameras = GetFlyByCameras(_activeCinematicCameraId))
{
// Initialize diff, and set camera
m_cinematicDiff = 0;
m_cinematicCamera = flyByCameras;
_cinematicDiff = 0;
_cinematicUpdateTimer.Reset();
_cinematicCamera = flyByCameras;
auto camitr = m_cinematicCamera->begin();
if (camitr != m_cinematicCamera->end())
auto camitr = _cinematicCamera->begin();
if (camitr != _cinematicCamera->end())
{
Position const& pos = camitr->locations;
if (!pos.IsPositionValid())
return;
player->GetMap()->LoadGrid(pos.GetPositionX(), pos.GetPositionY());
m_CinematicObject = player->SummonCreature(VISUAL_WAYPOINT, pos.m_positionX, pos.m_positionY, pos.m_positionZ, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 120000);
if (m_CinematicObject)
{
m_CinematicObject->setActive(true);
player->SetViewpoint(m_CinematicObject, true);
}
// Get cinematic length
m_cinematicLength = flyByCameras->back().timeStamp;
_player.GetMap()->LoadGridsInRange(pos, MAX_VISIBILITY_DISTANCE);
_remoteSightPosition.Relocate(pos);
_player.UpdateVisibilityForPlayer();
}
}
}
void CinematicMgr::EndCinematic()
{
if (m_activeCinematicCameraId == 0)
if (_activeCinematicCameraId == 0)
return;
m_cinematicDiff = 0;
m_cinematicCamera = nullptr;
m_activeCinematicCameraId = 0;
if (m_CinematicObject)
{
if (WorldObject* vpObject = player->GetViewpoint())
if (vpObject == m_CinematicObject)
player->SetViewpoint(m_CinematicObject, false);
m_CinematicObject->AddObjectToRemoveList();
}
_cinematicDiff = 0;
_cinematicUpdateTimer.Reset();
_cinematicCamera = nullptr;
_activeCinematicCameraId = 0;
_player.UpdateVisibilityForPlayer();
}
void CinematicMgr::UpdateCinematicLocation(uint32 /*diff*/)
void CinematicMgr::UpdateCinematic(uint32 const diff)
{
if (m_activeCinematicCameraId == 0 || !m_cinematicCamera || m_cinematicCamera->size() == 0)
if (_activeCinematicCameraId == 0 || !_cinematicCamera || _cinematicCamera->empty())
return;
_cinematicDiff += diff;
_cinematicUpdateTimer.Update(diff);
if (!_cinematicUpdateTimer.Passed())
return;
_cinematicUpdateTimer.Reset();
Position lastPosition;
uint32 lastTimestamp = 0;
Position nextPosition;
uint32 nextTimestamp = 0;
// Obtain direction of travel
for (FlyByCamera cam : *m_cinematicCamera)
for (FlyByCamera const& cam : *_cinematicCamera)
{
if (cam.timeStamp > m_cinematicDiff)
if (cam.timeStamp > _cinematicDiff)
{
nextPosition.Relocate(cam.locations);
nextTimestamp = cam.timeStamp;
@@ -113,26 +105,25 @@ void CinematicMgr::UpdateCinematicLocation(uint32 /*diff*/)
}
float angle = lastPosition.GetAbsoluteAngle(&nextPosition);
angle -= lastPosition.GetOrientation();
if (angle < 0)
angle += 2 * float(M_PI);
angle = Position::NormalizeOrientation(angle);
// Look for position around 2 second ahead of us.
int32 workDiff = m_cinematicDiff;
int32 workDiff = _cinematicDiff;
// Modify result based on camera direction (Humans for example, have the camera point behind)
workDiff += static_cast<int32>(float(CINEMATIC_LOOKAHEAD) * cos(angle));
// Get an iterator to the last entry in the cameras, to make sure we don't go beyond the end
auto endItr = m_cinematicCamera->rbegin();
if (endItr != m_cinematicCamera->rend() && workDiff > static_cast<int32>(endItr->timeStamp))
auto endItr = _cinematicCamera->rbegin();
if (endItr != _cinematicCamera->rend() && workDiff > static_cast<int32>(endItr->timeStamp))
workDiff = endItr->timeStamp;
// Never try to go back in time before the start of cinematic!
if (workDiff < 0)
workDiff = m_cinematicDiff;
workDiff = _cinematicDiff;
// Obtain the previous and next waypoint based on timestamp
for (FlyByCamera cam : *m_cinematicCamera)
for (FlyByCamera const& cam : *_cinematicCamera)
{
if (static_cast<int32>(cam.timeStamp) >= workDiff)
{
@@ -157,12 +148,15 @@ void CinematicMgr::UpdateCinematicLocation(uint32 /*diff*/)
Position interPosition(lastPosition.m_positionX + (xDiff * (float(interDiff) / float(timeDiff))), lastPosition.m_positionY +
(yDiff * (float(interDiff) / float(timeDiff))), lastPosition.m_positionZ + (zDiff * (float(interDiff) / float(timeDiff))));
// Advance (at speed) to this position. The remote sight object is used
// to send update information to player in cinematic
if (m_CinematicObject && interPosition.IsPositionValid())
m_CinematicObject->MonsterMoveWithSpeed(interPosition.m_positionX, interPosition.m_positionY, interPosition.m_positionZ, 500.0f);
// Advance _remoteSightPosition to new position
if (interPosition.IsPositionValid())
{
_player.GetMap()->LoadGridsInRange(interPosition, MAX_VISIBILITY_DISTANCE);
_remoteSightPosition.Relocate(interPosition);
_player.UpdateVisibilityForPlayer();
}
// If we never received an end packet 10 seconds after the final timestamp then force an end
if (m_cinematicDiff > m_cinematicLength + 10 * IN_MILLISECONDS)
if (_cinematicDiff > _cinematicCamera->back().timeStamp + 10 * IN_MILLISECONDS)
EndCinematic();
}
+16 -20
View File
@@ -20,7 +20,7 @@
#include "Define.h"
#include "Position.h"
#include "TemporarySummon.h"
#include "Timer.h"
#include <vector>
constexpr auto CINEMATIC_UPDATEDIFF = 500;
@@ -31,31 +31,27 @@ struct FlyByCamera;
class AC_GAME_API CinematicMgr
{
friend class Player;
public:
explicit CinematicMgr(Player* playerref);
~CinematicMgr();
explicit CinematicMgr(Player& player);
~CinematicMgr() = default;
// Cinematic camera data and remote sight functions
uint32 GetActiveCinematicCamera() const { return m_activeCinematicCameraId; }
void SetActiveCinematicCamera(uint32 cinematicCameraId = 0) { m_activeCinematicCameraId = cinematicCameraId; }
bool IsOnCinematic() const { return (m_cinematicCamera != nullptr); }
void BeginCinematic();
void StartCinematic(uint32 const cinematicSequenceId);
uint32 GetActiveCinematicCamera() const { return _activeCinematicCameraId; }
void SetActiveCinematicCamera(uint32 cinematicCameraId = 0) { _activeCinematicCameraId = cinematicCameraId; }
bool IsOnCinematic() const { return (_cinematicCamera != nullptr); }
void StartCinematicCamera();
void EndCinematic();
void UpdateCinematicLocation(uint32 diff);
void UpdateCinematic(uint32 const diff);
Position const& GetRemoteSightPosition() const { return _remoteSightPosition; }
private:
// Remote location information
Player* player;
protected:
uint32 m_cinematicDiff;
uint32 m_lastCinematicCheck;
uint32 m_activeCinematicCameraId;
uint32 m_cinematicLength;
std::vector<FlyByCamera> const* m_cinematicCamera;
Position m_remoteSightPosition;
TempSummon* m_CinematicObject;
Player& _player;
uint32 _cinematicDiff;
uint32 _activeCinematicCameraId;
std::vector<FlyByCamera> const* _cinematicCamera;
Position _remoteSightPosition;
IntervalTimer _cinematicUpdateTimer;
};
#endif
+53 -16
View File
@@ -154,7 +154,7 @@ static uint32 copseReclaimDelay[MAX_DEATH_COUNT] = { 30, 60, 120 };
#ifdef _MSC_VER
#pragma warning(disable:4355)
#endif
Player::Player(WorldSession* session): Unit(), m_mover(this)
Player::Player(WorldSession* session): Unit(), m_mover(this), _cinematicMgr(*this)
{
#ifdef _MSC_VER
#pragma warning(default:4355)
@@ -395,8 +395,6 @@ Player::Player(WorldSession* session): Unit(), m_mover(this)
m_creationTime = 0s;
_cinematicMgr = new CinematicMgr(this);
m_achievementMgr = new AchievementMgr(this);
m_reputationMgr = new ReputationMgr(this);
@@ -462,7 +460,6 @@ Player::~Player()
delete m_runes;
delete m_achievementMgr;
delete m_reputationMgr;
delete _cinematicMgr;
sWorldSessionMgr->DecreasePlayerCount();
@@ -772,7 +769,9 @@ bool Player::IsImmuneToEnvironmentalDamage()
uint32 Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
{
if (IsImmuneToEnvironmentalDamage())
// DAMAGE_FALL_TO_VOID bypasses all immunities (e.g. Divine Shield) to prevent
// players from being stuck infinitely falling below the map
if (type != DAMAGE_FALL_TO_VOID && IsImmuneToEnvironmentalDamage())
return 0;
// Absorb, resist some environmental damage type
@@ -5697,10 +5696,6 @@ void Player::SendCinematicStart(uint32 CinematicSequenceId) const
WorldPacket data(SMSG_TRIGGER_CINEMATIC, 4);
data << uint32(CinematicSequenceId);
SendDirectMessage(&data);
if (CinematicSequencesEntry const* sequence = sCinematicSequencesStore.LookupEntry(CinematicSequenceId))
{
_cinematicMgr->SetActiveCinematicCamera(sequence->cinematicCamera);
}
}
void Player::SendMovieStart(uint32 MovieId)
@@ -10457,7 +10452,7 @@ void Player::SendTaxiNodeStatusMultiple()
if (!creature->HasNpcFlag(UNIT_NPC_FLAG_FLIGHTMASTER))
return;
uint32 nearestNode = sObjectMgr->GetNearestTaxiNode(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetMapId(), GetTeamId());
uint32 nearestNode = sObjectMgr->GetNearestTaxiNode(*creature, GetTeamId(true));
if (!nearestNode)
return;
@@ -12515,18 +12510,49 @@ bool Player::HasItemFitToSpellRequirements(SpellInfo const* spellInfo, Item cons
if (Item* item = GetUseableItemByPos(INVENTORY_SLOT_BAG_0, i))
if (item != ignoreItem && item->IsFitToSpellRequirements(spellInfo))
return true;
// Keep active non-passive auras (e.g. Bladestorm) when disarmed
if (!spellInfo->IsPassive())
{
bool hasWeaponInSlot = false;
for (uint8 i = EQUIPMENT_SLOT_MAINHAND; i < EQUIPMENT_SLOT_TABARD; ++i)
if (Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
if (item != ignoreItem && item->IsFitToSpellRequirements(spellInfo))
{
hasWeaponInSlot = true;
break;
}
if (!hasWeaponInSlot)
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
if (spellInfo->Effects[i].IsAura())
return true;
}
break;
}
case ITEM_CLASS_ARMOR:
{
// tabard not have dependent spells
for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_MAINHAND; ++i)
if (Item* item = GetUseableItemByPos(INVENTORY_SLOT_BAG_0, i))
// most used check: shield only
if (spellInfo->EquippedItemSubClassMask & (1 << ITEM_SUBCLASS_ARMOR_SHIELD))
{
if (Item* item = GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND))
if (item != ignoreItem && item->IsFitToSpellRequirements(spellInfo))
return true;
// shields can be equipped to offhand slot
if (Item* item = GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND))
// Keep active non-passive auras (e.g. Shield Wall) when disarmed
Item* offhand = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
if (!spellInfo->IsPassive() && offhand && offhand != ignoreItem)
{
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
if (spellInfo->Effects[i].IsAura())
return true;
}
}
// tabard not have dependent spells
for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_MAINHAND; ++i)
if (Item* item = GetUseableItemByPos(INVENTORY_SLOT_BAG_0, i))
if (item != ignoreItem && item->IsFitToSpellRequirements(spellInfo))
return true;
@@ -13210,6 +13236,14 @@ WorldObject* Player::GetViewpoint() const
return nullptr;
}
Position const& Player::GetSightPosition() const
{
if (_cinematicMgr.IsOnCinematic())
return _cinematicMgr.GetRemoteSightPosition();
return *m_seer;
}
bool Player::CanUseBattlegroundObject(GameObject* gameobject) const
{
// It is possible to call this method will a nullptr pointer, only skipping faction check.
@@ -16279,7 +16313,10 @@ bool Player::IsWorldObjectOutOfSightRange(WorldObject const* target) const
}
// Check if out of range
return !m_seer->IsWithinDist(target, GetSightRange(target), false);
if (!target->IsWithinSightRange(GetSightPosition(), GetSightRange(target)))
return true;
return false;
}
std::string Player::GetPlayerName()
+4 -2
View File
@@ -1394,7 +1394,8 @@ public:
[[nodiscard]] TradeData* GetTradeData() const { return m_trade; }
void TradeCancel(bool sendback, TradeStatus status = TRADE_STATUS_TRADE_CANCELED);
CinematicMgr* GetCinematicMgr() const { return _cinematicMgr; }
CinematicMgr& GetCinematicMgr() { return _cinematicMgr; }
CinematicMgr const& GetCinematicMgr() const { return _cinematicMgr; }
void UpdateEnchantTime(uint32 time);
void UpdateSoulboundTradeItems();
@@ -2388,6 +2389,7 @@ public:
WorldObject* GetSeer() const { return m_seer; }
void SetViewpoint(WorldObject* target, bool apply);
[[nodiscard]] WorldObject* GetViewpoint() const;
Position const& GetSightPosition() const;
void StopCastingCharm(Aura* except = nullptr);
void StopCastingBindSight(Aura* except = nullptr);
@@ -2984,7 +2986,7 @@ private:
Item* _StoreItem(uint16 pos, Item* pItem, uint32 count, bool clone, bool update);
Item* _LoadItem(CharacterDatabaseTransaction trans, uint32 zoneId, uint32 timeDiff, Field* fields);
CinematicMgr* _cinematicMgr;
CinematicMgr _cinematicMgr;
typedef GuidSet RefundableItemsSet;
RefundableItemsSet m_refundableItems;
@@ -68,14 +68,8 @@ void Player::Update(uint32 p_time)
m_nextMailDelivereTime = time_t(0);
}
// Update cinematic location, if 500ms have passed and we're doing a
// cinematic now.
_cinematicMgr->m_cinematicDiff += p_time;
if (_cinematicMgr->m_cinematicCamera && _cinematicMgr->m_activeCinematicCameraId && GetMSTimeDiffToNow(_cinematicMgr->m_lastCinematicCheck) > CINEMATIC_UPDATEDIFF)
{
_cinematicMgr->m_lastCinematicCheck = getMSTime();
_cinematicMgr->UpdateCinematicLocation(p_time);
}
// Update cinematic camera (if needed)
_cinematicMgr.UpdateCinematic(p_time);
// used to implement delayed far teleports
SetMustDelayTeleport(true);
@@ -1609,8 +1603,8 @@ void Player::UpdateVisibilityForPlayer(bool mapChange)
m_seer = this;
Acore::VisibleNotifier notifier(*this, mapChange);
Cell::VisitObjects(m_seer, notifier, GetSightRange());
Cell::VisitFarVisibleObjects(m_seer, notifier, VISIBILITY_DISTANCE_GIGANTIC);
Cell::VisitObjects(GetSightPosition().GetPositionX(), GetSightPosition().GetPositionY(), GetMap(), notifier, GetSightRange());
Cell::VisitFarVisibleObjects(GetSightPosition().GetPositionX(), GetSightPosition().GetPositionY(), GetMap(), notifier, VISIBILITY_DISTANCE_GIGANTIC);
notifier.SendToSelf();
if (mapChange)
+2 -2
View File
@@ -179,7 +179,7 @@ void Totem::UnSummon(Milliseconds msTime)
AddObjectToRemoveList();
}
bool Totem::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const
bool Totem::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Unit const* caster /*= nullptr*/) const
{
// xinef: immune to all positive spells, except of stoneclaw totem absorb, sentry totem bind sight and intervene
// totems positive spells have unit_caster target
@@ -209,5 +209,5 @@ bool Totem::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) con
break;
}
return Creature::IsImmunedToSpellEffect(spellInfo, index);
return Creature::IsImmunedToSpellEffect(spellInfo, index, caster);
}
+1 -1
View File
@@ -70,7 +70,7 @@ public:
void UpdateAttackPowerAndDamage(bool /*ranged*/) override {}
void UpdateDamagePhysical(WeaponAttackType /*attType*/) override {}
bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const override;
bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Unit const* caster = nullptr) const override;
protected:
TotemType m_type;
+268 -224
View File
@@ -72,6 +72,7 @@
#include "Vehicle.h"
#include "World.h"
#include "WorldPacket.h"
#include <algorithm>
#include <cmath>
float baseMoveSpeed[MAX_MOVE_TYPE] =
@@ -125,6 +126,28 @@ DamageInfo::DamageInfo(CalcDamageInfo const& dmgInfo, uint8 damageIndex)
m_damageType(DIRECT_DAMAGE), m_attackType(dmgInfo.attackType), m_absorb(dmgInfo.damages[damageIndex].absorb), m_resist(dmgInfo.damages[damageIndex].resist), m_block(dmgInfo.blocked_amount),
m_cleanDamage(dmgInfo.cleanDamage), m_hitMask(0)
{
switch (dmgInfo.TargetState)
{
case VICTIMSTATE_IS_IMMUNE:
m_hitMask |= PROC_HIT_IMMUNE;
break;
case VICTIMSTATE_BLOCKS:
m_hitMask |= PROC_HIT_FULL_BLOCK;
break;
}
if (dmgInfo.HitInfo & (HITINFO_PARTIAL_ABSORB | HITINFO_FULL_ABSORB))
m_hitMask |= PROC_HIT_ABSORB;
if (dmgInfo.HitInfo & HITINFO_FULL_RESIST)
m_hitMask |= PROC_HIT_FULL_RESIST;
if (m_block)
m_hitMask |= PROC_HIT_BLOCK;
bool const damageNullified = (dmgInfo.HitInfo & (HITINFO_FULL_ABSORB | HITINFO_FULL_RESIST)) != 0
|| (m_hitMask & (PROC_HIT_IMMUNE | PROC_HIT_FULL_BLOCK)) != 0;
switch (dmgInfo.hitOutCome)
{
case MELEE_HIT_MISS:
@@ -140,25 +163,19 @@ DamageInfo::DamageInfo(CalcDamageInfo const& dmgInfo, uint8 damageIndex)
m_hitMask |= PROC_HIT_EVADE;
break;
case MELEE_HIT_BLOCK:
m_hitMask |= PROC_HIT_BLOCK;
[[fallthrough]];
case MELEE_HIT_CRUSHING:
case MELEE_HIT_GLANCING:
case MELEE_HIT_NORMAL:
if (!damageNullified)
m_hitMask |= PROC_HIT_NORMAL;
break;
case MELEE_HIT_CRIT:
if (!damageNullified)
m_hitMask |= PROC_HIT_CRITICAL;
break;
default:
break;
}
if (dmgInfo.damages[damageIndex].absorb)
m_hitMask |= PROC_HIT_ABSORB;
if (dmgInfo.blocked_amount)
m_hitMask |= (dmgInfo.damages[damageIndex].damage == dmgInfo.blocked_amount) ? PROC_HIT_FULL_BLOCK : PROC_HIT_BLOCK;
}
DamageInfo::DamageInfo(SpellNonMeleeDamage const& spellNonMeleeDamage, DamageEffectType damageType, WeaponAttackType attackType, uint32 hitMask)
@@ -372,9 +389,6 @@ Unit::Unit() : WorldObject(),
m_transform = 0;
m_canModifyStats = false;
for (uint8 i = 0; i < MAX_SPELL_IMMUNITY; ++i)
m_spellImmune[i].clear();
for (uint8 i = 0; i < UNIT_MOD_END; ++i)
{
m_auraFlatModifiersGroup[i][BASE_VALUE] = 0.0f;
@@ -891,6 +905,48 @@ bool Unit::HasAuraTypeWithFamilyFlags(AuraType auraType, uint32 familyName, uint
return false;
}
bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, uint32 effectMask, Unit const* caster /*= nullptr*/)
{
if (!spellInfo)
return false;
bool immuneToAllEffects = true;
bool hasCheckedEffect = false;
for (uint8 i = EFFECT_0; i < MAX_SPELL_EFFECTS; ++i)
{
if (!(effectMask & (1u << i)))
continue;
if (!spellInfo->Effects[i].IsEffect())
continue;
hasCheckedEffect = true;
if (IsImmunedToSpellEffect(spellInfo, i, caster))
{
if (spellInfo->HasAttribute(SPELL_ATTR4_NO_PARTIAL_IMMUNITY))
return true;
continue;
}
immuneToAllEffects = false;
break;
}
if (hasCheckedEffect && immuneToAllEffects)
return true;
if (!spellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES))
{
if (IsImmunedToSchool(spellInfo))
return true;
}
return false;
}
bool Unit::HasBreakableByDamageAuraType(AuraType type, uint32 excludeAura) const
{
AuraEffectList const& auras = GetAuraEffectsByType(type);
@@ -2075,7 +2131,7 @@ void Unit::DealDamageShieldDamage(Unit* victim)
}
// ...or immuned
if (IsImmunedToDamageOrSchool(i_spellProto))
if (IsImmunedToDamage(victim, i_spellProto))
{
victim->SendSpellDamageImmune(this, i_spellProto->Id);
continue;
@@ -3203,7 +3259,7 @@ void Unit::SendMeleeAttackStop(Unit* victim)
bool Unit::isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttackType attackType)
{
// These spells can't be blocked
if (spellProto && spellProto->HasAttribute(SPELL_ATTR0_NO_ACTIVE_DEFENSE))
if (spellProto && (spellProto->HasAttribute(SPELL_ATTR0_NO_ACTIVE_DEFENSE) || spellProto->HasAttribute(SPELL_ATTR3_ALWAYS_HIT)))
return false;
if (victim->HasIgnoreHitDirectionAura() || victim->HasInArc(M_PI, this))
@@ -3571,6 +3627,9 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spellInfo
// Resist
SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spell, bool CanReflect)
{
if (spell->HasAttribute(SPELL_ATTR3_ALWAYS_HIT))
return SPELL_MISS_NONE;
// Check for immune
if (victim->IsImmunedToSpell(spell))
return SPELL_MISS_IMMUNE;
@@ -3581,11 +3640,6 @@ SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spell, bool Ca
&& (!IsHostileTo(victim))) // prevent from affecting enemy by "positive" spell
return SPELL_MISS_NONE;
// Check for immune
// xinef: check for school immunity only
if (victim->IsImmunedToSchool(spell))
return SPELL_MISS_IMMUNE;
if (this == victim)
return SPELL_MISS_NONE;
@@ -3650,13 +3704,17 @@ SpellMissInfo Unit::SpellHitResult(Unit* victim, Spell const* spell, bool CanRef
return SPELL_MISS_NONE;
}
// Check for immune
// xinef: check for school immunity only
if (victim->IsImmunedToSchool(spell))
// Check for immune to spell effects (includes school, mechanics, state, dispel immunities)
if (victim->IsImmunedToSpell(spellInfo, MAX_EFFECT_MASK, this))
{
return SPELL_MISS_IMMUNE;
}
// Damage immunity is only checked if the spell has damage effects, this immunity must not prevent aura apply
// returns SPELL_MISS_IMMUNE in that case, for other spells, the SMSG_SPELL_GO must show hit
if (spellInfo->HasOnlyDamageEffects() && victim->IsImmunedToDamage(this, spellInfo))
return SPELL_MISS_IMMUNE;
if (this == victim)
{
return SPELL_MISS_NONE;
@@ -5447,7 +5505,7 @@ void Unit::RemoveMovementImpairingAuras(bool withRoot)
}
}
void Unit::RemoveAurasWithMechanic(uint32 mechanic_mask, AuraRemoveMode removemode, uint32 except)
void Unit::RemoveAurasWithMechanic(uint64 mechanic_mask, AuraRemoveMode removemode, uint32 except)
{
for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
{
@@ -5466,7 +5524,7 @@ void Unit::RemoveAurasWithMechanic(uint32 mechanic_mask, AuraRemoveMode removemo
void Unit::RemoveAurasByShapeShift()
{
uint32 mechanic_mask = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT);
uint64 mechanic_mask = (UI64LIT(1) << MECHANIC_SNARE) | (UI64LIT(1) << MECHANIC_ROOT);
for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
{
Aura const* aura = iter->second->GetBase();
@@ -6015,17 +6073,17 @@ bool Unit::HasNegativeAuraWithAttribute(uint32 flag, ObjectGuid guid)
return false;
}
bool Unit::HasAuraWithMechanic(uint32 mechanicMask) const
bool Unit::HasAuraWithMechanic(uint64 mechanicMask) const
{
for (AuraApplicationMap::const_iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end(); ++iter)
{
SpellInfo const* spellInfo = iter->second->GetBase()->GetSpellInfo();
if (spellInfo->Mechanic && (mechanicMask & (1 << spellInfo->Mechanic)))
if (spellInfo->Mechanic && (mechanicMask & (UI64LIT(1) << spellInfo->Mechanic)))
return true;
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
if (iter->second->HasEffect(i) && spellInfo->Effects[i].Effect && spellInfo->Effects[i].Mechanic)
if (mechanicMask & (1 << spellInfo->Effects[i].Mechanic))
if (mechanicMask & (UI64LIT(1) << spellInfo->Effects[i].Mechanic))
return true;
}
@@ -7339,10 +7397,12 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
// set position before any AI calls/assistance
//if (IsCreature())
// ToCreature()->SetCombatStartPosition(GetPositionX(), GetPositionY(), GetPositionZ());
if (creature && !IsControlledByPlayer())
if (creature)
{
EngageWithTarget(victim);
if (!IsControlledByPlayer())
{
creature->SendAIReaction(AI_REACTION_HOSTILE);
/// @todo: Implement aggro range, detection range and assistance range templates
@@ -7353,6 +7413,7 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
}
}
// delay offhand weapon attack by 50% of the base attack time
if (HasOffhandWeaponForAttack() && isAttackReady(OFF_ATTACK))
@@ -8836,7 +8897,7 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui
});
}
if (uint32 mechanicMask = spellProto->GetAllEffectsMechanicMask())
if (uint64 mechanicMask = spellProto->GetAllEffectsMechanicMask())
{
int32 modifierMax = 0;
int32 modifierMin = 0;
@@ -8851,7 +8912,7 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui
if (!caster || caster->GetGUID() != (*i)->GetCasterGUID())
continue;
if (mechanicMask & uint32(1 << (*i)->GetMiscValue()))
if (mechanicMask & uint64(UI64LIT(1) << (*i)->GetMiscValue()))
{
if ((*i)->GetAmount() > 0)
{
@@ -9742,107 +9803,90 @@ int32 Unit::SpellBaseHealingBonusDone(SpellSchoolMask schoolMask)
return AdvertisedBenefit;
}
bool Unit::IsImmunedToDamage(SpellSchoolMask meleeSchoolMask) const
uint32 Unit::GetDamageImmunityMask() const
{
if (meleeSchoolMask == SPELL_SCHOOL_MASK_NONE)
{
return false;
}
// If m_immuneToDamage type contain magic, IMMUNE damage.
SpellImmuneList const& damageList = m_spellImmune[IMMUNITY_DAMAGE];
for (SpellImmuneList::const_iterator itr = damageList.begin(); itr != damageList.end(); ++itr)
if ((itr->type & meleeSchoolMask) == meleeSchoolMask)
return true;
return false;
uint32 mask = 0;
SpellImmuneContainer const& damageList = m_spellImmune[IMMUNITY_DAMAGE];
for (auto const& [immunitySchoolMask, _] : damageList)
mask |= immunitySchoolMask;
return mask;
}
bool Unit::IsImmunedToDamage(SpellInfo const* spellInfo) const
bool Unit::IsImmunedToDamage(SpellSchoolMask schoolMask) const
{
if (schoolMask == SPELL_SCHOOL_MASK_NONE)
return false;
// If m_immuneToSchool type contains all requested schools, IMMUNE damage.
SpellImmuneContainer const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
for (auto const& itr : schoolList)
if (IsImmuneMaskFully(SpellSchoolMask(itr.first), schoolMask))
return true;
// If m_immuneToDamage type contains all requested schools, IMMUNE damage.
SpellImmuneContainer const& damageList = m_spellImmune[IMMUNITY_DAMAGE];
return std::ranges::any_of(damageList, [schoolMask](auto const& immune)
{
return Unit::IsImmuneMaskFully(SpellSchoolMask(immune.first), schoolMask);
});
}
bool Unit::IsImmunedToDamage(Unit const* caster, SpellInfo const* spellInfo) const
{
if (!spellInfo)
{
return false;
}
if (spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES) && !HasSpiritOfRedemptionAura())
{
if (spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES) || spellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES))
return false;
}
if (spellInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS) || spellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES))
{
return false;
}
uint32 schoolMask = spellInfo->GetSchoolMask();
SpellSchoolMask schoolMask = SpellSchoolMask(spellInfo->GetSchoolMask());
if (schoolMask == SPELL_SCHOOL_MASK_NONE)
{
return false;
auto hasImmunity = [&](SpellImmuneContainer const& container)
{
uint32 schoolImmunityMask = 0;
for (auto const& [immunitySchoolMask, immunityAuraId] : container)
{
SpellInfo const* immuneAuraInfo = sSpellMgr->GetSpellInfo(immunityAuraId);
if (immuneAuraInfo && !immuneAuraInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS) && caster && caster->IsFriendlyTo(this))
continue;
if (immuneAuraInfo && spellInfo->CanPierceImmuneAura(immuneAuraInfo))
continue;
schoolImmunityMask |= immunitySchoolMask;
}
// If m_immuneToDamage type contain magic, IMMUNE damage.
SpellImmuneList const& damageList = m_spellImmune[IMMUNITY_DAMAGE];
for (SpellImmuneList::const_iterator itr = damageList.begin(); itr != damageList.end(); ++itr)
if ((itr->type & schoolMask) == schoolMask)
return true;
return false;
}
bool Unit::IsImmunedToDamage(Spell const* spell) const
{
SpellInfo const* spellInfo = spell->GetSpellInfo();
if (!spellInfo)
{
return false;
}
if (spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES) && !HasSpiritOfRedemptionAura())
{
return false;
}
if (spellInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS) || spellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES))
{
return false;
}
uint32 schoolMask = spell->GetSpellSchoolMask();
if (schoolMask == SPELL_SCHOOL_MASK_NONE)
{
return false;
}
// If m_immuneToDamage type contain magic, IMMUNE damage.
SpellImmuneList const& damageList = m_spellImmune[IMMUNITY_DAMAGE];
for (SpellImmuneList::const_iterator itr = damageList.begin(); itr != damageList.end(); ++itr)
{
if ((itr->type & schoolMask) == schoolMask)
{
return true;
}
}
return false;
}
bool Unit::IsImmunedToSchool(SpellSchoolMask meleeSchoolMask) const
{
if (meleeSchoolMask == SPELL_SCHOOL_MASK_NONE)
{
return false;
}
// We need to be immune to all types
return (schoolImmunityMask & schoolMask) == schoolMask;
};
// If m_immuneToSchool type contain this school type, IMMUNE damage.
SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
if ((itr->type & meleeSchoolMask) == meleeSchoolMask)
if (hasImmunity(m_spellImmune[IMMUNITY_SCHOOL]))
return true;
// If m_immuneToDamage type contain magic, IMMUNE damage.
if (hasImmunity(m_spellImmune[IMMUNITY_DAMAGE]))
return true;
return false;
}
bool Unit::IsImmunedToSchool(SpellSchoolMask schoolMask) const
{
if (schoolMask == SPELL_SCHOOL_MASK_NONE)
return false;
// Check IMMUNITY_SCHOOL: returns true if ALL schools in the mask are covered by at least one immunity
// (e.g., Anti-Magic Shell provides school immunity to all magic schools)
SpellImmuneContainer const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
return std::ranges::any_of(schoolList, [schoolMask](auto const& immune)
{
return (immune.first & schoolMask) == schoolMask;
});
}
bool Unit::IsImmunedToSchool(SpellInfo const* spellInfo) const
{
if (spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES) && !HasSpiritOfRedemptionAura())
@@ -9856,10 +9900,10 @@ bool Unit::IsImmunedToSchool(SpellInfo const* spellInfo) const
if (spellInfo->Id != 42292 && spellInfo->Id != 59752 && spellInfo->Id != 19574 && spellInfo->Id != 34471)
{
// If m_immuneToSchool type contain this school type, IMMUNE damage.
SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
if ((itr->type & schoolMask) == schoolMask && !spellInfo->CanPierceImmuneAura(sSpellMgr->GetSpellInfo(itr->spellId)))
// Check IMMUNITY_SCHOOL: returns true if ALL schools in the mask are covered and spell can't pierce
SpellImmuneContainer const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
for (auto itr = schoolList.begin(); itr != schoolList.end(); ++itr)
if ((itr->first & schoolMask) == schoolMask && !spellInfo->CanPierceImmuneAura(sSpellMgr->GetSpellInfo(itr->second)))
return true;
}
@@ -9882,11 +9926,11 @@ bool Unit::IsImmunedToSchool(Spell const* spell) const
if (spellInfo->Id != 42292 && spellInfo->Id != 59752 && spellInfo->Id != 19574 && spellInfo->Id != 34471)
{
// If m_immuneToSchool type contain this school type, IMMUNE damage.
SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
// Check IMMUNITY_SCHOOL: returns true if ALL schools in the mask are covered and spell can't pierce
SpellImmuneContainer const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
for (auto itr = schoolList.begin(); itr != schoolList.end(); ++itr)
{
if ((itr->type & schoolMask) == schoolMask && !spellInfo->CanPierceImmuneAura(sSpellMgr->GetSpellInfo(itr->spellId)))
if ((itr->first & schoolMask) == schoolMask && !spellInfo->CanPierceImmuneAura(sSpellMgr->GetSpellInfo(itr->second)))
{
return true;
}
@@ -9896,19 +9940,49 @@ bool Unit::IsImmunedToSchool(Spell const* spell) const
return false;
}
bool Unit::IsImmunedToDamageOrSchool(SpellSchoolMask meleeSchoolMask) const
bool Unit::IsImmunedToDamageOrSchool(SpellSchoolMask schoolMask) const
{
if (meleeSchoolMask == SPELL_SCHOOL_MASK_NONE)
if (schoolMask == SPELL_SCHOOL_MASK_NONE)
{
return false;
}
return IsImmunedToDamage(meleeSchoolMask) || IsImmunedToSchool(meleeSchoolMask);
return IsImmunedToDamage(schoolMask) || IsImmunedToSchool(schoolMask);
}
bool Unit::IsImmunedToDamageOrSchool(SpellInfo const* spellInfo) const
bool Unit::IsImmunedToAuraPeriodicTick(Unit const* caster, SpellInfo const* spellInfo) const
{
return IsImmunedToDamage(spellInfo) || IsImmunedToSchool(spellInfo);
if (!spellInfo)
return false;
if (spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES) || spellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES))
return false;
SpellSchoolMask schoolMask = SpellSchoolMask(spellInfo->GetSchoolMask());
if (schoolMask == SPELL_SCHOOL_MASK_NONE)
return false;
auto hasImmunity = [&](SpellImmuneContainer const& container)
{
uint32 schoolImmunityMask = 0;
for (auto const& [immunitySchoolMask, immunityAuraId] : container)
{
SpellInfo const* immuneAuraInfo = sSpellMgr->GetSpellInfo(immunityAuraId);
if (immuneAuraInfo && !immuneAuraInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS) && caster && caster->IsFriendlyTo(this))
continue;
schoolImmunityMask |= immunitySchoolMask;
}
// We need to be immune to all types
return (schoolImmunityMask & schoolMask) == schoolMask;
};
// If m_immuneToSchool type contain this school type, IMMUNE periodic tick.
if (hasImmunity(m_spellImmune[IMMUNITY_SCHOOL]))
return true;
return false;
}
bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell)
@@ -9917,38 +9991,34 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell)
return false;
// Single spell immunity.
SpellImmuneList const& idList = m_spellImmune[IMMUNITY_ID];
for (SpellImmuneList::const_iterator itr = idList.begin(); itr != idList.end(); ++itr)
if (itr->type == spellInfo->Id)
SpellImmuneContainer const& idList = m_spellImmune[IMMUNITY_ID];
if (idList.count(spellInfo->Id) > 0)
return true;
// xinef: my special immunity, if spellid is not on this list it means npc is immune
SpellImmuneList const& allowIdList = m_spellImmune[IMMUNITY_ALLOW_ID];
SpellImmuneContainer const& allowIdList = m_spellImmune[IMMUNITY_ALLOW_ID];
if (!allowIdList.empty())
{
for (SpellImmuneList::const_iterator itr = allowIdList.begin(); itr != allowIdList.end(); ++itr)
if (itr->type == spellInfo->Id)
return false;
if (allowIdList.count(spellInfo->Id) == 0)
return true;
return false;
}
if (spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES) && !HasSpiritOfRedemptionAura())
return false;
if (spellInfo->Dispel)
if (uint32 dispel = spellInfo->Dispel)
{
SpellImmuneList const& dispelList = m_spellImmune[IMMUNITY_DISPEL];
for (SpellImmuneList::const_iterator itr = dispelList.begin(); itr != dispelList.end(); ++itr)
if (itr->type == spellInfo->Dispel)
SpellImmuneContainer const& dispelList = m_spellImmune[IMMUNITY_DISPEL];
if (dispelList.count(dispel) > 0)
return true;
}
// Spells that don't have effectMechanics.
if (spellInfo->Mechanic)
if (uint32 mechanic = spellInfo->Mechanic)
{
SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
if (itr->type == spellInfo->Mechanic)
SpellImmuneContainer const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
if (mechanicList.count(mechanic) > 0)
return true;
}
@@ -9974,7 +10044,7 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell)
if (immuneToAllEffects) //Return immune only if the target is immune to all spell effects.
return true;
if (spellInfo->Id != 42292 && spellInfo->Id != 59752 && spellInfo->Id != 19574 && spellInfo->Id != 34471)
if (!spellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES))
{
SpellSchoolMask spellSchoolMask = spellInfo->GetSchoolMask();
if (spell)
@@ -9984,16 +10054,24 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell)
if (spellSchoolMask != SPELL_SCHOOL_MASK_NONE)
{
SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
SpellImmuneContainer const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
for (auto itr = schoolList.begin(); itr != schoolList.end(); ++itr)
{
SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(itr->spellId);
if (((itr->type & spellSchoolMask) == spellSchoolMask)
&& (!immuneSpellInfo || immuneSpellInfo->IsPositive()) && !spellInfo->IsPositive()
&& !spellInfo->CanPierceImmuneAura(immuneSpellInfo))
SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(itr->second);
if (!(itr->first & spellSchoolMask))
continue;
if (immuneSpellInfo && !immuneSpellInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS))
{
return true;
Unit const* spellCaster = spell ? spell->GetCaster() : nullptr;
if (spellCaster && spellCaster->IsFriendlyTo(this))
continue;
}
if (spellInfo->CanPierceImmuneAura(immuneSpellInfo))
continue;
return true;
}
}
}
@@ -10001,7 +10079,7 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell)
return false;
}
bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const
bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Unit const* caster /*= nullptr*/) const
{
if (!spellInfo || !spellInfo->Effects[index].IsEffect())
return false;
@@ -10013,12 +10091,16 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) cons
if (spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES) && !HasSpiritOfRedemptionAura())
return false;
// Special-case handling for Vezax's Aura of Despair.
static constexpr uint32 SPELL_AURA_OF_DESPAIR_1 = 62692;
static constexpr uint32 SPELL_AURA_OF_DESPAIR_2 = 64848;
//If m_immuneToEffect type contain this effect type, IMMUNE effect.
uint32 effect = spellInfo->Effects[index].Effect;
SpellImmuneList const& effectList = m_spellImmune[IMMUNITY_EFFECT];
for (SpellImmuneList::const_iterator itr = effectList.begin(); itr != effectList.end(); ++itr)
SpellImmuneContainer const& effectList = m_spellImmune[IMMUNITY_EFFECT];
for (SpellImmuneContainer::const_iterator itr = effectList.begin(); itr != effectList.end(); ++itr)
{
if (itr->type == effect && (itr->spellId != 62692 || (spellInfo->Effects[index].MiscValue == POWER_MANA && !CanRestoreMana(spellInfo))))
if (itr->first == effect && (itr->second != SPELL_AURA_OF_DESPAIR_1 || (spellInfo->Effects[index].MiscValue == POWER_MANA && !CanRestoreMana(spellInfo))))
{
return true;
}
@@ -10026,40 +10108,31 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) cons
if (uint32 mechanic = spellInfo->Effects[index].Mechanic)
{
SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
if (itr->type == mechanic)
auto const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
if (mechanicList.count(mechanic) > 0)
return true;
}
if (uint32 aura = spellInfo->Effects[index].ApplyAuraName)
{
SpellImmuneList const& list = m_spellImmune[IMMUNITY_STATE];
for (SpellImmuneList::const_iterator itr = list.begin(); itr != list.end(); ++itr)
{
if (itr->type == aura && (itr->spellId != 64848 || (spellInfo->Effects[index].MiscValue == POWER_MANA && !CanRestoreMana(spellInfo))))
{
if (!spellInfo->HasAttribute(SPELL_ATTR3_ALWAYS_HIT))
{
if (itr->blockType == SPELL_BLOCK_TYPE_ALL || spellInfo->IsPositive()) // xinef: added for pet scaling
if (uint32 aura = spellInfo->Effects[index].ApplyAuraName)
{
SpellImmuneContainer const& list = m_spellImmune[IMMUNITY_STATE];
for (SpellImmuneContainer::const_iterator itr = list.begin(); itr != list.end(); ++itr)
{
if (itr->first == aura && (itr->second != SPELL_AURA_OF_DESPAIR_2 || (spellInfo->Effects[index].MiscValue == POWER_MANA && !CanRestoreMana(spellInfo))))
return true;
}
}
}
}
if (!spellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES))
{
// Check for immune to application of harmful magical effects
AuraEffectList const& immuneAuraApply = GetAuraEffectsByType(SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL);
for (AuraEffectList::const_iterator iter = immuneAuraApply.begin(); iter != immuneAuraApply.end(); ++iter)
{
if (/*(spellInfo->Dispel == DISPEL_MAGIC || spellInfo->Dispel == DISPEL_CURSE || spellInfo->Dispel == DISPEL_DISEASE) &&*/ // Magic debuff, xinef: all kinds?
((*iter)->GetMiscValue() & spellInfo->GetSchoolMask()) && // Check school
!spellInfo->IsPositiveEffect(index) && // Harmful
spellInfo->Effects[index].Effect != SPELL_EFFECT_PERSISTENT_AREA_AURA) // Not Persistent area auras
for (AuraEffect* immuneAuraApply : GetAuraEffectsByType(SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL))
{
if (!(immuneAuraApply->GetMiscValue() & spellInfo->GetSchoolMask())) // Check school
continue;
if (spellInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS) || (caster && !IsFriendlyTo(caster))) // Harmful
return true;
}
}
@@ -10289,17 +10362,17 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT
});
// Mod damage from spell mechanic
uint32 mechanicMask = spellProto->GetAllEffectsMechanicMask();
uint64 mechanicMask = spellProto->GetAllEffectsMechanicMask();
// Shred, Maul - "Effects which increase Bleed damage also increase Shred damage"
if (spellProto->SpellFamilyName == SPELLFAMILY_DRUID && spellProto->SpellFamilyFlags[0] & 0x00008800)
mechanicMask |= (1 << MECHANIC_BLEED);
mechanicMask |= (UI64LIT(1) << MECHANIC_BLEED);
if (mechanicMask)
{
TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT, [mechanicMask](AuraEffect const* aurEff) -> bool
{
if (mechanicMask & uint32(1 << (aurEff->GetMiscValue())))
if (mechanicMask & uint64(UI64LIT(1) << (aurEff->GetMiscValue())))
return true;
return false;
});
@@ -10367,51 +10440,17 @@ private:
uint32 _type;
};
void Unit::ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply, SpellImmuneBlockType blockType)
void Unit::ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply, SpellImmuneBlockType /*blockType*/)
{
if (apply)
{
// xinef: immunities with spellId 0 are intended to be applied only once (script purposes mosty)
if (spellId == 0 && std::find_if(m_spellImmune[op].begin(), m_spellImmune[op].end(), spellIdImmunityPredicate(type)) != m_spellImmune[op].end())
return;
SpellImmune immune;
immune.spellId = spellId;
immune.type = type;
immune.blockType = blockType;
m_spellImmune[op].push_back(std::move(immune));
}
m_spellImmune[op].emplace(type, spellId);
else
{
for (SpellImmuneList::iterator itr = m_spellImmune[op].begin(); itr != m_spellImmune[op].end(); ++itr)
auto bounds = m_spellImmune[op].equal_range(type);
for (auto itr = bounds.first; itr != bounds.second;)
{
if (itr->spellId == spellId && itr->type == type)
{
m_spellImmune[op].erase(itr);
break;
}
}
}
}
void Unit::ApplySpellDispelImmunity(SpellInfo const* spellProto, DispelType type, bool apply)
{
ApplySpellImmune(spellProto->Id, IMMUNITY_DISPEL, type, apply);
if (apply && spellProto->HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT))
{
// Create dispel mask by dispel type
uint32 dispelMask = SpellInfo::GetDispelMask(type);
// Dispel all existing auras vs current dispel type
AuraApplicationMap& auras = GetAppliedAuras();
for (AuraApplicationMap::iterator itr = auras.begin(); itr != auras.end();)
{
SpellInfo const* spell = itr->second->GetBase()->GetSpellInfo();
if (spell->GetDispelMask() & dispelMask)
{
// Dispel aura
RemoveAura(itr);
}
if (itr->second == spellId)
itr = m_spellImmune[op].erase(itr);
else
++itr;
}
@@ -11177,8 +11216,9 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
{
if (Creature* creature = ToCreature())
{
uint32 immuneMask = creature->GetCreatureTemplate()->MechanicImmuneMask;
if (immuneMask & (1 << (MECHANIC_SNARE - 1)) || immuneMask & (1 << (MECHANIC_DAZE - 1)))
// use creature helper which now consults creature_immunities table
if (creature->HasMechanicTemplateImmunity(UI64LIT(1) << MECHANIC_SNARE) ||
creature->HasMechanicTemplateImmunity(UI64LIT(1) << MECHANIC_DAZE))
break;
}
@@ -11199,7 +11239,7 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
if (creature
&& !IsPet()
&& !(IsControlledByPlayer() && IsVehicle())
&& !(creature->HasMechanicTemplateImmunity(MECHANIC_SNARE))
&& !(creature->HasMechanicTemplateImmunity(UI64LIT(1) << MECHANIC_SNARE))
&& !(creature->IsDungeonBoss()))
{
// 1.6% for each % under 30.
@@ -11395,6 +11435,8 @@ void Unit::AtTargetAttacked(Unit* target, bool canInitialAggro)
target->EngageWithTarget(this);
if (Unit* targetOwner = target->GetCharmerOrOwner())
targetOwner->EngageWithTarget(this);
if (Unit* myOwner = GetCharmerOrOwner())
target->EngageWithTarget(myOwner);
// Patch 3.0.8: All player spells which cause a creature to become aggressive
// to you will now also immediately cause the creature to be tapped.
@@ -11422,12 +11464,8 @@ Unit* Creature::SelectVictim()
Unit* target = nullptr;
// Taunt handling is now done inside ThreatManager via TauntState
if (CanHaveThreatList())
{
if (!m_threatManager.IsThreatListEmpty())
target = m_threatManager.GetCurrentVictim();
}
else if (!HasReactState(REACT_PASSIVE))
{
// we have player pet probably
@@ -15087,7 +15125,7 @@ Aura* Unit::AddAura(SpellInfo const* spellInfo, uint8 effMask, Unit* target)
{
if (!(effMask & (1 << i)))
continue;
if (target->IsImmunedToSpellEffect(spellInfo, i))
if (target->IsImmunedToSpellEffect(spellInfo, i, this))
effMask &= ~(1 << i);
}
@@ -15739,6 +15777,12 @@ void Unit::_ExitVehicle(Position const* exitPosition)
pos.RelocateOffset({ seatAddon->ExitParameterX, seatAddon->ExitParameterY, seatAddon->ExitParameterZ, seatAddon->ExitParameterO });
else if (seatAddon->ExitParameter == VehicleExitParameters::VehicleExitParamDest)
pos.Relocate({ seatAddon->ExitParameterX, seatAddon->ExitParameterY, seatAddon->ExitParameterZ, seatAddon->ExitParameterO });
bool isInLoS = GetMap()->isInLineOfSight(GetPositionX(), GetPositionY(), GetPositionZ(), pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), GetPhaseMask(), LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::Nothing);
float floorZ = GetMapHeight(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ());
if (!isInLoS || pos.GetPositionZ() < floorZ)
pos = vehicleBase->GetPosition();
}
}
@@ -16344,8 +16388,8 @@ void Unit::ExecuteDelayedUnitRelocationEvent()
GetMap()->LoadGridsInRange(*player, MAX_VISIBILITY_DISTANCE);
Acore::PlayerRelocationNotifier notifier(*player);
Cell::VisitObjects(viewPoint, notifier, player->GetSightRange());
Cell::VisitFarVisibleObjects(viewPoint, notifier, VISIBILITY_DISTANCE_GIGANTIC);
Cell::VisitObjects(player->GetSightPosition().GetPositionX(), player->GetSightPosition().GetPositionY(), player->GetMap(), notifier, player->GetSightRange());
Cell::VisitFarVisibleObjects(player->GetSightPosition().GetPositionX(), player->GetSightPosition().GetPositionY(), player->GetMap(), notifier, VISIBILITY_DISTANCE_GIGANTIC);
notifier.SendToSelf();
this->AddToNotify(NOTIFY_AI_RELOCATION);
+17 -11
View File
@@ -1408,7 +1408,7 @@ public:
void RemoveAurasWithInterruptFlags(uint32 flag, uint32 except = 0, bool isAutoshot = false);
void RemoveAurasWithAttribute(uint32 flags);
void RemoveAurasWithFamily(SpellFamilyNames family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, ObjectGuid casterGUID);
void RemoveAurasWithMechanic(uint32 mechanic_mask, AuraRemoveMode removemode = AURA_REMOVE_BY_DEFAULT, uint32 except = 0);
void RemoveAurasWithMechanic(uint64 mechanic_mask, AuraRemoveMode removemode = AURA_REMOVE_BY_DEFAULT, uint32 except = 0);
void RemoveMovementImpairingAuras(bool withRoot);
void RemoveAurasByShapeShift();
@@ -1500,7 +1500,7 @@ public:
bool HasNegativeAuraWithInterruptFlag(uint32 flag, ObjectGuid guid = ObjectGuid::Empty);
[[nodiscard]] bool HasVisibleAuraType(AuraType auraType) const;
bool HasNegativeAuraWithAttribute(uint32 flag, ObjectGuid guid = ObjectGuid::Empty);
[[nodiscard]] bool HasAuraWithMechanic(uint32 mechanicMask) const;
[[nodiscard]] bool HasAuraWithMechanic(uint64 mechanicMask) const;
[[nodiscard]] bool HasAuraTypeWithFamilyFlags(AuraType auraType, uint32 familyName, uint32 familyFlags) const;
@@ -1636,17 +1636,22 @@ public:
// Spells immunities
void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply, SpellImmuneBlockType blockType = SPELL_BLOCK_TYPE_ALL);
void ApplySpellDispelImmunity(SpellInfo const* spellProto, DispelType type, bool apply);
virtual bool IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell = nullptr);
[[nodiscard]] bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask) const;
[[nodiscard]] bool IsImmunedToDamage(SpellInfo const* spellInfo) const;
[[nodiscard]] bool IsImmunedToDamage(Spell const* spell) const;
[[nodiscard]] bool IsImmunedToSchool(SpellSchoolMask meleeSchoolMask) const;
bool IsImmunedToSpell(SpellInfo const* spellInfo, uint32 effectMask, Unit const* caster = nullptr);
[[nodiscard]] bool IsImmunedToDamage(SpellSchoolMask schoolMask) const;
[[nodiscard]] bool IsImmunedToDamage(Unit const* caster, SpellInfo const* spellInfo) const;
[[nodiscard]] bool IsImmunedToSchool(SpellSchoolMask schoolMask) const;
static bool IsImmuneMaskFully(SpellSchoolMask immuneMask, SpellSchoolMask schoolMask) { return (immuneMask & schoolMask) == schoolMask; }
[[nodiscard]] uint32 GetSchoolImmunityMask() const;
[[nodiscard]] uint32 GetDamageImmunityMask() const;
[[nodiscard]] bool IsImmunedToSchool(SpellInfo const* spellInfo) const;
[[nodiscard]] bool IsImmunedToSchool(Spell const* spell) const;
[[nodiscard]] bool IsImmunedToDamageOrSchool(SpellSchoolMask meleeSchoolMask) const;
bool IsImmunedToDamageOrSchool(SpellInfo const* spellInfo) const;
virtual bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const;
[[nodiscard]] bool IsImmunedToDamageOrSchool(SpellSchoolMask schoolMask) const;
[[nodiscard]] bool IsImmunedToAuraPeriodicTick(Unit const* caster, SpellInfo const* spellInfo) const;
virtual bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Unit const* caster = nullptr) const;
// Critic chances
bool isBlockCritical();
@@ -2082,7 +2087,8 @@ public:
float m_modAttackSpeedPct[3];
SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY];
typedef std::unordered_multimap<uint32 /*type*/, uint32 /*spellId*/> SpellImmuneContainer;
SpellImmuneContainer m_spellImmune[MAX_SPELL_IMMUNITY];
uint32 m_lastSanctuaryTime;
// pet auras
+101 -58
View File
@@ -310,6 +310,9 @@ ObjectMgr::ObjectMgr():
{
_playerClassInfo[i] = nullptr;
}
// Initialize default spawn group
_spawnGroupDataStore[0] = {0, "Default Group", 0, SpawnGroupFlags(SPAWNGROUP_FLAG_SYSTEM)};
}
ObjectMgr::~ObjectMgr()
@@ -522,18 +525,18 @@ void ObjectMgr::LoadCreatureTemplates()
// 0 1 2 3 4 5 6 7 8
QueryResult result = WorldDatabase.Query("SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, name, subname, IconName, "
// 9 10 11 12 13 14 15 16 17 18 19 20 21 22
"gossip_menu_id, minlevel, maxlevel, exp, faction, npcflag, speed_walk, speed_run, speed_swim, speed_flight, detection_range, scale, `rank`, dmgschool, "
// 23 24 25 26 27 28 29 30 31 32
// 9 10 11 12 13 14 15 16 17 18 19 20 21
"gossip_menu_id, minlevel, maxlevel, exp, faction, npcflag, speed_walk, speed_run, speed_swim, speed_flight, detection_range, `rank`, dmgschool, "
// 22 23 24 25 26 27 28 29 30 31
"DamageModifier, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, dynamicflags, family, "
// 33 34 35 36 37
// 32 33 34 35 36
"type, type_flags, lootid, pickpocketloot, skinloot, "
// 38 39 40 41 42 43 44 45 46 47
// 37 38 39 40 41 42 43 44 45 46
"PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, "
// 48 49 50 51 52 53 54 55 56 57 58 59
"ctm.Chase, ctm.Random, ctm.InteractionPauseTimer, HoverHeight, HealthModifier, ManaModifier, ArmorModifier, ExperienceModifier, RacialLeader, movementId, RegenHealth, mechanic_immune_mask, "
// 60 61 62
"spell_school_immune_mask, flags_extra, ScriptName "
// 47 48 49 50 51 52 53 54 55 56 57
"ctm.Chase, ctm.Random, ctm.InteractionPauseTimer, HoverHeight, HealthModifier, ManaModifier, ArmorModifier, ExperienceModifier, RacialLeader, movementId, RegenHealth, "
// 58 59 60
"CreatureImmunitiesId, flags_extra, ScriptName "
"FROM creature_template ct LEFT JOIN creature_template_movement ctm ON ct.entry = ctm.CreatureId ORDER BY entry DESC;");
if (!result)
@@ -619,24 +622,23 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields, bool triggerHook)
creatureTemplate.speed_swim = fields[17].Get<float>();
creatureTemplate.speed_flight = fields[18].Get<float>();
creatureTemplate.detection_range = fields[19].Get<float>();
creatureTemplate.scale = fields[20].Get<float>();
creatureTemplate.rank = uint32(fields[21].Get<uint8>());
creatureTemplate.dmgschool = uint32(fields[22].Get<int8>());
creatureTemplate.DamageModifier = fields[23].Get<float>();
creatureTemplate.BaseAttackTime = fields[24].Get<uint32>();
creatureTemplate.RangeAttackTime = fields[25].Get<uint32>();
creatureTemplate.BaseVariance = fields[26].Get<float>();
creatureTemplate.RangeVariance = fields[27].Get<float>();
creatureTemplate.unit_class = uint32(fields[28].Get<uint8>());
creatureTemplate.unit_flags = fields[29].Get<uint32>();
creatureTemplate.unit_flags2 = fields[30].Get<uint32>();
creatureTemplate.dynamicflags = fields[31].Get<uint32>();
creatureTemplate.family = uint32(fields[32].Get<uint8>());
creatureTemplate.type = uint32(fields[33].Get<uint8>());
creatureTemplate.type_flags = fields[34].Get<uint32>();
creatureTemplate.lootid = fields[35].Get<uint32>();
creatureTemplate.pickpocketLootId = fields[36].Get<uint32>();
creatureTemplate.SkinLootId = fields[37].Get<uint32>();
creatureTemplate.rank = uint32(fields[20].Get<uint8>());
creatureTemplate.dmgschool = uint32(fields[21].Get<int8>());
creatureTemplate.DamageModifier = fields[22].Get<float>();
creatureTemplate.BaseAttackTime = fields[23].Get<uint32>();
creatureTemplate.RangeAttackTime = fields[24].Get<uint32>();
creatureTemplate.BaseVariance = fields[25].Get<float>();
creatureTemplate.RangeVariance = fields[26].Get<float>();
creatureTemplate.unit_class = uint32(fields[27].Get<uint8>());
creatureTemplate.unit_flags = fields[28].Get<uint32>();
creatureTemplate.unit_flags2 = fields[29].Get<uint32>();
creatureTemplate.dynamicflags = fields[30].Get<uint32>();
creatureTemplate.family = uint32(fields[31].Get<uint8>());
creatureTemplate.type = uint32(fields[32].Get<uint8>());
creatureTemplate.type_flags = fields[33].Get<uint32>();
creatureTemplate.lootid = fields[34].Get<uint32>();
creatureTemplate.pickpocketLootId = fields[35].Get<uint32>();
creatureTemplate.SkinLootId = fields[36].Get<uint32>();
for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
{
@@ -648,49 +650,56 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields, bool triggerHook)
creatureTemplate.spells[i] = 0;
}
creatureTemplate.PetSpellDataId = fields[38].Get<uint32>();
creatureTemplate.VehicleId = fields[39].Get<uint32>();
creatureTemplate.mingold = fields[40].Get<uint32>();
creatureTemplate.maxgold = fields[41].Get<uint32>();
creatureTemplate.AIName = fields[42].Get<std::string>();
creatureTemplate.MovementType = uint32(fields[43].Get<uint8>());
if (!fields[44].IsNull())
creatureTemplate.PetSpellDataId = fields[37].Get<uint32>();
creatureTemplate.VehicleId = fields[38].Get<uint32>();
creatureTemplate.mingold = fields[39].Get<uint32>();
creatureTemplate.maxgold = fields[40].Get<uint32>();
creatureTemplate.AIName = fields[41].Get<std::string>();
creatureTemplate.MovementType = uint32(fields[42].Get<uint8>());
if (!fields[43].IsNull())
{
creatureTemplate.Movement.Ground = static_cast<CreatureGroundMovementType>(fields[44].Get<uint8>());
creatureTemplate.Movement.Ground = static_cast<CreatureGroundMovementType>(fields[43].Get<uint8>());
}
creatureTemplate.Movement.Swim = fields[45].Get<bool>();
if (!fields[46].IsNull())
creatureTemplate.Movement.Swim = fields[44].Get<bool>();
if (!fields[45].IsNull())
{
creatureTemplate.Movement.Flight = static_cast<CreatureFlightMovementType>(fields[46].Get<uint8>());
creatureTemplate.Movement.Flight = static_cast<CreatureFlightMovementType>(fields[45].Get<uint8>());
}
creatureTemplate.Movement.Rooted = fields[47].Get<bool>();
creatureTemplate.Movement.Rooted = fields[46].Get<bool>();
if (!fields[47].IsNull())
{
creatureTemplate.Movement.Chase = static_cast<CreatureChaseMovementType>(fields[47].Get<uint8>());
}
if (!fields[48].IsNull())
{
creatureTemplate.Movement.Chase = static_cast<CreatureChaseMovementType>(fields[48].Get<uint8>());
creatureTemplate.Movement.Random = static_cast<CreatureRandomMovementType>(fields[48].Get<uint8>());
}
if (!fields[49].IsNull())
{
creatureTemplate.Movement.Random = static_cast<CreatureRandomMovementType>(fields[49].Get<uint8>());
}
if (!fields[50].IsNull())
{
creatureTemplate.Movement.InteractionPauseTimer = fields[50].Get<uint32>();
creatureTemplate.Movement.InteractionPauseTimer = fields[49].Get<uint32>();
}
creatureTemplate.HoverHeight = fields[51].Get<float>();
creatureTemplate.ModHealth = fields[52].Get<float>();
creatureTemplate.ModMana = fields[53].Get<float>();
creatureTemplate.ModArmor = fields[54].Get<float>();
creatureTemplate.ModExperience = fields[55].Get<float>();
creatureTemplate.RacialLeader = fields[56].Get<bool>();
creatureTemplate.movementId = fields[57].Get<uint32>();
creatureTemplate.RegenHealth = fields[58].Get<bool>();
creatureTemplate.MechanicImmuneMask = fields[59].Get<uint32>();
creatureTemplate.SpellSchoolImmuneMask = fields[60].Get<uint8>();
creatureTemplate.flags_extra = fields[61].Get<uint32>();
creatureTemplate.ScriptID = GetScriptId(fields[62].Get<std::string>());
creatureTemplate.HoverHeight = fields[50].Get<float>();
creatureTemplate.ModHealth = fields[51].Get<float>();
creatureTemplate.ModMana = fields[52].Get<float>();
creatureTemplate.ModArmor = fields[53].Get<float>();
creatureTemplate.ModExperience = fields[54].Get<float>();
creatureTemplate.RacialLeader = fields[55].Get<bool>();
creatureTemplate.movementId = fields[56].Get<uint32>();
creatureTemplate.RegenHealth = fields[57].Get<bool>();
creatureTemplate.CreatureImmunitiesId = fields[58].Get<int32>();
creatureTemplate.flags_extra = fields[59].Get<uint32>();
creatureTemplate.ScriptID = GetScriptId(fields[60].Get<std::string>());
// Warn about deprecated immunity flags that should be moved to `creature_immunities` table
if (creatureTemplate.flags_extra & CREATURE_FLAG_EXTRA_NO_TAUNT)
LOG_WARN("server.loading", "Creature (Entry: {}) has deprecated flags_extra bit NO_TAUNT (0x100) set. This will be migrated to the `creature_immunities` table in a future update.", entry);
if (creatureTemplate.flags_extra & CREATURE_FLAG_EXTRA_AVOID_AOE)
LOG_WARN("server.loading", "Creature (Entry: {}) has deprecated flags_extra bit AVOID_AOE (0x400000) set. This will be migrated to the `creature_immunities` table in a future update.", entry);
if (creatureTemplate.flags_extra & CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK)
LOG_WARN("server.loading", "Creature (Entry: {}) has deprecated flags_extra bit IMMUNITY_KNOCKBACK (0x40000000) set. This will be migrated to the `creature_immunities` table in a future update.", entry);
// useful if the creature template load is being triggered from outside this class
if (triggerHook)
@@ -2394,6 +2403,7 @@ void ObjectMgr::LoadCreatures()
data.unit_flags = fields[21].Get<uint32>();
data.dynamicflags = fields[22].Get<uint32>();
data.ScriptId = GetScriptId(fields[23].Get<std::string>());
data.spawnGroupId = 0;
if (!data.ScriptId)
data.ScriptId = cInfo->ScriptID;
@@ -2572,6 +2582,7 @@ CreatureData const* ObjectMgr::LoadCreatureDataFromDB(ObjectGuid::LowType spawnI
creatureData.unit_flags = fields[19].Get<uint32>();
creatureData.dynamicflags = fields[20].Get<uint32>();
creatureData.ScriptId = GetScriptId(fields[21].Get<std::string>());
creatureData.spawnGroupId = 0;
if (!creatureData.ScriptId)
creatureData.ScriptId = cInfo->ScriptID;
@@ -2754,6 +2765,7 @@ ObjectGuid::LowType ObjectMgr::AddGOData(uint32 entry, uint32 mapId, float x, fl
data.phaseMask = PHASEMASK_NORMAL;
data.artKit = goinfo->type == GAMEOBJECT_TYPE_CAPTURE_POINT ? 21 : 0;
data.dbData = false;
data.spawnGroupId = 0;
AddGameobjectToGrid(spawnId, &data);
@@ -2909,6 +2921,7 @@ void ObjectMgr::LoadGameobjects()
data.rotation.w = fields[10].Get<float>();
data.spawntimesecs = fields[11].Get<int32>();
data.ScriptId = GetScriptId(fields[18].Get<std::string>());
data.spawnGroupId = 0;
if (!data.ScriptId)
data.ScriptId = gInfo->ScriptId;
@@ -7160,6 +7173,11 @@ void ObjectMgr::LoadAreaTriggerScripts()
LOG_INFO("server.loading", " ");
}
uint32 ObjectMgr::GetNearestTaxiNode(WorldLocation const& loc, uint32 teamId)
{
return GetNearestTaxiNode(loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), loc.GetMapId(), teamId);
}
uint32 ObjectMgr::GetNearestTaxiNode(float x, float y, float z, uint32 mapid, uint32 teamId)
{
bool found = false;
@@ -8672,6 +8690,19 @@ void ObjectMgr::DeleteGOData(ObjectGuid::LowType guid)
_gameObjectDataStore.erase(guid);
}
SpawnData const* ObjectMgr::GetSpawnData(SpawnObjectType type, ObjectGuid::LowType spawnId) const
{
switch (type)
{
case SPAWN_TYPE_CREATURE:
return GetCreatureData(spawnId);
case SPAWN_TYPE_GAMEOBJECT:
return GetGameObjectData(spawnId);
default:
return nullptr;
}
}
void ObjectMgr::LoadQuestRelationsHelper(QuestRelations& map, std::string const& table, bool starter, bool go)
{
uint32 oldMSTime = getMSTime();
@@ -9719,6 +9750,7 @@ void ObjectMgr::LoadTrainers()
// For reload case
_trainers.clear();
_classTrainers.clear();
std::unordered_map<int32, std::vector<Trainer::Spell>> spellsByTrainer;
if (QueryResult trainerSpellsResult = WorldDatabase.Query("SELECT TrainerId, SpellId, MoneyCost, ReqSkillLine, ReqSkillRank, ReqAbility1, ReqAbility2, ReqAbility3, ReqLevel FROM trainer_spell"))
@@ -9795,7 +9827,18 @@ void ObjectMgr::LoadTrainers()
spellsByTrainer.erase(spellsItr);
}
_trainers.emplace(std::piecewise_construct, std::forward_as_tuple(trainerId), std::forward_as_tuple(trainerId, trainerType, requirement, std::move(greeting), std::move(spells)));
auto [it, isNew] = _trainers.emplace(std::piecewise_construct, std::forward_as_tuple(trainerId), std::forward_as_tuple(trainerId, trainerType, requirement, std::move(greeting), std::move(spells)));
ASSERT(isNew);
if (trainerType == Trainer::Type::Class)
{
if (!requirement || requirement >= MAX_CLASSES)
LOG_ERROR("sql.sql", "Table `trainer` has invalid class requirement for trainer {}, ignoring");
else
{
uint8 classId = static_cast<uint8>(requirement);
_classTrainers[classId].push_back(&it->second);
}
}
} while (trainersResult->NextRow());
}
+13
View File
@@ -506,6 +506,7 @@ struct AcoreString
typedef std::map<ObjectGuid, ObjectGuid> LinkedRespawnContainer;
typedef std::unordered_map<ObjectGuid::LowType, CreatureData> CreatureDataContainer;
typedef std::unordered_map<ObjectGuid::LowType, GameObjectData> GameObjectDataContainer;
typedef std::unordered_map<uint32, SpawnGroupTemplateData> SpawnGroupDataContainer;
typedef std::map<TempSummonGroupKey, std::vector<TempSummonData> > TempSummonDataContainer;
typedef std::map<TempSummonGroupKey, std::vector<GameObjectSummonData> > GameObjectSummonDataContainer;
typedef std::unordered_map<uint32, CreatureLocale> CreatureLocaleContainer;
@@ -811,6 +812,7 @@ public:
void GetPlayerLevelInfo(uint32 race, uint32 class_, uint8 level, PlayerLevelInfo* info) const;
uint32 GetNearestTaxiNode(float x, float y, float z, uint32 mapid, uint32 teamId);
uint32 GetNearestTaxiNode(WorldLocation const& loc, uint32 teamId);
void GetTaxiPath(uint32 source, uint32 destination, uint32& path, uint32& cost);
uint32 GetTaxiMountDisplayId(uint32 id, TeamId teamId, bool allowed_alt_team = false);
@@ -1269,6 +1271,14 @@ public:
if (itr == _gameObjectDataStore.end()) return nullptr;
return &itr->second;
}
[[nodiscard]] SpawnData const* GetSpawnData(SpawnObjectType type, ObjectGuid::LowType spawnId) const;
[[nodiscard]] SpawnGroupTemplateData const* GetSpawnGroupData(uint32 groupId) const
{
auto itr = _spawnGroupDataStore.find(groupId);
return itr != _spawnGroupDataStore.end() ? &itr->second : nullptr;
}
[[nodiscard]] CreatureLocale const* GetCreatureLocale(uint32 entry) const
{
CreatureLocaleContainer::const_iterator itr = _creatureLocaleStore.find(entry);
@@ -1419,6 +1429,7 @@ public:
bool DeleteGameTele(std::string_view name);
Trainer::Trainer* GetTrainer(uint32 creatureId);
std::vector<Trainer::Trainer const*> const& GetClassTrainers(uint8 classId) const { return _classTrainers.at(classId); }
[[nodiscard]] VendorItemData const* GetNpcVendorItemList(uint32 entry) const
{
@@ -1642,6 +1653,7 @@ private:
LinkedRespawnContainer _linkedRespawnStore;
CreatureLocaleContainer _creatureLocaleStore;
GameObjectDataContainer _gameObjectDataStore;
SpawnGroupDataContainer _spawnGroupDataStore;
GameObjectLocaleContainer _gameObjectLocaleStore;
GameObjectTemplateContainer _gameObjectTemplateStore;
GameObjectTemplateAddonContainer _gameObjectTemplateAddonStore;
@@ -1667,6 +1679,7 @@ private:
CacheVendorItemContainer _cacheVendorItemStore;
std::unordered_map<uint32, Trainer::Trainer> _trainers;
std::unordered_map<uint8, std::vector<Trainer::Trainer const*>> _classTrainers;
std::unordered_map<uint32, uint32> _creatureDefaultTrainers;
std::set<uint32> _difficultyEntries[MAX_DIFFICULTY - 1]; // already loaded difficulty 1 value in creatures, used in CheckCreatureTemplate
+1
View File
@@ -107,6 +107,7 @@ struct Cell
template<class T> static void VisitObjects(float x, float y, Map* map, T& visitor, float radius);
template<class T> static void VisitFarVisibleObjects(WorldObject const* obj, T& visitor, float radius);
template<class T> static void VisitFarVisibleObjects(float x, float y, Map* map, T& visitor, float radius);
private:
template<class T, class CONTAINER> void VisitCircle(TypeContainerVisitor<T, CONTAINER>&, Map&, CellCoord const&, CellCoord const&) const;
+9 -7
View File
@@ -164,11 +164,7 @@ inline void Cell::VisitCircle(TypeContainerVisitor<T, CONTAINER>& visitor, Map&
template<class T>
inline void Cell::VisitObjects(WorldObject const* center_obj, T& visitor, float radius)
{
CellCoord p(Acore::ComputeCellCoord(center_obj->GetPositionX(), center_obj->GetPositionY()));
Cell cell(p);
TypeContainerVisitor<T, GridTypeMapContainer> gnotifier(visitor);
cell.Visit(p, gnotifier, *center_obj->GetMap(), *center_obj, radius);
VisitObjects(center_obj->GetPositionX(), center_obj->GetPositionY(), center_obj->GetMap(), visitor, radius);
}
template<class T>
@@ -184,11 +180,17 @@ inline void Cell::VisitObjects(float x, float y, Map* map, T& visitor, float rad
template<class T>
inline void Cell::VisitFarVisibleObjects(WorldObject const* center_obj, T& visitor, float radius)
{
CellCoord p(Acore::ComputeCellCoord(center_obj->GetPositionX(), center_obj->GetPositionY()));
VisitFarVisibleObjects(center_obj->GetPositionX(), center_obj->GetPositionY(), center_obj->GetMap(), visitor, radius);
}
template<class T>
inline void Cell::VisitFarVisibleObjects(float x, float y, Map* map, T& visitor, float radius)
{
CellCoord p(Acore::ComputeCellCoord(x, y));
Cell cell(p);
TypeContainerVisitor<T, FarVisibleGridContainer> gnotifier(visitor);
cell.Visit(p, gnotifier, *center_obj->GetMap(), *center_obj, radius);
cell.Visit(p, gnotifier, *map, x, y, radius);
}
#endif

Some files were not shown because too many files have changed in this diff Show More