From afd8cfef9486205472f7ac7c01d081e2d83e3305 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sun, 9 Jun 2024 17:31:27 -0300 Subject: [PATCH 01/73] fix(DB/SAI): Subdue the Subduer should credit group (#19036) --- data/sql/updates/pending_db_world/rev_1717964255204489800.sql | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1717964255204489800.sql diff --git a/data/sql/updates/pending_db_world/rev_1717964255204489800.sql b/data/sql/updates/pending_db_world/rev_1717964255204489800.sql new file mode 100644 index 000000000..7953a4b10 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1717964255204489800.sql @@ -0,0 +1,4 @@ +-- +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\''); From 8a988fd10a1adba402cb6db45d7385c81ff606f9 Mon Sep 17 00:00:00 2001 From: Dan <83884799+elthehablo@users.noreply.github.com> Date: Sun, 9 Jun 2024 22:32:16 +0200 Subject: [PATCH 02/73] fix(Scripts/Hyjal): Air Burst back to random target (#19037) init --- .../CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp index 4ea6dc483..21e6d1c1e 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp @@ -295,7 +295,7 @@ struct boss_archimonde : public BossAI { scheduler.DelayGroup(GROUP_FEAR, 5s); Talk(SAY_AIR_BURST); - DoCastAOE(SPELL_AIR_BURST); + DoCastRandomTarget(SPELL_AIR_BURST); }, 25s, 40s); ScheduleTimedEvent(25s, 35s, [&] { From 24b4975320893caa6bef175517adebfd05a26d7b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 9 Jun 2024 20:32:18 +0000 Subject: [PATCH 03/73] chore(DB): import pending files Referenced commit(s): afd8cfef9486205472f7ac7c01d081e2d83e3305 --- .../rev_1717964255204489800.sql => db_world/2024_06_09_01.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1717964255204489800.sql => db_world/2024_06_09_01.sql} (94%) diff --git a/data/sql/updates/pending_db_world/rev_1717964255204489800.sql b/data/sql/updates/db_world/2024_06_09_01.sql similarity index 94% rename from data/sql/updates/pending_db_world/rev_1717964255204489800.sql rename to data/sql/updates/db_world/2024_06_09_01.sql index 7953a4b10..9a1f1eb2d 100644 --- a/data/sql/updates/pending_db_world/rev_1717964255204489800.sql +++ b/data/sql/updates/db_world/2024_06_09_01.sql @@ -1,3 +1,4 @@ +-- 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 From 289758094ce9d4a457d25f0f42e0b4a855dd7888 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sun, 9 Jun 2024 17:32:29 -0300 Subject: [PATCH 04/73] chore(Scripts/Hyjal): Clean up redundancy (#19035) --- .../CavernsOfTime/BattleForMountHyjal/hyjal.h | 2 + .../BattleForMountHyjal/instance_hyjal.cpp | 126 +++++++----------- 2 files changed, 47 insertions(+), 81 deletions(-) diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h index 4f2493e7c..8575d7e35 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h @@ -90,6 +90,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 +103,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, diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp index 2589d7067..76749ed62 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,7 +87,7 @@ public: SetHeaders(DataHeader); SetBossNumber(EncounterCount); LoadDoorData(doorData); - LoadObjectData(creatureData, objectData); + LoadObjectData(creatureData, nullptr); } void Initialize() override @@ -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()); @@ -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,9 +249,9 @@ 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; } @@ -290,14 +289,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) { @@ -338,13 +337,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)) @@ -399,6 +398,10 @@ public: _bossWave = DATA_ARCHIMONDE; ScheduleWaves(1ms, START_WAVE_NIGHT_ELF, MAX_WAVES_NIGHT_ELF, hyjalNightElfWaveTimers[0]); } + + if (_bossWave) + DoUpdateWorldState(WORLD_STATE_WAVES, 0); + break; case DATA_SPAWN_INFERNALS: { @@ -419,84 +422,46 @@ 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 && (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; @@ -533,10 +498,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 +537,7 @@ public: void Update(uint32 diff) override { - _scheduler.Update(diff); + scheduler.Update(diff); } void OnPlayerInWaterStateUpdate(Player* player, bool inWater) override @@ -588,7 +553,6 @@ public: uint8 _currentWave; uint8 _bossWave; uint8 _retreat; - TaskScheduler _scheduler; GuidSet _encounterNPCs; GuidSet _summonedNPCs; GuidSet _baseAlliance; From 6250936c6a5d8e0608a6af1563b7e2f66643ce87 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sun, 9 Jun 2024 17:32:43 -0300 Subject: [PATCH 05/73] fix(DB/SAI): Watoosun Polluted Essence shouldnt cast Acid Splash (#19038) --- data/sql/updates/pending_db_world/rev_1717965047865056400.sql | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1717965047865056400.sql diff --git a/data/sql/updates/pending_db_world/rev_1717965047865056400.sql b/data/sql/updates/pending_db_world/rev_1717965047865056400.sql new file mode 100644 index 000000000..402b8cf28 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1717965047865056400.sql @@ -0,0 +1,4 @@ +-- +UPDATE `creature_template` SET `AIName` = '' WHERE `entry` = 18145; + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 18145) AND (`source_type` = 0); From 12b187e6e5cb94c03b4e5d64142672616d4e4c3c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 9 Jun 2024 20:33:10 +0000 Subject: [PATCH 06/73] chore(DB): import pending files Referenced commit(s): 8a988fd10a1adba402cb6db45d7385c81ff606f9 --- .../rev_1717965047865056400.sql => db_world/2024_06_09_02.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1717965047865056400.sql => db_world/2024_06_09_02.sql} (77%) diff --git a/data/sql/updates/pending_db_world/rev_1717965047865056400.sql b/data/sql/updates/db_world/2024_06_09_02.sql similarity index 77% rename from data/sql/updates/pending_db_world/rev_1717965047865056400.sql rename to data/sql/updates/db_world/2024_06_09_02.sql index 402b8cf28..f854f30dd 100644 --- a/data/sql/updates/pending_db_world/rev_1717965047865056400.sql +++ b/data/sql/updates/db_world/2024_06_09_02.sql @@ -1,3 +1,4 @@ +-- DB update 2024_06_09_01 -> 2024_06_09_02 -- UPDATE `creature_template` SET `AIName` = '' WHERE `entry` = 18145; From 7a99e0ba82db88da2b632d701acdacb900b0b8be Mon Sep 17 00:00:00 2001 From: daobashun <49193927+fangshun2004@users.noreply.github.com> Date: Tue, 11 Jun 2024 05:05:47 +0800 Subject: [PATCH 07/73] fix:(DB/creatures) Repair the position of the chicken in Southshore (#19043) * Repair the position of the chicken in Southshore * Update rev_1718001686055216100.sql --- .../updates/pending_db_world/rev_1718001686055216100.sql | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1718001686055216100.sql diff --git a/data/sql/updates/pending_db_world/rev_1718001686055216100.sql b/data/sql/updates/pending_db_world/rev_1718001686055216100.sql new file mode 100644 index 000000000..fa303f6b2 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1718001686055216100.sql @@ -0,0 +1,7 @@ +-- 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); From 468bde4cea03e45a3eec8f29c68ea77593a17a3f Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Mon, 10 Jun 2024 18:06:05 -0300 Subject: [PATCH 08/73] fix(DB/Creature): Vashj elementals disorient immunity (#19042) --- data/sql/updates/pending_db_world/rev_1717979069932709000.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1717979069932709000.sql diff --git a/data/sql/updates/pending_db_world/rev_1717979069932709000.sql b/data/sql/updates/pending_db_world/rev_1717979069932709000.sql new file mode 100644 index 000000000..1fa357611 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1717979069932709000.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_template` SET `mechanic_immune_mask` = `mechanic_immune_mask`|2 WHERE `entry` = 21958; From 9ca9c2b651540a9395da826ffc3ec63b5e0ef7f7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 10 Jun 2024 21:06:40 +0000 Subject: [PATCH 09/73] chore(DB): import pending files Referenced commit(s): 7a99e0ba82db88da2b632d701acdacb900b0b8be --- .../rev_1717979069932709000.sql => db_world/2024_06_10_00.sql} | 1 + .../rev_1718001686055216100.sql => db_world/2024_06_10_01.sql} | 1 + 2 files changed, 2 insertions(+) rename data/sql/updates/{pending_db_world/rev_1717979069932709000.sql => db_world/2024_06_10_00.sql} (70%) rename data/sql/updates/{pending_db_world/rev_1718001686055216100.sql => db_world/2024_06_10_01.sql} (95%) diff --git a/data/sql/updates/pending_db_world/rev_1717979069932709000.sql b/data/sql/updates/db_world/2024_06_10_00.sql similarity index 70% rename from data/sql/updates/pending_db_world/rev_1717979069932709000.sql rename to data/sql/updates/db_world/2024_06_10_00.sql index 1fa357611..25c7008e0 100644 --- a/data/sql/updates/pending_db_world/rev_1717979069932709000.sql +++ b/data/sql/updates/db_world/2024_06_10_00.sql @@ -1,2 +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/pending_db_world/rev_1718001686055216100.sql b/data/sql/updates/db_world/2024_06_10_01.sql similarity index 95% rename from data/sql/updates/pending_db_world/rev_1718001686055216100.sql rename to data/sql/updates/db_world/2024_06_10_01.sql index fa303f6b2..eff060073 100644 --- a/data/sql/updates/pending_db_world/rev_1718001686055216100.sql +++ b/data/sql/updates/db_world/2024_06_10_01.sql @@ -1,3 +1,4 @@ +-- 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 From 57d856cd9e1fbc8290a1acef0ac303dc9a7c1187 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Mon, 10 Jun 2024 18:07:03 -0300 Subject: [PATCH 10/73] fix(Scripts/SSC): Fix Serpentshrine Parasites not being summoned (#19041) --- .../CoilfangReservoir/SerpentShrine/instance_serpent_shrine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); } From a9d67490b4aae7c960712e177398b9db28e1b224 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Mon, 10 Jun 2024 18:07:22 -0300 Subject: [PATCH 11/73] fix(DB/Creature): Crystalcore Sentinals & Devastators knockback immunity (#19040) --- data/sql/updates/pending_db_world/rev_1717972134201713800.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1717972134201713800.sql diff --git a/data/sql/updates/pending_db_world/rev_1717972134201713800.sql b/data/sql/updates/pending_db_world/rev_1717972134201713800.sql new file mode 100644 index 000000000..2608c3d80 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1717972134201713800.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_template` SET `flags_extra` = `flags_extra`|1073741824 WHERE `entry` IN (20040, 20041); From 0eace6238217c6f72abf9c548713348e5a3e189c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 10 Jun 2024 21:07:36 +0000 Subject: [PATCH 12/73] chore(DB): import pending files Referenced commit(s): 9ca9c2b651540a9395da826ffc3ec63b5e0ef7f7 --- .../rev_1717972134201713800.sql => db_world/2024_06_10_02.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1717972134201713800.sql => db_world/2024_06_10_02.sql} (71%) diff --git a/data/sql/updates/pending_db_world/rev_1717972134201713800.sql b/data/sql/updates/db_world/2024_06_10_02.sql similarity index 71% rename from data/sql/updates/pending_db_world/rev_1717972134201713800.sql rename to data/sql/updates/db_world/2024_06_10_02.sql index 2608c3d80..6f267fe6c 100644 --- a/data/sql/updates/pending_db_world/rev_1717972134201713800.sql +++ b/data/sql/updates/db_world/2024_06_10_02.sql @@ -1,2 +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); From cfcb5d5bd73fa1208e069df5e8ccfa993cf00690 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Mon, 10 Jun 2024 18:07:48 -0300 Subject: [PATCH 13/73] fix(Scripts/NPC): Fix arcanite dragonling attacking non flagged players (#19039) --- src/server/scripts/World/npcs_special.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) 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 From 9684eb437aae1092455217d9d20c90a09eb4f348 Mon Sep 17 00:00:00 2001 From: Dan <83884799+elthehablo@users.noreply.github.com> Date: Tue, 11 Jun 2024 03:32:50 +0200 Subject: [PATCH 14/73] fix(Scripts/Hyjal): remove very scary call by reference and posis without initialization (#19046) remove call by reference --- .../BattleForMountHyjal/boss_archimonde.cpp | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp index 21e6d1c1e..852d98c60 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 From 77d57efdd1dd16ad477e3ecb5cab87a79a6f98d2 Mon Sep 17 00:00:00 2001 From: Jelle Meeus Date: Tue, 11 Jun 2024 20:42:48 +0200 Subject: [PATCH 15/73] refactor(Scripts/Ulduar): Spell Scripts use registry macros (#19045) * algalon phase punch * algalon collapse * algalon trigger 3 adds * algalon cosmic smash damage * algalon big bang * algalon remove phase * algalon supermassive fail * auriaya sentinel blast * ic shield of runes * ic assembly meltdown * ic rune of summoning * thorim lightning pillar * thorim trash impale * kologarn ulduar stone grip cast target * kologarn stone grip * kologarn squeezed lifeless * kologarn stone shout pair * mimiron rapid burst * mimiron laser barrage * ignis scorch * ignis grab initial * ignis slag pot * ulduar energy sap * ulduar arachnopod damage * xt tympanic tantrum * xt gravity bomb damage * xt gravity bomb pair * xt searing light spwan life spark pair * fl load into catapult * fl auto repair * fl systems shutdown * fl pursue * fl vehicle throw passenger * fl tar blaze * fl vehicle grab pyrite * fl vehicle circuit overload * fl orbital supports * fl thorims hammer * fl transitus shield beam * fl shield generator * fl demolisher ride vehicle * yogg malady of the mind * yogg brain_link pair * yogg shadow beacon * yogg destabilization matrix * yogg titanic storm * yogg lunatic gaze * yogg protective gaze * yogg empowered * yogg insane periodic trigger * yogg insane * yogg sanity well * yogg sanity reduce * yogg empowering shadows yogg empowering shadows * yogg in the mwas of the old god * yogg target selectors * yogg grim reprisal * add sql * fixup! algalon phase punch * fixup! algalon remove phase * fixup! ic assembly meltdown * vezax mark of the faceless periodic * vezax mark of the faceless drainhealth * vezax saronite vapors dummy * vezax saronite vapors damage * vezax aura of despair vezax aura of despair style vezax aura of despair add validate * vezax aura of despair add validate hasspell * Revert "vezax aura of despair add validate hasspell" This reverts commit fccf163399a12119fc468c2fe41ea0798a55eefc. * sort sql --- .../rev_1717949882122545112.sql | 33 + .../Ulduar/boss_algalon_the_observer.cpp | 314 +++--- .../Ulduar/Ulduar/boss_assembly_of_iron.cpp | 117 +-- .../Northrend/Ulduar/Ulduar/boss_auriaya.cpp | 27 +- .../Ulduar/Ulduar/boss_flame_leviathan.cpp | 869 +++++++-------- .../Ulduar/Ulduar/boss_general_vezax.cpp | 265 ++--- .../Northrend/Ulduar/Ulduar/boss_ignis.cpp | 174 +-- .../Northrend/Ulduar/Ulduar/boss_kologarn.cpp | 191 ++-- .../Northrend/Ulduar/Ulduar/boss_mimiron.cpp | 136 ++- .../Northrend/Ulduar/Ulduar/boss_thorim.cpp | 62 +- .../Northrend/Ulduar/Ulduar/boss_xt002.cpp | 252 ++--- .../Ulduar/Ulduar/boss_yoggsaron.cpp | 988 ++++++++---------- .../Northrend/Ulduar/Ulduar/ulduar.cpp | 72 +- 13 files changed, 1518 insertions(+), 1982 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1717949882122545112.sql diff --git a/data/sql/updates/pending_db_world/rev_1717949882122545112.sql b/data/sql/updates/pending_db_world/rev_1717949882122545112.sql new file mode 100644 index 000000000..91ea4bdfd --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1717949882122545112.sql @@ -0,0 +1,33 @@ +-- +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/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); } From 7fe6d2cc9bc80d5e9572529a5f6faa6dd8bafd71 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 11 Jun 2024 18:43:42 +0000 Subject: [PATCH 16/73] chore(DB): import pending files Referenced commit(s): 77d57efdd1dd16ad477e3ecb5cab87a79a6f98d2 --- .../rev_1717949882122545112.sql => db_world/2024_06_11_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1717949882122545112.sql => db_world/2024_06_11_00.sql} (98%) diff --git a/data/sql/updates/pending_db_world/rev_1717949882122545112.sql b/data/sql/updates/db_world/2024_06_11_00.sql similarity index 98% rename from data/sql/updates/pending_db_world/rev_1717949882122545112.sql rename to data/sql/updates/db_world/2024_06_11_00.sql index 91ea4bdfd..ac9b85269 100644 --- a/data/sql/updates/pending_db_world/rev_1717949882122545112.sql +++ b/data/sql/updates/db_world/2024_06_11_00.sql @@ -1,3 +1,4 @@ +-- 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; From 29e747d9204457bab50ce24d924bf0e36db4a05d Mon Sep 17 00:00:00 2001 From: sudlud Date: Tue, 11 Jun 2024 21:27:01 +0200 Subject: [PATCH 17/73] fix(DB/Gameobject): unlink 'Mighty Blaze' spawns from game events (#19049) --- data/sql/updates/pending_db_world/rev_1718130548137611500.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1718130548137611500.sql diff --git a/data/sql/updates/pending_db_world/rev_1718130548137611500.sql b/data/sql/updates/pending_db_world/rev_1718130548137611500.sql new file mode 100644 index 000000000..c03514f4b --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1718130548137611500.sql @@ -0,0 +1,2 @@ +-- 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); From c1816c73da45695922614b841dbd9306040c3e53 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 11 Jun 2024 19:27:53 +0000 Subject: [PATCH 18/73] chore(DB): import pending files Referenced commit(s): 29e747d9204457bab50ce24d924bf0e36db4a05d --- .../rev_1718130548137611500.sql => db_world/2024_06_11_01.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1718130548137611500.sql => db_world/2024_06_11_01.sql} (88%) diff --git a/data/sql/updates/pending_db_world/rev_1718130548137611500.sql b/data/sql/updates/db_world/2024_06_11_01.sql similarity index 88% rename from data/sql/updates/pending_db_world/rev_1718130548137611500.sql rename to data/sql/updates/db_world/2024_06_11_01.sql index c03514f4b..774f0aa4e 100644 --- a/data/sql/updates/pending_db_world/rev_1718130548137611500.sql +++ b/data/sql/updates/db_world/2024_06_11_01.sql @@ -1,2 +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); From da8d42c72cf819f8baeda5cd0450023e7f1d066a Mon Sep 17 00:00:00 2001 From: sudlud Date: Tue, 11 Jun 2024 22:16:47 +0200 Subject: [PATCH 19/73] fix(CI/labeler): update Core, Documentation, Cmake labelling (#19022) fix(CI/labeler: update Core, Documentation, Cmake labelling --- .github/labeler.yml | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) 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: From 7441938bc36ac37f5641f009ed28375bd9c10d43 Mon Sep 17 00:00:00 2001 From: avarishd <46330494+avarishd@users.noreply.github.com> Date: Thu, 13 Jun 2024 16:21:31 +0300 Subject: [PATCH 20/73] fix(DB/Creature): Kadrak's wrong axe model (#19047) fix(DB/Creature): Kadrak's axe --- data/sql/updates/pending_db_world/rev_1718086018134799100.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1718086018134799100.sql diff --git a/data/sql/updates/pending_db_world/rev_1718086018134799100.sql b/data/sql/updates/pending_db_world/rev_1718086018134799100.sql new file mode 100644 index 000000000..5b6646603 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1718086018134799100.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_equip_template` SET `ItemID1` = 12285 WHERE (`CreatureID` = 8582); From 302421ae4b6715ad36a642ebdb49367777e2fd49 Mon Sep 17 00:00:00 2001 From: sudlud Date: Thu, 13 Jun 2024 15:21:53 +0200 Subject: [PATCH 21/73] fix(CI): reintroduce ubuntu-22.04 checks (#19052) - we wan to support the 2 latest ubuntu LTS versions --- .github/workflows/core-build-nopch.yml | 8 ++++++++ .github/workflows/core-build-pch.yml | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/.github/workflows/core-build-nopch.yml b/.github/workflows/core-build-nopch.yml index c26e55988..e3882a860 100644 --- a/.github/workflows/core-build-nopch.yml +++ b/.github/workflows/core-build-nopch.yml @@ -19,6 +19,14 @@ jobs: fail-fast: false 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 57bcd4910..a824e78eb 100644 --- a/.github/workflows/core-build-pch.yml +++ b/.github/workflows/core-build-pch.yml @@ -16,6 +16,10 @@ jobs: fail-fast: false matrix: include: + - os: ubuntu-22.04 + compiler: + CC: clang-15 + CXX: clang++-15 - os: ubuntu-24.04 compiler: CC: clang-18 From 4b40237d10d0a0da6359d5d7ca13ce6807bf53cc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 13 Jun 2024 13:22:26 +0000 Subject: [PATCH 22/73] chore(DB): import pending files Referenced commit(s): 7441938bc36ac37f5641f009ed28375bd9c10d43 --- .../rev_1718086018134799100.sql => db_world/2024_06_13_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1718086018134799100.sql => db_world/2024_06_13_00.sql} (66%) diff --git a/data/sql/updates/pending_db_world/rev_1718086018134799100.sql b/data/sql/updates/db_world/2024_06_13_00.sql similarity index 66% rename from data/sql/updates/pending_db_world/rev_1718086018134799100.sql rename to data/sql/updates/db_world/2024_06_13_00.sql index 5b6646603..b9892154e 100644 --- a/data/sql/updates/pending_db_world/rev_1718086018134799100.sql +++ b/data/sql/updates/db_world/2024_06_13_00.sql @@ -1,2 +1,3 @@ +-- DB update 2024_06_11_01 -> 2024_06_13_00 -- UPDATE `creature_equip_template` SET `ItemID1` = 12285 WHERE (`CreatureID` = 8582); From f846d7947805d5fe1ab99a8f46c9c3d0e1c75658 Mon Sep 17 00:00:00 2001 From: Jelle Meeus Date: Thu, 13 Jun 2024 15:31:35 +0200 Subject: [PATCH 23/73] fix(Core/Pet): Warlock pet handling (#19054) * dismiss summoned non-hunter pets by removing them * store createdbyspellid * Revert "dismiss summoned non-hunter pets by removing them" This reverts commit eb539e841d882a6c90f743792c91304b0d365a5c. --- src/server/game/Entities/Pet/Pet.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 416bb2d0b..f7d56dcb4 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; } From 278ee2a72836137b97de5469af9f8b00229238f9 Mon Sep 17 00:00:00 2001 From: sudlud Date: Thu, 13 Jun 2024 21:52:22 +0200 Subject: [PATCH 24/73] fix(docs): sync SECURITY.md with current CI config (#19057) --- .github/SECURITY.md | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) 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). From 923ea9f29a5c6f1f3462afb917daa0c5a2b6dda8 Mon Sep 17 00:00:00 2001 From: avarishd <46330494+avarishd@users.noreply.github.com> Date: Sat, 15 Jun 2024 01:03:18 +0300 Subject: [PATCH 25/73] fix(DB/Creature): Reth'hedron spawn timer (#19055) --- data/sql/updates/pending_db_world/rev_1718275290940257000.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1718275290940257000.sql diff --git a/data/sql/updates/pending_db_world/rev_1718275290940257000.sql b/data/sql/updates/pending_db_world/rev_1718275290940257000.sql new file mode 100644 index 000000000..724b4fca4 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1718275290940257000.sql @@ -0,0 +1,2 @@ +-- Reth'hedron the Subduer +UPDATE `creature` SET `spawntimesecs` = 90 WHERE `id1` = 22357 AND `guid` = 86754; From 85a2812dbc31a131942a6a9633f828f1fedd6f62 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 14 Jun 2024 22:04:09 +0000 Subject: [PATCH 26/73] chore(DB): import pending files Referenced commit(s): 923ea9f29a5c6f1f3462afb917daa0c5a2b6dda8 --- .../rev_1718275290940257000.sql => db_world/2024_06_14_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1718275290940257000.sql => db_world/2024_06_14_00.sql} (71%) diff --git a/data/sql/updates/pending_db_world/rev_1718275290940257000.sql b/data/sql/updates/db_world/2024_06_14_00.sql similarity index 71% rename from data/sql/updates/pending_db_world/rev_1718275290940257000.sql rename to data/sql/updates/db_world/2024_06_14_00.sql index 724b4fca4..9fe5958e1 100644 --- a/data/sql/updates/pending_db_world/rev_1718275290940257000.sql +++ b/data/sql/updates/db_world/2024_06_14_00.sql @@ -1,2 +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; From 28fae60efc157a6477c4d990fa15f6055e35ee2a Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sat, 15 Jun 2024 13:29:01 -0300 Subject: [PATCH 27/73] fix(DB/Creature): Aqueous Lord formation behaviour (#19064) fix(DB/Formations): Aqueous Spawn formation behaviour --- .../updates/pending_db_world/rev_1718466700851370000.sql | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1718466700851370000.sql diff --git a/data/sql/updates/pending_db_world/rev_1718466700851370000.sql b/data/sql/updates/pending_db_world/rev_1718466700851370000.sql new file mode 100644 index 000000000..0388ad1a5 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1718466700851370000.sql @@ -0,0 +1,9 @@ +-- +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); From c00f89a6fdcf4c41940e0b08b435eaa9ecd03fec Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sat, 15 Jun 2024 13:29:35 -0300 Subject: [PATCH 28/73] fix(DB/Spell): Sludge Nova stack from different casters (#19063) --- data/sql/updates/pending_db_world/rev_1718465866090605600.sql | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1718465866090605600.sql diff --git a/data/sql/updates/pending_db_world/rev_1718465866090605600.sql b/data/sql/updates/pending_db_world/rev_1718465866090605600.sql new file mode 100644 index 000000000..45e2e9132 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1718465866090605600.sql @@ -0,0 +1,3 @@ +-- +DELETE FROM `spell_custom_attr` WHERE `spell_id`=40103; +INSERT INTO `spell_custom_attr` (`spell_id`, `attributes`) VALUES (40103, 4194304); From 549e86f2eb3cafde3b9a91040facd1e508b0e8f7 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sat, 15 Jun 2024 13:29:51 -0300 Subject: [PATCH 29/73] fix(DB/Creature): Aquaneous Lord taunt immunity (#19061) --- data/sql/updates/pending_db_world/rev_1718459860752594600.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1718459860752594600.sql diff --git a/data/sql/updates/pending_db_world/rev_1718459860752594600.sql b/data/sql/updates/pending_db_world/rev_1718459860752594600.sql new file mode 100644 index 000000000..2ac8a2fba --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1718459860752594600.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_template` SET `flags_extra` = `flags_extra` |256 WHERE `entry` = 22878; From 710b25ee36b5d4e02f7cf451b0652eaf60349427 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 15 Jun 2024 16:29:53 +0000 Subject: [PATCH 30/73] chore(DB): import pending files Referenced commit(s): 28fae60efc157a6477c4d990fa15f6055e35ee2a --- .../rev_1718459860752594600.sql => db_world/2024_06_15_00.sql} | 1 + .../rev_1718465866090605600.sql => db_world/2024_06_15_01.sql} | 1 + .../rev_1718466700851370000.sql => db_world/2024_06_15_02.sql} | 1 + 3 files changed, 3 insertions(+) rename data/sql/updates/{pending_db_world/rev_1718459860752594600.sql => db_world/2024_06_15_00.sql} (67%) rename data/sql/updates/{pending_db_world/rev_1718465866090605600.sql => db_world/2024_06_15_01.sql} (76%) rename data/sql/updates/{pending_db_world/rev_1718466700851370000.sql => db_world/2024_06_15_02.sql} (89%) diff --git a/data/sql/updates/pending_db_world/rev_1718459860752594600.sql b/data/sql/updates/db_world/2024_06_15_00.sql similarity index 67% rename from data/sql/updates/pending_db_world/rev_1718459860752594600.sql rename to data/sql/updates/db_world/2024_06_15_00.sql index 2ac8a2fba..27ed63ba4 100644 --- a/data/sql/updates/pending_db_world/rev_1718459860752594600.sql +++ b/data/sql/updates/db_world/2024_06_15_00.sql @@ -1,2 +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/pending_db_world/rev_1718465866090605600.sql b/data/sql/updates/db_world/2024_06_15_01.sql similarity index 76% rename from data/sql/updates/pending_db_world/rev_1718465866090605600.sql rename to data/sql/updates/db_world/2024_06_15_01.sql index 45e2e9132..c72ced768 100644 --- a/data/sql/updates/pending_db_world/rev_1718465866090605600.sql +++ b/data/sql/updates/db_world/2024_06_15_01.sql @@ -1,3 +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/pending_db_world/rev_1718466700851370000.sql b/data/sql/updates/db_world/2024_06_15_02.sql similarity index 89% rename from data/sql/updates/pending_db_world/rev_1718466700851370000.sql rename to data/sql/updates/db_world/2024_06_15_02.sql index 0388ad1a5..e7bd74118 100644 --- a/data/sql/updates/pending_db_world/rev_1718466700851370000.sql +++ b/data/sql/updates/db_world/2024_06_15_02.sql @@ -1,3 +1,4 @@ +-- DB update 2024_06_15_01 -> 2024_06_15_02 -- DELETE FROM `creature_formations` WHERE `leaderGUID` = 148062; From e98e03302e04a51b2637b9a08abfc5fc05f0c205 Mon Sep 17 00:00:00 2001 From: Benjamin Jackson <38561765+heyitsbench@users.noreply.github.com> Date: Sat, 15 Jun 2024 12:34:24 -0400 Subject: [PATCH 31/73] fix(DB/Item): Stormherald PPM adjustment. (#19059) Init. --- data/sql/updates/pending_db_world/stunherald.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 data/sql/updates/pending_db_world/stunherald.sql diff --git a/data/sql/updates/pending_db_world/stunherald.sql b/data/sql/updates/pending_db_world/stunherald.sql new file mode 100644 index 000000000..5f5fc5838 --- /dev/null +++ b/data/sql/updates/pending_db_world/stunherald.sql @@ -0,0 +1 @@ +UPDATE `item_template` SET `spellppmRate_1` = 0.25 WHERE `entry` = 28442; From 564cbca7d37768d78a2b9e90467aad2204e1650b Mon Sep 17 00:00:00 2001 From: sudlud Date: Sat, 15 Jun 2024 18:34:42 +0200 Subject: [PATCH 32/73] feat(CI): enable fail-fast for pch/nopch (#19058) fix(CI): enable fail-fast for pch/nopch --- .github/workflows/core-build-nopch.yml | 2 +- .github/workflows/core-build-pch.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/core-build-nopch.yml b/.github/workflows/core-build-nopch.yml index e3882a860..41a8f0d38 100644 --- a/.github/workflows/core-build-nopch.yml +++ b/.github/workflows/core-build-nopch.yml @@ -16,7 +16,7 @@ concurrency: jobs: build: strategy: - fail-fast: false + fail-fast: true matrix: include: - os: ubuntu-22.04 diff --git a/.github/workflows/core-build-pch.yml b/.github/workflows/core-build-pch.yml index a824e78eb..4da23908a 100644 --- a/.github/workflows/core-build-pch.yml +++ b/.github/workflows/core-build-pch.yml @@ -13,7 +13,7 @@ concurrency: jobs: build: strategy: - fail-fast: false + fail-fast: true matrix: include: - os: ubuntu-22.04 From fb3b17cebc8d3c7328226eb69c13a27e8520375b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 15 Jun 2024 16:35:17 +0000 Subject: [PATCH 33/73] chore(DB): import pending files Referenced commit(s): e98e03302e04a51b2637b9a08abfc5fc05f0c205 --- .../stunherald.sql => db_world/2024_06_15_03.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/stunherald.sql => db_world/2024_06_15_03.sql} (62%) diff --git a/data/sql/updates/pending_db_world/stunherald.sql b/data/sql/updates/db_world/2024_06_15_03.sql similarity index 62% rename from data/sql/updates/pending_db_world/stunherald.sql rename to data/sql/updates/db_world/2024_06_15_03.sql index 5f5fc5838..df14511db 100644 --- a/data/sql/updates/pending_db_world/stunherald.sql +++ b/data/sql/updates/db_world/2024_06_15_03.sql @@ -1 +1,2 @@ +-- DB update 2024_06_15_02 -> 2024_06_15_03 UPDATE `item_template` SET `spellppmRate_1` = 0.25 WHERE `entry` = 28442; From 78aaa136cc1aa728674cc1b0138842f7bf06ae53 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sat, 15 Jun 2024 13:43:30 -0300 Subject: [PATCH 34/73] fix(Scripts/BlackTemple): Fix Free Friend spell (#19065) --- src/server/game/Spells/Auras/SpellAuraEffects.cpp | 1 + .../Outland/BlackTemple/instance_black_temple.cpp | 12 ++---------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 2d0c5c76f..16000a27b 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -4146,6 +4146,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); 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 From e255a3ac3e15a6fb632026d1a1a18561be591877 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sat, 15 Jun 2024 14:01:06 -0300 Subject: [PATCH 35/73] fix(Scripts/BlackTemple): Fix Najentus not enraging after 8 min (#19066) --- .../scripts/Outland/BlackTemple/boss_warlord_najentus.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp b/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp index 58680039f..0cdc8d5b9 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp @@ -43,8 +43,7 @@ enum Spells enum Events { - EVENT_SPELL_BERSERK = 1, - EVENT_TALK_CHECK = 2 + EVENT_TALK_CHECK = 1 }; struct boss_najentus : public BossAI @@ -58,11 +57,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); ScheduleTimedEvent(25s, 100s, [&] { From 9d882739768e0b2eba1e5ad96ad38cfde1799a07 Mon Sep 17 00:00:00 2001 From: Kitzunu <24550914+Kitzunu@users.noreply.github.com> Date: Sat, 15 Jun 2024 22:07:17 +0200 Subject: [PATCH 36/73] fix(DB/Achievement): Pilgrim reward mail (#19067) * closes #18429 --- data/sql/updates/pending_db_world/rev_1718481266706776400.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1718481266706776400.sql diff --git a/data/sql/updates/pending_db_world/rev_1718481266706776400.sql b/data/sql/updates/pending_db_world/rev_1718481266706776400.sql new file mode 100644 index 000000000..e6fe0b938 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1718481266706776400.sql @@ -0,0 +1,2 @@ +-- +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; From 5dae761a947956775ceea5a87dc39bf420b947e6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 15 Jun 2024 20:08:09 +0000 Subject: [PATCH 37/73] chore(DB): import pending files Referenced commit(s): 9d882739768e0b2eba1e5ad96ad38cfde1799a07 --- .../rev_1718481266706776400.sql => db_world/2024_06_15_04.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1718481266706776400.sql => db_world/2024_06_15_04.sql} (92%) diff --git a/data/sql/updates/pending_db_world/rev_1718481266706776400.sql b/data/sql/updates/db_world/2024_06_15_04.sql similarity index 92% rename from data/sql/updates/pending_db_world/rev_1718481266706776400.sql rename to data/sql/updates/db_world/2024_06_15_04.sql index e6fe0b938..4bcaf766a 100644 --- a/data/sql/updates/pending_db_world/rev_1718481266706776400.sql +++ b/data/sql/updates/db_world/2024_06_15_04.sql @@ -1,2 +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; From 03031d36167a686e5679aded25e1b4764ae9af34 Mon Sep 17 00:00:00 2001 From: xaenerys0 Date: Sun, 16 Jun 2024 04:20:25 -0400 Subject: [PATCH 38/73] fix(Scripts/Spells): Flag of Ownership (#18757) Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com> --- src/server/scripts/Spells/spell_generic.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) 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; } From 4e385304c0e6dcf159f66c83df2b5962e3749fd3 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sun, 16 Jun 2024 05:32:04 -0300 Subject: [PATCH 39/73] fix(Scripts/BlackTemple): Fix najentus enrage not reseting (#19074) --- .../Outland/BlackTemple/boss_warlord_najentus.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp b/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp index 0cdc8d5b9..101122b56 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp @@ -43,13 +43,20 @@ enum Spells enum Events { - EVENT_TALK_CHECK = 1 + 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; @@ -60,7 +67,7 @@ struct boss_najentus : public BossAI me->m_Events.AddEventAtOffset([this] { Talk(SAY_ENRAGE); DoCastSelf(SPELL_BERSERK, true); - }, 8min); + }, 8min, EVENT_ENRAGE); ScheduleTimedEvent(25s, 100s, [&] { From d6d49a9e45e5eb59e06fe14d7e4107015fcc0e0e Mon Sep 17 00:00:00 2001 From: Benjamin Jackson <38561765+heyitsbench@users.noreply.github.com> Date: Sun, 16 Jun 2024 12:12:16 -0400 Subject: [PATCH 40/73] refactor(Core/ObjectMgr): Implement display probabilities. (#19068) * Init. Cherry-picked from TC commits https://github.com/TrinityCore/TrinityCore/commit/9d210476e57949094fdd286001ef4900564edca5 and https://github.com/TrinityCore/TrinityCore/commit/c488fb219ab080031488593a0b86ac785a7d2cae Co-Authored-By: Traesh <9392905+traesh@users.noreply.github.com> Co-Authored-By: Shauren * Add brute data. Needs validation against what existed before, i.e. Classic change prevention. * Add validation info for brute data. * Remove incomplete data queries. * Requested changes. * Whitespace. * Requested change. Table name. Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com> * Requested change. Table name. Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com> * Resolve the funny merge conflicts. I wonder why git blame doesn't work on a file with 20k lines in it that's odd huh champ. * Remove unused parameter. * Remove uses of unused parameter. * Use unused parameter. Hopefully? * I will cry. * Sobbing endlessly. * Remove comment. * Adjust table structure query. Remove length parameters and allow null for build value. Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com> * Adjust column datatype and add check constraint. --------- Co-authored-by: Traesh <9392905+traesh@users.noreply.github.com> Co-authored-by: Shauren Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com> --- .../display-probabilities.sql | 24 ++ .../Database/Implementation/WorldDatabase.cpp | 2 +- .../game/AI/SmartScripts/SmartScript.cpp | 8 +- .../game/Entities/Creature/Creature.cpp | 168 +++++--- src/server/game/Entities/Creature/Creature.h | 3 +- .../game/Entities/Creature/CreatureData.h | 30 +- src/server/game/Entities/Pet/Pet.cpp | 4 +- src/server/game/Entities/Pet/Pet.h | 2 +- src/server/game/Entities/Unit/Unit.cpp | 15 +- src/server/game/Entities/Unit/Unit.h | 4 +- src/server/game/Globals/ObjectMgr.cpp | 378 +++++++++--------- src/server/game/Globals/ObjectMgr.h | 5 +- src/server/game/Handlers/QueryHandler.cpp | 44 +- .../game/Spells/Auras/SpellAuraEffects.cpp | 32 +- .../ScarletEnclave/chapter1.cpp | 4 +- 15 files changed, 423 insertions(+), 300 deletions(-) create mode 100644 data/sql/updates/pending_db_world/display-probabilities.sql diff --git a/data/sql/updates/pending_db_world/display-probabilities.sql b/data/sql/updates/pending_db_world/display-probabilities.sql new file mode 100644 index 000000000..296f17fb8 --- /dev/null +++ b/data/sql/updates/pending_db_world/display-probabilities.sql @@ -0,0 +1,24 @@ +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/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/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/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index fbebfb85c..1c84cb317 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(); @@ -1360,9 +1415,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; @@ -2031,11 +2086,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); } } @@ -3414,9 +3470,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; @@ -3430,9 +3486,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 3b8cb2cfc..2903e8f5a 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 @@ -389,6 +406,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/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index f7d56dcb4..a998afa57 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -2418,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/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 0e679cfcc..7e346a5e3 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -17034,13 +17034,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); } @@ -21233,17 +21236,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 3fb0e55ab..16dc4f605 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -2261,10 +2261,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 4b70e9ffe..48a359156 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); @@ -1021,6 +1021,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/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 16000a27b..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; @@ -5793,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; @@ -5823,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/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; From 22c9d689aa179a3c5dfdd3b61150bfc2bc695459 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 16 Jun 2024 16:13:07 +0000 Subject: [PATCH 41/73] chore(DB): import pending files Referenced commit(s): d6d49a9e45e5eb59e06fe14d7e4107015fcc0e0e --- .../display-probabilities.sql => db_world/2024_06_16_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/display-probabilities.sql => db_world/2024_06_16_00.sql} (97%) diff --git a/data/sql/updates/pending_db_world/display-probabilities.sql b/data/sql/updates/db_world/2024_06_16_00.sql similarity index 97% rename from data/sql/updates/pending_db_world/display-probabilities.sql rename to data/sql/updates/db_world/2024_06_16_00.sql index 296f17fb8..0f9d4369e 100644 --- a/data/sql/updates/pending_db_world/display-probabilities.sql +++ b/data/sql/updates/db_world/2024_06_16_00.sql @@ -1,3 +1,4 @@ +-- 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, From cf258bc9696ab0d1547a016bbc57631d63145c3e Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sun, 16 Jun 2024 13:14:31 -0300 Subject: [PATCH 42/73] =?UTF-8?q?fix(DB/Spells):=20Infinity=20Blade's=20Ma?= =?UTF-8?q?gic=20Disruption=20should=20stack=20for=20di=E2=80=A6=20(#19077?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix(DB/Spells): Infinity Blade's Magic Disruption should stack for different casters --- data/sql/updates/pending_db_world/rev_1718547209203696600.sql | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1718547209203696600.sql diff --git a/data/sql/updates/pending_db_world/rev_1718547209203696600.sql b/data/sql/updates/pending_db_world/rev_1718547209203696600.sql new file mode 100644 index 000000000..c5e2952d1 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1718547209203696600.sql @@ -0,0 +1,3 @@ +-- +DELETE FROM `spell_custom_attr` WHERE `spell_id`=36478; +INSERT INTO `spell_custom_attr` (`spell_id`, `attributes`) VALUES (36478, 4194304); From 737f487faef1c9bdbbf238ab0f0ec000b3d5089a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 16 Jun 2024 16:15:22 +0000 Subject: [PATCH 43/73] chore(DB): import pending files Referenced commit(s): cf258bc9696ab0d1547a016bbc57631d63145c3e --- .../rev_1718547209203696600.sql => db_world/2024_06_16_01.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1718547209203696600.sql => db_world/2024_06_16_01.sql} (76%) diff --git a/data/sql/updates/pending_db_world/rev_1718547209203696600.sql b/data/sql/updates/db_world/2024_06_16_01.sql similarity index 76% rename from data/sql/updates/pending_db_world/rev_1718547209203696600.sql rename to data/sql/updates/db_world/2024_06_16_01.sql index c5e2952d1..790f117a0 100644 --- a/data/sql/updates/pending_db_world/rev_1718547209203696600.sql +++ b/data/sql/updates/db_world/2024_06_16_01.sql @@ -1,3 +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); From 9e122a0cad6dc57e22e6d689ea7a763c430a6d78 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sun, 16 Jun 2024 13:57:51 -0300 Subject: [PATCH 44/73] =?UTF-8?q?fix(Core/AI):=20Fix=20bosses=20being=20st?= =?UTF-8?q?uck=20IN=5FPROGRESS=20if=20despawnonevade=20fl=E2=80=A6=20(#190?= =?UTF-8?q?70)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix(Core/AI): Fix bosses being stuck IN_PROGRESS if despawnonevade flag is used --- src/server/game/AI/CreatureAI.cpp | 4 ++-- src/server/game/AI/ScriptedAI/ScriptedCreature.cpp | 10 ++++++++++ src/server/game/AI/ScriptedAI/ScriptedCreature.h | 2 ++ .../scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) 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/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); From 95221c4d505d964ce5ef2538e4dedbb48f5e2d63 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sun, 16 Jun 2024 13:58:14 -0300 Subject: [PATCH 45/73] =?UTF-8?q?fix(Scripts/Hyjal):=20Archimonde=20should?= =?UTF-8?q?=20gain=20charges=20regardless=20of=20deat=E2=80=A6=20(#19069)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(Scripts/Hyjal): Archimonde should gain charges regardless of death cause * Update instance_hyjal.cpp * fix boss waves --- .../BattleForMountHyjal/boss_archimonde.cpp | 71 +++++++++---------- .../CavernsOfTime/BattleForMountHyjal/hyjal.h | 19 +++-- .../BattleForMountHyjal/instance_hyjal.cpp | 39 +++++----- 3 files changed, 64 insertions(+), 65 deletions(-) diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp index 852d98c60..5cc549636 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp @@ -187,7 +187,7 @@ struct boss_archimonde : public BossAI void Reset() override { - BossAI::Reset(); + _Reset(); _wispCount = 0; _isChanneling = false; _enraged = false; @@ -279,7 +279,7 @@ struct boss_archimonde : public BossAI void JustEngagedWith(Unit* who) override { - BossAI::JustEngagedWith(who); + _JustEngagedWith(); me->InterruptNonMeleeSpells(false); Talk(SAY_AGGRO); ScheduleTimedEvent(25s, 35s, [&] @@ -348,46 +348,43 @@ struct boss_archimonde : public BossAI 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 diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h index 8575d7e35..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, @@ -154,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 76749ed62..3e518ecca 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp @@ -92,7 +92,7 @@ public: void Initialize() override { - _bossWave = 0; + _bossWave = TO_BE_DECIDED; _retreat = 0; trash = 0; _currentWave = 0; @@ -185,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 @@ -228,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 @@ -256,6 +256,11 @@ public: 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 @@ -263,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) @@ -312,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) { @@ -359,39 +364,39 @@ 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) { @@ -399,7 +404,7 @@ public: ScheduleWaves(1ms, START_WAVE_NIGHT_ELF, MAX_WAVES_NIGHT_ELF, hyjalNightElfWaveTimers[0]); } - if (_bossWave) + if (_bossWave != TO_BE_DECIDED) DoUpdateWorldState(WORLD_STATE_WAVES, 0); break; @@ -455,7 +460,7 @@ public: if (Creature* creature = instance->GetCreature(guid)) creature->DespawnOrUnsummon(); - if (_bossWave && (GetBossState(_bossWave) != DONE)) + if (_bossWave != TO_BE_DECIDED && (GetBossState(_bossWave) != DONE)) SetBossState(_bossWave, NOT_STARTED); SetData(DATA_RESET_WAVES, 0); @@ -466,7 +471,7 @@ public: _summonedNPCs.clear(); _currentWave = 0; trash = 0; - _bossWave = 0; + _bossWave = TO_BE_DECIDED; _retreat = 0; DoUpdateWorldState(WORLD_STATE_WAVES, _currentWave); DoUpdateWorldState(WORLD_STATE_ENEMY, trash); From 36621804b9732a16485fd85bde71a944464fdfb7 Mon Sep 17 00:00:00 2001 From: Benjamin Jackson <38561765+heyitsbench@users.noreply.github.com> Date: Sun, 16 Jun 2024 17:27:38 -0400 Subject: [PATCH 46/73] fix(DB/Creature): Correct model info for Black Temple bosses. (#19079) * Init. * Consolidate, remove comments. --- data/sql/updates/pending_db_world/bt-bosses.sql | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 data/sql/updates/pending_db_world/bt-bosses.sql diff --git a/data/sql/updates/pending_db_world/bt-bosses.sql b/data/sql/updates/pending_db_world/bt-bosses.sql new file mode 100644 index 000000000..018afd683 --- /dev/null +++ b/data/sql/updates/pending_db_world/bt-bosses.sql @@ -0,0 +1,9 @@ +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; From b159d32cba90b195f7798989c9f6941869a73109 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 16 Jun 2024 21:28:32 +0000 Subject: [PATCH 47/73] chore(DB): import pending files Referenced commit(s): 36621804b9732a16485fd85bde71a944464fdfb7 --- .../bt-bosses.sql => db_world/2024_06_16_02.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/bt-bosses.sql => db_world/2024_06_16_02.sql} (96%) diff --git a/data/sql/updates/pending_db_world/bt-bosses.sql b/data/sql/updates/db_world/2024_06_16_02.sql similarity index 96% rename from data/sql/updates/pending_db_world/bt-bosses.sql rename to data/sql/updates/db_world/2024_06_16_02.sql index 018afd683..fef09ca20 100644 --- a/data/sql/updates/pending_db_world/bt-bosses.sql +++ b/data/sql/updates/db_world/2024_06_16_02.sql @@ -1,3 +1,4 @@ +-- 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; From 3211c7d884a2eeba1949e7a5b7310f0bedfa77a3 Mon Sep 17 00:00:00 2001 From: Jelle Meeus Date: Mon, 17 Jun 2024 00:00:07 +0200 Subject: [PATCH 48/73] fix(Scripts/ObsidianSanctum): add Flame Tsunami knockback (#19078) * refactor spellscript refactor spellscript * add flame tsunami knockback --- .../rev_1718486949488763477.sql | 5 + .../ObsidianSanctum/boss_sartharion.cpp | 158 +++++++++++------- 2 files changed, 106 insertions(+), 57 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1718486949488763477.sql diff --git a/data/sql/updates/pending_db_world/rev_1718486949488763477.sql b/data/sql/updates/pending_db_world/rev_1718486949488763477.sql new file mode 100644 index 000000000..9c1ad618e --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1718486949488763477.sql @@ -0,0 +1,5 @@ +-- +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/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); } - From 20ff8df91ca7f563246cd367894b111f067b532a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 16 Jun 2024 22:01:03 +0000 Subject: [PATCH 49/73] chore(DB): import pending files Referenced commit(s): 3211c7d884a2eeba1949e7a5b7310f0bedfa77a3 --- .../rev_1718486949488763477.sql => db_world/2024_06_16_03.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1718486949488763477.sql => db_world/2024_06_16_03.sql} (84%) diff --git a/data/sql/updates/pending_db_world/rev_1718486949488763477.sql b/data/sql/updates/db_world/2024_06_16_03.sql similarity index 84% rename from data/sql/updates/pending_db_world/rev_1718486949488763477.sql rename to data/sql/updates/db_world/2024_06_16_03.sql index 9c1ad618e..36992021f 100644 --- a/data/sql/updates/pending_db_world/rev_1718486949488763477.sql +++ b/data/sql/updates/db_world/2024_06_16_03.sql @@ -1,3 +1,4 @@ +-- 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 From 5f966e8e0c7bb104949d5e06e47ad8e2d4237a2c Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Mon, 17 Jun 2024 16:37:43 -0300 Subject: [PATCH 50/73] chore(Scripts/Hyjal): Remove unneeded Archimonde spell scripts (#19080) * chore(Scripts/Hyjal): Remove unneeded spell scripts * use trigger flags * Update boss_archimonde.cpp * Update boss_archimonde.cpp --- .../rev_1718581107240568800.sql | 3 + .../BattleForMountHyjal/boss_archimonde.cpp | 72 ++----------------- 2 files changed, 7 insertions(+), 68 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1718581107240568800.sql diff --git a/data/sql/updates/pending_db_world/rev_1718581107240568800.sql b/data/sql/updates/pending_db_world/rev_1718581107240568800.sql new file mode 100644 index 000000000..a82272d91 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1718581107240568800.sql @@ -0,0 +1,3 @@ +-- +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/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp index 5cc549636..cdf4fc11a 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp @@ -194,15 +194,6 @@ struct boss_archimonde : public BossAI _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); @@ -216,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); @@ -225,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)) @@ -253,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); @@ -264,20 +253,7 @@ struct boss_archimonde : public BossAI } } - void DoCastProtection() - { - 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 + void JustEngagedWith(Unit* /*who*/) override { _JustEngagedWith(); me->InterruptNonMeleeSpells(false); @@ -345,7 +321,7 @@ struct boss_archimonde : public BossAI instance->SetData(DATA_SPAWN_WAVES, 1); } - void KilledUnit(Unit* victim) override + void KilledUnit(Unit* /*victim*/) override { Talk(SAY_SLAY); } @@ -431,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); @@ -495,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); @@ -552,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); From 90ec2d6cbe0b2f3f1776704a35ab375c5975790b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 17 Jun 2024 19:38:36 +0000 Subject: [PATCH 51/73] chore(DB): import pending files Referenced commit(s): 5f966e8e0c7bb104949d5e06e47ad8e2d4237a2c --- .../rev_1718581107240568800.sql => db_world/2024_06_17_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1718581107240568800.sql => db_world/2024_06_17_00.sql} (82%) diff --git a/data/sql/updates/pending_db_world/rev_1718581107240568800.sql b/data/sql/updates/db_world/2024_06_17_00.sql similarity index 82% rename from data/sql/updates/pending_db_world/rev_1718581107240568800.sql rename to data/sql/updates/db_world/2024_06_17_00.sql index a82272d91..7bc1f67be 100644 --- a/data/sql/updates/pending_db_world/rev_1718581107240568800.sql +++ b/data/sql/updates/db_world/2024_06_17_00.sql @@ -1,3 +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); From e0cf15db93cdcccedefb2c72d5c7dec1005bcb74 Mon Sep 17 00:00:00 2001 From: AnchyDev <35346484+AnchyDev@users.noreply.github.com> Date: Tue, 18 Jun 2024 05:39:11 +1000 Subject: [PATCH 52/73] fix(Scripts/Misc) CanExecuteCommand renamed and moved to be executed for all commands. (#19081) * Fix CanExecuteCommand only being executed on command failure. * Updated for style guide. * Removed pointless hook call. * Modified the name of the hook to better reflect function and moved the call to trigger for non-existent commands. * Updated to OnTryExecuteCommand because Foe has a special place in my heart. * Forgot to change these 2 areas. --- .../game/Chat/ChatCommands/ChatCommand.cpp | 16 +++++----------- .../Scripting/ScriptDefines/AllCommandScript.cpp | 4 ++-- .../Scripting/ScriptDefines/AllCommandScript.h | 6 +++--- src/server/game/Scripting/ScriptMgr.h | 2 +- 4 files changed, 11 insertions(+), 17 deletions(-) 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/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 c65e40953..b767487a2 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -670,7 +670,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 */ From 916a8ef618690fecee0df2b2a68b753853b6b192 Mon Sep 17 00:00:00 2001 From: Jelle Meeus Date: Mon, 17 Jun 2024 21:42:45 +0200 Subject: [PATCH 53/73] fix(Scripts/BlackTemple): Akama shade missing says (#19076) Co-authored-by: Keader --- .../Outland/BlackTemple/boss_shade_of_akama.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) 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 From 4b5468face38ca051cf4ba010c1628651cc41d72 Mon Sep 17 00:00:00 2001 From: Benjamin Jackson <38561765+heyitsbench@users.noreply.github.com> Date: Mon, 17 Jun 2024 15:57:23 -0400 Subject: [PATCH 54/73] fix(Scripts/SlavePens): Rewrite Ahune. (#19075) * Add WPP SQL output. * Uncomment all entries. With one exception, one that does not exist in DB * Sort all by template entry. * Add reference names for templates. * Distinguish summons from static spawns. * Separate summons from static spawns in SQL parse. * Add timestamps and spell casts for creatures. * Init spawn query. * Init script stuff. * Init port work. Co-Authored-By: Gustavo * Bad flag porting. * Update stand states and unit flags properly. * Adjust SQL. * Add birth spell. Properly shows the desired animation, to be verified through sniffs if he actually casts it. * Update Frozen Core model data. Collected from TC master branch. Will correct with proper data once sniff data becomes available. * Elaborate rhyme aura text functions. Co-Authored-By: sudlud * Adjust for structure changes. * Elaborate delete queries. --------- Co-authored-by: Gustavo Co-authored-by: sudlud --- data/sql/updates/pending_db_world/ahune.sql | 320 +++++ .../SlavePens/boss_ahune.cpp | 1092 ++++++++++++----- .../SlavePens/instance_the_slave_pens.cpp | 14 +- 3 files changed, 1136 insertions(+), 290 deletions(-) create mode 100644 data/sql/updates/pending_db_world/ahune.sql diff --git a/data/sql/updates/pending_db_world/ahune.sql b/data/sql/updates/pending_db_world/ahune.sql new file mode 100644 index 000000000..8609ad977 --- /dev/null +++ b/data/sql/updates/pending_db_world/ahune.sql @@ -0,0 +1,320 @@ +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/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 From e76a5ad0f2f7a84d503a4dd9c81c7f54ceb12162 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 17 Jun 2024 19:58:19 +0000 Subject: [PATCH 55/73] chore(DB): import pending files Referenced commit(s): 4b5468face38ca051cf4ba010c1628651cc41d72 --- .../{pending_db_world/ahune.sql => db_world/2024_06_17_01.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/ahune.sql => db_world/2024_06_17_01.sql} (99%) diff --git a/data/sql/updates/pending_db_world/ahune.sql b/data/sql/updates/db_world/2024_06_17_01.sql similarity index 99% rename from data/sql/updates/pending_db_world/ahune.sql rename to data/sql/updates/db_world/2024_06_17_01.sql index 8609ad977..0c567e8c8 100644 --- a/data/sql/updates/pending_db_world/ahune.sql +++ b/data/sql/updates/db_world/2024_06_17_01.sql @@ -1,3 +1,4 @@ +-- DB update 2024_06_17_00 -> 2024_06_17_01 SET @OGUID := 1267; -- 21 free guids required SET @CGUID := 12529; -- 21 free guids required From 10892a519d2b529205729a3c67308fcae70ac1f9 Mon Sep 17 00:00:00 2001 From: Lyuboslav Kotsev Date: Mon, 17 Jun 2024 23:05:07 +0300 Subject: [PATCH 56/73] =?UTF-8?q?fix(core/spell):=20Presence=20of=20Mind?= =?UTF-8?q?=20should=20not=20apply=20cooldown=20mods=20on=20c=E2=80=A6=20(?= =?UTF-8?q?#17890)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix(core/spell): Presence of Mind should not apply cooldown mods on category spells. Mage T4 set 4 set bonus puts cooldown reduction on Presence of Mind which should not be passed down to category spells, because in case of infinity cooldown on Arcane Power it does not get reset when you lose the Presence of Mind aura and Arcane Power stays forever in cooldown or more specifically for 1 month(infinity cooldown). Closes https://github.com/azerothcore/azerothcore-wotlk/issues/17800 Patch 3.0.9 https://wowpedia.fandom.com/wiki/Patch_3.0.9 Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com> --- src/server/game/Spells/SpellInfoCorrections.cpp | 7 +++++++ 1 file changed, 7 insertions(+) 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]; From 4b0202a5254ec297612a42bf2f2fa27178d50e8f Mon Sep 17 00:00:00 2001 From: avarishd <46330494+avarishd@users.noreply.github.com> Date: Tue, 18 Jun 2024 03:25:35 +0300 Subject: [PATCH 57/73] fix(DB/Creature): Archmage Xylem patrol from mangos-wotlk (#19083) fix(DB/Creature): Archmage Xylem pathing --- .../rev_1718663929978276800.sql | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1718663929978276800.sql diff --git a/data/sql/updates/pending_db_world/rev_1718663929978276800.sql b/data/sql/updates/pending_db_world/rev_1718663929978276800.sql new file mode 100644 index 000000000..04306e388 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1718663929978276800.sql @@ -0,0 +1,35 @@ +-- 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); From 2cf95ca6cbba43139684b3f5ec18c1cf71166f52 Mon Sep 17 00:00:00 2001 From: avarishd <46330494+avarishd@users.noreply.github.com> Date: Tue, 18 Jun 2024 03:26:18 +0300 Subject: [PATCH 58/73] =?UTF-8?q?fix(Core/Spells):=20Don't=20send=20SMSG?= =?UTF-8?q?=5FCAST=5FFAILED=20for=20interrupted=20spells=20=E2=80=A6=20(#1?= =?UTF-8?q?9082)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix(Core/Spells): Don't send SMSG_CAST_FAILED for interrupted spells after they were launched or channelling was started (this clears cooldown on client) https: //github.com/TrinityCore/TrinityCore/commit/63bc405faeb7afcf99de6f7531e4ea59065165f4 Co-authored-by: Shauren --- src/server/game/Spells/Spell.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 5263c701b..f49653242 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()) From ef87925f28804692c67a1511f9862b636bb0b2c0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 18 Jun 2024 00:26:27 +0000 Subject: [PATCH 59/73] chore(DB): import pending files Referenced commit(s): 4b0202a5254ec297612a42bf2f2fa27178d50e8f --- .../rev_1718663929978276800.sql => db_world/2024_06_18_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1718663929978276800.sql => db_world/2024_06_18_00.sql} (98%) diff --git a/data/sql/updates/pending_db_world/rev_1718663929978276800.sql b/data/sql/updates/db_world/2024_06_18_00.sql similarity index 98% rename from data/sql/updates/pending_db_world/rev_1718663929978276800.sql rename to data/sql/updates/db_world/2024_06_18_00.sql index 04306e388..3e07188b7 100644 --- a/data/sql/updates/pending_db_world/rev_1718663929978276800.sql +++ b/data/sql/updates/db_world/2024_06_18_00.sql @@ -1,3 +1,4 @@ +-- 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 From 8f39e88567408fb03740739d93ca78a9b373a846 Mon Sep 17 00:00:00 2001 From: Benjamin Jackson <38561765+heyitsbench@users.noreply.github.com> Date: Mon, 17 Jun 2024 20:27:03 -0400 Subject: [PATCH 60/73] fix(DB/Procs): Add proc info for lower ranks of Reckoning talent. (#19071) * Init. * Adjust query. Use the rank system supported by the table rather than add the individual rank spell IDs. * Remove redundant query segment. --- data/sql/updates/pending_db_world/reckoning-downrank.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 data/sql/updates/pending_db_world/reckoning-downrank.sql diff --git a/data/sql/updates/pending_db_world/reckoning-downrank.sql b/data/sql/updates/pending_db_world/reckoning-downrank.sql new file mode 100644 index 000000000..25e515e44 --- /dev/null +++ b/data/sql/updates/pending_db_world/reckoning-downrank.sql @@ -0,0 +1 @@ +UPDATE `spell_proc_event` SET `entry` = -20177 WHERE `entry` = 20182; From 3d95ba220adfff873543d1e0c1a5a31154d68c9f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 18 Jun 2024 00:27:12 +0000 Subject: [PATCH 61/73] chore(DB): import pending files Referenced commit(s): 2cf95ca6cbba43139684b3f5ec18c1cf71166f52 --- .../reckoning-downrank.sql => db_world/2024_06_18_01.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/reckoning-downrank.sql => db_world/2024_06_18_01.sql} (61%) diff --git a/data/sql/updates/pending_db_world/reckoning-downrank.sql b/data/sql/updates/db_world/2024_06_18_01.sql similarity index 61% rename from data/sql/updates/pending_db_world/reckoning-downrank.sql rename to data/sql/updates/db_world/2024_06_18_01.sql index 25e515e44..d374e0ead 100644 --- a/data/sql/updates/pending_db_world/reckoning-downrank.sql +++ b/data/sql/updates/db_world/2024_06_18_01.sql @@ -1 +1,2 @@ +-- DB update 2024_06_18_00 -> 2024_06_18_01 UPDATE `spell_proc_event` SET `entry` = -20177 WHERE `entry` = 20182; From 2319789804e5e11f88ef2d8cb2766fc957bca870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A9=E9=B9=BF?= <18535853+PkllonG@users.noreply.github.com> Date: Tue, 18 Jun 2024 17:19:20 +0800 Subject: [PATCH 62/73] fix(DB/Hyjal): Update conditions after boss index change (#19086) * Create Hyjal * Delete data/sql/updates/pending_db_world/Hyjal * Add files via upload --- data/sql/updates/pending_db_world/Hyjal.sql | 59 +++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 data/sql/updates/pending_db_world/Hyjal.sql diff --git a/data/sql/updates/pending_db_world/Hyjal.sql b/data/sql/updates/pending_db_world/Hyjal.sql new file mode 100644 index 000000000..311752d38 --- /dev/null +++ b/data/sql/updates/pending_db_world/Hyjal.sql @@ -0,0 +1,59 @@ +-- +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'); From 90de4bb230c1e0a4900a084439a70d69409696ca Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 18 Jun 2024 09:20:13 +0000 Subject: [PATCH 63/73] chore(DB): import pending files Referenced commit(s): 2319789804e5e11f88ef2d8cb2766fc957bca870 --- .../{pending_db_world/Hyjal.sql => db_world/2024_06_18_02.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/Hyjal.sql => db_world/2024_06_18_02.sql} (98%) diff --git a/data/sql/updates/pending_db_world/Hyjal.sql b/data/sql/updates/db_world/2024_06_18_02.sql similarity index 98% rename from data/sql/updates/pending_db_world/Hyjal.sql rename to data/sql/updates/db_world/2024_06_18_02.sql index 311752d38..769659e12 100644 --- a/data/sql/updates/pending_db_world/Hyjal.sql +++ b/data/sql/updates/db_world/2024_06_18_02.sql @@ -1,3 +1,4 @@ +-- 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 From dea3748629e61434cf3e6cc73dd5223f04b1a9b2 Mon Sep 17 00:00:00 2001 From: atrapalis <104009206+atrapalis@users.noreply.github.com> Date: Wed, 19 Jun 2024 01:41:39 +0300 Subject: [PATCH 64/73] fix(Core/Quest): Correct XP Display when modified by SPELL_AURA_MOD_XP_QUEST_PCT (#19060) * fix(Core): Correct Quest XP Display when modified by SPELL_AURA_MOD_XP_QUEST_PCT The quest XP displayed on the gossip window was not modified for auras that increase quest XP gain (e.g. spell ID 57353). This commit corrects the quest XP display when accepting/returning quests. * refactor(Entities/Player): Added a `CalculateQuestRewardXP()` function to reduce duplicated code * cleanup(Entities/Creature): Removed now unused variable `playerLevel` * Apply suggestions from code review Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com> --------- Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com> --- .../game/Entities/Creature/GossipDef.cpp | 6 ++---- src/server/game/Entities/Player/Player.h | 1 + .../game/Entities/Player/PlayerQuest.cpp | 20 +++++++++++++------ 3 files changed, 17 insertions(+), 10 deletions(-) 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/Player/Player.h b/src/server/game/Entities/Player/Player.h index f10be00ed..ffdcc28e2 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 9c0eded90..f71d8a6f7 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; @@ -1398,6 +1393,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); From a644425758414071046d91f7701f5176955316f1 Mon Sep 17 00:00:00 2001 From: avarishd <46330494+avarishd@users.noreply.github.com> Date: Wed, 19 Jun 2024 01:42:24 +0300 Subject: [PATCH 65/73] fix(DB/Creature): Port Force-Commander Gorax patrol from mangos-wotlk (#19089) --- .../pending_db_world/rev_1718712283431197500.sql | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1718712283431197500.sql diff --git a/data/sql/updates/pending_db_world/rev_1718712283431197500.sql b/data/sql/updates/pending_db_world/rev_1718712283431197500.sql new file mode 100644 index 000000000..b7f1dcfb8 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1718712283431197500.sql @@ -0,0 +1,11 @@ +-- 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); From 980808422c3364d9788950b3627366cd4af65757 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 18 Jun 2024 22:42:35 +0000 Subject: [PATCH 66/73] chore(DB): import pending files Referenced commit(s): dea3748629e61434cf3e6cc73dd5223f04b1a9b2 --- .../rev_1718712283431197500.sql => db_world/2024_06_18_03.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1718712283431197500.sql => db_world/2024_06_18_03.sql} (95%) diff --git a/data/sql/updates/pending_db_world/rev_1718712283431197500.sql b/data/sql/updates/db_world/2024_06_18_03.sql similarity index 95% rename from data/sql/updates/pending_db_world/rev_1718712283431197500.sql rename to data/sql/updates/db_world/2024_06_18_03.sql index b7f1dcfb8..1741cac98 100644 --- a/data/sql/updates/pending_db_world/rev_1718712283431197500.sql +++ b/data/sql/updates/db_world/2024_06_18_03.sql @@ -1,3 +1,4 @@ +-- DB update 2024_06_18_02 -> 2024_06_18_03 -- Force-Commander Gorax UPDATE `creature_template_addon` SET `path_id` = 1926400 WHERE `entry` = 19264; From 95543437bf272a82fd1707d1f6915a6ebbf97a8e Mon Sep 17 00:00:00 2001 From: avarishd <46330494+avarishd@users.noreply.github.com> Date: Wed, 19 Jun 2024 01:43:04 +0300 Subject: [PATCH 67/73] fix(DB/Creature): Mote of Shadow incorrect low value for 2 npcs (#19088) --- data/sql/updates/pending_db_world/rev_1718710211512527300.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1718710211512527300.sql diff --git a/data/sql/updates/pending_db_world/rev_1718710211512527300.sql b/data/sql/updates/pending_db_world/rev_1718710211512527300.sql new file mode 100644 index 000000000..a9fea6844 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1718710211512527300.sql @@ -0,0 +1,2 @@ +-- Mote of Shadow +UPDATE `creature_loot_template` SET `Chance` = 25 WHERE `Item` = 22577 and `Entry` IN (18869,18870); From b90a6c0ce7c1e311e48b2c461695a6d3cf084575 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 18 Jun 2024 22:43:19 +0000 Subject: [PATCH 68/73] chore(DB): import pending files Referenced commit(s): a644425758414071046d91f7701f5176955316f1 --- .../rev_1718710211512527300.sql => db_world/2024_06_18_04.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1718710211512527300.sql => db_world/2024_06_18_04.sql} (73%) diff --git a/data/sql/updates/pending_db_world/rev_1718710211512527300.sql b/data/sql/updates/db_world/2024_06_18_04.sql similarity index 73% rename from data/sql/updates/pending_db_world/rev_1718710211512527300.sql rename to data/sql/updates/db_world/2024_06_18_04.sql index a9fea6844..88b0bbf6a 100644 --- a/data/sql/updates/pending_db_world/rev_1718710211512527300.sql +++ b/data/sql/updates/db_world/2024_06_18_04.sql @@ -1,2 +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); From e3789db3798c809c0b742ae24dfcc44563404cd7 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Tue, 18 Jun 2024 19:43:30 -0300 Subject: [PATCH 69/73] fix(Scripts/ICC): Fix Valithria reseting (#19087) --- .../Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp | 5 +++++ 1 file changed, 5 insertions(+) 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 From 8ea13ca778931f3d018472e0be47596c17615917 Mon Sep 17 00:00:00 2001 From: Benjamin Jackson <38561765+heyitsbench@users.noreply.github.com> Date: Tue, 18 Jun 2024 18:45:02 -0400 Subject: [PATCH 70/73] fix(Scripts/Spells): Implement damage scaling based off DoT stack count for Seal of Vengeance and Corruption. (#19073) * Init. * Whoops. * Move comment. Someone should fix this darn CI. * Logic adjustment. * Revert logic adjustment. This reverts commit ee09ee55df47c9a66ecf536be58a4a040f384b72. * Requested changes? --- data/sql/updates/pending_db_world/seals.sql | 4 ++ src/server/game/Entities/Unit/Unit.cpp | 12 ++---- src/server/scripts/Spells/spell_paladin.cpp | 47 ++++++++++++++++++++- 3 files changed, 54 insertions(+), 9 deletions(-) create mode 100644 data/sql/updates/pending_db_world/seals.sql diff --git a/data/sql/updates/pending_db_world/seals.sql b/data/sql/updates/pending_db_world/seals.sql new file mode 100644 index 000000000..fa75b7356 --- /dev/null +++ b/data/sql/updates/pending_db_world/seals.sql @@ -0,0 +1,4 @@ +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/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 7e346a5e3..d384219a0 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; 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); } From 4eaac11099af0602c9ded981e0f0626475fa19b3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 18 Jun 2024 22:46:01 +0000 Subject: [PATCH 71/73] chore(DB): import pending files Referenced commit(s): 8ea13ca778931f3d018472e0be47596c17615917 --- .../{pending_db_world/seals.sql => db_world/2024_06_18_05.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/seals.sql => db_world/2024_06_18_05.sql} (86%) diff --git a/data/sql/updates/pending_db_world/seals.sql b/data/sql/updates/db_world/2024_06_18_05.sql similarity index 86% rename from data/sql/updates/pending_db_world/seals.sql rename to data/sql/updates/db_world/2024_06_18_05.sql index fa75b7356..bb41a49b6 100644 --- a/data/sql/updates/pending_db_world/seals.sql +++ b/data/sql/updates/db_world/2024_06_18_05.sql @@ -1,3 +1,4 @@ +-- 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'), From eaa09ed95e20324a3cc9c9e189ad4502412f30dd Mon Sep 17 00:00:00 2001 From: Gultask <100873791+Gultask@users.noreply.github.com> Date: Tue, 18 Jun 2024 19:47:03 -0300 Subject: [PATCH 72/73] fix(DB/Creature): Fix minor issues with Dragonmaw Peons (#19091) Create rev_1718749668931737500.sql --- .../updates/pending_db_world/rev_1718749668931737500.sql | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1718749668931737500.sql diff --git a/data/sql/updates/pending_db_world/rev_1718749668931737500.sql b/data/sql/updates/pending_db_world/rev_1718749668931737500.sql new file mode 100644 index 000000000..547d03717 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1718749668931737500.sql @@ -0,0 +1,9 @@ +-- +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'); From 85965feab65a03b5479606429b6a52286d03d014 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 18 Jun 2024 22:47:57 +0000 Subject: [PATCH 73/73] chore(DB): import pending files Referenced commit(s): eaa09ed95e20324a3cc9c9e189ad4502412f30dd --- .../rev_1718749668931737500.sql => db_world/2024_06_18_06.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1718749668931737500.sql => db_world/2024_06_18_06.sql} (97%) diff --git a/data/sql/updates/pending_db_world/rev_1718749668931737500.sql b/data/sql/updates/db_world/2024_06_18_06.sql similarity index 97% rename from data/sql/updates/pending_db_world/rev_1718749668931737500.sql rename to data/sql/updates/db_world/2024_06_18_06.sql index 547d03717..24c5d67f1 100644 --- a/data/sql/updates/pending_db_world/rev_1718749668931737500.sql +++ b/data/sql/updates/db_world/2024_06_18_06.sql @@ -1,3 +1,4 @@ +-- DB update 2024_06_18_05 -> 2024_06_18_06 -- UPDATE `creature_text` SET `BroadcastTextId` = 21123 WHERE `BroadcastTextId` = 21223 AND `CreatureID` = 23311;