diff --git a/.github/actions/linux-build/action.yml b/.github/actions/linux-build/action.yml index 4109f918c..d06f88551 100644 --- a/.github/actions/linux-build/action.yml +++ b/.github/actions/linux-build/action.yml @@ -47,6 +47,7 @@ runs: shell: bash run: | sudo apt update + sudo apt remove needrestart #refer: https://github.com/actions/runner-images/issues/9937 sudo apt-get -y install ccache clang cmake curl google-perftools \ libmysqlclient-dev make unzip build-essential cmake-data \ libboost-all-dev libbz2-dev libncurses5-dev libmysql++-dev \ diff --git a/.github/labeler.yml b/.github/labeler.yml index d5987dac0..c41c0b22b 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,37 +1,54 @@ file-cpp: - - src/**/*.cpp - - src/**/*.h - - deps/**/*.cpp - - deps/**/*.h +- changed-files: + - any-glob-to-any-file: + - src/**/*.cpp + - src/**/*.h + - deps/**/*.cpp + - deps/**/*.h DB: - - data/**/*.sql +- changed-files: + - any-glob-to-any-file: data/**/*.sql CORE: - - any: ['src/**/*', '!src/server/scripts/*', '!src/tests/*'] +- all: + - changed-files: + - any-glob-to-any-file: 'src/**/*' + - all-globs-to-all-files: + - '!src/server/scripts/*' + - '!src/tests/*' Script: - - src/server/scripts/**/*.cpp - - src/server/scripts/**/*.h +- changed-files: + - any-glob-to-any-file: + - src/server/scripts/**/*.cpp + - src/server/scripts/**/*.h UnitTests: - - src/test/**/* +- changed-files: + - any-glob-to-any-file: src/test/**/* Documentation: - - ./*.md +- changed-files: + - any-glob-to-any-file: ./*.md Bash: - - ./*.sh - - apps/**/*.sh - - conf/**/*.sh - - deps/**/*.sh - - modules/**/*.sh +- changed-files: + - any-glob-to-any-file: + - ./*.sh + - apps/**/*.sh + - conf/**/*.sh + - deps/**/*.sh + - modules/**/*.sh CMake: - - ./*.cmake +- changed-files: + - any-glob-to-any-file: ./*.cmake Workflow: - - .github/workflows/* +- changed-files: + - any-glob-to-any-file: .github/workflows/* Batch: - - apps/**/*.bat +- changed-files: + - any-glob-to-any-file: apps/**/*.bat diff --git a/.github/workflows/pr_labeler.yml b/.github/workflows/pr_labeler.yml index 4e231bb0b..28ee6bd3d 100644 --- a/.github/workflows/pr_labeler.yml +++ b/.github/workflows/pr_labeler.yml @@ -11,7 +11,7 @@ jobs: - uses: actions/checkout@v4 with: persist-credentials: true - - uses: actions/labeler@v4 + - uses: actions/labeler@v5 with: repo-token: ${{ secrets.GITHUB_TOKEN }} configuration-path: .github/labeler.yml diff --git a/AUTHORS b/AUTHORS index ebf2b5f8a..8cf220b41 100644 --- a/AUTHORS +++ b/AUTHORS @@ -3,7 +3,7 @@ ## Warning The code of AzerothCore is shipped as it is without any form of warranty, and - except for third party libraries licensed under the AGPL 3, -which you can read from the file "LICENSE-AGPL3". +which you can read from the file "LICENSE". ## Point of current development The project is currently hosted at https://www.azerothcore.org/ and developed under https://github.com/azerothcore diff --git a/conf/dist/config.cmake b/conf/dist/config.cmake index 381cce46b..ab370f458 100644 --- a/conf/dist/config.cmake +++ b/conf/dist/config.cmake @@ -1,5 +1,5 @@ # -# Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3 +# Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE # Copyright (C) 2021+ WarheadCore # # This file is free software; as a special exception the author gives diff --git a/data/sql/updates/db_world/2024_05_26_00.sql b/data/sql/updates/db_world/2024_05_26_00.sql new file mode 100644 index 000000000..c127e92e5 --- /dev/null +++ b/data/sql/updates/db_world/2024_05_26_00.sql @@ -0,0 +1,3 @@ +-- DB update 2024_05_25_01 -> 2024_05_26_00 +-- +UPDATE `spell_proc_event` SET `Cooldown`=600 WHERE `entry`=69762; diff --git a/data/sql/updates/db_world/2024_05_26_01.sql b/data/sql/updates/db_world/2024_05_26_01.sql new file mode 100644 index 000000000..818e87dfd --- /dev/null +++ b/data/sql/updates/db_world/2024_05_26_01.sql @@ -0,0 +1,5 @@ +-- DB update 2024_05_26_00 -> 2024_05_26_01 +-- +DELETE FROM `creature_text` WHERE (`CreatureID` = 22515) AND (`GroupID` = 19); +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(22515, 19, 0, 'The Ancient Gate of the Keepers unlocks!', 41, 0, 100, 0, 0, 0, 34401, 0, 'Ulduar - The Ancient Gate of the Keepers unlocks!'); diff --git a/data/sql/updates/db_world/2024_05_26_02.sql b/data/sql/updates/db_world/2024_05_26_02.sql new file mode 100644 index 000000000..49b4f76e4 --- /dev/null +++ b/data/sql/updates/db_world/2024_05_26_02.sql @@ -0,0 +1,6 @@ +-- DB update 2024_05_26_01 -> 2024_05_26_02 +-- +DELETE FROM `creature` WHERE `id1` = 33742; +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 +(136768, 33742, 0, 0, 603, 0, 0, 3, 1, 0, 1809.8663330078125, -38.2449531555175781, 408.03680419921875, 0, 180, 0, 0, 26066, 0, 0, 0, 0, 0, '', 47720); +UPDATE `creature_template` SET `ScriptName` = 'boss_kologarn_pit_kill_bunny' WHERE `entry` = 33742; diff --git a/data/sql/updates/db_world/2024_05_27_00.sql b/data/sql/updates/db_world/2024_05_27_00.sql new file mode 100644 index 000000000..53ae78173 --- /dev/null +++ b/data/sql/updates/db_world/2024_05_27_00.sql @@ -0,0 +1,24 @@ +-- DB update 2024_05_26_02 -> 2024_05_27_00 +-- update DONT_OVERRIDE_SAI_ENTRY +-- #18734 +UPDATE `creature_template` SET `flags_extra` = 134217728 WHERE (`entry` = 4300); +UPDATE `creature_template` SET `flags_extra` = 134217728 WHERE (`entry` = 4301); +UPDATE `creature_template` SET `flags_extra` = 134217728 WHERE (`entry` = 4294); +UPDATE `creature_template` SET `flags_extra` = 134217728 WHERE (`entry` = 4295); +UPDATE `creature_template` SET `flags_extra` = 134217728 WHERE (`entry` = 4299); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 429400); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(429400, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 2, 35, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Monaster AshbringerEvent - Actionlist - Set_Faction Friend'), +(429400, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Monaster AshbringerEvent - Actionlist - stop movement'), +-- new add +(429400, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 212, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Monaster AshbringerEvent - Actionlist - Stop motion (StopMoving: 1, MovementExpired: 1)'), +(429400, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Monaster AshbringerEvent - Actionlist - Set Facing player'), +(429400, 9, 4, 0, 0, 0, 100, 0, 500, 500, 0, 0, 0, 0, 91, 8, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Monaster AshbringerEvent - Actionlist - SetStandState UNIT_STAND_STATE_STAND'), +(429400, 9, 5, 0, 0, 0, 100, 0, 500, 2500, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Monaster AshbringerEvent - Actionlist - SetSheath SHEATH_STATE_UNARMED'), +(429400, 9, 6, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 90, 8, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Monaster AshbringerEvent - Actionlist - SetSheath UNIT_STAND_STATE_KNEEL'), +(429400, 9, 7, 0, 0, 0, 50, 0, 1000, 2000, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Monaster AshbringerEvent - Actionlist - Talk 0'); + +-- #18850 fix +UPDATE `creature_template` SET `flags_extra` = 134217728 WHERE (`entry` = 27202); +UPDATE `creature_template` SET `flags_extra` = 134217728 WHERE (`entry` = 27203); diff --git a/data/sql/updates/db_world/2024_05_27_01.sql b/data/sql/updates/db_world/2024_05_27_01.sql new file mode 100644 index 000000000..18dac0804 --- /dev/null +++ b/data/sql/updates/db_world/2024_05_27_01.sql @@ -0,0 +1,5 @@ +-- DB update 2024_05_27_00 -> 2024_05_27_01 +-- +DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_azgalor_doom' AND `spell_id` = 31347; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(31347, 'spell_azgalor_doom'); diff --git a/data/sql/updates/db_world/2024_05_27_02.sql b/data/sql/updates/db_world/2024_05_27_02.sql new file mode 100644 index 000000000..0bdbf3bf5 --- /dev/null +++ b/data/sql/updates/db_world/2024_05_27_02.sql @@ -0,0 +1,5 @@ +-- DB update 2024_05_27_01 -> 2024_05_27_02 +-- +DELETE FROM `spell_linked_spell` WHERE `spell_trigger` = -42201 AND `spell_effect` = 42205; +INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES +(-42201, 42205, 0, 'Eternal Silence trigger Residue of Eternity on removal'); diff --git a/data/sql/updates/db_world/2024_05_28_00.sql b/data/sql/updates/db_world/2024_05_28_00.sql new file mode 100644 index 000000000..2d0e8b2e4 --- /dev/null +++ b/data/sql/updates/db_world/2024_05_28_00.sql @@ -0,0 +1,20 @@ +-- DB update 2024_05_27_02 -> 2024_05_28_00 +-- +-- Rocket Booster +UPDATE `gameobject` SET `position_x`=2307.000003, `position_y`=265.6011, `position_z`=424.287993 WHERE (`id` = 194904) AND (`guid` IN (35524)); +-- Delete 2nd Activate Tram gameobject +DELETE FROM `gameobject` WHERE `id` = 194438; +UPDATE `gameobject_template` SET `ScriptName` = '' WHERE `entry` = 194438; +-- Call Tram objects start as non-selectable +UPDATE `gameobject_template_addon` SET `flags` = `flags` | 16 WHERE `entry` IN (194912, 194914); +-- Buttons +UPDATE `gameobject_template` SET `AIName` = 'SmartGameObjectAI', `ScriptName` = '' WHERE `entry` IN (194437,194912,194914); +DELETE FROM `smart_scripts` WHERE (`entryorguid` IN (194437,194912,194914)) AND (`source_type` = 1); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(194437, 1, 0, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Activate Tram - On Respawn - Set Event Phase 1'), +(194437, 1, 1, 2, 64, 1, 100, 0, 0, 0, 0, 0, 0, 0, 34, 710, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Activate Tram - On Gossip Hello - Set Instance Data 710 to 1 (Phase 1)'), +(194437, 1, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Activate Tram - On Gossip Hello - Set Event Phase 2 (Phase 1)'), +(194437, 1, 3, 4, 64, 2, 100, 0, 0, 0, 0, 0, 0, 0, 34, 710, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Activate Tram - On Gossip Hello - Set Instance Data 710 to 0 (Phase 2)'), +(194437, 1, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Activate Tram - On Gossip Hello - Set Event Phase 1 (Phase 2)'), +(194912, 1, 0, 0, 64, 0, 100, 0, 0, 0, 0, 0, 0, 0, 34, 710, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Call Tram - On Gossip Hello - Set Instance Data 710 to 1'), +(194914, 1, 0, 0, 64, 0, 100, 0, 0, 0, 0, 0, 0, 0, 34, 710, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Call Tram - On Gossip Hello - Set Instance Data 710 to 0'); diff --git a/data/sql/updates/db_world/2024_05_29_00.sql b/data/sql/updates/db_world/2024_05_29_00.sql new file mode 100644 index 000000000..5b2dbda9e --- /dev/null +++ b/data/sql/updates/db_world/2024_05_29_00.sql @@ -0,0 +1,4 @@ +-- DB update 2024_05_28_00 -> 2024_05_29_00 +-- +DELETE FROM `smart_scripts` WHERE `entryorguid` = 18104 AND `source_type` = 0; +UPDATE `creature_template` SET `speed_run` = 3, `AIName` = '', `ScriptName` = 'npc_doomfire_spirit' WHERE `entry` = 18104; diff --git a/data/sql/updates/db_world/2024_06_01_00.sql b/data/sql/updates/db_world/2024_06_01_00.sql new file mode 100644 index 000000000..7e0b7adae --- /dev/null +++ b/data/sql/updates/db_world/2024_06_01_00.sql @@ -0,0 +1,16 @@ +-- DB update 2024_05_29_00 -> 2024_06_01_00 +UPDATE `gameobject_loot_template` SET `MaxCount` = 6 WHERE `Entry` = 22070 AND `Item` IN (22573, 22574); -- Mote of Fire/Earth +UPDATE `gameobject_loot_template` SET `MaxCount` = 4 WHERE `Entry` = 22070 AND `Item` = 32464; -- Nethercite Ore +UPDATE `item_loot_template` SET `Chance` = 60, `MaxCount` = 3 WHERE `Entry` = 32724 AND `Item` = 32728; -- Sludge +UPDATE `item_loot_template` SET `Chance` = 10 WHERE `Entry` = 32724 AND `Item` = 32727; -- Vial of Tears +UPDATE `item_loot_template` SET `Chance` = 2 WHERE `Entry` = 32724 AND `Item` = 32726; -- Murkblood Escape Plans +UPDATE `item_loot_template` SET `Chance` = 5 WHERE `Entry` = 32724 AND `Item` IN (32464, 32468, 32470); -- Ore, Pollen, Hide +UPDATE `creature_loot_template` SET `Chance` = 50 WHERE `Item` = 32427; -- Netherwing Crystal +UPDATE `creature_loot_template` SET `Chance` = 100 WHERE `Item` = 32502; -- Fel Gland +UPDATE `creature_loot_template` SET `Chance` = 1 WHERE `Item` = 32506; -- Netherwing Egg + +INSERT INTO `gameobject_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(22070, 32506, 0, 1, 0, 1, 0, 1, 1, 'Nethercite Deposit - Netherwing Egg'); +INSERT INTO `item_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(32724, 32506, 0, 1, 0, 1, 0, 1, 1, 'Sludge-covered Object - Netherwing Egg'), +(32724, 32725, 0, 10, 0, 1, 0, 1, 1, 'Sludge-covered Object - Murkblood Miner''s Pick'); diff --git a/data/sql/updates/db_world/2024_06_02_00.sql b/data/sql/updates/db_world/2024_06_02_00.sql new file mode 100644 index 000000000..cfcd02f1b --- /dev/null +++ b/data/sql/updates/db_world/2024_06_02_00.sql @@ -0,0 +1,5 @@ +-- DB update 2024_06_01_00 -> 2024_06_02_00 +-- +DELETE FROM `achievement_reward` WHERE `ID` = 431; +INSERT INTO `achievement_reward` (`ID`, `TitleA`, `TitleH`, `ItemID`, `Sender`, `Subject`, `Body`, `MailTemplateID`) VALUES +(431, 64, 64, 0, 0, null, null, 0); diff --git a/deps/recastnavigation/Detour/CMakeLists.txt b/deps/recastnavigation/Detour/CMakeLists.txt index c04ee437e..e658bef15 100644 --- a/deps/recastnavigation/Detour/CMakeLists.txt +++ b/deps/recastnavigation/Detour/CMakeLists.txt @@ -1,5 +1,5 @@ # Copyright (C) 2008-2016 TrinityCore -# Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3 +# Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE # # This file is free software; as a special exception the author gives # unlimited permission to copy and/or distribute it, with or without diff --git a/deps/recastnavigation/Recast/CMakeLists.txt b/deps/recastnavigation/Recast/CMakeLists.txt index 0058d81e0..ab1641bad 100644 --- a/deps/recastnavigation/Recast/CMakeLists.txt +++ b/deps/recastnavigation/Recast/CMakeLists.txt @@ -1,5 +1,5 @@ # Copyright (C) 2008-2016 TrinityCore -# Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3 +# Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE # # This file is free software; as a special exception the author gives # unlimited permission to copy and/or distribute it, with or without diff --git a/doc/changelog/master.md b/doc/changelog/master.md index b64820713..3cd001b8d 100644 --- a/doc/changelog/master.md +++ b/doc/changelog/master.md @@ -414,7 +414,7 @@ minimal-dynamic - builds commands and spells dynamically. Now don't support - Example loader script for modules: ```cpp /* - * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3 + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE */ // From SC diff --git a/src/common/Utilities/CircularBuffer.h b/src/common/Utilities/CircularBuffer.h index 17172b404..898ab1a11 100644 --- a/src/common/Utilities/CircularBuffer.h +++ b/src/common/Utilities/CircularBuffer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3 + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE * * This file was based on * https://embeddedartistry.com/blog/2017/05/17/creating-a-circular-buffer-in-c-and-c/ diff --git a/src/common/Utilities/DataMap.h b/src/common/Utilities/DataMap.h index 2deb99904..170539a67 100644 --- a/src/common/Utilities/DataMap.h +++ b/src/common/Utilities/DataMap.h @@ -1,5 +1,5 @@ /* - * Originally written by Rochet2 - Copyright (C) 2018+ AzerothCore , released under GNU AGPL v3 license: http://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3 + * Originally written by Rochet2 - Copyright (C) 2018+ AzerothCore , released under GNU AGPL v3 license: http://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE */ #ifndef _DATA_MAP_H_ diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 8ba4cbb9c..550cb101d 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -2176,6 +2176,9 @@ void Player::SetInWater(bool apply) RemoveAurasWithInterruptFlags(apply ? AURA_INTERRUPT_FLAG_NOT_ABOVEWATER : AURA_INTERRUPT_FLAG_NOT_UNDERWATER); getHostileRefMgr().updateThreatTables(); + + if (InstanceScript* instance = GetInstanceScript()) + instance->OnPlayerInWaterStateUpdate(this, apply); } bool Player::IsInAreaTriggerRadius(AreaTrigger const* trigger, float delta) const diff --git a/src/server/game/Entities/Player/PlayerUpdates.cpp b/src/server/game/Entities/Player/PlayerUpdates.cpp index 5fa90071c..91e62941c 100644 --- a/src/server/game/Entities/Player/PlayerUpdates.cpp +++ b/src/server/game/Entities/Player/PlayerUpdates.cpp @@ -436,31 +436,27 @@ void Player::UpdateNextMailTimeAndUnreads() { // Update the next delivery time and unread mails time_t cTime = GameTime::GetGameTime().count(); - // Get the next delivery time - CharacterDatabasePreparedStatement* stmtNextDeliveryTime = - CharacterDatabase.GetPreparedStatement(CHAR_SEL_NEXT_MAIL_DELIVERYTIME); - stmtNextDeliveryTime->SetData(0, GetGUID().GetCounter()); - stmtNextDeliveryTime->SetData(1, uint32(cTime)); - PreparedQueryResult resultNextDeliveryTime = - CharacterDatabase.Query(stmtNextDeliveryTime); - if (resultNextDeliveryTime) - { - Field* fields = resultNextDeliveryTime->Fetch(); - m_nextMailDelivereTime = time_t(fields[0].Get()); - } - // Get unread mails count - CharacterDatabasePreparedStatement* stmtUnreadAmount = - CharacterDatabase.GetPreparedStatement( - CHAR_SEL_CHARACTER_MAILCOUNT_UNREAD_SYNCH); - stmtUnreadAmount->SetData(0, GetGUID().GetCounter()); - stmtUnreadAmount->SetData(1, uint32(cTime)); - PreparedQueryResult resultUnreadAmount = - CharacterDatabase.Query(stmtUnreadAmount); - if (resultUnreadAmount) + m_nextMailDelivereTime = 0; + unReadMails = 0; + + for (Mail const* mail : GetMails()) { - Field* fields = resultUnreadAmount->Fetch(); - unReadMails = uint8(fields[0].Get()); + if (mail->deliver_time > cTime) + { + if (!m_nextMailDelivereTime || m_nextMailDelivereTime > mail->deliver_time) + m_nextMailDelivereTime = mail->deliver_time; + } + + // must be not checked yet + if (mail->checked & MAIL_CHECK_MASK_READ) + continue; + + // and already delivered or expired + if (cTime < mail->deliver_time || cTime > mail->expire_time) + continue; + + unReadMails++; } } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index bcd262a5d..b7c3b88d5 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -4223,7 +4223,7 @@ void Unit::ProcessTerrainStatusUpdate() // remove appropriate auras if we are swimming/not swimming respectively if (liquidData.Status & MAP_LIQUID_STATUS_SWIMMING) RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_ABOVEWATER); - else + else if (!isSwimming()) RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_UNDERWATER); // liquid aura handling diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 3d283f5ed..bf0ab70fa 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -287,10 +287,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe case COMMAND_ABANDON: // abandon (hunter pet) or dismiss (summoned pet) if (pet->GetCharmerGUID() == GetPlayer()->GetGUID()) { - if (pet->IsSummon()) - pet->ToTempSummon()->UnSummon(); - else - _player->StopCastingCharm(); + _player->StopCastingCharm(); } else if (pet->GetOwnerGUID() == GetPlayer()->GetGUID()) { diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h index 6fd2c9402..d65bb0349 100644 --- a/src/server/game/Instances/InstanceScript.h +++ b/src/server/game/Instances/InstanceScript.h @@ -186,6 +186,9 @@ public: virtual void OnPlayerAreaUpdate(Player* /*player*/, uint32 /*oldArea*/, uint32 /*newArea*/) {} + //Called when a player enters/leaves water bodies. + virtual void OnPlayerInWaterStateUpdate(Player* /*player*/, bool /*inWater*/) {} + //Handle open / close objects //use HandleGameObject(ObjectGuid::Empty, boolen, GO); in OnObjectCreate in instance scripts //use HandleGameObject(GUID, boolen, nullptr); in any other script diff --git a/src/server/game/Maps/AreaBoundary.cpp b/src/server/game/Maps/AreaBoundary.cpp index 3ef5601a8..e5b184876 100644 --- a/src/server/game/Maps/AreaBoundary.cpp +++ b/src/server/game/Maps/AreaBoundary.cpp @@ -110,3 +110,21 @@ bool BoundaryUnionBoundary::IsWithinBoundaryArea(Position const* pos) const { return (_b1->IsWithinBoundary(pos) || _b2->IsWithinBoundary(pos)); } + +// ---== INTERSECT OF 2 BOUNDARIES ==--- +BoundaryIntersectBoundary::BoundaryIntersectBoundary(AreaBoundary const* b1, AreaBoundary const* b2, bool isInverted) : + AreaBoundary(isInverted), _b1(b1), _b2(b2) +{ + ASSERT(b1 && b2); +} + +BoundaryIntersectBoundary::~BoundaryIntersectBoundary() +{ + delete _b1; + delete _b2; +} + +bool BoundaryIntersectBoundary::IsWithinBoundaryArea(Position const* pos) const +{ + return (_b1->IsWithinBoundary(pos) && _b2->IsWithinBoundary(pos)); +} diff --git a/src/server/game/Maps/AreaBoundary.h b/src/server/game/Maps/AreaBoundary.h index e599c335e..48a5e6671 100644 --- a/src/server/game/Maps/AreaBoundary.h +++ b/src/server/game/Maps/AreaBoundary.h @@ -165,4 +165,18 @@ class AC_GAME_API BoundaryUnionBoundary : public AreaBoundary AreaBoundary const* const _b2; }; +class AC_GAME_API BoundaryIntersectBoundary : public AreaBoundary +{ + public: + BoundaryIntersectBoundary(AreaBoundary const* b1, AreaBoundary const* b2, bool isInverted = false); + + protected: + virtual ~BoundaryIntersectBoundary(); + bool IsWithinBoundaryArea(Position const* pos) const override; + + private: + AreaBoundary const* const _b1; + AreaBoundary const* const _b2; +}; + #endif //ACORE_AREA_BOUNDARY_H diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp index e814cc607..ef67ccd39 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp @@ -65,9 +65,8 @@ public: context.Repeat(10s, 15s); }).Schedule(25s, 32s, [this](TaskContext context) { - if (DoCastRandomTarget(SPELL_SLEEP) == SPELL_CAST_OK) - Talk(SAY_SLEEP); - + Talk(SAY_SLEEP); + DoCastRandomTarget(SPELL_SLEEP, 1, 0.0f, true, false, false); context.Repeat(35s, 48s); }).Schedule(30s, 48s, [this](TaskContext context) { @@ -137,7 +136,6 @@ public: private: bool _recentlySpoken; - }; class spell_anetheron_sleep : public SpellScript diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp index 36b6a393f..27da08ef9 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp @@ -97,8 +97,9 @@ uint32 const availableChargeAurasAndSpells[3][2] = { Position const nordrassilPosition = { 5503.713f, -3523.436f, 1608.781f, 0.0f }; -float const DOOMFIRE_OFFSET = 15.0f; +float const DOOMFIRE_OFFSET = 25.0f; uint8 const WISP_OFFSET = 40; +uint8 NEAR_POINT = 0; struct npc_ancient_wisp : public ScriptedAI { @@ -148,6 +149,39 @@ private: InstanceScript* _instance; }; +struct npc_doomfire_spirit : public ScriptedAI +{ + npc_doomfire_spirit(Creature* creature) : ScriptedAI(creature) + { + _instance = creature->GetInstanceScript(); + } + + void Reset() override + { + scheduler.CancelAll(); + ScheduleTimedEvent(0s, [&]{ + if (Creature* archimonde = _instance->GetCreature(DATA_ARCHIMONDE)) + { + Position randomNearPosition = archimonde->GetRandomNearPosition(200.0f); + me->GetMotionMaster()->MovePoint(NEAR_POINT, randomNearPosition); + } + }, 6s); + } + + void UpdateAI(uint32 diff) override + { + scheduler.Update(diff); + + if (!UpdateVictim()) + return; + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + } +private: + InstanceScript* _instance; +}; + struct boss_archimonde : public BossAI { boss_archimonde(Creature* creature) : BossAI(creature, DATA_ARCHIMONDE) @@ -262,10 +296,7 @@ struct boss_archimonde : public BossAI }, 25s, 40s); ScheduleTimedEvent(25s, 35s, [&] { - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, false)) - { - DoCastDoomFire(target); - } + DoCastDoomFire(); }, 20s); ScheduleTimedEvent(25s, 35s, [&] { @@ -391,12 +422,12 @@ struct boss_archimonde : public BossAI } } - void DoCastDoomFire(Unit* target) + void DoCastDoomFire() { // hack because spell doesn't work? Talk(SAY_DOOMFIRE); - Position spiritPosition = { target->GetPositionX() + DOOMFIRE_OFFSET, target->GetPositionY() + DOOMFIRE_OFFSET, target->GetPositionZ(), 0.0f }; - Position doomfirePosition = { target->GetPositionX() - DOOMFIRE_OFFSET, target->GetPositionY() - DOOMFIRE_OFFSET, target->GetPositionZ(), 0.0f }; + Position spiritPosition = me->GetRandomNearPosition(DOOMFIRE_OFFSET); + Position doomfirePosition = me->GetRandomNearPosition(DOOMFIRE_OFFSET); if (Creature* doomfireSpirit = me->SummonCreature(CREATURE_DOOMFIRE_SPIRIT, spiritPosition, TEMPSUMMON_TIMED_DESPAWN, 27000)) { if (Creature* doomfire = me->SummonCreature(CREATURE_DOOMFIRE, doomfirePosition, TEMPSUMMON_TIMED_DESPAWN, 27000)) @@ -508,5 +539,6 @@ void AddSC_boss_archimonde() RegisterSpellScript(spell_finger_of_death); RegisterHyjalAI(boss_archimonde); RegisterHyjalAI(npc_ancient_wisp); + RegisterHyjalAI(npc_doomfire_spirit); } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp index a4fb98963..4bf335c9d 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp @@ -17,6 +17,8 @@ #include "CreatureScript.h" #include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellScriptLoader.h" #include "hyjal.h" enum Spells @@ -60,7 +62,7 @@ public: context.Repeat(8s, 16s); }).Schedule(25s, [this](TaskContext context) { - DoCastRandomTarget(SPELL_RAIN_OF_FIRE, 0, 40.f); + DoCastRandomTarget(SPELL_RAIN_OF_FIRE, 0, 40.f, false); context.Repeat(15s); }).Schedule(30s, [this](TaskContext context) { @@ -68,7 +70,7 @@ public: context.Repeat(18s, 20s); }).Schedule(45s, 55s, [this](TaskContext context) { - DoCastRandomTarget(SPELL_DOOM, 0, 100.f, true, false, false); + DoCastRandomTarget(SPELL_DOOM, 1, 100.f, true, false, false); Talk(SAY_DOOM); context.Repeat(); }).Schedule(10min, [this](TaskContext context) @@ -114,10 +116,29 @@ public: private: bool _recentlySpoken; +}; +class spell_azgalor_doom : public AuraScript +{ + PrepareAuraScript(spell_azgalor_doom); + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); + if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH && !IsExpired()) + { + target->CastSpell(target, GetSpellInfo()->Effects[EFFECT_0].TriggerSpell, true); + } + } + + void Register() override + { + OnEffectRemove += AuraEffectRemoveFn(spell_azgalor_doom::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + } }; void AddSC_boss_azgalor() { RegisterHyjalAI(boss_azgalor); + RegisterSpellScript(spell_azgalor_doom); } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp index 49937582f..37fc84809 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp @@ -133,67 +133,51 @@ private: uint8 _markCounter; }; -class spell_mark_of_kazrogal : public SpellScriptLoader +class spell_mark_of_kazrogal : public SpellScript { -public: - spell_mark_of_kazrogal() : SpellScriptLoader("spell_mark_of_kazrogal") { } + PrepareSpellScript(spell_mark_of_kazrogal); - class spell_mark_of_kazrogal_SpellScript : public SpellScript + void FilterTargets(std::list& targets) { - PrepareSpellScript(spell_mark_of_kazrogal_SpellScript); - - void FilterTargets(std::list& targets) - { - targets.remove_if(Acore::PowerCheck(POWER_MANA, false)); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mark_of_kazrogal_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - } - }; - - class spell_mark_of_kazrogal_AuraScript : public AuraScript - { - PrepareAuraScript(spell_mark_of_kazrogal_AuraScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - return ValidateSpellInfo({ SPELL_MARK_DAMAGE }); - } - - void OnPeriodic(AuraEffect const* aurEff) - { - Unit* target = GetTarget(); - - if ((int32)target->GetPower(POWER_MANA) < aurEff->GetBaseAmount()) - { - target->CastSpell(target, SPELL_MARK_DAMAGE, true, nullptr, aurEff); - // Remove aura - SetDuration(0); - } - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_mark_of_kazrogal_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_MANA_LEECH); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mark_of_kazrogal_SpellScript(); + targets.remove_if(Acore::PowerCheck(POWER_MANA, false)); } - AuraScript* GetAuraScript() const override + void Register() override { - return new spell_mark_of_kazrogal_AuraScript(); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mark_of_kazrogal::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } +}; + +class spell_mark_of_kazrogal_aura : public AuraScript +{ + PrepareAuraScript(spell_mark_of_kazrogal_aura); + + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_MARK_DAMAGE }); + } + + void OnPeriodic(AuraEffect const* aurEff) + { + Unit* target = GetTarget(); + + if ((int32)target->GetPower(POWER_MANA) < aurEff->GetBaseAmount()) + { + target->CastSpell(target, SPELL_MARK_DAMAGE, true, nullptr, aurEff); + // Remove aura + SetDuration(0); + } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_mark_of_kazrogal_aura::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_MANA_LEECH); } }; void AddSC_boss_kazrogal() { RegisterHyjalAI(boss_kazrogal); - new spell_mark_of_kazrogal(); + RegisterSpellAndAuraScriptPair(spell_mark_of_kazrogal, spell_mark_of_kazrogal_aura); } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h index b0c127f49..4f2493e7c 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h @@ -120,7 +120,11 @@ enum HyjalCreaturesIds NPC_KAZROGAL = 17888, NPC_AZGALOR = 17842, NPC_ARCHIMONDE = 17968, - NPC_WORLD_TRIGGER_TINY = 21987 + NPC_WORLD_TRIGGER_TINY = 21987, + + // Boss summons + NPC_TOWERING_INFERNAL = 17818, + NPC_LESSER_DOOMGUARD = 17864 }; enum HyjalGameobjectIds @@ -144,7 +148,11 @@ enum HyjalMisc START_WAVE_HORDE_RETREAT = 39, START_WAVE_NIGHT_ELF = 42, - CONTEXT_GROUP_WAVES = 1 + CONTEXT_GROUP_WAVES = 1, + + AREA_NORDRASSIL = 3710, + + SPELL_ETERNAL_SILENCE = 42201 }; enum HyjalPaths diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp index fd5d50672..f27da4a41 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp @@ -19,6 +19,7 @@ #include "InstanceMapScript.h" #include "InstanceScript.h" #include "Opcodes.h" +#include "Player.h" #include "WorldPacket.h" #include "hyjal.h" @@ -101,6 +102,7 @@ public: trash = 0; _currentWave = 0; _encounterNPCs.clear(); + _summonedNPCs.clear(); _baseAlliance.clear(); _baseHorde.clear(); _infernalTargets.clear(); @@ -199,6 +201,13 @@ public: _encounterNPCs.insert(creature->GetGUID()); // Used for despawning on wipe } break; + case NPC_TOWERING_INFERNAL: + case NPC_LESSER_DOOMGUARD: + if (creature->IsSummon()) + { + _summonedNPCs.insert(creature->GetGUID()); + } + break; } InstanceScript::OnCreatureCreate(creature); } @@ -232,6 +241,10 @@ public: } } break; + case NPC_TOWERING_INFERNAL: + case NPC_LESSER_DOOMGUARD: + _summonedNPCs.erase(unit->ToCreature()->GetGUID()); + break; case NPC_WINTERCHILL: case NPC_ANETHERON: case NPC_KAZROGAL: @@ -401,6 +414,14 @@ public: if (Creature* creature = instance->GetCreature(guid)) creature->DespawnOrUnsummon(); + // also force despawn boss summons + for (ObjectGuid const& guid : _summonedNPCs) + if (Creature* creature = instance->GetCreature(guid)) + creature->DespawnOrUnsummon(); + + if (_bossWave && (GetBossState(_bossWave) != DONE)) + SetBossState(_bossWave, NOT_STARTED); + _scheduler.Schedule(300s, [this](TaskContext) { for (ObjectGuid const& guid : _baseAlliance) @@ -419,6 +440,14 @@ public: if (Creature* creature = instance->GetCreature(guid)) creature->DespawnOrUnsummon(); + // also force despawn boss summons + for (ObjectGuid const& guid : _summonedNPCs) + if (Creature* creature = instance->GetCreature(guid)) + creature->DespawnOrUnsummon(); + + if (_bossWave && (GetBossState(_bossWave) != DONE)) + SetBossState(_bossWave, NOT_STARTED); + _scheduler.Schedule(300s, [this](TaskContext) { for (ObjectGuid const& guid : _baseHorde) @@ -454,6 +483,7 @@ public: case DATA_RESET_WAVES: _scheduler.CancelGroup(CONTEXT_GROUP_WAVES); _encounterNPCs.clear(); + _summonedNPCs.clear(); _currentWave = 0; trash = 0; _bossWave = 0; @@ -530,6 +560,14 @@ public: _scheduler.Update(diff); } + void OnPlayerInWaterStateUpdate(Player* player, bool inWater) override + { + if (inWater && player->GetAreaId() == AREA_NORDRASSIL) + { + player->CastSpell(player, SPELL_ETERNAL_SILENCE, true); + } + } + protected: int32 trash; uint8 _currentWave; @@ -537,6 +575,7 @@ public: uint8 _retreat; TaskScheduler _scheduler; GuidSet _encounterNPCs; + GuidSet _summonedNPCs; GuidSet _baseAlliance; GuidSet _baseHorde; GuidVector _infernalTargets; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp index 3f151ab85..2ec36b0f9 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp @@ -2383,20 +2383,45 @@ public: return GetCaster()->GetTypeId() == TYPEID_UNIT; } - void CheckEnergy() + void CalculatePower() { - if (GetCaster()->GetPower(POWER_ENERGY) >= 100) + Unit* caster = GetCaster(); + if (!caster) + return; + + SpellInfo const* spellInfo = GetSpellInfo(); + if (!spellInfo) + return; + + // Check if the effect is energize + if (spellInfo->Effects[EFFECT_1].Effect == SPELL_EFFECT_ENERGIZE) { - GetCaster()->CastSpell(GetCaster(), SPELL_OVERHEAT, true); - if (Vehicle* vehicle = GetCaster()->GetVehicleKit()) - if (Unit* passenger = vehicle->GetPassenger(0)) - sCreatureTextMgr->SendChat(GetCaster()->ToCreature(), SAY_OVERHEAT, passenger); + int32 energizeAmount = spellInfo->Effects[EFFECT_1].CalcValue(caster); + + // Apply the power gain directly to the caster + caster->ModifyPower(POWER_ENERGY, energizeAmount); } + + if (caster->GetPower(POWER_ENERGY) >= 100) + { + caster->CastSpell(caster, SPELL_OVERHEAT, true); + if (Vehicle* vehicle = caster->GetVehicleKit()) + if (Unit* passenger = vehicle->GetPassenger(0)) + sCreatureTextMgr->SendChat(caster->ToCreature(), SAY_OVERHEAT, passenger); + } + + } + + void PreventPowerGainOnHit(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); } void Register() override { - AfterHit += SpellHitFn(spell_igb_cannon_blast_SpellScript::CheckEnergy); + OnCast += SpellCastFn(spell_igb_cannon_blast_SpellScript::CalculatePower); + OnEffectHitTarget += SpellEffectFn(spell_igb_cannon_blast_SpellScript::PreventPowerGainOnHit, EFFECT_1, SPELL_EFFECT_ENERGIZE); + } }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index d21c9935d..b9326859a 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -869,85 +869,29 @@ private: bool _removeHealers; }; -class spell_sindragosa_unchained_magic : public SpellScriptLoader +class spell_sindragosa_unchained_magic : public SpellScript { -public: - spell_sindragosa_unchained_magic() : SpellScriptLoader("spell_sindragosa_unchained_magic") { } + PrepareSpellScript(spell_sindragosa_unchained_magic); - class spell_sindragosa_unchained_magic_SpellScript : public SpellScript + void FilterTargets(std::list& unitList) { - PrepareSpellScript(spell_sindragosa_unchained_magic_SpellScript); - - void FilterTargets(std::list& unitList) - { - std::list healList = unitList; - std::list dpsList = unitList; - unitList.clear(); - uint32 maxSize = uint32(GetCaster()->GetMap()->GetSpawnMode() & 1 ? 3 : 1); - healList.remove_if(UnchainedMagicTargetSelector(false)); - if (healList.size() > maxSize) - Acore::Containers::RandomResize(healList, maxSize); - dpsList.remove_if(UnchainedMagicTargetSelector(true)); - if (dpsList.size() > maxSize) - Acore::Containers::RandomResize(dpsList, maxSize); - unitList.splice(unitList.begin(), healList); - unitList.splice(unitList.begin(), dpsList); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sindragosa_unchained_magic_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_sindragosa_unchained_magic_SpellScript(); + std::list healList = unitList; + std::list dpsList = unitList; + unitList.clear(); + uint32 maxSize = uint32(GetCaster()->GetMap()->GetSpawnMode() & 1 ? 3 : 1); + healList.remove_if(UnchainedMagicTargetSelector(false)); + if (healList.size() > maxSize) + Acore::Containers::RandomResize(healList, maxSize); + dpsList.remove_if(UnchainedMagicTargetSelector(true)); + if (dpsList.size() > maxSize) + Acore::Containers::RandomResize(dpsList, maxSize); + unitList.splice(unitList.begin(), healList); + unitList.splice(unitList.begin(), dpsList); } - class spell_sindragosa_unchained_magic_AuraScript : public AuraScript + void Register() override { - PrepareAuraScript(spell_sindragosa_unchained_magic_AuraScript); - - std::map _lastMSTimeForSpell; - - bool Validate(SpellInfo const* /*spellInfo*/) override - { - _lastMSTimeForSpell.clear(); - return true; - } - - bool CheckProc(ProcEventInfo& eventInfo) - { - SpellInfo const* spellInfo = eventInfo.GetSpellInfo(); - if (!spellInfo) - return false; - - uint32 currMSTime = GameTime::GetGameTimeMS().count(); - std::map::iterator itr = _lastMSTimeForSpell.find(spellInfo->Id); - if (itr != _lastMSTimeForSpell.end()) - { - uint32 lastMSTime = itr->second; - itr->second = currMSTime; - if (getMSTimeDiff(lastMSTime, currMSTime) < 600) - return false; - - return true; - } - - _lastMSTimeForSpell[spellInfo->Id] = currMSTime; - return true; - } - - void Register() override - { - DoCheckProc += AuraCheckProcFn(spell_sindragosa_unchained_magic_AuraScript::CheckProc); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_sindragosa_unchained_magic_AuraScript(); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sindragosa_unchained_magic::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; @@ -2012,7 +1956,7 @@ void AddSC_boss_sindragosa() new boss_sindragosa(); new npc_ice_tomb(); new spell_sindragosa_s_fury(); - new spell_sindragosa_unchained_magic(); + RegisterSpellScript(spell_sindragosa_unchained_magic); new spell_sindragosa_permeating_chill(); new spell_sindragosa_instability(); new spell_sindragosa_icy_grip(); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp index 94e89fa71..56fb1a902 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp @@ -665,6 +665,37 @@ public: }; }; +struct boss_kologarn_pit_kill_bunny : public NullCreatureAI +{ + boss_kologarn_pit_kill_bunny(Creature* creature) : NullCreatureAI(creature) { } + + void Reset() override + { + RectangleBoundary* _boundaryXY = new RectangleBoundary(1782.0f, 1832.0f, -56.0f, 8.0f); + ZRangeBoundary* _boundaryZ = new ZRangeBoundary(400.0f, 439.0f); + _boundaryIntersect = new BoundaryIntersectBoundary(_boundaryXY, _boundaryZ); + + scheduler.Schedule(0s, [this](TaskContext context) + { + me->GetMap()->DoForAllPlayers([&](Player* player) + { + if (_boundaryIntersect->IsWithinBoundary(player->GetPosition()) && !player->IsGameMaster()) + { + player->KillSelf(false); + } + }); + context.Repeat(1s); + }); + } + + void UpdateAI(uint32 diff) override + { + scheduler.Update(diff); + } +private: + BoundaryIntersectBoundary const* _boundaryIntersect; +}; + // predicate function to select non main tank target class StoneGripTargetSelector { @@ -894,6 +925,7 @@ void AddSC_boss_kologarn() new boss_kologarn(); new boss_kologarn_arms(); new boss_kologarn_eyebeam(); + RegisterUlduarCreatureAI(boss_kologarn_pit_kill_bunny); // Spells new spell_ulduar_stone_grip_cast_target(); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp index dfbc906e0..93c0de72f 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp @@ -86,7 +86,8 @@ enum SpellData SPELL_HAND_PULSE_25_L = 64536, SPELL_SELF_REPAIR = 64383, - SPELL_SLEEP = 64394, + SPELL_SLEEP_VISUAL_1 = 64393, + SPELL_SLEEP_VISUAL_2 = 64394, }; enum NPCs @@ -172,10 +173,11 @@ enum EVENTS EVENT_JOIN_ACU = 35, EVENT_START_PHASE4 = 36, EVENT_FINISH = 50, - EVENT_SAY_VOLTRON_DEAD = 51, - EVENT_DISAPPEAR = 52, - EVENT_BERSERK = 53, - EVENT_BERSERK_2 = 54, + EVENT_STAND_UP_FRIENDLY = 51, + EVENT_SAY_VOLTRON_DEAD = 52, + EVENT_DISAPPEAR = 53, + EVENT_BERSERK = 54, + EVENT_BERSERK_2 = 55, // Leviathan: EVENT_SPELL_NAPALM_SHELL = 3, @@ -754,17 +756,20 @@ public: Position exitPos = me->GetPosition(); me->_ExitVehicle(&exitPos); me->AttackStop(); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_TALK); me->GetMotionMaster()->Clear(); summons.DoAction(1337); // despawn summons of summons summons.DespawnEntry(NPC_FLAMES_INITIAL); summons.DespawnEntry(33576); + me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + float angle = VX001->GetOrientation(); float v_x = me->GetPositionX() + cos(angle) * 10.0f; float v_y = me->GetPositionY() + std::sin(angle) * 10.0f; me->GetMotionMaster()->MoveJump(v_x, v_y, 364.32f, 7.0f, 7.0f); + DoCastSelf(SPELL_SLEEP_VISUAL_1); + if( pInstance ) for( uint16 i = 0; i < 3; ++i ) if( ObjectGuid guid = pInstance->GetGuidData(DATA_GO_MIMIRON_DOOR_1 + i) ) @@ -783,11 +788,20 @@ public: computer->AI()->Talk(TALK_COMPUTER_TERMINATED); events.Reset(); - events.ScheduleEvent(EVENT_SAY_VOLTRON_DEAD, 6s); + events.ScheduleEvent(EVENT_STAND_UP_FRIENDLY, 6s); } break; + case EVENT_STAND_UP_FRIENDLY: + me->RemoveAurasDueToSpell(SPELL_SLEEP_VISUAL_1); + DoCastSelf(SPELL_SLEEP_VISUAL_2); + me->SetFaction(FACTION_FRIENDLY); + events.ScheduleEvent(EVENT_SAY_VOLTRON_DEAD, 4s); + break; case EVENT_SAY_VOLTRON_DEAD: Talk(SAY_V07TRON_DEATH); + me->HandleEmoteCommand(EMOTE_ONESHOT_TALK); + if (pInstance) + pInstance->SetData(TYPE_MIMIRON, DONE); // spawn chest if (uint32 chestId = (hardmode ? RAID_MODE(GO_MIMIRON_CHEST_HARD, GO_MIMIRON_CHEST_HERO_HARD) : RAID_MODE(GO_MIMIRON_CHEST, GO_MIMIRON_CHEST_HERO))) { @@ -797,11 +811,9 @@ public: go->SetLootRecipient(me->GetMap()); } } - events.ScheduleEvent(EVENT_DISAPPEAR, 15s); + events.ScheduleEvent(EVENT_DISAPPEAR, 9s); break; case EVENT_DISAPPEAR: - if( pInstance ) - pInstance->SetData(TYPE_MIMIRON, DONE); DoCastSelf(SPELL_TELEPORT); summons.DespawnAll(); break; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp index d4289a097..ed7f69221 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp @@ -100,6 +100,15 @@ public: Position normalChestPosition = { 1967.152588f, -204.188461f, 432.686951f, 5.50957f }; Position hardChestPosition = { 2035.94600f, -202.084885f, 432.686859f, 3.164077f }; + // Mimiron Tram + ObjectGuid m_mimironTramGUID; + ObjectGuid m_mimironActivateTramGUID; + ObjectGuid m_mimironTramRocketBoosterGUID; + ObjectGuid m_mimironTramTurnaround1GUID; + ObjectGuid m_mimironTramTurnaround2GUID; + ObjectGuid m_mimironCallTramCenterGUID; + ObjectGuid m_mimironCallTramMimironGUID; + // Mimiron ObjectGuid m_MimironDoor[3]; ObjectGuid m_MimironLeviathanMKIIguid; @@ -124,10 +133,12 @@ public: ObjectGuid m_brannBronzebeardBaseCamp; uint32 m_algalonTimer; + // Ancient Gate + const Position triggerAncientGatePosition = { 1883.65f, 269.272f, 418.406f }; + // Shared EventMap _events; bool m_mimironTramUsed; - ObjectGuid m_mimironTramGUID; ObjectGuid m_keepersgateGUID; ObjectGuid m_keepersGossipGUID[4]; @@ -170,7 +181,18 @@ public: // mimiron tram: instance->LoadGrid(2307.0f, 284.632f); if (GameObject* MimironTram = instance->GetGameObject(m_mimironTramGUID)) + { player->UpdateVisibilityOf(MimironTram); + if (StaticTransport* t = MimironTram->ToStaticTransport()) + { + if (GameObject* go = instance->GetGameObject(m_mimironTramRocketBoosterGUID)) + if (!go->GetTransport()) + t->AddPassenger(go, true); + if (GameObject* go = instance->GetGameObject(m_mimironActivateTramGUID)) + if (!go->GetTransport()) + t->AddPassenger(go, true); + } + } if (!m_uiAlgalonGUID && m_algalonTimer && (m_algalonTimer <= 60 || m_algalonTimer == TIMER_ALGALON_TO_SUMMON)) { @@ -553,11 +575,30 @@ public: case GO_SNOW_MOUND: gameObject->EnableCollision(false); break; + // Mimiron Tram case GO_MIMIRON_TRAM: if (GetData(TYPE_MIMIRON) == DONE) m_mimironTramUsed = true; m_mimironTramGUID = gameObject->GetGUID(); break; + case GO_MIMIRON_TRAM_ROCKET_BOOSTER: + m_mimironTramRocketBoosterGUID = gameObject->GetGUID(); + break; + case GO_MIMIRON_ACTIVATE_TRAM: + m_mimironActivateTramGUID = gameObject->GetGUID(); + break; + case GO_MIMIRON_CALL_TRAM_CENTER: + m_mimironCallTramCenterGUID = gameObject->GetGUID(); + break; + case GO_MIMIRON_CALL_TRAM_MIMIRON: + m_mimironCallTramMimironGUID = gameObject->GetGUID(); + break; + case GO_DOODAD_UL_TRAIN_TURNAROUND01: + m_mimironTramTurnaround1GUID = gameObject->GetGUID(); + break; + case GO_DOODAD_UL_TRAIN_TURNAROUND02: + m_mimironTramTurnaround2GUID = gameObject->GetGUID(); + break; // Algalon the Observer case GO_CELESTIAL_PLANETARIUM_ACCESS_10: case GO_CELESTIAL_PLANETARIUM_ACCESS_25: @@ -668,8 +709,17 @@ public: m_auiEncounter[type] = data; if (GetData(TYPE_MIMIRON) == DONE && GetData(TYPE_FREYA) == DONE && GetData(TYPE_HODIR) == DONE && GetData(TYPE_THORIM) == DONE) { - if (GameObject* go = instance->GetGameObject(m_keepersgateGUID)) - go->RemoveGameObjectFlag(GO_FLAG_LOCKED); + scheduler.Schedule(45s, [this](TaskContext /*context*/) + { + if (GameObject* go = instance->GetGameObject(m_keepersgateGUID)) + { + go->RemoveGameObjectFlag(GO_FLAG_LOCKED); + if (Creature* trigger = instance->SummonCreature(NPC_ANCIENT_GATE_WORLD_TRIGGER, triggerAncientGatePosition, nullptr, 10*IN_MILLISECONDS)) + { + trigger->AI()->Talk(EMOTE_ANCIENT_GATE_UNLOCKED); + } + } + }); } if (type == TYPE_MIMIRON && data == IN_PROGRESS) // after reaching him without tram and starting the fight m_mimironTramUsed = true; @@ -785,9 +835,51 @@ public: if (StaticTransport* t = MimironTram->ToStaticTransport()) { if (data == 0 && t->GetGoState() == GO_STATE_ACTIVE && t->GetPathProgress() == t->GetPauseTime()) + { MimironTram->SetGoState(GO_STATE_READY); + if (GameObject* rocketBooster = instance->GetGameObject(m_mimironTramRocketBoosterGUID)) + rocketBooster->SetGoState(GO_STATE_ACTIVE); + if (GameObject* activateTramButton = instance->GetGameObject(m_mimironActivateTramGUID)) + activateTramButton->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE); + if (GameObject* callTramCenterButton = instance->GetGameObject(m_mimironCallTramCenterGUID)) + callTramCenterButton->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE); + scheduler.Schedule(30s, [this](TaskContext /*context*/) + { + if (GameObject* turnaround1 = instance->GetGameObject(m_mimironTramTurnaround1GUID)) + turnaround1->UseDoorOrButton(); + if (GameObject* rocketBooster = instance->GetGameObject(m_mimironTramRocketBoosterGUID)) + rocketBooster->SetGoState(GO_STATE_READY); + }).Schedule(60s, [this](TaskContext /*context*/) + { + if (GameObject* activateTramButton = instance->GetGameObject(m_mimironActivateTramGUID)) + activateTramButton->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE); + if (GameObject* callTramMimironButton = instance->GetGameObject(m_mimironCallTramMimironGUID)) + callTramMimironButton->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE); + }); + } if (data == 1 && t->GetGoState() == GO_STATE_READY && t->GetPathProgress() == 0) + { MimironTram->SetGoState(GO_STATE_ACTIVE); + if (GameObject* rocketBooster = instance->GetGameObject(m_mimironTramRocketBoosterGUID)) + rocketBooster->SetGoState(GO_STATE_ACTIVE); + if (GameObject* activateTramButton = instance->GetGameObject(m_mimironActivateTramGUID)) + activateTramButton->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE); + if (GameObject* callTramMimironButton = instance->GetGameObject(m_mimironCallTramMimironGUID)) + callTramMimironButton->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE); + scheduler.Schedule(33s, [this](TaskContext /*context*/) + { + if (GameObject* turnaround2 = instance->GetGameObject(m_mimironTramTurnaround2GUID)) + turnaround2->UseDoorOrButton(); + if (GameObject* rocketBooster = instance->GetGameObject(m_mimironTramRocketBoosterGUID)) + rocketBooster->SetGoState(GO_STATE_READY); + }).Schedule(63s, [this](TaskContext /*context*/) + { + if (GameObject* activateTramButton = instance->GetGameObject(m_mimironActivateTramGUID)) + activateTramButton->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE); + if (GameObject* callTramCenterButton = instance->GetGameObject(m_mimironCallTramCenterGUID)) + callTramCenterButton->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE); + }); + } } break; case DATA_BRANN_MEMOTESAY: diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.cpp index e8b6042d8..c9717cd34 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.cpp @@ -545,33 +545,6 @@ public: } }; -class go_call_tram : public GameObjectScript -{ -public: - go_call_tram() : GameObjectScript("go_call_tram") { } - - bool OnGossipHello(Player* /*player*/, GameObject* go) override - { - InstanceScript* pInstance = go->GetInstanceScript(); - - if (!pInstance) - return false; - - switch(go->GetEntry()) - { - case 194914: - case 194438: - pInstance->SetData(DATA_CALL_TRAM, 0); - break; - case 194912: - case 194437: - pInstance->SetData(DATA_CALL_TRAM, 1); - break; - } - return true; - } -}; - struct npc_salvaged_siege_engine : public VehicleAI { npc_salvaged_siege_engine(Creature* creature) : VehicleAI(creature) { } @@ -609,7 +582,5 @@ void AddSC_ulduar() new npc_ulduar_arachnopod_destroyer(); new spell_ulduar_arachnopod_damaged(); new AreaTrigger_at_celestial_planetarium_enterance(); - new go_call_tram(); - RegisterCreatureAI(npc_salvaged_siege_engine); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h index 288e87dcb..1735aeb39 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h @@ -215,7 +215,15 @@ enum UlduarGameObjects GO_KOLOGARN_DOORS = 194553, GO_KEEPERS_GATE = 194255, GO_XT002_DOORS = 194631, + + // Tram GO_MIMIRON_TRAM = 194675, + GO_MIMIRON_ACTIVATE_TRAM = 194437, + GO_MIMIRON_CALL_TRAM_CENTER = 194914, + GO_MIMIRON_CALL_TRAM_MIMIRON = 194912, + GO_MIMIRON_TRAM_ROCKET_BOOSTER = 194904, + GO_DOODAD_UL_TRAIN_TURNAROUND01 = 194915, // center + GO_DOODAD_UL_TRAIN_TURNAROUND02 = 194913, // mimiron // Mimiron, Hodir, Vezax GO_MIMIRON_ELEVATOR = 194749, @@ -290,6 +298,10 @@ enum UlduarMisc // Freya, Hodir, Mimiron, Thorim EVENT_KEEPER_TELEPORTED = 62941, + // Ancient Gate + NPC_ANCIENT_GATE_WORLD_TRIGGER = 22515, + EMOTE_ANCIENT_GATE_UNLOCKED = 19, + // Yogg-Saron ACTION_SARA_UPDATE_SUMMON_KEEPERS = 4, KEEPER_FREYA = 0,