diff --git a/.github/SECURITY.md b/.github/SECURITY.md index a907ec3ec..e7b138f77 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -37,34 +37,32 @@ Versions of CLang: | CLang Version | Supported | | ------------- | ------------------ | -| 12 | :white_check_mark: | -| 11 | :white_check_mark: | -| 10 | :white_check_mark: | -| 9 and lower | :red_circle: | +| 18 | :white_check_mark: | +| 15 | :white_check_mark: | +| 14 and lower | :red_circle: | Versions of GCC: | GCC Version | Supported | | ----------- | ------------------ | -| 10 | :white_check_mark: | -| 9 | :white_check_mark: | -| 8 | :white_check_mark: | -| 7 and lower | :red_circle: | +| 14 | :white_check_mark: | +| 12 | :white_check_mark: | +| 11 and lower| :red_circle: | Versions of Ubuntu: | Ubuntu version | Supported | | -------------- | ------------------ | -| 20.04 | :white_check_mark: | -| 18.04 and lower| :red_circle: | +| 24.04 | :white_check_mark: | +| 22.04 | :white_check_mark: | +| 20.04 and lower| :red_circle: | Versions of macOS: | macOS Version | Supported | | -------------- | ------------------ | | 12 | :white_check_mark: | -| 11 | :white_check_mark: | -| 10.15 and lower| :red_circle: | +| 11 and lower | :red_circle: | **Note**: We do NOT support any repacks that may or may not have been made based on AzerothCore. This is because they are usually based on older versions and there is no way to know what is in the precompiled binaries. Instead, you should compile your binaries from the AzerothCore source. To get started, read the [Installation Guide](https://www.azerothcore.org/wiki/installation). diff --git a/.github/labeler.yml b/.github/labeler.yml index e00e60701..55a71d605 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -11,12 +11,17 @@ DB: - any-glob-to-any-file: 'data/**/*.sql' CORE: -- all: - - changed-files: - - any-glob-to-any-file: 'src/**/*' - - all-globs-to-all-files: - - '!src/server/scripts/**/*' - - '!src/test/**/*' +- changed-files: + - any-glob-to-any-file: + - 'src/*' + - 'src/common/**/*' + - 'src/genrev/**/*' + - 'src/server/*' + - 'src/server/apps/**/*' + - 'src/server/database/**/*' + - 'src/server/game/**/*' + - 'src/server/shared/**/*' + - 'src/tools/**/*' Script: - changed-files: @@ -30,7 +35,7 @@ UnitTests: Documentation: - changed-files: - - any-glob-to-any-file: '*.md' + - any-glob-to-any-file: '**/*.md' Bash: - changed-files: @@ -43,7 +48,7 @@ Bash: CMake: - changed-files: - - any-glob-to-any-file: '*.cmake' + - any-glob-to-any-file: '**/*.cmake' Workflow: - changed-files: diff --git a/.github/workflows/core-build-nopch.yml b/.github/workflows/core-build-nopch.yml index ee906fe85..dd7e322f9 100644 --- a/.github/workflows/core-build-nopch.yml +++ b/.github/workflows/core-build-nopch.yml @@ -16,9 +16,17 @@ concurrency: jobs: build: strategy: - fail-fast: false + fail-fast: true matrix: include: + - os: ubuntu-22.04 + compiler: + CC: clang-15 + CXX: clang++-15 + - os: ubuntu-22.04 + compiler: + CC: gcc-12 + CXX: g++-12 - os: ubuntu-24.04 compiler: CC: clang-18 diff --git a/.github/workflows/core-build-pch.yml b/.github/workflows/core-build-pch.yml index c275d0fd0..2f71753ce 100644 --- a/.github/workflows/core-build-pch.yml +++ b/.github/workflows/core-build-pch.yml @@ -13,9 +13,13 @@ concurrency: jobs: build: strategy: - fail-fast: false + fail-fast: true matrix: include: + - os: ubuntu-22.04 + compiler: + CC: clang-15 + CXX: clang++-15 - os: ubuntu-24.04 compiler: CC: clang-18 diff --git a/data/sql/updates/db_world/2024_06_09_01.sql b/data/sql/updates/db_world/2024_06_09_01.sql new file mode 100644 index 000000000..9a1f1eb2d --- /dev/null +++ b/data/sql/updates/db_world/2024_06_09_01.sql @@ -0,0 +1,5 @@ +-- DB update 2024_06_09_00 -> 2024_06_09_01 +-- +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 22357) AND (`source_type` = 0) AND (`id` IN (2)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(22357, 0, 2, 0, 6, 0, 100, 512, 0, 0, 0, 0, 0, 0, 26, 11090, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Reth\'hedron the Subduer - On Just Died - Quest Credit \'Subdue the Subduer\''); diff --git a/data/sql/updates/db_world/2024_06_09_02.sql b/data/sql/updates/db_world/2024_06_09_02.sql new file mode 100644 index 000000000..f854f30dd --- /dev/null +++ b/data/sql/updates/db_world/2024_06_09_02.sql @@ -0,0 +1,5 @@ +-- DB update 2024_06_09_01 -> 2024_06_09_02 +-- +UPDATE `creature_template` SET `AIName` = '' WHERE `entry` = 18145; + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 18145) AND (`source_type` = 0); diff --git a/data/sql/updates/db_world/2024_06_10_00.sql b/data/sql/updates/db_world/2024_06_10_00.sql new file mode 100644 index 000000000..25c7008e0 --- /dev/null +++ b/data/sql/updates/db_world/2024_06_10_00.sql @@ -0,0 +1,3 @@ +-- DB update 2024_06_09_02 -> 2024_06_10_00 +-- +UPDATE `creature_template` SET `mechanic_immune_mask` = `mechanic_immune_mask`|2 WHERE `entry` = 21958; diff --git a/data/sql/updates/db_world/2024_06_10_01.sql b/data/sql/updates/db_world/2024_06_10_01.sql new file mode 100644 index 000000000..eff060073 --- /dev/null +++ b/data/sql/updates/db_world/2024_06_10_01.sql @@ -0,0 +1,8 @@ +-- DB update 2024_06_10_00 -> 2024_06_10_01 +-- Chicken +DELETE FROM `creature` WHERE (`id1` = 620) AND (`guid` IN (14896, 15403, 15943, 16368)); +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 +(14896, 620, 0, 0, 0, 267, 271, 1, 1, 0, -816.1612, -616.04034, 13.880794, 0.9943093061447144, 300, 5, 0, 1, 0, 1, 0, 0, 0, '', 0), +(15403, 620, 0, 0, 0, 267, 271, 1, 1, 0, -814.34357, -583.0802, 15.234792, 0.8475685715675354, 300, 3, 0, 1, 0, 1, 0, 0, 0, '', 0), +(15943, 620, 0, 0, 0, 267, 271, 1, 1, 0, -752.3134, -550.3316, 19.06126, 3.9133145809173584, 300, 5, 0, 1, 0, 1, 0, 0, 0, '', 0), +(16368, 620, 0, 0, 0, 267, 271, 1, 1, 0, -829.1331, -534.4989, 14.115756, 0.11760736256837845, 300, 5, 0, 1, 0, 1, 0, 0, 0, '', 0); diff --git a/data/sql/updates/db_world/2024_06_10_02.sql b/data/sql/updates/db_world/2024_06_10_02.sql new file mode 100644 index 000000000..6f267fe6c --- /dev/null +++ b/data/sql/updates/db_world/2024_06_10_02.sql @@ -0,0 +1,3 @@ +-- DB update 2024_06_10_01 -> 2024_06_10_02 +-- +UPDATE `creature_template` SET `flags_extra` = `flags_extra`|1073741824 WHERE `entry` IN (20040, 20041); diff --git a/data/sql/updates/db_world/2024_06_11_00.sql b/data/sql/updates/db_world/2024_06_11_00.sql new file mode 100644 index 000000000..ac9b85269 --- /dev/null +++ b/data/sql/updates/db_world/2024_06_11_00.sql @@ -0,0 +1,34 @@ +-- DB update 2024_06_10_02 -> 2024_06_11_00 +-- +UPDATE `spell_script_names` SET `ScriptName`='spell_algalon_collapse_aura' WHERE `spell_id`=62018; +UPDATE `spell_script_names` SET `ScriptName`='spell_algalon_phase_punch_aura' WHERE `spell_id`=64412; +UPDATE `spell_script_names` SET `ScriptName`='spell_algalon_remove_phase_aura' WHERE `spell_id`=64445; +UPDATE `spell_script_names` SET `ScriptName`='spell_assembly_rune_of_summoning_aura' WHERE `spell_id`=62019; +UPDATE `spell_script_names` SET `ScriptName`='spell_aura_of_despair_aura' WHERE `spell_id`=62692; +UPDATE `spell_script_names` SET `ScriptName`='spell_ignis_scorch_aura' WHERE `spell_id` IN (62546, 63474); +UPDATE `spell_script_names` SET `ScriptName`='spell_ignis_slag_pot_aura' WHERE `spell_id` IN (62717, 63477); +UPDATE `spell_script_names` SET `ScriptName`='spell_load_into_catapult_aura' WHERE `spell_id`=64414; +UPDATE `spell_script_names` SET `ScriptName`='spell_mark_of_the_faceless_periodic_aura' WHERE `spell_id`=63276; +UPDATE `spell_script_names` SET `ScriptName`='spell_mimiron_p3wx2_laser_barrage_aura' WHERE `spell_id`=63274; +UPDATE `spell_script_names` SET `ScriptName`='spell_mimiron_rapid_burst_aura' WHERE `spell_id`=63382; +UPDATE `spell_script_names` SET `ScriptName`='spell_orbital_supports_aura' WHERE `spell_id` IN (64482, 65075, 65076, 65077); +UPDATE `spell_script_names` SET `ScriptName`='spell_saronite_vapors_dummy_aura' WHERE `spell_id`=63322; +UPDATE `spell_script_names` SET `ScriptName`='spell_shield_generator_aura' WHERE `spell_id`=64677; +UPDATE `spell_script_names` SET `ScriptName`='spell_shield_of_runes_aura' WHERE `spell_id` IN (62274, 63489); +UPDATE `spell_script_names` SET `ScriptName`='spell_systems_shutdown_aura' WHERE `spell_id`=62475; +UPDATE `spell_script_names` SET `ScriptName`='spell_tar_blaze_aura' WHERE `spell_id`=62292; +UPDATE `spell_script_names` SET `ScriptName`='spell_thorim_lightning_pillar_P2_aura' WHERE `spell_id`=62976; +UPDATE `spell_script_names` SET `ScriptName`='spell_thorim_trash_impale_aura' WHERE `spell_id` IN (62331, 62418); +UPDATE `spell_script_names` SET `ScriptName`='spell_transitus_shield_beam_aura' WHERE `spell_id`=48310; +UPDATE `spell_script_names` SET `ScriptName`='spell_ulduar_arachnopod_damaged_aura' WHERE `spell_id`=64770; +UPDATE `spell_script_names` SET `ScriptName`='spell_ulduar_energy_sap_aura' WHERE `spell_id` IN (64740, 64876); +UPDATE `spell_script_names` SET `ScriptName`='spell_ulduar_stone_grip_aura' WHERE `spell_id` IN (62056, 63985); +UPDATE `spell_script_names` SET `ScriptName`='spell_vehicle_circuit_overload_aura' WHERE `spell_id`=62399; +UPDATE `spell_script_names` SET `ScriptName`='spell_xt002_gravity_bomb' WHERE `spell_id` IN (63024, 64234); +UPDATE `spell_script_names` SET `ScriptName`='spell_yogg_saron_empowered_aura' WHERE `spell_id`=64161; +UPDATE `spell_script_names` SET `ScriptName`='spell_yogg_saron_grim_reprisal_aura' WHERE `spell_id`=63305; +UPDATE `spell_script_names` SET `ScriptName`='spell_yogg_saron_insane_aura' WHERE `spell_id`=63120; +UPDATE `spell_script_names` SET `ScriptName`='spell_yogg_saron_malady_of_the_mind_aura' WHERE `spell_id` IN (63830, 63881) AND `ScriptName` = 'spell_yogg_saron_malady_of_the_mind'; +UPDATE `spell_script_names` SET `ScriptName`='spell_yogg_saron_protective_gaze_aura' WHERE `spell_id`=64174 AND `ScriptName` = 'spell_yogg_saron_protective_gaze'; +UPDATE `spell_script_names` SET `ScriptName`='spell_yogg_saron_sanity_well_aura' WHERE `spell_id`=64169; +UPDATE `spell_script_names` SET `ScriptName`='spell_yogg_saron_shadow_beacon_aura' WHERE `spell_id`=64465; diff --git a/data/sql/updates/db_world/2024_06_11_01.sql b/data/sql/updates/db_world/2024_06_11_01.sql new file mode 100644 index 000000000..774f0aa4e --- /dev/null +++ b/data/sql/updates/db_world/2024_06_11_01.sql @@ -0,0 +1,3 @@ +-- DB update 2024_06_11_00 -> 2024_06_11_01 +-- unlink 'Mighty Blaze' spawns from game events +DELETE from `game_event_gameobject` WHERE `guid` IN (31640, 31642, 31643, 31644, 31646, 31647, 31649, 31651, 31652, 31653, 31654, 31655, 31659, 31661, 31667, 31670, 31677, 31678, 31679, 31681, 31682, 31683, 31687, 31690, 31691, 31692, 31696, 31697, 31698, 31701, 31713, 31721, 31762); diff --git a/data/sql/updates/db_world/2024_06_13_00.sql b/data/sql/updates/db_world/2024_06_13_00.sql new file mode 100644 index 000000000..b9892154e --- /dev/null +++ b/data/sql/updates/db_world/2024_06_13_00.sql @@ -0,0 +1,3 @@ +-- DB update 2024_06_11_01 -> 2024_06_13_00 +-- +UPDATE `creature_equip_template` SET `ItemID1` = 12285 WHERE (`CreatureID` = 8582); diff --git a/data/sql/updates/db_world/2024_06_14_00.sql b/data/sql/updates/db_world/2024_06_14_00.sql new file mode 100644 index 000000000..9fe5958e1 --- /dev/null +++ b/data/sql/updates/db_world/2024_06_14_00.sql @@ -0,0 +1,3 @@ +-- DB update 2024_06_13_00 -> 2024_06_14_00 +-- Reth'hedron the Subduer +UPDATE `creature` SET `spawntimesecs` = 90 WHERE `id1` = 22357 AND `guid` = 86754; diff --git a/data/sql/updates/db_world/2024_06_15_00.sql b/data/sql/updates/db_world/2024_06_15_00.sql new file mode 100644 index 000000000..27ed63ba4 --- /dev/null +++ b/data/sql/updates/db_world/2024_06_15_00.sql @@ -0,0 +1,3 @@ +-- DB update 2024_06_14_00 -> 2024_06_15_00 +-- +UPDATE `creature_template` SET `flags_extra` = `flags_extra` |256 WHERE `entry` = 22878; diff --git a/data/sql/updates/db_world/2024_06_15_01.sql b/data/sql/updates/db_world/2024_06_15_01.sql new file mode 100644 index 000000000..c72ced768 --- /dev/null +++ b/data/sql/updates/db_world/2024_06_15_01.sql @@ -0,0 +1,4 @@ +-- DB update 2024_06_15_00 -> 2024_06_15_01 +-- +DELETE FROM `spell_custom_attr` WHERE `spell_id`=40103; +INSERT INTO `spell_custom_attr` (`spell_id`, `attributes`) VALUES (40103, 4194304); diff --git a/data/sql/updates/db_world/2024_06_15_02.sql b/data/sql/updates/db_world/2024_06_15_02.sql new file mode 100644 index 000000000..e7bd74118 --- /dev/null +++ b/data/sql/updates/db_world/2024_06_15_02.sql @@ -0,0 +1,10 @@ +-- DB update 2024_06_15_01 -> 2024_06_15_02 +-- +DELETE FROM `creature_formations` WHERE `leaderGUID` = 148062; + +UPDATE `creature_template` SET `flags_extra` = `flags_extra`|33554432 WHERE `entry` = 22878; + +DELETE FROM `creature_formations` WHERE `leaderGUID` = 148063; +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`) VALUES +(148063, 148063, 0, 0, 11), +(148063, 148064, 0, 0, 11); diff --git a/data/sql/updates/db_world/2024_06_15_03.sql b/data/sql/updates/db_world/2024_06_15_03.sql new file mode 100644 index 000000000..df14511db --- /dev/null +++ b/data/sql/updates/db_world/2024_06_15_03.sql @@ -0,0 +1,2 @@ +-- DB update 2024_06_15_02 -> 2024_06_15_03 +UPDATE `item_template` SET `spellppmRate_1` = 0.25 WHERE `entry` = 28442; diff --git a/data/sql/updates/db_world/2024_06_15_04.sql b/data/sql/updates/db_world/2024_06_15_04.sql new file mode 100644 index 000000000..4bcaf766a --- /dev/null +++ b/data/sql/updates/db_world/2024_06_15_04.sql @@ -0,0 +1,3 @@ +-- DB update 2024_06_15_03 -> 2024_06_15_04 +-- +UPDATE `achievement_reward` SET `Body`='Can you believe this Plump Turkey made it through November alive?\r\n\r\nSince all this friends have been served up on Bountiful Tables with sides of Cranberry Chutney and Spice Bread Stuffing and... ooo... I\'m getting hungry. But anyhow! He\'s all alone, now, so I was hoping you might be willing to take care of him. There simply isn\'t enough room left in my shop!\r\n\r\nJust keep him away from cooking fires, please. He gets this strange look in his eyes around them...' WHERE `ID`=3656; diff --git a/data/sql/updates/db_world/2024_06_16_00.sql b/data/sql/updates/db_world/2024_06_16_00.sql new file mode 100644 index 000000000..0f9d4369e --- /dev/null +++ b/data/sql/updates/db_world/2024_06_16_00.sql @@ -0,0 +1,25 @@ +-- DB update 2024_06_15_04 -> 2024_06_16_00 +DROP TABLE IF EXISTS `creature_template_model`; +CREATE TABLE `creature_template_model`( + `CreatureID` int unsigned NOT NULL, + `Idx` smallint unsigned NOT NULL DEFAULT '0', + `CreatureDisplayID` int unsigned NOT NULL, + `DisplayScale` float NOT NULL DEFAULT '1', + `Probability` float NOT NULL DEFAULT '0', + `VerifiedBuild` smallint unsigned, + PRIMARY KEY (`CreatureID`,`Idx`), + CONSTRAINT creature_template_model_chk_1 CHECK (`Idx` <= 3) +) ENGINE=InnoDB CHARSET=utf8mb4; + +INSERT IGNORE INTO `creature_template_model` (`CreatureID`,`Idx`,`CreatureDisplayID`,`DisplayScale`,`Probability`,`VerifiedBuild`) SELECT `entry`,0,`modelid1`,`scale`,1,`VerifiedBuild` FROM `creature_template` WHERE `modelid1`!=0; +INSERT IGNORE INTO `creature_template_model` (`CreatureID`,`Idx`,`CreatureDisplayID`,`DisplayScale`,`Probability`,`VerifiedBuild`) SELECT `entry`,1,`modelid2`,`scale`,1,`VerifiedBuild` FROM `creature_template` WHERE `modelid2`!=0; +INSERT IGNORE INTO `creature_template_model` (`CreatureID`,`Idx`,`CreatureDisplayID`,`DisplayScale`,`Probability`,`VerifiedBuild`) SELECT `entry`,2,`modelid3`,`scale`,1,`VerifiedBuild` FROM `creature_template` WHERE `modelid3`!=0; +INSERT IGNORE INTO `creature_template_model` (`CreatureID`,`Idx`,`CreatureDisplayID`,`DisplayScale`,`Probability`,`VerifiedBuild`) SELECT `entry`,3,`modelid4`,`scale`,1,`VerifiedBuild` FROM `creature_template` WHERE `modelid4`!=0; + +UPDATE `creature_template` SET `scale`=1; + +ALTER TABLE `creature_template` + DROP `modelid1`, + DROP `modelid2`, + DROP `modelid3`, + DROP `modelid4`; diff --git a/data/sql/updates/db_world/2024_06_16_01.sql b/data/sql/updates/db_world/2024_06_16_01.sql new file mode 100644 index 000000000..790f117a0 --- /dev/null +++ b/data/sql/updates/db_world/2024_06_16_01.sql @@ -0,0 +1,4 @@ +-- DB update 2024_06_16_00 -> 2024_06_16_01 +-- +DELETE FROM `spell_custom_attr` WHERE `spell_id`=36478; +INSERT INTO `spell_custom_attr` (`spell_id`, `attributes`) VALUES (36478, 4194304); diff --git a/data/sql/updates/db_world/2024_06_16_02.sql b/data/sql/updates/db_world/2024_06_16_02.sql new file mode 100644 index 000000000..fef09ca20 --- /dev/null +++ b/data/sql/updates/db_world/2024_06_16_02.sql @@ -0,0 +1,10 @@ +-- DB update 2024_06_16_01 -> 2024_06_16_02 +UPDATE `creature_model_info` SET `BoundingRadius` = 2.10000014305114746 WHERE `DisplayID` = 21174; +UPDATE `creature_model_info` SET `BoundingRadius` = 80, `CombatReach` = 24 WHERE `DisplayID` = 21145; +UPDATE `creature_model_info` SET `CombatReach` = 5.774999618530273437 WHERE `DisplayID` = 21443; +UPDATE `creature_model_info` SET `BoundingRadius` = 0.310000002384185791, `CombatReach` = 8 WHERE `DisplayID` IN (21483, 21484, 21485); +UPDATE `creature_model_info` SET `BoundingRadius` = 0.80429995059967041, `CombatReach` = 3.149999856948852539 WHERE `DisplayID` = 21417; +UPDATE `creature_model_info` SET `BoundingRadius` = 0.842599987983703613, `CombatReach` = 3.300000190734863281 WHERE `DisplayID` = 21416; +UPDATE `creature_model_info` SET `BoundingRadius` = 0.861749947071075439 WHERE `DisplayID` = 21418; +UPDATE `creature_model_info` SET `BoundingRadius` = 0.80429995059967041, `CombatReach` = 3.149999856948852539 WHERE `DisplayID` = 21419; +UPDATE `creature_model_info` SET `BoundingRadius` = 0.458999991416931152 WHERE `DisplayID` = 21135; diff --git a/data/sql/updates/db_world/2024_06_16_03.sql b/data/sql/updates/db_world/2024_06_16_03.sql new file mode 100644 index 000000000..36992021f --- /dev/null +++ b/data/sql/updates/db_world/2024_06_16_03.sql @@ -0,0 +1,6 @@ +-- DB update 2024_06_16_02 -> 2024_06_16_03 +-- +DELETE FROM `spell_script_names` WHERE `spell_id` IN (57491, 60241); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(57491, 'spell_obsidian_sanctum_flame_tsunami'), +(60241, 'spell_obsidian_sanctum_flame_tsunami_leap'); diff --git a/data/sql/updates/db_world/2024_06_17_00.sql b/data/sql/updates/db_world/2024_06_17_00.sql new file mode 100644 index 000000000..7bc1f67be --- /dev/null +++ b/data/sql/updates/db_world/2024_06_17_00.sql @@ -0,0 +1,4 @@ +-- DB update 2024_06_16_03 -> 2024_06_17_00 +-- +DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_hand_of_death', 'spell_finger_of_death'); +UPDATE `creature_template` SET `flags_extra` = `flags_extra` |128 WHERE `entry` IN (18104, 18095); diff --git a/data/sql/updates/db_world/2024_06_17_01.sql b/data/sql/updates/db_world/2024_06_17_01.sql new file mode 100644 index 000000000..0c567e8c8 --- /dev/null +++ b/data/sql/updates/db_world/2024_06_17_01.sql @@ -0,0 +1,321 @@ +-- DB update 2024_06_17_00 -> 2024_06_17_01 +SET @OGUID := 1267; -- 21 free guids required +SET @CGUID := 12529; -- 21 free guids required + +SET @NPC := @CGUID+10; +SET @PATH := @NPC * 10; + +UPDATE `creature_template` SET `difficulty_entry_1` = 0 WHERE `entry` IN (25740, 25755, 25756, 25865); +UPDATE `creature_template` SET `unit_flags` = `unit_flags` | 0x00000040, `mechanic_immune_mask` = `mechanic_immune_mask` | 0x02000000 WHERE `entry` = 25740; -- Ahune +UPDATE `creature_template_model` SET `CreatureDisplayID` = 23344 WHERE `CreatureID` = 25740 AND `Idx` = 0; -- ToDo: replace entries with sniffed shtuff. +UPDATE `creature_template` SET `minlevel` = 80, `maxlevel` = 80, `unit_flags` = `unit_flags` | 0x00000004 | 0x00000100 | 131072 | 33554432, `flags_extra` = `flags_extra` | 0x40000000, `ScriptName` = 'npc_frozen_core' WHERE `entry` = 25865; -- Frozen Core (might be interruptable) +UPDATE `creature_template` SET `AIName` = '', `ScriptName` = 'npc_ahune_bunny' WHERE `entry` = 25745; +UPDATE `creature_template` SET `ScriptName` = 'npc_earthen_ring_flamecaller' WHERE `entry` = 25754; +UPDATE `creature_template` SET `unit_flags` = `unit_flags` | 0x02000000, `MovementType` = 2 WHERE `entry` IN (25964, 25965, 25966); -- Shaman Beam Bunnies +UPDATE `creature_template` SET `flags_extra` = `flags_extra` | 0x00000080, `ScriptName` = 'npc_ahune_ice_spear_bunny' WHERE `entry` = 25985; -- Ahune Ice Spear Bunny +UPDATE `creature_template` SET `flags_extra` = `flags_extra` | 0x00000002 | 0x00000080 WHERE `entry` = 26239; + +UPDATE `creature_model_info` SET `BoundingRadius` = 7.1468, `CombatReach` = 22 WHERE `DisplayID` = 23447; + +UPDATE `gameobject_template` SET `ScriptName` = 'go_ahune_ice_spear' WHERE `entry` = 188077; -- Ice Spear + +DELETE FROM `creature_template_movement` WHERE `CreatureId` = 26190; +INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`, `Chase`, `Random`, `InteractionPauseTimer`) VALUES +(26190, 1, 1, 1, 0, 0, 0, NULL); + +DELETE FROM `spell_script_names` WHERE `ScriptName` IN +('spell_ahune_synch_health', +'spell_ice_spear_control_aura', +'spell_slippery_floor_periodic', +'spell_summon_ice_spear_delayer', +'spell_summoning_rhyme_aura', +'spell_ahune_spanky_hands', +'spell_ahune_minion_despawner', +'spell_ice_spear_target_picker', +'spell_ice_bombardment_dest_picker'); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(46430, 'spell_ahune_synch_health'), +(46371, 'spell_ice_spear_control_aura'), +(46320, 'spell_slippery_floor_periodic'), +(46878, 'spell_summon_ice_spear_delayer'), +(45926, 'spell_summoning_rhyme_aura'), +(46146, 'spell_ahune_spanky_hands'), +(46843, 'spell_ahune_minion_despawner'), +(46372, 'spell_ice_spear_target_picker'), +(46398, 'spell_ice_bombardment_dest_picker'); + +UPDATE `creature_text` SET `comment` = 'Ahune Bunny - EMOTE_EARTHEN_ASSAULT' WHERE `CreatureID` = 25745 AND `id` = 0; -- Missing space before hyphen + +DELETE FROM `creature_template_addon` WHERE `entry` IN (25740, 25754, 25755, 25865, 25952, 25985); +INSERT INTO `creature_template_addon` (`entry`, `path_id`, `mount`, `bytes1`, `bytes2`, `visibilityDistanceType`, `auras`) VALUES +(25740, 0, 0, 9, 1, 3, 61976), +(25754, 0, 0, 1, 1, 3, ''), +(25755, 0, 0, 0, 0, 3, 46542), +(25865, 0, 0, 0, 0, 0, '46810 61976'), +(25952, 0, 0, 0, 0, 3, 46314), +(25985, 0, 0, 0, 0, 0, '75498 46878'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 13 AND `SourceEntry` IN (45930, 45941, 46236, 46396, 46398, 46593, 46603, 46735, 46809, 46843); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13, 1, 45930, 0, 1, 31, 0, 3, 25971, 0, 0, 0, 0, '', "Spell 'Ahune - Summoning Rhyme Spell, make bonfire' can hit 'Shaman Bonfire Bunny 000'"), +(13, 1, 45930, 0, 2, 31, 0, 3, 25972, 0, 0, 0, 0, '', "Spell 'Ahune - Summoning Rhyme Spell, make bonfire' can hit 'Shaman Bonfire Bunny 001'"), +(13, 1, 45930, 0, 3, 31, 0, 3, 25973, 0, 0, 0, 0, '', "Spell 'Ahune - Summoning Rhyme Spell, make bonfire' can hit 'Shaman Bonfire Bunny 002'"), +(13, 1, 45941, 0, 0, 31, 0, 3, 25746, 0, 0, 0, 0, '', "Spell 'Summon Ahune's Loot Missile' can hit '[PH] Ahune Loot Loc Bunny'"), +(13, 1, 46236, 0, 1, 31, 0, 3, 25971, 0, 0, 0, 0, '', "Spell 'Close opening Visual' can hit 'Shaman Bonfire Bunny 000'"), +(13, 1, 46236, 0, 2, 31, 0, 3, 25972, 0, 0, 0, 0, '', "Spell 'Close opening Visual' can hit 'Shaman Bonfire Bunny 001'"), +(13, 1, 46236, 0, 3, 31, 0, 3, 25973, 0, 0, 0, 0, '', "Spell 'Close opening Visual' can hit 'Shaman Bonfire Bunny 002'"), +(13, 1, 46396, 0, 0, 31, 0, 3, 25972, 0, 0, 0, 0, '', "Spell 'Ice Bombardment' can hit 'Shaman Bonfire Bunny'"), +(13, 1, 46398, 0, 0, 31, 0, 3, 25972, 0, 0, 0, 0, '', "Spell 'Ice Bombardment Dest Picker' can hit 'Shaman Bonfire Bunny'"), +(13, 1, 46593, 0, 0, 31, 0, 3, 26120, 0, 0, 0, 0, '', "Spell 'Wisp Flight Missile and Beam' can hit 'Wisp Dest Bunny'"), +(13, 1, 46603, 0, 0, 31, 0, 3, 26121, 0, 0, 0, 0, '', "Spell 'Force Wisp Flight Missile' can hit 'Wisp Source Bunny'"), +(13, 1, 46735, 0, 0, 31, 0, 3, 26190, 0, 0, 0, 0, '', "Spell 'Spank - Force Bunny To Knock You To' can hit '[PH] Spank Target Bunny'"), +(13, 1, 46809, 0, 0, 31, 0, 3, 26239, 0, 0, 0, 0, '', "Spell 'Make Ahune's Ghost Burst' can hit 'Ghost of Ahune"), +(13, 1, 46843, 0, 3, 31, 0, 3, 25755, 0, 0, 0, 0, '', "Spell 'Minion Despawner' can hit 'Ahunite Hailstone'"), +(13, 1, 46843, 0, 1, 31, 0, 3, 25756, 0, 0, 0, 0, '', "Spell 'Minion Despawner' can hit 'Ahunite Coldwave'"), +(13, 1, 46843, 0, 2, 31, 0, 3, 25757, 0, 0, 0, 0, '', "Spell 'Minion Despawner' can hit 'Ahunite Frostwind'"); + +DELETE FROM `disables` WHERE `sourceType` = 0 AND `entry` IN (46314, 46422, 46593, 46603); +INSERT INTO `disables` (`sourceType`, `entry`, `flags`, `params_0`, `params_1`, `comment`) VALUES +(0, 46314, 64, 0, 0, 'Disable LOS for spell Ahune - Slippery Floor Ambient'), +(0, 46422, 64, 0, 0, 'Disable LOS for spell Shamans Look for Opening'), +(0, 46593, 64, 0, 0, 'Disable LOS for spell Whisp Flight Missile and Beam'), +(0, 46603, 64, 0, 0, 'Disable LOS for spell Force Whisp to Flight'); + +DELETE FROM `spell_linked_spell` WHERE `spell_trigger` IN (-45964, 45964); +INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES +(-45964, -46333, 0, ''), +(45964, 46333, 0, ''); + +-- Skar'this the Summoner +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 40446; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 40446 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 +(40446,0,0,0,1,0,100,1,0,0,0,0,11,75427,0,0,0,0,0,1,0,0,0,0,0,0,0,'Skar\'this the Summoner - OOC - Cast \'Frost Channelling\''), +(40446,0,1,0,4,0,100,1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Skar\'this the Summoner - On aggro - Say'), +(40446,0,2,0,0,0,100,0,5000,5000,15000,15000,11,55909,1,0,0,0,0,2,0,0,0,0,0,0,0,'Skar\'this the Summoner - IC - Cast Crashing Wave'), +(40446,0,3,0,0,0,100,0,10000,10000,20000,20000,11,11831,1,0,0,0,0,2,0,0,0,0,0,0,0,'Skar\'this the Summoner - IC - Cast Frost Nova'), +(40446,0,4,0,0,0,100,0,7000,7000,9000,9000,11,15043,0,0,0,0,0,2,0,0,0,0,0,0,0,'Skar\'this the Summoner - IC - Cast Frostbolt'); + +-- Summon Loot Bunny SAI +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 25746; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 25746 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 +(25746,0,0,0,8,0,100,0,45941,0,0,0,11,46891,0,0,0,0,0,1,0,0,0,0,0,0,0,'[PH] Ahune Loot Loc Bunny - On SpellHit - Cast \'Summon Loot\''); + +-- [PH] Spank Target Bunny SAI +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 26190; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 26190 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 +(26190,0,0,0,8,0,100,0,46735,0,0,0,11,46734,0,0,0,0,0,7,0,0,0,0,0,0,0,'[PH] Spank Target Bunny - On SpellHit \'Spank - Force Bunny To Knock You To\' - Cast \'Knock To\''); + +-- Ghost of Ahune +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 26239; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 26239 AND `source_type` = 0; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 2623900 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 +(26239,0,0,0,25,0,100,0,0,0,0,0,3,0,11686,0,0,0,0,1,0,0,0,0,0,0,0,'Ghost of Ahune - On Reset - Morph to Model 11686'), +(26239,0,1,0,8,0,100,0,46809,0,4000,4000,80,2623900,2,0,0,0,0,1,0,0,0,0,0,0,0,'Ghost of Ahune - On SpellHit \'Make Ahune\'s Ghost Burst\' - Call Timed ActionList'), +(2623900,9,0,0,0,0,100,0,0,0,0,0,3,0,23707,0,0,0,0,1,0,0,0,0,0,0,0,'Ghost of Ahune - Timed ActionList - Morph to Model 23707'), +(2623900,9,1,0,0,0,100,0,0,0,0,0,11,46786,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ghost of Ahune - Timed ActionList - Cast \'Ahune\'s Ghost Disguise\''), +(2623900,9,2,0,0,0,100,0,2400,2400,0,0,47,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ghost of Ahune - Timed ActionList - Set Visibility Off'), +(2623900,9,3,0,0,0,100,0,500,500,0,0,3,0,11686,0,0,0,0,1,0,0,0,0,0,0,0,'Ghost of Ahune - Timed ActionList - Morph to Model 11686'), +(2623900,9,4,0,0,0,100,0,0,0,0,0,47,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ghost of Ahune - Timed ActionList - Set Visibility On'); + +-- Wisp Source Bunny SAI +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 26121; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 26121 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 +(26121,0,0,1,8,0,100,0,46603,0,0,0,11,46593,0,0,0,0,0,11,26120,100,0,0,0,0,0,'Wisp Source Bunny - On SpellHit \'Force Wisp Flight Missile\' - Cast \'Wisp Flight Missile and Beam\''), +(26121,0,1,0,61,0,100,0,0,0,0,0,41,9000,0,0,0,0,0,1,0,0,0,0,0,0,0,'Wisp Source Bunny - On SpellHit \'Force Wisp Flight Missile\' - Despawn in 9s'); + +-- Wisp Dest Bunny SAI +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 26120; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 26120 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 +(26120,0,0,0,8,0,100,0,46593,0,0,0,41,9000,0,0,0,0,0,1,0,0,0,0,0,0,0,'Wisp Dest Bunny - On SpellHit \'Wisp Flight Missile and Beam\' - Despawn in 9s'); + +-- Shaman Beam Bunny SAI +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` IN (25971, 25972, 25973); +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (25971, 25972, 25973) 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 +(25971,0,0,0,8,0,100,0,45930,0,0,0,11,46339,0,0,0,0,0,1,0,0,0,0,0,0,0,'Shaman Beam Bunny 000 - On SpellHit - Cast \'Bonfire Disguise\''), +(25972,0,0,0,8,0,100,0,45930,0,0,0,11,46339,0,0,0,0,0,1,0,0,0,0,0,0,0,'Shaman Beam Bunny 001 - On SpellHit - Cast \'Bonfire Disguise\''), +(25973,0,0,0,8,0,100,0,45930,0,0,0,11,46339,0,0,0,0,0,1,0,0,0,0,0,0,0,'Shaman Beam Bunny 002 - On SpellHit - Cast \'Bonfire Disguise\''); + +-- Ahunite Hailstone SAI +-- UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=25755; -- has SAI, replace script only +DELETE FROM `smart_scripts` WHERE `entryorguid` = 25755 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 +(25755,0,0,0,0,0,100,0,6000,8000,6000,8000,11,2676,0,0,0,0,0,2,0,0,0,0,0,0,0,'Ahunite Hailstone - In Combat - Cast \'Pulverize\''); + +-- Ahunite Coldwave SAI +-- UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=25756; -- has SAI, replace script only +DELETE FROM `smart_scripts` WHERE `entryorguid` = 25756 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 +(25756,0,0,0,0,0,100,0,5000,7000,6000,8000,11,46406,0,0,0,0,0,2,0,0,0,0,0,0,0,'Ahunite Coldwave - In Combat - Cast \'Bitter Blast\''); + +-- Ahunite Frostwind SAI +-- UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=25757; -- has SAI, replace script only +DELETE FROM `smart_scripts` WHERE `entryorguid` = 25757 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 +(25757,0,0,0,54,0,100,0,0,0,0,0,11,12550,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ahunite Frostwind - On Just Summoned - Cast \'Lightning Shield\''), +(25757,0,1,0,0,0,100,0,2000,2000,5000,7000,11,46568,0,0,0,0,0,18,120,0,0,0,0,0,0,'Ahunite Frostwind - In Combat - Cast \'Wind Buffet\''); + +-- Clean up spawns +DELETE FROM `creature` WHERE `guid` IN (202734, 202735, 202736, 202737, 245704, 245800, 245801, 245810, 245811, 245812) AND `id1` IN (25697, 25754, 25710, 28015, 25971, 25972, 25973); +DELETE FROM `game_event_creature` WHERE `guid` IN (202734, 202735, 202736, 202737, 245704, 245800, 245801, 245810, 245811, 245812); +-- Ensure free GUIDs +DELETE FROM `creature` WHERE `guid` BETWEEN @CGUID+0 AND @CGUID+20 AND `id1` IN (25697, 25710, 25745, 25746, 25754, 25952, 25961, 25964, 25965, 25966, 5971, 25972, 25973, 26120, 26121, 26190, 26230, 40446); +DELETE FROM `game_event_creature` WHERE `guid` BETWEEN @CGUID+0 AND @CGUID+20; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (-245801, -245800) AND `source_type` = 0; +INSERT INTO `creature` (`guid`, `id1`, `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`, `VerifiedBuild`) VALUES +-- (@CGUID+0, 16592, 547, 0, 0, 3, 1, 0, -114.745880126953125, -117.226593017578125, -2.44469881057739257, 1.169368624687194824, 7200, 0, 0, 42, 0, 0, 0, 0, 0, 50172), +-- (@CGUID+0, 16592, 547, 0, 0, 3, 1, 0, -89.8604965209960937, -113.449333190917968, -2.3303837776184082, 2.617989301681518554, 7200, 0, 0, 42, 0, 0, 0, 0, 0, 50172), +(@CGUID+0 , 25697, 547, 0, 0, 3, 1, 0, -92.4571914672851562, -110.664161682128906, -2.86675882339477539, 2.408554315567016601, 7200, 0, 0, 4781, 0, 0, 0, 0, 0, 50172), +(@CGUID+1 , 25710, 547, 0, 0, 3, 1, 0, 131.4105682373046875, -120.632652282714843, -1.50722658634185791, 4.206243515014648437, 7200, 0, 0, 42, 0, 0, 0, 0, 0, 50172), +(@CGUID+2 , 25745, 547, 0, 0, 3, 1, 0, -96.6414566040039062, -230.886444091796875, 4.78095865249633789, 1.413716673851013183, 7200, 0, 0, 42, 0, 0, 0, 0, 0, 50172), +(@CGUID+3 , 25746, 547, 0, 0, 3, 1, 0, -96.8722991943359375, -212.84246826171875, -1.14914166927337646, 4.15388345718383789, 7200, 0, 0, 42, 0, 0, 0, 0, 0, 50172), +(@CGUID+4 , 25754, 547, 0, 0, 3, 1, 0, -112.209869384765625, -120.209037780761718, -2.65799570083618164, 5.183627605438232421, 7200, 0, 0, 10282, 0, 0, 0, 0, 0, 50172), +(@CGUID+5 , 25754, 547, 0, 0, 3, 1, 0, -110.19451904296875, -116.621482849121093, -3.25569367408752441, 0.104719758033752441, 7200, 0, 0, 10635, 0, 0, 0, 0, 0, 50172), +(@CGUID+6 , 25754, 547, 0, 0, 3, 1, 0, -93.1847915649414062, -115.92059326171875, -2.69253182411193847, 3.804817676544189453, 7200, 0, 0, 9940, 0, 0, 0, 0, 0, 50172), +(@CGUID+7 , 25952, 547, 0, 0, 3, 1, 0, -69.8390121459960937, -162.473968505859375, -2.30364584922790527, 2.513274192810058593, 7200, 0, 0, 42, 0, 0, 0, 0, 0, 50172), +(@CGUID+8 , 25961, 547, 0, 0, 3, 1, 0, -109.223983764648437, -120.052108764648437, -2.98242378234863281, 5.113814830780029296, 7200, 0, 0, 484, 0, 0, 0, 0, 0, 50172), +(@CGUID+9 , 25961, 547, 0, 0, 3, 1, 0, -92.689605712890625, -119.627853393554687, -2.27035880088806152, 4.223696708679199218, 7200, 0, 0, 484, 0, 0, 0, 0, 0, 50172), +(@CGUID+10, 25964, 547, 0, 0, 3, 1, 0, -90.0021133422851562, -224.928543090820312, -1.378753662109375, 4.571401596069335937, 7200, 0, 0, 42, 0, 0, 0, 0, 0, 50172), +(@CGUID+11, 25965, 547, 0, 0, 3, 1, 0, -97.396270751953125, -223.76104736328125, -1.49489867687225341, 5.32932901382446289, 7200, 0, 0, 42, 0, 0, 0, 0, 0, 50172), +(@CGUID+12, 25966, 547, 0, 0, 3, 1, 0, -104.356178283691406, -223.356185913085937, -1.46137666702270507, 5.672232627868652343, 7200, 0, 0, 42, 0, 0, 0, 0, 0, 50172), +(@CGUID+13, 25971, 547, 0, 0, 3, 1, 0, -143.17193603515625, -147.680130004882812, -3.16113066673278808, 4.852015495300292968, 7200, 0, 0, 42, 0, 0, 0, 0, 0, 50172), +(@CGUID+14, 25972, 547, 0, 0, 3, 1, 0, -134.30364990234375, -145.780303955078125, -1.70331764221191406, 4.677482128143310546, 7200, 0, 0, 42, 0, 0, 0, 0, 0, 50172), +(@CGUID+15, 25973, 547, 0, 0, 3, 1, 0, -125.035713195800781, -144.20654296875, -1.91659557819366455, 4.991641521453857421, 7200, 0, 0, 42, 0, 0, 0, 0, 0, 50172), +(@CGUID+16, 26120, 547, 0, 0, 3, 1, 0, -98.102935791015625, -230.786407470703125, -10.8084640502929687, 1.448623299598693847, 7200, 0, 0, 42, 0, 0, 0, 0, 0, 50172), +(@CGUID+17, 26121, 547, 0, 0, 3, 1, 0, -69.8120498657226562, -162.49542236328125, -2.30450677871704101, 1.710422635078430175, 7200, 0, 0, 42, 0, 0, 0, 0, 0, 50172), +(@CGUID+18, 26190, 547, 0, 0, 3, 1, 0, -95.335723876953125, -207.483352661132812, 16.28742027282714843, 4.904375076293945312, 7200, 0, 0, 4120, 0, 0, 0, 0, 0, 50172), +(@CGUID+19, 26230, 547, 0, 0, 3, 1, 0, -98.8607406616210937, -233.752609252929687, 8.372927665710449218, 2.757620096206665039, 7200, 0, 0, 42, 0, 0, 0, 0, 0, 50172), +(@CGUID+20, 40446, 547, 0, 0, 3, 1, 0, -76.9917221069335937, -157.080520629882812, -2.10638880729675292, 5.637413501739501953, 7200, 0, 0, 50400, 0, 0, 0, 0, 0, 50172); + +INSERT INTO `game_event_creature` (`eventEntry`, `guid`) VALUES +(1, @CGUID+0), +(1, @CGUID+1), +(1, @CGUID+2), +(1, @CGUID+3), +(1, @CGUID+4), +(1, @CGUID+5), +(1, @CGUID+6), +(1, @CGUID+7), +(1, @CGUID+8), +(1, @CGUID+9), +(1, @CGUID+10), +(1, @CGUID+11), +(1, @CGUID+12), +(1, @CGUID+13), +(1, @CGUID+14), +(1, @CGUID+15), +(1, @CGUID+16), +(1, @CGUID+17), +(1, @CGUID+18), +(1, @CGUID+19), +(1, @CGUID+20); + +-- Clean up spawns +DELETE FROM `gameobject` WHERE `guid` IN (87, 88, 11207, 11208, 11209, 11210, 11211, 11212, 11213, 11214, 11215, 11216, 11217, 220100, 220101, 220102, 220103, 220104, 220105, 220106, 220111, 220112) AND `id` IN (181371, 187882, 188067, 188072, 188073, 188142, 195000); +DELETE FROM `game_event_gameobject` WHERE `guid` IN (87, 88, 11207, 11208, 11209, 11210, 11211, 11212, 11213, 11214, 11215, 11216, 11217, 220100, 220101, 220102, 220103, 220104, 220105, 220106, 220111, 220112); +-- Ensure free GUIDs +DELETE FROM `gameobject` WHERE `guid` BETWEEN @OGUID+0 AND @OGUID+20 AND `id` IN (187882, 188067, 188072, 188073, 188142, 195000); +DELETE FROM `game_event_gameobject` WHERE `guid` BETWEEN @OGUID+0 AND @OGUID+20; +DELETE FROM `pool_gameobject` WHERE `guid` BETWEEN @OGUID+0 AND @OGUID+20; +INSERT INTO `gameobject` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`, `VerifiedBuild`) VALUES +-- (@OGUID+0 , 181290, 547, 0, 0, 3, 1, -114.745880126953125, -117.226593017578125, -2.52803206443786621, 1.169368624687194824, 0, 0, 0.551936149597167968, 0.833886384963989257, 7200, 255, 1, 50172), +-- (@OGUID+0 , 181290, 547, 0, 0, 3, 1, -89.8604965209960937, -113.449333190917968, -2.41371703147888183, 2.617989301681518554, 0, 0, 0.965925216674804687, 0.258821308612823486, 7200, 255, 1, 50172), +-- (@OGUID+0 , 181376, 547, 0, 0, 3, 1, -114.745880126953125, -117.226593017578125, -2.52803206443786621, 1.169368624687194824, 0, 0, 0.551936149597167968, 0.833886384963989257, 7200, 255, 1, 50172), +-- (@OGUID+0 , 181376, 547, 0, 0, 3, 1, -89.8604965209960937, -113.449333190917968, -2.41371703147888183, 2.617989301681518554, 0, 0, 0.965925216674804687, 0.258821308612823486, 7200, 255, 1, 50172), +(@OGUID+0 , 187882, 547, 0, 0, 3, 1, -69.9045486450195312, -162.244949340820312, -2.366563081741333, 2.426007747650146484, 0, 0, 0.936672210693359375, 0.350207358598709106, 7200, 255, 1, 50172), +(@OGUID+1 , 188067, 547, 0, 0, 3, 1, -115.598533630371093, -162.772384643554687, -1.92402505874633789, 5.724681377410888671, 0, 0, -0.27563667297363281, 0.961261868476867675, 7200, 255, 1, 50172), +(@OGUID+2 , 188067, 547, 0, 0, 3, 1, -83.5252761840820312, -172.18060302734375, -3.81652188301086425, 0.017452461645007133, 0, 0, 0.008726119995117187, 0.999961912631988525, 7200, 255, 1, 50172), +(@OGUID+3 , 188067, 547, 0, 0, 3, 1, -79.397003173828125, -219.702499389648437, -4.04289197921752929, 4.084071159362792968, 0, 0, -0.8910064697265625, 0.453990638256072998, 7200, 255, 1, 50172), +(@OGUID+4 , 188067, 547, 0, 0, 3, 1, -75.2318267822265625, -217.329315185546875, -3.0727999210357666, 5.794494152069091796, 0, 0, -0.24192142486572265, 0.970295846462249755, 7200, 255, 1, 50172), +(@OGUID+5 , 188067, 547, 0, 0, 3, 1, -75.9513931274414062, -182.77099609375, -4.88201713562011718, 5.131268978118896484, 0, 0, -0.54463863372802734, 0.838670849800109863, 7200, 255, 1, 50172), +(@OGUID+6 , 188067, 547, 0, 0, 3, 1, -71.8962478637695312, -145.49737548828125, -1.55181300640106201, 4.328419685363769531, 0, 0, -0.82903671264648437, 0.559194147586822509, 7200, 255, 1, 50172), +(@OGUID+7 , 188067, 547, 0, 0, 3, 1, -49.2725067138671875, -168.985946655273437, -1.89881098270416259, 2.007128477096557617, 0, 0, 0.84339141845703125, 0.537299633026123046, 7200, 255, 1, 50172), +(@OGUID+8 , 188072, 547, 0, 0, 3, 1, -71.824859619140625, -164.474990844726562, -3.96298193931579589, 5.35816192626953125, 0, 0, -0.446197509765625, 0.894934535026550292, 7200, 255, 1, 50172), +(@OGUID+9 , 188072, 547, 0, 0, 3, 1, -71.4891510009765625, -160.731643676757812, -4.18568992614746093, 5.864306926727294921, 0, 0, -0.20791149139404296, 0.978147625923156738, 7200, 255, 1, 50172), +(@OGUID+10, 188072, 547, 0, 0, 3, 1, -69.2083663940429687, -160.345046997070312, -4.25643014907836914, 1.85004889965057373, 0, 0, 0.798635482788085937, 0.60181504487991333, 7200, 255, 1, 50172), +(@OGUID+11, 188072, 547, 0, 0, 3, 1, -69.2177276611328125, -163.490951538085937, -2.04477310180664062, 2.967041015625, 0, 0, 0.996193885803222656, 0.087165042757987976, 7200, 255, 1, 50172), +(@OGUID+12, 188073, 547, 0, 0, 3, 1, -114.957443237304687, -117.301666259765625, -2.71000003814697265, 2.007128477096557617, 0, 0, 0.84339141845703125, 0.537299633026123046, 7200, 255, 1, 50172), +(@OGUID+13, 188073, 547, 0, 0, 3, 1, -89.7520523071289062, -113.500236511230468, -2.70944190025329589, 0.453785061836242675, 0, 0, 0.224950790405273437, 0.974370121955871582, 7200, 255, 1, 50172), +(@OGUID+14, 188142, 547, 0, 0, 3, 1, -118.919563293457031, -204.802276611328125, -1.50416100025177001, 1.919861555099487304, 0, 0, 0.819151878356933593, 0.573576688766479492, 7200, 255, 1, 50172), +(@OGUID+15, 188142, 547, 0, 0, 3, 1, -117.385650634765625, -165.964920043945312, -2.01864600181579589, 0.558503925800323486, 0, 0, 0.275636672973632812, 0.961261868476867675, 7200, 255, 1, 50172), +(@OGUID+16, 188142, 547, 0, 0, 3, 1, -103.713432312011718, -245.504074096679687, -1.37788105010986328, 4.991643905639648437, 0, 0, -0.60181427001953125, 0.798636078834533691, 7200, 255, 1, 50172), +(@OGUID+17, 188142, 547, 0, 0, 3, 1, -75.4278411865234375, -221.159988403320312, -2.88294100761413574, 0.488691210746765136, 0, 0, 0.241921424865722656, 0.970295846462249755, 7200, 255, 1, 50172), +(@OGUID+18, 188142, 547, 0, 0, 3, 1, -74.6595916748046875, -243.812469482421875, -2.73599910736083984, 2.216565132141113281, 0, 0, 0.894933700561523437, 0.44619917869567871, 7200, 255, 1, 50172), +(@OGUID+19, 188142, 547, 0, 0, 3, 1, -72.753143310546875, -185.154693603515625, -4.93059301376342773, 0.15707901120185852, 0, 0, 0.078458786010742187, 0.996917366981506347, 7200, 255, 1, 50172), +(@OGUID+20, 195000, 547, 0, 0, 3, 1, -98.0260238647460937, -230.428787231445312, -7.61181306838989257, 0, 0, 0, 0, 1, 7200, 255, 1, 50172); + +INSERT INTO `game_event_gameobject` (`eventEntry`, `guid`) VALUES +(1, @OGUID+0), +(1, @OGUID+1), +(1, @OGUID+2), +(1, @OGUID+3), +(1, @OGUID+4), +(1, @OGUID+5), +(1, @OGUID+6), +(1, @OGUID+7), +(1, @OGUID+8), +(1, @OGUID+9), +(1, @OGUID+10), +(1, @OGUID+11), +(1, @OGUID+12), +(1, @OGUID+13), +(1, @OGUID+14), +(1, @OGUID+15), +(1, @OGUID+16), +(1, @OGUID+17), +(1, @OGUID+18), +(1, @OGUID+19), +(1, @OGUID+20); + +DELETE FROM `creature_addon` WHERE `guid` IN (@NPC,@NPC+1,@NPC+2); +INSERT INTO `creature_addon` (`guid`,`path_id`) VALUES +(@NPC,@PATH), +(@NPC+1,@PATH+10), +(@NPC+2,@PATH+20); + +DELETE FROM `waypoint_data` WHERE `id` IN (@PATH,@PATH+10,@PATH+20); +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-107.1537,-233.7247,27.1834,0,0,0,100,0), +(@PATH,2,-109.4618,-232.0907,25.12787,0,0,0,100,0), +(@PATH,3,-109.4792,-229.4328,20.98899,0,0,0,100,0), +(@PATH,4,-105.9522,-226.8887,17.26674,0,0,0,100,0), +(@PATH,5,-101.0044,-224.8914,16.04452,0,0,0,100,0), +(@PATH,6,-96.82773,-225.9608,15.73896,0,0,0,100,0), +(@PATH,7,-92.59879,-227.0505,15.54452,0,0,0,100,0), +(@PATH,8,-90.07465,-229.0938,16.58224,0,0,0,100,0), +(@PATH,9,-88.24558,-231.7715,22.47455,0,0,0,100,0), +(@PATH,10,-91.0969,-232.6422,24.65563,0,0,0,100,0), +(@PATH,11,-97.20647,-234.4709,28.46118,0,0,0,100,0), +(@PATH,12,-101.5825,-234.9054,29.35008,0,0,0,100,0), + +(@PATH+10,1,-109.4618,-232.0907,25.12787,0,0,0,100,0), +(@PATH+10,2,-109.4792,-229.4328,20.98899,0,0,0,100,0), +(@PATH+10,3,-105.9522,-226.8887,17.26674,0,0,0,100,0), +(@PATH+10,4,-101.0044,-224.8914,16.04452,0,0,0,100,0), +(@PATH+10,5,-96.82773,-225.9608,15.73896,0,0,0,100,0), +(@PATH+10,6,-92.59879,-227.0505,15.54452,0,0,0,100,0), +(@PATH+10,7,-90.07465,-229.0938,16.58224,0,0,0,100,0), +(@PATH+10,8,-88.24558,-231.7715,22.47455,0,0,0,100,0), +(@PATH+10,9,-91.0969,-232.6422,24.65563,0,0,0,100,0), +(@PATH+10,10,-97.20647,-234.4709,28.46118,0,0,0,100,0), +(@PATH+10,11,-101.5825,-234.9054,29.35008,0,0,0,100,0), +(@PATH+10,12,-107.1537,-233.7247,27.1834,0,0,0,100,0), + +(@PATH+20,1,-97.20647,-234.4709,28.46118,0,0,0,100,0), +(@PATH+20,2,-101.5825,-234.9054,29.35008,0,0,0,100,0), +(@PATH+20,3,-107.1537,-233.7247,27.1834,0,0,0,100,0), +(@PATH+20,4,-109.4618,-232.0907,25.12787,0,0,0,100,0), +(@PATH+20,5,-109.4792,-229.4328,20.98899,0,0,0,100,0), +(@PATH+20,6,-105.9522,-226.8887,17.26674,0,0,0,100,0), +(@PATH+20,7,-101.0044,-224.8914,16.04452,0,0,0,100,0), +(@PATH+20,8,-96.82773,-225.9608,15.73896,0,0,0,100,0), +(@PATH+20,9,-92.59879,-227.0505,15.54452,0,0,0,100,0), +(@PATH+20,10,-90.07465,-229.0938,16.58224,0,0,0,100,0), +(@PATH+20,11,-88.24558,-231.7715,22.47455,0,0,0,100,0), +(@PATH+20,12,-91.0969,-232.6422,24.65563,0,0,0,100,0); diff --git a/data/sql/updates/db_world/2024_06_18_00.sql b/data/sql/updates/db_world/2024_06_18_00.sql new file mode 100644 index 000000000..3e07188b7 --- /dev/null +++ b/data/sql/updates/db_world/2024_06_18_00.sql @@ -0,0 +1,36 @@ +-- DB update 2024_06_17_01 -> 2024_06_18_00 +-- Archmage Xylem +DELETE FROM `creature` WHERE (`id1` = 8379); +INSERT INTO `creature` (`guid`, `id1`, `id2`, `id3`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`, `CreateObject`, `Comment`) VALUES +(35886, 8379, 0, 0, 1, 0, 0, 1, 1, 0, 3982.08, -4760.25, 304.8, 0.347593, 333, 0, 0, 2884, 5751, 2, 0, 0, 0, '', 0, 0, NULL); + +UPDATE `creature_addon` SET `path_id` = 3588600 WHERE `guid` = 35886; + +DELETE FROM `waypoint_data` WHERE `id` = 3588600; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(3588600, 1, 3982.08, -4760.25, 304.803, 5.3781, 60000, 0, 0, 100, 0), +(3588600, 2, 3975.94, -4767.85, 304.728, 100, 0, 0, 0, 100, 0), +(3588600, 3, 3972.76, -4771.82, 304.716, 100, 0, 0, 0, 100, 0), +(3588600, 4, 3970.95, -4777.04, 304.728, 100, 0, 0, 0, 100, 0), +(3588600, 5, 3970.78, -4780.04, 304.712, 100, 0, 0, 0, 100, 0), +(3588600, 6, 3971.65, -4784.84, 304.718, 100, 0, 0, 0, 100, 0), +(3588600, 7, 3976.24, -4788.04, 304.717, 100, 0, 0, 0, 100, 0), +(3588600, 8, 3977.89, -4786.99, 304.73, 100, 0, 0, 0, 100, 0), +(3588600, 9, 3977.45, -4783.41, 303.731, 100, 0, 0, 0, 100, 0), +(3588600, 10, 3979.76, -4780.78, 301.995, 100, 0, 0, 0, 100, 0), +(3588600, 11, 3983.23, -4782.2, 299.606, 100, 0, 0, 0, 100, 0), +(3588600, 12, 3982.05, -4785.25, 297.913, 100, 0, 0, 0, 100, 0), +(3588600, 13, 3974.91, -4782.9, 295.922, 100, 0, 0, 0, 100, 0), +(3588600, 14, 3969.92, -4784.16, 296.018, 100, 10000, 0, 0, 100, 0), +(3588600, 15, 3974.91, -4782.9, 295.922, 100, 0, 0, 0, 100, 0), +(3588600, 16, 3982.05, -4785.25, 297.913, 100, 0, 0, 0, 100, 0), +(3588600, 17, 3983.23, -4782.2, 299.606, 100, 0, 0, 0, 100, 0), +(3588600, 18, 3979.76, -4780.78, 301.995, 100, 0, 0, 0, 100, 0), +(3588600, 19, 3977.45, -4783.41, 303.731, 100, 0, 0, 0, 100, 0), +(3588600, 20, 3977.89, -4786.99, 304.73, 100, 0, 0, 0, 100, 0), +(3588600, 21, 3976.24, -4788.04, 304.717, 100, 0, 0, 0, 100, 0), +(3588600, 22, 3971.65, -4784.84, 304.718, 100, 0, 0, 0, 100, 0), +(3588600, 23, 3970.78, -4780.04, 304.712, 100, 0, 0, 0, 100, 0), +(3588600, 24, 3970.95, -4777.04, 304.728, 100, 0, 0, 0, 100, 0), +(3588600, 25, 3972.76, -4771.82, 304.716, 100, 0, 0, 0, 100, 0), +(3588600, 26, 3975.94, -4767.85, 304.728, 100, 0, 0, 0, 100, 0); diff --git a/data/sql/updates/db_world/2024_06_18_01.sql b/data/sql/updates/db_world/2024_06_18_01.sql new file mode 100644 index 000000000..d374e0ead --- /dev/null +++ b/data/sql/updates/db_world/2024_06_18_01.sql @@ -0,0 +1,2 @@ +-- DB update 2024_06_18_00 -> 2024_06_18_01 +UPDATE `spell_proc_event` SET `entry` = -20177 WHERE `entry` = 20182; diff --git a/data/sql/updates/db_world/2024_06_18_02.sql b/data/sql/updates/db_world/2024_06_18_02.sql new file mode 100644 index 000000000..769659e12 --- /dev/null +++ b/data/sql/updates/db_world/2024_06_18_02.sql @@ -0,0 +1,60 @@ +-- DB update 2024_06_18_01 -> 2024_06_18_02 +-- +DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 14) AND (`SourceGroup` IN (7552, 7581, 7706)); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +-- Jaina Text +(14, 7552, 9168, 0, 0, 13, 0, 0, 3, 2, 1, 0, 0, '', 'Show gossip text if Rage Winterchill is not defeated'), + +(14, 7552, 9380, 0, 0, 13, 0, 0, 3, 2, 0, 0, 0, '', 'Show gossip text if Rage Winterchill is defeated'), +(14, 7552, 9380, 0, 0, 13, 0, 1, 3, 2, 1, 0, 0, '', 'Show gossip text if Anetheron is not defeated'), + +(14, 7552, 9387, 0, 0, 13, 0, 0, 3, 2, 0, 0, 0, '', 'Show gossip text if Rage Winterchill is defeated'), +(14, 7552, 9387, 0, 0, 13, 0, 1, 3, 2, 0, 0, 0, '', 'Show gossip text if Anetheron is defeated'), + +-- Thrall Text +(14, 7581, 9224, 0, 0, 13, 0, 1, 3, 2, 1, 0, 0, '', 'Show gossip text if Anetheron is not defeated'), + +(14, 7581, 9225, 0, 0, 13, 0, 1, 3, 2, 0, 0, 0, '', 'Show gossip text if Anetheron is defeated'), +(14, 7581, 9225, 0, 0, 13, 0, 2, 3, 2, 1, 0, 0, '', 'Show gossip text if Kaz\'rogal is not defeated'), + +(14, 7581, 9396, 0, 0, 13, 0, 2, 3, 2, 0, 0, 0, '', 'Show gossip text if Kaz\'rogal is defeated'), +(14, 7581, 9396, 0, 0, 13, 0, 3, 3, 2, 1, 0, 0, '', 'Show gossip text if Azgalor is not defeated'), + +(14, 7581, 9398, 0, 0, 13, 0, 2, 3, 2, 0, 0, 0, '', 'Show gossip text if Kaz\'rogal is defeated'), +(14, 7581, 9398, 0, 0, 13, 0, 3, 3, 2, 0, 0, 0, '', 'Show gossip text if Azgalor is defeated'), + +-- Tyrande Text +(14, 7706, 9408, 0, 0, 13, 0, 1, 3, 2, 1, 0, 0, '', 'Show gossip text if Anetheron is not defeated'), +(14, 7706, 9408, 0, 0, 13, 0, 3, 3, 2, 1, 0, 0, '', 'Show gossip text if Azgalor is not defeated'), + +(14, 7706, 9409, 0, 0, 13, 0, 1, 3, 2, 0, 0, 0, '', 'Show gossip text if Anetheron is defeated'), +(14, 7706, 9409, 0, 0, 13, 0, 3, 3, 2, 1, 0, 0, '', 'Show gossip text if Azgalor is not defeated'), + +(14, 7706, 9410, 0, 0, 13, 0, 3, 3, 2, 0, 0, 0, '', 'Show gossip text if Azgalor is defeated'), + +(14, 7706, 9415, 0, 0, 13, 0, 4, 3, 2, 0, 0, 0, '', 'Show gossip text if Archimonde is defeated'); + +DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 15) AND (`SourceGroup` IN (7552, 7581, 7706)); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +-- Jaina Options +(15, 7552, 32918, 0, 0, 13, 0, 0, 3, 2, 1, 0, 0, '', 'Show gossip option if Rage Winterchill is not defeated'), + +(15, 7552, 32919, 0, 0, 13, 0, 0, 3, 2, 0, 0, 0, '', 'Show gossip option if Rage Winterchill is defeated'), +(15, 7552, 32919, 0, 0, 13, 0, 1, 3, 2, 1, 0, 0, '', 'Show gossip option if Anetheron is not defeated'), + +(15, 7552, 32920, 0, 0, 13, 0, 0, 3, 2, 0, 0, 0, '', 'Show gossip option if Rage Winterchill is defeated'), +(15, 7552, 32920, 0, 0, 13, 0, 1, 3, 2, 0, 0, 0, '', 'Show gossip option if Anetheron is defeated'), + +-- Thrall Options +(15, 7581, 35378, 0, 0, 13, 0, 1, 3, 2, 0, 0, 0, '', 'Show gossip option if Anetheron is defeated'), +(15, 7581, 35378, 0, 0, 13, 0, 2, 3, 2, 1, 0, 0, '', 'Show gossip option if Kaz\'rogal is not defeated'), + +(15, 7581, 35377, 0, 0, 13, 0, 2, 3, 2, 0, 0, 0, '', 'Show gossip option if Kaz\'rogal is defeated'), +(15, 7581, 35377, 0, 0, 13, 0, 3, 3, 2, 1, 0, 0, '', 'Show gossip option if Azgalor is not defeated'), + +(15, 7581, 35379, 0, 0, 13, 0, 2, 3, 2, 0, 0, 0, '', 'Show gossip option if Kaz\'rogal is defeated'), +(15, 7581, 35379, 0, 0, 13, 0, 3, 3, 2, 0, 0, 0, '', 'Show gossip option if Azgalor is defeated'), + +-- Tyrande Options +(15, 7706, 34158, 0, 0, 13, 0, 3, 3, 2, 0, 0, 0, '', 'Show gossip option if Azgalor is defeated'), +(15, 7706, 34158, 0, 0, 13, 0, 4, 3, 2, 1, 0, 0, '', 'Show gossip option if Archimonde is not defeated'); diff --git a/data/sql/updates/db_world/2024_06_18_03.sql b/data/sql/updates/db_world/2024_06_18_03.sql new file mode 100644 index 000000000..1741cac98 --- /dev/null +++ b/data/sql/updates/db_world/2024_06_18_03.sql @@ -0,0 +1,12 @@ +-- DB update 2024_06_18_02 -> 2024_06_18_03 +-- Force-Commander Gorax +UPDATE `creature_template_addon` SET `path_id` = 1926400 WHERE `entry` = 19264; + +DELETE FROM `creature` WHERE `guid` = 68832 AND `id1` = 19264; +INSERT INTO `creature` (`guid`, `id1`, `id2`, `id3`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`, `CreateObject`, `Comment`) VALUES +(68832, 19264, 0, 0, 530, 0, 0, 1, 1, 1, -222.317, 3098.66, -60.229, 3.73311, 300, 0, 0, 22108, 0, 0, 0, 0, 0, '', 0, 0, NULL); + +DELETE FROM `waypoint_data` WHERE `id`=1926400; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(1926400, 1, -223.712, 3100.36, -60.479, 100, 0, 0, 0, 100, 0), +(1926400, 2, -245.299, 3083.23, -64.9508, 100, 0, 0, 0, 100, 0); diff --git a/data/sql/updates/db_world/2024_06_18_04.sql b/data/sql/updates/db_world/2024_06_18_04.sql new file mode 100644 index 000000000..88b0bbf6a --- /dev/null +++ b/data/sql/updates/db_world/2024_06_18_04.sql @@ -0,0 +1,3 @@ +-- DB update 2024_06_18_03 -> 2024_06_18_04 +-- Mote of Shadow +UPDATE `creature_loot_template` SET `Chance` = 25 WHERE `Item` = 22577 and `Entry` IN (18869,18870); diff --git a/data/sql/updates/db_world/2024_06_18_05.sql b/data/sql/updates/db_world/2024_06_18_05.sql new file mode 100644 index 000000000..bb41a49b6 --- /dev/null +++ b/data/sql/updates/db_world/2024_06_18_05.sql @@ -0,0 +1,5 @@ +-- DB update 2024_06_18_04 -> 2024_06_18_05 +DELETE FROM `spell_script_names` WHERE `spell_id` IN (42463, 53739); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES -- Same script name, don't wanna duplicate the spell script +(42463, 'spell_pal_seal_of_vengeance'), +(53739, 'spell_pal_seal_of_vengeance'); diff --git a/data/sql/updates/db_world/2024_06_18_06.sql b/data/sql/updates/db_world/2024_06_18_06.sql new file mode 100644 index 000000000..24c5d67f1 --- /dev/null +++ b/data/sql/updates/db_world/2024_06_18_06.sql @@ -0,0 +1,10 @@ +-- DB update 2024_06_18_05 -> 2024_06_18_06 +-- +UPDATE `creature_text` SET `BroadcastTextId` = 21123 WHERE `BroadcastTextId` = 21223 AND `CreatureID` = 23311; + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 23311) AND (`source_type` = 0) AND (`id` IN (0, 9, 10, 11)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(23311, 0, 0, 1, 8, 0, 100, 513, 40742, 0, 0, 0, 0, 0, 33, 23311, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 'Disobedient Dragonmaw Peon - On Spell Hit (Booterang) - Give Kill Credit'), +(23311, 0, 9, 10, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 41, 10000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Disobedient Dragonmaw Peon - Linked with Previous Event - Despawn After 10 seconds'), +(23311, 0, 10, 0, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 17, 233, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Disobedient Dragonmaw Peon - Linked with Previous Event - Set Emote State'), +(23311, 0, 11, 0, 25, 0, 100, 512, 0, 0, 0, 0, 0, 0, 2, 62, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Disobedient Dragonmaw Peon - On Reset - Reset Faction'); diff --git a/src/server/database/Database/Implementation/WorldDatabase.cpp b/src/server/database/Database/Implementation/WorldDatabase.cpp index e6fa97751..c6e1c5d05 100644 --- a/src/server/database/Database/Implementation/WorldDatabase.cpp +++ b/src/server/database/Database/Implementation/WorldDatabase.cpp @@ -77,7 +77,7 @@ void WorldDatabaseConnection::DoPrepareStatements() PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_ID_BY_GUID, "SELECT id FROM waypoint_scripts WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_DEL_CREATURE, "DELETE FROM creature WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(WORLD_SEL_COMMANDS, "SELECT name, security, help FROM command", CONNECTION_SYNCH); - PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction, npcflag, speed_walk, speed_run, speed_swim, speed_flight, detection_range, scale, `rank`, dmgschool, DamageModifier, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_spell, trainer_class, trainer_race, type, type_flags, lootid, pickpocketloot, skinloot, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, ctm.Chase, ctm.Random, ctm.InteractionPauseTimer, HoverHeight, HealthModifier, ManaModifier, ArmorModifier, ExperienceModifier, RacialLeader, movementId, RegenHealth, mechanic_immune_mask, spell_school_immune_mask, flags_extra, ScriptName FROM creature_template ct LEFT JOIN creature_template_movement ctm ON ct.entry = ctm.CreatureId WHERE entry = ?", CONNECTION_SYNCH); + PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction, npcflag, speed_walk, speed_run, speed_swim, speed_flight, detection_range, scale, `rank`, dmgschool, DamageModifier, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_spell, trainer_class, trainer_race, type, type_flags, lootid, pickpocketloot, skinloot, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, ctm.Chase, ctm.Random, ctm.InteractionPauseTimer, HoverHeight, HealthModifier, ManaModifier, ArmorModifier, ExperienceModifier, RacialLeader, movementId, RegenHealth, mechanic_immune_mask, spell_school_immune_mask, flags_extra, ScriptName FROM creature_template ct LEFT JOIN creature_template_movement ctm ON ct.entry = ctm.CreatureId WHERE entry = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_BY_ID, "SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_ITEM_TEMPLATE_BY_NAME, "SELECT entry FROM item_template WHERE name = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_CREATURE_BY_ID, "SELECT guid FROM creature WHERE id1 = ? OR id2 = ? OR id3 = ?", CONNECTION_SYNCH); diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp index 17d48bf54..1f97131cb 100644 --- a/src/server/game/AI/CreatureAI.cpp +++ b/src/server/game/AI/CreatureAI.cpp @@ -223,14 +223,14 @@ void CreatureAI::EnterEvadeMode(EvadeReason why) me->GetVehicleKit()->Reset(true); } + sScriptMgr->OnUnitEnterEvadeMode(me, why); + // despawn bosses at reset - only verified tbc/woltk bosses with this reset type CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(me->GetEntry()); if (cInfo && cInfo->HasFlagsExtra(CREATURE_FLAG_EXTRA_HARD_RESET)) { me->DespawnOnEvade(); } - - sScriptMgr->OnUnitEnterEvadeMode(me, why); } /*void CreatureAI::AttackedBy(Unit* attacker) diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp index dbfd88504..9dbd754ff 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp @@ -650,6 +650,16 @@ void BossAI::_JustEngagedWith() } } +void BossAI::_EnterEvadeMode(EvadeReason why) +{ + CreatureAI::EnterEvadeMode(why); + if (instance) + { + instance->SetBossState(_bossId, NOT_STARTED); + instance->SaveToDB(); + } +} + void BossAI::TeleportCheaters() { float x, y, z; diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h index 55a838d24..be04450d0 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h @@ -488,6 +488,7 @@ public: void Reset() override { _Reset(); } void JustEngagedWith(Unit* /*who*/) override { _JustEngagedWith(); } + void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER) override { _EnterEvadeMode(why); } void JustDied(Unit* /*killer*/) override { _JustDied(); } void JustReachedHome() override { _JustReachedHome(); } @@ -496,6 +497,7 @@ protected: void _JustEngagedWith(); void _JustDied(); void _JustReachedHome() { me->setActive(false); } + void _EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER); [[nodiscard]] bool _ProccessHealthCheckEvent(uint8 healthPct, uint32 damage, std::function exec) const; void TeleportCheaters(); diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index a91489dae..cabedbe4a 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -424,10 +424,10 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u { if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(e.action.morphOrMount.creature)) { - uint32 displayId = ObjectMgr::ChooseDisplayId(ci); - target->ToCreature()->SetDisplayId(displayId); + CreatureModel const* model = ObjectMgr::ChooseDisplayId(ci); + target->ToCreature()->SetDisplayId(model->CreatureDisplayID, model->DisplayScale); LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry {}, GuidLow {} set displayid to {}", - target->GetEntry(), target->GetGUID().ToString(), displayId); + target->GetEntry(), target->GetGUID().ToString(), model->CreatureDisplayID); } } //if no param1, then use value from param2 (modelId) @@ -1316,7 +1316,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (e.action.morphOrMount.creature > 0) { if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(e.action.morphOrMount.creature)) - target->ToUnit()->Mount(ObjectMgr::ChooseDisplayId(cInfo)); + target->ToUnit()->Mount(ObjectMgr::ChooseDisplayId(cInfo)->CreatureDisplayID); } else target->ToUnit()->Mount(e.action.morphOrMount.model); diff --git a/src/server/game/Chat/ChatCommands/ChatCommand.cpp b/src/server/game/Chat/ChatCommands/ChatCommand.cpp index ae62f4214..9a68a213c 100644 --- a/src/server/game/Chat/ChatCommands/ChatCommand.cpp +++ b/src/server/game/Chat/ChatCommands/ChatCommand.cpp @@ -322,8 +322,12 @@ namespace Acore::Impl::ChatCommands oldTail = newTail; } + if (!sScriptMgr->OnTryExecuteCommand(handler, cmdStr)) + return true; + + /* if we matched a command at some point, invoke it */ if (cmd) - { /* if we matched a command at some point, invoke it */ + { handler.SetSentErrorMessage(false); if (cmd->IsInvokerVisible(handler) && cmd->_invoker(&handler, oldTail)) { /* invocation succeeded, log this */ @@ -332,11 +336,6 @@ namespace Acore::Impl::ChatCommands } else if (!handler.HasSentErrorMessage()) /* invocation failed, we should show usage */ { - if (!sScriptMgr->CanExecuteCommand(handler, cmdStr)) - { - return true; - } - cmd->SendCommandHelp(handler); handler.SetSentErrorMessage(true); } @@ -344,11 +343,6 @@ namespace Acore::Impl::ChatCommands return true; } - if (!sScriptMgr->CanExecuteCommand(handler, cmdStr)) - { - return true; - } - return false; } diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 74531c638..043fbdd77 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -116,51 +116,104 @@ VendorItem const* VendorItemData::FindItemCostPair(uint32 item_id, uint32 extend return nullptr; } -uint32 CreatureTemplate::GetRandomValidModelId() const +CreatureModel const CreatureModel::DefaultInvisibleModel(11686, 1.0f, 1.0f); +CreatureModel const CreatureModel::DefaultVisibleModel(17519, 1.0f, 1.0f); + +CreatureModel const* CreatureTemplate::GetModelByIdx(uint32 idx) const { - uint8 c = 0; - uint32 modelIDs[4]; - - if (Modelid1) modelIDs[c++] = Modelid1; - if (Modelid2) modelIDs[c++] = Modelid2; - if (Modelid3) modelIDs[c++] = Modelid3; - if (Modelid4) modelIDs[c++] = Modelid4; - - return ((c > 0) ? modelIDs[urand(0, c - 1)] : 0); + return idx < Models.size() ? &Models[idx] : nullptr; } -uint32 CreatureTemplate::GetFirstValidModelId() const +CreatureModel const* CreatureTemplate::GetRandomValidModel() const { - if (Modelid1) return Modelid1; - if (Modelid2) return Modelid2; - if (Modelid3) return Modelid3; - if (Modelid4) return Modelid4; - return 0; + if (!Models.size()) + return nullptr; + + // If only one element, ignore the Probability (even if 0) + if (Models.size() == 1) + return &Models[0]; + + auto selectedItr = Acore::Containers::SelectRandomWeightedContainerElement(Models, [](CreatureModel const& model) + { + return model.Probability; + }); + + return &(*selectedItr); +} + +CreatureModel const* CreatureTemplate::GetFirstValidModel() const +{ + for (CreatureModel const& model : Models) + if (model.CreatureDisplayID) + return &model; + + return nullptr; +} + +CreatureModel const* CreatureTemplate::GetModelWithDisplayId(uint32 displayId) const +{ + for (CreatureModel const& model : Models) + if (displayId == model.CreatureDisplayID) + return &model; + + return nullptr; +} + +CreatureModel const* CreatureTemplate::GetFirstInvisibleModel() const +{ + for (CreatureModel const& model : Models) + if (CreatureModelInfo const* modelInfo = sObjectMgr->GetCreatureModelInfo(model.CreatureDisplayID)) + if (modelInfo && modelInfo->is_trigger) + return &model; + + return &CreatureModel::DefaultInvisibleModel; +} + +CreatureModel const* CreatureTemplate::GetFirstVisibleModel() const +{ + for (CreatureModel const& model : Models) + if (CreatureModelInfo const* modelInfo = sObjectMgr->GetCreatureModelInfo(model.CreatureDisplayID)) + if (modelInfo && !modelInfo->is_trigger) + return &model; + + return &CreatureModel::DefaultVisibleModel; } void CreatureTemplate::InitializeQueryData() { queryData.Initialize(SMSG_CREATURE_QUERY_RESPONSE, 1); - queryData << uint32(Entry); // creature entry + queryData << uint32(Entry); // creature entry queryData << Name; - queryData << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4, always empty + queryData << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4, always empty queryData << SubName; - queryData << IconName; // "Directions" for guard, string for Icons 2.3.0 - queryData << uint32(type_flags); // flags - queryData << uint32(type); // CreatureType.dbc - queryData << uint32(family); // CreatureFamily.dbc - queryData << uint32(rank); // Creature Rank (elite, boss, etc) - queryData << uint32(KillCredit[0]); // new in 3.1, kill credit - queryData << uint32(KillCredit[1]); // new in 3.1, kill credit - queryData << uint32(Modelid1); // Modelid1 - queryData << uint32(Modelid2); // Modelid2 - queryData << uint32(Modelid3); // Modelid3 - queryData << uint32(Modelid4); // Modelid4 - queryData << float(ModHealth); // dmg/hp modifier - queryData << float(ModMana); // dmg/mana modifier + queryData << IconName; // "Directions" for guard, string for Icons 2.3.0 + queryData << uint32(type_flags); // flags + queryData << uint32(type); // CreatureType.dbc + queryData << uint32(family); // CreatureFamily.dbc + queryData << uint32(rank); // Creature Rank (elite, boss, etc) + queryData << uint32(KillCredit[0]); // new in 3.1, kill credit + queryData << uint32(KillCredit[1]); // new in 3.1, kill credit + if (GetModelByIdx(0)) + queryData << uint32(GetModelByIdx(0)->CreatureDisplayID); // Modelid1 + else + queryData << uint32(0); // Modelid1 + if (GetModelByIdx(1)) + queryData << uint32(GetModelByIdx(1)->CreatureDisplayID); // Modelid2 + else + queryData << uint32(0); // Modelid2 + if (GetModelByIdx(2)) + queryData << uint32(GetModelByIdx(2)->CreatureDisplayID); // Modelid3 + else + queryData << uint32(0); // Modelid3 + if (GetModelByIdx(3)) + queryData << uint32(GetModelByIdx(3)->CreatureDisplayID); // Modelid4 + else + queryData << uint32(0); // Modelid4 + queryData << float(ModHealth); // dmg/hp modifier + queryData << float(ModMana); // dmg/mana modifier queryData << uint8(RacialLeader); - queryData << uint32(movementId); // CreatureMovementInfo.dbc + queryData << uint32(movementId); // CreatureMovementInfo.dbc } bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) @@ -423,21 +476,22 @@ bool Creature::InitEntry(uint32 Entry, const CreatureData* data) SetByteValue(UNIT_FIELD_BYTES_0, 1, uint8(cinfo->unit_class)); // Cancel load if no model defined - if (!(cinfo->GetFirstValidModelId())) + if (!(cinfo->GetFirstValidModel())) { - LOG_ERROR("sql.sql", "Creature (Entry: {}) has no model defined in table `creature_template`, can't load. ", Entry); + LOG_ERROR("sql.sql", "Creature (Entry: {}) has no model defined in table `creature_template_model`, can't load. ", Entry); return false; } - uint32 displayID = ObjectMgr::ChooseDisplayId(GetCreatureTemplate(), data); - if (!sObjectMgr->GetCreatureModelRandomGender(&displayID)) // Cancel load if no model defined + CreatureModel model = *ObjectMgr::ChooseDisplayId(cinfo, data); + CreatureModelInfo const* mInfo = sObjectMgr->GetCreatureModelRandomGender(&model, cinfo); + if (!mInfo) // Cancel load if no model defined { - LOG_ERROR("sql.sql", "Creature (Entry: {}) has no model defined in table `creature_template`, can't load. ", Entry); + LOG_ERROR("sql.sql", "Creature (Entry: {}) has no model {} defined in table `creature_template_model`, can't load. ", Entry, model.CreatureDisplayID); return false; } - SetDisplayId(displayID); - SetNativeDisplayId(displayID); + SetDisplayId(model.CreatureDisplayID, model.DisplayScale); + SetNativeDisplayId(model.CreatureDisplayID); // Load creature equipment if (!data) @@ -1121,11 +1175,12 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, u break; } - uint32 displayID = GetNativeDisplayId(); - if (sObjectMgr->GetCreatureModelRandomGender(&displayID) && !IsTotem()) // Cancel load if no model defined or if totem + CreatureModel display(GetNativeDisplayId(), GetNativeObjectScale(), 1.0f); + CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&display, cinfo); + if (minfo && !IsTotem()) // Cancel load if no model defined or if totem { - SetDisplayId(displayID); - SetNativeDisplayId(displayID); + SetDisplayId(display.CreatureDisplayID, display.DisplayScale); + SetNativeDisplayId(display.CreatureDisplayID); } LoadCreaturesAddon(); @@ -1361,9 +1416,9 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask) CreatureTemplate const* cinfo = GetCreatureTemplate(); if (cinfo) { - if (displayId == cinfo->Modelid1 || displayId == cinfo->Modelid2 || - displayId == cinfo->Modelid3 || displayId == cinfo->Modelid4) - displayId = 0; + for (CreatureModel model : cinfo->Models) + if (displayId && displayId == model.CreatureDisplayID) + displayId = 0; if (npcflag == cinfo->npcflag) npcflag = 0; @@ -2032,11 +2087,12 @@ void Creature::Respawn(bool force) // Do not override transform auras if (GetAuraEffectsByType(SPELL_AURA_TRANSFORM).empty()) { - uint32 displayID = GetNativeDisplayId(); - if (sObjectMgr->GetCreatureModelRandomGender(&displayID)) // Cancel load if no model defined + CreatureModel display(GetNativeDisplayId(), GetNativeObjectScale(), 1.0f); + CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&display, GetCreatureTemplate()); + if (minfo) // Cancel load if no model defined { - SetDisplayId(displayID); - SetNativeDisplayId(displayID); + SetDisplayId(display.CreatureDisplayID, display.DisplayScale); + SetNativeDisplayId(display.CreatureDisplayID); } } @@ -3415,9 +3471,9 @@ void Creature::SetObjectScale(float scale) SetFloatValue(UNIT_FIELD_COMBATREACH, combatReach * scale); } -void Creature::SetDisplayId(uint32 modelId) +void Creature::SetDisplayId(uint32 modelId, float displayScale /*= 1.f*/) { - Unit::SetDisplayId(modelId); + Unit::SetDisplayId(modelId, displayScale); float combatReach = DEFAULT_WORLD_OBJECT_SIZE; @@ -3431,9 +3487,17 @@ void Creature::SetDisplayId(uint32 modelId) if (IsPet()) combatReach = DEFAULT_COMBAT_REACH; + SetObjectScale(displayScale); + SetFloatValue(UNIT_FIELD_COMBATREACH, combatReach * GetObjectScale()); } +void Creature::SetDisplayFromModel(uint32 modelIdx) +{ + if (CreatureModel const* model = GetCreatureTemplate()->GetModelByIdx(modelIdx)) + SetDisplayId(model->CreatureDisplayID, model->DisplayScale); +} + void Creature::SetTarget(ObjectGuid guid) { if (!_focusSpell) diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index c4e067a56..a29ae43de 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -53,7 +53,8 @@ public: float GetNativeObjectScale() const override; void SetObjectScale(float scale) override; - void SetDisplayId(uint32 modelId) override; + void SetDisplayId(uint32 displayId, float displayScale = 1.f) override; + void SetDisplayFromModel(uint32 modelIdx); void DisappearAndDie(); diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h index 9fdb31085..9dbe41cc3 100644 --- a/src/server/game/Entities/Creature/CreatureData.h +++ b/src/server/game/Entities/Creature/CreatureData.h @@ -171,16 +171,29 @@ struct CreatureMovementData std::string ToString() const; }; +struct CreatureModel +{ + static CreatureModel const DefaultInvisibleModel; + static CreatureModel const DefaultVisibleModel; + + CreatureModel() : + CreatureDisplayID(0), DisplayScale(0.0f), Probability(0.0f) { } + + CreatureModel(uint32 creatureDisplayID, float displayScale, float probability) : + CreatureDisplayID(creatureDisplayID), DisplayScale(displayScale), Probability(probability) { } + + uint32 CreatureDisplayID; + float DisplayScale; + float Probability; +}; + // from `creature_template` table struct CreatureTemplate { uint32 Entry; uint32 DifficultyEntry[MAX_DIFFICULTY - 1]; uint32 KillCredit[MAX_KILL_CREDIT]; - uint32 Modelid1; - uint32 Modelid2; - uint32 Modelid3; - uint32 Modelid4; + std::vector Models; std::string Name; std::string SubName; std::string IconName; @@ -239,8 +252,12 @@ struct CreatureTemplate uint32 flags_extra; uint32 ScriptID; WorldPacket queryData; // pussywizard - [[nodiscard]] uint32 GetRandomValidModelId() const; - [[nodiscard]] uint32 GetFirstValidModelId() const; + CreatureModel const* GetModelByIdx(uint32 idx) const; + CreatureModel const* GetRandomValidModel() const; + CreatureModel const* GetFirstValidModel() const; + CreatureModel const* GetModelWithDisplayId(uint32 displayId) const; + CreatureModel const* GetFirstInvisibleModel() const; + CreatureModel const* GetFirstVisibleModel() const; // helpers [[nodiscard]] SkillType GetRequiredLootSkill() const @@ -390,6 +407,7 @@ struct CreatureModelInfo float combat_reach; uint8 gender; uint32 modelid_other_gender; + float is_trigger; }; // Benchmarked: Faster than std::map (insert/find) diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp index 1f8a350f3..012e5599d 100644 --- a/src/server/game/Entities/Creature/GossipDef.cpp +++ b/src/server/game/Entities/Creature/GossipDef.cpp @@ -451,7 +451,6 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGU uint32 moneyRew = 0; Player* player = _session->GetPlayer(); - uint8 playerLevel = player ? player->GetLevel() : 0; if (player && (player->getLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player))) { moneyRew = quest->GetRewMoneyMaxLevel(); @@ -461,7 +460,7 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGU uint32 questXp; if (player && !sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player)) { - questXp = uint32(quest->XPValue(playerLevel) * player->GetQuestRate()); + questXp = player->CalculateQuestRewardXP(quest); } else { @@ -704,7 +703,6 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, ObjectGuid npcGUI uint32 moneyRew = 0; Player* player = _session->GetPlayer(); - uint8 playerLevel = player ? player->GetLevel() : 0; if (player && (player->GetLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player))) { moneyRew = quest->GetRewMoneyMaxLevel(); @@ -714,7 +712,7 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, ObjectGuid npcGUI uint32 questXp; if (player && !sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player)) { - questXp = uint32(quest->XPValue(playerLevel) * player->GetQuestRate()); + questXp = player->CalculateQuestRewardXP(quest); } else { diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 416bb2d0b..a998afa57 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -256,6 +256,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c if (current && owner->IsPetNeedBeTemporaryUnsummoned()) { + owner->SetLastPetSpell(petInfo->CreatedBySpellId); owner->SetTemporaryUnsummonedPetNumber(petInfo->PetNumber); return false; } @@ -2417,9 +2418,9 @@ void Pet::SynchronizeLevelWithOwner() } } -void Pet::SetDisplayId(uint32 modelId) +void Pet::SetDisplayId(uint32 modelId, float displayScale /*= 1.f*/) { - Guardian::SetDisplayId(modelId); + Guardian::SetDisplayId(modelId, displayScale); if (!isControlled()) return; diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h index d32f04fc6..323f489ae 100644 --- a/src/server/game/Entities/Pet/Pet.h +++ b/src/server/game/Entities/Pet/Pet.h @@ -46,7 +46,7 @@ public: void RemoveFromWorld() override; float GetNativeObjectScale() const override; - void SetDisplayId(uint32 modelId) override; + void SetDisplayId(uint32 modelId, float displayScale = 1.f) override; PetType getPetType() const { return m_petType; } void setPetType(PetType type) { m_petType = type; } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index b8e053924..12863bb89 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1451,6 +1451,7 @@ public: bool SatisfyQuestSeasonal(Quest const* qInfo, bool msg) const; bool GiveQuestSourceItem(Quest const* quest); bool TakeQuestSourceItem(uint32 questId, bool msg); + uint32 CalculateQuestRewardXP(Quest const* quest); [[nodiscard]] bool GetQuestRewardStatus(uint32 quest_id) const; [[nodiscard]] QuestStatus GetQuestStatus(uint32 quest_id) const; void SetQuestStatus(uint32 questId, QuestStatus status, bool update = true); diff --git a/src/server/game/Entities/Player/PlayerQuest.cpp b/src/server/game/Entities/Player/PlayerQuest.cpp index c9867c90c..1ad676ce7 100644 --- a/src/server/game/Entities/Player/PlayerQuest.cpp +++ b/src/server/game/Entities/Player/PlayerQuest.cpp @@ -742,12 +742,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, bool rewarded = IsQuestRewarded(quest_id) && !quest->IsDFQuest(); // Not give XP in case already completed once repeatable quest - uint32 XP = rewarded ? 0 : uint32(quest->XPValue(GetLevel()) * GetQuestRate(quest->IsDFQuest())); - - // handle SPELL_AURA_MOD_XP_QUEST_PCT auras - Unit::AuraEffectList const& ModXPPctAuras = GetAuraEffectsByType(SPELL_AURA_MOD_XP_QUEST_PCT); - for (Unit::AuraEffectList::const_iterator i = ModXPPctAuras.begin(); i != ModXPPctAuras.end(); ++i) - AddPct(XP, (*i)->GetAmount()); + uint32 XP = rewarded ? 0 : CalculateQuestRewardXP(quest); sScriptMgr->OnQuestComputeXP(this, quest, XP); int32 moneyRew = 0; @@ -1402,6 +1397,19 @@ bool Player::TakeQuestSourceItem(uint32 questId, bool msg) return true; } +uint32 Player::CalculateQuestRewardXP(Quest const* quest) +{ + // apply world quest rate + uint32 xp = uint32(quest->XPValue(GetLevel()) * GetQuestRate(quest->IsDFQuest())); + + // handle SPELL_AURA_MOD_XP_QUEST_PCT auras + Unit::AuraEffectList const& ModXPPctAuras = GetAuraEffectsByType(SPELL_AURA_MOD_XP_QUEST_PCT); + for (Unit::AuraEffectList::const_iterator i = ModXPPctAuras.begin(); i != ModXPPctAuras.end(); ++i) + AddPct(xp, (*i)->GetAmount()); + + return xp; +} + bool Player::GetQuestRewardStatus(uint32 quest_id) const { Quest const* qInfo = sObjectMgr->GetQuestTemplate(quest_id); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index b7c3b88d5..f4504bda5 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -7833,19 +7833,17 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere triggered_spell_id = 31803; - // On target with 5 stacks of Holy Vengeance direct damage is done if (Aura* aur = victim->GetAura(triggered_spell_id, GetGUID())) { if (aur->GetStackAmount() == 5) { if (stacker) aur->RefreshDuration(); - - CastSpell(victim, 42463, true, castItem, triggeredByAura); - return true; } } + CastSpell(victim, 42463, true, castItem, triggeredByAura); // Seal of Vengeance + if (!stacker) return false; break; @@ -7866,19 +7864,17 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere triggered_spell_id = 53742; - // On target with 5 stacks of Blood Corruption direct damage is done if (Aura* aur = victim->GetAura(triggered_spell_id, GetGUID())) { if (aur->GetStackAmount() == 5) { if (stacker) aur->RefreshDuration(); - - CastSpell(victim, 53739, true, castItem, triggeredByAura); - return true; } } + CastSpell(victim, 53739, true, castItem, triggeredByAura); // Seal of Corruption + if (!stacker) return false; break; @@ -17051,13 +17047,16 @@ void Unit::RecalculateObjectScale() SetObjectScale(std::max(scale, scaleMin)); } -void Unit::SetDisplayId(uint32 modelId) +void Unit::SetDisplayId(uint32 modelId, float displayScale /*=1.f*/) { SetUInt32Value(UNIT_FIELD_DISPLAYID, modelId); + // Set Gender by modelId if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(modelId)) SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender); + SetObjectScale(displayScale); + sScriptMgr->OnDisplayIdChange(this, modelId); } @@ -21264,17 +21263,11 @@ void Unit::PatchValuesUpdate(ByteBuffer& valuesUpdateBuf, BuildValuesCachePosPoi { if (target->IsGameMaster() && target->GetSession()->IsGMAccount()) { - if (cinfo->Modelid1) - displayId = cinfo->Modelid1; // Modelid1 is a visible model for gms - else - displayId = 17519; // world visible trigger's model + displayId = cinfo->GetFirstVisibleModel()->CreatureDisplayID; } else { - if (cinfo->Modelid2) - displayId = cinfo->Modelid2; // Modelid2 is an invisible model for players - else - displayId = 11686; // world invisible trigger's model + displayId = cinfo->GetFirstInvisibleModel()->CreatureDisplayID; } } } diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index fd32ac6ea..4ac796c90 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -2263,10 +2263,10 @@ public: virtual float GetNativeObjectScale() const { return 1.0f; } virtual void RecalculateObjectScale(); [[nodiscard]] uint32 GetDisplayId() const { return GetUInt32Value(UNIT_FIELD_DISPLAYID); } - virtual void SetDisplayId(uint32 modelId); + virtual void SetDisplayId(uint32 modelId, float displayScale = 1.f); [[nodiscard]] uint32 GetNativeDisplayId() const { return GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID); } void RestoreDisplayId(); - void SetNativeDisplayId(uint32 modelId) { SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID, modelId); } + void SetNativeDisplayId(uint32 displayId) { SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID, displayId); } void setTransForm(uint32 spellid) { m_transform = spellid;} [[nodiscard]] uint32 getTransForm() const { return m_transform;} diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 3eb3bdf2d..ea2332b58 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -36,6 +36,7 @@ #include "LFGMgr.h" #include "Log.h" #include "MapMgr.h" +#include #include "Pet.h" #include "PoolMgr.h" #include "ReputationMgr.h" @@ -576,20 +577,20 @@ void ObjectMgr::LoadCreatureTemplates() { uint32 oldMSTime = getMSTime(); -// 0 1 2 3 4 5 6 7 8 - QueryResult result = WorldDatabase.Query("SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, " -// 9 10 11 12 13 14 15 16 17 18 19 20 21 22 - "modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction, npcflag, speed_walk, speed_run, speed_swim, speed_flight, " -// 23 24 25 26 27 28 29 30 31 32 33 34 - "detection_range, scale, `rank`, dmgschool, DamageModifier, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, " -// 35 36 37 38 39 40 41 - "dynamicflags, family, trainer_type, trainer_spell, trainer_class, trainer_race, type, " -// 42 43 44 45 46 47 48 49 50 51 - "type_flags, lootid, pickpocketloot, skinloot, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, " -// 52 53 54 55 56 57 58 59 60 61 62 63 - "ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, ctm.Chase, ctm.Random, ctm.InteractionPauseTimer, HoverHeight, HealthModifier, ManaModifier, ArmorModifier, ExperienceModifier, " -// 64 65 66 67 68 69 70 - "RacialLeader, movementId, RegenHealth, mechanic_immune_mask, spell_school_immune_mask, flags_extra, ScriptName " +// 0 1 2 3 4 5 6 7 8 + QueryResult result = WorldDatabase.Query("SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, name, subname, IconName, " +// 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + "gossip_menu_id, minlevel, maxlevel, exp, faction, npcflag, speed_walk, speed_run, speed_swim, speed_flight, detection_range, scale, `rank`, dmgschool, " +// 23 24 25 26 27 28 29 30 31 32 33 34 + "DamageModifier, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_spell, " +// 35 36 37 38 39 40 41 + "trainer_class, trainer_race, type, type_flags, lootid, pickpocketloot, skinloot, " +// 42 43 44 45 46 47 48 49 50 51 + "PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, " +// 52 53 54 55 56 57 58 59 60 61 62 63 + "ctm.Chase, ctm.Random, ctm.InteractionPauseTimer, HoverHeight, HealthModifier, ManaModifier, ArmorModifier, ExperienceModifier, RacialLeader, movementId, RegenHealth, mechanic_immune_mask, " +// 64 65 66 + "spell_school_immune_mask, flags_extra, ScriptName " "FROM creature_template ct LEFT JOIN creature_template_movement ctm ON ct.entry = ctm.CreatureId ORDER BY entry DESC;"); if (!result) @@ -609,6 +610,9 @@ void ObjectMgr::LoadCreatureTemplates() ++count; } while (result->NextRow()); + // We load the creature models after loading but before checking + LoadCreatureTemplateModels(); + sScriptMgr->OnAfterDatabaseLoadCreatureTemplates(_creatureTemplateStoreFast); LoadCreatureTemplateResistances(); @@ -658,47 +662,42 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields, bool triggerHook) { creatureTemplate.KillCredit[i] = fields[4 + i].Get(); } - - creatureTemplate.Modelid1 = fields[6].Get(); - creatureTemplate.Modelid2 = fields[7].Get(); - creatureTemplate.Modelid3 = fields[8].Get(); - creatureTemplate.Modelid4 = fields[9].Get(); - creatureTemplate.Name = fields[10].Get(); - creatureTemplate.SubName = fields[11].Get(); - creatureTemplate.IconName = fields[12].Get(); - creatureTemplate.GossipMenuId = fields[13].Get(); - creatureTemplate.minlevel = fields[14].Get(); - creatureTemplate.maxlevel = fields[15].Get(); - creatureTemplate.expansion = uint32(fields[16].Get()); - creatureTemplate.faction = uint32(fields[17].Get()); - creatureTemplate.npcflag = fields[18].Get(); - creatureTemplate.speed_walk = fields[19].Get(); - creatureTemplate.speed_run = fields[20].Get(); - creatureTemplate.speed_swim = fields[21].Get(); - creatureTemplate.speed_flight = fields[22].Get(); - creatureTemplate.detection_range = fields[23].Get(); - creatureTemplate.scale = fields[24].Get(); - creatureTemplate.rank = uint32(fields[25].Get()); - creatureTemplate.dmgschool = uint32(fields[26].Get()); - creatureTemplate.DamageModifier = fields[27].Get(); - creatureTemplate.BaseAttackTime = fields[28].Get(); - creatureTemplate.RangeAttackTime = fields[29].Get(); - creatureTemplate.BaseVariance = fields[30].Get(); - creatureTemplate.RangeVariance = fields[31].Get(); - creatureTemplate.unit_class = uint32(fields[32].Get()); - creatureTemplate.unit_flags = fields[33].Get(); - creatureTemplate.unit_flags2 = fields[34].Get(); - creatureTemplate.dynamicflags = fields[35].Get(); - creatureTemplate.family = uint32(fields[36].Get()); - creatureTemplate.trainer_type = uint32(fields[37].Get()); - creatureTemplate.trainer_spell = fields[38].Get(); - creatureTemplate.trainer_class = uint32(fields[39].Get()); - creatureTemplate.trainer_race = uint32(fields[40].Get()); - creatureTemplate.type = uint32(fields[41].Get()); - creatureTemplate.type_flags = fields[42].Get(); - creatureTemplate.lootid = fields[43].Get(); - creatureTemplate.pickpocketLootId = fields[44].Get(); - creatureTemplate.SkinLootId = fields[45].Get(); + creatureTemplate.Name = fields[6].Get(); + creatureTemplate.SubName = fields[7].Get(); + creatureTemplate.IconName = fields[8].Get(); + creatureTemplate.GossipMenuId = fields[9].Get(); + creatureTemplate.minlevel = fields[10].Get(); + creatureTemplate.maxlevel = fields[11].Get(); + creatureTemplate.expansion = uint32(fields[12].Get()); + creatureTemplate.faction = uint32(fields[13].Get()); + creatureTemplate.npcflag = fields[14].Get(); + creatureTemplate.speed_walk = fields[15].Get(); + creatureTemplate.speed_run = fields[16].Get(); + creatureTemplate.speed_swim = fields[17].Get(); + creatureTemplate.speed_flight = fields[18].Get(); + creatureTemplate.detection_range = fields[19].Get(); + creatureTemplate.scale = fields[20].Get(); + creatureTemplate.rank = uint32(fields[21].Get()); + creatureTemplate.dmgschool = uint32(fields[22].Get()); + creatureTemplate.DamageModifier = fields[23].Get(); + creatureTemplate.BaseAttackTime = fields[24].Get(); + creatureTemplate.RangeAttackTime = fields[25].Get(); + creatureTemplate.BaseVariance = fields[26].Get(); + creatureTemplate.RangeVariance = fields[27].Get(); + creatureTemplate.unit_class = uint32(fields[28].Get()); + creatureTemplate.unit_flags = fields[29].Get(); + creatureTemplate.unit_flags2 = fields[30].Get(); + creatureTemplate.dynamicflags = fields[31].Get(); + creatureTemplate.family = uint32(fields[32].Get()); + creatureTemplate.trainer_type = uint32(fields[33].Get()); + creatureTemplate.trainer_spell = fields[34].Get(); + creatureTemplate.trainer_class = uint32(fields[35].Get()); + creatureTemplate.trainer_race = uint32(fields[36].Get()); + creatureTemplate.type = uint32(fields[37].Get()); + creatureTemplate.type_flags = fields[38].Get(); + creatureTemplate.lootid = fields[39].Get(); + creatureTemplate.pickpocketLootId = fields[40].Get(); + creatureTemplate.SkinLootId = fields[41].Get(); for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) { @@ -710,49 +709,49 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields, bool triggerHook) creatureTemplate.spells[i] = 0; } - creatureTemplate.PetSpellDataId = fields[46].Get(); - creatureTemplate.VehicleId = fields[47].Get(); - creatureTemplate.mingold = fields[48].Get(); - creatureTemplate.maxgold = fields[49].Get(); - creatureTemplate.AIName = fields[50].Get(); - creatureTemplate.MovementType = uint32(fields[51].Get()); + creatureTemplate.PetSpellDataId = fields[42].Get(); + creatureTemplate.VehicleId = fields[43].Get(); + creatureTemplate.mingold = fields[44].Get(); + creatureTemplate.maxgold = fields[45].Get(); + creatureTemplate.AIName = fields[46].Get(); // stopped here, fix it + creatureTemplate.MovementType = uint32(fields[47].Get()); + if (!fields[48].IsNull()) + { + creatureTemplate.Movement.Ground = static_cast(fields[48].Get()); + } + + creatureTemplate.Movement.Swim = fields[49].Get(); + if (!fields[50].IsNull()) + { + creatureTemplate.Movement.Flight = static_cast(fields[50].Get()); + } + + creatureTemplate.Movement.Rooted = fields[51].Get(); if (!fields[52].IsNull()) { - creatureTemplate.Movement.Ground = static_cast(fields[52].Get()); + creatureTemplate.Movement.Chase = static_cast(fields[52].Get()); + } + if (!fields[53].IsNull()) + { + creatureTemplate.Movement.Random = static_cast(fields[53].Get()); } - - creatureTemplate.Movement.Swim = fields[53].Get(); if (!fields[54].IsNull()) { - creatureTemplate.Movement.Flight = static_cast(fields[54].Get()); + creatureTemplate.Movement.InteractionPauseTimer = fields[54].Get(); } - creatureTemplate.Movement.Rooted = fields[55].Get(); - if (!fields[56].IsNull()) - { - creatureTemplate.Movement.Chase = static_cast(fields[56].Get()); - } - if (!fields[57].IsNull()) - { - creatureTemplate.Movement.Random = static_cast(fields[57].Get()); - } - if (!fields[58].IsNull()) - { - creatureTemplate.Movement.InteractionPauseTimer = fields[58].Get(); - } - - creatureTemplate.HoverHeight = fields[59].Get(); - creatureTemplate.ModHealth = fields[60].Get(); - creatureTemplate.ModMana = fields[61].Get(); - creatureTemplate.ModArmor = fields[62].Get(); - creatureTemplate.ModExperience = fields[63].Get(); - creatureTemplate.RacialLeader = fields[64].Get(); - creatureTemplate.movementId = fields[65].Get(); - creatureTemplate.RegenHealth = fields[66].Get(); - creatureTemplate.MechanicImmuneMask = fields[67].Get(); - creatureTemplate.SpellSchoolImmuneMask = fields[68].Get(); - creatureTemplate.flags_extra = fields[69].Get(); - creatureTemplate.ScriptID = GetScriptId(fields[70].Get()); + creatureTemplate.HoverHeight = fields[55].Get(); + creatureTemplate.ModHealth = fields[56].Get(); + creatureTemplate.ModMana = fields[57].Get(); + creatureTemplate.ModArmor = fields[58].Get(); + creatureTemplate.ModExperience = fields[59].Get(); + creatureTemplate.RacialLeader = fields[60].Get(); + creatureTemplate.movementId = fields[61].Get(); + creatureTemplate.RegenHealth = fields[62].Get(); + creatureTemplate.MechanicImmuneMask = fields[63].Get(); + creatureTemplate.SpellSchoolImmuneMask = fields[64].Get(); + creatureTemplate.flags_extra = fields[65].Get(); + creatureTemplate.ScriptID = GetScriptId(fields[66].Get()); // useful if the creature template load is being triggered from outside this class if (triggerHook) @@ -762,6 +761,58 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields, bool triggerHook) } +void ObjectMgr::LoadCreatureTemplateModels() +{ + uint32 oldMSTime = getMSTime(); + + // 0 1 2 3 + QueryResult result = WorldDatabase.Query("SELECT CreatureID, CreatureDisplayID, DisplayScale, Probability FROM creature_template_model ORDER BY Idx ASC"); + + if (!result) + { + LOG_INFO("server.loading", ">> Loaded 0 creature template model definitions. DB table `creature_template_model` is empty."); + return; + } + + uint32 count = 0; + do + { + Field* fields = result->Fetch(); + + uint32 creatureId = fields[0].Get(); + uint32 creatureDisplayId = fields[1].Get(); + float displayScale = fields[2].Get(); + float probability = fields[3].Get(); + + CreatureTemplate const* cInfo = GetCreatureTemplate(creatureId); + if (!cInfo) + { + LOG_ERROR("sql.sql", "Creature template (Entry: {}) does not exist but has a record in `creature_template_model`", creatureId); + continue; + } + + CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(creatureDisplayId); + if (!displayEntry) + { + LOG_ERROR("sql.sql", "Creature (Entry: {}) lists non-existing CreatureDisplayID id ({}), this can crash the client.", creatureId, creatureDisplayId); + continue; + } + + CreatureModelInfo const* modelInfo = GetCreatureModelInfo(creatureDisplayId); + if (!modelInfo) + LOG_ERROR("sql.sql", "No model data exist for `CreatureDisplayID` = {} listed by creature (Entry: {%u}}).", creatureDisplayId, creatureId); + + if (displayScale <= 0.0f) + displayScale = 1.0f; + + const_cast(cInfo)->Models.emplace_back(creatureDisplayId, displayScale, probability); + + ++count; + } while (result->NextRow()); + + LOG_INFO("server.loading", ">> Loaded {} creature template models in {} ms", count, GetMSTimeDiffToNow(oldMSTime)); +} + void ObjectMgr::LoadCreatureTemplateResistances() { uint32 oldMSTime = getMSTime(); @@ -1112,76 +1163,6 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo) if (!factionTemplate) LOG_ERROR("sql.sql", "Creature (Entry: {}) has non-existing faction template ({}).", cInfo->Entry, cInfo->faction); - // used later for scale - CreatureDisplayInfoEntry const* displayScaleEntry = nullptr; - - if (cInfo->Modelid1) - { - CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid1); - if (!displayEntry) - { - LOG_ERROR("sql.sql", "Creature (Entry: {}) lists non-existing Modelid1 id ({}), this can crash the client.", cInfo->Entry, cInfo->Modelid1); - const_cast(cInfo)->Modelid1 = 0; - } - else if (!displayScaleEntry) - displayScaleEntry = displayEntry; - - CreatureModelInfo const* modelInfo = GetCreatureModelInfo(cInfo->Modelid1); - if (!modelInfo) - LOG_ERROR("sql.sql", "No model data exist for `Modelid1` = {} listed by creature (Entry: {}).", cInfo->Modelid1, cInfo->Entry); - } - - if (cInfo->Modelid2) - { - CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid2); - if (!displayEntry) - { - LOG_ERROR("sql.sql", "Creature (Entry: {}) lists non-existing Modelid2 id ({}), this can crash the client.", cInfo->Entry, cInfo->Modelid2); - const_cast(cInfo)->Modelid2 = 0; - } - else if (!displayScaleEntry) - displayScaleEntry = displayEntry; - - CreatureModelInfo const* modelInfo = GetCreatureModelInfo(cInfo->Modelid2); - if (!modelInfo) - LOG_ERROR("sql.sql", "No model data exist for `Modelid2` = {} listed by creature (Entry: {}).", cInfo->Modelid2, cInfo->Entry); - } - - if (cInfo->Modelid3) - { - CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid3); - if (!displayEntry) - { - LOG_ERROR("sql.sql", "Creature (Entry: {}) lists non-existing Modelid3 id ({}), this can crash the client.", cInfo->Entry, cInfo->Modelid3); - const_cast(cInfo)->Modelid3 = 0; - } - else if (!displayScaleEntry) - displayScaleEntry = displayEntry; - - CreatureModelInfo const* modelInfo = GetCreatureModelInfo(cInfo->Modelid3); - if (!modelInfo) - LOG_ERROR("sql.sql", "No model data exist for `Modelid3` = {} listed by creature (Entry: {}).", cInfo->Modelid3, cInfo->Entry); - } - - if (cInfo->Modelid4) - { - CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid4); - if (!displayEntry) - { - LOG_ERROR("sql.sql", "Creature (Entry: {}) lists non-existing Modelid4 id ({}), this can crash the client.", cInfo->Entry, cInfo->Modelid4); - const_cast(cInfo)->Modelid4 = 0; - } - else if (!displayScaleEntry) - displayScaleEntry = displayEntry; - - CreatureModelInfo const* modelInfo = GetCreatureModelInfo(cInfo->Modelid4); - if (!modelInfo) - LOG_ERROR("sql.sql", "No model data exist for `Modelid4` = {} listed by creature (Entry: {}).", cInfo->Modelid4, cInfo->Entry); - } - - if (!displayScaleEntry) - LOG_ERROR("sql.sql", "Creature (Entry: {}) does not have any existing display id in Modelid1/Modelid2/Modelid3/Modelid4.", cInfo->Entry); - for (int k = 0; k < MAX_KILL_CREDIT; ++k) { if (cInfo->KillCredit[k]) @@ -1194,6 +1175,11 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo) } } + if (!cInfo->Models.size()) + LOG_ERROR("sql.sql", "Creature (Entry: {}) does not have any existing display id in creature_template_model.", cInfo->Entry); + else if (std::accumulate(cInfo->Models.begin(), cInfo->Models.end(), 0.0f, [](float sum, CreatureModel const& model) { return sum + model.Probability; }) <= 0.0f) + LOG_ERROR("sql.sql", "Creature (Entry: {}) has zero total chance for all models in creature_template_model.", cInfo->Entry); + if (!cInfo->unit_class || ((1 << (cInfo->unit_class - 1)) & CLASSMASK_ALL_CREATURES) == 0) { LOG_ERROR("sql.sql", "Creature (Entry: {}) has invalid unit_class ({}) in creature_template. Set to 1 (UNIT_CLASS_WARRIOR).", cInfo->Entry, cInfo->unit_class); @@ -1280,15 +1266,6 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo) const_cast(cInfo)->MovementType = IDLE_MOTION_TYPE; } - /// if not set custom creature scale then load scale from CreatureDisplayInfo.dbc - if (cInfo->scale <= 0.0f) - { - if (displayScaleEntry) - const_cast(cInfo)->scale = displayScaleEntry->scale; - else - const_cast(cInfo)->scale = 1.0f; - } - if (cInfo->expansion > (MAX_EXPANSIONS - 1)) { LOG_ERROR("sql.sql", "Table `creature_template` lists creature (Entry: {}) with expansion {}. Ignored and set to 0.", cInfo->Entry, cInfo->expansion); @@ -1722,13 +1699,19 @@ CreatureModelInfo const* ObjectMgr::GetCreatureModelInfo(uint32 modelId) const return nullptr; } -uint32 ObjectMgr::ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData const* data /*= nullptr*/) +CreatureModel const* ObjectMgr::ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData const* data /*= nullptr*/) { // Load creature model (display id) if (data && data->displayid) - return data->displayid; + if (CreatureModel const* model = cinfo->GetModelWithDisplayId(data->displayid)) + return model; - return cinfo->GetRandomValidModelId(); + if (!(cinfo->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER)) + if (CreatureModel const* model = cinfo->GetRandomValidModel()) + return model; + + // Triggers by default receive the invisible model + return cinfo->GetFirstInvisibleModel(); } void ObjectMgr::ChooseCreatureFlags(const CreatureTemplate* cinfo, uint32& npcflag, uint32& unit_flags, uint32& dynamicflags, const CreatureData* data /*= nullptr*/) @@ -1750,9 +1733,9 @@ void ObjectMgr::ChooseCreatureFlags(const CreatureTemplate* cinfo, uint32& npcfl } } -CreatureModelInfo const* ObjectMgr::GetCreatureModelRandomGender(uint32* displayID) +CreatureModelInfo const* ObjectMgr::GetCreatureModelRandomGender(CreatureModel* model, CreatureTemplate const* creatureTemplate) const { - CreatureModelInfo const* modelInfo = GetCreatureModelInfo(*displayID); + CreatureModelInfo const* modelInfo = GetCreatureModelInfo(model->CreatureDisplayID); if (!modelInfo) return nullptr; @@ -1761,11 +1744,20 @@ CreatureModelInfo const* ObjectMgr::GetCreatureModelRandomGender(uint32* display { CreatureModelInfo const* minfo_tmp = GetCreatureModelInfo(modelInfo->modelid_other_gender); if (!minfo_tmp) - LOG_ERROR("sql.sql", "Model (Entry: {}) has modelid_other_gender {} not found in table `creature_model_info`. ", *displayID, modelInfo->modelid_other_gender); + LOG_ERROR("sql.sql", "Model (Entry: {}) has modelid_other_gender {} not found in table `creature_model_info`. ", model->CreatureDisplayID, modelInfo->modelid_other_gender); else { // Model ID changed - *displayID = modelInfo->modelid_other_gender; + model->CreatureDisplayID = modelInfo->modelid_other_gender; + if (creatureTemplate) + { + auto itr = std::find_if(creatureTemplate->Models.begin(), creatureTemplate->Models.end(), [&](CreatureModel const& templateModel) + { + return templateModel.CreatureDisplayID == modelInfo->modelid_other_gender; + }); + if (itr != creatureTemplate->Models.end()) + *model = *itr; + } return minfo_tmp; } } @@ -1790,10 +1782,15 @@ void ObjectMgr::LoadCreatureModelInfo() _creatureModelStore.rehash(result->GetRowCount()); uint32 count = 0; + // List of ModelDataIDs that use Invisible models + uint32 triggerCreatureModelDataID[14] = { 1731, 1752, 2206, 2296, 2372, 2382, 2481, 2512, 2513, 2611, 2636, 2790, 3230, 3274 }; + do { Field* fields = result->Fetch(); + uint32 displayId = fields[0].Get(); + CreatureDisplayInfoEntry const* creatureDisplay = sCreatureDisplayInfoStore.LookupEntry(displayId); uint32 modelId = fields[0].Get(); CreatureModelInfo& modelInfo = _creatureModelStore[modelId]; @@ -1802,6 +1799,7 @@ void ObjectMgr::LoadCreatureModelInfo() modelInfo.combat_reach = fields[2].Get(); modelInfo.gender = fields[3].Get(); modelInfo.modelid_other_gender = fields[4].Get(); + modelInfo.is_trigger = false; // Checks @@ -1823,6 +1821,18 @@ void ObjectMgr::LoadCreatureModelInfo() if (modelInfo.combat_reach < 0.1f) modelInfo.combat_reach = DEFAULT_COMBAT_REACH; + if (CreatureModelDataEntry const* modelData = sCreatureModelDataStore.LookupEntry(creatureDisplay->ModelId)) + { + for (uint32 i = 0; i < 14; i++) + { + if (modelData->Id == triggerCreatureModelDataID[i]) + { + modelInfo.is_trigger = true; + break; + } + } + } + ++count; } while (result->NextRow()); @@ -6586,7 +6596,8 @@ void ObjectMgr::GetTaxiPath(uint32 source, uint32 destination, uint32& path, uin uint32 ObjectMgr::GetTaxiMountDisplayId(uint32 id, TeamId teamId, bool allowed_alt_team /* = false */) { - uint32 mount_id = 0; + CreatureModel mountModel; + CreatureTemplate const* mount_info = nullptr; // select mount creature id TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(id); @@ -6602,22 +6613,23 @@ uint32 ObjectMgr::GetTaxiMountDisplayId(uint32 id, TeamId teamId, bool allowed_a mount_entry = node->MountCreatureID[teamId]; } - CreatureTemplate const* mount_info = GetCreatureTemplate(mount_entry); + mount_info = GetCreatureTemplate(mount_entry); if (mount_info) { - mount_id = mount_info->GetRandomValidModelId(); - if (!mount_id) + CreatureModel const* model = mount_info->GetRandomValidModel(); + if (!model) { LOG_ERROR("sql.sql", "No displayid found for the taxi mount with the entry {}! Can't load it!", mount_entry); return 0; } + mountModel = *model; } } // minfo is not actually used but the mount_id was updated - GetCreatureModelRandomGender(&mount_id); + GetCreatureModelRandomGender(&mountModel, mount_info); - return mount_id; + return mountModel.CreatureDisplayID; } void ObjectMgr::LoadAreaTriggers() diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index b8031cb68..385ceb966 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -770,8 +770,8 @@ public: CreatureTemplate const* GetCreatureTemplate(uint32 entry); [[nodiscard]] CreatureTemplateContainer const* GetCreatureTemplates() const { return &_creatureTemplateStore; } CreatureModelInfo const* GetCreatureModelInfo(uint32 modelId) const; - CreatureModelInfo const* GetCreatureModelRandomGender(uint32* displayID); - static uint32 ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData const* data = nullptr); + CreatureModelInfo const* GetCreatureModelRandomGender(CreatureModel* model, CreatureTemplate const* creatureTemplate) const; + static CreatureModel const* ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData const* data = nullptr); static void ChooseCreatureFlags(CreatureTemplate const* cinfo, uint32& npcflag, uint32& unit_flags, uint32& dynamicflags, CreatureData const* data = nullptr); EquipmentInfo const* GetEquipmentInfo(uint32 entry, int8& id); CreatureAddon const* GetCreatureAddon(ObjectGuid::LowType lowguid); @@ -1022,6 +1022,7 @@ public: void LoadCreatureLocales(); void LoadCreatureTemplates(); void LoadCreatureTemplate(Field* fields, bool triggerHook = false); + void LoadCreatureTemplateModels(); void LoadCreatureTemplateAddons(); void LoadCreatureTemplateResistances(); void LoadCreatureTemplateSpells(); diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp index df6f4ff27..f38df27fc 100644 --- a/src/server/game/Handlers/QueryHandler.cpp +++ b/src/server/game/Handlers/QueryHandler.cpp @@ -116,23 +116,35 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket& recvData) } // guess size WorldPacket data(SMSG_CREATURE_QUERY_RESPONSE, 100); - data << uint32(entry); // creature entry + data << uint32(entry); // creature entry data << Name; - data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4, always empty + data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4, always empty data << Title; - data << ci->IconName; // "Directions" for guard, string for Icons 2.3.0 - data << uint32(ci->type_flags); // flags - data << uint32(ci->type); // CreatureType.dbc - data << uint32(ci->family); // CreatureFamily.dbc - data << uint32(ci->rank); // Creature Rank (elite, boss, etc) - data << uint32(ci->KillCredit[0]); // new in 3.1, kill credit - data << uint32(ci->KillCredit[1]); // new in 3.1, kill credit - data << uint32(ci->Modelid1); // Modelid1 - data << uint32(ci->Modelid2); // Modelid2 - data << uint32(ci->Modelid3); // Modelid3 - data << uint32(ci->Modelid4); // Modelid4 - data << float(ci->ModHealth); // dmg/hp modifier - data << float(ci->ModMana); // dmg/mana modifier + data << ci->IconName; // "Directions" for guard, string for Icons 2.3.0 + data << uint32(ci->type_flags); // flags + data << uint32(ci->type); // CreatureType.dbc + data << uint32(ci->family); // CreatureFamily.dbc + data << uint32(ci->rank); // Creature Rank (elite, boss, etc) + data << uint32(ci->KillCredit[0]); // new in 3.1, kill credit + data << uint32(ci->KillCredit[1]); // new in 3.1, kill credit + if (ci->GetModelByIdx(0)) + data << uint32(ci->GetModelByIdx(0)->CreatureDisplayID); // Modelid1 + else + data << uint32(0); // Modelid1 + if (ci->GetModelByIdx(1)) + data << uint32(ci->GetModelByIdx(1)->CreatureDisplayID); // Modelid2 + else + data << uint32(0); // Modelid2 + if (ci->GetModelByIdx(2)) + data << uint32(ci->GetModelByIdx(2)->CreatureDisplayID); // Modelid3 + else + data << uint32(0); // Modelid3 + if (ci->GetModelByIdx(3)) + data << uint32(ci->GetModelByIdx(3)->CreatureDisplayID); // Modelid4 + else + data << uint32(0); // Modelid4 + data << float(ci->ModHealth); // dmg/hp modifier + data << float(ci->ModMana); // dmg/mana modifier data << uint8(ci->RacialLeader); CreatureQuestItemList const* items = sObjectMgr->GetCreatureQuestItemList(entry); @@ -143,7 +155,7 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket& recvData) for (size_t i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i) data << uint32(0); - data << uint32(ci->movementId); // CreatureMovementInfo.dbc + data << uint32(ci->movementId); // CreatureMovementInfo.dbc SendPacket(&data); } else diff --git a/src/server/game/Scripting/ScriptDefines/AllCommandScript.cpp b/src/server/game/Scripting/ScriptDefines/AllCommandScript.cpp index 0ab2f297f..59b1395f5 100644 --- a/src/server/game/Scripting/ScriptDefines/AllCommandScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/AllCommandScript.cpp @@ -24,9 +24,9 @@ void ScriptMgr::OnHandleDevCommand(Player* player, bool& enable) CALL_ENABLED_HOOKS(AllCommandScript, ALLCOMMANDHOOK_ON_HANDLE_DEV_COMMAND, script->OnHandleDevCommand(player, enable)); } -bool ScriptMgr::CanExecuteCommand(ChatHandler& handler, std::string_view cmdStr) +bool ScriptMgr::OnTryExecuteCommand(ChatHandler& handler, std::string_view cmdStr) { - CALL_ENABLED_BOOLEAN_HOOKS(AllCommandScript, ALLCOMMANDHOOK_CAN_EXECUTE_COMMAND, !script->CanExecuteCommand(handler, cmdStr)); + CALL_ENABLED_BOOLEAN_HOOKS(AllCommandScript, ALLCOMMANDHOOK_ON_TRY_EXECUTE_COMMAND, !script->OnTryExecuteCommand(handler, cmdStr)); } AllCommandScript::AllCommandScript(const char* name, std::vector enabledHooks) diff --git a/src/server/game/Scripting/ScriptDefines/AllCommandScript.h b/src/server/game/Scripting/ScriptDefines/AllCommandScript.h index 509822e7a..750028115 100644 --- a/src/server/game/Scripting/ScriptDefines/AllCommandScript.h +++ b/src/server/game/Scripting/ScriptDefines/AllCommandScript.h @@ -24,7 +24,7 @@ enum AllCommandHook { ALLCOMMANDHOOK_ON_HANDLE_DEV_COMMAND, - ALLCOMMANDHOOK_CAN_EXECUTE_COMMAND, + ALLCOMMANDHOOK_ON_TRY_EXECUTE_COMMAND, ALLCOMMANDHOOK_END }; @@ -39,12 +39,12 @@ public: virtual void OnHandleDevCommand(Player* /*player*/, bool& /*enable*/) { } /** - * @brief This hook runs execute chat command + * @brief This hook is triggered when a command is parsed, but before it is executed * * @param handler Contains information about the ChatHandler * @param cmdStr Contains information about the command name */ - [[nodiscard]] virtual bool CanExecuteCommand(ChatHandler& /*handler*/, std::string_view /*cmdStr*/) { return true; } + [[nodiscard]] virtual bool OnTryExecuteCommand(ChatHandler& /*handler*/, std::string_view /*cmdStr*/) { return true; } }; // Compatibility for old scripts diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 23e69cb8a..bed6f0c35 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -703,7 +703,7 @@ public: /* MiscScript */ public: /* CommandSC */ void OnHandleDevCommand(Player* player, bool& enable); - bool CanExecuteCommand(ChatHandler& handler, std::string_view cmdStr); + bool OnTryExecuteCommand(ChatHandler& handler, std::string_view cmdStr); public: /* DatabaseScript */ diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 2d0c5c76f..5a533f307 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -2705,7 +2705,7 @@ void AuraEffect::HandleAuraTransform(AuraApplication const* aurApp, uint8 mode, { uint32 model_id = 0; - if (uint32 modelid = ci->GetRandomValidModelId()) + if (uint32 modelid = ObjectMgr::ChooseDisplayId(ci)->CreatureDisplayID) model_id = modelid; // Will use the default model here // Polymorph (sheep) @@ -2757,10 +2757,10 @@ void AuraEffect::HandleAuraTransform(AuraApplication const* aurApp, uint8 mode, uint32 cr_id = target->GetAuraEffectsByType(SPELL_AURA_MOUNTED).front()->GetMiscValue(); if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(cr_id)) { - uint32 displayID = ObjectMgr::ChooseDisplayId(ci); - sObjectMgr->GetCreatureModelRandomGender(&displayID); + CreatureModel model = *ObjectMgr::ChooseDisplayId(ci); + sObjectMgr->GetCreatureModelRandomGender(&model, ci); - target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, displayID); + target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, model.CreatureDisplayID); } } } @@ -3272,15 +3272,9 @@ void AuraEffect::HandleAuraMounted(AuraApplication const* aurApp, uint8 mode, bo if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(creatureEntry)) { - if (GetMiscValueB() > 0) // Choose proper modelid - { - displayId = GetMiscValueB() == 2 && creatureInfo->Modelid2 > 0 ? creatureInfo->Modelid2 : creatureInfo->Modelid1; - } - else // Should we choose random modelid in this case? - { - displayId = ObjectMgr::ChooseDisplayId(creatureInfo); - } - sObjectMgr->GetCreatureModelRandomGender(&displayId); + CreatureModel model = *ObjectMgr::ChooseDisplayId(creatureInfo); + sObjectMgr->GetCreatureModelRandomGender(&model, creatureInfo); + displayId = model.CreatureDisplayID; vehicleId = creatureInfo->VehicleId; @@ -4146,6 +4140,7 @@ void AuraEffect::HandleModMechanicImmunity(AuraApplication const* aurApp, uint8 case 34471: // The Beast Within case 19574: // Bestial Wrath case 38484: // Bestial Wrath + case 40081: // Free friend (Black Temple) mechanic = IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK; target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_CHARM, apply); target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply); @@ -5792,10 +5787,10 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(creatureEntry)) { - uint32 displayID = ObjectMgr::ChooseDisplayId(creatureInfo); - sObjectMgr->GetCreatureModelRandomGender(&displayID); + CreatureModel model = *ObjectMgr::ChooseDisplayId(creatureInfo); + sObjectMgr->GetCreatureModelRandomGender(&model, creatureInfo); - target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, displayID); + target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, model.CreatureDisplayID); } } break; @@ -5822,10 +5817,10 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(creatureEntry)) { - uint32 displayID = ObjectMgr::ChooseDisplayId(creatureInfo); - sObjectMgr->GetCreatureModelRandomGender(&displayID); + CreatureModel model = *ObjectMgr::ChooseDisplayId(creatureInfo); + sObjectMgr->GetCreatureModelRandomGender(&model, creatureInfo); - target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, displayID); + target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, model.CreatureDisplayID); } } break; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 36814b4b1..da1af4212 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -3710,7 +3710,6 @@ void Spell::cancel(bool bySelf) return; uint32 oldState = m_spellState; - bool autoRepeat = m_autoRepeat; m_spellState = SPELL_STATE_FINISHED; m_autoRepeat = false; @@ -3723,12 +3722,9 @@ void Spell::cancel(bool bySelf) if (m_caster->ToPlayer()->NeedSendSpectatorData()) ArenaSpectator::SendCommand_Spell(m_caster->FindMap(), m_caster->GetGUID(), "SPE", m_spellInfo->Id, bySelf ? 99998 : 99999); } - [[fallthrough]]; /// @todo: Not sure whether the fallthrough was a mistake (forgetting a break) or intended. This should be double-checked. + [[fallthrough]]; case SPELL_STATE_DELAYED: - SendInterrupted(0); - // xinef: fixes bugged gcd reset in some cases - if (!autoRepeat) - SendCastResult(SPELL_FAILED_INTERRUPTED); + SendInterrupted(SPELL_FAILED_INTERRUPTED); break; case SPELL_STATE_CASTING: @@ -3740,8 +3736,7 @@ void Spell::cancel(bool bySelf) unit->RemoveOwnedAura(m_spellInfo->Id, m_originalCasterGUID, 0, AURA_REMOVE_BY_CANCEL); SendChannelUpdate(0); - SendInterrupted(0); - SendCastResult(SPELL_FAILED_INTERRUPTED); + SendInterrupted(SPELL_FAILED_INTERRUPTED); } if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->NeedSendSpectatorData()) diff --git a/src/server/game/Spells/SpellInfoCorrections.cpp b/src/server/game/Spells/SpellInfoCorrections.cpp index ae0797b8e..8099392d6 100644 --- a/src/server/game/Spells/SpellInfoCorrections.cpp +++ b/src/server/game/Spells/SpellInfoCorrections.cpp @@ -4797,6 +4797,13 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->MaxAffectedTargets = 5; }); + // Presence Of Mind + ApplySpellFix({ 12043 }, [](SpellInfo* spellInfo) + { + // It should not share cooldown mods with category[1151] spells (Arcane Power [12042], Decimate [47271]) + spellInfo->AttributesEx6 |= SPELL_ATTR6_NO_CATEGORY_COOLDOWN_MODS; + }); + for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i) { SpellInfo* spellInfo = mSpellInfoMap[i]; diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp index 0d55b9f4c..cef361a80 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp @@ -63,7 +63,7 @@ struct npc_eye_of_acherus : public ScriptedAI { npc_eye_of_acherus(Creature* creature) : ScriptedAI(creature) { - creature->SetDisplayId(creature->GetCreatureTemplate()->Modelid1); + creature->SetDisplayFromModel(0); creature->SetReactState(REACT_PASSIVE); } @@ -968,7 +968,7 @@ public: { me->SetImmuneToAll(true); me->SetFaction(FACTION_FRIENDLY); - me->SetDisplayId(me->GetCreatureTemplate()->Modelid1); // Modelid2 is a horse. + me->SetDisplayFromModel(0); // Modelid2 is a horse. } ObjectGuid minerGUID; diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp index c9b6f89b4..403f690a4 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp @@ -94,7 +94,7 @@ struct boss_jindo : public BossAI void EnterEvadeMode(EvadeReason evadeReason) override { - if (_EnterEvadeMode(evadeReason)) + if (CreatureAI::_EnterEvadeMode(evadeReason)) { Reset(); me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_DANCE); diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp index 4ea6dc483..cdf4fc11a 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp @@ -141,24 +141,17 @@ private: struct npc_doomfire_spirit : public ScriptedAI { - npc_doomfire_spirit(Creature* creature) : ScriptedAI(creature) - { - _instance = creature->GetInstanceScript(); - } + npc_doomfire_spirit(Creature* creature) : ScriptedAI(creature){ } void Reset() override { - Position randomPosition; - scheduler.CancelAll(); ScheduleTimedEvent(0s, [&] { - DoomfireMovement(randomPosition, me->GetPosition()); - - me->GetMotionMaster()->MovePoint(NEAR_POINT, randomPosition); + me->GetMotionMaster()->MovePoint(NEAR_POINT, DoomfireMovement(me->GetPosition())); }, 1500ms); } - void DoomfireMovement(Position& targetPos, Position mePos) + Position DoomfireMovement(Position mePos) { float angle = mePos.GetOrientation(); float distance = 100.0f; @@ -166,8 +159,8 @@ struct npc_doomfire_spirit : public ScriptedAI float x = mePos.GetPositionX() + distance * cos(newAngle); float y = mePos.GetPositionY() + distance * sin(newAngle); - targetPos = Position(x, y, me->GetPositionZ()); - return; + Position targetPos = Position(x, y, me->GetPositionZ()); + return targetPos; } void UpdateAI(uint32 diff) override @@ -180,8 +173,6 @@ struct npc_doomfire_spirit : public ScriptedAI if (me->HasUnitState(UNIT_STATE_CASTING)) return; } -private: - InstanceScript* _instance; }; struct boss_archimonde : public BossAI @@ -196,22 +187,13 @@ struct boss_archimonde : public BossAI void Reset() override { - BossAI::Reset(); + _Reset(); _wispCount = 0; _isChanneling = false; _enraged = false; _availableAuras.clear(); _availableSpells.clear(); - if (Map* map = me->GetMap()) - { - map->DoForAllPlayers([&](Player* player) - { - player->ApplySpellImmune(SPELL_HAND_OF_DEATH, IMMUNITY_ID, SPELL_HAND_OF_DEATH, false); - player->ApplySpellImmune(0, IMMUNITY_ID, SPELL_HAND_OF_DEATH, false); - }); - } - if (instance->GetBossState(DATA_AZGALOR) != DONE) { me->SetVisible(false); @@ -225,7 +207,7 @@ struct boss_archimonde : public BossAI ScheduleHealthCheckEvent(10, [&]{ scheduler.CancelAll(); me->SetReactState(REACT_PASSIVE); - DoCastProtection(); + DoCastAOE(SPELL_PROTECTION_OF_ELUNE, true); Talk(SAY_ENRAGE); _enraged = true; me->GetMotionMaster()->Clear(false); @@ -234,7 +216,7 @@ struct boss_archimonde : public BossAI { if (_wispCount >= 30) { - Unit::DealDamage(me, me, me->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + me->KillSelf(); } Position wispPosition = { me->GetPositionX() + float(rand() % WISP_OFFSET), me->GetPositionY() + float(rand() % WISP_OFFSET), me->GetPositionZ(), 0.0f }; if (Creature* wisp = me->SummonCreature(CREATURE_ANCIENT_WISP, wispPosition)) @@ -262,8 +244,6 @@ struct boss_archimonde : public BossAI { if (Creature* nordrassil = me->SummonCreature(CREATURE_CHANNEL_TARGET, nordrassilPosition, TEMPSUMMON_TIMED_DESPAWN, 1200000)) { - nordrassil->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - nordrassil->SetDisplayId(DISPLAY_ID_TRIGGER); DoCast(nordrassil, SPELL_DRAIN_WORLD_TREE); _isChanneling = true; nordrassil->AI()->DoCast(me, SPELL_DRAIN_WORLD_TREE_2, true); @@ -273,29 +253,16 @@ struct boss_archimonde : public BossAI } } - void DoCastProtection() + void JustEngagedWith(Unit* /*who*/) override { - if (Map* map = me->GetMap()) - { - map->DoForAllPlayers([&](Player* player) - { - player->AddAura(SPELL_PROTECTION_OF_ELUNE, player); - player->ApplySpellImmune(SPELL_HAND_OF_DEATH, IMMUNITY_ID, SPELL_HAND_OF_DEATH, true); - player->ApplySpellImmune(0, IMMUNITY_ID, SPELL_HAND_OF_DEATH, true); - }); - } - } - - void JustEngagedWith(Unit* who) override - { - BossAI::JustEngagedWith(who); + _JustEngagedWith(); me->InterruptNonMeleeSpells(false); Talk(SAY_AGGRO); ScheduleTimedEvent(25s, 35s, [&] { scheduler.DelayGroup(GROUP_FEAR, 5s); Talk(SAY_AIR_BURST); - DoCastAOE(SPELL_AIR_BURST); + DoCastRandomTarget(SPELL_AIR_BURST); }, 25s, 40s); ScheduleTimedEvent(25s, 35s, [&] { @@ -354,49 +321,46 @@ struct boss_archimonde : public BossAI instance->SetData(DATA_SPAWN_WAVES, 1); } - void KilledUnit(Unit* victim) override + void KilledUnit(Unit* /*victim*/) override { Talk(SAY_SLAY); - - if (victim->IsPlayer()) - { - GainSoulCharge(victim->ToPlayer()); - } } - void GainSoulCharge(Player* player) + void SetGUID(ObjectGuid guid, int32 type) override { - switch (player->getClass()) + if (type == GUID_GAIN_SOUL_CHARGE_PLAYER) { - case CLASS_PALADIN: - case CLASS_PRIEST: - case CLASS_WARLOCK: - player->CastSpell(me, SPELL_SOUL_CHARGE_RED, true); - break; - case CLASS_DEATH_KNIGHT: - case CLASS_MAGE: - case CLASS_ROGUE: - case CLASS_WARRIOR: - player->CastSpell(me, SPELL_SOUL_CHARGE_YELLOW, true); - break; - case CLASS_DRUID: - case CLASS_HUNTER: - case CLASS_SHAMAN: - player->CastSpell(me, SPELL_SOUL_CHARGE_GREEN, true); - break; - case CLASS_NONE: - default: - break; - } - scheduler.Schedule(2s, 10s, [this](TaskContext) - { - UnleashSoulCharge(); - }); - } + if (Player* player = ObjectAccessor::GetPlayer(*me, guid)) + { + switch (player->getClass()) + { + case CLASS_PALADIN: + case CLASS_PRIEST: + case CLASS_WARLOCK: + player->CastSpell(me, SPELL_SOUL_CHARGE_RED, true); + break; + case CLASS_DEATH_KNIGHT: + case CLASS_MAGE: + case CLASS_ROGUE: + case CLASS_WARRIOR: + player->CastSpell(me, SPELL_SOUL_CHARGE_YELLOW, true); + break; + case CLASS_DRUID: + case CLASS_HUNTER: + case CLASS_SHAMAN: + player->CastSpell(me, SPELL_SOUL_CHARGE_GREEN, true); + break; + case CLASS_NONE: + default: + break; + } - void JustDied(Unit* killer) override - { - BossAI::JustDied(killer); + scheduler.Schedule(2s, 10s, [this](TaskContext) + { + UnleashSoulCharge(); + }); + } + } } void EnterEvadeMode(EvadeReason why) override @@ -443,8 +407,6 @@ struct boss_archimonde : public BossAI { if (Creature* doomfire = me->SummonCreature(CREATURE_DOOMFIRE, doomfirePosition, TEMPSUMMON_TIMED_DESPAWN, 27000)) { - doomfireSpirit->SetVisible(false); - doomfire->SetVisible(false); doomfireSpirit->SetWalk(false); doomfireSpirit->SetReactState(REACT_PASSIVE); doomfire->SetReactState(REACT_PASSIVE); @@ -507,42 +469,6 @@ class spell_red_sky_effect : public SpellScript } }; -class spell_finger_of_death : public SpellScript -{ - PrepareSpellScript(spell_finger_of_death); - - void HandleHit(SpellEffIndex /*effIndex*/) - { - if (GetHitUnit() && GetHitUnit()->GetAura(SPELL_PROTECTION_OF_ELUNE)) - PreventHitDamage(); - else - GetHitUnit()->RemoveAurasByType(SPELL_AURA_EFFECT_IMMUNITY); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_finger_of_death::HandleHit, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); - } -}; - -class spell_hand_of_death : public SpellScript -{ - PrepareSpellScript(spell_hand_of_death); - - void HandleHit(SpellEffIndex /*effIndex*/) - { - if (GetHitUnit() && GetHitUnit()->GetAura(SPELL_PROTECTION_OF_ELUNE)) - PreventHitDamage(); - else - GetHitUnit()->RemoveAurasByType(SPELL_AURA_EFFECT_IMMUNITY); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_hand_of_death::HandleHit, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); - } -}; - class spell_air_burst : public SpellScript { PrepareSpellScript(spell_air_burst); @@ -564,8 +490,6 @@ class spell_air_burst : public SpellScript void AddSC_boss_archimonde() { RegisterSpellScript(spell_red_sky_effect); - RegisterSpellScript(spell_hand_of_death); - RegisterSpellScript(spell_finger_of_death); RegisterSpellScript(spell_air_burst); RegisterHyjalAI(boss_archimonde); RegisterHyjalAI(npc_ancient_wisp); diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h index 4f2493e7c..f29a56eb2 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h @@ -27,18 +27,13 @@ uint32 const EncounterCount = 5; -enum HyjalBosses -{ - BOSS_ARCHIMONDE = 0, -}; - enum DataTypes { - DATA_WINTERCHILL = 1, - DATA_ANETHERON = 2, - DATA_KAZROGAL = 3, - DATA_AZGALOR = 4, - DATA_ARCHIMONDE = 5, + DATA_WINTERCHILL = 0, + DATA_ANETHERON = 1, + DATA_KAZROGAL = 2, + DATA_AZGALOR = 3, + DATA_ARCHIMONDE = 4, DATA_ALLIANCE_RETREAT = 11, DATA_HORDE_RETREAT = 12, @@ -90,6 +85,7 @@ enum HyjalCreaturesIds NPC_ALLIANCE_RIFLEMAN = 17921, NPC_ALLIANCE_PRIEST = 17928, NPC_ALLIANCE_SORCERESS = 17922, + NPC_GUARDIAN_ELEMENTAL = 18001, // Horde Base NPC_THRALL = 17852, @@ -102,6 +98,7 @@ enum HyjalCreaturesIds NPC_HORDE_PEON = 17937, NPC_INFERNAL_RELAY = 18242, NPC_INFERNAL_TARGET = 21075, + NPC_DIRE_WOLF = 17854, // Night Elf Base NPC_TYRANDE = 17948, @@ -152,7 +149,9 @@ enum HyjalMisc AREA_NORDRASSIL = 3710, - SPELL_ETERNAL_SILENCE = 42201 + SPELL_ETERNAL_SILENCE = 42201, + + GUID_GAIN_SOUL_CHARGE_PLAYER = 1 }; 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 2589d7067..3e518ecca 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp @@ -51,11 +51,6 @@ ObjectData const creatureData[] = { 0, 0 } }; -ObjectData const objectData[] = -{ - { 0, 0 } -}; - Milliseconds hyjalWaveTimers[4][MAX_WAVES_STANDARD] { { 130000ms, 130000ms, 130000ms, 130000ms, 130000ms, 130000ms, 130000ms, 190000ms, 0ms }, // Winterchill @@ -92,12 +87,12 @@ public: SetHeaders(DataHeader); SetBossNumber(EncounterCount); LoadDoorData(doorData); - LoadObjectData(creatureData, objectData); + LoadObjectData(creatureData, nullptr); } void Initialize() override { - _bossWave = 0; + _bossWave = TO_BE_DECIDED; _retreat = 0; trash = 0; _currentWave = 0; @@ -190,12 +185,12 @@ public: case NPC_GARGO: case NPC_FROST: case NPC_INFER: - if (_bossWave) + if (_bossWave != TO_BE_DECIDED) creature->AI()->DoAction(_bossWave); else if (_retreat) creature->AI()->DoAction(_retreat); - if (creature->IsSummon() && _bossWave) + if (creature->IsSummon() && _bossWave != TO_BE_DECIDED) { DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, ++trash); // Update the instance wave count on new trash spawn _encounterNPCs.insert(creature->GetGUID()); // Used for despawning on wipe @@ -203,6 +198,8 @@ public: break; case NPC_TOWERING_INFERNAL: case NPC_LESSER_DOOMGUARD: + case NPC_DIRE_WOLF: + case NPC_GUARDIAN_ELEMENTAL: if (creature->IsSummon()) { _summonedNPCs.insert(creature->GetGUID()); @@ -231,7 +228,7 @@ public: case NPC_STALK: if (creature->IsSummon()) { - if (_bossWave) + if (_bossWave != TO_BE_DECIDED) { DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, --trash); // Update the instance wave count on new trash death _encounterNPCs.erase(creature->GetGUID()); // Used for despawning on wipe @@ -243,6 +240,8 @@ public: break; case NPC_TOWERING_INFERNAL: case NPC_LESSER_DOOMGUARD: + case NPC_DIRE_WOLF: + case NPC_GUARDIAN_ELEMENTAL: _summonedNPCs.erase(creature->GetGUID()); break; case NPC_WINTERCHILL: @@ -250,13 +249,18 @@ public: case NPC_KAZROGAL: case NPC_AZGALOR: if (Creature* jaina = GetCreature(DATA_JAINA)) - jaina->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + jaina->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP); if (Creature* thrall = GetCreature(DATA_THRALL)) - thrall->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + thrall->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP); SetData(DATA_RESET_WAVES, 1); break; } } + else if (unit->IsPlayer() && GetBossState(DATA_ARCHIMONDE) == IN_PROGRESS) + { + if (Creature* archimonde = GetCreature(DATA_ARCHIMONDE)) + archimonde->AI()->SetGUID(unit->GetGUID(), GUID_GAIN_SOUL_CHARGE_PLAYER); + } } void SetData(uint32 type, uint32 data) override @@ -264,7 +268,7 @@ public: switch (type) { case DATA_ALLIANCE_RETREAT: - _bossWave = 0; + _bossWave = TO_BE_DECIDED; _retreat = DATA_ALLIANCE_RETREAT; // Spawn Ancient Gems for (ObjectGuid const& guid : _ancientGemAlliance) @@ -290,14 +294,14 @@ public: } // Despawn all alliance NPCs - _scheduler.Schedule(21000ms, [this](TaskContext) + scheduler.Schedule(21000ms, [this](TaskContext) { for (ObjectGuid const& guid : _baseAlliance) if (Creature* creature = instance->GetCreature(guid)) creature->DespawnOrUnsummon(); // Spawn Roaring Flame after a delay - _scheduler.Schedule(30s, [this](TaskContext) + scheduler.Schedule(30s, [this](TaskContext) { for (ObjectGuid const& guid : _roaringFlameAlliance) { @@ -313,7 +317,7 @@ public: SaveToDB(); break; case DATA_HORDE_RETREAT: - _bossWave = 0; + _bossWave = TO_BE_DECIDED; _retreat = DATA_HORDE_RETREAT; for (ObjectGuid const& guid : _ancientGemHorde) { @@ -338,13 +342,13 @@ public: } } - _scheduler.Schedule(21000ms, [this](TaskContext) + scheduler.Schedule(21000ms, [this](TaskContext) { for (ObjectGuid const& guid : _baseHorde) if (Creature* creature = instance->GetCreature(guid)) creature->DespawnOrUnsummon(); - _scheduler.Schedule(30s, [this](TaskContext) + scheduler.Schedule(30s, [this](TaskContext) { for (ObjectGuid const& guid : _roaringFlameHorde) if (GameObject* flame = instance->GetGameObject(guid)) @@ -360,45 +364,49 @@ public: _retreat = 0; if (GetBossState(DATA_WINTERCHILL) != DONE) { - if (!_bossWave) + if (_bossWave == TO_BE_DECIDED) for (ObjectGuid const& guid : _baseAlliance) if (Creature* creature = instance->GetCreature(guid)) creature->Respawn(); _bossWave = DATA_WINTERCHILL; - ScheduleWaves(1ms, START_WAVE_WINTERCHILL, MAX_WAVES_STANDARD, hyjalWaveTimers[DATA_WINTERCHILL - 1]); + ScheduleWaves(1ms, START_WAVE_WINTERCHILL, MAX_WAVES_STANDARD, hyjalWaveTimers[DATA_WINTERCHILL]); } else if (GetBossState(DATA_ANETHERON) != DONE) { - if (!_bossWave) + if (_bossWave == TO_BE_DECIDED) for (ObjectGuid const& guid : _baseAlliance) if (Creature* creature = instance->GetCreature(guid)) creature->Respawn(); _bossWave = DATA_ANETHERON; - ScheduleWaves(1ms, START_WAVE_ANETHERON, MAX_WAVES_STANDARD, hyjalWaveTimers[DATA_ANETHERON - 1]); + ScheduleWaves(1ms, START_WAVE_ANETHERON, MAX_WAVES_STANDARD, hyjalWaveTimers[DATA_ANETHERON]); } else if (GetBossState(DATA_KAZROGAL) != DONE) { - if (!_bossWave) + if (_bossWave == TO_BE_DECIDED) for (ObjectGuid const& guid : _baseHorde) if (Creature* creature = instance->GetCreature(guid)) creature->Respawn(); _bossWave = DATA_KAZROGAL; - ScheduleWaves(1ms, START_WAVE_KAZROGAL, MAX_WAVES_STANDARD, hyjalWaveTimers[DATA_KAZROGAL - 1]); + ScheduleWaves(1ms, START_WAVE_KAZROGAL, MAX_WAVES_STANDARD, hyjalWaveTimers[DATA_KAZROGAL]); } else if (GetBossState(DATA_AZGALOR) != DONE) { - if (!_bossWave) + if (_bossWave == TO_BE_DECIDED) for (ObjectGuid const& guid : _baseHorde) if (Creature* creature = instance->GetCreature(guid)) creature->Respawn(); _bossWave = DATA_AZGALOR; - ScheduleWaves(1ms, START_WAVE_AZGALOR, MAX_WAVES_STANDARD, hyjalWaveTimers[DATA_AZGALOR - 1]); + ScheduleWaves(1ms, START_WAVE_AZGALOR, MAX_WAVES_STANDARD, hyjalWaveTimers[DATA_AZGALOR]); } else if (GetBossState(DATA_ARCHIMONDE) != DONE) { _bossWave = DATA_ARCHIMONDE; ScheduleWaves(1ms, START_WAVE_NIGHT_ELF, MAX_WAVES_NIGHT_ELF, hyjalNightElfWaveTimers[0]); } + + if (_bossWave != TO_BE_DECIDED) + DoUpdateWorldState(WORLD_STATE_WAVES, 0); + break; case DATA_SPAWN_INFERNALS: { @@ -419,89 +427,51 @@ public: } } break; - case DATA_RESET_ALLIANCE: - for (ObjectGuid const& guid : _baseAlliance) - if (Creature* creature = instance->GetCreature(guid)) - creature->DespawnOrUnsummon(); - - for (ObjectGuid const& guid : _encounterNPCs) - 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) - if (Creature* creature = instance->GetCreature(guid)) - creature->Respawn(); - }); - - SetData(DATA_RESET_WAVES, 0); - break; - case DATA_RESET_HORDE: - for (ObjectGuid const& guid : _baseHorde) - if (Creature* creature = instance->GetCreature(guid)) - creature->DespawnOrUnsummon(); - - for (ObjectGuid const& guid : _encounterNPCs) - 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) - if (Creature* creature = instance->GetCreature(guid)) - creature->Respawn(); - }); - - SetData(DATA_RESET_WAVES, 0); - break; case DATA_RESET_NIGHT_ELF: + if (Creature* archimonde = GetCreature(DATA_ARCHIMONDE)) + archimonde->DespawnOrUnsummon(0s, 300s); + [[fallthrough]]; + case DATA_RESET_ALLIANCE: + case DATA_RESET_HORDE: + if (GetBossState(DATA_ANETHERON) != DONE) + { + for (ObjectGuid const& guid : _baseAlliance) + if (Creature* creature = instance->GetCreature(guid)) + creature->DespawnOrUnsummon(0s, 300s); + } + + if (GetBossState(DATA_AZGALOR) != DONE) + { + for (ObjectGuid const& guid : _baseHorde) + if (Creature* creature = instance->GetCreature(guid)) + creature->DespawnOrUnsummon(0s, 300s); + } + for (ObjectGuid const& guid : _baseNightElf) if (Creature* creature = instance->GetCreature(guid)) - creature->DespawnOrUnsummon(); + creature->DespawnOrUnsummon(0s, 300s); for (ObjectGuid const& guid : _encounterNPCs) if (Creature* creature = instance->GetCreature(guid)) creature->DespawnOrUnsummon(); - if (Creature* archimonde = GetCreature(DATA_ARCHIMONDE)) - archimonde->DespawnOrUnsummon(); + // also force despawn boss summons + for (ObjectGuid const& guid : _summonedNPCs) + if (Creature* creature = instance->GetCreature(guid)) + creature->DespawnOrUnsummon(); - _scheduler.Schedule(300s, [this](TaskContext) - { - for (ObjectGuid const& guid : _baseNightElf) - if (Creature* creature = instance->GetCreature(guid)) - creature->Respawn(); - - if (Creature* archi = GetCreature(DATA_ARCHIMONDE)) - archi->Respawn(); - }); + if (_bossWave != TO_BE_DECIDED && (GetBossState(_bossWave) != DONE)) + SetBossState(_bossWave, NOT_STARTED); SetData(DATA_RESET_WAVES, 0); break; case DATA_RESET_WAVES: - _scheduler.CancelGroup(CONTEXT_GROUP_WAVES); + scheduler.CancelGroup(CONTEXT_GROUP_WAVES); _encounterNPCs.clear(); _summonedNPCs.clear(); _currentWave = 0; trash = 0; - _bossWave = 0; + _bossWave = TO_BE_DECIDED; _retreat = 0; DoUpdateWorldState(WORLD_STATE_WAVES, _currentWave); DoUpdateWorldState(WORLD_STATE_ENEMY, trash); @@ -533,10 +503,10 @@ public: void ScheduleWaves(Milliseconds /* time */, uint8 startWaves, uint8 maxWaves, Milliseconds timerptr[]) { // No overlapping! - _scheduler.CancelGroup(CONTEXT_GROUP_WAVES); + scheduler.CancelGroup(CONTEXT_GROUP_WAVES); trash = 0; // Reset counter here to avoid resetting the counter from scheduled waves. Required because creatures killed for RP events counts towards the kill counter as well, confirmed in Retail. - _scheduler.Schedule(1ms, [this, startWaves, maxWaves, timerptr](TaskContext context) + scheduler.Schedule(1ms, [this, startWaves, maxWaves, timerptr](TaskContext context) { // If all waves reached, cancel scheduling new ones if (_currentWave >= maxWaves) @@ -572,7 +542,7 @@ public: void Update(uint32 diff) override { - _scheduler.Update(diff); + scheduler.Update(diff); } void OnPlayerInWaterStateUpdate(Player* player, bool inWater) override @@ -588,7 +558,6 @@ public: uint8 _currentWave; uint8 _bossWave; uint8 _retreat; - TaskScheduler _scheduler; GuidSet _encounterNPCs; GuidSet _summonedNPCs; GuidSet _baseAlliance; diff --git a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp index eae494c58..b1388a95d 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp @@ -82,6 +82,7 @@ enum Spells SPELL_SARTHARION_FLAME_BREATH = 56908, SPELL_SARTHARION_TAIL_LASH = 56910, SPELL_CYCLONE_AURA_PERIODIC = 57598, + SPELL_LAVA_STRIKE_DUMMY = 57578, SPELL_LAVA_STRIKE_DUMMY_TRIGGER = 57697, SPELL_LAVA_STRIKE_SUMMON = 57572, SPELL_SARTHARION_PYROBUFFET = 56916, @@ -102,6 +103,7 @@ enum Spells // Misc SPELL_FADE_ARMOR = 60708, SPELL_FLAME_TSUNAMI_DAMAGE_AURA = 57492, + SPELL_FLAME_TSUNAMI_LEAP = 60241, SPELL_SARTHARION_PYROBUFFET_TRIGGER = 57557, }; @@ -1512,65 +1514,107 @@ public: }; }; -class spell_sartharion_lava_strike : public SpellScriptLoader +class spell_sartharion_lava_strike : public SpellScript { -public: - spell_sartharion_lava_strike() : SpellScriptLoader("spell_sartharion_lava_strike") {} + PrepareSpellScript(spell_sartharion_lava_strike); - class spell_sartharion_lava_strike_SpellScript : public SpellScript + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareSpellScript(spell_sartharion_lava_strike_SpellScript); + return ValidateSpellInfo({ SPELL_LAVA_STRIKE_SUMMON, SPELL_LAVA_STRIKE_DUMMY_TRIGGER }); + } - bool spawned; - - bool Load() override - { - spawned = false; - return true; - } - - void HandleDummy(SpellEffIndex /*effIndex*/) - { - if (!GetCaster() || !GetHitUnit()) - return; - - GetCaster()->CastSpell(GetHitUnit()->GetPositionX(), GetHitUnit()->GetPositionY(), GetHitUnit()->GetPositionZ(), SPELL_LAVA_STRIKE_DUMMY_TRIGGER, true); - } - - void HandleSchoolDamage(SpellEffIndex /*effIndex*/) - { - if (!GetCaster() || !GetHitUnit() || spawned) - { - return; - } - - if (InstanceScript* pInstance = GetCaster()->GetInstanceScript()) - { - if (Creature* sarth = ObjectAccessor::GetCreature(*GetHitUnit(), pInstance->GetGuidData(DATA_SARTHARION))) - { - sarth->AI()->SetData(DATA_VOLCANO_BLOWS, GetHitUnit()->GetGUID().GetCounter()); - sarth->CastSpell(GetHitUnit(), SPELL_LAVA_STRIKE_SUMMON, true); - spawned = true; - } - } - } - - void Register() override - { - if (m_scriptSpellId == 57578) // Dummy lava strike - { - OnEffectHitTarget += SpellEffectFn(spell_sartharion_lava_strike_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); - } - else - { - OnEffectHitTarget += SpellEffectFn(spell_sartharion_lava_strike_SpellScript::HandleSchoolDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); - } - } - }; - - SpellScript* GetSpellScript() const override + bool Load() override { - return new spell_sartharion_lava_strike_SpellScript(); + _spawned = false; + return true; + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + if (!GetCaster() || !GetHitUnit()) + { + return; + } + + GetCaster()->CastSpell(GetHitUnit()->GetPositionX(), GetHitUnit()->GetPositionY(), GetHitUnit()->GetPositionZ(), SPELL_LAVA_STRIKE_DUMMY_TRIGGER, true); + } + + void HandleSchoolDamage(SpellEffIndex /*effIndex*/) + { + if (!GetCaster() || !GetHitUnit() || _spawned) + { + return; + } + + if (InstanceScript* instance = GetCaster()->GetInstanceScript()) + { + if (Creature* sarth = ObjectAccessor::GetCreature(*GetHitUnit(), instance->GetGuidData(DATA_SARTHARION))) + { + sarth->AI()->SetData(DATA_VOLCANO_BLOWS, GetHitUnit()->GetGUID().GetCounter()); + sarth->CastSpell(GetHitUnit(), SPELL_LAVA_STRIKE_SUMMON, true); + _spawned = true; + } + } + } + + void Register() override + { + if (m_scriptSpellId == SPELL_LAVA_STRIKE_DUMMY) + { + OnEffectHitTarget += SpellEffectFn(spell_sartharion_lava_strike::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + else + { + OnEffectHitTarget += SpellEffectFn(spell_sartharion_lava_strike::HandleSchoolDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + } + } + +private: + bool _spawned; +}; + +// 57491 - Flame Tsunami +class spell_obsidian_sanctum_flame_tsunami : public SpellScript +{ + PrepareSpellScript(spell_obsidian_sanctum_flame_tsunami); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_FLAME_TSUNAMI_LEAP }); + } + + void HandleHit(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + { + if (!target->HasAura(SPELL_FLAME_TSUNAMI_LEAP)) + { + target->CastSpell(target, SPELL_FLAME_TSUNAMI_LEAP, true); + bool isFacingSouth = std::fabs(GetCaster()->GetOrientation() - M_PI) < M_PI / 4; + target->KnockbackFrom(isFacingSouth ? 3283.44f : 3208.44f , target->GetPositionY(), 12.5f, 9.0f); + } + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_obsidian_sanctum_flame_tsunami::HandleHit, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + } +}; + +// 60241 - Flame Tsunami +class spell_obsidian_sanctum_flame_tsunami_leap : public SpellScript +{ + PrepareSpellScript(spell_obsidian_sanctum_flame_tsunami_leap); + + void HandleLeapBack(SpellEffIndex effIndex) + { + PreventHitEffect(effIndex); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_obsidian_sanctum_flame_tsunami_leap::HandleLeapBack, EFFECT_0, SPELL_EFFECT_LEAP_BACK); } }; @@ -1581,7 +1625,7 @@ void AddSC_boss_sartharion() new boss_sartharion_tenebron(); new boss_sartharion_vesperon(); new npc_twilight_summon(); - - new spell_sartharion_lava_strike(); + RegisterSpellScript(spell_sartharion_lava_strike); + RegisterSpellScript(spell_obsidian_sanctum_flame_tsunami); + RegisterSpellScript(spell_obsidian_sanctum_flame_tsunami_leap); } - diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp index 035d4bf34..901d3af98 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp @@ -555,6 +555,11 @@ public: BossAI::AttackStart(target); } + void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER) override + { + CreatureAI::EnterEvadeMode(why); + } + void MoveInLineOfSight(Unit* /*who*/) override {} bool CanAIAttack(Unit const* target) const override diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp index 27d64a306..3374fad99 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp @@ -1192,68 +1192,51 @@ public: } }; -class spell_algalon_phase_punch : public SpellScriptLoader +class spell_algalon_phase_punch_aura : public AuraScript { -public: - spell_algalon_phase_punch() : SpellScriptLoader("spell_algalon_phase_punch") { } + PrepareAuraScript(spell_algalon_phase_punch_aura); - class spell_algalon_phase_punch_AuraScript : public AuraScript + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareAuraScript(spell_algalon_phase_punch_AuraScript); + return ValidateSpellInfo(PhasePunchAlphaId); + } - void HandlePeriodic(AuraEffect const* /*aurEff*/) - { - PreventDefaultAction(); - if (GetStackAmount() != 1) - GetTarget()->RemoveAurasDueToSpell(PhasePunchAlphaId[GetStackAmount() - 2]); - GetTarget()->CastSpell(GetTarget(), PhasePunchAlphaId[GetStackAmount() - 1], TRIGGERED_FULL_MASK); - if (GetStackAmount() == 5) - Remove(AURA_REMOVE_BY_DEFAULT); - } - - void OnRemove(AuraEffect const*, AuraEffectHandleModes) - { - if (GetStackAmount() != 5) - GetTarget()->RemoveAurasDueToSpell(PhasePunchAlphaId[GetStackAmount() - 1]); - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_phase_punch_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); - OnEffectRemove += AuraEffectRemoveFn(spell_algalon_phase_punch_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override + void HandlePeriodic(AuraEffect const* /*aurEff*/) { - return new spell_algalon_phase_punch_AuraScript(); + PreventDefaultAction(); + if (GetStackAmount() != 1) + GetTarget()->RemoveAurasDueToSpell(PhasePunchAlphaId[GetStackAmount() - 2]); + GetTarget()->CastSpell(GetTarget(), PhasePunchAlphaId[GetStackAmount() - 1], TRIGGERED_FULL_MASK); + if (GetStackAmount() == 5) + Remove(AURA_REMOVE_BY_DEFAULT); + } + + void OnRemove(AuraEffect const*, AuraEffectHandleModes) + { + if (GetStackAmount() != 5) + GetTarget()->RemoveAurasDueToSpell(PhasePunchAlphaId[GetStackAmount() - 1]); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_phase_punch_aura::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + OnEffectRemove += AuraEffectRemoveFn(spell_algalon_phase_punch_aura::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); } }; -class spell_algalon_collapse : public SpellScriptLoader +class spell_algalon_collapse_aura : public AuraScript { -public: - spell_algalon_collapse() : SpellScriptLoader("spell_algalon_collapse") { } + PrepareAuraScript(spell_algalon_collapse_aura); - class spell_algalon_collapse_AuraScript : public AuraScript + void HandlePeriodic(AuraEffect const* /*aurEff*/) { - PrepareAuraScript(spell_algalon_collapse_AuraScript); + PreventDefaultAction(); + Unit::DealDamage(GetTarget(), GetTarget(), GetTarget()->CountPctFromMaxHealth(1), nullptr, NODAMAGE); + } - void HandlePeriodic(AuraEffect const* /*aurEff*/) - { - PreventDefaultAction(); - Unit::DealDamage(GetTarget(), GetTarget(), GetTarget()->CountPctFromMaxHealth(1), nullptr, NODAMAGE); - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_collapse_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); - } - }; - - AuraScript* GetAuraScript() const override + void Register() override { - return new spell_algalon_collapse_AuraScript(); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_collapse_aura::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); } }; @@ -1266,172 +1249,123 @@ public: } }; -class spell_algalon_trigger_3_adds : public SpellScriptLoader +class spell_algalon_trigger_3_adds : public SpellScript { -public: - spell_algalon_trigger_3_adds() : SpellScriptLoader("spell_algalon_trigger_3_adds") { } + PrepareSpellScript(spell_algalon_trigger_3_adds); - class spell_algalon_trigger_3_adds_SpellScript : public SpellScript + void SelectTarget(std::list& targets) { - PrepareSpellScript(spell_algalon_trigger_3_adds_SpellScript); + targets.remove_if(ActiveConstellationFilter()); + } - void SelectTarget(std::list& targets) - { - targets.remove_if(ActiveConstellationFilter()); - } - - void HandleDummyEffect(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); - Creature* target = GetHitCreature(); - if (!target) - return; - - target->AI()->DoAction(ACTION_ACTIVATE_STAR); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_algalon_trigger_3_adds_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); - OnEffectHitTarget += SpellEffectFn(spell_algalon_trigger_3_adds_SpellScript::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const override + void HandleDummyEffect(SpellEffIndex effIndex) { - return new spell_algalon_trigger_3_adds_SpellScript(); + PreventHitDefaultEffect(effIndex); + Creature* target = GetHitCreature(); + if (!target) + return; + + target->AI()->DoAction(ACTION_ACTIVATE_STAR); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_algalon_trigger_3_adds::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnEffectHitTarget += SpellEffectFn(spell_algalon_trigger_3_adds::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY); } }; -class spell_algalon_cosmic_smash_damage : public SpellScriptLoader +class spell_algalon_cosmic_smash_damage : public SpellScript { -public: - spell_algalon_cosmic_smash_damage() : SpellScriptLoader("spell_algalon_cosmic_smash_damage") { } + PrepareSpellScript(spell_algalon_cosmic_smash_damage); - class spell_algalon_cosmic_smash_damage_SpellScript : public SpellScript + void RecalculateDamage() { - PrepareSpellScript(spell_algalon_cosmic_smash_damage_SpellScript); + if (!GetExplTargetDest() || !GetHitUnit()) + return; - void RecalculateDamage() - { - if (!GetExplTargetDest() || !GetHitUnit()) - return; + float distance = GetHitUnit()->GetDistance2d(GetExplTargetDest()->GetPositionX(), GetExplTargetDest()->GetPositionY()); + if (distance >= 10.0f) + SetHitDamage(int32(float(GetHitDamage()) / distance)); + else if (distance > 6.0f) + SetHitDamage(int32(float(GetHitDamage()) / distance) * 2); + } - float distance = GetHitUnit()->GetDistance2d(GetExplTargetDest()->GetPositionX(), GetExplTargetDest()->GetPositionY()); - if (distance >= 10.0f) - SetHitDamage(int32(float(GetHitDamage()) / distance)); - else if (distance > 6.0f) - SetHitDamage(int32(float(GetHitDamage()) / distance) * 2); - } - - void Register() override - { - OnHit += SpellHitFn(spell_algalon_cosmic_smash_damage_SpellScript::RecalculateDamage); - } - }; - - SpellScript* GetSpellScript() const override + void Register() override { - return new spell_algalon_cosmic_smash_damage_SpellScript(); + OnHit += SpellHitFn(spell_algalon_cosmic_smash_damage::RecalculateDamage); } }; -class spell_algalon_big_bang : public SpellScriptLoader +class spell_algalon_big_bang : public SpellScript { -public: - spell_algalon_big_bang() : SpellScriptLoader("spell_algalon_big_bang") { } + PrepareSpellScript(spell_algalon_big_bang); - class spell_algalon_big_bang_SpellScript : public SpellScript + bool Load() override { - PrepareSpellScript(spell_algalon_big_bang_SpellScript); + _targetCount = 0; + return true; + } - bool Load() override - { - _targetCount = 0; - return true; - } - - void CountTargets(std::list& targets) - { - _targetCount = targets.size(); - } - - void CheckTargets() - { - Unit* caster = GetCaster(); - if (!_targetCount && caster && caster->GetAI()) - caster->GetAI()->DoAction(ACTION_ASCEND); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_algalon_big_bang_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - AfterCast += SpellCastFn(spell_algalon_big_bang_SpellScript::CheckTargets); - } - - uint32 _targetCount; - }; - - SpellScript* GetSpellScript() const override + void CountTargets(std::list& targets) { - return new spell_algalon_big_bang_SpellScript(); + _targetCount = targets.size(); + } + + void CheckTargets() + { + Unit* caster = GetCaster(); + if (!_targetCount && caster && caster->GetAI()) + caster->GetAI()->DoAction(ACTION_ASCEND); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_algalon_big_bang::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + AfterCast += SpellCastFn(spell_algalon_big_bang::CheckTargets); + } + +private: + uint32 _targetCount; +}; + +class spell_algalon_remove_phase_aura : public AuraScript +{ + PrepareAuraScript(spell_algalon_remove_phase_aura); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_BLACK_HOLE_DAMAGE }); + } + + void HandlePeriodic(AuraEffect const* /*aurEff*/) + { + PreventDefaultAction(); + GetTarget()->RemoveAurasByType(SPELL_AURA_PHASE); + GetTarget()->RemoveAurasDueToSpell(SPELL_BLACK_HOLE_DAMAGE); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_remove_phase_aura::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); } }; -class spell_algalon_remove_phase : public SpellScriptLoader +class spell_algalon_supermassive_fail : public SpellScript { -public: - spell_algalon_remove_phase() : SpellScriptLoader("spell_algalon_remove_phase") { } + PrepareSpellScript(spell_algalon_supermassive_fail); - class spell_algalon_remove_phase_AuraScript : public AuraScript + void RecalculateDamage() { - PrepareAuraScript(spell_algalon_remove_phase_AuraScript); + if (!GetHitPlayer()) + return; - void HandlePeriodic(AuraEffect const* /*aurEff*/) - { - PreventDefaultAction(); - GetTarget()->RemoveAurasByType(SPELL_AURA_PHASE); - GetTarget()->RemoveAurasDueToSpell(SPELL_BLACK_HOLE_DAMAGE); - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_remove_phase_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_algalon_remove_phase_AuraScript(); + GetHitPlayer()->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_CONDITION_NO_SPELL_HIT, GetSpellInfo()->Id, true); } -}; -class spell_algalon_supermassive_fail : public SpellScriptLoader -{ -public: - spell_algalon_supermassive_fail() : SpellScriptLoader("spell_algalon_supermassive_fail") { } - - class spell_algalon_supermassive_fail_SpellScript : public SpellScript + void Register() override { - PrepareSpellScript(spell_algalon_supermassive_fail_SpellScript); - - void RecalculateDamage() - { - if (!GetHitPlayer()) - return; - - GetHitPlayer()->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_CONDITION_NO_SPELL_HIT, GetSpellInfo()->Id, true); - } - - void Register() override - { - OnHit += SpellHitFn(spell_algalon_supermassive_fail_SpellScript::RecalculateDamage); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_algalon_supermassive_fail_SpellScript(); + OnHit += SpellHitFn(spell_algalon_supermassive_fail::RecalculateDamage); } }; @@ -1470,13 +1404,13 @@ void AddSC_boss_algalon_the_observer() new go_celestial_planetarium_access(); // Spells - new spell_algalon_phase_punch(); - new spell_algalon_collapse(); - new spell_algalon_trigger_3_adds(); - new spell_algalon_cosmic_smash_damage(); - new spell_algalon_big_bang(); - new spell_algalon_remove_phase(); - new spell_algalon_supermassive_fail(); + RegisterSpellScript(spell_algalon_phase_punch_aura); + RegisterSpellScript(spell_algalon_collapse_aura); + RegisterSpellScript(spell_algalon_trigger_3_adds); + RegisterSpellScript(spell_algalon_cosmic_smash_damage); + RegisterSpellScript(spell_algalon_big_bang); + RegisterSpellScript(spell_algalon_remove_phase_aura); + RegisterSpellScript(spell_algalon_supermassive_fail); // Achievements new achievement_algalon_he_feeds_on_your_tears(); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp index c8f049a50..aaef1709b 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp @@ -844,94 +844,71 @@ public: }; }; -class spell_shield_of_runes : public SpellScriptLoader +class spell_shield_of_runes_aura : public AuraScript { -public: - spell_shield_of_runes() : SpellScriptLoader("spell_shield_of_runes") { } + PrepareAuraScript(spell_shield_of_runes_aura); - class spell_shield_of_runes_AuraScript : public AuraScript + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareAuraScript(spell_shield_of_runes_AuraScript); + return ValidateSpellInfo({ SPELL_SHIELD_OF_RUNES_BUFF }); + } - void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) - { - if (Unit* owner = GetUnitOwner()) - if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL && aurEff->GetAmount() <= 0) - owner->CastSpell(owner, SPELL_SHIELD_OF_RUNES_BUFF, false); - } - - void Register() override - { - AfterEffectRemove += AuraEffectRemoveFn(spell_shield_of_runes_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override + void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) { - return new spell_shield_of_runes_AuraScript(); + if (Unit* owner = GetUnitOwner()) + if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL && aurEff->GetAmount() <= 0) + owner->CastSpell(owner, SPELL_SHIELD_OF_RUNES_BUFF, false); + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_shield_of_runes_aura::OnRemove, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB, AURA_EFFECT_HANDLE_REAL); } }; -class spell_assembly_meltdown : public SpellScriptLoader +class spell_assembly_meltdown : public SpellScript { -public: - spell_assembly_meltdown() : SpellScriptLoader("spell_assembly_meltdown") { } + PrepareSpellScript(spell_assembly_meltdown); - class spell_assembly_meltdown_SpellScript : public SpellScript + void HandleInstaKill(SpellEffIndex /*effIndex*/) { - PrepareSpellScript(spell_assembly_meltdown_SpellScript); + if (InstanceScript* instance = GetCaster()->GetInstanceScript()) + if (Creature* Steelbreaker = ObjectAccessor::GetCreature(*GetCaster(), instance->GetGuidData(DATA_STEELBREAKER))) + Steelbreaker->AI()->DoAction(ACTION_ADD_CHARGE); + } - void HandleInstaKill(SpellEffIndex /*effIndex*/) - { - if (InstanceScript* instance = GetCaster()->GetInstanceScript()) - if (Creature* Steelbreaker = ObjectAccessor::GetCreature(*GetCaster(), instance->GetGuidData(DATA_STEELBREAKER))) - Steelbreaker->AI()->DoAction(ACTION_ADD_CHARGE); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_assembly_meltdown_SpellScript::HandleInstaKill, EFFECT_1, SPELL_EFFECT_INSTAKILL); - } - }; - - SpellScript* GetSpellScript() const override + void Register() override { - return new spell_assembly_meltdown_SpellScript(); + OnEffectHitTarget += SpellEffectFn(spell_assembly_meltdown::HandleInstaKill, EFFECT_1, SPELL_EFFECT_INSTAKILL); } }; -class spell_assembly_rune_of_summoning : public SpellScriptLoader +class spell_assembly_rune_of_summoning_aura : public AuraScript { -public: - spell_assembly_rune_of_summoning() : SpellScriptLoader("spell_assembly_rune_of_summoning") { } + PrepareAuraScript(spell_assembly_rune_of_summoning_aura); - class spell_assembly_rune_of_summoning_AuraScript : public AuraScript + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareAuraScript(spell_assembly_rune_of_summoning_AuraScript); + return ValidateSpellInfo({ SPELL_RUNE_OF_SUMMONING_SUMMON }); + } - void OnPeriodic(AuraEffect const* aurEff) - { - PreventDefaultAction(); - if (aurEff->GetTickNumber() % 2 == 0) - GetTarget()->CastSpell(GetTarget(), SPELL_RUNE_OF_SUMMONING_SUMMON, true, nullptr, aurEff, GetTarget()->IsSummon() ? GetTarget()->ToTempSummon()->GetSummonerGUID() : ObjectGuid::Empty); - } - - void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - if (TempSummon* summ = GetTarget()->ToTempSummon()) - summ->DespawnOrUnsummon(1); - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_assembly_rune_of_summoning_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); - OnEffectRemove += AuraEffectRemoveFn(spell_assembly_rune_of_summoning_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override + void OnPeriodic(AuraEffect const* aurEff) { - return new spell_assembly_rune_of_summoning_AuraScript(); + PreventDefaultAction(); + if (aurEff->GetTickNumber() % 2 == 0) + GetTarget()->CastSpell(GetTarget(), SPELL_RUNE_OF_SUMMONING_SUMMON, true, nullptr, aurEff, GetTarget()->IsSummon() ? GetTarget()->ToTempSummon()->GetSummonerGUID() : ObjectGuid::Empty); + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (TempSummon* summ = GetTarget()->ToTempSummon()) + summ->DespawnOrUnsummon(1); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_assembly_rune_of_summoning_aura::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + OnEffectRemove += AuraEffectRemoveFn(spell_assembly_rune_of_summoning_aura::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); } }; @@ -978,9 +955,9 @@ void AddSC_boss_assembly_of_iron() new boss_stormcaller_brundir(); new npc_assembly_lightning(); - new spell_shield_of_runes(); - new spell_assembly_meltdown(); - new spell_assembly_rune_of_summoning(); + RegisterSpellScript(spell_shield_of_runes_aura); + RegisterSpellScript(spell_assembly_meltdown); + RegisterSpellScript(spell_assembly_rune_of_summoning_aura); new achievement_assembly_of_iron("achievement_but_im_on_your_side", 0); new achievement_assembly_of_iron("achievement_assembly_steelbreaker", NPC_STEELBREAKER); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp index 904e01a8f..b1b8fb589 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp @@ -432,29 +432,18 @@ public: }; }; -class spell_auriaya_sentinel_blast : public SpellScriptLoader +class spell_auriaya_sentinel_blast : public SpellScript { -public: - spell_auriaya_sentinel_blast() : SpellScriptLoader("spell_auriaya_sentinel_blast") { } + PrepareSpellScript(spell_auriaya_sentinel_blast); - class spell_auriaya_sentinel_blast_SpellScript : public SpellScript + void FilterTargets(std::list& unitList) { - PrepareSpellScript(spell_auriaya_sentinel_blast_SpellScript); + unitList.remove_if(PlayerOrPetCheck()); + } - void FilterTargets(std::list& unitList) - { - unitList.remove_if(PlayerOrPetCheck()); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auriaya_sentinel_blast_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY); - } - }; - - SpellScript* GetSpellScript() const override + void Register() override { - return new spell_auriaya_sentinel_blast_SpellScript(); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auriaya_sentinel_blast::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY); } }; @@ -496,7 +485,7 @@ void AddSC_boss_auriaya() new npc_auriaya_sanctum_sentry(); new npc_auriaya_feral_defender(); - new spell_auriaya_sentinel_blast(); + RegisterSpellScript(spell_auriaya_sentinel_blast); new achievement_auriaya_crazy_cat_lady(); new achievement_auriaya_nine_lives(); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp index 02b7569b7..786ae2c21 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp @@ -1437,151 +1437,133 @@ public: } }; -class spell_load_into_catapult : public SpellScriptLoader +enum LoadIntoCataPult { - enum Spells + SPELL_PASSENGER_LOADED = 62340 +}; + +class spell_load_into_catapult_aura : public AuraScript +{ + PrepareAuraScript(spell_load_into_catapult_aura); + + bool Validate(SpellInfo const* /*spellInfo*/) override { - SPELL_PASSENGER_LOADED = 62340, - }; + return ValidateSpellInfo({ SPELL_PASSENGER_LOADED }); + } -public: - spell_load_into_catapult() : SpellScriptLoader("spell_load_into_catapult") { } - - class spell_load_into_catapult_AuraScript : public AuraScript + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - PrepareAuraScript(spell_load_into_catapult_AuraScript); + Unit* owner = GetOwner()->ToUnit(); + if (!owner) + return; - void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - Unit* owner = GetOwner()->ToUnit(); - if (!owner) - return; + owner->CastSpell(owner, SPELL_PASSENGER_LOADED, true); + } - owner->CastSpell(owner, SPELL_PASSENGER_LOADED, true); - } - - void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - Unit* owner = GetOwner()->ToUnit(); - if (!owner) - return; - - owner->RemoveAurasDueToSpell(SPELL_PASSENGER_LOADED); - } - - void Register() override - { - OnEffectApply += AuraEffectApplyFn(spell_load_into_catapult_AuraScript::OnApply, EFFECT_0, SPELL_AURA_CONTROL_VEHICLE, AURA_EFFECT_HANDLE_REAL); - OnEffectRemove += AuraEffectRemoveFn(spell_load_into_catapult_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_CONTROL_VEHICLE, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); - } - }; - - AuraScript* GetAuraScript() const override + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - return new spell_load_into_catapult_AuraScript(); + Unit* owner = GetOwner()->ToUnit(); + if (!owner) + return; + + owner->RemoveAurasDueToSpell(SPELL_PASSENGER_LOADED); + } + + void Register() override + { + OnEffectApply += AuraEffectApplyFn(spell_load_into_catapult_aura::OnApply, EFFECT_0, SPELL_AURA_CONTROL_VEHICLE, AURA_EFFECT_HANDLE_REAL); + OnEffectRemove += AuraEffectRemoveFn(spell_load_into_catapult_aura::OnRemove, EFFECT_0, SPELL_AURA_CONTROL_VEHICLE, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); } }; -class spell_auto_repair : public SpellScriptLoader +enum AutoRepair { - enum Spells + SPELL_AUTO_REPAIR = 62705, +}; + +class spell_auto_repair : public SpellScript +{ + PrepareSpellScript(spell_auto_repair); + + bool Validate(SpellInfo const* /*spellInfo*/) override { - SPELL_AUTO_REPAIR = 62705, - }; + return ValidateSpellInfo({ SPELL_AUTO_REPAIR }); + } -public: - spell_auto_repair() : SpellScriptLoader("spell_auto_repair") {} - - class spell_auto_repair_SpellScript : public SpellScript + void FilterTargets(std::list& targets) { - PrepareSpellScript(spell_auto_repair_SpellScript); + std::list tmplist; + for (std::list::iterator itr = targets.begin(); itr != targets.end(); ++itr) + if (!(*itr)->ToUnit()->HasAura(SPELL_AUTO_REPAIR)) + tmplist.push_back(*itr); - void FilterTargets(std::list& targets) - { - std::list tmplist; - for (std::list::iterator itr = targets.begin(); itr != targets.end(); ++itr) - if (!(*itr)->ToUnit()->HasAura(SPELL_AUTO_REPAIR)) - tmplist.push_back(*itr); + targets.clear(); + for (std::list::iterator itr = tmplist.begin(); itr != tmplist.end(); ++itr) + targets.push_back(*itr); + } - targets.clear(); - for (std::list::iterator itr = tmplist.begin(); itr != tmplist.end(); ++itr) - targets.push_back(*itr); - } - - void HandleScript(SpellEffIndex /*eff*/) - { - Vehicle* vehicle = GetHitUnit()->GetVehicleKit(); - if (!vehicle) - return; - - Unit* driver = vehicle->GetPassenger(0); - if (!driver) - return; - - //driver->TextEmote(VEHICLE_EMOTE_REPAIR, driver, true); // No source - - // Actually should/could use basepoints (100) for this spell effect as percentage of health, but oh well. - vehicle->GetBase()->SetFullHealth(); - - // Achievement - if (InstanceScript* instance = vehicle->GetBase()->GetInstanceScript()) - instance->SetData(DATA_UNBROKEN_ACHIEVEMENT, 0); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auto_repair_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_DEST_AREA_ENTRY); - OnEffectHitTarget += SpellEffectFn(spell_auto_repair_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; - - SpellScript* GetSpellScript() const override + void HandleScript(SpellEffIndex /*eff*/) { - return new spell_auto_repair_SpellScript(); + Vehicle* vehicle = GetHitUnit()->GetVehicleKit(); + if (!vehicle) + return; + + Unit* driver = vehicle->GetPassenger(0); + if (!driver) + return; + + //driver->TextEmote(VEHICLE_EMOTE_REPAIR, driver, true); // No source + + // Actually should/could use basepoints (100) for this spell effect as percentage of health, but oh well. + vehicle->GetBase()->SetFullHealth(); + + // Achievement + if (InstanceScript* instance = vehicle->GetBase()->GetInstanceScript()) + instance->SetData(DATA_UNBROKEN_ACHIEVEMENT, 0); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auto_repair::FilterTargets, EFFECT_ALL, TARGET_UNIT_DEST_AREA_ENTRY); + OnEffectHitTarget += SpellEffectFn(spell_auto_repair::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; -class spell_systems_shutdown : public SpellScriptLoader +class spell_systems_shutdown_aura : public AuraScript { -public: - spell_systems_shutdown() : SpellScriptLoader("spell_systems_shutdown") { } + PrepareAuraScript(spell_systems_shutdown_aura); - class spell_systems_shutdown_AuraScript : public AuraScript + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareAuraScript(spell_systems_shutdown_AuraScript); + return ValidateSpellInfo({ SPELL_GATHERING_SPEED }); + } - void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - Creature* owner = GetOwner()->ToCreature(); - if (!owner) - return; - - owner->SetControlled(true, UNIT_STATE_STUNNED); - owner->RemoveAurasDueToSpell(SPELL_GATHERING_SPEED); - if (Vehicle* veh = owner->GetVehicleKit()) - if (Unit* cannon = veh->GetPassenger(SEAT_CANNON)) - cannon->GetAI()->DoAction(ACTION_DELAY_CANNON); - } - - void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - Creature* owner = GetOwner()->ToCreature(); - if (!owner) - return; - - owner->SetControlled(false, UNIT_STATE_STUNNED); - } - - void Register() override - { - OnEffectApply += AuraEffectApplyFn(spell_systems_shutdown_AuraScript::OnApply, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL); - OnEffectRemove += AuraEffectRemoveFn(spell_systems_shutdown_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - return new spell_systems_shutdown_AuraScript(); + Creature* owner = GetOwner()->ToCreature(); + if (!owner) + return; + + owner->SetControlled(true, UNIT_STATE_STUNNED); + owner->RemoveAurasDueToSpell(SPELL_GATHERING_SPEED); + if (Vehicle* vehicle = owner->GetVehicleKit()) + if (Unit* cannon = vehicle->GetPassenger(SEAT_CANNON)) + cannon->GetAI()->DoAction(ACTION_DELAY_CANNON); + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Creature* owner = GetOwner()->ToCreature(); + if (!owner) + return; + + owner->SetControlled(false, UNIT_STATE_STUNNED); + } + + void Register() override + { + OnEffectApply += AuraEffectApplyFn(spell_systems_shutdown_aura::OnApply, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL); + OnEffectRemove += AuraEffectRemoveFn(spell_systems_shutdown_aura::OnRemove, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL); } }; @@ -1625,431 +1607,344 @@ public: } }; -class spell_pursue : public SpellScriptLoader +class spell_pursue : public SpellScript { -public: - spell_pursue() : SpellScriptLoader("spell_pursue") {} + PrepareSpellScript(spell_pursue); - class spell_pursue_SpellScript : public SpellScript + void FilterTargets(std::list& targets) { - PrepareSpellScript(spell_pursue_SpellScript); - - void FilterTargets(std::list& targets) + targets.remove_if(FlameLeviathanPursuedTargetSelector()); + if (targets.empty()) { - targets.remove_if(FlameLeviathanPursuedTargetSelector()); - if (targets.empty()) - { - if (Creature* caster = GetCaster()->ToCreature()) - caster->AI()->EnterEvadeMode(); - } - else - { - //! In the end, only one target should be selected - WorldObject* _target = Acore::Containers::SelectRandomContainerElement(targets); - targets.clear(); - if (_target) - targets.push_back(_target); - } + if (Creature* caster = GetCaster()->ToCreature()) + caster->AI()->EnterEvadeMode(); } - - void HandleScript(SpellEffIndex /*eff*/) + else { - Creature* target = GetHitCreature(); - Unit* caster = GetCaster(); - if (!target || !caster) - return; - - caster->GetThreatMgr().ResetAllThreat(); - caster->GetAI()->AttackStart(target); // Chase target - caster->AddThreat(target, 10000000.0f); + //! In the end, only one target should be selected + WorldObject* _target = Acore::Containers::SelectRandomContainerElement(targets); + targets.clear(); + if (_target) + targets.push_back(_target); } + } - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pursue_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY); - OnEffectHitTarget += SpellEffectFn(spell_pursue_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_APPLY_AURA); - } - }; - - SpellScript* GetSpellScript() const override + void HandleScript(SpellEffIndex /*eff*/) { - return new spell_pursue_SpellScript(); + Creature* target = GetHitCreature(); + Unit* caster = GetCaster(); + if (!target || !caster) + return; + + caster->GetThreatMgr().ResetAllThreat(); + caster->GetAI()->AttackStart(target); // Chase target + caster->AddThreat(target, 10000000.0f); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pursue::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_pursue::HandleScript, EFFECT_0, SPELL_EFFECT_APPLY_AURA); } }; -class spell_vehicle_throw_passenger : public SpellScriptLoader +class spell_vehicle_throw_passenger : public SpellScript { -public: - spell_vehicle_throw_passenger() : SpellScriptLoader("spell_vehicle_throw_passenger") {} + PrepareSpellScript(spell_vehicle_throw_passenger); - class spell_vehicle_throw_passenger_SpellScript : public SpellScript + void HandleScript() { - PrepareSpellScript(spell_vehicle_throw_passenger_SpellScript); - void HandleScript() - { - Spell* baseSpell = GetSpell(); - SpellCastTargets targets = baseSpell->m_targets; - if (Vehicle* vehicle = GetCaster()->GetVehicleKit()) - if (Unit* passenger = vehicle->GetPassenger(3)) + Spell* baseSpell = GetSpell(); + SpellCastTargets targets = baseSpell->m_targets; + if (Vehicle* vehicle = GetCaster()->GetVehicleKit()) + if (Unit* passenger = vehicle->GetPassenger(3)) + { + // use 99 because it is 3d search + std::list targetList; + Acore::WorldObjectSpellAreaTargetCheck check(99, GetExplTargetDest(), GetCaster(), GetCaster(), GetSpellInfo(), TARGET_CHECK_DEFAULT, nullptr); + Acore::WorldObjectListSearcher searcher(GetCaster(), targetList, check); + Cell::VisitAllObjects(GetCaster(), searcher, 99.0f); + float minDist = 99 * 99; + Unit* target = nullptr; + for (std::list::iterator itr = targetList.begin(); itr != targetList.end(); ++itr) { - // use 99 because it is 3d search - std::list targetList; - Acore::WorldObjectSpellAreaTargetCheck check(99, GetExplTargetDest(), GetCaster(), GetCaster(), GetSpellInfo(), TARGET_CHECK_DEFAULT, nullptr); - Acore::WorldObjectListSearcher searcher(GetCaster(), targetList, check); - Cell::VisitAllObjects(GetCaster(), searcher, 99.0f); - float minDist = 99 * 99; - Unit* target = nullptr; - for (std::list::iterator itr = targetList.begin(); itr != targetList.end(); ++itr) - { - if (Unit* unit = (*itr)->ToUnit()) - if (unit->GetEntry() == NPC_SEAT) - if (Vehicle* seat = unit->GetVehicleKit()) - if (!seat->GetPassenger(0)) - if (Unit* device = seat->GetPassenger(2)) - if (!device->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) + if (Unit* unit = (*itr)->ToUnit()) + if (unit->GetEntry() == NPC_SEAT) + if (Vehicle* seat = unit->GetVehicleKit()) + if (!seat->GetPassenger(0)) + if (Unit* device = seat->GetPassenger(2)) + if (!device->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) + { + float dist = unit->GetExactDistSq(targets.GetDstPos()); + if (dist < minDist) { - float dist = unit->GetExactDistSq(targets.GetDstPos()); - if (dist < minDist) - { - minDist = dist; - target = unit; - } + minDist = dist; + target = unit; } - } - if (target && target->IsWithinDist2d(targets.GetDstPos(), GetSpellInfo()->Effects[EFFECT_0].CalcRadius() * 2)) // now we use *2 because the location of the seat is not correct - { - passenger->ExitVehicle(); - passenger->EnterVehicle(target, 0); - } - else - { - passenger->ExitVehicle(); - float x, y, z; - targets.GetDstPos()->GetPosition(x, y, z); - passenger->GetMotionMaster()->MoveJump(x, y, z, targets.GetSpeedXY(), targets.GetSpeedZ()); - } + } } - } - - void Register() override - { - AfterCast += SpellCastFn(spell_vehicle_throw_passenger_SpellScript::HandleScript); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_vehicle_throw_passenger_SpellScript(); - } -}; - -class spell_tar_blaze : public SpellScriptLoader -{ -public: - spell_tar_blaze() : SpellScriptLoader("spell_tar_blaze") { } - - class spell_tar_blaze_AuraScript : public AuraScript - { - PrepareAuraScript(spell_tar_blaze_AuraScript); - - void OnPeriodic(AuraEffect const* aurEff) - { - GetUnitOwner()->CastSpell((Unit*)nullptr, GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, true); - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_tar_blaze_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_tar_blaze_AuraScript(); - } -}; - -class spell_vehicle_grab_pyrite : public SpellScriptLoader -{ -public: - spell_vehicle_grab_pyrite() : SpellScriptLoader("spell_vehicle_grab_pyrite") {} - - class spell_vehicle_grab_pyrite_SpellScript : public SpellScript - { - PrepareSpellScript(spell_vehicle_grab_pyrite_SpellScript); - void HandleScript(SpellEffIndex /*effIndex*/) - { - if (Unit* target = GetHitUnit()) - if (Unit* seat = GetCaster()->GetVehicleBase()) + if (target && target->IsWithinDist2d(targets.GetDstPos(), GetSpellInfo()->Effects[EFFECT_0].CalcRadius() * 2)) // now we use *2 because the location of the seat is not correct { - if (Vehicle* vSeat = seat->GetVehicleKit()) - if (Unit* pyrite = vSeat->GetPassenger(1)) - pyrite->ExitVehicle(); - - if (Unit* parent = seat->GetVehicleBase()) - { - GetCaster()->CastSpell(parent, 62496 /*SPELL_ADD_PYRITE*/, true); - target->CastSpell(seat, GetEffectValue()); - - if (target->GetTypeId() == TYPEID_UNIT) - target->ToCreature()->DespawnOrUnsummon(1300); - } + passenger->ExitVehicle(); + passenger->EnterVehicle(target, 0); } - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_vehicle_grab_pyrite_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_vehicle_grab_pyrite_SpellScript(); - } -}; - -class spell_vehicle_circuit_overload : public SpellScriptLoader -{ -public: - spell_vehicle_circuit_overload() : SpellScriptLoader("spell_vehicle_circuit_overload") { } - - class spell_vehicle_circuit_overload_AuraScript : public AuraScript - { - PrepareAuraScript(spell_vehicle_circuit_overload_AuraScript); - - void OnPeriodic(AuraEffect const* /*aurEff*/) - { - if (Unit* target = GetTarget()) - if (int(target->GetAppliedAuras().count(SPELL_OVERLOAD_CIRCUIT)) >= (target->GetMap()->Is25ManRaid() ? 4 : 2)) + else { - target->CastSpell(target, SPELL_SYSTEMS_SHUTDOWN, true); - target->RemoveAurasDueToSpell(SPELL_OVERLOAD_CIRCUIT); + passenger->ExitVehicle(); + float x, y, z; + targets.GetDstPos()->GetPosition(x, y, z); + passenger->GetMotionMaster()->MoveJump(x, y, z, targets.GetSpeedXY(), targets.GetSpeedZ()); } - } + } + } - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_vehicle_circuit_overload_AuraScript::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY); - } - }; - - AuraScript* GetAuraScript() const override + void Register() override { - return new spell_vehicle_circuit_overload_AuraScript(); + AfterCast += SpellCastFn(spell_vehicle_throw_passenger::HandleScript); } }; -class spell_orbital_supports : public SpellScriptLoader +class spell_tar_blaze_aura : public AuraScript { -public: - spell_orbital_supports() : SpellScriptLoader("spell_orbital_supports") { } + PrepareAuraScript(spell_tar_blaze_aura); - class spell_orbital_supports_AuraScript : public AuraScript + void OnPeriodic(AuraEffect const* aurEff) { - PrepareAuraScript(spell_orbital_supports_AuraScript); + GetUnitOwner()->CastSpell((Unit*)nullptr, GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, true); + } - bool CheckAreaTarget(Unit* target) - { - return target->GetEntry() == NPC_LEVIATHAN; - } - void Register() override - { - DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_orbital_supports_AuraScript::CheckAreaTarget); - } - }; - - AuraScript* GetAuraScript() const override + void Register() override { - return new spell_orbital_supports_AuraScript(); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_tar_blaze_aura::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); } }; -class spell_thorims_hammer : public SpellScriptLoader +enum VehicleGrabPyrite { -public: - spell_thorims_hammer() : SpellScriptLoader("spell_thorims_hammer") { } + SPELL_ADD_PYRITE = 62496 +}; - class spell_thorims_hammer_SpellScript : public SpellScript +class spell_vehicle_grab_pyrite : public SpellScript +{ + PrepareSpellScript(spell_vehicle_grab_pyrite); + + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareSpellScript(spell_thorims_hammer_SpellScript); + return ValidateSpellInfo({ SPELL_ADD_PYRITE }); + } - void RecalculateDamage(SpellEffIndex effIndex) - { - if (!GetHitUnit() || effIndex == EFFECT_1) - { - PreventHitDefaultEffect(effIndex); - return; - } - - float dist = GetHitUnit()->GetExactDist2d(GetCaster()); - if (dist <= 7.0f) - { - SetHitDamage(GetSpellInfo()->Effects[EFFECT_1].CalcValue()); - } - else - { - dist -= 6.0f; - SetHitDamage(int32(GetSpellInfo()->Effects[EFFECT_1].CalcValue() / std::max(dist, 1.0f))); - } - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_thorims_hammer_SpellScript::RecalculateDamage, EFFECT_ALL, SPELL_EFFECT_SCHOOL_DAMAGE); - } - }; - - SpellScript* GetSpellScript() const override + void HandleScript(SpellEffIndex /*effIndex*/) { - return new spell_thorims_hammer_SpellScript(); + if (Unit* target = GetHitUnit()) + if (Unit* seat = GetCaster()->GetVehicleBase()) + { + if (Vehicle* vehicle = seat->GetVehicleKit()) + if (Unit* pyrite = vehicle->GetPassenger(1)) + pyrite->ExitVehicle(); + + if (Unit* parent = seat->GetVehicleBase()) + { + GetCaster()->CastSpell(parent, SPELL_ADD_PYRITE, true); + target->CastSpell(seat, GetEffectValue()); + + if (target->GetTypeId() == TYPEID_UNIT) + target->ToCreature()->DespawnOrUnsummon(1300); + } + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_vehicle_grab_pyrite::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; -class spell_transitus_shield_beam : public SpellScriptLoader +class spell_vehicle_circuit_overload_aura : public AuraScript { -public: - spell_transitus_shield_beam() : SpellScriptLoader("spell_transitus_shield_beam") { } + PrepareAuraScript(spell_vehicle_circuit_overload_aura); - class spell_transitus_shield_beam_AuraScript : public AuraScript + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareAuraScript(spell_transitus_shield_beam_AuraScript); + return ValidateSpellInfo({ SPELL_SYSTEMS_SHUTDOWN }); + } - void HandleOnEffectApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) - { - Unit* caster = GetCaster(); - if (!caster) - { - return; - } - - Unit* target = GetTarget(); - - if (!target) - { - return; - } - - switch (aurEff->GetEffIndex()) - { - case EFFECT_0: - caster->AddAura(SPELL_TRANSITUS_SHIELD_IMPACT, target); - break; - } - } - - void HandleOnEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - Unit* caster = GetCaster(); - - if (!caster) - { - return; - } - - Unit* target = GetTarget(); - - if (target) - { - target->RemoveAurasDueToSpell(SPELL_TRANSITUS_SHIELD_IMPACT); - } - } - - void Register() - { - OnEffectApply += AuraEffectApplyFn(spell_transitus_shield_beam_AuraScript::HandleOnEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); - OnEffectRemove += AuraEffectRemoveFn(spell_transitus_shield_beam_AuraScript::HandleOnEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); - } - }; - - AuraScript* GetAuraScript() const override + void OnPeriodic(AuraEffect const* /*aurEff*/) { - return new spell_transitus_shield_beam_AuraScript(); + if (Unit* target = GetTarget()) + if (int(target->GetAppliedAuras().count(SPELL_OVERLOAD_CIRCUIT)) >= (target->GetMap()->Is25ManRaid() ? 4 : 2)) + { + target->CastSpell(target, SPELL_SYSTEMS_SHUTDOWN, true); + target->RemoveAurasDueToSpell(SPELL_OVERLOAD_CIRCUIT); + } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_vehicle_circuit_overload_aura::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY); } }; -class spell_shield_generator : public SpellScriptLoader +class spell_orbital_supports_aura : public AuraScript { -public: - spell_shield_generator() : SpellScriptLoader("spell_shield_generator") { } + PrepareAuraScript(spell_orbital_supports_aura); - class spell_shield_generator_AuraScript : public AuraScript + bool CheckAreaTarget(Unit* target) { - PrepareAuraScript(spell_shield_generator_AuraScript); - - uint32 absorbPct; - - bool Load() override - { - absorbPct = GetSpellInfo()->Effects[EFFECT_0].CalcValue(GetCaster()); - return true; - } - - void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) - { - // Set absorbtion amount to unlimited - amount = -1; - } - - void Absorb(AuraEffect* /*aurEff*/, DamageInfo& dmgInfo, uint32& absorbAmount) - { - absorbAmount = CalculatePct(dmgInfo.GetDamage(), absorbPct); - } - - void Register() override - { - DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_shield_generator_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB); - OnEffectAbsorb += AuraEffectAbsorbFn(spell_shield_generator_AuraScript::Absorb, EFFECT_0); - } - }; - - AuraScript* GetAuraScript() const override + return target->GetEntry() == NPC_LEVIATHAN; + } + void Register() override { - return new spell_shield_generator_AuraScript(); + DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_orbital_supports_aura::CheckAreaTarget); } }; -class spell_demolisher_ride_vehicle : public SpellScriptLoader +class spell_thorims_hammer : public SpellScript { -public: - spell_demolisher_ride_vehicle() : SpellScriptLoader("spell_demolisher_ride_vehicle") {} + PrepareSpellScript(spell_thorims_hammer); - class spell_demolisher_ride_vehicle_SpellScript : public SpellScript + void RecalculateDamage(SpellEffIndex effIndex) { - PrepareSpellScript(spell_demolisher_ride_vehicle_SpellScript); - - SpellCastResult CheckCast() + if (!GetHitUnit() || effIndex == EFFECT_1) { - if (GetCaster()->GetTypeId() != TYPEID_PLAYER) - return SPELL_CAST_OK; + PreventHitDefaultEffect(effIndex); + return; + } - Unit* target = this->GetExplTargetUnit(); - if (!target || target->GetEntry() != NPC_SALVAGED_DEMOLISHER) - return SPELL_FAILED_DONT_REPORT; + float dist = GetHitUnit()->GetExactDist2d(GetCaster()); + if (dist <= 7.0f) + { + SetHitDamage(GetSpellInfo()->Effects[EFFECT_1].CalcValue()); + } + else + { + dist -= 6.0f; + SetHitDamage(int32(GetSpellInfo()->Effects[EFFECT_1].CalcValue() / std::max(dist, 1.0f))); + } + } - Vehicle* veh = target->GetVehicleKit(); - if (veh && veh->GetPassenger(0)) - if (Unit* target2 = veh->GetPassenger(1)) - if (Vehicle* veh2 = target2->GetVehicleKit()) - { - if (!veh2->GetPassenger(0)) - target2->HandleSpellClick(GetCaster()); + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_thorims_hammer::RecalculateDamage, EFFECT_ALL, SPELL_EFFECT_SCHOOL_DAMAGE); + } +}; - return SPELL_FAILED_DONT_REPORT; - } +class spell_transitus_shield_beam_aura : public AuraScript +{ + PrepareAuraScript(spell_transitus_shield_beam_aura); + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_TRANSITUS_SHIELD_IMPACT }); + } + + void HandleOnEffectApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + Unit* caster = GetCaster(); + if (!caster) + { + return; + } + + Unit* target = GetTarget(); + + if (!target) + { + return; + } + + switch (aurEff->GetEffIndex()) + { + case EFFECT_0: + caster->AddAura(SPELL_TRANSITUS_SHIELD_IMPACT, target); + break; + } + } + + void HandleOnEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* caster = GetCaster(); + + if (!caster) + { + return; + } + + Unit* target = GetTarget(); + + if (target) + { + target->RemoveAurasDueToSpell(SPELL_TRANSITUS_SHIELD_IMPACT); + } + } + + void Register() override + { + OnEffectApply += AuraEffectApplyFn(spell_transitus_shield_beam_aura::HandleOnEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + OnEffectRemove += AuraEffectRemoveFn(spell_transitus_shield_beam_aura::HandleOnEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + } +}; + +class spell_shield_generator_aura : public AuraScript +{ + PrepareAuraScript(spell_shield_generator_aura); + + bool Load() override + { + _absorbPct = GetSpellInfo()->Effects[EFFECT_0].CalcValue(GetCaster()); + return true; + } + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + // Set absorbtion amount to unlimited + amount = -1; + } + + void Absorb(AuraEffect* /*aurEff*/, DamageInfo& dmgInfo, uint32& absorbAmount) + { + absorbAmount = CalculatePct(dmgInfo.GetDamage(), _absorbPct); + } + + void Register() override + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_shield_generator_aura::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB); + OnEffectAbsorb += AuraEffectAbsorbFn(spell_shield_generator_aura::Absorb, EFFECT_0); + } + +private: + uint32 _absorbPct; +}; + +class spell_demolisher_ride_vehicle : public SpellScript +{ + PrepareSpellScript(spell_demolisher_ride_vehicle); + + SpellCastResult CheckCast() + { + if (GetCaster()->GetTypeId() != TYPEID_PLAYER) return SPELL_CAST_OK; - } - void Register() override - { - OnCheckCast += SpellCheckCastFn(spell_demolisher_ride_vehicle_SpellScript::CheckCast); - } - }; + Unit* target = this->GetExplTargetUnit(); + if (!target || target->GetEntry() != NPC_SALVAGED_DEMOLISHER) + return SPELL_FAILED_DONT_REPORT; - SpellScript* GetSpellScript() const override + Vehicle* vehicle = target->GetVehicleKit(); + if (vehicle && vehicle->GetPassenger(0)) + if (Unit* target2 = vehicle->GetPassenger(1)) + if (Vehicle* vehicle2 = target2->GetVehicleKit()) + { + if (!vehicle2->GetPassenger(0)) + target2->HandleSpellClick(GetCaster()); + + return SPELL_FAILED_DONT_REPORT; + } + + return SPELL_CAST_OK; + } + + void Register() override { - return new spell_demolisher_ride_vehicle_SpellScript(); + OnCheckCast += SpellCheckCastFn(spell_demolisher_ride_vehicle::CheckCast); } }; @@ -2143,19 +2038,19 @@ void AddSC_boss_flame_leviathan() new go_ulduar_tower(); // Spells - new spell_load_into_catapult(); - new spell_auto_repair(); - new spell_systems_shutdown(); - new spell_pursue(); - new spell_vehicle_throw_passenger(); - new spell_tar_blaze(); - new spell_vehicle_grab_pyrite(); - new spell_vehicle_circuit_overload(); - new spell_orbital_supports(); - new spell_thorims_hammer(); - new spell_transitus_shield_beam(); - new spell_shield_generator(); - new spell_demolisher_ride_vehicle(); + RegisterSpellScript(spell_load_into_catapult_aura); + RegisterSpellScript(spell_auto_repair); + RegisterSpellScript(spell_systems_shutdown_aura); + RegisterSpellScript(spell_pursue); + RegisterSpellScript(spell_vehicle_throw_passenger); + RegisterSpellScript(spell_tar_blaze_aura); + RegisterSpellScript(spell_vehicle_grab_pyrite); + RegisterSpellScript(spell_vehicle_circuit_overload_aura); + RegisterSpellScript(spell_orbital_supports_aura); + RegisterSpellScript(spell_thorims_hammer); + RegisterSpellScript(spell_transitus_shield_beam_aura); + RegisterSpellScript(spell_shield_generator_aura); + RegisterSpellScript(spell_demolisher_ride_vehicle); // Achievements new achievement_flame_leviathan_towers("achievement_flame_leviathan_orbital_bombardment", 1); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp index 2fa09a604..4c562f651 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp @@ -472,173 +472,138 @@ public: }; }; -class spell_aura_of_despair : public SpellScriptLoader +class spell_aura_of_despair_aura : public AuraScript { -public: - spell_aura_of_despair() : SpellScriptLoader("spell_aura_of_despair") { } + PrepareAuraScript(spell_aura_of_despair_aura); - class spell_aura_of_despair_AuraScript : public AuraScript + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareAuraScript(spell_aura_of_despair_AuraScript) + return ValidateSpellInfo({ SPELL_AURA_OF_DESPAIR_2, SPELL_CORRUPTED_RAGE, SPELL_CORRUPTED_WISDOM }); + } - void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - if (Unit* caster = GetCaster()) - if (Unit* target = GetTarget()) - { - if (target->GetTypeId() != TYPEID_PLAYER) - return; - - target->CastSpell(target, SPELL_AURA_OF_DESPAIR_2, true); - if( target->HasSpell(SPELL_SHAMANISTIC_RAGE) ) - caster->CastSpell(target, SPELL_CORRUPTED_RAGE, true); - else if( target->HasSpell(SPELL_JUDGEMENTS_OF_THE_WISDOM_RANK_1) || target->HasSpell(SPELL_JUDGEMENTS_OF_THE_WISDOM_RANK_1 + 1) || target->HasSpell(SPELL_JUDGEMENTS_OF_THE_WISDOM_RANK_1 + 2) ) - caster->CastSpell(target, SPELL_CORRUPTED_WISDOM, true); - } - } - - void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) if (Unit* target = GetTarget()) { - target->RemoveAurasDueToSpell(SPELL_AURA_OF_DESPAIR_2); - target->RemoveAurasDueToSpell(SPELL_CORRUPTED_RAGE); - target->RemoveAurasDueToSpell(SPELL_CORRUPTED_WISDOM); + if (target->GetTypeId() != TYPEID_PLAYER) + return; + + target->CastSpell(target, SPELL_AURA_OF_DESPAIR_2, true); + if (target->HasSpell(SPELL_SHAMANISTIC_RAGE)) + caster->CastSpell(target, SPELL_CORRUPTED_RAGE, true); + else if (target->HasSpell(SPELL_JUDGEMENTS_OF_THE_WISDOM_RANK_1) || target->HasSpell(SPELL_JUDGEMENTS_OF_THE_WISDOM_RANK_1 + 1) || target->HasSpell(SPELL_JUDGEMENTS_OF_THE_WISDOM_RANK_1 + 2)) + caster->CastSpell(target, SPELL_CORRUPTED_WISDOM, true); } - } + } - void Register() override - { - OnEffectApply += AuraEffectApplyFn(spell_aura_of_despair_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PREVENT_REGENERATE_POWER, AURA_EFFECT_HANDLE_REAL); - AfterEffectRemove += AuraEffectRemoveFn(spell_aura_of_despair_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PREVENT_REGENERATE_POWER, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - return new spell_aura_of_despair_AuraScript(); + if (Unit* target = GetTarget()) + { + target->RemoveAurasDueToSpell(SPELL_AURA_OF_DESPAIR_2); + target->RemoveAurasDueToSpell(SPELL_CORRUPTED_RAGE); + target->RemoveAurasDueToSpell(SPELL_CORRUPTED_WISDOM); + } + } + + void Register() override + { + OnEffectApply += AuraEffectApplyFn(spell_aura_of_despair_aura::OnApply, EFFECT_0, SPELL_AURA_PREVENT_REGENERATE_POWER, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_aura_of_despair_aura::OnRemove, EFFECT_0, SPELL_AURA_PREVENT_REGENERATE_POWER, AURA_EFFECT_HANDLE_REAL); } }; -class spell_mark_of_the_faceless_periodic : public SpellScriptLoader +class spell_mark_of_the_faceless_periodic_aura : public AuraScript { -public: - spell_mark_of_the_faceless_periodic() : SpellScriptLoader("spell_mark_of_the_faceless_periodic") { } + PrepareAuraScript(spell_mark_of_the_faceless_periodic_aura); - class spell_mark_of_the_faceless_periodic_AuraScript : public AuraScript + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareAuraScript(spell_mark_of_the_faceless_periodic_AuraScript) - - void HandleEffectPeriodic(AuraEffect const* /*aurEff*/) - { - if (Unit* caster = GetCaster()) - if (Unit* target = GetTarget()) - if (target->GetMapId() == 603) - { - int32 dmg = 5000; - caster->CastCustomSpell(target, SPELL_MARK_OF_THE_FACELESS_EFFECT, 0, &dmg, 0, true); - } - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_mark_of_the_faceless_periodic_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_mark_of_the_faceless_periodic_AuraScript(); + return ValidateSpellInfo({ SPELL_MARK_OF_THE_FACELESS_EFFECT }); } -}; -class spell_mark_of_the_faceless_drainhealth : public SpellScriptLoader -{ -public: - spell_mark_of_the_faceless_drainhealth() : SpellScriptLoader("spell_mark_of_the_faceless_drainhealth") { } - - class spell_mark_of_the_faceless_drainhealth_SpellScript : public SpellScript + void HandleEffectPeriodic(AuraEffect const* /*aurEff*/) { - PrepareSpellScript(spell_mark_of_the_faceless_drainhealth_SpellScript); - - void FilterTargets(std::list& targets) - { - targets.remove(GetExplTargetUnit()); - if (targets.empty()) - Cancel(); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mark_of_the_faceless_drainhealth_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENEMY); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mark_of_the_faceless_drainhealth_SpellScript(); - } -}; - -class spell_saronite_vapors_dummy : public SpellScriptLoader -{ -public: - spell_saronite_vapors_dummy() : SpellScriptLoader("spell_saronite_vapors_dummy") { } - - class spell_saronite_vapors_dummy_AuraScript : public AuraScript - { - PrepareAuraScript(spell_saronite_vapors_dummy_AuraScript) - - void HandleAfterEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - if (Unit* caster = GetCaster()) - { - int32 damage = 100 * pow(2.0f, (float)GetStackAmount()); - caster->CastCustomSpell(GetTarget(), SPELL_SARONITE_VAPORS_DMG, &damage, nullptr, nullptr, true); - } - } - - void Register() override - { - AfterEffectApply += AuraEffectApplyFn(spell_saronite_vapors_dummy_AuraScript::HandleAfterEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_saronite_vapors_dummy_AuraScript(); - } -}; - -class spell_saronite_vapors_damage : public SpellScriptLoader -{ -public: - spell_saronite_vapors_damage() : SpellScriptLoader("spell_saronite_vapors_damage") { } - - class spell_saronite_vapors_damage_SpellScript : public SpellScript - { - PrepareSpellScript(spell_saronite_vapors_damage_SpellScript); - - void HandleAfterHit() - { - if (Unit* caster = GetCaster()) - if (GetHitDamage() > 2) + if (Unit* caster = GetCaster()) + if (Unit* target = GetTarget()) + if (target->GetMapId() == 603) { - int32 mana = GetHitDamage() / 2; - if (Unit* t = GetHitUnit()) - caster->CastCustomSpell(t, SPELL_SARONITE_VAPORS_ENERGIZE, &mana, nullptr, nullptr, true); + int32 dmg = 5000; + caster->CastCustomSpell(target, SPELL_MARK_OF_THE_FACELESS_EFFECT, 0, &dmg, 0, true); } - } + } - void Register() override - { - AfterHit += SpellHitFn(spell_saronite_vapors_damage_SpellScript::HandleAfterHit); - } - }; - - SpellScript* GetSpellScript() const override + void Register() override { - return new spell_saronite_vapors_damage_SpellScript(); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_mark_of_the_faceless_periodic_aura::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } +}; + +class spell_mark_of_the_faceless_drainhealth : public SpellScript +{ + PrepareSpellScript(spell_mark_of_the_faceless_drainhealth); + + void FilterTargets(std::list& targets) + { + targets.remove(GetExplTargetUnit()); + if (targets.empty()) + Cancel(); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mark_of_the_faceless_drainhealth::FilterTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENEMY); + } +}; + +class spell_saronite_vapors_dummy_aura : public AuraScript +{ + PrepareAuraScript(spell_saronite_vapors_dummy_aura); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_SARONITE_VAPORS_DMG }); + } + + void HandleAfterEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + { + int32 damage = 100 * pow(2.0f, (float)GetStackAmount()); + caster->CastCustomSpell(GetTarget(), SPELL_SARONITE_VAPORS_DMG, &damage, nullptr, nullptr, true); + } + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_saronite_vapors_dummy_aura::HandleAfterEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + } +}; + +class spell_saronite_vapors_damage : public SpellScript +{ + PrepareSpellScript(spell_saronite_vapors_damage); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_SARONITE_VAPORS_ENERGIZE }); + } + + void HandleAfterHit() + { + if (Unit* caster = GetCaster()) + if (GetHitDamage() > 2) + { + int32 mana = GetHitDamage() / 2; + if (Unit* target = GetHitUnit()) + caster->CastCustomSpell(target, SPELL_SARONITE_VAPORS_ENERGIZE, &mana, nullptr, nullptr, true); + } + } + + void Register() override + { + AfterHit += SpellHitFn(spell_saronite_vapors_damage::HandleAfterHit); } }; @@ -693,11 +658,11 @@ void AddSC_boss_vezax() new npc_ulduar_saronite_vapors(); new npc_ulduar_saronite_animus(); - new spell_aura_of_despair(); - new spell_mark_of_the_faceless_periodic(); - new spell_mark_of_the_faceless_drainhealth(); - new spell_saronite_vapors_dummy(); - new spell_saronite_vapors_damage(); + RegisterSpellScript(spell_aura_of_despair_aura); + RegisterSpellScript(spell_mark_of_the_faceless_periodic_aura); + RegisterSpellScript(spell_mark_of_the_faceless_drainhealth); + RegisterSpellScript(spell_saronite_vapors_dummy_aura); + RegisterSpellScript(spell_saronite_vapors_damage); new achievement_smell_saronite(); new achievement_shadowdodger(); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp index e7e21fa99..26ae69145 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp @@ -426,112 +426,112 @@ public: }; }; -class spell_ignis_scorch : public SpellScriptLoader +class spell_ignis_scorch_aura : public AuraScript { -public: - spell_ignis_scorch() : SpellScriptLoader("spell_ignis_scorch") { } + PrepareAuraScript(spell_ignis_scorch_aura); - class spell_ignis_scorch_AuraScript : public AuraScript + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareAuraScript(spell_ignis_scorch_AuraScript) + return ValidateSpellInfo( { SPELL_SCORCHED_GROUND_10, SPELL_SCORCHED_GROUND_25 }); + } - void HandleEffectPeriodic(AuraEffect const* aurEff) - { - if (aurEff->GetTotalTicks() >= 0 && aurEff->GetTickNumber() == uint32(aurEff->GetTotalTicks())) - if (Unit* c = GetCaster()) - if (Creature* s = c->SummonCreature(NPC_SCORCHED_GROUND, c->GetPositionX() + 20.0f * cos(c->GetOrientation()), c->GetPositionY() + 20.0f * std::sin(c->GetOrientation()), 361.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 30000)) - { - if (!s->FindNearestCreature(NPC_WATER_TRIGGER, 25.0f, true)) // must be away from the water - s->CastSpell(s, (aurEff->GetId() == 62546 ? SPELL_SCORCHED_GROUND_10 : SPELL_SCORCHED_GROUND_25), true); - } - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_ignis_scorch_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - } - }; - - AuraScript* GetAuraScript() const override + void HandleEffectPeriodic(AuraEffect const* aurEff) { - return new spell_ignis_scorch_AuraScript(); + if (aurEff->GetTotalTicks() >= 0 && aurEff->GetTickNumber() == uint32(aurEff->GetTotalTicks())) + if (Unit* caster = GetCaster()) + if (Creature* summon = caster->SummonCreature(NPC_SCORCHED_GROUND, caster->GetPositionX() + 20.0f * cos(caster->GetOrientation()), caster->GetPositionY() + 20.0f * std::sin(caster->GetOrientation()), 361.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 30000)) + { + if (!summon->FindNearestCreature(NPC_WATER_TRIGGER, 25.0f, true)) // must be away from the water + summon->CastSpell(summon, (aurEff->GetId() == SPELL_SCORCH_10 ? SPELL_SCORCHED_GROUND_10 : SPELL_SCORCHED_GROUND_25), true); + } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_ignis_scorch_aura::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); } }; -class spell_ignis_grab_initial : public SpellScriptLoader +class spell_ignis_grab_initial : public SpellScript { -public: - spell_ignis_grab_initial() : SpellScriptLoader("spell_ignis_grab_initial") { } + PrepareSpellScript(spell_ignis_grab_initial); - class spell_ignis_grab_initial_SpellScript : public SpellScript + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareSpellScript(spell_ignis_grab_initial_SpellScript); + return ValidateSpellInfo( { SPELL_GRAB_TRIGGERED }); + } - void HandleScript(SpellEffIndex /*effIndex*/) - { - if (Unit* t = GetHitUnit()) - t->CastSpell(t, SPELL_GRAB_TRIGGERED, true); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_ignis_grab_initial_SpellScript::HandleScript, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; - - SpellScript* GetSpellScript() const override + void HandleScript(SpellEffIndex /*effIndex*/) { - return new spell_ignis_grab_initial_SpellScript(); + if (Unit* target = GetHitUnit()) + target->CastSpell(target, SPELL_GRAB_TRIGGERED, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_ignis_grab_initial::HandleScript, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT); } }; -class spell_ignis_slag_pot : public SpellScriptLoader +enum SlagPot { -public: - spell_ignis_slag_pot() : SpellScriptLoader("spell_ignis_slag_pot") { } + SPELL_SLAG_POT_DAMAGE_1 = 65722, + SPELL_SLAG_POT_DAMAGE_2 = 65723, + SPELL_SCORCH_DAMAGE_1 = 62549, + SPELL_SCORCH_DAMAGE_2 = 63475, + SPELL_SLAG_IMBUED_1 = 62836, + SPELL_SLAG_IMBUED_2 = 63536 +}; - class spell_ignis_slag_pot_AuraScript : public AuraScript +class spell_ignis_slag_pot_aura : public AuraScript +{ + PrepareAuraScript(spell_ignis_slag_pot_aura); + + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareAuraScript(spell_ignis_slag_pot_AuraScript) - - void HandleEffectPeriodic(AuraEffect const* /*aurEff*/) - { - if (Unit* c = GetCaster()) - if (Unit* t = GetTarget()) - c->CastSpell(t, (GetId() == 62717 ? 65722 : 65723), true); - } - - void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - if (Unit* t = GetTarget()) + return ValidateSpellInfo( { - t->ApplySpellImmune(GetId(), IMMUNITY_ID, 62549, true); - t->ApplySpellImmune(GetId(), IMMUNITY_ID, 63475, true); - } - } + SPELL_SLAG_POT_DAMAGE_1, + SPELL_SLAG_POT_DAMAGE_2, + SPELL_SCORCH_DAMAGE_1, + SPELL_SCORCH_DAMAGE_2, + SPELL_SLAG_IMBUED_1, + SPELL_SLAG_IMBUED_2 + }); + } - void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - if (Unit* t = GetTarget()) - { - t->ApplySpellImmune(GetId(), IMMUNITY_ID, 62549, false); - t->ApplySpellImmune(GetId(), IMMUNITY_ID, 63475, false); - if (t->IsAlive()) - t->CastSpell(t, (GetId() == 62717 ? 62836 : 63536), true); - } - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_ignis_slag_pot_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); - OnEffectApply += AuraEffectApplyFn(spell_ignis_slag_pot_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); - AfterEffectRemove += AuraEffectRemoveFn(spell_ignis_slag_pot_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override + void HandleEffectPeriodic(AuraEffect const* /*aurEff*/) { - return new spell_ignis_slag_pot_AuraScript(); + if (Unit* caster = GetCaster()) + if (Unit* target = GetTarget()) + caster->CastSpell(target, (GetId() == SPELL_SLAG_POT_10 ? SPELL_SLAG_POT_DAMAGE_1 : SPELL_SLAG_POT_DAMAGE_2), true); + } + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* target = GetTarget()) + { + target->ApplySpellImmune(GetId(), IMMUNITY_ID, SPELL_SCORCH_DAMAGE_1, true); + target->ApplySpellImmune(GetId(), IMMUNITY_ID, SPELL_SCORCH_DAMAGE_2, true); + } + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* target = GetTarget()) + { + target->ApplySpellImmune(GetId(), IMMUNITY_ID, SPELL_SCORCH_DAMAGE_1, false); + target->ApplySpellImmune(GetId(), IMMUNITY_ID, SPELL_SCORCH_DAMAGE_2, false); + if (target->IsAlive()) + target->CastSpell(target, (GetId() == SPELL_SLAG_POT_10 ? SPELL_SLAG_IMBUED_1 : SPELL_SLAG_IMBUED_2), true); + } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_ignis_slag_pot_aura::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + OnEffectApply += AuraEffectApplyFn(spell_ignis_slag_pot_aura::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_ignis_slag_pot_aura::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); } }; @@ -552,8 +552,8 @@ void AddSC_boss_ignis() { new boss_ignis(); new npc_ulduar_iron_construct(); - new spell_ignis_scorch(); - new spell_ignis_grab_initial(); - new spell_ignis_slag_pot(); + RegisterSpellScript(spell_ignis_scorch_aura); + RegisterSpellScript(spell_ignis_grab_initial); + RegisterSpellScript(spell_ignis_slag_pot_aura); new achievement_ignis_shattered(); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp index 56fb1a902..34e213d04 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp @@ -718,156 +718,107 @@ private: Unit const* _victim; }; -class spell_ulduar_stone_grip_cast_target : public SpellScriptLoader +class spell_ulduar_stone_grip_cast_target : public SpellScript { -public: - spell_ulduar_stone_grip_cast_target() : SpellScriptLoader("spell_ulduar_stone_grip_cast_target") { } + PrepareSpellScript(spell_ulduar_stone_grip_cast_target); - class spell_ulduar_stone_grip_cast_target_SpellScript : public SpellScript + bool Load() override { - PrepareSpellScript(spell_ulduar_stone_grip_cast_target_SpellScript); + if (GetCaster()->GetTypeId() != TYPEID_UNIT) + return false; + return true; + } - bool Load() override - { - if (GetCaster()->GetTypeId() != TYPEID_UNIT) - return false; - return true; - } - - void FilterTargetsInitial(std::list& targets) - { - // Remove "main tank" and non-player targets - targets.remove_if (StoneGripTargetSelector(GetCaster()->ToCreature(), GetCaster()->GetVictim())); - // Maximum affected targets per difficulty mode - uint32 maxTargets = 1; - if (GetSpellInfo()->Id == 63981) - maxTargets = 3; - - // Return a random amount of targets based on maxTargets - while (maxTargets < targets.size()) - { - std::list::iterator itr = targets.begin(); - advance(itr, urand(0, targets.size() - 1)); - targets.erase(itr); - } - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ulduar_stone_grip_cast_target_SpellScript::FilterTargetsInitial, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY); - } - }; - - SpellScript* GetSpellScript() const override + void FilterTargetsInitial(std::list& targets) { - return new spell_ulduar_stone_grip_cast_target_SpellScript(); + // Remove "main tank" and non-player targets + targets.remove_if (StoneGripTargetSelector(GetCaster()->ToCreature(), GetCaster()->GetVictim())); + // Maximum affected targets per difficulty mode + uint32 maxTargets = 1; + if (GetSpellInfo()->Id == 63981) + maxTargets = 3; + + // Return a random amount of targets based on maxTargets + while (maxTargets < targets.size()) + { + std::list::iterator itr = targets.begin(); + advance(itr, urand(0, targets.size() - 1)); + targets.erase(itr); + } + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ulduar_stone_grip_cast_target::FilterTargetsInitial, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY); } }; -class spell_ulduar_stone_grip : public SpellScriptLoader +class spell_ulduar_stone_grip_aura : public AuraScript { -public: - spell_ulduar_stone_grip() : SpellScriptLoader("spell_ulduar_stone_grip") { } + PrepareAuraScript(spell_ulduar_stone_grip_aura); - class spell_ulduar_stone_grip_AuraScript : public AuraScript + void OnRemoveStun(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) { - PrepareAuraScript(spell_ulduar_stone_grip_AuraScript); + if (Player* owner = GetOwner()->ToPlayer()) + owner->RemoveAurasDueToSpell(aurEff->GetAmount()); + } - void OnRemoveStun(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) - { - if (Player* owner = GetOwner()->ToPlayer()) - owner->RemoveAurasDueToSpell(aurEff->GetAmount()); - } - - void Register() override - { - OnEffectRemove += AuraEffectRemoveFn(spell_ulduar_stone_grip_AuraScript::OnRemoveStun, EFFECT_2, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override + void Register() override { - return new spell_ulduar_stone_grip_AuraScript(); + OnEffectRemove += AuraEffectRemoveFn(spell_ulduar_stone_grip_aura::OnRemoveStun, EFFECT_2, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); } }; -class spell_ulduar_squeezed_lifeless : public SpellScriptLoader +class spell_ulduar_squeezed_lifeless : public SpellScript { -public: - spell_ulduar_squeezed_lifeless() : SpellScriptLoader("spell_ulduar_squeezed_lifeless") { } + PrepareSpellScript(spell_ulduar_squeezed_lifeless); - class spell_ulduar_squeezed_lifeless_SpellScript : public SpellScript + void HandleInstaKill(SpellEffIndex /*effIndex*/) { - PrepareSpellScript(spell_ulduar_squeezed_lifeless_SpellScript); + if (!GetHitPlayer() || !GetHitPlayer()->GetVehicle()) + return; - void HandleInstaKill(SpellEffIndex /*effIndex*/) - { - if (!GetHitPlayer() || !GetHitPlayer()->GetVehicle()) - return; + // Hack to set correct position is in _ExitVehicle() + GetHitPlayer()->ExitVehicle(); + } - // Hack to set correct position is in _ExitVehicle() - GetHitPlayer()->ExitVehicle(); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_ulduar_squeezed_lifeless_SpellScript::HandleInstaKill, EFFECT_1, SPELL_EFFECT_INSTAKILL); - } - }; - - SpellScript* GetSpellScript() const override + void Register() override { - return new spell_ulduar_squeezed_lifeless_SpellScript(); + OnEffectHitTarget += SpellEffectFn(spell_ulduar_squeezed_lifeless::HandleInstaKill, EFFECT_1, SPELL_EFFECT_INSTAKILL); } }; -class spell_kologarn_stone_shout : public SpellScriptLoader +class spell_kologarn_stone_shout : public SpellScript { -public: - spell_kologarn_stone_shout() : SpellScriptLoader("spell_kologarn_stone_shout") { } + PrepareSpellScript(spell_kologarn_stone_shout); - class spell_kologarn_stone_shout_AuraScript : public AuraScript + void FilterTargets(std::list& targets) { - PrepareAuraScript(spell_kologarn_stone_shout_AuraScript); - - void OnPeriodic(AuraEffect const* /*aurEff*/) - { - uint32 triggerSpellId = GetSpellInfo()->Effects[EFFECT_0].TriggerSpell; - if (Unit* caster = GetCaster()) - caster->CastSpell(caster, triggerSpellId, false); - } - - void Register() override - { - if (m_scriptSpellId == SPELL_STONE_SHOUT_10 || m_scriptSpellId == SPELL_STONE_SHOUT_25) - OnEffectPeriodic += AuraEffectPeriodicFn(spell_kologarn_stone_shout_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_kologarn_stone_shout_AuraScript(); + targets.remove_if (PlayerOrPetCheck()); } - class spell_kologarn_stone_shout_SpellScript : public SpellScript + void Register() override { - PrepareSpellScript(spell_kologarn_stone_shout_SpellScript); + if (m_scriptSpellId != SPELL_STONE_SHOUT_10 && m_scriptSpellId != SPELL_STONE_SHOUT_25) + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_kologarn_stone_shout::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } +}; - void FilterTargets(std::list& targets) - { - targets.remove_if (PlayerOrPetCheck()); - } +class spell_kologarn_stone_shout_aura : public AuraScript +{ + PrepareAuraScript(spell_kologarn_stone_shout_aura); - void Register() override - { - if (m_scriptSpellId != SPELL_STONE_SHOUT_10 && m_scriptSpellId != SPELL_STONE_SHOUT_25) - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_kologarn_stone_shout_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - } - }; - - SpellScript* GetSpellScript() const override + void OnPeriodic(AuraEffect const* /*aurEff*/) { - return new spell_kologarn_stone_shout_SpellScript(); + uint32 triggerSpellId = GetSpellInfo()->Effects[EFFECT_0].TriggerSpell; + if (Unit* caster = GetCaster()) + caster->CastSpell(caster, triggerSpellId, false); + } + + void Register() override + { + if (m_scriptSpellId == SPELL_STONE_SHOUT_10 || m_scriptSpellId == SPELL_STONE_SHOUT_25) + OnEffectPeriodic += AuraEffectPeriodicFn(spell_kologarn_stone_shout_aura::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); } }; @@ -928,10 +879,10 @@ void AddSC_boss_kologarn() RegisterUlduarCreatureAI(boss_kologarn_pit_kill_bunny); // Spells - new spell_ulduar_stone_grip_cast_target(); - new spell_ulduar_stone_grip(); - new spell_ulduar_squeezed_lifeless(); - new spell_kologarn_stone_shout(); + RegisterSpellScript(spell_ulduar_stone_grip_cast_target); + RegisterSpellScript(spell_ulduar_stone_grip_aura); + RegisterSpellScript(spell_ulduar_squeezed_lifeless); + RegisterSpellAndAuraScriptPair(spell_kologarn_stone_shout, spell_kologarn_stone_shout_aura); // Achievements new achievement_kologarn_looks_could_kill(); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp index 93c0de72f..90ada7fc1 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp @@ -2104,87 +2104,83 @@ public: }; }; -class spell_mimiron_rapid_burst : public SpellScriptLoader +class spell_mimiron_rapid_burst_aura : public AuraScript { -public: - spell_mimiron_rapid_burst() : SpellScriptLoader("spell_mimiron_rapid_burst") { } + PrepareAuraScript(spell_mimiron_rapid_burst_aura); - class spell_mimiron_rapid_burst_AuraScript : public AuraScript + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareAuraScript(spell_mimiron_rapid_burst_AuraScript) - - void HandleEffectPeriodic(AuraEffect const* aurEff) - { - if (Unit* c = GetCaster()) + return ValidateSpellInfo( { - uint32 id = ( c->GetMap()->Is25ManRaid() ? ((aurEff->GetTickNumber() % 2) ? SPELL_RAPID_BURST_DAMAGE_25_2 : SPELL_RAPID_BURST_DAMAGE_25_1) : ((aurEff->GetTickNumber() % 2) ? SPELL_RAPID_BURST_DAMAGE_10_2 : SPELL_RAPID_BURST_DAMAGE_10_1) ); - c->CastSpell((Unit*)nullptr, id, true); - } - } + SPELL_RAPID_BURST_DAMAGE_10_1, + SPELL_RAPID_BURST_DAMAGE_10_2, + SPELL_RAPID_BURST_DAMAGE_25_1, + SPELL_RAPID_BURST_DAMAGE_25_2 + }); + } - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_mimiron_rapid_burst_AuraScript::HandleEffectPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY); - } - }; - - AuraScript* GetAuraScript() const override + void HandleEffectPeriodic(AuraEffect const* aurEff) { - return new spell_mimiron_rapid_burst_AuraScript(); + if (Unit* caster = GetCaster()) + { + uint32 id = (caster->GetMap()->Is25ManRaid() ? ((aurEff->GetTickNumber() % 2) ? SPELL_RAPID_BURST_DAMAGE_25_2 : SPELL_RAPID_BURST_DAMAGE_25_1) : ((aurEff->GetTickNumber() % 2) ? SPELL_RAPID_BURST_DAMAGE_10_2 : SPELL_RAPID_BURST_DAMAGE_10_1)); + caster->CastSpell((Unit*)nullptr, id, true); + } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_mimiron_rapid_burst_aura::HandleEffectPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY); } }; -class spell_mimiron_p3wx2_laser_barrage : public SpellScriptLoader +enum p3wx2LaserBarrage { -public: - spell_mimiron_p3wx2_laser_barrage() : SpellScriptLoader("spell_mimiron_p3wx2_laser_barrage") { } + SPELL_P3WX2_LASER_BARRAGE_1 = 63297, + SPELL_P3WX2_LASER_BARRAGE_2 = 64042 +}; - class spell_mimiron_p3wx2_laser_barrage_AuraScript : public AuraScript +class spell_mimiron_p3wx2_laser_barrage_aura : public AuraScript +{ + PrepareAuraScript(spell_mimiron_p3wx2_laser_barrage_aura); + + bool Load() override { - PrepareAuraScript(spell_mimiron_p3wx2_laser_barrage_AuraScript) - - uint32 lastMSTime; - float lastOrientation; - - bool Load() override - { - lastMSTime = GameTime::GetGameTimeMS().count(); - lastOrientation = -1.0f; - return true; - } - - void HandleEffectPeriodic(AuraEffect const* /*aurEff*/) - { - if (Unit* c = GetCaster()) - { - if (c->GetTypeId() != TYPEID_UNIT) - return; - uint32 diff = getMSTimeDiff(lastMSTime, GameTime::GetGameTimeMS().count()); - if (lastOrientation == -1.0f) - { - lastOrientation = (c->ToCreature()->AI()->GetData(0) * 2 * M_PI) / 100.0f; - diff = 0; - } - float new_o = Position::NormalizeOrientation(lastOrientation - (M_PI / 60) * (diff / 250.0f)); - lastMSTime = GameTime::GetGameTimeMS().count(); - lastOrientation = new_o; - c->SetFacingTo(new_o); - - c->CastSpell((Unit*)nullptr, 63297, true); - c->CastSpell((Unit*)nullptr, 64042, true); - } - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_mimiron_p3wx2_laser_barrage_AuraScript::HandleEffectPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_mimiron_p3wx2_laser_barrage_AuraScript(); + _lastMSTime = GameTime::GetGameTimeMS().count(); + _lastOrientation = -1.0f; + return true; } + + void HandleEffectPeriodic(AuraEffect const* /*aurEff*/) + { + if (Unit* caster = GetCaster()) + { + if (caster->GetTypeId() != TYPEID_UNIT) + return; + uint32 diff = getMSTimeDiff(_lastMSTime, GameTime::GetGameTimeMS().count()); + if (_lastOrientation == -1.0f) + { + _lastOrientation = (caster->ToCreature()->AI()->GetData(0) * 2 * M_PI) / 100.0f; + diff = 0; + } + float new_o = Position::NormalizeOrientation(_lastOrientation - (M_PI / 60) * (diff / 250.0f)); + _lastMSTime = GameTime::GetGameTimeMS().count(); + _lastOrientation = new_o; + caster->SetFacingTo(new_o); + + caster->CastSpell((Unit*)nullptr, SPELL_P3WX2_LASER_BARRAGE_1, true); + caster->CastSpell((Unit*)nullptr, SPELL_P3WX2_LASER_BARRAGE_2, true); + } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_mimiron_p3wx2_laser_barrage_aura::HandleEffectPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + +private: + uint32 _lastMSTime; + float _lastOrientation; }; class go_ulduar_do_not_push_this_button : public GameObjectScript @@ -2518,8 +2514,8 @@ void AddSC_boss_mimiron() new npc_ulduar_mimiron_rocket(); new npc_ulduar_magnetic_core(); new npc_ulduar_bot_summon_trigger(); - new spell_mimiron_rapid_burst(); - new spell_mimiron_p3wx2_laser_barrage(); + RegisterSpellScript(spell_mimiron_rapid_burst_aura); + RegisterSpellScript(spell_mimiron_p3wx2_laser_barrage_aura); new go_ulduar_do_not_push_this_button(); new npc_ulduar_flames_initial(); new npc_ulduar_flames_spread(); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp index cf62d6241..f9e6743a7 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp @@ -1729,59 +1729,37 @@ public: } }; -class spell_thorim_lightning_pillar_P2 : public SpellScriptLoader +class spell_thorim_lightning_pillar_P2_aura : public AuraScript { -public: - spell_thorim_lightning_pillar_P2() : SpellScriptLoader("spell_thorim_lightning_pillar_P2") { } + PrepareAuraScript(spell_thorim_lightning_pillar_P2_aura); - class spell_thorim_lightning_pillar_P2_AuraScript : public AuraScript + void OnPeriodic(AuraEffect const* aurEff) { - PrepareAuraScript(spell_thorim_lightning_pillar_P2_AuraScript); + PreventDefaultAction(); + if (Unit* caster = GetCaster()) + GetUnitOwner()->CastSpell(caster, GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, true); + } - void OnPeriodic(AuraEffect const* aurEff) - { - PreventDefaultAction(); - if (Unit* caster = GetCaster()) - GetUnitOwner()->CastSpell(caster, GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, true); - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_thorim_lightning_pillar_P2_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - } - }; - - AuraScript* GetAuraScript() const override + void Register() override { - return new spell_thorim_lightning_pillar_P2_AuraScript(); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_thorim_lightning_pillar_P2_aura::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); } }; -class spell_thorim_trash_impale : public SpellScriptLoader +class spell_thorim_trash_impale_aura : public AuraScript { -public: - spell_thorim_trash_impale() : SpellScriptLoader("spell_thorim_trash_impale") { } + PrepareAuraScript(spell_thorim_trash_impale_aura); - class spell_thorim_trash_impale_AuraScript : public AuraScript + void OnPeriodic(AuraEffect const* /*aurEff*/) { - PrepareAuraScript(spell_thorim_trash_impale_AuraScript); + // deals damage until target is healed above 90% + if (GetUnitOwner()->HealthAbovePct(90)) + SetDuration(0); + } - void OnPeriodic(AuraEffect const* /*aurEff*/) - { - // deals damage until target is healed above 90% - if (GetUnitOwner()->HealthAbovePct(90)) - SetDuration(0); - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_thorim_trash_impale_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); - } - }; - - AuraScript* GetAuraScript() const override + void Register() override { - return new spell_thorim_trash_impale_AuraScript(); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_thorim_trash_impale_aura::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); } }; @@ -1838,8 +1816,8 @@ void AddSC_boss_thorim() new go_thorim_lever(); // Spells - new spell_thorim_lightning_pillar_P2(); - new spell_thorim_trash_impale(); + RegisterSpellScript(spell_thorim_lightning_pillar_P2_aura); + RegisterSpellScript(spell_thorim_trash_impale_aura); // Achievements new achievement_thorim_stand_in_the_lightning(); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp index 9168fa4b5..7a2fde768 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp @@ -857,191 +857,147 @@ public: }; // 62775 - Tympanic Tantrum -class spell_xt002_tympanic_tantrum : public SpellScriptLoader +class spell_xt002_tympanic_tantrum : public SpellScript { -public: - spell_xt002_tympanic_tantrum() : SpellScriptLoader("spell_xt002_tympanic_tantrum") { } + PrepareSpellScript(spell_xt002_tympanic_tantrum); - class spell_xt002_tympanic_tantrum_SpellScript : public SpellScript + void FilterTargets(std::list& targets) { - PrepareSpellScript(spell_xt002_tympanic_tantrum_SpellScript); + targets.remove_if(PlayerOrPetCheck()); + } - void FilterTargets(std::list& targets) - { - targets.remove_if(PlayerOrPetCheck()); - } - - void RecalculateDamage() - { - if (GetHitUnit()) - SetHitDamage(GetHitUnit()->CountPctFromMaxHealth(GetHitDamage())); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_xt002_tympanic_tantrum_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY); - OnHit += SpellHitFn(spell_xt002_tympanic_tantrum_SpellScript::RecalculateDamage); - } - }; - - SpellScript* GetSpellScript() const override + void RecalculateDamage() { - return new spell_xt002_tympanic_tantrum_SpellScript(); + if (GetHitUnit()) + SetHitDamage(GetHitUnit()->CountPctFromMaxHealth(GetHitDamage())); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_xt002_tympanic_tantrum::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY); + OnHit += SpellHitFn(spell_xt002_tympanic_tantrum::RecalculateDamage); } }; // 64234, 63024 - Gravity Bomb -class spell_xt002_gravity_bomb_aura : public SpellScriptLoader +enum GravityBomb { -public: - spell_xt002_gravity_bomb_aura() : SpellScriptLoader("spell_xt002_gravity_bomb_aura") { } + SPELL_GRAVTY_BOMB_10 = 63025 +}; - class spell_xt002_gravity_bomb_aura_AuraScript : public AuraScript +class spell_xt002_gravity_bomb : public SpellScript +{ + PrepareSpellScript(spell_xt002_gravity_bomb); + + void SelectTarget(std::list& targets) { - PrepareAuraScript(spell_xt002_gravity_bomb_aura_AuraScript); - - void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) - { - if (Player* player = GetOwner()->ToPlayer()) - if (Unit* xt002 = GetCaster()) - if (xt002->HasAura(aurEff->GetAmount())) // Heartbreak aura indicating hard mode - if (Creature* cr = xt002->SummonCreature(NPC_VOID_ZONE, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 180000)) - { - int32 damage = GetSpellInfo()->Id == 63025 ? 5000 : 7500; - cr->CastCustomSpell(cr, SPELL_VOID_ZONE_DAMAGE, &damage, 0, 0, true); - } - } - - void OnPeriodic(AuraEffect const* aurEff) - { - Unit* xt002 = GetCaster(); - if (!xt002) - return; - - Unit* owner = GetOwner()->ToUnit(); - if (!owner) - return; - - if (aurEff->GetAmount() >= int32(owner->GetHealth())) - if (xt002->GetAI()) - xt002->GetAI()->DoAction(DATA_XT002_GRAVITY_ACHIEV); - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_xt002_gravity_bomb_aura_AuraScript::OnPeriodic, EFFECT_2, SPELL_AURA_PERIODIC_DAMAGE); - AfterEffectRemove += AuraEffectRemoveFn(spell_xt002_gravity_bomb_aura_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_xt002_gravity_bomb_aura_AuraScript(); + if (Unit* victim = GetCaster()->GetVictim()) + targets.remove_if(Acore::ObjectGUIDCheck(victim->GetGUID(), true)); } - class spell_xt002_gravity_bomb_aura_SpellScript : public SpellScript + void Register() override { - PrepareSpellScript(spell_xt002_gravity_bomb_aura_SpellScript); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_xt002_gravity_bomb::SelectTarget, EFFECT_ALL, TARGET_UNIT_DEST_AREA_ENEMY); + } +}; - void SelectTarget(std::list& targets) - { - if (Unit* victim = GetCaster()->GetVictim()) - targets.remove_if(Acore::ObjectGUIDCheck(victim->GetGUID(), true)); - } +class spell_xt002_gravity_bomb_aura : public AuraScript +{ + PrepareAuraScript(spell_xt002_gravity_bomb_aura); - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_xt002_gravity_bomb_aura_SpellScript::SelectTarget, EFFECT_ALL, TARGET_UNIT_DEST_AREA_ENEMY); - } - }; - - SpellScript* GetSpellScript() const override + bool Validate(SpellInfo const* /*spellInfo*/) override { - return new spell_xt002_gravity_bomb_aura_SpellScript(); + return ValidateSpellInfo({ SPELL_VOID_ZONE_DAMAGE }); + } + + void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + if (Player* player = GetOwner()->ToPlayer()) + if (Unit* xt002 = GetCaster()) + if (xt002->HasAura(aurEff->GetAmount())) // Heartbreak aura indicating hard mode + if (Creature* creature = xt002->SummonCreature(NPC_VOID_ZONE, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 180000)) + { + int32 damage = GetSpellInfo()->Id == SPELL_GRAVTY_BOMB_10 ? 5000 : 7500; + creature->CastCustomSpell(creature, SPELL_VOID_ZONE_DAMAGE, &damage, 0, 0, true); + } + } + + void OnPeriodic(AuraEffect const* aurEff) + { + Unit* xt002 = GetCaster(); + if (!xt002) + return; + + Unit* owner = GetOwner()->ToUnit(); + if (!owner) + return; + + if (aurEff->GetAmount() >= int32(owner->GetHealth())) + if (xt002->GetAI()) + xt002->GetAI()->DoAction(DATA_XT002_GRAVITY_ACHIEV); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_xt002_gravity_bomb_aura::OnPeriodic, EFFECT_2, SPELL_AURA_PERIODIC_DAMAGE); + AfterEffectRemove += AuraEffectRemoveFn(spell_xt002_gravity_bomb_aura::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); } }; // 64233, 63025 - Gravity Bomb -class spell_xt002_gravity_bomb_damage : public SpellScriptLoader +class spell_xt002_gravity_bomb_damage : public SpellScript { -public: - spell_xt002_gravity_bomb_damage() : SpellScriptLoader("spell_xt002_gravity_bomb_damage") { } + PrepareSpellScript(spell_xt002_gravity_bomb_damage); - class spell_xt002_gravity_bomb_damage_SpellScript : public SpellScript + void HandleScript(SpellEffIndex /*eff*/) { - PrepareSpellScript(spell_xt002_gravity_bomb_damage_SpellScript); + Unit* caster = GetCaster(); + if (!caster) + return; - void HandleScript(SpellEffIndex /*eff*/) - { - Unit* caster = GetCaster(); - if (!caster) - return; + if (GetHitDamage() >= int32(GetHitUnit()->GetHealth())) + if (caster->GetAI()) + caster->GetAI()->DoAction(DATA_XT002_GRAVITY_ACHIEV); + } - if (GetHitDamage() >= int32(GetHitUnit()->GetHealth())) - if (caster->GetAI()) - caster->GetAI()->DoAction(DATA_XT002_GRAVITY_ACHIEV); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_xt002_gravity_bomb_damage_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); - } - }; - - SpellScript* GetSpellScript() const override + void Register() override { - return new spell_xt002_gravity_bomb_damage_SpellScript(); + OnEffectHitTarget += SpellEffectFn(spell_xt002_gravity_bomb_damage::HandleScript, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); } }; // 63018, 65121 - Searing Light -class spell_xt002_searing_light_spawn_life_spark : public SpellScriptLoader +class spell_xt002_searing_light_spawn_life_spark : public SpellScript { -public: - spell_xt002_searing_light_spawn_life_spark() : SpellScriptLoader("spell_xt002_searing_light_spawn_life_spark") { } + PrepareSpellScript(spell_xt002_searing_light_spawn_life_spark); - class spell_xt002_searing_light_spawn_life_spark_AuraScript : public AuraScript + void SelectTarget(std::list& targets) { - PrepareAuraScript(spell_xt002_searing_light_spawn_life_spark_AuraScript); - - void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) - { - if (Player* player = GetOwner()->ToPlayer()) - if (Unit* xt002 = GetCaster()) - if (xt002->HasAura(aurEff->GetAmount())) // Heartbreak aura indicating hard mode - xt002->SummonCreature(NPC_LIFE_SPARK, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 180000); - } - - void Register() override - { - OnEffectRemove += AuraEffectRemoveFn(spell_xt002_searing_light_spawn_life_spark_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_xt002_searing_light_spawn_life_spark_AuraScript(); + if (Unit* victim = GetCaster()->GetVictim()) + targets.remove_if(Acore::ObjectGUIDCheck(victim->GetGUID(), true)); } - class spell_xt002_searing_light_spawn_life_spark_SpellScript : public SpellScript + void Register() override { - PrepareSpellScript(spell_xt002_searing_light_spawn_life_spark_SpellScript); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_xt002_searing_light_spawn_life_spark::SelectTarget, EFFECT_ALL, TARGET_UNIT_DEST_AREA_ENEMY); + } +}; - void SelectTarget(std::list& targets) - { - if (Unit* victim = GetCaster()->GetVictim()) - targets.remove_if(Acore::ObjectGUIDCheck(victim->GetGUID(), true)); - } +class spell_xt002_searing_light_spawn_life_spark_aura : public AuraScript +{ + PrepareAuraScript(spell_xt002_searing_light_spawn_life_spark_aura); - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_xt002_searing_light_spawn_life_spark_SpellScript::SelectTarget, EFFECT_ALL, TARGET_UNIT_DEST_AREA_ENEMY); - } - }; - - SpellScript* GetSpellScript() const override + void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) { - return new spell_xt002_searing_light_spawn_life_spark_SpellScript(); + if (Player* player = GetOwner()->ToPlayer()) + if (Unit* xt002 = GetCaster()) + if (xt002->HasAura(aurEff->GetAmount())) // Heartbreak aura indicating hard mode + xt002->SummonCreature(NPC_LIFE_SPARK, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 180000); + } + + void Register() override + { + OnEffectRemove += AuraEffectRemoveFn(spell_xt002_searing_light_spawn_life_spark_aura::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); } }; @@ -1088,10 +1044,10 @@ void AddSC_boss_xt002() new npc_xt002_life_spark(); // Spells - new spell_xt002_tympanic_tantrum(); - new spell_xt002_gravity_bomb_aura(); - new spell_xt002_gravity_bomb_damage(); - new spell_xt002_searing_light_spawn_life_spark(); + RegisterSpellScript(spell_xt002_tympanic_tantrum); + RegisterSpellAndAuraScriptPair(spell_xt002_gravity_bomb, spell_xt002_gravity_bomb_aura); + RegisterSpellScript(spell_xt002_gravity_bomb_damage); + RegisterSpellAndAuraScriptPair(spell_xt002_searing_light_spawn_life_spark, spell_xt002_searing_light_spawn_life_spark_aura); // Achievements new achievement_xt002_nerf_engineering(); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yoggsaron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yoggsaron.cpp index 71e73971b..9fc2ba88a 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yoggsaron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yoggsaron.cpp @@ -2269,493 +2269,397 @@ public: }; // 63830, 63881 - Malady of the Mind -class spell_yogg_saron_malady_of_the_mind : public SpellScriptLoader +class spell_yogg_saron_malady_of_the_mind_aura : public AuraScript { -public: - spell_yogg_saron_malady_of_the_mind() : SpellScriptLoader("spell_yogg_saron_malady_of_the_mind") { } + PrepareAuraScript(spell_yogg_saron_malady_of_the_mind_aura); - class spell_yogg_saron_malady_of_the_mind_AuraScript : public AuraScript + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareAuraScript(spell_yogg_saron_malady_of_the_mind_AuraScript); + return ValidateSpellInfo({ SPELL_DEATH_RAY_DAMAGE_REAL, SPELL_MALADY_OF_THE_MIND_TRIGGER }); + } - void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - GetUnitOwner()->ApplySpellImmune(SPELL_DEATH_RAY_DAMAGE_REAL, IMMUNITY_ID, SPELL_DEATH_RAY_DAMAGE_REAL, true); - } - - void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - GetUnitOwner()->ApplySpellImmune(SPELL_DEATH_RAY_DAMAGE_REAL, IMMUNITY_ID, SPELL_DEATH_RAY_DAMAGE_REAL, false); - GetUnitOwner()->CastCustomSpell(SPELL_MALADY_OF_THE_MIND_TRIGGER, SPELLVALUE_MAX_TARGETS, 1, GetUnitOwner(), true); - } - - void Register() override - { - OnEffectApply += AuraEffectApplyFn(spell_yogg_saron_malady_of_the_mind_AuraScript::OnApply, EFFECT_1, SPELL_AURA_MOD_FEAR, AURA_EFFECT_HANDLE_REAL); - OnEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_malady_of_the_mind_AuraScript::OnRemove, EFFECT_1, SPELL_AURA_MOD_FEAR, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - return new spell_yogg_saron_malady_of_the_mind_AuraScript(); + GetUnitOwner()->ApplySpellImmune(SPELL_DEATH_RAY_DAMAGE_REAL, IMMUNITY_ID, SPELL_DEATH_RAY_DAMAGE_REAL, true); + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetUnitOwner()->ApplySpellImmune(SPELL_DEATH_RAY_DAMAGE_REAL, IMMUNITY_ID, SPELL_DEATH_RAY_DAMAGE_REAL, false); + GetUnitOwner()->CastCustomSpell(SPELL_MALADY_OF_THE_MIND_TRIGGER, SPELLVALUE_MAX_TARGETS, 1, GetUnitOwner(), true); + } + + void Register() override + { + OnEffectApply += AuraEffectApplyFn(spell_yogg_saron_malady_of_the_mind_aura::OnApply, EFFECT_1, SPELL_AURA_MOD_FEAR, AURA_EFFECT_HANDLE_REAL); + OnEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_malady_of_the_mind_aura::OnRemove, EFFECT_1, SPELL_AURA_MOD_FEAR, AURA_EFFECT_HANDLE_REAL); } }; // 63802 - Brain Link -class spell_yogg_saron_brain_link : public SpellScriptLoader +class spell_yogg_saron_brain_link : public SpellScript { -public: - spell_yogg_saron_brain_link() : SpellScriptLoader("spell_yogg_saron_brain_link") { } + PrepareSpellScript(spell_yogg_saron_brain_link); - class spell_yogg_saron_brain_link_AuraScript : public AuraScript + void FilterTargets(std::list& targets) { - PrepareAuraScript(spell_yogg_saron_brain_link_AuraScript); + std::list tempList; + for (std::list::iterator itr = targets.begin(); itr != targets.end(); ++itr) + if ((*itr)->GetPositionZ() > 300.0f) + tempList.push_back(*itr); - void HandleOnEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - PreventDefaultAction(); - Player* target = nullptr; - Map::PlayerList const& pList = GetUnitOwner()->GetMap()->GetPlayers(); - uint8 _offset = urand(0, pList.getSize() - 1); - uint8 _counter = 0; - for(Map::PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr, ++_counter) - { - if (itr->GetSource() == GetUnitOwner() || GetUnitOwner()->GetDistance(itr->GetSource()) > 50.0f || !itr->GetSource()->IsAlive() || itr->GetSource()->IsGameMaster()) - continue; - - if (_counter <= _offset || !target) - target = itr->GetSource(); - else - break; - } - - if (!target) - SetDuration(0); - else - _targetGUID = target->GetGUID(); - } - - void OnPeriodic(AuraEffect const* /*aurEff*/) - { - Unit* owner = GetUnitOwner(); - if (!owner) - { - SetDuration(0); - return; - } - - Unit* _target = ObjectAccessor::GetUnit(*owner, _targetGUID); - if (!_target || !_target->IsAlive() || std::fabs(owner->GetPositionZ() - _target->GetPositionZ()) > 10.0f) // Target or owner underground - { - SetDuration(0); - return; - } - - if (owner->GetDistance(_target) > 20.0f) - { - owner->CastSpell(_target, SPELL_BRAIN_LINK_DAMAGE, true); - owner->CastSpell(owner, SPELL_BRAIN_LINK_DAMAGE, true); - } - else - owner->CastSpell(_target, SPELL_BRAIN_LINK_OK, true); - } - - void Register() override - { - OnEffectApply += AuraEffectApplyFn(spell_yogg_saron_brain_link_AuraScript::HandleOnEffectApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); - OnEffectPeriodic += AuraEffectPeriodicFn(spell_yogg_saron_brain_link_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); - } - - protected: - ObjectGuid _targetGUID; - }; - - AuraScript* GetAuraScript() const override - { - return new spell_yogg_saron_brain_link_AuraScript(); + targets.clear(); + for (std::list::iterator itr = tempList.begin(); itr != tempList.end(); ++itr) + targets.push_back(*itr); } - class spell_yogg_saron_brain_link_SpellScript : public SpellScript + void Register() override { - PrepareSpellScript(spell_yogg_saron_brain_link_SpellScript); - - void FilterTargets(std::list& targets) - { - std::list tempList; - for (std::list::iterator itr = targets.begin(); itr != targets.end(); ++itr) - if ((*itr)->GetPositionZ() > 300.0f) - tempList.push_back(*itr); - - targets.clear(); - for (std::list::iterator itr = tempList.begin(); itr != tempList.end(); ++itr) - targets.push_back(*itr); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_brain_link_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_yogg_saron_brain_link_SpellScript(); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_brain_link::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; +class spell_yogg_saron_brain_link_aura : public AuraScript +{ + PrepareAuraScript(spell_yogg_saron_brain_link_aura); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_BRAIN_LINK_DAMAGE, SPELL_BRAIN_LINK_OK }); + } + + void HandleOnEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + PreventDefaultAction(); + Player* target = nullptr; + Map::PlayerList const& pList = GetUnitOwner()->GetMap()->GetPlayers(); + uint8 _offset = urand(0, pList.getSize() - 1); + uint8 _counter = 0; + for(Map::PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr, ++_counter) + { + if (itr->GetSource() == GetUnitOwner() || GetUnitOwner()->GetDistance(itr->GetSource()) > 50.0f || !itr->GetSource()->IsAlive() || itr->GetSource()->IsGameMaster()) + continue; + + if (_counter <= _offset || !target) + target = itr->GetSource(); + else + break; + } + + if (!target) + SetDuration(0); + else + _targetGUID = target->GetGUID(); + } + + void OnPeriodic(AuraEffect const* /*aurEff*/) + { + Unit* owner = GetUnitOwner(); + if (!owner) + { + SetDuration(0); + return; + } + + Unit* _target = ObjectAccessor::GetUnit(*owner, _targetGUID); + if (!_target || !_target->IsAlive() || std::fabs(owner->GetPositionZ() - _target->GetPositionZ()) > 10.0f) // Target or owner underground + { + SetDuration(0); + return; + } + + if (owner->GetDistance(_target) > 20.0f) + { + owner->CastSpell(_target, SPELL_BRAIN_LINK_DAMAGE, true); + owner->CastSpell(owner, SPELL_BRAIN_LINK_DAMAGE, true); + } + else + owner->CastSpell(_target, SPELL_BRAIN_LINK_OK, true); + } + + void Register() override + { + OnEffectApply += AuraEffectApplyFn(spell_yogg_saron_brain_link_aura::HandleOnEffectApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_yogg_saron_brain_link_aura::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } + +protected: + ObjectGuid _targetGUID; +}; + // 64465 - Shadow Beacon -class spell_yogg_saron_shadow_beacon : public SpellScriptLoader +class spell_yogg_saron_shadow_beacon_aura : public AuraScript { - public: - spell_yogg_saron_shadow_beacon() : SpellScriptLoader("spell_yogg_saron_shadow_beacon") { } + PrepareAuraScript(spell_yogg_saron_shadow_beacon_aura); - class spell_yogg_saron_shadow_beacon_AuraScript : public AuraScript + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - PrepareAuraScript(spell_yogg_saron_shadow_beacon_AuraScript); - - void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + if (Creature* target = GetTarget()->ToCreature()) { - if (Creature* target = GetTarget()->ToCreature()) - { - target->SetEntry(NPC_MARKED_IMMORTAL_GUARDIAN); - } + target->SetEntry(NPC_MARKED_IMMORTAL_GUARDIAN); } - - void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - if (Creature* target = GetTarget()->ToCreature()) - { - target->SetEntry(NPC_IMMORTAL_GUARDIAN); - } - } - - void Register() override - { - AfterEffectApply += AuraEffectApplyFn(spell_yogg_saron_shadow_beacon_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); - AfterEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_shadow_beacon_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_yogg_saron_shadow_beacon_AuraScript(); } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Creature* target = GetTarget()->ToCreature()) + { + target->SetEntry(NPC_IMMORTAL_GUARDIAN); + } + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_yogg_saron_shadow_beacon_aura::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_shadow_beacon_aura::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + } }; // 65206 - Destabilization Matrix -class spell_yogg_saron_destabilization_matrix : public SpellScriptLoader +class spell_yogg_saron_destabilization_matrix : public SpellScript { -public: - spell_yogg_saron_destabilization_matrix() : SpellScriptLoader("spell_yogg_saron_destabilization_matrix") { } + PrepareSpellScript(spell_yogg_saron_destabilization_matrix); - class spell_yogg_saron_destabilization_matrix_SpellScript : public SpellScript + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareSpellScript(spell_yogg_saron_destabilization_matrix_SpellScript); + return ValidateSpellInfo({ SPELL_DESTABILIZATION_MATRIX_ATTACK }); + } - void HandleDummyEffect(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); - if (Unit* target = GetHitUnit()) - GetCaster()->CastSpell(target, SPELL_DESTABILIZATION_MATRIX_ATTACK, false); - } - - void FilterTargets(std::list& targets) - { - WorldObject* target = nullptr; - for (std::list::iterator itr = targets.begin(); itr != targets.end(); ++itr) - if (!(*itr)->ToUnit()->HasAura(SPELL_DESTABILIZATION_MATRIX_ATTACK)) - { - target = *itr; - break; - } - - targets.clear(); - if (target) - targets.push_back(target); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_destabilization_matrix_SpellScript::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY); - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_destabilization_matrix_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); - } - }; - - SpellScript* GetSpellScript() const override + void HandleDummyEffect(SpellEffIndex effIndex) { - return new spell_yogg_saron_destabilization_matrix_SpellScript(); + PreventHitDefaultEffect(effIndex); + if (Unit* target = GetHitUnit()) + GetCaster()->CastSpell(target, SPELL_DESTABILIZATION_MATRIX_ATTACK, false); + } + + void FilterTargets(std::list& targets) + { + WorldObject* target = nullptr; + for (std::list::iterator itr = targets.begin(); itr != targets.end(); ++itr) + if (!(*itr)->ToUnit()->HasAura(SPELL_DESTABILIZATION_MATRIX_ATTACK)) + { + target = *itr; + break; + } + + targets.clear(); + if (target) + targets.push_back(target); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_destabilization_matrix::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_destabilization_matrix::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); } }; // 64172 - Titanic Storm -class spell_yogg_saron_titanic_storm : public SpellScriptLoader +class spell_yogg_saron_titanic_storm : public SpellScript { -public: - spell_yogg_saron_titanic_storm() : SpellScriptLoader("spell_yogg_saron_titanic_storm") { } + PrepareSpellScript(spell_yogg_saron_titanic_storm); - class spell_yogg_saron_titanic_storm_SpellScript : public SpellScript + void HandleDummyEffect(SpellEffIndex effIndex) { - PrepareSpellScript(spell_yogg_saron_titanic_storm_SpellScript); + PreventHitDefaultEffect(effIndex); + if (Unit* target = GetHitUnit()) + Unit::Kill(GetCaster(), target); + } - void HandleDummyEffect(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); - if (Unit* target = GetHitUnit()) - Unit::Kill(GetCaster(), target); - } - - void FilterTargets(std::list& targets) - { - WorldObject* target = nullptr; - for (std::list::iterator itr = targets.begin(); itr != targets.end(); ++itr) - if ((*itr)->ToUnit()->HasAura(SPELL_WEAKENED)) - { - target = *itr; - break; - } - - targets.clear(); - if (target) - targets.push_back(target); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_titanic_storm_SpellScript::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY); - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_titanic_storm_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); - } - }; - - SpellScript* GetSpellScript() const override + void FilterTargets(std::list& targets) { - return new spell_yogg_saron_titanic_storm_SpellScript(); + WorldObject* target = nullptr; + for (std::list::iterator itr = targets.begin(); itr != targets.end(); ++itr) + if ((*itr)->ToUnit()->HasAura(SPELL_WEAKENED)) + { + target = *itr; + break; + } + + targets.clear(); + if (target) + targets.push_back(target); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_titanic_storm::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_titanic_storm::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); } }; // 64164, 64168 - Lunatic Gaze -class spell_yogg_saron_lunatic_gaze : public SpellScriptLoader +class spell_yogg_saron_lunatic_gaze : public SpellScript { -public: - spell_yogg_saron_lunatic_gaze() : SpellScriptLoader("spell_yogg_saron_lunatic_gaze") { } + PrepareSpellScript(spell_yogg_saron_lunatic_gaze); - class spell_yogg_saron_lunatic_gaze_SpellScript : public SpellScript + void FilterTargets(std::list& targets) { - PrepareSpellScript(spell_yogg_saron_lunatic_gaze_SpellScript); + std::list tmplist; + for (std::list::iterator itr = targets.begin(); itr != targets.end(); ++itr) + if ((*itr)->HasInArc(M_PI, GetCaster())) + tmplist.push_back(*itr); - void FilterTargets(std::list& targets) - { - std::list tmplist; - for (std::list::iterator itr = targets.begin(); itr != targets.end(); ++itr) - if ((*itr)->HasInArc(M_PI, GetCaster())) - tmplist.push_back(*itr); + targets.clear(); + for (std::list::iterator itr = tmplist.begin(); itr != tmplist.end(); ++itr) + targets.push_back(*itr); + } - targets.clear(); - for (std::list::iterator itr = tmplist.begin(); itr != tmplist.end(); ++itr) - targets.push_back(*itr); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_lunatic_gaze_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY); - } - }; - - SpellScript* GetSpellScript() const override + void Register() override { - return new spell_yogg_saron_lunatic_gaze_SpellScript(); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_lunatic_gaze::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY); } }; // 64174 - Protective Gaze -class spell_yogg_saron_protective_gaze : public SpellScriptLoader +class spell_yogg_saron_protective_gaze_aura : public AuraScript { -public: - spell_yogg_saron_protective_gaze() : SpellScriptLoader("spell_yogg_saron_protective_gaze") { } + PrepareAuraScript(spell_yogg_saron_protective_gaze_aura); - class spell_yogg_saron_protective_gaze_AuraScript : public AuraScript + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareAuraScript(spell_yogg_saron_protective_gaze_AuraScript); + return ValidateSpellInfo({ SPELL_HODIR_FLASH_FREEZE }); + } - void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) - { - // Set absorbtion amount to unlimited - amount = -1; - } - - void Absorb(AuraEffect* /*aurEff*/, DamageInfo& dmgInfo, uint32& absorbAmount) - { - Unit* target = GetTarget(); - if (dmgInfo.GetDamage() < target->GetHealth() || !GetCaster() || GetCaster()->ToCreature()->HasSpellCooldown(SPELL_HODIR_FLASH_FREEZE)) - return; - - target->CastSpell(target, SPELL_HODIR_FLASH_FREEZE, true); - GetCaster()->AddSpellCooldown(SPELL_HODIR_FLASH_FREEZE, 0, 0); - absorbAmount = dmgInfo.GetDamage(); - } - - void Register() override - { - DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_yogg_saron_protective_gaze_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB); - OnEffectAbsorb += AuraEffectAbsorbFn(spell_yogg_saron_protective_gaze_AuraScript::Absorb, EFFECT_0); - } - }; - - AuraScript* GetAuraScript() const override + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) { - return new spell_yogg_saron_protective_gaze_AuraScript(); + // Set absorbtion amount to unlimited + amount = -1; + } + + void Absorb(AuraEffect* /*aurEff*/, DamageInfo& dmgInfo, uint32& absorbAmount) + { + Unit* target = GetTarget(); + if (dmgInfo.GetDamage() < target->GetHealth() || !GetCaster() || GetCaster()->ToCreature()->HasSpellCooldown(SPELL_HODIR_FLASH_FREEZE)) + return; + + target->CastSpell(target, SPELL_HODIR_FLASH_FREEZE, true); + GetCaster()->AddSpellCooldown(SPELL_HODIR_FLASH_FREEZE, 0, 0); + absorbAmount = dmgInfo.GetDamage(); + } + + void Register() override + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_yogg_saron_protective_gaze_aura::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB); + OnEffectAbsorb += AuraEffectAbsorbFn(spell_yogg_saron_protective_gaze_aura::Absorb, EFFECT_0); } }; // 64161 - Empowered -class spell_yogg_saron_empowered : public SpellScriptLoader +class spell_yogg_saron_empowered_aura : public AuraScript { -public: - spell_yogg_saron_empowered() : SpellScriptLoader("spell_yogg_saron_empowered") { } + PrepareAuraScript(spell_yogg_saron_empowered_aura); - class spell_yogg_saron_empowered_AuraScript : public AuraScript + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareAuraScript(spell_yogg_saron_empowered_AuraScript); + return ValidateSpellInfo({ SPELL_EMPOWERED, SPELL_WEAKENED }); + } - void OnPeriodic(AuraEffect const* /*aurEff*/) - { - Unit* target = GetUnitOwner(); - uint8 stack = std::min(uint8(target->GetHealthPct() / 10), (uint8)9); - - if (!stack) - { - target->RemoveAura(SPELL_EMPOWERED); - target->CastSpell(target, SPELL_WEAKENED, true); - } - else if (Aura* aur = target->AddAura(SPELL_EMPOWERED, target)) - { - aur->SetStackAmount(stack); - target->RemoveAurasDueToSpell(SPELL_WEAKENED); - } - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_yogg_saron_empowered_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); - } - }; - - AuraScript* GetAuraScript() const override + void OnPeriodic(AuraEffect const* /*aurEff*/) { - return new spell_yogg_saron_empowered_AuraScript(); + Unit* target = GetUnitOwner(); + uint8 stack = std::min(uint8(target->GetHealthPct() / 10), (uint8)9); + + if (!stack) + { + target->RemoveAura(SPELL_EMPOWERED); + target->CastSpell(target, SPELL_WEAKENED, true); + } + else if (Aura* aur = target->AddAura(SPELL_EMPOWERED, target)) + { + aur->SetStackAmount(stack); + target->RemoveAurasDueToSpell(SPELL_WEAKENED); + } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_yogg_saron_empowered_aura::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); } }; // 64555 - Insane Periodic -class spell_yogg_saron_insane_periodic_trigger : public SpellScriptLoader +class spell_yogg_saron_insane_periodic_trigger : public SpellScript { -public: - spell_yogg_saron_insane_periodic_trigger() : SpellScriptLoader("spell_yogg_saron_insane_periodic_trigger") { } + PrepareSpellScript(spell_yogg_saron_insane_periodic_trigger); - class spell_yogg_saron_insane_periodic_trigger_SpellScript : public SpellScript + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareSpellScript(spell_yogg_saron_insane_periodic_trigger_SpellScript); + return ValidateSpellInfo({ SPELL_INSANE1, SPELL_INSANE2 }); + } - void HandleDummyEffect(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); - Player* target = GetHitPlayer(); - if (!target) - return; - - Unit* caster = GetCaster(); - caster->CastSpell(target, SPELL_INSANE1, true); - target->CastSpell(target, SPELL_INSANE2, true); - } - - void FilterTargets(std::list& targets) - { - std::list tmplist; - for (std::list::iterator itr = targets.begin(); itr != targets.end(); ++itr) - if ((*itr)->IsPlayer() && !(*itr)->ToPlayer()->HasAuraType(SPELL_AURA_AOE_CHARM) && !(*itr)->ToPlayer()->HasAura(SPELL_SANITY)) - tmplist.push_back(*itr); - - targets.clear(); - for (std::list::iterator itr = tmplist.begin(); itr != tmplist.end(); ++itr) - targets.push_back(*itr); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_insane_periodic_trigger_SpellScript::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY); - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_insane_periodic_trigger_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - } - }; - - SpellScript* GetSpellScript() const override + void HandleDummyEffect(SpellEffIndex effIndex) { - return new spell_yogg_saron_insane_periodic_trigger_SpellScript(); + PreventHitDefaultEffect(effIndex); + Player* target = GetHitPlayer(); + if (!target) + return; + + Unit* caster = GetCaster(); + caster->CastSpell(target, SPELL_INSANE1, true); + target->CastSpell(target, SPELL_INSANE2, true); + } + + void FilterTargets(std::list& targets) + { + std::list tmplist; + for (std::list::iterator itr = targets.begin(); itr != targets.end(); ++itr) + if ((*itr)->IsPlayer() && !(*itr)->ToPlayer()->HasAuraType(SPELL_AURA_AOE_CHARM) && !(*itr)->ToPlayer()->HasAura(SPELL_SANITY)) + tmplist.push_back(*itr); + + targets.clear(); + for (std::list::iterator itr = tmplist.begin(); itr != tmplist.end(); ++itr) + targets.push_back(*itr); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_insane_periodic_trigger::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_insane_periodic_trigger::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; // 63120 - Insane -class spell_yogg_saron_insane : public SpellScriptLoader +class spell_yogg_saron_insane_aura : public AuraScript { -public: - spell_yogg_saron_insane() : SpellScriptLoader("spell_yogg_saron_insane") { } + PrepareAuraScript(spell_yogg_saron_insane_aura); - class spell_yogg_saron_insane_AuraScript : public AuraScript + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - PrepareAuraScript(spell_yogg_saron_insane_AuraScript); + Unit::Kill(GetUnitOwner(), GetUnitOwner()); + } - void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - Unit::Kill(GetUnitOwner(), GetUnitOwner()); - } - - void Register() override - { - OnEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_insane_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_AOE_CHARM, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override + void Register() override { - return new spell_yogg_saron_insane_AuraScript(); + OnEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_insane_aura::OnRemove, EFFECT_0, SPELL_AURA_AOE_CHARM, AURA_EFFECT_HANDLE_REAL); } }; // 64169 - Sanity Well -class spell_yogg_saron_sanity_well : public SpellScriptLoader +class spell_yogg_saron_sanity_well_aura : public AuraScript { -public: - spell_yogg_saron_sanity_well() : SpellScriptLoader("spell_yogg_saron_sanity_well") { } + PrepareAuraScript(spell_yogg_saron_sanity_well_aura); - class spell_yogg_saron_sanity_well_AuraScript : public AuraScript + void HandleEffectCalcPeriodic(AuraEffect const* /*aurEff*/, bool& isPeriodic, int32& amplitude) { - PrepareAuraScript(spell_yogg_saron_sanity_well_AuraScript); + isPeriodic = true; + amplitude = 2 * IN_MILLISECONDS; + } - void HandleEffectCalcPeriodic(AuraEffect const* /*aurEff*/, bool& isPeriodic, int32& amplitude) - { - isPeriodic = true; - amplitude = 2 * IN_MILLISECONDS; - } - - void HandleEffectPeriodic(AuraEffect const* /*aurEff*/) - { - Unit* target = GetTarget(); - if (!target || !target->IsPlayer()) - return; - - if (Aura* aur = target->GetAura(SPELL_SANITY)) - aur->SetStackAmount(std::min(100, aur->GetStackAmount() + 20)); - } - - void Register() override - { - DoEffectCalcPeriodic += AuraEffectCalcPeriodicFn(spell_yogg_saron_sanity_well_AuraScript::HandleEffectCalcPeriodic, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); - OnEffectPeriodic += AuraEffectPeriodicFn(spell_yogg_saron_sanity_well_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); - } - }; - - AuraScript* GetAuraScript() const override + void HandleEffectPeriodic(AuraEffect const* /*aurEff*/) { - return new spell_yogg_saron_sanity_well_AuraScript(); + Unit* target = GetTarget(); + if (!target || !target->IsPlayer()) + return; + + if (Aura* aur = target->GetAura(SPELL_SANITY)) + aur->SetStackAmount(std::min(100, aur->GetStackAmount() + 20)); + } + + void Register() override + { + DoEffectCalcPeriodic += AuraEffectCalcPeriodicFn(spell_yogg_saron_sanity_well_aura::HandleEffectCalcPeriodic, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_yogg_saron_sanity_well_aura::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); } }; @@ -2794,213 +2698,181 @@ class spell_keeper_freya_summon_sanity_well : public SpellScript 63803 - Brain Link 65301 - Psychosis 64168 - Lunatic Gaze */ -class spell_yogg_saron_sanity_reduce : public SpellScriptLoader +enum SanityReduce { -public: - spell_yogg_saron_sanity_reduce() : SpellScriptLoader("spell_yogg_saron_sanity_reduce") { } + SPELL_SANITY_SCREEN_EFFECT = 63752, + SPELL_LUNATIC_GAZE_TRIGGER = 64168, + SPELL_YS_LUNATIC_GAZE_TRIGGER = 64164 +}; - class spell_yogg_saron_sanity_reduce_SpellScript : public SpellScript +class spell_yogg_saron_sanity_reduce : public SpellScript +{ + PrepareSpellScript(spell_yogg_saron_sanity_reduce); + + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareSpellScript(spell_yogg_saron_sanity_reduce_SpellScript); + return ValidateSpellInfo({ SPELL_CANCEL_ILLUSION_AURA, SPELL_SANITY_SCREEN_EFFECT }); + } - void HandleScriptEffect(SpellEffIndex effIndex) + void HandleScriptEffect(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + Player* target = GetHitPlayer(); + if (!target) + return; + + uint8 _reduceAmount = 0; + switch (GetSpellInfo()->Id) { - PreventHitDefaultEffect(effIndex); - Player* target = GetHitPlayer(); - if (!target) - return; - - uint8 _reduceAmount = 0; - switch (GetSpellInfo()->Id) - { - case SPELL_SARA_PSYCHOSIS_10: - _reduceAmount = 9; - break; - case SPELL_SARA_PSYCHOSIS_25: - _reduceAmount = 12; - break; - case SPELL_MALADY_OF_THE_MIND: - _reduceAmount = 3; - break; - case SPELL_MALADY_OF_THE_MIND_TRIGGER: - _reduceAmount = 3; - break; - case SPELL_BRAIN_LINK_DAMAGE: - _reduceAmount = 2; - break; - case 64168 /*SPELL_LUNATIC_GAZE*/: - _reduceAmount = 2; - break; - case 64164 /*SPELL_YS_LUNATIC_GAZE*/: - _reduceAmount = 4; - break; - case SPELL_INDUCE_MADNESS: - // Teleported out of brain - if (target->GetPositionZ() > 300.0f) - return; - else - target->CastSpell(target, SPELL_CANCEL_ILLUSION_AURA, true); // else we are underground, remove illusion aura and teleport outside - _reduceAmount = 100; - break; - } - - if (Aura* aur = target->GetAura(SPELL_SANITY)) - { - if ((aur->GetStackAmount() - _reduceAmount) <= 20) - target->CastSpell(target, 63752 /*SANITY_SCREEN_EFFECT*/, true); - aur->ModStackAmount(-_reduceAmount); - } + case SPELL_SARA_PSYCHOSIS_10: + _reduceAmount = 9; + break; + case SPELL_SARA_PSYCHOSIS_25: + _reduceAmount = 12; + break; + case SPELL_MALADY_OF_THE_MIND: + _reduceAmount = 3; + break; + case SPELL_MALADY_OF_THE_MIND_TRIGGER: + _reduceAmount = 3; + break; + case SPELL_BRAIN_LINK_DAMAGE: + _reduceAmount = 2; + break; + case SPELL_LUNATIC_GAZE_TRIGGER: + _reduceAmount = 2; + break; + case SPELL_YS_LUNATIC_GAZE_TRIGGER: + _reduceAmount = 4; + break; + case SPELL_INDUCE_MADNESS: + // Teleported out of brain + if (target->GetPositionZ() > 300.0f) + return; + else + target->CastSpell(target, SPELL_CANCEL_ILLUSION_AURA, true); // else we are underground, remove illusion aura and teleport outside + _reduceAmount = 100; + break; } - void Register() override + if (Aura* aur = target->GetAura(SPELL_SANITY)) { - OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_sanity_reduce_SpellScript::HandleScriptEffect, EFFECT_FIRST_FOUND, SPELL_EFFECT_SCRIPT_EFFECT); + if ((aur->GetStackAmount() - _reduceAmount) <= 20) + target->CastSpell(target, SPELL_SANITY_SCREEN_EFFECT, true); + aur->ModStackAmount(-_reduceAmount); } - }; + } - SpellScript* GetSpellScript() const override + void Register() override { - return new spell_yogg_saron_sanity_reduce_SpellScript(); + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_sanity_reduce::HandleScriptEffect, EFFECT_FIRST_FOUND, SPELL_EFFECT_SCRIPT_EFFECT); } }; // 64467 - Empowering Shadows -class spell_yogg_saron_empowering_shadows : public SpellScriptLoader +enum EmpoweringShadows { -public: - spell_yogg_saron_empowering_shadows() : SpellScriptLoader("spell_yogg_saron_empowering_shadows") { } + SPELL_EMPOWERING_SHADOWS_HEAL_10 = 64468, + SPELL_EMPOWERING_SHADOWS_HEAL_25 = 64486 +}; - class spell_yogg_saron_empowering_shadows_SpellScript : public SpellScript +class spell_yogg_saron_empowering_shadows : public SpellScript +{ + PrepareSpellScript(spell_yogg_saron_empowering_shadows); + + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareSpellScript(spell_yogg_saron_empowering_shadows_SpellScript); + return ValidateSpellInfo({ SPELL_EMPOWERING_SHADOWS_HEAL_10, SPELL_EMPOWERING_SHADOWS_HEAL_25 }); + } - void HandleScriptEffect(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); - if (Unit* target = GetHitUnit()) - target->CastSpell(target, target->GetMap()->Is25ManRaid() ? 64486 : 64468, true); // SPELL_EMPOWERING_SHADOWS_HEAL - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_empowering_shadows_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; - - SpellScript* GetSpellScript() const override + void HandleScriptEffect(SpellEffIndex effIndex) { - return new spell_yogg_saron_empowering_shadows_SpellScript(); + PreventHitDefaultEffect(effIndex); + if (Unit* target = GetHitUnit()) + target->CastSpell(target, target->GetMap()->Is25ManRaid() ? SPELL_EMPOWERING_SHADOWS_HEAL_25 : SPELL_EMPOWERING_SHADOWS_HEAL_10, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_empowering_shadows::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; // 64184 - In the Maws of the Old God -class spell_yogg_saron_in_the_maws_of_the_old_god : public SpellScriptLoader +class spell_yogg_saron_in_the_maws_of_the_old_god : public SpellScript { -public: - spell_yogg_saron_in_the_maws_of_the_old_god() : SpellScriptLoader("spell_yogg_saron_in_the_maws_of_the_old_god") {} + PrepareSpellScript(spell_yogg_saron_in_the_maws_of_the_old_god); - class spell_yogg_saron_in_the_maws_of_the_old_god_SpellScript : public SpellScript + SpellCastResult CheckCast() { - PrepareSpellScript(spell_yogg_saron_in_the_maws_of_the_old_god_SpellScript); + if (!GetCaster()->IsPlayer()) + return SPELL_FAILED_BAD_TARGETS; - SpellCastResult CheckCast() - { - if (!GetCaster()->IsPlayer()) - return SPELL_FAILED_BAD_TARGETS; + Unit* target = GetCaster()->ToPlayer()->GetSelectedUnit(); + if (!target || target->GetEntry() != NPC_YOGG_SARON) + return SPELL_FAILED_BAD_TARGETS; - Unit* target = GetCaster()->ToPlayer()->GetSelectedUnit(); - if (!target || target->GetEntry() != NPC_YOGG_SARON) - return SPELL_FAILED_BAD_TARGETS; + Spell* spell = target->GetCurrentSpell(CURRENT_GENERIC_SPELL); + if (!spell || spell->GetSpellInfo()->Id != SPELL_DEAFENING_ROAR) + return SPELL_FAILED_TARGET_AURASTATE; - Spell* spell = target->GetCurrentSpell(CURRENT_GENERIC_SPELL); - if (!spell || spell->GetSpellInfo()->Id != SPELL_DEAFENING_ROAR) - return SPELL_FAILED_TARGET_AURASTATE; + return SPELL_CAST_OK; + } - return SPELL_CAST_OK; - } - - void Register() override - { - OnCheckCast += SpellCheckCastFn(spell_yogg_saron_in_the_maws_of_the_old_god_SpellScript::CheckCast); - } - }; - - SpellScript* GetSpellScript() const override + void Register() override { - return new spell_yogg_saron_in_the_maws_of_the_old_god_SpellScript(); + OnCheckCast += SpellCheckCastFn(spell_yogg_saron_in_the_maws_of_the_old_god::CheckCast); } }; /* 63744 - Sara's Anger 63747 - Sara's Fervor 63745 - Sara's Blessing */ -class spell_yogg_saron_target_selectors : public SpellScriptLoader +class spell_yogg_saron_target_selectors : public SpellScript { -public: - spell_yogg_saron_target_selectors() : SpellScriptLoader("spell_yogg_saron_target_selectors") { } + PrepareSpellScript(spell_yogg_saron_target_selectors); - class spell_yogg_saron_target_selectors_SpellScript : public SpellScript + void HandleScript(SpellEffIndex /*effIndex*/) { - PrepareSpellScript(spell_yogg_saron_target_selectors_SpellScript); - - void HandleScript(SpellEffIndex /*effIndex*/) + if (Unit* target = GetHitUnit()) { - if (Unit* target = GetHitUnit()) - { - GetCaster()->SetFacingToObject(target); - GetCaster()->CastSpell(target, uint32(GetEffectValue())); - } + GetCaster()->SetFacingToObject(target); + GetCaster()->CastSpell(target, uint32(GetEffectValue())); } + } - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_target_selectors_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const override + void Register() override { - return new spell_yogg_saron_target_selectors_SpellScript(); + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_target_selectors::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); } }; // 63305 - Grim Reprisal -class spell_yogg_saron_grim_reprisal : public SpellScriptLoader +class spell_yogg_saron_grim_reprisal_aura : public AuraScript { -public: - spell_yogg_saron_grim_reprisal() : SpellScriptLoader("spell_yogg_saron_grim_reprisal") { } + PrepareAuraScript(spell_yogg_saron_grim_reprisal_aura); - class spell_yogg_saron_grim_reprisal_AuraScript : public AuraScript + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareAuraScript(spell_yogg_saron_grim_reprisal_AuraScript); + return ValidateSpellInfo({ SPELL_GRIM_REPRISAL_DAMAGE }); + } - bool Validate(SpellInfo const* /*spellInfo*/) override - { - return ValidateSpellInfo({ SPELL_GRIM_REPRISAL_DAMAGE }); - } - - void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) - { - DamageInfo* damageInfo = eventInfo.GetDamageInfo(); - - if (!damageInfo || !damageInfo->GetDamage()) - { - return; - } - - int32 damage = CalculatePct(static_cast(damageInfo->GetDamage()), 60); - GetTarget()->CastCustomSpell(SPELL_GRIM_REPRISAL_DAMAGE, SPELLVALUE_BASE_POINT0, damage, damageInfo->GetAttacker(), true, nullptr, aurEff); - } - - void Register() override - { - OnEffectProc += AuraEffectProcFn(spell_yogg_saron_grim_reprisal_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); - } - }; - - AuraScript* GetAuraScript() const override + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) { - return new spell_yogg_saron_grim_reprisal_AuraScript(); + DamageInfo* damageInfo = eventInfo.GetDamageInfo(); + + if (!damageInfo || !damageInfo->GetDamage()) + { + return; + } + + int32 damage = CalculatePct(static_cast(damageInfo->GetDamage()), 60); + GetTarget()->CastCustomSpell(SPELL_GRIM_REPRISAL_DAMAGE, SPELLVALUE_BASE_POINT0, damage, damageInfo->GetAttacker(), true, nullptr, aurEff); + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_yogg_saron_grim_reprisal_aura::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); } }; @@ -3089,23 +2961,23 @@ void AddSC_boss_yoggsaron() new boss_yoggsaron_voice(); // SPELLS - new spell_yogg_saron_malady_of_the_mind(); - new spell_yogg_saron_brain_link(); - new spell_yogg_saron_shadow_beacon(); - new spell_yogg_saron_destabilization_matrix(); - new spell_yogg_saron_titanic_storm(); - new spell_yogg_saron_lunatic_gaze(); - new spell_yogg_saron_protective_gaze(); - new spell_yogg_saron_empowered(); - new spell_yogg_saron_insane_periodic_trigger(); - new spell_yogg_saron_insane(); - new spell_yogg_saron_sanity_well(); + RegisterSpellScript(spell_yogg_saron_malady_of_the_mind_aura); + RegisterSpellAndAuraScriptPair(spell_yogg_saron_brain_link, spell_yogg_saron_brain_link_aura); + RegisterSpellScript(spell_yogg_saron_shadow_beacon_aura); + RegisterSpellScript(spell_yogg_saron_destabilization_matrix); + RegisterSpellScript(spell_yogg_saron_titanic_storm); + RegisterSpellScript(spell_yogg_saron_lunatic_gaze); + RegisterSpellScript(spell_yogg_saron_protective_gaze_aura); + RegisterSpellScript(spell_yogg_saron_empowered_aura); + RegisterSpellScript(spell_yogg_saron_insane_periodic_trigger); + RegisterSpellScript(spell_yogg_saron_insane_aura); + RegisterSpellScript(spell_yogg_saron_sanity_well_aura); RegisterSpellScript(spell_keeper_freya_summon_sanity_well); - new spell_yogg_saron_sanity_reduce(); - new spell_yogg_saron_empowering_shadows(); - new spell_yogg_saron_in_the_maws_of_the_old_god(); - new spell_yogg_saron_target_selectors(); - new spell_yogg_saron_grim_reprisal(); + RegisterSpellScript(spell_yogg_saron_sanity_reduce); + RegisterSpellScript(spell_yogg_saron_empowering_shadows); + RegisterSpellScript(spell_yogg_saron_in_the_maws_of_the_old_god); + RegisterSpellScript(spell_yogg_saron_target_selectors); + RegisterSpellScript(spell_yogg_saron_grim_reprisal_aura); // ACHIEVEMENTS new achievement_yogg_saron_drive_me_crazy(); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.cpp index c9717cd34..51c37e94e 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.cpp @@ -79,7 +79,8 @@ enum UldSpells { SPELL_SIMPLE_TELEPORT = 12980, SPELL_KEEPER_TELEPORT = 62940, - SPELL_SNOW_MOUND_PARTICLES = 64615 + SPELL_SNOW_MOUND_PARTICLES = 64615, + SPELL_ENERGY_SAP_10 = 64740 }; class npc_ulduar_keeper : public CreatureScript @@ -201,30 +202,30 @@ public: } }; -class spell_ulduar_energy_sap : public SpellScriptLoader +enum EnergySap { -public: - spell_ulduar_energy_sap() : SpellScriptLoader("spell_ulduar_energy_sap") { } + SPELL_ENERGY_SAP_DAMAGE_1 = 64747, + SPELL_ENERGY_SAP_DAMAGE_2 = 64863, +}; - class spell_ulduar_energy_sap_AuraScript : public AuraScript +class spell_ulduar_energy_sap_aura : public AuraScript +{ + PrepareAuraScript(spell_ulduar_energy_sap_aura); + + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareAuraScript(spell_ulduar_energy_sap_AuraScript) + return ValidateSpellInfo({ SPELL_ENERGY_SAP_DAMAGE_1, SPELL_ENERGY_SAP_DAMAGE_2 }); + } - void HandleEffectPeriodic(AuraEffect const* aurEff) - { - if (Unit* target = GetTarget()) - target->CastSpell(target, (aurEff->GetId() == 64740) ? 64747 : 64863, true); - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_ulduar_energy_sap_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); - } - }; - - AuraScript* GetAuraScript() const override + void HandleEffectPeriodic(AuraEffect const* aurEff) { - return new spell_ulduar_energy_sap_AuraScript(); + if (Unit* target = GetTarget()) + target->CastSpell(target, (aurEff->GetId() == SPELL_ENERGY_SAP_10) ? SPELL_ENERGY_SAP_DAMAGE_1 : SPELL_ENERGY_SAP_DAMAGE_2, true); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_ulduar_energy_sap_aura::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); } }; @@ -500,30 +501,19 @@ public: }; }; -class spell_ulduar_arachnopod_damaged : public SpellScriptLoader +class spell_ulduar_arachnopod_damaged_aura : public AuraScript { -public: - spell_ulduar_arachnopod_damaged() : SpellScriptLoader("spell_ulduar_arachnopod_damaged") { } + PrepareAuraScript(spell_ulduar_arachnopod_damaged_aura); - class spell_ulduar_arachnopod_damaged_AuraScript : public AuraScript + void HandleEffectPeriodic(AuraEffect const* /*aurEff*/) { - PrepareAuraScript(spell_ulduar_arachnopod_damaged_AuraScript) + if (Unit* caster = GetCaster()) + Unit::Kill(caster, caster, false); + } - void HandleEffectPeriodic(AuraEffect const* /*aurEff*/) - { - if (Unit* c = GetCaster()) - Unit::Kill(c, c, false); - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_ulduar_arachnopod_damaged_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - } - }; - - AuraScript* GetAuraScript() const override + void Register() override { - return new spell_ulduar_arachnopod_damaged_AuraScript(); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_ulduar_arachnopod_damaged_aura::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); } }; @@ -576,11 +566,11 @@ struct npc_salvaged_siege_engine : public VehicleAI void AddSC_ulduar() { new npc_ulduar_keeper(); - new spell_ulduar_energy_sap(); + RegisterSpellScript(spell_ulduar_energy_sap_aura); RegisterUlduarCreatureAI(npc_ulduar_snow_mound); new npc_ulduar_storm_tempered_keeper(); new npc_ulduar_arachnopod_destroyer(); - new spell_ulduar_arachnopod_damaged(); + RegisterSpellScript(spell_ulduar_arachnopod_damaged_aura); new AreaTrigger_at_celestial_planetarium_enterance(); RegisterCreatureAI(npc_salvaged_siege_engine); } diff --git a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp index d55c9169f..a48e835c3 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp @@ -213,6 +213,7 @@ struct npc_akama_shade : public ScriptedAI me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP); DoCastSelf(SPELL_STEALTH, true); me->SetWalk(true); + _sayLowHealth = false; scheduler.CancelAll(); } @@ -261,6 +262,15 @@ struct npc_akama_shade : public ScriptedAI } } + void DamageTaken(Unit* /*unit*/, uint32& damage, DamageEffectType, SpellSchoolMask) override + { + if (me->HealthBelowPctDamaged(20, damage) && !_sayLowHealth) + { + _sayLowHealth = true; + Talk(SAY_LOW_HEALTH); + } + } + void DoAction(int32 param) override { if (param == ACTION_AKAMA_START_OUTRO) @@ -284,6 +294,7 @@ struct npc_akama_shade : public ScriptedAI void JustDied(Unit* /*killer*/) override { + Talk(SAY_DEATH); if (Creature* shade = instance->GetCreature(DATA_SHADE_OF_AKAMA)) { shade->SetHomePosition(shade->GetHomePosition()); @@ -318,6 +329,9 @@ struct npc_akama_shade : public ScriptedAI scheduler.Update(diff); DoMeleeAttackIfReady(); } + + private: + bool _sayLowHealth; }; struct npc_creature_generator_akama : public ScriptedAI diff --git a/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp b/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp index 58680039f..101122b56 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp @@ -43,14 +43,20 @@ enum Spells enum Events { - EVENT_SPELL_BERSERK = 1, - EVENT_TALK_CHECK = 2 + EVENT_TALK_CHECK = 1, + EVENT_ENRAGE = 2 }; struct boss_najentus : public BossAI { boss_najentus(Creature* creature) : BossAI(creature, DATA_HIGH_WARLORD_NAJENTUS), _canTalk(true) { } + void Reset() override + { + _Reset(); + me->m_Events.CancelEventGroup(EVENT_ENRAGE); + } + void JustEngagedWith(Unit* who) override { _canTalk = true; @@ -58,11 +64,10 @@ struct boss_najentus : public BossAI BossAI::JustEngagedWith(who); Talk(SAY_AGGRO); - ScheduleUniqueTimedEvent(8min, [&] - { + me->m_Events.AddEventAtOffset([this] { Talk(SAY_ENRAGE); DoCastSelf(SPELL_BERSERK, true); - }, EVENT_SPELL_BERSERK); + }, 8min, EVENT_ENRAGE); ScheduleTimedEvent(25s, 100s, [&] { diff --git a/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp b/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp index 175437358..75dbcd67a 100644 --- a/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp +++ b/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp @@ -253,16 +253,8 @@ public: void HandleScriptEffect(SpellEffIndex effIndex) { PreventHitDefaultEffect(effIndex); - Unit* target = GetHitUnit(); - if (!target) - return; - - target->RemoveAurasDueToSpell(SPELL_AURA_MOD_CHARM); - target->RemoveAurasDueToSpell(SPELL_AURA_MOD_STUN); - target->RemoveAurasDueToSpell(SPELL_AURA_MOD_DECREASE_SPEED); - target->RemoveAurasDueToSpell(SPELL_AURA_MOD_ROOT); - target->RemoveAurasDueToSpell(SPELL_AURA_MOD_CONFUSE); - target->RemoveAurasDueToSpell(SPELL_AURA_MOD_FEAR); + if (Unit* target = GetHitUnit()) + target->RemoveAurasWithMechanic(IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK); } void Register() override diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/instance_serpent_shrine.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/instance_serpent_shrine.cpp index 53103f73f..aa8f213af 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/instance_serpent_shrine.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/instance_serpent_shrine.cpp @@ -201,7 +201,7 @@ class spell_serpentshrine_cavern_serpentshrine_parasite : public AuraScript void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - if (GetTarget()->GetInstanceScript() && GetTarget()->GetInstanceScript()->IsEncounterInProgress()) + if (GetTarget()->GetInstanceScript()) GetTarget()->CastSpell(GetTarget(), SPELL_SUMMON_SERPENTSHRINE_PARASITE, true); } diff --git a/src/server/scripts/Outland/CoilfangReservoir/SlavePens/boss_ahune.cpp b/src/server/scripts/Outland/CoilfangReservoir/SlavePens/boss_ahune.cpp index 6a536ddea..a3d7fc6e6 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SlavePens/boss_ahune.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SlavePens/boss_ahune.cpp @@ -17,391 +17,907 @@ #include "CreatureScript.h" #include "GameObjectScript.h" +#include "ScriptMgr.h" +#include "Containers.h" +#include "CreatureTextMgr.h" +#include "GameObject.h" +#include "GameObjectAI.h" #include "Group.h" +#include "InstanceScript.h" #include "LFGMgr.h" +#include "Map.h" +#include "MotionMaster.h" +#include "ObjectAccessor.h" #include "PassiveAI.h" #include "Player.h" #include "ScriptedCreature.h" #include "ScriptedGossip.h" +#include "SpellAuraEffects.h" +#include "SpellInfo.h" +#include "SpellMgr.h" +#include "SpellScript.h" +#include "SpellScriptLoader.h" +#include "TemporarySummon.h" #include "the_slave_pens.h" -#define GOSSIP_TEXT_ID 15864 -#define QUEST_SUMMON_AHUNE 11691 -#define ITEM_MAGMA_TOTEM 34953 -#define AHUNE_DEFAULT_MODEL 23344 - -const Position AhuneSummonPos = {-97.3473f, -233.139f, -1.27587f, M_PI / 2}; -const Position TotemPos[3] = { {-115.141f, -143.317f, -2.09467f, 4.92772f}, {-120.178f, -144.398f, -2.23786f, 4.92379f}, {-125.277f, -145.463f, -1.95209f, 4.97877f} }; -const Position MinionSummonPos = {-97.154404f, -204.382675f, -1.19f, M_PI / 2}; - -enum Text +enum Spells { - EMOTE_RETREAT = 0, - EMOTE_RESURFACE = 1, + // Ahune + SPELL_SYNCH_HEALTH = 46430, + SPELL_AHUNES_SHIELD = 45954, + SPELL_STAY_SUBMERGED = 46981, + SPELL_AHUNE_SELF_STUN = 46416, + SPELL_AHUNE_ACHIEVEMENT = 62043, + SPELL_AHUNE_SPANKY_HANDS = 46146, + SPELL_COLD_SLAP = 46145, + SPELL_RESURFACE = 46402, + SPELL_SUBMERGED = 37751, + SPELL_STAND = 37752, + SPELL_BIRTH = 37745, + + //Earther Ring Flamecaller + SPELL_FIND_OPENING_VISUAL = 45964, + SPELL_FIND_OPENING_BEAM_END = 46333, + SPELL_FIND_OPENING_TRIGGER = 46341, + SPELL_FIND_OPENING_CHANNEL = 46345, + SPELL_BONFIRE_VISUAL = 46339, + SPELL_FOUND_OPENING = 46421, + + //Ahune Bunny + SPELL_SUMMON_COLDWEAVE = 46143, + SPELL_SUMMON_FROSTWIND = 46382, + SPELL_SUMMON_HAILSTONE = 46176, + SPELL_SUMMONING_VISUAL_1 = 45937, + SPELL_SUMMONING_RHYME_AURA = 45926, + SPELL_SUMMONING_RHYME_BONFIRE = 45930, + SPELL_FORCE_WHISP_FLIGHT = 46603, + SPELL_SHAMANS_LOOK_FOR_OPENING = 46422, + SPELL_CLOSE_OPENING_VISUAL = 46236, + SPELL_ICE_BOMBARD = 46397, + SPELL_ICE_BOMBARDMENT_DEST_PICKER = 46398, + SPELL_ICE_BOMBARDMENT = 46396, + + // Ice Spear + SPELL_ICE_SPEAR_KNOCKBACK = 46360, + SPELL_SUMMON_ICE_SPEAR_GO = 46369, + SPELL_ICE_SPEAR_DELAY = 46878, + SPELL_ICE_SPEAR_VISUAL = 75498, + + // Slippery Floor + SPELL_SLIPPERY_FLOOR_AMBIENT = 46314, + SPELL_SLIPPERY_FLOOR_PERIODIC = 46320, + SPELL_SLIPPERY_FLOOR_SLIP = 45947, + SPELL_SLIPPERY_FLOOR_YOU_SLIPPED = 45946, + + // Frozen Core + SPELL_ICE_SPEAR_CONTROL_AURA = 46371, + SPELL_FROZEN_CORE_GETS_HIT = 46810, + SPELL_IS_DEAD_CHECK = 61976, // NYI + SPELL_ICE_SPEAR_TARGET_PICKER = 46372, + SPELL_SUMMON_ICE_SPEAR_BUNNY = 46359, + SPELL_SUICIDE = 45254, + SPELL_SUMMON_LOOT_MISSILE = 45941, + SPELL_MINION_DESPAWNER = 46843, + SPELL_GHOST_DISGUISE = 46786 }; -enum EventSpells +enum Emotes { - SPELL_STARTING_BEAM = 46593, - SPELL_MAKE_BONFIRE = 45930, - SPELL_TOTEM_BEAM = 46363, - SPELL_SELF_STUN = 46416, - SPELL_EMERGE_0 = 66947, - SPELL_SUBMERGE_0 = 37550, - SPELL_AHUNE_RESURFACES = 46402, - - SPELL_AHUNES_SHIELD = 45954, - SPELL_COLD_SLAP = 46198, - SPELL_SUMMON_HAILSTONE = 45951, - SPELL_SUMMON_COLDWAVE = 45952, - SPELL_SUMMON_FROSTWIND = 45953, - - SPELL_CHILLING_AURA = 46542, - - /* - SPELL_SUMMON_ICE_SPEAR_BUNNY= 46359, // any dest - SPELL_ICE_SPEAR_KNOCKBACK = 46360, // src caster - SPELL_ICE_SPEAR_SUMMON_OBJ = 46369, - SPELL_ICE_SPEAR_CONTROL_AURA= 46371, // periodic dummy - */ + EMOTE_EARTHEN_ASSAULT = 0, + EMOTE_RETREAT = 0, + EMOTE_RESURFACE = 1 }; -enum CreatureIds +enum Says { - NPC_AHUNITE_HAILSTONE = 25755 + SAY_PLAYER_TEXT_1 = 0, + SAY_PLAYER_TEXT_2 = 1, + SAY_PLAYER_TEXT_3 = 2 }; -enum eEvents +enum Events { EVENT_EMERGE = 1, - EVENT_INVOKER_SAY_1, - EVENT_INVOKER_SAY_2, - EVENT_INVOKER_SAY_3, - EVENT_SUMMON_TOTEMS, - EVENT_ATTACK, - EVENT_TOTEMS_ATTACK, - EVENT_SUBMERGE, - EVENT_COMBAT_EMERGE, - EVENT_EMERGE_WARNING, + EVENT_INITIAL_EMERGE, + EVENT_SYNCH_HEALTH, + EVENT_LOOKFOROPENING_0, + EVENT_LOOKFOROPENING_1, + EVENT_LOOKFOROPENING_2, + EVENT_SUMMON_HAILSTONE, + EVENT_SUMMON_COLDWEAVE, + EVENT_SUMMON_FROSTWIND, + EVENT_SUMMON_AHUNE, + EVENT_CLOSE_OPENING, + EVENT_AHUNE_PHASE_ONE, + EVENT_AHUNE_PHASE_TWO, + EVENT_START_LOOKING_FOR_OPENING, + EVENT_STOP_LOOKING_FOR_OPENING +}; - EVENT_SPELL_COLD_SLAP, - EVENT_SPELL_SUMMON_HAILSTONE, - EVENT_SPELL_SUMMON_COLDWAVE, +enum Actions +{ + ACTION_START_EVENT = -2574500, + ACTION_STOP_EVENT = -2574501, + ACTION_AHUNE_RETREAT = -2586500, + ACTION_AHUNE_RESURFACE = -2586501, + ACTION_EMOTE_RESURFACE = -2575400 +}; + +enum Phases +{ + PHASE_ONE = 0, + PHASE_TWO = 1 +}; + +enum Points +{ + POINT_FLAMECALLER_000, + POINT_FLAMECALLER_001, + POINT_FLAMECALLER_002 }; enum Misc { - SET_GUID_INVOKER = 1 + MAX_FLAMECALLERS = 3 }; -struct boss_ahune : public ScriptedAI +Position const SummonPositions[] = { - boss_ahune(Creature* c) : ScriptedAI(c), summons(me) + { -99.1021f, -233.7526f, -1.22307f, 1.588250f }, // Ahune + { -98.0151f, -230.4555f, -1.21089f, 1.797689f }, // Frozen Core + { -143.172f, -147.6801f, -3.16113f, 4.852015f }, // Bonfire Bunny 000 + { -134.304f, -145.7803f, -1.70332f, 4.677482f }, // Bonfire Bunny 001 + { -125.036f, -144.2065f, -1.91660f, 4.991642f } // Bonfire Bunny 002 +}; + +Position const FlameCallerSpots[] = +{ + { -145.2233f, -137.5543f, -1.59056f, 5.427049f }, + { -137.4383f, -136.4050f, -1.72384f, 5.336747f }, + { -129.0413f, -132.1494f, -2.09285f, 5.460842f } +}; + +struct boss_ahune : public BossAI +{ + boss_ahune(Creature* creature) : BossAI(creature, DATA_AHUNE) { - me->SetCombatMovement(false); - SetEquipmentSlots(false, 54806, EQUIP_UNEQUIP, EQUIP_UNEQUIP); - me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - InvokerGUID.Clear(); - events.Reset(); - events.RescheduleEvent(EVENT_EMERGE, 12000); - events.RescheduleEvent(EVENT_INVOKER_SAY_1, 1000); - events.RescheduleEvent(EVENT_SUMMON_TOTEMS, 4000); + me->SetControlled(true, UNIT_STATE_ROOT); } - EventMap events; - SummonList summons; - ObjectGuid InvokerGUID; - - void StartPhase1() + void JustEngagedWith(Unit* who) override { - me->CastSpell(me, SPELL_AHUNES_SHIELD, true); - events.RescheduleEvent(EVENT_TOTEMS_ATTACK, 80000); - events.RescheduleEvent(EVENT_SPELL_COLD_SLAP, 1200); - events.RescheduleEvent(EVENT_SPELL_SUMMON_HAILSTONE, 2000); - events.RescheduleEvent(EVENT_SPELL_SUMMON_COLDWAVE, 5000); + BossAI::JustEngagedWith(who); + events.ScheduleEvent(EVENT_INITIAL_EMERGE, 4ms); + events.ScheduleEvent(EVENT_SYNCH_HEALTH, 3000); } - void JustEngagedWith(Unit* /*who*/) override + void EnterEvadeMode(EvadeReason /*why*/) override { - DoZoneInCombat(); - events.Reset(); - StartPhase1(); + if (Creature* ahuneBunny = instance->GetCreature(DATA_AHUNE_BUNNY)) + ahuneBunny->AI()->DoAction(ACTION_STOP_EVENT); + summons.DespawnAll(); + me->DespawnOrUnsummon(); } - void SetGUID(ObjectGuid guid, int32 id) override + void JustDied(Unit* /*killer*/) override { - if (id == SET_GUID_INVOKER) + instance->DoCastSpellOnPlayers(SPELL_AHUNE_ACHIEVEMENT); + + if (Creature* ahuneBunny = instance->GetCreature(DATA_AHUNE_BUNNY)) + Unit::Kill(me, ahuneBunny); + if (Creature* frozenCore = instance->GetCreature(DATA_FROZEN_CORE)) + Unit::Kill(me, frozenCore); + + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + if (!players.IsEmpty()) { - InvokerGUID = guid; + if (Group* group = players.begin()->GetSource()->GetGroup()) + if (group->isLFGGroup()) + sLFGMgr->FinishDungeon(group->GetGUID(), 286, me->GetMap()); + } + + _JustDied(); + } + + void DoAction(int32 action) override + { + if (action == ACTION_AHUNE_RETREAT) + { + Submerge(); + events.ScheduleEvent(EVENT_EMERGE, 35s); + } + } + + void ExecuteEvent(uint32 eventId) override + { + switch (eventId) + { + case EVENT_INITIAL_EMERGE: + DoCastSelf(SPELL_BIRTH); + DoCastSelf(SPELL_STAND); + DoCastSelf(SPELL_AHUNE_SPANKY_HANDS); + DoCastSelf(SPELL_AHUNES_SHIELD); + me->SetStandState(UNIT_STAND_STATE_STAND); // Likely needs to be moved to SPELL_STAND script, forced temporarily + break; + case EVENT_EMERGE: + Emerge(); + break; + case EVENT_SYNCH_HEALTH: + if (Creature* frozenCore = instance->GetCreature(DATA_FROZEN_CORE)) + DoCast(frozenCore, SPELL_SYNCH_HEALTH, true); + else + DoCastSelf(SPELL_SUICIDE); + events.Repeat(3s); + break; + default: + break; + } + } + + void Emerge() + { + if (Creature* frozenCore = instance->GetCreature(DATA_FROZEN_CORE)) + frozenCore->AI()->DoAction(ACTION_AHUNE_RESURFACE); + + DoCastSelf(SPELL_AHUNES_SHIELD); + me->RemoveAurasDueToSpell(SPELL_AHUNE_SELF_STUN); + me->RemoveAurasDueToSpell(SPELL_STAY_SUBMERGED); + DoCastSelf(SPELL_BIRTH); + DoCastSelf(SPELL_STAND); + DoCastSelf(SPELL_RESURFACE, true); + me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + events.ScheduleEvent(EVENT_SYNCH_HEALTH, 3s); + } + + void Submerge() + { + if (Creature* frozenCore = instance->GetCreature(DATA_FROZEN_CORE)) + frozenCore->AI()->DoAction(ACTION_AHUNE_RETREAT); + me->RemoveAurasDueToSpell(SPELL_AHUNES_SHIELD); + DoCastSelf(SPELL_SUBMERGED, true); + DoCastSelf(SPELL_AHUNE_SELF_STUN, true); + DoCastSelf(SPELL_STAY_SUBMERGED, true); + me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE); + me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + me->SetStandState(UNIT_STAND_STATE_SUBMERGED); + events.Reset(); + } +}; + +struct npc_frozen_core : public ScriptedAI +{ + npc_frozen_core(Creature* creature) : ScriptedAI(creature) + { + _instance = me->GetInstanceScript(); + Initialize(); + } + + void Initialize() + { + me->SetReactState(REACT_PASSIVE); + me->SetRegeneratingHealth(false); + DoCastSelf(SPELL_ICE_SPEAR_CONTROL_AURA); + DoCastSelf(SPELL_FROZEN_CORE_GETS_HIT); + DoCastSelf(SPELL_IS_DEAD_CHECK); + } + + void JustDied(Unit* /*killer*/) override + { + if (Creature* ahune = _instance->GetCreature(DATA_AHUNE)) + Unit::Kill(me, ahune); + + DoCast(SPELL_SUMMON_LOOT_MISSILE); + DoCast(SPELL_MINION_DESPAWNER); + } + + void DoAction(int32 action) override + { + if (action == ACTION_AHUNE_RETREAT) + { + me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + me->SetImmuneToPC(false); + me->RemoveAurasDueToSpell(SPELL_ICE_SPEAR_CONTROL_AURA); + _events.ScheduleEvent(EVENT_SYNCH_HEALTH, 3000, 0, PHASE_TWO); + } + else if (action == ACTION_AHUNE_RESURFACE) + { + _events.Reset(); + DoCastSelf(SPELL_ICE_SPEAR_CONTROL_AURA); + me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + me->SetImmuneToPC(true); } } void UpdateAI(uint32 diff) override { - if (!UpdateVictim() && !me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE)) - return; + _events.Update(diff); - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) + while (uint32 eventId = _events.ExecuteEvent()) { - case 0: - break; - case EVENT_EMERGE: - me->SetVisible(true); - me->CastSpell(me, SPELL_EMERGE_0, false); - events.RescheduleEvent(EVENT_ATTACK, 2000); - break; - case EVENT_SUMMON_TOTEMS: - for (uint8 i = 0; i < 3; ++i) - DoSummon(NPC_TOTEM, TotemPos[i], 10 * 60 * 1000, TEMPSUMMON_TIMED_DESPAWN); - break; - case EVENT_INVOKER_SAY_1: - if (Player* plr = ObjectAccessor::GetPlayer(*me, InvokerGUID)) + switch (eventId) { - plr->Say("The Ice Stone has melted!", LANG_UNIVERSAL); - plr->CastSpell(plr, SPELL_MAKE_BONFIRE, true); + case EVENT_SYNCH_HEALTH: + if (Creature* ahune = _instance->GetCreature(DATA_AHUNE)) + DoCast(ahune, SPELL_SYNCH_HEALTH, true); + else + DoCastSelf(SPELL_SUICIDE); + _events.Repeat(3000ms, 3000ms); + break; + default: + break; } - events.RescheduleEvent(EVENT_INVOKER_SAY_2, 2000); - break; - case EVENT_INVOKER_SAY_2: - if (Player* plr = ObjectAccessor::GetPlayer(*me, InvokerGUID)) - plr->Say("Ahune, your strength grows no more!", LANG_UNIVERSAL); - events.RescheduleEvent(EVENT_INVOKER_SAY_3, 2000); - break; - case EVENT_INVOKER_SAY_3: - if (Player* plr = ObjectAccessor::GetPlayer(*me, InvokerGUID)) - plr->Say("Your frozen reign will not come to pass!", LANG_UNIVERSAL); - break; - case EVENT_ATTACK: - events.Reset(); - if (Player* plr = ObjectAccessor::GetPlayer(*me, InvokerGUID)) - AttackStart(plr); - me->SetInCombatWithZone(); - if (!me->IsInCombat()) - { - EnterEvadeMode(EVADE_REASON_OTHER); - return; - } - else - me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - break; - case EVENT_TOTEMS_ATTACK: - for (uint8 i = 0; i < 3; ++i) - if (Creature* bunny = me->FindNearestCreature(NPC_TOTEM_BUNNY_1 + i, 150.0f, true)) - bunny->CastSpell(me, SPELL_TOTEM_BEAM, false); - events.RescheduleEvent(EVENT_SUBMERGE, 10000); - break; - case EVENT_SUBMERGE: - Talk(EMOTE_RETREAT); - me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - me->CastSpell(me, SPELL_SUBMERGE_0, true); - me->CastSpell(me, SPELL_SELF_STUN, true); - if (Creature* c = DoSummon(NPC_FROZEN_CORE, *me, 24000, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN)) - { - c->SetHealth(me->GetHealth()); - } - events.Reset(); - events.RescheduleEvent(EVENT_COMBAT_EMERGE, 25000); - events.RescheduleEvent(EVENT_EMERGE_WARNING, 20000); - break; - case EVENT_EMERGE_WARNING: - Talk(EMOTE_RESURFACE); - break; - case EVENT_COMBAT_EMERGE: - me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - me->RemoveAura(SPELL_SELF_STUN); - me->CastSpell(me, SPELL_EMERGE_0, false); - // me->CastSpell(me, SPELL_AHUNE_RESURFACES, true); // done in SummonedCreatureDespawn - me->RemoveAura(SPELL_SUBMERGE_0); - summons.DespawnEntry(NPC_FROZEN_CORE); - StartPhase1(); - break; - - case EVENT_SPELL_COLD_SLAP: - if (Unit* target = SelectTarget(SelectTargetMethod::MaxDistance, 0, 5.0f, true)) - if (target->GetPositionZ() < me->GetPositionZ() + 6.0f) - { - int32 dmg = urand(5500, 6000); - me->CastCustomSpell(target, SPELL_COLD_SLAP, &dmg, nullptr, nullptr, false); - float x, y, z; - target->GetNearPoint(target, x, y, z, target->GetObjectSize(), 30.0f, target->GetAngle(me->GetPositionX(), me->GetPositionY()) + M_PI); - target->GetMotionMaster()->MoveJump(x, y, z + 20.0f, 10.0f, 20.0f); - } - events.RepeatEvent(1500); - break; - case EVENT_SPELL_SUMMON_HAILSTONE: - { - float dist = (float)urand(3, 10); - float angle = rand_norm() * 2 * M_PI; - me->CastSpell(MinionSummonPos.GetPositionX() + cos(angle) * dist, MinionSummonPos.GetPositionY() + std::sin(angle) * dist, MinionSummonPos.GetPositionZ(), SPELL_SUMMON_HAILSTONE, false); } - break; - case EVENT_SPELL_SUMMON_COLDWAVE: - for (uint8 i = 0; i < 2; ++i) - { - float dist = (float)urand(3, 10); - float angle = rand_norm() * 2 * M_PI; - me->CastSpell(MinionSummonPos.GetPositionX() + cos(angle) * dist, MinionSummonPos.GetPositionY() + std::sin(angle) * dist, MinionSummonPos.GetPositionZ(), SPELL_SUMMON_COLDWAVE, false); - } - { - float dist = (float)urand(3, 10); - float angle = rand_norm() * 2 * M_PI; - me->CastSpell(MinionSummonPos.GetPositionX() + cos(angle) * dist, MinionSummonPos.GetPositionY() + std::sin(angle) * dist, MinionSummonPos.GetPositionZ(), SPELL_SUMMON_FROSTWIND, false); - } - events.RepeatEvent(12000); - break; - - default: - break; - } - - DoMeleeAttackIfReady(); } - void MoveInLineOfSight(Unit* /*who*/) override {} +private: + InstanceScript* _instance; + EventMap _events; +}; - void EnterEvadeMode(EvadeReason why) override +struct npc_ahune_bunny : public ScriptedAI +{ + npc_ahune_bunny(Creature* creature) : ScriptedAI(creature), _summons(me) { - me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - events.Reset(); - summons.DespawnAll(); - me->DespawnOrUnsummon(1); - - ScriptedAI::EnterEvadeMode(why); + _instance = me->GetInstanceScript(); + _submerged = false; } void JustSummoned(Creature* summon) override { - summons.Summon(summon); - summon->SetInCombatWithZone(); + if (summon->GetEntry() == NPC_AHUNE) + return; - if (summon->GetEntry() == NPC_AHUNITE_HAILSTONE) + DoZoneInCombat(summon); + _summons.Summon(summon); + } + + void JustDied(Unit* /*killer*/) override + { + _summons.DespawnAll(); + ResetFlameCallers(); + } + + void DoAction(int32 action) override + { + if (action == ACTION_START_EVENT) { - // Doesn't work when cast normally or when added to - // creature template addon. Needs further investigation. - if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_CHILLING_AURA)) + DoCastSelf(SPELL_SUMMONING_VISUAL_1); + me->SummonCreature(NPC_SHAMAN_BONFIRE_BUNNY_000, SummonPositions[2], TEMPSUMMON_MANUAL_DESPAWN); + me->SummonCreature(NPC_SHAMAN_BONFIRE_BUNNY_001, SummonPositions[3], TEMPSUMMON_MANUAL_DESPAWN); + me->SummonCreature(NPC_SHAMAN_BONFIRE_BUNNY_002, SummonPositions[4], TEMPSUMMON_MANUAL_DESPAWN); + + for (uint8 counter = 0; counter < MAX_FLAMECALLERS; ++counter) + if (Creature* flameCaller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FLAMECALLER_000 + counter))) + flameCaller->GetMotionMaster()->MovePoint(counter, FlameCallerSpots[counter].GetPosition()); + + _submerged = false; + _events.Reset(); + _events.SetPhase(PHASE_ONE); + _events.ScheduleEvent(EVENT_SUMMON_AHUNE, 10000); + _events.ScheduleEvent(EVENT_START_LOOKING_FOR_OPENING, 14000, 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_SUMMON_COLDWEAVE, 22000, 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_SUMMON_HAILSTONE, 14000, 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_AHUNE_PHASE_TWO, 108000, 0, PHASE_ONE); + } + else if (action == ACTION_STOP_EVENT) + { + _summons.DespawnAll(); + _events.Reset(); + ResetFlameCallers(); + + me->SummonGameObject(GO_ICE_STONE, -69.90455f, -162.2449f, -2.366563f, 2.426008f, 0.0f, 0.0f, 0.9366722f, 0.3502074f, 0); //quaternion + } + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) { - Aura::TryRefreshStackOrCreate(spellInfo, MAX_EFFECT_MASK, summon, summon); + case EVENT_START_LOOKING_FOR_OPENING: + Talk(EMOTE_EARTHEN_ASSAULT); + for (uint8 counter = 0; counter < MAX_FLAMECALLERS; ++counter) + if (Creature* flamecaller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FLAMECALLER_000 + counter))) + DoCast(flamecaller, SPELL_SHAMANS_LOOK_FOR_OPENING, true); + break; + case EVENT_SUMMON_HAILSTONE: + DoCast(SPELL_SUMMON_HAILSTONE); + break; + case EVENT_SUMMON_COLDWEAVE: + DoCast(SPELL_SUMMON_COLDWEAVE); + DoCast(SPELL_SUMMON_COLDWEAVE); + _events.Repeat(8000ms); + if (_submerged) + _events.ScheduleEvent(EVENT_SUMMON_FROSTWIND, 4000, 0, PHASE_ONE); + break; + case EVENT_SUMMON_FROSTWIND: + DoCast(SPELL_SUMMON_FROSTWIND); + break; + case EVENT_SUMMON_AHUNE: + if (TempSummon* ahune = me->SummonCreature(NPC_AHUNE, SummonPositions[0], TEMPSUMMON_DEAD_DESPAWN)) + { + ahune->SummonCreature(NPC_FROZEN_CORE, SummonPositions[1], TEMPSUMMON_CORPSE_DESPAWN); + DoZoneInCombat(ahune); + DoCast(ahune, SPELL_RESURFACE); + } + break; + case EVENT_CLOSE_OPENING: + if (Creature* flamecaller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FLAMECALLER_000))) + flamecaller->AI()->DoAction(ACTION_EMOTE_RESURFACE); + DoCast(SPELL_CLOSE_OPENING_VISUAL); + DoCastSelf(SPELL_ICE_BOMBARD); + break; + case EVENT_AHUNE_PHASE_TWO: + if (Creature* flamecaller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FLAMECALLER_000))) + DoCast(flamecaller, SPELL_FOUND_OPENING); + if (Creature* ahune = _instance->GetCreature(DATA_AHUNE)) + ahune->AI()->DoAction(ACTION_AHUNE_RETREAT); + _events.Reset(); + _events.SetPhase(PHASE_TWO); + _events.ScheduleEvent(EVENT_CLOSE_OPENING, 25000, 0, PHASE_TWO); + _events.ScheduleEvent(EVENT_AHUNE_PHASE_ONE, 35000, 0, PHASE_TWO); + break; + case EVENT_AHUNE_PHASE_ONE: + _submerged = true; + _events.Reset(); + _events.SetPhase(PHASE_ONE); + _events.ScheduleEvent(EVENT_SUMMON_COLDWEAVE, 8000, 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_SUMMON_HAILSTONE, 5000, 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_START_LOOKING_FOR_OPENING, 5000, 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_AHUNE_PHASE_TWO, 100000, 0, PHASE_ONE); + break; + default: + break; } } } - void SummonedCreatureDespawn(Creature* summon) override + void ResetFlameCallers() { - if (summon && summon->GetEntry() == NPC_FROZEN_CORE) + for (uint8 counter = 0; counter < MAX_FLAMECALLERS; ++counter) + if (Creature* flamecaller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FLAMECALLER_000 + counter))) + flamecaller->AI()->EnterEvadeMode(); + } + +private: + InstanceScript* _instance; + EventMap _events; + SummonList _summons; + bool _submerged; +}; + +struct npc_earthen_ring_flamecaller : public ScriptedAI +{ + npc_earthen_ring_flamecaller(Creature* creature) : ScriptedAI(creature) + { + _instance = me->GetInstanceScript(); + _mySpot = 0; + } + + void Reset() override + { + _events.Reset(); + } + + void MovementInform(uint32 motionType, uint32 pointId) override + { + if (motionType != POINT_MOTION_TYPE) + return; + + switch (pointId) { - if (summon->GetHealth() > 0) - { - me->SetHealth(summon->GetHealth()); - summon->CastSpell(summon, SPELL_AHUNE_RESURFACES, true); - } - else - Unit::Kill(me, me, false); + case POINT_FLAMECALLER_000: + _mySpot = POINT_FLAMECALLER_000; + me->SetOrientation(FlameCallerSpots[_mySpot].GetOrientation()); + break; + case POINT_FLAMECALLER_001: + _mySpot = POINT_FLAMECALLER_001; + me->SetOrientation(FlameCallerSpots[_mySpot].GetOrientation()); + break; + case POINT_FLAMECALLER_002: + _mySpot = POINT_FLAMECALLER_002; + me->SetOrientation(FlameCallerSpots[_mySpot].GetOrientation()); + break; + default: + break; + } + + DoCastSelf(SPELL_FIND_OPENING_CHANNEL); + } + + void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override + { + switch (spellInfo->Id) + { + case SPELL_SHAMANS_LOOK_FOR_OPENING: + _events.ScheduleEvent(EVENT_LOOKFOROPENING_0, 17000); + break; + case SPELL_FOUND_OPENING: + Talk(EMOTE_RETREAT); + break; + default: + break; } } - void JustDied(Unit* /*killer*/) override + void DoAction(int action) override { - summons.DespawnAll(); - me->DespawnOrUnsummon(15000); - if (GameObject* chest = me->SummonGameObject(187892, MinionSummonPos.GetPositionX(), MinionSummonPos.GetPositionY(), MinionSummonPos.GetPositionZ(), M_PI / 2, 0.0f, 0.0f, 0.0f, 0.0f, 900000000)) // loot - me->RemoveGameObject(chest, false); + if (action == ACTION_EMOTE_RESURFACE) + Talk(EMOTE_RESURFACE); + } - bool finished = false; + void UpdateAI(uint32 diff) override + { + _events.Update(diff); - me->GetMap()->DoForAllPlayers([&](Player* player) + while (uint32 eventId = _events.ExecuteEvent()) { - player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, 25740, 1, me); - - if (player->GetGroup() && !finished) + switch (eventId) { - finished = true; - sLFGMgr->FinishDungeon(player->GetGroup()->GetGUID(), lfg::LFG_DUNGEON_FROST_LORD_AHUNE, me->FindMap()); + case EVENT_LOOKFOROPENING_0: + LookOpening(true, 0); + _events.ScheduleEvent(EVENT_LOOKFOROPENING_1, 26000); + break; + case EVENT_LOOKFOROPENING_1: + LookOpening(true, 1); + _events.ScheduleEvent(EVENT_LOOKFOROPENING_2, 25000); + break; + case EVENT_LOOKFOROPENING_2: + LookOpening(true, 2); + _events.ScheduleEvent(EVENT_STOP_LOOKING_FOR_OPENING, 27000); + break; + case EVENT_STOP_LOOKING_FOR_OPENING: + LookOpening(false, _mySpot); + break; + default: + break; } - }); + } + } + + void LookOpening(bool activate, uint8 spot) + { + if (_mySpot != spot) + return; + + if (Creature* bonfireBunny = _instance->GetCreature(DATA_BONFIRE_BUNNY_000 + spot)) + if (Creature* beamBunny = _instance->GetCreature(DATA_BEAM_BUNNY_000 + spot)) + { + if (activate) + { + DoCast(bonfireBunny, SPELL_FIND_OPENING_TRIGGER); + bonfireBunny->CastSpell(beamBunny, SPELL_FIND_OPENING_VISUAL, true); + } + else + { + DoCastSelf(SPELL_FIND_OPENING_CHANNEL); + bonfireBunny->CastStop(); + beamBunny->RemoveAurasDueToSpell(SPELL_FIND_OPENING_BEAM_END); + } + } + } + +private: + EventMap _events; + InstanceScript* _instance; + uint8 _mySpot; +}; + +struct npc_ahune_ice_spear_bunny : public ScriptedAI +{ + npc_ahune_ice_spear_bunny(Creature* creature) : ScriptedAI(creature) { } + + void InitializeAI() override + { + DoCastSelf(SPELL_SUMMON_ICE_SPEAR_GO); + DoCastSelf(SPELL_ICE_SPEAR_VISUAL); + + _scheduler.Schedule(2500ms, [this](TaskContext /*task*/) + { + DoCastSelf(SPELL_ICE_SPEAR_DELAY); + me->DespawnOrUnsummon(3500); + }); + } + + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); + } + +private: + TaskScheduler _scheduler; +}; + +struct go_ahune_ice_spear : public GameObjectAI +{ + go_ahune_ice_spear(GameObject* go) : GameObjectAI(go) { } + + void Reset() override + { + _scheduler.Schedule(2500ms, [this](TaskContext /*context*/) + { + me->UseDoorOrButton(); + me->DespawnOrUnsummon(3500ms); + }); + } + + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); + } + +private: + TaskScheduler _scheduler; +}; + +struct go_ahune_ice_stone : public GameObjectAI +{ + go_ahune_ice_stone(GameObject* go) : GameObjectAI(go), _instance(go->GetInstanceScript()) { } + + bool GossipSelect(Player* player, uint32 /*sender*/, uint32 /*action*/) override + { + ClearGossipMenuFor(player); + + if (Creature* ahuneBunny = _instance->GetCreature(DATA_AHUNE_BUNNY)) + ahuneBunny->AI()->DoAction(ACTION_START_EVENT); + + if (Creature* luma = _instance->GetCreature(DATA_LUMA_SKYMOTHER)) + luma->CastSpell(player, SPELL_SUMMONING_RHYME_AURA, true); + CloseGossipMenuFor(player); + me->Delete(); + return true; + } + +private: + InstanceScript* _instance; +}; + +// 46430 - Synch Health +class spell_ahune_synch_health : public SpellScript +{ + PrepareSpellScript(spell_ahune_synch_health); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->SetHealth(GetCaster()->GetHealth()); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_ahune_synch_health::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; -class go_ahune_ice_stone : public GameObjectScript +// 45926 - Summoning Rhyme Aura +class spell_summoning_rhyme_aura : public AuraScript { -public: - go_ahune_ice_stone() : GameObjectScript("go_ahune_ice_stone") { } + PrepareAuraScript(spell_summoning_rhyme_aura); - bool OnGossipHello(Player* player, GameObject* go) override + bool Validate(SpellInfo const* /*spellInfo*/) override { - if (!player || !go) - return true; - - if (!player->IsGameMaster()) - { - if (Group const* group = player->GetGroup()) - { - if (sLFGMgr->GetDungeon(group->GetGUID()) != lfg::LFG_DUNGEON_FROST_LORD_AHUNE) - { - return true; - } - } - } - - if (go->FindNearestCreature(NPC_AHUNE, 200.0f, true)) - return true; - - AddGossipItemFor(player, GOSSIP_ICON_CHAT, "Disturb the stone and summon Lord Ahune.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1337); - SendGossipMenuFor(player, GOSSIP_TEXT_ID, go->GetGUID()); - return true; + return ValidateSpellInfo({ SPELL_FORCE_WHISP_FLIGHT, SPELL_SUMMONING_RHYME_BONFIRE }); } - bool OnGossipSelect(Player* player, GameObject* go, uint32 /*sender*/, uint32 action) override + void PeriodicTick(AuraEffect const* aurEff) { - if (!player || !go) - return true; + if (!GetCaster()) + return; - if (!player->IsGameMaster()) + Creature* caster = GetCaster()->ToCreature(); + Player* player = GetTarget()->ToPlayer(); + if (!caster || !player) + return; + + player->CastSpell(player, SPELL_FORCE_WHISP_FLIGHT); + + switch (aurEff->GetTickNumber()) { - if (Group const* group = player->GetGroup()) - { - if (sLFGMgr->GetDungeon(group->GetGUID()) != lfg::LFG_DUNGEON_FROST_LORD_AHUNE) - { - return true; - } - } + case 1: + sCreatureTextMgr->SendChat(caster, SAY_PLAYER_TEXT_1, nullptr, CHAT_MSG_SAY, LANG_UNIVERSAL, TEXT_RANGE_NORMAL, 0U, TEAM_NEUTRAL, false, player); + player->CastSpell(player, SPELL_SUMMONING_RHYME_BONFIRE, true); + break; + case 2: + sCreatureTextMgr->SendChat(caster, SAY_PLAYER_TEXT_2, nullptr, CHAT_MSG_SAY, LANG_UNIVERSAL, TEXT_RANGE_NORMAL, 0U, TEAM_NEUTRAL, false, player); + break; + case 3: + sCreatureTextMgr->SendChat(caster, SAY_PLAYER_TEXT_3, nullptr, CHAT_MSG_SAY, LANG_UNIVERSAL, TEXT_RANGE_NORMAL, 0U, TEAM_NEUTRAL, false, player); + if (Aura* aur = player->GetAura(SPELL_SUMMONING_RHYME_AURA)) + aur->Remove(); + break; } + } - if (action != GOSSIP_ACTION_INFO_DEF + 1337) - return true; - if (go->FindNearestCreature(NPC_AHUNE, 200.0f, true)) - return true; + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_summoning_rhyme_aura::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } +}; - if (Creature* c = go->SummonCreature(NPC_AHUNE, AhuneSummonPos, TEMPSUMMON_MANUAL_DESPAWN)) - { - player->DestroyItemCount(ITEM_MAGMA_TOTEM, 1, true, false); - player->AreaExploredOrEventHappens(QUEST_SUMMON_AHUNE); // auto rewarded +// 46878 - Summon Ice Spear Delayer +class spell_summon_ice_spear_delayer : public AuraScript +{ + PrepareAuraScript(spell_summon_ice_spear_delayer); - c->SetVisible(false); - c->SetDisplayId(AHUNE_DEFAULT_MODEL); - c->SetFloatValue(UNIT_FIELD_COMBATREACH, 18.0f); - if (c->AI()) + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_ICE_SPEAR_KNOCKBACK }); + } + + void PeriodicTick(AuraEffect const* /*aurEff*/) + { + Unit* target = GetTarget(); + target->CastSpell(target, SPELL_ICE_SPEAR_KNOCKBACK); + if (Aura* aur = GetCaster()->ToCreature()->GetAura(SPELL_ICE_SPEAR_DELAY)) + aur->Remove(); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_summon_ice_spear_delayer::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } +}; + +// 46371 - Ice Spear Control Aura +class spell_ice_spear_control_aura : public AuraScript +{ + PrepareAuraScript(spell_ice_spear_control_aura); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_ICE_SPEAR_TARGET_PICKER }); + } + + void PeriodicTick(AuraEffect const* /*aurEff*/) + { + if (Unit* caster = GetCaster()) + caster->CastSpell(caster, SPELL_ICE_SPEAR_TARGET_PICKER); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_ice_spear_control_aura::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } +}; + +// 46372 - Ice Spear Target Picker +class spell_ice_spear_target_picker : public SpellScript +{ + PrepareSpellScript(spell_ice_spear_target_picker); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_SUMMON_ICE_SPEAR_BUNNY }); + } + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + WorldObject* target = Acore::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(target); + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetHitUnit(), SPELL_SUMMON_ICE_SPEAR_BUNNY, true); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ice_spear_target_picker::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnEffectHitTarget += SpellEffectFn(spell_ice_spear_target_picker::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +// 46320 - Spell Slippery Floor Periodic +class spell_slippery_floor_periodic : public SpellScript +{ + PrepareSpellScript(spell_slippery_floor_periodic); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_SLIPPERY_FLOOR_SLIP }); + } + + void HandleScriptEffect(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + if (target->isMoving()) { - c->AI()->SetGUID(player->GetGUID(), SET_GUID_INVOKER); + target->CastSpell(target, SPELL_SLIPPERY_FLOOR_SLIP, true); + target->CastSpell(target, SPELL_SLIPPERY_FLOOR_YOU_SLIPPED, true); } + } - if (Creature* bunny = go->SummonCreature(NPC_AHUNE_SUMMON_LOC_BUNNY, AhuneSummonPos, TEMPSUMMON_TIMED_DESPAWN, 12000)) - if (Creature* crystal_trigger = go->SummonCreature(WORLD_TRIGGER, go->GetPositionX(), go->GetPositionY(), 5.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 12000)) - crystal_trigger->CastSpell(bunny, SPELL_STARTING_BEAM, false); - } + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_slippery_floor_periodic::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; - CloseGossipMenuFor(player); - return true; +// 46146 - Ahune Spanky Hands +class spell_ahune_spanky_hands : public AuraScript +{ + PrepareAuraScript(spell_ahune_spanky_hands); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_COLD_SLAP }); + } + + void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_COLD_SLAP, true); + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_ahune_spanky_hands::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } +}; + +// 46843 - Minion Despawner +class spell_ahune_minion_despawner : public SpellScript +{ + PrepareSpellScript(spell_ahune_minion_despawner); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (GetHitCreature()) + GetHitCreature()->DespawnOrUnsummon(); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_ahune_minion_despawner::HandleScript, EFFECT_0, SPELL_EFFECT_APPLY_AURA); + } +}; + +// 46398 - Spell Ice Bombardment Dest Picker +class spell_ice_bombardment_dest_picker : public SpellScript +{ + PrepareSpellScript(spell_ice_bombardment_dest_picker); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_ICE_BOMBARDMENT }); + } + + void HandleScriptEffect(SpellEffIndex /*effIndex*/) + { + Position hitDest = GetHitDest()->GetPosition(); + GetCaster()->CastSpell(hitDest.GetPositionX(), hitDest.GetPositionY(), hitDest.GetPositionZ(), SPELL_ICE_BOMBARDMENT, true); + } + + void Register() override + { + OnEffectHit += SpellEffectFn(spell_ice_bombardment_dest_picker::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_DUMMY); } }; void AddSC_boss_ahune() { - new go_ahune_ice_stone(); RegisterTheSlavePensCreatureAI(boss_ahune); + RegisterTheSlavePensCreatureAI(npc_frozen_core); + RegisterTheSlavePensCreatureAI(npc_earthen_ring_flamecaller); + RegisterTheSlavePensCreatureAI(npc_ahune_bunny); + RegisterTheSlavePensCreatureAI(npc_ahune_ice_spear_bunny); + RegisterGameObjectAI(go_ahune_ice_spear); + RegisterGameObjectAI(go_ahune_ice_stone); + RegisterSpellScript(spell_ahune_synch_health); + RegisterSpellScript(spell_summoning_rhyme_aura); + RegisterSpellScript(spell_summon_ice_spear_delayer); + RegisterSpellScript(spell_ice_spear_control_aura); + RegisterSpellScript(spell_ice_spear_target_picker); + RegisterSpellScript(spell_slippery_floor_periodic); + RegisterSpellScript(spell_ahune_spanky_hands); + RegisterSpellScript(spell_ahune_minion_despawner); + RegisterSpellScript(spell_ice_bombardment_dest_picker); } - diff --git a/src/server/scripts/Outland/CoilfangReservoir/SlavePens/instance_the_slave_pens.cpp b/src/server/scripts/Outland/CoilfangReservoir/SlavePens/instance_the_slave_pens.cpp index 2f561789a..bc40dbb1e 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SlavePens/instance_the_slave_pens.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SlavePens/instance_the_slave_pens.cpp @@ -30,8 +30,18 @@ ObjectData const creatureData[] = { - { NPC_QUAGMIRRAN, DATA_QUAGMIRRAN }, - { 0, 0 } + { NPC_QUAGMIRRAN, DATA_QUAGMIRRAN }, + { NPC_AHUNE, DATA_AHUNE }, + { NPC_AHUNE_LOC_BUNNY, DATA_AHUNE_BUNNY }, + { NPC_FROZEN_CORE, DATA_FROZEN_CORE }, + { NPC_SHAMAN_BONFIRE_BUNNY_000, DATA_BONFIRE_BUNNY_000 }, + { NPC_SHAMAN_BONFIRE_BUNNY_001, DATA_BONFIRE_BUNNY_001 }, + { NPC_SHAMAN_BONFIRE_BUNNY_002, DATA_BONFIRE_BUNNY_002 }, + { NPC_SHAMAN_BEAM_BUNNY_000, DATA_BEAM_BUNNY_000 }, + { NPC_SHAMAN_BEAM_BUNNY_001, DATA_BEAM_BUNNY_001 }, + { NPC_SHAMAN_BEAM_BUNNY_002, DATA_BEAM_BUNNY_002 }, + { NPC_LUMA_SKYMOTHER, DATA_LUMA_SKYMOTHER }, + { 0, 0 } }; class instance_the_slave_pens : public InstanceMapScript diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index f1502d756..fc2ad1645 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -114,6 +114,12 @@ private: bool _hasFlag; }; +enum FlagOfOwnership +{ + TEXT_FLAG_OF_OWNERSHIP = 28008, + SPELL_TAUNT_FLAG = 52605 +}; + // 51640 - Taunt Flag Targeting class spell_the_flag_of_ownership : public SpellScript { @@ -126,7 +132,7 @@ class spell_the_flag_of_ownership : public SpellScript return true; } - void HandleScript(SpellEffIndex /*effIndex*/) + void HandleScript(SpellEffIndex /*effIndex*/) { Unit* caster = GetCaster(); if (!caster || caster->GetTypeId() != TYPEID_PLAYER) @@ -134,10 +140,13 @@ class spell_the_flag_of_ownership : public SpellScript Player* target = GetHitPlayer(); if (!target) return; - caster->CastSpell(target, 52605, true); - char buff[100]; - snprintf(buff, sizeof(buff), "%s plants the Flag of Ownership in the corpse of %s.", caster->GetName().c_str(), target->GetName().c_str()); - caster->TextEmote(buff, caster); + caster->CastSpell(target, SPELL_TAUNT_FLAG, true); + + LocaleConstant loc_idx = caster->ToPlayer()->GetSession()->GetSessionDbLocaleIndex(); + BroadcastText const* bct = sObjectMgr->GetBroadcastText(TEXT_FLAG_OF_OWNERSHIP); + std::string bctMsg = Acore::StringFormat(bct->GetText(loc_idx, caster->getGender()), caster->GetName().c_str(), target->GetName().c_str()); + caster->Talk(bctMsg, CHAT_MSG_MONSTER_EMOTE, LANG_UNIVERSAL, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), target); + haveTarget = true; } diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp index 4793489fe..7dcdeb919 100644 --- a/src/server/scripts/Spells/spell_paladin.cpp +++ b/src/server/scripts/Spells/spell_paladin.cpp @@ -90,7 +90,12 @@ enum PaladinSpells // Crystalforge Raiment - Tier 5 Holy 2 Set SPELL_IMPROVED_JUDGEMENT = 37188, - SPELL_IMPROVED_JUDGEMENT_ENERGIZE = 43838 + SPELL_IMPROVED_JUDGEMENT_ENERGIZE = 43838, + + SPELL_PALADIN_HOLY_VENGEANCE = 31803, + SPELL_PALADIN_BLOOD_CORRUPTION = 53742, + SPELL_PALADIN_SEAL_OF_VENGEANCE_EFFECT = 42463, + SPELL_PALADIN_SEAL_OF_CORRUPTION_EFFECT = 53739 }; enum PaladinSpellIcons @@ -1105,6 +1110,45 @@ class spell_pal_seal_of_righteousness : public AuraScript } }; +// 42463 - Seal of Vengeance +// 53739 - Seal of Corruption +class spell_pal_seal_of_vengeance : public SpellScript +{ + PrepareSpellScript(spell_pal_seal_of_vengeance); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_PALADIN_SEAL_OF_VENGEANCE_EFFECT, SPELL_PALADIN_SEAL_OF_CORRUPTION_EFFECT }); + } + + void HandleScriptEffect(SpellEffIndex /*effIndex*/) + { + Unit* target = GetExplTargetUnit(); + uint32 spellId = GetSpell()->GetSpellInfo()->Id; + uint32 auraId = (spellId == SPELL_PALADIN_SEAL_OF_VENGEANCE_EFFECT) + ? SPELL_PALADIN_HOLY_VENGEANCE + : SPELL_PALADIN_BLOOD_CORRUPTION; + int32 damage = GetHitDamage(); + uint8 stacks = 0; + + if (target) + { + Aura* aura = target->GetAura(auraId, GetCaster()->GetGUID()); + if (aura) + stacks = aura->GetStackAmount(); + + damage = ((damage * stacks) / 5); + + SetHitDamage(damage); + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_pal_seal_of_vengeance::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_WEAPON_PERCENT_DAMAGE); + } +}; + void AddSC_paladin_spell_scripts() { RegisterSpellAndAuraScriptPair(spell_pal_seal_of_command, spell_pal_seal_of_command_aura); @@ -1132,5 +1176,6 @@ void AddSC_paladin_spell_scripts() RegisterSpellScript(spell_pal_lay_on_hands); RegisterSpellScript(spell_pal_righteous_defense); RegisterSpellScript(spell_pal_seal_of_righteousness); + RegisterSpellScript(spell_pal_seal_of_vengeance); } diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index f02e4a58e..c0fdf07fe 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -2602,6 +2602,17 @@ public: events.Reset(); } + bool CanAIAttack(Unit const* target) const override + { + if (Unit* summoner = me->GetCharmerOrOwner()) + { + if (target->IsPlayer() && (!summoner->IsPvP() || !target->IsPvP())) + return false; + } + + return true; + } + void JustEngagedWith(Unit* /*who*/) override { events.ScheduleEvent(EVENT_FLAME_BUFFET, 4s); @@ -2610,12 +2621,9 @@ public: void IsSummonedBy(WorldObject* summoner) override { - if (summoner->GetTypeId() != TYPEID_UNIT) - { - return; - } + if (summoner->GetTypeId() == TYPEID_UNIT || summoner->IsPlayer()) + me->GetMotionMaster()->MoveFollow(summoner->ToUnit(), PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); - me->GetMotionMaster()->MoveFollow(summoner->ToUnit(), PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); } void UpdateAI(uint32 diff) override