diff options
35 files changed, 726 insertions, 220 deletions
diff --git a/.github/ISSUE_TEMPLATE/ee_cc.yml b/.github/ISSUE_TEMPLATE/ee_cc.yml index 4ed34e08e0..ad7d6744a6 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/data/sql/updates/pending_db_world/rev_1764224411866335544.sql b/data/sql/updates/db_world/2025_11_29_00.sql index cee78d2912..bc7f243229 100644 --- a/data/sql/updates/pending_db_world/rev_1764224411866335544.sql +++ b/data/sql/updates/db_world/2025_11_29_00.sql @@ -1,3 +1,4 @@ +-- 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`) 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 0000000000..54434ca272 --- /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 0000000000..c4da8275c2 --- /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 0000000000..f11598497c --- /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 0000000000..2c17d4fd58 --- /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 0000000000..1d3b995119 --- /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 0000000000..86ab760949 --- /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 0000000000..a59af90568 --- /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 0000000000..f2462e6997 --- /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 0000000000..a8f2539156 --- /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 0000000000..83b9493be3 --- /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 0000000000..fa6fe98c34 --- /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 0000000000..babbf5e14b --- /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 0000000000..cdc6629f00 --- /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 0000000000..cdbff3fc43 --- /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/src/common/Utilities/Systemd.cpp b/src/common/Utilities/Systemd.cpp new file mode 100644 index 0000000000..f7c39cfb17 --- /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 <http://www.gnu.org/licenses/>. + */ + +#if defined(__linux__) +#include "Log.h" +#include "StringConvert.h" +#include <cstdlib> +#include <unistd.h> +#include <string> + +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<int>(listen_pid).value_or(0); + if (pid != getpid()) + return 0; + + int fds = Acore::StringTo<int>(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 0000000000..312345cea1 --- /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 <http://www.gnu.org/licenses/>. + */ + +#ifndef _SYSTEMD_H_ +#define _SYSTEMD_H_ + +int get_listen_fd(); + +#endif diff --git a/src/server/apps/worldserver/Main.cpp b/src/server/apps/worldserver/Main.cpp index d1c10131b1..511c17e367 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<bool>("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 07945f07f3..089c1911a5 100644 --- a/src/server/apps/worldserver/worldserver.conf.dist +++ b/src/server/apps/worldserver/worldserver.conf.dist @@ -398,6 +398,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 + +# ################################################################################################### ################################################################################################### diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 8891c8788e..5bcd49fcf3 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -7647,7 +7647,7 @@ void Player::_ApplyAllItemMods() if (!proto) continue; - ApplyItemDependentAuras(m_items[i], false); + ApplyItemDependentAuras(m_items[i], true); _ApplyItemBonuses(proto, i, true); WeaponAttackType const attackType = Player::GetAttackBySlot(i); diff --git a/src/server/game/Entities/Player/PlayerUpdates.cpp b/src/server/game/Entities/Player/PlayerUpdates.cpp index 1d3b5788b3..9a4427ce49 100644 --- a/src/server/game/Entities/Player/PlayerUpdates.cpp +++ b/src/server/game/Entities/Player/PlayerUpdates.cpp @@ -701,7 +701,7 @@ void Player::UpdateRating(CombatRating cr) void Player::UpdateAllRatings() { - for (uint 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 4e2fd4532a..24c025ac6d 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); } @@ -272,7 +272,7 @@ void Player::UpdateArmor() 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 += GetStat(STAT_AGILITY) * 2.0f; // armor bonus from stats value += GetFlatModifierValue(unitMod, TOTAL_VALUE); //add dynamic flat mods diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 817bc25b77..623886eb78 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -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); @@ -13465,7 +13465,12 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT if (mechanicMask) { - TakenTotalMod *= GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT, mechanicMask); + TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT, [mechanicMask](AuraEffect const* aurEff) -> bool + { + if (mechanicMask & uint32(1 << (aurEff->GetMiscValue()))) + return true; + return false; + }); } } diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 8370ebae57..934bb1c70c 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -219,7 +219,7 @@ enum WeaponAttackType : uint8 MAX_ATTACK }; -enum CombatRating +enum CombatRating : uint8 { CR_WEAPON_SKILL = 0, CR_DEFENSE_SKILL = 1, diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index a878194589..fb40ce36ac 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/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index dcef617a65..7ffb4065f8 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -726,9 +726,12 @@ void AuraEffect::ChangeAmount(int32 newAmount, bool mark, bool onStackOrReapply) std::list<AuraApplication*> effectApplications; GetApplicationList(effectApplications); - for (std::list<AuraApplication*>::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) { @@ -739,9 +742,15 @@ void AuraEffect::ChangeAmount(int32 newAmount, bool mark, bool onStackOrReapply) CalculateSpellMod(); } - for (std::list<AuraApplication*>::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) @@ -5105,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); } @@ -5121,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); } diff --git a/src/server/game/Spells/SpellInfoCorrections.cpp b/src/server/game/Spells/SpellInfoCorrections.cpp index ca45356219..0615f39c00 100644 --- a/src/server/game/Spells/SpellInfoCorrections.cpp +++ b/src/server/game/Spells/SpellInfoCorrections.cpp @@ -5162,6 +5162,14 @@ void SpellMgr::LoadSpellInfoCorrections() 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]; diff --git a/src/server/scripts/Northrend/zone_crystalsong_forest.cpp b/src/server/scripts/Northrend/zone_crystalsong_forest.cpp index bdf394cad9..645d3c0224 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 <http://www.gnu.org/licenses/>. */ +#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; + explicit npc_preparations_for_war_vehicle(Creature* creature) : VehicleAI(creature), searchForShipTimer(0), transportEntry(me->GetEntry() == NPC_CLOUDBUSTER ? TRANSPORT_THE_SKYBREAKER : TRANSPORT_ORGRIMS_HAMMER) + { + 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 InitializeAI() override + void PassengerBoarded(Unit* who, int8 /*seatId*/, bool apply) override { - me->GetMotionMaster()->MovePath(me->GetEntry(), FORCED_MOVEMENT_NONE, PathSource::SMART_WAYPOINT_MGR); + 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? + } - NullCreatureAI::InitializeAI(); - pointId = 0; - searchForShipTimer = 0; - transportEntry = (me->GetEntry() == NPC_HAMMERHEAD ? TRANSPORT_ORGRIMS_HAMMER : TRANSPORT_THE_SKYBREAKER); + void MovementInform(uint32 type, uint32 id) override + { + if (type == ESCORT_MOTION_TYPE && id == POINT_END) + searchForShipTimer = 3000; } - void MovementInform(uint32 type, uint32 /*id*/) override + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override { - if (type == ESCORT_MOTION_TYPE) - if (++pointId == 17) // path size - searchForShipTimer = 3000; + 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_howling_fjord.cpp b/src/server/scripts/Northrend/zone_howling_fjord.cpp index fc28598ec2..928a0a71e8 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/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp index c6f90e153e..85a12610da 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<AuraEffect*> 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 f36f2d2234..38f669693f 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -5673,6 +5673,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); @@ -5846,4 +5869,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_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp index 870cc73850..4e1b563333 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/shared/Network/AsyncAcceptor.h b/src/server/shared/Network/AsyncAcceptor.h index f91c2ca37e..71c58ed937 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 <atomic> #include <boost/asio/ip/tcp.hpp> #include <functional> @@ -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<class T> @@ -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<bool> _closed; std::function<std::pair<tcp::socket*, uint32>()> _socketFactory; + bool _supportSocketActivation; }; template<class T> diff --git a/src/server/shared/Network/SocketMgr.h b/src/server/shared/Network/SocketMgr.h index dc0c5e6f5f..085e4e2380 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 <boost/asio/ip/tcp.hpp> @@ -42,7 +43,8 @@ public: std::unique_ptr<AsyncAcceptor> acceptor; try { - acceptor = std::make_unique<AsyncAcceptor>(ioContext, bindIp, port); + bool supportSocketActivation = sConfigMgr->GetOption<bool>("Network.UseSocketActivation", false); + acceptor = std::make_unique<AsyncAcceptor>(ioContext, bindIp, port, supportSocketActivation); } catch (boost::system::system_error const& err) { |
