mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-29 08:33:47 +00:00
Merge branch 'master' into Playerbot
This commit is contained in:
2
.github/workflows/build_dbimport.yml
vendored
2
.github/workflows/build_dbimport.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
COMPILER: ${{ matrix.compiler }}
|
||||
if: github.repository == 'azerothcore/azerothcore-wotlk' && !github.event.pull_request.draft
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Cache
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
|
||||
2
.github/workflows/check_pending_sql.yml
vendored
2
.github/workflows/check_pending_sql.yml
vendored
@@ -6,6 +6,6 @@ jobs:
|
||||
check-pending-sql:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Check pending SQL
|
||||
run: source ./apps/ci/ci-pending.sh
|
||||
|
||||
2
.github/workflows/codestyle.yml
vendored
2
.github/workflows/codestyle.yml
vendored
@@ -11,6 +11,6 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: check codestyle
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Check core codestyle
|
||||
run: source ./apps/ci/ci-codestyle.sh
|
||||
|
||||
4
.github/workflows/core_build.yml
vendored
4
.github/workflows/core_build.yml
vendored
@@ -23,9 +23,9 @@ jobs:
|
||||
COMPILER: ${{ matrix.compiler }}
|
||||
if: github.repository == 'azerothcore/azerothcore-wotlk' && !github.event.pull_request.draft
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: var/ccache
|
||||
key: ccache:${{ matrix.os }}:${{ matrix.compiler }}:${{ github.ref }}:${{ github.sha }}
|
||||
|
||||
4
.github/workflows/core_matrix_build.yml
vendored
4
.github/workflows/core_matrix_build.yml
vendored
@@ -40,9 +40,9 @@ jobs:
|
||||
|| github.event.label.name == 'run-build')
|
||||
)
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: var/ccache
|
||||
key: ccache:${{ matrix.os }}:${{ matrix.compiler }}:${{ github.ref }}:${{ github.sha }}
|
||||
|
||||
4
.github/workflows/core_modules_build.yml
vendored
4
.github/workflows/core_modules_build.yml
vendored
@@ -34,12 +34,12 @@ jobs:
|
||||
|| github.event.label.name == 'run-build')
|
||||
)
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Checkout modules
|
||||
run: ./apps/ci/ci-install-modules.sh
|
||||
if: matrix.modules == 'with'
|
||||
- name: Cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: var/ccache
|
||||
key: ccache:${{ matrix.os }}:${{ matrix.compiler }}:${{ matrix.modules }}-modules:${{ github.ref }}:${{ github.sha }}
|
||||
|
||||
2
.github/workflows/cpp-check.yml
vendored
2
.github/workflows/cpp-check.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
name: cpp check
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: cpp check
|
||||
run: |
|
||||
sudo apt update -y
|
||||
|
||||
2
.github/workflows/docker_build.yml
vendored
2
.github/workflows/docker_build.yml
vendored
@@ -124,7 +124,7 @@ jobs:
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: var/docker/ccache
|
||||
key: ccache:${{ matrix.os }}:clang:without-modules:${{ github.ref }}:${{ github.sha }}
|
||||
|
||||
2
.github/workflows/import_pending.yml
vendored
2
.github/workflows/import_pending.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.repository == 'azerothcore/azerothcore-wotlk' && !github.event.pull_request.draft
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Extract branch name
|
||||
|
||||
4
.github/workflows/macos_build.yml
vendored
4
.github/workflows/macos_build.yml
vendored
@@ -25,9 +25,9 @@ jobs:
|
||||
&& !github.event.pull_request.draft
|
||||
&& (github.ref == 'refs/heads/master' || contains(github.event.pull_request.labels.*.name, 'run-build') || github.event.label.name == 'run-build')
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/Library/Caches/ccache
|
||||
key: ccache:${{ matrix.os }}:${{ github.ref }}:${{ github.sha }}
|
||||
|
||||
2
.github/workflows/tools_build.yml
vendored
2
.github/workflows/tools_build.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
COMPILER: ${{ matrix.compiler }}
|
||||
if: github.repository == 'azerothcore/azerothcore-wotlk' && !github.event.pull_request.draft
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Cache
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
|
||||
8
.github/workflows/windows_build.yml
vendored
8
.github/workflows/windows_build.yml
vendored
@@ -25,7 +25,9 @@ jobs:
|
||||
&& !github.event.pull_request.draft
|
||||
&& (github.ref == 'refs/heads/master' || contains(github.event.pull_request.labels.*.name, 'run-build') || github.event.label.name == 'run-build')
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2.9
|
||||
- name: Configure OS
|
||||
shell: bash
|
||||
env:
|
||||
@@ -40,6 +42,10 @@ jobs:
|
||||
run: |
|
||||
export CTOOLS_BUILD=all
|
||||
./acore.sh compiler build
|
||||
- name: Copy dll files
|
||||
shell: bash
|
||||
run: |
|
||||
cp "/c/Program Files/OpenSSL/bin/legacy.dll" "env/dist"
|
||||
- name: Dry run authserver
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
export OPENSSL_ROOT_DIR=$(brew --prefix openssl@1.1)
|
||||
export OPENSSL_ROOT_DIR=$(brew --prefix openssl@3)
|
||||
|
||||
export CCACHE_CPP2=true
|
||||
export CCACHE_MAXSIZE='500M'
|
||||
|
||||
@@ -26,4 +26,4 @@ if ! command -v cmake &>/dev/null ; then
|
||||
fi
|
||||
##########################################
|
||||
|
||||
brew install openssl@1.1 readline boost bash-completion curl unzip mysql ccache
|
||||
brew install openssl@3 readline boost bash-completion curl unzip mysql ccache
|
||||
|
||||
2
data/sql/updates/db_world/2023_07_26_00.sql
Normal file
2
data/sql/updates/db_world/2023_07_26_00.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
-- DB update 2023_07_24_00 -> 2023_07_26_00
|
||||
UPDATE `spell_proc_event` SET `procFlags` = 4 WHERE `entry` = 23689;
|
||||
3
data/sql/updates/db_world/2023_07_26_01.sql
Normal file
3
data/sql/updates/db_world/2023_07_26_01.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
-- DB update 2023_07_26_00 -> 2023_07_26_01
|
||||
--
|
||||
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 17671) AND (`source_type` = 0) AND (`id` IN (4));
|
||||
46
data/sql/updates/db_world/2023_07_26_02.sql
Normal file
46
data/sql/updates/db_world/2023_07_26_02.sql
Normal file
@@ -0,0 +1,46 @@
|
||||
-- DB update 2023_07_26_01 -> 2023_07_26_02
|
||||
--
|
||||
UPDATE `item_template` SET `spellcooldown_1` = -1 WHERE (`entry` = 37111);
|
||||
UPDATE `item_template` SET `spellcooldown_1` = -1, `spellcategorycooldown_1` = 2000 WHERE (`entry` = 47477);
|
||||
UPDATE `item_template` SET `spellcooldown_1` = -1, `spellcategorycooldown_1` = 2000 WHERE (`entry` = 47316);
|
||||
UPDATE `item_template` SET `spellcooldown_1` = -1, `spellcooldown_2` = -1, `spellcooldown_3` = -1 WHERE (`entry` = 45507);
|
||||
UPDATE `item_template` SET `spellcooldown_2` = -1, `spellcooldown_3` = -1 WHERE (`entry` = 45522);
|
||||
UPDATE `item_template` SET `spellcooldown_2` = -1, `spellcooldown_3` = -1 WHERE (`entry` = 45929);
|
||||
UPDATE `item_template` SET `spellcooldown_2` = -1, `spellcooldown_3` = -1 WHERE (`entry` = 45931);
|
||||
UPDATE `item_template` SET `spelltrigger_2` = 0, `spellcooldown_2` = -1, `spellcooldown_3` = -1 WHERE (`entry` = 45866);
|
||||
UPDATE `item_template` SET `spellcooldown_1` = -1, `spellcategorycooldown_1` = 45000 WHERE (`entry` = 40255);
|
||||
UPDATE `item_template` SET `spellcooldown_1` = -1 WHERE (`entry` = 40373);
|
||||
UPDATE `item_template` SET `spellcooldown_1` = 0, `spellcategorycooldown_1` = -1 WHERE (`entry` = 37835);
|
||||
UPDATE `item_template` SET `spellcooldown_1` = 0, `spellcategorycooldown_1` = -1 WHERE (`entry` = 39229);
|
||||
UPDATE `item_template` SET `spellcooldown_1` = 0 WHERE (`entry` = 37390);
|
||||
UPDATE `item_template` SET `spellcooldown_1` = 0 WHERE (`entry` = 37657);
|
||||
UPDATE `item_template` SET `spellcooldown_1` = 0 WHERE (`entry` = 37660);
|
||||
|
||||
UPDATE `item_template` SET `spellppmRate_1` = 0 WHERE (`entry` = 50348);
|
||||
UPDATE `item_template` SET `spellppmRate_1` = 0 WHERE (`entry` = 50353);
|
||||
UPDATE `item_template` SET `spellppmRate_1` = 0 WHERE (`entry` = 54588);
|
||||
|
||||
UPDATE `spell_proc_event` SET `CustomChance` = 45 WHERE `entry` = 71545;
|
||||
UPDATE `spell_proc_event` SET `CustomChance` = 35 WHERE `entry` = 71562;
|
||||
|
||||
UPDATE `spell_proc_event` SET `Cooldown` = 50000 WHERE `entry` = 71585;
|
||||
UPDATE `spell_proc_event` SET `Cooldown` = 50000 WHERE `entry` = 64738;
|
||||
UPDATE `spell_proc_event` SET `Cooldown` = 50000 WHERE `entry` = 64792;
|
||||
UPDATE `spell_proc_event` SET `Cooldown` = 50000 WHERE `entry` = 62114;
|
||||
UPDATE `spell_proc_event` SET `Cooldown` = 45000 WHERE `entry` = 58901;
|
||||
UPDATE `spell_proc_event` SET `Cooldown` = 50000 WHERE `entry` = 33648;
|
||||
UPDATE `spell_proc_event` SET `Cooldown` = 50000 WHERE `entry` = 49622;
|
||||
UPDATE `spell_proc_event` SET `Cooldown` = 50000 WHERE `entry` = 65013;
|
||||
UPDATE `spell_proc_event` SET `Cooldown` = 50000 WHERE `entry` = 65002;
|
||||
UPDATE `spell_proc_event` SET `Cooldown` = 50000 WHERE `entry` = 62115;
|
||||
UPDATE `spell_proc_event` SET `Cooldown` = 50000 WHERE `entry` = 67672;
|
||||
UPDATE `spell_proc_event` SET `Cooldown` = 50000 WHERE `entry` = 33648;
|
||||
UPDATE `spell_proc_event` SET `Cooldown` = 50000 WHERE `entry` = 60221;
|
||||
UPDATE `spell_proc_event` SET `Cooldown` = 50000 WHERE `entry` = 60519;
|
||||
UPDATE `spell_proc_event` SET `Cooldown` = 50000 WHERE `entry` = 63251;
|
||||
|
||||
DELETE FROM `spell_proc_event` WHERE `entry` IN (75474, 71602, 64764);
|
||||
INSERT INTO `spell_proc_event` (`entry`, `SchoolMask`, `SpellFamilyName`, `SpellFamilyMask0`, `SpellFamilyMask1`, `SpellFamilyMask2`, `procFlags`, `procEx`, `procPhase`, `ppmRate`, `CustomChance`, `Cooldown`) VALUES
|
||||
(75474,0,0,0,0,0,0,0,0,0,0,50000),
|
||||
(64764,0,0,0,0,0,0,0,0,0,0,50000),
|
||||
(71602,0,0,0,0,0,0,0,0,0,0,45000);
|
||||
4
data/sql/updates/db_world/2023_07_26_03.sql
Normal file
4
data/sql/updates/db_world/2023_07_26_03.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
-- DB update 2023_07_26_02 -> 2023_07_26_03
|
||||
--
|
||||
DELETE FROM `areatrigger_teleport` WHERE `ID` = 2068;
|
||||
INSERT INTO `areatrigger_teleport` (`ID`, `Name`, `target_map`, `target_position_x`, `target_position_y`, `target_position_z`, `target_orientation`) VALUES (2068, 'Blackrock Spire - Jump Exit', 0, -7558.39, -1309.43, 248.454, 1.5708);
|
||||
5
data/sql/updates/db_world/2023_07_26_04.sql
Normal file
5
data/sql/updates/db_world/2023_07_26_04.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
-- DB update 2023_07_26_03 -> 2023_07_26_04
|
||||
--
|
||||
UPDATE `creature_template` SET `AIName` = '' WHERE `entry` = 12298;
|
||||
|
||||
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 12298) AND (`source_type` = 0);
|
||||
29
data/sql/updates/db_world/2023_07_27_00.sql
Normal file
29
data/sql/updates/db_world/2023_07_27_00.sql
Normal file
@@ -0,0 +1,29 @@
|
||||
-- DB update 2023_07_26_04 -> 2023_07_27_00
|
||||
-- path of Garn Mathers
|
||||
SET @NPC := 30758 * 10; -- Garn mathers GUID * 10
|
||||
DELETE FROM `waypoint_data` WHERE `id` = @NPC;
|
||||
INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`) VALUES
|
||||
(@NPC, 1, -3050.0679, -4329.487, 8.319094, 0),
|
||||
(@NPC, 2, -3044.8179, -4326.487, 7.819094, 0),
|
||||
(@NPC, 3, -3036.245, -4321.0723, 7.388595, 0),
|
||||
(@NPC, 4, -3023.495, -4328.3223, 7.888595, 0),
|
||||
(@NPC, 5, -3007.757, -4334.8223, 6.9061613, 0),
|
||||
(@NPC, 6, -2997.757, -4344.0723, 6.6561613, 0),
|
||||
(@NPC, 7, -2981.6763, -4353.217, 8.946001, 0),
|
||||
(@NPC, 8, -2970.2686, -4358.55, 10.112873, 0),
|
||||
(@NPC, 9, -2972.253, -4368.476, 9.980476, 0),
|
||||
(@NPC, 10, -2983.7305, -4381.0786, 10.497398, 0),
|
||||
(@NPC, 11, -3000.9695, -4383.346, 10.6955185, 0),
|
||||
(@NPC, 12, -3011.9897, -4373.612, 9.795075, 0),
|
||||
(@NPC, 13, -3023.2007, -4366.656, 10.3360815, 0),
|
||||
(@NPC, 14, -3026.9507, -4364.906, 10.0860815, 0),
|
||||
(@NPC, 15, -3040.5425, -4358.04, 8.381775, 0),
|
||||
(@NPC, 16, -3048.0571, -4343.4937, 8.053871, 0);
|
||||
|
||||
DELETE FROM `creature` WHERE `id1` = 23679 AND `guid` = 30758;
|
||||
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
|
||||
(30758, 23679, 0, 0, 1, 0, 0, 1, 1, 1, -3050.214, -4329.639, 8.156482, 1.730132341384887695, 180, 0, 0, 1536, 0, 2, 0, 0, 0, '', 50375);
|
||||
|
||||
DELETE FROM `creature_addon` WHERE `guid` = 30758;
|
||||
INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) VALUES
|
||||
(30758, @NPC, 0, 0, 1, 0, 0, '');
|
||||
3
data/sql/updates/db_world/2023_07_27_01.sql
Normal file
3
data/sql/updates/db_world/2023_07_27_01.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
-- DB update 2023_07_27_00 -> 2023_07_27_01
|
||||
--
|
||||
UPDATE `creature_template` SET `ScriptName`='npc_crashin_thrashin_robot' WHERE `entry`=17299;
|
||||
5
data/sql/updates/db_world/2023_07_27_02.sql
Normal file
5
data/sql/updates/db_world/2023_07_27_02.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
-- DB update 2023_07_27_01 -> 2023_07_27_02
|
||||
--
|
||||
DELETE FROM `spell_linked_spell` WHERE `spell_trigger` = 29683 AND `spell_effect` = 32214;
|
||||
INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES
|
||||
(29683, 32214, 0, "Spotlight 20% player buff");
|
||||
4
data/sql/updates/db_world/2023_07_27_03.sql
Normal file
4
data/sql/updates/db_world/2023_07_27_03.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
-- DB update 2023_07_27_02 -> 2023_07_27_03
|
||||
--
|
||||
UPDATE `creature` SET `wander_distance` = 0, `MovementType` = 0 WHERE `guid` = 15542;
|
||||
|
||||
6
data/sql/updates/db_world/2023_07_27_04.sql
Normal file
6
data/sql/updates/db_world/2023_07_27_04.sql
Normal file
@@ -0,0 +1,6 @@
|
||||
-- DB update 2023_07_27_03 -> 2023_07_27_04
|
||||
--
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid` = 17157 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`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
|
||||
(17157, 0, 0, 0, 0, 0, 100, 0, 9600, 12900, 30600, 43600, 0, 11, 33840, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Rumbler - In Combat - Cast \'Earth Rumble\' '),
|
||||
(17157, 0, 1, 0, 8, 0, 100, 513, 32001, 0, 0, 0, 0, 80, 1715700, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Rumbler - On Spellhit \'Throw Gordawg\'s Boulder\' - Run Script (No Repeat)');
|
||||
4
data/sql/updates/db_world/2023_07_27_05.sql
Normal file
4
data/sql/updates/db_world/2023_07_27_05.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
-- DB update 2023_07_27_04 -> 2023_07_27_05
|
||||
--
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid` = 94 AND `source_type` = 0;
|
||||
UPDATE `creature_template` SET `AIName` = '' WHERE `entry` = 94;
|
||||
3
data/sql/updates/db_world/2023_07_28_00.sql
Normal file
3
data/sql/updates/db_world/2023_07_28_00.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
-- DB update 2023_07_27_05 -> 2023_07_28_00
|
||||
--
|
||||
UPDATE `creature` SET `position_x`=-33.3555, `position_y`=-927.892, `position_z`=54.5261, `orientation`=1.54421, `spawntimesecs`=600, `wander_distance`=1, `MovementType`=1, `VerifiedBuild`=50375 WHERE `guid`=15542;
|
||||
4
data/sql/updates/db_world/2023_07_29_00.sql
Normal file
4
data/sql/updates/db_world/2023_07_29_00.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
-- DB update 2023_07_28_00 -> 2023_07_29_00
|
||||
--
|
||||
DELETE FROM `spell_script_names` WHERE `spell_id` = 38048;
|
||||
INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES (38048, 'spell_gen_curse_of_pain');
|
||||
3
data/sql/updates/db_world/2023_07_29_01.sql
Normal file
3
data/sql/updates/db_world/2023_07_29_01.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
-- DB update 2023_07_29_00 -> 2023_07_29_01
|
||||
--
|
||||
UPDATE `creature_model_info` SET `BoundingRadius`=9, `CombatReach`=15.75 WHERE `DisplayID`=17887;
|
||||
@@ -1563,6 +1563,14 @@ AllowTwoSide.Interaction.Group = 0
|
||||
|
||||
AllowTwoSide.Interaction.Guild = 0
|
||||
|
||||
#
|
||||
# AllowTwoSide.Interaction.Arena
|
||||
# Description: Allow joining arena teams between factions.
|
||||
# Default: 0 - (Disabled)
|
||||
# 1 - (Enabled)
|
||||
|
||||
AllowTwoSide.Interaction.Arena = 0
|
||||
|
||||
#
|
||||
# AllowTwoSide.Interaction.Auction
|
||||
# Description: Allow auctions between factions.
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "Arena.h"
|
||||
#include "ArenaTeamMgr.h"
|
||||
#include "GroupMgr.h"
|
||||
#include "Log.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "Player.h"
|
||||
@@ -93,6 +94,47 @@ void Arena::AddPlayer(Player* player)
|
||||
}
|
||||
|
||||
UpdateArenaWorldState();
|
||||
|
||||
Group* group = player->GetGroup();
|
||||
if (group)
|
||||
{
|
||||
// Hackfix for crossfaction arenas, recreate group when joining
|
||||
// Without this, players in a crossfaction arena group would not be able to cast beneficial spells on their teammates
|
||||
|
||||
std::vector<Player*> members;
|
||||
bool isCrossfaction = false;
|
||||
for (Group::member_citerator mitr = group->GetMemberSlots().begin(); mitr != group->GetMemberSlots().end(); ++mitr)
|
||||
{
|
||||
Player* member = ObjectAccessor::FindPlayer(mitr->guid);
|
||||
if (!member || member->GetGUID() == player->GetGUID())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
members.push_back(member);
|
||||
if (member->GetTeamId(true) != player->GetTeamId(true))
|
||||
{
|
||||
isCrossfaction = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isCrossfaction)
|
||||
{
|
||||
for (Player* member : members)
|
||||
{
|
||||
member->RemoveFromGroup();
|
||||
}
|
||||
group->Disband();
|
||||
|
||||
group = new Group();
|
||||
SetBgRaid(player->GetBgTeamId(), group);
|
||||
group->Create(player);
|
||||
sGroupMgr->AddGroup(group);
|
||||
for (Player* member : members)
|
||||
{
|
||||
group->AddMember(member);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arena::RemovePlayer(Player* /*player*/)
|
||||
|
||||
@@ -133,7 +133,7 @@ void WorldSession::HandleArenaTeamInviteOpcode(WorldPacket& recvData)
|
||||
if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUID()))
|
||||
return;
|
||||
|
||||
if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && player->GetTeamId() != GetPlayer()->GetTeamId())
|
||||
if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_ARENA) && player->GetTeamId() != GetPlayer()->GetTeamId())
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
|
||||
return;
|
||||
@@ -185,7 +185,7 @@ void WorldSession::HandleArenaTeamAcceptOpcode(WorldPacket& /*recvData*/)
|
||||
}
|
||||
|
||||
// Only allow members of the other faction to join the team if cross faction interaction is enabled
|
||||
if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && _player->GetTeamId() != sCharacterCache->GetCharacterTeamByGuid(arenaTeam->GetCaptain()))
|
||||
if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_ARENA) && _player->GetTeamId() != sCharacterCache->GetCharacterTeamByGuid(arenaTeam->GetCaptain()))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
|
||||
return;
|
||||
|
||||
@@ -414,18 +414,14 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket& recvData)
|
||||
if (!signatures)
|
||||
return;
|
||||
|
||||
// not let enemies sign guild charter
|
||||
if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeamId() != sCharacterCache->GetCharacterTeamByGuid(petition->ownerGuid))
|
||||
{
|
||||
if (type != GUILD_CHARTER_TYPE)
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
|
||||
else
|
||||
Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NOT_ALLIED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type != GUILD_CHARTER_TYPE)
|
||||
{
|
||||
if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_ARENA) && GetPlayer()->GetTeamId() != sCharacterCache->GetCharacterTeamByGuid(petition->ownerGuid))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_player->GetLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", _player->GetName().c_str(), ERR_ARENA_TEAM_TARGET_TOO_LOW_S);
|
||||
@@ -450,6 +446,12 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket& recvData)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeamId() != sCharacterCache->GetCharacterTeamByGuid(petition->ownerGuid))
|
||||
{
|
||||
Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NOT_ALLIED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_player->GetGuildId())
|
||||
{
|
||||
Guild::SendCommandResult(this, GUILD_COMMAND_INVITE, ERR_ALREADY_IN_GUILD_S, _player->GetName());
|
||||
@@ -567,17 +569,14 @@ void WorldSession::HandleOfferPetitionOpcode(WorldPacket& recvData)
|
||||
if (!petition)
|
||||
return;
|
||||
|
||||
if (GetPlayer()->GetTeamId() != player->GetTeamId())
|
||||
{
|
||||
if (petition->petitionType != GUILD_CHARTER_TYPE)
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
|
||||
else
|
||||
Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NOT_ALLIED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (petition->petitionType != GUILD_CHARTER_TYPE)
|
||||
{
|
||||
if (GetPlayer()->GetTeamId() != player->GetTeamId() && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_ARENA))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (player->GetLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
|
||||
{
|
||||
// player is too low level to join an arena team
|
||||
@@ -604,6 +603,12 @@ void WorldSession::HandleOfferPetitionOpcode(WorldPacket& recvData)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetPlayer()->GetTeamId() != player->GetTeamId() && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD))
|
||||
{
|
||||
Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NOT_ALLIED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (player->GetGuildId())
|
||||
{
|
||||
Guild::SendCommandResult(this, GUILD_COMMAND_INVITE, ERR_ALREADY_IN_GUILD_S, _player->GetName());
|
||||
|
||||
@@ -79,6 +79,7 @@ enum WorldBoolConfigs
|
||||
CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL,
|
||||
CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP,
|
||||
CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD,
|
||||
CONFIG_ALLOW_TWO_SIDE_INTERACTION_ARENA,
|
||||
CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION,
|
||||
CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL,
|
||||
CONFIG_ALLOW_TWO_SIDE_WHO_LIST,
|
||||
|
||||
@@ -731,6 +731,7 @@ void World::LoadConfigSettings(bool reload)
|
||||
_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL] = sConfigMgr->GetOption<bool>("AllowTwoSide.Interaction.Channel", false);
|
||||
_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP] = sConfigMgr->GetOption<bool>("AllowTwoSide.Interaction.Group", false);
|
||||
_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD] = sConfigMgr->GetOption<bool>("AllowTwoSide.Interaction.Guild", false);
|
||||
_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_ARENA] = sConfigMgr->GetOption<bool>("AllowTwoSide.Interaction.Arena", false);
|
||||
_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION] = sConfigMgr->GetOption<bool>("AllowTwoSide.Interaction.Auction", false);
|
||||
_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL] = sConfigMgr->GetOption<bool>("AllowTwoSide.Interaction.Mail", false);
|
||||
_bool_configs[CONFIG_ALLOW_TWO_SIDE_WHO_LIST] = sConfigMgr->GetOption<bool>("AllowTwoSide.WhoList", false);
|
||||
|
||||
@@ -121,8 +121,6 @@ struct boss_moroes : public BossAI
|
||||
context.Repeat(5s);
|
||||
}).Schedule(1min, 2min, GROUP_PRECOMBAT_TALK, [this](TaskContext context)
|
||||
{
|
||||
//this was not scheduled in the previous commit
|
||||
//does this have to be removed?
|
||||
Talk(SAY_OUT_OF_COMBAT);
|
||||
context.Repeat(1min, 2min);
|
||||
});
|
||||
|
||||
@@ -15,13 +15,6 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Boss_Netherspite
|
||||
SD%Complete: 90
|
||||
SDComment: Not sure about timing and portals placing
|
||||
SDCategory: Karazhan
|
||||
EndScriptData */
|
||||
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
@@ -29,19 +22,35 @@ EndScriptData */
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellScript.h"
|
||||
|
||||
enum Netherspite
|
||||
enum Emotes
|
||||
{
|
||||
EMOTE_PHASE_PORTAL = 0,
|
||||
EMOTE_PHASE_BANISH = 1,
|
||||
EMOTE_PHASE_PORTAL = 0,
|
||||
EMOTE_PHASE_BANISH = 1
|
||||
};
|
||||
|
||||
SPELL_NETHERBURN_AURA = 30522,
|
||||
SPELL_VOIDZONE = 37063,
|
||||
SPELL_NETHER_INFUSION = 38688,
|
||||
SPELL_NETHERBREATH = 38523,
|
||||
SPELL_BANISH_VISUAL = 39833,
|
||||
SPELL_BANISH_ROOT = 42716,
|
||||
SPELL_EMPOWERMENT = 38549,
|
||||
SPELL_NETHERSPITE_ROAR = 38684,
|
||||
enum Spells
|
||||
{
|
||||
SPELL_NETHERBURN_AURA = 30522,
|
||||
SPELL_VOIDZONE = 37063,
|
||||
SPELL_NETHER_INFUSION = 38688,
|
||||
SPELL_NETHERBREATH = 38523,
|
||||
SPELL_BANISH_VISUAL = 39833,
|
||||
SPELL_BANISH_ROOT = 42716,
|
||||
SPELL_EMPOWERMENT = 38549,
|
||||
SPELL_NETHERSPITE_ROAR = 38684
|
||||
};
|
||||
|
||||
enum Portals
|
||||
{
|
||||
RED_PORTAL = 0, // Perseverence
|
||||
GREEN_PORTAL = 1, // Serenity
|
||||
BLUE_PORTAL = 2 // Dominance
|
||||
};
|
||||
|
||||
enum Groups
|
||||
{
|
||||
PORTAL_PHASE = 0,
|
||||
VANISH_PHASE = 1
|
||||
};
|
||||
|
||||
const float PortalCoord[3][3] =
|
||||
@@ -51,302 +60,255 @@ const float PortalCoord[3][3] =
|
||||
{-11094.493164f, -1591.969238f, 279.949188f} // Back side
|
||||
};
|
||||
|
||||
enum Netherspite_Portal
|
||||
{
|
||||
RED_PORTAL = 0, // Perseverence
|
||||
GREEN_PORTAL = 1, // Serenity
|
||||
BLUE_PORTAL = 2 // Dominance
|
||||
};
|
||||
|
||||
const uint32 PortalID[3] = {17369, 17367, 17368};
|
||||
const uint32 PortalID[3] = {17369, 17367, 17368};
|
||||
const uint32 PortalVisual[3] = {30487, 30490, 30491};
|
||||
const uint32 PortalBeam[3] = {30465, 30464, 30463};
|
||||
const uint32 PlayerBuff[3] = {30421, 30422, 30423};
|
||||
const uint32 NetherBuff[3] = {30466, 30467, 30468};
|
||||
const uint32 PortalBeam[3] = {30465, 30464, 30463};
|
||||
const uint32 PlayerBuff[3] = {30421, 30422, 30423};
|
||||
const uint32 NetherBuff[3] = {30466, 30467, 30468};
|
||||
const uint32 PlayerDebuff[3] = {38637, 38638, 38639};
|
||||
|
||||
class boss_netherspite : public CreatureScript
|
||||
struct boss_netherspite : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_netherspite() : CreatureScript("boss_netherspite") { }
|
||||
boss_netherspite(Creature* creature) : BossAI(creature, DATA_NETHERSPITE) {}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
bool IsBetween(WorldObject* u1, WorldObject* target, WorldObject* u2) // the in-line checker
|
||||
{
|
||||
return GetKarazhanAI<boss_netherspiteAI>(creature);
|
||||
if (!u1 || !u2 || !target)
|
||||
return false;
|
||||
|
||||
float xn, yn, xp, yp, xh, yh;
|
||||
xn = u1->GetPositionX();
|
||||
yn = u1->GetPositionY();
|
||||
xp = u2->GetPositionX();
|
||||
yp = u2->GetPositionY();
|
||||
xh = target->GetPositionX();
|
||||
yh = target->GetPositionY();
|
||||
|
||||
// check if target is between (not checking distance from the beam yet)
|
||||
if (dist(xn, yn, xh, yh) >= dist(xn, yn, xp, yp) || dist(xp, yp, xh, yh) >= dist(xn, yn, xp, yp))
|
||||
return false;
|
||||
// check distance from the beam
|
||||
return (std::abs((xn - xp) * yh + (yp - yn) * xh - xn * yp + xp * yn) / dist(xn, yn, xp, yp) < 1.5f);
|
||||
}
|
||||
|
||||
struct boss_netherspiteAI : public ScriptedAI
|
||||
float dist(float xa, float ya, float xb, float yb) // auxiliary method for distance
|
||||
{
|
||||
boss_netherspiteAI(Creature* creature) : ScriptedAI(creature)
|
||||
return std::sqrt((xa - xb) * (xa - xb) + (ya - yb) * (ya - yb));
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
berserk = false;
|
||||
HandleDoors(true);
|
||||
DestroyPortals();
|
||||
}
|
||||
|
||||
void SummonPortals()
|
||||
{
|
||||
uint8 r = rand() % 4;
|
||||
uint8 pos[3];
|
||||
pos[RED_PORTAL] = ((r % 2) ? (r > 1 ? 2 : 1) : 0);
|
||||
pos[GREEN_PORTAL] = ((r % 2) ? 0 : (r > 1 ? 2 : 1));
|
||||
pos[BLUE_PORTAL] = (r > 1 ? 1 : 2); // Blue Portal not on the left side (0)
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
bool PortalPhase;
|
||||
bool Berserk;
|
||||
uint32 PhaseTimer; // timer for phase switching
|
||||
uint32 VoidZoneTimer;
|
||||
uint32 NetherInfusionTimer; // berserking timer
|
||||
uint32 NetherbreathTimer;
|
||||
uint32 EmpowermentTimer;
|
||||
uint32 PortalTimer; // timer for beam checking
|
||||
ObjectGuid PortalGUID[3]; // guid's of portals
|
||||
ObjectGuid BeamerGUID[3]; // guid's of auxiliary beaming portals
|
||||
ObjectGuid BeamTarget[3]; // guid's of portals' current targets
|
||||
|
||||
bool IsBetween(WorldObject* u1, WorldObject* target, WorldObject* u2) // the in-line checker
|
||||
{
|
||||
if (!u1 || !u2 || !target)
|
||||
return false;
|
||||
|
||||
float xn, yn, xp, yp, xh, yh;
|
||||
xn = u1->GetPositionX();
|
||||
yn = u1->GetPositionY();
|
||||
xp = u2->GetPositionX();
|
||||
yp = u2->GetPositionY();
|
||||
xh = target->GetPositionX();
|
||||
yh = target->GetPositionY();
|
||||
|
||||
// check if target is between (not checking distance from the beam yet)
|
||||
if (dist(xn, yn, xh, yh) >= dist(xn, yn, xp, yp) || dist(xp, yp, xh, yh) >= dist(xn, yn, xp, yp))
|
||||
return false;
|
||||
// check distance from the beam
|
||||
return (std::abs((xn - xp) * yh + (yp - yn) * xh - xn * yp + xp * yn) / dist(xn, yn, xp, yp) < 1.5f);
|
||||
}
|
||||
|
||||
float dist(float xa, float ya, float xb, float yb) // auxiliary method for distance
|
||||
{
|
||||
return std::sqrt((xa - xb) * (xa - xb) + (ya - yb) * (ya - yb));
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Berserk = false;
|
||||
NetherInfusionTimer = 540000;
|
||||
VoidZoneTimer = 15000;
|
||||
NetherbreathTimer = 3000;
|
||||
|
||||
HandleDoors(true);
|
||||
DestroyPortals();
|
||||
}
|
||||
|
||||
void SummonPortals()
|
||||
{
|
||||
uint8 r = rand() % 4;
|
||||
uint8 pos[3];
|
||||
pos[RED_PORTAL] = ((r % 2) ? (r > 1 ? 2 : 1) : 0);
|
||||
pos[GREEN_PORTAL] = ((r % 2) ? 0 : (r > 1 ? 2 : 1));
|
||||
pos[BLUE_PORTAL] = (r > 1 ? 1 : 2); // Blue Portal not on the left side (0)
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
if (Creature* portal = me->SummonCreature(PortalID[i], PortalCoord[pos[i]][0], PortalCoord[pos[i]][1], PortalCoord[pos[i]][2], 0, TEMPSUMMON_TIMED_DESPAWN, 60000))
|
||||
{
|
||||
PortalGUID[i] = portal->GetGUID();
|
||||
portal->AddAura(PortalVisual[i], portal);
|
||||
}
|
||||
}
|
||||
|
||||
void DestroyPortals()
|
||||
{
|
||||
for (int i = 0; i < 3; ++i)
|
||||
if (Creature* portal = me->SummonCreature(PortalID[i], PortalCoord[pos[i]][0], PortalCoord[pos[i]][1], PortalCoord[pos[i]][2], 0, TEMPSUMMON_TIMED_DESPAWN, 60000))
|
||||
{
|
||||
if (Creature* portal = ObjectAccessor::GetCreature(*me, PortalGUID[i]))
|
||||
portal->DisappearAndDie();
|
||||
if (Creature* portal = ObjectAccessor::GetCreature(*me, BeamerGUID[i]))
|
||||
portal->DisappearAndDie();
|
||||
PortalGUID[i].Clear();
|
||||
BeamTarget[i].Clear();
|
||||
PortalGUID[i] = portal->GetGUID();
|
||||
portal->AddAura(PortalVisual[i], portal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdatePortals() // Here we handle the beams' behavior
|
||||
void DestroyPortals()
|
||||
{
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
for (int j = 0; j < 3; ++j) // j = color
|
||||
if (Creature* portal = ObjectAccessor::GetCreature(*me, PortalGUID[j]))
|
||||
if (Creature* portal = ObjectAccessor::GetCreature(*me, PortalGUID[i]))
|
||||
{
|
||||
portal->DisappearAndDie();
|
||||
}
|
||||
if (Creature* portal = ObjectAccessor::GetCreature(*me, BeamerGUID[i]))
|
||||
{
|
||||
portal->DisappearAndDie();
|
||||
}
|
||||
PortalGUID[i].Clear();
|
||||
BeamTarget[i].Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdatePortals() // Here we handle the beams' behavior
|
||||
{
|
||||
for (int j = 0; j < 3; ++j) // j = color
|
||||
{
|
||||
if (Creature* portal = ObjectAccessor::GetCreature(*me, PortalGUID[j]))
|
||||
{
|
||||
// the one who's been cast upon before
|
||||
Unit* current = ObjectAccessor::GetUnit(*portal, BeamTarget[j]);
|
||||
// temporary store for the best suitable beam reciever
|
||||
Unit* target = me;
|
||||
|
||||
if (Map* map = me->GetMap())
|
||||
{
|
||||
// the one who's been cast upon before
|
||||
Unit* current = ObjectAccessor::GetUnit(*portal, BeamTarget[j]);
|
||||
// temporary store for the best suitable beam reciever
|
||||
Unit* target = me;
|
||||
Map::PlayerList const& players = map->GetPlayers();
|
||||
|
||||
if (Map* map = me->GetMap())
|
||||
// get the best suitable target
|
||||
for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i)
|
||||
{
|
||||
Map::PlayerList const& players = map->GetPlayers();
|
||||
|
||||
// get the best suitable target
|
||||
for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i)
|
||||
{
|
||||
Player* p = i->GetSource();
|
||||
if (p && p->IsAlive() // alive
|
||||
&& (!target || target->GetDistance2d(portal) > p->GetDistance2d(portal)) // closer than current best
|
||||
&& !p->HasAura(PlayerDebuff[j]) // not exhausted
|
||||
&& !p->HasAura(PlayerBuff[(j + 1) % 3]) // not on another beam
|
||||
&& !p->HasAura(PlayerBuff[(j + 2) % 3])
|
||||
&& IsBetween(me, p, portal)) // on the beam
|
||||
target = p;
|
||||
}
|
||||
Player* p = i->GetSource();
|
||||
if (p && p->IsAlive() // alive
|
||||
&& (!target || target->GetDistance2d(portal) > p->GetDistance2d(portal)) // closer than current best
|
||||
&& !p->HasAura(PlayerDebuff[j]) // not exhausted
|
||||
&& !p->HasAura(PlayerBuff[(j + 1) % 3]) // not on another beam
|
||||
&& !p->HasAura(PlayerBuff[(j + 2) % 3])
|
||||
&& IsBetween(me, p, portal)) // on the beam
|
||||
target = p;
|
||||
}
|
||||
// buff the target
|
||||
if (target->GetTypeId() == TYPEID_PLAYER)
|
||||
target->AddAura(PlayerBuff[j], target);
|
||||
else
|
||||
target->AddAura(NetherBuff[j], target);
|
||||
// cast visual beam on the chosen target if switched
|
||||
// simple target switching isn't working -> using BeamerGUID to cast (workaround)
|
||||
if (!current || target != current)
|
||||
{
|
||||
BeamTarget[j] = target->GetGUID();
|
||||
// remove currently beaming portal
|
||||
if (Creature* beamer = ObjectAccessor::GetCreature(*portal, BeamerGUID[j]))
|
||||
{
|
||||
beamer->CastSpell(target, PortalBeam[j], false);
|
||||
beamer->DisappearAndDie();
|
||||
BeamerGUID[j].Clear();
|
||||
}
|
||||
// create new one and start beaming on the target
|
||||
if (Creature* beamer = portal->SummonCreature(PortalID[j], portal->GetPositionX(), portal->GetPositionY(), portal->GetPositionZ(), portal->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, 60000))
|
||||
{
|
||||
beamer->CastSpell(target, PortalBeam[j], false);
|
||||
BeamerGUID[j] = beamer->GetGUID();
|
||||
}
|
||||
}
|
||||
// aggro target if Red Beam
|
||||
if (j == RED_PORTAL && me->GetVictim() != target && target->GetTypeId() == TYPEID_PLAYER)
|
||||
me->GetThreatMgr().AddThreat(target, 100000.0f + DoGetThreat(me->GetVictim()));
|
||||
}
|
||||
// buff the target
|
||||
if (target->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
target->AddAura(PlayerBuff[j], target);
|
||||
}
|
||||
else
|
||||
{
|
||||
target->AddAura(NetherBuff[j], target);
|
||||
}
|
||||
// cast visual beam on the chosen target if switched
|
||||
// simple target switching isn't working -> using BeamerGUID to cast (workaround)
|
||||
if (!current || target != current)
|
||||
{
|
||||
BeamTarget[j] = target->GetGUID();
|
||||
// remove currently beaming portal
|
||||
if (Creature* beamer = ObjectAccessor::GetCreature(*portal, BeamerGUID[j]))
|
||||
{
|
||||
beamer->CastSpell(target, PortalBeam[j], false);
|
||||
beamer->DisappearAndDie();
|
||||
BeamerGUID[j].Clear();
|
||||
}
|
||||
// create new one and start beaming on the target
|
||||
if (Creature* beamer = portal->SummonCreature(PortalID[j], portal->GetPositionX(), portal->GetPositionY(), portal->GetPositionZ(), portal->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, 60000))
|
||||
{
|
||||
beamer->CastSpell(target, PortalBeam[j], false);
|
||||
BeamerGUID[j] = beamer->GetGUID();
|
||||
}
|
||||
}
|
||||
// aggro target if Red Beam
|
||||
if (j == RED_PORTAL && me->GetVictim() != target && target->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
me->GetThreatMgr().AddThreat(target, 100000.0f + DoGetThreat(me->GetVictim()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SwitchToPortalPhase()
|
||||
void SwitchToPortalPhase()
|
||||
{
|
||||
scheduler.CancelGroup(VANISH_PHASE);
|
||||
me->RemoveAurasDueToSpell(SPELL_BANISH_ROOT);
|
||||
me->RemoveAurasDueToSpell(SPELL_BANISH_VISUAL);
|
||||
SummonPortals();
|
||||
scheduler.Schedule(60s, [this](TaskContext /*context*/)
|
||||
{
|
||||
me->RemoveAurasDueToSpell(SPELL_BANISH_ROOT);
|
||||
me->RemoveAurasDueToSpell(SPELL_BANISH_VISUAL);
|
||||
SummonPortals();
|
||||
PhaseTimer = 60000;
|
||||
PortalPhase = true;
|
||||
PortalTimer = 10000;
|
||||
EmpowermentTimer = 10000;
|
||||
Talk(EMOTE_PHASE_PORTAL);
|
||||
}
|
||||
|
||||
void SwitchToBanishPhase()
|
||||
{
|
||||
me->RemoveAurasDueToSpell(SPELL_EMPOWERMENT);
|
||||
me->RemoveAurasDueToSpell(SPELL_NETHERBURN_AURA);
|
||||
DoCast(me, SPELL_BANISH_VISUAL, true);
|
||||
DoCast(me, SPELL_BANISH_ROOT, true);
|
||||
DestroyPortals();
|
||||
PhaseTimer = 30000;
|
||||
PortalPhase = false;
|
||||
Talk(EMOTE_PHASE_BANISH);
|
||||
|
||||
for (uint8 i = 0; i < 3; ++i)
|
||||
me->RemoveAurasDueToSpell(NetherBuff[i]);
|
||||
}
|
||||
|
||||
void HandleDoors(bool open) // Massive Door switcher
|
||||
{
|
||||
if (GameObject* Door = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_GO_MASSIVE_DOOR) ))
|
||||
Door->SetGoState(open ? GO_STATE_ACTIVE : GO_STATE_READY);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
HandleDoors(false);
|
||||
SwitchToPortalPhase();
|
||||
DoZoneInCombat();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
HandleDoors(true);
|
||||
DestroyPortals();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
if (!me->IsNonMeleeSpellCast(false))
|
||||
{
|
||||
SwitchToBanishPhase();
|
||||
return;
|
||||
|
||||
// Void Zone
|
||||
if (VoidZoneTimer <= diff)
|
||||
{
|
||||
DoCast(SelectTarget(SelectTargetMethod::Random, 1, 45, true), SPELL_VOIDZONE, true);
|
||||
VoidZoneTimer = 15000;
|
||||
}
|
||||
else
|
||||
VoidZoneTimer -= diff;
|
||||
}).Schedule(10s, PORTAL_PHASE, [this](TaskContext context)
|
||||
{
|
||||
UpdatePortals();
|
||||
context.Repeat(1s);
|
||||
}).Schedule(10s, PORTAL_PHASE, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_EMPOWERMENT);
|
||||
me->AddAura(SPELL_NETHERBURN_AURA, me);
|
||||
context.Repeat(90s);
|
||||
});
|
||||
Talk(EMOTE_PHASE_PORTAL);
|
||||
}
|
||||
|
||||
// NetherInfusion Berserk
|
||||
if (!Berserk && NetherInfusionTimer <= diff)
|
||||
void SwitchToBanishPhase()
|
||||
{
|
||||
scheduler.CancelGroup(PORTAL_PHASE);
|
||||
me->RemoveAurasDueToSpell(SPELL_EMPOWERMENT);
|
||||
me->RemoveAurasDueToSpell(SPELL_NETHERBURN_AURA);
|
||||
DoCastSelf(SPELL_BANISH_VISUAL, true);
|
||||
DoCastSelf(SPELL_BANISH_ROOT, true);
|
||||
DestroyPortals();
|
||||
scheduler.Schedule(30s, [this](TaskContext /*context*/)
|
||||
{
|
||||
if (!me->IsNonMeleeSpellCast(false))
|
||||
{
|
||||
me->AddAura(SPELL_NETHER_INFUSION, me);
|
||||
DoCast(me, SPELL_NETHERSPITE_ROAR);
|
||||
Berserk = true;
|
||||
SwitchToPortalPhase();
|
||||
return;
|
||||
}
|
||||
else
|
||||
NetherInfusionTimer -= diff;
|
||||
|
||||
if (PortalPhase) // PORTAL PHASE
|
||||
{
|
||||
// Distribute beams and buffs
|
||||
if (PortalTimer <= diff)
|
||||
{
|
||||
UpdatePortals();
|
||||
PortalTimer = 1000;
|
||||
}
|
||||
else
|
||||
PortalTimer -= diff;
|
||||
|
||||
// Empowerment & Nether Burn
|
||||
if (EmpowermentTimer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_EMPOWERMENT);
|
||||
me->AddAura(SPELL_NETHERBURN_AURA, me);
|
||||
EmpowermentTimer = 90000;
|
||||
}
|
||||
else
|
||||
EmpowermentTimer -= diff;
|
||||
|
||||
if (PhaseTimer <= diff)
|
||||
{
|
||||
if (!me->IsNonMeleeSpellCast(false))
|
||||
{
|
||||
SwitchToBanishPhase();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
PhaseTimer -= diff;
|
||||
}
|
||||
else // BANISH PHASE
|
||||
{
|
||||
// Netherbreath
|
||||
if (NetherbreathTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40, true))
|
||||
DoCast(target, SPELL_NETHERBREATH);
|
||||
NetherbreathTimer = urand(5000, 7000);
|
||||
}
|
||||
else
|
||||
NetherbreathTimer -= diff;
|
||||
|
||||
if (PhaseTimer <= diff)
|
||||
{
|
||||
if (!me->IsNonMeleeSpellCast(false))
|
||||
{
|
||||
SwitchToPortalPhase();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
PhaseTimer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}).Schedule(10s, VANISH_PHASE, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_NETHERBREATH, 0, 40.0f, true);
|
||||
context.Repeat(5s, 7s);
|
||||
});
|
||||
Talk(EMOTE_PHASE_BANISH);
|
||||
for (uint8 i = 0; i < 3; ++i)
|
||||
{
|
||||
me->RemoveAurasDueToSpell(NetherBuff[i]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void HandleDoors(bool open)
|
||||
{
|
||||
if (GameObject* door = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_GO_MASSIVE_DOOR)))
|
||||
{
|
||||
door->SetGoState(open ? GO_STATE_ACTIVE : GO_STATE_READY);
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
HandleDoors(false);
|
||||
SwitchToPortalPhase();
|
||||
DoZoneInCombat();
|
||||
scheduler.Schedule(15s, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_VOIDZONE, 1, 45.0f, true, true);
|
||||
context.Repeat(15s);
|
||||
}).Schedule(9min, [this](TaskContext /*context*/)
|
||||
{
|
||||
if (!berserk)
|
||||
{
|
||||
DoCastSelf(SPELL_NETHER_INFUSION);
|
||||
DoCastAOE(SPELL_NETHERSPITE_ROAR);
|
||||
berserk = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
HandleDoors(true);
|
||||
DestroyPortals();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
scheduler.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
bool berserk;
|
||||
ObjectGuid PortalGUID[3]; // guid's of portals
|
||||
ObjectGuid BeamerGUID[3]; // guid's of auxiliary beaming portals
|
||||
ObjectGuid BeamTarget[3]; // guid's of portals' current targets
|
||||
};
|
||||
|
||||
class spell_nether_portal_perseverence : public AuraScript
|
||||
@@ -366,6 +328,6 @@ class spell_nether_portal_perseverence : public AuraScript
|
||||
|
||||
void AddSC_boss_netherspite()
|
||||
{
|
||||
new boss_netherspite();
|
||||
RegisterKarazhanCreatureAI(boss_netherspite);
|
||||
RegisterSpellScript(spell_nether_portal_perseverence);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ EndScriptData */
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "TaskScheduler.h"
|
||||
#include "karazhan.h"
|
||||
|
||||
enum Spells
|
||||
@@ -52,6 +53,12 @@ enum Says
|
||||
EMOTE_BREATH = 4
|
||||
};
|
||||
|
||||
enum Groups
|
||||
{
|
||||
GROUP_GROUND = 0,
|
||||
GROUP_FLYING = 1
|
||||
};
|
||||
|
||||
float IntroWay[8][3] =
|
||||
{
|
||||
{-11053.37f, -1794.48f, 149.00f},
|
||||
@@ -62,218 +69,270 @@ float IntroWay[8][3] =
|
||||
{-11128.73f, -1929.75f, 125.00f},
|
||||
{-11140.00f, -1915.00f, 122.00f},
|
||||
{-11163.00f, -1903.00f, 91.473f}
|
||||
};
|
||||
}; //TODO: move to table
|
||||
|
||||
class boss_nightbane : public CreatureScript
|
||||
struct boss_nightbane : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_nightbane() : CreatureScript("boss_nightbane") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
boss_nightbane(Creature* creature) : BossAI(creature, DATA_NIGHTBANE)
|
||||
{
|
||||
return GetKarazhanAI<boss_nightbaneAI>(creature);
|
||||
_intro = true;
|
||||
_skeletonCount = 5;
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
struct boss_nightbaneAI : public ScriptedAI
|
||||
void Reset() override
|
||||
{
|
||||
boss_nightbaneAI(Creature* creature) : ScriptedAI(creature)
|
||||
BossAI::Reset();
|
||||
_skeletonscheduler.CancelAll();
|
||||
Phase = 1;
|
||||
MovePhase = 0;
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
|
||||
me->SetSpeed(MOVE_RUN, 2.0f);
|
||||
me->SetDisableGravity(_intro);
|
||||
me->SetWalk(false);
|
||||
me->setActive(true);
|
||||
|
||||
if (instance)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
Intro = true;
|
||||
if (instance->GetData(DATA_NIGHTBANE) == DONE)
|
||||
me->DisappearAndDie();
|
||||
else
|
||||
instance->SetData(DATA_NIGHTBANE, NOT_STARTED);
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
HandleTerraceDoors(true);
|
||||
|
||||
uint32 Phase;
|
||||
_flying = false;
|
||||
_movement = false;
|
||||
|
||||
bool RainBones;
|
||||
bool Skeletons;
|
||||
|
||||
uint32 BellowingRoarTimer;
|
||||
uint32 CharredEarthTimer;
|
||||
uint32 DistractingAshTimer;
|
||||
uint32 SmolderingBreathTimer;
|
||||
uint32 TailSweepTimer;
|
||||
uint32 RainofBonesTimer;
|
||||
uint32 SmokingBlastTimer;
|
||||
uint32 FireballBarrageTimer;
|
||||
uint32 SearingCindersTimer;
|
||||
|
||||
uint32 FlyCount;
|
||||
uint32 FlyTimer;
|
||||
|
||||
bool Intro;
|
||||
bool Flying;
|
||||
bool Movement;
|
||||
|
||||
uint32 MovePhase;
|
||||
|
||||
void Reset() override
|
||||
if (!_intro)
|
||||
{
|
||||
BellowingRoarTimer = 30000;
|
||||
CharredEarthTimer = 15000;
|
||||
DistractingAshTimer = 20000;
|
||||
SmolderingBreathTimer = 10000;
|
||||
TailSweepTimer = 12000;
|
||||
RainofBonesTimer = 10000;
|
||||
SmokingBlastTimer = 20000;
|
||||
FireballBarrageTimer = 13000;
|
||||
SearingCindersTimer = 14000;
|
||||
|
||||
//when boss is reset and we're past the intro
|
||||
//cannot despawn, but have to move to a location where he normally is
|
||||
//me->SetHomePosition(IntroWay[7][0], IntroWay[7][1], IntroWay[7][2], 0);
|
||||
Position preSpawnPosis = me->GetHomePosition();
|
||||
me->NearTeleportTo(preSpawnPosis);
|
||||
instance->SetData(DATA_NIGHTBANE, NOT_STARTED);
|
||||
_intro = true;
|
||||
Phase = 1;
|
||||
FlyCount = 0;
|
||||
MovePhase = 0;
|
||||
}
|
||||
|
||||
me->SetSpeed(MOVE_RUN, 2.0f);
|
||||
me->SetDisableGravity(Intro);
|
||||
me->SetWalk(false);
|
||||
me->setActive(true);
|
||||
ScheduleHealthCheckEvent({25, 50, 70}, [&]{
|
||||
TakeOff();
|
||||
});
|
||||
}
|
||||
|
||||
if (instance)
|
||||
void HandleTerraceDoors(bool open)
|
||||
{
|
||||
if (instance)
|
||||
{
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_MASTERS_TERRACE_DOOR_1), open);
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_MASTERS_TERRACE_DOOR_2), open);
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
if (instance)
|
||||
instance->SetData(DATA_NIGHTBANE, IN_PROGRESS);
|
||||
|
||||
HandleTerraceDoors(false);
|
||||
Talk(YELL_AGGRO);
|
||||
ScheduleGround();
|
||||
}
|
||||
|
||||
void ScheduleGround() {
|
||||
scheduler.Schedule(30s, GROUP_GROUND, [this](TaskContext context)
|
||||
{
|
||||
DoCastAOE(SPELL_BELLOWING_ROAR);
|
||||
context.Repeat(30s, 40s);
|
||||
}).Schedule(15s, GROUP_GROUND, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_CHARRED_EARTH, 0, 100.0f, true);
|
||||
context.Repeat(20s);
|
||||
}).Schedule(10s, GROUP_GROUND, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_SMOLDERING_BREATH);
|
||||
context.Repeat(20s);
|
||||
}).Schedule(12s, GROUP_GROUND, [this](TaskContext context)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
{
|
||||
if (instance->GetData(DATA_NIGHTBANE) == DONE)
|
||||
me->DisappearAndDie();
|
||||
else
|
||||
instance->SetData(DATA_NIGHTBANE, NOT_STARTED);
|
||||
}
|
||||
|
||||
HandleTerraceDoors(true);
|
||||
|
||||
Flying = false;
|
||||
Movement = false;
|
||||
|
||||
if (!Intro)
|
||||
{
|
||||
me->SetHomePosition(IntroWay[7][0], IntroWay[7][1], IntroWay[7][2], 0);
|
||||
me->GetMotionMaster()->MoveTargetedHome();
|
||||
}
|
||||
}
|
||||
|
||||
void HandleTerraceDoors(bool open)
|
||||
{
|
||||
if (instance)
|
||||
{
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_MASTERS_TERRACE_DOOR_1), open);
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_MASTERS_TERRACE_DOOR_2), open);
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SetData(DATA_NIGHTBANE, IN_PROGRESS);
|
||||
|
||||
HandleTerraceDoors(false);
|
||||
Talk(YELL_AGGRO);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (!Intro && !Flying)
|
||||
ScriptedAI::AttackStart(who);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SetData(DATA_NIGHTBANE, DONE);
|
||||
|
||||
HandleTerraceDoors(true);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (!Intro && !Flying)
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (type != POINT_MOTION_TYPE)
|
||||
return;
|
||||
|
||||
if (Intro)
|
||||
{
|
||||
if (id >= 8)
|
||||
if (!me->HasInArc(M_PI, target))
|
||||
{
|
||||
Intro = false;
|
||||
me->SetHomePosition(IntroWay[7][0], IntroWay[7][1], IntroWay[7][2], 0);
|
||||
return;
|
||||
DoCast(target, SPELL_TAIL_SWEEP);
|
||||
}
|
||||
}
|
||||
context.Repeat(15s);
|
||||
}).Schedule(14s, GROUP_GROUND, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_SEARING_CINDERS);
|
||||
context.Repeat(10s);
|
||||
});
|
||||
}
|
||||
|
||||
void ScheduleFly() {
|
||||
_skeletonSpawnCounter = 0;
|
||||
|
||||
scheduler.Schedule(2s, GROUP_FLYING, [this](TaskContext)
|
||||
{
|
||||
DoCastVictim(SPELL_RAIN_OF_BONES);
|
||||
_skeletonscheduler.Schedule(50ms, [this](TaskContext context)
|
||||
{
|
||||
//spawns skeletons every second until skeletonCount is reached
|
||||
if(_skeletonSpawnCounter < _skeletonCount)
|
||||
{
|
||||
DoCastVictim(SPELL_SUMMON_SKELETON, true);
|
||||
_skeletonSpawnCounter++;
|
||||
context.Repeat(2s);
|
||||
}
|
||||
});
|
||||
}).Schedule(20s, GROUP_FLYING, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_DISTRACTING_ASH);
|
||||
context.Repeat(2s); //timer wrong?
|
||||
}).Schedule(25s, GROUP_FLYING, [this](TaskContext context)
|
||||
{
|
||||
//5 seconds added due to double trigger?
|
||||
//trigger for timer in original + in rain of bones
|
||||
//timers need some investigation
|
||||
DoCastVictim(SPELL_SMOKING_BLAST);
|
||||
context.Repeat(1500ms); //timer wrong?
|
||||
}).Schedule(13s, GROUP_FLYING, [this](TaskContext context)
|
||||
{
|
||||
DoCastOnFarAwayPlayers(SPELL_FIREBALL_BARRAGE, false, 80.0f);
|
||||
context.Repeat(20s);
|
||||
});
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (!_intro && !_flying)
|
||||
ScriptedAI::AttackStart(who);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (instance)
|
||||
instance->SetData(DATA_NIGHTBANE, DONE);
|
||||
|
||||
HandleTerraceDoors(true);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (!_intro && !_flying)
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (type != POINT_MOTION_TYPE)
|
||||
return;
|
||||
|
||||
if (_intro)
|
||||
{
|
||||
if (id >= 8)
|
||||
{
|
||||
_intro = false;
|
||||
//me->SetHomePosition(IntroWay[7][0], IntroWay[7][1], IntroWay[7][2], 0);
|
||||
//doesn't need home position because we have to "despawn" boss on reset
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetInCombatWithZone();
|
||||
return;
|
||||
}
|
||||
|
||||
MovePhase = id + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_flying)
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
Talk(EMOTE_BREATH);
|
||||
_flying = false;
|
||||
Phase = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
if (id < 8)
|
||||
MovePhase = id + 1;
|
||||
else
|
||||
{
|
||||
Phase = 1;
|
||||
_flying = false;
|
||||
_movement = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Flying)
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summon->AI()->AttackStart(me->GetVictim());
|
||||
summons.Summon(summon);
|
||||
}
|
||||
|
||||
void DoCastOnFarAwayPlayers(uint32 spellid, bool triggered, float tresholddistance)
|
||||
{
|
||||
//resembles DoCastToAllHostilePlayers a bit/lot
|
||||
ThreatContainer::StorageType targets = me->GetThreatMgr().GetThreatList();
|
||||
for (ThreatContainer::StorageType::const_iterator itr = targets.begin(); itr != targets.end(); ++itr)
|
||||
{
|
||||
if (Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()))
|
||||
{
|
||||
if (id == 0)
|
||||
if (unit->IsPlayer() && !unit->IsWithinDist(me, tresholddistance, false))
|
||||
{
|
||||
Talk(EMOTE_BREATH);
|
||||
Flying = false;
|
||||
Phase = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
if (id < 8)
|
||||
MovePhase = id + 1;
|
||||
else
|
||||
{
|
||||
Phase = 1;
|
||||
Flying = false;
|
||||
Movement = true;
|
||||
return;
|
||||
me->CastSpell(unit, spellid, triggered);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summoned) override
|
||||
void TakeOff()
|
||||
{
|
||||
Talk(YELL_FLY_PHASE);
|
||||
scheduler.CancelGroup(GROUP_GROUND);
|
||||
|
||||
me->InterruptSpell(CURRENT_GENERIC_SPELL);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
|
||||
me->SetDisableGravity(true);
|
||||
me->GetMotionMaster()->Clear(false);
|
||||
me->GetMotionMaster()->MovePoint(0, IntroWay[2][0], IntroWay[2][1], IntroWay[2][2]);
|
||||
|
||||
_flying = true;
|
||||
|
||||
ScheduleFly();
|
||||
|
||||
//handle landing again
|
||||
scheduler.Schedule(45s, 60s, [this](TaskContext)
|
||||
{
|
||||
summoned->AI()->AttackStart(me->GetVictim());
|
||||
}
|
||||
Talk(YELL_LAND_PHASE);
|
||||
|
||||
void TakeOff()
|
||||
{
|
||||
Talk(YELL_FLY_PHASE);
|
||||
|
||||
me->InterruptSpell(CURRENT_GENERIC_SPELL);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
|
||||
me->SetDisableGravity(true);
|
||||
me->GetMotionMaster()->Clear(false);
|
||||
me->GetMotionMaster()->MovePoint(0, IntroWay[2][0], IntroWay[2][1], IntroWay[2][2]);
|
||||
me->GetMotionMaster()->MovePoint(3, IntroWay[3][0], IntroWay[3][1], IntroWay[3][2]);
|
||||
|
||||
Flying = true;
|
||||
|
||||
FlyTimer = urand(45000, 60000); //timer wrong between 45 and 60 seconds
|
||||
++FlyCount;
|
||||
|
||||
RainofBonesTimer = 5000; //timer wrong (maybe)
|
||||
RainBones = false;
|
||||
Skeletons = false;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (Intro)
|
||||
_flying = true;
|
||||
scheduler.CancelGroup(GROUP_FLYING);
|
||||
scheduler.Schedule(2s, [this](TaskContext)
|
||||
{
|
||||
if (MovePhase)
|
||||
{
|
||||
if (MovePhase >= 7)
|
||||
{
|
||||
me->SetDisableGravity(false);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
|
||||
me->GetMotionMaster()->MovePoint(8, IntroWay[7][0], IntroWay[7][1], IntroWay[7][2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->GetMotionMaster()->MovePoint(MovePhase, IntroWay[MovePhase][0], IntroWay[MovePhase][1], IntroWay[MovePhase][2]);
|
||||
}
|
||||
MovePhase = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
ScheduleGround();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (Flying && MovePhase)
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (_intro)
|
||||
{
|
||||
if (MovePhase)
|
||||
{
|
||||
if (MovePhase >= 7)
|
||||
{
|
||||
@@ -282,158 +341,70 @@ public:
|
||||
me->GetMotionMaster()->MovePoint(8, IntroWay[7][0], IntroWay[7][1], IntroWay[7][2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->GetMotionMaster()->MovePoint(MovePhase, IntroWay[MovePhase][0], IntroWay[MovePhase][1], IntroWay[MovePhase][2]);
|
||||
|
||||
}
|
||||
MovePhase = 0;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (Flying)
|
||||
return;
|
||||
|
||||
// Phase 1 "GROUND FIGHT"
|
||||
if (Phase == 1)
|
||||
{
|
||||
if (Movement)
|
||||
{
|
||||
DoStartMovement(me->GetVictim());
|
||||
Movement = false;
|
||||
}
|
||||
|
||||
if (BellowingRoarTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_BELLOWING_ROAR);
|
||||
BellowingRoarTimer = urand(30000, 40000);
|
||||
}
|
||||
else
|
||||
BellowingRoarTimer -= diff;
|
||||
|
||||
if (SmolderingBreathTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_SMOLDERING_BREATH);
|
||||
SmolderingBreathTimer = 20000;
|
||||
}
|
||||
else
|
||||
SmolderingBreathTimer -= diff;
|
||||
|
||||
if (CharredEarthTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
DoCast(target, SPELL_CHARRED_EARTH);
|
||||
CharredEarthTimer = 20000;
|
||||
}
|
||||
else
|
||||
CharredEarthTimer -= diff;
|
||||
|
||||
if (TailSweepTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
if (!me->HasInArc(M_PI, target))
|
||||
DoCast(target, SPELL_TAIL_SWEEP);
|
||||
TailSweepTimer = 15000;
|
||||
}
|
||||
else
|
||||
TailSweepTimer -= diff;
|
||||
|
||||
if (SearingCindersTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
DoCast(target, SPELL_SEARING_CINDERS);
|
||||
SearingCindersTimer = 10000;
|
||||
}
|
||||
else
|
||||
SearingCindersTimer -= diff;
|
||||
|
||||
uint32 Prozent = uint32(me->GetHealthPct());
|
||||
|
||||
if (Prozent < 75 && FlyCount == 0) // first take off 75%
|
||||
TakeOff();
|
||||
|
||||
if (Prozent < 50 && FlyCount == 1) // secound take off 50%
|
||||
TakeOff();
|
||||
|
||||
if (Prozent < 25 && FlyCount == 2) // third take off 25%
|
||||
TakeOff();
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
//Phase 2 "FLYING FIGHT"
|
||||
if (Phase == 2)
|
||||
{
|
||||
if (!RainBones)
|
||||
{
|
||||
if (!Skeletons)
|
||||
{
|
||||
for (uint8 i = 0; i <= 3; ++i)
|
||||
{
|
||||
DoCastVictim(SPELL_SUMMON_SKELETON);
|
||||
Skeletons = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (RainofBonesTimer < diff && !RainBones) // only once at the beginning of phase 2
|
||||
{
|
||||
DoCastVictim(SPELL_RAIN_OF_BONES);
|
||||
RainBones = true;
|
||||
SmokingBlastTimer = 20000;
|
||||
}
|
||||
else
|
||||
RainofBonesTimer -= diff;
|
||||
|
||||
if (DistractingAshTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
DoCast(target, SPELL_DISTRACTING_ASH);
|
||||
DistractingAshTimer = 2000; //timer wrong
|
||||
}
|
||||
else
|
||||
DistractingAshTimer -= diff;
|
||||
}
|
||||
|
||||
if (RainBones)
|
||||
{
|
||||
if (SmokingBlastTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_SMOKING_BLAST);
|
||||
SmokingBlastTimer = 1500; //timer wrong
|
||||
}
|
||||
else
|
||||
SmokingBlastTimer -= diff;
|
||||
}
|
||||
|
||||
if (FireballBarrageTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MinDistance, 0))
|
||||
DoCast(target, SPELL_FIREBALL_BARRAGE);
|
||||
FireballBarrageTimer = 20000;
|
||||
}
|
||||
else
|
||||
FireballBarrageTimer -= diff;
|
||||
|
||||
if (FlyTimer <= diff) //landing
|
||||
{
|
||||
Talk(YELL_LAND_PHASE);
|
||||
|
||||
me->GetMotionMaster()->Clear(false);
|
||||
me->GetMotionMaster()->MovePoint(3, IntroWay[3][0], IntroWay[3][1], IntroWay[3][2]);
|
||||
|
||||
Flying = true;
|
||||
}
|
||||
else
|
||||
FlyTimer -= diff;
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
if (_flying && MovePhase)
|
||||
{
|
||||
if (MovePhase >= 7)
|
||||
{
|
||||
me->SetDisableGravity(false);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
|
||||
me->GetMotionMaster()->MovePoint(8, IntroWay[7][0], IntroWay[7][1], IntroWay[7][2]);
|
||||
}
|
||||
else
|
||||
me->GetMotionMaster()->MovePoint(MovePhase, IntroWay[MovePhase][0], IntroWay[MovePhase][1], IntroWay[MovePhase][2]);
|
||||
|
||||
MovePhase = 0;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (_flying)
|
||||
return;
|
||||
|
||||
scheduler.Update(diff);
|
||||
_skeletonscheduler.Update(diff);
|
||||
|
||||
// Phase 1 "GROUND FIGHT"
|
||||
if (Phase == 1)
|
||||
{
|
||||
if (_movement)
|
||||
{
|
||||
DoStartMovement(me->GetVictim());
|
||||
_movement = false;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 Phase;
|
||||
|
||||
TaskScheduler _skeletonscheduler;
|
||||
|
||||
bool _intro;
|
||||
bool _flying;
|
||||
bool _movement;
|
||||
|
||||
uint32 MovePhase;
|
||||
uint8 _skeletonCount;
|
||||
uint8 _skeletonSpawnCounter;
|
||||
};
|
||||
class go_blackened_urn : public GameObjectScript
|
||||
{
|
||||
public:
|
||||
go_blackened_urn() : GameObjectScript("go_blackened_urn") { }
|
||||
|
||||
//if we summon an entity instead of using a sort of invisible entity, we could unsummon boss on reset
|
||||
//right now that doesn't work because of how the urn works
|
||||
bool OnGossipHello(Player* player, GameObject* go) override
|
||||
{
|
||||
if (InstanceScript* pInstance = go->GetInstanceScript())
|
||||
@@ -449,6 +420,6 @@ public:
|
||||
|
||||
void AddSC_boss_nightbane()
|
||||
{
|
||||
new boss_nightbane();
|
||||
RegisterKarazhanCreatureAI(boss_nightbane);
|
||||
new go_blackened_urn();
|
||||
}
|
||||
|
||||
@@ -292,6 +292,7 @@ public:
|
||||
{
|
||||
instance->SetData(DATA_ARCHIMONDEEVENT, NOT_STARTED);
|
||||
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
DoomfireSpiritGUID.Clear();
|
||||
WorldTreeGUID.Clear();
|
||||
WispCount = 0;
|
||||
@@ -618,6 +619,7 @@ public:
|
||||
break;
|
||||
}
|
||||
case EVENT_BELOW_10_PERCENT_HP:
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
DoCastProtection(); // Protection of Elune against Finger and Hand of Death
|
||||
BelowTenPercent = true;
|
||||
me->GetMotionMaster()->Clear(false);
|
||||
|
||||
@@ -218,9 +218,9 @@ struct boss_magtheridon : public BossAI
|
||||
Talk(SAY_EMOTE_FREE);
|
||||
Talk(SAY_FREE);
|
||||
scheduler.CancelGroup(GROUP_EARLY_RELEASE_CHECK); //cancel regular countdown
|
||||
_magReleased = true;
|
||||
scheduler.Schedule(3s, [this](TaskContext)
|
||||
{
|
||||
_magReleased = true; //redundancy
|
||||
ScheduleCombatEvents();
|
||||
});
|
||||
}
|
||||
@@ -239,6 +239,7 @@ struct boss_magtheridon : public BossAI
|
||||
{
|
||||
Talk(SAY_EMOTE_FREE);
|
||||
Talk(SAY_FREE);
|
||||
_magReleased = true;
|
||||
}).Schedule(123s, GROUP_EARLY_RELEASE_CHECK, [this](TaskContext /*context*/)
|
||||
{
|
||||
ScheduleCombatEvents();
|
||||
|
||||
@@ -4884,6 +4884,39 @@ class spell_gen_shriveling_gaze : public AuraScript
|
||||
}
|
||||
};
|
||||
|
||||
// 38048 - Curse of Pain
|
||||
enum CurseOfPain
|
||||
{
|
||||
SPELL_CURSE_OF_PAIN = 38048,
|
||||
};
|
||||
|
||||
class spell_gen_curse_of_pain : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_gen_curse_of_pain);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_CURSE_OF_PAIN });
|
||||
}
|
||||
|
||||
void OnPeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
if (target && target->ToPlayer())
|
||||
{
|
||||
if (target->GetHealthPct() < 50.f)
|
||||
{
|
||||
target->RemoveAurasDueToSpell(SPELL_CURSE_OF_PAIN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_gen_curse_of_pain::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_generic_spell_scripts()
|
||||
{
|
||||
RegisterSpellScript(spell_silithyst);
|
||||
@@ -5029,4 +5062,5 @@ void AddSC_generic_spell_scripts()
|
||||
RegisterSpellScript(spell_freezing_circle);
|
||||
RegisterSpellScript(spell_gen_threshalisk_charge);
|
||||
RegisterSpellScript(spell_gen_shriveling_gaze);
|
||||
RegisterSpellScript(spell_gen_curse_of_pain);
|
||||
}
|
||||
|
||||
@@ -974,6 +974,9 @@ class spell_q6124_6129_apply_salve : public SpellScript
|
||||
if (newEntry)
|
||||
{
|
||||
creatureTarget->UpdateEntry(newEntry);
|
||||
creatureTarget->GetMotionMaster()->Clear();
|
||||
creatureTarget->GetMotionMaster()->MoveFleeing(caster);
|
||||
creatureTarget->SetUnitFlag(UNIT_FLAG_NOT_ATTACKABLE_1);
|
||||
creatureTarget->DespawnOrUnsummon(DESPAWN_TIME);
|
||||
caster->KilledMonsterCredit(newEntry);
|
||||
}
|
||||
|
||||
@@ -486,7 +486,7 @@ public:
|
||||
if (creature->IsTrainer())
|
||||
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN);
|
||||
|
||||
if (player->HasSkill(SKILL_ALCHEMY) && player->GetBaseSkillValue(SKILL_ALCHEMY) >= 350 && player->GetLevel() > 67)
|
||||
if (player->HasSkill(SKILL_ALCHEMY) && player->GetBaseSkillValue(SKILL_ALCHEMY) >= 325 && player->GetLevel() > 67)
|
||||
{
|
||||
if (player->GetQuestRewardStatus(Q_MASTER_TRANSMUTE) || player->GetQuestRewardStatus(Q_MASTER_ELIXIR) || player->GetQuestRewardStatus(Q_MASTER_POTION))
|
||||
{
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "ScriptedGossip.h"
|
||||
#include "SmartAI.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "TaskScheduler.h"
|
||||
#include "WaypointMgr.h"
|
||||
#include "World.h"
|
||||
|
||||
@@ -2653,6 +2654,32 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct npc_crashin_thrashin_robot : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
npc_crashin_thrashin_robot(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
}
|
||||
|
||||
void IsSummonedBy(WorldObject* /*summoner*/) override
|
||||
{
|
||||
_scheduler.Schedule(180s, [this](TaskContext /*context*/)
|
||||
{
|
||||
me->KillSelf();
|
||||
});
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
_scheduler.Update(diff);
|
||||
|
||||
ScriptedAI::UpdateAI(diff);
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
void AddSC_npcs_special()
|
||||
{
|
||||
// Ours
|
||||
@@ -2680,4 +2707,5 @@ void AddSC_npcs_special()
|
||||
new npc_spring_rabbit();
|
||||
new npc_stable_master();
|
||||
RegisterCreatureAI(npc_arcanite_dragonling);
|
||||
RegisterCreatureAI(npc_crashin_thrashin_robot);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user