diff --git a/data/sql/updates/pending_db_character/rev_1719945200692175000.sql b/data/sql/updates/db_characters/2024_07_05_00.sql similarity index 56% rename from data/sql/updates/pending_db_character/rev_1719945200692175000.sql rename to data/sql/updates/db_characters/2024_07_05_00.sql index 93b01738b..4a7e9e03c 100644 --- a/data/sql/updates/pending_db_character/rev_1719945200692175000.sql +++ b/data/sql/updates/db_characters/2024_07_05_00.sql @@ -1,3 +1,4 @@ +-- DB update 2024_01_20_00 -> 2024_07_05_00 -- ALTER TABLE `character_homebind` diff --git a/data/sql/updates/db_world/2024_07_04_00.sql b/data/sql/updates/db_world/2024_07_04_00.sql new file mode 100644 index 000000000..fd521f81e --- /dev/null +++ b/data/sql/updates/db_world/2024_07_04_00.sql @@ -0,0 +1,2 @@ +-- DB update 2024_07_02_00 -> 2024_07_04_00 +UPDATE `gameobject` SET `position_x` = -11102.743, `position_y` = -1848.9752, `position_z` = 221.06969, `orientation` = 5.393069, `rotation2` = -0.43051052, `rotation3` = 0.90258557 WHERE `guid` = 56429 AND `id` = 185119; diff --git a/data/sql/updates/db_world/2024_07_04_01.sql b/data/sql/updates/db_world/2024_07_04_01.sql new file mode 100644 index 000000000..863d045ca --- /dev/null +++ b/data/sql/updates/db_world/2024_07_04_01.sql @@ -0,0 +1,3 @@ +-- DB update 2024_07_04_00 -> 2024_07_04_01 +-- +UPDATE `creature_template` SET `flags_extra` = `flags_extra` | 128 WHERE `entry` = 8611; diff --git a/data/sql/updates/db_world/2024_07_04_02.sql b/data/sql/updates/db_world/2024_07_04_02.sql new file mode 100644 index 000000000..7c27ae5bd --- /dev/null +++ b/data/sql/updates/db_world/2024_07_04_02.sql @@ -0,0 +1,33 @@ +-- DB update 2024_07_04_01 -> 2024_07_04_02 +DELETE FROM `gossip_menu` WHERE `MenuID` = 7175; +INSERT INTO `gossip_menu` (`MenuID`, `TextID`) VALUES +(7175, 8454), +(7175, 8455); +DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 14) AND (`SourceGroup` IN (7175)); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `Comment`) VALUES +(14, 7175, 8455, 0, 0, 5, 0, 529, 240, 0, 0, 'Player for which gossip text is shown has at least reputation Friendly, Honored, Revered, Exalted to faction 529'); + +DELETE FROM `gossip_menu_option` WHERE `MenuID` = 7175; +INSERT INTO `gossip_menu_option` (`MenuID`, `OptionID`, `OptionIcon`, `OptionText`, `OptionBroadcastTextID`, `OptionType`, `OptionNpcFlag`, `ActionMenuID`, `ActionPoiID`, `BoxCoded`, `BoxMoney`, `BoxText`, `BoxBroadcastTextID`, `VerifiedBuild`) VALUES +(7175, 0, 0, 'I am diseased. Please cure me, medic.', 12154, 1, 1, 0, 0, 0, 0, NULL, 0, 0); + +DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 15) AND (`SourceGroup` IN (7175)); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `Comment`) VALUES +(15, 7175, 0, 0, 0, 1, 0, 12541, 0, 0, 0, 'Player for which gossip text is shown has aura of spell Ghoul Rot (Ghoul Rot12541), effect EFFECT_0'), +(15, 7175, 0, 0, 1, 1, 0, 3427, 0, 0, 0, 'Player for which gossip text is shown has aura of spell Infected Wound (3427), effect EFFECT_0'), +(15, 7175, 0, 0, 2, 1, 0, 16449, 0, 0, 0, 'Player for which gossip text is shown has aura of spell Maggot Slime (16449), effect EFFECT_0'); + +-- Argent Medic smart ai +SET @ENTRY := 16284; +UPDATE `creature_template` SET `AIName` = 'SmartAI', `ScriptName` = '' WHERE `entry` = @ENTRY; +DELETE FROM `smart_scripts` WHERE `source_type` = 0 AND `entryOrGuid` = @ENTRY; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(@ENTRY, 0, 0, 0, 2, 0, 100, 1, 0, 15, 0, 0, 25, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Argent Medic - Self: Flee for assist'), +(@ENTRY, 0, 1, 0, 25, 0, 100, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Argent Medic - On reset - Set event phase to phase 1'), +(@ENTRY, 0, 2, 0, 62, 0, 100, 512, 7175, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Player - On gossip action 0 from menu 7175 selected - Gossip player: Close gossip'), +(@ENTRY, 0, 3, 4, 62, 1, 100, 512, 7175, 0, 0, 0, 22, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Player - On gossip action 0 from menu 7175 selected - Set event phase to phase 2'), +(@ENTRY, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 11, 28133, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Player - On gossip action 0 from menu 7175 selected - Self: Cast spell Cure Disease (28133) on Gossip player'), +(@ENTRY, 0, 5, 0, 31, 0, 100, 0, 28133, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Argent Medic - On spell Cure Disease (28133) hit a target - Set event phase to phase 1'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 22 AND `SourceEntry` = 16284 AND `SourceId` = 0; + diff --git a/data/sql/updates/db_world/2024_07_04_03.sql b/data/sql/updates/db_world/2024_07_04_03.sql new file mode 100644 index 000000000..1ef76fb66 --- /dev/null +++ b/data/sql/updates/db_world/2024_07_04_03.sql @@ -0,0 +1,14 @@ +-- DB update 2024_07_04_02 -> 2024_07_04_03 +-- +-- Razuvious +DELETE FROM `creature_text` WHERE `CreatureID` = 16061 AND `GroupID` IN (4, 5); +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(16061, 4, 0, 'Pathetic...', 12, 0, 100, 5, 0, 0, 27865, 0, 'Razuvious SAY_PATHETIC'), +(16061, 5, 0, 'Start doing something before I replace that target dummy with you and begin a warm up session of my own!', 12, 0, 100, 5, 0, 0, 13136, 0, 'Razuvious SAY_TARGET_DUMMY'); + +-- Death Knight Understudy +DELETE FROM `creature_text` WHERE `CreatureID` = 16803; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(16803, 0, 0, 'Sir, student requests that you beat him for his lack of understanding!', 12, 0, 100, 1, 0, 0, 13140, 0, 'Death Knight Understudy SAY_BEAT_ME'), +(16803, 0, 1, 'I am unworthy, master!', 12, 0, 100, 1, 0, 0, 13138, 0, 'Death Knight Understudy SAY_UNWORTHY'), +(16803, 0, 2, 'Student is worthless, master! Student apologizes for his deficiency!', 12, 0, 100, 1, 0, 0, 13137, 0, 'Death Knight Understudy SAY_WORTHLESS'); diff --git a/data/sql/updates/db_world/2024_07_04_04.sql b/data/sql/updates/db_world/2024_07_04_04.sql new file mode 100644 index 000000000..aded22c2c --- /dev/null +++ b/data/sql/updates/db_world/2024_07_04_04.sql @@ -0,0 +1,15 @@ +-- DB update 2024_07_04_03 -> 2024_07_04_04 +-- +DELETE FROM `waypoint_data` WHERE `id` IN (2357601, 2357602, 2357603); +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(2357601, 1, -52.642, 1419.357, 27.31, NULL, 0, 1, 0, 100, 0), +(2357602, 1, -69.908, 1419.721, 27.31, NULL, 0, 1, 0, 100, 0), +(2357602, 2, -79.929, 1395.958, 27.31, NULL, 0, 1, 0, 100, 0), +(2357602, 3, -80.072, 1374.555, 40.87, NULL, 0, 1, 0, 100, 0), +(2357603, 1, -80.072, 1314.398, 40.87, NULL, 0, 1, 0, 100, 0), +(2357603, 2, -80.072, 1295.775, 48.60, NULL, 0, 1, 0, 100, 0); + +DELETE FROM `creature_text` WHERE `CreatureID` = 23576 AND `GroupID` IN (14, 15); +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(23576, 14, 0, 'Mua-ha-ha!', 14, 0, 100, 0, 0, 0, 22145, 1, 'Nalorakk - RUN AWAY'), +(23576, 15, 0, '%s transforms into a bear!', 16, 0, 100, 0, 0, 0, 24263, 1, 'Nalorakk - EMOTE BEAR'); diff --git a/data/sql/updates/db_world/2024_07_04_05.sql b/data/sql/updates/db_world/2024_07_04_05.sql new file mode 100644 index 000000000..f34250d85 --- /dev/null +++ b/data/sql/updates/db_world/2024_07_04_05.sql @@ -0,0 +1,11 @@ +-- DB update 2024_07_04_04 -> 2024_07_04_05 +-- Shattrath Daily Normal/Heroic holograms +UPDATE `creature_template` SET `ScriptName` = 'npc_shattrath_daily_quest' WHERE `entry` IN (24410,24854); + +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 24369; +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24369); +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 +(24369, 0, 0, 1, 1, 0, 100, 1, 0, 0, 0, 0, 0, 0, 223, 1, 0, 0, 0, 0, 0, 10, 79464, 24854, 0, 0, 0, 0, 0, 0, 'Wind Trader Zhareem - Out of Combat - Do Action ID 1 (No Repeat)'), +(24369, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 223, 1, 0, 0, 0, 0, 0, 10, 79462, 24410, 0, 0, 0, 0, 0, 0, 'Wind Trader Zhareem - Out of Combat - Do Action ID 1 (No Repeat)'), +(24369, 0, 2, 3, 101, 0, 100, 0, 1, 30, 60000, 60000, 60000, 0, 223, 1, 0, 0, 0, 0, 0, 10, 79464, 24854, 0, 0, 0, 0, 0, 0, 'Wind Trader Zhareem - On 1 or More Players in Range - Do Action ID 1'), +(24369, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 223, 1, 0, 0, 0, 0, 0, 10, 79462, 24410, 0, 0, 0, 0, 0, 0, 'Wind Trader Zhareem - On 1 or More Players in Range - Do Action ID 1'); diff --git a/data/sql/updates/db_world/2024_07_04_06.sql b/data/sql/updates/db_world/2024_07_04_06.sql new file mode 100644 index 000000000..c67e8bc1e --- /dev/null +++ b/data/sql/updates/db_world/2024_07_04_06.sql @@ -0,0 +1,5 @@ +-- DB update 2024_07_04_05 -> 2024_07_04_06 +-- +DELETE FROM `spell_custom_attr` WHERE `spell_id` = 38510; +INSERT INTO `spell_custom_attr` (`spell_id`, `attributes`) VALUES +(38510, 2147483648); diff --git a/data/sql/updates/db_world/2024_07_05_00.sql b/data/sql/updates/db_world/2024_07_05_00.sql new file mode 100644 index 000000000..b917c5e87 --- /dev/null +++ b/data/sql/updates/db_world/2024_07_05_00.sql @@ -0,0 +1,5 @@ +-- DB update 2024_07_04_06 -> 2024_07_05_00 +-- +DELETE FROM `spell_script_names` WHERE `spell_id` = 38929; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(38929, 'spell_item_fel_mana_potion'); diff --git a/data/sql/updates/db_world/2024_07_05_01.sql b/data/sql/updates/db_world/2024_07_05_01.sql new file mode 100644 index 000000000..a05420758 --- /dev/null +++ b/data/sql/updates/db_world/2024_07_05_01.sql @@ -0,0 +1,26 @@ +-- DB update 2024_07_05_00 -> 2024_07_05_01 +-- +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 1367 AND `source_type` = 0 AND `id` = 1; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 1367 AND `source_type` = 0 AND `id` = 3; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 1367 AND `source_type` = 0 AND `id` = 5; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 1368 AND `source_type` = 0 AND `id` = 1; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 1368 AND `source_type` = 0 AND `id` = 3; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 1371 AND `source_type` = 0 AND `id` = 2; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 1371 AND `source_type` = 0 AND `id` = 4; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 1414 AND `source_type` = 0 AND `id` = 4; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 1415 AND `source_type` = 0 AND `id` = 3; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 2470 AND `source_type` = 0 AND `id` = 0; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 137300 AND `source_type` = 9 AND `id` = 20; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 137300 AND `source_type` = 9 AND `id` = 19; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 1043900 AND `source_type` = 9 AND `id` = 2; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 2129100 AND `source_type` = 9 AND `id` = 1; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 2129100 AND `source_type` = 9 AND `id` = 13; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 2711300 AND `source_type` = 9 AND `id` = 1; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 2711300 AND `source_type` = 9 AND `id` = 3; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 2711400 AND `source_type` = 9 AND `id` = 1; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 2711400 AND `source_type` = 9 AND `id` = 3; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 2711500 AND `source_type` = 9 AND `id` = 1; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 2711500 AND `source_type` = 9 AND `id` = 3; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 2731600 AND `source_type` = 9 AND `id` = 2; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 2731600 AND `source_type` = 9 AND `id` = 3; +UPDATE `smart_scripts` SET `target_type` = 8 WHERE `entryorguid` = 3019000 AND `source_type` = 9 AND `id` = 13; diff --git a/data/sql/updates/db_world/2024_07_05_02.sql b/data/sql/updates/db_world/2024_07_05_02.sql new file mode 100644 index 000000000..2b8ab129c --- /dev/null +++ b/data/sql/updates/db_world/2024_07_05_02.sql @@ -0,0 +1,41 @@ +-- DB update 2024_07_05_01 -> 2024_07_05_02 +-- +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 18870); +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 +(18870, 0, 0, 0, 25, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - On Reset - Set Event Phase 0'), +(18870, 0, 1, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 34302, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - On Respawn - Cast \'Coalesce\''), +(18870, 0, 2, 0, 4, 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, 'Voidshrieker - On Aggro - Set Event Phase 1'), +(18870, 0, 3, 4, 8, 1, 100, 0, 0, 2, 0, 0, 0, 0, 11, 34336, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - On Spellhit \'Holy\' - Cast \'Damage Reduction: Holy\' (Phase 1)'), +(18870, 0, 4, 5, 61, 1, 100, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - On Spellhit \'Holy\' - Say Line 1 (Phase 1)'), +(18870, 0, 5, 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, 'Voidshrieker - On Spellhit \'Holy\' - Set Event Phase 2 (Phase 1)'), +(18870, 0, 6, 7, 8, 1, 100, 0, 0, 4, 0, 0, 0, 0, 11, 34333, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - On Spellhit \'Fire\' - Cast \'Damage Reduction: Fire\' (Phase 1)'), +(18870, 0, 7, 8, 61, 1, 100, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - On Spellhit \'Fire\' - Say Line 2 (Phase 1)'), +(18870, 0, 8, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - On Spellhit \'Fire\' - Set Event Phase 3 (Phase 1)'), +(18870, 0, 9, 10, 8, 1, 100, 0, 0, 8, 0, 0, 0, 0, 11, 34335, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - On Spellhit \'Nature\' - Cast \'Damage Reduction: Nature\' (Phase 1)'), +(18870, 0, 10, 11, 61, 1, 100, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - On Spellhit \'Nature\' - Say Line 3 (Phase 1)'), +(18870, 0, 11, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - On Spellhit \'Nature\' - Set Event Phase 4 (Phase 1)'), +(18870, 0, 12, 13, 8, 1, 100, 0, 0, 16, 0, 0, 0, 0, 11, 34334, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - On Spellhit \'Frost\' - Cast \'Damage Reduction: Frost\' (Phase 1)'), +(18870, 0, 13, 14, 61, 1, 100, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - On Spellhit \'Frost\' - Say Line 4 (Phase 1)'), +(18870, 0, 14, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 5, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - On Spellhit \'Frost\' - Set Event Phase 5 (Phase 1)'), +(18870, 0, 15, 16, 8, 1, 100, 0, 0, 32, 0, 0, 0, 0, 11, 34338, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - On Spellhit \'Shadow\' - Cast \'Damage Reduction: Shadow\' (Phase 1)'), +(18870, 0, 16, 17, 61, 1, 100, 0, 0, 0, 0, 0, 0, 0, 1, 5, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - On Spellhit \'Shadow\' - Say Line 5 (Phase 1)'), +(18870, 0, 17, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 6, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - On Spellhit \'Shadow\' - Set Event Phase 6 (Phase 1)'), +(18870, 0, 18, 19, 8, 1, 100, 0, 0, 64, 0, 0, 0, 0, 11, 34331, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - On Spellhit \'Arcane\' - Cast \'Damage Reduction: Arcane\' (Phase 1)'), +(18870, 0, 19, 20, 61, 1, 100, 0, 0, 0, 0, 0, 0, 0, 1, 6, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - On Spellhit \'Arcane\' - Say Line 6 (Phase 1)'), +(18870, 0, 20, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - On Spellhit \'Arcane\' - Set Event Phase 7 (Phase 1)'), +(18870, 0, 21, 0, 106, 0, 100, 0, 9000, 13000, 14000, 18000, 0, 8, 11, 22884, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - On Hostile in Range - Cast \'Psychic Scream\''), +(18870, 0, 22, 0, 0, 33, 100, 0, 0, 1000, 3000, 3500, 0, 0, 11, 12471, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - In Combat - Cast \'Shadow Bolt\' (Phases 1 & 6)'), +(18870, 0, 23, 0, 0, 2, 100, 0, 0, 1000, 2500, 3000, 0, 0, 11, 15498, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - In Combat - Cast \'Holy Smite\' (Phase 2)'), +(18870, 0, 24, 0, 0, 4, 100, 0, 0, 1000, 3000, 3500, 0, 0, 11, 14034, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - In Combat - Cast \'Fireball\' (Phase 3)'), +(18870, 0, 25, 0, 0, 8, 100, 0, 0, 1000, 3000, 3500, 0, 0, 11, 12167, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - In Combat - Cast \'Lightning Bolt\' (Phase 4)'), +(18870, 0, 26, 0, 0, 16, 100, 0, 0, 1000, 3000, 3500, 0, 0, 11, 15497, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - In Combat - Cast \'Frostbolt\' (Phase 5)'), +(18870, 0, 27, 0, 0, 64, 100, 0, 0, 1000, 5000, 6000, 0, 0, 11, 38204, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Voidshrieker - In Combat - Cast \'Arcane Bolt\' (Phase 7)'); + +DELETE FROM `creature_text` WHERE (`CreatureID` = 18870); +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(18870, 1, 0, '%s absorbs the holy energy of the attack.', 16, 0, 0, 0, 0, 0, 17110, 0, 'Voidshrieker'), +(18870, 2, 0, '%s absorbs the fire energy of the attack.', 16, 0, 0, 0, 0, 0, 17105, 0, 'Voidshrieker'), +(18870, 3, 0, '%s absorbs the nature energy of the attack.', 16, 0, 0, 0, 0, 0, 17107, 0, 'Voidshrieker'), +(18870, 4, 0, '%s absorbs the frost energy of the attack.', 16, 0, 0, 0, 0, 0, 17106, 0, 'Voidshrieker'), +(18870, 5, 0, '%s absorbs the shadow energy of the attack.', 16, 0, 0, 0, 0, 0, 17108, 0, 'Voidshrieker'), +(18870, 6, 0, '%s absorbs the arcane energy of the attack.', 16, 0, 0, 0, 0, 0, 17109, 0, 'Voidshrieker'); diff --git a/data/sql/updates/db_world/2024_07_06_00.sql b/data/sql/updates/db_world/2024_07_06_00.sql new file mode 100644 index 000000000..3b65178a3 --- /dev/null +++ b/data/sql/updates/db_world/2024_07_06_00.sql @@ -0,0 +1,10 @@ +-- DB update 2024_07_05_02 -> 2024_07_06_00 +-- +UPDATE `conditions` SET `ConditionTypeOrReference` = 8 WHERE `SourceGroup` = 8234 AND `SourceTypeOrReferenceId` = 15 AND `ConditionTypeOrReference` = 9; + +DELETE FROM `gossip_menu_option` WHERE (`MenuID` = 8234); +INSERT INTO `gossip_menu_option` (`MenuID`, `OptionID`, `OptionIcon`, `OptionText`, `OptionBroadcastTextID`, `OptionType`, `OptionNpcFlag`, `ActionMenuID`, `ActionPoiID`, `BoxCoded`, `BoxMoney`, `BoxText`, `BoxBroadcastTextID`, `VerifiedBuild`) VALUES +(8234, 0, 0, 'I seem to have misplaced my ring.', 21813, 1, 1, 0, 0, 0, 0, '', 0, 55056), +(8234, 1, 0, 'I seem to have misplaced my ring.', 21813, 1, 1, 0, 0, 0, 0, '', 0, 55056), +(8234, 2, 0, 'I seem to have misplaced my ring.', 21813, 1, 1, 0, 0, 0, 0, '', 0, 55056), +(8234, 3, 0, 'I seem to have misplaced my ring.', 21813, 1, 1, 0, 0, 0, 0, '', 0, 55056); diff --git a/data/sql/updates/db_world/2024_07_06_01.sql b/data/sql/updates/db_world/2024_07_06_01.sql new file mode 100644 index 000000000..1fd815d2d --- /dev/null +++ b/data/sql/updates/db_world/2024_07_06_01.sql @@ -0,0 +1,18 @@ +-- DB update 2024_07_06_00 -> 2024_07_06_01 +-- +DELETE FROM `creature_text` WHERE (`CreatureID` = 6240); +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(6240, 0, 0, '%s is demoralized and runs!', 16, 0, 100, 0, 0, 0, 2356, 0, 'Affray Challenger'); + +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 6240; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 6240); +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 +(6240, 0, 1, 0, 61, 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, 'Affray Challenger - On Spellhit \'Demoralizing Shout\' - Emote'), +(6240, 0, 2, 1, 8, 0, 100, 0, 1160, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Affray Challenger - On Spellhit \'Demoralizing Shout\' - Flee For Assist'), +(6240, 0, 3, 1, 8, 0, 100, 0, 6190, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Affray Challenger - On Spellhit \'Demoralizing Shout\' - Flee For Assist'), +(6240, 0, 4, 1, 8, 0, 100, 0, 11554, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Affray Challenger - On Spellhit \'Demoralizing Shout\' - Flee For Assist'), +(6240, 0, 5, 1, 8, 0, 100, 0, 11555, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Affray Challenger - On Spellhit \'Demoralizing Shout\' - Flee For Assist'), +(6240, 0, 6, 1, 8, 0, 100, 0, 11556, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Affray Challenger - On Spellhit \'Demoralizing Shout\' - Flee For Assist'), +(6240, 0, 7, 1, 8, 0, 100, 0, 25202, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Affray Challenger - On Spellhit \'Demoralizing Shout\' - Flee For Assist'), +(6240, 0, 8, 1, 8, 0, 100, 0, 25203, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Affray Challenger - On Spellhit \'Demoralizing Shout\' - Flee For Assist'); diff --git a/data/sql/updates/db_world/2024_07_06_02.sql b/data/sql/updates/db_world/2024_07_06_02.sql new file mode 100644 index 000000000..1c568b645 --- /dev/null +++ b/data/sql/updates/db_world/2024_07_06_02.sql @@ -0,0 +1,3 @@ +-- DB update 2024_07_06_01 -> 2024_07_06_02 +-- +DELETE FROM `creature_loot_template` WHERE `Item` = 21314; diff --git a/data/sql/updates/db_world/2024_07_06_03.sql b/data/sql/updates/db_world/2024_07_06_03.sql new file mode 100644 index 000000000..02801d8b2 --- /dev/null +++ b/data/sql/updates/db_world/2024_07_06_03.sql @@ -0,0 +1,5 @@ +-- DB update 2024_07_06_02 -> 2024_07_06_03 +-- +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 23383) AND (`source_type` = 0) AND (`id` IN (7)); +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 +(23383, 0, 7, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Skyguard Prisoner - On Respawn - Set Reactstate Passive'); diff --git a/data/sql/updates/db_world/2024_07_06_04.sql b/data/sql/updates/db_world/2024_07_06_04.sql new file mode 100644 index 000000000..c6fe8b15d --- /dev/null +++ b/data/sql/updates/db_world/2024_07_06_04.sql @@ -0,0 +1,3 @@ +-- DB update 2024_07_06_03 -> 2024_07_06_04 +-- RequiredMinRepValue was set to 1 +UPDATE `quest_template_addon` SET `RequiredMinRepValue` = 0 WHERE (`ID` IN (10412, 10414, 10415, 10325, 10326, 10327)); diff --git a/data/sql/updates/db_world/2024_07_06_05.sql b/data/sql/updates/db_world/2024_07_06_05.sql new file mode 100644 index 000000000..9f83fb107 --- /dev/null +++ b/data/sql/updates/db_world/2024_07_06_05.sql @@ -0,0 +1,5 @@ +-- DB update 2024_07_06_04 -> 2024_07_06_05 +-- +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 3395) 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 +(3395, 0, 0, 0, 1, 0, 100, 1, 4000, 4000, 0, 0, 0, 0, 53, 0, 3395, 0, 0, 600000, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Verog the Dervish - Out of Combat - Start Waypoint Movement (No Repeat)'); diff --git a/data/sql/updates/db_world/2024_07_06_06.sql b/data/sql/updates/db_world/2024_07_06_06.sql new file mode 100644 index 000000000..3fd7d1a0c --- /dev/null +++ b/data/sql/updates/db_world/2024_07_06_06.sql @@ -0,0 +1,11 @@ +-- DB update 2024_07_06_05 -> 2024_07_06_06 +-- +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 18945) AND (`source_type` = 0) AND (`id` IN (4, 5, 6)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(18945, 0, 4, 0, 11, 0, 100, 512, 0, 0, 0, 0, 0, 0, 80, 1894500, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Pit Commander - On Respawn - Run Script'), +(18945, 0, 5, 0, 21, 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, 'Pit Commander - On Reached Home - Set Event Phase'); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 1894500); +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 +(1894500, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 51347, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Pit Commander - Actionlist - Cast \'Teleport Visual Only\''), +(1894500, 9, 1, 0, 0, 0, 100, 0, 4000, 4000, 0, 0, 0, 0, 53, 0, 18945, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Pit Commander - Actionlist - Start Waypoint Path 18945'); diff --git a/data/sql/updates/db_world/2024_07_06_07.sql b/data/sql/updates/db_world/2024_07_06_07.sql new file mode 100644 index 000000000..e3f324cda --- /dev/null +++ b/data/sql/updates/db_world/2024_07_06_07.sql @@ -0,0 +1,18 @@ +-- DB update 2024_07_06_06 -> 2024_07_06_07 +-- +DELETE FROM `creature_text` WHERE (`CreatureID` = 22484); +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(22484, 0, 0, '%s gathers the warp chaser\'s blood.', 16, 0, 100, 0, 0, 0, 20371, 0, 'Zeppit - Gather blood'); + +UPDATE `smart_scripts` SET`target_param2` = 25 WHERE `entryorguid`=18884 AND `source_type`=0 AND `id`=3; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 22484); +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 +(22484, 0, 0, 0, 38, 0, 100, 0, 1, 1, 3000, 3000, 0, 0, 69, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Zeppit - On Data Set 1 1 - Move To Invoker'), +(22484, 0, 1, 0, 34, 0, 100, 0, 8, 1, 0, 0, 0, 0, 80, 2248400, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Zeppit - On Reached Point 1 - Run Script'); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 2248400); +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 +(2248400, 9, 0, 0, 0, 0, 100, 0, 1500, 1500, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Zeppit - Actionlist - Say Line 0'), +(2248400, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 39244, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 'Zeppit - Actionlist - Cast \'Gather Warp Chaser Blood\''), +(2248400, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 'Zeppit - Actionlist - Start Follow Owner Or Summoner'); diff --git a/data/sql/updates/db_world/2024_07_06_08.sql b/data/sql/updates/db_world/2024_07_06_08.sql new file mode 100644 index 000000000..1a7faa883 --- /dev/null +++ b/data/sql/updates/db_world/2024_07_06_08.sql @@ -0,0 +1,3 @@ +-- DB update 2024_07_06_07 -> 2024_07_06_08 +-- +UPDATE `creature_template` SET `detection_range` = 55 WHERE `entry` = 22849; diff --git a/data/sql/updates/db_world/2024_07_06_09.sql b/data/sql/updates/db_world/2024_07_06_09.sql new file mode 100644 index 000000000..d364f1302 --- /dev/null +++ b/data/sql/updates/db_world/2024_07_06_09.sql @@ -0,0 +1,3 @@ +-- DB update 2024_07_06_08 -> 2024_07_06_09 +-- +UPDATE `creature_template` SET `mechanic_immune_mask` = `mechanic_immune_mask`|33554432 WHERE `entry` = 23394; diff --git a/data/sql/updates/db_world/2024_07_06_10.sql b/data/sql/updates/db_world/2024_07_06_10.sql new file mode 100644 index 000000000..903d2adcd --- /dev/null +++ b/data/sql/updates/db_world/2024_07_06_10.sql @@ -0,0 +1,3 @@ +-- DB update 2024_07_06_09 -> 2024_07_06_10 +-- +UPDATE `quest_template` SET `AllowableRaces` = 690 WHERE `ID` = 9846; diff --git a/data/sql/updates/db_world/2024_07_06_11.sql b/data/sql/updates/db_world/2024_07_06_11.sql new file mode 100644 index 000000000..8a74db700 --- /dev/null +++ b/data/sql/updates/db_world/2024_07_06_11.sql @@ -0,0 +1,6 @@ +-- DB update 2024_07_06_10 -> 2024_07_06_11 +DELETE FROM `spell_script_names` WHERE `spell_id` = 31944; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES (31944, 'spell_doomfire'); + +DELETE FROM `spell_custom_attr` WHERE `spell_id` = 31944; +INSERT INTO `spell_custom_attr` (`spell_id`, `attributes`) VALUES (31944, 4194304); diff --git a/src/common/Configuration/Config.cpp b/src/common/Configuration/Config.cpp index 742777b18..d8665593c 100644 --- a/src/common/Configuration/Config.cpp +++ b/src/common/Configuration/Config.cpp @@ -35,6 +35,14 @@ namespace std::unordered_map _envVarCache; std::mutex _configLock; + std::vector _fatalConfigOptions = + { + { "RealmID" }, + { "LoginDatabaseInfo" }, + { "WorldDatabaseInfo" }, + { "CharacterDatabaseInfo" }, + }; + // Check system configs like *server.conf* bool IsAppConfig(std::string_view fileName) { @@ -388,6 +396,7 @@ T ConfigMgr::GetValueDefault(std::string const& name, T const& def, bool showLog std::string strValue; auto const& itr = _configOptions.find(name); + bool fatalConfig = false; bool notFound = itr == _configOptions.end(); auto envVarName = GetEnvVarName(name); Optional envVar = GetEnvFromCache(name, envVarName); @@ -406,7 +415,18 @@ T ConfigMgr::GetValueDefault(std::string const& name, T const& def, bool showLog { if (showLogs) { - LOG_ERROR("server.loading", "> Config: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.", + for (std::string s : _fatalConfigOptions) + if (s == name) + { + fatalConfig = true; + break; + } + + if (fatalConfig) + LOG_FATAL("server.loading", "> Config:\n\nFATAL ERROR: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable\n\nYour server cannot start without this option!", + name, _filename, name, Acore::ToString(def), envVarName); + else + LOG_WARN("server.loading", "> Config: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.", name, _filename, name, Acore::ToString(def), envVarName); } return def; @@ -435,6 +455,7 @@ template<> std::string ConfigMgr::GetValueDefault(std::string const& name, std::string const& def, bool showLogs /*= true*/) const { auto const& itr = _configOptions.find(name); + bool fatalConfig = false; bool notFound = itr == _configOptions.end(); auto envVarName = GetEnvVarName(name); Optional envVar = GetEnvFromCache(name, envVarName); @@ -453,7 +474,18 @@ std::string ConfigMgr::GetValueDefault(std::string const& name, std { if (showLogs) { - LOG_ERROR("server.loading", "> Config: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.", + for (std::string s : _fatalConfigOptions) + if (s == name) + { + fatalConfig = true; + break; + } + + if (fatalConfig) + LOG_FATAL("server.loading", "> Config:\n\nFATAL ERROR: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.\n\nYour server cannot start without this option!", + name, _filename, name, def, envVarName); + else + LOG_WARN("server.loading", "> Config: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.", name, _filename, name, def, envVarName); } diff --git a/src/common/Logging/enuminfo_LogCommon.cpp b/src/common/Logging/enuminfo_LogCommon.cpp index e1750cb3f..2e4265563 100644 --- a/src/common/Logging/enuminfo_LogCommon.cpp +++ b/src/common/Logging/enuminfo_LogCommon.cpp @@ -15,8 +15,8 @@ * with this program. If not, see . */ -#include "Define.h" #include "LogCommon.h" +#include "Define.h" #include "SmartEnum.h" #include diff --git a/src/server/database/Database/DatabaseLoader.cpp b/src/server/database/Database/DatabaseLoader.cpp index a9f0bfcb8..2bee9d683 100644 --- a/src/server/database/Database/DatabaseLoader.cpp +++ b/src/server/database/Database/DatabaseLoader.cpp @@ -154,7 +154,7 @@ DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool& pool, std::st bool DatabaseLoader::Load() { if (!_updateFlags) - LOG_INFO("sql.updates", "Automatic database updates are disabled for all databases!"); + LOG_WARN("sql.updates", "> AUTOUPDATER: Automatic database updates are disabled for all databases in the config! This is not recommended!"); if (!OpenDatabases()) return false; diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h index 865415f59..2f9bba321 100644 --- a/src/server/game/AI/CoreAI/UnitAI.h +++ b/src/server/game/AI/CoreAI/UnitAI.h @@ -23,6 +23,17 @@ #include "Unit.h" #include +#define CAST_AI(a, b) (dynamic_cast(b)) +#define ENSURE_AI(a,b) (EnsureAI(b)) + +template +T* EnsureAI(U* ai) +{ + T* cast_ai = dynamic_cast(ai); + ASSERT(cast_ai); + return cast_ai; +} + class Player; class Quest; class Unit; diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h index be04450d0..f6ed31486 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h @@ -25,8 +25,6 @@ #include "InstanceScript.h" #include "TaskScheduler.h" -#define CAST_AI(a, b) (dynamic_cast(b)) - typedef std::list ObjectList; class InstanceScript; diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index d126a9cfc..d3ec5eb51 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -962,9 +962,9 @@ uint32 SmartAI::GetData(uint32 /*id*/) const return 0; } -void SmartAI::SetData(uint32 id, uint32 value) +void SmartAI::SetData(uint32 id, uint32 value, Unit* invoker) { - GetScript()->ProcessEventsFor(SMART_EVENT_DATA_SET, nullptr, id, value); + GetScript()->ProcessEventsFor(SMART_EVENT_DATA_SET, invoker, id, value); } void SmartAI::SetGUID(ObjectGuid /*guid*/, int32 /*id*/) @@ -1232,9 +1232,9 @@ void SmartGameObjectAI::Destroyed(Player* player, uint32 eventId) GetScript()->ProcessEventsFor(SMART_EVENT_DEATH, player, eventId, 0, false, nullptr, me); } -void SmartGameObjectAI::SetData(uint32 id, uint32 value) +void SmartGameObjectAI::SetData(uint32 id, uint32 value, Unit* invoker) { - GetScript()->ProcessEventsFor(SMART_EVENT_DATA_SET, nullptr, id, value); + GetScript()->ProcessEventsFor(SMART_EVENT_DATA_SET, invoker, id, value); } void SmartGameObjectAI::SetScript9(SmartScriptHolder& e, uint32 entry, Unit* invoker) diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h index acb52d904..0311590fe 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.h +++ b/src/server/game/AI/SmartScripts/SmartAI.h @@ -159,7 +159,8 @@ public: uint32 GetData(uint32 id = 0) const override; // Used in scripts to share variables - void SetData(uint32 id, uint32 value) override; + void SetData(uint32 id, uint32 value) override { SetData(id, value, nullptr); } + void SetData(uint32 id, uint32 value, Unit* invoker); // Used in scripts to share variables void SetGUID(ObjectGuid guid, int32 id = 0) override; @@ -272,7 +273,8 @@ public: bool QuestAccept(Player* player, Quest const* quest) override; bool QuestReward(Player* player, Quest const* quest, uint32 opt) override; void Destroyed(Player* player, uint32 eventId) override; - void SetData(uint32 id, uint32 value) override; + void SetData(uint32 id, uint32 value) override { SetData(id, value, nullptr); } + void SetData(uint32 id, uint32 value, Unit* invoker); void SetScript9(SmartScriptHolder& e, uint32 entry, Unit* invoker); void OnGameEvent(bool start, uint16 eventId) override; void OnStateChanged(uint32 state, Unit* unit) override; diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index cabedbe4a..7930317bf 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -63,7 +63,46 @@ SmartScript::SmartScript() SmartScript::~SmartScript() { +} +bool SmartScript::IsSmart(Creature* c, bool silent) const +{ + if (!c) + return false; + + bool smart = true; + if (!dynamic_cast(c->AI())) + smart = false; + + if (!smart && !silent) + LOG_ERROR("sql.sql", "SmartScript: Action target Creature(entry: {}) is not using SmartAI, action skipped to prevent crash.", c ? c->GetEntry() : (me ? me->GetEntry() : 0)); + + return smart; +} + +bool SmartScript::IsSmart(GameObject* g, bool silent) const +{ + if (!g) + return false; + + bool smart = true; + if (!dynamic_cast(g->AI())) + smart = false; + + if (!smart && !silent) + LOG_ERROR("sql.sql", "SmartScript: Action target GameObject(entry: {}) is not using SmartGameObjectAI, action skipped to prevent crash.", g ? g->GetEntry() : (go ? go->GetEntry() : 0)); + + return smart; +} + +bool SmartScript::IsSmart(bool silent) const +{ + if (me) + return IsSmart(me, silent); + if (go) + return IsSmart(go, silent); + + return false; } void SmartScript::OnReset() @@ -1272,22 +1311,29 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u { for (WorldObject* target : targets) { - Milliseconds despawnDelay(e.action.forceDespawn.delay); + if (e.action.forceDespawn.removeObjectFromWorld) + { + if (e.action.forceDespawn.delay || e.action.forceDespawn.forceRespawnTimer) + LOG_ERROR("sql.sql", "SmartScript: SMART_ACTION_FORCE_DESPAWN has removeObjectFromWorld set. delay and forceRespawnTimer ignored."); - // Wait at least one world update tick before despawn, so it doesn't break linked actions. - if (despawnDelay <= 0ms) - { - despawnDelay = 1ms; + if (Creature* creature = target->ToCreature()) + creature->AddObjectToRemoveList(); + else if (GameObject* go = target->ToGameObject()) + go->AddObjectToRemoveList(); } + else + { + Milliseconds despawnDelay(e.action.forceDespawn.delay); - Seconds forceRespawnTimer(e.action.forceDespawn.forceRespawnTimer); - if (Creature* creature = target->ToCreature()) - { - creature->DespawnOrUnsummon(despawnDelay, forceRespawnTimer); - } - else if (GameObject* go = target->ToGameObject()) - { - go->DespawnOrUnsummon(despawnDelay, forceRespawnTimer); + // Wait at least one world update tick before despawn, so it doesn't break linked actions. + if (despawnDelay <= 0ms) + despawnDelay = 1ms; + + Seconds forceRespawnTimer(e.action.forceDespawn.forceRespawnTimer); + if (Creature* creature = target->ToCreature()) + creature->DespawnOrUnsummon(despawnDelay, forceRespawnTimer); + else if (GameObject* go = target->ToGameObject()) + go->DespawnOrUnsummon(despawnDelay, forceRespawnTimer); } } @@ -1348,10 +1394,22 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u { for (WorldObject* target : targets) { - if (IsCreature(target)) - target->ToCreature()->AI()->SetData(e.action.setData.field, e.action.setData.data); - else if (IsGameObject(target)) - target->ToGameObject()->AI()->SetData(e.action.setData.field, e.action.setData.data); + if (Creature* cTarget = target->ToCreature()) + { + CreatureAI* ai = cTarget->AI(); + if (IsSmart(cTarget)) + ENSURE_AI(SmartAI, ai)->SetData(e.action.setData.field, e.action.setData.data, me); + else + ai->SetData(e.action.setData.field, e.action.setData.data); + } + else if (GameObject* oTarget = target->ToGameObject()) + { + GameObjectAI* ai = oTarget->AI(); + if (IsSmart(oTarget)) + ENSURE_AI(SmartGameObjectAI, ai)->SetData(e.action.setData.field, e.action.setData.data, me); + else + ai->SetData(e.action.setData.field, e.action.setData.data); + } } break; } @@ -1737,60 +1795,61 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u WorldObject* target = nullptr; - if (e.GetTargetType() == SMART_TARGET_RANDOM_POINT) + switch (e.GetTargetType()) { + case SMART_TARGET_POSITION: + { + G3D::Vector3 dest(e.target.x, e.target.y, e.target.z); + if (e.action.moveToPos.transport) + if (TransportBase* trans = me->GetDirectTransport()) + trans->CalculatePassengerPosition(dest.x, dest.y, dest.z); + + me->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, dest.x, dest.y, dest.z, true, true, + isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE, e.target.o); + + break; + } + case SMART_TARGET_RANDOM_POINT: if (me) { float range = (float)e.target.randomPoint.range; Position srcPos = { e.target.x, e.target.y, e.target.z, e.target.o }; Position randomPoint = me->GetRandomPoint(srcPos, range); me->GetMotionMaster()->MovePoint( - e.action.moveToPos.pointId, - randomPoint.m_positionX, - randomPoint.m_positionY, - randomPoint.m_positionZ, - true, - true, - isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE + e.action.moveToPos.pointId, + randomPoint.m_positionX, + randomPoint.m_positionY, + randomPoint.m_positionZ, + true, + true, + isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE ); + + break; } - - break; - } - - /*if (e.GetTargetType() == SMART_TARGET_CREATURE_RANGE || e.GetTargetType() == SMART_TARGET_CREATURE_GUID || - e.GetTargetType() == SMART_TARGET_CREATURE_DISTANCE || e.GetTargetType() == SMART_TARGET_GAMEOBJECT_RANGE || - e.GetTargetType() == SMART_TARGET_GAMEOBJECT_GUID || e.GetTargetType() == SMART_TARGET_GAMEOBJECT_DISTANCE || - e.GetTargetType() == SMART_TARGET_CLOSEST_CREATURE || e.GetTargetType() == SMART_TARGET_CLOSEST_GAMEOBJECT || - e.GetTargetType() == SMART_TARGET_OWNER_OR_SUMMONER || e.GetTargetType() == SMART_TARGET_ACTION_INVOKER || - e.GetTargetType() == SMART_TARGET_CLOSEST_ENEMY || e.GetTargetType() == SMART_TARGET_CLOSEST_FRIENDLY || - e.GetTargetType() == SMART_TARGET_SELF || e.GetTargetType() == SMART_TARGET_STORED)) */ - { - // we want to move to random element - if (!targets.empty()) - target = Acore::Containers::SelectRandomContainerElement(targets); - } - - if (!target) - { - G3D::Vector3 dest(e.target.x, e.target.y, e.target.z); - if (e.action.moveToPos.transport) - if (TransportBase* trans = me->GetDirectTransport()) - trans->CalculatePassengerPosition(dest.x, dest.y, dest.z); - - me->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, dest.x, dest.y, dest.z, true, true, - isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE, e.target.o); - } - else // Xinef: we can use dest.x, dest.y, dest.z to make offset - { - float x, y, z; - target->GetPosition(x, y, z); - if (e.action.moveToPos.ContactDistance > 0) + // Can use target floats as offset + default: { - target->GetNearPoint(me, x, y, z, e.action.moveToPos.ContactDistance, 0, target->GetAngle(me)); + // we want to move to random element + if (targets.empty()) + return; + else + target = Acore::Containers::SelectRandomContainerElement(targets); + + float x, y, z; + target->GetPosition(x, y, z); + + if (e.action.moveToPos.combatReach) + target->GetNearPoint(me, x, y, z, target->GetCombatReach() + e.action.moveToPos.ContactDistance, 0, target->GetAngle(me)); + else if (e.action.moveToPos.ContactDistance) + target->GetNearPoint(me, x, y, z, e.action.moveToPos.ContactDistance, 0, target->GetAngle(me)); + + me->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, x + e.target.x, y + e.target.y, z + e.target.z, true, true, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE); + + break; } - me->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, x + e.target.x, y + e.target.y, z + e.target.z, true, true, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE); } + break; } case SMART_ACTION_MOVE_TO_POS_TARGET: @@ -1966,7 +2025,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } else if (GameObject* go = target->ToGameObject()) { - if (IsSmartGO(go)) + if (IsSmart(go)) CAST_AI(SmartGameObjectAI, go->AI())->SetScript9(e, e.action.timedActionList.id, GetLastInvoker()); } } @@ -2053,7 +2112,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } else if (GameObject* go = target->ToGameObject()) { - if (IsSmartGO(go)) + if (IsSmart(go)) CAST_AI(SmartGameObjectAI, go->AI())->SetScript9(e, id, GetLastInvoker()); } } @@ -2077,7 +2136,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } else if (GameObject* go = target->ToGameObject()) { - if (IsSmartGO(go)) + if (IsSmart(go)) CAST_AI(SmartGameObjectAI, go->AI())->SetScript9(e, id, GetLastInvoker()); } } diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index b9ab57327..82ac3700d 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -76,6 +76,10 @@ public: void DoFindFriendlyMissingBuff(std::vector& creatures, float range, uint32 spellid) const; Unit* DoFindClosestFriendlyInRange(float range, bool playerOnly) const; + bool IsSmart(Creature* c, bool silent = false) const; + bool IsSmart(GameObject* g, bool silent = false) const; + bool IsSmart(bool silent = false) const; + void StoreTargetList(ObjectVector const& targets, uint32 id) { // insert or replace @@ -83,35 +87,6 @@ public: _storedTargets.emplace(id, ObjectGuidVector(targets)); } - bool IsSmart(Creature* c = nullptr) - { - bool smart = true; - if (c && c->GetAIName() != "SmartAI") - smart = false; - - if (!me || me->GetAIName() != "SmartAI") - smart = false; - - if (!smart) - LOG_ERROR("sql.sql", "SmartScript: Action target Creature(entry: {}) is not using SmartAI, action skipped to prevent crash.", c ? c->GetEntry() : (me ? me->GetEntry() : 0)); - - return smart; - } - - bool IsSmartGO(GameObject* g = nullptr) - { - bool smart = true; - if (g && g->GetAIName() != "SmartGameObjectAI") - smart = false; - - if (!go || go->GetAIName() != "SmartGameObjectAI") - smart = false; - if (!smart) - LOG_ERROR("sql.sql", "SmartScript: Action target GameObject(entry: {}) is not using SmartGameObjectAI, action skipped to prevent crash.", g ? g->GetEntry() : (go ? go->GetEntry() : 0)); - - return smart; - } - ObjectVector const* GetStoredTargetVector(uint32 id, WorldObject const& ref) const { auto itr = _storedTargets.find(id); diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 1f2c3ae9b..a3d759a6d 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -346,6 +346,7 @@ void SmartAIMgr::LoadSmartAIFromDB() case SMART_EVENT_TRANSPORT_ADDCREATURE: case SMART_EVENT_NEAR_PLAYERS: case SMART_EVENT_SUMMONED_UNIT_EVADE: + case SMART_EVENT_DATA_SET: return true; default: return false; diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 66d0deaa9..1d65711e3 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -978,6 +978,7 @@ struct SmartAction { uint32 delay; uint32 forceRespawnTimer; + SAIBool removeObjectFromWorld; } forceDespawn; struct @@ -1201,6 +1202,7 @@ struct SmartAction SAIBool transport; uint32 controlled; uint32 ContactDistance; + uint32 combatReach; } moveToPos; struct diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index 170782631..57836678c 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -33,6 +33,7 @@ #include "World.h" #include "WorldPacket.h" #include "WorldSession.h" +#include Player* ChatHandler::GetPlayer() const { @@ -888,3 +889,105 @@ int CliHandler::GetSessionDbLocaleIndex() const { return sObjectMgr->GetDBCLocaleIndex(); } + +bool AddonChannelCommandHandler::ParseCommands(std::string_view str) +{ + if (memcmp(str.data(), "AzerothCore\t", 12)) + return false; + char opcode = str[12]; + if (!opcode) // str[12] is opcode + return false; + if (!str[13] || !str[14] || !str[15] || !str[16]) // str[13] through str[16] is 4-character command counter + return false; + echo = str.substr(13); + + switch (opcode) + { + case 'p': // p Ping + SendAck(); + return true; + case 'h': // h Issue human-readable command + case 'i': // i Issue command + if (!str[17]) + return false; + humanReadable = (opcode == 'h'); + if (_ParseCommands(str.substr(17))) // actual command starts at str[17] + { + if (!hadAck) + SendAck(); + if (HasSentErrorMessage()) + SendFailed(); + else + SendOK(); + } + else + { + SendSysMessage(LANG_CMD_INVALID); + SendFailed(); + } + return true; + default: + return false; + } +} + +void AddonChannelCommandHandler::Send(std::string const& msg) +{ + WorldPacket data; + ChatHandler::BuildChatPacket(data, CHAT_MSG_WHISPER, LANG_ADDON, GetSession()->GetPlayer(), GetSession()->GetPlayer(), msg); + GetSession()->SendPacket(&data); +} + +void AddonChannelCommandHandler::SendAck() // a Command acknowledged, no body +{ + ASSERT(echo.size()); + std::string ack = "AzerothCore\ta"; + ack.resize(18); + memcpy(&ack[13], echo.data(), 4); + ack[17] = '\0'; + Send(ack); + hadAck = true; +} + +void AddonChannelCommandHandler::SendOK() // o Command OK, no body +{ + ASSERT(echo.size()); + std::string ok = "AzerothCore\to"; + ok.resize(18); + memcpy(&ok[13], echo.data(), 4); + ok[17] = '\0'; + Send(ok); +} + +void AddonChannelCommandHandler::SendFailed() // f Command failed, no body +{ + ASSERT(echo.size()); + std::string fail = "AzerothCore\tf"; + fail.resize(18); + memcpy(&fail[13], echo.data(), 4); + fail[17] = '\0'; + Send(fail); +} + +// m Command message, message in body +void AddonChannelCommandHandler::SendSysMessage(std::string_view str, bool escapeCharacters) +{ + ASSERT(echo.size()); + if (!hadAck) + SendAck(); + + std::string msg = "AzerothCore\tm"; + msg.append(echo.data(), 4); + std::string body(str); + if (escapeCharacters) + boost::replace_all(body, "|", "||"); + size_t pos, lastpos; + for (lastpos = 0, pos = body.find('\n', lastpos); pos != std::string::npos; lastpos = pos + 1, pos = body.find('\n', lastpos)) + { + std::string line(msg); + line.append(body, lastpos, pos - lastpos); + Send(line); + } + msg.append(body, lastpos, pos - lastpos); + Send(msg); +} diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h index d6f91bb86..c4873f2cc 100644 --- a/src/server/game/Chat/Chat.h +++ b/src/server/game/Chat/Chat.h @@ -168,4 +168,24 @@ private: Print* m_print; }; +class AC_GAME_API AddonChannelCommandHandler : public ChatHandler +{ + public: + using ChatHandler::ChatHandler; + bool ParseCommands(std::string_view str) override; + void SendSysMessage(std::string_view str, bool escapeCharacters) override; + using ChatHandler::SendSysMessage; + bool IsHumanReadable() const override { return humanReadable; } + + private: + void Send(std::string const& msg); + void SendAck(); + void SendOK(); + void SendFailed(); + + std::string echo; + bool hadAck = false; + bool humanReadable = false; +}; + #endif diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index 8b98e0b8b..805fcd06d 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -1054,10 +1054,10 @@ void ConditionMgr::LoadConditions(bool isReload) LootTemplates_Spell.ResetConditions(); LootTemplates_Player.ResetConditions(); - LOG_INFO("server.loading", "Re-Loading `gossip_menu` Table for Conditions!"); + LOG_INFO("server.loading", "Reloading `gossip_menu` Table for Conditions!"); sObjectMgr->LoadGossipMenu(); - LOG_INFO("server.loading", "Re-Loading `gossip_menu_option` Table for Conditions!"); + LOG_INFO("server.loading", "Reloading `gossip_menu_option` Table for Conditions!"); sObjectMgr->LoadGossipMenuItems(); sSpellMgr->UnloadSpellInfoImplicitTargetConditionLists(); } diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 98389c5c2..113199ead 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -170,7 +170,7 @@ DBCStorage sSpellFocusObjectStore(SpellFocusObjectfmt); DBCStorage sSpellRadiusStore(SpellRadiusfmt); DBCStorage sSpellRangeStore(SpellRangefmt); DBCStorage sSpellRuneCostStore(SpellRuneCostfmt); -DBCStorage sSpellShapeshiftStore(SpellShapeshiftfmt); +DBCStorage sSpellShapeshiftFormStore(SpellShapeshiftFormEntryfmt); DBCStorage sSpellVisualStore(SpellVisualfmt); DBCStorage sStableSlotPricesStore(StableSlotPricesfmt); DBCStorage sSummonPropertiesStore(SummonPropertiesfmt); @@ -375,7 +375,7 @@ void LoadDBCStores(const std::string& dataPath) LOAD_DBC(sSpellRadiusStore, "SpellRadius.dbc", "spellradius_dbc"); LOAD_DBC(sSpellRangeStore, "SpellRange.dbc", "spellrange_dbc"); LOAD_DBC(sSpellRuneCostStore, "SpellRuneCost.dbc", "spellrunecost_dbc"); - LOAD_DBC(sSpellShapeshiftStore, "SpellShapeshiftForm.dbc", "spellshapeshiftform_dbc"); + LOAD_DBC(sSpellShapeshiftFormStore, "SpellShapeshiftForm.dbc", "spellshapeshiftform_dbc"); LOAD_DBC(sSpellVisualStore, "SpellVisual.dbc", "spellvisual_dbc"); LOAD_DBC(sStableSlotPricesStore, "StableSlotPrices.dbc", "stableslotprices_dbc"); LOAD_DBC(sSummonPropertiesStore, "SummonProperties.dbc", "summonproperties_dbc"); diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index 20b9b0e29..5e93bce70 100644 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -139,7 +139,7 @@ extern DBCStorage sItemLimitCategoryStore; extern DBCStorage sItemRandomPropertiesStore; extern DBCStorage sItemRandomSuffixStore; extern DBCStorage sItemSetStore; -extern DBCStorage sLFGDungeonStore; +extern DBCStorage sLFGDungeonStore; extern DBCStorage sLiquidTypeStore; extern DBCStorage sLockStore; extern DBCStorage sMailTemplateStore; @@ -175,7 +175,7 @@ extern std::unordered_set sPetTalentSpells; extern DBCStorage sSpellRadiusStore; extern DBCStorage sSpellRangeStore; extern DBCStorage sSpellRuneCostStore; -extern DBCStorage sSpellShapeshiftStore; +extern DBCStorage sSpellShapeshiftFormStore; extern DBCStorage sSpellStore; extern DBCStorage sSpellVisualStore; extern DBCStorage sStableSlotPricesStore; diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 0db064434..44776dc46 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -2173,15 +2173,6 @@ bool GameObject::IsInRange(float x, float y, float z, float radius) const && dz < (info->maxZ * scale) + radius && dz > (info->minZ * scale) - radius; } -void GameObject::SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/, bool includeMargin, Player const* skipped_rcvr) const -{ - dist += GetObjectSize(); - if (includeMargin) - dist += VISIBILITY_COMPENSATION * 2.0f; // pussywizard: to ensure everyone receives all important packets - Acore::MessageDistDeliverer notifier(this, data, dist, false, skipped_rcvr); - Cell::VisitWorldObjects(this, notifier, dist); -} - void GameObject::EventInform(uint32 eventId) { if (!eventId) diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index ed47aa084..678052b14 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -289,8 +289,6 @@ public: void SendCustomAnim(uint32 anim); [[nodiscard]] bool IsInRange(float x, float y, float z, float radius) const; - void SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/, bool includeMargin = false, Player const* skipped_rcvr = nullptr) const override; // pussywizard! - void ModifyHealth(int32 change, Unit* attackerOrHealer = nullptr, uint32 spellId = 0); void SetDestructibleBuildingModifyState(bool allow) { m_allowModifyDestructibleBuilding = allow; } // sets GameObject type 33 destruction flags and optionally default health for that state diff --git a/src/server/game/Entities/Item/enuminfo_Item.cpp b/src/server/game/Entities/Item/enuminfo_Item.cpp index d43ff6470..a7b1ecc35 100644 --- a/src/server/game/Entities/Item/enuminfo_Item.cpp +++ b/src/server/game/Entities/Item/enuminfo_Item.cpp @@ -15,8 +15,8 @@ * with this program. If not, see . */ -#include "Define.h" #include "Item.h" +#include "Define.h" #include "SmartEnum.h" #include diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 5f505655d..e6b60ffca 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -2077,15 +2077,24 @@ void Unit::BuildHeartBeatMsg(WorldPacket* data) const BuildMovementPacket(data); } -void WorldObject::SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/, bool includeMargin, Player const* skipped_rcvr) const +void WorldObject::SendMessageToSet(WorldPacket const* data, bool self) const { - dist += GetObjectSize(); - if (includeMargin) - dist += VISIBILITY_COMPENSATION; // pussywizard: to ensure everyone receives all important packets - Acore::MessageDistDeliverer notifier(this, data, dist, false, skipped_rcvr); + if (IsInWorld()) + SendMessageToSetInRange(data, GetVisibilityRange(), self); +} + +void WorldObject::SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/) const +{ + Acore::MessageDistDeliverer notifier(this, data, dist); Cell::VisitWorldObjects(this, notifier, dist); } +void WorldObject::SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const +{ + Acore::MessageDistDeliverer notifier(this, data, GetVisibilityRange(), false, skipped_rcvr); + Cell::VisitWorldObjects(this, notifier, GetVisibilityRange()); +} + void WorldObject::SendObjectDeSpawnAnim(ObjectGuid guid) { WorldPacket data(SMSG_GAMEOBJECT_DESPAWN_ANIM, 8); diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index f9a9ac69c..6dd7f0d7f 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -479,9 +479,9 @@ public: virtual void CleanupsBeforeDelete(bool finalCleanup = true); // used in destructor or explicitly before mass creature delete to remove cross-references to already deleted units - virtual void SendMessageToSet(WorldPacket const* data, bool self) const { if (IsInWorld()) SendMessageToSetInRange(data, GetVisibilityRange(), self, true); } // pussywizard! - virtual void SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/, bool includeMargin = false, Player const* skipped_rcvr = nullptr) const; // pussywizard! - virtual void SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const { if (IsInWorld()) SendMessageToSetInRange(data, GetVisibilityRange(), false, true, skipped_rcvr); } // pussywizard! + virtual void SendMessageToSet(WorldPacket const* data, bool self) const; + virtual void SendMessageToSetInRange(WorldPacket const* data, float dist, bool self) const; + virtual void SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const; virtual uint8 getLevelForTarget(WorldObject const* /*target*/) const { return 1; } diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index a998afa57..0f77f0c97 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -394,7 +394,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c // Send fake summon spell cast - this is needed for correct cooldown application for spells // Example: 46584 - without this cooldown (which should be set always when pet is loaded) isn't set clientside /// @todo pets should be summoned from real cast instead of just faking it? - if (petInfo->CreatedBySpellId) + if (petInfo->CreatedBySpellId && spellInfo && (spellInfo->CategoryRecoveryTime > 0 || spellInfo->RecoveryTime > 0)) { WorldPacket data(SMSG_SPELL_GO, (8 + 8 + 4 + 4 + 2)); data << owner->GetPackGUID(); @@ -2499,11 +2499,6 @@ float Pet::GetNativeObjectScale() const { uint8 ctFamily = GetCreatureTemplate()->family; - // hackfix: Edge case where DBC scale values for DEVILSAUR pets make them too small. - // Therefore we take data from spirit beast instead. - if (ctFamily && ctFamily == CREATURE_FAMILY_DEVILSAUR) - ctFamily = CREATURE_FAMILY_SPIRIT_BEAST; - CreatureFamilyEntry const* creatureFamily = sCreatureFamilyStore.LookupEntry(ctFamily); if (creatureFamily && creatureFamily->minScale > 0.0f && getPetType() & HUNTER_PET) { @@ -2520,6 +2515,13 @@ float Pet::GetNativeObjectScale() const float scale = (creatureFamily->maxScale - creatureFamily->minScale) * scaleMod + creatureFamily->minScale; + scale = std::min(scale, creatureFamily->maxScale); + + if (CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.LookupEntry(GetNativeDisplayId())) + { + if (scale < 1.f && displayInfo->scale > 1.f) + scale *= displayInfo->scale; + } return scale; } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 24a8faa95..c127095fc 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -5612,25 +5612,40 @@ void Player::SaveRecallPosition() m_recallO = GetOrientation(); } -void Player::SendMessageToSetInRange(WorldPacket const* data, float dist, bool self, bool includeMargin, Player const* skipped_rcvr) const +void Player::SendMessageToSet(WorldPacket const* data, bool self) const +{ + SendMessageToSetInRange(data, GetVisibilityRange(), self); +} + +void Player::SendMessageToSetInRange(WorldPacket const* data, float dist, bool self) const { if (self) - GetSession()->SendPacket(data); + SendDirectMessage(data); + + Acore::MessageDistDeliverer notifier(this, data, dist); + Cell::VisitWorldObjects(this, notifier, dist); +} + +void Player::SendMessageToSetInRange(WorldPacket const* data, float dist, bool self, bool includeMargin, bool ownTeamOnly, bool required3dDist) const +{ + if (self) + SendDirectMessage(data); dist += GetObjectSize(); if (includeMargin) dist += VISIBILITY_COMPENSATION; // pussywizard: to ensure everyone receives all important packets - Acore::MessageDistDeliverer notifier(this, data, dist, false, skipped_rcvr); + + Acore::MessageDistDeliverer notifier(this, data, dist, ownTeamOnly, nullptr, required3dDist); Cell::VisitWorldObjects(this, notifier, dist); } -void Player::SendMessageToSetInRange_OwnTeam(WorldPacket const* data, float dist, bool self) const +void Player::SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const { - if (self) - GetSession()->SendPacket(data); + if (skipped_rcvr != this) + SendDirectMessage(data); - Acore::MessageDistDeliverer notifier(this, data, dist, true); - Cell::VisitWorldObjects(this, notifier, dist); + Acore::MessageDistDeliverer notifier(this, data, GetVisibilityRange(), false, skipped_rcvr); + Cell::VisitWorldObjects(this, notifier, GetVisibilityRange()); } void Player::SendDirectMessage(WorldPacket const* data) const @@ -9291,7 +9306,7 @@ void Player::Say(std::string_view text, Language language, WorldObject const* /* WorldPacket data; ChatHandler::BuildChatPacket(data, CHAT_MSG_SAY, language, this, this, _text); - SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), true); + SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), true, false, false, true); } void Player::Say(uint32 textId, WorldObject const* target /*= nullptr*/) @@ -9312,7 +9327,7 @@ void Player::Yell(std::string_view text, Language language, WorldObject const* / WorldPacket data; ChatHandler::BuildChatPacket(data, CHAT_MSG_YELL, language, this, this, _text); - SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL), true); + SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL), true, false, false, true); } void Player::Yell(uint32 textId, WorldObject const* target /*= nullptr*/) @@ -9334,14 +9349,7 @@ void Player::TextEmote(std::string_view text, WorldObject const* /*= nullptr*/, WorldPacket data; ChatHandler::BuildChatPacket(data, CHAT_MSG_EMOTE, LANG_UNIVERSAL, this, this, _text); - if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_EMOTE)) - { - SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), true); - } - else - { - SendMessageToSetInRange_OwnTeam(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), true); - } + SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), true, false, !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_EMOTE), true); } void Player::TextEmote(uint32 textId, WorldObject const* target /*= nullptr*/, bool /*isBossEmote = false*/) @@ -10521,7 +10529,7 @@ void Player::InitDataForForm(bool reapplyMods) { ShapeshiftForm form = GetShapeshiftForm(); - SpellShapeshiftEntry const* ssEntry = sSpellShapeshiftStore.LookupEntry(form); + SpellShapeshiftFormEntry const* ssEntry = sSpellShapeshiftFormStore.LookupEntry(form); if (ssEntry && ssEntry->attackSpeed) { SetAttackTime(BASE_ATTACK, ssEntry->attackSpeed); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 3f3eb95c9..7c8fdf844 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2000,11 +2000,10 @@ public: void ProcessTerrainStatusUpdate() override; - void SendMessageToSet(WorldPacket const* data, bool self) const override { SendMessageToSetInRange(data, GetVisibilityRange(), self, true); } // pussywizard! - void SendMessageToSetInRange(WorldPacket const* data, float dist, bool self, bool includeMargin = false, Player const* skipped_rcvr = nullptr) const override; // pussywizard! - void SendMessageToSetInRange_OwnTeam(WorldPacket const* data, float dist, bool self) const; // pussywizard! param includeMargin not needed here - void SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const override { SendMessageToSetInRange(data, GetVisibilityRange(), skipped_rcvr != this, true, skipped_rcvr); } // pussywizard! - + void SendMessageToSet(WorldPacket const* data, bool self) const override; + void SendMessageToSetInRange(WorldPacket const* data, float dist, bool self) const override; + void SendMessageToSetInRange(WorldPacket const* data, float dist, bool self, bool includeMargin, bool ownTeamOnly, bool required3dDist = false) const; + void SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const override; void SendTeleportAckPacket(); [[nodiscard]] Corpse* GetCorpse() const; diff --git a/src/server/game/Entities/Player/PlayerQuest.cpp b/src/server/game/Entities/Player/PlayerQuest.cpp index 329bb7ca9..2da11b7df 100644 --- a/src/server/game/Entities/Player/PlayerQuest.cpp +++ b/src/server/game/Entities/Player/PlayerQuest.cpp @@ -753,7 +753,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, else { sScriptMgr->OnGivePlayerXP(this, XP, nullptr, isLFGReward ? PlayerXPSource::XPSOURCE_QUEST_DF : PlayerXPSource::XPSOURCE_QUEST); - GiveXP(XP, nullptr, isLFGReward); + GiveXP(XP, nullptr, 1.0f, isLFGReward); } // Give player extra money if GetRewOrReqMoney > 0 and get ReqMoney if negative diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index f4504bda5..3e3984c31 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -3453,7 +3453,8 @@ SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spell, bool Ca return SPELL_MISS_NONE; // Return evade for units in evade mode - if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks() && !spell->HasAura(SPELL_AURA_CONTROL_VEHICLE) && !spell->HasAttribute(SPELL_ATTR0_CU_IGNORE_EVADE)) + if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks() && !spell->HasAura(SPELL_AURA_CONTROL_VEHICLE) + && !spell->HasAttribute(SPELL_ATTR0_CU_IGNORE_EVADE) && !spell->HasAttribute(SPELL_ATTR1_AURA_STAYS_AFTER_COMBAT)) return SPELL_MISS_EVADE; // Try victim reflect spell @@ -3528,7 +3529,7 @@ SpellMissInfo Unit::SpellHitResult(Unit* victim, Spell const* spell, bool CanRef // Return evade for units in evade mode if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks() && !spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE) && - !spellInfo->HasAttribute(SPELL_ATTR0_CU_IGNORE_EVADE)) + !spellInfo->HasAttribute(SPELL_ATTR0_CU_IGNORE_EVADE) && !spellInfo->HasAttribute(SPELL_ATTR1_AURA_STAYS_AFTER_COMBAT)) { return SPELL_MISS_EVADE; } @@ -5384,7 +5385,8 @@ void Unit::RemoveEvadeAuras() { Aura const* aura = iter->second->GetBase(); SpellInfo const* spellInfo = aura->GetSpellInfo(); - if (spellInfo->HasAttribute(SPELL_ATTR0_CU_IGNORE_EVADE) || spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE) || spellInfo->HasAura(SPELL_AURA_CLONE_CASTER) || (aura->IsPassive() && GetOwnerGUID().IsPlayer())) + if (spellInfo->HasAttribute(SPELL_ATTR0_CU_IGNORE_EVADE) || spellInfo->HasAttribute(SPELL_ATTR1_AURA_STAYS_AFTER_COMBAT) || spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE) + || spellInfo->HasAura(SPELL_AURA_CLONE_CASTER) || (aura->IsPassive() && GetOwnerGUID().IsPlayer())) ++iter; else _UnapplyAura(iter, AURA_REMOVE_BY_DEFAULT); @@ -5394,7 +5396,8 @@ void Unit::RemoveEvadeAuras() { Aura* aura = iter->second; SpellInfo const* spellInfo = aura->GetSpellInfo(); - if (spellInfo->HasAttribute(SPELL_ATTR0_CU_IGNORE_EVADE) || spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE) || spellInfo->HasAura(SPELL_AURA_CLONE_CASTER) || (aura->IsPassive() && GetOwnerGUID().IsPlayer())) + if (spellInfo->HasAttribute(SPELL_ATTR0_CU_IGNORE_EVADE) || spellInfo->HasAttribute(SPELL_ATTR1_AURA_STAYS_AFTER_COMBAT) || spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE) + || spellInfo->HasAura(SPELL_AURA_CLONE_CASTER) || (aura->IsPassive() && GetOwnerGUID().IsPlayer())) ++iter; else RemoveOwnedAura(iter, AURA_REMOVE_BY_DEFAULT); @@ -15190,7 +15193,7 @@ uint32 Unit::GetCreatureType() const if (GetTypeId() == TYPEID_PLAYER) { ShapeshiftForm form = GetShapeshiftForm(); - SpellShapeshiftEntry const* ssEntry = sSpellShapeshiftStore.LookupEntry(form); + SpellShapeshiftFormEntry const* ssEntry = sSpellShapeshiftFormStore.LookupEntry(form); if (ssEntry && ssEntry->creatureType > 0) return ssEntry->creatureType; else @@ -19677,7 +19680,7 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form, uint32 spellId) const } uint32 modelid = 0; - SpellShapeshiftEntry const* formEntry = sSpellShapeshiftStore.LookupEntry(form); + SpellShapeshiftFormEntry const* formEntry = sSpellShapeshiftFormStore.LookupEntry(form); if (formEntry && formEntry->modelID_A) { // Take the alliance modelid as default @@ -21613,7 +21616,7 @@ bool Unit::IsInDisallowedMountForm() const if (ShapeshiftForm form = GetShapeshiftForm()) { - SpellShapeshiftEntry const* shapeshift = sSpellShapeshiftStore.LookupEntry(form); + SpellShapeshiftFormEntry const* shapeshift = sSpellShapeshiftFormStore.LookupEntry(form); if (!shapeshift) { return true; @@ -21656,6 +21659,20 @@ bool Unit::IsInDisallowedMountForm() const return false; } +void Unit::SetUInt32Value(uint16 index, uint32 value) +{ + Object::SetUInt32Value(index, value); + + switch (index) + { + // Invalidating the cache on health change should fix an issue where the client sees dead NPCs when they are not. + // We might also need to invalidate the cache for some other fields as well. + case UNIT_FIELD_HEALTH: + InvalidateValuesUpdateCache(); + break; + } +} + std::string Unit::GetDebugInfo() const { std::stringstream sstr; diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 4ac796c90..fb62a18d8 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1571,6 +1571,8 @@ public: void ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply); void ApplyCastTimePercentMod(float val, bool apply); + void SetUInt32Value(uint16 index, uint32 value); + UnitFlags GetUnitFlags() const { return UnitFlags(GetUInt32Value(UNIT_FIELD_FLAGS)); } bool HasUnitFlag(UnitFlags flags) const { return HasFlag(UNIT_FIELD_FLAGS, flags); } void SetUnitFlag(UnitFlags flags) { SetFlag(UNIT_FIELD_FLAGS, flags); } diff --git a/src/server/game/Entities/Unit/enuminfo_Unit.cpp b/src/server/game/Entities/Unit/enuminfo_Unit.cpp index bd16ebd35..a3c4938c6 100644 --- a/src/server/game/Entities/Unit/enuminfo_Unit.cpp +++ b/src/server/game/Entities/Unit/enuminfo_Unit.cpp @@ -15,9 +15,9 @@ * with this program. If not, see . */ +#include "Unit.h" #include "Define.h" #include "SmartEnum.h" -#include "Unit.h" #include namespace Acore::Impl::EnumUtilsImpl diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.cpp b/src/server/game/Grids/Notifiers/GridNotifiers.cpp index db2ad0a67..42661e934 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.cpp +++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp @@ -217,8 +217,14 @@ void MessageDistDeliverer::Visit(PlayerMapType& m) if (!target->InSamePhase(i_phaseMask)) continue; - if (target->GetExactDist2dSq(i_source) > i_distSq) - continue; + if (required3dDist) + { + if (target->GetExactDistSq(i_source) > i_distSq) + continue; + } + else + if (target->GetExactDist2dSq(i_source) > i_distSq) + continue; // Send packet to all who are sharing the player's vision if (target->HasSharedVision()) @@ -242,8 +248,14 @@ void MessageDistDeliverer::Visit(CreatureMapType& m) if (!target->HasSharedVision() || !target->InSamePhase(i_phaseMask)) continue; - if (target->GetExactDist2dSq(i_source) > i_distSq) - continue; + if (required3dDist) + { + if (target->GetExactDistSq(i_source) > i_distSq) + continue; + } + else + if (target->GetExactDist2dSq(i_source) > i_distSq) + continue; // Send packet to all who are sharing the creature's vision SharedVisionList::const_iterator i = target->GetSharedVisionList().begin(); @@ -265,8 +277,14 @@ void MessageDistDeliverer::Visit(DynamicObjectMapType& m) if (!target->IsViewpoint()) continue; - if (target->GetExactDist2dSq(i_source) > i_distSq) - continue; + if (required3dDist) + { + if (target->GetExactDistSq(i_source) > i_distSq) + continue; + } + else + if (target->GetExactDist2dSq(i_source) > i_distSq) + continue; // Send packet back to the caster if the caster has vision of dynamic object Player* caster = (Player*)target->GetCaster(); diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index e06b9091f..97189e16c 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -102,10 +102,11 @@ namespace Acore float i_distSq; TeamId teamId; Player const* skipped_receiver; - MessageDistDeliverer(WorldObject const* src, WorldPacket const* msg, float dist, bool own_team_only = false, Player const* skipped = nullptr) + bool required3dDist; + MessageDistDeliverer(WorldObject const* src, WorldPacket const* msg, float dist, bool own_team_only = false, Player const* skipped = nullptr, bool req3dDist = false) : i_source(src), i_message(msg), i_phaseMask(src->GetPhaseMask()), i_distSq(dist * dist) , teamId((own_team_only && src->GetTypeId() == TYPEID_PLAYER) ? src->ToPlayer()->GetTeamId() : TEAM_NEUTRAL) - , skipped_receiver(skipped) + , skipped_receiver(skipped), required3dDist(req3dDist) { } void Visit(PlayerMapType& m); diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 8db5f3740..c9e8a5896 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -41,6 +41,8 @@ #include "World.h" #include "WorldPacket.h" #include "WorldSession.h" +#include "ArenaTeam.h" +#include "ArenaTeamMgr.h" Roll::Roll(ObjectGuid _guid, LootItem const& li) : itemGUID(_guid), itemid(li.itemid), itemRandomPropId(li.randomPropertyId), itemRandomSuffix(li.randomSuffix), itemCount(li.count), @@ -896,7 +898,7 @@ void Group::SendLootStartRollToPlayer(uint32 countDown, uint32 mapId, Player* p, p->GetSession()->SendPacket(&data); } -void Group::SendLootRoll(ObjectGuid sourceGuid, ObjectGuid targetGuid, uint8 rollNumber, uint8 rollType, Roll const& roll) +void Group::SendLootRoll(ObjectGuid sourceGuid, ObjectGuid targetGuid, uint8 rollNumber, uint8 rollType, Roll const& roll, bool autoPass) { WorldPacket data(SMSG_LOOT_ROLL, (8 + 4 + 8 + 4 + 4 + 4 + 1 + 1 + 1)); data << sourceGuid; // guid of the item rolled @@ -907,7 +909,7 @@ void Group::SendLootRoll(ObjectGuid sourceGuid, ObjectGuid targetGuid, uint8 rol data << uint32(roll.itemRandomPropId); // Item random property ID data << uint8(rollNumber); // 0: "Need for: [item name]" > 127: "you passed on: [item name]" Roll number data << uint8(rollType); // 0: "Need for: [item name]" 0: "You have selected need for [item name] 1: need roll 2: greed roll - data << uint8(0); // 1: "You automatically passed on: %s because you cannot loot that item." - Possibly used in need befor greed + data << uint8(autoPass); // 1: "You automatically passed on: %s because you cannot loot that item." for (Roll::PlayerVote::const_iterator itr = roll.playerVote.begin(); itr != roll.playerVote.end(); ++itr) { @@ -984,6 +986,23 @@ void Group::SendLooter(Creature* creature, Player* groupLooter) BroadcastPacket(&data, false); } +bool CanRollOnItem(LootItem const& item, Player const* player, Loot* loot) +{ + // Players can't roll on unique items if they already reached the maximum quantity of that item + ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item.itemid); + if (!proto) + return false; + + uint32 itemCount = player->GetItemCount(item.itemid); + if ((proto->MaxCount > 0 && static_cast(itemCount) >= proto->MaxCount) || (player->CanEquipUniqueItem(proto) != EQUIP_ERR_OK)) + return false; + + if (!item.AllowedForPlayer(player, loot->sourceWorldObjectGUID)) + return false; + + return true; +} + void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject) { std::vector::iterator i; @@ -1011,23 +1030,20 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject) for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next()) { Player* member = itr->GetSource(); - if (!member) + if (!member || !member->GetSession()) continue; if (member->IsAtLootRewardDistance(pLootedObject)) { - if (i->AllowedForPlayer(member, loot->sourceWorldObjectGUID)) - { - r->totalPlayersRolling++; + r->totalPlayersRolling++; - if (member->GetPassOnGroupLoot()) - { - r->playerVote[member->GetGUID()] = PASS; - r->totalPass++; - // can't broadcast the pass now. need to wait until all rolling players are known. - } - else - r->playerVote[member->GetGUID()] = NOT_EMITED_YET; + RollVote vote = member->GetPassOnGroupLoot() ? PASS : NOT_EMITED_YET; + if (!CanRollOnItem(*i, member, loot)) + { + vote = PASS; + ++r->totalPass; } + + r->playerVote[member->GetGUID()] = vote; } } @@ -1050,23 +1066,28 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject) continue; if (itr->second == PASS) - SendLootRoll(newitemGUID, p->GetGUID(), 128, ROLL_PASS, *r); + SendLootRoll(newitemGUID, p->GetGUID(), 128, ROLL_PASS, *r, true); } } - SendLootStartRoll(60000, pLootedObject->GetMapId(), *r); - - RollId.push_back(r); - - if (Creature* creature = pLootedObject->ToCreature()) + if (r->totalPass == r->totalPlayersRolling) + delete r; + else { - creature->m_groupLootTimer = 60000; - creature->lootingGroupLowGUID = GetGUID().GetCounter(); - } - else if (GameObject* go = pLootedObject->ToGameObject()) - { - go->m_groupLootTimer = 60000; - go->lootingGroupLowGUID = GetGUID().GetCounter(); + SendLootStartRoll(60000, pLootedObject->GetMapId(), *r); + + RollId.push_back(r); + + if (Creature* creature = pLootedObject->ToCreature()) + { + creature->m_groupLootTimer = 60000; + creature->lootingGroupLowGUID = GetGUID().GetCounter(); + } + else if (GameObject* go = pLootedObject->ToGameObject()) + { + go->m_groupLootTimer = 60000; + go->lootingGroupLowGUID = GetGUID().GetCounter(); + } } } else @@ -1094,16 +1115,18 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject) for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next()) { Player* member = itr->GetSource(); - if (!member) + if (!member || !member->GetSession()) continue; if (member->IsAtLootRewardDistance(pLootedObject)) { - if (i->AllowedForPlayer(member, loot->sourceWorldObjectGUID)) + RollVote vote = NOT_EMITED_YET; + if (!CanRollOnItem(*i, member, loot)) { - r->totalPlayersRolling++; - r->playerVote[member->GetGUID()] = NOT_EMITED_YET; + vote = PASS; + ++r->totalPass; } + r->playerVote[member->GetGUID()] = vote; } } @@ -1154,20 +1177,21 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject) for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next()) { Player* playerToRoll = itr->GetSource(); - if (!playerToRoll) + if (!playerToRoll || !playerToRoll->GetSession()) continue; - if (i->AllowedForPlayer(playerToRoll, loot->sourceWorldObjectGUID) && playerToRoll->IsAtLootRewardDistance(lootedObject)) + if (playerToRoll->IsAtGroupRewardDistance(lootedObject)) { r->totalPlayersRolling++; - if (playerToRoll->GetPassOnGroupLoot()) + + RollVote vote = playerToRoll->GetPassOnGroupLoot() ? PASS : NOT_EMITED_YET; + if (!CanRollOnItem(*i, playerToRoll, loot)) { - r->playerVote[playerToRoll->GetGUID()] = PASS; - r->totalPass++; - // can't broadcast the pass now. need to wait until all rolling players are known. + vote = PASS; + r->totalPass++; // Can't broadcast the pass now. need to wait until all rolling players are known } - else - r->playerVote[playerToRoll->GetGUID()] = NOT_EMITED_YET; + + r->playerVote[playerToRoll->GetGUID()] = vote; } } @@ -1228,13 +1252,21 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject) for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next()) { Player* playerToRoll = itr->GetSource(); - if (!playerToRoll) + if (!playerToRoll || !playerToRoll->GetSession()) continue; - if (i->AllowedForPlayer(playerToRoll, loot->sourceWorldObjectGUID) && playerToRoll->IsAtLootRewardDistance(lootedObject)) + if (playerToRoll->IsAtGroupRewardDistance(lootedObject)) { r->totalPlayersRolling++; - r->playerVote[playerToRoll->GetGUID()] = NOT_EMITED_YET; + + RollVote vote = playerToRoll->GetPassOnGroupLoot() ? PASS : NOT_EMITED_YET; + if (!CanRollOnItem(*i, playerToRoll, loot)) + { + vote = PASS; + r->totalPass++; // Can't broadcast the pass now. need to wait until all rolling players are known + } + + r->playerVote[playerToRoll->GetGUID()] = vote; } } @@ -1996,6 +2028,35 @@ GroupJoinBattlegroundResult Group::CanJoinBattlegroundQueue(Battleground const* if (bgTemplate->isArena() && memberscount != MinPlayerCount) return ERR_ARENA_TEAM_PARTY_SIZE; + //check against other arena team members + if (isRated) + { + ArenaTeam* arenaTeam = sArenaTeamMgr->GetArenaTeamById(arenaTeamId); + for (auto const& itr : arenaTeam->GetMembers()) + { + Player* teamMember = ObjectAccessor::FindConnectedPlayer(itr.Guid); + //are they online and not a member of this current group? + if (teamMember && !IsMember(teamMember->GetGUID())) + { + //are they already in queue for a rated arena? + if (teamMember->InBattlegroundQueueForBattlegroundQueueType(bgQueueTypeId)) + { + GroupQueueInfo ginfo; + BattlegroundQueue& queue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); + if (queue.GetPlayerGroupInfoData(teamMember->GetGUID(), &ginfo)) + { + if (ginfo.IsRated) + return ERR_BATTLEGROUND_JOIN_FAILED; + } + } + //are they currently in an arena match? + Battleground* bg = teamMember->GetBattleground(false); + if (bg && bg->isRated() && bg->GetMinPlayersPerTeam() == MinPlayerCount) + return ERR_BATTLEGROUND_JOIN_FAILED; + } + } + } + return GroupJoinBattlegroundResult(bgTemplate->GetBgTypeID()); } diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h index ffb7f2f2e..e07360342 100644 --- a/src/server/game/Groups/Group.h +++ b/src/server/game/Groups/Group.h @@ -288,7 +288,7 @@ public: bool isRollLootActive() const; void SendLootStartRoll(uint32 CountDown, uint32 mapid, const Roll& r); void SendLootStartRollToPlayer(uint32 countDown, uint32 mapId, Player* p, bool canNeed, Roll const& r); - void SendLootRoll(ObjectGuid SourceGuid, ObjectGuid TargetGuid, uint8 RollNumber, uint8 RollType, const Roll& r); + void SendLootRoll(ObjectGuid SourceGuid, ObjectGuid TargetGuid, uint8 RollNumber, uint8 RollType, const Roll& r, bool autoPass = false); void SendLootRollWon(ObjectGuid SourceGuid, ObjectGuid TargetGuid, uint8 RollNumber, uint8 RollType, const Roll& r); void SendLootAllPassed(Roll const& roll); void SendLooter(Creature* creature, Player* pLooter); diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 53c476b90..4f8a3c782 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -889,6 +889,9 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder) pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation()); else pCurrChar->TeleportTo(pCurrChar->m_homebindMapId, pCurrChar->m_homebindX, pCurrChar->m_homebindY, pCurrChar->m_homebindZ, pCurrChar->GetOrientation()); + + // Probably a hackfix, but currently the best workaround to prevent character names showing as Unknown after teleport out from instances at login. + pCurrChar->GetSession()->SendNameQueryOpcode(pCurrChar->GetGUID()); } pCurrChar->SendInitialPacketsAfterAddToMap(); diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp index ffd54a76b..cd677556e 100644 --- a/src/server/game/Handlers/ChatHandler.cpp +++ b/src/server/game/Handlers/ChatHandler.cpp @@ -283,14 +283,22 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) if (msg.empty()) return; - if (ChatHandler(this).ParseCommands(msg.c_str())) - return; - - if (!_player->CanSpeak()) + if (lang == LANG_ADDON) { - std::string timeStr = secsToTimeString(m_muteTime - GameTime::GetGameTime().count()); - SendNotification(GetAcoreString(LANG_WAIT_BEFORE_SPEAKING), timeStr.c_str()); - return; + if (AddonChannelCommandHandler(this).ParseCommands(msg.c_str())) + return; + } + else + { + if (ChatHandler(this).ParseCommands(msg.c_str())) + return; + + if (!_player->CanSpeak()) + { + std::string timeStr = secsToTimeString(m_muteTime - GameTime::GetGameTime().count()); + SendNotification(GetAcoreString(LANG_WAIT_BEFORE_SPEAKING), timeStr.c_str()); + return; + } } } diff --git a/src/server/game/Handlers/CombatHandler.cpp b/src/server/game/Handlers/CombatHandler.cpp index 0150c83e4..6a92526de 100644 --- a/src/server/game/Handlers/CombatHandler.cpp +++ b/src/server/game/Handlers/CombatHandler.cpp @@ -84,9 +84,12 @@ void WorldSession::HandleSetSheathedOpcode(WorldPackets::Combat::SetSheathed& pa void WorldSession::SendAttackStop(Unit const* enemy) { - WorldPacket data(SMSG_ATTACKSTOP, (8 + 8 + 4)); // we guess size + WorldPacket data(SMSG_ATTACKSTOP, (8 + 8 + 4)); // we guess size data << GetPlayer()->GetPackGUID(); - data << (enemy ? enemy->GetPackGUID() : PackedGuid()); // must be packed guid - data << uint32(0); // unk, can be 1 also + if (enemy) + { + data << enemy->GetPackGUID(); // must be packed guid + data << enemy->isDead(); + } SendPacket(&data); } diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index d78da716b..b76bc49b9 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -3069,7 +3069,7 @@ void InstanceMap::CreateInstanceScript(bool load, std::string data, uint32 compl bool isOtherAI = false; - sScriptMgr->OnBeforeCreateInstanceScript(this, instance_data, load, data, completedEncounterMask); + sScriptMgr->OnBeforeCreateInstanceScript(this, &instance_data, load, data, completedEncounterMask); if (instance_data) isOtherAI = true; diff --git a/src/server/game/Quests/enuminfo_QuestDef.cpp b/src/server/game/Quests/enuminfo_QuestDef.cpp index cf4651adc..aec7b5de3 100644 --- a/src/server/game/Quests/enuminfo_QuestDef.cpp +++ b/src/server/game/Quests/enuminfo_QuestDef.cpp @@ -15,8 +15,8 @@ * with this program. If not, see . */ -#include "Define.h" #include "QuestDef.h" +#include "Define.h" #include "SmartEnum.h" #include diff --git a/src/server/game/Scripting/ScriptDefines/AllMapScript.cpp b/src/server/game/Scripting/ScriptDefines/AllMapScript.cpp index e35700a12..c778b8fff 100644 --- a/src/server/game/Scripting/ScriptDefines/AllMapScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/AllMapScript.cpp @@ -279,7 +279,7 @@ void ScriptMgr::OnMapUpdate(Map* map, uint32 diff) }); } -void ScriptMgr::OnBeforeCreateInstanceScript(InstanceMap* instanceMap, InstanceScript* instanceData, bool load, std::string data, uint32 completedEncounterMask) +void ScriptMgr::OnBeforeCreateInstanceScript(InstanceMap* instanceMap, InstanceScript** instanceData, bool load, std::string data, uint32 completedEncounterMask) { ExecuteScript([&](AllMapScript* script) { diff --git a/src/server/game/Scripting/ScriptDefines/AllMapScript.h b/src/server/game/Scripting/ScriptDefines/AllMapScript.h index f97198866..77479fc1b 100644 --- a/src/server/game/Scripting/ScriptDefines/AllMapScript.h +++ b/src/server/game/Scripting/ScriptDefines/AllMapScript.h @@ -51,7 +51,7 @@ public: * @param data Contains information about the instance save data * @param completedEncounterMask Contains information about the completed encouter mask */ - virtual void OnBeforeCreateInstanceScript(InstanceMap* /*instanceMap*/, InstanceScript* /*instanceData*/, bool /*load*/, std::string /*data*/, uint32 /*completedEncounterMask*/) { } + virtual void OnBeforeCreateInstanceScript(InstanceMap* /*instanceMap*/, InstanceScript** /*instanceData*/, bool /*load*/, std::string /*data*/, uint32 /*completedEncounterMask*/) { } /** * @brief This hook called before destroy instance diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index bed6f0c35..79cad095f 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -605,7 +605,7 @@ public: /* AllGameobjectScript */ void OnGameObjectSaveToDB(GameObject* go); public: /* AllMapScript */ - void OnBeforeCreateInstanceScript(InstanceMap* instanceMap, InstanceScript* instanceData, bool load, std::string data, uint32 completedEncounterMask); + void OnBeforeCreateInstanceScript(InstanceMap* instanceMap, InstanceScript** instanceData, bool load, std::string data, uint32 completedEncounterMask); void OnDestroyInstance(MapInstanced* mapInstanced, Map* map); public: /* BGScript */ diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 3c7f16d7a..63af8f62b 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -2011,7 +2011,7 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo if (modelid > 0) { bool allow = true; - if (target->getTransForm()) + if (target->getTransForm() && !(target->GetMapId() == 560 /*The Escape From Durnholde*/)) if (SpellInfo const* transformSpellInfo = sSpellMgr->GetSpellInfo(target->getTransForm())) if (transformSpellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES) || !transformSpellInfo->IsPositive()) allow = false; @@ -2143,7 +2143,7 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo if (target->GetTypeId() == TYPEID_PLAYER) { - SpellShapeshiftEntry const* shapeInfo = sSpellShapeshiftStore.LookupEntry(form); + SpellShapeshiftFormEntry const* shapeInfo = sSpellShapeshiftFormStore.LookupEntry(form); // Learn spells for shapeshift form - no need to send action bars or add spells to spellbook for (uint8 i = 0; i < MAX_SHAPESHIFT_SPELLS; ++i) { diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 06301226b..8cb33d758 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5799,7 +5799,7 @@ SpellCastResult Spell::CheckCast(bool strict) SpellEffectInfo const* effInfo = &m_spellInfo->Effects[effIndex]; if (effInfo->ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT) { - SpellShapeshiftEntry const* shapeShiftEntry = sSpellShapeshiftStore.LookupEntry(effInfo->MiscValue); + SpellShapeshiftFormEntry const* shapeShiftEntry = sSpellShapeshiftFormStore.LookupEntry(effInfo->MiscValue); if (shapeShiftEntry && (shapeShiftEntry->flags1 & 1) == 0) // unk flag checkMask |= VEHICLE_SEAT_FLAG_UNCONTROLLED; break; diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index c90f3a9c4..42455c958 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1435,10 +1435,10 @@ SpellCastResult SpellInfo::CheckShapeshift(uint32 form) const return SPELL_CAST_OK; bool actAsShifted = false; - SpellShapeshiftEntry const* shapeInfo = nullptr; + SpellShapeshiftFormEntry const* shapeInfo = nullptr; if (form > 0) { - shapeInfo = sSpellShapeshiftStore.LookupEntry(form); + shapeInfo = sSpellShapeshiftFormStore.LookupEntry(form); if (!shapeInfo) { LOG_ERROR("spells", "GetErrorAtShapeshiftedCast: unknown shapeshift {}", form); @@ -2437,7 +2437,7 @@ int32 SpellInfo::CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask, S if (AttributesEx4 & SPELL_ATTR4_WEAPON_SPEED_COST_SCALING) { uint32 speed = 0; - if (SpellShapeshiftEntry const* ss = sSpellShapeshiftStore.LookupEntry(caster->GetShapeshiftForm())) + if (SpellShapeshiftFormEntry const* ss = sSpellShapeshiftFormStore.LookupEntry(caster->GetShapeshiftForm())) speed = ss->attackSpeed; else { diff --git a/src/server/game/Time/UpdateTime.cpp b/src/server/game/Time/UpdateTime.cpp index 8aa9592b7..3c4886376 100644 --- a/src/server/game/Time/UpdateTime.cpp +++ b/src/server/game/Time/UpdateTime.cpp @@ -165,10 +165,11 @@ void WorldUpdateTime::RecordUpdateTime(Milliseconds gameTimeMs, uint32 diff, uin { if (GetMSTimeDiff(_lastRecordTime, gameTimeMs) > _recordUpdateTimeInverval) { - LOG_INFO("time.update", "Last {} diffs summary with {} players online:", GetDatasetSize(), sessionCount); - LOG_INFO("time.update", " - Mean: {};", GetAverageUpdateTime()); - LOG_INFO("time.update", " - Median: {};", GetPercentile(50)); - LOG_INFO("time.update", " - Percentiles (95, 99, max): {}, {}, {}.", GetPercentile(95), GetPercentile(99), GetPercentile(100)); + LOG_INFO("time.update", "Update time diff: {}ms with {} players online", GetLastUpdateTime(), sessionCount); + LOG_INFO("time.update", "Last {} diffs summary:", GetDatasetSize()); + LOG_INFO("time.update", "|- Mean: {}ms", GetAverageUpdateTime()); + LOG_INFO("time.update", "|- Median: {}ms", GetPercentile(50)); + LOG_INFO("time.update", "|- Percentiles (95, 99, max): {}ms, {}ms, {}ms", GetPercentile(95), GetPercentile(99), GetPercentile(100)); _lastRecordTime = gameTimeMs; } } diff --git a/src/server/game/Warden/enuminfo_WardenCheckMgr.cpp b/src/server/game/Warden/enuminfo_WardenCheckMgr.cpp index f4d906b69..f76872a82 100644 --- a/src/server/game/Warden/enuminfo_WardenCheckMgr.cpp +++ b/src/server/game/Warden/enuminfo_WardenCheckMgr.cpp @@ -15,9 +15,9 @@ * with this program. If not, see . */ +#include "WardenCheckMgr.h" #include "Define.h" #include "SmartEnum.h" -#include "WardenCheckMgr.h" #include namespace Acore::Impl::EnumUtilsImpl diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp index 1cd1e0a23..9ea10809b 100644 --- a/src/server/scripts/Commands/cs_reload.cpp +++ b/src/server/scripts/Commands/cs_reload.cpp @@ -223,7 +223,7 @@ public: static bool HandleReloadBattlegroundTemplate(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Battleground Templates..."); + LOG_INFO("server.loading", "Reloading Battleground Templates..."); sBattlegroundMgr->LoadBattlegroundTemplates(); handler->SendGlobalGMSysMessage("DB table `battleground_template` reloaded."); return true; @@ -247,7 +247,7 @@ public: static bool HandleReloadAllLootCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Loot Tables..."); + LOG_INFO("server.loading", "Reloading Loot Tables..."); LoadLootTables(); handler->SendGlobalGMSysMessage("DB tables `*_loot_template` reloaded."); sConditionMgr->LoadConditions(true); @@ -271,7 +271,7 @@ public: HandleReloadQuestTemplateCommand(handler); HandleReloadLocalesQuestGreetingCommand(handler); - LOG_INFO("server.loading", "Re-Loading Quests Relations..."); + LOG_INFO("server.loading", "Reloading Quests Relations..."); sObjectMgr->LoadQuestStartersAndEnders(); handler->SendGlobalGMSysMessage("DB tables `*_queststarter` and `*_questender` reloaded."); return true; @@ -285,7 +285,7 @@ public: return false; } - LOG_INFO("server.loading", "Re-Loading Scripts..."); + LOG_INFO("server.loading", "Reloading Scripts..."); HandleReloadEventScriptsCommand(handler); HandleReloadSpellScriptsCommand(handler); handler->SendGlobalGMSysMessage("DB tables `*_scripts` reloaded."); @@ -346,7 +346,7 @@ public: static bool HandleReloadConfigCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading config settings..."); + LOG_INFO("server.loading", "Reloading config settings..."); sWorld->LoadConfigSettings(true); sMapMgr->InitializeVisibilityDistanceInfo(); handler->SendGlobalGMSysMessage("World config settings reloaded."); @@ -355,7 +355,7 @@ public: static bool HandleReloadDungeonAccessCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Dungeon Access Requirement definitions..."); + LOG_INFO("server.loading", "Reloading Dungeon Access Requirement definitions..."); sObjectMgr->LoadAccessRequirements(); handler->SendGlobalGMSysMessage("DB tables `dungeon_access_template` AND `dungeon_access_requirements` reloaded."); return true; @@ -363,7 +363,7 @@ public: static bool HandleReloadAchievementCriteriaDataCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Additional Achievement Criteria Data..."); + LOG_INFO("server.loading", "Reloading Additional Achievement Criteria Data..."); sAchievementMgr->LoadAchievementCriteriaData(); handler->SendGlobalGMSysMessage("DB table `achievement_criteria_data` reloaded."); return true; @@ -371,7 +371,7 @@ public: static bool HandleReloadAchievementRewardCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Achievement Reward Data..."); + LOG_INFO("server.loading", "Reloading Achievement Reward Data..."); sAchievementMgr->LoadRewards(); handler->SendGlobalGMSysMessage("DB table `achievement_reward` reloaded."); return true; @@ -379,7 +379,7 @@ public: static bool HandleReloadAreaTriggerTavernCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Tavern Area Triggers..."); + LOG_INFO("server.loading", "Reloading Tavern Area Triggers..."); sObjectMgr->LoadTavernAreaTriggers(); handler->SendGlobalGMSysMessage("DB table `areatrigger_tavern` reloaded."); return true; @@ -387,7 +387,7 @@ public: static bool HandleReloadAreaTriggerCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Area Trigger definitions..."); + LOG_INFO("server.loading", "Reloading Area Trigger definitions..."); sObjectMgr->LoadAreaTriggers(); handler->SendGlobalGMSysMessage("DB table `areatrigger` reloaded."); return true; @@ -395,7 +395,7 @@ public: static bool HandleReloadAreaTriggerTeleportCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Area Trigger teleport definitions..."); + LOG_INFO("server.loading", "Reloading Area Trigger teleport definitions..."); sObjectMgr->LoadAreaTriggerTeleports(); handler->SendGlobalGMSysMessage("DB table `areatrigger_teleport` reloaded."); return true; @@ -403,7 +403,7 @@ public: static bool HandleReloadAutobroadcastCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Autobroadcasts..."); + LOG_INFO("server.loading", "Reloading Autobroadcasts..."); sAutobroadcastMgr->LoadAutobroadcasts(); handler->SendGlobalGMSysMessage("DB table `autobroadcast` reloaded."); return true; @@ -411,7 +411,7 @@ public: static bool HandleReloadMotdCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Motd..."); + LOG_INFO("server.loading", "Reloading Motd..."); sMotdMgr->LoadMotd(); handler->SendGlobalGMSysMessage("DB table `motd` reloaded."); handler->SendGlobalSysMessage(sMotdMgr->GetMotd()); @@ -420,7 +420,7 @@ public: static bool HandleReloadBroadcastTextCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Broadcast texts..."); + LOG_INFO("server.loading", "Reloading Broadcast texts..."); sObjectMgr->LoadBroadcastTexts(); sObjectMgr->LoadBroadcastTextLocales(); handler->SendGlobalGMSysMessage("DB table `broadcast_text` reloaded."); @@ -440,7 +440,7 @@ public: static bool HandleReloadOnKillReputationCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading creature award reputation definitions..."); + LOG_INFO("server.loading", "Reloading creature award reputation definitions..."); sObjectMgr->LoadReputationOnKill(); handler->SendGlobalGMSysMessage("DB table `creature_onkill_reputation` reloaded."); return true; @@ -510,7 +510,7 @@ public: static bool HandleReloadGossipMenuCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading `gossip_menu` Table!"); + LOG_INFO("server.loading", "Reloading `gossip_menu` Table!"); sObjectMgr->LoadGossipMenu(); handler->SendGlobalGMSysMessage("DB table `gossip_menu` reloaded."); sConditionMgr->LoadConditions(true); @@ -519,7 +519,7 @@ public: static bool HandleReloadGossipMenuOptionCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading `gossip_menu_option` Table!"); + LOG_INFO("server.loading", "Reloading `gossip_menu_option` Table!"); sObjectMgr->LoadGossipMenuItems(); handler->SendGlobalGMSysMessage("DB table `gossip_menu_option` reloaded."); sConditionMgr->LoadConditions(true); @@ -544,7 +544,7 @@ public: static bool HandleReloadQuestAreaTriggersCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Quest Area Triggers..."); + LOG_INFO("server.loading", "Reloading Quest Area Triggers..."); sObjectMgr->LoadQuestAreaTriggers(); handler->SendGlobalGMSysMessage("DB table `areatrigger_involvedrelation` (quest area triggers) reloaded."); return true; @@ -552,7 +552,7 @@ public: static bool HandleReloadQuestGreetingCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Quest Greeting ..."); + LOG_INFO("server.loading", "Reloading Quest Greeting ..."); sObjectMgr->LoadQuestGreetings(); handler->SendGlobalGMSysMessage("DB table `quest_greeting` reloaded."); return true; @@ -560,7 +560,7 @@ public: static bool HandleReloadLocalesQuestGreetingCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Quest Greeting locales..."); + LOG_INFO("server.loading", "Reloading Quest Greeting locales..."); sObjectMgr->LoadQuestGreetingsLocales(); handler->SendGlobalGMSysMessage("DB table `quest_greeting_locale` reloaded."); return true; @@ -568,12 +568,12 @@ public: static bool HandleReloadQuestTemplateCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Quest Templates..."); + LOG_INFO("server.loading", "Reloading Quest Templates..."); sObjectMgr->LoadQuests(); handler->SendGlobalGMSysMessage("DB table `quest_template` (quest definitions) reloaded."); /// dependent also from `gameobject` but this table not reloaded anyway - LOG_INFO("server.loading", "Re-Loading GameObjects for quests..."); + LOG_INFO("server.loading", "Reloading GameObjects for quests..."); sObjectMgr->LoadGameObjectForQuests(); handler->SendGlobalGMSysMessage("Data GameObjects for quests reloaded."); return true; @@ -581,7 +581,7 @@ public: static bool HandleReloadLootTemplatesCreatureCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Loot Tables... (`creature_loot_template`)"); + LOG_INFO("server.loading", "Reloading Loot Tables... (`creature_loot_template`)"); LoadLootTemplates_Creature(); LootTemplates_Creature.CheckLootRefs(); handler->SendGlobalGMSysMessage("DB table `creature_loot_template` reloaded."); @@ -591,7 +591,7 @@ public: static bool HandleReloadCreatureMovementOverrideCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Creature movement overrides..."); + LOG_INFO("server.loading", "Reloading Creature movement overrides..."); sObjectMgr->LoadCreatureMovementOverrides(); handler->SendGlobalGMSysMessage("DB table `creature_movement_override` reloaded."); return true; @@ -599,7 +599,7 @@ public: static bool HandleReloadLootTemplatesDisenchantCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Loot Tables... (`disenchant_loot_template`)"); + LOG_INFO("server.loading", "Reloading Loot Tables... (`disenchant_loot_template`)"); LoadLootTemplates_Disenchant(); LootTemplates_Disenchant.CheckLootRefs(); handler->SendGlobalGMSysMessage("DB table `disenchant_loot_template` reloaded."); @@ -609,7 +609,7 @@ public: static bool HandleReloadLootTemplatesFishingCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Loot Tables... (`fishing_loot_template`)"); + LOG_INFO("server.loading", "Reloading Loot Tables... (`fishing_loot_template`)"); LoadLootTemplates_Fishing(); LootTemplates_Fishing.CheckLootRefs(); handler->SendGlobalGMSysMessage("DB table `fishing_loot_template` reloaded."); @@ -619,7 +619,7 @@ public: static bool HandleReloadLootTemplatesGameobjectCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Loot Tables... (`gameobject_loot_template`)"); + LOG_INFO("server.loading", "Reloading Loot Tables... (`gameobject_loot_template`)"); LoadLootTemplates_Gameobject(); LootTemplates_Gameobject.CheckLootRefs(); handler->SendGlobalGMSysMessage("DB table `gameobject_loot_template` reloaded."); @@ -629,7 +629,7 @@ public: static bool HandleReloadLootTemplatesItemCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Loot Tables... (`item_loot_template`)"); + LOG_INFO("server.loading", "Reloading Loot Tables... (`item_loot_template`)"); LoadLootTemplates_Item(); LootTemplates_Item.CheckLootRefs(); handler->SendGlobalGMSysMessage("DB table `item_loot_template` reloaded."); @@ -639,7 +639,7 @@ public: static bool HandleReloadLootTemplatesMillingCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Loot Tables... (`milling_loot_template`)"); + LOG_INFO("server.loading", "Reloading Loot Tables... (`milling_loot_template`)"); LoadLootTemplates_Milling(); LootTemplates_Milling.CheckLootRefs(); handler->SendGlobalGMSysMessage("DB table `milling_loot_template` reloaded."); @@ -649,7 +649,7 @@ public: static bool HandleReloadLootTemplatesPickpocketingCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Loot Tables... (`pickpocketing_loot_template`)"); + LOG_INFO("server.loading", "Reloading Loot Tables... (`pickpocketing_loot_template`)"); LoadLootTemplates_Pickpocketing(); LootTemplates_Pickpocketing.CheckLootRefs(); handler->SendGlobalGMSysMessage("DB table `pickpocketing_loot_template` reloaded."); @@ -659,7 +659,7 @@ public: static bool HandleReloadLootTemplatesProspectingCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Loot Tables... (`prospecting_loot_template`)"); + LOG_INFO("server.loading", "Reloading Loot Tables... (`prospecting_loot_template`)"); LoadLootTemplates_Prospecting(); LootTemplates_Prospecting.CheckLootRefs(); handler->SendGlobalGMSysMessage("DB table `prospecting_loot_template` reloaded."); @@ -669,7 +669,7 @@ public: static bool HandleReloadLootTemplatesMailCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Loot Tables... (`mail_loot_template`)"); + LOG_INFO("server.loading", "Reloading Loot Tables... (`mail_loot_template`)"); LoadLootTemplates_Mail(); LootTemplates_Mail.CheckLootRefs(); handler->SendGlobalGMSysMessage("DB table `mail_loot_template` reloaded."); @@ -679,7 +679,7 @@ public: static bool HandleReloadLootTemplatesReferenceCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Loot Tables... (`reference_loot_template`)"); + LOG_INFO("server.loading", "Reloading Loot Tables... (`reference_loot_template`)"); LoadLootTemplates_Reference(); handler->SendGlobalGMSysMessage("DB table `reference_loot_template` reloaded."); sConditionMgr->LoadConditions(true); @@ -688,7 +688,7 @@ public: static bool HandleReloadLootTemplatesSkinningCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Loot Tables... (`skinning_loot_template`)"); + LOG_INFO("server.loading", "Reloading Loot Tables... (`skinning_loot_template`)"); LoadLootTemplates_Skinning(); LootTemplates_Skinning.CheckLootRefs(); handler->SendGlobalGMSysMessage("DB table `skinning_loot_template` reloaded."); @@ -698,7 +698,7 @@ public: static bool HandleReloadLootTemplatesSpellCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Loot Tables... (`spell_loot_template`)"); + LOG_INFO("server.loading", "Reloading Loot Tables... (`spell_loot_template`)"); LoadLootTemplates_Spell(); LootTemplates_Spell.CheckLootRefs(); handler->SendGlobalGMSysMessage("DB table `spell_loot_template` reloaded."); @@ -708,7 +708,7 @@ public: static bool HandleReloadLootTemplatesPlayerCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Loot Tables... (`player_loot_template`)"); + LOG_INFO("server.loading", "Reloading Loot Tables... (`player_loot_template`)"); LoadLootTemplates_Player(); LootTemplates_Player.CheckLootRefs(); handler->SendGlobalGMSysMessage("DB table `player_loot_template` reloaded."); @@ -718,7 +718,7 @@ public: static bool HandleReloadAcoreStringCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading acore_string Table!"); + LOG_INFO("server.loading", "Reloading acore_string Table!"); sObjectMgr->LoadAcoreStrings(); handler->SendGlobalGMSysMessage("DB table `acore_string` reloaded."); return true; @@ -732,7 +732,7 @@ public: return false; } - LOG_INFO("server.loading", "Re-Loading warden_action Table!"); + LOG_INFO("server.loading", "Reloading warden_action Table!"); sWardenCheckMgr->LoadWardenOverrides(); handler->SendGlobalGMSysMessage("DB table `warden_action` reloaded."); return true; @@ -740,7 +740,7 @@ public: static bool HandleReloadNpcTrainerCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading `npc_trainer` Table!"); + LOG_INFO("server.loading", "Reloading `npc_trainer` Table!"); sObjectMgr->LoadTrainerSpell(); handler->SendGlobalGMSysMessage("DB table `npc_trainer` reloaded."); return true; @@ -748,7 +748,7 @@ public: static bool HandleReloadNpcVendorCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading `npc_vendor` Table!"); + LOG_INFO("server.loading", "Reloading `npc_vendor` Table!"); sObjectMgr->LoadVendors(); handler->SendGlobalGMSysMessage("DB table `npc_vendor` reloaded."); return true; @@ -756,7 +756,7 @@ public: static bool HandleReloadPointsOfInterestCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading `points_of_interest` Table!"); + LOG_INFO("server.loading", "Reloading `points_of_interest` Table!"); sObjectMgr->LoadPointsOfInterest(); handler->SendGlobalGMSysMessage("DB table `points_of_interest` reloaded."); return true; @@ -764,7 +764,7 @@ public: static bool HandleReloadQuestPOICommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Quest POI ..." ); + LOG_INFO("server.loading", "Reloading Quest POI ..." ); sObjectMgr->LoadQuestPOI(); handler->SendGlobalGMSysMessage("DB Table `quest_poi` and `quest_poi_points` reloaded."); return true; @@ -772,7 +772,7 @@ public: static bool HandleReloadSpellClickSpellsCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading `npc_spellclick_spells` Table!"); + LOG_INFO("server.loading", "Reloading `npc_spellclick_spells` Table!"); sObjectMgr->LoadNPCSpellClickSpells(); handler->SendGlobalGMSysMessage("DB table `npc_spellclick_spells` reloaded."); return true; @@ -780,7 +780,7 @@ public: static bool HandleReloadReservedNameCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Reserved Names!"); + LOG_INFO("server.loading", "Reloading Reserved Names!"); sObjectMgr->LoadReservedPlayerNamesDB(); sObjectMgr->LoadReservedPlayerNamesDBC(); // Needed because we clear the store in LoadReservedPlayerNamesDB() handler->SendGlobalGMSysMessage("Reserved Names reloaded."); @@ -789,7 +789,7 @@ public: static bool HandleReloadProfanityNameCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Profanity Names!"); + LOG_INFO("server.loading", "Reloading Profanity Names!"); sObjectMgr->LoadProfanityNamesFromDB(); sObjectMgr->LoadProfanityNamesFromDBC(); // Needed because we clear the store in LoadProfanityNamesFromDB() handler->SendGlobalGMSysMessage("Profanity Names reloaded."); @@ -798,7 +798,7 @@ public: static bool HandleReloadReputationRewardRateCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading `reputation_reward_rate` Table!" ); + LOG_INFO("server.loading", "Reloading `reputation_reward_rate` Table!" ); sObjectMgr->LoadReputationRewardRate(); handler->SendGlobalSysMessage("DB table `reputation_reward_rate` reloaded."); return true; @@ -806,7 +806,7 @@ public: static bool HandleReloadReputationSpilloverTemplateCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading `reputation_spillover_template` Table!" ); + LOG_INFO("server.loading", "Reloading `reputation_spillover_template` Table!" ); sObjectMgr->LoadReputationSpilloverTemplate(); handler->SendGlobalSysMessage("DB table `reputation_spillover_template` reloaded."); return true; @@ -814,7 +814,7 @@ public: static bool HandleReloadSkillDiscoveryTemplateCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Skill Discovery Table..."); + LOG_INFO("server.loading", "Reloading Skill Discovery Table..."); LoadSkillDiscoveryTable(); handler->SendGlobalGMSysMessage("DB table `skill_discovery_template` (recipes discovered at crafting) reloaded."); return true; @@ -823,7 +823,7 @@ public: static bool HandleReloadSkillPerfectItemTemplateCommand(ChatHandler* handler) { // latched onto HandleReloadSkillExtraItemTemplateCommand as it's part of that table group (and i don't want to chance all the command IDs) - LOG_INFO("server.loading", "Re-Loading Skill Perfection Data Table..."); + LOG_INFO("server.loading", "Reloading Skill Perfection Data Table..."); LoadSkillPerfectItemTable(); handler->SendGlobalGMSysMessage("DB table `skill_perfect_item_template` (perfect item procs when crafting) reloaded."); return true; @@ -831,7 +831,7 @@ public: static bool HandleReloadSkillExtraItemTemplateCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Skill Extra Item Table..."); + LOG_INFO("server.loading", "Reloading Skill Extra Item Table..."); LoadSkillExtraItemTable(); handler->SendGlobalGMSysMessage("DB table `skill_extra_item_template` (extra item creation when crafting) reloaded."); return HandleReloadSkillPerfectItemTemplateCommand(handler); @@ -839,7 +839,7 @@ public: static bool HandleReloadSkillFishingBaseLevelCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Skill Fishing base level requirements..."); + LOG_INFO("server.loading", "Reloading Skill Fishing base level requirements..."); sObjectMgr->LoadFishingBaseSkillLevel(); handler->SendGlobalGMSysMessage("DB table `skill_fishing_base_level` (fishing base level for zone/subzone) reloaded."); return true; @@ -847,7 +847,7 @@ public: static bool HandleReloadSpellAreaCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading SpellArea Data..."); + LOG_INFO("server.loading", "Reloading SpellArea Data..."); sSpellMgr->LoadSpellAreas(); handler->SendGlobalGMSysMessage("DB table `spell_area` (spell dependences from area/quest/auras state) reloaded."); return true; @@ -855,7 +855,7 @@ public: static bool HandleReloadSpellRequiredCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Spell Required Data... "); + LOG_INFO("server.loading", "Reloading Spell Required Data... "); sSpellMgr->LoadSpellRequired(); handler->SendGlobalGMSysMessage("DB table `spell_required` reloaded."); return true; @@ -863,7 +863,7 @@ public: static bool HandleReloadSpellGroupsCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Spell Groups..."); + LOG_INFO("server.loading", "Reloading Spell Groups..."); sSpellMgr->LoadSpellGroups(); handler->SendGlobalGMSysMessage("DB table `spell_group` (spell groups) reloaded."); return true; @@ -871,7 +871,7 @@ public: static bool HandleReloadSpellLinkedSpellCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Spell Linked Spells..."); + LOG_INFO("server.loading", "Reloading Spell Linked Spells..."); sSpellMgr->LoadSpellLinked(); handler->SendGlobalGMSysMessage("DB table `spell_linked_spell` reloaded."); return true; @@ -879,7 +879,7 @@ public: static bool HandleReloadSpellProcEventCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Spell Proc Event conditions..."); + LOG_INFO("server.loading", "Reloading Spell Proc Event conditions..."); sSpellMgr->LoadSpellProcEvents(); handler->SendGlobalGMSysMessage("DB table `spell_proc_event` (spell proc trigger requirements) reloaded."); return true; @@ -887,7 +887,7 @@ public: static bool HandleReloadSpellProcsCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Spell Proc conditions and data..."); + LOG_INFO("server.loading", "Reloading Spell Proc conditions and data..."); sSpellMgr->LoadSpellProcs(); handler->SendGlobalGMSysMessage("DB table `spell_proc` (spell proc conditions and data) reloaded."); return true; @@ -895,7 +895,7 @@ public: static bool HandleReloadSpellBonusesCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Spell Bonus Data..."); + LOG_INFO("server.loading", "Reloading Spell Bonus Data..."); sSpellMgr->LoadSpellBonuses(); handler->SendGlobalGMSysMessage("DB table `spell_bonus_data` (spell damage/healing coefficients) reloaded."); return true; @@ -903,7 +903,7 @@ public: static bool HandleReloadSpellTargetPositionCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Spell target coordinates..."); + LOG_INFO("server.loading", "Reloading Spell target coordinates..."); sSpellMgr->LoadSpellTargetPositions(); handler->SendGlobalGMSysMessage("DB table `spell_target_position` (destination coordinates for spell targets) reloaded."); return true; @@ -911,7 +911,7 @@ public: static bool HandleReloadSpellThreatsCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Aggro Spells Definitions..."); + LOG_INFO("server.loading", "Reloading Aggro Spells Definitions..."); sSpellMgr->LoadSpellThreats(); handler->SendGlobalGMSysMessage("DB table `spell_threat` (spell aggro definitions) reloaded."); return true; @@ -919,7 +919,7 @@ public: static bool HandleReloadSpellGroupStackRulesCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Spell Group Stack Rules..."); + LOG_INFO("server.loading", "Reloading Spell Group Stack Rules..."); sSpellMgr->LoadSpellGroupStackRules(); handler->SendGlobalGMSysMessage("DB table `spell_group_stack_rules` (spell stacking definitions) reloaded."); return true; @@ -927,7 +927,7 @@ public: static bool HandleReloadSpellPetAurasCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Spell pet auras..."); + LOG_INFO("server.loading", "Reloading Spell pet auras..."); sSpellMgr->LoadSpellPetAuras(); handler->SendGlobalGMSysMessage("DB table `spell_pet_auras` reloaded."); return true; @@ -935,7 +935,7 @@ public: static bool HandleReloadPageTextsCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Page Texts..."); + LOG_INFO("server.loading", "Reloading Page Texts..."); sObjectMgr->LoadPageTexts(); handler->SendGlobalGMSysMessage("DB table `page_texts` reloaded."); handler->SendGlobalGMSysMessage("You need to delete your client cache or change the cache number in config in order for your players see the changes."); @@ -944,7 +944,7 @@ public: static bool HandleReloadItemEnchantementsCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Item Random Enchantments Table..."); + LOG_INFO("server.loading", "Reloading Item Random Enchantments Table..."); LoadRandomEnchantmentsTable(); handler->SendGlobalGMSysMessage("DB table `item_enchantment_template` reloaded."); return true; @@ -952,7 +952,7 @@ public: static bool HandleReloadItemSetNamesCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Item set names..."); + LOG_INFO("server.loading", "Reloading Item set names..."); sObjectMgr->LoadItemSetNames(); handler->SendGlobalGMSysMessage("DB table `item_set_names` reloaded."); return true; @@ -966,7 +966,7 @@ public: return false; } - LOG_INFO("server.loading", "Re-Loading Scripts from `event_scripts`..."); + LOG_INFO("server.loading", "Reloading Scripts from `event_scripts`..."); sObjectMgr->LoadEventScripts(); @@ -983,7 +983,7 @@ public: return false; } - LOG_INFO("server.loading", "Re-Loading Scripts from `waypoint_scripts`..."); + LOG_INFO("server.loading", "Reloading Scripts from `waypoint_scripts`..."); sObjectMgr->LoadWaypointScripts(); @@ -994,7 +994,7 @@ public: static bool HandleReloadWpCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Waypoints data from 'waypoints_data'"); + LOG_INFO("server.loading", "Reloading Waypoints data from 'waypoints_data'"); sWaypointMgr->Load(); handler->SendGlobalGMSysMessage("DB Table 'waypoint_data' reloaded."); @@ -1009,7 +1009,7 @@ public: return false; } - LOG_INFO("server.loading", "Re-Loading Scripts from `spell_scripts`..."); + LOG_INFO("server.loading", "Reloading Scripts from `spell_scripts`..."); sObjectMgr->LoadSpellScripts(); @@ -1020,7 +1020,7 @@ public: static bool HandleReloadGameGraveyardZoneCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Graveyard-zone links..."); + LOG_INFO("server.loading", "Reloading Graveyard-zone links..."); sGraveyard->LoadGraveyardZones(); @@ -1031,7 +1031,7 @@ public: static bool HandleReloadGameTeleCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Game Tele coordinates..."); + LOG_INFO("server.loading", "Reloading Game Tele coordinates..."); sObjectMgr->LoadGameTele(); @@ -1042,7 +1042,7 @@ public: static bool HandleReloadDisablesCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading disables table..."); + LOG_INFO("server.loading", "Reloading disables table..."); DisableMgr::LoadDisables(); LOG_INFO("server.loading", "Checking quest disables..."); DisableMgr::CheckQuestDisables(); @@ -1052,7 +1052,7 @@ public: static bool HandleReloadLocalesAchievementRewardCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Achievement Reward Data Locale..."); + LOG_INFO("server.loading", "Reloading Achievement Reward Data Locale..."); sAchievementMgr->LoadRewardLocales(); handler->SendGlobalGMSysMessage("DB table `achievement_reward_locale` reloaded."); return true; @@ -1060,7 +1060,7 @@ public: static bool HandleReloadLfgRewardsCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading lfg dungeon rewards..."); + LOG_INFO("server.loading", "Reloading lfg dungeon rewards..."); sLFGMgr->LoadRewards(); handler->SendGlobalGMSysMessage("DB table `lfg_dungeon_rewards` reloaded."); return true; @@ -1068,7 +1068,7 @@ public: static bool HandleReloadLocalesCreatureCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Creature Template Locale..."); + LOG_INFO("server.loading", "Reloading Creature Template Locale..."); sObjectMgr->LoadCreatureLocales(); handler->SendGlobalGMSysMessage("DB table `creature_template_locale` reloaded."); return true; @@ -1076,7 +1076,7 @@ public: static bool HandleReloadLocalesCreatureTextCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Creature Texts Locale..."); + LOG_INFO("server.loading", "Reloading Creature Texts Locale..."); sCreatureTextMgr->LoadCreatureTextLocales(); handler->SendGlobalGMSysMessage("DB table `creature_text_locale` reloaded."); return true; @@ -1084,7 +1084,7 @@ public: static bool HandleReloadLocalesGameobjectCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Gameobject Template Locale ... "); + LOG_INFO("server.loading", "Reloading Gameobject Template Locale ... "); sObjectMgr->LoadGameObjectLocales(); handler->SendGlobalGMSysMessage("DB table `gameobject_template_locale` reloaded."); return true; @@ -1092,7 +1092,7 @@ public: static bool HandleReloadLocalesGossipMenuOptionCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Gossip Menu Option Locale ... "); + LOG_INFO("server.loading", "Reloading Gossip Menu Option Locale ... "); sObjectMgr->LoadGossipMenuItemsLocales(); handler->SendGlobalGMSysMessage("DB table `gossip_menu_option_locale` reloaded."); return true; @@ -1100,7 +1100,7 @@ public: static bool HandleReloadLocalesItemCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Item Template Locale ... "); + LOG_INFO("server.loading", "Reloading Item Template Locale ... "); sObjectMgr->LoadItemLocales(); handler->SendGlobalGMSysMessage("DB table `item_template_locale` reloaded."); return true; @@ -1108,7 +1108,7 @@ public: static bool HandleReloadLocalesItemSetNameCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Item set name Locale... "); + LOG_INFO("server.loading", "Reloading Item set name Locale... "); sObjectMgr->LoadItemSetNameLocales(); handler->SendGlobalGMSysMessage("DB table `item_set_name_locale` reloaded."); return true; @@ -1116,7 +1116,7 @@ public: static bool HandleReloadLocalesNpcTextCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading NPC Text Locale ... "); + LOG_INFO("server.loading", "Reloading NPC Text Locale ... "); sObjectMgr->LoadNpcTextLocales(); handler->SendGlobalGMSysMessage("DB table `npc_text_locale` reloaded."); return true; @@ -1124,7 +1124,7 @@ public: static bool HandleReloadLocalesPageTextCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Page Text Locale ... "); + LOG_INFO("server.loading", "Reloading Page Text Locale ... "); sObjectMgr->LoadPageTextLocales(); handler->SendGlobalGMSysMessage("DB table `page_text_locale` reloaded."); handler->SendGlobalGMSysMessage("You need to delete your client cache or change the cache number in config in order for your players see the changes."); @@ -1133,7 +1133,7 @@ public: static bool HandleReloadLocalesPointsOfInterestCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Points Of Interest Locale ... "); + LOG_INFO("server.loading", "Reloading Points Of Interest Locale ... "); sObjectMgr->LoadPointOfInterestLocales(); handler->SendGlobalGMSysMessage("DB table `points_of_interest_locale` reloaded."); return true; @@ -1141,7 +1141,7 @@ public: static bool HandleReloadLocalesQuestCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Locales Quest ... "); + LOG_INFO("server.loading", "Reloading Locales Quest ... "); sObjectMgr->LoadQuestLocales(); handler->SendGlobalGMSysMessage("DB table `quest_template_locale` reloaded."); return true; @@ -1149,7 +1149,7 @@ public: static bool HandleReloadLocalesQuestOfferRewardCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Quest Offer Reward Locale... "); + LOG_INFO("server.loading", "Reloading Quest Offer Reward Locale... "); sObjectMgr->LoadQuestOfferRewardLocale(); handler->SendGlobalGMSysMessage("DB table `quest_offer_reward_locale` reloaded."); return true; @@ -1157,7 +1157,7 @@ public: static bool HandleReloadLocalesQuestRequestItemsCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Quest Request Item Locale... "); + LOG_INFO("server.loading", "Reloading Quest Request Item Locale... "); sObjectMgr->LoadQuestRequestItemsLocale(); handler->SendGlobalGMSysMessage("DB table `quest_request_item_locale` reloaded."); return true; @@ -1165,7 +1165,7 @@ public: static bool HandleReloadMailLevelRewardCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Player level dependent mail rewards..."); + LOG_INFO("server.loading", "Reloading Player level dependent mail rewards..."); sObjectMgr->LoadMailLevelRewards(); handler->SendGlobalGMSysMessage("DB table `mail_level_reward` reloaded."); return true; @@ -1173,7 +1173,7 @@ public: static bool HandleReloadMailServerTemplateCommand(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading `server_mail_template` table"); + LOG_INFO("server.loading", "Reloading `server_mail_template` table"); sObjectMgr->LoadMailServerTemplates(); handler->SendGlobalGMSysMessage("DB table `server_mail_template` reloaded."); return true; @@ -1182,7 +1182,7 @@ public: static bool HandleReloadAuctionsCommand(ChatHandler* handler) { ///- Reload dynamic data tables from the database - LOG_INFO("server.loading", "Re-Loading Auctions..."); + LOG_INFO("server.loading", "Reloading Auctions..."); sAuctionMgr->LoadAuctionItems(); sAuctionMgr->LoadAuctions(); handler->SendGlobalGMSysMessage("Auctions reloaded."); @@ -1191,7 +1191,7 @@ public: static bool HandleReloadConditions(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Conditions..."); + LOG_INFO("server.loading", "Reloading Conditions..."); sConditionMgr->LoadConditions(true); handler->SendGlobalGMSysMessage("Conditions reloaded."); return true; @@ -1199,7 +1199,7 @@ public: static bool HandleReloadCreatureText(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Creature Texts..."); + LOG_INFO("server.loading", "Reloading Creature Texts..."); sCreatureTextMgr->LoadCreatureTexts(); handler->SendGlobalGMSysMessage("Creature Texts reloaded."); return true; @@ -1207,7 +1207,7 @@ public: static bool HandleReloadSmartScripts(ChatHandler* handler) { - LOG_INFO("server.loading", "Re-Loading Smart Scripts..."); + LOG_INFO("server.loading", "Reloading Smart Scripts..."); sSmartScriptMgr->LoadSmartAIFromDB(); handler->SendGlobalGMSysMessage("Smart Scripts reloaded."); return true; diff --git a/src/server/scripts/Commands/cs_server.cpp b/src/server/scripts/Commands/cs_server.cpp index 9df570105..0c1087436 100644 --- a/src/server/scripts/Commands/cs_server.cpp +++ b/src/server/scripts/Commands/cs_server.cpp @@ -244,23 +244,17 @@ public: handler->PSendSysMessage("LoginDatabase queue size: %zu", LoginDatabase.QueueSize()); handler->PSendSysMessage("CharacterDatabase queue size: %zu", CharacterDatabase.QueueSize()); handler->PSendSysMessage("WorldDatabase queue size: %zu", WorldDatabase.QueueSize()); - - if (Acore::Module::GetEnableModulesList().empty()) - handler->SendSysMessage("No modules enabled"); - else - handler->SendSysMessage("> List enable modules:"); #ifdef MOD_PLAYERBOTS handler->PSendSysMessage("PlayerbotsDatabase queue size: %zu", PlayerbotsDatabase.QueueSize()); #endif if (Acore::Module::GetEnableModulesList().empty()) - handler->SendSysMessage("No modules enabled"); + handler->SendSysMessage("No modules are enabled"); else - handler->SendSysMessage("> List enable modules:"); - + handler->SendSysMessage("List of enabled modules:"); for (auto const& modName : Acore::Module::GetEnableModulesList()) { - handler->SendSysMessage(Acore::StringFormatFmt("- {}", modName)); + handler->SendSysMessage(Acore::StringFormatFmt("|- {}", modName)); } return true; @@ -283,9 +277,9 @@ public: handler->PSendSysMessage("Connection peak: %u.", connPeak); handler->PSendSysMessage(LANG_UPTIME, secsToTimeString(GameTime::GetUptime().count()).c_str()); handler->PSendSysMessage("Update time diff: %ums. Last %d diffs summary:", sWorldUpdateTime.GetLastUpdateTime(), sWorldUpdateTime.GetDatasetSize()); - handler->PSendSysMessage("- Mean: %ums", sWorldUpdateTime.GetAverageUpdateTime()); - handler->PSendSysMessage("- Median: %ums", sWorldUpdateTime.GetPercentile(50)); - handler->PSendSysMessage("- Percentiles (95, 99, max): %ums, %ums, %ums", + handler->PSendSysMessage("|- Mean: %ums", sWorldUpdateTime.GetAverageUpdateTime()); + handler->PSendSysMessage("|- Median: %ums", sWorldUpdateTime.GetPercentile(50)); + handler->PSendSysMessage("|- Percentiles (95, 99, max): %ums, %ums, %ums", sWorldUpdateTime.GetPercentile(95), sWorldUpdateTime.GetPercentile(99), sWorldUpdateTime.GetPercentile(100)); diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp index c63797afa..e586d9ecf 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp @@ -73,7 +73,11 @@ enum Spells SPELL_SHADOW_PYRO = 29978, - SPELL_ATIESH_VISUAL = 31796 + SPELL_ATIESH_VISUAL = 31796, + + SPELL_CURSE_OF_TONGUE_RANK1 = 1714, + SPELL_CURSE_OF_TONGUE_RANK2 = 11719, + SPELL_MIND_NUMBING_POISON = 5760 }; enum Creatures @@ -100,6 +104,8 @@ enum Misc Position const roomCenter = {-11158.f, -1920.f}; +std::vector immuneSpells = { SPELL_CURSE_OF_TONGUE_RANK1, SPELL_CURSE_OF_TONGUE_RANK2, SPELL_MIND_NUMBING_POISON }; + struct boss_shade_of_aran : public BossAI { boss_shade_of_aran(Creature* creature) : BossAI(creature, DATA_ARAN), _atieshReaction(false) { } @@ -118,6 +124,9 @@ struct boss_shade_of_aran : public BossAI _drinking = false; _hasDrunk = false; + for (int i = 0; i < immuneSpells.size(); i++) + me->ApplySpellImmune(0, IMMUNITY_ID, immuneSpells[i], true); + if (GameObject* libraryDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_GO_LIBRARY_DOOR))) { libraryDoor->SetGoState(GO_STATE_ACTIVE); diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp index 5631b5edc..af0e1e19d 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp @@ -46,19 +46,6 @@ enum Spells SPELL_DEAFENINGROAR = 42398 }; -// Trash Waves -float NalorakkWay[8][3] = -{ - { 18.569f, 1414.512f, 11.42f}, // waypoint 1 - {-17.264f, 1419.551f, 12.62f}, - {-52.642f, 1419.357f, 27.31f}, // waypoint 2 - {-69.908f, 1419.721f, 27.31f}, - {-79.929f, 1395.958f, 27.31f}, - {-80.072f, 1374.555f, 40.87f}, // waypoint 3 - {-80.072f, 1314.398f, 40.87f}, - {-80.072f, 1295.775f, 48.60f} // waypoint 4 -}; - enum Talks { SAY_WAVE1 = 0, @@ -74,399 +61,300 @@ enum Talks SAY_KILL_TWO, SAY_DEATH, SAY_NALORAKK_EVENT1, // Not implemented - SAY_NALORAKK_EVENT2 // Not implemented + SAY_NALORAKK_EVENT2, // Not implemented + SAY_RUN_AWAY, + EMOTE_BEAR }; -class boss_nalorakk : public CreatureScript +enum Phases { -public: - boss_nalorakk() - : CreatureScript("boss_nalorakk") + PHASE_SEND_GUARDS_1 = 0, + PHASE_SEND_GUARDS_2 = 1, + PHASE_SEND_GUARDS_3 = 2, + PHASE_SEND_GUARDS_4 = 3, + PHASE_SEND_GUARDS_5 = 4, + PHASE_START_COMBAT = 5 +}; + +enum NalorakkGroups +{ + GROUP_CHECK_DEAD = 1, + GROUP_MOVE = 2, + GROUP_BERSERK = 3, + GROUP_HUMAN = 4, + GROUP_BEAR = 5 +}; + +struct boss_nalorakk : public BossAI +{ + boss_nalorakk(Creature* creature) : BossAI(creature, DATA_NALORAKKEVENT) { + _ranIntro = false; + _active = true; + creature->SetReactState(REACT_PASSIVE); + me->SetImmuneToAll(true); } - struct boss_nalorakkAI : public ScriptedAI + void Reset() override { - boss_nalorakkAI(Creature* creature) : ScriptedAI(creature) + BossAI::Reset(); + _waveList.clear(); + _introScheduler.CancelAll(); + if (_bearForm) { - MoveEvent = true; - MovePhase = 0; - instance = creature->GetInstanceScript(); + me->RemoveAurasDueToSpell(SPELL_BEARFORM); + _bearForm = false; } - - InstanceScript* instance; - - uint32 BrutalSwipe_Timer; - uint32 Mangle_Timer; - uint32 Surge_Timer; - - uint32 LaceratingSlash_Timer; - uint32 RendFlesh_Timer; - uint32 DeafeningRoar_Timer; - - uint32 ShapeShift_Timer; - uint32 Berserk_Timer; - - bool inBearForm; - bool MoveEvent; - bool inMove; - uint32 MovePhase; - uint32 waitTimer; - - void Reset() override + if (_ranIntro) { - if (MoveEvent) - { - me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - inMove = false; - waitTimer = 0; - me->SetSpeed(MOVE_RUN, 2); - me->SetWalk(false); - ResetMobs(); - } - else - { - (*me).GetMotionMaster()->MovePoint(0, NalorakkWay[7][0], NalorakkWay[7][1], NalorakkWay[7][2]); - } + _phase = PHASE_START_COMBAT; + me->SetReactState(REACT_AGGRESSIVE); + _active = false; - if (instance) - { - instance->SetData(DATA_NALORAKKEVENT, NOT_STARTED); - } - - Surge_Timer = urand(15000, 20000); - BrutalSwipe_Timer = urand(7000, 12000); - Mangle_Timer = urand(10000, 15000); - ShapeShift_Timer = urand(45000, 50000); - Berserk_Timer = 600000; - - inBearForm = false; - // me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122); /// @todo find the correct equipment id } + } - void ResetMobs() + void MoveInLineOfSight(Unit* who) override + { + if (who->IsPlayer() && _phase < PHASE_START_COMBAT && _active) { - std::list templist; - float x, y, z; - me->GetPosition(x, y, z); - + _active = false; + switch (_phase) { - CellCoord pair(Acore::ComputeCellCoord(x, y)); - Cell cell(pair); - cell.SetNoCreate(); - - Acore::AllFriendlyCreaturesInGrid check(me); - Acore::CreatureListSearcher searcher(me, templist, check); - - TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); - - cell.Visit(pair, cSearcher, *(me->GetMap()), *me, me->GetGridActivationRange()); - } - - if (templist.empty()) - return; - - for (std::list::const_iterator i = templist.begin(); i != templist.end(); ++i) - if ((*i) && me->GetGUID() != (*i)->GetGUID() && me->IsWithinDistInMap((*i), 25)) - (*i)->AI()->Reset(); - } - - void SendAttacker(Unit* target) - { - std::list templist; - float x, y, z; - me->GetPosition(x, y, z); - - { - CellCoord pair(Acore::ComputeCellCoord(x, y)); - Cell cell(pair); - cell.SetNoCreate(); - - Acore::AllFriendlyCreaturesInGrid check(me); - Acore::CreatureListSearcher searcher(me, templist, check); - - TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); - - cell.Visit(pair, cSearcher, *(me->GetMap()), *me, me->GetGridActivationRange()); - } - - if (templist.empty()) - return; - - for (std::list::const_iterator i = templist.begin(); i != templist.end(); ++i) - { - if ((*i) && me->IsWithinDistInMap((*i), 25)) - { - (*i)->SetNoCallAssistance(true); - (*i)->AI()->AttackStart(target); - } - } - } - - void AttackStart(Unit* who) override - { - if (!MoveEvent) - ScriptedAI::AttackStart(who); - } - - void MoveInLineOfSight(Unit* who) override - - { - if (!MoveEvent) - { - ScriptedAI::MoveInLineOfSight(who); - } - else - { - if (me->IsHostileTo(who)) - { - if (!inMove) + case PHASE_SEND_GUARDS_1: + me->GetCreaturesWithEntryInRange(_waveList, 10.0f, NPC_AMANISHI_AXE_THROWER); + me->GetCreaturesWithEntryInRange(_waveList, 10.0f, NPC_AMANISHI_TRIBESMAN); + GroupedAttack(_waveList); + Talk(SAY_WAVE1); + _introScheduler.Schedule(5s, GROUP_CHECK_DEAD, [this](TaskContext context) { - switch (MovePhase) + if (CheckFullyDeadGroup(_waveList)) { - case 0: - if (me->IsWithinDistInMap(who, 50)) + if (_phase == PHASE_SEND_GUARDS_1) + { + _introScheduler.CancelGroup(GROUP_CHECK_DEAD); + _waveList.clear(); + me->GetMotionMaster()->MovePath(me->GetEntry()*100+1, false); + Talk(SAY_RUN_AWAY); + _introScheduler.Schedule(5s, [this](TaskContext) { - Talk(SAY_WAVE1); - - (*me).GetMotionMaster()->MovePoint(1, NalorakkWay[1][0], NalorakkWay[1][1], NalorakkWay[1][2]); - MovePhase ++; - inMove = true; - - SendAttacker(who); - } - break; - case 2: - if (me->IsWithinDistInMap(who, 40)) - { - Talk(SAY_WAVE2); - - (*me).GetMotionMaster()->MovePoint(3, NalorakkWay[3][0], NalorakkWay[3][1], NalorakkWay[3][2]); - MovePhase ++; - inMove = true; - - SendAttacker(who); - } - break; - case 5: - if (me->IsWithinDistInMap(who, 40)) - { - Talk(SAY_WAVE3); - - (*me).GetMotionMaster()->MovePoint(6, NalorakkWay[6][0], NalorakkWay[6][1], NalorakkWay[6][2]); - MovePhase ++; - inMove = true; - - SendAttacker(who); - } - break; - case 7: - if (me->IsWithinDistInMap(who, 50)) - { - SendAttacker(who); - - Talk(SAY_WAVE4); - - me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - - MoveEvent = false; - } - break; + me->SetFacingTo(6.25f); + _active = true; + }); + _phase = PHASE_SEND_GUARDS_2; + } } - } - } - } - } - - void JustEngagedWith(Unit* /*who*/) override - { - if (instance) - instance->SetData(DATA_NALORAKKEVENT, IN_PROGRESS); - - Talk(SAY_AGGRO); - DoZoneInCombat(); - } - - void JustDied(Unit* /*killer*/) override - { - ResetMobs(); - - if (instance) - instance->SetData(DATA_NALORAKKEVENT, DONE); - - Talk(SAY_DEATH); - } - - void KilledUnit(Unit* /*victim*/) override - { - switch (urand(0, 1)) - { - case 0: - Talk(SAY_KILL_ONE); + context.Repeat(5s); + }); break; - case 1: - Talk(SAY_KILL_TWO); - break; - } - } - - void MovementInform(uint32 type, uint32 id) override - { - if (MoveEvent) - { - if (type != POINT_MOTION_TYPE) - return; - - if (!inMove) - return; - - if (MovePhase != id) - return; - - switch (MovePhase) - { - case 2: - me->SetOrientation(3.1415f * 2); - inMove = false; - return; - case 1: - case 3: - case 4: - case 6: - MovePhase ++; - waitTimer = 1; - inMove = true; - return; - case 5: - me->SetOrientation(3.1415f * 0.5f); - inMove = false; - return; - case 7: - me->SetOrientation(3.1415f * 0.5f); - inMove = false; - return; - } - } - } - - void UpdateAI(uint32 diff) override - { - if (waitTimer && inMove) - { - if (waitTimer <= diff) - { - (*me).GetMotionMaster()->MovementExpired(); - (*me).GetMotionMaster()->MovePoint(MovePhase, NalorakkWay[MovePhase][0], NalorakkWay[MovePhase][1], NalorakkWay[MovePhase][2]); - waitTimer = 0; - } - else waitTimer -= diff; - } - - if (!UpdateVictim()) - return; - - if (Berserk_Timer <= diff) - { - DoCast(me, SPELL_BERSERK, true); - Talk(SAY_BERSERK); - Berserk_Timer = 600000; - } - else Berserk_Timer -= diff; - - if (ShapeShift_Timer <= diff) - { - if (inBearForm) - { - // me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122); - Talk(SAY_SHIFTEDTOTROLL); - me->RemoveAurasDueToSpell(SPELL_BEARFORM); - Surge_Timer = urand(15000, 20000); - BrutalSwipe_Timer = urand(7000, 12000); - Mangle_Timer = urand(10000, 15000); - ShapeShift_Timer = urand(45000, 50000); - inBearForm = false; - } - else - { - // me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 0); - Talk(SAY_SHIFTEDTOBEAR); - DoCast(me, SPELL_BEARFORM, true); - LaceratingSlash_Timer = 2000; // dur 18s - RendFlesh_Timer = 3000; // dur 5s - DeafeningRoar_Timer = urand(5000, 10000); // dur 2s - ShapeShift_Timer = urand(20000, 25000); // dur 30s - inBearForm = true; - } - } - else ShapeShift_Timer -= diff; - - if (!inBearForm) - { - if (BrutalSwipe_Timer <= diff) - { - DoCastVictim(SPELL_BRUTALSWIPE); - BrutalSwipe_Timer = urand(7000, 12000); - } - else BrutalSwipe_Timer -= diff; - - if (Mangle_Timer <= diff) - { - if (me->GetVictim() && !me->GetVictim()->HasAura(SPELL_MANGLEEFFECT)) + case PHASE_SEND_GUARDS_2: + me->GetCreaturesWithEntryInRange(_waveList, 10.0f, NPC_AMANISHI_AXE_THROWER); + me->GetCreaturesWithEntryInRange(_waveList, 10.0f, NPC_AMANISHI_TRIBESMAN); + me->GetCreaturesWithEntryInRange(_waveList, 10.0f, NPC_AMANISHI_MEDICINE_MAN); + GroupedAttack(_waveList); + Talk(SAY_WAVE2); + _introScheduler.Schedule(5s, GROUP_CHECK_DEAD, [this](TaskContext context) { - DoCastVictim(SPELL_MANGLE); - Mangle_Timer = 1000; - } - else Mangle_Timer = urand(10000, 15000); - } - else Mangle_Timer -= diff; + if (CheckFullyDeadGroup(_waveList)) + { + if (_phase == PHASE_SEND_GUARDS_2) + { + _introScheduler.CancelGroup(GROUP_CHECK_DEAD); + _waveList.clear(); + Talk(SAY_RUN_AWAY); + me->GetMotionMaster()->MovePath(me->GetEntry()*100+2, false); + _introScheduler.Schedule(6s, [this](TaskContext) + { + me->SetFacingTo(1.54f); + _active = true; + }); + _phase = PHASE_SEND_GUARDS_3; + } - if (Surge_Timer <= diff) - { - Talk(SAY_SURGE); - Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 45, true); - if (target) - DoCast(target, SPELL_SURGE); - Surge_Timer = urand(15000, 20000); - } - else Surge_Timer -= diff; + } + context.Repeat(5s); + }); + break; + case PHASE_SEND_GUARDS_3: + me->GetCreaturesWithEntryInRange(_waveList, 10.0f, NPC_AMANISHI_WARBRINGER); + GroupedAttack(_waveList); + Talk(SAY_WAVE3); + _introScheduler.Schedule(5s, GROUP_CHECK_DEAD, [this](TaskContext context) + { + if (CheckFullyDeadGroup(_waveList)) + { + if (_phase == PHASE_SEND_GUARDS_3) + { + _introScheduler.CancelGroup(GROUP_CHECK_DEAD); + _waveList.clear(); + Talk(SAY_RUN_AWAY); + me->GetMotionMaster()->MovePath(me->GetEntry()*100+3, false); + _introScheduler.Schedule(6s, [this](TaskContext) + { + me->SetFacingTo(1.54f); + _active = true; + }); + _phase = PHASE_SEND_GUARDS_4; + } + } + context.Repeat(5s); + }); + break; + case PHASE_SEND_GUARDS_4: + me->GetCreaturesWithEntryInRange(_waveList, 25.0f, NPC_AMANISHI_WARBRINGER); + me->GetCreaturesWithEntryInRange(_waveList, 25.0f, NPC_AMANISHI_MEDICINE_MAN); + GroupedAttack(_waveList); + Talk(SAY_WAVE4); + _introScheduler.Schedule(5s, GROUP_CHECK_DEAD, [this](TaskContext context) + { + if (CheckFullyDeadGroup(_waveList)) + { + if (_phase == PHASE_SEND_GUARDS_4) + { + _introScheduler.CancelGroup(GROUP_CHECK_DEAD); + me->SetHomePosition(me->GetPosition()); + me->SetImmuneToAll(false); + me->SetReactState(REACT_AGGRESSIVE); + me->SetInCombatWithZone(); + _waveList.clear(); + _phase = PHASE_START_COMBAT; + _ranIntro = true; + } + } + context.Repeat(5s); + }); + break; + } + } + BossAI::MoveInLineOfSight(who); + } + + void JustEngagedWith(Unit* who) override + { + BossAI::JustEngagedWith(who); + Talk(SAY_AGGRO); + scheduler.Schedule(15s, 20s, GROUP_HUMAN, [this](TaskContext context) + { + Talk(SAY_SURGE); + DoCastRandomTarget(SPELL_SURGE, 0, 45.0f, false, false, false); + context.Repeat(); + }).Schedule(7s, 12s, GROUP_HUMAN, [this](TaskContext context) + { + DoCastVictim(SPELL_BRUTALSWIPE); + context.Repeat(); + }).Schedule(10s, 15s, GROUP_HUMAN, [this](TaskContext context) + { + if (!me->GetVictim()->HasAura(SPELL_MANGLEEFFECT)) + { + DoCastVictim(SPELL_MANGLE); + context.Repeat(1s); } else { - if (LaceratingSlash_Timer <= diff) - { - DoCastVictim(SPELL_LACERATINGSLASH); - LaceratingSlash_Timer = urand(18000, 23000); - } - else LaceratingSlash_Timer -= diff; - - if (RendFlesh_Timer <= diff) - { - DoCastVictim(SPELL_RENDFLESH); - RendFlesh_Timer = urand(5000, 10000); - } - else RendFlesh_Timer -= diff; - - if (DeafeningRoar_Timer <= diff) - { - DoCastVictim(SPELL_DEAFENINGROAR); - DeafeningRoar_Timer = urand(15000, 20000); - } - else DeafeningRoar_Timer -= diff; + context.Repeat(); } - - DoMeleeAttackIfReady(); - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetZulAmanAI(creature); + }).Schedule(10min, GROUP_BERSERK, [this](TaskContext) + { + Talk(SAY_BERSERK); + DoCastSelf(SPELL_BERSERK, true); + }).Schedule(45s, 50s, GROUP_HUMAN, [this](TaskContext) + { + ShapeShift(_bearForm); + }); } + + void ShapeShift(bool currentlyInBearForm) + { + if (currentlyInBearForm) + { + Talk(SAY_SHIFTEDTOTROLL); + me->RemoveAurasDueToSpell(SPELL_BEARFORM); + scheduler.CancelGroup(GROUP_BEAR); + _bearForm = false; + scheduler.Schedule(15s, 20s, GROUP_HUMAN, [this](TaskContext context) + { + Talk(SAY_SURGE); + DoCastRandomTarget(SPELL_SURGE, 0, 45.0f, false, false, false); + context.Repeat(); + }).Schedule(7s, 12s, GROUP_HUMAN, [this](TaskContext context) + { + DoCastVictim(SPELL_BRUTALSWIPE); + context.Repeat(); + }).Schedule(10s, 15s, GROUP_HUMAN, [this](TaskContext context) + { + DoCastVictim(SPELL_MANGLE); + context.Repeat(); + }).Schedule(10min, GROUP_BERSERK, [this](TaskContext) + { + Talk(SAY_BERSERK); + DoCastSelf(SPELL_BERSERK, true); + }).Schedule(45s, 50s, GROUP_HUMAN, [this](TaskContext) + { + ShapeShift(_bearForm); + }); + } + else + { + Talk(SAY_SHIFTEDTOBEAR); + Talk(EMOTE_BEAR); + DoCastSelf(SPELL_BEARFORM, true); + scheduler.CancelGroup(GROUP_HUMAN); + _bearForm = true; + scheduler.Schedule(2s, GROUP_BEAR, [this](TaskContext context) + { + DoCastVictim(SPELL_LACERATINGSLASH); + context.Repeat(18s, 23s); + }).Schedule(3s, GROUP_BEAR, [this](TaskContext context) + { + DoCastVictim(SPELL_RENDFLESH); + context.Repeat(5s, 10s); + }).Schedule(5s, 10s, GROUP_BEAR, [this](TaskContext context) + { + DoCastSelf(SPELL_DEAFENINGROAR); + context.Repeat(15s, 20s); + }).Schedule(25s, 30s, GROUP_BEAR, [this](TaskContext context) + { + ShapeShift(_bearForm); + context.Repeat(); + }); + } + } + + void GroupedAttack(std::list attackerList) + { + for (Creature* attacker : attackerList) + { + attacker->SetInCombatWithZone(); + } + } + + void UpdateAI(uint32 diff) override + { + _introScheduler.Update(diff); + BossAI::UpdateAI(diff); + } + + bool CheckFullyDeadGroup(std::list groupToCheck) + { + for (Creature* member : groupToCheck) + { + if (member->IsAlive()) + { + return false; + } + } + return true; + } +private: + uint8 _phase; + bool _ranIntro; + bool _active; + bool _bearForm; + TaskScheduler _introScheduler; + std::list _waveList; }; void AddSC_boss_nalorakk() { - new boss_nalorakk(); + RegisterZulAmanCreatureAI(boss_nalorakk); } diff --git a/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp b/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp index baa83f557..ffb1b771b 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp @@ -57,8 +57,8 @@ Position const HarrisonJonesLoc = {120.687f, 1674.0f, 42.0217f, 1.59044f}; ObjectData const creatureData[] = { - { NPC_SPIRIT_LYNX, DATA_SPIRIT_LYNX }, - { 0, 0 } + { NPC_SPIRIT_LYNX, DATA_SPIRIT_LYNX }, + { 0, 0 } }; ObjectData const gameObjectData[] = diff --git a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.h b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.h index 4ca81145b..caf94bfc2 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.h +++ b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.h @@ -46,7 +46,11 @@ enum CreatureIds NPC_HEXLORD = 24239, NPC_HALAZZI = 23577, NPC_NALORAKK = 23576, - NPC_SPIRIT_LYNX = 24143 + NPC_SPIRIT_LYNX = 24143, + NPC_AMANISHI_WARBRINGER = 23580, + NPC_AMANISHI_TRIBESMAN = 23582, + NPC_AMANISHI_MEDICINE_MAN = 23581, + NPC_AMANISHI_AXE_THROWER = 23542 }; enum GameobjectIds diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp index cdf4fc11a..6b5fae927 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp @@ -18,6 +18,7 @@ #include "CreatureScript.h" #include "Player.h" #include "ScriptedCreature.h" +#include "SpellAuraEffects.h" #include "SpellAuras.h" #include "SpellScript.h" #include "SpellScriptLoader.h" @@ -51,6 +52,7 @@ enum ArchiSpells SPELL_DOOMFIRE_STRIKE = 31903, //summons two creatures SPELL_DOOMFIRE_SPAWN = 32074, SPELL_DOOMFIRE = 31945, + SPELL_DOOMFIRE_DOT = 31969, SPELL_SOUL_CHARGE_YELLOW = 32045, SPELL_SOUL_CHARGE_GREEN = 32051, SPELL_SOUL_CHARGE_RED = 32052, @@ -143,35 +145,37 @@ struct npc_doomfire_spirit : public ScriptedAI { npc_doomfire_spirit(Creature* creature) : ScriptedAI(creature){ } + float const turnConstant = 0.785402f; + float fAngle = urand(0, M_PI * 2); + void Reset() override { scheduler.CancelAll(); ScheduleTimedEvent(0s, [&] { - me->GetMotionMaster()->MovePoint(NEAR_POINT, DoomfireMovement(me->GetPosition())); - }, 1500ms); + float nextOrientation = Position::NormalizeOrientation(me->GetOrientation() + irand(-1, 1) * turnConstant); + Position pos = GetFirstRandomAngleCollisionPosition(8.f, nextOrientation); // both orientation and distance verified with sniffs + me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), nextOrientation); + }, 1600ms); + + fAngle = urand(0, M_PI * 2); } - Position DoomfireMovement(Position mePos) + Position GetFirstRandomAngleCollisionPosition(float dist, float angle) { - float angle = mePos.GetOrientation(); - float distance = 100.0f; - float newAngle = angle + ((rand() % 181) - 90) * M_PI / 180; - float x = mePos.GetPositionX() + distance * cos(newAngle); - float y = mePos.GetPositionY() + distance * sin(newAngle); - - Position targetPos = Position(x, y, me->GetPositionZ()); - return targetPos; + Position pos; + for (uint32 i = 0; i < 10; ++i) + { + pos = me->WorldObject::GetFirstCollisionPosition(dist, angle); + if (me->GetDistance(pos) > dist * 0.8f) // if at least 80% distance, good enough + break; + angle += (M_PI / 5); // else try slightly different angle + } + return pos; } void UpdateAI(uint32 diff) override { scheduler.Update(diff); - - if (!UpdateVictim()) - return; - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; } }; @@ -313,7 +317,7 @@ struct boss_archimonde : public BossAI DoCastVictim(SPELL_RED_SKY_EFFECT); DoCastVictim(SPELL_HAND_OF_DEATH); }, 3s); - scheduler.Schedule(25s, 35s, GROUP_FEAR, [this](TaskContext context) + scheduler.Schedule(40s, GROUP_FEAR, [this](TaskContext context) { DoCastAOE(SPELL_FEAR); context.Repeat(42s); @@ -381,11 +385,6 @@ struct boss_archimonde : public BossAI summoned->CastSpell(summoned, SPELL_DOOMFIRE_SPAWN); summoned->CastSpell(summoned, SPELL_DOOMFIRE, true, 0, 0, me->GetGUID()); } - else if (summoned->GetEntry() == CREATURE_DOOMFIRE_SPIRIT) - { - Position randomPosition = summoned->GetRandomNearPosition(40.0f); - summoned->GetMotionMaster()->MovePoint(0, randomPosition); - } else { summoned->SetFaction(me->GetFaction()); //remove? @@ -487,10 +486,38 @@ class spell_air_burst : public SpellScript } }; +class spell_doomfire : public AuraScript +{ + PrepareAuraScript(spell_doomfire); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_DOOMFIRE_DOT }); + } + + void PeriodicTick(AuraEffect const* aurEff) + { + Unit* target = GetTarget(); + if (!target) + return; + + int32 bp = GetSpellInfo()->Effects[EFFECT_1].CalcValue(); + float tickCoef = (static_cast(aurEff->GetTickNumber() - 1) / aurEff->GetTotalTicks()); // Tick moved back to ensure proper damage on each tick + int32 damage = bp - (bp*tickCoef); + SpellCastResult result = target->CastCustomSpell(target, SPELL_DOOMFIRE_DOT, &damage, &damage, &damage, true, nullptr, nullptr, target->GetGUID()); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_doomfire::PeriodicTick, EFFECT_ALL, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } +}; + void AddSC_boss_archimonde() { RegisterSpellScript(spell_red_sky_effect); RegisterSpellScript(spell_air_burst); + RegisterSpellScript(spell_doomfire); RegisterHyjalAI(boss_archimonde); RegisterHyjalAI(npc_ancient_wisp); RegisterHyjalAI(npc_doomfire_spirit); diff --git a/src/server/scripts/Northrend/Naxxramas/boss_razuvious.h b/src/server/scripts/Northrend/Naxxramas/boss_razuvious.h index ceb3f0c91..3067078f6 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_razuvious.h +++ b/src/server/scripts/Northrend/Naxxramas/boss_razuvious.h @@ -7,36 +7,53 @@ namespace Razuvious { -enum RazuviousSays +enum Says { - RAZUVIOUS_SAY_AGGRO = 0, - RAZUVIOUS_SAY_SLAY = 1, - RAZUVIOUS_SAY_TAUNTED = 2, - RAZUVIOUS_SAY_DEATH = 3 + SAY_AGGRO = 0, + SAY_SLAY = 1, + SAY_TAUNTED = 2, + SAY_DEATH = 3, + SAY_PATHETIC = 4, + SAY_TARGET_DUMMY = 5, + SAY_DEATH_KNIGHT_UNDERSTUDY = 0, }; -enum RazuviousSpells +enum Spells { SPELL_UNBALANCING_STRIKE = 26613, SPELL_DISRUPTING_SHOUT_10 = 55543, SPELL_DISRUPTING_SHOUT_25 = 29107, SPELL_JAGGED_KNIFE = 55550, SPELL_HOPELESS = 29125, - - RAZUVIOUS_SPELL_TAUNT = 29060 + SPELL_TAUNT = 29060 }; -enum RazuviousEvents +enum Events { EVENT_UNBALANCING_STRIKE = 1, EVENT_DISRUPTING_SHOUT = 2, EVENT_JAGGED_KNIFE = 3 }; -enum RazuviousMisc +enum NPCs { NPC_DEATH_KNIGHT_UNDERSTUDY = 16803, - NPC_RAZUVIOUS = 16061 + NPC_TARGET_DUMMY = 16211, +}; + +enum Actions +{ + ACTION_FACE_ME = 0, + ACTION_TALK = 1, + ACTION_EMOTE = 2, + ACTION_SALUTE = 3, + ACTION_BACK_TO_TRAINING = 4, +}; + +enum Misc +{ + GROUP_OOC_RP = 0, + POINT_DEATH_KNIGHT = 0, }; class boss_razuvious : public CreatureScript @@ -82,13 +99,106 @@ public: summons.DespawnAll(); events.Reset(); SpawnHelpers(); + ScheduleRP(); + } + + void ScheduleInteractWithDeathKnight() + { + if (_rpBuddyGUID) + if (Creature* understudy = ObjectAccessor::GetCreature(*me, _rpBuddyGUID)) + me->SetFacingToObject(understudy); + + scheduler.Schedule(2s, GROUP_OOC_RP, [this](TaskContext /*context*/) + { + if (roll_chance_i(75)) + { + bool longText = roll_chance_i(50); + Talk(longText ? SAY_TARGET_DUMMY : SAY_PATHETIC); + scheduler.Schedule(4s, GROUP_OOC_RP, [this](TaskContext /*context*/) + { + if (_rpBuddyGUID) + if (Creature* understudy = ObjectAccessor::GetCreature(*me, _rpBuddyGUID)) + understudy->AI()->DoAction(ACTION_TALK); + }); + if (longText) + scheduler.DelayGroup(GROUP_OOC_RP, 5s); + } + else + { + me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); + scheduler.Schedule(4s, GROUP_OOC_RP, [this](TaskContext /*context*/) + { + if (_rpBuddyGUID) + if (Creature* understudy = ObjectAccessor::GetCreature(*me, _rpBuddyGUID)) + { + if (roll_chance_i(25)) + understudy->AI()->DoAction(ACTION_EMOTE); + else + understudy->AI()->DoAction(ACTION_TALK); + } + }); + } + }).Schedule(4s, GROUP_OOC_RP, [this](TaskContext /*context*/) + { + if (_rpBuddyGUID) + if (Creature* understudy = ObjectAccessor::GetCreature(*me, _rpBuddyGUID)) + understudy->AI()->DoAction(ACTION_FACE_ME); + }).Schedule(10s, GROUP_OOC_RP, [this](TaskContext /*context*/) + { + if (_rpBuddyGUID) + if (Creature* understudy = ObjectAccessor::GetCreature(*me, _rpBuddyGUID)) + understudy->AI()->DoAction(ACTION_SALUTE); + }).Schedule(13s, GROUP_OOC_RP, [this](TaskContext /*context*/) + { + me->ResumeMovement(); + }).Schedule(16s, GROUP_OOC_RP, [this](TaskContext /*context*/) + { + if (_rpBuddyGUID) + if (Creature* understudy = ObjectAccessor::GetCreature(*me, _rpBuddyGUID)) + understudy->AI()->DoAction(ACTION_BACK_TO_TRAINING); + ScheduleRP(); + }); + } + + void MovementInform(uint32 type, uint32 id) override + { + if (type == POINT_MOTION_TYPE && id == POINT_DEATH_KNIGHT) + { + ScheduleInteractWithDeathKnight(); + } + } + + void ScheduleRP() + { + _rpBuddyGUID = Acore::Containers::SelectRandomContainerElement(summons); + scheduler.Schedule(60s, 80s, GROUP_OOC_RP, [this](TaskContext context) + { + if (_rpBuddyGUID) + { + if (Creature* understudy = ObjectAccessor::GetCreature(*me, _rpBuddyGUID)) + { + if (me->GetDistance2d(understudy) <= 6.0f) + { + me->PauseMovement(); + scheduler.Schedule(500ms, GROUP_OOC_RP, [this](TaskContext /*context*/) + { + if (_rpBuddyGUID) + if (Creature* understudy = ObjectAccessor::GetCreature(*me, _rpBuddyGUID)) + me->GetMotionMaster()->MovePoint(POINT_DEATH_KNIGHT, understudy->GetNearPosition(3.2f, understudy->GetRelativeAngle(me))); + }); + return; + } + } + } + context.Repeat(2s); + }); } void KilledUnit(Unit* who) override { if (roll_chance_i(30)) { - Talk(RAZUVIOUS_SAY_SLAY); + Talk(SAY_SLAY); } if (who->GetTypeId() == TYPEID_PLAYER && pInstance) { @@ -108,22 +218,23 @@ public: void JustDied(Unit* killer) override { BossAI::JustDied(killer); - Talk(RAZUVIOUS_SAY_DEATH); + Talk(SAY_DEATH); me->CastSpell(me, SPELL_HOPELESS, true); } void SpellHit(Unit* caster, SpellInfo const* spell) override { - if (spell->Id == RAZUVIOUS_SPELL_TAUNT) + if (spell->Id == SPELL_TAUNT) { - Talk(RAZUVIOUS_SAY_TAUNTED, caster); + Talk(SAY_TAUNTED, caster); } } void JustEngagedWith(Unit* who) override { BossAI::JustEngagedWith(who); - Talk(RAZUVIOUS_SAY_AGGRO); + scheduler.CancelGroup(GROUP_OOC_RP); + Talk(SAY_AGGRO); events.ScheduleEvent(EVENT_UNBALANCING_STRIKE, 20s); events.ScheduleEvent(EVENT_DISRUPTING_SHOUT, 15s); events.ScheduleEvent(EVENT_JAGGED_KNIFE, 10s); @@ -132,6 +243,9 @@ public: void UpdateAI(uint32 diff) override { + if (!me->IsInCombat()) + scheduler.Update(diff); + if (!UpdateVictim()) return; @@ -159,6 +273,9 @@ public: } DoMeleeAttackIfReady(); } + + private: + ObjectGuid _rpBuddyGUID; }; }; @@ -167,20 +284,65 @@ class boss_razuvious_minion : public CreatureScript public: boss_razuvious_minion() : CreatureScript("boss_razuvious_minion") { } - CreatureAI* GetAI(Creature* pCreature) const override + CreatureAI* GetAI(Creature* creature) const override { - return GetNaxxramasAI(pCreature); + return GetNaxxramasAI(creature); } struct boss_razuvious_minionAI : public ScriptedAI { - explicit boss_razuvious_minionAI(Creature* c) : ScriptedAI(c) { } - - EventMap events; + explicit boss_razuvious_minionAI(Creature* creature) : ScriptedAI(creature) { } void Reset() override { - events.Reset(); + scheduler.CancelAll(); + ScheduleAttackDummy(); + } + + void ScheduleAttackDummy() + { + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY1H); + if (Creature* targetDummy = me->FindNearestCreature(NPC_TARGET_DUMMY, 10.0f)) + { + me->SetFacingToObject(targetDummy); + } + scheduler.Schedule(6s, 9s, GROUP_OOC_RP, [this](TaskContext context) + { + me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACK1H); + context.Repeat(6s, 9s); + }); + } + + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_FACE_ME: + scheduler.CancelGroup(GROUP_OOC_RP); + me->SetSheath(SHEATH_STATE_UNARMED); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + if (InstanceScript* instance = me->GetInstanceScript()) + { + if (Creature* creature = instance->GetCreature(DATA_RAZUVIOUS)) + { + me->SetFacingToObject(creature); + } + } + break; + case ACTION_TALK: + Talk(SAY_DEATH_KNIGHT_UNDERSTUDY); + break; + case ACTION_EMOTE: + me->HandleEmoteCommand(EMOTE_ONESHOT_TALK); + break; + case ACTION_SALUTE: + me->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); + break; + case ACTION_BACK_TO_TRAINING: + me->SetSheath(SHEATH_STATE_MELEE); + ScheduleAttackDummy(); + break; + } } void KilledUnit(Unit* who) override @@ -193,18 +355,23 @@ public: void JustEngagedWith(Unit* who) override { - if (Creature* cr = me->FindNearestCreature(NPC_RAZUVIOUS, 100.0f)) + scheduler.CancelGroup(GROUP_OOC_RP); + if (InstanceScript* instance = me->GetInstanceScript()) { - cr->SetInCombatWithZone(); - cr->AI()->AttackStart(who); + if (Creature* creature = instance->GetCreature(DATA_RAZUVIOUS)) + { + creature->SetInCombatWithZone(); + creature->AI()->AttackStart(who); + } } } void UpdateAI(uint32 diff) override { + scheduler.Update(diff); + if (UpdateVictim()) { - events.Update(diff); if (!me->HasUnitState(UNIT_STATE_CASTING) || !me->IsCharmed()) { DoMeleeAttackIfReady(); diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp index 2f45192b7..431e5ae55 100644 --- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp +++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp @@ -52,6 +52,17 @@ inline uint8 GetEruptionSection(float x, float y) return 3; } +ObjectData const creatureData[] = +{ + { NPC_RAZUVIOUS, DATA_RAZUVIOUS }, + { 0, 0 } +}; + +ObjectData const gameObjectData[] = +{ + { 0, 0 } +}; + class instance_naxxramas : public InstanceMapScript { public: @@ -68,6 +79,7 @@ public: { SetHeaders(DataHeader); SetBossNumber(MAX_ENCOUNTERS); + LoadObjectData(creatureData, gameObjectData); for (auto& i : HeiganEruption) i.clear(); @@ -253,6 +265,8 @@ public: _lichkingGUID = creature->GetGUID(); return; } + + InstanceScript::OnCreatureCreate(creature); } void OnGameObjectCreate(GameObject* pGo) override @@ -498,6 +512,8 @@ public: } break; } + + InstanceScript::OnGameObjectCreate(pGo); } void OnGameObjectRemove(GameObject* pGo) override diff --git a/src/server/scripts/Northrend/Naxxramas/naxxramas.h b/src/server/scripts/Northrend/Naxxramas/naxxramas.h index 256ca8633..5c237d784 100644 --- a/src/server/scripts/Northrend/Naxxramas/naxxramas.h +++ b/src/server/scripts/Northrend/Naxxramas/naxxramas.h @@ -58,26 +58,27 @@ enum NXData DATA_STALAGG_BOSS = 108, DATA_FEUGEN_BOSS = 109, DATA_THADDIUS_GATE = 110, - DATA_GOTHIK_BOSS = 111, - DATA_GOTHIK_ENTER_GATE = 112, - DATA_GOTHIK_INNER_GATE = 113, - DATA_GOTHIK_EXIT_GATE = 114, - DATA_HORSEMEN_GATE = 115, - DATA_LICH_KING_BOSS = 116, - DATA_KELTHUZAD_FLOOR = 117, - DATA_ABOMINATION_KILLED = 118, - DATA_FRENZY_REMOVED = 119, - DATA_CHARGES_CROSSED = 120, - DATA_SPORE_KILLED = 121, - DATA_HUNDRED_CLUB = 122, - DATA_DANCE_FAIL = 123, - DATA_IMMORTAL_FAIL = 124, - DATA_KELTHUZAD_GATE = 125, - DATA_HAD_THADDIUS_GREET = 126, - DATA_KELTHUZAD_PORTAL_1 = 127, - DATA_KELTHUZAD_PORTAL_2 = 128, - DATA_KELTHUZAD_PORTAL_3 = 129, - DATA_KELTHUZAD_PORTAL_4 = 130 + DATA_RAZUVIOUS = 111, + DATA_GOTHIK_BOSS = 112, + DATA_GOTHIK_ENTER_GATE = 113, + DATA_GOTHIK_INNER_GATE = 114, + DATA_GOTHIK_EXIT_GATE = 115, + DATA_HORSEMEN_GATE = 116, + DATA_LICH_KING_BOSS = 117, + DATA_KELTHUZAD_FLOOR = 118, + DATA_ABOMINATION_KILLED = 119, + DATA_FRENZY_REMOVED = 120, + DATA_CHARGES_CROSSED = 121, + DATA_SPORE_KILLED = 122, + DATA_HUNDRED_CLUB = 123, + DATA_DANCE_FAIL = 124, + DATA_IMMORTAL_FAIL = 125, + DATA_KELTHUZAD_GATE = 126, + DATA_HAD_THADDIUS_GREET = 127, + DATA_KELTHUZAD_PORTAL_1 = 128, + DATA_KELTHUZAD_PORTAL_2 = 129, + DATA_KELTHUZAD_PORTAL_3 = 130, + DATA_KELTHUZAD_PORTAL_4 = 131 }; enum NXGOs @@ -137,6 +138,9 @@ enum NXNPCs NPC_STALAGG = 15929, NPC_FEUGEN = 15930, + // Razuvious + NPC_RAZUVIOUS = 16061, + // Four horseman NPC_BARON_RIVENDARE = 30549, NPC_SIR_ZELIEK = 16063, diff --git a/src/server/scripts/Northrend/zone_dalaran.cpp b/src/server/scripts/Northrend/zone_dalaran.cpp index 9085eeeb3..274748225 100644 --- a/src/server/scripts/Northrend/zone_dalaran.cpp +++ b/src/server/scripts/Northrend/zone_dalaran.cpp @@ -20,6 +20,7 @@ #include "Player.h" #include "ScriptedCreature.h" #include "ScriptedGossip.h" +#include "TaskScheduler.h" #include "World.h" // Ours @@ -506,108 +507,113 @@ enum MinigobData SPELL_IMPROVED_BLINK = 61995, EVENT_SELECT_TARGET = 1, - EVENT_BLINK = 2, - EVENT_DESPAWN_VISUAL = 3, - EVENT_DESPAWN = 4, + EVENT_POLYMORPH = 2, + EVENT_LAUGH = 3, + EVENT_MOVE = 4, + EVENT_DESPAWN_VISUAL = 5, + EVENT_DESPAWN = 6, MAIL_MINIGOB_ENTRY = 264, MAIL_DELIVER_DELAY_MIN = 5 * MINUTE, MAIL_DELIVER_DELAY_MAX = 15 * MINUTE }; -class npc_minigob_manabonk : public CreatureScript +struct npc_minigob_manabonk : public ScriptedAI { -public: - npc_minigob_manabonk() : CreatureScript("npc_minigob_manabonk") {} - - struct npc_minigob_manabonkAI : public ScriptedAI + npc_minigob_manabonk(Creature* creature) : ScriptedAI(creature) { - npc_minigob_manabonkAI(Creature* creature) : ScriptedAI(creature) - { - me->setActive(true); - } + me->setActive(true); + } - void Reset() override - { - me->SetVisible(false); - events.ScheduleEvent(EVENT_SELECT_TARGET, IN_MILLISECONDS); - } + void Reset() override + { + me->SetVisible(false); + events.ScheduleEvent(EVENT_SELECT_TARGET, 1s); + } - Player* SelectTargetInDalaran() - { - std::list PlayerInDalaranList; - PlayerInDalaranList.clear(); + Player* SelectTargetInDalaran() + { + std::list playerInDalaranList; + playerInDalaranList.clear(); - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - if (Player* player = itr->GetSource()->ToPlayer()) - if (player->GetZoneId() == ZONE_DALARAN && !player->IsFlying() && !player->IsMounted() && !player->IsGameMaster()) - PlayerInDalaranList.push_back(player); - - if (PlayerInDalaranList.empty()) - return nullptr; - return Acore::Containers::SelectRandomContainerElement(PlayerInDalaranList); - } - - void SendMailToPlayer(Player* player) - { - CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); - int16 deliverDelay = irand(MAIL_DELIVER_DELAY_MIN, MAIL_DELIVER_DELAY_MAX); - MailDraft(MAIL_MINIGOB_ENTRY, true).SendMailTo(trans, MailReceiver(player), MailSender(MAIL_CREATURE, me->GetEntry()), MAIL_CHECK_MASK_NONE, deliverDelay); - CharacterDatabase.CommitTransaction(trans); - } - - void UpdateAI(uint32 diff) override - { - if (!sWorld->getBoolConfig(CONFIG_MINIGOB_MANABONK)) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) + me->GetMap()->DoForAllPlayers([&](Player* player) { - switch (eventId) - { - case EVENT_SELECT_TARGET: - me->SetVisible(true); - DoCast(me, SPELL_TELEPORT_VISUAL); - if (Player* player = SelectTargetInDalaran()) - { - me->NearTeleportTo(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), 0.0f); - DoCast(player, SPELL_MANABONKED); - SendMailToPlayer(player); - } - events.ScheduleEvent(EVENT_BLINK, 3ms); - break; - case EVENT_BLINK: - { - DoCast(me, SPELL_IMPROVED_BLINK); - Position pos = me->GetRandomNearPosition((urand(15, 40))); - me->GetMotionMaster()->MovePoint(0, pos.m_positionX, pos.m_positionY, pos.m_positionZ); - events.ScheduleEvent(EVENT_DESPAWN, 3ms); - events.ScheduleEvent(EVENT_DESPAWN_VISUAL, 3ms); - break; - } - case EVENT_DESPAWN_VISUAL: - DoCast(me, SPELL_TELEPORT_VISUAL); - break; - case EVENT_DESPAWN: + if (player->GetZoneId() == ZONE_DALARAN && !player->IsFlying() && !player->IsMounted() && !player->IsGameMaster()) + playerInDalaranList.push_back(player); + }); + + if (playerInDalaranList.empty()) + return nullptr; + return Acore::Containers::SelectRandomContainerElement(playerInDalaranList); + } + + void SendMailToPlayer(Player* player) + { + CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); + int16 deliverDelay = irand(MAIL_DELIVER_DELAY_MIN, MAIL_DELIVER_DELAY_MAX); + MailDraft(MAIL_MINIGOB_ENTRY, true).SendMailTo(trans, MailReceiver(player), MailSender(MAIL_CREATURE, me->GetEntry()), MAIL_CHECK_MASK_NONE, deliverDelay); + CharacterDatabase.CommitTransaction(trans); + } + + void UpdateAI(uint32 diff) override + { + if (!sWorld->getBoolConfig(CONFIG_MINIGOB_MANABONK)) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SELECT_TARGET: + me->SetVisible(true); + DoCastSelf(SPELL_TELEPORT_VISUAL); + if (Player* player = SelectTargetInDalaran()) + { + playerGUID = player->GetGUID(); + Position pos = player->GetPosition(); + me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()); + me->GetMotionMaster()->MoveRandom(10); + } + events.ScheduleEvent(EVENT_POLYMORPH, 30s); + break; + case EVENT_POLYMORPH: + if (Player* player = ObjectAccessor::GetPlayer(*me, playerGUID)) + { + DoCast(player, SPELL_MANABONKED); + SendMailToPlayer(player); + } + else me->DespawnOrUnsummon(); - break; - default: - break; - } + events.ScheduleEvent(EVENT_LAUGH, 2s); + break; + case EVENT_LAUGH: + me->GetMotionMaster()->MoveIdle(); + me->HandleEmoteCommand(EMOTE_ONESHOT_LAUGH_NO_SHEATHE); + events.ScheduleEvent(EVENT_MOVE, 4s); + break; + case EVENT_MOVE: + { + Position pos = me->GetRandomNearPosition((urand(15, 40))); + me->GetMotionMaster()->MovePoint(0, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), true); + } + events.ScheduleEvent(EVENT_DESPAWN_VISUAL, 3s); + events.ScheduleEvent(EVENT_DESPAWN, 4s); + break; + case EVENT_DESPAWN_VISUAL: + DoCastSelf(SPELL_IMPROVED_BLINK); + break; + case EVENT_DESPAWN: + me->DespawnOrUnsummon(); + break; + default: + break; } } - - private: - EventMap events; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_minigob_manabonkAI(creature); } +private: + ObjectGuid playerGUID; }; class npc_dalaran_mage : public CreatureScript @@ -861,8 +867,6 @@ void AddSC_dalaran() new npc_dalaran_mage(); new npc_dalaran_warrior(); RegisterCreatureAI(npc_cosmetic_toy_plane); - - // theirs new npc_mageguard_dalaran(); - new npc_minigob_manabonk(); + RegisterCreatureAI(npc_minigob_manabonk); } diff --git a/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp b/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp index 00034a60f..8c0e5d9cb 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp @@ -46,6 +46,7 @@ enum Spells SPELL_POSSESS_SPIRIT_IMMUNE = 40282, SPELL_SPIRITUAL_VENGEANCE = 40268, SPELL_BRIEF_STUN = 41421, + SPELL_BERSERK = 45078, SPELL_SPIRIT_LANCE = 40157, SPELL_SPIRIT_CHAINS = 40175, @@ -54,13 +55,7 @@ enum Spells enum Misc { - SET_DATA_INTRO = 1, - - EVENT_SPELL_INCINERATE = 1, - EVENT_SPELL_DOOM_BLOSSOM = 2, - EVENT_SPELL_CRUSHING_SHADOWS = 3, - EVENT_SPELL_SHADOW_OF_DEATH = 4, - EVENT_TALK_KILL = 10 + SET_DATA_INTRO = 1 }; struct ShadowOfDeathSelector @@ -73,9 +68,11 @@ struct ShadowOfDeathSelector struct boss_teron_gorefiend : public BossAI { - boss_teron_gorefiend(Creature* creature) : BossAI(creature, DATA_TERON_GOREFIEND), intro(false) { } - - bool intro; + boss_teron_gorefiend(Creature* creature) : BossAI(creature, DATA_TERON_GOREFIEND) + { + _recentlySpoken = false; + _intro = false; + } void Reset() override { @@ -83,36 +80,72 @@ struct boss_teron_gorefiend : public BossAI me->CastSpell(me, SPELL_SHADOW_OF_DEATH_REMOVE, true); } + void JustEngagedWith(Unit* who) override + { + ScheduleTimedEvent(20s, 30s, [&] + { + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) + { + if (roll_chance_i(50)) + Talk(SAY_INCINERATE); + me->CastSpell(target, SPELL_INCINERATE, false); + } + }, 20s, 50s); + + ScheduleTimedEvent(5s, 10s, [&] + { + if (roll_chance_i(50)) + Talk(SAY_BLOSSOM); + me->CastSpell(me, SPELL_SUMMON_DOOM_BLOSSOM, false); + }, 35s); + + ScheduleTimedEvent(17s, 22s, [&] + { + if (roll_chance_i(20)) + Talk(SAY_CRUSHING); + me->CastCustomSpell(SPELL_CRUSHING_SHADOWS, SPELLVALUE_MAX_TARGETS, 5, me, false); + }, 10s, 26s); + + ScheduleTimedEvent(10s, [&] + { + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, ShadowOfDeathSelector())) + me->CastSpell(target, SPELL_SHADOW_OF_DEATH, false); + }, 30s, 50s); + + ScheduleTimedEvent(10min, [&] + { + DoCastSelf(SPELL_BERSERK); + }, 5min); + + BossAI::JustEngagedWith(who); + } + + void KilledUnit(Unit* victim) override + { + if (!_recentlySpoken && victim->IsPlayer()) + { + Talk(SAY_SLAY); + _recentlySpoken = true; + + ScheduleUniqueTimedEvent(6s, [&] + { + _recentlySpoken = false; + }, 1); + } + } + void SetData(uint32 type, uint32 id) override { if (type || !me->IsAlive()) return; - if (id == SET_DATA_INTRO && !intro) + if (id == SET_DATA_INTRO && !_intro) { - intro = true; + _intro = true; Talk(SAY_INTRO); } } - void JustEngagedWith(Unit* who) override - { - BossAI::JustEngagedWith(who); - events.ScheduleEvent(EVENT_SPELL_INCINERATE, 24000); - events.ScheduleEvent(EVENT_SPELL_DOOM_BLOSSOM, 10000); - events.ScheduleEvent(EVENT_SPELL_CRUSHING_SHADOWS, 17000); - events.ScheduleEvent(EVENT_SPELL_SHADOW_OF_DEATH, 20000); - } - - void KilledUnit(Unit* /*victim*/) override - { - if (events.GetNextEventTime(EVENT_TALK_KILL) == 0) - { - Talk(SAY_SLAY); - events.ScheduleEvent(EVENT_TALK_KILL, 6000); - } - } - void JustSummoned(Creature* summon) override { summons.Summon(summon); @@ -130,43 +163,13 @@ struct boss_teron_gorefiend : public BossAI if (!UpdateVictim()) return; - events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_SPELL_INCINERATE: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) - { - if (roll_chance_i(50)) - Talk(SAY_INCINERATE); - me->CastSpell(target, SPELL_INCINERATE, false); - } - events.ScheduleEvent(EVENT_SPELL_INCINERATE, 25000); - break; - case EVENT_SPELL_DOOM_BLOSSOM: - if (roll_chance_i(50)) - Talk(SAY_BLOSSOM); - - me->CastSpell(me, SPELL_SUMMON_DOOM_BLOSSOM, false); - events.ScheduleEvent(EVENT_SPELL_DOOM_BLOSSOM, 40000); - break; - case EVENT_SPELL_CRUSHING_SHADOWS: - if (roll_chance_i(20)) - Talk(SAY_CRUSHING); - me->CastCustomSpell(SPELL_CRUSHING_SHADOWS, SPELLVALUE_MAX_TARGETS, 5, me, false); - events.ScheduleEvent(EVENT_SPELL_CRUSHING_SHADOWS, 15000); - break; - case EVENT_SPELL_SHADOW_OF_DEATH: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, ShadowOfDeathSelector())) - me->CastSpell(target, SPELL_SHADOW_OF_DEATH, false); - events.ScheduleEvent(EVENT_SPELL_SHADOW_OF_DEATH, 30000); - break; - } - + scheduler.Update(diff); DoMeleeAttackIfReady(); } + + private: + bool _recentlySpoken; + bool _intro; }; class spell_teron_gorefiend_shadow_of_death : public AuraScript diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp index b1f07c880..62818e025 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp @@ -392,34 +392,14 @@ struct boss_kaelthas : public BossAI } } }); - scheduler.Schedule(2min, GROUP_PROGRESS_PHASE, [this](TaskContext) + scheduler.Schedule(90s, GROUP_PROGRESS_PHASE, [this](TaskContext) { PhaseAllAdvisorsExecute(); }); }, EVENT_PREFIGHT_PHASE52); break; case ACTION_PROGRESS_PHASE_CHECK: - if (_phase == PHASE_WEAPONS) - { - bool aliveWeapon = false; - summons.DoForAllSummons([&aliveWeapon](WorldObject* summon) - { - if (Creature* summonedCreature = summon->ToCreature()) - { - if (summonedCreature->IsAlive()) - { - if (summonedCreature->GetEntry() >= NPC_NETHERSTRAND_LONGBOW && summonedCreature->GetEntry() <= NPC_STAFF_OF_DISINTEGRATION) - { - aliveWeapon = true; - return; - } - } - } - }); - if (!aliveWeapon) - PhaseAllAdvisorsExecute(); - } - else if (_phase == PHASE_ALL_ADVISORS) + if (_phase == PHASE_ALL_ADVISORS) { bool advisorAlive = false; summons.DoForAllSummons([&advisorAlive](WorldObject* summon) @@ -1163,9 +1143,19 @@ class spell_kaelthas_mind_control : public SpellScript targets.remove_if(Acore::ObjectTypeIdCheck(TYPEID_PLAYER, false)); } + void HandleEffect(SpellEffIndex /*effIndex*/) + { + if (!GetCaster() || !GetHitPlayer()) + return; + + if (Player* player = GetHitPlayer()) + GetCaster()->GetThreatMgr().ResetThreat(player); + } + void Register() override { OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_kaelthas_mind_control::SelectTarget, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_kaelthas_mind_control::HandleEffect, EFFECT_ALL, SPELL_AURA_ANY); } }; diff --git a/src/server/scripts/Outland/zone_shattrath_city.cpp b/src/server/scripts/Outland/zone_shattrath_city.cpp index 34ca2c9e0..bccd14d26 100644 --- a/src/server/scripts/Outland/zone_shattrath_city.cpp +++ b/src/server/scripts/Outland/zone_shattrath_city.cpp @@ -16,6 +16,7 @@ */ #include "CreatureScript.h" +#include "PassiveAI.h" #include "Player.h" #include "ScriptedCreature.h" #include "ScriptedEscortAI.h" @@ -253,9 +254,166 @@ public: }; }; +enum ShattrathQuests +{ + // QuestID : Creature Template ID + // Heroic Daily Quests + QUEST_H_NAZZAN = 11354, // 24410 + QUEST_H_KELIDAN = 11362, // 24413 + QUEST_H_BLADEFIST = 11363, // 24414 + QUEST_H_QUAG = 11368, // 24419 + QUEST_H_BLACKSTALKER = 11369, // 24420 + QUEST_H_WARLORD = 11370, // 24421 + QUEST_H_IKISS = 11372, // 24422 + QUEST_H_SHAFFAR = 11373, // 24423 + QUEST_H_EXARCH = 11374, // 24424 + QUEST_H_MURMUR = 11375, // 24425 + QUEST_H_EPOCH = 11378, // 24427 + QUEST_H_AEONUS = 11382, // 24428 + QUEST_H_WARP = 11384, // 24431 + QUEST_H_CALCULATOR = 11386, // 21504 + QUEST_H_SKYRISS = 11388, // 24435 + QUEST_H_KAEL = 11499, // 24855 + // Normal Daily Quests + QUEST_N_CENTURIONS = 11364, // 24411 + QUEST_N_MYRMIDONS = 11371, // 24415 + QUEST_N_INSTRUCTORS = 11376, // 24426 + QUEST_N_LORDS = 11383, // 24429 + QUEST_N_CHANNELERS = 11385, // 24430 + QUEST_N_DESTROYERS = 11387, // 24432 + QUEST_N_SENTINELS = 11389, // 24434 + QUEST_N_SISTERS = 11500, // 24854 + + ACTION_UPDATE_QUEST_STATUS = 1, + + POOL_SHATTRATH_DAILY_H = 356, + POOL_SHATTRATH_DAILY_N = 357, + + // Image NPCs + NPC_SHATTRATH_DAILY_H = 24854, + NPC_SHATTRATH_DAILY_N = 24410 +}; + +struct npc_shattrath_daily_quest : public NullCreatureAI +{ + npc_shattrath_daily_quest(Creature* c) : NullCreatureAI(c) {} + + void DoAction(int32 action) override + { + if (action == ACTION_UPDATE_QUEST_STATUS) + { + uint32 creature = me->GetEntry(); + QueryResult result = CharacterDatabase.Query("SELECT `quest_id` FROM `pool_quest_save` WHERE `pool_id` = '{}'", creature == NPC_SHATTRATH_DAILY_H ? POOL_SHATTRATH_DAILY_H : POOL_SHATTRATH_DAILY_N); + if (result) + { + Field *fields = result->Fetch(); + int quest_id = fields[0].Get(); + uint32 templateID; + + if (creature == NPC_SHATTRATH_DAILY_H) + { + switch (quest_id) + { + case QUEST_H_NAZZAN: + templateID = 24410; + break; + case QUEST_H_KELIDAN: + templateID = 24413; + break; + case QUEST_H_BLADEFIST: + templateID = 24414; + break; + case QUEST_H_QUAG: + templateID = 24419; + break; + case QUEST_H_BLACKSTALKER: + templateID = 24420; + break; + case QUEST_H_WARLORD: + templateID = 24421; + break; + case QUEST_H_IKISS: + templateID = 24422; + break; + case QUEST_H_SHAFFAR: + templateID = 24423; + break; + case QUEST_H_EXARCH: + templateID = 24424; + break; + case QUEST_H_MURMUR: + templateID = 24425; + break; + case QUEST_H_EPOCH: + templateID = 24427; + break; + case QUEST_H_AEONUS: + templateID = 24428; + break; + case QUEST_H_WARP: + templateID = 24431; + break; + case QUEST_H_CALCULATOR: + templateID = 21504; + break; + case QUEST_H_SKYRISS: + templateID = 24435; + break; + case QUEST_H_KAEL: + templateID = 24855; + break; + default: + break; + } + } + + if (creature == NPC_SHATTRATH_DAILY_N) + { + switch (quest_id) + { + case QUEST_N_CENTURIONS: + templateID = 24411; + break; + case QUEST_N_MYRMIDONS: + templateID = 24415; + break; + case QUEST_N_INSTRUCTORS: + templateID = 24426; + break; + case QUEST_N_LORDS: + templateID = 24429; + break; + case QUEST_N_CHANNELERS: + templateID = 24430; + break; + case QUEST_N_DESTROYERS: + templateID = 24432; + break; + case QUEST_N_SENTINELS: + templateID = 24434; + break; + case QUEST_N_SISTERS: + templateID = 24854; + break; + default: + break; + } + } + + if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(templateID)) + { + CreatureModel const* model = ObjectMgr::ChooseDisplayId(ci); + me->SetDisplayId(model->CreatureDisplayID, model->DisplayScale); + } + } + } + } +}; + void AddSC_shattrath_city() { new npc_shattrathflaskvendors(); new npc_zephyr(); new npc_kservant(); + RegisterCreatureAI(npc_shattrath_daily_quest); } diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp index 654d14a63..2a69287c2 100644 --- a/src/server/scripts/Spells/spell_item.cpp +++ b/src/server/scripts/Spells/spell_item.cpp @@ -3990,6 +3990,37 @@ class spell_item_eye_of_grillok_aura : public AuraScript } }; +enum FelManaPotion +{ + SPELL_ALCHEMIST_STONE = 17619, + SPELL_ALCHEMIST_STONE_ENERGIZE = 21400 +}; + +class spell_item_fel_mana_potion : public AuraScript +{ + PrepareAuraScript(spell_item_fel_mana_potion) + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_ALCHEMIST_STONE, SPELL_ALCHEMIST_STONE_ENERGIZE }); + } + + void OnPeriodic(AuraEffect const* /*aurEff*/) + { + if (Unit* caster = GetCaster()) + if (caster->HasAura(SPELL_ALCHEMIST_STONE)) + { + uint32 val = GetSpellInfo()->Effects[EFFECT_0].BasePoints * 0.4f; + caster->CastCustomSpell(SPELL_ALCHEMIST_STONE_ENERGIZE, SPELLVALUE_BASE_POINT0, val, caster, true); + } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_item_fel_mana_potion::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_ENERGIZE); + } +}; + void AddSC_item_spell_scripts() { RegisterSpellScript(spell_item_massive_seaforium_charge); @@ -4112,5 +4143,6 @@ void AddSC_item_spell_scripts() RegisterSpellScript(spell_item_venomhide_feed); RegisterSpellScript(spell_item_scroll_of_retribution); RegisterSpellAndAuraScriptPair(spell_item_eye_of_grillok, spell_item_eye_of_grillok_aura); + RegisterSpellScript(spell_item_fel_mana_potion); } diff --git a/src/server/shared/DataStores/DBCStructure.h b/src/server/shared/DataStores/DBCStructure.h index b3e634673..938411343 100644 --- a/src/server/shared/DataStores/DBCStructure.h +++ b/src/server/shared/DataStores/DBCStructure.h @@ -590,11 +590,11 @@ struct BarberShopStyleEntry { uint32 Id; // 0 uint32 type; // 1 value 0 -> hair, value 2 -> facialhair - //char const* name[16]; // 2-17 name of hair style - //uint32 name_flags; // 18 - //uint32 unk_name[16]; // 19-34, all empty - //uint32 unk_flags; // 35 - //float CostMultiplier; // 36 values 1 and 0.75 + //char const* displayNameLang[16]; // 2-17 name of hair style + //char const* displayNameLangMask; // 18 + //char const* descriptionLang[16]; // 19-34, all empty + //char const* descriptionLangMask; // 35 + //float costModifier; // 36 values 1 and 0.75 uint32 race; // 37 race uint32 gender; // 38 0 -> male, 1 -> female uint32 hair_id; // 39 real ID to hair/facial hair @@ -618,11 +618,11 @@ struct BattlemasterListEntry struct CharStartOutfitEntry { - //uint32 Id; // 0 + //uint32 ID; // 0 uint8 Race; // 1 uint8 Class; // 2 uint8 Gender; // 3 - //uint8 Unused; // 4 + //uint8 outfitID; // 4 unused int32 ItemId[MAX_OUTFIT_ITEMS]; // 5-28 //int32 ItemDisplayId[MAX_OUTFIT_ITEMS]; // 29-52 not required at server side //int32 ItemInventorySlot[MAX_OUTFIT_ITEMS]; // 53-76 not required at server side @@ -658,11 +658,11 @@ struct CharSectionsEntry struct CharTitlesEntry { uint32 ID; // 0, title ids, for example in Quest::GetCharTitleId() - //uint32 unk1; // 1 flags? + //uint32 conditionID; // 1 Never used by the client. Should be used serverside? char const* nameMale[16]; // 2-17 - // 18 string flag, unused + //uint32 nameLangMask // 18 string flag, unused char const* nameFemale[16]; // 19-34 - // 35 string flag, unused + //uint32 nameLang1Mask // 35 string flag, unused uint32 bit_index; // 36 used in PLAYER_CHOSEN_TITLE and 1< RankID; // 4-8 - // 9-12 not used, always 0, maybe not used high ranks - uint32 DependsOn; // 13 index in Talent.dbc (TalentEntry) - // 14-15 not used - uint32 DependsOnRank; // 16 - // 17-18 not used + // uint32 spellRank [4] // 9-12 not used, always 0, maybe not used high ranks + uint32 DependsOn; // 13 preReqTalent1 index in Talent.dbc (TalentEntry) + // uint32 preReqTalent[2] // 14-15 not used + uint32 DependsOnRank; // 16 preReqRank1 + // uint32 preReqRank[2] // 17-18 not used uint32 addToSpellBook; // 19 also need disable higest ranks on reset talent tree - //uint32 unk2; // 20, all 0 - //uint64 allowForPet; // 21-22 its a 64 bit mask for pet 1<. */ -#include "Define.h" #include "SharedDefines.h" +#include "Define.h" #include "SmartEnum.h" #include @@ -311,7 +311,7 @@ AC_API_EXPORT EnumText EnumUtils::ToString(SpellAttr1 value) case SPELL_ATTR1_FINISHING_MOVE_DURATION: return { "SPELL_ATTR1_FINISHING_MOVE_DURATION", "Requires combo points (type 2)", "" }; case SPELL_ATTR1_IGNORE_OWNERS_DEATH: return { "SPELL_ATTR1_IGNORE_OWNERS_DEATH", "Unknwon attribute 23@Attr1", "" }; case SPELL_ATTR1_SPECIAL_SKILLUP: return { "SPELL_ATTR1_SPECIAL_SKILLUP", "Fishing (client only)", "" }; - case SPELL_ATTR1_AURA_STAYS_AFTER_COMBAT: return { "SPELL_ATTR1_AURA_STAYS_AFTER_COMBAT", "Unknown attribute 25@Attr1", "" }; + case SPELL_ATTR1_AURA_STAYS_AFTER_COMBAT: return { "SPELL_ATTR1_AURA_STAYS_AFTER_COMBAT", "Aura stays after combat", "Aura will not be removed when the unit leaves combat" }; case SPELL_ATTR1_REQUIRE_ALL_TARGETS: return { "SPELL_ATTR1_REQUIRE_ALL_TARGETS", "Unknown attribute 26@Attr1", "Related to [target=focus] and [target=mouseover] macros?" }; case SPELL_ATTR1_DISCOUNT_POWER_ON_MISS: return { "SPELL_ATTR1_DISCOUNT_POWER_ON_MISS", "Unknown attribute 27@Attr1", "Melee spell?" }; case SPELL_ATTR1_NO_AURA_ICON: return { "SPELL_ATTR1_NO_AURA_ICON", "Hide in aura bar (client only)", "" };