Merge branch 'master' into test-staging
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
-- DB update 2026_04_03_03 -> 2026_04_04_00
|
||||
-- Fix Scarlet Monastery Cathedral Mograine/Whitemane encounter resetting during scripted phase
|
||||
-- Disable evade during the scripted "fake death" / "Deep Sleep" / "resurrection" phase
|
||||
-- to prevent JustExitedCombat auto-evade from triggering SMART_EVENT_EVADE and setting FAIL
|
||||
|
||||
-- Mograine: Disable evade when fake-dying (actionlist 397600)
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid` = 397600 AND `source_type` = 9 AND `id` = 10;
|
||||
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
|
||||
(397600, 9, 10, 0, 0, 0, 100, 0, 0, 0, 0, 0, 117, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Actionlist - Disable Evade');
|
||||
|
||||
-- Mograine: Re-enable evade when reaching Whitemane after resurrection (On Reached Point 1 chain)
|
||||
-- Update id 24 to link to new id 29
|
||||
UPDATE `smart_scripts` SET `link` = 29 WHERE `entryorguid` = 3976 AND `source_type` = 0 AND `id` = 24;
|
||||
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid` = 3976 AND `source_type` = 0 AND `id` = 29;
|
||||
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
|
||||
(3976, 0, 29, 0, 61, 0, 100, 0, 0, 0, 0, 0, 117, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Reached Point 1 - Enable Evade');
|
||||
|
||||
-- Whitemane: Disable evade when casting Deep Sleep (actionlist 397700)
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid` = 397700 AND `source_type` = 9 AND `id` = 5;
|
||||
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
|
||||
(397700, 9, 5, 0, 0, 0, 100, 0, 0, 0, 0, 0, 117, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - Actionlist - Disable Evade');
|
||||
|
||||
-- Whitemane: Re-enable evade when re-engaging after resurrection (actionlist 397701)
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid` = 397701 AND `source_type` = 9 AND `id` = 8;
|
||||
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
|
||||
(397701, 9, 8, 0, 0, 0, 100, 0, 0, 0, 0, 0, 117, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - Actionlist - Enable Evade');
|
||||
@@ -0,0 +1,5 @@
|
||||
-- DB update 2026_04_04_00 -> 2026_04_04_01
|
||||
--
|
||||
DELETE FROM `item_loot_template` WHERE (`Entry` = 52676) AND (`Item` IN (47241));
|
||||
INSERT INTO `item_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
|
||||
(52676, 47241, 0, 100, 0, 1, 0, 2, 2, '');
|
||||
@@ -0,0 +1,2 @@
|
||||
-- DB update 2026_04_04_01 -> 2026_04_05_00
|
||||
UPDATE `smart_scripts` SET `event_phase_mask` = 0 WHERE `entryorguid` = 27653 AND `id` IN (2, 3);
|
||||
@@ -0,0 +1,17 @@
|
||||
-- DB update 2026_04_05_00 -> 2026_04_05_01
|
||||
--
|
||||
-- Alexstrasza the Life-Binder (Dragonblight) - Add Focusing Iris key menu_option. (Previously empty)
|
||||
DELETE FROM `gossip_menu_option` WHERE `MenuID` = 10192;
|
||||
INSERT INTO `gossip_menu_option` (`MenuID`, `OptionID`, `OptionIcon`, `OptionText`, `OptionBroadcastTextID`, `OptionType`, `OptionNpcFlag`, `ActionMenuID`, `ActionPoiID`, `BoxCoded`, `BoxMoney`, `BoxText`, `BoxBroadcastTextID`, `VerifiedBuild`) VALUES
|
||||
(10192, 0, 0, 'Oh great Queen of the Dragons, I have somehow misplaced my Key to the Focusing Iris. Can you find it for me?', 32832, 1, 1, 0, 0, 0, 0, '', 0, 0),
|
||||
(10192, 1, 0, 'Oh great Queen of the Dragons, I have somehow misplaced my Heroic Key to the Focusing Iris. Can you find it for me?', 32836, 1, 1, 0, 0, 0, 0, '', 0, 0);
|
||||
|
||||
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 15) AND (`SourceGroup` = 10192) AND (`SourceEntry` IN (0, 1)) AND (`SourceId` = 0);
|
||||
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
|
||||
(15, 10192, 0, 0, 0, 8, 0, 13372, 0, 0, 0, 0, 0, '', 'must have completed Quest \'The Key to the Focusing Iris\''),
|
||||
(15, 10192, 0, 0, 0, 2, 0, 44582, 1, 1, 1, 0, 0, '', 'must not have item \'Key to the Focusing Iris\''),
|
||||
(15, 10192, 1, 0, 0, 8, 0, 13375, 0, 0, 0, 0, 0, '', 'must have completed Quest \'The Heroic Key to the Focusing Iris\''),
|
||||
(15, 10192, 1, 0, 0, 2, 0, 44581, 1, 1, 1, 0, 0, '', 'must not have item \'Heroic Key to the Focusing Iris\'');
|
||||
|
||||
UPDATE `spell_dbc` SET `Targets` = 1, `Effect_1` = 24, `EffectBasePoints_1` = 1, `EffectItemType_1` = 44582 WHERE (`ID` = 60989);
|
||||
UPDATE `spell_dbc` SET `Targets` = 1, `Effect_1` = 24, `EffectBasePoints_1` = 1, `EffectItemType_1` = 44581 WHERE (`ID` = 60992);
|
||||
@@ -0,0 +1,9 @@
|
||||
-- DB update 2026_04_05_01 -> 2026_04_05_02
|
||||
-- Fix quest The Dread Relic
|
||||
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 22369) 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
|
||||
(22369, 0, 0, 1, 54, 0, 100, 1, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Dread Relic Thrall - On Just Summoned - Set Passive'),
|
||||
(22369, 0, 1, 0, 61, 0, 100, 1, 0, 0, 0, 0, 0, 0, 67, 1, 10000, 10000, 0, 0, 100, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Dread Relic Thrall - On Just Summoned - Create Timed Event'),
|
||||
(22369, 0, 2, 3, 59, 0, 100, 1, 1, 0, 0, 0, 0, 0, 8, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Dread Relic Thrall - Timed Event - Set Aggressive'),
|
||||
(22369, 0, 3, 0, 61, 0, 100, 1, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 'Dread Relic Thrall - Timed Event - Attack Summoner'),
|
||||
(22369, 0, 4, 0, 4, 0, 100, 4, 0, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 11, 22369, 10, 0, 0, 0, 0, 0, 0, 'Dread Relic Thrall - On Aggro - Set Data');
|
||||
@@ -0,0 +1,19 @@
|
||||
-- DB update 2026_04_05_02 -> 2026_04_05_03
|
||||
-- Primal Ooze (6557)
|
||||
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 6557) 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
|
||||
(6557, 0, 0, 0, 8, 0, 100, 512, 16031, 0, 0, 0, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Primal Ooze - On Spellhit 16031 (Releasing Corrupt Ooze) - Set Event Phase 2'),
|
||||
(6557, 0, 1, 0, 8, 0, 100, 513, 15702, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Primal Ooze - On Spellhit 15702 (Filling Empty Jar) - Despawn'),
|
||||
(6557, 0, 2, 0, 2, 0, 100, 1, 0, 30, 0, 0, 0, 0, 11, 14146, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Primal Ooze - Between 0-30% Health - Cast Clone (No Repeat)'),
|
||||
(6557, 0, 3, 0, 2, 0, 100, 1, 0, 30, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Primal Ooze - Between 0-30% Health - Say Line 0 (No Repeat)'),
|
||||
(6557, 0, 4, 5, 75, 2, 100, 513, 0, 10290, 3, 1000, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Primal Ooze - Phase 2 - On Distance Creature 10290 within 3yd - Set Visibility Off'),
|
||||
(6557, 0, 5, 6, 61, 2, 100, 513, 0, 0, 0, 0, 0, 0, 12, 9621, 6, 20000, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Primal Ooze - Phase 2 (Link) - Summon Gargantuan Ooze'),
|
||||
(6557, 0, 6, 7, 61, 2, 100, 513, 0, 0, 0, 0, 0, 0, 11, 16032, 0, 0, 0, 0, 0, 9, 9621, 0, 10, 0, 0, 0, 0, 0, 'Primal Ooze - Phase 2 (Link) - Cast Merging Oozes on Gargantuan Ooze'),
|
||||
(6557, 0, 7, 0, 61, 2, 100, 513, 0, 0, 0, 0, 0, 0, 41, 50, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Primal Ooze - Phase 2 (Link) - Despawn In 50ms');
|
||||
|
||||
-- Captured Felwood Ooze (10290)
|
||||
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 10290) 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
|
||||
(10290, 0, 0, 0, 54, 0, 100, 513, 0, 0, 0, 0, 0, 0, 29, 0, 0, 1, 0, 1, 0, 9, 6557, 0, 50, 0, 0, 0, 0, 0, 'Captured Felwood Ooze - On Just Summoned - Start Follow Closest Primal Ooze'),
|
||||
(10290, 0, 1, 2, 75, 0, 100, 513, 0, 6557, 3, 500, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Captured Felwood Ooze - Within 3yd of Primal Ooze - Set Visibility Off'),
|
||||
(10290, 0, 2, 0, 61, 0, 100, 513, 0, 0, 0, 0, 0, 0, 41, 500, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Captured Felwood Ooze - Within 3yd (Link) - Despawn In 500ms');
|
||||
@@ -0,0 +1,27 @@
|
||||
-- DB update 2026_04_05_03 -> 2026_04_10_00
|
||||
|
||||
-- Edit Actionlists
|
||||
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 2840600) AND (`source_type` = 9) AND (`id` IN (0, 1, 2, 4, 5, 8, 9));
|
||||
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
|
||||
(2840600, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 54238, 0, 0, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - Actionlist - Cast \'Duel Aura Check 01\''),
|
||||
(2840600, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 52991, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - Actionlist - Cast \'Duel Flag\''),
|
||||
(2840600, 9, 2, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - Actionlist - Say Line 0'),
|
||||
(2840600, 9, 4, 0, 0, 0, 100, 0, 3000, 3000, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - Actionlist - Say Line 1'),
|
||||
(2840600, 9, 5, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - Actionlist - Say Line 2'),
|
||||
(2840600, 9, 8, 0, 0, 0, 100, 0, 500, 500, 0, 0, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - Actionlist - Set Event Phase 2'),
|
||||
(2840600, 9, 9, 0, 0, 0, 100, 0, 500, 500, 0, 0, 0, 0, 42, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - Actionlist - Set Invincibility Hp 1%');
|
||||
|
||||
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 2840601) AND (`source_type` = 9) AND (`id` IN (7, 8));
|
||||
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
|
||||
(2840601, 9, 7, 0, 0, 0, 100, 0, 1000, 1000, 0, 0, 0, 0, 117, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - Actionlist - Enable Evade'),
|
||||
(2840601, 9, 8, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - Actionlist - Despawn Instant');
|
||||
|
||||
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 2840602) AND (`source_type` = 9) AND (`id` IN (5, 6));
|
||||
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
|
||||
(2840602, 9, 5, 0, 0, 0, 100, 0, 1000, 1000, 0, 0, 0, 0, 117, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - Actionlist - Enable Evade'),
|
||||
(2840602, 9, 6, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - Actionlist - Despawn Instant');
|
||||
|
||||
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 2840611) AND (`source_type` = 9) AND (`id` IN (7, 8));
|
||||
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
|
||||
(2840611, 9, 7, 0, 0, 0, 100, 0, 1000, 1000, 0, 0, 0, 0, 117, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - Actionlist - Enable Evade'),
|
||||
(2840611, 9, 8, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Death Knight Initiate - Actionlist - Despawn Instant');
|
||||
@@ -0,0 +1,3 @@
|
||||
-- DB update 2026_04_10_00 -> 2026_04_10_01
|
||||
--
|
||||
UPDATE `creature_template_addon` SET `auras` = '70203' WHERE `entry` IN (37126, 38258);
|
||||
@@ -0,0 +1,4 @@
|
||||
-- DB update 2026_04_10_01 -> 2026_04_10_02
|
||||
|
||||
-- Update Conditions (Death Knight Initiate)
|
||||
UPDATE `conditions` SET `SourceTypeOrReferenceId` = 20, `SourceGroup` = 0, `SourceEntry` = 28406 WHERE (`SourceTypeOrReferenceId` = 15) AND (`SourceGroup` = 9765) AND (`SourceEntry` = 0) AND (`SourceId` = 0) AND (`ElseGroup` = 0) AND (`ConditionTypeOrReference` IN (1, 47)) AND (`ConditionTarget` = 0) AND (`ConditionValue1` IN (12733, 54238)) AND (`ConditionValue2` IN (0, 8)) AND (`ConditionValue3` = 0);
|
||||
@@ -99,6 +99,7 @@ bool DBUpdater<LoginDatabaseConnection>::IsEnabled(uint32 const updateMask)
|
||||
template<>
|
||||
std::string DBUpdater<LoginDatabaseConnection>::GetDBModuleName()
|
||||
{
|
||||
// must be lowercase
|
||||
return "auth";
|
||||
}
|
||||
|
||||
@@ -137,6 +138,7 @@ bool DBUpdater<WorldDatabaseConnection>::IsEnabled(uint32 const updateMask)
|
||||
template<>
|
||||
std::string DBUpdater<WorldDatabaseConnection>::GetDBModuleName()
|
||||
{
|
||||
// must be lowercase
|
||||
return "world";
|
||||
}
|
||||
|
||||
@@ -175,35 +177,10 @@ bool DBUpdater<CharacterDatabaseConnection>::IsEnabled(uint32 const updateMask)
|
||||
template<>
|
||||
std::string DBUpdater<CharacterDatabaseConnection>::GetDBModuleName()
|
||||
{
|
||||
// must be lowercase
|
||||
return "characters";
|
||||
}
|
||||
|
||||
#ifdef MOD_PLAYERBOTS
|
||||
// Playerbots Database
|
||||
template<>
|
||||
std::string DBUpdater<PlayerbotsDatabaseConnection>::GetConfigEntry()
|
||||
{
|
||||
return "Updates.Playerbots";
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string DBUpdater<PlayerbotsDatabaseConnection>::GetTableName()
|
||||
{
|
||||
return "Playerbots";
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string DBUpdater<PlayerbotsDatabaseConnection>::GetSourceDirectory()
|
||||
{
|
||||
return BuiltInConfig::GetSourceDirectory() + "/modules/mod-playerbots";
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string DBUpdater<PlayerbotsDatabaseConnection>::GetBaseFilesDirectory()
|
||||
{
|
||||
return DBUpdater<PlayerbotsDatabaseConnection>::GetSourceDirectory() + "/data/sql/playerbots/base/";
|
||||
}
|
||||
|
||||
template<>
|
||||
bool DBUpdater<PlayerbotsDatabaseConnection>::IsEnabled(uint32 const updateMask)
|
||||
{
|
||||
|
||||
@@ -160,18 +160,30 @@ UpdateFetcher::DirectoryStorage UpdateFetcher::ReceiveIncludedDirectories() cons
|
||||
moduleList.emplace_back(itr);
|
||||
|
||||
// data/sql
|
||||
for (auto const& itr : moduleList)
|
||||
for (auto const& moduleName : moduleList)
|
||||
{
|
||||
std::string path = _sourceDirectory->generic_string() + "/modules/" + itr + "/data/sql/" + _dbModuleName; // modules/mod-name/data/sql/db-world
|
||||
|
||||
Path const p(path);
|
||||
std::string path = _sourceDirectory->generic_string() + "/modules/" + moduleName + "/data/sql/"; // modules/mod-name/data/sql/
|
||||
Path const p{path};
|
||||
if (!is_directory(p))
|
||||
continue;
|
||||
|
||||
DirectoryEntry const entry = { p, AppliedFileEntry::StateConvert("MODULE") };
|
||||
directories.push_back(entry);
|
||||
directory_iterator const end;
|
||||
for (directory_iterator itr{p}; itr != end; ++itr)
|
||||
{
|
||||
if (!is_directory(itr->path()))
|
||||
continue;
|
||||
|
||||
LOG_TRACE("sql.updates", "Added applied modules file \"{}\" from remote.", p.filename().generic_string());
|
||||
std::filesystem::path dirPath = itr->path(); // modules/mod-name/data/sql/db-world
|
||||
std::string dirName = dirPath.filename().string(); // db-world
|
||||
|
||||
if (dirName.find(_dbModuleName) == std::string::npos)
|
||||
continue;
|
||||
|
||||
DirectoryEntry const entry = { dirPath, AppliedFileEntry::StateConvert("MODULE") };
|
||||
directories.push_back(entry);
|
||||
|
||||
LOG_TRACE("sql.updates", "Added applied modules file \"{}\" from remote.", dirPath.filename().generic_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -697,6 +697,20 @@ void SmartAI::MovementInform(uint32 MovementType, uint32 Data)
|
||||
MovepointReached(Data);
|
||||
}
|
||||
|
||||
void SmartAI::JustExitedCombat()
|
||||
{
|
||||
// When evade is suppressed or disabled, don't auto-evade on combat exit.
|
||||
// This prevents scripted encounters (e.g. Mograine/Whitemane) from resetting
|
||||
// when bosses temporarily stop fighting during scripted phases.
|
||||
if (mSuppressEvade || mEvadeDisabled)
|
||||
{
|
||||
EngagementOver();
|
||||
return;
|
||||
}
|
||||
|
||||
CreatureAI::JustExitedCombat();
|
||||
}
|
||||
|
||||
void SmartAI::EnterEvadeMode(EvadeReason /*why*/)
|
||||
{
|
||||
if (mSuppressEvade)
|
||||
|
||||
@@ -85,6 +85,9 @@ public:
|
||||
// Called for reaction at enter to combat if not in combat yet (enemy can be nullptr)
|
||||
void JustEngagedWith(Unit* enemy) override;
|
||||
|
||||
// Called when creature exits combat (all combat refs gone)
|
||||
void JustExitedCombat() override;
|
||||
|
||||
// Called for reaction at stopping attack at no attackers or targets
|
||||
void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER) override;
|
||||
|
||||
|
||||
@@ -974,7 +974,7 @@ bool ConditionMgr::IsObjectMeetToConditions(ConditionSourceInfo& sourceInfo, Con
|
||||
bool ConditionMgr::CanHaveSourceGroupSet(ConditionSourceType sourceType) const
|
||||
{
|
||||
return (sourceType == CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE ||
|
||||
sourceType == CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU || sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION || sourceType == CONDITION_SOURCE_TYPE_VEHICLE_SPELL ||
|
||||
sourceType == CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU || sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION || sourceType == CONDITION_SOURCE_TYPE_VEHICLE_SPELL || sourceType == CONDITION_SOURCE_TYPE_GOSSIP_HELLO ||
|
||||
sourceType == CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET || sourceType == CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT || sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT || sourceType == CONDITION_SOURCE_TYPE_NPC_VENDOR || sourceType == CONDITION_SOURCE_TYPE_PLAYER_LOOT_TEMPLATE);
|
||||
}
|
||||
|
||||
@@ -1808,9 +1808,15 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case CONDITION_SOURCE_TYPE_UNUSED_20:
|
||||
LOG_ERROR("sql.sql", "CONDITION_SOURCE_TYPE_UNUSED_20 is not in use. SourceEntry = ({}), skipped", cond->SourceEntry);
|
||||
case CONDITION_SOURCE_TYPE_GOSSIP_HELLO:
|
||||
{
|
||||
if (!sObjectMgr->GetCreatureTemplate(cond->SourceEntry))
|
||||
{
|
||||
LOG_ERROR("sql.sql", "CONDITION_SOURCE_TYPE_GOSSIP_HELLO: creature entry {} in `condition` table does not exist in `creature_template`, ignoring.", cond->SourceEntry);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CONDITION_SOURCE_TYPE_VEHICLE_SPELL:
|
||||
case CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT:
|
||||
if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup))
|
||||
|
||||
@@ -142,7 +142,7 @@ enum ConditionSourceType
|
||||
CONDITION_SOURCE_TYPE_SPELL = 17,
|
||||
CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT = 18,
|
||||
CONDITION_SOURCE_TYPE_QUEST_AVAILABLE = 19,
|
||||
CONDITION_SOURCE_TYPE_UNUSED_20 = 20, // placeholder
|
||||
CONDITION_SOURCE_TYPE_GOSSIP_HELLO = 20,
|
||||
CONDITION_SOURCE_TYPE_VEHICLE_SPELL = 21,
|
||||
CONDITION_SOURCE_TYPE_SMART_EVENT = 22,
|
||||
CONDITION_SOURCE_TYPE_NPC_VENDOR = 23,
|
||||
|
||||
@@ -2224,7 +2224,7 @@ 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(UI64LIT(1) << spellInfo->Mechanic))
|
||||
if (spellInfo->Mechanic > MECHANIC_NONE && HasMechanicTemplateImmunity(1ULL << spellInfo->Mechanic))
|
||||
return true;
|
||||
|
||||
// The above helper uses the creature_immunities table rather than a
|
||||
@@ -2247,7 +2247,7 @@ bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell)
|
||||
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(UI64LIT(1) << spellInfo->Effects[index].Mechanic))
|
||||
if (spellInfo->Effects[index].Mechanic > MECHANIC_NONE && HasMechanicTemplateImmunity(1ULL << spellInfo->Effects[index].Mechanic))
|
||||
return true;
|
||||
|
||||
if (GetCreatureTemplate()->type == CREATURE_TYPE_MECHANICAL && spellInfo->Effects[index].Effect == SPELL_EFFECT_HEAL)
|
||||
|
||||
@@ -10398,24 +10398,39 @@ void Player::ContinueTaxiFlight()
|
||||
|
||||
TaxiPathNodeList const& nodeList = sTaxiPathNodesByPath[path];
|
||||
|
||||
float bestDist = SIZE_OF_GRIDS * SIZE_OF_GRIDS; // xinef: large value
|
||||
float currDist = 0.0f;
|
||||
// Use triangle inequality to find the segment the player is on.
|
||||
// When distPrev + distNext < distNodes, the player projects between
|
||||
// the two nodes of the segment. Resume from the end node (i).
|
||||
float distPrev;
|
||||
float distNext =
|
||||
(nodeList[0]->x - GetPositionX()) * (nodeList[0]->x - GetPositionX()) +
|
||||
(nodeList[0]->y - GetPositionY()) * (nodeList[0]->y - GetPositionY()) +
|
||||
(nodeList[0]->z - GetPositionZ()) * (nodeList[0]->z - GetPositionZ());
|
||||
|
||||
// xinef: changed to -1, we dont want to catch last node
|
||||
for (uint32 i = 0; i < nodeList.size() - 1; ++i)
|
||||
for (uint32 i = 1; i < nodeList.size(); ++i)
|
||||
{
|
||||
TaxiPathNodeEntry const* node = nodeList[i];
|
||||
TaxiPathNodeEntry const* nextNode = nodeList[i + 1];
|
||||
TaxiPathNodeEntry const* prevNode = nodeList[i - 1];
|
||||
|
||||
// xinef: skip nodes at another map, get last valid node on current map
|
||||
if (nextNode->mapid != GetMapId() || node->mapid != GetMapId())
|
||||
// skip nodes at another map
|
||||
if (node->mapid != GetMapId())
|
||||
continue;
|
||||
|
||||
currDist = (node->x - GetPositionX()) * (node->x - GetPositionX()) + (node->y - GetPositionY()) * (node->y - GetPositionY()) + (node->z - GetPositionZ()) * (node->z - GetPositionZ());
|
||||
if (currDist < bestDist)
|
||||
distPrev = distNext;
|
||||
distNext =
|
||||
(node->x - GetPositionX()) * (node->x - GetPositionX()) +
|
||||
(node->y - GetPositionY()) * (node->y - GetPositionY()) +
|
||||
(node->z - GetPositionZ()) * (node->z - GetPositionZ());
|
||||
|
||||
float distNodes =
|
||||
(node->x - prevNode->x) * (node->x - prevNode->x) +
|
||||
(node->y - prevNode->y) * (node->y - prevNode->y) +
|
||||
(node->z - prevNode->z) * (node->z - prevNode->z);
|
||||
|
||||
if (distPrev + distNext < distNodes)
|
||||
{
|
||||
startNode = i;
|
||||
bestDist = currDist;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1436,7 +1436,7 @@ void Player::UpdatePvPState()
|
||||
|
||||
if (pvpInfo.IsHostile) // in hostile area
|
||||
{
|
||||
if (IsInFlight()) // on taxi
|
||||
if (IsInFlight() || !m_taxi.empty()) // on taxi or taxi pending resume after login
|
||||
return;
|
||||
|
||||
if (!IsPvP() || pvpInfo.EndTimer != 0)
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
#include "WorldPacket.h"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
float baseMoveSpeed[MAX_MOVE_TYPE] =
|
||||
{
|
||||
@@ -910,6 +911,9 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, uint32 effectMask, Unit
|
||||
if (!spellInfo)
|
||||
return false;
|
||||
|
||||
if (spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES) && !HasSpiritOfRedemptionAura())
|
||||
return false;
|
||||
|
||||
bool immuneToAllEffects = true;
|
||||
bool hasCheckedEffect = false;
|
||||
|
||||
@@ -940,8 +944,28 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, uint32 effectMask, Unit
|
||||
|
||||
if (!spellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES))
|
||||
{
|
||||
if (IsImmunedToSchool(spellInfo))
|
||||
return true;
|
||||
if (spellInfo->Id == 42292 || spellInfo->Id == 59752 || spellInfo->Id == 19574 || spellInfo->Id == 34471)
|
||||
return false;
|
||||
|
||||
SpellSchoolMask schoolMask = spellInfo->GetSchoolMask();
|
||||
if (schoolMask != SPELL_SCHOOL_MASK_NONE)
|
||||
{
|
||||
SpellImmuneContainer const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
|
||||
for (auto const& [immunitySchoolMask, immunityAuraId] : schoolList)
|
||||
{
|
||||
SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(immunityAuraId);
|
||||
if ((immunitySchoolMask & schoolMask) != schoolMask)
|
||||
continue;
|
||||
|
||||
if (IgnoresSchoolImmunityFromFriendlyCaster(caster, immunityAuraId, immuneSpellInfo))
|
||||
continue;
|
||||
|
||||
if (spellInfo->CanPierceImmuneAura(immuneSpellInfo))
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -1204,7 +1228,8 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
|
||||
if (!attacker || attacker->IsControlledByPlayer() || attacker->IsCreatedByPlayer())
|
||||
{
|
||||
uint32 unDamage = health < damage ? health : damage;
|
||||
bool damagedByPlayer = unDamage && attacker && (attacker->IsPlayer() || attacker->m_movedByPlayer != nullptr);
|
||||
bool damagedByPlayer = unDamage && attacker && (attacker->IsPlayer() || attacker->m_movedByPlayer != nullptr
|
||||
|| attacker->GetCharmerOrOwnerGUID().IsPlayer());
|
||||
victim->ToCreature()->LowerPlayerDamageReq(unDamage, damagedByPlayer);
|
||||
}
|
||||
}
|
||||
@@ -2193,7 +2218,7 @@ bool Unit::IsDamageReducedByArmor(SpellSchoolMask schoolMask, SpellInfo const* s
|
||||
{
|
||||
if (spellInfo->Effects[effIndex].ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE ||
|
||||
spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_SCHOOL_DAMAGE)
|
||||
if (spellInfo->GetEffectMechanicMask(effIndex) & (1 << MECHANIC_BLEED))
|
||||
if (spellInfo->GetEffectMechanicMask(effIndex) & (1ULL << MECHANIC_BLEED))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -5489,7 +5514,7 @@ void Unit::RemoveAurasWithFamily(SpellFamilyNames family, uint32 familyFlag1, ui
|
||||
void Unit::RemoveMovementImpairingAuras(bool withRoot)
|
||||
{
|
||||
if (withRoot)
|
||||
RemoveAurasWithMechanic(1 << MECHANIC_ROOT);
|
||||
RemoveAurasWithMechanic(1ULL << MECHANIC_ROOT);
|
||||
|
||||
// Snares
|
||||
for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
|
||||
@@ -5524,7 +5549,7 @@ void Unit::RemoveAurasWithMechanic(uint64 mechanic_mask, AuraRemoveMode removemo
|
||||
|
||||
void Unit::RemoveAurasByShapeShift()
|
||||
{
|
||||
uint64 mechanic_mask = (UI64LIT(1) << MECHANIC_SNARE) | (UI64LIT(1) << MECHANIC_ROOT);
|
||||
uint64 mechanic_mask = (1ULL << MECHANIC_SNARE) | (1ULL << MECHANIC_ROOT);
|
||||
for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
|
||||
{
|
||||
Aura const* aura = iter->second->GetBase();
|
||||
@@ -6081,12 +6106,12 @@ 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 & (UI64LIT(1) << spellInfo->Mechanic)))
|
||||
if (spellInfo->Mechanic && (mechanicMask & (1ULL << 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 & (UI64LIT(1) << spellInfo->Effects[i].Mechanic))
|
||||
if (mechanicMask & (1ULL << spellInfo->Effects[i].Mechanic))
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -8596,7 +8621,7 @@ float Unit::SpellPctDamageModsDone(Unit* victim, SpellInfo const* spellProto, Da
|
||||
|
||||
// Torment the weak
|
||||
if (spellProto->SpellFamilyFlags[0] & 0x20600021 || spellProto->SpellFamilyFlags[1] & 0x9000)
|
||||
if (victim->HasAuraWithMechanic((1 << MECHANIC_SNARE) | (1 << MECHANIC_SLOW_ATTACK)))
|
||||
if (victim->HasAuraWithMechanic((1ULL << MECHANIC_SNARE) | (1ULL << MECHANIC_SLOW_ATTACK)))
|
||||
if (AuraEffect* aurEff = GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_GENERIC, 3263, EFFECT_0))
|
||||
AddPct(DoneTotalMod, aurEff->GetAmount());
|
||||
break;
|
||||
@@ -8915,7 +8940,7 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui
|
||||
if (!caster || caster->GetGUID() != (*i)->GetCasterGUID())
|
||||
continue;
|
||||
|
||||
if (mechanicMask & uint64(UI64LIT(1) << (*i)->GetMiscValue()))
|
||||
if (mechanicMask & (1ULL << (*i)->GetMiscValue()))
|
||||
{
|
||||
if ((*i)->GetAmount() > 0)
|
||||
{
|
||||
@@ -9223,7 +9248,7 @@ float Unit::SpellTakenCritChance(Unit const* caster, SpellInfo const* spellProto
|
||||
case SPELLFAMILY_MAGE:
|
||||
// Glyph of Fire Blast
|
||||
if (spellProto->SpellFamilyFlags[0] == 0x2 && spellProto->SpellIconID == 12)
|
||||
if (HasAuraWithMechanic((1 << MECHANIC_STUN) | (1 << MECHANIC_KNOCKOUT)))
|
||||
if (HasAuraWithMechanic((1ULL << MECHANIC_STUN) | (1ULL << MECHANIC_KNOCKOUT)))
|
||||
if (AuraEffect const* aurEff = caster->GetAuraEffect(56369, EFFECT_0))
|
||||
crit_chance += aurEff->GetAmount();
|
||||
break;
|
||||
@@ -9815,6 +9840,18 @@ uint32 Unit::GetDamageImmunityMask() const
|
||||
return mask;
|
||||
}
|
||||
|
||||
bool Unit::IgnoresSchoolImmunityFromFriendlyCaster(Unit const* caster, uint32 immunityAuraId, SpellInfo const* immunitySpellInfo) const
|
||||
{
|
||||
if (!caster || !caster->IsFriendlyTo(this))
|
||||
return false;
|
||||
|
||||
if (immunitySpellInfo)
|
||||
return !immunitySpellInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS);
|
||||
|
||||
// Creature template immunities are loaded with a placeholder spell id.
|
||||
return immunityAuraId == std::numeric_limits<uint32>::max();
|
||||
}
|
||||
|
||||
bool Unit::IsImmunedToDamage(SpellSchoolMask schoolMask) const
|
||||
{
|
||||
if (schoolMask == SPELL_SCHOOL_MASK_NONE)
|
||||
@@ -9852,7 +9889,7 @@ bool Unit::IsImmunedToDamage(Unit const* caster, SpellInfo const* spellInfo) con
|
||||
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))
|
||||
if (IgnoresSchoolImmunityFromFriendlyCaster(caster, immunityAuraId, immuneAuraInfo))
|
||||
continue;
|
||||
|
||||
if (immuneAuraInfo && spellInfo->CanPierceImmuneAura(immuneAuraInfo))
|
||||
@@ -9933,7 +9970,10 @@ bool Unit::IsImmunedToSchool(Spell const* spell) const
|
||||
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)))
|
||||
SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(itr->second);
|
||||
if ((itr->first & schoolMask) == schoolMask
|
||||
&& !IgnoresSchoolImmunityFromFriendlyCaster(spell->GetCaster(), itr->second, immuneSpellInfo)
|
||||
&& !spellInfo->CanPierceImmuneAura(immuneSpellInfo))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -9971,7 +10011,7 @@ bool Unit::IsImmunedToAuraPeriodicTick(Unit const* caster, SpellInfo const* spel
|
||||
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))
|
||||
if (IgnoresSchoolImmunityFromFriendlyCaster(caster, immunityAuraId, immuneAuraInfo))
|
||||
continue;
|
||||
|
||||
schoolImmunityMask |= immunitySchoolMask;
|
||||
@@ -10050,6 +10090,7 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell)
|
||||
if (!spellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES))
|
||||
{
|
||||
SpellSchoolMask spellSchoolMask = spellInfo->GetSchoolMask();
|
||||
Unit const* spellCaster = spell ? spell->GetCaster() : nullptr;
|
||||
if (spell)
|
||||
{
|
||||
spellSchoolMask = spell->GetSpellSchoolMask();
|
||||
@@ -10064,12 +10105,8 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell)
|
||||
if (!(itr->first & spellSchoolMask))
|
||||
continue;
|
||||
|
||||
if (immuneSpellInfo && !immuneSpellInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS))
|
||||
{
|
||||
Unit const* spellCaster = spell ? spell->GetCaster() : nullptr;
|
||||
if (spellCaster && spellCaster->IsFriendlyTo(this))
|
||||
continue;
|
||||
}
|
||||
if (IgnoresSchoolImmunityFromFriendlyCaster(spellCaster, itr->second, immuneSpellInfo))
|
||||
continue;
|
||||
|
||||
if (spellInfo->CanPierceImmuneAura(immuneSpellInfo))
|
||||
continue;
|
||||
@@ -10369,13 +10406,13 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT
|
||||
|
||||
// Shred, Maul - "Effects which increase Bleed damage also increase Shred damage"
|
||||
if (spellProto->SpellFamilyName == SPELLFAMILY_DRUID && spellProto->SpellFamilyFlags[0] & 0x00008800)
|
||||
mechanicMask |= (UI64LIT(1) << MECHANIC_BLEED);
|
||||
mechanicMask |= (1ULL << MECHANIC_BLEED);
|
||||
|
||||
if (mechanicMask)
|
||||
{
|
||||
TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT, [mechanicMask](AuraEffect const* aurEff) -> bool
|
||||
{
|
||||
if (mechanicMask & uint64(UI64LIT(1) << (aurEff->GetMiscValue())))
|
||||
if (mechanicMask & (1ULL << (aurEff->GetMiscValue())))
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
@@ -11220,8 +11257,8 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
|
||||
if (Creature* creature = ToCreature())
|
||||
{
|
||||
// use creature helper which now consults creature_immunities table
|
||||
if (creature->HasMechanicTemplateImmunity(UI64LIT(1) << MECHANIC_SNARE) ||
|
||||
creature->HasMechanicTemplateImmunity(UI64LIT(1) << MECHANIC_DAZE))
|
||||
if (creature->HasMechanicTemplateImmunity(1ULL << MECHANIC_SNARE) ||
|
||||
creature->HasMechanicTemplateImmunity(1ULL << MECHANIC_DAZE))
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -11242,7 +11279,7 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
|
||||
if (creature
|
||||
&& !IsPet()
|
||||
&& !(IsControlledByPlayer() && IsVehicle())
|
||||
&& !(creature->HasMechanicTemplateImmunity(UI64LIT(1) << MECHANIC_SNARE))
|
||||
&& !(creature->HasMechanicTemplateImmunity(1ULL << MECHANIC_SNARE))
|
||||
&& !(creature->IsDungeonBoss()))
|
||||
{
|
||||
// 1.6% for each % under 30.
|
||||
@@ -11498,12 +11535,12 @@ Unit* Creature::SelectVictim()
|
||||
return target;
|
||||
}
|
||||
|
||||
// last case when creature must not go to evade mode:
|
||||
// it in combat but attacker not make any damage and not enter to aggro radius to have record in threat list
|
||||
// Note: creature does not have targeted movement generator but has attacker in this case
|
||||
for (AttackerSet::const_iterator itr = m_attackers.begin(); itr != m_attackers.end(); ++itr)
|
||||
if ((*itr) && CanCreatureAttack(*itr) && !(*itr)->IsPlayer() && !(*itr)->ToCreature()->HasUnitTypeMask(UNIT_MASK_CONTROLLABLE_GUARDIAN))
|
||||
return nullptr;
|
||||
// Don't evade if another unit has us on their threat list — evading would
|
||||
// end the bidirectional combat reference and remove us from their threat list,
|
||||
// causing them to lose their target (e.g. an NPC fighting a guardian whose
|
||||
// CanAIAttack rejects the NPC).
|
||||
if (!m_threatManager.GetThreatenedByMeList().empty())
|
||||
return nullptr;
|
||||
|
||||
if (GetVehicle())
|
||||
return nullptr;
|
||||
@@ -11600,7 +11637,7 @@ int32 Unit::ModSpellDuration(SpellInfo const* spellProto, Unit const* target, in
|
||||
// xinef: also calculate self casts, spell can be reflected for example
|
||||
if (!positive)
|
||||
{
|
||||
int32 mechanic = spellProto->GetSpellMechanicMaskByEffectMask(effectMask);
|
||||
uint64 mechanic = spellProto->GetSpellMechanicMaskByEffectMask(effectMask);
|
||||
|
||||
int32 durationMod;
|
||||
int32 durationMod_always = 0;
|
||||
@@ -11608,11 +11645,11 @@ int32 Unit::ModSpellDuration(SpellInfo const* spellProto, Unit const* target, in
|
||||
|
||||
for (uint8 i = 1; i <= MECHANIC_ENRAGED; ++i)
|
||||
{
|
||||
if (!(mechanic & 1 << i))
|
||||
if (!(mechanic & (1ULL << i)))
|
||||
continue;
|
||||
|
||||
// Xinef: spells affecting movement imparing effects should not reduce duration if disoriented mechanic is present
|
||||
if (i == MECHANIC_SNARE && (mechanic & (1 << MECHANIC_DISORIENTED)))
|
||||
if (i == MECHANIC_SNARE && (mechanic & (1ULL << MECHANIC_DISORIENTED)))
|
||||
continue;
|
||||
|
||||
// Find total mod value (negative bonus)
|
||||
@@ -15121,7 +15158,7 @@ Aura* Unit::AddAura(SpellInfo const* spellInfo, uint8 effMask, Unit* target)
|
||||
if (!spellInfo)
|
||||
return nullptr;
|
||||
|
||||
if (target->IsImmunedToSpell(spellInfo))
|
||||
if (target->IsImmunedToSpell(spellInfo, effMask, this))
|
||||
return nullptr;
|
||||
|
||||
for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
|
||||
@@ -1638,6 +1638,7 @@ public:
|
||||
void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply, SpellImmuneBlockType blockType = SPELL_BLOCK_TYPE_ALL);
|
||||
virtual bool IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell = nullptr);
|
||||
bool IsImmunedToSpell(SpellInfo const* spellInfo, uint32 effectMask, Unit const* caster = nullptr);
|
||||
bool IgnoresSchoolImmunityFromFriendlyCaster(Unit const* caster, uint32 immunityAuraId, SpellInfo const* immunitySpellInfo) const;
|
||||
[[nodiscard]] bool IsImmunedToDamage(SpellSchoolMask schoolMask) const;
|
||||
[[nodiscard]] bool IsImmunedToDamage(Unit const* caster, SpellInfo const* spellInfo) const;
|
||||
[[nodiscard]] bool IsImmunedToSchool(SpellSchoolMask schoolMask) const;
|
||||
|
||||
@@ -1492,7 +1492,7 @@ void Group::CountTheRoll(Rolls::iterator rollI, Map* allowedMap)
|
||||
AllowedLooterSet looters = item->GetAllowedLooters();
|
||||
Item* _item = player->StoreNewItem(dest, roll->itemid, true, item->randomPropertyId, looters);
|
||||
if (_item)
|
||||
sScriptMgr->OnPlayerGroupRollRewardItem(player, _item, _item->GetCount(), NEED, roll);
|
||||
sScriptMgr->OnPlayerGroupRollRewardItem(player, _item, item->count, NEED, roll);
|
||||
player->UpdateLootAchievements(item, roll->getLoot());
|
||||
}
|
||||
else
|
||||
@@ -1562,7 +1562,7 @@ void Group::CountTheRoll(Rolls::iterator rollI, Map* allowedMap)
|
||||
AllowedLooterSet looters = item->GetAllowedLooters();
|
||||
Item* _item = player->StoreNewItem(dest, roll->itemid, true, item->randomPropertyId, looters);
|
||||
if (_item)
|
||||
sScriptMgr->OnPlayerGroupRollRewardItem(player, _item, _item->GetCount(), GREED, roll);
|
||||
sScriptMgr->OnPlayerGroupRollRewardItem(player, _item, item->count, GREED, roll);
|
||||
player->UpdateLootAchievements(item, roll->getLoot());
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1125,6 +1125,13 @@ void WorldSession::HandlePlayerLoginToCharInWorld(Player* pCurrChar)
|
||||
ChatHandler chH = ChatHandler(this);
|
||||
m_playerLoading = true;
|
||||
|
||||
// Exit vehicle on reconnect - the client has fully reset so
|
||||
// the player can no longer control the vehicle. Without this
|
||||
// the player is stuck: server-side still seated, but the
|
||||
// client has no vehicle UI or movement control.
|
||||
if (pCurrChar->GetVehicle())
|
||||
pCurrChar->ExitVehicle();
|
||||
|
||||
pCurrChar->SendDungeonDifficulty(false);
|
||||
|
||||
WorldPacket data(SMSG_LOGIN_VERIFY_WORLD, 20);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "Battleground.h"
|
||||
#include "ConditionMgr.h"
|
||||
#include "BattlegroundMgr.h"
|
||||
#include "Creature.h"
|
||||
#include "DatabaseEnv.h"
|
||||
@@ -150,6 +151,11 @@ void WorldSession::HandleGossipHelloOpcode(WorldPacket& recvData)
|
||||
if (unit->GetNpcFlags() == UNIT_NPC_FLAG_NONE)
|
||||
return;
|
||||
|
||||
// Check GossipHello conditions - block gossip opening if conditions not met
|
||||
ConditionList gossipConditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_GOSSIP_HELLO, unit->GetEntry());
|
||||
if (!sConditionMgr->IsObjectMeetToConditions(_player, unit, gossipConditions))
|
||||
return;
|
||||
|
||||
// set faction visible if needed
|
||||
if (FactionTemplateEntry const* factionTemplateEntry = sFactionTemplateStore.LookupEntry(unit->GetFaction()))
|
||||
_player->GetReputationMgr().SetVisible(factionTemplateEntry);
|
||||
|
||||
@@ -441,8 +441,26 @@ bool LootItem::AllowedForPlayer(Player const* player, ObjectGuid source) const
|
||||
return false;
|
||||
|
||||
// check quest requirements
|
||||
if (needs_quest && !pProto->HasFlagCu(ITEM_FLAGS_CU_IGNORE_QUEST_STATUS) && !player->HasQuestForItem(itemid))
|
||||
return false;
|
||||
if (!pProto->HasFlagCu(ITEM_FLAGS_CU_IGNORE_QUEST_STATUS))
|
||||
{
|
||||
if (needs_quest && !player->HasQuestForItem(itemid))
|
||||
return false;
|
||||
|
||||
// Hide quest starter items when quest is already started/rewarded,
|
||||
// when unique count is already reached, or when prerequisite is missing.
|
||||
if (pProto->StartQuest)
|
||||
{
|
||||
uint32 prevQuestId = 0;
|
||||
if (Quest const* startQuest = sObjectMgr->GetQuestTemplate(pProto->StartQuest))
|
||||
prevQuestId = startQuest->GetPrevQuestId();
|
||||
|
||||
if (player->GetQuestStatus(pProto->StartQuest) != QUEST_STATUS_NONE ||
|
||||
player->GetQuestRewardStatus(pProto->StartQuest) ||
|
||||
(pProto->MaxCount && player->HasItemCount(itemid, pProto->MaxCount, true)) ||
|
||||
(prevQuestId && !player->GetQuestRewardStatus(prevQuestId)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sScriptMgr->OnAllowedForPlayerLootCheck(player, source))
|
||||
return false;
|
||||
|
||||
@@ -215,15 +215,15 @@ bool OPvPCapturePoint::DelObject(uint32 type)
|
||||
|
||||
bool OPvPCapturePoint::DelCapturePoint()
|
||||
{
|
||||
sObjectMgr->DeleteGOData(m_capturePointSpawnId);
|
||||
m_capturePointSpawnId = 0;
|
||||
|
||||
if (_capturePoint)
|
||||
{
|
||||
_capturePoint->SetRespawnTime(0); // not save respawn time
|
||||
_capturePoint->Delete();
|
||||
}
|
||||
|
||||
sObjectMgr->DeleteGOData(m_capturePointSpawnId);
|
||||
m_capturePointSpawnId = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1223,7 +1223,7 @@ bool AuraEffect::CheckEffectProc(AuraApplication* aurApp, ProcEventInfo& eventIn
|
||||
case SPELL_AURA_MECHANIC_IMMUNITY:
|
||||
case SPELL_AURA_MOD_MECHANIC_RESISTANCE:
|
||||
// compare mechanic
|
||||
if (!spellInfo || !(spellInfo->GetAllEffectsMechanicMask() & (UI64LIT(1) << GetMiscValue())))
|
||||
if (!spellInfo || !(spellInfo->GetAllEffectsMechanicMask() & (1ULL << GetMiscValue())))
|
||||
return false;
|
||||
break;
|
||||
case SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK:
|
||||
|
||||
@@ -6828,7 +6828,7 @@ SpellCastResult Spell::CheckCasterAuras(bool preventionOnly) const
|
||||
return SPELL_CAST_OK;
|
||||
|
||||
uint8 school_immune = 0;
|
||||
uint32 mechanic_immune = 0;
|
||||
uint64 mechanic_immune = 0;
|
||||
uint32 dispel_immune = 0;
|
||||
|
||||
// Check if the spell grants school or mechanic immunity.
|
||||
@@ -6840,7 +6840,7 @@ SpellCastResult Spell::CheckCasterAuras(bool preventionOnly) const
|
||||
if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_SCHOOL_IMMUNITY)
|
||||
school_immune |= uint32(m_spellInfo->Effects[i].MiscValue);
|
||||
else if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MECHANIC_IMMUNITY)
|
||||
mechanic_immune |= 1 << uint32(m_spellInfo->Effects[i].MiscValue);
|
||||
mechanic_immune |= 1ULL << uint32(m_spellInfo->Effects[i].MiscValue);
|
||||
else if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_DISPEL_IMMUNITY)
|
||||
dispel_immune |= SpellInfo::GetDispelMask(DispelType(m_spellInfo->Effects[i].MiscValue));
|
||||
}
|
||||
@@ -6871,13 +6871,13 @@ SpellCastResult Spell::CheckCasterAuras(bool preventionOnly) const
|
||||
if (usableInStun)
|
||||
{
|
||||
bool foundNotStun = false;
|
||||
uint32 mask = (1 << MECHANIC_STUN) | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_HORROR);
|
||||
uint64 mask = (1ULL << MECHANIC_STUN) | (1ULL << MECHANIC_FREEZE) | (1ULL << MECHANIC_HORROR);
|
||||
// Barkskin should skip sleep effects, sap and fears
|
||||
if (m_spellInfo->Id == 22812)
|
||||
mask |= 1 << MECHANIC_SAPPED | 1 << MECHANIC_HORROR | 1 << MECHANIC_SLEEP;
|
||||
mask |= 1ULL << MECHANIC_SAPPED | 1ULL << MECHANIC_HORROR | 1ULL << MECHANIC_SLEEP;
|
||||
// Hand of Freedom, can be used while sapped and while under fear-mechanic stuns (e.g. Intimidating Shout primary target)
|
||||
if (m_spellInfo->Id == 1044)
|
||||
mask |= (1 << MECHANIC_SAPPED) | (1 << MECHANIC_FEAR);
|
||||
mask |= (1ULL << MECHANIC_SAPPED) | (1ULL << MECHANIC_FEAR);
|
||||
Unit::AuraEffectList const& stunAuras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_STUN);
|
||||
for (Unit::AuraEffectList::const_iterator i = stunAuras.begin(); i != stunAuras.end(); ++i)
|
||||
{
|
||||
@@ -6936,13 +6936,13 @@ SpellCastResult Spell::CheckCasterAuras(bool preventionOnly) const
|
||||
{
|
||||
case SPELL_AURA_MOD_STUN:
|
||||
{
|
||||
uint32 mask = 1 << MECHANIC_STUN;
|
||||
uint64 mask = 1ULL << MECHANIC_STUN;
|
||||
// Barkskin should skip sleep effects, sap and fears
|
||||
if (m_spellInfo->Id == 22812)
|
||||
mask |= 1 << MECHANIC_SAPPED | 1 << MECHANIC_HORROR | 1 << MECHANIC_SLEEP;
|
||||
mask |= 1ULL << MECHANIC_SAPPED | 1ULL << MECHANIC_HORROR | 1ULL << MECHANIC_SLEEP;
|
||||
// Hand of Freedom, can be used while sapped and while under fear-mechanic stuns (e.g. Intimidating Shout primary target)
|
||||
if (m_spellInfo->Id == 1044)
|
||||
mask |= (1 << MECHANIC_SAPPED) | (1 << MECHANIC_FEAR);
|
||||
mask |= (1ULL << MECHANIC_SAPPED) | (1ULL << MECHANIC_FEAR);
|
||||
|
||||
if (!usableInStun || !(auraInfo->GetAllEffectsMechanicMask() & mask))
|
||||
return SPELL_FAILED_STUNNED;
|
||||
|
||||
@@ -856,7 +856,7 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex)
|
||||
SpellInfo const* spell = iter->second->GetBase()->GetSpellInfo();
|
||||
|
||||
// Pounce Bleed shouldn't be removed by Cloak of Shadows.
|
||||
if (spell->GetAllEffectsMechanicMask() & (UI64LIT(1) << MECHANIC_BLEED))
|
||||
if (spell->GetAllEffectsMechanicMask() & (1ULL << MECHANIC_BLEED))
|
||||
return;
|
||||
|
||||
bool dmgClassNone = false;
|
||||
@@ -2493,8 +2493,8 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
|
||||
|
||||
if (properties->Category == SUMMON_CATEGORY_ALLY)
|
||||
{
|
||||
summon->SetOwnerGUID(m_originalCaster->GetGUID());
|
||||
summon->SetFaction(m_originalCaster->GetFaction());
|
||||
summon->SetOwnerGUID(summoner->GetGUID());
|
||||
summon->SetFaction(summoner->GetFaction());
|
||||
}
|
||||
|
||||
ExecuteLogEffectSummonObject(effIndex, summon);
|
||||
@@ -5157,7 +5157,7 @@ void Spell::EffectDispelMechanic(SpellEffIndex effIndex)
|
||||
continue;
|
||||
if (roll_chance_i(aura->CalcDispelChance(unitTarget, !unitTarget->IsFriendlyTo(m_caster))))
|
||||
{
|
||||
if ((aura->GetSpellInfo()->GetAllEffectsMechanicMask() & (UI64LIT(1) << mechanic)))
|
||||
if (aura->GetSpellInfo()->GetAllEffectsMechanicMask() & (1ULL << mechanic))
|
||||
{
|
||||
dispel_list.push(std::make_pair(aura->GetId(), aura->GetCasterGUID()));
|
||||
|
||||
|
||||
@@ -1900,10 +1900,10 @@ uint64 SpellInfo::GetAllEffectsMechanicMask() const
|
||||
{
|
||||
uint64 mask = 0;
|
||||
if (Mechanic)
|
||||
mask |= UI64LIT(1) << Mechanic;
|
||||
mask |= 1ULL << Mechanic;
|
||||
for (int i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
if (Effects[i].IsEffect() && Effects[i].Mechanic)
|
||||
mask |= UI64LIT(1) << Effects[i].Mechanic;
|
||||
mask |= 1ULL << Effects[i].Mechanic;
|
||||
return mask;
|
||||
}
|
||||
|
||||
@@ -1911,9 +1911,9 @@ uint64 SpellInfo::GetEffectMechanicMask(uint8 effIndex) const
|
||||
{
|
||||
uint64 mask = 0;
|
||||
if (Mechanic)
|
||||
mask |= UI64LIT(1) << Mechanic;
|
||||
mask |= 1ULL << Mechanic;
|
||||
if (Effects[effIndex].IsEffect() && Effects[effIndex].Mechanic)
|
||||
mask |= UI64LIT(1) << Effects[effIndex].Mechanic;
|
||||
mask |= 1ULL << Effects[effIndex].Mechanic;
|
||||
return mask;
|
||||
}
|
||||
|
||||
@@ -1921,10 +1921,10 @@ uint64 SpellInfo::GetSpellMechanicMaskByEffectMask(uint32 effectMask) const
|
||||
{
|
||||
uint64 mask = 0;
|
||||
if (Mechanic)
|
||||
mask |= UI64LIT(1) << Mechanic;
|
||||
mask |= 1ULL << Mechanic;
|
||||
for (int i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
if ((effectMask & (1 << i)) && Effects[i].Mechanic)
|
||||
mask |= UI64LIT(1) << Effects[i].Mechanic;
|
||||
mask |= 1ULL << Effects[i].Mechanic;
|
||||
return mask;
|
||||
}
|
||||
|
||||
@@ -2008,7 +2008,7 @@ AuraStateType SpellInfo::LoadAuraState() const
|
||||
return AURA_STATE_ENRAGE;
|
||||
|
||||
// Bleeding aura state
|
||||
if (GetAllEffectsMechanicMask() & (UI64LIT(1) << MECHANIC_BLEED))
|
||||
if (GetAllEffectsMechanicMask() & (1ULL << MECHANIC_BLEED))
|
||||
return AURA_STATE_BLEEDING;
|
||||
|
||||
// Banished aura state
|
||||
|
||||
@@ -705,7 +705,7 @@ public:
|
||||
|
||||
handler->PSendSysMessage(LANG_NPCINFO_MECHANIC_IMMUNE, Acore::StringFormat("0x{:X}", mechanicImmuneMask).c_str());
|
||||
for (uint8 i = 1; i < MAX_MECHANIC; ++i)
|
||||
if (mechanicImmuneMask & (UI64LIT(1) << i))
|
||||
if (mechanicImmuneMask & (1ULL << i))
|
||||
handler->PSendSysMessage(mechanicImmunes[i].text, mechanicImmunes[i].flag);
|
||||
|
||||
handler->PSendSysMessage(LANG_NPCINFO_SPELL_SCHOOL_IMMUNE, spellSchoolImmuneMask);
|
||||
|
||||
@@ -80,6 +80,7 @@ enum Events
|
||||
EVENT_MIGHT_OF_RAGNAROS,
|
||||
EVENT_LAVA_BURST,
|
||||
EVENT_MAGMA_BLAST,
|
||||
EVENT_MELEE_SCAN,
|
||||
EVENT_SUBMERGE,
|
||||
EVENT_LAVA_BURST_TRIGGER,
|
||||
|
||||
@@ -218,29 +219,6 @@ struct boss_ragnaros : public BossAI
|
||||
DoStartNoMovement(target);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (!me->GetThreatMgr().IsThreatListEmpty())
|
||||
{
|
||||
if (!_processingMagmaBurst)
|
||||
{
|
||||
// Boss try to evade, but still got some targets on threat list - it means that none of these targets are in melee range - cast magma blast
|
||||
_processingMagmaBurst = true;
|
||||
events.ScheduleEvent(EVENT_MAGMA_BLAST, 4s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BossAI::EnterEvadeMode(why);
|
||||
}
|
||||
}
|
||||
|
||||
bool CanAIAttack(Unit const* victim) const override
|
||||
{
|
||||
// Used for Magma Blast handling to force EnterEvadeMode if there are no melee targets
|
||||
return me->IsWithinMeleeRange(victim);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!extraEvents.Empty())
|
||||
@@ -307,10 +285,7 @@ struct boss_ragnaros : public BossAI
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
if (!_processingMagmaBurst)
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
@@ -348,19 +323,47 @@ struct boss_ragnaros : public BossAI
|
||||
DoCastAOE(SPELL_LAVA_BURST);
|
||||
break;
|
||||
}
|
||||
case EVENT_MELEE_SCAN:
|
||||
{
|
||||
// ReselectVictim() in the threat system already prefers
|
||||
// in-melee-range targets, so if the current victim is out
|
||||
// of melee range it means *nobody* is in range. Use that
|
||||
// as the trigger for the Magma Blast fallback.
|
||||
if (!IsVictimWithinMeleeRange())
|
||||
{
|
||||
if (!_processingMagmaBurst)
|
||||
{
|
||||
_processingMagmaBurst = true;
|
||||
events.ScheduleEvent(EVENT_MAGMA_BLAST, 4s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
}
|
||||
}
|
||||
else if (_processingMagmaBurst)
|
||||
{
|
||||
events.CancelEvent(EVENT_MAGMA_BLAST);
|
||||
_processingMagmaBurst = false;
|
||||
}
|
||||
events.Repeat(500ms);
|
||||
break;
|
||||
}
|
||||
case EVENT_MAGMA_BLAST:
|
||||
{
|
||||
_processingMagmaBurst = false;
|
||||
|
||||
if (!IsVictimWithinMeleeRange())
|
||||
if (IsVictimWithinMeleeRange())
|
||||
break;
|
||||
|
||||
if (Unit* victim = me->GetVictim())
|
||||
{
|
||||
DoCastRandomTarget(SPELL_MAGMA_BLAST);
|
||||
DoCast(victim, SPELL_MAGMA_BLAST);
|
||||
|
||||
if (!_hasYelledMagmaBurst)
|
||||
{
|
||||
Talk(SAY_MAGMABURST);
|
||||
_hasYelledMagmaBurst = true;
|
||||
}
|
||||
|
||||
_processingMagmaBurst = true;
|
||||
events.ScheduleEvent(EVENT_MAGMA_BLAST, 4s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -454,12 +457,14 @@ private:
|
||||
events.RescheduleEvent(EVENT_LAVA_BURST, 10s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
events.RescheduleEvent(EVENT_SUBMERGE, 180s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
events.RescheduleEvent(EVENT_MIGHT_OF_RAGNAROS, 11s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
events.RescheduleEvent(EVENT_MELEE_SCAN, 500ms, PHASE_EMERGED, PHASE_EMERGED);
|
||||
}
|
||||
|
||||
bool IsVictimWithinMeleeRange() const
|
||||
{
|
||||
return me->GetVictim() && me->IsWithinMeleeRange(me->GetVictim());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
constexpr std::array<uint32, 8> RagnarosLavaBurstSpells = { SPELL_LAVA_BURST_A, SPELL_LAVA_BURST_B, SPELL_LAVA_BURST_C, SPELL_LAVA_BURST_D, SPELL_LAVA_BURST_E, SPELL_LAVA_BURST_F, SPELL_LAVA_BURST_G, SPELL_LAVA_BURST_H };
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "CreatureScript.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptedGossip.h"
|
||||
#include "SpellAuras.h"
|
||||
|
||||
enum Orphans
|
||||
@@ -628,9 +629,33 @@ private:
|
||||
/*######
|
||||
## npc_cw_alexstrasza_trigger
|
||||
######*/
|
||||
enum eAlexstrasza
|
||||
{
|
||||
SPELL_KEY_TO_FOCUSING_IRIS = 60989,
|
||||
SPELL_HEROIC_KEY_TO_FOCUSING_IRIS = 60992,
|
||||
};
|
||||
|
||||
struct npc_alexstraza_the_lifebinder : public ScriptedAI
|
||||
{
|
||||
npc_alexstraza_the_lifebinder(Creature* creature) : ScriptedAI(creature) {}
|
||||
explicit npc_alexstraza_the_lifebinder(Creature* creature) : ScriptedAI(creature) {}
|
||||
|
||||
void sGossipSelect(Player* player, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
switch (action)
|
||||
{
|
||||
case 0:
|
||||
CloseGossipMenuFor(player);
|
||||
player->CastSpell(player, SPELL_KEY_TO_FOCUSING_IRIS, false);
|
||||
break;
|
||||
case 1:
|
||||
CloseGossipMenuFor(player);
|
||||
player->CastSpell(player, SPELL_HEROIC_KEY_TO_FOCUSING_IRIS, false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
@@ -653,6 +678,8 @@ struct npc_alexstraza_the_lifebinder : public ScriptedAI
|
||||
case 2:
|
||||
me->SetOrientation(me->GetHomePosition().GetOrientation());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -767,8 +794,8 @@ struct npc_alexstraza_the_lifebinder : public ScriptedAI
|
||||
}
|
||||
|
||||
private:
|
||||
int8 phase;
|
||||
uint32 timer;
|
||||
int8 phase{};
|
||||
uint32 timer{};
|
||||
ObjectGuid playerGUID;
|
||||
ObjectGuid orphanGUID;
|
||||
};
|
||||
|
||||
@@ -136,7 +136,7 @@ enum Misc
|
||||
// Movement points
|
||||
POINT_LANDING = 1,
|
||||
|
||||
// Lava directions. Its used to identify to which side lava was moving by last time
|
||||
// Lava directions
|
||||
LAVA_LEFT_SIDE = 0,
|
||||
LAVA_RIGHT_SIDE = 1,
|
||||
|
||||
@@ -307,7 +307,6 @@ struct boss_sartharion : public BossAI
|
||||
{
|
||||
explicit boss_sartharion(Creature* creature) : BossAI(creature, DATA_SARTHARION),
|
||||
dragonsCount(0),
|
||||
lastLavaSide(LAVA_RIGHT_SIDE),
|
||||
usedBerserk(false),
|
||||
below11PctReached(false)
|
||||
{
|
||||
@@ -628,8 +627,8 @@ private:
|
||||
extraEvents.ScheduleEvent(EVENT_SARTHARION_START_LAVA, 3600ms);
|
||||
extraEvents.ScheduleEvent(EVENT_SARTHARION_FINISH_LAVA, 11s);
|
||||
|
||||
// Send wave from left
|
||||
if (lastLavaSide == LAVA_RIGHT_SIDE)
|
||||
// Randomly choose which side the wave comes from
|
||||
if (urand(LAVA_LEFT_SIDE, LAVA_RIGHT_SIDE) == LAVA_LEFT_SIDE)
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_LEFT_LAVA_TSUNAMIS; ++i)
|
||||
{
|
||||
@@ -638,10 +637,7 @@ private:
|
||||
if (((i - 1) % 3 == 0) && tsunami) // If center of wave
|
||||
tsunami->CastSpell(tsunami, SPELL_FLAME_TSUNAMI_VISUAL, true);
|
||||
}
|
||||
|
||||
lastLavaSide = LAVA_LEFT_SIDE;
|
||||
}
|
||||
// from right
|
||||
else
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_RIGHT_LAVA_TSUNAMIS; ++i)
|
||||
@@ -651,8 +647,6 @@ private:
|
||||
if (((i - 1) % 3 == 0) && tsunami) // If center of wave
|
||||
tsunami->CastSpell(tsunami, SPELL_FLAME_TSUNAMI_VISUAL, true);
|
||||
}
|
||||
|
||||
lastLavaSide = LAVA_RIGHT_SIDE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -683,7 +677,6 @@ private:
|
||||
EventMap extraEvents;
|
||||
std::list<uint32> volcanoBlows;
|
||||
uint8 dragonsCount;
|
||||
uint8 lastLavaSide; // 0 = left, 1 = right
|
||||
bool usedBerserk;
|
||||
bool below11PctReached;
|
||||
};
|
||||
|
||||
@@ -224,7 +224,7 @@ class spell_uk_second_wind : public AuraScript
|
||||
if (!spellInfo)
|
||||
return false;
|
||||
|
||||
return (spellInfo->GetAllEffectsMechanicMask() & ((1 << MECHANIC_ROOT) | (1 << MECHANIC_STUN))) != 0;
|
||||
return (spellInfo->GetAllEffectsMechanicMask() & ((1ULL << MECHANIC_ROOT) | (1ULL << MECHANIC_STUN))) != 0;
|
||||
}
|
||||
|
||||
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
|
||||
|
||||
@@ -128,7 +128,7 @@ struct boss_lady_vashj : public BossAI
|
||||
summon->CastSpell(summon, SPELL_MAGIC_BARRIER);
|
||||
break;
|
||||
case NPC_ENCHANTED_ELEMENTAL:
|
||||
summon->GetMotionMaster()->MoveFollow(me, 0.0f, 0.0f, MOTION_SLOT_ACTIVE, false);
|
||||
summon->GetMotionMaster()->MoveFollow(me, 0.0f, 0.0f, MOTION_SLOT_ACTIVE, false, false);
|
||||
summon->SetWalk(true);
|
||||
summon->SetReactState(REACT_PASSIVE);
|
||||
break;
|
||||
|
||||
@@ -242,10 +242,11 @@ struct boss_magtheridon : public BossAI
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
scheduler.Update(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
scheduler.Update(diff);
|
||||
_interruptScheduler.Update(diff);
|
||||
|
||||
if (_currentPhase != 1 && !_castingQuake)
|
||||
|
||||
@@ -385,11 +385,11 @@ public:
|
||||
|
||||
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (attacker && attacker->GetCharmerOrOwnerOrOwnGUID().IsPlayer() && damage > 0 && !me->isActiveObject())
|
||||
if (attacker && attacker->GetCharmerOrOwnerOrOwnGUID().IsPlayer() && damage > 0 && instance->GetBossState(DATA_WARDEN_MELLICHAR) != IN_PROGRESS)
|
||||
{
|
||||
me->setActive(true);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
me->SetImmuneToAll(true);
|
||||
me->SetImmuneToAll(true, true);
|
||||
events.ScheduleEvent(EVENT_WARDEN_INTRO1, 1500ms);
|
||||
events.ScheduleEvent(EVENT_WARDEN_CHECK_PLAYERS, 1s);
|
||||
instance->SetBossState(DATA_WARDEN_MELLICHAR, IN_PROGRESS);
|
||||
|
||||
@@ -3001,7 +3001,7 @@ class spell_dk_pvp_4p_bonus : public AuraScript
|
||||
if (!spellInfo)
|
||||
return false;
|
||||
|
||||
return (spellInfo->GetAllEffectsMechanicMask() & ((1 << MECHANIC_ROOT) | (1 << MECHANIC_SNARE))) != 0;
|
||||
return (spellInfo->GetAllEffectsMechanicMask() & ((1ULL << MECHANIC_ROOT) | (1ULL << MECHANIC_SNARE))) != 0;
|
||||
}
|
||||
|
||||
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
|
||||
|
||||
@@ -770,7 +770,7 @@ class spell_dru_moonkin_form_passive : public AuraScript
|
||||
void Absorb(AuraEffect* /*aurEff*/, DamageInfo& dmgInfo, uint32& absorbAmount)
|
||||
{
|
||||
// reduces all damage taken while Stunned in Moonkin Form
|
||||
if (GetTarget()->GetUnitFlags() & (UNIT_FLAG_STUNNED) && GetTarget()->HasAuraWithMechanic(1 << MECHANIC_STUN))
|
||||
if (GetTarget()->GetUnitFlags() & (UNIT_FLAG_STUNNED) && GetTarget()->HasAuraWithMechanic(1ULL << MECHANIC_STUN))
|
||||
absorbAmount = CalculatePct(dmgInfo.GetDamage(), absorbPct);
|
||||
}
|
||||
|
||||
@@ -837,7 +837,7 @@ class spell_dru_primal_tenacity : public AuraScript
|
||||
void Absorb(AuraEffect* /*aurEff*/, DamageInfo& dmgInfo, uint32& absorbAmount)
|
||||
{
|
||||
// reduces all damage taken while Stunned in Cat Form
|
||||
if (GetTarget()->GetShapeshiftForm() == FORM_CAT && GetTarget()->HasUnitFlag(UNIT_FLAG_STUNNED) && GetTarget()->HasAuraWithMechanic(1 << MECHANIC_STUN))
|
||||
if (GetTarget()->GetShapeshiftForm() == FORM_CAT && GetTarget()->HasUnitFlag(UNIT_FLAG_STUNNED) && GetTarget()->HasAuraWithMechanic(1ULL << MECHANIC_STUN))
|
||||
absorbAmount = CalculatePct(dmgInfo.GetDamage(), absorbPct);
|
||||
}
|
||||
|
||||
|
||||
@@ -4372,7 +4372,7 @@ class spell_item_luffa : public SpellScript
|
||||
for (Unit::AuraApplicationMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
|
||||
{
|
||||
Aura const* aura = itr->second->GetBase();
|
||||
if (!(aura->GetSpellInfo()->GetAllEffectsMechanicMask() & (1 << MECHANIC_BLEED)) || aura->GetCasterLevel() > 60 || aura->GetSpellInfo()->IsPositive())
|
||||
if (!(aura->GetSpellInfo()->GetAllEffectsMechanicMask() & (1ULL << MECHANIC_BLEED)) || aura->GetCasterLevel() > 60 || aura->GetSpellInfo()->IsPositive())
|
||||
continue;
|
||||
|
||||
return SPELL_CAST_OK;
|
||||
@@ -4392,7 +4392,7 @@ class spell_item_luffa : public SpellScript
|
||||
for (Unit::AuraApplicationMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
|
||||
{
|
||||
Aura const* aura = itr->second->GetBase();
|
||||
if (!(aura->GetSpellInfo()->GetAllEffectsMechanicMask() & (1 << MECHANIC_BLEED)) || aura->GetCasterLevel() > 60 || aura->GetSpellInfo()->IsPositive())
|
||||
if (!(aura->GetSpellInfo()->GetAllEffectsMechanicMask() & (1ULL << MECHANIC_BLEED)) || aura->GetCasterLevel() > 60 || aura->GetSpellInfo()->IsPositive())
|
||||
continue;
|
||||
|
||||
player->RemoveAurasDueToSpell(aura->GetId(), aura->GetCasterGUID());
|
||||
|
||||
@@ -120,7 +120,7 @@ class spell_mage_burning_determination : public AuraScript
|
||||
return false;
|
||||
|
||||
// Need Interrupt or Silenced mechanic
|
||||
if (!(eventInfo.GetSpellInfo()->GetAllEffectsMechanicMask() & ((1 << MECHANIC_INTERRUPT) | (1 << MECHANIC_SILENCE))))
|
||||
if (!(eventInfo.GetSpellInfo()->GetAllEffectsMechanicMask() & ((1ULL << MECHANIC_INTERRUPT) | (1ULL << MECHANIC_SILENCE))))
|
||||
return false;
|
||||
|
||||
// Xinef: immuned effect should just eat charge
|
||||
|
||||
@@ -1486,7 +1486,7 @@ class spell_pal_divine_purpose : public AuraScript
|
||||
{
|
||||
PreventDefaultAction();
|
||||
if (Unit* target = eventInfo.GetActionTarget())
|
||||
target->RemoveAurasWithMechanic(1 << MECHANIC_STUN, AURA_REMOVE_BY_ENEMY_SPELL);
|
||||
target->RemoveAurasWithMechanic(1ULL << MECHANIC_STUN, AURA_REMOVE_BY_ENEMY_SPELL);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
|
||||
@@ -473,7 +473,7 @@ class spell_pri_mana_burn : public SpellScript
|
||||
void HandleAfterHit()
|
||||
{
|
||||
if (Unit* unitTarget = GetHitUnit())
|
||||
unitTarget->RemoveAurasWithMechanic((1 << MECHANIC_FEAR) | (1 << MECHANIC_POLYMORPH));
|
||||
unitTarget->RemoveAurasWithMechanic((1ULL << MECHANIC_FEAR) | (1ULL << MECHANIC_POLYMORPH));
|
||||
}
|
||||
|
||||
void Register() override
|
||||
|
||||
@@ -735,13 +735,13 @@ class spell_rog_vanish_purge : public SpellScript
|
||||
void HandleRootRemove(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (GetCaster() && !GetCaster()->HasAura(SPELL_PARALYZE)) // Root from Tainted Core SSC, should not be removed by vanish.
|
||||
GetCaster()->RemoveAurasWithMechanic(1 << MECHANIC_ROOT);
|
||||
GetCaster()->RemoveAurasWithMechanic(1ULL << MECHANIC_ROOT);
|
||||
}
|
||||
|
||||
void HandleSnareRemove(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (GetCaster())
|
||||
GetCaster()->RemoveAurasWithMechanic(1 << MECHANIC_SNARE);
|
||||
GetCaster()->RemoveAurasWithMechanic(1ULL << MECHANIC_SNARE);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
|
||||
@@ -1494,7 +1494,7 @@ class spell_sha_astral_shift_aura : public AuraScript
|
||||
bool CheckProc(ProcEventInfo& eventInfo)
|
||||
{
|
||||
if (SpellInfo const* spellInfo = eventInfo.GetSpellInfo())
|
||||
if (spellInfo->GetAllEffectsMechanicMask() & ((1 << MECHANIC_SILENCE) | (1 << MECHANIC_STUN) | (1 << MECHANIC_FEAR)))
|
||||
if (spellInfo->GetAllEffectsMechanicMask() & ((1ULL << MECHANIC_SILENCE) | (1ULL << MECHANIC_STUN) | (1ULL << MECHANIC_FEAR)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
||||
@@ -927,7 +927,7 @@ class spell_warl_demonic_circle_teleport : public AuraScript
|
||||
if (GameObject* circle = player->GetGameObject(SPELL_WARLOCK_DEMONIC_CIRCLE_SUMMON))
|
||||
{
|
||||
player->NearTeleportTo(circle->GetPositionX(), circle->GetPositionY(), circle->GetPositionZ(), circle->GetOrientation(), false, false, false, true);
|
||||
player->RemoveAurasWithMechanic(1 << MECHANIC_SNARE);
|
||||
player->RemoveAurasWithMechanic(1ULL << MECHANIC_SNARE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -612,7 +612,7 @@ class spell_warr_shattering_throw : public SpellScript
|
||||
|
||||
// remove shields, will still display immune to damage part
|
||||
if (Unit* target = GetHitUnit())
|
||||
target->RemoveAurasWithMechanic(1 << MECHANIC_IMMUNE_SHIELD, AURA_REMOVE_BY_ENEMY_SPELL);
|
||||
target->RemoveAurasWithMechanic(1ULL << MECHANIC_IMMUNE_SHIELD, AURA_REMOVE_BY_ENEMY_SPELL);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
@@ -1013,7 +1013,7 @@ class spell_warr_second_wind : public AuraScript
|
||||
return false;
|
||||
|
||||
// Must be from stun or root mechanic
|
||||
if (!(procSpell->GetAllEffectsMechanicMask() & ((1 << MECHANIC_ROOT) | (1 << MECHANIC_STUN))))
|
||||
if (!(procSpell->GetAllEffectsMechanicMask() & ((1ULL << MECHANIC_ROOT) | (1ULL << MECHANIC_STUN))))
|
||||
return false;
|
||||
|
||||
// Not from self
|
||||
|
||||
@@ -1352,22 +1352,22 @@ enum Mechanics : uint32
|
||||
|
||||
// Used for spell 42292 Immune Movement Impairment and Loss of Control (0x49967ca6)
|
||||
inline constexpr uint64 IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK =
|
||||
(UI64LIT(1) << MECHANIC_CHARM) |
|
||||
(UI64LIT(1) << MECHANIC_DISORIENTED) |
|
||||
(UI64LIT(1) << MECHANIC_FEAR) |
|
||||
(UI64LIT(1) << MECHANIC_ROOT) |
|
||||
(UI64LIT(1) << MECHANIC_SLEEP) |
|
||||
(UI64LIT(1) << MECHANIC_SNARE) |
|
||||
(UI64LIT(1) << MECHANIC_STUN) |
|
||||
(UI64LIT(1) << MECHANIC_FREEZE) |
|
||||
(UI64LIT(1) << MECHANIC_KNOCKOUT) |
|
||||
(UI64LIT(1) << MECHANIC_POLYMORPH) |
|
||||
(UI64LIT(1) << MECHANIC_BANISH) |
|
||||
(UI64LIT(1) << MECHANIC_SHACKLE) |
|
||||
(UI64LIT(1) << MECHANIC_TURN) |
|
||||
(UI64LIT(1) << MECHANIC_HORROR) |
|
||||
(UI64LIT(1) << MECHANIC_DAZE) |
|
||||
(UI64LIT(1) << MECHANIC_SAPPED);
|
||||
(1ULL << MECHANIC_CHARM) |
|
||||
(1ULL << MECHANIC_DISORIENTED) |
|
||||
(1ULL << MECHANIC_FEAR) |
|
||||
(1ULL << MECHANIC_ROOT) |
|
||||
(1ULL << MECHANIC_SLEEP) |
|
||||
(1ULL << MECHANIC_SNARE) |
|
||||
(1ULL << MECHANIC_STUN) |
|
||||
(1ULL << MECHANIC_FREEZE) |
|
||||
(1ULL << MECHANIC_KNOCKOUT) |
|
||||
(1ULL << MECHANIC_POLYMORPH) |
|
||||
(1ULL << MECHANIC_BANISH) |
|
||||
(1ULL << MECHANIC_SHACKLE) |
|
||||
(1ULL << MECHANIC_TURN) |
|
||||
(1ULL << MECHANIC_HORROR) |
|
||||
(1ULL << MECHANIC_DAZE) |
|
||||
(1ULL << MECHANIC_SAPPED);
|
||||
|
||||
// Spell dispel type
|
||||
enum DispelType : uint8
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include "Unit.h" // needed for SpellSchoolMask and mask helper
|
||||
@@ -79,30 +80,24 @@ namespace
|
||||
|
||||
bool HasOnlyDamageEffects(SpellDesc const& spell)
|
||||
{
|
||||
bool hasAny = false;
|
||||
|
||||
for (EffectDesc const& e : spell.effects)
|
||||
bool hasAny = std::ranges::any_of(spell.effects, [](EffectDesc const& effect)
|
||||
{
|
||||
if (e.effect == EFFECT_NONE)
|
||||
continue;
|
||||
return effect.effect != EFFECT_NONE;
|
||||
});
|
||||
|
||||
hasAny = true;
|
||||
if (!IsDamageEffect(e.effect))
|
||||
return false;
|
||||
}
|
||||
|
||||
return hasAny;
|
||||
return hasAny && std::ranges::all_of(spell.effects, [](EffectDesc const& effect)
|
||||
{
|
||||
return effect.effect == EFFECT_NONE || IsDamageEffect(effect.effect);
|
||||
});
|
||||
}
|
||||
|
||||
// Helper to classify spells which apply a stun aura
|
||||
bool IsStunSpell(SpellDesc const& spell)
|
||||
{
|
||||
for (EffectDesc const& e : spell.effects)
|
||||
return std::ranges::any_of(spell.effects, [](EffectDesc const& effect)
|
||||
{
|
||||
if (e.effect == EFFECT_APPLY_AURA && e.aura == AURA_MOD_STUN)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return effect.effect == EFFECT_APPLY_AURA && effect.aura == AURA_MOD_STUN;
|
||||
});
|
||||
}
|
||||
|
||||
bool IsEffectBlockedByStunImmunity(EffectDesc const& effect, bool immuneToStun)
|
||||
@@ -130,6 +125,11 @@ namespace
|
||||
return hasAnyEffect;
|
||||
}
|
||||
|
||||
bool IsBlockedBySchoolImmunity(bool casterFriendly, bool immunityAppliesToFriendly)
|
||||
{
|
||||
return !casterFriendly || immunityAppliesToFriendly;
|
||||
}
|
||||
|
||||
// The last parameter defaults to false to avoid updating existing tests
|
||||
// that don't care about mechanic immunities. Bladestorm grants a
|
||||
// specific mechanic immunity (including stun) that should block
|
||||
@@ -364,3 +364,18 @@ TEST(SpellImmunityTest, StunImmunity_DoesNotFullyBlockMixedSpell)
|
||||
EXPECT_TRUE(IsStunSpell(mixedSpell));
|
||||
EXPECT_EQ(ComputeSpellHitResult(false, false, mixedSpell, true), SPELL_MISS_NONE);
|
||||
}
|
||||
|
||||
TEST(SpellImmunityTest, SchoolImmunity_TemplateStyle_AllowsFriendlySpell)
|
||||
{
|
||||
EXPECT_FALSE(IsBlockedBySchoolImmunity(true, false));
|
||||
}
|
||||
|
||||
TEST(SpellImmunityTest, SchoolImmunity_ExplicitFriendlyBlockStillApplies)
|
||||
{
|
||||
EXPECT_TRUE(IsBlockedBySchoolImmunity(true, true));
|
||||
}
|
||||
|
||||
TEST(SpellImmunityTest, SchoolImmunity_BlocksHostileSpell)
|
||||
{
|
||||
EXPECT_TRUE(IsBlockedBySchoolImmunity(false, false));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user