diff --git a/.github/SECURITY.md b/.github/SECURITY.md index b55b3cc60..13faf3a07 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -55,15 +55,15 @@ Versions of Ubuntu: | Ubuntu version | Supported | | -------------- | ------------------ | | 20.04 | :white_check_mark: | -| 18.04 | :white_check_mark: | +| 18.04 and lower| :red_circle: | Versions of macOS: -| macOS Version | Supported | -| ------------- | ------------------ | -| 12 | :white_check_mark: | -| 11 | :white_check_mark: | -| 10.15 | :white_check_mark: | +| macOS Version | Supported | +| -------------- | ------------------ | +| 12 | :white_check_mark: | +| 11 | :white_check_mark: | +| 10.15 and lower| :red_circle: | **Note**: We do NOT support any repacks that may or may not have been made based on AzerothCore. Nor do we support any of the releases that are made under AzerothCore. diff --git a/.github/workflows/core_matrix_build.yml b/.github/workflows/core_matrix_build.yml index 95732a403..5852c6c17 100644 --- a/.github/workflows/core_matrix_build.yml +++ b/.github/workflows/core_matrix_build.yml @@ -4,7 +4,7 @@ on: branches: - 'master' pull_request: - types: ['labeled', 'labeled', 'opened', 'synchronize', 'reopened'] + types: ['labeled', 'opened', 'synchronize', 'reopened'] concurrency: group: ${{ github.head_ref }} || concat(${{ github.ref }}, ${{ github.workflow }}) @@ -21,10 +21,6 @@ jobs: compiler: clang12 - os: ubuntu-20.04 compiler: clang11 - - os: ubuntu-18.04 - compiler: clang10 - - os: ubuntu-18.04 - compiler: gcc8 - os: ubuntu-20.04 compiler: gcc # default in 20.04 is gcc 9 - os: ubuntu-20.04 diff --git a/.github/workflows/core_modules_build.yml b/.github/workflows/core_modules_build.yml index 6db57dcfc..7003d96f9 100644 --- a/.github/workflows/core_modules_build.yml +++ b/.github/workflows/core_modules_build.yml @@ -4,7 +4,7 @@ on: branches: - 'master' pull_request: - types: ['labeled', 'labeled', 'opened', 'synchronize', 'reopened'] + types: ['labeled', 'opened', 'synchronize', 'reopened'] concurrency: group: ${{ github.head_ref }} || concat(${{ github.ref }}, ${{ github.workflow }}) diff --git a/.github/workflows/docker_build.yml b/.github/workflows/docker_build.yml index 872f6c36f..7ccbf23f9 100644 --- a/.github/workflows/docker_build.yml +++ b/.github/workflows/docker_build.yml @@ -4,7 +4,7 @@ on: branches: - 'master' pull_request: - types: ['labeled', 'labeled', 'opened', 'synchronize', 'reopened'] + types: ['labeled', 'opened', 'synchronize', 'reopened'] concurrency: group: ${{ github.head_ref }} || concat(${{ github.ref }}, ${{ github.workflow }}) diff --git a/.github/workflows/macos_build.yml b/.github/workflows/macos_build.yml index 92ebfbf6a..5d58a15e6 100644 --- a/.github/workflows/macos_build.yml +++ b/.github/workflows/macos_build.yml @@ -4,7 +4,7 @@ on: branches: - 'master' pull_request: - types: ['labeled', 'labeled', 'opened', 'synchronize', 'reopened'] + types: ['labeled', 'opened', 'synchronize', 'reopened'] concurrency: group: ${{ github.head_ref }} || concat(${{ github.ref }}, ${{ github.workflow }}) @@ -16,7 +16,6 @@ jobs: fail-fast: false matrix: os: - - macos-10.15 - macos-11 - macos-12 runs-on: ${{ matrix.os }} diff --git a/.github/workflows/windows_build.yml b/.github/workflows/windows_build.yml index 43792b754..a57f6d532 100644 --- a/.github/workflows/windows_build.yml +++ b/.github/workflows/windows_build.yml @@ -4,7 +4,7 @@ on: branches: - 'master' pull_request: - types: ['labeled', 'labeled', 'opened', 'synchronize', 'reopened'] + types: ['labeled', 'opened', 'synchronize', 'reopened'] concurrency: group: ${{ github.head_ref }} || concat(${{ github.ref }}, ${{ github.workflow }}) @@ -24,7 +24,9 @@ jobs: steps: - uses: actions/checkout@v2 - name: Configure OS - run: choco install --no-progress openssl boost-msvc-14.3 + run: | + choco install --no-progress openssl + choco install --no-progress boost-msvc-14.3 --version=1.79.0 - name: Build shell: bash run: | diff --git a/data/sql/updates/db_characters/2022_08_02_00.sql b/data/sql/updates/db_characters/2022_08_02_00.sql new file mode 100644 index 000000000..177cfe81f --- /dev/null +++ b/data/sql/updates/db_characters/2022_08_02_00.sql @@ -0,0 +1,3 @@ +-- DB update 2022_05_24_00 -> 2022_08_02_00 +-- +UPDATE `characters` SET `taxi_path`=CONCAT('0 ', `taxi_path`) WHERE LENGTH(`taxi_path`) > 0; diff --git a/data/sql/updates/db_characters/2022_08_07_00.sql b/data/sql/updates/db_characters/2022_08_07_00.sql new file mode 100644 index 000000000..343f886f9 --- /dev/null +++ b/data/sql/updates/db_characters/2022_08_07_00.sql @@ -0,0 +1,6 @@ +-- DB update 2022_08_02_00 -> 2022_08_07_00 +-- +ALTER TABLE `character_entry_point` +ADD COLUMN `taxiPath0` INT UNSIGNED DEFAULT 0 NOT NULL AFTER `joinMapId`, +ADD COLUMN `taxiPath1` INT UNSIGNED DEFAULT 0 NOT NULL AFTER `taxiPath0`, +DROP COLUMN `taxiPath`; diff --git a/data/sql/updates/db_world/2022_07_29_00.sql b/data/sql/updates/db_world/2022_07_29_00.sql new file mode 100644 index 000000000..bf158f6a4 --- /dev/null +++ b/data/sql/updates/db_world/2022_07_29_00.sql @@ -0,0 +1,8 @@ +-- DB update 2022_07_27_04 -> 2022_07_29_00 +-- +UPDATE `creature_template` SET `skinloot` = 14887 WHERE (`entry` IN (14887, 14888, 14889, 14890)); + +DELETE FROM `skinning_loot_template` WHERE (`Entry` = 14887) AND (`Item` IN (15412, 20381)); +INSERT INTO `skinning_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(14887, 15412, 0, 60, 0, 1, 1, 5, 8, ''), +(14887, 20381, 0, 40, 0, 1, 1, 3, 5, ''); diff --git a/data/sql/updates/db_world/2022_07_31_00.sql b/data/sql/updates/db_world/2022_07_31_00.sql new file mode 100644 index 000000000..dc9d0ed5d --- /dev/null +++ b/data/sql/updates/db_world/2022_07_31_00.sql @@ -0,0 +1,7 @@ +-- DB update 2022_07_29_00 -> 2022_07_31_00 +-- Chief Hawkwind +UPDATE `creature_template` SET `gossip_menu_id`=0, `npcflag`=`npcflag`&~1 WHERE `entry`=2981; + +DELETE FROM `quest_greeting` WHERE `ID`=2981; +INSERT INTO `quest_greeting` (`ID`, `Type`, `GreetEmoteType`, `GreetEmoteDelay`, `Greeting`, `VerifiedBuild`) VALUES +(2981,0,0,0,"Hail, $c. In my years I have seen many eager tauren who wish to prove their worth to the tribe. It should not be forgotten that eagerness is no substitute for wisdom and experience.",0); diff --git a/data/sql/updates/db_world/2022_07_31_01.sql b/data/sql/updates/db_world/2022_07_31_01.sql new file mode 100644 index 000000000..bb4e25120 --- /dev/null +++ b/data/sql/updates/db_world/2022_07_31_01.sql @@ -0,0 +1,4 @@ +-- DB update 2022_07_31_00 -> 2022_07_31_01 +-- +/* Movetype and wander distance corrections for Entranceway */ +UPDATE `creature` SET `wander_distance`=2, `MovementType`=1 WHERE `guid` IN (49739, 49740); diff --git a/data/sql/updates/db_world/2022_07_31_02.sql b/data/sql/updates/db_world/2022_07_31_02.sql new file mode 100644 index 000000000..d008e7c48 --- /dev/null +++ b/data/sql/updates/db_world/2022_07_31_02.sql @@ -0,0 +1,60 @@ +-- DB update 2022_07_31_01 -> 2022_07_31_02 +-- +-- Kum'isha the Collector +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=7363; +DELETE FROM `smart_scripts` WHERE `entryorguid`=7363 AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=736300 AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `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 +(7363,0,0,0,20,0,100,0,2521,0,0,0,80,736300,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kum'isha the Collector - On Quest 'To Serve Kum'isha' Finished - Run Script"), +(736300,9,0,0,0,0,100,0,0,0,0,0,83,3,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kum'isha the Collector - On Script - Remove Npc Flag Questgiver+Gossip"), +(736300,9,1,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,1.03552,"Kum'isha the Collector - On Script - Set Orientation"), +(736300,9,2,0,0,0,100,0,1000,1000,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kum'isha the Collector - On Script - Say Line 0"), +(736300,9,3,0,0,0,100,0,0,0,0,0,12,7364,8,0,0,0,0,8,0,0,0,-11359.4,-2977.5,-0.447796,4.13626,"Kum'isha the Collector - On Script - Summon Creature 'Flawless Draenethyst Sphere'"), +(736300,9,4,0,0,0,100,0,4000,4000,0,0,11,65633,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kum'isha the Collector - On Script - Cast 'Arcane Cast Visual'"), +(736300,9,5,0,0,0,100,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kum'isha the Collector - On Script - Say Line 1"), +(736300,9,6,0,0,0,100,0,3000,3000,0,0,50,137167,26,0,0,0,0,8,0,0,0,-11359.4,-2977.5,-0.447796,0.185707,"Kum'isha the Collector - On Script - Summon Gameobject 'Nether Rift'"), +(736300,9,7,0,0,0,100,0,2000,2000,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kum'isha the Collector - On Script - Say Line 2"), +(736300,9,8,0,0,0,100,0,0,0,0,0,107,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kum'isha the Collector - On Script - Summon Group"), +(736300,9,9,0,0,0,100,0,10000,10000,0,0,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kum'isha the Collector - On Script - Say Line 3"), +(736300,9,10,0,0,0,100,0,15000,15000,0,0,86,58538,0,19,7364,0,0,1,0,0,0,0,0,0,0,"Kum'isha the Collector - On Script - Cross Cast 'Arcane Explosion Visual'"), +(736300,9,11,0,0,0,100,0,500,500,0,0,41,0,0,0,0,0,0,19,7364,0,0,0,0,0,0,"Kum'isha the Collector - On Script - Despawn Creature 'Flawless Draenethyst Sphere'"), +(736300,9,12,0,0,0,100,0,3000,3000,0,0,1,4,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kum'isha the Collector - On Script - Say Line 4"), +(736300,9,13,0,0,0,100,0,0,0,0,0,82,3,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kum'isha the Collector - On Script - Add Npc Flag Questgiver+Gossip"), +(736300,9,14,0,0,0,100,0,5000,5000,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,2.79076,"Kum'isha the Collector - On Script - Set Orientation"); + +DELETE FROM `creature_summon_groups` WHERE `summonerId`=7363; +INSERT INTO `creature_summon_groups` (`summonerId`, `summonerType`, `groupId`, `entry`, `position_x`, `position_y`, `position_z`, `orientation`, `summonType`, `summonTime`) VALUES +(7363,0,1,7401,-11303.2,-2989.65,5.53587,2.83237,8,300000), +(7363,0,1,7401,-11309.1,-2972.41,8.33972,3.24362,8,300000), +(7363,0,1,7401,-11317.0,-2978.34,5.48171,3.21221,8,300000), +(7363,0,1,7401,-11328.8,-2979.58,6.07384,3.19257,8,300000), +(7363,0,1,7401,-11321.9,-2974.86,7.56403,3.30645,8,300000); + +DELETE FROM `creature_text` WHERE `CreatureID`=7363; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(7363,0,0,"%s releases the flawless draenethyst sphere, allowing it to hover before him.",16,0,100,0,0,0,3441,0,"Kum'isha the Collector"), +(7363,1,0,"%s chants in an unknown tongue.",16,0,100,0,0,0,3442,0,"Kum'isha the Collector"), +(7363,2,0,"Success, the rift is open!! My brethren, rise and return home! The Outland awaits!",14,0,100,0,0,0,3475,0,"Kum'isha the Collector"), +(7363,3,0,"Hurry brothers! You must go now! I do not know how much longer the rift will remain open!",12,0,100,0,0,0,3476,0,"Kum'isha the Collector"), +(7363,4,0,"And now you know why I live in a crater.",12,0,100,0,0,0,3477,0,"Kum'isha the Collector"); + +DELETE FROM `gossip_menu` WHERE `MenuID`=752 AND `TextID`=1303; +INSERT INTO `gossip_menu` (`MenuID`, `TextID`) VALUES +(752,1303); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=752; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(14,752,1303,0,0,8,0,2521,0,0,0,0,0,"","Show gossip text 1303 if quest 'To Serve Kum'isha' is rewarded"); + +-- Draenei Refugee +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=7401; +DELETE FROM `smart_scripts` WHERE `entryorguid`=7401 AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(7401,0,0,0,54,0,100,0,0,0,0,0,53,0,7401,0,0,0,0,1,0,0,0,0,0,0,0,"Draenei Refugee - Just Summoned - Start Waypoint"), +(7401,0,1,0,58,0,100,0,0,0,0,0,11,51347,0,0,0,0,0,1,0,0,0,0,0,0,0,"Draenei Refugee - On Waypoint Ended - Cast 'Teleport Visual Only'"), +(7401,0,2,0,58,0,100,0,0,0,0,0,41,1000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Draenei Refugee - On Waypoint Ended - Despawn after 1 second"); + +DELETE FROM `waypoints` WHERE `entry`=7401; +INSERT INTO `waypoints` (`entry`,`pointid`,`position_x`,`position_y`,`position_z`,`point_comment`) VALUES +(7401,1,-11336.5,-2981.66,2.98413,""), +(7401,2,-11359.4,-2977.5,-0.447796,""); diff --git a/data/sql/updates/db_world/2022_08_01_00.sql b/data/sql/updates/db_world/2022_08_01_00.sql new file mode 100644 index 000000000..df3cd6dd4 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_01_00.sql @@ -0,0 +1,5 @@ +-- DB update 2022_07_31_02 -> 2022_08_01_00 +-- + +UPDATE `creature` SET `position_z`=94.3 WHERE `guid`=34977; + diff --git a/data/sql/updates/db_world/2022_08_01_01.sql b/data/sql/updates/db_world/2022_08_01_01.sql new file mode 100644 index 000000000..32fd72b92 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_01_01.sql @@ -0,0 +1,3 @@ +-- DB update 2022_08_01_00 -> 2022_08_01_01 +-- +UPDATE `creature` SET `spawntimesecs` = 300 WHERE `id1` IN (11406, 14724, 16013, 22026); diff --git a/data/sql/updates/db_world/2022_08_01_02.sql b/data/sql/updates/db_world/2022_08_01_02.sql new file mode 100644 index 000000000..7db25b8a9 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_01_02.sql @@ -0,0 +1,3 @@ +-- DB update 2022_08_01_01 -> 2022_08_01_02 +-- trainer can learn skills +UPDATE `creature_template` SET `npcflag`=`npcflag`|1 WHERE `entry` IN (18753,18752,18771); diff --git a/data/sql/updates/db_world/2022_08_01_03.sql b/data/sql/updates/db_world/2022_08_01_03.sql new file mode 100644 index 000000000..2956174fe --- /dev/null +++ b/data/sql/updates/db_world/2022_08_01_03.sql @@ -0,0 +1,3 @@ +-- DB update 2022_08_01_02 -> 2022_08_01_03 +-- Ghost Mushroom Position +UPDATE `gameobject` SET `position_x` = 328.167, `position_y` = -3705.581, `position_z` = 107.007 WHERE `guid` = 16425; diff --git a/data/sql/updates/db_world/2022_08_01_04.sql b/data/sql/updates/db_world/2022_08_01_04.sql new file mode 100644 index 000000000..7d8c32ac5 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_01_04.sql @@ -0,0 +1,3 @@ +-- DB update 2022_08_01_03 -> 2022_08_01_04 +-- Marin Noggenfogger +UPDATE `gossip_menu_option` SET `OptionText`="Yes! I want more of that fabulous Noggenfogger Elixir!", `OptionBroadcastTextID`=3793 WHERE `MenuID`=922 AND `OptionID`=0; diff --git a/data/sql/updates/db_world/2022_08_01_05.sql b/data/sql/updates/db_world/2022_08_01_05.sql new file mode 100644 index 000000000..cbfea8e89 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_01_05.sql @@ -0,0 +1,15 @@ +-- DB update 2022_08_01_04 -> 2022_08_01_05 +-- Sprinkle +DELETE FROM `creature_text` WHERE `CreatureID`=7583 AND `GroupID`=3; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(7583,3,0,"Just sit tight while I get this prepared for you!",12,0,100,0,0,0,3661,0,"Sprinkle"); + +DELETE FROM `smart_scripts` WHERE `entryorguid`=7583 AND `source_type`=0 AND `id`=2; +DELETE FROM `smart_scripts` WHERE `entryorguid`=758302 AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `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 +(7583,0,2,0,20,0,100,0,2641,0,0,0,80,758302,0,0,0,0,0,1,0,0,0,0,0,0,0,"Sprinkle - On Quest 'Sprinkle's Secret Ingredient' Finished - Run Script"), +(758302,9,0,0,0,0,100,0,0,0,0,0,83,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Sprinkle - On Script - Remove Npc Flag Questgiver"), +(758302,9,1,0,0,0,100,0,0,0,0,0,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0,"Sprinkle - On Script - Say Line 3"), +(758302,9,2,0,0,0,100,0,1000,1000,0,0,17,69,0,0,0,0,0,1,0,0,0,0,0,0,0,"Sprinkle - On Script - Set Emote State 'Usestanding'"), +(758302,9,3,0,0,0,100,0,6000,6000,0,0,17,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Sprinkle - On Script - Set Emote State 'None'"), +(758302,9,4,0,0,0,100,0,0,0,0,0,82,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Sprinkle - On Script - Add Npc Flag Questgiver"); diff --git a/data/sql/updates/db_world/2022_08_01_06.sql b/data/sql/updates/db_world/2022_08_01_06.sql new file mode 100644 index 000000000..0f8b595c8 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_01_06.sql @@ -0,0 +1,14 @@ +-- DB update 2022_08_01_05 -> 2022_08_01_06 +-- Wooden Outhouse +DELETE FROM `smart_scripts` WHERE `entryorguid`=173265 AND `source_type`=1 AND `id`=4; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `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 +(173265,1,4,0,62,0,100,0,2387,0,0,0,0,70,60,0,0,0,0,0,14,47578,173266,0,0,0,0,0,"Wooden Outhouse - On Gossip Option Selected - Respawn Gameobject 'Goodsteel Ledger'"); + +DELETE FROM `gossip_menu_option` WHERE `MenuID`=2387; +INSERT INTO `gossip_menu_option` (`MenuID`, `OptionID`, `OptionIcon`, `OptionText`, `OptionBroadcastTextID`, `OptionType`, `OptionNpcFlag`, `ActionMenuID`, `ActionPoiID`, `VerifiedBuild`) VALUES +(2387,0,0,"Um... sorry to bother you, but could I see Goodsteel's ledger again... if you're not using it.",5410,1,1,2386,0,0); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=2387; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(15,2387,0,0,0,9,0,4450,0,0,0,0,0,"","Show gossip option if quest 'Ledger from Tanaris' is taken"), +(15,2387,0,0,0,2,0,11727,1,1,1,0,0,"","Show gossip option if player does not have item 'Goodsteel Ledger'"); diff --git a/data/sql/updates/db_world/2022_08_01_07.sql b/data/sql/updates/db_world/2022_08_01_07.sql new file mode 100644 index 000000000..62644b4ae --- /dev/null +++ b/data/sql/updates/db_world/2022_08_01_07.sql @@ -0,0 +1,139 @@ +-- DB update 2022_08_01_06 -> 2022_08_01_07 +-- +/* Maintenance on ZG Before Bats Part 2: Pooling Part 1 */ +DELETE FROM `creature` WHERE `guid` BETWEEN 91480 AND 91484; + +/* Crocolisk Packs: This method can be exported into all Crocolisk Packs, it requires 25 creature entries and 6 pools. +50% Chance to spawn 5, 10% chance for each location to spawn empty creating a 4 pack + +INSERT INTO `creature` (`guid`, `id1`, `id2`, `id3`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`) VALUES +(@GUID+, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11903.1, -1490.94, 12.5739, 1.91973, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11895.3, -1503.19, 15.1803, 5.42918, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11892.8, -1498.98, 13.7794, 4.75143, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11912.7, -1494.4, 12.0913, 3.05153, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11903, -1502.04, 14.7285, 0.400987, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +*/ + +SET @GUID :=61271; +DELETE FROM `creature` WHERE `guid` BETWEEN @GUID+0 AND @GUID+24; +INSERT INTO `creature` (`guid`, `id1`, `id2`, `id3`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`) VALUES +-- 5 Pack +(@GUID+0, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11903.1, -1490.94, 12.5739, 1.91973, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+1, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11895.3, -1503.19, 15.1803, 5.42918, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+2, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11892.8, -1498.98, 13.7794, 4.75143, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+3, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11912.7, -1494.4, 12.0913, 3.05153, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+4, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11903, -1502.04, 14.7285, 0.400987, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +-- 4 Pack Missing First +(@GUID+5, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11895.3, -1503.19, 15.1803, 5.42918, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+6, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11892.8, -1498.98, 13.7794, 4.75143, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+7, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11912.7, -1494.4, 12.0913, 3.05153, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+8, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11903, -1502.04, 14.7285, 0.400987, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +-- 4 Pack Missing Second +(@GUID+9, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11903.1, -1490.94, 12.5739, 1.91973, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+10, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11892.8, -1498.98, 13.7794, 4.75143, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+11, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11912.7, -1494.4, 12.0913, 3.05153, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+12, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11903, -1502.04, 14.7285, 0.400987, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +-- 4 Pack Missing Third +(@GUID+13, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11903.1, -1490.94, 12.5739, 1.91973, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+14, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11895.3, -1503.19, 15.1803, 5.42918, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+15, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11912.7, -1494.4, 12.0913, 3.05153, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+16, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11903, -1502.04, 14.7285, 0.400987, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +-- 4 Pack Missing Fourth +(@GUID+17, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11903.1, -1490.94, 12.5739, 1.91973, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+18, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11895.3, -1503.19, 15.1803, 5.42918, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+19, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11892.8, -1498.98, 13.7794, 4.75143, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+20, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11903, -1502.04, 14.7285, 0.400987, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +-- 4 Pack Missing Final +(@GUID+21, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11903.1, -1490.94, 12.5739, 1.91973, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+22, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11895.3, -1503.19, 15.1803, 5.42918, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+23, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11892.8, -1498.98, 13.7794, 4.75143, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0), +(@GUID+24, 15043, 0, 0, 309, 0, 0, 1, 1, 0, -11912.7, -1494.4, 12.0913, 3.05153, 7200, 0, 0, 9156, 0, 0, 0, 0, 0, '', 0); + +SET @POOL :=469; +DELETE FROM `pool_template` WHERE `entry` BETWEEN @POOL+0 AND @POOL+6; +DELETE FROM `pool_creature` WHERE `guid` BETWEEN @GUID+0 AND @GUID+24; + +INSERT INTO `pool_template` (`entry`, `max_limit`, `description`) VALUES +(@POOL+0, 1, 'ZG Before Bats 4-5 Pack Pool of Zulian Crocs Pool of Pools'), +(@POOL+1, 5, 'ZG Before Bats 5 Pack of Zulian Crocs 15043 50% 1/6'), +(@POOL+2, 4, 'ZG Before Bats 4 Pack of Zulian Crocs 15043 10% 2/6'), +(@POOL+3, 4, 'ZG Before Bats 4 Pack of Zulian Crocs 15043 10% 3/6'), +(@POOL+4, 4, 'ZG Before Bats 4 Pack of Zulian Crocs 15043 10% 4/6'), +(@POOL+5, 4, 'ZG Before Bats 4 Pack of Zulian Crocs 15043 10% 5/6'), +(@POOL+6, 4, 'ZG Before Bats 4 Pack of Zulian Crocs 15043 10% 6/6'); + +DELETE FROM `pool_pool` WHERE `pool_id` BETWEEN @POOL+0 AND @POOL+6; +DELETE FROM `pool_pool` WHERE `mother_pool` BETWEEN @POOL+0 AND @POOL+6; +INSERT INTO `pool_pool` (`pool_id`, `mother_pool`, `chance`, `description`) VALUES +(@POOL+1, @POOL+0, 50, 'ZG Before Bats 5 Pack of Zulian Crocs 1/1'), +(@POOL+2, @POOL+0, 10, 'ZG Before Bats 4 Pack of Zulian Crocs 1/5'), +(@POOL+3, @POOL+0, 10, 'ZG Before Bats 4 Pack of Zulian Crocs 2/5'), +(@POOL+4, @POOL+0, 10, 'ZG Before Bats 4 Pack of Zulian Crocs 3/5'), +(@POOL+5, @POOL+0, 10, 'ZG Before Bats 4 Pack of Zulian Crocs 4/5'), +(@POOL+6, @POOL+0, 10, 'ZG Before Bats 4 Pack of Zulian Crocs 5/5'); + +INSERT INTO `pool_creature` (`guid`, `pool_entry`, `description`) VALUES +-- +(@GUID+0, @POOL+1, 'ZG Before Bats 5 Pack of Zulian Crocs 1/1 Croc 1'), +(@GUID+1, @POOL+1, 'ZG Before Bats 5 Pack of Zulian Crocs 1/1 Croc 2'), +(@GUID+2, @POOL+1, 'ZG Before Bats 5 Pack of Zulian Crocs 1/1 Croc 3'), +(@GUID+3, @POOL+1, 'ZG Before Bats 5 Pack of Zulian Crocs 1/1 Croc 4'), +(@GUID+4, @POOL+1, 'ZG Before Bats 5 Pack of Zulian Crocs 1/1 Croc 5'), +-- +(@GUID+5, @POOL+2, 'ZG Before Bats 4 Pack of Zulian Crocs 1/5 Croc 1'), +(@GUID+6, @POOL+2, 'ZG Before Bats 4 Pack of Zulian Crocs 1/5 Croc 2'), +(@GUID+7, @POOL+2, 'ZG Before Bats 4 Pack of Zulian Crocs 1/5 Croc 3'), +(@GUID+8, @POOL+2, 'ZG Before Bats 4 Pack of Zulian Crocs 1/5 Croc 4'), +-- +(@GUID+9, @POOL+3, 'ZG Before Bats 4 Pack of Zulian Crocs 2/5 Croc 1'), +(@GUID+10, @POOL+3, 'ZG Before Bats 4 Pack of Zulian Crocs 2/5 Croc 2'), +(@GUID+11, @POOL+3, 'ZG Before Bats 4 Pack of Zulian Crocs 2/5 Croc 3'), +(@GUID+12, @POOL+3, 'ZG Before Bats 4 Pack of Zulian Crocs 2/5 Croc 4'), +-- +(@GUID+13, @POOL+4, 'ZG Before Bats 4 Pack of Zulian Crocs 3/5 Croc 1'), +(@GUID+14, @POOL+4, 'ZG Before Bats 4 Pack of Zulian Crocs 3/5 Croc 2'), +(@GUID+15, @POOL+4, 'ZG Before Bats 4 Pack of Zulian Crocs 3/5 Croc 3'), +(@GUID+16, @POOL+4, 'ZG Before Bats 4 Pack of Zulian Crocs 3/5 Croc 4'), +-- +(@GUID+17, @POOL+5, 'ZG Before Bats 4 Pack of Zulian Crocs 4/5 Croc 1'), +(@GUID+18, @POOL+5, 'ZG Before Bats 4 Pack of Zulian Crocs 4/5 Croc 2'), +(@GUID+19, @POOL+5, 'ZG Before Bats 4 Pack of Zulian Crocs 4/5 Croc 3'), +(@GUID+20, @POOL+5, 'ZG Before Bats 4 Pack of Zulian Crocs 4/5 Croc 4'), +-- +(@GUID+21, @POOL+6, 'ZG Before Bats 4 Pack of Zulian Crocs 5/5 Croc 1'), +(@GUID+22, @POOL+6, 'ZG Before Bats 4 Pack of Zulian Crocs 5/5 Croc 2'), +(@GUID+23, @POOL+6, 'ZG Before Bats 4 Pack of Zulian Crocs 5/5 Croc 3'), +(@GUID+24, @POOL+6, 'ZG Before Bats 4 Pack of Zulian Crocs 5/5 Croc 4'); + +DELETE FROM `creature_formations` WHERE `memberGUID` BETWEEN @GUID+0 AND @GUID+24; +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES +(@GUID+0, @GUID+0, 0, 0, 3, 0, 0), +(@GUID+0, @GUID+1, 0, 0, 3, 0, 0), +(@GUID+0, @GUID+2, 0, 0, 3, 0, 0), +(@GUID+0, @GUID+3, 0, 0, 3, 0, 0), +(@GUID+0, @GUID+4, 0, 0, 3, 0, 0), +-- +(@GUID+5, @GUID+5, 0, 0, 3, 0, 0), +(@GUID+5, @GUID+6, 0, 0, 3, 0, 0), +(@GUID+5, @GUID+7, 0, 0, 3, 0, 0), +(@GUID+5, @GUID+8, 0, 0, 3, 0, 0), +-- +(@GUID+9, @GUID+9, 0, 0, 3, 0, 0), +(@GUID+9, @GUID+10, 0, 0, 3, 0, 0), +(@GUID+9, @GUID+11, 0, 0, 3, 0, 0), +(@GUID+9, @GUID+12, 0, 0, 3, 0, 0), +-- +(@GUID+13, @GUID+13, 0, 0, 3, 0, 0), +(@GUID+13, @GUID+14, 0, 0, 3, 0, 0), +(@GUID+13, @GUID+15, 0, 0, 3, 0, 0), +(@GUID+13, @GUID+16, 0, 0, 3, 0, 0), +-- +(@GUID+17, @GUID+17, 0, 0, 3, 0, 0), +(@GUID+17, @GUID+18, 0, 0, 3, 0, 0), +(@GUID+17, @GUID+19, 0, 0, 3, 0, 0), +(@GUID+17, @GUID+20, 0, 0, 3, 0, 0), +-- +(@GUID+21, @GUID+21, 0, 0, 3, 0, 0), +(@GUID+21, @GUID+22, 0, 0, 3, 0, 0), +(@GUID+21, @GUID+23, 0, 0, 3, 0, 0), +(@GUID+21, @GUID+24, 0, 0, 3, 0, 0); diff --git a/data/sql/updates/db_world/2022_08_01_08.sql b/data/sql/updates/db_world/2022_08_01_08.sql new file mode 100644 index 000000000..8e5a967e0 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_01_08.sql @@ -0,0 +1,97 @@ +-- DB update 2022_08_01_07 -> 2022_08_01_08 + +SET @GUID :=86939; +DELETE FROM `creature_formations` WHERE `memberGUID` BETWEEN @GUID+0 AND @GUID+71; +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES +(@GUID+0, @GUID+0, 0, 0, 3, 0, 0), +(@GUID+0, @GUID+1, 0, 0, 3, 0, 0), +(@GUID+0, @GUID+2, 0, 0, 3, 0, 0), + +(@GUID+3, @GUID+3, 0, 0, 3, 0, 0), +(@GUID+3, @GUID+4, 0, 0, 3, 0, 0), +(@GUID+3, @GUID+5, 0, 0, 3, 0, 0), + +(@GUID+6, @GUID+6, 0, 0, 3, 0, 0), +(@GUID+6, @GUID+7, 0, 0, 3, 0, 0), +(@GUID+6, @GUID+8, 0, 0, 3, 0, 0), + +(@GUID+9, @GUID+9, 0, 0, 3, 0, 0), +(@GUID+9, @GUID+10, 0, 0, 3, 0, 0), +(@GUID+9, @GUID+11, 0, 0, 3, 0, 0), + +(@GUID+12, @GUID+12, 0, 0, 3, 0, 0), +(@GUID+12, @GUID+13, 0, 0, 3, 0, 0), +(@GUID+12, @GUID+14, 0, 0, 3, 0, 0), + +(@GUID+15, @GUID+15, 0, 0, 3, 0, 0), +(@GUID+15, @GUID+16, 0, 0, 3, 0, 0), +(@GUID+15, @GUID+17, 0, 0, 3, 0, 0), + +(@GUID+18, @GUID+18, 0, 0, 3, 0, 0), +(@GUID+18, @GUID+19, 0, 0, 3, 0, 0), +(@GUID+18, @GUID+20, 0, 0, 3, 0, 0), + +(@GUID+21, @GUID+21, 0, 0, 3, 0, 0), +(@GUID+21, @GUID+22, 0, 0, 3, 0, 0), +(@GUID+21, @GUID+23, 0, 0, 3, 0, 0), + +(@GUID+24, @GUID+24, 0, 0, 3, 0, 0), +(@GUID+24, @GUID+25, 0, 0, 3, 0, 0), +(@GUID+24, @GUID+26, 0, 0, 3, 0, 0), +(@GUID+24, @GUID+27, 0, 0, 3, 0, 0), + +(@GUID+28, @GUID+28, 0, 0, 3, 0, 0), +(@GUID+28, @GUID+29, 0, 0, 3, 0, 0), +(@GUID+28, @GUID+30, 0, 0, 3, 0, 0), +(@GUID+28, @GUID+31, 0, 0, 3, 0, 0), + +(@GUID+32, @GUID+32, 0, 0, 3, 0, 0), +(@GUID+32, @GUID+33, 0, 0, 3, 0, 0), +(@GUID+32, @GUID+34, 0, 0, 3, 0, 0), +(@GUID+32, @GUID+35, 0, 0, 3, 0, 0), + +(@GUID+36, @GUID+36, 0, 0, 3, 0, 0), +(@GUID+36, @GUID+37, 0, 0, 3, 0, 0), +(@GUID+36, @GUID+38, 0, 0, 3, 0, 0), +(@GUID+36, @GUID+39, 0, 0, 3, 0, 0), + +(@GUID+40, @GUID+40, 0, 0, 3, 0, 0), +(@GUID+40, @GUID+41, 0, 0, 3, 0, 0), +(@GUID+40, @GUID+42, 0, 0, 3, 0, 0), +(@GUID+40, @GUID+43, 0, 0, 3, 0, 0), + +(@GUID+44, @GUID+44, 0, 0, 3, 0, 0), +(@GUID+44, @GUID+45, 0, 0, 3, 0, 0), +(@GUID+44, @GUID+46, 0, 0, 3, 0, 0), +(@GUID+44, @GUID+47, 0, 0, 3, 0, 0), + +(@GUID+48, @GUID+48, 0, 0, 3, 0, 0), +(@GUID+48, @GUID+49, 0, 0, 3, 0, 0), +(@GUID+48, @GUID+50, 0, 0, 3, 0, 0), +(@GUID+48, @GUID+51, 0, 0, 3, 0, 0), + +(@GUID+52, @GUID+52, 0, 0, 3, 0, 0), +(@GUID+52, @GUID+53, 0, 0, 3, 0, 0), +(@GUID+52, @GUID+54, 0, 0, 3, 0, 0), +(@GUID+52, @GUID+55, 0, 0, 3, 0, 0), + +(@GUID+56, @GUID+56, 0, 0, 3, 0, 0), +(@GUID+56, @GUID+57, 0, 0, 3, 0, 0), +(@GUID+56, @GUID+58, 0, 0, 3, 0, 0), +(@GUID+56, @GUID+59, 0, 0, 3, 0, 0), + +(@GUID+60, @GUID+60, 0, 0, 3, 0, 0), +(@GUID+60, @GUID+61, 0, 0, 3, 0, 0), +(@GUID+60, @GUID+62, 0, 0, 3, 0, 0), +(@GUID+60, @GUID+63, 0, 0, 3, 0, 0), + +(@GUID+64, @GUID+64, 0, 0, 3, 0, 0), +(@GUID+64, @GUID+65, 0, 0, 3, 0, 0), +(@GUID+64, @GUID+66, 0, 0, 3, 0, 0), +(@GUID+64, @GUID+67, 0, 0, 3, 0, 0), + +(@GUID+68, @GUID+68, 0, 0, 3, 0, 0), +(@GUID+68, @GUID+69, 0, 0, 3, 0, 0), +(@GUID+68, @GUID+70, 0, 0, 3, 0, 0), +(@GUID+68, @GUID+71, 0, 0, 3, 0, 0); + diff --git a/data/sql/updates/db_world/2022_08_01_09.sql b/data/sql/updates/db_world/2022_08_01_09.sql new file mode 100644 index 000000000..e59e3359c --- /dev/null +++ b/data/sql/updates/db_world/2022_08_01_09.sql @@ -0,0 +1,5 @@ +-- DB update 2022_08_01_08 -> 2022_08_01_09 +-- +UPDATE `creature` SET `wander_distance`=16, `MovementType`=1 WHERE `guid`=21773; +UPDATE `creature` SET `wander_distance`=18, `MovementType`=1 WHERE `guid`=21774; +UPDATE `creature` SET `wander_distance`=15, `MovementType`=1 WHERE `guid`=21775; diff --git a/data/sql/updates/db_world/2022_08_01_10.sql b/data/sql/updates/db_world/2022_08_01_10.sql new file mode 100644 index 000000000..e27a8b215 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_01_10.sql @@ -0,0 +1,3 @@ +-- DB update 2022_08_01_09 -> 2022_08_01_10 +-- Undertaker Mordo https://classic.wowhead.com/npc=1568/undertaker-mordo +UPDATE `creature` SET `position_x` = 1671.89,`position_y` = 1678.29,`position_z` = 120.802, `orientation` = 0.0349066 WHERE `id1` = 1568; diff --git a/data/sql/updates/db_world/2022_08_01_11.sql b/data/sql/updates/db_world/2022_08_01_11.sql new file mode 100644 index 000000000..3664b560b --- /dev/null +++ b/data/sql/updates/db_world/2022_08_01_11.sql @@ -0,0 +1,121 @@ +-- DB update 2022_08_01_10 -> 2022_08_01_11 +-- +-- Maintenance on ZG Before Bats Part 4: Pooling Part 3 Standing Bats Pack +-- Old Locations Pre-work +DELETE FROM `creature` WHERE `guid` IN (49190, 49191, 49192, 49193); +DELETE FROM `creature_addon` WHERE `guid` IN (49190, 49191, 49192, 49193); + +/* Bat Pack in ZG Bat Rider (14750) should shift spawn positions with 11368 and they agro together as one + +INSERT INTO `creature` (`guid`, `id1`, `id2`, `id3`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`) VALUES +(@GUID+, , 0, 0, 309, 0, 0, 1, 1, 0, -11985.9, -1475.85, 79.7788, 1.59486, 7200, 2, 0, 5341, 0, 1, 0, 0, 0, '', 0), +(@GUID+, , 0, 0, 309, 0, 0, 1, 1, 0, -11978.2, -1464.7, 80.1628, 1.46608, 7200, 2, 0, 5341, 0, 1, 0, 0, 0, '', 0), +(@GUID+, , 0, 0, 309, 0, 0, 1, 1, 0, -11988.6, -1467.06, 80.3768, 1.98968, 7200, 2, 0, 5341, 0, 1, 0, 0, 0, '', 0), +(@GUID+, , 0, 0, 309, 0, 0, 1, 1, 0, -11981.1, -1475.36, 79.7364, 0.874606, 7200, 2, 0, 31440, 0, 1, 0, 0, 0, '', 0); + +This ZG Bat Rider had a row in creautre_addon--I could not find it anywhere in the sniff so it is not included, however noting it here for historical purposes: + +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) VALUES +(XRIDERX, 0, 0, 0, 4097, 0, 0, NULL); + +*/ + +-- Setup and auto-cleanup for pooling, creatures, and formations +SET @GUID :=56934; +SET @POOL :=479; +DELETE FROM `pool_template` WHERE `entry` BETWEEN @POOL+0 AND @POOL+4; +DELETE FROM `pool_creature` WHERE `guid` BETWEEN @GUID+0 AND @GUID+15; +DELETE FROM `pool_pool` WHERE `pool_id` BETWEEN @POOL+0 AND @POOL+4; +DELETE FROM `pool_pool` WHERE `mother_pool` BETWEEN @POOL+0 AND @POOL+4; +DELETE FROM `creature_formations` WHERE `memberGUID` BETWEEN @GUID+0 AND @GUID+15; +DELETE FROM `creature` WHERE `guid` BETWEEN @GUID+0 AND @GUID+15; + +-- Insert Creatures +INSERT INTO `creature` (`guid`, `id1`, `id2`, `id3`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`) VALUES +(@GUID+0, 14750, 0, 0, 309, 0, 0, 1, 1, 0, -11985.9, -1475.85, 79.7788, 1.59486, 7200, 2, 0, 5341, 0, 1, 0, 0, 0, '', 0), +(@GUID+1, 11368, 0, 0, 309, 0, 0, 1, 1, 0, -11978.2, -1464.7, 80.1628, 1.46608, 7200, 2, 0, 5341, 0, 1, 0, 0, 0, '', 0), +(@GUID+2, 11368, 0, 0, 309, 0, 0, 1, 1, 0, -11988.6, -1467.06, 80.3768, 1.98968, 7200, 2, 0, 5341, 0, 1, 0, 0, 0, '', 0), +(@GUID+3, 11368, 0, 0, 309, 0, 0, 1, 1, 0, -11981.1, -1475.36, 79.7364, 0.874606, 7200, 2, 0, 31440, 0, 1, 0, 0, 0, '', 0), + +(@GUID+4, 11368, 0, 0, 309, 0, 0, 1, 1, 0, -11985.9, -1475.85, 79.7788, 1.59486, 7200, 2, 0, 5341, 0, 1, 0, 0, 0, '', 0), +(@GUID+5, 14750, 0, 0, 309, 0, 0, 1, 1, 0, -11978.2, -1464.7, 80.1628, 1.46608, 7200, 2, 0, 5341, 0, 1, 0, 0, 0, '', 0), +(@GUID+6, 11368, 0, 0, 309, 0, 0, 1, 1, 0, -11988.6, -1467.06, 80.3768, 1.98968, 7200, 2, 0, 5341, 0, 1, 0, 0, 0, '', 0), +(@GUID+7, 11368, 0, 0, 309, 0, 0, 1, 1, 0, -11981.1, -1475.36, 79.7364, 0.874606, 7200, 2, 0, 31440, 0, 1, 0, 0, 0, '', 0), + +(@GUID+8, 11368, 0, 0, 309, 0, 0, 1, 1, 0, -11985.9, -1475.85, 79.7788, 1.59486, 7200, 2, 0, 5341, 0, 1, 0, 0, 0, '', 0), +(@GUID+9, 11368, 0, 0, 309, 0, 0, 1, 1, 0, -11978.2, -1464.7, 80.1628, 1.46608, 7200, 2, 0, 5341, 0, 1, 0, 0, 0, '', 0), +(@GUID+10, 14750, 0, 0, 309, 0, 0, 1, 1, 0, -11988.6, -1467.06, 80.3768, 1.98968, 7200, 2, 0, 5341, 0, 1, 0, 0, 0, '', 0), +(@GUID+11, 11368, 0, 0, 309, 0, 0, 1, 1, 0, -11981.1, -1475.36, 79.7364, 0.874606, 7200, 2, 0, 31440, 0, 1, 0, 0, 0, '', 0), + +(@GUID+12, 11368, 0, 0, 309, 0, 0, 1, 1, 0, -11985.9, -1475.85, 79.7788, 1.59486, 7200, 2, 0, 5341, 0, 1, 0, 0, 0, '', 0), +(@GUID+13, 11368, 0, 0, 309, 0, 0, 1, 1, 0, -11978.2, -1464.7, 80.1628, 1.46608, 7200, 2, 0, 5341, 0, 1, 0, 0, 0, '', 0), +(@GUID+14, 11368, 0, 0, 309, 0, 0, 1, 1, 0, -11988.6, -1467.06, 80.3768, 1.98968, 7200, 2, 0, 5341, 0, 1, 0, 0, 0, '', 0), +(@GUID+15, 14750, 0, 0, 309, 0, 0, 1, 1, 0, -11981.1, -1475.36, 79.7364, 0.874606, 7200, 2, 0, 31440, 0, 1, 0, 0, 0, '', 0); + +-- Insert Pooling + +INSERT INTO `pool_template` (`entry`, `max_limit`, `description`) VALUES +(@POOL+0, 1, 'ZG Before Bats Bat Pack Rider Location Shuffle'), +(@POOL+1, 4, 'ZG Before Bats Bat Pack Loc 1/4'), +(@POOL+2, 4, 'ZG Before Bats Bat Pack Loc 2/4'), +(@POOL+3, 4, 'ZG Before Bats Bat Pack Loc 3/4'), +(@POOL+4, 4, 'ZG Before Bats Bat Pack Loc 4/4'); + +INSERT INTO `pool_pool` (`pool_id`, `mother_pool`, `chance`, `description`) VALUES +(@POOL+1, @POOL+0, 25, 'ZG Before Bats Bat Pack Loc 1'), +(@POOL+2, @POOL+0, 25, 'ZG Before Bats Bat Pack Loc 2'), +(@POOL+3, @POOL+0, 25, 'ZG Before Bats Bat Pack Loc 3'), +(@POOL+4, @POOL+0, 25, 'ZG Before Bats Bat Pack Loc 4'); + +INSERT INTO `pool_creature` (`guid`, `pool_entry`, `description`) VALUES + +(@GUID+0, @POOL+1, 'ZG Before Bats Bat Pack Loc 1 Rider'), +(@GUID+1, @POOL+1, 'ZG Before Bats Bat Pack Loc 1 Bat'), +(@GUID+2, @POOL+1, 'ZG Before Bats Bat Pack Loc 1 Bat'), +(@GUID+3, @POOL+1, 'ZG Before Bats Bat Pack Loc 1 Bat'), + +(@GUID+4, @POOL+2, 'ZG Before Bats Bat Pack Loc 2 Bat'), +(@GUID+5, @POOL+2, 'ZG Before Bats Bat Pack Loc 2 Rider'), +(@GUID+6, @POOL+2, 'ZG Before Bats Bat Pack Loc 2 Bat'), +(@GUID+7, @POOL+2, 'ZG Before Bats Bat Pack Loc 2 Bat'), + +(@GUID+8, @POOL+3, 'ZG Before Bats Bat Pack Loc 3 Bat'), +(@GUID+9, @POOL+3, 'ZG Before Bats Bat Pack Loc 3 Bat'), +(@GUID+10, @POOL+3, 'ZG Before Bats Bat Pack Loc 3 Rider'), +(@GUID+11, @POOL+3, 'ZG Before Bats Bat Pack Loc 3 Bat'), + +(@GUID+12, @POOL+4, 'ZG Before Bats Bat Pack Loc 4 Bat'), +(@GUID+13, @POOL+4, 'ZG Before Bats Bat Pack Loc 4 Bat'), +(@GUID+14, @POOL+4, 'ZG Before Bats Bat Pack Loc 4 Bat'), +(@GUID+15, @POOL+4, 'ZG Before Bats Bat Pack Loc 4 Rider'); + +-- Insert Formations + +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES +(@GUID+0, @GUID+0, 0, 0, 3, 0, 0), +(@GUID+0, @GUID+1, 0, 0, 3, 0, 0), +(@GUID+0, @GUID+2, 0, 0, 3, 0, 0), +(@GUID+0, @GUID+3, 0, 0, 3, 0, 0), + +(@GUID+4, @GUID+4, 0, 0, 3, 0, 0), +(@GUID+4, @GUID+5, 0, 0, 3, 0, 0), +(@GUID+4, @GUID+6, 0, 0, 3, 0, 0), +(@GUID+4, @GUID+7, 0, 0, 3, 0, 0), + +(@GUID+8, @GUID+8, 0, 0, 3, 0, 0), +(@GUID+8, @GUID+9, 0, 0, 3, 0, 0), +(@GUID+8, @GUID+10, 0, 0, 3, 0, 0), +(@GUID+8, @GUID+11, 0, 0, 3, 0, 0), + +(@GUID+12, @GUID+12, 0, 0, 3, 0, 0), +(@GUID+12, @GUID+13, 0, 0, 3, 0, 0), +(@GUID+12, @GUID+14, 0, 0, 3, 0, 0), +(@GUID+12, @GUID+15, 0, 0, 3, 0, 0); + +-- Maintenance on ZG Before Bats Part 5: Agro linking via creature_formations +DELETE FROM `creature_formations` WHERE `memberGUID` IN (49753, 49754, 49096, 49097); +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES +(49753, 49753, 0, 0, 3, 0, 0), +(49753, 49754, 0, 0, 3, 0, 0), +(49753, 49096, 0, 0, 3, 0, 0), +(49753, 49097, 0, 0, 3, 0, 0); diff --git a/data/sql/updates/db_world/2022_08_01_12.sql b/data/sql/updates/db_world/2022_08_01_12.sql new file mode 100644 index 000000000..a07f650b6 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_01_12.sql @@ -0,0 +1,11 @@ +-- DB update 2022_08_01_11 -> 2022_08_01_12 +-- +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 11831; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 11831); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(11831, 0, 0, 0, 4, 0, 30, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Hakkari Witch Doctor - On Aggro - Say Line 0'), +(11831, 0, 1, 0, 0, 0, 100, 0, 3000, 8000, 5000, 8000, 0, 11, 24053, 4, 32, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 'Hakkari Witch Doctor - In Combat - Cast \'Hex\''), +(11831, 0, 2, 0, 0, 0, 100, 0, 1000, 3000, 3000, 5000, 0, 11, 17289, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Hakkari Witch Doctor - In Combat - Cast \'Shadow Shock\''), +(11831, 0, 3, 0, 0, 0, 100, 0, 5000, 15000, 5000, 10000, 0, 11, 24054, 1, 32, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Hakkari Witch Doctor - In Combat - Cast \'Shrink\''), +(11831, 0, 4, 0, 0, 0, 100, 1, 7500, 125000, 0, 0, 0, 11, 24052, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Hakkari Witch Doctor - In Combat - Cast \'Summon Voodoo Spirit\' (No Repeat)'); diff --git a/data/sql/updates/db_world/2022_08_01_13.sql b/data/sql/updates/db_world/2022_08_01_13.sql new file mode 100644 index 000000000..fe6baf573 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_01_13.sql @@ -0,0 +1,9 @@ +-- DB update 2022_08_01_12 -> 2022_08_01_13 +DELETE FROM `creature` WHERE `guid` IN (161044, 161045, 161046); +INSERT INTO `creature` (`guid`, `id1`, `id2`, `id3`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`) VALUES +(161044, 1128, 0, 0, 0, 0, 0, 1, 1, 0, -4310.01, -1447.54, 400.56363, 3.93681, 120, 19, 0, 122, 0, 1, 0, 0, 0, '', 0), +(161045, 1128, 0, 0, 0, 0, 0, 1, 1, 0, -4293.55, -1431.15, 390.08798, 2.1588, 120, 13, 0, 144, 0, 1, 0, 0, 0, '', 0), +(161046, 1129, 0, 0, 0, 0, 0, 1, 1, 0, -4300.36, -1420.53, 391.496, 5.16617, 120, 0, 0, 144, 0, 0, 0, 0, 0, '', 0); + +DELETE FROM `creature_addon` WHERE `guid` = 161046; +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) VALUES (161046, 0, 0, 1, 0, 0, 0, NULL); diff --git a/data/sql/updates/db_world/2022_08_01_14.sql b/data/sql/updates/db_world/2022_08_01_14.sql new file mode 100644 index 000000000..140dd97e4 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_01_14.sql @@ -0,0 +1,4 @@ +-- DB update 2022_08_01_13 -> 2022_08_01_14 +-- +UPDATE `creature_template` SET `unit_flags`=`unit_flags`|33554432 WHERE `entry`=14459; + diff --git a/data/sql/updates/db_world/2022_08_01_15.sql b/data/sql/updates/db_world/2022_08_01_15.sql new file mode 100644 index 000000000..612ae20ee --- /dev/null +++ b/data/sql/updates/db_world/2022_08_01_15.sql @@ -0,0 +1,7 @@ +-- DB update 2022_08_01_14 -> 2022_08_01_15 +-- +DELETE FROM `spell_linked_spell` WHERE `spell_trigger` = 25654 AND `spell_effect` = 6608; +INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES +(25654, 6608, 1, 'Hive\'Zara Tail Lasher: On Tail Lash - Apply Dropped Weapon'); + +UPDATE `smart_scripts` SET `event_param3`=10900, `event_param4`=23100 WHERE `entryorguid`=15336 AND `source_type`=0 AND `id`=4 AND `link`=0; diff --git a/data/sql/updates/db_world/2022_08_01_16.sql b/data/sql/updates/db_world/2022_08_01_16.sql new file mode 100644 index 000000000..05ad28c8d --- /dev/null +++ b/data/sql/updates/db_world/2022_08_01_16.sql @@ -0,0 +1,36 @@ +-- DB update 2022_08_01_15 -> 2022_08_01_16 +-- +-- Maintenance on ZG Before Bats Part 3: Pooling Part 2 Troll Pack before Bat Area +-- Formations shouldn't be needed on this pack (they agro properly without) + +-- Pool Troll pack before Bat area (49120, 49121, 49122) with it's counterpart, (created as 12814, 12815, 12816) +DELETE FROM `creature` WHERE `guid` BETWEEN 12814 AND 12816; +INSERT INTO `creature` (`guid`, `id1`, `id2`, `id3`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`) VALUES +(12814, 11831, 0, 0, 309, 0, 0, 1, 1, 1, -12007.2, -1492.45, 82.0241, 1.39626, 7200, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), +(12815, 11831, 0, 0, 309, 0, 0, 1, 1, 1, -12008.5, -1484.79, 79.1498, 4.87654, 7200, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), +(12816, 11351, 0, 0, 309, 0, 0, 1, 1, 1, -12004.5, -1483.46, 79.5746, 4.71553, 7200, 0, 0, 0, 0, 0, 0, 0, 0, '', 0); + +DELETE FROM `pool_template` WHERE `entry` BETWEEN 476 AND 478; +DELETE FROM `pool_pool` WHERE `pool_id` BETWEEN 476 AND 478; +DELETE FROM `pool_pool` WHERE `mother_pool` BETWEEN 476 AND 478; +DELETE FROM `pool_creature` WHERE `pool_entry` BETWEEN 476 AND 478; +DELETE FROM `pool_creature` WHERE `guid` IN (49120, 49121, 49122, 12814, 12815, 12816); + + +INSERT INTO `pool_template` (`entry`, `max_limit`, `description`) VALUES +(476, 1, 'ZG Before Bats Troll 3-Pack'), +(477, 3, 'ZG Before Bats Troll 3-Pack with 2x entry 11831 50% 1/2'), +(478, 3, 'ZG Before Bats Troll 3-Pack with 2x entry 11351 50% 2/2'); + +INSERT INTO `pool_pool` (`pool_id`, `mother_pool`, `chance`, `description`) VALUES +(477, 476, 50, 'ZG Before Bats Troll 3-Pack with 2x entry 11831'), +(478, 476, 50, 'ZG Before Bats Troll 3-Pack with 2x entry 11351'); + +INSERT INTO `pool_creature` (`guid`, `pool_entry`, `description`) VALUES +(12814, 477, 'ZG Before Bats Troll 3-Pack entry 11831'), +(12815, 477, 'ZG Before Bats Troll 3-Pack entry 11831'), +(12816, 477, 'ZG Before Bats Troll 3-Pack entry 11351'), + +(49120, 478, 'ZG Before Bats Troll 3-Pack entry 11351'), +(49121, 478, 'ZG Before Bats Troll 3-Pack entry 11351'), +(49122, 478, 'ZG Before Bats Troll 3-Pack entry 11831'); diff --git a/data/sql/updates/db_world/2022_08_01_17.sql b/data/sql/updates/db_world/2022_08_01_17.sql new file mode 100644 index 000000000..5546977e4 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_01_17.sql @@ -0,0 +1,22 @@ +-- DB update 2022_08_01_16 -> 2022_08_01_17 +-- +DELETE FROM `creature_text` WHERE `CreatureID` = 15320 AND `GroupID` = 0; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration` ,`Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(15320, 0, 0, '%s counterattacks with retaliation.', 16, 0, 100, 0, 0, 0, 11018, 0, 'Hive\'Zara Soldier - On Retaliation'); + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 15320) AND (`source_type` = 0) AND (`id` IN (0, 1, 2)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `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 +(15320, 0, 0, 2, 2, 0, 100, 1, 0, 30, 0, 0, 0, 11, 22857, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Hive\'Zara Soldier - Between 0-30% Health - Cast \'Retaliation\' (No Repeat)'), +(15320, 0, 1, 0, 9, 0, 100, 0, 0, 30, 10000, 18200, 0, 11, 25497, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Hive\'Zara Soldier - Within 0-30 Range - Cast \'Venom Spit\''), +(15320, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Hive\'Zara Soldier - Between 0-30% Health - Say Line 0 (No Repeat)'); + +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 15344; + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 15344) 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`, `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 +(15344, 0, 0, 0, 0, 0, 100, 0, 4850, 18250, 4850, 18250, 0, 11, 40504, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Swarmguard Needler - In Combat - Cast \'Cleave\''); + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 15387) AND (`source_type` = 0) AND (`id` IN (2,3)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `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 +(15387, 0, 2, 0, 0, 0, 100, 0, 3600, 14600, 3600, 14600, 0, 11, 10966, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Qiraji Warrior - In Combat - Cast \'Uppercut\''), +(15387, 0, 3, 0, 0, 0, 100, 0, 40000, 70000, 40000, 70000, 0, 11, 15588, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Qiraji Warrior - In Combat - Cast \'Thunderclap\''); diff --git a/data/sql/updates/db_world/2022_08_01_18.sql b/data/sql/updates/db_world/2022_08_01_18.sql new file mode 100644 index 000000000..43752e8b2 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_01_18.sql @@ -0,0 +1,9 @@ +-- DB update 2022_08_01_17 -> 2022_08_01_18 +-- +DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_crystal_weakness'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(25177, 'spell_crystal_weakness'), +(25178, 'spell_crystal_weakness'), +(25180, 'spell_crystal_weakness'), +(25181, 'spell_crystal_weakness'), +(25183, 'spell_crystal_weakness'); diff --git a/data/sql/updates/db_world/2022_08_05_00.sql b/data/sql/updates/db_world/2022_08_05_00.sql new file mode 100644 index 000000000..f68faea28 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_05_00.sql @@ -0,0 +1,3 @@ +-- DB update 2022_08_01_18 -> 2022_08_05_00 +-- +UPDATE `smart_scripts` SET `action_param1` = 0 WHERE `entryorguid` = 2700300 AND `source_type` = 9 AND `id` = 1; diff --git a/data/sql/updates/db_world/2022_08_06_00.sql b/data/sql/updates/db_world/2022_08_06_00.sql new file mode 100644 index 000000000..281f834fe --- /dev/null +++ b/data/sql/updates/db_world/2022_08_06_00.sql @@ -0,0 +1,5 @@ +-- DB update 2022_08_05_00 -> 2022_08_06_00 +-- +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=28757; +INSERT INTO `spell_linked_spell` VALUES +(28757,28758,0,'Stalker\'s Ally'); diff --git a/data/sql/updates/db_world/2022_08_06_01.sql b/data/sql/updates/db_world/2022_08_06_01.sql new file mode 100644 index 000000000..f5375864f --- /dev/null +++ b/data/sql/updates/db_world/2022_08_06_01.sql @@ -0,0 +1,85 @@ +-- DB update 2022_08_06_00 -> 2022_08_06_01 +-- +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 15391; + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 15391) AND (`source_type` = 0) AND (`id` IN (0, 1, 2, 3, 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`, `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 +(15391, 0, 0, 0, 0, 0, 100, 2, 10000, 11000, 8000, 9000, 0, 11, 24317, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Qeez - In Combat - Cast \'Sunder Armor\' (Normal Dungeon)'), +(15391, 0, 1, 0, 0, 0, 100, 2, 12000, 13000, 14000, 15000, 0, 11, 19134, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Qeez - In Combat - Cast \'Frightening Shout\' (Normal Dungeon)'), +(15391, 0, 2, 0, 0, 0, 100, 514, 13000, 17000, 14000, 18000, 0, 23, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Qeez - In Combat - Increment Phase (Normal Dungeon)'), +(15391, 0, 3, 0, 0, 1, 100, 2, 1000, 1000, 1000, 1000, 0, 11, 40504, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Qeez - In Combat - Cast \'Cleave\' (Phase 1) (Normal Dungeon)'), +(15391, 0, 4, 0, 0, 1, 100, 2, 2000, 2000, 2000, 2000, 0, 11, 40504, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Qeez - In Combat - Cast \'Cleave\' (Phase 1) (Normal Dungeon)'), +(15391, 0, 5, 0, 0, 1, 100, 514, 3000, 3000, 3000, 3000, 0, 23, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Qeez - In Combat - Decrement Phase (Phase 1) (Normal Dungeon)'), +(15391, 0, 6, 0, 4, 0, 100, 0, 0, 0, 0, 0, 0, 34, 1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Qeez - On Aggro - Set Instance Data 1 to 8'); + +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 15392; + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 15392) AND (`source_type` = 0) AND (`id` IN (0, 1, 2, 3, 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`, `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 +(15392, 0, 0, 0, 0, 0, 100, 2, 10000, 11000, 8000, 9000, 0, 11, 24317, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Tuubid - In Combat - Cast \'Sunder Armor\' (Normal Dungeon)'), +(15392, 0, 1, 0, 0, 0, 100, 2, 12000, 13000, 14000, 15000, 0, 11, 25471, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Tuubid - In Combat - Cast \'Attack Order\' (Normal Dungeon)'), +(15392, 0, 2, 0, 0, 0, 100, 514, 13000, 17000, 14000, 18000, 0, 23, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Tuubid - In Combat - Increment Phase (Normal Dungeon)'), +(15392, 0, 3, 0, 0, 1, 100, 2, 1000, 1000, 1000, 1000, 0, 11, 40504, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Tuubid - In Combat - Cast \'Cleave\' (Phase 1) (Normal Dungeon)'), +(15392, 0, 4, 0, 0, 1, 100, 2, 2000, 2000, 2000, 2000, 0, 11, 40504, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Tuubid - In Combat - Cast \'Cleave\' (Phase 1) (Normal Dungeon)'), +(15392, 0, 5, 0, 0, 1, 100, 514, 3000, 3000, 3000, 3000, 0, 23, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Tuubid - In Combat - Decrement Phase (Phase 1) (Normal Dungeon)'), +(15392, 0, 6, 0, 4, 0, 100, 0, 0, 0, 0, 0, 0, 34, 1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Tuubid - On Aggro - Set Instance Data 1 to 9'); + +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 15389; + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 15389) AND (`source_type` = 0) AND (`id` IN (0, 1, 2, 3, 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`, `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 +(15389, 0, 0, 0, 0, 0, 100, 2, 10000, 11000, 8000, 9000, 0, 11, 24317, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Drenn - In Combat - Cast \'Sunder Armor\' (Normal Dungeon)'), +(15389, 0, 1, 0, 0, 0, 100, 2, 12000, 13000, 14000, 15000, 0, 11, 26550, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Drenn - In Combat - Cast \'Lightning Cloud\' (Normal Dungeon)'), +(15389, 0, 2, 0, 0, 0, 100, 514, 13000, 17000, 14000, 18000, 0, 23, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Drenn - In Combat - Increment Phase (Normal Dungeon)'), +(15389, 0, 3, 0, 0, 1, 100, 2, 1000, 1000, 1000, 1000, 0, 11, 40504, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Drenn - In Combat - Cast \'Cleave\' (Phase 1) (Normal Dungeon)'), +(15389, 0, 4, 0, 0, 1, 100, 2, 2000, 2000, 2000, 2000, 0, 11, 40504, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Drenn - In Combat - Cast \'Cleave\' (Phase 1) (Normal Dungeon)'), +(15389, 0, 5, 0, 0, 1, 100, 514, 3000, 3000, 3000, 3000, 0, 23, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Drenn - In Combat - Decrement Phase (Phase 1) (Normal Dungeon)'), +(15389, 0, 6, 0, 4, 0, 100, 0, 0, 0, 0, 0, 0, 34, 1, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Drenn - On Aggro - Set Instance Data 1 to 10'); + +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 15390; + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 15390) AND (`source_type` = 0) AND (`id` IN (0, 1, 2, 3, 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`, `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 +(15390, 0, 0, 0, 0, 0, 100, 2, 10000, 11000, 8000, 9000, 0, 11, 24317, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Xurrem - In Combat - Cast \'Sunder Armor\' (Normal Dungeon)'), +(15390, 0, 1, 0, 0, 0, 100, 2, 12000, 13000, 14000, 15000, 0, 11, 25425, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Xurrem - In Combat - Cast \'Shockwave\' (Normal Dungeon)'), +(15390, 0, 2, 0, 0, 0, 100, 514, 13000, 17000, 14000, 18000, 0, 23, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Xurrem - In Combat - Increment Phase (Normal Dungeon)'), +(15390, 0, 3, 0, 0, 1, 100, 2, 1000, 1000, 1000, 1000, 0, 11, 40504, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Xurrem - In Combat - Cast \'Cleave\' (Phase 1) (Normal Dungeon)'), +(15390, 0, 4, 0, 0, 1, 100, 2, 2000, 2000, 2000, 2000, 0, 11, 40504, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Xurrem - In Combat - Cast \'Cleave\' (Phase 1) (Normal Dungeon)'), +(15390, 0, 5, 0, 0, 1, 100, 514, 3000, 3000, 3000, 3000, 0, 23, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Xurrem - In Combat - Decrement Phase (Phase 1) (Normal Dungeon)'), +(15390, 0, 6, 0, 4, 0, 100, 0, 0, 0, 0, 0, 0, 34, 1, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Captain Xurrem - On Aggro - Set Instance Data 1 to 11'); + +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 15386; + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 15386) AND (`source_type` = 0) AND (`id` IN (0, 1, 2, 3, 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`, `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 +(15386, 0, 0, 0, 0, 0, 100, 2, 10000, 11000, 8000, 9000, 0, 11, 24317, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Major Yeggeth - In Combat - Cast \'Sunder Armor\' (Normal Dungeon)'), +(15386, 0, 1, 0, 0, 0, 100, 2, 12000, 13000, 8000, 9000, 0, 11, 25282, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 'Major Yeggeth - In Combat - Cast \'Shield of Rajaxx\' (Normal Dungeon)'), +(15386, 0, 2, 0, 0, 0, 100, 514, 13000, 17000, 14000, 18000, 0, 23, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Major Yeggeth - In Combat - Increment Phase (Normal Dungeon)'), +(15386, 0, 3, 0, 0, 1, 100, 2, 1000, 1000, 1000, 1000, 0, 11, 40504, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Major Yeggeth - In Combat - Cast \'Cleave\' (Phase 1) (Normal Dungeon)'), +(15386, 0, 4, 0, 0, 1, 100, 2, 2000, 2000, 2000, 2000, 0, 11, 40504, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Major Yeggeth - In Combat - Cast \'Cleave\' (Phase 1) (Normal Dungeon)'), +(15386, 0, 5, 0, 0, 1, 100, 514, 3000, 3000, 3000, 3000, 0, 23, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Major Yeggeth - In Combat - Decrement Phase (Phase 1) (Normal Dungeon)'), +(15386, 0, 6, 0, 4, 0, 100, 0, 0, 0, 0, 0, 0, 34, 1, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Major Yeggeth - On Aggro - Set Instance Data 1 to 12'); + +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 15388; + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 15388) AND (`source_type` = 0) AND (`id` IN (0, 1, 2, 3, 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`, `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 +(15388, 0, 0, 0, 0, 0, 100, 2, 10000, 11000, 8000, 9000, 0, 11, 24317, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Major Pakkon - In Combat - Cast \'Sunder Armor\' (Normal Dungeon)'), +(15388, 0, 1, 0, 0, 0, 100, 2, 12000, 13000, 14000, 15000, 0, 11, 25322, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Major Pakkon - In Combat - Cast \'Sweeping Slam\' (Normal Dungeon)'), +(15388, 0, 2, 0, 0, 0, 100, 514, 13000, 17000, 14000, 18000, 0, 23, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Major Pakkon - In Combat - Increment Phase (Normal Dungeon)'), +(15388, 0, 3, 0, 0, 1, 100, 2, 1000, 1000, 1000, 1000, 0, 11, 40504, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Major Pakkon - In Combat - Cast \'Cleave\' (Phase 1) (Normal Dungeon)'), +(15388, 0, 4, 0, 0, 1, 100, 2, 2000, 2000, 2000, 2000, 0, 11, 40504, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Major Pakkon - In Combat - Cast \'Cleave\' (Phase 1) (Normal Dungeon)'), +(15388, 0, 5, 0, 0, 1, 100, 514, 3000, 3000, 3000, 3000, 0, 23, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Major Pakkon - In Combat - Decrement Phase (Phase 1) (Normal Dungeon)'), +(15388, 0, 6, 0, 4, 0, 100, 0, 0, 0, 0, 0, 0, 34, 1, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Major Pakkon - On Aggro - Set Instance Data 1 to 13'); + +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 15385; + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 15385) AND (`source_type` = 0) AND (`id` IN (0, 1, 2, 3, 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`, `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 +(15385, 0, 0, 0, 0, 0, 100, 2, 10000, 11000, 8000, 9000, 0, 11, 24317, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Colonel Zerran - In Combat - Cast \'Sunder Armor\' (Normal Dungeon)'), +(15385, 0, 1, 0, 0, 0, 100, 2, 12000, 13000, 8000, 9000, 0, 11, 25462, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 'Colonel Zerran - In Combat - Cast \'Enlarge\' (Normal Dungeon)'), +(15385, 0, 2, 0, 0, 0, 100, 514, 13000, 17000, 14000, 18000, 0, 23, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Colonel Zerran - In Combat - Increment Phase (Normal Dungeon)'), +(15385, 0, 3, 0, 0, 1, 100, 2, 1000, 1000, 1000, 1000, 0, 11, 40504, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Colonel Zerran - In Combat - Cast \'Cleave\' (Phase 1) (Normal Dungeon)'), +(15385, 0, 4, 0, 0, 1, 100, 2, 2000, 2000, 2000, 2000, 0, 11, 40504, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Colonel Zerran - In Combat - Cast \'Cleave\' (Phase 1) (Normal Dungeon)'), +(15385, 0, 5, 0, 0, 1, 100, 514, 3000, 3000, 3000, 3000, 0, 23, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Colonel Zerran - In Combat - Decrement Phase (Phase 1) (Normal Dungeon)'), +(15385, 0, 6, 0, 4, 0, 100, 0, 0, 0, 0, 0, 0, 34, 1, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Colonel Zerran - On Aggro - Set Instance Data 1 to 14'); diff --git a/data/sql/updates/db_world/2022_08_07_00.sql b/data/sql/updates/db_world/2022_08_07_00.sql new file mode 100644 index 000000000..2259de526 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_07_00.sql @@ -0,0 +1,3 @@ +-- DB update 2022_08_06_01 -> 2022_08_07_00 +-- +UPDATE `gameobject_template` SET `data3`=8000 WHERE `entry`=180619; diff --git a/data/sql/updates/db_world/2022_08_07_01.sql b/data/sql/updates/db_world/2022_08_07_01.sql new file mode 100644 index 000000000..c8d0469dc --- /dev/null +++ b/data/sql/updates/db_world/2022_08_07_01.sql @@ -0,0 +1,5 @@ +-- DB update 2022_08_07_00 -> 2022_08_07_01 +-- +UPDATE `smart_scripts` SET `event_type`=0, `event_param1`=7000, `event_param2`=10000 WHERE `entryorguid`=15336 AND `source_type`=0 AND `id`=4 AND `link`=0; +UPDATE `smart_scripts` SET `event_type`=0, `event_param1`=10000, `event_param2`=16000, `event_param3`=21800, `event_param4`=34400 WHERE `entryorguid`=15319 AND `source_type`=0 AND `id`=0 AND `link`=0; +UPDATE `smart_scripts` SET `event_param1`=12000, `event_param2`=15000, `event_param3`=26700, `event_param4`=36500 WHERE `entryorguid`=15319 AND `source_type`=0 AND `id`=1 AND `link`=0; diff --git a/data/sql/updates/db_world/2022_08_07_02.sql b/data/sql/updates/db_world/2022_08_07_02.sql new file mode 100644 index 000000000..d507e5ee6 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_07_02.sql @@ -0,0 +1,40 @@ +-- DB update 2022_08_07_01 -> 2022_08_07_02 +-- +DELETE FROM `creature_formations` WHERE `leaderguid` IN (144466, 144476, 144473, 144469, 144481, 144470, 144452, 144456, 144454); +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES +(144466, 144466, 0, 0, 3, 0, 0), +(144466, 144474, 0, 0, 3, 0, 0), +(144466, 144475, 0, 0, 3, 0, 0), +(144476, 144476, 0, 0, 3, 0, 0), +(144476, 144467, 0, 0, 3, 0, 0), +(144476, 144468, 0, 0, 3, 0, 0), +(144473, 144473, 0, 0, 3, 0, 0), +(144473, 144464, 0, 0, 3, 0, 0), +(144473, 144465, 0, 0, 3, 0, 0), +(144469, 144469, 0, 0, 3, 0, 0), +(144469, 144477, 0, 0, 3, 0, 0), +(144469, 144478, 0, 0, 3, 0, 0), +(144481, 144481, 0, 0, 3, 0, 0), +(144481, 144471, 0, 0, 3, 0, 0), +(144481, 144472, 0, 0, 3, 0, 0), +(144470, 144470, 0, 0, 3, 0, 0), +(144470, 144479, 0, 0, 3, 0, 0), +(144470, 144480, 0, 0, 3, 0, 0), +(144452, 144452, 0, 0, 3, 0, 0), +(144452, 144453, 0, 0, 3, 0, 0), +(144452, 144458, 0, 0, 3, 0, 0), +(144452, 144459, 0, 0, 3, 0, 0), +(144452, 144586, 0, 0, 3, 0, 0), +(144452, 144587, 0, 0, 3, 0, 0), +(144456, 144456, 0, 0, 3, 0, 0), +(144456, 144457, 0, 0, 3, 0, 0), +(144456, 144462, 0, 0, 3, 0, 0), +(144456, 144463, 0, 0, 3, 0, 0), +(144456, 144590, 0, 0, 3, 0, 0), +(144456, 144591, 0, 0, 3, 0, 0), +(144454, 144454, 0, 0, 3, 0, 0), +(144454, 144455, 0, 0, 3, 0, 0), +(144454, 144460, 0, 0, 3, 0, 0), +(144454, 144461, 0, 0, 3, 0, 0), +(144454, 144588, 0, 0, 3, 0, 0), +(144454, 144589, 0, 0, 3, 0, 0); diff --git a/data/sql/updates/db_world/2022_08_07_03.sql b/data/sql/updates/db_world/2022_08_07_03.sql new file mode 100644 index 000000000..bedff5b58 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_07_03.sql @@ -0,0 +1,7 @@ +-- DB update 2022_08_07_02 -> 2022_08_07_03 +-- +UPDATE `creature_template_addon` SET `auras` = '' WHERE (`entry` = 15385); + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 15385) AND (`source_type` = 0) AND (`id` IN (1)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `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 +(15385, 0, 1, 0, 0, 0, 100, 2, 12000, 13000, 20000, 26000, 0, 11, 25462, 32, 0, 0, 0, 0, 26, 20, 0, 0, 0, 0, 0, 0, 0, 'Colonel Zerran - In Combat - Cast \'Enlarge\''); diff --git a/data/sql/updates/db_world/2022_08_07_04.sql b/data/sql/updates/db_world/2022_08_07_04.sql new file mode 100644 index 000000000..f1f84b3a0 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_07_04.sql @@ -0,0 +1,14 @@ +-- DB update 2022_08_07_03 -> 2022_08_07_04 +-- +UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=5316 WHERE `MenuID`=435 AND `OptionID`=0; +UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=3428 WHERE `MenuID`=435 AND `OptionID`=6; +UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=9756 WHERE `MenuID`=435 AND `OptionID`=10; +UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=10359 WHERE `MenuID`=435 AND `OptionID`=11; + +UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=2870 WHERE `MenuID`=1951 AND `OptionID`=2; +UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=4895 WHERE `MenuID`=1951 AND `OptionID`=4; +UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=5316 WHERE `MenuID`=1951 AND `OptionID`=5; +UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=5518 WHERE `MenuID`=1951 AND `OptionID`=6; +UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=7253 WHERE `MenuID`=1951 AND `OptionID`=7; +UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=9756 WHERE `MenuID`=1951 AND `OptionID`=9; +UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=10359 WHERE `MenuID`=1951 AND `OptionID`=10; diff --git a/data/sql/updates/db_world/2022_08_07_05.sql b/data/sql/updates/db_world/2022_08_07_05.sql new file mode 100644 index 000000000..b4f866e56 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_07_05.sql @@ -0,0 +1,10 @@ +-- DB update 2022_08_07_04 -> 2022_08_07_05 +DELETE FROM `gameobject` WHERE `id` = 176966; +DELETE FROM `gameobject` WHERE `guid` = 75160; +INSERT INTO `gameobject` (`guid`, `id`, `map`, `zoneId`, `areaId`, + `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, + `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, + `spawntimesecs`, `animprogress`, `state`, `ScriptName`, `VerifiedBuild`) +VALUES (75160, 176966, 469, 0, 0, 1, 1, -7488.1, -1150.7, 476.535, 3.73064, -0.0, + -0.0, -0.95694, 0.290285, 300, 0, 1, 'Nefarian\'s Gate', 0); +UPDATE `gameobject_template_addon` SET `flags` = `flags`|16 WHERE `entry` = 176966; diff --git a/data/sql/updates/db_world/2022_08_07_06.sql b/data/sql/updates/db_world/2022_08_07_06.sql new file mode 100644 index 000000000..6b01fd86c --- /dev/null +++ b/data/sql/updates/db_world/2022_08_07_06.sql @@ -0,0 +1,12 @@ +-- DB update 2022_08_07_05 -> 2022_08_07_06 +-- +UPDATE `creature_template` SET `lootid` = 0, `skinloot` = 0, `mingold` = 0, `maxgold` = 0 WHERE (`entry` = 11374); +DELETE FROM `creature_loot_template` WHERE `entry` = 11374; + +UPDATE `creature_template` SET `skinloot` = 0 WHERE (`entry` = 10596); + +UPDATE `creature_template` SET `lootid` = 0, `skinloot` = 0 WHERE (`entry` = 15101); +DELETE FROM `creature_loot_template` WHERE `entry` = 15101; + +UPDATE `creature_template` SET `lootid` = 0, `skinloot` = 0 WHERE (`entry` = 15068); +DELETE FROM `creature_loot_template` WHERE `entry` = 15068; diff --git a/data/sql/updates/db_world/2022_08_07_07.sql b/data/sql/updates/db_world/2022_08_07_07.sql new file mode 100644 index 000000000..b3928f67a --- /dev/null +++ b/data/sql/updates/db_world/2022_08_07_07.sql @@ -0,0 +1,3 @@ +-- DB update 2022_08_07_06 -> 2022_08_07_07 +-- +UPDATE `gameobject` SET `ScriptName` = '' WHERE `id` = 176966; diff --git a/data/sql/updates/db_world/2022_08_08_00.sql b/data/sql/updates/db_world/2022_08_08_00.sql new file mode 100644 index 000000000..ee547efc9 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_08_00.sql @@ -0,0 +1,63 @@ +-- DB update 2022_08_07_07 -> 2022_08_08_00 +-- +-- Pathing for Sand Vortex Entry: 15428 +SET @NPC := 144680; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-9524.06,`position_y`=1881.9224,`position_z`=85.64029 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0,25160); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-9467.716,1801.2075,85.68075,0,0,0,0,100,0), +(@PATH,2,-9433.638,1767.3511,85.68072,0,0,0,0,100,0), +(@PATH,3,-9400.586,1733.8876,85.68073,0,0,0,0,100,0), +(@PATH,4,-9366.376,1733.2712,85.65805,0,0,0,0,100,0), +(@PATH,5,-9333.135,1732.013,85.61758,0,0,0,0,100,0), +(@PATH,6,-9300.71,1733.3823,85.68074,0,0,0,0,100,0), +(@PATH,7,-9266.841,1766.4036,85.68074,0,0,0,0,100,0), +(@PATH,8,-9234.005,1800.0885,85.68074,0,0,0,0,100,0), +(@PATH,9,-9200.683,1833.4056,85.68073,0,0,0,0,100,0), +(@PATH,10,-9168.018,1866.673,86.23005,0,0,0,0,100,0), +(@PATH,11,-9171.645,1901.1793,85.68071,0,0,0,0,100,0), +(@PATH,12,-9173.781,1933.2633,85.68071,0,0,0,0,100,0), +(@PATH,13,-9195.187,1966.727,86.19511,0,0,0,0,100,0), +(@PATH,14,-9220.778,1999.9199,85.68075,0,0,0,0,100,0), +(@PATH,15,-9256.546,2032.9481,86.04485,0,0,0,0,100,0), +(@PATH,16,-9289.013,2066.2517,87.10255,0,0,0,0,100,0), +(@PATH,17,-9333.082,2071.4539,85.99686,0,0,0,0,100,0), +(@PATH,18,-9366.466,2075.198,86.651405,0,0,0,0,100,0), +(@PATH,19,-9399.833,2040.6716,86.5944,0,0,0,0,100,0), +(@PATH,20,-9432.466,2006.033,85.930725,0,0,0,0,100,0), +(@PATH,21,-9466.139,1975.4115,85.92978,0,0,0,0,100,0), +(@PATH,22,-9499.492,1940.9631,85.67978,0,0,0,0,100,0), +(@PATH,23,-9525.446,1900.1099,85.680725,0,0,0,0,100,0), +(@PATH,24,-9519.793,1870.9224,85.68071,0,0,0,0,100,0), +(@PATH,25,-9499.598,1833.6816,85.68074,0,0,0,0,100,0); + +-- Pathing for Sand Vortex Entry: 15428 +SET @NPC := 144679; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-9228.479,`position_y`=1925.3331,`position_z`=85.64147 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0,25160); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-9267.194,1866.0243,85.597404,0,0,0,0,100,0), +(@PATH,2,-9299.206,1833.0114,85.52548,0,0,0,0,100,0), +(@PATH,3,-9333.244,1799.9004,83.67978,0,0,0,0,100,0), +(@PATH,4,-9366.875,1774.673,85.68073,0,0,0,0,100,0), +(@PATH,5,-9393.9375,1800.2031,85.642654,0,0,0,0,100,0), +(@PATH,6,-9399.323,1833.3334,85.68074,0,0,0,0,100,0), +(@PATH,7,-9425.436,1859.5237,85.63606,0,0,0,0,100,0), +(@PATH,8,-9461.292,1861.6554,85.68074,0,0,0,0,100,0), +(@PATH,9,-9466.752,1899.8247,85.68074,0,0,0,0,100,0), +(@PATH,10,-9432.557,1932.738,84.57658,0,0,0,0,100,0), +(@PATH,11,-9400.856,1965.8516,86.60922,0,0,0,0,100,0), +(@PATH,12,-9369.419,2000.3989,85.680725,0,0,0,0,100,0), +(@PATH,13,-9332.606,2018.017,85.68073,0,0,0,0,100,0), +(@PATH,14,-9311.325,1999.8208,85.68074,0,0,0,0,100,0), +(@PATH,15,-9310.085,1969.1917,85.68074,0,0,0,0,100,0), +(@PATH,16,-9285.372,1947.293,85.68074,0,0,0,0,100,0), +(@PATH,17,-9255.054,1952.4874,85.68074,0,0,0,0,100,0), +(@PATH,18,-9225.013,1923.3672,85.68074,0,0,0,0,100,0), +(@PATH,19,-9233.319,1899.1927,85.68073,0,0,0,0,100,0); diff --git a/data/sql/updates/db_world/2022_08_09_00.sql b/data/sql/updates/db_world/2022_08_09_00.sql new file mode 100644 index 000000000..14bda1883 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_09_00.sql @@ -0,0 +1,21 @@ +-- DB update 2022_08_08_00 -> 2022_08_09_00 +-- +SET @NPC := 15369; +SET @PATH := @NPC * 10; +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-9689.981,1548.2961,33.27733,0,0,0,0,100,0), +(@PATH,2,-9682.716,1554.252,31.416214,0,0,0,0,100,0), +(@PATH,3,-9677.917,1558.839,27.249535,0,0,0,0,100,0); + +-- Summon HiveZara larvae +UPDATE `spell_dbc` SET `Effect_1` = 28, `EffectMiscValueB_1` = 64, `EffectBasePoints_1` = 1, `EffectDieSides_1` = 0 WHERE `ID` IN (26538, 26539); + +DELETE FROM `spell_target_position` WHERE `ID` IN (26538, 26539); +INSERT INTO `spell_target_position` (`ID`, `EffectIndex`, `MapID`, `PositionX`, `PositionY`, `PositionZ`, `Orientation`, `VerifiedBuild`) VALUES +(26538, 0, 509, -9678.29, 1526.39, 24.403833,0,0), +(26539, 0, 509, -9709, 1551.2, 23.988834, 0, 0); + +DELETE FROM `creature_template_movement` WHERE `CreatureId` = 15546; +INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Chase`, `Random`, `InteractionPauseTimer`) VALUES +(15546, 1, 0, 1, 0, 0, NULL); diff --git a/data/sql/updates/db_world/2022_08_10_00.sql b/data/sql/updates/db_world/2022_08_10_00.sql new file mode 100644 index 000000000..b5bb80ff1 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_10_00.sql @@ -0,0 +1,31 @@ +-- DB update 2022_08_09_00 -> 2022_08_10_00 +-- +DELETE FROM `spell_target_position` WHERE `ID` IN (720, 731, 1121, 518, 25831, 25832); +INSERT INTO `spell_target_position` (`ID`, `EffectIndex`, `MapID`, `PositionX`, `PositionY`, `PositionZ`, `Orientation`) VALUES +(720, 0, 531, -8043.6, 1254.1, -84.3, 0), +(731, 0, 531, -8003, 1222.9, -82.1, 0), +(1121, 0, 531, -8022.3, 1149, -89.1, 0), +(518, 0, 531, -8028.5, 1050.9, -54, 0), +(25831, 0, 531, -8158.03, 1139.3, -83.95, 0), +(25832, 0, 531, -8029.25, 1237.78, -85.2285, 0); + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 15630) 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`, `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 +(15630, 0, 0, 0, 0, 0, 100, 3, 10000, 20000, 0, 0, 0, 11, 26662, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Spawn of Fankriss - In Combat - Cast \'Berserk\' (No Repeat) (Normal Dungeon)'); + +DELETE FROM `creature_formations` WHERE `memberGUID` IN (87911, 87773, 87775, 87796, 87806, 87792); +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES +(87911, 87911, 0, 0, 3, 0, 0), +(87911, 87773, 0, 0, 3, 0, 0), +(87911, 87775, 0, 0, 3, 0, 0), +(87911, 87796, 0, 0, 3, 0, 0), +(87911, 87806, 0, 0, 3, 0, 0), +(87911, 87792, 0, 0, 3, 0, 0); + +DELETE FROM `linked_respawn` WHERE `guid` IN (87773, 87775, 87796, 87806, 87792); +INSERT INTO `linked_respawn` (`guid`, `linkedGuid`, `linkType`) VALUES +(87773, 87911, 0), +(87775, 87911, 0), +(87796, 87911, 0), +(87806, 87911, 0), +(87792, 87911, 0); diff --git a/data/sql/updates/db_world/2022_08_10_01.sql b/data/sql/updates/db_world/2022_08_10_01.sql new file mode 100644 index 000000000..86ba73faa --- /dev/null +++ b/data/sql/updates/db_world/2022_08_10_01.sql @@ -0,0 +1,5 @@ +-- DB update 2022_08_10_00 -> 2022_08_10_01 +-- +DELETE FROM `smart_scripts` WHERE `source_type` = 0 AND `entryorguid` = 15277 AND `id`=12; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(15277, 0, 12, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 11, 27630, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Anubisath Defender - On Just Died - Cast \'Serverside - Drop Obsidian\''); diff --git a/data/sql/updates/db_world/2022_08_10_02.sql b/data/sql/updates/db_world/2022_08_10_02.sql new file mode 100644 index 000000000..1acdf4320 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_10_02.sql @@ -0,0 +1,3 @@ +-- DB update 2022_08_10_01 -> 2022_08_10_02 +-- +DELETE FROM `creature_addon` WHERE `guid`=144632; diff --git a/data/sql/updates/db_world/2022_08_11_00.sql b/data/sql/updates/db_world/2022_08_11_00.sql new file mode 100644 index 000000000..2b3b04e9a --- /dev/null +++ b/data/sql/updates/db_world/2022_08_11_00.sql @@ -0,0 +1,10 @@ +-- DB update 2022_08_10_02 -> 2022_08_11_00 +-- +UPDATE `quest_template_addon` SET `AllowableClasses`=1 WHERE `id`=8316; +UPDATE `quest_template_addon` SET `AllowableClasses`=2 WHERE `id`=8376; +UPDATE `quest_template_addon` SET `AllowableClasses`=4 WHERE `id`=8377; +UPDATE `quest_template_addon` SET `AllowableClasses`=8 WHERE `id`=8378; +UPDATE `quest_template_addon` SET `AllowableClasses`=16 WHERE `id`=8379; +UPDATE `quest_template_addon` SET `AllowableClasses`=64 WHERE `id`=8380; +UPDATE `quest_template_addon` SET `AllowableClasses`=384 WHERE `id`=8381; +UPDATE `quest_template_addon` SET `AllowableClasses`=1024 WHERE `id`=8382; diff --git a/data/sql/updates/db_world/2022_08_12_00.sql b/data/sql/updates/db_world/2022_08_12_00.sql new file mode 100644 index 000000000..ba7b36701 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_12_00.sql @@ -0,0 +1,3 @@ +-- DB update 2022_08_11_00 -> 2022_08_12_00 + +UPDATE `conditions` SET `ConditionValue3` = 0 WHERE `SourceTypeOrReferenceId` = 22 AND `SourceGroup` = 2 AND `SourceEntry` = 182026; diff --git a/data/sql/updates/db_world/2022_08_12_01.sql b/data/sql/updates/db_world/2022_08_12_01.sql new file mode 100644 index 000000000..a419681ab --- /dev/null +++ b/data/sql/updates/db_world/2022_08_12_01.sql @@ -0,0 +1,2 @@ +-- DB update 2022_08_12_00 -> 2022_08_12_01 +UPDATE `creature` SET `wander_distance`=20.0,`MovementType`=1 WHERE `guid`=58019 AND `id1`=16854; diff --git a/data/sql/updates/db_world/2022_08_14_00.sql b/data/sql/updates/db_world/2022_08_14_00.sql new file mode 100644 index 000000000..526cfcded --- /dev/null +++ b/data/sql/updates/db_world/2022_08_14_00.sql @@ -0,0 +1,8 @@ +-- DB update 2022_08_12_01 -> 2022_08_14_00 +-- +UPDATE `creature_formations` SET `dist`=5 WHERE `memberGUID` IN (87649,87650,87651); + +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=26084 AND `spell_effect`=25174 AND `type`=1; +INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES +(26084, 25174, 1, 'Battleguard Sartura - OnHit Whirlwind - Apply Sundering Cleave'); + diff --git a/data/sql/updates/db_world/2022_08_14_01.sql b/data/sql/updates/db_world/2022_08_14_01.sql new file mode 100644 index 000000000..1dd0c127f --- /dev/null +++ b/data/sql/updates/db_world/2022_08_14_01.sql @@ -0,0 +1,3 @@ +-- DB update 2022_08_14_00 -> 2022_08_14_01 +-- +UPDATE `creature_template` SET `ScriptName`='npc_hivezara_stinger' WHERE `entry`=15327; diff --git a/data/sql/updates/db_world/2022_08_14_02.sql b/data/sql/updates/db_world/2022_08_14_02.sql new file mode 100644 index 000000000..187bacf19 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_14_02.sql @@ -0,0 +1,16 @@ +-- DB update 2022_08_14_01 -> 2022_08_14_02 +-- +DELETE FROM `smart_scripts` WHERE `entryorguid` = 15324 AND `source_type` = 0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(15324,0,0,0,11,0,100,256,0,0,0,0,211,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Qiraji Gladiator - On Respawn - Set not phase reset"), +(15324,0,1,0,0,0,100,0,5400,8500,6000,17000,11,5568,0,0,0,0,0,1,0,0,0,0,0,0,0,"Qiraji Gladiator - In Combat - Cast 'Trample'"), +(15324,0,2,0,0,0,100,0,8500,13000,8000,16000,11,10966,0,0,0,0,0,2,0,0,0,0,0,0,0,"Qiraji Gladiator - In Combat - Cast 'Uppercut'"), +(15324,0,3,4,38,0,100,0,0,1,0,0,11,25164,0,0,0,0,0,1,0,0,0,0,0,0,0,"Qiraji Gladiator - On Data Set 0 1 - Cast 'Vengeance'"), +(15324,0,4,5,61,0,100,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Qiraji Gladiator - On Link - Say Line 0"), +(15324,0,5,0,61,0,100,256,0,0,0,0,22,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Qiraji Gladiator - On Link - Set Phase 1"), +(15324,0,6,0,6,0,100,0,0,0,0,0,45,0,1,0,0,0,0,19,15324,30,0,0,0,0,0,"Qiraji Gladiator - On Death - Set Data 0 1"), +(15324,0,7,0,0,1,100,0,60000,60000,60000,60000,11,25164,0,0,0,0,0,1,0,0,0,0,0,0,0,"Qiraji Gladiator - IC - Cast 'Vengeance' (Phase 1)"); + +DELETE FROM `creature_text` WHERE `CreatureID`=15324; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(15324,0,0,'%s becomes enraged!',16,0,100,0,0,0,24144,0,'Qiraji Gladiator'); diff --git a/data/sql/updates/db_world/2022_08_14_03.sql b/data/sql/updates/db_world/2022_08_14_03.sql new file mode 100644 index 000000000..bc0408e18 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_14_03.sql @@ -0,0 +1,11 @@ +-- DB update 2022_08_14_02 -> 2022_08_14_03 +-- +UPDATE `smart_scripts` SET `link`=2 WHERE `entryorguid` = 15323 AND `source_type` = 0 AND `id`=1; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 15323 AND `source_type` = 0 AND `id` IN (2,3,4,5,6,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`,`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 +(15323,0,2,3,61,0,100,0,0,0,0,0,20,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Hive'Zara Sandstalker - In Combat - Disable melee attack"), +(15323,0,3,0,61,0,100,0,0,0,0,0,22,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Hive'Zara Sandstalker - In Combat - Set Phase 1"), +(15323,0,4,5,0,1,100,0,3000,6000,3000,6000,28,26381,0,0,0,0,0,1,0,0,0,0,0,0,0,"Hive'Zara Sandstalker - IC - Remove Borrow"), +(15323,0,5,6,61,0,100,0,0,0,0,0,11,41390,0,0,0,0,0,2,0,0,0,0,0,0,0,"Hive'Zara Sandstalker - IC - Cast Ambush"), +(15323,0,6,7,61,0,100,0,0,0,0,0,20,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Hive'Zara Sandstalker - In Combat - Enable melee attack"), +(15323,0,7,0,61,0,100,0,0,0,0,0,22,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Hive'Zara Sandstalker - In Combat - Set Phase 0"); diff --git a/data/sql/updates/db_world/2022_08_14_04.sql b/data/sql/updates/db_world/2022_08_14_04.sql new file mode 100644 index 000000000..1f7648d9d --- /dev/null +++ b/data/sql/updates/db_world/2022_08_14_04.sql @@ -0,0 +1,5 @@ +-- DB update 2022_08_14_03 -> 2022_08_14_04 +-- +DELETE FROM `creature_text` WHERE `CreatureID`=15264; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(15264,0,0,'%s becomes enraged!',16,0,100,0,0,0,24144,0,'Anubisath Sentinel'); diff --git a/data/sql/updates/db_world/2022_08_14_05.sql b/data/sql/updates/db_world/2022_08_14_05.sql new file mode 100644 index 000000000..ff6c8cf76 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_14_05.sql @@ -0,0 +1,24 @@ +-- DB update 2022_08_14_04 -> 2022_08_14_05 +-- Fix Silithid Carapace to depend only to Agent of Nozdormu item +UPDATE `creature_loot_template` SET `QuestRequired` = 0 WHERE `Item` = 20384; + +DELETE FROM `conditions` WHERE `SourceEntry` = 20384 AND `ConditionValue1` = 20402; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(1, 11698, 20384, 0, 0, 2, 0, 20402, 1, 0, 0, 0, 0, '', ''), +(1, 11721, 20384, 0, 0, 2, 0, 20402, 1, 0, 0, 0, 0, '', ''), +(1, 11722, 20384, 0, 0, 2, 0, 20402, 1, 0, 0, 0, 0, '', ''), +(1, 11723, 20384, 0, 0, 2, 0, 20402, 1, 0, 0, 0, 0, '', ''), +(1, 11724, 20384, 0, 0, 2, 0, 20402, 1, 0, 0, 0, 0, '', ''), +(1, 11725, 20384, 0, 0, 2, 0, 20402, 1, 0, 0, 0, 0, '', ''), +(1, 11726, 20384, 0, 0, 2, 0, 20402, 1, 0, 0, 0, 0, '', ''), +(1, 11727, 20384, 0, 0, 2, 0, 20402, 1, 0, 0, 0, 0, '', ''), +(1, 11728, 20384, 0, 0, 2, 0, 20402, 1, 0, 0, 0, 0, '', ''), +(1, 11729, 20384, 0, 0, 2, 0, 20402, 1, 0, 0, 0, 0, '', ''), +(1, 11730, 20384, 0, 0, 2, 0, 20402, 1, 0, 0, 0, 0, '', ''), +(1, 11731, 20384, 0, 0, 2, 0, 20402, 1, 0, 0, 0, 0, '', ''), +(1, 11732, 20384, 0, 0, 2, 0, 20402, 1, 0, 0, 0, 0, '', ''), +(1, 11733, 20384, 0, 0, 2, 0, 20402, 1, 0, 0, 0, 0, '', ''), +(1, 11734, 20384, 0, 0, 2, 0, 20402, 1, 0, 0, 0, 0, '', ''), +(1, 13136, 20384, 0, 0, 2, 0, 20402, 1, 0, 0, 0, 0, '', ''), +(1, 13301, 20384, 0, 0, 2, 0, 20402, 1, 0, 0, 0, 0, '', ''), +(1, 15759, 20384, 0, 0, 2, 0, 20402, 1, 0, 0, 0, 0, '', ''); diff --git a/data/sql/updates/db_world/2022_08_15_00.sql b/data/sql/updates/db_world/2022_08_15_00.sql new file mode 100644 index 000000000..d50300ebc --- /dev/null +++ b/data/sql/updates/db_world/2022_08_15_00.sql @@ -0,0 +1,3 @@ +-- DB update 2022_08_14_05 -> 2022_08_15_00 +-- Remove a duplicate and wrong gossip with anachronos +DELETE FROM `gossip_menu_option` WHERE `MenuID` = 6539 AND `OptionID` IN (0); diff --git a/data/sql/updates/db_world/2022_08_15_01.sql b/data/sql/updates/db_world/2022_08_15_01.sql new file mode 100644 index 000000000..0020614c9 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_15_01.sql @@ -0,0 +1,110 @@ +-- DB update 2022_08_15_00 -> 2022_08_15_01 +-- +-- Remove all entries, they will be replaced +DELETE FROM `creature` WHERE `id1`=2955; +DELETE FROM `creature` WHERE `id2`=2955; +DELETE FROM `creature` WHERE `id3`=2955; + +-- Corrects spawn points to sniffed values, mostly this was fine, but the XYZ values were done manually rather than from sniffed variables +-- Wander distance was already set to 20, which is a good minimum value, about half of them have a wander value of around 30 or more, the sniff will be uploaded later to the collective if anyone wants to deep dive that for some reason +-- Similarly, 155 was the spawntime set before this fix, 180 is probbably correct, but this is fine imo without dynamic spawning +SET @GUID :=88354; +DELETE FROM `creature` WHERE `guid` BETWEEN @GUID+0 AND @GUID+96; +INSERT INTO `creature` (`guid`, `id1`, `id2`, `id3`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`) VALUES +(@GUID+0, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2915.9321, -117.10601, 77.61542, 1.884955525398254394, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2915.9321 -117.10601 77.61542 +(@GUID+1, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2881.4697, -150.06369, 67.3019, 3.03687286376953125, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2881.4697 -150.06369 67.3019 +(@GUID+2, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2983.2869, -181.743, 63.0384, 2.146754980087280273, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2983.2869 -181.743 63.0384 +(@GUID+3, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3049.5332, -116.48638, 52.78892, 3.612831592559814453, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3049.5332 -116.48638 52.78892 +(@GUID+4, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3084.8281, -151.3636, 47.7102, 1.972222089767456054, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3084.8281 -151.3636 47.7102 +(@GUID+5, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3048.971, -183.28185, 59.85856, 1.553343057632446289, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3048.971 -183.28185 59.85856 +(@GUID+6, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3016.0718, -217.09685, 56.218082, 4.398229598999023437, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3016.0718 -217.09685 56.218082 +(@GUID+7, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2849.0051, -182.61052, 59.357796, 1.692969322204589843, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2849.0051 -182.61052 59.357796 +(@GUID+8, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2817.4912, -216.73177, 56.172832, 3.96189737319946289, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2817.4912 -216.73177 56.172832 +(@GUID+9, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2848.5728, -316.2174, 55.82892, 1.919862151145935058, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2848.5728 -316.2174 55.82892 +(@GUID+10, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2817.3057, -284.28928, 58.999767, 0.261799395084381103, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2817.3057 -284.28928 58.999767 +(@GUID+11, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2791.1252, -316.0387, 55.81441, 5.096361160278320312, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2791.1252 -316.0387 55.81441 +(@GUID+12, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2816.52, -348.31967, 57.394314, 4.747295379638671875, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2816.52 -348.31967 57.394314 +(@GUID+13, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2849.3384, -383.77203, 55.30781, 0.331612557172775268, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2849.3384 -383.77203 55.30781 +(@GUID+14, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2883.8289, -350.39417, 55.231503, 4.171336650848388671, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2883.8289 -350.39417 55.231503 +(@GUID+15, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2915.2188, -383.69476, 55.308075, 3.124139308929443359, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2915.2188 -383.69476 55.308075 +(@GUID+16, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2882.5889, -417.75314, 49.94027, 0, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2882.5889 -417.75314 49.94027 +(@GUID+17, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2864.4363, -449.93967, 53.77305, 1.605702877044677734, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2864.4363 -449.93967 53.77305 +(@GUID+18, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2883.513, -483.6671, 47.450447, 2.687807083129882812, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2883.513 -483.6671 47.450447 +(@GUID+19, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2951.8186, -350.5021, 55.86079, 5.846852779388427734, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2951.8186 -350.5021 55.86079 +(@GUID+20, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2983.916, -316.7991, 48.84321, 1.029744267463684082, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2983.916 -316.7991 48.84321 +(@GUID+21, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3018.8704, -284.1935, 43.844025, 2.111848354339599609, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3018.8704 -284.1935 43.844025 +(@GUID+22, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3050.7756, -317.3549, 42.753426, 0.383972436189651489, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3050.7756 -317.3549 42.753426 +(@GUID+23, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3117.3638, -317.11685, 40.205025, 1.815142393112182617, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3117.3638 -317.11685 40.205025 +(@GUID+24, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3082.7852, -283.14948, 36.52417, 4.450589656829833984, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3082.7852 -283.14948 36.52417 +(@GUID+25, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3082.5708, -350.88812, 36.985973, 0.139626339077949523, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3082.5708 -350.88812 36.985973 +(@GUID+26, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3049.2266, -384.4684, 39.612816, 3.682644605636596679, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3049.2266 -384.4684 39.612816 +(@GUID+27, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3084.3826, -417.4145, 37.911163, 5.951572895050048828, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3084.3826 -417.4145 37.911163 +(@GUID+28, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3116.5625, -383.2819, 41.819256, 2.321287870407104492, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3116.5625 -383.2819 41.819256 +(@GUID+29, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3016.7205, -417.2922, 48.25192, 0.575958669185638427, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3016.7205 -417.2922 48.25192 +(@GUID+30, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2983.6528, -382.88184, 53.537003, 2.827433347702026367, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2983.6528 -382.88184 53.537003 +(@GUID+31, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2984.1338, -450.97092, 46.477955, 4.537856101989746093, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2984.1338 -450.97092 46.477955 +(@GUID+32, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2950.2192, -417.1669, 53.86521, 0.104719758033752441, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2950.2192 -417.1669 53.86521 +(@GUID+33, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2917.082, -450.50412, 46.918938, 4.78220224380493164, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2917.082 -450.50412 46.918938 +(@GUID+34, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2883.351, -549.6797, 51.405052, 5.078907966613769531, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2883.351 -549.6797 51.405052 +(@GUID+35, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2850.924, -517.7154, 50.91358, 5.06145477294921875, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2850.924 -517.7154 50.91358 +(@GUID+36, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2817.7004, -549.1674, 55.274178, 2.617993831634521484, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2817.7004 -549.1674 55.274178 +(@GUID+37, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2851.802, -583.9538, 57.15891, 3.630284786224365234, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2851.802 -583.9538 57.15891 +(@GUID+38, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2915.418, -517.8362, 47.194675, 4.380776405334472656, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2915.418 -517.8362 47.194675 +(@GUID+39, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2817.2737, -617.9309, 56.016186, 5.619960308074951171, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2817.2737 -617.9309 56.016186 +(@GUID+40, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2884.533, -616.6502, 55.083035, 5.969026088714599609, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2884.533 -616.6502 55.083035 +(@GUID+41, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2949.897, -615.9156, 39.461315, 2.897246599197387695, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2949.897 -615.9156 39.461315 +(@GUID+42, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2915.745, -583.6176, 50.565845, 5.462880611419677734, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2915.745 -583.6176 50.565845 +(@GUID+43, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2949.016, -549.3831, 45.385597, 4.049163818359375, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2949.016 -549.3831 45.385597 +(@GUID+44, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2983.931, -583.4975, 38.284866, 6.0737457275390625, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2983.931 -583.4975 38.284866 +(@GUID+45, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3018.492, -617.0446, 29.809212, 1.256637096405029296, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3018.492 -617.0446 29.809212 +(@GUID+46, 2966, 0, 0, 1, 0, 0, 1, 1, 0, -3017.079, -685.03986, 41.89431, 5.432766437530517578, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3017.079 -685.03986 41.89431 +(@GUID+47, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3084.279, -682.7648, 31.90988, 0.802851438522338867, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3084.279 -682.7648 31.90988 +(@GUID+48, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3050.0088, -650.9782, 29.19056, 0.680678427219390869, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3050.0088 -650.9782 29.19056 +(@GUID+49, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3085.173, -617.01215, 34.477776, 5.689773082733154296, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3085.173 -617.01215 34.477776 +(@GUID+50, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3116.6624, -649.3928, 32.413265, 1.169370532035827636, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3116.6624 -649.3928 32.413265 +(@GUID+51, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3116.1125, -714.4594, 33.46272, 0.942477762699127197, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3116.1125 -714.4594 33.46272 +(@GUID+52, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3148.6108, -683.60284, 23.079771, 3.141592741012573242, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3148.6108 -683.60284 23.079771 +(@GUID+53, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3182.7786, -716.07, 26.982426, 4.537856101989746093, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3182.7786 -716.07 26.982426 +(@GUID+54, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3148.8203, -615.4817, 35.513004, 2.356194496154785156, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3148.8203 -615.4817 35.513004 +(@GUID+55, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3117.3677, -251.52632, 41.896477, 2.722713708877563476, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3117.3677 -251.52632 41.896477 +(@GUID+56, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3150.7246, -216.66353, 43.11533, 1.029744267463684082, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3150.7246 -216.66353 43.11533 +(@GUID+57, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3182.763, -249.51974, 40.0922, 0.628318548202514648, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3182.763 -249.51974 40.0922 +(@GUID+58, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3184.1643, -317.5604, 37.124756, 5.707226753234863281, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3184.1643 -317.5604 37.124756 +(@GUID+59, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3150.1514, -285.3053, 39.282925, 3.089232683181762695, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3150.1514 -285.3053 39.282925 +(@GUID+60, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3149.0168, -349.84933, 34.957115, 4.660028934478759765, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3149.0168 -349.84933 34.957115 +(@GUID+61, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3215.4568, -217.2468, 31.292675, 4.328416347503662109, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3215.4568 -217.2468 31.292675 +(@GUID+62, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3182.377, -184.5408, 41.331944, 1.692969322204589843, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3182.377 -184.5408 41.331944 +(@GUID+63, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3215.015, -284.60513, 30.6046, 4.590215682983398437, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3215.015 -284.60513 30.6046 +(@GUID+64, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3284.4084, -217.13043, 39.615646, 3.787364482879638671, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3284.4084 -217.13043 39.615646 +(@GUID+65, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3284.5642, -282.64816, 37.027092, 2.199114799499511718, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3284.5642 -282.64816 37.027092 +(@GUID+66, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3214.8604, -347.4374, 28.102503, 5.969026088714599609, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3214.8604 -347.4374 28.102503 +(@GUID+67, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3248.986, -316.8644, 32.329453, 4.886921882629394531, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3248.986 -316.8644 32.329453 +(@GUID+68, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3282.3496, -350.19608, 43.65876, 2.39110112190246582, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3282.3496 -350.19608 43.65876 +(@GUID+69, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3249.6396, -384.67285, 31.974255, 2.0245819091796875, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3249.6396 -384.67285 31.974255 +(@GUID+70, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3281.6199, -417.9758, 36.595318, 0.122173048555850982, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3281.6199 -417.9758 36.595318 +(@GUID+71, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3215.3584, -416.1518, 25.393665, 2.356194496154785156, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3215.3584 -416.1518 25.393665 +(@GUID+72, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3248.7173, -450.7054, 28.379059, 1.48352980613708496, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3248.7173 -450.7054 28.379059 +(@GUID+73, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3216.2603, -483.22516, 24.11747, 4.310963153839111328, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3216.2603 -483.22516 24.11747 +(@GUID+74, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3249.8452, -516.86914, 27.956903, 5.393067359924316406, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3249.8452 -516.86914 27.956903 +(@GUID+75, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3150.8284, -482.7306, 30.151358, 1.884955525398254394, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3150.8284 -482.7306 30.151358 +(@GUID+76, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3149.8757, -417.15897, 31.773283, 4.590215682983398437, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3149.8757 -417.15897 31.773283 +(@GUID+77, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3115.8054, -449.89996, 29.697945, 3.735004663467407226, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3115.8054 -449.89996 29.697945 +(@GUID+78, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3083.3086, -483.736, 31.280085, 3.560471534729003906, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3083.3086 -483.736 31.280085 +(@GUID+79, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3118.7922, -516.90375, 34.351627, 0.03490658476948738, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3118.7922 -516.90375 34.351627 +(@GUID+80, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3148.536, -550.18274, 30.679869, 2.443460941314697265, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3148.536 -550.18274 30.679869 +(@GUID+81, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3116.379, -583.2126, 34.0221, 4.886921882629394531, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3116.379 -583.2126 34.0221 +(@GUID+82, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3217.4094, -616.01, 28.73066, 3.665191411972045898, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3217.4094 -616.01 28.73066 +(@GUID+83, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3216.0747, -548.41754, 25.538637, 4.834561824798583984, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3216.0747 -548.41754 25.538637 +(@GUID+84, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3282.0308, -550.7741, 46.280766, 1.151917338371276855, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3282.0308 -550.7741 46.280766 +(@GUID+85, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3280.8374, -617.0858, 35.034283, 4.345870018005371093, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3280.8374 -617.0858 35.034283 +(@GUID+86, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3248.9495, -581.88226, 30.587183, 4.677482128143310546, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3248.9495 -581.88226 30.587183 +(@GUID+87, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3281.4895, -683.2465, 39.041134, 1.675516128540039062, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3281.4895 -683.2465 39.041134 +(@GUID+88, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3247.2446, -649.0194, 30.383823, 4.328416347503662109, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3247.2446 -649.0194 30.383823 +(@GUID+89, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3215.3052, -682.5738, 29.801714, 2.042035102844238281, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3215.3052 -682.5738 29.801714 +(@GUID+90, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3247.6877, -714.72, 36.439972, 2.652900457382202148, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3247.6877 -714.72 36.439972 +(@GUID+91, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3182.1843, -648.84247, 29.093792, 1.169370532035827636, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3182.1843 -648.84247 29.093792 +(@GUID+92, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3051.3738, -582.958, 25.07603, 1.535889744758605957, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3051.3738 -582.958 25.07603 +(@GUID+93, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3015.6433, -549.345, 31.536392, 0.401425719261169433, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -3015.6433 -549.345 31.536392 +(@GUID+94, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2949.265, -482.95715, 43.765648, 3.089232683181762695, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2949.265 -482.95715 43.765648 +(@GUID+95, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -2984.5002, -517.8174, 39.379818, 3.141592741012573242, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0), -- .go xyz -2984.5002 -517.8174 39.379818 +(@GUID+96, 2955, 0, 0, 1, 0, 0, 1, 1, 0, -3016.3232, -483.44913, 36.235992, 0.663225114345550537, 155, 20, 0, 1, 0, 1, 0, 0, 0, '', 0); diff --git a/data/sql/updates/db_world/2022_08_15_02.sql b/data/sql/updates/db_world/2022_08_15_02.sql new file mode 100644 index 000000000..c00dc06ec --- /dev/null +++ b/data/sql/updates/db_world/2022_08_15_02.sql @@ -0,0 +1,4 @@ +-- DB update 2022_08_15_01 -> 2022_08_15_02 +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 15656) AND (`source_type` = 0) AND (`id` = 2); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `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 +(15656, 0, 2, 0, 75, 0, 100, 0, 0, 15958, 20, 1200, 0, 49, 0, 0, 0, 0, 0, 0, 19, 15402, 53, 0, 0, 0, 0, 0, 0, 'Angershade - On Distance To Creature - Start Attacking'); diff --git a/data/sql/updates/db_world/2022_08_15_03.sql b/data/sql/updates/db_world/2022_08_15_03.sql new file mode 100644 index 000000000..ee1094bba --- /dev/null +++ b/data/sql/updates/db_world/2022_08_15_03.sql @@ -0,0 +1,2 @@ +-- DB update 2022_08_15_02 -> 2022_08_15_03 +UPDATE `creature_addon` SET `bytes2`=1 WHERE `guid`=71028; diff --git a/data/sql/updates/db_world/2022_08_15_04.sql b/data/sql/updates/db_world/2022_08_15_04.sql new file mode 100644 index 000000000..f63d5a34f --- /dev/null +++ b/data/sql/updates/db_world/2022_08_15_04.sql @@ -0,0 +1,158 @@ +-- DB update 2022_08_15_03 -> 2022_08_15_04 +-- +DELETE FROM `spell_target_position` WHERE `ID` IN (25708, 25709, 25825, 25826, 25827, 25828); +INSERT INTO `spell_target_position` (`ID`, `EffectIndex`, `MapID`, `PositionX`, `PositionY`, `PositionZ`, `Orientation`, `VerifiedBuild`) VALUES +(25708, 0, 509, -9846, 1353, 106.083336, 0, 0), +(25709, 0, 509, -9757.87, 1416.71, 76.7664, 0, 0), +(25825, 0, 509, -9805.95, 1422.85, 77.5852, 0, 0), +(25826, 0, 509, -9827.58, 1506.28, 82.3052, 0, 0), +(25827, 0, 509, -9778.91, 1419.98, 61.0743, 0, 0), +(25828, 0, 509, -9829.42, 1456.37, 90.7015, 0, 0); + +DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_ayamiss_swarmer_teleport_trigger'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(25830, 'spell_ayamiss_swarmer_teleport_trigger'); + +DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_ayamiss_swarmer_swarm'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(25844, 'spell_ayamiss_swarmer_swarm'); + +UPDATE `spell_dbc` SET `Effect_1` = 28, `EffectMiscValueB_1` = 64, `EffectBasePoints_1` = 1, `EffectDieSides_1` = 0 WHERE `ID` = 25708; + +DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_ayamiss_swarmer_start_loop'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(25711, 'spell_ayamiss_swarmer_start_loop'); + +DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_gen_ayamiss_swarmer_loop_1', 'spell_gen_ayamiss_swarmer_loop_2', 'spell_gen_ayamiss_swarmer_loop_3'); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(25833, 'spell_gen_ayamiss_swarmer_loop_1'), +(25834, 'spell_gen_ayamiss_swarmer_loop_2'), +(25835, 'spell_gen_ayamiss_swarmer_loop_3'); + +UPDATE `creature_template` SET `ScriptName` = 'npc_hive_zara_swarmer' WHERE `entry` = 15546; + +SET @NPC := 15546; +SET @PATH := @NPC * 10; +DELETE FROM `waypoint_data` WHERE `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(@PATH, 1, -9758.247, 1426.3112, 84.167656, 0, 0, 0, 0, 100, 0), +(@PATH, 2, -9762.383, 1436.3455, 84.428795, 0, 0, 0, 0, 100, 0), +(@PATH, 3, -9760.481, 1452.1432, 75.32612, 0, 0, 0, 0, 100, 0), +(@PATH, 4, -9754.527, 1466.5826, 61.60388, 0, 0, 0, 0, 100, 0), +(@PATH, 5, -9750.208, 1479.4608, 45.937202, 0, 0, 0, 0, 100, 0); + +SET @PATH := (@NPC + 1) * 10; +DELETE FROM `waypoint_data` WHERE `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(@PATH, 1, -9804.298, 1432.3503, 85.9217, 0, 0, 0, 0, 100, 0), +(@PATH, 2, -9799.983, 1443.1294, 82.55095, 0, 0, 0, 0, 100, 0), +(@PATH, 3, -9785.31, 1456.0002, 76.88425, 0, 0, 0, 0, 100, 0), +(@PATH, 4, -9769.325, 1467.856, 68.520706, 0, 0, 0, 0, 100, 0), +(@PATH, 5, -9750.661, 1477.6143, 48.96516, 0, 0, 0, 0, 100, 0); + +SET @PATH := (@NPC + 2) * 10; +DELETE FROM `waypoint_data` WHERE `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(@PATH, 1, -9818.727, 1512.838, 89.24695, 0, 0, 0, 0, 100, 0), +(@PATH, 2, -9812.264, 1511.9375, 87.49864, 0, 0, 0, 0, 100, 0), +(@PATH, 3, -9806.9375, 1505.4645, 83.19313, 0, 0, 0, 0, 100, 0), +(@PATH, 4, -9796.596, 1494.5698, 76.8735, 0, 0, 0, 0, 100, 0), +(@PATH, 5, -9781.221, 1486.8652, 71.7902, 0, 0, 0, 0, 100, 0), +(@PATH, 6, -9765.105, 1476.7782, 63.17909, 0, 0, 0, 0, 100, 0), +(@PATH, 7, -9753.014, 1478.1317, 50.817974, 0, 0, 0, 0, 100, 0); + +SET @PATH := (@NPC + 3) * 10; +DELETE FROM `waypoint_data` WHERE `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(@PATH, 1, -9776.323, 1428.8531, 65.629776, 0, 0, 0, 0, 100, 0), +(@PATH, 2, -9776.123, 1436.0718, 67.35508, 0, 0, 0, 0, 100, 0), +(@PATH, 3, -9764.125, 1455.0714, 66.27153, 0, 0, 0, 0, 100, 0), +(@PATH, 4, -9754.778, 1466.8633, 62.577053, 0, 0, 0, 0, 100, 0), +(@PATH, 5, -9747.529, 1473.6367, 49.077087, 0, 0, 0, 0, 100, 0); + +SET @PATH := (@NPC + 4) * 10; +DELETE FROM `waypoint_data` WHERE `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(@PATH, 1, -9818.173, 1460.0463, 95.69417, 0, 0, 0, 0, 100, 0), +(@PATH, 2, -9811.176, 1460.6091, 92.56013, 0, 0, 0, 0, 100, 0), +(@PATH, 3, -9802.768, 1455.1123, 86.143425, 0, 0, 0, 0, 100, 0), +(@PATH, 4, -9797.88, 1450.7151, 81.69902, 0, 0, 0, 0, 100, 0), +(@PATH, 5, -9761.196, 1470.298, 64.64121, 0, 0, 0, 0, 100, 0), +(@PATH, 6, -9754.684, 1475.3403, 49.030098, 0, 0, 0, 0, 100, 0); + +SET @PATH := (@NPC + 5) * 10; +DELETE FROM `waypoint_data` WHERE `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(@PATH, 1, -9745.072, 1489.5533, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 2, -9745.766, 1502.0659, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 3, -9734.748, 1502.8883, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 4, -9715.551, 1496.5533, 42.267452, 0, 0, 0, 0, 100, 0), +(@PATH, 5, -9697.712, 1511.8822, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 6, -9694.466, 1539.3663, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 7, -9696.591, 1561.1914, 41.37858, 0, 0, 0, 0, 100, 0), +(@PATH, 8, -9667.614, 1571.5212, 43.489666, 0, 0, 0, 0, 100, 0), +(@PATH, 9, -9653.44, 1552.1632, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 10, -9612.033, 1551.3334, 39.26745, 0, 0, 0, 0, 100, 0), +(@PATH, 11, -9582.261, 1572.4617, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 12, -9598.483, 1615.416, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 13, -9638.286, 1645.0948, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 14, -9682.366, 1625.8219, 37.211887, 0, 0, 0, 0, 100, 0), +(@PATH, 15, -9667.457, 1593.8171, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 16, -9625.382, 1598.9684, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 17, -9618.158, 1566.9963, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 18, -9661.183, 1554.485, 42.489677, 0, 0, 0, 0, 100, 0), +(@PATH, 19, -9690.858, 1543.3951, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 20, -9711.017, 1540.3297, 43.517445, 0, 0, 0, 0, 100, 0), +(@PATH, 21, -9736.964, 1511.8362, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 22, -9725.431, 1487.6272, 44.323, 0, 0, 0, 0, 100, 0), +(@PATH, 23, -9742.012, 1485.945, 44.323, 0, 0, 0, 0, 100, 0); + +SET @PATH := (@NPC + 6) * 10; +DELETE FROM `waypoint_data` WHERE `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(@PATH, 1, -9748.129, 1488.4904, 45.764896, 0, 0, 0, 0, 100, 0), +(@PATH, 2, -9748.667, 1498.9249, 47.07047, 0, 0, 0, 0, 100, 0), +(@PATH, 3, -9744.251, 1508.8634, 46.820465, 0, 0, 0, 0, 100, 0), +(@PATH, 4, -9713.56, 1502.6979, 43.542686, 0, 0, 0, 0, 100, 0), +(@PATH, 5, -9701.453, 1522.0952, 43.542686, 0, 0, 0, 0, 100, 0), +(@PATH, 6, -9702.735, 1548.3297, 40.987125, 0, 0, 0, 0, 100, 0), +(@PATH, 7, -9682.249, 1544.3987, 41.12602, 0, 0, 0, 0, 100, 0), +(@PATH, 8, -9661.323, 1537.9355, 42.959347, 0, 0, 0, 0, 100, 0), +(@PATH, 9, -9647.55, 1544.9911, 42.959347, 0, 0, 0, 0, 100, 0), +(@PATH, 10, -9651.3125, 1565.7776, 42.98713, 0, 0, 0, 0, 100, 0), +(@PATH, 11, -9657.682, 1593.8557, 45.070454, 0, 0, 0, 0, 100, 0), +(@PATH, 12, -9684.013, 1619.9458, 45.070454, 0, 0, 0, 0, 100, 0), +(@PATH, 13, -9645.765, 1642.1168, 50.042664, 0, 0, 0, 0, 100, 0), +(@PATH, 14, -9618.591, 1606.9883, 45.070454, 0, 0, 0, 0, 100, 0), +(@PATH, 15, -9624.827, 1566.3673, 45.070454, 0, 0, 0, 0, 100, 0), +(@PATH, 16, -9662.095, 1559.2485, 45.070454, 0, 0, 0, 0, 100, 0), +(@PATH, 17, -9689.207, 1559.972, 45.070454, 0, 0, 0, 0, 100, 0), +(@PATH, 18, -9692.733, 1523.6748, 45.070454, 0, 0, 0, 0, 100, 0), +(@PATH, 19, -9731.375, 1527.3365, 45.070454, 0, 0, 0, 0, 100, 0), +(@PATH, 20, -9729.185, 1490.0042, 45.070454, 0, 0, 0, 0, 100, 0), +(@PATH, 21, -9745.345, 1485.0509, 45.487125, 0, 0, 0, 0, 100, 0); + +SET @PATH := (@NPC + 7) * 10; +DELETE FROM `waypoint_data` WHERE `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(@PATH, 1, -9745.88, 1488.399, 45.917397, 0, 0, 0, 0, 100, 0), +(@PATH, 2, -9744.661, 1507.4883, 46.028458, 0, 0, 0, 0, 100, 0), +(@PATH, 3, -9735.175, 1527.706, 43.806267, 0, 0, 0, 0, 100, 0), +(@PATH, 4, -9701.6455, 1545.9641, 44.3896, 0, 0, 0, 0, 100, 0), +(@PATH, 5, -9658.681, 1541.812, 43.472916, 0, 0, 0, 0, 100, 0), +(@PATH, 6, -9616.4375, 1554.6978, 41.278492, 0, 0, 0, 0, 100, 0), +(@PATH, 7, -9583.255, 1572.3322, 42.61181, 0, 0, 0, 0, 100, 0), +(@PATH, 8, -9594.106, 1611.233, 43.16736, 0, 0, 0, 0, 100, 0), +(@PATH, 9, -9626.409, 1625.0471, 40.945137, 0, 0, 0, 0, 100, 0), +(@PATH, 10, -9665.356, 1653.7917, 45.472958, 0, 0, 0, 0, 100, 0), +(@PATH, 11, -9684.14, 1617.8658, 42.111813, 0, 0, 0, 0, 100, 0), +(@PATH, 12, -9687.5625, 1573.8448, 43.97294, 0, 0, 0, 0, 100, 0), +(@PATH, 13, -9690.304, 1535.7795, 44.167366, 0, 0, 0, 0, 100, 0), +(@PATH, 14, -9711.632, 1498.4967, 41.334064, 0, 0, 0, 0, 100, 0), +(@PATH, 15, -9741.987, 1484.3424, 45.7785, 0, 0, 0, 0, 100, 0); + +DELETE FROM `creature_addon` WHERE `guid` = 144641; + +DELETE FROM `creature_template_movement` WHERE `CreatureId` = 15369; +INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Chase`, `Random`, `InteractionPauseTimer`) VALUES +(15369, 1, 0, 1, 0, 0, NULL); diff --git a/data/sql/updates/db_world/2022_08_15_05.sql b/data/sql/updates/db_world/2022_08_15_05.sql new file mode 100644 index 000000000..335c5db78 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_15_05.sql @@ -0,0 +1,12 @@ +-- DB update 2022_08_15_04 -> 2022_08_15_05 +-- +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 1491; +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 1491) AND (`source_type` = 0) AND (`id` IN (0, 1)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `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 +(1491, 0, 0, 0, 0, 0, 100, 512, 3000, 6000, 7000, 8000, 0, 11, 9080, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Zanzil Naga - In Combat - Cast \'Hamstring\''), +(1491, 0, 1, 0, 0, 0, 100, 512, 4000, 5000, 10000, 11000, 0, 11, 12555, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Zanzil Naga - In Combat - Cast \'Pummel\''); + +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 1488; +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 1488) 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`, `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 +(1488, 0, 0, 0, 0, 0, 100, 513, 2000, 3000, 0, 0, 0, 11, 7102, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Zanzil Zombie - In Combat - Cast \'Contagion of Rot\' (No Repeat)'); diff --git a/data/sql/updates/db_world/2022_08_15_06.sql b/data/sql/updates/db_world/2022_08_15_06.sql new file mode 100644 index 000000000..41eb9c252 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_15_06.sql @@ -0,0 +1,3 @@ +-- DB update 2022_08_15_05 -> 2022_08_15_06 +-- +UPDATE `gameobject_template_addon` SET `flags`=`flags`|1 WHERE `entry`=180619; diff --git a/data/sql/updates/db_world/2022_08_15_07.sql b/data/sql/updates/db_world/2022_08_15_07.sql new file mode 100644 index 000000000..1aef808c9 --- /dev/null +++ b/data/sql/updates/db_world/2022_08_15_07.sql @@ -0,0 +1,63 @@ +-- DB update 2022_08_15_06 -> 2022_08_15_07 +DELETE FROM `creature_queststarter` WHERE `quest` IN (6821, 6822, 6823, 6824, 7486) AND `id` = 13278; +INSERT INTO `creature_queststarter` (`id`, `quest`) VALUES +(13278, 6821), -- Eye of the Emberseer +(13278, 6822), -- The Molten Core +(13278, 6823), -- Agent of Hydraxis +(13278, 6824), -- Hands of the Enemy +(13278, 7486); -- A Hero's Reward + +DELETE FROM `creature_questender` WHERE `quest` IN (6804, 6821, 6822, 6823, 6824) AND `id` = 13278; +INSERT INTO `creature_questender` (`id`, `quest`) VALUES +(13278, 6804), -- Poisoned Water +(13278, 6821), -- Eye of the Emberseer +(13278, 6822), -- The Molten Core +(13278, 6823), -- Agent of Hydraxis +(13278, 6824); -- Hands of the Enemy + +DELETE FROM `quest_template_addon` WHERE `ID` IN (6821, 6822, 6823, 6824, 7486); +INSERT INTO `quest_template_addon` (`ID`, `PrevQuestID`, `NextQuestID`) VALUES +(6821, 6805, 6822), +(6822, 6021, 6823), +(6823, 6022, 6824), +(6824, 6823, 7486), +(7486, 6824, 0); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 19 AND `SourceEntry` = 6821; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(19, 0, 6821, 0, 0, 47, 0, 6804, 64, 0, 0, 0, 0, '', 'Quest Eyes of the Emberseer available if quest Poisoned Water has been rewarded.'), +(19, 0, 6821, 0, 0, 47, 0, 6805, 64, 0, 0, 0, 0, '', 'Quest Eyes of the Emberseer available if quest Stormers and Rumblers has been rewarded.'); + +DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 15) AND (`SourceGroup` = 5065) AND (`SourceId` IN (0, 1)); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(15, 5065, 0, 0, 0, 5, 0, 749, 224, 0, 0, 0, 0, '', 'Duke Hydraxis - Create Aqual Quintessence Gossip - Requires Honored Rep'), +(15, 5065, 0, 0, 0, 47, 0, 6824, 64, 0, 0, 0, 0, '', 'Duke Hydraxis - Aqual Quintessence Gossip available if quest Hand of the Enemy rewarded.'), +(15, 5065, 1, 0, 0, 5, 0, 749, 192, 0, 0, 0, 0, '', 'Duke Hydraxis - Create Eternal Quintessence Gossip - Requires Revered Rep'), +(15, 5065, 1, 0, 0, 47, 0, 6824, 64, 0, 0, 0, 0, '', 'Duke Hydraxis - Create Eternal Quintessence Gossip - Requires Hand of the Enemy rewarded'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 19 AND `SourceEntry` IN (6822, 6823, 6824, 7486); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(19, 0, 6822, 0, 0, 47, 0, 6821, 64, 0, 0, 0, 0, '', 'Quest Molten Core available if quest Eye of the Emberseer has been rewarded.'), +(19, 0, 6823, 0, 0, 47, 0, 6822, 64, 0, 0, 0, 0, '', 'Quest Agent of Hydraxis available if quest Molten Core has been rewarded.'), +(19, 0, 6824, 0, 0, 47, 0, 6823, 64, 0, 0, 0, 0, '', 'Quest Hands of the Enemy available if quest Agents of Hydraxis has been rewarded.'), +(19, 0, 7486, 0, 0, 47, 0, 6824, 64, 0, 0, 0, 0, '', 'Quest A Hero\'s Reward available if quest Hands of the Enemy has been rewarded.'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 19 AND `SourceEntry` IN (6822, 6823, 6824, 7486); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(19, 0, 6822, 0, 0, 47, 0, 6821, 64, 0, 0, 0, 0, '', 'Quest Molten Core available if quest Eye of the Emberseer has been rewarded.'), +(19, 0, 6823, 0, 0, 47, 0, 6822, 64, 0, 0, 0, 0, '', 'Quest Agent of Hydraxis available if quest Molten Core has been rewarded.'), +(19, 0, 6824, 0, 0, 47, 0, 6823, 64, 0, 0, 0, 0, '', 'Quest Hands of the Enemy available if quest Agents of Hydraxis has been rewarded.'), +(19, 0, 7486, 0, 0, 47, 0, 6824, 64, 0, 0, 0, 0, '', 'Quest A Hero\'s Reward available if quest Hands of the Enemy has been rewarded.'); + +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 13278; +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 13278) AND (`source_type` = 0) AND (`id` IN (0, 1, 2, 3)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `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 +(13278, 0, 0, 1, 62, 0, 100, 0, 5065, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Duke Hydraxis - On Gossip Option 0 Selected - Close Gossip'), +(13278, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 56, 17333, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Duke Hydraxis - On Link - Add item \'Aqual Quintessence\''), +(13278, 0, 2, 3, 62, 0, 100, 0, 5065, 1, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Duke Hydraxis - On Gossip Option 1 Selected - Close Gossip'), +(13278, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 56, 22754, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Duke Hydraxis - On Link - Add item \' Eternal Quintessence\''); + +DELETE FROM `gossip_menu_option` WHERE `MenuID` = 5065 AND `OptionID` IN (0, 1); +INSERT INTO `gossip_menu_option` (`MenuID`, `OptionID`, `OptionIcon`, `OptionText`, `OptionBroadcastTextID`, `OptionType`, `OptionNpcFlag`, `ActionMenuID`, `ActionPoiID`, `BoxCoded`, `BoxMoney`, `BoxText`, `BoxBroadcastTextID`, `VerifiedBuild`) VALUES +(5065,0,0,'I require a vial of aqual quintessence, Hydraxis, for I go to the Molten Core to extinguish a rune of the Firelords.',8666,1,2,0,0,0,0,'',0,0), +(5065,1,0,'I desire this eternal quintessence, Duke Hydraxis.',12363,1,2,0,0,0,0,'',0,0); diff --git a/data/sql/updates/db_world/2022_08_15_08.sql b/data/sql/updates/db_world/2022_08_15_08.sql new file mode 100644 index 000000000..8e8745d1a --- /dev/null +++ b/data/sql/updates/db_world/2022_08_15_08.sql @@ -0,0 +1,5 @@ +-- DB update 2022_08_15_07 -> 2022_08_15_08 +-- +UPDATE `creature_template` SET `unit_flags` = `unit_flags` | 33554432, `ScriptName` = 'npc_dirt_mound' WHERE `entry` = 15712; + +UPDATE `gameobject_template_addon` SET `flags` = `flags` | 16 WHERE `entry` = 180795; diff --git a/data/sql/updates/db_world/2022_08_16_00.sql b/data/sql/updates/db_world/2022_08_16_00.sql new file mode 100644 index 000000000..d1a2a259e --- /dev/null +++ b/data/sql/updates/db_world/2022_08_16_00.sql @@ -0,0 +1,60 @@ +-- DB update 2022_08_15_08 -> 2022_08_16_00 +-- +UPDATE `quest_template_addon` SET `SpecialFlags` = `SpecialFlags` | 1 WHERE `id` IN (8805, 8807); + +SET @ENTRY := 21132; +DELETE FROM `item_loot_template` WHERE `Entry` = @ENTRY; +INSERT INTO `item_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(@ENTRY, 20939, 0, 0, 0, 1, 1, 1, 1, "Logistics Assigment II - Alliance"), +(@ENTRY, 21257, 0, 0, 0, 1, 1, 1, 1, "Logistics Assigment IV"), +(@ENTRY, 21259, 0, 0, 0, 1, 1, 1, 1, "Logistics Assigment V"), +(@ENTRY, 21260, 0, 0, 0, 1, 1, 1, 1, "Logistics Assigment VI"), +(@ENTRY, 21263, 0, 0, 0, 1, 1, 1, 1, "Logistics Assigment VII"), +(@ENTRY, 20806, 0, 0, 0, 1, 1, 1, 1, "Logistics Assigment X"); + +SET @ENTRY := 21266; +DELETE FROM `item_loot_template` WHERE `Entry` = @ENTRY; +INSERT INTO `item_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(@ENTRY, 21379, 0, 0, 0, 1, 1, 1, 1, "Logistics Assigment II - Horde"), +(@ENTRY, 21258, 0, 0, 0, 1, 1, 1, 1, "Logistics Assigment IV - Horde"), +(@ENTRY, 21382, 0, 0, 0, 1, 1, 1, 1, "Logistics Assigment V - Horde"), +(@ENTRY, 21261, 0, 0, 0, 1, 1, 1, 1, "Logistics Assigment VI - Horde"), +(@ENTRY, 21264, 0, 0, 0, 1, 1, 1, 1, "Logistics Assigment VII - Horde"), +(@ENTRY, 21385, 0, 0, 0, 1, 1, 1, 1, "Logistics Assigment X - Horde"); + + +SET @ENTRY := 20805; +DELETE FROM `item_loot_template` WHERE `Entry` = @ENTRY; +INSERT INTO `item_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(@ENTRY, 20807, 0, 0, 0, 1, 1, 1, 1, "Logistics Assignment I - Alliance"), +(@ENTRY, 20940, 0, 0, 0, 1, 1, 1, 1, "Logistics Assignment III - Alliance"), +(@ENTRY, 21262, 0, 0, 0, 1, 1, 1, 1, "Logistics Assignment VIII - Alliance"), +(@ENTRY, 21265, 0, 0, 0, 1, 1, 1, 1, "Logistics Assignment IX - Alliance"), +(@ENTRY, 21514, 0, 0, 0, 1, 1, 1, 1, "Logistics Assignment XI - Alliance"); + +SET @ENTRY := 21386; +DELETE FROM `item_loot_template` WHERE `Entry` = @ENTRY; +INSERT INTO `item_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(@ENTRY, 21378, 0, 0, 0, 1, 1, 1, 1, "Logistics Assignment I - Horde"), +(@ENTRY, 21380, 0, 0, 0, 1, 1, 1, 1, "Logistics Assignment III - Horde"), +(@ENTRY, 21384, 0, 0, 0, 1, 1, 1, 1, "Logistics Assignment VIII - Horde"), +(@ENTRY, 21381, 0, 0, 0, 1, 1, 1, 1, "Logistics Assignment IX - Horde"), +(@ENTRY, 21514, 0, 0, 0, 1, 1, 1, 1, "Logistics Assignment XI - Horde"); + +SET @ENTRY := 20809; +DELETE FROM `item_loot_template` WHERE `Entry` = @ENTRY; +INSERT INTO `item_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(@ENTRY, 21245, 0, 0, 0, 1, 1, 1, 1, "Tactical Assignment I - Horde"), +(@ENTRY, 21751, 0, 0, 0, 1, 1, 1, 1, "Tactical Assignment III - Horde"), +(@ENTRY, 21165, 0, 0, 0, 1, 1, 1, 1, "Tactical Assignment VI - Horde"), +(@ENTRY, 21166, 0, 0, 0, 1, 1, 1, 1, "Tactical Assignment VII - Horde"), +(@ENTRY, 20944, 0, 0, 0, 1, 1, 1, 1, "Tactical Assignment IX - Horde"); + +SET @ENTRY := 21133; +DELETE FROM `item_loot_template` WHERE `Entry` = @ENTRY; +INSERT INTO `item_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(@ENTRY, 20945, 0, 0, 0, 1, 1, 1, 1, "Tactical Assignment II - Horde"), +(@ENTRY, 20947, 0, 0, 0, 1, 1, 1, 1, "Tactical Assignment IV - Horde"), +(@ENTRY, 20948, 0, 0, 0, 1, 1, 1, 1, "Tactical Assignment V - Horde"), +(@ENTRY, 21167, 0, 0, 0, 1, 1, 1, 1, "Tactical Assignment VIII - Horde"), +(@ENTRY, 20943, 0, 0, 0, 1, 1, 1, 1, "Tactical Assignment X - Horde"); diff --git a/src/common/Utilities/EventEmitter.h b/src/common/Utilities/EventEmitter.h new file mode 100644 index 000000000..77755935b --- /dev/null +++ b/src/common/Utilities/EventEmitter.h @@ -0,0 +1,44 @@ +/* + * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by the + * Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef __EVENT_EMITTER_H +#define __EVENT_EMITTER_H + +template +class EventEmitter +{ +public: + template + void operator+=(Functor&& f) + { + functions.emplace_back(std::forward(f)); + } + + template + void operator()(Args&&... args) const + { + for (auto& f : functions) + { + f(args...); + } + } + +private: + std::vector> functions; +}; + +#endif diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index 314c37b17..dd44d437a 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -102,7 +102,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_SEL_CHARACTER_CRITERIAPROGRESS, "SELECT criteria, counter, date FROM character_achievement_progress WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHARACTER_EQUIPMENTSETS, "SELECT setguid, setindex, name, iconname, ignore_mask, item0, item1, item2, item3, item4, item5, item6, item7, item8, " "item9, item10, item11, item12, item13, item14, item15, item16, item17, item18 FROM character_equipmentsets WHERE guid = ? ORDER BY setindex", CONNECTION_ASYNC); - PrepareStatement(CHAR_SEL_CHARACTER_ENTRY_POINT, "SELECT joinX, joinY, joinZ, joinO, joinMapId, taxiPath, mountSpell FROM character_entry_point WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_SEL_CHARACTER_ENTRY_POINT, "SELECT joinX, joinY, joinZ, joinO, joinMapId, taxiPath0, taxiPath1, mountSpell FROM character_entry_point WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHARACTER_GLYPHS, "SELECT talentGroup, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6 FROM character_glyphs WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHARACTER_TALENTS, "SELECT spell, specMask FROM character_talent WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHARACTER_SKILLS, "SELECT skill, value, max FROM character_skills WHERE guid = ?", CONNECTION_ASYNC); @@ -286,7 +286,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_UPD_ARENA_TEAM_NAME, "UPDATE arena_team SET name = ? WHERE arenaTeamId = ?", CONNECTION_ASYNC); // Character battleground data - PrepareStatement(CHAR_INS_PLAYER_ENTRY_POINT, "INSERT INTO character_entry_point (guid, joinX, joinY, joinZ, joinO, joinMapId, taxiPath, mountSpell) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); + PrepareStatement(CHAR_INS_PLAYER_ENTRY_POINT, "INSERT INTO character_entry_point (guid, joinX, joinY, joinZ, joinO, joinMapId, taxiPath0, taxiPath1, mountSpell) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_PLAYER_ENTRY_POINT, "DELETE FROM character_entry_point WHERE guid = ?", CONNECTION_ASYNC); // Character homebind diff --git a/src/server/game/AI/CoreAI/PassiveAI.cpp b/src/server/game/AI/CoreAI/PassiveAI.cpp index d1ac8350f..f8b8973d7 100644 --- a/src/server/game/AI/CoreAI/PassiveAI.cpp +++ b/src/server/game/AI/CoreAI/PassiveAI.cpp @@ -29,7 +29,7 @@ int32 NullCreatureAI::Permissible(Creature const* creature) return PERMIT_BASE_PROACTIVE + 50; if (creature->IsTrigger()) - return PERMIT_BASE_REACTIVE; + return PERMIT_BASE_PROACTIVE; return PERMIT_BASE_IDLE; } diff --git a/src/server/game/AI/CoreAI/UnitAI.cpp b/src/server/game/AI/CoreAI/UnitAI.cpp index baf48ef86..1304a6cfe 100644 --- a/src/server/game/AI/CoreAI/UnitAI.cpp +++ b/src/server/game/AI/CoreAI/UnitAI.cpp @@ -90,6 +90,24 @@ bool UnitAI::DoSpellAttackIfReady(uint32 spell) return false; } +void UnitAI::DoSpellAttackToRandomTargetIfReady(uint32 spell, uint32 threatTablePosition /*= 0*/, float dist /*= 0.f*/, bool playerOnly /*= true*/) +{ + if (me->HasUnitState(UNIT_STATE_CASTING) || !me->isAttackReady()) + return; + + if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell)) + { + if (Unit* target = SelectTarget(SelectTargetMethod::Random, threatTablePosition, dist, playerOnly)) + { + if (me->IsWithinCombatRange(target, spellInfo->GetMaxRange(false))) + { + me->CastSpell(target, spell, false); + me->resetAttackTimer(); + } + } + } +} + Unit* UnitAI::SelectTarget(SelectTargetMethod targetType, uint32 position, float dist, bool playerOnly, int32 aura) { return SelectTarget(targetType, position, DefaultTargetSelector(me, dist, playerOnly, aura)); @@ -106,6 +124,14 @@ float UnitAI::DoGetSpellMaxRange(uint32 spellId, bool positive) return spellInfo ? spellInfo->GetMaxRange(positive) : 0; } +std::string UnitAI::GetDebugInfo() const +{ + std::stringstream sstr; + sstr << std::boolalpha + << "Me: " << (me ? me->GetDebugInfo() : "NULL"); + return sstr.str(); +} + SpellCastResult UnitAI::DoAddAuraToAllHostilePlayers(uint32 spellid) { if (me->IsInCombat()) diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h index ae24f2dcb..a423997b9 100644 --- a/src/server/game/AI/CoreAI/UnitAI.h +++ b/src/server/game/AI/CoreAI/UnitAI.h @@ -330,6 +330,7 @@ public: void DoMeleeAttackIfReady(); bool DoSpellAttackIfReady(uint32 spell); + void DoSpellAttackToRandomTargetIfReady(uint32 spell, uint32 threatTablePosition = 0, float dist = 0.f, bool playerOnly = true); static AISpellInfoType* AISpellInfo; static void FillAISpellInfo(); @@ -345,6 +346,8 @@ public: virtual void sQuestComplete(Player* /*player*/, Quest const* /*quest*/) {} virtual void sQuestReward(Player* /*player*/, Quest const* /*quest*/, uint32 /*opt*/) {} virtual void sOnGameEvent(bool /*start*/, uint16 /*eventId*/) {} + + virtual std::string GetDebugInfo() const; }; class PlayerAI : public UnitAI diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 29cda5530..61db4f067 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -917,7 +917,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (IsUnit(target)) { float angle = e.action.follow.angle > 6 ? (e.action.follow.angle * M_PI / 180.0f) : e.action.follow.angle; - CAST_AI(SmartAI, me->AI())->SetFollow(target->ToUnit(), float(e.action.follow.dist) + 0.1f, angle, e.action.follow.credit, e.action.follow.entry, e.action.follow.creditType); + CAST_AI(SmartAI, me->AI())->SetFollow(target->ToUnit(), float(e.action.follow.dist) + 0.1f, angle, e.action.follow.credit, e.action.follow.entry, e.action.follow.creditType, e.action.follow.aliveState); LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_FOLLOW: Creature {} following target {}", me->GetGUID().ToString(), target->GetGUID().ToString()); break; @@ -3187,6 +3187,10 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, { targets.push_back(owner); } + else if (me->IsSummon() && me->ToTempSummon()->GetSummonerUnit()) + { + targets.push_back(me->ToTempSummon()->GetSummonerUnit()); + } } else if (go) { diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 92c24beaa..80c2eb221 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -492,7 +492,7 @@ bool SmartAIMgr::CheckUnusedEventParams(SmartScriptHolder const& e) case SMART_EVENT_IC_LOS: return sizeof(SmartEvent::los); case SMART_EVENT_PASSENGER_BOARDED: return sizeof(SmartEvent::minMax); case SMART_EVENT_PASSENGER_REMOVED: return sizeof(SmartEvent::minMax); - // case SMART_EVENT_CHARMED: return sizeof(SmartEvent::charm); + case SMART_EVENT_CHARMED: return sizeof(SmartEvent::charm); case SMART_EVENT_CHARMED_TARGET: return NO_PARAMS; case SMART_EVENT_SPELLHIT_TARGET: return sizeof(SmartEvent::spellHit); case SMART_EVENT_DAMAGED: return sizeof(SmartEvent::minMaxRepeat); @@ -533,7 +533,7 @@ bool SmartAIMgr::CheckUnusedEventParams(SmartScriptHolder const& e) case SMART_EVENT_IS_BEHIND_TARGET: return sizeof(SmartEvent::behindTarget); case SMART_EVENT_GAME_EVENT_START: return sizeof(SmartEvent::gameEvent); case SMART_EVENT_GAME_EVENT_END: return sizeof(SmartEvent::gameEvent); - // case SMART_EVENT_GO_LOOT_STATE_CHANGED: return sizeof(SmartEvent::goLootStateChanged); + case SMART_EVENT_GO_STATE_CHANGED: return sizeof(SmartEvent::goStateChanged); case SMART_EVENT_GO_EVENT_INFORM: return sizeof(SmartEvent::eventInform); case SMART_EVENT_ACTION_DONE: return sizeof(SmartEvent::doAction); case SMART_EVENT_ON_SPELLCLICK: return NO_PARAMS; @@ -546,9 +546,11 @@ bool SmartAIMgr::CheckUnusedEventParams(SmartScriptHolder const& e) //case SMART_EVENT_SCENE_CANCEL: return sizeof(SmartEvent::raw); //case SMART_EVENT_SCENE_COMPLETE: return sizeof(SmartEvent::raw); case SMART_EVENT_SUMMONED_UNIT_DIES: return sizeof(SmartEvent::summoned); + case SMART_EVENT_NEAR_PLAYERS: return sizeof(SmartEvent::nearPlayer); + case SMART_EVENT_NEAR_PLAYERS_NEGATION: return sizeof(SmartEvent::nearPlayerNegation); default: - LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using an event with no unused params specified in SmartAIMgr::CheckUnusedEventParams(), please report this.", - e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); + LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using an event {} with no unused params specified in SmartAIMgr::CheckUnusedEventParams(), please report this.", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetEventType()); return sizeof(SmartEvent::raw); } }(); @@ -602,8 +604,8 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e) case SMART_ACTION_ALLOW_COMBAT_MOVEMENT: return sizeof(SmartAction::combatMove); case SMART_ACTION_SET_EVENT_PHASE: return sizeof(SmartAction::setEventPhase); case SMART_ACTION_INC_EVENT_PHASE: return sizeof(SmartAction::incEventPhase); - // case SMART_ACTION_EVADE: return sizeof(SmartAction::evade); - // case SMART_ACTION_FLEE_FOR_ASSIST: return sizeof(SmartAction::fleeAssist); + case SMART_ACTION_EVADE: return NO_PARAMS; + case SMART_ACTION_FLEE_FOR_ASSIST: return sizeof(SmartAction::flee); case SMART_ACTION_CALL_GROUPEVENTHAPPENS: return sizeof(SmartAction::quest); case SMART_ACTION_COMBAT_STOP: return NO_PARAMS; case SMART_ACTION_REMOVEAURASFROMSPELL: return sizeof(SmartAction::removeAura); @@ -624,9 +626,10 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e) case SMART_ACTION_MOUNT_TO_ENTRY_OR_MODEL: return sizeof(SmartAction::morphOrMount); case SMART_ACTION_SET_INGAME_PHASE_MASK: return sizeof(SmartAction::ingamePhaseMask); case SMART_ACTION_SET_DATA: return sizeof(SmartAction::setData); + case SMART_ACTION_MOVE_FORWARD: return sizeof(SmartAction::moveRandom); case SMART_ACTION_ATTACK_STOP: return NO_PARAMS; case SMART_ACTION_SET_VISIBILITY: return sizeof(SmartAction::visibility); - // case SMART_ACTION_SET_ACTIVE: return sizeof(SmartAction::active); + case SMART_ACTION_SET_ACTIVE: return sizeof(SmartAction::setActive); case SMART_ACTION_ATTACK_START: return NO_PARAMS; case SMART_ACTION_SUMMON_GO: return sizeof(SmartAction::summonGO); case SMART_ACTION_KILL_UNIT: return NO_PARAMS; @@ -638,7 +641,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e) case SMART_ACTION_REMOVE_ITEM: return sizeof(SmartAction::item); case SMART_ACTION_INSTALL_AI_TEMPLATE: return sizeof(SmartAction::installTtemplate); case SMART_ACTION_SET_RUN: return sizeof(SmartAction::setRun); - // case SMART_ACTION_SET_DISABLE_GRAVITY: return sizeof(SmartAction::setDisableGravity); + case SMART_ACTION_SET_FLY: return sizeof(SmartAction::setFly); case SMART_ACTION_SET_SWIM: return sizeof(SmartAction::setSwim); case SMART_ACTION_TELEPORT: return sizeof(SmartAction::teleport); case SMART_ACTION_SET_COUNTER: return sizeof(SmartAction::setCounter); @@ -648,7 +651,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e) case SMART_ACTION_CREATE_TIMED_EVENT: return sizeof(SmartAction::timeEvent); case SMART_ACTION_PLAYMOVIE: return sizeof(SmartAction::movie); case SMART_ACTION_MOVE_TO_POS: return sizeof(SmartAction::moveToPos); - // case SMART_ACTION_ENABLE_TEMP_GOBJ: return sizeof(SmartAction::enableTempGO); + case SMART_ACTION_RESPAWN_TARGET: return sizeof(SmartAction::RespawnTarget); case SMART_ACTION_EQUIP: return sizeof(SmartAction::equip); case SMART_ACTION_CLOSE_GOSSIP: return NO_PARAMS; case SMART_ACTION_TRIGGER_TIMED_EVENT: return sizeof(SmartAction::timeEvent); @@ -663,7 +666,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e) case SMART_ACTION_ADD_NPC_FLAG: return sizeof(SmartAction::flag); case SMART_ACTION_REMOVE_NPC_FLAG: return sizeof(SmartAction::flag); case SMART_ACTION_SIMPLE_TALK: return sizeof(SmartAction::simpleTalk); - // case SMART_ACTION_SELF_CAST: return sizeof(SmartAction::cast); + case SMART_ACTION_INVOKER_CAST: return sizeof(SmartAction::cast); case SMART_ACTION_CROSS_CAST: return sizeof(SmartAction::crossCast); case SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST: return sizeof(SmartAction::randTimedActionList); case SMART_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST: return sizeof(SmartAction::randRangeTimedActionList); @@ -692,7 +695,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e) case SMART_ACTION_GAME_EVENT_STOP: return sizeof(SmartAction::gameEventStop); case SMART_ACTION_GAME_EVENT_START: return sizeof(SmartAction::gameEventStart); case SMART_ACTION_START_CLOSEST_WAYPOINT: return sizeof(SmartAction::closestWaypointFromList); - // case SMART_ACTION_MOVE_OFFSET: return NO_PARAMS; + case SMART_ACTION_RISE_UP: return sizeof(SmartAction::moveRandom); case SMART_ACTION_RANDOM_SOUND: return sizeof(SmartAction::randomSound); case SMART_ACTION_SET_CORPSE_DELAY: return sizeof(SmartAction::corpseDelay); case SMART_ACTION_DISABLE_EVADE: return sizeof(SmartAction::disableEvade); @@ -722,6 +725,19 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e) case SMART_ACTION_SET_HOVER: return sizeof(SmartAction::setHover); case SMART_ACTION_SET_HEALTH_PCT: return sizeof(SmartAction::setHealthPct); //case SMART_ACTION_CREATE_CONVERSATION: return sizeof(SmartAction::raw); + case SMART_ACTION_MOVE_TO_POS_TARGET: return sizeof(SmartAction::moveToPos); + case SMART_ACTION_SET_GO_STATE: return sizeof(SmartAction::goState); + case SMART_ACTION_EXIT_VEHICLE: return NO_PARAMS; + case SMART_ACTION_SET_UNIT_MOVEMENT_FLAGS: return sizeof(SmartAction::movementFlag); + case SMART_ACTION_SET_COMBAT_DISTANCE: return sizeof(SmartAction::combatDistance); + case SMART_ACTION_SET_CASTER_COMBAT_DIST: return sizeof(SmartAction::casterDistance); + case SMART_ACTION_FALL: return NO_PARAMS; + case SMART_ACTION_SET_EVENT_FLAG_RESET: return sizeof(SmartAction::setActive); + case SMART_ACTION_STOP_MOTION: return sizeof(SmartAction::stopMotion); + case SMART_ACTION_NO_ENVIRONMENT_UPDATE: return NO_PARAMS; + case SMART_ACTION_ZONE_UNDER_ATTACK: return NO_PARAMS; + case SMART_ACTION_LOAD_GRID: return NO_PARAMS; + case SMART_ACTION_MUSIC: return sizeof(SmartAction::music); default: LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using an action with no unused params specified in SmartAIMgr::CheckUnusedActionParams(), please report this.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); @@ -785,9 +801,10 @@ bool SmartAIMgr::CheckUnusedTargetParams(SmartScriptHolder const& e) case SMART_TARGET_FARTHEST: return sizeof(SmartTarget::farthest); case SMART_TARGET_VEHICLE_PASSENGER: return sizeof(SmartTarget::vehicle); // case SMART_TARGET_CLOSEST_UNSPAWNED_GAMEOBJECT: return sizeof(SmartTarget::goClosest); + case SMART_TARGET_PLAYER_WITH_AURA: return sizeof(SmartTarget::playerWithAura); default: - LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using a target with no unused params specified in SmartAIMgr::CheckUnusedTargetParams(), please report this.", - e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); + LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using a target {} with no unused params specified in SmartAIMgr::CheckUnusedTargetParams(), please report this.", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType()); return sizeof(SmartTarget::raw); } }(); diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.cpp b/src/server/game/Battlegrounds/BattlegroundQueue.cpp index 7f1cbe78b..43f9b7320 100644 --- a/src/server/game/Battlegrounds/BattlegroundQueue.cpp +++ b/src/server/game/Battlegrounds/BattlegroundQueue.cpp @@ -86,28 +86,29 @@ bool BattlegroundQueue::SelectionPool::KickGroup(const uint32 size) // find last group with proper size or largest bool foundProper = false; - auto groupToKick = SelectedGroups.begin(); - for (auto& itr = groupToKick; itr != SelectedGroups.end(); ++itr) + GroupQueueInfo* groupToKick{ SelectedGroups.front() }; + + for (auto const& gInfo : SelectedGroups) { // if proper size - overwrite to kick last one - if (std::abs(int32((*itr)->Players.size()) - (int32)size) <= 1) + if (std::abs(int32(gInfo->Players.size()) - (int32)size) <= 1) { - groupToKick = itr; + groupToKick = gInfo; foundProper = true; } - else if (!foundProper && (*itr)->Players.size() >= (*groupToKick)->Players.size()) - groupToKick = itr; + else if (!foundProper && gInfo->Players.size() >= groupToKick->Players.size()) + groupToKick = gInfo; } // remove selected from pool - GroupQueueInfo* ginfo = (*groupToKick); - SelectedGroups.erase(groupToKick); - PlayerCount -= ginfo->Players.size(); + auto playersCountInGroup{ groupToKick->Players.size() }; + PlayerCount -= playersCountInGroup; + std::erase(SelectedGroups, groupToKick); if (foundProper) return false; - return (ginfo->Players.size() > size); + return playersCountInGroup > size; } // returns true if added or desired count not yet reached diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index ccf220a9c..7a03bd85c 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -565,11 +565,11 @@ void LoadDBCStores(const std::string& dataPath) if (sInfo->Effect[j] == SPELL_EFFECT_SEND_TAXI) spellPaths.insert(sInfo->EffectMiscValue[j]); - memset(sTaxiNodesMask, 0, sizeof(sTaxiNodesMask)); - memset(sOldContinentsNodesMask, 0, sizeof(sOldContinentsNodesMask)); - memset(sHordeTaxiNodesMask, 0, sizeof(sHordeTaxiNodesMask)); - memset(sAllianceTaxiNodesMask, 0, sizeof(sAllianceTaxiNodesMask)); - memset(sDeathKnightTaxiNodesMask, 0, sizeof(sDeathKnightTaxiNodesMask)); + sTaxiNodesMask.fill(0); + sOldContinentsNodesMask.fill(0); + sHordeTaxiNodesMask.fill(0); + sAllianceTaxiNodesMask.fill(0); + sDeathKnightTaxiNodesMask.fill(0); for (uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i) { diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 7e261d8d7..34976db59 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -3656,3 +3656,12 @@ uint32 Creature::GetPlayerDamageReq() const { return _playerDamageReq; } + +std::string Creature::GetDebugInfo() const +{ + std::stringstream sstr; + sstr << Unit::GetDebugInfo() << "\n" + << "AIName: " << GetAIName() << " ScriptName: " << GetScriptName() + << " WaypointPath: " << GetWaypointPath() << " SpawnId: " << GetSpawnId(); + return sstr.str(); +} diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index ffafd9bf4..782e94ffa 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -385,6 +385,8 @@ public: void ModifyThreatPercentTemp(Unit* victim, int32 percent, Milliseconds duration); + std::string GetDebugInfo() const override; + protected: bool CreateFromProto(ObjectGuid::LowType guidlow, uint32 Entry, uint32 vehId, const CreatureData* data = nullptr); bool InitEntry(uint32 entry, const CreatureData* data = nullptr); diff --git a/src/server/game/Entities/Creature/TemporarySummon.cpp b/src/server/game/Entities/Creature/TemporarySummon.cpp index 9f3c289e5..a76ea477f 100644 --- a/src/server/game/Entities/Creature/TemporarySummon.cpp +++ b/src/server/game/Entities/Creature/TemporarySummon.cpp @@ -320,6 +320,15 @@ void TempSummon::RemoveFromWorld() Creature::RemoveFromWorld(); } +std::string TempSummon::GetDebugInfo() const +{ + std::stringstream sstr; + sstr << Creature::GetDebugInfo() << "\n" + << std::boolalpha + << "TempSummonType : " << std::to_string(GetSummonType()) << " Summoner: " << GetSummonerGUID().ToString(); + return sstr.str(); +} + Minion::Minion(SummonPropertiesEntry const* properties, ObjectGuid owner, bool isWorldObject) : TempSummon(properties, owner, isWorldObject) , m_owner(owner) { @@ -378,6 +387,15 @@ void Minion::setDeathState(DeathState s, bool despawn) } } +std::string Minion::GetDebugInfo() const +{ + std::stringstream sstr; + sstr << TempSummon::GetDebugInfo() << "\n" + << std::boolalpha + << "Owner: " << (GetOwner() ? GetOwner()->GetGUID().ToString() : ""); + return sstr.str(); +} + Guardian::Guardian(SummonPropertiesEntry const* properties, ObjectGuid owner, bool isWorldObject) : Minion(properties, owner, isWorldObject) { m_unitTypeMask |= UNIT_MASK_GUARDIAN; @@ -416,6 +434,13 @@ void Guardian::InitSummon() } } +std::string Guardian::GetDebugInfo() const +{ + std::stringstream sstr; + sstr << Minion::GetDebugInfo(); + return sstr.str(); +} + Puppet::Puppet(SummonPropertiesEntry const* properties, ObjectGuid owner) : Minion(properties, owner, false), m_owner(owner) //maybe true? { ASSERT(owner.IsPlayer()); diff --git a/src/server/game/Entities/Creature/TemporarySummon.h b/src/server/game/Entities/Creature/TemporarySummon.h index c9700e8da..3e005270f 100644 --- a/src/server/game/Entities/Creature/TemporarySummon.h +++ b/src/server/game/Entities/Creature/TemporarySummon.h @@ -52,12 +52,14 @@ public: [[nodiscard]] Unit* GetSummonerUnit() const; [[nodiscard]] Creature* GetSummonerCreatureBase() const; [[nodiscard]] GameObject* GetSummonerGameObject() const; - ObjectGuid GetSummonerGUID() { return m_summonerGUID; } - TempSummonType const& GetSummonType() { return m_type; } + ObjectGuid GetSummonerGUID() const { return m_summonerGUID; } + TempSummonType GetSummonType() const { return m_type; } uint32 GetTimer() { return m_timer; } void SetTimer(uint32 t) { m_timer = t; } const SummonPropertiesEntry* const m_Properties; + + std::string GetDebugInfo() const override; private: TempSummonType m_type; uint32 m_timer; @@ -77,6 +79,8 @@ public: [[nodiscard]] bool IsPetGhoul() const {return GetEntry() == 26125 /*normal ghoul*/ || GetEntry() == 30230 /*Raise Ally ghoul*/;} // Ghoul may be guardian or pet [[nodiscard]] bool IsGuardianPet() const; void setDeathState(DeathState s, bool despawn = false) override; // override virtual Unit::setDeathState + + std::string GetDebugInfo() const override; protected: const ObjectGuid m_owner; float m_followAngle; @@ -97,6 +101,8 @@ public: void UpdateMaxPower(Powers power) override; void UpdateAttackPowerAndDamage(bool ranged = false) override; void UpdateDamagePhysical(WeaponAttackType attType) override; + + std::string GetDebugInfo() const override; }; class Puppet : public Minion diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index f7dae5606..50a36df5e 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -131,7 +131,7 @@ void GameObject::RemoveFromOwner() return; } - LOG_FATAL("entities.gameobject", "Delete GameObject ({} Entry: {} SpellId {} LinkedGO {}) that lost references to owner {} GO list. Crash possible later.", + LOG_DEBUG("entities.gameobject", "Delete GameObject ({} Entry: {} SpellId {} LinkedGO {}) that lost references to owner {} GO list.", GetGUID().ToString(), GetGOInfo()->entry, m_spellId, GetGOInfo()->GetLinkedGameObjectEntry(), ownerGUID.ToString()); SetOwnerGUID(ObjectGuid::Empty); @@ -3091,3 +3091,11 @@ bool GameObject::IsInSkillupList(ObjectGuid playerGuid) const return false; } + +std::string GameObject::GetDebugInfo() const +{ + std::stringstream sstr; + sstr << WorldObject::GetDebugInfo() << "\n" + << "SpawnId: " << GetSpawnId() << " GoState: " << std::to_string(GetGoState()) << " ScriptId: " << GetScriptId() << " AIName: " << GetAIName(); + return sstr.str(); +} diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index d74f7cccd..ce62f7a55 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -1061,6 +1061,8 @@ public: void UpdateSaveToDb(bool enable); void SavingStateOnDB(); + + std::string GetDebugInfo() const override; protected: bool AIM_Initialize(); GameObjectModel* CreateModel(); diff --git a/src/server/game/Entities/Item/Container/Bag.cpp b/src/server/game/Entities/Item/Container/Bag.cpp index 4d887f082..ad7164c56 100644 --- a/src/server/game/Entities/Item/Container/Bag.cpp +++ b/src/server/game/Entities/Item/Container/Bag.cpp @@ -239,3 +239,10 @@ Item* Bag::GetItemByPos(uint8 slot) const return nullptr; } + +std::string Bag::GetDebugInfo() const +{ + std::stringstream sstr; + sstr << Item::GetDebugInfo(); + return sstr.str(); +} diff --git a/src/server/game/Entities/Item/Container/Bag.h b/src/server/game/Entities/Item/Container/Bag.h index afd59d1c5..dfe7654f8 100644 --- a/src/server/game/Entities/Item/Container/Bag.h +++ b/src/server/game/Entities/Item/Container/Bag.h @@ -35,7 +35,6 @@ public: bool Create(ObjectGuid::LowType guidlow, uint32 itemid, Player const* owner) override; - void Clear(); void StoreItem(uint8 slot, Item* pItem, bool update); void RemoveItem(uint8 slot, bool update); @@ -58,6 +57,8 @@ public: void BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) const override; + std::string GetDebugInfo() const override; + protected: // Bag Storage space Item* m_bagslot[MAX_BAG_SIZE]; diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp index 01149086f..bfcb13892 100644 --- a/src/server/game/Entities/Item/Item.cpp +++ b/src/server/game/Entities/Item/Item.cpp @@ -1097,7 +1097,7 @@ Item* Item::CreateItem(uint32 item, uint32 count, Player const* player, bool clo if (count > pProto->GetMaxStackSize()) count = pProto->GetMaxStackSize(); - ASSERT(count != 0 && "pProto->Stackable == 0 but checked at loading already"); + ASSERT_NODEBUGINFO(count != 0 && "pProto->Stackable == 0 but checked at loading already"); Item* pItem = NewItemOrBag(pProto); if (pItem->Create(sObjectMgr->GetGenerator().Generate(), item, player)) @@ -1287,3 +1287,13 @@ bool Item::CheckSoulboundTradeExpire() return false; } + +std::string Item::GetDebugInfo() const +{ + std::stringstream sstr; + sstr << Object::GetDebugInfo() << "\n" + << std::boolalpha + << "Owner: " << GetOwnerGUID().ToString() << " Count: " << GetCount() + << " BagSlot: " << std::to_string(GetBagSlot()) << " Slot: " << std::to_string(GetSlot()) << " Equipped: " << IsEquipped(); + return sstr.str(); +} diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h index 6be9b0cfe..300e7a6a1 100644 --- a/src/server/game/Entities/Item/Item.h +++ b/src/server/game/Entities/Item/Item.h @@ -353,6 +353,8 @@ public: void RemoveFromObjectUpdate() override; [[nodiscard]] uint32 GetScriptId() const { return GetTemplate()->ScriptId; } + + std::string GetDebugInfo() const override; private: std::string m_text; uint8 m_slot; diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index ac23ffbaf..506f4c3f9 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -1010,6 +1010,13 @@ bool Object::PrintIndexError(uint32 index, bool set) const return false; } +std::string Object::GetDebugInfo() const +{ + std::stringstream sstr; + sstr << GetGUID().ToString() + " Entry " << GetEntry(); + return sstr.str(); +} + void MovementInfo::OutDebug() { LOG_INFO("movement", "MOVEMENT INFO"); @@ -2419,6 +2426,15 @@ Player* WorldObject::SelectNearestPlayer(float distance) const return target; } +std::string WorldObject::GetDebugInfo() const +{ + std::stringstream sstr; + sstr << WorldLocation::GetDebugInfo() << "\n" + << Object::GetDebugInfo() << "\n" + << "Name: " << GetName(); + return sstr.str(); +} + void WorldObject::GetGameObjectListWithEntryInGrid(std::list& gameobjectList, uint32 entry, float maxSearchRange) const { Acore::AllGameObjectsWithEntryInRange check(this, entry, maxSearchRange); diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index bb1bbb476..a7dcd97e3 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -208,6 +208,8 @@ public: DynamicObject* ToDynObject() { if (GetTypeId() == TYPEID_DYNAMICOBJECT) return reinterpret_cast(this); else return nullptr; } [[nodiscard]] DynamicObject const* ToDynObject() const { if (GetTypeId() == TYPEID_DYNAMICOBJECT) return reinterpret_cast(this); else return nullptr; } + virtual std::string GetDebugInfo() const; + DataMap CustomData; protected: @@ -613,6 +615,8 @@ public: [[nodiscard]] bool HasAllowedLooter(ObjectGuid guid) const; [[nodiscard]] GuidUnorderedSet const& GetAllowedLooters() const; + std::string GetDebugInfo() const override; + ElunaEventProcessor* elunaEvents; protected: diff --git a/src/server/game/Entities/Object/Position.cpp b/src/server/game/Entities/Object/Position.cpp index a4920bfb4..90302ac4c 100644 --- a/src/server/game/Entities/Object/Position.cpp +++ b/src/server/game/Entities/Object/Position.cpp @@ -208,3 +208,10 @@ ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& st buf << x << y << z << o; return buf; } + +std::string WorldLocation::GetDebugInfo() const +{ + std::stringstream sstr; + sstr << "MapID: " << m_mapId << " " << Position::ToString(); + return sstr.str(); +} diff --git a/src/server/game/Entities/Object/Position.h b/src/server/game/Entities/Object/Position.h index 98f51e86b..8b87368d1 100644 --- a/src/server/game/Entities/Object/Position.h +++ b/src/server/game/Entities/Object/Position.h @@ -317,6 +317,8 @@ public: } uint32 m_mapId; + + std::string GetDebugInfo() const; }; ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYStreamer const& streamer); diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 79ea17ede..dd78a94b7 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -2439,3 +2439,13 @@ std::string Pet::GenerateActionBarData() const return oss.str(); } + +std::string Pet::GetDebugInfo() const +{ + std::stringstream sstr; + sstr << Guardian::GetDebugInfo() << "\n" + << std::boolalpha + << "PetType: " << std::to_string(getPetType()) << " " + << "PetNumber: " << m_charmInfo->GetPetNumber(); + return sstr.str(); +} diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h index 2f9b84167..12086749d 100644 --- a/src/server/game/Entities/Pet/Pet.h +++ b/src/server/game/Entities/Pet/Pet.h @@ -143,6 +143,8 @@ public: void SetLoading(bool load) { m_loading = load; } [[nodiscard]] bool HasTempSpell() const { return m_tempspell != 0; } + + std::string GetDebugInfo() const override; protected: Player* m_owner; int32 m_happinessTimer; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 949fc9707..701cafe4e 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -222,6 +222,7 @@ Player::Player(WorldSession* session): Unit(true), m_mover(this) m_bHasDelayedTeleport = false; teleportStore_options = 0; m_canTeleport = false; + m_canKnockback = false; m_trade = nullptr; @@ -1644,10 +1645,8 @@ void Player::ProcessDelayedOperations() { if (m_entryPointData.HasTaxiPath()) { - for (size_t i = 0; i < m_entryPointData.taxiPath.size() - 1; ++i) - m_taxi.AddTaxiDestination(m_entryPointData.taxiPath[i]); - m_taxi.SetTaxiSegment(m_entryPointData.taxiPath[m_entryPointData.taxiPath.size() - 1]); - + m_taxi.AddTaxiDestination(m_entryPointData.taxiPath[0]); + m_taxi.AddTaxiDestination(m_entryPointData.taxiPath[1]); m_entryPointData.ClearTaxiPath(); ContinueTaxiFlight(); } @@ -10004,26 +10003,6 @@ bool Player::ActivateTaxiPathTo(std::vector const& nodes, Creature* npc return false; } - // check node starting pos data set case if provided - if (node->x != 0.0f || node->y != 0.0f || node->z != 0.0f) - { - if (node->map_id != GetMapId() || - (node->x - GetPositionX()) * (node->x - GetPositionX()) + - (node->y - GetPositionY()) * (node->y - GetPositionY()) + - (node->z - GetPositionZ()) * (node->z - GetPositionZ()) > - (2 * INTERACTION_DISTANCE) * (2 * INTERACTION_DISTANCE) * (2 * INTERACTION_DISTANCE)) - { - GetSession()->SendActivateTaxiReply(ERR_TAXITOOFARAWAY); - return false; - } - } - // node must have pos if taxi master case (npc != nullptr) - else if (npc) - { - GetSession()->SendActivateTaxiReply(ERR_TAXIUNSPECIFIEDSERVERERROR); - return false; - } - // Prepare to flight start now // stop combat at start taxi flight if any @@ -10045,6 +10024,7 @@ bool Player::ActivateTaxiPathTo(std::vector const& nodes, Creature* npc // fill destinations path tail uint32 sourcepath = 0; uint32 totalcost = 0; + uint32 firstcost = 0; uint32 prevnode = sourcenode; uint32 lastnode = 0; @@ -10063,6 +10043,8 @@ bool Player::ActivateTaxiPathTo(std::vector const& nodes, Creature* npc } totalcost += cost; + if (i == 1) + firstcost = cost; if (prevnode == sourcenode) sourcepath = path; @@ -10091,7 +10073,16 @@ bool Player::ActivateTaxiPathTo(std::vector const& nodes, Creature* npc uint32 money = GetMoney(); if (npc) - totalcost = (uint32)ceil(totalcost * GetReputationPriceDiscount(npc)); + { + float discount = GetReputationPriceDiscount(npc); + totalcost = uint32(ceil(totalcost * discount)); + firstcost = uint32(ceil(firstcost * discount)); + m_taxi.SetFlightMasterFactionTemplateId(npc->GetFaction()); + } + else + { + m_taxi.SetFlightMasterFactionTemplateId(0); + } if (money < totalcost) { @@ -10102,8 +10093,6 @@ bool Player::ActivateTaxiPathTo(std::vector const& nodes, Creature* npc //Checks and preparations done, DO FLIGHT UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN, 1); - ModifyMoney(-(int32)totalcost); - UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, totalcost); // prevent stealth flight //RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK); @@ -10113,12 +10102,16 @@ bool Player::ActivateTaxiPathTo(std::vector const& nodes, Creature* npc { TaxiNodesEntry const* lastPathNode = sTaxiNodesStore.LookupEntry(nodes[nodes.size() - 1]); m_taxi.ClearTaxiDestinations(); + ModifyMoney(-(int32)totalcost); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, totalcost); TeleportTo(lastPathNode->map_id, lastPathNode->x, lastPathNode->y, lastPathNode->z, GetOrientation()); return false; } else { m_flightSpellActivated = spellid; + ModifyMoney(-(int32)firstcost); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, firstcost); GetSession()->SendActivateTaxiReply(ERR_TAXIOK); GetSession()->SendDoFlight(mount_display_id, sourcepath); } @@ -10214,6 +10207,39 @@ void Player::ContinueTaxiFlight() GetSession()->SendDoFlight(mountDisplayId, path, startNode); } +void Player::SendTaxiNodeStatusMultiple() +{ + for (auto itr = m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr) + { + if (!itr->IsCreature()) + { + continue; + } + + Creature* creature = ObjectAccessor::GetCreature(*this, *itr); + if (!creature || creature->IsHostileTo(this)) + { + continue; + } + + if (!creature->HasNpcFlag(UNIT_NPC_FLAG_FLIGHTMASTER)) + { + continue; + } + + uint32 nearestNode = sObjectMgr->GetNearestTaxiNode(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetMapId(), GetTeamId()); + if (!nearestNode) + { + continue; + } + + WorldPacket data(SMSG_TAXINODE_STATUS, 9); + data << *itr; + data << uint8(m_taxi.IsTaximaskNodeKnown(nearestNode) ? 1 : 0); + SendDirectMessage(&data); + } +} + void Player::ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs) { PacketCooldowns cooldowns; @@ -10984,11 +11010,8 @@ void Player::SetEntryPoint() m_entryPointData.mountSpell = 0; m_entryPointData.joinPos = WorldLocation(GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation()); - std::vector const& taxi = m_taxi.GetPath(); - for (std::vector::const_iterator itr = taxi.begin(); itr != taxi.end(); ++itr) - m_entryPointData.taxiPath.push_back(*itr); - - m_entryPointData.taxiPath.push_back(m_taxi.GetTaxiSegment()); + m_entryPointData.taxiPath[0] = m_taxi.GetTaxiSource(); + m_entryPointData.taxiPath[1] = m_taxi.GetTaxiDestination(); } else { @@ -11353,6 +11376,7 @@ void Player::SendInitialPacketsAfterAddToMap() SendEnchantmentDurations(); // must be after add to map SendItemDurations(); // must be after add to map SendQuestGiverStatusMultiple(); + SendTaxiNodeStatusMultiple(); // raid downscaling - send difficulty to player if (GetMap()->IsRaid()) @@ -12007,23 +12031,21 @@ bool Player::GetBGAccessByLevel(BattlegroundTypeId bgTypeId) const float Player::GetReputationPriceDiscount(Creature const* creature) const { - FactionTemplateEntry const* vendorFaction = creature->GetFactionTemplateEntry(); - if (!vendorFaction) + return GetReputationPriceDiscount(creature->GetFactionTemplateEntry()); +} + +float Player::GetReputationPriceDiscount(FactionTemplateEntry const* factionTemplate) const +{ + if (!factionTemplate || !factionTemplate->faction) { return 1.0f; } - return GetReputationPriceDiscount(vendorFaction); -} - -float Player::GetReputationPriceDiscount(FactionTemplateEntry const* vendorFaction) const -{ - if (!vendorFaction->faction) - return 1.0f; - - ReputationRank rank = GetReputationRank(vendorFaction->faction); + ReputationRank rank = GetReputationRank(factionTemplate->faction); if (rank <= REP_NEUTRAL) + { return 1.0f; + } return 1.0f - 0.05f * (rank - REP_NEUTRAL); } @@ -13875,20 +13897,27 @@ void Player::ResummonPetTemporaryUnSummonedIfAny() bool Player::CanResummonPet(uint32 spellid) { - if (getClass() == CLASS_DEATH_KNIGHT) + switch (getClass()) { - if (CanSeeDKPet()) + case CLASS_DEATH_KNIGHT: + if (CanSeeDKPet()) + return true; + else if (spellid == 52150) //Raise Dead + return false; + break; + case CLASS_MAGE: + if (HasSpell(31687) && HasAura(70937)) //Has [Summon Water Elemental] spell and [Glyph of Eternal Water]. + return true; + break; + case CLASS_HUNTER: + case CLASS_WARLOCK: return true; - else if (spellid == 52150) - return false; + break; + default: + break; } - else if (getClass() == CLASS_HUNTER || getClass() == CLASS_MAGE || getClass() == CLASS_WARLOCK) - return true; - if (!HasSpell(spellid)) - return false; - - return true; + return HasSpell(spellid); } bool Player::CanSeeSpellClickOn(Creature const* c) const @@ -14228,16 +14257,9 @@ void Player::_SaveEntryPoint(CharacterDatabaseTransaction trans) stmt->SetData (3, m_entryPointData.joinPos.GetPositionZ()); stmt->SetData (4, m_entryPointData.joinPos.GetOrientation()); stmt->SetData(5, m_entryPointData.joinPos.GetMapId()); - - std::ostringstream ss(""); - if (m_entryPointData.HasTaxiPath()) - { - for (size_t i = 0; i < m_entryPointData.taxiPath.size(); ++i) - ss << m_entryPointData.taxiPath[i] << ' '; // xinef: segment is stored as last point - } - - stmt->SetData(6, ss.str()); - stmt->SetData(7, m_entryPointData.mountSpell); + stmt->SetData(6, m_entryPointData.taxiPath[0]); + stmt->SetData(7, m_entryPointData.taxiPath[1]); + stmt->SetData(8, m_entryPointData.mountSpell); trans->Append(stmt); } @@ -15958,3 +15980,10 @@ void Player::ResetSpeakTimers() m_speakTime = 0; m_speakCount = 0; } + +std::string Player::GetDebugInfo() const +{ + std::stringstream sstr; + sstr << Unit::GetDebugInfo(); + return sstr.str(); +} \ No newline at end of file diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 89124e9c7..a3974576d 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1035,11 +1035,11 @@ struct EntryPointData } uint32 mountSpell{0}; - std::vector taxiPath; + std::array taxiPath; WorldLocation joinPos; - void ClearTaxiPath() { taxiPath.clear(); } - [[nodiscard]] bool HasTaxiPath() const { return !taxiPath.empty(); } + void ClearTaxiPath() { taxiPath.fill(0); } + [[nodiscard]] bool HasTaxiPath() const { return taxiPath[0] && taxiPath[1]; } }; class Player : public Unit, public GridObject @@ -1126,6 +1126,7 @@ public: bool ActivateTaxiPathTo(uint32 taxi_path_id, uint32 spellid = 1); void CleanupAfterTaxiFlight(); void ContinueTaxiFlight(); + void SendTaxiNodeStatusMultiple(); // mount_id can be used in scripting calls [[nodiscard]] bool IsDeveloper() const { return HasPlayerFlag(PLAYER_FLAGS_DEVELOPER); } @@ -1336,8 +1337,8 @@ public: bool BuyItemFromVendorSlot(ObjectGuid vendorguid, uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot); bool _StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot, int32 price, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore); - float GetReputationPriceDiscount(Creature const* creature) const; - float GetReputationPriceDiscount(FactionTemplateEntry const* vendorFaction) const; + [[nodiscard]] float GetReputationPriceDiscount(Creature const* creature) const; + [[nodiscard]] float GetReputationPriceDiscount(FactionTemplateEntry const* factionTemplate) const; [[nodiscard]] Player* GetTrader() const { return m_trade ? m_trade->GetTrader() : nullptr; } [[nodiscard]] TradeData* GetTradeData() const { return m_trade; } @@ -2429,6 +2430,8 @@ public: bool CanTeleport() { return m_canTeleport; } void SetCanTeleport(bool value) { m_canTeleport = value; } + bool CanKnockback() { return m_canKnockback; } + void SetCanKnockback(bool value) { m_canKnockback = value; } bool isAllowedToLoot(Creature const* creature); @@ -2557,6 +2560,8 @@ public: void ResetSpeakTimers(); + std::string GetDebugInfo() const override; + protected: // Gamemaster whisper whitelist WhisperListContainer WhisperList; @@ -2884,6 +2889,7 @@ private: bool m_bMustDelayTeleport; bool m_bHasDelayedTeleport; bool m_canTeleport; + bool m_canKnockback; std::unique_ptr m_petStable; diff --git a/src/server/game/Entities/Player/PlayerStorage.cpp b/src/server/game/Entities/Player/PlayerStorage.cpp index 7e275bd1d..1b615fe65 100644 --- a/src/server/game/Entities/Player/PlayerStorage.cpp +++ b/src/server/game/Entities/Player/PlayerStorage.cpp @@ -4894,21 +4894,9 @@ void Player::_LoadEntryPointData(PreparedQueryResult result) fields[2].Get(), // Z fields[3].Get()); // Orientation - std::string_view taxi = fields[5].Get(); - if (!taxi.empty()) - { - for (auto const& itr : Acore::Tokenize(taxi, ' ', false)) - { - uint32 node = Acore::StringTo(itr).value_or(0); - m_entryPointData.taxiPath.emplace_back(node); - } - - // Check integrity - if (m_entryPointData.taxiPath.size() < 3) - m_entryPointData.ClearTaxiPath(); - } - - m_entryPointData.mountSpell = fields[6].Get(); + m_entryPointData.taxiPath[0] = fields[5].Get(); + m_entryPointData.taxiPath[1] = fields[6].Get(); + m_entryPointData.mountSpell = fields[7].Get(); } bool Player::LoadPositionFromDB(uint32& mapid, float& x, float& y, float& z, float& o, bool& in_flight, ObjectGuid::LowType guid) @@ -5190,10 +5178,8 @@ bool Player::LoadFromDB(ObjectGuid playerGuid, CharacterDatabaseQueryHolder cons // xinef: restore taxi flight from entry point data if (m_entryPointData.HasTaxiPath()) { - for (size_t i = 0; i < m_entryPointData.taxiPath.size() - 1; ++i) - m_taxi.AddTaxiDestination(m_entryPointData.taxiPath[i]); - m_taxi.SetTaxiSegment(m_entryPointData.taxiPath[m_entryPointData.taxiPath.size() - 1]); - + m_taxi.AddTaxiDestination(m_entryPointData.taxiPath[0]); + m_taxi.AddTaxiDestination(m_entryPointData.taxiPath[1]); m_entryPointData.ClearTaxiPath(); } } diff --git a/src/server/game/Entities/Player/PlayerTaxi.cpp b/src/server/game/Entities/Player/PlayerTaxi.cpp index a4bff7aa6..680af2e28 100644 --- a/src/server/game/Entities/Player/PlayerTaxi.cpp +++ b/src/server/game/Entities/Player/PlayerTaxi.cpp @@ -20,11 +20,6 @@ #include "Tokenize.h" #include "StringConvert.h" -PlayerTaxi::PlayerTaxi() : _taxiSegment(0) -{ - memset(m_taximask, 0, sizeof(m_taximask)); -} - void PlayerTaxi::InitTaxiNodesForLevel(uint32 race, uint32 chrClass, uint8 level) { // class specific initial known nodes @@ -136,9 +131,25 @@ bool PlayerTaxi::LoadTaxiDestinationsFromString(const std::string& values, TeamI { ClearTaxiDestinations(); - for (auto const& itr : Acore::Tokenize(values, ' ', false)) + std::vector tokens = Acore::Tokenize(values, ' ', false); + auto itr = tokens.begin(); + if (itr != tokens.end()) { - if (Optional node = Acore::StringTo(itr)) + if (Optional faction = Acore::StringTo(*itr)) + { + m_flightMasterFactionId = *faction; + } + else + { + return false; + } + } + else + return false; + + while ((++itr) != tokens.end()) + { + if (Optional node = Acore::StringTo(*itr)) { AddTaxiDestination(*node); } @@ -148,26 +159,33 @@ bool PlayerTaxi::LoadTaxiDestinationsFromString(const std::string& values, TeamI } } + if (m_TaxiDestinations.empty()) + { + return true; + } + // Check integrity - if (m_TaxiDestinations.size() < 3) + if (m_TaxiDestinations.size() < 2) + { return false; + } - // xinef: current segment is saved as last destination in db - _taxiSegment = m_TaxiDestinations[m_TaxiDestinations.size() - 1]; - m_TaxiDestinations.pop_back(); - - for (size_t i = 0; i < m_TaxiDestinations.size() - 1; ++i) + for (size_t i = 1; i < m_TaxiDestinations.size(); ++i) { uint32 cost; uint32 path; - sObjectMgr->GetTaxiPath(m_TaxiDestinations[i], m_TaxiDestinations[i + 1], path, cost); + sObjectMgr->GetTaxiPath(m_TaxiDestinations[i - 1], m_TaxiDestinations[i], path, cost); if (!path) + { return false; + } } // can't load taxi path without mount set (quest taxi path?) if (!sObjectMgr->GetTaxiMountDisplayId(GetTaxiSource(), teamId, true)) + { return false; + } return true; } @@ -175,26 +193,34 @@ bool PlayerTaxi::LoadTaxiDestinationsFromString(const std::string& values, TeamI std::string PlayerTaxi::SaveTaxiDestinationsToString() { if (m_TaxiDestinations.empty()) + { return ""; + } + + ASSERT(m_TaxiDestinations.size() >= 2); std::ostringstream ss; + ss << m_flightMasterFactionId << ' '; for (size_t i = 0; i < m_TaxiDestinations.size(); ++i) + { ss << m_TaxiDestinations[i] << ' '; + } - ss << _taxiSegment << ' '; return ss.str(); } uint32 PlayerTaxi::GetCurrentTaxiPath() const { - if (m_TaxiDestinations.size() < 2 || m_TaxiDestinations.size() <= _taxiSegment + 1) + if (m_TaxiDestinations.size() < 2) + { return 0; + } uint32 path; uint32 cost; - sObjectMgr->GetTaxiPath(m_TaxiDestinations[_taxiSegment], m_TaxiDestinations[_taxiSegment + 1], path, cost); + sObjectMgr->GetTaxiPath(m_TaxiDestinations[0], m_TaxiDestinations[1], path, cost); return path; } @@ -205,3 +231,8 @@ std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi) ss << taxi.m_taximask[i] << ' '; return ss; } + +FactionTemplateEntry const* PlayerTaxi::GetFlightMasterFactionTemplate() const +{ + return sFactionTemplateStore.LookupEntry(m_flightMasterFactionId); +} diff --git a/src/server/game/Entities/Player/PlayerTaxi.h b/src/server/game/Entities/Player/PlayerTaxi.h index 774b8499b..3923a8c54 100644 --- a/src/server/game/Entities/Player/PlayerTaxi.h +++ b/src/server/game/Entities/Player/PlayerTaxi.h @@ -26,7 +26,7 @@ class ByteBuffer; class AC_GAME_API PlayerTaxi { public: - PlayerTaxi(); + PlayerTaxi() : m_flightMasterFactionId(0) { m_taximask.fill(0); } ~PlayerTaxi() = default; // Nodes @@ -59,29 +59,28 @@ public: bool LoadTaxiDestinationsFromString(std::string const& values, TeamId teamId); std::string SaveTaxiDestinationsToString(); - void ClearTaxiDestinations() { m_TaxiDestinations.clear(); _taxiSegment = 0; } + void ClearTaxiDestinations() { m_TaxiDestinations.clear(); } void AddTaxiDestination(uint32 dest) { m_TaxiDestinations.push_back(dest); } - [[nodiscard]] uint32 GetTaxiSource() const { return m_TaxiDestinations.size() <= _taxiSegment + 1 ? 0 : m_TaxiDestinations[_taxiSegment]; } - [[nodiscard]] uint32 GetTaxiDestination() const { return m_TaxiDestinations.size() <= _taxiSegment + 1 ? 0 : m_TaxiDestinations[_taxiSegment + 1]; } + [[nodiscard]] uint32 GetTaxiSource() const { return m_TaxiDestinations.empty() ? 0 : m_TaxiDestinations.front(); } + [[nodiscard]] uint32 GetTaxiDestination() const { return m_TaxiDestinations.size() < 2 ? 0 : m_TaxiDestinations[1]; } [[nodiscard]] uint32 GetCurrentTaxiPath() const; uint32 NextTaxiDestination() { - ++_taxiSegment; + m_TaxiDestinations.pop_front(); return GetTaxiDestination(); } - // xinef: - void SetTaxiSegment(uint32 segment) { _taxiSegment = segment; } - [[nodiscard]] uint32 GetTaxiSegment() const { return _taxiSegment; } - - [[nodiscard]] std::vector const& GetPath() const { return m_TaxiDestinations; } + [[nodiscard]] std::deque const& GetPath() const { return m_TaxiDestinations; } [[nodiscard]] bool empty() const { return m_TaxiDestinations.empty(); } + [[nodiscard]] FactionTemplateEntry const* GetFlightMasterFactionTemplate() const; + void SetFlightMasterFactionTemplateId(uint32 factionTemplateId) { m_flightMasterFactionId = factionTemplateId; } friend std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi); + private: TaxiMask m_taximask; - std::vector m_TaxiDestinations; - uint32 _taxiSegment; + std::deque m_TaxiDestinations; + uint32 m_flightMasterFactionId; }; #endif diff --git a/src/server/game/Entities/Totem/Totem.cpp b/src/server/game/Entities/Totem/Totem.cpp index 73486f979..172cf5fd6 100644 --- a/src/server/game/Entities/Totem/Totem.cpp +++ b/src/server/game/Entities/Totem/Totem.cpp @@ -116,38 +116,40 @@ void Totem::UnSummon(uint32 msTime) CombatStop(); RemoveAurasDueToSpell(GetSpell(), GetGUID()); - Unit* owner = GetOwner(); - // clear owner's totem slot - for (uint8 i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i) + if (Unit* owner = GetOwner()) { - if (owner->m_SummonSlot[i] == GetGUID()) + // clear owner's totem slot + for (uint8 i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i) { - owner->m_SummonSlot[i].Clear(); - break; - } - } - - owner->RemoveAurasDueToSpell(GetSpell(), GetGUID()); - - // Remove Sentry Totem Aura - if (GetEntry() == SENTRY_TOTEM_ENTRY) - owner->RemoveAurasDueToSpell(SENTRY_TOTEM_SPELLID); - - //remove aura all party members too - if (Player* player = owner->ToPlayer()) - { - player->SendAutoRepeatCancel(this); - - if (SpellInfo const* spell = sSpellMgr->GetSpellInfo(GetUInt32Value(UNIT_CREATED_BY_SPELL))) - player->SendCooldownEvent(spell, 0, nullptr, false); - - if (Group* group = player->GetGroup()) - { - for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) + if (owner->m_SummonSlot[i] == GetGUID()) { - Player* target = itr->GetSource(); - if (target && target->IsInMap(player) && group->SameSubGroup(player, target)) - target->RemoveAurasDueToSpell(GetSpell(), GetGUID()); + owner->m_SummonSlot[i].Clear(); + break; + } + } + + owner->RemoveAurasDueToSpell(GetSpell(), GetGUID()); + + // Remove Sentry Totem Aura + if (GetEntry() == SENTRY_TOTEM_ENTRY) + owner->RemoveAurasDueToSpell(SENTRY_TOTEM_SPELLID); + + //remove aura all party members too + if (Player* player = owner->ToPlayer()) + { + player->SendAutoRepeatCancel(this); + + if (SpellInfo const* spell = sSpellMgr->GetSpellInfo(GetUInt32Value(UNIT_CREATED_BY_SPELL))) + player->SendCooldownEvent(spell, 0, nullptr, false); + + if (Group* group = player->GetGroup()) + { + for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) + { + Player* target = itr->GetSource(); + if (target && target->IsInMap(player) && group->SameSubGroup(player, target)) + target->RemoveAurasDueToSpell(GetSpell(), GetGUID()); + } } } } diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp index 841dd1b69..89e1e329f 100644 --- a/src/server/game/Entities/Transport/Transport.cpp +++ b/src/server/game/Entities/Transport/Transport.cpp @@ -1004,3 +1004,10 @@ void StaticTransport::RemovePassenger(WorldObject* passenger, bool withAll) } } } + +std::string MotionTransport::GetDebugInfo() const +{ + std::stringstream sstr; + sstr << GameObject::GetDebugInfo(); + return sstr.str(); +} diff --git a/src/server/game/Entities/Transport/Transport.h b/src/server/game/Entities/Transport/Transport.h index 98aae380f..75fc9f9ee 100644 --- a/src/server/game/Entities/Transport/Transport.h +++ b/src/server/game/Entities/Transport/Transport.h @@ -78,6 +78,7 @@ public: uint32 GetPeriod() const { return GetUInt32Value(GAMEOBJECT_LEVEL); } void SetPeriod(uint32 period) { SetUInt32Value(GAMEOBJECT_LEVEL, period); } + std::string GetDebugInfo() const override; private: void MoveToNextWaypoint(); float CalculateSegmentPos(float perc); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 488dda03c..11be39428 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -465,6 +465,7 @@ void Unit::Update(uint32 p_time) // xinef: if attack time > 0, reduce by diff // if on next update, attack time < 0 assume player didnt attack - set to 0 bool suspendAttackTimer = false; + bool suspendRangedAttackTimer = false; if (IsPlayer() && HasUnitState(UNIT_STATE_CASTING)) { for (Spell* spell : m_currentSpells) @@ -473,6 +474,11 @@ void Unit::Update(uint32 p_time) { if (spell->GetSpellInfo()->HasAttribute(SPELL_ATTR2_DO_NOT_RESET_COMBAT_TIMERS)) { + if (spell->IsChannelActive()) + { + suspendRangedAttackTimer = true; + } + suspendAttackTimer = true; break; } @@ -493,9 +499,12 @@ void Unit::Update(uint32 p_time) } } - if (int32 ranged_attack = getAttackTimer(RANGED_ATTACK)) + if (!suspendRangedAttackTimer) { - setAttackTimer(RANGED_ATTACK, ranged_attack > 0 ? ranged_attack - (int32) p_time : 0); + if (int32 ranged_attack = getAttackTimer(RANGED_ATTACK)) + { + setAttackTimer(RANGED_ATTACK, ranged_attack > 0 ? ranged_attack - (int32)p_time : 0); + } } // update abilities available only for fraction of time @@ -1109,7 +1118,7 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage { Player* he = duel_wasMounted ? victim->GetCharmer()->ToPlayer() : victim->ToPlayer(); - ASSERT(he && he->duel); + ASSERT_NODEBUGINFO(he && he->duel); if (duel_wasMounted) // In this case victim==mount victim->SetHealth(1); @@ -2415,7 +2424,7 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType /*= BASE_A DealMeleeDamage(&damageInfo, true); DamageInfo dmgInfo(damageInfo); - ProcDamageAndSpell(damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, damageInfo.procEx, damageInfo.damage, + Unit::ProcDamageAndSpell(damageInfo.attacker, damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, damageInfo.procEx, damageInfo.damage, damageInfo.attackType, nullptr, nullptr, -1, nullptr, &dmgInfo); if (GetTypeId() == TYPEID_PLAYER) @@ -5961,15 +5970,15 @@ void Unit::SendSpellNonMeleeDamageLog(Unit* target, SpellInfo const* spellInfo, SendSpellNonMeleeDamageLog(&log); } -void Unit::ProcDamageAndSpell(Unit* victim, uint32 procAttacker, uint32 procVictim, uint32 procExtra, uint32 amount, WeaponAttackType attType, SpellInfo const* procSpellInfo, SpellInfo const* procAura, int8 procAuraEffectIndex, Spell const* procSpell, DamageInfo* damageInfo, HealInfo* healInfo, uint32 procPhase) +void Unit::ProcDamageAndSpell(Unit* actor, Unit* victim, uint32 procAttacker, uint32 procVictim, uint32 procExtra, uint32 amount, WeaponAttackType attType, SpellInfo const* procSpellInfo, SpellInfo const* procAura, int8 procAuraEffectIndex, Spell const* procSpell, DamageInfo* damageInfo, HealInfo* healInfo, uint32 procPhase) { // Not much to do if no flags are set. - if (procAttacker) - ProcDamageAndSpellFor(false, victim, procAttacker, procExtra, attType, procSpellInfo, amount, procAura, procAuraEffectIndex, procSpell, damageInfo, healInfo, procPhase); + if (procAttacker && actor) + actor->ProcDamageAndSpellFor(false, victim, procAttacker, procExtra, attType, procSpellInfo, amount, procAura, procAuraEffectIndex, procSpell, damageInfo, healInfo, procPhase); // Now go on with a victim's events'n'auras // Not much to do if no flags are set or there is no victim if (victim && victim->IsAlive() && procVictim) - victim->ProcDamageAndSpellFor(true, this, procVictim, procExtra, attType, procSpellInfo, amount, procAura, procAuraEffectIndex, procSpell, damageInfo, healInfo, procPhase); + victim->ProcDamageAndSpellFor(true, actor, procVictim, procExtra, attType, procSpellInfo, amount, procAura, procAuraEffectIndex, procSpell, damageInfo, healInfo, procPhase); } void Unit::SendPeriodicAuraLog(SpellPeriodicAuraLogInfo* pInfo) @@ -6151,7 +6160,7 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit* target, uint8 /*SwingType } //victim may be nullptr -bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown) +bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, Spell const* spellProc /*= nullptr*/) { SpellInfo const* dummySpell = triggeredByAura->GetSpellInfo(); uint32 effIndex = triggeredByAura->GetEffIndex(); @@ -7077,7 +7086,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere case 28719: { // mana back - basepoints0 = int32(CalculatePct(procSpell->ManaCost, 30)); + basepoints0 = int32(CalculatePct(spellProc->GetPowerCost(), 30)); target = this; triggered_spell_id = 28742; break; @@ -16009,7 +16018,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u case SPELL_AURA_DUMMY: { LOG_DEBUG("spells.aura", "ProcDamageAndSpell: casting spell id {} (triggered by {} dummy aura of spell {})", spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId()); - if (HandleDummyAuraProc(target, damage, triggeredByAura, procSpellInfo, procFlag, procExtra, cooldown)) + if (HandleDummyAuraProc(target, damage, triggeredByAura, procSpellInfo, procFlag, procExtra, cooldown, procSpell)) takeCharges = true; break; } @@ -17406,15 +17415,15 @@ void Unit::Kill(Unit* killer, Unit* victim, bool durabilityLoss, WeaponAttackTyp if (killer && (killer->IsPet() || killer->IsTotem())) if (Unit* owner = killer->GetOwner()) { - owner->ProcDamageAndSpell(victim, PROC_FLAG_KILL, PROC_FLAG_NONE, PROC_EX_NONE, 0, attackType, spellProto, nullptr, -1, spell); + Unit::ProcDamageAndSpell(owner, victim, PROC_FLAG_KILL, PROC_FLAG_NONE, PROC_EX_NONE, 0, attackType, spellProto, nullptr, -1, spell); sScriptMgr->OnCreatureKilledByPet( killer->GetCharmerOrOwnerPlayerOrPlayerItself(), victim->ToCreature()); } if (killer != victim && !victim->IsCritter()) - killer->ProcDamageAndSpell(victim, killer ? PROC_FLAG_KILL : 0, PROC_FLAG_KILLED, PROC_EX_NONE, 0, attackType, spellProto, nullptr, -1, spell); + Unit::ProcDamageAndSpell(killer, victim, killer ? PROC_FLAG_KILL : 0, PROC_FLAG_KILLED, PROC_EX_NONE, 0, attackType, spellProto, nullptr, -1, spell); // Proc auras on death - must be before aura/combat remove - victim->ProcDamageAndSpell(nullptr, PROC_FLAG_DEATH, PROC_FLAG_NONE, PROC_EX_NONE, 0, attackType, spellProto, nullptr, -1, spell); + Unit::ProcDamageAndSpell(victim, nullptr, PROC_FLAG_DEATH, PROC_FLAG_NONE, PROC_EX_NONE, 0, attackType, spellProto, nullptr, -1, spell); // update get killing blow achievements, must be done before setDeathState to be able to require auras on target // and before Spirit of Redemption as it also removes auras @@ -18750,6 +18759,7 @@ void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ) player->SetCanFly(true, true); sScriptMgr->AnticheatSetSkipOnePacketForASH(player, true); + player->SetCanKnockback(true); } } @@ -20843,3 +20853,14 @@ bool Unit::IsInDisallowedMountForm() const return false; } + +std::string Unit::GetDebugInfo() const +{ + std::stringstream sstr; + sstr << WorldObject::GetDebugInfo() << "\n" + << std::boolalpha + << "AliveState: " << IsAlive() + << " UnitMovementFlags: " << GetUnitMovementFlags() << " ExtraUnitMovementFlags: " << GetExtraUnitMovementFlags() + << " Class: " << std::to_string(getClass()); + return sstr.str(); +} diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 3a5edde39..ce81bb6e3 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1525,7 +1525,7 @@ public: static void Kill(Unit* killer, Unit* victim, bool durabilityLoss = true, WeaponAttackType attackType = BASE_ATTACK, SpellInfo const* spellProto = nullptr, Spell const* spell = nullptr); static int32 DealHeal(Unit* healer, Unit* victim, uint32 addhealth); - void ProcDamageAndSpell(Unit* victim, uint32 procAttacker, uint32 procVictim, uint32 procEx, uint32 amount, WeaponAttackType attType = BASE_ATTACK, SpellInfo const* procSpellInfo = nullptr, SpellInfo const* procAura = nullptr, int8 procAuraEffectIndex = -1, Spell const* procSpell = nullptr, DamageInfo* damageInfo = nullptr, HealInfo* healInfo = nullptr, uint32 procPhase = 2 /*PROC_SPELL_PHASE_HIT*/); + static void ProcDamageAndSpell(Unit* actor, Unit* victim, uint32 procAttacker, uint32 procVictim, uint32 procEx, uint32 amount, WeaponAttackType attType = BASE_ATTACK, SpellInfo const* procSpellInfo = nullptr, SpellInfo const* procAura = nullptr, int8 procAuraEffectIndex = -1, Spell const* procSpell = nullptr, DamageInfo* damageInfo = nullptr, HealInfo* healInfo = nullptr, uint32 procPhase = 2 /*PROC_SPELL_PHASE_HIT*/); void ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, SpellInfo const* procSpellInfo, uint32 damage, SpellInfo const* procAura = nullptr, int8 procAuraEffectIndex = -1, Spell const* procSpell = nullptr, DamageInfo* damageInfo = nullptr, HealInfo* healInfo = nullptr, uint32 procPhase = 2 /*PROC_SPELL_PHASE_HIT*/); void GetProcAurasTriggeredOnEvent(std::list& aurasTriggeringProc, std::list* procAuras, ProcEventInfo eventInfo); @@ -2431,6 +2431,8 @@ public: virtual bool SetCannotReachTarget(bool cannotReach, bool isChase = true); [[nodiscard]] bool CanNotReachTarget() const { return m_cannotReachTarget; } + std::string GetDebugInfo() const override; + protected: explicit Unit (bool isWorldObject); @@ -2515,7 +2517,7 @@ protected: private: bool IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent, ProcEventInfo const& eventInfo); - bool HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); + bool HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, Spell const* spellProc = nullptr); bool HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, bool* handled); bool HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, uint32 procPhase, ProcEventInfo& eventInfo); bool HandleOverrideClassScriptAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 cooldown); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index c82efc403..025ec9a0b 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -9875,8 +9875,8 @@ void ObjectMgr::SendServerMail(Player* player, uint32 id, uint32 reqLevel, uint3 MailSender sender(MAIL_NORMAL, player->GetGUID().GetCounter(), MAIL_STATIONERY_GM); MailDraft draft(subject, body); - draft.AddMoney(player->GetTeamId() == TEAM_ALLIANCE ? rewardMoneyH : rewardMoneyA); - if (Item* mailItem = Item::CreateItem(player->GetTeamId() == TEAM_ALLIANCE ? rewardItemH : rewardItemA, player->GetTeamId() == TEAM_ALLIANCE ? rewardItemCountH : rewardItemCountA)) + draft.AddMoney(player->GetTeamId() == TEAM_ALLIANCE ? rewardMoneyA : rewardMoneyH); + if (Item* mailItem = Item::CreateItem(player->GetTeamId() == TEAM_ALLIANCE ? rewardItemA : rewardItemH, player->GetTeamId() == TEAM_ALLIANCE ? rewardItemCountA : rewardItemCountH)) { mailItem->SaveToDB(trans); draft.AddItem(mailItem); diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index ab72656b9..4623f8ca7 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -1449,7 +1449,8 @@ void Group::CountTheRoll(Rolls::iterator rollI, Map* allowedMap) roll->getLoot()->unlootedCount--; AllowedLooterSet looters = item->GetAllowedLooters(); Item* _item = player->StoreNewItem(dest, roll->itemid, true, item->randomPropertyId, looters); - sScriptMgr->OnGroupRollRewardItem(player, _item, _item->GetCount(), NEED, roll); + if (_item) + sScriptMgr->OnGroupRollRewardItem(player, _item, _item->GetCount(), NEED, roll); player->UpdateLootAchievements(item, roll->getLoot()); } else @@ -1518,7 +1519,8 @@ void Group::CountTheRoll(Rolls::iterator rollI, Map* allowedMap) roll->getLoot()->unlootedCount--; AllowedLooterSet looters = item->GetAllowedLooters(); Item* _item = player->StoreNewItem(dest, roll->itemid, true, item->randomPropertyId, looters); - sScriptMgr->OnGroupRollRewardItem(player, _item, _item->GetCount(), GREED, roll); + if (_item) + sScriptMgr->OnGroupRollRewardItem(player, _item, _item->GetCount(), GREED, roll); player->UpdateLootAchievements(item, roll->getLoot()); } else diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp index c03f619aa..ece0e94df 100644 --- a/src/server/game/Handlers/AuctionHouseHandler.cpp +++ b/src/server/game/Handlers/AuctionHouseHandler.cpp @@ -506,6 +506,7 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData) sAuctionMgr->SendAuctionSalePendingMail(auction, trans); sAuctionMgr->SendAuctionSuccessfulMail(auction, trans); sAuctionMgr->SendAuctionWonMail(auction, trans); + sScriptMgr->OnAuctionSuccessful(auctionHouse, auction); SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, ERR_AUCTION_OK); diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp index e89c2d71c..7e76aa6e4 100644 --- a/src/server/game/Handlers/BattleGroundHandler.cpp +++ b/src/server/game/Handlers/BattleGroundHandler.cpp @@ -533,13 +533,20 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket& recvData) } else // leave queue { - bgQueue.RemovePlayer(_player->GetGUID(), true); - _player->RemoveBattlegroundQueueId(bgQueueTypeId); + for (auto const& playerGuid : ginfo.Players) + { + auto player = ObjectAccessor::FindConnectedPlayer(playerGuid); + if (!player) + continue; - sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0, TEAM_NEUTRAL); - SendPacket(&data); + bgQueue.RemovePlayer(playerGuid, true); + player->RemoveBattlegroundQueueId(bgQueueTypeId); - LOG_DEBUG("bg.battleground", "Battleground: player {} {} left queue for bgtype {}, queue type {}.", _player->GetName(), _player->GetGUID().ToString(), bg->GetBgTypeID(), bgQueueTypeId); + sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0, TEAM_NEUTRAL); + player->SendDirectMessage(&data); + + LOG_DEBUG("bg.battleground", "Battleground: player {} {} left queue for bgtype {}, queue type {}.", player->GetName(), playerGuid.ToString(), bg->GetBgTypeID(), bgQueueTypeId); + } // player left queue, we should update it - do not update Arena Queue if (!ginfo.ArenaType) diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index d7eadb063..f0c6c053c 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -2189,7 +2189,7 @@ void WorldSession::HandleCharFactionOrRaceChangeCallback(std::shared_ptrSetData(0, uint16(AT_LOGIN_CHECK_ACHIEVS)); + stmt->SetData(1, lowGuid); + trans->Append(stmt); + CharacterDatabase.CommitTransaction(trans); LOG_DEBUG("entities.player", "{} (IP: {}) changed race from {} to {}", GetPlayerInfo(), GetRemoteAddress(), oldRace, factionChangeInfo->Race); diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 0c602e8bb..8c9523f00 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -188,6 +188,22 @@ void WorldSession::HandleMoveWorldportAck() GetPlayer()->SendInitialPacketsAfterAddToMap(); + // flight fast teleport case + if (GetPlayer()->IsInFlight()) + { + if (!GetPlayer()->InBattleground()) + { + // short preparations to continue flight + MovementGenerator* movementGenerator = GetPlayer()->GetMotionMaster()->top(); + movementGenerator->Initialize(GetPlayer()); + return; + } + + // battleground state prepare, stop flight + GetPlayer()->GetMotionMaster()->MovementExpired(); + GetPlayer()->CleanupAfterTaxiFlight(); + } + // resurrect character at enter into instance where his corpse exist after add to map Corpse* corpse = GetPlayer()->GetMap()->GetCorpseByPlayer(GetPlayer()->GetGUID()); if (corpse && corpse->GetType() != CORPSE_BONES) diff --git a/src/server/game/Handlers/TaxiHandler.cpp b/src/server/game/Handlers/TaxiHandler.cpp index 466285a24..e3678168a 100644 --- a/src/server/game/Handlers/TaxiHandler.cpp +++ b/src/server/game/Handlers/TaxiHandler.cpp @@ -15,6 +15,7 @@ * with this program. If not, see . */ +#include "GameTime.h" #include "ObjectMgr.h" #include "Opcodes.h" #include "Player.h" @@ -36,25 +37,24 @@ void WorldSession::HandleTaxiNodeStatusQueryOpcode(WorldPacket& recvData) void WorldSession::SendTaxiStatus(ObjectGuid guid) { - // cheating checks - Creature* unit = GetPlayer()->GetMap()->GetCreature(guid); - if (!unit) + Player* const player = GetPlayer(); + Creature* unit = ObjectAccessor::GetCreature(*player, guid); + if (!unit || unit->IsHostileTo(player) || !unit->HasNpcFlag(UNIT_NPC_FLAG_FLIGHTMASTER)) { LOG_DEBUG("network", "WorldSession::SendTaxiStatus - Unit ({}) not found.", guid.ToString()); return; } - uint32 curloc = sObjectMgr->GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), GetPlayer()->GetTeamId()); - - // not found nearest - if (curloc == 0) + // find taxi node + uint32 nearest = sObjectMgr->GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), player->GetTeamId()); + if (!nearest) + { return; - - LOG_DEBUG("network", "WORLD: current location {} ", curloc); + } WorldPacket data(SMSG_TAXINODE_STATUS, 9); data << guid; - data << uint8(GetPlayer()->m_taxi.IsTaximaskNodeKnown(curloc) ? 1 : 0); + data << uint8(player->m_taxi.IsTaximaskNodeKnown(nearest) ? 1 : 0); SendPacket(&data); LOG_DEBUG("network", "WORLD: Sent SMSG_TAXINODE_STATUS"); } @@ -166,7 +166,7 @@ void WorldSession::SendDiscoverNewTaxiNode(uint32 nodeid) } } -void WorldSession::HandleActivateTaxiExpressOpcode (WorldPacket& recvData) +void WorldSession::HandleActivateTaxiExpressOpcode(WorldPacket& recvData) { LOG_DEBUG("network", "WORLD: Received CMSG_ACTIVATETAXIEXPRESS"); @@ -179,6 +179,7 @@ void WorldSession::HandleActivateTaxiExpressOpcode (WorldPacket& recvData) if (!npc) { LOG_DEBUG("network", "WORLD: HandleActivateTaxiExpressOpcode - Unit ({}) not found or you can't interact with it.", guid.ToString()); + SendActivateTaxiReply(ERR_TAXITOOFARAWAY); return; } std::vector nodes; @@ -218,6 +219,46 @@ void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recvData) ReadMovementInfo(recvData, &movementInfo); recvData.read_skip(); // spline id + + // in taxi flight packet received in 2 case: + // 1) end taxi path in far (multi-node) flight + // 2) switch from one map to other in case multim-map taxi path + // we need process only (1) + + uint32 curDest = GetPlayer()->m_taxi.GetTaxiDestination(); + if (curDest) + { + TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest); + + // far teleport case + if (curDestNode && curDestNode->map_id != GetPlayer()->GetMapId() && GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) + { + if (FlightPathMovementGenerator* flight = dynamic_cast(GetPlayer()->GetMotionMaster()->top())) + { + // short preparations to continue flight + flight->SetCurrentNodeAfterTeleport(); + TaxiPathNodeEntry const* node = flight->GetPath()[flight->GetCurrentNode()]; + flight->SkipCurrentNode(); + + GetPlayer()->TeleportTo(curDestNode->map_id, node->x, node->y, node->z, GetPlayer()->GetOrientation(), TELE_TO_NOT_LEAVE_TAXI); + } + } + + return; + } + + // at this point only 1 node is expected (final destination) + if (GetPlayer()->m_taxi.GetPath().size() != 1) + { + return; + } + + GetPlayer()->CleanupAfterTaxiFlight(); + GetPlayer()->SetFallInformation(GameTime::GetGameTime().count(), GetPlayer()->GetPositionZ()); + if (GetPlayer()->pvpInfo.IsHostile) + { + GetPlayer()->CastSpell(GetPlayer(), 2479, true); + } } void WorldSession::HandleActivateTaxiOpcode(WorldPacket& recvData) @@ -234,6 +275,7 @@ void WorldSession::HandleActivateTaxiOpcode(WorldPacket& recvData) if (!npc) { LOG_DEBUG("network", "WORLD: HandleActivateTaxiOpcode - Unit ({}) not found or you can't interact with it.", guid.ToString()); + SendActivateTaxiReply(ERR_TAXITOOFARAWAY); return; } diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp index 6058b300b..f622976ec 100644 --- a/src/server/game/Instances/InstanceSaveMgr.cpp +++ b/src/server/game/Instances/InstanceSaveMgr.cpp @@ -94,7 +94,7 @@ InstanceSave* InstanceSaveMgr::AddInstanceSave(uint32 mapId, uint32 instanceId, } else { - resetTime = GameTime::GetGameTime().count() + 3 * DAY; // normals expire after 3 days even if someone is still bound to them, cleared on startup + resetTime = GameTime::GetGameTime().count() + static_cast(3) * DAY; // normals expire after 3 days even if someone is still bound to them, cleared on startup extendedResetTime = 0; } InstanceSave* save = new InstanceSave(mapId, instanceId, difficulty, resetTime, extendedResetTime); diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index 25cc841f4..062719942 100644 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -429,14 +429,6 @@ bool LootItem::AllowedForPlayer(Player const* player, bool isGivenByMasterLooter return false; } - // Checking for unique or unique(XX) objects - // master looter should still be able to see the loot to give to people. - // casting to avoid warnings, it's unlikely there's an item with unique but 2^31 items allowed. - if (!isMasterLooter && pProto->MaxCount > 0 && ((int32)player->GetItemCount(itemid, true) >= pProto->MaxCount)) - { - return false; - } - // not show loot for not own team if ((pProto->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY) && player->GetTeamId(true) != TEAM_HORDE) { diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 0846f2281..e821c1623 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -4027,3 +4027,21 @@ void Map::DeleteCorpseData() stmt->SetData(1, GetInstanceId()); CharacterDatabase.Execute(stmt); } + +std::string Map::GetDebugInfo() const +{ + std::stringstream sstr; + sstr << std::boolalpha + << "Id: " << GetId() << " InstanceId: " << GetInstanceId() << " Difficulty: " << std::to_string(GetDifficulty()) + << " HasPlayers: " << HavePlayers(); + return sstr.str(); +} + +std::string InstanceMap::GetDebugInfo() const +{ + std::stringstream sstr; + sstr << Map::GetDebugInfo() << "\n" + << std::boolalpha + << "ScriptId: " << GetScriptId() << " ScriptName: " << GetScriptName(); + return sstr.str(); +} diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index cfa5fba90..a0aa1f82f 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -649,6 +649,8 @@ public: return m_activeNonPlayers.size(); } + virtual std::string GetDebugInfo() const; + private: void LoadMapAndVMap(int gx, int gy); void LoadVMap(int gx, int gy); @@ -830,6 +832,9 @@ public: [[nodiscard]] uint32 GetMaxResetDelay() const; void InitVisibilityDistance() override; + + std::string GetDebugInfo() const override; + private: bool m_resetAfterUnload; bool m_unloadWhenEmpty; diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp index 10c9563df..bd57f449f 100644 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp @@ -270,35 +270,69 @@ void WaypointMovementGenerator::MovementInform(Creature* creature) uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const { if (i_currentNode >= i_path.size()) + { return i_path.size(); + } uint32 curMapId = i_path[i_currentNode]->mapid; for (uint32 i = i_currentNode; i < i_path.size(); ++i) + { if (i_path[i]->mapid != curMapId) + { return i; + } + } return i_path.size(); } +#define SKIP_SPLINE_POINT_DISTANCE_SQ (40.0f * 40.0f) + +bool IsNodeIncludedInShortenedPath(TaxiPathNodeEntry const* p1, TaxiPathNodeEntry const* p2) +{ + return p1->mapid != p2->mapid || std::pow(p1->x - p2->x, 2) + std::pow(p1->y - p2->y, 2) > SKIP_SPLINE_POINT_DISTANCE_SQ; +} + void FlightPathMovementGenerator::LoadPath(Player* player) { _pointsForPathSwitch.clear(); - std::vector const& taxi = player->m_taxi.GetPath(); - for (uint32 src = player->m_taxi.GetTaxiSegment(), dst = player->m_taxi.GetTaxiSegment() + 1; dst < taxi.size(); src = dst++) + std::deque const& taxi = player->m_taxi.GetPath(); + float discount = player->GetReputationPriceDiscount(player->m_taxi.GetFlightMasterFactionTemplate()); + for (uint32 src = 0, dst = 1; dst < taxi.size(); src = dst++) { uint32 path, cost; sObjectMgr->GetTaxiPath(taxi[src], taxi[dst], path, cost); if (path > sTaxiPathNodesByPath.size()) + { return; + } TaxiPathNodeList const& nodes = sTaxiPathNodesByPath[path]; if (!nodes.empty()) { + TaxiPathNodeEntry const* start = nodes[0]; + TaxiPathNodeEntry const* end = nodes[nodes.size() - 1]; + bool passedPreviousSegmentProximityCheck = false; for (uint32 i = 0; i < nodes.size(); ++i) - i_path.push_back(nodes[i]); + { + if (passedPreviousSegmentProximityCheck || !src || i_path.empty() || IsNodeIncludedInShortenedPath(i_path[i_path.size() - 1], nodes[i])) + { + if ((!src || (IsNodeIncludedInShortenedPath(start, nodes[i]) && i >= 2)) && + (dst == taxi.size() - 1 || (IsNodeIncludedInShortenedPath(end, nodes[i]) && i < nodes.size() - 1))) + { + passedPreviousSegmentProximityCheck = true; + i_path.push_back(nodes[i]); + } + } + else + { + i_path.pop_back(); + --_pointsForPathSwitch.back().PathIndex; + } + } } - _pointsForPathSwitch.push_back(uint32(i_path.size() - 1)); + _pointsForPathSwitch.push_back({ uint32(i_path.size() - 1), int32(ceil(cost * discount)) }); } } @@ -313,7 +347,7 @@ void FlightPathMovementGenerator::DoFinalize(Player* player) // remove flag to prevent send object build movement packets for flight state and crash (movement generator already not at top of stack) player->ClearUnitState(UNIT_STATE_IN_FLIGHT); - // xinef: this should be cleaned by CleanupAfterTaxiFlight(); function! + player->m_taxi.ClearTaxiDestinations(); player->Dismount(); player->RemoveUnitFlag(UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT); @@ -324,6 +358,8 @@ void FlightPathMovementGenerator::DoFinalize(Player* player) // this prevent cheating with landing point at lags // when client side flight end early in comparison server side player->StopMoving(); + + // When the player reaches the last flight point, teleport to destination taxi node location player->SetFallInformation(GameTime::GetGameTime().count(), player->GetPositionZ()); } @@ -334,13 +370,23 @@ void FlightPathMovementGenerator::DoFinalize(Player* player) void FlightPathMovementGenerator::DoReset(Player* player) { + uint32 end = GetPathAtMapEnd(); + uint32 currentNodeId = GetCurrentNode(); + + if (currentNodeId == end) + { + LOG_DEBUG("movement.flightpath", "FlightPathMovementGenerator::DoReset: trying to start a flypath from the end point. {}", player->GetGUID().ToString().c_str()); + return; + } + player->getHostileRefMgr().setOnlineOfflineState(false); player->AddUnitState(UNIT_STATE_IN_FLIGHT); player->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT); Movement::MoveSplineInit init(player); - uint32 end = GetPathAtMapEnd(); - for (uint32 i = GetCurrentNode(); i < end; ++i) + // Providing a starting vertex since the taxi paths do not provide such + init.Path().push_back(G3D::Vector3(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ())); + for (uint32 i = currentNodeId; i != end; ++i) { G3D::Vector3 vertice(i_path[i]->x, i_path[i]->y, i_path[i]->z); init.Path().push_back(vertice); @@ -353,77 +399,40 @@ void FlightPathMovementGenerator::DoReset(Player* player) bool FlightPathMovementGenerator::DoUpdate(Player* player, uint32 /*diff*/) { - if (!player) - return false; - - // xinef: map was switched - if (_mapSwitch) - { - DoInitialize(player); - _mapSwitch = false; - return true; - } - - uint32 pointId = (uint32)player->movespline->currentPathIdx(); - if (pointId > i_currentNode) + // skipping the first spline path point because it's our starting point and not a taxi path point + uint32 pointId = player->movespline->currentPathIdx() <= 0 ? 0 : player->movespline->currentPathIdx() - 1; + if (pointId > i_currentNode && i_currentNode < i_path.size() - 1) { bool departureEvent = true; do { - if (i_currentNode >= i_path.size()) - { - LOG_INFO("misc", "TAXI NODE WAS GREATER THAN PATH SIZE, {}, POINTID: {}, NODESIZE: {}, CURRENT: {}", - player->GetGUID().ToString(), pointId, i_path.size(), i_currentNode); - player->CleanupAfterTaxiFlight(); - return false; - } - - if (i_path[i_currentNode]->mapid != player->GetMapId()) - { - LOG_INFO("misc", "Player on different map, curmap: {}, pointmap: {}, nodesize: {}, currentnode: {}", player->GetMapId(), i_path[i_currentNode]->mapid, i_path.size(), i_currentNode); - player->CleanupAfterTaxiFlight(); - return false; - } + ASSERT(i_currentNode < i_path.size(), "Point Id: {}\n{}", pointId, player->GetGUID().ToString().c_str()); DoEventIfAny(player, i_path[i_currentNode], departureEvent); - - // xinef: erase any previous points - uint32 curSize = _pointsForPathSwitch.size(); - while (!_pointsForPathSwitch.empty() && _pointsForPathSwitch.front() <= i_currentNode) + while (!_pointsForPathSwitch.empty() && _pointsForPathSwitch.front().PathIndex <= i_currentNode) + { _pointsForPathSwitch.pop_front(); - - // xinef: switch destination only once - if (curSize != _pointsForPathSwitch.size()) player->m_taxi.NextTaxiDestination(); + if (!_pointsForPathSwitch.empty()) + { + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, _pointsForPathSwitch.front().Cost); + player->ModifyMoney(-_pointsForPathSwitch.front().Cost); + } + } if (pointId == i_currentNode) + { break; + } - if (i_currentNode == _preloadTargetNode && player->GetMapId() == _endMapId) + if (i_currentNode == _preloadTargetNode) + { PreloadEndGrid(); - i_currentNode += (uint32)departureEvent; + } + + i_currentNode += departureEvent ? 1 : 0; departureEvent = !departureEvent; - - // xinef: map should be switched, do not rely on client packets QQ - if (i_currentNode + 1 < i_path.size() && i_path[i_currentNode + 1]->mapid != player->GetMapId()) - { - ++i_currentNode; - _mapSwitch = true; - player->TeleportTo(i_path[i_currentNode]->mapid, i_path[i_currentNode]->x, i_path[i_currentNode]->y, i_path[i_currentNode]->z, player->GetOrientation(), TELE_TO_NOT_LEAVE_TAXI); - return true; - } - - // xinef: reached the end - if (i_currentNode >= i_path.size() - 1) - { - player->CleanupAfterTaxiFlight(); - player->SetFallInformation(GameTime::GetGameTime().count(), player->GetPositionZ()); - if (player->pvpInfo.IsHostile) - player->CastSpell(player, 2479, true); - - return false; - } - } while (true); + } while (i_currentNode < i_path.size() - 1); } return i_currentNode < (i_path.size() - 1); @@ -432,7 +441,9 @@ bool FlightPathMovementGenerator::DoUpdate(Player* player, uint32 /*diff*/) void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport() { if (i_path.empty() || i_currentNode >= i_path.size()) + { return; + } uint32 map0 = i_path[i_currentNode]->mapid; for (size_t i = i_currentNode + 1; i < i_path.size(); ++i) @@ -449,11 +460,20 @@ void FlightPathMovementGenerator::DoEventIfAny(Player* player, TaxiPathNodeEntry { if (uint32 eventid = departure ? node->departureEventID : node->arrivalEventID) { - LOG_DEBUG("maps.script", "Taxi {} event {} of node {} of path {} for player {}", departure ? "departure" : "arrival", eventid, node->index, node->path, player->GetName()); + LOG_DEBUG("maps.script", "Taxi {} event {} of node {} of path {} for player {}", departure ? "departure" : "arrival", eventid, node->index, node->path, player->GetName().c_str()); player->GetMap()->ScriptsStart(sEventScripts, eventid, player, player); } } +bool FlightPathMovementGenerator::GetResetPos(Player*, float& x, float& y, float& z) +{ + TaxiPathNodeEntry const* node = i_path[i_currentNode]; + x = node->x; + y = node->y; + z = node->z; + return true; +} + void FlightPathMovementGenerator::InitEndGridInfo() { /*! Storage to preload flightmaster grid at end of flight. For multi-stop flights, this will @@ -485,11 +505,11 @@ void FlightPathMovementGenerator::PreloadEndGrid() // Load the grid if (endMap) { - LOG_DEBUG("movement", "Preloading rid ({}, {}) for map {} at node index {}/{}", _endGridX, _endGridY, _endMapId, _preloadTargetNode, (uint32)(i_path.size() - 1)); + LOG_DEBUG("misc", "Preloading grid ({}, {}) for map %u at node index {}/{}", _endGridX, _endGridY, _endMapId, _preloadTargetNode, (uint32)(i_path.size() - 1)); endMap->LoadGrid(_endGridX, _endGridY); } else { - LOG_DEBUG("movement", "Unable to determine map to preload flightmaster grid"); + LOG_DEBUG("misc", "Unable to determine map to preload flightmaster grid"); } } diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h index 35eaa932a..1699a71a6 100644 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h @@ -101,40 +101,48 @@ private: class FlightPathMovementGenerator : public MovementGeneratorMedium< Player, FlightPathMovementGenerator >, public PathMovementBase { -public: - explicit FlightPathMovementGenerator(uint32 startNode = 0) - { - i_currentNode = startNode; - _endGridX = 0.0f; - _endGridY = 0.0f; - _endMapId = 0; - _preloadTargetNode = 0; - _mapSwitch = false; - } - void LoadPath(Player* player); - void DoInitialize(Player*); - void DoReset(Player*); - void DoFinalize(Player*); - bool DoUpdate(Player*, uint32); - MovementGeneratorType GetMovementGeneratorType() { return FLIGHT_MOTION_TYPE; } + public: + explicit FlightPathMovementGenerator(uint32 startNode = 0) + { + i_currentNode = startNode; + _endGridX = 0.0f; + _endGridY = 0.0f; + _endMapId = 0; + _preloadTargetNode = 0; + } + void LoadPath(Player* player); + void DoInitialize(Player*); + void DoReset(Player*); + void DoFinalize(Player*); + bool DoUpdate(Player*, uint32); + MovementGeneratorType GetMovementGeneratorType() override { return FLIGHT_MOTION_TYPE; } - TaxiPathNodeList const& GetPath() { return i_path; } - uint32 GetPathAtMapEnd() const; - bool HasArrived() const { return (i_currentNode >= i_path.size()); } - void SetCurrentNodeAfterTeleport(); - void SkipCurrentNode() { ++i_currentNode; } - void DoEventIfAny(Player* player, TaxiPathNodeEntry const* node, bool departure); + TaxiPathNodeList const& GetPath() { return i_path; } + uint32 GetPathAtMapEnd() const; + bool HasArrived() const { return (i_currentNode >= i_path.size()); } + void SetCurrentNodeAfterTeleport(); + void SkipCurrentNode() { ++i_currentNode; } + void DoEventIfAny(Player* player, TaxiPathNodeEntry const* node, bool departure); - void InitEndGridInfo(); - void PreloadEndGrid(); + bool GetResetPos(Player*, float& x, float& y, float& z); -private: - float _endGridX; //! X coord of last node location - float _endGridY; //! Y coord of last node location - uint32 _endMapId; //! map Id of last node location - uint32 _preloadTargetNode; //! node index where preloading starts - bool _mapSwitch; + void InitEndGridInfo(); + void PreloadEndGrid(); - std::deque _pointsForPathSwitch; //! node indexes and costs where TaxiPath changes + private: + + float _endGridX; //! X coord of last node location + float _endGridY; //! Y coord of last node location + uint32 _endMapId; //! map Id of last node location + uint32 _preloadTargetNode; //! node index where preloading starts + + struct TaxiNodeChangeInfo + { + uint32 PathIndex; + int32 Cost; + }; + + std::deque _pointsForPathSwitch; //! node indexes and costs where TaxiPath changes }; + #endif diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 4d9e89169..0717511cc 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -1913,6 +1913,10 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo case FORM_FLIGHT: case FORM_MOONKIN: { + if (Player* player = target->ToPlayer()) + { + player->SetCanTeleport(true); + } // remove movement affects target->RemoveAurasByShapeShift(); @@ -6396,8 +6400,8 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const target->SendPeriodicAuraLog(&pInfo); Unit::DealDamage(caster, target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), true); - // allow null caster to call this function - caster->ProcDamageAndSpell(target, caster ? procAttacker : 0, procVictim, procEx, damage, BASE_ATTACK, GetSpellInfo(), nullptr, GetEffIndex(), nullptr, &dmgInfo); + + Unit::ProcDamageAndSpell(caster, target, caster ? procAttacker : 0, procVictim, procEx, damage, BASE_ATTACK, GetSpellInfo(), nullptr, GetEffIndex(), nullptr, &dmgInfo); } void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) const @@ -6485,8 +6489,8 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c int32 new_damage; new_damage = Unit::DealDamage(caster, target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), false); - // allow null caster to call this function - caster->ProcDamageAndSpell(target, caster ? procAttacker : 0, procVictim, procEx, damage, BASE_ATTACK, GetSpellInfo(), nullptr, GetEffIndex(), nullptr, &dmgInfo); + + Unit::ProcDamageAndSpell(caster, target, caster ? procAttacker : 0, procVictim, procEx, damage, BASE_ATTACK, GetSpellInfo(), nullptr, GetEffIndex(), nullptr, &dmgInfo); if (!caster || !caster->IsAlive()) return; @@ -6668,8 +6672,7 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const // ignore item heals if (!haveCastItem && GetAuraType() != SPELL_AURA_OBS_MOD_HEALTH) // xinef: dont allow obs_mod_health to proc spells, this is passive regeneration and not hot - // xinef: allow null caster to proc - caster->ProcDamageAndSpell(target, caster ? procAttacker : 0, procVictim, procEx, heal, BASE_ATTACK, GetSpellInfo(), nullptr, GetEffIndex(), nullptr, nullptr, &healInfo); + Unit::ProcDamageAndSpell(caster, target, caster ? procAttacker : 0, procVictim, procEx, heal, BASE_ATTACK, GetSpellInfo(), nullptr, GetEffIndex(), nullptr, nullptr, &healInfo); } void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) const @@ -6857,7 +6860,7 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con caster->DealSpellDamage(&damageInfo, true); DamageInfo dmgInfo(damageInfo, DOT); - caster->ProcDamageAndSpell(damageInfo.target, procAttacker, procVictim, procEx, damageInfo.damage, BASE_ATTACK, spellProto, nullptr, GetEffIndex(), nullptr, &dmgInfo); + Unit::ProcDamageAndSpell(caster, damageInfo.target, procAttacker, procVictim, procEx, damageInfo.damage, BASE_ATTACK, spellProto, nullptr, GetEffIndex(), nullptr, &dmgInfo); } void AuraEffect::HandleProcTriggerSpellAuraProc(AuraApplication* aurApp, ProcEventInfo& eventInfo) diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 28c979e86..0a9e80332 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -297,8 +297,8 @@ void AuraApplication::ClientUpdate(bool remove) uint8 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint8 avalibleEffectMask, WorldObject* owner) { - ASSERT(spellProto); - ASSERT(owner); + ASSERT_NODEBUGINFO(spellProto); + ASSERT_NODEBUGINFO(owner); uint8 effMask = 0; switch (owner->GetTypeId()) { @@ -325,10 +325,10 @@ uint8 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint8 avalibleE Aura* Aura::TryRefreshStackOrCreate(SpellInfo const* spellproto, uint8 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount /*= nullptr*/, Item* castItem /*= nullptr*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, bool* refresh /*= nullptr*/, bool periodicReset /*= false*/) { - ASSERT(spellproto); - ASSERT(owner); - ASSERT(caster || casterGUID); - ASSERT(tryEffMask <= MAX_EFFECT_MASK); + ASSERT_NODEBUGINFO(spellproto); + ASSERT_NODEBUGINFO(owner); + ASSERT_NODEBUGINFO(caster || casterGUID); + ASSERT_NODEBUGINFO(tryEffMask <= MAX_EFFECT_MASK); if (refresh) *refresh = false; uint8 effMask = Aura::BuildEffectMaskForOwner(spellproto, tryEffMask, owner); @@ -351,10 +351,10 @@ Aura* Aura::TryRefreshStackOrCreate(SpellInfo const* spellproto, uint8 tryEffMas Aura* Aura::TryCreate(SpellInfo const* spellproto, uint8 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount /*= nullptr*/, Item* castItem /*= nullptr*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, ObjectGuid itemGUID /*= ObjectGuid::Empty*/) { - ASSERT(spellproto); - ASSERT(owner); - ASSERT(caster || casterGUID); - ASSERT(tryEffMask <= MAX_EFFECT_MASK); + ASSERT_NODEBUGINFO(spellproto); + ASSERT_NODEBUGINFO(owner); + ASSERT_NODEBUGINFO(caster || casterGUID); + ASSERT_NODEBUGINFO(tryEffMask <= MAX_EFFECT_MASK); uint8 effMask = Aura::BuildEffectMaskForOwner(spellproto, tryEffMask, owner); if (!effMask) return nullptr; @@ -363,11 +363,11 @@ Aura* Aura::TryCreate(SpellInfo const* spellproto, uint8 tryEffMask, WorldObject Aura* Aura::Create(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32* baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid itemGUID /*= ObjectGuid::Empty*/) { - ASSERT(effMask); - ASSERT(spellproto); - ASSERT(owner); - ASSERT(caster || casterGUID); - ASSERT(effMask <= MAX_EFFECT_MASK); + ASSERT_NODEBUGINFO(effMask); + ASSERT_NODEBUGINFO(spellproto); + ASSERT_NODEBUGINFO(owner); + ASSERT_NODEBUGINFO(caster || casterGUID); + ASSERT_NODEBUGINFO(effMask <= MAX_EFFECT_MASK); // try to get caster of aura if (casterGUID) { @@ -2707,6 +2707,15 @@ void Aura::SetTriggeredByAuraSpellInfo(SpellInfo const* triggeredByAuraSpellInfo m_triggeredByAuraSpellInfo = triggeredByAuraSpellInfo; } +std::string Aura::GetDebugInfo() const +{ + std::stringstream sstr; + sstr << std::boolalpha + << "Id: " << GetId() << " Caster: " << GetCasterGUID().ToString() + << "\nOwner: " << (GetOwner() ? GetOwner()->GetDebugInfo() : "NULL"); + return sstr.str(); +} + SpellInfo const* Aura::GetTriggeredByAuraSpellInfo() const { return m_triggeredByAuraSpellInfo; diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index bcf0d6408..4600a4242 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -236,6 +236,8 @@ public: std::list m_loadedScripts; + virtual std::string GetDebugInfo() const; + void SetTriggeredByAuraSpellInfo(SpellInfo const* triggeredByAuraSpellInfo); SpellInfo const* GetTriggeredByAuraSpellInfo() const; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 75b252b20..96c554a5d 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2792,7 +2792,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) // Do triggers for unit (reflect triggers passed on hit phase for correct drop charge) if (canEffectTrigger) - caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, addhealth, m_attackType, m_spellInfo, m_triggeredByAuraSpell.spellInfo, + Unit::ProcDamageAndSpell(caster, unitTarget, procAttacker, procVictim, procEx, addhealth, m_attackType, m_spellInfo, m_triggeredByAuraSpell.spellInfo, m_triggeredByAuraSpell.effectIndex, this, nullptr, &healInfo); } // Do damage and triggers @@ -2871,7 +2871,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) if (canEffectTrigger) { DamageInfo dmgInfo(damageInfo, SPELL_DIRECT_DAMAGE); - caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, damageInfo.damage, m_attackType, m_spellInfo, m_triggeredByAuraSpell.spellInfo, + Unit::ProcDamageAndSpell(caster, unitTarget, procAttacker, procVictim, procEx, damageInfo.damage, m_attackType, m_spellInfo, m_triggeredByAuraSpell.spellInfo, m_triggeredByAuraSpell.effectIndex, this, &dmgInfo); if (caster->GetTypeId() == TYPEID_PLAYER && m_spellInfo->HasAttribute(SPELL_ATTR0_CANCELS_AUTO_ATTACK_COMBAT) == 0 && @@ -2891,7 +2891,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) if (canEffectTrigger) { DamageInfo dmgInfo(damageInfo, NODAMAGE); - caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, 0, m_attackType, m_spellInfo, m_triggeredByAuraSpell.spellInfo, + Unit::ProcDamageAndSpell(caster, unitTarget, procAttacker, procVictim, procEx, 0, m_attackType, m_spellInfo, m_triggeredByAuraSpell.spellInfo, m_triggeredByAuraSpell.effectIndex, this, &dmgInfo); // Xinef: eg. rogue poisons can proc off cheap shot, etc. so this block should be here also @@ -3972,7 +3972,7 @@ void Spell::_cast(bool skipCheck) break; } - m_originalCaster->ProcDamageAndSpell(m_originalCaster, procAttacker, PROC_FLAG_NONE, procEx, 1, BASE_ATTACK, m_spellInfo, m_triggeredByAuraSpell.spellInfo, + Unit::ProcDamageAndSpell(m_originalCaster, m_originalCaster, procAttacker, PROC_FLAG_NONE, procEx, 1, BASE_ATTACK, m_spellInfo, m_triggeredByAuraSpell.spellInfo, m_triggeredByAuraSpell.effectIndex, this, nullptr, nullptr, PROC_SPELL_PHASE_CAST); } @@ -4312,7 +4312,7 @@ void Spell::_handle_finish_phase() break; } - m_originalCaster->ProcDamageAndSpell(m_originalCaster, procAttacker, PROC_FLAG_NONE, procEx, 1, BASE_ATTACK, m_spellInfo, m_triggeredByAuraSpell.spellInfo, + Unit::ProcDamageAndSpell(m_originalCaster, m_originalCaster, procAttacker, PROC_FLAG_NONE, procEx, 1, BASE_ATTACK, m_spellInfo, m_triggeredByAuraSpell.spellInfo, m_triggeredByAuraSpell.effectIndex, this, nullptr, nullptr, PROC_SPELL_PHASE_FINISH); } } @@ -8155,7 +8155,7 @@ bool ReflectEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) { Unit* target = ObjectAccessor::GetUnit(*_caster, _targetGUID); if (target && _caster->IsInMap(target)) - _caster->ProcDamageAndSpell(target, PROC_FLAG_NONE, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_EX_REFLECT, 1, BASE_ATTACK, _spellInfo); + Unit::ProcDamageAndSpell(_caster, target, PROC_FLAG_NONE, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_EX_REFLECT, 1, BASE_ATTACK, _spellInfo); return true; } @@ -8866,6 +8866,15 @@ void TriggeredByAuraSpellData::Init(AuraEffect const* aurEff) tickNumber = aurEff->GetTickNumber(); } +std::string Spell::GetDebugInfo() const +{ + std::stringstream sstr; + sstr << std::boolalpha + << "Id: " << GetSpellInfo()->Id << " OriginalCaster: " << m_originalCasterGUID.ToString() + << " State: " << getState(); + return sstr.str(); +} + namespace Acore { diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 65f2d9bf7..d9a564871 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -606,6 +606,8 @@ public: Spell** m_selfContainer; // pointer to our spell container (if applicable) + std::string GetDebugInfo() const; + //Spell data SpellSchoolMask m_spellSchoolMask; // Spell school (can be overwrite for some spells (wand shoot for example) WeaponAttackType m_attackType; // For weapon based attack diff --git a/src/server/game/Spells/SpellInfoCorrections.cpp b/src/server/game/Spells/SpellInfoCorrections.cpp index 30ca46693..4a46e8115 100644 --- a/src/server/game/Spells/SpellInfoCorrections.cpp +++ b/src/server/game/Spells/SpellInfoCorrections.cpp @@ -4329,6 +4329,25 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->Effects[EFFECT_0].SpellClassMask = flag96(0x00000003, 0x00001000); }); + // Elemental Vulnerability + ApplySpellFix({ 28772 }, [](SpellInfo* spellInfo) + { + spellInfo->Speed = 1; + }); + + // Find the Ancient Hero: Kill Credit + ApplySpellFix({ 25729 }, [](SpellInfo* spellInfo) + { + spellInfo->Effects[EFFECT_0].TargetA = TARGET_UNIT_SUMMONER; + }); + + // Artorius Demonic Doom + ApplySpellFix({ 23298 }, [](SpellInfo* spellInfo) + { + spellInfo->AttributesEx4 |= SPELL_ATTR4_IGNORE_DAMAGE_TAKEN_MODIFIERS; + spellInfo->AttributesEx6 |= SPELL_ATTR6_IGNORE_CASTER_DAMAGE_MODIFIERS; + }); + for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i) { SpellInfo* spellInfo = mSpellInfoMap[i]; diff --git a/src/server/scripts/Commands/cs_achievement.cpp b/src/server/scripts/Commands/cs_achievement.cpp index 1fb43b2db..070ae2d4f 100644 --- a/src/server/scripts/Commands/cs_achievement.cpp +++ b/src/server/scripts/Commands/cs_achievement.cpp @@ -40,7 +40,7 @@ public: static ChatCommandTable achievementCommandTable = { { "add", HandleAchievementAddCommand, SEC_GAMEMASTER, Console::No }, - { "checkall", HandleAchievementCheckAllCommand, SEC_ADMINISTRATOR, Console::No } + { "checkall", HandleAchievementCheckAllCommand, SEC_ADMINISTRATOR, Console::Yes } }; static ChatCommandTable commandTable = { @@ -63,17 +63,33 @@ public: return true; } - static bool HandleAchievementCheckAllCommand(ChatHandler* handler) + static bool HandleAchievementCheckAllCommand(ChatHandler* handler, Optional player) { - Player* target = handler->getSelectedPlayer(); - if (!target) + if (!player) { - handler->SendSysMessage(LANG_NO_CHAR_SELECTED); + player = PlayerIdentifier::FromTarget(handler); + } + + if (!player) + { + handler->SendSysMessage(LANG_PLAYER_NOT_FOUND); handler->SetSentErrorMessage(true); return false; } - target->CheckAllAchievementCriteria(); + if (player->IsConnected()) + { + if (Player* target = player->GetConnectedPlayer()) + target->CheckAllAchievementCriteria(); + } + else + { + auto* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); + stmt->SetData(0, uint16(AT_LOGIN_CHECK_ACHIEVS)); + stmt->SetData(1, player->GetGUID().GetCounter()); + CharacterDatabase.Execute(stmt); + } + return true; } }; diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/blackwing_lair.h b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/blackwing_lair.h index a0adcf52b..1313f4f3a 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/blackwing_lair.h +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/blackwing_lair.h @@ -43,7 +43,8 @@ enum BWLEncounter DATA_NEFARIAN_TROOPS = 10, // Doors - DATA_GO_CHROMAGGUS_DOOR = 11 + DATA_GO_CHROMAGGUS_DOOR = 11, + DATA_GO_CHROMAGGUS_DOOR_EXIT= 12 }; enum BWLCreatureIds @@ -92,7 +93,8 @@ enum BWLGameObjectIds GO_PORTCULLIS_THREEDRAGONS = 179115, GO_CHROMAGGUS_LEVER = 179148, GO_PORTCULLIS_CHROMAGGUS = 179116, - GO_PORTCULLIS_NEFARIAN = 179117, + GO_PORTCULLIS_CHROMAGGUS_EXIT = 179117, + GO_PORTCULLIS_NEFARIAN = 176966, GO_SUPPRESSION_DEVICE = 179784 }; diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_chromaggus.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_chromaggus.cpp index 9da7d418a..e01a22aab 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_chromaggus.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_chromaggus.cpp @@ -85,7 +85,7 @@ public: Acore::Containers::RandomResize(_breathSpells, 2); // Hack fix: This is here to prevent him from being pulled from the floor underneath, remove it once maps are fixed. - creature->SetReactState(REACT_PASSIVE); + creature->SetImmuneToAll(true); } void Initialize() @@ -122,7 +122,7 @@ public: { _playerGUID = guid; // Hack fix: This is here to prevent him from being pulled from the floor underneath, remove it once maps are fixed. - me->SetReactState(REACT_AGGRESSIVE); + me->SetImmuneToAll(false); } } diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp index a9d1299e6..93abf5146 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp @@ -35,8 +35,9 @@ DoorData const doorData[] = { GO_PORTCULLIS_RAZORGORE_ROOM, DATA_RAZORGORE_THE_UNTAMED, DOOR_TYPE_ROOM, }, // ID 176964 || GUID 75158 { GO_PORTCULLIS_VAELASTRASZ, DATA_VAELASTRAZ_THE_CORRUPT, DOOR_TYPE_PASSAGE }, // ID 175185 || GUID 7229 { GO_PORTCULLIS_BROODLORD, DATA_BROODLORD_LASHLAYER, DOOR_TYPE_PASSAGE }, // ID 179365 || GUID 75159 - { GO_PORTCULLIS_NEFARIAN, DATA_CHROMAGGUS, DOOR_TYPE_PASSAGE }, // ID 179116 || GUID 75161 - { GO_PORTCULLIS_NEFARIAN, DATA_NEFARIAN, DOOR_TYPE_ROOM }, // ID 179117 || GUID 75164 + { GO_PORTCULLIS_CHROMAGGUS_EXIT,DATA_CHROMAGGUS, DOOR_TYPE_PASSAGE }, // ID 179117 || GUID 75164 + { GO_PORTCULLIS_CHROMAGGUS_EXIT,DATA_NEFARIAN, DOOR_TYPE_ROOM }, // ID 179117 || GUID 75164 + { GO_PORTCULLIS_NEFARIAN, DATA_NEFARIAN, DOOR_TYPE_ROOM }, // ID 176966 { 0, 0, DOOR_TYPE_ROOM } // END }; @@ -45,12 +46,13 @@ ObjectData const creatureData[] = { NPC_GRETHOK, DATA_GRETHOK }, { NPC_NEFARIAN_TROOPS, DATA_NEFARIAN_TROOPS }, { NPC_VICTOR_NEFARIUS, DATA_LORD_VICTOR_NEFARIUS }, - { NPC_CHROMAGGUS, DATA_CHROMAGGUS } + { NPC_CHROMAGGUS, DATA_CHROMAGGUS }, }; ObjectData const objectData[] = { - { GO_PORTCULLIS_CHROMAGGUS, DATA_GO_CHROMAGGUS_DOOR } + { GO_PORTCULLIS_CHROMAGGUS, DATA_GO_CHROMAGGUS_DOOR }, + { GO_PORTCULLIS_CHROMAGGUS_EXIT, DATA_GO_CHROMAGGUS_DOOR_EXIT } }; Position const SummonPosition[8] = diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp index dc6a899d0..e376e3fd1 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp @@ -1220,33 +1220,6 @@ public: }; }; -class spell_q12779_an_end_to_all_things : public SpellScriptLoader -{ -public: - spell_q12779_an_end_to_all_things() : SpellScriptLoader("spell_q12779_an_end_to_all_things") { } - - class spell_q12779_an_end_to_all_things_SpellScript : public SpellScript - { - PrepareSpellScript(spell_q12779_an_end_to_all_things_SpellScript); - - void HandleScriptEffect(SpellEffIndex /*effIndex*/) - { - if (GetHitUnit()) - GetHitUnit()->CastSpell(GetCaster(), GetEffectValue(), true); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_q12779_an_end_to_all_things_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_q12779_an_end_to_all_things_SpellScript(); - } -}; - void AddSC_the_scarlet_enclave_c2() { new npc_crusade_persuaded(); @@ -1254,7 +1227,4 @@ void AddSC_the_scarlet_enclave_c2() new npc_koltira_deathweaver(); new npc_high_inquisitor_valroth(); new npc_a_special_surprise(); - - // Xinef: Should be in chapter III - new spell_q12779_an_end_to_all_things(); } diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter3.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter3.cpp new file mode 100644 index 000000000..7504b35cf --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter3.cpp @@ -0,0 +1,42 @@ +/* + * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by the + * Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "Player.h" +#include "ScriptMgr.h" +#include "SpellInfo.h" +#include "SpellScript.h" + +class spell_q12779_an_end_to_all_things : public SpellScript +{ + PrepareSpellScript(spell_q12779_an_end_to_all_things); + + void HandleScriptEffect(SpellEffIndex /*effIndex*/) + { + if (GetHitUnit()) + GetHitUnit()->CastSpell(GetCaster(), GetEffectValue(), true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_q12779_an_end_to_all_things::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + +void AddSC_the_scarlet_enclave_c3() +{ + RegisterSpellScript(spell_q12779_an_end_to_all_things); +} diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_gahzranka.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_gahzranka.cpp index 4cf8348d0..d05d1696f 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_gahzranka.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_gahzranka.cpp @@ -168,18 +168,20 @@ class spell_pagles_point_cast : public SpellScript { if (InstanceScript* instanceScript = caster->GetInstanceScript()) { - if (!instanceScript->GetData(DATA_GAHZRANKA)) + if (!instanceScript->GetData(DATA_GAHZRANKA) && !caster->FindNearestCreature(NPC_GAHZRANKA, 50.0f)) { caster->m_Events.AddEventAtOffset([caster]() { if (GameObject* lure = caster->SummonGameObject(GAMEOBJECT_MUDSKUNK_LURE, -11688.5f, -1737.74f, 10.409842f, 1.f, 0.f, 0.f, 0.f, 0.f, 30 * IN_MILLISECONDS)) { - caster->m_Events.AddEventAtOffset([caster, lure]() + lure->DespawnOrUnsummon(5s); + caster->m_Events.AddEventAtOffset([caster]() { - if (lure) - lure->DespawnOrUnsummon(); - caster->CastSpell(caster, SPELL_SPLASH, true); - caster->SummonCreature(NPC_GAHZRANKA, -11688.5f, -1723.74f, -5.78f, 0.f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5 * DAY * IN_MILLISECONDS); + if (!caster->FindNearestCreature(NPC_GAHZRANKA, 50.0f)) + { + caster->CastSpell(caster, SPELL_SPLASH, true); + caster->SummonCreature(NPC_GAHZRANKA, -11688.5f, -1723.74f, -5.78f, 0.f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5 * DAY * IN_MILLISECONDS); + } }, 5s); } }, 2s); diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp index cf9d16c47..a9d8414a6 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp @@ -719,11 +719,14 @@ public: { if (Unit* target = GetTarget()) { - if (Creature* caster = GetCaster()->ToCreature()) + if (Unit* caster = GetCaster()) { - if (caster->IsAIEnabled) + if (Creature* cCaster = caster->ToCreature()) { - caster->AI()->SetGUID(target->GetGUID(), ACTION_CHARGE); + if (cCaster->IsAIEnabled) + { + cCaster->AI()->SetGUID(target->GetGUID(), ACTION_CHARGE); + } } } } diff --git a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp index cfe1b9ec3..e8cf955c9 100644 --- a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp +++ b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp @@ -97,6 +97,7 @@ void AddSC_instance_molten_core(); void AddSC_the_scarlet_enclave(); //Scarlet Enclave void AddSC_the_scarlet_enclave_c1(); void AddSC_the_scarlet_enclave_c2(); +void AddSC_the_scarlet_enclave_c3(); void AddSC_the_scarlet_enclave_c5(); void AddSC_instance_scarlet_monastery(); //Scarlet Monastery void AddSC_boss_kirtonos_the_herald(); @@ -247,6 +248,7 @@ void AddEasternKingdomsScripts() AddSC_the_scarlet_enclave(); //Scarlet Enclave AddSC_the_scarlet_enclave_c1(); AddSC_the_scarlet_enclave_c2(); + AddSC_the_scarlet_enclave_c3(); AddSC_the_scarlet_enclave_c5(); AddSC_instance_scarlet_monastery(); //Scarlet Monastery AddSC_boss_kirtonos_the_herald(); diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp index d1198e820..41204a176 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp @@ -18,281 +18,427 @@ #include "Player.h" #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "SpellScript.h" #include "ruins_of_ahnqiraj.h" +#include "TaskScheduler.h" enum Spells { - SPELL_STINGER_SPRAY = 25749, - SPELL_POISON_STINGER = 25748, - SPELL_PARALYZE = 25725, - SPELL_FRENZY = 8269, - SPELL_LASH = 25852, - SPELL_FEED = 25721 + SPELL_STINGER_SPRAY = 25749, + SPELL_POISON_STINGER = 25748, + SPELL_PARALYZE = 25725, + SPELL_FRENZY = 8269, + SPELL_LASH = 25852, + SPELL_FEED = 25721, + SPELL_THRASH = 3391, + + // Server-side spells + SPELL_SUMMON_LARVA_A = 26538, + SPELL_SUMMON_LARVA_B = 26539, + SPELL_LARVA_AGGRO_EFFECT = 25724, // Unknown purpose + SPELL_LARVA_FEAR_EFFECT = 25726, // Unknown purpose + SPELL_SUMMON_HIVEZARA_SWARMER = 25708, + SPELL_HIVEZARA_SWARMER_TELEPORT_1 = 25709, + SPELL_HIVEZARA_SWARMER_TELEPORT_2 = 25825, + SPELL_HIVEZARA_SWARMER_TELEPORT_3 = 25826, + SPELL_HIVEZARA_SWARMER_TELEPORT_4 = 25827, + SPELL_HIVEZARA_SWARMER_TELEPORT_5 = 25828, + SPELL_HIVEZARA_SWARMER_TELEPORT_TRIGGER = 25830, + SPELL_HIVEZARA_SWARMER_START_LOOP = 25711, + SPELL_HIVEZARA_SWARMER_LOOP_1 = 25833, + SPELL_HIVEZARA_SWARMER_LOOP_2 = 25834, + SPELL_HIVEZARA_SWARMER_LOOP_3 = 25835, + SPELL_HIVEZARA_SWARMER_SWARM = 25844 }; -enum Events +enum Misc { - EVENT_STINGER_SPRAY = 1, - EVENT_POISON_STINGER = 2, - EVENT_SUMMON_SWARMER = 3, - EVENT_SWARMER_ATTACK = 4, - EVENT_PARALYZE = 5, - EVENT_LASH = 6 + MAX_SWARMER_COUNT = 28, + ACTION_SWARMER_SWARM = 1, }; enum Emotes { - EMOTE_FRENZY = 0 + EMOTE_FRENZY = 0 }; enum Phases { - PHASE_AIR = 0, - PHASE_GROUND = 1 + PHASE_AIR = 0, + PHASE_GROUND = 1 }; enum Points { - POINT_AIR = 0, - POINT_GROUND = 1, - POINT_PARALYZE = 2 + POINT_AIR = 0, + POINT_GROUND = 2, + POINT_PARALYZE = 2 }; -const Position AyamissAirPos = { -9689.292f, 1547.912f, 48.02729f, 0.0f }; -const Position AltarPos = { -9717.18f, 1517.72f, 27.4677f, 0.0f }; -/// @todo These below are probably incorrect, taken from SD2 -const Position SwarmerPos = { -9647.352f, 1578.062f, 55.32f, 0.0f }; -const Position LarvaPos[2] = -{ - { -9674.4707f, 1528.4133f, 22.457f, 0.0f }, - { -9701.6005f, 1566.9993f, 24.118f, 0.0f } -}; +const Position AyamissAirPos = { -9689.292f, 1547.912f, 48.02729f, 0.0f }; +const Position AltarPos = { -9717.18f, 1517.72f, 27.4677f, 0.0f }; -class boss_ayamiss : public CreatureScript +struct boss_ayamiss : public BossAI { -public: - boss_ayamiss() : CreatureScript("boss_ayamiss") { } + boss_ayamiss(Creature* creature) : BossAI(creature, DATA_AYAMISS) { homePos = creature->GetHomePosition(); } - struct boss_ayamissAI : public BossAI + void Reset() override { - boss_ayamissAI(Creature* creature) : BossAI(creature, DATA_AYAMISS) {} + BossAI::Reset(); + _phase = PHASE_AIR; + _enraged = false; + SetCombatMovement(false); + _scheduler.CancelAll(); + } - void Reset() override + void JustSummoned(Creature* who) override + { + switch (who->GetEntry()) { - _Reset(); - _phase = PHASE_AIR; - _enraged = false; - SetCombatMovement(false); + case NPC_HIVEZARA_SWARMER: + who->CastSpell(who, SPELL_HIVEZARA_SWARMER_TELEPORT_TRIGGER, true); + _swarmers.push_back(who->GetGUID()); + break; + case NPC_HIVEZARA_LARVA: + who->GetMotionMaster()->MovePoint(POINT_PARALYZE, AltarPos); + break; } - void JustSummoned(Creature* who) override + summons.Summon(who); + } + + void MovementInform(uint32 type, uint32 id) override + { + if (type == POINT_MOTION_TYPE && id == POINT_AIR) { - switch (who->GetEntry()) + me->AddUnitState(UNIT_STATE_ROOT); + } + else if (type == WAYPOINT_MOTION_TYPE && id == POINT_GROUND) + { + SetCombatMovement(true); + + me->m_Events.AddEventAtOffset([this]() { - case NPC_SWARMER: - _swarmers.push_back(who->GetGUID()); - break; - case NPC_LARVA: - who->GetMotionMaster()->MovePoint(POINT_PARALYZE, AltarPos); - break; - case NPC_HORNET: + if (me->GetVictim()) + { + me->GetMotionMaster()->MoveChase(me->GetVictim()); + } + + }, 1s); + } + } + + void ScheduleTasks() + { + _scheduler.Schedule(20s, 30s, [this](TaskContext context) + { + DoCastSelf(SPELL_STINGER_SPRAY); + context.Repeat(15s, 20s); + }).Schedule(5s, [this](TaskContext context) { + DoCastVictim(SPELL_POISON_STINGER); + context.SetGroup(PHASE_AIR); + context.Repeat(2s, 3s); + }).Schedule(5s, [this](TaskContext context) { + DoCastAOE(SPELL_SUMMON_HIVEZARA_SWARMER, true); + + if (_swarmers.size() >= MAX_SWARMER_COUNT) + { + DoCastAOE(SPELL_HIVEZARA_SWARMER_SWARM, true); + } + + context.Repeat(RAND(2400ms, 3600ms)); + }).Schedule(15s, [this](TaskContext context) { + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0, true)) + { + DoCast(target, SPELL_PARALYZE, true); + instance->SetGuidData(DATA_PARALYZED, target->GetGUID()); + DoCastAOE(RAND(SPELL_SUMMON_LARVA_A, SPELL_SUMMON_LARVA_B), true); + } + context.Repeat(); + }); + } + + void DoAction(int32 action) override + { + if (action == ACTION_SWARMER_SWARM) + { + for (ObjectGuid const& guid : _swarmers) + { + if (Creature* swarmer = me->GetMap()->GetCreature(guid)) + { if (Unit* target = SelectTarget(SelectTargetMethod::Random)) { - who->AI()->AttackStart(target); + swarmer->AI()->AttackStart(target); } - break; - } - } - - void MovementInform(uint32 type, uint32 id) override - { - if (type == POINT_MOTION_TYPE) - { - switch (id) - { - case POINT_AIR: - me->AddUnitState(UNIT_STATE_ROOT); - break; - case POINT_GROUND: - me->GetMotionMaster()->MoveChase(me->GetVictim()); - break; } } + + _swarmers.clear(); } + } - void EnterEvadeMode(EvadeReason why) override - { - me->ClearUnitState(UNIT_STATE_ROOT); - BossAI::EnterEvadeMode(why); - } - - void EnterCombat(Unit* attacker) override - { - BossAI::EnterCombat(attacker); - events.ScheduleEvent(EVENT_STINGER_SPRAY, urand(20000, 30000)); - events.ScheduleEvent(EVENT_POISON_STINGER, 5000); - events.ScheduleEvent(EVENT_SUMMON_SWARMER, 5000); - events.ScheduleEvent(EVENT_SWARMER_ATTACK, 60000); - events.ScheduleEvent(EVENT_PARALYZE, 15000); - me->SetCanFly(true); - me->SetDisableGravity(true); - me->GetMotionMaster()->MovePoint(POINT_AIR, AyamissAirPos); - } - - void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override - { - if (_phase == PHASE_AIR && me->GetHealthPct() < 70.0f) - { - _phase = PHASE_GROUND; - SetCombatMovement(true); - me->ClearUnitState(UNIT_STATE_ROOT); - me->SetCanFly(false); - me->SetDisableGravity(false); - Position VictimPos = me->GetVictim()->GetPosition(); - me->GetMotionMaster()->MovePoint(POINT_GROUND, VictimPos); - events.ScheduleEvent(EVENT_LASH, urand(5000, 8000)); - events.CancelEvent(EVENT_POISON_STINGER); - DoResetThreat(); - } - if (!_enraged && me->GetHealthPct() < 20.0f) - { - DoCastSelf(SPELL_FRENZY); - Talk(EMOTE_FRENZY); - _enraged = true; - } - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_STINGER_SPRAY: - DoCastSelf(SPELL_STINGER_SPRAY); - events.ScheduleEvent(EVENT_STINGER_SPRAY, urand(15000, 20000)); - break; - case EVENT_POISON_STINGER: - DoCastVictim(SPELL_POISON_STINGER); - events.ScheduleEvent(EVENT_POISON_STINGER, urand(2000, 3000)); - break; - case EVENT_PARALYZE: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0, true)) - { - DoCast(target, SPELL_PARALYZE); - instance->SetGuidData(DATA_PARALYZED, target->GetGUID()); - uint8 Index = urand(0, 1); - me->SummonCreature(NPC_LARVA, LarvaPos[Index], TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000); - } - events.ScheduleEvent(EVENT_PARALYZE, 15000); - break; - case EVENT_SWARMER_ATTACK: - for (ObjectGuid const& guid : _swarmers) - { - if (Creature* swarmer = me->GetMap()->GetCreature(guid)) - { - if (Unit* target = SelectTarget(SelectTargetMethod::Random)) - { - swarmer->AI()->AttackStart(target); - } - } - } - _swarmers.clear(); - events.ScheduleEvent(EVENT_SWARMER_ATTACK, 60000); - break; - case EVENT_SUMMON_SWARMER: - { - Position Pos = me->GetRandomPoint(SwarmerPos, 80.0f); - me->SummonCreature(NPC_SWARMER, Pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); - events.ScheduleEvent(EVENT_SUMMON_SWARMER, 5000); - break; - } - case EVENT_LASH: - DoCastVictim(SPELL_LASH); - events.ScheduleEvent(EVENT_LASH, urand(8000, 15000)); - break; - } - } - DoMeleeAttackIfReady(); - } - private: - GuidList _swarmers; - uint8 _phase; - bool _enraged; - }; - - CreatureAI* GetAI(Creature* creature) const override + void EnterEvadeMode(EvadeReason why) override { - return GetRuinsOfAhnQirajAI(creature); + me->ClearUnitState(UNIT_STATE_ROOT); + me->SetHomePosition(homePos); + BossAI::EnterEvadeMode(why); + } + + void EnterCombat(Unit* attacker) override + { + BossAI::EnterCombat(attacker); + me->SetCanFly(true); + me->SetDisableGravity(true); + me->GetMotionMaster()->MovePoint(POINT_AIR, AyamissAirPos); + ScheduleTasks(); + } + + void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType, SpellSchoolMask) override + { + if (_phase == PHASE_AIR && me->HealthBelowPctDamaged(70, damage)) + { + _phase = PHASE_GROUND; + me->ClearUnitState(UNIT_STATE_ROOT); + me->SetCanFly(false); + me->SetDisableGravity(false); + me->GetMotionMaster()->MovePath(me->GetEntry() * 10, false); + DoResetThreat(); + + _scheduler.Schedule(5s, 8s, [this](TaskContext context) { + DoCastVictim(SPELL_LASH); + context.Repeat(8s, 15s); + }).Schedule(16s, [this](TaskContext context) + { + DoCastSelf(SPELL_THRASH); + context.Repeat(); + }); + + _scheduler.DelayAll(5s); + _scheduler.CancelGroup(PHASE_AIR); + } + + if (!_enraged && me->HealthBelowPctDamaged(20, damage)) + { + DoCastSelf(SPELL_FRENZY); + Talk(EMOTE_FRENZY); + _enraged = true; + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + _scheduler.Update(diff, + std::bind(&BossAI::DoMeleeAttackIfReady, this)); + } +private: + GuidList _swarmers; + uint8 _phase; + bool _enraged; + TaskScheduler _scheduler; + Position homePos; +}; + +struct npc_hive_zara_larva : public ScriptedAI +{ + npc_hive_zara_larva(Creature* creature) : ScriptedAI(creature) + { + _instance = me->GetInstanceScript(); + } + + void MovementInform(uint32 type, uint32 id) override + { + if (type == POINT_MOTION_TYPE && id == POINT_PARALYZE) + { + if (Player* target = ObjectAccessor::GetPlayer(*me, _instance->GetGuidData(DATA_PARALYZED))) + { + DoCast(target, SPELL_FEED); + } + } + } + + void JustSummoned(Creature* summon) override + { + if (Creature* ayamiss = _instance->GetCreature(DATA_AYAMISS)) + { + ayamiss->AI()->JustSummoned(summon); + } + } + + void MoveInLineOfSight(Unit* who) override + { + if (_instance->GetBossState(DATA_AYAMISS) == IN_PROGRESS) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void AttackStart(Unit* victim) override + { + if (_instance->GetBossState(DATA_AYAMISS) == IN_PROGRESS) + return; + + ScriptedAI::AttackStart(victim); + } + + void UpdateAI(uint32 diff) override + { + if (_instance->GetBossState(DATA_AYAMISS) == IN_PROGRESS) + return; + + ScriptedAI::UpdateAI(diff); + } +private: + InstanceScript* _instance; +}; + +struct npc_hive_zara_swarmer : public ScriptedAI +{ + npc_hive_zara_swarmer(Creature* creature) : ScriptedAI(creature) { } + + void PathEndReached(uint32 /*pathId*/) override + { + // Delay is required because we are calling the movement generator from inside the pathing hook. + // If we issue another call here, it will be flushed before it is executed. + me->m_Events.AddEventAtOffset([this]() + { + DoCastSelf(SPELL_HIVEZARA_SWARMER_START_LOOP); + }, 1s); } }; -class npc_hive_zara_larva : public CreatureScript +struct WaspTeleportData { -public: - npc_hive_zara_larva() : CreatureScript("npc_hive_zara_larva") { } + uint32 spellId; + uint32 pathId; +}; - struct npc_hive_zara_larvaAI : public ScriptedAI +class spell_ayamiss_swarmer_teleport_trigger : public SpellScript +{ + PrepareSpellScript(spell_ayamiss_swarmer_teleport_trigger); + + bool Validate(SpellInfo const* /*spellInfo*/) override { - npc_hive_zara_larvaAI(Creature* creature) : ScriptedAI(creature) - { - _instance = me->GetInstanceScript(); - } - - void MovementInform(uint32 type, uint32 id) override - { - if (type == POINT_MOTION_TYPE) - { - if (id == POINT_PARALYZE) - { - if (Player* target = ObjectAccessor::GetPlayer(*me, _instance->GetGuidData(DATA_PARALYZED))) - { - DoCast(target, SPELL_FEED); - } - } - } - } - - void MoveInLineOfSight(Unit* who) override - - { - if (_instance->GetBossState(DATA_AYAMISS) == IN_PROGRESS) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - - void AttackStart(Unit* victim) override - { - if (_instance->GetBossState(DATA_AYAMISS) == IN_PROGRESS) - return; - - ScriptedAI::AttackStart(victim); - } - - void UpdateAI(uint32 diff) override - { - if (_instance->GetBossState(DATA_AYAMISS) == IN_PROGRESS) - return; - - ScriptedAI::UpdateAI(diff); - } - private: - InstanceScript* _instance; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetRuinsOfAhnQirajAI(creature); + return ValidateSpellInfo + ( { + SPELL_HIVEZARA_SWARMER_TELEPORT_1, SPELL_HIVEZARA_SWARMER_TELEPORT_2, + SPELL_HIVEZARA_SWARMER_TELEPORT_3, SPELL_HIVEZARA_SWARMER_TELEPORT_4, + SPELL_HIVEZARA_SWARMER_TELEPORT_5 + }); } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + WaspTeleportData telData[5] = + { + { SPELL_HIVEZARA_SWARMER_TELEPORT_1, NPC_HIVEZARA_SWARMER * 10 }, + { SPELL_HIVEZARA_SWARMER_TELEPORT_2, (NPC_HIVEZARA_SWARMER + 1) * 10 }, + { SPELL_HIVEZARA_SWARMER_TELEPORT_3, (NPC_HIVEZARA_SWARMER + 2) * 10 }, + { SPELL_HIVEZARA_SWARMER_TELEPORT_4, (NPC_HIVEZARA_SWARMER + 3) * 10 }, + { SPELL_HIVEZARA_SWARMER_TELEPORT_5, (NPC_HIVEZARA_SWARMER + 4) * 10 } + }; + + WaspTeleportData data = Acore::Containers::SelectRandomContainerElement(telData); + caster->CastSpell((Unit*)nullptr, data.spellId, true); + + uint32 pathId = data.pathId; + caster->m_Events.AddEventAtOffset([caster, pathId]() + { + caster->GetMotionMaster()->MovePath(pathId, false); + }, 1s); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_ayamiss_swarmer_teleport_trigger::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + +class spell_ayamiss_swarmer_swarm : public SpellScript +{ + PrepareSpellScript(spell_ayamiss_swarmer_swarm); + + bool Load() override + { + return GetCaster()->GetEntry() == NPC_AYAMISS; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->ToCreature()->AI()->DoAction(ACTION_SWARMER_SWARM); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_ayamiss_swarmer_swarm::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +class spell_ayamiss_swarmer_start_loop : public SpellScript +{ + PrepareSpellScript(spell_ayamiss_swarmer_start_loop); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_HIVEZARA_SWARMER_LOOP_1, SPELL_HIVEZARA_SWARMER_LOOP_2, SPELL_HIVEZARA_SWARMER_LOOP_3 }); + } + + bool Load() override + { + return GetCaster()->GetEntry() == NPC_HIVEZARA_SWARMER; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + uint32 loopSpells[3] = { SPELL_HIVEZARA_SWARMER_LOOP_1, SPELL_HIVEZARA_SWARMER_LOOP_2, SPELL_HIVEZARA_SWARMER_LOOP_3 }; + GetCaster()->CastSpell((Unit*)nullptr, Acore::Containers::SelectRandomContainerElement(loopSpells)); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_ayamiss_swarmer_start_loop::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + +class spell_gen_ayamiss_swarmer_loop: public SpellScript +{ + PrepareSpellScript(spell_gen_ayamiss_swarmer_loop); + +public: + spell_gen_ayamiss_swarmer_loop(uint32 pathId) : SpellScript(), _pathId(pathId) { } + + bool Load() override + { + return GetCaster()->GetEntry() == NPC_HIVEZARA_SWARMER; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->ToCreature()->GetMotionMaster()->Clear(); + GetCaster()->ToCreature()->GetMotionMaster()->MovePath(_pathId, false); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_gen_ayamiss_swarmer_loop::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); + } + +private: + uint32 _pathId; }; void AddSC_boss_ayamiss() { - new boss_ayamiss(); - new npc_hive_zara_larva(); + RegisterRuinsOfAhnQirajCreatureAI(boss_ayamiss); + RegisterRuinsOfAhnQirajCreatureAI(npc_hive_zara_larva); + RegisterRuinsOfAhnQirajCreatureAI(npc_hive_zara_swarmer); + RegisterSpellScript(spell_ayamiss_swarmer_teleport_trigger); + RegisterSpellScript(spell_ayamiss_swarmer_swarm); + RegisterSpellScript(spell_ayamiss_swarmer_start_loop); + RegisterSpellScriptWithArgs(spell_gen_ayamiss_swarmer_loop, "spell_gen_ayamiss_swarmer_loop_1", (NPC_HIVEZARA_SWARMER + 5) * 10); + RegisterSpellScriptWithArgs(spell_gen_ayamiss_swarmer_loop, "spell_gen_ayamiss_swarmer_loop_2", (NPC_HIVEZARA_SWARMER + 6) * 10); + RegisterSpellScriptWithArgs(spell_gen_ayamiss_swarmer_loop, "spell_gen_ayamiss_swarmer_loop_3", (NPC_HIVEZARA_SWARMER + 7) * 10); } diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp index 97a419af7..90744df9a 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp @@ -80,7 +80,7 @@ struct boss_buru : public BossAI void EnterCombat(Unit* who) override { - _EnterCombat(); + BossAI::EnterCombat(who); Talk(EMOTE_TARGET, who); DoCastSelf(SPELL_THORNS); ManipulateEggs(true); diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp index 34619337a..b0cf0c878 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp @@ -28,14 +28,16 @@ enum Spells SPELL_SAND_TRAP = 25648, SPELL_ENRAGE = 26527, SPELL_SUMMON_PLAYER = 26446, - SPELL_WIDE_SLASH = 25814 + SPELL_WIDE_SLASH = 25814, + SPELL_THRASH = 3391 }; enum Events { EVENT_MORTAL_WOUND = 1, EVENT_SAND_TRAP = 2, - EVENT_WIDE_SLASH = 3 + EVENT_WIDE_SLASH = 3, + EVENT_THRASH = 4 }; enum Texts @@ -47,6 +49,12 @@ struct boss_kurinnaxx : public BossAI { boss_kurinnaxx(Creature* creature) : BossAI(creature, DATA_KURINNAXX) {} + void InitializeAI() override + { + me->m_CombatDistance = 50.0f; + Reset(); + } + void Reset() override { BossAI::Reset(); @@ -54,6 +62,7 @@ struct boss_kurinnaxx : public BossAI events.ScheduleEvent(EVENT_MORTAL_WOUND, 8s, 10s); events.ScheduleEvent(EVENT_SAND_TRAP, 5s, 15s); events.ScheduleEvent(EVENT_WIDE_SLASH, 10s, 15s); + events.ScheduleEvent(EVENT_THRASH, 16s); } void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override @@ -108,6 +117,10 @@ struct boss_kurinnaxx : public BossAI DoCastSelf(SPELL_WIDE_SLASH); events.ScheduleEvent(EVENT_WIDE_SLASH, 12s, 15s); break; + case EVENT_THRASH: + DoCastSelf(SPELL_THRASH); + events.ScheduleEvent(EVENT_THRASH, 16s); + break; default: break; } diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp index a4f70a104..d5b7269b1 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp @@ -66,9 +66,9 @@ struct boss_moam : public BossAI { BossAI::EnterCombat(who); Talk(EMOTE_AGGRO); - events.ScheduleEvent(EVENT_STONE_PHASE, 90000); - events.ScheduleEvent(EVENT_SPELL_TRAMPLE, 9000); - events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, 3000); + events.ScheduleEvent(EVENT_STONE_PHASE, 90s); + events.ScheduleEvent(EVENT_SPELL_TRAMPLE, 9s); + events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, 3s); } void JustDied(Unit* /*killer*/) override @@ -113,20 +113,20 @@ struct boss_moam : public BossAI DoCastAOE(SPELL_SUMMON_MANA_FIENDS); DoCastSelf(SPELL_ENERGIZE); events.CancelEvent(EVENT_SPELL_DRAIN_MANA); - events.ScheduleEvent(EVENT_STONE_PHASE_END, 90000); + events.ScheduleEvent(EVENT_STONE_PHASE_END, 90s); break; case EVENT_STONE_PHASE_END: me->RemoveAurasDueToSpell(SPELL_ENERGIZE); - events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, urand(2000, 6000)); - events.ScheduleEvent(EVENT_STONE_PHASE, 90000); + events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, 2s, 6s); + events.ScheduleEvent(EVENT_STONE_PHASE, 90s); break; case EVENT_SPELL_DRAIN_MANA: DoCastAOE(SPELL_DRAIN_MANA_SERVERSIDE); - events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, urand(2000, 6000)); + events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, 2s, 6s); break; case EVENT_SPELL_TRAMPLE: DoCastAOE(SPELL_TRAMPLE); - events.ScheduleEvent(EVENT_SPELL_TRAMPLE, 15000); + events.ScheduleEvent(EVENT_SPELL_TRAMPLE, 15s); break; default: break; @@ -148,6 +148,11 @@ class spell_moam_mana_drain_filter : public SpellScript { return !target->IsPlayer() || target->ToPlayer()->getPowerType() != POWER_MANA; }); + + if (!targets.empty()) + { + Acore::Containers::RandomResize(targets, 6); + } } void HandleScript(SpellEffIndex /*effIndex*/) @@ -160,7 +165,7 @@ class spell_moam_mana_drain_filter : public SpellScript void Register() override { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_moam_mana_drain_filter::FilterTargets, EFFECT_ALL, TARGET_UNIT_DEST_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_moam_mana_drain_filter::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY); OnEffectHitTarget += SpellEffectFn(spell_moam_mana_drain_filter::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp index bfa85bc52..e61163f57 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp @@ -21,6 +21,7 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "SpellInfo.h" +#include "SpellScript.h" #include "ruins_of_ahnqiraj.h" #include "TaskScheduler.h" @@ -35,12 +36,20 @@ enum Texts enum Spells { - SPELL_CURSE_OF_TONGUES = 25195, - SPELL_ENVELOPING_WINDS = 25189, - SPELL_WAR_STOMP = 25188, - SPELL_STRENGHT_OF_OSSIRIAN = 25176, - SPELL_SAND_STORM = 25160, - SPELL_SUMMON_CRYSTAL = 25192 + SPELL_CURSE_OF_TONGUES = 25195, + SPELL_ENVELOPING_WINDS = 25189, + SPELL_WAR_STOMP = 25188, + SPELL_STRENGHT_OF_OSSIRIAN = 25176, + SPELL_SAND_STORM = 25160, + SPELL_SUMMON_CRYSTAL = 25192, + SPELL_SUMMON_SMALL_OBSIDIAN_CHUNK = 27627, // Server-side + + // Crystal + SPELL_FIRE_WEAKNESS = 25177, + SPELL_FROST_WEAKNESS = 25178, + SPELL_NATURE_WEAKNESS = 25180, + SPELL_ARCANE_WEAKNESS = 25181, + SPELL_SHADOW_WEAKNESS = 25183 }; enum Actions @@ -55,25 +64,27 @@ enum Events EVENT_STOMP = 3 }; -uint8 const NUM_CRYSTALS = 9; +uint8 const NUM_CRYSTALS = 11; Position CrystalCoordinates[NUM_CRYSTALS] = { - { -9394.230469f, 1951.808594f, 85.97733f, 0.0f }, - { -9357.931641f, 1930.596802f, 85.556198f, 0.0f }, - { -9383.113281f, 2011.042725f, 85.556389f, 0.0f }, - { -9243.36f, 1979.04f, 85.556f, 0.0f }, - { -9281.68f, 1886.66f, 85.5558f, 0.0f }, - { -9241.8f, 1806.39f, 85.5557f, 0.0f }, - { -9366.78f, 1781.76f, 85.5561f, 0.0f }, - { -9430.37f, 1786.86f, 85.557f, 0.0f }, - { -9406.73f, 1863.13f, 85.5558f, 0.0f } + { -9388.4404296875f, 1940.20996093750f, 85.6390991210937f, 3.17650008201599f }, + { -9357.8603515625f, 1929.07995605469f, 85.6390991210937f, 1.06465005874634f }, + { -9383.2900390625f, 2012.68005371094f, 85.6511001586914f, 2.93214988708496f }, + { -9248.4101562500f, 1974.82995605469f, 85.6390991210937f, 5.89920997619629f }, + { -9432.4003906250f, 1782.53002929687f, 85.6390991210937f, 5.86430978775024f }, + { -9299.7304687500f, 1748.44995117187f, 85.6390991210937f, 1.44861996173859f }, + { -9406.0996093750f, 1862.38000488281f, 85.6390991210937f, 6.23082017898560f }, + { -9506.1904296875f, 1865.56994628906f, 85.6390991210937f, 4.27606010437012f }, + { -9282.0800781250f, 1887.33996582031f, 85.6390991210937f, 2.00712990760803f }, + { -9244.4101562500f, 1808.97998046875f, 85.6390991210937f, 5.63741016387939f }, + { -9367.1699218750f, 1780.89001464844f, 85.6390991210937f, 1.90241003036499f } }; -float roomRadius = 165.0f; -uint8 const NUM_TORNADOS = 2; +Position initialCrystalPosition = { -9407.7197265625f, 1960.2099609375f, 85.6390991210937f, 1.11700999736786f }; + uint8 const NUM_WEAKNESS = 5; -uint32 const spellWeakness[NUM_WEAKNESS] = { 25177, 25178, 25180, 25181, 25183 }; -Position const RoomCenter = { -9343.041992f, 1923.278198f, 85.555984f, 0.0 }; +uint32 const spellWeakness[NUM_WEAKNESS] = +{ SPELL_FIRE_WEAKNESS, SPELL_FROST_WEAKNESS, SPELL_NATURE_WEAKNESS, SPELL_ARCANE_WEAKNESS, SPELL_SHADOW_WEAKNESS }; struct boss_ossirian : public BossAI { @@ -82,36 +93,103 @@ struct boss_ossirian : public BossAI _saidIntro = false; } - void Reset() override + void InitializeAI() override { - BossAI::Reset(); - _crystalIterator = 0; - _triggerGUID.Clear(); - _crystalGUID.Clear(); - } + Reset(); - void SpellHit(Unit* caster, SpellInfo const* spell) override - { - for (uint8 weakness : spellWeakness) + if (Creature* trigger = me->GetMap()->SummonCreature(NPC_OSSIRIAN_TRIGGER, initialCrystalPosition)) { - if (spell->Id == weakness) + _triggerGUID[0] = trigger->GetGUID(); + if (GameObject* crystal = trigger->SummonGameObject(GO_OSSIRIAN_CRYSTAL, + initialCrystalPosition.GetPositionX(), + initialCrystalPosition.GetPositionY(), + initialCrystalPosition.GetPositionZ(), + 0, 0, 0, 0, 0, uint32(-1))) { - me->RemoveAurasDueToSpell(SPELL_STRENGHT_OF_OSSIRIAN); - ((TempSummon*)caster)->UnSummon(); - SpawnNextCrystal(); + _crystalGUID[0] = crystal->GetGUID(); + crystal->SetOwnerGUID(ObjectGuid::Empty); + crystal->RemoveGameObjectFlag(GO_FLAG_IN_USE); } } } - void DoAction(int32 action) override + void Reset() override + { + BossAI::Reset(); + + _crystalIterator = urand(0, NUM_CRYSTALS - 1); + _triggerGUID[1].Clear(); + _crystalGUID[1].Clear(); + } + + void JustReachedHome() override + { + if (me->IsVisible()) + { + Creature* trigger = me->GetMap()->GetCreature(_triggerGUID[0]); + if (trigger) + { + trigger->DespawnOrUnsummon(); + if (GameObject* crystal = me->GetMap()->GetGameObject(_crystalGUID[0])) + crystal->Delete(); + } + + trigger = me->GetMap()->SummonCreature(NPC_OSSIRIAN_TRIGGER, initialCrystalPosition); + if (trigger) + { + _triggerGUID[0] = trigger->GetGUID(); + if (GameObject* crystal = trigger->SummonGameObject(GO_OSSIRIAN_CRYSTAL, + initialCrystalPosition.GetPositionX(), + initialCrystalPosition.GetPositionY(), + initialCrystalPosition.GetPositionZ(), + 0, 0, 0, 0, 0, uint32(-1))) + { + _crystalGUID[0] = crystal->GetGUID(); + crystal->SetOwnerGUID(ObjectGuid::Empty); + crystal->RemoveGameObjectFlag(GO_FLAG_IN_USE); + } + } + } + } + + void SpellHit(Unit* caster, SpellInfo const* spell) override + { + for (uint32 weakness : spellWeakness) + { + if (spell->Id == weakness) + { + me->RemoveAurasDueToSpell(SPELL_STRENGHT_OF_OSSIRIAN); + + if (caster->GetGUID() == _triggerGUID[1]) + { + if (Creature* creatureCaster = caster->ToCreature()) + { + creatureCaster->DespawnOrUnsummon(); + } + } + } + } + } + + void SetGUID(ObjectGuid guid, int32 action) override { if (action == ACTION_TRIGGER_WEAKNESS) { - if (Creature* trigger = me->GetMap()->GetCreature(_triggerGUID)) + for (uint8 i = 0; i < 2; ++i) { - if (!trigger->HasUnitState(UNIT_STATE_CASTING)) + if (_crystalGUID[i] == guid) { - trigger->CastSpell(trigger, spellWeakness[urand(0, 4)], false); + if (Creature* trigger = me->GetMap()->GetCreature(_triggerGUID[i])) + { + if (!trigger->HasUnitState(UNIT_STATE_CASTING)) + { + trigger->CastSpell(trigger, spellWeakness[urand(0, 4)], false); + } + } + + SpawnNextCrystal(); + + break; } } } @@ -133,77 +211,55 @@ struct boss_ossirian : public BossAI WorldPackets::Misc::Weather weather(WEATHER_STATE_HEAVY_SANDSTORM, 1.0f); map->SendToPlayers(weather.Write()); - for (uint8 i = 0; i < NUM_TORNADOS; ++i) - { - Position Point = me->GetRandomPoint(RoomCenter, roomRadius); - if (Creature* Tornado = me->GetMap()->SummonCreature(NPC_SAND_VORTEX, Point)) - { - Tornado->CastSpell(Tornado, SPELL_SAND_STORM, true); - } - } + SpawnNextCrystal(); } + void SummonedCreatureDespawn(Creature* summon) override + { + summons.Despawn(summon); + + if (GameObject* crystal = GetClosestGameObjectWithEntry(summon, GO_OSSIRIAN_CRYSTAL, 5.0f)) + { + crystal->Delete(); + } + } + void KilledUnit(Unit* /*victim*/) override { Talk(SAY_SLAY); } - void EnterEvadeMode(EvadeReason why) override - { - Cleanup(); - summons.DespawnAll(); - BossAI::EnterEvadeMode(why); - } - - void JustDied(Unit* killer) override - { - Cleanup(); - BossAI::JustDied(killer); - } - - void Cleanup() - { - if (GameObject* crystal = me->GetMap()->GetGameObject(_crystalGUID)) - { - crystal->Use(me); - } - - std::list vortexes; - me->GetCreaturesWithEntryInRange(vortexes, 200.f, NPC_SAND_VORTEX); - for (Creature* vortex : vortexes) - vortex->DespawnOrUnsummon(); - } - void SpawnNextCrystal() { if (_crystalIterator == NUM_CRYSTALS) _crystalIterator = 0; - if (Creature* trigger = me->GetMap()->SummonCreature(NPC_OSSIRIAN_TRIGGER, CrystalCoordinates[_crystalIterator])) + if (Creature* trigger = me->SummonCreature(NPC_OSSIRIAN_TRIGGER, CrystalCoordinates[_crystalIterator])) { - _triggerGUID = trigger->GetGUID(); + _triggerGUID[1] = trigger->GetGUID(); if (GameObject* crystal = trigger->SummonGameObject(GO_OSSIRIAN_CRYSTAL, CrystalCoordinates[_crystalIterator].GetPositionX(), CrystalCoordinates[_crystalIterator].GetPositionY(), CrystalCoordinates[_crystalIterator].GetPositionZ(), 0, 0, 0, 0, 0, uint32(-1))) { - _crystalGUID = crystal->GetGUID(); + _crystalGUID[1] = crystal->GetGUID(); ++_crystalIterator; crystal->SetOwnerGUID(ObjectGuid::Empty); + crystal->RemoveGameObjectFlag(GO_FLAG_IN_USE); } } } void MoveInLineOfSight(Unit* who) override - { if (!_saidIntro) { Talk(SAY_INTRO); _saidIntro = true; } + BossAI::MoveInLineOfSight(who); } @@ -220,7 +276,7 @@ struct boss_ossirian : public BossAI } else { - for (uint8 weakness : spellWeakness) + for (uint32 weakness : spellWeakness) { if (me->HasAura(weakness)) { @@ -260,8 +316,8 @@ struct boss_ossirian : public BossAI } protected: - ObjectGuid _triggerGUID; - ObjectGuid _crystalGUID; + std::array _triggerGUID; + std::array _crystalGUID; uint8 _crystalIterator; bool _saidIntro; }; @@ -271,18 +327,18 @@ class go_ossirian_crystal : public GameObjectScript public: go_ossirian_crystal() : GameObjectScript("go_ossirian_crystal") { } - bool OnGossipHello(Player* player, GameObject* /*go*/) override + bool OnGossipHello(Player* player, GameObject* go) override { InstanceScript* instance = player->GetInstanceScript(); if (!instance) - return false; + return true; Creature* ossirian = instance->GetCreature(DATA_OSSIRIAN); - if (!ossirian || instance->GetBossState(DATA_OSSIRIAN) != IN_PROGRESS) - return false; + if (!ossirian) + return true; - ossirian->AI()->DoAction(ACTION_TRIGGER_WEAKNESS); - return true; + ossirian->AI()->SetGUID(go->GetGUID(), ACTION_TRIGGER_WEAKNESS); + return false; } }; @@ -348,6 +404,11 @@ struct npc_anubisath_guardian : public ScriptedAI } } + void JustDied(Unit* /*killer*/) override + { + DoCastSelf(SPELL_SUMMON_SMALL_OBSIDIAN_CHUNK, true); + } + void UpdateAI(uint32 diff) override { if (!UpdateVictim()) @@ -363,9 +424,28 @@ private: TaskScheduler _scheduler; }; +class spell_crystal_weakness : public SpellScript +{ + PrepareSpellScript(spell_crystal_weakness); + + void FilterTargets(std::list& targets) + { + targets.remove_if([&](WorldObject const* target) -> bool + { + return target->GetEntry() != NPC_OSSIRIAN; + }); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_crystal_weakness::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENTRY); + } +}; + void AddSC_boss_ossirian() { RegisterRuinsOfAhnQirajCreatureAI(boss_ossirian); new go_ossirian_crystal(); RegisterCreatureAI(npc_anubisath_guardian); + RegisterSpellScript(spell_crystal_weakness); } diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_rajaxx.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_rajaxx.cpp index 2c648dfb0..6b543c55b 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_rajaxx.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_rajaxx.cpp @@ -46,71 +46,60 @@ enum Events EVENT_CHANGE_AGGRO = 3, }; -class boss_rajaxx : public CreatureScript +struct boss_rajaxx : public BossAI { -public: - boss_rajaxx() : CreatureScript("boss_rajaxx") { } + boss_rajaxx(Creature* creature) : BossAI(creature, DATA_RAJAXX) { } - struct boss_rajaxxAI : public BossAI + void Reset() override { - boss_rajaxxAI(Creature* creature) : BossAI(creature, DATA_RAJAXX) { } - - void Reset() override - { - _Reset(); - enraged = false; - } - - void JustDied(Unit* /*killer*/) override - { - Talk(SAY_DEATH); - _JustDied(); - } - - void EnterCombat(Unit* /*victim*/) override - { - _EnterCombat(); - events.ScheduleEvent(EVENT_DISARM, 10000); - events.ScheduleEvent(EVENT_THUNDERCRASH, 12000); - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_DISARM: - DoCastVictim(SPELL_DISARM); - events.ScheduleEvent(EVENT_DISARM, 22000); - break; - case EVENT_THUNDERCRASH: - DoCast(me, SPELL_THUNDERCRASH); - events.ScheduleEvent(EVENT_THUNDERCRASH, 21000); - break; - default: - break; - } - } - - DoMeleeAttackIfReady(); - } - private: - bool enraged; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetRuinsOfAhnQirajAI(creature); + BossAI::Reset(); + enraged = false; } + + void JustDied(Unit* /*killer*/) override + { + Talk(SAY_DEATH); + _JustDied(); + } + + void EnterCombat(Unit* /*victim*/) override + { + _EnterCombat(); + events.ScheduleEvent(EVENT_DISARM, 10s); + events.ScheduleEvent(EVENT_THUNDERCRASH, 12s); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_DISARM: + DoCastVictim(SPELL_DISARM); + events.ScheduleEvent(EVENT_DISARM, 22s); + break; + case EVENT_THUNDERCRASH: + DoCastSelf(SPELL_THUNDERCRASH); + events.ScheduleEvent(EVENT_THUNDERCRASH, 21s); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } +private: + bool enraged; }; class spell_rajaxx_thundercrash : public SpellScript @@ -136,6 +125,6 @@ class spell_rajaxx_thundercrash : public SpellScript void AddSC_boss_rajaxx() { - new boss_rajaxx(); + RegisterRuinsOfAhnQirajCreatureAI(boss_rajaxx); RegisterSpellScript(spell_rajaxx_thundercrash); } diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp index aa088d091..c5ac1d205 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp @@ -26,6 +26,7 @@ ObjectData const creatureData[] = { NPC_BURU, DATA_BURU }, { NPC_KURINNAXX, DATA_KURINNAXX }, { NPC_RAJAXX, DATA_RAJAXX }, + { NPC_AYAMISS, DATA_AYAMISS }, { NPC_OSSIRIAN, DATA_OSSIRIAN }, { NPC_QUUEZ, DATA_QUUEZ }, { NPC_TUUBID, DATA_TUUBID }, @@ -36,14 +37,17 @@ ObjectData const creatureData[] = { NPC_ZERRAN, DATA_ZERRAN }, }; -enum RajaxxText +enum RajaxxWaveEvent { SAY_WAVE3 = 0, SAY_WAVE4 = 1, SAY_WAVE5 = 2, SAY_WAVE6 = 3, SAY_WAVE7 = 4, - SAY_ENGAGE = 5 + SAY_ENGAGE = 5, + + DATA_RAJAXX_WAVE_ENGAGED = 1, + GROUP_RAJAXX_WAVE_TIMER = 1 }; std::array RajaxxWavesData[] = @@ -90,12 +94,13 @@ public: case NPC_BURU: _buruGUID = creature->GetGUID(); break; - case NPC_AYAMISS: - _ayamissGUID = creature->GetGUID(); - break; case NPC_OSSIRIAN: _ossirianGUID = creature->GetGUID(); break; + case NPC_SAND_VORTEX: + _sandVortexes.push_back(creature->GetGUID()); + creature->SetVisible(false); + break; } } @@ -130,6 +135,20 @@ public: } } + void SetData(uint32 type, uint32 /*data*/) override + { + if (type == DATA_RAJAXX_WAVE_ENGAGED) + { + _scheduler.CancelGroup(GROUP_RAJAXX_WAVE_TIMER); + _scheduler.Schedule(2min, [this](TaskContext context) + { + CallNextRajaxxLeader(); + context.SetGroup(GROUP_RAJAXX_WAVE_TIMER); + context.Repeat(); + }); + } + } + void OnUnitDeath(Unit* unit) override { if (Creature* creature = unit->ToCreature()) @@ -151,7 +170,7 @@ public: _scheduler.Schedule(1s, [this, formation](TaskContext /*context*/) { if (!formation->IsAnyMemberAlive()) { - CallNextRajaxxLeader(); + CallNextRajaxxLeader(true); } }); break; @@ -174,6 +193,31 @@ public: _paralyzedGUID = data; } + bool SetBossState(uint32 type, EncounterState state) override + { + if (!InstanceScript::SetBossState(type, state)) + return false; + + switch (type) + { + case DATA_OSSIRIAN: + { + for (ObjectGuid const& guid : _sandVortexes) + { + if (Creature* sandVortex = instance->GetCreature(guid)) + { + sandVortex->SetVisible(state == IN_PROGRESS); + } + } + break; + default: + break; + } + } + + return true; + } + ObjectGuid GetGuidData(uint32 type) const override { switch (type) @@ -186,8 +230,6 @@ public: return _moamGUID; case DATA_BURU: return _buruGUID; - case DATA_AYAMISS: - return _ayamissGUID; case DATA_OSSIRIAN: return _ossirianGUID; case DATA_PARALYZED: @@ -240,17 +282,20 @@ public: OUT_LOAD_INST_DATA_COMPLETE; } - void CallNextRajaxxLeader() + void CallNextRajaxxLeader(bool announce = false) { ++_rajaxWaveCounter; if (Creature* nextLeader = GetCreature(RajaxxWavesData[_rajaxWaveCounter].at(0))) { - if (_rajaxWaveCounter >= 2) + if (announce) { - if (Creature* rajaxx = GetCreature(DATA_RAJAXX)) + if (_rajaxWaveCounter >= 2) { - rajaxx->AI()->Talk(RajaxxWavesData[_rajaxWaveCounter].at(1)); + if (Creature* rajaxx = GetCreature(DATA_RAJAXX)) + { + rajaxx->AI()->Talk(RajaxxWavesData[_rajaxWaveCounter].at(1)); + } } } @@ -268,6 +313,7 @@ public: void ResetRajaxxWaves() { _rajaxWaveCounter = 0; + _scheduler.CancelAll(); for (auto const& data : RajaxxWavesData) { if (Creature* creature = GetCreature(data.at(0))) @@ -285,9 +331,9 @@ public: ObjectGuid _rajaxxGUID; ObjectGuid _moamGUID; ObjectGuid _buruGUID; - ObjectGuid _ayamissGUID; ObjectGuid _ossirianGUID; ObjectGuid _paralyzedGUID; + GuidVector _sandVortexes; uint32 _rajaxWaveCounter; TaskScheduler _scheduler; }; diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.cpp new file mode 100644 index 000000000..5675b922a --- /dev/null +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.cpp @@ -0,0 +1,86 @@ +/* + * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by the + * Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ruins_of_ahnqiraj.h" +#include "TaskScheduler.h" + +enum Spells +{ + SPELL_HIVEZARA_CATALYST = 25187, + SPELL_STINGER_CHARGE_NORMAL = 25190, + SPELL_STINGER_CHARGE_BUFFED = 25191 +}; + +struct npc_hivezara_stinger : public ScriptedAI +{ + npc_hivezara_stinger(Creature* creature) : ScriptedAI(creature) + { + } + + void Reset() override + { + _scheduler.CancelAll(); + } + + void EnterCombat(Unit* who) override + { + DoCast(who ,who->HasAura(SPELL_HIVEZARA_CATALYST) ? SPELL_STINGER_CHARGE_BUFFED : SPELL_STINGER_CHARGE_NORMAL, true); + + _scheduler.Schedule(5s, [this](TaskContext context) + { + Unit* target = SelectTarget(SelectTargetMethod::Random, 1, [&](Unit* u) + { + return u && !u->IsPet() && u->IsWithinDist2d(me, 20.f) && u->HasAura(SPELL_HIVEZARA_CATALYST); + }); + if (!target) + { + target = SelectTarget(SelectTargetMethod::Random, 1, [&](Unit* u) + { + return u && !u->IsPet() && u->IsWithinDist2d(me, 20.f); + }); + } + + if (target) + { + DoCast(target, target->HasAura(SPELL_HIVEZARA_CATALYST) ? SPELL_STINGER_CHARGE_BUFFED : SPELL_STINGER_CHARGE_NORMAL, true); + } + + context.Repeat(4500ms, 6500ms); + }); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + { + return; + } + + _scheduler.Update(diff, + std::bind(&ScriptedAI::DoMeleeAttackIfReady, this)); + } + +private: + TaskScheduler _scheduler; +}; + +void AddSC_ruins_of_ahnqiraj() +{ + RegisterRuinsOfAhnQirajCreatureAI(npc_hivezara_stinger); +} diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h index 522b70c78..418c9edbe 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h @@ -60,9 +60,6 @@ enum Creatures NPC_OSSIRIAN_TRIGGER = 15590, NPC_HATCHLING = 15521, NPC_BURU_EGG = 15514, - NPC_LARVA = 15555, - NPC_SWARMER = 15546, - NPC_HORNET = 15934, // Rajaxx NPC_QUUEZ = 15391, diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp index cf765b460..c57a95144 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp @@ -137,9 +137,9 @@ public: me->SetReactState(REACT_PASSIVE); } - void MovementInform(uint32 type, uint32 /*id*/) override + void MovementInform(uint32 type, uint32 id) override { - if (type != POINT_MOTION_TYPE) + if (type != POINT_MOTION_TYPE || id != POINT_CONSUME) return; me->GetMotionMaster()->MoveIdle(); @@ -153,6 +153,7 @@ public: me->SetReactState(REACT_AGGRESSIVE); if (Unit* target = me->GetVictim()) { + me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveChase(target); AttackStart(target); } @@ -195,7 +196,7 @@ public: void DamageTaken(Unit* who, uint32& damage, DamageEffectType, SpellSchoolMask) override { - if (me->HealthBelowPctDamaged(1, damage) && instance->GetData(DATA_BUG_TRIO_DEATH) < 2 && who->GetGUID() != me->GetGUID()) + if (me->HealthBelowPctDamaged(1, damage) && instance->GetData(DATA_BUG_TRIO_DEATH) < 2 && who->GetGUID() != me->GetGUID() && !dying) { damage = 0; if (isEating) @@ -205,6 +206,7 @@ public: me->SetStandState(UNIT_STAND_STATE_DEAD); me->SetReactState(REACT_PASSIVE); me->SetControlled(true, UNIT_STATE_ROOT); + dying = true; DoFinalSpell(); @@ -236,7 +238,7 @@ public: _scheduler.Schedule(4s, [this](TaskContext /*context*/) { - if (!me->IsInEvadeMode()) + if (!me->IsInEvadeMode() && instance->GetData(DATA_BUG_TRIO_DEATH) < 2) { DoCastSelf(SPELL_BLOODY_DEATH, true); Talk(EMOTE_DEVOURED); @@ -452,9 +454,9 @@ class spell_vem_vengeance : public SpellScript void AddSC_bug_trio() { - RegisterCreatureAI(boss_kri); - RegisterCreatureAI(boss_vem); - RegisterCreatureAI(boss_yauj); + RegisterTempleOfAhnQirajCreatureAI(boss_kri); + RegisterTempleOfAhnQirajCreatureAI(boss_vem); + RegisterTempleOfAhnQirajCreatureAI(boss_yauj); RegisterSpellScript(spell_vem_knockback); RegisterSpellScript(spell_vem_vengeance); } diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp index 66211a1b0..778daca97 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp @@ -142,93 +142,85 @@ public: //Kick out position const Position KickPos = { -8545.0f, 1984.0f, -96.0f, 0.0f}; -class boss_eye_of_cthun : public CreatureScript +struct boss_eye_of_cthun : public ScriptedAI { -public: - boss_eye_of_cthun() : CreatureScript("boss_eye_of_cthun") { } - - CreatureAI* GetAI(Creature* creature) const override + boss_eye_of_cthun(Creature* creature) : ScriptedAI(creature), _summons(creature) { - return GetTempleOfAhnQirajAI(creature); + instance = creature->GetInstanceScript(); + + SetCombatMovement(false); } - struct eye_of_cthunAI : public ScriptedAI + void Reset() override { - eye_of_cthunAI(Creature* creature) : ScriptedAI(creature), _summons(creature) + //Dark Beam phase 35 seconds (each tick = 1 second, 35 ticks) + DarkGlareTick = 0; + DarkGlareAngle = 0; + ClockWise = false; + + _eyeTentacleCounter = 0; + + //Reset flags + me->RemoveAurasDueToSpell(SPELL_RED_COLORATION); + me->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM); + me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + me->SetVisible(true); + + //Reset Phase + instance->SetData(DATA_CTHUN_PHASE, PHASE_NOT_STARTED); + + //to avoid having a following void zone + Creature* pPortal = me->FindNearestCreature(NPC_CTHUN_PORTAL, 10); + if (pPortal) + pPortal->SetReactState(REACT_PASSIVE); + + _summons.DespawnAll(); + _scheduler.CancelAll(); + } + + void EnterCombat(Unit* /*who*/) override + { + DoZoneInCombat(); + ScheduleTasks(); + instance->SetData(DATA_CTHUN_PHASE, PHASE_EYE_GREEN_BEAM); + } + + void MoveInLineOfSight(Unit* who) override + { + if (who->GetTypeId() == TYPEID_PLAYER && !me->IsInCombat()) { - instance = creature->GetInstanceScript(); - - SetCombatMovement(false); - } - - void Reset() override - { - //Dark Beam phase 35 seconds (each tick = 1 second, 35 ticks) - DarkGlareTick = 0; - DarkGlareAngle = 0; - ClockWise = false; - - _eyeTentacleCounter = 0; - - //Reset flags - me->RemoveAurasDueToSpell(SPELL_RED_COLORATION); - me->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM); - me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - me->SetVisible(true); - - //Reset Phase - instance->SetData(DATA_CTHUN_PHASE, PHASE_NOT_STARTED); - - //to avoid having a following void zone - Creature* pPortal = me->FindNearestCreature(NPC_CTHUN_PORTAL, 10); - if (pPortal) - pPortal->SetReactState(REACT_PASSIVE); - - _summons.DespawnAll(); - _scheduler.CancelAll(); - } - - void EnterCombat(Unit* /*who*/) override - { - DoZoneInCombat(); - ScheduleTasks(); - instance->SetData(DATA_CTHUN_PHASE, PHASE_EYE_GREEN_BEAM); - } - - void MoveInLineOfSight(Unit* who) override - { - if (who->GetTypeId() == TYPEID_PLAYER && !me->IsInCombat()) + // Z checks are necessary here because AQ maps do funky stuff. + if (me->IsWithinLOSInMap(who) && me->IsWithinDist2d(who, 50.0f) && who->GetPositionZ() > 100.0f) { - // Z checks are necessary here because AQ maps do funky stuff. - if (me->IsWithinLOSInMap(who) && me->IsWithinDist2d(who, 50.0f) && who->GetPositionZ() > 100.0f) - { - AttackStart(who); - } + AttackStart(who); } } + } - void DoAction(int32 action) override + void DoAction(int32 action) override + { + if (action == ACTION_SPAWN_EYE_TENTACLES) { - if (action == ACTION_SPAWN_EYE_TENTACLES) - { - me->SummonCreatureGroup(_eyeTentacleCounter); - _eyeTentacleCounter++; + me->SummonCreatureGroup(_eyeTentacleCounter); + _eyeTentacleCounter++; - if (_eyeTentacleCounter >= MAX_TENTACLE_GROUPS) - { - _eyeTentacleCounter = 0; - } + if (_eyeTentacleCounter >= MAX_TENTACLE_GROUPS) + { + _eyeTentacleCounter = 0; } } + } - void ScheduleTasks() - { - _scheduler.Schedule(3s, [this](TaskContext task) + void ScheduleTasks() + { + _scheduler. + Schedule(3s, [this](TaskContext task) { DoCastRandomTarget(SPELL_GREEN_BEAM); task.SetGroup(GROUP_BEAM_PHASE); task.Repeat(); - }).Schedule(12s, [this](TaskContext task) + }) + .Schedule(12s, [this](TaskContext task) { if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true)) { @@ -240,12 +232,14 @@ public: task.SetGroup(GROUP_BEAM_PHASE); task.Repeat(); - }).Schedule(45s, [this](TaskContext task) + }) + .Schedule(45s, [this](TaskContext task) { DoAction(ACTION_SPAWN_EYE_TENTACLES); task.SetGroup(GROUP_BEAM_PHASE); task.Repeat(); - }).Schedule(50s, [this](TaskContext /*task*/) + }) + .Schedule(50s, [this](TaskContext /*task*/) { _scheduler.CancelGroup(GROUP_BEAM_PHASE); @@ -311,340 +305,366 @@ public: }); }); }); - } - - void JustSummoned(Creature* summon) override - { - _summons.Summon(summon); - summon->SetInCombatWithZone(); - } - - void UpdateAI(uint32 diff) override - { - //Check if we have a target - if (!UpdateVictim()) - return; - - switch (instance->GetData(DATA_CTHUN_PHASE)) - { - //Transition phase - case PHASE_CTHUN_TRANSITION: - //Remove any target - me->SetTarget(); - me->SetHealth(0); - me->SetVisible(false); - break; - - //Dead phase - case PHASE_CTHUN_DONE: - if (Creature* pPortal = me->FindNearestCreature(NPC_CTHUN_PORTAL, 10)) - { - pPortal->DespawnOrUnsummon(); - } - - me->DespawnOrUnsummon(); - break; - } - - _scheduler.Update(diff); - } - - void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override - { - switch (instance->GetData(DATA_CTHUN_PHASE)) - { - case PHASE_EYE_GREEN_BEAM: - case PHASE_EYE_RED_BEAM: - //Only if it will kill - if (damage < me->GetHealth()) - return; - - //Fake death in phase 0 or 1 (green beam or dark glare phase) - me->InterruptNonMeleeSpells(false); - - //Remove Red coloration from c'thun - me->RemoveAurasDueToSpell(SPELL_RED_COLORATION); - - //Reset to normal emote state and prevent select and attack - me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - - //Remove Target field - me->SetTarget(); - - //Death animation/respawning; - instance->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_TRANSITION); - - me->SetHealth(0); - damage = 0; - - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - _scheduler.CancelAll(); - break; - - case PHASE_CTHUN_DONE: - //Allow death here - return; - - default: - //Prevent death in these phases - damage = 0; - return; - } - } - - private: - InstanceScript* instance; - - //Dark Glare phase - uint32 DarkGlareTick; - float DarkGlareAngle; - bool ClockWise; - - uint32 _eyeTentacleCounter; - TaskScheduler _scheduler; - SummonList _summons; - }; -}; - -class boss_cthun : public CreatureScript -{ -public: - boss_cthun() : CreatureScript("boss_cthun") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetTempleOfAhnQirajAI(creature); } - struct cthunAI : public ScriptedAI + void JustSummoned(Creature* summon) override { - cthunAI(Creature* creature) : ScriptedAI(creature) - { - SetCombatMovement(false); + _summons.Summon(summon); + summon->SetInCombatWithZone(); + } - instance = creature->GetInstanceScript(); + void UpdateAI(uint32 diff) override + { + //Check if we have a target + if (!UpdateVictim()) + return; + + switch (instance->GetData(DATA_CTHUN_PHASE)) + { + //Transition phase + case PHASE_CTHUN_TRANSITION: + //Remove any target + me->SetTarget(); + me->SetHealth(0); + me->SetVisible(false); + break; + + //Dead phase + case PHASE_CTHUN_DONE: + if (Creature* pPortal = me->FindNearestCreature(NPC_CTHUN_PORTAL, 10)) + { + pPortal->DespawnOrUnsummon(); + } + + me->DespawnOrUnsummon(); + break; } - InstanceScript* instance; + _scheduler.Update(diff); + } - //Out of combat whisper timer - uint32 WisperTimer; + void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override + { + switch (instance->GetData(DATA_CTHUN_PHASE)) + { + case PHASE_EYE_GREEN_BEAM: + case PHASE_EYE_RED_BEAM: + //Only if it will kill + if (damage < me->GetHealth()) + return; - //Global variables - uint32 PhaseTimer; + //Fake death in phase 0 or 1 (green beam or dark glare phase) + me->InterruptNonMeleeSpells(false); - //------------------- + //Remove Red coloration from c'thun + me->RemoveAurasDueToSpell(SPELL_RED_COLORATION); - //Phase transition - ObjectGuid HoldPlayer; + //Reset to normal emote state and prevent select and attack + me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + + //Remove Target field + me->SetTarget(); + + //Death animation/respawning; + instance->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_TRANSITION); + + me->SetHealth(0); + damage = 0; + + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + _scheduler.CancelAll(); + break; + + case PHASE_CTHUN_DONE: + //Allow death here + return; + + default: + //Prevent death in these phases + damage = 0; + return; + } + } + +private: + InstanceScript* instance; + + //Dark Glare phase + uint32 DarkGlareTick; + float DarkGlareAngle; + bool ClockWise; + + uint32 _eyeTentacleCounter; + TaskScheduler _scheduler; + SummonList _summons; +}; + +struct boss_cthun : public ScriptedAI +{ + boss_cthun(Creature* creature) : ScriptedAI(creature) + { + SetCombatMovement(false); + + instance = creature->GetInstanceScript(); + } + + InstanceScript* instance; + + //Out of combat whisper timer + uint32 WisperTimer; + + //Global variables + uint32 PhaseTimer; + + //------------------- + + //Phase transition + ObjectGuid HoldPlayer; + + //Body Phase + uint32 EyeTentacleTimer; + uint8 FleshTentaclesKilled; + uint32 GiantClawTentacleTimer; + uint32 GiantEyeTentacleTimer; + uint32 StomachAcidTimer; + uint32 StomachEnterTimer; + uint32 StomachEnterVisTimer; + ObjectGuid StomachEnterTarget; + + //Stomach map, bool = true then in stomach + std::unordered_map Stomach_Map; + + void Reset() override + { + //One random wisper every 90 - 300 seconds + WisperTimer = 90000; + + //Phase information + PhaseTimer = 10000; //Emerge in 10 seconds + + //No hold player for transition + HoldPlayer.Clear(); //Body Phase - uint32 EyeTentacleTimer; - uint8 FleshTentaclesKilled; - uint32 GiantClawTentacleTimer; - uint32 GiantEyeTentacleTimer; - uint32 StomachAcidTimer; - uint32 StomachEnterTimer; - uint32 StomachEnterVisTimer; - ObjectGuid StomachEnterTarget; + EyeTentacleTimer = 30000; + FleshTentaclesKilled = 0; + GiantClawTentacleTimer = 15000; //15 seconds into body phase (1 min repeat) + GiantEyeTentacleTimer = 45000; //15 seconds into body phase (1 min repeat) + StomachAcidTimer = 4000; //Every 4 seconds + StomachEnterTimer = 10000; //Every 10 seconds + StomachEnterVisTimer = 0; //Always 3.5 seconds after Stomach Enter Timer + StomachEnterTarget.Clear(); //Target to be teleported to stomach - //Stomach map, bool = true then in stomach - std::unordered_map Stomach_Map; + //Clear players in stomach and outside + Stomach_Map.clear(); - void Reset() override + //Reset flags + me->RemoveAurasDueToSpell(SPELL_TRANSFORM); + me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + me->SetVisible(false); + + instance->SetData(DATA_CTHUN_PHASE, PHASE_NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) override + { + DoZoneInCombat(); + } + + Unit* SelectRandomNotStomach() + { + if (Stomach_Map.empty()) + return nullptr; + + std::unordered_map::const_iterator i = Stomach_Map.begin(); + + std::list temp; + std::list::const_iterator j; + + //Get all players in map + while (i != Stomach_Map.end()) { - //One random wisper every 90 - 300 seconds - WisperTimer = 90000; + //Check for valid player + Unit* unit = ObjectAccessor::GetUnit(*me, i->first); - //Phase information - PhaseTimer = 10000; //Emerge in 10 seconds + //Only units out of stomach + if (unit && !i->second) + temp.push_back(unit); - //No hold player for transition - HoldPlayer.Clear(); - - //Body Phase - EyeTentacleTimer = 30000; - FleshTentaclesKilled = 0; - GiantClawTentacleTimer = 15000; //15 seconds into body phase (1 min repeat) - GiantEyeTentacleTimer = 45000; //15 seconds into body phase (1 min repeat) - StomachAcidTimer = 4000; //Every 4 seconds - StomachEnterTimer = 10000; //Every 10 seconds - StomachEnterVisTimer = 0; //Always 3.5 seconds after Stomach Enter Timer - StomachEnterTarget.Clear(); //Target to be teleported to stomach - - //Clear players in stomach and outside - Stomach_Map.clear(); - - //Reset flags - me->RemoveAurasDueToSpell(SPELL_TRANSFORM); - me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - me->SetVisible(false); - - instance->SetData(DATA_CTHUN_PHASE, PHASE_NOT_STARTED); + ++i; } - void EnterCombat(Unit* /*who*/) override + if (temp.empty()) + return nullptr; + + j = temp.begin(); + + //Get random but only if we have more than one unit on threat list + if (temp.size() > 1) + advance(j, rand() % (temp.size() - 1)); + + return (*j); + } + + void UpdateAI(uint32 diff) override + { + //Check if we have a target + if (!UpdateVictim()) { - DoZoneInCombat(); - } - - Unit* SelectRandomNotStomach() - { - if (Stomach_Map.empty()) - return nullptr; - - std::unordered_map::const_iterator i = Stomach_Map.begin(); - - std::list temp; - std::list::const_iterator j; - - //Get all players in map - while (i != Stomach_Map.end()) + //No target so we'll use this section to do our random wispers instance wide + //WisperTimer + if (WisperTimer <= diff) { - //Check for valid player - Unit* unit = ObjectAccessor::GetUnit(*me, i->first); + Map* map = me->GetMap(); + if (!map->IsDungeon()) + return; - //Only units out of stomach - if (unit && !i->second) - temp.push_back(unit); + //Play random sound to the zone + Map::PlayerList const& PlayerList = map->GetPlayers(); - ++i; - } - - if (temp.empty()) - return nullptr; - - j = temp.begin(); - - //Get random but only if we have more than one unit on threat list - if (temp.size() > 1) - advance (j, rand() % (temp.size() - 1)); - - return (*j); - } - - void UpdateAI(uint32 diff) override - { - //Check if we have a target - if (!UpdateVictim()) - { - //No target so we'll use this section to do our random wispers instance wide - //WisperTimer - if (WisperTimer <= diff) + if (!PlayerList.IsEmpty()) { - Map* map = me->GetMap(); - if (!map->IsDungeon()) - return; - - //Play random sound to the zone - Map::PlayerList const& PlayerList = map->GetPlayers(); - - if (!PlayerList.IsEmpty()) + for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) { - for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) - { - if (Player* pPlr = itr->GetSource()) - pPlr->PlayDirectSound(RANDOM_SOUND_WHISPER, pPlr); - } + if (Player* pPlr = itr->GetSource()) + pPlr->PlayDirectSound(RANDOM_SOUND_WHISPER, pPlr); } - - //One random wisper every 90 - 300 seconds - WisperTimer = urand(90000, 300000); } - else WisperTimer -= diff; - return; + //One random wisper every 90 - 300 seconds + WisperTimer = urand(90000, 300000); } + else WisperTimer -= diff; - me->SetTarget(); + return; + } - uint32 currentPhase = instance->GetData(DATA_CTHUN_PHASE); - if (currentPhase == PHASE_CTHUN_STOMACH || currentPhase == PHASE_CTHUN_WEAK) + me->SetTarget(); + + uint32 currentPhase = instance->GetData(DATA_CTHUN_PHASE); + if (currentPhase == PHASE_CTHUN_STOMACH || currentPhase == PHASE_CTHUN_WEAK) + { + // EyeTentacleTimer + if (EyeTentacleTimer <= diff) { - // EyeTentacleTimer - if (EyeTentacleTimer <= diff) + if (Creature* eye = instance->GetCreature(DATA_EYE_OF_CTHUN)) { - if (Creature* eye = instance->GetCreature(DATA_EYE_OF_CTHUN)) - { - eye->AI()->DoAction(ACTION_SPAWN_EYE_TENTACLES); - } - - EyeTentacleTimer = 30000; // every 30sec in phase 2 + eye->AI()->DoAction(ACTION_SPAWN_EYE_TENTACLES); } - else EyeTentacleTimer -= diff; - } - switch (currentPhase) - { + EyeTentacleTimer = 30000; // every 30sec in phase 2 + } + else EyeTentacleTimer -= diff; + } + + switch (currentPhase) + { //Transition phase - case PHASE_CTHUN_TRANSITION: - //PhaseTimer - if (PhaseTimer <= diff) + case PHASE_CTHUN_TRANSITION: + //PhaseTimer + if (PhaseTimer <= diff) + { + //Switch + instance->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_STOMACH); + + //Switch to c'thun model + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_TRANSFORM, false); + me->SetFullHealth(); + + me->SetVisible(true); + me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + + //Emerging phase + //AttackStart(ObjectAccessor::GetUnit(*me, HoldpPlayer)); + DoZoneInCombat(); + + //Place all units in threat list on outside of stomach + Stomach_Map.clear(); + + for (std::list::const_iterator i = me->GetThreatMgr().getThreatList().begin(); i != me->GetThreatMgr().getThreatList().end(); ++i) + Stomach_Map[(*i)->getUnitGuid()] = false; //Outside stomach + + //Spawn 2 flesh tentacles + FleshTentaclesKilled = 0; + + //Spawn flesh tentacle + for (uint8 i = 0; i < 2; i++) { - //Switch - instance->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_STOMACH); - - //Switch to c'thun model - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_TRANSFORM, false); - me->SetFullHealth(); - - me->SetVisible(true); - me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - - //Emerging phase - //AttackStart(ObjectAccessor::GetUnit(*me, HoldpPlayer)); - DoZoneInCombat(); - - //Place all units in threat list on outside of stomach - Stomach_Map.clear(); - - for (std::list::const_iterator i = me->GetThreatMgr().getThreatList().begin(); i != me->GetThreatMgr().getThreatList().end(); ++i) - Stomach_Map[(*i)->getUnitGuid()] = false; //Outside stomach - - //Spawn 2 flesh tentacles - FleshTentaclesKilled = 0; - - //Spawn flesh tentacle - for (uint8 i = 0; i < 2; i++) - { - Creature* spawned = me->SummonCreature(NPC_FLESH_TENTACLE, FleshTentaclePos[i], TEMPSUMMON_CORPSE_DESPAWN); - if (!spawned) - ++FleshTentaclesKilled; - } - - PhaseTimer = 0; + Creature* spawned = me->SummonCreature(NPC_FLESH_TENTACLE, FleshTentaclePos[i], TEMPSUMMON_CORPSE_DESPAWN); + if (!spawned) + ++FleshTentaclesKilled; } - else PhaseTimer -= diff; - break; + PhaseTimer = 0; + } + else PhaseTimer -= diff; + + break; //Body Phase - case PHASE_CTHUN_STOMACH: - //Remove Target field - me->SetTarget(); + case PHASE_CTHUN_STOMACH: + //Remove Target field + me->SetTarget(); - //Weaken - if (FleshTentaclesKilled > 1) + //Weaken + if (FleshTentaclesKilled > 1) + { + instance->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_WEAK); + + Talk(EMOTE_WEAKENED); + PhaseTimer = 45000; + + DoCast(me, SPELL_PURPLE_COLORATION, true); + + std::unordered_map::iterator i = Stomach_Map.begin(); + + //Kick all players out of stomach + while (i != Stomach_Map.end()) { - instance->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_WEAK); + //Check for valid player + Unit* unit = ObjectAccessor::GetUnit(*me, i->first); - Talk(EMOTE_WEAKENED); - PhaseTimer = 45000; - - DoCast(me, SPELL_PURPLE_COLORATION, true); - - std::unordered_map::iterator i = Stomach_Map.begin(); - - //Kick all players out of stomach - while (i != Stomach_Map.end()) + //Only move units in stomach + if (unit && i->second) { - //Check for valid player - Unit* unit = ObjectAccessor::GetUnit(*me, i->first); + //Teleport each player out + DoTeleportPlayer(unit, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 10, float(rand() % 6)); - //Only move units in stomach - if (unit && i->second) + //Cast knockback on them + DoCast(unit, SPELL_EXIT_STOMACH_KNOCKBACK, true); + + //Remove the acid debuff + unit->RemoveAurasDueToSpell(SPELL_DIGESTIVE_ACID); + + i->second = false; + } + ++i; + } + + return; + } + + //Stomach acid + if (StomachAcidTimer <= diff) + { + //Apply aura to all players in stomach + std::unordered_map::iterator i = Stomach_Map.begin(); + + while (i != Stomach_Map.end()) + { + //Check for valid player + Unit* unit = ObjectAccessor::GetUnit(*me, i->first); + + //Only apply to units in stomach + if (unit && i->second) + { + //Cast digestive acid on them + DoCast(unit, SPELL_DIGESTIVE_ACID, true); + + //Check if player should be kicked from stomach + if (unit->IsWithinDist3d(&KickPos, 15.0f)) { //Teleport each player out DoTeleportPlayer(unit, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 10, float(rand() % 6)); @@ -657,388 +677,321 @@ public: i->second = false; } - ++i; } - - return; + ++i; } - //Stomach acid - if (StomachAcidTimer <= diff) + StomachAcidTimer = 4000; + } + else StomachAcidTimer -= diff; + + //Stomach Enter Timer + if (StomachEnterTimer <= diff) + { + if (Unit* target = SelectRandomNotStomach()) { - //Apply aura to all players in stomach - std::unordered_map::iterator i = Stomach_Map.begin(); - - while (i != Stomach_Map.end()) - { - //Check for valid player - Unit* unit = ObjectAccessor::GetUnit(*me, i->first); - - //Only apply to units in stomach - if (unit && i->second) - { - //Cast digestive acid on them - DoCast(unit, SPELL_DIGESTIVE_ACID, true); - - //Check if player should be kicked from stomach - if (unit->IsWithinDist3d(&KickPos, 15.0f)) - { - //Teleport each player out - DoTeleportPlayer(unit, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 10, float(rand() % 6)); - - //Cast knockback on them - DoCast(unit, SPELL_EXIT_STOMACH_KNOCKBACK, true); - - //Remove the acid debuff - unit->RemoveAurasDueToSpell(SPELL_DIGESTIVE_ACID); - - i->second = false; - } - } - ++i; - } - - StomachAcidTimer = 4000; + //Set target in stomach + Stomach_Map[target->GetGUID()] = true; + target->InterruptNonMeleeSpells(false); + target->CastSpell(target, SPELL_MOUTH_TENTACLE, true, nullptr, nullptr, me->GetGUID()); + StomachEnterTarget = target->GetGUID(); + StomachEnterVisTimer = 3800; } - else StomachAcidTimer -= diff; - //Stomach Enter Timer - if (StomachEnterTimer <= diff) + StomachEnterTimer = 13800; + } + else StomachEnterTimer -= diff; + + if (StomachEnterVisTimer && StomachEnterTarget) + { + if (StomachEnterVisTimer <= diff) { - if (Unit* target = SelectRandomNotStomach()) + //Check for valid player + Unit* unit = ObjectAccessor::GetUnit(*me, StomachEnterTarget); + + if (unit) { - //Set target in stomach - Stomach_Map[target->GetGUID()] = true; - target->InterruptNonMeleeSpells(false); - target->CastSpell(target, SPELL_MOUTH_TENTACLE, true, nullptr, nullptr, me->GetGUID()); - StomachEnterTarget = target->GetGUID(); - StomachEnterVisTimer = 3800; + DoTeleportPlayer(unit, STOMACH_X, STOMACH_Y, STOMACH_Z, STOMACH_O); } - StomachEnterTimer = 13800; + StomachEnterTarget.Clear(); + StomachEnterVisTimer = 0; } - else StomachEnterTimer -= diff; + else StomachEnterVisTimer -= diff; + } - if (StomachEnterVisTimer && StomachEnterTarget) + //GientClawTentacleTimer + if (GiantClawTentacleTimer <= diff) + { + if (Unit* target = SelectRandomNotStomach()) { - if (StomachEnterVisTimer <= diff) - { - //Check for valid player - Unit* unit = ObjectAccessor::GetUnit(*me, StomachEnterTarget); - - if (unit) - { - DoTeleportPlayer(unit, STOMACH_X, STOMACH_Y, STOMACH_Z, STOMACH_O); - } - - StomachEnterTarget.Clear(); - StomachEnterVisTimer = 0; - } - else StomachEnterVisTimer -= diff; + //Spawn claw tentacle on the random target + if (Creature* spawned = me->SummonCreature(NPC_GIANT_CLAW_TENTACLE, *target, TEMPSUMMON_CORPSE_DESPAWN, 500)) + if (spawned->AI()) + spawned->AI()->AttackStart(target); } - //GientClawTentacleTimer - if (GiantClawTentacleTimer <= diff) + //One giant claw tentacle every minute + GiantClawTentacleTimer = 60000; + } + else GiantClawTentacleTimer -= diff; + + //GiantEyeTentacleTimer + if (GiantEyeTentacleTimer <= diff) + { + if (Unit* target = SelectRandomNotStomach()) { - if (Unit* target = SelectRandomNotStomach()) - { - //Spawn claw tentacle on the random target - if (Creature* spawned = me->SummonCreature(NPC_GIANT_CLAW_TENTACLE, *target, TEMPSUMMON_CORPSE_DESPAWN, 500)) - if (spawned->AI()) - spawned->AI()->AttackStart(target); - } - - //One giant claw tentacle every minute - GiantClawTentacleTimer = 60000; + //Spawn claw tentacle on the random target + if (Creature* spawned = me->SummonCreature(NPC_GIANT_EYE_TENTACLE, *target, TEMPSUMMON_CORPSE_DESPAWN, 500)) + if (spawned->AI()) + spawned->AI()->AttackStart(target); } - else GiantClawTentacleTimer -= diff; - //GiantEyeTentacleTimer - if (GiantEyeTentacleTimer <= diff) - { - if (Unit* target = SelectRandomNotStomach()) - { - //Spawn claw tentacle on the random target - if (Creature* spawned = me->SummonCreature(NPC_GIANT_EYE_TENTACLE, *target, TEMPSUMMON_CORPSE_DESPAWN, 500)) - if (spawned->AI()) - spawned->AI()->AttackStart(target); - } + //One giant eye tentacle every minute + GiantEyeTentacleTimer = 60000; + } + else GiantEyeTentacleTimer -= diff; - //One giant eye tentacle every minute - GiantEyeTentacleTimer = 60000; - } - else GiantEyeTentacleTimer -= diff; - - break; + break; //Weakened state - case PHASE_CTHUN_WEAK: - //PhaseTimer - if (PhaseTimer <= diff) + case PHASE_CTHUN_WEAK: + //PhaseTimer + if (PhaseTimer <= diff) + { + //Switch + instance->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_STOMACH); + + //Remove purple coloration + me->RemoveAurasDueToSpell(SPELL_PURPLE_COLORATION); + + //Spawn 2 flesh tentacles + FleshTentaclesKilled = 0; + + //Spawn flesh tentacle + for (uint8 i = 0; i < 2; i++) { - //Switch - instance->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_STOMACH); - - //Remove purple coloration - me->RemoveAurasDueToSpell(SPELL_PURPLE_COLORATION); - - //Spawn 2 flesh tentacles - FleshTentaclesKilled = 0; - - //Spawn flesh tentacle - for (uint8 i = 0; i < 2; i++) - { - Creature* spawned = me->SummonCreature(NPC_FLESH_TENTACLE, FleshTentaclePos[i], TEMPSUMMON_CORPSE_DESPAWN); - if (!spawned) - ++FleshTentaclesKilled; - } - - PhaseTimer = 0; + Creature* spawned = me->SummonCreature(NPC_FLESH_TENTACLE, FleshTentaclePos[i], TEMPSUMMON_CORPSE_DESPAWN); + if (!spawned) + ++FleshTentaclesKilled; } - else PhaseTimer -= diff; - break; - } + PhaseTimer = 0; + } + else PhaseTimer -= diff; + + break; } - - void JustDied(Unit* /*killer*/) override - { - instance->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_DONE); - } - - void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override - { - switch (instance->GetData(DATA_CTHUN_PHASE)) - { - case PHASE_CTHUN_STOMACH: - //Not weakened so reduce damage by 99% - damage /= 100; - if (damage == 0) - damage = 1; - - //Prevent death in non-weakened state - if (damage >= me->GetHealth()) - damage = 0; - - return; - - case PHASE_CTHUN_WEAK: - //Weakened - takes normal damage - return; - - default: - damage = 0; - break; - } - } - - void SummonedCreatureDies(Creature* creature, Unit* /*killer*/) override - { - if (creature->GetEntry() == NPC_FLESH_TENTACLE) - { - ++FleshTentaclesKilled; - } - } - }; -}; - -class npc_eye_tentacle : public CreatureScript -{ -public: - npc_eye_tentacle() : CreatureScript("npc_eye_tentacle") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return new eye_tentacleAI(creature); } - struct eye_tentacleAI : public ScriptedAI + void JustDied(Unit* /*killer*/) override { - eye_tentacleAI(Creature* creature) : ScriptedAI(creature) - { - if (Creature* portal = me->SummonCreature(NPC_SMALL_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) - { - portal->SetReactState(REACT_PASSIVE); - _portalGUID = portal->GetGUID(); - } + instance->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_DONE); + } - SetCombatMovement(false); + void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override + { + switch (instance->GetData(DATA_CTHUN_PHASE)) + { + case PHASE_CTHUN_STOMACH: + //Not weakened so reduce damage by 99% + damage /= 100; + if (damage == 0) + damage = 1; + + //Prevent death in non-weakened state + if (damage >= me->GetHealth()) + damage = 0; + + return; + + case PHASE_CTHUN_WEAK: + //Weakened - takes normal damage + return; + + default: + damage = 0; + break; + } + } + + void SummonedCreatureDies(Creature* creature, Unit* /*killer*/) override + { + if (creature->GetEntry() == NPC_FLESH_TENTACLE) + { + ++FleshTentaclesKilled; + } + } +}; + +struct npc_eye_tentacle : public ScriptedAI +{ + npc_eye_tentacle(Creature* creature) : ScriptedAI(creature) + { + if (Creature* portal = me->SummonCreature(NPC_SMALL_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) + { + portal->SetReactState(REACT_PASSIVE); + _portalGUID = portal->GetGUID(); } - void JustDied(Unit* /*killer*/) override - { - if (Unit* p = ObjectAccessor::GetUnit(*me, _portalGUID)) - { - Unit::Kill(p, p); - } - } + SetCombatMovement(false); + } - void Reset() override + void JustDied(Unit* /*killer*/) override + { + if (Unit* p = ObjectAccessor::GetUnit(*me, _portalGUID)) { - _scheduler.Schedule(500ms, [this](TaskContext /*task*/) + Unit::Kill(p, p); + } + } + + void Reset() override + { + _scheduler.Schedule(500ms, [this](TaskContext /*task*/) { DoCastAOE(SPELL_GROUND_RUPTURE); - }).Schedule(5min, [this](TaskContext /*task*/) + }) + .Schedule(5min, [this](TaskContext /*task*/) { me->DespawnOrUnsummon(); - }).Schedule(1s, 5s, [this](TaskContext context) + }) + .Schedule(1s, 5s, [this](TaskContext context) { if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, [&](Unit* u) { return u && u->GetTypeId() == TYPEID_PLAYER && !u->HasAura(SPELL_DIGESTIVE_ACID) && !u->HasAura(SPELL_MIND_FLAY); })) { - DoCast(target, SPELL_MIND_FLAY); + DoCast(target, SPELL_MIND_FLAY); } context.Repeat(10s, 15s); }); - } - - void EnterCombat(Unit* /*who*/) override - { - DoZoneInCombat(); - } - - void UpdateAI(uint32 diff) override - { - //Check if we have a target - if (!UpdateVictim()) - return; - - _scheduler.Update(diff); - } - - private: - TaskScheduler _scheduler; - ObjectGuid _portalGUID; - }; -}; - -class npc_claw_tentacle : public CreatureScript -{ -public: - npc_claw_tentacle() : CreatureScript("npc_claw_tentacle") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return new claw_tentacleAI(creature); } - struct claw_tentacleAI : public ScriptedAI + void EnterCombat(Unit* /*who*/) override { - claw_tentacleAI(Creature* creature) : ScriptedAI(creature) - { - SetCombatMovement(false); + DoZoneInCombat(); + } - if (Creature* portal = me->SummonCreature(NPC_SMALL_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) - { - portal->SetReactState(REACT_PASSIVE); - _portalGUID = portal->GetGUID(); - } + void UpdateAI(uint32 diff) override + { + //Check if we have a target + if (!UpdateVictim()) + return; + + _scheduler.Update(diff); + } + +private: + TaskScheduler _scheduler; + ObjectGuid _portalGUID; +}; + +struct npc_claw_tentacle : public ScriptedAI +{ + npc_claw_tentacle(Creature* creature) : ScriptedAI(creature) + { + SetCombatMovement(false); + + if (Creature* portal = me->SummonCreature(NPC_SMALL_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) + { + portal->SetReactState(REACT_PASSIVE); + _portalGUID = portal->GetGUID(); } + } - void JustDied(Unit* /*killer*/) override + void JustDied(Unit* /*killer*/) override + { + if (Unit* p = ObjectAccessor::GetUnit(*me, _portalGUID)) { - if (Unit* p = ObjectAccessor::GetUnit(*me, _portalGUID)) - { - Unit::Kill(p, p); - } + Unit::Kill(p, p); } + } - void Reset() override - { - _scheduler.Schedule(Milliseconds(500), [this](TaskContext /*task*/) + void Reset() override + { + _scheduler.Schedule(Milliseconds(500), [this](TaskContext /*task*/) { DoCastAOE(SPELL_GROUND_RUPTURE); }).Schedule(Minutes(5), [this](TaskContext /*task*/) { me->DespawnOrUnsummon(); }); - } + } - void EnterCombat(Unit* /*who*/) override - { - DoZoneInCombat(); + void EnterCombat(Unit* /*who*/) override + { + DoZoneInCombat(); - _scheduler.Schedule(2s, [this](TaskContext context) + _scheduler.Schedule(2s, [this](TaskContext context) { DoCastVictim(SPELL_HAMSTRING); context.Repeat(5s); }); - } - - void UpdateAI(uint32 diff) override - { - //Check if we have a target - if (!UpdateVictim()) - return; - - _scheduler.Update(diff); - - DoMeleeAttackIfReady(); - } - - private: - TaskScheduler _scheduler; - ObjectGuid _portalGUID; - }; -}; - -class npc_giant_claw_tentacle : public CreatureScript -{ -public: - npc_giant_claw_tentacle() : CreatureScript("npc_giant_claw_tentacle") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return new giant_claw_tentacleAI(creature); } - struct giant_claw_tentacleAI : public ScriptedAI + void UpdateAI(uint32 diff) override { - giant_claw_tentacleAI(Creature* creature) : ScriptedAI(creature) - { - SetCombatMovement(false); + //Check if we have a target + if (!UpdateVictim()) + return; - if (Creature* portal = me->SummonCreature(NPC_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) - { - portal->SetReactState(REACT_PASSIVE); - _portalGUID = portal->GetGUID(); - } + _scheduler.Update(diff); + + DoMeleeAttackIfReady(); + } + +private: + TaskScheduler _scheduler; + ObjectGuid _portalGUID; +}; + +struct npc_giant_claw_tentacle : public ScriptedAI +{ + npc_giant_claw_tentacle(Creature* creature) : ScriptedAI(creature) + { + SetCombatMovement(false); + + if (Creature* portal = me->SummonCreature(NPC_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) + { + portal->SetReactState(REACT_PASSIVE); + _portalGUID = portal->GetGUID(); } + } - void JustDied(Unit* /*killer*/) override + void JustDied(Unit* /*killer*/) override + { + if (Unit* p = ObjectAccessor::GetUnit(*me, _portalGUID)) { - if (Unit* p = ObjectAccessor::GetUnit(*me, _portalGUID)) - { - Unit::Kill(p, p); - } + Unit::Kill(p, p); } + } - void Reset() override - { - _scheduler.Schedule(500ms, [this](TaskContext /*task*/) + void Reset() override + { + _scheduler.Schedule(500ms, [this](TaskContext /*task*/) { DoCastAOE(SPELL_MASSIVE_GROUND_RUPTURE); }); - } + } - void EnterCombat(Unit* /*who*/) override - { - DoZoneInCombat(); + void EnterCombat(Unit* /*who*/) override + { + DoZoneInCombat(); - _scheduler.Schedule(2s, [this](TaskContext context) + _scheduler.Schedule(2s, [this](TaskContext context) { DoCastVictim(SPELL_HAMSTRING); context.Repeat(10s); - }).Schedule(5s, [this](TaskContext context) { + }).Schedule(5s, [this](TaskContext context) + { DoCastSelf(SPELL_THRASH); context.Repeat(10s); }); - } + } - void ScheduleMeleeCheck() - { - // Check if a target is in melee range - _scheduler.Schedule(10s, [this](TaskContext task) + void ScheduleMeleeCheck() + { + // Check if a target is in melee range + _scheduler.Schedule(10s, [this](TaskContext task) { if (Unit* target = me->GetVictim()) { @@ -1058,108 +1011,98 @@ public: task.Repeat(); }); + } + + void Submerge() + { + if (me->SelectNearestPlayer(5.0f)) + { + return; } - void Submerge() + // Despawn portal + if (Creature* p = ObjectAccessor::GetCreature(*me, _portalGUID)) { - if (me->SelectNearestPlayer(5.0f)) - { - return; - } + p->DespawnOrUnsummon(); + } - // Despawn portal - if (Creature* p = ObjectAccessor::GetCreature(*me, _portalGUID)) - { - p->DespawnOrUnsummon(); - } + DoCastSelf(SPELL_SUBMERGE_VISUAL); + me->SetHealth(me->GetMaxHealth()); + me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - DoCastSelf(SPELL_SUBMERGE_VISUAL); - me->SetHealth(me->GetMaxHealth()); - me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + _scheduler.CancelAll(); - _scheduler.CancelAll(); - - _scheduler.Schedule(5s, [this](TaskContext /*task*/) + _scheduler.Schedule(5s, [this](TaskContext /*task*/) { Emerge(); }); - } - - void Emerge() - { - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, NotInStomachSelector())) - { - Position pos = target->GetPosition(); - me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), 0); - if (Creature* portal = me->SummonCreature(NPC_GIANT_PORTAL, pos, TEMPSUMMON_CORPSE_DESPAWN)) - { - portal->SetReactState(REACT_PASSIVE); - _portalGUID = portal->GetGUID(); - } - - me->RemoveAurasDueToSpell(SPELL_SUBMERGE_VISUAL); - DoCastSelf(SPELL_BIRTH); - DoCastAOE(SPELL_MASSIVE_GROUND_RUPTURE, true); - me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - - ScheduleMeleeCheck(); - } - } - - void UpdateAI(uint32 diff) override - { - //Check if we have a target - if (!UpdateVictim()) - return; - - _scheduler.Update(diff); - - DoMeleeAttackIfReady(); - } - - private: - TaskScheduler _scheduler; - ObjectGuid _portalGUID; - }; -}; - -class npc_giant_eye_tentacle : public CreatureScript -{ -public: - npc_giant_eye_tentacle() : CreatureScript("npc_giant_eye_tentacle") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return new giant_eye_tentacleAI(creature); } - struct giant_eye_tentacleAI : public ScriptedAI + void Emerge() { - giant_eye_tentacleAI(Creature* creature) : ScriptedAI(creature) + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, NotInStomachSelector())) { - SetCombatMovement(false); - - if (Creature* portal = me->SummonCreature(NPC_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) + Position pos = target->GetPosition(); + me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), 0); + if (Creature* portal = me->SummonCreature(NPC_GIANT_PORTAL, pos, TEMPSUMMON_CORPSE_DESPAWN)) { portal->SetReactState(REACT_PASSIVE); _portalGUID = portal->GetGUID(); } - } - void JustDied(Unit* /*killer*/) override - { - if (Unit* p = ObjectAccessor::GetUnit(*me, _portalGUID)) - { - Unit::Kill(p, p); - } - } + me->RemoveAurasDueToSpell(SPELL_SUBMERGE_VISUAL); + DoCastSelf(SPELL_BIRTH); + DoCastAOE(SPELL_MASSIVE_GROUND_RUPTURE, true); + me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - void Reset() override + ScheduleMeleeCheck(); + } + } + + void UpdateAI(uint32 diff) override + { + //Check if we have a target + if (!UpdateVictim()) + return; + + _scheduler.Update(diff); + + DoMeleeAttackIfReady(); + } + +private: + TaskScheduler _scheduler; + ObjectGuid _portalGUID; +}; + +struct npc_giant_eye_tentacle : public ScriptedAI +{ + npc_giant_eye_tentacle(Creature* creature) : ScriptedAI(creature) + { + SetCombatMovement(false); + + if (Creature* portal = me->SummonCreature(NPC_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) { - _scheduler.Schedule(500ms, [this](TaskContext /*task*/) + portal->SetReactState(REACT_PASSIVE); + _portalGUID = portal->GetGUID(); + } + } + + void JustDied(Unit* /*killer*/) override + { + if (Unit* p = ObjectAccessor::GetUnit(*me, _portalGUID)) + { + Unit::Kill(p, p); + } + } + + void Reset() override + { + _scheduler.Schedule(500ms, [this](TaskContext /*task*/) { DoCastAOE(SPELL_MASSIVE_GROUND_RUPTURE); - }).Schedule(1s, 5s, [this](TaskContext context) { + }).Schedule(1s, 5s, [this](TaskContext context) + { if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, -SPELL_DIGESTIVE_ACID)) { DoCast(target, SPELL_GREEN_BEAM); @@ -1167,36 +1110,33 @@ public: context.Repeat(2100ms); }); - } + } - void EnterCombat(Unit* /*who*/) override - { - DoZoneInCombat(); - } + void EnterCombat(Unit* /*who*/) override + { + DoZoneInCombat(); + } - void UpdateAI(uint32 diff) override - { - //Check if we have a target - if (!UpdateVictim()) - return; + void UpdateAI(uint32 diff) override + { + //Check if we have a target + if (!UpdateVictim()) + return; - _scheduler.Update(diff); - } + _scheduler.Update(diff); + } - private: - TaskScheduler _scheduler; - ObjectGuid _portalGUID; - }; +private: + TaskScheduler _scheduler; + ObjectGuid _portalGUID; }; -//GetAIs - void AddSC_boss_cthun() { - new boss_eye_of_cthun(); - new boss_cthun(); - new npc_eye_tentacle(); - new npc_claw_tentacle(); - new npc_giant_claw_tentacle(); - new npc_giant_eye_tentacle(); + RegisterTempleOfAhnQirajCreatureAI(boss_eye_of_cthun); + RegisterTempleOfAhnQirajCreatureAI(boss_cthun); + RegisterTempleOfAhnQirajCreatureAI(npc_eye_tentacle); + RegisterTempleOfAhnQirajCreatureAI(npc_claw_tentacle); + RegisterTempleOfAhnQirajCreatureAI(npc_giant_claw_tentacle); + RegisterTempleOfAhnQirajCreatureAI(npc_giant_eye_tentacle); } diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp index fdd08243b..d0ca30daa 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp @@ -15,154 +15,118 @@ * with this program. If not, see . */ -/* ScriptData -SDName: Boss_Fankriss -SD%Complete: 100 -SDComment: sound not implemented -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "TaskScheduler.h" #include "temple_of_ahnqiraj.h" -#define SOUND_SENTENCE_YOU 8588 -#define SOUND_SERVE_TO 8589 -#define SOUND_LAWS 8590 -#define SOUND_TRESPASS 8591 -#define SOUND_WILL_BE 8592 - enum Spells { SPELL_MORTAL_WOUND = 25646, - SPELL_ROOT = 28858, + SPELL_ENTANGLE_RIGHT = 720, + SPELL_ENTANGLE_CENTER = 731, + SPELL_ENTANGLE_LEFT = 1121, - // Enrage for his spawns - SPELL_ENRAGE = 28798 + SPELL_SUMMON_WORM_1 = 518, + SPELL_SUMMON_WORM_2 = 25831, + SPELL_SUMMON_WORM_3 = 25832 }; -class boss_fankriss : public CreatureScript +enum Misc { -public: - boss_fankriss() : CreatureScript("boss_fankriss") { } + MAX_HATCHLING_SPAWN = 4, + NPC_VEKNISS_HATCHLING = 15962 +}; - CreatureAI* GetAI(Creature* creature) const override +const std::array hatchlingsSpawnPoints +{ { - return GetTempleOfAhnQirajAI(creature); + { -8043.6f, 1254.1f, -84.3f }, // Right + { -8003.0f, 1222.9f, -82.1f }, // Center + { -8022.3f, 1149.0f, -89.1f } // Left + } +}; + +const std::array entangleSpells = { SPELL_ENTANGLE_RIGHT, SPELL_ENTANGLE_CENTER, SPELL_ENTANGLE_LEFT }; + +struct boss_fankriss : public BossAI +{ + boss_fankriss(Creature* creature) : BossAI(creature, DATA_FANKRISS) { } + + void Reset() override + { + _scheduler.CancelAll(); + summonWormSpells = { SPELL_SUMMON_WORM_1, SPELL_SUMMON_WORM_2, SPELL_SUMMON_WORM_3}; + + BossAI::Reset(); } - struct boss_fankrissAI : public ScriptedAI + void SummonWorms() { - boss_fankrissAI(Creature* creature) : ScriptedAI(creature) { } + uint32 amount = urand(1, 3); + Acore::Containers::RandomResize(summonWormSpells, amount); + for (uint32 summonSpell : summonWormSpells) + DoCastAOE(summonSpell, true); + summonWormSpells = { SPELL_SUMMON_WORM_1, SPELL_SUMMON_WORM_2, SPELL_SUMMON_WORM_3 }; + } - void SummonSpawn() + void SummonHatchlingWaves() + { + for (Position spawnPos : hatchlingsSpawnPoints) { - Rand = 10 + (rand() % 10); - switch (rand() % 2) + for (uint8 i = 0; i < MAX_HATCHLING_SPAWN; i++) { - case 0: - RandX = 0.0f - Rand; - break; - case 1: - RandX = 0.0f + Rand; - break; + Position randSpawn = me->GetRandomPoint(spawnPos, 10.f); + me->SummonCreature(NPC_VEKNISS_HATCHLING, randSpawn, TEMPSUMMON_CORPSE_DESPAWN); } - - Rand = 10 + (rand() % 10); - switch (rand() % 2) - { - case 0: - RandY = 0.0f - Rand; - break; - case 1: - RandY = 0.0f + Rand; - break; - } - Rand = 0; - DoSpawnCreature(15630, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); } + } - void EnterCombat(Unit* /*who*/) override - { - _scheduler.CancelAll(); + void EnterCombat(Unit* who) override + { + _scheduler.CancelAll(); + BossAI::EnterCombat(who); - _scheduler.Schedule(4s, 8s, [this](TaskContext context) { + _scheduler + .Schedule(7s, 14s, [this](TaskContext context) + { DoCastVictim(SPELL_MORTAL_WOUND); context.Repeat(); - }).Schedule(15s, 45s, [this](TaskContext context) { - switch (urand(0, 2)) + }) + .Schedule(30s, 50s, [this](TaskContext context) + { + SummonWorms(); + context.Repeat(22s, 70s); + }) + .Schedule(15s, 20s, [this](TaskContext context) + { + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 0.0f, true)) { - case 0: - SummonSpawn(); - break; - case 1: - SummonSpawn(); - SummonSpawn(); - break; - case 2: - SummonSpawn(); - SummonSpawn(); - SummonSpawn(); - break; + uint32 spellId = Acore::Containers::SelectRandomContainerElement(entangleSpells); + DoCast(target, spellId); } - context.Repeat(30s, 60s); - }).Schedule(15s, 45s, [this](TaskContext context) { - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true)) - { - DoCast(target, SPELL_ROOT); - if (DoGetThreat(target)) - DoModifyThreatPercent(target, -100); - - switch (urand(0, 2)) - { - case 0: - DoTeleportPlayer(target, -8106.0142f, 1289.2900f, -74.419533f, 5.112f); - me->SummonCreature(15962, target->GetPositionX() - 3, target->GetPositionY() - 3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - me->SummonCreature(15962, target->GetPositionX() - 3, target->GetPositionY() + 3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - me->SummonCreature(15962, target->GetPositionX() - 5, target->GetPositionY() - 5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - me->SummonCreature(15962, target->GetPositionX() - 5, target->GetPositionY() + 5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - break; - case 1: - DoTeleportPlayer(target, -7990.135354f, 1155.1907f, -78.849319f, 2.608f); - me->SummonCreature(15962, target->GetPositionX() - 3, target->GetPositionY() - 3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - me->SummonCreature(15962, target->GetPositionX() - 3, target->GetPositionY() + 3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - me->SummonCreature(15962, target->GetPositionX() - 5, target->GetPositionY() - 5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - me->SummonCreature(15962, target->GetPositionX() - 5, target->GetPositionY() + 5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - break; - case 2: - DoTeleportPlayer(target, -8159.7753f, 1127.9064f, -76.868660f, 0.675f); - me->SummonCreature(15962, target->GetPositionX() - 3, target->GetPositionY() - 3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - me->SummonCreature(15962, target->GetPositionX() - 3, target->GetPositionY() + 3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - me->SummonCreature(15962, target->GetPositionX() - 5, target->GetPositionY() - 5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - me->SummonCreature(15962, target->GetPositionX() - 5, target->GetPositionY() + 5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - break; - } - } - context.Repeat(45s, 60s); + SummonHatchlingWaves(); + context.Repeat(25s, 55s); }); - } + } - void UpdateAI(uint32 diff) override - { - //Return since we have no target - if (!UpdateVictim()) - return; + void UpdateAI(uint32 diff) override + { + //Return since we have no target + if (!UpdateVictim()) + return; - _scheduler.Update(diff, - std::bind(&ScriptedAI::DoMeleeAttackIfReady, this)); - } + _scheduler.Update(diff, + std::bind(&ScriptedAI::DoMeleeAttackIfReady, this)); + } - private: - TaskScheduler _scheduler; - int Rand; - float RandX; - float RandY; - }; +private: + TaskScheduler _scheduler; + std::vector summonWormSpells; }; void AddSC_boss_fankriss() { - new boss_fankriss(); + RegisterTempleOfAhnQirajCreatureAI(boss_fankriss); } diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp index bdd58744e..5a2d7255b 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp @@ -41,115 +41,104 @@ enum Huhuran SPELL_WYVERN_STING_DAMAGE = 26233 }; -class boss_huhuran : public CreatureScript +struct boss_huhuran : public ScriptedAI { -public: - boss_huhuran() : CreatureScript("boss_huhuran") { } + boss_huhuran(Creature* creature) : ScriptedAI(creature) { } - CreatureAI* GetAI(Creature* creature) const override + uint32 Frenzy_Timer; + uint32 Wyvern_Timer; + uint32 Spit_Timer; + uint32 PoisonBolt_Timer; + uint32 NoxiousPoison_Timer; + uint32 FrenzyBack_Timer; + + bool Frenzy; + bool Berserk; + + void Reset() override { - return GetTempleOfAhnQirajAI(creature); + Frenzy_Timer = urand(25000, 35000); + Wyvern_Timer = urand(18000, 28000); + Spit_Timer = 8000; + PoisonBolt_Timer = 4000; + NoxiousPoison_Timer = urand(10000, 20000); + FrenzyBack_Timer = 15000; + + Frenzy = false; + Berserk = false; } - struct boss_huhuranAI : public ScriptedAI + void UpdateAI(uint32 diff) override { - boss_huhuranAI(Creature* creature) : ScriptedAI(creature) { } + //Return since we have no target + if (!UpdateVictim()) + return; - uint32 Frenzy_Timer; - uint32 Wyvern_Timer; - uint32 Spit_Timer; - uint32 PoisonBolt_Timer; - uint32 NoxiousPoison_Timer; - uint32 FrenzyBack_Timer; - - bool Frenzy; - bool Berserk; - - void Reset() override + //Frenzy_Timer + if (!Frenzy && Frenzy_Timer <= diff) { + DoCast(me, SPELL_FRENZY); + Talk(EMOTE_FRENZY_KILL); + Frenzy = true; + PoisonBolt_Timer = 3000; Frenzy_Timer = urand(25000, 35000); - Wyvern_Timer = urand(18000, 28000); - Spit_Timer = 8000; - PoisonBolt_Timer = 4000; - NoxiousPoison_Timer = urand(10000, 20000); - FrenzyBack_Timer = 15000; - - Frenzy = false; - Berserk = false; } + else Frenzy_Timer -= diff; - void UpdateAI(uint32 diff) override + // Wyvern Timer + if (Wyvern_Timer <= diff) { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Frenzy_Timer - if (!Frenzy && Frenzy_Timer <= diff) - { - DoCast(me, SPELL_FRENZY); - Talk(EMOTE_FRENZY_KILL); - Frenzy = true; - PoisonBolt_Timer = 3000; - Frenzy_Timer = urand(25000, 35000); - } - else Frenzy_Timer -= diff; - - // Wyvern Timer - if (Wyvern_Timer <= diff) - { - DoCastAOE(SPELL_WYVERNSTING); - Wyvern_Timer = urand(15000, 32000); - } - else Wyvern_Timer -= diff; - - //Spit Timer - if (Spit_Timer <= diff) - { - DoCastVictim(SPELL_ACIDSPIT); - Spit_Timer = urand(5000, 10000); - } - else Spit_Timer -= diff; - - //NoxiousPoison_Timer - if (NoxiousPoison_Timer <= diff) - { - DoCastVictim(SPELL_NOXIOUSPOISON); - NoxiousPoison_Timer = urand(12000, 24000); - } - else NoxiousPoison_Timer -= diff; - - //PoisonBolt only if frenzy or berserk - if (Frenzy || Berserk) - { - if (PoisonBolt_Timer <= diff) - { - DoCastVictim(SPELL_POISONBOLT); - PoisonBolt_Timer = 3000; - } - else PoisonBolt_Timer -= diff; - } - - //FrenzyBack_Timer - if (Frenzy && FrenzyBack_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - Frenzy = false; - FrenzyBack_Timer = 15000; - } - else FrenzyBack_Timer -= diff; - - if (!Berserk && HealthBelowPct(31)) - { - me->InterruptNonMeleeSpells(false); - Talk(EMOTE_BERSERK); - DoCast(me, SPELL_BERSERK); - Berserk = true; - } - - DoMeleeAttackIfReady(); + DoCastAOE(SPELL_WYVERNSTING); + Wyvern_Timer = urand(15000, 32000); } - }; + else Wyvern_Timer -= diff; + + //Spit Timer + if (Spit_Timer <= diff) + { + DoCastVictim(SPELL_ACIDSPIT); + Spit_Timer = urand(5000, 10000); + } + else Spit_Timer -= diff; + + //NoxiousPoison_Timer + if (NoxiousPoison_Timer <= diff) + { + DoCastVictim(SPELL_NOXIOUSPOISON); + NoxiousPoison_Timer = urand(12000, 24000); + } + else NoxiousPoison_Timer -= diff; + + //PoisonBolt only if frenzy or berserk + if (Frenzy || Berserk) + { + if (PoisonBolt_Timer <= diff) + { + DoCastVictim(SPELL_POISONBOLT); + PoisonBolt_Timer = 3000; + } + else PoisonBolt_Timer -= diff; + } + + //FrenzyBack_Timer + if (Frenzy && FrenzyBack_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + Frenzy = false; + FrenzyBack_Timer = 15000; + } + else FrenzyBack_Timer -= diff; + + if (!Berserk && HealthBelowPct(31)) + { + me->InterruptNonMeleeSpells(false); + Talk(EMOTE_BERSERK); + DoCast(me, SPELL_BERSERK); + Berserk = true; + } + + DoMeleeAttackIfReady(); + } }; // 26180 - Wyvern Sting @@ -173,6 +162,6 @@ class spell_huhuran_wyvern_sting : public AuraScript void AddSC_boss_huhuran() { - new boss_huhuran(); + RegisterTempleOfAhnQirajCreatureAI(boss_huhuran); RegisterSpellScript(spell_huhuran_wyvern_sting); } diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_ouro.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_ouro.cpp index 0969f3e53..974620cb8 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_ouro.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_ouro.cpp @@ -15,188 +15,360 @@ * with this program. If not, see . */ -/* ScriptData -SDName: Boss_Ouro -SD%Complete: 85 -SDComment: No model for submerging. Currently just invisible. -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - +#include "Cell.h" +#include "CellImpl.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "Player.h" #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "TaskScheduler.h" #include "temple_of_ahnqiraj.h" enum Spells { + // Ouro SPELL_SWEEP = 26103, - SPELL_SANDBLAST = 26102, + SPELL_SAND_BLAST = 26102, SPELL_GROUND_RUPTURE = 26100, - SPELL_BIRTH = 26262, // The Birth Animation + SPELL_BERSERK = 26615, + SPELL_BOULDER = 26616, + SPELL_OURO_SUBMERGE_VISUAL = 26063, + SPELL_SUMMON_SANDWORM_BASE = 26133, + + // Misc - Mounds, Ouro Spawner + SPELL_BIRTH = 26586, SPELL_DIRTMOUND_PASSIVE = 26092, - SPELL_SUMMON_OURO = 26061 + SPELL_SUMMON_OURO = 26061, + SPELL_SUMMON_OURO_MOUNDS = 26058, + SPELL_QUAKE = 26093, + SPELL_SUMMON_SCARABS = 26060, + SPELL_SUMMON_OURO_AURA = 26642, + SPELL_DREAM_FOG = 24780 }; -class npc_ouro_spawner : public CreatureScript +enum Misc { -public: - npc_ouro_spawner() : CreatureScript("npc_ouro_spawner") {} + GROUP_EMERGED = 0, + GROUP_PHASE_TRANSITION = 1, - CreatureAI* GetAI(Creature* creature) const - { - return new npc_ouro_spawnerAI(creature); - } + NPC_DIRT_MOUND = 15712, + GO_SANDWORM_BASE = 180795, - struct npc_ouro_spawnerAI : public ScriptedAI - { - npc_ouro_spawnerAI(Creature* creature) : ScriptedAI(creature) - { - Reset(); - } - - bool hasSummoned; - - void Reset() override - { - hasSummoned = false; - DoCast(me, SPELL_DIRTMOUND_PASSIVE); - } - - void MoveInLineOfSight(Unit* who) override - { - // Spawn Ouro on LoS check - if (!hasSummoned && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 40.0f)) - { - DoCast(me, SPELL_SUMMON_OURO); - hasSummoned = true; - } - - ScriptedAI::MoveInLineOfSight(who); - } - - void JustSummoned(Creature* creature) override - { - // Despawn when Ouro is spawned - if (creature->GetEntry() == NPC_OURO) - { - creature->SetInCombatWithZone(); - creature->CastSpell(creature, SPELL_BIRTH, false); - me->DespawnOrUnsummon(); - } - } - - }; + DATA_OURO_HEALTH = 0 }; -class boss_ouro : public CreatureScript +struct npc_ouro_spawner : public ScriptedAI { -public: - boss_ouro() : CreatureScript("boss_ouro") { } - - CreatureAI* GetAI(Creature* creature) const override + npc_ouro_spawner(Creature* creature) : ScriptedAI(creature) { - return GetTempleOfAhnQirajAI(creature); + Reset(); } - struct boss_ouroAI : public ScriptedAI + bool hasSummoned; + + void Reset() override { - boss_ouroAI(Creature* creature) : ScriptedAI(creature) { } + hasSummoned = false; + DoCastSelf(SPELL_DIRTMOUND_PASSIVE); + } - uint32 Sweep_Timer; - uint32 SandBlast_Timer; - uint32 Submerge_Timer; - uint32 Back_Timer; - uint32 ChangeTarget_Timer; - uint32 Spawn_Timer; - - bool Enrage; - bool Submerged; - - void Reset() override + void MoveInLineOfSight(Unit* who) override + { + // Spawn Ouro on LoS check + if (!hasSummoned && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 40.0f) && !who->ToPlayer()->IsGameMaster()) { - Sweep_Timer = urand(5000, 10000); - SandBlast_Timer = urand(20000, 35000); - Submerge_Timer = urand(90000, 150000); - Back_Timer = urand(30000, 45000); - ChangeTarget_Timer = urand(5000, 8000); - Spawn_Timer = urand(10000, 20000); - - Enrage = false; - Submerged = false; + DoCastSelf(SPELL_SUMMON_OURO); + hasSummoned = true; } - void EnterCombat(Unit* /*who*/) override + ScriptedAI::MoveInLineOfSight(who); + } + + void JustSummoned(Creature* creature) override + { + // Despawn when Ouro is spawned + if (creature->GetEntry() == NPC_OURO) { - DoCastVictim(SPELL_BIRTH); + creature->SetInCombatWithZone(); + me->DespawnOrUnsummon(); + } + } +}; + +struct boss_ouro : public BossAI +{ + boss_ouro(Creature* creature) : BossAI(creature, DATA_OURO) + { + SetCombatMovement(false); + me->SetControlled(true, UNIT_STATE_ROOT); + _scheduler.SetValidator([this] { return !me->HasUnitState(UNIT_STATE_CASTING); }); + } + + void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType, SpellSchoolMask) override + { + if (me->HealthBelowPctDamaged(20, damage) && !_enraged) + { + DoCastSelf(SPELL_BERSERK, true); + _enraged = true; + _scheduler.CancelGroup(GROUP_PHASE_TRANSITION); + _scheduler.Schedule(1s, [this](TaskContext context) + { + if (!IsPlayerWithinMeleeRange()) + DoSpellAttackToRandomTargetIfReady(SPELL_BOULDER); + + context.Repeat(); + }) + .Schedule(20s, [this](TaskContext context) + { + DoCastSelf(SPELL_SUMMON_OURO_MOUNDS, true); + context.Repeat(); + }); + } + } + + void Submerge() + { + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + _submergeMelee = 0; + _submerged = true; + DoCastSelf(SPELL_OURO_SUBMERGE_VISUAL); + _scheduler.CancelGroup(GROUP_EMERGED); + _scheduler.CancelGroup(GROUP_PHASE_TRANSITION); + + if (GameObject* base = me->FindNearestGameObject(GO_SANDWORM_BASE, 10.f)) + { + base->Use(me); + base->DespawnOrUnsummon(6s); } - void UpdateAI(uint32 diff) override + DoCastSelf(SPELL_SUMMON_OURO_MOUNDS, true); + // According to sniffs, Ouro uses his mounds to respawn. The health management could be a little scuffed. + std::list ouroMounds; + me->GetCreatureListWithEntryInGrid(ouroMounds, NPC_DIRT_MOUND, 200.f); + if (!ouroMounds.empty()) // This can't be possible, but just to be sure. { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Sweep_Timer - if (!Submerged && Sweep_Timer <= diff) + if (Creature* mound = Acore::Containers::SelectRandomContainerElement(ouroMounds)) { - DoCastVictim(SPELL_SWEEP); - Sweep_Timer = urand(15000, 30000); + mound->AddAura(SPELL_SUMMON_OURO_AURA, mound); + mound->AI()->SetData(DATA_OURO_HEALTH, me->GetHealth()); } - else Sweep_Timer -= diff; - - //SandBlast_Timer - if (!Submerged && SandBlast_Timer <= diff) - { - DoCastVictim(SPELL_SANDBLAST); - SandBlast_Timer = urand(20000, 35000); - } - else SandBlast_Timer -= diff; - - //Submerge_Timer - if (!Submerged && Submerge_Timer <= diff) - { - //Cast - me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE); - me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - me->SetFaction(FACTION_FRIENDLY); - DoCast(me, SPELL_DIRTMOUND_PASSIVE); - - Submerged = true; - Back_Timer = urand(30000, 45000); - } - else Submerge_Timer -= diff; - - //ChangeTarget_Timer - if (Submerged && ChangeTarget_Timer <= diff) - { - Unit* target = SelectTarget(SelectTargetMethod::Random, 0); - - if (target) - me->NearTeleportTo(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), me->GetOrientation()); - - ChangeTarget_Timer = urand(10000, 20000); - } - else ChangeTarget_Timer -= diff; - - //Back_Timer - if (Submerged && Back_Timer <= diff) - { - me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - me->SetFaction(FACTION_MONSTER); - - DoCastVictim(SPELL_GROUND_RUPTURE); - - Submerged = false; - Submerge_Timer = urand(60000, 120000); - } - else Back_Timer -= diff; - - DoMeleeAttackIfReady(); } - }; + + me->DespawnOrUnsummon(1000); + } + + void CastGroundRupture() + { + std::list targets; + Acore::AllWorldObjectsInRange checker(me, 10.0f); + Acore::WorldObjectListSearcher searcher(me, targets, checker); + Cell::VisitAllObjects(me, searcher, 10.0f); + + for (WorldObject* target : targets) + { + if (Unit* unitTarget = target->ToUnit()) + { + if (unitTarget->IsHostileTo(me)) + DoCast(unitTarget, SPELL_GROUND_RUPTURE, true); + } + } + } + + void SpellHitTarget(Unit* target, SpellInfo const* spellInfo) override + { + if (spellInfo->Id == SPELL_SAND_BLAST && target) + me->GetThreatMgr().modifyThreatPercent(target, 100); + } + + void Emerge() + { + DoCastSelf(SPELL_BIRTH); + DoCastSelf(SPELL_SUMMON_SANDWORM_BASE, true); + me->SetReactState(REACT_AGGRESSIVE); + CastGroundRupture(); + _scheduler + .Schedule(20s, GROUP_EMERGED, [this](TaskContext context) + { + DoCastVictim(SPELL_SAND_BLAST); + context.Repeat(); + }) + .Schedule(22s, GROUP_EMERGED, [this](TaskContext context) + { + DoCastVictim(SPELL_SWEEP); + context.Repeat(); + }) + .Schedule(90s, GROUP_PHASE_TRANSITION, [this](TaskContext /*context*/) + { + Submerge(); + }) + .Schedule(3s, GROUP_PHASE_TRANSITION, [this](TaskContext context) + { + if (!IsPlayerWithinMeleeRange() && !_submerged) + { + if (_submergeMelee < 10) + { + _submergeMelee++; + } + else + { + if (!_enraged) + Submerge(); + _submergeMelee = 0; + } + } + else + { + _submergeMelee = 0; + } + + if (!_submerged) + context.Repeat(1s); + }); + } + + void Reset() override + { + instance->SetBossState(DATA_OURO, NOT_STARTED); + _scheduler.CancelAll(); + _submergeMelee = 0; + _submerged = false; + _enraged = false; + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + DoCastSelf(SPELL_OURO_SUBMERGE_VISUAL); + me->DespawnOrUnsummon(1000); + // Remove after the header file is sorted with the bosses first. + if (Creature* ouroSpawner = instance->GetCreature(DATA_OURO_SPAWNER)) + ouroSpawner->Respawn(); + instance->SetBossState(DATA_OURO, FAIL); + if (GameObject* base = me->FindNearestGameObject(GO_SANDWORM_BASE, 200.f)) + base->DespawnOrUnsummon(); + } + + void EnterCombat(Unit* who) override + { + Emerge(); + + BossAI::EnterCombat(who); + } + + void UpdateAI(uint32 diff) override + { + //Return since we have no target + if (!UpdateVictim()) + return; + + _scheduler.Update(diff, [this] + { + DoMeleeAttackIfReady(); + }); + } + +protected: + TaskScheduler _scheduler; + bool _enraged; + uint8 _submergeMelee; + bool _submerged; + + bool IsPlayerWithinMeleeRange() const + { + return me->IsWithinMeleeRange(me->GetVictim()); + } +}; + +struct npc_dirt_mound : ScriptedAI +{ + npc_dirt_mound(Creature* creature) : ScriptedAI(creature) + { + _instance = creature->GetInstanceScript(); + } + + void JustSummoned(Creature* creature) override + { + if (creature->GetEntry() == NPC_OURO) + { + creature->SetInCombatWithZone(); + creature->SetHealth(_ouroHealth); + } + } + + void SetData(uint32 type, uint32 data) override + { + if (type == DATA_OURO_HEALTH) + _ouroHealth = data; + } + + void EnterCombat(Unit* /*who*/) override + { + DoZoneInCombat(); + _scheduler.Schedule(30s, [this](TaskContext /*context*/) + { + DoCastSelf(SPELL_SUMMON_SCARABS, true); + me->DespawnOrUnsummon(1000); + }) + .Schedule(100ms, [this](TaskContext context) + { + ChaseNewTarget(); + context.Repeat(5s, 10s); + }); + } + + void ChaseNewTarget() + { + DoResetThreat(); + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 200.f, true)) + { + me->AddThreat(target, 1000000.f); + AttackStart(target); + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + _scheduler.Update(diff); + } + + void Reset() override + { + DoCastSelf(SPELL_DIRTMOUND_PASSIVE, true); + DoCastSelf(SPELL_DREAM_FOG, true); + DoCastSelf(SPELL_QUAKE, true); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + if (_instance) + { + _instance->SetBossState(DATA_OURO, FAIL); + + // Remove after the header file is sorted with the bosses first. + if (Creature* ouroSpawner = _instance->GetCreature(DATA_OURO_SPAWNER)) + ouroSpawner->Respawn(); + } + + if (GameObject* base = me->FindNearestGameObject(GO_SANDWORM_BASE, 200.f)) + base->DespawnOrUnsummon(); + + me->DespawnOrUnsummon(); + } + +protected: + TaskScheduler _scheduler; + uint32 _ouroHealth; + InstanceScript* _instance; }; void AddSC_boss_ouro() { - new npc_ouro_spawner(); - new boss_ouro(); + RegisterTempleOfAhnQirajCreatureAI(npc_ouro_spawner); + RegisterTempleOfAhnQirajCreatureAI(boss_ouro); + RegisterTempleOfAhnQirajCreatureAI(npc_dirt_mound); } diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp index f851d2b5c..789fe5bcf 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp @@ -15,301 +15,314 @@ * with this program. If not, see . */ -/* ScriptData -SDName: Boss_Sartura -SD%Complete: 95 -SDComment: -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - #include "ScriptMgr.h" +#include "SpellScript.h" #include "ScriptedCreature.h" #include "temple_of_ahnqiraj.h" -enum Sartura +enum Says { - SAY_AGGRO = 0, - SAY_SLAY = 1, - SAY_DEATH = 2, - - SPELL_WHIRLWIND = 26083, - SPELL_ENRAGE = 8269, - SPELL_BERSERK = 27680, - - //Guard Spell - SPELL_WHIRLWINDADD = 26038, - SPELL_KNOCKBACK = 26027 + SAY_AGGRO = 0, + SAY_SLAY = 1, + SAY_DEATH = 2 }; -class boss_sartura : public CreatureScript +enum Spells { -public: - boss_sartura() : CreatureScript("boss_sartura") { } + // Battleguard Sartura + SPELL_WHIRLWIND = 26083, // MechanicImmunity->Stunned (15sec) + SPELL_ENRAGE = 8269, + SPELL_BERSERK = 27680, + SPELL_SUNDERING_CLEAVE = 25174, - CreatureAI* GetAI(Creature* creature) const override - { - return GetTempleOfAhnQirajAI(creature); - } - - struct boss_sarturaAI : public ScriptedAI - { - boss_sarturaAI(Creature* creature) : ScriptedAI(creature) { } - - uint32 WhirlWind_Timer; - uint32 WhirlWindRandom_Timer; - uint32 WhirlWindEnd_Timer; - uint32 AggroReset_Timer; - uint32 AggroResetEnd_Timer; - uint32 EnrageHard_Timer; - - bool Enraged; - bool EnragedHard; - bool WhirlWind; - bool AggroReset; - - void Reset() override - { - WhirlWind_Timer = 30000; - WhirlWindRandom_Timer = urand(3000, 7000); - WhirlWindEnd_Timer = 15000; - AggroReset_Timer = urand(45000, 55000); - AggroResetEnd_Timer = 5000; - EnrageHard_Timer = 10 * 60000; - - WhirlWind = false; - AggroReset = false; - Enraged = false; - EnragedHard = false; - } - - void EnterCombat(Unit* /*who*/) override - { - Talk(SAY_AGGRO); - } - - void JustDied(Unit* /*killer*/) override - { - Talk(SAY_DEATH); - } - - void KilledUnit(Unit* /*victim*/) override - { - Talk(SAY_SLAY); - } - - void UpdateAI(uint32 diff) override - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (WhirlWind) - { - if (WhirlWindRandom_Timer <= diff) - { - //Attack random Gamers - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true)) - { - me->AddThreat(target, 1.0f); - me->TauntApply(target); - AttackStart(target); - } - WhirlWindRandom_Timer = urand(3000, 7000); - } - else WhirlWindRandom_Timer -= diff; - - if (WhirlWindEnd_Timer <= diff) - { - WhirlWind = false; - WhirlWind_Timer = urand(25000, 40000); - } - else WhirlWindEnd_Timer -= diff; - } - - if (!WhirlWind) - { - if (WhirlWind_Timer <= diff) - { - DoCast(me, SPELL_WHIRLWIND); - WhirlWind = true; - WhirlWindEnd_Timer = 15000; - } - else WhirlWind_Timer -= diff; - - if (AggroReset_Timer <= diff) - { - //Attack random Gamers - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true)) - { - me->AddThreat(target, 1.0f); - me->TauntApply(target); - AttackStart(target); - } - AggroReset = true; - AggroReset_Timer = urand(2000, 5000); - } - else AggroReset_Timer -= diff; - - if (AggroReset) - { - if (AggroResetEnd_Timer <= diff) - { - AggroReset = false; - AggroResetEnd_Timer = 5000; - AggroReset_Timer = urand(35000, 45000); - } - else AggroResetEnd_Timer -= diff; - } - - //If she is 20% enrage - if (!Enraged) - { - if (!HealthAbovePct(20) && !me->IsNonMeleeSpellCast(false)) - { - DoCast(me, SPELL_ENRAGE, true); - Enraged = true; - } - } - - //After 10 minutes hard enrage - if (!EnragedHard) - { - if (EnrageHard_Timer <= diff) - { - DoCast(me, SPELL_BERSERK, true); - EnragedHard = true; - } - else EnrageHard_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } - } - }; + // Sartura's Royal Guard + SPELL_GUARD_WHIRLWIND = 26038, + SPELL_GUARD_KNOCKBACK = 26027 }; -class npc_sartura_royal_guard : public CreatureScript +enum events { -public: - npc_sartura_royal_guard() : CreatureScript("npc_sartura_royal_guard") { } + // Battleguard Sartura + EVENT_SARTURA_WHIRLWIND = 1, + EVENT_SARTURA_WHIRLWIND_RANDOM = 2, + EVENT_SARTURA_WHIRLWIND_END = 3, + EVENT_SPELL_BERSERK = 4, + EVENT_SARTURA_AGGRO_RESET = 5, + EVENT_SARTURA_AGGRO_RESET_END = 6, - CreatureAI* GetAI(Creature* creature) const override + // Sartura's Royal Guard + EVENT_GUARD_WHIRLWIND = 7, + EVENT_GUARD_WHIRLWIND_RANDOM = 8, + EVENT_GUARD_WHIRLWIND_END = 9, + EVENT_GUARD_KNOCKBACK = 10, + EVENT_GUARD_AGGRO_RESET = 11, + EVENT_GUARD_AGGRO_RESET_END = 12 +}; + +struct boss_sartura : public BossAI +{ + boss_sartura(Creature* creature) : BossAI(creature, DATA_SARTURA) {} + + void Reset() override { - return GetTempleOfAhnQirajAI(creature); + _Reset(); + whirlwind = false; + enraged = false; + berserked = false; + aggroReset = false; + MinionReset(); + _savedTargetGUID.Clear(); + _savedTargetThreat = 0.f; } - struct npc_sartura_royal_guardAI : public ScriptedAI + void MinionReset() { - npc_sartura_royal_guardAI(Creature* creature) : ScriptedAI(creature) { } - - uint32 WhirlWind_Timer; - uint32 WhirlWindRandom_Timer; - uint32 WhirlWindEnd_Timer; - uint32 AggroReset_Timer; - uint32 AggroResetEnd_Timer; - uint32 KnockBack_Timer; - - bool WhirlWind; - bool AggroReset; - - void Reset() override + std::list royalGuards; + me->GetCreaturesWithEntryInRange(royalGuards, 200.0f, NPC_SARTURA_ROYAL_GUARD); + for (Creature* minion : royalGuards) { - WhirlWind_Timer = 30000; - WhirlWindRandom_Timer = urand(3000, 7000); - WhirlWindEnd_Timer = 15000; - AggroReset_Timer = urand(45000, 55000); - AggroResetEnd_Timer = 5000; - KnockBack_Timer = 10000; - - WhirlWind = false; - AggroReset = false; + minion->Respawn(); } + } - void EnterCombat(Unit* /*who*/) override + void EnterCombat(Unit* who) override + { + BossAI::EnterCombat(who); + Talk(SAY_AGGRO); + events.ScheduleEvent(EVENT_SARTURA_WHIRLWIND, 30000); + events.ScheduleEvent(EVENT_SARTURA_AGGRO_RESET, urand(45000, 55000)); + events.ScheduleEvent(EVENT_SPELL_BERSERK, 10 * 60000); + } + + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + Talk(SAY_DEATH); + } + + void KilledUnit(Unit* /*victim*/) override + { + Talk(SAY_SLAY); + } + + void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override + { + if (!enraged && HealthBelowPct(20)) { + DoCastSelf(SPELL_ENRAGE); + enraged = true; } + } - void UpdateAI(uint32 diff) override + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override + { + if (spell->Id != SPELL_SUNDERING_CLEAVE) + return; + + me->RemoveAura(SPELL_SUNDERING_CLEAVE); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!WhirlWind && WhirlWind_Timer <= diff) + switch (eventId) { - DoCast(me, SPELL_WHIRLWINDADD); - WhirlWind = true; - WhirlWind_Timer = urand(25000, 40000); - WhirlWindEnd_Timer = 15000; - } - else WhirlWind_Timer -= diff; - - if (WhirlWind) - { - if (WhirlWindRandom_Timer <= diff) - { - //Attack random Gamers - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true)) + case EVENT_SARTURA_WHIRLWIND: + DoCastSelf(SPELL_WHIRLWIND, true); + whirlwind = true; + events.ScheduleEvent(EVENT_SARTURA_WHIRLWIND_RANDOM, urand(3000, 7000)); + events.ScheduleEvent(EVENT_SARTURA_WHIRLWIND_END, 15000); + break; + case EVENT_SARTURA_WHIRLWIND_RANDOM: + if (whirlwind == true) { - me->AddThreat(target, 1.0f); - me->TauntApply(target); - AttackStart(target); + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true)) + { + me->AddThreat(target, 1.0f); + me->TauntApply(target); + AttackStart(target); + } + events.RepeatEvent(urand(3000, 7000)); } - - WhirlWindRandom_Timer = urand(3000, 7000); - } - else WhirlWindRandom_Timer -= diff; - - if (WhirlWindEnd_Timer <= diff) - { - WhirlWind = false; - } - else WhirlWindEnd_Timer -= diff; - } - - if (!WhirlWind) - { - if (AggroReset_Timer <= diff) - { - //Attack random Gamers - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true)) + break; + case EVENT_SARTURA_WHIRLWIND_END: + events.CancelEvent(EVENT_SARTURA_WHIRLWIND_RANDOM); + whirlwind = false; + events.ScheduleEvent(EVENT_SARTURA_WHIRLWIND, urand(25000, 40000)); + break; + case EVENT_SARTURA_AGGRO_RESET: + if (aggroReset == false) { - me->AddThreat(target, 1.0f); - me->TauntApply(target); - AttackStart(target); + if (Unit* originalTarget = SelectTarget(SelectTargetMethod::Random, 0)) + { + _savedTargetGUID = originalTarget->GetGUID(); + _savedTargetThreat = me->GetThreatMgr().getThreat(originalTarget); + me->GetThreatMgr().modifyThreatPercent(originalTarget, -100); + } + aggroReset = true; + events.ScheduleEvent(EVENT_SARTURA_AGGRO_RESET_END, 5000); } - - AggroReset = true; - AggroReset_Timer = urand(2000, 5000); - } - else AggroReset_Timer -= diff; - - if (KnockBack_Timer <= diff) - { - DoCast(me, SPELL_WHIRLWINDADD); - KnockBack_Timer = urand(10000, 20000); - } - else KnockBack_Timer -= diff; + else + { + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true)) + { + me->AddThreat(target, 1.0f); + me->TauntApply(target); + AttackStart(target); + } + } + events.RepeatEvent(urand(1000, 2000)); + break; + case EVENT_SARTURA_AGGRO_RESET_END: + events.CancelEvent(EVENT_SARTURA_AGGRO_RESET); + if (Unit* originalTarget = ObjectAccessor::GetUnit(*me, _savedTargetGUID)) + { + me->GetThreatMgr().addThreat(originalTarget, _savedTargetThreat); + _savedTargetGUID.Clear(); + } + aggroReset = false; + events.RescheduleEvent(EVENT_SARTURA_AGGRO_RESET, urand(30000, 40000)); + break; + case EVENT_SPELL_BERSERK: + if (!berserked) + { + DoCastSelf(SPELL_BERSERK); + berserked = true; + } + break; + default: + break; } - - if (AggroReset) - { - if (AggroResetEnd_Timer <= diff) - { - AggroReset = false; - AggroResetEnd_Timer = 5000; - AggroReset_Timer = urand(30000, 40000); - } - else AggroResetEnd_Timer -= diff; - } - - DoMeleeAttackIfReady(); } + DoMeleeAttackIfReady(); }; + private: + bool whirlwind; + bool enraged; + bool berserked; + bool aggroReset; + ObjectGuid _savedTargetGUID; + float _savedTargetThreat; +}; + +struct npc_sartura_royal_guard : public ScriptedAI +{ + npc_sartura_royal_guard(Creature* creature) : ScriptedAI(creature) {} + + void Reset() override + { + events.Reset(); + whirlwind = false; + aggroReset = false; + _savedTargetGUID.Clear(); + _savedTargetThreat = 0.f; + } + + void EnterCombat(Unit* /*who*/) override + { + events.ScheduleEvent(EVENT_GUARD_WHIRLWIND, 30000); + events.ScheduleEvent(EVENT_GUARD_AGGRO_RESET, urand(45000, 55000)); + events.ScheduleEvent(EVENT_GUARD_KNOCKBACK, 10000); + } + + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override + { + if (spell->Id != SPELL_SUNDERING_CLEAVE) + return; + + me->RemoveAura(SPELL_SUNDERING_CLEAVE); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventid = events.ExecuteEvent()) + { + switch (eventid) + { + case EVENT_GUARD_WHIRLWIND: + DoCastSelf(SPELL_GUARD_WHIRLWIND); + whirlwind = true; + events.ScheduleEvent(EVENT_GUARD_WHIRLWIND_RANDOM, urand(3000, 7000)); + events.ScheduleEvent(EVENT_GUARD_WHIRLWIND_END, 15000); + break; + case EVENT_GUARD_WHIRLWIND_RANDOM: + if (whirlwind == true) + { + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true)) + { + me->AddThreat(target, 1.0f); + me->TauntApply(target); + AttackStart(target); + } + events.RepeatEvent(urand(3000, 7000)); + } + break; + case EVENT_GUARD_WHIRLWIND_END: + events.CancelEvent(EVENT_GUARD_WHIRLWIND_RANDOM); + whirlwind = false; + events.ScheduleEvent(EVENT_GUARD_WHIRLWIND, urand(25000, 40000)); + break; + case EVENT_GUARD_AGGRO_RESET: + if (aggroReset == true) + { + if (Unit* originalTarget = SelectTarget(SelectTargetMethod::Random, 0)) + { + _savedTargetGUID = originalTarget->GetGUID(); + _savedTargetThreat = me->GetThreatMgr().getThreat(originalTarget); + me->GetThreatMgr().modifyThreatPercent(originalTarget, -100); + } + aggroReset = true; + events.ScheduleEvent(EVENT_GUARD_AGGRO_RESET_END, 5000); + } + else + { + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true)) + { + me->AddThreat(target, 1.0f); + me->TauntApply(target); + AttackStart(target); + } + } + events.RepeatEvent(urand(1000, 2000)); + break; + case EVENT_GUARD_AGGRO_RESET_END: + events.CancelEvent(EVENT_GUARD_AGGRO_RESET); + if (Unit* originalTarget = ObjectAccessor::GetUnit(*me, _savedTargetGUID)) + { + me->GetThreatMgr().addThreat(originalTarget, _savedTargetThreat); + _savedTargetGUID.Clear(); + } + aggroReset = false; + events.RescheduleEvent(EVENT_GUARD_AGGRO_RESET, urand(30000, 40000)); + break; + case EVENT_GUARD_KNOCKBACK: + DoCastVictim(SPELL_GUARD_KNOCKBACK); + events.RepeatEvent(urand(10000, 20000)); + break; + } + } + DoMeleeAttackIfReady(); + } + private: + bool whirlwind; + bool aggroReset; + ObjectGuid _savedTargetGUID; + float _savedTargetThreat; }; void AddSC_boss_sartura() { - new boss_sartura(); - new npc_sartura_royal_guard(); + RegisterTempleOfAhnQirajCreatureAI(boss_sartura); + RegisterTempleOfAhnQirajCreatureAI(npc_sartura_royal_guard); } diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp index 5944c9e95..4a9fc1ac3 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp @@ -47,183 +47,161 @@ enum Events uint32 const BlinkSpells[3] = { 4801, 8195, 20449 }; -class boss_skeram : public CreatureScript +struct boss_skeram : public BossAI { -public: - boss_skeram() : CreatureScript("boss_skeram") { } + boss_skeram(Creature* creature) : BossAI(creature, DATA_SKERAM) { } - struct boss_skeramAI : public BossAI + void Reset() override { - boss_skeramAI(Creature* creature) : BossAI(creature, DATA_SKERAM) { } + _Reset(); + _flag = 0; + _hpct = 75.0f; + me->SetVisible(true); + } - void Reset() override + void KilledUnit(Unit* /*victim*/) override + { + Talk(SAY_SLAY); + } + + void EnterEvadeMode(EvadeReason why) override + { + ScriptedAI::EnterEvadeMode(why); + if (me->IsSummon()) + ((TempSummon*)me)->UnSummon(); + } + + void JustSummoned(Creature* creature) override + { + // Shift the boss and images (Get it? *Shift*?) + uint8 rand = 0; + if (_flag != 0) { - _Reset(); - _flag = 0; - _hpct = 75.0f; - me->SetVisible(true); - } - - void KilledUnit(Unit* /*victim*/) override - { - Talk(SAY_SLAY); - } - - void EnterEvadeMode(EvadeReason why) override - { - ScriptedAI::EnterEvadeMode(why); - if (me->IsSummon()) - ((TempSummon*)me)->UnSummon(); - } - - void JustSummoned(Creature* creature) override - { - // Shift the boss and images (Get it? *Shift*?) - uint8 rand = 0; - if (_flag != 0) - { - while (_flag & (1 << rand)) - rand = urand(0, 2); - DoCast(me, BlinkSpells[rand]); - _flag |= (1 << rand); - _flag |= (1 << 7); - } - while (_flag & (1 << rand)) rand = urand(0, 2); - creature->CastSpell(creature, BlinkSpells[rand]); + DoCast(me, BlinkSpells[rand]); _flag |= (1 << rand); - - if (_flag & (1 << 7)) - _flag = 0; - - float ImageHealthPct; - - if (me->GetHealthPct() < 25.0f) - ImageHealthPct = 0.50f; - else if (me->GetHealthPct() < 50.0f) - ImageHealthPct = 0.20f; - else - ImageHealthPct = 0.10f; - - creature->SetMaxHealth(me->GetMaxHealth() * ImageHealthPct); - creature->SetHealth(creature->GetMaxHealth() * (me->GetHealthPct() / 100.0f)); - BossAI::JustSummoned(creature); + _flag |= (1 << 7); } - void JustDied(Unit* /*killer*/) override - { - if (!me->IsSummon()) - { - _JustDied(); - Talk(SAY_DEATH); - } - else - me->RemoveCorpse(); - } + while (_flag & (1 << rand)) + rand = urand(0, 2); + creature->CastSpell(creature, BlinkSpells[rand]); + _flag |= (1 << rand); - void EnterCombat(Unit* /*who*/) override - { - _EnterCombat(); - events.Reset(); + if (_flag & (1 << 7)) + _flag = 0; - events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, urand(6000, 12000)); - events.ScheduleEvent(EVENT_FULLFILMENT, 15000); - events.ScheduleEvent(EVENT_BLINK, urand(30000, 45000)); - events.ScheduleEvent(EVENT_EARTH_SHOCK, 2000); + float ImageHealthPct; - Talk(SAY_AGGRO); - } + if (me->GetHealthPct() < 25.0f) + ImageHealthPct = 0.50f; + else if (me->GetHealthPct() < 50.0f) + ImageHealthPct = 0.20f; + else + ImageHealthPct = 0.10f; - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_ARCANE_EXPLOSION: - DoCastAOE(SPELL_ARCANE_EXPLOSION, true); - events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, urand(8000, 18000)); - break; - case EVENT_FULLFILMENT: - /// @todo For some weird reason boss does not cast this - // Spell actually works, tested in duel - DoCast(SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true), SPELL_TRUE_FULFILLMENT, true); - events.ScheduleEvent(EVENT_FULLFILMENT, urand(20000, 30000)); - break; - case EVENT_BLINK: - DoCast(me, BlinkSpells[urand(0, 2)]); - DoResetThreat(); - me->SetVisible(true); - events.ScheduleEvent(EVENT_BLINK, urand(10000, 30000)); - break; - case EVENT_EARTH_SHOCK: - DoCastVictim(SPELL_EARTH_SHOCK); - events.ScheduleEvent(EVENT_EARTH_SHOCK, 2000); - break; - } - } - - if (!me->IsSummon() && me->GetHealthPct() < _hpct) - { - DoCast(me, SPELL_SUMMON_IMAGES, true); - Talk(SAY_SPLIT); - _hpct -= 25.0f; - me->SetVisible(false); - events.RescheduleEvent(EVENT_BLINK, 2000); - } - - if (me->IsWithinMeleeRange(me->GetVictim())) - { - events.RescheduleEvent(EVENT_EARTH_SHOCK, 2000); - DoMeleeAttackIfReady(); - } - } - - private: - float _hpct; - uint8 _flag; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetTempleOfAhnQirajAI(creature); + creature->SetMaxHealth(me->GetMaxHealth() * ImageHealthPct); + creature->SetHealth(creature->GetMaxHealth() * (me->GetHealthPct() / 100.0f)); + BossAI::JustSummoned(creature); } + + void JustDied(Unit* /*killer*/) override + { + if (!me->IsSummon()) + { + _JustDied(); + Talk(SAY_DEATH); + } + else + me->RemoveCorpse(); + } + + void EnterCombat(Unit* /*who*/) override + { + _EnterCombat(); + events.Reset(); + + events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, 6s, 12s); + events.ScheduleEvent(EVENT_FULLFILMENT, 15s); + events.ScheduleEvent(EVENT_BLINK, 30s, 45s); + events.ScheduleEvent(EVENT_EARTH_SHOCK, 2s); + + Talk(SAY_AGGRO); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_ARCANE_EXPLOSION: + DoCastAOE(SPELL_ARCANE_EXPLOSION, true); + events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, 8s, 18s); + break; + case EVENT_FULLFILMENT: + /// @todo For some weird reason boss does not cast this + // Spell actually works, tested in duel + DoCast(SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true), SPELL_TRUE_FULFILLMENT, true); + events.ScheduleEvent(EVENT_FULLFILMENT, 20s, 30s); + break; + case EVENT_BLINK: + DoCast(me, BlinkSpells[urand(0, 2)]); + DoResetThreat(); + me->SetVisible(true); + events.ScheduleEvent(EVENT_BLINK, 10s, 30s); + break; + case EVENT_EARTH_SHOCK: + DoCastVictim(SPELL_EARTH_SHOCK); + events.ScheduleEvent(EVENT_EARTH_SHOCK, 2s); + break; + } + } + + if (!me->IsSummon() && me->GetHealthPct() < _hpct) + { + DoCast(me, SPELL_SUMMON_IMAGES, true); + Talk(SAY_SPLIT); + _hpct -= 25.0f; + me->SetVisible(false); + events.RescheduleEvent(EVENT_BLINK, 2s); + } + + if (me->IsWithinMeleeRange(me->GetVictim())) + { + events.RescheduleEvent(EVENT_EARTH_SHOCK, 2s); + DoMeleeAttackIfReady(); + } + } + +private: + float _hpct; + uint8 _flag; }; -class spell_skeram_arcane_explosion : public SpellScriptLoader +class spell_skeram_arcane_explosion : public SpellScript { -public: - spell_skeram_arcane_explosion() : SpellScriptLoader("spell_skeram_arcane_explosion") { } + PrepareSpellScript(spell_skeram_arcane_explosion); - class spell_skeram_arcane_explosion_SpellScript : public SpellScript + void FilterTargets(std::list& targets) { - PrepareSpellScript(spell_skeram_arcane_explosion_SpellScript); + targets.remove_if(PlayerOrPetCheck()); + } - void FilterTargets(std::list& targets) - { - targets.remove_if(PlayerOrPetCheck()); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_skeram_arcane_explosion_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - } - }; - - SpellScript* GetSpellScript() const override + void Register() override { - return new spell_skeram_arcane_explosion_SpellScript(); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_skeram_arcane_explosion::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; void AddSC_boss_skeram() { - new boss_skeram(); - new spell_skeram_arcane_explosion(); + RegisterTempleOfAhnQirajCreatureAI(boss_skeram); + RegisterSpellScript(spell_skeram_arcane_explosion); } diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp index 841280dcf..33b32fa44 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp @@ -377,223 +377,203 @@ struct boss_twinemperorsAI : public ScriptedAI } }; -class boss_veknilash : public CreatureScript +struct boss_veknilash : public boss_twinemperorsAI { -public: - boss_veknilash() : CreatureScript("boss_veknilash") { } + boss_veknilash(Creature* creature) : boss_twinemperorsAI(creature) { } - CreatureAI* GetAI(Creature* creature) const override + bool IAmVeklor() override { return false; } + + uint32 UpperCut_Timer; + uint32 UnbalancingStrike_Timer; + uint32 Scarabs_Timer; + int Rand; + int RandX; + int RandY; + + Creature* Summoned; + + void Reset() override { - return GetTempleOfAhnQirajAI(creature); + TwinReset(); + UpperCut_Timer = urand(14000, 29000); + UnbalancingStrike_Timer = urand(8000, 18000); + Scarabs_Timer = urand(7000, 14000); + + //Added. Can be removed if its included in DB. + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); } - struct boss_veknilashAI : public boss_twinemperorsAI + void CastSpellOnBug(Creature* target) override { - bool IAmVeklor() override {return false;} - boss_veknilashAI(Creature* creature) : boss_twinemperorsAI(creature) { } + target->SetFaction(FACTION_MONSTER); + target->AI()->AttackStart(me->GetThreatMgr().getHostileTarget()); + target->AddAura(SPELL_MUTATE_BUG, target); + target->SetFullHealth(); + } - uint32 UpperCut_Timer; - uint32 UnbalancingStrike_Timer; - uint32 Scarabs_Timer; - int Rand; - int RandX; - int RandY; + void UpdateAI(uint32 diff) override + { + //Return since we have no target + if (!UpdateVictim()) + return; - Creature* Summoned; + if (!TryActivateAfterTTelep(diff)) + return; - void Reset() override + //UnbalancingStrike_Timer + if (UnbalancingStrike_Timer <= diff) { - TwinReset(); - UpperCut_Timer = urand(14000, 29000); - UnbalancingStrike_Timer = urand(8000, 18000); - Scarabs_Timer = urand(7000, 14000); - - //Added. Can be removed if its included in DB. - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); + DoCastVictim(SPELL_UNBALANCING_STRIKE); + UnbalancingStrike_Timer = 8000 + rand() % 12000; } + else UnbalancingStrike_Timer -= diff; - void CastSpellOnBug(Creature* target) override + if (UpperCut_Timer <= diff) { - target->SetFaction(FACTION_MONSTER); - target->AI()->AttackStart(me->GetThreatMgr().getHostileTarget()); - target->AddAura(SPELL_MUTATE_BUG, target); - target->SetFullHealth(); + Unit* randomMelee = SelectTarget(SelectTargetMethod::Random, 0, NOMINAL_MELEE_RANGE, true); + if (randomMelee) + DoCast(randomMelee, SPELL_UPPERCUT); + UpperCut_Timer = 15000 + rand() % 15000; } + else UpperCut_Timer -= diff; - void UpdateAI(uint32 diff) override + HandleBugs(diff); + + //Heal brother when 60yrds close + TryHealBrother(diff); + + //Teleporting to brother + if (Teleport_Timer <= diff) { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!TryActivateAfterTTelep(diff)) - return; - - //UnbalancingStrike_Timer - if (UnbalancingStrike_Timer <= diff) - { - DoCastVictim(SPELL_UNBALANCING_STRIKE); - UnbalancingStrike_Timer = 8000 + rand() % 12000; - } - else UnbalancingStrike_Timer -= diff; - - if (UpperCut_Timer <= diff) - { - Unit* randomMelee = SelectTarget(SelectTargetMethod::Random, 0, NOMINAL_MELEE_RANGE, true); - if (randomMelee) - DoCast(randomMelee, SPELL_UPPERCUT); - UpperCut_Timer = 15000 + rand() % 15000; - } - else UpperCut_Timer -= diff; - - HandleBugs(diff); - - //Heal brother when 60yrds close - TryHealBrother(diff); - - //Teleporting to brother - if (Teleport_Timer <= diff) - { - TeleportToMyBrother(); - } - else Teleport_Timer -= diff; - - CheckEnrage(diff); - - DoMeleeAttackIfReady(); + TeleportToMyBrother(); } - }; + else Teleport_Timer -= diff; + + CheckEnrage(diff); + + DoMeleeAttackIfReady(); + } }; -class boss_veklor : public CreatureScript +struct boss_veklor : public boss_twinemperorsAI { -public: - boss_veklor() : CreatureScript("boss_veklor") { } + boss_veklor(Creature* creature) : boss_twinemperorsAI(creature) { } - CreatureAI* GetAI(Creature* creature) const override + bool IAmVeklor() override { return true; } + + uint32 ShadowBolt_Timer; + uint32 Blizzard_Timer; + uint32 ArcaneBurst_Timer; + uint32 Scorpions_Timer; + int Rand; + int RandX; + + Creature* Summoned; + + void Reset() override { - return GetTempleOfAhnQirajAI(creature); + TwinReset(); + ShadowBolt_Timer = 0; + Blizzard_Timer = urand(15000, 20000); + ArcaneBurst_Timer = 1000; + Scorpions_Timer = urand(7000, 14000); + + //Added. Can be removed if its included in DB. + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); } - struct boss_veklorAI : public boss_twinemperorsAI + void CastSpellOnBug(Creature* target) override { - bool IAmVeklor() override {return true;} - boss_veklorAI(Creature* creature) : boss_twinemperorsAI(creature) { } + target->SetFaction(FACTION_MONSTER); + target->AddAura(SPELL_EXPLODEBUG, target); + target->SetFullHealth(); + } - uint32 ShadowBolt_Timer; - uint32 Blizzard_Timer; - uint32 ArcaneBurst_Timer; - uint32 Scorpions_Timer; - int Rand; - int RandX; + void UpdateAI(uint32 diff) override + { + //Return since we have no target + if (!UpdateVictim()) + return; - Creature* Summoned; + // reset arcane burst after teleport - we need to do this because + // when VL jumps to VN's location there will be a warrior who will get only 2s to run away + // which is almost impossible + if (AfterTeleport) + ArcaneBurst_Timer = 5000; + if (!TryActivateAfterTTelep(diff)) + return; - void Reset() override + //ShadowBolt_Timer + if (ShadowBolt_Timer <= diff) { - TwinReset(); - ShadowBolt_Timer = 0; - Blizzard_Timer = urand(15000, 20000); - ArcaneBurst_Timer = 1000; - Scorpions_Timer = urand(7000, 14000); - - //Added. Can be removed if its included in DB. - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); + if (!me->IsWithinDist(me->GetVictim(), 45.0f)) + me->GetMotionMaster()->MoveChase(me->GetVictim(), VEKLOR_DIST, 0); + else + DoCastVictim(SPELL_SHADOWBOLT); + ShadowBolt_Timer = 2000; } + else ShadowBolt_Timer -= diff; - void CastSpellOnBug(Creature* target) override + //Blizzard_Timer + if (Blizzard_Timer <= diff) { - target->SetFaction(FACTION_MONSTER); - target->AddAura(SPELL_EXPLODEBUG, target); - target->SetFullHealth(); + Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 45, true); + if (target) + { + DoCast(target, SPELL_BLIZZARD); + } + Blizzard_Timer = 15000 + rand() % 15000; } + else Blizzard_Timer -= diff; - void UpdateAI(uint32 diff) override + if (ArcaneBurst_Timer <= diff) { - //Return since we have no target - if (!UpdateVictim()) - return; - - // reset arcane burst after teleport - we need to do this because - // when VL jumps to VN's location there will be a warrior who will get only 2s to run away - // which is almost impossible - if (AfterTeleport) + Unit* mvic; + if ((mvic = SelectTarget(SelectTargetMethod::MaxDistance, 0, NOMINAL_MELEE_RANGE, true)) != nullptr) + { + DoCast(mvic, SPELL_ARCANEBURST); ArcaneBurst_Timer = 5000; - if (!TryActivateAfterTTelep(diff)) - return; - - //ShadowBolt_Timer - if (ShadowBolt_Timer <= diff) - { - if (!me->IsWithinDist(me->GetVictim(), 45.0f)) - me->GetMotionMaster()->MoveChase(me->GetVictim(), VEKLOR_DIST, 0); - else - DoCastVictim(SPELL_SHADOWBOLT); - ShadowBolt_Timer = 2000; } - else ShadowBolt_Timer -= diff; - - //Blizzard_Timer - if (Blizzard_Timer <= diff) - { - Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 45, true); - if (target) - { - DoCast(target, SPELL_BLIZZARD); - } - Blizzard_Timer = 15000 + rand() % 15000; - } - else Blizzard_Timer -= diff; - - if (ArcaneBurst_Timer <= diff) - { - Unit* mvic; - if ((mvic = SelectTarget(SelectTargetMethod::MaxDistance, 0, NOMINAL_MELEE_RANGE, true)) != nullptr) - { - DoCast(mvic, SPELL_ARCANEBURST); - ArcaneBurst_Timer = 5000; - } - } - else ArcaneBurst_Timer -= diff; - - HandleBugs(diff); - - //Heal brother when 60yrds close - TryHealBrother(diff); - - //Teleporting to brother - if (Teleport_Timer <= diff) - { - TeleportToMyBrother(); - } - else Teleport_Timer -= diff; - - CheckEnrage(diff); - - //VL doesn't melee - //DoMeleeAttackIfReady(); } + else ArcaneBurst_Timer -= diff; - void AttackStart(Unit* who) override + HandleBugs(diff); + + //Heal brother when 60yrds close + TryHealBrother(diff); + + //Teleporting to brother + if (Teleport_Timer <= diff) { - if (!who) - return; + TeleportToMyBrother(); + } + else Teleport_Timer -= diff; - if (who->isTargetableForAttack()) + CheckEnrage(diff); + + //VL doesn't melee + //DoMeleeAttackIfReady(); + } + + void AttackStart(Unit* who) override + { + if (!who) + return; + + if (who->isTargetableForAttack()) + { + // VL doesn't melee + if (me->Attack(who, false)) { - // VL doesn't melee - if (me->Attack(who, false)) - { - me->GetMotionMaster()->MoveChase(who, VEKLOR_DIST, 0); - me->AddThreat(who, 0.0f); - } + me->GetMotionMaster()->MoveChase(who, VEKLOR_DIST, 0); + me->AddThreat(who, 0.0f); } } - }; + } }; void AddSC_boss_twinemperors() { - new boss_veknilash(); - new boss_veklor(); + RegisterTempleOfAhnQirajCreatureAI(boss_veknilash); + RegisterTempleOfAhnQirajCreatureAI(boss_veklor); } diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp index a993aa06e..e5e0834d1 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp @@ -84,223 +84,201 @@ enum MovePoints Position const ViscidusCoord = { -7992.36f, 908.19f, -52.62f, 1.68f }; /// @todo Visci isn't in room middle float const RoomRadius = 40.0f; /// @todo Not sure if its correct -class boss_viscidus : public CreatureScript +struct boss_viscidus : public BossAI { -public: - boss_viscidus() : CreatureScript("boss_viscidus") { } + boss_viscidus(Creature* creature) : BossAI(creature, DATA_VISCIDUS) { } - struct boss_viscidusAI : public BossAI + void Reset() override { - boss_viscidusAI(Creature* creature) : BossAI(creature, DATA_VISCIDUS) { } + _Reset(); + _hitcounter = 0; + _phase = PHASE_FROST; + } - void Reset() override + void DamageTaken(Unit* attacker, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override + { + if (!attacker || _phase != PHASE_MELEE) + return; + + ++_hitcounter; + + if (attacker->HasUnitState(UNIT_STATE_MELEE_ATTACKING) && _hitcounter >= HITCOUNTER_EXPLODE) { - _Reset(); - _hitcounter = 0; - _phase = PHASE_FROST; + Talk(EMOTE_EXPLODE); + events.Reset(); + _phase = PHASE_GLOB; + DoCast(me, SPELL_VISCIDUS_EXPLODE); + me->SetVisible(false); + me->RemoveAura(SPELL_TOXIN); + me->RemoveAura(SPELL_VISCIDUS_FREEZE); + + uint8 NumGlobes = me->GetHealthPct() / 5.0f; + for (uint8 i = 0; i < NumGlobes; ++i) + { + float Angle = i * 2 * M_PI / NumGlobes; + float X = ViscidusCoord.GetPositionX() + std::cos(Angle) * RoomRadius; + float Y = ViscidusCoord.GetPositionY() + std::sin(Angle) * RoomRadius; + float Z = -35.0f; + + if (TempSummon* Glob = me->SummonCreature(NPC_GLOB_OF_VISCIDUS, X, Y, Z)) + { + Glob->UpdateAllowedPositionZ(X, Y, Z); + Glob->NearTeleportTo(X, Y, Z, 0.0f); + Glob->GetMotionMaster()->MovePoint(ROOM_CENTER, ViscidusCoord); + } + } } + else if (_hitcounter == HITCOUNTER_SHATTER) + Talk(EMOTE_SHATTER); + else if (_hitcounter == HITCOUNTER_CRACK) + Talk(EMOTE_CRACK); + } - void DamageTaken(Unit* attacker, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override + { + if ((spell->GetSchoolMask() & SPELL_SCHOOL_MASK_FROST) && _phase == PHASE_FROST && me->GetHealthPct() > 5.0f) { - if (!attacker || _phase != PHASE_MELEE) - return; - ++_hitcounter; - if (attacker->HasUnitState(UNIT_STATE_MELEE_ATTACKING) && _hitcounter >= HITCOUNTER_EXPLODE) + if (_hitcounter >= HITCOUNTER_FREEZE) { - Talk(EMOTE_EXPLODE); - events.Reset(); - _phase = PHASE_GLOB; - DoCast(me, SPELL_VISCIDUS_EXPLODE); - me->SetVisible(false); - me->RemoveAura(SPELL_TOXIN); - me->RemoveAura(SPELL_VISCIDUS_FREEZE); - - uint8 NumGlobes = me->GetHealthPct() / 5.0f; - for (uint8 i = 0; i < NumGlobes; ++i) - { - float Angle = i * 2 * M_PI / NumGlobes; - float X = ViscidusCoord.GetPositionX() + std::cos(Angle) * RoomRadius; - float Y = ViscidusCoord.GetPositionY() + std::sin(Angle) * RoomRadius; - float Z = -35.0f; - - if (TempSummon* Glob = me->SummonCreature(NPC_GLOB_OF_VISCIDUS, X, Y, Z)) - { - Glob->UpdateAllowedPositionZ(X, Y, Z); - Glob->NearTeleportTo(X, Y, Z, 0.0f); - Glob->GetMotionMaster()->MovePoint(ROOM_CENTER, ViscidusCoord); - } - } - } - else if (_hitcounter == HITCOUNTER_SHATTER) - Talk(EMOTE_SHATTER); - else if (_hitcounter == HITCOUNTER_CRACK) - Talk(EMOTE_CRACK); - } - - void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override - { - if ((spell->GetSchoolMask() & SPELL_SCHOOL_MASK_FROST) && _phase == PHASE_FROST && me->GetHealthPct() > 5.0f) - { - ++_hitcounter; - - if (_hitcounter >= HITCOUNTER_FREEZE) - { - _hitcounter = 0; - Talk(EMOTE_FROZEN); - _phase = PHASE_MELEE; - DoCast(me, SPELL_VISCIDUS_FREEZE); - me->RemoveAura(SPELL_VISCIDUS_SLOWED_MORE); - events.ScheduleEvent(EVENT_RESET_PHASE, 15000); - } - else if (_hitcounter >= HITCOUNTER_SLOW_MORE) - { - Talk(EMOTE_FREEZE); - me->RemoveAura(SPELL_VISCIDUS_SLOWED); - DoCast(me, SPELL_VISCIDUS_SLOWED_MORE); - } - else if (_hitcounter >= HITCOUNTER_SLOW) - { - Talk(EMOTE_SLOW); - DoCast(me, SPELL_VISCIDUS_SLOWED); - } - } - } - - void EnterCombat(Unit* /*who*/) override - { - _EnterCombat(); - events.Reset(); - InitSpells(); - } - - void InitSpells() - { - DoCast(me, SPELL_TOXIN); - events.ScheduleEvent(EVENT_POISONBOLT_VOLLEY, urand(10000, 15000)); - events.ScheduleEvent(EVENT_POISON_SHOCK, urand(7000, 12000)); - } - - void EnterEvadeMode(EvadeReason why) override - { - summons.DespawnAll(); - ScriptedAI::EnterEvadeMode(why); - } - - void JustDied(Unit* /*killer*/) override - { - DoCast(me, SPELL_VISCIDUS_SUICIDE); - summons.DespawnAll(); - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - if (_phase == PHASE_GLOB && summons.empty()) - { - DoResetThreat(); - me->NearTeleportTo(ViscidusCoord.GetPositionX(), - ViscidusCoord.GetPositionY(), - ViscidusCoord.GetPositionZ(), - ViscidusCoord.GetOrientation()); - _hitcounter = 0; - _phase = PHASE_FROST; - InitSpells(); - me->SetVisible(true); + Talk(EMOTE_FROZEN); + _phase = PHASE_MELEE; + DoCast(me, SPELL_VISCIDUS_FREEZE); + me->RemoveAura(SPELL_VISCIDUS_SLOWED_MORE); + events.ScheduleEvent(EVENT_RESET_PHASE, 15000); } - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) + else if (_hitcounter >= HITCOUNTER_SLOW_MORE) { - switch (eventId) - { - case EVENT_POISONBOLT_VOLLEY: - DoCast(me, SPELL_POISONBOLT_VOLLEY); - events.ScheduleEvent(EVENT_POISONBOLT_VOLLEY, urand(10000, 15000)); - break; - case EVENT_POISON_SHOCK: - DoCast(me, SPELL_POISON_SHOCK); - events.ScheduleEvent(EVENT_POISON_SHOCK, urand(7000, 12000)); - break; - case EVENT_RESET_PHASE: - _hitcounter = 0; - _phase = PHASE_FROST; - break; - default: - break; - } + Talk(EMOTE_FREEZE); + me->RemoveAura(SPELL_VISCIDUS_SLOWED); + DoCast(me, SPELL_VISCIDUS_SLOWED_MORE); } + else if (_hitcounter >= HITCOUNTER_SLOW) + { + Talk(EMOTE_SLOW); + DoCast(me, SPELL_VISCIDUS_SLOWED); + } + } + } - if (_phase != PHASE_GLOB) - DoMeleeAttackIfReady(); + void EnterCombat(Unit* /*who*/) override + { + _EnterCombat(); + events.Reset(); + InitSpells(); + } + + void InitSpells() + { + DoCast(me, SPELL_TOXIN); + events.ScheduleEvent(EVENT_POISONBOLT_VOLLEY, 10s, 15s); + events.ScheduleEvent(EVENT_POISON_SHOCK, 7s, 12s); + } + + void EnterEvadeMode(EvadeReason why) override + { + summons.DespawnAll(); + ScriptedAI::EnterEvadeMode(why); + } + + void JustDied(Unit* /*killer*/) override + { + DoCast(me, SPELL_VISCIDUS_SUICIDE); + summons.DespawnAll(); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + if (_phase == PHASE_GLOB && summons.empty()) + { + DoResetThreat(); + me->NearTeleportTo(ViscidusCoord.GetPositionX(), + ViscidusCoord.GetPositionY(), + ViscidusCoord.GetPositionZ(), + ViscidusCoord.GetOrientation()); + + _hitcounter = 0; + _phase = PHASE_FROST; + InitSpells(); + me->SetVisible(true); } - private: - uint8 _hitcounter; - Phases _phase; - }; + events.Update(diff); - CreatureAI* GetAI(Creature* creature) const override - { - return GetTempleOfAhnQirajAI(creature); + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_POISONBOLT_VOLLEY: + DoCast(me, SPELL_POISONBOLT_VOLLEY); + events.ScheduleEvent(EVENT_POISONBOLT_VOLLEY, 10s, 15s); + break; + case EVENT_POISON_SHOCK: + DoCast(me, SPELL_POISON_SHOCK); + events.ScheduleEvent(EVENT_POISON_SHOCK, 7s, 12s); + break; + case EVENT_RESET_PHASE: + _hitcounter = 0; + _phase = PHASE_FROST; + break; + default: + break; + } + } + + if (_phase != PHASE_GLOB) + DoMeleeAttackIfReady(); } + +private: + uint8 _hitcounter; + Phases _phase; }; -class npc_glob_of_viscidus : public CreatureScript +struct boss_glob_of_viscidus : public ScriptedAI { -public: - npc_glob_of_viscidus() : CreatureScript("boss_glob_of_viscidus") { } + boss_glob_of_viscidus(Creature* creature) : ScriptedAI(creature) { } - struct npc_glob_of_viscidusAI : public ScriptedAI + void JustDied(Unit* /*killer*/) override { - npc_glob_of_viscidusAI(Creature* creature) : ScriptedAI(creature) { } + InstanceScript* instance = me->GetInstanceScript(); - void JustDied(Unit* /*killer*/) override + if (Creature* viscidus = me->GetMap()->GetCreature(instance->GetGuidData(DATA_VISCIDUS))) { - InstanceScript* Instance = me->GetInstanceScript(); + if (BossAI* viscidusAI = dynamic_cast(viscidus->GetAI())) + viscidusAI->SummonedCreatureDespawn(me); - if (Creature* Viscidus = me->GetMap()->GetCreature(Instance->GetGuidData(DATA_VISCIDUS))) + if (viscidus->IsAlive() && viscidus->GetHealthPct() < 5.0f) { - if (BossAI* ViscidusAI = dynamic_cast(Viscidus->GetAI())) - ViscidusAI->SummonedCreatureDespawn(me); - - if (Viscidus->IsAlive() && Viscidus->GetHealthPct() < 5.0f) - { - Viscidus->SetVisible(true); - Unit::Kill(Viscidus->GetVictim(), Viscidus); - } - else - { - Viscidus->SetHealth(Viscidus->GetHealth() - Viscidus->GetMaxHealth() / 20); - Viscidus->CastSpell(Viscidus, SPELL_VISCIDUS_SHRINKS); - } + viscidus->SetVisible(true); + Unit::Kill(viscidus->GetVictim(), viscidus); + } + else + { + viscidus->SetHealth(viscidus->GetHealth() - viscidus->GetMaxHealth() / 20); + viscidus->CastSpell(viscidus, SPELL_VISCIDUS_SHRINKS); } } + } - void MovementInform(uint32 /*type*/, uint32 id) override - { - if (id == ROOM_CENTER) - { - DoCast(me, SPELL_REJOIN_VISCIDUS); - if (TempSummon* summon = me->ToTempSummon()) - summon->UnSummon(); - } - } - }; - - CreatureAI* GetAI(Creature* creature) const override + void MovementInform(uint32 /*type*/, uint32 id) override { - return GetTempleOfAhnQirajAI(creature); + if (id == ROOM_CENTER) + { + DoCast(me, SPELL_REJOIN_VISCIDUS); + if (TempSummon* summon = me->ToTempSummon()) + summon->UnSummon(); + } } }; void AddSC_boss_viscidus() { - new boss_viscidus(); - new npc_glob_of_viscidus(); + RegisterTempleOfAhnQirajCreatureAI(boss_viscidus); + RegisterTempleOfAhnQirajCreatureAI(boss_glob_of_viscidus); } diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/instance_temple_of_ahnqiraj.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/instance_temple_of_ahnqiraj.cpp index 3056a305f..215e4c790 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/instance_temple_of_ahnqiraj.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/instance_temple_of_ahnqiraj.cpp @@ -30,7 +30,8 @@ EndScriptData */ ObjectData const creatureData[] = { { NPC_SARTURA, DATA_SARTURA }, - { NPC_EYE_OF_CTHUN, DATA_EYE_OF_CTHUN } + { NPC_EYE_OF_CTHUN, DATA_EYE_OF_CTHUN }, + { NPC_OURO_SPAWNER, DATA_OURO_SPAWNER } }; class instance_temple_of_ahnqiraj : public InstanceMapScript @@ -102,6 +103,10 @@ public: case NPC_VISCIDUS: ViscidusGUID = creature->GetGUID(); break; + case NPC_OURO_SPAWNER: + if (GetBossState(DATA_OURO) != DONE) + creature->Respawn(); + break; } InstanceScript::OnCreatureCreate(creature); @@ -177,6 +182,27 @@ public: break; } } + + bool SetBossState(uint32 type, EncounterState state) override + { + if (!InstanceScript::SetBossState(type, state)) + return false; + + switch (type) + { + case DATA_OURO: + if (state == FAIL) + { + if (Creature* ouroSpawner = GetCreature(DATA_OURO)) + ouroSpawner->Respawn(); + } + break; + default: + break; + } + + return true; + } }; }; diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/mob_anubisath_sentinel.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/mob_anubisath_sentinel.cpp index c2cb324f7..6d1e21635 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/mob_anubisath_sentinel.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/mob_anubisath_sentinel.cpp @@ -34,25 +34,33 @@ EndScriptData */ enum Spells { - SPELL_MENDING_BUFF = 2147, + SPELL_MENDING_BUFF = 2147, - SPELL_KNOCK_BUFF = 21737, - SPELL_KNOCK = 25778, - SPELL_MANAB_BUFF = 812, - SPELL_MANAB = 25779, + SPELL_KNOCK_BUFF = 21737, + SPELL_KNOCK = 25778, + SPELL_MANAB_BUFF = 812, + SPELL_MANAB = 25779, - SPELL_REFLECTAF_BUFF = 13022, - SPELL_REFLECTSFr_BUFF = 19595, - SPELL_THORNS_BUFF = 25777, + SPELL_REFLECTAF_BUFF = 13022, + SPELL_REFLECTSFr_BUFF = 19595, + SPELL_THORNS_BUFF = 25777, - SPELL_THUNDER_BUFF = 2834, - SPELL_THUNDER = 8732, + SPELL_THUNDER_BUFF = 2834, + SPELL_THUNDER = 8732, - SPELL_MSTRIKE_BUFF = 9347, - SPELL_MSTRIKE = 24573, + SPELL_MSTRIKE_BUFF = 9347, + SPELL_MSTRIKE = 24573, - SPELL_STORM_BUFF = 2148, - SPELL_STORM = 26546 + SPELL_STORM_BUFF = 2148, + SPELL_STORM = 26546, + + SPELL_SUMMON_SMALL_OBSIDIAN_CHUNK = 27627, // Server-side + + SPELL_TRANSFER_POWER = 2400, + SPELL_HEAL_BRETHEN = 26565, + SPELL_ENRAGE = 8599, + + TALK_ENRAGE = 0 }; class npc_anubisath_sentinel : public CreatureScript @@ -245,6 +253,7 @@ public: } ClearBuddyList(); gatherOthersWhenAggro = true; + _enraged = false; } void GainSentinelAbility(uint32 id) @@ -261,6 +270,20 @@ public: DoZoneInCombat(); } + void SpellHitTarget(Unit* target, SpellInfo const* spellInfo) override + { + if (spellInfo->Id == SPELL_TRANSFER_POWER) + { + if (Creature* sentinel = target->ToCreature()) + { + if (sentinel->IsAIEnabled) + { + CAST_AI(aqsentinelAI, sentinel->AI())->GainSentinelAbility(ability); + } + } + } + } + void JustDied(Unit* /*killer*/) override { for (int ni = 0; ni < 3; ++ni) @@ -270,10 +293,26 @@ public: continue; if (sent->isDead()) continue; - sent->ModifyHealth(int32(sent->CountPctFromMaxHealth(50))); - CAST_AI(aqsentinelAI, sent->AI())->GainSentinelAbility(ability); + DoCast(sent, SPELL_HEAL_BRETHEN, true); + DoCast(sent, SPELL_TRANSFER_POWER, true); + } + + DoCastSelf(SPELL_SUMMON_SMALL_OBSIDIAN_CHUNK, true); + } + + void DamageTaken(Unit* /*doneBy*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override + { + if (!_enraged && me->HealthBelowPctDamaged(50, damage)) + { + _enraged = true; + damage = 0; + DoCastSelf(SPELL_ENRAGE, true); + Talk(TALK_ENRAGE); } } + + private: + bool _enraged; }; }; diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h index d32f6dbd9..9301c9503 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h @@ -35,7 +35,10 @@ enum DataTypes DATA_VEKNILASH = 9, DATA_VEKNILASHISDEAD = 10, DATA_VEKNILASH_DEATH = 11, - DATA_BUG_TRIO_DEATH = 14, + DATA_FANKRISS = 12, + DATA_OURO = 13, + DATA_OURO_SPAWNER = 14, + DATA_BUG_TRIO_DEATH = 15, DATA_CTHUN_PHASE = 20, DATA_VISCIDUS = 21, DATA_SARTURA = 22, @@ -55,7 +58,7 @@ enum Creatures NPC_GIANT_EYE_TENTACLE = 15334, NPC_FLESH_TENTACLE = 15802, NPC_GIANT_PORTAL = 15910, - + NPC_SARTURA_ROYAL_GUARD = 15984, NPC_VISCIDUS = 15299, NPC_GLOB_OF_VISCIDUS = 15667, @@ -66,6 +69,7 @@ enum Creatures NPC_VEKLOR = 15276, NPC_VEKNILASH = 15275, NPC_OURO = 15517, + NPC_OURO_SPAWNER = 15957, NPC_SARTURA = 15516 }; @@ -75,4 +79,6 @@ inline AI* GetTempleOfAhnQirajAI(T* obj) return GetInstanceAI(obj, TempleOfAhnQirajScriptName); } +#define RegisterTempleOfAhnQirajCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetTempleOfAhnQirajAI) + #endif diff --git a/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp b/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp index c3391cbdd..e628322e3 100644 --- a/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp +++ b/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp @@ -57,6 +57,7 @@ void AddSC_boss_moam(); void AddSC_boss_buru(); void AddSC_boss_ayamiss(); void AddSC_boss_ossirian(); +void AddSC_ruins_of_ahnqiraj(); void AddSC_instance_ruins_of_ahnqiraj(); void AddSC_boss_cthun(); //Temple of ahn'qiraj void AddSC_boss_viscidus(); @@ -139,6 +140,7 @@ void AddKalimdorScripts() AddSC_boss_buru(); AddSC_boss_ayamiss(); AddSC_boss_ossirian(); + AddSC_ruins_of_ahnqiraj(); AddSC_instance_ruins_of_ahnqiraj(); AddSC_boss_cthun(); //Temple of ahn'qiraj AddSC_boss_viscidus(); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp index 7daf57746..ebf54535a 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp @@ -118,11 +118,11 @@ public: if( pInstance ) pInstance->SetData(TYPE_JARAXXUS, NOT_STARTED); - // checked for safety - while( Creature* c = me->FindNearestCreature(NPC_INFERNAL_VOLCANO, 500.0f, true) ) - c->DespawnOrUnsummon(); - while( Creature* c = me->FindNearestCreature(NPC_NETHER_PORTAL, 500.0f, true) ) - c->DespawnOrUnsummon(); + std::list creatures; + me->GetCreatureListWithEntryInGrid(creatures, NPC_INFERNAL_VOLCANO, 500.f); + me->GetCreatureListWithEntryInGrid(creatures, NPC_NETHER_PORTAL, 500.f); + for (Creature* creature : creatures) + creature->DespawnOrUnsummon(); } void EnterCombat(Unit* /*who*/) override diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 8204f55b4..6036ab00d 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -1199,7 +1199,7 @@ class spell_gen_adaptive_warding : public AuraScript bool CheckProc(ProcEventInfo& eventInfo) { - if (eventInfo.GetSpellInfo()) + if (!eventInfo.GetSpellInfo()) return false; // find Mage Armor diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp index 0e715bf55..759141d94 100644 --- a/src/server/scripts/Spells/spell_hunter.cpp +++ b/src/server/scripts/Spells/spell_hunter.cpp @@ -666,10 +666,13 @@ class spell_hun_readiness : public SpellScript && spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != SPELL_HUNTER_READINESS && spellInfo->Id != SPELL_HUNTER_BESTIAL_WRATH - && spellInfo->Id != SPELL_DRAENEI_GIFT_OF_THE_NAARU - && spellInfo->GetRecoveryTime() > 0) + && spellInfo->Id != SPELL_DRAENEI_GIFT_OF_THE_NAARU) { - caster->RemoveSpellCooldown(spellInfo->Id, itr->second.needSendToClient); + if (spellInfo->RecoveryTime > 0) + caster->RemoveSpellCooldown(spellInfo->Id, itr->second.needSendToClient); + + if (spellInfo->CategoryRecoveryTime > 0) + caster->RemoveCategoryCooldown(spellInfo->GetCategory()); } } } diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index 384bee7da..89624091b 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -428,9 +428,26 @@ class spell_pri_lightwell_renew : public AuraScript } } + void HandleUpdateSpellclick(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + { + if (Player* player = GetTarget()->ToPlayer()) + { + UpdateData data; + WorldPacket packet; + caster->BuildValuesUpdateBlockForPlayer(&data, player); + data.BuildPacket(&packet); + player->SendDirectMessage(&packet); + } + } + } + void Register() override { DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_pri_lightwell_renew::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_HEAL); + AfterEffectApply += AuraEffectApplyFn(spell_pri_lightwell_renew::HandleUpdateSpellclick, EFFECT_0, SPELL_AURA_PERIODIC_HEAL, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_pri_lightwell_renew::HandleUpdateSpellclick, EFFECT_0, SPELL_AURA_PERIODIC_HEAL, AURA_EFFECT_HANDLE_REAL); } }; diff --git a/src/server/scripts/World/boss_emerald_dragons.cpp b/src/server/scripts/World/boss_emerald_dragons.cpp index 5d0a3d35e..a45f55d13 100644 --- a/src/server/scripts/World/boss_emerald_dragons.cpp +++ b/src/server/scripts/World/boss_emerald_dragons.cpp @@ -22,6 +22,7 @@ #include "Spell.h" #include "SpellAuraEffects.h" #include "SpellScript.h" +#include "TaskScheduler.h" // // Emerald Dragon NPCs and IDs (kept here for reference) @@ -34,6 +35,9 @@ enum EmeraldDragonNPC DRAGON_LETHON = 14888, DRAGON_EMERISS = 14889, DRAGON_TAERAR = 14890, + + GUID_DRAGON = 1, + GUID_FOG_TARGET = 2 }; // @@ -64,6 +68,7 @@ enum Events EVENT_SEEPING_FOG = 1, EVENT_NOXIOUS_BREATH, EVENT_TAIL_SWEEP, + EVENT_SUMMON_PLAYER, // Ysondre EVENT_LIGHTNING_WAVE, @@ -102,6 +107,7 @@ struct emerald_dragonAI : public WorldBossAI events.ScheduleEvent(EVENT_TAIL_SWEEP, 4000); events.ScheduleEvent(EVENT_NOXIOUS_BREATH, urand(7500, 15000)); events.ScheduleEvent(EVENT_SEEPING_FOG, urand(12500, 20000)); + events.ScheduleEvent(EVENT_SUMMON_PLAYER, 1s); } // Target killed during encounter, mark them as suspectible for Aura Of Nature @@ -133,6 +139,20 @@ struct emerald_dragonAI : public WorldBossAI DoCast(me, SPELL_TAIL_SWEEP); events.ScheduleEvent(EVENT_TAIL_SWEEP, 2000); break; + case EVENT_SUMMON_PLAYER: + if (Unit* target = me->GetVictim()) + if (!target->IsWithinRange(me, 50.f)) + DoCast(target, SPELL_SUMMON_PLAYER); + events.ScheduleEvent(EVENT_SUMMON_PLAYER, 500ms); + break; + } + } + + void JustSummoned(Creature* summon) override + { + if (summon->GetEntry() == NPC_DREAM_FOG) + { + summon->AI()->SetGUID(me->GetGUID(), GUID_DRAGON); } } @@ -149,9 +169,6 @@ struct emerald_dragonAI : public WorldBossAI while (uint32 eventId = events.ExecuteEvent()) ExecuteEvent(eventId); - if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 0, -50.0f, true)) - DoCast(target, SPELL_SUMMON_PLAYER); - DoMeleeAttackIfReady(); } }; @@ -167,13 +184,66 @@ public: struct npc_dream_fogAI : public ScriptedAI { - npc_dream_fogAI(Creature* creature) : ScriptedAI(creature) - { - } + npc_dream_fogAI(Creature* creature) : ScriptedAI(creature) { } void Reset() override { - _roamTimer = 0; + ScheduleEvents(); + } + + void ScheduleEvents() + { + _scheduler.CancelAll(); + + _scheduler.Schedule(1s, [this](TaskContext context) + { + // Chase target, but don't attack - otherwise just roam around + if (Unit* chaseTarget = GetRandomUnitFromDragonThreatList()) + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveFollow(chaseTarget, 0.02f, 0.0f); + _targetGUID = chaseTarget->GetGUID(); + context.Repeat(15s, 30s); + } + else + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveRandom(25.0f); + context.Repeat(2500ms); + } + + // Seeping fog movement is slow enough for a player to be able to walk backwards and still outpace it + me->SetWalk(true); + me->SetSpeed(MOVE_WALK, 0.75f); + }); + } + + void SetGUID(ObjectGuid guid, int32 type) override + { + if (type == GUID_DRAGON) + { + _dragonGUID = guid; + } + else if (type == GUID_FOG_TARGET) + { + if (guid == _targetGUID) + { + ScheduleEvents(); + } + } + } + + Unit* GetRandomUnitFromDragonThreatList() + { + if (Creature* dragon = ObjectAccessor::GetCreature(*me, _dragonGUID)) + { + if (dragon->GetAI()) + { + return dragon->GetAI()->SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true); + } + } + + return nullptr; } void UpdateAI(uint32 diff) override @@ -181,31 +251,13 @@ public: if (!UpdateVictim()) return; - if (!_roamTimer) - { - // Chase target, but don't attack - otherwise just roam around - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true)) - { - _roamTimer = urand(15000, 30000); - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveChase(target, 0.2f); - } - else - { - _roamTimer = 2500; - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveRandom(25.0f); - } - // Seeping fog movement is slow enough for a player to be able to walk backwards and still outpace it - me->SetWalk(true); - me->SetSpeed(MOVE_WALK, 0.75f); - } - else - _roamTimer -= diff; + _scheduler.Update(diff); } private: - uint32 _roamTimer; + ObjectGuid _targetGUID; + ObjectGuid _dragonGUID; + TaskScheduler _scheduler; }; CreatureAI* GetAI(Creature* creature) const override @@ -609,6 +661,7 @@ public: ++_stage; } } + void ExecuteEvent(uint32 eventId) override { switch (eventId) @@ -687,6 +740,17 @@ public: { PrepareSpellScript(spell_dream_fog_sleep_SpellScript); + void HandleEffect(SpellEffIndex /*effIndex*/) + { + if (Unit* caster = GetCaster()) + { + if (Unit* target = GetHitUnit()) + { + caster->GetAI()->SetGUID(target->GetGUID(), GUID_FOG_TARGET); + } + } + } + void FilterTargets(std::list& targets) { targets.remove_if(Acore::UnitAuraCheck(true, SPELL_SLEEP)); @@ -694,6 +758,7 @@ public: void Register() override { + OnEffectHitTarget += SpellEffectFn(spell_dream_fog_sleep_SpellScript::HandleEffect, EFFECT_0, SPELL_EFFECT_APPLY_AURA); OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dream_fog_sleep_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); } }; diff --git a/src/server/scripts/World/npc_stave_of_ancients.cpp b/src/server/scripts/World/npc_stave_of_ancients.cpp index e8d32856f..8ce88a0d5 100644 --- a/src/server/scripts/World/npc_stave_of_ancients.cpp +++ b/src/server/scripts/World/npc_stave_of_ancients.cpp @@ -394,6 +394,14 @@ public: DoMeleeAttackIfReady(); } + void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType, SpellSchoolMask) override + { + if (attacker == me) + { + me->LowerPlayerDamageReq(damage); + } + } + void SpellHit(Unit* /*Caster*/, SpellInfo const* Spell) override { uint32 serpentStings[12] = { 1978, 13549, 13550, 13551, 13552, 13553, 13554, 13555, 25295, 27016, 49000, 49001 }; @@ -1173,6 +1181,14 @@ public: } } + void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType, SpellSchoolMask) override + { + if (attacker == me) + { + me->LowerPlayerDamageReq(damage); + } + } + void ScheduleEncounterStart(ObjectGuid playerGUID) { PrepareForEncounter(); diff --git a/src/server/shared/DataStores/DBCEnums.h b/src/server/shared/DataStores/DBCEnums.h index ff66f1a8e..525cf05d8 100644 --- a/src/server/shared/DataStores/DBCEnums.h +++ b/src/server/shared/DataStores/DBCEnums.h @@ -415,33 +415,33 @@ enum TotemCategoryType // SummonProperties.dbc, col 1 enum SummonPropGroup { - SUMMON_PROP_GROUP_UNKNOWN1 = 0, // 1160 spells in 3.0.3 - SUMMON_PROP_GROUP_UNKNOWN2 = 1, // 861 spells in 3.0.3 - SUMMON_PROP_GROUP_PETS = 2, // 52 spells in 3.0.3, pets mostly - SUMMON_PROP_GROUP_CONTROLLABLE = 3, // 13 spells in 3.0.3, mostly controllable - SUMMON_PROP_GROUP_UNKNOWN3 = 4 // 86 spells in 3.0.3, taxi/mounts + SUMMON_PROP_GROUP_NONE = 0, // 1160 spells in 3.0.3 + SUMMON_PROP_GROUP_GUARDIAN = 1, // 861 spells in 3.0.3 TODO: Needs implementation + SUMMON_PROP_GROUP_PETS = 2, // 52 spells in 3.0.3, pets mostly TODO: Needs implementation + SUMMON_PROP_GROUP_CONTROLLABLE = 3, // 13 spells in 3.0.3, mostly controllable TODO: Needs implementation + SUMMON_PROP_GROUP_VEHICLE = 4 // 86 spells in 3.0.3, taxi/mounts TODO: Needs implementation }; // SummonProperties.dbc, col 5 enum SummonPropFlags { - SUMMON_PROP_FLAG_NONE = 0x00000000, // 1342 spells in 3.0.3 - SUMMON_PROP_FLAG_UNK1 = 0x00000001, // 75 spells in 3.0.3, something unfriendly - SUMMON_PROP_FLAG_UNK2 = 0x00000002, // 616 spells in 3.0.3, something friendly - SUMMON_PROP_FLAG_UNK3 = 0x00000004, // 22 spells in 3.0.3, no idea... - SUMMON_PROP_FLAG_DESPAWN_ON_SUMMONER_DEATH = 0x00000008, // 49 spells in 3.0.3, some mounts - SUMMON_PROP_FLAG_PERSONAL_SPAWN = 0x00000010, // 25 spells in 3.0.3, quest related? - SUMMON_PROP_FLAG_UNK6 = 0x00000020, // 0 spells in 3.3.5, unused - SUMMON_PROP_FLAG_UNK7 = 0x00000040, // 12 spells in 3.0.3, no idea - SUMMON_PROP_FLAG_UNK8 = 0x00000080, // 4 spells in 3.0.3, no idea - SUMMON_PROP_FLAG_UNK9 = 0x00000100, // 51 spells in 3.0.3, no idea, many quest related - SUMMON_PROP_FLAG_UNK10 = 0x00000200, // 51 spells in 3.0.3, something defensive - SUMMON_PROP_FLAG_UNK11 = 0x00000400, // 3 spells, requires something near? - SUMMON_PROP_FLAG_UNK12 = 0x00000800, // 30 spells in 3.0.3, no idea - SUMMON_PROP_FLAG_UNK13 = 0x00001000, // Lightwell, Jeeves, Gnomish Alarm-o-bot, Build vehicles(wintergrasp) - SUMMON_PROP_FLAG_UNK14 = 0x00002000, // Guides, player follows - SUMMON_PROP_FLAG_UNK15 = 0x00004000, // Force of Nature, Shadowfiend, Feral Spirit, Summon Water Elemental - SUMMON_PROP_FLAG_UNK16 = 0x00008000, // Light/Dark Bullet, Soul/Fiery Consumption, Twisted Visage, Twilight Whelp. Phase related? + SUMMON_PROP_FLAG_NONE = 0x00000000, // 1342 spells in 3.0.3 + SUMMON_PROP_FLAG_ATTACK_SUMMONER = 0x00000001, // 75 spells in 3.0.3, something unfriendly TODO: Needs implementation + SUMMON_PROP_FLAG_ASSIST_COMBAT_SUMMON = 0x00000002, // 616 spells in 3.0.3, something friendly TODO: Needs implementation + SUMMON_PROP_FLAG_USE_LEVEL_OFFSET = 0x00000004, // 22 spells in 3.0.3, no idea... TODO: Needs implementation + SUMMON_PROP_FLAG_DESPAWN_ON_SUMMONER_DEATH = 0x00000008, // 49 spells in 3.0.3, some mounts TODO: Needs implementation + SUMMON_PROP_FLAG_ONLY_VISIBLE_TO_SUMMONER = 0x00000010, // 25 spells in 3.0.3, quest related? TODO: Needs implementation + SUMMON_PROP_FLAG_CANNOT_DISMISS_PET = 0x00000020, // 0 spells in 3.3.5, unused TODO: Needs implementation + SUMMON_PROP_FLAG_USE_DEMON_TIMEOUT = 0x00000040, // 12 spells in 3.0.3, no idea TODO: Needs implementation + SUMMON_PROP_FLAG_UNLIMITED_SUMMONS = 0x00000080, // 4 spells in 3.0.3, no idea TODO: Needs implementation + SUMMON_PROP_FLAG_USE_CREATURE_LEVEL = 0x00000100, // 51 spells in 3.0.3, no idea, many quest related TODO: Needs implementation + SUMMON_PROP_FLAG_JOIN_SUMMONER_SPAWN_GROUP = 0x00000200, // 51 spells in 3.0.3, something defensive TODO: Needs implementation + SUMMON_PROP_FLAG_DO_NOT_TOGGLE = 0x00000400, // 3 spells, requires something near? TODO: Needs implementation + SUMMON_PROP_FLAG_DESPAWN_WHEN_EXPIRED = 0x00000800, // 30 spells in 3.0.3, no idea TODO: Needs implementation + SUMMON_PROP_FLAG_USE_SUMMONER_FACTION = 0x00001000, // Lightwell, Jeeves, Gnomish Alarm-o-bot, Build vehicles(wintergrasp) TODO: Needs implementation + SUMMON_PROP_FLAG_DO_NOT_FOLLOW_MOUNTED_SUMMONER = 0x00002000, // Guides, player follows TODO: Needs implementation + SUMMON_PROP_FLAG_SAVE_PET_AUTOCAST = 0x00004000, // Force of Nature, Shadowfiend, Feral Spirit, Summon Water Elemental TODO: Needs implementation + SUMMON_PROP_FLAG_IGNORE_SUMMONER_PHASE = 0x00008000, // Light/Dark Bullet, Soul/Fiery Consumption, Twisted Visage, Twilight Whelp. Phase related? TODO: Needs implementation }; enum VehicleSeatFlags diff --git a/src/server/shared/DataStores/DBCStructure.h b/src/server/shared/DataStores/DBCStructure.h index 249167c0e..0370f9c95 100644 --- a/src/server/shared/DataStores/DBCStructure.h +++ b/src/server/shared/DataStores/DBCStructure.h @@ -22,6 +22,7 @@ #include "Define.h" #include "SharedDefines.h" #include "Util.h" +#include #include #include #include @@ -2239,6 +2240,7 @@ typedef std::map TaxiPathSetBySource; typedef std::vector TaxiPathNodeList; typedef std::vector TaxiPathNodesByPath; -#define TaxiMaskSize 14 -typedef uint32 TaxiMask[TaxiMaskSize]; +static constexpr size_t TaxiMaskSize = 14; +typedef std::array TaxiMask; + #endif