diff --git a/.github/ISSUE_TEMPLATE/ee_cc.yml b/.github/ISSUE_TEMPLATE/ee_cc.yml index 4ed34e08e..ad7d6744a 100644 --- a/.github/ISSUE_TEMPLATE/ee_cc.yml +++ b/.github/ISSUE_TEMPLATE/ee_cc.yml @@ -8,5 +8,10 @@ body: label: Triage description: | Paste the issue from ChromieCraft here. + value: | + Issue linked from CC: + Triage Notes: + Original Post Below: + --- validations: required: true diff --git a/apps/installer/includes/functions.sh b/apps/installer/includes/functions.sh index 3c9b2edba..79fbb355d 100644 --- a/apps/installer/includes/functions.sh +++ b/apps/installer/includes/functions.sh @@ -155,7 +155,7 @@ function inst_simple_restarter { function inst_download_client_data { # change the following version when needed - local VERSION=v18.0 + local VERSION=v19 echo "#######################" echo "Client data downloader" diff --git a/data/sql/updates/db_world/2025_11_24_00.sql b/data/sql/updates/db_world/2025_11_24_00.sql new file mode 100644 index 000000000..ccbf878eb --- /dev/null +++ b/data/sql/updates/db_world/2025_11_24_00.sql @@ -0,0 +1,6 @@ +-- DB update 2025_11_23_00 -> 2025_11_24_00 +-- +-- Set GOSSIP flag +UPDATE `creature_template` SET `npcflag` = `npcflag` | 1 WHERE (`entry` IN (34712, 34713, 34714, 34786, 34785)); +-- 10568 -- Hello, $N. If you're looking for cooking training, you've come to the right place. I usually get lots of new students when Pilgrim's Bounty rolls around. +UPDATE `creature_template` SET `gossip_menu_id` = 10568 WHERE (`entry` IN (34708, 34712, 34713, 34714, 34786, 34785, 34711)); diff --git a/data/sql/updates/db_world/2025_11_24_01.sql b/data/sql/updates/db_world/2025_11_24_01.sql new file mode 100644 index 000000000..3811b0c7d --- /dev/null +++ b/data/sql/updates/db_world/2025_11_24_01.sql @@ -0,0 +1,3 @@ +-- DB update 2025_11_24_00 -> 2025_11_24_01 +-- +UPDATE `quest_template_addon` SET `PrevQuestID` = 0 WHERE (`ID` = 11311); diff --git a/data/sql/updates/db_world/2025_11_24_02.sql b/data/sql/updates/db_world/2025_11_24_02.sql new file mode 100644 index 000000000..751231a40 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_24_02.sql @@ -0,0 +1,5 @@ +-- DB update 2025_11_24_01 -> 2025_11_24_02 +-- Alliance +UPDATE `conditions` SET `ConditionValue1` = 11248, `Comment` = 'Vrykul Scroll of Ascension - Requires quest Operation: Skornful Wrath completed' WHERE `SourceTypeOrReferenceId` = 1 AND `SourceEntry` = 33314 AND `ConditionTypeOrReference` = 8 AND `ConditionValue1` = 11247; +-- Horde +UPDATE `conditions` SET `ConditionValue1` = 11256, `Comment` = 'Vrykul Scroll of Ascension - Requires quest Skorn Must Fall! completed' WHERE `SourceTypeOrReferenceId` = 1 AND `SourceEntry` = 33345 AND `ConditionTypeOrReference` = 8 AND `ConditionValue1` = 11258; diff --git a/data/sql/updates/db_world/2025_11_24_03.sql b/data/sql/updates/db_world/2025_11_24_03.sql new file mode 100644 index 000000000..2a8f48c4f --- /dev/null +++ b/data/sql/updates/db_world/2025_11_24_03.sql @@ -0,0 +1,3 @@ +-- DB update 2025_11_24_02 -> 2025_11_24_03 +-- +UPDATE `quest_template_addon` SET `PrevQuestID` = 0 WHERE (`ID` = 12487); diff --git a/data/sql/updates/db_world/2025_11_25_00.sql b/data/sql/updates/db_world/2025_11_25_00.sql new file mode 100644 index 000000000..6579ab65d --- /dev/null +++ b/data/sql/updates/db_world/2025_11_25_00.sql @@ -0,0 +1,3 @@ +-- DB update 2025_11_24_03 -> 2025_11_25_00 +-- Light Won't Grant Me Vengeance requires Crusader Forward Camp +UPDATE `quest_template_addon` SET `PrevQuestID` = 12894 WHERE `ID` = 12904; diff --git a/data/sql/updates/db_world/2025_11_25_01.sql b/data/sql/updates/db_world/2025_11_25_01.sql new file mode 100644 index 000000000..6ef704bb9 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_25_01.sql @@ -0,0 +1,3 @@ +-- DB update 2025_11_25_00 -> 2025_11_25_01 +-- Makes the quest "Remember Everfrost" repetable +UPDATE `quest_template_addon` SET `SpecialFlags` = `SpecialFlags` | 1 WHERE `ID` = 13421; diff --git a/data/sql/updates/db_world/2025_11_25_02.sql b/data/sql/updates/db_world/2025_11_25_02.sql new file mode 100644 index 000000000..49dd26164 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_25_02.sql @@ -0,0 +1,3 @@ +-- DB update 2025_11_25_01 -> 2025_11_25_02 +-- Removes the pre-quest for Elixir of Pain [502] for Elixir of Agony +UPDATE `quest_template_addon` SET `PrevQuestID` = 0 WHERE (`ID` = 509); diff --git a/data/sql/updates/db_world/2025_11_26_00.sql b/data/sql/updates/db_world/2025_11_26_00.sql new file mode 100644 index 000000000..5dc5d3596 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_26_00.sql @@ -0,0 +1,7 @@ +-- DB update 2025_11_25_02 -> 2025_11_26_00 +-- +SET @link = 8; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 28948 AND `source_type` = 0 AND `id` = @link; +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 +(28948, 0, @link, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 0, 60, 0, 0, 0, 0, 14, 268515, 190949, 0, 0, 0, 0, 0, 0, 'Malmortis - On Just Summoned - Despawn Instant (Musty Coffin)'); +UPDATE `smart_scripts` SET `link` = @link WHERE `entryorguid` = 28948 AND `source_type` = 0 AND `id` = 1; diff --git a/data/sql/updates/db_world/2025_11_26_01.sql b/data/sql/updates/db_world/2025_11_26_01.sql new file mode 100644 index 000000000..a6aedf138 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_26_01.sql @@ -0,0 +1,17 @@ +-- DB update 2025_11_26_00 -> 2025_11_26_01 +-- +DELETE FROM `waypoint_data` WHERE `id`=125946; + +UPDATE `creature_template_movement` SET `Flight` = 0 WHERE (`CreatureId` = 24083); + +DELETE FROM `creature` WHERE (`id1` = 24083) AND (`guid` IN (1971380)); +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`, `Comment`, `VerifiedBuild`) VALUES +(1971380, 24083, 0, 0, 574, 0, 0, 3, 1, 0, 209.1206, -187.86578, 200.00346, 0.677681, 3600, 0, 0, 71856, 0, 0, 0, 0, 0, '', NULL, 0); + +DELETE FROM `vehicle_accessory` WHERE `guid` = 1971380 AND `accessory_entry` = 24849; +INSERT INTO `vehicle_accessory` (`guid`, `accessory_entry`, `seat_id`, `minion`, `description`, `summontype`, `summontimer`) VALUES +(1971380, 24849, 0, 0, 'Proto Drake Rider mounted to Enslaved Proto Drake', 6, 30000); + +DELETE FROM `creature_movement_override` WHERE `SpawnId`=1971380; +INSERT INTO `creature_movement_override` (`SpawnId`, `Ground`, `Swim`, `Flight`, `Rooted`, `Chase`, `Random`, `InteractionPauseTimer`) VALUES +(1971380, 1, 1, 2, 0, 0, 0, NULL); diff --git a/data/sql/updates/db_world/2025_11_26_02.sql b/data/sql/updates/db_world/2025_11_26_02.sql new file mode 100644 index 000000000..9288d17df --- /dev/null +++ b/data/sql/updates/db_world/2025_11_26_02.sql @@ -0,0 +1,9 @@ +-- DB update 2025_11_26_01 -> 2025_11_26_02 +-- +-- Quest item Ahunae's Knife can target dead Heb'Drakkar Headhunter or dead Heb'Drakkar Striker +DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 17) AND (`SourceEntry` = 52090); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(17, 0, 52090, 0, 0, 31, 1, 3, 28600, 0, 0, 173, 0, '', 'Item 38731 "Ahunae\'s Knife" targets 28600 dead "Heb\'Drakkar Headhunter"'), +(17, 0, 52090, 0, 0, 36, 1, 0, 0, 0, 1, 173, 0, '', 'Item 38731 "Ahunae\'s Knife" targets 28600 dead "Heb\'Drakkar Headhunter"'), +(17, 0, 52090, 0, 1, 31, 1, 3, 28465, 0, 0, 173, 0, '', 'Item 38731 "Ahunae\'s Knife" targets 28465 dead "Heb\'Drakkar Striker"'), +(17, 0, 52090, 0, 1, 36, 1, 0, 0, 0, 1, 173, 0, '', 'Item 38731 "Ahunae\'s Knife" targets 28465 dead "Heb\'Drakkar Striker"'); diff --git a/data/sql/updates/db_world/2025_11_26_03.sql b/data/sql/updates/db_world/2025_11_26_03.sql new file mode 100644 index 000000000..c47de4525 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_26_03.sql @@ -0,0 +1,113 @@ +-- DB update 2025_11_26_02 -> 2025_11_26_03 + +-- Set right factions (sniffed) +UPDATE `creature_template` SET `faction` = 2068 WHERE (`entry` = 31301); +UPDATE `creature_template` SET `faction` = 1770 WHERE (`entry` = 31306); +UPDATE `creature_template` SET `faction` = 2102 WHERE (`entry` = 30698); + +-- Set Unit Flags (sniffed) +UPDATE `creature_template` SET `unit_flags` = `unit_flags` |64 WHERE (`entry` = 30698); +UPDATE `creature_template` SET `unit_flags` = `unit_flags` |32768 WHERE (`entry` IN (31314, 31428)); + +-- Set emote 25 on text 0 (Crusader Olakin Sainrith) +UPDATE `creature_text` SET `Emote` = 25 WHERE (`CreatureID` = 31428) AND (`GroupID` IN (0)); + +-- Delete Olakin spawn point (it must be summoned) +DELETE FROM `creature` WHERE `id1` = 31428; + +-- Set new Sniffed Spawn Points (Margrave Dhakar, Ebon Blade Veteran) +DELETE FROM `creature` WHERE (`id1` IN (31306, 31314)); +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 +(74974, 31306, 0, 0, 571, 0, 0, 1, 175, 1, 6865.82, 3577.98, 736.045, 2.93215, 300, 0, 0, 37800, 11982, 0, 0, 0, 0, '', NULL, 0, NULL), +(75082, 31314, 0, 0, 571, 0, 0, 1, 175, 1, 6865.11, 3570.75, 736.079, 3.01942, 120, 0, 0, 12600, 3994, 0, 0, 0, 0, '', NULL, 0, NULL), +(75083, 31314, 0, 0, 571, 0, 0, 1, 175, 1, 6868.48, 3579.73, 736.148, 2.9496, 120, 0, 0, 12600, 3994, 0, 0, 0, 0, '', NULL, 0, NULL), +(75084, 31314, 0, 0, 571, 0, 0, 1, 175, 1, 6866.22, 3574.63, 735.908, 3.03687, 120, 0, 0, 12600, 3994, 0, 0, 0, 0, '', NULL, 0, NULL), +(75085, 31314, 0, 0, 571, 0, 0, 1, 175, 1, 6869.78, 3584.1, 735.892, 2.87979, 120, 0, 0, 12600, 3994, 0, 0, 0, 0, '', NULL, 0, NULL); + +-- SmartAI (Margrave Dhakar) +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 31306; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 31306); +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 +(31306, 0, 0, 1, 62, 0, 100, 0, 10060, 0, 0, 0, 0, 0, 64, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Margrave Dhakar - On Gossip Option 0 Selected - Store Targetlist'), +(31306, 0, 1, 2, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Margrave Dhakar - On Gossip Option 0 Selected - Close Gossip'), +(31306, 0, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Margrave Dhakar - On Gossip Option 0 Selected - Set Npc Flag '), +(31306, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 80, 3130600, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Margrave Dhakar - On Gossip Option 0 Selected - Run Script'), +(31306, 0, 4, 5, 38, 0, 100, 0, 1, 1, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Margrave Dhakar - On Data Set 1 1 - Set Event Phase 1'), +(31306, 0, 5, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 10, 74956, 30698, 0, 0, 0, 0, 0, 0, 'Margrave Dhakar - On Data Set 1 1 - Start Attacking'), +(31306, 0, 6, 0, 7, 1, 100, 0, 0, 0, 0, 0, 0, 0, 80, 3130601, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Margrave Dhakar - On Evade - Run Script (Phase 1)'), +(31306, 0, 7, 0, 4, 1, 100, 0, 0, 0, 0, 0, 0, 0, 11, 58949, 2, 0, 0, 0, 0, 10, 74956, 30698, 0, 0, 0, 0, 0, 0, 'Margrave Dhakar - On Aggro - Cast \'Ride Morbidus\' (Phase 1)'), +(31306, 0, 8, 0, 0, 0, 100, 1, 1000, 2000, 0, 0, 0, 0, 11, 37548, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Margrave Dhakar - In Combat - Cast \'Taunt\' (No Repeat)'), +(31306, 0, 9, 0, 0, 0, 100, 0, 3000, 4000, 6000, 8000, 0, 0, 11, 5547, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Margrave Dhakar - In Combat - Cast \'Swing\''); + +-- Action List (Margrave Dhakar) +DELETE FROM `smart_scripts` WHERE (`source_type` = 9) AND (`entryorguid` IN (3130600, 3130601)); +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 +(3130600, 9, 0, 0, 0, 0, 100, 0, 1000, 1000, 0, 0, 0, 0, 12, 31301, 8, 0, 0, 0, 0, 8, 0, 0, 0, 0, 6858.5957, 3580.4998, 736.75116, 5.67231, 'Margrave Dhakar - Actionlist - Summon Creature \'The Lich King\''), +(3130600, 9, 1, 0, 0, 0, 100, 0, 1000, 1000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Margrave Dhakar - Actionlist - Say Line 0'), +(3130601, 9, 0, 0, 0, 0, 100, 0, 3000, 3000, 0, 0, 0, 0, 5, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Margrave Dhakar - Actionlist - Play Emote 4'), +(3130601, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Margrave Dhakar - Actionlist - Despawn In 5000 ms'); + +-- SmartAI (Lich King) +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 31301; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 31301); +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 +(31301, 0, 0, 0, 54, 0, 100, 512, 0, 0, 0, 0, 0, 0, 80, 3130100, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'The Lich King - On Just Summoned - Run Script'); + +-- Action List (Lich King) +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 3130100); +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 +(3130100, 9, 0, 0, 0, 0, 100, 0, 100, 100, 0, 0, 0, 0, 11, 34427, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'The Lich King - Actionlist - Cast \'Ethereal Teleport\''), +(3130100, 9, 1, 0, 0, 0, 100, 0, 500, 500, 0, 0, 0, 0, 11, 53274, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'The Lich King - Actionlist - Cast \'Icebound Visage\''), +(3130100, 9, 2, 0, 0, 0, 100, 0, 1000, 1000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'The Lich King - Actionlist - Say Line 0'), +(3130100, 9, 3, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'The Lich King - Actionlist - Say Line 1'), +(3130100, 9, 4, 0, 0, 0, 100, 0, 4000, 4000, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'The Lich King - Actionlist - Say Line 2'), +(3130100, 9, 5, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'The Lich King - Actionlist - Say Line 3'), +(3130100, 9, 6, 0, 0, 0, 100, 0, 8000, 8000, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'The Lich King - Actionlist - Say Line 4'), +(3130100, 9, 7, 0, 0, 0, 100, 0, 6000, 6000, 0, 0, 0, 0, 12, 31428, 8, 0, 0, 0, 0, 8, 0, 0, 0, 0, 6857.33, 3571.49, 735.892, 1.15191, 'The Lich King - Actionlist - Summon Creature \'Crusader Olakin Sainrith\''), +(3130100, 9, 8, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, 30698, 0, 0, 0, 0, 0, 0, 0, 'The Lich King - Actionlist - Set Data 1 1'), +(3130100, 9, 9, 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, 'The Lich King - Actionlist - Despawn Instant'); + +-- SmartAI (Crusader Olakin Sainrith) +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 31428; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 31428); +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 +(31428, 0, 0, 1, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 2, 1770, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Crusader Olakin Sainrith - On Just Summoned - Set Faction 1770'), +(31428, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 80, 3142800, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Crusader Olakin Sainrith - On Just Summoned - Run Script'), +(31428, 0, 2, 3, 38, 0, 100, 0, 1, 1, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Crusader Olakin Sainrith - On Data Set 1 1 - Set Event Phase 1'), +(31428, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 10, 74956, 30698, 0, 0, 0, 0, 0, 0, 'Crusader Olakin Sainrith - On Data Set 1 1 - Start Attacking'), +(31428, 0, 4, 0, 7, 1, 100, 0, 0, 0, 0, 0, 0, 0, 41, 8000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Crusader Olakin Sainrith - On Evade - Despawn In 8000 ms (Phase 1)'); + +-- Action List (Crusader Olakin Sainrith) +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 3142800); +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 +(3142800, 9, 0, 0, 0, 0, 100, 0, 3000, 3000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Crusader Olakin Sainrith - Actionlist - Say Line 0'); + +-- SmartAI (Morbidus) +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 30698; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 30698); +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 +(30698, 0, 0, 0, 38, 0, 100, 0, 1, 1, 0, 0, 0, 0, 80, 3069800, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Morbidus - On Data Set 1 1 - Run Script'), +(30698, 0, 1, 0, 25, 0, 100, 0, 0, 0, 0, 0, 0, 0, 18, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Morbidus - On Reset - Set Flags Immune To Players & Immune To NPC\'s'), +(30698, 0, 2, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 33, 30698, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 'Morbidus - On Just Died - Quest Credit \'null\''); + +-- Action List (Morbidus) +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 3069800); +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 +(3069800, 9, 0, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 0, 0, 19, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Morbidus - Actionlist - Remove Flags Immune To Players & Immune To NPC\'s'), +(3069800, 9, 1, 0, 0, 0, 100, 0, 200, 200, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 9, 31306, 0, 200, 0, 0, 0, 0, 0, 'Morbidus - Actionlist - Set Data 1 1'), +(3069800, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 9, 31428, 0, 200, 0, 0, 0, 0, 0, 'Morbidus - Actionlist - Set Data 1 1'), +(3069800, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 9, 31314, 0, 200, 0, 0, 0, 0, 0, 'Morbidus - Actionlist - Set Data 1 1'); + +-- SmartAI (Ebon Blade Veteran) +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 31314; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 31314); +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 +(31314, 0, 0, 1, 38, 0, 100, 0, 1, 1, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Ebon Blade Veteran - On Data Set 1 1 - Set Event Phase 1'), +(31314, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 10, 74956, 30698, 0, 0, 0, 0, 0, 0, 'Ebon Blade Veteran - On Data Set 1 1 - Start Attacking'), +(31314, 0, 2, 0, 0, 0, 100, 0, 3000, 6000, 10000, 14000, 0, 0, 11, 50688, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Ebon Blade Veteran - In Combat - Cast \'Plague Strike\''), +(31314, 0, 3, 0, 7, 1, 100, 0, 0, 0, 0, 0, 0, 0, 41, 12000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Ebon Blade Veteran - On Evade - Despawn In 12000 ms (Phase 1)'); diff --git a/data/sql/updates/db_world/2025_11_26_04.sql b/data/sql/updates/db_world/2025_11_26_04.sql new file mode 100644 index 000000000..1464e8d16 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_26_04.sql @@ -0,0 +1,3 @@ +-- DB update 2025_11_26_03 -> 2025_11_26_04 +-- +UPDATE `smart_scripts` SET `action_param1`=51873, `comment`='Duke Vallenhal - Between 0-50% Health - Cast \'Bloodworm\'' WHERE `entryorguid`=26926 AND `source_type`=0 AND `id`=1; diff --git a/data/sql/updates/db_world/2025_11_26_05.sql b/data/sql/updates/db_world/2025_11_26_05.sql new file mode 100644 index 000000000..bd2b6a34b --- /dev/null +++ b/data/sql/updates/db_world/2025_11_26_05.sql @@ -0,0 +1,6 @@ +-- DB update 2025_11_26_04 -> 2025_11_26_05 +-- +DELETE FROM `smart_scripts` WHERE `entryorguid` = 1200 AND `source_type` = 0 AND `id` IN (2, 3); +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 +(1200, 0, 2, 0, 0, 0, 100, 0, 0, 0, 0, 6000, 0, 0, 11, 3108, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Morbent Fel - In Combat - Cast \'Touch of Death\''), +(1200, 0, 3, 0, 0, 0, 100, 0, 5000, 25000, 22500, 27500, 0, 0, 11, 3109, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Morbent Fel - In Combat - Cast \'Presence of Death\''); diff --git a/data/sql/updates/db_world/2025_11_26_06.sql b/data/sql/updates/db_world/2025_11_26_06.sql new file mode 100644 index 000000000..72170aa04 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_26_06.sql @@ -0,0 +1,12 @@ +-- DB update 2025_11_26_05 -> 2025_11_26_06 + +-- Remove row 5 (set range 100) and update comments. +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 32769; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 32769); +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 +(32769, 0, 0, 0, 1, 0, 100, 0, 5000, 10000, 3000, 6000, 0, 0, 49, 0, 0, 0, 0, 0, 0, 19, 31406, 80, 0, 0, 0, 0, 0, 0, 'Gargoyle Ambusher - Out of Combat - Start Attacking'), +(32769, 0, 1, 0, 1, 0, 100, 0, 5000, 10000, 3000, 6000, 0, 0, 49, 0, 0, 0, 0, 0, 0, 19, 32512, 80, 0, 0, 0, 0, 0, 0, 'Gargoyle Ambusher - Out of Combat - Start Attacking'), +(32769, 0, 2, 0, 1, 0, 100, 0, 5000, 10000, 3000, 6000, 0, 0, 49, 0, 0, 0, 0, 0, 0, 19, 31838, 80, 0, 0, 0, 0, 0, 0, 'Gargoyle Ambusher - Out of Combat - Start Attacking'), +(32769, 0, 3, 0, 1, 0, 100, 0, 5000, 10000, 3000, 6000, 0, 0, 49, 0, 0, 0, 0, 0, 0, 19, 32513, 80, 0, 0, 0, 0, 0, 0, 'Gargoyle Ambusher - Out of Combat - Start Attacking'), +(32769, 0, 4, 0, 9, 0, 100, 0, 0, 0, 1500, 1500, 0, 40, 11, 60239, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Gargoyle Ambusher - Within 0-40 Range - Cast \'Gargoyle Ambusher Strike\''); diff --git a/data/sql/updates/db_world/2025_11_27_00.sql b/data/sql/updates/db_world/2025_11_27_00.sql new file mode 100644 index 000000000..8aba98c25 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_27_00.sql @@ -0,0 +1,41 @@ +-- DB update 2025_11_26_06 -> 2025_11_27_00 +-- +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 30474); +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 +(30474, 0, 0, 1, 25, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'The North Wind - On Reset - Set Event Phase 1'), +(30474, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 19, 256, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'The North Wind - On Reset - Remove Flags Immune To Players'), +(30474, 0, 2, 0, 0, 1, 100, 0, 1000, 3000, 8000, 11000, 0, 0, 11, 61662, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'The North Wind - In Combat - Cast \'Cyclone\' (Phase 1)'), +(30474, 0, 3, 0, 0, 1, 100, 0, 1000, 8000, 12000, 16000, 0, 0, 11, 61663, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'The North Wind - In Combat - Cast \'Gust of Wind\' (Phase 1)'), +(30474, 0, 4, 0, 2, 0, 100, 1, 0, 20, 0, 0, 0, 0, 80, 3047400, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'The North Wind - Between 0-20% Health - Run Script (No Repeat)'); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 3047400); +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 +(3047400, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'The North Wind - Actionlist - Set Event Phase 2'), +(3047400, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'The North Wind - Actionlist - Stop Attack'), +(3047400, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 117, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'The North Wind - Actionlist - Disable Evade'), +(3047400, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 2, 35, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'The North Wind - Actionlist - Set Faction 35'), +(3047400, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 18, 256, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'The North Wind - Actionlist - Set Flags Immune To Players'), +(3047400, 9, 5, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 46957, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'The North Wind - Actionlist - Cast \'Cosmetic - Stun (Permanent)\''), +(3047400, 9, 6, 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, 'The North Wind - Actionlist - Say Line 0'), +(3047400, 9, 7, 0, 0, 0, 100, 0, 1000, 1000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 19, 30388, 100, 0, 0, 0, 0, 0, 0, 'The North Wind - Actionlist - Say Line 0'), +(3047400, 9, 8, 0, 0, 0, 100, 0, 1000, 1000, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'The North Wind - Actionlist - Say Line 1'), +(3047400, 9, 9, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 19, 30388, 100, 0, 0, 0, 0, 0, 0, 'The North Wind - Actionlist - Say Line 1'), +(3047400, 9, 10, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 0, 0, 11, 56892, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'The North Wind - Actionlist - Cast \'Drop Horn of Elemental Fury\''), +(3047400, 9, 11, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 28, 46598, 0, 0, 0, 0, 0, 19, 30388, 100, 0, 0, 0, 0, 0, 0, 'The North Wind - Actionlist - Remove Aura \'Ride Vehicle Hardcoded\''), +(3047400, 9, 12, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 60000, 10, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'The North Wind - Actionlist - Despawn In 60000 ms'); + +DELETE FROM `creature_template_spell` WHERE (`CreatureID` = 30388) AND (`Index` IN (0, 2)); +INSERT INTO `creature_template_spell` (`CreatureID`, `Index`, `Spell`, `VerifiedBuild`) VALUES +(30388, 0, 56896, 12340), +(30388, 2, 56897, 12340); + +-- eject forward and to the right +DELETE FROM `vehicle_seat_addon` WHERE `SeatEntry` = 2245; +INSERT INTO `vehicle_seat_addon` (`SeatEntry`, `SeatOrientation`, `ExitParamX`, `ExitParamY`, `ExitParamZ`, `ExitParamO`, `ExitParamValue`) VALUES +(2245, 0.0, 3.0, -4.0, 3.0, 0.0, 1); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 1 AND `entryorguid` = 194123); +UPDATE `gameobject_template` SET `AIName` = '' WHERE (`entry` = 194123); + +-- Remove duplicate spawn of 'The North Wind' +DELETE FROM `creature` WHERE `guid` = 1955014 AND `id1` = 30474; diff --git a/data/sql/updates/db_world/2025_11_27_01.sql b/data/sql/updates/db_world/2025_11_27_01.sql new file mode 100644 index 000000000..2b9d7f64a --- /dev/null +++ b/data/sql/updates/db_world/2025_11_27_01.sql @@ -0,0 +1,745 @@ +-- DB update 2025_11_27_00 -> 2025_11_27_01 +-- +-- Setthek Talon Lord wields a sword, but shares id1 with War Hawk (no equipment) +-- workaround for error: Table `creature` have creature (Entries: 18321, 21904, 0) one or more with equipment_id 1 not found in table `creature_equip_template`, set to no equipment. +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 18321) AND (`source_type` = 0) AND (`id` IN (1)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(18321, 0, 1, 0, 37, 0, 100, 0, 0, 0, 0, 0, 0, 0, 124, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Sethekk Talon Lord - On Initialize - Load Equipment Id 1'); + +-- CreatureID 2603 (Kovork) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 2603 AND `guid` IN (300753); + +-- CreatureID 2604 (Molok the Crusher) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 2604 AND `guid` IN (300754); + +-- CreatureID 2605 (Zalas Witherbark) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 2605 AND `guid` IN (300757, 301300, 301301, 301302); + +-- CreatureID 2606 (Nimar the Slayer) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 2606 AND `guid` IN (300755, 301290, 301291, 301292); + +-- CreatureID 4842 (Earthcaller Halmgar) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 4842 AND `guid` IN (1975863); + +-- CreatureID 5569 (Fizzlebang Booms) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 5569 AND `guid` IN (12523); + +-- CreatureID 6490 (Azshir the Sleepless) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 6490 AND `guid` IN (1975841); + +-- CreatureID 7157 (Deadwood Avenger) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 7157 AND `guid` IN (40303, 40304, 40386, 40388); + +-- CreatureID 7158 (Deadwood Shaman) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 7158 AND `guid` IN (40305); + +-- CreatureID 7354 (Ragglesnout) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 7354 AND `guid` IN (247108); + +-- CreatureID 8116 (Ziggle Sparks) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 8116 AND `guid` IN (12524); + +-- CreatureID 8117 (Wizbang Booms) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 8117 AND `guid` IN (12525); + +-- CreatureID 8121 (Jaxxil Sparks) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 8121 AND `guid` IN (12527); + +-- CreatureID 8122 (Kizzak Sparks) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 8122 AND `guid` IN (12528); + +-- CreatureID 8387 (Horizon Scout First Mate) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 8387 AND `guid` IN (160359); + +-- CreatureID 8388 (Horizon Scout Cook) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 8388 AND `guid` IN (160360); + +-- CreatureID 8389 (Horizon Scout Engineer) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 8389 AND `guid` IN (160361); + +-- CreatureID 8478 (Second Mate Shandril) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 8478 AND `guid` IN (160363); + +-- CreatureID 9216 (Spirestone Warlord) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 9216 AND `guid` IN (24187, 24188, 248595, 248596, 248597, 248598, 248599, 248600); + +-- CreatureID 9462 (Chieftain Bloodmaw) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 9462 AND `guid` IN (40427); + +-- CreatureID 9693 (Bloodaxe Evoker) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 9693 AND `guid` IN (52124, 52125, 52126, 52127, 52128, 52129, 52130, 52131, 52132, 52133, 52134); + +-- CreatureID 11277 (Caer Darrow Citizen) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 11277 AND `guid` IN (131325, 131326, 131327, 131328, 131338, 131343, 131344, 131346, 131347); + +-- CreatureID 11279 (Caer Darrow Guardsman) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 11279 AND `guid` IN (131329, 131330, 131331, 131342); + +-- CreatureID 11280 (Caer Darrow Cannoneer) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 11280 AND `guid` IN (131332, 131333, 131334); + +-- CreatureID 11287 (Baker Masterson) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 11287 AND `guid` IN (131345); + +-- CreatureID 11316 (Joseph Dirte) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 11316 AND `guid` IN (131337); + +-- CreatureID 14684 (Balzaphon) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 14684 AND `guid` IN (248654); + +-- CreatureID 14695 (Lord Blackwood) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 14695 AND `guid` IN (153321); + +-- CreatureID 14724 (Bubulo Acerbus) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 14724 AND `guid` IN (1741); + +-- CreatureID 15197 (Darkcaller Yanka) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15197 AND `guid` IN (240193); + +-- CreatureID 15199 (Sergeant Hartman) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15199 AND `guid` IN (240192); + +-- CreatureID 15264 (Anubisath Sentinel) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15264 AND `guid` IN (87564, 87565, 87566, 87567, 87568, 87569, 87570, 87571); + +-- CreatureID 15275 (Emperor Vek'nilash) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15275 AND `guid` IN (88076); + +-- CreatureID 15276 (Emperor Vek'lor) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15276 AND `guid` IN (88077); + +-- CreatureID 15383 (Sergeant Stonebrow) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15383 AND `guid` IN (83120); + +-- CreatureID 15431 (Corporal Carnes) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15431 AND `guid` IN (83121); + +-- CreatureID 15434 (Private Draxlegauge) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15434 AND `guid` IN (83123); + +-- CreatureID 15437 (Master Nightsong) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15437 AND `guid` IN (83124); + +-- CreatureID 15445 (Sergeant Major Germaine) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15445 AND `guid` IN (83125); + +-- CreatureID 15446 (Bonnie Stoneflayer) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15446 AND `guid` IN (83126); + +-- CreatureID 15448 (Private Porter) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15448 AND `guid` IN (83127); + +-- CreatureID 15450 (Marta Finespindle) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15450 AND `guid` IN (83128); + +-- CreatureID 15451 (Sentinel Silversky) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15451 AND `guid` IN (83129); + +-- CreatureID 15453 (Keeper Moonshade) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15453 AND `guid` IN (83131); + +-- CreatureID 15455 (Slicky Gastronome) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15455 AND `guid` IN (83132); + +-- CreatureID 15457 (Huntress Swiftriver) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15457 AND `guid` IN (83134); + +-- CreatureID 15458 (Commander Stronghammer) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15458 AND `guid` IN (83146); + +-- CreatureID 15459 (Miner Cromwell) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15459 AND `guid` IN (83152); + +-- CreatureID 15460 (Grunt Maug) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15460 AND `guid` IN (83153); + +-- CreatureID 15469 (Senior Sergeant T'kelah) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15469 AND `guid` IN (83154); + +-- CreatureID 15477 (Herbalist Proudfeather) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15477 AND `guid` IN (83155); + +-- CreatureID 15502 (Andorgos) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15502 AND `guid` IN (87527); + +-- CreatureID 15503 (Kandrostrasz) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15503 AND `guid` IN (87529); + +-- CreatureID 15504 (Vethsera) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15504 AND `guid` IN (87528); + +-- CreatureID 15508 (Batrider Pele'keiki) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15508 AND `guid` IN (83156); + +-- CreatureID 15512 (Apothecary Jezel) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15512 AND `guid` IN (83157); + +-- CreatureID 15515 (Skinner Jamani) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15515 AND `guid` IN (83158); + +-- CreatureID 15522 (Sergeant Umala) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15522 AND `guid` IN (83148); + +-- CreatureID 15525 (Doctor Serratus) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15525 AND `guid` IN (83159); + +-- CreatureID 15528 (Healer Longrunner) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15528 AND `guid` IN (83160); + +-- CreatureID 15532 (Stoneguard Clayhoof) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15532 AND `guid` IN (83162); + +-- CreatureID 15533 (Bloodguard Rawtar) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15533 AND `guid` IN (83149); + +-- CreatureID 15534 (Fisherman Lin'do) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15534 AND `guid` IN (83150); + +-- CreatureID 15535 (Chief Sharpclaw) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15535 AND `guid` IN (83151); + +-- CreatureID 15539 (General Zog) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15539 AND `guid` IN (83118); + +-- CreatureID 15700 (Warlord Gorchuk) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15700 AND `guid` IN (83168); + +-- CreatureID 15701 (Field Marshal Snowfall) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15701 AND `guid` IN (83140); + +-- CreatureID 15702 (Senior Sergeant Taiga) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15702 AND `guid` IN (83169); + +-- CreatureID 15703 (Senior Sergeant Grimsford) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15703 AND `guid` IN (83170); + +-- CreatureID 15704 (Senior Sergeant Kai'jin) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15704 AND `guid` IN (83171); + +-- CreatureID 15707 (Master Sergeant Fizzlebolt) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15707 AND `guid` IN (83172); + +-- CreatureID 15709 (Master Sergeant Moonshadow) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15709 AND `guid` IN (83174); + +-- CreatureID 15723 (Booty Bay Reveler) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15723 AND `guid` IN (420041, 420042, 420043, 420044, 420045, 420046, 420047, 420048, 420049, 420050, 420051, 420052, 420053, 420054, 420055, 420056, 420057, 420058, 420059); + +-- CreatureID 15724 (Drunken Bruiser) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15724 AND `guid` IN (420060, 420061, 420062, 420063, 420064, 420065, 420066, 420067, 420068, 420069, 420070, 420071, 420072, 420073, 420074, 420075, 420076, 420077, 420078, 420079, 420080, 420081, 420082, 420083, 420084, 420085, 420086, 420087, 420088, 420089, 420090, 420091, 420092, 420093, 420094, 420095, 420096, 420097, 420098, 420099, 420100, 420101, 420102, 420103, 420104, 420105, 420106, 420107, 420108, 420109, 420110, 420111, 420112, 420113, 420114, 420115, 420116, 420117, 420118, 420119, 420120, 420121); + +-- CreatureID 15765 (Officer Redblade) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 15765 AND `guid` IN (83179); + +-- CreatureID 16241 (Argent Recruiter) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 16241 AND `guid` IN (12863, 12867, 12870, 12871); + +-- CreatureID 16255 (Argent Scout) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 16255 AND `guid` IN (12876, 12880, 12884, 12887); + +-- CreatureID 16281 (Keeper of the Rolls) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 16281 AND `guid` IN (12860); + +-- CreatureID 16285 (Argent Emissary) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 16285 AND `guid` IN (12861, 12864, 12868, 12872); + +-- CreatureID 16359 (Argent Messenger) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 16359 AND `guid` IN (12877, 12881, 12885, 12888); + +-- CreatureID 16361 (Commander Thomas Helleran) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 16361 AND `guid` IN (12862); + +-- CreatureID 16384 (Argent Dawn Initiate) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 16384 AND `guid` IN (153326, 153327, 153328); + +-- CreatureID 16395 (Argent Dawn Paladin) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 16395 AND `guid` IN (153322, 153323, 153324, 153325); + +-- CreatureID 16433 (Argent Dawn Crusader) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 16433 AND `guid` IN (153329, 153330, 153331, 153332); + +-- CreatureID 16434 (Argent Dawn Champion) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 16434 AND `guid` IN (153336, 153337, 153338, 153339); + +-- CreatureID 16435 (Argent Dawn Cleric) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 16435 AND `guid` IN (153333, 153334, 153335); + +-- CreatureID 16436 (Argent Dawn Priest) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 16436 AND `guid` IN (153340, 153341, 153342); + +-- CreatureID 17190 (Siltfin Murloc) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 17190 AND `guid` IN (60815, 60818, 60820, 60821, 60822, 60825, 60827, 60830, 60831, 60834, 60836, 60837, 60839, 60842, 60845, 60847, 60853, 60854, 60858, 60859, 60863, 60864, 60870, 60871, 60872, 60875, 60877, 60879, 60884, 60887, 60889, 60892, 60895, 60899, 60901, 60903, 60904, 60906, 60907, 60908, 60911, 60913, 60916); + +-- CreatureID 17191 (Siltfin Oracle) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 17191 AND `guid` IN (60816, 60819, 60823, 60824, 60826, 60828, 60833, 60835, 60838, 60841, 60843, 60846, 60850, 60851, 60852, 60856, 60861, 60862, 60865, 60866, 60868, 60869, 60873, 60876, 60880, 60881, 60882, 60883, 60885, 60888, 60891, 60898, 60900, 60902, 60910, 60912, 60914, 60915); + +-- CreatureID 17192 (Siltfin Hunter) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 17192 AND `guid` IN (60817, 60829, 60832, 60840, 60844, 60848, 60849, 60860, 60867, 60874, 60878, 60886, 60894, 60905, 60909, 60917, 60918); + +-- CreatureID 17211 (Human Footman) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 17211 AND `guid` IN (76021, 76022, 76023, 76025, 76026, 76027, 76029, 76031); + +-- CreatureID 17469 (Orc Grunt) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 17469 AND `guid` IN (76020, 76028, 76030, 76032, 76033, 76035, 76036, 76040); + +-- CreatureID 17701 (Lord Xiz) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 17701 AND `guid` IN (63448); + +-- CreatureID 17885 (Earthbinder Rayge) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 17885 AND `guid` IN (138478); + +-- CreatureID 18192 (Horde Halaani Guard) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 18192 AND `guid` IN (12416, 12417, 12418, 12419, 12420, 12421, 12422, 12423, 12424, 12425, 12426, 12427, 12428, 12429, 12430); + +-- CreatureID 18206 (Wastewalker Captive) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 18206 AND `guid` IN (79461, 79463, 79469, 79471, 79472, 79475, 79482, 79488, 79490, 135044, 135045, 135047, 135048, 135049, 135050, 135051, 135052, 135054, 135055, 135057, 135058, 135060, 135061, 135062, 135063, 135064, 135065, 135066, 135067, 135072, 135073, 135074, 135075, 135076, 135077, 135078, 135079, 135080, 135081, 135082, 135083, 135084, 135085, 135086, 135087, 135089); + +-- CreatureID 18256 (Alliance Halaani Guard) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 18256 AND `guid` IN (12436, 12437, 12438, 12439, 12440, 12441, 12442, 12443, 12444, 12445, 12446, 12447, 12448, 12449, 12450); + +-- CreatureID 18556 (Phasing Soldier) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 18556 AND `guid` IN (132411, 132422, 132436); + +-- CreatureID 18557 (Phasing Cleric) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 18557 AND `guid` IN (132409, 132413, 132414, 132425, 132429, 132430); + +-- CreatureID 18558 (Phasing Sorcerer) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 18558 AND `guid` IN (132404, 132417, 132431, 132437); + +-- CreatureID 18559 (Phasing Stalker) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 18559 AND `guid` IN (132406, 132408, 132416, 132420, 132421, 132428); + +-- CreatureID 18684 (Bro'Gaz the Clanless) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 18684 AND `guid` IN (100866, 100867, 100868); + +-- CreatureID 20885 (Dalliah the Doomsayer) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 20885 AND `guid` IN (138950); + +-- CreatureID 21474 (Coreiel) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 21474 AND `guid` IN (12413); + +-- CreatureID 21485 (Aldraan) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 21485 AND `guid` IN (12433); + +-- CreatureID 21682 (Human Cleric) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 21682 AND `guid` IN (76046, 76048); + +-- CreatureID 21683 (Human Conjurer) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 21683 AND `guid` IN (76047); + +-- CreatureID 21684 (King Llane) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 21684 AND `guid` IN (76049); + +-- CreatureID 21726 (Summoned Daemon) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 21726 AND `guid` IN (76034, 76039); + +-- CreatureID 21736 (Wildhammer Defender) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 21736 AND `guid` IN (213465, 213466, 213467, 213468, 213469, 213470, 213471, 213472, 213473, 213474, 213475, 213476, 213477, 213478, 213479, 213480, 213481, 213482, 213483, 213484, 213485, 213486, 213487, 213488, 213489, 213490, 213491, 213492, 213493, 213494, 213495, 213496, 213497, 213498, 213499, 213500, 213501, 213502, 213503, 213504, 213505, 213506, 213507, 213508, 213509, 213510, 213511, 213512, 213513, 213514, 213515, 213516, 213517, 213518, 213519, 213520, 213521, 213522, 213523, 213524, 213525, 213526, 213527, 213528, 213529, 213530, 213531, 213532, 213533, 213534, 213535, 213536, 213537, 213538, 213539, 213540, 213541, 213542, 213543, 213544, 213545, 213546, 213547, 213548, 213549, 213550, 213551, 213552, 213553, 213554, 213555, 213556, 213557, 213558, 213559, 213560, 213561, 213562, 213563, 213564, 213565, 213566, 213567, 213568, 213569, 213570, 213571, 213572, 213573, 213574, 213575, 213576, 213577, 213578, 213579, 213580, 213581, 213582, 213583, 213584, 213585, 213586, 213587, 213588, 213589, 213590); + +-- CreatureID 21747 (Orc Necrolyte) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 21747 AND `guid` IN (76037, 76041); + +-- CreatureID 21748 (Orc Wolf) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 21748 AND `guid` IN (76038, 76042); + +-- CreatureID 21749 (Shadowmoon Scout) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 21749 AND `guid` IN (213591, 213592, 213593, 213594, 213595, 213596, 213597, 213598, 213599, 213600, 213601, 213602, 213603, 213604, 213605, 213606, 213607, 213608, 213609, 213610, 213611, 213612, 213613, 213614, 213615, 213616, 213617, 213618, 213619, 213620, 213621, 213622, 213623, 213624, 213625, 213626, 213627, 213628, 213629, 213630, 213631, 213632, 213633, 213634, 213635, 213636, 213637, 213638, 213639, 213640, 213641, 213642, 213643, 213644, 213645, 213646, 213647, 213648, 213649, 213650, 213651, 213652, 213653, 213654, 213655, 213656, 213657, 213658, 213659, 213660, 213661, 213662, 213663, 213664, 213665, 213666, 213667, 213668, 213669, 213670, 213671, 213672, 213673, 213674, 213675, 213676, 213677, 213678, 213679, 213680, 213681, 213682, 213683, 213684, 213685, 213686, 213687, 213688, 213689, 213690, 213691, 213692, 213693, 213694, 213695, 213696, 213697, 213698, 213699, 213700, 213701, 213702, 213703, 213704, 213705, 213706, 213707, 213708, 213709, 213710, 213711, 213712, 213713, 213714, 213715, 213716, 213717, 213718, 213719); + +-- CreatureID 21750 (Orc Warlock) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 21750 AND `guid` IN (76043); + +-- CreatureID 21752 (Warchief Blackhand) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 21752 AND `guid` IN (76044); + +-- CreatureID 21797 (Ancient Shadowmoon Spirit) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 21797 AND `guid` IN (100050); + +-- CreatureID 21846 (Slain Auchenai Warrior) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 21846 AND `guid` IN (1977353, 1977354, 1977355, 1977356, 1977357, 1977358, 1977359, 1977360, 1977361, 1977362, 1977363, 1977364, 1977365, 1977366, 1977367, 1977368, 1977369, 1977370, 1977371, 1977372, 1977373, 1977374, 1977375, 1977376, 1977377, 1977378, 1977379, 1977380, 1977381, 1977382, 1977383, 1977384, 1977385, 1977386, 1977387, 1977388); + +-- CreatureID 21961 (Cataclysm Overseer) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 21961 AND `guid` IN (213306, 213307, 213308, 213309, 213310, 213311, 213312, 213313); + +-- CreatureID 22954 (Illidari Fearbringer) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 22954 AND `guid` IN (148140, 148141, 148142, 148143); + +-- CreatureID 22955 (Charming Courtesan) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 22955 AND `guid` IN (148543, 148544, 148547, 148548, 148549, 148551, 148554, 148556, 148558, 148559, 148560, 148562, 148563, 148565, 148568, 148571, 148572, 148576, 148577, 148578, 148581, 148584, 148586, 148588, 148589, 148593, 148594, 148597, 148598, 148600, 148603, 148609, 148610, 148612, 148613, 148614, 148616, 148619, 148621, 148622, 148624, 148626, 148627, 148628, 148629, 148632, 148634, 148636, 148638, 148639, 148640, 148643, 148645, 148648, 148649, 148650, 148653, 148656, 148658, 148661, 148662, 148664, 148666, 148668, 148670, 148671, 148674, 148675); + +-- CreatureID 23008 (Ethereum Jailor) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 23008 AND `guid` IN (1975937, 1975938, 1975939, 1975940, 1975941, 1975942, 1975943, 1975944, 1975945, 1975946, 1975947, 1975948, 1975949, 1975950, 1975951, 1975952, 1975953, 1975954, 1975955, 1975956, 1975957); + +-- CreatureID 23023 (Scryer Reveler) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 23023 AND `guid` IN (420203, 420204, 420205, 420206, 420207, 420208, 420209, 420210, 420211, 420212); + +-- CreatureID 23024 (Aldor Reveler) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 23024 AND `guid` IN (420213, 420214, 420215, 420216, 420217, 420218, 420219, 420220); + +-- CreatureID 23039 (Draenei Reveler) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 23039 AND `guid` IN (420221, 420222, 420223, 420224, 420225, 420226, 420227, 420228, 420229, 420230, 420231, 420232, 420233, 420234, 420235, 420236, 420237, 420238, 420239); + +-- CreatureID 23045 (Blood Elf Reveler) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 23045 AND `guid` IN (420240, 420241, 420242, 420243, 420244, 420245, 420246, 420247, 420248, 420249, 420250, 420251, 420252, 420253, 420254, 420255, 420256); + +-- CreatureID 23146 (Dragonmaw Enforcer) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 23146 AND `guid` IN (52106, 52107, 52108, 52109, 52110, 52111, 52112, 52113, 52114, 52115, 52121, 52230, 52231, 143596, 143597, 143598); + +-- CreatureID 23196 (Bonechewer Behemoth) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 23196 AND `guid` IN (148360, 148361, 148362, 148363, 148364); + +-- CreatureID 23305 (Crazed Murkblood Foreman) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 23305 AND `guid` IN (143892, 143893); + +-- CreatureID 23311 (Disobedient Dragonmaw Peon) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 23311 AND `guid` IN (136178, 136179, 136180, 136181, 136182, 136183, 136184, 136185, 136186, 136187, 136188, 136189, 136190, 136191, 136192, 136193, 136194, 136195, 136196, 136197, 136198, 136199, 136200, 136201, 136202, 136203, 136204, 136205, 136206, 136207, 136208, 136209, 136210, 136211, 136212, 136213, 136214, 136215, 136216, 136217, 136218, 136219, 136220, 136221, 136222); + +-- CreatureID 23324 (Crazed Murkblood Miner) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 23324 AND `guid` IN (143882, 143883, 143884, 143885, 143886, 143887, 143888, 143889, 143890, 143891); + +-- CreatureID 23381 (Tydormu) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 23381 AND `guid` IN (139700); + +-- CreatureID 23437 (Indormi) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 23437 AND `guid` IN (139701); + +-- CreatureID 23718 (Mack) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 23718 AND `guid` IN (139273); + +-- CreatureID 23748 (Kurzel) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 23748 AND `guid` IN (139328); + +-- CreatureID 23872 (Coren Direbrew) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 23872 AND `guid` IN (240000); + +-- CreatureID 23982 (Forsaken Deckhand) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 23982 AND `guid` IN (88486, 88487, 88488, 88489, 88490, 88491, 88492, 88493, 88494, 88495, 88496, 88497, 88498, 88499, 88500, 88501, 88502, 88503, 88504, 88505, 88506, 88507, 88508, 88509, 88510, 88511, 88512, 88513, 88514, 88515, 88516, 88517, 88518, 88519, 88520, 88521, 88522, 88523, 88524, 88525, 88526, 88527, 88528, 88529, 88530, 88531, 88532, 88533, 88534, 88535, 88536, 88537, 88538); + +-- CreatureID 24239 (Hex Lord Malacrass) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 24239 AND `guid` IN (89357); + +-- CreatureID 24364 (Flynn Firebrew) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 24364 AND `guid` IN (240002); + +-- CreatureID 24527 (Bok Dropcertain) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 24527 AND `guid` IN (134677, 240001); + +-- CreatureID 24833 (Captain "Stash" Torgoley) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 24833 AND `guid` IN (52011); + +-- CreatureID 24834 (Galley Chief Grace) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 24834 AND `guid` IN (52012); + +-- CreatureID 24835 (First Mate Kowalski) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 24835 AND `guid` IN (52013); + +-- CreatureID 24838 (Sailor Henders) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 24838 AND `guid` IN (52016); + +-- CreatureID 24839 (Sailor Wicks) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 24839 AND `guid` IN (52017); + +-- CreatureID 24840 (Sailor Vines) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 24840 AND `guid` IN (52018); + +-- CreatureID 24841 (Marine Halters) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 24841 AND `guid` IN (52019); + +-- CreatureID 24842 (Marine Anderson) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 24842 AND `guid` IN (52020); + +-- CreatureID 24843 (Engineer Combs) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 24843 AND `guid` IN (52021); + +-- CreatureID 25239 (Thulrin) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 25239 AND `guid` IN (110115); + +-- CreatureID 25258 (Footman Rob) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 25258 AND `guid` IN (85221); + +-- CreatureID 25259 (Footman George) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 25259 AND `guid` IN (85222); + +-- CreatureID 25261 (Footman Chuck) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 25261 AND `guid` IN (85226); + +-- CreatureID 25338 (Warsong Caravan Guard) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 25338 AND `guid` IN (74539, 74540, 74541); + +-- CreatureID 26335 (Fallen Earthen Warrior) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 26335 AND `guid` IN (117222); + +-- CreatureID 26772 (Icemist Warrior) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 26772 AND `guid` IN (75010, 75011, 75012, 75013, 75014, 75015, 75016, 75017, 75018, 75019, 75020, 75021); + +-- CreatureID 28106 (Shaman Jakjek) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 28106 AND `guid` IN (1975898); + +-- CreatureID 28209 (Mizli Crankwheel) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 28209 AND `guid` IN (12564); + +-- CreatureID 28210 (Ognip Blastbolt) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 28210 AND `guid` IN (12565); + +-- CreatureID 28344 (Blazzle) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 28344 AND `guid` IN (116); + +-- CreatureID 28347 (Miles Sidney) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 28347 AND `guid` IN (45216); + +-- CreatureID 28355 (Wright Williams) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 28355 AND `guid` IN (45215); + +-- CreatureID 28495 (Gawanil) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 28495 AND `guid` IN (110277); + +-- CreatureID 28496 (Chulo the Mad) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 28496 AND `guid` IN (110278); + +-- CreatureID 28668 (Zepik the Gorloc Hunter) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 28668 AND `guid` IN (202970); + +-- CreatureID 29503 (Fjorn) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 29503 AND `guid` IN (88308); + +-- CreatureID 29519 (Unworthy Initiate) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 29519 AND `guid` IN (128557, 128558, 128559); + +-- CreatureID 29520 (Unworthy Initiate) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 29520 AND `guid` IN (128561, 128563); + +-- CreatureID 29565 (Unworthy Initiate) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 29565 AND `guid` IN (128740); + +-- CreatureID 29566 (Unworthy Initiate) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 29566 AND `guid` IN (128742, 128743, 128744); + +-- CreatureID 29567 (Unworthy Initiate) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 29567 AND `guid` IN (128747, 128748, 128749); + +-- CreatureID 29862 (Stormforged Monitor) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 29862 AND `guid` IN (1975936); + +-- CreatureID 30060 (Stormforged Warmonger) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 30060 AND `guid` IN (1976443, 1976444, 1976445, 1976446, 1976447, 1976448, 1976449, 1976450, 1976451, 1976452, 1976453, 1976454); + +-- CreatureID 30065 (Frostborn Axemaster) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 30065 AND `guid` IN (1976470, 1976471, 1976472, 1976473, 1976474, 1976475, 1976476, 1976477, 1976478, 1976479, 1976480, 1976481, 1976482, 1976483, 1976484, 1976485, 1976486, 1976487, 1976488, 1976489, 1976490, 1976491, 1976492); + +-- CreatureID 30099 (Njormeld) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 30099 AND `guid` IN (1975964); + +-- CreatureID 30121 (Frost Giant Stormherald) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 30121 AND `guid` IN (1975993, 1975994, 1975995); + +-- CreatureID 30182 (Yorg Stormheart) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 30182 AND `guid` IN (1976494); + +-- CreatureID 30188 (Argent Champion) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 30188 AND `guid` IN (1977144, 1977145, 1977146, 1977147, 1977148, 1977149, 1977150, 1977151, 1977152, 1977153, 1977154, 1977155, 1977156, 1977157, 1977158, 1977159, 1977160, 1977161, 1977162, 1977163, 1977164, 1977165, 1977166, 1977167, 1977168); + +-- CreatureID 30295 (Thorim) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 30295 AND `guid` IN (1955077); + +-- CreatureID 30382 (Brann Bronzebeard) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 30382 AND `guid` IN (1976495); + +-- CreatureID 30399 (Thorim) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 30399 AND `guid` IN (49141); + +-- CreatureID 30571 (Michael Belfast) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 30571 AND `guid` IN (1970932); + +-- CreatureID 31283 (Orbaz Bloodbane) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 31283 AND `guid` IN (129851); + +-- CreatureID 31306 (Margrave Dhakar) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 31306 AND `guid` IN (74957); + +-- CreatureID 31314 (Ebon Blade Veteran) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 31314 AND `guid` IN (74952, 74953, 74954, 74955); + +-- CreatureID 31316 (Ebon Blade Reaper) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 31316 AND `guid` IN (129852, 129853, 129859, 129860, 129862, 129863, 129865, 129866, 129867, 129868, 129869, 129870, 129871, 129872, 129873, 129874); + +-- CreatureID 31412 (Thrall) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 31412 AND `guid` IN (3108763); + +-- CreatureID 31420 (Karus) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 31420 AND `guid` IN (1976083); + +-- CreatureID 31421 (Koma) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 31421 AND `guid` IN (1976084); + +-- CreatureID 31422 (Soran) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 31422 AND `guid` IN (1976085); + +-- CreatureID 31423 (Kaja) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 31423 AND `guid` IN (1976086); + +-- CreatureID 31425 (Olvia) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 31425 AND `guid` IN (1976088); + +-- CreatureID 31426 (Doras) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 31426 AND `guid` IN (1976089); + +-- CreatureID 31427 (Felika) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 31427 AND `guid` IN (1976090); + +-- CreatureID 31428 (Crusader Olakin Sainrith) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 31428 AND `guid` IN (74958); + +-- CreatureID 31431 (Overlord Runthak) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 31431 AND `guid` IN (1976093); + +-- CreatureID 31440 (Sergeant Kregga) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 31440 AND `guid` IN (1975899); + +-- CreatureID 31649 (Vol'jin) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 31649 AND `guid` IN (3109787); + +-- CreatureID 31739 (Warsong Battleguard) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 31739 AND `guid` IN (3109792, 3109793, 3109794, 3109795); + +-- CreatureID 32239 (Highlord Tirion Fordring) +UPDATE `creature` SET `equipment_id` = 2 WHERE `id1` = 32239 AND `guid` IN (74512); + +-- CreatureID 32241 (Disguised Crusader) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 32241 AND `guid` IN (74513, 74514, 74515); + +-- CreatureID 32365 (Lady Sylvanas Windrunner) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 32365 AND `guid` IN (3109786); + +-- CreatureID 32376 (Broll Bearmantle) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 32376 AND `guid` IN (3109766); + +-- CreatureID 32378 (Valeera Sanguinar) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 32378 AND `guid` IN (3109767); + +-- CreatureID 32387 (Stormwind Elite) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 32387 AND `guid` IN (3109768, 3109769, 3109770, 3109771, 3109772, 3109773); + +-- CreatureID 32401 (King Varian Wrynn) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 32401 AND `guid` IN (3109764); + +-- CreatureID 32402 (Lady Jaina Proudmoore) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 32402 AND `guid` IN (3109765); + +-- CreatureID 32518 (Thrall) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 32518 AND `guid` IN (3109785); + +-- CreatureID 34382 (Chapman) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 34382 AND `guid` IN (240228, 240229, 240251, 240252, 240253, 240254, 240255, 240256, 240257, 240258); + +-- CreatureID 34383 (Catrina) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 34383 AND `guid` IN (240226, 240227, 240259, 240260, 240261, 240262, 240263, 240264, 240265, 240266); + +-- CreatureID 34478 (Cheerful Dwarf Spirit) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 34478 AND `guid` IN (240293); + +-- CreatureID 34528 (Tahu Sagewind) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 34528 AND `guid` IN (37); + +-- CreatureID 34712 (Roberta Carter) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 34712 AND `guid` IN (240609); + +-- CreatureID 34713 (Ondani Greatmill) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 34713 AND `guid` IN (240534); + +-- CreatureID 34714 (Mahara Goldwheat) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 34714 AND `guid` IN (240577); + +-- CreatureID 34744 (Jasper Moore) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 34744 AND `guid` IN (240458); + +-- CreatureID 34768 (William Mullins) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 34768 AND `guid` IN (240610); + +-- CreatureID 34785 (Alnar Whitebough) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 34785 AND `guid` IN (240519); + +-- CreatureID 34786 (Alice Rigsdale) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 34786 AND `guid` IN (240642); + +-- CreatureID 36162 (Goblin Engineering Crew) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 36162 AND `guid` IN (74976, 74977); + +-- CreatureID 36164 (Kor'kron Reaver) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 36164 AND `guid` IN (74978, 74979, 74980, 74981, 74982, 74983, 74984, 74985, 74986, 74987); + +-- CreatureID 36165 (7th Legion Deckhand) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 36165 AND `guid` IN (74998, 74999); + +-- CreatureID 36166 (7th Legion Marine) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 36166 AND `guid` IN (74988, 74989, 74990, 74991, 74992, 74993, 74994, 74995, 74996, 74997); + +-- CreatureID 36217 (Overseer Kraggosh) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 36217 AND `guid` IN (79263); + +-- CreatureID 36296 (Apothecary Hummel) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 36296 AND `guid` IN (146623); + +-- CreatureID 36888 (Rescued Alliance Slave) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 36888 AND `guid` IN (202285, 202286, 202287, 202288); + +-- CreatureID 36889 (Rescued Horde Slave) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 36889 AND `guid` IN (202279, 202280, 202283, 202284); + +-- CreatureID 36970 (Skybreaker Deckhand) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 36970 AND `guid` IN (133978, 133979, 133980, 133981, 133982, 133983, 133984, 133985); + +-- CreatureID 36971 (Orgrim's Hammer Crew) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 36971 AND `guid` IN (133964, 133965, 133966, 133967, 133968, 133969, 133970, 133971, 133975); + +-- CreatureID 37182 (High Captain Justin Bartlett) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 37182 AND `guid` IN (133977); + +-- CreatureID 37184 (Zafod Boombox) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 37184 AND `guid` IN (133957, 133976); + +-- CreatureID 37214 (Crown Lackey) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 37214 AND `guid` IN (12461, 12462, 12463, 12464, 12465, 12466, 244581, 244582, 244583, 244584, 244585, 244586, 244587, 244588, 244589, 244590); + +-- CreatureID 37226 (The Lich King) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 37226 AND `guid` IN (1971982); + +-- CreatureID 37523 (Warden of the Sunwell) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 37523 AND `guid` IN (1976590, 1976591); + +-- CreatureID 37527 (Halduron Brightwing) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 37527 AND `guid` IN (43498); + +-- CreatureID 37715 (Snivel Rustrocket) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 37715 AND `guid` IN (244629, 244630); + +-- CreatureID 37763 (Grand Magister Rommath) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 37763 AND `guid` IN (1976652); + +-- CreatureID 37765 (Captain Auric Sunchaser) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 37765 AND `guid` IN (1976655); + +-- CreatureID 37833 (Sky-Reaver Korm Blackscar) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 37833 AND `guid` IN (133958); + +-- CreatureID 37917 (Crown Thug) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 37917 AND `guid` IN (12483, 12484, 12485, 12486, 12487, 12488, 12489, 12490, 12491, 12492, 12493, 12494, 244567, 244568, 244569, 244570, 244591, 244592, 244593, 244594, 244595); + +-- CreatureID 37984 (Crown Duster) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 37984 AND `guid` IN (12468, 12469, 12470, 12471, 12472, 244621, 244622, 244623, 244624, 244625); + +-- CreatureID 38006 (Crown Hoodlum) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 38006 AND `guid` IN (12473, 12474, 12475, 12476, 12477, 244616, 244617, 244618, 244619, 244620); + +-- CreatureID 38023 (Crown Sprinkler) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 38023 AND `guid` IN (12500, 12501, 12502, 12503, 12504, 244596, 244597, 244598, 244599, 244600); + +-- CreatureID 38030 (Crown Underling) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 38030 AND `guid` IN (12505, 12506, 12507, 12508, 12509, 12510, 12511, 244601, 244602, 244603, 244604, 244605); + +-- CreatureID 38032 (Crown Sprayer) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 38032 AND `guid` IN (12512, 12513, 12514, 12515, 12516, 12517, 12518, 12519, 12520, 12521, 12522, 244532, 244533, 244534, 244535, 244536, 244537, 244538, 244539, 244540, 244541, 244542, 244543, 244544); + +-- CreatureID 38065 (Crown Supply Sentry) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 38065 AND `guid` IN (244631, 244632, 244633); + +-- CreatureID 40446 (Skar'this the Summoner) +UPDATE `creature` SET `equipment_id` = 1 WHERE `id1` = 40446 AND `guid` IN (12549); diff --git a/data/sql/updates/db_world/2025_11_27_02.sql b/data/sql/updates/db_world/2025_11_27_02.sql new file mode 100644 index 000000000..2c804e560 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_27_02.sql @@ -0,0 +1,12 @@ +-- DB update 2025_11_27_01 -> 2025_11_27_02 +-- Fix Plagued Proto-Drake Egg not despawning after being frozen +-- https://github.com/azerothcore/azerothcore-wotlk/issues/23851 +-- Quests: Aberrations (12925), The Aberrations Must Die (13425) + +-- Set SmartGameObjectAI for Plagued Proto-Drake Egg +UPDATE `gameobject_template` SET `AIName` = 'SmartGameObjectAI' WHERE `entry` = 191840; + +-- Add SmartAI script: On spell hit by Vial of Frost Oil (55647), despawn immediately +DELETE FROM `smart_scripts` WHERE `entryorguid` = 191840 AND `source_type` = 1; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(191840, 1, 0, 0, 8, 0, 100, 0, 55647, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Plagued Proto-Drake Egg - On Spell Hit (Vial of Frost Oil) - Despawn'); diff --git a/data/sql/updates/db_world/2025_11_27_03.sql b/data/sql/updates/db_world/2025_11_27_03.sql new file mode 100644 index 000000000..586c44e30 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_27_03.sql @@ -0,0 +1,3 @@ +-- DB update 2025_11_27_02 -> 2025_11_27_03 +-- Sets all Everfrost Gameobjects to be able to seen in phase 1, 2, 4, 8 and 12 +UPDATE `gameobject` SET `phaseMask` = 15 WHERE `id` = 193997; diff --git a/data/sql/updates/db_world/2025_11_27_04.sql b/data/sql/updates/db_world/2025_11_27_04.sql new file mode 100644 index 000000000..7ddce6ecb --- /dev/null +++ b/data/sql/updates/db_world/2025_11_27_04.sql @@ -0,0 +1,2 @@ +-- DB update 2025_11_27_03 -> 2025_11_27_04 +DELETE FROM `gameobject` WHERE `guid` = 21197; diff --git a/data/sql/updates/db_world/2025_11_27_05.sql b/data/sql/updates/db_world/2025_11_27_05.sql new file mode 100644 index 000000000..8d58407d7 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_27_05.sql @@ -0,0 +1,16 @@ +-- DB update 2025_11_27_04 -> 2025_11_27_05 + +-- Updated SAI & comments +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 27587; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 27587); +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 +(27587, 0, 0, 0, 38, 0, 100, 512, 0, 1, 0, 0, 0, 0, 11, 49122, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 'Alliance Steam Tank - On Data Set 0 1 - Cast \'Plague Wagon Credit\''), +(27587, 0, 1, 0, 25, 0, 100, 512, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Alliance Steam Tank - On Reset - Set Reactstate Passive'), +(27587, 0, 2, 0, 1, 0, 100, 512, 30000, 30000, 50000, 50000, 0, 0, 1, 1, 0, 0, 0, 0, 0, 19, 27588, 10, 0, 0, 0, 0, 0, 0, 'Alliance Steam Tank - Out of Combat - Say Line 1'), +(27587, 0, 3, 0, 8, 0, 100, 512, 49081, 0, 0, 0, 0, 0, 80, 2758700, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Alliance Steam Tank - On Spellhit \'Drop Off Soldier\' - Run Script'), +(27587, 0, 4, 0, 25, 0, 100, 512, 0, 0, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Alliance Steam Tank - On Reset - Set Run On'), +(27587, 0, 5, 6, 28, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 6000, 0, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 0, 0, 0, 'Alliance Steam Tank - On Passenger Removed - Despawn In 6000 ms'), +(27587, 0, 6, 7, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 6000, 0, 0, 0, 0, 0, 29, 2, 0, 0, 0, 0, 0, 0, 0, 'Alliance Steam Tank - On Passenger Removed - Despawn In 6000 ms'), +(27587, 0, 7, 8, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 6000, 0, 0, 0, 0, 0, 29, 3, 0, 0, 0, 0, 0, 0, 0, 'Alliance Steam Tank - On Passenger Removed - Despawn In 6000 ms'), +(27587, 0, 8, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 6000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Alliance Steam Tank - On Passenger Removed - Despawn In 6000 ms'); diff --git a/data/sql/updates/db_world/2025_11_27_06.sql b/data/sql/updates/db_world/2025_11_27_06.sql new file mode 100644 index 000000000..e9726779a --- /dev/null +++ b/data/sql/updates/db_world/2025_11_27_06.sql @@ -0,0 +1,167 @@ +-- DB update 2025_11_27_05 -> 2025_11_27_06 +-- +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 27719); +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 +(27719, 0, 0, 0, 19, 0, 100, 0, 12427, 0, 0, 0, 0, 0, 80, 2771900, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - On Quest \'The Conquest Pit: Bear Wrestling!\' Taken - Run Script'), +(27719, 0, 1, 0, 19, 0, 100, 0, 12428, 0, 0, 0, 0, 0, 80, 2771910, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - On Quest \'The Conquest Pit: Mad Furbolg Fighting\' Taken - Run Script'), +(27719, 0, 2, 0, 19, 0, 100, 0, 12429, 0, 0, 0, 0, 0, 80, 2771920, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - On Quest \'The Conquest Pit: Blood and Metal\' Taken - Run Script'), +(27719, 0, 3, 0, 19, 0, 100, 0, 12430, 0, 0, 0, 0, 0, 80, 2771930, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - On Quest \'The Conquest Pit: Death Is Likely\' Taken - Run Script'), +(27719, 0, 4, 0, 19, 0, 100, 0, 12431, 0, 0, 0, 0, 0, 80, 2771940, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - On Quest \'The Conquest Pit: Final Showdown\' Taken - Run Script'), +(27719, 0, 5, 0, 38, 0, 100, 0, 0, 1, 0, 0, 0, 0, 80, 2771901, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - On Data Set 0 1 - Run Script'), +(27719, 0, 6, 0, 38, 0, 100, 0, 0, 2, 0, 0, 0, 0, 80, 2771902, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - On Data Set 0 2 - Run Script'), +(27719, 0, 7, 0, 38, 0, 100, 0, 1, 1, 0, 0, 0, 0, 80, 2771911, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - On Data Set 1 1 - Run Script'), +(27719, 0, 8, 0, 38, 0, 100, 0, 1, 2, 0, 0, 0, 0, 80, 2771912, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - On Data Set 1 2 - Run Script'), +(27719, 0, 9, 0, 38, 0, 100, 0, 2, 1, 0, 0, 0, 0, 80, 2771921, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - On Data Set 2 1 - Run Script'), +(27719, 0, 10, 0, 38, 0, 100, 0, 2, 2, 0, 0, 0, 0, 80, 2771922, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - On Data Set 2 2 - Run Script'), +(27719, 0, 11, 0, 38, 0, 100, 0, 3, 1, 0, 0, 0, 0, 80, 2771931, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - On Data Set 3 1 - Run Script'), +(27719, 0, 12, 0, 38, 0, 100, 0, 3, 2, 0, 0, 0, 0, 80, 2771932, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - On Data Set 3 2 - Run Script'), +(27719, 0, 13, 0, 38, 0, 100, 0, 4, 1, 0, 0, 0, 0, 80, 2771941, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - On Data Set 4 1 - Run Script'), +(27719, 0, 14, 0, 38, 0, 100, 0, 4, 2, 0, 0, 0, 0, 80, 2771942, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - On Data Set 4 2 - Run Script'); + +-- Quest start actionlists +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` IN (2771900, 2771910, 2771920, 2771930, 2771940)); +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 +(2771900, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 64, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Gurgthock - Actionlist - Store Targetlist'), +(2771900, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 64, 2, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 'Gurgthock - Actionlist - Store Targetlist'), +(2771900, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 83, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Gurgthock - Actionlist - Remove Npc Flags Questgiver'), +(2771900, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 0, 'Gurgthock - Actionlist - Say Line 0'), +(2771900, 9, 5, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 12, 27715, 6, 5000, 0, 0, 0, 8, 0, 0, 0, 0, 3242.77, -2340.98, 92.34, 0.98, 'Gurgthock - Actionlist - Summon Creature \'Ironhide\''), +(2771910, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 64, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Gurgthock - Actionlist - Store Targetlist'), +(2771910, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 64, 2, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 'Gurgthock - Actionlist - Store Targetlist'), +(2771910, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 83, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Gurgthock - Actionlist - Remove Npc Flags Questgiver'), +(2771910, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Say Line 1'), +(2771910, 9, 5, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 12, 27716, 6, 5000, 0, 0, 0, 8, 0, 0, 0, 0, 3242.77, -2340.98, 92.34, 0.98, 'Grennix Shivwiggle - Actionlist - Summon Creature \'Torgg Thundertotem\''), +(2771920, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 64, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Store Targetlist'), +(2771920, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 64, 2, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Store Targetlist'), +(2771920, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 83, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Remove Npc Flags Questgiver'), +(2771920, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Say Line 2'), +(2771920, 9, 4, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 0, 0, 1, 3, 0, 1, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Say Line 3'), +(2771920, 9, 5, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 12, 27717, 6, 5000, 0, 0, 0, 8, 0, 0, 0, 0, 3242.77, -2340.98, 92.34, 0.98, 'Grennix Shivwiggle - Actionlist - Summon Creature \'Rustblood\''), +(2771930, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 64, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Store Targetlist'), +(2771930, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 64, 2, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Store Targetlist'), +(2771930, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 83, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Remove Npc Flags Questgiver'), +(2771930, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0, 1, 0, 0, 0, 12, 4, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Say Line 4'), +(2771930, 9, 4, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 0, 0, 1, 5, 0, 1, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Say Line 5'), +(2771930, 9, 5, 0, 0, 0, 100, 0, 10000, 10000, 0, 0, 0, 0, 1, 6, 0, 1, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Say Line 6'), +(2771930, 9, 6, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 12, 27718, 6, 5000, 0, 0, 0, 8, 0, 0, 0, 0, 3242.77, -2340.98, 92.34, 0.98, 'Grennix Shivwiggle - Actionlist - Summon Creature \'Horgrenn Hellcleave\''), +(2771940, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 64, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Store Targetlist'), +(2771940, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 64, 2, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Store Targetlist'), +(2771940, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 83, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Remove Npc Flags Questgiver'), +(2771940, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 7, 0, 1, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Say Line 7'), +(2771940, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 12, 27727, 6, 5000, 0, 0, 0, 8, 0, 0, 0, 0, 3251.91, -2340.61, 91.86, 3.1, 'Grennix Shivwiggle - Actionlist - Summon Creature \'Conqueror Krenna\''); + +-- Quest success and fail actionlists +DELETE FROM `smart_scripts` WHERE (`entryorguid` IN (2771901, 2771902, 2771911, 2771912, 2771921, 2771922, 2771931, 2771932, 2771941, 2771942)) AND (`source_type` = 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 +(2771901, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 82, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Add Npc Flags Questgiver'), +(2771901, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 15, 12427, 0, 0, 0, 0, 0, 12, 2, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Quest Credit \'The Conquest Pit: Bear Wrestling!\''), +(2771902, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 82, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Add Npc Flags Questgiver'), +(2771902, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 6, 12427, 0, 0, 0, 0, 0, 12, 2, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Fail Quest \'The Conquest Pit: Bear Wrestling!\''), +(2771911, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 82, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Add Npc Flags Questgiver'), +(2771911, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 15, 12428, 0, 0, 0, 0, 0, 12, 2, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Quest Credit \'The Conquest Pit: Mad Furbolg Fighting!\''), +(2771912, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 82, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Add Npc Flags Questgiver'), +(2771912, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 6, 12428, 0, 0, 0, 0, 0, 12, 2, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Fail Quest \'The Conquest Pit: Mad Furbolg Fighting!\''), +(2771921, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 82, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Add Npc Flags Questgiver'), +(2771921, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 15, 12429, 0, 0, 0, 0, 0, 12, 2, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Quest Credit \'The Conquest Pit: Blood and Metal!\''), +(2771922, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 82, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Add Npc Flags Questgiver'), +(2771922, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 6, 12429, 0, 0, 0, 0, 0, 12, 2, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Fail Quest \'The Conquest Pit: Blood and Metal!\''), +(2771931, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 82, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Add Npc Flags Questgiver'), +(2771931, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 15, 12430, 0, 0, 0, 0, 0, 12, 2, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Quest Credit \'The Conquest Pit: Blood and Metal!\''), +(2771932, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 82, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Add Npc Flags Questgiver'), +(2771932, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 6, 12430, 0, 0, 0, 0, 0, 12, 2, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Fail Quest \'The Conquest Pit: Blood and Metal!\''), +(2771941, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 15, 12431, 0, 0, 0, 0, 0, 12, 2, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Quest Credit \'The Conquest Pit: Final Showdown!\''), +(2771941, 9, 1, 0, 0, 0, 100, 0, 15000, 15000, 0, 0, 0, 0, 82, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Add Npc Flags Questgiver'), +(2771942, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 82, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Add Npc Flags Questgiver'), +(2771942, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 6, 12431, 0, 0, 0, 0, 0, 12, 2, 0, 0, 0, 0, 0, 0, 0, 'Grennix Shivwiggle - Actionlist - Fail Quest \'The Conquest Pit: Final Showdown!\''); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` IN (27715, 27716, 27717, 27718, 27727)); +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 +(27715, 0, 0, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 45, 0, 1, 0, 0, 0, 0, 10, 102451, 27719, 0, 0, 0, 0, 0, 0, 'Ironhide - On Just Died - Set Data 0 1 on Grennix'), +(27715, 0, 1, 2, 1, 0, 100, 1, 30000, 30000, 0, 0, 0, 0, 45, 0, 2, 0, 0, 0, 0, 10, 102451, 27719, 0, 0, 0, 0, 0, 0, 'Ironhide - Out of Combat - Set Data 0 2 on Grennix (No Repeat)'), +(27715, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Ironhide - Out of Combat - Despawn Instant (No Repeat)'), +(27715, 0, 3, 0, 9, 0, 100, 0, 0, 0, 17000, 24000, 8, 25, 11, 32323, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Ironhide - Within 8-25 Range - Cast \'Charge\''), +(27715, 0, 4, 0, 0, 0, 100, 0, 5000, 7000, 7000, 9000, 0, 0, 11, 34298, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Ironhide - In Combat - Cast \'Maul\''), +(27715, 0, 5, 0, 9, 0, 100, 0, 0, 0, 7000, 11000, 0, 5, 11, 31279, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Ironhide - Within 0-5 Range - Cast \'Swipe\''), +(27716, 0, 0, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 10, 102451, 27719, 0, 0, 0, 0, 0, 0, 'Torgg Thundertotem - On Just Died - Set Data 1 1 on Grennix'), +(27716, 0, 1, 2, 1, 0, 100, 1, 30000, 30000, 0, 0, 0, 0, 45, 1, 2, 0, 0, 0, 0, 10, 102451, 27719, 0, 0, 0, 0, 0, 0, 'Torgg Thundertotem - Out of Combat - Set Data 1 2 on Grennix (No Repeat)'), +(27716, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Torgg Thundertotem - Out of Combat - Despawn Instant (No Repeat)'), +(27716, 0, 3, 0, 0, 0, 100, 0, 1000, 3000, 6000, 8000, 0, 0, 11, 16033, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Torgg Thundertotem - In Combat - Cast \'Chain Lightning\''), +(27716, 0, 4, 0, 2, 0, 100, 0, 0, 30, 15000, 25000, 0, 0, 11, 15982, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Torgg Thundertotem - Between 0-30% Health - Cast \'Healing Wave\''), +(27716, 0, 5, 0, 0, 0, 100, 0, 0, 0, 21000, 21000, 0, 0, 11, 31991, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Torgg Thundertotem - In Combat - Cast \'Corrupted Nova Totem\''), +(27716, 0, 6, 0, 0, 0, 100, 0, 4000, 4000, 12000, 12000, 0, 0, 11, 15501, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Torgg Thundertotem - In Combat - Cast \'Earth Shock\''), +(27717, 0, 0, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 45, 2, 1, 0, 0, 0, 0, 10, 102451, 27719, 0, 0, 0, 0, 0, 0, 'Rustblood - On Just Died - Set Data 2 1 on Grennix'), +(27717, 0, 1, 2, 1, 0, 100, 1, 30000, 30000, 0, 0, 0, 0, 45, 2, 2, 0, 0, 0, 0, 10, 102451, 27719, 0, 0, 0, 0, 0, 0, 'Rustblood - Out of Combat - Set Data 2 2 on Grennix (No Repeat)'), +(27717, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rustblood - Out of Combat - Despawn Instant (No Repeat)'), +(27717, 0, 3, 0, 0, 0, 100, 0, 5000, 7000, 5000, 7000, 0, 0, 11, 42746, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Rustblood - In Combat - Cast \'Cleave\''), +(27717, 0, 4, 0, 9, 0, 100, 0, 0, 0, 22000, 30000, 0, 5, 11, 49398, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Rustblood - Within 0-5 Range - Cast \'Knockback\''), +(27717, 0, 5, 0, 0, 0, 100, 0, 12000, 15000, 18000, 21000, 0, 0, 11, 14102, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Rustblood - In Combat - Cast \'Head Smash\''), +(27717, 0, 6, 0, 0, 0, 100, 0, 0, 3000, 12000, 12000, 0, 0, 11, 61893, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Rustblood - In Combat - Cast \'Lightning Bolt\''), +(27718, 0, 0, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 45, 3, 1, 0, 0, 0, 0, 10, 102451, 27719, 0, 0, 0, 0, 0, 0, 'Horgrenn Hellcleave - On Just Died - Set Data 3 1 on Grennix'), +(27718, 0, 1, 2, 1, 0, 100, 1, 30000, 30000, 0, 0, 0, 0, 45, 3, 2, 0, 0, 0, 0, 10, 102451, 27719, 0, 0, 0, 0, 0, 0, 'Horgrenn Hellcleave - Out of Combat - Set Data 3 2 on Grennix (No Repeat)'), +(27718, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Horgrenn Hellcleave - Out of Combat - Despawn Instant (No Repeat)'), +(27718, 0, 3, 0, 9, 1, 100, 0, 0, 0, 21000, 29000, 0, 10, 11, 16508, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Horgrenn Hellcleave - Within 0-10 Range - Cast \'Intimidating Roar\' (Phase 1)'), +(27718, 0, 4, 0, 0, 1, 100, 0, 3000, 6000, 8000, 12000, 0, 0, 11, 15572, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Horgrenn Hellcleave - In Combat - Cast \'Sunder Armor\' (Phase 1)'), +(27718, 0, 5, 0, 0, 1, 100, 0, 9000, 12000, 12000, 16000, 0, 0, 11, 39171, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Horgrenn Hellcleave - In Combat - Cast \'Mortal Strike\' (Phase 1)'), +(27718, 0, 6, 0, 0, 1, 100, 0, 13000, 15000, 13000, 18000, 0, 0, 11, 38618, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Horgrenn Hellcleave - In Combat - Cast \'Whirlwind\' (Phase 1)'), +(27718, 0, 7, 0, 37, 0, 100, 0, 0, 0, 0, 0, 0, 0, 80, 2771800, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Horgrenn Hellcleave - On Initialize - Run Script'), +(27727, 0, 0, 9, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 45, 4, 1, 0, 0, 0, 0, 10, 102451, 27719, 0, 0, 0, 0, 0, 0, 'Conqueror Krenna - On Just Died - Set Data 4 1 on Grennix'), +(27727, 0, 1, 2, 1, 0, 100, 1, 60000, 60000, 0, 0, 0, 0, 45, 4, 2, 0, 0, 0, 0, 10, 102451, 27719, 0, 0, 0, 0, 0, 0, 'Conqueror Krenna - Out of Combat - Set Data 4 2 on Grennix (No Repeat)'), +(27727, 0, 2, 10, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Conqueror Krenna - Out of Combat - Despawn Instant (No Repeat)'), +(27727, 0, 3, 0, 9, 1, 100, 0, 0, 0, 7000, 9000, 0, 5, 11, 15284, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Conqueror Krenna - Within 0-5 Range - Cast \'Cleave\' (Phase 1)'), +(27727, 0, 4, 0, 0, 1, 100, 0, 9000, 12000, 12000, 17000, 0, 0, 11, 11430, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Conqueror Krenna - In Combat - Cast \'Slam\' (Phase 1)'), +(27727, 0, 5, 0, 105, 1, 100, 0, 14000, 17000, 14000, 17000, 0, 5, 11, 12555, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Conqueror Krenna - On Hostile Casting in Range - Cast \'Pummel\' (Phase 1)'), +(27727, 0, 6, 0, 13, 1, 100, 0, 3000, 6000, 6000, 0, 0, 0, 11, 34719, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Conqueror Krenna - On Victim Casting \'Open Wound\' - Cast \'Fixate\' (Phase 1)'), +(27727, 0, 7, 0, 37, 0, 100, 0, 0, 0, 0, 0, 0, 0, 80, 2772700, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Conqueror Krenna - On Initialize - Run Script'), +(27727, 0, 8, 0, 52, 0, 100, 0, 2, 27726, 0, 0, 0, 0, 80, 2772701, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Conqueror Krenna - On Text 2 Over - Run Script'), +(27727, 0, 9, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 204, 27726, 0, 0, 0, 0, 0, 0, 0, 'Conqueror Krenna - On Just Died - Set Data 1 1'), +(27727, 0, 10, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 45, 1, 2, 0, 0, 0, 0, 204, 27726, 0, 0, 0, 0, 0, 0, 0, 'Conqueror Krenna - Out of Combat - Set Data 1 2 (No Repeat)'); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 2771800); +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 +(2771800, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 18, 256, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Horgrenn Hellcleave - Actionlist - Set Flags Immune To Players'), +(2771800, 9, 1, 0, 0, 0, 100, 0, 3000, 3000, 0, 0, 0, 0, 11, 48350, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Horgrenn Hellcleave - Actionlist - Cast \'Emote Roar\''), +(2771800, 9, 2, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 0, 0, 19, 256, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Horgrenn Hellcleave - Actionlist - Remove Flags Immune To Players'), +(2771800, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Horgrenn Hellcleave - Actionlist - Set Event Phase 1'); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 2772700); +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 +(2772700, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 12, 27726, 3, 300000, 0, 0, 0, 8, 0, 0, 0, 0, 3244.5, -2340.56, 92.14, 6.27, 'Conqueror Krenna - Actionlist - Summon Creature \'Gorgonna\''), +(2772700, 9, 1, 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, 'Conqueror Krenna - Actionlist - Say Line 0'), +(2772700, 9, 2, 0, 0, 0, 100, 0, 18000, 18000, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Conqueror Krenna - Actionlist - Say Line 1'), +(2772700, 9, 3, 0, 0, 0, 100, 0, 18000, 18000, 0, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Conqueror Krenna - Actionlist - Set Faction 4'), +(2772700, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Conqueror Krenna - Actionlist - Set Event Phase 1'), +(2772700, 9, 5, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 11, 27726, 40, 1, 0, 0, 0, 0, 0, 'Conqueror Krenna - Actionlist - Start Attacking'); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 27726); +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 +(27726, 0, 0, 0, 37, 0, 100, 0, 0, 0, 0, 0, 0, 0, 80, 2772600, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Gorgonna - On Initialize - Run Script'), +(27726, 0, 1, 0, 38, 0, 100, 0, 1, 1, 0, 0, 0, 0, 80, 2772601, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Gorgonna - On Data Set 1 1 - Run Script'), +(27726, 0, 2, 0, 38, 0, 100, 0, 1, 2, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Gorgonna - On Data Set 1 2 - Despawn Instant'); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` IN (2772600, 2772601)); +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 +(2772600, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 83, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Gorgonna - Actionlist - Remove Npc Flags Questgiver'), +(2772600, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 117, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Gorgonna - Actionlist - Disable Evade'), +(2772600, 9, 2, 0, 0, 0, 100, 0, 6000, 6000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Gorgonna - Actionlist - Say Line 0'), +(2772600, 9, 3, 0, 0, 0, 100, 0, 6000, 6000, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Gorgonna - Actionlist - Say Line 1'), +(2772600, 9, 4, 0, 0, 0, 100, 0, 18000, 18000, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Gorgonna - Actionlist - Say Line 2'), +(2772601, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 81, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Gorgonna - Actionlist - Set Npc Flags Questgiver'), +(2772601, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 90, 8, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Gorgonna - Actionlist - Set Flag Standstate Kneel'), +(2772601, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 30000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Gorgonna - Actionlist - Despawn In 25000 ms'), +(2772601, 9, 3, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Gorgonna - Actionlist - Say Line 2'); + +DELETE FROM `creature_text` WHERE (`CreatureID` = 27719); +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(27719, 0, 0, 'Ladies and gentlemen, gather round the Conquest Pit! Witness the battle of $r versus bear and place your bets with confidence!', 14, 0, 100, 0, 0, 0, 27017, 0, 'Grennix Shivwiggle - Quest Accepted'), +(27719, 1, 0, 'Just when you think you\'ve seen it all! $n will square off with an authentic Grizzly Hills crazed furbolg in front of your very eyes here at the Conquest Pit! Place your bets, folks!', 14, 0, 100, 0, 0, 0, 27018, 0, 'Grennix Shivwiggle - Quest Accepted'), +(27719, 2, 0, 'Gather round, folks! Grab a warm drink and find a good seat for you\'re about to witness a showdown between $r and machine!', 14, 0, 100, 0, 0, 0, 27019, 0, 'Grennix Shivwiggle - Quest Accepted'), +(27719, 3, 0, 'Straight out of Thor Modan and made of 100 percent authentic... metal... here is Rustblood, the lightning-powered iron golem!', 14, 0, 100, 0, 0, 0, 27020, 0, 'Grennix Shivwiggle - Spawn'), +(27719, 4, 0, 'Ladies and gentlemen... gather round the pit!', 14, 0, 100, 0, 0, 0, 27014, 0, 'Grennix Shivwiggle - Quest Accepted'), +(27719, 5, 0, 'In one corner we have... $n, truly a world class $c. Slayer of reptiles, mammals, mechanical constructs and the odd dragon...kin. You\'ve never seen another $r like $g him : her;.', 14, 0, 100, 0, 0, 0, 27015, 0, 'Grennix Shivwiggle - Spawn'), +(27719, 6, 0, 'In the other corner, a serial killer, mass defenestrator, sentenced to death multiple times by noose and by blunt instrument! Horgrenn... Hellcleave! Ladies and gentlemen... place your bets!', 14, 0, 100, 0, 0, 0, 27016, 0, 'Grennix Shivwiggle - Spawn'), +(27719, 7, 0, 'Ladies and gentlemen! Well... let\'s just say you don\'t want to miss this one!', 14, 0, 100, 0, 0, 0, 27032, 0, 'Grennix Shivwiggle - Quest Accepted'); + +UPDATE `creature_template` SET `npcflag` = `npcflag` | 2 WHERE (`entry` = 27726); +DELETE FROM `creature_questender` WHERE (`id` = 27726 AND `quest` = 12431); +INSERT INTO `creature_questender` (`id`, `quest`) VALUES +(27726, 12431); diff --git a/data/sql/updates/db_world/2025_11_27_07.sql b/data/sql/updates/db_world/2025_11_27_07.sql new file mode 100644 index 000000000..850402fd3 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_27_07.sql @@ -0,0 +1,3 @@ +-- DB update 2025_11_27_06 -> 2025_11_27_07 +-- Following the same rule as the herbs, ores and fishing for the everfrost to be visible by all possible, they all use phase 255. +UPDATE `gameobject` SET `phaseMask` = 255 WHERE `id` = 193997; diff --git a/data/sql/updates/db_world/2025_11_27_08.sql b/data/sql/updates/db_world/2025_11_27_08.sql new file mode 100644 index 000000000..d982851c8 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_27_08.sql @@ -0,0 +1,11 @@ +-- DB update 2025_11_27_07 -> 2025_11_27_08 + +-- Set respawn time to 120 secs. +UPDATE `creature` SET `spawntimesecs` = 120 WHERE `id1` = 31306 AND `guid` = 74974; + +-- Add row Set Invincibility to 1% (Margrave Dhakar) +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 31306; + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 31306) AND (`source_type` = 0) AND (`id` IN (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`, `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 +(31306, 0, 10, 0, 25, 0, 100, 0, 0, 0, 0, 0, 0, 0, 42, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Margrave Dhakar - On Reset - Set Invincibility Hp 1%'); diff --git a/data/sql/updates/db_world/2025_11_27_09.sql b/data/sql/updates/db_world/2025_11_27_09.sql new file mode 100644 index 000000000..304d392ae --- /dev/null +++ b/data/sql/updates/db_world/2025_11_27_09.sql @@ -0,0 +1,36 @@ +-- DB update 2025_11_27_08 -> 2025_11_27_09 +-- Update SAI Comments (Image of Megalith) +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 24381; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24381); +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 +(24381, 0, 0, 0, 54, 0, 100, 512, 0, 0, 0, 0, 0, 0, 80, 2438100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Image of Megalith - On Just Summoned - Run Script'); + +-- Update Action List (Image of Megalith) +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 2438100); +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 +(2438100, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 12, 24385, 7, 0, 0, 0, 0, 8, 0, 0, 0, 0, 2410.14, -5727.26, 270.986, 4.28769, 'Image of Megalith - Actionlist - Summon Creature \'Image of Stone Giant\''), +(2438100, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 12, 24385, 7, 0, 0, 0, 0, 8, 0, 0, 0, 0, 2414.86, -5729.5, 272.095, 3.98296, 'Image of Megalith - Actionlist - Summon Creature \'Image of Stone Giant\''), +(2438100, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 12, 24385, 7, 0, 0, 0, 0, 8, 0, 0, 0, 0, 2417.34, -5733.23, 273.029, 3.60361, 'Image of Megalith - Actionlist - Summon Creature \'Image of Stone Giant\''), +(2438100, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 12, 24385, 7, 0, 0, 0, 0, 8, 0, 0, 0, 0, 2419.4, -5738.03, 274.121, 3.24154, 'Image of Megalith - Actionlist - Summon Creature \'Image of Stone Giant\''), +(2438100, 9, 4, 0, 0, 0, 100, 0, 4000, 4000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Image of Megalith - Actionlist - Say Line 0'), +(2438100, 9, 5, 0, 0, 0, 100, 0, 4000, 4000, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Image of Megalith - Actionlist - Say Line 1'), +(2438100, 9, 6, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Image of Megalith - Actionlist - Say Line 2'), +(2438100, 9, 7, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 0, 0, 223, 45, 0, 0, 0, 0, 0, 204, 24385, 0, 0, 0, 0, 0, 0, 0, 'Image of Megalith - Actionlist - Do Action ID 45'), -- Action Changed with do action / target summoned creatures +(2438100, 9, 8, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 43693, 0, 0, 0, 0, 0, 21, 40, 0, 0, 0, 0, 0, 0, 0, 'Image of Megalith - Actionlist - Cast \'Image of Megalith Kill Credit\''), +(2438100, 9, 9, 0, 0, 0, 100, 0, 3000, 3000, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Image of Megalith - Actionlist - Say Line 3'), +(2438100, 9, 10, 0, 0, 0, 100, 0, 3000, 3000, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Image of Megalith - Actionlist - Despawn Instant'); + +-- Add SAI (Image of Stone Giant) +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 24385; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24385); +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 +(24385, 0, 0, 0, 72, 0, 100, 0, 45, 0, 0, 0, 0, 0, 80, 2438500, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Image of Stone Giant - On Action 45 Done - Run Script'); -- Added this event. + +-- Update Action List comments (Image of Stone Giant) +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 2438500); +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 +(2438500, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Image of Stone Giant - Actionlist - Set Run Off'), +(2438500, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 2515.45, -5670.36, 298.778, 0.618311, 'Image of Stone Giant - Actionlist - Move To Position'), +(2438500, 9, 2, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Image of Stone Giant - Actionlist - Despawn Instant'); diff --git a/data/sql/updates/db_world/2025_11_27_10.sql b/data/sql/updates/db_world/2025_11_27_10.sql new file mode 100644 index 000000000..c92d1157e --- /dev/null +++ b/data/sql/updates/db_world/2025_11_27_10.sql @@ -0,0 +1,8 @@ +-- DB update 2025_11_27_09 -> 2025_11_27_10 +-- Sets all Herbs spawn time to be 15 minutes (as they are currently not pooled). +-- Goldclover, Tiger Lily, Talandra's Rose, Lichbloom, Icethorn, Frozen Herb (190173, 190174 and 190175), Adder's Tongue and Frost Lotus (currently can be farmed in an instance for free.) +UPDATE `gameobject` SET `spawntimesecs` = 900 WHERE `id` IN (189973, 190169, 190170, 190171, 190172, 190173, 190174, 190175, 191019, 190176) AND `SpawnMask` != 3; + +-- Sets all Ore Veins spawn time to be 15 minutes (as they are currently not pooled). +-- Colbat Deposit, Rich Cobalt Deposit, Sranoite Depoist, Rich Saronite Deposit, Titatinum Vein and Pure Sarotine Depoist +UPDATE `gameobject` SET `spawntimesecs` = 900 WHERE `id` IN (189980, 189981, 189978, 189979, 191133, 195036) AND `SpawnMask` != 3; diff --git a/data/sql/updates/db_world/2025_11_28_00.sql b/data/sql/updates/db_world/2025_11_28_00.sql new file mode 100644 index 000000000..f06028a20 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_28_00.sql @@ -0,0 +1,3 @@ +-- DB update 2025_11_27_10 -> 2025_11_28_00 +-- +UPDATE `creature_template_addon` SET `bytes2` = 3, `auras` = '49132 55795 61204' WHERE `entry` = 27530; diff --git a/data/sql/updates/db_world/2025_11_28_01.sql b/data/sql/updates/db_world/2025_11_28_01.sql new file mode 100644 index 000000000..78b491e60 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_28_01.sql @@ -0,0 +1,7 @@ +-- DB update 2025_11_28_00 -> 2025_11_28_01 +-- +-- Modify Target 9 - CREATURE_RANGE (can have multiple targets) to Target 19 - CLOSEST_CREATURE +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 18649100) AND (`source_type` = 9) AND (`id` IN (0, 2)); +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 +(18649100, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, 24035, 10, 0, 0, 0, 0, 0, 0, 'Gjalerbron Cage - Script - Set Data'), +(18649100, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 100, 1, 0, 0, 0, 0, 0, 19, 24035, 10, 0, 0, 0, 0, 0, 0, 'Gjalerbron Cage - Script - Send Targetlist'); diff --git a/data/sql/updates/db_world/2025_11_28_02.sql b/data/sql/updates/db_world/2025_11_28_02.sql new file mode 100644 index 000000000..c12a7a004 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_28_02.sql @@ -0,0 +1,9 @@ +-- DB update 2025_11_28_01 -> 2025_11_28_02 +-- update loot of Deep Sea Monsterbelly School (192053) +-- Crystallized Water, Deep Sea Monsterbelly, Reinforced Crate +UPDATE `gameobject_loot_template` SET `GroupId` = 1 WHERE (`Entry` = 25671) AND (`Item` IN (37705, 41800, 44475)); +-- Crystallized Water, Reinforced Crate +UPDATE `gameobject_loot_template` SET `Chance` = 0 WHERE (`Entry` = 25671) AND (`Item` IN (37705, 44475)); + +-- Pygmy Suckerfish, Sea Turtle, Blacktip Shark +UPDATE `gameobject_loot_template` SET `GroupId` = 2 WHERE (`Entry` = 25671) AND (`Item` IN (40199, 46109, 50289)); diff --git a/data/sql/updates/db_world/2025_11_28_03.sql b/data/sql/updates/db_world/2025_11_28_03.sql new file mode 100644 index 000000000..a4e262833 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_28_03.sql @@ -0,0 +1,8 @@ +-- DB update 2025_11_28_02 -> 2025_11_28_03 +-- +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 18636) AND (`source_type` = 0) AND (`id` IN (1, 2, 3, 4)); +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 +(18636, 0, 1, 0, 10, 0, 100, 1, 0, 8, 4000, 8000, 0, 0, 11, 30986, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Cabal Assassin - Out of Combat LoS - Cast \'Cheap Shot\''), +(18636, 0, 2, 0, 67, 0, 100, 0, 5000, 7000, 4500, 6500, 0, 5, 11, 30992, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Cabal Assassin - On Behind Target - Cast \'Backstab\''), +(18636, 0, 3, 0, 0, 0, 100, 0, 2000, 4500, 12000, 20000, 0, 0, 11, 30981, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Cabal Assassin - In Combat - Cast \'Crippling Poison\''), +(18636, 0, 4, 0, 0, 0, 100, 0, 8000, 11000, 22000, 25000, 0, 0, 11, 36974, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Cabal Assassin - In Combat - Cast \'Wound Poison\''); diff --git a/data/sql/updates/db_world/2025_11_28_04.sql b/data/sql/updates/db_world/2025_11_28_04.sql new file mode 100644 index 000000000..2436adc34 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_28_04.sql @@ -0,0 +1,15 @@ +-- DB update 2025_11_28_03 -> 2025_11_28_04 + +-- Morbidus send a set data to Dhakar on death. +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 30698; + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 30698) AND (`source_type` = 0) AND (`id` IN (2)); +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 +(30698, 0, 2, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 45, 1, 2, 0, 0, 0, 0, 10, 74974, 31306, 0, 0, 0, 0, 0, 0, 'Morbidus - On Just Died - Set Data 1 2'); + +-- Margrave Dhakar gives credit to stored target on data set. +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 31306; + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 31306) AND (`source_type` = 0) AND (`id` IN (11)); +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 +(31306, 0, 11, 0, 38, 0, 100, 0, 1, 2, 0, 0, 0, 0, 33, 30698, 0, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 0, 'Margrave Dhakar - On Data Set 1 2 - Quest Credit \'Morbidus\''); diff --git a/data/sql/updates/db_world/2025_11_28_05.sql b/data/sql/updates/db_world/2025_11_28_05.sql new file mode 100644 index 000000000..91b234083 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_28_05.sql @@ -0,0 +1,214 @@ +-- DB update 2025_11_28_04 -> 2025_11_28_05 +ALTER TABLE `spell_group` DROP `special_flag`; +ALTER TABLE `spell_group` MODIFY COLUMN `spell_id` int; + +-- import from trinitycore +DELETE FROM `spell_group`; +INSERT INTO `spell_group` (`id`,`spell_id`) VALUES +(1, 2367), (1, 2374), (1, 3160), (1, 3164), (1, 7844), (1, 8212), (1, 10667), (1, 10669), (1, 11328), (1, 11334), (1, 11390), (1, 11405), (1, 11406), (1, 11474), (1, 16322), (1, 16323), (1, 16329), (1, 17038), (1, 17537), (1, 17538), (1, 17539), (1, 17626), (1, 17627), (1, 17628), (1, 17629), (1, 21920), (1, 26276), (1, 28486), (1, 28488), (1, 28490), (1, 28491), (1, 28493), (1, 28497), (1, 28501), (1, 28503), (1, 28518), (1, 28519), (1, 28520), (1, 28521), (1, 28540), (1, 33720), (1, 33721), (1, 33726), (1, 38954), (1, 40567), (1, 40568), (1, 40572), (1, 40573), (1, 40575), (1, 40576), (1, 41608), (1, 41609), (1, 41610), (1, 41611), (1, 42735), (1, 45373), (1, 46837), (1, 46839), (1, 53746), (1, 53748), (1, 53749), (1, 53752), (1, 53755), (1, 53758), (1, 53760), (1, 54212), (1, 54452), (1, 54494), (1, 60340), (1, 60341), (1, 60344), (1, 60345), (1, 60346), (1, 62380), (1, 63729), (1, 67016), (1, 67017), (1, 67018), +(2, 673), (2, 2378), (2, 2380), (2, 3166), (2, 3219), (2, 3220), (2, 3222), (2, 3223), (2, 3593), (2, 10668), (2, 10692), (2, 10693), (2, 11319), (2, 11348), (2, 11349), (2, 11371), (2, 11396), (2, 15231), (2, 15233), (2, 16321), (2, 16325), (2, 16326), (2, 16327), (2, 17535), (2, 17626), (2, 17627), (2, 17628), (2, 17629), (2, 24361), (2, 24363), (2, 24382), (2, 24383), (2, 24417), (2, 27652), (2, 27653), (2, 28502), (2, 28509), (2, 28514), (2, 28518), (2, 28519), (2, 28520), (2, 28521), (2, 28540), (2, 29348), (2, 39625), (2, 39626), (2, 39627), (2, 39628), (2, 40567), (2, 40568), (2, 40572), (2, 40573), (2, 40575), (2, 40576), (2, 41608), (2, 41609), (2, 41610), (2, 41611), (2, 42735), (2, 46837), (2, 46839), (2, 53747), (2, 53751), (2, 53752), (2, 53755), (2, 53758), (2, 53760), (2, 53763), (2, 53764), (2, 54212), (2, 60343), (2, 60347), (2, 62380), (2, 67016), (2, 67017), (2, 67018), +(1001, 18125), (1001, 18141), (1001, 19705), (1001, 19706), (1001, 19708), (1001, 19709), (1001, 19710), (1001, 19711), (1001, 20875), (1001, 23697), (1001, 24799), (1001, 24870), (1001, 25037), (1001, 25694), (1001, 25722), (1001, 25804), (1001, 25941), (1001, 33254), (1001, 33256), (1001, 33257), (1001, 33259), (1001, 33261), (1001, 33263), (1001, 33265), (1001, 33268), (1001, 33272), (1001, 35272), (1001, 40323), (1001, 42293), (1001, 43722), (1001, 43764), (1001, 43771), (1001, 44097), (1001, 44098), (1001, 44099), (1001, 44100), (1001, 44101), (1001, 44102), (1001, 44104), (1001, 44105), (1001, 44106), (1001, 45245), (1001, 45619), (1001, 45694), (1001, 46682), (1001, 46687), (1001, 46899), (1001, 53284), (1001, 57079), (1001, 57097), (1001, 57100), (1001, 57102), (1001, 57107), (1001, 57111), (1001, 57139), (1001, 57286), (1001, 57288), (1001, 57291), (1001, 57294), (1001, 57325), (1001, 57327), (1001, 57329), (1001, 57332), (1001, 57334), (1001, 57356), (1001, 57358), (1001, 57360), (1001, 57363), (1001, 57365), (1001, 57367), (1001, 57371), (1001, 57373), (1001, 57399), (1001, 58468), (1001, 58479), (1001, 59230), (1001, 62349), (1001, 64057), (1001, 65247), (1001, 65365), (1001, 65410), (1001, 65412), (1001, 65414), (1001, 65415), (1001, 65416), (1001, 66623), (1001, 66624), (1001, 69559), +(1002, 19740), (1002, 25782), (1002, 56520), -- Blessing of Might +(1003, 6673), -- Battle Shout +(1004, -1003), (1004, -1002), -- Flap AP Buffs +(1005, 19742), (1005, 25894), (1005, 56521), -- Blessing of Wisdom +(1006, 20217), (1006, 25898), (1006, 43223), (1006, 56525), (1006, 58054), (1006, 72586), -- All Stats Percentage +(1007, 20911), (1007, 25899), -- Blessing of Sanctuary +(1008, 23415), (1008, 41450), -- Blessing of Protection +(1009, 32770), -- Blessing of Light +(1010, -1009), (1010, -1008), (1010, -1007), (1010, -1006), (1010, -1005), (1010, -1002), -- Blessings +(1011, -1091), (1011, -1003), -- Warrior Shouts +(1012, 55749), -- Acid Spit +(1013, 8647), -- Expose Armor +(1014, 58567), -- Sunder Armor +(1015, -1014), (1015, -1013), (1015, -1012), -- Major Armor Debuffs +(1016, 770), (1016, 16857), -- Faerie Fire +(1017, 56626), -- Sting +(1019, -1063), (1019, -1017), (1019, -1016), -- Minor Armor Debuffs +(1020, 55610), -- Icy Talons +(1021, 8515), -- Windfury Totem +(1022, -1021), (1022, -1020), -- Melee Haste Buffs +(1023, 24932), -- Leader of the Pack +(1024, 29801), -- Rampage +(1025, -1024), (1025, -1023), -- Physical Crit Buffs +(1026, 53137), -- Abomination's Might +(1027, 19506), -- Trueshot Aura +(1028, 30802), -- Unleashed Rage +(1029, -1028), (1029, -1027), (1029, -1026), -- Percentage AP Buffs +(1030, 33878), -- Mangle (Bear) +(1031, 33876), -- Mangle (Cat) +(1032, 46856), -- Trauma +(1033, -1032), (1033, -1031), (1033, -1030), -- Bleed Debuffs +(1034, 24907), -- Moonkin Aura +(1035, 51466), -- Elemental Oath +(1036, -1035), (1036, -1034), -- Spell Crit Buffs +(1037, 12579), (1037, 17794), (1037, 17797), (1037, 17798), (1037, 17799), (1037, 17800), (1037, 22959), -- Spell Crit Debuffs +(1038, -1006), (1038, 67480), -- All Stats Percentage with Sanctuary +-- 1039-44 +(1045, 52109), -- Flametongue Totem +(1046, 57658), -- Totem of Wrath +(1047, 48090), -- Demonic Pact +(1048, -1047), (1048, -1046), (1048, -1045), -- Spell Power Buffs +-- 1049 +(1050, 33196), -- Misery +(1051, -1050), (1051, -1016), -- Spell Hit Debuffs +(1052, 7294), -- Retribution Aura +(1053, 63531), -- Sanctified Retribution +(1054, -1053), (1054, -1052), (1054, 50170), -- Haste Buffs +-- 1055 +(1056, -1053), (1056, -1052), (1056, 31579), (1056, 75593), -- Damage Done Buffs +(1057, 13218), -- Wound Poison +(1058, -1057), (1058, 2818), (1058, 3409), (1058, 5760), (1058, 21183), (1058, 30708), -- Crit Taken Debuffs +(1059, 89), (1059, 6136), (1059, 6343), (1059, 6360), (1059, 7321), (1059, 8042), (1059, 16914), (1059, 20005), (1059, 27648), (1059, 51693), (1059, 55095), (1059, 58179), (1059, 68055), -- Attack Speed Debuffs +(1060, 3043), (1060, 5570), -- Hit Chance Debuffs +(1061, -1057), (1061, 12294), (1061, 19434), (1061, 56112), -- Healing Taken Debuffs +(1062, -1063), (1062, 67), (1062, 99), (1062, 1160), -- AP Debuffs +(1063, 702), -- Curse of Weakness +(1064, 8076), -- Strength of Earth +(1065, 57330), -- Horn of Winter +(1066, 8118), -- Strength Scroll +(1067, 8115), -- Agility Scroll +(1068, 8096), -- Intellect Scroll +(1069, 8099), -- Stamina Scroll +(1070, 8112), -- Spirit Scroll +(1071, 8091), -- Armor Scroll +(1072, 1459), -- Arcane Intellect +(1073, 54424), -- Fel Intelligence +(1074, 1243), -- Power Word: Fortitude +(1075, 21562), -- Prayer of Fortitude +(1076, 14752), -- Divine Spirit +(1077, 27681), -- Prayer of Spirit +(1078, 1126), -- Mark of the Wild +(1079, 21849), -- Gift of the Wild +(1080, 23028), -- Arcane Brilliance +(1081, 61024), -- Dalaran Intellect +(1082, 61316), -- Dalaran Brilliance +(1083, -1082), (1083, -1081), (1083, -1080), (1083, -1072), (1083, -1068), -- Mage Intellect Buffs +(1084, -1075), (1084, -1074), (1084, -1069), (1084, 72590), -- Priest Stamina Buffs +(1085, -1077), (1085, -1076), (1085, -1070), -- Priest Spirit Buffs +(1086, -1071), (1086, 8072), -- Armor Buffs +(1087, -1071), (1087, -1070), (1087, -1069), (1087, -1068), (1087, -1067), (1087, -1066),-- Scrolls +(1088, -1065), (1088, -1064), -- Strength and Agility Buffs +(1091, 469), -- Commanding Shout +(1092, 6307), -- Blood Pact +(1093, -1092), (1093, -1091), -- HP Buffs +(1094, 34123), (1094, 63514), -- Healing Taken Buffs +(1095, 14893), (1095, 16177), -- Physical Taken Buffs +(1096, 1714), (1096, 5760), (1096, 31589), -- Cast Time Debuffs +(1097, 122), (1097, 33395), (1097, 55080), -- Frost Novas +(1098, 976), (1098, 27683), -- Shadow Protection +(1099, 348), (1099, 30108), -- Immolate and Unstable Affliction +(1100, 604), (1100, 1008), -- Dampen/Amplify Magic +(1101, 1490), (1101, 51726), (1101, 60431), -- Spell Damage Taken Debuffs +(1102, 40055), (1102, 40165), (1102, 40166), (1102, 40167), -- Introspection +(1103, 40623), (1103, 40625), (1103, 40626), -- Apexis Movement Speed +(1104, 12880), (1104, 57514), (1104, 57518), -- Warrior Enrages +(1105, -1005), (1105, 5677), -- MP5 Buffs +(1106, 6562), (1106, 28878), -- Heroic Presence +(1107, 12042), (1107, 12292), (1107, 31884), (1107, 34471), (1107, 49016), (1107, 57933), -- Temporary Damage Increases +(1108, 30069), (1108, 58684), -- Phys Damage Taken Debuffs +(1110, 74826), (1110, 74827), (1110, 74828), (1110, 74829), (1110, 74830), (1110, 74831), (1110, 74832), (1110, 74833), (1110, 74834), (1110, 74835), (1110, 74836), -- Corporeality +(1111, 62727), (1111, 63438), (1111, 63439), (1111, 63440), (1111, 63441), (1111, 63442), (1111, 63443), (1111, 63444), (1111, 63445), (1111, 63446), -- Champion's Pennant +(1112, 8219), (1112, 8220), (1112, 8221), (1112, 8222), -- Flip Out +-- 1116-20 +(1121, 3671), (1121, 3672), (1121, 3673), -- Elemental Slave Buffs +(1122, 2825), (1122, 10060), (1122, 32182), -- Temporary Haste Buffs +(1123, 10060), (1123, 12042), -- Power Infusion and Arcane Power +(1124, -1085), (1124, -1073), -- Intellect Buffs +(1125, -1083), (1125, -1073), -- Spirit Buffs + +-- values missing from trinitycore +(1, 33053), -- Crawdad Flask +(1001, 5020), (1001, 5021), (1001, 5257), (1001, 6114), (1001, 15852), (1001, 18191), (1001, 18192), (1001, 18193), (1001, 18194), (1001, 18222), (1001, 22730), (1001, 22789), (1001, 25661), (1001, 37058), (1001, 43730), -- More Foods +(1006, 26393), -- Elune's Blessing +(1062, 24423), -- Demoralizing Screech +(1019, 50274), -- Spore Cloud +(1022, 23060), -- Battle Squawk +-- (1058, 45176), -- Server Side Master Poisoner (is it needed?) +(1084, 23947), (1084, 23948), -- NPC Power Word Fortitude +(1096, 35387), -- Poison Spit +(1096, 58604), -- Lava Breath +(1089, -1079), (1089, -1078), (1089, 72588), (1089, 16878), (1089, 24752), (1089, 39233), -- Mark of the Wild +(1107, 48391), -- Owlkin Frenzy +(1090, 7481), (1090, 7483), (1090, 7484), -- Howling Rage +(1113, 467), -- Thorns +(1114, 70233), (1114, 70234), (1114, 70235), (1114, 70242), (1114, 70243), (1114, 70244), -- Perfumes/Colognes +(1115, 46302), -- K'iru's Song of Victory +(1126, -1115), (1126, -1084), -- Stamina Buffs +(1124, -1115); -- Intellect Buffs + +DELETE FROM `spell_group_stack_rules`; +INSERT INTO `spell_group_stack_rules` (`group_id`,`stack_rule`, `description`) VALUES +(1, 1,'Battle Elixir'), +(2, 1, 'Guardian Elixir'), +(1001, 1, 'Well Fed'), +(1002, 4, 'Blessing of Might'), +(1003, 4, 'Battle Shout'), +(1004, 4, 'Flat AP Buffs'), +(1005, 4, 'Blessing of Wisdom'), +(1006, 1, 'All Stats Percentage'), +(1007, 1, 'Blessing of Sanctuary'), +(1008, 1, 'Blessing of Protection'), +(1009, 1, 'Blessing of Light'), +(1010, 2, 'Blessings'), +(1011, 2, 'Warrior Shouts'), +(1015, 3, 'Major Armor Debuffs'), +(1016, 4, 'Faerie Fire'), +(1019, 3, 'Minor Armor Debuffs'), +(1022, 3, 'Melee Haste Buffs'), +(1023, 4, 'Leader of the Pack'), +(1024, 4, 'Rampage'), +(1025, 3, 'Physical Crit Buffs'), +(1029, 1, 'Percentage AP Buffs'), +(1033, 1, 'Bleed Debuffs'), +(1036, 4, 'Spell Crit Buffs'), +(1037, 3, 'Spell Crit Debuffs'), +(1038, 3, 'All Stats Percentage with Sanctuary'), +(1046, 4, 'Totem of Wrath'), +(1048, 4, 'Spell Power Buffs'), +(1051, 3, 'Spell Hit Debuffs'), +(1054, 3, 'Haste Buffs'), +(1056, 3, 'Damage Done Buffs'), +(1058, 3, 'Poisons'), +(1059, 3, 'Attack Speed Debuffs'), +(1060, 3, 'Hit Chance Debuffs'), +(1061, 4, 'Healing Taken Debuffs'), +(1062, 4, 'AP Debuffs'), +(1083, 4, 'Single Intellect Buffs'), +(1084, 4, 'Single Stamina Buffs'), +(1085, 4, 'Single Spirit Buffs'), +(1086, 4, 'Armor Buffs'), +(1087, 4, 'Scrolls'), +(1088, 4, 'Strength and Agility Buffs'), +(1091, 0, 'Commanding Shout'), +(1092, 0, 'Blood Pact'), +(1093, 4, 'Flat HP Buffs'), +(1094, 3, 'Healing Taken Buffs'), +(1095, 4, 'Physical Taken Buffs'), +(1096, 4, 'Cast Time Debuffs'), +(1097, 1, 'Frost Novals'), +(1098, 4, 'Shadow Protection'), +(1099, 2, 'Immolate and Unstable Affliction'), +(1100, 1, 'Dampen/Amplify Magic'), +(1101, 3, 'Spell Damage Taken Debuffs'), +(1104, 1, 'Warrior Enrages'), +(1105, 3, 'MP5 Buffs'), +(1106, 1, 'Heroic Presence'), +(1107, 4, 'Temporary Damage Increases'), +(1108, 4, 'Phys Damage Taken Debuffs'), +(1110, 1, 'Corporeality'), +(1111, 1, 'Champion''s Pennants'), +(1112, 1, 'Flip Out'), +(1121, 1, 'Elemental Slave Buffs'), +(1122, 4, 'Temporary Haste Buffs'), +(1123, 1, 'Power Infusion and Arcane Power'), +(1124, 3, 'Intellect Buffs'), +(1125, 3, 'Spirit Buffs'), + +-- additions +(1089, 4, 'Mark of the Wild'), +(1113, 4, 'Thorns'), +(1126, 3, 'Stamina Buffs'); + +DELETE FROM `spell_script_names` WHERE `spell_id` IN (18735, 56246, 56247); +INSERT INTO `spell_script_names` VALUES (18735, 'spell_warl_voidwalker_pet_passive'); \ No newline at end of file diff --git a/data/sql/updates/db_world/2025_11_28_06.sql b/data/sql/updates/db_world/2025_11_28_06.sql new file mode 100644 index 000000000..b2d5d6b30 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_28_06.sql @@ -0,0 +1,47 @@ +-- DB update 2025_11_28_05 -> 2025_11_28_06 +-- +-- Increase despawn timer +UPDATE `smart_scripts` SET `action_param3`=180000 WHERE `entryorguid` IN (-125414, -123669, -123663, -123660) AND `source_type`=0 AND `id`=0; + +-- Spawn only when there's a Wyrm Reanimator nearby +DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 22) AND (`SourceGroup` = 1) AND (`SourceEntry` IN (-125414, -123669, -123663, -123660)) AND (`SourceId` = 0) AND (`ElseGroup` = 0) AND (`ConditionTypeOrReference` = 29) AND (`ConditionTarget` = 1) AND (`ConditionValue1` = 31731) AND (`ConditionValue2` = 30) AND (`ConditionValue3` = 0); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(22, 1, -125414, 0, 0, 29, 1, 31731, 30, 0, 0, 0, 0, '', 'must be near \'Wyrm Reanimator\''), +(22, 1, -123669, 0, 0, 29, 1, 31731, 30, 0, 0, 0, 0, '', 'must be near \'Wyrm Reanimator\''), +(22, 1, -123663, 0, 0, 29, 1, 31731, 30, 0, 0, 0, 0, '', 'must be near \'Wyrm Reanimator\''), +(22, 1, -123660, 0, 0, 29, 1, 31731, 30, 0, 0, 0, 0, '', 'must be near \'Wyrm Reanimator\''); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 31702); +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 +(31702, 0, 0, 1, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 64, 1, 0, 0, 0, 0, 0, 19, 31731, 0, 0, 0, 0, 0, 0, 0, 'Frostbrood Spawn - On Just Summoned - Store Targetlist'), +(31702, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 80, 3170200, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Frostbrood Spawn - On Just Summoned - Run Script'), +(31702, 0, 2, 0, 34, 0, 100, 0, 8, 1, 0, 0, 0, 0, 80, 3170201, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Frostbrood Spawn - On Reached Point 1 - Run Script'), +(31702, 0, 3, 0, 0, 0, 100, 0, 0, 5000, 5000, 15000, 0, 0, 11, 60667, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Frostbrood Spawn - In Combat - Cast \'Frost Breath\''), +(31702, 0, 4, 0, 17, 0, 100, 0, 31731, 0, 0, 0, 0, 0, 64, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Frostbrood Spawn - On Summoned Unit - Store Targetlist'); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 3170200); +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 +(3170200, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 60, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Frostbrood Spawn - Actionlist - Set Fly On'), +(3170200, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 0, 30, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 0, 'Frostbrood Spawn - Actionlist - Despawn Instant'), +(3170200, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 12, 31731, 1, 120000, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 0, 'Frostbrood Spawn - Actionlist - Summon Creature \'Wyrm Reanimator\''), +(3170200, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Frostbrood Spawn - Actionlist - Set Active On'), +(3170200, 9, 4, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 0, 'Frostbrood Spawn - Actionlist - Move To Stored'); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 3170201); +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 +(3170201, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 36380, 2, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 0, 'Frostbrood Spawn - Actionlist - Cast \'Special Unarmed\''), +(3170201, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 86, 52391, 2, 12, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Frostbrood Spawn - Actionlist - Cross Cast \'Ride Vehicle\''), +(3170201, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 53, 2, 317020, 0, 0, 0, 1, 8, 0, 0, 0, 0, 7326.43, 1289.52, 611.652, 0, 'Frostbrood Spawn - Actionlist - Start Waypoint Path 317020'), +(3170201, 9, 3, 0, 0, 0, 100, 0, 30000, 30000, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 0, 'Frostbrood Spawn - Actionlist - Despawn Instant'), +(3170201, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Frostbrood Spawn - Actionlist - Despawn Instant'); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 31731); +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 +(31731, 0, 0, 0, 0, 0, 100, 0, 5000, 9000, 15000, 15000, 0, 0, 11, 32063, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Wyrm Reanimator - In Combat - Cast \'Corruption\''), +(31731, 0, 1, 0, 0, 0, 100, 0, 1000, 1000, 3000, 4000, 0, 0, 11, 9613, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Wyrm Reanimator - In Combat - Cast \'Shadow Bolt\''), +(31731, 0, 2, 0, 0, 0, 100, 0, 4000, 7000, 16000, 22000, 0, 0, 11, 11443, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Wyrm Reanimator - In Combat - Cast \'Cripple\''), +(31731, 0, 3, 0, 1, 1, 100, 0, 0, 0, 30000, 30000, 0, 0, 11, 59661, 0, 0, 0, 0, 0, 19, 27047, 0, 0, 0, 0, 0, 0, 0, 'Wyrm Reanimator - Out of Combat - Cast \'Icecrown Purple Beam\' (Phase 1)'), +(31731, 0, 4, 5, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 92, 0, 59661, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wyrm Reanimator - On Just Summoned - Interrupt Spell \'Icecrown Purple Beam\''), +(31731, 0, 5, 6, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 52385, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wyrm Reanimator - On Just Summoned - Cast \'Cosmetic - Periodic Cower\''), +(31731, 0, 6, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wyrm Reanimator - On Just Summoned - Set Event Phase 2'), +(31731, 0, 7, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wyrm Reanimator - On Respawn - Set Event Phase 1'); diff --git a/data/sql/updates/db_world/2025_11_28_07.sql b/data/sql/updates/db_world/2025_11_28_07.sql new file mode 100644 index 000000000..715309451 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_28_07.sql @@ -0,0 +1,128 @@ +-- DB update 2025_11_28_06 -> 2025_11_28_07 +-- +-- Gryphon Commander Urik SAI +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 27317; +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 27317); +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 +(27317, 0, 0, 0, 19, 0, 100, 0, 12511, 0, 0, 0, 0, 0, 11, 50629, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Gryphon Commander Urik - On Quest \'The Hills Have Us\' Taken - Cast \'Gryphon to Amberpine Lodge\''); + +-- Wintergarde Gryphon SAI +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 28061; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 28061); +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 +(28061, 0, 0, 0, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 80, 2806100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - On Just Summoned - Run Script'), +(28061, 0, 1, 0, 40, 0, 100, 0, 10, 0, 0, 0, 0, 0, 80, 2806101, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - On Point 10 of Path Any Reached - Run Script'), +(28061, 0, 2, 0, 40, 0, 100, 0, 21, 0, 0, 0, 0, 0, 80, 2806102, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - On Point 21 of Path Any Reached - Run Script'), +(28061, 0, 3, 0, 40, 0, 100, 0, 22, 0, 0, 0, 0, 0, 54, 4000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - On Point 22 of Path Any Reached - Pause Waypoint'), +(28061, 0, 4, 5, 40, 0, 100, 0, 31, 0, 0, 0, 0, 0, 54, 7000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - On Point 31 of Path Any Reached - Pause Waypoint'), +(28061, 0, 5, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 80, 2806103, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - On Point 31 of Path Any Reached - Run Script'), +(28061, 0, 6, 0, 40, 0, 100, 0, 33, 0, 0, 0, 0, 0, 80, 2806104, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - On Point 33 of Path Any Reached - Run Script'); + +DELETE FROM `smart_scripts` WHERE `entryorguid` BETWEEN 2806100 AND 2806104 AND `source_type` = 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 +(2806100, 9, 0, 0, 0, 0, 100, 0, 1000, 1000, 0, 0, 0, 0, 53, 2, 28061, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - Actionlist - Start Waypoint Path 28061'), +(2806100, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 60, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - Actionlist - Set Fly On'), +(2806100, 9, 2, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 19, 28065, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - Actionlist - Say Line 0'), +(2806101, 9, 0, 0, 0, 0, 100, 0, 1000, 1000, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 19, 28065, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - On Script - Say Line 1 (Wintergarde Gryphon Rider)'), +(2806102, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 19, 28065, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - On Script - Say Line 2 (Wintergarde Gryphon Rider)'), +(2806102, 9, 1, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 0, 0, 11, 50560, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - On Script - Cast \'Summon Conquest War Rider\''), +(2806102, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 50560, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - On Script - Cast \'Summon Conquest War Rider\''), +(2806102, 9, 3, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 0, 0, 11, 50560, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - On Script - Cast \'Summon Conquest War Rider\''), +(2806102, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44423, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - On Script - Cast \'Soar\''), +(2806102, 9, 5, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 19, 28065, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - On Script - Say Line 3 (Wintergarde Gryphon Rider)'), +(2806103, 9, 0, 0, 0, 0, 100, 0, 1000, 1000, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 19, 28065, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - On Script - Say Line 4 (Wintergarde Gryphon Rider)'), +(2806103, 9, 1, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 0, 0, 11, 49261, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - On Script - Cast \'Dismount Passenger\''), +(2806104, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 49259, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - On Script - Cast \'Despawn Driver\''), +(2806104, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 19, 28065, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - On Script - Despawn Instant Closest Creature \'Wintergarde Gryphon Rider\''), +(2806104, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 3000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Gryphon - On Script - Despawn (3000)'); + +-- SmartAI ignores 'delay' column +DELETE FROM `waypoints` WHERE `entry` = 28061; +INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `point_comment`) VALUES +(28061, 1, 3699.6936, -721.9221, 219.29805, 0, 0, 'Wintergarde Gryphon'), +(28061, 2, 3716.3372, -744.8086, 219.29805, 0, 0, 'Wintergarde Gryphon'), +(28061, 3, 3754.6975, -766.4142, 219.29805, 0, 0, 'Wintergarde Gryphon'), +(28061, 4, 3823.4036, -778.20447, 229.43698, 0, 0, 'Wintergarde Gryphon'), +(28061, 5, 3855.0312, -824.1102, 240.18695, 0, 0, 'Wintergarde Gryphon'), +(28061, 6, 3854.3972, -931.2962, 240.18697, 0, 0, 'Wintergarde Gryphon'), +(28061, 7, 3816.714, -1052.798, 218.93703, 0, 0, 'Wintergarde Gryphon'), +(28061, 8, 3674.9307, -1234.0061, 169.63153, 0, 0, 'Wintergarde Gryphon'), +(28061, 9, 3562.7188, -1421.7626, 169.63153, 0, 0, 'Wintergarde Gryphon'), +(28061, 10, 3549.2375, -1556.2838, 169.63153, 0, 0, 'Wintergarde Gryphon'), +(28061, 11, 3494.7446, -1667.5358, 166.7296, 0, 0, 'Wintergarde Gryphon'), +(28061, 12, 3469.591, -1731.115, 160.06296, 0, 0, 'Wintergarde Gryphon'), +(28061, 13, 3398.6677, -1834.3002, 160.06296, 0, 0, 'Wintergarde Gryphon'), +(28061, 14, 3326.5435, -1956.757, 160.06296, 0, 0, 'Wintergarde Gryphon'), +(28061, 15, 3302.4072, -2047.635, 160.06296, 0, 0, 'Wintergarde Gryphon'), +(28061, 16, 3321.5894, -2172.2275, 169.86847, 0, 0, 'Wintergarde Gryphon'), +(28061, 17, 3352.4548, -2278.8647, 174.61842, 0, 0, 'Wintergarde Gryphon'), +(28061, 18, 3349.7534, -2368.1155, 174.61842, 0, 0, 'Wintergarde Gryphon'), +(28061, 19, 3273.5618, -2401.9539, 174.61842, 0, 0, 'Wintergarde Gryphon'), +(28061, 20, 3236.3962, -2316.1958, 174.61842, 0, 0, 'Wintergarde Gryphon'), +(28061, 21, 3353.9648, -2232.0115, 170.36844, 0, 0, 'Wintergarde Gryphon'), -- delay: 4000 +(28061, 22, 3406.751, -2232.2563, 159.57182, 0, 0, 'Wintergarde Gryphon'), +(28061, 23, 3484.2961, -2251.2778, 147.90515, 0, 0, 'Wintergarde Gryphon'), +(28061, 24, 3584.2512, -2299.296, 147.90515, 0, 0, 'Wintergarde Gryphon'), +(28061, 25, 3687.5261, -2328.181, 173.07814, 0, 0, 'Wintergarde Gryphon'), +(28061, 26, 3739.8252, -2392.6477, 199.38365, 0, 0, 'Wintergarde Gryphon'), +(28061, 27, 3800.0535, -2478.2786, 214.51729, 0, 0, 'Wintergarde Gryphon'), +(28061, 28, 3769.2024, -2553.0325, 213.62839, 0, 0, 'Wintergarde Gryphon'), +(28061, 29, 3692.256, -2609.5562, 206.48958, 0, 0, 'Wintergarde Gryphon'), +(28061, 30, 3558.7239, -2723.1643, 213.62839, 0, 0, 'Wintergarde Gryphon'), +(28061, 31, 3439.4553, -2757.1624, 223.79466, 0, 0, 'Wintergarde Gryphon'), -- delay: 7000 +(28061, 32, 3406.0881, -2755.1821, 227.184, 0, 0, 'Wintergarde Gryphon'), +(28061, 33, 3390.089, -2773.591, 227.184, 0, 0, 'Wintergarde Gryphon'); + +DELETE FROM `creature_template_movement` WHERE `CreatureId` IN (28061, 28063); +INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`, `Chase`, `Random`) VALUES +(28061, 0, 0, 1, 0, 0, 0), +(28063, 0, 0, 1, 0, 0, 0); + +DELETE FROM `vehicle_template_accessory` WHERE `entry` = 28061; +INSERT INTO `vehicle_template_accessory` (`entry`, `accessory_entry`, `seat_id`, `minion`, `description`, `summontype`, `summontimer`) VALUES +(28061, 28065, 0, 1, 'Wintergarde Gryphon - Wintergarde Gryphon Rider', 8, 0); + +DELETE FROM `spell_script_names` WHERE `spell_id` IN (49261, 49259) AND `ScriptName` = 'spell_gen_eject_passenger'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(49261, 'spell_gen_eject_passenger'), +(49259, 'spell_gen_eject_passenger'); + +-- Conquest Hold Windrager SAI +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 28063; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 28063); +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 +(28063, 0, 0, 1, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 80, 2806300, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Conquest Hold Windrager - On Just Summoned - Run Script'), +(28063, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Conquest Hold Windrager - On Just Summoned - Stop Attacking'); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 2806300); +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 +(2806300, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Conquest Hold Windrager - Actionlist - Say Line 0'), +(2806300, 9, 1, 0, 0, 0, 100, 0, 1000, 3000, 0, 0, 0, 0, 11, 50593, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Conquest Hold Windrager - Actionlist - Cast \'Throw Spear\''), +(2806300, 9, 2, 0, 0, 0, 100, 0, 1000, 3000, 0, 0, 0, 0, 11, 50593, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Conquest Hold Windrager - Actionlist - Cast \'Throw Spear\''), +(2806300, 9, 3, 0, 0, 0, 100, 0, 1000, 3000, 0, 0, 0, 0, 11, 50593, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Conquest Hold Windrager - Actionlist - Cast \'Throw Spear\''), +(2806300, 9, 4, 0, 0, 0, 100, 0, 13000, 16000, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Conquest Hold Windrager - Actionlist - Despawn Instant'); + +DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 13) AND (`SourceGroup` = 1) AND (`SourceEntry` = 50592) AND (`SourceId` = 0) AND (`ElseGroup` = 0) AND (`ConditionTypeOrReference` = 31) AND (`ConditionTarget` = 0) AND (`ConditionValue1` = 3) AND (`ConditionValue2` = 28061) AND (`ConditionValue3` = 0); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13, 1, 50592, 0, 0, 31, 0, 3, 28061, 0, 0, 0, 0, '', 'Group 0: Spell \'Throw Spear\' (Effect 1) targets creature \'Wintergarde Gryphon\''); + +DELETE FROM `creature_text` WHERE `CreatureID` IN (28065, 28063); +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(28063, 0, 0, 'INTRUDERS! KILL THEM!', 12, 1, 100, 0, 0, 0, 27473, 0, 'Conquest Hold Windrager'), +(28063, 0, 1, 'ALLIANCE FILTH! DIE! DIE!', 12, 1, 100, 0, 0, 0, 27474, 0, 'Conquest Hold Windrager'), +(28063, 0, 2, 'Take their heads! For the Horde!', 12, 1, 100, 0, 0, 0, 27475, 0, 'Conquest Hold Windrager'), +(28065, 0, 0, 'I\'ll have you at Amberpine Lodge in no time, ally! We just have to make one brief stop first...', 12, 7, 100, 0, 0, 0, 27440, 0, 'Wintergarde Gryphon Rider'), +(28065, 1, 0, 'We\'re gonna do a quick fly by Conquest Hold to see what those filthy, no good, Horde are up to. Keep your eyes peeled for their wind riders. Not that they\'d ever catch me!', 12, 7, 100, 0, 0, 0, 27442, 0, 'Wintergarde Gryphon Rider'), +(28065, 2, 0, 'What in the name of Bronzebeard is goin\' on here? Look at this place! I think...', 12, 7, 100, 0, 0, 0, 27443, 0, 'Wintergarde Gryphon Rider'), +(28065, 3, 0, 'Uh-oh. We\'ve got company! HOLD ON TIGHT! I\'m gonna try and lose \'em!', 12, 7, 100, 0, 0, 0, 27444, 0, 'Wintergarde Gryphon Rider'), +(28065, 4, 0, 'I think we lost \'em! That was a close one! Welp, as promised, Amberpine Lodge in one piece! Keep your feet on the ground, friend!', 12, 7, 100, 0, 0, 0, 27472, 0, 'Wintergarde Gryphon Rider'); + +-- Spell 50557 specified in npc_spellclick_spells is not a valid vehicle enter aura +UPDATE `npc_spellclick_spells` SET `spell_id` = 46598 WHERE `npc_entry` = 28061 AND `spell_id` = 50557; + +-- 'Flight + Speed' aura +DELETE FROM `creature_template_addon` WHERE (`entry` = 28061); +INSERT INTO `creature_template_addon` (`entry`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) VALUES +(28061, 0, 0, 0, 0, 0, 0, '49303'); diff --git a/data/sql/updates/db_world/2025_11_28_08.sql b/data/sql/updates/db_world/2025_11_28_08.sql new file mode 100644 index 000000000..cc5800b56 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_28_08.sql @@ -0,0 +1,25 @@ +-- DB update 2025_11_28_07 -> 2025_11_28_08 +-- +SET @CGUID := 20861; +DELETE FROM `creature` WHERE (`id1` = 31881) AND (`guid` = @CGUID); +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`, `Comment`, `VerifiedBuild`) VALUES +(@CGUID, 31881, 0, 0, 571, 0, 0, 1, 1, 0, 7505.81, 1707.04, 350.194, 1.53589, 300, 0, 0, 63000, 0, 0, 0, 0, 0, '', '', 0); + +UPDATE `creature_template` SET `ArmorModifier` = 0 WHERE (`entry` = 32227); + +-- Disable Gravity, allows Parachute on exit +DELETE FROM `creature_template_movement` WHERE (`CreatureId` IN (31884, 32227)); +INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`, `Chase`, `Random`, `InteractionPauseTimer`) VALUES +(31884, 0, 0, 1, 0, 0, 0, 0), +(32227, 0, 0, 1, 0, 0, 0, 0); + +DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 18) AND (`SourceGroup` IN (31884, 32227)) AND (`SourceEntry` = 46598) AND (`SourceId` = 0); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(18, 31884, 46598, 0, 0, 9, 0, 13310, 0, 0, 0, 0, 0, '', 'Kor\'kron Suppression Turret requires player to be on quest Assault by Air'), +(18, 32227, 46598, 0, 0, 9, 0, 13309, 0, 0, 0, 0, 0, '', 'Skybreaker Suppression Turret requires player to be on quest Assault by Air'); + +UPDATE `vehicle_template_accessory` SET `summontype`=5 WHERE `entry`=31881 AND `seat_id`=1; +UPDATE `vehicle_template_accessory` SET `summontype`=5 WHERE `entry`=32225 AND `seat_id`=1; + +-- Prevent vehicle and passengers to attack players from the opposite faction +UPDATE `creature_template` SET `unit_flags` = `unit_flags` | 256 WHERE (`entry` IN (32225, 31881, 31882, 31891, 32223, 32225)); diff --git a/data/sql/updates/db_world/2025_11_29_00.sql b/data/sql/updates/db_world/2025_11_29_00.sql new file mode 100644 index 000000000..bc7f24322 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_29_00.sql @@ -0,0 +1,5 @@ +-- DB update 2025_11_28_08 -> 2025_11_29_00 +-- Add creature_text for Eck the Ferocious "grows increasingly crazed" emote +DELETE FROM `creature_text` WHERE `CreatureID` = 29932 AND `GroupID` = 1; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) +VALUES (29932, 1, 0, '%s grows increasingly crazed!', 16, 0, 100, 0, 0, 0, 30727, 0, 'Eck the Ferocious - Crazed Warning'); diff --git a/data/sql/updates/db_world/2025_11_29_01.sql b/data/sql/updates/db_world/2025_11_29_01.sql new file mode 100644 index 000000000..54434ca27 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_29_01.sql @@ -0,0 +1,8 @@ +-- DB update 2025_11_29_00 -> 2025_11_29_01 +-- +SET @REPTRASH := 1; +SET @REPREGULAR := 18; +SET @REPBOSS := 275; +UPDATE `creature_onkill_reputation` SET `RewOnKillRepValue1` = @REPTRASH, `RewOnKillRepValue2` = @REPTRASH WHERE `creature_id` IN (30902, 30903); +UPDATE `creature_onkill_reputation` SET `RewOnKillRepValue1` = @REPREGULAR, `RewOnKillRepValue2` = @REPREGULAR WHERE `creature_id` IN (30901, 30904, 30905, 30915, 30916, 30906, 30913, 30907, 30908, 30909, 30910, 30911, 30912, 30914); +UPDATE `creature_onkill_reputation` SET `RewOnKillRepValue1` = @REPBOSS, `RewOnKillRepValue2` = @REPBOSS WHERE `creature_id` IN (31558, 31559, 31560, 31561); diff --git a/data/sql/updates/db_world/2025_11_29_02.sql b/data/sql/updates/db_world/2025_11_29_02.sql new file mode 100644 index 000000000..c4da8275c --- /dev/null +++ b/data/sql/updates/db_world/2025_11_29_02.sql @@ -0,0 +1,5 @@ +-- DB update 2025_11_29_01 -> 2025_11_29_02 +-- +UPDATE `quest_template` SET `RewardNextQuest` = 0 WHERE (`ID` = 11287); +UPDATE `quest_template_addon` SET `NextQuestID` = 0 WHERE (`ID` = 11287); +UPDATE `quest_template_addon` SET `ExclusiveGroup` = 11287 WHERE `ID` IN (11287, 11286); diff --git a/data/sql/updates/db_world/2025_11_29_03.sql b/data/sql/updates/db_world/2025_11_29_03.sql new file mode 100644 index 000000000..f11598497 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_29_03.sql @@ -0,0 +1,3 @@ +-- DB update 2025_11_29_02 -> 2025_11_29_03 +UPDATE `quest_template_addon` SET `PrevQuestID` = 13348 WHERE `ID` = 13359; +UPDATE `quest_template_addon` SET `PrevQuestID` = 13396 WHERE `ID` = 13398; diff --git a/data/sql/updates/db_world/2025_11_30_00.sql b/data/sql/updates/db_world/2025_11_30_00.sql new file mode 100644 index 000000000..2c17d4fd5 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_30_00.sql @@ -0,0 +1,8 @@ +-- DB update 2025_11_29_03 -> 2025_11_30_00 +-- +DELETE FROM `smart_scripts` WHERE `entryorguid` = 1889 AND `source_type` = 0 AND `id` IN (0, 1, 2, 3); +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 +(1889, 0, 0, 0, 1, 0, 100, 0, 1000, 1000, 1000, 1000, 0, 0, 11, 12544, 32, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Dalaran Wizard - Out of Combat - Cast \'Frost Armor\''), +(1889, 0, 1, 0, 0, 0, 100, 0, 0, 0, 3400, 5400, 0, 0, 11, 20792, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Dalaran Wizard - In Combat - Cast \'Frostbolt\''), +(1889, 0, 2, 0, 106, 0, 100, 0, 12500, 45000, 15000, 45000, 0, 10, 11, 11831, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Dalaran Wizard - On Hostile in Range - Cast \'Frost Nova\''), +(1889, 0, 3, 0, 0, 0, 100, 1, 3000, 5000, 14000, 20000, 0, 0, 11, 4980, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Dalaran Wizard - In Combat - Cast \'Quick Frost Ward\' (No Repeat)'); diff --git a/data/sql/updates/db_world/2025_11_30_01.sql b/data/sql/updates/db_world/2025_11_30_01.sql new file mode 100644 index 000000000..1d3b99511 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_30_01.sql @@ -0,0 +1,3 @@ +-- DB update 2025_11_30_00 -> 2025_11_30_01 +-- Burning to Help doesn't require Sharpening Your Talons +UPDATE `quest_template_addon` SET `PrevQuestID` = 0 WHERE `ID` = 12683; diff --git a/data/sql/updates/db_world/2025_11_30_02.sql b/data/sql/updates/db_world/2025_11_30_02.sql new file mode 100644 index 000000000..86ab76094 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_30_02.sql @@ -0,0 +1,6 @@ +-- DB update 2025_11_30_01 -> 2025_11_30_02 + +-- Event occours only if a player dismount. +DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 22) AND (`SourceGroup` = 6) AND (`SourceEntry` = 27587) AND (`SourceId` = 0) AND (`ElseGroup` = 0) AND (`ConditionTypeOrReference` = 32) AND (`ConditionTarget` = 0) AND (`ConditionValue1` = 16) AND (`ConditionValue2` = 0) AND (`ConditionValue3` = 0); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(22, 6, 27587, 0, 0, 32, 0, 16, 0, 0, 0, 0, 0, '', 'Event occours only if a player dismount.'); diff --git a/data/sql/updates/db_world/2025_11_30_03.sql b/data/sql/updates/db_world/2025_11_30_03.sql new file mode 100644 index 000000000..a59af9056 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_30_03.sql @@ -0,0 +1,8 @@ +-- DB update 2025_11_30_02 -> 2025_11_30_03 + +-- Add SmartAI +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 26523; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 26523); +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 +(26523, 0, 0, 0, 28, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 6000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Forsaken Blight Spreader - On Passenger Removed - Despawn In 6000 ms'); diff --git a/data/sql/updates/db_world/2025_11_30_04.sql b/data/sql/updates/db_world/2025_11_30_04.sql new file mode 100644 index 000000000..f2462e699 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_30_04.sql @@ -0,0 +1,4 @@ +-- DB update 2025_11_30_03 -> 2025_11_30_04 +-- +UPDATE `creature_template` SET `lootid` = 29605 WHERE `entry` = 30291; +DELETE FROM `creature_loot_template` WHERE `Entry` = 30291; diff --git a/data/sql/updates/db_world/2025_11_30_05.sql b/data/sql/updates/db_world/2025_11_30_05.sql new file mode 100644 index 000000000..a8f253915 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_30_05.sql @@ -0,0 +1,4 @@ +-- DB update 2025_11_30_04 -> 2025_11_30_05 +-- +-- Remove the RewardNextQuest, previously: 12070 (Rallying the Troops), link from 12249 (Ursoc, the Bear God) +UPDATE `quest_template` SET `RewardNextQuest` = 0 WHERE (`ID` = 12249); diff --git a/data/sql/updates/db_world/2025_11_30_06.sql b/data/sql/updates/db_world/2025_11_30_06.sql new file mode 100644 index 000000000..83b9493be --- /dev/null +++ b/data/sql/updates/db_world/2025_11_30_06.sql @@ -0,0 +1,8 @@ +-- DB update 2025_11_30_05 -> 2025_11_30_06 +-- +-- Judgment Day Comes! should not be available if Honor Above All Else is taken/complete/rewarded +-- Uses CONDITION_QUESTSTATE (47) with state_mask 74 (2+8+64 = Completed+InProgress+Rewarded) +DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 19) AND (`SourceEntry` IN (13226, 13227)) AND (`ConditionTypeOrReference` = 47) AND (`ConditionValue1` = 13036); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(19, 0, 13226, 0, 0, 47, 0, 13036, 74, 0, 1, 0, 0, '', 'Judgment Day Comes! - NOT have Honor Above All Else (taken/complete/rewarded)'), +(19, 0, 13227, 0, 0, 47, 0, 13036, 74, 0, 1, 0, 0, '', 'Judgment Day Comes! - NOT have Honor Above All Else (taken/complete/rewarded)'); diff --git a/data/sql/updates/db_world/2025_11_30_07.sql b/data/sql/updates/db_world/2025_11_30_07.sql new file mode 100644 index 000000000..fa6fe98c3 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_30_07.sql @@ -0,0 +1,90 @@ +-- DB update 2025_11_30_06 -> 2025_11_30_07 +-- +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=-43351 AND `spell_effect`=50167 AND `type`=0; + +DELETE FROM `spell_script_names` WHERE (`spell_id` = 43365 AND `ScriptName` = 'spell_the_cleansing_shrine_cast'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 43351 AND (`ScriptName` = 'spell_the_cleansing_cleansing_soul' OR `ScriptName` = 'spell_q11322_q11317_the_cleansing')); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 50217 AND `ScriptName` = 'spell_the_cleansing_mirror_image_script_effect'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 50238 AND `ScriptName` = 'spell_the_cleansing_on_death_cast_on_master'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 39823 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 39825 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 40201 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 40203 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 40204 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 40205 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 40206 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 40207 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 40208 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 40210 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 40213 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 40217 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 40218 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 40233 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 40252 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 40352 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 50014 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 50023 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 50219 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 50221 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 50222 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 50223 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 53374 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 60807 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +DELETE FROM `spell_script_names` WHERE (`spell_id` = 60811 AND `ScriptName` = 'spell_gen_whisper_to_controller'); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(43365, 'spell_the_cleansing_shrine_cast'), +(43351, 'spell_the_cleansing_cleansing_soul'), +(50217, 'spell_the_cleansing_mirror_image_script_effect'), +(50238, 'spell_the_cleansing_on_death_cast_on_master'), +(39823, 'spell_gen_whisper_to_controller'), +(39825, 'spell_gen_whisper_to_controller'), +(40201, 'spell_gen_whisper_to_controller'), +(40203, 'spell_gen_whisper_to_controller'), +(40204, 'spell_gen_whisper_to_controller'), +(40205, 'spell_gen_whisper_to_controller'), +(40206, 'spell_gen_whisper_to_controller'), +(40207, 'spell_gen_whisper_to_controller'), +(40208, 'spell_gen_whisper_to_controller'), +(40210, 'spell_gen_whisper_to_controller'), +(40213, 'spell_gen_whisper_to_controller'), +(40217, 'spell_gen_whisper_to_controller'), +(40218, 'spell_gen_whisper_to_controller'), +(40233, 'spell_gen_whisper_to_controller'), +(40252, 'spell_gen_whisper_to_controller'), +(40352, 'spell_gen_whisper_to_controller'), +(50014, 'spell_gen_whisper_to_controller'), +(50023, 'spell_gen_whisper_to_controller'), +(50219, 'spell_gen_whisper_to_controller'), +(50221, 'spell_gen_whisper_to_controller'), +(50222, 'spell_gen_whisper_to_controller'), +(50223, 'spell_gen_whisper_to_controller'), +(53374, 'spell_gen_whisper_to_controller'), +(60807, 'spell_gen_whisper_to_controller'), +(60811, 'spell_gen_whisper_to_controller'); + +DELETE FROM `creature_text` WHERE `CreatureID` = 27959; + +UPDATE `creature_template` SET `ScriptName` = '', `AIName` = 'SmartAI' WHERE `entry` = 27959; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 27959 AND `source_type` = 0; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 2795900 AND `source_type` = 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`,`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 +(27959, 0, 0, 0, 37, 0, 100, 0, 0, 0, 0, 0, 0, 116, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Your Inner Turmoil - On Initialize - Set Corpse Delay to 2s'), +(27959, 0, 1, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 80, 2795900, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Your Inner Turmoil - On Respawn - Run Script'), +(27959, 0, 2, 0, 2, 0, 100, 1, 0, 50, 0, 0, 0, 11, 50222, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Your Inner Turmoil - Between 0-50% Health - Cast \'The Cleansing: Your Inner Turmoil`s Whisper to Controller - On Health 50%\' (No Repeat)'), +(27959, 0, 3, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 11, 50223, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Your Inner Turmoil - On Just Died - Cast \'The Cleansing: Your Inner Turmoil`s Whisper to Controller - On Death\''), +(27959, 0, 4, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 11, 50238, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Your Inner Turmoil - On Just Died - Cast \'The Cleansing: Your Inner Turmoil`s On Death Cast on Master\''), +-- It has SPELL_ATTR3_DEATH_PERSISTENT but actually is removed after death, maybe not manually +-- Kinda odd because it makes creature invisible, but Copy Weapon auras are not removed, so only weapons are visible without body +(27959, 0, 5, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 28, 50218, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Your Inner Turmoil - On Just Died - Remove Aura \'The Cleansing: Your Inner Turmoil`s Mirror Image Aura\''), +(2795900, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 11, 50217, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 'Your Inner Turmoil - Actionlist - Cast \'The Cleansing: Script Effect Player Cast Mirror Image\''), +(2795900, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 11, 41408, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Your Inner Turmoil - Actionlist - Cast \'Shadowform\''), +(2795900, 9, 2, 0, 0, 0, 100, 0, 1000, 1000, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 'Your Inner Turmoil - Actionlist - Set Orientation Owner Or Summoner'), +(2795900, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 11, 50219, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Your Inner Turmoil - Actionlist - Cast \'The Cleansing: Your Inner Turmoil`s Whisper to Controller - Spawn 01\''), +(2795900, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Your Inner Turmoil - Actionlist - Play Emote 1'), +(2795900, 9, 5, 0, 0, 0, 100, 0, 6000, 6000, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 'Your Inner Turmoil - Actionlist - Set Orientation Owner Or Summoner'), +(2795900, 9, 6, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 11, 50221, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Your Inner Turmoil - Actionlist - Cast \'The Cleansing: Your Inner Turmoil`s Whisper to Controller - Spawn 02\''), +(2795900, 9, 7, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 5, 25, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Your Inner Turmoil - Actionlist - Play Emote 25'), +-- Yes, again +(2795900, 9, 8, 0, 0, 0, 100, 0, 6000, 6000, 0, 0, 0, 11, 50217, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 'Your Inner Turmoil - Actionlist - Cast \'The Cleansing: Script Effect Player Cast Mirror Image\''), +(2795900, 9, 9, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 19, 512, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Your Inner Turmoil - Actionlist - Remove Flags Immune To NPC\'s'), +(2795900, 9, 10, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 'Your Inner Turmoil - Actionlist - Start Attacking'); diff --git a/data/sql/updates/db_world/2025_11_30_08.sql b/data/sql/updates/db_world/2025_11_30_08.sql new file mode 100644 index 000000000..babbf5e14 --- /dev/null +++ b/data/sql/updates/db_world/2025_11_30_08.sql @@ -0,0 +1,18 @@ +-- DB update 2025_11_30_07 -> 2025_11_30_08 +SET @ITEM = 6995; +SET @ENTRY = 1055; + +-- Creates a reference loot for "Corrupted Kor Gem" +DELETE FROM `reference_loot_template` WHERE `Entry` = @ENTRY AND `Item` = @ITEM; +INSERT INTO `reference_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(@ENTRY, @ITEM, 0, 100, 1, 1, 1, 1, 1, 'Corrupted Kor Gem'); + +-- Deletes "Corrupted Kor Gem" from every creature's loot +DELETE FROM `creature_loot_template` WHERE `item` = @ITEM; + +-- Adds reference loot for "Corrupted Kor Gem" for each creature below +DELETE FROM `creature_loot_template` WHERE `Reference` = @ENTRY AND `Entry` IN (4802, 4803, 4805); +INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(4802, @ITEM, @ENTRY, 80, 0, 1, 0, 1, 1, 'Blackfathom Tide Priestess - Corrupted Kor Gem'), +(4803, @ITEM, @ENTRY, 80, 0, 1, 0, 1, 1, 'Blackfathom Oracle - Corrupted Kor Gem'), +(4805, @ITEM, @ENTRY, 80, 0, 1, 0, 1, 1, 'Blackfathom Sea Witch - Corrupted Kor Gem'); diff --git a/data/sql/updates/db_world/2025_12_01_00.sql b/data/sql/updates/db_world/2025_12_01_00.sql new file mode 100644 index 000000000..cdc6629f0 --- /dev/null +++ b/data/sql/updates/db_world/2025_12_01_00.sql @@ -0,0 +1,3 @@ +-- DB update 2025_11_30_08 -> 2025_12_01_00 +-- +UPDATE `spell_group_stack_rules` SET `stack_rule` = 1 WHERE `group_id` = 1087; diff --git a/data/sql/updates/db_world/2025_12_01_01.sql b/data/sql/updates/db_world/2025_12_01_01.sql new file mode 100644 index 000000000..cdbff3fc4 --- /dev/null +++ b/data/sql/updates/db_world/2025_12_01_01.sql @@ -0,0 +1,124 @@ +-- DB update 2025_12_01_00 -> 2025_12_01_01 +-- +SET @CGUID:=126834; + +-- Remove old '[DND]' bunnies +DELETE FROM `creature` WHERE `id1` IN (30655, 30640, 30832, 30646, 30651, 30707, 30649, 30749, 30700, 30699, 30690, 31246, 31353, 30589, 30588, 30476, 30559); +DELETE FROM `creature` WHERE `id1` = 15214 AND `guid` IN (122568, 122569, 122570); +DELETE FROM `creature` WHERE `guid` BETWEEN @CGUID+0 AND @CGUID+29; +INSERT INTO `creature` (`guid`, `id1`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `MovementType`) VALUES +(@CGUID+0, 30640, 623, 1, 1, 35.03846, 36.06336, 25.11708, 5.288348, 120, 0, 0), -- 30640 (Area: 4508) (possible waypoints or random movement) +(@CGUID+1, 30640, 623, 1, 1, 6.909693, 9.529325, 20.54005, 2.303835, 120, 0, 0), -- 30640 (Area: 4508) (possible waypoints or random movement) +(@CGUID+2, 30640, 623, 1, 1, -27.16368, 2.981263, 20.54094, 0.122173, 120, 0, 0), -- 30640 (Area: 4508) (possible waypoints or random movement) +(@CGUID+3, 30640, 623, 1, 1, -56.31194, 12.39219, 31.00466, 3.281219, 120, 0, 0), -- 30640 (Area: 4537) (possible waypoints or random movement) +(@CGUID+4, 30646, 623, 1, 1, -30.25571, 31.80029, 12.35424, 1.605703, 120, 0, 0), -- 30646 (Area: 4508) (possible waypoints or random movement) +(@CGUID+5, 30646, 623, 1, 1, -5.325279, 31.62501, 12.34004, 1.500983, 120, 0, 0), -- 30646 (Area: 4508) (possible waypoints or random movement) +(@CGUID+6, 30651, 623, 1, 1, -40.68238, 29.21558, 12.33503, 1.919862, 120, 0, 0), -- 30651 (Area: 4508) (possible waypoints or random movement) +(@CGUID+7, 30651, 623, 1, 1, -17.81335, 32.07878, 12.3449, 1.553343, 120, 0, 0), -- 30651 (Area: 4508) (possible waypoints or random movement) +(@CGUID+8, 30651, 623, 1, 1, 5.88316, 30.50419, 12.34755, 1.32645, 120, 0, 0), -- 30651 (Area: 4508) (possible waypoints or random movement) +(@CGUID+9, 30655, 623, 1, 1, 6.662919, 19.23895, 10.05156, 0.5061455, 120, 0, 0), -- 30655 (Area: 4509) +(@CGUID+10, 30655, 623, 1, 1, -43.53964, 18.66365, 9.692578, 3.246312, 120, 0, 0), -- 30655 (Area: 4509) (possible waypoints or random movement) +(@CGUID+11, 30559, 623, 1, 1, 38.16154, -0.040522, 40.16801, 4.223697, 120, 0, 0), -- 30559 (Area: 4508) (possible waypoints or random movement) +(@CGUID+12, 30476, 623, 1, 1, 31.41805, 0.126893, 41.69821, 0.05235988, 120, 0, 0), -- 30476 (Area: 4508) (Auras: 56852 - 56852) (possible waypoints or random movement) +(@CGUID+13, 31353, 623, 1, 1, -21.7234, 19.33753, 9.687197, 1.64061, 120, 0, 0), -- 31353 (Area: 4509) (Auras: 57726 - 57726) +(@CGUID+14, 30690, 622, 1, 1, 15.24723, 32.37709, 10.63188, 1.553343, 120, 0, 0), -- 30690 (Area: 4533) (possible waypoints or random movement) +(@CGUID+15, 30690, 622, 1, 1, -11.22309, 32.91199, 10.55865, 1.58825, 120, 0, 0), -- 30690 (Area: 4533) (possible waypoints or random movement) +(@CGUID+16, 30649, 622, 1, 1, 4.109683, 19.52689, 34.74765, 3.752458, 120, 0, 0), -- 30649 (Area: 4533) (possible waypoints or random movement) +(@CGUID+17, 30649, 622, 1, 1, -32.53434, 24.30232, 33.9708, 3.211406, 120, 0, 0), -- 30649 (Area: 4533) (possible waypoints or random movement) +(@CGUID+18, 30649, 622, 1, 1, 50.99569, 46.95655, 23.41373, 2.583087, 120, 0, 0), -- 30649 (Area: 4533) (possible waypoints or random movement) +(@CGUID+19, 30649, 622, 1, 1, 2.006737, 15.73845, 9.250069, 3.368485, 120, 0, 0), -- 30649 (Area: 4533) (possible waypoints or random movement) +(@CGUID+20, 30699, 622, 1, 1, 1.853844, 32.8888, 10.02361, 1.58825, 120, 0, 0), -- 30699 (Area: 4533) (possible waypoints or random movement) +(@CGUID+21, 30700, 622, 1, 1, -35.66628, 29.43331, 1.87925, 1.745329, 120, 0, 0), -- 30700 (Area: 0) (possible waypoints or random movement) +(@CGUID+22, 30700, 622, 1, 1, 7.417077, 32.82674, 38.35604, 1.553343, 120, 0, 0), -- 30700 (Area: 0) (possible waypoints or random movement) +(@CGUID+23, 30700, 622, 1, 1, -55.9708, 28.44186, 18.02501, 2.268928, 120, 0, 0), -- 30700 (Area: 0) (possible waypoints or random movement) +(@CGUID+24, 30700, 622, 1, 1, 38.76255, 30.09343, 2.308181, 1.134464, 120, 0, 0), -- 30700 (Area: 4533) (possible waypoints or random movement) +(@CGUID+25, 30707, 622, 1, 1, 19.47087, 27.5296, 10.64527, 1.396263, 120, 0, 0), -- 30707 (Area: 4533) (possible waypoints or random movement) +(@CGUID+26, 30707, 622, 1, 1, -15.3085, 30.59285, 11.11614, 2.635447, 120, 0, 0), -- 30707 (Area: 0) (possible waypoints or random movement) +(@CGUID+27, 31353, 622, 1, 1, -7.999845, 17.85185, 35.04856, 2.460914, 120, 0, 0), -- 31353 (Area: 0) (possible waypoints or random movement) +(@CGUID+28, 30588, 622, 1, 1, -18.10283, -0.042108, 45.31725, 1.762783, 120, 0, 0), -- 30588 (Area: 4533) (Auras: 57424 - 57424) (possible waypoints or random movement) +(@CGUID+29, 30589, 622, 1, 1, -11.83204, -0.019289, 43.11467, 4.153883, 120, 0, 0); -- 30589 (Area: 4533) (possible waypoints or random movement) + +UPDATE `creature_template` SET `flags_extra`= `flags_extra` | 128 WHERE `entry` IN (30690, 30699); + +DELETE FROM `creature_addon` WHERE `guid` IN (122568, 122569, 122758, 122777, 124002, 124113); + +-- Match existing (A) entry, 'To Icecrown - Airship (H) - Aura - Approach' +UPDATE `creature_template_addon` SET `auras` = '57424' WHERE (`entry` = 30588); + +DELETE FROM `creature_template_movement` WHERE (`CreatureId` IN (30476, 30588)); +INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`, `Chase`, `Random`, `InteractionPauseTimer`) VALUES +(30476, 0, 0, 1, 0, 0, 0, 0), +(30588, 0, 0, 1, 0, 0, 0, 0); + +UPDATE `creature_template_addon` SET `auras` = '' WHERE (`entry` IN (30470, 30585)); +DELETE FROM `creature_template_movement` WHERE (`CreatureId` IN (30470, 30585)); +INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`, `Chase`, `Random`, `InteractionPauseTimer`) VALUES +(30470, 0, 0, 1, 0, 0, 0, 0), +(30585, 0, 0, 1, 0, 0, 0, 0); + +-- teleport target condition +DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 13) AND (`SourceGroup` = 1) AND (`SourceEntry` IN (56905, 56917, 57420, 57417)) AND (`SourceId` = 0) AND (`ElseGroup` IN (0, 1)) AND (`ConditionTypeOrReference` = 31) AND (`ConditionTarget` = 0) AND (`ConditionValue1` = 3) AND (`ConditionValue2` IN (30476, 30559, 30588, 30589)) AND (`ConditionValue3` = 0); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13, 1, 56905, 0, 0, 31, 0, 3, 30476, 0, 0, 0, 0, '', 'target must be [DND] Icecrown Flight To Airship Bunny (A)'), +(13, 1, 56917, 0, 0, 31, 0, 3, 30559, 0, 0, 0, 0, '', 'target must be [DND] Icecrown Flight To Airship Bunny (A) Teleport Target'), +(13, 1, 57420, 0, 0, 31, 0, 3, 30588, 0, 0, 0, 0, '', 'target must be [DND] Icecrown Flight To Airship Bunny (H)'), +(13, 1, 57417, 0, 0, 31, 0, 3, 30589, 0, 0, 0, 0, '', 'target must be [DND] Icecrown Flight To Airship Bunny (H) Teleport Target'); + +-- dismount trigger condition +DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 17) AND (`SourceGroup` = 0) AND (`SourceEntry` = 56921) AND (`SourceId` = 0) AND (`ElseGroup` IN (0, 1)) AND (`ConditionTypeOrReference` = 31) AND (`ConditionTarget` = 1) AND (`ConditionValue1` = 3) AND (`ConditionValue2` IN (30470, 30585)) AND (`ConditionValue3` = 0); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(17, 0, 56921, 0, 0, 31, 1, 3, 30470, 0, 0, 0, 0, '', 'target must be Skybreaker Cloudbuster'), +(17, 0, 56921, 0, 1, 31, 1, 3, 30585, 0, 0, 0, 0, '', 'target must be Hammerhead'); + +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` IN (30476, 30588); +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` IN (30476, 30588)); +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 +(30476, 0, 0, 1, 8, 0, 100, 0, 56905, 0, 0, 0, 0, 0, 11, 57554, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '[DND] Icecrown Flight To Airship Bunny (A) - On Spellhit \'To Icecrown - Player - Aura (A) - Dismount Trigger\' - Cast \'To Icecrown Airship - Teleport to Airship (A) Force Player to Cast\''), +(30476, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 56921, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '[DND] Icecrown Flight To Airship Bunny (A) - On Spellhit \'To Icecrown - Player - Aura (A) - Dismount Trigger\' - Cast \'To Icecrown - Aura - Dismount Response\''), +(30588, 0, 0, 1, 8, 0, 100, 0, 57420, 0, 0, 0, 0, 0, 11, 57556, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '[DND] Icecrown Flight To Airship Bunny (H) - On Spellhit \'To Icecrown - Player - Aura (A) - Dismount Trigger\' - Cast \'To Icecrown Airship - Teleport to Airship (H) Force Player to Cast\''), +(30588, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 56921, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '[DND] Icecrown Flight To Airship Bunny (H) - On Spellhit \'To Icecrown - Player - Aura (A) - Dismount Trigger\' - Cast \'To Icecrown - Aura - Dismount Response\''); + +DELETE FROM `waypoints` WHERE `entry` IN (30470, 30585) AND `pointid` BETWEEN 1 AND 18; +INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES +(30470, 1, 5818.54, 483.97, 660.0, 'Skybreaker Cloudbuster'), +(30470, 2, 5810.04, 486.907, 660.167, 'Skybreaker Cloudbuster'), +(30470, 3, 5827.64, 482.851, 669.25, 'Skybreaker Cloudbuster'), +(30470, 4, 5845.60, 505.766, 677.9, 'Skybreaker Cloudbuster'), +(30470, 5, 5865.83, 544.756, 689.667, 'Skybreaker Cloudbuster'), +(30470, 6, 5897.43, 586.118, 689.667, 'Skybreaker Cloudbuster'), +(30470, 7, 5936.38, 642.625, 682.418, 'Skybreaker Cloudbuster'), +(30470, 8, 5954.68, 688.565, 678.141, 'Skybreaker Cloudbuster'), +(30470, 9, 5987.02, 725.128, 673.53, 'Skybreaker Cloudbuster'), +(30470, 10, 6055.09, 766.575, 663.057, 'Skybreaker Cloudbuster'), +(30470, 11, 6077.21, 796.139, 663.057, 'Skybreaker Cloudbuster'), +(30470, 12, 6089.87, 824.184, 658.753, 'Skybreaker Cloudbuster'), +(30470, 13, 6119.88, 881.953, 657.474, 'Skybreaker Cloudbuster'), +(30470, 14, 6187.39, 959.597, 663.057, 'Skybreaker Cloudbuster'), +(30470, 15, 6346.12, 1060.05, 654.669, 'Skybreaker Cloudbuster'), +(30470, 16, 6466.61, 1107.18, 653.78, 'Skybreaker Cloudbuster'), +(30470, 17, 6626.67, 1136.81, 647.084, 'Skybreaker Cloudbuster'), +(30470, 18, 6733.84, 1153.34, 663.057, 'Skybreaker Cloudbuster'), +(30585, 1, 5836.95, 475.408, 660.167, 'Hammerhead'), +(30585, 2, 5835.36, 490.093, 669.25, 'Hammerhead'), +(30585, 3, 5845.6, 505.766, 677.9, 'Hammerhead'), +(30585, 4, 5865.83, 544.756, 689.667, 'Hammerhead'), +(30585, 5, 5897.43, 586.118, 689.667, 'Hammerhead'), +(30585, 6, 5936.38, 642.625, 682.418, 'Hammerhead'), +(30585, 7, 5954.68, 688.565, 678.141, 'Hammerhead'), +(30585, 8, 5987.02, 725.128, 673.53, 'Hammerhead'), +(30585, 9, 6055.09, 766.575, 663.057, 'Hammerhead'), +(30585, 10, 6077.21, 796.139, 663.057, 'Hammerhead'), +(30585, 11, 6089.87, 824.184, 663.057, 'Hammerhead'), +(30585, 12, 6133.36, 911.233, 642.309, 'Hammerhead'), +(30585, 13, 6187.39, 959.597, 625.03, 'Hammerhead'), +(30585, 14, 6346.12, 1060.05, 631.336, 'Hammerhead'), +(30585, 15, 6466.61, 1107.18, 640.891, 'Hammerhead'), +(30585, 16, 6626.67, 1136.81, 639.669, 'Hammerhead'), +(30585, 17, 6733.84, 1153.34, 637.03, 'Hammerhead'), +(30585, 18, 6835.57, 1203.64, 642.974, 'Hammerhead'); + +-- TP To Dalaran after 5 minutes +-- Location copied from 30719 'Teleport to Dalaran' +DELETE FROM `spell_target_position` WHERE `ID` = 57461 AND `EffectIndex` = 0; +INSERT INTO `spell_target_position` (`ID`, `EffectIndex`, `MapID`, `PositionX`, `PositionY`, `PositionZ`, `Orientation`, `VerifiedBuild`) VALUES +(57461, 0, 571, 5807.75, 588.347, 661.505, 1.663, 0); diff --git a/data/sql/updates/db_world/2025_12_01_02.sql b/data/sql/updates/db_world/2025_12_01_02.sql new file mode 100644 index 000000000..5f3db97d5 --- /dev/null +++ b/data/sql/updates/db_world/2025_12_01_02.sql @@ -0,0 +1,4 @@ +-- DB update 2025_12_01_01 -> 2025_12_01_02 + +-- Set HP +UPDATE `creature` SET `curhealth` = 8982 WHERE (`id1` = 26523) AND (`guid` IN (150213, 150214, 150215, 150216, 150217)); diff --git a/data/sql/updates/db_world/2025_12_01_03.sql b/data/sql/updates/db_world/2025_12_01_03.sql new file mode 100644 index 000000000..1ac4d11d6 --- /dev/null +++ b/data/sql/updates/db_world/2025_12_01_03.sql @@ -0,0 +1,5 @@ +-- DB update 2025_12_01_02 -> 2025_12_01_03 +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 13 AND `SourceEntry` = 52457; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13, 1, 52457, 0, 0, 31, 0, 3, 26797, 0, 0, 0, 0, '', 'Spell 52457 (Drak\'aguul\'s Soldiers) - Target Drakkari Protector'), +(13, 1, 52457, 0, 1, 31, 0, 3, 26795, 0, 0, 0, 0, '', 'Spell 52457 (Drak\'aguul\'s Soldiers) - Target Drakkari Oracle'); diff --git a/data/sql/updates/db_world/2025_12_01_04.sql b/data/sql/updates/db_world/2025_12_01_04.sql new file mode 100644 index 000000000..a4c5268e0 --- /dev/null +++ b/data/sql/updates/db_world/2025_12_01_04.sql @@ -0,0 +1,43 @@ +-- DB update 2025_12_01_03 -> 2025_12_01_04 +-- Update gameobject 'Kaskala Supplies' with sniffed values +-- updated spawns +DELETE FROM `gameobject` WHERE (`id` IN (188164)) AND (`guid` IN (21196, 21198, 21199, 21200, 21201, 55049, 55050, 55053, 55054, 55055, 55056, 55062, 55063, 55064, 55065, 55066, 55067, 55068, 55069, 55070, 55071, 55072, 55073, 55074, 55075, 55076)); +INSERT INTO `gameobject` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`, `ScriptName`, `VerifiedBuild`, `Comment`) VALUES +(21196, 188164, 571, 0, 0, 1, 1, 3090.959716796875, 4834.1533203125, 1.773596048355102539, 4.258606910705566406, 0, 0, -0.84804725646972656, 0.529920578002929687, 300, 255, 1, "", 46368, NULL), +(21198, 188164, 571, 0, 0, 1, 1, 2852.42529296875, 4359.61181640625, 2.469172000885009765, 3.45575571060180664, 0, 0, -0.98768806457519531, 0.156436234712600708, 300, 255, 1, "", 45854, NULL), +(21199, 188164, 571, 0, 0, 1, 1, 2861.06689453125, 4320.09130859375, 1.672091960906982421, 4.258606910705566406, 0, 0, -0.84804725646972656, 0.529920578002929687, 300, 255, 1, "", 45854, NULL), +(21200, 188164, 571, 0, 0, 1, 1, 2903.911376953125, 4342.56689453125, 3.770941972732543945, 1.884953022003173828, 0, 0, 0.809016227722167968, 0.587786316871643066, 300, 255, 1, "", 45854, NULL), +(21201, 188164, 571, 0, 0, 1, 1, 2920.125732421875, 4348.05224609375, 4.131337165832519531, 2.827429771423339843, 0, 0, 0.987688064575195312, 0.156436234712600708, 300, 255, 1, "", 45854, NULL), +(55049, 188164, 571, 0, 0, 1, 1, 2971.307861328125, 4833.74755859375, 0.396221011877059936, 0.872663915157318115, 0, 0, 0.422617912292480468, 0.906307935714721679, 300, 255, 1, "", 45854, NULL), +(55050, 188164, 571, 0, 0, 1, 1, 3021.4794921875, 4658.08935546875, 0.396221011877059936, 3.822272777557373046, 0, 0, -0.94264125823974609, 0.333807557821273803, 300, 255, 1, "", 46158, NULL), +(55053, 188164, 571, 0, 0, 1, 1, 3026.746826171875, 4698.53955078125, 0.396218985319137573, 5.864306926727294921, 0, 0, -0.20791149139404296, 0.978147625923156738, 300, 255, 1, "", 46158, NULL), +(55054, 188164, 571, 0, 0, 1, 1, 2988.111572265625, 4615.74853515625, 0.39622199535369873, 4.607671737670898437, 0, 0, -0.74314403533935546, 0.669131457805633544, 300, 255, 1, "", 46158, NULL), +(55055, 188164, 571, 0, 0, 1, 1, 2999.525634765625, 4844.74462890625, 0.396218985319137573, 0.104719325900077819, 0, 0, 0.052335739135742187, 0.998629570007324218, 300, 255, 1, "", 45854, NULL), +(55056, 188164, 571, 0, 0, 1, 1, 3092.693115234375, 4880.60107421875, 0.396218985319137573, 4.48549652099609375, 0, 0, -0.7826080322265625, 0.622514784336090087, 300, 255, 1, "", 46158, NULL), +(55062, 188164, 571, 0, 0, 1, 1, 2877.409423828125, 4866.79833984375, 0.396219998598098754, 4.520402908325195312, 0, 0, -0.77162456512451171, 0.636078238487243652, 300, 255, 1, "", 46158, NULL), +(55063, 188164, 571, 0, 0, 1, 1, 3021.50048828125, 4881.67431640625, 0.396218985319137573, 3.961898565292358398, 0, 0, -0.91705989837646484, 0.398749500513076782, 300, 255, 1, "", 45854, NULL), +(55064, 188164, 571, 0, 0, 1, 1, 2923.610595703125, 4830.14697265625, 0.396219998598098754, 6.09120035171508789, 0, 0, -0.09584522247314453, 0.995396256446838378, 300, 255, 1, "", 45854, NULL), +(55065, 188164, 571, 0, 0, 1, 1, 3123.70458984375, 4742.7275390625, 7.44305276870727539, 3.071766138076782226, 0, 0, 0.999390602111816406, 0.034906134009361267, 300, 255, 1, "", 46158, NULL), +(55066, 188164, 571, 0, 0, 1, 1, 2890.171875, 4936.33447265625, 1.871719002723693847, 4.345870018005371093, 0, 0, -0.82412624359130859, 0.566406130790710449, 300, 255, 1, "", 45854, NULL), +(55067, 188164, 571, 0, 0, 1, 1, 2969.289794921875, 4851.22705078125, 0.408302009105682373, 1.745326757431030273, 0, 0, 0.766043663024902343, 0.642788589000701904, 300, 255, 1, "", 45854, NULL), +(55068, 188164, 571, 0, 0, 1, 1, 2879.10107421875, 4905.57763671875, 2.53964996337890625, 3.595378875732421875, 0, 0, -0.97437000274658203, 0.224951311945915222, 300, 255, 1, "", 45854, NULL), +(55069, 188164, 571, 0, 0, 1, 1, 2918.706298828125, 4889.00537109375, 2.560297966003417968, 0.907570242881774902, 0, 0, 0.438370704650878906, 0.898794233798980712, 300, 255, 1, "", 45854, NULL), +(55070, 188164, 571, 0, 0, 1, 1, 3083.975830078125, 4848.85400390625, 3.177611112594604492, 0.575957298278808593, 0, 0, 0.284014701843261718, 0.958819925785064697, 300, 255, 1, "", 45854, NULL), +(55071, 188164, 571, 0, 0, 1, 1, 3027.964599609375, 4724.9462890625, 0.396210014820098876, 6.230826377868652343, 0, 0, -0.02617645263671875, 0.999657332897186279, 300, 255, 1, "", 46158, NULL), +(55072, 188164, 571, 0, 0, 1, 1, 3099.82373046875, 4804.06005859375, 1.220486998558044433, 1.308995485305786132, 0, 0, 0.608760833740234375, 0.793353796005249023, 300, 255, 1, "", 46158, NULL), +(55073, 188164, 571, 0, 0, 1, 1, 3056.2587890625, 4769.31591796875, 1.679136037826538085, 2.548179388046264648, 0, 0, 0.956304550170898437, 0.292372345924377441, 300, 255, 1, "", 46368, NULL), +(55074, 188164, 571, 0, 0, 1, 1, 3133.72998046875, 4752.50341796875, 8.12195587158203125, 5.969027042388916015, 0, 0, -0.1564340591430664, 0.987688362598419189, 300, 255, 1, "", 46158, NULL), +(55075, 188164, 571, 0, 0, 1, 1, 3051.9287109375, 4808.58056640625, 2.0370330810546875, 0.820303261280059814, 0, 0, 0.398748397827148437, 0.917060375213623046, 300, 255, 1, "", 45854, NULL), +(55076, 188164, 571, 0, 0, 1, 1, 3035.663818359375, 4777.59912109375, 0.396205991506576538, 3.874631166458129882, 0, 0, -0.93358039855957031, 0.358368009328842163, 300, 255, 1, "", 46368, NULL); + +-- new spawns +DELETE FROM `gameobject` WHERE (`id` IN (188164)) AND (`guid` IN (582, 583, 584, 585, 586, 587, 588, 589)); +INSERT INTO `gameobject` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`, `ScriptName`, `VerifiedBuild`, `Comment`) VALUES +(582, 188164, 571, 0, 0, 1, 1, 2913.260498046875, 4930.26806640625, 2.561732053756713867, 3.45575571060180664, 0, 0, -0.98768806457519531, 0.156436234712600708, 300, 255, 1, "", 46158, NULL), +(583, 188164, 571, 0, 0, 1, 1, 2991.869384765625, 4628.22216796875, 0.396219998598098754, 5.672322273254394531, 0, 0, -0.3007049560546875, 0.953717231750488281, 300, 255, 1, "", 46158, NULL), +(584, 188164, 571, 0, 0, 1, 1, 3058.022705078125, 4826.490234375, 1.375823974609375, 1.85004889965057373, 0, 0, 0.798635482788085937, 0.60181504487991333, 300, 255, 1, "", 45854, NULL), +(585, 188164, 571, 0, 0, 1, 1, 3060.99365234375, 4765.1005859375, 1.134042024612426757, 4.537858963012695312, 0, 0, -0.76604366302490234, 0.642788589000701904, 300, 255, 1, "", 46158, NULL), +(586, 188164, 571, 0, 0, 1, 1, 3075.670654296875, 4824.07275390625, 1.220486044883728027, 1.884953022003173828, 0, 0, 0.809016227722167968, 0.587786316871643066, 300, 255, 1, "", 48632, NULL), +(587, 188164, 571, 0, 0, 1, 1, 3094.1884765625, 4792.8369140625, 1.994282007217407226, 1.274088263511657714, 0, 0, 0.594821929931640625, 0.80385744571685791, 300, 255, 1, "", 45854, NULL), +(588, 188164, 571, 0, 0, 1, 1, 3109.00830078125, 4778.85791015625, 6.534741878509521484, 3.211419343948364257, 0, 0, -0.9993906021118164, 0.034906134009361267, 300, 255, 1, "", 46158, NULL), +(589, 188164, 571, 0, 0, 1, 1, 3122.1181640625, 4826.61669921875, 1.442281007766723632, 0.471238493919372558, 0, 0, 0.233445167541503906, 0.972369968891143798, 300, 255, 1, "", 46158, NULL); diff --git a/data/sql/updates/db_world/2025_12_01_05.sql b/data/sql/updates/db_world/2025_12_01_05.sql new file mode 100644 index 000000000..81ce9a5ad --- /dev/null +++ b/data/sql/updates/db_world/2025_12_01_05.sql @@ -0,0 +1,9 @@ +-- DB update 2025_12_01_04 -> 2025_12_01_05 +-- +-- Wolfsbane Root (189313) - Despawn on use via SmartAI +-- Closes https://github.com/azerothcore/azerothcore-wotlk/issues/23904 +UPDATE `gameobject_template` SET `AIName` = 'SmartGameObjectAI' WHERE `entry` = 189313; + +DELETE FROM `smart_scripts` WHERE `entryorguid` = 189313 AND `source_type` = 1; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(189313, 1, 0, 0, 70, 0, 100, 0, 2, 0, 0, 0, 0, 0, 41, 1000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Wolfsbane Root - On State Changed - Despawn'); diff --git a/data/sql/updates/db_world/2025_12_02_00.sql b/data/sql/updates/db_world/2025_12_02_00.sql new file mode 100644 index 000000000..ca9e7aea3 --- /dev/null +++ b/data/sql/updates/db_world/2025_12_02_00.sql @@ -0,0 +1,4 @@ +-- DB update 2025_12_01_05 -> 2025_12_02_00 + +-- Remove double spawn point +DELETE FROM `creature` WHERE (`id1` = 32250) AND (`guid` IN (125031)); diff --git a/data/sql/updates/db_world/2025_12_02_01.sql b/data/sql/updates/db_world/2025_12_02_01.sql new file mode 100644 index 000000000..63705b3fc --- /dev/null +++ b/data/sql/updates/db_world/2025_12_02_01.sql @@ -0,0 +1,38 @@ +-- DB update 2025_12_02_00 -> 2025_12_02_01 +-- +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 29796) AND (`source_type` = 0) AND (`id` IN (0)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(29796, 0, 0, 0, 19, 0, 100, 0, 12886, 0, 0, 0, 0, 0, 11, 55253, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Gretta the Arbiter - On Quest \'The Drakkensryd\' Taken - Cast \'Force Cast Initial Proto-Drake\''); + +UPDATE `creature_template` SET `speed_run` = 3.2 WHERE (`entry` = 29679); + +-- 55971 Eagle Flight +UPDATE `creature_template_addon` SET `auras` = '55971' WHERE (`entry` = 29679); + +-- Update comments, Exit vehicle on death +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 29694) AND (`source_type` = 0) AND (`id` IN (0, 1, 2)); +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 +(29694, 0, 0, 0, 0, 0, 100, 0, 2000, 5000, 5000, 9000, 0, 0, 11, 32736, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Hyldsmeet Drakerider - In Combat - Cast \'Mortal Strike\''), +(29694, 0, 1, 2, 6, 0, 100, 512, 0, 0, 0, 0, 0, 0, 33, 29800, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Hyldsmeet Drakerider - On Just Died - Quest Credit \'null\''), +(29694, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Hyldsmeet Drakerider - On Just Died - Exit vehicle'); + +-- Hyldsmeet Drakerider eject NPC passenger vertically +DELETE FROM `vehicle_seat_addon` WHERE (`SeatEntry` = 2101); +INSERT INTO `vehicle_seat_addon` (`SeatEntry`, `SeatOrientation`, `ExitParamX`, `ExitParamY`, `ExitParamZ`, `ExitParamO`, `ExitParamValue`) VALUES +(2101, 0, 0, 0, 4, 0, 1); + +-- Update Comments, Reduce despawn time from 2s to 1s +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 29679) AND (`source_type` = 0) AND (`id` IN (0, 1, 2)); +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 +(29679, 0, 0, 0, 60, 0, 100, 513, 1000, 1000, 0, 0, 0, 0, 53, 2, 29679, 0, 0, 1000, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Hyldsmeet Proto-Drake - On Update - Start Waypoint Path 29679 (No Repeat)'), +(29679, 0, 1, 0, 60, 0, 100, 513, 500, 500, 0, 0, 0, 0, 60, 1, 500, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Hyldsmeet Proto-Drake - On Update - Set Fly On (No Repeat)'), +(29679, 0, 2, 0, 28, 0, 100, 512, 0, 0, 0, 0, 0, 0, 41, 1000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Hyldsmeet Proto-Drake - On Passenger Removed - Despawn In 1000 ms'); + +DELETE FROM `spell_area` WHERE `spell` IN (55012, 72914) AND `area` IN (4430, 4431, 4432) AND `quest_start` = 12886; +INSERT INTO `spell_area` (`spell`, `area`, `quest_start`, `quest_end`, `aura_spell`, `racemask`, `gender`, `autocast`, `quest_start_status`, `quest_end_status`) VALUES +(55012, 4430, 12886, 0, 0, 0, 2, 1, 10, 0), +(55012, 4431, 12886, 0, 0, 0, 2, 1, 10, 0), +(55012, 4432, 12886, 0, 0, 0, 2, 1, 10, 0), +(72914, 4430, 12886, 0, 0, 0, 2, 1, 10, 0), +(72914, 4431, 12886, 0, 0, 0, 2, 1, 10, 0), +(72914, 4432, 12886, 0, 0, 0, 2, 1, 10, 0); diff --git a/data/sql/updates/db_world/2025_12_02_02.sql b/data/sql/updates/db_world/2025_12_02_02.sql new file mode 100644 index 000000000..e2f4488bd --- /dev/null +++ b/data/sql/updates/db_world/2025_12_02_02.sql @@ -0,0 +1,66 @@ +-- DB update 2025_12_02_01 -> 2025_12_02_02 +-- Makes all Everfrost Chips spawns 45 minutes (before 30 and 1 hour). +UPDATE `gameobject` SET `spawntimesecs` = 2700 WHERE `id` = 193997; + +DELETE FROM `pool_template` WHERE `entry` IN (150, 151, 152); +INSERT INTO `pool_template` (`entry`, `max_limit`, `description`) VALUES +(150, 8, "Everfrost Chip - Valley of Ancient Winters"), -- Total 30 / 4 = 7.5 rounded to 8 +(151, 4, "Everfrost Chip - Frostfield Lake"), -- Total 16 / 4 = 4 +(152, 2, "Everfrost Chip - Dun Niffelem"); -- Total 08 / 4 = 2 + +DELETE FROM `pool_gameobject` WHERE `pool_entry` IN (150, 151, 152) AND `guid` IN (221000, 221002, 1161, 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 3721, 3722, 3723, 3724, 3725, 3726, 3727, 3728, 3729, 3730, 3731, 3732, 3733, 3734, 3735, 3736, 3737, 3738, 3739, 3740, 3741, 3742, 3743, 3744, 3745, 3746, 3747, 3748, 3749, 3750, 3751, 3752, 3753, 3754, 3755, 3756, 3757, 3758, 3759, 3760, 3761, 221001); +INSERT INTO `pool_gameobject` (`guid`, `pool_entry`, `chance`, `description`) VALUES +(3728, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3751, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3761, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3721, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3734, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3755, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3724, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(1170, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3732, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3723, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3729, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3746, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3752, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(1161, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3722, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3756, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3731, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(1162, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(1163, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3737, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3730, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3726, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3727, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(1169, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3736, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(221002, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3749, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(221000, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3743, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3725, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3759, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3733, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3753, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3758, 151, 0, "Everfrost Chip - Frostfield Lake"), +(221001, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3735, 151, 0, "Everfrost Chip - Frostfield Lake"), +(1168, 151, 0, "Everfrost Chip - Frostfield Lake"), +(1167, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3760, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3745, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3741, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3744, 151, 0, "Everfrost Chip - Frostfield Lake"), +(1166, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3739, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3757, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3748, 152, 0, "Everfrost Chip - Dun Niffelem"), +(3740, 152, 0, "Everfrost Chip - Dun Niffelem"), +(3738, 152, 0, "Everfrost Chip - Dun Niffelem"), +(3750, 152, 0, "Everfrost Chip - Dun Niffelem"), +(1164, 152, 0, "Everfrost Chip - Dun Niffelem"), +(3747, 152, 0, "Everfrost Chip - Dun Niffelem"), +(1165, 152, 0, "Everfrost Chip - Dun Niffelem"), +(3742, 152, 0, "Everfrost Chip - Dun Niffelem"), +(3754, 152, 0, "Everfrost Chip - Dun Niffelem"); diff --git a/data/sql/updates/db_world/2025_12_02_03.sql b/data/sql/updates/db_world/2025_12_02_03.sql new file mode 100644 index 000000000..7dc717196 --- /dev/null +++ b/data/sql/updates/db_world/2025_12_02_03.sql @@ -0,0 +1,3 @@ +-- DB update 2025_12_02_02 -> 2025_12_02_03 +-- From: "from that $r" to "from that troll" as refers to the troll (Drakkari prisoner) and not the player's race. +UPDATE `quest_offer_reward` SET `RewardText` = 'You\'ve done it!$B$BThe intelligence gathered from that troll will undoubtedly be of great value. I\'ll be certain to make mention of your efforts in my report to the commander.$B$BThank you, $N.' WHERE `ID` = 12541; diff --git a/data/sql/updates/db_world/2025_12_02_04.sql b/data/sql/updates/db_world/2025_12_02_04.sql new file mode 100644 index 000000000..d4388331d --- /dev/null +++ b/data/sql/updates/db_world/2025_12_02_04.sql @@ -0,0 +1,23 @@ +-- DB update 2025_12_02_03 -> 2025_12_02_04 +-- Seething Revenant (30387) - Add missing loot +-- Closes https://github.com/azerothcore/azerothcore-wotlk/issues/23807 + +UPDATE `creature_loot_template` SET `Chance` = 0.04 WHERE `Entry` = 30387 AND `Item` = 45912; + +DELETE FROM `creature_loot_template` WHERE `Entry` = 30387 AND `Item` IN (39512, 42780, 37702, 39513, 43624, 42173, 42175, 26001, 26002, 26013, 26014, 26015, 26027, 26028, 35074); +INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(30387, 39512, 0, 56, 0, 1, 0, 1, 1, 'Seething Revenant - Hoary Crystals'), +(30387, 42780, 0, 26, 0, 1, 0, 1, 1, 'Seething Revenant - Relic of Ulduar'), +(30387, 37702, 0, 19, 0, 1, 0, 1, 2, 'Seething Revenant - Crystallized Fire'), +(30387, 39513, 0, 14, 0, 1, 0, 1, 1, 'Seething Revenant - Efflorescing Shards'), +(30387, 43624, 0, 0.01, 0, 1, 0, 1, 1, 'Seething Revenant - Titanium Lockbox'), +(30387, 42173, 0, 0.005, 0, 1, 0, 1, 1, 'Seething Revenant - Pattern: Blue Lumberjack Shirt'), +(30387, 42175, 0, 0.005, 0, 1, 0, 1, 1, 'Seething Revenant - Pattern: Green Lumberjack Shirt'), +(30387, 26001, 26001, 3, 0, 1, 1, 1, 1, 'Seething Revenant - (ReferenceTable)'), +(30387, 26002, 26002, 3, 0, 1, 1, 1, 1, 'Seething Revenant - (ReferenceTable)'), +(30387, 26013, 26013, 1, 0, 1, 1, 1, 1, 'Seething Revenant - (ReferenceTable)'), +(30387, 26014, 26014, 1, 0, 1, 1, 1, 1, 'Seething Revenant - (ReferenceTable)'), +(30387, 26015, 26015, 1, 0, 1, 1, 1, 1, 'Seething Revenant - (ReferenceTable)'), +(30387, 26027, 26027, 0.5, 0, 1, 1, 1, 1, 'Seething Revenant - (ReferenceTable)'), +(30387, 26028, 26028, 0.5, 0, 1, 1, 1, 1, 'Seething Revenant - (ReferenceTable)'), +(30387, 35074, 35074, 0.1, 0, 1, 1, 1, 1, 'Seething Revenant - (ReferenceTable)'); diff --git a/data/sql/updates/db_world/2025_12_04_00.sql b/data/sql/updates/db_world/2025_12_04_00.sql new file mode 100644 index 000000000..a57036c8a --- /dev/null +++ b/data/sql/updates/db_world/2025_12_04_00.sql @@ -0,0 +1,4 @@ +-- DB update 2025_12_02_04 -> 2025_12_04_00 + +UPDATE `creature_template` SET `exp` = 2 WHERE (`entry` = 32263); +UPDATE `creature` SET `curhealth` = 10080 WHERE (`id1` = 32263) AND `guid` = 85056; diff --git a/data/sql/updates/db_world/2025_12_05_00.sql b/data/sql/updates/db_world/2025_12_05_00.sql new file mode 100644 index 000000000..f2564e9ab --- /dev/null +++ b/data/sql/updates/db_world/2025_12_05_00.sql @@ -0,0 +1,9 @@ +-- DB update 2025_12_04_00 -> 2025_12_05_00 +-- DB/Quest: Westguard Sergeant despawns when leaving Skorn +DELETE FROM `smart_scripts` WHERE `entryorguid` = 24060 AND `source_type` = 0 AND `id` = 2; +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 +(24060, 0, 2, 0, 1, 0, 100, 0, 3000, 5000, 3000, 5000, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Westguard Sergeant - Out of Combat - Despawn Instant (Outside Skorn)'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 22 AND `SourceGroup` = 3 AND `SourceEntry` = 24060 AND `SourceId` = 0; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(22, 3, 24060, 0, 0, 23, 1, 4002, 0, 0, 1, 0, 0, '', 'Westguard Sergeant - Despawn script only triggers when NOT in Skorn (area 4002)'); diff --git a/data/sql/updates/db_world/2025_12_05_01.sql b/data/sql/updates/db_world/2025_12_05_01.sql new file mode 100644 index 000000000..24a1cbe94 --- /dev/null +++ b/data/sql/updates/db_world/2025_12_05_01.sql @@ -0,0 +1,146 @@ +-- DB update 2025_12_05_00 -> 2025_12_05_01 + +-- Add sniffed Waypoints +DELETE FROM `waypoint_data` WHERE (`id` IN (12641600, 12641900, 12642000, 12640000, 12639700)); +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(12641600, 1, 3122.1736, 532.6602, 88.01989, NULL, 0, 0, 0, 100, 0), +(12641600, 2, 3125.966, 508.25412, 88.542816, NULL, 0, 0, 0, 100, 0), +(12641600, 3, 3146.3586, 476.755, 78.63365, NULL, 0, 0, 0, 100, 0), +(12641600, 4, 3176.8057, 466.12268, 63.954556, NULL, 0, 0, 0, 100, 0), +(12641600, 5, 3186.5317, 454.58585, 62.529587, NULL, 0, 0, 0, 100, 0), +(12641600, 6, 3203.792, 452.24567, 60.55202, NULL, 2000, 0, 0, 100, 0), +(12641600, 7, 3186.5317, 454.58585, 62.529587, NULL, 0, 0, 0, 100, 0), +(12641600, 8, 3176.8057, 466.12268, 63.954556, NULL, 0, 0, 0, 100, 0), +(12641600, 9, 3146.3586, 476.755, 78.63365, NULL, 0, 0, 0, 100, 0), +(12641600, 10, 3125.966, 508.25412, 88.542816, NULL, 0, 0, 0, 100, 0), +(12641600, 11, 3127.8643, 505.31055, 87.93867, NULL, 0, 0, 0, 100, 0), +(12641600, 12, 3121.3276, 554.1918, 89.05305, NULL, 0, 0, 0, 100, 0), +(12641600, 13, 3122.1736, 532.6602, 88.01989, NULL, 0, 0, 0, 100, 0), +(12641600, 14, 3121.3276, 554.1918, 89.05305, NULL, 0, 0, 0, 100, 0), +(12641900, 1, 3169.1216, 650.4629, 73.140945, NULL, 0, 0, 0, 100, 0), +(12641900, 2, 3174.4927, 671.8068, 80.675766, NULL, 0, 0, 0, 100, 0), +(12641900, 3, 3192.1406, 689.416, 89.47004, NULL, 0, 0, 0, 100, 0), +(12641900, 4, 3217.8877, 703.09235, 93.65135, NULL, 0, 0, 0, 100, 0), +(12641900, 5, 3264.109, 700.6325, 92.4675, NULL, 0, 0, 0, 100, 0), +(12641900, 6, 3288.6113, 691.9492, 90.03599, NULL, 0, 0, 0, 100, 0), +(12641900, 7, 3296.816, 667.01575, 83.845055, NULL, 0, 0, 0, 100, 0), +(12641900, 8, 3294.3733, 646.39856, 78.13237, NULL, 0, 0, 0, 100, 0), +(12641900, 9, 3299.9355, 631.39844, 74.52907, NULL, 0, 0, 0, 100, 0), +(12641900, 10, 3292.5527, 608.5703, 64.710144, NULL, 2000, 0, 0, 100, 0), +(12641900, 11, 3299.9355, 631.39844, 74.52907, NULL, 0, 0, 0, 100, 0), +(12641900, 12, 3294.3733, 646.39856, 78.13237, NULL, 0, 0, 0, 100, 0), +(12641900, 13, 3296.816, 667.01575, 83.845055, NULL, 0, 0, 0, 100, 0), +(12641900, 14, 3288.6113, 691.9492, 90.03599, NULL, 0, 0, 0, 100, 0), +(12641900, 15, 3264.109, 700.6325, 92.4675, NULL, 0, 0, 0, 100, 0), +(12641900, 16, 3217.8877, 703.09235, 93.65135, NULL, 0, 0, 0, 100, 0), +(12641900, 17, 3192.1406, 689.416, 89.47004, NULL, 0, 0, 0, 100, 0), +(12641900, 18, 3174.4927, 671.8068, 80.675766, NULL, 0, 0, 0, 100, 0), +(12641900, 19, 3169.1216, 650.4629, 73.140945, NULL, 0, 0, 0, 100, 0), +(12641900, 20, 3166.53, 627.90375, 68.15999, NULL, 0, 0, 0, 100, 0), +(12641900, 21, 3176.731, 609.7736, 62.805485, NULL, 0, 0, 0, 100, 0), +(12641900, 22, 3166.53, 627.90375, 68.15999, NULL, 0, 0, 0, 100, 0), +(12642000, 1, 3386.952, 502.5323, 95.89945, NULL, 0, 0, 0, 100, 0), +(12642000, 2, 3375.5227, 476.80362, 91.18758, NULL, 0, 0, 0, 100, 0), +(12642000, 3, 3358.9795, 465.80887, 87.52131, NULL, 0, 0, 0, 100, 0), +(12642000, 4, 3339.3208, 447.99405, 84.71066, NULL, 0, 0, 0, 100, 0), +(12642000, 5, 3328.7197, 425.91498, 76.79626, NULL, 0, 0, 0, 100, 0), +(12642000, 6, 3318.7969, 413.56195, 70.89054, NULL, 0, 0, 0, 100, 0), +(12642000, 7, 3299.4473, 435.4253, 64.41885, NULL, 0, 0, 0, 100, 0), +(12642000, 8, 3289.706, 451.7539, 63.35991, NULL, 0, 0, 0, 100, 0), +(12642000, 9, 3276.5793, 458.35553, 61.149826, NULL, 0, 0, 0, 100, 0), +(12642000, 10, 3261.4954, 463.6344, 58.083496, NULL, 2000, 0, 0, 100, 0), +(12642000, 11, 3276.5793, 458.35553, 61.149826, NULL, 0, 0, 0, 100, 0), +(12642000, 12, 3289.706, 451.7539, 63.35991, NULL, 0, 0, 0, 100, 0), +(12642000, 13, 3299.4473, 435.4253, 64.41885, NULL, 0, 0, 0, 100, 0), +(12642000, 14, 3318.7969, 413.56195, 70.89054, NULL, 0, 0, 0, 100, 0), +(12642000, 15, 3328.7197, 425.91498, 76.79626, NULL, 0, 0, 0, 100, 0), +(12642000, 16, 3339.3208, 447.99405, 84.71066, NULL, 0, 0, 0, 100, 0), +(12642000, 17, 3358.9795, 465.80887, 87.52131, NULL, 0, 0, 0, 100, 0), +(12642000, 18, 3375.5227, 476.80362, 91.18758, NULL, 0, 0, 0, 100, 0), +(12642000, 19, 3386.952, 502.5323, 95.89945, NULL, 0, 0, 0, 100, 0), +(12642000, 20, 3388.6235, 530.1738, 97.31077, NULL, 0, 0, 0, 100, 0), +(12642000, 21, 3390.374, 550.4353, 95.18623, NULL, 0, 0, 0, 100, 0), +(12642000, 22, 3388.6235, 530.1738, 97.31077, NULL, 0, 0, 0, 100, 0), +(12640000, 1, 3112.822, 652.9017, 79.580154, NULL, 0, 0, 0, 100, 0), +(12640000, 2, 3106.8435, 626.3539, 77.43082, NULL, 0, 0, 0, 100, 0), +(12640000, 3, 3092.7388, 610.93243, 77.23309, NULL, 0, 0, 0, 100, 0), +(12640000, 4, 3100.2705, 593.8865, 78.54593, NULL, 0, 0, 0, 100, 0), +(12640000, 5, 3119.237, 590.99493, 75.144455, NULL, 0, 0, 0, 100, 0), +(12640000, 6, 3142.236, 594.5618, 69.939224, NULL, 0, 0, 0, 100, 0), +(12640000, 7, 3151.5881, 617.27466, 68.80421, NULL, 0, 0, 0, 100, 0), +(12640000, 8, 3149.7422, 647.2168, 74.23805, NULL, 0, 0, 0, 100, 0), +(12640000, 9, 3154.8203, 666.55273, 77.53181, NULL, 0, 0, 0, 100, 0), +(12640000, 10, 3143.1262, 667.666, 79.811264, NULL, 0, 0, 0, 100, 0), +(12640000, 11, 3130.7563, 662.6465, 80.169395, NULL, 0, 0, 0, 100, 0), +(12639700, 1, 3314.8162, 664.1162, 84.00654, NULL, 0, 0, 0, 100, 0), +(12639700, 2, 3308.4458, 649.0255, 81.44372, NULL, 0, 0, 0, 100, 0), +(12639700, 3, 3314.9888, 625.7648, 76.64586, NULL, 0, 0, 0, 100, 0), +(12639700, 4, 3334.93, 617.82074, 80.46573, NULL, 0, 0, 0, 100, 0), +(12639700, 5, 3355.2317, 616.2408, 84.47163, NULL, 0, 0, 0, 100, 0), +(12639700, 6, 3348.8887, 616.72656, 82.99916, NULL, 0, 0, 0, 100, 0), +(12639700, 7, 3347.2444, 636.7253, 85.3196, NULL, 0, 0, 0, 100, 0), +(12639700, 8, 3331.8745, 656.21674, 85.11536, NULL, 0, 0, 0, 100, 0); + +-- Add Spell Difficulty (Devotion Aura) +DELETE FROM `spelldifficulty_dbc` WHERE (`ID` IN (57740)); +INSERT INTO `spelldifficulty_dbc` (`ID`,`DifficultySpellID_1`,`DifficultySpellID_2`,`DifficultySpellID_3`,`DifficultySpellID_4`) VALUES +(57740, 57740, 58944, 0, 0); + +-- Remove auras from Onyx Brood General +UPDATE `creature_template_addon` SET `auras` = '' WHERE (`entry` IN (30680, 30999)); + +-- Update SP, MT and WD (sniffed values) +UPDATE `creature` SET `position_x` = 3123.9624, `position_y` = 563.4905, `position_z` = 89.08344, `orientation` = 4.43663, `MovementType` = 2, `wander_distance` = 0, `VerifiedBuild` = 64481 WHERE (`id1` = 30453) AND `guid` = 126416; +UPDATE `creature` SET `position_x` = 3125.977, `position_y` = 574.3518, `position_z` = 86.13242, `orientation` = 5.34753, `MovementType` = 0, `wander_distance` = 0, `VerifiedBuild` = 64481 WHERE (`id1` = 30453) AND `guid` = 126417; +UPDATE `creature` SET `position_x` = 3181.6206, `position_y` = 604.76, `position_z` = 60.37278, `orientation` = 5.04935, `MovementType` = 0, `wander_distance` = 0, `VerifiedBuild` = 64481 WHERE (`id1` = 30453) AND `guid` = 126418; +UPDATE `creature` SET `position_x` = 3177.7805, `position_y` = 616.0001, `position_z` = 64.20651, `orientation` = 4.54553, `MovementType` = 2, `wander_distance` = 0, `VerifiedBuild` = 64481 WHERE (`id1` = 30453) AND `guid` = 126419; +UPDATE `creature` SET `position_x` = 3391.5247, `position_y` = 554.5057, `position_z` = 94.93257, `orientation` = 4.43663, `MovementType` = 2, `wander_distance` = 0, `VerifiedBuild` = 64481 WHERE (`id1` = 30453) AND `guid` = 126420; +UPDATE `creature` SET `position_x` = 3393.2766, `position_y` = 567.3406, `position_z` = 91.24738, `orientation` = 4.13784, `MovementType` = 0, `wander_distance` = 0, `VerifiedBuild` = 64481 WHERE (`id1` = 30453) AND `guid` = 126421; +UPDATE `creature` SET `position_x` = 3149.0312, `position_y` = 668.306, `position_z` = 79.01899, `orientation` = 3.24923, `MovementType` = 2, `wander_distance` = 0, `VerifiedBuild` = 64481 WHERE (`id1` = 30680) AND `guid` = 126400; +UPDATE `creature` SET `position_x` = 3351.0344, `position_y` = 636.5978, `position_z` = 85.80331, `orientation` = 3.10852, `MovementType` = 2, `wander_distance` = 0, `VerifiedBuild` = 64481 WHERE (`id1` = 30680) AND `guid` = 126397; +UPDATE `creature` SET `position_x` = 3361.3906, `position_y` = 625.84937, `position_z` = 87.20121, `orientation` = 3.07296, `MovementType` = 0, `wander_distance` = 0, `VerifiedBuild` = 64481 WHERE (`id1` = 30682) AND `guid` = 126407; +UPDATE `creature` SET `position_x` = 3149.0798, `position_y` = 677.131, `position_z` = 81.535164, `orientation` = 4.61926, `MovementType` = 0, `wander_distance` = 0, `VerifiedBuild` = 64481 WHERE (`id1` = 30682) AND `guid` = 126412; +UPDATE `creature` SET `position_x` = 3157.8823, `position_y` = 666.0498, `position_z` = 77.16373, `orientation` = 3.85403, `MovementType` = 0, `wander_distance` = 0, `VerifiedBuild` = 64481 WHERE (`id1` = 30682) AND `guid` = 126408; +UPDATE `creature` SET `position_x` = 3351.464, `position_y` = 627.4477, `position_z` = 85.05361, `orientation` = 2.89519, `MovementType` = 0, `wander_distance` = 0, `VerifiedBuild` = 64481 WHERE (`id1` = 30681) AND `guid` = 126401; +UPDATE `creature` SET `position_x` = 3160.2383, `position_y` = 676.69977, `position_z` = 80.68675, `orientation` = 4.17643, `MovementType` = 0, `wander_distance` = 0, `VerifiedBuild` = 64481 WHERE (`id1` = 30681) AND `guid` = 126405; +UPDATE `creature` SET `position_x` = 3361.7314, `position_y` = 635.8682, `position_z` = 87.79267, `orientation` = 3.46105, `MovementType` = 0, `wander_distance` = 0, `VerifiedBuild` = 64481 WHERE (`id1` = 30681) AND `guid` = 126406; + +-- Set creature formations +DELETE FROM `creature_formations` WHERE (`leaderGUID` IN (126416, 126419, 126420, 126397, 126400)); +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES +(126416, 126416, 0, 0, 515, 0, 0), +(126416, 126417, 10, 180, 515, 0, 0), +(126420, 126420, 0, 0, 515, 0, 0), +(126420, 126421, 10, 180, 515, 0, 0), +(126419, 126419, 0, 0, 515, 0, 0), +(126419, 126418, 10, 180, 515, 0, 0), +(126397, 126397, 0, 0, 515, 0, 0), +(126397, 126406, 10, 240, 515, 0, 0), +(126397, 126401, 10, 120, 515, 0, 0), +(126397, 126407, 15, 180, 515, 0, 0), +(126400, 126400, 0, 0, 515, 0, 0), +(126400, 126412, 10, 240, 515, 0, 0), +(126400, 126408, 10, 120, 515, 0, 0), +(126400, 126405, 15, 180, 515, 0, 0); + +-- Set Waypoints +DELETE FROM `creature_addon` WHERE (`guid` IN (126416, 126419, 126420, 126400, 126397)); +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) VALUES +(126416, 12641600, 0, 0, 1, 0, 0, NULL), +(126419, 12641900, 0, 0, 1, 0, 0, NULL), +(126420, 12642000, 0, 0, 1, 0, 0, NULL), +(126400, 12640000, 0, 0, 1, 0, 0, NULL), +(126397, 12639700, 0, 0, 1, 0, 0, NULL); + +-- Update SmartAI (Onyx Sanctum Guardian & Onyx Brood General) +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE (`entry` IN (30453, 30680)); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0) AND (`entryorguid` IN (30453, 30680)); +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 +(30453, 0, 0, 0, 0, 0, 100, 0, 7000, 9000, 17000, 18000, 0, 0, 11, 57728, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Onyx Sanctum Guardian - In Combat - Cast \'Shockwave\''), +(30453, 0, 1, 0, 0, 0, 100, 0, 13000, 13000, 30000, 30000, 0, 0, 11, 39647, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 'Onyx Sanctum Guardian - In Combat - Cast \'Curse of Mending\''), +(30453, 0, 2, 0, 12, 0, 100, 0, 25, 30, 5000, 5000, 0, 0, 11, 53801, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Onyx Sanctum Guardian - Target Between 25-30% Health - Cast \'Frenzy\''), +(30680, 0, 0, 0, 60, 0, 100, 0, 0, 0, 600000, 600000, 0, 0, 11, 57740, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Onyx Brood General - On Update - Cast \'Devotion Aura\''), +(30680, 0, 1, 0, 0, 0, 100, 0, 5000, 6000, 7000, 8000, 0, 0, 11, 13737, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Onyx Brood General - In Combat - Cast \'Mortal Strike\''), +(30680, 0, 2, 0, 0, 0, 100, 0, 15000, 15000, 40000, 40000, 0, 0, 11, 57733, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Onyx Brood General - In Combat - Cast \'Draconic Rage\''), +(30680, 0, 3, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 57742, 2, 0, 0, 0, 0, 26, 10, 0, 0, 0, 0, 0, 0, 0, 'Onyx Brood General - On Just Died - Cast \'Avenging Fury\''); diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 3acaf45a0..a4b8c14c6 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -290,6 +290,11 @@ add_library(modules STATIC if (MOD_ALE_FOUND) target_link_libraries(modules PUBLIC lualib) + # Also ensure include directories are propagated for modules that include sol.hpp + get_target_property(LUALIB_INCLUDE_DIRS lualib INTERFACE_INCLUDE_DIRECTORIES) + if(LUALIB_INCLUDE_DIRS) + list(APPEND PUBLIC_INCLUDES ${LUALIB_INCLUDE_DIRS}) + endif() endif() target_link_libraries(modules diff --git a/src/cmake/macros/FindMySQL.cmake b/src/cmake/macros/FindMySQL.cmake index 2a8de7e7a..999dadc48 100644 --- a/src/cmake/macros/FindMySQL.cmake +++ b/src/cmake/macros/FindMySQL.cmake @@ -137,7 +137,6 @@ if(WIN32) ) list(SORT _MYSQL_ROOT_HINTS_SUBKEYS COMPARE NATURAL ORDER DESCENDING) - set(_MYSQL_ROOT_HINTS_REGISTRY_LOCATIONS) foreach(subkey IN LISTS _MYSQL_ROOT_HINTS_SUBKEYS) cmake_host_system_information( RESULT @@ -147,7 +146,7 @@ if(WIN32) "HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\${subkey}" VALUE "Location" VIEW BOTH ) - list(APPEND _MYSQL_ROOT_HINTS_REGISTRY_LOCATIONS ${_MYSQL_ROOT_HINTS_REGISTRY_LOCATION}) + list(APPEND _MYSQL_ROOT_HINTS ${_MYSQL_ROOT_HINTS_REGISTRY_LOCATION}) endforeach() file(GLOB _MYSQL_ROOT_PATHS_VERSION_SUBDIRECTORIES diff --git a/src/common/Collision/Maps/MapDefines.h b/src/common/Collision/Maps/MapDefines.h index d928c5172..a3527f16c 100644 --- a/src/common/Collision/Maps/MapDefines.h +++ b/src/common/Collision/Maps/MapDefines.h @@ -26,7 +26,7 @@ #define SIZE_OF_GRIDS 533.3333f #define MMAP_MAGIC 0x4d4d4150 // 'MMAP' -#define MMAP_VERSION 18 +#define MMAP_VERSION 19 struct MmapTileRecastConfig { diff --git a/src/common/Collision/VMapDefinitions.h b/src/common/Collision/VMapDefinitions.h index 623dea502..b8026d949 100644 --- a/src/common/Collision/VMapDefinitions.h +++ b/src/common/Collision/VMapDefinitions.h @@ -22,8 +22,8 @@ namespace VMAP { - const char VMAP_MAGIC[] = "VMAP_4.7"; - const char RAW_VMAP_MAGIC[] = "VMAP047"; // used in extracted vmap files with raw data + const char VMAP_MAGIC[] = "VMAP_4.8"; + const char RAW_VMAP_MAGIC[] = "VMAP048"; // used in extracted vmap files with raw data const char GAMEOBJECT_MODELS[] = "GameObjectModels.dtree"; // defined in TileAssembler.cpp currently... diff --git a/src/common/Utilities/Systemd.cpp b/src/common/Utilities/Systemd.cpp new file mode 100644 index 000000000..f7c39cfb1 --- /dev/null +++ b/src/common/Utilities/Systemd.cpp @@ -0,0 +1,59 @@ +/* + * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information. + * + * Portions of this file are derived from systemd, licensed under: + * - GPL-2.0-or-later (if the original systemd file was GPL-2.0+) + * OR + * - LGPL-2.1-or-later, relicensed under GPL-2.0-or-later as permitted by LGPL-2.1+ + * + * Original systemd copyright: + * Copyright (c) the systemd contributors. + * + * 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 . + */ + +#if defined(__linux__) +#include "Log.h" +#include "StringConvert.h" +#include +#include +#include + +int get_listen_fd() +{ + char* const listen_pid = std::getenv("LISTEN_PID"); + char* const listen_fds = std::getenv("LISTEN_FDS"); + if (!listen_pid || !listen_fds) + return 0; + + pid_t pid = Acore::StringTo(listen_pid).value_or(0); + if (pid != getpid()) + return 0; + + int fds = Acore::StringTo(listen_fds).value_or(0); + if (fds <= 0) + return 0; + + if (fds > 1) + LOG_WARN("network", "Multiple file descriptors received from systemd socket activation, only the first will be used"); + + return 3; +} +#else +// On non-Linux systems, just return 0 (no socket activation) +int get_listen_fd() +{ + return 0; +} +#endif diff --git a/src/common/Utilities/Systemd.h b/src/common/Utilities/Systemd.h new file mode 100644 index 000000000..312345cea --- /dev/null +++ b/src/common/Utilities/Systemd.h @@ -0,0 +1,31 @@ +/* + * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information. + * + * Portions of this file are derived from systemd, licensed under: + * - GPL-2.0-or-later (if the original systemd file was GPL-2.0+) + * OR + * - LGPL-2.1-or-later, relicensed under GPL-2.0-or-later as permitted by LGPL-2.1+ + * + * Original systemd copyright: + * Copyright (c) the systemd contributors. + * + * 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 . + */ + +#ifndef _SYSTEMD_H_ +#define _SYSTEMD_H_ + +int get_listen_fd(); + +#endif diff --git a/src/common/Utilities/Util.h b/src/common/Utilities/Util.h index 95891e349..a7669fa16 100644 --- a/src/common/Utilities/Util.h +++ b/src/common/Utilities/Util.h @@ -47,15 +47,6 @@ AC_COMMON_API Optional MoneyStringToMoney(std::string_view moneyString); std::string secsToTimeString(uint64 timeInSecs, bool shortText = false); uint32 TimeStringToSecs(const std::string& timestring); -inline void ApplyPercentModFloatVar(float& var, float val, bool apply) -{ - if (val == -100.0f) // prevent set var to zero - { - val = -99.99f; - } - var *= (apply ? (100.0f + val) / 100.0f : 100.0f / (100.0f + val)); -} - // Percentage calculation template inline T CalculatePct(T base, U pct) diff --git a/src/server/apps/worldserver/Main.cpp b/src/server/apps/worldserver/Main.cpp index ac44f62fc..6a08e9689 100644 --- a/src/server/apps/worldserver/Main.cpp +++ b/src/server/apps/worldserver/Main.cpp @@ -48,6 +48,7 @@ #include "SecretMgr.h" #include "SharedDefines.h" #include "SteadyTimer.h" +#include "Systemd.h" #include "World.h" #include "WorldSessionMgr.h" #include "WorldSocket.h" @@ -406,7 +407,8 @@ int main(int argc, char** argv) sScriptMgr->OnShutdown(); // set server offline - LoginDatabase.DirectExecute("UPDATE realmlist SET flag = flag | {} WHERE id = '{}'", REALM_FLAG_OFFLINE, realm.Id.Realm); + if (!sConfigMgr->GetOption("Network.UseSocketActivation", false)) + LoginDatabase.DirectExecute("UPDATE realmlist SET flag = flag | {} WHERE id = '{}'", REALM_FLAG_OFFLINE, realm.Id.Realm); LOG_INFO("server.worldserver", "Halting process..."); diff --git a/src/server/apps/worldserver/worldserver.conf.dist b/src/server/apps/worldserver/worldserver.conf.dist index 001a89e9c..84c6bc0ad 100644 --- a/src/server/apps/worldserver/worldserver.conf.dist +++ b/src/server/apps/worldserver/worldserver.conf.dist @@ -397,6 +397,20 @@ Network.TcpNodelay = 1 Network.EnableProxyProtocol = 0 +# +# Network.UseSocketActivation +# Description: Enable systemd socket activation support for the worldserver. +# When enabled and the process is started by systemd socket activation, +# the server will use the socket passed by systemd instead of +# creating and binding its own listening socket. Disabled by default. +# +# When enabled the realm is not automatically set as offline on shutdown. +# +# Example: 1 - (Enabled) +# Default: 0 - (Disabled) + +Network.UseSocketActivation = 0 + # ################################################################################################### @@ -3363,6 +3377,15 @@ DungeonAccessRequirements.LFGLevelDBCOverride = 0 DungeonFinder.CastDeserter = 1 +# +# DungeonFinder.AllowCompleted +# +# Description: Controls whether completed heroic dungeons are excluded from LFG queue. +# 0 - (Classic WLK mode: Dungeons completed by any group member today are excluded (daily lockout enforced)) +# Default: 1 - (Blizzlike: All dungeons are available for queue, even if already completed) + +DungeonFinder.AllowCompleted = 1 + # ################################################################################################### diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp index 762dc6e12..522b17e41 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp @@ -15,12 +15,13 @@ * with this program. If not, see . */ -#include "ScriptedCreature.h" #include "Cell.h" #include "CellImpl.h" +#include "Containers.h" #include "GameTime.h" #include "GridNotifiers.h" #include "ObjectMgr.h" +#include "ScriptedCreature.h" #include "Spell.h" #include "TemporarySummon.h" @@ -141,6 +142,23 @@ Creature* SummonList::GetCreatureWithEntry(uint32 entry) const return nullptr; } +Creature* SummonList::GetRandomCreatureWithEntry(uint32 entry) const +{ + std::vector candidates; + candidates.reserve(storage_.size()); + + for (auto const guid : storage_) + if (Creature* summon = ObjectAccessor::GetCreature(*me, guid)) + if (summon->GetEntry() == entry) + candidates.push_back(guid); + + if (candidates.empty()) + return nullptr; + + ObjectGuid randomGuid = Acore::Containers::SelectRandomContainerElement(candidates); + return ObjectAccessor::GetCreature(*me, randomGuid); +} + bool SummonList::IsAnyCreatureAlive() const { for (auto const& guid : storage_) diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h index 4aceb3fae..47f8cf30c 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h @@ -157,6 +157,7 @@ public: uint32 GetEntryCount(uint32 entry) const; void Respawn(); Creature* GetCreatureWithEntry(uint32 entry) const; + Creature* GetRandomCreatureWithEntry(uint32 entry) const; private: Creature* me; diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index f88840349..3c952a42d 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -858,7 +858,7 @@ void SmartAI::AttackStart(Unit* who) return; } - if (who && me->Attack(who, me->IsWithinMeleeRange(who))) + if (who && me->Attack(who, me->IsWithinMeleeRange(who) || _currentRangeMode)) { if (!me->HasUnitState(UNIT_STATE_NO_COMBAT_MOVEMENT)) { @@ -870,7 +870,7 @@ void SmartAI::AttackStart(Unit* who) me->GetMotionMaster()->Clear(false); } - me->GetMotionMaster()->MoveChase(who); + me->GetMotionMaster()->MoveChase(who, _attackDistance); } } } @@ -941,6 +941,35 @@ void SmartAI::PassengerBoarded(Unit* who, int8 seatId, bool apply) void SmartAI::InitializeAI() { GetScript()->OnInitialize(me); + + for (SmartScriptHolder const& event : GetScript()->GetEvents()) + { + if (event.GetActionType() != SMART_ACTION_CAST) + continue; + + if (!(event.action.cast.castFlags & SMARTCAST_MAIN_SPELL)) + continue; + + SetMainSpell(event.action.cast.spell); + break; + } + + // Fallback: use first SMARTCAST_COMBAT_MOVE if no MAIN_SPELL found + if (!_currentRangeMode) + { + for (SmartScriptHolder const& event : GetScript()->GetEvents()) + { + if (event.GetActionType() != SMART_ACTION_CAST) + continue; + + if (!(event.action.cast.castFlags & SMARTCAST_COMBAT_MOVE)) + continue; + + SetMainSpell(event.action.cast.spell); + break; + } + } + if (!me->isDead()) { mJustReset = true; @@ -1083,6 +1112,20 @@ void SmartAI::SetCurrentRangeMode(bool on, float range) me->GetMotionMaster()->MoveChase(victim, _attackDistance); } +void SmartAI::SetMainSpell(uint32 spellId) +{ + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); + if (!spellInfo) + return; + + float maxRange = spellInfo->GetMaxRange(false); + if (maxRange <= NOMINAL_MELEE_RANGE) + return; + + _attackDistance = std::max(maxRange - NOMINAL_MELEE_RANGE, 0.0f); + _currentRangeMode = true; +} + void SmartAI::DistanceYourself(float range) { Unit* victim = me->GetVictim(); diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h index d6b957cc0..087633645 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.h +++ b/src/server/game/AI/SmartScripts/SmartAI.h @@ -67,6 +67,7 @@ public: void SetAutoAttack(bool on) { mCanAutoAttack = on; } void SetCombatMovement(bool on, bool stopOrStartMovement); void SetCurrentRangeMode(bool on, float range = 0.f); + void SetMainSpell(uint32 spellId); void DistanceYourself(float range); void SetFollow(Unit* target, float dist = 0.0f, float angle = 0.0f, uint32 credit = 0, uint32 end = 0, uint32 creditType = 0, bool aliveState = true); void StopFollow(bool complete); diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index a9b42edeb..2f66b4ac1 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -707,7 +707,6 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u continue; } - // Let us not try to cast spell if we know it is going to fail anyway. Stick to chasing and continue. if (distanceToTarget > spellMaxRange && isWithinLOSInMap) { failedSpellCast = true; @@ -745,12 +744,9 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (e.action.cast.castFlags & SMARTCAST_COMBAT_MOVE) { - // If cast flag SMARTCAST_COMBAT_MOVE is set combat movement will not be allowed unless target is outside spell range, out of mana, or LOS. - if (result == SPELL_FAILED_OUT_OF_RANGE || result == SPELL_CAST_OK) - // if we are just out of range, we only chase until we are back in spell range. + if (result == SPELL_FAILED_OUT_OF_RANGE) CAST_AI(SmartAI, me->AI())->SetCurrentRangeMode(true, std::max(spellMaxRange - NOMINAL_MELEE_RANGE, 0.0f)); - else // move into melee on any other fail - // if spell fail for any other reason, we chase to melee range, or stay where we are if spellcast was successful. + else if (result != SPELL_CAST_OK) CAST_AI(SmartAI, me->AI())->SetCurrentRangeMode(false, 0.f); } @@ -2696,6 +2692,8 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u { if (me && me->FindMap()) me->FindMap()->LoadGrid(e.target.x, e.target.y); + else if (go && go->FindMap()) + go->FindMap()->LoadGrid(e.target.x, e.target.y); break; } case SMART_ACTION_PLAYER_TALK: diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index e0f32438c..250fdd775 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -207,6 +207,8 @@ public: void AddCreatureSummon(ObjectGuid const& guid); void RemoveCreatureSummon(ObjectGuid const& guid); + SmartAIEventList const& GetEvents() const { return mEvents; } + private: void IncPhase(uint32 p); void DecPhase(uint32 p); diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 5e8e5e9e0..8dd177dfa 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -1932,16 +1932,17 @@ enum SmartEventFlags enum SmartCastFlags { - SMARTCAST_INTERRUPT_PREVIOUS = 0x001, // Interrupt any spell casting - SMARTCAST_TRIGGERED = 0x002, // Triggered (this makes spell cost zero mana and have no cast time) - //CAST_FORCE_CAST = 0x004, // Forces cast even if creature is out of mana or out of range - //CAST_NO_MELEE_IF_OOM = 0x008, // Prevents creature from entering melee if out of mana or out of range - //CAST_FORCE_TARGET_SELF = 0x010, // Forces the target to cast this spell on itself - SMARTCAST_AURA_NOT_PRESENT = 0x020, // Only casts the spell if the target does not have an aura from the spell - SMARTCAST_COMBAT_MOVE = 0x040, // Prevents combat movement if cast successful. Allows movement on range, OOM, LOS - SMARTCAST_THREATLIST_NOT_SINGLE = 0x080, // Only cast if the source's threatlist is higher than one. This includes pets (see Skeram's True Fulfillment) - SMARTCAST_TARGET_POWER_MANA = 0x100, // Only cast if the target has power type mana (e.g. Mana Drain) - SMARTCAST_ENABLE_COMBAT_MOVE_ON_LOS = 0x200, + SMARTCAST_INTERRUPT_PREVIOUS = 0x001, // Interrupt any spell casting + SMARTCAST_TRIGGERED = 0x002, // Triggered (this makes spell cost zero mana and have no cast time) + //CAST_FORCE_CAST = 0x004, // Forces cast even if creature is out of mana or out of range + //CAST_NO_MELEE_IF_OOM = 0x008, // Prevents creature from entering melee if out of mana or out of range + //CAST_FORCE_TARGET_SELF = 0x010, // Forces the target to cast this spell on itself + SMARTCAST_AURA_NOT_PRESENT = 0x020, // Only casts the spell if the target does not have an aura from the spell + SMARTCAST_COMBAT_MOVE = 0x040, // Prevents combat movement if cast successful. Allows movement on range, OOM, LOS + SMARTCAST_THREATLIST_NOT_SINGLE = 0x080, // Only cast if the source's threatlist is higher than one. This includes pets (see Skeram's True Fulfillment) + SMARTCAST_TARGET_POWER_MANA = 0x100, // Only cast if the target has power type mana (e.g. Mana Drain) + SMARTCAST_ENABLE_COMBAT_MOVE_ON_LOS = 0x200, // Allows combat movement when not in line of sight + SMARTCAST_MAIN_SPELL = 0x400, // Sets this spell's max range as the creature's chase distance on spawn }; enum SmartFollowType diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index b88d04c65..4b19fac35 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -688,7 +688,7 @@ namespace lfg // xinef: dont check compatibile dungeons for already running group (bind problems) if (!isContinue) { - GetCompatibleDungeons(dungeons, players, joinData.lockmap); + GetCompatibleDungeons(dungeons, players, joinData.lockmap, rDungeonId); if (dungeons.empty()) joinData.result = grp ? LFG_JOIN_PARTY_NOT_MEET_REQS : LFG_JOIN_NOT_MEET_REQS; } @@ -1485,7 +1485,7 @@ namespace lfg @param[in] players Set of players to check their dungeon restrictions @param[out] lockMap Map of players Lock status info of given dungeons (Empty if dungeons is not empty) */ - void LFGMgr::GetCompatibleDungeons(LfgDungeonSet& dungeons, LfgGuidSet const& players, LfgLockPartyMap& lockMap) + void LFGMgr::GetCompatibleDungeons(LfgDungeonSet& dungeons, LfgGuidSet const& players, LfgLockPartyMap& lockMap, bool isRDF) { lockMap.clear(); for (LfgGuidSet::const_iterator it = players.begin(); it != players.end() && !dungeons.empty(); ++it) @@ -1496,6 +1496,9 @@ namespace lfg { uint32 dungeonId = (it2->first & 0x00FFFFFF); // Compare dungeon ids + if (it2->second == LFG_LOCKSTATUS_RAID_LOCKED && isRDF && sWorld->getBoolConfig(CONFIG_LFG_ALLOW_COMPLETED)) + continue; + LfgDungeonSet::iterator itDungeon = dungeons.find(dungeonId); if (itDungeon != dungeons.end()) { @@ -1762,10 +1765,8 @@ namespace lfg else { // RDF removes all binds to that map - if (randomDungeon && !sInstanceSaveMgr->PlayerIsPermBoundToInstance(player->GetGUID(), dungeon->map, player->GetDungeonDifficulty())) - { + if (randomDungeon) sInstanceSaveMgr->PlayerUnbindInstance(player->GetGUID(), dungeon->map, player->GetDungeonDifficulty(), true); - } } playersTeleported.push_back(player); diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index b842122eb..ec05cdbfa 100644 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -590,7 +590,7 @@ namespace lfg void DecreaseKicksLeft(ObjectGuid guid); void SetState(ObjectGuid guid, LfgState state); void SetCanOverrideRBState(ObjectGuid guid, bool val); - void GetCompatibleDungeons(LfgDungeonSet& dungeons, LfgGuidSet const& players, LfgLockPartyMap& lockMap); + void GetCompatibleDungeons(LfgDungeonSet& dungeons, LfgGuidSet const& players, LfgLockPartyMap& lockMap, bool isRDF = false); void _SaveToDB(ObjectGuid guid); // Proposals diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index f6eb19034..289d4ac5e 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -38,6 +38,7 @@ #include "PoolMgr.h" #include "ScriptMgr.h" #include "ScriptedGossip.h" +#include "SpellAuraDefines.h" #include "SpellAuraEffects.h" #include "SpellMgr.h" #include "TemporarySummon.h" @@ -601,13 +602,13 @@ bool Creature::UpdateEntry(uint32 Entry, const CreatureData* data, bool changele SetMeleeDamageSchool(SpellSchools(cInfo->dmgschool)); CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(GetLevel(), cInfo->unit_class); float armor = stats->GenerateArmor(cInfo); - SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, armor); - SetModifierValue(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_HOLY])); - SetModifierValue(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FIRE])); - SetModifierValue(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_NATURE])); - SetModifierValue(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FROST])); - SetModifierValue(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_SHADOW])); - SetModifierValue(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_ARCANE])); + SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, armor); + SetStatFlatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_HOLY])); + SetStatFlatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FIRE])); + SetStatFlatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_NATURE])); + SetStatFlatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FROST])); + SetStatFlatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_SHADOW])); + SetStatFlatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_ARCANE])); SetCanModifyStats(true); UpdateAllStats(); @@ -1017,10 +1018,7 @@ void Creature::Regenerate(Powers power) } // Apply modifiers (if any). - AuraEffectList const& ModPowerRegenPCTAuras = GetAuraEffectsByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT); - for (AuraEffectList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i) - if (Powers((*i)->GetMiscValue()) == power) - AddPct(addvalue, (*i)->GetAmount()); + addvalue *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, power); addvalue += GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, power) * (power == POWER_FOCUS ? PET_FOCUS_REGEN_INTERVAL.count() : CREATURE_REGEN_INTERVAL) / (5 * IN_MILLISECONDS); @@ -1056,9 +1054,7 @@ void Creature::RegenerateHealth() } // Apply modifiers (if any). - AuraEffectList const& ModPowerRegenPCTAuras = GetAuraEffectsByType(SPELL_AURA_MOD_HEALTH_REGEN_PERCENT); - for (AuraEffectList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i) - AddPct(addvalue, (*i)->GetAmount()); + addvalue *= GetTotalAuraMultiplier(SPELL_AURA_MOD_HEALTH_REGEN_PERCENT); addvalue += GetTotalAuraModifier(SPELL_AURA_MOD_REGEN) * CREATURE_REGEN_INTERVAL / (5 * IN_MILLISECONDS); @@ -1559,8 +1555,8 @@ void Creature::SelectLevel(bool changelevel) /// @todo: set UNIT_FIELD_POWER*, for some creature class case (energy, etc) - SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, (float)health); - SetModifierValue(UNIT_MOD_MANA, BASE_VALUE, (float)mana); + SetStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, (float)health); + SetStatFlatModifier(UNIT_MOD_MANA, BASE_VALUE, (float)mana); // damage @@ -1578,8 +1574,8 @@ void Creature::SelectLevel(bool changelevel) SetBaseWeaponDamage(RANGED_ATTACK, MINDAMAGE, weaponBaseMinDamage); SetBaseWeaponDamage(RANGED_ATTACK, MAXDAMAGE, weaponBaseMaxDamage); - SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, stats->AttackPower); - SetModifierValue(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, stats->RangedAttackPower); + SetStatFlatModifier(UNIT_MOD_ATTACK_POWER, BASE_VALUE, stats->AttackPower); + SetStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, stats->RangedAttackPower); sScriptMgr->OnCreatureSelectLevel(cInfo, this); } diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 3d86fd059..73ced5874 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -815,13 +815,6 @@ void Object::ApplyModSignedFloatValue(uint16 index, float val, bool apply) SetFloatValue(index, cur); } -void Object::ApplyPercentModFloatValue(uint16 index, float val, bool apply) -{ - float value = GetFloatValue(index); - ApplyPercentModFloatVar(value, val, apply); - SetFloatValue(index, value); -} - void Object::ApplyModPositiveFloatValue(uint16 index, float val, bool apply) { float cur = GetFloatValue(index); diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 9e84a3732..02d38a2f5 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -165,7 +165,6 @@ public: void ApplyModUInt64Value(uint16 index, int32 val, bool apply); void ApplyModPositiveFloatValue(uint16 index, float val, bool apply); void ApplyModSignedFloatValue(uint16 index, float val, bool apply); - void ApplyPercentModFloatValue(uint16 index, float val, bool apply); void SetFlag(uint16 index, uint32 newFlag); void RemoveFlag(uint16 index, uint32 oldFlag); diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 4cb7d3d1b..55ebf72af 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -1075,7 +1075,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel) SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool)); } - SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel * 50)); + SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel * 50)); uint32 attackTime = BASE_ATTACK_TIME; if (!owner->IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET) && cinfo->BaseAttackTime >= 1000) @@ -1094,7 +1094,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel) // xinef: hunter pets should not inherit template resistances if (!IsHunterPet()) for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) - SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(cinfo->resistance[i])); + SetStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(cinfo->resistance[i])); //health, mana, armor and resistance PetLevelInfo const* pInfo = sObjectMgr->GetPetLevelInfo(creature_ID, petlevel); @@ -1111,15 +1111,15 @@ bool Guardian::InitStatsForLevel(uint8 petlevel) } SetCreateHealth(pInfo->health*factorHealth); - SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, (float)pInfo->health); + SetStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, (float)pInfo->health); if (petType != HUNTER_PET) //hunter pet use focus { SetCreateMana(pInfo->mana); - SetModifierValue(UNIT_MOD_MANA, BASE_VALUE, (float)pInfo->mana); + SetStatFlatModifier(UNIT_MOD_MANA, BASE_VALUE, (float)pInfo->mana); } if (pInfo->armor > 0) - SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor)); + SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor)); for (uint8 stat = 0; stat < MAX_STATS; ++stat) SetCreateStat(Stats(stat), float(pInfo->stats[stat])); @@ -1138,9 +1138,9 @@ bool Guardian::InitStatsForLevel(uint8 petlevel) } SetCreateHealth(std::max(1, stats->BaseHealth[cinfo->expansion]*factorHealth)); - SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, GetCreateHealth()); + SetStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, GetCreateHealth()); SetCreateMana(stats->BaseMana * factorMana); - SetModifierValue(UNIT_MOD_MANA, BASE_VALUE, GetCreateMana()); + SetStatFlatModifier(UNIT_MOD_MANA, BASE_VALUE, GetCreateMana()); // xinef: added some multipliers so debuffs can affect pets in any way... SetCreateStat(STAT_STRENGTH, 22); @@ -1174,24 +1174,6 @@ bool Guardian::InitStatsForLevel(uint8 petlevel) switch (GetEntry()) { - case NPC_FELGUARD: - { - // xinef: Glyph of Felguard, so ugly im crying... no appropriate spell - if (AuraEffect* aurEff = owner->GetAuraEffectDummy(SPELL_GLYPH_OF_FELGUARD)) - { - HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, aurEff->GetAmount(), true); - } - - break; - } - case NPC_VOIDWALKER: - { - if (AuraEffect* aurEff = owner->GetAuraEffectDummy(SPELL_GLYPH_OF_VOIDWALKER)) - { - HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_PCT, aurEff->GetAmount(), true); - } - break; - } case NPC_WATER_ELEMENTAL_PERM: { AddAura(SPELL_PET_AVOIDANCE, this); diff --git a/src/server/game/Entities/Player/KillRewarder.cpp b/src/server/game/Entities/Player/KillRewarder.cpp index dce44da0f..78d24b4db 100644 --- a/src/server/game/Entities/Player/KillRewarder.cpp +++ b/src/server/game/Entities/Player/KillRewarder.cpp @@ -21,6 +21,7 @@ #include "Pet.h" #include "Player.h" #include "ScriptMgr.h" +#include "SpellAuraDefines.h" #include "SpellAuraEffects.h" // KillRewarder incapsulates logic of rewarding player upon kill with: @@ -162,9 +163,7 @@ void KillRewarder::_RewardXP(Player* player, float rate) if (xp) { // 4.2.2. Apply auras modifying rewarded XP (SPELL_AURA_MOD_XP_PCT). - Unit::AuraEffectList const& auras = player->GetAuraEffectsByType(SPELL_AURA_MOD_XP_PCT); - for (Unit::AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i) - AddPct(xp, (*i)->GetAmount()); + xp *= player->GetTotalAuraMultiplier(SPELL_AURA_MOD_XP_PCT); // 4.2.3. Give XP to player. sScriptMgr->OnPlayerGiveXP(player, xp, _victim, PlayerXPSource::XPSOURCE_KILL); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 11793c4ee..3271fc3f7 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -69,8 +69,10 @@ #include "Realm.h" #include "ReputationMgr.h" #include "ScriptMgr.h" +#include "SharedDefines.h" #include "SocialMgr.h" #include "Spell.h" +#include "SpellAuraDefines.h" #include "SpellAuraEffects.h" #include "SpellAuras.h" #include "SpellMgr.h" @@ -312,8 +314,8 @@ Player::Player(WorldSession* session): Unit(), m_mover(this) for (uint8 i = 0; i < BASEMOD_END; ++i) { - m_auraBaseMod[i][FLAT_MOD] = 0.0f; - m_auraBaseMod[i][PCT_MOD] = 1.0f; + m_auraBaseFlatMod[i] = 0.0f; + m_auraBasePctMod[i] = 1.0f; } for (uint8 i = 0; i < MAX_COMBAT_RATING; i++) @@ -831,9 +833,7 @@ int32 Player::getMaxTimer(MirrorTimerType timer) if (!IsAlive() || HasWaterBreathingAura() || GetSession()->GetSecurity() >= AccountTypes(sWorld->getIntConfig(CONFIG_DISABLE_BREATHING))) return DISABLED_MIRROR_TIMER; int32 UnderWaterTime = sWorld->getIntConfig(CONFIG_WATER_BREATH_TIMER); - AuraEffectList const& mModWaterBreathing = GetAuraEffectsByType(SPELL_AURA_MOD_WATER_BREATHING); - for (AuraEffectList::const_iterator i = mModWaterBreathing.begin(); i != mModWaterBreathing.end(); ++i) - AddPct(UnderWaterTime, (*i)->GetAmount()); + UnderWaterTime *= GetTotalAuraMultiplier(SPELL_AURA_MOD_WATER_BREATHING); return UnderWaterTime; } case FIRE_TIMER: @@ -1922,10 +1922,7 @@ void Player::Regenerate(Powers power) // Mana regen calculated in Player::UpdateManaRegen(), energy regen calculated in Player::UpdateEnergyRegen() if (power != POWER_MANA && power != POWER_ENERGY) { - AuraEffectList const& ModPowerRegenPCTAuras = GetAuraEffectsByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT); - for (AuraEffectList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i) - if (Powers((*i)->GetMiscValue()) == power) - AddPct(addvalue, (*i)->GetAmount()); + addvalue *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, power); // Butchery requires combat for this effect if (power != POWER_RUNIC_POWER || IsInCombat()) @@ -2008,11 +2005,7 @@ void Player::RegenerateHealth() addvalue *= 1.33f; } - AuraEffectList const& mModHealthRegenPct = GetAuraEffectsByType(SPELL_AURA_MOD_HEALTH_REGEN_PERCENT); - for (AuraEffectList::const_iterator i = mModHealthRegenPct.begin(); i != mModHealthRegenPct.end(); ++i) - { - AddPct(addvalue, (*i)->GetAmount()); - } + addvalue *= GetTotalAuraMultiplier(SPELL_AURA_MOD_HEALTH_REGEN_PERCENT); if (!IsInCombat()) { @@ -2666,14 +2659,14 @@ void Player::InitStatsForLevel(bool reapplyMods) // set armor (resistance 0) to original value (create_agility*2) SetArmor(int32(m_createStats[STAT_AGILITY] * 2)); - SetResistanceBuffMods(SpellSchools(0), true, 0.0f); - SetResistanceBuffMods(SpellSchools(0), false, 0.0f); + SetFloatValue(UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + AsUnderlyingType(SPELL_SCHOOL_NORMAL), 0.0f); + SetFloatValue(UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + AsUnderlyingType(SPELL_SCHOOL_NORMAL), 0.0f); // set other resistance to original value (0) for (uint8 i = 1; i < MAX_SPELL_SCHOOL; ++i) { SetResistance(SpellSchools(i), 0); - SetResistanceBuffMods(SpellSchools(i), true, 0.0f); - SetResistanceBuffMods(SpellSchools(i), false, 0.0f); + SetFloatValue(UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + i, 0.0f); + SetFloatValue(UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + i, 0.0f); } SetUInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, 0); @@ -5047,24 +5040,107 @@ void Player::ClearChannelWatch() (*itr)->RemoveWatching(this); } -void Player::HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, float amount, bool apply) +void Player::HandleBaseModFlatValue(BaseModGroup modGroup, float amount, bool apply) { if (modGroup >= BASEMOD_END) { - LOG_ERROR("entities.player", "ERROR in HandleBaseModValue(): non existed BaseModGroup!"); + LOG_ERROR("entities.player", "Player::HandleBaseModFlatValue: Invalid BaseModGroup/BaseModType ({}/{}) for player '{}' ({})", + modGroup, FLAT_MOD, GetName(), GetGUID().ToString()); return; } - switch (modType) + m_auraBaseFlatMod[modGroup] += apply ? amount : -amount; + UpdateBaseModGroup(modGroup); +} + +void Player::ApplyBaseModPctValue(BaseModGroup modGroup, float pct) +{ + if (modGroup >= BASEMOD_END) { - case FLAT_MOD: - m_auraBaseMod[modGroup][modType] += apply ? amount : -amount; + LOG_ERROR("entities.player", "Player::ApplyBaseModPctValue: Invalid BaseModGroup/BaseModType ({}/{}) for player '{}' ({})", + modGroup, PCT_MOD, GetName(), GetGUID().ToString()); + return; + } + + m_auraBasePctMod[modGroup] += CalculatePct(1.0f, pct); + UpdateBaseModGroup(modGroup); +} + +void Player::SetBaseModFlatValue(BaseModGroup modGroup, float val) +{ + if (m_auraBaseFlatMod[modGroup] == val) + return; + + m_auraBaseFlatMod[modGroup] = val; + UpdateBaseModGroup(modGroup); +} + +void Player::SetBaseModPctValue(BaseModGroup modGroup, float val) +{ + if (m_auraBasePctMod[modGroup] == val) + return; + + m_auraBasePctMod[modGroup] = val; + UpdateBaseModGroup(modGroup); +} + +void Player::UpdateDamageDoneMods(WeaponAttackType attackType, int32 skipEnchantSlot /*= -1*/) +{ + Unit::UpdateDamageDoneMods(attackType, skipEnchantSlot); + + UnitMods unitMod; + switch (attackType) + { + case BASE_ATTACK: + unitMod = UNIT_MOD_DAMAGE_MAINHAND; break; - case PCT_MOD: - ApplyPercentModFloatVar(m_auraBaseMod[modGroup][modType], amount, apply); + case OFF_ATTACK: + unitMod = UNIT_MOD_DAMAGE_OFFHAND; + break; + case RANGED_ATTACK: + unitMod = UNIT_MOD_DAMAGE_RANGED; + break; + default: + ABORT(); break; } + float amount = 0.0f; + Item* item = GetWeaponForAttack(attackType, true); + if (!item) + return; + + for (uint8 slot = 0; slot < MAX_ENCHANTMENT_SLOT; ++slot) + { + if (skipEnchantSlot == slot) + continue; + + SpellItemEnchantmentEntry const* enchantmentEntry = sSpellItemEnchantmentStore.LookupEntry(item->GetEnchantmentId(EnchantmentSlot(slot))); + if (!enchantmentEntry) + continue; + + for (uint8 i = 0; i < MAX_SPELL_ITEM_ENCHANTMENT_EFFECTS; ++i) + { + switch (enchantmentEntry->type[i]) + { + case ITEM_ENCHANTMENT_TYPE_DAMAGE: + amount += enchantmentEntry->amount[i]; + break; + case ITEM_ENCHANTMENT_TYPE_TOTEM: + if (IsClass(CLASS_SHAMAN, CLASS_CONTEXT_ABILITY)) + amount += enchantmentEntry->amount[i] * item->GetTemplate()->Delay / 1000.0f; + break; + default: + break; + } + } + } + + HandleStatFlatModifier(unitMod, TOTAL_VALUE, amount, true); +} + +void Player::UpdateBaseModGroup(BaseModGroup modGroup) +{ if (!CanModifyStats()) return; @@ -5095,10 +5171,7 @@ float Player::GetBaseModValue(BaseModGroup modGroup, BaseModType modType) const return 0.0f; } - if (modType == PCT_MOD && m_auraBaseMod[modGroup][PCT_MOD] <= 0.0f) - return 0.0f; - - return m_auraBaseMod[modGroup][modType]; + return (modType == FLAT_MOD ? m_auraBaseFlatMod[modGroup] : m_auraBasePctMod[modGroup]); } float Player::GetTotalBaseModValue(BaseModGroup modGroup) const @@ -5109,15 +5182,15 @@ float Player::GetTotalBaseModValue(BaseModGroup modGroup) const return 0.0f; } - if (m_auraBaseMod[modGroup][PCT_MOD] <= 0.0f) + if (m_auraBasePctMod[modGroup] <= 0.0f) return 0.0f; - return m_auraBaseMod[modGroup][FLAT_MOD] * m_auraBaseMod[modGroup][PCT_MOD]; + return m_auraBaseFlatMod[modGroup] * m_auraBasePctMod[modGroup]; } uint32 Player::GetShieldBlockValue() const { - float value = (m_auraBaseMod[SHIELD_BLOCK_VALUE][FLAT_MOD] + GetStat(STAT_STRENGTH) * 0.5f - 10) * m_auraBaseMod[SHIELD_BLOCK_VALUE][PCT_MOD]; + float value = (m_auraBaseFlatMod[SHIELD_BLOCK_VALUE] + GetStat(STAT_STRENGTH) * 0.5f - 10) * m_auraBasePctMod[SHIELD_BLOCK_VALUE]; value = (value < 0) ? 0 : value; @@ -5186,7 +5259,7 @@ void Player::GetDodgeFromAgility(float& diminishing, float& nondiminishing) return; /// @todo: research if talents/effects that increase total agility by x% should increase non-diminishing part - float base_agility = GetCreateStat(STAT_AGILITY) * m_auraModifiersGroup[UNIT_MOD_STAT_START + static_cast(STAT_AGILITY)][BASE_PCT]; + float base_agility = GetCreateStat(STAT_AGILITY) * GetPctModifierValue(UnitMods(UNIT_MOD_STAT_START + AsUnderlyingType(STAT_AGILITY)), BASE_PCT); float bonus_agility = GetStat(STAT_AGILITY) - base_agility; // calculate diminishing (green in char screen) and non-diminishing (white) contribution @@ -6609,20 +6682,22 @@ void Player::_ApplyItemMods(Item* item, uint8 slot, bool apply) LOG_DEBUG("entities.player", "applying mods for item {} ", item->GetGUID().ToString()); - WeaponAttackType attacktype = Player::GetAttackBySlot(slot); - if (item->HasSocket()) //only (un)equipping of items with sockets can influence metagems, so no need to waste time with normal items CorrectMetaGemEnchants(slot, apply); - if (attacktype < MAX_ATTACK) - _ApplyWeaponDependentAuraMods(item, attacktype, apply); - _ApplyItemBonuses(proto, slot, apply); if (slot == EQUIPMENT_SLOT_RANGED) _ApplyAmmoBonuses(); ApplyItemEquipSpell(item, apply); + + ApplyItemDependentAuras(item, apply); + + WeaponAttackType const attackType = Player::GetAttackBySlot(slot); + if (attackType != MAX_ATTACK) + UpdateWeaponDependentAuras(attackType); + ApplyEnchantment(item, apply); LOG_DEBUG("entities.player.items", "_ApplyItemMods complete."); @@ -6693,30 +6768,30 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply switch (statType) { case ITEM_MOD_MANA: - HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_MANA, BASE_VALUE, float(val), apply); break; case ITEM_MOD_HEALTH: // modify HP - HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(val), apply); break; case ITEM_MOD_AGILITY: // modify agility - HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply); - ApplyStatBuffMod(STAT_AGILITY, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply); + UpdateStatBuffMod(STAT_AGILITY); break; case ITEM_MOD_STRENGTH: //modify strength - HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply); - ApplyStatBuffMod(STAT_STRENGTH, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply); + UpdateStatBuffMod(STAT_STRENGTH); break; case ITEM_MOD_INTELLECT: //modify intellect - HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply); - ApplyStatBuffMod(STAT_INTELLECT, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply); + UpdateStatBuffMod(STAT_INTELLECT); break; case ITEM_MOD_SPIRIT: //modify spirit - HandleStatModifier(UNIT_MOD_STAT_SPIRIT, BASE_VALUE, float(val), apply); - ApplyStatBuffMod(STAT_SPIRIT, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_STAT_SPIRIT, BASE_VALUE, float(val), apply); + UpdateStatBuffMod(STAT_SPIRIT); break; case ITEM_MOD_STAMINA: //modify stamina - HandleStatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(val), apply); - ApplyStatBuffMod(STAT_STAMINA, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(val), apply); + UpdateStatBuffMod(STAT_STAMINA); break; case ITEM_MOD_DEFENSE_SKILL_RATING: ApplyRatingMod(CR_DEFENSE_SKILL, int32(val), apply); @@ -6805,11 +6880,11 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply ApplyRatingMod(CR_EXPERTISE, int32(val), apply); break; case ITEM_MOD_ATTACK_POWER: - HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(val), apply); - HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply); break; case ITEM_MOD_RANGED_ATTACK_POWER: - HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply); break; // case ITEM_MOD_FERAL_ATTACK_POWER: // ApplyFeralAPBonus(int32(val), apply); @@ -6830,7 +6905,7 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply ApplySpellPenetrationBonus(val, apply); break; case ITEM_MOD_BLOCK_VALUE: - HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(val), apply); + HandleBaseModFlatValue(SHIELD_BLOCK_VALUE, float(val), apply); break; /// @deprecated item mods case ITEM_MOD_SPELL_HEALING_DONE: @@ -6860,7 +6935,7 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply if (armor) { - UnitModifierType modType = TOTAL_VALUE; + UnitModifierFlatType modType = TOTAL_VALUE; if (proto->Class == ITEM_CLASS_ARMOR) { switch (proto->SubClass) @@ -6874,33 +6949,33 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply break; } } - HandleStatModifier(UNIT_MOD_ARMOR, modType, float(armor), apply); + HandleStatFlatModifier(UNIT_MOD_ARMOR, modType, float(armor), apply); } // Add armor bonus from ArmorDamageModifier if > 0 if (proto->ArmorDamageModifier > 0 && sScriptMgr->OnPlayerCanArmorDamageModifier(this)) - HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(proto->ArmorDamageModifier), apply); + HandleStatFlatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(proto->ArmorDamageModifier), apply); if (proto->Block) - HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(proto->Block), apply); + HandleBaseModFlatValue(SHIELD_BLOCK_VALUE, float(proto->Block), apply); if (proto->HolyRes) - HandleStatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(proto->HolyRes), apply); + HandleStatFlatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(proto->HolyRes), apply); if (proto->FireRes) - HandleStatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(proto->FireRes), apply); + HandleStatFlatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(proto->FireRes), apply); if (proto->NatureRes) - HandleStatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(proto->NatureRes), apply); + HandleStatFlatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(proto->NatureRes), apply); if (proto->FrostRes) - HandleStatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(proto->FrostRes), apply); + HandleStatFlatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(proto->FrostRes), apply); if (proto->ShadowRes) - HandleStatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(proto->ShadowRes), apply); + HandleStatFlatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(proto->ShadowRes), apply); if (proto->ArcaneRes) - HandleStatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(proto->ArcaneRes), apply); + HandleStatFlatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(proto->ArcaneRes), apply); WeaponAttackType attType = Player::GetAttackBySlot(slot); if (attType != MAX_ATTACK) @@ -7071,6 +7146,100 @@ void Player::UpdateItemObtainSpells(Item* item, uint8 bag, uint8 slot) ApplyItemObtainSpells(item, true); } +// this one rechecks weapon auras and stores them in BaseModGroup container +// needed for things like axe specialization applying only to axe weapons in case of dual-wield +void Player::UpdateWeaponDependentCritAuras(WeaponAttackType attackType) +{ + BaseModGroup modGroup; + switch (attackType) + { + case BASE_ATTACK: + modGroup = CRIT_PERCENTAGE; + break; + case OFF_ATTACK: + modGroup = OFFHAND_CRIT_PERCENTAGE; + break; + case RANGED_ATTACK: + modGroup = RANGED_CRIT_PERCENTAGE; + break; + default: + ABORT(); + break; + } + + float amount = 0.0f; + amount += GetTotalAuraModifier(SPELL_AURA_MOD_WEAPON_CRIT_PERCENT, std::bind(&Unit::CheckAttackFitToAuraRequirement, this, attackType, std::placeholders::_1)); + + // these auras don't have item requirement (only Combat Expertise in 3.3.5a) + amount += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_PCT); + + SetBaseModFlatValue(modGroup, amount); +} + +void Player::UpdateAllWeaponDependentCritAuras() +{ + for (uint8 i = BASE_ATTACK; i < MAX_ATTACK; ++i) + UpdateWeaponDependentCritAuras(WeaponAttackType(i)); +} + +void Player::UpdateWeaponDependentAuras(WeaponAttackType attackType) +{ + UpdateWeaponDependentCritAuras(attackType); + UpdateDamageDoneMods(attackType); + UpdateDamagePctDoneMods(attackType); +} + +void Player::ApplyItemDependentAuras(Item* item, bool apply) +{ + if (apply) + { + for (auto [spellId, playerSpell]: GetSpellMap()) + { + if (playerSpell->State == PLAYERSPELL_REMOVED) + continue; + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); + if (!spellInfo || !spellInfo->IsPassive() || spellInfo->EquippedItemClass < 0) + continue; + + if (!HasAura(spellId) && HasItemFitToSpellRequirements(spellInfo)) + AddAura(spellId, this); // no SMSG_SPELL_GO in sniff found + } + + // Check talents (they are stored separately from regular spells) + for (auto [spellId, playerTalent] : GetTalentMap()) + { + if (playerTalent->State == PLAYERSPELL_REMOVED) + continue; + + if (!(playerTalent->IsInSpec(GetActiveSpec()))) + continue; + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); + if (!spellInfo || !spellInfo->IsPassive() || spellInfo->EquippedItemClass < 0) + continue; + + if (!HasAura(spellId) && HasItemFitToSpellRequirements(spellInfo)) + AddAura(spellId, this); + } + } + else + RemoveItemDependentAurasAndCasts(item); +} + +bool Player::CheckAttackFitToAuraRequirement(WeaponAttackType attackType, AuraEffect const* aurEff) const +{ + SpellInfo const* spellInfo = aurEff->GetSpellInfo(); + if (spellInfo->EquippedItemClass == -1) + return true; + + Item* item = GetWeaponForAttack(attackType, true); + if (!item || !item->IsFitToSpellRequirements(spellInfo)) + return false; + + return true; +} + SpellSchoolMask Player::GetMeleeDamageSchoolMask(WeaponAttackType attackType /*= BASE_ATTACK*/, uint8 damageIndex /*= 0*/) const { if (Item const* weapon = GetWeaponForAttack(attackType, true)) @@ -7081,110 +7250,6 @@ SpellSchoolMask Player::GetMeleeDamageSchoolMask(WeaponAttackType attackType /*= return SPELL_SCHOOL_MASK_NORMAL; } -void Player::_ApplyWeaponDependentAuraMods(Item* item, WeaponAttackType attackType, bool apply) -{ - AuraEffectList const& auraCritList = GetAuraEffectsByType(SPELL_AURA_MOD_WEAPON_CRIT_PERCENT); - for (AuraEffectList::const_iterator itr = auraCritList.begin(); itr != auraCritList.end(); ++itr) - _ApplyWeaponDependentAuraCritMod(item, attackType, *itr, apply); - - AuraEffectList const& auraDamageFlatList = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE); - for (AuraEffectList::const_iterator itr = auraDamageFlatList.begin(); itr != auraDamageFlatList.end(); ++itr) - _ApplyWeaponDependentAuraDamageMod(item, attackType, *itr, apply); - - AuraEffectList const& auraDamagePctList = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); - for (AuraEffectList::const_iterator itr = auraDamagePctList.begin(); itr != auraDamagePctList.end(); ++itr) - _ApplyWeaponDependentAuraDamageMod(item, attackType, *itr, apply); -} - -void Player::_ApplyWeaponDependentAuraCritMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply) -{ - // don't apply mod if item is broken or cannot be used - if (item->IsBroken() || !CanUseAttackType(attackType)) - return; - - // generic not weapon specific case processes in aura code - if (aura->GetSpellInfo()->EquippedItemClass == -1) - return; - - if (!sScriptMgr->OnPlayerCanApplyWeaponDependentAuraDamageMod(this, item, attackType, aura, apply)) - return; - - BaseModGroup mod = BASEMOD_END; - switch (attackType) - { - case BASE_ATTACK: - mod = CRIT_PERCENTAGE; - break; - case OFF_ATTACK: - mod = OFFHAND_CRIT_PERCENTAGE; - break; - case RANGED_ATTACK: - mod = RANGED_CRIT_PERCENTAGE; - break; - default: - return; - } - - if (item->IsFitToSpellRequirements(aura->GetSpellInfo())) - HandleBaseModValue(mod, FLAT_MOD, float (aura->GetAmount()), apply); -} - -void Player::_ApplyWeaponDependentAuraDamageMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply) -{ - // don't apply mod if item is broken or cannot be used - if (item->IsBroken() || !CanUseAttackType(attackType)) - return; - - // ignore spell mods for not wands - if ((aura->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) == 0 && (getClassMask() & CLASSMASK_WAND_USERS) == 0) - return; - - // generic not weapon specific case processes in aura code - if (aura->GetSpellInfo()->EquippedItemClass == -1) - return; - - UnitMods unitMod = UNIT_MOD_END; - switch (attackType) - { - case BASE_ATTACK: - unitMod = UNIT_MOD_DAMAGE_MAINHAND; - break; - case OFF_ATTACK: - unitMod = UNIT_MOD_DAMAGE_OFFHAND; - break; - case RANGED_ATTACK: - unitMod = UNIT_MOD_DAMAGE_RANGED; - break; - default: - return; - } - - UnitModifierType unitModType = TOTAL_VALUE; - switch (aura->GetAuraType()) - { - case SPELL_AURA_MOD_DAMAGE_DONE: - unitModType = TOTAL_VALUE; - break; - case SPELL_AURA_MOD_DAMAGE_PERCENT_DONE: - unitModType = TOTAL_PCT; - break; - default: - return; - } - - if (item->IsFitToSpellRequirements(aura->GetSpellInfo())) - { - HandleStatModifier(unitMod, unitModType, float(aura->GetAmount()), apply); - if (unitModType == TOTAL_VALUE) - { - if (aura->GetAmount() > 0) - ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS, aura->GetAmount(), apply); - else - ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG, aura->GetAmount(), apply); - } - } -} - void Player::ApplyItemEquipSpell(Item* item, bool apply, bool form_change) { if (!item) @@ -7499,12 +7564,6 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 continue; } - if (!spellInfo->CheckElixirStacking(this)) - { - Spell::SendCastResult(this, spellInfo, cast_count, SPELL_FAILED_AURA_BOUNCED); - continue; - } - Spell* spell = new Spell(this, spellInfo, (count > 0) ? TRIGGERED_FULL_MASK : TRIGGERED_NONE); spell->m_CastItem = item; spell->m_cast_count = cast_count; // set count of casts @@ -7613,10 +7672,7 @@ void Player::_RemoveAllItemMods() if (!proto) continue; - WeaponAttackType attacktype = Player::GetAttackBySlot(i); - if (attacktype < MAX_ATTACK) - _ApplyWeaponDependentAuraMods(m_items[i], attacktype, false); - + ApplyItemDependentAuras(m_items[i], false); _ApplyItemBonuses(proto, i, false); if (i == EQUIPMENT_SLOT_RANGED) @@ -7642,12 +7698,13 @@ void Player::_ApplyAllItemMods() if (!proto) continue; - WeaponAttackType attacktype = Player::GetAttackBySlot(i); - if (attacktype < MAX_ATTACK) - _ApplyWeaponDependentAuraMods(m_items[i], attacktype, true); - + ApplyItemDependentAuras(m_items[i], true); _ApplyItemBonuses(proto, i, true); + WeaponAttackType const attackType = Player::GetAttackBySlot(i); + if (attackType != MAX_ATTACK) + UpdateWeaponDependentAuras(attackType); + if (i == EQUIPMENT_SLOT_RANGED) _ApplyAmmoBonuses(); } @@ -7872,7 +7929,9 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type) // And permit out of range GO with no owner in case fishing hole if (!go || (loot_type != LOOT_FISHINGHOLE && ((loot_type != LOOT_FISHING && loot_type != LOOT_FISHING_JUNK) || go->GetOwnerGUID() != GetGUID()) && !go->IsWithinDistInMap(this)) || (loot_type == LOOT_CORPSE && go->GetRespawnTime() && go->isSpawnedByDefault())) { - go->ForceValuesUpdateAtIndex(GAMEOBJECT_BYTES_1); + if (go) + go->ForceValuesUpdateAtIndex(GAMEOBJECT_BYTES_1); + SendLootRelease(guid); return; } @@ -12646,9 +12705,9 @@ void Player::RemoveItemDependentAurasAndCasts(Item* pItem) { Aura* aura = itr->second; - // skip passive (passive item dependent spells work in another way) and not self applied auras + // skip not self applied auras SpellInfo const* spellInfo = aura->GetSpellInfo(); - if (aura->IsPassive() || aura->GetCasterGUID() != GetGUID()) + if (aura->GetCasterGUID() != GetGUID()) { ++itr; continue; diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 1140cc984..8cb516577 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1325,7 +1325,7 @@ public: { return StoreItem(dest, pItem, update); } - void RemoveItem(uint8 bag, uint8 slot, bool update, bool swap = false); + void RemoveItem(uint8 bag, uint8 slot, bool update); void MoveItemFromInventory(uint8 bag, uint8 slot, bool update); // in trade, auction, guild bank, mail.... void MoveItemToInventory(ItemPosCountVec const& dest, Item* pItem, bool update, bool in_characterInventoryDB = false); @@ -2181,11 +2181,19 @@ public: [[nodiscard]] bool CanTameExoticPets() const { return IsGameMaster() || HasAuraType(SPELL_AURA_ALLOW_TAME_PET_TYPE); } void SetRegularAttackTime(); - void SetBaseModValue(BaseModGroup modGroup, BaseModType modType, float value) { m_auraBaseMod[modGroup][modType] = value; } - void HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, float amount, bool apply); + + void HandleBaseModFlatValue(BaseModGroup modGroup, float amount, bool apply); + void ApplyBaseModPctValue(BaseModGroup modGroup, float pct); + + void SetBaseModFlatValue(BaseModGroup modGroup, float val); + void SetBaseModPctValue(BaseModGroup modGroup, float val); + + void UpdateDamageDoneMods(WeaponAttackType attackType, int32 skipEnchantSlot = -1) override; + void UpdateBaseModGroup(BaseModGroup modGroup); + [[nodiscard]] float GetBaseModValue(BaseModGroup modGroup, BaseModType modType) const; [[nodiscard]] float GetTotalBaseModValue(BaseModGroup modGroup) const; - [[nodiscard]] float GetTotalPercentageModValue(BaseModGroup modGroup) const { return m_auraBaseMod[modGroup][FLAT_MOD] + m_auraBaseMod[modGroup][PCT_MOD]; } + void _ApplyAllStatBonuses(); void _RemoveAllStatBonuses(); @@ -2197,9 +2205,13 @@ public: SpellSchoolMask GetMeleeDamageSchoolMask(WeaponAttackType attackType = BASE_ATTACK, uint8 damageIndex = 0) const override; - void _ApplyWeaponDependentAuraMods(Item* item, WeaponAttackType attackType, bool apply); - void _ApplyWeaponDependentAuraCritMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply); - void _ApplyWeaponDependentAuraDamageMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply); + void UpdateWeaponDependentAuras(WeaponAttackType attackType); + void ApplyItemDependentAuras(Item* item, bool apply); + + bool CheckAttackFitToAuraRequirement(WeaponAttackType attackType, AuraEffect const* aurEff) const override; + + void UpdateWeaponDependentCritAuras(WeaponAttackType attackType); + void UpdateAllWeaponDependentCritAuras(); void _ApplyItemMods(Item* item, uint8 slot, bool apply); void _RemoveAllItemMods(); @@ -2825,7 +2837,8 @@ protected: ActionButtonList m_actionButtons; - float m_auraBaseMod[BASEMOD_END][MOD_END]; + float m_auraBaseFlatMod[BASEMOD_END]; + float m_auraBasePctMod[BASEMOD_END]; int32 m_baseRatingValue[MAX_COMBAT_RATING]; uint32 m_baseSpellPower; uint32 m_baseSpellDamage; diff --git a/src/server/game/Entities/Player/PlayerQuest.cpp b/src/server/game/Entities/Player/PlayerQuest.cpp index 554622bba..a2a99a4bd 100644 --- a/src/server/game/Entities/Player/PlayerQuest.cpp +++ b/src/server/game/Entities/Player/PlayerQuest.cpp @@ -1405,9 +1405,7 @@ uint32 Player::CalculateQuestRewardXP(Quest const* quest) uint32 xp = uint32(quest->XPValue(GetLevel()) * GetQuestRate(quest->IsDFQuest())); // handle SPELL_AURA_MOD_XP_QUEST_PCT auras - Unit::AuraEffectList const& ModXPPctAuras = GetAuraEffectsByType(SPELL_AURA_MOD_XP_QUEST_PCT); - for (Unit::AuraEffectList::const_iterator i = ModXPPctAuras.begin(); i != ModXPPctAuras.end(); ++i) - AddPct(xp, (*i)->GetAmount()); + xp *= GetTotalAuraMultiplier(SPELL_AURA_MOD_XP_QUEST_PCT); return xp; } diff --git a/src/server/game/Entities/Player/PlayerStorage.cpp b/src/server/game/Entities/Player/PlayerStorage.cpp index 68018e362..d636ba951 100644 --- a/src/server/game/Entities/Player/PlayerStorage.cpp +++ b/src/server/game/Entities/Player/PlayerStorage.cpp @@ -60,6 +60,7 @@ #include "StringConvert.h" #include "Tokenize.h" #include "Transport.h" +#include "Unit.h" #include "UpdateFieldFlags.h" #include "Util.h" #include "World.h" @@ -2921,7 +2922,7 @@ void Player::VisualizeItem(uint8 slot, Item* pItem) pItem->SetState(ITEM_CHANGED, this); } -void Player::RemoveItem(uint8 bag, uint8 slot, bool update, bool swap) +void Player::RemoveItem(uint8 bag, uint8 slot, bool update) { // note: removeitem does not actually change the item // it only takes the item out of storage temporarily @@ -2956,12 +2957,6 @@ void Player::RemoveItem(uint8 bag, uint8 slot, bool update, bool swap) // remove item dependent auras and casts (only weapon and armor slots) if (slot < INVENTORY_SLOT_BAG_END && slot < EQUIPMENT_SLOT_END) { - // Xinef: Ensure that this function is called for places with swap=true - if (!swap) - { - RemoveItemDependentAurasAndCasts(pItem); - } - // remove held enchantments, update expertise if (slot == EQUIPMENT_SLOT_MAINHAND) { @@ -3096,9 +3091,6 @@ void Player::DestroyItem(uint8 bag, uint8 slot, bool update) if (slot < EQUIPMENT_SLOT_END) { - // remove item dependent auras and casts (only weapon and armor slots) - RemoveItemDependentAurasAndCasts(pItem); - // update expertise and armor penetration - passive auras may need it switch (slot) { @@ -3890,8 +3882,8 @@ void Player::SwapItem(uint16 src, uint16 dst) } // now do moves, remove... - RemoveItem(dstbag, dstslot, false, true); - RemoveItem(srcbag, srcslot, false, true); + RemoveItem(dstbag, dstslot, false); + RemoveItem(srcbag, srcslot, false); // add to dest if (IsInventoryPos(dst)) @@ -4380,13 +4372,12 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool // processed in Player::CastItemCombatSpell break; case ITEM_ENCHANTMENT_TYPE_DAMAGE: - if (item->GetSlot() == EQUIPMENT_SLOT_MAINHAND) - HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(enchant_amount), apply); - else if (item->GetSlot() == EQUIPMENT_SLOT_OFFHAND) - HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(enchant_amount), apply); - else if (item->GetSlot() == EQUIPMENT_SLOT_RANGED) - HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(enchant_amount), apply); + { + WeaponAttackType const attackType = Player::GetAttackBySlot(item->GetSlot()); + if (attackType != MAX_ATTACK) + UpdateDamageDoneMods(attackType, apply ? -1 : slot); break; + } case ITEM_ENCHANTMENT_TYPE_EQUIP_SPELL: if (enchant_spell_id) { @@ -4437,7 +4428,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool } } - HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + enchant_spell_id), TOTAL_VALUE, float(enchant_amount), apply); + HandleStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + enchant_spell_id), TOTAL_VALUE, float(enchant_amount), apply); break; case ITEM_ENCHANTMENT_TYPE_STAT: { @@ -4464,36 +4455,36 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool { case ITEM_MOD_MANA: LOG_DEBUG("entities.player.items", "+ {} MANA", enchant_amount); - HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, float(enchant_amount), apply); + HandleStatFlatModifier(UNIT_MOD_MANA, BASE_VALUE, float(enchant_amount), apply); break; case ITEM_MOD_HEALTH: LOG_DEBUG("entities.player.items", "+ {} HEALTH", enchant_amount); - HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(enchant_amount), apply); + HandleStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(enchant_amount), apply); break; case ITEM_MOD_AGILITY: LOG_DEBUG("entities.player.items", "+ {} AGILITY", enchant_amount); - HandleStatModifier(UNIT_MOD_STAT_AGILITY, TOTAL_VALUE, float(enchant_amount), apply); - ApplyStatBuffMod(STAT_AGILITY, (float)enchant_amount, apply); + HandleStatFlatModifier(UNIT_MOD_STAT_AGILITY, TOTAL_VALUE, float(enchant_amount), apply); + UpdateStatBuffMod(STAT_AGILITY); break; case ITEM_MOD_STRENGTH: LOG_DEBUG("entities.player.items", "+ {} STRENGTH", enchant_amount); - HandleStatModifier(UNIT_MOD_STAT_STRENGTH, TOTAL_VALUE, float(enchant_amount), apply); - ApplyStatBuffMod(STAT_STRENGTH, (float)enchant_amount, apply); + HandleStatFlatModifier(UNIT_MOD_STAT_STRENGTH, TOTAL_VALUE, float(enchant_amount), apply); + UpdateStatBuffMod(STAT_STRENGTH); break; case ITEM_MOD_INTELLECT: LOG_DEBUG("entities.player.items", "+ {} INTELLECT", enchant_amount); - HandleStatModifier(UNIT_MOD_STAT_INTELLECT, TOTAL_VALUE, float(enchant_amount), apply); - ApplyStatBuffMod(STAT_INTELLECT, (float)enchant_amount, apply); + HandleStatFlatModifier(UNIT_MOD_STAT_INTELLECT, TOTAL_VALUE, float(enchant_amount), apply); + UpdateStatBuffMod(STAT_INTELLECT); break; case ITEM_MOD_SPIRIT: LOG_DEBUG("entities.player.items", "+ {} SPIRIT", enchant_amount); - HandleStatModifier(UNIT_MOD_STAT_SPIRIT, TOTAL_VALUE, float(enchant_amount), apply); - ApplyStatBuffMod(STAT_SPIRIT, (float)enchant_amount, apply); + HandleStatFlatModifier(UNIT_MOD_STAT_SPIRIT, TOTAL_VALUE, float(enchant_amount), apply); + UpdateStatBuffMod(STAT_SPIRIT); break; case ITEM_MOD_STAMINA: LOG_DEBUG("entities.player.items", "+ {} STAMINA", enchant_amount); - HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_VALUE, float(enchant_amount), apply); - ApplyStatBuffMod(STAT_STAMINA, (float)enchant_amount, apply); + HandleStatFlatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_VALUE, float(enchant_amount), apply); + UpdateStatBuffMod(STAT_STAMINA); break; case ITEM_MOD_DEFENSE_SKILL_RATING: ApplyRatingMod(CR_DEFENSE_SKILL, enchant_amount, apply); @@ -4604,12 +4595,12 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool LOG_DEBUG("entities.player.items", "+ {} EXPERTISE", enchant_amount); break; case ITEM_MOD_ATTACK_POWER: - HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(enchant_amount), apply); - HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply); + HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(enchant_amount), apply); + HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply); LOG_DEBUG("entities.player.items", "+ {} ATTACK_POWER", enchant_amount); break; case ITEM_MOD_RANGED_ATTACK_POWER: - HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply); + HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply); LOG_DEBUG("entities.player.items", "+ {} RANGED_ATTACK_POWER", enchant_amount); break; // case ITEM_MOD_FERAL_ATTACK_POWER: @@ -4637,7 +4628,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool LOG_DEBUG("entities.player.items", "+ {} SPELL_PENETRATION", enchant_amount); break; case ITEM_MOD_BLOCK_VALUE: - HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(enchant_amount), apply); + HandleBaseModFlatValue(SHIELD_BLOCK_VALUE, float(enchant_amount), apply); LOG_DEBUG("entities.player.items", "+ {} BLOCK_VALUE", enchant_amount); break; /// @deprecated item mods @@ -4656,20 +4647,9 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool } case ITEM_ENCHANTMENT_TYPE_TOTEM: // Shaman Rockbiter Weapon { - if (IsClass(CLASS_SHAMAN, CLASS_CONTEXT_ABILITY)) - { - float addValue = 0.0f; - if (item->GetSlot() == EQUIPMENT_SLOT_MAINHAND) - { - addValue = float(enchant_amount * item->GetTemplate()->Delay / 1000.0f); - HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, addValue, apply); - } - else if (item->GetSlot() == EQUIPMENT_SLOT_OFFHAND) - { - addValue = float(enchant_amount * item->GetTemplate()->Delay / 1000.0f); - HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, addValue, apply); - } - } + WeaponAttackType const attackType = Player::GetAttackBySlot(item->GetSlot()); + if (attackType != MAX_ATTACK) + UpdateDamageDoneMods(attackType); break; } case ITEM_ENCHANTMENT_TYPE_USE_SPELL: @@ -6333,7 +6313,7 @@ void Player::_LoadQuestStatus(PreparedQueryResult result) ++slot; } - LOG_DEBUG("entities.player.loading", "Quest status is {{}} for quest {{}} for player ({})", questStatusData.Status, quest_id, GetGUID().ToString()); + LOG_DEBUG("entities.player.loading", "Quest status is ({}) for quest ({}) for player ({})", questStatusData.Status, quest_id, GetGUID().ToString()); } } while (result->NextRow()); } @@ -6444,7 +6424,7 @@ void Player::_LoadWeeklyQuestStatus(PreparedQueryResult result) continue; m_weeklyquests.insert(quest_id); - LOG_DEBUG("entities.player.loading", "Weekly quest {{}} cooldown for player ({})", quest_id, GetGUID().ToString()); + LOG_DEBUG("entities.player.loading", "Weekly quest ({}) cooldown for player ({})", quest_id, GetGUID().ToString()); } while (result->NextRow()); } @@ -6467,7 +6447,7 @@ void Player::_LoadSeasonalQuestStatus(PreparedQueryResult result) continue; m_seasonalquests[event_id].insert(quest_id); - LOG_DEBUG("entities.player.loading", "Seasonal quest {{}} cooldown for player ({})", quest_id, GetGUID().ToString()); + LOG_DEBUG("entities.player.loading", "Seasonal quest ({}) cooldown for player ({})", quest_id, GetGUID().ToString()); } while (result->NextRow()); } @@ -6489,7 +6469,7 @@ void Player::_LoadMonthlyQuestStatus(PreparedQueryResult result) continue; m_monthlyquests.insert(quest_id); - LOG_DEBUG("entities.player.loading", "Monthly quest {{}} cooldown for player ({})", quest_id, GetGUID().ToString()); + LOG_DEBUG("entities.player.loading", "Monthly quest ({}) cooldown for player ({})", quest_id, GetGUID().ToString()); } while (result->NextRow()); } diff --git a/src/server/game/Entities/Player/PlayerUpdates.cpp b/src/server/game/Entities/Player/PlayerUpdates.cpp index b9ba72b9e..d765ec4f3 100644 --- a/src/server/game/Entities/Player/PlayerUpdates.cpp +++ b/src/server/game/Entities/Player/PlayerUpdates.cpp @@ -702,7 +702,7 @@ void Player::UpdateRating(CombatRating cr) void Player::UpdateAllRatings() { - for (int cr = 0; cr < MAX_COMBAT_RATING; ++cr) + for (uint8 cr = 0; cr < MAX_COMBAT_RATING; ++cr) UpdateRating(CombatRating(cr)); } diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index 9009bc7d7..24c025ac6 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -157,7 +157,7 @@ bool Player::UpdateStats(Stats stat) mask |= (*i)->GetMiscValue(); if (mask) { - for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating) + for (uint8 rating = 0; rating < MAX_COMBAT_RATING; ++rating) if (mask & (1 << rating)) ApplyRatingMod(CombatRating(rating), 0, true); } @@ -204,7 +204,7 @@ void Player::UpdateSpellDamageAndHealingBonus() bool Player::UpdateAllStats() { - for (int8 i = STAT_STRENGTH; i < MAX_STATS; ++i) + for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i) { float value = GetTotalStatValue(Stats(i)); SetStat(Stats(i), int32(value)); @@ -247,9 +247,9 @@ void Player::UpdateResistances(uint32 school) float value = 0.0f; UnitMods unitMod = UnitMods(UNIT_MOD_RESISTANCE_START + school); - value = GetModifierValue(unitMod, BASE_VALUE); - value *= GetModifierValue(unitMod, BASE_PCT); - value += GetModifierValue(unitMod, TOTAL_VALUE); + value = GetFlatModifierValue(unitMod, BASE_VALUE); + value *= GetPctModifierValue(unitMod, BASE_PCT); + value += GetFlatModifierValue(unitMod, TOTAL_VALUE); AuraEffectList const& mResbyIntellect = GetAuraEffectsByType(SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT); for(AuraEffectList::const_iterator i = mResbyIntellect.begin(); i != mResbyIntellect.end(); ++i) @@ -258,7 +258,7 @@ void Player::UpdateResistances(uint32 school) value += int32(GetStat(Stats((*i)->GetMiscValueB())) * (*i)->GetAmount() / 100.0f); } - value *= GetModifierValue(unitMod, TOTAL_PCT); + value *= GetPctModifierValue(unitMod, TOTAL_PCT); SetResistance(SpellSchools(school), int32(value)); } @@ -270,10 +270,10 @@ void Player::UpdateArmor() { UnitMods unitMod = UNIT_MOD_ARMOR; - float value = GetModifierValue(unitMod, BASE_VALUE); // base armor (from items) - value *= GetModifierValue(unitMod, BASE_PCT); // armor percent from items - value += GetStat(STAT_AGILITY) * 2.0f; // armor bonus from stats - value += GetModifierValue(unitMod, TOTAL_VALUE); + float value = GetFlatModifierValue(unitMod, BASE_VALUE); // base armor (from items) + value *= GetPctModifierValue(unitMod, BASE_PCT); // armor percent from items + value += GetStat(STAT_AGILITY) * 2.0f; // armor bonus from stats + value += GetFlatModifierValue(unitMod, TOTAL_VALUE); //add dynamic flat mods AuraEffectList const& mResbyIntellect = GetAuraEffectsByType(SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT); @@ -283,7 +283,7 @@ void Player::UpdateArmor() value += CalculatePct(GetStat(Stats((*i)->GetMiscValueB())), (*i)->GetAmount()); } - value *= GetModifierValue(unitMod, TOTAL_PCT); + value *= GetPctModifierValue(unitMod, TOTAL_PCT); SetArmor(int32(value)); @@ -314,10 +314,10 @@ void Player::UpdateMaxHealth() { UnitMods unitMod = UNIT_MOD_HEALTH; - float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreateHealth(); - value *= GetModifierValue(unitMod, BASE_PCT); - value += GetModifierValue(unitMod, TOTAL_VALUE) + GetHealthBonusFromStamina(); - value *= GetModifierValue(unitMod, TOTAL_PCT); + float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreateHealth(); + value *= GetPctModifierValue(unitMod, BASE_PCT); + value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + GetHealthBonusFromStamina(); + value *= GetPctModifierValue(unitMod, TOTAL_PCT); sScriptMgr->OnPlayerAfterUpdateMaxHealth(this, value); SetMaxHealth((uint32)value); @@ -329,10 +329,10 @@ void Player::UpdateMaxPower(Powers power) float bonusPower = (power == POWER_MANA && GetCreatePowers(power) > 0) ? GetManaBonusFromIntellect() : 0; - float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power); - value *= GetModifierValue(unitMod, BASE_PCT); - value += GetModifierValue(unitMod, TOTAL_VALUE) + bonusPower; - value *= GetModifierValue(unitMod, TOTAL_PCT); + float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power); + value *= GetPctModifierValue(unitMod, BASE_PCT); + value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + bonusPower; + value *= GetPctModifierValue(unitMod, TOTAL_PCT); sScriptMgr->OnPlayerAfterUpdateMaxPower(this, power, value); SetMaxPower(power, uint32(value)); @@ -487,10 +487,10 @@ void Player::UpdateAttackPowerAndDamage(bool ranged) } } - SetModifierValue(unitMod, BASE_VALUE, val2); + SetStatFlatModifier(unitMod, BASE_VALUE, val2); - float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); - float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); + float base_attPower = GetFlatModifierValue(unitMod, BASE_VALUE) * GetPctModifierValue(unitMod, BASE_PCT); + float attPowerMod = GetFlatModifierValue(unitMod, TOTAL_VALUE); //add dynamic flat mods if (ranged) @@ -514,7 +514,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged) attPowerMod += int32(GetArmor() / (*iter)->GetAmount()); } - float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; + float attPowerMultiplier = GetPctModifierValue(unitMod, TOTAL_PCT) - 1.0f; sScriptMgr->OnPlayerAfterUpdateAttackPowerAndDamage(this, level, base_attPower, attPowerMod, attPowerMultiplier, ranged); SetInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field @@ -576,10 +576,10 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo float attackSpeedMod = GetAPMultiplier(attType, normalized); - float baseValue = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 14.0f * attackSpeedMod; - float basePct = GetModifierValue(unitMod, BASE_PCT); - float totalValue = GetModifierValue(unitMod, TOTAL_VALUE); - float totalPct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f; + float baseValue = GetFlatModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 14.0f * attackSpeedMod; + float basePct = GetPctModifierValue(unitMod, BASE_PCT); + float totalValue = GetFlatModifierValue(unitMod, TOTAL_VALUE); + float totalPct = addTotalPct ? GetPctModifierValue(unitMod, TOTAL_PCT) : 1.0f; float weaponMinDamage = GetWeaponDamageRange(attType, MINDAMAGE); float weaponMaxDamage = GetWeaponDamageRange(attType, MAXDAMAGE); @@ -681,7 +681,8 @@ void Player::UpdateCritPercentage(WeaponAttackType attType) break; } - float value = GetTotalPercentageModValue(modGroup) + GetRatingBonusValue(cr); + // flat = bonus from crit auras, pct = bonus from agility, combat rating = mods from items + float value = GetBaseModValue(modGroup, FLAT_MOD) + GetBaseModValue(modGroup, PCT_MOD) + GetRatingBonusValue(cr); // Modify crit from weapon skill and maximized defense skill of same level victim difference value += (int32(GetWeaponSkillValue(attType)) - int32(GetMaxSkillValueForLevel())) * 0.04f; @@ -698,9 +699,9 @@ void Player::UpdateAllCritPercentages() { float value = GetMeleeCritFromAgility(); - SetBaseModValue(CRIT_PERCENTAGE, PCT_MOD, value); - SetBaseModValue(OFFHAND_CRIT_PERCENTAGE, PCT_MOD, value); - SetBaseModValue(RANGED_CRIT_PERCENTAGE, PCT_MOD, value); + SetBaseModPctValue(CRIT_PERCENTAGE, value); + SetBaseModPctValue(OFFHAND_CRIT_PERCENTAGE, value); + SetBaseModPctValue(RANGED_CRIT_PERCENTAGE, value); UpdateCritPercentage(BASE_ATTACK); UpdateCritPercentage(OFF_ATTACK); @@ -849,7 +850,7 @@ void Player::UpdateSpellCritChance(uint32 school) // Crit from Intellect crit += GetSpellCritFromIntellect(); // Increase crit from SPELL_AURA_MOD_SPELL_CRIT_CHANCE - crit += GetTotalAuraModifierAreaExclusive(SPELL_AURA_MOD_SPELL_CRIT_CHANCE); + crit += GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_CRIT_CHANCE); // Increase crit from SPELL_AURA_MOD_CRIT_PCT crit += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_PCT); // Increase crit by school from SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL @@ -900,16 +901,11 @@ void Player::UpdateExpertise(WeaponAttackType attack) Item* weapon = GetWeaponForAttack(attack, true); - AuraEffectList const& expAuras = GetAuraEffectsByType(SPELL_AURA_MOD_EXPERTISE); - for (AuraEffectList::const_iterator itr = expAuras.begin(); itr != expAuras.end(); ++itr) + expertise += GetTotalAuraModifier(SPELL_AURA_MOD_EXPERTISE, [weapon](AuraEffect const* aurEff) { - // item neutral spell - if ((*itr)->GetSpellInfo()->EquippedItemClass == -1) - expertise += (*itr)->GetAmount(); - // item dependent spell - else if (weapon && weapon->IsFitToSpellRequirements((*itr)->GetSpellInfo())) - expertise += (*itr)->GetAmount(); - } + return aurEff->GetSpellInfo()->EquippedItemClass == -1 || // item neutral spell + (weapon && weapon->IsFitToSpellRequirements(aurEff->GetSpellInfo())); // item dependent spell + }); if (expertise < 0) expertise = 0; @@ -1100,9 +1096,9 @@ void Creature::UpdateAttackPowerAndDamage(bool ranged) indexMulti = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER; } - float baseAttackPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); - float attackPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); - float attackPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; + float baseAttackPower = GetFlatModifierValue(unitMod, BASE_VALUE) * GetPctModifierValue(unitMod, BASE_PCT); + float attackPowerMod = GetFlatModifierValue(unitMod, TOTAL_VALUE); + float attackPowerMultiplier = GetPctModifierValue(unitMod, TOTAL_PCT) - 1.0f; SetInt32Value(index, uint32(baseAttackPower)); // UNIT_FIELD_(RANGED)_ATTACK_POWER SetInt32Value(indexMod, uint32(attackPowerMod)); // UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS @@ -1166,10 +1162,10 @@ void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, float attackPower = GetTotalAttackPowerValue(attType); float attackSpeedMulti = GetAPMultiplier(attType, normalized); - float baseValue = GetModifierValue(unitMod, BASE_VALUE) + (attackPower / 14.0f) * variance; - float basePct = GetModifierValue(unitMod, BASE_PCT) * attackSpeedMulti; - float totalValue = GetModifierValue(unitMod, TOTAL_VALUE); - float totalPct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f; + float baseValue = GetFlatModifierValue(unitMod, BASE_VALUE) + (attackPower / 14.0f) * variance; + float basePct = GetPctModifierValue(unitMod, BASE_PCT) * attackSpeedMulti; + float totalValue = GetFlatModifierValue(unitMod, TOTAL_VALUE); + float totalPct = addTotalPct ? GetPctModifierValue(unitMod, TOTAL_PCT) : 1.0f; float dmgMultiplier = GetCreatureTemplate()->DamageModifier; // = DamageModifier * _GetDamageMod(rank); minDamage = ((weaponMinDamage + baseValue) * dmgMultiplier * basePct + totalValue) * totalPct; @@ -1233,11 +1229,11 @@ bool Guardian::UpdateAllStats() void Guardian::UpdateArmor() { - float value = GetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE); - value *= GetModifierValue(UNIT_MOD_ARMOR, BASE_PCT); + float value = GetFlatModifierValue(UNIT_MOD_ARMOR, BASE_VALUE); + value *= GetPctModifierValue(UNIT_MOD_ARMOR, BASE_PCT); value += std::max(GetStat(STAT_AGILITY) - GetCreateStat(STAT_AGILITY), 0.0f) * 2.0f; - value += GetModifierValue(UNIT_MOD_ARMOR, TOTAL_VALUE); - value *= GetModifierValue(UNIT_MOD_ARMOR, TOTAL_PCT); + value += GetFlatModifierValue(UNIT_MOD_ARMOR, TOTAL_VALUE); + value *= GetPctModifierValue(UNIT_MOD_ARMOR, TOTAL_PCT); SetArmor(int32(value)); } @@ -1278,10 +1274,10 @@ void Guardian::UpdateMaxHealth() break; } - float value = GetModifierValue(unitMod, BASE_VALUE);// xinef: Do NOT add base health TWICE + GetCreateHealth(); - value *= GetModifierValue(unitMod, BASE_PCT); - value += GetModifierValue(unitMod, TOTAL_VALUE) + stamina * multiplicator; - value *= GetModifierValue(unitMod, TOTAL_PCT); + float value = GetFlatModifierValue(unitMod, BASE_VALUE);// xinef: Do NOT add base health TWICE + GetCreateHealth(); + value *= GetPctModifierValue(unitMod, BASE_PCT); + value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + stamina * multiplicator; + value *= GetPctModifierValue(unitMod, TOTAL_PCT); SetMaxHealth((uint32)value); } @@ -1311,11 +1307,11 @@ void Guardian::UpdateMaxPower(Powers power) break; } - // xinef: Do NOT add base mana TWICE - float value = GetModifierValue(unitMod, BASE_VALUE) + (power != POWER_MANA ? GetCreatePowers(power) : 0); - value *= GetModifierValue(unitMod, BASE_PCT); - value += GetModifierValue(unitMod, TOTAL_VALUE) + addValue * multiplicator; - value *= GetModifierValue(unitMod, TOTAL_PCT); + // Do NOT add base mana TWICE + float value = GetFlatModifierValue(unitMod, BASE_VALUE) + (power != POWER_MANA ? GetCreatePowers(power) : 0); + value *= GetPctModifierValue(unitMod, BASE_PCT); + value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + addValue * multiplicator; + value *= GetPctModifierValue(unitMod, TOTAL_PCT); SetMaxPower(power, uint32(value)); } @@ -1335,12 +1331,12 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged) else val = 2 * GetStat(STAT_STRENGTH) - 20.0f; - SetModifierValue(unitMod, BASE_VALUE, val); + SetStatFlatModifier(unitMod, BASE_VALUE, val); //in BASE_VALUE of UNIT_MOD_ATTACK_POWER for creatures we store data of meleeattackpower field in DB - float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); - float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); - float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; + float base_attPower = GetFlatModifierValue(unitMod, BASE_VALUE) * GetPctModifierValue(unitMod, BASE_PCT); + float attPowerMod = GetFlatModifierValue(unitMod, TOTAL_VALUE); + float attPowerMultiplier = GetPctModifierValue(unitMod, TOTAL_PCT) - 1.0f; //UNIT_FIELD_(RANGED)_ATTACK_POWER field SetInt32Value(UNIT_FIELD_ATTACK_POWER, (int32)base_attPower); @@ -1362,10 +1358,10 @@ void Guardian::UpdateDamagePhysical(WeaponAttackType attType) float att_speed = float(GetAttackTime(BASE_ATTACK)) / 1000.0f; - float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 14.0f * att_speed; - float base_pct = GetModifierValue(unitMod, BASE_PCT); - float total_value = GetModifierValue(unitMod, TOTAL_VALUE); - float total_pct = GetModifierValue(unitMod, TOTAL_PCT); + float base_value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 14.0f * att_speed; + float base_pct = GetPctModifierValue(unitMod, BASE_PCT); + float total_value = GetFlatModifierValue(unitMod, TOTAL_VALUE); + float total_pct = GetPctModifierValue(unitMod, TOTAL_PCT); float weapon_mindamage = GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE); float weapon_maxdamage = GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 2dea1a379..e75a49358 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -16,7 +16,6 @@ */ #include "Unit.h" -#include "AccountMgr.h" #include "AreaDefines.h" #include "ArenaSpectator.h" #include "Battlefield.h" @@ -35,6 +34,7 @@ #include "CreatureGroups.h" #include "DisableMgr.h" #include "DynamicVisibility.h" +#include "Errors.h" #include "GameObjectAI.h" #include "GameTime.h" #include "GridNotifiersImpl.h" @@ -54,19 +54,19 @@ #include "Player.h" #include "ReputationMgr.h" #include "ScriptMgr.h" -#include "SmartAI.h" +#include "SharedDefines.h" #include "Spell.h" +#include "SpellAuraDefines.h" #include "SpellAuraEffects.h" #include "SpellAuras.h" #include "SpellInfo.h" #include "SpellMgr.h" -#include "TargetedMovementGenerator.h" #include "TemporarySummon.h" -#include "Tokenize.h" #include "Totem.h" #include "TotemAI.h" #include "Transport.h" #include "UpdateFieldFlags.h" +#include "UpdateFields.h" #include "Util.h" #include "Vehicle.h" #include "World.h" @@ -268,13 +268,13 @@ Unit::Unit() : WorldObject(), for (uint8 i = 0; i < UNIT_MOD_END; ++i) { - m_auraModifiersGroup[i][BASE_VALUE] = 0.0f; - m_auraModifiersGroup[i][BASE_PCT] = 1.0f; - m_auraModifiersGroup[i][TOTAL_VALUE] = 0.0f; - m_auraModifiersGroup[i][TOTAL_PCT] = 1.0f; + m_auraFlatModifiersGroup[i][BASE_VALUE] = 0.0f; + m_auraFlatModifiersGroup[i][TOTAL_VALUE] = 0.0f; + m_auraPctModifiersGroup[i][BASE_PCT] = 1.0f; + m_auraPctModifiersGroup[i][TOTAL_PCT] = 1.0f; } // implement 50% base damage from offhand - m_auraModifiersGroup[UNIT_MOD_DAMAGE_OFFHAND][TOTAL_PCT] = 0.5f; + m_auraPctModifiersGroup[UNIT_MOD_DAMAGE_OFFHAND][TOTAL_PCT] = 0.5f; for (uint8 i = 0; i < MAX_ATTACK; ++i) { @@ -628,7 +628,7 @@ void Unit::UpdateSplinePosition() //if (HasUnitState(UNIT_STATE_CANNOT_TURN)) // loc.orientation = GetOrientation(); - if (IsPlayer()) + if (IsPlayer() || IsPet()) UpdatePosition(loc.x, loc.y, loc.z, loc.orientation); else ToCreature()->SetPosition(loc.x, loc.y, loc.z, loc.orientation); @@ -2095,22 +2095,22 @@ uint32 Unit::CalcArmorReducedDamage(Unit const* attacker, Unit const* victim, co if (attacker->IsPlayer()) { float bonusPct = 0; - AuraEffectList const& armorPenAuras = attacker->GetAuraEffectsByType(SPELL_AURA_MOD_ARMOR_PENETRATION_PCT); - for (AuraEffectList::const_iterator itr = armorPenAuras.begin(); itr != armorPenAuras.end(); ++itr) + bonusPct += attacker->GetTotalAuraModifier(SPELL_AURA_MOD_ARMOR_PENETRATION_PCT, [spellInfo,attacker](AuraEffect const* aurEff) { - if ((*itr)->GetSpellInfo()->EquippedItemClass == -1) + if (aurEff->GetSpellInfo()->EquippedItemClass == -1) { - if (!spellInfo || (*itr)->IsAffectedOnSpell(spellInfo) || (*itr)->GetMiscValue() & spellInfo->GetSchoolMask()) - bonusPct += (*itr)->GetAmount(); - else if (!(*itr)->GetMiscValue() && !(*itr)->HasSpellClassMask()) - bonusPct += (*itr)->GetAmount(); + if (!spellInfo || aurEff->IsAffectedOnSpell(spellInfo) || aurEff->GetMiscValue() & spellInfo->GetSchoolMask()) + return true; + else if (!aurEff->GetMiscValue() && !aurEff->HasSpellClassMask()) + return true; } else { - if (attacker->ToPlayer()->HasItemFitToSpellRequirements((*itr)->GetSpellInfo())) - bonusPct += (*itr)->GetAmount(); + if (attacker->ToPlayer()->HasItemFitToSpellRequirements(aurEff->GetSpellInfo())) + return true; } - } + return false; + }); float maxArmorPen = 0; if (victim->GetLevel() < 60) @@ -3533,10 +3533,8 @@ SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spell, bool Ca if (CanReflect) { int32 reflectchance = victim->GetTotalAuraModifier(SPELL_AURA_REFLECT_SPELLS); - Unit::AuraEffectList const& mReflectSpellsSchool = victim->GetAuraEffectsByType(SPELL_AURA_REFLECT_SPELLS_SCHOOL); - for (Unit::AuraEffectList::const_iterator i = mReflectSpellsSchool.begin(); i != mReflectSpellsSchool.end(); ++i) - if ((*i)->GetMiscValue() & spell->GetSchoolMask()) - reflectchance += (*i)->GetAmount(); + reflectchance += victim->GetTotalAuraModifierByMiscMask(SPELL_AURA_REFLECT_SPELLS_SCHOOL, spell->GetSchoolMask()); + if (reflectchance > 0 && roll_chance_i(reflectchance)) { // Start triggers for remove charges if need (trigger only for victim, and mark as active spell) @@ -3610,14 +3608,7 @@ SpellMissInfo Unit::SpellHitResult(Unit* victim, Spell const* spell, bool CanRef if (CanReflect) { int32 reflectchance = victim->GetTotalAuraModifier(SPELL_AURA_REFLECT_SPELLS); - Unit::AuraEffectList const& mReflectSpellsSchool = victim->GetAuraEffectsByType(SPELL_AURA_REFLECT_SPELLS_SCHOOL); - for (Unit::AuraEffectList::const_iterator i = mReflectSpellsSchool.begin(); i != mReflectSpellsSchool.end(); ++i) - { - if ((*i)->GetMiscValue() & spell->GetSpellSchoolMask()) - { - reflectchance += (*i)->GetAmount(); - } - } + reflectchance += victim->GetTotalAuraModifierByMiscMask(SPELL_AURA_REFLECT_SPELLS_SCHOOL, spellInfo->GetSchoolMask()); if (reflectchance > 0 && roll_chance_i(reflectchance)) { @@ -3798,14 +3789,10 @@ float Unit::GetUnitCriticalChance(WeaponAttackType attackType, Unit const* victi else crit += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE); - AuraEffectList const& mTotalAuraList = victim->GetAuraEffectsByType(SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + crit += victim->GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER, [this](AuraEffect const* aurEff) { - if (GetGUID() != (*i)->GetCasterGUID()) - continue; - - crit += (*i)->GetAmount(); - } + return GetGUID() == aurEff->GetCasterGUID(); + }); // reduce crit chance from Rating for players if (attackType != RANGED_ATTACK) @@ -4419,16 +4406,85 @@ void Unit::DeMorph() SetDisplayId(GetNativeDisplayId()); } +int32 Unit::GetHighestExclusiveSameEffectSpellGroupValue(AuraEffect const* aurEff, AuraType auraType, bool checkMiscValue /*= false*/, int32 miscValue /*= 0*/) const +{ + int32 val = 0; + SpellSpellGroupMapBounds spellGroup = sSpellMgr->GetSpellSpellGroupMapBounds(aurEff->GetSpellInfo()->GetFirstRankSpell()->Id); + for (SpellSpellGroupMap::const_iterator itr = spellGroup.first; itr != spellGroup.second ; ++itr) + { + if (sSpellMgr->GetSpellGroupStackRule(itr->second) == SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT) + { + AuraEffectList const& auraEffList = GetAuraEffectsByType(auraType); + for (AuraEffectList::const_iterator auraItr = auraEffList.begin(); auraItr != auraEffList.end(); ++auraItr) + { + if (aurEff != (*auraItr) && (!checkMiscValue || (*auraItr)->GetMiscValue() == miscValue) && + sSpellMgr->IsSpellMemberOfSpellGroup((*auraItr)->GetSpellInfo()->Id, itr->second)) + { + // absolute value only + if (abs(val) < abs((*auraItr)->GetAmount())) + val = (*auraItr)->GetAmount(); + } + } + } + } + return val; +} + +bool Unit::IsHighestExclusiveAura(Aura const* aura, bool removeOtherAuraApplications /*= false*/) +{ + for (uint32 i = 0 ; i < MAX_SPELL_EFFECTS; ++i) + if (AuraEffect const* aurEff = aura->GetEffect(i)) + if (!IsHighestExclusiveAuraEffect(aura->GetSpellInfo(), aurEff->GetAuraType(), aurEff->GetAmount(), aura->GetEffectMask(), removeOtherAuraApplications)) + return false; + + return true; +} + +bool Unit::IsHighestExclusiveAuraEffect(SpellInfo const* spellInfo, AuraType auraType, int32 effectAmount, uint8 auraEffectMask, bool removeOtherAuraApplications /*= false*/) +{ + AuraEffectList const& auras = GetAuraEffectsByType(auraType); + for (Unit::AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end();) + { + AuraEffect const* existingAurEff = (*itr); + ++itr; + + if (sSpellMgr->CheckSpellGroupStackRules(spellInfo, existingAurEff->GetSpellInfo()) == SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST) + { + int32 diff = abs(effectAmount) - abs(existingAurEff->GetAmount()); + if (!diff) + for (int32 i = 0; i < MAX_SPELL_EFFECTS; ++i) + diff += int32((auraEffectMask & (1 << i)) >> i) - int32((existingAurEff->GetBase()->GetEffectMask() & (1 << i)) >> i); + + if (diff > 0) + { + Aura const* base = existingAurEff->GetBase(); + // no removing of area auras from the original owner, as that completely cancels them + if (removeOtherAuraApplications && (!base->IsArea() || base->GetOwner() != this)) + { + if (AuraApplication* aurApp = existingAurEff->GetBase()->GetApplicationOfTarget(GetGUID())) + { + bool hasMoreThanOneEffect = base->HasMoreThanOneEffectForType(auraType); + uint32 removedAuras = m_removedAurasCount; + RemoveAura(aurApp); + if (hasMoreThanOneEffect || m_removedAurasCount > removedAuras) + itr = auras.begin(); + } + } + } + else if (diff < 0) + return false; + } + } + + return true; +} + Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 effMask, Unit* caster, int32* baseAmount /*= nullptr*/, Item* castItem /*= nullptr*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, bool periodicReset /*= false*/) { ASSERT(casterGUID || caster); if (!casterGUID) casterGUID = caster->GetGUID(); - // Xinef: Hax for mixology, best solution qq - if (sSpellMgr->GetSpellGroup(newAura->Id) == 1) - return nullptr; - // passive and Incanter's Absorption and auras with different type can stack with themselves any number of times if (!newAura->IsMultiSlotAura()) { @@ -4484,7 +4540,7 @@ void Unit::_AddAura(UnitAura* aura, Unit* caster) ASSERT(!m_cleanupDone); m_ownedAuras.insert(AuraMap::value_type(aura->GetId(), aura)); - _RemoveNoStackAurasDueToAura(aura); + _RemoveNoStackAurasDueToAura(aura, true); if (aura->IsRemoved()) return; @@ -4574,7 +4630,7 @@ void Unit::_ApplyAura(AuraApplication* aurApp, uint8 effMask) { Aura* aura = aurApp->GetBase(); - _RemoveNoStackAurasDueToAura(aura); + _RemoveNoStackAurasDueToAura(aura, false); if (aurApp->GetRemoveMode()) return; @@ -4732,7 +4788,7 @@ void Unit::_UnapplyAura(AuraApplication* aurApp, AuraRemoveMode removeMode) ABORT(); } -void Unit::_RemoveNoStackAurasDueToAura(Aura* aura) +void Unit::_RemoveNoStackAurasDueToAura(Aura* aura, bool owned) { //SpellInfo const* spellProto = aura->GetSpellInfo(); @@ -4742,23 +4798,17 @@ void Unit::_RemoveNoStackAurasDueToAura(Aura* aura) // if (spellProto->IsPassiveStackableWithRanks()) // return; - bool remove = false; - for (AuraApplicationMap::iterator i = m_appliedAuras.begin(); i != m_appliedAuras.end(); ++i) + ASSERT(aura); + if (!IsHighestExclusiveAura(aura)) { - if (remove) - { - remove = false; - i = m_appliedAuras.begin(); - } - - if (aura->CanStackWith(i->second->GetBase(), true)) - continue; - - RemoveAura(i, AURA_REMOVE_BY_DEFAULT); - if (i == m_appliedAuras.end()) - break; - remove = true; + aura->Remove(); + return; } + + if (owned) + RemoveOwnedAuras([aura](Aura const* ownedAura) { return !aura->CanStackWith(ownedAura); }); + else + RemoveAppliedAuras([aura](AuraApplication const* appliedAura) { return !aura->CanStackWith(appliedAura->GetBase()); }); } void Unit::_RegisterAuraEffect(AuraEffect* aurEff, bool apply) @@ -5986,232 +6036,309 @@ uint32 Unit::GetDoTsByCaster(ObjectGuid casterGUID) const return dots; } -int32 Unit::GetTotalAuraModifierAreaExclusive(AuraType auratype) const +int32 Unit::GetTotalAuraModifier(AuraType auraType, std::function const& predicate) const { - int32 modifier = 0; - int32 areaModifier = 0; + AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auraType); + if (mTotalAuraList.empty()) + return 0; - AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + std::map sameEffectSpellGroup; + int32 modifier = 0; + + for (AuraEffect const* aurEff : mTotalAuraList) { - if ((*i)->GetSpellInfo()->HasAreaAuraEffect()) + if (predicate(aurEff)) { - if (areaModifier < (*i)->GetAmount()) - areaModifier = (*i)->GetAmount(); + // Check if the Aura Effect has a the Same Effect Stack Rule and if so, use the highest amount of that SpellGroup + // If the Aura Effect does not have this Stack Rule, it returns false so we can add to the multiplier as usual + if (!sSpellMgr->AddSameEffectStackRuleSpellGroups(aurEff->GetSpellInfo(), static_cast(auraType), aurEff->GetAmount(), sameEffectSpellGroup)) + modifier += aurEff->GetAmount(); } - else - modifier += (*i)->GetAmount(); } - return modifier + areaModifier; + // Add the highest of the Same Effect Stack Rule SpellGroups to the accumulator + for (auto const& [_, amount] : sameEffectSpellGroup) + modifier += amount; + + return modifier; } -int32 Unit::GetTotalAuraModifier(AuraType auratype) const +float Unit::GetTotalAuraMultiplier(AuraType auraType, std::function const& predicate) const { - AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); + AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auraType); + if (mTotalAuraList.empty()) + return 1.0f; + + std::map sameEffectSpellGroup; + float multiplier = 1.0f; + + for (AuraEffect const* aurEff : mTotalAuraList) + { + if (predicate(aurEff)) + { + // Check if the Aura Effect has a the Same Effect Stack Rule and if so, use the highest amount of that SpellGroup + // If the Aura Effect does not have this Stack Rule, it returns false so we can add to the multiplier as usual + if (!sSpellMgr->AddSameEffectStackRuleSpellGroups(aurEff->GetSpellInfo(), static_cast(auraType), aurEff->GetAmount(), sameEffectSpellGroup)) + AddPct(multiplier, aurEff->GetAmount()); + } + } + + // Add the highest of the Same Effect Stack Rule SpellGroups to the multiplier + for (auto itr = sameEffectSpellGroup.begin(); itr != sameEffectSpellGroup.end(); ++itr) + AddPct(multiplier, itr->second); + + return multiplier; +} + +int32 Unit::GetMaxPositiveAuraModifier(AuraType auraType, std::function const& predicate) const +{ + AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auraType); if (mTotalAuraList.empty()) return 0; int32 modifier = 0; - - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) - modifier += (*i)->GetAmount(); - - return modifier; -} - -float Unit::GetTotalAuraMultiplier(AuraType auratype) const -{ - float multiplier = 1.0f; - - AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) - AddPct(multiplier, (*i)->GetAmount()); - - return multiplier; -} - -int32 Unit::GetMaxPositiveAuraModifier(AuraType auratype) -{ - int32 modifier = 0; - - AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + for (AuraEffect const* aurEff : mTotalAuraList) { - if ((*i)->GetAmount() > modifier) - modifier = (*i)->GetAmount(); + if (predicate(aurEff)) + modifier = std::max(modifier, aurEff->GetAmount()); } return modifier; } -int32 Unit::GetMaxNegativeAuraModifier(AuraType auratype) const +int32 Unit::GetMaxNegativeAuraModifier(AuraType auraType, std::function const& predicate) const { + AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auraType); + if (mTotalAuraList.empty()) + return 0; + int32 modifier = 0; - - AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) - if ((*i)->GetAmount() < modifier) - modifier = (*i)->GetAmount(); - - return modifier; -} - -int32 Unit::GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const -{ - int32 modifier = 0; - - AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + for (AuraEffect const* aurEff : mTotalAuraList) { - if ((*i)->GetMiscValue()& misc_mask) - modifier += (*i)->GetAmount(); - } - return modifier; -} - -float Unit::GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const -{ - float multiplier = 1.0f; - - AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) - if (((*i)->GetMiscValue() & misc_mask)) - AddPct(multiplier, (*i)->GetAmount()); - - return multiplier; -} - -int32 Unit::GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask, const AuraEffect* except) const -{ - int32 modifier = 0; - - AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) - { - if (except != (*i) && (*i)->GetMiscValue()& misc_mask && (*i)->GetAmount() > modifier) - modifier = (*i)->GetAmount(); + if (predicate(aurEff)) + modifier = std::min(modifier, aurEff->GetAmount()); } return modifier; } -int32 Unit::GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const +int32 Unit::GetTotalAuraModifier(AuraType auraType) const { - int32 modifier = 0; + return GetTotalAuraModifier(auraType, [](AuraEffect const* /*aurEff*/) { return true; }); +} - AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) +float Unit::GetTotalAuraMultiplier(AuraType auraType) const +{ + return GetTotalAuraMultiplier(auraType, [](AuraEffect const* /*aurEff*/) { return true; }); +} + +int32 Unit::GetMaxPositiveAuraModifier(AuraType auraType) const +{ + return GetMaxPositiveAuraModifier(auraType, [](AuraEffect const* /*aurEff*/) { return true; }); +} + +int32 Unit::GetMaxNegativeAuraModifier(AuraType auraType) const +{ + return GetMaxNegativeAuraModifier(auraType, [](AuraEffect const* /*aurEff*/) { return true; }); +} + +int32 Unit::GetTotalAuraModifierByMiscMask(AuraType auraType, uint32 miscMask) const +{ + return GetTotalAuraModifier(auraType, [miscMask](AuraEffect const* aurEff) -> bool { - if ((*i)->GetMiscValue()& misc_mask && (*i)->GetAmount() < modifier) - modifier = (*i)->GetAmount(); - } - - return modifier; + if ((aurEff->GetMiscValue() & miscMask) != 0) + return true; + return false; + }); } -int32 Unit::GetTotalAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const +float Unit::GetTotalAuraMultiplierByMiscMask(AuraType auraType, uint32 miscMask) const { - int32 modifier = 0; - - AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) - if ((*i)->GetMiscValue() == misc_value) - modifier += (*i)->GetAmount(); - - return modifier; -} - -float Unit::GetTotalAuraMultiplierByMiscValue(AuraType auratype, int32 misc_value) const -{ - float multiplier = 1.0f; - - AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) - if ((*i)->GetMiscValue() == misc_value) - AddPct(multiplier, (*i)->GetAmount()); - - return multiplier; -} - -int32 Unit::GetMaxPositiveAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const -{ - int32 modifier = 0; - - AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + return GetTotalAuraMultiplier(auraType, [miscMask](AuraEffect const* aurEff) -> bool { - if ((*i)->GetMiscValue() == misc_value && (*i)->GetAmount() > modifier) - modifier = (*i)->GetAmount(); - } - - return modifier; + if ((aurEff->GetMiscValue() & miscMask) != 0) + return true; + return false; + }); } -int32 Unit::GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const +int32 Unit::GetMaxPositiveAuraModifierByMiscMask(AuraType auraType, uint32 miscMask, AuraEffect const* except /*= nullptr*/) const { - int32 modifier = 0; - - AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + return GetMaxPositiveAuraModifier(auraType, [miscMask, except](AuraEffect const* aurEff) -> bool { - if ((*i)->GetMiscValue() == misc_value && (*i)->GetAmount() < modifier) - modifier = (*i)->GetAmount(); - } - - return modifier; + if (except != aurEff && (aurEff->GetMiscValue() & miscMask) != 0) + return true; + return false; + }); } -int32 Unit::GetTotalAuraModifierByAffectMask(AuraType auratype, SpellInfo const* affectedSpell) const +int32 Unit::GetMaxNegativeAuraModifierByMiscMask(AuraType auraType, uint32 miscMask) const { - int32 modifier = 0; - - AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) - if ((*i)->IsAffectedOnSpell(affectedSpell)) - modifier += (*i)->GetAmount(); - - return modifier; -} - -float Unit::GetTotalAuraMultiplierByAffectMask(AuraType auratype, SpellInfo const* affectedSpell) const -{ - float multiplier = 1.0f; - - AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) - if ((*i)->IsAffectedOnSpell(affectedSpell)) - AddPct(multiplier, (*i)->GetAmount()); - - return multiplier; -} - -int32 Unit::GetMaxPositiveAuraModifierByAffectMask(AuraType auratype, SpellInfo const* affectedSpell) const -{ - int32 modifier = 0; - - AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + return GetMaxNegativeAuraModifier(auraType, [miscMask](AuraEffect const* aurEff) -> bool { - if ((*i)->IsAffectedOnSpell(affectedSpell) && (*i)->GetAmount() > modifier) - modifier = (*i)->GetAmount(); - } - - return modifier; + if ((aurEff->GetMiscValue() & miscMask) != 0) + return true; + return false; + }); } -int32 Unit::GetMaxNegativeAuraModifierByAffectMask(AuraType auratype, SpellInfo const* affectedSpell) const +int32 Unit::GetTotalAuraModifierByMiscValue(AuraType auraType, int32 miscValue) const { - int32 modifier = 0; - - AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + return GetTotalAuraModifier(auraType, [miscValue](AuraEffect const* aurEff) -> bool { - if ((*i)->IsAffectedOnSpell(affectedSpell) && (*i)->GetAmount() < modifier) - modifier = (*i)->GetAmount(); - } + if (aurEff->GetMiscValue() == miscValue) + return true; + return false; + }); +} - return modifier; +float Unit::GetTotalAuraMultiplierByMiscValue(AuraType auraType, int32 miscValue) const +{ + return GetTotalAuraMultiplier(auraType, [miscValue](AuraEffect const* aurEff) -> bool + { + if (aurEff->GetMiscValue() == miscValue) + return true; + return false; + }); +} + +int32 Unit::GetMaxPositiveAuraModifierByMiscValue(AuraType auraType, int32 miscValue) const +{ + return GetMaxPositiveAuraModifier(auraType, [miscValue](AuraEffect const* aurEff) -> bool + { + if (aurEff->GetMiscValue() == miscValue) + return true; + return false; + }); +} + +int32 Unit::GetMaxNegativeAuraModifierByMiscValue(AuraType auraType, int32 miscValue) const +{ + return GetMaxNegativeAuraModifier(auraType, [miscValue](AuraEffect const* aurEff) -> bool + { + if (aurEff->GetMiscValue() == miscValue) + return true; + return false; + }); +} + +int32 Unit::GetTotalAuraModifierByAffectMask(AuraType auraType, SpellInfo const* affectedSpell) const +{ + return GetTotalAuraModifier(auraType, [affectedSpell](AuraEffect const* aurEff) -> bool + { + if (aurEff->IsAffectedOnSpell(affectedSpell)) + return true; + return false; + }); +} + +float Unit::GetTotalAuraMultiplierByAffectMask(AuraType auraType, SpellInfo const* affectedSpell) const +{ + return GetTotalAuraMultiplier(auraType, [affectedSpell](AuraEffect const* aurEff) -> bool + { + if (aurEff->IsAffectedOnSpell(affectedSpell)) + return true; + return false; + }); +} + +int32 Unit::GetMaxPositiveAuraModifierByAffectMask(AuraType auraType, SpellInfo const* affectedSpell) const +{ + return GetMaxPositiveAuraModifier(auraType, [affectedSpell](AuraEffect const* aurEff) -> bool + { + if (aurEff->IsAffectedOnSpell(affectedSpell)) + return true; + return false; + }); +} + +int32 Unit::GetMaxNegativeAuraModifierByAffectMask(AuraType auraType, SpellInfo const* affectedSpell) const +{ + return GetMaxNegativeAuraModifier(auraType, [affectedSpell](AuraEffect const* aurEff) -> bool + { + if (aurEff->IsAffectedOnSpell(affectedSpell)) + return true; + return false; + }); +} + +void Unit::UpdateResistanceBuffModsMod(SpellSchools school) +{ + float modPos = 0.0f; + float modNeg = 0.0f; + + // these auras are always positive + modPos = GetMaxPositiveAuraModifierByMiscMask(SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE, 1 << school); + modPos += GetTotalAuraModifier(SPELL_AURA_MOD_RESISTANCE, [school](AuraEffect const* aurEff) -> bool + { + if ((aurEff->GetMiscValue() & (1 << school)) && aurEff->GetAmount() > 0) + return true; + return false; + }); + + modNeg = GetTotalAuraModifier(SPELL_AURA_MOD_RESISTANCE, [school](AuraEffect const* aurEff) -> bool + { + if ((aurEff->GetMiscValue() & (1 << school)) && aurEff->GetAmount() < 0) + return true; + return false; + }); + + float factor = GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_RESISTANCE_PCT, 1 << school); + modPos *= factor; + modNeg *= factor; + + SetFloatValue(UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + AsUnderlyingType(school), modPos); + SetFloatValue(UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + AsUnderlyingType(school), modNeg); +} + +void Unit::UpdateStatBuffMod(Stats stat) +{ + float modPos = 0.0f; + float modNeg = 0.0f; + float factor = 0.0f; + + UnitMods const unitMod = static_cast(UNIT_MOD_STAT_START + AsUnderlyingType(stat)); + + // includes value from items and enchantments + float modValue = GetFlatModifierValue(unitMod, BASE_VALUE); + if (modValue > 0.f) + modPos += modValue; + else + modNeg += modValue; + + modPos += GetTotalAuraModifier(SPELL_AURA_MOD_STAT, [stat](AuraEffect const* aurEff) -> bool + { + if ((aurEff->GetMiscValue() < 0 || aurEff->GetMiscValue() == stat) && aurEff->GetAmount() > 0) + return true; + return false; + }); + + modNeg += GetTotalAuraModifier(SPELL_AURA_MOD_STAT, [stat](AuraEffect const* aurEff) -> bool + { + if ((aurEff->GetMiscValue() < 0 || aurEff->GetMiscValue() == stat) && aurEff->GetAmount() < 0) + return true; + return false; + }); + + factor = GetTotalAuraMultiplier(SPELL_AURA_MOD_PERCENT_STAT, [stat](AuraEffect const* aurEff) -> bool + { + if (aurEff->GetMiscValue() == -1 || aurEff->GetMiscValue() == stat) + return true; + return false; + }); + + factor *= GetTotalAuraMultiplier(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, [stat](AuraEffect const* aurEff) -> bool + { + if (aurEff->GetMiscValue() == -1 || aurEff->GetMiscValue() == stat) + return true; + return false; + }); + + modPos *= factor; + modNeg *= factor; + + SetFloatValue(UNIT_FIELD_POSSTAT0 + AsUnderlyingType(stat), modPos); + SetFloatValue(UNIT_FIELD_NEGSTAT0 + AsUnderlyingType(stat), modNeg); } void Unit::_RegisterDynObject(DynamicObject* dynObj) @@ -11392,44 +11519,41 @@ float Unit::SpellPctDamageModsDone(Unit* victim, SpellInfo const* spellProto, Da // Done total percent damage auras float DoneTotalMod = 1.0f; - AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); - for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i) + DoneTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, [spellProto, this, damagetype](AuraEffect const* aurEff) { // prevent apply mods from weapon specific case to non weapon specific spells (Example: thunder clap and two-handed weapon specialization) - if (spellProto->EquippedItemClass == -1 && (*i)->GetSpellInfo()->EquippedItemClass != -1 && - !(*i)->GetSpellInfo()->HasAttribute(SPELL_ATTR5_AURA_AFFECTS_NOT_JUST_REQ_EQUIPPED_ITEM) && (*i)->GetMiscValue() == SPELL_SCHOOL_MASK_NORMAL) + if (spellProto->EquippedItemClass == -1 && aurEff->GetSpellInfo()->EquippedItemClass != -1 && + !aurEff->GetSpellInfo()->HasAttribute(SPELL_ATTR5_AURA_AFFECTS_NOT_JUST_REQ_EQUIPPED_ITEM) && aurEff->GetMiscValue() == SPELL_SCHOOL_MASK_NORMAL) { - continue; - } - - if (!spellProto->ValidateAttribute6SpellDamageMods(this, *i, damagetype == DOT)) - continue; - - if (!sScriptMgr->IsNeedModSpellDamagePercent(this, *i, DoneTotalMod, spellProto)) - continue; - - if ((*i)->GetMiscValue() & spellProto->GetSchoolMask()) - { - if ((*i)->GetSpellInfo()->EquippedItemClass == -1) - AddPct(DoneTotalMod, (*i)->GetAmount()); - else if (!(*i)->GetSpellInfo()->HasAttribute(SPELL_ATTR5_AURA_AFFECTS_NOT_JUST_REQ_EQUIPPED_ITEM) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0)) - AddPct(DoneTotalMod, (*i)->GetAmount()); - else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements((*i)->GetSpellInfo())) - AddPct(DoneTotalMod, (*i)->GetAmount()); - } + return false; } + if (!spellProto->ValidateAttribute6SpellDamageMods(this, aurEff, damagetype == DOT)) + return false; + + if (aurEff->GetMiscValue() & spellProto->GetSchoolMask()) + { + if (aurEff->GetSpellInfo()->EquippedItemClass == -1) + return true; + else if (!aurEff->GetSpellInfo()->HasAttribute(SPELL_ATTR5_AURA_AFFECTS_NOT_JUST_REQ_EQUIPPED_ITEM) && (aurEff->GetSpellInfo()->EquippedItemSubClassMask == 0)) + return true; + else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements(aurEff->GetSpellInfo())) + return true; + } + return false; + }); + uint32 creatureTypeMask = victim->GetCreatureTypeMask(); - AuraEffectList const& mDamageDoneVersus = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS); - for (AuraEffectList::const_iterator i = mDamageDoneVersus.begin(); i != mDamageDoneVersus.end(); ++i) - if ((creatureTypeMask & uint32((*i)->GetMiscValue())) && spellProto->ValidateAttribute6SpellDamageMods(this, *i, damagetype == DOT)) - AddPct(DoneTotalMod, (*i)->GetAmount()); + DoneTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS, [creatureTypeMask, spellProto, damagetype, this](AuraEffect const* aurEff) + { + return creatureTypeMask & aurEff->GetMiscValue() && spellProto->ValidateAttribute6SpellDamageMods(this, aurEff, damagetype == DOT); + }); // bonus against aurastate - AuraEffectList const& mDamageDoneVersusAurastate = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS_AURASTATE); - for (AuraEffectList::const_iterator i = mDamageDoneVersusAurastate.begin(); i != mDamageDoneVersusAurastate.end(); ++i) - if (victim->HasAuraState(AuraStateType((*i)->GetMiscValue())) && spellProto->ValidateAttribute6SpellDamageMods(this, *i, damagetype == DOT)) - AddPct(DoneTotalMod, (*i)->GetAmount()); + DoneTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS_AURASTATE, [victim, spellProto, damagetype, this](AuraEffect const* aurEff) + { + return victim->HasAuraState(AuraStateType(aurEff->GetMiscValue())) && spellProto->ValidateAttribute6SpellDamageMods(this, aurEff, damagetype == DOT); + }); // done scripted mod (take it from owner) Unit* owner = GetOwner() ? GetOwner() : this; @@ -11881,22 +12005,19 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui // from positive and negative SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN // multiplicative bonus, for example Dispersion + Shadowform (0.10*0.85=0.085) - AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) - if (((*i)->GetMiscValue() & spellProto->GetSchoolMask())) - if (spellProto->ValidateAttribute6SpellDamageMods(caster, *i, damagetype == DOT)) - AddPct(TakenTotalMod, (*i)->GetAmount()); + TakenTotalMod *= GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, spellProto->GetSchoolMask()); TakenTotalMod = processDummyAuras(TakenTotalMod); // From caster spells if (caster) { - AuraEffectList const& mOwnerTaken = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER); - for (AuraEffectList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i) - if ((*i)->GetCasterGUID() == caster->GetGUID() && (*i)->IsAffectedOnSpell(spellProto)) - if (spellProto->ValidateAttribute6SpellDamageMods(caster, *i, damagetype == DOT)) - AddPct(TakenTotalMod, (*i)->GetAmount()); + TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_DAMAGE_FROM_CASTER, [caster, spellProto](AuraEffect const* aurEff) -> bool + { + if (aurEff->GetCasterGUID() == caster->GetGUID() && aurEff->IsAffectedOnSpell(spellProto)) + return true; + return false; + }); } if (uint32 mechanicMask = spellProto->GetAllEffectsMechanicMask()) @@ -12019,16 +12140,14 @@ float Unit::processDummyAuras(float TakenTotalMod) const int32 Unit::SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) { - int32 DoneAdvertisedBenefit = 0; - - AuraEffectList const& mDamageDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE); - for (AuraEffectList::const_iterator i = mDamageDone.begin(); i != mDamageDone.end(); ++i) - if (((*i)->GetMiscValue() & schoolMask) != 0 && - (*i)->GetSpellInfo()->EquippedItemClass == -1 && + int32 DoneAdvertisedBenefit = GetTotalAuraModifier(SPELL_AURA_MOD_DAMAGE_DONE, [schoolMask](AuraEffect const* aurEff) + { + return aurEff->GetMiscValue() & schoolMask && // -1 == any item class (not wand then) - (*i)->GetSpellInfo()->EquippedItemInventoryTypeMask == 0) - // 0 == any inventory type (not wand then) - DoneAdvertisedBenefit += (*i)->GetAmount(); + aurEff->GetSpellInfo()->EquippedItemClass == -1 && + // 0 == any inventory type (not wand then) + aurEff->GetSpellInfo()->EquippedItemInventoryTypeMask == 0; + }); if (IsPlayer()) { @@ -12048,31 +12167,20 @@ int32 Unit::SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) } } // ... and attack power - AuraEffectList const& mDamageDonebyAP = GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER); - for (AuraEffectList::const_iterator i = mDamageDonebyAP.begin(); i != mDamageDonebyAP.end(); ++i) - if ((*i)->GetMiscValue() & schoolMask) - DoneAdvertisedBenefit += int32(CalculatePct(GetTotalAttackPowerValue(BASE_ATTACK), (*i)->GetAmount())); + DoneAdvertisedBenefit += int32(CalculatePct(GetTotalAttackPowerValue(BASE_ATTACK), GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER, schoolMask))); } return DoneAdvertisedBenefit; } int32 Unit::SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask, bool isDoT) { - int32 TakenAdvertisedBenefit = 0; - - AuraEffectList const& mDamageTaken = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_TAKEN); - for (AuraEffectList::const_iterator i = mDamageTaken.begin(); i != mDamageTaken.end(); ++i) - if (((*i)->GetMiscValue() & schoolMask) != 0) - { + return GetTotalAuraModifier(SPELL_AURA_MOD_DAMAGE_TAKEN, [schoolMask, isDoT](AuraEffect const* aurEff) + { + return (aurEff->GetMiscValue() & schoolMask) != 0 // Xinef: if we have DoT damage type and aura has charges, check if it affects DoTs // Xinef: required for hemorrhage & rupture / garrote - if (isDoT && (*i)->GetBase()->IsUsingCharges() && !((*i)->GetSpellInfo()->ProcFlags & PROC_FLAG_TAKEN_PERIODIC)) - continue; - - TakenAdvertisedBenefit += (*i)->GetAmount(); - } - - return TakenAdvertisedBenefit; + && !(isDoT && aurEff->GetBase()->IsUsingCharges() && aurEff->GetSpellInfo()->ProcFlags & PROC_FLAG_TAKEN_PERIODIC); + }); } float Unit::SpellDoneCritChance(Unit const* /*victim*/, SpellInfo const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType, bool skipEffectCheck) const @@ -12343,14 +12451,10 @@ float Unit::SpellTakenCritChance(Unit const* caster, SpellInfo const* spellProto if (caster) { - AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + crit_chance += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER, [caster](AuraEffect const* aurEff) { - if (caster->GetGUID() != (*i)->GetCasterGUID()) - continue; - - crit_chance += (*i)->GetAmount(); - } + return caster->GetGUID() == aurEff->GetCasterGUID(); + }); } // Modify critical chance by victim SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE @@ -12463,14 +12567,7 @@ float Unit::SpellPctHealingModsDone(Unit* victim, SpellInfo const* spellProto, D float DoneTotalMod = 1.0f; // Healing done percent - AuraEffectList const& mHealingDonePct = GetAuraEffectsByType(SPELL_AURA_MOD_HEALING_DONE_PERCENT); - for (auto const& auraEff : mHealingDonePct) - { - if (!sScriptMgr->IsNeedModHealPercent(this, auraEff, DoneTotalMod, spellProto)) - continue; - - AddPct(DoneTotalMod, auraEff->GetAmount()); - } + DoneTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_HEALING_DONE_PERCENT); // done scripted mod (take it from owner) Unit* owner = GetOwner() ? GetOwner() : this; @@ -12636,6 +12733,8 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: DoneTotal = 0; break; + default: + break; } if (spellProto->Effects[i].Effect == SPELL_EFFECT_HEALTH_LEECH) DoneTotal = 0; @@ -12677,7 +12776,7 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u int32 TakenTotal = 0; // Taken fixed damage bonus auras - int32 TakenAdvertisedBenefit = SpellBaseHealingBonusTaken(spellProto->GetSchoolMask()); + int32 TakenAdvertisedBenefit = GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_HEALING, spellProto->GetSchoolMask()); // Nourish cast, glyph of nourish if (spellProto->SpellFamilyName == SPELLFAMILY_DRUID && spellProto->SpellFamilyFlags[1] & 0x2000000 && caster) @@ -12751,10 +12850,10 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u if (caster) { - AuraEffectList const& mHealingGet = GetAuraEffectsByType(SPELL_AURA_MOD_HEALING_RECEIVED); - for (AuraEffectList::const_iterator i = mHealingGet.begin(); i != mHealingGet.end(); ++i) - if (caster->GetGUID() == (*i)->GetCasterGUID() && (*i)->IsAffectedOnSpell(spellProto)) - AddPct(TakenTotalMod, (*i)->GetAmount()); + TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_HEALING_RECEIVED, [caster, spellProto](AuraEffect const* aurEff) + { + return caster->GetGUID() == aurEff->GetCasterGUID() && aurEff->IsAffectedOnSpell(spellProto); + }); } for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) @@ -12766,6 +12865,8 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: TakenTotal = 0; break; + default: + break; } if (spellProto->Effects[i].Effect == SPELL_EFFECT_HEALTH_LEECH) TakenTotal = 0; @@ -12787,10 +12888,10 @@ int32 Unit::SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) { int32 AdvertisedBenefit = 0; - AuraEffectList const& mHealingDone = GetAuraEffectsByType(SPELL_AURA_MOD_HEALING_DONE); - for (AuraEffectList::const_iterator i = mHealingDone.begin(); i != mHealingDone.end(); ++i) - if (!(*i)->GetMiscValue() || ((*i)->GetMiscValue() & schoolMask) != 0) - AdvertisedBenefit += (*i)->GetAmount(); + AdvertisedBenefit += GetTotalAuraModifier(SPELL_AURA_MOD_HEALING_DONE, [schoolMask](AuraEffect const* aurEff) + { + return !aurEff->GetMiscValue() || (aurEff->GetMiscValue() & schoolMask) != 0; + }); // Healing bonus of spirit, intellect and strength if (IsPlayer()) @@ -12809,26 +12910,11 @@ int32 Unit::SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) } // ... and attack power - AuraEffectList const& mHealingDonebyAP = GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER); - for (AuraEffectList::const_iterator i = mHealingDonebyAP.begin(); i != mHealingDonebyAP.end(); ++i) - if ((*i)->GetMiscValue() & schoolMask) - AdvertisedBenefit += int32(CalculatePct(GetTotalAttackPowerValue(BASE_ATTACK), (*i)->GetAmount())); + AdvertisedBenefit += int32(CalculatePct(GetTotalAttackPowerValue(BASE_ATTACK), GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER, schoolMask))); } return AdvertisedBenefit; } -int32 Unit::SpellBaseHealingBonusTaken(SpellSchoolMask schoolMask) -{ - int32 AdvertisedBenefit = 0; - - AuraEffectList const& mDamageTaken = GetAuraEffectsByType(SPELL_AURA_MOD_HEALING); - for (AuraEffectList::const_iterator i = mDamageTaken.begin(); i != mDamageTaken.end(); ++i) - if (((*i)->GetMiscValue() & schoolMask) != 0) - AdvertisedBenefit += (*i)->GetAmount(); - - return AdvertisedBenefit; -} - bool Unit::IsImmunedToDamage(SpellSchoolMask meleeSchoolMask) const { if (meleeSchoolMask == SPELL_SCHOOL_MASK_NONE) @@ -13177,10 +13263,7 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType int32 DoneFlatBenefit = 0; // ..done - AuraEffectList const& mDamageDoneCreature = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE_CREATURE); - for (AuraEffectList::const_iterator i = mDamageDoneCreature.begin(); i != mDamageDoneCreature.end(); ++i) - if (creatureTypeMask & uint32((*i)->GetMiscValue())) - DoneFlatBenefit += (*i)->GetAmount(); + DoneFlatBenefit += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_DAMAGE_DONE_CREATURE, creatureTypeMask); // ..done // SPELL_AURA_MOD_DAMAGE_DONE included in weapon damage @@ -13193,20 +13276,14 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType APbonus += victim->GetTotalAuraModifier(SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS); // ..done (base at attack power and creature type) - AuraEffectList const& mCreatureAttackPower = GetAuraEffectsByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS); - for (AuraEffectList::const_iterator i = mCreatureAttackPower.begin(); i != mCreatureAttackPower.end(); ++i) - if (creatureTypeMask & uint32((*i)->GetMiscValue())) - APbonus += (*i)->GetAmount(); + APbonus += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS, creatureTypeMask); } else { APbonus += victim->GetTotalAuraModifier(SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS); // ..done (base at attack power and creature type) - AuraEffectList const& mCreatureAttackPower = GetAuraEffectsByType(SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS); - for (AuraEffectList::const_iterator i = mCreatureAttackPower.begin(); i != mCreatureAttackPower.end(); ++i) - if (creatureTypeMask & uint32((*i)->GetMiscValue())) - APbonus += (*i)->GetAmount(); + APbonus += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS, creatureTypeMask); } if (APbonus != 0) // Can be negative @@ -13229,37 +13306,34 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType if (!(damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL)) { // Some spells don't benefit from pct done mods - AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); - for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i) - { - if (!spellProto || (spellProto->ValidateAttribute6SpellDamageMods(this, *i, false) && - sScriptMgr->IsNeedModMeleeDamagePercent(this, *i, DoneTotalMod, spellProto))) + DoneTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, [spellProto, this, damageSchoolMask](AuraEffect const* aurEff) { - if (((*i)->GetMiscValue() & damageSchoolMask)) + if (!spellProto || (spellProto->ValidateAttribute6SpellDamageMods(this, aurEff, false))) + { + if ((aurEff->GetMiscValue() & damageSchoolMask)) { - if ((*i)->GetSpellInfo()->EquippedItemClass == -1) - AddPct(DoneTotalMod, (*i)->GetAmount()); - else if (!(*i)->GetSpellInfo()->HasAttribute(SPELL_ATTR5_AURA_AFFECTS_NOT_JUST_REQ_EQUIPPED_ITEM) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0)) - AddPct(DoneTotalMod, (*i)->GetAmount()); - else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements((*i)->GetSpellInfo())) - AddPct(DoneTotalMod, (*i)->GetAmount()); + if (aurEff->GetSpellInfo()->EquippedItemClass == -1) + return true; + else if (!aurEff->GetSpellInfo()->HasAttribute(SPELL_ATTR5_AURA_AFFECTS_NOT_JUST_REQ_EQUIPPED_ITEM) && (aurEff->GetSpellInfo()->EquippedItemSubClassMask == 0)) + return true; + else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements(aurEff->GetSpellInfo())) + return true; } } - } + return false; + }); } - AuraEffectList const& mDamageDoneVersus = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS); - for (AuraEffectList::const_iterator i = mDamageDoneVersus.begin(); i != mDamageDoneVersus.end(); ++i) - if (creatureTypeMask & uint32((*i)->GetMiscValue())) - if (!spellProto || spellProto->ValidateAttribute6SpellDamageMods(this, *i, false)) - AddPct(DoneTotalMod, (*i)->GetAmount()); + DoneTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS, [creatureTypeMask, spellProto, this](AuraEffect const* aurEff) + { + return (creatureTypeMask & aurEff->GetMiscValue() && (!spellProto || spellProto->ValidateAttribute6SpellDamageMods(this, aurEff, false))); + }); // bonus against aurastate - AuraEffectList const& mDamageDoneVersusAurastate = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS_AURASTATE); - for (AuraEffectList::const_iterator i = mDamageDoneVersusAurastate.begin(); i != mDamageDoneVersusAurastate.end(); ++i) - if (victim->HasAuraState(AuraStateType((*i)->GetMiscValue()))) - if (!spellProto || spellProto->ValidateAttribute6SpellDamageMods(this, *i, false)) - AddPct(DoneTotalMod, (*i)->GetAmount()); + DoneTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS_AURASTATE, [victim, spellProto, this](AuraEffect const* aurEff) + { + return (victim->HasAuraState(AuraStateType(aurEff->GetMiscValue())) && (!spellProto || spellProto->ValidateAttribute6SpellDamageMods(this, aurEff, false))); + }); // done scripted mod (take it from owner) Unit* owner = GetOwner() ? GetOwner() : this; @@ -13366,10 +13440,7 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT int32 TakenFlatBenefit = 0; // ..taken - AuraEffectList const& mDamageTaken = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_TAKEN); - for (AuraEffectList::const_iterator i = mDamageTaken.begin(); i != mDamageTaken.end(); ++i) - if ((*i)->GetMiscValue() & damageSchoolMask) - TakenFlatBenefit += (*i)->GetAmount(); + TakenFlatBenefit += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_DAMAGE_TAKEN, damageSchoolMask); if (attType != RANGED_ATTACK) TakenFlatBenefit += GetTotalAuraModifier(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN); @@ -13385,10 +13456,10 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT if (spellProto) { // From caster spells - AuraEffectList const& mOwnerTaken = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER); - for (AuraEffectList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i) - if ((*i)->GetCasterGUID() == attacker->GetGUID() && (*i)->IsAffectedOnSpell(spellProto)) - AddPct(TakenTotalMod, (*i)->GetAmount()); + TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_DAMAGE_FROM_CASTER, [attacker, spellProto](AuraEffect const* aurEff) + { + return attacker->GetGUID() == aurEff->GetCasterGUID() && aurEff->IsAffectedOnSpell(spellProto); + }); // Mod damage from spell mechanic uint32 mechanicMask = spellProto->GetAllEffectsMechanicMask(); @@ -13399,10 +13470,12 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT if (mechanicMask) { - AuraEffectList const& mDamageDoneMechanic = GetAuraEffectsByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT); - for (AuraEffectList::const_iterator i = mDamageDoneMechanic.begin(); i != mDamageDoneMechanic.end(); ++i) - if (mechanicMask & uint32(1 << ((*i)->GetMiscValue()))) - AddPct(TakenTotalMod, (*i)->GetAmount()); + TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT, [mechanicMask](AuraEffect const* aurEff) -> bool + { + if (mechanicMask & uint32(1 << (aurEff->GetMiscValue()))) + return true; + return false; + }); } } @@ -13419,15 +13492,11 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT if (attType != RANGED_ATTACK) { - AuraEffectList const& mModMeleeDamageTakenPercent = GetAuraEffectsByType(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT); - for (AuraEffectList::const_iterator i = mModMeleeDamageTakenPercent.begin(); i != mModMeleeDamageTakenPercent.end(); ++i) - AddPct(TakenTotalMod, (*i)->GetAmount()); + TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT); } else { - AuraEffectList const& mModRangedDamageTakenPercent = GetAuraEffectsByType(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT); - for (AuraEffectList::const_iterator i = mModRangedDamageTakenPercent.begin(); i != mModRangedDamageTakenPercent.end(); ++i) - AddPct(TakenTotalMod, (*i)->GetAmount()); + TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT); } // No positive taken bonus, custom attr @@ -14026,7 +14095,22 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo if (repThisToTarget > REP_NEUTRAL || (repTargetToThis = target->GetReactionTo(this)) > REP_NEUTRAL) - return false; + { + // contested guards can attack contested PvP players even though players may be friendly + if (!target->IsControlledByPlayer()) + return false; + + bool isContestedGuard = false; + if (FactionTemplateEntry const* entry = GetFactionTemplateEntry()) + isContestedGuard = entry->factionFlags & FACTION_TEMPLATE_FLAG_ATTACK_PVP_ACTIVE_PLAYERS; + + bool isContestedPvp = false; + if (Player const* player = target->GetCharmerOrOwnerPlayerOrPlayerItself()) + isContestedPvp = player->HasPlayerFlag(PLAYER_FLAGS_CONTESTED_PVP); + + if (!isContestedGuard && !isContestedPvp) + return false; + } // Not all neutral creatures can be attacked (even some unfriendly faction does not react aggresive to you, like Sporaggar) if (repThisToTarget == REP_NEUTRAL && @@ -14277,15 +14361,6 @@ int32 Unit::ModifyPower(Powers power, int32 dVal, bool withPowerUpdate /*= true* return gain; } -// returns negative amount on power reduction -int32 Unit::ModifyPowerPct(Powers power, float pct, bool apply) -{ - float amount = (float)GetMaxPower(power); - ApplyPercentModFloatVar(amount, pct, apply); - - return ModifyPower(power, (int32)amount - (int32)GetMaxPower(power)); -} - bool Unit::IsAlwaysVisibleFor(WorldObject const* seer) const { if (WorldObject::IsAlwaysVisibleFor(seer)) @@ -15235,30 +15310,100 @@ uint32 Unit::GetCreatureType() const ######## ######## #######################################*/ -bool Unit::HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply) +bool Unit::HandleStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float amount, bool apply) { - if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_END) + if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_FLAT_END) { LOG_ERROR("entities.unit", "ERROR in HandleStatModifier(): non-existing UnitMods or wrong UnitModifierType!"); return false; } + if (!amount) + return false; + switch (modifierType) { case BASE_VALUE: case TOTAL_VALUE: - m_auraModifiersGroup[unitMod][modifierType] += apply ? amount : -amount; - break; - case BASE_PCT: - case TOTAL_PCT: - ApplyPercentModFloatVar(m_auraModifiersGroup[unitMod][modifierType], amount, apply); + m_auraFlatModifiersGroup[unitMod][modifierType] += apply ? amount : -amount; break; default: break; } - if (!CanModifyStats()) - return false; + UpdateUnitMod(unitMod); + return true; +} + +// Usage outside of AuraEffect Handlers is discouraged as the value will be lost when auras change. Use an Aura instead. +void Unit::ApplyStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float pct) +{ + if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_PCT_END) + { + LOG_ERROR("entities.unit", "ERROR in ApplyStatPctModifier(): non-existing UnitMods or wrong UnitModifierType!"); + return; + } + + if (!pct) + return; + + switch (modifierType) + { + case BASE_PCT: + case TOTAL_PCT: + AddPct(m_auraPctModifiersGroup[unitMod][modifierType], pct); + break; + default: + break; + } + + UpdateUnitMod(unitMod); +} + +void Unit::SetStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float val) +{ + if (m_auraFlatModifiersGroup[unitMod][modifierType] == val) + return; + + m_auraFlatModifiersGroup[unitMod][modifierType] = val; + UpdateUnitMod(unitMod); +} + +void Unit::SetStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float val) +{ + if (m_auraPctModifiersGroup[unitMod][modifierType] == val) + return; + + m_auraPctModifiersGroup[unitMod][modifierType] = val; + UpdateUnitMod(unitMod); +} + +float Unit::GetFlatModifierValue(UnitMods unitMod, UnitModifierFlatType modifierType) const +{ + if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_FLAT_END) + { + LOG_ERROR("entities.unit", "attempt to access non-existing modifier value from UnitMods!"); + return 0.0f; + } + + return m_auraFlatModifiersGroup[unitMod][modifierType]; +} + +float Unit::GetPctModifierValue(UnitMods unitMod, UnitModifierPctType modifierType) const +{ + if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_PCT_END) + { + LOG_ERROR("entities.unit", "attempt to access non-existing modifier value from UnitMods!"); + return 0.0f; + } + + return m_auraPctModifiersGroup[unitMod][modifierType]; +} + +void Unit::UpdateUnitMod(UnitMods unitMod) +{ + if (!CanModifyStats()) + return; switch (unitMod) { @@ -15316,36 +15461,100 @@ bool Unit::HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, f default: break; } - - return true; } -float Unit::GetModifierValue(UnitMods unitMod, UnitModifierType modifierType) const +void Unit::UpdateDamageDoneMods(WeaponAttackType attackType, int32 /*skipEnchantSlot = -1*/) { - if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_END) + UnitMods unitMod; + switch (attackType) { - LOG_ERROR("entities.unit", "attempt to access non-existing modifier value from UnitMods!"); - return 0.0f; + case BASE_ATTACK: + unitMod = UNIT_MOD_DAMAGE_MAINHAND; + break; + case OFF_ATTACK: + unitMod = UNIT_MOD_DAMAGE_OFFHAND; + break; + case RANGED_ATTACK: + unitMod = UNIT_MOD_DAMAGE_RANGED; + break; + default: + ABORT(); + break; } - if (modifierType == TOTAL_PCT && m_auraModifiersGroup[unitMod][modifierType] <= 0.0f) - return 0.0f; + float amount = GetTotalAuraModifier(SPELL_AURA_MOD_DAMAGE_DONE, [&](AuraEffect const* aurEff) -> bool + { + if (!(aurEff->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)) + return false; - return m_auraModifiersGroup[unitMod][modifierType]; + return CheckAttackFitToAuraRequirement(attackType, aurEff); + }); + + SetStatFlatModifier(unitMod, TOTAL_VALUE, amount); +} + +void Unit::UpdateAllDamageDoneMods() +{ + for (uint8 i = BASE_ATTACK; i < MAX_ATTACK; ++i) + UpdateDamageDoneMods(WeaponAttackType(i)); +} + +void Unit::UpdateDamagePctDoneMods(WeaponAttackType attackType) +{ + float factor; + UnitMods unitMod; + switch (attackType) + { + case BASE_ATTACK: + factor = 1.0f; + unitMod = UNIT_MOD_DAMAGE_MAINHAND; + break; + case OFF_ATTACK: + // off hand has 50% penalty + factor = 0.5f; + unitMod = UNIT_MOD_DAMAGE_OFFHAND; + break; + case RANGED_ATTACK: + factor = 1.0f; + unitMod = UNIT_MOD_DAMAGE_RANGED; + break; + default: + ABORT(); + break; + } + + factor *= GetTotalAuraMultiplier(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, [attackType, this](AuraEffect const* aurEff) -> bool + { + if (!(aurEff->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)) + return false; + + return CheckAttackFitToAuraRequirement(attackType, aurEff); + }); + + if (attackType == OFF_ATTACK) + factor *= GetTotalAuraMultiplier(SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT, std::bind(&Unit::CheckAttackFitToAuraRequirement, this, attackType, std::placeholders::_1)); + + SetStatPctModifier(unitMod, TOTAL_PCT, factor); +} + +void Unit::UpdateAllDamagePctDoneMods() +{ + for (uint8 i = BASE_ATTACK; i < MAX_ATTACK; ++i) + UpdateDamagePctDoneMods(WeaponAttackType(i)); } float Unit::GetTotalStatValue(Stats stat, float additionalValue) const { UnitMods unitMod = UnitMods(static_cast(UNIT_MOD_STAT_START) + stat); - if (m_auraModifiersGroup[unitMod][TOTAL_PCT] <= 0.0f) + if (GetPctModifierValue(unitMod, TOTAL_PCT) <= 0.0f) return 0.0f; // value = ((base_value * base_pct) + total_value) * total_pct - float value = m_auraModifiersGroup[unitMod][BASE_VALUE] + GetCreateStat(stat); - value *= m_auraModifiersGroup[unitMod][BASE_PCT]; - value += m_auraModifiersGroup[unitMod][TOTAL_VALUE] + additionalValue; - value *= m_auraModifiersGroup[unitMod][TOTAL_PCT]; + float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreateStat(stat); + value *= GetPctModifierValue(unitMod, BASE_PCT); + value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + additionalValue; + value *= GetPctModifierValue(unitMod, TOTAL_PCT); return value; } @@ -15358,25 +15567,16 @@ float Unit::GetTotalAuraModValue(UnitMods unitMod) const return 0.0f; } - if (m_auraModifiersGroup[unitMod][TOTAL_PCT] <= 0.0f) + if (GetPctModifierValue(unitMod, TOTAL_PCT) <= 0.0f) return 0.0f; - float value = m_auraModifiersGroup[unitMod][BASE_VALUE]; - value *= m_auraModifiersGroup[unitMod][BASE_PCT]; - value += m_auraModifiersGroup[unitMod][TOTAL_VALUE]; - value *= m_auraModifiersGroup[unitMod][TOTAL_PCT]; - + float value = GetFlatModifierValue(unitMod, BASE_VALUE); + value *= GetPctModifierValue(unitMod, BASE_PCT); + value += GetFlatModifierValue(unitMod, TOTAL_VALUE); + value *= GetPctModifierValue(unitMod, TOTAL_PCT); return value; } -void Unit::ApplyStatPercentBuffMod(Stats stat, float val, bool apply) -{ - if (val == -100.0f) // prevent set var to zero - val = -99.99f; - float var = GetStat(stat) * val / 100.0f; - ApplyModSignedFloatValue((var > 0 ? static_cast(UNIT_FIELD_POSSTAT0) + stat : static_cast(UNIT_FIELD_NEGSTAT0) + stat), var, apply); -} - SpellSchools Unit::GetSpellSchoolByAuraGroup(UnitMods unitMod) const { SpellSchools school = SPELL_SCHOOL_NORMAL; @@ -17083,28 +17283,40 @@ Unit* Unit::SelectNearbyNoTotemTarget(Unit* exclude, float dist) const return Acore::Containers::SelectRandomContainerElement(targets); } +void ApplyPercentModFloatVar(float& var, float val, bool apply) +{ + var *= (apply ? (100.0f + val) / 100.0f : 100.0f / (100.0f + val)); +} + void Unit::ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply) { + float amount = GetFloatValue(UNIT_FIELD_BASEATTACKTIME + AsUnderlyingType(att)); + float remainingTimePct = std::max((float)m_attackTimer[att], 0.0f) / (GetAttackTime(att) * m_modAttackSpeedPct[att]); - if (val > 0) + if (val > 0.f) { ApplyPercentModFloatVar(m_modAttackSpeedPct[att], val, !apply); - ApplyPercentModFloatValue(static_cast(UNIT_FIELD_BASEATTACKTIME) + att, val, !apply); + ApplyPercentModFloatVar(amount, val, !apply); } else { ApplyPercentModFloatVar(m_modAttackSpeedPct[att], -val, apply); - ApplyPercentModFloatValue(static_cast(UNIT_FIELD_BASEATTACKTIME) + att, -val, apply); + ApplyPercentModFloatVar(amount, -val, apply); } + SetFloatValue(UNIT_FIELD_BASEATTACKTIME + AsUnderlyingType(att), amount); m_attackTimer[att] = uint32(GetAttackTime(att) * m_modAttackSpeedPct[att] * remainingTimePct); } void Unit::ApplyCastTimePercentMod(float val, bool apply) { - if (val > 0) - ApplyPercentModFloatValue(UNIT_MOD_CAST_SPEED, val, !apply); + float amount = GetFloatValue(UNIT_MOD_CAST_SPEED); + + if (val > 0.f) + ApplyPercentModFloatVar(amount, val, !apply); else - ApplyPercentModFloatValue(UNIT_MOD_CAST_SPEED, -val, apply); + ApplyPercentModFloatVar(amount, -val, apply); + + SetFloatValue(UNIT_MOD_CAST_SPEED, amount); } uint32 Unit::GetCastingTimeForBonus(SpellInfo const* spellProto, DamageEffectType damagetype, uint32 CastingTime) const @@ -18397,7 +18609,7 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au } // dismount players when charmed - if (IsPlayer()) + if (IsPlayer() && type != CHARM_TYPE_POSSESS) RemoveAurasByType(SPELL_AURA_MOUNTED); if (charmer->IsPlayer()) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index ae7b5cd67..a475b5eaa 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -123,13 +123,18 @@ enum HitInfo HITINFO_FAKE_DAMAGE = 0x01000000 // enables damage animation even if no damage done, set only if no damage }; -enum UnitModifierType +enum UnitModifierFlatType { BASE_VALUE = 0, - BASE_PCT = 1, - TOTAL_VALUE = 2, - TOTAL_PCT = 3, - MODIFIER_TYPE_END = 4 + TOTAL_VALUE = 1, + MODIFIER_TYPE_FLAT_END = 3 +}; + +enum UnitModifierPctType +{ + BASE_PCT = 0, + TOTAL_PCT = 1, + MODIFIER_TYPE_PCT_END = 2 }; enum WeaponDamageRange @@ -214,7 +219,7 @@ enum WeaponAttackType : uint8 MAX_ATTACK }; -enum CombatRating +enum CombatRating : uint8 { CR_WEAPON_SKILL = 0, CR_DEFENSE_SKILL = 1, @@ -1050,16 +1055,32 @@ public: for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i) SetFloatValue(static_cast(UNIT_FIELD_NEGSTAT0) + i, 0); } - bool HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply); - void SetModifierValue(UnitMods unitMod, UnitModifierType modifierType, float value) { m_auraModifiersGroup[unitMod][modifierType] = value; } - [[nodiscard]] float GetModifierValue(UnitMods unitMod, UnitModifierType modifierType) const; + bool HandleStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float amount, bool apply); + void ApplyStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float amount); + + void SetStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float val); + void SetStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float val); + + [[nodiscard]] float GetFlatModifierValue(UnitMods unitMod, UnitModifierFlatType modifierType) const; + [[nodiscard]] float GetPctModifierValue(UnitMods unitMod, UnitModifierPctType modifierType) const; + + void UpdateUnitMod(UnitMods unitMod); + + // only players have item requirements + [[nodiscard]] virtual bool CheckAttackFitToAuraRequirement(WeaponAttackType /*attackType*/, AuraEffect const* /*aurEff*/) const { return true; } + + virtual void UpdateDamageDoneMods(WeaponAttackType attackType, int32 skipEnchantSlot = -1); + void UpdateAllDamageDoneMods(); + + void UpdateDamagePctDoneMods(WeaponAttackType attackType); + void UpdateAllDamagePctDoneMods(); + [[nodiscard]] float GetTotalStatValue(Stats stat, float additionalValue = 0.0f) const; void SetCanModifyStats(bool modifyStats) { m_canModifyStats = modifyStats; } [[nodiscard]] bool CanModifyStats() const { return m_canModifyStats; } - void ApplyStatBuffMod(Stats stat, float val, bool apply) { ApplyModSignedFloatValue((val > 0 ? static_cast(UNIT_FIELD_POSSTAT0) + stat : static_cast(UNIT_FIELD_NEGSTAT0) + stat), val, apply); } - void ApplyStatPercentBuffMod(Stats stat, float val, bool apply); + void UpdateStatBuffMod(Stats stat); // Unit level methods [[nodiscard]] uint8 GetLevel() const { return uint8(GetUInt32Value(UNIT_FIELD_LEVEL)); } @@ -1104,7 +1125,6 @@ public: void SetMaxPower(Powers power, uint32 val); int32 ModifyPower(Powers power, int32 val, bool withPowerUpdate = true); - int32 ModifyPowerPct(Powers power, float pct, bool apply = true); void RewardRage(uint32 damage, uint32 weaponSpeedHitFactor, bool attacker); @@ -1159,13 +1179,9 @@ public: [[nodiscard]] uint32 GetResistance(SpellSchoolMask mask) const; [[nodiscard]] uint32 GetResistance(SpellSchools school) const { return GetUInt32Value(static_cast(UNIT_FIELD_RESISTANCES) + school); } static float GetEffectiveResistChance(Unit const* owner, SpellSchoolMask schoolMask, Unit const* victim); - [[nodiscard]] float GetResistanceBuffMods(SpellSchools school, bool positive) const { return GetFloatValue(positive ? static_cast(UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE) + school : static_cast(UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE) + + school); } void SetResistance(SpellSchools school, int32 val) { SetStatInt32Value(static_cast(UNIT_FIELD_RESISTANCES) + school, val); } - void SetResistanceBuffMods(SpellSchools school, bool positive, float val) { SetFloatValue(positive ? static_cast(UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE) + school : static_cast(UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE) + + school, val); } - - void ApplyResistanceBuffModsMod(SpellSchools school, bool positive, float val, bool apply) { ApplyModSignedFloatValue(positive ? static_cast(UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE) + school : static_cast(UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE) + + school, val, apply); } - void ApplyResistanceBuffModsPercentMod(SpellSchools school, bool positive, float val, bool apply) { ApplyPercentModFloatValue(positive ? static_cast(UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE) + school : static_cast(UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE) + + school, val, apply); } + void UpdateResistanceBuffModsMod(SpellSchools school); //////////// Need triage //////////////// uint16 GetMaxSkillValueForLevel(Unit const* target = nullptr) const { return (target ? getLevelForTarget(target) : GetLevel()) * 5; } @@ -1319,6 +1335,10 @@ public: void SetAuraStack(uint32 spellId, Unit* target, uint32 stack); + int32 GetHighestExclusiveSameEffectSpellGroupValue(AuraEffect const* aurEff, AuraType auraType, bool checkMiscValue = false, int32 miscValue = 0) const; + bool IsHighestExclusiveAura(Aura const* aura, bool removeOtherAuraApplications = false); + bool IsHighestExclusiveAuraEffect(SpellInfo const* spellInfo, AuraType auraType, int32 effectAmount, uint8 auraEffectMask, bool removeOtherAuraApplications = false); + // aura apply/remove helpers - you should better not use these Aura* _TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 effMask, Unit* caster, int32* baseAmount = nullptr, Item* castItem = nullptr, ObjectGuid casterGUID = ObjectGuid::Empty, bool periodicReset = false); void _AddAura(UnitAura* aura, Unit* caster); @@ -1328,7 +1348,7 @@ public: void _UnapplyAura(AuraApplicationMap::iterator& i, AuraRemoveMode removeMode); void _UnapplyAura(AuraApplication* aurApp, AuraRemoveMode removeMode); void _RemoveNoStackAuraApplicationsDueToAura(Aura* aura); - void _RemoveNoStackAurasDueToAura(Aura* aura); + void _RemoveNoStackAurasDueToAura(Aura* aura, bool owned); bool _IsNoStackAuraDueToAura(Aura* appliedAura, Aura* existingAura) const; void _RegisterAuraEffect(AuraEffect* aurEff, bool apply); @@ -1474,15 +1494,19 @@ public: uint32 GetDiseasesByCaster(ObjectGuid casterGUID, uint8 mode = 0); [[nodiscard]] uint32 GetDoTsByCaster(ObjectGuid casterGUID) const; - [[nodiscard]] int32 GetTotalAuraModifierAreaExclusive(AuraType auratype) const; [[nodiscard]] int32 GetTotalAuraModifier(AuraType auratype) const; [[nodiscard]] float GetTotalAuraMultiplier(AuraType auratype) const; - int32 GetMaxPositiveAuraModifier(AuraType auratype); + [[nodiscard]] int32 GetMaxPositiveAuraModifier(AuraType auratype) const; [[nodiscard]] int32 GetMaxNegativeAuraModifier(AuraType auratype) const; + [[nodiscard]] int32 GetTotalAuraModifier(AuraType auratype, std::function const& predicate) const; + [[nodiscard]] float GetTotalAuraMultiplier(AuraType auraType, std::function const& predicate) const; + [[nodiscard]] int32 GetMaxPositiveAuraModifier(AuraType auraType, std::function const& predicate) const; + [[nodiscard]] int32 GetMaxNegativeAuraModifier(AuraType auraType, std::function const& predicate) const; + [[nodiscard]] int32 GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const; [[nodiscard]] float GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const; - int32 GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask, const AuraEffect* except = nullptr) const; + [[nodiscard]] int32 GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask, const AuraEffect* except = nullptr) const; [[nodiscard]] int32 GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const; [[nodiscard]] int32 GetTotalAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const; @@ -1581,7 +1605,6 @@ public: int32 HealBySpell(HealInfo& healInfo, bool critical = false); int32 SpellBaseHealingBonusDone(SpellSchoolMask schoolMask); - int32 SpellBaseHealingBonusTaken(SpellSchoolMask schoolMask); float SpellPctHealingModsDone(Unit* victim, SpellInfo const* spellProto, DamageEffectType damagetype); uint32 SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint8 effIndex, float TotalMod = 0.0f, uint32 stack = 1); uint32 SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack = 1); @@ -2138,7 +2161,8 @@ protected: AuraStateAurasMap m_auraStateAuras; // Used for improve performance of aura state checks on aura apply/remove uint32 m_interruptMask; - float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END]; + float m_auraFlatModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_FLAT_END]; + float m_auraPctModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_PCT_END]; float m_weaponDamage[MAX_ATTACK][MAX_WEAPON_DAMAGE_RANGE][MAX_ITEM_PROTO_DAMAGES]; bool m_canModifyStats; VisibleAuraMap m_visibleAuras; diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp index aef876754..9fc5643d0 100644 --- a/src/server/game/Handlers/ItemHandler.cpp +++ b/src/server/game/Handlers/ItemHandler.cpp @@ -256,8 +256,8 @@ void WorldSession::HandleAutoEquipItemOpcode(WorldPackets::Item::AutoEquipItem& } // now do moves, remove... - _player->RemoveItem(dstbag, dstslot, true, true); - _player->RemoveItem(packet.SourceBag, packet.SourceSlot, true, true); + _player->RemoveItem(dstbag, dstslot, true); + _player->RemoveItem(packet.SourceBag, packet.SourceSlot, true); // add to dest _player->EquipItem(dest, pSrcItem, true); diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index a87819458..fb40ce36a 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -299,6 +299,8 @@ void WorldSession::HandleMoveTeleportAck(WorldPacket& recvData) plMover->UpdatePosition(dest, true); + plMover->SetFallInformation(GameTime::GetGameTime().count(), dest.GetPositionZ()); + // xinef: teleport pets if they are not unsummoned if (Pet* pet = plMover->GetPet()) { diff --git a/src/server/game/Scripting/ScriptDefines/AllSpellScript.cpp b/src/server/game/Scripting/ScriptDefines/AllSpellScript.cpp index 3f1564893..d47939fe0 100644 --- a/src/server/game/Scripting/ScriptDefines/AllSpellScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/AllSpellScript.cpp @@ -24,16 +24,6 @@ void ScriptMgr::OnCalcMaxDuration(Aura const* aura, int32& maxDuration) CALL_ENABLED_HOOKS(AllSpellScript, ALLSPELLHOOK_ON_CALC_MAX_DURATION, script->OnCalcMaxDuration(aura, maxDuration)); } -bool ScriptMgr::CanModAuraEffectDamageDone(AuraEffect const* auraEff, Unit* target, AuraApplication const* aurApp, uint8 mode, bool apply) -{ - CALL_ENABLED_BOOLEAN_HOOKS(AllSpellScript, ALLSPELLHOOK_CAN_MOD_AURA_EFFECT_DAMAGE_DONE, !script->CanModAuraEffectDamageDone(auraEff, target, aurApp, mode, apply)); -} - -bool ScriptMgr::CanModAuraEffectModDamagePercentDone(AuraEffect const* auraEff, Unit* target, AuraApplication const* aurApp, uint8 mode, bool apply) -{ - CALL_ENABLED_BOOLEAN_HOOKS(AllSpellScript, ALLSPELLHOOK_CAN_MOD_AURA_EFFECT_MOD_DAMAGE_PERCENT_DONE, !script->CanModAuraEffectModDamagePercentDone(auraEff, target, aurApp, mode, apply)); -} - void ScriptMgr::OnSpellCheckCast(Spell* spell, bool strict, SpellCastResult& res) { CALL_ENABLED_HOOKS(AllSpellScript, ALLSPELLHOOK_ON_SPELL_CHECK_CAST, script->OnSpellCheckCast(spell, strict, res)); diff --git a/src/server/game/Scripting/ScriptDefines/AllSpellScript.h b/src/server/game/Scripting/ScriptDefines/AllSpellScript.h index 7536f8cf5..df069bcb1 100644 --- a/src/server/game/Scripting/ScriptDefines/AllSpellScript.h +++ b/src/server/game/Scripting/ScriptDefines/AllSpellScript.h @@ -24,8 +24,6 @@ enum AllSpellHook { ALLSPELLHOOK_ON_CALC_MAX_DURATION, - ALLSPELLHOOK_CAN_MOD_AURA_EFFECT_DAMAGE_DONE, - ALLSPELLHOOK_CAN_MOD_AURA_EFFECT_MOD_DAMAGE_PERCENT_DONE, ALLSPELLHOOK_ON_SPELL_CHECK_CAST, ALLSPELLHOOK_CAN_PREPARE, ALLSPELLHOOK_CAN_SCALING_EVERYTHING, @@ -56,10 +54,6 @@ public: // Calculate max duration in applying aura virtual void OnCalcMaxDuration(Aura const* /*aura*/, int32& /*maxDuration*/) { } - [[nodiscard]] virtual bool CanModAuraEffectDamageDone(AuraEffect const* /*auraEff*/, Unit* /*target*/, AuraApplication const* /*aurApp*/, uint8 /*mode*/, bool /*apply*/) { return true; } - - [[nodiscard]] virtual bool CanModAuraEffectModDamagePercentDone(AuraEffect const* /*auraEff*/, Unit* /*target*/, AuraApplication const* /*aurApp*/, uint8 /*mode*/, bool /*apply*/) { return true; } - virtual void OnSpellCheckCast(Spell* /*spell*/, bool /*strict*/, SpellCastResult& /*res*/) { } [[nodiscard]] virtual bool CanPrepare(Spell* /*spell*/, SpellCastTargets const* /*targets*/, AuraEffect const* /*triggeredByAura*/) { return true; } diff --git a/src/server/game/Scripting/ScriptDefines/UnitScript.cpp b/src/server/game/Scripting/ScriptDefines/UnitScript.cpp index 2975ec4f1..c36cfcd25 100644 --- a/src/server/game/Scripting/ScriptDefines/UnitScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/UnitScript.cpp @@ -84,21 +84,6 @@ bool ScriptMgr::IfNormalReaction(Unit const* unit, Unit const* target, Reputatio CALL_ENABLED_BOOLEAN_HOOKS(UnitScript, UNITHOOK_IF_NORMAL_REACTION, !script->IfNormalReaction(unit, target, repRank)); } -bool ScriptMgr::IsNeedModSpellDamagePercent(Unit const* unit, AuraEffect* auraEff, float& doneTotalMod, SpellInfo const* spellProto) -{ - CALL_ENABLED_BOOLEAN_HOOKS(UnitScript, UNITHOOK_IS_NEEDMOD_SPELL_DAMAGE_PERCENT, !script->IsNeedModSpellDamagePercent(unit, auraEff, doneTotalMod, spellProto)); -} - -bool ScriptMgr::IsNeedModMeleeDamagePercent(Unit const* unit, AuraEffect* auraEff, float& doneTotalMod, SpellInfo const* spellProto) -{ - CALL_ENABLED_BOOLEAN_HOOKS(UnitScript, UNITHOOK_IS_NEEDMOD_MELEE_DAMAGE_PERCENT, !script->IsNeedModMeleeDamagePercent(unit, auraEff, doneTotalMod, spellProto)); -} - -bool ScriptMgr::IsNeedModHealPercent(Unit const* unit, AuraEffect* auraEff, float& doneTotalMod, SpellInfo const* spellProto) -{ - CALL_ENABLED_BOOLEAN_HOOKS(UnitScript, UNITHOOK_IS_NEEDMOD_HEAL_PERCENT, !script->IsNeedModHealPercent(unit, auraEff, doneTotalMod, spellProto)); -} - bool ScriptMgr::CanSetPhaseMask(Unit const* unit, uint32 newPhaseMask, bool update) { CALL_ENABLED_BOOLEAN_HOOKS(UnitScript, UNITHOOK_CAN_SET_PHASE_MASK, !script->CanSetPhaseMask(unit, newPhaseMask, update)); diff --git a/src/server/game/Scripting/ScriptDefines/UnitScript.h b/src/server/game/Scripting/ScriptDefines/UnitScript.h index 26c4e2b13..046f9cc11 100644 --- a/src/server/game/Scripting/ScriptDefines/UnitScript.h +++ b/src/server/game/Scripting/ScriptDefines/UnitScript.h @@ -33,9 +33,6 @@ enum UnitHook UNITHOOK_ON_AURA_APPLY, UNITHOOK_ON_AURA_REMOVE, UNITHOOK_IF_NORMAL_REACTION, - UNITHOOK_IS_NEEDMOD_SPELL_DAMAGE_PERCENT, - UNITHOOK_IS_NEEDMOD_MELEE_DAMAGE_PERCENT, - UNITHOOK_IS_NEEDMOD_HEAL_PERCENT, UNITHOOK_CAN_SET_PHASE_MASK, UNITHOOK_IS_CUSTOM_BUILD_VALUES_UPDATE, UNITHOOK_SHOULD_TRACK_VALUES_UPDATE_POS_BY_INDEX, @@ -89,12 +86,6 @@ public: [[nodiscard]] virtual bool IfNormalReaction(Unit const* /*unit*/, Unit const* /*target*/, ReputationRank& /*repRank*/) { return true; } - [[nodiscard]] virtual bool IsNeedModSpellDamagePercent(Unit const* /*unit*/, AuraEffect* /*auraEff*/, float& /*doneTotalMod*/, SpellInfo const* /*spellProto*/) { return true; } - - [[nodiscard]] virtual bool IsNeedModMeleeDamagePercent(Unit const* /*unit*/, AuraEffect* /*auraEff*/, float& /*doneTotalMod*/, SpellInfo const* /*spellProto*/) { return true; } - - [[nodiscard]] virtual bool IsNeedModHealPercent(Unit const* /*unit*/, AuraEffect* /*auraEff*/, float& /*doneTotalMod*/, SpellInfo const* /*spellProto*/) { return true; } - [[nodiscard]] virtual bool CanSetPhaseMask(Unit const* /*unit*/, uint32 /*newPhaseMask*/, bool /*update*/) { return true; } [[nodiscard]] virtual bool IsCustomBuildValuesUpdate(Unit const* /*unit*/, uint8 /*updateType*/, ByteBuffer& /*fieldBuffer*/, Player const* /*target*/, uint16 /*index*/) { return false; } diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index e9b00d445..749ea202e 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -572,9 +572,6 @@ public: /* UnitScript */ void OnAuraApply(Unit* /*unit*/, Aura* /*aura*/); void OnAuraRemove(Unit* unit, AuraApplication* aurApp, AuraRemoveMode mode); bool IfNormalReaction(Unit const* unit, Unit const* target, ReputationRank& repRank); - bool IsNeedModSpellDamagePercent(Unit const* unit, AuraEffect* auraEff, float& doneTotalMod, SpellInfo const* spellProto); - bool IsNeedModMeleeDamagePercent(Unit const* unit, AuraEffect* auraEff, float& doneTotalMod, SpellInfo const* spellProto); - bool IsNeedModHealPercent(Unit const* unit, AuraEffect* auraEff, float& doneTotalMod, SpellInfo const* spellProto); bool CanSetPhaseMask(Unit const* unit, uint32 newPhaseMask, bool update); bool IsCustomBuildValuesUpdate(Unit const* unit, uint8 updateType, ByteBuffer& fieldBuffer, Player const* target, uint16 index); bool ShouldTrackValuesUpdatePosByIndex(Unit const* unit, uint8 updateType, uint16 index); @@ -632,8 +629,6 @@ public: /* Arena Team Script */ public: /* SpellSC */ void OnCalcMaxDuration(Aura const* aura, int32& maxDuration); - bool CanModAuraEffectDamageDone(AuraEffect const* auraEff, Unit* target, AuraApplication const* aurApp, uint8 mode, bool apply); - bool CanModAuraEffectModDamagePercentDone(AuraEffect const* auraEff, Unit* target, AuraApplication const* aurApp, uint8 mode, bool apply); void OnSpellCheckCast(Spell* spell, bool strict, SpellCastResult& res); bool CanPrepare(Spell* spell, SpellCastTargets const* targets, AuraEffect const* triggeredByAura); bool CanScalingEverything(Spell* spell); diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 2f3d559f3..8a212f546 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -125,7 +125,7 @@ WorldSession::WorldSession(uint32 id, std::string&& name, uint32 accountFlags, s m_playerLogout(false), m_playerRecentlyLogout(false), m_playerSave(false), - m_sessionDbcLocale(sWorld->GetDefaultDbcLocale()), + m_sessionDbcLocale(sWorld->GetAvailableDbcLocale(locale)), m_sessionDbLocaleIndex(locale), m_latency(0), m_TutorialsChanged(false), diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 06d3166e0..7ffb4065f 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -212,7 +212,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS] = &AuraEffect::HandleModStateImmunityMask, //147 SPELL_AURA_MECHANIC_IMMUNITY_MASK &AuraEffect::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS &AuraEffect::HandleNoImmediateEffect, //149 SPELL_AURA_REDUCE_PUSHBACK - &AuraEffect::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT + &AuraEffect::HandleShieldBlockValuePercent, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT &AuraEffect::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED &AuraEffect::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAggroRange &AuraEffect::HandleNoImmediateEffect, //153 SPELL_AURA_SPLIT_DAMAGE_FLAT @@ -393,7 +393,6 @@ AuraEffect::AuraEffect(Aura* base, uint8 effIndex, int32* baseAmount, Unit* cast m_amount = CalculateAmount(caster); m_casterLevel = caster ? caster->GetLevel() : 0; m_applyResilience = caster && caster->CanApplyResilience(); - m_auraGroup = sSpellMgr->GetSpellGroup(GetId()); CalculateSpellMod(); @@ -727,9 +726,12 @@ void AuraEffect::ChangeAmount(int32 newAmount, bool mark, bool onStackOrReapply) std::list effectApplications; GetApplicationList(effectApplications); - for (std::list::const_iterator apptItr = effectApplications.begin(); apptItr != effectApplications.end(); ++apptItr) - if ((*apptItr)->HasEffect(GetEffIndex())) - HandleEffect(*apptItr, handleMask, false); + for (AuraApplication* aurApp : effectApplications) + if (aurApp->HasEffect(GetEffIndex())) + { + aurApp->GetTarget()->_RegisterAuraEffect(this, false); + HandleEffect(aurApp, handleMask, false); + } if (handleMask & AURA_EFFECT_HANDLE_CHANGE_AMOUNT) { @@ -740,9 +742,15 @@ void AuraEffect::ChangeAmount(int32 newAmount, bool mark, bool onStackOrReapply) CalculateSpellMod(); } - for (std::list::const_iterator apptItr = effectApplications.begin(); apptItr != effectApplications.end(); ++apptItr) - if ((*apptItr)->HasEffect(GetEffIndex())) - HandleEffect(*apptItr, handleMask, true); + for (AuraApplication* aurApp : effectApplications) + if (aurApp->HasEffect(GetEffIndex())) + { + if (aurApp->GetRemoveMode() != AURA_REMOVE_NONE) + continue; + + aurApp->GetTarget()->_RegisterAuraEffect(this, true); + HandleEffect(aurApp, handleMask, true); + } } void AuraEffect::HandleEffect(AuraApplication* aurApp, uint8 mode, bool apply) @@ -3000,14 +3008,17 @@ void AuraEffect::HandleAuraModDisarm(AuraApplication const* aurApp, uint8 mode, // Handle damage modification, shapeshifted druids are not affected if (target->IsPlayer() && (!target->IsInFeralForm() || target->GetShapeshiftForm() == FORM_GHOSTWOLF)) { - if (Item* pItem = target->ToPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) + Player* player = target->ToPlayer(); + if (Item* pItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) { - WeaponAttackType attacktype = Player::GetAttackBySlot(slot); + WeaponAttackType attackType = Player::GetAttackBySlot(slot); - if (attacktype < MAX_ATTACK) + player->ApplyItemDependentAuras(pItem, !apply); + if (attackType < MAX_ATTACK) { - target->ToPlayer()->_ApplyWeaponDamage(slot, pItem->GetTemplate(), nullptr, !apply); - target->ToPlayer()->_ApplyWeaponDependentAuraMods(pItem, attacktype, !apply); + player->_ApplyWeaponDamage(slot, pItem->GetTemplate(), nullptr, !apply); + if (!apply) // apply case already handled on item dependent aura removal (if any) + player->UpdateWeaponDependentAuras(attackType); } } } @@ -3439,9 +3450,17 @@ void AuraEffect::HandleModThreat(AuraApplication const* aurApp, uint8 mode, bool return; Unit* target = aurApp->GetTarget(); - for (int8 i = 0; i < MAX_SPELL_SCHOOL; ++i) + for (uint8 i = 0; i < MAX_SPELL_SCHOOL; ++i) if (GetMiscValue() & (1 << i)) - ApplyPercentModFloatVar(target->m_threatModifier[i], float(GetAmount()), apply); + { + if (apply) + AddPct(target->m_threatModifier[i], GetAmount()); + else + { + float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_THREAT, 1 << i); + target->m_threatModifier[i] = amount; + } + } } void AuraEffect::HandleAuraModTotalThreat(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -4318,7 +4337,7 @@ void AuraEffect::HandleAuraModResistanceExclusive(AuraApplication const* aurApp, Unit* target = aurApp->GetTarget(); - for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++) + for (uint8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++) { if (GetMiscValue() & int32(1 << x)) { @@ -4326,9 +4345,9 @@ void AuraEffect::HandleAuraModResistanceExclusive(AuraApplication const* aurApp, if (amount < GetAmount()) { float value = float(GetAmount() - amount); - target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, value, apply); - if (target->IsPlayer()) - target->ApplyResistanceBuffModsMod(SpellSchools(x), aurApp->IsPositive(), value, apply); + target->HandleStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, value, apply); + if (target->IsPlayer() || target->IsPet()) + target->UpdateResistanceBuffModsMod(SpellSchools(x)); } } } @@ -4345,9 +4364,9 @@ void AuraEffect::HandleAuraModResistance(AuraApplication const* aurApp, uint8 mo { if (GetMiscValue() & int32(1 << x)) { - target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(GetAmount()), apply); + target->HandleStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(GetAmount()), apply); if (target->IsPlayer() || target->IsPet()) - target->ApplyResistanceBuffModsMod(SpellSchools(x), GetAmount() > 0, (float)GetAmount(), apply); + target->UpdateResistanceBuffModsMod(SpellSchools(x)); } } } @@ -4358,32 +4377,39 @@ void AuraEffect::HandleAuraModBaseResistancePCT(AuraApplication const* aurApp, u return; Unit* target = aurApp->GetTarget(); - for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++) + for (uint8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++) { if (GetMiscValue() & int32(1 << x)) { - target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(GetAmount()), apply); + if (apply) + target->ApplyStatPctModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(GetAmount())); + else + { + float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_BASE_RESISTANCE_PCT, 1 << x); + target->SetStatPctModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, amount); + } } } } -void AuraEffect::HandleModResistancePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const +void AuraEffect::HandleModResistancePercent(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const { if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) return; Unit* target = aurApp->GetTarget(); - for (int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) + for (uint8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) { if (GetMiscValue() & int32(1 << i)) { - target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(GetAmount()), apply); + float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_RESISTANCE_PCT, 1 << i); + if (target->GetPctModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT) == amount) + continue; + + target->SetStatPctModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, amount); if (target->IsPlayer() || target->IsPet()) - { - target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), true, (float)GetAmount(), apply); - target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), false, (float)GetAmount(), apply); - } + target->UpdateResistanceBuffModsMod(SpellSchools(i)); } } } @@ -4398,7 +4424,7 @@ void AuraEffect::HandleModBaseResistance(AuraApplication const* aurApp, uint8 mo { if (GetMiscValue() & (1 << i)) { - target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(GetAmount()), apply); + target->HandleStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(GetAmount()), apply); } } } @@ -4430,23 +4456,28 @@ void AuraEffect::HandleAuraModStat(AuraApplication const* aurApp, uint8 mode, bo if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) return; - Unit* target = aurApp->GetTarget(); - if (GetMiscValue() < -2 || GetMiscValue() > 4) { LOG_ERROR("spells.aura.effect", "WARNING: Spell {} effect {} has an unsupported misc value ({}) for SPELL_AURA_MOD_STAT ", GetId(), GetEffIndex(), GetMiscValue()); return; } + Unit* target = aurApp->GetTarget(); + int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_STAT, true, GetMiscValue()); + if (std::abs(spellGroupVal) >= std::abs(GetAmount())) + return; + for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++) { // -1 or -2 is all stats (misc < -2 checked in function beginning) if (GetMiscValue() < 0 || GetMiscValue() == i) { - //target->ApplyStatMod(Stats(i), m_amount, apply); - target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetAmount()), apply); + if (spellGroupVal) + target->HandleStatFlatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetAmount()), !apply); + + target->HandleStatFlatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetAmount()), apply); if (target->IsPlayer() || target->IsPet()) - target->ApplyStatBuffMod(Stats(i), (float)GetAmount(), apply); + target->UpdateStatBuffMod(Stats(i)); } } } @@ -4470,8 +4501,16 @@ void AuraEffect::HandleModPercentStat(AuraApplication const* aurApp, uint8 mode, for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i) { - if (GetMiscValue() == i || GetMiscValue() == -1) - target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_amount), apply); + if (apply) + target->ApplyStatPctModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(GetAmount())); + else + { + float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_PERCENT_STAT, [i](AuraEffect const* aurEff) + { + return (aurEff->GetMiscValue() == i || aurEff->GetMiscValue() == -1); + }); + target->SetStatPctModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, amount); + } } } @@ -4549,7 +4588,7 @@ void AuraEffect::HandleModHealingDone(AuraApplication const* aurApp, uint8 mode, target->ToPlayer()->UpdateSpellDamageAndHealingBonus(); } -void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8 mode, bool apply) const +void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const { if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) return; @@ -4565,39 +4604,22 @@ void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8 // save current health state float healthPct = target->GetHealthPct(); bool alive = target->IsAlive(); - float value = GetAmount(); - - if (GetId() == 67480) // xinef: hack fix for blessing of sanctuary stats stack with blessing of kings... - { - if (value) // not turned off - value = 10.0f; - for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++) - { - if (i == STAT_STRENGTH || i == STAT_STAMINA) - { - if (apply && (target->IsPlayer() || target->IsPet())) - target->ApplyStatPercentBuffMod(Stats(i), value, apply); - - target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, value, apply); - - if (!apply && (target->IsPlayer() || target->IsPet())) - target->ApplyStatPercentBuffMod(Stats(i), value, apply); - } - } - return; - } for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++) { if (GetMiscValue() == i || GetMiscValue() == -1) { - if (apply && (target->IsPlayer() || target->IsPet())) - target->ApplyStatPercentBuffMod(Stats(i), value, apply); + float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, [i](AuraEffect const* aurEff) + { + return (aurEff->GetMiscValue() == i || aurEff->GetMiscValue() == -1); + }); - target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, value, apply); + if (target->GetPctModifierValue(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT) == amount) + continue; - if (!apply && (target->IsPlayer() || target->IsPet())) - target->ApplyStatPercentBuffMod(Stats(i), value, apply); + target->SetStatPctModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, amount); + if (target->IsPlayer() || target->IsPet()) + target->UpdateStatBuffMod(Stats(i)); } } @@ -4693,7 +4715,7 @@ void AuraEffect::HandleAuraModIncreaseHealth(AuraApplication const* aurApp, uint if (apply) { - target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply); + target->HandleStatFlatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply); target->ModifyHealth(GetAmount()); } else @@ -4702,7 +4724,7 @@ void AuraEffect::HandleAuraModIncreaseHealth(AuraApplication const* aurApp, uint target->ModifyHealth(-GetAmount()); else target->SetHealth(1); - target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply); + target->HandleStatFlatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply); } } @@ -4716,7 +4738,7 @@ void AuraEffect::HandleAuraModIncreaseMaxHealth(AuraApplication const* aurApp, u uint32 oldhealth = target->GetHealth(); double healthPercentage = (double)oldhealth / (double)target->GetMaxHealth(); - target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply); + target->HandleStatFlatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply); // refresh percentage if (oldhealth > 0) @@ -4746,7 +4768,7 @@ void AuraEffect::HandleAuraModIncreaseEnergy(AuraApplication const* aurApp, uint UnitMods unitMod = UnitMods(static_cast(UNIT_MOD_POWER_START) + PowerType); - target->HandleStatModifier(unitMod, TOTAL_VALUE, float(GetAmount()), apply); + target->HandleStatFlatModifier(unitMod, TOTAL_VALUE, float(GetAmount()), apply); } void AuraEffect::HandleAuraModIncreaseEnergyPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -4765,17 +4787,16 @@ void AuraEffect::HandleAuraModIncreaseEnergyPercent(AuraApplication const* aurAp // return; UnitMods unitMod = UnitMods(static_cast(UNIT_MOD_POWER_START) + PowerType); - float amount = float(GetAmount()); if (apply) { - target->HandleStatModifier(unitMod, TOTAL_PCT, amount, apply); - target->ModifyPowerPct(PowerType, amount, apply); + float amount = float(GetAmount()); + target->ApplyStatPctModifier(unitMod, TOTAL_PCT, amount); } else { - target->ModifyPowerPct(PowerType, amount, apply); - target->HandleStatModifier(unitMod, TOTAL_PCT, amount, apply); + float amount = target->GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT, GetMiscValue()); + target->SetStatPctModifier(unitMod, TOTAL_PCT, amount); } } @@ -4788,7 +4809,14 @@ void AuraEffect::HandleAuraModIncreaseHealthPercent(AuraApplication const* aurAp // Unit will keep hp% after MaxHealth being modified if unit is alive. float percent = target->GetHealthPct(); - target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(GetAmount()), apply); + + if (apply) + target->ApplyStatPctModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(GetAmount())); + else + { + float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT); + target->SetStatPctModifier(UNIT_MOD_HEALTH, TOTAL_PCT, amount); + } // Xinef: pct was rounded down and could "kill" creature by setting its health to 0 making npc zombie if (target->IsAlive()) @@ -4803,7 +4831,13 @@ void AuraEffect::HandleAuraIncreaseBaseHealthPercent(AuraApplication const* aurA Unit* target = aurApp->GetTarget(); - target->HandleStatModifier(UNIT_MOD_HEALTH, BASE_PCT, float(GetAmount()), apply); + if (apply) + target->ApplyStatPctModifier(UNIT_MOD_HEALTH, BASE_PCT, float(GetAmount())); + else + { + float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_BASE_HEALTH_PCT); + target->SetStatPctModifier(UNIT_MOD_HEALTH, BASE_PCT, amount); + } } /********************************/ @@ -4857,34 +4891,17 @@ void AuraEffect::HandleAuraModRegenInterrupt(AuraApplication const* aurApp, uint HandleModManaRegen(aurApp, mode, apply); } -void AuraEffect::HandleAuraModWeaponCritPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const +void AuraEffect::HandleAuraModWeaponCritPercent(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const { if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) return; - Unit* target = aurApp->GetTarget(); + Player* target = aurApp->GetTarget()->ToPlayer(); - if (!target->IsPlayer()) + if (!target) return; - for (int i = 0; i < MAX_ATTACK; ++i) - if (Item* pItem = target->ToPlayer()->GetWeaponForAttack(WeaponAttackType(i), true)) - target->ToPlayer()->_ApplyWeaponDependentAuraCritMod(pItem, WeaponAttackType(i), this, apply); - - // mods must be applied base at equipped weapon class and subclass comparison - // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask - // GetMiscValue() comparison with item generated damage types - - if (GetSpellInfo()->EquippedItemClass == -1) - { - target->ToPlayer()->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply); - target->ToPlayer()->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply); - target->ToPlayer()->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply); - } - else - { - // done in Player::_ApplyWeaponDependentAuraMods - } + target->UpdateAllWeaponDependentCritAuras(); } void AuraEffect::HandleModHitChance(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -4960,9 +4977,7 @@ void AuraEffect::HandleAuraModCritPct(AuraApplication const* aurApp, uint8 mode, return; } - target->ToPlayer()->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply); - target->ToPlayer()->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply); - target->ToPlayer()->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply); + target->ToPlayer()->UpdateAllWeaponDependentCritAuras(); // included in Player::UpdateSpellCritChance calculation target->ToPlayer()->UpdateAllSpellCritChances(); @@ -4986,6 +5001,13 @@ void AuraEffect::HandleModCastingSpeed(AuraApplication const* aurApp, uint8 mode return; } + int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, GetAuraType()); + if (std::abs(spellGroupVal) >= std::abs(GetAmount())) + return; + + if (spellGroupVal) + target->ApplyCastTimePercentMod(float(spellGroupVal), !apply); + target->ApplyCastTimePercentMod((float)GetAmount(), apply); } @@ -5007,6 +5029,17 @@ void AuraEffect::HandleModCombatSpeedPct(AuraApplication const* aurApp, uint8 mo return; Unit* target = aurApp->GetTarget(); + int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MELEE_SLOW); + if (std::abs(spellGroupVal) >= std::abs(GetAmount())) + return; + + if (spellGroupVal) + { + target->ApplyCastTimePercentMod(float(spellGroupVal), !apply); + target->ApplyAttackTimePercentMod(BASE_ATTACK, float(spellGroupVal), !apply); + target->ApplyAttackTimePercentMod(OFF_ATTACK, float(spellGroupVal), !apply); + target->ApplyAttackTimePercentMod(RANGED_ATTACK, float(spellGroupVal), !apply); + } target->ApplyCastTimePercentMod(float(GetAmount()), apply); target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply); @@ -5031,7 +5064,15 @@ void AuraEffect::HandleModMeleeSpeedPct(AuraApplication const* aurApp, uint8 mod return; Unit* target = aurApp->GetTarget(); + int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_MELEE_HASTE); + if (std::abs(spellGroupVal) >= std::abs(GetAmount())) + return; + if (spellGroupVal) + { + target->ApplyAttackTimePercentMod(BASE_ATTACK, float(spellGroupVal), !apply); + target->ApplyAttackTimePercentMod(OFF_ATTACK, float(spellGroupVal), !apply); + } target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply); target->ApplyAttackTimePercentMod(OFF_ATTACK, float(GetAmount()), apply); } @@ -5073,7 +5114,7 @@ void AuraEffect::HandleModRating(AuraApplication const* aurApp, uint8 mode, bool if (!target->IsPlayer()) return; - for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating) + for (uint8 rating = 0; rating < MAX_COMBAT_RATING; ++rating) if (GetMiscValue() & (1 << rating)) target->ToPlayer()->ApplyRatingMod(CombatRating(rating), GetAmount(), apply); } @@ -5089,7 +5130,7 @@ void AuraEffect::HandleModRatingFromStat(AuraApplication const* aurApp, uint8 mo return; // Just recalculate ratings - for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating) + for (uint8 rating = 0; rating < MAX_COMBAT_RATING; ++rating) if (GetMiscValue() & (1 << rating)) target->ToPlayer()->ApplyRatingMod(CombatRating(rating), 0, apply); } @@ -5105,7 +5146,7 @@ void AuraEffect::HandleAuraModAttackPower(AuraApplication const* aurApp, uint8 m Unit* target = aurApp->GetTarget(); - target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(GetAmount()), apply); + target->HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(GetAmount()), apply); } void AuraEffect::HandleAuraModRangedAttackPower(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -5118,7 +5159,7 @@ void AuraEffect::HandleAuraModRangedAttackPower(AuraApplication const* aurApp, u if ((target->getClassMask() & CLASSMASK_WAND_USERS) != 0) return; - target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(GetAmount()), apply); + target->HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(GetAmount()), apply); } void AuraEffect::HandleAuraModAttackPowerPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -5129,7 +5170,13 @@ void AuraEffect::HandleAuraModAttackPowerPercent(AuraApplication const* aurApp, Unit* target = aurApp->GetTarget(); //UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1 - target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(GetAmount()), apply); + if (apply) + target->ApplyStatPctModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(GetAmount())); + else + { + float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_ATTACK_POWER_PCT); + target->SetStatPctModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, amount); + } } void AuraEffect::HandleAuraModRangedAttackPowerPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -5143,7 +5190,13 @@ void AuraEffect::HandleAuraModRangedAttackPowerPercent(AuraApplication const* au return; //UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1 - target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(GetAmount()), apply); + if (apply) + target->ApplyStatPctModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(GetAmount())); + else + { + float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT); + target->SetStatPctModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, amount); + } } void AuraEffect::HandleAuraModRangedAttackPowerOfStatPercent(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const @@ -5184,85 +5237,25 @@ void AuraEffect::HandleModDamageDone(AuraApplication const* aurApp, uint8 mode, Unit* target = aurApp->GetTarget(); - // apply item specific bonuses for already equipped weapon - if (target->IsPlayer()) - { - for (int i = 0; i < MAX_ATTACK; ++i) - if (Item* pItem = target->ToPlayer()->GetWeaponForAttack(WeaponAttackType(i), true)) - target->ToPlayer()->_ApplyWeaponDependentAuraDamageMod(pItem, WeaponAttackType(i), this, apply); - } + if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) != 0) + target->UpdateAllDamageDoneMods(); - // GetMiscValue() is bitmask of spell schools - // 1 (0-bit) - normal school damage (SPELL_SCHOOL_MASK_NORMAL) - // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wands - // 127 - full bitmask any damages - // - // mods must be applied base at equipped weapon class and subclass comparison - // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask - // GetMiscValue() comparison with item generated damage types - - if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) != 0 && sScriptMgr->CanModAuraEffectDamageDone(this, target, aurApp, mode, apply)) - { - // apply generic physical damage bonuses including wand case - if (GetSpellInfo()->EquippedItemClass == -1 || !target->IsPlayer()) - { - target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(GetAmount()), apply); - target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(GetAmount()), apply); - target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(GetAmount()), apply); - - if (target->IsPlayer()) - { - if (GetAmount() > 0) - target->ApplyModInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS, GetAmount(), apply); - else - target->ApplyModInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG, GetAmount(), apply); - } - } - else - { - // done in Player::_ApplyWeaponDependentAuraMods - } - } - - // Skip non magic case for Speedup - if ((GetMiscValue() & SPELL_SCHOOL_MASK_MAGIC) == 0) - return; - - if (GetSpellInfo()->EquippedItemClass != -1 || GetSpellInfo()->EquippedItemInventoryTypeMask != 0) - { - // wand magic case (skip generic to all item spell bonuses) - // done in Player::_ApplyWeaponDependentAuraMods - - // Skip item specific requirements for not wand magic damage - return; - } - - // Magic damage modifiers implemented in Unit::SpellDamageBonus + // Magic damage modifiers implemented in Unit::SpellBaseDamageBonus // This information for client side use only if (target->IsPlayer()) { - if (GetAmount() > 0) - { - for (uint32 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++) - { - if ((GetMiscValue() & (1 << i)) != 0) - target->ApplyModInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + i, GetAmount(), apply); - } - } - else - { - for (uint32 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++) - { - if ((GetMiscValue() & (1 << i)) != 0) - target->ApplyModInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + i, GetAmount(), apply); - } - } + + uint16 baseField = GetAmount() >= 0 ? PLAYER_FIELD_MOD_DAMAGE_DONE_POS : PLAYER_FIELD_MOD_DAMAGE_DONE_NEG; + for (uint16 i = 0; i < MAX_SPELL_SCHOOL; ++i) + if (GetMiscValue() & (1 << i)) + target->ApplyModUInt32Value(baseField + i, GetAmount(), apply); + if (Guardian* pet = target->ToPlayer()->GetGuardianPet()) pet->UpdateAttackPowerAndDamage(); } } -void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8 mode, bool apply) const +void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const { if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) return; @@ -5271,39 +5264,32 @@ void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8 if (!target) return; - if (!sScriptMgr->CanModAuraEffectModDamagePercentDone(this, target, aurApp, mode, apply)) - return; + if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)) + target->UpdateAllDamagePctDoneMods(); if (target->IsPlayer()) { - for (int i = 0; i < MAX_ATTACK; ++i) - if (Item* item = target->ToPlayer()->GetWeaponForAttack(WeaponAttackType(i), false)) - target->ToPlayer()->_ApplyWeaponDependentAuraDamageMod(item, WeaponAttackType(i), this, apply); - } - - if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) && (GetSpellInfo()->EquippedItemClass == -1 || !target->IsPlayer())) - { - target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(GetAmount()), apply); - target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply); - target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(GetAmount()), apply); - - if (target->IsPlayer()) - target->ToPlayer()->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT, float (GetAmount()), apply); - } - else - { - // done in Player::_ApplyWeaponDependentAuraMods for SPELL_SCHOOL_MASK_NORMAL && EquippedItemClass != -1 and also for wand case + for (uint8 i = 0; i < MAX_SPELL_SCHOOL; ++i) + { + if (GetMiscValue() & (1 << i)) + { + // only aura type modifying PLAYER_FIELD_MOD_DAMAGE_DONE_PCT + float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, 1 << i); + target->SetFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT + i, amount); + } + } } } -void AuraEffect::HandleModOffhandDamagePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const +void AuraEffect::HandleModOffhandDamagePercent(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const { if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) return; Unit* target = aurApp->GetTarget(); - target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply); + // also handles spell group stacks + target->UpdateDamagePctDoneMods(OFF_ATTACK); } void AuraEffect::HandleShieldBlockValue(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -5311,14 +5297,29 @@ void AuraEffect::HandleShieldBlockValue(AuraApplication const* aurApp, uint8 mod if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) return; - Unit* target = aurApp->GetTarget(); + Player* target = aurApp->GetTarget()->ToPlayer(); + if (!target) + return; - BaseModType modType = FLAT_MOD; - if (GetAuraType() == SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT) - modType = PCT_MOD; + target->HandleBaseModFlatValue(SHIELD_BLOCK_VALUE, float(GetAmount()), apply); +} - if (target->IsPlayer()) - target->ToPlayer()->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(GetAmount()), apply); +void AuraEffect::HandleShieldBlockValuePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const +{ + if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Player* target = aurApp->GetTarget()->ToPlayer(); + if (!target) + return; + + if (apply) + target->ApplyBaseModPctValue(SHIELD_BLOCK_VALUE, float(GetAmount())); + else + { + float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT); + target->SetBaseModPctValue(SHIELD_BLOCK_VALUE, amount); + } } /********************************/ diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index 73640626b..8349c83fc 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -112,8 +112,6 @@ public: float GetPctMods() const { return m_pctMods; } void SetPctMods(float pctMods) { m_pctMods = pctMods; } - // xinef: stacking - uint32 GetAuraGroup() const { return m_auraGroup; } int32 GetOldAmount() const { return m_oldAmount; } void SetOldAmount(int32 amount) { m_oldAmount = amount; } void SetEnabled(bool enabled) { m_isAuraEnabled = enabled; } @@ -131,8 +129,6 @@ private: float m_critChance; float m_pctMods; - // xinef: stacking - uint32 m_auraGroup; int32 m_oldAmount; bool m_isAuraEnabled; // xinef: channel information for channel triggering @@ -299,6 +295,7 @@ public: void HandleModDamagePercentDone(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleModOffhandDamagePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleShieldBlockValue(AuraApplication const* aurApp, uint8 mode, bool apply) const; + void HandleShieldBlockValuePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const; // power cost void HandleModPowerCostPCT(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleModPowerCost(AuraApplication const* aurApp, uint8 mode, bool apply) const; diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 7d6260e24..0b3b35d59 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -181,67 +181,6 @@ void AuraApplication::_HandleEffect(uint8 effIndex, bool apply) // Remove all triggered by aura spells vs unlimited duration aurEff->CleanupTriggeredSpells(GetTarget()); } - - // Stacking! - if (uint32 groupId = aurEff->GetAuraGroup()) - { - SpellGroupStackFlags sFlag = sSpellMgr->GetGroupStackFlags(groupId); - if (!aurEff->IsPeriodic() && (sFlag & SPELL_GROUP_STACK_FLAG_EFFECT_EXCLUSIVE)) - { - AuraApplication* strongestApp = apply ? this : nullptr; - AuraEffect* strongestEff = apply ? aurEff : nullptr; - int32 amount = apply ? std::abs(aurEff->GetAmount()) : 0; - Unit* target = GetTarget(); - Unit::AuraEffectList const& auraList = target->GetAuraEffectsByType(aurEff->GetAuraType()); - for (Unit::AuraEffectList::const_iterator iter = auraList.begin(); iter != auraList.end(); ++iter) - { - if ((*iter)->GetAuraGroup() != groupId || (*iter) == strongestEff || (*iter)->GetBase()->IsRemoved()) - continue; - - // xinef: skip different misc values - if (aurEff->GetAuraType() != SPELL_AURA_230 /*SPELL_AURA_MOD_INCREASE_HEALTH_2*/ && aurEff->GetAuraType() != SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK && - aurEff->GetMiscValue() != (*iter)->GetMiscValue()) - continue; - - // xinef: should not happen - AuraApplication* aurApp = (*iter)->GetBase()->GetApplicationOfTarget(target->GetGUID()); - if (!aurApp) - continue; - - if (amount < std::abs((*iter)->GetForcedAmount())) - { - // xinef: if we have strongest aura and it is active, turn it off - // xinef: otherwise just save new aura; - if (strongestApp && strongestEff && strongestApp->IsActive(strongestEff->GetEffIndex())) - { - strongestEff->HandleEffect(strongestApp, AURA_EFFECT_HANDLE_CHANGE_AMOUNT, false); - if (!strongestEff->GetSpellInfo()->HasAreaAuraEffect()) - strongestEff->SetEnabled(false); - strongestApp->SetDisableMask(strongestEff->GetEffIndex()); - } - strongestApp = aurApp; - strongestEff = (*iter); - amount = std::abs((*iter)->GetAmount()); - } - // xinef: itered aura is weaker, deactivate if active - else if (aurApp->IsActive((*iter)->GetEffIndex())) - { - (*iter)->HandleEffect(aurApp, AURA_EFFECT_HANDLE_CHANGE_AMOUNT, false); - if (!(*iter)->GetSpellInfo()->HasAreaAuraEffect()) - (*iter)->SetEnabled(false); - aurApp->SetDisableMask((*iter)->GetEffIndex()); - } - } - - // xinef: if we have new strongest aura, and it is not active - if (strongestApp && strongestEff && !strongestApp->IsActive(strongestEff->GetEffIndex())) - { - strongestApp->RemoveDisableMask(strongestEff->GetEffIndex()); - strongestEff->SetEnabled(true); - strongestEff->HandleEffect(strongestApp, AURA_EFFECT_HANDLE_CHANGE_AMOUNT, true); - } - } - } SetNeedClientUpdate(); } @@ -661,6 +600,9 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply) if (!itr->second || itr->first->IsImmunedToSpell(GetSpellInfo()) || !CanBeAppliedOn(itr->first)) addUnit = false; + if (addUnit && !itr->first->IsHighestExclusiveAura(this, true)) + addUnit = false; + if (addUnit) { // persistent area aura does not hit flying targets @@ -684,7 +626,7 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply) for (Unit::AuraApplicationMap::iterator iter = itr->first->GetAppliedAuras().begin(); iter != itr->first->GetAppliedAuras().end(); ++iter) { Aura const* aura = iter->second->GetBase(); - if (!CanStackWith(aura, false)) + if (!CanStackWith(aura)) { addUnit = false; break; @@ -1069,6 +1011,16 @@ void Aura::RefreshSpellMods() player->RestoreAllSpellMods(0, this); } +bool Aura::HasMoreThanOneEffectForType(AuraType auraType) const +{ + uint32 count = 0; + for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects()) + if (HasEffect(spellEffectInfo.EffectIndex) && spellEffectInfo.ApplyAuraName == auraType) + ++count; + + return count > 1; +} + bool Aura::IsArea() const { for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) @@ -1589,7 +1541,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b // Alchemy: Mixology if (caster && caster->HasAura(53042) && caster->IsPlayer() && !caster->ToPlayer()->GetSession()->PlayerLoading()) { - if (sSpellMgr->GetSpellGroup(GetId()) == 1) /*Elixirs*/ + if (sSpellMgr->IsSpellMemberOfSpellGroup(GetId(), SPELL_GROUP_ELIXIR_BATTLE) || sSpellMgr->IsSpellMemberOfSpellGroup(GetId(), SPELL_GROUP_ELIXIR_GUARDIAN)) { if (caster->HasSpell(GetSpellInfo()->Effects[EFFECT_0].TriggerSpell)) { @@ -2018,7 +1970,7 @@ bool Aura::IsAuraStronger(Aura const* newAura) const return false; } -bool Aura::CanStackWith(Aura const* existingAura, bool remove) const +bool Aura::CanStackWith(Aura const* existingAura) const { // Can stack with self if (this == existingAura) @@ -2056,47 +2008,19 @@ bool Aura::CanStackWith(Aura const* existingAura, bool remove) const return false; // check spell group stack rules - // xinef: this assures us that both spells are in same group! - SpellGroupStackFlags stackFlags = sSpellMgr->CheckSpellGroupStackRules(m_spellInfo, existingSpellInfo, remove, IsArea()); - if (stackFlags) + switch (sSpellMgr->CheckSpellGroupStackRules(m_spellInfo, existingSpellInfo)) { - // xinef: same caster rule is bounded by spellfamily - if (sameCaster && m_spellInfo->SpellFamilyName == existingSpellInfo->SpellFamilyName && - (stackFlags & SPELL_GROUP_STACK_FLAG_NOT_SAME_CASTER)) + case SPELL_GROUP_STACK_RULE_EXCLUSIVE: + case SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST: // if it reaches this point, existing aura is lower/equal return false; - - // xinef: normal exclusive stacking, remove if auras are equal by effects - if (stackFlags & SPELL_GROUP_STACK_FLAG_EXCLUSIVE) - { - if (GetSpellInfo()->IsAuraEffectEqual(existingSpellInfo) || GetSpellInfo()->IsRankOf(existingSpellInfo)) - { - if (remove) - return IsAuraStronger(existingAura); - else - return existingAura->IsAuraStronger(this); - } - } - - // xinef: check priority before effect mask - SpellGroupSpecialFlags thisAuraFlag = sSpellMgr->GetSpellGroupSpecialFlags(GetId()); - SpellGroupSpecialFlags existingAuraFlag = sSpellMgr->GetSpellGroupSpecialFlags(existingSpellInfo->Id); - if (thisAuraFlag >= SPELL_GROUP_SPECIAL_FLAG_PRIORITY1 && thisAuraFlag <= SPELL_GROUP_SPECIAL_FLAG_PRIORITY4 && - existingAuraFlag >= SPELL_GROUP_SPECIAL_FLAG_PRIORITY1 && existingAuraFlag <= SPELL_GROUP_SPECIAL_FLAG_PRIORITY4) - { - if (thisAuraFlag < existingAuraFlag) - { + case SPELL_GROUP_STACK_RULE_EXCLUSIVE_FROM_SAME_CASTER: + if (sameCaster) return false; - } - } - - // xinef: forced strongest aura in group by flag - if (stackFlags & SPELL_GROUP_STACK_FLAG_FORCED_STRONGEST) - return !remove; - if (stackFlags & SPELL_GROUP_STACK_FLAG_FORCED_WEAKEST) - return remove; - - // xinef: forced return, handle all cases using available flags! - return !(stackFlags & SPELL_GROUP_STACK_FLAG_NEVER_STACK); + break; + case SPELL_GROUP_STACK_RULE_DEFAULT: + case SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT: + default: + break; } if (m_spellInfo->SpellFamilyName != existingSpellInfo->SpellFamilyName) diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index 7b7ab603e..8731299f8 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -153,6 +153,7 @@ public: uint8 GetCasterLevel() const { return m_casterLevel; } + bool HasMoreThanOneEffectForType(AuraType auraType) const; bool IsArea() const; bool IsPassive() const; bool IsDeathPersistent() const; @@ -188,7 +189,7 @@ public: void HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, bool apply, bool onReapply); bool CanBeAppliedOn(Unit* target); bool CheckAreaTarget(Unit* target); - bool CanStackWith(Aura const* checkAura, bool remove) const; + bool CanStackWith(Aura const* existingAura) const; bool IsAuraStronger(Aura const* newAura) const; // Proc system diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 681b90516..2d7a658d1 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -19,7 +19,6 @@ #include "ArenaSpectator.h" #include "BattlefieldMgr.h" #include "Battleground.h" -#include "BattlegroundIC.h" #include "CharmInfo.h" #include "CellImpl.h" #include "Common.h" @@ -33,7 +32,6 @@ #include "InstanceScript.h" #include "Log.h" #include "LootMgr.h" -#include "MapMgr.h" #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "Opcodes.h" @@ -41,6 +39,7 @@ #include "Player.h" #include "ScriptMgr.h" #include "SharedDefines.h" +#include "SpellAuraDefines.h" #include "SpellAuraEffects.h" #include "SpellInfo.h" #include "SpellMgr.h" @@ -1240,11 +1239,7 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge // Other special target selection goes here if (uint32 maxTargets = m_spellValue->MaxAffectedTargets) { - Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS); - for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j) - if ((*j)->IsAffectedOnSpell(m_spellInfo)) - maxTargets += (*j)->GetAmount(); - + maxTargets += m_caster->GetTotalAuraModifierByAffectMask(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS, m_spellInfo); Acore::Containers::RandomResize(targets, maxTargets); } @@ -1327,11 +1322,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge // Other special target selection goes here if (uint32 maxTargets = m_spellValue->MaxAffectedTargets) { - Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS); - for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j) - if ((*j)->IsAffectedOnSpell(m_spellInfo)) - maxTargets += (*j)->GetAmount(); - + maxTargets += m_caster->GetTotalAuraModifierByAffectMask(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS, m_spellInfo); Acore::Containers::RandomResize(targets, maxTargets); } @@ -6076,6 +6067,8 @@ SpellCastResult Spell::CheckCast(bool strict) } } + uint8 approximateAuraEffectMask = 0; + uint8 nonAuraEffectMask = 0; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { // for effects of spells that have only one target @@ -6561,6 +6554,11 @@ SpellCastResult Spell::CheckCast(bool strict) default: break; } + + if (m_spellInfo->Effects[i].IsAura()) + approximateAuraEffectMask |= 1 << i; + else if (m_spellInfo->Effects[i].IsEffect()) + nonAuraEffectMask |= 1 << i; } for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) @@ -6609,8 +6607,13 @@ SpellCastResult Spell::CheckCast(bool strict) if (target->IsCreature() && target->ToCreature()->IsVehicle()) return SPELL_FAILED_BAD_IMPLICIT_TARGETS; + // Allow SPELL_AURA_MOD_POSSESS to work on mounted players, + // but keep the old restriction for everything else. if (target->IsMounted()) - return SPELL_FAILED_CANT_BE_CHARMED; + { + if (!(target->IsPlayer() && m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_POSSESS)) + return SPELL_FAILED_CANT_BE_CHARMED; + } if (target->GetCharmerGUID()) return SPELL_FAILED_CHARMED; @@ -6718,6 +6721,13 @@ SpellCastResult Spell::CheckCast(bool strict) default: break; } + + // check if target already has the same type, but more powerful aura + if (!nonAuraEffectMask && (approximateAuraEffectMask & (1 << i)) && !m_spellInfo->IsTargetingArea()) + if (Unit* target = m_targets.GetUnitTarget()) + if (!target->IsHighestExclusiveAuraEffect(m_spellInfo, AuraType(m_spellInfo->Effects[i].ApplyAuraName), + m_spellInfo->Effects[i].CalcValue(m_caster, &m_spellValue->EffectBasePoints[i]), approximateAuraEffectMask, false)) + return SPELL_FAILED_AURA_BOUNCED; } // check trade slot case (last, for allow catch any another cast problems) @@ -6968,26 +6978,35 @@ bool Spell::CanAutoCast(Unit* target) { ObjectGuid targetguid = target->GetGUID(); - for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (m_spellInfo->Effects[j].Effect == SPELL_EFFECT_APPLY_AURA) + if (!spellEffectInfo.IsAura()) + continue; + + AuraType const& auraType = spellEffectInfo.ApplyAuraName; + Unit::AuraEffectList const& auras = target->GetAuraEffectsByType(auraType); + for (Unit::AuraEffectList::const_iterator auraIt = auras.begin(); auraIt != auras.end(); ++auraIt) { - if (m_spellInfo->StackAmount <= 1) - { - if (target->HasAuraEffect(m_spellInfo->Id, j)) - return false; - } - else - { - if (AuraEffect* aureff = target->GetAuraEffect(m_spellInfo->Id, j)) - if (aureff->GetBase()->GetStackAmount() >= m_spellInfo->StackAmount) - return false; - } - } - else if (m_spellInfo->Effects[j].IsAreaAuraEffect()) - { - if (target->HasAuraEffect(m_spellInfo->Id, j)) + if (GetSpellInfo()->Id == (*auraIt)->GetSpellInfo()->Id) return false; + + switch (sSpellMgr->CheckSpellGroupStackRules(GetSpellInfo(), (*auraIt)->GetSpellInfo())) + { + case SPELL_GROUP_STACK_RULE_EXCLUSIVE: + return false; + case SPELL_GROUP_STACK_RULE_EXCLUSIVE_FROM_SAME_CASTER: + if (GetCaster() == (*auraIt)->GetCaster()) + return false; + break; + case SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT: // this one has further checks, but i don't think they're necessary for autocast logic + case SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST: + if (abs(spellEffectInfo.BasePoints) <= abs((*auraIt)->GetAmount())) + return false; + break; + case SPELL_GROUP_STACK_RULE_DEFAULT: + default: + break; + } } } @@ -7905,7 +7924,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff) const case SPELL_AURA_AOE_CHARM: if (target->IsCreature() && target->IsVehicle()) return false; - if (target->IsMounted()) + if (target->IsMounted() && m_spellInfo->Effects[eff].ApplyAuraName != SPELL_AURA_MOD_POSSESS) return false; if (target->GetCharmerGUID()) return false; diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 3343c7059..d725b682e 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -1952,13 +1952,10 @@ void Spell::EffectEnergize(SpellEffIndex effIndex) Unit::AuraApplicationMap& Auras = unitTarget->GetAppliedAuras(); for (Unit::AuraApplicationMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr) { - SpellGroupSpecialFlags sFlag = sSpellMgr->GetSpellGroupSpecialFlags(itr->second->GetBase()->GetId()); - if (!guardianFound) - if (sFlag & SPELL_GROUP_SPECIAL_FLAG_ELIXIR_GUARDIAN) - guardianFound = true; - if (!battleFound) - if (sFlag & SPELL_GROUP_SPECIAL_FLAG_ELIXIR_BATTLE) - battleFound = true; + if (!guardianFound && sSpellMgr->IsSpellMemberOfSpellGroup(itr->second->GetBase()->GetId(), SPELL_GROUP_ELIXIR_GUARDIAN)) + guardianFound = true; + if (!battleFound && sSpellMgr->IsSpellMemberOfSpellGroup(itr->second->GetBase()->GetId(), SPELL_GROUP_ELIXIR_BATTLE)) + battleFound = true; if (battleFound && guardianFound) break; } @@ -1966,9 +1963,9 @@ void Spell::EffectEnergize(SpellEffIndex effIndex) // get all available elixirs by mask and spell level std::set availableElixirs; if (!guardianFound) - sSpellMgr->GetSetOfSpellsInSpellGroupWithFlag(1, SPELL_GROUP_SPECIAL_FLAG_ELIXIR_GUARDIAN, availableElixirs); + sSpellMgr->GetSetOfSpellsInSpellGroup(SPELL_GROUP_ELIXIR_GUARDIAN, availableElixirs); if (!battleFound) - sSpellMgr->GetSetOfSpellsInSpellGroupWithFlag(1, SPELL_GROUP_SPECIAL_FLAG_ELIXIR_BATTLE, availableElixirs); + sSpellMgr->GetSetOfSpellsInSpellGroup(SPELL_GROUP_ELIXIR_BATTLE, availableElixirs); for (std::set::iterator itr = availableElixirs.begin(); itr != availableElixirs.end();) { SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(*itr); @@ -3598,7 +3595,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) unitMod = UNIT_MOD_DAMAGE_RANGED; break; } - float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT); + float weapon_total_pct = m_caster->GetPctModifierValue(unitMod, TOTAL_PCT); fixed_bonus = int32(fixed_bonus * weapon_total_pct); spell_bonus = int32(spell_bonus * weapon_total_pct); } diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 2a5490043..74b89e99b 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -326,9 +326,9 @@ std::array SpellImplic SpellEffectInfo::SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const* spellInfo, uint8 effIndex) { _spellInfo = spellInfo; - _effIndex = effIndex; + EffectIndex = effIndex; Effect = spellEntry->Effect[effIndex]; - ApplyAuraName = spellEntry->EffectApplyAuraName[effIndex]; + ApplyAuraName = AuraType(spellEntry->EffectApplyAuraName[effIndex]); Amplitude = spellEntry->EffectAmplitude[effIndex]; DieSides = spellEntry->EffectDieSides[effIndex]; RealPointsPerLevel = spellEntry->EffectRealPointsPerLevel[effIndex]; @@ -456,7 +456,7 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const value += PointsPerComboPoint * comboPoints; } - value = caster->ApplyEffectModifiers(_spellInfo, _effIndex, value); + value = caster->ApplyEffectModifiers(_spellInfo, EffectIndex, value); // amount multiplication based on caster's level if (!caster->IsControlledByPlayer() && @@ -501,7 +501,7 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const break; } - if ((sSpellMgr->GetSpellInfo(_spellInfo->Effects[_effIndex].TriggerSpell) && sSpellMgr->GetSpellInfo(_spellInfo->Effects[_effIndex].TriggerSpell)->HasAttribute(SPELL_ATTR0_SCALES_WITH_CREATURE_LEVEL)) && _spellInfo->HasAttribute(SPELL_ATTR0_SCALES_WITH_CREATURE_LEVEL)) + if ((sSpellMgr->GetSpellInfo(_spellInfo->Effects[EffectIndex].TriggerSpell) && sSpellMgr->GetSpellInfo(_spellInfo->Effects[EffectIndex].TriggerSpell)->HasAttribute(SPELL_ATTR0_SCALES_WITH_CREATURE_LEVEL)) && _spellInfo->HasAttribute(SPELL_ATTR0_SCALES_WITH_CREATURE_LEVEL)) canEffectScale = false; if (canEffectScale) @@ -1579,122 +1579,6 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a return SPELL_CAST_OK; } - -bool SpellInfo::IsStrongerAuraActive(Unit const* caster, Unit const* target) const -{ - if (!target) - return false; - - // xinef: check spell group - uint32 groupId = sSpellMgr->GetSpellGroup(Id); - if (!groupId) - return false; - - SpellGroupSpecialFlags sFlag = sSpellMgr->GetSpellGroupSpecialFlags(Id); - if (sFlag & SPELL_GROUP_SPECIAL_FLAG_SKIP_STRONGER_CHECK) - return false; - - for (uint8 i = EFFECT_0; i < MAX_SPELL_EFFECTS; ++i) - { - // xinef: Skip Empty effects - if (!Effects[i].IsEffect()) - continue; - - // xinef: if non-aura effect is preset - return false - if (!Effects[i].IsAura()) - return false; - - // xinef: aura is periodic - return false - if (Effects[i].Amplitude) - return false; - - // xinef: exclude dummy auras - if (Effects[i].ApplyAuraName == SPELL_AURA_DUMMY) - return false; - } - - for (uint8 i = EFFECT_0; i < MAX_SPELL_EFFECTS; ++i) - { - // xinef: skip non-aura efects - if (!Effects[i].IsAura()) - return false; - - Unit::AuraEffectList const& auraList = target->GetAuraEffectsByType((AuraType)Effects[i].ApplyAuraName); - for (Unit::AuraEffectList::const_iterator iter = auraList.begin(); iter != auraList.end(); ++iter) - { - // xinef: aura is not groupped or in different group - uint32 auraGroup = (*iter)->GetAuraGroup(); - if (!auraGroup || auraGroup != groupId) - continue; - - if (IsRankOf((*iter)->GetSpellInfo()) && (sFlag & SPELL_GROUP_SPECIAL_FLAG_SKIP_STRONGER_SAME_SPELL)) - { - continue; - } - - // xinef: check priority before effect mask - if (sFlag >= SPELL_GROUP_SPECIAL_FLAG_PRIORITY1 && sFlag <= SPELL_GROUP_SPECIAL_FLAG_PRIORITY4) - { - SpellGroupSpecialFlags sFlagCurr = sSpellMgr->GetSpellGroupSpecialFlags((*iter)->GetId()); - if (sFlagCurr >= SPELL_GROUP_SPECIAL_FLAG_PRIORITY1 && sFlagCurr <= SPELL_GROUP_SPECIAL_FLAG_PRIORITY4 && sFlagCurr < sFlag) - { - return true; - } - } - - // xinef: check aura effect equal auras only, some auras have different effects on different ranks - check rank also - if (!IsAuraEffectEqual((*iter)->GetSpellInfo()) && !IsRankOf((*iter)->GetSpellInfo())) - continue; - - // xinef: misc value mismatches - // xinef: commented, checked above - //if (Effects[i].MiscValue != (*iter)->GetMiscValue()) - // continue; - - // xinef: should not happen, or effect is not active - stronger one is present - AuraApplication* aurApp = (*iter)->GetBase()->GetApplicationOfTarget(target->GetGUID()); - if (!aurApp || !aurApp->IsActive((*iter)->GetEffIndex())) - continue; - - // xinef: assume that all spells are either positive or negative, otherwise they should not be in one group - // xinef: take custom values into account - - int32 basePoints = Effects[i].BasePoints; - int32 duration = GetMaxDuration(); - - // xinef: should have the same id, can be different if spell is triggered - // xinef: have to fix spell mods for triggered spell, turn off current spellmodtakingspell for preparing and restore after - if (Player const* player = caster->GetSpellModOwner()) - if (player->m_spellModTakingSpell && player->m_spellModTakingSpell->m_spellInfo->Id == Id) - basePoints = player->m_spellModTakingSpell->GetSpellValue()->EffectBasePoints[i]; - - int32 curValue = std::abs(Effects[i].CalcValue(caster, &basePoints)); - int32 auraValue = (sFlag & SPELL_GROUP_SPECIAL_FLAG_BASE_AMOUNT_CHECK) ? - std::abs((*iter)->GetSpellInfo()->Effects[(*iter)->GetEffIndex()].CalcValue((*iter)->GetCaster())) : - std::abs((*iter)->GetAmount()); - - // xinef: for same spells, divide amount by stack amount - if (Id == (*iter)->GetId()) - auraValue /= (*iter)->GetBase()->GetStackAmount(); - - if (curValue < auraValue) - return true; - - // xinef: little hack, if current spell is the same as aura spell, asume it is not stronger - // xinef: if values are the same, duration mods should be taken into account but they are almost always passive - if (curValue == auraValue) - { - if (Id == (*iter)->GetId()) - continue; - if (!(*iter)->GetBase()->IsPassive() && duration < (*iter)->GetBase()->GetDuration()) - return true; - } - } - } - - return false; -} - bool SpellInfo::IsAuraEffectEqual(SpellInfo const* otherSpellInfo) const { uint8 matchCount = 0; @@ -1938,10 +1822,6 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* ta if (HasEffect(SPELL_EFFECT_SELF_RESURRECT) || HasEffect(SPELL_EFFECT_RESURRECT) || HasEffect(SPELL_EFFECT_RESURRECT_NEW)) return SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED; - // xinef: check if stronger aura is active - if (IsStrongerAuraActive(caster, unitTarget)) - return SPELL_FAILED_AURA_BOUNCED; - return SPELL_CAST_OK; } @@ -2316,6 +2196,8 @@ SpellSpecificType SpellInfo::LoadSpellSpecific() const case SPELL_AURA_TRACK_RESOURCES: case SPELL_AURA_TRACK_STEALTHED: return SPELL_SPECIFIC_TRACKER; + default: + break; } } } @@ -2399,6 +2281,8 @@ uint32 SpellInfo::GetMaxTicks() const if (Effects[x].Amplitude != 0) return DotDuration / Effects[x].Amplitude; break; + default: + break; } } @@ -2889,50 +2773,3 @@ void SpellInfo::_UnloadImplicitTargetConditionLists() delete cur; } } - -bool SpellInfo::CheckElixirStacking(Unit const* caster) const -{ - if (!caster) - { - return true; - } - - // xinef: check spell group - uint32 groupId = sSpellMgr->GetSpellGroup(Id); - if (groupId != SPELL_GROUP_GUARDIAN_AND_BATTLE_ELIXIRS) - { - return true; - } - - SpellGroupSpecialFlags sFlag = sSpellMgr->GetSpellGroupSpecialFlags(Id); - for (uint8 i = EFFECT_0; i < MAX_SPELL_EFFECTS; ++i) - { - if (!Effects[i].IsAura()) - { - continue; - } - - Unit::AuraApplicationMap const& Auras = caster->GetAppliedAuras(); - for (Unit::AuraApplicationMap::const_iterator itr = Auras.begin(); itr != Auras.end(); ++itr) - { - // xinef: aura is not groupped or in different group - uint32 auraGroup = sSpellMgr->GetSpellGroup(itr->first); - if (auraGroup != groupId) - { - continue; - } - - // Cannot apply guardian/battle elixir if flask is present - if (sFlag == SPELL_GROUP_SPECIAL_FLAG_ELIXIR_BATTLE || sFlag == SPELL_GROUP_SPECIAL_FLAG_ELIXIR_GUARDIAN) - { - SpellGroupSpecialFlags sAuraFlag = sSpellMgr->GetSpellGroupSpecialFlags(itr->first); - if ((sAuraFlag & SPELL_GROUP_SPECIAL_FLAG_FLASK) == SPELL_GROUP_SPECIAL_FLAG_FLASK) - { - return false; - } - } - } - } - - return true; -} diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index eba1ad901..50b6d88d4 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -248,10 +248,10 @@ private: class SpellEffectInfo { SpellInfo const* _spellInfo; - uint8 _effIndex; public: + uint8 EffectIndex; uint32 Effect; - uint32 ApplyAuraName; + AuraType ApplyAuraName; uint32 Amplitude; int32 DieSides; float RealPointsPerLevel; @@ -272,7 +272,7 @@ public: flag96 SpellClassMask; std::list* ImplicitTargetConditions; - SpellEffectInfo() : _spellInfo(nullptr), _effIndex(0), Effect(0), ApplyAuraName(0), Amplitude(0), DieSides(0), + SpellEffectInfo() : _spellInfo(nullptr), EffectIndex(0), Effect(0), ApplyAuraName(SPELL_AURA_NONE), Amplitude(0), DieSides(0), RealPointsPerLevel(0), BasePoints(0), PointsPerComboPoint(0), ValueMultiplier(0), DamageMultiplier(0), BonusMultiplier(0), MiscValue(0), MiscValueB(0), Mechanic(MECHANIC_NONE), RadiusEntry(nullptr), ChainTarget(0), ItemType(0), TriggerSpell(0), ImplicitTargetConditions(nullptr) {} @@ -482,8 +482,6 @@ public: SpellCastResult CheckExplicitTarget(Unit const* caster, WorldObject const* target, Item const* itemTarget = nullptr) const; bool CheckTargetCreatureType(Unit const* target) const; - // xinef: aura stacking - bool IsStrongerAuraActive(Unit const* caster, Unit const* target) const; bool IsAuraEffectEqual(SpellInfo const* otherSpellInfo) const; bool ValidateAttribute6SpellDamageMods(Unit const* caster, const AuraEffect* auraEffect, bool isDot) const; @@ -539,8 +537,6 @@ public: // unloading helpers void _UnloadImplicitTargetConditionLists(); - bool CheckElixirStacking(Unit const* caster) const; - private: std::array& _GetEffects() { return Effects; } SpellEffectInfo& _GetEffect(SpellEffIndex index) { ASSERT(index < Effects.size()); return Effects[index]; } diff --git a/src/server/game/Spells/SpellInfoCorrections.cpp b/src/server/game/Spells/SpellInfoCorrections.cpp index c474996c9..0615f39c0 100644 --- a/src/server/game/Spells/SpellInfoCorrections.cpp +++ b/src/server/game/Spells/SpellInfoCorrections.cpp @@ -570,14 +570,6 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->AttributesEx3 |= SPELL_ATTR3_SUPPRESS_CASTER_PROCS; }); - // Blessing of sanctuary stats - ApplySpellFix({ 67480 }, [](SpellInfo* spellInfo) - { - spellInfo->Effects[EFFECT_0].MiscValue = -1; - spellInfo->SpellFamilyName = SPELLFAMILY_UNK1; // allows stacking - spellInfo->Effects[EFFECT_1].ApplyAuraName = SPELL_AURA_DUMMY; // just a marker - }); - ApplySpellFix({ 6940, // Hand of Sacrifice 64205 // Divine Sacrifice @@ -5164,6 +5156,20 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->AttributesEx3 |= SPELL_ATTR3_DOT_STACKING_RULE; }); + // King Mrlg-Mrgl's Spare Suit + ApplySpellFix({ 45278 }, [](SpellInfo* spellInfo) + { + spellInfo->ProcCharges = 1; + }); + + ApplySpellFix({ + 56917, // To Icecrown Airship - Teleport to Airship (A) + 57417, // To Icecrown Airship - Teleport to Airship (H) + }, [](SpellInfo* spellInfo) + { + spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(6); // 100 yards + }); + for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i) { SpellInfo* spellInfo = mSpellInfoMap[i]; @@ -5285,14 +5291,6 @@ void SpellMgr::LoadSpellInfoCorrections() factionTemplateEntry = const_cast(sFactionTemplateStore.LookupEntry(1921)); // The Taunka factionTemplateEntry->hostileMask |= 8; - // Remove 1 from guards friendly mask, making able to attack players - factionTemplateEntry = const_cast(sFactionTemplateStore.LookupEntry(1857)); // Area 52 Bruiser - factionTemplateEntry->friendlyMask &= ~1; - factionTemplateEntry = const_cast(sFactionTemplateStore.LookupEntry(1806)); // Netherstorm Agent - factionTemplateEntry->friendlyMask &= ~1; - factionTemplateEntry = const_cast(sFactionTemplateStore.LookupEntry(1812)); // K3 Bruiser - factionTemplateEntry->friendlyMask &= ~1; - // Remove vehicles attr, making accessories selectable VehicleSeatEntry* vse = const_cast(sVehicleSeatStore.LookupEntry(4689)); // Siege Engine, Accessory vse->m_flags &= ~VEHICLE_SEAT_FLAG_PASSENGER_NOT_SELECTABLE; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index f424be399..ba297d458 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -18,12 +18,9 @@ #include "SpellMgr.h" #include "BattlefieldMgr.h" #include "BattlegroundIC.h" -#include "BattlegroundMgr.h" #include "Chat.h" #include "DBCStores.h" -#include "GameGraveyard.h" #include "InstanceScript.h" -#include "MapMgr.h" #include "ObjectMgr.h" #include "Player.h" #include "ScriptMgr.h" @@ -648,82 +645,143 @@ SpellTargetPosition const* SpellMgr::GetSpellTargetPosition(uint32 spell_id, Spe return nullptr; } -SpellGroupStackFlags SpellMgr::GetGroupStackFlags(uint32 groupid) const +SpellSpellGroupMapBounds SpellMgr::GetSpellSpellGroupMapBounds(uint32 spell_id) const { - SpellGroupStackMap::const_iterator itr = mSpellGroupStackMap.find(groupid); - if (itr != mSpellGroupStackMap.end()) + spell_id = GetFirstSpellInChain(spell_id); + return mSpellSpellGroup.equal_range(spell_id); +} + +bool SpellMgr::IsSpellMemberOfSpellGroup(uint32 spell_id, SpellGroup group_id) const +{ + SpellSpellGroupMapBounds spellGroup = GetSpellSpellGroupMapBounds(spell_id); + for (SpellSpellGroupMap::const_iterator itr = spellGroup.first; itr != spellGroup.second; ++itr) + { + if (itr->second == group_id) + return true; + } + return false; +} + +SpellGroupSpellMapBounds SpellMgr::GetSpellGroupSpellMapBounds(SpellGroup group_id) const +{ + return mSpellGroupSpell.equal_range(group_id); +} + +void SpellMgr::GetSetOfSpellsInSpellGroup(SpellGroup group_id, std::set& foundSpells) const +{ + std::set usedGroups; + GetSetOfSpellsInSpellGroup(group_id, foundSpells, usedGroups); +} + +void SpellMgr::GetSetOfSpellsInSpellGroup(SpellGroup group_id, std::set& foundSpells, std::set& usedGroups) const +{ + if (usedGroups.find(group_id) != usedGroups.end()) + return; + usedGroups.insert(group_id); + + SpellGroupSpellMapBounds groupSpell = GetSpellGroupSpellMapBounds(group_id); + for (SpellGroupSpellMap::const_iterator itr = groupSpell.first; itr != groupSpell.second; ++itr) + { + if (itr->second < 0) + { + SpellGroup currGroup = (SpellGroup)abs(itr->second); + GetSetOfSpellsInSpellGroup(currGroup, foundSpells, usedGroups); + } + else + { + foundSpells.insert(itr->second); + } + } +} + +bool SpellMgr::AddSameEffectStackRuleSpellGroups(SpellInfo const* spellInfo, uint32 auraType, int32 amount, std::map& groups) const +{ + uint32 spellId = spellInfo->GetFirstRankSpell()->Id; + auto spellGroupBounds = GetSpellSpellGroupMapBounds(spellId); + // Find group with SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT if it belongs to one + for (auto itr = spellGroupBounds.first; itr != spellGroupBounds.second; ++itr) + { + SpellGroup group = itr->second; + auto found = mSpellSameEffectStack.find(group); + if (found != mSpellSameEffectStack.end()) + { + // check auraTypes + if (!found->second.count(auraType)) + continue; + + // Put the highest amount in the map + auto groupItr = groups.find(group); + if (groupItr == groups.end()) + groups.emplace(group, amount); + else + { + int32 curr_amount = groups[group]; + // Take absolute value because this also counts for the highest negative aura + if (std::abs(curr_amount) < std::abs(amount)) + groupItr->second = amount; + } + // return because a spell should be in only one SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT group per auraType + return true; + } + } + // Not in a SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT group, so return false + return false; +} + +SpellGroupStackRule SpellMgr::CheckSpellGroupStackRules(SpellInfo const* spellInfo1, SpellInfo const* spellInfo2) const +{ + ASSERT(spellInfo1); + ASSERT(spellInfo2); + + uint32 spell_id1 = spellInfo1->GetFirstRankSpell()->Id; + uint32 spell_id2 = spellInfo2->GetFirstRankSpell()->Id; + + // find SpellGroups which are common for both spells + SpellSpellGroupMapBounds spellGroup1 = GetSpellSpellGroupMapBounds(spell_id1); + std::set groups; + for (SpellSpellGroupMap::const_iterator itr = spellGroup1.first; itr != spellGroup1.second; ++itr) + { + if (IsSpellMemberOfSpellGroup(spell_id2, itr->second)) + { + bool add = true; + SpellGroupSpellMapBounds groupSpell = GetSpellGroupSpellMapBounds(itr->second); + for (SpellGroupSpellMap::const_iterator itr2 = groupSpell.first; itr2 != groupSpell.second; ++itr2) + { + if (itr2->second < 0) + { + SpellGroup currGroup = (SpellGroup)abs(itr2->second); + if (IsSpellMemberOfSpellGroup(spell_id1, currGroup) && IsSpellMemberOfSpellGroup(spell_id2, currGroup)) + { + add = false; + break; + } + } + } + if (add) + groups.insert(itr->second); + } + } + + SpellGroupStackRule rule = SPELL_GROUP_STACK_RULE_DEFAULT; + + for (std::set::iterator itr = groups.begin(); itr!= groups.end(); ++itr) + { + SpellGroupStackMap::const_iterator found = mSpellGroupStack.find(*itr); + if (found != mSpellGroupStack.end()) + rule = found->second; + if (rule) + break; + } + return rule; +} + +SpellGroupStackRule SpellMgr::GetSpellGroupStackRule(SpellGroup group) const +{ + SpellGroupStackMap::const_iterator itr = mSpellGroupStack.find(group); + if (itr != mSpellGroupStack.end()) return itr->second; - return SPELL_GROUP_STACK_FLAG_NONE; -} - -uint32 SpellMgr::GetSpellGroup(uint32 spell_id) const -{ - uint32 first_rank = GetFirstSpellInChain(spell_id); - SpellGroupMap::const_iterator itr = mSpellGroupMap.find(first_rank); - if (itr != mSpellGroupMap.end()) - return itr->second.groupId; - - return 0; -} - -SpellGroupSpecialFlags SpellMgr::GetSpellGroupSpecialFlags(uint32 spell_id) const -{ - uint32 first_rank = GetFirstSpellInChain(spell_id); - SpellGroupMap::const_iterator itr = mSpellGroupMap.find(first_rank); - if (itr != mSpellGroupMap.end()) - return itr->second.specialFlags; - - return SPELL_GROUP_SPECIAL_FLAG_NONE; -} - -SpellGroupStackFlags SpellMgr::CheckSpellGroupStackRules(SpellInfo const* spellInfo1, SpellInfo const* spellInfo2, bool remove, bool areaAura) const -{ - uint32 spellid_1 = spellInfo1->GetFirstRankSpell()->Id; - uint32 spellid_2 = spellInfo2->GetFirstRankSpell()->Id; - - uint32 groupId = GetSpellGroup(spellid_1); - - SpellGroupSpecialFlags flag1 = GetSpellGroupSpecialFlags(spellid_1); - - // xinef: dunno why i added this - if (spellid_1 == spellid_2 && remove && !areaAura) - { - if (flag1 & SPELL_GROUP_SPECIAL_FLAG_SAME_SPELL_CHECK) - { - return SPELL_GROUP_STACK_FLAG_EXCLUSIVE; - } - - return SPELL_GROUP_STACK_FLAG_NONE; - } - - if (groupId > 0 && groupId == GetSpellGroup(spellid_2)) - { - SpellGroupSpecialFlags flag2 = GetSpellGroupSpecialFlags(spellid_2); - SpellGroupStackFlags additionFlag = SPELL_GROUP_STACK_FLAG_NONE; - // xinef: first flags are used for elixir stacking rules - if (flag1 & SPELL_GROUP_SPECIAL_FLAG_STACK_EXCLUSIVE_MAX && flag2 & SPELL_GROUP_SPECIAL_FLAG_STACK_EXCLUSIVE_MAX) - { - if (flag1 & flag2) - return SPELL_GROUP_STACK_FLAG_NEVER_STACK; - } - // xinef: check only flag1 (new spell) - else if (flag1 & SPELL_GROUP_SPECIAL_FLAG_FORCED_STRONGEST) - additionFlag = SPELL_GROUP_STACK_FLAG_FORCED_STRONGEST; - else if (flag2 & SPELL_GROUP_SPECIAL_FLAG_FORCED_STRONGEST) - additionFlag = SPELL_GROUP_STACK_FLAG_FORCED_WEAKEST; - - return SpellGroupStackFlags(GetGroupStackFlags(groupId) | additionFlag); - } - - return SPELL_GROUP_STACK_FLAG_NONE; -} - -void SpellMgr::GetSetOfSpellsInSpellGroupWithFlag(uint32 group_id, SpellGroupSpecialFlags flag, std::set& availableElixirs) const -{ - for (SpellGroupMap::const_iterator itr = mSpellGroupMap.begin(); itr != mSpellGroupMap.end(); ++itr) - if (itr->second.groupId == group_id && itr->second.specialFlags == flag) - availableElixirs.insert(itr->first); // insert spell id + return SPELL_GROUP_STACK_RULE_DEFAULT; } SpellProcEventEntry const* SpellMgr::GetSpellProcEvent(uint32 spellId) const @@ -1627,10 +1685,11 @@ void SpellMgr::LoadSpellGroups() { uint32 oldMSTime = getMSTime(); - mSpellGroupMap.clear(); // need for reload case + mSpellSpellGroup.clear(); // need for reload case + mSpellGroupSpell.clear(); - // 0 1 2 - QueryResult result = WorldDatabase.Query("SELECT id, spell_id, special_flag FROM spell_group"); + // 0 1 + QueryResult result = WorldDatabase.Query("SELECT id, spell_id FROM spell_group"); if (!result) { LOG_WARN("server.loading", ">> Loaded 0 spell group definitions. DB table `spell_group` is empty."); @@ -1638,48 +1697,68 @@ void SpellMgr::LoadSpellGroups() return; } + std::set groups; uint32 count = 0; do { Field* fields = result->Fetch(); uint32 group_id = fields[0].Get(); - int32 spell_id = fields[1].Get(); - SpellGroupSpecialFlags specialFlag = (SpellGroupSpecialFlags)fields[2].Get(); - SpellInfo const* spellInfo = GetSpellInfo(spell_id); - - if (!spellInfo) + if (group_id <= SPELL_GROUP_DB_RANGE_MIN && group_id >= SPELL_GROUP_CORE_RANGE_MAX) { - LOG_ERROR("sql.sql", "Spell {} listed in `spell_group` does not exist", spell_id); - continue; - } - else if (spellInfo->GetRank() > 1) - { - LOG_ERROR("sql.sql", "Spell {} listed in `spell_group` is not first rank of spell", spell_id); + LOG_ERROR("sql.sql", "SpellGroup id {} listed in `spell_group` is in core range, but is not defined in core!", group_id); continue; } + int32 spell_id = fields[1].Get(); - if (mSpellGroupMap.find(spell_id) != mSpellGroupMap.end()) - { - LOG_ERROR("sql.sql", "Spell {} listed in `spell_group` has more than one group", spell_id); - continue; - } + groups.insert(group_id); + mSpellGroupSpell.emplace(SpellGroup(group_id), spell_id); - if (specialFlag >= SPELL_GROUP_SPECIAL_FLAG_MAX) - { - LOG_ERROR("sql.sql", "Spell {} listed in `spell_group` has invalid special flag!", spell_id); - continue; - } - - SpellStackInfo ssi; - ssi.groupId = group_id; - ssi.specialFlags = specialFlag; - mSpellGroupMap[spell_id] = ssi; - - ++count; } while (result->NextRow()); - LOG_INFO("server.loading", ">> Loaded {} Spell Group Definitions in {} ms", count, GetMSTimeDiffToNow(oldMSTime)); + for (auto itr = mSpellGroupSpell.begin(); itr!= mSpellGroupSpell.end();) + { + if (itr->second < 0) + { + if (groups.find(abs(itr->second)) == groups.end()) + { + LOG_ERROR("sql.sql", "SpellGroup id {} listed in `spell_group` does not exist", abs(itr->second)); + itr = mSpellGroupSpell.erase(itr); + } + else + ++itr; + } + else + { + SpellInfo const* spellInfo = GetSpellInfo(itr->second); + if (!spellInfo) + { + LOG_ERROR("sql.sql", "Spell {} listed in `spell_group` does not exist", itr->second); + itr = mSpellGroupSpell.erase(itr); + } + else if (spellInfo->GetRank() > 1) + { + LOG_ERROR("sql.sql", "Spell {} listed in `spell_group` is not first rank of spell.", itr->second); + itr = mSpellGroupSpell.erase(itr); + } + else + ++itr; + } + } + + for (auto groupItr = groups.begin(); groupItr != groups.end(); ++groupItr) + { + std::set spells; + GetSetOfSpellsInSpellGroup(SpellGroup(*groupItr), spells); + + for (auto spellItr = spells.begin(); spellItr != spells.end(); ++spellItr) + { + ++count; + mSpellSpellGroup.emplace(*spellItr, SpellGroup(*groupItr)); + } + } + + LOG_INFO("server.loading", ">> Loaded {} spell group Definitions in {} ms", count, GetMSTimeDiffToNow(oldMSTime)); LOG_INFO("server.loading", " "); } @@ -1687,7 +1766,10 @@ void SpellMgr::LoadSpellGroupStackRules() { uint32 oldMSTime = getMSTime(); - mSpellGroupStackMap.clear(); // need for reload case + mSpellGroupStack.clear(); // need for reload case + mSpellSameEffectStack.clear(); + + std::vector sameEffectGroups; // 0 1 QueryResult result = WorldDatabase.Query("SELECT group_id, stack_rule FROM spell_group_stack_rules"); @@ -1705,32 +1787,132 @@ void SpellMgr::LoadSpellGroupStackRules() uint32 group_id = fields[0].Get(); uint8 stack_rule = fields[1].Get(); - if (stack_rule >= SPELL_GROUP_STACK_FLAG_MAX) + if (stack_rule >= SPELL_GROUP_STACK_RULE_MAX) { - LOG_ERROR("sql.sql", "SpellGroupStackRule {} listed in `spell_group_stack_rules` does not exist", stack_rule); + LOG_ERROR("sql.sql", "SpellGroupStackRule {} listed in `spell_group_stack_rules` does not exist.", stack_rule); continue; } - bool present = false; - for (SpellGroupMap::const_iterator itr = mSpellGroupMap.begin(); itr != mSpellGroupMap.end(); ++itr) - if (itr->second.groupId == group_id) - { - present = true; - break; - } - - if (!present) + auto bounds = GetSpellGroupSpellMapBounds((SpellGroup)group_id); + if (bounds.first == bounds.second) { - LOG_ERROR("sql.sql", "SpellGroup id {} listed in `spell_group_stack_rules` does not exist", group_id); + LOG_ERROR("sql.sql", "SpellGroup id {} listed in `spell_group_stack_rules` does not exist.", group_id); continue; } - mSpellGroupStackMap[group_id] = (SpellGroupStackFlags)stack_rule; + mSpellGroupStack.emplace(SpellGroup(group_id), SpellGroupStackRule(stack_rule)); + + // different container for same effect stack rules, need to check effect types + if (stack_rule == SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT) + sameEffectGroups.push_back(group_id); ++count; } while (result->NextRow()); - LOG_INFO("server.loading", ">> Loaded {} Spell Group Stack Rules in {} ms", count, GetMSTimeDiffToNow(oldMSTime)); + LOG_INFO("server.loading", ">> Loaded {} spell group stack rules in {} ms", count, GetMSTimeDiffToNow(oldMSTime)); + LOG_INFO("server.loading", " "); + + count = 0; + oldMSTime = getMSTime(); + + for (uint32 group_id : sameEffectGroups) + { + std::set spellIds; + GetSetOfSpellsInSpellGroup(SpellGroup(group_id), spellIds); + + std::unordered_set auraTypes; + + // we have to 'guess' what effect this group corresponds to + { + std::unordered_multiset frequencyContainer; + + // only waylay for the moment (shared group) + std::vector> const SubGroups = + { + { SPELL_AURA_MOD_MELEE_HASTE, SPELL_AURA_MOD_MELEE_RANGED_HASTE, SPELL_AURA_MOD_RANGED_HASTE } + }; + + for (uint32 spellId : spellIds) + { + SpellInfo const* spellInfo = AssertSpellInfo(spellId); + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) + { + if (!spellEffectInfo.IsAura()) + continue; + + uint32 auraName = spellEffectInfo.ApplyAuraName; + for (std::vector const& subGroup : SubGroups) + { + if (std::find(subGroup.begin(), subGroup.end(), auraName) != subGroup.end()) + { + // count as first aura + auraName = subGroup.front(); + break; + } + } + + frequencyContainer.insert(auraName); + } + } + + uint32 auraType = 0; + size_t auraTypeCount = 0; + for (uint32 auraName : frequencyContainer) + { + size_t currentCount = frequencyContainer.count(auraName); + if (currentCount > auraTypeCount) + { + auraType = auraName; + auraTypeCount = currentCount; + } + } + + for (std::vector const& subGroup : SubGroups) + { + if (auraType == subGroup.front()) + { + auraTypes.insert(subGroup.begin(), subGroup.end()); + break; + } + } + + if (auraTypes.empty()) + auraTypes.insert(auraType); + } + + // re-check spells against guessed group + for (uint32 spellId : spellIds) + { + SpellInfo const* spellInfo = AssertSpellInfo(spellId); + + bool found = false; + while (spellInfo) + { + for (uint32 auraType : auraTypes) + { + if (spellInfo->HasAura(AuraType(auraType))) + { + found = true; + break; + } + } + + if (found) + break; + + spellInfo = spellInfo->GetNextRankSpell(); + } + + // not found either, log error + if (!found) + LOG_ERROR("sql.sql", "SpellId {} listed in `spell_group` with stack rule 3 does not share aura assigned for group {}", spellId, group_id); + } + + mSpellSameEffectStack[SpellGroup(group_id)] = auraTypes; + ++count; + } + + LOG_INFO("server.loading", ">> Loaded {} SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT stack rules in {} ms", count, GetMSTimeDiffToNow(oldMSTime)); LOG_INFO("server.loading", " "); } @@ -2920,6 +3102,8 @@ void SpellMgr::LoadSpellInfoCustomAttributes() case SPELL_AURA_WATER_BREATHING: spellInfo->AttributesCu |= SPELL_ATTR0_CU_NO_INITIAL_THREAT; break; + default: + break; } switch (spellInfo->Effects[j].ApplyAuraName) @@ -3494,6 +3678,9 @@ void SpellMgr::LoadSpellInfoCustomAttributes() if (triggerSpell->AttributesCu & SPELL_ATTR0_CU_BINARY_SPELL) allNonBinary = false; } + break; + default: + break; } } } diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index feb1e4f7e..30220e151 100644 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -20,7 +20,6 @@ // For static or at-server-startup loaded spell data -#include "Common.h" #include "Log.h" #include "SharedDefines.h" #include "Unit.h" @@ -330,56 +329,49 @@ struct SpellBonusEntry typedef std::unordered_map SpellBonusMap; -enum SpellGroupSpecialFlags +enum SpellGroup { - SPELL_GROUP_SPECIAL_FLAG_NONE = 0x000, - SPELL_GROUP_SPECIAL_FLAG_ELIXIR_BATTLE = 0x001, - SPELL_GROUP_SPECIAL_FLAG_ELIXIR_GUARDIAN = 0x002, - SPELL_GROUP_SPECIAL_FLAG_ELIXIR_UNSTABLE = 0x004, - SPELL_GROUP_SPECIAL_FLAG_ELIXIR_SHATTRATH = 0x008, - SPELL_GROUP_SPECIAL_FLAG_STACK_EXCLUSIVE_MAX = 0x00F, - SPELL_GROUP_SPECIAL_FLAG_FORCED_STRONGEST = 0x010, // xinef: specially helpful flag if some spells have different auras, but only one should be present - SPELL_GROUP_SPECIAL_FLAG_SKIP_STRONGER_CHECK = 0x020, - SPELL_GROUP_SPECIAL_FLAG_BASE_AMOUNT_CHECK = 0x040, - SPELL_GROUP_SPECIAL_FLAG_PRIORITY1 = 0x100, - SPELL_GROUP_SPECIAL_FLAG_PRIORITY2 = 0x200, - SPELL_GROUP_SPECIAL_FLAG_PRIORITY3 = 0x400, - SPELL_GROUP_SPECIAL_FLAG_PRIORITY4 = 0x800, - SPELL_GROUP_SPECIAL_FLAG_SAME_SPELL_CHECK = 0x1000, - SPELL_GROUP_SPECIAL_FLAG_SKIP_STRONGER_SAME_SPELL = 0x2000, - SPELL_GROUP_SPECIAL_FLAG_MAX = 0x4000, - - SPELL_GROUP_SPECIAL_FLAG_FLASK = SPELL_GROUP_SPECIAL_FLAG_ELIXIR_BATTLE | SPELL_GROUP_SPECIAL_FLAG_ELIXIR_GUARDIAN + SPELL_GROUP_NONE = 0, + SPELL_GROUP_ELIXIR_BATTLE = 1, + SPELL_GROUP_ELIXIR_GUARDIAN = 2, + SPELL_GROUP_CORE_RANGE_MAX = 3 }; -enum SpellGroupStackFlags +namespace std { - SPELL_GROUP_STACK_FLAG_NONE = 0x00, - SPELL_GROUP_STACK_FLAG_EXCLUSIVE = 0x01, - SPELL_GROUP_STACK_FLAG_NOT_SAME_CASTER = 0x02, - SPELL_GROUP_STACK_FLAG_FLAGGED = 0x04, // xinef: just a marker - SPELL_GROUP_STACK_FLAG_NEVER_STACK = 0x08, - SPELL_GROUP_STACK_FLAG_EFFECT_EXCLUSIVE = 0x10, - SPELL_GROUP_STACK_FLAG_MAX = 0x20, + template<> + struct hash + { + size_t operator()(SpellGroup const& group) const + { + return hash()(uint32(group)); + } + }; +} - // Internal use - SPELL_GROUP_STACK_FLAG_FORCED_STRONGEST = 0x100, - SPELL_GROUP_STACK_FLAG_FORCED_WEAKEST = 0x200, +#define SPELL_GROUP_DB_RANGE_MIN 1000 + +// spell_id, group_id +typedef std::unordered_multimap SpellSpellGroupMap; +typedef std::pair SpellSpellGroupMapBounds; + +// group_id, spell_id +typedef std::unordered_multimap SpellGroupSpellMap; +typedef std::pair SpellGroupSpellMapBounds; + +enum SpellGroupStackRule +{ + SPELL_GROUP_STACK_RULE_DEFAULT, + SPELL_GROUP_STACK_RULE_EXCLUSIVE, + SPELL_GROUP_STACK_RULE_EXCLUSIVE_FROM_SAME_CASTER, + SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT, + SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST, + SPELL_GROUP_STACK_RULE_MAX }; -enum SpellGroupIDs -{ - SPELL_GROUP_GUARDIAN_AND_BATTLE_ELIXIRS = 1 -}; +typedef std::unordered_map SpellGroupStackMap; -struct SpellStackInfo -{ - uint32 groupId; - SpellGroupSpecialFlags specialFlags; -}; -// spell_id, group_id -typedef std::map SpellGroupMap; -typedef std::map SpellGroupStackMap; +typedef std::unordered_map> SameEffectStackMap; struct SpellThreatEntry { @@ -679,12 +671,18 @@ public: // Spell target coordinates [[nodiscard]] SpellTargetPosition const* GetSpellTargetPosition(uint32 spell_id, SpellEffIndex effIndex) const; - // Spell Groups - [[nodiscard]] uint32 GetSpellGroup(uint32 spellid) const; - [[nodiscard]] SpellGroupSpecialFlags GetSpellGroupSpecialFlags(uint32 spell_id) const; - [[nodiscard]] SpellGroupStackFlags GetGroupStackFlags(uint32 groupid) const; - SpellGroupStackFlags CheckSpellGroupStackRules(SpellInfo const* spellInfo1, SpellInfo const* spellInfo2, bool remove, bool areaAura) const; - void GetSetOfSpellsInSpellGroupWithFlag(uint32 group_id, SpellGroupSpecialFlags flag, std::set& availableElixirs) const; + // Spell Groups table + SpellSpellGroupMapBounds GetSpellSpellGroupMapBounds(uint32 spell_id) const; + bool IsSpellMemberOfSpellGroup(uint32 spell_id, SpellGroup group_id) const; + + SpellGroupSpellMapBounds GetSpellGroupSpellMapBounds(SpellGroup group_id) const; + void GetSetOfSpellsInSpellGroup(SpellGroup group_id, std::set& foundSpells) const; + void GetSetOfSpellsInSpellGroup(SpellGroup group_id, std::set& foundSpells, std::set& usedGroups) const; + + // Spell Group Stack Rules table + bool AddSameEffectStackRuleSpellGroups(SpellInfo const* spellInfo, uint32 auraType, int32 amount, std::map& groups) const; + SpellGroupStackRule CheckSpellGroupStackRules(SpellInfo const* spellInfo1, SpellInfo const* spellInfo2) const; + SpellGroupStackRule GetSpellGroupStackRule(SpellGroup group_id) const; // Spell proc event table [[nodiscard]] SpellProcEventEntry const* GetSpellProcEvent(uint32 spellId) const; @@ -798,8 +796,10 @@ private: SpellRequiredMap mSpellReq; SpellLearnSkillMap mSpellLearnSkills; SpellTargetPositionMap mSpellTargetPositions; - SpellGroupMap mSpellGroupMap; - SpellGroupStackMap mSpellGroupStackMap; + SpellSpellGroupMap mSpellSpellGroup; + SpellGroupSpellMap mSpellGroupSpell; + SpellGroupStackMap mSpellGroupStack; + SameEffectStackMap mSpellSameEffectStack; SpellProcEventMap mSpellProcEventMap; SpellProcMap mSpellProcMap; SpellBonusMap mSpellBonusMap; diff --git a/src/server/game/World/WorldConfig.cpp b/src/server/game/World/WorldConfig.cpp index 761b8dd7b..6ae1b16ce 100644 --- a/src/server/game/World/WorldConfig.cpp +++ b/src/server/game/World/WorldConfig.cpp @@ -555,8 +555,8 @@ void WorldConfig::BuildConfigCache() // Dungeon finder SetConfigValue(CONFIG_LFG_OPTIONSMASK, "DungeonFinder.OptionsMask", 5); - SetConfigValue(CONFIG_LFG_CAST_DESERTER, "DungeonFinder.CastDeserter", true); + SetConfigValue(CONFIG_LFG_ALLOW_COMPLETED, "DungeonFinder.AllowCompleted", true); // DBC_ItemAttributes SetConfigValue(CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES, "DBC.EnforceItemAttributes", true); diff --git a/src/server/game/World/WorldConfig.h b/src/server/game/World/WorldConfig.h index 540fd8324..7a34aad36 100644 --- a/src/server/game/World/WorldConfig.h +++ b/src/server/game/World/WorldConfig.h @@ -94,6 +94,7 @@ enum ServerConfigs CONFIG_ALLOW_TICKETS, CONFIG_DELETE_CHARACTER_TICKET_TRACE, CONFIG_LFG_CAST_DESERTER, + CONFIG_LFG_ALLOW_COMPLETED, CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES, CONFIG_PRESERVE_CUSTOM_CHANNELS, CONFIG_PDUMP_NO_PATHS, diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp index 584e05f6f..83275a179 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp @@ -78,6 +78,10 @@ Position const PosMoveOnSpawn[1] = { -11561.9f, -1627.868f, 41.29941f, 0.0f } }; +// hack +float const DamageIncrease = 35.0f; +float const DamageDecrease = 100.f / (1.f + DamageIncrease / 100.f) - 100.f; + class boss_arlokk : public CreatureScript { public: @@ -90,7 +94,7 @@ public: void Reset() override { if (events.IsInPhase(PHASE_TWO)) - me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack + me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageDecrease); // hack _Reset(); _summonCountA = 0; _summonCountB = 0; @@ -253,7 +257,7 @@ public: events.ScheduleEvent(EVENT_RAVAGE, 10s, 14s, 0, PHASE_TWO); events.ScheduleEvent(EVENT_TRANSFORM_BACK, 30s, 40s, 0, PHASE_TWO); events.SetPhase(PHASE_TWO); - me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, true); // hack + me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageIncrease); // hack break; case EVENT_RAVAGE: DoCastVictim(SPELL_RAVAGE, true); @@ -265,7 +269,7 @@ public: DoCast(me, SPELL_VANISH_VISUAL); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_DAGGER)); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(WEAPON_DAGGER)); - me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack + me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageDecrease); // hack events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 4s, 7s, 0, PHASE_ONE); events.ScheduleEvent(EVENT_GOUGE, 12s, 15s, 0, PHASE_ONE); events.ScheduleEvent(EVENT_TRANSFORM, 30s, 0, PHASE_ONE); diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp index d453d5e2f..b350b680e 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp @@ -73,6 +73,10 @@ enum Misc GO_SPIDER_EGGS = 179985, }; +// hack +float const DamageIncrease = 35.0f; +float const DamageDecrease = 100.f / (1.f + DamageIncrease / 100.f) - 100.f; + // High Priestess Mar'li (14510) struct boss_marli : public BossAI { @@ -84,7 +88,7 @@ public: if (_phase == PHASE_SPIDER) { me->RemoveAura(SPELL_SPIDER_FORM); - me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); + me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageDecrease); _phase = PHASE_TROLL; } @@ -143,7 +147,7 @@ private: me->RemoveAura(SPELL_SPIDER_FORM); DoCastSelf(SPELL_TRANSFORM_BACK, true); Talk(SAY_TRANSFORM_BACK); - me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); + me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageDecrease); scheduler.CancelGroup(PHASE_SPIDER); } @@ -186,7 +190,7 @@ private: Talk(SAY_TRANSFORM); DoCastSelf(SPELL_SPIDER_FORM, true); - me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, true); + me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageIncrease); scheduler.Schedule(5s, PHASE_SPIDER, [this](TaskContext context) { diff --git a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_jedoga_shadowseeker.cpp b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_jedoga_shadowseeker.cpp index 6392a738e..d78077606 100644 --- a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_jedoga_shadowseeker.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_jedoga_shadowseeker.cpp @@ -16,7 +16,6 @@ */ #include "AchievementCriteriaScript.h" -#include "Containers.h" #include "CreatureScript.h" #include "ObjectAccessor.h" #include "ScriptedCreature.h" @@ -209,7 +208,7 @@ struct boss_jedoga_shadowseeker : public BossAI } } - sacraficeTarget_GUID.Clear(); + sacrificeTargetGUID.Clear(); sayPreachTimer = 120000; ritualTriggered = false; volunteerWork = true; @@ -268,12 +267,12 @@ struct boss_jedoga_shadowseeker : public BossAI } case NPC_TWILIGHT_VOLUNTEER: { - if (sacraficeTarget_GUID && summon->GetGUID() != sacraficeTarget_GUID) + if (sacrificeTargetGUID && summon->GetGUID() != sacrificeTargetGUID) { break; } - if (killer != me && killer->GetGUID() != sacraficeTarget_GUID) + if (killer != me && killer->GetGUID() != sacrificeTargetGUID) { volunteerWork = false; } @@ -315,7 +314,7 @@ struct boss_jedoga_shadowseeker : public BossAI { if (action == ACTION_SACRAFICE) { - if (Creature* target = ObjectAccessor::GetCreature(*me, sacraficeTarget_GUID)) + if (Creature* target = ObjectAccessor::GetCreature(*me, sacrificeTargetGUID)) { Unit::Kill(me, target); } @@ -395,9 +394,9 @@ struct boss_jedoga_shadowseeker : public BossAI me->SetFacingTo(5.66f); if (!summons.empty()) { - sacraficeTarget_GUID = Acore::Containers::SelectRandomContainerElement(summons); - if (ObjectAccessor::GetCreature(*me, sacraficeTarget_GUID)) + if (Creature* creature = summons.GetRandomCreatureWithEntry(NPC_TWILIGHT_VOLUNTEER)) { + sacrificeTargetGUID = creature->GetGUID(); events.ScheduleEvent(EVENT_JEDGA_START_RITUAL, 3s, 0, PHASE_RITUAL); } // Something failed, let players continue but do not grant achievement @@ -518,15 +517,16 @@ struct boss_jedoga_shadowseeker : public BossAI } case EVENT_JEDGA_START_RITUAL: { - sacraficeTarget_GUID = Acore::Containers::SelectRandomContainerElement(summons); - if (Creature* volunteer = ObjectAccessor::GetCreature(*me, sacraficeTarget_GUID)) + if (Creature* creature = summons.GetRandomCreatureWithEntry(NPC_TWILIGHT_VOLUNTEER)) { + sacrificeTargetGUID = creature->GetGUID(); Talk(SAY_SACRIFICE_1); - sacraficeTarget_GUID = volunteer->GetGUID(); - volunteer->AI()->DoAction(ACTION_RITUAL_BEGIN); + creature->AI()->DoAction(ACTION_RITUAL_BEGIN); } break; } + default: + break; } } @@ -546,7 +546,7 @@ struct boss_jedoga_shadowseeker : public BossAI private: GuidList oocSummons; GuidList oocTriggers; - ObjectGuid sacraficeTarget_GUID; + ObjectGuid sacrificeTargetGUID; uint32 sayPreachTimer; bool combatSummonsSummoned; bool ritualTriggered; diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp index 319fc1f83..d27d43b38 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp @@ -2037,7 +2037,7 @@ public: npc_toc_enh_shamanAI(Creature* pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) { SetEquipmentSlots(false, 51803, 48013, EQUIP_NO_CHANGE); - me->SetModifierValue(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, 1.0f); + me->SetStatPctModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, 1.0f); me->UpdateDamagePhysical(OFF_ATTACK); events.Reset(); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp index eb26cad02..2ffe2f7dd 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp @@ -109,7 +109,7 @@ struct boss_twin_valkyrAI : public ScriptedAI { pInstance = pCreature->GetInstanceScript(); me->SetReactState(REACT_PASSIVE); - me->SetModifierValue(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, 1.0f); + me->SetStatPctModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, 1.0f); me->UpdateDamagePhysical(OFF_ATTACK); LastSynchroHP = (int32)me->GetMaxHealth(); SpecialMask = 0; diff --git a/src/server/scripts/Northrend/Gundrak/boss_eck.cpp b/src/server/scripts/Northrend/Gundrak/boss_eck.cpp index 9e7a6bbc9..12f84b71f 100644 --- a/src/server/scripts/Northrend/Gundrak/boss_eck.cpp +++ b/src/server/scripts/Northrend/Gundrak/boss_eck.cpp @@ -36,7 +36,8 @@ enum Misc EVENT_ECK_BITE = 2, EVENT_ECK_SPIT = 3, EVENT_ECK_SPRING = 4, - EVENT_ECK_HEALTH = 5 + EVENT_ECK_CRAZED_EMOTE = 5, + EMOTE_CRAZED = 1 }; class boss_eck : public CreatureScript @@ -89,7 +90,8 @@ public: void JustEngagedWith(Unit* who) override { BossAI::JustEngagedWith(who); - events.ScheduleEvent(EVENT_ECK_BERSERK, 60s, 90s); + events.ScheduleEvent(EVENT_ECK_CRAZED_EMOTE, 76s, 78s); + events.ScheduleEvent(EVENT_ECK_BERSERK, 90s); events.ScheduleEvent(EVENT_ECK_BITE, 5s); events.ScheduleEvent(EVENT_ECK_SPIT, 10s, 37s); events.ScheduleEvent(EVENT_ECK_SPRING, 10s, 24s); @@ -111,18 +113,11 @@ public: switch (events.ExecuteEvent()) { - case EVENT_ECK_HEALTH: - if (me->HealthBelowPct(21)) - { - events.CancelEvent(EVENT_ECK_BERSERK); - me->CastSpell(me, SPELL_ECK_BERSERK, false); - break; - } - events.ScheduleEvent(EVENT_ECK_HEALTH, 1s); + case EVENT_ECK_CRAZED_EMOTE: + Talk(EMOTE_CRAZED); break; case EVENT_ECK_BERSERK: me->CastSpell(me, SPELL_ECK_BERSERK, false); - events.CancelEvent(EVENT_ECK_HEALTH); break; case EVENT_ECK_BITE: me->CastSpell(me->GetVictim(), SPELL_ECK_BITE, false); diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp index 77af6636b..1530cab2e 100644 --- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp +++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp @@ -547,12 +547,17 @@ public: } case DONE: { + if (!horsemanKilled) // if no horsemen are found, assume wing is cleared + { + ActivateWingPortal(DATA_HORSEMAN_PORTAL); + break; + } + _events.RescheduleEvent(EVENT_AND_THEY_WOULD_ALL_GO_DOWN_TOGETHER, 15s); if (horsemanKilled != HorsemanCount) return false; - // all horsemans are killed if (Creature* cr = GetCreature(DATA_BARON_RIVENDARE_BOSS)) cr->CastSpell(cr, SPELL_THE_FOUR_HORSEMAN_CREDIT, true); diff --git a/src/server/scripts/Northrend/Naxxramas/naxxramas.h b/src/server/scripts/Northrend/Naxxramas/naxxramas.h index 6f47c4fa1..4b790f1cc 100644 --- a/src/server/scripts/Northrend/Naxxramas/naxxramas.h +++ b/src/server/scripts/Northrend/Naxxramas/naxxramas.h @@ -75,17 +75,15 @@ enum NaxxramasData DATA_DANCE_FAIL = 301, DATA_SPORE_KILLED = 302, DATA_FRENZY_REMOVED = 303, - DATA_THADDIUS_INTRO = 304, - DATA_CHARGES_CROSSED = 305, - DATA_HUNDRED_CLUB = 306, - DATA_ABOMINATION_KILLED = 307, + DATA_CHARGES_CROSSED = 304, + DATA_HUNDRED_CLUB = 305, + DATA_ABOMINATION_KILLED = 306, }; enum NaxxramasPersistentData { - PERSISTENT_DATA_THADDIUS_INTRO = 0, - PERSISTENT_DATA_KELTHUZAD_DIALOG = 1, - PERSISTENT_DATA_IMMORTAL_FAIL = 2, + PERSISTENT_DATA_KELTHUZAD_DIALOG = 0, + PERSISTENT_DATA_IMMORTAL_FAIL = 1, PERSISTENT_DATA_COUNT }; diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/brann_bronzebeard.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/brann_bronzebeard.cpp index be6ab6c9e..ac60a5736 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/brann_bronzebeard.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/brann_bronzebeard.cpp @@ -676,7 +676,6 @@ public: me->CastSpell(me, 59046, true); // credit } - me->ReplaceAllNpcFlags(UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER); me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STAND); me->SendMovementFlagUpdate(); @@ -883,6 +882,7 @@ void brann_bronzebeard::brann_bronzebeardAI::WaypointReached(uint32 id) //Tribunal end, stand in the middle of the sky room case 17: SetEscortPaused(true); + me->ReplaceAllNpcFlags(UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER); me->SetOrientation(3.91672f); me->SendMovementFlagUpdate(); break; diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp index 09ee36991..1a7cb3030 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp @@ -82,30 +82,33 @@ struct npc_dragonflayer_forge_master : public ScriptedAI enum EnslavedProtoDrake { - TYPE_PROTODRAKE_AT = 28, - DATA_PROTODRAKE_MOVE = 6, - - PATH_PROTODRAKE = 125946, - - EVENT_REND = 1, - EVENT_FLAME_BREATH = 2, - EVENT_KNOCKAWAY = 3, - SPELL_REND = 43931, SPELL_FLAME_BREATH = 50653, SPELL_KNOCK_AWAY = 49722, - POINT_LAST = 6, + EVENT_REND = 1, + EVENT_FLAME_BREATH = 2, + EVENT_KNOCKAWAY = 3, + // Special + EVENT_PRE_LAND = 4, + EVENT_LAND = 5, + + // Special + TYPE_PROTODRAKE_AT = 28, + DATA_PROTODRAKE_MOVE = 6, + POINT_TAKE_OFF = 1, + POINT_PRE_LAND = 2, + POINT_LAND = 3, }; -const Position protodrakeCheckPos = {206.24f, -190.28f, 200.11f, 0.f}; +const Position protodrakeCheckPos{206.24f, -190.28f, 200.11f, 0.f}; +const Position protodrakeTakeOffPos{209.1206f, -187.86578f, 215.00346f}; +const Position protodrakePreLandPos{230.80234f, -164.99632f, 196.74878f}; +const Position protodrakeLandPos{241.2079f, -163.06265f, 193.47125f}; struct npc_enslaved_proto_drake : public ScriptedAI { - npc_enslaved_proto_drake(Creature* creature) : ScriptedAI(creature) - { - _setData = false; - } + explicit npc_enslaved_proto_drake(Creature* creature) : ScriptedAI(creature) { } void Reset() override { @@ -113,22 +116,35 @@ struct npc_enslaved_proto_drake : public ScriptedAI _events.ScheduleEvent(EVENT_REND, 2s, 3s); _events.ScheduleEvent(EVENT_FLAME_BREATH, 5500ms, 7s); _events.ScheduleEvent(EVENT_KNOCKAWAY, 3500ms, 6s); + scheduler.CancelAll(); } void MovementInform(uint32 type, uint32 id) override { - if (type == WAYPOINT_MOTION_TYPE && id == POINT_LAST) + if (type == EFFECT_MOTION_TYPE && id == POINT_TAKE_OFF) { + ScheduleUniqueTimedEvent(500ms, [&] + { + me->GetMotionMaster()->MovePoint(POINT_PRE_LAND, protodrakePreLandPos); + }, EVENT_PRE_LAND); + } + + if (type == POINT_MOTION_TYPE && id == POINT_PRE_LAND) + { + ScheduleUniqueTimedEvent(0s, [&] + { + me->GetMotionMaster()->MovePoint(POINT_LAND, protodrakeLandPos); + }, EVENT_LAND); + } + + if (type == POINT_MOTION_TYPE && id == POINT_LAND) + { + me->SetFacingTo(0.25f); me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0.25f); if (Vehicle* v = me->GetVehicleKit()) if (Unit* p = v->GetPassenger(0)) if (Creature* rider = p->ToCreature()) rider->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0.25f); - - me->SetCanFly(false); - me->SetDisableGravity(false); - me->SetFacingTo(0.25f); - me->SetImmuneToAll(false); } } @@ -137,14 +153,14 @@ struct npc_enslaved_proto_drake : public ScriptedAI if (type == TYPE_PROTODRAKE_AT && data == DATA_PROTODRAKE_MOVE && !_setData && me->IsAlive() && me->GetDistance(protodrakeCheckPos) < 10.0f) { _setData = true; - me->SetCanFly(true); - me->SetDisableGravity(true); - me->GetMotionMaster()->MoveWaypoint(PATH_PROTODRAKE, false); + me->GetMotionMaster()->MoveTakeoff(POINT_TAKE_OFF, protodrakeTakeOffPos, 8.0f); } } void UpdateAI(uint32 diff) override { + scheduler.Update(diff); + if (!UpdateVictim()) return; @@ -178,7 +194,7 @@ struct npc_enslaved_proto_drake : public ScriptedAI } private: - bool _setData; + bool _setData{false}; EventMap _events; }; diff --git a/src/server/scripts/Northrend/zone_crystalsong_forest.cpp b/src/server/scripts/Northrend/zone_crystalsong_forest.cpp index bdf394cad..645d3c022 100644 --- a/src/server/scripts/Northrend/zone_crystalsong_forest.cpp +++ b/src/server/scripts/Northrend/zone_crystalsong_forest.cpp @@ -15,52 +15,100 @@ * with this program. If not, see . */ +#include "CombatAI.h" #include "CreatureScript.h" -#include "PassiveAI.h" #include "Player.h" #include "ScriptedCreature.h" -#include "SmartScriptMgr.h" +#include "SpellAuras.h" +#include "SpellScript.h" #include "Transport.h" #include "Vehicle.h" enum ePreparationsForWar { - NPC_HAMMERHEAD = 30585, - NPC_CLOUDBUSTER = 30470, - TRANSPORT_ORGRIMS_HAMMER = 192241, - TRANSPORT_THE_SKYBREAKER = 192242 + NPC_CLOUDBUSTER = 30470, + NPC_HAMMERHEAD = 30585, + TRANSPORT_ORGRIMS_HAMMER = 192241, + TRANSPORT_THE_SKYBREAKER = 192242, + SEAT_PLAYER = 0, + SPELL_FLIGHT = 48602, + SPELL_TO_ICECROWN_PLAYER_AURA_DISMOUNT_A = 56904, + SPELL_TO_ICECROWN_PLAYER_AURA_DISMOUNT_H = 57419, + SPELL_TO_ICECROWN_AIRSHIP_PLAYER_AURA_TELEPORT_TO_DALARAN = 57460, + SPELL_TO_ICECROWN_AIRSHIP_FROST_WYRM_WAITING_TO_SUMMON_AURA = 57498, + POINT_END = 16, + SPELL_TO_ICECROWN_AIRSHIP_AURA_DISMOUNT_RESPONSE = 56921, // unhandled - vehicle casts 50630 on self + SPELL_EJECT_ALL_PASSENGERS = 50630, + SPELL_TO_ICECROWN_AIRSHIP_TELEPORT_TO_AIRSHIP_A_FORCE_PLAYER_TO_CAST = 57554, + SPELL_TO_ICECROWN_AIRSHIP_TELEPORT_TO_AIRSHIP_H_FORCE_PLAYER_TO_CAST = 57556, + SPELL_TO_ICECROWN_AIRSHIP_TELEPORT_TO_AIRSHIP_A = 56917, + SPELL_TO_ICECROWN_AIRSHIP_TELEPORT_TO_AIRSHIP_H = 57417, }; -struct npc_preparations_for_war_vehicle : public NullCreatureAI +struct npc_preparations_for_war_vehicle : public VehicleAI { - npc_preparations_for_war_vehicle(Creature* creature) : NullCreatureAI(creature) { } - - uint8 pointId; - uint32 searchForShipTimer; - uint32 transportEntry; - - void InitializeAI() override + explicit npc_preparations_for_war_vehicle(Creature* creature) : VehicleAI(creature), searchForShipTimer(0), transportEntry(me->GetEntry() == NPC_CLOUDBUSTER ? TRANSPORT_THE_SKYBREAKER : TRANSPORT_ORGRIMS_HAMMER) { - me->GetMotionMaster()->MovePath(me->GetEntry(), FORCED_MOVEMENT_NONE, PathSource::SMART_WAYPOINT_MGR); - - NullCreatureAI::InitializeAI(); - pointId = 0; - searchForShipTimer = 0; - transportEntry = (me->GetEntry() == NPC_HAMMERHEAD ? TRANSPORT_ORGRIMS_HAMMER : TRANSPORT_THE_SKYBREAKER); + if (transportEntry == TRANSPORT_THE_SKYBREAKER) + { + // 30476 - [DND] Icecrown Flight To Airship Bunny (A) + passenger_x = 31.41805; + passenger_y = 0.126893; + passenger_z = 41.69821; + } + else // TRANSPORT_ORGRIMS_HAMMER + { + // 30588 - [DND] Icecrown Flight To Airship Bunny (H) + passenger_x = -18.10283; + passenger_y = -0.042108; + passenger_z = 45.31725; + } } - void MovementInform(uint32 type, uint32 /*id*/) override + void PassengerBoarded(Unit* who, int8 /*seatId*/, bool apply) override { - if (type == ESCORT_MOTION_TYPE) - if (++pointId == 17) // path size - searchForShipTimer = 3000; + if (apply) + { + DoCastSelf(SPELL_TO_ICECROWN_AIRSHIP_PLAYER_AURA_TELEPORT_TO_DALARAN, true); + DoCastSelf(SPELL_FLIGHT, true); + DoCastSelf(me->GetEntry() == NPC_CLOUDBUSTER ? SPELL_TO_ICECROWN_PLAYER_AURA_DISMOUNT_A : SPELL_TO_ICECROWN_PLAYER_AURA_DISMOUNT_H , true); + DoCastSelf(SPELL_TO_ICECROWN_AIRSHIP_FROST_WYRM_WAITING_TO_SUMMON_AURA, true); + me->GetMotionMaster()->MovePath(me->GetEntry(), FORCED_MOVEMENT_NONE, PathSource::SMART_WAYPOINT_MGR); + } + else + who->RemoveAurasDueToSpell(VEHICLE_SPELL_PARACHUTE); // maybe vehicle / seat flag should be responsible for parachute gain? + } + + void MovementInform(uint32 type, uint32 id) override + { + if (type == ESCORT_MOTION_TYPE && id == POINT_END) + searchForShipTimer = 3000; + } + + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override + { + switch (spell->Id) + { + case SPELL_TO_ICECROWN_AIRSHIP_AURA_DISMOUNT_RESPONSE: + break; + case SPELL_TO_ICECROWN_AIRSHIP_TELEPORT_TO_AIRSHIP_A_FORCE_PLAYER_TO_CAST: + case SPELL_TO_ICECROWN_AIRSHIP_TELEPORT_TO_AIRSHIP_H_FORCE_PLAYER_TO_CAST: + { + uint32 teleportSpell = (spell->Id == SPELL_TO_ICECROWN_AIRSHIP_TELEPORT_TO_AIRSHIP_A_FORCE_PLAYER_TO_CAST) + ? SPELL_TO_ICECROWN_AIRSHIP_TELEPORT_TO_AIRSHIP_A + : SPELL_TO_ICECROWN_AIRSHIP_TELEPORT_TO_AIRSHIP_H; + DoCastSelf(teleportSpell, true); // hack: cast on self to avoid visual glitch on player when ejecting and teleporting on transport + DoCastSelf(SPELL_EJECT_ALL_PASSENGERS, true); + me->DespawnOrUnsummon(0s); + break; + } + default: + break; + } } void UpdateAI(uint32 diff) override { - // horde 7.55f, -0.09, 34.44, 3.13, +20 - // ally 45.18f, 0.03, 40.09, 3.14 +5 - if (searchForShipTimer) { searchForShipTimer += diff; @@ -68,37 +116,14 @@ struct npc_preparations_for_war_vehicle : public NullCreatureAI { searchForShipTimer = 1; TransportsContainer const& transports = me->GetMap()->GetAllTransports(); - for (TransportsContainer::const_iterator itr = transports.begin(); itr != transports.end(); ++itr) + for (auto const transport : transports) { - if ((*itr)->GetEntry() == transportEntry) + if (transport->GetEntry() == transportEntry) { - float x, y, z; - if (transportEntry == TRANSPORT_ORGRIMS_HAMMER) - { - x = 7.55f; - y = -0.09f; - z = 54.44f; - } - else - { - x = 45.18f; - y = 0.03f; - z = 45.09f; - } + float x = passenger_x, y = passenger_y, z = passenger_z; + transport->CalculatePassengerPosition(x, y, z); - (*itr)->CalculatePassengerPosition(x, y, z); - - if (me->GetDistance2d(x, y) < 10.0f) - { - me->DespawnOrUnsummon(1s); - if (Vehicle* vehicle = me->GetVehicleKit()) - if (Unit* passenger = vehicle->GetPassenger(0)) - { - passenger->NearTeleportTo(x, y, z - (transportEntry == TRANSPORT_ORGRIMS_HAMMER ? 19.0f : 4.0f), M_PI); - passenger->RemoveAurasDueToSpell(VEHICLE_SPELL_PARACHUTE); // maybe vehicle / seat flag should be responsible for parachute gain? - } - } - else + if (me->GetDistance2d(x, y) > 20.0f) // dismount trigger (56905, 57420) range is 30 me->GetMotionMaster()->MovePoint(0, x, y, z, FORCED_MOVEMENT_NONE, 0.f, 0.f, false, false); break; } @@ -106,6 +131,10 @@ struct npc_preparations_for_war_vehicle : public NullCreatureAI } } } +private: + float passenger_x, passenger_y, passenger_z; + uint32 searchForShipTimer; + uint32 transportEntry; }; /******************************************************* diff --git a/src/server/scripts/Northrend/zone_dalaran.cpp b/src/server/scripts/Northrend/zone_dalaran.cpp index ca887acbe..7c5b9fba4 100644 --- a/src/server/scripts/Northrend/zone_dalaran.cpp +++ b/src/server/scripts/Northrend/zone_dalaran.cpp @@ -428,7 +428,7 @@ public: struct npc_mageguard_dalaranAI : public ScriptedAI { - npc_mageguard_dalaranAI(Creature* creature) : ScriptedAI(creature) + explicit npc_mageguard_dalaranAI(Creature* creature) : ScriptedAI(creature) { creature->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); creature->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_NORMAL, true); @@ -449,6 +449,9 @@ public: if (!me->IsWithinDist(who, 5.0f, false)) return; + if (who->IsCreature() && who->GetCreatureType() == CREATURE_TYPE_NON_COMBAT_PET) + return; + Player* player = who->GetCharmerOrOwnerPlayerOrPlayerItself(); if (!player || player->IsGameMaster() || player->IsBeingTeleported() || (player->GetPositionZ() > 670 && player->GetVehicle()) || @@ -484,7 +487,6 @@ public: break; } me->SetOrientation(me->GetHomePosition().GetOrientation()); - return; } void UpdateAI(uint32 /*diff*/) override {} diff --git a/src/server/scripts/Northrend/zone_howling_fjord.cpp b/src/server/scripts/Northrend/zone_howling_fjord.cpp index fc28598ec..928a0a71e 100644 --- a/src/server/scripts/Northrend/zone_howling_fjord.cpp +++ b/src/server/scripts/Northrend/zone_howling_fjord.cpp @@ -66,109 +66,6 @@ public: } }; -// The cleansing -enum TurmoilTexts -{ - SAY_TURMOIL_0 = 0, - SAY_TURMOIL_1 = 1, - SAY_TURMOIL_HALF_HP = 2, - SAY_TURMOIL_DEATH = 3, -}; - -class npc_your_inner_turmoil : public CreatureScript -{ -public: - npc_your_inner_turmoil() : CreatureScript("npc_your_inner_turmoil") { } - - struct npc_your_inner_turmoilAI : public ScriptedAI - { - npc_your_inner_turmoilAI(Creature* creature) : ScriptedAI(creature) {} - - uint32 timer; - short phase; - bool health50; - - void Reset() override - { - timer = 0; - phase = 0; - health50 = false; - } - - void UpdateAI(uint32 diff) override - { - if (timer >= 6000 && phase < 2) - { - phase++; - setphase(phase); - timer = 0; - } - - timer += diff; - - DoMeleeAttackIfReady(); - } - - void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override - { - if (HealthBelowPct(50) && !health50) - { - if (TempSummon const* tempSummon = me->ToTempSummon()) - { - if (WorldObject* summoner = tempSummon->GetSummonerUnit()) - { - Talk(SAY_TURMOIL_HALF_HP, summoner); - } - } - - health50 = true; - } - } - - void JustDied(Unit* /*killer*/) override - { - if (TempSummon const* tempSummon = me->ToTempSummon()) - { - if (WorldObject* summoner = tempSummon->GetSummonerUnit()) - { - Talk(SAY_TURMOIL_DEATH, summoner); - } - } - } - - void setphase(short newPhase) - { - Unit* summoner = me->ToTempSummon() ? me->ToTempSummon()->GetSummonerUnit() : nullptr; - if (!summoner || !summoner->IsPlayer()) - return; - - switch (newPhase) - { - case 1: - Talk(SAY_TURMOIL_0, summoner->ToPlayer()); - return; - case 2: - { - Talk(SAY_TURMOIL_1, summoner->ToPlayer()); - me->SetLevel(summoner->GetLevel()); - me->SetFaction(FACTION_MONSTER); - if (me->GetExactDist(summoner) < 50.0f) - { - me->UpdatePosition(summoner->GetPositionX(), summoner->GetPositionY(), summoner->GetPositionZ(), 0.0f, true); - summoner->CastSpell(me, 50218, true); // clone caster - AttackStart(summoner); - } - } - } - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_your_inner_turmoilAI(creature); - } -}; - /*###### ## npc_apothecary_hanes ######*/ @@ -457,13 +354,145 @@ class spell_hawk_hunting : public SpellScript } }; +/*###### +## Quest 11317, 11322: The Cleansing +######*/ + +enum TheCleansing +{ + SPELL_CLEANSING_SOUL = 43351, + SPELL_SUMMON_INNER_TURMOIL = 50167, + SPELL_RECENT_MEDITATION = 61720, + SPELL_MIRROR_IMAGE_AURA = 50218, + + QUEST_THE_CLEANSING_H = 11317, + QUEST_THE_CLEANSING_A = 11322 +}; + +// 43365 - The Cleansing: Shrine Cast +class spell_the_cleansing_shrine_cast : public SpellScript +{ + PrepareSpellScript(spell_the_cleansing_shrine_cast); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_RECENT_MEDITATION, SPELL_CLEANSING_SOUL }) && + sObjectMgr->GetQuestTemplate(QUEST_THE_CLEANSING_H) && + sObjectMgr->GetQuestTemplate(QUEST_THE_CLEANSING_A); + } + + SpellCastResult CheckCast() + { + // Error is correct for quest check but may be not correct for aura and this may be a wrong place to send error + if (Player* target = GetExplTargetUnit()->ToPlayer()) + { + if (target->HasAura(SPELL_RECENT_MEDITATION) || (!(target->GetQuestStatus(QUEST_THE_CLEANSING_H) == QUEST_STATUS_INCOMPLETE || + target->GetQuestStatus(QUEST_THE_CLEANSING_A) == QUEST_STATUS_INCOMPLETE))) + { + Spell::SendCastResult(target, GetSpellInfo(), 0, SPELL_FAILED_FIZZLE); + return SPELL_FAILED_FIZZLE; + } + } + return SPELL_CAST_OK; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_CLEANSING_SOUL, true); + } + + void Register() override + { + OnCheckCast += SpellCheckCastFn(spell_the_cleansing_shrine_cast::CheckCast); + OnEffectHitTarget += SpellEffectFn(spell_the_cleansing_shrine_cast::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + +// 43351 - Cleansing Soul +class spell_the_cleansing_cleansing_soul : public AuraScript +{ + PrepareAuraScript(spell_the_cleansing_cleansing_soul); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_SUMMON_INNER_TURMOIL, SPELL_RECENT_MEDITATION }); + } + + void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->SetStandState(UNIT_STAND_STATE_SIT); + } + + void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); + target->SetStandState(UNIT_STAND_STATE_STAND); + target->CastSpell(target, SPELL_SUMMON_INNER_TURMOIL, true); + target->CastSpell(target, SPELL_RECENT_MEDITATION, true); + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_the_cleansing_cleansing_soul::AfterApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_the_cleansing_cleansing_soul::AfterRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } +}; + +// 50217 - The Cleansing: Script Effect Player Cast Mirror Image +class spell_the_cleansing_mirror_image_script_effect : public SpellScript +{ + PrepareSpellScript(spell_the_cleansing_mirror_image_script_effect); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_MIRROR_IMAGE_AURA }); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_MIRROR_IMAGE_AURA, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_the_cleansing_mirror_image_script_effect::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + +// 50238 - The Cleansing: Your Inner Turmoil's On Death Cast on Master +class spell_the_cleansing_on_death_cast_on_master : public SpellScript +{ + PrepareSpellScript(spell_the_cleansing_on_death_cast_on_master); + + bool Validate(SpellInfo const* spellInfo) override + { + return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()) }); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* caster = GetCaster()) + if (TempSummon* casterSummon = caster->ToTempSummon()) + if (Unit* summoner = casterSummon->GetSummonerUnit()) + summoner->CastSpell(summoner, GetSpellInfo()->Effects[EFFECT_0].CalcValue(), true); + } + + void Register() override + { + OnEffectHit += SpellEffectFn(spell_the_cleansing_on_death_cast_on_master::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + void AddSC_howling_fjord() { new npc_attracted_reef_bull(); - new npc_your_inner_turmoil(); new npc_apothecary_hanes(); new npc_plaguehound_tracker(); new npc_razael_and_lyana(); RegisterCreatureAI(npc_rodin_lightning_enabler); RegisterSpellScript(spell_hawk_hunting); + RegisterSpellScript(spell_the_cleansing_shrine_cast); + RegisterSpellScript(spell_the_cleansing_cleansing_soul); + RegisterSpellScript(spell_the_cleansing_mirror_image_script_effect); + RegisterSpellScript(spell_the_cleansing_on_death_cast_on_master); } diff --git a/src/server/scripts/Northrend/zone_storm_peaks.cpp b/src/server/scripts/Northrend/zone_storm_peaks.cpp index ede34025a..e97505ffb 100644 --- a/src/server/scripts/Northrend/zone_storm_peaks.cpp +++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp @@ -918,72 +918,40 @@ public: } }; -class npc_hyldsmeet_protodrake : public CreatureScript +enum HyldsmeetProtoDrake { - enum NPCs + NPC_HYLDSMEET_DRAKERIDER = 29694 +}; + +struct npc_hyldsmeet_protodrake : public CreatureAI +{ + explicit npc_hyldsmeet_protodrake(Creature* creature) : CreatureAI(creature), _accessoryRespawnTimer(0) { } + + void PassengerBoarded(Unit* who, int8 /*seat*/, bool apply) override { - NPC_HYLDSMEET_DRAKERIDER = 29694 - }; + if (apply) + return; -public: - npc_hyldsmeet_protodrake() : CreatureScript("npc_hyldsmeet_protodrake") { } - - class npc_hyldsmeet_protodrakeAI : public CreatureAI - { - public: - npc_hyldsmeet_protodrakeAI(Creature* creature) : CreatureAI(creature), _accessoryRespawnTimer(0), _vehicleKit(creature->GetVehicleKit()) { } - - void PassengerBoarded(Unit* who, int8 /*seat*/, bool apply) override - { - if (apply) - { - class DelayedTransportPositionOffsets : public BasicEvent - { - public: - DelayedTransportPositionOffsets(Unit* owner) : _owner(owner) { } - - bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override - { - _owner->m_movementInfo.transport.pos.Relocate(-3.5f, 0.f, -0.2f, 0.f); - return true; - } - - private: - Unit* _owner; - }; - - if (who->IsPlayer()) - who->m_Events.AddEventAtOffset(new DelayedTransportPositionOffsets(who), 500ms); - - return; - } - - if (who->GetEntry() == NPC_HYLDSMEET_DRAKERIDER) - _accessoryRespawnTimer = 5 * MINUTE * IN_MILLISECONDS; - } - - void UpdateAI(uint32 diff) override - { - //! We need to manually reinstall accessories because the vehicle itself is friendly to players, - //! so EnterEvadeMode is never triggered. The accessory on the other hand is hostile and killable. - if (_accessoryRespawnTimer && _accessoryRespawnTimer <= diff && _vehicleKit) - { - _vehicleKit->InstallAllAccessories(true); - _accessoryRespawnTimer = 0; - } - else - _accessoryRespawnTimer -= diff; - } - - private: - uint32 _accessoryRespawnTimer; - Vehicle* _vehicleKit; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_hyldsmeet_protodrakeAI(creature); + if (who->GetEntry() == NPC_HYLDSMEET_DRAKERIDER) + _accessoryRespawnTimer = 5 * MINUTE * IN_MILLISECONDS; } + + void UpdateAI(uint32 diff) override + { + //! We need to manually reinstall accessories because the vehicle itself is friendly to players, + //! so EnterEvadeMode is never triggered. The accessory on the other hand is hostile and killable. + Vehicle* vehicleKit = me->GetVehicleKit(); + if (_accessoryRespawnTimer && _accessoryRespawnTimer <= diff && vehicleKit) + { + vehicleKit->InstallAllAccessories(true); + _accessoryRespawnTimer = 0; + } + else + _accessoryRespawnTimer -= diff; + } + +private: + uint32 _accessoryRespawnTimer; }; enum CloseRift @@ -1218,7 +1186,7 @@ void AddSC_storm_peaks() new npc_brunnhildar_prisoner(); new npc_freed_protodrake(); new npc_icefang(); - new npc_hyldsmeet_protodrake(); + RegisterCreatureAI(npc_hyldsmeet_protodrake); RegisterSpellScript(spell_close_rift_aura); new npc_vehicle_d16_propelled_delivery(); RegisterSpellScript(spell_q12823_remove_collapsing_cave_aura); diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp index 6cc9c8ae3..94e300720 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp @@ -271,12 +271,12 @@ class spell_astromancer_solarian_transform : public AuraScript void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - GetUnitOwner()->HandleStatModifier(UnitMods(UNIT_MOD_ARMOR), TOTAL_PCT, 400.0f, true); + GetUnitOwner()->ApplyStatPctModifier(UNIT_MOD_ARMOR, TOTAL_PCT, 400.0f); } void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - GetUnitOwner()->HandleStatModifier(UnitMods(UNIT_MOD_ARMOR), TOTAL_PCT, 400.0f, false); + GetUnitOwner()->ApplyStatPctModifier(UnitMods(UNIT_MOD_ARMOR), TOTAL_PCT, -80.0f); } void Register() override diff --git a/src/server/scripts/Pet/pet_hunter.cpp b/src/server/scripts/Pet/pet_hunter.cpp index 3a6d97950..b82180e66 100644 --- a/src/server/scripts/Pet/pet_hunter.cpp +++ b/src/server/scripts/Pet/pet_hunter.cpp @@ -99,7 +99,7 @@ struct npc_pet_hunter_snake_trap : public ScriptedAI uint32 health = uint32(107 * (me->GetLevel() - 40) * 0.025f); me->SetCreateHealth(health); - me->SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, (float)health); + me->SetStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, (float)health); me->SetMaxHealth(health); //Add delta to make them not all hit the same time diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index 49687928f..4cb86db3d 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -174,8 +174,8 @@ class spell_dk_raise_ally : public SpellScript if (pInfo) // exist in DB { ghoul->SetCreateHealth(pInfo->health); - ghoul->SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, pInfo->health); - ghoul->SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor)); + ghoul->SetStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, pInfo->health); + ghoul->SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor)); for (uint8 stat = 0; stat < MAX_STATS; ++stat) ghoul->SetCreateStat(Stats(stat), float(pInfo->stats[stat])); } @@ -194,9 +194,9 @@ class spell_dk_raise_ally : public SpellScript // DK Ghoul haste refresh float val = (GetCaster()->m_modAttackSpeedPct[BASE_ATTACK] - 1.0f) * 100.0f; + val *= 2000.0f + 2000.0f * ((100.0f + val) / 100.0f); ghoul->m_modAttackSpeedPct[BASE_ATTACK] = GetCaster()->m_modAttackSpeedPct[BASE_ATTACK]; - ghoul->SetFloatValue(UNIT_FIELD_BASEATTACKTIME, 2000.0f); - ghoul->ApplyPercentModFloatValue(UNIT_FIELD_BASEATTACKTIME, val, true); // we want to reduce attack time + ghoul->SetFloatValue(UNIT_FIELD_BASEATTACKTIME, val); // Strength + Stamina for (uint8 i = STAT_STRENGTH; i <= STAT_STAMINA; ++i) @@ -223,20 +223,20 @@ class spell_dk_raise_ally : public SpellScript value = float(GetCaster()->GetStat(stat)) * mod; value = ghoul->GetTotalStatValue(stat, value); ghoul->SetStat(stat, int32(value)); - ghoul->ApplyStatBuffMod(stat, value, true); + ghoul->UpdateStatBuffMod(stat); } // Attack Power - ghoul->SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, 589 + ghoul->GetStat(STAT_STRENGTH) + ghoul->GetStat(STAT_AGILITY)); - ghoul->SetInt32Value(UNIT_FIELD_ATTACK_POWER, (int32)ghoul->GetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE) * ghoul->GetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_PCT)); - ghoul->SetInt32Value(UNIT_FIELD_ATTACK_POWER_MODS, (int32)ghoul->GetModifierValue(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE)); - ghoul->SetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER, ghoul->GetModifierValue(UNIT_MOD_ATTACK_POWER, TOTAL_PCT) - 1.0f); + ghoul->SetStatFlatModifier(UNIT_MOD_ATTACK_POWER, BASE_VALUE, 589 + ghoul->GetStat(STAT_STRENGTH) + ghoul->GetStat(STAT_AGILITY)); + ghoul->SetInt32Value(UNIT_FIELD_ATTACK_POWER, (int32)ghoul->GetFlatModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE) * ghoul->GetPctModifierValue(UNIT_MOD_ATTACK_POWER, BASE_PCT)); + ghoul->SetInt32Value(UNIT_FIELD_ATTACK_POWER_MODS, (int32)ghoul->GetFlatModifierValue(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE)); + ghoul->SetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER, ghoul->GetPctModifierValue(UNIT_MOD_ATTACK_POWER, TOTAL_PCT) - 1.0f); // Health - ghoul->SetModifierValue(UNIT_MOD_HEALTH, TOTAL_VALUE, (ghoul->GetStat(STAT_STAMINA) - ghoul->GetCreateStat(STAT_STAMINA)) * 10.0f); + ghoul->SetStatFlatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, (ghoul->GetStat(STAT_STAMINA) - ghoul->GetCreateStat(STAT_STAMINA)) * 10.0f); // Power Energy - ghoul->SetModifierValue(UnitMods(UNIT_MOD_POWER_START + static_cast(POWER_ENERGY)), BASE_VALUE, ghoul->GetCreatePowers(POWER_ENERGY)); + ghoul->SetStatFlatModifier(UnitMods(UNIT_MOD_POWER_START + static_cast(POWER_ENERGY)), BASE_VALUE, ghoul->GetCreatePowers(POWER_ENERGY)); ghoul->UpdateAllStats(); ghoul->SetFullHealth(); diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp index c6f90e153..85a12610d 100644 --- a/src/server/scripts/Spells/spell_druid.cpp +++ b/src/server/scripts/Spells/spell_druid.cpp @@ -443,15 +443,16 @@ class spell_dru_enrage : public AuraScript void RecalculateBaseArmor() { + // Recalculate modifies the list while we're iterating through it, so let's copy it instead Unit::AuraEffectList const& auras = GetTarget()->GetAuraEffectsByType(SPELL_AURA_MOD_BASE_RESISTANCE_PCT); - for (Unit::AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i) + std::vector aurEffs(auras.begin(), auras.end()); + + for (AuraEffect* aurEff : aurEffs) { - SpellInfo const* spellInfo = (*i)->GetSpellInfo(); + SpellInfo const* spellInfo = aurEff->GetSpellInfo(); // Dire- / Bear Form (Passive) if (spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && spellInfo->SpellFamilyFlags.HasFlag(0x0, 0x0, 0x2)) - { - (*i)->RecalculateAmount(); - } + aurEff->RecalculateAmount(); } } diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index f9def7bca..7c325aac6 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -4422,7 +4422,9 @@ class spell_gen_eject_all_passengers : public SpellScript } }; -/* 62539 - Eject Passenger 2 +/* 49259 - Despawn Driver + 49261 - Dismount Passenger + 62539 - Eject Passenger 2 64614 - Eject Passenger 4 64629 - Eject Passenger 1 64630 - Eject Passenger 2 @@ -5670,6 +5672,29 @@ class spell_gen_bm_on : public SpellScript } }; +class spell_gen_whisper_to_controller : public SpellScript +{ + PrepareSpellScript(spell_gen_whisper_to_controller); + + bool Validate(SpellInfo const* spellInfo) override + { + return sObjectMgr->GetBroadcastText(uint32(spellInfo->GetEffect(EFFECT_0).CalcValue())); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* caster = GetCaster()) + if (TempSummon* casterSummon = caster->ToTempSummon()) + if (Player* target = casterSummon->GetSummonerUnit()->ToPlayer()) + casterSummon->Unit::Whisper(uint32(GetEffectValue()), target, false); + } + + void Register() override + { + OnEffectHit += SpellEffectFn(spell_gen_whisper_to_controller::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + void AddSC_generic_spell_scripts() { RegisterSpellScript(spell_silithyst); @@ -5843,4 +5868,5 @@ void AddSC_generic_spell_scripts() RegisterSpellScript(spell_gen_invis_on); RegisterSpellScript(spell_gen_bm_on); RegisterSpellScript(spell_gen_bm_off); + RegisterSpellScript(spell_gen_whisper_to_controller); } diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp index f9cdd7623..0acf87cb2 100644 --- a/src/server/scripts/Spells/spell_paladin.cpp +++ b/src/server/scripts/Spells/spell_paladin.cpp @@ -473,11 +473,7 @@ class spell_pal_blessing_of_sanctuary : public AuraScript { Unit* target = GetTarget(); if (Unit* caster = GetCaster()) - { - // xinef: hack - int32 value = 9; - caster->CastCustomSpell(target, SPELL_PALADIN_BLESSING_OF_SANCTUARY_BUFF, &value, &value, 0, true); - } + caster->CastSpell(target, SPELL_PALADIN_BLESSING_OF_SANCTUARY_BUFF, true); } void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) @@ -965,6 +961,24 @@ class spell_pal_lay_on_hands : public SpellScript return true; } + void HandleMaxHealthHeal(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + Unit* target = GetExplTargetUnit(); + + if (!target || !caster) + return; + + uint32 baseHeal = caster->GetMaxHealth(); + uint32 modifiedHeal = target->SpellHealingBonusTaken(caster, GetSpellInfo(), baseHeal, HEAL); + + // EffectHealMaxHealth() ignores healing modifiers, so we pre-apply the + // difference here; this delta will be added on top of the raw heal. + int64 healAdjustment = int64(modifiedHeal) - int64(baseHeal); + + SetHitHeal(healAdjustment); + } + SpellCastResult CheckCast() { Unit* caster = GetCaster(); @@ -1004,6 +1018,7 @@ class spell_pal_lay_on_hands : public SpellScript { OnCheckCast += SpellCheckCastFn(spell_pal_lay_on_hands::CheckCast); AfterHit += SpellHitFn(spell_pal_lay_on_hands::HandleScript); + OnEffectHitTarget += SpellEffectFn(spell_pal_lay_on_hands::HandleMaxHealthHeal, EFFECT_0, SPELL_EFFECT_HEAL_MAX_HEALTH); } int32 _manaAmount; diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp index 870cc7385..4e1b56333 100644 --- a/src/server/scripts/Spells/spell_quest.cpp +++ b/src/server/scripts/Spells/spell_quest.cpp @@ -247,28 +247,6 @@ class spell_q10525_vision_guide : public AuraScript } }; -class spell_q11322_q11317_the_cleansing : public AuraScript -{ - PrepareAuraScript(spell_q11322_q11317_the_cleansing) - - void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - Unit* ar = GetCaster(); - if (ar && ar->ToPlayer()) - { - if (ar->ToPlayer()->GetQuestStatus(11317) == QUEST_STATUS_INCOMPLETE || ar->ToPlayer()->GetQuestStatus(11322) == QUEST_STATUS_INCOMPLETE) - ar->SummonCreature(27959, 3032.0f, -5095.0f, 723.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); - - ar->SetStandState(UNIT_STAND_STATE_SIT); - } - } - - void Register() override - { - OnEffectApply += AuraEffectApplyFn(spell_q11322_q11317_the_cleansing::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - } -}; - class spell_q10714_on_spirits_wings : public SpellScript { PrepareSpellScript(spell_q10714_on_spirits_wings); @@ -2499,7 +2477,6 @@ void AddSC_quest_spell_scripts() RegisterSpellScript(spell_q12014_steady_as_a_rock); RegisterSpellAndAuraScriptPair(spell_q11026_a11051_banish_the_demons, spell_q11026_a11051_banish_the_demons_aura); RegisterSpellScript(spell_q10525_vision_guide); - RegisterSpellScript(spell_q11322_q11317_the_cleansing); RegisterSpellScript(spell_q10714_on_spirits_wings); RegisterSpellScript(spell_q10720_the_smallest_creature); RegisterSpellScript(spell_q13086_last_line_of_defence); diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index d6a6a3d8c..e484b2b33 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -18,6 +18,7 @@ #include "AreaDefines.h" #include "CreatureScript.h" #include "Pet.h" +#include "PetDefines.h" #include "Player.h" #include "SpellAuraEffects.h" #include "SpellInfo.h" @@ -25,6 +26,8 @@ #include "SpellScript.h" #include "SpellScriptLoader.h" #include "TemporarySummon.h" +#include "Unit.h" +#include "Util.h" /* * Scripts for spells with SPELLFAMILY_WARLOCK and SPELLFAMILY_GENERIC spells used by warlock players. * Ordered alphabetically using scriptname. @@ -73,6 +76,7 @@ enum WarlockSpells SPELL_WARLOCK_EYE_OF_KILROGG_FLY = 58083, SPELL_WARLOCK_PET_VOID_STAR_TALISMAN = 37386, // Void Star Talisman SPELL_WARLOCK_DEMONIC_PACT_PROC = 48090, + SPELL_WARLOCK_GLYPH_OF_VOIDWALKER = 56247, }; enum WarlockSpellIcons @@ -292,7 +296,7 @@ class spell_warl_generic_scaling : public AuraScript void CalculateResistanceAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) { - // xinef: pet inherits 40% of resistance from owner and 35% of armor + // pet inherits 40% of resistance from owner and 35% of armor if (Unit* owner = GetUnitOwner()->GetOwner()) { SpellSchoolMask schoolMask = SpellSchoolMask(aurEff->GetSpellInfo()->Effects[aurEff->GetEffIndex()].MiscValue); @@ -308,7 +312,7 @@ class spell_warl_generic_scaling : public AuraScript void CalculateStatAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) { - // xinef: by default warlock pet inherits 75% of stamina and 30% of intellect + // by default warlock pet inherits 75% of stamina and 30% of intellect if (Unit* owner = GetUnitOwner()->GetOwner()) { Stats stat = Stats(aurEff->GetSpellInfo()->Effects[aurEff->GetEffIndex()].MiscValue); @@ -317,21 +321,33 @@ class spell_warl_generic_scaling : public AuraScript } } - void CalculateAPAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + void CalculateAPAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) { - // xinef: by default warlock pet inherits 57% of max(SP FIRE, SP SHADOW) as AP - if (Unit* owner = GetUnitOwner()->GetOwner()) + if (Unit* pet = GetUnitOwner()) { - int32 fire = owner->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_FIRE); - int32 shadow = owner->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_SHADOW); - int32 maximum = (fire > shadow) ? fire : shadow; - amount = CalculatePct(std::max(0, maximum), 57); + // by default warlock pet inherits 57% of max(SP FIRE, SP SHADOW) as AP + if (Unit* owner = pet->GetOwner()) + { + int32 fire = owner->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_FIRE); + int32 shadow = owner->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_SHADOW); + int32 maximum = (fire > shadow) ? fire : shadow; + amount = CalculatePct(std::max(0, maximum), 57); + + // Glyph of felguard, 99% sure this is a HACK + if (pet->GetEntry() == NPC_FELGUARD) + { + if (AuraEffect* glyph = owner->GetAuraEffect(SPELL_GLYPH_OF_FELGUARD, EFFECT_0)) + { + amount += CalculatePct(pet->GetTotalAuraModValue(UNIT_MOD_ATTACK_POWER) - aurEff->GetAmount() + amount, glyph->GetAmount()); + } + } + } } } void CalculateSPAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) { - // xinef: by default warlock pet inherits 15% of max(SP FIRE, SP SHADOW) as SP + // by default warlock pet inherits 15% of max(SP FIRE, SP SHADOW) as SP if (Unit* owner = GetUnitOwner()->GetOwner()) { int32 fire = owner->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_FIRE); @@ -339,7 +355,7 @@ class spell_warl_generic_scaling : public AuraScript int32 maximum = (fire > shadow) ? fire : shadow; amount = CalculatePct(std::max(0, maximum), 15); - // xinef: Update appropriate player field + // Update appropriate player field if (owner->IsPlayer()) owner->SetUInt32Value(PLAYER_PET_SPELL_POWER, (uint32)amount); } @@ -1370,81 +1386,27 @@ class spell_warl_shadowburn : public AuraScript } }; -class spell_warl_glyph_of_felguard : public AuraScript +class spell_warl_voidwalker_pet_passive : public AuraScript { - PrepareAuraScript(spell_warl_glyph_of_felguard); + PrepareAuraScript(spell_warl_voidwalker_pet_passive); - void HandleApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + bool Validate(SpellInfo const* /*spellInfo*/) override { - if (Player* player = GetCaster()->ToPlayer()) - { - if (Pet* pet = player->GetPet()) - { - if (pet->GetEntry() == NPC_FELGUARD) - { - pet->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, aurEff->GetAmount(), true); - } - } - } + return ValidateSpellInfo({ SPELL_WARLOCK_GLYPH_OF_VOIDWALKER }); } - void HandleRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + void CalculateAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) { - if (Player* player = GetCaster()->ToPlayer()) - { - if (Pet* pet = player->GetPet()) - { - if (pet->GetEntry() == NPC_FELGUARD) - { - pet->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, aurEff->GetAmount(), false); - } - } - } + if (Unit* pet = GetUnitOwner()) + if (pet->IsPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + if (AuraEffect* aurEff = owner->GetAuraEffect(SPELL_WARLOCK_GLYPH_OF_VOIDWALKER, EFFECT_0)) + amount += aurEff->GetAmount(); } void Register() override { - OnEffectApply += AuraEffectApplyFn(spell_warl_glyph_of_felguard::HandleApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - OnEffectRemove += AuraEffectRemoveFn(spell_warl_glyph_of_felguard::HandleRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - } -}; - -class spell_warl_glyph_of_voidwalker : public AuraScript -{ - PrepareAuraScript(spell_warl_glyph_of_voidwalker); - - void HandleApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) - { - if (Player* player = GetCaster()->ToPlayer()) - { - if (Pet* pet = player->GetPet()) - { - if (pet->GetEntry() == NPC_VOIDWALKER) - { - pet->HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_PCT, aurEff->GetAmount(), true); - } - } - } - } - - void HandleRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) - { - if (Player* player = GetCaster()->ToPlayer()) - { - if (Pet* pet = player->GetPet()) - { - if (pet->GetEntry() == NPC_VOIDWALKER) - { - pet->HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_PCT, aurEff->GetAmount(), false); - } - } - } - } - - void Register() override - { - OnEffectApply += AuraEffectApplyFn(spell_warl_glyph_of_voidwalker::HandleApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - OnEffectRemove += AuraEffectRemoveFn(spell_warl_glyph_of_voidwalker::HandleRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_voidwalker_pet_passive::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE); } }; @@ -1529,7 +1491,6 @@ void AddSC_warlock_spell_scripts() RegisterSpellScript(spell_warl_unstable_affliction); RegisterSpellScript(spell_warl_drain_soul); RegisterSpellScript(spell_warl_shadowburn); - RegisterSpellScript(spell_warl_glyph_of_felguard); - RegisterSpellScript(spell_warl_glyph_of_voidwalker); + RegisterSpellScript(spell_warl_voidwalker_pet_passive); RegisterSpellScript(spell_warl_demonic_pact_aura); } diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index 23b46b039..cb669c3f0 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -563,10 +563,6 @@ public: if (!SpawnAssoc) return; - // check if they're hostile - if (!(me->IsHostileTo(who) || who->IsHostileTo(me))) - return; - if (me->IsValidAttackTarget(who)) { Player* playerTarget = who->ToPlayer(); diff --git a/src/server/shared/DataStores/DBCStructure.h b/src/server/shared/DataStores/DBCStructure.h index 449b8fb08..98ddad98d 100644 --- a/src/server/shared/DataStores/DBCStructure.h +++ b/src/server/shared/DataStores/DBCStructure.h @@ -1244,8 +1244,7 @@ struct ItemRandomPropertiesEntry { uint32 ID; // 0 //char const* InternalName; // 1 - std::array Enchantment; // 2-4 - //std::array UnusedEnchantment; // 5-6 + std::array Enchantment; // 2-6 std::array Name; // 7-22 //uint32 Name_lang_mask; // 23 }; @@ -1256,10 +1255,8 @@ struct ItemRandomSuffixEntry std::array Name; // 1-16 //uint32 Name_lang_mask; // 17 //char const* InternalName; // 18 - std::array Enchantment; // 19-21 - //std::array UnusedEnchantment; // 22-23 - std::array AllocationPct; // 24-26 - //std::array UnusedAllocationPct; // 27-28 + std::array Enchantment; // 19-23 + std::array AllocationPct; // 24-28 }; #define MAX_ITEM_SET_ITEMS 10 diff --git a/src/server/shared/Network/AsyncAcceptor.h b/src/server/shared/Network/AsyncAcceptor.h index f91c2ca37..71c58ed93 100644 --- a/src/server/shared/Network/AsyncAcceptor.h +++ b/src/server/shared/Network/AsyncAcceptor.h @@ -20,6 +20,7 @@ #include "IpAddress.h" #include "Log.h" +#include "Systemd.h" #include #include #include @@ -33,10 +34,20 @@ class AsyncAcceptor public: typedef void(*AcceptCallback)(tcp::socket&& newSocket, uint32 threadIndex); - AsyncAcceptor(Acore::Asio::IoContext& ioContext, std::string const& bindIp, uint16 port) : + AsyncAcceptor(Acore::Asio::IoContext& ioContext, std::string const& bindIp, uint16 port, bool supportSocketActivation = false) : _acceptor(ioContext), _endpoint(Acore::Net::make_address(bindIp), port), - _socket(ioContext), _closed(false), _socketFactory([this](){ return DefaultSocketFactory(); }) + _socket(ioContext), _closed(false), _socketFactory([this](){ return DefaultSocketFactory(); }), + _supportSocketActivation(supportSocketActivation) { + int const listen_fd = get_listen_fd(); + if (_supportSocketActivation && listen_fd > 0) + { + LOG_DEBUG("network", "Using socket from systemd socket activation"); + boost::system::error_code errorCode; + _acceptor.assign(boost::asio::ip::tcp::v4(), listen_fd, errorCode); + if (errorCode) + LOG_WARN("network", "Failed to assign socket {}", errorCode.message()); + } } template @@ -72,27 +83,31 @@ public: bool Bind() { boost::system::error_code errorCode; - _acceptor.open(_endpoint.protocol(), errorCode); - if (errorCode) + // with socket activation the acceptor is already open and bound + if (!_acceptor.is_open()) { - LOG_INFO("network", "Failed to open acceptor {}", errorCode.message()); - return false; - } + _acceptor.open(_endpoint.protocol(), errorCode); + if (errorCode) + { + LOG_INFO("network", "Failed to open acceptor {}", errorCode.message()); + return false; + } #if AC_PLATFORM != AC_PLATFORM_WINDOWS - _acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true), errorCode); - if (errorCode) - { - LOG_INFO("network", "Failed to set reuse_address option on acceptor {}", errorCode.message()); - return false; - } + _acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true), errorCode); + if (errorCode) + { + LOG_INFO("network", "Failed to set reuse_address option on acceptor {}", errorCode.message()); + return false; + } #endif - _acceptor.bind(_endpoint, errorCode); - if (errorCode) - { - LOG_INFO("network", "Could not bind to {}:{} {}", _endpoint.address().to_string(), _endpoint.port(), errorCode.message()); - return false; + _acceptor.bind(_endpoint, errorCode); + if (errorCode) + { + LOG_INFO("network", "Could not bind to {}:{} {}", _endpoint.address().to_string(), _endpoint.port(), errorCode.message()); + return false; + } } _acceptor.listen(ACORE_MAX_LISTEN_CONNECTIONS, errorCode); @@ -124,6 +139,7 @@ private: tcp::socket _socket; std::atomic _closed; std::function()> _socketFactory; + bool _supportSocketActivation; }; template diff --git a/src/server/shared/Network/SocketMgr.h b/src/server/shared/Network/SocketMgr.h index dc0c5e6f5..085e4e238 100644 --- a/src/server/shared/Network/SocketMgr.h +++ b/src/server/shared/Network/SocketMgr.h @@ -19,6 +19,7 @@ #define SocketMgr_h__ #include "AsyncAcceptor.h" +#include "Config.h" #include "Errors.h" #include "NetworkThread.h" #include @@ -42,7 +43,8 @@ public: std::unique_ptr acceptor; try { - acceptor = std::make_unique(ioContext, bindIp, port); + bool supportSocketActivation = sConfigMgr->GetOption("Network.UseSocketActivation", false); + acceptor = std::make_unique(ioContext, bindIp, port, supportSocketActivation); } catch (boost::system::system_error const& err) { diff --git a/src/tools/mmaps_generator/mmaps-config.yaml b/src/tools/mmaps_generator/mmaps-config.yaml index 2a0aba1fc..7adcee64c 100644 --- a/src/tools/mmaps_generator/mmaps-config.yaml +++ b/src/tools/mmaps_generator/mmaps-config.yaml @@ -119,6 +119,11 @@ mmapsConfig: # https://github.com/azerothcore/azerothcore-wotlk/pull/22462#issuecomment-3067024680 walkableSlopeAngle: 45 + "530": # Outland + tilesOverrides: + "32,30": # Dark portal + walkableSlopeAngle: 45 # https://github.com/chromiecraft/chromiecraft/issues/8404#issuecomment-3476012660 + # debugOutput generates debug files in the `meshes` directory for use with RecastDemo. # This is useful for inspecting and debugging mmap generation visually. # diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp index 3b6e5a5be..52f4983f8 100644 --- a/src/tools/vmap4_extractor/vmapexport.cpp +++ b/src/tools/vmap4_extractor/vmapexport.cpp @@ -144,6 +144,7 @@ bool ExtractSingleWmo(std::string& fname) WMODoodadData& doodads = WmoDoodads[plain_name]; std::swap(doodads, froot.DoodadData); int Wmo_nVertices = 0; + uint32 groupCount = 0; //printf("root has %d groups\n", froot->nGroups); if (froot.nGroups != 0) { @@ -170,7 +171,11 @@ bool ExtractSingleWmo(std::string& fname) break; } + if (fgroup.ShouldSkip(&froot)) + continue; + Wmo_nVertices += fgroup.ConvertToVMAPGroupWmo(output, preciseVectorData); + ++groupCount; for (uint16 groupReference : fgroup.DoodadReferences) { if (groupReference >= doodads.Spawns.size()) @@ -187,6 +192,8 @@ bool ExtractSingleWmo(std::string& fname) fseek(output, 8, SEEK_SET); // store the correct no of vertices fwrite(&Wmo_nVertices, sizeof(int), 1, output); + // store the correct no of groups + fwrite(&groupCount, sizeof(uint32), 1, output); fclose(output); // Delete the extracted file in the case of an error diff --git a/src/tools/vmap4_extractor/vmapexport.h b/src/tools/vmap4_extractor/vmapexport.h index bf0872bfa..fc8433996 100644 --- a/src/tools/vmap4_extractor/vmapexport.h +++ b/src/tools/vmap4_extractor/vmapexport.h @@ -24,8 +24,8 @@ namespace VMAP { - const char VMAP_MAGIC[] = "VMAP_4.7"; - const char RAW_VMAP_MAGIC[] = "VMAP047"; // used in extracted vmap files with raw data + const char VMAP_MAGIC[] = "VMAP_4.8"; + const char RAW_VMAP_MAGIC[] = "VMAP048"; // used in extracted vmap files with raw data } enum ModelFlags diff --git a/src/tools/vmap4_extractor/wmo.cpp b/src/tools/vmap4_extractor/wmo.cpp index 0a2536794..ed20db119 100644 --- a/src/tools/vmap4_extractor/wmo.cpp +++ b/src/tools/vmap4_extractor/wmo.cpp @@ -103,6 +103,11 @@ bool WMORoot::open() DoodadData.Spawns.resize(size / sizeof(WMO::MODD)); f.read(DoodadData.Spawns.data(), size); } + else if (!strcmp(fourcc, "MOGN")) + { + GroupNames.resize(size); + f.read(GroupNames.data(), size); + } /* else if (!strcmp(fourcc,"MOTX")) { @@ -497,6 +502,22 @@ uint32 WMOGroup::GetLiquidTypeId(uint32 liquidTypeId) return liquidTypeId; } +bool WMOGroup::ShouldSkip(WMORoot const* root) const +{ + // skip unreachable + if (mogpFlags & 0x80) + return true; + + // skip antiportals + if (mogpFlags & 0x4000000) + return true; + + if (groupName < int32(root->GroupNames.size()) && !strcmp(&root->GroupNames[groupName], "antiportal")) + return true; + + return false; +} + WMOGroup::~WMOGroup() { delete [] MOPY; diff --git a/src/tools/vmap4_extractor/wmo.h b/src/tools/vmap4_extractor/wmo.h index dc44331e3..4d00b11ce 100644 --- a/src/tools/vmap4_extractor/wmo.h +++ b/src/tools/vmap4_extractor/wmo.h @@ -85,6 +85,7 @@ public: float bbcorn1[3]; float bbcorn2[3]; + std::vector GroupNames; WMODoodadData DoodadData; std::unordered_set ValidDoodadNames; @@ -154,6 +155,7 @@ public: bool open(WMORoot* rootWMO); int ConvertToVMAPGroupWmo(FILE* output, bool preciseVectorData); uint32 GetLiquidTypeId(uint32 liquidTypeId); + bool ShouldSkip(WMORoot const* root) const; }; namespace MapObject